From 737b6eb7b7d70b6448d3143a61d0be5eb594d3c0 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 14 Aug 2026 13:05:24 -0400 Subject: [PATCH] chore: extract Drive and catalog (#42612) --- .github/workflows/deploy-lab-catalog.yml | 49 - .github/workflows/test.yml | 2 +- .opencode/skills/opencode-drive/SKILL.md | 253 - bun.lock | 356 +- package.json | 1 - packages/cli/script/service-smoke.ts | 45 - packages/cli/script/verify-artifact.ts | 6 +- .../cli/test/drive/mini-interactive.drive.mjs | 371 -- packages/cli/test/drive/run-smoke.drive.mjs | 87 - packages/drive/CHANGELOG.md | 89 - packages/drive/LICENSE | 21 - packages/drive/README.md | 565 --- packages/drive/RELEASING.md | 27 - .../commit-mono/CommitMono-400-Italic.otf | Bin 274500 -> 0 bytes .../commit-mono/CommitMono-400-Regular.otf | Bin 274752 -> 0 bytes .../commit-mono/CommitMono-700-Italic.otf | Bin 276000 -> 0 bytes .../commit-mono/CommitMono-700-Regular.otf | Bin 276188 -> 0 bytes .../assets/fonts/commit-mono/license.txt | 90 - .../fonts/noto/NotoSansMath-Regular.ttf | Bin 1015396 -> 0 bytes .../assets/fonts/noto/NotoSansSymbols.ttf | Bin 372684 -> 0 bytes .../fonts/noto/NotoSansSymbols2-Regular.ttf | Bin 1233128 -> 0 bytes packages/drive/assets/fonts/noto/license.txt | 93 - packages/drive/bin/opencode-drive | 2 - packages/drive/compile/public-api.ts | 46 - packages/drive/docs/open-code-driver-api.md | 500 -- .../docs/open-code-driver-architecture.md | 228 - packages/drive/examples/multiple-clients.ts | 58 - packages/drive/examples/serve.ts | 43 - packages/drive/examples/simple.ts | 32 - packages/drive/examples/viewport-resize.ts | 43 - packages/drive/package.json | 80 - packages/drive/src/cli/check.ts | 74 - packages/drive/src/cli/commands.ts | 220 - packages/drive/src/cli/dir.ts | 6 - packages/drive/src/cli/index.ts | 257 -- packages/drive/src/cli/init.ts | 10 - packages/drive/src/cli/list.ts | 6 - packages/drive/src/cli/mock-backend.ts | 72 - packages/drive/src/cli/parse.ts | 28 - packages/drive/src/cli/prune.ts | 41 - packages/drive/src/cli/response-generator.ts | 302 -- packages/drive/src/cli/restart.ts | 11 - packages/drive/src/cli/run.ts | 31 - packages/drive/src/cli/script-init.ts | 44 - packages/drive/src/cli/script.ts | 199 - packages/drive/src/cli/send.ts | 60 - packages/drive/src/cli/start.ts | 485 -- packages/drive/src/cli/stop.ts | 38 - packages/drive/src/cli/types.ts | 25 - packages/drive/src/client/index.ts | 11 - packages/drive/src/client/protocol.ts | 4 - packages/drive/src/driver/client.ts | 277 -- packages/drive/src/driver/error.ts | 14 - packages/drive/src/driver/index.ts | 152 - packages/drive/src/driver/llm-controller.ts | 409 -- packages/drive/src/driver/llm-errors.ts | 41 - packages/drive/src/driver/llm-responder.ts | 235 - packages/drive/src/driver/llm-state.ts | 299 -- packages/drive/src/driver/llm.ts | 9 - packages/drive/src/driver/opencode.ts | 55 - packages/drive/src/driver/prepared.ts | 121 - packages/drive/src/driver/project.ts | 44 - packages/drive/src/driver/report.ts | 30 - packages/drive/src/driver/screenshot.ts | 15 - packages/drive/src/driver/server.ts | 228 - packages/drive/src/driver/shared.ts | 26 - packages/drive/src/driver/ui.ts | 424 -- packages/drive/src/frame/index.ts | 162 - packages/drive/src/globals.d.ts | 3 - packages/drive/src/index.ts | 8 - packages/drive/src/instance/control.ts | 162 - .../drive/src/instance/default-config.jsonc | 34 - packages/drive/src/instance/dev.ts | 37 - packages/drive/src/instance/error.ts | 15 - packages/drive/src/instance/instance.ts | 114 - packages/drive/src/instance/media.ts | 16 - packages/drive/src/instance/process.ts | 228 - packages/drive/src/instance/readiness.ts | 68 - packages/drive/src/instance/registry.ts | 317 -- packages/drive/src/instance/runtime.ts | 534 --- packages/drive/src/instance/service.ts | 53 - packages/drive/src/llm/index.ts | 100 - packages/drive/src/llm/internal.ts | 40 - packages/drive/src/log.ts | 72 - packages/drive/src/project.ts | 46 - packages/drive/src/recording/decode.ts | 109 - packages/drive/src/recording/encode.ts | 98 - packages/drive/src/recording/export.ts | 87 - packages/drive/src/recording/ffmpeg.ts | 24 - packages/drive/src/recording/finalize.ts | 14 - packages/drive/src/recording/frame-rate.ts | 6 - packages/drive/src/recording/index.ts | 14 - packages/drive/src/recording/render.ts | 147 - packages/drive/src/recording/replay.ts | 99 - packages/drive/src/recording/terminal.ts | 120 - packages/drive/src/recording/types.ts | 48 - packages/drive/src/script/errors.ts | 19 - packages/drive/src/script/filesystem.ts | 97 - packages/drive/src/script/index.ts | 18 - packages/drive/src/script/project.ts | 72 - packages/drive/src/script/tooling.ts | 158 - packages/drive/src/script/types.ts | 83 - packages/drive/src/simulation/connector.ts | 349 -- .../drive/src/simulation/opencode-protocol.ts | 336 -- packages/drive/src/tool/controller.ts | 676 --- packages/drive/src/tool/index.ts | 1 - packages/drive/src/tool/plugin.js | 167 - packages/drive/src/tool/producer.ts | 831 ---- packages/drive/src/tool/types.ts | 202 - packages/drive/test/cli/check.test.ts | 29 - packages/drive/test/cli/integration.test.ts | 1831 -------- packages/drive/test/cli/parse.test.ts | 46 - packages/drive/test/cli/run.test.ts | 100 - packages/drive/test/driver/index.test.ts | 619 --- .../drive/test/driver/llm-controller.test.ts | 539 --- packages/drive/test/driver/llm-state.test.ts | 95 - packages/drive/test/driver/report.test.ts | 48 - packages/drive/test/driver/shared.test.ts | 20 - packages/drive/test/driver/ui.test.ts | 477 -- .../drive/test/fixtures/callback-script.ts | 1 - .../test/fixtures/caught-timeout-script.ts | 12 - .../drive/test/fixtures/crashing-script.ts | 14 - .../fixtures/failed-launch-retry-script.ts | 43 - packages/drive/test/fixtures/fake-opencode.ts | 383 -- .../drive/test/fixtures/hanging-script.ts | 9 - .../test/fixtures/kill-primary-script.ts | 12 - .../drive/test/fixtures/kill-server-script.ts | 57 - .../test/fixtures/manual-clients-script.ts | 52 - .../test/fixtures/prepared-git-script.ts | 32 - .../drive/test/fixtures/restart-script.ts | 26 - packages/drive/test/fixtures/script.ts | 50 - packages/drive/test/fixtures/serve-script.ts | 20 - packages/drive/test/fixtures/source-script.ts | 6 - packages/drive/test/fixtures/title-script.ts | 12 - .../test/fixtures/tool-control-script.ts | 51 - .../drive/test/fixtures/tui-options-script.ts | 19 - packages/drive/test/frame.test.ts | 73 - packages/drive/test/instance/config.test.ts | 162 - packages/drive/test/instance/dev.test.ts | 34 - packages/drive/test/instance/process.test.ts | 50 - packages/drive/test/instance/runtime.test.ts | 55 - packages/drive/test/llm.test.ts | 122 - .../test/manual/tui-regressions/README.md | 104 - .../initial-message-hydration.ts | 30 - .../tui-regressions/interaction-lifecycle.ts | 30 - .../tui-regressions/lifecycle-properties.ts | 616 --- .../multi-tool-interleavings.ts | 215 - .../tui-regressions/pending-form-restart.ts | 50 - .../tui-regressions/reconnect-outage.ts | 20 - .../manual/tui-regressions/server-restart.ts | 28 - .../manual/tui-regressions/state-machine.ts | 90 - packages/drive/test/recording/decode.test.ts | 70 - .../test/recording/export-dedupe.test.ts | 46 - packages/drive/test/recording/export.test.ts | 388 -- packages/drive/test/recording/replay.test.ts | 231 - packages/drive/test/script-filesystem.test.ts | 55 - packages/drive/test/script-project.test.ts | 128 - .../drive/test/simulation/backend.test.ts | 289 -- .../drive/test/simulation/connector.test.ts | 139 - .../drive/test/simulation/lifecycle.test.ts | 124 - .../test/simulation/opencode-protocol.test.ts | 139 - .../drive/test/simulation/protocol.test.ts | 98 - packages/drive/test/simulation/rpc.test.ts | 138 - .../drive/test/simulation/transport-peer.ts | 80 - packages/drive/test/simulation/ui.test.ts | 134 - packages/drive/test/tool/controller.test.ts | 952 ---- packages/drive/test/tool/producer.test.ts | 1393 ------ packages/drive/tsconfig.json | 10 - packages/drive/vitest.config.ts | 11 - packages/lab/catalog/.gitignore | 4 - .../miniflare-CacheObject/metadata.sqlite | Bin 4096 -> 0 bytes .../miniflare-CacheObject/metadata.sqlite-shm | Bin 32768 -> 0 bytes .../miniflare-CacheObject/metadata.sqlite-wal | Bin 8272 -> 0 bytes packages/lab/catalog/AGENTS.md | 145 - packages/lab/catalog/README.md | 235 - .../lab/catalog/catalog/authored/flows.ts | 116 - .../lab/catalog/catalog/authored/index.ts | 10 - .../lab/catalog/catalog/authored/screens.ts | 229 - .../catalog/catalog/authored/taxonomies.ts | 134 - .../lab/catalog/catalog/authoring.test.ts | 272 -- packages/lab/catalog/catalog/authoring.ts | 205 - .../catalog/catalog/authoring.typecheck.ts | 115 - .../lab/catalog/catalog/capture-sets.test.ts | 81 - .../lab/catalog/catalog/deep-link.test.ts | 34 - packages/lab/catalog/catalog/dsl.ts | 139 - packages/lab/catalog/catalog/feedback.test.ts | 57 - packages/lab/catalog/catalog/flow.test.ts | 119 - packages/lab/catalog/catalog/flow.ts | 241 - .../lab/catalog/catalog/font-coverage.test.ts | 22 - .../catalog/catalog/lifecycle-flows.test.ts | 75 - .../catalog/response-tool-flows.test.ts | 32 - packages/lab/catalog/catalog/schema.ts | 148 - .../lab/catalog/catalog/search-flows.test.ts | 25 - packages/lab/catalog/catalog/worker.test.ts | 56 - .../lab/catalog/compile/driver-consumer.ts | 22 - packages/lab/catalog/doctor.config.json | 6 - packages/lab/catalog/package.json | 40 - packages/lab/catalog/perf/capture-feedback.md | 74 - packages/lab/catalog/perf/capture-matrix.md | 31 - .../everforest/agent-picker.frame.json | 680 --- .../assistant-response-failed.frame.json | 517 --- .../assistant-response-interrupted.frame.json | 546 --- .../assistant-response-succeeded.frame.json | 476 -- .../everforest/command-palette.frame.json | 741 --- .../captures/everforest/debug.frame.json | 627 --- .../everforest/diff-viewer.frame.json | 460 -- .../captures/everforest/glob-empty.frame.json | 530 --- .../everforest/glob-success.frame.json | 486 -- .../captures/everforest/grep-empty.frame.json | 547 --- .../everforest/grep-failure.frame.json | 547 --- .../everforest/grep-success.frame.json | 547 --- .../everforest/grouped-exploration.frame.json | 547 --- .../captures/everforest/help.frame.json | 678 --- .../captures/everforest/home.frame.json | 616 --- .../everforest/integration-picker.frame.json | 729 --- .../captures/everforest/mcp-list.frame.json | 676 --- .../everforest/model-picker.frame.json | 687 --- .../captures/everforest/pair.frame.json | 813 ---- .../everforest/patch-created.frame.json | 498 -- .../everforest/patch-deleted.frame.json | 558 --- .../everforest/patch-failed.frame.json | 577 --- .../patch-input-streaming.frame.json | 481 -- .../everforest/patch-success.frame.json | 509 -- .../everforest/patch-updated.frame.json | 538 --- .../permission-always-confirmation.frame.json | 493 -- .../permission-always-selected.frame.json | 543 --- .../permission-fullscreen.frame.json | 558 --- .../everforest/permission-prompt.frame.json | 543 --- .../permission-reject-selected.frame.json | 542 --- .../question-awaiting-form.frame.json | 539 --- .../everforest/question-denied.frame.json | 582 --- .../question-input-streaming.frame.json | 478 -- .../everforest/question-prompt.frame.json | 586 --- .../everforest/question-review.frame.json | 498 -- .../everforest/question-succeeded.frame.json | 525 --- .../everforest/read-denied.frame.json | 575 --- .../read-input-streaming.frame.json | 478 -- .../everforest/read-permission.frame.json | 505 -- .../everforest/read-succeeded.frame.json | 486 -- .../everforest/session-export.frame.json | 647 --- .../everforest/session-fork.frame.json | 574 --- .../session-picker-populated.frame.json | 620 --- .../everforest/session-picker.frame.json | 628 --- .../everforest/session-rename.frame.json | 602 --- .../everforest/session-tabs-idle.frame.json | 481 -- .../session-tabs-running.frame.json | 472 -- .../shell-execute-failed.frame.json | 556 --- .../shell-execute-succeeded.frame.json | 520 --- .../shell-input-streaming.frame.json | 489 -- .../shell-output-streaming.frame.json | 495 -- .../everforest/skill-picker.frame.json | 619 --- .../captures/everforest/status.frame.json | 669 --- .../everforest/subagent-completed.frame.json | 494 -- .../everforest/subagent-running.frame.json | 478 -- .../everforest/subagent-session.frame.json | 507 -- .../everforest/theme-picker.frame.json | 727 --- .../everforest/thinking-streaming.frame.json | 469 -- .../everforest/toast-error.frame.json | 593 --- .../captures/everforest/toast-info.frame.json | 686 --- .../everforest/toast-success.frame.json | 593 --- .../everforest/webfetch-streaming.frame.json | 475 -- .../everforest/webfetch-success.frame.json | 483 -- .../everforest/websearch-failure.frame.json | 529 --- .../everforest/websearch-running.frame.json | 518 --- .../captures/opencode/agent-picker.frame.json | 684 --- .../assistant-response-failed.frame.json | 517 --- .../assistant-response-interrupted.frame.json | 548 --- .../assistant-response-succeeded.frame.json | 476 -- .../opencode/command-palette.frame.json | 741 --- .../public/captures/opencode/debug.frame.json | 555 --- .../captures/opencode/diff-viewer.frame.json | 460 -- .../captures/opencode/glob-empty.frame.json | 530 --- .../captures/opencode/glob-success.frame.json | 486 -- .../captures/opencode/grep-empty.frame.json | 547 --- .../captures/opencode/grep-failure.frame.json | 547 --- .../captures/opencode/grep-success.frame.json | 547 --- .../opencode/grouped-exploration.frame.json | 547 --- .../public/captures/opencode/help.frame.json | 682 --- .../public/captures/opencode/home.frame.json | 616 --- .../opencode/integration-picker.frame.json | 729 --- .../captures/opencode/mcp-list.frame.json | 680 --- .../captures/opencode/model-picker.frame.json | 691 --- .../public/captures/opencode/pair.frame.json | 669 --- .../opencode/patch-created.frame.json | 498 -- .../opencode/patch-deleted.frame.json | 557 --- .../captures/opencode/patch-failed.frame.json | 576 --- .../opencode/patch-input-streaming.frame.json | 481 -- .../opencode/patch-success.frame.json | 509 -- .../opencode/patch-updated.frame.json | 537 --- .../permission-always-confirmation.frame.json | 494 -- .../permission-always-selected.frame.json | 543 --- .../opencode/permission-fullscreen.frame.json | 556 --- .../opencode/permission-prompt.frame.json | 542 --- .../permission-reject-selected.frame.json | 543 --- .../question-awaiting-form.frame.json | 539 --- .../opencode/question-denied.frame.json | 582 --- .../question-input-streaming.frame.json | 478 -- .../opencode/question-prompt.frame.json | 586 --- .../opencode/question-review.frame.json | 498 -- .../opencode/question-succeeded.frame.json | 525 --- .../captures/opencode/read-denied.frame.json | 575 --- .../opencode/read-input-streaming.frame.json | 478 -- .../opencode/read-permission.frame.json | 509 -- .../opencode/read-succeeded.frame.json | 486 -- .../opencode/session-export.frame.json | 647 --- .../captures/opencode/session-fork.frame.json | 550 --- .../session-picker-populated.frame.json | 608 --- .../opencode/session-picker.frame.json | 578 --- .../opencode/session-rename.frame.json | 602 --- .../opencode/session-tabs-idle.frame.json | 482 -- .../opencode/session-tabs-running.frame.json | 474 -- .../opencode/shell-execute-failed.frame.json | 557 --- .../shell-execute-succeeded.frame.json | 520 --- .../opencode/shell-input-streaming.frame.json | 494 -- .../shell-output-streaming.frame.json | 492 -- .../captures/opencode/skill-picker.frame.json | 569 --- .../captures/opencode/status.frame.json | 673 --- .../opencode/subagent-completed.frame.json | 496 -- .../opencode/subagent-running.frame.json | 480 -- .../opencode/subagent-session.frame.json | 506 -- .../captures/opencode/theme-picker.frame.json | 715 --- .../opencode/thinking-streaming.frame.json | 470 -- .../captures/opencode/toast-error.frame.json | 593 --- .../captures/opencode/toast-info.frame.json | 674 --- .../opencode/toast-success.frame.json | 593 --- .../opencode/webfetch-streaming.frame.json | 473 -- .../opencode/webfetch-success.frame.json | 486 -- .../opencode/websearch-failure.frame.json | 527 --- .../opencode/websearch-running.frame.json | 517 --- .../tokyonight/agent-picker.frame.json | 680 --- .../assistant-response-failed.frame.json | 517 --- .../assistant-response-interrupted.frame.json | 547 --- .../assistant-response-succeeded.frame.json | 476 -- .../tokyonight/command-palette.frame.json | 741 --- .../captures/tokyonight/debug.frame.json | 627 --- .../tokyonight/diff-viewer.frame.json | 460 -- .../captures/tokyonight/glob-empty.frame.json | 530 --- .../tokyonight/glob-success.frame.json | 486 -- .../captures/tokyonight/grep-empty.frame.json | 547 --- .../tokyonight/grep-failure.frame.json | 547 --- .../tokyonight/grep-success.frame.json | 547 --- .../tokyonight/grouped-exploration.frame.json | 547 --- .../captures/tokyonight/help.frame.json | 678 --- .../captures/tokyonight/home.frame.json | 616 --- .../tokyonight/integration-picker.frame.json | 729 --- .../captures/tokyonight/mcp-list.frame.json | 676 --- .../tokyonight/model-picker.frame.json | 687 --- .../captures/tokyonight/pair.frame.json | 813 ---- .../tokyonight/patch-created.frame.json | 499 -- .../tokyonight/patch-deleted.frame.json | 557 --- .../tokyonight/patch-failed.frame.json | 577 --- .../patch-input-streaming.frame.json | 481 -- .../tokyonight/patch-success.frame.json | 509 -- .../tokyonight/patch-updated.frame.json | 537 --- .../permission-always-confirmation.frame.json | 495 -- .../permission-always-selected.frame.json | 546 --- .../permission-fullscreen.frame.json | 556 --- .../tokyonight/permission-prompt.frame.json | 545 --- .../permission-reject-selected.frame.json | 543 --- .../question-awaiting-form.frame.json | 539 --- .../tokyonight/question-denied.frame.json | 582 --- .../question-input-streaming.frame.json | 478 -- .../tokyonight/question-prompt.frame.json | 586 --- .../tokyonight/question-review.frame.json | 498 -- .../tokyonight/question-succeeded.frame.json | 525 --- .../tokyonight/read-denied.frame.json | 575 --- .../read-input-streaming.frame.json | 477 -- .../tokyonight/read-permission.frame.json | 504 -- .../tokyonight/read-succeeded.frame.json | 486 -- .../tokyonight/session-export.frame.json | 647 --- .../tokyonight/session-fork.frame.json | 574 --- .../session-picker-populated.frame.json | 620 --- .../tokyonight/session-picker.frame.json | 628 --- .../tokyonight/session-rename.frame.json | 602 --- .../tokyonight/session-tabs-idle.frame.json | 483 -- .../session-tabs-running.frame.json | 472 -- .../shell-execute-failed.frame.json | 557 --- .../shell-execute-succeeded.frame.json | 520 --- .../shell-input-streaming.frame.json | 488 -- .../shell-output-streaming.frame.json | 491 -- .../tokyonight/skill-picker.frame.json | 619 --- .../captures/tokyonight/status.frame.json | 669 --- .../tokyonight/subagent-completed.frame.json | 497 -- .../tokyonight/subagent-running.frame.json | 481 -- .../tokyonight/subagent-session.frame.json | 506 -- .../tokyonight/theme-picker.frame.json | 715 --- .../tokyonight/thinking-streaming.frame.json | 469 -- .../tokyonight/toast-error.frame.json | 593 --- .../captures/tokyonight/toast-info.frame.json | 686 --- .../tokyonight/toast-success.frame.json | 593 --- .../tokyonight/webfetch-streaming.frame.json | 474 -- .../tokyonight/webfetch-success.frame.json | 486 -- .../tokyonight/websearch-failure.frame.json | 527 --- .../tokyonight/websearch-running.frame.json | 517 --- packages/lab/catalog/public/catalog.json | 4075 ----------------- .../lab/catalog/public/drive-captures.json | 1660 ------- packages/lab/catalog/scenarios/index.ts | 77 - .../responses/assistant-lifecycle.ts | 84 - packages/lab/catalog/scenarios/runtime.ts | 55 - .../lab/catalog/scenarios/session-tabs.ts | 53 - .../scenarios/subagents/subagent-lifecycle.ts | 131 - .../scenarios/tools/patch-file-changes.ts | 107 - .../catalog/scenarios/tools/patch-success.ts | 181 - .../scenarios/tools/question-lifecycle.ts | 144 - .../catalog/scenarios/tools/read-lifecycle.ts | 83 - .../scenarios/tools/search-lifecycle.ts | 147 - .../scenarios/tools/shell-lifecycle.ts | 127 - .../catalog/scenarios/tools/web-lifecycle.ts | 112 - .../lab/catalog/scripts/bench-capture-flow.ts | 51 - .../catalog/scripts/bench-capture-matrix.ts | 25 - .../catalog/scripts/capture-opencode-drive.ts | 525 --- packages/lab/catalog/scripts/capture-sets.ts | 90 - .../lab/catalog/scripts/generate-catalog.ts | 73 - packages/lab/catalog/scripts/generate-og.ts | 209 - .../lab/catalog/scripts/reproduce-state.ts | 52 - packages/lab/catalog/server.ts | 51 - packages/lab/catalog/src/App.tsx | 532 --- packages/lab/catalog/src/annotations.ts | 82 - packages/lab/catalog/src/base-path.ts | 3 - packages/lab/catalog/src/catalog.ts | 133 - .../src/components/AnnotationEditor.tsx | 185 - .../src/components/CaptureActionsMenu.tsx | 42 - .../src/components/CaptureContextMenu.tsx | 83 - .../src/components/CaptureSetSwitcher.tsx | 30 - .../catalog/src/components/CommandPalette.tsx | 264 -- .../catalog/src/components/ContactSheet.tsx | 159 - .../lab/catalog/src/components/FilterBar.tsx | 105 - .../lab/catalog/src/components/FilterMenu.tsx | 99 - .../catalog/src/components/FlowBrowser.tsx | 136 - .../lab/catalog/src/components/Header.tsx | 89 - .../src/components/MatrixNavigation.tsx | 29 - .../catalog/src/components/TerminalFrame.tsx | 154 - .../lab/catalog/src/components/Viewer.tsx | 251 - packages/lab/catalog/src/deep-link.ts | 73 - packages/lab/catalog/src/feedback.ts | 48 - packages/lab/catalog/src/globals.d.ts | 6 - packages/lab/catalog/src/index.html | 13 - packages/lab/catalog/src/main.tsx | 28 - packages/lab/catalog/src/styles.css | 1989 -------- packages/lab/catalog/tsconfig.json | 18 - packages/lab/catalog/worker.ts | 82 - packages/lab/catalog/wrangler.jsonc | 19 - packages/simulation/package.json | 1 + script/publish.ts | 4 +- scripts/drive-mermaid-visual.ts | 75 - turbo.json | 8 - 446 files changed, 24 insertions(+), 148422 deletions(-) delete mode 100644 .github/workflows/deploy-lab-catalog.yml delete mode 100644 .opencode/skills/opencode-drive/SKILL.md delete mode 100644 packages/cli/test/drive/mini-interactive.drive.mjs delete mode 100644 packages/cli/test/drive/run-smoke.drive.mjs delete mode 100644 packages/drive/CHANGELOG.md delete mode 100644 packages/drive/LICENSE delete mode 100644 packages/drive/README.md delete mode 100644 packages/drive/RELEASING.md delete mode 100644 packages/drive/assets/fonts/commit-mono/CommitMono-400-Italic.otf delete mode 100644 packages/drive/assets/fonts/commit-mono/CommitMono-400-Regular.otf delete mode 100644 packages/drive/assets/fonts/commit-mono/CommitMono-700-Italic.otf delete mode 100644 packages/drive/assets/fonts/commit-mono/CommitMono-700-Regular.otf delete mode 100644 packages/drive/assets/fonts/commit-mono/license.txt delete mode 100644 packages/drive/assets/fonts/noto/NotoSansMath-Regular.ttf delete mode 100644 packages/drive/assets/fonts/noto/NotoSansSymbols.ttf delete mode 100644 packages/drive/assets/fonts/noto/NotoSansSymbols2-Regular.ttf delete mode 100644 packages/drive/assets/fonts/noto/license.txt delete mode 100755 packages/drive/bin/opencode-drive delete mode 100644 packages/drive/compile/public-api.ts delete mode 100644 packages/drive/docs/open-code-driver-api.md delete mode 100644 packages/drive/docs/open-code-driver-architecture.md delete mode 100644 packages/drive/examples/multiple-clients.ts delete mode 100644 packages/drive/examples/serve.ts delete mode 100644 packages/drive/examples/simple.ts delete mode 100644 packages/drive/examples/viewport-resize.ts delete mode 100644 packages/drive/package.json delete mode 100644 packages/drive/src/cli/check.ts delete mode 100644 packages/drive/src/cli/commands.ts delete mode 100644 packages/drive/src/cli/dir.ts delete mode 100644 packages/drive/src/cli/index.ts delete mode 100644 packages/drive/src/cli/init.ts delete mode 100644 packages/drive/src/cli/list.ts delete mode 100644 packages/drive/src/cli/mock-backend.ts delete mode 100644 packages/drive/src/cli/parse.ts delete mode 100644 packages/drive/src/cli/prune.ts delete mode 100644 packages/drive/src/cli/response-generator.ts delete mode 100644 packages/drive/src/cli/restart.ts delete mode 100644 packages/drive/src/cli/run.ts delete mode 100644 packages/drive/src/cli/script-init.ts delete mode 100644 packages/drive/src/cli/script.ts delete mode 100644 packages/drive/src/cli/send.ts delete mode 100644 packages/drive/src/cli/start.ts delete mode 100644 packages/drive/src/cli/stop.ts delete mode 100644 packages/drive/src/cli/types.ts delete mode 100644 packages/drive/src/client/index.ts delete mode 100644 packages/drive/src/client/protocol.ts delete mode 100644 packages/drive/src/driver/client.ts delete mode 100644 packages/drive/src/driver/error.ts delete mode 100644 packages/drive/src/driver/index.ts delete mode 100644 packages/drive/src/driver/llm-controller.ts delete mode 100644 packages/drive/src/driver/llm-errors.ts delete mode 100644 packages/drive/src/driver/llm-responder.ts delete mode 100644 packages/drive/src/driver/llm-state.ts delete mode 100644 packages/drive/src/driver/llm.ts delete mode 100644 packages/drive/src/driver/opencode.ts delete mode 100644 packages/drive/src/driver/prepared.ts delete mode 100644 packages/drive/src/driver/project.ts delete mode 100644 packages/drive/src/driver/report.ts delete mode 100644 packages/drive/src/driver/screenshot.ts delete mode 100644 packages/drive/src/driver/server.ts delete mode 100644 packages/drive/src/driver/shared.ts delete mode 100644 packages/drive/src/driver/ui.ts delete mode 100644 packages/drive/src/frame/index.ts delete mode 100644 packages/drive/src/globals.d.ts delete mode 100644 packages/drive/src/index.ts delete mode 100644 packages/drive/src/instance/control.ts delete mode 100644 packages/drive/src/instance/default-config.jsonc delete mode 100644 packages/drive/src/instance/dev.ts delete mode 100644 packages/drive/src/instance/error.ts delete mode 100644 packages/drive/src/instance/instance.ts delete mode 100644 packages/drive/src/instance/media.ts delete mode 100644 packages/drive/src/instance/process.ts delete mode 100644 packages/drive/src/instance/readiness.ts delete mode 100644 packages/drive/src/instance/registry.ts delete mode 100644 packages/drive/src/instance/runtime.ts delete mode 100644 packages/drive/src/instance/service.ts delete mode 100644 packages/drive/src/llm/index.ts delete mode 100644 packages/drive/src/llm/internal.ts delete mode 100644 packages/drive/src/log.ts delete mode 100644 packages/drive/src/project.ts delete mode 100644 packages/drive/src/recording/decode.ts delete mode 100644 packages/drive/src/recording/encode.ts delete mode 100644 packages/drive/src/recording/export.ts delete mode 100644 packages/drive/src/recording/ffmpeg.ts delete mode 100644 packages/drive/src/recording/finalize.ts delete mode 100644 packages/drive/src/recording/frame-rate.ts delete mode 100644 packages/drive/src/recording/index.ts delete mode 100644 packages/drive/src/recording/render.ts delete mode 100644 packages/drive/src/recording/replay.ts delete mode 100644 packages/drive/src/recording/terminal.ts delete mode 100644 packages/drive/src/recording/types.ts delete mode 100644 packages/drive/src/script/errors.ts delete mode 100644 packages/drive/src/script/filesystem.ts delete mode 100644 packages/drive/src/script/index.ts delete mode 100644 packages/drive/src/script/project.ts delete mode 100644 packages/drive/src/script/tooling.ts delete mode 100644 packages/drive/src/script/types.ts delete mode 100644 packages/drive/src/simulation/connector.ts delete mode 100644 packages/drive/src/simulation/opencode-protocol.ts delete mode 100644 packages/drive/src/tool/controller.ts delete mode 100644 packages/drive/src/tool/index.ts delete mode 100644 packages/drive/src/tool/plugin.js delete mode 100644 packages/drive/src/tool/producer.ts delete mode 100644 packages/drive/src/tool/types.ts delete mode 100644 packages/drive/test/cli/check.test.ts delete mode 100644 packages/drive/test/cli/integration.test.ts delete mode 100644 packages/drive/test/cli/parse.test.ts delete mode 100644 packages/drive/test/cli/run.test.ts delete mode 100644 packages/drive/test/driver/index.test.ts delete mode 100644 packages/drive/test/driver/llm-controller.test.ts delete mode 100644 packages/drive/test/driver/llm-state.test.ts delete mode 100644 packages/drive/test/driver/report.test.ts delete mode 100644 packages/drive/test/driver/shared.test.ts delete mode 100644 packages/drive/test/driver/ui.test.ts delete mode 100644 packages/drive/test/fixtures/callback-script.ts delete mode 100644 packages/drive/test/fixtures/caught-timeout-script.ts delete mode 100644 packages/drive/test/fixtures/crashing-script.ts delete mode 100644 packages/drive/test/fixtures/failed-launch-retry-script.ts delete mode 100644 packages/drive/test/fixtures/fake-opencode.ts delete mode 100644 packages/drive/test/fixtures/hanging-script.ts delete mode 100644 packages/drive/test/fixtures/kill-primary-script.ts delete mode 100644 packages/drive/test/fixtures/kill-server-script.ts delete mode 100644 packages/drive/test/fixtures/manual-clients-script.ts delete mode 100644 packages/drive/test/fixtures/prepared-git-script.ts delete mode 100644 packages/drive/test/fixtures/restart-script.ts delete mode 100644 packages/drive/test/fixtures/script.ts delete mode 100644 packages/drive/test/fixtures/serve-script.ts delete mode 100644 packages/drive/test/fixtures/source-script.ts delete mode 100644 packages/drive/test/fixtures/title-script.ts delete mode 100644 packages/drive/test/fixtures/tool-control-script.ts delete mode 100644 packages/drive/test/fixtures/tui-options-script.ts delete mode 100644 packages/drive/test/frame.test.ts delete mode 100644 packages/drive/test/instance/config.test.ts delete mode 100644 packages/drive/test/instance/dev.test.ts delete mode 100644 packages/drive/test/instance/process.test.ts delete mode 100644 packages/drive/test/instance/runtime.test.ts delete mode 100644 packages/drive/test/llm.test.ts delete mode 100644 packages/drive/test/manual/tui-regressions/README.md delete mode 100644 packages/drive/test/manual/tui-regressions/initial-message-hydration.ts delete mode 100644 packages/drive/test/manual/tui-regressions/interaction-lifecycle.ts delete mode 100644 packages/drive/test/manual/tui-regressions/lifecycle-properties.ts delete mode 100644 packages/drive/test/manual/tui-regressions/multi-tool-interleavings.ts delete mode 100644 packages/drive/test/manual/tui-regressions/pending-form-restart.ts delete mode 100644 packages/drive/test/manual/tui-regressions/reconnect-outage.ts delete mode 100644 packages/drive/test/manual/tui-regressions/server-restart.ts delete mode 100644 packages/drive/test/manual/tui-regressions/state-machine.ts delete mode 100644 packages/drive/test/recording/decode.test.ts delete mode 100644 packages/drive/test/recording/export-dedupe.test.ts delete mode 100644 packages/drive/test/recording/export.test.ts delete mode 100644 packages/drive/test/recording/replay.test.ts delete mode 100644 packages/drive/test/script-filesystem.test.ts delete mode 100644 packages/drive/test/script-project.test.ts delete mode 100644 packages/drive/test/simulation/backend.test.ts delete mode 100644 packages/drive/test/simulation/connector.test.ts delete mode 100644 packages/drive/test/simulation/lifecycle.test.ts delete mode 100644 packages/drive/test/simulation/opencode-protocol.test.ts delete mode 100644 packages/drive/test/simulation/protocol.test.ts delete mode 100644 packages/drive/test/simulation/rpc.test.ts delete mode 100644 packages/drive/test/simulation/transport-peer.ts delete mode 100644 packages/drive/test/simulation/ui.test.ts delete mode 100644 packages/drive/test/tool/controller.test.ts delete mode 100644 packages/drive/test/tool/producer.test.ts delete mode 100644 packages/drive/tsconfig.json delete mode 100644 packages/drive/vitest.config.ts delete mode 100644 packages/lab/catalog/.gitignore delete mode 100644 packages/lab/catalog/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite delete mode 100644 packages/lab/catalog/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-shm delete mode 100644 packages/lab/catalog/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-wal delete mode 100644 packages/lab/catalog/AGENTS.md delete mode 100644 packages/lab/catalog/README.md delete mode 100644 packages/lab/catalog/catalog/authored/flows.ts delete mode 100644 packages/lab/catalog/catalog/authored/index.ts delete mode 100644 packages/lab/catalog/catalog/authored/screens.ts delete mode 100644 packages/lab/catalog/catalog/authored/taxonomies.ts delete mode 100644 packages/lab/catalog/catalog/authoring.test.ts delete mode 100644 packages/lab/catalog/catalog/authoring.ts delete mode 100644 packages/lab/catalog/catalog/authoring.typecheck.ts delete mode 100644 packages/lab/catalog/catalog/capture-sets.test.ts delete mode 100644 packages/lab/catalog/catalog/deep-link.test.ts delete mode 100644 packages/lab/catalog/catalog/dsl.ts delete mode 100644 packages/lab/catalog/catalog/feedback.test.ts delete mode 100644 packages/lab/catalog/catalog/flow.test.ts delete mode 100644 packages/lab/catalog/catalog/flow.ts delete mode 100644 packages/lab/catalog/catalog/font-coverage.test.ts delete mode 100644 packages/lab/catalog/catalog/lifecycle-flows.test.ts delete mode 100644 packages/lab/catalog/catalog/response-tool-flows.test.ts delete mode 100644 packages/lab/catalog/catalog/schema.ts delete mode 100644 packages/lab/catalog/catalog/search-flows.test.ts delete mode 100644 packages/lab/catalog/catalog/worker.test.ts delete mode 100644 packages/lab/catalog/compile/driver-consumer.ts delete mode 100644 packages/lab/catalog/doctor.config.json delete mode 100644 packages/lab/catalog/package.json delete mode 100644 packages/lab/catalog/perf/capture-feedback.md delete mode 100644 packages/lab/catalog/perf/capture-matrix.md delete mode 100644 packages/lab/catalog/public/captures/everforest/agent-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/assistant-response-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/assistant-response-interrupted.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/assistant-response-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/command-palette.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/debug.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/diff-viewer.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/glob-empty.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/glob-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/grep-empty.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/grep-failure.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/grep-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/grouped-exploration.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/help.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/home.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/integration-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/mcp-list.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/model-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/pair.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/patch-created.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/patch-deleted.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/patch-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/patch-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/patch-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/patch-updated.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/permission-always-confirmation.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/permission-always-selected.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/permission-fullscreen.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/permission-prompt.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/permission-reject-selected.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/question-awaiting-form.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/question-denied.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/question-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/question-prompt.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/question-review.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/question-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/read-denied.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/read-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/read-permission.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/read-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-export.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-fork.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-picker-populated.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-rename.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-tabs-idle.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/session-tabs-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/shell-execute-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/shell-execute-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/shell-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/shell-output-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/skill-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/status.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/subagent-completed.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/subagent-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/subagent-session.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/theme-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/thinking-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/toast-error.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/toast-info.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/toast-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/webfetch-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/webfetch-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/websearch-failure.frame.json delete mode 100644 packages/lab/catalog/public/captures/everforest/websearch-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/agent-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/assistant-response-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/assistant-response-interrupted.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/assistant-response-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/command-palette.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/debug.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/diff-viewer.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/glob-empty.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/glob-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/grep-empty.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/grep-failure.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/grep-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/grouped-exploration.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/help.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/home.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/integration-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/mcp-list.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/model-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/pair.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/patch-created.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/patch-deleted.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/patch-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/patch-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/patch-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/patch-updated.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/permission-always-confirmation.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/permission-always-selected.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/permission-fullscreen.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/permission-prompt.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/permission-reject-selected.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/question-awaiting-form.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/question-denied.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/question-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/question-prompt.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/question-review.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/question-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/read-denied.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/read-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/read-permission.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/read-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-export.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-fork.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-picker-populated.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-rename.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-tabs-idle.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/session-tabs-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/shell-execute-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/shell-execute-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/shell-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/shell-output-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/skill-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/status.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/subagent-completed.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/subagent-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/subagent-session.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/theme-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/thinking-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/toast-error.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/toast-info.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/toast-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/webfetch-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/webfetch-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/websearch-failure.frame.json delete mode 100644 packages/lab/catalog/public/captures/opencode/websearch-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/agent-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/assistant-response-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/assistant-response-interrupted.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/assistant-response-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/command-palette.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/debug.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/diff-viewer.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/glob-empty.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/glob-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/grep-empty.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/grep-failure.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/grep-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/grouped-exploration.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/help.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/home.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/integration-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/mcp-list.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/model-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/pair.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/patch-created.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/patch-deleted.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/patch-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/patch-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/patch-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/patch-updated.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/permission-always-confirmation.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/permission-always-selected.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/permission-fullscreen.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/permission-prompt.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/permission-reject-selected.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/question-awaiting-form.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/question-denied.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/question-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/question-prompt.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/question-review.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/question-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/read-denied.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/read-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/read-permission.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/read-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-export.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-fork.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-picker-populated.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-rename.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-tabs-idle.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/session-tabs-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/shell-execute-failed.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/shell-execute-succeeded.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/shell-input-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/shell-output-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/skill-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/status.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/subagent-completed.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/subagent-running.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/subagent-session.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/theme-picker.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/thinking-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/toast-error.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/toast-info.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/toast-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/webfetch-streaming.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/webfetch-success.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/websearch-failure.frame.json delete mode 100644 packages/lab/catalog/public/captures/tokyonight/websearch-running.frame.json delete mode 100644 packages/lab/catalog/public/catalog.json delete mode 100644 packages/lab/catalog/public/drive-captures.json delete mode 100644 packages/lab/catalog/scenarios/index.ts delete mode 100644 packages/lab/catalog/scenarios/responses/assistant-lifecycle.ts delete mode 100644 packages/lab/catalog/scenarios/runtime.ts delete mode 100644 packages/lab/catalog/scenarios/session-tabs.ts delete mode 100644 packages/lab/catalog/scenarios/subagents/subagent-lifecycle.ts delete mode 100644 packages/lab/catalog/scenarios/tools/patch-file-changes.ts delete mode 100644 packages/lab/catalog/scenarios/tools/patch-success.ts delete mode 100644 packages/lab/catalog/scenarios/tools/question-lifecycle.ts delete mode 100644 packages/lab/catalog/scenarios/tools/read-lifecycle.ts delete mode 100644 packages/lab/catalog/scenarios/tools/search-lifecycle.ts delete mode 100644 packages/lab/catalog/scenarios/tools/shell-lifecycle.ts delete mode 100644 packages/lab/catalog/scenarios/tools/web-lifecycle.ts delete mode 100644 packages/lab/catalog/scripts/bench-capture-flow.ts delete mode 100644 packages/lab/catalog/scripts/bench-capture-matrix.ts delete mode 100644 packages/lab/catalog/scripts/capture-opencode-drive.ts delete mode 100644 packages/lab/catalog/scripts/capture-sets.ts delete mode 100644 packages/lab/catalog/scripts/generate-catalog.ts delete mode 100644 packages/lab/catalog/scripts/generate-og.ts delete mode 100644 packages/lab/catalog/scripts/reproduce-state.ts delete mode 100644 packages/lab/catalog/server.ts delete mode 100644 packages/lab/catalog/src/App.tsx delete mode 100644 packages/lab/catalog/src/annotations.ts delete mode 100644 packages/lab/catalog/src/base-path.ts delete mode 100644 packages/lab/catalog/src/catalog.ts delete mode 100644 packages/lab/catalog/src/components/AnnotationEditor.tsx delete mode 100644 packages/lab/catalog/src/components/CaptureActionsMenu.tsx delete mode 100644 packages/lab/catalog/src/components/CaptureContextMenu.tsx delete mode 100644 packages/lab/catalog/src/components/CaptureSetSwitcher.tsx delete mode 100644 packages/lab/catalog/src/components/CommandPalette.tsx delete mode 100644 packages/lab/catalog/src/components/ContactSheet.tsx delete mode 100644 packages/lab/catalog/src/components/FilterBar.tsx delete mode 100644 packages/lab/catalog/src/components/FilterMenu.tsx delete mode 100644 packages/lab/catalog/src/components/FlowBrowser.tsx delete mode 100644 packages/lab/catalog/src/components/Header.tsx delete mode 100644 packages/lab/catalog/src/components/MatrixNavigation.tsx delete mode 100644 packages/lab/catalog/src/components/TerminalFrame.tsx delete mode 100644 packages/lab/catalog/src/components/Viewer.tsx delete mode 100644 packages/lab/catalog/src/deep-link.ts delete mode 100644 packages/lab/catalog/src/feedback.ts delete mode 100644 packages/lab/catalog/src/globals.d.ts delete mode 100644 packages/lab/catalog/src/index.html delete mode 100644 packages/lab/catalog/src/main.tsx delete mode 100644 packages/lab/catalog/src/styles.css delete mode 100644 packages/lab/catalog/tsconfig.json delete mode 100644 packages/lab/catalog/worker.ts delete mode 100644 packages/lab/catalog/wrangler.jsonc delete mode 100644 scripts/drive-mermaid-visual.ts diff --git a/.github/workflows/deploy-lab-catalog.yml b/.github/workflows/deploy-lab-catalog.yml deleted file mode 100644 index fb5b7634f2b..00000000000 --- a/.github/workflows/deploy-lab-catalog.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: deploy-lab-catalog - -on: - push: - branches: [v2] - paths: - - ".github/workflows/deploy-lab-catalog.yml" - - "bun.lock" - - "package.json" - - "packages/drive/**" - - "packages/protocol/src/simulation.ts" - - "packages/simulation/**" - - "packages/lab/catalog/**" - workflow_dispatch: - -concurrency: - group: deploy-lab-catalog-${{ github.ref_name }} - cancel-in-progress: false - -permissions: - contents: read - -jobs: - deploy: - if: github.repository == 'anomalyco/opencode' && github.ref_name == 'v2' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - uses: ./.github/actions/setup-bun - - - name: Install ffmpeg - run: | - sudo apt-get update - sudo apt-get install --yes ffmpeg - - - name: Validate - run: | - bun --cwd packages/protocol typecheck - bun --cwd packages/simulation typecheck - bun --cwd packages/drive run check - bun --cwd packages/drive run test - bun --cwd packages/lab/catalog run check - - - name: Deploy - working-directory: packages/lab/catalog - run: bun run deploy - env: - CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5dce1b33f04..cf495355acc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -72,7 +72,7 @@ jobs: - name: Run unit tests timeout-minutes: 20 - run: GITHUB_ACTIONS=false bun turbo test ${{ runner.os == 'Windows' && '--filter=!opencode-drive' || '' }} + run: GITHUB_ACTIONS=false bun turbo test env: OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: ${{ runner.os == 'Windows' && 'true' || 'false' }} diff --git a/.opencode/skills/opencode-drive/SKILL.md b/.opencode/skills/opencode-drive/SKILL.md deleted file mode 100644 index 371a1ef9151..00000000000 --- a/.opencode/skills/opencode-drive/SKILL.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -name: opencode-drive -description: Use when an agent needs drive OpenCode via a script or interact with an isolated instance ---- - -# OpenCode Drive - -Use `opencode-drive` to launch an isolated OpenCode instance and control it via commands or a script. - -There are two modes. Always default to using a script unless specifically directed to be interactive (connect -to an existing running instance, or start a new one, and make a few changes to the UI and read it, and iterate -on changes). - -Scripts allow you to run a full walkthrough in one run. When the script is done opencode-drive exits, -stops all processes, and cleans up all artifacts. - -# Prepare The Environment - -Use `init` when files must be added to the isolated home or project before OpenCode starts. It prints the artifact directory without launching OpenCode. A later `start` with the same name reuses it. - -```bash -artifacts=$(opencode-drive init --name demo) -cp -R ./fixtures/home/. "$artifacts/" -cp -R ./fixtures/project/. "$artifacts/files/" -opencode-drive start --name demo --dev ~/projects/opencode -``` - -The simulated project is under `$artifacts/files`. Running `start` without a prior `init` initializes the artifacts automatically. - -# Scripted usage - -You can write scripts that walk through entire flows, and gives you full access to controlling -the backend too. See examples of the script API at the bottom of this file. - -After creating or editing a script, always typecheck it before running. Never skip this step: - -```bash -opencode-drive check ./reproduce-stale-exploring-empty.ts -``` - -Run it by passing `--script` to start: - -```bash -opencode-drive start --name auto-stop-reproduction --script ./reproduce-stale-exploring-empty.ts -``` - -It will output information about the run, including paths to log files which you can read -to inspect what happened. If you need to dig into failures that aren't clear, read those log -files. If the script is unsuccessful, automatically fix the script and run it again. - -Scripts use one typed definition object. `setup` runs before OpenCode starts, -and `fs.writeFile` always writes inside the simulated project. - -You can read the full typed API here: https://raw.githubusercontent.com/anomalyco/opencode/v2/packages/drive/src/script/types.ts - -```ts -import { defineScript } from "opencode-drive" - -export default defineScript({ - async setup({ fs, config }) { - config.autoupdate = false - await fs.writeFile("src/example.ts", "export const value = 1\n") - }, - - async run({ ui, llm }) { - await ui.submit("Open src/example.ts") - await llm.send(llm.text("The file exports `value`.")) - await ui.waitFor("The file exports `value`.") - }, -}) -``` - -`setup` receives the current OpenCode config object, which starts from the -default drive config unless the prepared instance already has one. When a script -needs custom config, mutate this `config` parameter instead of generating and -writing a new config object from scratch, so the script keeps the default -provider/model settings unless it intentionally changes them. - -Note that the simulated model is a GPT model type, and opencode uses the `patch` tool for working with files Do not use a `edit` or `write` tool to edit files. - -Use `launch: "manual"` when the script needs to launch the server and every TUI -itself (this is extremely rare, do not use this unless explicitly asked). In this -mode `ui` is typed as `null`; call `server.launch()` exactly -once before launching clients. Each `clients.launch(name)` result provides the -same UI methods as the automatic client. You can see an example of this API -here: https://raw.githubusercontent.com/anomalyco/opencode/v2/packages/drive/examples/multiple-clients.ts - -Use the exported `wait(milliseconds)` utility for an unconditional delay. - -`await llm.send(...)` waits for the next request and resolves after OpenCode -acknowledges its complete response. `llm.queue(...)` declares responses in -advance. Chunks may be built with `text`, `reasoning`, `toolCall`, `raw`, -`finish`, and `disconnect`. A normal response receives `finish("stop")` -automatically unless it yields or queues an explicit terminal event. - -`llm.text(text, { delay, chunkSize })` defaults to a 2 ms delay and a -15-character target varied by plus or minus 5 per chunk. - -`llm.reasoning` accepts the same options, and `llm.pause(milliseconds)` adds a -delay between any two outputs. - -Use `llm.serve` for an ongoing typed response generator: - -```ts -llm.serve(async function* (request, index) { - yield llm.reasoning(`Handling request ${index + 1}`) - yield llm.text(`Received ${request.id}`) - yield llm.finish("stop") -}) -``` - -The backend connection, response cleanup, cancellation, and recording -completion are automatic. - -You can see some example scripts here: - -- https://raw.githubusercontent.com/anomalyco/opencode/v2/packages/drive/examples/simple.ts -- https://raw.githubusercontent.com/anomalyco/opencode/v2/packages/drive/examples/serve.ts - -## Prune - -- `prune` removes artifact directories. These are always cleaned up after running a script - successfully, but leftover on failed runs. Always call this if a script fails. - -```bash -opencode-drive prune --name demo - -// --force cleans up all artifcat directories -opencode-dirve prune --force -``` - -# Live interaction usage - -- Always give headless instances a unique `--name`. Visible instances may omit it. -- A normal headless `start` detaches automatically and returns after the instance is ready. -- Do not add `&`; the long-running owner already runs in the background. -- Configure simulated model responses after startup when needed. -- Send ordered UI commands with `send`. -- Always stop the instance when finished. - -```bash -opencode-drive start --name demo - -opencode-drive send --name demo \ - --command.ui.type '{"text":"Explain this project"}' \ - --command.ui.enter - -opencode-drive stop --name demo -``` - -## Send UI Commands - -- Every `send` opens a connection to the named instance, runs its commands in order, and exits. -- Combine typing and Enter in one command when submitting a prompt. -- JSON-valued commands require one JSON argument. -- Multiple command flags execute from left to right. - -Commands: - -- `--command.ui.type ` types into the focused editor. Arguments: `text` string. -- `--command.ui.press ` presses a key. Arguments: `key` string; optional `modifiers` object with boolean `ctrl`, `shift`, `meta`, `super`, or `hyper`. -- `--command.ui.enter` presses Enter. Arguments: none. -- `--command.ui.arrow ` presses an arrow key. Arguments: `direction` is `up`, `down`, `left`, or `right`. -- `--command.ui.focus ` focuses an element. Arguments: `target` is the numeric element `num` returned by `ui.state`. -- `--command.ui.click ` clicks an element. Arguments: numeric `target`, `x`, and `y`; use the element `num` returned by `ui.state` as `target`. -- `--command.ui.state` prints focus and interactive element metadata as JSON. Arguments: none. -- `--command.ui.matches ` prints whether literal, case-sensitive text appears on screen. Arguments: `text` string. - -```bash -opencode-drive send --name demo \ - --command.ui.type '{"text":"Find the relevant code and explain it"}' \ - --command.ui.enter - -opencode-drive send --name demo \ - --command.ui.press '{"key":"p","modifiers":{"ctrl":true}}' - -opencode-drive send --name demo \ - --command.ui.arrow '{"direction":"down"}' - -opencode-drive send --name demo \ - --command.ui.focus '{"target":12}' - -opencode-drive send --name demo \ - --command.ui.click '{"target":12,"x":4,"y":1}' - -opencode-drive send --name demo \ - --command.ui.matches '{"text":"OpenCode"}' -``` - -To read the UI state and see information about interactable elements, use the `ui.state` command: - -```bash -opencode-drive send --name demo --command.ui.state -``` - -## Configure LLM Responses - -- `responses` controls what the LLM responds with -- Only use this if you are wanting to reproduce an exact type of response -- Defaults are `text,reasoning,diff,tool` with `write,apply_patch`. -- Supported types are `text`, `reasoning`, `diff`, and `tool`. -- `--tools` limits generated tool calls to names offered by OpenCode. - -```bash -opencode-drive responses --name demo \ - --types text,reasoning,diff,tool \ - --tools write,apply_patch - -opencode-drive responses --name demo \ - --types tool \ - --tools read,glob,grep -``` - -## Inspect The UI - -- `ui.state` prints focus and interactive element metadata as JSON. -- `ui.matches` checks for literal, case-sensitive screen text. -- `screenshot` prints the generated image path. - -```bash -opencode-drive screenshot --name demo -``` - -## Lifecycle - -- `stop` waits for recording export and owner cleanup before returning. - -```bash -opencode-drive stop --name demo -``` - -# Record The UI - -- Start with `--record` to capture a headless instance from its first rendered frame. -- `stop` finishes the recording, exports an MP4, and prints its path. - -```bash -opencode-drive start --name demo --record - -opencode-drive send --name demo \ - --command.ui.type '{"text":"Show me the current architecture"}' \ - --command.ui.enter - -opencode-drive stop --name demo -``` - -# Artifacts dir - -- `dir` prints the artifact directory for the instance. - -```bash -opencode-drive dir --name demo -``` diff --git a/bun.lock b/bun.lock index 6291c02b38e..df60bc5e7a8 100644 --- a/bun.lock +++ b/bun.lock @@ -465,31 +465,6 @@ "@parcel/watcher-win32-x64": "2.5.1", }, }, - "packages/drive": { - "name": "opencode-drive", - "version": "1.4.3", - "bin": { - "opencode-drive": "bin/opencode-drive", - }, - "dependencies": { - "@effect/platform-node": "catalog:", - "@napi-rs/canvas": "1.0.2", - "@opencode-ai/client": "workspace:*", - "@opencode-ai/protocol": "workspace:*", - "@types/bun": "catalog:", - "@typescript/native-preview": "catalog:", - "@wterm/core": "0.3.0", - "@wterm/ghostty": "0.3.0", - "effect": "catalog:", - }, - "devDependencies": { - "@effect/vitest": "4.0.0-beta.101", - "@tsconfig/bun": "catalog:", - "oxlint": "1.60.0", - "typescript": "catalog:", - "vitest": "4.1.10", - }, - }, "packages/enterprise": { "name": "@opencode-ai/enterprise", "version": "1.18.15", @@ -571,27 +546,6 @@ "@typescript/native-preview": "catalog:", }, }, - "packages/lab/catalog": { - "name": "@opencode-ai/lab-catalog", - "dependencies": { - "@fontsource/commit-mono": "5.2.5", - "@fontsource/noto-sans-math": "5.2.8", - "@fontsource/noto-sans-symbols": "5.2.8", - "@fontsource/noto-sans-symbols-2": "5.2.8", - "react": "^19.2.7", - "react-dom": "^19.2.7", - }, - "devDependencies": { - "@napi-rs/canvas": "1.0.2", - "@types/bun": "catalog:", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "effect": "catalog:", - "opencode-drive": "workspace:*", - "typescript": "^7.0.2", - "wrangler": "4.110.0", - }, - }, "packages/merman": { "name": "@opencode-ai/merman", "version": "0.0.0", @@ -1635,8 +1589,6 @@ "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.101", "", { "peerDependencies": { "effect": "^4.0.0-beta.101" } }, "sha512-s6AC7LXCEjCN+nKegKFY4MOi6bmT1+SLR9YHEYwhY3P5qyQQB4R5yYLgt+3J4EPp5fa3t4FIDdPEUwz9LdKm6g=="], - "@effect/vitest": ["@effect/vitest@4.0.0-beta.101", "", { "peerDependencies": { "effect": "^4.0.0-beta.101", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-F5Ur8pZYti0xkZFyb4hPZt8RrKQ1XBoC28ZkKxc7N1iPbhE9fWOvlWA1NC2XlN2wWG08yb5g5jR53LdOxjlhpQ=="], - "@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], "@electron/fuses": ["@electron/fuses@1.8.0", "", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="], @@ -1769,18 +1721,10 @@ "@floating-ui/utils": ["@floating-ui/utils@0.2.12", "", {}, "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww=="], - "@fontsource/commit-mono": ["@fontsource/commit-mono@5.2.5", "", {}, "sha512-htX8yQWtiPt5L1Hzh4sirvfUJT2+KYiquDB/Q2sY2tWQYplpBUOD5zHnIM3k36Hnm4V+JIIqA/wmwupSQ68WjA=="], - "@fontsource/ibm-plex-mono": ["@fontsource/ibm-plex-mono@5.2.5", "", {}, "sha512-G09N3GfuT9qj3Ax2FDZvKqZttzM3v+cco2l8uXamhKyXLdmlaUDH5o88/C3vtTHj2oT7yRKsvxz9F+BXbWKMYA=="], "@fontsource/inter": ["@fontsource/inter@5.3.0", "", {}, "sha512-RofMylZmjlJEfELXeNHFWBRcSs75rGU/6bV2S2jfnvv/3rPXPGe0LgUJTklcHZ9lM4OZmAVFhcJPnACfb91A3g=="], - "@fontsource/noto-sans-math": ["@fontsource/noto-sans-math@5.2.8", "", {}, "sha512-LKP8MXf5if2NoQcpgkIWS3SKGk7b4IZCLKTTHEFmHuy1g/n5KKg21+wk4cTKEoJZtHaMo13jwd4Hw8TWxaz8gQ=="], - - "@fontsource/noto-sans-symbols": ["@fontsource/noto-sans-symbols@5.2.8", "", {}, "sha512-x5U4btr3+aveZWNXK24tG3jvds7RRTg4diQ0D9nvZQxxtskbXVFEBP7Iok8TS86R9XHyg1TBS5GoR+ZLZSF5fw=="], - - "@fontsource/noto-sans-symbols-2": ["@fontsource/noto-sans-symbols-2@5.2.8", "", {}, "sha512-OGKq1CaSIszlSBc4Ie2XPBS8yFfF1fMfzjjoRRfpijjgjk1Xg/WSo/3Bg0cJdoxxIdQ0a2XENzJHhfpWLNv5Lw=="], - "@gar/promise-retry": ["@gar/promise-retry@1.0.3", "", {}, "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA=="], "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="], @@ -1981,30 +1925,6 @@ "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="], - "@napi-rs/canvas": ["@napi-rs/canvas@1.0.2", "", { "optionalDependencies": { "@napi-rs/canvas-android-arm64": "1.0.2", "@napi-rs/canvas-darwin-arm64": "1.0.2", "@napi-rs/canvas-darwin-x64": "1.0.2", "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.2", "@napi-rs/canvas-linux-arm64-gnu": "1.0.2", "@napi-rs/canvas-linux-arm64-musl": "1.0.2", "@napi-rs/canvas-linux-riscv64-gnu": "1.0.2", "@napi-rs/canvas-linux-x64-gnu": "1.0.2", "@napi-rs/canvas-linux-x64-musl": "1.0.2", "@napi-rs/canvas-win32-arm64-msvc": "1.0.2", "@napi-rs/canvas-win32-x64-msvc": "1.0.2" } }, "sha512-EYEqlMYaCbpZDz+IgDH5xp9MTd3ui4dmGqbQYryhMLnSRxrhHKq5KQWHHKxFUcEP4Hp8/BWgvqXocX4j7iSbOQ=="], - - "@napi-rs/canvas-android-arm64": ["@napi-rs/canvas-android-arm64@1.0.2", "", { "os": "android", "cpu": "arm64" }, "sha512-IMXKVQod0ol4vt3gmClUfXz4JAgHYESGPCUqmH3lQxBoL0K/2greJaQE1HVBVxWWFKfLc4OLZVdxg7kXVyXv+g=="], - - "@napi-rs/canvas-darwin-arm64": ["@napi-rs/canvas-darwin-arm64@1.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sc8tPi6cF+5lqOzCCKFALJHhDiRwyMzTPYm3bbhdXsOunU0lQO5f05ucyOzN2r55I23Hg5bsjH63uSCvWp3EgQ=="], - - "@napi-rs/canvas-darwin-x64": ["@napi-rs/canvas-darwin-x64@1.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-niDXZ9LhKB1zLrUdYB64RHQFDGz9rr0eGx061qtJJU3U20EMMIx28ADF5fVYbhtOgkWQrBjFicfaye1yM0U62A=="], - - "@napi-rs/canvas-linux-arm-gnueabihf": ["@napi-rs/canvas-linux-arm-gnueabihf@1.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-sgatQL9JxGRH/Amzcvu0P3t8Am3duou74CisfuJ41Dwt8cWy723z/9KZ8LlgmxfypEwEZxSTNFJtU8d281lmhQ=="], - - "@napi-rs/canvas-linux-arm64-gnu": ["@napi-rs/canvas-linux-arm64-gnu@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgKuX0peF3xwY6ZF5QxGS4wbfDqpoFAJYXiLSp+guZKARQUKMkRqZSDrXKj7nfrec3UCMzC0PFCPte0ES98AiA=="], - - "@napi-rs/canvas-linux-arm64-musl": ["@napi-rs/canvas-linux-arm64-musl@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-qwROoDIC9upfvDoRLuPn2aNg9CGW1x0Ygr4k2Or+8paA9d0qBLwk87U+g8KQpoOviKoPoiwl97kvBYuYD7qZoA=="], - - "@napi-rs/canvas-linux-riscv64-gnu": ["@napi-rs/canvas-linux-riscv64-gnu@1.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-fXRjnPihdnbO6qy1QQOgxAonb68A0TCEG7rj1x7v7rxNElsE8EVIKIEUTvyDtU+sthYSbX+8e7g3oZiLGnOmxw=="], - - "@napi-rs/canvas-linux-x64-gnu": ["@napi-rs/canvas-linux-x64-gnu@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-nPR97DXhbWIAy7yazF3jc06kEPMqYMLmPzFOVNlwKPfIoSChnI+x7dc0hTLaihz3jxrjL6j4BbA7earxfx4X3g=="], - - "@napi-rs/canvas-linux-x64-musl": ["@napi-rs/canvas-linux-x64-musl@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-l7zZY5+jL5qnBZtDz7CoBtY6p7EkHu422g/0zWwrOrzIwWyWxZFRfZZORY1UG7YApymPLx+UbOkN206xXn/c1Q=="], - - "@napi-rs/canvas-win32-arm64-msvc": ["@napi-rs/canvas-win32-arm64-msvc@1.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-yE0koHCFF4PIbMc2o2SEALhnipz7WBISh5glLvQiomtIoCcW0np3H4Lw93ceJAfJttTTeIIWFbwH84F7EVzjMQ=="], - - "@napi-rs/canvas-win32-x64-msvc": ["@napi-rs/canvas-win32-x64-msvc@1.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-okU8/t2foV6C31n0GtvEMbfD5rOFc70+/6xUNME9Guld29sgSOIGUEDScAWFlcP3k5TYQRl9TNkwJEEjh15w8A=="], - "@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" } }, "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw=="], @@ -2127,8 +2047,6 @@ "@opencode-ai/httpapi-codegen": ["@opencode-ai/httpapi-codegen@workspace:packages/httpapi-codegen"], - "@opencode-ai/lab-catalog": ["@opencode-ai/lab-catalog@workspace:packages/lab/catalog"], - "@opencode-ai/merman": ["@opencode-ai/merman@workspace:packages/merman"], "@opencode-ai/plugin": ["@opencode-ai/plugin@workspace:packages/plugin"], @@ -3261,46 +3179,6 @@ "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20251207.1", "", { "os": "win32", "cpu": "x64" }, "sha512-5l51HlXjX7lXwo65DEl1IaCFLjmkMtL6K3NrSEamPNeNTtTQwZRa3pQ9V65dCglnnCQ0M3+VF1RqzC7FU0iDKg=="], - "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], - - "@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="], - - "@typescript/typescript-darwin-x64": ["@typescript/typescript-darwin-x64@7.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA=="], - - "@typescript/typescript-freebsd-arm64": ["@typescript/typescript-freebsd-arm64@7.0.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ=="], - - "@typescript/typescript-freebsd-x64": ["@typescript/typescript-freebsd-x64@7.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw=="], - - "@typescript/typescript-linux-arm": ["@typescript/typescript-linux-arm@7.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ=="], - - "@typescript/typescript-linux-arm64": ["@typescript/typescript-linux-arm64@7.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ=="], - - "@typescript/typescript-linux-loong64": ["@typescript/typescript-linux-loong64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ=="], - - "@typescript/typescript-linux-mips64el": ["@typescript/typescript-linux-mips64el@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA=="], - - "@typescript/typescript-linux-ppc64": ["@typescript/typescript-linux-ppc64@7.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA=="], - - "@typescript/typescript-linux-riscv64": ["@typescript/typescript-linux-riscv64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ=="], - - "@typescript/typescript-linux-s390x": ["@typescript/typescript-linux-s390x@7.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw=="], - - "@typescript/typescript-linux-x64": ["@typescript/typescript-linux-x64@7.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A=="], - - "@typescript/typescript-netbsd-arm64": ["@typescript/typescript-netbsd-arm64@7.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA=="], - - "@typescript/typescript-netbsd-x64": ["@typescript/typescript-netbsd-x64@7.0.2", "", { "os": "none", "cpu": "x64" }, "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA=="], - - "@typescript/typescript-openbsd-arm64": ["@typescript/typescript-openbsd-arm64@7.0.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ=="], - - "@typescript/typescript-openbsd-x64": ["@typescript/typescript-openbsd-x64@7.0.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg=="], - - "@typescript/typescript-sunos-x64": ["@typescript/typescript-sunos-x64@7.0.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g=="], - - "@typescript/typescript-win32-arm64": ["@typescript/typescript-win32-arm64@7.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ=="], - - "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], - "@typescript/vfs": ["@typescript/vfs@1.6.4", "", { "dependencies": { "debug": "^4.4.3" }, "peerDependencies": { "typescript": "*" } }, "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ=="], "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.8", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-bLMpVcWZNzq6lYOybwFwOAR1IXKcHnhUNqYeHjl1bET/qE3jFPFH+p8Wrh3rU4xwdnifPxmKNESBYnvnmc75aA=="], @@ -3363,10 +3241,6 @@ "@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="], - "@wterm/core": ["@wterm/core@0.3.0", "", {}, "sha512-aQ73QBP+eyA3kcn31mA7DmAi7qmEsQijZdmvgwxtSjCi2248EAOZgtkGDpjlspfrxyVxQbUl/IF+gCVcXt4nZQ=="], - - "@wterm/ghostty": ["@wterm/ghostty@0.3.0", "", { "dependencies": { "@wterm/core": "0.3.0" } }, "sha512-TDjEmUSRD7IaFxq31P7+I3Inkp5mHCfBfO6LYj3/vbLbWOkOZOKPhjAcZ36AYFHe9Q0HLCFvLWmrxIO3aGCjDA=="], - "@xmldom/xmldom": ["@xmldom/xmldom@0.8.13", "", {}, "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw=="], "@yuuang/ffi-rs-android-arm64": ["@yuuang/ffi-rs-android-arm64@1.3.7", "", { "os": "android", "cpu": "arm64" }, "sha512-t6Wx3Xll6c07Nuk0k3xnZsxKFxlshm92i0U/BiTHc6kQbvu+fMJF+gKsj4yEj886jH51CM3EqZT9Xdhq9CdUVw=="], @@ -5021,8 +4895,6 @@ "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], - "opencode-drive": ["opencode-drive@workspace:packages/drive"], - "openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="], "opentui-spinner": ["opentui-spinner@0.0.7", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.3.4", "@opentui/react": "^0.3.4", "@opentui/solid": "^0.3.4", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-nPzwAvJG+y9rVEwwHLHqbsMzLnIk2zw+F9LqwA7aYJvpM5gsrKC2rrGi36A+tZpA+1RnWxXeWEgVZMchnaH18Q=="], @@ -5249,7 +5121,7 @@ "react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="], - "react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + "react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], @@ -5417,7 +5289,7 @@ "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="], - "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], @@ -6349,16 +6221,12 @@ "@jsx-email/cli/esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], - "@jsx-email/cli/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - "@jsx-email/cli/tailwindcss": ["tailwindcss@3.3.3", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.18.2", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w=="], "@jsx-email/cli/vite": ["vite@4.5.14", "", { "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", "rollup": "^3.27.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g=="], "@jsx-email/doiuse-email/htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="], - "@jsx-email/tailwind/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - "@kobalte/core/solid-presence": ["solid-presence@0.1.8", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA=="], "@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], @@ -6447,20 +6315,12 @@ "@opencode-ai/desktop/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], - "@opencode-ai/lab-catalog/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], - - "@opencode-ai/lab-catalog/typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], - - "@opencode-ai/lab-catalog/wrangler": ["wrangler@4.110.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "4.20260708.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260708.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260708.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js", "cf-wrangler": "bin/cf-wrangler.js" } }, "sha512-xZeXKYi7hxQRF5anL+v77RkufJNpF9f3Eqeyqq2QBsETpLZgh0Agj0jJ6JPtkbgn6ukZdh8OK5egsGPWIditgg=="], - "@opencode-ai/session-ui/@opencode-ai/sdk": ["@opencode-ai/sdk@../app/vendor/opencode-ai-sdk-1.18.8-dev.tgz", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-C2nfk4x0sPINwE5V6DPkFSuH3PkUmKPWHPzxpXC1j+3Ui5hslLCWJbkk8WcOG1Lyt3C0+yp4ea64v/kmtYCO4w=="], "@opencode-ai/session-ui/@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="], "@opencode-ai/storybook/@types/react": ["@types/react@18.0.25", "", { "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g=="], - "@opencode-ai/storybook/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - "@opencode-ai/ui/@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="], "@opencode-ai/updates/wrangler": ["wrangler@4.110.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "4.20260708.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260708.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260708.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js", "cf-wrangler": "bin/cf-wrangler.js" } }, "sha512-xZeXKYi7hxQRF5anL+v77RkufJNpF9f3Eqeyqq2QBsETpLZgh0Agj0jJ6JPtkbgn6ukZdh8OK5egsGPWIditgg=="], @@ -6493,44 +6353,20 @@ "@pierre/diffs/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], + "@pierre/diffs/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + + "@pierre/theming/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + "@pierre/trees/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], + "@pierre/trees/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + "@poppinss/dumper/@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], "@protobuf-ts/plugin/typescript": ["typescript@3.9.10", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q=="], - "@radix-ui/react-arrow/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-collapsible/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-collection/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-dismissable-layer/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-focus-scope/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-popover/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-popper/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-portal/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-presence/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-primitive/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-roving-focus/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-toggle/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-toggle-group/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-tooltip/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - - "@radix-ui/react-visually-hidden/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "@scalar/types/nanoid": ["nanoid@5.1.16", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ=="], @@ -6589,6 +6425,8 @@ "@storybook/addon-docs/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], + "@storybook/addon-docs/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + "@storybook/csf-plugin/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg=="], @@ -6711,6 +6549,8 @@ "blume/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], + "blume/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + "blume/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "blume/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -6827,8 +6667,6 @@ "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "framer-motion/react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], - "fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], @@ -6935,8 +6773,6 @@ "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "react-dom/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], - "readdir-glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], "rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], @@ -7477,8 +7313,6 @@ "@jsx-email/cli/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.19.12", "", { "os": "win32", "cpu": "x64" }, "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA=="], - "@jsx-email/cli/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "@jsx-email/cli/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "@jsx-email/cli/tailwindcss/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -7493,8 +7327,6 @@ "@jsx-email/doiuse-email/htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - "@jsx-email/tailwind/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "@malept/flatpak-bundler/fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], "@mapbox/node-pre-gyp/nopt/abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="], @@ -7593,18 +7425,6 @@ "@opencode-ai/desktop/@actions/artifact/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], - "@opencode-ai/lab-catalog/wrangler/@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="], - - "@opencode-ai/lab-catalog/wrangler/@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare": ["miniflare@4.20260708.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.34.5", "undici": "7.28.0", "workerd": "1.20260708.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-c94O9zRDISdqO18EHt6l0iF/fWgWt8p18PJvRsA/L/NJZ9Cfke3s/F5Blg1XXF7WDutVRzWVWy8Vy4LaT5ifsA=="], - - "@opencode-ai/lab-catalog/wrangler/workerd": ["workerd@1.20260708.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260708.1", "@cloudflare/workerd-darwin-arm64": "1.20260708.1", "@cloudflare/workerd-linux-64": "1.20260708.1", "@cloudflare/workerd-linux-arm64": "1.20260708.1", "@cloudflare/workerd-windows-64": "1.20260708.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-WAK+Kt/VVCSldH2qSr8lx46XCJ4Q+bdlHNaFqUtOHthBEIB8C1N8HVW+VOLrxDoTCk0NGNv0zajnBeQK4JOB9w=="], - - "@opencode-ai/storybook/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "@opencode-ai/updates/wrangler/@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="], "@opencode-ai/updates/wrangler/@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="], @@ -7693,35 +7513,13 @@ "@oxc-resolver/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], - "@radix-ui/react-arrow/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], + "@pierre/diffs/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], - "@radix-ui/react-collapsible/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], + "@pierre/theming/react-dom/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], - "@radix-ui/react-collection/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], + "@pierre/theming/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], - "@radix-ui/react-dismissable-layer/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-focus-scope/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-popover/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-popper/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-portal/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-presence/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-primitive/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-roving-focus/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-toggle-group/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-toggle/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-tooltip/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "@radix-ui/react-visually-hidden/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], + "@pierre/trees/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], "@sentry/bundler-plugin-core/glob/minimatch": ["minimatch@8.0.7", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg=="], @@ -7783,6 +7581,8 @@ "@solidjs/start/shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="], + "@storybook/addon-docs/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + "@storybook/csf-plugin/unplugin/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="], "@storybook/csf-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], @@ -7913,6 +7713,8 @@ "blume/node-html-parser/entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="], + "blume/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + "builder-util/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -7959,8 +7761,6 @@ "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "framer-motion/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "gcp-metadata/gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "js-beautify/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], @@ -8627,72 +8427,6 @@ "@opencode-ai/desktop/@actions/artifact/@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], - - "@opencode-ai/lab-catalog/wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="], - - "@opencode-ai/lab-catalog/wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260708.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-HXFCvhS1wpg3uXO0CLUwmwC41i2loM5FSK69EUchOBpmYBAXxT1oHLm6EOA5lqhTk5Mu9kjRiQYxa1GwKPwfJg=="], - - "@opencode-ai/lab-catalog/wrangler/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260708.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JVlJaKDoRTVKSroHIlf8g3UCPjKj4iDbMZE2CNYht5qQ+2rL0FAUiVlV82G3BqKnnw9kHYnnsMzC08b9zVtdzA=="], - - "@opencode-ai/lab-catalog/wrangler/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260708.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3daE60YdD7YX0Jtuzc9DE/r/qMkmx8ZvHTkF8Mzmp3F5tbzlV0DAzmu5PFUPF2WuvtKbAhZKbvC2cHmWpQYxnA=="], - - "@opencode-ai/lab-catalog/wrangler/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260708.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-VLdNYOx5Hj+9C6isy0ACWZsbMtSxex2DIJWEe7cZxUdlphZ58ZT8zxNXK8yunFiowd34hn3VwGMopdvdj8lvmA=="], - - "@opencode-ai/lab-catalog/wrangler/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260708.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bC/aSAwLy16Vjo24i9XU3aWH+eRgz7NeR5xPKavGbembO18ZywYTQbXh14eXtY6fAqN3RzRG8psijTdhX4xydA=="], - "@opencode-ai/updates/wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], "@opencode-ai/updates/wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], @@ -9387,54 +9121,6 @@ "@opencode-ai/desktop/@actions/artifact/@actions/core/@actions/exec/@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="], - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], - - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], - "@opencode-ai/updates/wrangler/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], "@opencode-ai/updates/wrangler/miniflare/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], @@ -9715,8 +9401,6 @@ "@astrojs/cloudflare/wrangler/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], - "@opencode-ai/lab-catalog/wrangler/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], - "@opencode-ai/updates/wrangler/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], "@opencode-ai/www/@astrojs/cloudflare/@cloudflare/vite-plugin/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="], diff --git a/package.json b/package.json index 9cf85b09f0a..430d5159ca6 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "packages": [ "packages/*", "packages/console/*", - "packages/lab/*", "packages/stats/*", "packages/slack" ], diff --git a/packages/cli/script/service-smoke.ts b/packages/cli/script/service-smoke.ts index 42b87eac435..d74a47fe803 100644 --- a/packages/cli/script/service-smoke.ts +++ b/packages/cli/script/service-smoke.ts @@ -88,7 +88,6 @@ try { if (!(await exitsWithin(winner, 10_000))) throw new Error("Compiled service did not stop") for (let attempt = 0; attempt < 200 && (await Bun.file(registration).exists()); attempt++) await Bun.sleep(25) if (await Bun.file(registration).exists()) throw new Error("Compiled service registration was not removed") - await driveSmoke() } catch (cause) { failure = cause } finally { @@ -112,50 +111,6 @@ function spawnService() { return process } -async function driveSmoke() { - const name = "compiled-artifact" - const drive = path.resolve(import.meta.dir, "../../drive/src/cli/index.ts") - const driveEnv = { - ...env, - DRIVE_REGISTRY_DIR: path.join(root, "drive-registry"), - OPENCODE_DRIVE_KEEP_ARTIFACTS: "1", - OPENCODE_DRIVE_MEDIA_DIR: path.join(root, "drive-media"), - } - let started = false - try { - await runDrive(["start", "--name", name, "--", binary], drive, driveEnv) - started = true - const screenshot = ( - await runDrive( - ["send", "--name", name, "--command.ui.screenshot", '{"name":"compiled-capture"}'], - drive, - driveEnv, - ) - ).trim() - const bytes = Buffer.from(await Bun.file(screenshot).arrayBuffer()) - if (!bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) - throw new Error("Compiled Drive bridge did not produce a PNG capture") - } finally { - if (started) await runDrive(["stop", "--name", name], drive, driveEnv) - } -} - -async function runDrive(args: ReadonlyArray, drive: string, driveEnv: Record) { - const child = Bun.spawn([process.execPath, drive, ...args], { - cwd: root, - env: driveEnv, - stdout: "pipe", - stderr: "pipe", - }) - const [status, stdout, stderr] = await Promise.all([ - child.exited, - new Response(child.stdout).text(), - new Response(child.stderr).text(), - ]) - if (status !== 0) throw new Error(`opencode-drive ${args[0]} failed:\n${stderr}`) - return stdout -} - async function waitForRegistration() { const directory = path.join(root, "state", "opencode") for (let attempt = 0; attempt < 400; attempt++) { diff --git a/packages/cli/script/verify-artifact.ts b/packages/cli/script/verify-artifact.ts index a17426920bd..68b8e9c2770 100644 --- a/packages/cli/script/verify-artifact.ts +++ b/packages/cli/script/verify-artifact.ts @@ -14,7 +14,6 @@ const forbidden = [ "noto-sans-math-math-400-normal", "CommitMono-400-Regular.otf", "NotoSansSymbols.ttf", - "packages/drive/src/recording/render", "src/frontend/png.ts", "skia.darwin-", "skia.linux-", @@ -37,10 +36,7 @@ export function verifySimulationGraph(inputs: Iterable) { ] const missing = required.filter((input) => !modules.some((module) => module.endsWith(input))) if (missing.length > 0) throw new Error(`Build graph is missing simulation bridge inputs: ${missing.join(", ")}`) - const leaked = modules.find( - (module) => - module.includes("/packages/simulation/src/frontend/png.") || module.includes("/packages/drive/src/recording/"), - ) + const leaked = modules.find((module) => module.includes("/packages/simulation/src/frontend/png.")) if (leaked) throw new Error(`Build graph contains Drive-only rendering input: ${leaked}`) } diff --git a/packages/cli/test/drive/mini-interactive.drive.mjs b/packages/cli/test/drive/mini-interactive.drive.mjs deleted file mode 100644 index 5323380d50b..00000000000 --- a/packages/cli/test/drive/mini-interactive.drive.mjs +++ /dev/null @@ -1,371 +0,0 @@ -import { Effect } from "effect" -import { defineScript, Llm } from "opencode-drive" -import { mkdir } from "node:fs/promises" -import path from "node:path" - -export default defineScript({ - launch: "manual", - config: { autoupdate: false }, - run: ({ artifacts, llm, server }) => - Effect.gen(function* () { - yield* Effect.promise(() => configureServicePort(artifacts)) - yield* server.launch() - - const registration = yield* Effect.promise(() => serviceRegistration(artifacts)) - const root = path.resolve(import.meta.dir, "../../../..") - const preload = Bun.resolveSync("@opentui/solid/preload", path.join(root, "packages/cli")) - const session = `mini-stage2-${process.pid}` - const snapshots = path.join(artifacts, "mini-stage2") - const explicitDirectory = path.join(artifacts, "explicit-model") - yield* Effect.promise(() => - Promise.all([snapshots, explicitDirectory].map((dir) => mkdir(dir, { recursive: true }))), - ) - /** @param {string} directory @param {string | undefined} model */ - const mini = (directory, model) => [ - "env", - `PWD=${directory}`, - `OPENCODE_PASSWORD=${registration.password}`, - `OPENCODE_CONFIG_DIR=${path.join(artifacts, "files/.opencode")}`, - `OPENCODE_TEST_HOME=${artifacts}`, - `XDG_CACHE_HOME=${path.join(artifacts, "home/.cache")}`, - `XDG_CONFIG_HOME=${path.join(artifacts, "home/.config")}`, - `XDG_DATA_HOME=${path.join(artifacts, "logs")}`, - `XDG_STATE_HOME=${path.join(artifacts, "home/.local/state")}`, - "OPENCODE_DISABLE_AUTOUPDATE=1", - "OPENCODE_DIRECT_TRACE=1", - process.execPath, - "--conditions=browser", - `--preload=${preload}`, - path.join(root, "packages/cli/src/index.ts"), - "mini", - "--server", - registration.url, - ...(model ? ["--model", model] : []), - ] - - yield* llm.queue( - Llm.toolCall({ - index: 0, - id: "mini-shell", - name: "shell", - input: { command: "printf 'drive-mini-tool-output\\n'" }, - }), - Llm.finish("tool-calls"), - ) - yield* llm.queue(Llm.text("drive mini response complete", { delay: 5, chunkSize: 4 })) - - const journey = Effect.gen(function* () { - yield* Effect.uninterruptible( - Effect.promise(() => - tmux([ - "new-session", - "-d", - "-s", - session, - "-x", - "140", - "-y", - "30", - "--", - ...mini(path.join(artifacts, "files"), undefined), - ]), - ), - ) - yield* Effect.promise(() => tmux(["set-option", "-t", session, "remain-on-exit", "on"])) - - const first = yield* Effect.promise(() => waitForPane(session, "OpenCode")) - yield* Effect.promise(() => Bun.write(path.join(snapshots, "01-first-paint.txt"), first)) - if (first.includes("drive mini response complete")) - throw new Error("response rendered before prompt submission") - - yield* Effect.promise(() => waitForPane(session, "Default model", 15_000)) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "C-p"])) - yield* Effect.promise(() => waitForVisiblePane(session, "Commands")) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "-l", "model"])) - yield* Effect.promise(() => waitForVisiblePane(session, "Switch model")) - yield* Effect.promise(() => tmux(["send-keys", "-H", "-t", session, "0d"])) - yield* Effect.promise(() => waitForVisiblePane(session, "Select model")) - yield* Effect.promise(() => waitForVisiblePane(session, "Simulated Model", 15_000)) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "Escape"])) - yield* Effect.promise(() => waitForVisiblePane(session, "Ask anything...")) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "-l", "exercise the mini frontend"])) - yield* Effect.sleep(100) - yield* Effect.promise(() => tmux(["send-keys", "-H", "-t", session, "0d"])) - const completed = yield* Effect.promise(() => waitForPane(session, "drive mini response complete", 20_000)) - if (!completed.includes("drive-mini-tool-output")) throw new Error("shell tool output was not rendered") - yield* Effect.promise(() => Bun.write(path.join(snapshots, "02-tool-and-response.txt"), completed)) - - yield* Effect.sleep(500) - const resizeOutput = path.join(snapshots, "03-resize-output.ansi") - yield* Effect.promise(() => tmux(["pipe-pane", "-t", session, `cat > ${JSON.stringify(resizeOutput)}`])) - yield* Effect.promise(() => tmux(["resize-window", "-t", session, "-x", "72", "-y", "22"])) - yield* Effect.promise(() => - waitForFile( - resizeOutput, - (value) => value.includes("drive mini response complete") && value.includes("drive-mini-tool-output"), - ), - ) - yield* Effect.promise(() => tmux(["pipe-pane", "-t", session])) - const resized = yield* Effect.promise(() => captureVisiblePane(session)) - if (!resized.includes("drive-mini-tool-output")) throw new Error("resize replay lost shell tool output") - yield* Effect.promise(() => Bun.write(path.join(snapshots, "03-resize-replay.txt"), resized)) - - yield* llm.queue( - Llm.toolCall({ - index: 0, - id: "mini-question", - name: "question", - input: { - questions: [ - { - header: "Drive form", - question: "Choose the Mini Form answer", - options: [{ label: "Accepted", description: "Continue the run" }], - multiple: false, - }, - ], - }, - }), - Llm.finish("tool-calls"), - ) - yield* llm.queue(Llm.text("drive mini form complete")) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "-l", "exercise the form"])) - yield* Effect.promise(() => tmux(["send-keys", "-H", "-t", session, "0d"])) - yield* Effect.promise(() => waitForPane(session, "Choose the Mini Form answer", 20_000)) - yield* Effect.promise(() => tmux(["send-keys", "-H", "-t", session, "0d"])) - yield* Effect.promise(() => waitForPane(session, "drive mini form complete", 20_000)) - - yield* llm.queue( - Llm.toolCall({ - index: 0, - id: "mini-slow-shell", - name: "shell", - input: { command: "sleep 10" }, - }), - Llm.finish("tool-calls"), - ) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "-l", "interrupt this turn"])) - yield* Effect.sleep(100) - yield* Effect.promise(() => tmux(["send-keys", "-H", "-t", session, "0d"])) - yield* Effect.promise(() => waitForPane(session, "$ sleep 10")) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "Escape"])) - const armed = yield* Effect.promise(() => waitForPane(session, "esc again")) - yield* Effect.promise(() => Bun.write(path.join(snapshots, "04-interrupt-armed.txt"), armed)) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "Escape"])) - const interrupted = yield* Effect.promise(() => waitForPane(session, "Step interrupted", 10_000)) - yield* Effect.promise(() => Bun.write(path.join(snapshots, "05-interrupted.txt"), interrupted)) - - yield* Effect.promise(async () => { - if (!(await paneAlive(session))) throw new Error("Mini exited while interrupting an active turn") - }) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "C-c"])) - yield* Effect.promise(() => waitForPane(session, "EXIT Press ctrl+")) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "C-c"])) - yield* Effect.promise(() => waitForDeadPane(session)) - const status = yield* Effect.promise(() => paneDeadStatus(session)) - if (status !== 0) throw new Error(`Mini exited with status ${status}`) - const exited = yield* Effect.promise(() => capturePane(session)) - if (!exited.includes("Continue") || !exited.includes("opencode mini -s")) - throw new Error("Mini exit splash was not rendered before teardown") - yield* Effect.promise(() => Bun.write(path.join(snapshots, "06-exit-teardown.txt"), exited)) - - yield* Effect.promise(() => tmux(["clear-history", "-t", session])) - yield* Effect.promise(() => - tmux(["respawn-pane", "-k", "-t", session, "--", ...mini(explicitDirectory, "simulation/gpt-sim-model")]), - ) - const explicitModel = yield* Effect.promise(() => waitForPane(session, "Simulated Model", 15_000)) - yield* Effect.promise(() => Bun.write(path.join(snapshots, "07-explicit-model.txt"), explicitModel)) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "C-c"])) - yield* Effect.promise(() => waitForPane(session, "EXIT Press ctrl+")) - yield* Effect.promise(() => tmux(["send-keys", "-t", session, "C-c"])) - yield* Effect.promise(() => waitForDeadPane(session)) - if ((yield* Effect.promise(() => paneDeadStatus(session))) !== 0) - throw new Error("Explicit-model Mini did not exit cleanly") - - yield* Effect.promise(async () => { - for (const failure of [ - { - args: ["--model", "simulation/definitely-missing"], - capture: "08-unavailable-model.txt", - expected: "Model unavailable: simulation/definitely-missing", - }, - { - args: ["--agent", "definitely-missing"], - capture: "09-unavailable-agent.txt", - expected: 'Agent not found: "definitely-missing"', - }, - ]) { - const child = Bun.spawn( - [ - process.execPath, - path.join(root, "packages/cli/src/index.ts"), - "run", - "--server", - registration.url, - ...failure.args, - "optimistic selection check", - ], - { - cwd: path.join(root, "packages/cli"), - env: { - ...process.env, - PWD: path.join(artifacts, "files"), - OPENCODE_PASSWORD: registration.password, - OPENCODE_CONFIG_DIR: path.join(artifacts, "files/.opencode"), - OPENCODE_DISABLE_AUTOUPDATE: "1", - }, - stdin: "ignore", - stdout: "pipe", - stderr: "pipe", - }, - ) - const [exitCode, stdout, stderr] = await Promise.all([ - child.exited, - new Response(child.stdout).text(), - new Response(child.stderr).text(), - ]) - await Bun.write(path.join(snapshots, failure.capture), stdout + stderr) - if (exitCode !== 1) throw new Error(`${failure.expected} run exited with status ${exitCode}`) - if (!stderr.includes(failure.expected)) - throw new Error(`Selection failure was not diagnosed by execution: ${stderr}`) - } - }) - }) - - yield* journey.pipe(Effect.ensuring(Effect.promise(() => tmux(["kill-session", "-t", session], true)))) - }), -}) - -/** @param {string[]} args */ -async function tmux(args, allowFailure = false) { - const child = Bun.spawn(["tmux", ...args], { stdout: "pipe", stderr: "pipe" }) - let timedOut = false - const timeout = setTimeout(() => { - timedOut = true - child.kill("SIGKILL") - }, 5_000) - const [status, stdout, stderr] = await Promise.all([ - child.exited, - new Response(child.stdout).text(), - new Response(child.stderr).text(), - ]) - clearTimeout(timeout) - if (timedOut) throw new Error(`tmux ${args[0]} timed out`) - if (status !== 0 && !allowFailure) throw new Error(`tmux ${args[0]} failed: ${stderr || stdout}`) - return stdout -} - -/** @param {string} session */ -function capturePane(session) { - return tmux(["capture-pane", "-p", "-t", session, "-S", "-"]) -} - -/** @param {string} session */ -function captureVisiblePane(session) { - return tmux(["capture-pane", "-p", "-t", session]) -} - -/** @param {string} session @param {string} text @param {number} [timeout] */ -async function waitForVisiblePane(session, text, timeout = 5_000) { - const deadline = Date.now() + timeout - let last = "" - while (Date.now() < deadline) { - last = await captureVisiblePane(session) - if (last.includes(text)) return last - if (!(await paneAlive(session))) throw new Error(`Mini exited before rendering ${JSON.stringify(text)}:\n${last}`) - await Bun.sleep(50) - } - throw new Error(`Timed out waiting for visible ${JSON.stringify(text)}:\n${last}`) -} - -/** @param {string} session */ -async function paneAlive(session) { - return (await tmux(["display-message", "-p", "-t", session, "#{pane_dead}"], true)).trim() === "0" -} - -/** @param {string} session */ -async function paneDeadStatus(session) { - return Number((await tmux(["display-message", "-p", "-t", session, "#{pane_dead_status}"])).trim()) -} - -/** - * @param {string} session - * @param {string} text - * @param {number} [timeout] - * @param {(() => Promise) | undefined} [trigger] - */ -async function waitForPane(session, text, timeout = 5_000, trigger) { - const deadline = Date.now() + timeout - let last = "" - while (Date.now() < deadline) { - await trigger?.() - last = await capturePane(session) - if (last.includes(text)) return last - if (!(await paneAlive(session))) throw new Error(`Mini exited before rendering ${JSON.stringify(text)}:\n${last}`) - await Bun.sleep(50) - } - throw new Error(`Timed out waiting for ${JSON.stringify(text)}:\n${last}`) -} - -/** @param {string} session */ -async function waitForDeadPane(session) { - for (let attempt = 0; attempt < 100; attempt++) { - if (!(await paneAlive(session))) return - await Bun.sleep(50) - } - throw new Error("Mini did not tear down after the exit sequence") -} - -/** - * @param {string} file - * @param {(value: string) => boolean} accept - */ -async function waitForFile(file, accept) { - let value = "" - for (let attempt = 0; attempt < 100; attempt++) { - value = await Bun.file(file) - .text() - .catch(() => "") - if (accept(value)) return value - await Bun.sleep(50) - } - throw new Error("resize did not replay committed transcript output") -} - -/** @param {string} artifacts */ -async function configureServicePort(artifacts) { - const probe = Bun.serve({ hostname: "127.0.0.1", port: 0, fetch: () => new Response() }) - const port = probe.port - await probe.stop(true) - if (!port) throw new Error("Failed to allocate a Drive service port") - const file = path.join(artifacts, "files/.opencode/service-local.json") - await mkdir(path.dirname(file), { recursive: true }) - await Bun.write(file, JSON.stringify({ port })) -} - -/** @param {string} artifacts */ -async function serviceRegistration(artifacts) { - const directory = path.join(artifacts, "home/.local/state/opencode") - for (let attempt = 0; attempt < 200; attempt++) { - for (const name of ["service-local.json", "service.json"]) { - const value = await Bun.file(path.join(directory, name)) - .json() - .catch(() => undefined) - if (isRegistration(value)) return value - } - await Bun.sleep(50) - } - throw new Error("Drive service registration was not written") -} - -/** @param {unknown} value */ -function isRegistration(value) { - return ( - typeof value === "object" && - value !== null && - "url" in value && - typeof value.url === "string" && - "password" in value && - typeof value.password === "string" - ) -} diff --git a/packages/cli/test/drive/run-smoke.drive.mjs b/packages/cli/test/drive/run-smoke.drive.mjs deleted file mode 100644 index d462a2feb3a..00000000000 --- a/packages/cli/test/drive/run-smoke.drive.mjs +++ /dev/null @@ -1,87 +0,0 @@ -import { defineScript } from "opencode-drive" -import { mkdir } from "node:fs/promises" -import path from "node:path" - -export default defineScript({ - launch: "manual", - setup({ config }) { - config.autoupdate = false - }, - async run({ artifacts, llm, server }) { - await configureServicePort(artifacts) - llm.queue(llm.text("drive noninteractive smoke ok")) - await server.launch() - - const registration = await serviceRegistration(artifacts) - const root = path.resolve(import.meta.dir, "../../../..") - const directory = path.join(artifacts, "files") - const child = Bun.spawn( - [ - process.execPath, - path.join(root, "packages/cli/src/index.ts"), - "run", - "--server", - registration.url, - "drive smoke", - ], - { - cwd: path.join(root, "packages/cli"), - env: { - ...process.env, - PWD: directory, - OPENCODE_PASSWORD: registration.password, - OPENCODE_CONFIG_DIR: path.join(directory, ".opencode"), - OPENCODE_DISABLE_AUTOUPDATE: "1", - }, - stdin: "ignore", - stdout: "pipe", - stderr: "pipe", - }, - ) - const [exitCode, stdout, stderr] = await Promise.all([ - child.exited, - new Response(child.stdout).text(), - new Response(child.stderr).text(), - ]) - if (exitCode !== 0) throw new Error(`run exited ${exitCode}: ${stderr}`) - if (stdout !== "drive noninteractive smoke ok\n") throw new Error(`unexpected run output: ${stdout}`) - }, -}) - -/** @param {string} artifacts */ -async function configureServicePort(artifacts) { - const probe = Bun.serve({ hostname: "127.0.0.1", port: 0, fetch: () => new Response() }) - const port = probe.port - await probe.stop(true) - if (!port) throw new Error("Failed to allocate a Drive service port") - const file = path.join(artifacts, "files/.opencode/service-local.json") - await mkdir(path.dirname(file), { recursive: true }) - await Bun.write(file, JSON.stringify({ port })) -} - -/** @param {string} artifacts */ -async function serviceRegistration(artifacts) { - const directory = path.join(artifacts, "home/.local/state/opencode") - for (let attempt = 0; attempt < 200; attempt++) { - for (const name of ["service-local.json", "service.json"]) { - const value = await Bun.file(path.join(directory, name)) - .json() - .catch(() => undefined) - if (isRegistration(value)) return value - } - await Bun.sleep(50) - } - throw new Error("Drive service registration was not written") -} - -/** @param {unknown} value */ -function isRegistration(value) { - return ( - typeof value === "object" && - value !== null && - "url" in value && - typeof value.url === "string" && - "password" in value && - typeof value.password === "string" - ) -} diff --git a/packages/drive/CHANGELOG.md b/packages/drive/CHANGELOG.md deleted file mode 100644 index 11df70f97b1..00000000000 --- a/packages/drive/CHANGELOG.md +++ /dev/null @@ -1,89 +0,0 @@ -# opencode-drive - -## 1.4.3 - -### Patch Changes - -- 99561ad: Restore controlled tools against the current V2 plugin API and add typed runtime control for write calls. - -## 1.4.2 - -### Patch Changes - -- b524213: Render light box-drawing borders as continuous geometric primitives. -- a24a09d: Defer recording font initialization so source-checkout scripts can start without loading a duplicate renderer. - -## 1.4.1 - -### Patch Changes - -- 6a8d52b: Prevent concurrent detached launchers from stealing prepared instance ownership and spawning competing daemon processes. -- d71356f: Restore compatibility with current OpenCode V2 checkouts and packed Drive installations. Drive now uses V2's built-in simulation transport and provider shape, isolates scripted service ports and command forms, and compiles standalone scripts against the launching Drive toolchain without package installation or source-directory links. - -## 1.4.0 - -### Minor Changes - -- c20d147: Control arbitrary provider-backed tool lifecycles with dynamic registration, structured progress, success, failure, cancellation, and reconnect-safe replay. - -## 1.3.0 - -### Minor Changes - -- 7caebeb: Expose semantic UI snapshots, exact semantic node polling, and safe semantic-node clicks for compatible OpenCode endpoints. - -## 1.2.0 - -### Minor Changes - -- 4e0c002: Write screenshots and recordings beneath run- and restart-scoped media directories so named outputs cannot overwrite earlier runs. - -## 1.1.0 - -### Minor Changes - -- fad9f96: Allow scripts and library drivers to intercept declared tools and control concurrent invocations by call ID at runtime. - -### Patch Changes - -- 63d3464: Keep service and progress output out of visible TUI sessions and avoid reinstalling the OpenTUI preload package for development checkouts. -- fd45cfe: Allow Drive runs to select a durable OpenCode database with the Effect-configured `OPENCODE_DRIVE_DB` setting while retaining `:memory:` as the default. -- e66adc1: Preserve recorded frame timing during MP4 encoding and reduce work for dense or unchanged terminal output. -- e7dff5f: Render diagonal quadrant block glyphs as exact terminal cell geometry in screenshots, recordings, and catalog frames. -- 63d3464: Export recordings at 60 FPS by default and preserve the requested frame rate in generated MP4 files. - -## 1.0.0 - -### Major Changes - -- 1009394: Remove the Promise-based simulation clients. `SimulationClient`, `BackendSimulationClient`, `connectSimulation`, and `connectBackendSimulation` are gone, along with the `opencode-drive/experimental` entry point. The `opencode-drive/client` entry now exports only the canonical protocol schemas and default ports; the public API is Effect-only, as documented. The CLI drives instances through the Effect `SimulationConnector` directly. - -### Minor Changes - -- 9deab8d: Add the browser-safe `opencode-drive/frame` entry point: canonical cell geometry, OpenTUI text-attribute bits, the geometric block/bar glyph table, and baseline placement shared by the Drive PNG renderer and downstream canvas renderers. The PNG renderer now also draws the `┃` and `╹` structural bars geometrically instead of with fonts. - -### Patch Changes - -- 8481090: Settle simulated LLM responses cleanly when OpenCode terminates an invocation during interruption. Drive now uses the negotiated `llm.pending` capability to distinguish external termination from genuine response write failures. - -## 0.6.0 - -### Minor Changes - -- 58c4801: Return simulated background shells immediately, continue their handlers asynchronously, notify the session when they finish, and cancel them when Drive shuts down. -- b5e8dfe: Make the script API Effect-only. Script setup and run callbacks, UI, LLM, filesystem, server, and TUI operations now return Effects; LLM serve handlers return Streams; and script cancellation uses Effect interruption without a Promise compatibility shim. -- 775f799: Remove the tool handler `AbortSignal`. Foreground session interruption, transport disconnects, and Drive shutdown now surface uniformly as Effect interruption, and controller shutdown awaits handler finalizers. Detached background shell handlers remain active after launch and are interrupted during Drive shutdown. -- 8e51796: Add deterministic shell, web fetch, and web search handlers with progress, success, failure, and interruption simulation. -- 905f846: Add `opencode-drive script init` for generating an Effect-native starter script and show focused migration guidance when `check` finds Promise-style script callbacks. -- d1bba54: Add first-class tool call input streaming through `Llm.toolCall` stream options. -- 72f7aff: Expose the authenticated generated OpenCode SDK as `opencode` to drivers and scripts. -- 37b4cd1: Give capabilities precise typed errors, validate UI predicates in canonical `ui.waitFor`, expose concrete failures through `Errors`, and keep pure response constructors exclusively under `Llm`. -- 13ec474: Unify the Effect driver and `defineScript` around one canonical programmatic model. Both expose the generated SDK as `opencode`, the primary frontend as `tui`, additional frontends through `tuis`, and the primary UI as `ui`. Every `Tui` has the same `{ ui, close, recording }` shape and `{ recording, viewport }` options. Project setup now uses the shared `Project`, `Setup`, `SetupContext`, and `ProjectFileSystem` types. Remove duplicate script UI types, flattened frontend handles, partial settlement controls, root-level raw simulation exports, convenience CLI aliases, and the `wait` helper. - -### Patch Changes - -- c8f5b51: Attach one best-effort normalized terminal frame to UI polling timeout errors without retaining screenshot artifacts. -- c8f5b51: Render OpenCode's full UI symbol set with deterministic bundled fallback fonts instead of platform fonts or hand-drawn symbol exceptions. -- c8f5b51: Preserve the managed driver's `Scope.Scope` requirement when consumed from TypeScript workspace applications. -- 40d2241: Render the background completion arrow correctly in exported recordings. -- 11cbbfd: Preserve the canonical OpenCode UI command shapes for optional named screenshots and key presses. diff --git a/packages/drive/LICENSE b/packages/drive/LICENSE deleted file mode 100644 index cf52343bc39..00000000000 --- a/packages/drive/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 opencode-drive - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/drive/README.md b/packages/drive/README.md deleted file mode 100644 index ca06d5282d2..00000000000 --- a/packages/drive/README.md +++ /dev/null @@ -1,565 +0,0 @@ -# opencode-drive - -This project gives your agents control over OpenCode: - -- Run it during development and let your agents see and poke at the running instance -- Allow your agents to run it in headless mode and drive it to test things - -## Requirements - -OpenCode Drive requires [Bun](https://bun.sh/) 1.3.14 or newer. MP4 recording export also requires `ffmpeg` on `PATH`. - -Install dependencies with: - -```sh -bun install -``` - -## Skill - -```sh -npx skills add anomalyco/opencode --agent opencode --skill opencode-drive -``` - -## Effect programs - -The primary way to automate OpenCode is a default-exported, fully provided -Effect. Drive type-checks the module contract, compiles the script and its local -imports against the launching Drive toolchain, then validates and runs the -export in an isolated Bun process: - -```ts -// drive.ts -import { OpenCodeDriver } from "opencode-drive" - -export default OpenCodeDriver.use(({ ui }) => ui.screenshot("home")) -``` - -```sh -opencode-drive run ./drive.ts -``` - -`run` accepts exactly one module path. It rejects `--command.*` flags, other -command flags, and application arguments after `--`. Backend and UI behavior -belongs in the Effect program. - -`OpenCodeDriver.use` is the safe default. It owns the scope, observes backend -failure, settles queued LLM work, closes every TUI, and exports recordings -whether the program succeeds or fails: - -```ts -import { Effect } from "effect" -import { Llm, OpenCodeDriver } from "opencode-drive" - -export default OpenCodeDriver.use( - { - project: { - git: true, - files: { "src/value.ts": "export const value = 1\n" }, - }, - }, - ({ ui, llm }) => - Effect.gen(function* () { - yield* llm.queue(Llm.text("The value is 1.")) - yield* ui.submit("Read src/value.ts") - yield* ui.waitFor("The value is 1.") - }), -) -``` - -Use `OpenCodeDriver.useReport` when the program also needs structured evidence. -It returns the program value plus a schema-validated report containing branded -artifact and recording paths, retention, and the negotiated or legacy -compatibility of every simulation endpoint: - -```ts -const result = yield * OpenCodeDriver.useReport(options, program) -yield * Effect.log(result.report) -``` - -Drive prefers `simulation.handshake` and explicitly records legacy fallback. -Require negotiation when protocol skew must fail before the program runs: - -```ts -OpenCodeDriver.use( - { - opencode: { compatibility: "required" }, - }, - program, -) -``` - -Additional TUIs share the same server and LLM controller: - -```ts -import { Effect } from "effect" -import { OpenCodeDriver } from "opencode-drive" - -export default OpenCodeDriver.use((oc) => - Effect.gen(function* () { - const secondary = yield* oc.tuis.launch({ - viewport: { cols: 120, rows: 40 }, - }) - yield* oc.ui.screenshot("primary") - yield* secondary.ui.screenshot("secondary") - }), -) -``` - -The generated OpenCode SDK client is exposed as `opencode`; launched frontend -processes are `tui` and `tuis`. This keeps SDK calls distinct from terminal UI -control: - -```ts -const health = yield * opencode.health.get() -const frame = yield * tui.ui.capture() -``` - -Enable recording per TUI. Settlement finishes each timeline and exports its -video automatically: - -```ts -import { Effect } from "effect" -import { OpenCodeDriver } from "opencode-drive" - -export default OpenCodeDriver.use({ tui: { recording: true } }, (oc) => - Effect.gen(function* () { - yield* oc.ui.screenshot("recorded-home") - yield* Effect.log(`recording will be exported to ${oc.tui.recording?.path}`) - }), -) -``` - -Settlement errors are program failures. For example, output after a terminal -LLM event fails the run while `use` still closes TUIs and attempts recording -export: - -```ts -import { Effect } from "effect" -import { Llm, OpenCodeDriver } from "opencode-drive" - -export default OpenCodeDriver.use(({ ui, llm }) => - Effect.gen(function* () { - yield* llm.queue(Llm.finish(), Llm.text("too late")) - yield* ui.submit("trigger a response") - }), -) -``` - -Use `OpenCodeDriver.make` only when the program needs explicit terminal -settlement. It requires a scope, and `driver.settle()` must run before leaving -that scope: - -```ts -import { Effect } from "effect" -import { OpenCodeDriver } from "opencode-drive" - -export default Effect.scoped( - Effect.gen(function* () { - const driver = yield* OpenCodeDriver.make() - yield* driver.ui.screenshot("home") - yield* driver.settle() - }), -) -``` - -Use `opencode-drive check ./drive.ts` and `start --script` for the Effect-native -`defineScript` workflow described below. - -## OpenCode development - -Run this: - -```sh -OPENCODE_DRIVE=1 bun run dev -``` - -If you installed the skill file, OpenCode will be able to see and interact with the running instance. - -## Using with agents - -Install the skill file above and ask the agent to test various flows with the app. Start with `--record` when you want a video; `opencode-drive stop` then exports the complete session and prints its path. - -Screenshots and videos are written beneath `/opencode-drive/output//`, so named outputs cannot overwrite media from earlier runs or restarts. Set `OPENCODE_DRIVE_MEDIA_DIR` to use a different media root. - -Captured frames use the official full Commit Mono v1.143 faces at 16px with bundled Noto Symbols, Symbols 2, and Math fallbacks in a fixed 10x20 cell grid. Set `OPENCODE_DRIVE_FONT` to a comma-separated list of font files (for example regular, bold, italic, and bold-italic faces) to use a different primary capture font without changing the symbol fallback or cell geometry. - -## UI development - -If you are doing UI development in OpenCode, you might want to run it in a simulated mode. This allows `opencode-drive` to drive it and always put it into a state that you want to see. - -Run it in visible mode: - -```sh -opencode-drive start --visible --dev ~/projects/opencode -``` - -Initialize first when you need to customize the isolated environment before OpenCode starts: - -```sh -artifacts=$(opencode-drive init --name demo) -cp -R ./fixtures/home/. "$artifacts/" -cp -R ./fixtures/project/. "$artifacts/files/" -opencode-drive start --name demo --visible --dev ~/projects/opencode -``` - -`start` reuses the prepared artifacts for that name. If `init` was not run, `start` initializes them automatically. - -Drive uses an in-memory OpenCode database by default. Set -`OPENCODE_DRIVE_DB` when a test restarts the OpenCode service and needs sessions -to survive the replacement process. Relative paths resolve inside the isolated -run's OpenCode data directory: - -```sh -OPENCODE_DRIVE_DB=restart.sqlite \ - opencode-drive start --name restart-demo --script ./restart.ts -``` - -Remove artifact directories left by sessions that are no longer active: - -```sh -opencode-drive prune -``` - -Prune one inactive instance's artifacts by instance name, or force removal of all artifact directories: - -```sh -opencode-drive prune --name demo -opencode-drive prune --force -``` - -While developing, you can run `opencode-drive restart` to restart only the UI (the server will persist as a separate process). Do this with agents, and they will always restart and get the UI where you want it to be automatically. - -View the [skills file](https://github.com/anomalyco/opencode/blob/v2/.opencode/skills/opencode-drive/SKILL.md) for more details about the CLI. - -## Effect script API - -Scripted runs use one fully typed, Effect-only definition. `setup` and `run` -return Effects; Promise callbacks are not part of the API: - -```sh -opencode-drive script init ./drive.ts -``` - -This creates a canonical starter without overwriting an existing file. The -generated script is ready for `opencode-drive check ./drive.ts` and -`start --script ./drive.ts`. - -```ts -import { defineScript, Effect, Llm } from "opencode-drive" - -export default defineScript({ - config: { - autoupdate: false, - }, - tuiConfig: { - theme: "system", - }, - project: { - git: true, - files: { - "src/example.ts": "export const value = 1\n", - }, - }, - setup: ({ config, tuiConfig }) => - Effect.sync(() => { - config.username = "Drive" - tuiConfig.scroll_speed = 1 - }), - run: ({ ui, llm }) => - Effect.gen(function* () { - yield* ui.submit("Read src/example.ts") - yield* llm.send(Llm.text("The value is 1.")) - yield* ui.waitFor("The value is 1.") - }), -}) -``` - -`project.files` seeds the isolated project before `setup` runs. With -`project.git: true`, Drive creates a fresh repository and commits the complete -pre-launch state, including files written in `setup`. A prepared repository is -never replaced; omit `project.git` when an `init` step supplies Git history. -Declared `config` and `tuiConfig` values are deeply merged over fixture -`.opencode/opencode.jsonc` and `.opencode/tui.jsonc` files. Arrays replace -instead of merging, and mutations made in `setup` take final precedence. - -Attach arbitrary provider-backed tools at runtime with their JSON schemas, then -take and settle native OpenCode invocations by model call ID. `attach` replaces -the complete dynamic set atomically; it does not affect the built-in adapters -configured through the driver or script `tools` option. - -```ts -import { Effect } from "effect" -import { Llm, OpenCodeDriver } from "opencode-drive" - -export default OpenCodeDriver.use(({ tools, llm, ui }) => - Effect.gen(function* () { - yield* tools.attach({ - tools: [ - { - name: "lookup", - description: "Look up a value", - inputSchema: { - type: "object", - properties: { query: { type: "string" } }, - required: ["query"], - }, - outputSchema: { - type: "object", - properties: { answer: { type: "number" } }, - required: ["answer"], - }, - options: { codemode: false }, - }, - ], - }) - yield* llm.queue( - Llm.toolCall({ - index: 0, - id: "call_lookup", - name: "lookup", - input: { query: "meaning" }, - }), - Llm.finish("tool-calls"), - ) - yield* ui.submit("Look up the meaning") - - const lookup = yield* tools.take("call_lookup") - yield* lookup.progress({ - structured: { phase: "searching" }, - content: [{ type: "text", text: "Searching" }], - }) - yield* lookup.finish({ - structured: { answer: 42 }, - content: [{ type: "text", text: "42" }], - }) - }), -) -``` - -Drive owns progress sequence numbers and retries uncertain operations without -rerunning a claimed call. `awaitCancelled()` completes when OpenCode interrupts -the native invocation before `finish` or `fail`. Dynamic registrations survive -the tool-only controller reconnecting; an intentional server generation change -cancels unresolved calls and reapplies the desired set after launch. - -Declare which built-in tools Drive should intercept with `tools`, then control -their invocations inside `run`. Each tool controller accepts calls in arrival -order or by the stable call ID chosen in `Llm.toolCall`: - -```ts -import { Effect } from "effect" -import { defineScript, Llm } from "opencode-drive" - -export default defineScript({ - tools: ["shell"], - run: ({ ui, llm, tools }) => - Effect.gen(function* () { - const shells = yield* tools.control("shell") - yield* llm.queue( - Llm.toolCall({ - index: 0, - id: "call_shell", - name: "shell", - input: { command: "deploy production" }, - }), - Llm.finish("tool-calls"), - ) - yield* ui.submit("Deploy production") - const shell = yield* shells.take("call_shell") - yield* shell.progress(`Running: ${shell.input.command}...\n`) - yield* shell.succeed({ output: "Controlled output\n", exit: 0 }) - }), -}) -``` - -Use `calls.take(id)` to coordinate known parallel calls independently, or -`calls.take()` to accept the next unclaimed invocation. A controlled call can -emit progress and then succeed or fail exactly once. `awaitInterrupted()` -observes OpenCode interruption or transport disconnection. Drive interrupts -all unresolved calls when it shuts down. - -The original `tools(registry)` callback remains available for fixed handlers -that do not need orchestration from `run`. Foreground handler Effects are -interrupted when OpenCode interrupts the session, the transport disconnects, -or Drive shuts down. Detached background shell handlers continue after their -launch response and are interrupted when Drive shuts down. - -Only declared or registered tools are replaced. Unhandled tools continue to -use OpenCode's real implementations. Each `progress` value replaces the -visible tool output; send accumulated output when earlier lines should remain -visible. -Supported adapters are `shell`, `webfetch`, and `websearch`; each handler -receives its canonical typed V2 input and maintains an independent call index. -When a shell call sets `background: true`, Drive returns immediately with the -OpenCode tool call ID as `shellID`, keeps the handler running, and injects the -terminal `completed`, `error`, or `cancelled` result into the session -automatically. Background handlers are cancelled when Drive shuts down. - -Type-check every new or edited script before running it: - -```sh -opencode-drive check ./drive.ts -``` - -Drive resolves its script API, Effect, Bun declarations, and `tsgo` from the -launching installation without installing packages or modifying the script's -directory. When it detects an old Promise-style `setup`, `run`, or `ui.waitFor` -callback, it prints the equivalent Effect shape after the TypeScript -diagnostics. Use `Effect.sleep(milliseconds)` for unconditional delays. - -The `fs`, `ui`, `llm`, `tools`, `server`, and `tuis` capabilities expose -Effect-returning operations. Compose them with `yield*`, `Effect.flatMap`, or -other Effect operators. Scripts receive the same `Ui`, `Tui`, `Tuis`, and TUI -options as `OpenCodeDriver`; `defineScript` does not define a second -programmatic interface. Predicates passed to `ui.waitFor` may return a boolean -or an Effect. Set `launch: "manual"` to launch the shared OpenCode server and -every TUI explicitly: - -```ts -import { Effect } from "effect" -import { defineScript } from "opencode-drive" - -export default defineScript({ - launch: "manual", - run: ({ ui, server, tuis }) => - Effect.gen(function* () { - // ui is null in manual mode. - yield* server.launch() - const alice = yield* tuis.launch("alice") - const bob = yield* tuis.launch("bob") - yield* alice.ui.submit("Hello from Alice") - yield* bob.ui.screenshot("bob-view") - }), -}) -``` - -Only one server may be launched per script. All TUIs share its LLM backend. TUI -processes and compiled script artifacts are cleaned up when the script ends. - -`yield* server.kill()` stops the server so it can be launched again later. -`yield* tui.close()` closes a TUI, after which its name may be reused. - -Pass `{ recording: true }` to record an individual TUI: - -```ts -const alice = yield * tuis.launch("alice", { recording: true }) -yield * alice.ui.submit("Hello") -yield * alice.close() -``` - -Recordings are exported when the script settles. Call -`alice.recording.finish()` only when the video is needed before settlement. - -Background title requests receive `OpenCode Drive` by default and do not -consume `llm.queue`, `llm.send`, or `llm.serve` responses. Manual-launch -scripts can customize them before starting the server: - -```ts -yield * llm.title(() => Effect.succeed("Custom title")) -yield * server.launch() -``` - -Use `yield* llm.send(...)` to wait for and complete the next request or `yield* -llm.queue(...)` to declare future responses upfront. For ongoing responses, -the handler passed to `llm.serve` returns an Effect `Stream`: - -```ts -import { Stream } from "effect" -import { Llm } from "opencode-drive" - -yield * llm.serve((_request, index) => Stream.make(Llm.text(`Response ${index + 1}`))) -``` - -The backend connection, default `finish("stop")`, and cleanup are automatic. -Cancellation is represented by Effect interruption: interrupting the script or -the fiber running an operation interrupts its in-flight work and runs scoped -finalizers. There is no Promise compatibility shim or separate cancellation -API. All public script types are canonically defined in -[`src/script/types.ts`](./src/script/types.ts), which can be provided directly -to an authoring agent. - -`Llm.text()` streams text in randomized chunks. It defaults to a 2 ms delay and -a target chunk size of 15 characters, varied by plus or minus 5 per chunk: - -```ts -Llm.text("A deliberately slower response", { delay: 20, chunkSize: 10 }) -``` - -`Llm.reasoning()` accepts the same streaming options. Use -`Llm.pause(milliseconds)` to add timing between any two outputs. - -`Llm.toolCall()` emits a complete call atomically by default. Pass the same -streaming options to expose partial JSON input while it is generated: - -```ts -Llm.toolCall( - { - index: 0, - id: "call_patch", - name: "patch", - input: { patchText: "*** Begin Patch\n*** End Patch" }, - }, - { delay: 40, chunkSize: 12 }, -) -``` - -Finish a tool-calling response with `Llm.finish("tool-calls")`. Streamed calls -drive OpenCode's normal tool-input start, delta, and end lifecycle; `Llm.raw()` -remains available for provider-wire scenarios not covered by these helpers. - -Current OpenCode simulation endpoints expose a semantic UI tree alongside -renderer state and terminal capture. Use `ui.snapshot()` for the complete -versioned tree or `ui.getNode()` to poll for one exact semantic match. Semantic -nodes carry stable IDs, optional occurrence identity, role, label, hierarchy, -component-owned state, and a transient element handle that `ui.click()` can -resolve safely: - -```ts -const allow = - yield * - ui.getNode({ - role: "option", - label: "Allow once", - selected: true, - disabled: false, - }) - -yield * ui.click(allow) -``` - -`ui.snapshot` and atomic semantic clicks are negotiated as optional -capabilities so ordinary operations remain compatible with older OpenCode -checkouts. Calling `ui.snapshot()`, `ui.getNode()`, or `ui.click(node)` when its -required capability is unavailable fails locally with `UiCapabilityError`. - -Capability errors are typed and the concrete classes are grouped under -`Errors`. UI timeouts remain owner-fatal even when caught; recover locally -from errors for which the script has a truthful fallback: - -Polling timeouts from `ui.waitFor`, `ui.getElement`, and `ui.getNode` make one -best-effort, bounded `ui.capture` request. When it succeeds, the resulting -normalized terminal frame is available as `error.frame` without creating or -retaining a screenshot file. RPC-level timeouts and failed diagnostic captures -leave `error.frame` undefined. - -```ts -import { Effect } from "effect" -import { Errors } from "opencode-drive" - -yield * - ui - .getElement({ editor: true }) - .pipe(Effect.catchTag("UiElementAmbiguousError", (error) => Effect.logWarning(`Matched ${error.count} editors`))) - -const isFileSystemError = (error: unknown) => error instanceof Errors.FileSystemError -``` - -## Release validation - -Before publishing a release, run the non-publishing validation command to -check, test, and inspect the packed artifact: - -```sh -bun run release:validate -``` diff --git a/packages/drive/RELEASING.md b/packages/drive/RELEASING.md deleted file mode 100644 index 734ae592d91..00000000000 --- a/packages/drive/RELEASING.md +++ /dev/null @@ -1,27 +0,0 @@ -# Releasing opencode-drive - -`opencode-drive` keeps its own version line. OpenCode product releases must not rewrite its version. - -The imported baseline is `1.4.3` and the workspace package remains `private` until release setup is complete. -Do not remove that guard or publish from this repository until both release gates are complete: - -1. The versions of `@opencode-ai/client` and `@opencode-ai/protocol` written into the packed Drive manifest are available on npm, including the `@opencode-ai/protocol/simulation` export. -2. npm package administration and trusted publishing move from `anomalyco/opencode-drive` to `anomalyco/opencode`. - -The npm package is currently maintained by `jlongster`, and its trusted publisher is the old repository's -`publish.yml`. James must add the destination release operator as an npm owner or update the trusted publisher -himself. Keep James as an owner through the first successful release from this repository. - -The first destination release will be `1.4.4`, which contains the pending special-key fix after `1.4.3`. Use a -dedicated GitHub-hosted workflow named `publish-drive.yml` with Node 24, npm trusted publishing, and -`id-token: write`. Its tag must be `opencode-drive-v1.4.4`; bare `v1.4.4` already belongs to OpenCode. - -Before enabling that workflow: - -1. Pack Drive and inspect the rewritten `package.json` inside the tarball. -2. Install the tarball in a clean Bun consumer and import every public export. -3. Run the installed `opencode-drive` binary and one scripted flow. -4. Configure npm's trusted publisher for `anomalyco/opencode` and `publish-drive.yml`. -5. Publish the namespaced tag and verify npm provenance points at this repository and workflow. - -After the first successful destination release, disable the old publish workflow and archive the old repository. diff --git a/packages/drive/assets/fonts/commit-mono/CommitMono-400-Italic.otf b/packages/drive/assets/fonts/commit-mono/CommitMono-400-Italic.otf deleted file mode 100644 index 94a5a7653d4a2ed53050991f262cfb235f2f0c0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 274500 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