@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,83 @@
1
+ /**
2
+ * 旅行时间线(memory-design M4 层,P1):「去过哪、何时、和谁」的 append-only 事实层。
3
+ *
4
+ * 立场(memory-design §1):确定性事实归代码——日期解析复用 slot-spec(锚点卡词表+绝对),
5
+ * 词表外 unresolved 不猜;每条事件必须带 evidence(用户原话或 wish 确认),溯源 P0。
6
+ * 消费:出发地三级解析(未来行程→时间线→问用户)/「去过不再推」排序通道/
7
+ * 回流率分子(verified_outcome ⟺ timeline 有对应行程)。
8
+ * 多用户前向兼容:append-only + 稳定 trip_id,账本化只换存储面(RFC §6.5)。
9
+ */
10
+
11
+ import { parseAbsoluteDate, ymd, type TimeAnchor } from './time-anchor.ts'
12
+ import { resolveSlotDate } from './slot-spec.ts'
13
+
14
+ export type TimelineSource = 'user-verbatim' | 'wish-confirmed'
15
+
16
+ export interface TimelineEvent {
17
+ schema: 'travel_timeline.v1'
18
+ /** 稳定主键:语义派生(目的地|start|source),重放 no-op */
19
+ trip_id: string
20
+ destination: string
21
+ /** YYYY-MM-DD(入库前必须已解析为绝对日期) */
22
+ start: string
23
+ end?: string
24
+ companions?: string[]
25
+ source: TimelineSource
26
+ /** 用户原话或 wish confirm-outcome 指针 */
27
+ evidence: string
28
+ ts: string
29
+ }
30
+
31
+ /** 相对/模糊表达 → 绝对日期(守门:词表外返回 null,调用方必须拒收而非猜) */
32
+ export function resolveTimelineDate(expr: string, anchor: TimeAnchor): string | null {
33
+ return resolveSlotDate(expr, anchor).date
34
+ }
35
+
36
+ /** 语义主键:同目的地+同 start+同 source = 同一行程(重放 no-op) */
37
+ export function makeTripId(ev: Omit<TimelineEvent, 'schema' | 'trip_id' | 'ts'>): string {
38
+ return `${ev.destination}|${ev.start}|${ev.source}`.replace(/\s+/g, '_')
39
+ }
40
+
41
+ /**
42
+ * 追加守门(纯函数,不改入参):
43
+ * - destination/evidence 必填,start 必须已是绝对日期(YYYY-MM-DD),否则拒收(null);
44
+ * - end < start 拒收;
45
+ * - 同 trip_id 已存在 → no-op(返回 appended:false,幂等);
46
+ * - 同目的地日期区间重叠(不同 trip_id)→ 拒收(冲突即停,由人裁决)。
47
+ */
48
+ export function appendTrip(
49
+ events: TimelineEvent[],
50
+ ev: Omit<TimelineEvent, 'schema' | 'trip_id' | 'ts'>,
51
+ ): { events: TimelineEvent[]; appended: boolean; tripId?: string; reason?: string } {
52
+ if (!ev.destination?.trim()) return { events, appended: false, reason: 'destination 必填' }
53
+ if (!ev.evidence?.trim()) return { events, appended: false, reason: 'evidence 必填(用户原话或 wish 确认指针)' }
54
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(ev.start)) return { events, appended: false, reason: 'start 必须为 YYYY-MM-DD(词表外日期由上游解析,不猜)' }
55
+ if (ev.end && ev.end < ev.start) return { events, appended: false, reason: 'end 早于 start' }
56
+ const tripId = makeTripId(ev)
57
+ if (events.some(e => e.trip_id === tripId)) return { events, appended: false, tripId }
58
+ const overlap = events.find(e => e.destination === ev.destination && !(e.end && e.end < ev.start) && !(ev.end && ev.end < e.start))
59
+ if (overlap) return { events, appended: false, tripId: overlap.trip_id, reason: `与已有行程 ${overlap.trip_id} 日期重叠,冲突即停` }
60
+ const full: TimelineEvent = { schema: 'travel_timeline.v1', trip_id: tripId, ts: new Date().toISOString(), ...ev }
61
+ return { events: [...events, full], appended: true, tripId }
62
+ }
63
+
64
+ /** 只读投影:按 start 倒序的行程摘要(「去过」行/brief 注入用) */
65
+ export function projectTimeline(events: TimelineEvent[]): Array<{ tripId: string; destination: string; start: string; end?: string; companions?: string[] }> {
66
+ return [...events]
67
+ .sort((a, b) => (a.start < b.start ? 1 : -1))
68
+ .map(e => ({ tripId: e.trip_id, destination: e.destination, start: e.start, end: e.end, companions: e.companions }))
69
+ }
70
+
71
+ /**
72
+ * 交叉一致(回流率分子的质变):verified_outcome 的 wish 应有对应时间线行程。
73
+ * 返回缺口清单(verified 但无 timeline)——巡检口径,不自动补写(补写需要用户确认日期)。
74
+ */
75
+ export function timelineGapsForVerified(
76
+ timeline: TimelineEvent[],
77
+ verifiedWishes: Array<{ wishId: string; destination?: string }>,
78
+ ): Array<{ wishId: string }> {
79
+ const dests = new Set(timeline.map(t => t.destination))
80
+ return verifiedWishes.filter(w => w.destination && !dests.has(w.destination)).map(w => ({ wishId: w.wishId }))
81
+ }
82
+
83
+ export { ymd }
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Per-agent, per-turn wall-clock boundary driven by routing (ADR-24 v2).
3
+ *
4
+ * 职责只有一件:保证每一轮终结在三态之一——当面答完(converge)、转后台
5
+ * 并给出回访承诺(handoff)、或明确暂停。绝不允许第四态:流死掉、什么
6
+ * 都没交付(2026-09-02 轨迹的失败形态)。
7
+ *
8
+ * - 阈值不再固定:每次 user/message 由 `turn-policy.ts` 的确定性分类器
9
+ * 解析 TurnPolicy(softMs/hardMs/exit);benchmark opt-in 用 fixedPolicy
10
+ * 钉死以保证可复现。
11
+ * - 硬阈拒绝时**同步**抑制工具 schema(防同 step 回环),并按 exit 语义
12
+ * 返回两种结构化结果:converge=用已有证据作答;handoff=落
13
+ * `gotry_turn_handoff.v1` 工单并指令模型告知用户 ETA 与回访方式。
14
+ * - handoff 工单是**新的独立格式**,落在 `<stateRoot>/gotry-state/
15
+ * turn-handoffs/`,不与 `async/` 的 loop 求解工单混用——async-collect
16
+ * 对无 spec 的 state 会立即结算 failed(假失败),收集器是未来的
17
+ * agent tick(loopx),不是 async-collect。
18
+ */
19
+
20
+ import { randomUUID } from 'node:crypto'
21
+ import { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises'
22
+ import { join } from 'node:path'
23
+ import type { Context } from '@deepseek-ai/cordis'
24
+ import type { Agent } from '@deepseek-ai/dsh-agent'
25
+ // 类型面显式依赖:session/event、session/disposed 的事件表声明在 dsh-session 的
26
+ // cordis Events augmentation 里——不显式导入时,该声明只在 peer 恰好物化进
27
+ // ts/node_modules 的机器上可见(legacy-peer-deps 安装则缺,5 个 TS2345/TS7006)。
28
+ import type {} from '@deepseek-ai/dsh-session'
29
+ import type { ToolExecutionResult, ToolExecutionToken } from '@deepseek-ai/dsh-tools'
30
+ import { classifyTurn, TURN_HANDOFF_ETA_LABEL, turnPolicyFor, type TurnPolicy } from './turn-policy.ts'
31
+
32
+ export const TURN_DEADLINE_SOFT = 'TURN_DEADLINE_SOFT'
33
+ export const TURN_DEADLINE_EXHAUSTED = 'TURN_DEADLINE_EXHAUSTED'
34
+ export const TURN_DEADLINE_HANDOFF = 'TURN_DEADLINE_HANDOFF'
35
+ export const TURN_HANDOFF_SCHEMA = 'gotry_turn_handoff.v1' as const
36
+
37
+ export interface TurnHandoffTicket {
38
+ schema: typeof TURN_HANDOFF_SCHEMA
39
+ id: string
40
+ objective: string
41
+ userMessage: string
42
+ requestedAt: string
43
+ etaLabel: string
44
+ status: 'open' | 'settled' | 'failed'
45
+ /** 结算时间(ISO);open 时缺省。 */
46
+ settledAt?: string
47
+ /** 结算交付物文件名(与工单同目录的 .deliverable.md)。 */
48
+ deliverableFile?: string
49
+ /** failed 时的稳定错误描述。 */
50
+ error?: string
51
+ }
52
+
53
+ /** 复访视图:工单事实 + 已结算交付物摘录(有界)。 */
54
+ export interface TurnHandoffTicketView {
55
+ id: string
56
+ status: TurnHandoffTicket['status']
57
+ objective: string
58
+ requestedAt: string
59
+ etaLabel: string
60
+ settledAt?: string
61
+ error?: string
62
+ deliverableExcerpt?: string
63
+ }
64
+
65
+ export interface TurnDeadlineOptions {
66
+ /** When false the install call returns immediately with zero side effects. */
67
+ enabled?: boolean
68
+ /** Benchmark pin: routing is bypassed, every turn gets this exact policy. */
69
+ fixedPolicy?: TurnPolicy
70
+ /** Product: handoff ticket target root. Handoff degrades to converge when absent. */
71
+ stateRoot?: string
72
+ /** Wall-clock source — overridden by tests for determinism. */
73
+ now?: () => number
74
+ }
75
+
76
+ export async function writeTurnHandoffTicket(stateRoot: string, userMessage: string): Promise<TurnHandoffTicket> {
77
+ const ticket: TurnHandoffTicket = {
78
+ schema: TURN_HANDOFF_SCHEMA,
79
+ id: `th-${Date.now().toString(36)}-${randomUUID().slice(0, 6)}`,
80
+ objective: userMessage.length > 120 ? `${userMessage.slice(0, 120)}…` : userMessage,
81
+ userMessage,
82
+ requestedAt: new Date().toISOString(),
83
+ etaLabel: TURN_HANDOFF_ETA_LABEL,
84
+ status: 'open',
85
+ }
86
+ await writeTicketJson(stateRoot, ticket)
87
+ return ticket
88
+ }
89
+
90
+ function handoffDir(stateRoot: string): string {
91
+ const root = stateRoot === '.' ? process.cwd() : stateRoot
92
+ return join(root, 'gotry-state', 'turn-handoffs')
93
+ }
94
+
95
+ async function writeTicketJson(stateRoot: string, ticket: TurnHandoffTicket): Promise<string> {
96
+ const dir = handoffDir(stateRoot)
97
+ await mkdir(dir, { recursive: true })
98
+ const path = join(dir, `${ticket.id}.json`)
99
+ const tmp = `${path}.tmp`
100
+ await writeFile(tmp, JSON.stringify(ticket, null, 2), 'utf-8')
101
+ await rename(tmp, path)
102
+ return path
103
+ }
104
+
105
+ /**
106
+ * 结算工单:交付物落 `<id>.deliverable.md`(settled=规划产物;failed=诚实
107
+ * 失败说明),工单 json 原子更新 status/settledAt/deliverableFile/error。
108
+ */
109
+ export async function settleTurnHandoffTicket(
110
+ stateRoot: string,
111
+ ticket: TurnHandoffTicket,
112
+ status: 'settled' | 'failed',
113
+ deliverable: string,
114
+ error?: string,
115
+ ): Promise<{ ticketPath: string; deliverablePath: string }> {
116
+ const dir = handoffDir(stateRoot)
117
+ await mkdir(dir, { recursive: true })
118
+ const deliverablePath = join(dir, `${ticket.id}.deliverable.md`)
119
+ const deliverableTmp = `${deliverablePath}.tmp`
120
+ await writeFile(deliverableTmp, deliverable, 'utf-8')
121
+ await rename(deliverableTmp, deliverablePath)
122
+ const settled: TurnHandoffTicket = {
123
+ ...ticket,
124
+ status,
125
+ settledAt: new Date().toISOString(),
126
+ deliverableFile: `${ticket.id}.deliverable.md`,
127
+ ...(error ? { error } : {}),
128
+ }
129
+ const ticketPath = await writeTicketJson(stateRoot, settled)
130
+ return { ticketPath, deliverablePath }
131
+ }
132
+
133
+ /** 复访查询:按请求时间倒序列出工单;settled 附交付物摘录(≤600 字)。 */
134
+ export async function listTurnHandoffTickets(stateRoot: string): Promise<TurnHandoffTicketView[]> {
135
+ const dir = handoffDir(stateRoot)
136
+ let names: string[]
137
+ try {
138
+ names = await readdir(dir)
139
+ } catch {
140
+ return []
141
+ }
142
+ const views: TurnHandoffTicketView[] = []
143
+ for (const name of names) {
144
+ if (!name.endsWith('.json')) continue
145
+ try {
146
+ const raw = JSON.parse(await readFile(join(dir, name), 'utf-8')) as TurnHandoffTicket
147
+ if (raw?.schema !== TURN_HANDOFF_SCHEMA) continue
148
+ const view: TurnHandoffTicketView = {
149
+ id: raw.id,
150
+ status: raw.status,
151
+ objective: raw.objective,
152
+ requestedAt: raw.requestedAt,
153
+ etaLabel: raw.etaLabel,
154
+ ...(raw.settledAt ? { settledAt: raw.settledAt } : {}),
155
+ ...(raw.error ? { error: raw.error } : {}),
156
+ }
157
+ if (raw.status !== 'open' && raw.deliverableFile) {
158
+ try {
159
+ const text = await readFile(join(dir, raw.deliverableFile), 'utf-8')
160
+ view.deliverableExcerpt = text.length > 600 ? `${text.slice(0, 600)}…` : text
161
+ } catch { /* 交付物缺失时视图降级,不阻塞列表 */ }
162
+ }
163
+ views.push(view)
164
+ } catch { /* 单个坏工单不阻塞列表 */ }
165
+ }
166
+ views.sort((a, b) => (a.requestedAt < b.requestedAt ? 1 : -1))
167
+ return views
168
+ }
169
+
170
+ function resolveEnvPin(name: string): number | null {
171
+ const raw = process.env[name]
172
+ if (!raw) return null
173
+ const parsed = Number.parseInt(raw, 10)
174
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : null
175
+ }
176
+
177
+ function convergenceContext(code: string, text: string) {
178
+ return {
179
+ id: randomUUID(),
180
+ role: 'user' as const,
181
+ content: [{ type: 'text' as const, text: `${code}: ${text}` }],
182
+ // 0.2.0-rc.2(V4 会话格式)移除 'plugin' source kind;运行时自产注入归 system-prompt。
183
+ source: { kind: 'system-prompt' as const },
184
+ }
185
+ }
186
+
187
+ function exhaustionResult(reason: string): ToolExecutionResult {
188
+ return {
189
+ isError: true,
190
+ error: {
191
+ message: reason,
192
+ info: { name: 'TurnDeadlineError', code: TURN_DEADLINE_EXHAUSTED },
193
+ },
194
+ content: [{ type: 'text', text: reason }],
195
+ additionalContexts: [convergenceContext(
196
+ TURN_DEADLINE_EXHAUSTED,
197
+ 'No more tool dispatches are permitted in this turn. Produce the final answer from existing results.',
198
+ ) as never],
199
+ }
200
+ }
201
+
202
+ function handoffResult(ticket: TurnHandoffTicket): ToolExecutionResult {
203
+ const instruction = `Turn handed off to background planning. Async ticket ${ticket.id} created (ETA ${ticket.etaLabel}). Stop dispatching tools and tell the user in one short message: the deep planning continues in the background, the expected time, and to check back later (mention ticket ${ticket.id}).`
204
+ return {
205
+ isError: true,
206
+ error: {
207
+ message: `${TURN_DEADLINE_HANDOFF}: sync window exhausted for a deep-planning turn; ticket ${ticket.id}`,
208
+ info: { name: 'TurnDeadlineHandoff', code: TURN_DEADLINE_HANDOFF },
209
+ },
210
+ content: [{ type: 'text', text: `${TURN_DEADLINE_HANDOFF}: ${instruction}` }],
211
+ additionalContexts: [convergenceContext(TURN_DEADLINE_HANDOFF, instruction) as never],
212
+ }
213
+ }
214
+
215
+ type RestrictableTools = {
216
+ schemas?: () => Array<{ name: string }>
217
+ restrict?: (filter: { deny: string[] }) => () => void
218
+ }
219
+
220
+ type AgentTurnState = {
221
+ startedAt: number
222
+ policy: TurnPolicy
223
+ userMessage?: string
224
+ }
225
+
226
+ /**
227
+ * Install the runtime boundary, kept separate from the GoTry tool catalog so
228
+ * the actual Cordis waterfalls can be exercised without booting every tool.
229
+ */
230
+ export function installTurnDeadline(ctx: Context, options: TurnDeadlineOptions = {}): void {
231
+ if (options.enabled === false) return
232
+
233
+ // Some offline contract tests intentionally provide a registration-only
234
+ // Context slice. They do not drive an agent loop, so there is no boundary
235
+ // to install and no reason to require an event bus.
236
+ if (typeof (ctx as unknown as { on?: unknown }).on !== 'function') return
237
+
238
+ const now = options.now ?? (() => Date.now())
239
+ // Test/benchmark seam only: pin the resolved numbers without touching the
240
+ // routed exit strategy. Product runs never set these.
241
+ const softPin = resolveEnvPin('GOTRY_TURN_DEADLINE_SOFT_MS')
242
+ const hardPin = resolveEnvPin('GOTRY_TURN_DEADLINE_HARD_MS')
243
+
244
+ const defaultPolicy = options.fixedPolicy ?? turnPolicyFor('sync-planning')
245
+ const routePolicy = (message: string): TurnPolicy => {
246
+ if (options.fixedPolicy) return { ...options.fixedPolicy }
247
+ const policy = turnPolicyFor(classifyTurn(message))
248
+ return { ...policy, softMs: softPin ?? policy.softMs, hardMs: hardPin ?? policy.hardMs }
249
+ }
250
+
251
+ const stateByAgent = new Map<string, AgentTurnState>()
252
+ const softExecutions = new Map<ToolExecutionToken, { agentId: string; exit: string }>()
253
+ const finalOnlyDisposers = new Map<string, () => void>()
254
+
255
+ const clearAgent = (agentId: string) => {
256
+ stateByAgent.delete(agentId)
257
+ for (const [token, owner] of softExecutions) {
258
+ if (owner.agentId === agentId) softExecutions.delete(token)
259
+ }
260
+ finalOnlyDisposers.get(agentId)?.()
261
+ finalOnlyDisposers.delete(agentId)
262
+ }
263
+
264
+ const enterFinalOnly = (agent: Agent) => {
265
+ const agentId = String(agent.id)
266
+ if (finalOnlyDisposers.has(agentId)) return
267
+ const globalTools = ctx.tools as unknown as RestrictableTools
268
+ const scopedTools = agent.ctx?.tools as unknown as RestrictableTools | undefined
269
+ if (typeof globalTools.schemas !== 'function' || typeof scopedTools?.restrict !== 'function') {
270
+ // No registry to suppress: subsequent tool calls in the same turn hit the
271
+ // same per-call denial branch and stay refused until the next turn.
272
+ return
273
+ }
274
+ const inheritedNames = globalTools.schemas()
275
+ .map(schema => schema.name)
276
+ .filter(name => name !== 'run_code')
277
+ if (inheritedNames.length === 0) return
278
+ finalOnlyDisposers.set(agentId, scopedTools.restrict({ deny: inheritedNames }))
279
+ }
280
+
281
+ // 事件主体是 session 对象;agent 归属同一 session 时共用同一预算键。
282
+ const keyOfAgent = (agent: Agent) => {
283
+ const session = (agent as unknown as { session?: { id?: unknown } }).session
284
+ return String(session?.id ?? agent.id)
285
+ }
286
+
287
+ ctx.on('session/event', (subject, event) => {
288
+ const agentId = String(subject.id)
289
+ if (event.type === 'turn/end') {
290
+ clearAgent(agentId)
291
+ return
292
+ }
293
+ if (event.type === 'turn/start') {
294
+ finalOnlyDisposers.get(agentId)?.()
295
+ finalOnlyDisposers.delete(agentId)
296
+ if (!stateByAgent.has(agentId)) {
297
+ stateByAgent.set(agentId, {
298
+ startedAt: now(),
299
+ policy: { ...defaultPolicy, softMs: softPin ?? defaultPolicy.softMs, hardMs: hardPin ?? defaultPolicy.hardMs },
300
+ })
301
+ }
302
+ return
303
+ }
304
+ if (event.type === 'user/message') {
305
+ // dsh 事件载荷在 event.data 下(benchmark-agent-conformance 同型读法)。
306
+ const message = (event as {
307
+ data?: { source?: { kind?: string }; content?: ReadonlyArray<{ type?: string; text?: string }> }
308
+ }).data
309
+ if (message?.source?.kind !== 'user') return
310
+ const text = (message.content ?? []).find(block => block.type === 'text')?.text ?? ''
311
+ if (!text.trim()) return
312
+ // 每个 user 消息 = 新的预算:路由分类 + 时钟重置。plugin/skill 注入
313
+ // 的 user/message(source.kind !== 'user')不参与路由。
314
+ stateByAgent.set(agentId, { startedAt: now(), policy: routePolicy(text), userMessage: text })
315
+ }
316
+ })
317
+ ctx.on('session/disposed', subject => clearAgent(String(subject.id)))
318
+
319
+ ctx.on('tools/execute', (exec, next) => {
320
+ // Programmatic/direct calls are not part of a model planner turn.
321
+ if (!exec.agent) return next()
322
+ const agentId = keyOfAgent(exec.agent)
323
+ const state = stateByAgent.get(agentId)
324
+ ?? { startedAt: now(), policy: { ...defaultPolicy, softMs: softPin ?? defaultPolicy.softMs, hardMs: hardPin ?? defaultPolicy.hardMs } }
325
+ stateByAgent.set(agentId, state)
326
+
327
+ const elapsed = now() - state.startedAt
328
+ if (elapsed > state.policy.hardMs) {
329
+ // Synchronous schema suppression so same-step follow-up calls cannot
330
+ // loop on refusal results (the 2026-09-02 trajectory failure).
331
+ enterFinalOnly(exec.agent)
332
+ if (state.policy.exit === 'handoff' && state.userMessage && options.stateRoot) {
333
+ return writeTurnHandoffTicket(options.stateRoot, state.userMessage)
334
+ .then(ticket => handoffResult(ticket))
335
+ .catch(() => exhaustionResult(
336
+ `${TURN_DEADLINE_EXHAUSTED}: hard deadline ${state.policy.hardMs}ms reached (ticket persistence failed; degraded to converge)`,
337
+ ))
338
+ }
339
+ return Promise.resolve(exhaustionResult(
340
+ `${TURN_DEADLINE_EXHAUSTED}: turn exceeded hard deadline of ${state.policy.hardMs}ms (elapsed ${elapsed}ms); provide a final answer using existing results`,
341
+ ))
342
+ }
343
+ if (elapsed > state.policy.softMs) {
344
+ softExecutions.set(exec.token, { agentId, exit: state.policy.exit })
345
+ }
346
+ return next()
347
+ })
348
+
349
+ ctx.on('tools/post-execute', (exec, _result, next) => {
350
+ return next().then(decision => {
351
+ const owner = softExecutions.get(exec.token)
352
+ if (!owner) return decision
353
+ softExecutions.delete(exec.token)
354
+ const text = owner.exit === 'handoff'
355
+ ? 'Turn has crossed the soft deadline of a deep-planning turn. Wrap up context gathering now; the turn will hand off to background planning at the hard deadline.'
356
+ : 'Turn has crossed the soft deadline. Stop dispatching new tools and produce the final answer from gathered evidence.'
357
+ return {
358
+ ...decision,
359
+ additionalContexts: [
360
+ ...(decision.additionalContexts ?? []),
361
+ convergenceContext(TURN_DEADLINE_SOFT, text) as never,
362
+ ],
363
+ }
364
+ })
365
+ })
366
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Per-turn routing & time allocation (ADR-24 v2).
3
+ *
4
+ * 用户主观时间是产品路径唯一的预算:复杂度决定**出口结构**(converge /
5
+ * handoff),时间只是在所选结构内的资源分配。路由在 user/message 落地时
6
+ * 一次完成,纯函数、零 LLM、零 IO——控制面判定必须是确定性组件
7
+ * (stage1 责任铁律;ADR-9 同型先例),且不能花它要分配的资源。
8
+ *
9
+ * Tier 0(消息内禀)是 v1 的全部规则输入;Tier 1(账本读回)只在
10
+ * handoff 落单时用于工单上下文,不参与分类。`loop.ts` 的 isComplex 是
11
+ * S5 循环架构内的访谈后复核,不在产品路径上,不进本层。
12
+ */
13
+
14
+ export type TaskClass = 'quick' | 'sync-planning' | 'deep-planning'
15
+
16
+ export type TurnExit = 'converge' | 'handoff'
17
+
18
+ export interface TurnPolicy {
19
+ /** 软阈:注入收敛/转出提示,不拦截。 */
20
+ softMs: number
21
+ /** 硬阈:拒绝后续工具派发,按 exit 语义出口。 */
22
+ hardMs: number
23
+ /** 硬阈出口:converge=用已有证据作答;handoff=落工单转后台并告知用户。 */
24
+ exit: TurnExit
25
+ }
26
+
27
+ /** v1 阈值表:数据不是代码;评测/部署换表不换执行器。 */
28
+ export const TURN_POLICIES: Record<TaskClass, TurnPolicy> = {
29
+ // quick:实际上限只是安全网——quick 类历史上没有发散记录。
30
+ quick: { softMs: 120_000, hardMs: 180_000, exit: 'converge' },
31
+ 'sync-planning': { softMs: 300_000, hardMs: 600_000, exit: 'converge' },
32
+ // deep-planning:同步窗口只够"摸底 + 落单承诺",到点必须转后台。
33
+ 'deep-planning': { softMs: 120_000, hardMs: 240_000, exit: 'handoff' },
34
+ }
35
+
36
+ export const TURN_HANDOFF_ETA_LABEL = '约 1 小时'
37
+
38
+ /** 约束词表:只作弱信号(命中≥2 才可能推 deep);新增词=加一行+一测。 */
39
+ export const TURN_CONSTRAINT_LEXICON = [
40
+ '婚礼', '婚宴', '回门', '订婚',
41
+ 'IRW', 'irw',
42
+ '请假', '年假', '调休', '额度',
43
+ '签证', '同行', '伴侣', '亲子', '带娃', '父母', '团建', '出差',
44
+ '红眼', '中转', '联程', '多城',
45
+ ] as const
46
+
47
+ export interface TurnSignals {
48
+ messageLength: number
49
+ /** 消息内的绝对日期(已过 1-12/1-31 校验)。 */
50
+ absoluteDates: Array<{ year: number | null; month: number; day: number }>
51
+ /** 绝对日期≥2 时为极差天数;否则为跨度词天数;都没有则 null。 */
52
+ spanDays: number | null
53
+ /** 命中的约束词(去重,保留词表序)。 */
54
+ constraintHits: string[]
55
+ }
56
+
57
+ const CN_DIGITS: Record<string, number> = {
58
+ 一: 1, 二: 2, 两: 2, 三: 3, 四: 4, 五: 5, 六: 6, 七: 7, 八: 8, 九: 9, 十: 10,
59
+ }
60
+
61
+ function dayCount(year: number | null, month: number, day: number): number {
62
+ // 无年份时按平年锚定:跨度计算只需要差值,月份跨年场景 v1 不覆盖。
63
+ const y = year ?? 1970
64
+ return Date.UTC(y, month - 1, day) / 86_400_000
65
+ }
66
+
67
+ /** 跨度词 → 估算天数;按声明强度取第一个命中,v1 不做组合。 */
68
+ function spanWordDays(message: string): number | null {
69
+ if (/十几天/.test(message)) return 12
70
+ if (/半个月/.test(message)) return 15
71
+ if (/一个月/.test(message)) return 30
72
+ const week = message.match(/[一两]个?(?:星期|周)/)
73
+ if (week) return week[0].startsWith('两') ? 14 : 7
74
+ const dayMatch = message.match(/([0-9一二两三四五六七八九十]+)\s*天/)
75
+ if (dayMatch) {
76
+ const raw = dayMatch[1]
77
+ if (/^[0-9]+$/.test(raw)) return Math.min(Number.parseInt(raw, 10), 60)
78
+ if (CN_DIGITS[raw] !== undefined) return Math.min(CN_DIGITS[raw], 60)
79
+ }
80
+ return null
81
+ }
82
+
83
+ export function extractTurnSignals(message: string): TurnSignals {
84
+ const absoluteDates: TurnSignals['absoluteDates'] = []
85
+
86
+ // 完整日期先摘除,避免 2026-10-03 再被月/日模式重复计数。
87
+ let rest = message.replace(
88
+ /(?<!\d)(\d{4})[年\-.\/](\d{1,2})[月\-.\/](\d{1,2})日?(?!\d)/g,
89
+ (_all, y: string, m: string, d: string) => {
90
+ const month = Number.parseInt(m, 10)
91
+ const day = Number.parseInt(d, 10)
92
+ if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
93
+ absoluteDates.push({ year: Number.parseInt(y, 10), month, day })
94
+ }
95
+ return ' '
96
+ },
97
+ )
98
+ rest = rest.replace(
99
+ /(?<!\d)(\d{1,2})月(\d{1,2})日?(?!\d)/g,
100
+ (_all, m: string, d: string) => {
101
+ const month = Number.parseInt(m, 10)
102
+ const day = Number.parseInt(d, 10)
103
+ if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
104
+ absoluteDates.push({ year: null, month, day })
105
+ }
106
+ return ' '
107
+ },
108
+ )
109
+ rest = rest.replace(
110
+ /(?<!\d)(\d{1,2})[.\/](\d{1,2})(?!\d)/g,
111
+ (_all, m: string, d: string) => {
112
+ const month = Number.parseInt(m, 10)
113
+ const day = Number.parseInt(d, 10)
114
+ if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
115
+ absoluteDates.push({ year: null, month, day })
116
+ }
117
+ return ' '
118
+ },
119
+ )
120
+
121
+ const constraintHits = TURN_CONSTRAINT_LEXICON.filter(word => message.includes(word))
122
+
123
+ let spanDays: number | null = null
124
+ if (absoluteDates.length >= 2) {
125
+ const counts = absoluteDates.map(d => dayCount(d.year, d.month, d.day))
126
+ spanDays = Math.max(...counts) - Math.min(...counts)
127
+ } else {
128
+ spanDays = spanWordDays(message)
129
+ }
130
+
131
+ return { messageLength: message.length, absoluteDates, spanDays, constraintHits }
132
+ }
133
+
134
+ /**
135
+ * 分类规则(有序,可表测):长跨度或多约束 → deep(转后台);无日期无约束
136
+ * 且短 → quick;其余落默认中间档 sync-planning。误分有界:三态出口保证
137
+ * 最坏结局是"本可当面答的被转了后台"(下一轮可救),而非流死掉。
138
+ */
139
+ export function classifyTurn(message: string): TaskClass {
140
+ const s = extractTurnSignals(message)
141
+ if (s.spanDays !== null && s.spanDays >= 7) return 'deep-planning'
142
+ if (s.absoluteDates.length >= 2 && s.constraintHits.length >= 1) return 'deep-planning'
143
+ if (s.constraintHits.length >= 2 && (s.absoluteDates.length >= 1 || s.spanDays !== null)) {
144
+ return 'deep-planning'
145
+ }
146
+ if (s.absoluteDates.length === 0 && s.constraintHits.length === 0 && s.spanDays === null && s.messageLength <= 60) {
147
+ return 'quick'
148
+ }
149
+ return 'sync-planning'
150
+ }
151
+
152
+ export function turnPolicyFor(taskClass: TaskClass): TurnPolicy {
153
+ return { ...TURN_POLICIES[taskClass] }
154
+ }