@danceiny/gotry 0.0.1-rc.9 → 0.2.0-rc.28
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 -219
- 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 +1788 -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 -56
- 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 +161 -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 +553 -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 +947 -110
- package/dist/capabilities/fx-contract.js +293 -0
- package/dist/capabilities/geo-atlas.js +246 -0
- package/dist/capabilities/ground-transfer.js +676 -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/provider-detail-sanitize.js +64 -0
- package/dist/capabilities/resilience.js +191 -0
- package/dist/capabilities/route-provider-conformance.js +341 -0
- package/dist/capabilities/session/action-cache.js +50 -44
- package/dist/capabilities/session/adapters/ctrip-flight.js +120 -62
- 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 +35 -54
- 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 +31 -21
- 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 +75 -24
- package/dist/capabilities/session/static-flight-golden.js +150 -0
- package/dist/capabilities/session/transport.js +97 -83
- 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 +635 -44
- 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 +24 -59
- 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-path-measure-tests.js +133 -0
- package/dist/scripts/anything-path-measure.js +150 -0
- package/dist/scripts/anything-tests.js +250 -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 +50 -11
- 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 +126 -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 +1549 -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/city-scenario-tier-tests.js +234 -0
- package/dist/scripts/companion-tests.js +25 -70
- 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 +600 -0
- package/dist/scripts/drill-multiuser-ledger-tests.js +1076 -0
- package/dist/scripts/drill-sdk-descendant-cleanup-tests.js +606 -0
- package/dist/scripts/drill-w2a-sensor-tests.js +788 -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-llm-tests.js +437 -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 +150 -0
- package/dist/scripts/g5-guard.js +193 -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 +382 -246
- package/dist/scripts/ledger-workflow-crash.js +10 -20
- package/dist/scripts/m3-cohort-tests.js +714 -0
- package/dist/scripts/m3-cohort.js +310 -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 +18 -52
- package/dist/scripts/memory-lifecycle-tests.js +657 -0
- package/dist/scripts/memory-lifecycle.js +196 -0
- package/dist/scripts/memory-metrics.js +24 -12
- 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 +203 -0
- package/dist/scripts/nightly-evidence.js +303 -0
- package/dist/scripts/nudge-digest.js +39 -28
- 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/outcome-projection-tests.js +427 -0
- package/dist/scripts/persona-sim-tests.js +603 -0
- package/dist/scripts/persona-sim.js +1081 -0
- 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 +22 -18
- package/dist/scripts/replay-real.js +18 -18
- package/dist/scripts/replay.js +54 -82
- package/dist/scripts/route-provider-conformance-tests.js +391 -0
- package/dist/scripts/session-attach-diagnose.js +20 -20
- package/dist/scripts/session-attach-poc.js +34 -37
- 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 +14 -35
- package/dist/scripts/session-link-tests.js +478 -0
- package/dist/scripts/session-login.js +27 -46
- package/dist/scripts/session-tests.js +796 -96
- package/dist/scripts/session-zone-crash.js +49 -0
- package/dist/scripts/session-zone-ledger-tests.js +432 -0
- package/dist/scripts/session-zone-observation-tests.js +492 -0
- package/dist/scripts/session-zone-observe.js +135 -0
- package/dist/scripts/session-zone-wiring-tests.js +566 -0
- package/dist/scripts/session-zones-tests.js +374 -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 +690 -246
- package/dist/scripts/spawn-bounded-abort-tests.js +244 -0
- package/dist/scripts/sponsor-reuse-tests.js +262 -0
- package/dist/scripts/state-cli-tests.js +226 -101
- package/dist/scripts/state-cli.js +565 -198
- 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 +212 -192
- package/dist/scripts/travel-timeline-tests.js +29 -93
- 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 +60 -20
- 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 +46 -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/city-scenario-tier.js +378 -0
- package/dist/src/companions.js +48 -74
- package/dist/src/contracts.js +21 -43
- package/dist/src/dsh-llm.js +171 -115
- 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 +2385 -881
- 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 +331 -161
- package/dist/src/m3-cohort.js +1577 -0
- package/dist/src/memory-capture.js +180 -32
- package/dist/src/memory-decay.js +30 -14
- 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/outcome-projection.js +746 -0
- 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-zone-ledger.js +312 -0
- package/dist/src/session-zone-observation.js +354 -0
- package/dist/src/session-zone-wiring.js +658 -0
- package/dist/src/session-zones.js +510 -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 +696 -524
- 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 +44 -63
- 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 +600 -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 +282 -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 +293 -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 +586 -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 +17 -3
- package/ts/src/dsh-llm.ts +152 -17
- package/ts/src/flyai-setup-tool.ts +77 -0
- package/ts/src/index.ts +2123 -200
- 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 +234 -26
- 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 +1166 -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 +444 -105
- package/ts/src/wish-pool.ts +79 -0
- package/dist/scripts/session-attach-wait.js +0 -41
package/dist/src/loop.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 1 对话循环(S2 段1,docs/design/stage1-top-down-design.md §2.3)。
|
|
3
|
+
*
|
|
4
|
+
* 自顶向下:循环只依赖两个端口——LlmPort(mock/真)与确定性工具(interview_next)。
|
|
5
|
+
* 求解/渲染接线是 S2 后续段;本段验收:重放用户开场白,系统一轮内完成
|
|
6
|
+
* 日历断言 + 访谈补全启动(问出工作窗口与已订资源——Kimi 第 6 轮才问的事)。
|
|
7
|
+
*/
|
|
8
|
+
import { buildTimeAnchor, isRealIsoDate, planningWindowBounds, parsePlanningWindow } from './time-anchor.js';
|
|
1
9
|
import { anythingSearch } from '../capabilities/anything.js';
|
|
2
10
|
export function newState(year = 2026) {
|
|
3
11
|
return {
|
|
4
|
-
calendar: {
|
|
5
|
-
year,
|
|
6
|
-
assertedWeekdays: {}
|
|
7
|
-
},
|
|
12
|
+
calendar: { year, assertedWeekdays: {} },
|
|
8
13
|
profile: {},
|
|
9
14
|
gates: [],
|
|
10
|
-
wishes: []
|
|
15
|
+
wishes: [],
|
|
11
16
|
};
|
|
12
17
|
}
|
|
18
|
+
/** ADR-9:访谈由缺失字段驱动(确定性,无 LLM 即兴) */
|
|
13
19
|
export function interviewNext(state) {
|
|
14
20
|
const p = state.profile;
|
|
15
21
|
const questions = [];
|
|
@@ -18,14 +24,14 @@ export function interviewNext(state) {
|
|
|
18
24
|
questions.push({
|
|
19
25
|
key: 'workWindow',
|
|
20
26
|
text: '你这两周要远程办公——工作时间是几点到几点、按哪个时区?这决定每天的可玩时段。',
|
|
21
|
-
why: '工作窗口直接决定每日节奏(普吉 13:00-22:00 与 9:00-18:00 是两种人生)'
|
|
27
|
+
why: '工作窗口直接决定每日节奏(普吉 13:00-22:00 与 9:00-18:00 是两种人生)',
|
|
22
28
|
});
|
|
23
29
|
}
|
|
24
30
|
if (!p.bookedResources) {
|
|
25
31
|
questions.push({
|
|
26
32
|
key: 'bookedResources',
|
|
27
33
|
text: '已经有订好的航班或酒店吗?(哪怕只是意向)——已订资源是硬锚点,先告诉我再规划。',
|
|
28
|
-
why: '已订资源决定哪些段不可动,Kimi 式规划会绕开它们重排'
|
|
34
|
+
why: '已订资源决定哪些段不可动,Kimi 式规划会绕开它们重排',
|
|
29
35
|
});
|
|
30
36
|
}
|
|
31
37
|
if (!p.budgetTier) {
|
|
@@ -34,35 +40,28 @@ export function interviewNext(state) {
|
|
|
34
40
|
text: '预算档位:经济(¥12.6k 级)/ 舒适(¥16.3k 级)/ 便利优先?',
|
|
35
41
|
why: '分层预算决定班次与住宿的选型口径',
|
|
36
42
|
options: [
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
label: '舒适',
|
|
43
|
-
tradeOff: 'workation 办公质量优先'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
label: '便利优先',
|
|
47
|
-
tradeOff: '时间最省'
|
|
48
|
-
}
|
|
49
|
-
]
|
|
43
|
+
{ label: '经济', tradeOff: '省钱,接驳多走路' },
|
|
44
|
+
{ label: '舒适', tradeOff: 'workation 办公质量优先' },
|
|
45
|
+
{ label: '便利优先', tradeOff: '时间最省' },
|
|
46
|
+
],
|
|
50
47
|
});
|
|
51
48
|
}
|
|
52
|
-
return {
|
|
53
|
-
questions,
|
|
54
|
-
missing: questions.map((q)=>q.key)
|
|
55
|
-
};
|
|
49
|
+
return { questions, missing: questions.map(q => q.key) };
|
|
56
50
|
}
|
|
51
|
+
/** spec 校验闸:LLM 翻译产物进求解器前的确定性形状检查(责任边界的执行点)。 */
|
|
57
52
|
export function validateSpec(spec) {
|
|
58
|
-
if (!Array.isArray(spec.segments) || spec.segments.length === 0)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (!
|
|
62
|
-
|
|
53
|
+
if (!Array.isArray(spec.segments) || spec.segments.length === 0)
|
|
54
|
+
return '没有段(segments)';
|
|
55
|
+
for (const seg of spec.segments) {
|
|
56
|
+
if (!seg.id)
|
|
57
|
+
return '存在缺少 id 的段';
|
|
58
|
+
if (!Array.isArray(seg.options) || seg.options.length === 0)
|
|
59
|
+
return `段 ${seg.id} 没有可选方案`;
|
|
60
|
+
for (const opt of seg.options) {
|
|
63
61
|
const svcs = opt.move?.services;
|
|
64
|
-
if (!Array.isArray(svcs) || svcs.length === 0)
|
|
65
|
-
|
|
62
|
+
if (!Array.isArray(svcs) || svcs.length === 0)
|
|
63
|
+
return `段 ${seg.id} 的方案 ${opt.id} 缺少班次(services)`;
|
|
64
|
+
for (const s of svcs) {
|
|
66
65
|
if (typeof s.depMin !== 'number' || typeof s.arrMin !== 'number') {
|
|
67
66
|
return `段 ${seg.id}/${opt.id} 的班次 ${s.id ?? '?'} 缺少时刻(depMin/arrMin)`;
|
|
68
67
|
}
|
|
@@ -71,7 +70,113 @@ export function validateSpec(spec) {
|
|
|
71
70
|
}
|
|
72
71
|
return null;
|
|
73
72
|
}
|
|
73
|
+
function isoDateInBounds(date, bounds) {
|
|
74
|
+
const m = date.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
75
|
+
if (!m || !isRealIsoDate(Number(m[1]), Number(m[2]), Number(m[3])))
|
|
76
|
+
return false;
|
|
77
|
+
return date >= bounds.start && date <= bounds.end;
|
|
78
|
+
}
|
|
79
|
+
function hasDatedCandidates(spec) {
|
|
80
|
+
return spec.segments.some(segment => segment.date !== undefined || segment.options.some(option => option.date !== undefined));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Enforce a named-year future window at the planner boundary. Historical
|
|
84
|
+
* lookup/backtesting remains an explicit bypass; an expired named year fails
|
|
85
|
+
* instead of being silently rolled into a different year.
|
|
86
|
+
*/
|
|
87
|
+
export function applyPlanningWindow(spec, window, anchor, options = {}) {
|
|
88
|
+
// Dated recommendations are future-oriented even without optional named-year context.
|
|
89
|
+
// Fully dateless legacy calculations remain untouched; historical bypass is explicit.
|
|
90
|
+
if (window?.intent === 'historical')
|
|
91
|
+
return { spec, rejected: [] };
|
|
92
|
+
const implicitFutureFloor = !window && options.defaultDatedFuture === true && hasDatedCandidates(spec);
|
|
93
|
+
if (!window && !implicitFutureFloor)
|
|
94
|
+
return { spec, rejected: [] };
|
|
95
|
+
const currentYear = Number(anchor.today.slice(0, 4));
|
|
96
|
+
if (window && window.requestedYear < currentYear) {
|
|
97
|
+
return {
|
|
98
|
+
spec,
|
|
99
|
+
rejected: [],
|
|
100
|
+
error: `${window.requestedYear} 年已结束(当前规划参考日 ${anchor.today}),不会自动改用其他年份;如需历史查询请明确说明“历史/回测”。`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const bounds = window
|
|
104
|
+
? planningWindowBounds(window, anchor)
|
|
105
|
+
: { start: anchor.today, end: '9999-12-31' };
|
|
106
|
+
if (!bounds)
|
|
107
|
+
return { spec, rejected: [], error: `无法建立 ${window.requestedYear} 年的未来规划窗口。` };
|
|
108
|
+
const rejected = [];
|
|
109
|
+
const guardedSegments = spec.segments.map(segment => ({
|
|
110
|
+
...segment,
|
|
111
|
+
options: segment.options.filter(option => {
|
|
112
|
+
const date = option.date ?? segment.date;
|
|
113
|
+
if (date && isoDateInBounds(date, bounds))
|
|
114
|
+
return true;
|
|
115
|
+
rejected.push({ segmentId: segment.id, optionId: option.id, date: date ?? '未提供明确日期' });
|
|
116
|
+
return false;
|
|
117
|
+
}),
|
|
118
|
+
}));
|
|
119
|
+
if (guardedSegments.some(segment => segment.options.length === 0)) {
|
|
120
|
+
return {
|
|
121
|
+
spec: { ...spec, segments: guardedSegments },
|
|
122
|
+
rejected,
|
|
123
|
+
error: implicitFutureFloor
|
|
124
|
+
? `带日期的未来推荐必须不早于当前规划参考日 ${bounds.start};没有带明确日期且在未来窗口内的可接受方案。`
|
|
125
|
+
: `${window.requestedYear} 年未来规划窗口为 ${bounds.start} 至 ${bounds.end};没有带明确日期且落在窗口内的可接受方案。`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return { spec: { ...spec, segments: guardedSegments }, rejected };
|
|
129
|
+
}
|
|
130
|
+
function latestPlanningWindow(history, userMsg, anchor) {
|
|
131
|
+
const turns = [...history, { role: 'user', text: userMsg }];
|
|
132
|
+
for (let i = turns.length - 1; i >= 0; i--) {
|
|
133
|
+
const turn = turns[i];
|
|
134
|
+
if (turn?.role !== 'user')
|
|
135
|
+
continue;
|
|
136
|
+
const parsed = parsePlanningWindow(turn.text, anchor);
|
|
137
|
+
if (parsed)
|
|
138
|
+
return parsed;
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
export const ASYNC_TERMINAL_SCHEMA = 'gotry_async_terminal.v1';
|
|
143
|
+
function asyncTerminalOutcome(ticketId, checks) {
|
|
144
|
+
const failedChecks = Object.entries(checks).filter(([, passed]) => !passed).map(([name]) => name);
|
|
145
|
+
return {
|
|
146
|
+
schema: ASYNC_TERMINAL_SCHEMA,
|
|
147
|
+
ticket_id: ticketId,
|
|
148
|
+
status: failedChecks.length === 0 ? 'succeeded' : 'failed',
|
|
149
|
+
passed: Object.values(checks).filter(Boolean).length,
|
|
150
|
+
total: 4,
|
|
151
|
+
checks,
|
|
152
|
+
failed_checks: failedChecks,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function terminalOutcomeFromState(ticketId, state) {
|
|
156
|
+
if (!state.spec || !state.solve) {
|
|
157
|
+
return asyncTerminalOutcome(ticketId, {
|
|
158
|
+
'1_承诺时间后必有明确产物': false,
|
|
159
|
+
'2_产物通过自检清单': false,
|
|
160
|
+
'3_待决问题全部是简单选择题': false,
|
|
161
|
+
'4_做不到的诚实说': false,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
// issue #620:求解器自身失败时既没有产物也没有判定——2 条不成立;但「做不到诚实说」
|
|
165
|
+
// 恰恰成立(我们明说了是引擎故障而非不可行),不靠 unsat_core 冒充自检通过。
|
|
166
|
+
const solverFailed = Boolean(state.solve.solver_error);
|
|
167
|
+
return asyncTerminalOutcome(ticketId, {
|
|
168
|
+
'1_承诺时间后必有明确产物': Boolean(state.solve.legs?.length || state.solve.verdicts?.length),
|
|
169
|
+
'2_产物通过自检清单': solverFailed
|
|
170
|
+
? false
|
|
171
|
+
: state.solve.feasible
|
|
172
|
+
? (state.solve.legs?.every(l => l['energy_pct'] !== undefined) ?? false)
|
|
173
|
+
: Boolean(state.solve.unsat_core?.length),
|
|
174
|
+
'3_待决问题全部是简单选择题': state.gates.every(g => g.id === 'budget' || g.options.length >= 2),
|
|
175
|
+
'4_做不到的诚实说': solverFailed || state.solve.feasible || Boolean(state.solve.suggestions?.length),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
74
178
|
export function isComplex(state) {
|
|
179
|
+
/** 复杂度判据(架构占位,后续可细化):多段或多约束即深规划 */
|
|
75
180
|
const p = state.profile;
|
|
76
181
|
return Boolean(p.workWindow && p.bookedResources) && (state.gates.length > 0 || Boolean(state.spec));
|
|
77
182
|
}
|
|
@@ -80,135 +185,155 @@ export async function requestDeepPlanning(state) {
|
|
|
80
185
|
id: `dp-${Date.now().toString(36)}`,
|
|
81
186
|
objective: '生成已验证的行程方案:全成本核算 + 动机/约束匹配 + 不失望四条',
|
|
82
187
|
requestedAt: new Date().toISOString(),
|
|
83
|
-
etaLabel: '约 1 小时(mock 期:秒级)'
|
|
84
|
-
};
|
|
85
|
-
state.gates.push({
|
|
86
|
-
id: `async-${ticket.id}`,
|
|
87
|
-
question: `深度规划已启动(${ticket.etaLabel})`,
|
|
88
|
-
options: []
|
|
89
|
-
});
|
|
90
|
-
const reply = '这趟行程跨度大(两周 workation + 三城 + 红眼返程),我切到**深度规划模式**:后台做多轮校验' + '(锚点/工作窗口/全成本/负例排查),做好后通知你。**先留一道选择题给你**,回来直接定:' + '\n1. 预算档位?(经济/舒适/便利优先)';
|
|
91
|
-
return {
|
|
92
|
-
reply,
|
|
93
|
-
ticket
|
|
188
|
+
etaLabel: '约 1 小时(mock 期:秒级)',
|
|
94
189
|
};
|
|
190
|
+
state.gates.push({ id: `async-${ticket.id}`, question: `深度规划已启动(${ticket.etaLabel})`, options: [] });
|
|
191
|
+
const reply = '这趟行程跨度大(两周 workation + 三城 + 红眼返程),我切到**深度规划模式**:后台做多轮校验'
|
|
192
|
+
+ '(锚点/工作窗口/全成本/负例排查),做好后通知你。**先留一道选择题给你**,回来直接定:'
|
|
193
|
+
+ '\n1. 预算档位?(经济/舒适/便利优先)';
|
|
194
|
+
return { reply, ticket };
|
|
95
195
|
}
|
|
96
196
|
export async function collectDeepPlanning(state, ticket, solve) {
|
|
97
197
|
const spec = state.spec;
|
|
98
|
-
if (!spec)
|
|
99
|
-
|
|
100
|
-
state
|
|
101
|
-
}
|
|
198
|
+
if (!spec) {
|
|
199
|
+
const outcome = terminalOutcomeFromState(ticket.id, state);
|
|
200
|
+
return { reply: '(内部状态缺失 spec——深度规划未就绪,这是不应发生的路径)', state, outcome };
|
|
201
|
+
}
|
|
102
202
|
state.solve = await solve(spec);
|
|
103
|
-
state.gates = state.gates.filter(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
'4_做不到的诚实说': state.solve.feasible || Boolean(state.solve.suggestions?.length)
|
|
109
|
-
};
|
|
110
|
-
const head = `# 回访交付:${ticket.objective}\n(工单 ${ticket.id},不失望四条:${Object.values(checks).every(Boolean) ? '4/4 ✅' : '有未达项 ❌'})`;
|
|
111
|
-
return {
|
|
112
|
-
reply: `${head}\n\n${renderSolve(state)}`,
|
|
113
|
-
state
|
|
114
|
-
};
|
|
203
|
+
state.gates = state.gates.filter(g => !g.id.startsWith('async-'));
|
|
204
|
+
// 不失望四条自检(交付物自带,总纲 3.6)
|
|
205
|
+
const outcome = terminalOutcomeFromState(ticket.id, state);
|
|
206
|
+
const head = `# 回访交付:${ticket.objective}\n(工单 ${ticket.id},不失望四条:${outcome.status === 'succeeded' ? '4/4 ✅' : '有未达项 ❌'})`;
|
|
207
|
+
return { reply: `${head}\n\n${renderSolve(state)}`, state, outcome };
|
|
115
208
|
}
|
|
209
|
+
/** 求解结果 → 人话(模板;S4 可由 LLM 润色,数字与判定不可改) */
|
|
116
210
|
export function renderSolve(state) {
|
|
117
211
|
const s = state.solve;
|
|
118
|
-
if (!s)
|
|
212
|
+
if (!s)
|
|
213
|
+
return '(无求解结果)';
|
|
119
214
|
const lines = [];
|
|
120
|
-
if (s.
|
|
215
|
+
if (s.solver_error) {
|
|
216
|
+
// issue #620:求解器自己失败 ≠ 行程不可行。这里**不**说「不可行」、不列「冲突」,
|
|
217
|
+
// 也不把机器 token(solver_error.code)渲染给用户——它只在日志/证据里。
|
|
218
|
+
lines.push('**这轮没算出结论——求解器自身出错了,不是你的行程不可行**');
|
|
219
|
+
lines.push('- 我不把引擎故障说成「不可行」:这条已记录,修好或换候选形态(枚举)后重算');
|
|
220
|
+
}
|
|
221
|
+
else if (s.feasible) {
|
|
121
222
|
lines.push(`**方案可行,机票合计 ¥${s.money_cny}**`);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
223
|
+
// §7-1 issue #559 卡点 4:从 s.skeleton_notes 字符串编码里推断 unscaffolded 的 seg.id,
|
|
224
|
+
// 不动 unified.ts/journey.ts(内核冻结面 #234),用户面给 ⚠ 前缀与「枢纽对未在骨架覆盖」补充。
|
|
225
|
+
// skeleton_notes 单条形态:`<seg.id>: [骨架:openflights] ❌ ...` 或 `<seg.id>: [骨架:openflights] ✅ ...`
|
|
226
|
+
const unscaffoldedSegIds = new Set();
|
|
227
|
+
for (const n of s.skeleton_notes ?? []) {
|
|
228
|
+
const m = /^([^:]+):\s*\[骨架:openflights\]\s*❌/.exec(n);
|
|
229
|
+
if (m)
|
|
230
|
+
unscaffoldedSegIds.add(m[1]);
|
|
125
231
|
}
|
|
126
|
-
for (const
|
|
127
|
-
|
|
232
|
+
for (const lg of s.legs ?? []) {
|
|
233
|
+
const l = lg;
|
|
234
|
+
const unscaffoldedFlag = unscaffoldedSegIds.has(String(l['leg'])) ? '⚠ ' : '';
|
|
235
|
+
const unscaffoldedNote = unscaffoldedSegIds.has(String(l['leg'])) ? '(枢纽对未在骨架覆盖,实时源以新航线为准)' : '';
|
|
236
|
+
lines.push(`- ${unscaffoldedFlag}${l['leg']} ${l['service']}:${l['dep']} 起飞,${l['wake']} 出发,${l['arrive_stay']} 到,`
|
|
237
|
+
+ `门到门 ${l['door_to_door']},落地精力 ${l['energy_pct']}%,¥${l['price_cny']}${unscaffoldedNote ? ` ${unscaffoldedNote}` : ''}`);
|
|
128
238
|
}
|
|
129
|
-
for (const n of s.skeleton_notes ?? [])
|
|
130
|
-
|
|
131
|
-
|
|
239
|
+
for (const n of s.skeleton_notes ?? [])
|
|
240
|
+
lines.push(`- ${n}`);
|
|
241
|
+
for (const f of s.red_flags ?? [])
|
|
242
|
+
lines.push(`- ⚠️ ${f}`);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
132
245
|
lines.push(`**当前约束下不可行——冲突:${(s.unsat_core ?? []).join('、')}`);
|
|
133
|
-
for (const sg of s.suggestions ?? [])
|
|
246
|
+
for (const sg of s.suggestions ?? [])
|
|
247
|
+
lines.push(`- 放宽「${sg.relax}」可解(约 ¥${sg.money_cny})`);
|
|
248
|
+
}
|
|
249
|
+
for (const e of s.work_window_exclusions ?? []) {
|
|
250
|
+
lines.push(`- 已排除 ${e.option}(工作窗口):${e.reason}`);
|
|
134
251
|
}
|
|
135
252
|
if (state.gates.length) {
|
|
136
253
|
lines.push('', '**待你决定(选择题)**');
|
|
137
|
-
for (const g of state.gates){
|
|
138
|
-
lines.push(`- ${g.question} → ${g.options.map(
|
|
254
|
+
for (const g of state.gates) {
|
|
255
|
+
lines.push(`- ${g.question} → ${g.options.map(o => o.label + (o.tradeOff ? `(${o.tradeOff})` : '')).join(' / ')}`);
|
|
139
256
|
}
|
|
140
257
|
}
|
|
141
258
|
return lines.join('\n');
|
|
142
259
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
role: 'user',
|
|
148
|
-
text: userMsg
|
|
149
|
-
}
|
|
150
|
-
], state);
|
|
260
|
+
/** 一次对话回合:抽取事实(冲突即指出)→ 增量访谈 → 约束齐备则求解+渲染。 */
|
|
261
|
+
export async function runTurn(state, userMsg, llm, history = [], solve = null, now = new Date()) {
|
|
262
|
+
const anchor = buildTimeAnchor(now);
|
|
263
|
+
const facts = await llm.extractFacts([...history, { role: 'user', text: userMsg }], state);
|
|
151
264
|
const conflicts = [];
|
|
152
265
|
if (facts.calendar?.assertedWeekdays) {
|
|
153
|
-
for (const [date, wd] of Object.entries(facts.calendar.assertedWeekdays)){
|
|
266
|
+
for (const [date, wd] of Object.entries(facts.calendar.assertedWeekdays)) {
|
|
154
267
|
const prev = state.calendar.assertedWeekdays[date];
|
|
155
268
|
if (prev && prev !== wd) {
|
|
156
269
|
conflicts.push(`${date}:已有断言 ${prev},新说法 ${wd}——以先断言为准,如需改请明确说`);
|
|
157
|
-
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
158
272
|
state.calendar.assertedWeekdays[date] = wd;
|
|
159
273
|
}
|
|
160
274
|
}
|
|
161
275
|
}
|
|
162
276
|
Object.assign(state.profile, facts.profile ?? {});
|
|
277
|
+
// 访谈:workWindow/bookedResources 是求解前置;budgetTier 转为 gate(不阻塞规划)
|
|
163
278
|
const { questions } = interviewNext(state);
|
|
164
|
-
const blocking = questions.filter(
|
|
165
|
-
const budgetQ = questions.find(
|
|
166
|
-
if (budgetQ && !state.gates.some(
|
|
279
|
+
const blocking = questions.filter(q => q.key !== 'budgetTier');
|
|
280
|
+
const budgetQ = questions.find(q => q.key === 'budgetTier');
|
|
281
|
+
if (budgetQ && !state.gates.some(g => g.id === 'budget')) {
|
|
167
282
|
state.gates.push({
|
|
168
283
|
id: 'budget',
|
|
169
284
|
question: budgetQ.text,
|
|
170
|
-
options: budgetQ.options ?? [
|
|
171
|
-
{
|
|
172
|
-
label: '经济'
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
label: '舒适'
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
label: '便利优先'
|
|
179
|
-
}
|
|
180
|
-
]
|
|
285
|
+
options: budgetQ.options ?? [{ label: '经济' }, { label: '舒适' }, { label: '便利优先' }],
|
|
181
286
|
});
|
|
182
287
|
}
|
|
183
288
|
const parts = [];
|
|
184
|
-
if (conflicts.length)
|
|
289
|
+
if (conflicts.length)
|
|
290
|
+
parts.push(`⚠️ 日历冲突:\n${conflicts.map(c => `- ${c}`).join('\n')}`);
|
|
291
|
+
// D-7a 例外: blocking>0 时,用户消息含"查+地名/酒店/天气"信号时,直接调 anything_search
|
|
292
|
+
// 走 PoI 真相(datasources 层主动调,不动 polling 状态机,不改求解器)
|
|
185
293
|
const poiProbe = probePoi(userMsg);
|
|
186
294
|
if (poiProbe) {
|
|
187
|
-
const ar = await anythingSearch({
|
|
188
|
-
keyword: poiProbe
|
|
189
|
-
});
|
|
295
|
+
const ar = await anythingSearch({ keyword: poiProbe });
|
|
190
296
|
if (ar.verdict === 'hit' && ar.hits && ar.hits.length > 0) {
|
|
191
297
|
const top = ar.hits.slice(0, 5);
|
|
192
|
-
const lines = top.map((h, i)=>{
|
|
193
|
-
const latlng = h.latitude !== undefined && h.longitude !== undefined
|
|
298
|
+
const lines = top.map((h, i) => {
|
|
299
|
+
const latlng = h.latitude !== undefined && h.longitude !== undefined
|
|
300
|
+
? ` @ (${h.latitude.toFixed(3)},${h.longitude.toFixed(3)})`
|
|
301
|
+
: '';
|
|
194
302
|
return ` ${i + 1}. [${h.type}] ${h.name}${latlng}`;
|
|
195
303
|
}).join('\n');
|
|
196
304
|
parts.push(`**${poiProbe} → hit (${ar.hits.length} 候选项)**\n${lines}\n${ar.evidence}`);
|
|
197
|
-
}
|
|
305
|
+
}
|
|
306
|
+
else if (ar.verdict === 'miss') {
|
|
198
307
|
parts.push(`**${poiProbe} → miss** (酒店-be Anything 一切正常但无候选)\n${ar.evidence}`);
|
|
199
|
-
}
|
|
200
|
-
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// 用户面只给人话原因 + 来源 tag:evidence 里的上游原话是溯源契约(能力层测试锁),
|
|
311
|
+
// 其中的进程噪音(如 `(exit null)`)不该渲染进回复。
|
|
312
|
+
const sourceTag = ar.evidence.match(/^\[[^\]]+\]/)?.[0];
|
|
313
|
+
parts.push(`**${poiProbe} → 实时查询不可用**(${ar.error ?? 'hbcli 不可达'})——这条不阻塞本轮规划,只影响实时数据源,其余结论照常带来源标注${sourceTag ? `\n${sourceTag}` : ''}`);
|
|
201
314
|
}
|
|
202
315
|
}
|
|
203
|
-
for (const q of blocking)
|
|
316
|
+
for (const q of blocking)
|
|
317
|
+
parts.push(await llm.polishQuestion(q));
|
|
318
|
+
// 约束齐备(无阻塞问题)→ 翻译 spec → **校验闸 + 日期一致性闸** → 求解 → 渲染
|
|
204
319
|
if (blocking.length === 0 && solve) {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
320
|
+
const extractedSpec = await llm.extractSpec([...history, { role: 'user', text: userMsg }], state);
|
|
321
|
+
const planning = latestPlanningWindow(history, userMsg, anchor);
|
|
322
|
+
const planningCheck = extractedSpec ? applyPlanningWindow(extractedSpec, planning, anchor) : null;
|
|
323
|
+
if (planningCheck?.error) {
|
|
324
|
+
state.spec = undefined;
|
|
325
|
+
state.solve = undefined;
|
|
326
|
+
parts.push(`⚠️ ${planningCheck.error}`);
|
|
327
|
+
return { reply: parts.join('\n\n'), state };
|
|
328
|
+
}
|
|
329
|
+
if (planningCheck?.rejected.length) {
|
|
330
|
+
const rejected = planningCheck.rejected
|
|
331
|
+
.map(r => `${r.segmentId}/${r.optionId}(${r.date})`)
|
|
332
|
+
.join('、');
|
|
333
|
+
parts.push(`已排除规划窗口外的候选:${rejected}`);
|
|
334
|
+
}
|
|
335
|
+
const spec = planningCheck?.spec ?? extractedSpec;
|
|
336
|
+
// 场景路由:erhai 候选标记 → 候选求解(洱海金标准的引擎判定)——纯 TS unify 路径
|
|
212
337
|
if (spec && spec.note === 'erhai-candidates') {
|
|
213
338
|
const { readFile } = await import('node:fs/promises');
|
|
214
339
|
const { join } = await import('node:path');
|
|
@@ -222,56 +347,52 @@ export async function runTurn(state, userMsg, llm, history = [], solve = null) {
|
|
|
222
347
|
const result = solveChoiceSegment(erhaiSpec, req);
|
|
223
348
|
state.solve = result;
|
|
224
349
|
parts.push(result.answer_md ?? '(候选求解完成)');
|
|
225
|
-
}
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
226
352
|
parts.push('(洱海候选求解暂不可用——退回访谈)');
|
|
227
353
|
}
|
|
228
|
-
}
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
229
356
|
const invalid = spec ? validateSpec(spec) : '翻译器未产出 spec';
|
|
230
357
|
if (spec && !invalid) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
text: userMsg
|
|
236
|
-
}
|
|
237
|
-
]);
|
|
358
|
+
// D-10 切片 C:spec↔槽位日期一致性闸(ADR-10 翻译≠造数的执行点)。
|
|
359
|
+
// LLM 翻译的 spec 日期与代码层换算的槽位日期分歧时不求解、不猜,追问确认——
|
|
360
|
+
// 日期是求解关键输入,错日期 = 错判决。槽位缺失/unresolved 不参与(不造假阳性)。
|
|
361
|
+
const ext = await llm.extractSlots([...history, { role: 'user', text: userMsg }], now);
|
|
238
362
|
if (ext) {
|
|
239
363
|
const { resolveSlots, specDateMismatches } = await import('./slot-spec.js');
|
|
240
|
-
const
|
|
241
|
-
const mismatches = specDateMismatches(spec, resolveSlots(ext, buildTimeAnchor()));
|
|
364
|
+
const mismatches = specDateMismatches(spec, resolveSlots(ext, anchor));
|
|
242
365
|
if (mismatches.length > 0) {
|
|
243
|
-
const lines = mismatches.map(
|
|
366
|
+
const lines = mismatches.map(m => `- ${m.specAt}:翻译说 ${m.specDate},你的原话换算是 ${m.slotDate}(${m.field})`);
|
|
244
367
|
parts.push(`⚠️ 日期分歧,确认后我再算(以你为准):\n${lines.join('\n')}`);
|
|
245
|
-
return {
|
|
246
|
-
reply: parts.join('\n\n'),
|
|
247
|
-
state
|
|
248
|
-
};
|
|
368
|
+
return { reply: parts.join('\n\n'), state };
|
|
249
369
|
}
|
|
250
370
|
}
|
|
251
371
|
state.spec = spec;
|
|
252
372
|
state.solve = await solve(spec);
|
|
253
373
|
parts.push(llm.render ? await llm.render(state) : renderSolve(state));
|
|
254
|
-
}
|
|
374
|
+
}
|
|
375
|
+
else if (blocking.length === 0 && invalid) {
|
|
255
376
|
parts.push(`(行程骨架还不完整:${invalid}——请补充对应信息,我不猜)`);
|
|
256
377
|
}
|
|
257
378
|
}
|
|
258
|
-
}
|
|
379
|
+
}
|
|
380
|
+
else if (blocking.length === 0) {
|
|
259
381
|
parts.push('(约束齐备——进入规划,S3 接线后此处产出方案与选择题)');
|
|
260
382
|
}
|
|
261
|
-
return {
|
|
262
|
-
reply: parts.join('\n\n'),
|
|
263
|
-
state
|
|
264
|
-
};
|
|
383
|
+
return { reply: parts.join('\n\n'), state };
|
|
265
384
|
}
|
|
385
|
+
// ---- 异步工单持久化(S5 编排半段 → ADR-15 durable 工单):真正的「一小时后」必须跨进程存续 ----
|
|
386
|
+
// 权威 = 账本 workflow_runs/workflow_steps(单事务;崩溃后 done 步骤不重执行);
|
|
387
|
+
// {id}.json / {id}.deliverable.md 降级为视图(AGENTS.md 清扫合同 + 人工检视),
|
|
388
|
+
// tmp+rename 原子写——此前裸 writeFile 的非原子缺口(RFC §1.1)就此关闭。
|
|
266
389
|
import { join } from 'node:path';
|
|
267
390
|
import { mkdir, rename, writeFile, readFile } from 'node:fs/promises';
|
|
268
391
|
import { ensureLedger, openLedgerIfExists } from './state-ledger.js';
|
|
269
392
|
async function asyncDir(stateRoot) {
|
|
270
393
|
const root = stateRoot === '.' ? process.cwd() : stateRoot;
|
|
271
394
|
const dir = join(root, 'gotry-state', 'async');
|
|
272
|
-
await mkdir(dir, {
|
|
273
|
-
recursive: true
|
|
274
|
-
});
|
|
395
|
+
await mkdir(dir, { recursive: true });
|
|
275
396
|
return dir;
|
|
276
397
|
}
|
|
277
398
|
async function atomicWrite(path, text) {
|
|
@@ -281,45 +402,73 @@ async function atomicWrite(path, text) {
|
|
|
281
402
|
}
|
|
282
403
|
export async function persistAsyncTicket(ticket, state, stateRoot = '.') {
|
|
283
404
|
const ledger = ensureLedger(stateRoot);
|
|
284
|
-
ledger.createWorkflowRun({
|
|
285
|
-
id: ticket.id,
|
|
286
|
-
goal: ticket.objective,
|
|
287
|
-
ticket,
|
|
288
|
-
state
|
|
289
|
-
});
|
|
405
|
+
ledger.createWorkflowRun({ id: ticket.id, goal: ticket.objective, ticket, state });
|
|
290
406
|
const dir = await asyncDir(stateRoot);
|
|
291
407
|
const p = join(dir, `${ticket.id}.json`);
|
|
292
|
-
await atomicWrite(p, JSON.stringify({
|
|
293
|
-
ticket,
|
|
294
|
-
state
|
|
295
|
-
}, null, 2));
|
|
408
|
+
await atomicWrite(p, JSON.stringify({ ticket, state }, null, 2));
|
|
296
409
|
return p;
|
|
297
410
|
}
|
|
298
411
|
export async function loadAsyncTicket(ticketId, stateRoot = '.') {
|
|
412
|
+
// 账本优先;无账本的 root 回退旧 json 文件(只读,兼容存量已交付工单)
|
|
299
413
|
const ledger = openLedgerIfExists(stateRoot);
|
|
300
414
|
const run = ledger?.getWorkflowRun(ticketId);
|
|
301
415
|
if (run) {
|
|
302
416
|
return {
|
|
303
417
|
ticket: JSON.parse(run.ticket_json),
|
|
304
|
-
state: JSON.parse(run.state_json)
|
|
418
|
+
state: JSON.parse(run.state_json),
|
|
305
419
|
};
|
|
306
420
|
}
|
|
307
421
|
try {
|
|
308
422
|
const p = join(await asyncDir(stateRoot), `${ticketId}.json`);
|
|
309
423
|
return JSON.parse(await readFile(p, 'utf-8'));
|
|
310
|
-
}
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
311
426
|
return null;
|
|
312
427
|
}
|
|
313
428
|
}
|
|
314
|
-
export async function settleAsyncTicket(ticketId, reply, stateRoot = '.') {
|
|
315
|
-
openLedgerIfExists(stateRoot)
|
|
429
|
+
export async function settleAsyncTicket(ticketId, reply, stateRoot = '.', outcome) {
|
|
430
|
+
const ledger = openLedgerIfExists(stateRoot);
|
|
431
|
+
const terminalOutcome = outcome ?? recoverAsyncTerminalOutcome(ledger, ticketId);
|
|
432
|
+
if (ledger && !terminalOutcome) {
|
|
433
|
+
throw new Error(`workflow ${ticketId} 缺少可恢复的 ${ASYNC_TERMINAL_SCHEMA},拒绝误结算`);
|
|
434
|
+
}
|
|
435
|
+
if (terminalOutcome?.status === 'failed')
|
|
436
|
+
ledger?.failWorkflowRun(ticketId, reply, terminalOutcome);
|
|
437
|
+
else
|
|
438
|
+
ledger?.settleWorkflowRun(ticketId, reply, terminalOutcome);
|
|
316
439
|
const dir = await asyncDir(stateRoot);
|
|
317
440
|
const p = join(dir, `${ticketId}.deliverable.md`);
|
|
318
441
|
await atomicWrite(p, reply);
|
|
319
442
|
return p;
|
|
320
443
|
}
|
|
444
|
+
function recoverAsyncTerminalOutcome(ledger, ticketId) {
|
|
445
|
+
if (!ledger)
|
|
446
|
+
return undefined;
|
|
447
|
+
const run = ledger.getWorkflowRun(ticketId);
|
|
448
|
+
if (!run)
|
|
449
|
+
return undefined;
|
|
450
|
+
try {
|
|
451
|
+
const state = JSON.parse(run.state_json);
|
|
452
|
+
if (!state.spec)
|
|
453
|
+
return terminalOutcomeFromState(ticketId, state);
|
|
454
|
+
const solveStep = ledger.getWorkflowStep(ticketId, 'solve');
|
|
455
|
+
if (solveStep?.status !== 'done' || !solveStep.result)
|
|
456
|
+
return undefined;
|
|
457
|
+
state.solve = JSON.parse(solveStep.result);
|
|
458
|
+
state.gates = state.gates.filter(g => !g.id.startsWith('async-'));
|
|
459
|
+
return terminalOutcomeFromState(ticketId, state);
|
|
460
|
+
}
|
|
461
|
+
catch {
|
|
462
|
+
return undefined;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* 可日志化 solve 端口(ADR-15 步骤日志,intent-before-execute):
|
|
467
|
+
* 先记 intent 再执行,done 后结果落账本——任意进程恢复时 done 的步骤直接复用
|
|
468
|
+
* 结果不重执行(exactly-once:LLM/求解调用不重复花钱),intent 悬挂的重试。
|
|
469
|
+
*/
|
|
321
470
|
export function makeJournaledSolvePort(ledger, runId, solve, opts) {
|
|
322
|
-
return async (spec)=>{
|
|
471
|
+
return async (spec) => {
|
|
323
472
|
const step = ledger.getWorkflowStep(runId, 'solve');
|
|
324
473
|
if (step?.status === 'done' && step.result) {
|
|
325
474
|
return JSON.parse(step.result);
|
|
@@ -331,30 +480,51 @@ export function makeJournaledSolvePort(ledger, runId, solve, opts) {
|
|
|
331
480
|
return r;
|
|
332
481
|
};
|
|
333
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* probePoi:从 user msg 探测"查 POI/酒店" 信号,返回关键词。
|
|
485
|
+
* 触发的不是关键词,是**结构**;关键词抓取有方向性——
|
|
486
|
+
* 1) 显式搜索动词(查/搜/找/看看/推荐/告诉我/检索)+ 宾语在动词后;
|
|
487
|
+
* 2) 住宿名词(酒店/民宿/客栈/饭店):优先取名词**之后**的名称段(须含拉丁/数字,
|
|
488
|
+
* 「我订了酒店:The Title…」→ The Title…);退路是名词前 2-6 字紧邻地名
|
|
489
|
+
* (「大理酒店」→ 大理;「机票和」类垃圾后缀拒);
|
|
490
|
+
* 3) 开放问(有什么/玩什么/有哪些):取名词前的地名;
|
|
491
|
+
* 4) 短裸地名:≤12 字、无标点、无陈述动词(「大理」✓;「明天有空」「我的工作时间是…」✗——
|
|
492
|
+
* 2026-08-28 巡检收紧:旧版 ≤24 直通把访谈答案整句当关键词,垃圾 hbcli 调用+证据噪音)。
|
|
493
|
+
* 不是意图(改求解器),只是 datasources 编排层的"提早调 anything"提示。
|
|
494
|
+
*/
|
|
495
|
+
/** 住宿名称段上界:路径 2 已要求含拉丁/数字且被标点截断,旧 24 字会把
|
|
496
|
+
* 「The Title East Wing Rawai」这类真实酒店名截残后回显给用户(2026-09-22)。 */
|
|
497
|
+
const POI_NAME_MAX = 48;
|
|
334
498
|
export function probePoi(msg) {
|
|
335
499
|
const trimmed = msg.trim();
|
|
336
|
-
if (!trimmed)
|
|
337
|
-
|
|
500
|
+
if (!trimmed)
|
|
501
|
+
return null;
|
|
502
|
+
const cutAtPunct = (s) => s.split(/[,,。.;;!!??]/)[0]?.trim() ?? '';
|
|
503
|
+
// 1) 显式搜索动词 + 宾语
|
|
338
504
|
const m = trimmed.match(/(查一下|查|搜|找|看看|推荐|告诉我|检索)\s*(.{2,24})/);
|
|
339
505
|
if (m?.[2]) {
|
|
340
506
|
const obj = cutAtPunct(m[2]);
|
|
341
|
-
if (obj.length >= 2)
|
|
507
|
+
if (obj.length >= 2)
|
|
508
|
+
return obj.slice(0, 24);
|
|
342
509
|
}
|
|
510
|
+
// 2) 住宿名词:名称段在名词后
|
|
343
511
|
if (/(酒店|民宿|客栈|饭店)/.test(trimmed)) {
|
|
344
512
|
const parts = trimmed.split(/(酒店|民宿|客栈|饭店)/);
|
|
345
513
|
const after = cutAtPunct((parts[2] ?? '').replace(/^[的::\s]+/, ''));
|
|
346
|
-
if (after.length >= 2 && /[A-Za-z0-9]/.test(after))
|
|
514
|
+
if (after.length >= 2 && /[A-Za-z0-9]/.test(after))
|
|
515
|
+
return after.length > POI_NAME_MAX ? `${after.slice(0, POI_NAME_MAX - 1)}…` : after;
|
|
347
516
|
const nounAt = trimmed.search(/(酒店|民宿|客栈|饭店)/);
|
|
348
517
|
const pre = trimmed.slice(Math.max(0, nounAt - 6), nounAt).match(/[一-龥]{2,6}$/);
|
|
349
|
-
if (pre && !/(机票|车票|和|做|订|的)$/.test(pre[0]))
|
|
518
|
+
if (pre && !/(机票|车票|和|做|订|的)$/.test(pre[0]))
|
|
519
|
+
return pre[0];
|
|
350
520
|
}
|
|
521
|
+
// 3) 开放问:地名在疑问词前
|
|
351
522
|
const q = trimmed.match(/([一-龥a-zA-Z]{2,12})\s*(?:有什么|玩什么|有哪些)/);
|
|
352
|
-
if (q?.[1])
|
|
523
|
+
if (q?.[1])
|
|
524
|
+
return q[1];
|
|
525
|
+
// 4) 短裸地名(≤12 字,无标点,无陈述动词)
|
|
353
526
|
if (trimmed.length <= 12 && !/[,,。.;;!!??::]/.test(trimmed) && !/[是有在要想得到说订吧呢]/.test(trimmed)) {
|
|
354
527
|
return trimmed.slice(0, 24);
|
|
355
528
|
}
|
|
356
529
|
return null;
|
|
357
530
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
//# sourceURL=/Users/bytedance/work/gotry/ts/src/loop.ts
|