| author | |
| committer | |
| log | dfe06261c459e9171d4fe4807bd1030fa3636b9f |
| tree | 51796be8045eb41254549fba18bb7b332c4fde59 |
| parent | 29a632cb521e199874dd0d2cd4ecca2b1c6f6c0b |
17 files changed, 350 insertions(+), 316 deletions(-)
.oxlintrc.json+3-1| ... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
| 15 | "perf": "warn" | 15 | "perf": "warn" |
| 16 | }, | 16 | }, |
| 17 | "rules": { | 17 | "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" | ||
| 19 | } | 21 | } |
| 20 | } | 22 | } |
apps/server/src/git/Layers/GitManager.ts+43-40| ... | @@ -29,10 +29,7 @@ function limitContext(value: string, maxChars: number): string { | ... | @@ -29,10 +29,7 @@ function limitContext(value: string, maxChars: number): string { |
| 29 | return `${value.slice(0, maxChars)}\n\n[truncated]`; | 29 | return `${value.slice(0, maxChars)}\n\n[truncated]`; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | function sanitizeCommitMessage(generated: { | 32 | function sanitizeCommitMessage(generated: { subject: string; body: string }): { |
| 33 | subject: string; | ||
| 34 | body: string; | ||
| 35 | }): { | ||
| 36 | subject: string; | 33 | subject: string; |
| 37 | body: string; | 34 | body: string; |
| 38 | } { | 35 | } { |
| ... | @@ -161,12 +158,14 @@ export const makeGitManager = Effect.gen(function* () { | ... | @@ -161,12 +158,14 @@ export const makeGitManager = Effect.gen(function* () { |
| 161 | 158 | ||
| 162 | let generated = parseCustomCommitMessage(commitMessage ?? ""); | 159 | let generated = parseCustomCommitMessage(commitMessage ?? ""); |
| 163 | if (!generated) { | 160 | if (!generated) { |
| 164 | generated = yield* textGeneration.generateCommitMessage({ | 161 | generated = yield* textGeneration |
| 165 | cwd, | 162 | .generateCommitMessage({ |
| 166 | branch, | 163 | cwd, |
| 167 | stagedSummary: limitContext(context.stagedSummary, 8_000), | 164 | branch, |
| 168 | stagedPatch: limitContext(context.stagedPatch, 50_000), | 165 | stagedSummary: limitContext(context.stagedSummary, 8_000), |
| 169 | }).pipe(Effect.map((result) => sanitizeCommitMessage(result))); | 166 | stagedPatch: limitContext(context.stagedPatch, 50_000), |
| 167 | }) | ||
| 168 | .pipe(Effect.map((result) => sanitizeCommitMessage(result))); | ||
| 170 | } | 169 | } |
| 171 | 170 | ||
| 172 | const { commitSha } = yield* gitCore.commit(cwd, generated.subject, generated.body); | 171 | const { commitSha } = yield* gitCore.commit(cwd, generated.subject, generated.body); |
| ... | @@ -182,7 +181,10 @@ export const makeGitManager = Effect.gen(function* () { | ... | @@ -182,7 +181,10 @@ export const makeGitManager = Effect.gen(function* () { |
| 182 | const details = yield* gitCore.statusDetails(cwd); | 181 | const details = yield* gitCore.statusDetails(cwd); |
| 183 | const branch = details.branch ?? fallbackBranch; | 182 | const branch = details.branch ?? fallbackBranch; |
| 184 | if (!branch) { | 183 | 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 | ); | ||
| 186 | } | 188 | } |
| 187 | if (!details.hasUpstream) { | 189 | if (!details.hasUpstream) { |
| 188 | return yield* gitManagerError( | 190 | return yield* gitManagerError( |
| ... | @@ -220,11 +222,7 @@ export const makeGitManager = Effect.gen(function* () { | ... | @@ -220,11 +222,7 @@ export const makeGitManager = Effect.gen(function* () { |
| 220 | .writeFileString(bodyFile, generated.body) | 222 | .writeFileString(bodyFile, generated.body) |
| 221 | .pipe( | 223 | .pipe( |
| 222 | Effect.mapError((cause) => | 224 | Effect.mapError((cause) => |
| 223 | gitManagerError( | 225 | gitManagerError("runPrStep", "Failed to write pull request body temp file.", cause), |
| 224 | "runPrStep", | ||
| 225 | "Failed to write pull request body temp file.", | ||
| 226 | cause, | ||
| 227 | ), | ||
| 228 | ), | 226 | ), |
| 229 | ); | 227 | ); |
| 230 | yield* gitHubCli | 228 | yield* gitHubCli |
| ... | @@ -279,35 +277,40 @@ export const makeGitManager = Effect.gen(function* () { | ... | @@ -279,35 +277,40 @@ export const makeGitManager = Effect.gen(function* () { |
| 279 | }; | 277 | }; |
| 280 | }); | 278 | }); |
| 281 | 279 | ||
| 282 | const runStackedAction: GitManagerShape["runStackedAction"] = Effect.fnUntraced(function* (input) { | 280 | const runStackedAction: GitManagerShape["runStackedAction"] = Effect.fnUntraced( |
| 283 | const wantsPush = input.action !== "commit"; | 281 | function* (input) { |
| 284 | const wantsPr = input.action === "commit_push_pr"; | 282 | const wantsPush = input.action !== "commit"; |
| 283 | const wantsPr = input.action === "commit_push_pr"; | ||
| 285 | 284 | ||
| 286 | const initialStatus = yield* gitCore.statusDetails(input.cwd); | 285 | const initialStatus = yield* gitCore.statusDetails(input.cwd); |
| 287 | if (wantsPush && !initialStatus.branch) { | 286 | if (wantsPush && !initialStatus.branch) { |
| 288 | return yield* gitManagerError("runStackedAction", "Cannot push from detached HEAD."); | 287 | return yield* gitManagerError("runStackedAction", "Cannot push from detached HEAD."); |
| 289 | } | 288 | } |
| 290 | if (wantsPr && !initialStatus.branch) { | 289 | if (wantsPr && !initialStatus.branch) { |
| 291 | return yield* gitManagerError("runStackedAction", "Cannot create a pull request from detached HEAD."); | 290 | return yield* gitManagerError( |
| 292 | } | 291 | "runStackedAction", |
| 292 | "Cannot create a pull request from detached HEAD.", | ||
| 293 | ); | ||
| 294 | } | ||
| 293 | 295 | ||
| 294 | const commit = yield* runCommitStep(input.cwd, initialStatus.branch, input.commitMessage); | 296 | const commit = yield* runCommitStep(input.cwd, initialStatus.branch, input.commitMessage); |
| 295 | 297 | ||
| 296 | const push = wantsPush | 298 | const push = wantsPush |
| 297 | ? yield* gitCore.pushCurrentBranch(input.cwd, initialStatus.branch) | 299 | ? yield* gitCore.pushCurrentBranch(input.cwd, initialStatus.branch) |
| 298 | : { status: "skipped_not_requested" as const }; | 300 | : { status: "skipped_not_requested" as const }; |
| 299 | 301 | ||
| 300 | const pr = wantsPr | 302 | const pr = wantsPr |
| 301 | ? yield* runPrStep(input.cwd, initialStatus.branch) | 303 | ? yield* runPrStep(input.cwd, initialStatus.branch) |
| 302 | : { status: "skipped_not_requested" as const }; | 304 | : { status: "skipped_not_requested" as const }; |
| 303 | 305 | ||
| 304 | return { | 306 | return { |
| 305 | action: input.action, | 307 | action: input.action, |
| 306 | commit, | 308 | commit, |
| 307 | push, | 309 | push, |
| 308 | pr, | 310 | pr, |
| 309 | }; | 311 | }; |
| 310 | }); | 312 | }, |
| 313 | ); | ||
| 311 | 314 | ||
| 312 | return { | 315 | return { |
| 313 | status, | 316 | status, |
apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts+3-1| ... | @@ -561,7 +561,9 @@ describe("OrchestrationEngine", () => { | ... | @@ -561,7 +561,9 @@ describe("OrchestrationEngine", () => { |
| 561 | ).rejects.toThrow("projection failed"); | 561 | ).rejects.toThrow("projection failed"); |
| 562 | 562 | ||
| 563 | const readModelAfterFailure = await runtime.runPromise(engine.getReadModel()); | 563 | 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 | ); | ||
| 565 | expect(readModelAfterFailure.snapshotSequence).toBe(3); | 567 | expect(readModelAfterFailure.snapshotSequence).toBe(3); |
| 566 | expect(updatedThread?.title).toBe("sync-after-failed-projection"); | 568 | expect(updatedThread?.title).toBe("sync-after-failed-projection"); |
| 567 | 569 |
apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts+125-124| ... | @@ -412,125 +412,127 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { | ... | @@ -412,125 +412,127 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { |
| 412 | }), | 412 | }), |
| 413 | ); | 413 | ); |
| 414 | 414 | ||
| 415 | it.effect("resolves turn-count conflicts when checkpoint completion rewrites provisional turns", () => | 415 | it.effect( |
| 416 | Effect.gen(function* () { | 416 | "resolves turn-count conflicts when checkpoint completion rewrites provisional turns", |
| 417 | const projectionPipeline = yield* OrchestrationProjectionPipeline; | 417 | () => |
| 418 | const eventStore = yield* OrchestrationEventStore; | 418 | Effect.gen(function* () { |
| 419 | const sql = yield* SqlClient.SqlClient; | 419 | const projectionPipeline = yield* OrchestrationProjectionPipeline; |
| 420 | const appendAndProject = (event: Parameters<typeof eventStore.append>[0]) => | 420 | const eventStore = yield* OrchestrationEventStore; |
| 421 | eventStore | 421 | const sql = yield* SqlClient.SqlClient; |
| 422 | .append(event) | 422 | const appendAndProject = (event: Parameters<typeof eventStore.append>[0]) => |
| 423 | .pipe(Effect.flatMap((savedEvent) => projectionPipeline.projectEvent(savedEvent))); | 423 | eventStore |
| 424 | 424 | .append(event) | |
| 425 | yield* appendAndProject({ | 425 | .pipe(Effect.flatMap((savedEvent) => projectionPipeline.projectEvent(savedEvent))); |
| 426 | type: "project.created", | 426 | |
| 427 | eventId: EventId.makeUnsafe("evt-conflict-1"), | 427 | yield* appendAndProject({ |
| 428 | aggregateKind: "project", | 428 | type: "project.created", |
| 429 | aggregateId: ProjectId.makeUnsafe("project-conflict"), | 429 | eventId: EventId.makeUnsafe("evt-conflict-1"), |
| 430 | occurredAt: "2026-02-26T13:00:00.000Z", | 430 | aggregateKind: "project", |
| 431 | commandId: CommandId.makeUnsafe("cmd-conflict-1"), | 431 | aggregateId: ProjectId.makeUnsafe("project-conflict"), |
| 432 | causationEventId: null, | 432 | occurredAt: "2026-02-26T13:00:00.000Z", |
| 433 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"), | 433 | commandId: CommandId.makeUnsafe("cmd-conflict-1"), |
| 434 | metadata: {}, | 434 | causationEventId: null, |
| 435 | payload: { | 435 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"), |
| 436 | projectId: ProjectId.makeUnsafe("project-conflict"), | 436 | metadata: {}, |
| 437 | title: "Project Conflict", | 437 | payload: { |
| 438 | workspaceRoot: "/tmp/project-conflict", | 438 | projectId: ProjectId.makeUnsafe("project-conflict"), |
| 439 | defaultModel: null, | 439 | title: "Project Conflict", |
| 440 | scripts: [], | 440 | workspaceRoot: "/tmp/project-conflict", |
| 441 | createdAt: "2026-02-26T13:00:00.000Z", | 441 | defaultModel: null, |
| 442 | updatedAt: "2026-02-26T13:00:00.000Z", | 442 | scripts: [], |
| 443 | }, | 443 | createdAt: "2026-02-26T13:00:00.000Z", |
| 444 | }); | 444 | updatedAt: "2026-02-26T13:00:00.000Z", |
| 445 | 445 | }, | |
| 446 | yield* appendAndProject({ | 446 | }); |
| 447 | type: "thread.created", | 447 | |
| 448 | eventId: EventId.makeUnsafe("evt-conflict-2"), | 448 | yield* appendAndProject({ |
| 449 | aggregateKind: "thread", | 449 | type: "thread.created", |
| 450 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | 450 | eventId: EventId.makeUnsafe("evt-conflict-2"), |
| 451 | occurredAt: "2026-02-26T13:00:01.000Z", | 451 | aggregateKind: "thread", |
| 452 | commandId: CommandId.makeUnsafe("cmd-conflict-2"), | 452 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), |
| 453 | causationEventId: null, | 453 | occurredAt: "2026-02-26T13:00:01.000Z", |
| 454 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"), | 454 | commandId: CommandId.makeUnsafe("cmd-conflict-2"), |
| 455 | metadata: {}, | 455 | causationEventId: null, |
| 456 | payload: { | 456 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"), |
| 457 | threadId: ThreadId.makeUnsafe("thread-conflict"), | 457 | metadata: {}, |
| 458 | projectId: ProjectId.makeUnsafe("project-conflict"), | 458 | payload: { |
| 459 | title: "Thread Conflict", | 459 | threadId: ThreadId.makeUnsafe("thread-conflict"), |
| 460 | model: "gpt-5-codex", | 460 | projectId: ProjectId.makeUnsafe("project-conflict"), |
| 461 | branch: null, | 461 | title: "Thread Conflict", |
| 462 | worktreePath: null, | 462 | model: "gpt-5-codex", |
| 463 | createdAt: "2026-02-26T13:00:01.000Z", | 463 | branch: null, |
| 464 | updatedAt: "2026-02-26T13:00:01.000Z", | 464 | worktreePath: null, |
| 465 | }, | 465 | createdAt: "2026-02-26T13:00:01.000Z", |
| 466 | }); | 466 | updatedAt: "2026-02-26T13:00:01.000Z", |
| 467 | 467 | }, | |
| 468 | yield* appendAndProject({ | 468 | }); |
| 469 | type: "thread.turn-interrupt-requested", | 469 | |
| 470 | eventId: EventId.makeUnsafe("evt-conflict-3"), | 470 | yield* appendAndProject({ |
| 471 | aggregateKind: "thread", | 471 | type: "thread.turn-interrupt-requested", |
| 472 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | 472 | eventId: EventId.makeUnsafe("evt-conflict-3"), |
| 473 | occurredAt: "2026-02-26T13:00:02.000Z", | 473 | aggregateKind: "thread", |
| 474 | commandId: CommandId.makeUnsafe("cmd-conflict-3"), | 474 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), |
| 475 | causationEventId: null, | 475 | occurredAt: "2026-02-26T13:00:02.000Z", |
| 476 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"), | 476 | commandId: CommandId.makeUnsafe("cmd-conflict-3"), |
| 477 | metadata: {}, | 477 | causationEventId: null, |
| 478 | payload: { | 478 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"), |
| 479 | threadId: ThreadId.makeUnsafe("thread-conflict"), | 479 | metadata: {}, |
| 480 | turnId: TurnId.makeUnsafe("turn-interrupted"), | 480 | payload: { |
| 481 | createdAt: "2026-02-26T13:00:02.000Z", | 481 | threadId: ThreadId.makeUnsafe("thread-conflict"), |
| 482 | }, | 482 | turnId: TurnId.makeUnsafe("turn-interrupted"), |
| 483 | }); | 483 | createdAt: "2026-02-26T13:00:02.000Z", |
| 484 | 484 | }, | |
| 485 | yield* appendAndProject({ | 485 | }); |
| 486 | type: "thread.message-sent", | 486 | |
| 487 | eventId: EventId.makeUnsafe("evt-conflict-4"), | 487 | yield* appendAndProject({ |
| 488 | aggregateKind: "thread", | 488 | type: "thread.message-sent", |
| 489 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | 489 | eventId: EventId.makeUnsafe("evt-conflict-4"), |
| 490 | occurredAt: "2026-02-26T13:00:03.000Z", | 490 | aggregateKind: "thread", |
| 491 | commandId: CommandId.makeUnsafe("cmd-conflict-4"), | 491 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), |
| 492 | causationEventId: null, | 492 | occurredAt: "2026-02-26T13:00:03.000Z", |
| 493 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"), | 493 | commandId: CommandId.makeUnsafe("cmd-conflict-4"), |
| 494 | metadata: {}, | 494 | causationEventId: null, |
| 495 | payload: { | 495 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"), |
| 496 | threadId: ThreadId.makeUnsafe("thread-conflict"), | 496 | metadata: {}, |
| 497 | messageId: MessageId.makeUnsafe("assistant-conflict"), | 497 | payload: { |
| 498 | role: "assistant", | 498 | threadId: ThreadId.makeUnsafe("thread-conflict"), |
| 499 | text: "done", | 499 | messageId: MessageId.makeUnsafe("assistant-conflict"), |
| 500 | turnId: TurnId.makeUnsafe("turn-completed"), | 500 | role: "assistant", |
| 501 | streaming: false, | 501 | text: "done", |
| 502 | createdAt: "2026-02-26T13:00:03.000Z", | 502 | turnId: TurnId.makeUnsafe("turn-completed"), |
| 503 | updatedAt: "2026-02-26T13:00:03.000Z", | 503 | streaming: false, |
| 504 | }, | 504 | createdAt: "2026-02-26T13:00:03.000Z", |
| 505 | }); | 505 | updatedAt: "2026-02-26T13:00:03.000Z", |
| 506 | 506 | }, | |
| 507 | yield* appendAndProject({ | 507 | }); |
| 508 | type: "thread.turn-diff-completed", | 508 | |
| 509 | eventId: EventId.makeUnsafe("evt-conflict-5"), | 509 | yield* appendAndProject({ |
| 510 | aggregateKind: "thread", | 510 | type: "thread.turn-diff-completed", |
| 511 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | 511 | eventId: EventId.makeUnsafe("evt-conflict-5"), |
| 512 | occurredAt: "2026-02-26T13:00:04.000Z", | 512 | aggregateKind: "thread", |
| 513 | commandId: CommandId.makeUnsafe("cmd-conflict-5"), | 513 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), |
| 514 | causationEventId: null, | 514 | occurredAt: "2026-02-26T13:00:04.000Z", |
| 515 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"), | 515 | commandId: CommandId.makeUnsafe("cmd-conflict-5"), |
| 516 | metadata: {}, | 516 | causationEventId: null, |
| 517 | payload: { | 517 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"), |
| 518 | threadId: ThreadId.makeUnsafe("thread-conflict"), | 518 | metadata: {}, |
| 519 | turnId: TurnId.makeUnsafe("turn-completed"), | 519 | payload: { |
| 520 | checkpointTurnCount: 1, | 520 | threadId: ThreadId.makeUnsafe("thread-conflict"), |
| 521 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"), | 521 | turnId: TurnId.makeUnsafe("turn-completed"), |
| 522 | status: "ready", | 522 | checkpointTurnCount: 1, |
| 523 | files: [], | 523 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"), |
| 524 | assistantMessageId: MessageId.makeUnsafe("assistant-conflict"), | 524 | status: "ready", |
| 525 | completedAt: "2026-02-26T13:00:04.000Z", | 525 | files: [], |
| 526 | }, | 526 | assistantMessageId: MessageId.makeUnsafe("assistant-conflict"), |
| 527 | }); | 527 | completedAt: "2026-02-26T13:00:04.000Z", |
| 528 | }, | ||
| 529 | }); | ||
| 528 | 530 | ||
| 529 | const turnRows = yield* sql<{ | 531 | const turnRows = yield* sql<{ |
| 530 | readonly turnId: string; | 532 | readonly turnId: string; |
| 531 | readonly checkpointTurnCount: number | null; | 533 | readonly checkpointTurnCount: number | null; |
| 532 | readonly status: string; | 534 | readonly status: string; |
| 533 | }>` | 535 | }>` |
| 534 | SELECT | 536 | SELECT |
| 535 | turn_id AS "turnId", | 537 | turn_id AS "turnId", |
| 536 | checkpoint_turn_count AS "checkpointTurnCount", | 538 | checkpoint_turn_count AS "checkpointTurnCount", |
| ... | @@ -545,11 +547,11 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { | ... | @@ -545,11 +547,11 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { |
| 545 | checkpoint_turn_count ASC, | 547 | checkpoint_turn_count ASC, |
| 546 | requested_at ASC | 548 | requested_at ASC |
| 547 | `; | 549 | `; |
| 548 | assert.deepEqual(turnRows, [ | 550 | assert.deepEqual(turnRows, [ |
| 549 | { turnId: "turn-completed", checkpointTurnCount: 1, status: "completed" }, | 551 | { turnId: "turn-completed", checkpointTurnCount: 1, status: "completed" }, |
| 550 | { turnId: "turn-interrupted", checkpointTurnCount: null, status: "interrupted" }, | 552 | { turnId: "turn-interrupted", checkpointTurnCount: null, status: "interrupted" }, |
| 551 | ]); | 553 | ]); |
| 552 | }), | 554 | }), |
| 553 | ); | 555 | ); |
| 554 | 556 | ||
| 555 | it.effect("does not fallback-retain messages whose turnId is removed by revert", () => | 557 | it.effect("does not fallback-retain messages whose turnId is removed by revert", () => |
| ... | @@ -753,7 +755,6 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { | ... | @@ -753,7 +755,6 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { |
| 753 | ]); | 755 | ]); |
| 754 | }), | 756 | }), |
| 755 | ); | 757 | ); |
| 756 | |||
| 757 | }); | 758 | }); |
| 758 | 759 | ||
| 759 | it.effect("restores pending turn-start metadata across projection pipeline restart", () => | 760 | it.effect("restores pending turn-start metadata across projection pipeline restart", () => |
apps/server/src/orchestration/Layers/ProjectionPipeline.ts+17-5| ... | @@ -14,7 +14,10 @@ import { | ... | @@ -14,7 +14,10 @@ import { |
| 14 | ProjectionThreadMessageRepository, | 14 | ProjectionThreadMessageRepository, |
| 15 | } from "../../persistence/Services/ProjectionThreadMessages.ts"; | 15 | } from "../../persistence/Services/ProjectionThreadMessages.ts"; |
| 16 | import { ProjectionThreadSessionRepository } from "../../persistence/Services/ProjectionThreadSessions.ts"; | 16 | import { ProjectionThreadSessionRepository } from "../../persistence/Services/ProjectionThreadSessions.ts"; |
| 17 | import { type ProjectionTurn, ProjectionTurnRepository } from "../../persistence/Services/ProjectionTurns.ts"; | 17 | import { |
| 18 | type ProjectionTurn, | ||
| 19 | ProjectionTurnRepository, | ||
| 20 | } from "../../persistence/Services/ProjectionTurns.ts"; | ||
| 18 | import { ProjectionThreadRepository } from "../../persistence/Services/ProjectionThreads.ts"; | 21 | import { ProjectionThreadRepository } from "../../persistence/Services/ProjectionThreads.ts"; |
| 19 | import { ProjectionPendingApprovalRepositoryLive } from "../../persistence/Layers/ProjectionPendingApprovals.ts"; | 22 | import { ProjectionPendingApprovalRepositoryLive } from "../../persistence/Layers/ProjectionPendingApprovals.ts"; |
| 20 | import { ProjectionProjectRepositoryLive } from "../../persistence/Layers/ProjectionProjects.ts"; | 23 | import { ProjectionProjectRepositoryLive } from "../../persistence/Layers/ProjectionProjects.ts"; |
| ... | @@ -64,7 +67,10 @@ function retainProjectionMessagesAfterRevert( | ... | @@ -64,7 +67,10 @@ function retainProjectionMessagesAfterRevert( |
| 64 | const retainedMessageIds = new Set<string>(); | 67 | const retainedMessageIds = new Set<string>(); |
| 65 | const retainedTurnIds = new Set<string>(); | 68 | const retainedTurnIds = new Set<string>(); |
| 66 | const keptTurns = turns.filter( | 69 | 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, | ||
| 68 | ); | 74 | ); |
| 69 | for (const turn of keptTurns) { | 75 | for (const turn of keptTurns) { |
| 70 | if (turn.turnId !== null) { | 76 | if (turn.turnId !== null) { |
| ... | @@ -511,16 +517,22 @@ const makeOrchestrationProjectionPipeline = Effect.gen(function* () { | ... | @@ -511,16 +517,22 @@ const makeOrchestrationProjectionPipeline = Effect.gen(function* () { |
| 511 | (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.messageId : null), | 517 | (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.messageId : null), |
| 512 | startedAt: | 518 | startedAt: |
| 513 | existingTurn.value.startedAt ?? | 519 | existingTurn.value.startedAt ?? |
| 514 | (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.requestedAt : event.occurredAt), | 520 | (Option.isSome(pendingTurnStart) |
| 521 | ? pendingTurnStart.value.requestedAt | ||
| 522 | : event.occurredAt), | ||
| 515 | requestedAt: | 523 | requestedAt: |
| 516 | existingTurn.value.requestedAt ?? | 524 | existingTurn.value.requestedAt ?? |
| 517 | (Option.isSome(pendingTurnStart) ? pendingTurnStart.value.requestedAt : event.occurredAt), | 525 | (Option.isSome(pendingTurnStart) |
| 526 | ? pendingTurnStart.value.requestedAt | ||
| 527 | : event.occurredAt), | ||
| 518 | }); | 528 | }); |
| 519 | } else { | 529 | } else { |
| 520 | yield* projectionTurnRepository.upsertByTurnId({ | 530 | yield* projectionTurnRepository.upsertByTurnId({ |
| 521 | turnId, | 531 | turnId, |
| 522 | threadId: event.payload.threadId, | 532 | threadId: event.payload.threadId, |
| 523 | pendingMessageId: Option.isSome(pendingTurnStart) ? pendingTurnStart.value.messageId : null, | 533 | pendingMessageId: Option.isSome(pendingTurnStart) |
| 534 | ? pendingTurnStart.value.messageId | ||
| 535 | : null, | ||
| 524 | assistantMessageId: null, | 536 | assistantMessageId: null, |
| 525 | state: "running", | 537 | state: "running", |
| 526 | requestedAt: Option.isSome(pendingTurnStart) | 538 | requestedAt: Option.isSome(pendingTurnStart) |
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+5-8| ... | @@ -149,14 +149,11 @@ const make = Effect.gen(function* () { | ... | @@ -149,14 +149,11 @@ const make = Effect.gen(function* () { |
| 149 | projects: readModel.projects, | 149 | projects: readModel.projects, |
| 150 | }); | 150 | }); |
| 151 | 151 | ||
| 152 | const startedSession = yield* providerService.startSession( | 152 | const startedSession = yield* providerService.startSession(threadId, { |
| 153 | threadId, | 153 | ...(preferredProvider ? { provider: preferredProvider } : {}), |
| 154 | { | 154 | ...(effectiveCwd ? { cwd: effectiveCwd } : {}), |
| 155 | ...(preferredProvider ? { provider: preferredProvider } : {}), | 155 | ...(thread.model ? { model: thread.model } : {}), |
| 156 | ...(effectiveCwd ? { cwd: effectiveCwd } : {}), | 156 | }); |
| 157 | ...(thread.model ? { model: thread.model } : {}), | ||
| 158 | }, | ||
| 159 | ); | ||
| 160 | 157 | ||
| 161 | yield* setThreadSession({ | 158 | yield* setThreadSession({ |
| 162 | threadId, | 159 | threadId, |
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts+7-3| ... | @@ -274,7 +274,8 @@ describe("ProviderRuntimeIngestion", () => { | ... | @@ -274,7 +274,8 @@ describe("ProviderRuntimeIngestion", () => { |
| 274 | await waitForThread( | 274 | await waitForThread( |
| 275 | harness.engine, | 275 | harness.engine, |
| 276 | (thread) => | 276 | (thread) => |
| 277 | thread.session?.status === "running" && thread.session?.activeTurnId === "turn-complete-dedup", | 277 | thread.session?.status === "running" && |
| 278 | thread.session?.activeTurnId === "turn-complete-dedup", | ||
| 278 | ); | 279 | ); |
| 279 | 280 | ||
| 280 | harness.emit({ | 281 | harness.emit({ |
| ... | @@ -317,14 +318,17 @@ describe("ProviderRuntimeIngestion", () => { | ... | @@ -317,14 +318,17 @@ describe("ProviderRuntimeIngestion", () => { |
| 317 | ); | 318 | ); |
| 318 | 319 | ||
| 319 | const events = await Effect.runPromise( | 320 | 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 | ), | ||
| 321 | ); | 324 | ); |
| 322 | const completionEvents = events.filter((event) => { | 325 | const completionEvents = events.filter((event) => { |
| 323 | if (event.type !== "thread.message-sent") { | 326 | if (event.type !== "thread.message-sent") { |
| 324 | return false; | 327 | return false; |
| 325 | } | 328 | } |
| 326 | return ( | 329 | 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 | ||
| 328 | ); | 332 | ); |
| 329 | }); | 333 | }); |
| 330 | expect(completionEvents).toHaveLength(1); | 334 | expect(completionEvents).toHaveLength(1); |
apps/server/src/orchestration/projector.test.ts+6-2| ... | @@ -702,7 +702,9 @@ describe("orchestration projector", () => { | ... | @@ -702,7 +702,9 @@ describe("orchestration projector", () => { |
| 702 | }, | 702 | }, |
| 703 | }), | 703 | }), |
| 704 | ); | 704 | ); |
| 705 | const afterMessages = await messageEvents.reduce<Promise<ReturnType<typeof createEmptyReadModel>>>( | 705 | const afterMessages = await messageEvents.reduce< |
| 706 | Promise<ReturnType<typeof createEmptyReadModel>> | ||
| 707 | >( | ||
| 706 | (statePromise, event) => | 708 | (statePromise, event) => |
| 707 | statePromise.then((state) => Effect.runPromise(projectEvent(state, event))), | 709 | statePromise.then((state) => Effect.runPromise(projectEvent(state, event))), |
| 708 | Promise.resolve(afterCreate), | 710 | Promise.resolve(afterCreate), |
| ... | @@ -730,7 +732,9 @@ describe("orchestration projector", () => { | ... | @@ -730,7 +732,9 @@ describe("orchestration projector", () => { |
| 730 | }, | 732 | }, |
| 731 | }), | 733 | }), |
| 732 | ); | 734 | ); |
| 733 | const finalState = await checkpointEvents.reduce<Promise<ReturnType<typeof createEmptyReadModel>>>( | 735 | const finalState = await checkpointEvents.reduce< |
| 736 | Promise<ReturnType<typeof createEmptyReadModel>> | ||
| 737 | >( | ||
| 734 | (statePromise, event) => | 738 | (statePromise, event) => |
| 735 | statePromise.then((state) => Effect.runPromise(projectEvent(state, event))), | 739 | statePromise.then((state) => Effect.runPromise(projectEvent(state, event))), |
| 736 | Promise.resolve(afterMessages), | 740 | Promise.resolve(afterMessages), |
apps/server/src/persistence/Layers/ProjectionTurns.ts+21-22| ... | @@ -260,23 +260,21 @@ const makeProjectionTurnRepository = Effect.gen(function* () { | ... | @@ -260,23 +260,21 @@ const makeProjectionTurnRepository = Effect.gen(function* () { |
| 260 | ), | 260 | ), |
| 261 | ); | 261 | ); |
| 262 | 262 | ||
| 263 | const getPendingTurnStartByThreadId: ProjectionTurnRepositoryShape["getPendingTurnStartByThreadId"] = ( | 263 | const getPendingTurnStartByThreadId: ProjectionTurnRepositoryShape["getPendingTurnStartByThreadId"] = |
| 264 | input, | 264 | (input) => |
| 265 | ) => | 265 | getPendingProjectionTurn(input).pipe( |
| 266 | getPendingProjectionTurn(input).pipe( | 266 | Effect.mapError( |
| 267 | Effect.mapError( | 267 | toPersistenceSqlError("ProjectionTurnRepository.getPendingTurnStartByThreadId:query"), |
| 268 | toPersistenceSqlError("ProjectionTurnRepository.getPendingTurnStartByThreadId:query"), | 268 | ), |
| 269 | ), | 269 | ); |
| 270 | ); | ||
| 271 | 270 | ||
| 272 | const deletePendingTurnStartByThreadId: ProjectionTurnRepositoryShape["deletePendingTurnStartByThreadId"] = ( | 271 | const deletePendingTurnStartByThreadId: ProjectionTurnRepositoryShape["deletePendingTurnStartByThreadId"] = |
| 273 | input, | 272 | (input) => |
| 274 | ) => | 273 | clearPendingProjectionTurnsByThread(input).pipe( |
| 275 | clearPendingProjectionTurnsByThread(input).pipe( | 274 | Effect.mapError( |
| 276 | Effect.mapError( | 275 | toPersistenceSqlError("ProjectionTurnRepository.deletePendingTurnStartByThreadId:query"), |
| 277 | toPersistenceSqlError("ProjectionTurnRepository.deletePendingTurnStartByThreadId:query"), | 276 | ), |
| 278 | ), | 277 | ); |
| 279 | ); | ||
| 280 | 278 | ||
| 281 | const listByThreadId: ProjectionTurnRepositoryShape["listByThreadId"] = (input) => | 279 | const listByThreadId: ProjectionTurnRepositoryShape["listByThreadId"] = (input) => |
| 282 | listProjectionTurnsByThread(input).pipe( | 280 | listProjectionTurnsByThread(input).pipe( |
| ... | @@ -306,12 +304,13 @@ const makeProjectionTurnRepository = Effect.gen(function* () { | ... | @@ -306,12 +304,13 @@ const makeProjectionTurnRepository = Effect.gen(function* () { |
| 306 | ), | 304 | ), |
| 307 | ); | 305 | ); |
| 308 | 306 | ||
| 309 | const clearCheckpointTurnConflict: ProjectionTurnRepositoryShape["clearCheckpointTurnConflict"] = ( | 307 | const clearCheckpointTurnConflict: ProjectionTurnRepositoryShape["clearCheckpointTurnConflict"] = |
| 310 | input, | 308 | (input) => |
| 311 | ) => | 309 | clearCheckpointTurnConflictRow(input).pipe( |
| 312 | clearCheckpointTurnConflictRow(input).pipe( | 310 | Effect.mapError( |
| 313 | Effect.mapError(toPersistenceSqlError("ProjectionTurnRepository.clearCheckpointTurnConflict:query")), | 311 | toPersistenceSqlError("ProjectionTurnRepository.clearCheckpointTurnConflict:query"), |
| 314 | ); | 312 | ), |
| 313 | ); | ||
| 315 | 314 | ||
| 316 | const deleteByThreadId: ProjectionTurnRepositoryShape["deleteByThreadId"] = (input) => | 315 | const deleteByThreadId: ProjectionTurnRepositoryShape["deleteByThreadId"] = (input) => |
| 317 | deleteProjectionTurnsByThread(input).pipe( | 316 | deleteProjectionTurnsByThread(input).pipe( |
apps/server/src/provider/Layers/ProviderService.test.ts+34-64| ... | @@ -323,13 +323,10 @@ it.effect( | ... | @@ -323,13 +323,10 @@ it.effect( |
| 323 | 323 | ||
| 324 | const startedSession = yield* Effect.gen(function* () { | 324 | const startedSession = yield* Effect.gen(function* () { |
| 325 | const provider = yield* ProviderService; | 325 | const provider = yield* ProviderService; |
| 326 | return yield* provider.startSession( | 326 | return yield* provider.startSession(asThreadId("thread-1"), { |
| 327 | asThreadId("thread-1"), | 327 | provider: "codex", |
| 328 | { | 328 | cwd: "/tmp/project", |
| 329 | provider: "codex", | 329 | }); |
| 330 | cwd: "/tmp/project", | ||
| 331 | }, | ||
| 332 | ); | ||
| 333 | }).pipe(Effect.provide(firstProviderLayer)); | 330 | }).pipe(Effect.provide(firstProviderLayer)); |
| 334 | 331 | ||
| 335 | yield* Effect.gen(function* () { | 332 | yield* Effect.gen(function* () { |
| ... | @@ -398,13 +395,10 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -398,13 +395,10 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 398 | Effect.gen(function* () { | 395 | Effect.gen(function* () { |
| 399 | const provider = yield* ProviderService; | 396 | const provider = yield* ProviderService; |
| 400 | 397 | ||
| 401 | const session = yield* provider.startSession( | 398 | const session = yield* provider.startSession(asThreadId("thread-1"), { |
| 402 | asThreadId("thread-1"), | 399 | provider: "codex", |
| 403 | { | 400 | cwd: "/tmp/project", |
| 404 | provider: "codex", | 401 | }); |
| 405 | cwd: "/tmp/project", | ||
| 406 | }, | ||
| 407 | ); | ||
| 408 | assert.equal(session.provider, "codex"); | 402 | assert.equal(session.provider, "codex"); |
| 409 | 403 | ||
| 410 | const sessions = yield* provider.listSessions(); | 404 | const sessions = yield* provider.listSessions(); |
| ... | @@ -453,13 +447,10 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -453,13 +447,10 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 453 | Effect.gen(function* () { | 447 | Effect.gen(function* () { |
| 454 | const provider = yield* ProviderService; | 448 | const provider = yield* ProviderService; |
| 455 | 449 | ||
| 456 | const initial = yield* provider.startSession( | 450 | const initial = yield* provider.startSession(asThreadId("thread-1"), { |
| 457 | asThreadId("thread-1"), | 451 | provider: "codex", |
| 458 | { | 452 | cwd: "/tmp/project", |
| 459 | provider: "codex", | 453 | }); |
| 460 | cwd: "/tmp/project", | ||
| 461 | }, | ||
| 462 | ); | ||
| 463 | yield* routing.codex.stopSession(initial.sessionId); | 454 | yield* routing.codex.stopSession(initial.sessionId); |
| 464 | routing.codex.startSession.mockClear(); | 455 | routing.codex.startSession.mockClear(); |
| 465 | routing.codex.rollbackThread.mockClear(); | 456 | routing.codex.rollbackThread.mockClear(); |
| ... | @@ -487,18 +478,12 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -487,18 +478,12 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 487 | Effect.gen(function* () { | 478 | Effect.gen(function* () { |
| 488 | const provider = yield* ProviderService; | 479 | const provider = yield* ProviderService; |
| 489 | 480 | ||
| 490 | yield* provider.startSession( | 481 | yield* provider.startSession(asThreadId("thread-1"), { |
| 491 | asThreadId("thread-1"), | 482 | provider: "codex", |
| 492 | { | 483 | }); |
| 493 | provider: "codex", | 484 | yield* provider.startSession(asThreadId("thread-2"), { |
| 494 | }, | 485 | provider: "codex", |
| 495 | ); | 486 | }); |
| 496 | yield* provider.startSession( | ||
| 497 | asThreadId("thread-2"), | ||
| 498 | { | ||
| 499 | provider: "codex", | ||
| 500 | }, | ||
| 501 | ); | ||
| 502 | 487 | ||
| 503 | yield* provider.stopAll(); | 488 | yield* provider.stopAll(); |
| 504 | 489 | ||
| ... | @@ -512,12 +497,9 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -512,12 +497,9 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 512 | const provider = yield* ProviderService; | 497 | const provider = yield* ProviderService; |
| 513 | const runtimeRepository = yield* ProviderSessionRuntimeRepository; | 498 | const runtimeRepository = yield* ProviderSessionRuntimeRepository; |
| 514 | 499 | ||
| 515 | const session = yield* provider.startSession( | 500 | const session = yield* provider.startSession(asThreadId("thread-1"), { |
| 516 | asThreadId("thread-1"), | 501 | provider: "codex", |
| 517 | { | 502 | }); |
| 518 | provider: "codex", | ||
| 519 | }, | ||
| 520 | ); | ||
| 521 | yield* provider.sendTurn({ | 503 | yield* provider.sendTurn({ |
| 522 | sessionId: session.sessionId, | 504 | sessionId: session.sessionId, |
| 523 | input: "hello", | 505 | input: "hello", |
| ... | @@ -566,12 +548,9 @@ fanout.layer("ProviderServiceLive fanout", (it) => { | ... | @@ -566,12 +548,9 @@ fanout.layer("ProviderServiceLive fanout", (it) => { |
| 566 | it.effect("fans out adapter turn completion events", () => | 548 | it.effect("fans out adapter turn completion events", () => |
| 567 | Effect.gen(function* () { | 549 | Effect.gen(function* () { |
| 568 | const provider = yield* ProviderService; | 550 | const provider = yield* ProviderService; |
| 569 | const session = yield* provider.startSession( | 551 | const session = yield* provider.startSession(asThreadId("thread-1"), { |
| 570 | asThreadId("thread-1"), | 552 | provider: "codex", |
| 571 | { | 553 | }); |
| 572 | provider: "codex", | ||
| 573 | }, | ||
| 574 | ); | ||
| 575 | 554 | ||
| 576 | const eventsRef = yield* Ref.make<Array<ProviderRuntimeEvent>>([]); | 555 | const eventsRef = yield* Ref.make<Array<ProviderRuntimeEvent>>([]); |
| 577 | const consumer = yield* Stream.runForEach(provider.streamEvents, (event) => | 556 | const consumer = yield* Stream.runForEach(provider.streamEvents, (event) => |
| ... | @@ -606,12 +585,9 @@ fanout.layer("ProviderServiceLive fanout", (it) => { | ... | @@ -606,12 +585,9 @@ fanout.layer("ProviderServiceLive fanout", (it) => { |
| 606 | it.effect("keeps subscriber delivery ordered and isolates failing subscribers", () => | 585 | it.effect("keeps subscriber delivery ordered and isolates failing subscribers", () => |
| 607 | Effect.gen(function* () { | 586 | Effect.gen(function* () { |
| 608 | const provider = yield* ProviderService; | 587 | const provider = yield* ProviderService; |
| 609 | const session = yield* provider.startSession( | 588 | const session = yield* provider.startSession(asThreadId("thread-1"), { |
| 610 | asThreadId("thread-1"), | 589 | provider: "codex", |
| 611 | { | 590 | }); |
| 612 | provider: "codex", | ||
| 613 | }, | ||
| 614 | ); | ||
| 615 | 591 | ||
| 616 | const receivedByHealthy: string[] = []; | 592 | const receivedByHealthy: string[] = []; |
| 617 | const expectedEventIds = new Set<string>(["evt-ordered-1", "evt-ordered-2", "evt-ordered-3"]); | 593 | const expectedEventIds = new Set<string>(["evt-ordered-1", "evt-ordered-2", "evt-ordered-3"]); |
| ... | @@ -686,12 +662,9 @@ validation.layer("ProviderServiceLive validation", (it) => { | ... | @@ -686,12 +662,9 @@ validation.layer("ProviderServiceLive validation", (it) => { |
| 686 | const provider = yield* ProviderService; | 662 | const provider = yield* ProviderService; |
| 687 | 663 | ||
| 688 | const failure = yield* Effect.result( | 664 | const failure = yield* Effect.result( |
| 689 | provider.startSession( | 665 | provider.startSession(asThreadId("thread-validation"), { |
| 690 | asThreadId("thread-validation"), | 666 | provider: "invalid-provider", |
| 691 | { | 667 | } as never), |
| 692 | provider: "invalid-provider", | ||
| 693 | } as never, | ||
| 694 | ), | ||
| 695 | ); | 668 | ); |
| 696 | 669 | ||
| 697 | assert.equal(failure._tag, "Failure"); | 670 | assert.equal(failure._tag, "Failure"); |
| ... | @@ -726,13 +699,10 @@ validation.layer("ProviderServiceLive validation", (it) => { | ... | @@ -726,13 +699,10 @@ validation.layer("ProviderServiceLive validation", (it) => { |
| 726 | ); | 699 | ); |
| 727 | 700 | ||
| 728 | const failure = yield* Effect.result( | 701 | const failure = yield* Effect.result( |
| 729 | provider.startSession( | 702 | provider.startSession(asThreadId("thread-missing"), { |
| 730 | asThreadId("thread-missing"), | 703 | provider: "codex", |
| 731 | { | 704 | cwd: "/tmp/project", |
| 732 | provider: "codex", | 705 | }), |
| 733 | cwd: "/tmp/project", | ||
| 734 | }, | ||
| 735 | ), | ||
| 736 | ); | 706 | ); |
| 737 | 707 | ||
| 738 | assertFailure( | 708 | assertFailure( |
apps/server/src/terminal/Layers/Manager.ts+5-1| ... | @@ -415,7 +415,11 @@ export class TerminalManagerRuntime extends EventEmitter<TerminalManagerEvents> | ... | @@ -415,7 +415,11 @@ export class TerminalManagerRuntime extends EventEmitter<TerminalManagerEvents> |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | if (!existing.process) { | 417 | 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 | ); | ||
| 419 | return this.snapshot(existing); | 423 | return this.snapshot(existing); |
| 420 | } | 424 | } |
| 421 | 425 |
apps/server/src/wsServer.test.ts+9-3| ... | @@ -543,7 +543,9 @@ describe("WebSocket Server", () => { | ... | @@ -543,7 +543,9 @@ describe("WebSocket Server", () => { |
| 543 | issues: [], | 543 | issues: [], |
| 544 | }); | 544 | }); |
| 545 | 545 | ||
| 546 | const persistedConfig = JSON.parse(fs.readFileSync(keybindingsPath, "utf8")) as KeybindingsConfig; | 546 | const persistedConfig = JSON.parse( |
| 547 | fs.readFileSync(keybindingsPath, "utf8"), | ||
| 548 | ) as KeybindingsConfig; | ||
| 547 | expect(persistedConfig).toEqual(DEFAULT_KEYBINDINGS); | 549 | expect(persistedConfig).toEqual(DEFAULT_KEYBINDINGS); |
| 548 | }); | 550 | }); |
| 549 | 551 | ||
| ... | @@ -711,7 +713,9 @@ describe("WebSocket Server", () => { | ... | @@ -711,7 +713,9 @@ describe("WebSocket Server", () => { |
| 711 | 713 | ||
| 712 | const response = await sendRequest(ws, WS_METHODS.serverGetConfig); | 714 | const response = await sendRequest(ws, WS_METHODS.serverGetConfig); |
| 713 | expect(response.error).toBeUndefined(); | 715 | 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; | ||
| 715 | expect(response.result).toEqual({ | 719 | expect(response.result).toEqual({ |
| 716 | cwd: "/my/workspace", | 720 | cwd: "/my/workspace", |
| 717 | keybindingsConfigPath: keybindingsPath, | 721 | keybindingsConfigPath: keybindingsPath, |
| ... | @@ -742,7 +746,9 @@ describe("WebSocket Server", () => { | ... | @@ -742,7 +746,9 @@ describe("WebSocket Server", () => { |
| 742 | command: "script.run-tests.run", | 746 | command: "script.run-tests.run", |
| 743 | }); | 747 | }); |
| 744 | expect(upsertResponse.error).toBeUndefined(); | 748 | 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; | ||
| 746 | const persistedCommands = new Set(persistedConfig.map((entry) => entry.command)); | 752 | const persistedCommands = new Set(persistedConfig.map((entry) => entry.command)); |
| 747 | for (const defaultRule of DEFAULT_KEYBINDINGS) { | 753 | for (const defaultRule of DEFAULT_KEYBINDINGS) { |
| 748 | expect(persistedCommands.has(defaultRule.command)).toBe(true); | 754 | expect(persistedCommands.has(defaultRule.command)).toBe(true); |
apps/web/src/components/ProjectScriptsControl.tsx+14-3| ... | @@ -16,8 +16,15 @@ import { | ... | @@ -16,8 +16,15 @@ import { |
| 16 | } from "lucide-react"; | 16 | } from "lucide-react"; |
| 17 | import React, { type FormEvent, type KeyboardEvent, useMemo, useState } from "react"; | 17 | import React, { type FormEvent, type KeyboardEvent, useMemo, useState } from "react"; |
| 18 | 18 | ||
| 19 | import { keybindingValueForCommand, decodeProjectScriptKeybindingRule } from "~/lib/projectScriptKeybindings"; | 19 | import { |
| 20 | import { commandForProjectScript, nextProjectScriptId, primaryProjectScript } from "~/projectScripts"; | 20 | keybindingValueForCommand, |
| 21 | decodeProjectScriptKeybindingRule, | ||
| 22 | } from "~/lib/projectScriptKeybindings"; | ||
| 23 | import { | ||
| 24 | commandForProjectScript, | ||
| 25 | nextProjectScriptId, | ||
| 26 | primaryProjectScript, | ||
| 27 | } from "~/projectScripts"; | ||
| 21 | import { shortcutLabelForCommand } from "~/keybindings"; | 28 | import { shortcutLabelForCommand } from "~/keybindings"; |
| 22 | import { isMacPlatform } from "~/lib/utils"; | 29 | import { isMacPlatform } from "~/lib/utils"; |
| 23 | import { Button } from "./ui/button"; | 30 | import { Button } from "./ui/button"; |
| ... | @@ -188,7 +195,11 @@ export default function ProjectScriptsControl({ | ... | @@ -188,7 +195,11 @@ export default function ProjectScriptsControl({ |
| 188 | setValidationError(null); | 195 | setValidationError(null); |
| 189 | try { | 196 | try { |
| 190 | const scriptIdForValidation = | 197 | const scriptIdForValidation = |
| 191 | editingScriptId ?? nextProjectScriptId(trimmedName, scripts.map((script) => script.id)); | 198 | editingScriptId ?? |
| 199 | nextProjectScriptId( | ||
| 200 | trimmedName, | ||
| 201 | scripts.map((script) => script.id), | ||
| 202 | ); | ||
| 192 | const keybindingRule = decodeProjectScriptKeybindingRule({ | 203 | const keybindingRule = decodeProjectScriptKeybindingRule({ |
| 193 | keybinding, | 204 | keybinding, |
| 194 | command: commandForProjectScript(scriptIdForValidation), | 205 | command: commandForProjectScript(scriptIdForValidation), |
apps/web/src/routes/__root.tsx+1-4| ... | @@ -201,10 +201,7 @@ function EventRouter() { | ... | @@ -201,10 +201,7 @@ function EventRouter() { |
| 201 | void queryClient | 201 | void queryClient |
| 202 | .ensureQueryData(serverConfigQueryOptions()) | 202 | .ensureQueryData(serverConfigQueryOptions()) |
| 203 | .then((config) => | 203 | .then((config) => |
| 204 | api.shell.openInEditor( | 204 | api.shell.openInEditor(config.keybindingsConfigPath, preferredTerminalEditor()), |
| 205 | config.keybindingsConfigPath, | ||
| 206 | preferredTerminalEditor(), | ||
| 207 | ), | ||
| 208 | ) | 205 | ) |
| 209 | .catch((error) => { | 206 | .catch((error) => { |
| 210 | toastManager.add({ | 207 | toastManager.add({ |
apps/web/src/routes/_chat.settings.tsx+2-2| ... | @@ -241,8 +241,8 @@ function SettingsRouteView() { | ... | @@ -241,8 +241,8 @@ function SettingsRouteView() { |
| 241 | <div className="mb-4"> | 241 | <div className="mb-4"> |
| 242 | <h2 className="text-sm font-medium text-foreground">Keybindings</h2> | 242 | <h2 className="text-sm font-medium text-foreground">Keybindings</h2> |
| 243 | <p className="mt-1 text-xs text-muted-foreground"> | 243 | <p className="mt-1 text-xs text-muted-foreground"> |
| 244 | Open the persisted <code>keybindings.json</code> file to edit advanced | 244 | Open the persisted <code>keybindings.json</code> file to edit advanced bindings |
| 245 | bindings directly. | 245 | directly. |
| 246 | </p> | 246 | </p> |
| 247 | </div> | 247 | </div> |
| 248 | 248 |
bun.lock+53-31| ... | @@ -5,8 +5,8 @@ | ... | @@ -5,8 +5,8 @@ |
| 5 | "": { | 5 | "": { |
| 6 | "name": "@t3tools/monorepo", | 6 | "name": "@t3tools/monorepo", |
| 7 | "devDependencies": { | 7 | "devDependencies": { |
| 8 | "oxfmt": "^0.28.0", | 8 | "oxfmt": "^0.35.0", |
| 9 | "oxlint": "^1.43.0", | 9 | "oxlint": "^1.50.0", |
| 10 | "turbo": "^2.3.3", | 10 | "turbo": "^2.3.3", |
| 11 | "typescript": "^5.7.3", | 11 | "typescript": "^5.7.3", |
| 12 | "vitest": "^4.0.0", | 12 | "vitest": "^4.0.0", |
| ... | @@ -301,59 +301,81 @@ | ... | @@ -301,59 +301,81 @@ |
| 301 | 301 | ||
| 302 | "@oxc-project/types": ["@oxc-project/types@0.112.0", "", {}, "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ=="], | 302 | "@oxc-project/types": ["@oxc-project/types@0.112.0", "", {}, "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ=="], |
| 303 | 303 | ||
| 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=="], |
| 305 | 305 | ||
| 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=="], |
| 307 | 307 | ||
| 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=="], |
| 309 | 309 | ||
| 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=="], |
| 311 | 311 | ||
| 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=="], |
| 313 | 313 | ||
| 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=="], |
| 315 | 315 | ||
| 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=="], |
| 317 | 317 | ||
| 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=="], |
| 319 | 319 | ||
| 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=="], |
| 321 | 321 | ||
| 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=="], |
| 323 | 323 | ||
| 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=="], |
| 325 | 325 | ||
| 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=="], |
| 327 | 327 | ||
| 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=="], |
| 329 | 329 | ||
| 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=="], |
| 331 | 331 | ||
| 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=="], |
| 333 | 333 | ||
| 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=="], |
| 335 | 335 | ||
| 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=="], |
| 337 | 337 | ||
| 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=="], |
| 339 | 339 | ||
| 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=="], |
| 341 | 341 | ||
| 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=="], |
| 343 | 343 | ||
| 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=="], |
| 345 | 345 | ||
| 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=="], |
| 347 | 347 | ||
| 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=="], |
| 349 | 349 | ||
| 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=="], |
| 351 | 351 | ||
| 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=="], |
| 353 | 353 | ||
| 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=="], |
| 355 | 355 | ||
| 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=="], | ||
| 357 | 379 | ||
| 358 | "@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=="], | 380 | "@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=="], |
| 359 | 381 | ||
| ... | @@ -1115,9 +1137,9 @@ | ... | @@ -1115,9 +1137,9 @@ |
| 1115 | 1137 | ||
| 1116 | "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="], | 1138 | "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="], |
| 1117 | 1139 | ||
| 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=="], |
| 1119 | 1141 | ||
| 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=="], |
| 1121 | 1143 | ||
| 1122 | "p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="], | 1144 | "p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="], |
| 1123 | 1145 |
package.json+2-2| ... | @@ -36,8 +36,8 @@ | ... | @@ -36,8 +36,8 @@ |
| 36 | "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs" | 36 | "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs" |
| 37 | }, | 37 | }, |
| 38 | "devDependencies": { | 38 | "devDependencies": { |
| 39 | "oxfmt": "^0.28.0", | 39 | "oxfmt": "^0.35.0", |
| 40 | "oxlint": "^1.43.0", | 40 | "oxlint": "^1.50.0", |
| 41 | "turbo": "^2.3.3", | 41 | "turbo": "^2.3.3", |
| 42 | "typescript": "^5.7.3", | 42 | "typescript": "^5.7.3", |
| 43 | "vitest": "^4.0.0" | 43 | "vitest": "^4.0.0" |