authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-21 19:04:59-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-26 13:20:36-08:00
log4f4691676acad990c6a51221e2522d4ffb131415
tree9b498f596cfa0e5cc09df76e3ae684ef2f9f9178
parent483a1ae3718e39269075e99ea84e437d4cfad591

Persist turn diffs and checkpoint reverts in orchestration

- map `checkpoint/captured` to `thread.turnDiff.complete` and record turn status/id - handle `thread.revert` to truncate messages and turn summaries in read model - migrate event store from `better-sqlite3` to `node:sqlite` and add safe close/idempotent stop tests

10 files changed, 553 insertions(+), 99 deletions(-)

apps/server/package.json-2
...@@ -17,7 +17,6 @@...@@ -17,7 +17,6 @@
17 "test": "vitest run"17 "test": "vitest run"
18 },18 },
19 "dependencies": {19 "dependencies": {
20 "better-sqlite3": "^12.6.2",
21 "effect": "^3.19.19",20 "effect": "^3.19.19",
22 "node-pty": "^1.1.0",21 "node-pty": "^1.1.0",
23 "open": "^10.1.0",22 "open": "^10.1.0",
...@@ -26,7 +25,6 @@...@@ -26,7 +25,6 @@
26 "devDependencies": {25 "devDependencies": {
27 "@t3tools/contracts": "workspace:*",26 "@t3tools/contracts": "workspace:*",
28 "@t3tools/web": "workspace:*",27 "@t3tools/web": "workspace:*",
29 "@types/better-sqlite3": "^7.6.13",
30 "@types/node": "^22.10.2",28 "@types/node": "^22.10.2",
31 "@types/ws": "^8.5.13",29 "@types/ws": "^8.5.13",
32 "tsdown": "^0.20.3",30 "tsdown": "^0.20.3",
apps/server/src/orchestration/engine.test.ts+194
...@@ -116,4 +116,198 @@ describe("OrchestrationEngine", () => {...@@ -116,4 +116,198 @@ describe("OrchestrationEngine", () => {
116 expect(events[1]?.type).toBe("project.deleted");116 expect(events[1]?.type).toBe("project.deleted");
117 await engine.stop();117 await engine.stop();
118 });118 });
119
120 it("stores completed turn summaries even when no files changed", async () => {
121 const stateDir = makeTempDir("t3code-orchestration-turn-diff-");
122 const engine = new OrchestrationEngine(stateDir);
123 const completedAt = new Date().toISOString();
124 await engine.start();
125 await engine.dispatch({
126 type: "project.create",
127 commandId: "cmd-project-turn-diff",
128 projectId: "project-turn-diff",
129 name: "turn-diff",
130 cwd: "/tmp/turn-diff",
131 model: "gpt-5-codex",
132 createdAt: completedAt,
133 });
134 await engine.dispatch({
135 type: "thread.create",
136 commandId: "cmd-thread-turn-diff",
137 threadId: "thread-turn-diff",
138 projectId: "project-turn-diff",
139 title: "Turn diff thread",
140 model: "gpt-5-codex",
141 branch: null,
142 worktreePath: null,
143 createdAt: completedAt,
144 });
145 await engine.dispatch({
146 type: "thread.turnDiff.complete",
147 commandId: "cmd-turn-diff-complete",
148 threadId: "thread-turn-diff",
149 turnId: "turn-1",
150 completedAt,
151 status: "completed",
152 files: [],
153 checkpointTurnCount: 1,
154 createdAt: completedAt,
155 });
156
157 const firstThread = engine.getSnapshot().threads.find((thread) => thread.id === "thread-turn-diff");
158 expect(firstThread?.turnDiffSummaries).toEqual([
159 {
160 turnId: "turn-1",
161 completedAt,
162 status: "completed",
163 files: [],
164 checkpointTurnCount: 1,
165 },
166 ]);
167 await engine.stop();
168
169 const restartedEngine = new OrchestrationEngine(stateDir);
170 await restartedEngine.start();
171 const restartedThread = restartedEngine
172 .getSnapshot()
173 .threads.find((thread) => thread.id === "thread-turn-diff");
174 expect(restartedThread?.turnDiffSummaries).toEqual([
175 {
176 turnId: "turn-1",
177 completedAt,
178 status: "completed",
179 files: [],
180 checkpointTurnCount: 1,
181 },
182 ]);
183 await restartedEngine.stop();
184 });
185
186 it("reverts thread messages and turn summaries to a checkpoint", async () => {
187 const stateDir = makeTempDir("t3code-orchestration-revert-");
188 const engine = new OrchestrationEngine(stateDir);
189 const createdAt = new Date().toISOString();
190 await engine.start();
191 await engine.dispatch({
192 type: "project.create",
193 commandId: "cmd-project-revert",
194 projectId: "project-revert",
195 name: "revert",
196 cwd: "/tmp/revert",
197 model: "gpt-5-codex",
198 createdAt,
199 });
200 await engine.dispatch({
201 type: "thread.create",
202 commandId: "cmd-thread-revert",
203 threadId: "thread-revert",
204 projectId: "project-revert",
205 title: "Revert thread",
206 model: "gpt-5-codex",
207 branch: null,
208 worktreePath: null,
209 createdAt,
210 });
211 await engine.dispatch({
212 type: "message.send",
213 commandId: "cmd-msg-1-user",
214 threadId: "thread-revert",
215 messageId: "user-1",
216 role: "user",
217 text: "first",
218 streaming: false,
219 createdAt,
220 });
221 await engine.dispatch({
222 type: "message.send",
223 commandId: "cmd-msg-1-assistant",
224 threadId: "thread-revert",
225 messageId: "assistant:turn-1",
226 role: "assistant",
227 text: "first-response",
228 streaming: false,
229 createdAt,
230 });
231 await engine.dispatch({
232 type: "thread.turnDiff.complete",
233 commandId: "cmd-turn-1-complete",
234 threadId: "thread-revert",
235 turnId: "turn-1",
236 completedAt: createdAt,
237 status: "completed",
238 files: [],
239 assistantMessageId: "assistant:turn-1",
240 checkpointTurnCount: 1,
241 createdAt,
242 });
243
244 const createdAtSecond = new Date(Date.now() + 1_000).toISOString();
245 await engine.dispatch({
246 type: "message.send",
247 commandId: "cmd-msg-2-user",
248 threadId: "thread-revert",
249 messageId: "user-2",
250 role: "user",
251 text: "second",
252 streaming: false,
253 createdAt: createdAtSecond,
254 });
255 await engine.dispatch({
256 type: "message.send",
257 commandId: "cmd-msg-2-assistant",
258 threadId: "thread-revert",
259 messageId: "assistant:turn-2",
260 role: "assistant",
261 text: "second-response",
262 streaming: false,
263 createdAt: createdAtSecond,
264 });
265 await engine.dispatch({
266 type: "thread.turnDiff.complete",
267 commandId: "cmd-turn-2-complete",
268 threadId: "thread-revert",
269 turnId: "turn-2",
270 completedAt: createdAtSecond,
271 status: "completed",
272 files: [],
273 assistantMessageId: "assistant:turn-2",
274 checkpointTurnCount: 2,
275 createdAt: createdAtSecond,
276 });
277
278 await engine.dispatch({
279 type: "thread.revert",
280 commandId: "cmd-thread-revert-apply",
281 threadId: "thread-revert",
282 turnCount: 1,
283 messageCount: 2,
284 createdAt: createdAtSecond,
285 });
286
287 const thread = engine.getSnapshot().threads.find((entry) => entry.id === "thread-revert");
288 expect(thread?.messages.map((message) => message.id)).toEqual(["user-1", "assistant:turn-1"]);
289 expect(thread?.turnDiffSummaries.map((summary) => summary.turnId)).toEqual(["turn-1"]);
290 expect(thread?.latestTurnId).toBe("turn-1");
291 await engine.stop();
292
293 const restarted = new OrchestrationEngine(stateDir);
294 await restarted.start();
295 const restartedThread = restarted
296 .getSnapshot()
297 .threads.find((entry) => entry.id === "thread-revert");
298 expect(restartedThread?.messages.map((message) => message.id)).toEqual([
299 "user-1",
300 "assistant:turn-1",
301 ]);
302 expect(restartedThread?.turnDiffSummaries.map((summary) => summary.turnId)).toEqual(["turn-1"]);
303 await restarted.stop();
304 });
305
306 it("allows stop to be called multiple times", async () => {
307 const stateDir = makeTempDir("t3code-orchestration-stop-");
308 const engine = new OrchestrationEngine(stateDir);
309 await engine.start();
310 await engine.stop();
311 await expect(engine.stop()).resolves.toBeUndefined();
312 });
119});313});
apps/server/src/orchestration/engine.ts+51-5
...@@ -148,6 +148,42 @@ function mapCommandToEvent(command: OrchestrationCommand): Omit<OrchestrationEve...@@ -148,6 +148,42 @@ function mapCommandToEvent(command: OrchestrationCommand): Omit<OrchestrationEve
148 updatedAt: command.createdAt,148 updatedAt: command.createdAt,
149 },149 },
150 };150 };
151 case "thread.turnDiff.complete":
152 return {
153 eventId,
154 type: "thread.turn-diff-completed",
155 aggregateType: "thread",
156 aggregateId: command.threadId,
157 occurredAt: command.createdAt,
158 commandId: command.commandId,
159 payload: {
160 threadId: command.threadId,
161 turnId: command.turnId,
162 completedAt: command.completedAt,
163 ...(command.status !== undefined ? { status: command.status } : {}),
164 files: command.files,
165 ...(command.assistantMessageId !== undefined
166 ? { assistantMessageId: command.assistantMessageId }
167 : {}),
168 ...(command.checkpointTurnCount !== undefined
169 ? { checkpointTurnCount: command.checkpointTurnCount }
170 : {}),
171 },
172 };
173 case "thread.revert":
174 return {
175 eventId,
176 type: "thread.reverted",
177 aggregateType: "thread",
178 aggregateId: command.threadId,
179 occurredAt: command.createdAt,
180 commandId: command.commandId,
181 payload: {
182 threadId: command.threadId,
183 turnCount: command.turnCount,
184 messageCount: command.messageCount,
185 },
186 };
151 }187 }
152}188}
153189
...@@ -169,7 +205,9 @@ export class OrchestrationEngine {...@@ -169,7 +205,9 @@ export class OrchestrationEngine {
169 this.eventStore = new SqliteEventStore(dbPath);205 this.eventStore = new SqliteEventStore(dbPath);
170 this.readModel = createEmptyReadModel(new Date().toISOString());206 this.readModel = createEmptyReadModel(new Date().toISOString());
171 this.commandQueue = Runtime.runSync(this.runtime)(Queue.unbounded<CommandEnvelope>());207 this.commandQueue = Runtime.runSync(this.runtime)(Queue.unbounded<CommandEnvelope>());
172 this.readModelPubSub = Runtime.runSync(this.runtime)(PubSub.unbounded<OrchestrationReadModel>());208 this.readModelPubSub = Runtime.runSync(this.runtime)(
209 PubSub.unbounded<OrchestrationReadModel>(),
210 );
173 this.eventPubSub = Runtime.runSync(this.runtime)(PubSub.unbounded<OrchestrationEvent>());211 this.eventPubSub = Runtime.runSync(this.runtime)(PubSub.unbounded<OrchestrationEvent>());
174 }212 }
175213
...@@ -184,11 +222,15 @@ export class OrchestrationEngine {...@@ -184,11 +222,15 @@ export class OrchestrationEngine {
184 Effect.tryPromise({222 Effect.tryPromise({
185 try: async () => {223 try: async () => {
186 const eventBase = mapCommandToEvent(envelope.command);224 const eventBase = mapCommandToEvent(envelope.command);
187 const savedEvent = await Runtime.runPromise(this.runtime)(this.eventStore.append(eventBase));225 const savedEvent = await Runtime.runPromise(this.runtime)(
226 this.eventStore.append(eventBase),
227 );
188 this.readModel = reduceEvent(this.readModel, savedEvent);228 this.readModel = reduceEvent(this.readModel, savedEvent);
189 await Promise.all([229 await Promise.all([
190 Runtime.runPromise(this.runtime)(PubSub.publish(this.eventPubSub, savedEvent)),230 Runtime.runPromise(this.runtime)(PubSub.publish(this.eventPubSub, savedEvent)),
191 Runtime.runPromise(this.runtime)(PubSub.publish(this.readModelPubSub, this.readModel)),231 Runtime.runPromise(this.runtime)(
232 PubSub.publish(this.readModelPubSub, this.readModel),
233 ),
192 ]);234 ]);
193 for (const listener of this.domainEventListeners) {235 for (const listener of this.domainEventListeners) {
194 listener(savedEvent);236 listener(savedEvent);
...@@ -199,7 +241,8 @@ export class OrchestrationEngine {...@@ -199,7 +241,8 @@ export class OrchestrationEngine {
199 envelope.resolve({ sequence: savedEvent.sequence });241 envelope.resolve({ sequence: savedEvent.sequence });
200 },242 },
201 catch: (error) => {243 catch: (error) => {
202 const message = error instanceof Error ? error.message : "Unknown command processing error";244 const message =
245 error instanceof Error ? error.message : "Unknown command processing error";
203 envelope.reject(new Error(message));246 envelope.reject(new Error(message));
204 return undefined;247 return undefined;
205 },248 },
...@@ -219,6 +262,7 @@ export class OrchestrationEngine {...@@ -219,6 +262,7 @@ export class OrchestrationEngine {
219 await Runtime.runPromise(this.runtime)(Fiber.interrupt(this.workerFiber));262 await Runtime.runPromise(this.runtime)(Fiber.interrupt(this.workerFiber));
220 this.workerFiber = null;263 this.workerFiber = null;
221 }264 }
265 this.eventStore.close();
222 }266 }
223267
224 getSnapshot(): OrchestrationReadModel {268 getSnapshot(): OrchestrationReadModel {
...@@ -226,7 +270,9 @@ export class OrchestrationEngine {...@@ -226,7 +270,9 @@ export class OrchestrationEngine {
226 }270 }
227271
228 async replayEvents(fromSequenceExclusive: number): Promise<OrchestrationEvent[]> {272 async replayEvents(fromSequenceExclusive: number): Promise<OrchestrationEvent[]> {
229 return Runtime.runPromise(this.runtime)(this.eventStore.readFromSequence(fromSequenceExclusive));273 return Runtime.runPromise(this.runtime)(
274 this.eventStore.readFromSequence(fromSequenceExclusive),
275 );
230 }276 }
231277
232 async dispatchUnknown(command: unknown): Promise<{ sequence: number }> {278 async dispatchUnknown(command: unknown): Promise<{ sequence: number }> {
apps/server/src/orchestration/eventStore.ts+65-21
...@@ -1,8 +1,9 @@...@@ -1,8 +1,9 @@
1import fs from "node:fs";1import fs from "node:fs";
2import path from "node:path";2import path from "node:path";
3import { DatabaseSync, StatementSync } from "node:sqlite";
4import type { SQLOutputValue } from "node:sqlite";
35
4import type { OrchestrationEvent } from "@t3tools/contracts";6import type { OrchestrationEvent } from "@t3tools/contracts";
5import Database from "better-sqlite3";
6import { Effect } from "effect";7import { Effect } from "effect";
78
8interface EventRow {9interface EventRow {
...@@ -16,15 +17,56 @@ interface EventRow {...@@ -16,15 +17,56 @@ interface EventRow {
16 payload_json: string;17 payload_json: string;
17}18}
1819
20function readRequiredString(
21 row: Record<string, SQLOutputValue>,
22 column: keyof EventRow,
23): string {
24 const value = row[column];
25 if (typeof value !== "string") {
26 throw new Error(`Invalid SQLite value for ${String(column)}: expected string`);
27 }
28 return value;
29}
30
31function readOptionalString(
32 row: Record<string, SQLOutputValue>,
33 column: keyof EventRow,
34): string | null {
35 const value = row[column];
36 if (value === null) return null;
37 if (typeof value !== "string") {
38 throw new Error(`Invalid SQLite value for ${String(column)}: expected string or null`);
39 }
40 return value;
41}
42
43function readRequiredNumber(
44 row: Record<string, SQLOutputValue>,
45 column: keyof EventRow,
46): number {
47 const value = row[column];
48 if (typeof value === "number") return value;
49 if (typeof value === "bigint") return Number(value);
50 throw new Error(`Invalid SQLite value for ${String(column)}: expected number`);
51}
52
19export class SqliteEventStore {53export class SqliteEventStore {
20 private readonly db: Database.Database;54 private readonly db: DatabaseSync;
55 private readonly insertStatement: StatementSync;
56 private closed = false;
2157
22 constructor(dbPath: string) {58 constructor(dbPath: string) {
23 fs.mkdirSync(path.dirname(dbPath), { recursive: true });59 fs.mkdirSync(path.dirname(dbPath), { recursive: true });
24 this.db = new Database(dbPath);60 this.db = new DatabaseSync(dbPath);
25 this.db.pragma("journal_mode = WAL");61 this.db.exec("PRAGMA journal_mode = WAL;");
26 this.db.pragma("foreign_keys = ON");62 this.db.exec("PRAGMA foreign_keys = ON;");
27 this.migrate();63 this.migrate();
64 this.insertStatement = this.db.prepare(`
65 INSERT INTO orchestration_events (
66 event_id, event_type, aggregate_type, aggregate_id, occurred_at, command_id, payload_json
67 )
68 VALUES (?, ?, ?, ?, ?, ?, ?)
69 `);
28 }70 }
2971
30 private migrate(): void {72 private migrate(): void {
...@@ -47,13 +89,7 @@ export class SqliteEventStore {...@@ -47,13 +89,7 @@ export class SqliteEventStore {
4789
48 append(event: Omit<OrchestrationEvent, "sequence">): Effect.Effect<OrchestrationEvent> {90 append(event: Omit<OrchestrationEvent, "sequence">): Effect.Effect<OrchestrationEvent> {
49 return Effect.sync(() => {91 return Effect.sync(() => {
50 const stmt = this.db.prepare(`92 const result = this.insertStatement.run(
51 INSERT INTO orchestration_events (
52 event_id, event_type, aggregate_type, aggregate_id, occurred_at, command_id, payload_json
53 )
54 VALUES (?, ?, ?, ?, ?, ?, ?)
55 `);
56 const result = stmt.run(
57 event.eventId,93 event.eventId,
58 event.type,94 event.type,
59 event.aggregateType,95 event.aggregateType,
...@@ -82,16 +118,16 @@ export class SqliteEventStore {...@@ -82,16 +118,16 @@ export class SqliteEventStore {
82 LIMIT ?118 LIMIT ?
83 `,119 `,
84 )120 )
85 .all(sequenceExclusive, limit) as EventRow[];121 .all(sequenceExclusive, limit);
86 return rows.map((row) => ({122 return rows.map((row) => ({
87 sequence: row.sequence,123 sequence: readRequiredNumber(row, "sequence"),
88 eventId: row.event_id,124 eventId: readRequiredString(row, "event_id"),
89 type: row.event_type,125 type: readRequiredString(row, "event_type"),
90 aggregateType: row.aggregate_type,126 aggregateType: readRequiredString(row, "aggregate_type"),
91 aggregateId: row.aggregate_id,127 aggregateId: readRequiredString(row, "aggregate_id"),
92 occurredAt: row.occurred_at,128 occurredAt: readRequiredString(row, "occurred_at"),
93 commandId: row.command_id,129 commandId: readOptionalString(row, "command_id"),
94 payload: JSON.parse(row.payload_json) as unknown,130 payload: JSON.parse(readRequiredString(row, "payload_json")) as unknown,
95 }));131 }));
96 });132 });
97 }133 }
...@@ -99,4 +135,12 @@ export class SqliteEventStore {...@@ -99,4 +135,12 @@ export class SqliteEventStore {
99 readAll(): Effect.Effect<OrchestrationEvent[]> {135 readAll(): Effect.Effect<OrchestrationEvent[]> {
100 return this.readFromSequence(0, Number.MAX_SAFE_INTEGER);136 return this.readFromSequence(0, Number.MAX_SAFE_INTEGER);
101 }137 }
138
139 close(): void {
140 if (this.closed) {
141 return;
142 }
143 this.closed = true;
144 this.db.close();
145 }
102}146}
apps/server/src/orchestration/reducer.ts+105
...@@ -31,6 +31,10 @@ function asNumber(value: unknown): number | null {...@@ -31,6 +31,10 @@ function asNumber(value: unknown): number | null {
31 return typeof value === "number" && Number.isFinite(value) ? value : null;31 return typeof value === "number" && Number.isFinite(value) ? value : null;
32}32}
3333
34function asArray(value: unknown): unknown[] {
35 return Array.isArray(value) ? value : [];
36}
37
34export function createEmptyReadModel(nowIso: string): OrchestrationReadModel {38export function createEmptyReadModel(nowIso: string): OrchestrationReadModel {
35 return {39 return {
36 sequence: 0,40 sequence: 0,
...@@ -192,6 +196,107 @@ export function reduceEvent(...@@ -192,6 +196,107 @@ export function reduceEvent(
192 }),196 }),
193 };197 };
194 }198 }
199 case "thread.turn-diff-completed": {
200 if (!payload) return nextBase;
201 const threadId = asString(payload.threadId) ?? event.aggregateId;
202 const thread = nextBase.threads.find((entry) => entry.id === threadId);
203 const turnId = asString(payload.turnId);
204 if (!thread || !turnId) return nextBase;
205
206 const files = asArray(payload.files).flatMap((filePayload) => {
207 const file = asObject(filePayload);
208 const filePath = asString(file?.path);
209 if (!filePath) {
210 return [];
211 }
212
213 const nextFile: {
214 path: string;
215 kind?: string;
216 additions?: number;
217 deletions?: number;
218 } = { path: filePath };
219 const kind = asString(file?.kind);
220 if (kind !== null) {
221 nextFile.kind = kind;
222 }
223 const additions = asNumber(file?.additions);
224 if (additions !== null) {
225 nextFile.additions = additions;
226 }
227 const deletions = asNumber(file?.deletions);
228 if (deletions !== null) {
229 nextFile.deletions = deletions;
230 }
231 return [nextFile];
232 });
233
234 const nextSummary = {
235 turnId,
236 completedAt: asString(payload.completedAt) ?? event.occurredAt,
237 ...(asString(payload.status) !== null ? { status: asString(payload.status) ?? undefined } : {}),
238 files,
239 ...(asString(payload.assistantMessageId) !== null
240 ? { assistantMessageId: asString(payload.assistantMessageId) ?? undefined }
241 : {}),
242 ...(asNumber(payload.checkpointTurnCount) !== null
243 ? { checkpointTurnCount: asNumber(payload.checkpointTurnCount) ?? undefined }
244 : {}),
245 };
246 const turnDiffSummaries = [...thread.turnDiffSummaries.filter((summary) => summary.turnId !== turnId), nextSummary]
247 .toSorted((left, right) => left.completedAt.localeCompare(right.completedAt));
248
249 return {
250 ...nextBase,
251 threads: updateThread(nextBase.threads, threadId, {
252 latestTurnId: turnId,
253 latestTurnCompletedAt: nextSummary.completedAt,
254 turnDiffSummaries,
255 updatedAt: event.occurredAt,
256 }),
257 };
258 }
259 case "thread.reverted": {
260 if (!payload) return nextBase;
261 const threadId = asString(payload.threadId) ?? event.aggregateId;
262 const thread = nextBase.threads.find((entry) => entry.id === threadId);
263 if (!thread) return nextBase;
264
265 const targetTurnCount = Math.max(0, Math.floor(asNumber(payload.turnCount) ?? 0));
266 const targetMessageCount = Math.max(0, Math.floor(asNumber(payload.messageCount) ?? 0));
267 const sortedSummaries = [...thread.turnDiffSummaries].toSorted((left, right) =>
268 left.completedAt.localeCompare(right.completedAt),
269 );
270 const inferredTurnCountByTurnId = new Map<string, number>();
271 for (let index = 0; index < sortedSummaries.length; index += 1) {
272 const summary = sortedSummaries[index];
273 if (!summary) continue;
274 inferredTurnCountByTurnId.set(summary.turnId, index + 1);
275 }
276
277 const turnDiffSummaries = thread.turnDiffSummaries
278 .filter((summary) => {
279 const checkpointTurnCount =
280 summary.checkpointTurnCount ?? inferredTurnCountByTurnId.get(summary.turnId) ?? 0;
281 return checkpointTurnCount <= targetTurnCount;
282 })
283 .toSorted((left, right) => left.completedAt.localeCompare(right.completedAt));
284 const latestSummary =
285 turnDiffSummaries.length > 0 ? turnDiffSummaries[turnDiffSummaries.length - 1] : null;
286
287 return {
288 ...nextBase,
289 threads: updateThread(nextBase.threads, threadId, {
290 messages: thread.messages.slice(0, Math.min(targetMessageCount, thread.messages.length)),
291 turnDiffSummaries,
292 latestTurnId: latestSummary?.turnId ?? null,
293 latestTurnStartedAt: null,
294 latestTurnCompletedAt: latestSummary?.completedAt ?? null,
295 latestTurnDurationMs: null,
296 updatedAt: event.occurredAt,
297 }),
298 };
299 }
195 case "git.read-model-upsert": {300 case "git.read-model-upsert": {
196 if (!payload) return nextBase;301 if (!payload) return nextBase;
197 const projectId = asString(payload.projectId) ?? event.aggregateId;302 const projectId = asString(payload.projectId) ?? event.aggregateId;
apps/server/src/providerManager.test.ts+14-1
...@@ -298,12 +298,14 @@ describe("ProviderManager", () => {...@@ -298,12 +298,14 @@ describe("ProviderManager", () => {
298298
299 it("emits checkpoint/captured after turn completion checkpoint capture", async () => {299 it("emits checkpoint/captured after turn completion checkpoint capture", async () => {
300 const manager = new ProviderManager();300 const manager = new ProviderManager();
301 const events: Array<{ method: string; payload?: unknown; threadId?: string }> = [];301 const events: Array<{ method: string; payload?: unknown; threadId?: string; turnId?: string }> =
302 [];
302 manager.on("event", (event) => {303 manager.on("event", (event) => {
303 events.push({304 events.push({
304 method: event.method,305 method: event.method,
305 ...(event.payload !== undefined ? { payload: event.payload } : {}),306 ...(event.payload !== undefined ? { payload: event.payload } : {}),
306 ...(event.threadId ? { threadId: event.threadId } : {}),307 ...(event.threadId ? { threadId: event.threadId } : {}),
308 ...(event.turnId ? { turnId: event.turnId } : {}),
307 });309 });
308 });310 });
309311
...@@ -316,6 +318,8 @@ describe("ProviderManager", () => {...@@ -316,6 +318,8 @@ describe("ProviderManager", () => {
316 createdAt: string;318 createdAt: string;
317 method: string;319 method: string;
318 threadId: string;320 threadId: string;
321 turnId?: string;
322 payload?: unknown;
319 }) => void;323 }) => void;
320 codex: {324 codex: {
321 hasSession: (sessionId: string) => boolean;325 hasSession: (sessionId: string) => boolean;
...@@ -351,6 +355,12 @@ describe("ProviderManager", () => {...@@ -351,6 +355,12 @@ describe("ProviderManager", () => {
351 createdAt: "2026-02-19T00:00:00.000Z",355 createdAt: "2026-02-19T00:00:00.000Z",
352 method: "turn/completed",356 method: "turn/completed",
353 threadId: "thr_1",357 threadId: "thr_1",
358 turnId: "turn_1",
359 payload: {
360 turn: {
361 status: "completed",
362 },
363 },
354 });364 });
355365
356 await vi.waitFor(() => {366 await vi.waitFor(() => {
...@@ -364,9 +374,12 @@ describe("ProviderManager", () => {...@@ -364,9 +374,12 @@ describe("ProviderManager", () => {
364374
365 const checkpointCapturedEvent = events.find((event) => event.method === "checkpoint/captured");375 const checkpointCapturedEvent = events.find((event) => event.method === "checkpoint/captured");
366 expect(checkpointCapturedEvent?.threadId).toBe("thr_1");376 expect(checkpointCapturedEvent?.threadId).toBe("thr_1");
377 expect(checkpointCapturedEvent?.turnId).toBe("turn_1");
367 expect(checkpointCapturedEvent?.payload).toEqual({378 expect(checkpointCapturedEvent?.payload).toEqual({
368 threadId: "thr_1",379 threadId: "thr_1",
369 turnCount: 1,380 turnCount: 1,
381 turnId: "turn_1",
382 status: "completed",
370 });383 });
371384
372 manager.dispose();385 manager.dispose();
apps/server/src/providerManager.ts+31-3
...@@ -130,6 +130,12 @@ function summarizeTurn(turn: CodexThreadTurnSnapshot): {...@@ -130,6 +130,12 @@ function summarizeTurn(turn: CodexThreadTurnSnapshot): {
130 };130 };
131}131}
132132
133function readTurnCompletionStatus(event: ProviderEvent): string | undefined {
134 const payload = asObject(event.payload);
135 const turn = asObject(payload?.turn);
136 return asString(turn?.status);
137}
138
133function buildCheckpoints(turns: CodexThreadTurnSnapshot[]): ProviderCheckpoint[] {139function buildCheckpoints(turns: CodexThreadTurnSnapshot[]): ProviderCheckpoint[] {
134 const checkpoints: ProviderCheckpoint[] = [];140 const checkpoints: ProviderCheckpoint[] = [];
135 let messageCount = 0;141 let messageCount = 0;
...@@ -475,6 +481,7 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -475,6 +481,7 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
475 return;481 return;
476 }482 }
477483
484 const turnStatus = readTurnCompletionStatus(event);
478 const checkpointCwd = this.sessionCheckpointCwds.get(event.sessionId);485 const checkpointCwd = this.sessionCheckpointCwds.get(event.sessionId);
479 if (!checkpointCwd) {486 if (!checkpointCwd) {
480 void this.getOrInitializeFilesystemCheckpointCwd(event.sessionId)487 void this.getOrInitializeFilesystemCheckpointCwd(event.sessionId)
...@@ -483,7 +490,13 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -483,7 +490,13 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
483 return;490 return;
484 }491 }
485 const snapshot = await this.codex.readThread(event.sessionId);492 const snapshot = await this.codex.readThread(event.sessionId);
486 this.emitCheckpointCaptured(event.sessionId, snapshot.threadId, snapshot.turns.length);493 this.emitCheckpointCaptured(
494 event.sessionId,
495 snapshot.threadId,
496 snapshot.turns.length,
497 event.turnId,
498 turnStatus,
499 );
487 })500 })
488 .catch((error) => {501 .catch((error) => {
489 const message =502 const message =
...@@ -504,14 +517,26 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -504,14 +517,26 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
504 threadId: snapshot.threadId,517 threadId: snapshot.threadId,
505 turnCount: snapshot.turns.length,518 turnCount: snapshot.turns.length,
506 });519 });
507 this.emitCheckpointCaptured(event.sessionId, snapshot.threadId, snapshot.turns.length);520 this.emitCheckpointCaptured(
521 event.sessionId,
522 snapshot.threadId,
523 snapshot.turns.length,
524 event.turnId,
525 turnStatus,
526 );
508 }).catch((error) => {527 }).catch((error) => {
509 const message = error instanceof Error ? error.message : "Failed to capture checkpoint.";528 const message = error instanceof Error ? error.message : "Failed to capture checkpoint.";
510 this.emitFilesystemCheckpointError(event.sessionId, message, event.threadId);529 this.emitFilesystemCheckpointError(event.sessionId, message, event.threadId);
511 });530 });
512 }531 }
513532
514 private emitCheckpointCaptured(sessionId: string, threadId: string, turnCount: number): void {533 private emitCheckpointCaptured(
534 sessionId: string,
535 threadId: string,
536 turnCount: number,
537 turnId?: string,
538 status?: string,
539 ): void {
515 this.emit("event", {540 this.emit("event", {
516 id: randomUUID(),541 id: randomUUID(),
517 kind: "notification",542 kind: "notification",
...@@ -520,9 +545,12 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -520,9 +545,12 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
520 createdAt: new Date().toISOString(),545 createdAt: new Date().toISOString(),
521 method: "checkpoint/captured",546 method: "checkpoint/captured",
522 threadId,547 threadId,
548 ...(turnId ? { turnId } : {}),
523 payload: {549 payload: {
524 threadId,550 threadId,
525 turnCount,551 turnCount,
552 ...(turnId ? { turnId } : {}),
553 ...(status ? { status } : {}),
526 },554 },
527 });555 });
528 }556 }
apps/server/src/wsServer.ts+69-1
...@@ -75,6 +75,19 @@ function parseBooleanEnv(value: string | undefined): boolean | undefined {...@@ -75,6 +75,19 @@ function parseBooleanEnv(value: string | undefined): boolean | undefined {
75 return undefined;75 return undefined;
76}76}
7777
78function asObject(value: unknown): Record<string, unknown> | null {
79 if (!value || typeof value !== "object") return null;
80 return value as Record<string, unknown>;
81}
82
83function asString(value: unknown): string | null {
84 return typeof value === "string" ? value : null;
85}
86
87function asNumber(value: unknown): number | null {
88 return typeof value === "number" && Number.isFinite(value) ? value : null;
89}
90
78export function createServer(options: ServerOptions) {91export function createServer(options: ServerOptions) {
79 const {92 const {
80 port,93 port,
...@@ -200,6 +213,26 @@ export function createServer(options: ServerOptions) {...@@ -200,6 +213,26 @@ export function createServer(options: ServerOptions) {
200 createdAt: now,213 createdAt: now,
201 });214 });
202 }215 }
216 if (event.method === "checkpoint/captured") {
217 const payload = asObject(event.payload);
218 const turnId = event.turnId ?? asString(payload?.turnId);
219 if (turnId) {
220 await orchestrationEngine.dispatch({
221 type: "thread.turnDiff.complete",
222 commandId: crypto.randomUUID(),
223 threadId: thread.id,
224 turnId,
225 completedAt: now,
226 ...(asString(payload?.status) !== null ? { status: asString(payload?.status) ?? undefined } : {}),
227 files: [],
228 assistantMessageId: `assistant:${turnId}`,
229 ...(asNumber(payload?.turnCount) !== null
230 ? { checkpointTurnCount: asNumber(payload?.turnCount) ?? undefined }
231 : {}),
232 createdAt: now,
233 });
234 }
235 }
203 if (event.kind === "error" && event.message) {236 if (event.kind === "error" && event.message) {
204 await orchestrationEngine.dispatch({237 await orchestrationEngine.dispatch({
205 type: "thread.session",238 type: "thread.session",
...@@ -425,7 +458,42 @@ export function createServer(options: ServerOptions) {...@@ -425,7 +458,42 @@ export function createServer(options: ServerOptions) {
425 return providerManager.getCheckpointDiff(request.params as never);458 return providerManager.getCheckpointDiff(request.params as never);
426459
427 case WS_METHODS.providersRevertToCheckpoint:460 case WS_METHODS.providersRevertToCheckpoint:
428 return providerManager.revertToCheckpoint(request.params as never);461 {
462 const result = await providerManager.revertToCheckpoint(request.params as never);
463 const params = request.params as { sessionId?: string };
464 const sessionId = params.sessionId;
465 if (typeof sessionId === "string") {
466 const snapshot = orchestrationEngine.getSnapshot();
467 const thread = snapshot.threads.find((entry) => entry.session?.sessionId === sessionId);
468 if (thread) {
469 const now = new Date().toISOString();
470 await orchestrationEngine.dispatch({
471 type: "thread.revert",
472 commandId: crypto.randomUUID(),
473 threadId: thread.id,
474 turnCount: result.turnCount,
475 messageCount: result.messageCount,
476 createdAt: now,
477 });
478 if (thread.session) {
479 await orchestrationEngine.dispatch({
480 type: "thread.session",
481 commandId: crypto.randomUUID(),
482 threadId: thread.id,
483 session: {
484 ...thread.session,
485 status: "ready",
486 activeTurnId: null,
487 updatedAt: now,
488 lastError: null,
489 },
490 createdAt: now,
491 });
492 }
493 }
494 }
495 return result;
496 }
429497
430 case WS_METHODS.projectsList:498 case WS_METHODS.projectsList:
431 return projectRegistry.list();499 return projectRegistry.list();
bun.lock-66
...@@ -34,7 +34,6 @@...@@ -34,7 +34,6 @@
34 "t3": "./dist/index.mjs",34 "t3": "./dist/index.mjs",
35 },35 },
36 "dependencies": {36 "dependencies": {
37 "better-sqlite3": "^12.6.2",
38 "effect": "^3.19.19",37 "effect": "^3.19.19",
39 "node-pty": "^1.1.0",38 "node-pty": "^1.1.0",
40 "open": "^10.1.0",39 "open": "^10.1.0",
...@@ -43,7 +42,6 @@...@@ -43,7 +42,6 @@
43 "devDependencies": {42 "devDependencies": {
44 "@t3tools/contracts": "workspace:*",43 "@t3tools/contracts": "workspace:*",
45 "@t3tools/web": "workspace:*",44 "@t3tools/web": "workspace:*",
46 "@types/better-sqlite3": "^7.6.13",
47 "@types/node": "^22.10.2",45 "@types/node": "^22.10.2",
48 "@types/ws": "^8.5.13",46 "@types/ws": "^8.5.13",
49 "tsdown": "^0.20.3",47 "tsdown": "^0.20.3",
...@@ -498,8 +496,6 @@...@@ -498,8 +496,6 @@
498496
499 "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],497 "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
500498
501 "@types/better-sqlite3": ["@types/better-sqlite3@7.6.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA=="],
502
503 "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="],499 "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="],
504500
505 "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],501 "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
...@@ -588,28 +584,18 @@...@@ -588,28 +584,18 @@
588584
589 "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],585 "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
590586
591 "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
592
593 "baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],587 "baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],
594588
595 "better-sqlite3": ["better-sqlite3@12.6.2", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA=="],
596
597 "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],589 "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
598590
599 "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
600
601 "birpc": ["birpc@4.0.0", "", {}, "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw=="],591 "birpc": ["birpc@4.0.0", "", {}, "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw=="],
602592
603 "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
604
605 "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="],593 "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="],
606594
607 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],595 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
608596
609 "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],597 "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
610598
611 "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
612
613 "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],599 "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
614600
615 "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],601 "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
...@@ -640,8 +626,6 @@...@@ -640,8 +626,6 @@
640626
641 "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],627 "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
642628
643 "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
644
645 "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],629 "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
646630
647 "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],631 "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
...@@ -674,8 +658,6 @@...@@ -674,8 +658,6 @@
674658
675 "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],659 "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
676660
677 "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
678
679 "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],661 "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
680662
681 "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],663 "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
...@@ -748,8 +730,6 @@...@@ -748,8 +730,6 @@
748730
749 "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],731 "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
750732
751 "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
752
753 "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],733 "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
754734
755 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],735 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
...@@ -762,16 +742,12 @@...@@ -762,16 +742,12 @@
762742
763 "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],743 "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
764744
765 "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
766
767 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],745 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
768746
769 "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],747 "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
770748
771 "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],749 "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
772750
773 "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
774
775 "fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],751 "fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
776752
777 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],753 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
...@@ -790,8 +766,6 @@...@@ -790,8 +766,6 @@
790766
791 "get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],767 "get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
792768
793 "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
794
795 "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],769 "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
796770
797 "global-agent": ["global-agent@3.0.0", "", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="],771 "global-agent": ["global-agent@3.0.0", "", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="],
...@@ -840,16 +814,10 @@...@@ -840,16 +814,10 @@
840814
841 "http2-wrapper": ["http2-wrapper@1.0.3", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" } }, "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg=="],815 "http2-wrapper": ["http2-wrapper@1.0.3", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" } }, "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg=="],
842816
843 "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
844
845 "import-from": ["import-from@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ=="],817 "import-from": ["import-from@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ=="],
846818
847 "import-without-cache": ["import-without-cache@0.2.5", "", {}, "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A=="],819 "import-without-cache": ["import-without-cache@0.2.5", "", {}, "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A=="],
848820
849 "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
850
851 "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
852
853 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],821 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
854822
855 "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],823 "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
...@@ -1044,8 +1012,6 @@...@@ -1044,8 +1012,6 @@
10441012
1045 "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],1013 "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
10461014
1047 "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
1048
1049 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],1015 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
10501016
1051 "msw": ["msw@2.12.10", "", { "dependencies": { "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", "graphql": "^16.12.0", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^5.2.0", "until-async": "^3.0.2", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw=="],1017 "msw": ["msw@2.12.10", "", { "dependencies": { "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", "graphql": "^16.12.0", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^5.2.0", "until-async": "^3.0.2", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw=="],
...@@ -1054,10 +1020,6 @@...@@ -1054,10 +1020,6 @@
10541020
1055 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],1021 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
10561022
1057 "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
1058
1059 "node-abi": ["node-abi@3.87.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="],
1060
1061 "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],1023 "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
10621024
1063 "node-pty": ["node-pty@1.1.0", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg=="],1025 "node-pty": ["node-pty@1.1.0", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg=="],
...@@ -1104,8 +1066,6 @@...@@ -1104,8 +1066,6 @@
11041066
1105 "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],1067 "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
11061068
1107 "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
1108
1109 "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],1069 "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
11101070
1111 "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],1071 "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
...@@ -1122,8 +1082,6 @@...@@ -1122,8 +1082,6 @@
11221082
1123 "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],1083 "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],
11241084
1125 "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
1126
1127 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],1085 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
11281086
1129 "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],1087 "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
...@@ -1132,8 +1090,6 @@...@@ -1132,8 +1090,6 @@
11321090
1133 "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],1091 "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
11341092
1135 "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
1136
1137 "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],1093 "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
11381094
1139 "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],1095 "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],
...@@ -1184,8 +1140,6 @@...@@ -1184,8 +1140,6 @@
11841140
1185 "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],1141 "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
11861142
1187 "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
1188
1189 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],1143 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
11901144
1191 "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],1145 "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
...@@ -1204,10 +1158,6 @@...@@ -1204,10 +1158,6 @@
12041158
1205 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],1159 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
12061160
1207 "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
1208
1209 "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
1210
1211 "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],1161 "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
12121162
1213 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],1163 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
...@@ -1226,14 +1176,10 @@...@@ -1226,14 +1176,10 @@
12261176
1227 "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],1177 "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
12281178
1229 "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
1230
1231 "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],1179 "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
12321180
1233 "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],1181 "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
12341182
1235 "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
1236
1237 "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],1183 "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
12381184
1239 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],1185 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
...@@ -1254,10 +1200,6 @@...@@ -1254,10 +1200,6 @@
12541200
1255 "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],1201 "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
12561202
1257 "tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
1258
1259 "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
1260
1261 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],1203 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
12621204
1263 "tiny-warning": ["tiny-warning@1.0.3", "", {}, "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="],1205 "tiny-warning": ["tiny-warning@1.0.3", "", {}, "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="],
...@@ -1292,8 +1234,6 @@...@@ -1292,8 +1234,6 @@
12921234
1293 "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],1235 "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
12941236
1295 "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
1296
1297 "turbo": ["turbo@2.8.7", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.7", "turbo-darwin-arm64": "2.8.7", "turbo-linux-64": "2.8.7", "turbo-linux-arm64": "2.8.7", "turbo-windows-64": "2.8.7", "turbo-windows-arm64": "2.8.7" }, "bin": { "turbo": "bin/turbo" } }, "sha512-RBLh5caMAu1kFdTK1jgH2gH/z+jFsvX5rGbhgJ9nlIAWXSvxlzwId05uDlBA1+pBd3wO/UaKYzaQZQBXDd7kcA=="],1237 "turbo": ["turbo@2.8.7", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.7", "turbo-darwin-arm64": "2.8.7", "turbo-linux-64": "2.8.7", "turbo-linux-arm64": "2.8.7", "turbo-windows-64": "2.8.7", "turbo-windows-arm64": "2.8.7" }, "bin": { "turbo": "bin/turbo" } }, "sha512-RBLh5caMAu1kFdTK1jgH2gH/z+jFsvX5rGbhgJ9nlIAWXSvxlzwId05uDlBA1+pBd3wO/UaKYzaQZQBXDd7kcA=="],
12981238
1299 "turbo-darwin-64": ["turbo-darwin-64@2.8.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-Xr4TO/oDDwoozbDtBvunb66g//WK8uHRygl72vUthuwzmiw48pil4IuoG/QbMHd9RE8aBnVmzC0WZEWk/WWt3A=="],1239 "turbo-darwin-64": ["turbo-darwin-64@2.8.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-Xr4TO/oDDwoozbDtBvunb66g//WK8uHRygl72vUthuwzmiw48pil4IuoG/QbMHd9RE8aBnVmzC0WZEWk/WWt3A=="],
...@@ -1344,8 +1284,6 @@...@@ -1344,8 +1284,6 @@
13441284
1345 "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],1285 "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
13461286
1347 "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
1348
1349 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],1287 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
13501288
1351 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],1289 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
...@@ -1436,8 +1374,6 @@...@@ -1436,8 +1374,6 @@
14361374
1437 "@types/babel__template/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],1375 "@types/babel__template/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
14381376
1439 "@types/better-sqlite3/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
1440
1441 "@vitejs/plugin-react/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],1377 "@vitejs/plugin-react/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
14421378
1443 "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],1379 "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
...@@ -1494,8 +1430,6 @@...@@ -1494,8 +1430,6 @@
14941430
1495 "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],1431 "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
14961432
1497 "@types/better-sqlite3/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
1498
1499 "electron/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],1433 "electron/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
15001434
1501 "rolldown-plugin-dts/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.1", "", {}, "sha512-vi/pfmbrOtQmqgfboaBhaCU50G7mcySVu69VU8z+lYoPPB6WzI9VgV7WQfL908M4oeSH5fDkmoupIqoE0SdApw=="],1435 "rolldown-plugin-dts/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.1", "", {}, "sha512-vi/pfmbrOtQmqgfboaBhaCU50G7mcySVu69VU8z+lYoPPB6WzI9VgV7WQfL908M4oeSH5fDkmoupIqoE0SdApw=="],
packages/contracts/src/orchestration.ts+24
...@@ -189,6 +189,28 @@ export const UpsertGitReadModelCommandSchema = Schema.Struct({...@@ -189,6 +189,28 @@ export const UpsertGitReadModelCommandSchema = Schema.Struct({
189 createdAt: IsoDateTimeSchema,189 createdAt: IsoDateTimeSchema,
190});190});
191191
192export const CompleteThreadTurnDiffCommandSchema = Schema.Struct({
193 type: Schema.Literal("thread.turnDiff.complete"),
194 commandId: IdSchema,
195 threadId: IdSchema,
196 turnId: IdSchema,
197 completedAt: IsoDateTimeSchema,
198 status: Schema.optional(Schema.String),
199 files: Schema.Array(OrchestrationTurnDiffFileSchema),
200 assistantMessageId: Schema.optional(Schema.String),
201 checkpointTurnCount: Schema.optional(Schema.Number),
202 createdAt: IsoDateTimeSchema,
203});
204
205export const RevertThreadCommandSchema = Schema.Struct({
206 type: Schema.Literal("thread.revert"),
207 commandId: IdSchema,
208 threadId: IdSchema,
209 turnCount: Schema.Number,
210 messageCount: Schema.Number,
211 createdAt: IsoDateTimeSchema,
212});
213
192export const OrchestrationCommandSchema = Schema.Union(214export const OrchestrationCommandSchema = Schema.Union(
193 CreateProjectCommandSchema,215 CreateProjectCommandSchema,
194 DeleteProjectCommandSchema,216 DeleteProjectCommandSchema,
...@@ -198,6 +220,8 @@ export const OrchestrationCommandSchema = Schema.Union(...@@ -198,6 +220,8 @@ export const OrchestrationCommandSchema = Schema.Union(
198 SendMessageCommandSchema,220 SendMessageCommandSchema,
199 SetThreadSessionSchema,221 SetThreadSessionSchema,
200 UpsertGitReadModelCommandSchema,222 UpsertGitReadModelCommandSchema,
223 CompleteThreadTurnDiffCommandSchema,
224 RevertThreadCommandSchema,
201);225);
202226
203export type OrchestrationCommand = Schema.Schema.Type<typeof OrchestrationCommandSchema>;227export type OrchestrationCommand = Schema.Schema.Type<typeof OrchestrationCommandSchema>;