| ... | ... | @@ -58,7 +58,9 @@ it.layer(NodeServices.layer)("Claude capability probe SDK boundary", (it) => { |
| 58 | 58 | const fs = yield* FileSystem.FileSystem; |
| 59 | 59 | const path = yield* Path.Path; |
| 60 | 60 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-claude-probe-sdk-" }); |
| 61 | | const executablePath = path.join(tempDir, "fake-claude.mjs"); |
| 61 | const executablePath = yield* path.fromFileUrl( |
| 62 | new URL("./testing/ClaudeCapabilitiesProbe.fixture.mjs", import.meta.url), |
| 63 | ); |
| 62 | 64 | const invocationPath = path.join(tempDir, "invocation.json"); |
| 63 | 65 | // The probe aborts the SDK without awaiting the child's exit, and on |
| 64 | 66 | // Windows a directory that is still some process's cwd cannot be |
| ... | ... | @@ -80,68 +82,6 @@ it.layer(NodeServices.layer)("Claude capability probe SDK boundary", (it) => { |
| 80 | 82 | ), |
| 81 | 83 | ); |
| 82 | 84 | |
| 83 | | yield* fs.writeFileString( |
| 84 | | executablePath, |
| 85 | | [ |
| 86 | | "#!/usr/bin/env node", |
| 87 | | 'import { existsSync, readFileSync, writeFileSync } from "node:fs";', |
| 88 | | 'import { createInterface } from "node:readline";', |
| 89 | | "const args = process.argv.slice(2);", |
| 90 | | 'const mcpConfigIndex = args.indexOf("--mcp-config");', |
| 91 | | "const rawMcpConfig = mcpConfigIndex >= 0 ? args[mcpConfigIndex + 1] : undefined;", |
| 92 | | "let mcpConfig;", |
| 93 | | "if (rawMcpConfig) {", |
| 94 | | ' const contents = existsSync(rawMcpConfig) ? readFileSync(rawMcpConfig, "utf8") : rawMcpConfig;', |
| 95 | | " try { mcpConfig = JSON.parse(contents); } catch { mcpConfig = contents; }", |
| 96 | | "}", |
| 97 | | "writeFileSync(process.env.T3_PROBE_INVOCATION_PATH, JSON.stringify({", |
| 98 | | " args,", |
| 99 | | " cwd: process.cwd(),", |
| 100 | | " connectorEnv: process.env.ENABLE_CLAUDEAI_MCP_SERVERS,", |
| 101 | | " mcpConfig,", |
| 102 | | "}));", |
| 103 | | "const lines = createInterface({ input: process.stdin });", |
| 104 | | 'lines.on("line", (line) => {', |
| 105 | | " const message = JSON.parse(line);", |
| 106 | | ' if (message.type !== "control_request") return;', |
| 107 | | " const reply = (response) => process.stdout.write(JSON.stringify({", |
| 108 | | ' type: "control_response",', |
| 109 | | ' response: { subtype: "success", request_id: message.request_id, response },', |
| 110 | | ' }) + "\\n");', |
| 111 | | ' if (message.request?.subtype === "initialize") {', |
| 112 | | " reply({", |
| 113 | | ' commands: [{ name: "review", description: "Review changes", argumentHint: "[path]" }],', |
| 114 | | " agents: [],", |
| 115 | | ' output_style: "default",', |
| 116 | | ' available_output_styles: ["default"],', |
| 117 | | " models: [],", |
| 118 | | ' account: { email: "dev@example.com", subscriptionType: "pro", tokenSource: "oauth" },', |
| 119 | | " });", |
| 120 | | " }", |
| 121 | | " // The probe follows initialize with get_usage on the same process.", |
| 122 | | ' if (message.request?.subtype === "get_usage") {', |
| 123 | | " reply({", |
| 124 | | " session: {},", |
| 125 | | ' subscription_type: "pro",', |
| 126 | | " rate_limits_available: true,", |
| 127 | | ' rate_limits: { five_hour: { utilization: 12, resets_at: "2026-07-18T14:39:00Z" } },', |
| 128 | | " behaviors: null,", |
| 129 | | " });", |
| 130 | | " }", |
| 131 | | "});", |
| 132 | | "// Stay alive for follow-up control requests, but never outlive the", |
| 133 | | "// parent: the probe aborts the SDK without awaiting the child, so an", |
| 134 | | "// unconditional interval would strand this process until reboot.", |
| 135 | | "const keepAlive = setInterval(() => {}, 1_000);", |
| 136 | | 'lines.on("close", () => {', |
| 137 | | " clearInterval(keepAlive);", |
| 138 | | " process.exit(0);", |
| 139 | | "});", |
| 140 | | "", |
| 141 | | ].join("\n"), |
| 142 | | ); |
| 143 | | yield* fs.chmod(executablePath, 0o755); |
| 144 | | |
| 145 | 85 | const capabilities = yield* probeClaudeCapabilities( |
| 146 | 86 | decodeClaudeSettings({ binaryPath: executablePath }), |
| 147 | 87 | { |