| ... | ... | @@ -32,6 +32,7 @@ import { |
| 32 | 32 | } from "@t3tools/shared/assistantCitations"; |
| 33 | 33 | import { createModelSelection } from "@t3tools/shared/model"; |
| 34 | 34 | import { it, assert, describe, vi } from "@effect/vitest"; |
| 35 | import { afterAll } from "vite-plus/test"; |
| 35 | 36 | |
| 36 | 37 | import * as Cause from "effect/Cause"; |
| 37 | 38 | import * as Deferred from "effect/Deferred"; |
| ... | ... | @@ -54,6 +55,7 @@ import { |
| 54 | 55 | ProviderAdapterSessionNotFoundError, |
| 55 | 56 | ProviderUnsupportedError, |
| 56 | 57 | ProviderValidationError, |
| 58 | ProviderWorkspaceMissingError, |
| 57 | 59 | type ProviderAdapterError, |
| 58 | 60 | } from "../Errors.ts"; |
| 59 | 61 | import type { ProviderAdapterShape } from "../Services/ProviderAdapter.ts"; |
| ... | ... | @@ -79,6 +81,16 @@ const serverConfigTestLayer = ServerConfig.layerTest(process.cwd(), process.cwd( |
| 79 | 81 | Layer.provide(NodeServices.layer), |
| 80 | 82 | ); |
| 81 | 83 | |
| 84 | // startSession verifies the workspace folder exists before dispatching to an |
| 85 | // adapter, so session cwd fixtures must be real directories. |
| 86 | const fixtureCwdRoot = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "provider-service-test-")); |
| 87 | afterAll(() => NodeFS.rmSync(fixtureCwdRoot, { recursive: true, force: true })); |
| 88 | function fixtureCwd(name: string): string { |
| 89 | const dir = NodePath.join(fixtureCwdRoot, name); |
| 90 | NodeFS.mkdirSync(dir, { recursive: true }); |
| 91 | return dir; |
| 92 | } |
| 93 | |
| 82 | 94 | const asRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value); |
| 83 | 95 | const asEventId = (value: string): EventId => EventId.make(value); |
| 84 | 96 | const asThreadId = (value: string): ThreadId => ThreadId.make(value); |
| ... | ... | @@ -425,6 +437,7 @@ function makeProviderServiceLayer( |
| 425 | 437 | const layer = it.layer( |
| 426 | 438 | Layer.mergeAll( |
| 427 | 439 | makeProviderServiceLive().pipe( |
| 440 | Layer.provide(NodeServices.layer), |
| 428 | 441 | Layer.provide(providerAdapterLayer), |
| 429 | 442 | Layer.provide(directoryLayer), |
| 430 | 443 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -477,6 +490,7 @@ for (const [enabled, completed] of [ |
| 477 | 490 | const scope = yield* Scope.make(); |
| 478 | 491 | const services = yield* Layer.build( |
| 479 | 492 | makeProviderServiceLive().pipe( |
| 493 | Layer.provide(NodeServices.layer), |
| 480 | 494 | Layer.provide( |
| 481 | 495 | Layer.succeed(ProviderSessionDirectory.ProviderSessionDirectory, directory), |
| 482 | 496 | ), |
| ... | ... | @@ -596,6 +610,7 @@ it.effect("ProviderServiceLive catches stopAll failures during shutdown", () => |
| 596 | 610 | const directoryLayer = ProviderSessionDirectoryLive.pipe(Layer.provide(runtimeRepositoryLayer)); |
| 597 | 611 | const providerLayer = Layer.mergeAll( |
| 598 | 612 | makeProviderServiceLive().pipe( |
| 613 | Layer.provide(NodeServices.layer), |
| 599 | 614 | Layer.provide(providerAdapterLayer), |
| 600 | 615 | Layer.provide(directoryLayer), |
| 601 | 616 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -638,6 +653,7 @@ it.effect("ProviderServiceLive flushes deferred completions during shutdown", () |
| 638 | 653 | const directoryLayer = ProviderSessionDirectoryLive.pipe(Layer.provide(runtimeRepositoryLayer)); |
| 639 | 654 | const providerLayer = Layer.mergeAll( |
| 640 | 655 | makeProviderServiceLive().pipe( |
| 656 | Layer.provide(NodeServices.layer), |
| 641 | 657 | Layer.provide(providerAdapterLayer), |
| 642 | 658 | Layer.provide(directoryLayer), |
| 643 | 659 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -774,6 +790,7 @@ it.effect("ProviderServiceLive rejects new sessions for disabled providers", () |
| 774 | 790 | ); |
| 775 | 791 | const directoryLayer = ProviderSessionDirectoryLive.pipe(Layer.provide(runtimeRepositoryLayer)); |
| 776 | 792 | const providerLayer = makeProviderServiceLive().pipe( |
| 793 | Layer.provide(NodeServices.layer), |
| 777 | 794 | Layer.provide(providerAdapterLayer), |
| 778 | 795 | Layer.provide(directoryLayer), |
| 779 | 796 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -857,6 +874,7 @@ it.effect( |
| 857 | 874 | Layer.provide(runtimeRepositoryLayer), |
| 858 | 875 | ); |
| 859 | 876 | const providerLayer = makeProviderServiceLive().pipe( |
| 877 | Layer.provide(NodeServices.layer), |
| 860 | 878 | Layer.provide(providerAdapterLayer), |
| 861 | 879 | Layer.provide(directoryLayer), |
| 862 | 880 | Layer.provide(serverSettingsLayer), |
| ... | ... | @@ -926,6 +944,7 @@ it.effect("ProviderServiceLive rejects new sessions for disabled custom instance |
| 926 | 944 | ); |
| 927 | 945 | const directoryLayer = ProviderSessionDirectoryLive.pipe(Layer.provide(runtimeRepositoryLayer)); |
| 928 | 946 | const providerLayer = makeProviderServiceLive().pipe( |
| 947 | Layer.provide(NodeServices.layer), |
| 929 | 948 | Layer.provide(providerAdapterLayer), |
| 930 | 949 | Layer.provide(directoryLayer), |
| 931 | 950 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -1044,7 +1063,7 @@ unsupportedRollback.layer("ProviderServiceLive unsupported rewind", (it) => { |
| 1044 | 1063 | yield* provider.startSession(threadId, { |
| 1045 | 1064 | providerInstanceId: codexInstanceId, |
| 1046 | 1065 | threadId, |
| 1047 | | cwd: "/tmp/project", |
| 1066 | cwd: fixtureCwd("project"), |
| 1048 | 1067 | runtimeMode: "approval-required", |
| 1049 | 1068 | }); |
| 1050 | 1069 | if (!active) { |
| ... | ... | @@ -1098,6 +1117,7 @@ it.effect( |
| 1098 | 1117 | Layer.provide(runtimeRepositoryLayer), |
| 1099 | 1118 | ); |
| 1100 | 1119 | const providerLayer = makeProviderServiceLive().pipe( |
| 1120 | Layer.provide(NodeServices.layer), |
| 1101 | 1121 | Layer.provide(Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, registry)), |
| 1102 | 1122 | Layer.provide(directoryLayer), |
| 1103 | 1123 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -1218,6 +1238,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", ( |
| 1218 | 1238 | }).pipe(Effect.provide(directoryLayer)); |
| 1219 | 1239 | |
| 1220 | 1240 | const providerLayer = makeProviderServiceLive().pipe( |
| 1241 | Layer.provide(NodeServices.layer), |
| 1221 | 1242 | Layer.provide(Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, registry)), |
| 1222 | 1243 | Layer.provide(directoryLayer), |
| 1223 | 1244 | Layer.provide(defaultServerSettingsLayer), |
| ... | ... | @@ -1283,6 +1304,7 @@ it.effect( |
| 1283 | 1304 | Layer.provide(runtimeRepositoryLayer), |
| 1284 | 1305 | ); |
| 1285 | 1306 | const firstProviderLayer = makeProviderServiceLive().pipe( |
| 1307 | Layer.provide(NodeServices.layer), |
| 1286 | 1308 | Layer.provide( |
| 1287 | 1309 | Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, firstRegistry), |
| 1288 | 1310 | ), |
| ... | ... | @@ -1310,7 +1332,7 @@ it.effect( |
| 1310 | 1332 | const session = yield* provider.startSession(threadId, { |
| 1311 | 1333 | provider: ProviderDriverKind.make("codex"), |
| 1312 | 1334 | providerInstanceId: codexInstanceId, |
| 1313 | | cwd: "/tmp/project", |
| 1335 | cwd: fixtureCwd("project"), |
| 1314 | 1336 | runtimeMode: "full-access", |
| 1315 | 1337 | threadId, |
| 1316 | 1338 | }); |
| ... | ... | @@ -1343,6 +1365,7 @@ it.effect( |
| 1343 | 1365 | Layer.provide(runtimeRepositoryLayer), |
| 1344 | 1366 | ); |
| 1345 | 1367 | const secondProviderLayer = makeProviderServiceLive().pipe( |
| 1368 | Layer.provide(NodeServices.layer), |
| 1346 | 1369 | Layer.provide( |
| 1347 | 1370 | Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, secondRegistry), |
| 1348 | 1371 | ), |
| ... | ... | @@ -1380,7 +1403,7 @@ it.effect( |
| 1380 | 1403 | threadId?: string; |
| 1381 | 1404 | }; |
| 1382 | 1405 | assert.equal(startPayload.provider, "codex"); |
| 1383 | | assert.equal(startPayload.cwd, "/tmp/project"); |
| 1406 | assert.equal(startPayload.cwd, fixtureCwd("project")); |
| 1384 | 1407 | assert.deepEqual(startPayload.resumeCursor, updatedResumeCursor); |
| 1385 | 1408 | assert.equal(startPayload.threadId, startedSession.threadId); |
| 1386 | 1409 | } |
| ... | ... | @@ -1394,6 +1417,61 @@ it.effect( |
| 1394 | 1417 | ); |
| 1395 | 1418 | |
| 1396 | 1419 | routing.layer("ProviderServiceLive routing", (it) => { |
| 1420 | it.effect.each([CODEX_DRIVER, CLAUDE_AGENT_DRIVER, CURSOR_DRIVER])( |
| 1421 | "rejects missing, file, and saved workspace paths before starting %s", |
| 1422 | (driver) => |
| 1423 | Effect.gen(function* () { |
| 1424 | const provider = yield* ProviderService.ProviderService; |
| 1425 | const adapter = |
| 1426 | driver === CODEX_DRIVER |
| 1427 | ? routing.codex |
| 1428 | : driver === CLAUDE_AGENT_DRIVER |
| 1429 | ? routing.claude |
| 1430 | : routing.cursor; |
| 1431 | const cwd = fixtureCwd(`missing-workspace-${driver}`); |
| 1432 | const movedCwd = `${cwd}-moved`; |
| 1433 | const threadId = asThreadId(`missing-workspace-${driver}`); |
| 1434 | const input = { |
| 1435 | provider: driver, |
| 1436 | providerInstanceId: ProviderInstanceId.make(driver), |
| 1437 | threadId, |
| 1438 | runtimeMode: "full-access" as const, |
| 1439 | cwd, |
| 1440 | }; |
| 1441 | |
| 1442 | yield* provider.startSession(threadId, input); |
| 1443 | yield* provider.stopSession({ threadId }); |
| 1444 | adapter.startSession.mockClear(); |
| 1445 | NodeFS.renameSync(cwd, movedCwd); |
| 1446 | |
| 1447 | const failure = yield* provider.startSession(threadId, input).pipe(Effect.flip); |
| 1448 | assert.instanceOf(failure, ProviderWorkspaceMissingError); |
| 1449 | assert.include(failure.message, cwd); |
| 1450 | assert.equal(adapter.startSession.mock.calls.length, 0); |
| 1451 | |
| 1452 | const { cwd: _cwd, ...savedInput } = input; |
| 1453 | const savedFailure = yield* provider.startSession(threadId, savedInput).pipe(Effect.flip); |
| 1454 | assert.instanceOf(savedFailure, ProviderWorkspaceMissingError); |
| 1455 | assert.include(savedFailure.message, cwd); |
| 1456 | assert.equal(adapter.startSession.mock.calls.length, 0); |
| 1457 | |
| 1458 | NodeFS.writeFileSync(cwd, "not a directory"); |
| 1459 | const fileFailure = yield* provider.startSession(threadId, input).pipe(Effect.flip); |
| 1460 | assert.instanceOf(fileFailure, ProviderWorkspaceMissingError); |
| 1461 | assert.include(fileFailure.message, cwd); |
| 1462 | assert.equal(adapter.startSession.mock.calls.length, 0); |
| 1463 | |
| 1464 | NodeFS.unlinkSync(cwd); |
| 1465 | NodeFS.renameSync(movedCwd, cwd); |
| 1466 | const restored = yield* provider.startSession(threadId, savedInput); |
| 1467 | assert.equal(restored.cwd, cwd); |
| 1468 | assert.equal(adapter.startSession.mock.calls.length, 1); |
| 1469 | yield* provider.stopSession({ threadId }); |
| 1470 | adapter.startSession.mockClear(); |
| 1471 | adapter.stopSession.mockClear(); |
| 1472 | }), |
| 1473 | ); |
| 1474 | |
| 1397 | 1475 | it.effect("allows promptless continuation only for capable providers", () => |
| 1398 | 1476 | Effect.gen(function* () { |
| 1399 | 1477 | const provider = yield* ProviderService.ProviderService; |
| ... | ... | @@ -1452,7 +1530,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1452 | 1530 | provider: ProviderDriverKind.make("codex"), |
| 1453 | 1531 | providerInstanceId: codexInstanceId, |
| 1454 | 1532 | threadId: asThreadId("thread-1"), |
| 1455 | | cwd: "/tmp/project", |
| 1533 | cwd: fixtureCwd("project"), |
| 1456 | 1534 | runtimeMode: "full-access", |
| 1457 | 1535 | }); |
| 1458 | 1536 | assert.equal(session.provider, "codex"); |
| ... | ... | @@ -1522,7 +1600,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1522 | 1600 | threadId?: string; |
| 1523 | 1601 | }; |
| 1524 | 1602 | assert.equal(startPayload.provider, "codex"); |
| 1525 | | assert.equal(startPayload.cwd, "/tmp/project"); |
| 1603 | assert.equal(startPayload.cwd, fixtureCwd("project")); |
| 1526 | 1604 | assert.deepEqual(startPayload.resumeCursor, session.resumeCursor); |
| 1527 | 1605 | assert.equal(startPayload.threadId, session.threadId); |
| 1528 | 1606 | } |
| ... | ... | @@ -1799,7 +1877,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1799 | 1877 | provider: CODEX_DRIVER, |
| 1800 | 1878 | providerInstanceId: codexInstanceId, |
| 1801 | 1879 | threadId, |
| 1802 | | cwd: "/tmp/feedback-project", |
| 1880 | cwd: fixtureCwd("feedback-project"), |
| 1803 | 1881 | runtimeMode: "full-access", |
| 1804 | 1882 | }); |
| 1805 | 1883 | yield* routing.codex.stopSession(threadId); |
| ... | ... | @@ -1862,7 +1940,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1862 | 1940 | provider: ProviderDriverKind.make("codex"), |
| 1863 | 1941 | providerInstanceId: codexInstanceId, |
| 1864 | 1942 | threadId: asThreadId("thread-attach"), |
| 1865 | | cwd: "/tmp/project", |
| 1943 | cwd: fixtureCwd("project"), |
| 1866 | 1944 | runtimeMode: "full-access", |
| 1867 | 1945 | }); |
| 1868 | 1946 | |
| ... | ... | @@ -1937,7 +2015,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1937 | 2015 | provider: ProviderDriverKind.make("codex"), |
| 1938 | 2016 | providerInstanceId: codexInstanceId, |
| 1939 | 2017 | threadId: asThreadId("thread-1"), |
| 1940 | | cwd: "/tmp/project", |
| 2018 | cwd: fixtureCwd("project"), |
| 1941 | 2019 | runtimeMode: "full-access", |
| 1942 | 2020 | }); |
| 1943 | 2021 | yield* routing.codex.stopSession(initial.threadId); |
| ... | ... | @@ -1963,7 +2041,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1963 | 2041 | threadId?: string; |
| 1964 | 2042 | }; |
| 1965 | 2043 | assert.equal(startPayload.provider, "codex"); |
| 1966 | | assert.equal(startPayload.cwd, "/tmp/project"); |
| 2044 | assert.equal(startPayload.cwd, fixtureCwd("project")); |
| 1967 | 2045 | assert.deepEqual(startPayload.resumeCursor, initial.resumeCursor); |
| 1968 | 2046 | assert.equal(startPayload.threadId, initial.threadId); |
| 1969 | 2047 | } |
| ... | ... | @@ -1982,7 +2060,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1982 | 2060 | provider: ProviderDriverKind.make("codex"), |
| 1983 | 2061 | providerInstanceId: codexInstanceId, |
| 1984 | 2062 | threadId: asThreadId("thread-reap-preserve"), |
| 1985 | | cwd: "/tmp/project-reap-preserve", |
| 2063 | cwd: fixtureCwd("project-reap-preserve"), |
| 1986 | 2064 | runtimeMode: "full-access", |
| 1987 | 2065 | }); |
| 1988 | 2066 | |
| ... | ... | @@ -2017,7 +2095,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2017 | 2095 | threadId?: string; |
| 2018 | 2096 | }; |
| 2019 | 2097 | assert.equal(startPayload.provider, "codex"); |
| 2020 | | assert.equal(startPayload.cwd, "/tmp/project-reap-preserve"); |
| 2098 | assert.equal(startPayload.cwd, fixtureCwd("project-reap-preserve")); |
| 2021 | 2099 | assert.deepEqual(startPayload.resumeCursor, initial.resumeCursor); |
| 2022 | 2100 | assert.equal(startPayload.threadId, initial.threadId); |
| 2023 | 2101 | } |
| ... | ... | @@ -2033,7 +2111,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2033 | 2111 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2034 | 2112 | providerInstanceId: claudeAgentInstanceId, |
| 2035 | 2113 | threadId: asThreadId("thread-claude"), |
| 2036 | | cwd: "/tmp/project-claude", |
| 2114 | cwd: fixtureCwd("project-claude"), |
| 2037 | 2115 | runtimeMode: "full-access", |
| 2038 | 2116 | }); |
| 2039 | 2117 | |
| ... | ... | @@ -2049,7 +2127,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2049 | 2127 | }; |
| 2050 | 2128 | assert.equal(startPayload.provider, "claudeAgent"); |
| 2051 | 2129 | assert.equal(startPayload.providerInstanceId, claudeAgentInstanceId); |
| 2052 | | assert.equal(startPayload.cwd, "/tmp/project-claude"); |
| 2130 | assert.equal(startPayload.cwd, fixtureCwd("project-claude")); |
| 2053 | 2131 | } |
| 2054 | 2132 | }), |
| 2055 | 2133 | ); |
| ... | ... | @@ -2064,7 +2142,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2064 | 2142 | provider: ProviderDriverKind.make("codex"), |
| 2065 | 2143 | providerInstanceId: codexInstanceId, |
| 2066 | 2144 | threadId, |
| 2067 | | cwd: "/tmp/project-binding-mismatch", |
| 2145 | cwd: fixtureCwd("project-binding-mismatch"), |
| 2068 | 2146 | runtimeMode: "full-access", |
| 2069 | 2147 | }); |
| 2070 | 2148 | yield* directory.upsert({ |
| ... | ... | @@ -2094,7 +2172,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2094 | 2172 | provider: ProviderDriverKind.make("codex"), |
| 2095 | 2173 | providerInstanceId: codexInstanceId, |
| 2096 | 2174 | threadId, |
| 2097 | | cwd: "/tmp/project-provider-replacement", |
| 2175 | cwd: fixtureCwd("project-provider-replacement"), |
| 2098 | 2176 | runtimeMode: "full-access", |
| 2099 | 2177 | }); |
| 2100 | 2178 | |
| ... | ... | @@ -2105,7 +2183,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2105 | 2183 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2106 | 2184 | providerInstanceId: claudeAgentInstanceId, |
| 2107 | 2185 | threadId, |
| 2108 | | cwd: "/tmp/project-provider-replacement", |
| 2186 | cwd: fixtureCwd("project-provider-replacement"), |
| 2109 | 2187 | runtimeMode: "full-access", |
| 2110 | 2188 | }); |
| 2111 | 2189 | |
| ... | ... | @@ -2132,7 +2210,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2132 | 2210 | provider: ProviderDriverKind.make("codex"), |
| 2133 | 2211 | providerInstanceId: codexInstanceId, |
| 2134 | 2212 | threadId: asThreadId("thread-1"), |
| 2135 | | cwd: "/tmp/project-send-turn", |
| 2213 | cwd: fixtureCwd("project-send-turn"), |
| 2136 | 2214 | runtimeMode: "full-access", |
| 2137 | 2215 | }); |
| 2138 | 2216 | |
| ... | ... | @@ -2157,7 +2235,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2157 | 2235 | threadId?: string; |
| 2158 | 2236 | }; |
| 2159 | 2237 | assert.equal(startPayload.provider, "codex"); |
| 2160 | | assert.equal(startPayload.cwd, "/tmp/project-send-turn"); |
| 2238 | assert.equal(startPayload.cwd, fixtureCwd("project-send-turn")); |
| 2161 | 2239 | assert.deepEqual(startPayload.resumeCursor, initial.resumeCursor); |
| 2162 | 2240 | assert.equal(startPayload.threadId, initial.threadId); |
| 2163 | 2241 | } |
| ... | ... | @@ -2173,7 +2251,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2173 | 2251 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2174 | 2252 | providerInstanceId: claudeAgentInstanceId, |
| 2175 | 2253 | threadId: asThreadId("thread-claude-send-turn"), |
| 2176 | | cwd: "/tmp/project-claude-send-turn", |
| 2254 | cwd: fixtureCwd("project-claude-send-turn"), |
| 2177 | 2255 | modelSelection: createModelSelection( |
| 2178 | 2256 | ProviderInstanceId.make("claudeAgent"), |
| 2179 | 2257 | "claude-opus-4-6", |
| ... | ... | @@ -2204,7 +2282,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2204 | 2282 | threadId?: string; |
| 2205 | 2283 | }; |
| 2206 | 2284 | assert.equal(startPayload.provider, "claudeAgent"); |
| 2207 | | assert.equal(startPayload.cwd, "/tmp/project-claude-send-turn"); |
| 2285 | assert.equal(startPayload.cwd, fixtureCwd("project-claude-send-turn")); |
| 2208 | 2286 | assert.deepEqual( |
| 2209 | 2287 | startPayload.modelSelection, |
| 2210 | 2288 | createModelSelection(ProviderInstanceId.make("claudeAgent"), "claude-opus-4-6", [ |
| ... | ... | @@ -2368,6 +2446,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2368 | 2446 | Layer.provide(runtimeRepositoryLayer), |
| 2369 | 2447 | ); |
| 2370 | 2448 | const firstProviderLayer = makeProviderServiceLive().pipe( |
| 2449 | Layer.provide(NodeServices.layer), |
| 2371 | 2450 | Layer.provide( |
| 2372 | 2451 | Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, firstRegistry), |
| 2373 | 2452 | ), |
| ... | ... | @@ -2389,7 +2468,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2389 | 2468 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2390 | 2469 | providerInstanceId: claudeAgentInstanceId, |
| 2391 | 2470 | threadId: asThreadId("thread-claude-start"), |
| 2392 | | cwd: "/tmp/project-claude-start", |
| 2471 | cwd: fixtureCwd("project-claude-start"), |
| 2393 | 2472 | runtimeMode: "full-access", |
| 2394 | 2473 | }); |
| 2395 | 2474 | }).pipe(Effect.provide(firstProviderLayer)); |
| ... | ... | @@ -2407,6 +2486,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2407 | 2486 | Layer.provide(runtimeRepositoryLayer), |
| 2408 | 2487 | ); |
| 2409 | 2488 | const secondProviderLayer = makeProviderServiceLive().pipe( |
| 2489 | Layer.provide(NodeServices.layer), |
| 2410 | 2490 | Layer.provide( |
| 2411 | 2491 | Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, secondRegistry), |
| 2412 | 2492 | ), |
| ... | ... | @@ -2430,7 +2510,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2430 | 2510 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2431 | 2511 | providerInstanceId: claudeAgentInstanceId, |
| 2432 | 2512 | threadId: initial.threadId, |
| 2433 | | cwd: "/tmp/project-claude-start", |
| 2513 | cwd: fixtureCwd("project-claude-start"), |
| 2434 | 2514 | runtimeMode: "full-access", |
| 2435 | 2515 | }); |
| 2436 | 2516 | }).pipe(Effect.provide(secondProviderLayer)); |
| ... | ... | @@ -2446,7 +2526,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2446 | 2526 | threadId?: string; |
| 2447 | 2527 | }; |
| 2448 | 2528 | assert.equal(startPayload.provider, "claudeAgent"); |
| 2449 | | assert.equal(startPayload.cwd, "/tmp/project-claude-start"); |
| 2529 | assert.equal(startPayload.cwd, fixtureCwd("project-claude-start")); |
| 2450 | 2530 | assert.deepEqual(startPayload.resumeCursor, initial.resumeCursor); |
| 2451 | 2531 | assert.equal(startPayload.threadId, initial.threadId); |
| 2452 | 2532 | } |
| ... | ... | @@ -2476,6 +2556,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2476 | 2556 | Layer.provide(runtimeRepositoryLayer), |
| 2477 | 2557 | ); |
| 2478 | 2558 | const firstProviderLayer = makeProviderServiceLive().pipe( |
| 2559 | Layer.provide(NodeServices.layer), |
| 2479 | 2560 | Layer.provide( |
| 2480 | 2561 | Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, firstRegistry), |
| 2481 | 2562 | ), |
| ... | ... | @@ -2497,7 +2578,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2497 | 2578 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2498 | 2579 | providerInstanceId: claudeAgentInstanceId, |
| 2499 | 2580 | threadId: asThreadId("thread-claude-cwd"), |
| 2500 | | cwd: "/tmp/project-claude-cwd", |
| 2581 | cwd: fixtureCwd("project-claude-cwd"), |
| 2501 | 2582 | runtimeMode: "full-access", |
| 2502 | 2583 | }); |
| 2503 | 2584 | }).pipe(Effect.provide(firstProviderLayer)); |
| ... | ... | @@ -2510,6 +2591,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2510 | 2591 | Layer.provide(runtimeRepositoryLayer), |
| 2511 | 2592 | ); |
| 2512 | 2593 | const secondProviderLayer = makeProviderServiceLive().pipe( |
| 2594 | Layer.provide(NodeServices.layer), |
| 2513 | 2595 | Layer.provide( |
| 2514 | 2596 | Layer.succeed(ProviderAdapterRegistry.ProviderAdapterRegistry, secondRegistry), |
| 2515 | 2597 | ), |
| ... | ... | @@ -2548,7 +2630,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 2548 | 2630 | threadId?: string; |
| 2549 | 2631 | }; |
| 2550 | 2632 | assert.equal(startPayload.provider, "claudeAgent"); |
| 2551 | | assert.equal(startPayload.cwd, "/tmp/project-claude-cwd"); |
| 2633 | assert.equal(startPayload.cwd, fixtureCwd("project-claude-cwd")); |
| 2552 | 2634 | assert.deepEqual(startPayload.resumeCursor, initial.resumeCursor); |
| 2553 | 2635 | assert.equal(startPayload.threadId, initial.threadId); |
| 2554 | 2636 | } |
| ... | ... | @@ -2742,7 +2824,7 @@ fanout.layer("ProviderServiceLive fanout", (it) => { |
| 2742 | 2824 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2743 | 2825 | providerInstanceId: claudeAgentInstanceId, |
| 2744 | 2826 | threadId: asThreadId("thread-metrics"), |
| 2745 | | cwd: "/tmp/project", |
| 2827 | cwd: fixtureCwd("project"), |
| 2746 | 2828 | runtimeMode: "full-access", |
| 2747 | 2829 | }); |
| 2748 | 2830 | |
| ... | ... | @@ -2820,7 +2902,7 @@ fanout.layer("ProviderServiceLive fanout", (it) => { |
| 2820 | 2902 | provider: ProviderDriverKind.make("claudeAgent"), |
| 2821 | 2903 | providerInstanceId: claudeAgentInstanceId, |
| 2822 | 2904 | threadId: asThreadId("thread-send-metrics"), |
| 2823 | | cwd: "/tmp/project-send-metrics", |
| 2905 | cwd: fixtureCwd("project-send-metrics"), |
| 2824 | 2906 | runtimeMode: "full-access", |
| 2825 | 2907 | }); |
| 2826 | 2908 | |
| ... | ... | @@ -4155,7 +4237,7 @@ validation.layer("ProviderServiceLive validation", (it) => { |
| 4155 | 4237 | provider: ProviderDriverKind.make("codex"), |
| 4156 | 4238 | providerInstanceId: codexInstanceId, |
| 4157 | 4239 | threadId: asThreadId("thread-missing"), |
| 4158 | | cwd: "/tmp/project", |
| 4240 | cwd: fixtureCwd("project"), |
| 4159 | 4241 | runtimeMode: "full-access", |
| 4160 | 4242 | }); |
| 4161 | 4243 | |
| ... | ... | @@ -4204,7 +4286,7 @@ boundedListing.layer("ProviderServiceLive session listing", (it) => { |
| 4204 | 4286 | provider: CODEX_DRIVER, |
| 4205 | 4287 | providerInstanceId: codexInstanceId, |
| 4206 | 4288 | threadId: activeSessionThreadId, |
| 4207 | | cwd: "/tmp/project-active-session", |
| 4289 | cwd: fixtureCwd("project-active-session"), |
| 4208 | 4290 | runtimeMode: "full-access", |
| 4209 | 4291 | }); |
| 4210 | 4292 | listThreadIds.mockClear(); |