@gajae-code/coding-agent 0.17.2 → 0.17.5
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 +267 -0
- 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 +1049 -3
- package/dist/types/config/file-lock.d.ts +13 -3
- package/dist/types/config/model-profile-activation.d.ts +45 -1
- package/dist/types/config/model-registry.d.ts +14 -3
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/settings-schema.d.ts +11 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
- package/dist/types/daemon/operator-contract.d.ts +5 -1
- package/dist/types/eval/js/worker-protocol.d.ts +2 -0
- package/dist/types/exec/bash-executor.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/gjc-plugins/runtime-adapters.d.ts +11 -2
- 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/gjc-runtime/state-writer.d.ts +14 -1
- package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
- package/dist/types/harness-control-plane/finalize.d.ts +14 -3
- 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 +23 -1
- package/dist/types/modes/acp/acp-agent.d.ts +55 -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/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/loader.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +69 -6
- 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/broker/broker.d.ts +17 -4
- package/dist/types/sdk/broker/ensure.d.ts +3 -0
- package/dist/types/sdk/broker/identity.d.ts +5 -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/managed-task-dag.d.ts +1335 -0
- package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
- 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 +12 -0
- package/dist/types/sdk/broker/startup-failure.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 +7 -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 +85 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
- package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/session.d.ts +3 -3
- 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 +48 -4
- package/dist/types/sdk/transport/stdio.d.ts +5 -1
- package/dist/types/session/agent-session.d.ts +175 -23
- 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/task/types.d.ts +2 -0
- package/dist/types/tools/bash-interactive.d.ts +1 -0
- package/dist/types/tools/bash.d.ts +37 -11
- package/dist/types/tools/fetch.d.ts +10 -1
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/steer-fold.d.ts +31 -0
- package/dist/types/tools/subagent.d.ts +8 -1
- package/dist/types/utils/git.d.ts +28 -2
- package/dist/types/utils/mupdf-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 +22 -1
- 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 +541 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +10 -1
- package/src/cli/skills-cli.ts +46 -2
- package/src/cli/stats-cli.ts +11 -1
- package/src/cli.ts +61 -1
- package/src/commands/daemon.ts +65 -69
- package/src/commands/sdk.ts +175 -117
- package/src/commands/setup.ts +2 -0
- package/src/commands/skills.ts +11 -0
- package/src/config/autorouting-tier-map.ts +543 -3
- package/src/config/file-lock.ts +206 -65
- package/src/config/model-discovery-manager.ts +4 -4
- package/src/config/model-profile-activation.ts +417 -66
- package/src/config/model-registry.ts +254 -36
- package/src/config/model-resolver.ts +6 -1
- 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 +179 -9
- package/src/coordinator-mcp/server.ts +521 -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/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/exec/bash-executor.ts +3 -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/gjc-plugins/runtime-adapters.ts +46 -8
- package/src/extensibility/runtime-skill-discovery.ts +61 -3
- package/src/extensibility/shared-events.ts +3 -1
- package/src/gjc-runtime/session-state-lock.ts +165 -24
- package/src/gjc-runtime/state-writer.ts +317 -6
- package/src/gjc-runtime/ultragoal-succession.ts +31 -3
- package/src/harness-control-plane/control-endpoint.ts +24 -6
- package/src/harness-control-plane/finalize.ts +312 -25
- package/src/harness-control-plane/owner.ts +323 -89
- package/src/internal-urls/docs-index.generated.ts +23 -20
- 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 +192 -74
- package/src/modes/acp/acp-agent.ts +973 -56
- package/src/modes/acp/startup-provenance.ts +59 -0
- package/src/modes/components/custom-provider-wizard.ts +308 -7
- package/src/modes/components/gjc-bundle-settings.ts +21 -1
- package/src/modes/components/oauth-selector.ts +9 -0
- package/src/modes/components/session-selector.ts +47 -4
- package/src/modes/components/tool-status-header.ts +72 -6
- 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/runtime-mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +161 -15
- 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/loader.ts +6 -3
- package/src/runtime-mcp/manager.ts +845 -109
- 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 +27 -8
- package/src/sdk/broker/broker.ts +1431 -198
- package/src/sdk/broker/ensure.ts +21 -3
- package/src/sdk/broker/identity.ts +22 -1
- package/src/sdk/broker/lifecycle-ledger.ts +95 -31
- package/src/sdk/broker/lifecycle.ts +690 -141
- package/src/sdk/broker/managed-task-dag.ts +1927 -0
- package/src/sdk/broker/managed-task-verification.ts +642 -0
- package/src/sdk/broker/runtime.ts +1 -1
- package/src/sdk/broker/session-index.ts +97 -4
- package/src/sdk/broker/spawn-authority.ts +175 -14
- package/src/sdk/broker/startup-failure.ts +80 -1
- package/src/sdk/broker/stderr-drainer.ts +59 -0
- package/src/sdk/broker/transport.ts +1 -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 +707 -81
- package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
- package/src/sdk/bus/telegram-daemon-contract.ts +7 -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 +705 -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 +184 -2
- package/src/sdk/host/session-runtime.ts +322 -101
- 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/lifecycle/service.ts +2 -0
- package/src/sdk/prompt-deadline-flush.ts +356 -0
- package/src/sdk/prompt-deadline-manager.ts +133 -1
- package/src/sdk/prompt-tool-boundary.ts +121 -0
- package/src/sdk/protocol/operation-inventory.generated.json +106 -0
- package/src/sdk/router/session-router.ts +9 -1
- package/src/sdk/session.ts +763 -116
- package/src/sdk/startup-capability.ts +1 -1
- package/src/sdk/transport/relay.ts +71 -6
- package/src/sdk/transport/serve-cli.ts +397 -42
- package/src/sdk/transport/socket.ts +12 -11
- package/src/sdk/transport/stdio.ts +7 -3
- package/src/session/agent-session.ts +2472 -407
- 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 +68 -18
- package/src/session/internal/managed-session-storage.ts +334 -12
- package/src/session/session-manager.ts +382 -44
- package/src/session/session-work-lease.ts +34 -0
- package/src/setup/model-onboarding-guidance.ts +1 -1
- package/src/setup/provider-onboarding.ts +397 -24
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +259 -15
- package/src/task/executor.ts +46 -17
- package/src/task/index.ts +14 -2
- package/src/task/types.ts +2 -0
- package/src/tools/bash-interactive.ts +2 -0
- package/src/tools/bash.ts +118 -78
- package/src/tools/fetch.ts +140 -25
- 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/subagent-render.ts +24 -1
- package/src/tools/subagent.ts +27 -1
- 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.ts +136 -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
package/src/tools/read.ts
CHANGED
|
@@ -14,7 +14,7 @@ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
|
14
14
|
import { getActiveSkills } from "../extensibility/skills";
|
|
15
15
|
import { formatHashLine, formatHashLines, formatLineHash, HL_BODY_SEP } from "../hashline/hash";
|
|
16
16
|
import { InternalUrlRouter } from "../internal-urls";
|
|
17
|
-
import { parseInternalUrl } from "../internal-urls/parse";
|
|
17
|
+
import { normalizeInternalUrlInput, parseInternalUrl } from "../internal-urls/parse";
|
|
18
18
|
import type { InternalUrl } from "../internal-urls/types";
|
|
19
19
|
import { getLanguageFromPath, type Theme } from "../modes/theme/theme";
|
|
20
20
|
import readDescription from "../prompts/tools/read.md" with { type: "text" };
|
|
@@ -2745,7 +2745,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
2745
2745
|
// off the URL and surfaced via parseSel rather than confusing handlers.
|
|
2746
2746
|
const internalRouter = InternalUrlRouter.instance();
|
|
2747
2747
|
if (internalRouter.canHandle(readPath)) {
|
|
2748
|
-
const internalTarget = splitInternalUrlSel(readPath, {
|
|
2748
|
+
const internalTarget = splitInternalUrlSel(normalizeInternalUrlInput(readPath), {
|
|
2749
2749
|
activeSkillNames: getActiveSkills().map(skill => skill.name),
|
|
2750
2750
|
});
|
|
2751
2751
|
const parsed = parseSel(internalTarget.sel);
|
|
@@ -3590,7 +3590,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
3590
3590
|
sourcePath: resource.sourcePath,
|
|
3591
3591
|
sourceInternal: url,
|
|
3592
3592
|
entityLabel: "resource",
|
|
3593
|
-
ignoreResultLimits: scheme === "skill",
|
|
3593
|
+
ignoreResultLimits: scheme === "skill" || scheme === "embedded",
|
|
3594
3594
|
immutable: resource.immutable,
|
|
3595
3595
|
raw,
|
|
3596
3596
|
truncationDirection: direction,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { logger } from "@gajae-code/utils";
|
|
2
|
+
import type { FoldReason } from "../async/job-manager";
|
|
3
|
+
import type { ToolSession } from ".";
|
|
4
|
+
|
|
5
|
+
/** A short foreground wait stays in the foreground even when a steer is admitted. */
|
|
6
|
+
export const STEER_FOLD_GRACE_MS = 2_000;
|
|
7
|
+
|
|
8
|
+
/** Model-facing line appended to a steer-folded background-start result. */
|
|
9
|
+
export function steerFoldReasonLine(jobId: string): string {
|
|
10
|
+
return `Folded into background job ${jobId} because a user steer arrived; the command keeps running with its original timeout and its result will wake a later turn.`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Model-facing cause clause for a fold, keyed by the recorded {@link FoldReason}. */
|
|
14
|
+
export function foldReasonClause(reason: FoldReason): string {
|
|
15
|
+
switch (reason) {
|
|
16
|
+
case "steer":
|
|
17
|
+
return "because a user steer arrived";
|
|
18
|
+
case "chord":
|
|
19
|
+
return "because the user pressed the fold chord";
|
|
20
|
+
case "sdk_control":
|
|
21
|
+
return "because an SDK client requested it";
|
|
22
|
+
case "timer":
|
|
23
|
+
return "because the auto-background threshold elapsed";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Model-facing line used when the `job` tool's own wait is folded; states the real trigger. */
|
|
28
|
+
export function foldAwaitReasonLine(folded: ReadonlyMap<string, FoldReason>): string {
|
|
29
|
+
const jobIds = [...folded.keys()];
|
|
30
|
+
const names = jobIds.map(id => `\`${id}\``).join(", ");
|
|
31
|
+
const reasons = [...new Set(folded.values())];
|
|
32
|
+
const single = reasons.length === 1 ? reasons[0] : undefined;
|
|
33
|
+
const cause = single ? foldReasonClause(single) : "because the waits were folded";
|
|
34
|
+
const plural = jobIds.length !== 1;
|
|
35
|
+
return `Folded the job await for ${names} ${cause}; the job${plural ? "s keep" : " keeps"} running with ${plural ? "their original deadlines" : "its original deadline"}, and ${plural ? "their results" : "its result"} will wake a later turn.`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type SteerFoldSession = Pick<ToolSession, "settings" | "waitForUserSteering" | "requestForegroundBashBackground">;
|
|
39
|
+
|
|
40
|
+
/** The session hooks a steer fold needs, resolved once so callers never re-read and non-null-assert them. */
|
|
41
|
+
interface SteerFoldHooks {
|
|
42
|
+
waitForSteer: NonNullable<ToolSession["waitForUserSteering"]>;
|
|
43
|
+
requestFold: NonNullable<ToolSession["requestForegroundBashBackground"]>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Whether a queued user steer may fold the running foreground wait. Mirrors
|
|
48
|
+
* the loop's steer admission: `busyPromptMode=queue` never admits a steer
|
|
49
|
+
* into the busy run, so it never folds. `toolInterruptPolicy` is
|
|
50
|
+
* deliberately NOT a gate: `finish_tools` means "do not kill the batch to
|
|
51
|
+
* deliver a steer", and a fold kills nothing. It is the one way to deliver
|
|
52
|
+
* the steer now AND let the command finish, so it applies under both
|
|
53
|
+
* policies; the policy only decides what the loop does with sibling tools
|
|
54
|
+
* after the fold returns. The auto-background setting is likewise not
|
|
55
|
+
* consulted: like the chord, a steer fold is a user action.
|
|
56
|
+
*
|
|
57
|
+
* Fails closed: a session that cannot report newly admitted steering or
|
|
58
|
+
* accept a fold request is not steer-foldable.
|
|
59
|
+
*/
|
|
60
|
+
function steerFoldHooks(session: SteerFoldSession): SteerFoldHooks | undefined {
|
|
61
|
+
const { waitForUserSteering, requestForegroundBashBackground } = session;
|
|
62
|
+
if (!waitForUserSteering || !requestForegroundBashBackground) return undefined;
|
|
63
|
+
if (session.settings.get("busyPromptMode") !== "steer") return undefined;
|
|
64
|
+
return { waitForSteer: waitForUserSteering, requestFold: requestForegroundBashBackground };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Fold on the first user steer that ARRIVES after the wait has run for
|
|
69
|
+
* {@link STEER_FOLD_GRACE_MS} since `startedAt`. A steer already queued when
|
|
70
|
+
* the wait starts, or one that arrives inside the grace window, never folds:
|
|
71
|
+
* the wait finishes normally and that steer is consumed at the ordinary tool
|
|
72
|
+
* boundary. The watcher keeps observing so a later qualifying steer still
|
|
73
|
+
* folds, and re-checks the gate at that moment so a `busyPromptMode` change
|
|
74
|
+
* during the wait is honored. `requestFold` receives the session's resolved
|
|
75
|
+
* fold request so the caller targets its own adapter without re-reading the
|
|
76
|
+
* optional session hook.
|
|
77
|
+
* Returns a stop function; call it when the wait settles. No-op when steer
|
|
78
|
+
* folding is gated off at start.
|
|
79
|
+
*/
|
|
80
|
+
export function watchSteerForFold(
|
|
81
|
+
session: SteerFoldSession,
|
|
82
|
+
startedAt: number,
|
|
83
|
+
requestFold: (fold: SteerFoldHooks["requestFold"]) => Promise<unknown>,
|
|
84
|
+
jobId?: string,
|
|
85
|
+
): () => void {
|
|
86
|
+
const hooks = steerFoldHooks(session);
|
|
87
|
+
if (!hooks) return () => {};
|
|
88
|
+
const watch = new AbortController();
|
|
89
|
+
const observe = async (): Promise<void> => {
|
|
90
|
+
while (!watch.signal.aborted) {
|
|
91
|
+
await hooks.waitForSteer(watch.signal);
|
|
92
|
+
if (watch.signal.aborted) return;
|
|
93
|
+
if (Date.now() - startedAt < STEER_FOLD_GRACE_MS) continue;
|
|
94
|
+
const current = steerFoldHooks(session);
|
|
95
|
+
if (!current) continue;
|
|
96
|
+
await requestFold(current.requestFold);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
observe().catch((error: unknown) => {
|
|
101
|
+
logger.warn("Steer-triggered fold failed", {
|
|
102
|
+
...(jobId ? { jobId } : {}),
|
|
103
|
+
error: error instanceof Error ? error.message : String(error),
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
return () => watch.abort();
|
|
107
|
+
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { Component } from "@gajae-code/tui";
|
|
11
11
|
import { Text } from "@gajae-code/tui";
|
|
12
|
+
import { formatNumber } from "@gajae-code/utils";
|
|
12
13
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
13
14
|
import type { Theme } from "../modes/theme/theme";
|
|
14
15
|
import { providerRetryPhaseLabel } from "../task/provider-retry-status";
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
truncateToWidth,
|
|
23
24
|
} from "./render-utils";
|
|
24
25
|
import {
|
|
26
|
+
SUBAGENT_ACTIVITY_BUCKET_MS,
|
|
25
27
|
type SubagentLiveProgress,
|
|
26
28
|
type SubagentSnapshot,
|
|
27
29
|
type SubagentToolDetails,
|
|
@@ -186,7 +188,28 @@ function renderSubagentStatusLine(snapshot: SubagentSnapshot, theme: Theme, spin
|
|
|
186
188
|
)
|
|
187
189
|
: theme.fg("dim", snapshot.status);
|
|
188
190
|
const duration = theme.fg("dim", formatDuration(snapshot.durationMs));
|
|
189
|
-
|
|
191
|
+
const live = snapshot.liveProgressAvailable !== false ? snapshot.progress : undefined;
|
|
192
|
+
return `${icon} ${id} ${status} ${duration}${live ? formatLiveStats(live, theme, Date.now()) : ""}`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Live stats ride the cheap status line (rebuilt every render), never the cached
|
|
196
|
+
// body. Quantize age to the producer cadence so incidental renders do not churn it.
|
|
197
|
+
function formatLiveStats(progress: SubagentLiveProgress, theme: Theme, nowMs: number): string {
|
|
198
|
+
const parts: string[] = [];
|
|
199
|
+
if (progress.toolCount) parts.push(`${progress.toolCount} ${progress.toolCount === 1 ? "tool" : "tools"}`);
|
|
200
|
+
if (progress.contextTokens) {
|
|
201
|
+
parts.push(
|
|
202
|
+
progress.contextWindow
|
|
203
|
+
? `${formatNumber(progress.contextTokens)}/${formatNumber(progress.contextWindow)} ctx`
|
|
204
|
+
: `${formatNumber(progress.contextTokens)} ctx`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (progress.lastActivityMs !== undefined && progress.status === "running") {
|
|
208
|
+
const ageMs = Math.max(0, nowMs - progress.lastActivityMs);
|
|
209
|
+
const ageBucketMs = Math.floor(ageMs / SUBAGENT_ACTIVITY_BUCKET_MS) * SUBAGENT_ACTIVITY_BUCKET_MS;
|
|
210
|
+
parts.push(`last activity ${formatDuration(ageBucketMs)} ago`);
|
|
211
|
+
}
|
|
212
|
+
return parts.map(part => `${theme.sep.dot}${theme.fg("dim", part)}`).join("");
|
|
190
213
|
}
|
|
191
214
|
|
|
192
215
|
function renderSubagentLiveProgress(
|
package/src/tools/subagent.ts
CHANGED
|
@@ -120,6 +120,10 @@ export interface SubagentLiveProgress {
|
|
|
120
120
|
currentTool?: string;
|
|
121
121
|
recentTool?: string;
|
|
122
122
|
recentOutputSummary?: { lineCount: number };
|
|
123
|
+
toolCount?: number;
|
|
124
|
+
contextTokens?: number;
|
|
125
|
+
contextWindow?: number;
|
|
126
|
+
lastActivityMs?: number;
|
|
123
127
|
fastMode?: boolean;
|
|
124
128
|
retryState?: {
|
|
125
129
|
attempt: number;
|
|
@@ -145,6 +149,14 @@ function toSubagentLiveProgress(progress: AgentProgress): SubagentLiveProgress {
|
|
|
145
149
|
...(progress.recentOutput.length > 0
|
|
146
150
|
? { recentOutputSummary: { lineCount: Math.min(progress.recentOutput.length, 6) } }
|
|
147
151
|
: {}),
|
|
152
|
+
...(progress.toolCount > 0 ? { toolCount: progress.toolCount } : {}),
|
|
153
|
+
...(progress.contextTokens !== undefined && progress.contextTokens > 0
|
|
154
|
+
? { contextTokens: progress.contextTokens }
|
|
155
|
+
: {}),
|
|
156
|
+
...(progress.contextWindow !== undefined && progress.contextWindow > 0
|
|
157
|
+
? { contextWindow: progress.contextWindow }
|
|
158
|
+
: {}),
|
|
159
|
+
...(progress.lastActivityMs !== undefined ? { lastActivityMs: progress.lastActivityMs } : {}),
|
|
148
160
|
...(progress.fastMode ? { fastMode: true } : {}),
|
|
149
161
|
...(progress.retryState
|
|
150
162
|
? {
|
|
@@ -1104,11 +1116,15 @@ function previewJobOutput(
|
|
|
1104
1116
|
* unsafe.
|
|
1105
1117
|
*
|
|
1106
1118
|
* Time-derived fields are intentionally excluded so the panel does not churn while
|
|
1107
|
-
* idle
|
|
1119
|
+
* idle (the child's last-event timestamp is included; it moves only on real
|
|
1120
|
+
* activity): raw durations (`durationMs`), current-tool elapsed (`currentToolStartMs`),
|
|
1108
1121
|
* and retry countdowns (`retryState.startedAtMs`) are omitted. Idle duration and
|
|
1109
1122
|
* countdown ticking is sacrificed by design; every real transition still changes
|
|
1110
1123
|
* the signature.
|
|
1111
1124
|
*/
|
|
1125
|
+
/** Shared cadence for await progress refreshes and rendered last-activity age. */
|
|
1126
|
+
export const SUBAGENT_ACTIVITY_BUCKET_MS = 5_000;
|
|
1127
|
+
|
|
1112
1128
|
export function subagentAwaitRenderedStateSignature(
|
|
1113
1129
|
subagents: readonly SubagentSnapshot[],
|
|
1114
1130
|
receipt?: Pick<SubagentToolDetails, "awaitOutcome" | "interrupted">,
|
|
@@ -1156,6 +1172,16 @@ function canonicalizeProgressForSignature(progress: SubagentLiveProgress): unkno
|
|
|
1156
1172
|
currentTool: progress.currentTool ?? null,
|
|
1157
1173
|
recentTool: progress.recentTool ?? null,
|
|
1158
1174
|
recentOutputSummary: progress.recentOutputSummary ?? null,
|
|
1175
|
+
toolCount: progress.toolCount ?? 0,
|
|
1176
|
+
contextTokens: progress.contextTokens ?? null,
|
|
1177
|
+
contextWindow: progress.contextWindow ?? null,
|
|
1178
|
+
// Event timestamp, bucketed: it only moves when the child actually does
|
|
1179
|
+
// something (idle gating holds), and the bucket keeps a streaming child from
|
|
1180
|
+
// re-emitting on every delta. The status-line age is quantized to this cadence.
|
|
1181
|
+
lastActivityBucket:
|
|
1182
|
+
progress.lastActivityMs === undefined
|
|
1183
|
+
? null
|
|
1184
|
+
: Math.floor(progress.lastActivityMs / SUBAGENT_ACTIVITY_BUCKET_MS),
|
|
1159
1185
|
fastMode: progress.fastMode ?? false,
|
|
1160
1186
|
retryFailure: progress.retryFailure ?? null,
|
|
1161
1187
|
retryState: progress.retryState
|
|
@@ -27,7 +27,7 @@ export const TOOL_CATALOG: Readonly<Record<string, ToolCatalogEntry>> = {
|
|
|
27
27
|
"read": {
|
|
28
28
|
"name": "read",
|
|
29
29
|
"label": "Read",
|
|
30
|
-
"description": "Read files, directories, archives, SQLite databases, images, documents, internal resources, and web URLs through a single `path` string.\n\n<instruction>\n- One tool for filesystem, archives, SQLite, images, documents (PDF/DOCX/PPTX/XLSX/RTF/EPUB/ipynb), internal URIs, and web URLs (reader-mode by default).\n- You SHOULD parallelize independent reads when exploring related files.\n- You SHOULD reach for `read` — not a browser/puppeteer tool — for fetching web content.\n</instruction>\n\n## Parameters\n\n- `path` — required. Local path, internal URI (`agent://`, `artifact://`, `rule://`, `local://`), or URL. Append `:<sel>` for line ranges, raw mode, or special modes (e.g. `src/foo.ts:50-200`, `src/foo.ts:raw`, `db.sqlite:users:42`).\n- `truncation` — optional `head` | `last` | `both`; selects which end of an over-budget result to retain. Configured default: last (factory default: `last`); structural summaries and routes such as URLs, directories and converted documents default to `head`. A line-range selector still bounds the selection — this only picks which end of that selection survives the byte/line cap. SQLite row queries page via their own `limit`/`offset` and ignore it.\n## Selectors\nAppend `:<sel>` to `path`. The bare path falls back to the default mode.\n\n- _(none)_ — parseable code → structural summary (signatures kept, bodies elided); a plain text file → a bounded receipt of about undefined lines or undefined KiB, whichever is smaller; the configured truncation direction is last (factory default: last). Line+hash anchors keep their real file line numbers and a footer names the omitted range. Archive members use the larger 3000-line / 50 KiB budget. Converted documents, notebooks, URLs and directory listings still start from the beginning.\n- `:50` / `:50-` — read from line 50 onward.\n- `:50-200` — lines 50–200 inclusive.\n- `:50+150` — 150 lines starting at line 50.\n- `:20+1` — exactly one line.\n- `:5-16,960-973` — multiple ranges in one call (sorted, overlaps merged).\n- `:raw` — verbatim text; no anchors, no summary, no line prefixes.\n- `:2-4:raw` or `:raw:2-4` — range AND verbatim; the two compose in either order.\n- `:conflicts` — one-line-per-block index of every unresolved git merge conflict.\n\n# Files\n\n- Reading a directory path returns a depth-limited dirent listing.\n- Parseable code without a selector returns a **structural summary**: declarations kept, large bodies collapsed to `..` (merged brace pair) or `…` (standalone). Summarized output ends with a footer of the form:\n\n `[NN lines across MM elided regions; read <path>:raw or a line range like <path>:1-9999 for verbatim content]`\n\n If the elided body is what you actually need, re-issue the **exact selector the footer names**. NEVER guess what's inside `..` / `…` — those markers carry no content.\n- Structural summaries honor explicit `truncation`: `head` retains the beginning, `last` the end, and `both` both ends within the summary byte budget. Complete summary units and their original source anchors stay intact and in source order; budget omissions are marked where they occur. This does not switch to raw source. Summaries that fit are unchanged by direction.\n- Directional windows identify the retained first/last lines and the omitted range; use the `re-read <path>:1-<total>` or `:raw` hint in the footer to recover the full content.\n\n# Documents & Notebooks\n\nExtracts text from PDF, Word, PowerPoint, Excel, RTF, and EPUB. Notebooks (`.ipynb`) are shown as editable `# %% [type] cell:N` text; edits round-trip back to the underlying JSON preserving notebook metadata. Add `:raw` to a notebook to bypass the converter and read the JSON directly.\n\n# Images\n\nReading an image path returns the image itself for visual inspection by a vision-capable model.\n\n# Archives\n\nSupports `.tar`, `.tar.gz`, `.tgz`, `.zip`. Use `archive.ext:path/inside/archive` to read a member, and append a normal selector to the inner path: `archive.zip:dir/file.ts:50-60`.\n\n# SQLite\n\nFor `.sqlite`, `.sqlite3`, `.db`, `.db3`:\n- `file.db` — list tables with row counts\n- `file.db:table` — schema + sample rows\n- `file.db:table:key` — single row by primary key\n- `file.db:table?limit=50&offset=100` — paginated rows\n- `file.db:table?where=status='active'&order=created:desc` — filtered rows\n- `file.db?q=SELECT …` — read-only SELECT query\n\n# URLs\n\n- Default reader-mode: HTML pages, GitHub issues/PRs, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, RSS/Atom, JSON endpoints, PDFs → clean text/markdown.\n- `:raw` returns untouched HTML; line selectors (`:50`, `:50-100`, `:50+150`) paginate the cached fetched output.\n- Bare `host:port` URLs collide with the selector grammar — add a trailing slash before the selector: `https://example.com/:80`.\n\n# Internal URIs\n\n`agent://<id>`, `artifact://<id>`, `rule://<name>`, and `local://<name>.md` resolve transparently and accept the same line selectors as filesystem paths. Use `artifact://<id>` to recover full output that a previous bash/eval/tool result spilled or truncated.\n\n<critical>\n- Always include `path`; never call `read` with `{}`.\n- For line ranges, append the selector to `path`.\n- Re-issue the selector named by a summary footer before relying on elided content.\n</critical>",
|
|
30
|
+
"description": "Read files, directories, archives, SQLite databases, images, documents, internal resources, and web URLs through a single `path` string.\n\n<instruction>\n- One tool for filesystem, archives, SQLite, images, documents (PDF/DOCX/PPTX/XLSX/RTF/EPUB/ipynb), internal URIs, and web URLs (reader-mode by default).\n- You SHOULD parallelize independent reads when exploring related files.\n- You SHOULD reach for `read` — not a browser/puppeteer tool — for fetching web content.\n</instruction>\n\n## Parameters\n\n- `path` — required. Local path, internal URI (`agent://`, `artifact://`, `rule://`, `local://`), or URL. Append `:<sel>` for line ranges, raw mode, or special modes (e.g. `src/foo.ts:50-200`, `src/foo.ts:raw`, `db.sqlite:users:42`).\n- `truncation` — optional `head` | `last` | `both`; selects which end of an over-budget result to retain. Configured default: last (factory default: `last`); structural summaries and routes such as URLs, directories and converted documents default to `head`. A line-range selector still bounds the selection — this only picks which end of that selection survives the byte/line cap. SQLite row queries page via their own `limit`/`offset` and ignore it.\n## Selectors\nAppend `:<sel>` to `path`. The bare path falls back to the default mode.\n\n- _(none)_ — parseable code → structural summary (signatures kept, bodies elided); a plain text file → a bounded receipt of about undefined lines or undefined KiB, whichever is smaller; the configured truncation direction is last (factory default: last). Line+hash anchors keep their real file line numbers and a footer names the omitted range. Archive members use the larger 3000-line / 50 KiB budget. Converted documents, notebooks, URLs and directory listings still start from the beginning.\n- `:50` / `:50-` — read from line 50 onward.\n- `:50-200` — lines 50–200 inclusive.\n- `:50+150` — 150 lines starting at line 50.\n- `:20+1` — exactly one line.\n- `:5-16,960-973` — multiple ranges in one call (sorted, overlaps merged).\n- `:raw` — verbatim text; no anchors, no summary, no line prefixes.\n- `:2-4:raw` or `:raw:2-4` — range AND verbatim; the two compose in either order.\n- `:conflicts` — one-line-per-block index of every unresolved git merge conflict.\n\n# Files\n\n- Reading a directory path returns a depth-limited dirent listing.\n- Parseable code without a selector returns a **structural summary**: declarations kept, large bodies collapsed to `..` (merged brace pair) or `…` (standalone). Summarized output ends with a footer of the form:\n\n `[NN lines across MM elided regions; read <path>:raw or a line range like <path>:1-9999 for verbatim content]`\n\n If the elided body is what you actually need, re-issue the **exact selector the footer names**. NEVER guess what's inside `..` / `…` — those markers carry no content.\n- Structural summaries honor explicit `truncation`: `head` retains the beginning, `last` the end, and `both` both ends within the summary byte budget. Complete summary units and their original source anchors stay intact and in source order; budget omissions are marked where they occur. This does not switch to raw source. Summaries that fit are unchanged by direction.\n- Directional windows identify the retained first/last lines and the omitted range; use the `re-read <path>:1-<total>` or `:raw` hint in the footer to recover the full content.\n\n# Documents & Notebooks\n\nExtracts text from PDF, Word, PowerPoint, Excel, RTF, and EPUB. Notebooks (`.ipynb`) are shown as editable `# %% [type] cell:N` text; edits round-trip back to the underlying JSON preserving notebook metadata. Add `:raw` to a notebook to bypass the converter and read the JSON directly.\n\n# Images\n\nReading an image path returns the image itself for visual inspection by a vision-capable model.\n\n# Archives\n\nSupports `.tar`, `.tar.gz`, `.tgz`, `.zip`. Use `archive.ext:path/inside/archive` to read a member, and append a normal selector to the inner path: `archive.zip:dir/file.ts:50-60`.\n\n# SQLite\n\nFor `.sqlite`, `.sqlite3`, `.db`, `.db3`:\n- `file.db` — list tables with row counts\n- `file.db:table` — schema + sample rows\n- `file.db:table:key` — single row by primary key\n- `file.db:table?limit=50&offset=100` — paginated rows\n- `file.db:table?where=status='active'&order=created:desc` — filtered rows\n- `file.db?q=SELECT …` — read-only SELECT query\n\n# URLs\n\n- Default reader-mode: HTML pages, GitHub issues/PRs, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, RSS/Atom, JSON endpoints, PDFs → clean text/markdown.\n- `:raw` returns untouched HTML; line selectors (`:50`, `:50-100`, `:50+150`) paginate the cached fetched output.\n- Bare `host:port` URLs collide with the selector grammar — add a trailing slash before the selector: `https://example.com/:80`.\n\n# Internal URIs\n\n`agent://<id>`, `artifact://<id>`, `rule://<name>`, and `local://<name>.md` resolve transparently and accept the same line selectors as filesystem paths. Use `artifact://<id>` to recover full output that a previous bash/eval/tool result spilled or truncated.\n\nBundled skills have no filesystem home, so the skill tool and skill discovery report them as `embedded:gjc/skills/<name>/SKILL.md`; read that identifier verbatim. Bundled skill fragments, when surfaced, likewise use `embedded:gjc/skill-fragments/...` identifiers.\n\n<critical>\n- Always include `path`; never call `read` with `{}`.\n- For line ranges, append the selector to `path`.\n- Re-issue the selector named by a summary footer before relying on elided content.\n</critical>",
|
|
31
31
|
"parameters": {
|
|
32
32
|
"type": "object",
|
|
33
33
|
"properties": {
|
|
@@ -89,6 +89,33 @@ export const TOOL_CATALOG: Readonly<Record<string, ToolCatalogEntry>> = {
|
|
|
89
89
|
"pty": {
|
|
90
90
|
"type": "boolean",
|
|
91
91
|
"description": "run in pty mode"
|
|
92
|
+
},
|
|
93
|
+
"activity": {
|
|
94
|
+
"description": "declare browser activity for the aside browser backend: repl or exec",
|
|
95
|
+
"type": "object",
|
|
96
|
+
"properties": {
|
|
97
|
+
"kind": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"const": "browser"
|
|
100
|
+
},
|
|
101
|
+
"provider": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"const": "aside"
|
|
104
|
+
},
|
|
105
|
+
"mode": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"enum": [
|
|
108
|
+
"repl",
|
|
109
|
+
"exec"
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"required": [
|
|
114
|
+
"kind",
|
|
115
|
+
"provider",
|
|
116
|
+
"mode"
|
|
117
|
+
],
|
|
118
|
+
"additionalProperties": false
|
|
92
119
|
}
|
|
93
120
|
},
|
|
94
121
|
"required": [
|
|
@@ -2326,7 +2353,7 @@ export const TOOL_CATALOG: Readonly<Record<string, ToolCatalogEntry>> = {
|
|
|
2326
2353
|
"job": {
|
|
2327
2354
|
"name": "job",
|
|
2328
2355
|
"label": "Job",
|
|
2329
|
-
"description": "Inspects, waits, or cancels async jobs.\n\nBackground job results are delivered automatically when complete. Jobs that back task subagents should be controlled via the `subagent` tool when it is available; use `job` for non-subagent jobs (async bash, monitors) and as a compatibility fallback. Running job output stays quiet by default to avoid flooding the conversation; use `tail` when you explicitly want to show/reopen retained output. Reach for this tool only when you need to inspect or intervene.\n\nIn the interactive TUI, a running foreground command can be folded into a background job by pressing the fold chord twice (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via `app.tool.backgroundFold`), or automatically when the user sends a steer after the command has run for at least 2 seconds (with `busyPromptMode=steer` (`toolInterruptPolicy` is not a gate)). This covers managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands. A folded job keeps its original deadline, is never killed or restarted by folding, and its result wakes a later turn automatically; a folded PTY continues output-only and no longer accepts input. Job listings expose `foldReason` (`steer`, `chord`, `timer`, or `sdk_control`) beside `backgrounded` so you can tell why a job left the foreground. `task`/`subagent` waits are not foldable. Raw shell `Ctrl+Z`/`bg` is not the supported path inside GJC because it bypasses job ownership and output-routing contracts.\n\n# Operations\n\n## `list: true`\nUse to inspect what's running.\n\n## `tail: [id, …]`\nShow the retained output buffer for one or more background jobs without waiting.\n- Use this to reopen/tail a backgrounded long-running bash/tool output after folding it away.\n- Output is bounded by the manager retention window; stale cursors may report that only the retained tail is available.\n- Prefer `tail` over polling when you only need to peek at progress, so the conversation can continue without flooding the TUI.\n\n## `poll: [id, …]`\nBlock until the specified jobs finish or the wait window (~30 s, not configurable) elapses.\n- Use when you are genuinely blocked on a result and have no other work to do.\n- Returns the current snapshot when the timer elapses; running jobs remain running.\n- Completed jobs include their final output in the returned snapshot.\n\n## `cancel: [id, …]`\nStop running jobs.\n- Use when a job is stalled, hung, or no longer needed.\n- Returns immediately after cancelling.",
|
|
2356
|
+
"description": "Inspects, waits, or cancels async jobs.\n\nBackground job results are delivered automatically when complete. Jobs that back task subagents should be controlled via the `subagent` tool when it is available; use `job` for non-subagent jobs (async bash, monitors) and as a compatibility fallback. Running job output stays quiet by default to avoid flooding the conversation; use `tail` when you explicitly want to show/reopen retained output. Reach for this tool only when you need to inspect or intervene.\n\nIn the interactive TUI, a running foreground command can be folded into a background job by pressing the fold chord twice (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via `app.tool.backgroundFold`), or automatically when the user sends a steer after the command has run for at least 2 seconds (with `busyPromptMode=steer` (`toolInterruptPolicy` is not a gate)). This covers managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands. A folded job keeps its original deadline, is never killed or restarted by folding, and its result wakes a later turn automatically; a folded PTY continues output-only and no longer accepts input. A `job` await also folds after the same 2-second grace window when a steer arrives, returning immediately with the still-running job id(s) while those jobs keep their original deadlines and wake a later turn with their results. Job listings expose `foldReason` (`steer`, `chord`, `timer`, or `sdk_control`) beside `backgrounded` so you can tell why a job left the foreground. `task`/`subagent` waits are not foldable. Raw shell `Ctrl+Z`/`bg` is not the supported path inside GJC because it bypasses job ownership and output-routing contracts.\n\n# Operations\n\n## `list: true`\nUse to inspect what's running.\n\n## `tail: [id, …]`\nShow the retained output buffer for one or more background jobs without waiting.\n- Use this to reopen/tail a backgrounded long-running bash/tool output after folding it away.\n- Output is bounded by the manager retention window; stale cursors may report that only the retained tail is available.\n- Prefer `tail` over polling when you only need to peek at progress, so the conversation can continue without flooding the TUI.\n\n## `poll: [id, …]`\nBlock until the specified jobs finish or the wait window (~30 s, not configurable) elapses.\n- Use when you are genuinely blocked on a result and have no other work to do.\n- Returns the current snapshot when the timer elapses; running jobs remain running.\n- Completed jobs include their final output in the returned snapshot.\n\n## `cancel: [id, …]`\nStop running jobs.\n- Use when a job is stalled, hung, or no longer needed.\n- Returns immediately after cancelling.",
|
|
2330
2357
|
"parameters": {
|
|
2331
2358
|
"type": "object",
|
|
2332
2359
|
"properties": {
|
package/src/tools/tool-errors.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { markDesignedError } from "@gajae-code/utils/error-classification";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Standardized error types for tool execution.
|
|
3
5
|
*
|
|
@@ -16,6 +18,7 @@ export class ToolError extends Error {
|
|
|
16
18
|
) {
|
|
17
19
|
super(message);
|
|
18
20
|
this.name = "ToolError";
|
|
21
|
+
markDesignedError(this);
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
/** Render error for LLM consumption. Override for custom formatting. */
|
|
@@ -33,6 +36,7 @@ export class ToolAbortError extends Error {
|
|
|
33
36
|
constructor(message: string = ToolAbortError.MESSAGE) {
|
|
34
37
|
super(message);
|
|
35
38
|
this.name = "ToolAbortError";
|
|
39
|
+
markDesignedError(this);
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
42
|
|
package/src/utils/git.ts
CHANGED
|
@@ -805,10 +805,18 @@ export const status = Object.assign(
|
|
|
805
805
|
// ════════════════════════════════════════════════════════════════════════════
|
|
806
806
|
|
|
807
807
|
export const stage = {
|
|
808
|
-
/**
|
|
809
|
-
|
|
808
|
+
/**
|
|
809
|
+
* Stage files. Empty array stages all (`git add -A`). Accepts a bare signal or
|
|
810
|
+
* `{ env, signal }`; `env` exists so a caller can stage into an isolated
|
|
811
|
+
* `GIT_INDEX_FILE` instead of the repository's real index.
|
|
812
|
+
*/
|
|
813
|
+
async files(
|
|
814
|
+
cwd: string,
|
|
815
|
+
files: readonly string[] = [],
|
|
816
|
+
options: AbortSignal | Pick<CommandOptions, "env" | "signal"> = {},
|
|
817
|
+
): Promise<void> {
|
|
810
818
|
const args = files.length === 0 ? ["add", "-A"] : ["add", "--", ...files];
|
|
811
|
-
await runEffect(cwd, args, { signal });
|
|
819
|
+
await runEffect(cwd, args, options instanceof AbortSignal ? { signal: options } : options);
|
|
812
820
|
},
|
|
813
821
|
|
|
814
822
|
/** Selectively stage hunks from the provided diff or the current working tree diff. */
|
|
@@ -902,6 +910,28 @@ export async function writeTree(cwd: string, options: Pick<CommandOptions, "env"
|
|
|
902
910
|
return (await runText(cwd, ["write-tree"], options)).trim();
|
|
903
911
|
}
|
|
904
912
|
|
|
913
|
+
export interface CommitTreeOptions {
|
|
914
|
+
readonly env?: Record<string, string | undefined>;
|
|
915
|
+
readonly parents?: readonly string[];
|
|
916
|
+
readonly signal?: AbortSignal;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Create a commit object from an existing tree and return its SHA. Plumbing:
|
|
921
|
+
* unlike `commit` this touches neither the index nor any ref, and runs no
|
|
922
|
+
* `pre-commit`/`commit-msg` hook.
|
|
923
|
+
*/
|
|
924
|
+
export async function commitTree(
|
|
925
|
+
cwd: string,
|
|
926
|
+
tree: string,
|
|
927
|
+
message: string,
|
|
928
|
+
options: CommitTreeOptions = {},
|
|
929
|
+
): Promise<string> {
|
|
930
|
+
const args = ["commit-tree", tree];
|
|
931
|
+
for (const parent of options.parents ?? []) args.push("-p", parent);
|
|
932
|
+
return (await runText(cwd, args, { env: options.env, signal: options.signal, stdin: message })).trim();
|
|
933
|
+
}
|
|
934
|
+
|
|
905
935
|
// ════════════════════════════════════════════════════════════════════════════
|
|
906
936
|
// API: show
|
|
907
937
|
// ════════════════════════════════════════════════════════════════════════════
|
|
@@ -1075,6 +1105,26 @@ export const ref = {
|
|
|
1075
1105
|
return result.stdout.trim() || null;
|
|
1076
1106
|
},
|
|
1077
1107
|
|
|
1108
|
+
/**
|
|
1109
|
+
* Move a ref to `newValue`, but only while it still holds `expectedOldValue`
|
|
1110
|
+
* (the empty string asserts the ref does not exist yet). Git verifies the old
|
|
1111
|
+
* value and writes the new one under its own ref lock, so this is an atomic
|
|
1112
|
+
* compare-and-swap: a concurrent writer that moved the ref first makes this
|
|
1113
|
+
* throw instead of silently clobbering their commit.
|
|
1114
|
+
*/
|
|
1115
|
+
async update(
|
|
1116
|
+
cwd: string,
|
|
1117
|
+
refName: string,
|
|
1118
|
+
newValue: string,
|
|
1119
|
+
expectedOldValue: string,
|
|
1120
|
+
options: { reason?: string; signal?: AbortSignal } = {},
|
|
1121
|
+
): Promise<void> {
|
|
1122
|
+
const args = ["update-ref"];
|
|
1123
|
+
if (options.reason) args.push("-m", options.reason);
|
|
1124
|
+
args.push(refName, newValue, expectedOldValue);
|
|
1125
|
+
await runEffect(cwd, args, { signal: options.signal });
|
|
1126
|
+
},
|
|
1127
|
+
|
|
1078
1128
|
/** Tags pointing at a ref. */
|
|
1079
1129
|
async tags(cwd: string, refName = "HEAD", signal?: AbortSignal): Promise<string[]> {
|
|
1080
1130
|
return splitLines(
|
package/src/utils/markit.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { untilAborted } from "@gajae-code/utils";
|
|
2
|
-
import type { Markit, StreamInfo } from "markit-ai";
|
|
2
|
+
import type { Markit, StreamInfo } from "../../vendor/markit-ai/dist/index.js";
|
|
3
3
|
import { ToolAbortError } from "../tools/tool-errors";
|
|
4
|
-
import {
|
|
4
|
+
import { prepareMuPdf, sanitizeMuPdfDiagnostic, withMuPdfDiagnostic } from "./mupdf";
|
|
5
5
|
|
|
6
6
|
export interface MarkitConversionResult {
|
|
7
7
|
content: string;
|
|
@@ -9,20 +9,23 @@ export interface MarkitConversionResult {
|
|
|
9
9
|
error?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
const instance = new Markit();
|
|
15
|
-
markit = () => instance;
|
|
16
|
-
return instance;
|
|
17
|
-
});
|
|
18
|
-
markit = () => promise;
|
|
19
|
-
return promise;
|
|
20
|
-
};
|
|
12
|
+
let instance: Markit | undefined;
|
|
13
|
+
let instancePromise: Promise<Markit> | undefined;
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
async function loadMarkit(): Promise<Markit> {
|
|
16
|
+
if (instancePromise === undefined) {
|
|
17
|
+
instancePromise = import("../../vendor/markit-ai/dist/index.js")
|
|
18
|
+
.then(({ Markit: MarkitConstructor }) => {
|
|
19
|
+
instance = new MarkitConstructor();
|
|
20
|
+
return instance;
|
|
21
|
+
})
|
|
22
|
+
.catch(error => {
|
|
23
|
+
instancePromise = undefined;
|
|
24
|
+
throw error;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return instancePromise;
|
|
28
|
+
}
|
|
26
29
|
|
|
27
30
|
function normalizeExtension(extension: string): string {
|
|
28
31
|
const trimmed = extension.trim().toLowerCase();
|
|
@@ -30,33 +33,27 @@ function normalizeExtension(extension: string): string {
|
|
|
30
33
|
return trimmed.startsWith(".") ? trimmed : `.${trimmed}`;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
function normalizeError(error: unknown): string {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const base = normalizeError(error);
|
|
47
|
-
if (!base.includes("PDF support requires 'mupdf'")) return base;
|
|
48
|
-
try {
|
|
49
|
-
await import("mupdf");
|
|
50
|
-
} catch (cause) {
|
|
51
|
-
return `${base} (mupdf import failed: ${normalizeError(cause)})`;
|
|
36
|
+
function normalizeError(error: unknown, pdf = false): string {
|
|
37
|
+
const messages: string[] = [];
|
|
38
|
+
const seen = new Set<unknown>();
|
|
39
|
+
while (error !== undefined && !seen.has(error)) {
|
|
40
|
+
seen.add(error);
|
|
41
|
+
if (error instanceof Error) {
|
|
42
|
+
const message = `${error.name}: ${error.message}`;
|
|
43
|
+
messages.push(pdf ? sanitizeMuPdfDiagnostic(message) : message);
|
|
44
|
+
error = error.cause;
|
|
45
|
+
} else {
|
|
46
|
+
messages.push(pdf ? sanitizeMuPdfDiagnostic(String(error)) : String(error));
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
52
49
|
}
|
|
53
|
-
return
|
|
50
|
+
return messages.join("; caused by: ") || "Conversion failed";
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
async function runMarkitConversion<T>(task: (markit: Markit) => Promise<T>, signal?: AbortSignal): Promise<T> {
|
|
57
54
|
try {
|
|
58
|
-
const
|
|
59
|
-
return signal ? await untilAborted(signal, () => task(
|
|
55
|
+
const markit = instance ?? (await loadMarkit());
|
|
56
|
+
return signal ? await untilAborted(signal, () => task(markit)) : await task(markit);
|
|
60
57
|
} catch (error) {
|
|
61
58
|
if (error instanceof ToolAbortError) {
|
|
62
59
|
throw error;
|
|
@@ -78,13 +75,22 @@ function finalizeConversion(markdown?: string): MarkitConversionResult {
|
|
|
78
75
|
|
|
79
76
|
export async function convertFileWithMarkit(filePath: string, signal?: AbortSignal): Promise<MarkitConversionResult> {
|
|
80
77
|
try {
|
|
81
|
-
|
|
78
|
+
if (filePath.toLowerCase().endsWith(".pdf")) await prepareMuPdf();
|
|
79
|
+
const result = await runMarkitConversion(async markit => {
|
|
80
|
+
return markit.convertFile(filePath);
|
|
81
|
+
}, signal);
|
|
82
82
|
return finalizeConversion(result.markdown);
|
|
83
83
|
} catch (error) {
|
|
84
84
|
if (error instanceof ToolAbortError) {
|
|
85
85
|
throw error;
|
|
86
86
|
}
|
|
87
|
-
return {
|
|
87
|
+
return {
|
|
88
|
+
content: "",
|
|
89
|
+
ok: false,
|
|
90
|
+
error: filePath.toLowerCase().endsWith(".pdf")
|
|
91
|
+
? normalizeError(withMuPdfDiagnostic(error), true)
|
|
92
|
+
: normalizeError(error),
|
|
93
|
+
};
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
|
|
@@ -100,12 +106,20 @@ export async function convertBufferWithMarkit(
|
|
|
100
106
|
};
|
|
101
107
|
|
|
102
108
|
try {
|
|
103
|
-
|
|
109
|
+
if (normalizedExtension === ".pdf") await prepareMuPdf();
|
|
110
|
+
const result = await runMarkitConversion(async markit => {
|
|
111
|
+
return markit.convert(Buffer.from(buffer), streamInfo);
|
|
112
|
+
}, signal);
|
|
104
113
|
return finalizeConversion(result.markdown);
|
|
105
114
|
} catch (error) {
|
|
106
115
|
if (error instanceof ToolAbortError) {
|
|
107
116
|
throw error;
|
|
108
117
|
}
|
|
109
|
-
return {
|
|
118
|
+
return {
|
|
119
|
+
content: "",
|
|
120
|
+
ok: false,
|
|
121
|
+
error:
|
|
122
|
+
normalizedExtension === ".pdf" ? normalizeError(withMuPdfDiagnostic(error), true) : normalizeError(error),
|
|
123
|
+
};
|
|
110
124
|
}
|
|
111
125
|
}
|