@gajae-code/coding-agent 0.10.2 → 0.11.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 +58 -2
- package/dist/types/append-only-mode.d.ts +1 -1
- package/dist/types/async/job-manager.d.ts +46 -7
- 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/ultragoal-receipt-freshness.d.ts +11 -0
- 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/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
- 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 +5 -2
- 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 +170 -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 +7 -2
- 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 +42 -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 +50 -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 +78 -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/dist/types/tools/subagent-render.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +6 -1
- package/package.json +34 -13
- package/scripts/build-sdk-package-smoke.ts +99 -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/async/job-manager.ts +406 -63
- 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 +108 -14
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
- 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 +10 -17
- package/src/modes/controllers/event-controller.ts +11 -16
- package/src/modes/controllers/extension-ui-controller.ts +396 -28
- package/src/modes/controllers/selector-controller.ts +674 -36
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +87 -36
- 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 +1258 -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 +7 -2
- 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 +113 -0
- package/src/sdk/broker/ensure.ts +307 -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 +355 -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 +2292 -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 +3979 -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 +603 -63
- 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 +2650 -944
- 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/task/index.ts +26 -16
- 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/subagent-render.ts +19 -8
- package/src/tools/subagent.ts +84 -32
- 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
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { processIncarnation } from "./process-incarnation";
|
|
5
|
+
import { assertSupportedStateVersion, SDK_STATE_VERSION } from "./state-version";
|
|
6
|
+
|
|
7
|
+
export const BROKER_HEARTBEAT_TTL_MS = 15_000;
|
|
8
|
+
export interface BrokerDiscovery {
|
|
9
|
+
version: typeof SDK_STATE_VERSION;
|
|
10
|
+
protocolVersion: 3;
|
|
11
|
+
packageGeneration: string;
|
|
12
|
+
ownerId: string;
|
|
13
|
+
pid: number;
|
|
14
|
+
incarnation: string;
|
|
15
|
+
host: "127.0.0.1";
|
|
16
|
+
port: number;
|
|
17
|
+
url: string;
|
|
18
|
+
token: string;
|
|
19
|
+
startedAt: number;
|
|
20
|
+
heartbeatAt: number;
|
|
21
|
+
}
|
|
22
|
+
export type RedactedBrokerDiscovery = Omit<BrokerDiscovery, "token"> & { token: "[redacted]" };
|
|
23
|
+
export type BrokerDiscoveryWrite = Omit<BrokerDiscovery, "incarnation"> & { incarnation?: string };
|
|
24
|
+
export const brokerDiscoveryPath = (agentDir: string) => path.join(agentDir, "sdk", "broker.json");
|
|
25
|
+
export const newBrokerToken = () => randomBytes(32).toString("hex");
|
|
26
|
+
export const brokerProcessIncarnation = processIncarnation;
|
|
27
|
+
export function isPidAlive(pid: number): boolean {
|
|
28
|
+
try {
|
|
29
|
+
process.kill(pid, 0);
|
|
30
|
+
return true;
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return (e as NodeJS.ErrnoException).code === "EPERM";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function syncFile(file: string): Promise<void> {
|
|
36
|
+
const handle = await fs.open(file, "r");
|
|
37
|
+
try {
|
|
38
|
+
await handle.sync();
|
|
39
|
+
} finally {
|
|
40
|
+
await handle.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function syncDirectory(directory: string): Promise<void> {
|
|
45
|
+
let handle: fs.FileHandle;
|
|
46
|
+
try {
|
|
47
|
+
handle = await fs.open(directory, "r");
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
50
|
+
if (process.platform === "win32" && (code === "EPERM" || code === "EACCES")) return;
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await handle.sync();
|
|
55
|
+
} catch (error) {
|
|
56
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
57
|
+
if (process.platform !== "win32" || (code !== "EPERM" && code !== "EACCES")) throw error;
|
|
58
|
+
} finally {
|
|
59
|
+
await handle.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function writeBrokerDiscovery(agentDir: string, discovery: BrokerDiscoveryWrite): Promise<void> {
|
|
63
|
+
const incarnation = discovery.incarnation ?? brokerProcessIncarnation(discovery.pid);
|
|
64
|
+
if (!incarnation) throw new Error(`Broker process incarnation is unavailable for pid ${discovery.pid}.`);
|
|
65
|
+
const record: BrokerDiscovery = { ...discovery, incarnation };
|
|
66
|
+
const file = brokerDiscoveryPath(agentDir);
|
|
67
|
+
const dir = path.dirname(file);
|
|
68
|
+
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
69
|
+
await fs.chmod(dir, 0o700);
|
|
70
|
+
const temp = `${file}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
71
|
+
try {
|
|
72
|
+
await fs.writeFile(temp, `${JSON.stringify(record)}\n`, { mode: 0o600 });
|
|
73
|
+
await fs.chmod(temp, 0o600);
|
|
74
|
+
await syncFile(temp);
|
|
75
|
+
await fs.rename(temp, file);
|
|
76
|
+
await syncDirectory(dir);
|
|
77
|
+
} finally {
|
|
78
|
+
await fs.rm(temp, { force: true });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function readBrokerDiscovery(
|
|
82
|
+
agentDir: string,
|
|
83
|
+
ttlMs = BROKER_HEARTBEAT_TTL_MS,
|
|
84
|
+
): Promise<BrokerDiscovery | null> {
|
|
85
|
+
try {
|
|
86
|
+
const raw: unknown = JSON.parse(await fs.readFile(brokerDiscoveryPath(agentDir), "utf8"));
|
|
87
|
+
if (!raw || typeof raw !== "object") return null;
|
|
88
|
+
assertSupportedStateVersion(brokerDiscoveryPath(agentDir), raw);
|
|
89
|
+
const d = raw as BrokerDiscovery;
|
|
90
|
+
if (
|
|
91
|
+
d.version !== SDK_STATE_VERSION ||
|
|
92
|
+
d.protocolVersion !== 3 ||
|
|
93
|
+
d.host !== "127.0.0.1" ||
|
|
94
|
+
!d.token ||
|
|
95
|
+
!Number.isSafeInteger(d.pid) ||
|
|
96
|
+
d.pid <= 0 ||
|
|
97
|
+
typeof d.incarnation !== "string" ||
|
|
98
|
+
d.incarnation.length === 0 ||
|
|
99
|
+
!Number.isFinite(d.heartbeatAt)
|
|
100
|
+
)
|
|
101
|
+
return null;
|
|
102
|
+
if (!isPidAlive(d.pid)) return null;
|
|
103
|
+
const incarnation = brokerProcessIncarnation(d.pid);
|
|
104
|
+
if (!incarnation || incarnation !== d.incarnation || Date.now() - d.heartbeatAt > ttlMs) return null;
|
|
105
|
+
return d;
|
|
106
|
+
} catch (e) {
|
|
107
|
+
if ((e as NodeJS.ErrnoException).code === "ENOENT" || e instanceof SyntaxError) return null;
|
|
108
|
+
throw e;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function redactBrokerDiscovery(discovery: BrokerDiscovery): RedactedBrokerDiscovery {
|
|
112
|
+
return { ...discovery, token: "[redacted]" };
|
|
113
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { type ChildProcess, spawn } from "node:child_process";
|
|
2
|
+
import { type BrokerDiscovery, brokerProcessIncarnation, readBrokerDiscovery } from "./discovery";
|
|
3
|
+
import { resolveSdkInternalSpawnCommand, type SdkInternalSpawnCommand } from "./runtime";
|
|
4
|
+
export interface EnsureBrokerSettings {
|
|
5
|
+
agentDir: string;
|
|
6
|
+
heartbeatTtlMs?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Environment for the spawned detached broker. Defaults to `process.env`; tests
|
|
9
|
+
* that pre-start an isolated broker pass the same sanitized child env so the
|
|
10
|
+
* broker and the child that attaches to it share one owned root.
|
|
11
|
+
*/
|
|
12
|
+
env?: NodeJS.ProcessEnv;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const DISCOVERY_TIMEOUT_MS = 10_000;
|
|
16
|
+
// Bounded grace windows for reaping a spawned broker on failure, mirroring the
|
|
17
|
+
// owned-process teardown convention (SIGTERM -> grace -> SIGKILL -> hard cap).
|
|
18
|
+
const REAP_GRACEFUL_MS = 2_000;
|
|
19
|
+
const REAP_SIGKILL_CAP_MS = 2_000;
|
|
20
|
+
export interface FixtureBrokerLease {
|
|
21
|
+
close(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface StartedFixtureBroker {
|
|
25
|
+
discovery: BrokerDiscovery;
|
|
26
|
+
lease: FixtureBrokerLease;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface BrokerOwner {
|
|
30
|
+
stop(): Promise<void>;
|
|
31
|
+
canReuse(discovery: BrokerDiscovery | null): boolean;
|
|
32
|
+
markReady(discovery: BrokerDiscovery): boolean;
|
|
33
|
+
}
|
|
34
|
+
type EnsureInitiator = "discovery" | "fixture-lease";
|
|
35
|
+
type EnsureOutcome =
|
|
36
|
+
| { kind: "external-discovery"; discovery: BrokerDiscovery }
|
|
37
|
+
| { kind: "prior-local-owner"; discovery: BrokerDiscovery; owner: BrokerOwner }
|
|
38
|
+
| { kind: "local-started-discovery"; discovery: BrokerDiscovery }
|
|
39
|
+
| { kind: "local-started-fixture"; discovery: BrokerDiscovery; owner: BrokerOwner };
|
|
40
|
+
interface EnsureInFlight {
|
|
41
|
+
initiator: EnsureInitiator;
|
|
42
|
+
promise: Promise<EnsureOutcome>;
|
|
43
|
+
discovery: Promise<BrokerDiscovery>;
|
|
44
|
+
}
|
|
45
|
+
const owners = new Map<string, BrokerOwner>();
|
|
46
|
+
const ensureInFlight = new Map<string, EnsureInFlight>();
|
|
47
|
+
const reapErrorGuards = new WeakSet<ChildProcess>();
|
|
48
|
+
interface ReapTiming {
|
|
49
|
+
gracefulMs: number;
|
|
50
|
+
killVerifyMs: number;
|
|
51
|
+
}
|
|
52
|
+
const DEFAULT_REAP_TIMING: ReapTiming = {
|
|
53
|
+
gracefulMs: REAP_GRACEFUL_MS,
|
|
54
|
+
killVerifyMs: REAP_SIGKILL_CAP_MS,
|
|
55
|
+
};
|
|
56
|
+
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Terminate and reap a detached broker this process spawned, targeting the exact
|
|
60
|
+
* owned {@link ChildProcess} (never by name). SIGTERM escalates to SIGKILL after
|
|
61
|
+
* a bounded grace window; a child still alive after SIGKILL is surfaced rather
|
|
62
|
+
* than silently orphaned. Reaping is idempotent once the child has exited.
|
|
63
|
+
*
|
|
64
|
+
* Termination is proven only by an observed exit — an `exit`/`close` event or a
|
|
65
|
+
* non-null `exitCode`/`signalCode`. A still-live child can emit `error` during
|
|
66
|
+
* teardown (e.g. a transient signal-delivery failure); that is diagnostic only
|
|
67
|
+
* and never counts as exit, so the escalation cannot be skipped mid-shutdown.
|
|
68
|
+
*/
|
|
69
|
+
async function reapSpawnedBroker(child: ChildProcess, timing: ReapTiming = DEFAULT_REAP_TIMING): Promise<void> {
|
|
70
|
+
// A spawn failure (e.g. ENOENT) never created a kernel process: pid is
|
|
71
|
+
// undefined and there is nothing to signal or await. The `error` event is the
|
|
72
|
+
// only signal and is diagnostic here — termination trivially holds, so do not
|
|
73
|
+
// run out the TERM/KILL windows or report a stuck child that never existed.
|
|
74
|
+
if (child.pid === undefined) return;
|
|
75
|
+
// Reaping owns repeated teardown diagnostics too. Keep exactly one error
|
|
76
|
+
// listener for the retained child so a later signal-delivery error cannot
|
|
77
|
+
// become an unhandled EventEmitter error after the spawn listener is consumed.
|
|
78
|
+
if (!reapErrorGuards.has(child)) {
|
|
79
|
+
child.on("error", () => {});
|
|
80
|
+
reapErrorGuards.add(child);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Awaits an authoritative exit signal, never a transient `error`. Resolves on
|
|
84
|
+
// an `exit`/`close` event or when the codes are already set; the caller
|
|
85
|
+
// re-checks the codes after the race, so resolution alone is never proof.
|
|
86
|
+
const awaitVerifiedExit = (): Promise<void> => {
|
|
87
|
+
const { promise, resolve } = Promise.withResolvers<void>();
|
|
88
|
+
if (child.exitCode !== null || child.signalCode !== null) resolve();
|
|
89
|
+
else {
|
|
90
|
+
child.once("exit", () => resolve());
|
|
91
|
+
child.once("close", () => resolve());
|
|
92
|
+
}
|
|
93
|
+
return promise;
|
|
94
|
+
};
|
|
95
|
+
// Observed exit is authoritative: only non-null exit/signal codes prove the
|
|
96
|
+
// child is gone, regardless of which event (if any) resolved the wait.
|
|
97
|
+
const hasExited = (): boolean => child.exitCode !== null || child.signalCode !== null;
|
|
98
|
+
const signal = (sig: NodeJS.Signals): void => {
|
|
99
|
+
if (hasExited()) return;
|
|
100
|
+
try {
|
|
101
|
+
child.kill(sig);
|
|
102
|
+
} catch {
|
|
103
|
+
// already exited between the liveness check and the kill
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
if (hasExited()) return;
|
|
107
|
+
signal("SIGTERM");
|
|
108
|
+
await Promise.race([awaitVerifiedExit(), sleep(timing.gracefulMs)]);
|
|
109
|
+
if (hasExited()) return;
|
|
110
|
+
signal("SIGKILL");
|
|
111
|
+
await Promise.race([awaitVerifiedExit(), sleep(timing.killVerifyMs)]);
|
|
112
|
+
if (hasExited()) return;
|
|
113
|
+
// SIGKILL is uninterruptible; a child still alive past this bounded wait is a
|
|
114
|
+
// kernel-level stuck state. Surface it rather than silently orphaning the spawn.
|
|
115
|
+
throw new Error(`Detached SDK broker (pid ${child.pid}) did not exit after SIGKILL during reap.`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function registerBrokerOwner(
|
|
119
|
+
agentDir: string,
|
|
120
|
+
child: ChildProcess,
|
|
121
|
+
timing: ReapTiming = DEFAULT_REAP_TIMING,
|
|
122
|
+
): BrokerOwner {
|
|
123
|
+
const incarnation = child.pid === undefined ? undefined : brokerProcessIncarnation(child.pid);
|
|
124
|
+
let state: "starting" | "ready" | "cleanup-unverified" = "starting";
|
|
125
|
+
const matches = (discovery: BrokerDiscovery | null): boolean =>
|
|
126
|
+
Boolean(
|
|
127
|
+
discovery &&
|
|
128
|
+
child.pid !== undefined &&
|
|
129
|
+
incarnation &&
|
|
130
|
+
discovery.pid === child.pid &&
|
|
131
|
+
discovery.incarnation === incarnation,
|
|
132
|
+
);
|
|
133
|
+
const owner: BrokerOwner = {
|
|
134
|
+
async stop(): Promise<void> {
|
|
135
|
+
try {
|
|
136
|
+
await reapSpawnedBroker(child, timing);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
state = "cleanup-unverified";
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
if (owners.get(agentDir) === owner) owners.delete(agentDir);
|
|
142
|
+
},
|
|
143
|
+
canReuse(discovery): boolean {
|
|
144
|
+
return state === "ready" && matches(discovery);
|
|
145
|
+
},
|
|
146
|
+
markReady(discovery): boolean {
|
|
147
|
+
if (!matches(discovery)) return false;
|
|
148
|
+
state = "ready";
|
|
149
|
+
return true;
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
owners.set(agentDir, owner);
|
|
153
|
+
return owner;
|
|
154
|
+
}
|
|
155
|
+
function brokerSpawnEnvironment(command: SdkInternalSpawnCommand, override?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
156
|
+
const environment = { ...(override ?? command.env) };
|
|
157
|
+
delete environment.BUN_OPTIONS;
|
|
158
|
+
if (command.kind === "bun-source") {
|
|
159
|
+
delete environment.PI_COMPILED;
|
|
160
|
+
delete environment.GJC_COMPILED;
|
|
161
|
+
}
|
|
162
|
+
return environment;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function fixtureLeaseUnavailable(): Error {
|
|
166
|
+
return new Error("fixture_broker_lease_unavailable");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function createFixtureLease(owner: BrokerOwner): FixtureBrokerLease {
|
|
170
|
+
let closeAttempt: Promise<void> | undefined;
|
|
171
|
+
let closed = false;
|
|
172
|
+
return {
|
|
173
|
+
close(): Promise<void> {
|
|
174
|
+
if (closed) return Promise.resolve();
|
|
175
|
+
if (closeAttempt) return closeAttempt;
|
|
176
|
+
closeAttempt = owner.stop().then(
|
|
177
|
+
() => {
|
|
178
|
+
closed = true;
|
|
179
|
+
},
|
|
180
|
+
(error: unknown) => {
|
|
181
|
+
closeAttempt = undefined;
|
|
182
|
+
throw error;
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
return closeAttempt;
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function ensureBrokerOnce(settings: EnsureBrokerSettings, initiator: EnsureInitiator): Promise<EnsureOutcome> {
|
|
191
|
+
const priorOwner = owners.get(settings.agentDir);
|
|
192
|
+
const existing = await readBrokerDiscovery(settings.agentDir, settings.heartbeatTtlMs);
|
|
193
|
+
if (initiator === "fixture-lease" && (priorOwner || existing)) throw fixtureLeaseUnavailable();
|
|
194
|
+
if (priorOwner) {
|
|
195
|
+
// A retained cleanup failure fences every discovery record. Only a ready
|
|
196
|
+
// record bound to this exact child incarnation may be reused.
|
|
197
|
+
if (priorOwner.canReuse(existing)) return { kind: "prior-local-owner", discovery: existing!, owner: priorOwner };
|
|
198
|
+
await priorOwner.stop();
|
|
199
|
+
const discoveredAfterCleanup = await readBrokerDiscovery(settings.agentDir, settings.heartbeatTtlMs);
|
|
200
|
+
if (discoveredAfterCleanup) return { kind: "external-discovery", discovery: discoveredAfterCleanup };
|
|
201
|
+
} else if (existing) {
|
|
202
|
+
return { kind: "external-discovery", discovery: existing };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const command = resolveSdkInternalSpawnCommand("broker-internal");
|
|
206
|
+
const child = spawn(command.file, [...command.args, "--agent-dir", settings.agentDir], {
|
|
207
|
+
detached: true,
|
|
208
|
+
stdio: "ignore",
|
|
209
|
+
env: brokerSpawnEnvironment(command, settings.env),
|
|
210
|
+
...(command.kind === "bun-source" ? { cwd: command.cwd } : {}),
|
|
211
|
+
});
|
|
212
|
+
child.unref();
|
|
213
|
+
let spawnError: Error | undefined;
|
|
214
|
+
child.once("error", error => {
|
|
215
|
+
spawnError = error;
|
|
216
|
+
});
|
|
217
|
+
const owner = registerBrokerOwner(settings.agentDir, child);
|
|
218
|
+
const deadline = Date.now() + DISCOVERY_TIMEOUT_MS;
|
|
219
|
+
let discoveryError: unknown;
|
|
220
|
+
while (Date.now() < deadline) {
|
|
221
|
+
if (spawnError || child.exitCode !== null || child.signalCode !== null) break;
|
|
222
|
+
try {
|
|
223
|
+
const discovered = await readBrokerDiscovery(settings.agentDir, settings.heartbeatTtlMs);
|
|
224
|
+
if (discovered) {
|
|
225
|
+
if (owner.markReady(discovered)) {
|
|
226
|
+
return initiator === "fixture-lease"
|
|
227
|
+
? { kind: "local-started-fixture", discovery: discovered, owner }
|
|
228
|
+
: { kind: "local-started-discovery", discovery: discovered };
|
|
229
|
+
}
|
|
230
|
+
await owner.stop();
|
|
231
|
+
return { kind: "external-discovery", discovery: discovered };
|
|
232
|
+
}
|
|
233
|
+
} catch (error) {
|
|
234
|
+
discoveryError = error;
|
|
235
|
+
}
|
|
236
|
+
await sleep(50);
|
|
237
|
+
}
|
|
238
|
+
const exitedBeforeDiscovery = child.exitCode !== null || child.signalCode !== null;
|
|
239
|
+
const failure = spawnError
|
|
240
|
+
? new Error(`Failed to spawn detached SDK broker: ${spawnError.message}`)
|
|
241
|
+
: exitedBeforeDiscovery
|
|
242
|
+
? new Error(
|
|
243
|
+
`Detached SDK broker exited before discovery (code=${child.exitCode}, signal=${child.signalCode}).`,
|
|
244
|
+
)
|
|
245
|
+
: discoveryError
|
|
246
|
+
? discoveryError
|
|
247
|
+
: new Error("Timed out waiting for detached SDK broker discovery.");
|
|
248
|
+
try {
|
|
249
|
+
await owner.stop();
|
|
250
|
+
} catch (cleanupError) {
|
|
251
|
+
throw new AggregateError([failure, cleanupError], "SDK broker discovery and spawned broker cleanup both failed.");
|
|
252
|
+
}
|
|
253
|
+
throw failure;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function startEnsure(settings: EnsureBrokerSettings, initiator: EnsureInitiator): EnsureInFlight {
|
|
257
|
+
const promise = ensureBrokerOnce(settings, initiator);
|
|
258
|
+
const discovery = promise.then(outcome => outcome.discovery);
|
|
259
|
+
void discovery.catch(() => {});
|
|
260
|
+
const entry = { initiator, promise, discovery };
|
|
261
|
+
ensureInFlight.set(settings.agentDir, entry);
|
|
262
|
+
const clear = (): void => {
|
|
263
|
+
if (ensureInFlight.get(settings.agentDir) === entry) ensureInFlight.delete(settings.agentDir);
|
|
264
|
+
};
|
|
265
|
+
void promise.then(clear, clear);
|
|
266
|
+
return entry;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Starts the detached broker entrypoint when discovery has no live owner. */
|
|
270
|
+
export function ensureBroker(settings: EnsureBrokerSettings): Promise<BrokerDiscovery> {
|
|
271
|
+
const inFlight = ensureInFlight.get(settings.agentDir) ?? startEnsure(settings, "discovery");
|
|
272
|
+
return inFlight.discovery;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** Starts one fresh fixture broker and returns its sole exact-child close lease. */
|
|
276
|
+
export function startFixtureBrokerWithLeaseForTest(settings: EnsureBrokerSettings): Promise<StartedFixtureBroker> {
|
|
277
|
+
if (ensureInFlight.has(settings.agentDir)) return Promise.reject(fixtureLeaseUnavailable());
|
|
278
|
+
const inFlight = startEnsure(settings, "fixture-lease");
|
|
279
|
+
return inFlight.promise.then(outcome => {
|
|
280
|
+
if (outcome.kind !== "local-started-fixture") throw fixtureLeaseUnavailable();
|
|
281
|
+
return { discovery: outcome.discovery, lease: createFixtureLease(outcome.owner) };
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** Test hook: returns a stop handle for the detached broker this process spawned. */
|
|
286
|
+
export function brokerOwnerForTest(agentDir: string): BrokerOwner | undefined {
|
|
287
|
+
return owners.get(agentDir);
|
|
288
|
+
}
|
|
289
|
+
/** Test hook: drives the detached-broker reap on a controllable child surface. */
|
|
290
|
+
export function reapSpawnedBrokerForTest(child: ChildProcess, timing: ReapTiming = DEFAULT_REAP_TIMING): Promise<void> {
|
|
291
|
+
return reapSpawnedBroker(child, timing);
|
|
292
|
+
}
|
|
293
|
+
/** Test hook: resolves the complete broker environment without spawning. */
|
|
294
|
+
export function brokerSpawnEnvironmentForTest(
|
|
295
|
+
command: SdkInternalSpawnCommand,
|
|
296
|
+
override?: NodeJS.ProcessEnv,
|
|
297
|
+
): NodeJS.ProcessEnv {
|
|
298
|
+
return brokerSpawnEnvironment(command, override);
|
|
299
|
+
}
|
|
300
|
+
/** Test hook: installs an exact controllable owner to exercise replacement fencing. */
|
|
301
|
+
export function registerBrokerOwnerForTest(
|
|
302
|
+
agentDir: string,
|
|
303
|
+
child: ChildProcess,
|
|
304
|
+
timing: ReapTiming = DEFAULT_REAP_TIMING,
|
|
305
|
+
): BrokerOwner {
|
|
306
|
+
return registerBrokerOwner(agentDir, child, timing);
|
|
307
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
const MODE = 0o600;
|
|
6
|
+
|
|
7
|
+
export function brokerIdentityPath(agentDir: string): string {
|
|
8
|
+
return path.join(agentDir, "sdk", "broker.identity");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function getBrokerIdentityKey(agentDir: string): Promise<string> {
|
|
12
|
+
const file = brokerIdentityPath(agentDir);
|
|
13
|
+
await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
14
|
+
try {
|
|
15
|
+
const key = (await fs.readFile(file, "utf8")).trim();
|
|
16
|
+
if (/^[0-9a-f]{64}$/i.test(key)) return key;
|
|
17
|
+
throw new Error(`Invalid broker identity key at ${file}`);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
20
|
+
const key = randomBytes(32).toString("hex");
|
|
21
|
+
try {
|
|
22
|
+
await fs.writeFile(file, `${key}\n`, { encoding: "utf8", mode: MODE, flag: "wx" });
|
|
23
|
+
await fs.chmod(file, MODE);
|
|
24
|
+
return key;
|
|
25
|
+
} catch (writeError) {
|
|
26
|
+
if ((writeError as NodeJS.ErrnoException).code !== "EEXIST") throw writeError;
|
|
27
|
+
return getBrokerIdentityKey(agentDir);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function deriveIdempotencyIdentity(
|
|
33
|
+
agentDir: string,
|
|
34
|
+
operation: string,
|
|
35
|
+
callerKey: string,
|
|
36
|
+
canonicalTargetHash: string,
|
|
37
|
+
): Promise<string> {
|
|
38
|
+
const key = await getBrokerIdentityKey(agentDir);
|
|
39
|
+
return createHmac("sha256", Buffer.from(key, "hex"))
|
|
40
|
+
.update(`3|${operation}|${callerKey}|${canonicalTargetHash}`)
|
|
41
|
+
.digest("hex");
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gjc-sdk-broker-internal-source-marker-2178
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Product-owned empty Bun configuration for isolated SDK-internal source children.
|