Skip to content
Source
Sign inSign up
Open History to see the last commit

McpAppModelContext.test.ts

65 lines2.7 KB

1import { ThreadId, TurnItemId } from "@t3tools/contracts";
2import { assert, it } from "@effect/vitest";
3import * as NodeSqliteClient from "@t3tools/shared/nodeSqliteClient";
4import * as Effect from "effect/Effect";
5import * as Layer from "effect/Layer";
6import * as SqlClient from "effect/sql/SqlClient";
7​
8import { runMigrations } from "../persistence/Migrations.ts";
9import * as McpAppModelContext from "./McpAppModelContext.ts";
10​
11const database = NodeSqliteClient.layer({ filename: ":memory:" });
12const layer = it.layer(
13 Layer.merge(database, McpAppModelContext.layer.pipe(Layer.provide(database))),
14);
15​
16const threadId = ThreadId.make("thread-context");
17const forkId = ThreadId.make("thread-context-fork");
18​
19const insertAppItem = (itemId: string, runId: string, runStatus: string) =>
20 Effect.gen(function* () {
21 const sql = yield* SqlClient.SqlClient;
22 yield* sql`
23 INSERT INTO orchestration_v2_projection_runs
24 (run_id, thread_id, ordinal, provider, status, requested_at, payload_json)
25 VALUES (${runId}, ${threadId}, ${runId.length}, 'codex', ${runStatus}, '2026-01-01', '{}')
26 `;
27 yield* sql`
28 INSERT INTO orchestration_v2_projection_turn_items
29 (turn_item_id, thread_id, run_id, ordinal, type, status, updated_at, payload_json)
30 VALUES (${itemId}, ${threadId}, ${runId}, 0, 'dynamic_tool', 'completed', '2026-01-01', '{}')
31 `;
32 });
33​
34layer("McpAppModelContext", (it) => {
35 it.effect("sends only apps still in the thread's history, including a fork's", () =>
36 Effect.gen(function* () {
37 yield* runMigrations();
38 const store = yield* McpAppModelContext.McpAppModelContext;
39 yield* insertAppItem("item-kept", "run-a", "completed");
40 yield* insertAppItem("item-rolled-back", "run-bb", "rolled_back");
41 const set = (thread: ThreadId, itemId: string, text: string) =>
42 store.set({
43 threadId: thread,
44 itemId: TurnItemId.make(itemId),
45 server: "todos",
46 tool: "list_todos",
47 text,
48 });
49 yield* set(threadId, "item-kept", "kept");
50 yield* set(threadId, "item-rolled-back", "from a rolled-back run");
51 yield* set(threadId, "item-deleted", "from an item that is gone");
52​
53 yield* set(forkId, "item-kept", "from the fork");
54 yield* set(forkId, "item-rolled-back", "inherited before the rollback");
55​
56 const texts = (thread: ThreadId) =>
57 store.forThread(thread).pipe(Effect.map((entries) => entries.map((entry) => entry.text)));
58 assert.deepEqual(yield* texts(threadId), ["kept"]);
59 assert.deepEqual(yield* texts(forkId), ["from the fork", "inherited before the rollback"]);
60​
61 yield* set(threadId, "item-kept", "");
62 assert.deepEqual(yield* texts(threadId), []);
63 }),
64 );
65});