@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,181 @@
1
+ /**
2
+ * 携程机票站点适配器(RFC §3.2 首个适配器;PoC 已识别接口面,data-sources.md §8):
3
+ * - entry:URL 参数直开(https://flights.ctrip.com/online/list/oneway-{from}-{to}?depdate=YYYY-MM-DD)
4
+ * - networkHints:主搜索接口 search/api/search/batchSearch(POST,~550KB,国内票同走)
5
+ * - 解析:flightItineraryList[].flightSegments[0].flightList[0] + priceList 最小 adultPrice
6
+ * (schema 实测 2026-08-28,见 data-sources.md §8)
7
+ * 只读:适配器不含任何提交/预订语义;URL 直开即零 DOM 交互。
8
+ */
9
+
10
+ /** 城市三字码表(小起步集;词表外 unresolved 逐字保留,不做开放式猜测——ADR-12 同款边界) */
11
+ const CITY_CODES: Record<string, string> = {
12
+ 上海: 'sha', 北京: 'bjs', 广州: 'can', 深圳: 'szx', 成都: 'ctu', 昆明: 'kmg',
13
+ 大理: 'dlu', 丽江: 'ljg', 西安: 'sia', 杭州: 'hgh', 三亚: 'syx', 厦门: 'xmn',
14
+ 重庆: 'cqg', 青岛: 'taa', 长沙: 'csx', 武汉: 'wuh', 南京: 'nkg', 郑州: 'cgo',
15
+ 贵阳: 'kwe', 桂林: 'kwl', 西双版纳: 'jhg', 香格里拉: 'dig',
16
+ }
17
+
18
+ export interface AdapterEntry {
19
+ ok: boolean
20
+ url?: string
21
+ /** 词表外城市逐字保留(调用方降级无日期/无线路搜索) */
22
+ unresolved?: string[]
23
+ }
24
+
25
+ export function buildEntryUrl(from: string, to: string, depDate: string): AdapterEntry {
26
+ const unresolved: string[] = []
27
+ const fromCode = CITY_CODES[from]
28
+ const toCode = CITY_CODES[to]
29
+ if (!fromCode) unresolved.push(from)
30
+ if (!toCode) unresolved.push(to)
31
+ if (unresolved.length > 0 || !/^\d{4}-\d{2}-\d{2}$/.test(depDate)) {
32
+ return { ok: false, unresolved: unresolved.length > 0 ? unresolved : [depDate] }
33
+ }
34
+ return { ok: true, url: `https://flights.ctrip.com/online/list/oneway-${fromCode}-${toCode}?depdate=${depDate}` }
35
+ }
36
+
37
+ /** networkHints:响应 URL 命中即视为搜索回包(对 UI 改版免疫,只怕接口改版) */
38
+ export const NETWORK_HINTS = [/search\/api\/search\/batchSearch/]
39
+
40
+ /**
41
+ * 登录态检测(用户自己的账号,不是匿名实例——founder 2026-08-28 纠偏):
42
+ * 任一登录票据 cookie 存在即视为已登录;名单基于公开常识,首个真登录后校准(D-13)。
43
+ */
44
+ export const LOGIN_COOKIE_NAMES = ['cticket', 'uid', 'uname', 'passport']
45
+ export const SITE_DOMAIN = '.ctrip.com'
46
+
47
+ export interface SessionFlightOption {
48
+ flightNo: string
49
+ airline: string
50
+ depDateTime: string
51
+ arrDateTime: string
52
+ depAirport: string
53
+ arrAirport: string
54
+ durationMin: number
55
+ price: number
56
+ aircraft?: string
57
+ }
58
+
59
+ /** 解析结果的三态判语(issue #279):空响应不再一律 miss——已识别合法空 = miss,
60
+ * 形状未识别(malformed/unknown)= error,选项命中 = hit。误把任意 [] 判 miss 会把未知
61
+ * 响应错误收敛为「这条线路没有航班」,这是上游接口改版/协议变动期的常见陷阱 */
62
+ export type BatchSearchVerdict = 'hit' | 'miss' | 'error'
63
+ /** Fixed, value-free envelope classes for redacted transport evidence. */
64
+ export type BatchSearchShape =
65
+ | 'invalid_json'
66
+ | 'root_not_object'
67
+ | 'data_not_object'
68
+ | 'itinerary_list_not_array'
69
+ | 'itinerary_list_empty'
70
+ | 'itinerary_rows_unusable'
71
+ | 'itinerary_rows_usable'
72
+
73
+ export interface BatchSearchResult {
74
+ options: SessionFlightOption[]
75
+ verdict: BatchSearchVerdict
76
+ shape: BatchSearchShape
77
+ }
78
+
79
+ /** 安全取字符串字段(任意来源字段都可能是 null/undefined/数字/对象) */
80
+ function asString(v: unknown): string {
81
+ return typeof v === 'string' ? v : ''
82
+ }
83
+
84
+ /** 安全取正数(无法解析按 0 返,绝不伪造价格) */
85
+ function asPositiveNumber(v: unknown): number {
86
+ return typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : 0
87
+ }
88
+
89
+ /** 解析 batchSearch 响应(纯函数,fixture 测试锚点);malformed 一律返空,不抛错 */
90
+ export function parseBatchSearch(body: string): SessionFlightOption[] {
91
+ return parseBatchSearchResult(body).options
92
+ }
93
+
94
+ /**
95
+ * 结构化解析(issue #279):返回选项 + 三态判语。
96
+ * - `hit` = 已识别合法结构 + 至少一个有效行程
97
+ * - `miss` = 已识别合法空(data.flightItineraryList 是空数组)
98
+ * - `error`= 形状未识别(JSON 解析失败 / 非对象根 / data 缺失或非对象 /
99
+ * flightItineraryList 不是数组 / 非空数组没有可用行程)——未知响应
100
+ * 不可静默收敛为 miss
101
+ * 绝不发明价格、航班号、机场、时刻;混合数组保留有效项,全畸形数组报 error。
102
+ */
103
+ export function parseBatchSearchResult(body: string): BatchSearchResult {
104
+ let raw: unknown
105
+ try {
106
+ raw = JSON.parse(body)
107
+ } catch {
108
+ return { options: [], verdict: 'error', shape: 'invalid_json' }
109
+ }
110
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
111
+ return { options: [], verdict: 'error', shape: 'root_not_object' }
112
+ }
113
+ const data = (raw as { data?: unknown }).data
114
+ if (data === null || typeof data !== 'object' || Array.isArray(data)) {
115
+ return { options: [], verdict: 'error', shape: 'data_not_object' }
116
+ }
117
+ const list = (raw as { data: { flightItineraryList?: unknown } }).data.flightItineraryList
118
+ if (!Array.isArray(list)) {
119
+ return { options: [], verdict: 'error', shape: 'itinerary_list_not_array' }
120
+ }
121
+ const out: SessionFlightOption[] = []
122
+ for (const it of list) {
123
+ if (it === null || typeof it !== 'object' || Array.isArray(it)) continue
124
+ const item = it as { flightSegments?: unknown; priceList?: unknown }
125
+ const segs = item.flightSegments
126
+ if (!Array.isArray(segs) || segs.length === 0) continue
127
+ const seg = segs[0]
128
+ if (seg === null || typeof seg !== 'object' || Array.isArray(seg)) continue
129
+ const segObj = seg as { airlineName?: unknown; duration?: unknown; flightList?: unknown }
130
+ const fl = segObj.flightList
131
+ if (!Array.isArray(fl) || fl.length === 0) continue
132
+ const flight = fl[0]
133
+ if (flight === null || typeof flight !== 'object' || Array.isArray(flight)) continue
134
+ const f = flight as {
135
+ flightNo?: unknown
136
+ departureAirportName?: unknown
137
+ arrivalAirportName?: unknown
138
+ departureDateTime?: unknown
139
+ arrivalDateTime?: unknown
140
+ aircraftName?: unknown
141
+ }
142
+ if (typeof f.flightNo !== 'string' || !f.flightNo) continue
143
+ if (typeof f.departureDateTime !== 'string' || !f.departureDateTime) continue
144
+ // 缺 priceList 延续旧合同为「有航班、价格未知」;显式非数组与畸形价项
145
+ // 属未知响应,整项跳过。若响应里没有其他有效项,最终判 error 而非 miss。
146
+ if (item.priceList !== undefined && !Array.isArray(item.priceList)) continue
147
+ const priceList = item.priceList ?? []
148
+ const prices: number[] = []
149
+ let malformedPrice = false
150
+ for (const p of priceList) {
151
+ if (p === null || typeof p !== 'object' || Array.isArray(p)) {
152
+ malformedPrice = true
153
+ break
154
+ }
155
+ const adultPrice = (p as { adultPrice?: unknown }).adultPrice
156
+ if (adultPrice === undefined) continue
157
+ if (typeof adultPrice !== 'number' || !Number.isFinite(adultPrice)) {
158
+ malformedPrice = true
159
+ break
160
+ }
161
+ if (adultPrice > 0) prices.push(adultPrice)
162
+ }
163
+ if (malformedPrice) continue
164
+ out.push({
165
+ flightNo: f.flightNo,
166
+ airline: asString(segObj.airlineName),
167
+ depDateTime: asString(f.departureDateTime),
168
+ arrDateTime: asString(f.arrivalDateTime),
169
+ depAirport: asString(f.departureAirportName),
170
+ arrAirport: asString(f.arrivalAirportName),
171
+ durationMin: asPositiveNumber(segObj.duration),
172
+ price: prices.length > 0 ? Math.min(...prices) : 0,
173
+ aircraft: typeof f.aircraftName === 'string' ? f.aircraftName : undefined,
174
+ })
175
+ }
176
+ return {
177
+ options: out,
178
+ verdict: out.length > 0 ? 'hit' : list.length === 0 ? 'miss' : 'error',
179
+ shape: out.length > 0 ? 'itinerary_rows_usable' : list.length === 0 ? 'itinerary_list_empty' : 'itinerary_rows_unusable',
180
+ }
181
+ }
@@ -0,0 +1,238 @@
1
+ /**
2
+ * 携程酒店站点适配器(2026-09-03 迪拜 session 复盘:账号会话面此前只有机票,
3
+ * 用户要「携程找酒店」时被迫撞 flyai 429 与打码 web 读页;会话面酒店从
4
+ * 「备份」实装为通道之一,rfc §2.2 同款只读纪律)。
5
+ *
6
+ * - entry:https://hotels.ctrip.com/hotels/list?city=<id>&checkin=&checkout=&adult=N
7
+ * - networkHints:酒店检索 XHR 的 URL 形态(接口名公开资料多版并存,**首个真会话
8
+ * 后校准**——D-13 同款边界);URL hint 未命中时由 content-main 的**形状嗅探**
9
+ * 兜底(响应 JSON 含酒店清单签名即转发),对接口改名免疫
10
+ * - 解析:走形(walk)JSON 找「名字 + 价格」签名的条目数组,归一化最小字段;
11
+ * 页面/接口 JSON 是不可信输入(RFC §3.5)——本层只归形状,语义判定在工具层
12
+ *
13
+ * 只读:适配器不含任何提交/预订语义;URL 直开即零 DOM 交互;ReadGuard 对酒店
14
+ * 页面照常生效(下单/支付面 URL 仍被物理拦截)。
15
+ */
16
+
17
+ /** 城市码表(**实测校准 2026-09-03**:每条 id 均经 hotels.ctrip.com list 页
18
+ * <title> 验证——探测法曾纠出 104=平遥县(传猜成都)等 5 处错猜,表内只收
19
+ * 验证过的 id;词表外 unresolved 逐字保留,调用方可显式传 cityId 覆盖) */
20
+ const HOTEL_CITY_CODES: Record<string, string> = {
21
+ 上海: '2', 北京: '1', 广州: '32', 深圳: '30', 成都: '28',
22
+ 杭州: '17', 南京: '12', 苏州: '14', 无锡: '13', 扬州: '15', 镇江: '16',
23
+ 青岛: '7', 厦门: '25', 珠海: '31', 三亚: '43', 海口: '42',
24
+ 桂林: '33', 昆明: '34', 大理: '36', 丽江: '37', 西双版纳: '35',
25
+ 贵阳: '38', 拉萨: '41', 乌鲁木齐: '39', 太原: '105', 长春: '158', 南通: '82',
26
+ 敦煌: '11', 舟山: '19', 张家界: '27', 黄山市: '23', 九江: '24', 武夷山: '26',
27
+ 迪拜: '220',
28
+ }
29
+
30
+ export interface AdapterEntry {
31
+ ok: boolean
32
+ url?: string
33
+ /** 词表外城市逐字保留(调用方提示:web 搜携程酒店 list 页取 city id 后带 cityId 重试) */
34
+ unresolved?: string[]
35
+ }
36
+
37
+ export interface HotelEntryQuery {
38
+ /** 目的地(中文);词表外须配 cityId */
39
+ to: string
40
+ /** 显式城市 id(携程/trip.com 酒店 list 页 URL 的 city= 数字;覆盖码表) */
41
+ cityId?: number | string
42
+ /** YYYY-MM-DD */
43
+ checkIn?: string
44
+ /** YYYY-MM-DD(与 checkIn 成对) */
45
+ checkOut?: string
46
+ adults?: number
47
+ }
48
+
49
+ export function buildHotelEntryUrl(q: HotelEntryQuery): AdapterEntry {
50
+ const unresolved: string[] = []
51
+ const cityId = String(q.cityId ?? '').trim() || HOTEL_CITY_CODES[q.to.trim()]
52
+ if (!cityId) unresolved.push(q.to)
53
+ if (unresolved.length > 0) {
54
+ return { ok: false, unresolved }
55
+ }
56
+ const params = new URLSearchParams({ city: cityId })
57
+ if (q.checkIn) params.set('checkin', q.checkIn)
58
+ if (q.checkOut) params.set('checkout', q.checkOut)
59
+ if (q.adults && q.adults > 0) params.set('adult', String(q.adults))
60
+ return { ok: true, url: `https://hotels.ctrip.com/hotels/list?${params.toString()}` }
61
+ }
62
+
63
+ /** networkHints:酒店检索 XHR 的 URL 形态(restapi/soa2/34951/fetchHotelList
64
+ * 为 2026-09-03 自 list 页一方确认的现行接口;其余为多版并存口径;命中即读) */
65
+ export const HOTEL_NETWORK_HINTS = [
66
+ /hotels\.ctrip\.com\/(hotels\/api|domestic\/pc\/api)/i,
67
+ /GetHotelListBySOA|GetHotelListByCity|HotelSearch|hotelsearch/i,
68
+ /restapi\/soa2\/\d+\/fetchHotelList/i,
69
+ ]
70
+
71
+ /** 形状嗅探签名:URL hint 未命中时的兜底(对接口改名免疫);大小上限由调用方先把关 */
72
+ export function looksLikeHotelListBody(body: string): boolean {
73
+ if (!body || body.length > 2_000_000) return false
74
+ return /"hotelList"|"hotelMatchInfos"|"hotelName"/.test(body)
75
+ }
76
+
77
+ /** 酒店 page 域(content_scripts 注入面与 background 白名单的对账源) */
78
+ export const HOTEL_SITE_HOST = 'hotels.ctrip.com'
79
+
80
+ export interface SessionHotelOption {
81
+ /** 酒店名 */
82
+ name: string
83
+ /** 数字价(数值不可得时为 0;真实价以 jumpUrl 落地页为准) */
84
+ price: number
85
+ /** 价格原串(打码/区间等不可数值化的形态原样保留) */
86
+ priceRaw?: string
87
+ star?: number
88
+ /** 点评分(上游形态有数字有字符串,原样归一为字符串缺省) */
89
+ score?: string
90
+ address?: string
91
+ hotelId?: string
92
+ /** 酒店详情页跳转(由人完成预订;gotry 不碰) */
93
+ jumpUrl?: string
94
+ }
95
+
96
+ interface WalkCandidate {
97
+ name: string
98
+ price?: number
99
+ priceRaw?: string
100
+ star?: number
101
+ score?: string
102
+ address?: string
103
+ hotelId?: string
104
+ }
105
+
106
+ /** 条目签名:像不像一家酒店(名字类字段必有 + 价格类字段至少其一) */
107
+ function hotelSignature(o: Record<string, unknown>): WalkCandidate | null {
108
+ const name = (o.hotelName ?? o.name ?? o.hotelNameEn) as unknown
109
+ if (typeof name !== 'string' || !name.trim()) return null
110
+ let price: number | undefined
111
+ let priceRaw: string | undefined
112
+ // 顶层扁平价(数字/字符串直给;字符串价是打码/区间形态,原样保留不数值化)
113
+ if (typeof o.price === 'number' && o.price > 0) price = o.price
114
+ else if (typeof o.price === 'string' && o.price.trim()) priceRaw = o.price.trim()
115
+ const probe = (v: unknown, seen = new Set<unknown>()): void => {
116
+ if (v == null || typeof v !== 'object') return
117
+ if (seen.has(v)) return
118
+ seen.add(v)
119
+ for (const [k, child] of Object.entries(v as Record<string, unknown>)) {
120
+ if (/^(avgPrice|totalPrice|price|amount|total|startPrice)$/i.test(k) && typeof child === 'number' && child > 0 && price === undefined) price = child
121
+ else if (/^(price|priceDisplay|amountText)$/i.test(k) && typeof child === 'string' && child.trim() && priceRaw === undefined) priceRaw = child.trim()
122
+ else probe(child, seen)
123
+ }
124
+ }
125
+ probe(o.priceInfo)
126
+ const flatPrice = o.totalPrice ?? o.avgPrice ?? o.minPrice
127
+ if (typeof flatPrice === 'number' && flatPrice > 0 && price === undefined) price = flatPrice
128
+ const flatRaw = o.priceText ?? o.priceDisplay
129
+ if (typeof flatRaw === 'string' && flatRaw.trim() && priceRaw === undefined) priceRaw = flatRaw.trim()
130
+ if (price === undefined && priceRaw === undefined) return null
131
+ const starRaw = o.star ?? o.level ?? o.hotelStar
132
+ const star = typeof starRaw === 'number' && starRaw > 0 ? starRaw : Number.isFinite(Number(starRaw)) && Number(starRaw) > 0 ? Number(starRaw) : undefined
133
+ const scoreRaw = o.score ?? o.commentScore ?? o.reviewScore
134
+ const score = scoreRaw == null ? undefined : String(scoreRaw)
135
+ const pos = o.position as Record<string, unknown> | undefined
136
+ const address = (typeof pos?.address === 'string' ? pos.address : undefined) ?? (typeof o.address === 'string' ? o.address : undefined)
137
+ const hotelId = (typeof o.hotelId === 'number' || typeof o.hotelId === 'string' ? String(o.hotelId) : undefined)
138
+ ?? (typeof o.hotelIdStr === 'string' ? o.hotelIdStr : undefined)
139
+ return { name: name.trim(), price, priceRaw, star, score, address, hotelId }
140
+ }
141
+
142
+ /** 结构化候选:携程现行 list 形态(**一方校准 2026-09-03**,取自 list 页官方
143
+ * 前端代码反查 + SSR initListData 实测):
144
+ * - 条目 = hotelList[].hotelInfo{summary{hotelId,nameInfo{name,names[]},hotelStar{star},positionInfo},commentInfo{commentScore}}
145
+ * - 价格 = roomInfo[].priceInfo.price(多房型取最低;页面 room_price 即读此);
146
+ * priceToken 在而无 price = 加密价(fetchHotelListPrices 页面内存解密),
147
+ * 嗅探面拿不到明文——如实不报价,summary 指引到 jumpUrl 落地页
148
+ * - displayPrice(如 "¥468")作 priceRaw 兜底;通用 price/amount 子树探测殿后
149
+ * (直连复现 fetchHotelList 被 hotel-spider-defence 反爬 404——「让站点自己
150
+ * 发请求」正是会话桥的设计原因;官方前端为公开静态资产,路径自其中反查) */
151
+ function ctripStructuredCandidate(item: Record<string, unknown>): WalkCandidate | null {
152
+ const info = item.hotelInfo as Record<string, unknown> | undefined
153
+ const summary = (info?.summary ?? item) as Record<string, unknown>
154
+ const nameInfo = summary.nameInfo as Record<string, unknown> | undefined
155
+ const names = nameInfo?.names
156
+ const nameRaw = nameInfo?.name ?? (Array.isArray(names) && names.length > 0 ? names[0] : undefined) ?? summary.hotelName ?? summary.name
157
+ if (typeof nameRaw !== 'string' || !nameRaw.trim()) return null
158
+ // 价格:roomInfo[].priceInfo 官方路径优先(数值 price 取 min;displayPrice/字符串价作 priceRaw)
159
+ let price: number | undefined
160
+ let priceRaw: string | undefined
161
+ let encrypted = false
162
+ const rooms = info?.roomInfo ?? item.roomInfo
163
+ if (Array.isArray(rooms)) {
164
+ for (const room of rooms) {
165
+ if (room == null || typeof room !== 'object') continue
166
+ const pi = (room as Record<string, unknown>).priceInfo as Record<string, unknown> | undefined
167
+ if (!pi) continue
168
+ if (typeof pi.price === 'number' && pi.price > 0) price = price === undefined ? pi.price : Math.min(price, pi.price)
169
+ if (typeof pi.price === 'string' && pi.price.trim() && !priceRaw) priceRaw = pi.price.trim()
170
+ if (typeof pi.displayPrice === 'string' && pi.displayPrice.trim() && !priceRaw) priceRaw = pi.displayPrice.trim()
171
+ if (pi.priceToken != null && pi.price === undefined) encrypted = true
172
+ }
173
+ }
174
+ // 兜底:条目子树 price/amount 探测(SSR 形态 productInfo.priceInfo.price 等)
175
+ if (price === undefined && !priceRaw) {
176
+ const priceProbe = (v: unknown, depth: number, seen: Set<unknown>): void => {
177
+ if (price !== undefined || depth > 6 || v == null || typeof v !== 'object' || seen.has(v)) return
178
+ seen.add(v)
179
+ for (const [k, child] of Object.entries(v as Record<string, unknown>)) {
180
+ if (/^(price|avgPrice|totalPrice|minPrice|amount)$/i.test(k) && typeof child === 'number' && child > 0) { price = child; return }
181
+ if (/^(price|displayPrice|amountText)$/i.test(k) && typeof child === 'string' && child.trim()) { priceRaw = priceRaw ?? child.trim(); continue }
182
+ priceProbe(child, depth + 1, seen)
183
+ }
184
+ }
185
+ priceProbe(item, 0, new Set())
186
+ }
187
+ // 加密价(priceToken 在而无明文 price):条目保留,价如实为 0——不伪造任何价
188
+ if (price === undefined && !priceRaw && !encrypted) return null
189
+ const starOf = summary.hotelStar as Record<string, unknown> | undefined
190
+ const starRaw = starOf?.star ?? summary.star
191
+ const star = typeof starRaw === 'number' && starRaw > 0 ? starRaw : undefined
192
+ const scoreRaw = ((info?.commentInfo ?? summary.commentInfo) as Record<string, unknown> | undefined)?.commentScore
193
+ const pos = summary.positionInfo as Record<string, unknown> | undefined
194
+ const address = (typeof pos?.address === 'string' ? pos.address : undefined) ?? (typeof summary.address === 'string' ? summary.address : undefined)
195
+ const hotelId = summary.hotelId != null ? String(summary.hotelId) : undefined
196
+ return { name: nameRaw.trim(), price, priceRaw, star, score: scoreRaw == null ? undefined : String(scoreRaw), address, hotelId }
197
+ }
198
+
199
+ /** 走形:深找第一个酒店签名数组(纯函数,fixture 测试锚点);malformed 一律返空,不抛错 */
200
+ export function parseCtripHotelList(body: string, opts: { maxItems?: number } = {}): SessionHotelOption[] {
201
+ let raw: unknown
202
+ try {
203
+ raw = JSON.parse(body)
204
+ } catch {
205
+ return []
206
+ }
207
+ const out: SessionHotelOption[] = []
208
+ const maxItems = opts.maxItems ?? 20
209
+ const walk = (node: unknown, depth: number, seen: Set<unknown>): void => {
210
+ if (out.length >= maxItems || depth > 12 || node == null || typeof node !== 'object' || seen.has(node)) return
211
+ if (Array.isArray(node)) {
212
+ for (const item of node) {
213
+ if (out.length >= maxItems) return
214
+ if (item == null || typeof item !== 'object' || Array.isArray(item)) continue
215
+ const cand = hotelSignature(item as Record<string, unknown>) ?? ctripStructuredCandidate(item as Record<string, unknown>)
216
+ if (!cand) continue
217
+ out.push({
218
+ name: cand.name,
219
+ price: cand.price ?? 0,
220
+ priceRaw: cand.priceRaw,
221
+ star: cand.star,
222
+ score: cand.score,
223
+ address: cand.address,
224
+ hotelId: cand.hotelId,
225
+ jumpUrl: cand.hotelId ? `https://hotels.ctrip.com/hotel/${cand.hotelId}` : undefined,
226
+ })
227
+ }
228
+ return
229
+ }
230
+ seen.add(node)
231
+ for (const child of Object.values(node as Record<string, unknown>)) {
232
+ walk(child, depth + 1, seen)
233
+ if (out.length >= maxItems) return
234
+ }
235
+ }
236
+ walk(raw, 0, new Set())
237
+ return out
238
+ }