@gajae-code/coding-agent 0.11.0 → 0.11.2
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 +63 -1
- package/dist/types/async/job-manager.d.ts +46 -7
- package/dist/types/cli/config-cli.d.ts +11 -1
- package/dist/types/cli/notify-cli.d.ts +1 -0
- package/dist/types/cli/session-picker.d.ts +2 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/commands/mcp-serve.d.ts +33 -0
- package/dist/types/commands/mcp.d.ts +1 -1
- package/dist/types/commands/notify.d.ts +0 -2
- package/dist/types/commands/sdk.d.ts +1 -1
- package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
- package/dist/types/config/file-lock.d.ts +14 -4
- package/dist/types/config/keybindings.d.ts +42 -1
- package/dist/types/config/model-auth.d.ts +3 -0
- package/dist/types/config/model-bindings-applier.d.ts +13 -0
- package/dist/types/config/model-discovery-manager.d.ts +49 -0
- package/dist/types/config/model-equivalence.d.ts +20 -0
- package/dist/types/config/model-registry.d.ts +16 -15
- package/dist/types/config/model-resolver.d.ts +28 -18
- package/dist/types/config/models-config-schema.d.ts +11 -0
- package/dist/types/config/settings-schema.d.ts +56 -1
- package/dist/types/config/settings.d.ts +14 -11
- package/dist/types/coordinator-mcp/policy.d.ts +5 -0
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/discovery/helpers.d.ts +0 -6
- package/dist/types/edit/index.d.ts +3 -0
- package/dist/types/eval/py/env.d.ts +9 -0
- package/dist/types/extensibility/extensions/loader.d.ts +2 -1
- package/dist/types/extensibility/extensions/runner.d.ts +2 -2
- package/dist/types/extensibility/extensions/types.d.ts +34 -3
- package/dist/types/extensibility/hooks/runner.d.ts +1 -1
- package/dist/types/extensibility/shared-events.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
- package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
- package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
- package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
- package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
- package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
- package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
- package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
- package/dist/types/gjc-runtime/team-store.d.ts +160 -0
- package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
- package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
- package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
- package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
- package/dist/types/goals/runtime.d.ts +1 -0
- package/dist/types/goals/state.d.ts +8 -0
- package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
- package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
- package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/state.d.ts +11 -4
- package/dist/types/lsp/lspmux.d.ts +5 -3
- package/dist/types/lsp/path-trust.d.ts +1 -0
- package/dist/types/main.d.ts +3 -2
- package/dist/types/memories/storage.d.ts +1 -0
- package/dist/types/modes/action-registry.d.ts +29 -0
- package/dist/types/modes/components/chrome.d.ts +14 -0
- package/dist/types/modes/components/command-palette.d.ts +27 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
- package/dist/types/modes/components/index.d.ts +2 -1
- package/dist/types/modes/components/pet-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
- package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
- package/dist/types/modes/components/queue-pane.d.ts +12 -0
- package/dist/types/modes/components/read-tool-group.d.ts +6 -0
- package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
- package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
- package/dist/types/modes/components/settings-selector.d.ts +1 -1
- package/dist/types/modes/components/show-images-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/types.d.ts +1 -1
- package/dist/types/modes/components/status-line.d.ts +1 -94
- package/dist/types/modes/components/tasks-pane.d.ts +15 -0
- package/dist/types/modes/components/theme-selector.d.ts +1 -1
- package/dist/types/modes/components/tool-execution.d.ts +15 -0
- package/dist/types/modes/components/tool-status-header.d.ts +111 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
- package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
- package/dist/types/modes/controllers/input-controller.d.ts +8 -1
- package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
- package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
- package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
- package/dist/types/modes/interactive-mode.d.ts +21 -19
- package/dist/types/modes/jobs-observer.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +21 -2
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
- package/dist/types/modes/tasks-aggregator.d.ts +39 -0
- package/dist/types/modes/transcript-item-registry.d.ts +60 -0
- package/dist/types/modes/types.d.ts +22 -15
- package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
- package/dist/types/runtime-mcp/manager.d.ts +1 -1
- package/dist/types/sdk/broker/broker.d.ts +78 -12
- package/dist/types/sdk/broker/ensure.d.ts +9 -0
- package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
- package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
- package/dist/types/sdk/broker/session-index.d.ts +0 -1
- package/dist/types/sdk/broker/state-version.d.ts +2 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
- package/dist/types/sdk/bus/config-commands.d.ts +1 -1
- package/dist/types/sdk/bus/config.d.ts +11 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +5 -0
- package/dist/types/sdk/bus/html-format.d.ts +3 -2
- package/dist/types/sdk/bus/index.d.ts +27 -0
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/notification-service.d.ts +20 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
- package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
- package/dist/types/sdk/bus/rich-document.d.ts +7 -0
- package/dist/types/sdk/bus/rich-render.d.ts +18 -41
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +69 -3
- package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
- package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/session-directory.d.ts +56 -0
- package/dist/types/session/agent-session.d.ts +82 -47
- package/dist/types/session/agent-storage.d.ts +7 -0
- package/dist/types/session/fallback-chain-controller.d.ts +10 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
- package/dist/types/session/messages.d.ts +16 -0
- package/dist/types/session/session-manager-internal.d.ts +14 -0
- package/dist/types/session/session-manager.d.ts +82 -12
- package/dist/types/session/session-storage.d.ts +43 -3
- package/dist/types/session/volatile-context-pruning.d.ts +15 -0
- package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
- package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
- package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
- package/dist/types/system-prompt.d.ts +2 -11
- package/dist/types/task/executor.d.ts +3 -1
- package/dist/types/thinking.d.ts +7 -0
- package/dist/types/tool-discovery/tool-index.d.ts +1 -50
- package/dist/types/tools/ask.d.ts +64 -2
- package/dist/types/tools/bash.d.ts +3 -0
- package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
- package/dist/types/tools/cron.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -0
- package/dist/types/tools/index.d.ts +30 -15
- package/dist/types/tools/output-meta.d.ts +1 -0
- package/dist/types/tools/read.d.ts +3 -0
- package/dist/types/tools/search-tool-bm25.d.ts +3 -4
- package/dist/types/tools/subagent-render.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +6 -1
- package/dist/types/utils/event-bus.d.ts +1 -1
- package/dist/types/web/search/index.d.ts +3 -1
- package/package.json +21 -9
- package/scripts/build-sdk-package-smoke.ts +39 -1
- package/scripts/generate-hotkeys-docs.ts +74 -0
- package/scripts/generate-sdk-operation-inventory.ts +64 -20
- package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
- package/src/async/job-manager.ts +455 -69
- package/src/cli/config-cli.ts +75 -2
- package/src/cli/notify-cli.ts +92 -26
- package/src/cli/session-picker.ts +20 -3
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/config.ts +1 -1
- package/src/commands/harness.ts +34 -106
- package/src/commands/launch.ts +6 -4
- package/src/commands/mcp-serve.ts +85 -8
- package/src/commands/mcp.ts +2 -2
- package/src/commands/notify.ts +8 -4
- package/src/commands/sdk.ts +61 -40
- package/src/commands/ultragoal.ts +4 -1
- package/src/config/atomic-yaml-patch.ts +80 -13
- package/src/config/file-lock.ts +105 -43
- package/src/config/keybindings.ts +64 -20
- package/src/config/model-auth.ts +9 -0
- package/src/config/model-bindings-applier.ts +139 -0
- package/src/config/model-discovery-manager.ts +224 -0
- package/src/config/model-equivalence.ts +66 -0
- package/src/config/model-registry.ts +169 -302
- package/src/config/model-resolver.ts +361 -369
- package/src/config/models-config-schema.ts +5 -4
- package/src/config/settings-schema.ts +159 -2
- package/src/config/settings.ts +458 -482
- package/src/coordinator-mcp/policy.ts +76 -11
- package/src/coordinator-mcp/question-gate-codec.ts +274 -0
- package/src/coordinator-mcp/question-state.ts +778 -0
- package/src/coordinator-mcp/server.ts +1702 -238
- package/src/debug/index.ts +1 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
- package/src/defaults/gjc/skills/team/SKILL.md +16 -0
- package/src/discovery/helpers.ts +1 -50
- package/src/edit/index.ts +64 -0
- package/src/eval/py/env.ts +26 -0
- package/src/eval/py/kernel.ts +5 -3
- package/src/extensibility/extensions/loader.ts +9 -1
- package/src/extensibility/extensions/runner.ts +12 -3
- package/src/extensibility/extensions/types.ts +39 -1
- package/src/extensibility/gjc-plugins/installer.ts +16 -16
- package/src/extensibility/hooks/runner.ts +2 -2
- package/src/extensibility/runtime-skill-discovery.ts +33 -13
- package/src/extensibility/shared-events.ts +2 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
- package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
- package/src/gjc-runtime/deep-interview-state.ts +317 -5
- package/src/gjc-runtime/goal-mode-request.ts +55 -8
- package/src/gjc-runtime/launch-tmux.ts +2 -5
- package/src/gjc-runtime/launch-worktree.ts +5 -5
- package/src/gjc-runtime/linux-proc.ts +71 -0
- package/src/gjc-runtime/ralplan-runtime.ts +74 -90
- package/src/gjc-runtime/session-resolution.ts +18 -3
- package/src/gjc-runtime/session-state-sidecar.ts +6 -107
- package/src/gjc-runtime/state-migrations.ts +1 -1
- package/src/gjc-runtime/state-runtime.ts +320 -249
- package/src/gjc-runtime/state-writer.ts +36 -40
- package/src/gjc-runtime/team-launch.ts +319 -0
- package/src/gjc-runtime/team-notify.ts +326 -0
- package/src/gjc-runtime/team-runtime.ts +1099 -1482
- package/src/gjc-runtime/team-store.ts +828 -0
- package/src/gjc-runtime/team-workers.ts +962 -0
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
- package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
- package/src/gjc-runtime/tmux-sessions.ts +4 -21
- package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
- package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
- package/src/gjc-runtime/ultragoal-guard.ts +83 -12
- package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +156 -1319
- package/src/gjc-runtime/workflow-cli-common.ts +30 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +18 -0
- package/src/goals/continuation-timeout-guard.ts +79 -0
- package/src/goals/runtime.ts +7 -5
- package/src/goals/state.ts +18 -0
- package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
- package/src/harness-control-plane/phase-rollup.ts +4 -7
- package/src/harness-control-plane/receipt-ingest.ts +5 -0
- package/src/harness-control-plane/receipt-spool.ts +51 -7
- package/src/harness-control-plane/session-lease.ts +12 -130
- package/src/hindsight/backend.ts +26 -27
- package/src/hindsight/state.ts +101 -32
- package/src/hooks/skill-state.ts +17 -11
- package/src/internal-urls/docs-index.generated.ts +21 -18
- package/src/lsp/client.ts +1 -1
- package/src/lsp/config.ts +145 -26
- package/src/lsp/index.ts +1 -1
- package/src/lsp/lspmux.ts +39 -10
- package/src/lsp/path-trust.ts +81 -0
- package/src/main.ts +28 -8
- package/src/memories/index.ts +1 -0
- package/src/memories/storage.ts +6 -2
- package/src/modes/action-registry.ts +165 -0
- package/src/modes/components/chrome.ts +40 -0
- package/src/modes/components/command-palette.ts +168 -0
- package/src/modes/components/custom-editor.ts +1 -1
- package/src/modes/components/custom-provider-wizard.ts +51 -14
- package/src/modes/components/index.ts +2 -1
- package/src/modes/components/pet-selector.ts +11 -17
- package/src/modes/components/plan-preview-overlay.ts +295 -0
- package/src/modes/components/queue-mode-selector.ts +10 -27
- package/src/modes/components/queue-pane.ts +79 -0
- package/src/modes/components/read-tool-group.ts +13 -0
- package/src/modes/components/session-observer-overlay.ts +207 -772
- package/src/modes/components/sessions-dashboard.ts +181 -0
- package/src/modes/components/settings-selector.ts +1 -1
- package/src/modes/components/show-images-selector.ts +10 -24
- package/src/modes/components/status-line/types.ts +1 -1
- package/src/modes/components/status-line.ts +1 -969
- package/src/modes/components/tasks-pane.ts +73 -0
- package/src/modes/components/theme-selector.ts +11 -31
- package/src/modes/components/tool-execution.ts +22 -0
- package/src/modes/components/tool-status-header.ts +1056 -0
- package/src/modes/components/transcript-viewer-overlay.ts +384 -0
- package/src/modes/controllers/btw-controller.ts +1 -0
- package/src/modes/controllers/command-controller.ts +9 -15
- package/src/modes/controllers/event-controller.ts +3 -2
- package/src/modes/controllers/extension-ui-controller.ts +72 -25
- package/src/modes/controllers/goal-mode-controller.ts +474 -0
- package/src/modes/controllers/input-controller.ts +764 -229
- package/src/modes/controllers/mode-gate.ts +24 -0
- package/src/modes/controllers/plan-mode-controller.ts +517 -0
- package/src/modes/controllers/selector-controller.ts +225 -10
- package/src/modes/controllers/stt-controller.ts +125 -0
- package/src/modes/interactive-mode.ts +302 -1151
- package/src/modes/jobs-observer.ts +3 -0
- package/src/modes/runtime-init.ts +8 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +78 -19
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
- package/src/modes/tasks-aggregator.ts +199 -0
- package/src/modes/transcript-item-registry.ts +229 -0
- package/src/modes/types.ts +47 -20
- package/src/modes/utils/ui-helpers.ts +17 -9
- package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
- package/src/prompts/agent-fragments/restricted-bash.md +1 -0
- package/src/prompts/agents/architect.md +2 -8
- package/src/prompts/agents/critic.md +2 -8
- package/src/prompts/agents/executor.md +3 -0
- package/src/prompts/agents/planner.md +4 -12
- package/src/prompts/system/custom-system-prompt.md +1 -23
- package/src/prompts/system/plan-mode-approved.md +8 -0
- package/src/prompts/system/system-prompt.md +17 -96
- package/src/prompts/tools/bash.md +4 -4
- package/src/prompts/tools/browser.md +15 -52
- package/src/prompts/tools/find.md +2 -2
- package/src/prompts/tools/hashline.md +13 -55
- package/src/prompts/tools/read.md +3 -6
- package/src/prompts/tools/search-tool-bm25.md +0 -2
- package/src/prompts/tools/search.md +2 -4
- package/src/prompts/tools/skill-discovery.md +1 -2
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-mcp/manager.ts +1 -1
- package/src/sdk/broker/broker.ts +206 -78
- package/src/sdk/broker/discovery.ts +21 -2
- package/src/sdk/broker/ensure.ts +85 -25
- package/src/sdk/broker/lifecycle-codec.ts +11 -0
- package/src/sdk/broker/lifecycle-ledger.ts +371 -74
- package/src/sdk/broker/lifecycle.ts +1399 -142
- package/src/sdk/broker/process-incarnation.ts +5 -13
- package/src/sdk/broker/session-index.ts +145 -56
- package/src/sdk/broker/state-version.ts +21 -0
- package/src/sdk/broker/transport.ts +1 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -0
- package/src/sdk/bus/chat-daemon-control.ts +8 -28
- package/src/sdk/bus/chat-effect-journal.ts +14 -4
- package/src/sdk/bus/config-commands.ts +5 -4
- package/src/sdk/bus/config.ts +98 -0
- package/src/sdk/bus/conversation-store.ts +5 -29
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/discord-daemon.ts +25 -8
- package/src/sdk/bus/html-format.ts +20 -3
- package/src/sdk/bus/index.ts +834 -113
- package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
- package/src/sdk/bus/native-runtime-compatibility.ts +1 -1
- package/src/sdk/bus/natives-augment.d.ts +26 -1
- package/src/sdk/bus/notification-service.ts +168 -20
- package/src/sdk/bus/rate-limit-pool.ts +58 -14
- package/src/sdk/bus/recent-activity.ts +188 -74
- package/src/sdk/bus/rich-document.ts +258 -0
- package/src/sdk/bus/rich-render.ts +62 -70
- package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
- package/src/sdk/bus/telegram-daemon.ts +1491 -247
- package/src/sdk/bus/threaded-inbound.ts +8 -3
- package/src/sdk/bus/threaded-render.ts +57 -1
- package/src/sdk/bus/topic-registry.ts +120 -13
- package/src/sdk/host/control/dispatch.ts +14 -2
- package/src/sdk/host/control/operations.ts +6 -1
- package/src/sdk/host/host.ts +31 -1
- package/src/sdk/host/query/handlers.ts +20 -22
- package/src/sdk/host/query/revision-store.ts +80 -57
- package/src/sdk/index.ts +1 -0
- package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
- package/src/sdk/session-directory.ts +141 -0
- package/src/sdk/session.ts +458 -479
- package/src/session/agent-session.ts +1901 -637
- package/src/session/agent-storage.ts +18 -0
- package/src/session/cache-economics.ts +25 -8
- package/src/session/fallback-chain-controller.ts +53 -3
- package/src/session/internal/managed-session-scope.ts +2226 -0
- package/src/session/internal/managed-session-storage.ts +453 -0
- package/src/session/messages.ts +91 -2
- package/src/session/session-manager-internal.ts +33 -0
- package/src/session/session-manager.ts +1112 -333
- package/src/session/session-storage.ts +444 -39
- package/src/session/volatile-context-pruning.ts +78 -0
- package/src/setup/credential-auto-import.ts +2 -1
- package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
- package/src/setup/provider-onboarding.ts +36 -61
- package/src/setup/provider-presets.json +5 -0
- package/src/skill-state/active-state.ts +3 -13
- package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
- package/src/skill-state/workflow-state-contract.ts +6 -41
- package/src/slash-commands/builtin-registry.ts +46 -11
- package/src/system-prompt.ts +37 -44
- package/src/task/agents.ts +19 -1
- package/src/task/executor.ts +90 -6
- package/src/task/index.ts +62 -37
- package/src/thinking.ts +21 -6
- package/src/tool-discovery/tool-index.ts +2 -134
- package/src/tools/ask.ts +157 -21
- package/src/tools/ast-edit.ts +1 -1
- package/src/tools/bash.ts +38 -0
- package/src/tools/browser/dead-tab-recovery.ts +78 -0
- package/src/tools/browser/tab-supervisor.ts +282 -36
- package/src/tools/computer.ts +10 -3
- package/src/tools/cron.ts +30 -16
- package/src/tools/eval.ts +1 -2
- package/src/tools/fetch.ts +11 -4
- package/src/tools/index.ts +76 -24
- package/src/tools/output-meta.ts +13 -5
- package/src/tools/read.ts +37 -1
- package/src/tools/resource-gc.ts +2 -2
- package/src/tools/search-tool-bm25.ts +11 -74
- package/src/tools/subagent-render.ts +19 -8
- package/src/tools/subagent.ts +84 -32
- package/src/utils/event-bus.ts +9 -4
- package/src/web/search/index.ts +3 -3
- package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
- package/src/discovery/plugin-dir-roots.ts +0 -28
- package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
package/src/debug/index.ts
CHANGED
|
@@ -443,7 +443,7 @@ export class DebugSelectorComponent extends Container {
|
|
|
443
443
|
return {
|
|
444
444
|
model: this.ctx.session.model?.id,
|
|
445
445
|
thinkingLevel: this.ctx.session.thinkingLevel,
|
|
446
|
-
planModeEnabled: this.ctx.
|
|
446
|
+
planModeEnabled: this.ctx.planModeController.enabled,
|
|
447
447
|
toolOutputExpanded: this.ctx.toolOutputExpanded,
|
|
448
448
|
hideThinkingBlock: this.ctx.hideThinkingBlock,
|
|
449
449
|
};
|
|
@@ -248,11 +248,19 @@ I'm reading this as {N} top-level component(s):
|
|
|
248
248
|
1. {component_name}: {one_sentence_description}
|
|
249
249
|
2. ...
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
Locked intent:
|
|
252
|
+
- Artifacts: {category-prefixed IDs and concrete outputs}
|
|
253
|
+
- Surfaces: {category-prefixed IDs and user-visible surfaces}
|
|
254
|
+
- Integrations: {category-prefixed IDs and external/system boundaries}
|
|
255
|
+
- Constraints: {category-prefixed IDs and user-locked constraints}
|
|
256
|
+
|
|
257
|
+
Is that topology and locked intent right? Should any component or intent be added, removed, merged, split, or explicitly deferred?
|
|
252
258
|
```
|
|
253
259
|
|
|
254
260
|
Options should include contextually relevant choices such as **Looks right**, **Add/remove/merge components**, **Defer one or more components**, plus free-text, translated/localized according to `language.instruction` when present. This is the only pre-scoring question and preserves the one-question-per-round rule.
|
|
255
261
|
|
|
262
|
+
The Round 0 `ask` call MUST include `deepInterview.round = 0`, `deepInterview.component = "review-topology"`, `deepInterview.dimension = "topology"`, `deepInterview.intent_contract.items` containing the exact displayed locked-intent items, and `deepInterview.intent_contract.confirmation_options` listing only the displayed affirmative labels that lock the proposal (normally **Looks right**). The runtime recorder canonicalizes and locks this contract only when the user selects one of those labels; correction, deferral, free-text, and clarification answers never lock the pre-question proposal. Do not manually copy raw free text into intent evidence, and do not continue if this required recorder write fails.
|
|
263
|
+
|
|
256
264
|
3. **Lock topology into state** after the answer. Store a normalized component list and confirmation timestamp:
|
|
257
265
|
|
|
258
266
|
```json
|
|
@@ -288,6 +296,10 @@ Options should include contextually relevant choices such as **Looks right**, **
|
|
|
288
296
|
}
|
|
289
297
|
```
|
|
290
298
|
|
|
299
|
+
In the same Round 0 answer, the runtime recorder persists `state.intent_contract` version 1 from `deepInterview.intent_contract.items`. It contains the four exact categories `artifact`, `surface`, `integration`, and `constraint`; every item has a unique category-prefixed ID (for example `surface:review`) and a bounded non-empty statement. The recorder canonically sorts items, persists the full SHA-256 manifest digest, and binds confirmation to a redacted answer-hash reference. The confirmation answer locks this manifest before Round 1; later prose, inferred implementation detail, raw answer content, or a regenerated digest cannot replace it.
|
|
300
|
+
|
|
301
|
+
Before spec persistence, include every preserved locked ID literally in the final spec. Additions and clarifications need no extra question; the runtime derives and persists a `not_required` review when every locked ID remains. For any proposed missing locked ID, ask one intent-review question through `ask` and include `deepInterview.intent_review` with the proposed `observed_items`, every `supporting_substitution`, and the exact `approval_options` labels that count as approval. The runtime recorder writes `pending` when the user does not approve and writes `approved` only when an approval option is selected, binding the review to the recorder-generated answer hash without storing raw answer text. Approved reductions require every removed ID to map to an observed replacement ID. Spec persistence and handoff fail closed for missing, pending, malformed, stale, or unrecorded reduction review evidence. Intent review approves only that output reduction and never authorizes execution or ralplan handoff.
|
|
302
|
+
|
|
291
303
|
4. **Legacy state migration:** When resuming an existing `deep-interview` state file that lacks `topology`, treat it as `"status": "legacy_missing"`. If no final `spec_path` exists yet, run Round 0 before the next ambiguity scoring pass and then continue with the existing transcript. If a final spec already exists, do not rewrite history; note in any handoff that topology was not captured for that legacy interview.
|
|
292
304
|
|
|
293
305
|
5. **Single-component pass-through:** If the user confirms one active component, Phase 2 proceeds with the existing flow while still carrying `topology.components[0]` into scoring and spec output.
|
|
@@ -203,6 +203,22 @@ sleep 30 && gjc team monitor <team-name>
|
|
|
203
203
|
```
|
|
204
204
|
The mutating monitor path also performs bounded liveness recovery: expired task claims, stale heartbeat claims, and missing recorded worker panes are requeued instead of leaving work permanently `in_progress`.
|
|
205
205
|
|
|
206
|
+
### Opt-in stalled-worker continuation
|
|
207
|
+
|
|
208
|
+
`GJC_TEAM_AUTO_CONTINUE_STALLED_WORKERS=1` enables a separate, default-off monitor-only nudge for a stalled live worker. It is considered only when the team is running (not dry-run), the worker heartbeat is stale (using `GJC_TEAM_HEARTBEAT_STALE_MS`, default `120000` ms), and all of these checks pass:
|
|
209
|
+
|
|
210
|
+
- The recorded pane id is a non-leader `%<number>` pane that tmux currently reports in the recorded `tmux_target` as that same pane id; no other pane is targeted.
|
|
211
|
+
- Shutdown authority is proven absent; valid-present and invalid/unreadable records veto continuation without suppressing normal stale-claim recovery.
|
|
212
|
+
- Lifecycle is `ready` or `working`, and worker status is a structurally valid non-terminal state (not `draining`, `failed`, or `unknown`).
|
|
213
|
+
- One current non-terminal task is `in_progress`, assigned to and claimed by that worker; the stored claim record exactly matches its owner, token, and lease.
|
|
214
|
+
- The lease remains valid through the entire next hold interval.
|
|
215
|
+
|
|
216
|
+
The policy has at most two attempts per immutable incident: attempt 1 reserves a 30-second hold, then attempt 2 reserves a 120-second hold only after attempt 1 was recorded as sent and its hold elapsed. A retry still requires the heartbeat to be stale and every fence above to pass. Reservations and outcomes are create-without-clobber journal records keyed to the incident identity; a pre-existing reservation, an unknown/missing/non-sent outcome after restart, or a second-attempt record fails closed rather than sending again.
|
|
217
|
+
|
|
218
|
+
Each eligible attempt sends only the fixed continuation prompt to that verified recorded worker pane, followed by Enter. It does not replay provider output or a prior prompt, inspect or inject dynamic pane content, cross pane boundaries, kill or relaunch workers, create/split panes, or extend/rewrite claims. This bounded nudge is not automatic recovery for a dead, shutdown, reassigned, terminal, or lease-expired worker. When it cannot act, use `gjc team status <team-name>` / `gjc team monitor <team-name>` and the documented state evidence; manual pane intervention remains the last-resort fallback.
|
|
219
|
+
|
|
220
|
+
Continuation input is unsupported on psmux and native Windows send-keys fallback transports: the fixed prompt is not dispatched there because equivalent literal-input semantics are not proven. Startup's existing empty-pane worker command fallback is separate and unchanged.
|
|
221
|
+
|
|
206
222
|
## Operational Commands
|
|
207
223
|
|
|
208
224
|
```bash
|
package/src/discovery/helpers.ts
CHANGED
|
@@ -20,8 +20,6 @@ import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
|
|
|
20
20
|
import type { ForkContextPolicy } from "../task/types";
|
|
21
21
|
import { parseThinkingLevel } from "../thinking";
|
|
22
22
|
|
|
23
|
-
import { buildPluginDirRoot } from "./plugin-dir-roots";
|
|
24
|
-
|
|
25
23
|
/**
|
|
26
24
|
* Standard paths for each config source.
|
|
27
25
|
*/
|
|
@@ -900,14 +898,6 @@ export async function listClaudePluginRoots(
|
|
|
900
898
|
roots.push(...projectRoots, ...deduped);
|
|
901
899
|
}
|
|
902
900
|
|
|
903
|
-
// Merge --plugin-dir roots (highest precedence) on every fresh load
|
|
904
|
-
if (injectedPluginDirRoots.length > 0) {
|
|
905
|
-
const injectedIds = new Set(injectedPluginDirRoots.map(r => r.id));
|
|
906
|
-
const filtered = roots.filter(r => !injectedIds.has(r.id));
|
|
907
|
-
roots.length = 0;
|
|
908
|
-
roots.push(...injectedPluginDirRoots, ...filtered);
|
|
909
|
-
}
|
|
910
|
-
|
|
911
901
|
const result = { roots, warnings };
|
|
912
902
|
pluginRootsCache.set(cacheKey, result);
|
|
913
903
|
return result;
|
|
@@ -918,7 +908,7 @@ export async function listClaudePluginRoots(
|
|
|
918
908
|
*/
|
|
919
909
|
export function clearClaudePluginRootsCache(): void {
|
|
920
910
|
pluginRootsCache.clear();
|
|
921
|
-
preloadedPluginRoots = [
|
|
911
|
+
preloadedPluginRoots = [];
|
|
922
912
|
// Re-warm preloaded roots asynchronously so sync LSP config reads stay valid
|
|
923
913
|
if (lastPreloadHome) {
|
|
924
914
|
void preloadPluginRoots(lastPreloadHome, getProjectDir());
|
|
@@ -941,7 +931,6 @@ export function clearPluginRootsAndCaches(extraPaths?: readonly string[]): void
|
|
|
941
931
|
// getPreloadedPluginRoots(). Safe degradation: empty array if not warmed.
|
|
942
932
|
|
|
943
933
|
let preloadedPluginRoots: ClaudePluginRoot[] = [];
|
|
944
|
-
let injectedPluginDirRoots: ClaudePluginRoot[] = [];
|
|
945
934
|
let lastPreloadHome: string | undefined;
|
|
946
935
|
|
|
947
936
|
/**
|
|
@@ -962,41 +951,3 @@ export async function preloadPluginRoots(home: string, cwd?: string): Promise<vo
|
|
|
962
951
|
export function getPreloadedPluginRoots(): readonly ClaudePluginRoot[] {
|
|
963
952
|
return preloadedPluginRoots;
|
|
964
953
|
}
|
|
965
|
-
|
|
966
|
-
// ── --plugin-dir injection ──────────────────────────────────────────────────
|
|
967
|
-
|
|
968
|
-
/**
|
|
969
|
-
* Inject synthetic plugin roots from --plugin-dir paths.
|
|
970
|
-
* These are prepended to the cache with highest precedence (before GJC/Anthropic model entries).
|
|
971
|
-
* Must be called before any listAnthropic modelPluginRoots() access.
|
|
972
|
-
*/
|
|
973
|
-
export async function injectPluginDirRoots(home: string, dirs: string[], cwd?: string): Promise<void> {
|
|
974
|
-
const injected: ClaudePluginRoot[] = [];
|
|
975
|
-
for (const dir of dirs) {
|
|
976
|
-
const resolved = path.resolve(dir);
|
|
977
|
-
// Read plugin name from manifest
|
|
978
|
-
let pluginName = path.basename(resolved);
|
|
979
|
-
try {
|
|
980
|
-
const manifestPath = path.join(resolved, ".claude-plugin", "plugin.json");
|
|
981
|
-
const content = await Bun.file(manifestPath).text();
|
|
982
|
-
const manifest = JSON.parse(content);
|
|
983
|
-
if (typeof manifest.name === "string" && manifest.name) {
|
|
984
|
-
pluginName = manifest.name;
|
|
985
|
-
}
|
|
986
|
-
} catch {
|
|
987
|
-
// No manifest or invalid — use directory name
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
injected.push(buildPluginDirRoot(resolved, pluginName));
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
// Set injected roots BEFORE populating cache so listAnthropic modelPluginRoots merges them.
|
|
994
|
-
injectedPluginDirRoots = injected;
|
|
995
|
-
lastPreloadHome = home; // ensure cache-clear re-warm fires even when injectPluginDirRoots was the startup path
|
|
996
|
-
// Clear any stale cache entries (populated before injected roots were set).
|
|
997
|
-
pluginRootsCache.clear();
|
|
998
|
-
// Rebuild — cache miss triggers fresh load that includes both user+project registries
|
|
999
|
-
// and prepends injectedPluginDirRoots at highest precedence.
|
|
1000
|
-
const { roots } = await listClaudePluginRoots(home, cwd);
|
|
1001
|
-
preloadedPluginRoots = roots;
|
|
1002
|
-
}
|
package/src/edit/index.ts
CHANGED
|
@@ -57,6 +57,69 @@ type VimParams = z.infer<typeof vimSchema>;
|
|
|
57
57
|
type EditParams = ReplaceParams | PatchParams | HashlineParams | VimParams | ApplyPatchParams;
|
|
58
58
|
type EditToolResultDetails = EditToolDetails | VimToolDetails;
|
|
59
59
|
|
|
60
|
+
const UNSAFE_EDIT_SUMMARY_PATH =
|
|
61
|
+
/(?:\b(?:https?|wss?):\/\/|\b(?:api[-_ ]?key|access[-_ ]?token|bearer|secret|password)\b|\b(?:sk|pk|rk)-[A-Za-z0-9_-]{12,})/i;
|
|
62
|
+
|
|
63
|
+
const MAX_APPLY_PATCH_ACTIVITY_FILES = 2;
|
|
64
|
+
|
|
65
|
+
function isSafeEditSummaryPath(value: unknown): value is string {
|
|
66
|
+
return typeof value === "string" && value.length > 0 && value.length <= 100 && !UNSAFE_EDIT_SUMMARY_PATH.test(value);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Summarize only apply_patch file-operation headers, never its patch body. */
|
|
70
|
+
function summarizeApplyPatchActivity(input: string): string | undefined {
|
|
71
|
+
if (!input.trimStart().startsWith("*** Begin Patch")) return undefined;
|
|
72
|
+
|
|
73
|
+
const paths: string[] = [];
|
|
74
|
+
const marker = /^\*\*\* (?:Add|Delete|Update) File: ([^\r\n]+)\r?$/gm;
|
|
75
|
+
let count = 0;
|
|
76
|
+
let match = marker.exec(input);
|
|
77
|
+
while (match !== null) {
|
|
78
|
+
const editPath = match[1]!.trim();
|
|
79
|
+
if (!isSafeEditSummaryPath(editPath)) return undefined;
|
|
80
|
+
count++;
|
|
81
|
+
if (paths.length < MAX_APPLY_PATCH_ACTIVITY_FILES) paths.push(editPath);
|
|
82
|
+
match = marker.exec(input);
|
|
83
|
+
}
|
|
84
|
+
if (count === 0) return undefined;
|
|
85
|
+
|
|
86
|
+
const displayedPaths =
|
|
87
|
+
count > MAX_APPLY_PATCH_ACTIVITY_FILES ? `${paths.join(", ")}, +${count - paths.length} more` : paths.join(", ");
|
|
88
|
+
return `${displayedPaths}, ${count} edit${count === 1 ? "" : "s"}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Project edit targets and operation counts without exposing patches, diffs, or file contents. */
|
|
92
|
+
export function summarizeEditToolActivity(kind: "args" | "result", value: unknown): string | undefined {
|
|
93
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
94
|
+
const record = value as Record<string, unknown>;
|
|
95
|
+
if (kind === "args") {
|
|
96
|
+
const applyPatchInput = record.input;
|
|
97
|
+
if (typeof applyPatchInput === "string") return summarizeApplyPatchActivity(applyPatchInput);
|
|
98
|
+
|
|
99
|
+
const editPath = record.path;
|
|
100
|
+
if (!isSafeEditSummaryPath(editPath)) return undefined;
|
|
101
|
+
const edits = record.edits;
|
|
102
|
+
const count = Array.isArray(edits) ? edits.length : 1;
|
|
103
|
+
return `${editPath}, ${count} edit${count === 1 ? "" : "s"}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const details = record.details;
|
|
107
|
+
if (!details || typeof details !== "object" || Array.isArray(details)) return undefined;
|
|
108
|
+
const perFileResults = (details as Record<string, unknown>).perFileResults;
|
|
109
|
+
const count = Array.isArray(perFileResults)
|
|
110
|
+
? perFileResults.length
|
|
111
|
+
: "path" in (details as Record<string, unknown>)
|
|
112
|
+
? 1
|
|
113
|
+
: 0;
|
|
114
|
+
if (count === 0) return undefined;
|
|
115
|
+
const failed =
|
|
116
|
+
record.isError === true ||
|
|
117
|
+
(Array.isArray(perFileResults) &&
|
|
118
|
+
perFileResults.some(
|
|
119
|
+
entry => typeof entry === "object" && entry !== null && (entry as Record<string, unknown>).isError === true,
|
|
120
|
+
));
|
|
121
|
+
return `${failed ? "failed" : "applied"}, ${count} file${count === 1 ? "" : "s"}`;
|
|
122
|
+
}
|
|
60
123
|
type EditModeDefinition = {
|
|
61
124
|
description: (session: ToolSession) => string;
|
|
62
125
|
parameters: TInput;
|
|
@@ -279,6 +342,7 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
279
342
|
readonly nonAbortable = true;
|
|
280
343
|
readonly concurrency = "exclusive";
|
|
281
344
|
readonly strict = true;
|
|
345
|
+
readonly safeSummary = summarizeEditToolActivity;
|
|
282
346
|
|
|
283
347
|
readonly #allowFuzzy: boolean;
|
|
284
348
|
readonly #fuzzyThreshold: number;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Environment values consulted by the Python subprocess integration. */
|
|
2
|
+
export type PythonEnv = Record<string, string | undefined>;
|
|
3
|
+
|
|
4
|
+
const PYTHON_TRUTHY = new Set(["1", "true", "yes", "on", "y"]);
|
|
5
|
+
|
|
6
|
+
/** True when `value` is a non-empty string matching a truthy boolean token. */
|
|
7
|
+
export function isTruthyPythonFlag(value: string | undefined): boolean {
|
|
8
|
+
return value !== undefined && PYTHON_TRUTHY.has(value.trim().toLowerCase());
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Resolve paired GJC/legacy PI flags using OR semantics. */
|
|
12
|
+
export function resolvePythonFlag(env: PythonEnv, gjcName: string, piName: string): boolean {
|
|
13
|
+
return isTruthyPythonFlag(env[gjcName]) || isTruthyPythonFlag(env[piName]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function resolvePythonSkipCheck(env: PythonEnv): boolean {
|
|
17
|
+
return resolvePythonFlag(env, "GJC_PYTHON_SKIP_CHECK", "PI_PYTHON_SKIP_CHECK");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function resolvePythonIpcTrace(env: PythonEnv): boolean {
|
|
21
|
+
return resolvePythonFlag(env, "GJC_PYTHON_IPC_TRACE", "PI_PYTHON_IPC_TRACE");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function resolvePythonIntegrationGate(env: PythonEnv): boolean {
|
|
25
|
+
return resolvePythonFlag(env, "GJC_PYTHON_INTEGRATION", "PI_PYTHON_INTEGRATION");
|
|
26
|
+
}
|
package/src/eval/py/kernel.ts
CHANGED
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
12
|
import * as os from "node:os";
|
|
13
13
|
import * as path from "node:path";
|
|
14
|
-
import { $
|
|
14
|
+
import { $env, isBunTestRuntime, logger, Snowflake } from "@gajae-code/utils";
|
|
15
15
|
import type { Subprocess } from "bun";
|
|
16
16
|
import { $ } from "bun";
|
|
17
17
|
import { Settings } from "../../config/settings";
|
|
18
18
|
import { type KernelDisplayOutput, renderKernelDisplay } from "./display";
|
|
19
|
+
import { resolvePythonIpcTrace, resolvePythonSkipCheck } from "./env";
|
|
19
20
|
import { PYTHON_PRELUDE } from "./prelude";
|
|
20
21
|
import RUNNER_SCRIPT from "./runner.py" with { type: "text" };
|
|
21
22
|
import { ensurePythonRuntime, filterEnv, type PythonRuntimeOptions } from "./runtime";
|
|
@@ -23,7 +24,8 @@ import { ensurePythonRuntime, filterEnv, type PythonRuntimeOptions } from "./run
|
|
|
23
24
|
export type { KernelDisplayOutput, PythonStatusEvent } from "./display";
|
|
24
25
|
export { renderKernelDisplay } from "./display";
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
// Dual-read: `GJC_PYTHON_IPC_TRACE` is preferred, then legacy `PI_PYTHON_IPC_TRACE`.
|
|
28
|
+
const TRACE_IPC = resolvePythonIpcTrace($env);
|
|
27
29
|
|
|
28
30
|
// Cache the runner script on disk so the subprocess loads it normally. Cached
|
|
29
31
|
// per script hash so installs don't race across versions.
|
|
@@ -125,7 +127,7 @@ export async function checkPythonKernelAvailability(
|
|
|
125
127
|
cwd: string,
|
|
126
128
|
runtimeOptions?: PythonRuntimeOptions,
|
|
127
129
|
): Promise<PythonKernelAvailability> {
|
|
128
|
-
if (isBunTestRuntime() || $
|
|
130
|
+
if (isBunTestRuntime() || resolvePythonSkipCheck($env)) {
|
|
129
131
|
return { ok: true };
|
|
130
132
|
}
|
|
131
133
|
try {
|
|
@@ -5,7 +5,7 @@ import type * as fs1 from "node:fs";
|
|
|
5
5
|
import * as fs from "node:fs/promises";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import type { ThinkingLevel } from "@gajae-code/agent-core";
|
|
8
|
-
import type { ImageContent, Model, TextContent, UsageReport } from "@gajae-code/ai";
|
|
8
|
+
import type { ImageContent, Model, TextContent, Tool, UsageReport } from "@gajae-code/ai";
|
|
9
9
|
import type { KeyId } from "@gajae-code/tui";
|
|
10
10
|
import { hasFsCode, isEacces, isEnoent, logger } from "@gajae-code/utils";
|
|
11
11
|
import * as Zod from "zod/v4";
|
|
@@ -82,6 +82,10 @@ export class ExtensionRuntime implements IExtensionRuntime {
|
|
|
82
82
|
throw new ExtensionRuntimeNotInitializedError();
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
resolveTool(): Pick<Tool, "safeSummary" | "safeSummaryFields"> | undefined {
|
|
86
|
+
throw new ExtensionRuntimeNotInitializedError();
|
|
87
|
+
}
|
|
88
|
+
|
|
85
89
|
setActiveTools(): Promise<void> {
|
|
86
90
|
throw new ExtensionRuntimeNotInitializedError();
|
|
87
91
|
}
|
|
@@ -257,6 +261,10 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
|
|
|
257
261
|
return this.runtime.getAllTools();
|
|
258
262
|
}
|
|
259
263
|
|
|
264
|
+
resolveTool(name: string): Pick<Tool, "safeSummary" | "safeSummaryFields"> | undefined {
|
|
265
|
+
return this.runtime.resolveTool(name);
|
|
266
|
+
}
|
|
267
|
+
|
|
260
268
|
setActiveTools(toolNames: string[]): Promise<void> {
|
|
261
269
|
return this.runtime.setActiveTools(toolNames);
|
|
262
270
|
}
|
|
@@ -8,7 +8,7 @@ import { logger } from "@gajae-code/utils";
|
|
|
8
8
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
9
9
|
import type { WorkflowGateEmitter } from "../../modes/shared/agent-wire/workflow-gate-broker";
|
|
10
10
|
import { type Theme, theme } from "../../modes/theme/theme";
|
|
11
|
-
import type
|
|
11
|
+
import { createReadonlySessionManager, type SessionManager } from "../../session/session-manager";
|
|
12
12
|
import type {
|
|
13
13
|
AfterProviderResponseEvent,
|
|
14
14
|
BeforeAgentStartEvent,
|
|
@@ -199,6 +199,7 @@ export class ExtensionRunner {
|
|
|
199
199
|
#getQueuedMessagesFn: ExtensionContext["getQueuedMessages"] = () => [];
|
|
200
200
|
#getActiveToolsFn: ExtensionContext["getActiveTools"] = () => [];
|
|
201
201
|
#getAllToolsFn: ExtensionContext["getAllTools"] = () => [];
|
|
202
|
+
#getResolveToolFn: ExtensionContext["resolveTool"] = () => undefined;
|
|
202
203
|
#cycleModelFn: ExtensionContextActions["cycleModel"] = undefined;
|
|
203
204
|
#cycleThinkingLevelFn: ExtensionContextActions["cycleThinkingLevel"] = undefined;
|
|
204
205
|
#setQueueModeFn: ExtensionContextActions["setQueueMode"] = undefined;
|
|
@@ -275,6 +276,7 @@ export class ExtensionRunner {
|
|
|
275
276
|
this.runtime.appendEntry = actions.appendEntry;
|
|
276
277
|
this.runtime.getActiveTools = actions.getActiveTools;
|
|
277
278
|
this.runtime.getAllTools = actions.getAllTools;
|
|
279
|
+
this.runtime.resolveTool = actions.resolveTool ?? (() => undefined);
|
|
278
280
|
this.runtime.setActiveTools = actions.setActiveTools;
|
|
279
281
|
this.runtime.getCommands = actions.getCommands;
|
|
280
282
|
this.runtime.setModel = actions.setModel;
|
|
@@ -309,6 +311,7 @@ export class ExtensionRunner {
|
|
|
309
311
|
this.#getQueuedMessagesFn = contextActions.getQueuedMessages ?? (() => []);
|
|
310
312
|
this.#getActiveToolsFn = contextActions.getActiveTools ?? (() => []);
|
|
311
313
|
this.#getAllToolsFn = contextActions.getAllTools ?? (() => []);
|
|
314
|
+
this.#getResolveToolFn = contextActions.resolveTool ?? (() => undefined);
|
|
312
315
|
this.#cycleModelFn = contextActions.cycleModel;
|
|
313
316
|
this.#cycleThinkingLevelFn = contextActions.cycleThinkingLevel;
|
|
314
317
|
this.#setQueueModeFn = contextActions.setQueueMode;
|
|
@@ -540,7 +543,7 @@ export class ExtensionRunner {
|
|
|
540
543
|
compact: instructionsOrOptions => this.#compactFn(instructionsOrOptions),
|
|
541
544
|
hasUI: this.hasUI(),
|
|
542
545
|
cwd: this.cwd,
|
|
543
|
-
sessionManager: this.sessionManager,
|
|
546
|
+
sessionManager: createReadonlySessionManager(this.sessionManager),
|
|
544
547
|
sessionMetadata: this.sessionMetadata,
|
|
545
548
|
modelRegistry: this.modelRegistry,
|
|
546
549
|
get model() {
|
|
@@ -557,6 +560,7 @@ export class ExtensionRunner {
|
|
|
557
560
|
getQueuedMessages: () => this.#getQueuedMessagesFn(),
|
|
558
561
|
getActiveTools: () => this.#getActiveToolsFn(),
|
|
559
562
|
getAllTools: () => this.#getAllToolsFn(),
|
|
563
|
+
resolveTool: name => this.#getResolveToolFn(name),
|
|
560
564
|
cycleModel: async () => await this.#cycleModelFn?.(),
|
|
561
565
|
cycleThinkingLevel: () => this.#cycleThinkingLevelFn?.(),
|
|
562
566
|
setQueueMode: (kind, mode) => this.#setQueueModeFn?.(kind, mode) ?? false,
|
|
@@ -678,7 +682,10 @@ export class ExtensionRunner {
|
|
|
678
682
|
}
|
|
679
683
|
}
|
|
680
684
|
|
|
681
|
-
async emit<TEvent extends RunnerEmitEvent>(
|
|
685
|
+
async emit<TEvent extends RunnerEmitEvent>(
|
|
686
|
+
event: TEvent,
|
|
687
|
+
continueWhile?: () => boolean,
|
|
688
|
+
): Promise<RunnerEmitResult<TEvent>> {
|
|
682
689
|
const handlers = this.#handlersByEvent.get(event.type) ?? [];
|
|
683
690
|
if (handlers.length === 0) return undefined as RunnerEmitResult<TEvent>;
|
|
684
691
|
|
|
@@ -686,7 +693,9 @@ export class ExtensionRunner {
|
|
|
686
693
|
let result: SessionBeforeEventResult | SessionCompactingResult | undefined;
|
|
687
694
|
|
|
688
695
|
for (const { ext, handler } of handlers) {
|
|
696
|
+
if (continueWhile && !continueWhile()) return result as RunnerEmitResult<TEvent>;
|
|
689
697
|
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
698
|
+
if (continueWhile && !continueWhile()) return result as RunnerEmitResult<TEvent>;
|
|
690
699
|
|
|
691
700
|
if (this.#isSessionBeforeEvent(event) && handlerResult) {
|
|
692
701
|
result = handlerResult as SessionBeforeEventResult;
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
SimpleStreamOptions,
|
|
22
22
|
Static,
|
|
23
23
|
TextContent,
|
|
24
|
+
Tool,
|
|
24
25
|
TSchema,
|
|
25
26
|
UsageReport,
|
|
26
27
|
} from "@gajae-code/ai";
|
|
@@ -271,7 +272,11 @@ export interface ExtensionUIContext {
|
|
|
271
272
|
/** Get current tool output expansion state. */
|
|
272
273
|
getToolsExpanded(): boolean;
|
|
273
274
|
|
|
274
|
-
/**
|
|
275
|
+
/**
|
|
276
|
+
* Set tool output expansion state. This is an explicit fold choice, pinning
|
|
277
|
+
* existing tool and read components for their renderer instance lifetime,
|
|
278
|
+
* the same as the user shortcut.
|
|
279
|
+
*/
|
|
275
280
|
setToolsExpanded(expanded: boolean): void;
|
|
276
281
|
}
|
|
277
282
|
|
|
@@ -352,6 +357,8 @@ export interface ExtensionContext {
|
|
|
352
357
|
getQueuedMessages(): unknown[];
|
|
353
358
|
getActiveTools(): string[];
|
|
354
359
|
getAllTools(): string[];
|
|
360
|
+
/** Resolve display-safe metadata for a configured tool without exposing its implementation. */
|
|
361
|
+
resolveTool(name: string): Pick<Tool, "safeSummary" | "safeSummaryFields"> | undefined;
|
|
355
362
|
/** Session control seams used by the SDK host. */
|
|
356
363
|
cycleModel(): Promise<{ model: Model; thinkingLevel: ThinkingLevel | undefined } | undefined>;
|
|
357
364
|
cycleThinkingLevel(): ThinkingLevel | undefined;
|
|
@@ -589,6 +596,26 @@ export interface MessageUpdateEvent {
|
|
|
589
596
|
assistantMessageEvent: AssistantMessageEvent;
|
|
590
597
|
}
|
|
591
598
|
|
|
599
|
+
export interface ReasoningSummaryStartEvent {
|
|
600
|
+
type: "reasoning_summary_start";
|
|
601
|
+
message: AgentMessage;
|
|
602
|
+
contentIndex: number;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
export interface ReasoningSummaryDeltaEvent {
|
|
606
|
+
type: "reasoning_summary_delta";
|
|
607
|
+
message: AgentMessage;
|
|
608
|
+
contentIndex: number;
|
|
609
|
+
delta: string;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
export interface ReasoningSummaryEndEvent {
|
|
613
|
+
type: "reasoning_summary_end";
|
|
614
|
+
message: AgentMessage;
|
|
615
|
+
contentIndex: number;
|
|
616
|
+
content: string;
|
|
617
|
+
}
|
|
618
|
+
|
|
592
619
|
/** Fired when a message ends */
|
|
593
620
|
export interface MessageEndEvent {
|
|
594
621
|
type: "message_end";
|
|
@@ -838,6 +865,9 @@ export type ExtensionEvent =
|
|
|
838
865
|
| MessageStartEvent
|
|
839
866
|
| MessageUpdateEvent
|
|
840
867
|
| MessageEndEvent
|
|
868
|
+
| ReasoningSummaryStartEvent
|
|
869
|
+
| ReasoningSummaryDeltaEvent
|
|
870
|
+
| ReasoningSummaryEndEvent
|
|
841
871
|
| ToolExecutionStartEvent
|
|
842
872
|
| ToolExecutionUpdateEvent
|
|
843
873
|
| ToolExecutionEndEvent
|
|
@@ -999,6 +1029,9 @@ export interface ExtensionAPI {
|
|
|
999
1029
|
on(event: "turn_end", handler: ExtensionHandler<TurnEndEvent>): void;
|
|
1000
1030
|
on(event: "message_start", handler: ExtensionHandler<MessageStartEvent>): void;
|
|
1001
1031
|
on(event: "message_update", handler: ExtensionHandler<MessageUpdateEvent>): void;
|
|
1032
|
+
on(event: "reasoning_summary_start", handler: ExtensionHandler<ReasoningSummaryStartEvent>): void;
|
|
1033
|
+
on(event: "reasoning_summary_delta", handler: ExtensionHandler<ReasoningSummaryDeltaEvent>): void;
|
|
1034
|
+
on(event: "reasoning_summary_end", handler: ExtensionHandler<ReasoningSummaryEndEvent>): void;
|
|
1002
1035
|
on(event: "message_end", handler: ExtensionHandler<MessageEndEvent>): void;
|
|
1003
1036
|
on(event: "tool_execution_start", handler: ExtensionHandler<ToolExecutionStartEvent>): void;
|
|
1004
1037
|
on(event: "tool_execution_update", handler: ExtensionHandler<ToolExecutionUpdateEvent>): void;
|
|
@@ -1103,6 +1136,8 @@ export interface ExtensionAPI {
|
|
|
1103
1136
|
|
|
1104
1137
|
/** Get all configured tools (built-in + extension tools). */
|
|
1105
1138
|
getAllTools(): string[];
|
|
1139
|
+
/** Resolve display-safe metadata for a configured tool without exposing its implementation. */
|
|
1140
|
+
resolveTool(name: string): Pick<Tool, "safeSummary" | "safeSummaryFields"> | undefined;
|
|
1106
1141
|
|
|
1107
1142
|
/** Set the active tools by name. */
|
|
1108
1143
|
setActiveTools(toolNames: string[]): Promise<void>;
|
|
@@ -1304,6 +1339,7 @@ export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) =>
|
|
|
1304
1339
|
export type GetActiveToolsHandler = () => string[];
|
|
1305
1340
|
|
|
1306
1341
|
export type GetAllToolsHandler = () => string[];
|
|
1342
|
+
export type ResolveToolHandler = (name: string) => Pick<Tool, "safeSummary" | "safeSummaryFields"> | undefined;
|
|
1307
1343
|
|
|
1308
1344
|
export type GetCommandsHandler = () => SlashCommandInfo[];
|
|
1309
1345
|
|
|
@@ -1349,6 +1385,7 @@ export interface ExtensionActions {
|
|
|
1349
1385
|
setLabel: (targetId: string, label: string | undefined) => void;
|
|
1350
1386
|
getActiveTools: GetActiveToolsHandler;
|
|
1351
1387
|
getAllTools: GetAllToolsHandler;
|
|
1388
|
+
resolveTool: ResolveToolHandler;
|
|
1352
1389
|
setActiveTools: SetActiveToolsHandler;
|
|
1353
1390
|
getCommands: GetCommandsHandler;
|
|
1354
1391
|
setModel: SetModelHandler;
|
|
@@ -1381,6 +1418,7 @@ export interface ExtensionContextActions {
|
|
|
1381
1418
|
getQueuedMessages?: () => unknown[];
|
|
1382
1419
|
getActiveTools?: () => string[];
|
|
1383
1420
|
getAllTools?: () => string[];
|
|
1421
|
+
resolveTool?: (name: string) => Pick<Tool, "safeSummary" | "safeSummaryFields"> | undefined;
|
|
1384
1422
|
shutdown: () => void;
|
|
1385
1423
|
getContextUsage: () => ContextUsage | undefined;
|
|
1386
1424
|
compact: (instructionsOrOptions?: string | CompactOptions) => Promise<void>;
|
|
@@ -211,23 +211,23 @@ async function resolveTarball(source: string): Promise<ResolvedSource> {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
function runGit(args: string[], cwd?: string): Promise<string> {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
});
|
|
214
|
+
const { promise, resolve, reject } = Promise.withResolvers<string>();
|
|
215
|
+
// argv array (no shell) — repo/ref are passed as discrete args, not interpolated.
|
|
216
|
+
const child = spawn("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
217
|
+
let stdout = "";
|
|
218
|
+
let stderr = "";
|
|
219
|
+
child.stdout.on("data", d => {
|
|
220
|
+
stdout += d;
|
|
221
|
+
});
|
|
222
|
+
child.stderr.on("data", d => {
|
|
223
|
+
stderr += d;
|
|
224
|
+
});
|
|
225
|
+
child.on("error", reject);
|
|
226
|
+
child.on("close", code => {
|
|
227
|
+
if (code === 0) resolve(stdout.trim());
|
|
228
|
+
else reject(new GjcPluginLoadError("install_conflict", `git ${args[0]} failed: ${stderr.trim()}`));
|
|
230
229
|
});
|
|
230
|
+
return promise;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
async function resolveGit(source: string): Promise<ResolvedSource> {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { AgentMessage } from "@gajae-code/agent-core";
|
|
5
5
|
import type { Model } from "@gajae-code/ai";
|
|
6
6
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
7
|
-
import type
|
|
7
|
+
import { createReadonlySessionManager, type SessionManager } from "../../session/session-manager";
|
|
8
8
|
import { createNoOpUIContext } from "../utils";
|
|
9
9
|
import type {
|
|
10
10
|
AppendEntryHandler,
|
|
@@ -226,7 +226,7 @@ export class HookRunner {
|
|
|
226
226
|
ui: this.#uiContext,
|
|
227
227
|
hasUI: this.#hasUI,
|
|
228
228
|
cwd: this.cwd,
|
|
229
|
-
sessionManager: this.sessionManager,
|
|
229
|
+
sessionManager: createReadonlySessionManager(this.sessionManager),
|
|
230
230
|
modelRegistry: this.modelRegistry,
|
|
231
231
|
model: this.#getModel(),
|
|
232
232
|
isIdle: () => this.#isIdleFn(),
|
|
@@ -4,7 +4,8 @@ import * as path from "node:path";
|
|
|
4
4
|
import { findRepoRoot } from "../capability/fs";
|
|
5
5
|
import type { Skill as CapabilitySkill } from "../capability/skill";
|
|
6
6
|
import type { SkillsSettings } from "../config/settings-schema";
|
|
7
|
-
import { compareSkillOrder, scanSkillsFromDir } from "../discovery/helpers";
|
|
7
|
+
import { compareSkillOrder, SOURCE_PATHS, scanSkillsFromDir } from "../discovery/helpers";
|
|
8
|
+
import { CANONICAL_GJC_WORKFLOW_SKILLS } from "../skill-state/canonical-skills";
|
|
8
9
|
import type { Skill } from "./skills";
|
|
9
10
|
|
|
10
11
|
export type RuntimeSkillDiscoverySource = "project" | "user";
|
|
@@ -32,6 +33,7 @@ function getRuntimeHome(): string {
|
|
|
32
33
|
|
|
33
34
|
const DEFAULT_LIMIT = 20;
|
|
34
35
|
const MAX_LIMIT = 50;
|
|
36
|
+
const BUILT_IN_SKILL_NAMES = new Set<string>(CANONICAL_GJC_WORKFLOW_SKILLS);
|
|
35
37
|
|
|
36
38
|
function normalizeLimit(limit: number | undefined): number {
|
|
37
39
|
if (limit === undefined || !Number.isFinite(limit)) return DEFAULT_LIMIT;
|
|
@@ -56,6 +58,18 @@ async function getProjectSkillDirs(cwd: string, home: string): Promise<{ dirs: s
|
|
|
56
58
|
return { dirs, repoRoot };
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
function getUserSkillDirs(home: string): string[] {
|
|
62
|
+
const canonicalUserDir = SOURCE_PATHS.native.userAgent;
|
|
63
|
+
const configuredLegacyDir = SOURCE_PATHS.native.userBase;
|
|
64
|
+
return [
|
|
65
|
+
...new Set([
|
|
66
|
+
path.join(home, canonicalUserDir, "skills"),
|
|
67
|
+
path.join(home, configuredLegacyDir, "skills"),
|
|
68
|
+
path.join(home, ".gjc", "skills"),
|
|
69
|
+
]),
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
function getUseWhen(skill: CapabilitySkill): string[] | undefined {
|
|
60
74
|
const frontmatter = skill.frontmatter as Record<string, unknown> | undefined;
|
|
61
75
|
const values: string[] = [];
|
|
@@ -110,6 +124,7 @@ function isAllowedByPolicy(
|
|
|
110
124
|
source: RuntimeSkillDiscoverySource,
|
|
111
125
|
policy: SkillsSettings | undefined,
|
|
112
126
|
): boolean {
|
|
127
|
+
if (BUILT_IN_SKILL_NAMES.has(skill.name)) return false;
|
|
113
128
|
if (!sourceEnabled(source, policy)) return false;
|
|
114
129
|
if (isDisabledSkill(skill.name, policy?.disabledExtensions)) return false;
|
|
115
130
|
if (matchesIgnorePatterns(skill.name, policy?.ignoredSkills)) return false;
|
|
@@ -158,12 +173,14 @@ export async function discoverRuntimeSkills(
|
|
|
158
173
|
}
|
|
159
174
|
}
|
|
160
175
|
if ((source === "all" || source === "user") && sourceEnabled("user", policy)) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
176
|
+
for (const dir of getUserSkillDirs(home)) {
|
|
177
|
+
scanJobs.push(
|
|
178
|
+
scanSkillsFromDir(
|
|
179
|
+
{ cwd: options.cwd, home, repoRoot: home },
|
|
180
|
+
{ dir, providerId: "runtime", level: "user", requireDescription: true },
|
|
181
|
+
).then(result => result.items.map(skill => ({ skill, source: "user" as const }))),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
167
184
|
}
|
|
168
185
|
|
|
169
186
|
const seenNames = new Set<string>();
|
|
@@ -175,6 +192,7 @@ export async function discoverRuntimeSkills(
|
|
|
175
192
|
if (seenPaths.has(realPath) || seenNames.has(entry.skill.name)) continue;
|
|
176
193
|
seenPaths.add(realPath);
|
|
177
194
|
seenNames.add(entry.skill.name);
|
|
195
|
+
|
|
178
196
|
const candidate: RuntimeSkillDiscoveryCandidate = {
|
|
179
197
|
name: entry.skill.name,
|
|
180
198
|
description:
|
|
@@ -213,12 +231,14 @@ export async function findRuntimeSkillByName(
|
|
|
213
231
|
);
|
|
214
232
|
}
|
|
215
233
|
if (sourceEnabled("user", policy)) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
234
|
+
for (const dir of getUserSkillDirs(home)) {
|
|
235
|
+
scanJobs.push(
|
|
236
|
+
scanSkillsFromDir(
|
|
237
|
+
{ cwd, home, repoRoot: home },
|
|
238
|
+
{ dir, providerId: "runtime", level: "user", requireDescription: true },
|
|
239
|
+
).then(result => result.items.map(skill => ({ skill, source: "user" as const }))),
|
|
240
|
+
);
|
|
241
|
+
}
|
|
222
242
|
}
|
|
223
243
|
for (const entry of (await Promise.all(scanJobs)).flat()) {
|
|
224
244
|
if (entry.skill.name === normalized && isAllowedByPolicy(entry.skill, entry.source, policy)) {
|