@sayknow-cli/coding-agent 0.4.7 → 0.5.1
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 +122 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/cli/read-cli.d.ts +1 -0
- package/dist/types/cli.d.ts +9 -1
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/deep-interview.d.ts +9 -0
- package/dist/types/commands/harness.d.ts +22 -0
- package/dist/types/commands/read.d.ts +6 -0
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-contract.d.ts +40 -0
- package/dist/types/config/model-profiles.d.ts +2 -3
- package/dist/types/config/model-registry.d.ts +5 -0
- package/dist/types/config/provider-auth-health.d.ts +14 -0
- package/dist/types/config/provider-ranking.d.ts +59 -0
- package/dist/types/config/settings-schema.d.ts +156 -10
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/extensibility/extensions/types.d.ts +43 -2
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
- package/dist/types/main.d.ts +33 -2
- package/dist/types/memories/index.d.ts +2 -0
- package/dist/types/modes/acp/acp-agent.d.ts +22 -9
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
- package/dist/types/modes/components/queue-pane.d.ts +8 -0
- package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
- package/dist/types/modes/components/read-tool-group.d.ts +4 -4
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +5 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/event-controller.d.ts +3 -0
- package/dist/types/modes/interactive-mode.d.ts +13 -2
- package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +6 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
- package/dist/types/runtime/memory-domain.d.ts +9 -0
- package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
- package/dist/types/runtime/memory-guard.d.ts +39 -0
- package/dist/types/runtime/memory-limit.d.ts +11 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +1 -1
- package/dist/types/runtime-mcp/manager.d.ts +9 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/runtime-mcp/redaction.d.ts +2 -0
- package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
- package/dist/types/sdk/acp/final-text.d.ts +19 -0
- package/dist/types/sdk/acp/mcp.d.ts +23 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +13 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +9 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +52 -4
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +106 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +33 -9
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +286 -12
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/host.d.ts +3 -1
- package/dist/types/sdk/host/query/handlers.d.ts +14 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/lifecycle-session.d.ts +10 -1
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +7 -0
- package/dist/types/sdk/startup-capability.d.ts +9 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +83 -24
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/fallback-chain-controller.d.ts +18 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +70 -10
- package/dist/types/session/internal/managed-session-storage.d.ts +34 -12
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
- package/dist/types/session/session-manager.d.ts +89 -18
- package/dist/types/session/session-storage.d.ts +31 -0
- package/dist/types/session/streaming-output.d.ts +60 -5
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/skc-runtime/deep-interview-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/deep-interview-stage.d.ts +37 -0
- package/dist/types/skc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/linux-proc.d.ts +22 -14
- package/dist/types/skc-runtime/memory-guard-owner-claims.d.ts +47 -0
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +112 -1
- package/dist/types/skc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/skc-runtime/state-runtime.d.ts +3 -1
- package/dist/types/skc-runtime/state-writer.d.ts +5 -1
- package/dist/types/skc-runtime/team-launch.d.ts +1 -1
- package/dist/types/skc-runtime/team-runtime.d.ts +9 -2
- package/dist/types/skc-runtime/team-store.d.ts +12 -0
- package/dist/types/skc-runtime/team-worker-memory-guard.d.ts +92 -0
- package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +7 -0
- package/dist/types/skc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +28 -0
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/skill-state/workflow-hud.d.ts +3 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/executor.d.ts +6 -0
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/provider-retry-status.d.ts +13 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +133 -0
- package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
- package/dist/types/tools/browser/launch.d.ts +7 -0
- package/dist/types/tools/fetch.d.ts +22 -9
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +7 -1
- package/dist/types/tools/output-meta.d.ts +21 -1
- package/dist/types/tools/read-internals.d.ts +12 -0
- package/dist/types/tools/read.d.ts +45 -1
- package/dist/types/tools/resource-gc.d.ts +23 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/tools/tool-result.d.ts +7 -1
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -12
- package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/capture-sticky-viewport-showcase.ts +292 -0
- package/scripts/compile-args.ts +0 -1
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-docs-index.ts +4 -1
- package/scripts/generate-sdk-operation-inventory.ts +9 -0
- package/scripts/run-test-manifest.ts +6 -4
- package/scripts/verify-skc-sdk-canonicalization.ts +122 -18
- package/scripts/verify-sticky-viewport-showcase.ts +611 -0
- package/src/capability/index.ts +58 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +16 -100
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/mcp-cli.ts +4 -21
- package/src/cli/notify-cli.ts +6 -38
- package/src/cli/read-cli.ts +2 -1
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +133 -11
- package/src/commands/daemon.ts +22 -5
- package/src/commands/deep-interview.ts +26 -1
- package/src/commands/harness.ts +35 -12
- package/src/commands/read.ts +11 -2
- package/src/commands/sdk.ts +134 -17
- package/src/commands/team.ts +1 -1
- package/src/commit/agentic/index.ts +3 -3
- package/src/commit/map-reduce/index.ts +2 -2
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-contract.ts +174 -0
- package/src/config/model-profiles.ts +51 -10
- package/src/config/model-registry.ts +24 -4
- package/src/config/model-resolver.ts +2 -2
- package/src/config/provider-auth-health.ts +42 -0
- package/src/config/provider-ranking.ts +119 -0
- package/src/config/settings-schema.ts +157 -10
- package/src/config/settings.ts +254 -108
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/skc/skills/deep-interview/SKILL.md +147 -24
- package/src/defaults/skc/skills/ralplan/SKILL.md +91 -34
- package/src/defaults/skc/skills/team/SKILL.md +1 -1
- package/src/defaults/skc/skills/ultragoal/SKILL.md +68 -17
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/js/tool-bridge.ts +1 -1
- package/src/eval/py/executor.ts +37 -13
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +42 -4
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/extensibility/shared-events.ts +5 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +2 -1
- package/src/hooks/native-skill-hook.ts +17 -4
- package/src/internal-urls/docs-index.generated.ts +17 -16
- package/src/internal-urls/local-protocol.ts +87 -25
- package/src/internal-urls/local-root-gc.ts +127 -0
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +120 -42
- package/src/memories/index.ts +10 -0
- package/src/modes/DESIGN.md +52 -0
- package/src/modes/acp/acp-agent.ts +647 -83
- package/src/modes/acp/acp-event-mapper.ts +106 -12
- package/src/modes/acp/acp-mode.ts +39 -3
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/assistant-message.ts +123 -22
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/irc-sidebar.ts +176 -62
- package/src/modes/components/model-selector.ts +61 -4
- package/src/modes/components/notifications-settings-editor.ts +1 -1
- package/src/modes/components/oauth-selector.ts +42 -12
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/queue-pane.ts +55 -9
- package/src/modes/components/queued-message-selector.ts +53 -10
- package/src/modes/components/read-tool-group.ts +82 -14
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/sayknow-pet-widget.ts +20 -8
- package/src/modes/components/session-observer-overlay.ts +187 -32
- package/src/modes/components/settings-selector.ts +60 -18
- package/src/modes/components/tool-execution.ts +138 -27
- package/src/modes/components/tool-status-header.ts +26 -8
- package/src/modes/components/welcome.ts +50 -23
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +101 -54
- package/src/modes/controllers/event-controller.ts +119 -27
- package/src/modes/controllers/extension-ui-controller.ts +23 -12
- package/src/modes/controllers/input-controller.ts +100 -8
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +4 -1
- package/src/modes/interactive-mode.ts +201 -60
- package/src/modes/irc-observation-ledger.ts +71 -15
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/runtime-init.ts +20 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +3 -3
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +6 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +99 -4
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/architect.md +17 -3
- package/src/prompts/agents/critic.md +17 -2
- package/src/prompts/agents/executor.md +1 -1
- package/src/prompts/agents/planner.md +8 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -3
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/read.md +4 -2
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime/memory-domain.ts +66 -0
- package/src/runtime/memory-guard-contract.ts +73 -0
- package/src/runtime/memory-guard.ts +292 -0
- package/src/runtime/memory-limit.ts +50 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/discoverable-tool-metadata.ts +1 -1
- package/src/runtime-mcp/json-rpc.ts +28 -11
- package/src/runtime-mcp/manager.ts +77 -59
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/redaction.ts +30 -0
- package/src/runtime-mcp/smithery-auth.ts +17 -2
- package/src/runtime-mcp/smithery-connect.ts +11 -1
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/acp/adapter.ts +8 -1
- package/src/sdk/acp/final-text.ts +40 -0
- package/src/sdk/acp/mcp.ts +26 -0
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/identity.ts +22 -12
- package/src/sdk/broker/lifecycle.ts +293 -43
- package/src/sdk/broker/session-index.ts +11 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -2
- package/src/sdk/bus/chat-daemon-control.ts +22 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +10 -2
- package/src/sdk/bus/control-drain-lease.ts +104 -0
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/index.ts +793 -121
- package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +87 -25
- package/src/sdk/bus/operator-runtime.ts +31 -5
- package/src/sdk/bus/prompt-reconciliation.ts +240 -0
- package/src/sdk/bus/rate-limit-pool.ts +8 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/reconciliation-store.ts +224 -0
- package/src/sdk/bus/telegram-cli.ts +6 -13
- package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +34 -9
- package/src/sdk/bus/telegram-daemon-control.ts +161 -40
- package/src/sdk/bus/telegram-daemon.ts +3649 -593
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +8 -2
- package/src/sdk/host/control/operations.ts +3 -2
- package/src/sdk/host/host.ts +27 -9
- package/src/sdk/host/query/handlers.ts +125 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/lifecycle-session.ts +19 -3
- package/src/sdk/mcp/server.ts +46 -18
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +145 -0
- package/src/sdk/protocol/operation-registry.ts +24 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +69 -8
- package/src/sdk/startup-capability.ts +15 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +1112 -314
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/fallback-chain-controller.ts +47 -8
- package/src/session/internal/managed-session-scope.ts +1426 -259
- package/src/session/internal/managed-session-storage.ts +414 -238
- package/src/session/internal/native-publish-outcome.ts +271 -0
- package/src/session/memory-guard-checkpoint-participant.ts +131 -0
- package/src/session/session-manager.ts +2079 -469
- package/src/session/session-storage.ts +151 -11
- package/src/session/streaming-output.ts +262 -43
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +49 -5
- package/src/setup/provider-presets.json +2 -1
- package/src/skc-runtime/deep-interview-runtime.ts +303 -36
- package/src/skc-runtime/deep-interview-stage.ts +1016 -0
- package/src/skc-runtime/deep-interview-state.ts +8 -5
- package/src/skc-runtime/gc-render.ts +1 -0
- package/src/skc-runtime/gc-runtime.ts +11 -1
- package/src/skc-runtime/linux-proc.ts +70 -36
- package/src/skc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/skc-runtime/memory-guard-owner-claims.ts +389 -0
- package/src/skc-runtime/ralplan-runtime.ts +1057 -75
- package/src/skc-runtime/repository-binding.ts +267 -0
- package/src/skc-runtime/session-state-sidecar.ts +25 -9
- package/src/skc-runtime/state-runtime.ts +50 -12
- package/src/skc-runtime/state-writer.ts +68 -56
- package/src/skc-runtime/team-launch.ts +34 -5
- package/src/skc-runtime/team-runtime.ts +41 -1
- package/src/skc-runtime/team-store.ts +32 -0
- package/src/skc-runtime/team-worker-memory-guard.ts +363 -0
- package/src/skc-runtime/team-workers.ts +1 -0
- package/src/skc-runtime/tmux-common.ts +13 -2
- package/src/skc-runtime/tmux-owner-isolation.ts +20 -1
- package/src/skc-runtime/tmux-sessions.ts +45 -6
- package/src/skc-runtime/ultragoal-guard.ts +93 -15
- package/src/skc-runtime/ultragoal-receipt-freshness.ts +123 -0
- package/src/skc-runtime/ultragoal-runtime.ts +469 -38
- package/src/skc-runtime/workflow-manifest.generated.json +195 -5
- package/src/skc-runtime/workflow-manifest.ts +67 -3
- package/src/skill-state/workflow-hud.ts +25 -2
- package/src/skill-state/workflow-mutation-guard.ts +104 -12
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/executor.ts +165 -47
- package/src/task/index.ts +123 -15
- package/src/task/provider-retry-status.ts +88 -0
- package/src/task/receipt.ts +3 -0
- package/src/task/render.ts +45 -26
- package/src/task/skc-command.ts +2 -2
- package/src/task/types.ts +55 -10
- package/src/task/ultragoal-redteam-activation.ts +75 -0
- package/src/tools/ask.ts +1 -1
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-allowed-prefixes.ts +45 -1
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/launch.ts +41 -6
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +127 -154
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +7 -1
- package/src/tools/output-meta.ts +176 -9
- package/src/tools/path-utils.ts +5 -1
- package/src/tools/read-internals.ts +44 -0
- package/src/tools/read.ts +1544 -310
- package/src/tools/resource-gc.ts +665 -125
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/tools/subagent-render.ts +74 -16
- package/src/tools/subagent.ts +2 -0
- package/src/tools/tool-result.ts +14 -1
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
- package/src/web/search/providers/codex.ts +1 -1
- package/src/workflow/workflow-intent-diff.ts +4 -1
|
@@ -6,6 +6,8 @@ export interface SdkSessionEndpoint {
|
|
|
6
6
|
sessionId: string;
|
|
7
7
|
url: string;
|
|
8
8
|
token: string;
|
|
9
|
+
pid?: number;
|
|
10
|
+
stale?: boolean;
|
|
9
11
|
path: string;
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -38,12 +40,26 @@ function endpointDirectory(repo: string): string {
|
|
|
38
40
|
function parseEndpoint(sessionId: string, file: string, value: unknown): SdkSessionEndpoint {
|
|
39
41
|
if (!value || typeof value !== "object")
|
|
40
42
|
throw new SdkDiscoveryError(file, "SDK endpoint discovery record must be an object.");
|
|
41
|
-
const endpoint = value as { version?: unknown; url?: unknown; token?: unknown };
|
|
43
|
+
const endpoint = value as { version?: unknown; url?: unknown; token?: unknown; pid?: unknown; stale?: unknown };
|
|
42
44
|
if (typeof endpoint.version === "number" && endpoint.version > 1)
|
|
43
45
|
throw new SdkDiscoveryError(file, "Unsupported SDK endpoint discovery state version.");
|
|
44
|
-
if (typeof endpoint.url !== "string" ||
|
|
46
|
+
if (typeof endpoint.url !== "string" || !endpoint.url)
|
|
45
47
|
throw new SdkDiscoveryError(file, "SDK endpoint discovery record is invalid.");
|
|
46
|
-
|
|
48
|
+
const stale = typeof endpoint.stale === "boolean" ? endpoint.stale : undefined;
|
|
49
|
+
const pid =
|
|
50
|
+
typeof endpoint.pid === "number" && Number.isInteger(endpoint.pid) && endpoint.pid > 0 ? endpoint.pid : undefined;
|
|
51
|
+
if (endpoint.token !== undefined && typeof endpoint.token !== "string")
|
|
52
|
+
throw new SdkDiscoveryError(file, "SDK endpoint discovery record is invalid.");
|
|
53
|
+
const token = endpoint.token ?? "";
|
|
54
|
+
if (!token && stale !== true) throw new SdkDiscoveryError(file, "SDK endpoint discovery record is invalid.");
|
|
55
|
+
return {
|
|
56
|
+
sessionId,
|
|
57
|
+
url: endpoint.url,
|
|
58
|
+
token,
|
|
59
|
+
...(pid === undefined ? {} : { pid }),
|
|
60
|
+
...(stale === undefined ? {} : { stale }),
|
|
61
|
+
path: file,
|
|
62
|
+
};
|
|
47
63
|
}
|
|
48
64
|
|
|
49
65
|
function discoveryError(file: string, error: unknown): SdkDiscoveryError {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { SdkSessionEndpoint } from "./discovery";
|
|
2
|
+
|
|
3
|
+
export type SdkEndpointLiveness = "live" | "stale" | "dead" | "unknown";
|
|
4
|
+
|
|
5
|
+
export interface SdkEndpointSelectionError {
|
|
6
|
+
code:
|
|
7
|
+
| "endpoint_stale"
|
|
8
|
+
| "endpoint_dead"
|
|
9
|
+
| "endpoint_unknown"
|
|
10
|
+
| "no_live_endpoint"
|
|
11
|
+
| "multiple_live_endpoints"
|
|
12
|
+
| "not_found";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function classifyEndpoint(endpoint: SdkSessionEndpoint): SdkEndpointLiveness {
|
|
16
|
+
if (endpoint.stale === true) return "stale";
|
|
17
|
+
if (!Number.isInteger(endpoint.pid) || endpoint.pid === undefined || endpoint.pid <= 0) return "unknown";
|
|
18
|
+
try {
|
|
19
|
+
process.kill(endpoint.pid, 0);
|
|
20
|
+
return "live";
|
|
21
|
+
} catch (error) {
|
|
22
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
23
|
+
if (code === "ESRCH") return "dead";
|
|
24
|
+
return code === "EPERM" ? "live" : "unknown";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function selectLiveEndpoint(
|
|
29
|
+
records: readonly SdkSessionEndpoint[],
|
|
30
|
+
explicitSessionId?: string,
|
|
31
|
+
): SdkSessionEndpoint | SdkEndpointSelectionError {
|
|
32
|
+
if (explicitSessionId !== undefined) {
|
|
33
|
+
const endpoint = records.find(record => record.sessionId === explicitSessionId);
|
|
34
|
+
if (!endpoint) return { code: "not_found" };
|
|
35
|
+
switch (classifyEndpoint(endpoint)) {
|
|
36
|
+
case "live":
|
|
37
|
+
return endpoint;
|
|
38
|
+
case "stale":
|
|
39
|
+
return { code: "endpoint_stale" };
|
|
40
|
+
case "dead":
|
|
41
|
+
return { code: "endpoint_dead" };
|
|
42
|
+
case "unknown":
|
|
43
|
+
return { code: "endpoint_unknown" };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const live = records.filter(record => classifyEndpoint(record) === "live");
|
|
47
|
+
if (live.length === 1) return live[0]!;
|
|
48
|
+
return { code: live.length === 0 ? "no_live_endpoint" : "multiple_live_endpoints" };
|
|
49
|
+
}
|
|
@@ -137,7 +137,7 @@ function invoke(
|
|
|
137
137
|
): Promise<ControlValue> | ControlValue {
|
|
138
138
|
switch (operation) {
|
|
139
139
|
case "turn.prompt":
|
|
140
|
-
return surface.prompt(text(input), input.images);
|
|
140
|
+
return surface.prompt(text(input), input.images, input.clientRef as string | undefined);
|
|
141
141
|
case "turn.steer":
|
|
142
142
|
return surface.steer(text(input));
|
|
143
143
|
case "turn.follow_up":
|
|
@@ -158,7 +158,11 @@ function invoke(
|
|
|
158
158
|
case "workflow.plan_approve":
|
|
159
159
|
return surface.approvePlan(text(input, "id"), input.choice, input.expectedSessionId as string | undefined);
|
|
160
160
|
case "skill.invoke":
|
|
161
|
-
return surface.invokeSkill(
|
|
161
|
+
return surface.invokeSkill(
|
|
162
|
+
text(input, "name"),
|
|
163
|
+
input.args,
|
|
164
|
+
typeof input.clientRef === "string" ? input.clientRef : undefined,
|
|
165
|
+
);
|
|
162
166
|
case "mode.plan.set":
|
|
163
167
|
return surface.setPlanMode(input.on as boolean);
|
|
164
168
|
case "mode.goal.operate":
|
|
@@ -167,6 +171,8 @@ function invoke(
|
|
|
167
171
|
return surface.replaceTodo(input.items);
|
|
168
172
|
case "model.set":
|
|
169
173
|
return surface.setModel(text(input, "id"), input.thinkingLevel);
|
|
174
|
+
case "model.profile.set":
|
|
175
|
+
return surface.setModelProfile(text(input, "id"));
|
|
170
176
|
case "model.cycle":
|
|
171
177
|
return surface.cycleModel();
|
|
172
178
|
case "thinking.set":
|
|
@@ -6,7 +6,7 @@ export type ControlInput = Record<string, unknown>;
|
|
|
6
6
|
* AgentSession and its controllers without exposing those concrete types here.
|
|
7
7
|
*/
|
|
8
8
|
export interface ControlSurface {
|
|
9
|
-
prompt(text: string, images?: ControlValue): Promise<ControlValue> | ControlValue;
|
|
9
|
+
prompt(text: string, images?: ControlValue, clientRef?: string): Promise<ControlValue> | ControlValue;
|
|
10
10
|
steer(text: string): Promise<ControlValue> | ControlValue;
|
|
11
11
|
followUp(text: string): Promise<ControlValue> | ControlValue;
|
|
12
12
|
abort(): Promise<ControlValue> | ControlValue;
|
|
@@ -19,11 +19,12 @@ export interface ControlSurface {
|
|
|
19
19
|
idempotencyKey?: string,
|
|
20
20
|
): Promise<ControlValue> | ControlValue;
|
|
21
21
|
approvePlan(id: string, choice: ControlValue, expectedSessionId?: string): Promise<ControlValue> | ControlValue;
|
|
22
|
-
invokeSkill(name: string, args: ControlValue): Promise<ControlValue> | ControlValue;
|
|
22
|
+
invokeSkill(name: string, args: ControlValue, clientRef?: string): Promise<ControlValue> | ControlValue;
|
|
23
23
|
setPlanMode(on: boolean): Promise<ControlValue> | ControlValue;
|
|
24
24
|
operateGoal(op: string, objective?: string): Promise<ControlValue> | ControlValue;
|
|
25
25
|
replaceTodo(items: ControlValue): Promise<ControlValue> | ControlValue;
|
|
26
26
|
setModel(id: string, thinkingLevel?: ControlValue): Promise<ControlValue> | ControlValue;
|
|
27
|
+
setModelProfile(id: string): Promise<ControlValue> | ControlValue;
|
|
27
28
|
cycleModel(): Promise<ControlValue> | ControlValue;
|
|
28
29
|
setThinking(level: ControlValue): Promise<ControlValue> | ControlValue;
|
|
29
30
|
cycleThinking(): Promise<ControlValue> | ControlValue;
|
package/src/sdk/host/host.ts
CHANGED
|
@@ -9,16 +9,23 @@ export interface SessionSdkHostOptions extends HostEndpointAdapters {
|
|
|
9
9
|
query?: (connectionId: string, frame: SdkFrame) => unknown | Promise<unknown>;
|
|
10
10
|
/** Best-effort diagnostic observation of accepted control/query frames. */
|
|
11
11
|
onRequest?: SdkRequestObserver;
|
|
12
|
+
/** Runs before a control response is sent; identity transitions use sendTerminal. */
|
|
13
|
+
beforeControlResponse?: (
|
|
14
|
+
connectionId: string,
|
|
15
|
+
request: SdkFrame,
|
|
16
|
+
response: SdkFrame,
|
|
17
|
+
sendTerminal: () => Promise<void>,
|
|
18
|
+
) => void | Promise<void>;
|
|
12
19
|
/** Runs only after a successful control response has been sent to the client. */
|
|
13
20
|
afterControlResponse?: (connectionId: string, request: SdkFrame, response: SdkFrame) => void | Promise<void>;
|
|
14
21
|
installProviderDefinitions?: (capability: string, definitions: unknown) => void;
|
|
15
22
|
onProviderDefinitionsRemoved?: (capability: string) => void;
|
|
16
23
|
onReverseCancel?: (requestId: string, reason: "provider_disconnected" | "lease_released") => void;
|
|
17
24
|
/** Best-effort capabilities mirrored from the native transport for out-of-band consumers. */
|
|
18
|
-
connectionCapabilities?: (connectionId: string) => ReadonlySet<string
|
|
25
|
+
connectionCapabilities?: (connectionId: string) => ReadonlySet<string> | undefined;
|
|
19
26
|
}
|
|
20
27
|
|
|
21
|
-
const
|
|
28
|
+
const TOOL_ACTIVITY_CAPABILITY = "tool_activity_v2";
|
|
22
29
|
const CAP_GATED_FRAME_KINDS = new Set(["tool_activity", "reasoning_summary"]);
|
|
23
30
|
const EMPTY_CAPABILITIES: ReadonlySet<string> = new Set();
|
|
24
31
|
|
|
@@ -36,6 +43,14 @@ function errorFrame(connectionId: string, frame: SdkFrame, error: unknown): SdkF
|
|
|
36
43
|
? candidate.code
|
|
37
44
|
: "internal";
|
|
38
45
|
const message = typeof candidate?.message === "string" ? candidate.message : "SDK host operation failed.";
|
|
46
|
+
if (frame.type === "control_request") {
|
|
47
|
+
return {
|
|
48
|
+
type: "control_response",
|
|
49
|
+
id: typeof frame.id === "string" ? frame.id : "",
|
|
50
|
+
ok: false,
|
|
51
|
+
error: { code, message },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
39
54
|
return {
|
|
40
55
|
type: "reverse_response",
|
|
41
56
|
id: typeof frame.id === "string" ? frame.id : "",
|
|
@@ -214,7 +229,14 @@ export class SessionSdkHost {
|
|
|
214
229
|
const result = await this.#options.control?.(connectionId, frame);
|
|
215
230
|
if (result !== undefined) {
|
|
216
231
|
const response = { type: "control_response", ...(result as SdkFrame) };
|
|
217
|
-
|
|
232
|
+
let terminalSent = false;
|
|
233
|
+
const sendTerminal = async (): Promise<void> => {
|
|
234
|
+
if (terminalSent) return;
|
|
235
|
+
terminalSent = true;
|
|
236
|
+
await this.#send(connectionId, response);
|
|
237
|
+
};
|
|
238
|
+
await this.#options.beforeControlResponse?.(connectionId, frame, response, sendTerminal);
|
|
239
|
+
await sendTerminal();
|
|
218
240
|
await this.#options.afterControlResponse?.(connectionId, frame, response);
|
|
219
241
|
}
|
|
220
242
|
break;
|
|
@@ -231,13 +253,9 @@ export class SessionSdkHost {
|
|
|
231
253
|
const sinceGeneration = rawGeneration;
|
|
232
254
|
const sinceSeq = rawSeq;
|
|
233
255
|
const replay = this.events.replay(sinceSeq, sinceGeneration);
|
|
234
|
-
const capabilities =
|
|
235
|
-
? new Set(
|
|
236
|
-
frame.capabilities.filter((capability): capability is string => typeof capability === "string"),
|
|
237
|
-
)
|
|
238
|
-
: (this.#options.connectionCapabilities?.(connectionId) ?? EMPTY_CAPABILITIES);
|
|
256
|
+
const capabilities = this.#options.connectionCapabilities?.(connectionId) ?? EMPTY_CAPABILITIES;
|
|
239
257
|
const events = replay.events.filter(
|
|
240
|
-
event => !CAP_GATED_FRAME_KINDS.has(String(event.kind)) || capabilities.has(
|
|
258
|
+
event => !CAP_GATED_FRAME_KINDS.has(String(event.kind)) || capabilities.has(TOOL_ACTIVITY_CAPABILITY),
|
|
241
259
|
);
|
|
242
260
|
await this.#send(connectionId, {
|
|
243
261
|
type: "event_replay_result",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PROMPT_CLIENT_REF_MAX_LENGTH } from "../../prompt-status.js";
|
|
1
2
|
import {
|
|
2
3
|
assertCursorSelector,
|
|
3
4
|
type CursorEnvelope,
|
|
@@ -43,6 +44,15 @@ export interface SessionSurface {
|
|
|
43
44
|
| Promise<{ bytes: Uint8Array; totalBytes: number } | undefined>;
|
|
44
45
|
|
|
45
46
|
getJobs(): unknown | Promise<unknown>;
|
|
47
|
+
/** Q26 keyed lookup of a submitted prompt's authoritative reconciliation status. */
|
|
48
|
+
getPromptStatus?(selector: { commandId?: string; turnId?: string; clientRef?: string }): unknown | Promise<unknown>;
|
|
49
|
+
getSkillInvokeStatus?(selector: {
|
|
50
|
+
commandId?: string;
|
|
51
|
+
turnId?: string;
|
|
52
|
+
clientRef?: string;
|
|
53
|
+
}): unknown | Promise<unknown>;
|
|
54
|
+
/** Q27 effective model-profile catalog from the live session registry. */
|
|
55
|
+
getModelProfiles?(): unknown[] | Promise<unknown[]>;
|
|
46
56
|
/** Query rows backed by the session's installed binding map. */
|
|
47
57
|
installedQueries?: ReadonlySet<string>;
|
|
48
58
|
}
|
|
@@ -66,7 +76,7 @@ export interface QueryResponse {
|
|
|
66
76
|
ok: boolean;
|
|
67
77
|
page?: QueryPage;
|
|
68
78
|
result?: unknown;
|
|
69
|
-
error?: { code: string; message: string; restartQuery?: boolean };
|
|
79
|
+
error?: { code: string; message: string; restartQuery?: boolean; details?: unknown };
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
const sources: Record<string, { resource: string; method: keyof SessionSurface; mvcc: boolean }> = {
|
|
@@ -92,6 +102,7 @@ const sources: Record<string, { resource: string; method: keyof SessionSurface;
|
|
|
92
102
|
Q21: { resource: "queue", method: "getQueueMessages", mvcc: true },
|
|
93
103
|
Q22: { resource: "extensions", method: "getExtensions", mvcc: true },
|
|
94
104
|
Q25: { resource: "jobs", method: "getJobs", mvcc: false },
|
|
105
|
+
Q27: { resource: "modelProfiles", method: "getModelProfiles", mvcc: true },
|
|
95
106
|
};
|
|
96
107
|
const names = [
|
|
97
108
|
"transcript.list",
|
|
@@ -119,6 +130,9 @@ const names = [
|
|
|
119
130
|
"resource.body",
|
|
120
131
|
"artifact.read",
|
|
121
132
|
"runtime.jobs.list",
|
|
133
|
+
"turn.prompt_status",
|
|
134
|
+
"models.profiles.list",
|
|
135
|
+
"skill.invoke_status",
|
|
122
136
|
];
|
|
123
137
|
|
|
124
138
|
export class QueryHandlers {
|
|
@@ -147,13 +161,19 @@ export class QueryHandlers {
|
|
|
147
161
|
);
|
|
148
162
|
if (query === "Q02") return await this.#transcriptBody(request);
|
|
149
163
|
if (query === "Q23") return await this.#resourceBody(request);
|
|
164
|
+
if (query === "Q26") return await this.#promptStatus(request);
|
|
165
|
+
if (query === "Q28") return await this.#skillInvokeStatus(request);
|
|
150
166
|
if (query === "Q24") return await this.#artifact(request);
|
|
167
|
+
if (query === "Q27" && request.input && Object.keys(request.input).length > 0)
|
|
168
|
+
return this.#error(request, "invalid_request", false, "models.profiles.list does not accept input fields.");
|
|
169
|
+
if (query === "Q27" && typeof this.surface.getModelProfiles !== "function")
|
|
170
|
+
return this.#error(request, "unavailable", false, "models.profiles.list is unavailable for this session.");
|
|
151
171
|
const source = sources[query];
|
|
152
172
|
if (!source) return this.#error(request, "invalid_request");
|
|
153
173
|
return await this.#pageSource(request, query, source);
|
|
154
174
|
} catch (error) {
|
|
155
175
|
if (error instanceof CursorError) return this.#error(request, error.code, error.restartQuery, error.message);
|
|
156
|
-
if (isTypedError(error)) return this.#error(request, error.code, false, error.message);
|
|
176
|
+
if (isTypedError(error)) return this.#error(request, error.code, false, error.message, error.details);
|
|
157
177
|
return this.#error(request, "internal", false, error instanceof Error ? error.message : String(error));
|
|
158
178
|
}
|
|
159
179
|
}
|
|
@@ -504,8 +524,108 @@ export class QueryHandlers {
|
|
|
504
524
|
return { id: request.id, ok: true, page };
|
|
505
525
|
}
|
|
506
526
|
|
|
507
|
-
#
|
|
508
|
-
|
|
527
|
+
async #skillInvokeStatus(request: QueryRequest): Promise<QueryResponse> {
|
|
528
|
+
if (request.cursor)
|
|
529
|
+
return this.#error(request, "invalid_request", false, "skill.invoke_status does not support cursors.");
|
|
530
|
+
const input = request.input ?? {};
|
|
531
|
+
for (const key of Object.keys(input))
|
|
532
|
+
if (key !== "commandId" && key !== "turnId" && key !== "clientRef")
|
|
533
|
+
return this.#error(
|
|
534
|
+
request,
|
|
535
|
+
"invalid_request",
|
|
536
|
+
false,
|
|
537
|
+
`skill.invoke_status does not accept selector field "${key}".`,
|
|
538
|
+
);
|
|
539
|
+
const commandId = typeof input.commandId === "string" && input.commandId ? input.commandId : undefined;
|
|
540
|
+
const turnId = typeof input.turnId === "string" && input.turnId ? input.turnId : undefined;
|
|
541
|
+
const rawClientRef = typeof input.clientRef === "string" ? input.clientRef : undefined;
|
|
542
|
+
const trimmedClientRef = rawClientRef?.trim();
|
|
543
|
+
if (rawClientRef !== undefined && (!trimmedClientRef || trimmedClientRef.length > PROMPT_CLIENT_REF_MAX_LENGTH))
|
|
544
|
+
return this.#error(
|
|
545
|
+
request,
|
|
546
|
+
"invalid_request",
|
|
547
|
+
false,
|
|
548
|
+
"clientRef must be a non-empty string of at most 128 characters.",
|
|
549
|
+
);
|
|
550
|
+
const clientRef = trimmedClientRef || undefined;
|
|
551
|
+
if ((commandId === undefined) !== (turnId === undefined))
|
|
552
|
+
return this.#error(request, "invalid_request", false, "commandId and turnId must be provided together.");
|
|
553
|
+
if (commandId !== undefined && clientRef !== undefined)
|
|
554
|
+
return this.#error(
|
|
555
|
+
request,
|
|
556
|
+
"invalid_request",
|
|
557
|
+
false,
|
|
558
|
+
"Provide exactly one selector: a commandId/turnId pair or a clientRef.",
|
|
559
|
+
);
|
|
560
|
+
if (commandId === undefined && clientRef === undefined)
|
|
561
|
+
return this.#error(
|
|
562
|
+
request,
|
|
563
|
+
"invalid_request",
|
|
564
|
+
false,
|
|
565
|
+
"skill.invoke_status requires a commandId/turnId pair or a clientRef.",
|
|
566
|
+
);
|
|
567
|
+
if (typeof this.surface.getSkillInvokeStatus !== "function")
|
|
568
|
+
return this.#error(request, "unavailable", false, "skill.invoke_status is unavailable for this session.");
|
|
569
|
+
const result = await this.surface.getSkillInvokeStatus(
|
|
570
|
+
clientRef !== undefined ? { clientRef } : { commandId: commandId!, turnId: turnId! },
|
|
571
|
+
);
|
|
572
|
+
return { id: request.id, ok: true, result };
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async #promptStatus(request: QueryRequest): Promise<QueryResponse> {
|
|
576
|
+
if (request.cursor)
|
|
577
|
+
return this.#error(request, "invalid_request", false, "turn.prompt_status does not support cursors.");
|
|
578
|
+
const input = request.input ?? {};
|
|
579
|
+
for (const key of Object.keys(input))
|
|
580
|
+
if (key !== "commandId" && key !== "turnId" && key !== "clientRef")
|
|
581
|
+
return this.#error(
|
|
582
|
+
request,
|
|
583
|
+
"invalid_request",
|
|
584
|
+
false,
|
|
585
|
+
`turn.prompt_status does not accept selector field "${key}".`,
|
|
586
|
+
);
|
|
587
|
+
const commandId = typeof input.commandId === "string" && input.commandId ? input.commandId : undefined;
|
|
588
|
+
const turnId = typeof input.turnId === "string" && input.turnId ? input.turnId : undefined;
|
|
589
|
+
const rawClientRef = typeof input.clientRef === "string" ? input.clientRef : undefined;
|
|
590
|
+
const trimmedClientRef = rawClientRef?.trim();
|
|
591
|
+
if (rawClientRef !== undefined && (!trimmedClientRef || trimmedClientRef.length > PROMPT_CLIENT_REF_MAX_LENGTH))
|
|
592
|
+
return this.#error(
|
|
593
|
+
request,
|
|
594
|
+
"invalid_request",
|
|
595
|
+
false,
|
|
596
|
+
"clientRef must be a non-empty string of at most 128 characters.",
|
|
597
|
+
);
|
|
598
|
+
const clientRef = trimmedClientRef || undefined;
|
|
599
|
+
if ((commandId === undefined) !== (turnId === undefined))
|
|
600
|
+
return this.#error(request, "invalid_request", false, "commandId and turnId must be provided together.");
|
|
601
|
+
if (commandId !== undefined && clientRef !== undefined)
|
|
602
|
+
return this.#error(
|
|
603
|
+
request,
|
|
604
|
+
"invalid_request",
|
|
605
|
+
false,
|
|
606
|
+
"Provide exactly one selector: a commandId/turnId pair or a clientRef.",
|
|
607
|
+
);
|
|
608
|
+
if (commandId === undefined && clientRef === undefined)
|
|
609
|
+
return this.#error(
|
|
610
|
+
request,
|
|
611
|
+
"invalid_request",
|
|
612
|
+
false,
|
|
613
|
+
"turn.prompt_status requires a commandId/turnId pair or a clientRef.",
|
|
614
|
+
);
|
|
615
|
+
if (typeof this.surface.getPromptStatus !== "function")
|
|
616
|
+
return this.#error(request, "unavailable", false, "turn.prompt_status is unavailable for this session.");
|
|
617
|
+
const result = await this.surface.getPromptStatus(
|
|
618
|
+
clientRef !== undefined ? { clientRef } : { commandId: commandId!, turnId: turnId! },
|
|
619
|
+
);
|
|
620
|
+
return { id: request.id, ok: true, result };
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
#error(request: QueryRequest, code: string, restartQuery = false, message = code, details?: unknown): QueryResponse {
|
|
624
|
+
return {
|
|
625
|
+
id: request.id,
|
|
626
|
+
ok: false,
|
|
627
|
+
error: { code, message, ...(restartQuery ? { restartQuery: true } : {}), ...(details ? { details } : {}) },
|
|
628
|
+
};
|
|
509
629
|
}
|
|
510
630
|
}
|
|
511
631
|
function selectorFor(queryId: string, input: Record<string, unknown> | undefined): CursorSelector {
|
|
@@ -521,7 +641,7 @@ function idOf(value: unknown): string | undefined {
|
|
|
521
641
|
function lastId(value: unknown): string | undefined {
|
|
522
642
|
return Array.isArray(value) ? idOf(value.at(-1)) : undefined;
|
|
523
643
|
}
|
|
524
|
-
function isTypedError(error: unknown): error is { code: string; message: string } {
|
|
644
|
+
function isTypedError(error: unknown): error is { code: string; message: string; details?: unknown } {
|
|
525
645
|
return Boolean(
|
|
526
646
|
error &&
|
|
527
647
|
typeof error === "object" &&
|
package/src/sdk/index.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
export {
|
|
2
|
+
MODEL_PROFILE_DISCOVERY_QUERY,
|
|
3
|
+
MODEL_PROFILE_ERROR_DETAIL_MAX_BYTES,
|
|
4
|
+
type ModelProfileCatalogItem,
|
|
5
|
+
type ModelProfileErrorCode,
|
|
6
|
+
type ModelProfileErrorDetails,
|
|
7
|
+
ModelProfileRegistryError,
|
|
8
|
+
type ModelProfileRegistryErrorDetails,
|
|
9
|
+
type UnknownModelProfileDetails,
|
|
10
|
+
UnknownModelProfileError,
|
|
11
|
+
} from "../config/model-profile-contract";
|
|
1
12
|
export * as bus from "./bus";
|
|
2
13
|
export * from "./client";
|
|
3
14
|
export * as host from "./host";
|
|
@@ -10,5 +21,6 @@ export type {
|
|
|
10
21
|
Q10ThinkingEffort,
|
|
11
22
|
Q10ThinkingMode,
|
|
12
23
|
} from "./models";
|
|
24
|
+
export * from "./prompt-status";
|
|
13
25
|
export * from "./session";
|
|
14
26
|
export * from "./session-directory";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentSession } from "../session/agent-session";
|
|
2
2
|
import { type CreateAgentSessionOptions, createAgentSession } from "./session";
|
|
3
3
|
import {
|
|
4
|
+
lifecycleMcpStartupTimeoutOption,
|
|
4
5
|
lifecycleStartupCapabilityOption,
|
|
5
6
|
SdkStartupCapability,
|
|
6
7
|
type SdkStartupFailure,
|
|
@@ -15,17 +16,32 @@ export type CreateLifecycleAgentSessionResult =
|
|
|
15
16
|
}
|
|
16
17
|
| { capability: SdkStartupCapability; rollback: SdkStartupRollbackTracker; failure: SdkStartupFailure };
|
|
17
18
|
|
|
19
|
+
/** Options accepted by lifecycle-only session construction. */
|
|
20
|
+
export type CreateLifecycleAgentSessionOptions = CreateAgentSessionOptions & {
|
|
21
|
+
/**
|
|
22
|
+
* Startup budget for ACP lifecycle MCP launches, in milliseconds. Set only
|
|
23
|
+
* when the lifecycle request supplies `mcpServers`; ordinary consumers keep
|
|
24
|
+
* the manager's short default ceiling.
|
|
25
|
+
*/
|
|
26
|
+
mcpStartupTimeoutMs?: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
18
29
|
/** Internal lifecycle-only session construction with an owner-bound SDK startup result. */
|
|
19
30
|
export async function createLifecycleAgentSession(
|
|
20
|
-
options:
|
|
31
|
+
options: CreateLifecycleAgentSessionOptions = {},
|
|
21
32
|
): Promise<CreateLifecycleAgentSessionResult> {
|
|
22
33
|
const rollback = new SdkStartupRollbackTracker();
|
|
23
34
|
const capability = new SdkStartupCapability(rollback);
|
|
24
35
|
try {
|
|
36
|
+
const { mcpStartupTimeoutMs, ...sessionOptions } = options;
|
|
25
37
|
const internalOptions = {
|
|
26
|
-
...
|
|
38
|
+
...sessionOptions,
|
|
27
39
|
[lifecycleStartupCapabilityOption]: capability,
|
|
28
|
-
|
|
40
|
+
...(mcpStartupTimeoutMs !== undefined ? { [lifecycleMcpStartupTimeoutOption]: mcpStartupTimeoutMs } : {}),
|
|
41
|
+
} as CreateAgentSessionOptions & {
|
|
42
|
+
[lifecycleStartupCapabilityOption]: SdkStartupCapability;
|
|
43
|
+
[lifecycleMcpStartupTimeoutOption]?: number;
|
|
44
|
+
};
|
|
29
45
|
const result = await createAgentSession(internalOptions);
|
|
30
46
|
if (!result.session.extensionRunner)
|
|
31
47
|
capability.settleFailure(capability.normalizeFailure("registration", "runner_absent"));
|
package/src/sdk/mcp/server.ts
CHANGED
|
@@ -301,9 +301,16 @@ export function createSdkMcpServer(options: SdkMcpServerOptions = {}) {
|
|
|
301
301
|
export async function runSdkMcpStdio(options: SdkMcpServerOptions = {}): Promise<void> {
|
|
302
302
|
const server = createSdkMcpServer(options);
|
|
303
303
|
let buffer = "";
|
|
304
|
+
const inflight = new Set<Promise<void>>();
|
|
304
305
|
process.stdin.setEncoding("utf8");
|
|
305
|
-
|
|
306
|
-
|
|
306
|
+
|
|
307
|
+
const track = (work: Promise<void>): void => {
|
|
308
|
+
inflight.add(work);
|
|
309
|
+
void work.finally(() => inflight.delete(work));
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
await new Promise<void>((resolve, reject) => {
|
|
313
|
+
const onData = (chunk: string) => {
|
|
307
314
|
buffer += chunk;
|
|
308
315
|
let index = buffer.indexOf("\n");
|
|
309
316
|
while (index >= 0) {
|
|
@@ -311,22 +318,43 @@ export async function runSdkMcpStdio(options: SdkMcpServerOptions = {}): Promise
|
|
|
311
318
|
buffer = buffer.slice(index + 1);
|
|
312
319
|
index = buffer.indexOf("\n");
|
|
313
320
|
if (!line) continue;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
321
|
+
track(
|
|
322
|
+
(async () => {
|
|
323
|
+
let request: JsonRpcRequest;
|
|
324
|
+
try {
|
|
325
|
+
request = JSON.parse(line) as JsonRpcRequest;
|
|
326
|
+
} catch {
|
|
327
|
+
process.stdout.write(
|
|
328
|
+
`${JSON.stringify({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "parse_error" } })}\n`,
|
|
329
|
+
);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const response = await server.handleJsonRpc(request);
|
|
333
|
+
// JSON-RPC notifications (no id) receive no response.
|
|
334
|
+
if (request.id !== undefined) process.stdout.write(`${JSON.stringify(response)}\n`);
|
|
335
|
+
})(),
|
|
336
|
+
);
|
|
328
337
|
}
|
|
329
|
-
}
|
|
330
|
-
|
|
338
|
+
};
|
|
339
|
+
const onEnd = () => {
|
|
340
|
+
process.stdin.off("data", onData);
|
|
341
|
+
process.stdin.off("end", onEnd);
|
|
342
|
+
process.stdin.off("error", onError);
|
|
343
|
+
resolve();
|
|
344
|
+
};
|
|
345
|
+
const onError = (error: Error) => {
|
|
346
|
+
process.stdin.off("data", onData);
|
|
347
|
+
process.stdin.off("end", onEnd);
|
|
348
|
+
process.stdin.off("error", onError);
|
|
349
|
+
reject(error);
|
|
350
|
+
};
|
|
351
|
+
process.stdin.on("data", onData);
|
|
352
|
+
process.stdin.on("end", onEnd);
|
|
353
|
+
process.stdin.on("error", onError);
|
|
331
354
|
});
|
|
355
|
+
|
|
356
|
+
// Stdin EOF must not drop in-flight tools/call handlers (WS connect/query).
|
|
357
|
+
// Awaiting them also prevents the process from exiting before responses flush,
|
|
358
|
+
// and lets clients close so the event loop can drain deterministically.
|
|
359
|
+
await Promise.allSettled([...inflight]);
|
|
332
360
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public DTO contract for Q26 `turn.prompt_status` and the `clientRef`
|
|
3
|
+
* correlation field on `turn.prompt`.
|
|
4
|
+
*
|
|
5
|
+
* Semantics:
|
|
6
|
+
* - `turn.prompt` remains ordered and non-idempotent. An envelope
|
|
7
|
+
* `idempotencyKey` is ignored for replay/conflict purposes on ordered
|
|
8
|
+
* operations (no replay cache, no `idempotency_conflict`).
|
|
9
|
+
* - `clientRef` is a caller-chosen correlation key (trimmed, non-empty,
|
|
10
|
+
* 1..PROMPT_CLIENT_REF_MAX_LENGTH chars; one fresh value per logical prompt)
|
|
11
|
+
* mapped to the generated commandId/turnId at preflight acceptance so a
|
|
12
|
+
* caller can reconcile after a lost acknowledgement frame.
|
|
13
|
+
* - The clientRef index is scoped to one live session runtime: identical refs
|
|
14
|
+
* may coexist in different sessions, lookups never cross sessions, a ref
|
|
15
|
+
* conflicts only while its record is retained (`client_ref_conflict`), and
|
|
16
|
+
* after terminal TTL/capacity eviction a ref may be admitted again with the
|
|
17
|
+
* prior outcome unknown — callers MUST NOT reuse a clientRef as a retry
|
|
18
|
+
* mechanism and MUST treat `unknown` as uncertainty, not proof of
|
|
19
|
+
* non-execution.
|
|
20
|
+
* - The durability floor is the live session process: after restart or
|
|
21
|
+
* retained-record eviction, a lookup honestly reports `unknown`.
|
|
22
|
+
* - Q26 tracks prompts accepted through the SDK control surface (which always
|
|
23
|
+
* carries a requesting connection); submissions without a delivery owner are
|
|
24
|
+
* outside the reconciliation contract and hold no reservation.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export const PROMPT_CLIENT_REF_MAX_LENGTH = 128;
|
|
28
|
+
|
|
29
|
+
export interface TurnPromptImageInput {
|
|
30
|
+
data: string;
|
|
31
|
+
mimeType?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Public input contract for ordered `turn.prompt`. */
|
|
35
|
+
export interface TurnPromptInput {
|
|
36
|
+
text: string;
|
|
37
|
+
images?: TurnPromptImageInput[];
|
|
38
|
+
clientRef?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Terminal outcome is preserved exactly; active records never age into terminal. */
|
|
42
|
+
export type PromptReconciliationStatus = "accepted" | "in_flight" | "terminal_ok" | "failed";
|
|
43
|
+
|
|
44
|
+
/** Exactly one selector per lookup. */
|
|
45
|
+
export type TurnPromptStatusSelector = { clientRef: string } | { commandId: string; turnId: string };
|
|
46
|
+
|
|
47
|
+
interface TurnPromptReconciliationIdentity {
|
|
48
|
+
commandId: string;
|
|
49
|
+
turnId: string;
|
|
50
|
+
clientRef?: string;
|
|
51
|
+
/** Epoch milliseconds of preflight acceptance. */
|
|
52
|
+
acceptedAt: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TurnPromptReconciliationAccepted extends TurnPromptReconciliationIdentity {
|
|
56
|
+
status: "accepted";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface TurnPromptReconciliationInFlight extends TurnPromptReconciliationIdentity {
|
|
60
|
+
status: "in_flight";
|
|
61
|
+
/** Epoch milliseconds of the agent_start transition. */
|
|
62
|
+
startedAt: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface TurnPromptReconciliationTerminalOk extends TurnPromptReconciliationIdentity {
|
|
66
|
+
status: "terminal_ok";
|
|
67
|
+
startedAt?: number;
|
|
68
|
+
/** Epoch milliseconds of the terminal transition. */
|
|
69
|
+
terminalAt: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface TurnPromptReconciliationFailed extends TurnPromptReconciliationIdentity {
|
|
73
|
+
status: "failed";
|
|
74
|
+
startedAt?: number;
|
|
75
|
+
terminalAt: number;
|
|
76
|
+
/** Bounded, sanitized failure detail (code safe-token ≤64, message ≤512). */
|
|
77
|
+
error: { code: string; message: string };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface TurnPromptReconciliationUnknown {
|
|
81
|
+
status: "unknown";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type TurnPromptReconciliation =
|
|
85
|
+
| TurnPromptReconciliationAccepted
|
|
86
|
+
| TurnPromptReconciliationInFlight
|
|
87
|
+
| TurnPromptReconciliationTerminalOk
|
|
88
|
+
| TurnPromptReconciliationFailed
|
|
89
|
+
| TurnPromptReconciliationUnknown;
|
|
90
|
+
|
|
91
|
+
/** Result of a successful `turn.prompt` preflight acknowledgement. */
|
|
92
|
+
export interface TurnPromptAcceptedResult {
|
|
93
|
+
commandId: string;
|
|
94
|
+
turnId: string;
|
|
95
|
+
accepted: true;
|
|
96
|
+
clientRef?: string;
|
|
97
|
+
}
|