@gajae-code/coding-agent 0.17.1 → 0.17.4
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 +266 -0
- package/dist/types/async/job-manager.d.ts +7 -6
- package/dist/types/cli/daemon-cli.d.ts +3 -1
- package/dist/types/cli/github-release.d.ts +17 -0
- package/dist/types/cli/public-command-entry.d.ts +56 -0
- package/dist/types/cli/public-command-errors.d.ts +126 -0
- package/dist/types/cli/public-command-evidence.d.ts +99 -0
- package/dist/types/cli/public-command-help.d.ts +65 -0
- package/dist/types/cli/public-command-registry.d.ts +69 -0
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/cli/skills-cli.d.ts +5 -0
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +4 -50
- package/dist/types/commands/sdk.d.ts +20 -37
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/commands/skills.d.ts +9 -0
- package/dist/types/config/autorouting-tier-map.d.ts +24 -0
- package/dist/types/config/file-lock.d.ts +10 -1
- package/dist/types/config/model-profile-activation.d.ts +63 -4
- package/dist/types/config/model-registry.d.ts +20 -2
- package/dist/types/config/settings-schema.d.ts +11 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
- package/dist/types/coordinator-mcp/server.d.ts +3 -0
- package/dist/types/daemon/operator-contract.d.ts +5 -1
- package/dist/types/eval/js/worker-protocol.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +12 -0
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
- package/dist/types/extensibility/shared-events.d.ts +3 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
- package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/parse.d.ts +9 -1
- package/dist/types/main.d.ts +22 -0
- package/dist/types/modes/acp/acp-agent.d.ts +94 -1
- package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
- package/dist/types/modes/components/session-selector.d.ts +5 -2
- package/dist/types/modes/components/thinking-selector.d.ts +2 -1
- package/dist/types/modes/components/user-message-selector.d.ts +5 -2
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
- package/dist/types/modes/types.d.ts +2 -2
- package/dist/types/runtime/process-lifecycle.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +56 -0
- package/dist/types/runtime-mcp/pool.d.ts +17 -0
- package/dist/types/runtime-mcp/redaction.d.ts +20 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
- package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
- package/dist/types/sdk/acp/adapter.d.ts +27 -0
- package/dist/types/sdk/acp/final-text.d.ts +8 -0
- package/dist/types/sdk/broker/broker.d.ts +13 -2
- package/dist/types/sdk/broker/ensure.d.ts +46 -1
- package/dist/types/sdk/broker/identity.d.ts +3 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
- package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
- package/dist/types/sdk/broker/runtime.d.ts +1 -1
- package/dist/types/sdk/broker/session-index.d.ts +22 -3
- package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
- package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
- package/dist/types/sdk/bus/index.d.ts +19 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
- package/dist/types/sdk/cli/master-cli.d.ts +6 -10
- package/dist/types/sdk/cli/rows.d.ts +19 -1
- package/dist/types/sdk/cli/session-cli.d.ts +22 -5
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/guides/cli.d.ts +3 -4
- package/dist/types/sdk/guides/verify.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +9 -0
- package/dist/types/sdk/host/session-runtime.d.ts +31 -0
- package/dist/types/sdk/host/types.d.ts +10 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +38 -1
- package/dist/types/sdk/prompt-failure.d.ts +30 -1
- package/dist/types/sdk/prompt-status.d.ts +8 -0
- package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
- package/dist/types/sdk/router/replay-retention-gap-cache.d.ts +13 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/startup-capability.d.ts +2 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +73 -2
- package/dist/types/sdk/transport/stdio.d.ts +5 -1
- package/dist/types/session/agent-session.d.ts +168 -21
- package/dist/types/session/fallback-chain-controller.d.ts +6 -6
- package/dist/types/session/fold-coordinator.d.ts +17 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
- package/dist/types/session/session-manager.d.ts +64 -1
- package/dist/types/session/session-work-lease.d.ts +14 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
- package/dist/types/setup/provider-onboarding.d.ts +81 -1
- package/dist/types/thinking.d.ts +3 -1
- package/dist/types/tools/bash.d.ts +37 -11
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/steer-fold.d.ts +31 -0
- package/dist/types/utils/git.d.ts +28 -2
- package/dist/types/utils/mupdf-embedded.d.ts +2 -0
- package/dist/types/utils/mupdf-wasm-embedded.d.ts +2 -0
- package/dist/types/utils/mupdf.d.ts +4 -0
- package/dist/types/utils/session-title-generation.d.ts +6 -0
- package/dist/types/utils/title-generator.d.ts +11 -2
- package/dist/types/web/scrapers/types.d.ts +3 -0
- package/package.json +18 -10
- package/scripts/build-binary.ts +9 -3
- package/scripts/compile-args.ts +0 -9
- package/scripts/embed-mupdf.ts +52 -0
- package/scripts/generate-sdk-operation-inventory.ts +31 -1
- package/scripts/vendor-markit.ts +196 -0
- package/src/async/job-manager.ts +60 -9
- package/src/cli/daemon-cli.ts +53 -18
- package/src/cli/github-release.ts +87 -5
- package/src/cli/mcp-cli.ts +38 -4
- package/src/cli/public-command-entry.ts +450 -0
- package/src/cli/public-command-errors.ts +581 -0
- package/src/cli/public-command-evidence.ts +717 -0
- package/src/cli/public-command-help.ts +360 -0
- package/src/cli/public-command-registry.ts +535 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +9 -1
- package/src/cli/skills-cli.ts +46 -2
- package/src/cli.ts +61 -1
- package/src/commands/daemon.ts +65 -69
- package/src/commands/sdk.ts +232 -100
- package/src/commands/setup.ts +2 -0
- package/src/commands/skills.ts +11 -0
- package/src/config/autorouting-tier-map.ts +16 -0
- package/src/config/file-lock.ts +199 -68
- package/src/config/model-profile-activation.ts +406 -53
- package/src/config/model-registry.ts +204 -25
- package/src/config/settings-schema.ts +26 -2
- package/src/coordinator-mcp/policy.ts +10 -5
- package/src/coordinator-mcp/question-gate-codec.ts +17 -0
- package/src/coordinator-mcp/question-state.ts +175 -8
- package/src/coordinator-mcp/server.ts +528 -87
- package/src/coordinator-mcp/session-reaper.ts +6 -4
- package/src/crash/record-loader.ts +6 -2
- package/src/daemon/operator-contract.ts +26 -12
- package/src/debug/report-bundle.ts +114 -24
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
- package/src/eval/js/context-manager.ts +8 -8
- package/src/eval/js/worker-core.ts +9 -4
- package/src/eval/js/worker-protocol.ts +2 -0
- package/src/extensibility/extensions/runner.ts +52 -4
- package/src/extensibility/extensions/types.ts +10 -0
- package/src/extensibility/gjc-plugins/registry.ts +196 -37
- package/src/extensibility/runtime-skill-discovery.ts +61 -3
- package/src/extensibility/shared-events.ts +3 -1
- package/src/gjc-runtime/managed-owner-admission.ts +67 -50
- package/src/gjc-runtime/session-state-lock.ts +165 -24
- package/src/gjc-runtime/ultragoal-succession.ts +31 -3
- package/src/internal-urls/docs-index.generated.ts +21 -19
- package/src/internal-urls/embedded-protocol.ts +83 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/parse.ts +21 -1
- package/src/internal-urls/router.ts +4 -2
- package/src/main.ts +123 -55
- package/src/modes/acp/acp-agent.ts +593 -47
- package/src/modes/acp/acp-event-mapper.ts +9 -0
- package/src/modes/acp/startup-provenance.ts +59 -0
- package/src/modes/components/custom-provider-wizard.ts +308 -7
- package/src/modes/components/model-selector.ts +31 -15
- package/src/modes/components/oauth-selector.ts +9 -0
- package/src/modes/components/session-selector.ts +47 -4
- package/src/modes/components/status-line/segments.ts +6 -1
- package/src/modes/components/thinking-selector.ts +7 -3
- package/src/modes/components/user-message-selector.ts +57 -15
- package/src/modes/controllers/command-controller.ts +58 -32
- package/src/modes/controllers/extension-ui-controller.ts +33 -7
- package/src/modes/controllers/input-controller.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +177 -18
- package/src/modes/interactive-mode.ts +21 -7
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
- package/src/modes/types.ts +2 -2
- package/src/prompts/agent-fragments/browser-aside.md +1 -0
- package/src/prompts/system/title-system.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/job.md +1 -1
- package/src/prompts/tools/read.md +2 -0
- package/src/runtime/network-prewarm-service.test.ts +36 -1
- package/src/runtime/network-prewarm-service.ts +28 -3
- package/src/runtime/process-lifecycle.ts +22 -11
- package/src/runtime-mcp/config.ts +16 -1
- package/src/runtime-mcp/manager.ts +689 -55
- package/src/runtime-mcp/pool.test.ts +31 -0
- package/src/runtime-mcp/pool.ts +304 -28
- package/src/runtime-mcp/redaction.ts +42 -0
- package/src/runtime-mcp/startup-policy.ts +7 -0
- package/src/runtime-mcp/tool-bridge.ts +71 -0
- package/src/runtime-mcp/transports/http.ts +108 -25
- package/src/sdk/acp/adapter.ts +90 -9
- package/src/sdk/acp/final-text.ts +19 -2
- package/src/sdk/broker/broker.ts +378 -52
- package/src/sdk/broker/ensure.ts +97 -19
- package/src/sdk/broker/identity.ts +9 -1
- package/src/sdk/broker/lifecycle-ledger.ts +95 -31
- package/src/sdk/broker/lifecycle.ts +690 -141
- package/src/sdk/broker/runtime.ts +1 -1
- package/src/sdk/broker/session-index.ts +97 -4
- package/src/sdk/broker/spawn-authority.ts +35 -7
- package/src/sdk/broker/stderr-drainer.ts +59 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
- package/src/sdk/bus/index.ts +721 -84
- package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -3
- package/src/sdk/cli/master-cli.ts +47 -36
- package/src/sdk/cli/rows.ts +30 -7
- package/src/sdk/cli/session-cli.ts +687 -184
- package/src/sdk/client/client.ts +18 -0
- package/src/sdk/guides/catalog.ts +2 -2
- package/src/sdk/guides/cli.ts +20 -62
- package/src/sdk/guides/verify.ts +14 -0
- package/src/sdk/host/host.ts +49 -5
- package/src/sdk/host/session-runtime.test.ts +636 -9
- package/src/sdk/host/session-runtime.ts +499 -118
- package/src/sdk/host/types.ts +12 -1
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
- package/src/sdk/host/websocket-transport.ts +40 -6
- package/src/sdk/index.ts +11 -0
- package/src/sdk/prompt-deadline-flush.ts +334 -0
- package/src/sdk/prompt-deadline-manager.ts +136 -4
- package/src/sdk/prompt-failure.ts +43 -1
- package/src/sdk/prompt-status.ts +8 -0
- package/src/sdk/prompt-tool-boundary.ts +121 -0
- package/src/sdk/protocol/operation-inventory.generated.json +106 -0
- package/src/sdk/router/replay-retention-gap-cache.ts +27 -0
- package/src/sdk/router/session-router.ts +31 -4
- package/src/sdk/session.ts +194 -16
- package/src/sdk/startup-capability.ts +1 -1
- package/src/sdk/transport/relay.ts +71 -6
- package/src/sdk/transport/serve-cli.ts +494 -49
- package/src/sdk/transport/socket.ts +12 -11
- package/src/sdk/transport/stdio.ts +7 -3
- package/src/session/agent-session.ts +2437 -400
- package/src/session/fallback-chain-controller.ts +6 -7
- package/src/session/fold-coordinator.ts +24 -5
- package/src/session/internal/managed-session-scope.ts +58 -18
- package/src/session/internal/managed-session-storage.ts +304 -11
- package/src/session/session-manager.ts +382 -44
- package/src/session/session-work-lease.ts +34 -0
- package/src/session-import/codex.ts +12 -3
- package/src/setup/model-onboarding-guidance.ts +1 -1
- package/src/setup/provider-onboarding.ts +397 -24
- package/src/slash-commands/builtin-registry.ts +258 -14
- package/src/task/index.ts +14 -2
- package/src/thinking.ts +21 -2
- package/src/tools/bash.ts +98 -78
- package/src/tools/fetch.ts +119 -20
- package/src/tools/job.ts +151 -25
- package/src/tools/output-meta.ts +15 -2
- package/src/tools/path-utils.ts +27 -3
- package/src/tools/read.ts +3 -3
- package/src/tools/steer-fold.ts +107 -0
- package/src/tools/tool-catalog.generated.ts +29 -2
- package/src/tools/tool-errors.ts +4 -0
- package/src/utils/git.ts +53 -3
- package/src/utils/markit.ts +55 -41
- package/src/utils/mupdf-assets.d.ts +4 -0
- package/src/utils/mupdf-embedded.ts +4 -0
- package/src/utils/mupdf-wasm-embedded.ts +3 -0
- package/src/utils/mupdf-wasm.ts +24 -2
- package/src/utils/mupdf.ts +129 -0
- package/src/utils/session-title-generation.ts +29 -0
- package/src/utils/title-generator.ts +46 -2
- package/src/web/scrapers/types.ts +24 -3
- package/vendor/markit-ai/LICENSE +21 -0
- package/vendor/markit-ai/MANIFEST.json +412 -0
- package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/config.js +139 -0
- package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
- package/vendor/markit-ai/dist/commands/convert.js +113 -0
- package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/formats.js +92 -0
- package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/init.js +29 -0
- package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/onboard.js +61 -0
- package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/plugin.js +58 -0
- package/vendor/markit-ai/dist/config.d.ts +26 -0
- package/vendor/markit-ai/dist/config.js +42 -0
- package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/audio.js +104 -0
- package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/csv.js +83 -0
- package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/docx.js +57 -0
- package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/epub.js +128 -0
- package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
- package/vendor/markit-ai/dist/converters/github.js +148 -0
- package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/html.js +30 -0
- package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/image.js +124 -0
- package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
- package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
- package/vendor/markit-ai/dist/converters/iwork.js +391 -0
- package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/json.js +21 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
- package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
- package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
- package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
- package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
- package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
- package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
- package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/pptx.js +289 -0
- package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
- package/vendor/markit-ai/dist/converters/rss.js +138 -0
- package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
- package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
- package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/xml.js +18 -0
- package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/yaml.js +17 -0
- package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/zip.js +57 -0
- package/vendor/markit-ai/dist/index.d.ts +30 -0
- package/vendor/markit-ai/dist/index.js +26 -0
- package/vendor/markit-ai/dist/main.d.ts +2 -0
- package/vendor/markit-ai/dist/main.js +191 -0
- package/vendor/markit-ai/dist/markit.d.ts +45 -0
- package/vendor/markit-ai/dist/markit.js +267 -0
- package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
- package/vendor/markit-ai/dist/plugins/api.js +42 -0
- package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
- package/vendor/markit-ai/dist/plugins/index.js +3 -0
- package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/installer.js +176 -0
- package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
- package/vendor/markit-ai/dist/plugins/loader.js +61 -0
- package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/types.js +1 -0
- package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
- package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
- package/vendor/markit-ai/dist/providers/index.js +56 -0
- package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/openai.js +76 -0
- package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
- package/vendor/markit-ai/dist/providers/types.js +1 -0
- package/vendor/markit-ai/dist/types.d.ts +36 -0
- package/vendor/markit-ai/dist/types.js +1 -0
- package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
- package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
- package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
- package/vendor/markit-ai/dist/utils/output.js +31 -0
- package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
- package/vendor/markit-ai/dist/utils/turndown.js +70 -0
- package/vendor/markit-ai/package.json +74 -0
- package/vendor/markit-ai.patch +49 -0
package/src/sdk/session.ts
CHANGED
|
@@ -59,6 +59,7 @@ import { loadCapability, reset as resetCapabilities } from "../capability";
|
|
|
59
59
|
import { type Rule, ruleCapability, setActiveRules } from "../capability/rule";
|
|
60
60
|
import type { SourceMeta } from "../capability/types";
|
|
61
61
|
import { AUTOROUTING_INACTIVE_WARNING } from "../config/autorouting-contract";
|
|
62
|
+
import { ModelProfileCredentialError, resolveMissingSessionModelRecovery } from "../config/model-profile-activation";
|
|
62
63
|
import { resolveModelProfileName } from "../config/model-profile-contract";
|
|
63
64
|
import { resolveProfileBindings } from "../config/model-profiles";
|
|
64
65
|
import { kNoAuth, ModelRegistry } from "../config/model-registry";
|
|
@@ -144,7 +145,7 @@ import {
|
|
|
144
145
|
createOptionalRuntimeServices,
|
|
145
146
|
type OptionalRuntimeServicesOverrides,
|
|
146
147
|
} from "../runtime/optional-runtime-services";
|
|
147
|
-
import { loadAllMCPConfigs, MCPManager } from "../runtime-mcp";
|
|
148
|
+
import { isMCPStartupTimeoutError, loadAllMCPConfigs, MCPManager } from "../runtime-mcp";
|
|
148
149
|
import type { MCPLoadResult } from "../runtime-mcp/manager";
|
|
149
150
|
import type { MCPServerConfig } from "../runtime-mcp/types";
|
|
150
151
|
import {
|
|
@@ -1516,6 +1517,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1516
1517
|
let processCwdClaimed = false;
|
|
1517
1518
|
let hasRegistered = false;
|
|
1518
1519
|
let asyncJobManager: AsyncJobManager | undefined;
|
|
1520
|
+
let asyncJobManagerOwned = false;
|
|
1519
1521
|
let asyncJobManagerAdmitted = false;
|
|
1520
1522
|
let priorAsyncJobManager: AsyncJobManager | undefined;
|
|
1521
1523
|
let cleanupOwnedMcpManager: (() => Promise<void>) | undefined;
|
|
@@ -1967,9 +1969,22 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1967
1969
|
const persistedProfileOwnsDefault = acceptedPersistedProfileName
|
|
1968
1970
|
? resolveProfileBindings(persistedProfiles.get(acceptedPersistedProfileName)!).defaultSelector !== undefined
|
|
1969
1971
|
: false;
|
|
1970
|
-
|
|
1972
|
+
let startupActiveModelProfile =
|
|
1971
1973
|
acceptedInheritedProfileName ??
|
|
1972
1974
|
(!hasExplicitModel && acceptedPersistedProfileName ? acceptedPersistedProfileName : undefined);
|
|
1975
|
+
let savedDefaultWasUnresolved = false;
|
|
1976
|
+
let deferredMissingSessionRecovery = false;
|
|
1977
|
+
let retainedRecoveryBindingsAfterLateRestore = false;
|
|
1978
|
+
let recoveredSessionDefault:
|
|
1979
|
+
| {
|
|
1980
|
+
entries: string[];
|
|
1981
|
+
profileName: string;
|
|
1982
|
+
activeIndex: number;
|
|
1983
|
+
thinkingLevel?: ThinkingLevel;
|
|
1984
|
+
explicitThinkingLevel: boolean;
|
|
1985
|
+
skips: Array<{ selector: string; reason: string }>;
|
|
1986
|
+
}
|
|
1987
|
+
| undefined;
|
|
1973
1988
|
// If session has data, restore its configured default chain rather than the
|
|
1974
1989
|
// scalar runtime model, which may be a stale fallback from the prior run.
|
|
1975
1990
|
if (!hasExplicitModel && !model && hasExistingSession && defaultModelEntries.length > 0) {
|
|
@@ -1993,6 +2008,33 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1993
2008
|
if (model && preferredCredentialProvider && model.provider !== preferredCredentialProvider) {
|
|
1994
2009
|
model = undefined;
|
|
1995
2010
|
}
|
|
2011
|
+
savedDefaultWasUnresolved = !model;
|
|
2012
|
+
if (!model && resumeModelBehavior !== "useCurrentDefault") {
|
|
2013
|
+
try {
|
|
2014
|
+
const recovery = await resolveMissingSessionModelRecovery({
|
|
2015
|
+
modelRegistry,
|
|
2016
|
+
settings,
|
|
2017
|
+
defaultEntries: defaultModelEntries,
|
|
2018
|
+
skips: restoredDefaultResolution.skips,
|
|
2019
|
+
savedDefault: existingSession.models.default,
|
|
2020
|
+
credentialSessionId,
|
|
2021
|
+
...(persistedProfileOwnsDefault ? { aliasIntent: "preset-equivalent" as const } : {}),
|
|
2022
|
+
});
|
|
2023
|
+
deferredMissingSessionRecovery = true;
|
|
2024
|
+
if (
|
|
2025
|
+
recovery?.model &&
|
|
2026
|
+
(!preferredCredentialProvider || recovery.model.provider === preferredCredentialProvider)
|
|
2027
|
+
) {
|
|
2028
|
+
model = recovery.model;
|
|
2029
|
+
recoveredSessionDefault = recovery;
|
|
2030
|
+
startupActiveModelProfile = undefined;
|
|
2031
|
+
modelFallbackMessage =
|
|
2032
|
+
"Saved session model is no longer registered; restored the durable default preset instead.";
|
|
2033
|
+
}
|
|
2034
|
+
} catch {
|
|
2035
|
+
deferredMissingSessionRecovery = true;
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
1996
2038
|
if (!model) modelFallbackMessage = `Could not restore model ${defaultModelEntries.join(" -> ")}`;
|
|
1997
2039
|
});
|
|
1998
2040
|
}
|
|
@@ -2028,6 +2070,14 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2028
2070
|
thinkingLevel = restoredThinkingLevel;
|
|
2029
2071
|
}
|
|
2030
2072
|
|
|
2073
|
+
if (
|
|
2074
|
+
thinkingLevel === undefined &&
|
|
2075
|
+
(restoredThinkingLevel === undefined || restoredThinkingLevel === ThinkingLevel.Inherit) &&
|
|
2076
|
+
recoveredSessionDefault?.explicitThinkingLevel
|
|
2077
|
+
) {
|
|
2078
|
+
thinkingLevel = recoveredSessionDefault.thinkingLevel;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2031
2081
|
if (thinkingLevel === undefined && !hasExplicitModel && defaultRoleSpec.explicitThinkingLevel) {
|
|
2032
2082
|
thinkingLevel = defaultRoleSpec.thinkingLevel;
|
|
2033
2083
|
}
|
|
@@ -2296,6 +2346,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2296
2346
|
},
|
|
2297
2347
|
})
|
|
2298
2348
|
: options.inheritedAsyncJobManager;
|
|
2349
|
+
asyncJobManagerOwned = backgroundJobsEnabled === true && !options.parentTaskPrefix;
|
|
2299
2350
|
|
|
2300
2351
|
let promptMetadataModel: Model | undefined;
|
|
2301
2352
|
const getActiveModelString = (): string | undefined => {
|
|
@@ -3128,10 +3179,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
3128
3179
|
// consumed (publication happens before the starter can run), which is
|
|
3129
3180
|
// acceptable only because deferral never carries plugin-bundle servers.
|
|
3130
3181
|
gjcProducersComplete = false;
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3182
|
+
if (!isMCPStartupTimeoutError(err)) {
|
|
3183
|
+
logger.warn("GJC plugin MCP connect failed", {
|
|
3184
|
+
path: `mcp:${server}`,
|
|
3185
|
+
error: safeErrorForLog(err),
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3135
3188
|
}
|
|
3136
3189
|
const connectedPluginNames = new Set(result.connectedServers.filter(name => pluginNames.has(name)));
|
|
3137
3190
|
// Retain while any conventional server is still live: "connecting"
|
|
@@ -3493,6 +3546,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
3493
3546
|
if (!session) throw new Error("Terminal abort session is not initialized.");
|
|
3494
3547
|
return session.abortPromptAndWait(handle, seamOptions);
|
|
3495
3548
|
},
|
|
3549
|
+
pendingToolExecutions: handle => {
|
|
3550
|
+
if (!session) throw new Error("Terminal abort session is not initialized.");
|
|
3551
|
+
return session.pendingToolExecutions(handle);
|
|
3552
|
+
},
|
|
3496
3553
|
},
|
|
3497
3554
|
ensureProviderDaemon: options.ensureNotificationProviderDaemon,
|
|
3498
3555
|
runBtwTurn: async (question, signal) => {
|
|
@@ -3583,6 +3640,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
3583
3640
|
if (!session) throw new Error("Terminal abort session is not initialized.");
|
|
3584
3641
|
return session.abortPromptAndWait(handle, seamOptions);
|
|
3585
3642
|
},
|
|
3643
|
+
pendingToolExecutions: handle => {
|
|
3644
|
+
if (!session) throw new Error("Terminal abort session is not initialized.");
|
|
3645
|
+
return session.pendingToolExecutions(handle);
|
|
3646
|
+
},
|
|
3586
3647
|
},
|
|
3587
3648
|
});
|
|
3588
3649
|
}
|
|
@@ -3701,6 +3762,103 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
3701
3762
|
extensionsResult.runtime.pendingProviderRegistrations = [];
|
|
3702
3763
|
}
|
|
3703
3764
|
|
|
3765
|
+
// A startup extension can register the saved model after the initial
|
|
3766
|
+
// recovery lookup. Reconsider the saved chain against that completed
|
|
3767
|
+
// catalog before retaining a durable runtime fallback.
|
|
3768
|
+
if (savedDefaultWasUnresolved && defaultModelEntries.length > 0) {
|
|
3769
|
+
const restoredAfterExtensions = await resolveModelChainWithAuth(
|
|
3770
|
+
defaultModelEntries,
|
|
3771
|
+
modelRegistry,
|
|
3772
|
+
settings,
|
|
3773
|
+
credentialSessionId,
|
|
3774
|
+
{
|
|
3775
|
+
managedFallback: defaultModelEntries.length > 1,
|
|
3776
|
+
canonicalSessionId: providerSessionId,
|
|
3777
|
+
...(persistedProfileOwnsDefault ? { aliasIntent: "preset-equivalent" as const } : {}),
|
|
3778
|
+
},
|
|
3779
|
+
);
|
|
3780
|
+
if (
|
|
3781
|
+
restoredAfterExtensions.model &&
|
|
3782
|
+
(!preferredCredentialProvider || restoredAfterExtensions.model.provider === preferredCredentialProvider)
|
|
3783
|
+
) {
|
|
3784
|
+
model = restoredAfterExtensions.model;
|
|
3785
|
+
retainedRecoveryBindingsAfterLateRestore = savedDefaultWasUnresolved;
|
|
3786
|
+
if (options.thinkingLevel !== undefined) {
|
|
3787
|
+
thinkingLevel = resolveThinkingLevelForModel(model, options.thinkingLevel);
|
|
3788
|
+
} else if (restoredThinkingLevel !== undefined && restoredThinkingLevel !== ThinkingLevel.Inherit) {
|
|
3789
|
+
thinkingLevel = resolveThinkingLevelForModel(model, restoredThinkingLevel);
|
|
3790
|
+
} else {
|
|
3791
|
+
thinkingLevel = restoredAfterExtensions.explicitThinkingLevel
|
|
3792
|
+
? restoredAfterExtensions.thinkingLevel
|
|
3793
|
+
: undefined;
|
|
3794
|
+
if (thinkingLevel === undefined && !hasExplicitModel && defaultRoleSpec.explicitThinkingLevel)
|
|
3795
|
+
thinkingLevel = defaultRoleSpec.thinkingLevel;
|
|
3796
|
+
if (thinkingLevel === undefined && hasExplicitDefaultThinkingLevel)
|
|
3797
|
+
thinkingLevel = settings.get("defaultThinkingLevel");
|
|
3798
|
+
if (thinkingLevel === undefined && model.thinking?.defaultLevel !== undefined)
|
|
3799
|
+
thinkingLevel = model.thinking.defaultLevel;
|
|
3800
|
+
if (thinkingLevel === undefined) thinkingLevel = settings.get("defaultThinkingLevel");
|
|
3801
|
+
thinkingLevel = resolveThinkingLevelForModel(model, thinkingLevel);
|
|
3802
|
+
}
|
|
3803
|
+
recoveredSessionDefault = undefined;
|
|
3804
|
+
startupActiveModelProfile =
|
|
3805
|
+
acceptedInheritedProfileName ??
|
|
3806
|
+
(!hasExplicitModel && acceptedPersistedProfileName ? acceptedPersistedProfileName : undefined);
|
|
3807
|
+
modelFallbackMessage = undefined;
|
|
3808
|
+
} else if (deferredMissingSessionRecovery) {
|
|
3809
|
+
const hadProvisionalRecovery = recoveredSessionDefault !== undefined;
|
|
3810
|
+
let lateRecoveryAccepted = false;
|
|
3811
|
+
try {
|
|
3812
|
+
const recovery = await resolveMissingSessionModelRecovery({
|
|
3813
|
+
modelRegistry,
|
|
3814
|
+
settings,
|
|
3815
|
+
defaultEntries: defaultModelEntries,
|
|
3816
|
+
skips: restoredAfterExtensions.skips,
|
|
3817
|
+
savedDefault: existingSession.models.default,
|
|
3818
|
+
credentialSessionId,
|
|
3819
|
+
...(persistedProfileOwnsDefault ? { aliasIntent: "preset-equivalent" as const } : {}),
|
|
3820
|
+
});
|
|
3821
|
+
if (
|
|
3822
|
+
recovery?.model &&
|
|
3823
|
+
(!preferredCredentialProvider || recovery.model.provider === preferredCredentialProvider)
|
|
3824
|
+
) {
|
|
3825
|
+
model = recovery.model;
|
|
3826
|
+
if (options.thinkingLevel !== undefined) {
|
|
3827
|
+
thinkingLevel = resolveThinkingLevelForModel(model, options.thinkingLevel);
|
|
3828
|
+
} else if (restoredThinkingLevel !== undefined && restoredThinkingLevel !== ThinkingLevel.Inherit) {
|
|
3829
|
+
thinkingLevel = resolveThinkingLevelForModel(model, restoredThinkingLevel);
|
|
3830
|
+
} else {
|
|
3831
|
+
const recoveredLevel = recovery.explicitThinkingLevel
|
|
3832
|
+
? recovery.thinkingLevel
|
|
3833
|
+
: defaultRoleSpec.explicitThinkingLevel
|
|
3834
|
+
? defaultRoleSpec.thinkingLevel
|
|
3835
|
+
: hasExplicitDefaultThinkingLevel
|
|
3836
|
+
? settings.get("defaultThinkingLevel")
|
|
3837
|
+
: (model.thinking?.defaultLevel ?? settings.get("defaultThinkingLevel"));
|
|
3838
|
+
thinkingLevel = resolveThinkingLevelForModel(model, recoveredLevel);
|
|
3839
|
+
}
|
|
3840
|
+
recoveredSessionDefault = recovery;
|
|
3841
|
+
startupActiveModelProfile = undefined;
|
|
3842
|
+
modelFallbackMessage =
|
|
3843
|
+
"Saved session model is no longer registered; restored the durable default preset instead.";
|
|
3844
|
+
lateRecoveryAccepted = true;
|
|
3845
|
+
}
|
|
3846
|
+
} catch (error) {
|
|
3847
|
+
if (!(error instanceof ModelProfileCredentialError)) throw error;
|
|
3848
|
+
}
|
|
3849
|
+
// A completed extension catalog can make the saved selector registered
|
|
3850
|
+
// again without making it callable. Do not retain the provisional durable
|
|
3851
|
+
// fallback in that case: the saved model remains authoritative for the
|
|
3852
|
+
// normal unavailable-model path below.
|
|
3853
|
+
if (!lateRecoveryAccepted && hadProvisionalRecovery) {
|
|
3854
|
+
model = undefined;
|
|
3855
|
+
recoveredSessionDefault = undefined;
|
|
3856
|
+
startupActiveModelProfile = undefined;
|
|
3857
|
+
modelFallbackMessage = `Could not restore model ${defaultModelEntries.join(" -> ")}`;
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3704
3862
|
let startupCredentialModelRejected = false;
|
|
3705
3863
|
if (startupModelReference && (startupCredentialSelector || startupCredentialProviderMismatch)) {
|
|
3706
3864
|
const validated =
|
|
@@ -4788,6 +4946,14 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
4788
4946
|
providerSessionState: options.providerSessionState,
|
|
4789
4947
|
});
|
|
4790
4948
|
session.setActiveModelProfile(startupActiveModelProfile);
|
|
4949
|
+
if (retainedRecoveryBindingsAfterLateRestore) session.markStartupRecoveryBindingsRequired();
|
|
4950
|
+
if (recoveredSessionDefault)
|
|
4951
|
+
session.installRecoveredDefaultFallbackChain(
|
|
4952
|
+
recoveredSessionDefault.entries,
|
|
4953
|
+
recoveredSessionDefault.profileName,
|
|
4954
|
+
recoveredSessionDefault.activeIndex,
|
|
4955
|
+
recoveredSessionDefault.skips,
|
|
4956
|
+
);
|
|
4791
4957
|
session.configWarnings.push(...contextFileWarnings);
|
|
4792
4958
|
// Determined once, here, where settings are already available. Keep the
|
|
4793
4959
|
// durable warning for interactive and print consumers; ACP delivery is
|
|
@@ -5082,7 +5248,18 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
5082
5248
|
let hasErrors = false;
|
|
5083
5249
|
if (exact) {
|
|
5084
5250
|
const result = await exact.manager.discoverAndConnect({ configPath: exact.configPath });
|
|
5085
|
-
|
|
5251
|
+
// A slash control may commit while the deferred startup flight is
|
|
5252
|
+
// loading. Re-read the manager's fenced publication rather than
|
|
5253
|
+
// replaying the stale startup snapshot into the session registry. A
|
|
5254
|
+
// deferred manager can still be waiting to publish its first catalog,
|
|
5255
|
+
// though; only that explicit unpublished state may use the discovery
|
|
5256
|
+
// result. Empty published/fenced catalogs are authoritative and must
|
|
5257
|
+
// not replay stale tools across an exact control.
|
|
5258
|
+
const catalog = exact.manager.getToolCatalogSnapshot();
|
|
5259
|
+
const resultTools =
|
|
5260
|
+
catalog.publication === "unpublished"
|
|
5261
|
+
? (result.tools as CustomTool[])
|
|
5262
|
+
: (catalog.tools as CustomTool[]);
|
|
5086
5263
|
const toolNames = resultTools.map(tool => tool.name);
|
|
5087
5264
|
const collidingToolNames = findDeferredExactMcpToolNameCollisions(
|
|
5088
5265
|
toolNames,
|
|
@@ -5196,15 +5373,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
5196
5373
|
} else {
|
|
5197
5374
|
if (hasRegistered) agentRegistry.unregister(resolvedAgentId);
|
|
5198
5375
|
// Admission happens before session construction. Any later startup
|
|
5199
|
-
// failure must
|
|
5200
|
-
// the prior global only when this manager
|
|
5201
|
-
// a retry under the same endpoint is falsely
|
|
5202
|
-
// redirects global-manager consumers away from
|
|
5203
|
-
// (review thread P1).
|
|
5204
|
-
if (
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5376
|
+
// failure must eventually release THIS manager's endpoint mapping
|
|
5377
|
+
// through disposal and restore the prior global only when this manager
|
|
5378
|
+
// is still global: otherwise a retry under the same endpoint is falsely
|
|
5379
|
+
// rejected and an orphan redirects global-manager consumers away from
|
|
5380
|
+
// the live session (review thread P1).
|
|
5381
|
+
if (asyncJobManagerOwned && asyncJobManager) {
|
|
5382
|
+
if (asyncJobManagerAdmitted) {
|
|
5383
|
+
if (AsyncJobManager.instance() === asyncJobManager) {
|
|
5384
|
+
AsyncJobManager.setInstance(priorAsyncJobManager);
|
|
5385
|
+
}
|
|
5208
5386
|
}
|
|
5209
5387
|
await asyncJobManager.dispose({ timeoutMs: 100 });
|
|
5210
5388
|
}
|
|
@@ -161,7 +161,7 @@ export function normalizeSdkStartupFailure(
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
/** Collect process-scoped credentials without exposing a raw-secret API. */
|
|
164
|
-
function lifecycleKnownSecrets(): string[] {
|
|
164
|
+
export function lifecycleKnownSecrets(): string[] {
|
|
165
165
|
return Object.entries(process.env)
|
|
166
166
|
.filter(([name, value]) => value && /(?:token|secret|password|credential|api[_-]?key|auth)/iu.test(name))
|
|
167
167
|
.map(([, value]) => value!);
|
|
@@ -3,6 +3,7 @@ import type { Readable, Writable } from "node:stream";
|
|
|
3
3
|
export const REQUEST_FRAME_BYTES = 256 * 1024;
|
|
4
4
|
export const DEFAULT_PENDING_CEILING_BYTES = 8 * 1024 * 1024;
|
|
5
5
|
export const MIN_PENDING_CEILING_BYTES = REQUEST_FRAME_BYTES;
|
|
6
|
+
export const DEFAULT_UPSTREAM_HELLO_TIMEOUT_MS = 10_000;
|
|
6
7
|
|
|
7
8
|
export type RelayDirection = "downstream->ws" | "ws->downstream";
|
|
8
9
|
export type TransportError = {
|
|
@@ -34,6 +35,19 @@ export type RelayWebSocket = {
|
|
|
34
35
|
removeEventListener(type: string, listener: (event: RelayWebSocketEvent) => void): void;
|
|
35
36
|
};
|
|
36
37
|
|
|
38
|
+
/** The upstream host's hello marks the point at which downstream frames may be sent. */
|
|
39
|
+
function isServerHello(text: string): boolean {
|
|
40
|
+
let parsed: unknown;
|
|
41
|
+
try {
|
|
42
|
+
parsed = JSON.parse(text);
|
|
43
|
+
} catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return Boolean(
|
|
47
|
+
parsed && typeof parsed === "object" && !Array.isArray(parsed) && (parsed as { type?: unknown }).type === "hello",
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
export type RelayOptions = {
|
|
38
52
|
url: string;
|
|
39
53
|
token: string;
|
|
@@ -112,6 +126,14 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
|
|
|
112
126
|
let pendingToDownstream = 0;
|
|
113
127
|
let writingWs = false;
|
|
114
128
|
let writingDownstream = false;
|
|
129
|
+
// Capability authority belongs to the downstream client. Buffer its hello and
|
|
130
|
+
// requests until the upstream's (possibly minimal) hello has arrived, then
|
|
131
|
+
// forward the exact bytes unchanged in order.
|
|
132
|
+
let upstreamHelloReceived = false;
|
|
133
|
+
let preHelloToWs: Buffer[] = [];
|
|
134
|
+
let preHelloToWsBytes = 0;
|
|
135
|
+
let upstreamHelloTimer: ReturnType<typeof setTimeout> | undefined;
|
|
136
|
+
let openingSettled = false;
|
|
115
137
|
|
|
116
138
|
const settle = (error?: Error): void => {
|
|
117
139
|
if (completed) return;
|
|
@@ -121,6 +143,8 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
|
|
|
121
143
|
};
|
|
122
144
|
void finished.promise.catch(() => undefined);
|
|
123
145
|
const detach = (): void => {
|
|
146
|
+
if (upstreamHelloTimer !== undefined) clearTimeout(upstreamHelloTimer);
|
|
147
|
+
upstreamHelloTimer = undefined;
|
|
124
148
|
options.downstream.removeListener("data", onData);
|
|
125
149
|
options.downstream.removeListener("end", onEnd);
|
|
126
150
|
options.downstream.removeListener("error", onDownstreamError);
|
|
@@ -213,7 +237,14 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
|
|
|
213
237
|
downstreamBytes = 0;
|
|
214
238
|
if (options.validateDownstreamFrame && !options.validateDownstreamFrame(line.toString("utf8")))
|
|
215
239
|
return fail({ type: "transport_error", code: "protocol_error", direction: "downstream->ws" });
|
|
216
|
-
|
|
240
|
+
if (!upstreamHelloReceived) {
|
|
241
|
+
if (preHelloToWsBytes + line.length > options.pendingCeilingBytes) {
|
|
242
|
+
fail({ type: "transport_error", code: "pending_overflow", direction: "downstream->ws" });
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
preHelloToWs.push(line);
|
|
246
|
+
preHelloToWsBytes += line.length;
|
|
247
|
+
} else enqueue(toWs, "downstream->ws", line);
|
|
217
248
|
if (closed) return;
|
|
218
249
|
start = newline + 1;
|
|
219
250
|
newline = chunk.indexOf(0x0a, start);
|
|
@@ -233,20 +264,54 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
|
|
|
233
264
|
fail({ type: "transport_error", code: "protocol_error", direction: "ws->downstream" });
|
|
234
265
|
return;
|
|
235
266
|
}
|
|
267
|
+
if (!upstreamHelloReceived && isServerHello(event.data)) {
|
|
268
|
+
upstreamHelloReceived = true;
|
|
269
|
+
if (upstreamHelloTimer !== undefined) clearTimeout(upstreamHelloTimer);
|
|
270
|
+
upstreamHelloTimer = undefined;
|
|
271
|
+
const queued = preHelloToWs;
|
|
272
|
+
preHelloToWs = [];
|
|
273
|
+
preHelloToWsBytes = 0;
|
|
274
|
+
for (const frame of queued) enqueue(toWs, "downstream->ws", frame);
|
|
275
|
+
}
|
|
236
276
|
enqueue(toDownstream, "ws->downstream", Buffer.concat([Buffer.from(event.data, "utf8"), Buffer.from("\n")]));
|
|
237
277
|
};
|
|
238
|
-
const onClose = (): void =>
|
|
239
|
-
|
|
278
|
+
const onClose = (): void => {
|
|
279
|
+
if (!openingSettled) {
|
|
280
|
+
openingSettled = true;
|
|
281
|
+
opened.reject(new Error("upstream_closed"));
|
|
282
|
+
}
|
|
283
|
+
void close();
|
|
284
|
+
};
|
|
285
|
+
const onWebSocketError = (): void => {
|
|
286
|
+
if (!openingSettled) {
|
|
287
|
+
openingSettled = true;
|
|
288
|
+
opened.reject(new Error("upstream_error"));
|
|
289
|
+
}
|
|
290
|
+
void close(new Error("upstream_error"));
|
|
291
|
+
};
|
|
240
292
|
const onOpen = (): void => {
|
|
293
|
+
if (openingSettled) return;
|
|
294
|
+
openingSettled = true;
|
|
241
295
|
cleanupOpening();
|
|
296
|
+
if (!upstreamHelloReceived) {
|
|
297
|
+
upstreamHelloTimer = setTimeout(() => {
|
|
298
|
+
if (!upstreamHelloReceived && !closed)
|
|
299
|
+
fail({ type: "transport_error", code: "protocol_error", direction: "ws->downstream" });
|
|
300
|
+
}, DEFAULT_UPSTREAM_HELLO_TIMEOUT_MS);
|
|
301
|
+
upstreamHelloTimer.unref?.();
|
|
302
|
+
}
|
|
242
303
|
opened.resolve();
|
|
243
304
|
};
|
|
244
305
|
const onOpenError = (): void => {
|
|
306
|
+
if (openingSettled) return;
|
|
307
|
+
openingSettled = true;
|
|
245
308
|
cleanupOpening();
|
|
246
309
|
opened.reject(new Error("upstream_error"));
|
|
247
310
|
};
|
|
248
311
|
const onAbort = (): void => {
|
|
249
312
|
const error = new RelayOpenAbortedError();
|
|
313
|
+
if (openingSettled) return;
|
|
314
|
+
openingSettled = true;
|
|
250
315
|
cleanupOpening();
|
|
251
316
|
opened.reject(error);
|
|
252
317
|
void close(error);
|
|
@@ -258,6 +323,9 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
|
|
|
258
323
|
};
|
|
259
324
|
ws.addEventListener("open", onOpen, { once: true });
|
|
260
325
|
ws.addEventListener("error", onOpenError, { once: true });
|
|
326
|
+
ws.addEventListener("message", onMessage);
|
|
327
|
+
ws.addEventListener("close", onClose);
|
|
328
|
+
ws.addEventListener("error", onWebSocketError);
|
|
261
329
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
262
330
|
try {
|
|
263
331
|
await opened.promise;
|
|
@@ -265,9 +333,6 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
|
|
|
265
333
|
await close(error instanceof Error ? error : new Error(String(error)));
|
|
266
334
|
throw error;
|
|
267
335
|
}
|
|
268
|
-
ws.addEventListener("message", onMessage);
|
|
269
|
-
ws.addEventListener("close", onClose);
|
|
270
|
-
ws.addEventListener("error", onWebSocketError);
|
|
271
336
|
options.downstream.on("data", onData);
|
|
272
337
|
options.downstream.once("end", onEnd);
|
|
273
338
|
options.downstream.once("error", onDownstreamError);
|