| ... | @@ -103,7 +103,7 @@ const collectQueueUntil = Effect.fn("TransferBudget.collectQueueUntil")(function | ... | @@ -103,7 +103,7 @@ const collectQueueUntil = Effect.fn("TransferBudget.collectQueueUntil")(function |
| 103 | | 103 | |
| 104 | import * as BackgroundPolicy from "./background/BackgroundPolicy.ts"; | 104 | import * as BackgroundPolicy from "./background/BackgroundPolicy.ts"; |
| 105 | import * as ServerConfig from "./config.ts"; | 105 | import * as ServerConfig from "./config.ts"; |
| 106 | import { makeRoutesLayer } from "./server.ts"; | 106 | import { HTTP_ROUTER_CONFIG, makeRoutesLayer } from "./server.ts"; |
| 107 | import { | 107 | import { |
| 108 | isThreadDetailEvent, | 108 | isThreadDetailEvent, |
| 109 | resolveAvailableEditorsForConfig, | 109 | resolveAvailableEditorsForConfig, |
| ... | @@ -629,6 +629,7 @@ const buildAppUnderTest = (options?: { | ... | @@ -629,6 +629,7 @@ const buildAppUnderTest = (options?: { |
| 629 | { | 629 | { |
| 630 | disableListenLog: true, | 630 | disableListenLog: true, |
| 631 | disableLogger: true, | 631 | disableLogger: true, |
| | 632 | routerConfig: HTTP_ROUTER_CONFIG, |
| 632 | }, | 633 | }, |
| 633 | ).pipe( | 634 | ).pipe( |
| 634 | Layer.provide( | 635 | Layer.provide( |
| ... | @@ -1527,6 +1528,41 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -1527,6 +1528,41 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 1527 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), | 1528 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), |
| 1528 | ); | 1529 | ); |
| 1529 | | 1530 | |
| | 1531 | it.effect("serves snapshots for MCP handoff thread IDs above the router default", () => |
| | 1532 | Effect.gen(function* () { |
| | 1533 | const threadId = ThreadId.make( |
| | 1534 | "thread:mcp:abfba0d2-b591-4b7e-aad1-e943d89811fa:handoff%3A0ae5edf4-2ea3-4ee3-ba7c-48de3ac92896%3A2026-08-24T17%3A08%3A52.138Z:0", |
| | 1535 | ); |
| | 1536 | const thread = { |
| | 1537 | ...makeDefaultOrchestrationReadModel().threads[0]!, |
| | 1538 | id: threadId, |
| | 1539 | }; |
| | 1540 | yield* buildAppUnderTest({ |
| | 1541 | layers: { |
| | 1542 | projectionSnapshotQuery: { |
| | 1543 | getThreadDetailSnapshot: (requestedThreadId) => |
| | 1544 | Effect.succeed( |
| | 1545 | requestedThreadId === threadId |
| | 1546 | ? Option.some({ snapshotSequence: 1, thread }) |
| | 1547 | : Option.none(), |
| | 1548 | ), |
| | 1549 | }, |
| | 1550 | }, |
| | 1551 | }); |
| | 1552 | |
| | 1553 | const response = yield* fetchEffect( |
| | 1554 | yield* getHttpServerUrl(`/api/orchestration/threads/${encodeURIComponent(threadId)}`), |
| | 1555 | { headers: { cookie: yield* getAuthenticatedSessionCookieHeader() } }, |
| | 1556 | ); |
| | 1557 | const snapshot = yield* responseJsonEffect<{ |
| | 1558 | readonly thread: { readonly id: ThreadId }; |
| | 1559 | }>(response); |
| | 1560 | |
| | 1561 | assert.equal(response.status, 200); |
| | 1562 | assert.equal(snapshot.thread.id, threadId); |
| | 1563 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), |
| | 1564 | ); |
| | 1565 | |
| 1530 | it.effect("compresses large JSON responses through the composed routes", () => | 1566 | it.effect("compresses large JSON responses through the composed routes", () => |
| 1531 | Effect.gen(function* () { | 1567 | Effect.gen(function* () { |
| 1532 | const descriptor = { | 1568 | const descriptor = { |