import { type GrokSettings, type ModelCapabilities, type ServerProvider, type ServerProviderModel,} from "@t3tools/contracts";import type * as EffectAcpSchema from "effect-acp/schema";import { causeErrorTag } from "@t3tools/shared/observability";import * as Crypto from "effect/Crypto";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect";import * as Exit from "effect/Exit";import * as Option from "effect/Option";import * as Result from "effect/Result";import { HttpClient } from "effect/unstable/http";import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";import { createModelCapabilities } from "@t3tools/shared/model";import { resolveSpawnCommand } from "@t3tools/shared/shell"; import { buildServerProvider, isCommandMissingCause, parseGenericCliVersion, providerModelsFromSettings, spawnAndCollect, type ServerProviderDraft,} from "../providerSnapshot.ts";import { enrichProviderSnapshotWithVersionAdvisory, type ProviderMaintenanceCapabilities,} from "../providerMaintenance.ts";import { makeGrokAcpRuntime, resolveGrokAcpBaseModelId } from "../acp/GrokAcpSupport.ts"; const GROK_PRESENTATION = { displayName: "Grok", badgeLabel: "Early Access", showInteractionModeToggle: false, requiresNewThreadForModelChange: true,} as const;const EMPTY_CAPABILITIES: ModelCapabilities = createModelCapabilities({ optionDescriptors: [],}); const VERSION_PROBE_TIMEOUT_MS = 4_000;const GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15_000; const GROK_BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ { slug: "grok-build", name: "Grok Build", isCustom: false, capabilities: EMPTY_CAPABILITIES, },]; export function buildInitialGrokProviderSnapshot( grokSettings: GrokSettings,): Effect.Effect<ServerProviderDraft> { return Effect.gen(function* () { const checkedAt = yield* Effect.map(DateTime.now, DateTime.formatIso); const models = grokModelsFromSettings(grokSettings.customModels); if (!grokSettings.enabled) { return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: false, checkedAt, models, probe: { installed: false, version: null, status: "warning", auth: { status: "unknown" }, message: "Grok is disabled in T3 Code settings.", }, }); } return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: true, checkedAt, models, probe: { installed: true, version: null, status: "warning", auth: { status: "unknown" }, message: "Checking Grok CLI availability...", }, }); });} function grokModelsFromSettings( customModels: ReadonlyArray<string> | undefined, builtInModels: ReadonlyArray<ServerProviderModel> = GROK_BUILT_IN_MODELS,): ReadonlyArray<ServerProviderModel> { return providerModelsFromSettings(builtInModels, customModels ?? [], EMPTY_CAPABILITIES);} function buildGrokDiscoveredModelsFromSessionModelState( modelState: EffectAcpSchema.SessionModelState | null | undefined,): ReadonlyArray<ServerProviderModel> { if (!modelState || modelState.availableModels.length === 0) { return []; } const seen = new Set<string>(); return modelState.availableModels .map((model): ServerProviderModel | undefined => { const slug = resolveGrokAcpBaseModelId(model.modelId); if (!slug || seen.has(slug)) { return undefined; } seen.add(slug); return { slug, name: model.name.trim() || slug, isCustom: false, capabilities: EMPTY_CAPABILITIES, }; }) .filter((model): model is ServerProviderModel => model !== undefined);} const discoverGrokModelsViaAcp = ( grokSettings: GrokSettings, environment: NodeJS.ProcessEnv = process.env,) => Effect.gen(function* () { const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; const acp = yield* makeGrokAcpRuntime({ grokSettings, environment, childProcessSpawner, cwd: process.cwd(), clientInfo: { name: "t3-code-provider-probe", version: "0.0.0" }, }); const started = yield* acp.start(); return buildGrokDiscoveredModelsFromSessionModelState(started.sessionSetupResult.models); }).pipe(Effect.scoped); const runGrokVersionCommand = ( grokSettings: GrokSettings, environment: NodeJS.ProcessEnv = process.env,) => Effect.gen(function* () { const command = grokSettings.binaryPath || "grok"; const spawnCommand = yield* resolveSpawnCommand(command, ["--version"], { env: environment, }); return yield* spawnAndCollect( command, ChildProcess.make(spawnCommand.command, spawnCommand.args, { env: environment, shell: spawnCommand.shell, }), ); }); export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* ( grokSettings: GrokSettings, environment: NodeJS.ProcessEnv = process.env,): Effect.fn.Return< ServerProviderDraft, never, ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto> { const checkedAt = DateTime.formatIso(yield* DateTime.now); const fallbackModels = grokModelsFromSettings(grokSettings.customModels); if (!grokSettings.enabled) { return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: false, checkedAt, models: fallbackModels, probe: { installed: false, version: null, status: "warning", auth: { status: "unknown" }, message: "Grok is disabled in T3 Code settings.", }, }); } const versionResult = yield* runGrokVersionCommand(grokSettings, environment).pipe( Effect.timeoutOption(VERSION_PROBE_TIMEOUT_MS), Effect.result, ); if (Result.isFailure(versionResult)) { const error = versionResult.failure; yield* Effect.logWarning("Grok CLI health check failed.", { errorTag: error._tag, }); return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: grokSettings.enabled, checkedAt, models: fallbackModels, probe: { installed: !isCommandMissingCause(error), version: null, status: "error", auth: { status: "unknown" }, message: isCommandMissingCause(error) ? "Grok CLI (`grok`) is not installed or not on PATH." : "Failed to execute Grok CLI health check.", }, }); } if (Option.isNone(versionResult.success)) { return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: grokSettings.enabled, checkedAt, models: fallbackModels, probe: { installed: true, version: null, status: "error", auth: { status: "unknown" }, message: "Grok CLI is installed but timed out while running `grok --version`.", }, }); } const versionOutput = versionResult.success.value; const version = parseGenericCliVersion(`${versionOutput.stdout}\n${versionOutput.stderr}`); if (versionOutput.code !== 0) { yield* Effect.logWarning("Grok CLI version probe exited with a non-zero status.", { exitCode: versionOutput.code, stdoutLength: versionOutput.stdout.length, stderrLength: versionOutput.stderr.length, }); return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: grokSettings.enabled, checkedAt, models: fallbackModels, probe: { installed: true, version, status: "error", auth: { status: "unknown" }, message: "Grok CLI is installed but failed to run.", }, }); } const discoveryExit = yield* discoverGrokModelsViaAcp(grokSettings, environment).pipe( Effect.timeoutOption(GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS), Effect.exit, ); if (Exit.isFailure(discoveryExit)) { yield* Effect.logWarning("Grok ACP model discovery failed", { errorTag: causeErrorTag(discoveryExit.cause), }); return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: grokSettings.enabled, checkedAt, models: fallbackModels, probe: { installed: true, version, status: "error", auth: { status: "unknown" }, message: "Grok CLI is installed but ACP startup failed. Check server logs for details.", }, }); } if (Option.isNone(discoveryExit.value)) { yield* Effect.logWarning( `Grok ACP model discovery timed out after ${GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS}ms.`, ); return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: grokSettings.enabled, checkedAt, models: fallbackModels, probe: { installed: true, version, status: "error", auth: { status: "unknown" }, message: `Grok CLI is installed but ACP startup timed out after ${GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS}ms.`, }, }); } const discoveredModels = discoveryExit.value.value; const models = discoveredModels.length > 0 ? grokModelsFromSettings(grokSettings.customModels, discoveredModels) : fallbackModels; return buildServerProvider({ presentation: GROK_PRESENTATION, enabled: grokSettings.enabled, checkedAt, models, probe: { installed: true, version, status: "ready", auth: { status: "unknown" }, }, });}); export const enrichGrokSnapshot = (input: { readonly snapshot: ServerProvider; readonly maintenanceCapabilities: ProviderMaintenanceCapabilities; readonly enableProviderUpdateChecks?: boolean; readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>; readonly httpClient: HttpClient.HttpClient;}): Effect.Effect<void> => { const { snapshot, publishSnapshot } = input; return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities, { enableProviderUpdateChecks: input.enableProviderUpdateChecks, }).pipe( Effect.provideService(HttpClient.HttpClient, input.httpClient), Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), Effect.catchCause((cause) => Effect.logWarning("Grok version advisory enrichment failed", { errorTag: causeErrorTag(cause), }), ), Effect.asVoid, );};
import {
type GrokSettings,
type ModelCapabilities,
type ServerProvider,
type ServerProviderModel,
} from "@t3tools/contracts";
import type * as EffectAcpSchema from "effect-acp/schema";
import { causeErrorTag } from "@t3tools/shared/observability";
import * as Crypto from "effect/Crypto";
import * as DateTime from "effect/DateTime";
import * as Effect from "effect/Effect";
import * as Exit from "effect/Exit";
import * as Option from "effect/Option";
import * as Result from "effect/Result";
import { HttpClient } from "effect/unstable/http";
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
import { createModelCapabilities } from "@t3tools/shared/model";
import { resolveSpawnCommand } from "@t3tools/shared/shell";
import {
buildServerProvider,
isCommandMissingCause,
parseGenericCliVersion,
providerModelsFromSettings,
spawnAndCollect,
type ServerProviderDraft,
} from "../providerSnapshot.ts";
import {
enrichProviderSnapshotWithVersionAdvisory,
type ProviderMaintenanceCapabilities,
} from "../providerMaintenance.ts";
import { makeGrokAcpRuntime, resolveGrokAcpBaseModelId } from "../acp/GrokAcpSupport.ts";
const GROK_PRESENTATION = {
displayName: "Grok",
badgeLabel: "Early Access",
showInteractionModeToggle: false,
requiresNewThreadForModelChange: true,
} as const;
const EMPTY_CAPABILITIES: ModelCapabilities = createModelCapabilities({
optionDescriptors: [],
});
const VERSION_PROBE_TIMEOUT_MS = 4_000;
const GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15_000;
const GROK_BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [
{
slug: "grok-build",
name: "Grok Build",
isCustom: false,
capabilities: EMPTY_CAPABILITIES,
},
];
export function buildInitialGrokProviderSnapshot(
grokSettings: GrokSettings,
): Effect.Effect<ServerProviderDraft> {
return Effect.gen(function* () {
const checkedAt = yield* Effect.map(DateTime.now, DateTime.formatIso);
const models = grokModelsFromSettings(grokSettings.customModels);
if (!grokSettings.enabled) {
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: false,
checkedAt,
models,
probe: {
installed: false,
version: null,
status: "warning",
auth: { status: "unknown" },
message: "Grok is disabled in T3 Code settings.",
},
});
}
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: true,
checkedAt,
models,
probe: {
installed: true,
version: null,
status: "warning",
auth: { status: "unknown" },
message: "Checking Grok CLI availability...",
},
});
});
}
function grokModelsFromSettings(
customModels: ReadonlyArray<string> | undefined,
builtInModels: ReadonlyArray<ServerProviderModel> = GROK_BUILT_IN_MODELS,
): ReadonlyArray<ServerProviderModel> {
return providerModelsFromSettings(builtInModels, customModels ?? [], EMPTY_CAPABILITIES);
}
function buildGrokDiscoveredModelsFromSessionModelState(
modelState: EffectAcpSchema.SessionModelState | null | undefined,
): ReadonlyArray<ServerProviderModel> {
if (!modelState || modelState.availableModels.length === 0) {
return [];
}
const seen = new Set<string>();
return modelState.availableModels
.map((model): ServerProviderModel | undefined => {
const slug = resolveGrokAcpBaseModelId(model.modelId);
if (!slug || seen.has(slug)) {
return undefined;
}
seen.add(slug);
return {
slug,
name: model.name.trim() || slug,
isCustom: false,
capabilities: EMPTY_CAPABILITIES,
};
})
.filter((model): model is ServerProviderModel => model !== undefined);
}
const discoverGrokModelsViaAcp = (
grokSettings: GrokSettings,
environment: NodeJS.ProcessEnv = process.env,
) =>
Effect.gen(function* () {
const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;
const acp = yield* makeGrokAcpRuntime({
grokSettings,
environment,
childProcessSpawner,
cwd: process.cwd(),
clientInfo: { name: "t3-code-provider-probe", version: "0.0.0" },
});
const started = yield* acp.start();
return buildGrokDiscoveredModelsFromSessionModelState(started.sessionSetupResult.models);
}).pipe(Effect.scoped);
const runGrokVersionCommand = (
grokSettings: GrokSettings,
environment: NodeJS.ProcessEnv = process.env,
) =>
Effect.gen(function* () {
const command = grokSettings.binaryPath || "grok";
const spawnCommand = yield* resolveSpawnCommand(command, ["--version"], {
env: environment,
});
return yield* spawnAndCollect(
command,
ChildProcess.make(spawnCommand.command, spawnCommand.args, {
env: environment,
shell: spawnCommand.shell,
}),
);
});
export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* (
grokSettings: GrokSettings,
environment: NodeJS.ProcessEnv = process.env,
): Effect.fn.Return<
ServerProviderDraft,
never,
ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto
> {
const checkedAt = DateTime.formatIso(yield* DateTime.now);
const fallbackModels = grokModelsFromSettings(grokSettings.customModels);
if (!grokSettings.enabled) {
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: false,
checkedAt,
models: fallbackModels,
probe: {
installed: false,
version: null,
status: "warning",
auth: { status: "unknown" },
message: "Grok is disabled in T3 Code settings.",
},
});
}
const versionResult = yield* runGrokVersionCommand(grokSettings, environment).pipe(
Effect.timeoutOption(VERSION_PROBE_TIMEOUT_MS),
Effect.result,
);
if (Result.isFailure(versionResult)) {
const error = versionResult.failure;
yield* Effect.logWarning("Grok CLI health check failed.", {
errorTag: error._tag,
});
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: grokSettings.enabled,
checkedAt,
models: fallbackModels,
probe: {
installed: !isCommandMissingCause(error),
version: null,
status: "error",
auth: { status: "unknown" },
message: isCommandMissingCause(error)
? "Grok CLI (`grok`) is not installed or not on PATH."
: "Failed to execute Grok CLI health check.",
},
});
}
if (Option.isNone(versionResult.success)) {
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: grokSettings.enabled,
checkedAt,
models: fallbackModels,
probe: {
installed: true,
version: null,
status: "error",
auth: { status: "unknown" },
message: "Grok CLI is installed but timed out while running `grok --version`.",
},
});
}
const versionOutput = versionResult.success.value;
const version = parseGenericCliVersion(`${versionOutput.stdout}\n${versionOutput.stderr}`);
if (versionOutput.code !== 0) {
yield* Effect.logWarning("Grok CLI version probe exited with a non-zero status.", {
exitCode: versionOutput.code,
stdoutLength: versionOutput.stdout.length,
stderrLength: versionOutput.stderr.length,
});
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: grokSettings.enabled,
checkedAt,
models: fallbackModels,
probe: {
installed: true,
version,
status: "error",
auth: { status: "unknown" },
message: "Grok CLI is installed but failed to run.",
},
});
}
const discoveryExit = yield* discoverGrokModelsViaAcp(grokSettings, environment).pipe(
Effect.timeoutOption(GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS),
Effect.exit,
);
if (Exit.isFailure(discoveryExit)) {
yield* Effect.logWarning("Grok ACP model discovery failed", {
errorTag: causeErrorTag(discoveryExit.cause),
});
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: grokSettings.enabled,
checkedAt,
models: fallbackModels,
probe: {
installed: true,
version,
status: "error",
auth: { status: "unknown" },
message: "Grok CLI is installed but ACP startup failed. Check server logs for details.",
},
});
}
if (Option.isNone(discoveryExit.value)) {
yield* Effect.logWarning(
`Grok ACP model discovery timed out after ${GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS}ms.`,
);
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: grokSettings.enabled,
checkedAt,
models: fallbackModels,
probe: {
installed: true,
version,
status: "error",
auth: { status: "unknown" },
message: `Grok CLI is installed but ACP startup timed out after ${GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS}ms.`,
},
});
}
const discoveredModels = discoveryExit.value.value;
const models =
discoveredModels.length > 0
? grokModelsFromSettings(grokSettings.customModels, discoveredModels)
: fallbackModels;
return buildServerProvider({
presentation: GROK_PRESENTATION,
enabled: grokSettings.enabled,
checkedAt,
models,
probe: {
installed: true,
version,
status: "ready",
auth: { status: "unknown" },
},
});
});
export const enrichGrokSnapshot = (input: {
readonly snapshot: ServerProvider;
readonly maintenanceCapabilities: ProviderMaintenanceCapabilities;
readonly enableProviderUpdateChecks?: boolean;
readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>;
readonly httpClient: HttpClient.HttpClient;
}): Effect.Effect<void> => {
const { snapshot, publishSnapshot } = input;
return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities, {
enableProviderUpdateChecks: input.enableProviderUpdateChecks,
}).pipe(
Effect.provideService(HttpClient.HttpClient, input.httpClient),
Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)),
Effect.catchCause((cause) =>
Effect.logWarning("Grok version advisory enrichment failed", {
errorTag: causeErrorTag(cause),
}),
),
Effect.asVoid,
);
};