@danceiny/gotry 0.0.1-rc.8 → 0.2.0-rc.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (506) hide show
  1. package/README.md +172 -217
  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 +1744 -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 -49
  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 +135 -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 +546 -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 +968 -0
  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 +509 -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/resilience.js +191 -0
  41. package/dist/capabilities/session/action-cache.js +126 -0
  42. package/dist/capabilities/session/adapters/ctrip-flight.js +141 -0
  43. package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
  44. package/dist/capabilities/session/adapters/dida-portal.js +274 -0
  45. package/dist/capabilities/session/adapters/meituan-local.js +54 -0
  46. package/dist/capabilities/session/adapters/rail-12306.js +342 -0
  47. package/dist/capabilities/session/benchmark.js +189 -0
  48. package/dist/capabilities/session/bridge-ledger.js +224 -0
  49. package/dist/capabilities/session/extension-bridge.js +636 -0
  50. package/dist/capabilities/session/extension-channel.js +109 -0
  51. package/dist/capabilities/session/extension-distribution.js +230 -0
  52. package/dist/capabilities/session/extract.js +50 -0
  53. package/dist/capabilities/session/golden-score.js +114 -0
  54. package/dist/capabilities/session/health-watch.js +215 -0
  55. package/dist/capabilities/session/read-guard.js +107 -0
  56. package/dist/capabilities/session/static-flight-golden.js +150 -0
  57. package/dist/capabilities/session/transport.js +109 -0
  58. package/dist/capabilities/session/wizard.js +117 -0
  59. package/dist/capabilities/session-consent.js +178 -0
  60. package/dist/capabilities/session-login.js +170 -0
  61. package/dist/capabilities/session-search.js +686 -0
  62. package/dist/capabilities/spawn-bounded.js +203 -0
  63. package/dist/capabilities/sponsor-plugin.js +341 -0
  64. package/dist/capabilities/visa-policy.js +140 -0
  65. package/dist/capabilities/weather.js +243 -138
  66. package/dist/data/session-golden-20.json +25 -0
  67. package/dist/data/sf-golden-manifest.json +103 -0
  68. package/dist/data/sf-static-routes.json +91 -0
  69. package/dist/scripts/action-cache-tests.js +72 -0
  70. package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
  71. package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
  72. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  73. package/dist/scripts/agent-reach-error-tests.js +354 -0
  74. package/dist/scripts/agent-reach-tests.js +26 -18
  75. package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
  76. package/dist/scripts/anything-tests.js +116 -60
  77. package/dist/scripts/artifact-client-contract-tests.js +220 -0
  78. package/dist/scripts/artifacts-capability-tests.js +727 -0
  79. package/dist/scripts/async-collect.js +68 -10
  80. package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
  81. package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
  82. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
  83. package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
  84. package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
  85. package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
  86. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
  87. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
  88. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
  89. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
  90. package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
  91. package/dist/scripts/booking-copilot-dsh-warmer-proof.js +123 -0
  92. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
  93. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
  94. package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
  95. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
  96. package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
  97. package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
  98. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
  99. package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
  100. package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
  101. package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
  102. package/dist/scripts/booking-executor-tests.js +80 -0
  103. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  104. package/dist/scripts/booking-saga-tests.js +125 -0
  105. package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
  106. package/dist/scripts/bootstrap-tests.js +1479 -0
  107. package/dist/scripts/bridge-events-tests.js +239 -0
  108. package/dist/scripts/bridge-ledger-tests.js +428 -0
  109. package/dist/scripts/build-changelog.js +238 -0
  110. package/dist/scripts/build-metrics-report.js +331 -0
  111. package/dist/scripts/changelog-tests.js +118 -0
  112. package/dist/scripts/channel-probe-tests.js +103 -0
  113. package/dist/scripts/channel-probe.js +169 -0
  114. package/dist/scripts/channel-registry-tests.js +208 -0
  115. package/dist/scripts/companion-tests.js +67 -0
  116. package/dist/scripts/dida-cookie-probe.js +87 -0
  117. package/dist/scripts/dida-runner-stop-tests.js +311 -0
  118. package/dist/scripts/dida-sw-probe.js +114 -0
  119. package/dist/scripts/diff-test.js +17 -12
  120. package/dist/scripts/doctor-tests.js +564 -0
  121. package/dist/scripts/dsh-artifact-e2e.js +279 -0
  122. package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
  123. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  124. package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
  125. package/dist/scripts/dsh-runtime-closure.js +162 -0
  126. package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
  127. package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
  128. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  129. package/dist/scripts/effect-tests.js +539 -0
  130. package/dist/scripts/engine-run.js +1 -3
  131. package/dist/scripts/engine-tests.js +16 -10
  132. package/dist/scripts/evaluation-cadence-tests.js +174 -0
  133. package/dist/scripts/evaluation-contract-tests.js +268 -0
  134. package/dist/scripts/extension-distribution-cli.js +39 -0
  135. package/dist/scripts/extension-distribution-tests.js +443 -0
  136. package/dist/scripts/extension-tests.js +988 -0
  137. package/dist/scripts/external-event-tests.js +350 -0
  138. package/dist/scripts/fact-gate-tests.js +869 -0
  139. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  140. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  141. package/dist/scripts/flight-malformed-tests.js +159 -0
  142. package/dist/scripts/flyai-setup-tests.js +228 -0
  143. package/dist/scripts/flyai-setup-tool-tests.js +54 -0
  144. package/dist/scripts/flyai-tests.js +692 -0
  145. package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
  146. package/dist/scripts/fx-contract-tests.js +201 -0
  147. package/dist/scripts/g5-guard-tests.js +131 -0
  148. package/dist/scripts/g5-guard.js +189 -0
  149. package/dist/scripts/gen-lunar-anchors.js +106 -0
  150. package/dist/scripts/geo-atlas-tests.js +283 -0
  151. package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
  152. package/dist/scripts/gotry-try-demo-tests.js +79 -0
  153. package/dist/scripts/gotry-try-demo.js +49 -0
  154. package/dist/scripts/ground-transfer-tests.js +956 -0
  155. package/dist/scripts/hbcli-e2e-tests.js +159 -0
  156. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  157. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  158. package/dist/scripts/hbcli-tests.js +121 -69
  159. package/dist/scripts/health-watch-cli.js +73 -0
  160. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  161. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  162. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  163. package/dist/scripts/i18n-tests.js +41 -0
  164. package/dist/scripts/incident-tests.js +281 -87
  165. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  166. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  167. package/dist/scripts/issue-271-liveness-tests.js +569 -0
  168. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  169. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  170. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  171. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  172. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  173. package/dist/scripts/issue436-persisted-routing-e2e.js +247 -0
  174. package/dist/scripts/itinerary-artifact-tests.js +368 -0
  175. package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
  176. package/dist/scripts/itinerary-deck-export-tests.js +552 -0
  177. package/dist/scripts/itinerary-deck-tests.js +435 -0
  178. package/dist/scripts/itinerary-html-tests.js +426 -0
  179. package/dist/scripts/journey-tests.js +22 -27
  180. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  181. package/dist/scripts/kernel-manifest-gate.js +126 -0
  182. package/dist/scripts/kernel-manifest-tests.js +212 -0
  183. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  184. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  185. package/dist/scripts/kernel-manifest.js +369 -0
  186. package/dist/scripts/lavish-local-tests.js +1226 -0
  187. package/dist/scripts/lavish-product-tools-tests.js +537 -0
  188. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  189. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  190. package/dist/scripts/ledger-tests.js +480 -0
  191. package/dist/scripts/ledger-workflow-crash.js +32 -0
  192. package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
  193. package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
  194. package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
  195. package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
  196. package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
  197. package/dist/scripts/memory-capture-tests.js +242 -61
  198. package/dist/scripts/memory-decay-tests.js +49 -0
  199. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  200. package/dist/scripts/memory-lifecycle.js +196 -0
  201. package/dist/scripts/memory-metrics.js +29 -31
  202. package/dist/scripts/memory-value-report.js +631 -0
  203. package/dist/scripts/memory-value-tests.js +328 -0
  204. package/dist/scripts/metrics-report-tests.js +151 -0
  205. package/dist/scripts/model-override-e2e.js +137 -0
  206. package/dist/scripts/nightly-evidence-tests.js +161 -0
  207. package/dist/scripts/nightly-evidence.js +286 -0
  208. package/dist/scripts/nudge-digest.js +43 -42
  209. package/dist/scripts/observability-tests.js +381 -0
  210. package/dist/scripts/onboarding-tests.js +161 -0
  211. package/dist/scripts/opensky-check.js +18 -13
  212. package/dist/scripts/opensky-tests.js +28 -28
  213. package/dist/scripts/persona-surface-guard-tests.js +49 -0
  214. package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
  215. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  216. package/dist/scripts/price-drift-tests.js +340 -0
  217. package/dist/scripts/price-drift-watch.js +447 -0
  218. package/dist/scripts/probe-poi-tests.js +53 -45
  219. package/dist/scripts/product-metrics.js +483 -0
  220. package/dist/scripts/publish-preverify.js +110 -0
  221. package/dist/scripts/realtime-pricing-tests.js +76 -0
  222. package/dist/scripts/recall-tests.js +513 -0
  223. package/dist/scripts/replay-async.js +20 -18
  224. package/dist/scripts/replay-real.js +18 -18
  225. package/dist/scripts/replay.js +52 -82
  226. package/dist/scripts/session-attach-diagnose.js +31 -0
  227. package/dist/scripts/session-attach-poc.js +62 -0
  228. package/dist/scripts/session-benchmark.js +180 -0
  229. package/dist/scripts/session-dida-live-e2e.js +199 -0
  230. package/dist/scripts/session-extract-tests.js +60 -0
  231. package/dist/scripts/session-link-tests.js +478 -0
  232. package/dist/scripts/session-login.js +29 -0
  233. package/dist/scripts/session-tests.js +862 -0
  234. package/dist/scripts/session-zones-tests.js +358 -0
  235. package/dist/scripts/sf-live-benchmark.js +367 -0
  236. package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
  237. package/dist/scripts/sf-live-cli-tests.js +92 -0
  238. package/dist/scripts/sf-live-options.js +46 -0
  239. package/dist/scripts/sf-manifest-tests.js +30 -0
  240. package/dist/scripts/sf-manifest.js +33 -0
  241. package/dist/scripts/sf-soft-score-tests.js +67 -0
  242. package/dist/scripts/sf-summary-tests.js +324 -0
  243. package/dist/scripts/sf-summary.js +525 -0
  244. package/dist/scripts/share-tests.js +432 -0
  245. package/dist/scripts/skeleton-check.js +16 -14
  246. package/dist/scripts/skeleton-integration-test.js +28 -11
  247. package/dist/scripts/skills-contract-tests.js +51 -46
  248. package/dist/scripts/smoke-session-gate-tests.js +21 -0
  249. package/dist/scripts/smoke.js +703 -219
  250. package/dist/scripts/spawn-bounded-abort-tests.js +241 -0
  251. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  252. package/dist/scripts/state-cli-tests.js +261 -0
  253. package/dist/scripts/state-cli.js +585 -0
  254. package/dist/scripts/state-repair-cli.js +66 -0
  255. package/dist/scripts/state-repair-tests.js +140 -0
  256. package/dist/scripts/static-golden-tests.js +165 -0
  257. package/dist/scripts/time-eval-tests.js +210 -192
  258. package/dist/scripts/travel-timeline-tests.js +59 -0
  259. package/dist/scripts/turn-handoff-collect-tests.js +169 -0
  260. package/dist/scripts/turn-handoff-collect.js +161 -0
  261. package/dist/scripts/turn-policy-tests.js +55 -0
  262. package/dist/scripts/typed-contract-canary.js +176 -0
  263. package/dist/scripts/tz-resolver-sanity.js +50 -0
  264. package/dist/scripts/tz-resolver-tests.js +584 -0
  265. package/dist/scripts/unified-tests.js +23 -19
  266. package/dist/scripts/visa-policy-tests.js +62 -0
  267. package/dist/scripts/weather-tests.js +276 -41
  268. package/dist/scripts/wish-channel-gate-tests.js +54 -0
  269. package/dist/scripts/write-gate-tests.js +522 -0
  270. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  271. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  272. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  273. package/dist/scripts/z3-race-tests.js +41 -0
  274. package/dist/src/artifact-gate.js +829 -0
  275. package/dist/src/backend/kernel.js +91 -0
  276. package/dist/src/backend/modules/booking-copilot.js +92 -0
  277. package/dist/src/backend/modules/booking-executor.js +124 -0
  278. package/dist/src/backend/modules/session-search.js +551 -0
  279. package/dist/src/benchmark-agent-conformance.js +578 -0
  280. package/dist/src/benchmark-environment-bridge.js +515 -0
  281. package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
  282. package/dist/src/benchmark-tool-isolation.js +151 -0
  283. package/dist/src/bookable-facts.js +533 -0
  284. package/dist/src/booking-saga.js +97 -0
  285. package/dist/src/booking-surface/availability-policy.js +697 -0
  286. package/dist/src/booking-surface/booking-intent.js +43 -0
  287. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  288. package/dist/src/booking-surface/canonical-schema.js +116 -0
  289. package/dist/src/booking-surface/contracts.js +75 -0
  290. package/dist/src/booking-surface/dsh-planner.js +1854 -0
  291. package/dist/src/booking-surface/dsh-plugin.js +378 -0
  292. package/dist/src/booking-surface/dsh-worker.js +98 -0
  293. package/dist/src/booking-surface/error-codes.js +231 -0
  294. package/dist/src/booking-surface/index.js +9 -0
  295. package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
  296. package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
  297. package/dist/src/booking-surface/profile.js +24 -0
  298. package/dist/src/booking-surface/recovery-chain.js +367 -0
  299. package/dist/src/booking-surface/runtime.js +1968 -0
  300. package/dist/src/booking-surface/server.js +674 -0
  301. package/dist/src/booking-surface/startup.js +168 -0
  302. package/dist/src/booking-surface/validation.js +261 -0
  303. package/dist/src/bridge.js +20 -13
  304. package/dist/src/companions.js +86 -0
  305. package/dist/src/contracts.js +21 -43
  306. package/dist/src/dsh-llm.js +97 -111
  307. package/dist/src/engine.js +276 -193
  308. package/dist/src/evaluation-cadence.js +97 -0
  309. package/dist/src/evaluation-contracts.js +283 -0
  310. package/dist/src/flight-pack-adapter.js +54 -0
  311. package/dist/src/flight-pack-contract.js +2 -0
  312. package/dist/src/flyai-setup-tool.js +70 -0
  313. package/dist/src/gotry-backend.js +125 -0
  314. package/dist/src/hotel-date-gate.js +118 -0
  315. package/dist/src/i18n.js +88 -0
  316. package/dist/src/index.js +2305 -731
  317. package/dist/src/itinerary-deck.js +139 -0
  318. package/dist/src/itinerary-doc-shared.js +661 -0
  319. package/dist/src/itinerary-html.js +131 -0
  320. package/dist/src/journey.js +155 -108
  321. package/dist/src/lavish-tools.js +400 -0
  322. package/dist/src/ledger-repair-apply.js +538 -0
  323. package/dist/src/ledger-repair-plan.js +463 -0
  324. package/dist/src/loop.js +358 -162
  325. package/dist/src/memory-capture.js +180 -32
  326. package/dist/src/memory-decay.js +47 -0
  327. package/dist/src/memory-lifecycle.js +1310 -0
  328. package/dist/src/memory-utility.js +27 -40
  329. package/dist/src/mock-llm.js +36 -61
  330. package/dist/src/model.js +81 -36
  331. package/dist/src/realtime-pricing.js +103 -0
  332. package/dist/src/recall/card.js +74 -0
  333. package/dist/src/recall/evaluator.js +140 -0
  334. package/dist/src/recall/integration.js +17 -0
  335. package/dist/src/recall/tick.js +166 -0
  336. package/dist/src/session-link/plan-it-action.js +48 -0
  337. package/dist/src/session-link/session-link.js +248 -0
  338. package/dist/src/session-zones.js +507 -0
  339. package/dist/src/share/adapters.js +51 -0
  340. package/dist/src/share/share-consent.js +76 -0
  341. package/dist/src/share/share-deck.js +58 -0
  342. package/dist/src/share/share-token.js +146 -0
  343. package/dist/src/slot-spec.js +84 -106
  344. package/dist/src/state-ledger.js +767 -0
  345. package/dist/src/state-repair.js +299 -0
  346. package/dist/src/subagent-job-id-guard.js +58 -0
  347. package/dist/src/time-anchor.js +231 -33
  348. package/dist/src/tool-packet.js +20 -8
  349. package/dist/src/travel-slots.js +58 -35
  350. package/dist/src/travel-timeline.js +59 -0
  351. package/dist/src/turn-deadline.js +287 -0
  352. package/dist/src/turn-policy.js +118 -0
  353. package/dist/src/tz-resolver.js +143 -0
  354. package/dist/src/unified.js +538 -360
  355. package/dist/src/wish-pool.js +42 -12
  356. package/dist/src/write-gate.js +495 -0
  357. package/dist/src/z3-shared.js +284 -0
  358. package/extension/README.md +21 -0
  359. package/extension/README.zh-CN.md +21 -0
  360. package/extension/background.js +463 -0
  361. package/extension/content-bridge.js +270 -0
  362. package/extension/content-main.js +111 -0
  363. package/extension/manifest.json +60 -0
  364. package/package.json +407 -14
  365. package/schemas/booking.intent.schema.json +193 -0
  366. package/schemas/booking.surface.schema.json +2622 -0
  367. package/ts/capabilities/agent-reach-deep.ts +114 -0
  368. package/ts/capabilities/agent-reach.ts +198 -0
  369. package/ts/capabilities/anything.ts +255 -0
  370. package/ts/capabilities/artifacts.ts +428 -0
  371. package/ts/capabilities/fact-log.ts +54 -0
  372. package/ts/capabilities/flyai-config.ts +388 -0
  373. package/ts/capabilities/flyai.ts +1274 -0
  374. package/ts/capabilities/hbcli.ts +253 -71
  375. package/ts/capabilities/incident-log.ts +88 -59
  376. package/ts/capabilities/itinerary-artifact.ts +214 -0
  377. package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
  378. package/ts/capabilities/itinerary-deck-export.ts +378 -0
  379. package/ts/capabilities/opensky.ts +121 -0
  380. package/ts/capabilities/session/action-cache.ts +148 -0
  381. package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
  382. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  383. package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
  384. package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
  385. package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
  386. package/ts/capabilities/session/benchmark.ts +276 -0
  387. package/ts/capabilities/session/bridge-ledger.ts +333 -0
  388. package/ts/capabilities/session/extension-bridge.ts +794 -0
  389. package/ts/capabilities/session/extension-channel.ts +144 -0
  390. package/ts/capabilities/session/extension-distribution.ts +266 -0
  391. package/ts/capabilities/session/extract.ts +54 -0
  392. package/ts/capabilities/session/golden-score.ts +139 -0
  393. package/ts/capabilities/session/health-watch.ts +264 -0
  394. package/ts/capabilities/session/read-guard.ts +141 -0
  395. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  396. package/ts/capabilities/session/transport.ts +146 -0
  397. package/ts/capabilities/session/wizard.ts +140 -0
  398. package/ts/capabilities/session-consent.ts +211 -0
  399. package/ts/capabilities/session-login.ts +208 -0
  400. package/ts/capabilities/session-search.ts +893 -0
  401. package/ts/capabilities/weather.ts +330 -0
  402. package/ts/dsh-runtime/vendor/README.md +68 -0
  403. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  404. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
  405. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
  406. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
  407. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  408. package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
  409. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
  410. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  411. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
  412. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  413. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  414. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
  415. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  416. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
  417. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
  418. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
  419. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
  420. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  421. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  422. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
  423. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
  424. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  425. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  426. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  427. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  428. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
  429. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  430. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
  431. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  432. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  433. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
  434. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  435. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  436. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
  437. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
  438. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  439. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
  440. package/ts/package.json +296 -3
  441. package/ts/scripts/async-collect.ts +91 -0
  442. package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
  443. package/ts/scripts/skeleton-check.ts +1 -1
  444. package/ts/scripts/skeleton-integration-test.ts +23 -1
  445. package/ts/scripts/state-cli.ts +568 -0
  446. package/ts/scripts/turn-handoff-collect.ts +178 -0
  447. package/ts/src/artifact-gate.ts +991 -0
  448. package/ts/src/benchmark-agent-conformance.ts +619 -0
  449. package/ts/src/benchmark-environment-bridge.ts +538 -0
  450. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  451. package/ts/src/benchmark-tool-isolation.ts +166 -0
  452. package/ts/src/bookable-facts.ts +837 -0
  453. package/ts/src/booking-saga.ts +133 -0
  454. package/ts/src/booking-surface/availability-policy.ts +522 -0
  455. package/ts/src/booking-surface/booking-intent.ts +86 -0
  456. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  457. package/ts/src/booking-surface/canonical-schema.js +116 -0
  458. package/ts/src/booking-surface/contracts.ts +475 -0
  459. package/ts/src/booking-surface/dsh-planner.ts +1949 -0
  460. package/ts/src/booking-surface/dsh-plugin.js +378 -0
  461. package/ts/src/booking-surface/dsh-worker.ts +110 -0
  462. package/ts/src/booking-surface/error-codes.ts +241 -0
  463. package/ts/src/booking-surface/index.ts +9 -0
  464. package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
  465. package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
  466. package/ts/src/booking-surface/profile.ts +42 -0
  467. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  468. package/ts/src/booking-surface/runtime.ts +1793 -0
  469. package/ts/src/booking-surface/server.ts +733 -0
  470. package/ts/src/booking-surface/startup.ts +201 -0
  471. package/ts/src/booking-surface/validation.ts +217 -0
  472. package/ts/src/companions.ts +113 -0
  473. package/ts/src/contracts.ts +13 -3
  474. package/ts/src/dsh-llm.ts +44 -11
  475. package/ts/src/flyai-setup-tool.ts +77 -0
  476. package/ts/src/index.ts +2107 -224
  477. package/ts/src/itinerary-deck.ts +189 -0
  478. package/ts/src/itinerary-doc-shared.ts +741 -0
  479. package/ts/src/itinerary-html.ts +171 -0
  480. package/ts/src/loop.ts +278 -40
  481. package/ts/src/memory-capture.ts +283 -0
  482. package/ts/src/memory-decay.ts +55 -0
  483. package/ts/src/memory-utility.ts +70 -0
  484. package/ts/src/mock-llm.ts +4 -8
  485. package/ts/src/model.ts +88 -2
  486. package/ts/src/recall/card.ts +106 -0
  487. package/ts/src/recall/evaluator.ts +170 -0
  488. package/ts/src/recall/integration.ts +35 -0
  489. package/ts/src/recall/tick.ts +213 -0
  490. package/ts/src/session-link/plan-it-action.ts +78 -0
  491. package/ts/src/session-link/session-link.ts +275 -0
  492. package/ts/src/share/adapters.ts +93 -0
  493. package/ts/src/share/share-consent.ts +105 -0
  494. package/ts/src/share/share-deck.ts +85 -0
  495. package/ts/src/share/share-token.ts +166 -0
  496. package/ts/src/slot-spec.ts +172 -0
  497. package/ts/src/state-ledger.ts +912 -0
  498. package/ts/src/subagent-job-id-guard.ts +72 -0
  499. package/ts/src/time-anchor.ts +338 -0
  500. package/ts/src/tool-packet.ts +32 -0
  501. package/ts/src/travel-slots.ts +219 -0
  502. package/ts/src/travel-timeline.ts +83 -0
  503. package/ts/src/turn-deadline.ts +366 -0
  504. package/ts/src/turn-policy.ts +154 -0
  505. package/ts/src/unified.ts +360 -89
  506. package/ts/src/wish-pool.ts +79 -0
@@ -0,0 +1,252 @@
1
+ import assert from 'node:assert/strict';
2
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { join } from 'node:path';
6
+ import { ManagedDshRunPort } from '../src/booking-surface/managed-dsh-run-port.js';
7
+ import { ManagedDshCleanupError } from '../src/booking-surface/managed-dsh-cleanup-diagnostic.js';
8
+ const pendingWorkerPath = fileURLToPath(new URL('./fixtures/managed-dsh-pending-worker-fixture.mjs', import.meta.url));
9
+ // Attach a rejection handler in the same turn as every operation that can reject.
10
+ // This proof intentionally exercises real SDK promises, so it must not synthesize
11
+ // a completed `done` promise or leave a rejected close/run promise unobserved.
12
+ function observe(promise) {
13
+ return promise.then((value) => ({ status: 'fulfilled', value }), (reason) => ({ status: 'rejected', reason }));
14
+ }
15
+ async function bounded(promise, timeoutMs, label) {
16
+ let timer;
17
+ try {
18
+ return await Promise.race([
19
+ promise,
20
+ new Promise((_, reject) => {
21
+ timer = setTimeout(() => reject(new Error(label)), timeoutMs);
22
+ }),
23
+ ]);
24
+ }
25
+ finally {
26
+ clearTimeout(timer);
27
+ }
28
+ }
29
+ function reasonMessage(reason) {
30
+ return reason instanceof Error ? reason.message : String(reason);
31
+ }
32
+ async function rejectedWith(promise, expected, label) {
33
+ const outcome = await bounded(promise, 1_500, `${label}: promise did not settle`);
34
+ assert.equal(outcome.status, 'rejected', `${label}: promise must reject`);
35
+ const message = reasonMessage(outcome.reason);
36
+ assert.equal(message, expected, `${label}: stable public error`);
37
+ }
38
+ async function rejectedBeforeNextImmediate(promise, expected, label) {
39
+ let immediate;
40
+ try {
41
+ const outcome = await Promise.race([
42
+ promise,
43
+ new Promise((_, reject) => {
44
+ immediate = setImmediate(() => reject(new Error(`${label}: promise did not reject before next setImmediate`)));
45
+ }),
46
+ ]);
47
+ assert.equal(outcome.status, 'rejected', `${label}: promise must reject`);
48
+ assert.equal(reasonMessage(outcome.reason), expected, `${label}: stable public error`);
49
+ }
50
+ finally {
51
+ if (immediate)
52
+ clearImmediate(immediate);
53
+ }
54
+ }
55
+ async function waitForFile(path, timeoutMs) {
56
+ const deadline = Date.now() + timeoutMs;
57
+ while (!existsSync(path)) {
58
+ if (Date.now() >= deadline)
59
+ throw new Error(`fixture marker did not appear: ${path}`);
60
+ await new Promise((resolve) => setTimeout(resolve, 10));
61
+ }
62
+ }
63
+ async function waitForFileText(path, expected, timeoutMs) {
64
+ const deadline = Date.now() + timeoutMs;
65
+ while (!existsSync(path) || readFileSync(path, 'utf8') !== expected) {
66
+ if (Date.now() >= deadline)
67
+ throw new Error(`fixture marker did not reach ${expected}: ${path}`);
68
+ await new Promise((resolve) => setTimeout(resolve, 10));
69
+ }
70
+ }
71
+ async function waitForDead(pid, timeoutMs) {
72
+ const deadline = Date.now() + timeoutMs;
73
+ while (true) {
74
+ try {
75
+ process.kill(pid, 0);
76
+ }
77
+ catch {
78
+ return;
79
+ }
80
+ if (Date.now() >= deadline)
81
+ throw new Error(`fixture process ${pid} was not reaped`);
82
+ await new Promise((resolve) => setTimeout(resolve, 25));
83
+ }
84
+ }
85
+ async function cleanup(port) {
86
+ if (!port)
87
+ return;
88
+ // Keep cleanup rejection observed even when an assertion fails earlier.
89
+ await bounded(observe(port.close()), 2_000, 'cleanup did not settle');
90
+ }
91
+ async function proveNaturalExitRejectsNewRequests() {
92
+ const root = mkdtempSync(join(tmpdir(), 'gotry-managed-dsh-terminal-exit-'));
93
+ const pidFile = join(root, 'pid.json');
94
+ const requestFile = join(root, 'requests');
95
+ const statusFile = join(root, 'status.json');
96
+ let port;
97
+ try {
98
+ port = new ManagedDshRunPort({
99
+ workerPath: pendingWorkerPath,
100
+ graceMs: 50,
101
+ env: {
102
+ ...process.env,
103
+ MANAGED_DSH_FIXTURE_PID_FILE: pidFile,
104
+ MANAGED_DSH_FIXTURE_REQUEST_FILE: requestFile,
105
+ MANAGED_DSH_FIXTURE_STATUS_FILE: statusFile,
106
+ MANAGED_DSH_FIXTURE_EXIT_AFTER_REQUESTS: '1',
107
+ MANAGED_DSH_FIXTURE_EXIT_CODE: '23',
108
+ },
109
+ });
110
+ await waitForFile(pidFile, 1_000);
111
+ const oldPending = observe(port.run('terminal exit pending run', { sessionId: 'managed-dsh-terminal-exit-old' }));
112
+ await waitForFileText(requestFile, '1', 1_000);
113
+ await rejectedWith(oldPending, 'managed DSH worker exited', 'natural exit pending run');
114
+ await waitForFile(statusFile, 1_000);
115
+ const status = JSON.parse(readFileSync(statusFile, 'utf8'));
116
+ assert.equal(status.exitCode, 23, 'fixture naturally exits with code 23');
117
+ assert.equal(status.signal, null, 'fixture natural exit has no signal');
118
+ assert.ok(status.stderr.length <= 128, 'fixture stderr evidence is bounded');
119
+ // Wait for the real handle.done rejection/settlement path above, then probe
120
+ // both public request methods after the worker has exited.
121
+ await rejectedBeforeNextImmediate(observe(port.run('terminal exit post run', { sessionId: 'managed-dsh-terminal-exit-new' })), 'managed DSH worker exited', 'natural exit new run');
122
+ await rejectedBeforeNextImmediate(observe(port.warmup()), 'managed DSH worker exited', 'natural exit new warmup');
123
+ const closePromise = port.close();
124
+ const repeatedClosePromise = port.close();
125
+ assert.strictEqual(repeatedClosePromise, closePromise, 'natural exit repeated close returns one cleanup promise');
126
+ assert.equal((await bounded(observe(closePromise), 2_000, 'natural exit close did not settle')).status, 'fulfilled', 'natural exit close succeeds');
127
+ }
128
+ finally {
129
+ await cleanup(port);
130
+ rmSync(root, { recursive: true, force: true });
131
+ }
132
+ console.log('PASS managed DSH terminal natural exit: old pending and post-exit run/warmup reject immediately');
133
+ }
134
+ async function proveExplicitCloseIsBoundedAndIdempotent() {
135
+ const root = mkdtempSync(join(tmpdir(), 'gotry-managed-dsh-terminal-close-'));
136
+ const pidFile = join(root, 'pid.json');
137
+ const requestFile = join(root, 'requests');
138
+ let port;
139
+ try {
140
+ port = new ManagedDshRunPort({
141
+ workerPath: pendingWorkerPath,
142
+ graceMs: 50,
143
+ env: {
144
+ ...process.env,
145
+ MANAGED_DSH_FIXTURE_PID_FILE: pidFile,
146
+ MANAGED_DSH_FIXTURE_REQUEST_FILE: requestFile,
147
+ },
148
+ });
149
+ await waitForFile(pidFile, 1_000);
150
+ const pids = JSON.parse(readFileSync(pidFile, 'utf8'));
151
+ assert.ok(Number.isInteger(pids.workerPid) && Number.isInteger(pids.grandchildPid), 'fixture reports worker tree');
152
+ const pending = [
153
+ observe(port.run('terminal close first run', { sessionId: 'managed-dsh-terminal-close-1' })),
154
+ observe(port.run('terminal close second run', { sessionId: 'managed-dsh-terminal-close-2' })),
155
+ observe(port.warmup()),
156
+ ];
157
+ await waitForFileText(requestFile, '3', 1_000);
158
+ const closePromise = port.close();
159
+ const repeatedClosePromise = port.close();
160
+ assert.strictEqual(repeatedClosePromise, closePromise, 'repeated close returns one cleanup promise');
161
+ const closeOutcome = observe(closePromise);
162
+ const repeatedOutcome = observe(repeatedClosePromise);
163
+ for (const [index, request] of pending.entries()) {
164
+ await rejectedWith(request, 'managed DSH run port closed', `explicit close old pending ${index + 1}`);
165
+ }
166
+ assert.equal((await bounded(closeOutcome, 2_000, 'explicit close did not settle')).status, 'fulfilled', 'explicit close succeeds');
167
+ assert.equal((await bounded(repeatedOutcome, 2_000, 'repeated close did not settle')).status, 'fulfilled', 'repeated close succeeds');
168
+ await rejectedWith(observe(port.run('terminal close post run', { sessionId: 'managed-dsh-terminal-close-new' })), 'managed DSH run port is closed', 'explicit close new run');
169
+ await rejectedWith(observe(port.warmup()), 'managed DSH run port is closed', 'explicit close new warmup');
170
+ await waitForDead(pids.workerPid, 1_000);
171
+ await waitForDead(pids.grandchildPid, 1_000);
172
+ }
173
+ finally {
174
+ await cleanup(port);
175
+ rmSync(root, { recursive: true, force: true });
176
+ }
177
+ console.log('PASS managed DSH terminal explicit close: pending rejection, idempotent close, signal cleanup, and closed guards');
178
+ }
179
+ async function proveSignalTerminationRejectsPending() {
180
+ const root = mkdtempSync(join(tmpdir(), 'gotry-managed-dsh-terminal-signal-'));
181
+ const pidFile = join(root, 'pid.json');
182
+ const requestFile = join(root, 'requests');
183
+ let port;
184
+ try {
185
+ port = new ManagedDshRunPort({
186
+ workerPath: pendingWorkerPath,
187
+ graceMs: 50,
188
+ env: { ...process.env, MANAGED_DSH_FIXTURE_PID_FILE: pidFile, MANAGED_DSH_FIXTURE_REQUEST_FILE: requestFile },
189
+ });
190
+ await waitForFile(pidFile, 1_000);
191
+ const pids = JSON.parse(readFileSync(pidFile, 'utf8'));
192
+ assert.ok(Number.isInteger(pids.workerPid) && Number.isInteger(pids.grandchildPid), 'signal fixture reports its worker tree');
193
+ const oldPending = observe(port.run('terminal signal pending run', { sessionId: 'managed-dsh-terminal-signal-old' }));
194
+ await waitForFileText(requestFile, '1', 1_000);
195
+ // Kill the real child from outside the port. This exercises the SDK's
196
+ // signal-shaped done resolution, rather than ManagedDshRunPort.close().
197
+ process.kill(pids.workerPid, 'SIGKILL');
198
+ await rejectedWith(oldPending, 'managed DSH worker exited', 'signal exit pending run');
199
+ await waitForDead(pids.workerPid, 1_000);
200
+ await rejectedBeforeNextImmediate(observe(port.run('terminal signal post run', { sessionId: 'managed-dsh-terminal-signal-new' })), 'managed DSH worker exited', 'signal exit new run');
201
+ await rejectedBeforeNextImmediate(observe(port.warmup()), 'managed DSH worker exited', 'signal exit new warmup');
202
+ const closePromise = port.close();
203
+ const repeatedClosePromise = port.close();
204
+ assert.strictEqual(repeatedClosePromise, closePromise, 'signal exit repeated close returns one cleanup promise');
205
+ assert.equal((await bounded(observe(closePromise), 2_000, 'signal exit close did not settle')).status, 'fulfilled', 'signal exit close succeeds');
206
+ await waitForDead(pids.grandchildPid, 1_000);
207
+ }
208
+ finally {
209
+ await cleanup(port);
210
+ rmSync(root, { recursive: true, force: true });
211
+ }
212
+ console.log('PASS managed DSH terminal signal: SIGKILL, post-signal guards, idempotent close, and tree cleanup');
213
+ }
214
+ async function proveSpawnFailureIsSanitized() {
215
+ const root = mkdtempSync(join(tmpdir(), 'gotry-managed-dsh-terminal-spawn-'));
216
+ const missingCwd = join(root, 'missing-cwd');
217
+ let port;
218
+ try {
219
+ // dsh-subprocess-local returns a live handle and rejects handle.done for a
220
+ // missing cwd; this uses that real failure path rather than a fake promise.
221
+ port = new ManagedDshRunPort({
222
+ cwd: missingCwd,
223
+ workerPath: pendingWorkerPath,
224
+ graceMs: 50,
225
+ env: { ...process.env },
226
+ });
227
+ await rejectedWith(observe(port.run('terminal spawn failure run', { sessionId: 'managed-dsh-terminal-spawn-failure' })), 'managed DSH worker failed', 'spawn failure run');
228
+ await rejectedBeforeNextImmediate(observe(port.warmup()), 'managed DSH worker failed', 'spawn failure warmup');
229
+ await rejectedBeforeNextImmediate(observe(port.run('terminal spawn failure post run', { sessionId: 'managed-dsh-terminal-spawn-failure-post' })), 'managed DSH worker failed', 'spawn failure post run');
230
+ const closePromise = port.close();
231
+ const repeatedClosePromise = port.close();
232
+ assert.strictEqual(repeatedClosePromise, closePromise, 'spawn failure repeated close is idempotent');
233
+ for (const [label, promise] of [['spawn failure close', closePromise], ['spawn failure repeated close', repeatedClosePromise]]) {
234
+ const outcome = await bounded(observe(promise), 2_000, `${label} did not settle`);
235
+ assert.equal(outcome.status, 'rejected', `${label} must reject`);
236
+ const reason = outcome.reason;
237
+ assert.ok(reason instanceof ManagedDshCleanupError, `${label} carries the typed cleanup diagnostic`);
238
+ assert.equal(reason.message.split(';')[0], 'managed DSH worker failed', `${label} stable public error`);
239
+ }
240
+ }
241
+ finally {
242
+ await cleanup(port);
243
+ rmSync(root, { recursive: true, force: true });
244
+ }
245
+ console.log('PASS managed DSH terminal spawn failure: real missing cwd and sanitized immediate guards');
246
+ }
247
+ await proveNaturalExitRejectsNewRequests();
248
+ await proveExplicitCloseIsBoundedAndIdempotent();
249
+ await proveSignalTerminationRejectsPending();
250
+ await proveSpawnFailureIsSanitized();
251
+ assert.ok(existsSync(join(process.cwd(), 'node_modules/@deepseek-ai/dsh-subprocess-local')), 'proof uses installed dsh subprocess-local runtime');
252
+ console.log('MANAGED DSH TERMINAL PROOF: natural exit, explicit close, signal cleanup, and spawn failure are bounded and sanitized');
@@ -0,0 +1,365 @@
1
+ /**
2
+ * Package proof for issue #202.
3
+ *
4
+ * The full suite passes the executable from its clean tarball install; focused
5
+ * runs pack/unpack locally and attach the already-installed root closure. Both
6
+ * paths load the plugin from the artifact, never from the checkout vendor path.
7
+ * No map provider or paid endpoint is contacted; inline-coordinate geocoding is
8
+ * asserted with fetch disabled.
9
+ */
10
+ import { execFileSync } from 'node:child_process';
11
+ import { createHash } from 'node:crypto';
12
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
13
+ import { createRequire } from 'node:module';
14
+ import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
15
+ import { tmpdir } from 'node:os';
16
+ import { fileURLToPath, pathToFileURL } from 'node:url';
17
+ import assert from 'node:assert/strict';
18
+ const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
19
+ const upstreamLicenseSha256 = 'b6bbb0c73a02cf8d2c304e9f208b41c32f0a810fabe366986e2b14ac3338f618';
20
+ const upstreamVendorFileCount = 37;
21
+ const adaptedVendorAggregateSha256 = 'f01515d8c1ec2973c7b4fb2bec0f6e2175bceef7a5331847cb210a11855a49e2';
22
+ const expectedTools = [
23
+ 'map_bicycling_route',
24
+ 'map_driving_route',
25
+ 'map_geocode',
26
+ 'map_poi_search',
27
+ 'map_reverse_geocode',
28
+ 'map_transit_route',
29
+ 'map_walking_route',
30
+ ];
31
+ function sha256(path) {
32
+ return createHash('sha256').update(readFileSync(path)).digest('hex');
33
+ }
34
+ function vendorAggregate(root) {
35
+ const files = [];
36
+ const walk = (directory) => {
37
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
38
+ const path = join(directory, entry.name);
39
+ if (entry.isDirectory())
40
+ walk(path);
41
+ else
42
+ files.push(path.slice(root.length + 1).replaceAll('\\', '/'));
43
+ }
44
+ };
45
+ walk(root);
46
+ files.sort();
47
+ const digest = createHash('sha256');
48
+ for (const relative of files) {
49
+ digest.update(relative);
50
+ digest.update('\0');
51
+ digest.update(readFileSync(join(root, relative)));
52
+ digest.update('\0');
53
+ }
54
+ return { count: files.length, sha256: digest.digest('hex') };
55
+ }
56
+ function assertPackagingExcludesNodeModules() {
57
+ const tempRoot = mkdtempSync(join(tmpdir(), 'gotry-pack-excl-'));
58
+ try {
59
+ const archiveTar = join(tempRoot, 'head.tar');
60
+ execFileSync('git', ['archive', '--format=tar', '--output', archiveTar, 'HEAD'], { cwd: repoRoot });
61
+ const checkoutDir = join(tempRoot, 'checkout');
62
+ mkdirSync(checkoutDir);
63
+ execFileSync('tar', ['-xf', archiveTar, '-C', checkoutDir]);
64
+ copyFileSync(join(repoRoot, 'package.json'), join(checkoutDir, 'package.json'));
65
+ const vendorBinDir = join(checkoutDir, 'ts/dsh-runtime/vendor/dsh-map-tools/node_modules/.bin');
66
+ mkdirSync(vendorBinDir, { recursive: true });
67
+ for (const name of ['cordis', 'tsc', 'tsserver', 'vitest']) {
68
+ const binPath = join(vendorBinDir, name);
69
+ writeFileSync(binPath, '#!/usr/bin/env node\n');
70
+ chmodSync(binPath, 0o755);
71
+ }
72
+ const packDir = join(tempRoot, 'pack');
73
+ mkdirSync(packDir);
74
+ const packOutput = execFileSync('npm', [
75
+ 'pack', '--ignore-scripts', '--json', '--pack-destination', packDir,
76
+ ], { cwd: checkoutDir, encoding: 'utf8' });
77
+ const packInfo = JSON.parse(packOutput);
78
+ assert.equal(packInfo.length, 1, 'temp npm pack must produce one artifact');
79
+ const tarball = join(packDir, packInfo[0].filename);
80
+ assert.ok(existsSync(tarball), `temp packed artifact missing: ${tarball}`);
81
+ const entries = execFileSync('tar', ['-tzf', tarball], { encoding: 'utf8' }).trimEnd().split('\n');
82
+ const nodeModulesEntries = entries.filter(path => path.startsWith('package/ts/dsh-runtime/vendor/dsh-map-tools/node_modules'));
83
+ assert.equal(nodeModulesEntries.length, 0, `npm pack must exclude vendor node_modules: found ${nodeModulesEntries.join(', ')}`);
84
+ const extractDir = join(tempRoot, 'extracted');
85
+ mkdirSync(extractDir);
86
+ execFileSync('tar', ['-xzf', tarball, '-C', extractDir]);
87
+ const packedVendorRoot = join(extractDir, 'package/ts/dsh-runtime/vendor/dsh-map-tools');
88
+ const packedAggregate = vendorAggregate(packedVendorRoot);
89
+ assert.equal(packedAggregate.count, upstreamVendorFileCount, 'packed vendor file count drifted');
90
+ assert.equal(packedAggregate.sha256, adaptedVendorAggregateSha256, 'packed vendor aggregate drifted');
91
+ }
92
+ finally {
93
+ rmSync(tempRoot, { recursive: true, force: true });
94
+ }
95
+ }
96
+ function assertTargetLockClosure() {
97
+ const manifest = JSON.parse(readFileSync(join(repoRoot, 'ts/package.json'), 'utf8'));
98
+ assert.equal(manifest.dependencies?.['dsh-map-tools'], undefined, 'external map-tools dependency must stay removed');
99
+ const lock = JSON.parse(readFileSync(join(repoRoot, 'ts/package-lock.json'), 'utf8'));
100
+ assert.equal(lock.packages?.['']?.dependencies?.['dsh-map-tools'], undefined, 'lock root must not resolve external map-tools');
101
+ assert.equal(lock.packages?.['node_modules/dsh-map-tools'], undefined, 'lock must not carry external map-tools');
102
+ const dshEntries = Object.entries(lock.packages ?? {}).filter(([path]) => /(?:^|\/)node_modules\/@deepseek-ai\/(?:dsh|dsh-[^/]+)$/.test(path));
103
+ assert.ok(dshEntries.length >= 10, 'expected dsh-tools peer closure in the ts lock');
104
+ for (const [path, entry] of dshEntries) {
105
+ assert.equal(entry.version, '0.2.0-rc.2', `${path} drifted outside the 0.2.0-rc.2 closure`);
106
+ }
107
+ return { packages: dshEntries.length, version: '0.2.0-rc.2' };
108
+ }
109
+ function findPackageRoot(entry) {
110
+ let cursor = dirname(entry);
111
+ for (;;) {
112
+ const manifestPath = join(cursor, 'package.json');
113
+ if (existsSync(manifestPath)) {
114
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
115
+ if (manifest.name === '@danceiny/gotry')
116
+ return cursor;
117
+ }
118
+ const parent = dirname(cursor);
119
+ if (parent === cursor)
120
+ throw new Error(`cannot locate @danceiny/gotry package root from ${entry}`);
121
+ cursor = parent;
122
+ }
123
+ }
124
+ function assertBinTargetsPackage(binPath, expectedTarget) {
125
+ const resolvedExpectedTarget = realpathSync(expectedTarget);
126
+ if (realpathSync(binPath) === resolvedExpectedTarget)
127
+ return;
128
+ // pnpm writes an executable shell shim instead of a symlink. Its final
129
+ // machine-readable marker is safer to verify than accepting any occurrence
130
+ // of the package path in an otherwise unrelated executable.
131
+ const shim = readFileSync(binPath, 'utf8');
132
+ assert.ok(Buffer.byteLength(shim, 'utf8') <= 32_768, 'clean-install gotry shim is unexpectedly large');
133
+ const lines = shim.trimEnd().split(/\r?\n/);
134
+ const markers = lines.filter(line => line.startsWith('# cmd-shim-target='));
135
+ assert.equal(markers.length, 1, 'pnpm gotry shim must contain exactly one target marker');
136
+ assert.equal(lines.at(-1), markers[0], 'pnpm gotry shim target marker must be the final line');
137
+ const markerTarget = markers[0].slice('# cmd-shim-target='.length);
138
+ assert.ok(isAbsolute(markerTarget), 'pnpm gotry shim target must be absolute');
139
+ assert.equal(realpathSync(markerTarget), resolvedExpectedTarget, 'GOTRY_MAP_TOOLS_E2E_BIN shim must target this installed GoTry package');
140
+ }
141
+ function prepareProofPackage(cleanInstalledBin) {
142
+ if (cleanInstalledBin) {
143
+ const binPath = resolve(cleanInstalledBin);
144
+ assert.equal(basename(binPath), 'gotry', 'clean-install executable must use the gotry bin name');
145
+ assert.equal(basename(dirname(binPath)), '.bin', 'clean-install executable must come from node_modules/.bin');
146
+ assert.equal(basename(dirname(dirname(binPath))), 'node_modules', 'clean-install executable must come from a consumer install');
147
+ const consumerRoot = dirname(dirname(dirname(binPath)));
148
+ const packageMain = createRequire(join(consumerRoot, 'package.json')).resolve('@danceiny/gotry');
149
+ const packageRoot = findPackageRoot(packageMain);
150
+ const installedManifest = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'));
151
+ assert.equal(installedManifest.name, '@danceiny/gotry', 'clean-install executable must belong to GoTry');
152
+ const declaredBin = typeof installedManifest.bin === 'string'
153
+ ? installedManifest.bin
154
+ : installedManifest.bin?.gotry;
155
+ assert.equal(declaredBin, 'bin/gotry-inner.js', 'installed package must declare the production gotry bin');
156
+ assertBinTargetsPackage(binPath, join(packageRoot, declaredBin));
157
+ return { packageRoot };
158
+ }
159
+ const proofRoot = mkdtempSync(join(repoRoot, '.tmp-map-tools-proof-'));
160
+ try {
161
+ const packOutput = execFileSync('npm', [
162
+ 'pack', '--ignore-scripts', '--json', '--pack-destination', proofRoot,
163
+ ], { cwd: repoRoot, encoding: 'utf8' });
164
+ const packInfo = JSON.parse(packOutput);
165
+ assert.equal(packInfo.length, 1, 'npm pack must produce one artifact');
166
+ const tarball = join(proofRoot, packInfo[0].filename);
167
+ assert.ok(existsSync(tarball), `packed artifact missing: ${tarball}`);
168
+ const unpackRoot = join(proofRoot, 'unpacked');
169
+ mkdirSync(unpackRoot);
170
+ execFileSync('tar', ['-xzf', tarball, '-C', unpackRoot]);
171
+ const packageRoot = join(unpackRoot, 'package');
172
+ symlinkSync(join(repoRoot, 'node_modules'), join(packageRoot, 'node_modules'), process.platform === 'win32' ? 'junction' : 'dir');
173
+ return { packageRoot, proofRoot };
174
+ }
175
+ catch (error) {
176
+ rmSync(proofRoot, { recursive: true, force: true });
177
+ throw error;
178
+ }
179
+ }
180
+ const cleanInstalledBin = process.env.GOTRY_MAP_TOOLS_E2E_BIN;
181
+ const { packageRoot, proofRoot } = prepareProofPackage(cleanInstalledBin);
182
+ try {
183
+ assertPackagingExcludesNodeModules();
184
+ const lockedDsh = assertTargetLockClosure();
185
+ const vendorRoot = join(packageRoot, 'ts/dsh-runtime/vendor/dsh-map-tools');
186
+ const requiredFiles = [
187
+ 'LICENSE',
188
+ 'package.json',
189
+ 'cordis.patch.yml',
190
+ 'lib/index.js',
191
+ 'lib/settings-ns.js',
192
+ 'lib/config.js',
193
+ 'lib/tools/geocode.js',
194
+ 'lib/tools/routes.js',
195
+ 'lib/tools/poi.js',
196
+ ];
197
+ for (const relative of requiredFiles) {
198
+ assert.ok(existsSync(join(vendorRoot, relative)), `required vendor file missing: ${relative}`);
199
+ }
200
+ const vendorTree = vendorAggregate(vendorRoot);
201
+ assert.equal(vendorTree.count, upstreamVendorFileCount, 'vendored payload file count drifted');
202
+ assert.equal(vendorTree.sha256, adaptedVendorAggregateSha256, 'vendored payload aggregate drifted');
203
+ const vendorPackage = JSON.parse(readFileSync(join(vendorRoot, 'package.json'), 'utf8'));
204
+ assert.equal(vendorPackage.name, 'dsh-map-tools');
205
+ assert.equal(vendorPackage.version, '0.7.3');
206
+ assert.equal(vendorPackage.license, 'MIT');
207
+ assert.equal(sha256(join(vendorRoot, 'LICENSE')), upstreamLicenseSha256, 'upstream MIT license changed');
208
+ const packageRequire = createRequire(join(packageRoot, 'package.json'));
209
+ const dshToolsPackageJson = packageRequire.resolve('@deepseek-ai/dsh-tools/package.json');
210
+ const dshSettingsPackageJson = packageRequire.resolve('@deepseek-ai/dsh-settings/package.json');
211
+ const dshTools = JSON.parse(readFileSync(dshToolsPackageJson, 'utf8'));
212
+ const dshSettings = JSON.parse(readFileSync(dshSettingsPackageJson, 'utf8'));
213
+ assert.equal(dshTools.version, '0.2.0-rc.2');
214
+ assert.equal(dshSettings.version, '0.2.0-rc.2');
215
+ const settingsApi = await import(pathToFileURL(join(dirname(dshSettingsPackageJson), 'lib/index.js')).href);
216
+ // 0.2.0-rc.2:SettingsForms 取代了手工 section API——表单由插件导出的
217
+ // Config schema 自动生成,唯一的手工注册是页策略 settings.configure({auto}, fiber)。
218
+ const settingsConfigure = settingsApi.SettingsForms?.prototype?.configure;
219
+ assert.equal(typeof settingsConfigure, 'function', 'real 0.2.0-rc.2 SettingsForms.prototype.configure must be present');
220
+ const plugin = await import(pathToFileURL(join(vendorRoot, 'lib/index.js')).href);
221
+ const registered = new Map();
222
+ const registerEvents = [];
223
+ const toolDisposeEvents = [];
224
+ const settingsRegistrations = [];
225
+ const settingsWatchers = [];
226
+ const settingsProviderDisposers = [];
227
+ const contextDisposers = [];
228
+ const settingsConfigureCalls = [];
229
+ const activeToolNames = () => [...registered.keys()].sort();
230
+ const settingsConfigureDisposed = [];
231
+ const settingsProvider = {
232
+ ctx: {
233
+ effect(effect) {
234
+ const disposer = effect();
235
+ if (typeof disposer === 'function')
236
+ settingsProviderDisposers.push(disposer);
237
+ return disposer;
238
+ },
239
+ },
240
+ register: (...args) => {
241
+ settingsRegistrations.push(args);
242
+ return {
243
+ get: () => args[2] && typeof args[2] === 'object' ? args[2].base : undefined,
244
+ watch: (callback) => {
245
+ settingsWatchers.push(callback);
246
+ return () => {
247
+ const index = settingsWatchers.indexOf(callback);
248
+ if (index >= 0)
249
+ settingsWatchers.splice(index, 1);
250
+ };
251
+ },
252
+ update: async () => undefined,
253
+ replace: async () => undefined,
254
+ };
255
+ },
256
+ installSection: (..._args) => {
257
+ throw new Error('legacy installSection must not be called on the 0.2.0-rc.2 settings service');
258
+ },
259
+ configure: (presentation, owner) => {
260
+ settingsConfigureCalls.push({ presentation, owner });
261
+ return () => {
262
+ settingsConfigureDisposed.push('policy');
263
+ };
264
+ },
265
+ };
266
+ const context = {
267
+ fiber: { state: 'active' },
268
+ effect(effect) {
269
+ const disposer = effect();
270
+ if (typeof disposer === 'function')
271
+ contextDisposers.push(disposer);
272
+ return disposer;
273
+ },
274
+ tools: {
275
+ register(tool) {
276
+ assert.ok(tool.name.startsWith('map_'), `unexpected map tool name: ${tool.name}`);
277
+ registered.set(tool.name, tool);
278
+ registerEvents.push(tool.name);
279
+ return () => {
280
+ registered.delete(tool.name);
281
+ toolDisposeEvents.push(tool.name);
282
+ };
283
+ },
284
+ },
285
+ inject(dependencies, callback) {
286
+ if (dependencies.includes('settings')) {
287
+ callback({ settings: settingsProvider });
288
+ }
289
+ else if (dependencies.includes('webServer')) {
290
+ // 0.7.3 的 config-route 用 scope.effect 托管回环路由的撤销注册。
291
+ callback({
292
+ webServer: { register: () => undefined },
293
+ effect(effect) {
294
+ const disposer = effect();
295
+ if (typeof disposer === 'function')
296
+ contextDisposers.push(disposer);
297
+ return disposer;
298
+ },
299
+ });
300
+ }
301
+ else {
302
+ throw new Error(`unexpected dependency injection: ${dependencies.join(',')}`);
303
+ }
304
+ },
305
+ };
306
+ plugin.apply(context, {
307
+ provider: 'osm', amapKey: '', timeoutMs: 1000, maxQps: 2,
308
+ defaultMode: 'driving', language: 'zh',
309
+ });
310
+ assert.deepEqual(activeToolNames(), expectedTools, 'exactly seven active map tools must register');
311
+ assert.equal(registerEvents.length, expectedTools.length, 'schema-driven settings add no initial tool rebuild');
312
+ assert.equal(toolDisposeEvents.length, 0, 'schema-driven settings dispose no tool generation');
313
+ assert.equal(settingsConfigureCalls.length, 1, '0.2.0-rc.2 settings page policy must configure exactly once');
314
+ assert.deepEqual(settingsConfigureCalls[0]?.presentation, { auto: true }, 'page policy presentation must opt into the automatic card');
315
+ assert.equal(settingsConfigureCalls[0]?.owner, context.fiber, 'page policy owner must be the plugin fiber');
316
+ assert.equal(settingsRegistrations.length, 0, 'legacy per-section registration must stay retired');
317
+ assert.equal(settingsWatchers.length, 0, 'legacy settings watcher must stay retired');
318
+ assert.equal(settingsProviderDisposers.length, 0, 'legacy provider-detach fallback must stay retired');
319
+ // 两个受管撤销:config-route 的回环路由注册 + settings 页策略(按注册序)。
320
+ assert.equal(contextDisposers.length, 2, 'config-route disposer + settings page-policy disposer must register with the plugin effects');
321
+ contextDisposers[1]();
322
+ assert.equal(settingsConfigureDisposed.length, 1, 'plugin effect disposal must release the settings page policy');
323
+ assert.deepEqual(activeToolNames(), expectedTools, 'policy disposal must keep exactly seven active map tools');
324
+ const finalActiveTools = [...registered.values()];
325
+ const originalFetch = globalThis.fetch;
326
+ globalThis.fetch = (async () => { throw new Error('network forbidden by package proof'); });
327
+ try {
328
+ const geocode = registered.get('map_geocode');
329
+ assert.ok(geocode, 'map_geocode must be registered');
330
+ const result = await geocode.execute({ address: '116.397428,39.90923' }, { signal: new AbortController().signal });
331
+ assert.equal(result.provider, 'inline');
332
+ assert.deepEqual(result.location, [116.397428, 39.90923]);
333
+ }
334
+ finally {
335
+ globalThis.fetch = originalFetch;
336
+ }
337
+ for (const dispose of contextDisposers.splice(0).reverse())
338
+ dispose();
339
+ assert.equal(registered.size, 0, 'plugin unload must dispose the active map tool generation');
340
+ console.log(JSON.stringify({
341
+ proof: 'map-tools-vendor-package',
342
+ status: 'PASS',
343
+ artifactMode: cleanInstalledBin ? 'clean-installed-tarball' : 'packed-unpacked-focused',
344
+ vendored: {
345
+ sourcePackage: 'dsh-map-tools@0.7.3',
346
+ licenseSha256: upstreamLicenseSha256, vendorFileCount: vendorTree.count,
347
+ adaptedVendorAggregateSha256: vendorTree.sha256,
348
+ },
349
+ artifactVendor: vendorRoot,
350
+ dshClosure: { tools: dshTools.version, settings: dshSettings.version, ...lockedDsh },
351
+ settingsLifecycle: {
352
+ registerEvents: registerEvents.length,
353
+ toolDisposeEvents: toolDisposeEvents.length,
354
+ pagePolicyConfigured: settingsConfigureCalls.length,
355
+ legacySectionRegistrations: settingsRegistrations.length,
356
+ pluginUnloadDisposed: true,
357
+ },
358
+ tools: finalActiveTools.map(tool => tool.name).sort(),
359
+ inlineCoordinate: { provider: 'inline', network: 'forbidden' },
360
+ }, null, 2));
361
+ }
362
+ finally {
363
+ if (proofRoot)
364
+ rmSync(proofRoot, { recursive: true, force: true });
365
+ }