154 lines · 6.0 KB · TypeScript
RawDownload
import { ClaudeSettings } from "@t3tools/contracts";import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Path from "effect/Path";import * as Schema from "effect/Schema"; import {  buildClaudeCapabilitiesProbeQueryOptions,  CLAUDE_CAPABILITIES_PROBE_SETTING_SOURCES,  isLegacyClaudeModel,  probeClaudeCapabilities,} from "./ClaudeProvider.ts"; const decodeClaudeSettings = Schema.decodeSync(ClaudeSettings); it("keeps only the Claude 5 family out of legacy models", () => {  assert.deepStrictEqual(    ["claude-fable-5", "claude-opus-5", "claude-sonnet-5", "claude-opus-4-8"].map((model) => [      model,      isLegacyClaudeModel(model),    ]),    [      ["claude-fable-5", false],      ["claude-opus-5", false],      ["claude-sonnet-5", false],      ["claude-opus-4-8", true],    ],  );}); it("isolates Claude capability probes without dropping workspace setting sources", () => {  const abortController = new AbortController();  const options = buildClaudeCapabilitiesProbeQueryOptions({    executablePath: "/usr/bin/claude",    abortController,    environment: {      HOME: "/home/user",      ENABLE_CLAUDEAI_MCP_SERVERS: "true",    },    cwd: "/workspace/project",  });   assert.deepEqual(options.mcpServers, {});  assert.equal(options.strictMcpConfig, true);  assert.equal(options.cwd, "/workspace/project");  assert.deepEqual(options.settingSources, [...CLAUDE_CAPABILITIES_PROBE_SETTING_SOURCES]);  assert.deepEqual(options.allowedTools, []);  assert.equal(options.persistSession, false);  assert.equal(options.pathToClaudeCodeExecutable, "/usr/bin/claude");  assert.equal(options.abortController, abortController);  assert.equal(options.env?.HOME, "/home/user");  assert.equal(options.env?.ENABLE_CLAUDEAI_MCP_SERVERS, "false");}); it.layer(NodeServices.layer)("Claude capability probe SDK boundary", (it) => {  it.effect("serializes strict no-MCP options and still resolves account capabilities", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const path = yield* Path.Path;      const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-claude-probe-sdk-" });      const executablePath = path.join(tempDir, "fake-claude.mjs");      const invocationPath = path.join(tempDir, "invocation.json");      const workspaceCwd = path.join(tempDir, "workspace");      yield* fs.makeDirectory(workspaceCwd, { recursive: true });       yield* fs.writeFileString(        executablePath,        [          "#!/usr/bin/env node",          'import { existsSync, readFileSync, writeFileSync } from "node:fs";',          'import { createInterface } from "node:readline";',          "const args = process.argv.slice(2);",          'const mcpConfigIndex = args.indexOf("--mcp-config");',          "const rawMcpConfig = mcpConfigIndex >= 0 ? args[mcpConfigIndex + 1] : undefined;",          "let mcpConfig;",          "if (rawMcpConfig) {",          '  const contents = existsSync(rawMcpConfig) ? readFileSync(rawMcpConfig, "utf8") : rawMcpConfig;',          "  try { mcpConfig = JSON.parse(contents); } catch { mcpConfig = contents; }",          "}",          "writeFileSync(process.env.T3_PROBE_INVOCATION_PATH, JSON.stringify({",          "  args,",          "  cwd: process.cwd(),",          "  connectorEnv: process.env.ENABLE_CLAUDEAI_MCP_SERVERS,",          "  mcpConfig,",          "}));",          "const lines = createInterface({ input: process.stdin });",          'lines.on("line", (line) => {',          "  const message = JSON.parse(line);",          '  if (message.type !== "control_request" || message.request?.subtype !== "initialize") return;',          "  process.stdout.write(JSON.stringify({",          '    type: "control_response",',          "    response: {",          '      subtype: "success",',          "      request_id: message.request_id,",          "      response: {",          '        commands: [{ name: "review", description: "Review changes", argumentHint: "[path]" }],',          "        agents: [],",          '        output_style: "default",',          '        available_output_styles: ["default"],',          "        models: [],",          '        account: { email: "dev@example.com", subscriptionType: "pro", tokenSource: "oauth" },',          "      },",          "    },",          '  }) + "\\n");',          "});",          "setInterval(() => {}, 1_000);",          "",        ].join("\n"),      );      yield* fs.chmod(executablePath, 0o755);       const capabilities = yield* probeClaudeCapabilities(        decodeClaudeSettings({ binaryPath: executablePath }),        {          ...process.env,          T3_PROBE_INVOCATION_PATH: invocationPath,          ENABLE_CLAUDEAI_MCP_SERVERS: "true",        },        workspaceCwd,      );       assert.deepEqual(capabilities, {        email: "dev@example.com",        subscriptionType: "pro",        tokenSource: "oauth",        apiProvider: undefined,        slashCommands: [          {            name: "review",            description: "Review changes",            input: { hint: "[path]" },          },        ],      });       // @effect-diagnostics-next-line preferSchemaOverJson:off      const invocation = JSON.parse(yield* fs.readFileString(invocationPath)) as {        readonly args: ReadonlyArray<string>;        readonly cwd: string;        readonly connectorEnv: string;        readonly mcpConfig: unknown;      };      assert.equal(invocation.cwd, yield* fs.realPath(workspaceCwd));      assert.equal(invocation.connectorEnv, "false");      assert.equal(invocation.args.includes("--strict-mcp-config"), true);      assert.equal(invocation.args.includes("--mcp-config"), false);      assert.equal(invocation.mcpConfig, undefined);       assert.equal(invocation.args.includes("--setting-sources=user,project,local"), true);    }).pipe(Effect.scoped),  );});