authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-26 16:58:27-08:00
committergravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-26 16:58:27-08:00
logdfe06261c459e9171d4fe4807bd1030fa3636b9f
tree51796be8045eb41254549fba18bb7b332c4fde59
parent29a632cb521e199874dd0d2cd4ecca2b1c6f6c0b

fmt


17 files changed, 350 insertions(+), 316 deletions(-)

.oxlintrc.json+3-1
......@@ -15,6 +15,8 @@
1515 "perf": "warn"
1616 },
1717 "rules": {
18 "react-in-jsx-scope": "off"
18 "react-in-jsx-scope": "off",
19 "eslint/no-shadow": "off",
20 "eslint/no-await-in-loop": "off"
1921 }
2022}
apps/server/src/git/Layers/GitManager.ts+43-40
......@@ -29,10 +29,7 @@ function limitContext(value: string, maxChars: number): string {
2929 return `${value.slice(0, maxChars)}\n\n[truncated]`;
3030}
3131
32function sanitizeCommitMessage(generated: {
33 subject: string;
34 body: string;
35}): {
32function sanitizeCommitMessage(generated: { subject: string; body: string }): {
3633 subject: string;
3734 body: string;
3835} {
......@@ -161,12 +158,14 @@ export const makeGitManager = Effect.gen(function* () {
161158
162159 let generated = parseCustomCommitMessage(commitMessage ?? "");
163160 if (!generated) {
164 generated = yield* textGeneration.generateCommitMessage({
165 cwd,
166 branch,
167 stagedSummary: limitContext(context.stagedSummary, 8_000),
168 stagedPatch: limitContext(context.stagedPatch, 50_000),
169 }).pipe(Effect.map((result) => sanitizeCommitMessage(result)));
161 generated = yield* textGeneration
162 .generateCommitMessage({
163 cwd,
164 branch,
165 stagedSummary: limitContext(context.stagedSummary, 8_000),
166 stagedPatch: limitContext(context.stagedPatch, 50_000),
167 })
168 .pipe(Effect.map((result) => sanitizeCommitMessage(result)));
170169 }
171170
172171 const { commitSha } = yield* gitCore.commit(cwd, generated.subject, generated.body);
......@@ -182,7 +181,10 @@ export const makeGitManager = Effect.gen(function* () {
182181 const details = yield* gitCore.statusDetails(cwd);
183182 const branch = details.branch ?? fallbackBranch;
184183 if (!branch) {
185 return yield* gitManagerError("runPrStep", "Cannot create a pull request from detached HEAD.");
184 return yield* gitManagerError(
185 "runPrStep",
186 "Cannot create a pull request from detached HEAD.",
187 );
186188 }
187189 if (!details.hasUpstream) {
188190 return yield* gitManagerError(
......@@ -220,11 +222,7 @@ export const makeGitManager = Effect.gen(function* () {
220222 .writeFileString(bodyFile, generated.body)
221223 .pipe(
222224 Effect.mapError((cause) =>
223 gitManagerError(
224 "runPrStep",
225 "Failed to write pull request body temp file.",
226 cause,
227 ),
225 gitManagerError("runPrStep", "Failed to write pull request body temp file.", cause),
228226 ),
229227 );
230228 yield* gitHubCli
......@@ -279,35 +277,40 @@ export const makeGitManager = Effect.gen(function* () {
279277 };
280278 });
281279
282 const runStackedAction: GitManagerShape["runStackedAction"] = Effect.fnUntraced(function* (input) {
283 const wantsPush = input.action !== "commit";
284 const wantsPr = input.action === "commit_push_pr";
280 const runStackedAction: GitManagerShape["runStackedAction"] = Effect.fnUntraced(
281 function* (input) {
282 const wantsPush = input.action !== "commit";
283 const wantsPr = input.action === "commit_push_pr";
285284
286 const initialStatus = yield* gitCore.statusDetails(input.cwd);
287 if (wantsPush && !initialStatus.branch) {
288 return yield* gitManagerError("runStackedAction", "Cannot push from detached HEAD.");
289 }
290 if (wantsPr && !initialStatus.branch) {
291 return yield* gitManagerError("runStackedAction", "Cannot create a pull request from detached HEAD.");
292 }
285 const initialStatus = yield* gitCore.statusDetails(input.cwd);
286 if (wantsPush && !initialStatus.branch) {
287 return yield* gitManagerError("runStackedAction", "Cannot push from detached HEAD.");
288 }
289 if (wantsPr && !initialStatus.branch) {
290 return yield* gitManagerError(
291 "runStackedAction",
292 "Cannot create a pull request from detached HEAD.",
293 );
294 }
293295
294 const commit = yield* runCommitStep(input.cwd, initialStatus.branch, input.commitMessage);
296 const commit = yield* runCommitStep(input.cwd, initialStatus.branch, input.commitMessage);
295297
296 const push = wantsPush
297 ? yield* gitCore.pushCurrentBranch(input.cwd, initialStatus.branch)
298 : { status: "skipped_not_requested" as const };
298 const push = wantsPush
299 ? yield* gitCore.pushCurrentBranch(input.cwd, initialStatus.branch)
300 : { status: "skipped_not_requested" as const };
299301
300 const pr = wantsPr
301 ? yield* runPrStep(input.cwd, initialStatus.branch)
302 : { status: "skipped_not_requested" as const };
302 const pr = wantsPr
303 ? yield* runPrStep(input.cwd, initialStatus.branch)
304 : { status: "skipped_not_requested" as const };
303305
304 return {
305 action: input.action,
306 commit,
307 push,
308 pr,
309 };
310 });
306 return {
307 action: input.action,
308 commit,
309 push,
310 pr,
311 };
312 },
313 );
311314
312315 return {
313316 status,
apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts+3-1
......@@ -561,7 +561,9 @@ describe("OrchestrationEngine", () => {
561561 ).rejects.toThrow("projection failed");
562562
563563 const readModelAfterFailure = await runtime.runPromise(engine.getReadModel());
564 const updatedThread = readModelAfterFailure.threads.find((thread) => thread.id === "thread-sync");
564 const updatedThread = readModelAfterFailure.threads.find(
565 (thread) => thread.id === "thread-sync",
566 );
565567 expect(readModelAfterFailure.snapshotSequence).toBe(3);
566568 expect(updatedThread?.title).toBe("sync-after-failed-projection");
567569
apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts+125-124
......@@ -412,125 +412,127 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => {
412412 }),
413413 );
414414
415 it.effect("resolves turn-count conflicts when checkpoint completion rewrites provisional turns", () =>
416 Effect.gen(function* () {
417 const projectionPipeline = yield* OrchestrationProjectionPipeline;
418 const eventStore = yield* OrchestrationEventStore;
419 const sql = yield* SqlClient.SqlClient;
420 const appendAndProject = (event: Parameters<typeof eventStore.append>[0]) =>
421 eventStore
422 .append(event)
423 .pipe(Effect.flatMap((savedEvent) => projectionPipeline.projectEvent(savedEvent)));
424
425 yield* appendAndProject({
426 type: "project.created",
427 eventId: EventId.makeUnsafe("evt-conflict-1"),
428 aggregateKind: "project",
429 aggregateId: ProjectId.makeUnsafe("project-conflict"),
430 occurredAt: "2026-02-26T13:00:00.000Z",
431 commandId: CommandId.makeUnsafe("cmd-conflict-1"),
432 causationEventId: null,
433 correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"),
434 metadata: {},
435 payload: {
436 projectId: ProjectId.makeUnsafe("project-conflict"),
437 title: "Project Conflict",
438 workspaceRoot: "/tmp/project-conflict",
439 defaultModel: null,
440 scripts: [],
441 createdAt: "2026-02-26T13:00:00.000Z",
442 updatedAt: "2026-02-26T13:00:00.000Z",
443 },
444 });
445
446 yield* appendAndProject({
447 type: "thread.created",
448 eventId: EventId.makeUnsafe("evt-conflict-2"),
449 aggregateKind: "thread",
450 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
451 occurredAt: "2026-02-26T13:00:01.000Z",
452 commandId: CommandId.makeUnsafe("cmd-conflict-2"),
453 causationEventId: null,
454 correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"),
455 metadata: {},
456 payload: {
457 threadId: ThreadId.makeUnsafe("thread-conflict"),
458 projectId: ProjectId.makeUnsafe("project-conflict"),
459 title: "Thread Conflict",
460 model: "gpt-5-codex",
461 branch: null,
462 worktreePath: null,
463 createdAt: "2026-02-26T13:00:01.000Z",
464 updatedAt: "2026-02-26T13:00:01.000Z",
465 },
466 });
467
468 yield* appendAndProject({
469 type: "thread.turn-interrupt-requested",
470 eventId: EventId.makeUnsafe("evt-conflict-3"),
471 aggregateKind: "thread",
472 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
473 occurredAt: "2026-02-26T13:00:02.000Z",
474 commandId: CommandId.makeUnsafe("cmd-conflict-3"),
475 causationEventId: null,
476 correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"),
477 metadata: {},
478 payload: {
479 threadId: ThreadId.makeUnsafe("thread-conflict"),
480 turnId: TurnId.makeUnsafe("turn-interrupted"),
481 createdAt: "2026-02-26T13:00:02.000Z",
482 },
483 });
484
485 yield* appendAndProject({
486 type: "thread.message-sent",
487 eventId: EventId.makeUnsafe("evt-conflict-4"),
488 aggregateKind: "thread",
489 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
490 occurredAt: "2026-02-26T13:00:03.000Z",
491 commandId: CommandId.makeUnsafe("cmd-conflict-4"),
492 causationEventId: null,
493 correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"),
494 metadata: {},
495 payload: {
496 threadId: ThreadId.makeUnsafe("thread-conflict"),
497 messageId: MessageId.makeUnsafe("assistant-conflict"),
498 role: "assistant",
499 text: "done",
500 turnId: TurnId.makeUnsafe("turn-completed"),
501 streaming: false,
502 createdAt: "2026-02-26T13:00:03.000Z",
503 updatedAt: "2026-02-26T13:00:03.000Z",
504 },
505 });
506
507 yield* appendAndProject({
508 type: "thread.turn-diff-completed",
509 eventId: EventId.makeUnsafe("evt-conflict-5"),
510 aggregateKind: "thread",
511 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
512 occurredAt: "2026-02-26T13:00:04.000Z",
513 commandId: CommandId.makeUnsafe("cmd-conflict-5"),
514 causationEventId: null,
515 correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"),
516 metadata: {},
517 payload: {
518 threadId: ThreadId.makeUnsafe("thread-conflict"),
519 turnId: TurnId.makeUnsafe("turn-completed"),
520 checkpointTurnCount: 1,
521 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"),
522 status: "ready",
523 files: [],
524 assistantMessageId: MessageId.makeUnsafe("assistant-conflict"),
525 completedAt: "2026-02-26T13:00:04.000Z",
526 },
527 });
415 it.effect(
416 "resolves turn-count conflicts when checkpoint completion rewrites provisional turns",
417 () =>
418 Effect.gen(function* () {
419 const projectionPipeline = yield* OrchestrationProjectionPipeline;
420 const eventStore = yield* OrchestrationEventStore;
421 const sql = yield* SqlClient.SqlClient;
422 const appendAndProject = (event: Parameters<typeof eventStore.append>[0]) =>
423 eventStore
424 .append(event)
425 .pipe(Effect.flatMap((savedEvent) => projectionPipeline.projectEvent(savedEvent)));
426
427 yield* appendAndProject({
428 type: "project.created",
429 eventId: EventId.makeUnsafe("evt-conflict-1"),
430 aggregateKind: "project",
431 aggregateId: ProjectId.makeUnsafe("project-conflict"),
432 occurredAt: "2026-02-26T13:00:00.000Z",
433 commandId: CommandId.makeUnsafe("cmd-conflict-1"),
434 causationEventId: null,
435 correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"),
436 metadata: {},
437 payload: {
438 projectId: ProjectId.makeUnsafe("project-conflict"),
439 title: "Project Conflict",
440 workspaceRoot: "/tmp/project-conflict",
441 defaultModel: null,
442 scripts: [],
443 createdAt: "2026-02-26T13:00:00.000Z",
444 updatedAt: "2026-02-26T13:00:00.000Z",
445 },
446 });
447
448 yield* appendAndProject({
449 type: "thread.created",
450 eventId: EventId.makeUnsafe("evt-conflict-2"),
451 aggregateKind: "thread",
452 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
453 occurredAt: "2026-02-26T13:00:01.000Z",
454 commandId: CommandId.makeUnsafe("cmd-conflict-2"),
455 causationEventId: null,
456 correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"),
457 metadata: {},
458 payload: {
459 threadId: ThreadId.makeUnsafe("thread-conflict"),
460 projectId: ProjectId.makeUnsafe("project-conflict"),
461 title: "Thread Conflict",
462 model: "gpt-5-codex",
463 branch: null,
464 worktreePath: null,
465 createdAt: "2026-02-26T13:00:01.000Z",
466 updatedAt: "2026-02-26T13:00:01.000Z",
467 },
468 });
469
470 yield* appendAndProject({
471 type: "thread.turn-interrupt-requested",
472 eventId: EventId.makeUnsafe("evt-conflict-3"),
473 aggregateKind: "thread",
474 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
475 occurredAt: "2026-02-26T13:00:02.000Z",
476 commandId: CommandId.makeUnsafe("cmd-conflict-3"),
477 causationEventId: null,
478 correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"),
479 metadata: {},
480 payload: {
481 threadId: ThreadId.makeUnsafe("thread-conflict"),
482 turnId: TurnId.makeUnsafe("turn-interrupted"),
483 createdAt: "2026-02-26T13:00:02.000Z",
484 },
485 });
486
487 yield* appendAndProject({
488 type: "thread.message-sent",
489 eventId: EventId.makeUnsafe("evt-conflict-4"),
490 aggregateKind: "thread",
491 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
492 occurredAt: "2026-02-26T13:00:03.000Z",
493 commandId: CommandId.makeUnsafe("cmd-conflict-4"),
494 causationEventId: null,
495 correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"),
496 metadata: {},
497 payload: {
498 threadId: ThreadId.makeUnsafe("thread-conflict"),
499 messageId: MessageId.makeUnsafe("assistant-conflict"),
500 role: "assistant",
501 text: "done",
502 turnId: TurnId.makeUnsafe("turn-completed"),
503 streaming: false,
504 createdAt: "2026-02-26T13:00:03.000Z",
505 updatedAt: "2026-02-26T13:00:03.000Z",
506 },
507 });
508
509 yield* appendAndProject({
510 type: "thread.turn-diff-completed",
511 eventId: EventId.makeUnsafe("evt-conflict-5"),
512 aggregateKind: "thread",
513 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
514 occurredAt: "2026-02-26T13:00:04.000Z",
515 commandId: CommandId.makeUnsafe("cmd-conflict-5"),
516 causationEventId: null,
517 correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"),
518 metadata: {},
519 payload: {
520 threadId: ThreadId.makeUnsafe("thread-conflict"),
521 turnId: TurnId.makeUnsafe("turn-completed"),
522 checkpointTurnCount: 1,
523 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"),
524 status: "ready",
525 files: [],
526 assistantMessageId: MessageId.makeUnsafe("assistant-conflict"),
527 completedAt: "2026-02-26T13:00:04.000Z",
528 },
529 });
528530
529 const turnRows = yield* sql<{
530 readonly turnId: string;
531 readonly checkpointTurnCount: number | null;
532 readonly status: string;
533 }>`
531 const turnRows = yield* sql<{
532 readonly turnId: string;
533 readonly checkpointTurnCount: number | null;
534 readonly status: string;
535 }>`
534536 SELECT
535537 turn_id AS "turnId",
536538 checkpoint_turn_count AS "checkpointTurnCount",
......@@ -545,11 +547,11 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => {
545547 checkpoint_turn_count ASC,
546548 requested_at ASC
547549 `;
548 assert.deepEqual(turnRows, [
549 { turnId: "turn-completed", checkpointTurnCount: 1, status: "completed" },
550 { turnId: "turn-interrupted", checkpointTurnCount: null, status: "interrupted" },
551 ]);
552 }),
550 assert.deepEqual(turnRows, [
551 { turnId: "turn-completed", checkpointTurnCount: 1, status: "completed" },
552 { turnId: "turn-interrupted", checkpointTurnCount: null, status: "interrupted" },
553 ]);
554 }),
553555 );
554556
555557 it.effect("does not fallback-retain messages whose turnId is removed by revert", () =>
......@@ -753,7 +755,6 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => {
753755 ]);
754756 }),
755757 );
756
757758});
758759
759760it.effect("restores pending turn-start metadata across projection pipeline restart", () =>
apps/server/src/orchestration/Layers/ProjectionPipeline.ts+17-5
......@@ -14,7 +14,10 @@ import {
1414 ProjectionThreadMessageRepository,
1515} from "../../persistence/Services/ProjectionThreadMessages.ts";
1616import { ProjectionThreadSessionRepository } from "../../persistence/Services/ProjectionThreadSessions.ts";
17import { type ProjectionTurn, ProjectionTurnRepository } from "../../persistence/Services/ProjectionTurns.ts";
17import {
18 type ProjectionTurn,
19 ProjectionTurnRepository,
20} from "../../persistence/Services/ProjectionTurns.ts";
1821import { ProjectionThreadRepository } from "../../persistence/Services/ProjectionThreads.ts";
1922import { ProjectionPendingApprovalRepositoryLive } from "../../persistence/Layers/ProjectionPendingApprovals.ts";
2023import { ProjectionProjectRepositoryLive } from "../../persistence/Layers/ProjectionProjects.ts";
......@@ -64,7 +67,10 @@ function retainProjectionMessagesAfterRevert(
6467 const retainedMessageIds = new Set<string>();
6568 const retainedTurnIds = new Set<string>();
6669 const keptTurns = turns.filter(
67 (turn) => turn.turnId !== null && turn.checkpointTurnCount !== null && turn.checkpointTurnCount <= turnCount,
70 (turn) =>
71 turn.turnId !== null &&
72 turn.checkpointTurnCount !== null &&
73 turn.checkpointTurnCount <= turnCount,
6874 );
6975 for (const turn of keptTurns) {
7076 if (turn.turnId !== null) {
......@@ -511,16 +517,22 @@ const makeOrchestrationProjectionPipeline = Effect.gen(function* () {
511517 (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.messageId : null),
512518 startedAt:
513519 existingTurn.value.startedAt ??
514 (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.requestedAt : event.occurredAt),
520 (Option.isSome(pendingTurnStart)
521 ? pendingTurnStart.value.requestedAt
522 : event.occurredAt),
515523 requestedAt:
516524 existingTurn.value.requestedAt ??
517 (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.requestedAt : event.occurredAt),
525 (Option.isSome(pendingTurnStart)
526 ? pendingTurnStart.value.requestedAt
527 : event.occurredAt),
518528 });
519529 } else {
520530 yield* projectionTurnRepository.upsertByTurnId({
521531 turnId,
522532 threadId: event.payload.threadId,
523 pendingMessageId: Option.isSome(pendingTurnStart) ? pendingTurnStart.value.messageId : null,
533 pendingMessageId: Option.isSome(pendingTurnStart)
534 ? pendingTurnStart.value.messageId
535 : null,
524536 assistantMessageId: null,
525537 state: "running",
526538 requestedAt: Option.isSome(pendingTurnStart)
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+5-8
......@@ -149,14 +149,11 @@ const make = Effect.gen(function* () {
149149 projects: readModel.projects,
150150 });
151151
152 const startedSession = yield* providerService.startSession(
153 threadId,
154 {
155 ...(preferredProvider ? { provider: preferredProvider } : {}),
156 ...(effectiveCwd ? { cwd: effectiveCwd } : {}),
157 ...(thread.model ? { model: thread.model } : {}),
158 },
159 );
152 const startedSession = yield* providerService.startSession(threadId, {
153 ...(preferredProvider ? { provider: preferredProvider } : {}),
154 ...(effectiveCwd ? { cwd: effectiveCwd } : {}),
155 ...(thread.model ? { model: thread.model } : {}),
156 });
160157
161158 yield* setThreadSession({
162159 threadId,
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts+7-3
......@@ -274,7 +274,8 @@ describe("ProviderRuntimeIngestion", () => {
274274 await waitForThread(
275275 harness.engine,
276276 (thread) =>
277 thread.session?.status === "running" && thread.session?.activeTurnId === "turn-complete-dedup",
277 thread.session?.status === "running" &&
278 thread.session?.activeTurnId === "turn-complete-dedup",
278279 );
279280
280281 harness.emit({
......@@ -317,14 +318,17 @@ describe("ProviderRuntimeIngestion", () => {
317318 );
318319
319320 const events = await Effect.runPromise(
320 Stream.runCollect(harness.engine.readEvents(0)).pipe(Effect.map((chunk) => Array.from(chunk))),
321 Stream.runCollect(harness.engine.readEvents(0)).pipe(
322 Effect.map((chunk) => Array.from(chunk)),
323 ),
321324 );
322325 const completionEvents = events.filter((event) => {
323326 if (event.type !== "thread.message-sent") {
324327 return false;
325328 }
326329 return (
327 event.payload.messageId === "assistant:item-complete-dedup" && event.payload.streaming === false
330 event.payload.messageId === "assistant:item-complete-dedup" &&
331 event.payload.streaming === false
328332 );
329333 });
330334 expect(completionEvents).toHaveLength(1);
apps/server/src/orchestration/projector.test.ts+6-2
......@@ -702,7 +702,9 @@ describe("orchestration projector", () => {
702702 },
703703 }),
704704 );
705 const afterMessages = await messageEvents.reduce<Promise<ReturnType<typeof createEmptyReadModel>>>(
705 const afterMessages = await messageEvents.reduce<
706 Promise<ReturnType<typeof createEmptyReadModel>>
707 >(
706708 (statePromise, event) =>
707709 statePromise.then((state) => Effect.runPromise(projectEvent(state, event))),
708710 Promise.resolve(afterCreate),
......@@ -730,7 +732,9 @@ describe("orchestration projector", () => {
730732 },
731733 }),
732734 );
733 const finalState = await checkpointEvents.reduce<Promise<ReturnType<typeof createEmptyReadModel>>>(
735 const finalState = await checkpointEvents.reduce<
736 Promise<ReturnType<typeof createEmptyReadModel>>
737 >(
734738 (statePromise, event) =>
735739 statePromise.then((state) => Effect.runPromise(projectEvent(state, event))),
736740 Promise.resolve(afterMessages),
apps/server/src/persistence/Layers/ProjectionTurns.ts+21-22
......@@ -260,23 +260,21 @@ const makeProjectionTurnRepository = Effect.gen(function* () {
260260 ),
261261 );
262262
263 const getPendingTurnStartByThreadId: ProjectionTurnRepositoryShape["getPendingTurnStartByThreadId"] = (
264 input,
265 ) =>
266 getPendingProjectionTurn(input).pipe(
267 Effect.mapError(
268 toPersistenceSqlError("ProjectionTurnRepository.getPendingTurnStartByThreadId:query"),
269 ),
270 );
263 const getPendingTurnStartByThreadId: ProjectionTurnRepositoryShape["getPendingTurnStartByThreadId"] =
264 (input) =>
265 getPendingProjectionTurn(input).pipe(
266 Effect.mapError(
267 toPersistenceSqlError("ProjectionTurnRepository.getPendingTurnStartByThreadId:query"),
268 ),
269 );
271270
272 const deletePendingTurnStartByThreadId: ProjectionTurnRepositoryShape["deletePendingTurnStartByThreadId"] = (
273 input,
274 ) =>
275 clearPendingProjectionTurnsByThread(input).pipe(
276 Effect.mapError(
277 toPersistenceSqlError("ProjectionTurnRepository.deletePendingTurnStartByThreadId:query"),
278 ),
279 );
271 const deletePendingTurnStartByThreadId: ProjectionTurnRepositoryShape["deletePendingTurnStartByThreadId"] =
272 (input) =>
273 clearPendingProjectionTurnsByThread(input).pipe(
274 Effect.mapError(
275 toPersistenceSqlError("ProjectionTurnRepository.deletePendingTurnStartByThreadId:query"),
276 ),
277 );
280278
281279 const listByThreadId: ProjectionTurnRepositoryShape["listByThreadId"] = (input) =>
282280 listProjectionTurnsByThread(input).pipe(
......@@ -306,12 +304,13 @@ const makeProjectionTurnRepository = Effect.gen(function* () {
306304 ),
307305 );
308306
309 const clearCheckpointTurnConflict: ProjectionTurnRepositoryShape["clearCheckpointTurnConflict"] = (
310 input,
311 ) =>
312 clearCheckpointTurnConflictRow(input).pipe(
313 Effect.mapError(toPersistenceSqlError("ProjectionTurnRepository.clearCheckpointTurnConflict:query")),
314 );
307 const clearCheckpointTurnConflict: ProjectionTurnRepositoryShape["clearCheckpointTurnConflict"] =
308 (input) =>
309 clearCheckpointTurnConflictRow(input).pipe(
310 Effect.mapError(
311 toPersistenceSqlError("ProjectionTurnRepository.clearCheckpointTurnConflict:query"),
312 ),
313 );
315314
316315 const deleteByThreadId: ProjectionTurnRepositoryShape["deleteByThreadId"] = (input) =>
317316 deleteProjectionTurnsByThread(input).pipe(
apps/server/src/provider/Layers/ProviderService.test.ts+34-64
......@@ -323,13 +323,10 @@ it.effect(
323323
324324 const startedSession = yield* Effect.gen(function* () {
325325 const provider = yield* ProviderService;
326 return yield* provider.startSession(
327 asThreadId("thread-1"),
328 {
329 provider: "codex",
330 cwd: "/tmp/project",
331 },
332 );
326 return yield* provider.startSession(asThreadId("thread-1"), {
327 provider: "codex",
328 cwd: "/tmp/project",
329 });
333330 }).pipe(Effect.provide(firstProviderLayer));
334331
335332 yield* Effect.gen(function* () {
......@@ -398,13 +395,10 @@ routing.layer("ProviderServiceLive routing", (it) => {
398395 Effect.gen(function* () {
399396 const provider = yield* ProviderService;
400397
401 const session = yield* provider.startSession(
402 asThreadId("thread-1"),
403 {
404 provider: "codex",
405 cwd: "/tmp/project",
406 },
407 );
398 const session = yield* provider.startSession(asThreadId("thread-1"), {
399 provider: "codex",
400 cwd: "/tmp/project",
401 });
408402 assert.equal(session.provider, "codex");
409403
410404 const sessions = yield* provider.listSessions();
......@@ -453,13 +447,10 @@ routing.layer("ProviderServiceLive routing", (it) => {
453447 Effect.gen(function* () {
454448 const provider = yield* ProviderService;
455449
456 const initial = yield* provider.startSession(
457 asThreadId("thread-1"),
458 {
459 provider: "codex",
460 cwd: "/tmp/project",
461 },
462 );
450 const initial = yield* provider.startSession(asThreadId("thread-1"), {
451 provider: "codex",
452 cwd: "/tmp/project",
453 });
463454 yield* routing.codex.stopSession(initial.sessionId);
464455 routing.codex.startSession.mockClear();
465456 routing.codex.rollbackThread.mockClear();
......@@ -487,18 +478,12 @@ routing.layer("ProviderServiceLive routing", (it) => {
487478 Effect.gen(function* () {
488479 const provider = yield* ProviderService;
489480
490 yield* provider.startSession(
491 asThreadId("thread-1"),
492 {
493 provider: "codex",
494 },
495 );
496 yield* provider.startSession(
497 asThreadId("thread-2"),
498 {
499 provider: "codex",
500 },
501 );
481 yield* provider.startSession(asThreadId("thread-1"), {
482 provider: "codex",
483 });
484 yield* provider.startSession(asThreadId("thread-2"), {
485 provider: "codex",
486 });
502487
503488 yield* provider.stopAll();
504489
......@@ -512,12 +497,9 @@ routing.layer("ProviderServiceLive routing", (it) => {
512497 const provider = yield* ProviderService;
513498 const runtimeRepository = yield* ProviderSessionRuntimeRepository;
514499
515 const session = yield* provider.startSession(
516 asThreadId("thread-1"),
517 {
518 provider: "codex",
519 },
520 );
500 const session = yield* provider.startSession(asThreadId("thread-1"), {
501 provider: "codex",
502 });
521503 yield* provider.sendTurn({
522504 sessionId: session.sessionId,
523505 input: "hello",
......@@ -566,12 +548,9 @@ fanout.layer("ProviderServiceLive fanout", (it) => {
566548 it.effect("fans out adapter turn completion events", () =>
567549 Effect.gen(function* () {
568550 const provider = yield* ProviderService;
569 const session = yield* provider.startSession(
570 asThreadId("thread-1"),
571 {
572 provider: "codex",
573 },
574 );
551 const session = yield* provider.startSession(asThreadId("thread-1"), {
552 provider: "codex",
553 });
575554
576555 const eventsRef = yield* Ref.make<Array<ProviderRuntimeEvent>>([]);
577556 const consumer = yield* Stream.runForEach(provider.streamEvents, (event) =>
......@@ -606,12 +585,9 @@ fanout.layer("ProviderServiceLive fanout", (it) => {
606585 it.effect("keeps subscriber delivery ordered and isolates failing subscribers", () =>
607586 Effect.gen(function* () {
608587 const provider = yield* ProviderService;
609 const session = yield* provider.startSession(
610 asThreadId("thread-1"),
611 {
612 provider: "codex",
613 },
614 );
588 const session = yield* provider.startSession(asThreadId("thread-1"), {
589 provider: "codex",
590 });
615591
616592 const receivedByHealthy: string[] = [];
617593 const expectedEventIds = new Set<string>(["evt-ordered-1", "evt-ordered-2", "evt-ordered-3"]);
......@@ -686,12 +662,9 @@ validation.layer("ProviderServiceLive validation", (it) => {
686662 const provider = yield* ProviderService;
687663
688664 const failure = yield* Effect.result(
689 provider.startSession(
690 asThreadId("thread-validation"),
691 {
692 provider: "invalid-provider",
693 } as never,
694 ),
665 provider.startSession(asThreadId("thread-validation"), {
666 provider: "invalid-provider",
667 } as never),
695668 );
696669
697670 assert.equal(failure._tag, "Failure");
......@@ -726,13 +699,10 @@ validation.layer("ProviderServiceLive validation", (it) => {
726699 );
727700
728701 const failure = yield* Effect.result(
729 provider.startSession(
730 asThreadId("thread-missing"),
731 {
732 provider: "codex",
733 cwd: "/tmp/project",
734 },
735 ),
702 provider.startSession(asThreadId("thread-missing"), {
703 provider: "codex",
704 cwd: "/tmp/project",
705 }),
736706 );
737707
738708 assertFailure(
apps/server/src/terminal/Layers/Manager.ts+5-1
......@@ -415,7 +415,11 @@ export class TerminalManagerRuntime extends EventEmitter<TerminalManagerEvents>
415415 }
416416
417417 if (!existing.process) {
418 await this.startSession(existing, { ...input, cols: targetCols, rows: targetRows }, "started");
418 await this.startSession(
419 existing,
420 { ...input, cols: targetCols, rows: targetRows },
421 "started",
422 );
419423 return this.snapshot(existing);
420424 }
421425
apps/server/src/wsServer.test.ts+9-3
......@@ -543,7 +543,9 @@ describe("WebSocket Server", () => {
543543 issues: [],
544544 });
545545
546 const persistedConfig = JSON.parse(fs.readFileSync(keybindingsPath, "utf8")) as KeybindingsConfig;
546 const persistedConfig = JSON.parse(
547 fs.readFileSync(keybindingsPath, "utf8"),
548 ) as KeybindingsConfig;
547549 expect(persistedConfig).toEqual(DEFAULT_KEYBINDINGS);
548550 });
549551
......@@ -711,7 +713,9 @@ describe("WebSocket Server", () => {
711713
712714 const response = await sendRequest(ws, WS_METHODS.serverGetConfig);
713715 expect(response.error).toBeUndefined();
714 const persistedConfig = JSON.parse(fs.readFileSync(keybindingsPath, "utf8")) as KeybindingsConfig;
716 const persistedConfig = JSON.parse(
717 fs.readFileSync(keybindingsPath, "utf8"),
718 ) as KeybindingsConfig;
715719 expect(response.result).toEqual({
716720 cwd: "/my/workspace",
717721 keybindingsConfigPath: keybindingsPath,
......@@ -742,7 +746,9 @@ describe("WebSocket Server", () => {
742746 command: "script.run-tests.run",
743747 });
744748 expect(upsertResponse.error).toBeUndefined();
745 const persistedConfig = JSON.parse(fs.readFileSync(keybindingsPath, "utf8")) as KeybindingsConfig;
749 const persistedConfig = JSON.parse(
750 fs.readFileSync(keybindingsPath, "utf8"),
751 ) as KeybindingsConfig;
746752 const persistedCommands = new Set(persistedConfig.map((entry) => entry.command));
747753 for (const defaultRule of DEFAULT_KEYBINDINGS) {
748754 expect(persistedCommands.has(defaultRule.command)).toBe(true);
apps/web/src/components/ProjectScriptsControl.tsx+14-3
......@@ -16,8 +16,15 @@ import {
1616} from "lucide-react";
1717import React, { type FormEvent, type KeyboardEvent, useMemo, useState } from "react";
1818
19import { keybindingValueForCommand, decodeProjectScriptKeybindingRule } from "~/lib/projectScriptKeybindings";
20import { commandForProjectScript, nextProjectScriptId, primaryProjectScript } from "~/projectScripts";
19import {
20 keybindingValueForCommand,
21 decodeProjectScriptKeybindingRule,
22} from "~/lib/projectScriptKeybindings";
23import {
24 commandForProjectScript,
25 nextProjectScriptId,
26 primaryProjectScript,
27} from "~/projectScripts";
2128import { shortcutLabelForCommand } from "~/keybindings";
2229import { isMacPlatform } from "~/lib/utils";
2330import { Button } from "./ui/button";
......@@ -188,7 +195,11 @@ export default function ProjectScriptsControl({
188195 setValidationError(null);
189196 try {
190197 const scriptIdForValidation =
191 editingScriptId ?? nextProjectScriptId(trimmedName, scripts.map((script) => script.id));
198 editingScriptId ??
199 nextProjectScriptId(
200 trimmedName,
201 scripts.map((script) => script.id),
202 );
192203 const keybindingRule = decodeProjectScriptKeybindingRule({
193204 keybinding,
194205 command: commandForProjectScript(scriptIdForValidation),
apps/web/src/routes/__root.tsx+1-4
......@@ -201,10 +201,7 @@ function EventRouter() {
201201 void queryClient
202202 .ensureQueryData(serverConfigQueryOptions())
203203 .then((config) =>
204 api.shell.openInEditor(
205 config.keybindingsConfigPath,
206 preferredTerminalEditor(),
207 ),
204 api.shell.openInEditor(config.keybindingsConfigPath, preferredTerminalEditor()),
208205 )
209206 .catch((error) => {
210207 toastManager.add({
apps/web/src/routes/_chat.settings.tsx+2-2
......@@ -241,8 +241,8 @@ function SettingsRouteView() {
241241 <div className="mb-4">
242242 <h2 className="text-sm font-medium text-foreground">Keybindings</h2>
243243 <p className="mt-1 text-xs text-muted-foreground">
244 Open the persisted <code>keybindings.json</code> file to edit advanced
245 bindings directly.
244 Open the persisted <code>keybindings.json</code> file to edit advanced bindings
245 directly.
246246 </p>
247247 </div>
248248
bun.lock+53-31
......@@ -5,8 +5,8 @@
55 "": {
66 "name": "@t3tools/monorepo",
77 "devDependencies": {
8 "oxfmt": "^0.28.0",
9 "oxlint": "^1.43.0",
8 "oxfmt": "^0.35.0",
9 "oxlint": "^1.50.0",
1010 "turbo": "^2.3.3",
1111 "typescript": "^5.7.3",
1212 "vitest": "^4.0.0",
......@@ -301,59 +301,81 @@
301301
302302 "@oxc-project/types": ["@oxc-project/types@0.112.0", "", {}, "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ=="],
303303
304 "@oxfmt/darwin-arm64": ["@oxfmt/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jmUfF7cNJPw57bEK7sMIqrYRgn4LH428tSgtgLTCtjuGuu1ShREyrkeB7y8HtkXRfhBs4lVY+HMLhqElJvZ6ww=="],
304 "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.35.0", "", { "os": "android", "cpu": "arm" }, "sha512-BaRKlM3DyG81y/xWTsE6gZiv89F/3pHe2BqX2H4JbiB8HNVlWWtplzgATAE5IDSdwChdeuWLDTQzJ92Lglw3ZA=="],
305305
306 "@oxfmt/darwin-x64": ["@oxfmt/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-S6vlV8S7jbjzJOSjfVg2CimUC0r7/aHDLdUm/3+/B/SU/s1jV7ivqWkMv1/8EB43d1BBwT9JQ60ZMTkBqeXSFA=="],
306 "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.35.0", "", { "os": "android", "cpu": "arm64" }, "sha512-/O+EbuAJYs6nde/anv+aID6uHsGQApyE9JtYBo/79KyU8e6RBN3DMbT0ix97y1SOnCglurmL2iZ+hlohjP2PnQ=="],
307307
308 "@oxfmt/linux-arm64-gnu": ["@oxfmt/linux-arm64-gnu@0.28.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-TfJkMZjePbLiskmxFXVAbGI/OZtD+y+fwS0wyW8O6DWG0ARTf0AipY9zGwGoOdpFuXOJceXvN4SHGLbYNDMY4Q=="],
308 "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.35.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-pGqRtqlNdn9d4VrmGUWVyQjkw79ryhI6je9y2jfqNUIZCfqceob+R97YYAoG7C5TFyt8ILdLVoN+L2vw/hSFyA=="],
309309
310 "@oxfmt/linux-arm64-musl": ["@oxfmt/linux-arm64-musl@0.28.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-7fyQUdW203v4WWGr1T3jwTz4L7KX9y5DeATryQ6fLT6QQp9GEuct8/k0lYhd+ys42iTV/IkJF20e3YkfSOOILg=="],
310 "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.35.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-8GmsDcSozTPjrCJeGpp+sCmS9+9V5yRrdEZ1p/sTWxPG5nYeAfSLuS0nuEYjXSO+CtdSbStIW6dxa+4NM58yRw=="],
311311
312 "@oxfmt/linux-x64-gnu": ["@oxfmt/linux-x64-gnu@0.28.0", "", { "os": "linux", "cpu": "x64" }, "sha512-sRKqAvEonuz0qr1X1ncUZceOBJerKzkO2gZIZmosvy/JmqyffpIFL3OE2tqacFkeDhrC+dNYQpusO8zsfHo3pw=="],
312 "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.35.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QyfKfTe0ytHpFKHAcHCGQEzN45QSqq1AHJOYYxQMgLM3KY4xu8OsXHpCnINjDsV4XGnQzczJDU9e04Zmd8XqIQ=="],
313313
314 "@oxfmt/linux-x64-musl": ["@oxfmt/linux-x64-musl@0.28.0", "", { "os": "linux", "cpu": "x64" }, "sha512-fW6czbXutX/tdQe8j4nSIgkUox9RXqjyxwyWXUDItpoDkoXllq17qbD7GVc0whrEhYQC6hFE1UEAcDypLJoSzw=="],
314 "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.35.0", "", { "os": "linux", "cpu": "arm" }, "sha512-u+kv3JD6P3J38oOyUaiCqgY5TNESzBRZJ5lyZQ6c2czUW2v5SIN9E/KWWa9vxoc+P8AFXQFUVrdzGy1tK+nbPQ=="],
315315
316 "@oxfmt/win32-arm64": ["@oxfmt/win32-arm64@0.28.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-D/HDeQBAQRjTbD9OLV6kRDcStrIfO+JsUODDCdGmhRfNX8LPCx95GpfyybpZfn3wVF8Jq/yjPXV1xLkQ+s7RcA=="],
316 "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.35.0", "", { "os": "linux", "cpu": "arm" }, "sha512-1NiZroCiV57I7Pf8kOH4XGR366kW5zir3VfSMBU2D0V14GpYjiYmPYFAoJboZvp8ACnZKUReWyMkNKSa5ad58A=="],
317317
318 "@oxfmt/win32-x64": ["@oxfmt/win32-x64@0.28.0", "", { "os": "win32", "cpu": "x64" }, "sha512-4+S2j4OxOIyo8dz5osm5dZuL0yVmxXvtmNdHB5xyGwAWVvyWNvf7tCaQD7w2fdSsAXQLOvK7KFQrHFe33nJUCA=="],
318 "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-7Q0Xeg7ZnW2nxnZ4R7aF6DEbCFls4skgHZg+I63XitpNvJCbVIU8MFOTZlvZGRsY9+rPgWPQGeUpLHlyx0wvMA=="],
319319
320 "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.46.0", "", { "os": "android", "cpu": "arm" }, "sha512-vLPcE+HcZ/W/0cVA1KLuAnoUSejGougDH/fDjBFf0Q+rbBIyBNLevOhgx3AnBNAt3hcIGY7U05ISbJCKZeVa3w=="],
320 "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Okqi+uhYFxwKz8hcnUftNNwdm8BCkf6GSCbcz9xJxYMm87k1E4p7PEmAAbhLTk7cjSdDre6TDL0pDzNX+Y22Q=="],
321321
322 "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.46.0", "", { "os": "android", "cpu": "arm64" }, "sha512-b8IqCczUsirdtJ3R/be4cRm64I5pMPafMO/9xyTAZvc+R/FxZHMQuhw0iNT9hQwRn+Uo5rNAoA8QS7QurG2QeA=="],
322 "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.35.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9k66pbZQXM/lBJWys3Xbc5yhl4JexyfqkEf/tvtq8976VIJnLAAL3M127xHA3ifYSqxdVHfVGTg84eiBHCGcNw=="],
323323
324 "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.46.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CfC/KGnNMhI01dkfCMjquKnW4zby3kqD5o/9XA7+pgo9I4b+Nipm+JVFyZPWMNwKqLXNmi35GTLWjs9svPxlew=="],
324 "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.35.0", "", { "os": "linux", "cpu": "none" }, "sha512-aUcY9ofKPtjO52idT6t0SAQvEF6ctjzUQa1lLp7GDsRpSBvuTrBQGeq0rYKz3gN8dMIQ7mtMdGD9tT4LhR8jAQ=="],
325325
326 "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.46.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-m38mKPsV3rBdWOJ4TAGZiUjWU8RGrBxsmdSeMQ0bPr/8O6CUOm/RJkPBf0GAfPms2WRVcbkfEXvIiPshAeFkeA=="],
326 "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.35.0", "", { "os": "linux", "cpu": "none" }, "sha512-C6yhY5Hvc2sGM+mCPek9ZLe5xRUOC/BvhAt2qIWFAeXMn4il04EYIjl3DsWiJr0xDMTJhvMOmD55xTRPlNp39w=="],
327327
328 "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.46.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-YaFRKslSAfuMwn7ejS1/wo9jENqQigpGBjjThX+mrpmEROLYGky+zIC5xSVGRng28U92VEDVbSNJ/sguz3dUAA=="],
328 "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.35.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-RG2hlvOMK4OMZpO3mt8MpxLQ0AAezlFqhn5mI/g5YrVbPFyoCv9a34AAvbSJS501ocOxlFIRcKEuw5hFvddf9g=="],
329329
330 "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.46.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Nlw+5mSZQtkg1Oj0N8ulxzG8ATpmSDz5V2DNaGhaYAVlcdR8NYSm/xTOnweOXc/UOOv3LwkPPYzqcfPhu2lEkA=="],
330 "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-wzmh90Pwvqj9xOKHJjkQYBpydRkaXG77ZvDz+iFDRRQpnqIEqGm5gmim2s6vnZIkDGsvKCuTdtxm0GFmBjM1+w=="],
331331
332 "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.46.0", "", { "os": "linux", "cpu": "arm" }, "sha512-d3Y5y4ukMqAGnWLMKpwqj8ftNUaac7pA0NrId4AZ77JvHzezmxEcm2gswaBw2HW8y1pnq6KDB0vEPPvpTfDLrA=="],
332 "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+HCqYCJPCUy5I+b2cf+gUVaApfgtoQT3HdnSg/l7NIcLHOhKstlYaGyrFZLmUpQt4WkFbpGKZZayG6zjRU0KFA=="],
333333
334 "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.46.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jkjx+XSOPuFR+C458prQmehO+v0VK19/3Hj2mOYDF4hHUf3CzmtA4fTmQUtkITZiGHnky7Oao6JeJX24mrX7WQ=="],
334 "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.35.0", "", { "os": "none", "cpu": "arm64" }, "sha512-kFYmWfR9YL78XyO5ws+1dsxNvZoD973qfVMNFOS4e9bcHXGF7DvGC2tY5UDFwyMCeB33t3sDIuGONKggnVNSJA=="],
335335
336 "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.46.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-X/aPB1rpJUdykjWSeeGIbjk6qbD8VDulgLuTSMWgr/t6m1ljcAjqHb1g49pVG9bZl55zjECgzvlpPLWnfb4FMQ=="],
336 "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.35.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-uD/NGdM65eKNCDGyTGdO8e9n3IHX+wwuorBvEYrPJXhDXL9qz6gzddmXH8EN04ejUXUujlq4FsoSeCfbg0Y+Jg=="],
337337
338 "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.46.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-AymyOxGWwKY2KJa8b+h8iLrYJZbWKYCjqctSc2q6uIAkYPrCsxcWlge1JP6XZ14Sa80DVMwI/QvktbytSV+xVw=="],
338 "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.35.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-oSRD2k8J2uxYDEKR2nAE/YTY9PobOEnhZgCmspHu0+yBQ665yH8lFErQVSTE7fcGJmJp/cC6322/gc8VFuQf7g=="],
339339
340 "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.46.0", "", { "os": "linux", "cpu": "none" }, "sha512-PkeVdPKCDA59rlMuucsel2LjlNEpslQN5AhkMMorIJZItbbqi/0JSuACCzaiIcXYv0oNfbeQ8rbOBikv+aT6cg=="],
340 "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.35.0", "", { "os": "win32", "cpu": "x64" }, "sha512-WCDJjlS95NboR0ugI2BEwzt1tYvRDorDRM9Lvctls1SLyKYuNRCyrPwp1urUPFBnwgBNn9p2/gnmo7gFMySRoQ=="],
341341
342 "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.46.0", "", { "os": "linux", "cpu": "none" }, "sha512-snQaRLO/X+Ry/CxX1px1g8GUbmXzymdRs+/RkP2bySHWZFhFDtbLm2hA1ujX/jKlTLMJDZn4hYzFGLDwG/Rh2w=="],
342 "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.50.0", "", { "os": "android", "cpu": "arm" }, "sha512-G7MRGk/6NCe+L8ntonRdZP7IkBfEpiZ/he3buLK6JkLgMHgJShXZ+BeOwADmspXez7U7F7L1Anf4xLSkLHiGTg=="],
343343
344 "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.46.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-kZhDMwUe/sgDTluGao9c0Dqc1JzV6wPzfGo0l/FLQdh5Zmp39Yg1FbBsCgsJfVKmKl1fNqsHyFLTShWMOlOEhA=="],
344 "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.50.0", "", { "os": "android", "cpu": "arm64" }, "sha512-GeSuMoJWCVpovJi/e3xDSNgjeR8WEZ6MCXL6EtPiCIM2NTzv7LbflARINTXTJy2oFBYyvdf/l2PwHzYo6EdXvg=="],
345345
346 "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.46.0", "", { "os": "linux", "cpu": "x64" }, "sha512-n5a7VtQTxHZ13cNAKQc3ziARv5bE1Fx868v/tnhZNVUjaRNYe5uiUrRJ/LZghdAzOxVuQGarjjq/q4QM2+9OPA=="],
346 "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.50.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-w3SY5YtxGnxCHPJ8Twl3KmS9oja1gERYk3AMoZ7Hv8P43ZtB6HVfs02TxvarxfL214Tm3uzvc2vn+DhtUNeKnw=="],
347347
348 "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.46.0", "", { "os": "linux", "cpu": "x64" }, "sha512-KpsDU/BhdVn3iKCLxMXAOZIpO8fS0jEA5iluRoK1rhHPwKtpzEm/OCwERsu/vboMSZm66qnoTUVXRPJ8M+iKVQ=="],
348 "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.50.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-hNfogDqy7tvmllXKBSlHo6k5x7dhTUVOHbMSE15CCAcXzmqf5883aPvBYPOq9AE7DpDUQUZ1kVE22YbiGW+tuw=="],
349349
350 "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.46.0", "", { "os": "none", "cpu": "arm64" }, "sha512-jtbqUyEXlsDlRmMtTZqNbw49+1V/WxqNAR5l0S3OEkdat9diI5I+eqq9IT+jb5cSDdszTGcXpn7S3+gUYSydxQ=="],
350 "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.50.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ykZevOWEyu0nsxolA911ucxpEv0ahw8jfEeGWOwwb/VPoE4xoexuTOAiPNlWZNJqANlJl7yp8OyzCtXTUAxotw=="],
351351
352 "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.46.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-EE8NjpqEZPwHQVigNvdyJ11dZwWIfsfn4VeBAuiJeAdrnY4HFX27mIjJINJgP5ZdBYEFV1OWH/eb9fURCYel8w=="],
352 "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-hif3iDk7vo5GGJ4OLCCZAf2vjnU9FztGw4L0MbQL0M2iY9LKFtDMMiQAHmkF0PQGQMVbTYtPdXCLKVgdkiqWXQ=="],
353353
354 "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.46.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-BHyk3H/HRdXs+uImGZ/2+qCET+B8lwGHOm7m54JiJEEUWf3zYCFX/Df1SPqtozWWmnBvioxoTG1J3mPRAr8KUA=="],
354 "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-dVp9iSssiGAnTNey2Ruf6xUaQhdnvcFOJyRWd/mu5o2jVbFK15E5fbWGeFRfmuobu5QXuROtFga44+7DOS3PLg=="],
355355
356 "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.46.0", "", { "os": "win32", "cpu": "x64" }, "sha512-DJbQsSJUr4KSi9uU0QqOgI7PX2C+fKGZX+YDprt3vM2sC0dWZsgVTLoN2vtkNyEWJSY2mnvRFUshWXT3bmo0Ug=="],
356 "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1cT7yz2HA910CKA9NkH1ZJo50vTtmND2fkoW1oyiSb0j6WvNtJ0Wx2zoySfXWc/c+7HFoqRK5AbEoL41LOn9oA=="],
357
358 "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-++B3k/HEPFVlj89cOz8kWfQccMZB/aWL9AhsW7jPIkG++63Mpwb2cE9XOEsd0PATbIan78k2Gky+09uWM1d/gQ=="],
359
360 "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.50.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Z9b/KpFMkx66w3gVBqjIC1AJBTZAGoI9+U+K5L4QM0CB/G0JSNC1es9b3Y0Vcrlvtdn8A+IQTkYjd/Q0uCSaZw=="],
361
362 "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-jvmuIw8wRSohsQlFNIST5uUwkEtEJmOQYr33bf/K2FrFPXHhM4KqGekI3ShYJemFS/gARVacQFgBzzJKCAyJjg=="],
363
364 "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-x+UrN47oYNh90nmAAyql8eQaaRpHbDPu5guasDg10+OpszUQ3/1+1J6zFMmV4xfIEgTcUXG/oI5fxJhF4eWCNA=="],
365
366 "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.50.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-i/JLi2ljLUIVfekMj4ISmdt+Hn11wzYUdRRrkVUYsCWw7zAy5xV7X9iA+KMyM156LTFympa7s3oKBjuCLoTAUQ=="],
367
368 "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-/C7brhn6c6UUPccgSPCcpLQXcp+xKIW/3sji/5VZ8/OItL3tQ2U7KalHz887UxxSQeEOmd1kY6lrpuwFnmNqOA=="],
369
370 "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-oDR1f+bGOYU8LfgtEW8XtotWGB63ghtcxk5Jm6IDTCk++rTA/IRMsjOid2iMd+1bW+nP9Mdsmcdc7VbPD3+iyQ=="],
371
372 "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.50.0", "", { "os": "none", "cpu": "arm64" }, "sha512-4CmRGPp5UpvXyu4jjP9Tey/SrXDQLRvZXm4pb4vdZBxAzbFZkCyh0KyRy4txld/kZKTJlW4TO8N1JKrNEk+mWw=="],
373
374 "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.50.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Fq0M6vsGcFsSfeuWAACDhd5KJrO85ckbEfe1EGuBj+KPyJz7KeWte2fSFrFGmNKNXyhEMyx4tbgxiWRujBM2KQ=="],
375
376 "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.50.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-qTdWR9KwY/vxJGhHVIZG2eBOhidOQvOwzDxnX+jhW/zIVacal1nAhR8GLkiywW8BIFDkQKXo/zOfT+/DY+ns/w=="],
377
378 "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.50.0", "", { "os": "win32", "cpu": "x64" }, "sha512-682t7npLC4G2Ca+iNlI9fhAKTcFPYYXJjwoa88H4q+u5HHHlsnL/gHULapX3iqp+A8FIJbgdylL5KMYo2LaluQ=="],
357379
358380 "@pierre/diffs": ["@pierre/diffs@1.1.0-beta.16", "", { "dependencies": { "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-McjTuEPuacSIcXdoI2O9W6VSHIOs9ApEHnEUwONKZnKqIo2GGv1vNg9Pr8tgBOL7lgBWNEHX5ROJ5z1X74sENQ=="],
359381
......@@ -1115,9 +1137,9 @@
11151137
11161138 "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
11171139
1118 "oxfmt": ["oxfmt@0.28.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/darwin-arm64": "0.28.0", "@oxfmt/darwin-x64": "0.28.0", "@oxfmt/linux-arm64-gnu": "0.28.0", "@oxfmt/linux-arm64-musl": "0.28.0", "@oxfmt/linux-x64-gnu": "0.28.0", "@oxfmt/linux-x64-musl": "0.28.0", "@oxfmt/win32-arm64": "0.28.0", "@oxfmt/win32-x64": "0.28.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-3+hhBqPE6Kp22KfJmnstrZbl+KdOVSEu1V0ABaFIg1rYLtrMgrupx9znnHgHLqKxAVHebjTdiCJDk30CXOt6cw=="],
1140 "oxfmt": ["oxfmt@0.35.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.35.0", "@oxfmt/binding-android-arm64": "0.35.0", "@oxfmt/binding-darwin-arm64": "0.35.0", "@oxfmt/binding-darwin-x64": "0.35.0", "@oxfmt/binding-freebsd-x64": "0.35.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.35.0", "@oxfmt/binding-linux-arm-musleabihf": "0.35.0", "@oxfmt/binding-linux-arm64-gnu": "0.35.0", "@oxfmt/binding-linux-arm64-musl": "0.35.0", "@oxfmt/binding-linux-ppc64-gnu": "0.35.0", "@oxfmt/binding-linux-riscv64-gnu": "0.35.0", "@oxfmt/binding-linux-riscv64-musl": "0.35.0", "@oxfmt/binding-linux-s390x-gnu": "0.35.0", "@oxfmt/binding-linux-x64-gnu": "0.35.0", "@oxfmt/binding-linux-x64-musl": "0.35.0", "@oxfmt/binding-openharmony-arm64": "0.35.0", "@oxfmt/binding-win32-arm64-msvc": "0.35.0", "@oxfmt/binding-win32-ia32-msvc": "0.35.0", "@oxfmt/binding-win32-x64-msvc": "0.35.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-QYeXWkP+aLt7utt5SLivNIk09glWx9QE235ODjgcEZ3sd1VMaUBSpLymh6ZRCA76gD2rMP4bXanUz/fx+nLM9Q=="],
11191141
1120 "oxlint": ["oxlint@1.46.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.46.0", "@oxlint/binding-android-arm64": "1.46.0", "@oxlint/binding-darwin-arm64": "1.46.0", "@oxlint/binding-darwin-x64": "1.46.0", "@oxlint/binding-freebsd-x64": "1.46.0", "@oxlint/binding-linux-arm-gnueabihf": "1.46.0", "@oxlint/binding-linux-arm-musleabihf": "1.46.0", "@oxlint/binding-linux-arm64-gnu": "1.46.0", "@oxlint/binding-linux-arm64-musl": "1.46.0", "@oxlint/binding-linux-ppc64-gnu": "1.46.0", "@oxlint/binding-linux-riscv64-gnu": "1.46.0", "@oxlint/binding-linux-riscv64-musl": "1.46.0", "@oxlint/binding-linux-s390x-gnu": "1.46.0", "@oxlint/binding-linux-x64-gnu": "1.46.0", "@oxlint/binding-linux-x64-musl": "1.46.0", "@oxlint/binding-openharmony-arm64": "1.46.0", "@oxlint/binding-win32-arm64-msvc": "1.46.0", "@oxlint/binding-win32-ia32-msvc": "1.46.0", "@oxlint/binding-win32-x64-msvc": "1.46.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.11.2" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-I9h42QDtAVsRwoueJ4PL/7qN5jFzIUXvbO4Z5ddtII92ZCiD7uiS/JW2V4viBSfGLsbZkQp3YEs6Ls4I8q+8tA=="],
1142 "oxlint": ["oxlint@1.50.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.50.0", "@oxlint/binding-android-arm64": "1.50.0", "@oxlint/binding-darwin-arm64": "1.50.0", "@oxlint/binding-darwin-x64": "1.50.0", "@oxlint/binding-freebsd-x64": "1.50.0", "@oxlint/binding-linux-arm-gnueabihf": "1.50.0", "@oxlint/binding-linux-arm-musleabihf": "1.50.0", "@oxlint/binding-linux-arm64-gnu": "1.50.0", "@oxlint/binding-linux-arm64-musl": "1.50.0", "@oxlint/binding-linux-ppc64-gnu": "1.50.0", "@oxlint/binding-linux-riscv64-gnu": "1.50.0", "@oxlint/binding-linux-riscv64-musl": "1.50.0", "@oxlint/binding-linux-s390x-gnu": "1.50.0", "@oxlint/binding-linux-x64-gnu": "1.50.0", "@oxlint/binding-linux-x64-musl": "1.50.0", "@oxlint/binding-openharmony-arm64": "1.50.0", "@oxlint/binding-win32-arm64-msvc": "1.50.0", "@oxlint/binding-win32-ia32-msvc": "1.50.0", "@oxlint/binding-win32-x64-msvc": "1.50.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.14.1" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-iSJ4IZEICBma8cZX7kxIIz9PzsYLF2FaLAYN6RKu7VwRVKdu7RIgpP99bTZaGl//Yao7fsaGZLSEo5xBrI5ReQ=="],
11211143
11221144 "p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="],
11231145
package.json+2-2
......@@ -36,8 +36,8 @@
3636 "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs"
3737 },
3838 "devDependencies": {
39 "oxfmt": "^0.28.0",
40 "oxlint": "^1.43.0",
39 "oxfmt": "^0.35.0",
40 "oxlint": "^1.50.0",
4141 "turbo": "^2.3.3",
4242 "typescript": "^5.7.3",
4343 "vitest": "^4.0.0"