@gajae-code/coding-agent 0.10.2 → 0.11.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 +50 -2
- package/dist/types/append-only-mode.d.ts +1 -1
- package/dist/types/cli/args.d.ts +4 -5
- package/dist/types/cli/daemon-cli.d.ts +12 -1
- package/dist/types/cli/notify-cli.d.ts +21 -1
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/notify.d.ts +28 -1
- package/dist/types/commands/sdk.d.ts +33 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
- package/dist/types/config/model-profile-activation.d.ts +35 -15
- package/dist/types/config/model-profiles.d.ts +11 -5
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/model-resolver.d.ts +39 -6
- package/dist/types/config/model-selector-value.d.ts +17 -0
- package/dist/types/config/models-config-schema.d.ts +10 -6
- package/dist/types/config/settings-schema.d.ts +133 -6
- package/dist/types/config/settings.d.ts +63 -35
- package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
- package/dist/types/coordinator-mcp/server.d.ts +6 -49
- package/dist/types/daemon/builtin.d.ts +6 -5
- package/dist/types/daemon/control-types.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +12 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
- package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
- package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +10 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -3
- package/dist/types/extensibility/extensions/types.d.ts +141 -16
- package/dist/types/extensibility/hooks/types.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
- package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
- package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
- package/dist/types/harness-control-plane/operate.d.ts +5 -5
- package/dist/types/harness-control-plane/owner.d.ts +18 -4
- package/dist/types/harness-control-plane/receipts.d.ts +0 -1
- package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
- package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
- package/dist/types/harness-control-plane/types.d.ts +3 -4
- package/dist/types/lsp/index.d.ts +1 -1
- package/dist/types/main.d.ts +32 -38
- package/dist/types/modes/acp/acp-agent.d.ts +224 -53
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
- package/dist/types/modes/acp/acp-mode.d.ts +6 -15
- package/dist/types/modes/acp/permission-mode.d.ts +4 -0
- package/dist/types/modes/acp/startup-options.d.ts +6 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -4
- package/dist/types/modes/components/welcome.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
- package/dist/types/modes/index.d.ts +0 -4
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/runtime-init.d.ts +2 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
- package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
- package/dist/types/modes/types.d.ts +5 -0
- package/dist/types/runtime-mcp/client.d.ts +2 -0
- package/dist/types/runtime-mcp/config.d.ts +5 -1
- package/dist/types/runtime-mcp/manager.d.ts +8 -1
- package/dist/types/runtime-mcp/types.d.ts +4 -0
- package/dist/types/sdk/acp/adapter.d.ts +67 -0
- package/dist/types/sdk/acp/index.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +53 -0
- package/dist/types/sdk/broker/discovery.d.ts +30 -0
- package/dist/types/sdk/broker/ensure.d.ts +33 -0
- package/dist/types/sdk/broker/identity.d.ts +3 -0
- package/dist/types/sdk/broker/index.d.ts +8 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
- package/dist/types/sdk/broker/runtime.d.ts +33 -0
- package/dist/types/sdk/broker/session-index.d.ts +57 -0
- package/dist/types/sdk/broker/state-version.d.ts +8 -0
- package/dist/types/sdk/broker/transport.d.ts +9 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
- package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
- package/dist/types/sdk/bus/config.d.ts +274 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
- package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
- package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
- package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
- package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
- package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
- package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
- package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
- package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
- package/dist/types/sdk/bus/session-control.d.ts +83 -0
- package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
- package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
- package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
- package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
- package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
- package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/session-cli.d.ts +19 -0
- package/dist/types/sdk/client/client.d.ts +1 -0
- package/dist/types/sdk/client/discovery.d.ts +27 -0
- package/dist/types/sdk/client/index.d.ts +2 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
- package/dist/types/sdk/host/control/index.d.ts +2 -0
- package/dist/types/sdk/host/control/operations.d.ts +65 -0
- package/dist/types/sdk/host/events.d.ts +35 -0
- package/dist/types/sdk/host/host.d.ts +35 -0
- package/dist/types/sdk/host/index.d.ts +4 -0
- package/dist/types/sdk/host/query/cursor.d.ts +62 -0
- package/dist/types/sdk/host/query/handlers.d.ts +70 -0
- package/dist/types/sdk/host/query/index.d.ts +3 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
- package/dist/types/sdk/host/types.d.ts +32 -0
- package/dist/types/sdk/index.d.ts +6 -0
- package/dist/types/sdk/lifecycle-session.d.ts +14 -0
- package/dist/types/sdk/mcp/index.d.ts +1 -0
- package/dist/types/sdk/mcp/server.d.ts +37 -0
- package/dist/types/sdk/models.d.ts +44 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
- package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
- package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
- package/dist/types/sdk/startup-capability.d.ts +50 -0
- package/dist/types/session/agent-session.d.ts +114 -21
- package/dist/types/session/default-model-selection.d.ts +25 -0
- package/dist/types/session/fallback-chain-controller.d.ts +52 -0
- package/dist/types/session/session-manager.d.ts +58 -1
- package/dist/types/setup/credential-auto-import.d.ts +36 -6
- package/dist/types/tools/ask-answer-registry.d.ts +1 -1
- package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
- package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
- package/dist/types/tools/browser/launch.d.ts +22 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
- package/dist/types/tools/browser/profile-posture.d.ts +37 -0
- package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
- package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
- package/dist/types/tools/browser/registry.d.ts +19 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/index.d.ts +8 -8
- package/package.json +34 -13
- package/scripts/build-sdk-package-smoke.ts +94 -0
- package/scripts/capture-notifications-settings-showcase.ts +435 -0
- package/scripts/compile-args.ts +4 -2
- package/scripts/g005-daemon-smoke.ts +4 -5
- package/scripts/g011-daemon-path-smoke.ts +5 -5
- package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
- package/scripts/generate-sdk-operation-inventory.ts +867 -0
- package/scripts/generate-telegram-baseline-manifest.ts +128 -0
- package/scripts/manifest-schema.ts +124 -0
- package/scripts/run-test-manifest.ts +153 -0
- package/scripts/run-threat-model-check.ts +157 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
- package/scripts/verify-gjc-sdk-rename.ts +90 -0
- package/src/append-only-mode.ts +1 -1
- package/src/cli/args.ts +43 -12
- package/src/cli/auth-gateway-cli.ts +2 -2
- package/src/cli/config-cli.ts +2 -1
- package/src/cli/daemon-cli.ts +63 -14
- package/src/cli/list-models.ts +1 -1
- package/src/cli/notify-cli.ts +288 -286
- package/src/cli.ts +21 -2
- package/src/commands/daemon.ts +50 -6
- package/src/commands/harness.ts +93 -36
- package/src/commands/launch.ts +5 -2
- package/src/commands/mcp-serve.ts +19 -12
- package/src/commands/notify.ts +36 -3
- package/src/commands/sdk.ts +426 -0
- package/src/commit/agentic/agent.ts +1 -0
- package/src/config/atomic-yaml-patch.ts +423 -0
- package/src/config/model-profile-activation.ts +240 -89
- package/src/config/model-profiles.ts +18 -15
- package/src/config/model-registry.ts +51 -26
- package/src/config/model-resolver.ts +138 -51
- package/src/config/model-selector-value.ts +50 -0
- package/src/config/models-config-schema.ts +14 -21
- package/src/config/settings-schema.ts +128 -10
- package/src/config/settings.ts +1120 -158
- package/src/coordinator-mcp/model-preset.ts +74 -20
- package/src/coordinator-mcp/server.ts +1597 -3052
- package/src/daemon/builtin.ts +8 -5
- package/src/daemon/control-types.ts +1 -1
- package/src/defaults/gjc/skills/team/SKILL.md +4 -4
- package/src/discovery/mcp-json.ts +327 -20
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/compact-handler.ts +3 -3
- package/src/extensibility/extensions/get-commands-handler.ts +2 -2
- package/src/extensibility/extensions/loader.ts +69 -5
- package/src/extensibility/extensions/runner.ts +112 -4
- package/src/extensibility/extensions/types.ts +176 -17
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/gjc-runtime/launch-tmux.ts +170 -86
- package/src/gjc-runtime/psmux-detect.ts +82 -4
- package/src/gjc-runtime/session-state-sidecar.ts +41 -31
- package/src/gjc-runtime/team-runtime.ts +54 -35
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
- package/src/gjc-runtime/tmux-sessions.ts +19 -13
- package/src/gjc-runtime/ultragoal-guard.ts +53 -6
- package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
- package/src/gjc-runtime/windows-powershell-command.ts +58 -0
- package/src/harness-control-plane/operate.ts +9 -9
- package/src/harness-control-plane/owner.ts +283 -39
- package/src/harness-control-plane/receipts.ts +0 -1
- package/src/harness-control-plane/sdk-transport.ts +395 -0
- package/src/harness-control-plane/session-transport.ts +94 -0
- package/src/harness-control-plane/types.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +34 -35
- package/src/lsp/client.ts +42 -6
- package/src/lsp/index.ts +2 -2
- package/src/main.ts +299 -204
- package/src/modes/DESIGN.md +258 -0
- package/src/modes/acp/acp-agent.ts +1228 -2612
- package/src/modes/acp/acp-client-bridge.ts +2 -20
- package/src/modes/acp/acp-event-mapper.ts +18 -2
- package/src/modes/acp/acp-mode.ts +8 -36
- package/src/modes/acp/permission-mode.ts +25 -0
- package/src/modes/acp/startup-options.ts +6 -0
- package/src/modes/components/agent-dashboard.ts +37 -17
- package/src/modes/components/model-selector.ts +93 -35
- package/src/modes/components/notifications-settings-editor.ts +1379 -0
- package/src/modes/components/settings-selector.ts +60 -11
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +1 -2
- package/src/modes/controllers/event-controller.ts +11 -16
- package/src/modes/controllers/extension-ui-controller.ts +348 -4
- package/src/modes/controllers/selector-controller.ts +674 -36
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +59 -20
- package/src/modes/runtime-init.ts +298 -6
- package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
- package/src/modes/shared/agent-wire/event-contract.ts +7 -8
- package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
- package/src/modes/shared/agent-wire/event-observation.ts +16 -7
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
- package/src/modes/types.ts +5 -0
- package/src/runtime-mcp/client.ts +94 -19
- package/src/runtime-mcp/config.ts +27 -15
- package/src/runtime-mcp/manager.ts +343 -105
- package/src/runtime-mcp/oauth-flow.ts +42 -12
- package/src/runtime-mcp/transports/http.ts +49 -19
- package/src/runtime-mcp/transports/stdio.ts +47 -28
- package/src/runtime-mcp/types.ts +10 -0
- package/src/sdk/acp/adapter.ts +418 -0
- package/src/sdk/acp/index.ts +2 -0
- package/src/sdk/broker/broker.ts +642 -0
- package/src/sdk/broker/discovery.ts +94 -0
- package/src/sdk/broker/ensure.ts +249 -0
- package/src/sdk/broker/identity.ts +42 -0
- package/src/sdk/broker/index.ts +8 -0
- package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
- package/src/sdk/broker/internal-source.bunfig.toml +1 -0
- package/src/sdk/broker/lifecycle-ledger.ts +286 -0
- package/src/sdk/broker/lifecycle.ts +2157 -0
- package/src/sdk/broker/process-incarnation.ts +159 -0
- package/src/sdk/broker/runtime.ts +164 -0
- package/src/sdk/broker/session-index.ts +318 -0
- package/src/sdk/broker/state-version.ts +23 -0
- package/src/sdk/broker/transport.ts +125 -0
- package/src/sdk/bus/chat-command-policy.ts +107 -0
- package/src/sdk/bus/chat-daemon-cli.ts +214 -0
- package/src/sdk/bus/chat-daemon-control.ts +713 -0
- package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
- package/src/sdk/bus/chat-effect-journal.ts +353 -0
- package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
- package/src/sdk/bus/config.ts +433 -0
- package/src/sdk/bus/conversation-store.ts +391 -0
- package/src/sdk/bus/discord-conversation.ts +85 -0
- package/src/sdk/bus/discord-daemon.ts +2275 -0
- package/src/sdk/bus/discord-live-provider.ts +521 -0
- package/src/sdk/bus/discord-provider.ts +56 -0
- package/src/{notifications → sdk/bus}/html-format.ts +2 -2
- package/src/sdk/bus/index.ts +3943 -0
- package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
- package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
- package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
- package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
- package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
- package/src/sdk/bus/natives-augment.d.ts +38 -0
- package/src/sdk/bus/notification-orchestration.ts +535 -0
- package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
- package/src/sdk/bus/session-control.ts +333 -0
- package/src/sdk/bus/slack-conversation.ts +74 -0
- package/src/sdk/bus/slack-daemon.ts +2144 -0
- package/src/sdk/bus/slack-live-provider.ts +380 -0
- package/src/sdk/bus/slack-provider.ts +76 -0
- package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
- package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
- package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
- package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
- package/src/sdk/bus/telegram-setup.ts +663 -0
- package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/session-cli.ts +275 -0
- package/src/sdk/client/client.ts +1 -0
- package/src/sdk/client/discovery.ts +108 -0
- package/src/sdk/client/index.ts +2 -0
- package/src/sdk/host/control/dispatch.ts +367 -0
- package/src/sdk/host/control/index.ts +10 -0
- package/src/sdk/host/control/operations.ts +63 -0
- package/src/sdk/host/events.ts +91 -0
- package/src/sdk/host/host.ts +296 -0
- package/src/sdk/host/index.ts +4 -0
- package/src/sdk/host/query/cursor.ts +189 -0
- package/src/sdk/host/query/handlers.ts +533 -0
- package/src/sdk/host/query/index.ts +3 -0
- package/src/sdk/host/query/revision-store.ts +1126 -0
- package/src/sdk/host/reverse-leases.ts +325 -0
- package/src/sdk/host/types.ts +29 -0
- package/src/sdk/index.ts +13 -0
- package/src/sdk/lifecycle-session.ts +39 -0
- package/src/sdk/mcp/index.ts +1 -0
- package/src/sdk/mcp/server.ts +332 -0
- package/src/sdk/models.ts +168 -0
- package/src/sdk/protocol/adapter-validation.ts +48 -0
- package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
- package/src/sdk/protocol/operation-registry.ts +312 -0
- package/src/{sdk.ts → sdk/session.ts} +339 -212
- package/src/sdk/startup-capability.ts +189 -0
- package/src/session/agent-session.ts +2453 -894
- package/src/session/default-model-selection.ts +93 -0
- package/src/session/fallback-chain-controller.ts +136 -0
- package/src/session/session-manager.ts +438 -11
- package/src/session/session-storage.ts +8 -1
- package/src/setup/credential-auto-import.ts +290 -35
- package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/task/executor.ts +62 -13
- package/src/tools/ask-answer-registry.ts +1 -1
- package/src/tools/ask.ts +13 -8
- package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
- package/src/tools/browser/benchmark/detector-report.ts +157 -0
- package/src/tools/browser/benchmark/run-suite.ts +39 -0
- package/src/tools/browser/launch.ts +124 -19
- package/src/tools/browser/profile-discovery.ts +63 -0
- package/src/tools/browser/profile-posture.ts +59 -0
- package/src/tools/browser/profile-reuse.ts +102 -0
- package/src/tools/browser/profile-warmup.ts +109 -0
- package/src/tools/browser/registry.ts +87 -11
- package/src/tools/browser/tab-protocol.ts +1 -0
- package/src/tools/browser/tab-supervisor.ts +1 -0
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +6 -0
- package/src/tools/index.ts +8 -8
- package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
- package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
- package/src/tools/telegram-send.ts +2 -2
- package/vendor/insane-search/MANIFEST.json +2 -1
- package/vendor/insane-search/engine/bias_check.py +4 -1
- package/vendor/insane-search/engine/phase0.py +26 -1
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
- package/dist/types/modes/bridge/auth.d.ts +0 -12
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
- package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
- package/dist/types/modes/bridge/event-stream.d.ts +0 -8
- package/dist/types/modes/rpc/host-tools.d.ts +0 -1
- package/dist/types/modes/rpc/host-uris.d.ts +0 -1
- package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
- package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
- package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
- package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
- package/dist/types/notifications/config.d.ts +0 -132
- package/src/harness-control-plane/rpc-adapter.ts +0 -290
- package/src/modes/bridge/auth.ts +0 -41
- package/src/modes/bridge/bridge-client-bridge.ts +0 -47
- package/src/modes/bridge/bridge-mode.ts +0 -675
- package/src/modes/bridge/bridge-ui-context.ts +0 -200
- package/src/modes/bridge/event-stream.ts +0 -70
- package/src/modes/rpc/host-tools.ts +0 -1
- package/src/modes/rpc/host-uris.ts +0 -1
- package/src/modes/rpc/rpc-client.ts +0 -1166
- package/src/modes/rpc/rpc-mode.ts +0 -1029
- package/src/modes/rpc/rpc-socket-security.ts +0 -115
- package/src/modes/rpc/rpc-types.ts +0 -637
- package/src/modes/shared/agent-wire/command-contract.ts +0 -18
- package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
- package/src/modes/shared/agent-wire/command-validation.ts +0 -181
- package/src/modes/shared/agent-wire/handshake.ts +0 -157
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
- package/src/modes/shared/agent-wire/protocol.ts +0 -46
- package/src/modes/shared/agent-wire/responses.ts +0 -17
- package/src/modes/shared/agent-wire/scopes.ts +0 -94
- package/src/modes/shared/agent-wire/session-registry.ts +0 -109
- package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
- package/src/modes/shared/agent-wire/ui-result.ts +0 -48
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
- package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
- package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
- package/src/notifications/config.ts +0 -219
- package/src/notifications/index.ts +0 -1835
- package/src/notifications/telegram-daemon-cli.ts +0 -243
- package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
- /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
- /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
- /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
- /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
- /package/src/{notifications → sdk/bus}/engine.ts +0 -0
- /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
- /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
- /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
- /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
- /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
type VanishEvidence,
|
|
20
20
|
validateReceipt,
|
|
21
21
|
} from "./receipts";
|
|
22
|
-
import { type
|
|
22
|
+
import { type HarnessSessionTransport, singleFlightAccept } from "./session-transport";
|
|
23
23
|
import { writeReceiptImmutable } from "./storage";
|
|
24
24
|
import {
|
|
25
25
|
DEFAULT_RETRY_BUDGET,
|
|
@@ -35,10 +35,10 @@ export interface OperateOptions {
|
|
|
35
35
|
sessionId: string;
|
|
36
36
|
workspace: string;
|
|
37
37
|
branch: string;
|
|
38
|
-
|
|
39
|
-
/** Factory used to
|
|
40
|
-
|
|
41
|
-
/** Bounded observation provider (scripted in tests; real = git +
|
|
38
|
+
transport: HarnessSessionTransport;
|
|
39
|
+
/** Factory used to recreate an SDK transport on restart recovery. Defaults to reusing `transport`. */
|
|
40
|
+
transportFactory?: () => HarnessSessionTransport;
|
|
41
|
+
/** Bounded observation provider (scripted in tests; real = git + SDK session state). */
|
|
42
42
|
observe: () => Promise<Observation>;
|
|
43
43
|
/** Real dirty-worktree preservation; injectable for tests. Defaults to git stash/diff capture. */
|
|
44
44
|
preserve?: (workspace: string) => PreserveResult;
|
|
@@ -71,7 +71,7 @@ export async function operate(goal: string, opts: OperateOptions): Promise<Opera
|
|
|
71
71
|
const vanishReceiptIds: string[] = [];
|
|
72
72
|
const blockers: string[] = [];
|
|
73
73
|
|
|
74
|
-
let
|
|
74
|
+
let transport = opts.transport;
|
|
75
75
|
|
|
76
76
|
const now = (): string => new Date(opts.clock ? opts.clock() : Date.now()).toISOString();
|
|
77
77
|
let lifecycle: HarnessLifecycle = "started";
|
|
@@ -118,7 +118,7 @@ export async function operate(goal: string, opts: OperateOptions): Promise<Opera
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
const submit = async (): Promise<boolean> => {
|
|
121
|
-
const acc = await singleFlightAccept(
|
|
121
|
+
const acc = await singleFlightAccept(transport, goal, acceptanceTimeoutMs);
|
|
122
122
|
await emit(acc.accepted ? "info" : "warn", acc.accepted ? "prompt_accepted" : "prompt_not_accepted", {
|
|
123
123
|
reason: acc.reason,
|
|
124
124
|
});
|
|
@@ -160,11 +160,11 @@ export async function operate(goal: string, opts: OperateOptions): Promise<Opera
|
|
|
160
160
|
accepted = await submit();
|
|
161
161
|
} else if (decision.classification === "restart-clean") {
|
|
162
162
|
budget.zeroDeltaVanish = Math.max(0, budget.zeroDeltaVanish - 1);
|
|
163
|
-
|
|
163
|
+
transport = opts.transportFactory ? opts.transportFactory() : transport;
|
|
164
164
|
accepted = await submit();
|
|
165
165
|
} else if (decision.classification === "restart-preserve-delta") {
|
|
166
166
|
budget.dirtyVanishPreserve = Math.max(0, budget.dirtyVanishPreserve - 1);
|
|
167
|
-
|
|
167
|
+
transport = opts.transportFactory ? opts.transportFactory() : transport;
|
|
168
168
|
accepted = await submit();
|
|
169
169
|
} else if (decision.classification === "fallback-codex-exec") {
|
|
170
170
|
lifecycle = "blocked";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Responsibilities:
|
|
5
5
|
* - hold the {@link SessionLease} (single writer),
|
|
6
|
-
* - own
|
|
6
|
+
* - own an injected SDK session transport,
|
|
7
7
|
* - serve owner-routed primitives over the {@link ControlServer} endpoint,
|
|
8
8
|
* - be the SOLE writer of the severity event stream,
|
|
9
9
|
* - heartbeat the lease.
|
|
@@ -15,9 +15,9 @@ import { execFileSync } from "node:child_process";
|
|
|
15
15
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
16
16
|
import { existsSync } from "node:fs";
|
|
17
17
|
import type { AgentWireOwnerObservation } from "../modes/shared/agent-wire/event-contract";
|
|
18
|
-
import {
|
|
18
|
+
import { observeAgentWireFrame } from "../modes/shared/agent-wire/event-observation";
|
|
19
19
|
import { classifyRecovery } from "./classifier";
|
|
20
|
-
import { ControlServer, type EndpointRequest } from "./control-endpoint";
|
|
20
|
+
import { ControlServer, type EndpointHandler, type EndpointRequest } from "./control-endpoint";
|
|
21
21
|
import { defaultFinalizeChecks, type FinalizeChecks, runFinalize, type ValidationCommandSpec } from "./finalize";
|
|
22
22
|
import { type OperateResult, operate } from "./operate";
|
|
23
23
|
import { preserveDirtyWorktree } from "./preserve";
|
|
@@ -30,16 +30,22 @@ import {
|
|
|
30
30
|
type VanishEvidence,
|
|
31
31
|
validateReceipt,
|
|
32
32
|
} from "./receipts";
|
|
33
|
-
import { type HarnessRpc, type RpcStateSnapshot, singleFlightAccept } from "./rpc-adapter";
|
|
34
33
|
import {
|
|
35
34
|
acquireLease,
|
|
36
35
|
canWriteEvents,
|
|
37
36
|
classifyLeaseStatus,
|
|
38
37
|
heartbeat,
|
|
38
|
+
LeaseError,
|
|
39
39
|
readLease,
|
|
40
40
|
releaseLease,
|
|
41
41
|
type SessionLease,
|
|
42
42
|
} from "./session-lease";
|
|
43
|
+
import {
|
|
44
|
+
type HarnessSessionTransport,
|
|
45
|
+
type HarnessSessionTransportCloseContext,
|
|
46
|
+
type SessionStateSnapshot,
|
|
47
|
+
singleFlightAccept,
|
|
48
|
+
} from "./session-transport";
|
|
43
49
|
import { buildStateView, nextAllowedActions, submitUnavailableReason } from "./state-machine";
|
|
44
50
|
import {
|
|
45
51
|
appendEvent,
|
|
@@ -78,10 +84,26 @@ function reconcileLiveOwnerState(state: SessionState): { state: SessionState; re
|
|
|
78
84
|
};
|
|
79
85
|
}
|
|
80
86
|
|
|
87
|
+
function flattenAggregateCauses(errors: readonly unknown[]): unknown[] {
|
|
88
|
+
const causes: unknown[] = [];
|
|
89
|
+
for (const error of errors) {
|
|
90
|
+
if (error instanceof AggregateError) causes.push(...flattenAggregateCauses(error.errors));
|
|
91
|
+
else causes.push(error);
|
|
92
|
+
}
|
|
93
|
+
return causes;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Nominal sentinel: raised only after #stopOnce has verified teardown so the
|
|
98
|
+
* retry loop can rethrow it immediately. A private class prevents a lookalike
|
|
99
|
+
* cleanup AggregateError (message collision) from bypassing verification retries.
|
|
100
|
+
*/
|
|
101
|
+
class FramePumpAfterVerifiedCleanupError extends AggregateError {}
|
|
102
|
+
|
|
81
103
|
export interface OwnerOptions {
|
|
82
104
|
root: string;
|
|
83
105
|
sessionId: string;
|
|
84
|
-
|
|
106
|
+
transport: HarnessSessionTransport;
|
|
85
107
|
ownerId?: string;
|
|
86
108
|
ttlMs?: number;
|
|
87
109
|
heartbeatMs?: number;
|
|
@@ -89,6 +111,18 @@ export interface OwnerOptions {
|
|
|
89
111
|
clock?: () => number;
|
|
90
112
|
finalizeChecks?: FinalizeChecks;
|
|
91
113
|
validationCommands?: ValidationCommandSpec[];
|
|
114
|
+
/** Test seam for deterministic control-endpoint teardown failures. */
|
|
115
|
+
controlServerFactory?: (socketPath: string, handler: EndpointHandler) => ControlServer;
|
|
116
|
+
/** Test seam for deterministic lease-release teardown failures. */
|
|
117
|
+
leaseRelease?: typeof releaseLease;
|
|
118
|
+
/** Test seams for frame persistence failures. */
|
|
119
|
+
framePersistence?: {
|
|
120
|
+
appendEvent?: typeof appendEvent;
|
|
121
|
+
writeSessionState?: typeof writeSessionState;
|
|
122
|
+
};
|
|
123
|
+
/** Test seams; production retries verified shutdown without a finite limit. */
|
|
124
|
+
cleanupRetryMs?: number;
|
|
125
|
+
cleanupRetryLimit?: number;
|
|
92
126
|
}
|
|
93
127
|
|
|
94
128
|
export interface OwnerStartInfo {
|
|
@@ -100,20 +134,35 @@ export interface OwnerStartInfo {
|
|
|
100
134
|
const DEFAULT_TTL_MS = 30_000;
|
|
101
135
|
const DEFAULT_HEARTBEAT_MS = 10_000;
|
|
102
136
|
const DEFAULT_ACCEPT_TIMEOUT_MS = 60_000;
|
|
137
|
+
const DEFAULT_CLEANUP_RETRY_MS = 500;
|
|
138
|
+
const MAX_RETAINED_CLEANUP_FAILURES = 32;
|
|
103
139
|
|
|
104
140
|
export class RuntimeOwner {
|
|
105
141
|
readonly ownerId: string;
|
|
106
|
-
#opts: Required<
|
|
142
|
+
#opts: Required<
|
|
143
|
+
Omit<
|
|
144
|
+
OwnerOptions,
|
|
145
|
+
"clock" | "finalizeChecks" | "validationCommands" | "controlServerFactory" | "framePersistence"
|
|
146
|
+
>
|
|
147
|
+
> & { clock?: () => number };
|
|
107
148
|
#server: ControlServer;
|
|
108
149
|
#cursor = 0;
|
|
109
150
|
#leaseEpoch = 0;
|
|
151
|
+
#leaseHeld = false;
|
|
110
152
|
#heartbeatTimer: NodeJS.Timeout | null = null;
|
|
111
153
|
#socketPath: string;
|
|
112
154
|
#finalizeChecks?: FinalizeChecks;
|
|
113
155
|
#validationCommands?: ValidationCommandSpec[];
|
|
114
156
|
#unsubscribeFrames: (() => void) | null = null;
|
|
115
157
|
#framePump: Promise<void> = Promise.resolve();
|
|
158
|
+
#framePumpFailure: unknown = null;
|
|
116
159
|
#coalesced = new Map<string, true>();
|
|
160
|
+
#stopPromise: Promise<void> | null = null;
|
|
161
|
+
#lastStopFailures: unknown[] = [];
|
|
162
|
+
#reportedStopFailures = new Set<string>();
|
|
163
|
+
#transportClosed = false;
|
|
164
|
+
#serverClosed = false;
|
|
165
|
+
#framePersistence: Required<NonNullable<OwnerOptions["framePersistence"]>>;
|
|
117
166
|
|
|
118
167
|
constructor(opts: OwnerOptions) {
|
|
119
168
|
this.ownerId = opts.ownerId ?? `owner-${randomUUID()}`;
|
|
@@ -121,19 +170,51 @@ export class RuntimeOwner {
|
|
|
121
170
|
this.#opts = {
|
|
122
171
|
root: opts.root,
|
|
123
172
|
sessionId: opts.sessionId,
|
|
124
|
-
|
|
173
|
+
transport: opts.transport,
|
|
125
174
|
ownerId: this.ownerId,
|
|
126
175
|
ttlMs: opts.ttlMs ?? DEFAULT_TTL_MS,
|
|
127
176
|
heartbeatMs: opts.heartbeatMs ?? DEFAULT_HEARTBEAT_MS,
|
|
128
177
|
acceptanceTimeoutMs: opts.acceptanceTimeoutMs ?? DEFAULT_ACCEPT_TIMEOUT_MS,
|
|
129
178
|
clock: opts.clock,
|
|
179
|
+
cleanupRetryMs: opts.cleanupRetryMs ?? DEFAULT_CLEANUP_RETRY_MS,
|
|
180
|
+
cleanupRetryLimit: opts.cleanupRetryLimit ?? Number.POSITIVE_INFINITY,
|
|
181
|
+
leaseRelease: opts.leaseRelease ?? releaseLease,
|
|
130
182
|
};
|
|
131
183
|
this.#finalizeChecks = opts.finalizeChecks;
|
|
132
184
|
this.#validationCommands = opts.validationCommands;
|
|
133
|
-
this.#
|
|
185
|
+
this.#framePersistence = {
|
|
186
|
+
appendEvent: opts.framePersistence?.appendEvent ?? appendEvent,
|
|
187
|
+
writeSessionState: opts.framePersistence?.writeSessionState ?? writeSessionState,
|
|
188
|
+
};
|
|
189
|
+
this.#server = (opts.controlServerFactory ?? ((socketPath, handler) => new ControlServer(socketPath, handler)))(
|
|
190
|
+
this.#socketPath,
|
|
191
|
+
req => this.#handle(req),
|
|
192
|
+
);
|
|
134
193
|
}
|
|
135
194
|
|
|
136
195
|
async start(): Promise<OwnerStartInfo> {
|
|
196
|
+
try {
|
|
197
|
+
return await this.#startOnce();
|
|
198
|
+
} catch (startError) {
|
|
199
|
+
try {
|
|
200
|
+
await this.stop();
|
|
201
|
+
} catch (cleanupError) {
|
|
202
|
+
const cleanupCauses = flattenAggregateCauses([cleanupError]);
|
|
203
|
+
throw new AggregateError(
|
|
204
|
+
[startError, ...cleanupCauses],
|
|
205
|
+
"Runtime owner startup and exact-child rollback failed.",
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (this.#lastStopFailures.length > 0)
|
|
209
|
+
throw new AggregateError(
|
|
210
|
+
[startError, ...flattenAggregateCauses(this.#lastStopFailures)],
|
|
211
|
+
"Runtime owner startup failed after retrying exact-child rollback.",
|
|
212
|
+
);
|
|
213
|
+
throw startError;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async #startOnce(): Promise<OwnerStartInfo> {
|
|
137
218
|
const { root, sessionId } = this.#opts;
|
|
138
219
|
const eventsPath = sessionPaths(root, sessionId).events;
|
|
139
220
|
const existing = await readEvents(root, sessionId, 0);
|
|
@@ -146,19 +227,20 @@ export class RuntimeOwner {
|
|
|
146
227
|
ttlMs: this.#opts.ttlMs,
|
|
147
228
|
clock: this.#opts.clock,
|
|
148
229
|
});
|
|
230
|
+
this.#leaseHeld = true;
|
|
149
231
|
this.#leaseEpoch = lease.leaseEpoch;
|
|
150
|
-
await this.#server.listen();
|
|
151
|
-
await this.#emit("info", "owner_started", { ownerId: this.ownerId, leaseEpoch: this.#leaseEpoch });
|
|
152
|
-
if (this.#opts.rpc.onEventFrame) {
|
|
153
|
-
this.#unsubscribeFrames = this.#opts.rpc.onEventFrame(frame => this.#handleFrame(frame));
|
|
154
|
-
}
|
|
155
232
|
this.#heartbeatTimer = setInterval(() => {
|
|
156
233
|
void heartbeat(root, sessionId, this.ownerId, this.#opts.ttlMs, this.#opts.clock).catch(err => {
|
|
157
234
|
// Self-stop if a legitimate dead-owner takeover revoked our lease.
|
|
158
|
-
if (err instanceof Error && err.message.includes("not_lease_holder")) void this.stop();
|
|
235
|
+
if (err instanceof Error && err.message.includes("not_lease_holder")) void this.stop().catch(() => {});
|
|
159
236
|
});
|
|
160
237
|
}, this.#opts.heartbeatMs);
|
|
161
238
|
this.#heartbeatTimer.unref?.();
|
|
239
|
+
await this.#server.listen();
|
|
240
|
+
await this.#emit("info", "owner_started", { ownerId: this.ownerId, leaseEpoch: this.#leaseEpoch });
|
|
241
|
+
if (this.#opts.transport.onEventFrame) {
|
|
242
|
+
this.#unsubscribeFrames = this.#opts.transport.onEventFrame(frame => this.#handleFrame(frame));
|
|
243
|
+
}
|
|
162
244
|
return { ownerId: this.ownerId, socketPath: this.#socketPath, leaseEpoch: this.#leaseEpoch };
|
|
163
245
|
}
|
|
164
246
|
|
|
@@ -175,13 +257,18 @@ export class RuntimeOwner {
|
|
|
175
257
|
|
|
176
258
|
/** Map an RPC frame and route it: semantic/signal-bearing -> serial emit; high-frequency progress -> coalesce. */
|
|
177
259
|
#handleFrame(frame: Record<string, unknown>): void {
|
|
178
|
-
const mapped =
|
|
260
|
+
const mapped = observeAgentWireFrame(frame);
|
|
179
261
|
if (!mapped) return;
|
|
180
262
|
if (mapped.semantic || (mapped.signal && !mapped.coalesceKey)) {
|
|
181
263
|
this.#framePump = this.#framePump
|
|
182
|
-
.then(() =>
|
|
183
|
-
|
|
184
|
-
|
|
264
|
+
.then(async () => {
|
|
265
|
+
if (this.#framePumpFailure !== null) return;
|
|
266
|
+
await this.#flushCoalesced();
|
|
267
|
+
await this.#emitMapped(mapped);
|
|
268
|
+
})
|
|
269
|
+
.catch(error => {
|
|
270
|
+
if (this.#framePumpFailure === null) this.#framePumpFailure = error;
|
|
271
|
+
});
|
|
185
272
|
} else if (mapped.coalesceKey) {
|
|
186
273
|
// Coalesce progress-noise by key; never enqueues a per-frame emit, so a message_update
|
|
187
274
|
// storm cannot starve semantic frames. Bound memory.
|
|
@@ -197,7 +284,7 @@ export class RuntimeOwner {
|
|
|
197
284
|
if (this.#coalesced.size === 0) return;
|
|
198
285
|
const coalescedFrames = this.#coalesced.size;
|
|
199
286
|
this.#coalesced.clear();
|
|
200
|
-
await this.#emit("info", "rpc_activity", { coalescedFrames });
|
|
287
|
+
await this.#emit("info", "rpc_activity", { coalescedFrames }, true);
|
|
201
288
|
}
|
|
202
289
|
|
|
203
290
|
async #emitMapped(mapped: AgentWireOwnerObservation): Promise<void> {
|
|
@@ -211,13 +298,14 @@ export class RuntimeOwner {
|
|
|
211
298
|
) {
|
|
212
299
|
state.lifecycle = "finalizing";
|
|
213
300
|
state.updatedAt = new Date(this.#opts.clock ? this.#opts.clock() : Date.now()).toISOString();
|
|
214
|
-
await writeSessionState(this.#opts.root, state);
|
|
301
|
+
await this.#framePersistence.writeSessionState(this.#opts.root, state);
|
|
215
302
|
}
|
|
216
303
|
}
|
|
217
304
|
await this.#emit(
|
|
218
305
|
mapped.severity,
|
|
219
306
|
mapped.kind,
|
|
220
307
|
mapped.signal ? { ...mapped.evidence, signal: mapped.signal } : mapped.evidence,
|
|
308
|
+
true,
|
|
221
309
|
);
|
|
222
310
|
}
|
|
223
311
|
|
|
@@ -248,7 +336,12 @@ export class RuntimeOwner {
|
|
|
248
336
|
return rpcActive ? "rpc-not-idle" : null;
|
|
249
337
|
}
|
|
250
338
|
|
|
251
|
-
async #emit(
|
|
339
|
+
async #emit(
|
|
340
|
+
severity: Severity,
|
|
341
|
+
kind: string,
|
|
342
|
+
evidence: Record<string, unknown>,
|
|
343
|
+
framePersistence = false,
|
|
344
|
+
): Promise<void> {
|
|
252
345
|
const lease = await readLease(this.#opts.root, this.#opts.sessionId);
|
|
253
346
|
// Single-writer guard: only emit while we still hold a live lease.
|
|
254
347
|
if (!lease || !canWriteEvents(lease, this.ownerId, this.#opts.clock)) return;
|
|
@@ -274,7 +367,11 @@ export class RuntimeOwner {
|
|
|
274
367
|
nextAllowedActions: nextAllowedActions(view.lifecycle, true, { submitUnavailableReason: submitGateReason }),
|
|
275
368
|
writer: { ownerId: this.ownerId, leaseEpoch: this.#leaseEpoch },
|
|
276
369
|
};
|
|
277
|
-
await
|
|
370
|
+
await (framePersistence ? this.#framePersistence.appendEvent : appendEvent)(
|
|
371
|
+
this.#opts.root,
|
|
372
|
+
this.#opts.sessionId,
|
|
373
|
+
envelope,
|
|
374
|
+
);
|
|
278
375
|
}
|
|
279
376
|
|
|
280
377
|
#response(
|
|
@@ -291,7 +388,7 @@ export class RuntimeOwner {
|
|
|
291
388
|
};
|
|
292
389
|
}
|
|
293
390
|
|
|
294
|
-
#submitGateReason(state: SessionState, rpcState:
|
|
391
|
+
#submitGateReason(state: SessionState, rpcState: SessionStateSnapshot | null): string | null {
|
|
295
392
|
const rpcReason = rpcState
|
|
296
393
|
? rpcState.isStreaming || rpcState.steeringQueueDepth > 0 || rpcState.followupQueueDepth > 0
|
|
297
394
|
? "rpc-not-idle"
|
|
@@ -333,9 +430,9 @@ export class RuntimeOwner {
|
|
|
333
430
|
const state = await this.#loadState();
|
|
334
431
|
const workspace = state.handle.workspace;
|
|
335
432
|
let streaming = false;
|
|
336
|
-
let rpcState:
|
|
433
|
+
let rpcState: SessionStateSnapshot | null = null;
|
|
337
434
|
try {
|
|
338
|
-
rpcState = await this.#opts.
|
|
435
|
+
rpcState = await this.#opts.transport.getState();
|
|
339
436
|
streaming = rpcState.isStreaming;
|
|
340
437
|
} catch {
|
|
341
438
|
streaming = false;
|
|
@@ -366,8 +463,8 @@ export class RuntimeOwner {
|
|
|
366
463
|
gitDelta = "unknown";
|
|
367
464
|
}
|
|
368
465
|
}
|
|
369
|
-
const rpcLive = this.#opts.
|
|
370
|
-
const rpcLastFrameAt = this.#opts.
|
|
466
|
+
const rpcLive = this.#opts.transport.isLive ? this.#opts.transport.isLive() : rpcState !== null;
|
|
467
|
+
const rpcLastFrameAt = this.#opts.transport.lastFrameAt ? this.#opts.transport.lastFrameAt() : null;
|
|
371
468
|
// Sticky semantic signals come from the persisted owner event log -> survive polling gaps.
|
|
372
469
|
const recent = (await readEvents(this.#opts.root, this.#opts.sessionId, 0)).slice(-200);
|
|
373
470
|
const observedSignals = this.#aggregateSignals(recent).slice(0, 7);
|
|
@@ -519,7 +616,7 @@ export class RuntimeOwner {
|
|
|
519
616
|
sessionId: this.#opts.sessionId,
|
|
520
617
|
workspace: state.handle.workspace,
|
|
521
618
|
branch: state.handle.branch ?? "",
|
|
522
|
-
|
|
619
|
+
transport: this.#opts.transport,
|
|
523
620
|
observe: () => this.#observeGit(),
|
|
524
621
|
finalizeChecks: this.#finalizeChecks ?? defaultFinalizeChecks(state.handle.workspace),
|
|
525
622
|
validationCommands: this.#validationCommands,
|
|
@@ -544,8 +641,8 @@ export class RuntimeOwner {
|
|
|
544
641
|
// Review-only finalize with no explicit verdict pulls the final assistant text from the live
|
|
545
642
|
// RPC owner so the verdict can be extracted deterministically instead of demanded from the operator.
|
|
546
643
|
let assistantText: string | null = null;
|
|
547
|
-
if (reviewOnly && inputVerdict == null && this.#opts.
|
|
548
|
-
assistantText = await this.#opts.
|
|
644
|
+
if (reviewOnly && inputVerdict == null && this.#opts.transport.getLastAssistantText) {
|
|
645
|
+
assistantText = await this.#opts.transport.getLastAssistantText().catch(() => null);
|
|
549
646
|
}
|
|
550
647
|
const fin = await runFinalize({
|
|
551
648
|
root: this.#opts.root,
|
|
@@ -595,7 +692,7 @@ export class RuntimeOwner {
|
|
|
595
692
|
lifecycleGate,
|
|
596
693
|
);
|
|
597
694
|
}
|
|
598
|
-
const result = await singleFlightAccept(this.#opts.
|
|
695
|
+
const result = await singleFlightAccept(this.#opts.transport, prompt, this.#opts.acceptanceTimeoutMs);
|
|
599
696
|
if (result.accepted) {
|
|
600
697
|
state.lifecycle = "observing";
|
|
601
698
|
state.updatedAt = new Date(this.#opts.clock ? this.#opts.clock() : Date.now()).toISOString();
|
|
@@ -625,7 +722,31 @@ export class RuntimeOwner {
|
|
|
625
722
|
}
|
|
626
723
|
|
|
627
724
|
async #observe(): Promise<PrimitiveResponse> {
|
|
725
|
+
// Observation is a read barrier over every frame accepted before this request.
|
|
726
|
+
// Without it, a fast poll can read state/event storage while the serial frame
|
|
727
|
+
// pump is still persisting a terminal event, losing sticky completion evidence.
|
|
728
|
+
await this.#framePump;
|
|
628
729
|
const state = await this.#loadState();
|
|
730
|
+
if (this.#framePumpFailure !== null) {
|
|
731
|
+
const failedState: SessionState = {
|
|
732
|
+
...state,
|
|
733
|
+
lifecycle: "blocked",
|
|
734
|
+
blockers: [...new Set([...state.blockers, "frame-persistence-failed"])],
|
|
735
|
+
};
|
|
736
|
+
return this.#response(
|
|
737
|
+
failedState,
|
|
738
|
+
{
|
|
739
|
+
observation: {
|
|
740
|
+
lifecycle: "blocked",
|
|
741
|
+
observedSignals: ["frame-persistence-failed"],
|
|
742
|
+
rpcLive: this.#opts.transport.isLive?.() ?? true,
|
|
743
|
+
},
|
|
744
|
+
framePumpFailure: { severity: "critical", error: String(this.#framePumpFailure) },
|
|
745
|
+
ownerRouted: true,
|
|
746
|
+
},
|
|
747
|
+
false,
|
|
748
|
+
);
|
|
749
|
+
}
|
|
629
750
|
const observation = await this.#observeGit();
|
|
630
751
|
const submitGateReason =
|
|
631
752
|
typeof observation.submitUnavailableReason === "string" ? observation.submitUnavailableReason : null;
|
|
@@ -638,21 +759,144 @@ export class RuntimeOwner {
|
|
|
638
759
|
state.updatedAt = new Date(this.#opts.clock ? this.#opts.clock() : Date.now()).toISOString();
|
|
639
760
|
await writeSessionState(this.#opts.root, state);
|
|
640
761
|
await this.#emit("info", "owner_retired", {});
|
|
641
|
-
queueMicrotask(() => void this.stop());
|
|
762
|
+
queueMicrotask(() => void this.stop().catch(() => {}));
|
|
642
763
|
return this.#response(state, { retired: true });
|
|
643
764
|
}
|
|
644
765
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
766
|
+
stop(): Promise<void> {
|
|
767
|
+
// Every public caller receives the one truthful shared teardown result. Only
|
|
768
|
+
// the object capability passed to the exact transport.close() invocation can
|
|
769
|
+
// break a direct cleanup cycle; ambient synchronous callers have no bypass.
|
|
770
|
+
if (this.#stopPromise) return this.#stopPromise;
|
|
771
|
+
const pending = Promise.withResolvers<void>();
|
|
772
|
+
this.#stopPromise = pending.promise;
|
|
773
|
+
void this.#stopUntilVerified().then(pending.resolve, pending.reject);
|
|
774
|
+
return pending.promise;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
#closeTransport(): Promise<void> {
|
|
778
|
+
let available = true;
|
|
779
|
+
// `available` is the authority boundary; freezing the wrapper is only
|
|
780
|
+
// defense-in-depth against mutation by the receiving transport.
|
|
781
|
+
const context: HarnessSessionTransportCloseContext = Object.freeze({
|
|
782
|
+
acknowledgeDirectOwnerStopReentry(): Promise<void> {
|
|
783
|
+
if (!available) throw new Error("Runtime owner direct stop reentry capability is no longer available.");
|
|
784
|
+
available = false;
|
|
785
|
+
return Promise.resolve();
|
|
786
|
+
},
|
|
787
|
+
});
|
|
788
|
+
try {
|
|
789
|
+
return this.#opts.transport.close(context);
|
|
790
|
+
} finally {
|
|
791
|
+
// An async close implementation runs synchronously until it returns its
|
|
792
|
+
// promise. Expire the capability at that boundary so descendants cannot
|
|
793
|
+
// acquire completion authority after the direct invocation.
|
|
794
|
+
available = false;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
async #stopUntilVerified(): Promise<void> {
|
|
799
|
+
this.#lastStopFailures = [];
|
|
800
|
+
this.#reportedStopFailures.clear();
|
|
801
|
+
for (let attempt = 1; ; attempt++) {
|
|
802
|
+
try {
|
|
803
|
+
await this.#stopOnce();
|
|
804
|
+
if (this.#framePumpFailure !== null) {
|
|
805
|
+
throw new FramePumpAfterVerifiedCleanupError(
|
|
806
|
+
[this.#framePumpFailure, ...flattenAggregateCauses(this.#lastStopFailures)],
|
|
807
|
+
`Runtime owner frame pump failed after verified cleanup: ${String(this.#framePumpFailure)}`,
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
return;
|
|
811
|
+
} catch (error) {
|
|
812
|
+
if (error instanceof FramePumpAfterVerifiedCleanupError) throw error;
|
|
813
|
+
if (this.#lastStopFailures.length === MAX_RETAINED_CLEANUP_FAILURES) this.#lastStopFailures.shift();
|
|
814
|
+
this.#lastStopFailures.push(error);
|
|
815
|
+
if (attempt >= this.#opts.cleanupRetryLimit)
|
|
816
|
+
throw new AggregateError(
|
|
817
|
+
[
|
|
818
|
+
...(this.#framePumpFailure === null ? [] : [this.#framePumpFailure]),
|
|
819
|
+
...flattenAggregateCauses(this.#lastStopFailures),
|
|
820
|
+
],
|
|
821
|
+
"Runtime owner cleanup could not be verified.",
|
|
822
|
+
);
|
|
823
|
+
await Bun.sleep(this.#opts.cleanupRetryMs);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
async #reportStopFailure(kind: string, error: unknown): Promise<unknown | null> {
|
|
829
|
+
if (this.#reportedStopFailures.has(kind)) return null;
|
|
830
|
+
this.#reportedStopFailures.add(kind);
|
|
831
|
+
try {
|
|
832
|
+
await this.#emit("critical", kind, { error: String(error) });
|
|
833
|
+
return null;
|
|
834
|
+
} catch (reportError) {
|
|
835
|
+
return reportError;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
async #stopOnce(): Promise<void> {
|
|
840
|
+
const failures: unknown[] = [];
|
|
841
|
+
const recordFailure = async (kind: string, error: unknown): Promise<void> => {
|
|
842
|
+
failures.push(error);
|
|
843
|
+
const reportFailure = await this.#reportStopFailure(kind, error);
|
|
844
|
+
if (reportFailure !== null) failures.push(reportFailure);
|
|
845
|
+
};
|
|
846
|
+
const unsubscribe = this.#unsubscribeFrames;
|
|
847
|
+
if (unsubscribe) {
|
|
848
|
+
try {
|
|
849
|
+
unsubscribe();
|
|
850
|
+
this.#unsubscribeFrames = null;
|
|
851
|
+
} catch (error) {
|
|
852
|
+
await recordFailure("owner_unsubscribe_failed", error);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
await this.#framePump;
|
|
856
|
+
|
|
857
|
+
// The transport owns the exact spawned child. Do not surrender the lease while
|
|
858
|
+
// it is unverified; once each stage succeeds, retain that proof across retries.
|
|
859
|
+
if (!this.#transportClosed) {
|
|
860
|
+
try {
|
|
861
|
+
await this.#closeTransport();
|
|
862
|
+
this.#transportClosed = true;
|
|
863
|
+
} catch (error) {
|
|
864
|
+
await recordFailure("owner_transport_stop_failed", error);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
if (!this.#transportClosed) throw new AggregateError(failures, "Runtime owner transport cleanup failed.");
|
|
868
|
+
|
|
869
|
+
if (!this.#serverClosed) {
|
|
870
|
+
try {
|
|
871
|
+
await this.#server.close();
|
|
872
|
+
this.#serverClosed = true;
|
|
873
|
+
} catch (error) {
|
|
874
|
+
await recordFailure("owner_server_stop_failed", error);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (!this.#serverClosed) throw new AggregateError(failures, "Runtime owner endpoint cleanup failed.");
|
|
878
|
+
|
|
879
|
+
if (this.#leaseHeld) {
|
|
880
|
+
try {
|
|
881
|
+
await this.#opts.leaseRelease(this.#opts.root, this.#opts.sessionId, this.ownerId);
|
|
882
|
+
this.#leaseHeld = false;
|
|
883
|
+
} catch (error) {
|
|
884
|
+
if (error instanceof LeaseError && error.code === "not_lease_holder") {
|
|
885
|
+
// A successor already owns the lease. Our transport and endpoint are
|
|
886
|
+
// verified closed, so there is no old authority left to release.
|
|
887
|
+
this.#leaseHeld = false;
|
|
888
|
+
} else {
|
|
889
|
+
await recordFailure("owner_lease_release_failed", error);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
if (this.#leaseHeld) throw new AggregateError(failures, "Runtime owner lease cleanup failed.");
|
|
894
|
+
|
|
649
895
|
if (this.#heartbeatTimer) {
|
|
650
896
|
clearInterval(this.#heartbeatTimer);
|
|
651
897
|
this.#heartbeatTimer = null;
|
|
652
898
|
}
|
|
653
|
-
|
|
654
|
-
await this.#opts.rpc.close().catch(() => {});
|
|
655
|
-
await releaseLease(this.#opts.root, this.#opts.sessionId, this.ownerId).catch(() => {});
|
|
899
|
+
if (failures.length > 0) throw new AggregateError(failures, "Runtime owner cleanup failed.");
|
|
656
900
|
}
|
|
657
901
|
}
|
|
658
902
|
|
|
@@ -163,7 +163,6 @@ export interface VanishEvidence {
|
|
|
163
163
|
|
|
164
164
|
export interface PromptAcceptanceEvidence {
|
|
165
165
|
promptSha256: string;
|
|
166
|
-
rpcCommandId: string;
|
|
167
166
|
preSubmitState: { isStreaming: boolean; steeringQueueDepth: number; followupQueueDepth: number };
|
|
168
167
|
preSubmitCursor: number;
|
|
169
168
|
agentStartCursor: number;
|