@gajae-code/coding-agent 0.17.1 → 0.17.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +266 -0
- package/dist/types/async/job-manager.d.ts +7 -6
- package/dist/types/cli/daemon-cli.d.ts +3 -1
- package/dist/types/cli/github-release.d.ts +17 -0
- package/dist/types/cli/public-command-entry.d.ts +56 -0
- package/dist/types/cli/public-command-errors.d.ts +126 -0
- package/dist/types/cli/public-command-evidence.d.ts +99 -0
- package/dist/types/cli/public-command-help.d.ts +65 -0
- package/dist/types/cli/public-command-registry.d.ts +69 -0
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/cli/skills-cli.d.ts +5 -0
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +4 -50
- package/dist/types/commands/sdk.d.ts +20 -37
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/commands/skills.d.ts +9 -0
- package/dist/types/config/autorouting-tier-map.d.ts +24 -0
- package/dist/types/config/file-lock.d.ts +10 -1
- package/dist/types/config/model-profile-activation.d.ts +63 -4
- package/dist/types/config/model-registry.d.ts +20 -2
- package/dist/types/config/settings-schema.d.ts +11 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
- package/dist/types/coordinator-mcp/server.d.ts +3 -0
- package/dist/types/daemon/operator-contract.d.ts +5 -1
- package/dist/types/eval/js/worker-protocol.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +12 -0
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
- package/dist/types/extensibility/shared-events.d.ts +3 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
- package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/parse.d.ts +9 -1
- package/dist/types/main.d.ts +22 -0
- package/dist/types/modes/acp/acp-agent.d.ts +94 -1
- package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
- package/dist/types/modes/components/session-selector.d.ts +5 -2
- package/dist/types/modes/components/thinking-selector.d.ts +2 -1
- package/dist/types/modes/components/user-message-selector.d.ts +5 -2
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
- package/dist/types/modes/types.d.ts +2 -2
- package/dist/types/runtime/process-lifecycle.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +56 -0
- package/dist/types/runtime-mcp/pool.d.ts +17 -0
- package/dist/types/runtime-mcp/redaction.d.ts +20 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
- package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
- package/dist/types/sdk/acp/adapter.d.ts +27 -0
- package/dist/types/sdk/acp/final-text.d.ts +8 -0
- package/dist/types/sdk/broker/broker.d.ts +13 -2
- package/dist/types/sdk/broker/ensure.d.ts +46 -1
- package/dist/types/sdk/broker/identity.d.ts +3 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
- package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
- package/dist/types/sdk/broker/runtime.d.ts +1 -1
- package/dist/types/sdk/broker/session-index.d.ts +22 -3
- package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
- package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
- package/dist/types/sdk/bus/index.d.ts +19 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
- package/dist/types/sdk/cli/master-cli.d.ts +6 -10
- package/dist/types/sdk/cli/rows.d.ts +19 -1
- package/dist/types/sdk/cli/session-cli.d.ts +22 -5
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/guides/cli.d.ts +3 -4
- package/dist/types/sdk/guides/verify.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +9 -0
- package/dist/types/sdk/host/session-runtime.d.ts +31 -0
- package/dist/types/sdk/host/types.d.ts +10 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +38 -1
- package/dist/types/sdk/prompt-failure.d.ts +30 -1
- package/dist/types/sdk/prompt-status.d.ts +8 -0
- package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
- package/dist/types/sdk/router/replay-retention-gap-cache.d.ts +13 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/startup-capability.d.ts +2 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +73 -2
- package/dist/types/sdk/transport/stdio.d.ts +5 -1
- package/dist/types/session/agent-session.d.ts +168 -21
- package/dist/types/session/fallback-chain-controller.d.ts +6 -6
- package/dist/types/session/fold-coordinator.d.ts +17 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
- package/dist/types/session/session-manager.d.ts +64 -1
- package/dist/types/session/session-work-lease.d.ts +14 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
- package/dist/types/setup/provider-onboarding.d.ts +81 -1
- package/dist/types/thinking.d.ts +3 -1
- package/dist/types/tools/bash.d.ts +37 -11
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/steer-fold.d.ts +31 -0
- package/dist/types/utils/git.d.ts +28 -2
- package/dist/types/utils/mupdf-embedded.d.ts +2 -0
- package/dist/types/utils/mupdf-wasm-embedded.d.ts +2 -0
- package/dist/types/utils/mupdf.d.ts +4 -0
- package/dist/types/utils/session-title-generation.d.ts +6 -0
- package/dist/types/utils/title-generator.d.ts +11 -2
- package/dist/types/web/scrapers/types.d.ts +3 -0
- package/package.json +18 -10
- package/scripts/build-binary.ts +9 -3
- package/scripts/compile-args.ts +0 -9
- package/scripts/embed-mupdf.ts +52 -0
- package/scripts/generate-sdk-operation-inventory.ts +31 -1
- package/scripts/vendor-markit.ts +196 -0
- package/src/async/job-manager.ts +60 -9
- package/src/cli/daemon-cli.ts +53 -18
- package/src/cli/github-release.ts +87 -5
- package/src/cli/mcp-cli.ts +38 -4
- package/src/cli/public-command-entry.ts +450 -0
- package/src/cli/public-command-errors.ts +581 -0
- package/src/cli/public-command-evidence.ts +717 -0
- package/src/cli/public-command-help.ts +360 -0
- package/src/cli/public-command-registry.ts +535 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +9 -1
- package/src/cli/skills-cli.ts +46 -2
- package/src/cli.ts +61 -1
- package/src/commands/daemon.ts +65 -69
- package/src/commands/sdk.ts +232 -100
- package/src/commands/setup.ts +2 -0
- package/src/commands/skills.ts +11 -0
- package/src/config/autorouting-tier-map.ts +16 -0
- package/src/config/file-lock.ts +199 -68
- package/src/config/model-profile-activation.ts +406 -53
- package/src/config/model-registry.ts +204 -25
- package/src/config/settings-schema.ts +26 -2
- package/src/coordinator-mcp/policy.ts +10 -5
- package/src/coordinator-mcp/question-gate-codec.ts +17 -0
- package/src/coordinator-mcp/question-state.ts +175 -8
- package/src/coordinator-mcp/server.ts +528 -87
- package/src/coordinator-mcp/session-reaper.ts +6 -4
- package/src/crash/record-loader.ts +6 -2
- package/src/daemon/operator-contract.ts +26 -12
- package/src/debug/report-bundle.ts +114 -24
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
- package/src/eval/js/context-manager.ts +8 -8
- package/src/eval/js/worker-core.ts +9 -4
- package/src/eval/js/worker-protocol.ts +2 -0
- package/src/extensibility/extensions/runner.ts +52 -4
- package/src/extensibility/extensions/types.ts +10 -0
- package/src/extensibility/gjc-plugins/registry.ts +196 -37
- package/src/extensibility/runtime-skill-discovery.ts +61 -3
- package/src/extensibility/shared-events.ts +3 -1
- package/src/gjc-runtime/managed-owner-admission.ts +67 -50
- package/src/gjc-runtime/session-state-lock.ts +165 -24
- package/src/gjc-runtime/ultragoal-succession.ts +31 -3
- package/src/internal-urls/docs-index.generated.ts +21 -19
- package/src/internal-urls/embedded-protocol.ts +83 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/parse.ts +21 -1
- package/src/internal-urls/router.ts +4 -2
- package/src/main.ts +123 -55
- package/src/modes/acp/acp-agent.ts +593 -47
- package/src/modes/acp/acp-event-mapper.ts +9 -0
- package/src/modes/acp/startup-provenance.ts +59 -0
- package/src/modes/components/custom-provider-wizard.ts +308 -7
- package/src/modes/components/model-selector.ts +31 -15
- package/src/modes/components/oauth-selector.ts +9 -0
- package/src/modes/components/session-selector.ts +47 -4
- package/src/modes/components/status-line/segments.ts +6 -1
- package/src/modes/components/thinking-selector.ts +7 -3
- package/src/modes/components/user-message-selector.ts +57 -15
- package/src/modes/controllers/command-controller.ts +58 -32
- package/src/modes/controllers/extension-ui-controller.ts +33 -7
- package/src/modes/controllers/input-controller.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +177 -18
- package/src/modes/interactive-mode.ts +21 -7
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
- package/src/modes/types.ts +2 -2
- package/src/prompts/agent-fragments/browser-aside.md +1 -0
- package/src/prompts/system/title-system.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/job.md +1 -1
- package/src/prompts/tools/read.md +2 -0
- package/src/runtime/network-prewarm-service.test.ts +36 -1
- package/src/runtime/network-prewarm-service.ts +28 -3
- package/src/runtime/process-lifecycle.ts +22 -11
- package/src/runtime-mcp/config.ts +16 -1
- package/src/runtime-mcp/manager.ts +689 -55
- package/src/runtime-mcp/pool.test.ts +31 -0
- package/src/runtime-mcp/pool.ts +304 -28
- package/src/runtime-mcp/redaction.ts +42 -0
- package/src/runtime-mcp/startup-policy.ts +7 -0
- package/src/runtime-mcp/tool-bridge.ts +71 -0
- package/src/runtime-mcp/transports/http.ts +108 -25
- package/src/sdk/acp/adapter.ts +90 -9
- package/src/sdk/acp/final-text.ts +19 -2
- package/src/sdk/broker/broker.ts +378 -52
- package/src/sdk/broker/ensure.ts +97 -19
- package/src/sdk/broker/identity.ts +9 -1
- package/src/sdk/broker/lifecycle-ledger.ts +95 -31
- package/src/sdk/broker/lifecycle.ts +690 -141
- package/src/sdk/broker/runtime.ts +1 -1
- package/src/sdk/broker/session-index.ts +97 -4
- package/src/sdk/broker/spawn-authority.ts +35 -7
- package/src/sdk/broker/stderr-drainer.ts +59 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
- package/src/sdk/bus/index.ts +721 -84
- package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -3
- package/src/sdk/cli/master-cli.ts +47 -36
- package/src/sdk/cli/rows.ts +30 -7
- package/src/sdk/cli/session-cli.ts +687 -184
- package/src/sdk/client/client.ts +18 -0
- package/src/sdk/guides/catalog.ts +2 -2
- package/src/sdk/guides/cli.ts +20 -62
- package/src/sdk/guides/verify.ts +14 -0
- package/src/sdk/host/host.ts +49 -5
- package/src/sdk/host/session-runtime.test.ts +636 -9
- package/src/sdk/host/session-runtime.ts +499 -118
- package/src/sdk/host/types.ts +12 -1
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
- package/src/sdk/host/websocket-transport.ts +40 -6
- package/src/sdk/index.ts +11 -0
- package/src/sdk/prompt-deadline-flush.ts +334 -0
- package/src/sdk/prompt-deadline-manager.ts +136 -4
- package/src/sdk/prompt-failure.ts +43 -1
- package/src/sdk/prompt-status.ts +8 -0
- package/src/sdk/prompt-tool-boundary.ts +121 -0
- package/src/sdk/protocol/operation-inventory.generated.json +106 -0
- package/src/sdk/router/replay-retention-gap-cache.ts +27 -0
- package/src/sdk/router/session-router.ts +31 -4
- package/src/sdk/session.ts +194 -16
- package/src/sdk/startup-capability.ts +1 -1
- package/src/sdk/transport/relay.ts +71 -6
- package/src/sdk/transport/serve-cli.ts +494 -49
- package/src/sdk/transport/socket.ts +12 -11
- package/src/sdk/transport/stdio.ts +7 -3
- package/src/session/agent-session.ts +2437 -400
- package/src/session/fallback-chain-controller.ts +6 -7
- package/src/session/fold-coordinator.ts +24 -5
- package/src/session/internal/managed-session-scope.ts +58 -18
- package/src/session/internal/managed-session-storage.ts +304 -11
- package/src/session/session-manager.ts +382 -44
- package/src/session/session-work-lease.ts +34 -0
- package/src/session-import/codex.ts +12 -3
- package/src/setup/model-onboarding-guidance.ts +1 -1
- package/src/setup/provider-onboarding.ts +397 -24
- package/src/slash-commands/builtin-registry.ts +258 -14
- package/src/task/index.ts +14 -2
- package/src/thinking.ts +21 -2
- package/src/tools/bash.ts +98 -78
- package/src/tools/fetch.ts +119 -20
- package/src/tools/job.ts +151 -25
- package/src/tools/output-meta.ts +15 -2
- package/src/tools/path-utils.ts +27 -3
- package/src/tools/read.ts +3 -3
- package/src/tools/steer-fold.ts +107 -0
- package/src/tools/tool-catalog.generated.ts +29 -2
- package/src/tools/tool-errors.ts +4 -0
- package/src/utils/git.ts +53 -3
- package/src/utils/markit.ts +55 -41
- package/src/utils/mupdf-assets.d.ts +4 -0
- package/src/utils/mupdf-embedded.ts +4 -0
- package/src/utils/mupdf-wasm-embedded.ts +3 -0
- package/src/utils/mupdf-wasm.ts +24 -2
- package/src/utils/mupdf.ts +129 -0
- package/src/utils/session-title-generation.ts +29 -0
- package/src/utils/title-generator.ts +46 -2
- package/src/web/scrapers/types.ts +24 -3
- package/vendor/markit-ai/LICENSE +21 -0
- package/vendor/markit-ai/MANIFEST.json +412 -0
- package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/config.js +139 -0
- package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
- package/vendor/markit-ai/dist/commands/convert.js +113 -0
- package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/formats.js +92 -0
- package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/init.js +29 -0
- package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/onboard.js +61 -0
- package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/plugin.js +58 -0
- package/vendor/markit-ai/dist/config.d.ts +26 -0
- package/vendor/markit-ai/dist/config.js +42 -0
- package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/audio.js +104 -0
- package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/csv.js +83 -0
- package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/docx.js +57 -0
- package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/epub.js +128 -0
- package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
- package/vendor/markit-ai/dist/converters/github.js +148 -0
- package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/html.js +30 -0
- package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/image.js +124 -0
- package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
- package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
- package/vendor/markit-ai/dist/converters/iwork.js +391 -0
- package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/json.js +21 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
- package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
- package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
- package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
- package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
- package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
- package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
- package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/pptx.js +289 -0
- package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
- package/vendor/markit-ai/dist/converters/rss.js +138 -0
- package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
- package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
- package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/xml.js +18 -0
- package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/yaml.js +17 -0
- package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/zip.js +57 -0
- package/vendor/markit-ai/dist/index.d.ts +30 -0
- package/vendor/markit-ai/dist/index.js +26 -0
- package/vendor/markit-ai/dist/main.d.ts +2 -0
- package/vendor/markit-ai/dist/main.js +191 -0
- package/vendor/markit-ai/dist/markit.d.ts +45 -0
- package/vendor/markit-ai/dist/markit.js +267 -0
- package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
- package/vendor/markit-ai/dist/plugins/api.js +42 -0
- package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
- package/vendor/markit-ai/dist/plugins/index.js +3 -0
- package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/installer.js +176 -0
- package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
- package/vendor/markit-ai/dist/plugins/loader.js +61 -0
- package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/types.js +1 -0
- package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
- package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
- package/vendor/markit-ai/dist/providers/index.js +56 -0
- package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/openai.js +76 -0
- package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
- package/vendor/markit-ai/dist/providers/types.js +1 -0
- package/vendor/markit-ai/dist/types.d.ts +36 -0
- package/vendor/markit-ai/dist/types.js +1 -0
- package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
- package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
- package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
- package/vendor/markit-ai/dist/utils/output.js +31 -0
- package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
- package/vendor/markit-ai/dist/utils/turndown.js +70 -0
- package/vendor/markit-ai/package.json +74 -0
- package/vendor/markit-ai.patch +49 -0
|
@@ -57,10 +57,12 @@ export function selectReapableSessions(
|
|
|
57
57
|
/**
|
|
58
58
|
* Only a stale/absent endpoint makes a session permanently unreapable, so it is
|
|
59
59
|
* the sole failure that advances the force-eviction counter. Every other reap
|
|
60
|
-
* failure (close_failed, broker unavailability,
|
|
61
|
-
* and must keep retrying without ever escalating
|
|
62
|
-
* wires `reapSession` to throw `new Error(reason)`,
|
|
63
|
-
*
|
|
60
|
+
* failure (a close_failed without a stale endpoint, broker unavailability,
|
|
61
|
+
* filesystem errors) is transient and must keep retrying without ever escalating
|
|
62
|
+
* to force eviction. The server wires `reapSession` to throw `new Error(reason)`,
|
|
63
|
+
* except that a close the broker answered with endpoint_stale (close_failed with
|
|
64
|
+
* that detail) is thrown as endpoint_stale, so the reason code is the error
|
|
65
|
+
* message here.
|
|
64
66
|
*/
|
|
65
67
|
function isEndpointStaleReapError(err: unknown): boolean {
|
|
66
68
|
return (err instanceof Error ? err.message : String(err)) === "endpoint_stale";
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type CrashFingerprint,
|
|
18
18
|
type CrashProvenance,
|
|
19
19
|
computeCrashFingerprint,
|
|
20
|
+
computeHandledErrorFingerprint,
|
|
20
21
|
parseCrashRecordMarker,
|
|
21
22
|
} from "@gajae-code/utils";
|
|
22
23
|
|
|
@@ -60,8 +61,11 @@ function findBoundFingerprint(
|
|
|
60
61
|
// suffix omission against the marker rather than trusting its syntax.
|
|
61
62
|
if (remaining.length > 0) stackCandidates.push(remaining.slice(0, -1).join("\n").trimEnd());
|
|
62
63
|
for (const stack of stackCandidates) {
|
|
63
|
-
const
|
|
64
|
-
|
|
64
|
+
const input = { name, message, stack };
|
|
65
|
+
const fatalFingerprint = computeCrashFingerprint(input);
|
|
66
|
+
if (fatalFingerprint.fingerprint === markerFingerprint) return fatalFingerprint;
|
|
67
|
+
const handledFingerprint = computeHandledErrorFingerprint(input);
|
|
68
|
+
if (handledFingerprint.fingerprint === markerFingerprint) return handledFingerprint;
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* (automation); the default human output stays a concise per-daemon result.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import { replaceTabs, truncateToWidth } from "@gajae-code/tui";
|
|
16
|
+
import { sanitizeDisplayLine } from "@gajae-code/utils";
|
|
15
17
|
import type { DaemonAction, DaemonOperationResult, DaemonRecovery, DaemonStatus } from "./control-types";
|
|
16
18
|
|
|
17
19
|
/** Canonical daemon actions accepted as the leading verb. */
|
|
@@ -39,8 +41,14 @@ export function resolveDaemonAction(token: string | undefined): DaemonAction | u
|
|
|
39
41
|
return DAEMON_ACTION_ALIASES[token];
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
/**
|
|
43
|
-
export const DAEMON_EXIT = { ok: 0, failure: 1 } as const;
|
|
44
|
+
/** Public input failures exit 2; operational failures retain exit 1. */
|
|
45
|
+
export const DAEMON_EXIT = { ok: 0, failure: 1, usage: 2 } as const;
|
|
46
|
+
|
|
47
|
+
/** A refused result may follow a successful stop or spawn; snapshots and prose
|
|
48
|
+
* do not prove that no effect occurred. Only completed results prove applied. */
|
|
49
|
+
export function daemonOperationOutcome(result: DaemonOperationResult): "applied" | "unknown" {
|
|
50
|
+
return result.ok ? "applied" : "unknown";
|
|
51
|
+
}
|
|
44
52
|
|
|
45
53
|
/** Human-facing headline when a spawn/reload is refused by a live foreign identity. */
|
|
46
54
|
export const OWNERSHIP_MISMATCH_MESSAGE =
|
|
@@ -59,6 +67,10 @@ export function ownershipMismatchRecovery(): DaemonRecovery {
|
|
|
59
67
|
};
|
|
60
68
|
}
|
|
61
69
|
|
|
70
|
+
function safeDaemonText(value: string): string {
|
|
71
|
+
return truncateToWidth(replaceTabs(sanitizeDisplayLine(value).replaceAll(/[\u2028\u2029]/gu, " ")), 512);
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
function timestamp(ms: number | undefined): string | undefined {
|
|
63
75
|
if (ms === undefined) return undefined;
|
|
64
76
|
const date = new Date(ms);
|
|
@@ -73,31 +85,31 @@ export function formatDaemonStatus(status: DaemonStatus, opts: { verbose?: boole
|
|
|
73
85
|
const lines: string[] = [];
|
|
74
86
|
if (!status.configured) {
|
|
75
87
|
lines.push(`${status.kind}: not configured`);
|
|
76
|
-
if (status.runtime.warning) lines.push(` warning: ${status.runtime.warning}`);
|
|
88
|
+
if (status.runtime.warning) lines.push(` warning: ${safeDaemonText(status.runtime.warning)}`);
|
|
77
89
|
return lines.join("\n");
|
|
78
90
|
}
|
|
79
91
|
|
|
80
92
|
const meta: string[] = [];
|
|
81
93
|
if (status.pid !== undefined) meta.push(`pid ${status.pid}`);
|
|
82
|
-
if (status.ownerId) meta.push(`owner ${status.ownerId}`);
|
|
94
|
+
if (status.ownerId) meta.push(`owner ${safeDaemonText(status.ownerId)}`);
|
|
83
95
|
const rootCount = status.rootCount ?? status.roots?.length ?? 0;
|
|
84
96
|
if (rootCount > 0) meta.push(`${rootCount} root${rootCount === 1 ? "" : "s"}`);
|
|
85
97
|
|
|
86
98
|
let head = `${status.kind}: ${status.health}`;
|
|
87
99
|
if (meta.length > 0) head += ` (${meta.join(", ")})`;
|
|
88
|
-
if (status.detail) head += ` — ${status.detail}`;
|
|
100
|
+
if (status.detail) head += ` — ${safeDaemonText(status.detail)}`;
|
|
89
101
|
lines.push(head);
|
|
90
|
-
if (status.runtime.warning) lines.push(` warning: ${status.runtime.warning}`);
|
|
102
|
+
if (status.runtime.warning) lines.push(` warning: ${safeDaemonText(status.runtime.warning)}`);
|
|
91
103
|
|
|
92
104
|
if (opts.verbose) {
|
|
93
|
-
lines.push(` runtime: ${status.runtime.mode} (${status.runtime.execPath})`);
|
|
105
|
+
lines.push(` runtime: ${status.runtime.mode} (${safeDaemonText(status.runtime.execPath)})`);
|
|
94
106
|
const started = timestamp(status.startedAt);
|
|
95
107
|
if (started) lines.push(` started: ${started}`);
|
|
96
108
|
const heartbeat = timestamp(status.heartbeatAt);
|
|
97
109
|
if (heartbeat) lines.push(` heartbeat: ${heartbeat}`);
|
|
98
110
|
const roots = status.roots ?? [];
|
|
99
111
|
lines.push(` roots: ${rootCount}`);
|
|
100
|
-
for (const root of roots) lines.push(` - ${root}`);
|
|
112
|
+
for (const root of roots) lines.push(` - ${safeDaemonText(root)}`);
|
|
101
113
|
}
|
|
102
114
|
|
|
103
115
|
return lines.join("\n");
|
|
@@ -108,13 +120,15 @@ export function formatDaemonStatus(status: DaemonStatus, opts: { verbose?: boole
|
|
|
108
120
|
* <message>` head line, then any warnings, then actionable recovery steps.
|
|
109
121
|
*/
|
|
110
122
|
export function formatDaemonResult(result: DaemonOperationResult): string {
|
|
111
|
-
const lines = [
|
|
112
|
-
|
|
123
|
+
const lines = [
|
|
124
|
+
`${result.kind} ${result.action}: ${result.ok ? "ok" : "failed"} — ${safeDaemonText(result.message)}`,
|
|
125
|
+
];
|
|
126
|
+
for (const warning of result.warnings) lines.push(` warning: ${safeDaemonText(warning)}`);
|
|
113
127
|
if (result.recovery) {
|
|
114
|
-
lines.push(` ${result.recovery.summary}`);
|
|
128
|
+
lines.push(` ${safeDaemonText(result.recovery.summary)}`);
|
|
115
129
|
lines.push(" to recover:");
|
|
116
130
|
result.recovery.steps.forEach((step, i) => {
|
|
117
|
-
lines.push(` ${i + 1}. ${step}`);
|
|
131
|
+
lines.push(` ${i + 1}. ${safeDaemonText(step)}`);
|
|
118
132
|
});
|
|
119
133
|
}
|
|
120
134
|
return lines.join("\n");
|
|
@@ -6,7 +6,16 @@
|
|
|
6
6
|
import * as fs from "node:fs/promises";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import type { WorkProfile } from "@gajae-code/natives";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
APP_NAME,
|
|
11
|
+
getEffectiveLogPath,
|
|
12
|
+
getEffectiveLogsDir,
|
|
13
|
+
getLogPath,
|
|
14
|
+
getLogsDir,
|
|
15
|
+
getReportsDir,
|
|
16
|
+
isEnoent,
|
|
17
|
+
resolveEquivalentPath,
|
|
18
|
+
} from "@gajae-code/utils";
|
|
10
19
|
import type { CpuProfile, HeapSnapshot } from "./profiler";
|
|
11
20
|
import { collectSystemInfo, sanitizeEnv } from "./system-info";
|
|
12
21
|
|
|
@@ -34,6 +43,70 @@ async function readLastLines(filePath: string, n: number, maxBytes = MAX_LOG_BYT
|
|
|
34
43
|
}
|
|
35
44
|
}
|
|
36
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Both log directories can legitimately hold dated `gjc.<date>.log` files, and a
|
|
48
|
+
* reader that consults only one of them is wrong in one direction or the other.
|
|
49
|
+
*
|
|
50
|
+
* The *effective* directory is where this process writes — a trusted
|
|
51
|
+
* `GJC_LOG_DIR` pin, which the test preload sets to a per-process temp sink
|
|
52
|
+
* (issue #5618). The *canonical* directory is the config root, which carries
|
|
53
|
+
* history: previous runs, other processes, and anything written through
|
|
54
|
+
* `getLogsDir()` before this process pinned anything.
|
|
55
|
+
*
|
|
56
|
+
* Deduplicated by equivalent path, effective first. In production — and in any
|
|
57
|
+
* process that never pinned `GJC_LOG_DIR` — the two resolve to the same
|
|
58
|
+
* directory and this collapses to the single entry these readers have always
|
|
59
|
+
* used, so nothing is listed twice and no ordering changes.
|
|
60
|
+
*/
|
|
61
|
+
function logSearchDirs(): string[] {
|
|
62
|
+
const dirs: string[] = [];
|
|
63
|
+
for (const resolve of [getEffectiveLogsDir, getLogsDir]) {
|
|
64
|
+
const resolved = attemptPath(resolve);
|
|
65
|
+
if (resolved !== undefined && !dirs.includes(resolved)) dirs.push(resolved);
|
|
66
|
+
}
|
|
67
|
+
return dirs;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve a log path, or `undefined` when it is unavailable.
|
|
72
|
+
*
|
|
73
|
+
* `getLogsDir()`/`getLogPath()` throw when there is no trustworthy home. That
|
|
74
|
+
* must not deny the caller the *other* directory, which a pinned `GJC_LOG_DIR`
|
|
75
|
+
* can still supply.
|
|
76
|
+
*/
|
|
77
|
+
function attemptPath(resolve: () => string): string | undefined {
|
|
78
|
+
try {
|
|
79
|
+
return resolveEquivalentPath(resolve());
|
|
80
|
+
} catch {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Today's log text, oldest content first.
|
|
87
|
+
*
|
|
88
|
+
* Concatenated canonical-then-effective so the tail stays chronological, and the
|
|
89
|
+
* line cap is applied to the COMBINED result: capping per file would let a large
|
|
90
|
+
* history file push this process's own entries out of a bundle that still looks
|
|
91
|
+
* complete. When the two paths are the same file — production, and any process
|
|
92
|
+
* without a `GJC_LOG_DIR` pin — this is a single read of exactly the bytes the
|
|
93
|
+
* previous single-path implementation returned.
|
|
94
|
+
*/
|
|
95
|
+
async function readTodayLogText(maxLines: number): Promise<string> {
|
|
96
|
+
const parts: string[] = [];
|
|
97
|
+
const seen = new Set<string>();
|
|
98
|
+
for (const resolve of [getLogPath, getEffectiveLogPath]) {
|
|
99
|
+
const candidate = attemptPath(resolve);
|
|
100
|
+
if (candidate === undefined || seen.has(candidate)) continue;
|
|
101
|
+
seen.add(candidate);
|
|
102
|
+
const text = await readLastLines(candidate, maxLines);
|
|
103
|
+
if (text.length > 0) parts.push(text);
|
|
104
|
+
}
|
|
105
|
+
const combined = parts.join("\n");
|
|
106
|
+
const lines = combined.split("\n");
|
|
107
|
+
return lines.length > maxLines ? lines.slice(-maxLines).join("\n") : combined;
|
|
108
|
+
}
|
|
109
|
+
|
|
37
110
|
export interface ReportBundleOptions {
|
|
38
111
|
/** Session file path */
|
|
39
112
|
sessionFile: string | undefined;
|
|
@@ -101,9 +174,8 @@ export async function createReportBundle(options: ReportBundleOptions): Promise<
|
|
|
101
174
|
files.push("config.json");
|
|
102
175
|
}
|
|
103
176
|
|
|
104
|
-
// Recent logs (last 1000 lines)
|
|
105
|
-
const
|
|
106
|
-
const logs = await readLastLines(logPath, 1000);
|
|
177
|
+
// Recent logs (last 1000 lines, across both log directories)
|
|
178
|
+
const logs = await readTodayLogText(1000);
|
|
107
179
|
if (logs) {
|
|
108
180
|
data["logs.txt"] = logs;
|
|
109
181
|
files.push("logs.txt");
|
|
@@ -228,31 +300,50 @@ async function addSubagentSessions(
|
|
|
228
300
|
|
|
229
301
|
/** Get recent log entries for display (tail-limited to avoid OOM on large files). */
|
|
230
302
|
export async function getLogText(): Promise<string> {
|
|
231
|
-
return
|
|
303
|
+
return readTodayLogText(MAX_LOG_LINES);
|
|
232
304
|
}
|
|
233
305
|
|
|
234
306
|
const LOG_FILE_PATTERN = new RegExp(`^${APP_NAME}\\.(\\d{4}-\\d{2}-\\d{2})\\.log$`);
|
|
235
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Today's log file: the one this process is writing when it exists, else the
|
|
310
|
+
* canonical one. Both spellings share a basename, so the "is this today's file"
|
|
311
|
+
* filter below is unaffected by which is chosen.
|
|
312
|
+
*/
|
|
313
|
+
async function resolveTodayLogPath(): Promise<string> {
|
|
314
|
+
const effective = getEffectiveLogPath();
|
|
315
|
+
if (await Bun.file(effective).exists()) return effective;
|
|
316
|
+
const canonical = attemptPath(getLogPath);
|
|
317
|
+
if (canonical !== undefined && (await Bun.file(canonical).exists())) return canonical;
|
|
318
|
+
return effective;
|
|
319
|
+
}
|
|
320
|
+
|
|
236
321
|
export async function createDebugLogSource(): Promise<DebugLogSource> {
|
|
237
|
-
const
|
|
238
|
-
const todayPath = getLogPath();
|
|
322
|
+
const todayPath = await resolveTodayLogPath();
|
|
239
323
|
const todayName = path.basename(todayPath);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
.
|
|
250
|
-
.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
324
|
+
// Absolute paths, not bare names: entries can come from either log directory
|
|
325
|
+
// (see {@link logSearchDirs}), so the name alone no longer locates the file.
|
|
326
|
+
const olderFiles: string[] = [];
|
|
327
|
+
const dated: { path: string; date: string }[] = [];
|
|
328
|
+
const seen = new Set<string>();
|
|
329
|
+
for (const dir of logSearchDirs()) {
|
|
330
|
+
// A missing directory contributes nothing; the other one may still exist.
|
|
331
|
+
const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
332
|
+
for (const entry of entries) {
|
|
333
|
+
if (!entry.isFile()) continue;
|
|
334
|
+
const match = LOG_FILE_PATTERN.exec(entry.name);
|
|
335
|
+
if (!match || entry.name === todayName) continue;
|
|
336
|
+
const filePath = path.join(dir, entry.name);
|
|
337
|
+
if (seen.has(filePath)) continue;
|
|
338
|
+
seen.add(filePath);
|
|
339
|
+
dated.push({ path: filePath, date: match[1]! });
|
|
340
|
+
}
|
|
255
341
|
}
|
|
342
|
+
// Newest first. `sort` is stable, so same-date files keep the directory order
|
|
343
|
+
// above (effective before canonical) and the single-directory case is ordered
|
|
344
|
+
// exactly as it was before the second directory was added.
|
|
345
|
+
dated.sort((a, b) => b.date.localeCompare(a.date));
|
|
346
|
+
olderFiles.push(...dated.map(entry => entry.path));
|
|
256
347
|
|
|
257
348
|
let cursor = 0;
|
|
258
349
|
|
|
@@ -270,8 +361,7 @@ export async function createDebugLogSource(): Promise<DebugLogSource> {
|
|
|
270
361
|
const slice = olderFiles.slice(cursor, cursor + count);
|
|
271
362
|
cursor += slice.length;
|
|
272
363
|
const chunks: string[] = [];
|
|
273
|
-
for (const
|
|
274
|
-
const filePath = path.join(logsDir, filename);
|
|
364
|
+
for (const filePath of slice.reverse()) {
|
|
275
365
|
try {
|
|
276
366
|
const content = await readLastLines(filePath, MAX_LOG_LINES);
|
|
277
367
|
if (content.length > 0) {
|
|
@@ -458,7 +458,7 @@ Because unselected goals stay schedulable, ordinary source progress moves whole-
|
|
|
458
458
|
|
|
459
459
|
`adopt` runs in the target repository and starts a genuinely fresh run: new pending goals, fresh timestamps, the target repository's own binding, and no inherited receipts, quality gates, validation batches, steering or activated objective. The source brief and every selected objective are carried verbatim, together with the unresolved obligations recorded against those goals — requirements are carried forward in full, never summarized down. Dependency groups travel as explicit obligations with source-to-target id mapping: the source's batch metadata and receipts are not inherited, but the requirement to validate those goals together is.
|
|
460
460
|
|
|
461
|
-
Selection and authorization must be explicit. Only unfinished goals (`pending`, `failed`, `blocked`, `review_blocked`) may be handed off; the source run must be quiescent with no `active` goal; there is no implicit or wildcard selection; and a selection that takes only part of a validation batch, or splits a review blocker from the goal it still blocks, is rejected rather than silently dropping that obligation. Adoption fails closed on changed offered work, an altered or unfenced offer, an offer path that escapes the source worktree, a target the offer does not name, a linked worktree
|
|
461
|
+
Selection and authorization must be explicit. Only unfinished goals (`pending`, `failed`, `blocked`, `review_blocked`) may be handed off; the source run must be quiescent with no `active` goal; there is no implicit or wildcard selection; and a selection that takes only part of a validation batch, or splits a review blocker from the goal it still blocks, is rejected rather than silently dropping that obligation. Adoption fails closed on changed offered work, an altered or unfenced offer, an offer path that escapes the source worktree, a target the offer does not name, a different linked worktree from the exact named target, an occupied target session, and any duplicate or simultaneous adoption anywhere in the target repository. A linked worktree is a valid target when the offer names that exact worktree; the source and target may therefore be sibling worktrees, but aliases of the same source worktree remain self-transfers and are rejected using physical path identity, and an unavailable bound worktree root is refused rather than compared lexically. A retry reconciles the exact recorded operation or fails closed — a matching operation id is never authority to overwrite target work it did not write, and a published plan that has disappeared is never reconstructed.
|
|
462
462
|
|
|
463
463
|
Until publication completes, the target refuses to execute: a visible `goals.json` is not admission evidence, the adoption record is. `start`/`complete-goals` and `checkpoint` reject while an adoption remains pending.
|
|
464
464
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isCompiledBinary, logger, Snowflake } from "@gajae-code/utils";
|
|
2
|
+
import { isDesignedError } from "@gajae-code/utils/error-classification";
|
|
2
3
|
import { registerResourceOwner } from "../../runtime/process-lifecycle";
|
|
3
4
|
import type { ToolSession } from "../../tools";
|
|
4
5
|
import { ToolAbortError, ToolError } from "../../tools/tool-errors";
|
|
@@ -460,13 +461,11 @@ function reasonToError(reason: unknown, fallback: string): Error {
|
|
|
460
461
|
}
|
|
461
462
|
|
|
462
463
|
function errorFromPayload(payload: RunErrorPayload): Error {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const ctor = payload.isToolError ? ToolError : Error;
|
|
469
|
-
const error = new ctor(payload.message);
|
|
464
|
+
const error = payload.isDesigned
|
|
465
|
+
? payload.isAbort
|
|
466
|
+
? new ToolAbortError(payload.message || "Execution aborted")
|
|
467
|
+
: new ToolError(payload.message)
|
|
468
|
+
: new Error(payload.message);
|
|
470
469
|
if (payload.name) error.name = payload.name;
|
|
471
470
|
if (payload.stack) error.stack = payload.stack;
|
|
472
471
|
return error;
|
|
@@ -479,7 +478,8 @@ function toErrorPayload(error: unknown): RunErrorPayload {
|
|
|
479
478
|
message: error.message,
|
|
480
479
|
stack: error.stack,
|
|
481
480
|
isAbort: error.name === "AbortError" || error.name === "ToolAbortError",
|
|
482
|
-
isToolError: error instanceof ToolError
|
|
481
|
+
isToolError: error instanceof ToolError,
|
|
482
|
+
isDesigned: isDesignedError(error),
|
|
483
483
|
};
|
|
484
484
|
}
|
|
485
485
|
return { message: String(error) };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDesignedError } from "@gajae-code/utils/error-classification";
|
|
2
|
+
import { ToolAbortError, ToolError } from "../../tools/tool-errors";
|
|
2
3
|
import { JsRuntime, type RuntimeHooks } from "./shared/runtime";
|
|
3
4
|
import type { RunErrorPayload, SessionSnapshot, ToolReply, Transport, WorkerInbound } from "./worker-protocol";
|
|
4
5
|
|
|
@@ -24,15 +25,19 @@ function errorPayload(error: unknown): RunErrorPayload {
|
|
|
24
25
|
message: error.message,
|
|
25
26
|
stack: error.stack,
|
|
26
27
|
isAbort: error.name === "AbortError" || error.name === "ToolAbortError",
|
|
27
|
-
isToolError: error
|
|
28
|
+
isToolError: error instanceof ToolError,
|
|
29
|
+
isDesigned: isDesignedError(error),
|
|
28
30
|
};
|
|
29
31
|
}
|
|
30
32
|
return { message: String(error) };
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
function errorFromPayload(payload: RunErrorPayload): Error {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
+
const error = payload.isDesigned
|
|
37
|
+
? payload.isAbort
|
|
38
|
+
? new ToolAbortError(payload.message)
|
|
39
|
+
: new ToolError(payload.message)
|
|
40
|
+
: new Error(payload.message);
|
|
36
41
|
if (payload.name) error.name = payload.name;
|
|
37
42
|
if (payload.stack) error.stack = payload.stack;
|
|
38
43
|
return error;
|
|
@@ -13,6 +13,8 @@ export interface RunErrorPayload {
|
|
|
13
13
|
stack?: string;
|
|
14
14
|
isAbort?: boolean;
|
|
15
15
|
isToolError?: boolean;
|
|
16
|
+
/** Set only when the originating error carried the trusted designed marker. */
|
|
17
|
+
isDesigned?: boolean;
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export type ToolReply = { ok: true; value: unknown } | { ok: false; error: RunErrorPayload };
|
|
@@ -192,6 +192,7 @@ type RunnerEmitResult<TEvent extends RunnerEmitEvent> = TEvent extends { type: "
|
|
|
192
192
|
type Handler = Extension["handlers"] extends Map<string, Array<infer T>> ? T : never;
|
|
193
193
|
type IndexedHandler = { ext: Extension; handler: Handler; registrationOrder: number };
|
|
194
194
|
type IndexedFunctionHook = IndexedHandler & { registration: FunctionHookRegistration };
|
|
195
|
+
type CommandAliasTarget = { extensionPath: string; commandName: string };
|
|
195
196
|
|
|
196
197
|
export type FunctionHookDispatchResult<TEvent extends ExtensionEvent> =
|
|
197
198
|
| { action: "continue"; event: TEvent; transformed?: boolean }
|
|
@@ -272,6 +273,7 @@ export class ExtensionRunner {
|
|
|
272
273
|
#getCredentialSessionId: () => string = () => "";
|
|
273
274
|
#isIdleFn: () => boolean = () => true;
|
|
274
275
|
#getActivePromptHandleFn: () => string | undefined = () => undefined;
|
|
276
|
+
#getSessionWorkLeaseFn: ExtensionContextActions["getSessionWorkLease"] = undefined;
|
|
275
277
|
#waitForIdleFn: () => Promise<void> = async () => {};
|
|
276
278
|
#abortFn: () => void | Promise<void> = () => {};
|
|
277
279
|
#abortPromptAndWaitFn: NonNullable<ExtensionContextActions["abortPromptAndWait"]> = async () => {
|
|
@@ -328,6 +330,9 @@ export class ExtensionRunner {
|
|
|
328
330
|
#reloadHandler: () => Promise<void> = async () => {};
|
|
329
331
|
#shutdownHandler: ShutdownHandler = () => {};
|
|
330
332
|
#commandDiagnostics: Array<{ type: string; message: string; path: string }> = [];
|
|
333
|
+
#commandAliases = new Map<string, RegisteredCommand>();
|
|
334
|
+
#commandAliasAssignments = new Map<string, string>();
|
|
335
|
+
#commandAliasTargets = new Map<string, CommandAliasTarget>();
|
|
331
336
|
#initialized = false;
|
|
332
337
|
/**
|
|
333
338
|
* Buffer for `credential_disabled` events received via {@link emitCredentialDisabled}
|
|
@@ -424,6 +429,7 @@ export class ExtensionRunner {
|
|
|
424
429
|
this.#getCredentialSessionId = contextActions.getCredentialSessionId ?? (() => "");
|
|
425
430
|
this.#isIdleFn = contextActions.isIdle;
|
|
426
431
|
this.#getActivePromptHandleFn = contextActions.getActivePromptHandle ?? (() => undefined);
|
|
432
|
+
this.#getSessionWorkLeaseFn = contextActions.getSessionWorkLease;
|
|
427
433
|
this.#abortFn = contextActions.abort;
|
|
428
434
|
this.#abortPromptAndWaitFn =
|
|
429
435
|
contextActions.abortPromptAndWait ??
|
|
@@ -701,16 +707,49 @@ export class ExtensionRunner {
|
|
|
701
707
|
|
|
702
708
|
getRegisteredCommands(reserved?: Set<string>): RegisteredCommand[] {
|
|
703
709
|
this.#commandDiagnostics = [];
|
|
710
|
+
this.#commandAliases.clear();
|
|
704
711
|
|
|
705
712
|
const commands = new Map<string, RegisteredCommand>();
|
|
706
713
|
for (const ext of this.extensions) {
|
|
707
714
|
for (const command of ext.commands.values()) {
|
|
708
715
|
if (reserved?.has(command.name)) {
|
|
709
|
-
const
|
|
710
|
-
this.#
|
|
711
|
-
|
|
712
|
-
|
|
716
|
+
const assignmentKey = `${ext.path}\u0000${command.name}`;
|
|
717
|
+
let alias = this.#commandAliasAssignments.get(assignmentKey);
|
|
718
|
+
const aliasTarget = alias ? this.#commandAliasTargets.get(alias) : undefined;
|
|
719
|
+
const aliasOwnedByCommand =
|
|
720
|
+
aliasTarget?.extensionPath === ext.path && aliasTarget.commandName === command.name;
|
|
721
|
+
if (
|
|
722
|
+
!alias ||
|
|
723
|
+
reserved.has(alias) ||
|
|
724
|
+
commands.has(alias) ||
|
|
725
|
+
(aliasTarget !== undefined && !aliasOwnedByCommand)
|
|
726
|
+
) {
|
|
727
|
+
let candidate = alias ?? `extension:${command.name}`;
|
|
728
|
+
while (
|
|
729
|
+
reserved.has(candidate) ||
|
|
730
|
+
commands.has(candidate) ||
|
|
731
|
+
this.#commandAliases.has(candidate) ||
|
|
732
|
+
(this.#commandAliasTargets.has(candidate) &&
|
|
733
|
+
(this.#commandAliasTargets.get(candidate)?.extensionPath !== ext.path ||
|
|
734
|
+
this.#commandAliasTargets.get(candidate)?.commandName !== command.name))
|
|
735
|
+
)
|
|
736
|
+
candidate = `extension:${candidate}`;
|
|
737
|
+
if (
|
|
738
|
+
alias &&
|
|
739
|
+
this.#commandAliasTargets.get(alias)?.extensionPath === ext.path &&
|
|
740
|
+
this.#commandAliasTargets.get(alias)?.commandName === command.name
|
|
741
|
+
) {
|
|
742
|
+
this.#commandAliasTargets.delete(alias);
|
|
743
|
+
}
|
|
744
|
+
alias = candidate;
|
|
745
|
+
this.#commandAliasAssignments.set(assignmentKey, alias);
|
|
713
746
|
}
|
|
747
|
+
this.#commandAliasTargets.set(alias, { extensionPath: ext.path, commandName: command.name });
|
|
748
|
+
const namespaced = { ...command, name: alias };
|
|
749
|
+
this.#commandAliases.set(alias, namespaced);
|
|
750
|
+
commands.set(alias, namespaced);
|
|
751
|
+
const message = `Extension command '${command.name}' from ${ext.path} was renamed to '${alias}' to avoid a built-in command collision.`;
|
|
752
|
+
this.#commandDiagnostics.push({ type: "info", message, path: ext.path });
|
|
714
753
|
continue;
|
|
715
754
|
}
|
|
716
755
|
|
|
@@ -725,6 +764,14 @@ export class ExtensionRunner {
|
|
|
725
764
|
}
|
|
726
765
|
|
|
727
766
|
getCommand(name: string): RegisteredCommand | undefined {
|
|
767
|
+
const aliased = this.#commandAliases.get(name);
|
|
768
|
+
if (aliased) return aliased;
|
|
769
|
+
const aliasTarget = this.#commandAliasTargets.get(name);
|
|
770
|
+
if (aliasTarget) {
|
|
771
|
+
const extension = this.extensions.find(ext => ext.path === aliasTarget.extensionPath);
|
|
772
|
+
const command = extension?.commands.get(aliasTarget.commandName);
|
|
773
|
+
if (command) return { ...command, name };
|
|
774
|
+
}
|
|
728
775
|
for (let index = this.extensions.length - 1; index >= 0; index -= 1) {
|
|
729
776
|
const command = this.extensions[index]?.commands.get(name);
|
|
730
777
|
if (command) {
|
|
@@ -754,6 +801,7 @@ export class ExtensionRunner {
|
|
|
754
801
|
return getModel();
|
|
755
802
|
},
|
|
756
803
|
getActivePromptHandle: () => this.#getActivePromptHandleFn(),
|
|
804
|
+
getSessionWorkLease: () => this.#getSessionWorkLeaseFn?.(),
|
|
757
805
|
isIdle: () => this.#isIdleFn(),
|
|
758
806
|
abort: () => this.#abortFn(),
|
|
759
807
|
abortPromptAndWait: (handle, options) => this.#abortPromptAndWaitFn(handle, options),
|
|
@@ -58,6 +58,7 @@ import type {
|
|
|
58
58
|
} from "../../session/client-bridge";
|
|
59
59
|
import type { CustomMessage } from "../../session/messages";
|
|
60
60
|
import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager";
|
|
61
|
+
import type { SessionWorkLease } from "../../session/session-work-lease";
|
|
61
62
|
import type {
|
|
62
63
|
BashToolDetails,
|
|
63
64
|
BashToolInput,
|
|
@@ -482,6 +483,8 @@ export interface ExtensionContext {
|
|
|
482
483
|
isIdle(): boolean;
|
|
483
484
|
/** Stable resource ownership identifier for the active prompt run. */
|
|
484
485
|
getActivePromptHandle(): string | undefined;
|
|
486
|
+
/** The session's authoritative host-liveness lease. */
|
|
487
|
+
getSessionWorkLease?(): SessionWorkLease | undefined;
|
|
485
488
|
/** Abort the current agent operation */
|
|
486
489
|
abort(): void | Promise<void>;
|
|
487
490
|
/** Abort and prove whether resources for a specific prompt settled. */
|
|
@@ -1569,6 +1572,11 @@ export type SendUserMessageHandler = (
|
|
|
1569
1572
|
* grants root abort ownership.
|
|
1570
1573
|
*/
|
|
1571
1574
|
onQueuedPromoted?: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
1575
|
+
/**
|
|
1576
|
+
* Fired synchronously when a plain prompt's dispatch resolves at queue
|
|
1577
|
+
* time instead of run end (diverted into an in-flight run's steering).
|
|
1578
|
+
*/
|
|
1579
|
+
onDispatchDisposition?: (promotion: { startsOwnRun: boolean }) => void;
|
|
1572
1580
|
preflightSignal?: AbortSignal;
|
|
1573
1581
|
/** Internal SDK correlation owner for an exact queued follow-up. */
|
|
1574
1582
|
},
|
|
@@ -1660,6 +1668,8 @@ export interface ExtensionContextActions {
|
|
|
1660
1668
|
isIdle: () => boolean;
|
|
1661
1669
|
/** Stable resource ownership identifier for the active prompt run. */
|
|
1662
1670
|
getActivePromptHandle?: () => string | undefined;
|
|
1671
|
+
/** The session's authoritative host-liveness lease. */
|
|
1672
|
+
getSessionWorkLease?: () => SessionWorkLease | undefined;
|
|
1663
1673
|
abort: () => void | Promise<void>;
|
|
1664
1674
|
abortPromptAndWait?: (handle: string, options: { graceMs: number }) => Promise<RunSettlementProof>;
|
|
1665
1675
|
|