@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/sdk/bus/index.ts
CHANGED
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
type WorkflowGateTerminalController,
|
|
72
72
|
type WorkflowGateTerminalProof,
|
|
73
73
|
} from "../../modes/shared/agent-wire/workflow-gate-broker";
|
|
74
|
-
import type { AgentSessionEvent } from "../../session/agent-session";
|
|
74
|
+
import type { AgentSessionEvent, QueuedRunStartFailure } from "../../session/agent-session";
|
|
75
75
|
import type { ClientBridge } from "../../session/client-bridge";
|
|
76
76
|
import {
|
|
77
77
|
createSessionWorkLease,
|
|
@@ -102,6 +102,7 @@ import {
|
|
|
102
102
|
registerAskAnswerSource,
|
|
103
103
|
registerWorkflowGateEmitterListener,
|
|
104
104
|
} from "../../tools/ask-answer-registry";
|
|
105
|
+
import type { AwaitingInputKind } from "../../tools/awaiting-input";
|
|
105
106
|
import { acpFinalTextFromMessage } from "../acp/final-text";
|
|
106
107
|
import { ensureBroker } from "../broker/ensure";
|
|
107
108
|
import { publishSessionHostRuntimeEvidence, type SessionHostRuntimePublication } from "../broker/lifecycle";
|
|
@@ -117,11 +118,13 @@ import {
|
|
|
117
118
|
type SessionSdkHost,
|
|
118
119
|
SessionSdkSessionRuntime,
|
|
119
120
|
shouldHostSdk,
|
|
121
|
+
TURN_STREAM_CAPABILITY,
|
|
120
122
|
verifyMasterCapabilityFrame,
|
|
121
123
|
} from "../host";
|
|
122
124
|
import { type AbortScope, type ControlSurface, dispatchControl, TypedControlError } from "../host/control";
|
|
123
125
|
import { BROKER_RUNTIME_CLOSE_CAPABILITY_FIELD } from "../host/control/runtime-gate";
|
|
124
126
|
import { isAutoroutingInactive, markAutoroutingInactive } from "../host/internal-autorouting-state";
|
|
127
|
+
import { PromptImageUploadStore, retirePromptImageReservation } from "../host/prompt-image-upload";
|
|
125
128
|
import { CursorRegistry, QueryHandlers, RevisionStore, type SessionSurface } from "../host/query";
|
|
126
129
|
import { RESPONSE_CEILING_BYTES } from "../host/query/handlers";
|
|
127
130
|
import type { SdkFrame } from "../host/types";
|
|
@@ -132,7 +135,7 @@ import {
|
|
|
132
135
|
syntheticModelInputError,
|
|
133
136
|
syntheticNamespaceCollision,
|
|
134
137
|
} from "../model-profile-model";
|
|
135
|
-
import {
|
|
138
|
+
import { autosaveWorktreeOnPromptDeadline, deadlineFlushSuppressed } from "../prompt-deadline-flush";
|
|
136
139
|
import {
|
|
137
140
|
createPromptDeadlineLease,
|
|
138
141
|
isAttributableProgressEventType,
|
|
@@ -1235,6 +1238,10 @@ export class PresentationArbiter {
|
|
|
1235
1238
|
interface SessionRuntime {
|
|
1236
1239
|
server: NotificationServer;
|
|
1237
1240
|
host: SessionSdkHost;
|
|
1241
|
+
imageUploads: PromptImageUploadStore | undefined;
|
|
1242
|
+
releaseAcceptedImage: (correlation: { commandId: string; turnId: string }) => void;
|
|
1243
|
+
releaseAcceptedImagesForRun: (owner: AgentTerminalOwnerContext) => void;
|
|
1244
|
+
releaseAcceptedImages: () => void;
|
|
1238
1245
|
getJoinedPromptCorrelations: (owner: AgentTerminalOwnerContext) => Array<{ commandId: string; turnId: string }>;
|
|
1239
1246
|
isPromptRunOwner: (correlation: { commandId: string; turnId: string }, owner: AgentTerminalOwnerContext) => boolean;
|
|
1240
1247
|
retireJoinedPromptOwners: () => void;
|
|
@@ -1421,6 +1428,12 @@ interface SessionRuntime {
|
|
|
1421
1428
|
string,
|
|
1422
1429
|
{ toolName: string; args?: unknown; pendingPhase?: "completed" | "failed" | "cancelled" }
|
|
1423
1430
|
>;
|
|
1431
|
+
/**
|
|
1432
|
+
* Running tool calls that reported an awaiting-input signal, keyed by tool call
|
|
1433
|
+
* id. An entry stays undelivered while notifications are inactive or policy is
|
|
1434
|
+
* provisional, and is dropped when the call ends; one notification per call.
|
|
1435
|
+
*/
|
|
1436
|
+
awaitingInput: Map<string, { toolName: string; kind: AwaitingInputKind; delivered: boolean }>;
|
|
1424
1437
|
/** Cancels the postmortem cleanup that emits `session_closed` on process teardown. */
|
|
1425
1438
|
cancelPostmortemCleanup: () => void;
|
|
1426
1439
|
/** Disposes side-turn resources when their owning logical session becomes unavailable. */
|
|
@@ -1431,6 +1444,48 @@ const SENSITIVE_MODEL_LABEL =
|
|
|
1431
1444
|
/(?:\b(?:https?|wss?):\/\/|\b[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}\b|\b(?:api[-_ ]?key|access[-_ ]?token|bearer|secret|password|account(?:\s*id)?|email|exception|stack trace)\b|\b(?:sk|pk|rk)-[A-Za-z0-9_-]{12,}\b)/i;
|
|
1432
1445
|
const TOOL_SUMMARY_MAX = 280;
|
|
1433
1446
|
|
|
1447
|
+
/** The `awaitingInput` signal a running bash update carries, validated at the extension boundary. */
|
|
1448
|
+
function readAwaitingInput(partialResult: unknown): { kind: AwaitingInputKind } | undefined {
|
|
1449
|
+
if (!partialResult || typeof partialResult !== "object") return undefined;
|
|
1450
|
+
const details = (partialResult as { details?: unknown }).details;
|
|
1451
|
+
if (!details || typeof details !== "object") return undefined;
|
|
1452
|
+
const signal = (details as { awaitingInput?: unknown }).awaitingInput;
|
|
1453
|
+
if (!signal || typeof signal !== "object") return undefined;
|
|
1454
|
+
const kind = (signal as { kind?: unknown }).kind;
|
|
1455
|
+
return kind === "browser_auth" || kind === "device_code" ? { kind } : undefined;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Deliver every undelivered awaiting-input notice once stable policy admits it.
|
|
1460
|
+
* The notice describes the present ("a command is waiting now"), so it goes out
|
|
1461
|
+
* on the live native leg only and never enters the replay ring: a client that
|
|
1462
|
+
* reconnects after the command exited must not receive it. The native server
|
|
1463
|
+
* still withholds it from connections without `awaiting_input_v1`.
|
|
1464
|
+
*/
|
|
1465
|
+
function deliverAwaitingInput(
|
|
1466
|
+
runtime: Pick<SessionRuntime, "server" | "awaitingInput" | "notificationsActive" | "policySuspended">,
|
|
1467
|
+
sessionId: string,
|
|
1468
|
+
): void {
|
|
1469
|
+
if (!runtime.notificationsActive || runtime.policySuspended) return;
|
|
1470
|
+
for (const [toolCallId, entry] of runtime.awaitingInput) {
|
|
1471
|
+
if (entry.delivered) continue;
|
|
1472
|
+
entry.delivered = true;
|
|
1473
|
+
try {
|
|
1474
|
+
runtime.server.pushFrame(
|
|
1475
|
+
JSON.stringify({
|
|
1476
|
+
type: "awaiting_input",
|
|
1477
|
+
sessionId,
|
|
1478
|
+
toolCallId,
|
|
1479
|
+
toolName: entry.toolName,
|
|
1480
|
+
kind: entry.kind,
|
|
1481
|
+
}),
|
|
1482
|
+
);
|
|
1483
|
+
} catch (e) {
|
|
1484
|
+
logger.warn(`notifications: awaiting_input failed: ${String(e)}`);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1434
1489
|
/** Stable projection of the tool-owned safe-display seam (never the full Tool surface). */
|
|
1435
1490
|
type SafeSummaryTool = Pick<Tool, "safeSummary" | "safeSummaryFields">;
|
|
1436
1491
|
|
|
@@ -2459,11 +2514,13 @@ function sdkQuerySurface(
|
|
|
2459
2514
|
}),
|
|
2460
2515
|
getRuntimeHost: () => SessionSdkHost | undefined = () => undefined,
|
|
2461
2516
|
primaryControlSurface: "cli" | "sdk" = "sdk",
|
|
2517
|
+
imageUploadsAvailable = false,
|
|
2462
2518
|
): SessionSurface {
|
|
2463
2519
|
return createSdkSurfaceFactory({
|
|
2464
2520
|
ctx,
|
|
2465
2521
|
id,
|
|
2466
2522
|
api,
|
|
2523
|
+
imageUploadsAvailable,
|
|
2467
2524
|
getInstalledDefinitions,
|
|
2468
2525
|
getLiveState,
|
|
2469
2526
|
configOverrides,
|
|
@@ -2612,6 +2669,19 @@ function sdkControlSurface(
|
|
|
2612
2669
|
pendingInteractive: Map<string, PendingInteractiveAsk>,
|
|
2613
2670
|
gatePresentations: PresentationArbiter | undefined,
|
|
2614
2671
|
api: ExtensionAPI,
|
|
2672
|
+
imageUploads: PromptImageUploadStore | undefined,
|
|
2673
|
+
imageUploadsAvailable: boolean,
|
|
2674
|
+
retainAcceptedImage: (
|
|
2675
|
+
correlation: { commandId: string; turnId: string },
|
|
2676
|
+
release: () => void,
|
|
2677
|
+
preflightSignal: AbortSignal,
|
|
2678
|
+
submissionSettled: Promise<void>,
|
|
2679
|
+
) => {
|
|
2680
|
+
accepted: () => void;
|
|
2681
|
+
promoted: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
2682
|
+
refused: () => boolean;
|
|
2683
|
+
},
|
|
2684
|
+
releaseAcceptedImage: (correlation: { commandId: string; turnId: string }) => void,
|
|
2615
2685
|
isBusy: () => boolean,
|
|
2616
2686
|
onPromptAccepted: (
|
|
2617
2687
|
correlation: { commandId: string; turnId: string },
|
|
@@ -2626,6 +2696,12 @@ function sdkControlSurface(
|
|
|
2626
2696
|
correlation: { commandId: string; turnId: string },
|
|
2627
2697
|
error: unknown,
|
|
2628
2698
|
) => void | Promise<void> = () => {},
|
|
2699
|
+
onQueuedRunStartFailed: (
|
|
2700
|
+
correlation: { commandId: string; turnId: string },
|
|
2701
|
+
failure: QueuedRunStartFailure,
|
|
2702
|
+
sdkRunToken: string | undefined,
|
|
2703
|
+
refuseImage: (() => boolean) | undefined,
|
|
2704
|
+
) => boolean,
|
|
2629
2705
|
onPromptAcceptFailed: (correlation: { commandId: string; turnId: string }) => void = () => {},
|
|
2630
2706
|
onPromptDiverted: (correlation: { commandId: string; turnId: string }) => void,
|
|
2631
2707
|
onPromptPromoted: (
|
|
@@ -2659,6 +2735,10 @@ function sdkControlSurface(
|
|
|
2659
2735
|
// the session-wide preflight seam must not be invoked while another
|
|
2660
2736
|
// connection's active preflight could be cancelled by it (review P1).
|
|
2661
2737
|
noOtherConnectionPreflights?: () => boolean,
|
|
2738
|
+
// True only for an operator terminal abort that the broker control route already
|
|
2739
|
+
// authorized (`TerminalAbortInput.operator`, which a public SDK caller cannot grant):
|
|
2740
|
+
// it addresses the session's active turn, not the requesting connection's own prompt.
|
|
2741
|
+
operatorAuthorized?: boolean,
|
|
2662
2742
|
) => Promise<
|
|
2663
2743
|
| {
|
|
2664
2744
|
ok: true;
|
|
@@ -2723,6 +2803,7 @@ function sdkControlSurface(
|
|
|
2723
2803
|
ctx,
|
|
2724
2804
|
id: ctx.sessionManager.getSessionId(),
|
|
2725
2805
|
api,
|
|
2806
|
+
imageUploadsAvailable,
|
|
2726
2807
|
}).policy;
|
|
2727
2808
|
const missingExpectedSessionAudits = new Set<"workflow.gate_answer" | "workflow.plan_approve">();
|
|
2728
2809
|
const auditMissingExpectedSessionId = (operation: "workflow.gate_answer" | "workflow.plan_approve") => {
|
|
@@ -2908,6 +2989,18 @@ function sdkControlSurface(
|
|
|
2908
2989
|
requesterConnectionId?: string,
|
|
2909
2990
|
clientRef?: string,
|
|
2910
2991
|
trackReconciliation = false,
|
|
2992
|
+
onCorrelation?: (
|
|
2993
|
+
correlation: { commandId: string; turnId: string },
|
|
2994
|
+
preflightSignal: AbortSignal,
|
|
2995
|
+
submissionSettled: Promise<void>,
|
|
2996
|
+
) =>
|
|
2997
|
+
| {
|
|
2998
|
+
accepted: () => void;
|
|
2999
|
+
promoted: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
3000
|
+
refused: () => boolean;
|
|
3001
|
+
}
|
|
3002
|
+
| undefined,
|
|
3003
|
+
resolveImages?: () => unknown,
|
|
2911
3004
|
) => {
|
|
2912
3005
|
const trimmedClientRef = typeof clientRef === "string" ? clientRef.trim() : undefined;
|
|
2913
3006
|
if (clientRef !== undefined && (!trimmedClientRef || trimmedClientRef.length > PROMPT_CLIENT_REF_MAX_LENGTH))
|
|
@@ -2953,6 +3046,8 @@ function sdkControlSurface(
|
|
|
2953
3046
|
code: "busy",
|
|
2954
3047
|
},
|
|
2955
3048
|
);
|
|
3049
|
+
// Staged bytes are one-shot: reserve reconciliation before consuming them.
|
|
3050
|
+
if (resolveImages) images = resolveImages();
|
|
2956
3051
|
} catch (error) {
|
|
2957
3052
|
admission.abandon();
|
|
2958
3053
|
if (trackReconciliation) releasePromptAdmission(trimmedClientRef);
|
|
@@ -2984,6 +3079,8 @@ function sdkControlSurface(
|
|
|
2984
3079
|
const submissionSettled = Promise.withResolvers<void>();
|
|
2985
3080
|
let cancellation: Promise<void> | undefined;
|
|
2986
3081
|
const correlation = { commandId, turnId };
|
|
3082
|
+
let queuedRunRefused = false;
|
|
3083
|
+
const imageLifecycle = onCorrelation?.(correlation, preflightController.signal, submissionSettled.promise);
|
|
2987
3084
|
const key = preflightKey(requesterConnectionId, correlation);
|
|
2988
3085
|
const settlePreflight = (result: PreflightTerminalResult) => {
|
|
2989
3086
|
if (preflightSettled) return;
|
|
@@ -3034,6 +3131,8 @@ function sdkControlSurface(
|
|
|
3034
3131
|
admission.accepted();
|
|
3035
3132
|
accepting = false;
|
|
3036
3133
|
accepted = true;
|
|
3134
|
+
// A late durable acceptance after direct abort cannot end image retention.
|
|
3135
|
+
if (!preflightController.signal.aborted) imageLifecycle?.accepted();
|
|
3037
3136
|
if (effectiveDeliverAs !== undefined) onPromptDiverted(correlation);
|
|
3038
3137
|
// #4743: an accepted run owns a durable terminal publication when it
|
|
3039
3138
|
// settles; teardown joins it via this latch (never-accepted preflights
|
|
@@ -3061,13 +3160,22 @@ function sdkControlSurface(
|
|
|
3061
3160
|
onPreflightAcceptCommit,
|
|
3062
3161
|
onPreflightAccepted,
|
|
3063
3162
|
onQueuedPromoted: promotion => {
|
|
3163
|
+
if (queuedRunRefused) return;
|
|
3164
|
+
if (promotion.startsOwnRun === true) imageLifecycle?.promoted(promotion);
|
|
3064
3165
|
admission.hooks.onQueuedPromoted(promotion);
|
|
3065
3166
|
onPromptPromoted(correlation, promotion, ctx.getActivePromptHandle());
|
|
3167
|
+
if (promotion.startsOwnRun !== true) imageLifecycle?.promoted(promotion);
|
|
3168
|
+
if (promotion.removed) releaseAcceptedImage(correlation);
|
|
3066
3169
|
},
|
|
3067
3170
|
onDispatchDisposition: disposition => {
|
|
3171
|
+
if (queuedRunRefused) return;
|
|
3068
3172
|
admission.hooks.onDispatchDisposition(disposition);
|
|
3069
3173
|
if (!disposition.startsOwnRun) onPromptDiverted(correlation);
|
|
3070
3174
|
},
|
|
3175
|
+
onQueuedRunStartFailed: failure => {
|
|
3176
|
+
if (queuedRunRefused) return;
|
|
3177
|
+
queuedRunRefused = onQueuedRunStartFailed(correlation, failure, sdkRunToken, imageLifecycle?.refused);
|
|
3178
|
+
},
|
|
3071
3179
|
preflightSignal: preflightController.signal,
|
|
3072
3180
|
...(sdkRunToken ? { sdkRunToken } : {}),
|
|
3073
3181
|
}),
|
|
@@ -3075,7 +3183,7 @@ function sdkControlSurface(
|
|
|
3075
3183
|
} catch (error) {
|
|
3076
3184
|
submissionSettled.resolve();
|
|
3077
3185
|
admission.abandon();
|
|
3078
|
-
if (accepted && !preflightController.signal.aborted)
|
|
3186
|
+
if (accepted && !queuedRunRefused && !preflightController.signal.aborted)
|
|
3079
3187
|
trackReconciliationProducer?.(Promise.resolve(onPromptFailed(correlation, error)));
|
|
3080
3188
|
else settlePreflight({ status: "rejected", error });
|
|
3081
3189
|
}
|
|
@@ -3097,7 +3205,7 @@ function sdkControlSurface(
|
|
|
3097
3205
|
},
|
|
3098
3206
|
error => {
|
|
3099
3207
|
admission.abandon();
|
|
3100
|
-
if (accepted && !preflightController.signal.aborted)
|
|
3208
|
+
if (accepted && !queuedRunRefused && !preflightController.signal.aborted)
|
|
3101
3209
|
trackReconciliationProducer?.(Promise.resolve(onPromptFailed(correlation, error)));
|
|
3102
3210
|
else settlePreflight({ status: "rejected", error });
|
|
3103
3211
|
submissionSettled.resolve();
|
|
@@ -3120,8 +3228,52 @@ function sdkControlSurface(
|
|
|
3120
3228
|
cancelPendingPreflights(): Promise<void>;
|
|
3121
3229
|
cancelPendingPreflightsForConnection(connectionId: string): Promise<void>;
|
|
3122
3230
|
} = {
|
|
3123
|
-
prompt: (text, images, clientRef) =>
|
|
3124
|
-
|
|
3231
|
+
prompt: async (text, images, clientRef, stagedImages) => {
|
|
3232
|
+
if (stagedImages !== undefined && images !== undefined)
|
|
3233
|
+
throw Object.assign(new Error("Direct and staged images cannot be mixed."), { code: "invalid_input" });
|
|
3234
|
+
const requesterConnectionId = controlRequesterContext.getStore();
|
|
3235
|
+
let reservation: { images: ImageContent[]; release: () => void } | undefined;
|
|
3236
|
+
let correlation: { commandId: string; turnId: string } | undefined;
|
|
3237
|
+
try {
|
|
3238
|
+
return await submitPrompt(
|
|
3239
|
+
text,
|
|
3240
|
+
images,
|
|
3241
|
+
false,
|
|
3242
|
+
undefined,
|
|
3243
|
+
true,
|
|
3244
|
+
requesterConnectionId,
|
|
3245
|
+
clientRef,
|
|
3246
|
+
true,
|
|
3247
|
+
(current, preflightSignal, submissionSettled) => {
|
|
3248
|
+
correlation = current;
|
|
3249
|
+
if (reservation)
|
|
3250
|
+
return retainAcceptedImage(current, reservation.release, preflightSignal, submissionSettled);
|
|
3251
|
+
},
|
|
3252
|
+
stagedImages === undefined
|
|
3253
|
+
? undefined
|
|
3254
|
+
: () => {
|
|
3255
|
+
if (!imageUploads)
|
|
3256
|
+
throw Object.assign(new Error("Staged images are unavailable."), {
|
|
3257
|
+
code: "image_upload_unavailable",
|
|
3258
|
+
});
|
|
3259
|
+
reservation = imageUploads.redeem(requesterConnectionId, stagedImages);
|
|
3260
|
+
return reservation.images;
|
|
3261
|
+
},
|
|
3262
|
+
);
|
|
3263
|
+
} catch (error) {
|
|
3264
|
+
if (correlation) releaseAcceptedImage(correlation);
|
|
3265
|
+
else reservation?.release();
|
|
3266
|
+
throw error;
|
|
3267
|
+
}
|
|
3268
|
+
},
|
|
3269
|
+
...(imageUploads
|
|
3270
|
+
? {
|
|
3271
|
+
imageBegin: (input: unknown) => imageUploads.begin(controlRequesterContext.getStore(), input),
|
|
3272
|
+
imageAppend: (input: unknown) => imageUploads.append(controlRequesterContext.getStore(), input),
|
|
3273
|
+
imageFinish: (input: unknown) => imageUploads.finish(controlRequesterContext.getStore(), input),
|
|
3274
|
+
imageDiscard: (input: unknown) => imageUploads.discard(controlRequesterContext.getStore(), input),
|
|
3275
|
+
}
|
|
3276
|
+
: {}),
|
|
3125
3277
|
steer: (text, clientRef) => sendSteer(text, clientRef),
|
|
3126
3278
|
followUp: text => submitPrompt(text, undefined, false, "followUp", false, controlRequesterContext.getStore()),
|
|
3127
3279
|
abort: async () => {
|
|
@@ -3178,6 +3330,9 @@ function sdkControlSurface(
|
|
|
3178
3330
|
// invoking it (review thread P1).
|
|
3179
3331
|
() =>
|
|
3180
3332
|
![...pendingPreflightCancellations.values()].some(entry => entry.connectionId !== requesterConnectionId),
|
|
3333
|
+
// Broker-authorized operator authority is the one case where the abort
|
|
3334
|
+
// addresses a turn another connection submitted (see the parameter note).
|
|
3335
|
+
input.operator === true,
|
|
3181
3336
|
);
|
|
3182
3337
|
// Preflight cancellation happens ONLY for a NEWLY ADMITTED abort,
|
|
3183
3338
|
// after the durable admission/replay decision inside
|
|
@@ -4281,6 +4436,34 @@ export function boundedCorrelatedAgentEndFrame(frame: Record<string, unknown>):
|
|
|
4281
4436
|
};
|
|
4282
4437
|
}
|
|
4283
4438
|
|
|
4439
|
+
/** Connection-scoped identity of a queued prompt submission an abort may address. */
|
|
4440
|
+
export interface TerminalAbortSubmissionScope {
|
|
4441
|
+
connectionId?: string;
|
|
4442
|
+
terminal: boolean;
|
|
4443
|
+
}
|
|
4444
|
+
|
|
4445
|
+
/**
|
|
4446
|
+
* Whether a terminal abort addresses this prompt submission.
|
|
4447
|
+
*
|
|
4448
|
+
* An ordinary abort is scoped to the requesting connection's own prompt: `connectionId`
|
|
4449
|
+
* identifies the connection that submitted it, and a submission that already reached a
|
|
4450
|
+
* terminal state is never addressed. Broker-authorized operator authority
|
|
4451
|
+
* (`TerminalAbortInput.operator`, granted only through the broker control route) is the
|
|
4452
|
+
* documented exception — "operator authority changes only connection ownership, never
|
|
4453
|
+
* those settlement proofs" — so it addresses the session's submission even when another
|
|
4454
|
+
* connection submitted it. Without that override every operator abort issued over a
|
|
4455
|
+
* second connection (the SDK client case, where each request is its own connection)
|
|
4456
|
+
* reported no_active_turn while the turn was still running.
|
|
4457
|
+
*/
|
|
4458
|
+
export function terminalAbortAddressesSubmission(input: {
|
|
4459
|
+
connectionId: string | undefined;
|
|
4460
|
+
operatorAuthorized: boolean;
|
|
4461
|
+
submission: TerminalAbortSubmissionScope;
|
|
4462
|
+
}): boolean {
|
|
4463
|
+
if (input.submission.terminal) return false;
|
|
4464
|
+
return input.operatorAuthorized || input.submission.connectionId === input.connectionId;
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4284
4467
|
export function createNotificationsExtension(
|
|
4285
4468
|
api: ExtensionAPI,
|
|
4286
4469
|
options: {
|
|
@@ -4313,6 +4496,8 @@ export function createNotificationsExtension(
|
|
|
4313
4496
|
* preflight outside the durable admission path (review thread P2).
|
|
4314
4497
|
*/
|
|
4315
4498
|
terminalAbortSeams?: {
|
|
4499
|
+
/** Definitive event-driven observation; never mutates the owning run. */
|
|
4500
|
+
waitForRunSettlement?: (handle: string) => Promise<RunSettlementProof>;
|
|
4316
4501
|
getTerminalRunOwnerForEvent?: (event: object) => AgentTerminalOwnerContext | undefined;
|
|
4317
4502
|
getRunOwnerDomain?: (handle: string) => RunCancellationDomain | undefined;
|
|
4318
4503
|
getTerminalTurnEpoch: () => number | undefined;
|
|
@@ -4602,6 +4787,7 @@ export function createNotificationsExtension(
|
|
|
4602
4787
|
if (reason === "session" && requestedRuntime) {
|
|
4603
4788
|
requestedRuntime.inboundFenced = true;
|
|
4604
4789
|
requestedRuntime.stopping = true;
|
|
4790
|
+
requestedRuntime.imageUploads?.close();
|
|
4605
4791
|
requestedRuntime.retireJoinedPromptOwners();
|
|
4606
4792
|
requestedRuntime.abortEphemeralTurns();
|
|
4607
4793
|
}
|
|
@@ -4780,6 +4966,7 @@ export function createNotificationsExtension(
|
|
|
4780
4966
|
cleanupRetries.set(id, rt);
|
|
4781
4967
|
throw new AggregateError(ownerReleaseFailures, `SDK notification runtime ${id} owner release failed.`);
|
|
4782
4968
|
}
|
|
4969
|
+
rt.releaseAcceptedImages();
|
|
4783
4970
|
if (cleanupRetries.get(id) === rt) cleanupRetries.delete(id);
|
|
4784
4971
|
return true;
|
|
4785
4972
|
}
|
|
@@ -5054,7 +5241,11 @@ export function createNotificationsExtension(
|
|
|
5054
5241
|
};
|
|
5055
5242
|
|
|
5056
5243
|
type HostConnectionIncarnation = { generation: number; closed: boolean };
|
|
5057
|
-
type HostCapabilityCacheEntry = {
|
|
5244
|
+
type HostCapabilityCacheEntry = {
|
|
5245
|
+
generation: number;
|
|
5246
|
+
capabilities: ReadonlySet<string>;
|
|
5247
|
+
nativeConfirmed: ReadonlySet<string>;
|
|
5248
|
+
};
|
|
5058
5249
|
const hostCapCache = new Map<string, HostCapabilityCacheEntry>();
|
|
5059
5250
|
const hostConnectionIncarnations = new Map<string, HostConnectionIncarnation>();
|
|
5060
5251
|
const hostAttachedConnections = new Set<string>();
|
|
@@ -5068,12 +5259,28 @@ export function createNotificationsExtension(
|
|
|
5068
5259
|
hostConnectionIncarnations.set(connectionId, incarnation);
|
|
5069
5260
|
return incarnation;
|
|
5070
5261
|
};
|
|
5071
|
-
const rememberHostCapabilities = (
|
|
5262
|
+
const rememberHostCapabilities = (
|
|
5263
|
+
connectionId: string,
|
|
5264
|
+
capabilities: readonly string[],
|
|
5265
|
+
source: "replay" | "native",
|
|
5266
|
+
): void => {
|
|
5072
5267
|
const incarnation = liveHostConnection(connectionId);
|
|
5073
5268
|
if (!incarnation) return;
|
|
5269
|
+
const previous = hostCapCache.get(connectionId);
|
|
5270
|
+
const merged =
|
|
5271
|
+
previous?.generation === incarnation.generation ? new Set(previous.capabilities) : new Set<string>();
|
|
5272
|
+
const nativeConfirmed =
|
|
5273
|
+
previous?.generation === incarnation.generation ? new Set(previous.nativeConfirmed) : new Set<string>();
|
|
5274
|
+
for (const capability of capabilities) merged.add(capability);
|
|
5275
|
+
// Replay claims enable stream routing immediately, but only native snapshots
|
|
5276
|
+
// can remove a socket from host demand. Merge delayed snapshots monotonically.
|
|
5277
|
+
if (source === "native") {
|
|
5278
|
+
for (const capability of capabilities) nativeConfirmed.add(capability);
|
|
5279
|
+
}
|
|
5074
5280
|
hostCapCache.set(connectionId, {
|
|
5075
5281
|
generation: incarnation.generation,
|
|
5076
|
-
capabilities:
|
|
5282
|
+
capabilities: merged,
|
|
5283
|
+
nativeConfirmed,
|
|
5077
5284
|
});
|
|
5078
5285
|
};
|
|
5079
5286
|
const liveHostCapabilities = (connectionId: string): ReadonlySet<string> | undefined => {
|
|
@@ -5095,6 +5302,17 @@ export function createNotificationsExtension(
|
|
|
5095
5302
|
hostCapCache.delete(connectionId);
|
|
5096
5303
|
hostAttachedConnections.delete(connectionId);
|
|
5097
5304
|
};
|
|
5305
|
+
const imageUploadsAvailable =
|
|
5306
|
+
typeof terminalAbortSeams?.waitForRunSettlement === "function" &&
|
|
5307
|
+
typeof terminalAbortSeams.getRunOwnerDomain === "function" &&
|
|
5308
|
+
typeof terminalAbortSeams.getTerminalRunOwnerForEvent === "function" &&
|
|
5309
|
+
typeof ctx.getActivePromptHandle === "function";
|
|
5310
|
+
const imageUploads = imageUploadsAvailable
|
|
5311
|
+
? new PromptImageUploadStore(connectionId => {
|
|
5312
|
+
const incarnation = hostConnectionIncarnations.get(connectionId);
|
|
5313
|
+
return incarnation !== undefined && !incarnation.closed;
|
|
5314
|
+
})
|
|
5315
|
+
: undefined;
|
|
5098
5316
|
|
|
5099
5317
|
const configOverrides = new Map<string, unknown>();
|
|
5100
5318
|
const configRevision = { current: 0 };
|
|
@@ -5110,6 +5328,115 @@ export function createNotificationsExtension(
|
|
|
5110
5328
|
const OWNED_SETTLEMENT_GRACE_MS = 500;
|
|
5111
5329
|
const promptSubmissionKey = (correlation: { commandId: string; turnId: string }) =>
|
|
5112
5330
|
`${correlation.commandId}:${correlation.turnId}`;
|
|
5331
|
+
type AcceptedImageReservation = {
|
|
5332
|
+
release: () => void;
|
|
5333
|
+
preflightSignal: AbortSignal;
|
|
5334
|
+
/** The producer can still retain ImageContent until settlement or exact run adoption. */
|
|
5335
|
+
submissionPending: boolean;
|
|
5336
|
+
/** A promoted queue entry needs its own run's proof before release authority transfers. */
|
|
5337
|
+
awaitingAdoption: boolean;
|
|
5338
|
+
accepted: boolean;
|
|
5339
|
+
releaseRequested: boolean;
|
|
5340
|
+
};
|
|
5341
|
+
const acceptedImages = new Map<string, AcceptedImageReservation>();
|
|
5342
|
+
// Absence means never consumed; a present undefined owner means execution
|
|
5343
|
+
// started without exact ownership evidence and must remain charged.
|
|
5344
|
+
const acceptedImageRunOwners = new Map<string, AgentTerminalOwnerContext | undefined>();
|
|
5345
|
+
const retiringImages = new Set<string>();
|
|
5346
|
+
const retireAcceptedImage = (key: string): void => {
|
|
5347
|
+
const reservation = acceptedImages.get(key);
|
|
5348
|
+
if (!reservation) return;
|
|
5349
|
+
if (reservation.submissionPending || reservation.awaitingAdoption) {
|
|
5350
|
+
reservation.releaseRequested = true;
|
|
5351
|
+
return;
|
|
5352
|
+
}
|
|
5353
|
+
if (retiringImages.has(key)) return;
|
|
5354
|
+
const discard = (): void => {
|
|
5355
|
+
if (acceptedImages.get(key) !== reservation) return;
|
|
5356
|
+
acceptedImages.delete(key);
|
|
5357
|
+
acceptedImageRunOwners.delete(key);
|
|
5358
|
+
retiringImages.delete(key);
|
|
5359
|
+
reservation.release();
|
|
5360
|
+
};
|
|
5361
|
+
const owner = acceptedImageRunOwners.get(key);
|
|
5362
|
+
if (!owner) {
|
|
5363
|
+
if (acceptedImageRunOwners.has(key)) {
|
|
5364
|
+
retiringImages.add(key);
|
|
5365
|
+
logger.warn("SDK image capacity retained for execution without an exact resource owner");
|
|
5366
|
+
return;
|
|
5367
|
+
}
|
|
5368
|
+
discard();
|
|
5369
|
+
return;
|
|
5370
|
+
}
|
|
5371
|
+
const waitForSettlement = terminalAbortSeams?.waitForRunSettlement;
|
|
5372
|
+
if (!waitForSettlement) return;
|
|
5373
|
+
retiringImages.add(key);
|
|
5374
|
+
retirePromptImageReservation(
|
|
5375
|
+
owner.resourceRunId,
|
|
5376
|
+
waitForSettlement,
|
|
5377
|
+
() => acceptedImages.get(key) === reservation,
|
|
5378
|
+
discard,
|
|
5379
|
+
);
|
|
5380
|
+
};
|
|
5381
|
+
const settleAcceptedImageSubmission = (key: string, reservation: AcceptedImageReservation): void => {
|
|
5382
|
+
if (acceptedImages.get(key) !== reservation || !reservation.submissionPending) return;
|
|
5383
|
+
reservation.submissionPending = false;
|
|
5384
|
+
if (reservation.releaseRequested) retireAcceptedImage(key);
|
|
5385
|
+
};
|
|
5386
|
+
const retainAcceptedImage = (
|
|
5387
|
+
correlation: { commandId: string; turnId: string },
|
|
5388
|
+
release: () => void,
|
|
5389
|
+
preflightSignal: AbortSignal,
|
|
5390
|
+
submissionSettled: Promise<void>,
|
|
5391
|
+
): {
|
|
5392
|
+
accepted: () => void;
|
|
5393
|
+
promoted: (promotion: { startsOwnRun?: boolean; removed?: boolean }) => void;
|
|
5394
|
+
refused: () => boolean;
|
|
5395
|
+
} => {
|
|
5396
|
+
const key = promptSubmissionKey(correlation);
|
|
5397
|
+
const reservation: AcceptedImageReservation = {
|
|
5398
|
+
release,
|
|
5399
|
+
preflightSignal,
|
|
5400
|
+
submissionPending: true,
|
|
5401
|
+
awaitingAdoption: false,
|
|
5402
|
+
accepted: false,
|
|
5403
|
+
releaseRequested: false,
|
|
5404
|
+
};
|
|
5405
|
+
acceptedImages.set(key, reservation);
|
|
5406
|
+
void submissionSettled.then(() => settleAcceptedImageSubmission(key, reservation));
|
|
5407
|
+
return {
|
|
5408
|
+
accepted: () => {
|
|
5409
|
+
reservation.accepted = true;
|
|
5410
|
+
if (reservation.preflightSignal.aborted) return;
|
|
5411
|
+
if (acceptedImageRunOwners.get(key) && !reservation.awaitingAdoption) {
|
|
5412
|
+
settleAcceptedImageSubmission(key, reservation);
|
|
5413
|
+
if (reservation.releaseRequested) retireAcceptedImage(key);
|
|
5414
|
+
}
|
|
5415
|
+
},
|
|
5416
|
+
promoted: promotion => {
|
|
5417
|
+
reservation.awaitingAdoption = promotion.startsOwnRun === true && promotion.removed !== true;
|
|
5418
|
+
if (!reservation.awaitingAdoption && reservation.releaseRequested) retireAcceptedImage(key);
|
|
5419
|
+
},
|
|
5420
|
+
refused: () => {
|
|
5421
|
+
if (acceptedImages.get(key) !== reservation || acceptedImageRunOwners.has(key)) return false;
|
|
5422
|
+
reservation.awaitingAdoption = false;
|
|
5423
|
+
retireAcceptedImage(key);
|
|
5424
|
+
return true;
|
|
5425
|
+
},
|
|
5426
|
+
};
|
|
5427
|
+
};
|
|
5428
|
+
const releaseAcceptedImage = (correlation: { commandId: string; turnId: string }): void =>
|
|
5429
|
+
retireAcceptedImage(promptSubmissionKey(correlation));
|
|
5430
|
+
const releaseAcceptedImagesForRun = (owner: AgentTerminalOwnerContext): void => {
|
|
5431
|
+
for (const [key, runOwner] of acceptedImageRunOwners) {
|
|
5432
|
+
if (!runOwner || runOwner.resourceRunId !== owner.resourceRunId || runOwner.domain !== owner.domain)
|
|
5433
|
+
continue;
|
|
5434
|
+
retireAcceptedImage(key);
|
|
5435
|
+
}
|
|
5436
|
+
};
|
|
5437
|
+
const releaseAcceptedImages = (): void => {
|
|
5438
|
+
for (const key of acceptedImages.keys()) retireAcceptedImage(key);
|
|
5439
|
+
};
|
|
5113
5440
|
type PromptLifecycleFrame =
|
|
5114
5441
|
| {
|
|
5115
5442
|
type: "agent_start" | "agent_end";
|
|
@@ -5815,7 +6142,7 @@ export function createNotificationsExtension(
|
|
|
5815
6142
|
);
|
|
5816
6143
|
};
|
|
5817
6144
|
const emitPromptEvent = (event: AgentSessionEvent) => {
|
|
5818
|
-
if (!runtime) return;
|
|
6145
|
+
if (!runtime || runtime.stopping || runtime.serverStopped || runtimes.get(id) !== runtime) return;
|
|
5819
6146
|
cleanupPromptRecords();
|
|
5820
6147
|
const handle = ctx.getActivePromptHandle();
|
|
5821
6148
|
const domain = handle ? terminalAbortSeams?.getRunOwnerDomain?.(handle) : undefined;
|
|
@@ -5828,12 +6155,14 @@ export function createNotificationsExtension(
|
|
|
5828
6155
|
)
|
|
5829
6156
|
)
|
|
5830
6157
|
correlations.unshift(root);
|
|
6158
|
+
const owners = new Set<string>();
|
|
5831
6159
|
for (const correlation of correlations) {
|
|
5832
6160
|
// Renewal is attributed exactly like the correlated delivery below.
|
|
5833
6161
|
renewPromptDeadline(correlation, event);
|
|
5834
6162
|
noteToolDispatchBoundary(correlation, event);
|
|
5835
6163
|
const submission = promptSubmissions.get(promptSubmissionKey(correlation));
|
|
5836
6164
|
if (!submission || submission.abandoned) continue;
|
|
6165
|
+
owners.add(submission.connectionId);
|
|
5837
6166
|
const frame = {
|
|
5838
6167
|
type: "event",
|
|
5839
6168
|
kind: event.type,
|
|
@@ -5846,6 +6175,25 @@ export function createNotificationsExtension(
|
|
|
5846
6175
|
}
|
|
5847
6176
|
deliverCorrelatedFrame(submission, frame);
|
|
5848
6177
|
}
|
|
6178
|
+
// Broker-created hosts use this bus, not the SDK-only extension. Observers
|
|
6179
|
+
// must opt into BOTH capabilities and receive no other client's correlation.
|
|
6180
|
+
// Keep cumulative partialResult snapshots and authoritative final result
|
|
6181
|
+
// intact, and off the durable lifecycle replay ring, like owner content.
|
|
6182
|
+
for (const connectionId of sdkRuntime?.connectionIdsWithCapabilities([
|
|
6183
|
+
TURN_STREAM_CAPABILITY,
|
|
6184
|
+
SESSION_HOST_OBSERVER_CAPABILITY,
|
|
6185
|
+
]) ?? []) {
|
|
6186
|
+
if (owners.has(connectionId)) continue;
|
|
6187
|
+
try {
|
|
6188
|
+
sdkRuntime?.sendFrameTo(connectionId, {
|
|
6189
|
+
type: "event",
|
|
6190
|
+
kind: event.type,
|
|
6191
|
+
payload: toAgentWireEventPayload(event),
|
|
6192
|
+
});
|
|
6193
|
+
} catch {
|
|
6194
|
+
// Content delivery is best-effort and must not interrupt execution.
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
5849
6197
|
};
|
|
5850
6198
|
/**
|
|
5851
6199
|
* Status of a registered deadline expiry attempt after an awaited
|
|
@@ -6165,6 +6513,7 @@ export function createNotificationsExtension(
|
|
|
6165
6513
|
logger.warn(`sdk: failed to cancel fenced preflight: ${String(error)}`),
|
|
6166
6514
|
);
|
|
6167
6515
|
fencedConnections.add(submission.connectionId);
|
|
6516
|
+
imageUploads?.disconnect(submission.connectionId);
|
|
6168
6517
|
host?.handleDisconnect(submission.connectionId);
|
|
6169
6518
|
for (const [key, owned] of promptSubmissions)
|
|
6170
6519
|
if (owned.connectionId === submission.connectionId) {
|
|
@@ -6197,6 +6546,21 @@ export function createNotificationsExtension(
|
|
|
6197
6546
|
submission.executionHandle = handle;
|
|
6198
6547
|
submission.preflightAbort = undefined;
|
|
6199
6548
|
}
|
|
6549
|
+
if (acceptedImages.has(key) && !acceptedImageRunOwners.has(key)) {
|
|
6550
|
+
acceptedImageRunOwners.set(key, undefined);
|
|
6551
|
+
const domain = handle ? terminalAbortSeams?.getRunOwnerDomain?.(handle) : undefined;
|
|
6552
|
+
if (handle && domain) acceptedImageRunOwners.set(key, { resourceRunId: handle, domain });
|
|
6553
|
+
}
|
|
6554
|
+
const imageReservation = acceptedImages.get(key);
|
|
6555
|
+
if (
|
|
6556
|
+
imageReservation?.accepted &&
|
|
6557
|
+
!imageReservation.preflightSignal.aborted &&
|
|
6558
|
+
acceptedImageRunOwners.get(key)
|
|
6559
|
+
) {
|
|
6560
|
+
imageReservation.awaitingAdoption = false;
|
|
6561
|
+
settleAcceptedImageSubmission(key, imageReservation);
|
|
6562
|
+
if (imageReservation.releaseRequested) retireAcceptedImage(key);
|
|
6563
|
+
}
|
|
6200
6564
|
};
|
|
6201
6565
|
const onPromptDiverted = (correlation: { commandId: string; turnId: string }) => {
|
|
6202
6566
|
const submission = promptSubmissions.get(promptSubmissionKey(correlation));
|
|
@@ -6384,6 +6748,7 @@ export function createNotificationsExtension(
|
|
|
6384
6748
|
return;
|
|
6385
6749
|
}
|
|
6386
6750
|
if (capture) capture.proof = proof;
|
|
6751
|
+
releaseAcceptedImage(correlation);
|
|
6387
6752
|
}
|
|
6388
6753
|
if (deadlineAttempt) {
|
|
6389
6754
|
// Durability BEFORE the durable terminal (#5583, #5623 review round 4).
|
|
@@ -6408,21 +6773,12 @@ export function createNotificationsExtension(
|
|
|
6408
6773
|
if (
|
|
6409
6774
|
winner.kind === "failed" &&
|
|
6410
6775
|
winner.code === "prompt_deadline_exceeded" &&
|
|
6411
|
-
settings
|
|
6776
|
+
!deadlineFlushSuppressed(settings)
|
|
6412
6777
|
) {
|
|
6413
|
-
//
|
|
6414
|
-
//
|
|
6415
|
-
// honours the default inside a linked worktree the session owns.
|
|
6416
|
-
const configured = settings?.get("sdk.flushWorktreeOnDeadline");
|
|
6417
|
-
const hasExplicitSetting =
|
|
6418
|
-
typeof settings?.has === "function"
|
|
6419
|
-
? settings.has("sdk.flushWorktreeOnDeadline")
|
|
6420
|
-
: configured === true;
|
|
6421
|
-
const explicitOptIn = hasExplicitSetting === true && configured === true;
|
|
6778
|
+
// Same opt-in as the session runtime: user/global config or a runtime
|
|
6779
|
+
// override, never a project `.gjc` file or the schema default.
|
|
6422
6780
|
await runBoundedDeadlineFlush(signal =>
|
|
6423
|
-
|
|
6424
|
-
agentDir: settings?.getAgentDir(),
|
|
6425
|
-
explicitOptIn,
|
|
6781
|
+
autosaveWorktreeOnPromptDeadline(ctx.cwd, settings, {
|
|
6426
6782
|
isCurrent: () =>
|
|
6427
6783
|
deadlineAttemptStatus(promptSubmissionKey(correlation), submission, deadlineAttempt) ===
|
|
6428
6784
|
"current",
|
|
@@ -6611,7 +6967,8 @@ export function createNotificationsExtension(
|
|
|
6611
6967
|
};
|
|
6612
6968
|
const recordPromptFailure = async (correlation: { commandId: string; turnId: string }, error: unknown) => {
|
|
6613
6969
|
const submission = promptSubmissions.get(promptSubmissionKey(correlation));
|
|
6614
|
-
if (!submission) return;
|
|
6970
|
+
if (!submission || submission.terminal || submission.failed) return;
|
|
6971
|
+
releaseAcceptedImage(correlation);
|
|
6615
6972
|
submission.failed = true;
|
|
6616
6973
|
removePendingPromptCorrelation(correlation);
|
|
6617
6974
|
if (
|
|
@@ -6621,6 +6978,29 @@ export function createNotificationsExtension(
|
|
|
6621
6978
|
runtime.activePromptCorrelation = undefined;
|
|
6622
6979
|
await emitPromptFailure(correlation, error);
|
|
6623
6980
|
};
|
|
6981
|
+
const recordQueuedRunStartFailure = (
|
|
6982
|
+
correlation: { commandId: string; turnId: string },
|
|
6983
|
+
failure: QueuedRunStartFailure,
|
|
6984
|
+
sdkRunToken: string | undefined,
|
|
6985
|
+
refuseImage: (() => boolean) | undefined,
|
|
6986
|
+
): boolean => {
|
|
6987
|
+
const key = promptSubmissionKey(correlation);
|
|
6988
|
+
const submission = promptSubmissions.get(key);
|
|
6989
|
+
// A present undefined owner is already-started execution, not no-start evidence.
|
|
6990
|
+
if (
|
|
6991
|
+
failure.disposition !== "not-started" ||
|
|
6992
|
+
(submission && submission.sdkRunToken !== sdkRunToken) ||
|
|
6993
|
+
submission?.executionHandle !== undefined ||
|
|
6994
|
+
acceptedImageRunOwners.has(key)
|
|
6995
|
+
)
|
|
6996
|
+
return false;
|
|
6997
|
+
// Reservation proof outlives the mutable receipt. The captured lifecycle
|
|
6998
|
+
// checks reservation identity and keeps the pending producer fenced.
|
|
6999
|
+
if (refuseImage ? !refuseImage() : !submission) return false;
|
|
7000
|
+
if (submission && !submission.terminal && !submission.failed)
|
|
7001
|
+
trackReconciliationProducer(recordPromptFailure(correlation, failure.error));
|
|
7002
|
+
return true;
|
|
7003
|
+
};
|
|
6624
7004
|
const acknowledgePrompt = (connectionId: string, correlation: { commandId: string; turnId: string }) => {
|
|
6625
7005
|
const key = promptSubmissionKey(correlation);
|
|
6626
7006
|
const submission = promptSubmissions.get(key);
|
|
@@ -6653,6 +7033,7 @@ export function createNotificationsExtension(
|
|
|
6653
7033
|
selector => kindReconciliation.lookupSteer(selector),
|
|
6654
7034
|
() => host,
|
|
6655
7035
|
options.primaryControlSurface ?? "sdk",
|
|
7036
|
+
imageUploadsAvailable,
|
|
6656
7037
|
),
|
|
6657
7038
|
id,
|
|
6658
7039
|
revisions,
|
|
@@ -6663,12 +7044,17 @@ export function createNotificationsExtension(
|
|
|
6663
7044
|
pendingInteractive,
|
|
6664
7045
|
gatePresentations,
|
|
6665
7046
|
api,
|
|
7047
|
+
imageUploads,
|
|
7048
|
+
imageUploadsAvailable,
|
|
7049
|
+
retainAcceptedImage,
|
|
7050
|
+
releaseAcceptedImage,
|
|
6666
7051
|
() =>
|
|
6667
7052
|
runtime?.busy === true ||
|
|
6668
7053
|
pendingPromptCorrelations.length > 0 ||
|
|
6669
7054
|
pendingPromptCorrelationsBySdkRunToken.size > 0,
|
|
6670
7055
|
recordPromptAccepted,
|
|
6671
7056
|
recordPromptFailure,
|
|
7057
|
+
recordQueuedRunStartFailure,
|
|
6672
7058
|
discardPromptAcceptance,
|
|
6673
7059
|
onPromptDiverted,
|
|
6674
7060
|
onPromptPromoted,
|
|
@@ -6732,11 +7118,19 @@ export function createNotificationsExtension(
|
|
|
6732
7118
|
await terminalizePrompt({ commandId, turnId }, cancellationOutcome, {
|
|
6733
7119
|
fence: hasExecutionHandle || !submission.preflightAbort,
|
|
6734
7120
|
});
|
|
7121
|
+
if (!hasExecutionHandle && submission.preflightAbort) releaseAcceptedImage({ commandId, turnId });
|
|
6735
7122
|
}
|
|
6736
7123
|
}
|
|
6737
7124
|
return { aborted: true, disposition: "cancelled" as const };
|
|
6738
7125
|
},
|
|
6739
|
-
async (
|
|
7126
|
+
async (
|
|
7127
|
+
connectionId,
|
|
7128
|
+
scope,
|
|
7129
|
+
idempotencyKey,
|
|
7130
|
+
preflightCancel,
|
|
7131
|
+
noOtherConnectionPreflights,
|
|
7132
|
+
operatorAuthorized = false,
|
|
7133
|
+
) => {
|
|
6740
7134
|
// Capture the steering snapshot at ADMISSION (before the durable
|
|
6741
7135
|
// marker transaction): client steering admitted while the abort
|
|
6742
7136
|
// is in flight classifies as post-snapshot and is preserved at
|
|
@@ -7098,9 +7492,9 @@ export function createNotificationsExtension(
|
|
|
7098
7492
|
return "failed";
|
|
7099
7493
|
}
|
|
7100
7494
|
};
|
|
7101
|
-
|
|
7102
|
-
(
|
|
7103
|
-
);
|
|
7495
|
+
const addresses = (submission: TerminalAbortSubmissionScope): boolean =>
|
|
7496
|
+
terminalAbortAddressesSubmission({ connectionId, operatorAuthorized, submission });
|
|
7497
|
+
let active = [...promptSubmissions.entries()].find(([, submission]) => addresses(submission));
|
|
7104
7498
|
if (!active) {
|
|
7105
7499
|
// DURABLY reserve the key even for a no-active-turn abort: the
|
|
7106
7500
|
// generic idempotency cache is in-memory only, so after restart
|
|
@@ -7130,9 +7524,7 @@ export function createNotificationsExtension(
|
|
|
7130
7524
|
// and the durable no-effect row would block a same-key retry from
|
|
7131
7525
|
// stopping it — fall through to the pre-run / active fencing path
|
|
7132
7526
|
// when a submission now exists (review thread P1).
|
|
7133
|
-
active = [...promptSubmissions.entries()].find(
|
|
7134
|
-
([, submission]) => submission.connectionId === connectionId && !submission.terminal,
|
|
7135
|
-
);
|
|
7527
|
+
active = [...promptSubmissions.entries()].find(([, submission]) => addresses(submission));
|
|
7136
7528
|
if (!active) {
|
|
7137
7529
|
// Close the remaining acceptance race: cancel the requester's
|
|
7138
7530
|
// preflights HERE, in the same synchronous region as the
|
|
@@ -8157,6 +8549,10 @@ export function createNotificationsExtension(
|
|
|
8157
8549
|
runtime = {
|
|
8158
8550
|
server,
|
|
8159
8551
|
host,
|
|
8552
|
+
imageUploads,
|
|
8553
|
+
releaseAcceptedImage,
|
|
8554
|
+
releaseAcceptedImagesForRun,
|
|
8555
|
+
releaseAcceptedImages,
|
|
8160
8556
|
getJoinedPromptCorrelations,
|
|
8161
8557
|
isPromptRunOwner: (correlation, owner) => {
|
|
8162
8558
|
const handle = promptSubmissions.get(promptSubmissionKey(correlation))?.executionHandle;
|
|
@@ -8296,6 +8692,7 @@ export function createNotificationsExtension(
|
|
|
8296
8692
|
string,
|
|
8297
8693
|
{ toolName: string; args?: unknown; pendingPhase?: "completed" | "failed" | "cancelled" }
|
|
8298
8694
|
>(),
|
|
8695
|
+
awaitingInput: new Map(),
|
|
8299
8696
|
deferredInboundControls: [],
|
|
8300
8697
|
};
|
|
8301
8698
|
const initializedRuntime = runtime;
|
|
@@ -8415,7 +8812,18 @@ export function createNotificationsExtension(
|
|
|
8415
8812
|
sendEndpointStale(inbound.connectionId, typedFrame);
|
|
8416
8813
|
return;
|
|
8417
8814
|
}
|
|
8815
|
+
if (typedFrame.type === "control_request" && !liveHostConnection(inbound.connectionId)) {
|
|
8816
|
+
sendEndpointStale(inbound.connectionId, typedFrame);
|
|
8817
|
+
return;
|
|
8818
|
+
}
|
|
8418
8819
|
if (typedFrame.type === "event_replay") {
|
|
8820
|
+
const capabilities = typedFrame.capabilities;
|
|
8821
|
+
if (
|
|
8822
|
+
Array.isArray(capabilities) &&
|
|
8823
|
+
capabilities.every((capability: unknown) => typeof capability === "string")
|
|
8824
|
+
) {
|
|
8825
|
+
rememberHostCapabilities(inbound.connectionId, capabilities as string[], "replay");
|
|
8826
|
+
}
|
|
8419
8827
|
if (liveHostConnection(inbound.connectionId)) hostAttachedConnections.add(inbound.connectionId);
|
|
8420
8828
|
}
|
|
8421
8829
|
if (typedFrame.type === "ephemeral_turn" || typedFrame.type === "ephemeral_turn_cancel") return;
|
|
@@ -8460,7 +8868,7 @@ export function createNotificationsExtension(
|
|
|
8460
8868
|
const negotiated = tuple?.[1] ?? capabilities;
|
|
8461
8869
|
if (typeof id !== "string" || !Array.isArray(negotiated)) return;
|
|
8462
8870
|
const normalized = negotiated.filter((capability): capability is string => typeof capability === "string");
|
|
8463
|
-
rememberHostCapabilities(id, normalized);
|
|
8871
|
+
rememberHostCapabilities(id, normalized, "native");
|
|
8464
8872
|
if (liveHostCapabilities(id) === undefined) return;
|
|
8465
8873
|
hostAttachedConnections.add(id);
|
|
8466
8874
|
negotiatedCapabilitiesHandler?.(id, normalized);
|
|
@@ -8468,6 +8876,7 @@ export function createNotificationsExtension(
|
|
|
8468
8876
|
server.onConnectionClose((_err, connectionId) => {
|
|
8469
8877
|
if (!connectionId) return;
|
|
8470
8878
|
closeHostConnection(connectionId);
|
|
8879
|
+
imageUploads?.disconnect(connectionId);
|
|
8471
8880
|
connectionCloseHandler?.(connectionId);
|
|
8472
8881
|
void controlSurface
|
|
8473
8882
|
.cancelPendingPreflightsForConnection(connectionId)
|
|
@@ -9003,8 +9412,10 @@ export function createNotificationsExtension(
|
|
|
9003
9412
|
attachedClients: () => server.clientCount(),
|
|
9004
9413
|
observerClients: () => {
|
|
9005
9414
|
if (workLease.isHeld()) return 0;
|
|
9006
|
-
const observers = [...hostCapCache.
|
|
9007
|
-
|
|
9415
|
+
const observers = [...hostCapCache.entries()].filter(
|
|
9416
|
+
([connectionId, entry]) =>
|
|
9417
|
+
liveHostCapabilities(connectionId)?.has(SESSION_HOST_OBSERVER_CAPABILITY) &&
|
|
9418
|
+
entry.nativeConfirmed.has(SESSION_HOST_OBSERVER_CAPABILITY),
|
|
9008
9419
|
).length;
|
|
9009
9420
|
return Math.min(server.clientCount(), observers);
|
|
9010
9421
|
},
|
|
@@ -9459,6 +9870,7 @@ export function createNotificationsExtension(
|
|
|
9459
9870
|
runtime.gatePresentations?.activateDeferred(runtime.workflowGatePublicationEpoch);
|
|
9460
9871
|
flushPendingFinal(runtime, runtime.id);
|
|
9461
9872
|
flushPendingSettled(runtime, runtime.id);
|
|
9873
|
+
deliverAwaitingInput(runtime, runtime.id);
|
|
9462
9874
|
for (const processControl of runtime.deferredInboundControls.splice(0)) processControl();
|
|
9463
9875
|
},
|
|
9464
9876
|
reproveOwnership: async binding => {
|
|
@@ -10069,6 +10481,7 @@ export function createNotificationsExtension(
|
|
|
10069
10481
|
// The Agent's terminal owner is independent of delivery correlation. Never
|
|
10070
10482
|
// borrow a successor's run handle to settle a predecessor's SDK prompts.
|
|
10071
10483
|
const terminalOwner = terminalAbortSeams?.getTerminalRunOwnerForEvent?.(event);
|
|
10484
|
+
if (terminalOwner) rt.releaseAcceptedImagesForRun(terminalOwner);
|
|
10072
10485
|
const rootCorrelation = rt.activePromptCorrelation;
|
|
10073
10486
|
const correlations = terminalOwner ? rt.getJoinedPromptCorrelations(terminalOwner) : [];
|
|
10074
10487
|
if (
|
|
@@ -10085,6 +10498,7 @@ export function createNotificationsExtension(
|
|
|
10085
10498
|
// subsequent durable terminal claim fails. A fatal transport closure
|
|
10086
10499
|
// clears attribution, so an unrelated later agent_end cannot settle a
|
|
10087
10500
|
// predecessor's prompt correlation.
|
|
10501
|
+
if (terminalOwner) rt.releaseAcceptedImage(correlation);
|
|
10088
10502
|
const assistants = (Array.isArray(event.messages) ? [...event.messages].reverse() : []).filter(
|
|
10089
10503
|
message => message && typeof message === "object" && (message as { role?: unknown }).role === "assistant",
|
|
10090
10504
|
) as Array<{ stopReason?: unknown; errorKind?: unknown; errorCode?: unknown }>;
|
|
@@ -10360,8 +10774,18 @@ export function createNotificationsExtension(
|
|
|
10360
10774
|
});
|
|
10361
10775
|
|
|
10362
10776
|
api.on("tool_execution_update", (event, ctx) => {
|
|
10363
|
-
const
|
|
10777
|
+
const id = sessionId(ctx);
|
|
10778
|
+
const rt = runtimes.get(id);
|
|
10364
10779
|
rt?.emitPromptEvent(event);
|
|
10780
|
+
if (!rt) return;
|
|
10781
|
+
const awaitingInput = readAwaitingInput(event.partialResult);
|
|
10782
|
+
if (!awaitingInput || rt.awaitingInput.has(event.toolCallId)) return;
|
|
10783
|
+
// Notify-only and content-free (prompt kind only, never the URL or code), so
|
|
10784
|
+
// it is delivered under redaction exactly like the idle marker. While policy
|
|
10785
|
+
// is provisional it stays pending; activation delivers it if the call is
|
|
10786
|
+
// still running.
|
|
10787
|
+
rt.awaitingInput.set(event.toolCallId, { toolName: event.toolName, kind: awaitingInput.kind, delivered: false });
|
|
10788
|
+
deliverAwaitingInput(rt, id);
|
|
10365
10789
|
});
|
|
10366
10790
|
|
|
10367
10791
|
api.on("tool_execution_end", (event, ctx) => {
|
|
@@ -10369,6 +10793,7 @@ export function createNotificationsExtension(
|
|
|
10369
10793
|
const rt = runtimes.get(id);
|
|
10370
10794
|
if (!rt) return;
|
|
10371
10795
|
rt.emitPromptEvent(event);
|
|
10796
|
+
rt.awaitingInput.delete(event.toolCallId);
|
|
10372
10797
|
const inFlight = rt.inFlightTools.get(event.toolCallId);
|
|
10373
10798
|
if (!inFlight) return;
|
|
10374
10799
|
if (!rt.notificationsActive) {
|