@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.
Files changed (533) hide show
  1. package/README.md +172 -219
  2. package/README.zh-CN.md +222 -0
  3. package/bin/gotry-backend.js +53 -0
  4. package/bin/gotry-booking-copilot.js +53 -0
  5. package/bin/gotry-bootstrap.js +1788 -0
  6. package/bin/gotry-inner.js +733 -83
  7. package/bin/gotry-process-liveness.d.ts +27 -0
  8. package/bin/gotry-process-liveness.js +97 -0
  9. package/bin/gotry-runtime-resolution.d.ts +27 -0
  10. package/bin/gotry-runtime-resolution.js +49 -0
  11. package/bin/gotry.js +1 -1
  12. package/client/client.js +203 -0
  13. package/cordis.gotry-patch.yml +80 -56
  14. package/data/airline-airports.json +39 -0
  15. package/data/stations-12306-verify.json +524 -0
  16. package/dist/capabilities/agent-reach-deep.js +45 -122
  17. package/dist/capabilities/agent-reach.js +101 -146
  18. package/dist/capabilities/anything.js +161 -94
  19. package/dist/capabilities/artifacts.js +370 -0
  20. package/dist/capabilities/channel-health.js +131 -0
  21. package/dist/capabilities/channel-registry.js +256 -0
  22. package/dist/capabilities/doctor.js +553 -0
  23. package/dist/capabilities/effect.js +394 -0
  24. package/dist/capabilities/external-event.js +149 -0
  25. package/dist/capabilities/fact-log.js +55 -0
  26. package/dist/capabilities/flyai-config.js +337 -0
  27. package/dist/capabilities/flyai.js +947 -110
  28. package/dist/capabilities/fx-contract.js +293 -0
  29. package/dist/capabilities/geo-atlas.js +246 -0
  30. package/dist/capabilities/ground-transfer.js +676 -0
  31. package/dist/capabilities/hbcli.js +260 -123
  32. package/dist/capabilities/hotelbyte-transaction.js +194 -0
  33. package/dist/capabilities/incident-log.js +131 -61
  34. package/dist/capabilities/itinerary-artifact.js +190 -0
  35. package/dist/capabilities/itinerary-deck-artifact.js +194 -0
  36. package/dist/capabilities/itinerary-deck-export.js +339 -0
  37. package/dist/capabilities/lavish-local.js +924 -0
  38. package/dist/capabilities/model-override.js +38 -0
  39. package/dist/capabilities/opensky.js +54 -43
  40. package/dist/capabilities/provider-detail-sanitize.js +64 -0
  41. package/dist/capabilities/resilience.js +191 -0
  42. package/dist/capabilities/route-provider-conformance.js +341 -0
  43. package/dist/capabilities/session/action-cache.js +50 -44
  44. package/dist/capabilities/session/adapters/ctrip-flight.js +120 -62
  45. package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
  46. package/dist/capabilities/session/adapters/dida-portal.js +274 -0
  47. package/dist/capabilities/session/adapters/meituan-local.js +35 -54
  48. package/dist/capabilities/session/adapters/rail-12306.js +342 -0
  49. package/dist/capabilities/session/benchmark.js +189 -0
  50. package/dist/capabilities/session/bridge-ledger.js +224 -0
  51. package/dist/capabilities/session/extension-bridge.js +636 -0
  52. package/dist/capabilities/session/extension-channel.js +109 -0
  53. package/dist/capabilities/session/extension-distribution.js +230 -0
  54. package/dist/capabilities/session/extract.js +31 -21
  55. package/dist/capabilities/session/golden-score.js +114 -0
  56. package/dist/capabilities/session/health-watch.js +215 -0
  57. package/dist/capabilities/session/read-guard.js +75 -24
  58. package/dist/capabilities/session/static-flight-golden.js +150 -0
  59. package/dist/capabilities/session/transport.js +97 -83
  60. package/dist/capabilities/session/wizard.js +117 -0
  61. package/dist/capabilities/session-consent.js +178 -0
  62. package/dist/capabilities/session-login.js +170 -0
  63. package/dist/capabilities/session-search.js +635 -44
  64. package/dist/capabilities/spawn-bounded.js +203 -0
  65. package/dist/capabilities/sponsor-plugin.js +341 -0
  66. package/dist/capabilities/visa-policy.js +140 -0
  67. package/dist/capabilities/weather.js +243 -138
  68. package/dist/data/session-golden-20.json +25 -0
  69. package/dist/data/sf-golden-manifest.json +103 -0
  70. package/dist/data/sf-static-routes.json +91 -0
  71. package/dist/scripts/action-cache-tests.js +24 -59
  72. package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
  73. package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
  74. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  75. package/dist/scripts/agent-reach-error-tests.js +354 -0
  76. package/dist/scripts/agent-reach-tests.js +26 -18
  77. package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
  78. package/dist/scripts/anything-path-measure-tests.js +133 -0
  79. package/dist/scripts/anything-path-measure.js +150 -0
  80. package/dist/scripts/anything-tests.js +250 -60
  81. package/dist/scripts/artifact-client-contract-tests.js +220 -0
  82. package/dist/scripts/artifacts-capability-tests.js +727 -0
  83. package/dist/scripts/async-collect.js +50 -11
  84. package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
  85. package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
  86. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
  87. package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
  88. package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
  89. package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
  90. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
  91. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
  92. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
  93. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
  94. package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
  95. package/dist/scripts/booking-copilot-dsh-warmer-proof.js +126 -0
  96. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
  97. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
  98. package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
  99. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
  100. package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
  101. package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
  102. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
  103. package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
  104. package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
  105. package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
  106. package/dist/scripts/booking-executor-tests.js +80 -0
  107. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  108. package/dist/scripts/booking-saga-tests.js +125 -0
  109. package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
  110. package/dist/scripts/bootstrap-tests.js +1549 -0
  111. package/dist/scripts/bridge-events-tests.js +239 -0
  112. package/dist/scripts/bridge-ledger-tests.js +428 -0
  113. package/dist/scripts/build-changelog.js +238 -0
  114. package/dist/scripts/build-metrics-report.js +331 -0
  115. package/dist/scripts/changelog-tests.js +118 -0
  116. package/dist/scripts/channel-probe-tests.js +103 -0
  117. package/dist/scripts/channel-probe.js +169 -0
  118. package/dist/scripts/channel-registry-tests.js +208 -0
  119. package/dist/scripts/city-scenario-tier-tests.js +234 -0
  120. package/dist/scripts/companion-tests.js +25 -70
  121. package/dist/scripts/dida-cookie-probe.js +87 -0
  122. package/dist/scripts/dida-runner-stop-tests.js +311 -0
  123. package/dist/scripts/dida-sw-probe.js +114 -0
  124. package/dist/scripts/diff-test.js +17 -12
  125. package/dist/scripts/doctor-tests.js +600 -0
  126. package/dist/scripts/drill-multiuser-ledger-tests.js +1076 -0
  127. package/dist/scripts/drill-sdk-descendant-cleanup-tests.js +606 -0
  128. package/dist/scripts/drill-w2a-sensor-tests.js +788 -0
  129. package/dist/scripts/dsh-artifact-e2e.js +279 -0
  130. package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
  131. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  132. package/dist/scripts/dsh-llm-tests.js +437 -0
  133. package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
  134. package/dist/scripts/dsh-runtime-closure.js +162 -0
  135. package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
  136. package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
  137. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  138. package/dist/scripts/effect-tests.js +539 -0
  139. package/dist/scripts/engine-run.js +1 -3
  140. package/dist/scripts/engine-tests.js +16 -10
  141. package/dist/scripts/evaluation-cadence-tests.js +174 -0
  142. package/dist/scripts/evaluation-contract-tests.js +268 -0
  143. package/dist/scripts/extension-distribution-cli.js +39 -0
  144. package/dist/scripts/extension-distribution-tests.js +443 -0
  145. package/dist/scripts/extension-tests.js +988 -0
  146. package/dist/scripts/external-event-tests.js +350 -0
  147. package/dist/scripts/fact-gate-tests.js +869 -0
  148. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  149. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  150. package/dist/scripts/flight-malformed-tests.js +159 -0
  151. package/dist/scripts/flyai-setup-tests.js +228 -0
  152. package/dist/scripts/flyai-setup-tool-tests.js +54 -0
  153. package/dist/scripts/flyai-tests.js +692 -0
  154. package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
  155. package/dist/scripts/fx-contract-tests.js +201 -0
  156. package/dist/scripts/g5-guard-tests.js +150 -0
  157. package/dist/scripts/g5-guard.js +193 -0
  158. package/dist/scripts/gen-lunar-anchors.js +106 -0
  159. package/dist/scripts/geo-atlas-tests.js +283 -0
  160. package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
  161. package/dist/scripts/gotry-try-demo-tests.js +79 -0
  162. package/dist/scripts/gotry-try-demo.js +49 -0
  163. package/dist/scripts/ground-transfer-tests.js +956 -0
  164. package/dist/scripts/hbcli-e2e-tests.js +159 -0
  165. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  166. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  167. package/dist/scripts/hbcli-tests.js +121 -69
  168. package/dist/scripts/health-watch-cli.js +73 -0
  169. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  170. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  171. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  172. package/dist/scripts/i18n-tests.js +41 -0
  173. package/dist/scripts/incident-tests.js +281 -87
  174. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  175. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  176. package/dist/scripts/issue-271-liveness-tests.js +569 -0
  177. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  178. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  179. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  180. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  181. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  182. package/dist/scripts/issue436-persisted-routing-e2e.js +247 -0
  183. package/dist/scripts/itinerary-artifact-tests.js +368 -0
  184. package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
  185. package/dist/scripts/itinerary-deck-export-tests.js +552 -0
  186. package/dist/scripts/itinerary-deck-tests.js +435 -0
  187. package/dist/scripts/itinerary-html-tests.js +426 -0
  188. package/dist/scripts/journey-tests.js +22 -27
  189. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  190. package/dist/scripts/kernel-manifest-gate.js +126 -0
  191. package/dist/scripts/kernel-manifest-tests.js +212 -0
  192. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  193. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  194. package/dist/scripts/kernel-manifest.js +369 -0
  195. package/dist/scripts/lavish-local-tests.js +1226 -0
  196. package/dist/scripts/lavish-product-tools-tests.js +537 -0
  197. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  198. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  199. package/dist/scripts/ledger-tests.js +382 -246
  200. package/dist/scripts/ledger-workflow-crash.js +10 -20
  201. package/dist/scripts/m3-cohort-tests.js +714 -0
  202. package/dist/scripts/m3-cohort.js +310 -0
  203. package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
  204. package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
  205. package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
  206. package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
  207. package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
  208. package/dist/scripts/memory-capture-tests.js +242 -61
  209. package/dist/scripts/memory-decay-tests.js +18 -52
  210. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  211. package/dist/scripts/memory-lifecycle.js +196 -0
  212. package/dist/scripts/memory-metrics.js +24 -12
  213. package/dist/scripts/memory-value-report.js +631 -0
  214. package/dist/scripts/memory-value-tests.js +328 -0
  215. package/dist/scripts/metrics-report-tests.js +151 -0
  216. package/dist/scripts/model-override-e2e.js +137 -0
  217. package/dist/scripts/nightly-evidence-tests.js +203 -0
  218. package/dist/scripts/nightly-evidence.js +303 -0
  219. package/dist/scripts/nudge-digest.js +39 -28
  220. package/dist/scripts/observability-tests.js +381 -0
  221. package/dist/scripts/onboarding-tests.js +161 -0
  222. package/dist/scripts/opensky-check.js +18 -13
  223. package/dist/scripts/opensky-tests.js +28 -28
  224. package/dist/scripts/outcome-projection-tests.js +427 -0
  225. package/dist/scripts/persona-sim-tests.js +603 -0
  226. package/dist/scripts/persona-sim.js +1081 -0
  227. package/dist/scripts/persona-surface-guard-tests.js +49 -0
  228. package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
  229. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  230. package/dist/scripts/price-drift-tests.js +340 -0
  231. package/dist/scripts/price-drift-watch.js +447 -0
  232. package/dist/scripts/probe-poi-tests.js +53 -45
  233. package/dist/scripts/product-metrics.js +483 -0
  234. package/dist/scripts/publish-preverify.js +110 -0
  235. package/dist/scripts/realtime-pricing-tests.js +76 -0
  236. package/dist/scripts/recall-tests.js +513 -0
  237. package/dist/scripts/replay-async.js +22 -18
  238. package/dist/scripts/replay-real.js +18 -18
  239. package/dist/scripts/replay.js +54 -82
  240. package/dist/scripts/route-provider-conformance-tests.js +391 -0
  241. package/dist/scripts/session-attach-diagnose.js +20 -20
  242. package/dist/scripts/session-attach-poc.js +34 -37
  243. package/dist/scripts/session-benchmark.js +180 -0
  244. package/dist/scripts/session-dida-live-e2e.js +199 -0
  245. package/dist/scripts/session-extract-tests.js +14 -35
  246. package/dist/scripts/session-link-tests.js +478 -0
  247. package/dist/scripts/session-login.js +27 -46
  248. package/dist/scripts/session-tests.js +796 -96
  249. package/dist/scripts/session-zone-crash.js +49 -0
  250. package/dist/scripts/session-zone-ledger-tests.js +432 -0
  251. package/dist/scripts/session-zone-observation-tests.js +492 -0
  252. package/dist/scripts/session-zone-observe.js +135 -0
  253. package/dist/scripts/session-zone-wiring-tests.js +566 -0
  254. package/dist/scripts/session-zones-tests.js +374 -0
  255. package/dist/scripts/sf-live-benchmark.js +367 -0
  256. package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
  257. package/dist/scripts/sf-live-cli-tests.js +92 -0
  258. package/dist/scripts/sf-live-options.js +46 -0
  259. package/dist/scripts/sf-manifest-tests.js +30 -0
  260. package/dist/scripts/sf-manifest.js +33 -0
  261. package/dist/scripts/sf-soft-score-tests.js +67 -0
  262. package/dist/scripts/sf-summary-tests.js +324 -0
  263. package/dist/scripts/sf-summary.js +525 -0
  264. package/dist/scripts/share-tests.js +432 -0
  265. package/dist/scripts/skeleton-check.js +16 -14
  266. package/dist/scripts/skeleton-integration-test.js +28 -11
  267. package/dist/scripts/skills-contract-tests.js +51 -46
  268. package/dist/scripts/smoke-session-gate-tests.js +21 -0
  269. package/dist/scripts/smoke.js +690 -246
  270. package/dist/scripts/spawn-bounded-abort-tests.js +244 -0
  271. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  272. package/dist/scripts/state-cli-tests.js +226 -101
  273. package/dist/scripts/state-cli.js +565 -198
  274. package/dist/scripts/state-repair-cli.js +66 -0
  275. package/dist/scripts/state-repair-tests.js +140 -0
  276. package/dist/scripts/static-golden-tests.js +165 -0
  277. package/dist/scripts/time-eval-tests.js +212 -192
  278. package/dist/scripts/travel-timeline-tests.js +29 -93
  279. package/dist/scripts/turn-handoff-collect-tests.js +169 -0
  280. package/dist/scripts/turn-handoff-collect.js +161 -0
  281. package/dist/scripts/turn-policy-tests.js +55 -0
  282. package/dist/scripts/typed-contract-canary.js +176 -0
  283. package/dist/scripts/tz-resolver-sanity.js +50 -0
  284. package/dist/scripts/tz-resolver-tests.js +584 -0
  285. package/dist/scripts/unified-tests.js +60 -20
  286. package/dist/scripts/visa-policy-tests.js +62 -0
  287. package/dist/scripts/weather-tests.js +276 -41
  288. package/dist/scripts/wish-channel-gate-tests.js +54 -0
  289. package/dist/scripts/write-gate-tests.js +522 -0
  290. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  291. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  292. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  293. package/dist/scripts/z3-race-tests.js +46 -0
  294. package/dist/src/artifact-gate.js +829 -0
  295. package/dist/src/backend/kernel.js +91 -0
  296. package/dist/src/backend/modules/booking-copilot.js +92 -0
  297. package/dist/src/backend/modules/booking-executor.js +124 -0
  298. package/dist/src/backend/modules/session-search.js +551 -0
  299. package/dist/src/benchmark-agent-conformance.js +578 -0
  300. package/dist/src/benchmark-environment-bridge.js +515 -0
  301. package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
  302. package/dist/src/benchmark-tool-isolation.js +151 -0
  303. package/dist/src/bookable-facts.js +533 -0
  304. package/dist/src/booking-saga.js +97 -0
  305. package/dist/src/booking-surface/availability-policy.js +697 -0
  306. package/dist/src/booking-surface/booking-intent.js +43 -0
  307. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  308. package/dist/src/booking-surface/canonical-schema.js +116 -0
  309. package/dist/src/booking-surface/contracts.js +75 -0
  310. package/dist/src/booking-surface/dsh-planner.js +1854 -0
  311. package/dist/src/booking-surface/dsh-plugin.js +378 -0
  312. package/dist/src/booking-surface/dsh-worker.js +98 -0
  313. package/dist/src/booking-surface/error-codes.js +231 -0
  314. package/dist/src/booking-surface/index.js +9 -0
  315. package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
  316. package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
  317. package/dist/src/booking-surface/profile.js +24 -0
  318. package/dist/src/booking-surface/recovery-chain.js +367 -0
  319. package/dist/src/booking-surface/runtime.js +1968 -0
  320. package/dist/src/booking-surface/server.js +674 -0
  321. package/dist/src/booking-surface/startup.js +168 -0
  322. package/dist/src/booking-surface/validation.js +261 -0
  323. package/dist/src/bridge.js +20 -13
  324. package/dist/src/city-scenario-tier.js +378 -0
  325. package/dist/src/companions.js +48 -74
  326. package/dist/src/contracts.js +21 -43
  327. package/dist/src/dsh-llm.js +171 -115
  328. package/dist/src/engine.js +276 -193
  329. package/dist/src/evaluation-cadence.js +97 -0
  330. package/dist/src/evaluation-contracts.js +283 -0
  331. package/dist/src/flight-pack-adapter.js +54 -0
  332. package/dist/src/flight-pack-contract.js +2 -0
  333. package/dist/src/flyai-setup-tool.js +70 -0
  334. package/dist/src/gotry-backend.js +125 -0
  335. package/dist/src/hotel-date-gate.js +118 -0
  336. package/dist/src/i18n.js +88 -0
  337. package/dist/src/index.js +2385 -881
  338. package/dist/src/itinerary-deck.js +139 -0
  339. package/dist/src/itinerary-doc-shared.js +661 -0
  340. package/dist/src/itinerary-html.js +131 -0
  341. package/dist/src/journey.js +155 -108
  342. package/dist/src/lavish-tools.js +400 -0
  343. package/dist/src/ledger-repair-apply.js +538 -0
  344. package/dist/src/ledger-repair-plan.js +463 -0
  345. package/dist/src/loop.js +331 -161
  346. package/dist/src/m3-cohort.js +1577 -0
  347. package/dist/src/memory-capture.js +180 -32
  348. package/dist/src/memory-decay.js +30 -14
  349. package/dist/src/memory-lifecycle.js +1310 -0
  350. package/dist/src/memory-utility.js +27 -40
  351. package/dist/src/mock-llm.js +36 -61
  352. package/dist/src/model.js +81 -36
  353. package/dist/src/outcome-projection.js +746 -0
  354. package/dist/src/realtime-pricing.js +103 -0
  355. package/dist/src/recall/card.js +74 -0
  356. package/dist/src/recall/evaluator.js +140 -0
  357. package/dist/src/recall/integration.js +17 -0
  358. package/dist/src/recall/tick.js +166 -0
  359. package/dist/src/session-link/plan-it-action.js +48 -0
  360. package/dist/src/session-link/session-link.js +248 -0
  361. package/dist/src/session-zone-ledger.js +312 -0
  362. package/dist/src/session-zone-observation.js +354 -0
  363. package/dist/src/session-zone-wiring.js +658 -0
  364. package/dist/src/session-zones.js +510 -0
  365. package/dist/src/share/adapters.js +51 -0
  366. package/dist/src/share/share-consent.js +76 -0
  367. package/dist/src/share/share-deck.js +58 -0
  368. package/dist/src/share/share-token.js +146 -0
  369. package/dist/src/slot-spec.js +84 -106
  370. package/dist/src/state-ledger.js +696 -524
  371. package/dist/src/state-repair.js +299 -0
  372. package/dist/src/subagent-job-id-guard.js +58 -0
  373. package/dist/src/time-anchor.js +231 -33
  374. package/dist/src/tool-packet.js +20 -8
  375. package/dist/src/travel-slots.js +58 -35
  376. package/dist/src/travel-timeline.js +44 -63
  377. package/dist/src/turn-deadline.js +287 -0
  378. package/dist/src/turn-policy.js +118 -0
  379. package/dist/src/tz-resolver.js +143 -0
  380. package/dist/src/unified.js +600 -360
  381. package/dist/src/wish-pool.js +42 -12
  382. package/dist/src/write-gate.js +495 -0
  383. package/dist/src/z3-shared.js +284 -0
  384. package/extension/README.md +21 -0
  385. package/extension/README.zh-CN.md +21 -0
  386. package/extension/background.js +463 -0
  387. package/extension/content-bridge.js +270 -0
  388. package/extension/content-main.js +111 -0
  389. package/extension/manifest.json +60 -0
  390. package/package.json +407 -14
  391. package/schemas/booking.intent.schema.json +193 -0
  392. package/schemas/booking.surface.schema.json +2622 -0
  393. package/ts/capabilities/agent-reach-deep.ts +114 -0
  394. package/ts/capabilities/agent-reach.ts +198 -0
  395. package/ts/capabilities/anything.ts +282 -0
  396. package/ts/capabilities/artifacts.ts +428 -0
  397. package/ts/capabilities/fact-log.ts +54 -0
  398. package/ts/capabilities/flyai-config.ts +388 -0
  399. package/ts/capabilities/flyai.ts +1274 -0
  400. package/ts/capabilities/hbcli.ts +253 -71
  401. package/ts/capabilities/incident-log.ts +88 -59
  402. package/ts/capabilities/itinerary-artifact.ts +214 -0
  403. package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
  404. package/ts/capabilities/itinerary-deck-export.ts +378 -0
  405. package/ts/capabilities/opensky.ts +121 -0
  406. package/ts/capabilities/session/action-cache.ts +148 -0
  407. package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
  408. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  409. package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
  410. package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
  411. package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
  412. package/ts/capabilities/session/benchmark.ts +276 -0
  413. package/ts/capabilities/session/bridge-ledger.ts +333 -0
  414. package/ts/capabilities/session/extension-bridge.ts +794 -0
  415. package/ts/capabilities/session/extension-channel.ts +144 -0
  416. package/ts/capabilities/session/extension-distribution.ts +266 -0
  417. package/ts/capabilities/session/extract.ts +54 -0
  418. package/ts/capabilities/session/golden-score.ts +139 -0
  419. package/ts/capabilities/session/health-watch.ts +264 -0
  420. package/ts/capabilities/session/read-guard.ts +141 -0
  421. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  422. package/ts/capabilities/session/transport.ts +146 -0
  423. package/ts/capabilities/session/wizard.ts +140 -0
  424. package/ts/capabilities/session-consent.ts +211 -0
  425. package/ts/capabilities/session-login.ts +208 -0
  426. package/ts/capabilities/session-search.ts +893 -0
  427. package/ts/capabilities/weather.ts +330 -0
  428. package/ts/dsh-runtime/vendor/README.md +68 -0
  429. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  430. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
  431. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
  432. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
  433. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  434. package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
  435. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
  436. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  437. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
  438. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  439. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  440. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
  441. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  442. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
  443. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
  444. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
  445. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
  446. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  447. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  448. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
  449. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
  450. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  451. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  452. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  453. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  454. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
  455. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  456. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
  457. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  458. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  459. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
  460. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  461. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  462. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
  463. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
  464. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  465. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
  466. package/ts/package.json +293 -3
  467. package/ts/scripts/async-collect.ts +91 -0
  468. package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
  469. package/ts/scripts/skeleton-check.ts +1 -1
  470. package/ts/scripts/skeleton-integration-test.ts +23 -1
  471. package/ts/scripts/state-cli.ts +586 -0
  472. package/ts/scripts/turn-handoff-collect.ts +178 -0
  473. package/ts/src/artifact-gate.ts +991 -0
  474. package/ts/src/benchmark-agent-conformance.ts +619 -0
  475. package/ts/src/benchmark-environment-bridge.ts +538 -0
  476. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  477. package/ts/src/benchmark-tool-isolation.ts +166 -0
  478. package/ts/src/bookable-facts.ts +837 -0
  479. package/ts/src/booking-saga.ts +133 -0
  480. package/ts/src/booking-surface/availability-policy.ts +522 -0
  481. package/ts/src/booking-surface/booking-intent.ts +86 -0
  482. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  483. package/ts/src/booking-surface/canonical-schema.js +116 -0
  484. package/ts/src/booking-surface/contracts.ts +475 -0
  485. package/ts/src/booking-surface/dsh-planner.ts +1949 -0
  486. package/ts/src/booking-surface/dsh-plugin.js +378 -0
  487. package/ts/src/booking-surface/dsh-worker.ts +110 -0
  488. package/ts/src/booking-surface/error-codes.ts +241 -0
  489. package/ts/src/booking-surface/index.ts +9 -0
  490. package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
  491. package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
  492. package/ts/src/booking-surface/profile.ts +42 -0
  493. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  494. package/ts/src/booking-surface/runtime.ts +1793 -0
  495. package/ts/src/booking-surface/server.ts +733 -0
  496. package/ts/src/booking-surface/startup.ts +201 -0
  497. package/ts/src/booking-surface/validation.ts +217 -0
  498. package/ts/src/companions.ts +113 -0
  499. package/ts/src/contracts.ts +17 -3
  500. package/ts/src/dsh-llm.ts +152 -17
  501. package/ts/src/flyai-setup-tool.ts +77 -0
  502. package/ts/src/index.ts +2123 -200
  503. package/ts/src/itinerary-deck.ts +189 -0
  504. package/ts/src/itinerary-doc-shared.ts +741 -0
  505. package/ts/src/itinerary-html.ts +171 -0
  506. package/ts/src/loop.ts +234 -26
  507. package/ts/src/memory-capture.ts +283 -0
  508. package/ts/src/memory-decay.ts +55 -0
  509. package/ts/src/memory-utility.ts +70 -0
  510. package/ts/src/mock-llm.ts +4 -8
  511. package/ts/src/model.ts +88 -2
  512. package/ts/src/recall/card.ts +106 -0
  513. package/ts/src/recall/evaluator.ts +170 -0
  514. package/ts/src/recall/integration.ts +35 -0
  515. package/ts/src/recall/tick.ts +213 -0
  516. package/ts/src/session-link/plan-it-action.ts +78 -0
  517. package/ts/src/session-link/session-link.ts +275 -0
  518. package/ts/src/share/adapters.ts +93 -0
  519. package/ts/src/share/share-consent.ts +105 -0
  520. package/ts/src/share/share-deck.ts +85 -0
  521. package/ts/src/share/share-token.ts +166 -0
  522. package/ts/src/slot-spec.ts +172 -0
  523. package/ts/src/state-ledger.ts +1166 -0
  524. package/ts/src/subagent-job-id-guard.ts +72 -0
  525. package/ts/src/time-anchor.ts +338 -0
  526. package/ts/src/tool-packet.ts +32 -0
  527. package/ts/src/travel-slots.ts +219 -0
  528. package/ts/src/travel-timeline.ts +83 -0
  529. package/ts/src/turn-deadline.ts +366 -0
  530. package/ts/src/turn-policy.ts +154 -0
  531. package/ts/src/unified.ts +444 -105
  532. package/ts/src/wish-pool.ts +79 -0
  533. package/dist/scripts/session-attach-wait.js +0 -41
@@ -0,0 +1,676 @@
1
+ /**
2
+ * Bounded ground-transfer seam for explicit airport/station coordinates.
3
+ *
4
+ * This capability owns only the boundary between a public
5
+ * `map_driving_route` result and the deterministic candidate input. It never
6
+ * calls a map client directly, never writes shared state, and never supplies
7
+ * a price: the selected candidate transfer keeps its static `priceCny`.
8
+ *
9
+ * Each `ground_transfer` request resolves two deterministic directions —
10
+ * outbound (origin → destination) and return (destination → origin) — and
11
+ * binds the resulting route minutes to the candidate transfer as
12
+ * `minutesOut` / `minutesRet` overrides consumed by the solver / arithmetic
13
+ * layer. Cache, freshness, and fallback are isolated per direction so a
14
+ * miss / error / stale / mismatch in one direction never borrows the
15
+ * dynamic value of the other.
16
+ *
17
+ * A provider's OWN claims about its answer — declared `mode`, resolved
18
+ * origin/destination — are verified against the request whenever the provider
19
+ * makes them: a contradiction is refused with the conformance vocabulary
20
+ * (`mode_mismatch` / `direction_mismatch`) and falls back to the static estimate,
21
+ * so a transit duration is never bound as driving and a route between two other
22
+ * places is never bound as the airport transfer (issue #429 GAP-429-1/2). All
23
+ * three fields are OPTIONAL and absent means unverifiable: see
24
+ * `PublicMapDrivingRouteResult` for why absent is still accepted today.
25
+ *
26
+ * A provider failure becomes a `fallbackReason`, and `exposeGroundTransferEvidence`
27
+ * carries that text into the tool result and each matching verdict's
28
+ * `transfer_evidence`. It is therefore an EXPOSED surface: every provider-authored
29
+ * failure string passes through the shared `sanitizeFaultDetail` first, so markup,
30
+ * credential assignments and URLs from a provider response body can never reach it
31
+ * (issue #429 GAP-429-3). The historical 400-character bound and the historical
32
+ * empty-case wording are preserved, so existing `GROUND_TRANSFER_*` /
33
+ * `map_driving_route` reason strings are unchanged byte for byte.
34
+ */
35
+ import { ToolCallId } from '@deepseek-ai/dsh-llm';
36
+ import { sanitizeFaultDetail } from './provider-detail-sanitize.js';
37
+ export const GROUND_TRANSFER_MODE = 'driving';
38
+ export const GROUND_TRANSFER_POSITION = 'destination';
39
+ export const GROUND_TRANSFER_STATIC_MODE = 'taxi';
40
+ export const GROUND_TRANSFER_STATIC_MODE_MISMATCH = 'ground_transfer_static_mode_mismatch';
41
+ export const GROUND_TRANSFER_STATIC_PRICE_EVIDENCE = '[静态包:估算]';
42
+ export const GROUND_TRANSFER_DEFAULT_MAX_AGE_S = 15 * 60;
43
+ /**
44
+ * Refusal classifications for a provider that contradicts its own request. The
45
+ * two names are the #429 conformance gate's vocabulary verbatim
46
+ * (`RouteErrorCode`), reused here as the `<code>:<direction>:<detail>` reason
47
+ * prefix this module already uses for `map_driving_route_provider_error` and
48
+ * `stale_route_requery_error`. They are duplicated as literals on purpose: the
49
+ * gate must stay free of product callers, so nothing here imports it.
50
+ */
51
+ export const GROUND_TRANSFER_ROUTE_MODE_MISMATCH = 'mode_mismatch';
52
+ export const GROUND_TRANSFER_ROUTE_DIRECTION_MISMATCH = 'direction_mismatch';
53
+ /**
54
+ * Tolerance for verifying a provider's echoed endpoint against the requested
55
+ * one: 1e-4 degrees ≈ 11 m of latitude. A provider legitimately snaps a
56
+ * coordinate to the nearest routable road node, so an exact string match would
57
+ * refuse honest answers; anything beyond this bound is a different place, not a
58
+ * snap. Deliberately tight — refusing falls back to the static estimate, which
59
+ * is the safe direction.
60
+ */
61
+ export const GROUND_TRANSFER_ECHO_TOLERANCE_DEG = 1e-4;
62
+ const GROUND_TRANSFER_CACHE_LIMIT = 32;
63
+ function asRecord(value) {
64
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
65
+ ? value
66
+ : null;
67
+ }
68
+ function coordinate(value) {
69
+ const record = asRecord(value);
70
+ const longitude = record?.['longitude'];
71
+ const latitude = record?.['latitude'];
72
+ if (typeof longitude !== 'number' || !Number.isFinite(longitude) || longitude < -180 || longitude > 180
73
+ || typeof latitude !== 'number' || !Number.isFinite(latitude) || latitude < -90 || latitude > 90)
74
+ return null;
75
+ return { longitude, latitude };
76
+ }
77
+ function coordinatePair(value) {
78
+ const record = asRecord(value);
79
+ if (!record)
80
+ return null;
81
+ const origin = coordinate(record['origin']);
82
+ const destination = coordinate(record['destination']);
83
+ if (origin === null || destination === null)
84
+ return null;
85
+ return { origin, destination };
86
+ }
87
+ function coordinateText(value) {
88
+ return `${String(value.longitude)},${String(value.latitude)}`;
89
+ }
90
+ /** Parse a canonical `"lon,lat"` text back into a validated coordinate. */
91
+ function coordinateFromText(value) {
92
+ const parts = value.split(',');
93
+ if (parts.length !== 2)
94
+ return null;
95
+ const [longitudeText, latitudeText] = parts;
96
+ if (longitudeText.trim() === '' || latitudeText.trim() === '')
97
+ return null;
98
+ return coordinate({ longitude: Number(longitudeText), latitude: Number(latitudeText) });
99
+ }
100
+ /**
101
+ * Does a provider's echoed endpoint name the place that was requested?
102
+ *
103
+ * Compared within `GROUND_TRANSFER_ECHO_TOLERANCE_DEG` so a road-node snap still
104
+ * matches. An echo that cannot be parsed is NOT a match: present-but-unverifiable
105
+ * fails closed rather than being accepted as the requested pair.
106
+ */
107
+ function sameEndpoint(echoed, requested) {
108
+ const left = coordinateFromText(echoed);
109
+ const right = coordinateFromText(requested);
110
+ if (left === null || right === null)
111
+ return false;
112
+ return Math.abs(left.longitude - right.longitude) <= GROUND_TRANSFER_ECHO_TOLERANCE_DEG
113
+ && Math.abs(left.latitude - right.latitude) <= GROUND_TRANSFER_ECHO_TOLERANCE_DEG;
114
+ }
115
+ /**
116
+ * Normalize one of the provider's OWN optional claims into a comparable string.
117
+ *
118
+ * Absent (`undefined` / `null`) stays absent — that is the wired driving tool and
119
+ * its behaviour is unchanged. A present-but-unusable value is NOT dropped: it is
120
+ * carried as a non-empty string so the enforcement below can refuse it, because
121
+ * silently dropping a contradicting claim is exactly the relabel this seam
122
+ * forbids. A `{ longitude, latitude }` object is accepted as the canonical text.
123
+ */
124
+ function declaredClaim(value) {
125
+ if (value === undefined || value === null)
126
+ return undefined;
127
+ if (typeof value === 'string')
128
+ return value.trim() === '' ? '(blank)' : value.trim();
129
+ const asCoordinate = coordinate(value);
130
+ if (asCoordinate !== null)
131
+ return coordinateText(asCoordinate);
132
+ return typeof value === 'object' ? JSON.stringify(value) : String(value);
133
+ }
134
+ function cacheKey(direction) {
135
+ return JSON.stringify({
136
+ mode: GROUND_TRANSFER_MODE,
137
+ direction: direction.direction,
138
+ origin: direction.origin,
139
+ destination: direction.destination,
140
+ });
141
+ }
142
+ function nowMs(clock) {
143
+ const value = clock().getTime();
144
+ if (!Number.isFinite(value))
145
+ throw new Error('ground-transfer clock returned an invalid date');
146
+ return value;
147
+ }
148
+ function asOf(clock) {
149
+ return new Date(nowMs(clock)).toISOString();
150
+ }
151
+ /** Historical bound for an exposed provider failure string (unchanged). */
152
+ const GROUND_TRANSFER_FAULT_DETAIL_MAX_CHARS = 400;
153
+ /**
154
+ * Normalize a provider failure into an exposable label. The text reaches the tool
155
+ * result via `exposeGroundTransferEvidence`, so it is scrubbed of markup,
156
+ * credential assignments and URLs before anything else (#429 GAP-429-3); the
157
+ * historical length bound and empty-case wording are preserved.
158
+ */
159
+ function safeErrorMessage(value) {
160
+ const message = value instanceof Error ? value.message : String(value);
161
+ return sanitizeFaultDetail(message, {
162
+ maxChars: GROUND_TRANSFER_FAULT_DETAIL_MAX_CHARS,
163
+ emptyPlaceholder: 'unknown provider error',
164
+ });
165
+ }
166
+ /** Bound for a provider-authored claim quoted inside a refusal reason. */
167
+ const GROUND_TRANSFER_CLAIM_DETAIL_MAX_CHARS = 120;
168
+ /**
169
+ * A provider's own claim (mode / echoed endpoint / provider id) is provider-authored
170
+ * text, and a refusal reason reaches the tool result via
171
+ * `exposeGroundTransferEvidence`. Quote it only through the shared sanitizer.
172
+ */
173
+ function safeClaim(value) {
174
+ return sanitizeFaultDetail(value, {
175
+ maxChars: GROUND_TRANSFER_CLAIM_DETAIL_MAX_CHARS,
176
+ emptyPlaceholder: '(absent)',
177
+ });
178
+ }
179
+ function staticCache(status = 'bypass') {
180
+ return { status, ageS: null, asOf: null };
181
+ }
182
+ function notAppliedBase(parts) {
183
+ return {
184
+ requestedMode: parts.requestedMode,
185
+ requestedPosition: parts.requestedPosition,
186
+ provenance: 'none',
187
+ asOf: null,
188
+ freshness: 'not_attempted',
189
+ cache: staticCache('bypass'),
190
+ evidenceClass: 'none',
191
+ };
192
+ }
193
+ function staticDirectionResolution(direction, staticMinutes, reason) {
194
+ return {
195
+ applied: false,
196
+ direction,
197
+ staticMinutes,
198
+ provenance: 'static-transfer-pack',
199
+ asOf: null,
200
+ freshness: 'fallback',
201
+ cache: staticCache('bypass'),
202
+ evidenceClass: 'static_transfer_estimate',
203
+ fallbackReason: reason,
204
+ };
205
+ }
206
+ function parseRequest(value) {
207
+ const record = asRecord(value);
208
+ if (!record) {
209
+ return {
210
+ candidateId: null,
211
+ transferIndex: null,
212
+ requestedMode: null,
213
+ requestedPosition: null,
214
+ outbound: null,
215
+ ret: null,
216
+ invalidReason: 'ground_transfer_request_invalid:expected an object',
217
+ };
218
+ }
219
+ const candidateId = typeof record['candidate_id'] === 'string' && record['candidate_id'].trim()
220
+ ? record['candidate_id']
221
+ : null;
222
+ const transferIndex = Number.isInteger(record['transfer_index']) && Number(record['transfer_index']) >= 0
223
+ ? Number(record['transfer_index'])
224
+ : null;
225
+ const requestedMode = typeof record['mode'] === 'string' && record['mode'].trim()
226
+ ? record['mode']
227
+ : null;
228
+ const requestedPosition = typeof record['position'] === 'string' && record['position'].trim()
229
+ ? record['position']
230
+ : null;
231
+ let outbound = null;
232
+ let ret = null;
233
+ if (record['outbound'] !== undefined || record['return'] !== undefined) {
234
+ outbound = coordinatePair(record['outbound']);
235
+ ret = coordinatePair(record['return']);
236
+ }
237
+ else {
238
+ // Legacy single-pair shape: outbound = origin/destination; return = the
239
+ // swapped pair. Keeps pre-#364 payloads behavior-compatible.
240
+ const legacyOrigin = coordinate(record['origin']);
241
+ const legacyDestination = coordinate(record['destination']);
242
+ if (legacyOrigin && legacyDestination) {
243
+ outbound = { origin: legacyOrigin, destination: legacyDestination };
244
+ ret = { origin: legacyDestination, destination: legacyOrigin };
245
+ }
246
+ }
247
+ let invalidReason;
248
+ if (candidateId === null)
249
+ invalidReason = 'ground_transfer_binding_invalid:candidate_id is required';
250
+ else if (transferIndex === null)
251
+ invalidReason = 'ground_transfer_binding_invalid:transfer_index must be a non-negative integer';
252
+ else if (requestedPosition !== GROUND_TRANSFER_POSITION)
253
+ invalidReason = `unsupported_ground_transfer_position:${requestedPosition ?? 'unknown'}`;
254
+ else if (requestedMode !== GROUND_TRANSFER_MODE)
255
+ invalidReason = `unsupported_ground_transfer_mode:${requestedMode ?? 'unknown'}`;
256
+ else if (outbound === null || ret === null)
257
+ invalidReason = 'invalid_ground_transfer_coordinates:longitude/latitude must be finite and in range';
258
+ return {
259
+ candidateId,
260
+ transferIndex,
261
+ requestedMode,
262
+ requestedPosition,
263
+ outbound,
264
+ ret,
265
+ invalidReason,
266
+ };
267
+ }
268
+ function completeRequest(parts) {
269
+ if (parts.invalidReason || parts.candidateId === null || parts.transferIndex === null
270
+ || parts.requestedMode !== GROUND_TRANSFER_MODE || parts.requestedPosition !== GROUND_TRANSFER_POSITION
271
+ || parts.outbound === null || parts.ret === null)
272
+ return null;
273
+ return {
274
+ candidateId: parts.candidateId,
275
+ transferIndex: parts.transferIndex,
276
+ mode: GROUND_TRANSFER_MODE,
277
+ position: GROUND_TRANSFER_POSITION,
278
+ outbound: { direction: 'outbound', origin: parts.outbound.origin, destination: parts.outbound.destination },
279
+ ret: { direction: 'return', origin: parts.ret.origin, destination: parts.ret.destination },
280
+ };
281
+ }
282
+ function parseRouteResult(value) {
283
+ const record = asRecord(value);
284
+ if (!record)
285
+ throw new Error('map_driving_route returned an invalid public result');
286
+ const provider = record?.['provider'];
287
+ const distanceM = record?.['distanceM'];
288
+ const durationS = record?.['durationS'];
289
+ if (typeof provider !== 'string' || provider.trim() === ''
290
+ || typeof distanceM !== 'number' || !Number.isFinite(distanceM) || distanceM < 0
291
+ || typeof durationS !== 'number' || !Number.isFinite(durationS) || durationS < 0
292
+ // A positive distance cannot be covered in zero time: such a response is
293
+ // a self-contradictory route fact, not a credible provider hit. It falls
294
+ // into the explicit provider-miss fallback instead of silently binding
295
+ // zero minutes into the solver.
296
+ || (distanceM > 0 && durationS === 0))
297
+ throw new Error('map_driving_route returned an invalid public result');
298
+ // The provider's own claims are CARRIED, never dropped: `routeClaimRefusal`
299
+ // below checks them when they exist. Absent stays absent (the wired driving
300
+ // tool sends none of the three), and re-parsing an already-parsed result is
301
+ // idempotent because the carried values are already canonical.
302
+ const declaredMode = declaredClaim(record['mode']);
303
+ const resolvedOrigin = declaredClaim(record['resolvedOrigin']);
304
+ const resolvedDestination = declaredClaim(record['resolvedDestination']);
305
+ return {
306
+ provider,
307
+ distanceM,
308
+ durationS,
309
+ ...(typeof record['polyline'] === 'string' ? { polyline: record['polyline'] } : {}),
310
+ ...(Array.isArray(record['steps']) ? { steps: record['steps'] } : {}),
311
+ ...(declaredMode !== undefined ? { mode: declaredMode } : {}),
312
+ ...(resolvedOrigin !== undefined ? { resolvedOrigin } : {}),
313
+ ...(resolvedDestination !== undefined ? { resolvedDestination } : {}),
314
+ };
315
+ }
316
+ /**
317
+ * Verify the provider's OWN claims against the request for this direction, and
318
+ * return a typed refusal when one contradicts it (#429 GAP-429-1/2).
319
+ *
320
+ * ABSENT = UNVERIFIABLE, and absent is ACCEPTED — not because an unverified
321
+ * answer is as good as a verified one, but because the only wired provider (the
322
+ * registered `map_driving_route` tool) is driving by construction and echoes no
323
+ * origin/destination, so for it nothing changes byte for byte. Any future
324
+ * non-driving or address-resolving adapter must supply these fields; the #429
325
+ * conformance gate already refuses an adapter that does not.
326
+ *
327
+ * PRESENT and contradicting = REFUSAL. The caller falls back to the static
328
+ * transfer estimate with its original price label, so a mislabelled or
329
+ * misrouted answer never reaches the solver.
330
+ */
331
+ function routeClaimRefusal(direction, request, route) {
332
+ if (route.mode !== undefined && route.mode !== GROUND_TRANSFER_MODE) {
333
+ return {
334
+ code: GROUND_TRANSFER_ROUTE_MODE_MISMATCH,
335
+ detail: `provider ${safeClaim(route.provider)} returned mode '${safeClaim(route.mode)}' for a '${GROUND_TRANSFER_MODE}' request; a declared mode is never relabelled as ${GROUND_TRANSFER_MODE}; static transfer preserved`,
336
+ };
337
+ }
338
+ const { resolvedOrigin, resolvedDestination } = route;
339
+ if (resolvedOrigin === undefined && resolvedDestination === undefined)
340
+ return null;
341
+ if ((resolvedOrigin !== undefined && !sameEndpoint(resolvedOrigin, request.origin))
342
+ || (resolvedDestination !== undefined && !sameEndpoint(resolvedDestination, request.destination))) {
343
+ return {
344
+ code: GROUND_TRANSFER_ROUTE_DIRECTION_MISMATCH,
345
+ detail: `provider ${safeClaim(route.provider)} resolved ${safeClaim(resolvedOrigin ?? '(absent)')}>${safeClaim(resolvedDestination ?? '(absent)')} but the ${direction.direction} request was ${request.origin}>${request.destination}; direction binding is verified against the response, not assumed from the request; static transfer preserved`,
346
+ };
347
+ }
348
+ return null;
349
+ }
350
+ function buildRouteFact(direction, route, clock, cache) {
351
+ return {
352
+ direction: direction.direction,
353
+ origin: direction.origin,
354
+ destination: direction.destination,
355
+ mode: GROUND_TRANSFER_MODE,
356
+ provider: route.provider,
357
+ distanceM: route.distanceM,
358
+ durationS: route.durationS,
359
+ durationMin: Math.round(route.durationS / 60),
360
+ asOf: asOf(clock),
361
+ provenance: 'map_driving_route',
362
+ freshness: cache.status === 'hit' ? 'cache_hit' : 'fresh',
363
+ cache,
364
+ evidenceClass: 'public_map_route_estimate',
365
+ trafficStatus: 'not-live-route-estimate',
366
+ };
367
+ }
368
+ function selectionFor(candidates, parts) {
369
+ if (parts.candidateId === null || parts.transferIndex === null)
370
+ return null;
371
+ const matching = candidates
372
+ .map((candidate, index) => ({ candidate, index }))
373
+ .filter(({ candidate }) => candidate.id === parts.candidateId);
374
+ if (matching.length !== 1)
375
+ return null;
376
+ const match = matching[0];
377
+ const transfer = match.candidate.destTransfers[parts.transferIndex];
378
+ if (!transfer || typeof transfer.mode !== 'string' || !Number.isFinite(transfer.minutes) || transfer.minutes < 0 || !Number.isFinite(transfer.priceCny) || transfer.priceCny < 0)
379
+ return null;
380
+ return {
381
+ candidateIndex: match.index,
382
+ selection: {
383
+ candidateId: parts.candidateId,
384
+ transferIndex: parts.transferIndex,
385
+ staticMode: transfer.mode,
386
+ staticMinutes: transfer.minutes,
387
+ staticPriceCny: transfer.priceCny,
388
+ },
389
+ };
390
+ }
391
+ async function resolveDirection(direction, staticMinutes, provider, clock, cache, maxEntries, context) {
392
+ const key = cacheKey(direction);
393
+ const currentMs = nowMs(clock);
394
+ const cached = cache.get(key);
395
+ if (cached) {
396
+ const ageS = Math.max(0, currentMs - cached.storedAtMs) / 1000;
397
+ if (ageS <= GROUND_TRANSFER_DEFAULT_MAX_AGE_S) {
398
+ const hitCache = { status: 'hit', ageS, asOf: cached.fact.asOf };
399
+ const hitFact = { ...cached.fact, freshness: 'cache_hit', cache: hitCache };
400
+ return {
401
+ applied: true,
402
+ direction: direction.direction,
403
+ minutes: hitFact.durationMin,
404
+ staticMinutes,
405
+ provenance: 'map_driving_route',
406
+ asOf: hitFact.asOf,
407
+ freshness: 'cache_hit',
408
+ cache: hitCache,
409
+ evidenceClass: 'public_map_route_estimate',
410
+ routeFact: hitFact,
411
+ };
412
+ }
413
+ }
414
+ const requestForProvider = {
415
+ origin: coordinateText(direction.origin),
416
+ destination: coordinateText(direction.destination),
417
+ mode: GROUND_TRANSFER_MODE,
418
+ };
419
+ try {
420
+ const raw = await provider(requestForProvider, {
421
+ signal: context.signal ?? new AbortController().signal,
422
+ execution: context.execution,
423
+ });
424
+ const route = parseRouteResult(raw);
425
+ const refusal = routeClaimRefusal(direction, requestForProvider, route);
426
+ if (refusal !== null) {
427
+ // Fail closed: no fact is built and nothing is written to the cache, so a
428
+ // refused answer can never be served later as a cache hit. The static
429
+ // minutes, price and `[静态包:估算]` label are left untouched.
430
+ return {
431
+ applied: false,
432
+ direction: direction.direction,
433
+ staticMinutes,
434
+ provenance: 'static-transfer-pack',
435
+ asOf: null,
436
+ freshness: 'fallback',
437
+ cache: staticCache(cached ? 'stale' : 'bypass'),
438
+ evidenceClass: 'static_transfer_estimate',
439
+ fallbackReason: `${refusal.code}:${direction.direction}:${refusal.detail}`,
440
+ };
441
+ }
442
+ const cacheInfo = {
443
+ status: cached ? 'requery' : 'miss',
444
+ ageS: 0,
445
+ asOf: null,
446
+ };
447
+ const fact = buildRouteFact(direction, route, clock, cacheInfo);
448
+ cacheInfo.asOf = fact.asOf;
449
+ const entry = { fact, storedAtMs: currentMs };
450
+ if (cache.size >= maxEntries && !cache.has(key)) {
451
+ const oldest = cache.keys().next().value;
452
+ if (typeof oldest === 'string')
453
+ cache.delete(oldest);
454
+ }
455
+ cache.set(key, entry);
456
+ return {
457
+ applied: true,
458
+ direction: direction.direction,
459
+ minutes: fact.durationMin,
460
+ staticMinutes,
461
+ provenance: 'map_driving_route',
462
+ asOf: fact.asOf,
463
+ freshness: 'fresh',
464
+ cache: cacheInfo,
465
+ evidenceClass: 'public_map_route_estimate',
466
+ routeFact: fact,
467
+ };
468
+ }
469
+ catch (error) {
470
+ const detail = safeErrorMessage(error);
471
+ return {
472
+ applied: false,
473
+ direction: direction.direction,
474
+ staticMinutes,
475
+ provenance: 'static-transfer-pack',
476
+ asOf: null,
477
+ freshness: 'fallback',
478
+ cache: staticCache(cached ? 'stale' : 'bypass'),
479
+ evidenceClass: 'static_transfer_estimate',
480
+ fallbackReason: cached
481
+ ? `stale_route_requery_error:${direction.direction}:${detail}`
482
+ : `map_driving_route_provider_error:${direction.direction}:${detail}`,
483
+ };
484
+ }
485
+ }
486
+ export function createGroundTransferResolver(options) {
487
+ const clock = options.clock ?? (() => new Date());
488
+ const maxEntries = Number.isInteger(options.maxEntries) && Number(options.maxEntries) > 0
489
+ ? Number(options.maxEntries)
490
+ : GROUND_TRANSFER_CACHE_LIMIT;
491
+ const cache = new Map();
492
+ return {
493
+ async resolve(request, selection, context = {}) {
494
+ const [outbound, ret] = await Promise.all([
495
+ resolveDirection(request.outbound, selection.staticMinutes, options.provider, clock, cache, maxEntries, context),
496
+ resolveDirection(request.ret, selection.staticMinutes, options.provider, clock, cache, maxEntries, context),
497
+ ]);
498
+ const applied = outbound.applied || ret.applied;
499
+ // Aggregate fields are a summary only: per-direction objects above are
500
+ // the authoritative per-direction record. A full cache hit keeps the
501
+ // legacy aggregate semantics ('cache_hit'), a re-query keeps 'requery'.
502
+ const aggregateProvenance = applied ? 'map_driving_route' : 'static-transfer-pack';
503
+ const aggregateEvidenceClass = applied ? 'public_map_route_estimate' : 'static_transfer_estimate';
504
+ const aggregateFreshness = !applied
505
+ ? 'fallback'
506
+ : outbound.freshness === 'fresh' || ret.freshness === 'fresh'
507
+ ? 'fresh'
508
+ : 'cache_hit';
509
+ const statuses = [outbound.cache.status, ret.cache.status];
510
+ const aggregateCache = !applied
511
+ ? staticCache('bypass')
512
+ : {
513
+ status: statuses.includes('hit') ? 'hit' : statuses.includes('requery') ? 'requery' : 'miss',
514
+ ageS: 0,
515
+ asOf: null,
516
+ };
517
+ const aggregateAsOf = applied ? (outbound.asOf ?? ret.asOf) : null;
518
+ const resolution = {
519
+ applied,
520
+ candidateId: selection.candidateId,
521
+ transferIndex: selection.transferIndex,
522
+ requestedMode: request.mode,
523
+ requestedPosition: request.position,
524
+ staticMode: selection.staticMode,
525
+ staticMinutes: selection.staticMinutes,
526
+ priceCny: selection.staticPriceCny,
527
+ priceEvidence: GROUND_TRANSFER_STATIC_PRICE_EVIDENCE,
528
+ provenance: aggregateProvenance,
529
+ asOf: aggregateAsOf,
530
+ freshness: aggregateFreshness,
531
+ cache: aggregateCache,
532
+ evidenceClass: aggregateEvidenceClass,
533
+ outbound,
534
+ return: ret,
535
+ };
536
+ if (outbound.applied)
537
+ resolution.outboundMinutes = outbound.minutes;
538
+ if (ret.applied)
539
+ resolution.returnMinutes = ret.minutes;
540
+ if (!applied) {
541
+ resolution.fallbackReason = `both_directions_failed:${outbound.fallbackReason ?? 'unknown'};${ret.fallbackReason ?? 'unknown'}`;
542
+ }
543
+ return resolution;
544
+ },
545
+ };
546
+ }
547
+ /**
548
+ * Delegate through the registered public map tool. The dsh-tools types expose
549
+ * nested execution explicitly, so the current root/agent/signal are carried
550
+ * into the sub-dispatch instead of calling a private map client.
551
+ */
552
+ export function createPublicMapDrivingRouteProvider(ctx) {
553
+ return async (request, context) => {
554
+ const execution = context.execution;
555
+ if (!execution)
556
+ throw new Error('GROUND_TRANSFER_NESTED_EXECUTION_UNSUPPORTED: current tool execution context is unavailable');
557
+ const tools = ctx.tools;
558
+ if (typeof tools?.execute !== 'function' || typeof tools?.get !== 'function') {
559
+ throw new Error('GROUND_TRANSFER_NESTED_EXECUTION_UNSUPPORTED: host must expose dsh-tools ToolRuntime.execute/get');
560
+ }
561
+ if (!tools.get('map_driving_route', execution.agent)) {
562
+ throw new Error('GROUND_TRANSFER_PUBLIC_MAP_TOOL_UNAVAILABLE: map_driving_route is not registered in the current tool scope');
563
+ }
564
+ const nested = {
565
+ callId: ToolCallId(`${String(execution.callId)}:ground-transfer`),
566
+ rootCallId: execution.rootCallId,
567
+ name: 'map_driving_route',
568
+ arguments: { origin: request.origin, destination: request.destination },
569
+ ...(execution.agent !== undefined ? { agent: execution.agent } : {}),
570
+ parent: execution.token,
571
+ signal: execution.signal,
572
+ };
573
+ const result = await tools.execute(nested);
574
+ if (result.isError)
575
+ throw new Error(`map_driving_route failed: ${result.error.message}`);
576
+ return parseRouteResult(result.value);
577
+ };
578
+ }
579
+ /** Resolve and patch exactly one named transfer position before solver entry. */
580
+ export async function resolveGroundTransferPayload(rawRequest, candidates, resolver, context) {
581
+ const parts = parseRequest(rawRequest);
582
+ const bound = selectionFor(candidates, parts);
583
+ if (!bound) {
584
+ const base = notAppliedBase(parts);
585
+ return {
586
+ candidates: [...candidates],
587
+ resolution: {
588
+ ...base,
589
+ applied: false,
590
+ ...(parts.candidateId !== null ? { candidateId: parts.candidateId } : {}),
591
+ ...(parts.transferIndex !== null ? { transferIndex: parts.transferIndex } : {}),
592
+ outbound: staticDirectionResolution('outbound', Number.NaN, 'ground_transfer_binding_mismatch'),
593
+ return: staticDirectionResolution('return', Number.NaN, 'ground_transfer_binding_mismatch'),
594
+ fallbackReason: 'ground_transfer_binding_mismatch: candidate_id and transfer_index must identify exactly one valid static transfer',
595
+ },
596
+ };
597
+ }
598
+ const complete = completeRequest(parts);
599
+ if (!complete) {
600
+ return {
601
+ candidates: [...candidates],
602
+ resolution: {
603
+ applied: false,
604
+ candidateId: bound.selection.candidateId,
605
+ transferIndex: bound.selection.transferIndex,
606
+ requestedMode: parts.requestedMode,
607
+ requestedPosition: parts.requestedPosition,
608
+ staticMode: bound.selection.staticMode,
609
+ staticMinutes: bound.selection.staticMinutes,
610
+ priceCny: bound.selection.staticPriceCny,
611
+ priceEvidence: GROUND_TRANSFER_STATIC_PRICE_EVIDENCE,
612
+ provenance: 'static-transfer-pack',
613
+ asOf: null,
614
+ freshness: 'fallback',
615
+ cache: staticCache('bypass'),
616
+ evidenceClass: 'static_transfer_estimate',
617
+ outbound: staticDirectionResolution('outbound', bound.selection.staticMinutes, parts.invalidReason ?? 'ground_transfer_request_invalid'),
618
+ return: staticDirectionResolution('return', bound.selection.staticMinutes, parts.invalidReason ?? 'ground_transfer_request_invalid'),
619
+ fallbackReason: `${parts.invalidReason ?? 'ground_transfer_request_invalid'}; static transfer minutes and price preserved`,
620
+ },
621
+ };
622
+ }
623
+ if (bound.selection.staticMode !== GROUND_TRANSFER_STATIC_MODE) {
624
+ const reason = `${GROUND_TRANSFER_STATIC_MODE_MISMATCH}: mode=${bound.selection.staticMode}; only taxi accepts a driving route; static transfer preserved`;
625
+ return {
626
+ candidates: [...candidates],
627
+ resolution: {
628
+ applied: false,
629
+ candidateId: bound.selection.candidateId,
630
+ transferIndex: bound.selection.transferIndex,
631
+ requestedMode: parts.requestedMode,
632
+ requestedPosition: parts.requestedPosition,
633
+ staticMode: bound.selection.staticMode,
634
+ staticMinutes: bound.selection.staticMinutes,
635
+ priceCny: bound.selection.staticPriceCny,
636
+ priceEvidence: GROUND_TRANSFER_STATIC_PRICE_EVIDENCE,
637
+ provenance: 'static-transfer-pack',
638
+ asOf: null,
639
+ freshness: 'not_attempted',
640
+ cache: staticCache('bypass'),
641
+ evidenceClass: 'static_transfer_estimate',
642
+ outbound: staticDirectionResolution('outbound', bound.selection.staticMinutes, reason),
643
+ return: staticDirectionResolution('return', bound.selection.staticMinutes, reason),
644
+ fallbackReason: reason,
645
+ },
646
+ };
647
+ }
648
+ const resolution = await resolver.resolve(complete, bound.selection, context);
649
+ if (!resolution.applied) {
650
+ return { candidates: [...candidates], resolution };
651
+ }
652
+ const patched = candidates.map((candidate, candidateIndex) => {
653
+ if (candidateIndex !== bound.candidateIndex)
654
+ return candidate;
655
+ const destTransfers = candidate.destTransfers.map((transfer, transferIndex) => {
656
+ if (transferIndex !== bound.selection.transferIndex)
657
+ return transfer;
658
+ const next = { ...transfer };
659
+ if (resolution.outboundMinutes !== undefined)
660
+ next['minutesOut'] = resolution.outboundMinutes;
661
+ if (resolution.returnMinutes !== undefined)
662
+ next['minutesRet'] = resolution.returnMinutes;
663
+ return next;
664
+ });
665
+ return { ...candidate, destTransfers };
666
+ });
667
+ return { candidates: patched, resolution };
668
+ }
669
+ export function exposeGroundTransferEvidence(result, resolution) {
670
+ const verdicts = Array.isArray(result['verdicts'])
671
+ ? result['verdicts'].map(verdict => resolution.candidateId !== undefined && verdict['candidate_id'] === resolution.candidateId
672
+ ? { ...verdict, transfer_evidence: resolution }
673
+ : verdict)
674
+ : result['verdicts'];
675
+ return { ...result, verdicts, ground_transfer: resolution };
676
+ }