@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
package/ts/capabilities/hbcli.ts
CHANGED
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
* 估算必须显式标记。这是 L4 与 L1 透明卡片的接缝。
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { homedir } from 'node:os'
|
|
16
|
+
import { join } from 'node:path'
|
|
17
|
+
import { spawnBounded } from './spawn-bounded.ts'
|
|
16
18
|
|
|
17
19
|
export interface HbcliCallOptions {
|
|
18
|
-
/** hbcli 二进制路径(默认 'hbcli',依赖 PATH) */
|
|
20
|
+
/** hbcli 二进制路径(默认 'hbcli',依赖 PATH;~/.local/bin 等已知安装位自动回退) */
|
|
19
21
|
hbcliBin?: string
|
|
20
22
|
/** 超时(ms) */
|
|
21
23
|
timeoutMs?: number
|
|
@@ -23,6 +25,8 @@ export interface HbcliCallOptions {
|
|
|
23
25
|
token?: string
|
|
24
26
|
/** 环境(uat/prod/dev);默认 uat */
|
|
25
27
|
env?: 'uat' | 'prod' | 'dev'
|
|
28
|
+
/** 宿主取消信号(exec.signal);abort → SIGTERM,500ms 后 SIGKILL 有界回收 */
|
|
29
|
+
signal?: AbortSignal
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export interface HbcliCallResult {
|
|
@@ -43,76 +47,121 @@ export interface HbcliCallResult {
|
|
|
43
47
|
error?: string
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
/**
|
|
51
|
+
* hbcli 二进制候选路径(gotry setup 按官方脚本装到 ~/.local/bin/hbcli,
|
|
52
|
+
* symlink 指向 ~/.staicli/current/hbcli——当 PATH 不含 ~/.local/bin 时裸名
|
|
53
|
+
* spawn 仍 ENOENT,按已知安装位回退)。仅对默认名 'hbcli' 扩展;显式自定义
|
|
54
|
+
* 名(如测试注入的不存在路径)不扩展,保持配置即所用的可测性。
|
|
55
|
+
*/
|
|
56
|
+
export function hbcliBinCandidates(bin: string, homeDir: string = homedir()): string[] {
|
|
57
|
+
if (bin !== 'hbcli') return [bin]
|
|
58
|
+
return [bin, join(homeDir, '.local/bin/hbcli'), join(homeDir, '.staicli/current/hbcli')]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** 单个候选的一次 spawn 封装:失败不抛,返回降级结果(spawnError 标记 ENOENT 类失败供上层换候选) */
|
|
62
|
+
async function attemptHbcli(
|
|
63
|
+
bin: string,
|
|
64
|
+
args: string[],
|
|
65
|
+
opts: Required<Pick<HbcliCallOptions, 'timeoutMs' | 'env'>> & { envVars: Record<string, string>; signal?: AbortSignal },
|
|
66
|
+
): Promise<HbcliCallResult & { spawnError?: boolean }> {
|
|
67
|
+
const started = Date.now()
|
|
68
|
+
const r = await spawnBounded(bin, args, {
|
|
69
|
+
env: { ...process.env, ...opts.envVars },
|
|
70
|
+
timeoutMs: opts.timeoutMs,
|
|
71
|
+
signal: opts.signal,
|
|
72
|
+
})
|
|
73
|
+
const latencyMs = Date.now() - started
|
|
74
|
+
const ts = new Date().toISOString()
|
|
75
|
+
const cleanupError = r.groupReaped === false ? 'process group cleanup incomplete' : undefined
|
|
76
|
+
if (r.aborted) {
|
|
77
|
+
return {
|
|
78
|
+
via: 'hbcli-error', exitCode: r.code ?? -1, result: null,
|
|
79
|
+
evidence: `[实时API:hbcli@abort@${ts}]`,
|
|
80
|
+
stderr: r.stderr.slice(0, 2000), latencyMs,
|
|
81
|
+
error: ['aborted by host signal', cleanupError].filter(Boolean).join('; '),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (r.error || r.groupReaped === false || r.code !== 0) {
|
|
85
|
+
const error = [r.error, r.stderr.trim().slice(0, 200), cleanupError].filter(Boolean).join('; ')
|
|
86
|
+
const failureKind = r.timedOut ? 'timeout' : /ENOENT/.test(r.error ?? '') ? 'spawn_error' : 'error'
|
|
87
|
+
return {
|
|
88
|
+
via: 'hbcli-error', exitCode: r.code ?? -1, result: null,
|
|
89
|
+
evidence: `[实时API:hbcli@${failureKind}@${ts}]`,
|
|
90
|
+
stderr: r.stderr.slice(0, 2000),
|
|
91
|
+
latencyMs, error: error || `exit ${r.code}`,
|
|
92
|
+
spawnError: /ENOENT/.test(r.error ?? ''),
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// 尝试 JSON 解析
|
|
96
|
+
const jStart = r.stdout.search(/[\{\[]/)
|
|
97
|
+
const jsonStr = jStart >= 0 ? r.stdout.slice(jStart) : ''
|
|
98
|
+
let result: unknown = null
|
|
99
|
+
if (jsonStr) {
|
|
100
|
+
try { result = JSON.parse(jsonStr) } catch { /* 非 JSON 输出,留给调用方处理 */ }
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
via: 'hbcli-realtime', exitCode: 0, result,
|
|
104
|
+
evidence: `[实时API:hbcli@${ts}]`,
|
|
105
|
+
stdout: r.stdout.slice(0, 2000), latencyMs,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
46
109
|
/** 通用 hbcli JSON 调用封装:失败不抛,而是返回降级结果 */
|
|
47
110
|
export async function callHbcliJson(
|
|
48
111
|
args: string[],
|
|
49
112
|
opts: HbcliCallOptions = {},
|
|
50
113
|
): Promise<HbcliCallResult> {
|
|
51
|
-
const started = Date.now()
|
|
52
|
-
const bin = opts.hbcliBin ?? 'hbcli'
|
|
53
|
-
const timeoutMs = opts.timeoutMs ?? 15_000
|
|
54
114
|
const env = opts.env ?? 'uat'
|
|
55
115
|
const envVars: Record<string, string> = { HOTELBYTE_ENV: env }
|
|
56
116
|
if (opts.token) envVars['HOTELBYTE_TOKEN'] = opts.token
|
|
117
|
+
const callOpts = { timeoutMs: opts.timeoutMs ?? 15_000, env, envVars, signal: opts.signal }
|
|
118
|
+
const candidates = hbcliBinCandidates(opts.hbcliBin ?? 'hbcli')
|
|
119
|
+
// abort 状态不可触发 fallback 候选;spawn 前的 pre-aborted 调用整体零 spawn
|
|
120
|
+
if (opts.signal?.aborted) {
|
|
121
|
+
return attemptHbcli(candidates[0]!, args, callOpts)
|
|
122
|
+
}
|
|
123
|
+
let last: HbcliCallResult & { spawnError?: boolean } | undefined
|
|
124
|
+
for (const bin of candidates) {
|
|
125
|
+
last = await attemptHbcli(bin, args, callOpts)
|
|
126
|
+
// spawn 级失败(ENOENT 等)且还有候选 → 换下一个已知安装位;其余失败(退码/超时/abort)无重试意义
|
|
127
|
+
if (!(last.spawnError && candidates.indexOf(bin) < candidates.length - 1)) return last
|
|
128
|
+
}
|
|
129
|
+
return last!
|
|
130
|
+
}
|
|
57
131
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
// 尝试 JSON 解析
|
|
92
|
-
const jStart = stdout.search(/[\{\[]/)
|
|
93
|
-
const jsonStr = jStart >= 0 ? stdout.slice(jStart) : ''
|
|
94
|
-
let result: unknown = null
|
|
95
|
-
if (jsonStr) {
|
|
96
|
-
try { result = JSON.parse(jsonStr) } catch { /* 非 JSON 输出,留给调用方处理 */ }
|
|
97
|
-
}
|
|
98
|
-
resolve({
|
|
99
|
-
via: 'hbcli-realtime', exitCode: 0, result,
|
|
100
|
-
evidence: `[实时API:hbcli@${new Date().toISOString()}]`,
|
|
101
|
-
stdout: stdout.slice(0, 2000), latencyMs,
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
child.on('error', (e) => {
|
|
105
|
-
if (settled) return
|
|
106
|
-
settled = true
|
|
107
|
-
clearTimeout(timer)
|
|
108
|
-
// ENOENT (二进制不存在) 等也走降级路径
|
|
109
|
-
resolve({
|
|
110
|
-
via: 'hbcli-error', exitCode: -1, result: null,
|
|
111
|
-
evidence: `[实时API:hbcli@spawn_error@${new Date().toISOString()}]`,
|
|
112
|
-
latencyMs: Date.now() - started, error: (e as Error).message,
|
|
113
|
-
})
|
|
114
|
-
})
|
|
115
|
-
})
|
|
132
|
+
/** 上游 i18n 名称容错读取(zh 优先,中文优先产品口径;回退 en/ar) */
|
|
133
|
+
function i18nName(v: { zh?: string; en?: string; ar?: string } | string | undefined): string {
|
|
134
|
+
if (!v) return ''
|
|
135
|
+
if (typeof v === 'string') return v
|
|
136
|
+
return v.zh || v.en || v.ar || ''
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 实时 hotelList 响应 → 模型可读紧凑行(id/名称/星级/最低价)。
|
|
141
|
+
* issue #195:render 面只透 summary,若 summary 不含数据,模型只看到
|
|
142
|
+
* 「实时返回」四个字——工具调用等于白调。id 必须在行内,hotel-rates 的入参
|
|
143
|
+
* 就来自这里。上游 wire:HotelListResp{list:[Hotel{id,name:{en,zh},star,minPrice:{amount,currency}}]}。
|
|
144
|
+
*/
|
|
145
|
+
function hotelLines(result: unknown, max = 8): string {
|
|
146
|
+
const list = (result as { list?: unknown } | null)?.list
|
|
147
|
+
if (!Array.isArray(list) || list.length === 0) return ''
|
|
148
|
+
const lines: string[] = []
|
|
149
|
+
for (const item of list.slice(0, max)) {
|
|
150
|
+
const h = item as {
|
|
151
|
+
id?: string | number
|
|
152
|
+
name?: { zh?: string; en?: string; ar?: string }
|
|
153
|
+
star?: number
|
|
154
|
+
minPrice?: { amount?: number; currency?: string }
|
|
155
|
+
}
|
|
156
|
+
const name = i18nName(h.name) || `hotel ${h.id ?? '?'}`
|
|
157
|
+
const star = typeof h.star === 'number' && h.star > 0 ? ` ${h.star}★` : ''
|
|
158
|
+
const price = h.minPrice && typeof h.minPrice.amount === 'number'
|
|
159
|
+
? ` 低至 ${h.minPrice.amount}${h.minPrice.currency ? ` ${h.minPrice.currency}` : ''}`
|
|
160
|
+
: ''
|
|
161
|
+
lines.push(`- id=${h.id ?? '?'} ${name}${star}${price}`)
|
|
162
|
+
}
|
|
163
|
+
if (list.length > max) lines.push(`…(共 ${list.length} 家,仅列前 ${max})`)
|
|
164
|
+
return lines.join('\n')
|
|
116
165
|
}
|
|
117
166
|
|
|
118
167
|
/** 高层语义化封装:酒店列表查询(down-tier to 静态包 + 证据链标注) */
|
|
@@ -120,29 +169,70 @@ export async function searchHotels(
|
|
|
120
169
|
query: { destination: string; checkIn?: string; checkOut?: string; adults?: number },
|
|
121
170
|
opts: HbcliCallOptions & { fallbackPath?: string } = {},
|
|
122
171
|
): Promise<HbcliCallResult & { hotels?: unknown; summary: string }> {
|
|
123
|
-
// 旗标对齐上游 CLI
|
|
124
|
-
// hotel-list
|
|
172
|
+
// 旗标对齐上游 CLI(hotelbyte-com/hotelbyte-cli):--destination-name + --room-occupancies;
|
|
173
|
+
// hotel-list 支持日期旗标(--check-in/--check-out,上游帮助文档在册)——issue #195 教训:
|
|
174
|
+
// 「日期不传上游」会让实时价退化为当前窗口价,用户要下周五的房给的是今天的价。
|
|
125
175
|
const hbArgs = ['search', 'hotel-list', '--json', '--page-size', '10']
|
|
126
176
|
if (query.destination) hbArgs.push('--destination-name', query.destination)
|
|
177
|
+
if (query.checkIn) hbArgs.push('--check-in', query.checkIn)
|
|
178
|
+
if (query.checkOut) hbArgs.push('--check-out', query.checkOut)
|
|
127
179
|
if (query.adults) hbArgs.push('--room-occupancies', JSON.stringify([{ adultCount: query.adults, childrenAges: [] }]))
|
|
128
180
|
const live = await callHbcliJson(hbArgs, opts)
|
|
181
|
+
// 取消立即结束:不读静态包、不产出命中/无结果/估算,也不计上游故障
|
|
182
|
+
if (opts.signal?.aborted || /abort/i.test(live.error ?? '')) {
|
|
183
|
+
const ts = new Date().toISOString()
|
|
184
|
+
const cleanupError = /cleanup incomplete/i.test(live.error ?? '') ? `; ${live.error}` : ''
|
|
185
|
+
return {
|
|
186
|
+
via: 'hbcli-error', exitCode: live.exitCode, result: null,
|
|
187
|
+
evidence: `[实时API:hbcli@abort@${ts}]`,
|
|
188
|
+
latencyMs: live.latencyMs, error: `aborted by host signal${cleanupError}`, summary: `酒店「${query.destination}」检索已取消,未产生事实`,
|
|
189
|
+
}
|
|
190
|
+
}
|
|
129
191
|
if (live.via === 'hbcli-realtime') {
|
|
130
|
-
|
|
192
|
+
// summary 即模型面(render 只透 summary):必须自带紧凑数据行 + 证据链,
|
|
193
|
+
// 否则模型只看到「实时返回」占位一句话(issue #195 实锤)。
|
|
194
|
+
const list = (live.result as { list?: unknown[] } | null)?.list
|
|
195
|
+
const n = Array.isArray(list) ? list.length : 0
|
|
196
|
+
const dateTag = query.checkIn
|
|
197
|
+
? `入住 ${query.checkIn}${query.checkOut ? ` → 退房 ${query.checkOut}` : ''}`
|
|
198
|
+
: '未传日期(上游按当前窗口价)'
|
|
199
|
+
const lines = hotelLines(live.result)
|
|
200
|
+
const summary = `${query.destination}:hbcli 实时 ${n} 家(${dateTag})${lines ? `\n${lines}` : ''}\n${live.evidence}`
|
|
201
|
+
return { ...live, hotels: live.result, summary }
|
|
131
202
|
}
|
|
132
|
-
//
|
|
203
|
+
// 降级原因人话化(issue #24):hbcli 未安装时按 gotry setup 指引(npm 安装期已
|
|
204
|
+
// 自动跑过官方脚本;PATH 未含 ~/.local/bin 时上方候选路径也已兜住),
|
|
205
|
+
// 裸 "spawn hbcli ENOENT" 读起来像工具坏了——实际静态包降级是设计行为
|
|
206
|
+
const rawReason = live.error ?? live.via
|
|
207
|
+
const reason = /ENOENT/i.test(rawReason) ? '未安装 hbcli(可选实时源;npx @danceiny/gotry setup 可按官方脚本安装)' : rawReason
|
|
208
|
+
// 降级:读静态包,按目的地过滤命中的住宿块(issue #24)——整包倾倒会把无关场景
|
|
209
|
+
// (深圳/普吉/曼谷/云南/大理混装)灌给模型且不指明哪块相关;包内无该目的地时明示
|
|
210
|
+
// 「无数据」而不是伪装成可用结果。
|
|
133
211
|
const fallback = opts.fallbackPath
|
|
134
212
|
if (fallback) {
|
|
135
213
|
try {
|
|
136
214
|
const { readFile } = await import('node:fs/promises')
|
|
137
|
-
const pack = JSON.parse(await readFile(fallback, 'utf-8')) as Record<string, unknown>
|
|
215
|
+
const pack = JSON.parse(await readFile(fallback, 'utf-8')) as { stays?: unknown[] } & Record<string, unknown>
|
|
216
|
+
const kw = query.destination.trim()
|
|
217
|
+
const stays = Array.isArray(pack.stays) ? pack.stays : []
|
|
218
|
+
const matched = kw ? stays.filter(s => JSON.stringify(s).includes(kw)) : stays
|
|
219
|
+
if (matched.length) {
|
|
220
|
+
return {
|
|
221
|
+
...live,
|
|
222
|
+
hotels: { stays: matched },
|
|
223
|
+
// summary 即模型面:静态块内容(note/options/recommendation)直接内联,
|
|
224
|
+
// 模型不必再猜「命中 N 块」里有什么(issue #195)
|
|
225
|
+
summary: `${query.destination}:hbcli 实时源不可用(${reason}),已降级到静态包(公开渠道估算,非实时),命中 ${matched.length} 个住宿块:\n${JSON.stringify(matched).slice(0, 1600)}`,
|
|
226
|
+
}
|
|
227
|
+
}
|
|
138
228
|
return {
|
|
139
229
|
...live,
|
|
140
|
-
hotels:
|
|
141
|
-
summary: `${query.destination}:hbcli
|
|
230
|
+
hotels: null,
|
|
231
|
+
summary: `${query.destination}:hbcli 实时源不可用(${reason}),且静态包无「${query.destination}」住宿数据(静态包仅覆盖内置场景)`,
|
|
142
232
|
}
|
|
143
233
|
} catch { /* 静态包读不到也优雅降级 */ }
|
|
144
234
|
}
|
|
145
|
-
return { ...live, summary: `${query.destination}:hbcli
|
|
235
|
+
return { ...live, summary: `${query.destination}:hbcli 实时源不可用(${reason})且无静态包(仅返回错误)` }
|
|
146
236
|
}
|
|
147
237
|
|
|
148
238
|
/** 高层语义化封装:目的地列表(无数据依赖,通常 hbcli dest 命令可独立调通) */
|
|
@@ -150,3 +240,95 @@ export async function listDestinations(opts: HbcliCallOptions = {}): Promise<Hbc
|
|
|
150
240
|
const r = await callHbcliJson(['search', 'destinations', '--json'], opts)
|
|
151
241
|
return { ...r, destinations: r.result }
|
|
152
242
|
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 高层语义化封装:房型报价(hotel-rates;上游 hotelRates 创建后端 session,
|
|
246
|
+
* 产出带 RatePkgId 的房型列表——check-avail 与 book 的入参来源)。
|
|
247
|
+
*
|
|
248
|
+
* 价格面无静态降级(fail-closed):hotel-list 的静态包降级是定性住宿信息,
|
|
249
|
+
* 房价是钱——估算价格冒充实时价是红线;不可用就诚实失败,证据链标注,
|
|
250
|
+
* 与 bookable-facts 证据分级(live_inventory 才可进确认卡)同口径。
|
|
251
|
+
*/
|
|
252
|
+
export async function hotelRates(
|
|
253
|
+
query: {
|
|
254
|
+
hotelId: string
|
|
255
|
+
checkIn?: string
|
|
256
|
+
checkOut?: string
|
|
257
|
+
adults?: number
|
|
258
|
+
countryCode?: string
|
|
259
|
+
nationalityCode?: string
|
|
260
|
+
residencyCode?: string
|
|
261
|
+
},
|
|
262
|
+
opts: HbcliCallOptions = {},
|
|
263
|
+
): Promise<HbcliCallResult & { rates?: unknown; summary: string }> {
|
|
264
|
+
const hbArgs = ['search', 'hotel-rates', '--json', '--hotel-id', query.hotelId]
|
|
265
|
+
if (query.checkIn) hbArgs.push('--check-in', query.checkIn)
|
|
266
|
+
if (query.checkOut) hbArgs.push('--check-out', query.checkOut)
|
|
267
|
+
if (query.countryCode) hbArgs.push('--country-code', query.countryCode)
|
|
268
|
+
if (query.nationalityCode) hbArgs.push('--nationality-code', query.nationalityCode)
|
|
269
|
+
if (query.residencyCode) hbArgs.push('--residency-code', query.residencyCode)
|
|
270
|
+
if (query.adults) hbArgs.push('--room-occupancies', JSON.stringify([{ adultCount: query.adults, childrenAges: [] }]))
|
|
271
|
+
const live = await callHbcliJson(hbArgs, opts)
|
|
272
|
+
const summary = live.via === 'hbcli-realtime'
|
|
273
|
+
? `hotel ${query.hotelId}:hbcli 实时报价${query.checkIn ? `(${query.checkIn} → ${query.checkOut ?? '?'})` : ''}`
|
|
274
|
+
: `hotel ${query.hotelId}:hbcli 实时报价不可用(${live.error ?? live.via});价格面无静态降级,fail-closed 不估算`
|
|
275
|
+
return { ...live, rates: live.result, summary }
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** 高层语义化封装:下单前实时验价(check-avail;入参 RatePkgId 来自 hotel-rates 产物)。价格面同上:不可用即诚实失败。 */
|
|
279
|
+
export async function checkAvail(
|
|
280
|
+
query: { ratePkgId: string },
|
|
281
|
+
opts: HbcliCallOptions = {},
|
|
282
|
+
): Promise<HbcliCallResult & { avail?: unknown; summary: string }> {
|
|
283
|
+
const live = await callHbcliJson(['search', 'check-avail', '--json', '--rate-pkg-id', query.ratePkgId], opts)
|
|
284
|
+
const summary = live.via === 'hbcli-realtime'
|
|
285
|
+
? `ratePkg ${query.ratePkgId}:hbcli 实时验价(库存与价格以后端为准)`
|
|
286
|
+
: `ratePkg ${query.ratePkgId}:hbcli 实时验价不可用(${live.error ?? live.via});价格面无静态降级,fail-closed`
|
|
287
|
+
return { ...live, avail: live.result, summary }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* C 端客户邮箱验证码登录(hotelbyte-cli auth customer-* 两步流;后端
|
|
292
|
+
* loginByCustomerEmailCode:验证通过即登录,新邮箱即注册,无需密码):
|
|
293
|
+
* step 1 customerSendCode —— 邮箱收码(外发邮件动作,仅用户明示要登录/注册时调用);
|
|
294
|
+
* step 2 customerLogin —— 用户从收件箱报码,验证即建档/登录。
|
|
295
|
+
*
|
|
296
|
+
* 与检索族的本质差异:customerLogin 写 hbcli 共享凭据仓(customer 档,
|
|
297
|
+
* ~/.staicli/credentials.json)——hbcli 侧 customer 档是最低优先级凭据(无
|
|
298
|
+
* portal/API-key 凭据时才生效),登录不劫持既有凭据。本层不透出 token 值
|
|
299
|
+
* (CLI 只回 token_saved,凭据留在 CLI 仓内,不进 gotry 会话/日志)。
|
|
300
|
+
* auth 命令族要求 hbcli 带 register 支持(npm 0.0.4 起;0.0.3 报 unknown
|
|
301
|
+
* command,经 hbcli-error 面优雅失败)。
|
|
302
|
+
*/
|
|
303
|
+
export async function customerSendCode(
|
|
304
|
+
email: string,
|
|
305
|
+
opts: HbcliCallOptions = {},
|
|
306
|
+
): Promise<HbcliCallResult & { summary: string }> {
|
|
307
|
+
const live = await callHbcliJson(['--json', 'auth', 'customer-send-code', '--email', email], opts)
|
|
308
|
+
const r = live.result as { expiresIn?: number; nextTime?: string } | null
|
|
309
|
+
const summary = live.via === 'hbcli-realtime'
|
|
310
|
+
? `验证码已发送到 ${email}${r?.expiresIn ? `(有效期 ${r.expiresIn} 秒)` : ''}——请让用户从邮箱查收并报码,再走 gotry_hotel_auth_login`
|
|
311
|
+
: `验证码发送失败(${live.error ?? live.via});服务端有发码限流,勿立即重试`
|
|
312
|
+
return { ...live, summary }
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export async function customerLogin(
|
|
316
|
+
query: { email: string; code: string; ttl?: number; attributionToken?: string },
|
|
317
|
+
opts: HbcliCallOptions = {},
|
|
318
|
+
): Promise<HbcliCallResult & { summary: string }> {
|
|
319
|
+
const hbArgs = ['--json', 'auth', 'customer-login', '--email', query.email, '--code', query.code]
|
|
320
|
+
if (query.ttl && query.ttl > 0) hbArgs.push('--ttl', String(query.ttl))
|
|
321
|
+
if (query.attributionToken) hbArgs.push('--attribution-token', query.attributionToken)
|
|
322
|
+
const live = await callHbcliJson(hbArgs, opts)
|
|
323
|
+
const r = live.result as { status?: string; attributionBound?: boolean } | null
|
|
324
|
+
let summary: string
|
|
325
|
+
if (live.via === 'hbcli-realtime' && r?.status === 'logged_in') {
|
|
326
|
+
const attribution = typeof r.attributionBound === 'boolean'
|
|
327
|
+
? `;顾问归因绑定${r.attributionBound ? '成功' : '未成(登录不受影响,归因可重试)'}`
|
|
328
|
+
: ''
|
|
329
|
+
summary = `hotelbyte 客户登录成功(${query.email};新邮箱即注册${attribution})——凭据已存入 hbcli customer 档,后续酒店检索/报价走实时源`
|
|
330
|
+
} else {
|
|
331
|
+
summary = `hotelbyte 客户登录失败(${live.error ?? live.via});验证码是一次性凭据,失败后需重新发码`
|
|
332
|
+
}
|
|
333
|
+
return { ...live, summary }
|
|
334
|
+
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 进程级事故日志(D-NEW
|
|
2
|
+
* 进程级事故日志(D-NEW):同步、durable 的 JSONL 诊断记录。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 设计: 进程级 handler 同步写盘(fsync),尽量在进程被杀前留下事故证据。
|
|
9
|
-
* handler 自身不再抛——再次抛出会绕过 handler,变成无声死亡。
|
|
4
|
+
* `uncaughtExceptionMonitor` 只观察 fatal 事故并留下证据;宿主仍决定
|
|
5
|
+
* 是否退出。GoTry 不吞掉 fatal 事件、不调用 process.exit、也不隐式重启。
|
|
6
|
+
* 工具 execute 的业务失败仍由 guardToolExecute 转成结构化失败返回。
|
|
10
7
|
*
|
|
11
8
|
* §11 状态面同步:事故日志是 gotry-state/incidents.jsonl,
|
|
12
|
-
*
|
|
9
|
+
* 用户可见、可清理。
|
|
13
10
|
*/
|
|
14
11
|
|
|
15
|
-
import {
|
|
12
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, writeFileSync } from 'node:fs'
|
|
16
13
|
import { dirname, isAbsolute, join } from 'node:path'
|
|
17
|
-
import {
|
|
14
|
+
import { pathToFileURL } from 'node:url'
|
|
18
15
|
import type { ToolFailure } from '../src/tool-packet.ts'
|
|
19
16
|
|
|
20
17
|
export type IncidentKind = 'uncaughtException' | 'unhandledRejection' | 'plugin_error' | 'tool_execute_error'
|
|
@@ -43,68 +40,104 @@ function ensureDir(path: string): void {
|
|
|
43
40
|
|
|
44
41
|
let installed = false
|
|
45
42
|
let logPath: string | null = null
|
|
43
|
+
let activeMonitor: ((err: Error, origin: NodeJS.UncaughtExceptionOrigin) => void) | null = null
|
|
44
|
+
|
|
45
|
+
function safeErrorMessage(value: unknown): string {
|
|
46
|
+
try {
|
|
47
|
+
if (value instanceof Error) return typeof value.message === 'string' ? value.message : '[error-without-message]'
|
|
48
|
+
if (typeof value === 'string') return value
|
|
49
|
+
if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint' || typeof value === 'symbol') return String(value)
|
|
50
|
+
const json = JSON.stringify(value)
|
|
51
|
+
return typeof json === 'string' ? json : '[unprintable-error]'
|
|
52
|
+
} catch {
|
|
53
|
+
return '[unprintable-error]'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function safeErrorStack(value: unknown): string {
|
|
58
|
+
try {
|
|
59
|
+
const stack = (value as { stack?: unknown } | null | undefined)?.stack
|
|
60
|
+
return typeof stack === 'string' ? stack : ''
|
|
61
|
+
} catch {
|
|
62
|
+
return ''
|
|
63
|
+
}
|
|
64
|
+
}
|
|
46
65
|
|
|
47
66
|
/**
|
|
48
|
-
* 写入一条事故并 fsync
|
|
49
|
-
*
|
|
67
|
+
* 写入一条事故并 fsync。整个 append 使用同一个 fd,并保证所有失败路径
|
|
68
|
+
* 都尝试 close;返回 true 只表示写入、fsync、close 全部成功。
|
|
50
69
|
*/
|
|
51
70
|
export function recordIncident(inc: Incident, stateRoot?: string): boolean {
|
|
52
71
|
const target = stateRoot ? resolveIncidentsPath(stateRoot) : (logPath ?? resolveIncidentsPath('.'))
|
|
72
|
+
let fd: number | undefined
|
|
73
|
+
let closeAttempted = false
|
|
53
74
|
try {
|
|
54
75
|
ensureDir(target)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
fd = openSync(target, 'a')
|
|
77
|
+
writeFileSync(fd, JSON.stringify(inc) + '\n', { encoding: 'utf8' })
|
|
78
|
+
fsyncSync(fd)
|
|
79
|
+
closeAttempted = true
|
|
80
|
+
closeSync(fd)
|
|
81
|
+
fd = undefined
|
|
60
82
|
return true
|
|
61
83
|
} catch {
|
|
62
|
-
//
|
|
84
|
+
// 事故处理中的诊断失败绝不能再次抛出。
|
|
63
85
|
return false
|
|
86
|
+
} finally {
|
|
87
|
+
if (fd !== undefined && !closeAttempted) {
|
|
88
|
+
closeAttempted = true
|
|
89
|
+
try { closeSync(fd) } catch { /* best effort close on a failed write */ }
|
|
90
|
+
}
|
|
64
91
|
}
|
|
65
92
|
}
|
|
66
93
|
|
|
67
94
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* @returns 一个 disposer,卸载所有监听(测试场景使用)
|
|
95
|
+
* 安装进程级事故观察器。只挂 monitor,不改变 Node/dsh 的 fatal 行为。
|
|
96
|
+
* 进程整个生命周期仅生效一次;disposer 供宿主卸载和测试使用。
|
|
72
97
|
*/
|
|
73
98
|
export function installProcessGuards(stateRoot: string, labels?: { uncaughtException?: string; unhandledRejection?: string }): () => void {
|
|
74
99
|
if (installed) return () => { /* 已装,no-op */ }
|
|
75
100
|
installed = true
|
|
76
101
|
logPath = resolveIncidentsPath(stateRoot)
|
|
77
102
|
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
kind
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
const monitor = (err: Error, origin: NodeJS.UncaughtExceptionOrigin) => {
|
|
104
|
+
try {
|
|
105
|
+
const kind: IncidentKind = origin === 'unhandledRejection' ? 'unhandledRejection' : 'uncaughtException'
|
|
106
|
+
const source = kind === 'unhandledRejection'
|
|
107
|
+
? (labels?.unhandledRejection ?? 'promise')
|
|
108
|
+
: (labels?.uncaughtException ?? origin)
|
|
109
|
+
recordIncident({
|
|
110
|
+
ts: new Date().toISOString(),
|
|
111
|
+
kind,
|
|
112
|
+
message: safeErrorMessage(err).slice(0, 2000),
|
|
113
|
+
stack: safeErrorStack(err).slice(0, 4000),
|
|
114
|
+
source,
|
|
115
|
+
}, stateRoot)
|
|
116
|
+
} catch {
|
|
117
|
+
// Formatting must never replace the original fatal event. Keep a final
|
|
118
|
+
// plain fallback attempt for diagnostics, while the host retains control.
|
|
119
|
+
try {
|
|
120
|
+
recordIncident({
|
|
121
|
+
ts: new Date().toISOString(),
|
|
122
|
+
kind: origin === 'unhandledRejection' ? 'unhandledRejection' : 'uncaughtException',
|
|
123
|
+
message: '[incident-observer-fallback]',
|
|
124
|
+
source: 'incident-observer',
|
|
125
|
+
}, stateRoot)
|
|
126
|
+
} catch { /* observer is strictly best effort */ }
|
|
127
|
+
}
|
|
100
128
|
}
|
|
101
129
|
|
|
102
|
-
process.on('
|
|
103
|
-
|
|
130
|
+
process.on('uncaughtExceptionMonitor', monitor)
|
|
131
|
+
activeMonitor = monitor
|
|
132
|
+
let active = true
|
|
104
133
|
return () => {
|
|
105
|
-
|
|
106
|
-
|
|
134
|
+
if (!active) return
|
|
135
|
+
active = false
|
|
136
|
+
if (activeMonitor !== monitor) return
|
|
137
|
+
process.off('uncaughtExceptionMonitor', monitor)
|
|
107
138
|
installed = false
|
|
139
|
+
logPath = null
|
|
140
|
+
activeMonitor = null
|
|
108
141
|
}
|
|
109
142
|
}
|
|
110
143
|
|
|
@@ -112,24 +145,23 @@ export function installProcessGuards(stateRoot: string, labels?: { uncaughtExcep
|
|
|
112
145
|
* 工具执行面异常隔离(D-NEW gotry 侧收尾):dsh 的一个工具 execute 抛错/拒绝
|
|
113
146
|
* 会沿 cordis 传到主循环,拖垮整个会话。包装后:降级为结构化错误返回给 LLM、
|
|
114
147
|
* 事故落盘,永不向上抛。落盘失败也不抛(双保险,仍返回结构化错误)。
|
|
115
|
-
* 失败形状 = ToolFailure(RFC S1 observation envelope 的失败分支,编译期对齐)。
|
|
116
148
|
*/
|
|
117
149
|
export function guardToolExecute<A, R>(name: string, stateRoot: string, execute: (args: A, exec: unknown) => R | Promise<R>): (args: A, exec: unknown) => Promise<R> {
|
|
118
150
|
return async (args: A, exec: unknown): Promise<R> => {
|
|
119
151
|
try {
|
|
120
152
|
return await execute(args, exec)
|
|
121
153
|
} catch (e) {
|
|
122
|
-
const
|
|
154
|
+
const message = safeErrorMessage(e)
|
|
123
155
|
recordIncident({
|
|
124
156
|
ts: new Date().toISOString(),
|
|
125
157
|
kind: 'tool_execute_error',
|
|
126
|
-
message: `${name}: ${
|
|
127
|
-
stack: (
|
|
158
|
+
message: `${name}: ${message}`.slice(0, 2000),
|
|
159
|
+
stack: safeErrorStack(e).slice(0, 4000),
|
|
128
160
|
source: name,
|
|
129
161
|
}, stateRoot)
|
|
130
162
|
const failure: ToolFailure = {
|
|
131
163
|
ok: false,
|
|
132
|
-
summary: `gotry_${name} 内部错误(已隔离,会话继续): ${
|
|
164
|
+
summary: `gotry_${name} 内部错误(已隔离,会话继续): ${message.slice(0, 300)}`,
|
|
133
165
|
evidence: `[incident:tool_execute_error@${new Date().toISOString()}]`,
|
|
134
166
|
}
|
|
135
167
|
return failure as R
|
|
@@ -137,12 +169,9 @@ export function guardToolExecute<A, R>(name: string, stateRoot: string, execute:
|
|
|
137
169
|
}
|
|
138
170
|
}
|
|
139
171
|
|
|
140
|
-
/** CLI
|
|
141
|
-
if (
|
|
172
|
+
/** CLI 调试:最小 fatal 子进程会留下事故证据并按 Node 原生语义非零退出。 */
|
|
173
|
+
if (process.argv[1] !== undefined && pathToFileURL(process.argv[1]).href === import.meta.url && process.argv[2] === '--smoke') {
|
|
142
174
|
const stateRoot = process.argv[3] ?? '.'
|
|
143
175
|
installProcessGuards(stateRoot, { uncaughtException: 'smoke', unhandledRejection: 'smoke' })
|
|
144
|
-
|
|
145
|
-
// 触发一次未捕获,应被写盘(不真正杀进程——进程继续跑完)
|
|
146
|
-
setTimeout(() => Promise.reject(new Error('intentional smoke-rejection')), 50)
|
|
147
|
-
setTimeout(() => { console.log('SMOKE OK'); process.exit(0) }, 500)
|
|
176
|
+
setTimeout(() => { throw new Error('intentional smoke-uncaught') }, 50)
|
|
148
177
|
}
|