542 lines · 17.3 KB · TypeScript
RawDownload
import {  type CustomModelSetting,  type GrokSettings,  type ModelCapabilities,  type ServerProvider,  type ServerProviderAuth,  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 {  AUTH_PROBE_TIMEOUT_MS,  buildServerProvider,  COMPACT_SLASH_COMMAND,  isCommandMissingCause,  parseGenericCliVersion,  providerModelsFromSettings,  spawnAndCollect,  type ServerProviderDraft,} from "../providerSnapshot.ts";import {  enrichProviderSnapshotWithVersionAdvisory,  type ProviderMaintenanceCapabilities,} from "../providerMaintenance.ts";import {  GROK_DEFAULT_MODEL_SLUG,  isValidGrokReasoningEffortToken,  makeGrokAcpRuntime,  resolveGrokAcpBaseModelId,} from "../acp/GrokAcpSupport.ts";import { sessionModelStateFromInitialize } from "../acp/AcpRuntimeModel.ts";import { discoverGrokSkills } from "../Drivers/GrokSkills.ts"; const GROK_PRESENTATION = {  displayName: "Grok",  badgeLabel: "Early Access",  showInteractionModeToggle: false,} as const;const EMPTY_CAPABILITIES: ModelCapabilities = createModelCapabilities({  optionDescriptors: [],}); const VERSION_PROBE_TIMEOUT_MS = 4_000;// `initialize` is a single local round trip, so this is generous even on slow machines.const GROK_ACP_INITIALIZE_TIMEOUT_MS = 8_000;const GROK_API_KEY_ENV = "XAI_API_KEY"; const GROK_BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [  {    slug: GROK_DEFAULT_MODEL_SLUG,    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<CustomModelSetting> | undefined,  builtInModels: ReadonlyArray<ServerProviderModel> = GROK_BUILT_IN_MODELS,): ReadonlyArray<ServerProviderModel> {  return providerModelsFromSettings(builtInModels, customModels ?? [], EMPTY_CAPABILITIES);} function nonEmptyString(value: unknown): string | undefined {  return typeof value === "string" ? value.trim() || undefined : undefined;} function isRecord(value: unknown): value is Record<string, unknown> {  return typeof value === "object" && value !== null && !Array.isArray(value);} function grokReasoningOptionsFromModel(model: EffectAcpSchema.ModelInfo): {  readonly options: ReadonlyArray<{    value: string;    label: string;    description?: string;    isDefault?: boolean;  }>;  readonly currentValue: string | undefined;} {  const meta = model._meta;  if (!meta || meta.supportsReasoningEffort === false) {    return { options: [], currentValue: undefined };  }   const currentEffort = nonEmptyString(meta.reasoningEffort);  const advertisedOptions = Array.isArray(meta.reasoningEfforts) ? meta.reasoningEfforts : [];  const seen = new Set<string>();  const options: Array<{    value: string;    label: string;    description?: string;    advertisedDefault: boolean;  }> = [];   for (const entry of advertisedOptions) {    if (!isRecord(entry)) {      continue;    }    const rawValue = nonEmptyString(entry.value);    const rawId = nonEmptyString(entry.id);    const value =      rawValue && isValidGrokReasoningEffortToken(rawValue)        ? rawValue        : rawId && isValidGrokReasoningEffortToken(rawId)          ? rawId          : undefined;    if (value === undefined || seen.has(value)) {      continue;    }    seen.add(value);    const description = nonEmptyString(entry.description);    options.push({      value,      label: nonEmptyString(entry.label) ?? value,      ...(description ? { description } : {}),      advertisedDefault: entry.default === true || entry.isDefault === true,    });  }   const currentValue =    currentEffort && options.some((option) => option.value === currentEffort)      ? currentEffort      : undefined;  const advertisedDefaults = options.filter((option) => option.advertisedDefault);  const selectedDefault =    advertisedDefaults.find((option) => option.value === currentValue)?.value ??    advertisedDefaults[0]?.value;  return {    options: options.map(({ value, label, description }) => ({      value,      label,      ...(description ? { description } : {}),      ...(value === selectedDefault ? { isDefault: true } : {}),    })),    currentValue: currentValue ?? selectedDefault,  };} export function buildGrokModelCapabilities(model: EffectAcpSchema.ModelInfo): ModelCapabilities {  const reasoning = grokReasoningOptionsFromModel(model);  return reasoning.options.length > 0    ? createModelCapabilities({        optionDescriptors: [          {            id: "reasoningEffort",            label: "Reasoning",            type: "select",            options: reasoning.options.map((option) => ({              id: option.value,              label: option.label,              ...(option.description ? { description: option.description } : {}),              ...(option.isDefault ? { isDefault: true } : {}),            })),            ...(reasoning.currentValue ? { currentValue: reasoning.currentValue } : {}),          },        ],      })    : EMPTY_CAPABILITIES;} /** Models advertised by the ACP agent, with the session's current model marked as default. */export function buildGrokModelsFromSessionModelState(  modelState: EffectAcpSchema.SessionModelState | null | undefined,): ReadonlyArray<ServerProviderModel> {  if (!modelState || modelState.availableModels.length === 0) {    return [];  }  const currentModelId = modelState.currentModelId.trim();  const seen = new Set<string>();  return modelState.availableModels.flatMap((model): ServerProviderModel[] => {    const slug = resolveGrokAcpBaseModelId(model.modelId);    if (!slug || seen.has(slug)) {      return [];    }    seen.add(slug);    return [      {        slug,        name: model.name.trim() || slug,        isCustom: false,        ...(model.modelId.trim() === currentModelId ? { isDefault: true } : {}),        capabilities: buildGrokModelCapabilities(model),      },    ];  });} export interface GrokModelsCliOutput {  /** True or false when the CLI printed a login line, null when it printed neither. */  readonly authenticated: boolean | null;  readonly models: ReadonlyArray<ServerProviderModel>;} /** * Parses `grok models`. The command exits 0 whether or not the user is logged in, so the * text is the only signal. Current output looks like: * *     You are logged in with grok.com. *     Default model: grok-4.6 *     Available models: *       * grok-4.6 (default) *       - grok-4.5 */export function parseGrokModelsCliOutput(output: string): GrokModelsCliOutput {  const authenticated = /you are logged in/i.test(output)    ? true    : /not authenticated|not logged in/i.test(output)      ? false      : null;   const seen = new Set<string>();  const models: ServerProviderModel[] = [];  for (const line of output.split(/\r?\n/)) {    const bullet = line.match(/^\s*[*-]\s+(\S+)(.*)$/);    if (!bullet?.[1]) {      continue;    }    const slug = resolveGrokAcpBaseModelId(bullet[1]);    if (seen.has(slug)) {      continue;    }    seen.add(slug);    models.push({      slug,      name: displayNameFromGrokModelSlug(slug),      isCustom: false,      ...(/\(default\)/i.test(bullet[2] ?? "") ? { isDefault: true } : {}),      capabilities: EMPTY_CAPABILITIES,    });  }  return { authenticated, models };} function displayNameFromGrokModelSlug(slug: string): string {  return slug    .split(/[-_]/g)    .map((part) => (part.toLowerCase() === "grok" ? "Grok" : part))    .join(" ");} const runGrokCliCommand = (  grokSettings: GrokSettings,  args: ReadonlyArray<string>,  environment: NodeJS.ProcessEnv,) =>  Effect.gen(function* () {    const command = grokSettings.binaryPath || "grok";    const spawnCommand = yield* resolveSpawnCommand(command, args, { env: environment });    return yield* spawnAndCollect(      command,      ChildProcess.make(spawnCommand.command, spawnCommand.args, {        env: environment,        shell: spawnCommand.shell,      }),    );  }); /** * Reads model metadata from `initialize._meta.modelState`. This never calls `authenticate` * or `session/new`, so it cannot open a browser login or boot the workspace's MCP servers. */const discoverGrokModelsViaAcpInitialize = (  grokSettings: GrokSettings,  environment: NodeJS.ProcessEnv,) =>  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 initialized = yield* acp.initialize();    return buildGrokModelsFromSessionModelState(sessionModelStateFromInitialize(initialized));  }).pipe(Effect.scoped); export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* (  grokSettings: GrokSettings,  environment: NodeJS.ProcessEnv = process.env,  cwd?: string,): 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* runGrokCliCommand(grokSettings, ["--version"], 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.",      },    });  }   // `grok models` reports login state and model slugs without starting the agent.  const modelsResult = yield* runGrokCliCommand(grokSettings, ["models"], environment).pipe(    Effect.timeoutOption(AUTH_PROBE_TIMEOUT_MS),    Effect.result,  );  // Only a clean exit is parsed. Failed invocations print help or error text that  // must not be read as model slugs or as a login verdict.  const modelsOutput =    Result.isSuccess(modelsResult) &&    Option.isSome(modelsResult.success) &&    modelsResult.success.value.code === 0      ? modelsResult.success.value      : undefined;  const cliModels: GrokModelsCliOutput = modelsOutput    ? parseGrokModelsCliOutput(`${modelsOutput.stdout}\n${modelsOutput.stderr}`)    : { authenticated: null, models: [] };  if (!modelsOutput) {    yield* Effect.logWarning("Grok CLI model listing failed or timed out.", {      errorTag: Result.isFailure(modelsResult)        ? modelsResult.failure._tag        : Option.isNone(modelsResult.success)          ? "Timeout"          : `ExitCode${modelsResult.success.value.code}`,    });  }   const auth: ServerProviderAuth = environment[GROK_API_KEY_ENV]?.trim()    ? { status: "authenticated", type: "api_key", label: "xAI API key" }    : cliModels.authenticated === true      ? { status: "authenticated", type: "cached_token", label: "Grok account" }      : cliModels.authenticated === false        ? { status: "unauthenticated" }        : { status: "unknown" };   const skills = yield* discoverGrokSkills(grokSettings, environment, cwd).pipe(    Effect.tapError((cause) => Effect.logDebug("Grok skill discovery failed.", { cause })),    Effect.orElseSucceed(() => []),  );   const acpExit = yield* discoverGrokModelsViaAcpInitialize(grokSettings, environment).pipe(    Effect.timeoutOption(GROK_ACP_INITIALIZE_TIMEOUT_MS),    Effect.exit,  );  const acpModels = Exit.isSuccess(acpExit) ? Option.getOrElse(acpExit.value, () => []) : [];  const acpFailed = Exit.isFailure(acpExit) || Option.isNone(acpExit.value);  if (acpFailed) {    yield* Effect.logWarning("Grok ACP initialize probe failed or timed out.", {      errorTag: Exit.isFailure(acpExit) ? causeErrorTag(acpExit.cause) : "Timeout",    });  }   const discoveredModels = acpModels.length > 0 ? acpModels : cliModels.models;  const models =    discoveredModels.length > 0      ? grokModelsFromSettings(grokSettings.customModels, discoveredModels)      : fallbackModels;   if (auth.status === "unauthenticated") {    return buildServerProvider({      presentation: GROK_PRESENTATION,      enabled: grokSettings.enabled,      checkedAt,      models,      skills,      probe: {        installed: true,        version,        status: "error",        auth,        message: "Grok CLI is installed but not logged in. Run `grok login`.",      },    });  }   return buildServerProvider({    presentation: GROK_PRESENTATION,    enabled: grokSettings.enabled,

Lines 1–500 of 542.