@danceiny/gotry 0.0.1-rc.8 → 0.2.0-rc.27
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/README.md +172 -217
- package/README.zh-CN.md +222 -0
- package/bin/gotry-backend.js +53 -0
- package/bin/gotry-booking-copilot.js +53 -0
- package/bin/gotry-bootstrap.js +1744 -0
- package/bin/gotry-inner.js +733 -83
- package/bin/gotry-process-liveness.d.ts +27 -0
- package/bin/gotry-process-liveness.js +97 -0
- package/bin/gotry-runtime-resolution.d.ts +27 -0
- package/bin/gotry-runtime-resolution.js +49 -0
- package/bin/gotry.js +1 -1
- package/client/client.js +203 -0
- package/cordis.gotry-patch.yml +80 -49
- package/data/airline-airports.json +39 -0
- package/data/stations-12306-verify.json +524 -0
- package/dist/capabilities/agent-reach-deep.js +45 -122
- package/dist/capabilities/agent-reach.js +101 -146
- package/dist/capabilities/anything.js +135 -94
- package/dist/capabilities/artifacts.js +370 -0
- package/dist/capabilities/channel-health.js +131 -0
- package/dist/capabilities/channel-registry.js +256 -0
- package/dist/capabilities/doctor.js +546 -0
- package/dist/capabilities/effect.js +394 -0
- package/dist/capabilities/external-event.js +149 -0
- package/dist/capabilities/fact-log.js +55 -0
- package/dist/capabilities/flyai-config.js +337 -0
- package/dist/capabilities/flyai.js +968 -0
- package/dist/capabilities/fx-contract.js +293 -0
- package/dist/capabilities/geo-atlas.js +246 -0
- package/dist/capabilities/ground-transfer.js +509 -0
- package/dist/capabilities/hbcli.js +260 -123
- package/dist/capabilities/hotelbyte-transaction.js +194 -0
- package/dist/capabilities/incident-log.js +131 -61
- package/dist/capabilities/itinerary-artifact.js +190 -0
- package/dist/capabilities/itinerary-deck-artifact.js +194 -0
- package/dist/capabilities/itinerary-deck-export.js +339 -0
- package/dist/capabilities/lavish-local.js +924 -0
- package/dist/capabilities/model-override.js +38 -0
- package/dist/capabilities/opensky.js +54 -43
- package/dist/capabilities/resilience.js +191 -0
- package/dist/capabilities/session/action-cache.js +126 -0
- package/dist/capabilities/session/adapters/ctrip-flight.js +141 -0
- package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
- package/dist/capabilities/session/adapters/dida-portal.js +274 -0
- package/dist/capabilities/session/adapters/meituan-local.js +54 -0
- package/dist/capabilities/session/adapters/rail-12306.js +342 -0
- package/dist/capabilities/session/benchmark.js +189 -0
- package/dist/capabilities/session/bridge-ledger.js +224 -0
- package/dist/capabilities/session/extension-bridge.js +636 -0
- package/dist/capabilities/session/extension-channel.js +109 -0
- package/dist/capabilities/session/extension-distribution.js +230 -0
- package/dist/capabilities/session/extract.js +50 -0
- package/dist/capabilities/session/golden-score.js +114 -0
- package/dist/capabilities/session/health-watch.js +215 -0
- package/dist/capabilities/session/read-guard.js +107 -0
- package/dist/capabilities/session/static-flight-golden.js +150 -0
- package/dist/capabilities/session/transport.js +109 -0
- package/dist/capabilities/session/wizard.js +117 -0
- package/dist/capabilities/session-consent.js +178 -0
- package/dist/capabilities/session-login.js +170 -0
- package/dist/capabilities/session-search.js +686 -0
- package/dist/capabilities/spawn-bounded.js +203 -0
- package/dist/capabilities/sponsor-plugin.js +341 -0
- package/dist/capabilities/visa-policy.js +140 -0
- package/dist/capabilities/weather.js +243 -138
- package/dist/data/session-golden-20.json +25 -0
- package/dist/data/sf-golden-manifest.json +103 -0
- package/dist/data/sf-static-routes.json +91 -0
- package/dist/scripts/action-cache-tests.js +72 -0
- package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
- package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
- package/dist/scripts/agent-reach-deep-tests.js +30 -40
- package/dist/scripts/agent-reach-error-tests.js +354 -0
- package/dist/scripts/agent-reach-tests.js +26 -18
- package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
- package/dist/scripts/anything-tests.js +116 -60
- package/dist/scripts/artifact-client-contract-tests.js +220 -0
- package/dist/scripts/artifacts-capability-tests.js +727 -0
- package/dist/scripts/async-collect.js +68 -10
- package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
- package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
- package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
- package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
- package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
- package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
- package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
- package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
- package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
- package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
- package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
- package/dist/scripts/booking-copilot-dsh-warmer-proof.js +123 -0
- package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
- package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
- package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
- package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
- package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
- package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
- package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
- package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
- package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
- package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
- package/dist/scripts/booking-executor-tests.js +80 -0
- package/dist/scripts/booking-recovery-chain-tests.js +182 -0
- package/dist/scripts/booking-saga-tests.js +125 -0
- package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
- package/dist/scripts/bootstrap-tests.js +1479 -0
- package/dist/scripts/bridge-events-tests.js +239 -0
- package/dist/scripts/bridge-ledger-tests.js +428 -0
- package/dist/scripts/build-changelog.js +238 -0
- package/dist/scripts/build-metrics-report.js +331 -0
- package/dist/scripts/changelog-tests.js +118 -0
- package/dist/scripts/channel-probe-tests.js +103 -0
- package/dist/scripts/channel-probe.js +169 -0
- package/dist/scripts/channel-registry-tests.js +208 -0
- package/dist/scripts/companion-tests.js +67 -0
- package/dist/scripts/dida-cookie-probe.js +87 -0
- package/dist/scripts/dida-runner-stop-tests.js +311 -0
- package/dist/scripts/dida-sw-probe.js +114 -0
- package/dist/scripts/diff-test.js +17 -12
- package/dist/scripts/doctor-tests.js +564 -0
- package/dist/scripts/dsh-artifact-e2e.js +279 -0
- package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
- package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
- package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
- package/dist/scripts/dsh-runtime-closure.js +162 -0
- package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
- package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
- package/dist/scripts/dsh-target-closure-proof.js +178 -0
- package/dist/scripts/effect-tests.js +539 -0
- package/dist/scripts/engine-run.js +1 -3
- package/dist/scripts/engine-tests.js +16 -10
- package/dist/scripts/evaluation-cadence-tests.js +174 -0
- package/dist/scripts/evaluation-contract-tests.js +268 -0
- package/dist/scripts/extension-distribution-cli.js +39 -0
- package/dist/scripts/extension-distribution-tests.js +443 -0
- package/dist/scripts/extension-tests.js +988 -0
- package/dist/scripts/external-event-tests.js +350 -0
- package/dist/scripts/fact-gate-tests.js +869 -0
- package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
- package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
- package/dist/scripts/flight-malformed-tests.js +159 -0
- package/dist/scripts/flyai-setup-tests.js +228 -0
- package/dist/scripts/flyai-setup-tool-tests.js +54 -0
- package/dist/scripts/flyai-tests.js +692 -0
- package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
- package/dist/scripts/fx-contract-tests.js +201 -0
- package/dist/scripts/g5-guard-tests.js +131 -0
- package/dist/scripts/g5-guard.js +189 -0
- package/dist/scripts/gen-lunar-anchors.js +106 -0
- package/dist/scripts/geo-atlas-tests.js +283 -0
- package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
- package/dist/scripts/gotry-try-demo-tests.js +79 -0
- package/dist/scripts/gotry-try-demo.js +49 -0
- package/dist/scripts/ground-transfer-tests.js +956 -0
- package/dist/scripts/hbcli-e2e-tests.js +159 -0
- package/dist/scripts/hbcli-live-optin-tests.js +96 -0
- package/dist/scripts/hbcli-release-contract-tests.js +122 -0
- package/dist/scripts/hbcli-tests.js +121 -69
- package/dist/scripts/health-watch-cli.js +73 -0
- package/dist/scripts/hotel-date-gate-tests.js +496 -0
- package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
- package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
- package/dist/scripts/i18n-tests.js +41 -0
- package/dist/scripts/incident-tests.js +281 -87
- package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
- package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
- package/dist/scripts/issue-271-liveness-tests.js +569 -0
- package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
- package/dist/scripts/issue-289-model-retry-tests.js +441 -0
- package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
- package/dist/scripts/issue-338-home-city-e2e.js +577 -0
- package/dist/scripts/issue343-real-entry-e2e.js +160 -0
- package/dist/scripts/issue436-persisted-routing-e2e.js +247 -0
- package/dist/scripts/itinerary-artifact-tests.js +368 -0
- package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
- package/dist/scripts/itinerary-deck-export-tests.js +552 -0
- package/dist/scripts/itinerary-deck-tests.js +435 -0
- package/dist/scripts/itinerary-html-tests.js +426 -0
- package/dist/scripts/journey-tests.js +22 -27
- package/dist/scripts/kernel-manifest-evidence.js +109 -0
- package/dist/scripts/kernel-manifest-gate.js +126 -0
- package/dist/scripts/kernel-manifest-tests.js +212 -0
- package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
- package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
- package/dist/scripts/kernel-manifest.js +369 -0
- package/dist/scripts/lavish-local-tests.js +1226 -0
- package/dist/scripts/lavish-product-tools-tests.js +537 -0
- package/dist/scripts/ledger-repair-apply-tests.js +316 -0
- package/dist/scripts/ledger-repair-plan-tests.js +375 -0
- package/dist/scripts/ledger-tests.js +480 -0
- package/dist/scripts/ledger-workflow-crash.js +32 -0
- package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
- package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
- package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
- package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
- package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
- package/dist/scripts/memory-capture-tests.js +242 -61
- package/dist/scripts/memory-decay-tests.js +49 -0
- package/dist/scripts/memory-lifecycle-tests.js +657 -0
- package/dist/scripts/memory-lifecycle.js +196 -0
- package/dist/scripts/memory-metrics.js +29 -31
- package/dist/scripts/memory-value-report.js +631 -0
- package/dist/scripts/memory-value-tests.js +328 -0
- package/dist/scripts/metrics-report-tests.js +151 -0
- package/dist/scripts/model-override-e2e.js +137 -0
- package/dist/scripts/nightly-evidence-tests.js +161 -0
- package/dist/scripts/nightly-evidence.js +286 -0
- package/dist/scripts/nudge-digest.js +43 -42
- package/dist/scripts/observability-tests.js +381 -0
- package/dist/scripts/onboarding-tests.js +161 -0
- package/dist/scripts/opensky-check.js +18 -13
- package/dist/scripts/opensky-tests.js +28 -28
- package/dist/scripts/persona-surface-guard-tests.js +49 -0
- package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
- package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
- package/dist/scripts/price-drift-tests.js +340 -0
- package/dist/scripts/price-drift-watch.js +447 -0
- package/dist/scripts/probe-poi-tests.js +53 -45
- package/dist/scripts/product-metrics.js +483 -0
- package/dist/scripts/publish-preverify.js +110 -0
- package/dist/scripts/realtime-pricing-tests.js +76 -0
- package/dist/scripts/recall-tests.js +513 -0
- package/dist/scripts/replay-async.js +20 -18
- package/dist/scripts/replay-real.js +18 -18
- package/dist/scripts/replay.js +52 -82
- package/dist/scripts/session-attach-diagnose.js +31 -0
- package/dist/scripts/session-attach-poc.js +62 -0
- package/dist/scripts/session-benchmark.js +180 -0
- package/dist/scripts/session-dida-live-e2e.js +199 -0
- package/dist/scripts/session-extract-tests.js +60 -0
- package/dist/scripts/session-link-tests.js +478 -0
- package/dist/scripts/session-login.js +29 -0
- package/dist/scripts/session-tests.js +862 -0
- package/dist/scripts/session-zones-tests.js +358 -0
- package/dist/scripts/sf-live-benchmark.js +367 -0
- package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
- package/dist/scripts/sf-live-cli-tests.js +92 -0
- package/dist/scripts/sf-live-options.js +46 -0
- package/dist/scripts/sf-manifest-tests.js +30 -0
- package/dist/scripts/sf-manifest.js +33 -0
- package/dist/scripts/sf-soft-score-tests.js +67 -0
- package/dist/scripts/sf-summary-tests.js +324 -0
- package/dist/scripts/sf-summary.js +525 -0
- package/dist/scripts/share-tests.js +432 -0
- package/dist/scripts/skeleton-check.js +16 -14
- package/dist/scripts/skeleton-integration-test.js +28 -11
- package/dist/scripts/skills-contract-tests.js +51 -46
- package/dist/scripts/smoke-session-gate-tests.js +21 -0
- package/dist/scripts/smoke.js +703 -219
- package/dist/scripts/spawn-bounded-abort-tests.js +241 -0
- package/dist/scripts/sponsor-reuse-tests.js +262 -0
- package/dist/scripts/state-cli-tests.js +261 -0
- package/dist/scripts/state-cli.js +585 -0
- package/dist/scripts/state-repair-cli.js +66 -0
- package/dist/scripts/state-repair-tests.js +140 -0
- package/dist/scripts/static-golden-tests.js +165 -0
- package/dist/scripts/time-eval-tests.js +210 -192
- package/dist/scripts/travel-timeline-tests.js +59 -0
- package/dist/scripts/turn-handoff-collect-tests.js +169 -0
- package/dist/scripts/turn-handoff-collect.js +161 -0
- package/dist/scripts/turn-policy-tests.js +55 -0
- package/dist/scripts/typed-contract-canary.js +176 -0
- package/dist/scripts/tz-resolver-sanity.js +50 -0
- package/dist/scripts/tz-resolver-tests.js +584 -0
- package/dist/scripts/unified-tests.js +23 -19
- package/dist/scripts/visa-policy-tests.js +62 -0
- package/dist/scripts/weather-tests.js +276 -41
- package/dist/scripts/wish-channel-gate-tests.js +54 -0
- package/dist/scripts/write-gate-tests.js +522 -0
- package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
- package/dist/scripts/z3-lifecycle-tests.js +170 -0
- package/dist/scripts/z3-race-repeat-tests.js +39 -0
- package/dist/scripts/z3-race-tests.js +41 -0
- package/dist/src/artifact-gate.js +829 -0
- package/dist/src/backend/kernel.js +91 -0
- package/dist/src/backend/modules/booking-copilot.js +92 -0
- package/dist/src/backend/modules/booking-executor.js +124 -0
- package/dist/src/backend/modules/session-search.js +551 -0
- package/dist/src/benchmark-agent-conformance.js +578 -0
- package/dist/src/benchmark-environment-bridge.js +515 -0
- package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
- package/dist/src/benchmark-tool-isolation.js +151 -0
- package/dist/src/bookable-facts.js +533 -0
- package/dist/src/booking-saga.js +97 -0
- package/dist/src/booking-surface/availability-policy.js +697 -0
- package/dist/src/booking-surface/booking-intent.js +43 -0
- package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
- package/dist/src/booking-surface/canonical-schema.js +116 -0
- package/dist/src/booking-surface/contracts.js +75 -0
- package/dist/src/booking-surface/dsh-planner.js +1854 -0
- package/dist/src/booking-surface/dsh-plugin.js +378 -0
- package/dist/src/booking-surface/dsh-worker.js +98 -0
- package/dist/src/booking-surface/error-codes.js +231 -0
- package/dist/src/booking-surface/index.js +9 -0
- package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
- package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
- package/dist/src/booking-surface/profile.js +24 -0
- package/dist/src/booking-surface/recovery-chain.js +367 -0
- package/dist/src/booking-surface/runtime.js +1968 -0
- package/dist/src/booking-surface/server.js +674 -0
- package/dist/src/booking-surface/startup.js +168 -0
- package/dist/src/booking-surface/validation.js +261 -0
- package/dist/src/bridge.js +20 -13
- package/dist/src/companions.js +86 -0
- package/dist/src/contracts.js +21 -43
- package/dist/src/dsh-llm.js +97 -111
- package/dist/src/engine.js +276 -193
- package/dist/src/evaluation-cadence.js +97 -0
- package/dist/src/evaluation-contracts.js +283 -0
- package/dist/src/flight-pack-adapter.js +54 -0
- package/dist/src/flight-pack-contract.js +2 -0
- package/dist/src/flyai-setup-tool.js +70 -0
- package/dist/src/gotry-backend.js +125 -0
- package/dist/src/hotel-date-gate.js +118 -0
- package/dist/src/i18n.js +88 -0
- package/dist/src/index.js +2305 -731
- package/dist/src/itinerary-deck.js +139 -0
- package/dist/src/itinerary-doc-shared.js +661 -0
- package/dist/src/itinerary-html.js +131 -0
- package/dist/src/journey.js +155 -108
- package/dist/src/lavish-tools.js +400 -0
- package/dist/src/ledger-repair-apply.js +538 -0
- package/dist/src/ledger-repair-plan.js +463 -0
- package/dist/src/loop.js +358 -162
- package/dist/src/memory-capture.js +180 -32
- package/dist/src/memory-decay.js +47 -0
- package/dist/src/memory-lifecycle.js +1310 -0
- package/dist/src/memory-utility.js +27 -40
- package/dist/src/mock-llm.js +36 -61
- package/dist/src/model.js +81 -36
- package/dist/src/realtime-pricing.js +103 -0
- package/dist/src/recall/card.js +74 -0
- package/dist/src/recall/evaluator.js +140 -0
- package/dist/src/recall/integration.js +17 -0
- package/dist/src/recall/tick.js +166 -0
- package/dist/src/session-link/plan-it-action.js +48 -0
- package/dist/src/session-link/session-link.js +248 -0
- package/dist/src/session-zones.js +507 -0
- package/dist/src/share/adapters.js +51 -0
- package/dist/src/share/share-consent.js +76 -0
- package/dist/src/share/share-deck.js +58 -0
- package/dist/src/share/share-token.js +146 -0
- package/dist/src/slot-spec.js +84 -106
- package/dist/src/state-ledger.js +767 -0
- package/dist/src/state-repair.js +299 -0
- package/dist/src/subagent-job-id-guard.js +58 -0
- package/dist/src/time-anchor.js +231 -33
- package/dist/src/tool-packet.js +20 -8
- package/dist/src/travel-slots.js +58 -35
- package/dist/src/travel-timeline.js +59 -0
- package/dist/src/turn-deadline.js +287 -0
- package/dist/src/turn-policy.js +118 -0
- package/dist/src/tz-resolver.js +143 -0
- package/dist/src/unified.js +538 -360
- package/dist/src/wish-pool.js +42 -12
- package/dist/src/write-gate.js +495 -0
- package/dist/src/z3-shared.js +284 -0
- package/extension/README.md +21 -0
- package/extension/README.zh-CN.md +21 -0
- package/extension/background.js +463 -0
- package/extension/content-bridge.js +270 -0
- package/extension/content-main.js +111 -0
- package/extension/manifest.json +60 -0
- package/package.json +407 -14
- package/schemas/booking.intent.schema.json +193 -0
- package/schemas/booking.surface.schema.json +2622 -0
- package/ts/capabilities/agent-reach-deep.ts +114 -0
- package/ts/capabilities/agent-reach.ts +198 -0
- package/ts/capabilities/anything.ts +255 -0
- package/ts/capabilities/artifacts.ts +428 -0
- package/ts/capabilities/fact-log.ts +54 -0
- package/ts/capabilities/flyai-config.ts +388 -0
- package/ts/capabilities/flyai.ts +1274 -0
- package/ts/capabilities/hbcli.ts +253 -71
- package/ts/capabilities/incident-log.ts +88 -59
- package/ts/capabilities/itinerary-artifact.ts +214 -0
- package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
- package/ts/capabilities/itinerary-deck-export.ts +378 -0
- package/ts/capabilities/opensky.ts +121 -0
- package/ts/capabilities/session/action-cache.ts +148 -0
- package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
- package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
- package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
- package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
- package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
- package/ts/capabilities/session/benchmark.ts +276 -0
- package/ts/capabilities/session/bridge-ledger.ts +333 -0
- package/ts/capabilities/session/extension-bridge.ts +794 -0
- package/ts/capabilities/session/extension-channel.ts +144 -0
- package/ts/capabilities/session/extension-distribution.ts +266 -0
- package/ts/capabilities/session/extract.ts +54 -0
- package/ts/capabilities/session/golden-score.ts +139 -0
- package/ts/capabilities/session/health-watch.ts +264 -0
- package/ts/capabilities/session/read-guard.ts +141 -0
- package/ts/capabilities/session/static-flight-golden.ts +209 -0
- package/ts/capabilities/session/transport.ts +146 -0
- package/ts/capabilities/session/wizard.ts +140 -0
- package/ts/capabilities/session-consent.ts +211 -0
- package/ts/capabilities/session-login.ts +208 -0
- package/ts/capabilities/session-search.ts +893 -0
- package/ts/capabilities/weather.ts +330 -0
- package/ts/dsh-runtime/vendor/README.md +68 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
- package/ts/package.json +296 -3
- package/ts/scripts/async-collect.ts +91 -0
- package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
- package/ts/scripts/skeleton-check.ts +1 -1
- package/ts/scripts/skeleton-integration-test.ts +23 -1
- package/ts/scripts/state-cli.ts +568 -0
- package/ts/scripts/turn-handoff-collect.ts +178 -0
- package/ts/src/artifact-gate.ts +991 -0
- package/ts/src/benchmark-agent-conformance.ts +619 -0
- package/ts/src/benchmark-environment-bridge.ts +538 -0
- package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
- package/ts/src/benchmark-tool-isolation.ts +166 -0
- package/ts/src/bookable-facts.ts +837 -0
- package/ts/src/booking-saga.ts +133 -0
- package/ts/src/booking-surface/availability-policy.ts +522 -0
- package/ts/src/booking-surface/booking-intent.ts +86 -0
- package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
- package/ts/src/booking-surface/canonical-schema.js +116 -0
- package/ts/src/booking-surface/contracts.ts +475 -0
- package/ts/src/booking-surface/dsh-planner.ts +1949 -0
- package/ts/src/booking-surface/dsh-plugin.js +378 -0
- package/ts/src/booking-surface/dsh-worker.ts +110 -0
- package/ts/src/booking-surface/error-codes.ts +241 -0
- package/ts/src/booking-surface/index.ts +9 -0
- package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
- package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
- package/ts/src/booking-surface/profile.ts +42 -0
- package/ts/src/booking-surface/recovery-chain.ts +409 -0
- package/ts/src/booking-surface/runtime.ts +1793 -0
- package/ts/src/booking-surface/server.ts +733 -0
- package/ts/src/booking-surface/startup.ts +201 -0
- package/ts/src/booking-surface/validation.ts +217 -0
- package/ts/src/companions.ts +113 -0
- package/ts/src/contracts.ts +13 -3
- package/ts/src/dsh-llm.ts +44 -11
- package/ts/src/flyai-setup-tool.ts +77 -0
- package/ts/src/index.ts +2107 -224
- package/ts/src/itinerary-deck.ts +189 -0
- package/ts/src/itinerary-doc-shared.ts +741 -0
- package/ts/src/itinerary-html.ts +171 -0
- package/ts/src/loop.ts +278 -40
- package/ts/src/memory-capture.ts +283 -0
- package/ts/src/memory-decay.ts +55 -0
- package/ts/src/memory-utility.ts +70 -0
- package/ts/src/mock-llm.ts +4 -8
- package/ts/src/model.ts +88 -2
- package/ts/src/recall/card.ts +106 -0
- package/ts/src/recall/evaluator.ts +170 -0
- package/ts/src/recall/integration.ts +35 -0
- package/ts/src/recall/tick.ts +213 -0
- package/ts/src/session-link/plan-it-action.ts +78 -0
- package/ts/src/session-link/session-link.ts +275 -0
- package/ts/src/share/adapters.ts +93 -0
- package/ts/src/share/share-consent.ts +105 -0
- package/ts/src/share/share-deck.ts +85 -0
- package/ts/src/share/share-token.ts +166 -0
- package/ts/src/slot-spec.ts +172 -0
- package/ts/src/state-ledger.ts +912 -0
- package/ts/src/subagent-job-id-guard.ts +72 -0
- package/ts/src/time-anchor.ts +338 -0
- package/ts/src/tool-packet.ts +32 -0
- package/ts/src/travel-slots.ts +219 -0
- package/ts/src/travel-timeline.ts +83 -0
- package/ts/src/turn-deadline.ts +366 -0
- package/ts/src/turn-policy.ts +154 -0
- package/ts/src/unified.ts +360 -89
- package/ts/src/wish-pool.ts +79 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/** Closed, non-sensitive error vocabulary for planner/runtime boundaries. */
|
|
2
|
+
export const BOOKING_TYPED_ERROR_CODES = [
|
|
3
|
+
'PAYLOAD_TOO_LARGE',
|
|
4
|
+
'TASK_NOT_FOUND',
|
|
5
|
+
'TASK_TERMINAL',
|
|
6
|
+
'RECEIPT_REQUIRED',
|
|
7
|
+
'RECEIPT_CONFLICT',
|
|
8
|
+
'UNSUPPORTED_ACTION',
|
|
9
|
+
'PLANNER_SURFACE_ACTION_UNSUPPORTED',
|
|
10
|
+
'PLANNER_NO_DECISION',
|
|
11
|
+
'PLANNER_TYPED_DECISION_REQUIRED',
|
|
12
|
+
'PLANNER_PROVIDER_AUTH_FAILED',
|
|
13
|
+
'PLANNER_PROVIDER_QUOTA_EXHAUSTED',
|
|
14
|
+
'PLANNER_PROVIDER_RATE_LIMITED',
|
|
15
|
+
'PLANNER_PROVIDER_UNAVAILABLE',
|
|
16
|
+
'PLANNER_PROVIDER_REQUEST_REJECTED',
|
|
17
|
+
'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
18
|
+
'PLANNER_PROVIDER_TIMEOUT',
|
|
19
|
+
'PLANNER_BOOT_TIMEOUT',
|
|
20
|
+
'PLANNER_CONFIGURATION_INVALID',
|
|
21
|
+
'PLANNER_FAILED',
|
|
22
|
+
'INVALID_ACTION',
|
|
23
|
+
'INVALID_EVENT',
|
|
24
|
+
'CONTEXT_MISMATCH',
|
|
25
|
+
'WORKSPACE_MISMATCH',
|
|
26
|
+
'ACTION_CONFLICT',
|
|
27
|
+
'STALE_REVISION',
|
|
28
|
+
'OPERATION_LIMIT_REACHED',
|
|
29
|
+
'AVAILABILITY_TERMINAL_POLICY_OWNED',
|
|
30
|
+
'TRUSTED_INGRESS_BINDING_REQUIRED',
|
|
31
|
+
'INVALID_INGRESS_BINDING',
|
|
32
|
+
'BOOKING_SURFACE_SCHEMA_MISMATCH',
|
|
33
|
+
'UNAUTHORIZED',
|
|
34
|
+
'NOT_FOUND',
|
|
35
|
+
] as const
|
|
36
|
+
|
|
37
|
+
export type BookingTypedErrorCode = typeof BOOKING_TYPED_ERROR_CODES[number]
|
|
38
|
+
|
|
39
|
+
/** Exact, closed reasons safe to expose in dispatch diagnostics. */
|
|
40
|
+
export const BOOKING_DISPATCH_REJECTION_REASONS = [
|
|
41
|
+
'approval_expired',
|
|
42
|
+
'approval_mismatch',
|
|
43
|
+
'approval_not_awaiting',
|
|
44
|
+
'approval_not_presented',
|
|
45
|
+
'approval_replayed',
|
|
46
|
+
'approval_required',
|
|
47
|
+
'availability_attempt_mismatch',
|
|
48
|
+
'availability_attempt_unknown',
|
|
49
|
+
'availability_criteria_changed',
|
|
50
|
+
'availability_criteria_invalid',
|
|
51
|
+
'availability_criteria_mismatch',
|
|
52
|
+
'availability_criteria_required',
|
|
53
|
+
'availability_duplicate_offer_ref',
|
|
54
|
+
'availability_duplicate_offer_version_ref',
|
|
55
|
+
'availability_expected_revision_missing',
|
|
56
|
+
'availability_generation_mismatch',
|
|
57
|
+
'availability_hotel_limit_exceeded',
|
|
58
|
+
'availability_hotel_not_active',
|
|
59
|
+
'availability_hotel_unknown',
|
|
60
|
+
'availability_observation_required',
|
|
61
|
+
'availability_offer_limit_exceeded',
|
|
62
|
+
'availability_offers_count_mismatch',
|
|
63
|
+
'availability_offers_hotel_mismatch',
|
|
64
|
+
'availability_offers_observation_required',
|
|
65
|
+
'availability_offers_receipt_incoherent',
|
|
66
|
+
'availability_offers_unreported',
|
|
67
|
+
'availability_offers_workspace_mismatch',
|
|
68
|
+
'availability_query_not_reserved',
|
|
69
|
+
'availability_query_provenance_mismatch',
|
|
70
|
+
'availability_query_receipt_mismatch',
|
|
71
|
+
'availability_receipt_digest_mismatch',
|
|
72
|
+
'availability_receipt_incoherent',
|
|
73
|
+
'availability_stale_receipt',
|
|
74
|
+
'availability_terminal',
|
|
75
|
+
'booking_malformed_workspace',
|
|
76
|
+
'context_mismatch',
|
|
77
|
+
'invalid_task_id',
|
|
78
|
+
'receipt_action_mismatch',
|
|
79
|
+
'receipt_conflict',
|
|
80
|
+
'receipt_observation_action_mismatch',
|
|
81
|
+
'receipt_relaxation_unauthorized',
|
|
82
|
+
'receipt_required',
|
|
83
|
+
'receipt_source_action_mismatch',
|
|
84
|
+
'receipt_source_digest_mismatch',
|
|
85
|
+
'receipt_target_mismatch',
|
|
86
|
+
'receipt_verified_offer_expired',
|
|
87
|
+
'reanchor_turn_required',
|
|
88
|
+
'request_conflict',
|
|
89
|
+
'request_key_invalidated',
|
|
90
|
+
'revision_mismatch',
|
|
91
|
+
'revision_regression',
|
|
92
|
+
'task_not_found',
|
|
93
|
+
'task_terminal',
|
|
94
|
+
'turn_conflict',
|
|
95
|
+
'unexpected_receipt',
|
|
96
|
+
'unsafe_opaque_ref',
|
|
97
|
+
'workspace_mismatch',
|
|
98
|
+
] as const
|
|
99
|
+
|
|
100
|
+
export type BookingDispatchRejectionReason = typeof BOOKING_DISPATCH_REJECTION_REASONS[number]
|
|
101
|
+
export const BOOKING_DISPATCH_UNKNOWN_REASON = 'UNCLASSIFIED' as const
|
|
102
|
+
export type BookingDispatchLogReason = BookingDispatchRejectionReason | typeof BOOKING_DISPATCH_UNKNOWN_REASON
|
|
103
|
+
|
|
104
|
+
const DISPATCH_REJECTION_REASON_SET = new Set<string>(BOOKING_DISPATCH_REJECTION_REASONS)
|
|
105
|
+
|
|
106
|
+
/** Returns a reason only when the complete boundary error is one known token. */
|
|
107
|
+
export function extractBookingDispatchReason(error: unknown): BookingDispatchLogReason {
|
|
108
|
+
const message = typeof error === 'string' ? error : error instanceof Error ? error.message : undefined
|
|
109
|
+
return message !== undefined && DISPATCH_REJECTION_REASON_SET.has(message)
|
|
110
|
+
? message as BookingDispatchRejectionReason
|
|
111
|
+
: BOOKING_DISPATCH_UNKNOWN_REASON
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const ALIASES: Record<string, BookingTypedErrorCode> = {
|
|
115
|
+
payload_too_large: 'PAYLOAD_TOO_LARGE',
|
|
116
|
+
task_not_found: 'TASK_NOT_FOUND',
|
|
117
|
+
task_terminal: 'TASK_TERMINAL',
|
|
118
|
+
receipt_required: 'RECEIPT_REQUIRED',
|
|
119
|
+
receipt_conflict: 'RECEIPT_CONFLICT',
|
|
120
|
+
unsupported_action: 'UNSUPPORTED_ACTION',
|
|
121
|
+
planner_surface_action_unsupported: 'PLANNER_SURFACE_ACTION_UNSUPPORTED',
|
|
122
|
+
planner_no_decision: 'PLANNER_NO_DECISION',
|
|
123
|
+
planner_typed_decision_required: 'PLANNER_TYPED_DECISION_REQUIRED',
|
|
124
|
+
planner_provider_auth_failed: 'PLANNER_PROVIDER_AUTH_FAILED',
|
|
125
|
+
planner_provider_quota_exhausted: 'PLANNER_PROVIDER_QUOTA_EXHAUSTED',
|
|
126
|
+
planner_provider_rate_limited: 'PLANNER_PROVIDER_RATE_LIMITED',
|
|
127
|
+
planner_provider_unavailable: 'PLANNER_PROVIDER_UNAVAILABLE',
|
|
128
|
+
planner_provider_request_rejected: 'PLANNER_PROVIDER_REQUEST_REJECTED',
|
|
129
|
+
planner_provider_response_invalid: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
130
|
+
planner_provider_timeout: 'PLANNER_PROVIDER_TIMEOUT',
|
|
131
|
+
planner_boot_timeout: 'PLANNER_BOOT_TIMEOUT',
|
|
132
|
+
planner_configuration_invalid: 'PLANNER_CONFIGURATION_INVALID',
|
|
133
|
+
planner_failed: 'PLANNER_FAILED',
|
|
134
|
+
planner_invalid_tool_arguments: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
135
|
+
planner_invalid_typed_decision: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
136
|
+
planner_invalid_action: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
137
|
+
planner_booking_intent_required: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
138
|
+
planner_invalid_booking_intent: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
139
|
+
planner_ambiguous_booking_intent: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
140
|
+
planner_multiple_typed_decisions: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
141
|
+
planner_typed_decision_after_candidate: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
142
|
+
planner_typed_decision_missing: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
143
|
+
planner_unresolved_tool_call_before_candidate: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
144
|
+
planner_tool_call_duplicate_call_id: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
145
|
+
planner_tool_call_missing_call_id: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
146
|
+
planner_tool_call_rejected: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
147
|
+
planner_tool_result_malformed: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
148
|
+
planner_tool_result_out_of_order: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
149
|
+
planner_tool_result_unmatched: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
150
|
+
planner_terminal_checkpoint_mismatch: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
151
|
+
planner_terminal_checkpoint_unavailable: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
152
|
+
planner_terminal_intent_criteria_unachieved: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
153
|
+
planner_terminal_intent_target_unachieved: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
154
|
+
planner_terminal_intent_unjustified: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
155
|
+
planner_terminal_search_checkpoint_mismatch: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
156
|
+
planner_terminal_search_patch_not_ready: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
157
|
+
planner_terminal_search_results_not_ready: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
158
|
+
planner_terminal_search_workspace_mismatch: 'PLANNER_PROVIDER_RESPONSE_INVALID',
|
|
159
|
+
planner_forbidden_action: 'UNSUPPORTED_ACTION',
|
|
160
|
+
planner_forbidden_tool: 'UNSUPPORTED_ACTION',
|
|
161
|
+
planner_capability_action_mismatch: 'UNSUPPORTED_ACTION',
|
|
162
|
+
planner_intent_target_unsupported: 'PLANNER_SURFACE_ACTION_UNSUPPORTED',
|
|
163
|
+
planner_context_mismatch: 'CONTEXT_MISMATCH',
|
|
164
|
+
planner_revision_mismatch: 'STALE_REVISION',
|
|
165
|
+
booking_intent_required: 'INVALID_ACTION',
|
|
166
|
+
invalid_booking_intent: 'INVALID_ACTION',
|
|
167
|
+
action_intent_mismatch: 'INVALID_ACTION',
|
|
168
|
+
intent_mutation_forbidden: 'INVALID_ACTION',
|
|
169
|
+
invalid_action: 'INVALID_ACTION',
|
|
170
|
+
invalid_event: 'INVALID_EVENT',
|
|
171
|
+
context_mismatch: 'CONTEXT_MISMATCH',
|
|
172
|
+
workspace_mismatch: 'WORKSPACE_MISMATCH',
|
|
173
|
+
action_conflict: 'ACTION_CONFLICT',
|
|
174
|
+
approval_replayed: 'ACTION_CONFLICT',
|
|
175
|
+
request_conflict: 'ACTION_CONFLICT',
|
|
176
|
+
turn_conflict: 'ACTION_CONFLICT',
|
|
177
|
+
stale_revision: 'STALE_REVISION',
|
|
178
|
+
operation_limit_reached: 'OPERATION_LIMIT_REACHED',
|
|
179
|
+
availability_terminal_policy_owned: 'AVAILABILITY_TERMINAL_POLICY_OWNED',
|
|
180
|
+
trusted_ingress_binding_required: 'TRUSTED_INGRESS_BINDING_REQUIRED',
|
|
181
|
+
invalid_ingress_binding: 'INVALID_INGRESS_BINDING',
|
|
182
|
+
booking_surface_schema_mismatch: 'BOOKING_SURFACE_SCHEMA_MISMATCH',
|
|
183
|
+
unauthorized: 'UNAUTHORIZED',
|
|
184
|
+
not_found: 'NOT_FOUND',
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const SAFE_MESSAGES: Record<BookingTypedErrorCode, string> = {
|
|
188
|
+
PAYLOAD_TOO_LARGE: 'Request payload exceeds the configured limit.',
|
|
189
|
+
TASK_NOT_FOUND: 'The requested task was not found.',
|
|
190
|
+
TASK_TERMINAL: 'The task is already terminal.',
|
|
191
|
+
RECEIPT_REQUIRED: 'A matching receipt is required before another action.',
|
|
192
|
+
RECEIPT_CONFLICT: 'The receipt conflicts with the durable task record.',
|
|
193
|
+
UNSUPPORTED_ACTION: 'The requested action is outside the trusted action policy.',
|
|
194
|
+
PLANNER_SURFACE_ACTION_UNSUPPORTED: 'The planner action is outside the trusted surface policy.',
|
|
195
|
+
PLANNER_NO_DECISION: 'The planner returned no typed decision.',
|
|
196
|
+
PLANNER_TYPED_DECISION_REQUIRED: 'The planner returned no typed capability decision.',
|
|
197
|
+
PLANNER_PROVIDER_AUTH_FAILED: 'The planner provider rejected authentication.',
|
|
198
|
+
PLANNER_PROVIDER_QUOTA_EXHAUSTED: 'The planner provider quota is exhausted.',
|
|
199
|
+
PLANNER_PROVIDER_RATE_LIMITED: 'The planner provider rate-limited the request.',
|
|
200
|
+
PLANNER_PROVIDER_UNAVAILABLE: 'The planner provider is temporarily unavailable.',
|
|
201
|
+
PLANNER_PROVIDER_REQUEST_REJECTED: 'The planner provider rejected the model request.',
|
|
202
|
+
PLANNER_PROVIDER_RESPONSE_INVALID: 'The planner provider returned an invalid response.',
|
|
203
|
+
PLANNER_PROVIDER_TIMEOUT: 'The planner did not respond within the booking turn deadline.',
|
|
204
|
+
PLANNER_BOOT_TIMEOUT: 'The planner runtime did not finish starting within its local boot budget.',
|
|
205
|
+
PLANNER_CONFIGURATION_INVALID: 'The planner provider configuration is invalid.',
|
|
206
|
+
PLANNER_FAILED: 'The planner stopped unexpectedly before producing a usable action.',
|
|
207
|
+
INVALID_ACTION: 'The planner action failed contract validation.',
|
|
208
|
+
INVALID_EVENT: 'The planner event failed contract validation.',
|
|
209
|
+
CONTEXT_MISMATCH: 'The request context does not match the trusted task.',
|
|
210
|
+
WORKSPACE_MISMATCH: 'The request workspace does not match the trusted task.',
|
|
211
|
+
ACTION_CONFLICT: 'The request conflicts with the durable action checkpoint.',
|
|
212
|
+
STALE_REVISION: 'The request revision is stale.',
|
|
213
|
+
OPERATION_LIMIT_REACHED: 'The task operation limit has been reached.',
|
|
214
|
+
AVAILABILITY_TERMINAL_POLICY_OWNED: 'Availability policy owns the terminal decision.',
|
|
215
|
+
TRUSTED_INGRESS_BINDING_REQUIRED: 'A trusted ingress binding is required.',
|
|
216
|
+
INVALID_INGRESS_BINDING: 'The trusted ingress binding is invalid.',
|
|
217
|
+
BOOKING_SURFACE_SCHEMA_MISMATCH: 'The booking surface schema is not supported.',
|
|
218
|
+
UNAUTHORIZED: 'The request is not authorized.',
|
|
219
|
+
NOT_FOUND: 'The requested resource was not found.',
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function rawCode(error: unknown): string {
|
|
223
|
+
if (typeof error === 'string') return error.split(':', 1)[0]!
|
|
224
|
+
if (error instanceof Error && error.message) return error.message.split(':', 1)[0]!
|
|
225
|
+
return 'planner_failed'
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function normalizeBookingErrorCode(error: unknown): BookingTypedErrorCode {
|
|
229
|
+
const raw = rawCode(error)
|
|
230
|
+
const normalized = raw.trim().toLowerCase()
|
|
231
|
+
const aliased = ALIASES[normalized]
|
|
232
|
+
if (aliased) return aliased
|
|
233
|
+
const uppercase = raw.trim().replace(/[^A-Za-z0-9]+/g, '_').toUpperCase()
|
|
234
|
+
return (BOOKING_TYPED_ERROR_CODES as readonly string[]).includes(uppercase)
|
|
235
|
+
? uppercase as BookingTypedErrorCode
|
|
236
|
+
: 'PLANNER_FAILED'
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function safeBookingErrorMessage(code: string): string {
|
|
240
|
+
return SAFE_MESSAGES[(BOOKING_TYPED_ERROR_CODES as readonly string[]).includes(code) ? code as BookingTypedErrorCode : 'PLANNER_FAILED']
|
|
241
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './contracts.ts'
|
|
2
|
+
export * from './dsh-planner.ts'
|
|
3
|
+
export * from './profile.ts'
|
|
4
|
+
export * from './runtime.ts'
|
|
5
|
+
export * from './server.ts'
|
|
6
|
+
export * from './startup.ts'
|
|
7
|
+
export * from './validation.ts'
|
|
8
|
+
export * from './availability-policy.ts'
|
|
9
|
+
export * from './booking-intent.ts'
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process'
|
|
2
|
+
|
|
3
|
+
export type ManagedDshWorkerOutcome =
|
|
4
|
+
| { state: 'pending' }
|
|
5
|
+
| { state: 'exited'; exitCode: number | null; signal: string | null }
|
|
6
|
+
| { state: 'failed' }
|
|
7
|
+
|
|
8
|
+
export interface ManagedDshGroupMember {
|
|
9
|
+
pid: number
|
|
10
|
+
ppid: number
|
|
11
|
+
pgid: number
|
|
12
|
+
state: string
|
|
13
|
+
/** Read-only `ps lstart` identity evidence; zombies keep their original start time. */
|
|
14
|
+
startedAt: string | null
|
|
15
|
+
zombie: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `has-live-members`: at least one non-zombie member remains. `zombie-only`:
|
|
20
|
+
* every remaining member is a dead-but-unreaped zombie. `empty`: the group has
|
|
21
|
+
* no visible member. On Darwin the detached-fallback observation
|
|
22
|
+
* (`kill(-pgid, 0)`) cannot distinguish these: it returns EPERM for
|
|
23
|
+
* zombie-only groups, which the runtime maps to "alive".
|
|
24
|
+
*/
|
|
25
|
+
export type ManagedDshGroupClassification = 'empty' | 'zombie-only' | 'has-live-members'
|
|
26
|
+
|
|
27
|
+
export interface ManagedDshProcessGroupSnapshot {
|
|
28
|
+
status: 'observed' | 'unavailable' | 'unsupported' | 'unknown_worker'
|
|
29
|
+
expectedPgid: number | null
|
|
30
|
+
members: ManagedDshGroupMember[]
|
|
31
|
+
truncated: boolean
|
|
32
|
+
classification: ManagedDshGroupClassification | null
|
|
33
|
+
liveMemberCount: number | null
|
|
34
|
+
zombieMemberCount: number | null
|
|
35
|
+
/** Start-time anchor captured while the worker was alive, for identity comparison. */
|
|
36
|
+
workerStartedAt: string | null
|
|
37
|
+
workerIdentity: 'match' | 'mismatch' | 'worker-absent' | 'unknown' | null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ManagedDshCleanupDiagnostic {
|
|
41
|
+
schemaVersion: 'managed-dsh-cleanup.v2'
|
|
42
|
+
role: 'task' | 'warmer' | 'unspecified'
|
|
43
|
+
workerPid: number | null
|
|
44
|
+
elapsedMs: number
|
|
45
|
+
deadlineMs: number
|
|
46
|
+
graceMs: number
|
|
47
|
+
workerOutcome: ManagedDshWorkerOutcome
|
|
48
|
+
processGroup: ManagedDshProcessGroupSnapshot
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Diagnostics never include argv, environment, provider output or request data. */
|
|
52
|
+
export class ManagedDshCleanupError extends Error {
|
|
53
|
+
constructor(message: string, readonly diagnostic: ManagedDshCleanupDiagnostic) {
|
|
54
|
+
// Keep the safe snapshot visible even when nested AggregateError inspection
|
|
55
|
+
// collapses custom object properties in an uncaught-error log.
|
|
56
|
+
super(`${message}; diagnostic=${JSON.stringify(diagnostic)}`)
|
|
57
|
+
this.name = 'ManagedDshCleanupError'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const MEMBER_LINE = /^(\d+)\s+(\d+)\s+(\d+)\s+([A-Za-z+<NsLlEWXU-]+)\s+(.+?)\s*$/
|
|
62
|
+
const MAX_MEMBERS = 32
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Classify one `ps -axo pid=,ppid=,pgid=,stat=,lstart=` table for the owned
|
|
66
|
+
* group. Pure so proofs can feed crafted tables without signalling anything.
|
|
67
|
+
*/
|
|
68
|
+
export function parseManagedDshGroupSnapshot(
|
|
69
|
+
stdout: string,
|
|
70
|
+
expectedPgid: number | null,
|
|
71
|
+
workerStartedAt: string | null = null,
|
|
72
|
+
): ManagedDshProcessGroupSnapshot {
|
|
73
|
+
const empty = {
|
|
74
|
+
status: 'unknown_worker', expectedPgid, members: [], truncated: false, classification: null,
|
|
75
|
+
liveMemberCount: null, zombieMemberCount: null, workerStartedAt, workerIdentity: null,
|
|
76
|
+
} as ManagedDshProcessGroupSnapshot
|
|
77
|
+
if (expectedPgid === null) return { ...empty, status: 'unknown_worker' }
|
|
78
|
+
const members: ManagedDshGroupMember[] = []
|
|
79
|
+
for (const line of stdout.split('\n')) {
|
|
80
|
+
const match = line.trim().match(MEMBER_LINE)
|
|
81
|
+
if (!match || Number(match[3]) !== expectedPgid) continue
|
|
82
|
+
members.push({
|
|
83
|
+
pid: Number(match[1]), ppid: Number(match[2]), pgid: Number(match[3]),
|
|
84
|
+
state: match[4], startedAt: match[5] ?? null, zombie: match[4].startsWith('Z'),
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
const liveMemberCount = members.filter((member) => !member.zombie).length
|
|
88
|
+
const zombieMemberCount = members.length - liveMemberCount
|
|
89
|
+
const classification: ManagedDshGroupClassification =
|
|
90
|
+
members.length === 0 ? 'empty' : liveMemberCount === 0 ? 'zombie-only' : 'has-live-members'
|
|
91
|
+
let workerIdentity: ManagedDshProcessGroupSnapshot['workerIdentity'] = 'unknown'
|
|
92
|
+
if (workerStartedAt !== null) {
|
|
93
|
+
const workerRow = members.find((member) => member.pid === expectedPgid)
|
|
94
|
+
workerIdentity = workerRow === undefined
|
|
95
|
+
? 'worker-absent'
|
|
96
|
+
: workerRow.startedAt === workerStartedAt ? 'match' : 'mismatch'
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
status: 'observed', expectedPgid,
|
|
100
|
+
members: members.slice(0, MAX_MEMBERS), truncated: members.length > MAX_MEMBERS,
|
|
101
|
+
classification, liveMemberCount, zombieMemberCount,
|
|
102
|
+
workerStartedAt, workerIdentity,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Whether the snapshot proves the owned group holds no live member. */
|
|
107
|
+
export function managedDshGroupIsQuiescent(group: ManagedDshProcessGroupSnapshot): boolean {
|
|
108
|
+
return group.status === 'observed' && (group.classification === 'empty' || group.classification === 'zombie-only')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Read-only one-shot start-time anchor for the live worker (Darwin only). */
|
|
112
|
+
export function readManagedDshWorkerStart(pid: number): Promise<string | null> {
|
|
113
|
+
if (process.platform !== 'darwin') return Promise.resolve(null)
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
execFile('/bin/ps', ['-p', String(pid), '-o', 'lstart='], {
|
|
116
|
+
encoding: 'utf8', timeout: 250, maxBuffer: 4096,
|
|
117
|
+
env: { PATH: '/usr/bin:/bin', LC_ALL: 'C' },
|
|
118
|
+
}, (error, stdout) => resolve(error ? null : stdout.trim() || null))
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Observe only the detached worker's group, without signalling any process.
|
|
124
|
+
* Snapshot fields are limited to pid/ppid/pgid/state/start time — never argv,
|
|
125
|
+
* environment, or request content.
|
|
126
|
+
*/
|
|
127
|
+
export async function snapshotManagedDshGroup(
|
|
128
|
+
workerPid: number | null,
|
|
129
|
+
workerStartedAt: string | null = null,
|
|
130
|
+
): Promise<ManagedDshProcessGroupSnapshot> {
|
|
131
|
+
const empty = {
|
|
132
|
+
status: 'unknown_worker', expectedPgid: null, members: [], truncated: false, classification: null,
|
|
133
|
+
liveMemberCount: null, zombieMemberCount: null, workerStartedAt, workerIdentity: null,
|
|
134
|
+
} as ManagedDshProcessGroupSnapshot
|
|
135
|
+
if (workerPid === null) return { ...empty, status: 'unknown_worker' }
|
|
136
|
+
// Only Darwin's installed detached fallback establishes PID == PGID here.
|
|
137
|
+
// Linux native scopes and Windows Jobs require a provider range identity,
|
|
138
|
+
// so an unsupported platform claims no expected group at all.
|
|
139
|
+
if (process.platform !== 'darwin') return { ...empty, status: 'unsupported' }
|
|
140
|
+
return new Promise((resolve) => {
|
|
141
|
+
// A separate, bounded failure-only observation; it does not extend the
|
|
142
|
+
// provider's cleanup deadline or change its success/failure verdict.
|
|
143
|
+
execFile('/bin/ps', ['-axo', 'pid=,ppid=,pgid=,stat=,lstart='], {
|
|
144
|
+
encoding: 'utf8', timeout: 250, maxBuffer: 1024 * 1024,
|
|
145
|
+
env: { PATH: '/usr/bin:/bin', LC_ALL: 'C' },
|
|
146
|
+
}, (error, stdout) => {
|
|
147
|
+
if (error) return resolve({ ...empty, expectedPgid: workerPid, status: 'unavailable' })
|
|
148
|
+
resolve(parseManagedDshGroupSnapshot(stdout, workerPid, workerStartedAt))
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { Context } from '@deepseek-ai/cordis'
|
|
6
|
+
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
|
|
7
|
+
import type { SubprocessHandle } from '@deepseek-ai/dsh-subprocess'
|
|
8
|
+
import type { DshBootObservation, DshPlannerRunPort, DshPlannerRunResult } from './dsh-planner.ts'
|
|
9
|
+
import {
|
|
10
|
+
ManagedDshCleanupError,
|
|
11
|
+
managedDshGroupIsQuiescent,
|
|
12
|
+
readManagedDshWorkerStart,
|
|
13
|
+
snapshotManagedDshGroup,
|
|
14
|
+
type ManagedDshProcessGroupSnapshot,
|
|
15
|
+
type ManagedDshWorkerOutcome,
|
|
16
|
+
} from './managed-dsh-cleanup-diagnostic.ts'
|
|
17
|
+
|
|
18
|
+
export interface ManagedDshRunPortOptions {
|
|
19
|
+
cwd?: string
|
|
20
|
+
workerPath?: string
|
|
21
|
+
graceMs?: number
|
|
22
|
+
cleanupRole?: 'task' | 'warmer'
|
|
23
|
+
env?: NodeJS.ProcessEnv
|
|
24
|
+
/** Test seam overriding the failure-path group snapshot; production uses the safe ps snapshot. */
|
|
25
|
+
groupObserver?: typeof snapshotManagedDshGroup
|
|
26
|
+
/**
|
|
27
|
+
* Boot-marker channel (#511): receives one `HARNESS_BOOT_STAGE …` line per
|
|
28
|
+
* completed initialize handshake and one `HARNESS_BOOT_TIMEOUT …` line when
|
|
29
|
+
* the worker's own handshake deadline expires. Defaults to process stderr —
|
|
30
|
+
* the serving process log surface these markers were missing from.
|
|
31
|
+
*/
|
|
32
|
+
bootLog?: (line: string) => void
|
|
33
|
+
[key: string]: unknown
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The only worker failure classifications allowed to cross the process boundary. */
|
|
37
|
+
const WORKER_FAILURE_CODES = new Set(['HARNESS_BOOT_TIMEOUT', 'HARNESS_START_FAILED', 'HARNESS_RUN_FAILED'])
|
|
38
|
+
|
|
39
|
+
const requireFromModule = createRequire(import.meta.url)
|
|
40
|
+
|
|
41
|
+
function workerLaunch(path: string): readonly string[] {
|
|
42
|
+
// The worker cwd is the isolated booking state root, so a bare `tsx/esm`
|
|
43
|
+
// loader would resolve from the wrong dependency tree and exit before the
|
|
44
|
+
// first request. Resolve the loader from this package once and pass its
|
|
45
|
+
// absolute installed path to Node.
|
|
46
|
+
return path.endsWith('.ts')
|
|
47
|
+
? [process.execPath, '--import', requireFromModule.resolve('tsx/esm'), path]
|
|
48
|
+
: [process.execPath, path]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Run DeepSeekHarness in a child tree owned by dsh-subprocess-local. */
|
|
52
|
+
export class ManagedDshRunPort implements DshPlannerRunPort {
|
|
53
|
+
private readonly handle: SubprocessHandle
|
|
54
|
+
private readonly runtime: LocalSubprocessRuntime
|
|
55
|
+
private readonly pending = new Map<number, { ok: (value?: DshPlannerRunResult) => void; fail: (error: Error) => void; progress?: () => void }>()
|
|
56
|
+
private sequence = 0
|
|
57
|
+
private closePromise: Promise<void> | undefined
|
|
58
|
+
private terminalError: Error | undefined
|
|
59
|
+
private inputBuffer = ''
|
|
60
|
+
private workerPid: number | null = null
|
|
61
|
+
private workerStartedAt: string | null = null
|
|
62
|
+
private workerOutcome: ManagedDshWorkerOutcome = { state: 'pending' }
|
|
63
|
+
private readonly cleanupRole: 'task' | 'warmer' | 'unspecified'
|
|
64
|
+
private readonly graceMs: number
|
|
65
|
+
|
|
66
|
+
constructor(options: ManagedDshRunPortOptions = {}) {
|
|
67
|
+
const defaultWorker = join(dirname(fileURLToPath(import.meta.url)), 'dsh-worker.js')
|
|
68
|
+
const workerPath = options.workerPath ?? (existsSync(defaultWorker) ? defaultWorker : defaultWorker.replace(/\.js$/, '.ts'))
|
|
69
|
+
const { workerPath: _worker, graceMs = 500, cleanupRole, env, groupObserver, bootLog, ...harnessOptions } = options
|
|
70
|
+
this.cleanupRole = cleanupRole ?? 'unspecified'
|
|
71
|
+
this.graceMs = graceMs
|
|
72
|
+
this.groupObserver = groupObserver ?? snapshotManagedDshGroup
|
|
73
|
+
this.bootLog = bootLog ?? ((line: string) => { process.stderr.write(`${line}\n`) })
|
|
74
|
+
this.constructedAtMs = Date.now()
|
|
75
|
+
this.runtime = new LocalSubprocessRuntime(new Context())
|
|
76
|
+
this.handle = this.runtime.spawn({
|
|
77
|
+
argv: workerLaunch(workerPath),
|
|
78
|
+
cwd: options.cwd ?? process.cwd(),
|
|
79
|
+
// Provider diagnostics may contain request fragments. Keep a bounded
|
|
80
|
+
// private tail for ownership without inheriting it into service logs.
|
|
81
|
+
stdio: { stdin: 'pipe', stdout: 'pipe', stderr: { maxBytes: 64 * 1024 } },
|
|
82
|
+
graceMs,
|
|
83
|
+
env,
|
|
84
|
+
})
|
|
85
|
+
this.handle.stdout!.setEncoding('utf8')
|
|
86
|
+
this.handle.stdout!.on('data', (chunk: string) => this.consume(chunk))
|
|
87
|
+
this.handle.done.then(
|
|
88
|
+
(outcome) => {
|
|
89
|
+
this.workerOutcome = { state: 'exited', exitCode: outcome.exitCode, signal: outcome.signal }
|
|
90
|
+
this.markTerminal('managed DSH worker exited')
|
|
91
|
+
},
|
|
92
|
+
() => {
|
|
93
|
+
this.workerOutcome = { state: 'failed' }
|
|
94
|
+
this.markTerminal('managed DSH worker failed')
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
// Credentials are already in the managed worker environment. Never copy
|
|
98
|
+
// them into the JSON-lines protocol or a thrown worker error.
|
|
99
|
+
this.harnessOptions = harnessOptions
|
|
100
|
+
this.cleanupDeadlineMs = Math.max(1_000, graceMs * 4)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private readonly harnessOptions: Record<string, unknown>
|
|
104
|
+
private readonly cleanupDeadlineMs: number
|
|
105
|
+
private readonly groupObserver: typeof snapshotManagedDshGroup
|
|
106
|
+
private readonly bootLog: (line: string) => void
|
|
107
|
+
private readonly constructedAtMs: number
|
|
108
|
+
private booted: DshBootObservation | undefined
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* #511: surface the boot markers in the serving process. The four startup
|
|
112
|
+
* marker families previously existed only in build-time proof output, so a
|
|
113
|
+
* recurrence in service runtime left nothing to grep. Payloads are closed
|
|
114
|
+
* shapes only — role, timings; never prompts, provider fragments, or
|
|
115
|
+
* credentials.
|
|
116
|
+
*/
|
|
117
|
+
private emitBootLog(line: string): void {
|
|
118
|
+
try {
|
|
119
|
+
this.bootLog(line)
|
|
120
|
+
} catch { /* boot markers must never break the worker protocol */ }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* What the most recent worker request paid for the initialize handshake: the
|
|
125
|
+
* measured wall time when that request started the runtime, and zero when an
|
|
126
|
+
* earlier request in the same worker already had. Read by the planner to keep
|
|
127
|
+
* our own boot cost separate from the provider budget it must not consume.
|
|
128
|
+
*/
|
|
129
|
+
bootObservation(): DshBootObservation | undefined {
|
|
130
|
+
return this.booted
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private consume(chunk: string): void {
|
|
134
|
+
this.inputBuffer += chunk
|
|
135
|
+
for (;;) {
|
|
136
|
+
const newline = this.inputBuffer.indexOf('\n')
|
|
137
|
+
if (newline < 0) return
|
|
138
|
+
const line = this.inputBuffer.slice(0, newline); this.inputBuffer = this.inputBuffer.slice(newline + 1)
|
|
139
|
+
try {
|
|
140
|
+
const message = JSON.parse(line) as { id: number; ok?: boolean; progress?: boolean; result?: DshPlannerRunResult; error?: string; lifecycle?: string; workerPid?: number; parentPid?: number; boot?: DshBootObservation }
|
|
141
|
+
if (message.lifecycle === 'worker_started') {
|
|
142
|
+
if (this.workerPid === null && Number.isSafeInteger(message.workerPid) && message.workerPid! > 0 && message.parentPid === process.pid) {
|
|
143
|
+
this.workerPid = message.workerPid!
|
|
144
|
+
// One bounded read-only start-time anchor, captured while the worker
|
|
145
|
+
// is alive, so a later failure snapshot can disprove PID reuse.
|
|
146
|
+
void readManagedDshWorkerStart(this.workerPid).then((startedAt) => {
|
|
147
|
+
if (this.workerStartedAt === null) this.workerStartedAt = startedAt
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
152
|
+
if (message.progress) {
|
|
153
|
+
this.pending.get(message.id)?.progress?.()
|
|
154
|
+
continue
|
|
155
|
+
}
|
|
156
|
+
// A boot checkpoint carries the initialize handshake the worker already
|
|
157
|
+
// completed; the terminal reply for the same request still follows, and
|
|
158
|
+
// a request killed after booting has left this measurement behind.
|
|
159
|
+
if (message.boot) {
|
|
160
|
+
this.booted = message.boot
|
|
161
|
+
// One line per real subprocess boot (#511): only a 'started'
|
|
162
|
+
// handshake measured an initialize; 'reused' rode an earlier one.
|
|
163
|
+
if (message.boot.mode === 'started') {
|
|
164
|
+
this.emitBootLog(`HARNESS_BOOT_STAGE ${JSON.stringify({ role: this.cleanupRole, initializeMs: message.boot.initializeMs, mode: 'started' })}`)
|
|
165
|
+
}
|
|
166
|
+
if (message.ok === undefined) continue
|
|
167
|
+
}
|
|
168
|
+
const waiter = this.pending.get(message.id); if (!waiter) continue
|
|
169
|
+
this.pending.delete(message.id)
|
|
170
|
+
if (message.ok) waiter.ok(message.result)
|
|
171
|
+
// Worker stdout is a process boundary: an arbitrary payload must never
|
|
172
|
+
// become the error the planner classifies on.
|
|
173
|
+
else if (typeof message.error === 'string' && WORKER_FAILURE_CODES.has(message.error)) {
|
|
174
|
+
if (message.error === 'HARNESS_BOOT_TIMEOUT') {
|
|
175
|
+
// The worker's own initialize deadline expired before any handshake
|
|
176
|
+
// completed; record the closed classification plus what this port
|
|
177
|
+
// observable spent on it (closeMs belongs to cleanup diagnostics).
|
|
178
|
+
this.emitBootLog(`HARNESS_BOOT_TIMEOUT ${JSON.stringify({
|
|
179
|
+
role: this.cleanupRole,
|
|
180
|
+
elapsedMs: Date.now() - this.constructedAtMs,
|
|
181
|
+
initializeMs: this.booted?.initializeMs ?? null,
|
|
182
|
+
})}`)
|
|
183
|
+
}
|
|
184
|
+
waiter.fail(new Error(message.error))
|
|
185
|
+
}
|
|
186
|
+
else waiter.fail(new Error('HARNESS_RUN_FAILED'))
|
|
187
|
+
} catch (error) { this.failPending(error instanceof Error ? error : new Error(String(error))) }
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private failPending(error: Error): void {
|
|
192
|
+
for (const waiter of this.pending.values()) waiter.fail(error)
|
|
193
|
+
this.pending.clear()
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private markTerminal(message: string): void {
|
|
197
|
+
// Retain a safe terminal outcome before rejecting existing waiters: their
|
|
198
|
+
// continuations may immediately submit another request to this same port.
|
|
199
|
+
this.terminalError ??= new Error(message)
|
|
200
|
+
this.failPending(this.terminalError)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
run(prompt: string, options: { sessionId: string; onProgress?: () => void }): Promise<DshPlannerRunResult> {
|
|
204
|
+
if (this.closePromise) return Promise.reject(new Error('managed DSH run port is closed'))
|
|
205
|
+
if (this.terminalError) return Promise.reject(this.terminalError)
|
|
206
|
+
const id = ++this.sequence
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
this.pending.set(id, { ok: (value) => resolve(value as DshPlannerRunResult), fail: reject, progress: options.onProgress })
|
|
209
|
+
this.handle.stdin!.write(`${JSON.stringify({ id, prompt, sessionId: options.sessionId, options: this.harnessOptions })}\n`)
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Boot the in-worker harness without consuming a provider call. */
|
|
214
|
+
warmup(): Promise<void> {
|
|
215
|
+
if (this.closePromise) return Promise.reject(new Error('managed DSH run port is closed'))
|
|
216
|
+
if (this.terminalError) return Promise.reject(this.terminalError)
|
|
217
|
+
const id = ++this.sequence
|
|
218
|
+
return new Promise((resolve, reject) => {
|
|
219
|
+
this.pending.set(id, { ok: () => resolve(), fail: reject })
|
|
220
|
+
this.handle.stdin!.write(`${JSON.stringify({ id, warmup: true, options: this.harnessOptions })}\n`)
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
close(): Promise<void> {
|
|
225
|
+
if (this.closePromise) return this.closePromise
|
|
226
|
+
this.closePromise = (async () => {
|
|
227
|
+
const started = performance.now()
|
|
228
|
+
this.failPending(new Error('managed DSH run port closed'))
|
|
229
|
+
this.handle.terminate()
|
|
230
|
+
// Observe worker failure even if range observation rejects or times out
|
|
231
|
+
// first. This derived promise must never become an unhandled rejection.
|
|
232
|
+
const outcome = this.handle.done.then(
|
|
233
|
+
() => undefined,
|
|
234
|
+
() => new Error('managed DSH worker failed'),
|
|
235
|
+
)
|
|
236
|
+
let rangeEmpty: boolean
|
|
237
|
+
try {
|
|
238
|
+
rangeEmpty = await this.handle.waitForExit(AbortSignal.timeout(this.cleanupDeadlineMs))
|
|
239
|
+
} catch {
|
|
240
|
+
throw await this.cleanupError('managed DSH process tree observation failed', started)
|
|
241
|
+
}
|
|
242
|
+
if (!rangeEmpty) {
|
|
243
|
+
// On Darwin the installed detached fallback observes the group through
|
|
244
|
+
// kill(-pgid, 0): a zombie-only group yields EPERM, which the runtime
|
|
245
|
+
// maps to "alive", and zombies only disappear when their owner reaps
|
|
246
|
+
// them — no signal can accelerate that. The deadline has not moved;
|
|
247
|
+
// verify through the safe process table whether a live member actually
|
|
248
|
+
// remains before converting the observation deadline into a failure.
|
|
249
|
+
const processGroup = await this.groupObserver(this.workerPid, this.workerStartedAt)
|
|
250
|
+
if (!managedDshGroupIsQuiescent(processGroup)) {
|
|
251
|
+
throw await this.cleanupError('managed DSH process tree cleanup timeout', started, processGroup)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (await outcome) throw await this.cleanupError('managed DSH worker failed', started)
|
|
255
|
+
})()
|
|
256
|
+
return this.closePromise
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private async cleanupError(message: string, started: number, processGroup?: ManagedDshProcessGroupSnapshot): Promise<ManagedDshCleanupError> {
|
|
260
|
+
const elapsedMs = Math.round(performance.now() - started)
|
|
261
|
+
const workerOutcome = { ...this.workerOutcome }
|
|
262
|
+
const group = processGroup ?? await this.groupObserver(this.workerPid, this.workerStartedAt)
|
|
263
|
+
return new ManagedDshCleanupError(message, {
|
|
264
|
+
schemaVersion: 'managed-dsh-cleanup.v2', role: this.cleanupRole,
|
|
265
|
+
workerPid: this.workerPid, elapsedMs, deadlineMs: this.cleanupDeadlineMs,
|
|
266
|
+
graceMs: this.graceMs, workerOutcome, processGroup: group,
|
|
267
|
+
})
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function createManagedDshRunPort(options?: ManagedDshRunPortOptions): DshPlannerRunPort {
|
|
272
|
+
return new ManagedDshRunPort(options)
|
|
273
|
+
}
|