@gajae-code/coding-agent 0.18.11 → 0.19.0
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 +760 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/capability/rule.d.ts +7 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/append-system-prompt.d.ts +6 -0
- package/dist/types/cli/args.d.ts +7 -2
- package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
- package/dist/types/cli/customize-doctor.d.ts +4 -3
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +2 -0
- package/dist/types/cli/root-flags.d.ts +0 -12
- package/dist/types/cli/update-cli.d.ts +21 -3
- package/dist/types/cli-main.d.ts +0 -6
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/launch.d.ts +0 -6
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +13 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/commit/map-reduce/index.d.ts +4 -4
- package/dist/types/config/autorouting-tier-map.d.ts +53 -1
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +44 -0
- package/dist/types/config/file-lock.d.ts +52 -3
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +79 -9
- package/dist/types/config/model-registry.d.ts +72 -8
- package/dist/types/config/model-resolver.d.ts +7 -4
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +57 -4
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/customization/import.d.ts +2 -0
- package/dist/types/customization/types.d.ts +1 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/dap/session.d.ts +11 -2
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +7 -2
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/index.d.ts +5 -0
- package/dist/types/edit/modes/patch.d.ts +14 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/export/ttsr.d.ts +19 -0
- package/dist/types/extensibility/extensions/types.d.ts +5 -1
- package/dist/types/extensibility/slash-commands.d.ts +1 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/content.d.ts +5 -6
- package/dist/types/internal-urls/types.d.ts +2 -0
- package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
- package/dist/types/main.d.ts +23 -18
- package/dist/types/migrate/action-planner.d.ts +10 -1
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +42 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/hook-module.d.ts +23 -0
- package/dist/types/migrate/report.d.ts +2 -1
- package/dist/types/migrate/types.d.ts +82 -3
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +43 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/modes/utils/host-status.d.ts +15 -11
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +3 -3
- package/dist/types/sdk/broker/broker.d.ts +29 -2
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +141 -9
- package/dist/types/sdk/broker/hop.d.ts +45 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +6 -1
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +44 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
- package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/control/operations.d.ts +5 -1
- package/dist/types/sdk/host/events.d.ts +4 -0
- package/dist/types/sdk/host/host.d.ts +2 -1
- package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
- package/dist/types/sdk/host/session-runtime.d.ts +40 -8
- package/dist/types/sdk/host/surface-policy.d.ts +2 -1
- package/dist/types/sdk/lifecycle/service.d.ts +12 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/prompt-status.d.ts +11 -4
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +107 -9
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +29 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +20 -4
- package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/ssh/ssh-executor.d.ts +8 -1
- package/dist/types/system-prompt.d.ts +3 -2
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/task/role-body.d.ts +11 -0
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/awaiting-input.d.ts +28 -0
- package/dist/types/tools/bash-allowed-prefixes.d.ts +17 -0
- package/dist/types/tools/bash-skill-urls.d.ts +4 -0
- package/dist/types/tools/bash.d.ts +7 -0
- package/dist/types/tools/descriptors.d.ts +15 -2
- package/dist/types/tools/fetch.d.ts +7 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/irc.d.ts +5 -3
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/utils/file-mentions.d.ts +5 -0
- package/dist/types/utils/image-limits.d.ts +7 -0
- package/dist/types/utils/image-loading.d.ts +0 -1
- package/dist/types/utils/open.d.ts +0 -1
- package/dist/types/utils/pasted-image-loading.d.ts +1 -5
- package/dist/types/utils/prompt-suggestion.d.ts +2 -2
- package/dist/types/utils/shell-snapshot.d.ts +2 -0
- package/dist/types/utils/title-generator.d.ts +13 -3
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/codex.d.ts +6 -7
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +10 -9
- package/scripts/acp-conformance-agent.ts +12 -2
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +38 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +58 -22
- package/src/capability/index.ts +2 -2
- package/src/capability/rule.ts +11 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/append-system-prompt.ts +12 -0
- package/src/cli/args.ts +11 -7
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/customize-doctor-precedence.ts +31 -0
- package/src/cli/customize-doctor.ts +49 -39
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -3
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +19 -6
- package/src/cli/public-command-errors.ts +6 -0
- package/src/cli/root-flags.ts +2 -4
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +471 -13
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/harness.ts +25 -15
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +277 -50
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/agentic/agent.ts +6 -6
- package/src/commit/analysis/conventional.ts +14 -5
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/map-reduce/index.ts +7 -7
- package/src/commit/message.ts +10 -3
- package/src/commit/pipeline.ts +12 -12
- package/src/config/autorouting-tier-map.ts +50 -1
- package/src/config/config-file.ts +106 -3
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +742 -0
- package/src/config/file-lock.ts +1615 -328
- package/src/config/keybindings.ts +154 -7
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +889 -148
- package/src/config/model-registry.ts +1706 -205
- package/src/config/model-resolver.ts +52 -22
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +73 -4
- package/src/config/settings.ts +460 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/coordinator-mcp/server.ts +37 -2
- package/src/crash/sanitize.ts +7 -1
- package/src/customization/import.ts +279 -8
- package/src/customization/inventory.ts +24 -8
- package/src/customization/types.ts +1 -0
- package/src/dap/client.ts +3 -2
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/dap/session.ts +161 -36
- package/src/debug/crash-diagnostics.ts +89 -6
- package/src/debug/report-bundle.ts +90 -2
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/builtin.ts +4 -3
- package/src/discovery/helpers.ts +25 -16
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +204 -22
- package/src/edit/modes/patch.ts +214 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/eval/py/runtime.ts +44 -4
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/exec/non-interactive-env.ts +0 -1
- package/src/export/html/index.ts +86 -6
- package/src/export/ttsr.ts +176 -1
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +10 -1
- package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
- package/src/extensibility/extensions/types.ts +5 -1
- package/src/extensibility/hooks/loader.ts +10 -2
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/extensibility/plugins/marketplace/manager.ts +36 -10
- package/src/extensibility/slash-commands.ts +5 -0
- package/src/gjc-runtime/gc-runtime.ts +37 -7
- package/src/gjc-runtime/launch-tmux.ts +30 -15
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/ralplan-current-final.ts +294 -0
- package/src/gjc-runtime/ralplan-runtime.ts +95 -1
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/gjc-runtime/state-writer.ts +109 -5
- package/src/gjc-runtime/tmux-sessions.ts +93 -13
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
- package/src/gjc-runtime/ultragoal-guard.ts +9 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
- package/src/harness-control-plane/finalize.ts +11 -0
- package/src/harness-control-plane/receipt-spool.ts +105 -28
- package/src/harness-control-plane/storage.ts +124 -6
- package/src/hindsight/content.ts +116 -16
- package/src/hindsight/mental-models.ts +22 -10
- package/src/hindsight/state.ts +7 -4
- package/src/hooks/native-skill-hook.ts +17 -12
- package/src/internal-urls/artifact-protocol.ts +3 -1
- package/src/internal-urls/docs-index.generated.ts +23 -22
- package/src/internal-urls/local-protocol.ts +167 -8
- package/src/internal-urls/types.ts +2 -0
- package/src/lsp/client.ts +2 -1
- package/src/lsp/clients/biome-client.ts +2 -0
- package/src/lsp/clients/swiftlint-client.ts +2 -0
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/main.ts +330 -92
- package/src/memories/index.ts +25 -2
- package/src/migrate/action-planner.ts +574 -2
- package/src/migrate/adapters/claude-code.ts +162 -5
- package/src/migrate/adapters/codex.ts +77 -7
- package/src/migrate/adapters/index.ts +258 -5
- package/src/migrate/adapters/opencode.ts +10 -1
- package/src/migrate/executor.ts +222 -7
- package/src/migrate/hook-module.ts +193 -0
- package/src/migrate/report.ts +63 -2
- package/src/migrate/types.ts +84 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/acp-agent.ts +10 -1
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/agent-dashboard.ts +20 -4
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/customization/customization-dashboard.ts +7 -0
- package/src/modes/components/customization/import-wizard.ts +29 -3
- package/src/modes/components/model-selector.ts +157 -103
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/components/welcome.ts +3 -1
- package/src/modes/controllers/command-controller.ts +300 -9
- package/src/modes/controllers/event-controller.ts +1 -1
- package/src/modes/controllers/extension-ui-controller.ts +31 -1
- package/src/modes/controllers/goal-mode-controller.ts +79 -10
- package/src/modes/controllers/input-controller.ts +2 -0
- package/src/modes/controllers/plan-mode-controller.ts +66 -11
- package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
- package/src/modes/controllers/selector-controller.ts +76 -7
- package/src/modes/interactive-mode.ts +123 -4
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +5 -1
- package/src/modes/theme/theme.ts +15 -0
- package/src/modes/utils/host-status.ts +21 -10
- package/src/prompts/agent-fragments/browser-aside.md +2 -2
- package/src/prompts/system/irc-incoming.md +3 -1
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +40 -3
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/project-host-values.ts +12 -8
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +194 -21
- package/src/runtime-mcp/transports/stdio.ts +2 -1
- package/src/sdk/broker/broker-exit.ts +10 -5
- package/src/sdk/broker/broker.ts +484 -85
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1214 -268
- package/src/sdk/broker/hop.ts +286 -0
- package/src/sdk/broker/lifecycle-ledger.ts +38 -11
- package/src/sdk/broker/lifecycle.ts +102 -6
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +91 -16
- package/src/sdk/broker/transport.ts +17 -1
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +460 -35
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/session-control.ts +2 -0
- package/src/sdk/bus/slack-daemon.ts +105 -9
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -2
- package/src/sdk/bus/threaded-render.ts +20 -1
- package/src/sdk/cli/session-cli.ts +23 -6
- package/src/sdk/host/control/dispatch.ts +13 -1
- package/src/sdk/host/control/operations.ts +10 -1
- package/src/sdk/host/events.ts +67 -4
- package/src/sdk/host/host.ts +8 -2
- package/src/sdk/host/prompt-image-upload.ts +438 -0
- package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
- package/src/sdk/host/session-runtime.test.ts +1737 -129
- package/src/sdk/host/session-runtime.ts +684 -83
- package/src/sdk/host/surface-policy.ts +4 -0
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
- package/src/sdk/host/websocket-transport.ts +19 -7
- package/src/sdk/lifecycle/service.ts +15 -1
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/prompt-status.ts +6 -4
- package/src/sdk/protocol/adapter-validation.ts +81 -12
- package/src/sdk/protocol/operation-inventory.generated.json +261 -2
- package/src/sdk/protocol/operation-registry.ts +33 -3
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +237 -97
- package/src/session/agent-session.ts +2726 -479
- package/src/session/history-storage.ts +182 -12
- package/src/session/internal/managed-session-scope.ts +173 -57
- package/src/session/internal/managed-session-storage.ts +85 -12
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +326 -19
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/redact.ts +53 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +2145 -206
- package/src/slash-commands/builtin-registry.ts +21 -6
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/mcp.ts +11 -3
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/ssh/ssh-executor.ts +9 -2
- package/src/stt/recorder.ts +26 -9
- package/src/system-prompt.ts +61 -16
- package/src/task/executor.ts +115 -20
- package/src/task/index.ts +389 -175
- package/src/task/role-body.ts +84 -0
- package/src/task/token-log-mode.test.ts +162 -0
- package/src/task/token-log.ts +91 -2
- package/src/tools/archive-reader.ts +650 -37
- package/src/tools/ask.ts +1 -0
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/ast-grep.ts +7 -2
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +15 -3
- package/src/tools/awaiting-input.ts +114 -0
- package/src/tools/bash-allowed-prefixes.ts +214 -6
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash-skill-urls.ts +58 -5
- package/src/tools/bash.ts +113 -26
- package/src/tools/browser/tab-worker.ts +39 -13
- package/src/tools/browser.ts +17 -7
- package/src/tools/cron.ts +10 -1
- package/src/tools/debug.ts +16 -8
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +50 -6
- package/src/tools/eval.ts +15 -0
- package/src/tools/fetch.ts +93 -4
- package/src/tools/gh.ts +27 -12
- package/src/tools/image-gen.ts +20 -6
- package/src/tools/index.ts +2 -0
- package/src/tools/irc.ts +5 -3
- package/src/tools/monitor.ts +9 -1
- package/src/tools/output-meta.ts +74 -5
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +26 -37
- package/src/tools/recipe/runner.ts +23 -12
- package/src/tools/render-utils.ts +2 -2
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/search.ts +3 -2
- package/src/tools/ssh.ts +274 -8
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +118 -5
- package/src/tools/tmux-self-injection-guard.ts +3301 -122
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +32 -4
- package/src/tools/ultragoal-ask-guard.ts +13 -1
- package/src/tools/write.ts +42 -3
- package/src/tui/tree-list.ts +15 -1
- package/src/utils/commit-message-generator.ts +12 -4
- package/src/utils/external-editor.ts +21 -7
- package/src/utils/file-mentions.ts +75 -7
- package/src/utils/git.ts +38 -7
- package/src/utils/image-limits.ts +8 -0
- package/src/utils/image-loading.ts +1 -1
- package/src/utils/open.ts +73 -4
- package/src/utils/pasted-image-loading.ts +9 -8
- package/src/utils/prompt-suggestion.ts +5 -4
- package/src/utils/shell-snapshot.ts +9 -1
- package/src/utils/title-generator.ts +72 -22
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/index.ts +2 -1
- package/src/web/search/providers/codex.ts +29 -32
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
package/src/export/ttsr.ts
CHANGED
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
* Manages rules that get injected mid-stream when their condition pattern matches
|
|
5
5
|
* the agent's output. When a match occurs, the stream is aborted, the rule is
|
|
6
6
|
* injected as a system reminder, and the request is retried.
|
|
7
|
+
*
|
|
8
|
+
* Rules may also carry `astCondition` ast-grep patterns, which are evaluated
|
|
9
|
+
* against the source a write/edit tool call introduces, before it executes.
|
|
7
10
|
*/
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import { AstMatchStrictness, astMatch } from "@gajae-code/natives";
|
|
8
13
|
import { logger } from "@gajae-code/utils";
|
|
9
14
|
import type { Rule } from "../capability/rule";
|
|
10
15
|
import type { TtsrSettings } from "../config/settings";
|
|
@@ -22,6 +27,14 @@ export interface TtsrMatchContext {
|
|
|
22
27
|
streamKey?: string;
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
/** An astCondition pattern parse issue observed while checking a target language. */
|
|
31
|
+
export interface TtsrAstConditionDiagnostic {
|
|
32
|
+
ruleName: string;
|
|
33
|
+
lang: string;
|
|
34
|
+
patterns: string[];
|
|
35
|
+
parseErrors: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
interface ToolScope {
|
|
26
39
|
toolName?: string;
|
|
27
40
|
pathGlob?: Bun.Glob;
|
|
@@ -39,6 +52,7 @@ interface TtsrEntry {
|
|
|
39
52
|
rule: Rule;
|
|
40
53
|
conditions: RegExp[];
|
|
41
54
|
conditionWindows: Array<number | undefined>;
|
|
55
|
+
astConditions?: string[];
|
|
42
56
|
|
|
43
57
|
scope: TtsrScope;
|
|
44
58
|
globalPathGlobs?: Bun.Glob[];
|
|
@@ -69,6 +83,7 @@ const DEFAULT_SETTINGS: Required<TtsrSettings> = {
|
|
|
69
83
|
|
|
70
84
|
const SAFE_REGEX_WINDOW_CAP = 4096;
|
|
71
85
|
const SAFE_REGEX_WINDOW_MULTIPLIER = 4;
|
|
86
|
+
const SOURCE_SYNTAX_PARSE_ERROR = "parse error (syntax tree contains error nodes)";
|
|
72
87
|
|
|
73
88
|
const DEFAULT_SCOPE: TtsrScope = {
|
|
74
89
|
allowText: true,
|
|
@@ -81,7 +96,9 @@ export class TtsrManager {
|
|
|
81
96
|
readonly #settings: Required<TtsrSettings>;
|
|
82
97
|
readonly #rules = new Map<string, TtsrEntry>();
|
|
83
98
|
readonly #injectionRecords = new Map<string, InjectionRecord>();
|
|
99
|
+
readonly #astConditionDiagnostics = new Map<string, TtsrAstConditionDiagnostic>();
|
|
84
100
|
readonly #buffers = new Map<string, string>();
|
|
101
|
+
readonly #lastAstSnapshots = new Map<string, string>();
|
|
85
102
|
#messageCount = 0;
|
|
86
103
|
|
|
87
104
|
constructor(settings?: Partial<TtsrSettings>) {
|
|
@@ -339,7 +356,10 @@ export class TtsrManager {
|
|
|
339
356
|
}
|
|
340
357
|
|
|
341
358
|
const conditions = this.#compileConditions(rule);
|
|
342
|
-
|
|
359
|
+
const astConditions = rule.astCondition ?? [];
|
|
360
|
+
|
|
361
|
+
// Rule must have either regex or AST conditions
|
|
362
|
+
if (conditions.length === 0 && astConditions.length === 0) {
|
|
343
363
|
return false;
|
|
344
364
|
}
|
|
345
365
|
|
|
@@ -357,6 +377,7 @@ export class TtsrManager {
|
|
|
357
377
|
rule,
|
|
358
378
|
conditions,
|
|
359
379
|
conditionWindows,
|
|
380
|
+
astConditions: astConditions.length > 0 ? astConditions : undefined,
|
|
360
381
|
scope,
|
|
361
382
|
globalPathGlobs,
|
|
362
383
|
});
|
|
@@ -364,6 +385,7 @@ export class TtsrManager {
|
|
|
364
385
|
logger.debug("TTSR rule registered", {
|
|
365
386
|
ruleName: rule.name,
|
|
366
387
|
conditions: rule.condition,
|
|
388
|
+
astConditions: rule.astCondition,
|
|
367
389
|
scope: rule.scope,
|
|
368
390
|
globs: rule.globs,
|
|
369
391
|
});
|
|
@@ -446,6 +468,25 @@ export class TtsrManager {
|
|
|
446
468
|
return Array.from(this.#injectionRecords.keys());
|
|
447
469
|
}
|
|
448
470
|
|
|
471
|
+
/**
|
|
472
|
+
* Undo a provisional claim whose reminder was never delivered: restore the
|
|
473
|
+
* record the rule had before the claim, or forget it when it had none, so the
|
|
474
|
+
* rule is eligible again exactly as before.
|
|
475
|
+
*/
|
|
476
|
+
releaseInjected(ruleName: string, previous: TtsrInjectionRecord | undefined): void {
|
|
477
|
+
const name = ruleName.trim();
|
|
478
|
+
if (name.length === 0) return;
|
|
479
|
+
if (!previous) {
|
|
480
|
+
this.#injectionRecords.delete(name);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
this.#injectionRecords.set(name, {
|
|
484
|
+
lastInjectedAt: previous.lastInjectedAt,
|
|
485
|
+
repeatMode: previous.repeatMode,
|
|
486
|
+
repeatGap: previous.repeatGap,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
449
490
|
/** Get full injected rule records (for persistence). */
|
|
450
491
|
getInjectedRecords(): TtsrInjectionRecord[] {
|
|
451
492
|
return Array.from(this.#injectionRecords, ([name, record]) => ({ name, ...record }));
|
|
@@ -477,6 +518,7 @@ export class TtsrManager {
|
|
|
477
518
|
/** Reset stream buffers (called on new turn). */
|
|
478
519
|
resetBuffer(): void {
|
|
479
520
|
this.#buffers.clear();
|
|
521
|
+
this.#lastAstSnapshots.clear();
|
|
480
522
|
}
|
|
481
523
|
|
|
482
524
|
/** Check if any TTSR rules are registered. */
|
|
@@ -509,4 +551,137 @@ export class TtsrManager {
|
|
|
509
551
|
getSettings(): Required<TtsrSettings> {
|
|
510
552
|
return this.#settings;
|
|
511
553
|
}
|
|
554
|
+
|
|
555
|
+
/** Check if any registered rule carries an `astCondition`. */
|
|
556
|
+
hasAstRules(): boolean {
|
|
557
|
+
if (this.#isDisabled()) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
for (const entry of this.#rules.values()) {
|
|
561
|
+
if (entry.astConditions) {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/** Get observed astCondition pattern parse issues for rule diagnostics. */
|
|
569
|
+
getAstConditionDiagnostics(): TtsrAstConditionDiagnostic[] {
|
|
570
|
+
return Array.from(this.#astConditionDiagnostics.values(), diagnostic => ({
|
|
571
|
+
...diagnostic,
|
|
572
|
+
patterns: [...diagnostic.patterns],
|
|
573
|
+
parseErrors: [...diagnostic.parseErrors],
|
|
574
|
+
}));
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/** Derive an ast-grep language alias from the candidate file extensions. */
|
|
578
|
+
#deriveLang(filePaths: string[] | undefined): string | undefined {
|
|
579
|
+
for (const filePath of filePaths ?? []) {
|
|
580
|
+
const ext = path.extname(this.#normalizePath(filePath));
|
|
581
|
+
if (ext.length > 1) return ext.slice(1).toLowerCase();
|
|
582
|
+
}
|
|
583
|
+
return undefined;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/** Match the source introduced by finalized tool arguments, before execution. */
|
|
587
|
+
async checkAstSnapshot(snapshot: string, context: TtsrMatchContext, signal?: AbortSignal): Promise<Rule[]> {
|
|
588
|
+
if (this.#isDisabled() || context.source !== "tool" || signal?.aborted) {
|
|
589
|
+
return [];
|
|
590
|
+
}
|
|
591
|
+
const lang = this.#deriveLang(context.filePaths);
|
|
592
|
+
if (!lang) return [];
|
|
593
|
+
|
|
594
|
+
const candidates: TtsrEntry[] = [];
|
|
595
|
+
for (const [name, entry] of this.#rules) {
|
|
596
|
+
if (!entry.astConditions?.length) continue;
|
|
597
|
+
if (
|
|
598
|
+
!this.#canTrigger(name) ||
|
|
599
|
+
!this.#matchesScope(entry, context) ||
|
|
600
|
+
!this.#matchesGlobalPaths(entry, context)
|
|
601
|
+
) {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
candidates.push(entry);
|
|
605
|
+
}
|
|
606
|
+
if (candidates.length === 0) return [];
|
|
607
|
+
|
|
608
|
+
const bufferKey = this.#bufferKey(context);
|
|
609
|
+
if (this.#lastAstSnapshots.get(bufferKey) === snapshot) return [];
|
|
610
|
+
this.#lastAstSnapshots.set(bufferKey, snapshot);
|
|
611
|
+
|
|
612
|
+
const matches: Rule[] = [];
|
|
613
|
+
for (const entry of candidates) {
|
|
614
|
+
if (!entry.astConditions) continue;
|
|
615
|
+
const matched = await this.#astConditionsMatch(entry.rule.name, entry.astConditions, snapshot, lang, signal);
|
|
616
|
+
if (signal?.aborted) return [];
|
|
617
|
+
if (matched) {
|
|
618
|
+
matches.push(entry.rule);
|
|
619
|
+
logger.debug("TTSR ast condition matched", {
|
|
620
|
+
ruleName: entry.rule.name,
|
|
621
|
+
astConditions: entry.rule.astCondition,
|
|
622
|
+
toolName: context.toolName,
|
|
623
|
+
filePaths: context.filePaths,
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return matches;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
#recordAstConditionDiagnostics(
|
|
631
|
+
ruleName: string,
|
|
632
|
+
patterns: string[],
|
|
633
|
+
lang: string,
|
|
634
|
+
parseErrors: string[] | undefined,
|
|
635
|
+
): void {
|
|
636
|
+
const patternParseErrors = parseErrors?.filter(parseError => parseError !== SOURCE_SYNTAX_PARSE_ERROR) ?? [];
|
|
637
|
+
if (patternParseErrors.length === 0) return;
|
|
638
|
+
|
|
639
|
+
const key = JSON.stringify([ruleName, lang]);
|
|
640
|
+
if (this.#astConditionDiagnostics.has(key)) return;
|
|
641
|
+
|
|
642
|
+
const diagnostic: TtsrAstConditionDiagnostic = {
|
|
643
|
+
ruleName,
|
|
644
|
+
lang,
|
|
645
|
+
patterns: [...patterns],
|
|
646
|
+
parseErrors: patternParseErrors,
|
|
647
|
+
};
|
|
648
|
+
this.#astConditionDiagnostics.set(key, diagnostic);
|
|
649
|
+
logger.warn("TTSR astCondition pattern is invalid for target language", {
|
|
650
|
+
ruleName,
|
|
651
|
+
lang,
|
|
652
|
+
patterns: diagnostic.patterns,
|
|
653
|
+
parseErrors: diagnostic.parseErrors,
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
async #astConditionsMatch(
|
|
658
|
+
ruleName: string,
|
|
659
|
+
patterns: string[],
|
|
660
|
+
source: string,
|
|
661
|
+
lang: string,
|
|
662
|
+
signal?: AbortSignal,
|
|
663
|
+
): Promise<boolean> {
|
|
664
|
+
try {
|
|
665
|
+
const result = await astMatch({
|
|
666
|
+
patterns,
|
|
667
|
+
source,
|
|
668
|
+
lang,
|
|
669
|
+
strictness: AstMatchStrictness.Smart,
|
|
670
|
+
limit: 1,
|
|
671
|
+
signal,
|
|
672
|
+
});
|
|
673
|
+
if (!signal?.aborted) {
|
|
674
|
+
this.#recordAstConditionDiagnostics(ruleName, patterns, lang, result.parseErrors);
|
|
675
|
+
}
|
|
676
|
+
return result.totalMatches > 0;
|
|
677
|
+
} catch (error) {
|
|
678
|
+
logger.warn("TTSR ast match failed, treating as no match", {
|
|
679
|
+
ruleName,
|
|
680
|
+
patterns,
|
|
681
|
+
lang,
|
|
682
|
+
error: error instanceof Error ? error.message : String(error),
|
|
683
|
+
});
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
512
687
|
}
|
|
@@ -21,9 +21,11 @@ export class CustomToolAdapter<TParams extends TSchema = TSchema, TDetails = any
|
|
|
21
21
|
private tool: CustomTool<TParams, TDetails>,
|
|
22
22
|
private getContext: () => CustomToolContext,
|
|
23
23
|
) {
|
|
24
|
-
|
|
24
|
+
// Own these before proxying: with useDefineForClassFields off, the uninitialized fields do not
|
|
25
|
+
// exist yet, so applyToolProxy would install getter-only accessors that reject assignment.
|
|
25
26
|
this.strict = tool.strict;
|
|
26
27
|
this.concurrency = tool.concurrency;
|
|
28
|
+
applyToolProxy(tool, this);
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
execute(
|
|
@@ -15,6 +15,7 @@ import { loadCapability } from "../../discovery";
|
|
|
15
15
|
import { getExtensionNameFromPath } from "../../discovery/helpers";
|
|
16
16
|
import type { ExecOptions } from "../../exec/exec";
|
|
17
17
|
import { execCommand } from "../../exec/exec";
|
|
18
|
+
import type { QueuedRunStartFailure } from "../../session/agent-session";
|
|
18
19
|
import type { CustomMessage } from "../../session/messages";
|
|
19
20
|
import { EventBus } from "../../utils/event-bus";
|
|
20
21
|
import { installLegacyPiSpecifierShim, loadLegacyPiModule } from "../plugins/legacy-pi-compat";
|
|
@@ -394,6 +395,7 @@ class ConcreteExtensionAPI implements ExtensionAPI {
|
|
|
394
395
|
onPreflightAccepted?: () => void;
|
|
395
396
|
onPreflightAcceptCommit?: () => void | Promise<void>;
|
|
396
397
|
onQueuedPromoted?: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
398
|
+
onQueuedRunStartFailed?: (failure: QueuedRunStartFailure) => void;
|
|
397
399
|
onDispatchDisposition?: (promotion: { startsOwnRun: boolean }) => void;
|
|
398
400
|
preflightSignal?: AbortSignal;
|
|
399
401
|
},
|
|
@@ -791,7 +793,14 @@ export async function discoverAndLoadExtensions(
|
|
|
791
793
|
...(options.profileAuthority === undefined ? {} : { profileAuthority: options.profileAuthority }),
|
|
792
794
|
...(options.settings === undefined ? {} : { settings: options.settings }),
|
|
793
795
|
});
|
|
794
|
-
|
|
796
|
+
// Filter project modules before first-wins name deduplication. `items` has
|
|
797
|
+
// already deduplicated, so a project module could otherwise shadow the
|
|
798
|
+
// same-named user module before being rejected here.
|
|
799
|
+
const seenDiscoveredNames = new Set<string>();
|
|
800
|
+
for (const ext of discovered.all) {
|
|
801
|
+
if (ext._source.provider === "native" && ext.level === "project") continue;
|
|
802
|
+
if (seenDiscoveredNames.has(ext.name)) continue;
|
|
803
|
+
seenDiscoveredNames.add(ext.name);
|
|
795
804
|
if (ext._source.provider !== "native") continue;
|
|
796
805
|
addPath(ext.path);
|
|
797
806
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { ptree } from "@gajae-code/utils";
|
|
2
|
+
import { $credentialEnv, startupProjectEnvSnapshot } from "@gajae-code/utils/env";
|
|
3
|
+
import { canonicalEnvKey } from "@gajae-code/utils/env-file";
|
|
4
|
+
import type { ExecResult } from "../../exec/exec";
|
|
1
5
|
import type { MCPServerConnection, MCPToolCallResult } from "../../runtime-mcp";
|
|
2
6
|
import { callTool, connectToServer, disconnectServer } from "../../runtime-mcp";
|
|
3
7
|
import { createExactPrefixCommandBridge } from "./prefix-command-bridge";
|
|
4
8
|
import type { ExtensionContext, InputEvent, InputEventResult } from "./types";
|
|
5
9
|
|
|
6
10
|
const OUROBOROS_CLI_ENV = "OUROBOROS_CLI";
|
|
11
|
+
const DEFAULT_OUROBOROS_COMMAND = "ouroboros";
|
|
7
12
|
const INTERVIEW_COMMAND = "ooo interview";
|
|
8
13
|
const INTERVIEW_TOOL = "ouroboros_interview";
|
|
9
14
|
const INTERVIEW_SESSION_PATTERN = /^interview_[A-Za-z0-9_-]+$/;
|
|
@@ -23,8 +28,64 @@ interface OuroborosOooBridgeHandler {
|
|
|
23
28
|
reset(): Promise<void>;
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
function projectSuppliedOuroborosCli(): boolean {
|
|
32
|
+
const snapshot = startupProjectEnvSnapshot();
|
|
33
|
+
const key = canonicalEnvKey(OUROBOROS_CLI_ENV);
|
|
34
|
+
return Object.hasOwn(snapshot.values, key) || snapshot.dynamic.has(key);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Executable for `ooo` dispatch and the interview MCP server.
|
|
39
|
+
*
|
|
40
|
+
* The string is spawned directly, so a repository `.env` must not choose it.
|
|
41
|
+
* `$credentialEnv` keeps a launching-shell or user-owned setting and ignores
|
|
42
|
+
* the project dotenv, including a dynamic declaration. Anything else stays the
|
|
43
|
+
* default command name. A rejected project value is removed from `process.env`
|
|
44
|
+
* before either spawn. Prefix dispatch also passes that cleaned object: Bun
|
|
45
|
+
* keeps the startup environment for a spawn that omits `env`, so deleting the
|
|
46
|
+
* key alone would still hand the project value to the child.
|
|
47
|
+
*/
|
|
26
48
|
function resolveOuroborosCommand(): string {
|
|
27
|
-
|
|
49
|
+
const trusted = $credentialEnv(OUROBOROS_CLI_ENV)?.trim();
|
|
50
|
+
if (trusted) {
|
|
51
|
+
const live = process.env[OUROBOROS_CLI_ENV];
|
|
52
|
+
if (live !== undefined && live.trim() !== trusted) process.env[OUROBOROS_CLI_ENV] = trusted;
|
|
53
|
+
return trusted;
|
|
54
|
+
}
|
|
55
|
+
if (projectSuppliedOuroborosCli()) delete process.env[OUROBOROS_CLI_ENV];
|
|
56
|
+
return DEFAULT_OUROBOROS_COMMAND;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function ouroborosSpawnEnv(): Record<string, string> {
|
|
60
|
+
resolveOuroborosCommand();
|
|
61
|
+
const env: Record<string, string> = {};
|
|
62
|
+
for (const key of Object.keys(process.env)) {
|
|
63
|
+
const value = process.env[key];
|
|
64
|
+
if (typeof value === "string") env[key] = value;
|
|
65
|
+
}
|
|
66
|
+
return env;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function dispatchOuroborosCommand(
|
|
70
|
+
command: string,
|
|
71
|
+
args: string[],
|
|
72
|
+
ctx: ExtensionContext,
|
|
73
|
+
execOptions: { timeout?: number },
|
|
74
|
+
): Promise<ExecResult> {
|
|
75
|
+
const result = await ptree.exec([command, ...args], {
|
|
76
|
+
cwd: ctx.cwd,
|
|
77
|
+
timeout: execOptions.timeout,
|
|
78
|
+
allowNonZero: true,
|
|
79
|
+
allowAbort: true,
|
|
80
|
+
stderr: "full",
|
|
81
|
+
env: ouroborosSpawnEnv(),
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
stdout: result.stdout,
|
|
85
|
+
stderr: result.stderr,
|
|
86
|
+
code: result.exitCode ?? 0,
|
|
87
|
+
killed: Boolean(result.exitError?.aborted),
|
|
88
|
+
};
|
|
28
89
|
}
|
|
29
90
|
|
|
30
91
|
function interviewArgument(text: string): string | undefined {
|
|
@@ -89,6 +150,7 @@ export function createOuroborosOooBridge(options: OuroborosOooBridgeOptions = {}
|
|
|
89
150
|
prefix: "ooo",
|
|
90
151
|
command: resolveOuroborosCommand(),
|
|
91
152
|
args: ["dispatch", "--runtime", "gjc"],
|
|
153
|
+
dispatch: dispatchOuroborosCommand,
|
|
92
154
|
});
|
|
93
155
|
|
|
94
156
|
function assertCurrent(generation: number, signal: AbortSignal | undefined): void {
|
|
@@ -50,7 +50,7 @@ import type { CustomEditor } from "../../modes/components/custom-editor";
|
|
|
50
50
|
import type { WorkflowGateEmitter } from "../../modes/shared/agent-wire/workflow-gate-broker";
|
|
51
51
|
import type { Theme } from "../../modes/theme/theme";
|
|
52
52
|
import type { ProjectProgressSnapshot } from "../../progress/progress-contract";
|
|
53
|
-
import type { AgentSessionEventListener } from "../../session/agent-session";
|
|
53
|
+
import type { AgentSessionEventListener, QueuedRunStartFailure } from "../../session/agent-session";
|
|
54
54
|
import type {
|
|
55
55
|
ClientBridge,
|
|
56
56
|
ClientBridgePermissionOption,
|
|
@@ -1347,6 +1347,8 @@ export interface ExtensionAPI {
|
|
|
1347
1347
|
onPreflightAccepted?: () => void;
|
|
1348
1348
|
onPreflightAcceptCommit?: () => void | Promise<void>;
|
|
1349
1349
|
onQueuedPromoted?: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
1350
|
+
/** Internal positive refusal before an exact queued invocation can start. */
|
|
1351
|
+
onQueuedRunStartFailed?: (failure: QueuedRunStartFailure) => void;
|
|
1350
1352
|
onDispatchDisposition?: (promotion: { startsOwnRun: boolean }) => void;
|
|
1351
1353
|
preflightSignal?: AbortSignal;
|
|
1352
1354
|
/** Internal SDK correlation owner for an exact queued follow-up. */
|
|
@@ -1577,6 +1579,8 @@ export type SendUserMessageHandler = (
|
|
|
1577
1579
|
* grants root abort ownership.
|
|
1578
1580
|
*/
|
|
1579
1581
|
onQueuedPromoted?: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
1582
|
+
/** Internal positive refusal, not an inference from a dispatch error or missing event. */
|
|
1583
|
+
onQueuedRunStartFailed?: (failure: QueuedRunStartFailure) => void;
|
|
1580
1584
|
/**
|
|
1581
1585
|
* Fired synchronously when a plain prompt's dispatch resolves at queue
|
|
1582
1586
|
* time instead of run end (diverted into an in-flight run's steering).
|
|
@@ -346,9 +346,17 @@ export async function discoverAndLoadHooks(configuredPaths: string[], cwd: strin
|
|
|
346
346
|
};
|
|
347
347
|
|
|
348
348
|
// 1. Discover hooks via capability API and validate the provider descriptor
|
|
349
|
-
// against the canonical model before importing
|
|
349
|
+
// against the canonical model before importing. A repository
|
|
350
|
+
// `<cwd>/.gjc/hooks` module is not imported. Skip those entries before
|
|
351
|
+
// dedup so a same-named user-agent hook still loads. An explicit path
|
|
352
|
+
// below remains a consent path.
|
|
350
353
|
const discovered = await loadCapability<Hook>(hookCapability.id, { cwd, providers: ["native"] });
|
|
351
|
-
|
|
354
|
+
const seenHookKeys = new Set<string>();
|
|
355
|
+
for (const hook of discovered.all) {
|
|
356
|
+
if (hook.level === "project") continue;
|
|
357
|
+
const hookKey = `${hook.type}:${hook.tool}:${hook.name}`;
|
|
358
|
+
if (seenHookKeys.has(hookKey)) continue;
|
|
359
|
+
seenHookKeys.add(hookKey);
|
|
352
360
|
const convention =
|
|
353
361
|
hook._source.provider === "native"
|
|
354
362
|
? HookSourceConvention.NativeGjc
|
|
@@ -10,7 +10,7 @@ import * as https from "node:https";
|
|
|
10
10
|
import * as net from "node:net";
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import * as path from "node:path";
|
|
13
|
-
import { isEnoent, logger } from "@gajae-code/utils";
|
|
13
|
+
import { isEnoent, logger, redactCrashSecrets } from "@gajae-code/utils";
|
|
14
14
|
import * as git from "../../../utils/git";
|
|
15
15
|
import { isPrivateOrSpecialAddress, validatePublicHttpUrl } from "../../../web/insane/url-guard";
|
|
16
16
|
|
|
@@ -461,7 +461,7 @@ async function cloneAndReadCatalog(url: string, cacheDir: string): Promise<Fetch
|
|
|
461
461
|
const tmpDir = path.join(cacheDir, `.tmp-clone-${Date.now()}`);
|
|
462
462
|
await fs.mkdir(cacheDir, { recursive: true });
|
|
463
463
|
|
|
464
|
-
logger.debug(`[marketplace] cloning ${url} → ${tmpDir}`);
|
|
464
|
+
logger.debug(redactCrashSecrets(`[marketplace] cloning ${url} → ${tmpDir}`));
|
|
465
465
|
await git.clone(url, tmpDir);
|
|
466
466
|
|
|
467
467
|
const catalogPath = path.join(tmpDir, CATALOG_RELATIVE_PATH);
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type NativeDirectoryTreeSnapshot,
|
|
16
16
|
type NativeExactUnlinkResult,
|
|
17
17
|
renameDirectoryNoReplacePathAsync,
|
|
18
|
+
renameNoReplacePathAsync,
|
|
18
19
|
snapshotDirectoryTree,
|
|
19
20
|
} from "@gajae-code/natives";
|
|
20
21
|
import { isEnoent, logger, pathIsWithin } from "@gajae-code/utils";
|
|
@@ -175,6 +176,13 @@ async function snapshotIfPresent(targetPath: string): Promise<NativeDirectoryTre
|
|
|
175
176
|
return snapshot.ok ? snapshot.snapshot : undefined;
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
/** Windows supports directory no-replace through the handle-based path API, not the POSIX directory fallback. */
|
|
180
|
+
function renameDirectoryNoReplace(sourcePath: string, destinationPath: string) {
|
|
181
|
+
return process.platform === "win32"
|
|
182
|
+
? renameNoReplacePathAsync(sourcePath, destinationPath)
|
|
183
|
+
: renameDirectoryNoReplacePathAsync(sourcePath, destinationPath);
|
|
184
|
+
}
|
|
185
|
+
|
|
178
186
|
/**
|
|
179
187
|
* Full identity comparison between two directory tree snapshots. A same-
|
|
180
188
|
* filesystem `renameat`-class namespace operation changes neither the root's
|
|
@@ -850,9 +858,10 @@ export class MarketplaceManager {
|
|
|
850
858
|
});
|
|
851
859
|
if (finalStat?.isSymbolicLink()) throw new MarketplaceRestoreError("final_path_is_symlink");
|
|
852
860
|
const hadFinal = finalStat !== undefined;
|
|
853
|
-
//
|
|
854
|
-
//
|
|
855
|
-
const
|
|
861
|
+
// Keep the private backup component bounded independently of the canonical
|
|
862
|
+
// cache basename, which can itself be near NAME_MAX through a long version.
|
|
863
|
+
const backupName = `.gjc-restore-backup-${createHash("sha256").update(finalPath).digest("hex")}-${randomBytes(12).toString("hex")}`;
|
|
864
|
+
const backup = path.join(pluginsCacheDir, backupName);
|
|
856
865
|
|
|
857
866
|
const parentRecheck = await fs.lstat(pluginsCacheDir, { bigint: true }).catch(() => undefined);
|
|
858
867
|
if (!parentRecheck || parentRecheck.dev !== parentBefore.dev || parentRecheck.ino !== parentBefore.ino)
|
|
@@ -878,12 +887,29 @@ export class MarketplaceManager {
|
|
|
878
887
|
// merely a decision about whether it is safe to proceed. sideEffectStarted
|
|
879
888
|
// stays false — effects are physical, not procedural.
|
|
880
889
|
if (!finalSnapshotBefore) throw new MarketplaceRestoreError("final_path_snapshot_unavailable");
|
|
881
|
-
const detached = exactRemoveDirectoryTree(
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
890
|
+
const detached = exactRemoveDirectoryTree(
|
|
891
|
+
finalPath,
|
|
892
|
+
finalSnapshotBefore,
|
|
893
|
+
{
|
|
894
|
+
dev: parentBefore.dev,
|
|
895
|
+
ino: parentBefore.ino,
|
|
896
|
+
},
|
|
897
|
+
true,
|
|
898
|
+
);
|
|
885
899
|
const detachedPath = detachedTree(detached);
|
|
886
900
|
if (!detachedPath) {
|
|
901
|
+
if (detached.code === "restore_failed" && detached.detachedPath) {
|
|
902
|
+
const retainedSnapshot = await snapshotIfPresent(detached.detachedPath).catch(() => undefined);
|
|
903
|
+
const retainedBackupPath =
|
|
904
|
+
retainedSnapshot && sameDirectoryTreeIdentity(finalSnapshotBefore, retainedSnapshot)
|
|
905
|
+
? detached.detachedPath
|
|
906
|
+
: undefined;
|
|
907
|
+
throw new MarketplaceRestoreError("backup_detach_unverified", {
|
|
908
|
+
sideEffectStarted: true,
|
|
909
|
+
outcome: "uncertain",
|
|
910
|
+
...(retainedBackupPath ? { retainedBackupPath } : {}),
|
|
911
|
+
});
|
|
912
|
+
}
|
|
887
913
|
// identity_mismatch means finalPath already changed before we ever
|
|
888
914
|
// touched it — exactRemoveDirectoryTree refused the mutation entirely,
|
|
889
915
|
// so this is a pure precheck refusal: nothing moved, sideEffectStarted
|
|
@@ -906,7 +932,7 @@ export class MarketplaceManager {
|
|
|
906
932
|
// later detach of the same canonical path inside this same transaction (the
|
|
907
933
|
// rollback path) collides with our own leftover and is misread as a foreign
|
|
908
934
|
// claim. The rename below is what vacates it; failure is reported, never assumed.
|
|
909
|
-
const backupPublish = await
|
|
935
|
+
const backupPublish = await renameDirectoryNoReplace(detachedPath, backup);
|
|
910
936
|
if (!backupPublish.ok) {
|
|
911
937
|
// mutationState "not_committed" proves the rename never moved the
|
|
912
938
|
// object; it is still at the detached path, so that path is real
|
|
@@ -962,7 +988,7 @@ export class MarketplaceManager {
|
|
|
962
988
|
// devices on cross_device, the dev/ino-stability assumption behind
|
|
963
989
|
// `stagedSnapshot` breaks silently and every identity-bound check in this
|
|
964
990
|
// method becomes unsound.
|
|
965
|
-
const publish = await
|
|
991
|
+
const publish = await renameDirectoryNoReplace(token.stagedArtifactPath, finalPath);
|
|
966
992
|
// Test seam only (no-op in production): lets a test deterministically
|
|
967
993
|
// simulate a concurrent second writer republishing finalPath here,
|
|
968
994
|
// exercising the foreign-owner branch below without weakening it.
|
|
@@ -1233,7 +1259,7 @@ export class MarketplaceManager {
|
|
|
1233
1259
|
);
|
|
1234
1260
|
}
|
|
1235
1261
|
}
|
|
1236
|
-
const restorePublish = await
|
|
1262
|
+
const restorePublish = await renameDirectoryNoReplace(backup, finalPath);
|
|
1237
1263
|
if (!restorePublish.ok) {
|
|
1238
1264
|
// Restore failed: confirm what actually remains at `backup` right now
|
|
1239
1265
|
// (the no-replace rename may have left it there proven-untouched, or
|
|
@@ -116,6 +116,11 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<
|
|
|
116
116
|
return cmd;
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
+
export function getBuiltinSlashCommandsForSession(hasExactMcpControls: boolean): typeof BUILTIN_SLASH_COMMANDS {
|
|
120
|
+
if (hasExactMcpControls) return BUILTIN_SLASH_COMMANDS;
|
|
121
|
+
return BUILTIN_SLASH_COMMANDS.filter(command => command.name !== "mcp");
|
|
122
|
+
}
|
|
123
|
+
|
|
119
124
|
/**
|
|
120
125
|
* Represents a custom slash command loaded from a file
|
|
121
126
|
*/
|
|
@@ -18,7 +18,15 @@ import * as fsp from "node:fs/promises";
|
|
|
18
18
|
import * as os from "node:os";
|
|
19
19
|
import * as path from "node:path";
|
|
20
20
|
import { exactRemoveDirectoryTree, exactUnlink, snapshotDirectoryTree } from "@gajae-code/natives";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
getAgentDir,
|
|
23
|
+
getBlobsDir,
|
|
24
|
+
getSessionsDir,
|
|
25
|
+
isEnoent,
|
|
26
|
+
loadedProjectEnvSnapshot,
|
|
27
|
+
VERSION,
|
|
28
|
+
} from "@gajae-code/utils";
|
|
29
|
+
import { type ProjectEnvSnapshot, projectEnvSnapshot } from "@gajae-code/utils/env-file";
|
|
22
30
|
import { getDefault } from "../config/settings-schema";
|
|
23
31
|
import { listHarnessRootRegistriesForGc } from "../harness-control-plane/storage";
|
|
24
32
|
import { SessionIndex } from "../sdk/broker/session-index";
|
|
@@ -54,6 +62,7 @@ import {
|
|
|
54
62
|
} from "./empty-delete-gc";
|
|
55
63
|
import { buildGcReportText } from "./gc-render";
|
|
56
64
|
import { collectSessionScopeUsage, type GcSessionScopeUsage, shouldReportSessionScope } from "./gc-session-scope";
|
|
65
|
+
import { trustedCoordinatorEnv } from "./sidecar-bootstrap-env";
|
|
57
66
|
|
|
58
67
|
export type GcStore = "harness_leases" | "file_locks" | "tmux_sessions" | "registry_entries" | "local_roots";
|
|
59
68
|
|
|
@@ -456,8 +465,21 @@ export function computeExitCode(report: GcReport): number {
|
|
|
456
465
|
return 0;
|
|
457
466
|
}
|
|
458
467
|
|
|
459
|
-
|
|
460
|
-
|
|
468
|
+
/**
|
|
469
|
+
* Operator override only. Same project-dotenv rule as `getAgentDir()`: a value
|
|
470
|
+
* the checkout declares is ignored, and an operator value it does not declare
|
|
471
|
+
* is kept. A repository `.env` must not choose the tree `gjc gc` reclaims.
|
|
472
|
+
*
|
|
473
|
+
* `snapshot` is the dotenv provenance from when that environment was loaded.
|
|
474
|
+
* `process.env` uses the module-load snapshot. A separate env map uses the
|
|
475
|
+
* snapshot taken with it before awaited GC work. Neither path rereads files later.
|
|
476
|
+
*/
|
|
477
|
+
function resolveGcAgentDir(env: NodeJS.ProcessEnv, snapshot: ProjectEnvSnapshot): string {
|
|
478
|
+
return (
|
|
479
|
+
trustedCoordinatorEnv("GJC_CODING_AGENT_DIR", env, snapshot) ||
|
|
480
|
+
trustedCoordinatorEnv("PI_CODING_AGENT_DIR", env, snapshot) ||
|
|
481
|
+
getAgentDir()
|
|
482
|
+
);
|
|
461
483
|
}
|
|
462
484
|
|
|
463
485
|
/**
|
|
@@ -572,6 +594,10 @@ export async function runGjcGcCommand(
|
|
|
572
594
|
adapters?: GcStoreAdapter[],
|
|
573
595
|
diskPolicy?: Partial<GcDiskPolicy>,
|
|
574
596
|
): Promise<GcRunResult> {
|
|
597
|
+
// process.env was loaded before this module. Reusing that snapshot keeps a
|
|
598
|
+
// project value rejected after its declaration is removed or changed.
|
|
599
|
+
// A caller-supplied env is not that load: bind its cwd files once, here.
|
|
600
|
+
const loadedProjectEnv = env === process.env ? loadedProjectEnvSnapshot() : projectEnvSnapshot(cwd);
|
|
575
601
|
let parsed: ParsedGcArgs;
|
|
576
602
|
try {
|
|
577
603
|
parsed = parseGcArgs(argv);
|
|
@@ -656,17 +682,18 @@ export async function runGjcGcCommand(
|
|
|
656
682
|
const ordinaryPrune = parsed.prune && (emptyDeleteReceipts?.errors.length ?? 0) === 0;
|
|
657
683
|
const report = await collectGcReport(resolvedAdapters, ctx, ordinaryPrune);
|
|
658
684
|
report.operation = parsed.repairSessionIndex ? "repair_session_index" : parsed.prune ? "prune" : "dry_run";
|
|
659
|
-
|
|
685
|
+
const agentDir = resolveGcAgentDir(env, loadedProjectEnv);
|
|
686
|
+
report.session_index = await collectSessionIndexHealth(parsed.repairSessionIndex, agentDir);
|
|
660
687
|
if (parsed.disk) {
|
|
661
688
|
report.disk = await collectGcDiskReport({
|
|
662
|
-
agentDir
|
|
689
|
+
agentDir,
|
|
663
690
|
env,
|
|
664
691
|
policy: resolveGcDiskPolicy(diskPolicy),
|
|
665
692
|
prune: ordinaryPrune,
|
|
666
693
|
});
|
|
667
694
|
}
|
|
668
695
|
if (emptyDeleteReceipts) report.empty_delete_receipts = emptyDeleteReceipts;
|
|
669
|
-
const scopeUsage = await collectGcSessionScope(cwd,
|
|
696
|
+
const scopeUsage = await collectGcSessionScope(cwd, agentDir);
|
|
670
697
|
if (scopeUsage && shouldReportSessionScope(scopeUsage)) report.session_scope = scopeUsage;
|
|
671
698
|
const sessionIndexFailed =
|
|
672
699
|
report.session_index?.status === "corrupt" ||
|
|
@@ -2272,7 +2299,10 @@ async function removeGcDiskEntry(
|
|
|
2272
2299
|
return { removed: false, reason: "entry_changed" };
|
|
2273
2300
|
}
|
|
2274
2301
|
const retainedAtOriginal = !removal.detachedPath || path.resolve(removal.detachedPath) === path.resolve(target);
|
|
2275
|
-
if (
|
|
2302
|
+
if (
|
|
2303
|
+
(removal.code === "permission_denied" || removal.code === "access_denied" || removal.code === "io_error") &&
|
|
2304
|
+
retainedAtOriginal
|
|
2305
|
+
) {
|
|
2276
2306
|
return { removed: false, reason: "withheld_evidence_incomplete: tree_unreadable", withheld: true };
|
|
2277
2307
|
}
|
|
2278
2308
|
return {
|