@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,538 @@
1
+ import { accessSync, constants, lstatSync, readFileSync, statSync } from 'node:fs'
2
+ import { getuid } from 'node:process'
3
+ import { isAbsolute } from 'node:path'
4
+ import {
5
+ assertSupportedJsonSchema,
6
+ validateJsonSchemaValue,
7
+ ToolArgsError,
8
+ type ObjectJsonSchema,
9
+ type ToolDefinition,
10
+ } from '@deepseek-ai/dsh-tools'
11
+ import {
12
+ validateTerminalOutputConfig,
13
+ type BenchmarkBridgeProjection,
14
+ type TerminalOutputConfig,
15
+ } from './benchmark-agent-conformance.ts'
16
+
17
+ // v4(#215 Round 12):terminal_output 携带 closed body schema(结构关键字白名单,
18
+ // 禁数据值注解面);v3 及更早配置缺该面,按契约不兼容 fail-closed。
19
+ const SCHEMA_VERSION = 'gotry_benchmark_environment_bridge_v4'
20
+ export const BENCHMARK_TOOL_RESULT_SCHEMA_VERSION = 'gotry_benchmark_tool_result_v1'
21
+ export const BENCHMARK_DOMAIN_RECOVERIES = ['none', 'retry_same', 'revise_arguments', 'choose_alternative'] as const
22
+ type BenchmarkDomainRecovery = typeof BENCHMARK_DOMAIN_RECOVERIES[number]
23
+ const IDENTIFIER = /^[A-Za-z][A-Za-z0-9_.-]*$/
24
+ const RECOVERIES = new Set<string>(BENCHMARK_DOMAIN_RECOVERIES)
25
+ const CONFIG_KEYS = ['argv_prefix', 'cwd', 'enabled', 'executable', 'isolation', 'max_output_bytes', 'schema_version', 'terminal_output', 'timeout_ms', 'tools']
26
+ const INPUT_SCHEMA_MAX_BYTES = 16 * 1024
27
+ const INPUT_SCHEMA_MAX_DEPTH = 8
28
+ const INPUT_SCHEMA_MAX_NODES = 256
29
+ const INPUT_SCHEMA_MAX_PROPERTIES = 256
30
+ const INPUT_SCHEMA_MAX_ENUM_VALUES = 256
31
+ const INPUT_SCHEMA_MAX_DESCRIPTION_LENGTH = 512
32
+ const INPUT_SCHEMA_TYPES = new Set(['string', 'number', 'integer', 'boolean', 'null', 'array', 'object'])
33
+
34
+ export interface BenchmarkEnvironmentBridgeConfig {
35
+ schema_version: typeof SCHEMA_VERSION
36
+ enabled: true
37
+ executable: string
38
+ cwd: string
39
+ argv_prefix: string[]
40
+ tools: BenchmarkToolDescriptor[]
41
+ timeout_ms: number
42
+ max_output_bytes: number
43
+ terminal_output: TerminalOutputConfig
44
+ isolation: {
45
+ mode: 'host-enforced'
46
+ writes: 'forbidden'
47
+ network: 'denied'
48
+ }
49
+ }
50
+
51
+ export interface BenchmarkToolDescriptor {
52
+ name: string
53
+ description: string
54
+ input_schema: ObjectJsonSchema
55
+ output_keys: string[]
56
+ domain_outcomes: Array<{ status: 'miss' | 'error'; code: string; recovery: BenchmarkDomainRecovery }>
57
+ }
58
+
59
+ function plainObject(value: unknown): value is Record<string, unknown> {
60
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
61
+ }
62
+
63
+ function deepFreezeJson<T>(value: T): T {
64
+ if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value
65
+ for (const child of Object.values(value as Record<string, unknown>)) deepFreezeJson(child)
66
+ return Object.freeze(value)
67
+ }
68
+
69
+ function existingExecutable(value: unknown): value is string {
70
+ if (typeof value !== 'string' || !isAbsolute(value)) return false
71
+ try {
72
+ const stat = statSync(value)
73
+ accessSync(value, constants.X_OK)
74
+ return stat.isFile()
75
+ } catch {
76
+ return false
77
+ }
78
+ }
79
+
80
+ function existingDirectory(value: unknown): value is string {
81
+ if (typeof value !== 'string' || !isAbsolute(value)) return false
82
+ try {
83
+ return statSync(value).isDirectory()
84
+ } catch {
85
+ return false
86
+ }
87
+ }
88
+
89
+ function identifiers(value: unknown, allowEmpty = false): value is string[] {
90
+ return Array.isArray(value) && (allowEmpty || value.length > 0) && value.length <= 64 && new Set(value).size === value.length && value.every(
91
+ item => typeof item === 'string' && item.length > 0 && IDENTIFIER.test(item),
92
+ )
93
+ }
94
+
95
+ function exactKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {
96
+ return Object.keys(value).every(key => allowed.includes(key))
97
+ }
98
+
99
+ function validDescription(value: unknown, required = false): boolean {
100
+ if (value === undefined) return !required
101
+ return typeof value === 'string'
102
+ && (!required || value.trim().length > 0)
103
+ && value.length <= INPUT_SCHEMA_MAX_DESCRIPTION_LENGTH
104
+ && !/[\u0000-\u001f\u007f]/.test(value)
105
+ }
106
+
107
+ function scalarMatches(type: string, value: unknown): boolean {
108
+ if (type === 'string') return typeof value === 'string' && value.length <= 512
109
+ if (type === 'number') return typeof value === 'number' && Number.isFinite(value)
110
+ if (type === 'integer') return typeof value === 'number' && Number.isSafeInteger(value)
111
+ if (type === 'boolean') return typeof value === 'boolean'
112
+ return type === 'null' && value === null
113
+ }
114
+
115
+ function validInputSchema(value: unknown): value is ObjectJsonSchema {
116
+ if (!plainObject(value)) return false
117
+ let serialized: string
118
+ try {
119
+ serialized = JSON.stringify(value)
120
+ } catch {
121
+ return false
122
+ }
123
+ if (Buffer.byteLength(serialized, 'utf8') > INPUT_SCHEMA_MAX_BYTES) return false
124
+
125
+ const pending: Array<{ node: Record<string, unknown>; depth: number }> = [{ node: value, depth: 0 }]
126
+ const seen = new Set<object>()
127
+ let nodes = 0
128
+ let properties = 0
129
+ let enumValues = 0
130
+ while (pending.length > 0) {
131
+ const { node, depth } = pending.pop()!
132
+ if (seen.has(node) || ++nodes > INPUT_SCHEMA_MAX_NODES || depth > INPUT_SCHEMA_MAX_DEPTH) return false
133
+ seen.add(node)
134
+ if (!INPUT_SCHEMA_TYPES.has(String(node.type)) || !validDescription(node.description)) return false
135
+
136
+ if (node.type === 'object') {
137
+ if (!exactKeys(node, ['type', 'description', 'properties', 'required', 'additionalProperties'])
138
+ || !plainObject(node.properties)
139
+ || !Array.isArray(node.required)
140
+ || node.additionalProperties !== false) return false
141
+ const propertyEntries = Object.entries(node.properties)
142
+ properties += propertyEntries.length
143
+ if (properties > INPUT_SCHEMA_MAX_PROPERTIES || propertyEntries.some(([key, child]) => !IDENTIFIER.test(key) || !plainObject(child))) return false
144
+ const required = node.required
145
+ if (required.length > propertyEntries.length
146
+ || new Set(required).size !== required.length
147
+ || required.some(key => typeof key !== 'string' || !Object.hasOwn(node.properties as Record<string, unknown>, key))) return false
148
+ for (const [, child] of propertyEntries) pending.push({ node: child as Record<string, unknown>, depth: depth + 1 })
149
+ continue
150
+ }
151
+
152
+ if (node.type === 'array') {
153
+ if (!exactKeys(node, ['type', 'description', 'items']) || !plainObject(node.items)) return false
154
+ pending.push({ node: node.items, depth: depth + 1 })
155
+ continue
156
+ }
157
+
158
+ if (!exactKeys(node, ['type', 'description', 'enum', 'const'])
159
+ || (Object.hasOwn(node, 'enum') && Object.hasOwn(node, 'const'))) return false
160
+ if (Object.hasOwn(node, 'const') && !scalarMatches(String(node.type), node.const)) return false
161
+ if (Object.hasOwn(node, 'enum')) {
162
+ if (!Array.isArray(node.enum) || node.enum.length === 0 || node.enum.length > 64) return false
163
+ enumValues += node.enum.length
164
+ if (enumValues > INPUT_SCHEMA_MAX_ENUM_VALUES
165
+ || new Set(node.enum).size !== node.enum.length
166
+ || node.enum.some(item => !scalarMatches(String(node.type), item))) return false
167
+ }
168
+ }
169
+ return value.type === 'object'
170
+ }
171
+
172
+ function toolDescriptors(value: unknown): value is BenchmarkToolDescriptor[] {
173
+ if (!Array.isArray(value) || value.length === 0 || value.length > 64) return false
174
+ const names = new Set<string>()
175
+ return value.every(item => {
176
+ if (!plainObject(item)) return false
177
+ const keys = Object.keys(item).sort()
178
+ const required = ['description', 'domain_outcomes', 'input_schema', 'name']
179
+ if (JSON.stringify(keys) !== JSON.stringify([...required, 'output_keys'].sort())) return false
180
+ if (typeof item.name !== 'string' || !IDENTIFIER.test(item.name) || names.has(item.name)) return false
181
+ names.add(item.name)
182
+ if (!validDescription(item.description, true) || !validInputSchema(item.input_schema)) return false
183
+ if (!Array.isArray(item.domain_outcomes) || item.domain_outcomes.length > 64) return false
184
+ const outcomeKeys = new Set<string>()
185
+ if (!item.domain_outcomes.every(outcome => plainObject(outcome)
186
+ && JSON.stringify(Object.keys(outcome).sort()) === JSON.stringify(['code', 'recovery', 'status'])
187
+ && (outcome.status === 'miss' || outcome.status === 'error')
188
+ && typeof outcome.code === 'string' && IDENTIFIER.test(outcome.code)
189
+ && typeof outcome.recovery === 'string' && RECOVERIES.has(outcome.recovery)
190
+ && !outcomeKeys.has(outcome.code)
191
+ && (outcomeKeys.add(outcome.code), true))) return false
192
+ return identifiers(item.output_keys)
193
+ })
194
+ }
195
+
196
+ // These are passed as direct argv entries (never through a shell), so options
197
+ // such as "-m" and dotted module names are valid. Keep the prefix bounded and
198
+ // reject line/control separators that could make diagnostics ambiguous.
199
+ function argvPrefix(value: unknown): value is string[] {
200
+ return Array.isArray(value) && value.length > 0 && value.length <= 32 && value.every(
201
+ item => typeof item === 'string'
202
+ && item.length > 0
203
+ && item.length <= 256
204
+ && !item.includes('\0')
205
+ && !item.includes('\r')
206
+ && !item.includes('\n'),
207
+ )
208
+ }
209
+
210
+ function exactIsolation(value: unknown): value is BenchmarkEnvironmentBridgeConfig['isolation'] {
211
+ if (!plainObject(value)) return false
212
+ const keys = Object.keys(value).sort()
213
+ return JSON.stringify(keys) === JSON.stringify(['mode', 'network', 'writes'])
214
+ && value.mode === 'host-enforced'
215
+ && value.writes === 'forbidden'
216
+ && value.network === 'denied'
217
+ }
218
+
219
+ function validBound(value: unknown, maximum: number): value is number {
220
+ return typeof value === 'number' && Number.isInteger(value) && value >= 1 && value <= maximum
221
+ }
222
+
223
+ function validate(value: unknown): value is BenchmarkEnvironmentBridgeConfig {
224
+ const configKeys = plainObject(value) ? Object.keys(value).sort() : []
225
+ const baseKeys = [...CONFIG_KEYS].sort()
226
+ if (!plainObject(value)
227
+ || JSON.stringify(configKeys) !== JSON.stringify(baseKeys)
228
+ || value.schema_version !== SCHEMA_VERSION
229
+ || value.enabled !== true
230
+ || !existingExecutable(value.executable)
231
+ || !existingDirectory(value.cwd)
232
+ || !argvPrefix(value.argv_prefix)
233
+ || !toolDescriptors(value.tools)
234
+ || !validBound(value.timeout_ms, 120_000)
235
+ || !validBound(value.max_output_bytes, 10 * 1024 * 1024)
236
+ || !validateTerminalOutputConfig(value.terminal_output)
237
+ || !exactIsolation(value.isolation)
238
+ ) return false
239
+ return true
240
+ }
241
+
242
+ /** Read and validate an owner-local bridge config without exposing its contents. */
243
+ export function loadBenchmarkEnvironmentConfig(path: string): BenchmarkEnvironmentBridgeConfig | null {
244
+ try {
245
+ if (!isAbsolute(path)) return null
246
+ const metadata = lstatSync(path)
247
+ if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.size > 64 * 1024) return null
248
+ if (typeof getuid !== 'function' || metadata.uid !== getuid()) return null
249
+ if ((metadata.mode & 0o022) !== 0) return null
250
+ const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'))
251
+ return validate(parsed) ? deepFreezeJson(parsed) : null
252
+ } catch {
253
+ return null
254
+ }
255
+ }
256
+
257
+ type Register = (tool: ToolDefinition) => void
258
+ interface CollectedText {
259
+ readFrom(offset: number): { text: string; nextOffset: number; lossy?: boolean }
260
+ }
261
+
262
+ interface SubprocessHandle {
263
+ collected: { stdout: CollectedText; stderr: CollectedText }
264
+ done: Promise<{ exitCode: number | null; signal?: string | null }>
265
+ terminate?: () => void
266
+ }
267
+
268
+ export interface BenchmarkSubprocessService {
269
+ spawn(spec: {
270
+ argv: readonly string[]
271
+ cwd: string
272
+ stdio: {
273
+ stdin: 'ignore'
274
+ stdout: { maxBytes: number }
275
+ stderr: { maxBytes: number }
276
+ }
277
+ graceMs: number
278
+ env?: NodeJS.ProcessEnv
279
+ signal?: AbortSignal
280
+ }): SubprocessHandle
281
+ }
282
+
283
+ function structuredObject(text: string): Record<string, unknown> | null {
284
+ try {
285
+ const parsed: unknown = JSON.parse(text.trim())
286
+ return plainObject(parsed) ? parsed : null
287
+ } catch {
288
+ return null
289
+ }
290
+ }
291
+
292
+ function jsonObject(value: unknown): Record<string, never> {
293
+ return JSON.parse(JSON.stringify(value)) as Record<string, never>
294
+ }
295
+
296
+ const FORBIDDEN_OUTPUT_KEY_FRAGMENTS = [
297
+ 'answer', 'expected', 'gold', 'groundtruth', 'hiddenquery', 'label',
298
+ 'loadermetadata', 'oracle', 'reference', 'reward', 'score',
299
+ ]
300
+
301
+ export const BRIDGE_ERROR_CONTRACT: Record<string, { recoverable: boolean; remedy: string }> = Object.freeze({
302
+ invalid_action: { recoverable: true, remedy: 'action 只允许 tools、call 或 errors' },
303
+ disallowed_tool: { recoverable: true, remedy: '先 action=tools 列出 allowed_tools 清单,再从清单内选工具' },
304
+ invalid_arguments: { recoverable: true, remedy: 'arguments 必须是可序列化 JSON 对象(≤64KB、深度≤12);收窄后重试' },
305
+ timed_out: { recoverable: true, remedy: '上游超时;可原样重试一次或换其他工具' },
306
+ output_truncated: { recoverable: true, remedy: '输出超出上限;让被调工具收窄查询范围后重试' },
307
+ invalid_json: { recoverable: true, remedy: '上游输出不是合法 JSON;重试一次或换工具' },
308
+ invalid_output: { recoverable: true, remedy: '上游输出结构不符;重试或换工具' },
309
+ runner_failed: { recoverable: true, remedy: '上游进程非零退出;可重试一次,持续失败换工具' },
310
+ spawn_failed: { recoverable: false, remedy: '可执行文件不可用——环境问题,调用方不可恢复' },
311
+ forbidden_output: { recoverable: false, remedy: '输出含未授权键(策略边界)——不可恢复,换工具或放弃' },
312
+ })
313
+
314
+ function inspectOutput(value: unknown): 'ok' | 'forbidden_key' | 'structure_limit' {
315
+ const pending: Array<{ value: unknown; depth: number }> = [{ value, depth: 0 }]
316
+ let nodes = 0
317
+ while (pending.length > 0) {
318
+ const current = pending.pop()!
319
+ if (++nodes > 10_000 || current.depth > 24) return 'structure_limit'
320
+ if (Array.isArray(current.value)) {
321
+ for (const child of current.value) pending.push({ value: child, depth: current.depth + 1 })
322
+ continue
323
+ }
324
+ if (!plainObject(current.value)) continue
325
+ for (const [key, child] of Object.entries(current.value)) {
326
+ if (!/^[\x20-\x7E]+$/.test(key)) return 'forbidden_key'
327
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, '')
328
+ if (FORBIDDEN_OUTPUT_KEY_FRAGMENTS.some(fragment => normalized.includes(fragment))) return 'forbidden_key'
329
+ pending.push({ value: child, depth: current.depth + 1 })
330
+ }
331
+ }
332
+ return 'ok'
333
+ }
334
+
335
+ function inspectAllowedOutput(value: unknown, allowedKeys: string[]): boolean {
336
+ const allowed = new Set(allowedKeys)
337
+ const pending: Array<{ value: unknown; depth: number; coveredByDeclaredKey: boolean }> = [{ value, depth: 0, coveredByDeclaredKey: false }]
338
+ let nodes = 0
339
+ while (pending.length > 0) {
340
+ const current = pending.pop()!
341
+ if (++nodes > 10_000 || current.depth > 24) return false
342
+ if (Array.isArray(current.value)) {
343
+ for (const child of current.value) pending.push({ value: child, depth: current.depth + 1, coveredByDeclaredKey: current.coveredByDeclaredKey })
344
+ continue
345
+ }
346
+ if (!plainObject(current.value)) {
347
+ if (!current.coveredByDeclaredKey) return false
348
+ continue
349
+ }
350
+ for (const [key, child] of Object.entries(current.value)) {
351
+ if (!allowed.has(key)) return false
352
+ pending.push({ value: child, depth: current.depth + 1, coveredByDeclaredKey: true })
353
+ }
354
+ }
355
+ return true
356
+ }
357
+
358
+ function serializedArguments(value: Record<string, unknown>): { json: string; reason?: never } | { json?: never; reason: string } {
359
+ const seen = new Set<object>()
360
+ let nodes = 0
361
+ let keys = 0
362
+ const inspect = (current: unknown, depth: number): boolean => {
363
+ if (++nodes > 10_000 || depth > 12) return false
364
+ if (current && typeof current === 'object') {
365
+ if (seen.has(current)) return false
366
+ seen.add(current)
367
+ if (Array.isArray(current)) return current.every(item => inspect(item, depth + 1))
368
+ return Object.entries(current).every(([key, child]) => {
369
+ if (++keys > 10_000) return false
370
+ return inspect(key, depth + 1) && inspect(child, depth + 1)
371
+ })
372
+ }
373
+ return true
374
+ }
375
+ if (!inspect(value, 0)) return { reason: 'serialization_limit' }
376
+ try {
377
+ const json = JSON.stringify(value)
378
+ if (typeof json !== 'string' || Buffer.byteLength(json, 'utf8') > 65_536) return { reason: 'serialization_limit' }
379
+ return { json }
380
+ } catch {
381
+ return { reason: 'serialization_limit' }
382
+ }
383
+ }
384
+
385
+ /** Register the opt-in model-facing bridge. */
386
+ export function registerBenchmarkEnvironmentBridge(
387
+ path: string,
388
+ register: Register,
389
+ subprocess?: BenchmarkSubprocessService,
390
+ ): BenchmarkBridgeProjection {
391
+ const bridge = loadBenchmarkEnvironmentConfig(path)
392
+ if (!bridge) throw new Error('benchmark environment bridge configuration unavailable')
393
+ if (!subprocess) throw new Error('benchmark environment bridge subprocess unavailable')
394
+
395
+ const parameters: Record<string, unknown> = deepFreezeJson({
396
+ type: 'object',
397
+ description: 'Flat benchmark bridge wire: choose an action, then provide the mapped tool and its arguments.',
398
+ properties: {
399
+ action: { type: 'string', enum: ['tools', 'call', 'errors'], description: 'tools=列出可调工具;call=执行工具;errors=拉取错误契约' },
400
+ tool: { type: 'string', enum: bridge.tools.map(item => item.name), description: 'action=call 时选择的冻结工具名' },
401
+ arguments: { type: 'object', additionalProperties: true, description: 'action=call 时传给工具的参数对象' },
402
+ },
403
+ required: ['action'],
404
+ additionalProperties: false,
405
+ })
406
+ assertSupportedJsonSchema(parameters)
407
+
408
+ const definition: ToolDefinition = {
409
+ name: 'gotry_benchmark_environment',
410
+ description: 'When a prompt asks to run agent_env.cli, use action=call here with the mapped tool; arbitrary shell is not exposed.',
411
+ parameters,
412
+ output: {
413
+ schema: {},
414
+ render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }],
415
+ },
416
+ async execute(args: unknown): Promise<Record<string, never>> {
417
+ const violations = validateJsonSchemaValue(parameters, args, 'arguments')
418
+ if (violations.length > 0) throw new ToolArgsError(violations)
419
+ const query = args as Record<string, unknown>
420
+ const tool = query.tool
421
+ const descriptor = bridge.tools.find(item => item.name === tool)
422
+ const keys = Object.keys(query)
423
+ if (query.action === 'tools') {
424
+ if (keys.length !== 1) throw new ToolArgsError(['arguments: tools action accepts no tool or arguments'])
425
+ return jsonObject({ ok: true, tools: bridge.tools })
426
+ }
427
+ if (query.action === 'errors') {
428
+ if (keys.length !== 1) throw new ToolArgsError(['arguments: errors action accepts no tool or arguments'])
429
+ return jsonObject({ ok: true, errors: BRIDGE_ERROR_CONTRACT })
430
+ }
431
+ if (query.action !== 'call') {
432
+ return jsonObject({ ok: false, error: 'invalid_action' })
433
+ }
434
+ if (keys.length !== 3 || !Object.hasOwn(query, 'tool') || !Object.hasOwn(query, 'arguments')) {
435
+ throw new ToolArgsError(['arguments: call action requires exactly tool and arguments'])
436
+ }
437
+ if (typeof tool !== 'string' || !descriptor) {
438
+ return jsonObject({ ok: false, error: 'disallowed_tool' })
439
+ }
440
+ if (!plainObject(query.arguments)) {
441
+ return jsonObject({ ok: false, error: 'invalid_arguments' })
442
+ }
443
+ const callArguments = query.arguments
444
+ const argumentViolations = validateJsonSchemaValue(descriptor.input_schema, callArguments, 'arguments')
445
+ if (argumentViolations.length > 0) throw new ToolArgsError(argumentViolations)
446
+ const serialized = serializedArguments(callArguments)
447
+ if (serialized.reason) return jsonObject({ ok: false, error: 'invalid_arguments', reason: serialized.reason })
448
+ const controller = new AbortController()
449
+ const timer = setTimeout(() => {
450
+ controller.abort()
451
+ }, bridge.timeout_ms)
452
+ let handle: SubprocessHandle | undefined
453
+ try {
454
+ const env: NodeJS.ProcessEnv = Object.fromEntries(
455
+ Object.keys(process.env).map(key => [key, undefined]),
456
+ )
457
+ for (const key of ['PATH', 'LANG', 'LC_ALL', 'LC_CTYPE', 'TZ']) {
458
+ if (process.env[key] !== undefined) env[key] = process.env[key]!
459
+ }
460
+ env.PYTHONDONTWRITEBYTECODE = '1'
461
+ env.PYTHONNOUSERSITE = '1'
462
+ try {
463
+ handle = subprocess.spawn({
464
+ argv: [bridge.executable, ...bridge.argv_prefix, 'call', tool, serialized.json!],
465
+ cwd: bridge.cwd,
466
+ stdio: {
467
+ stdin: 'ignore',
468
+ stdout: { maxBytes: bridge.max_output_bytes },
469
+ stderr: { maxBytes: bridge.max_output_bytes },
470
+ },
471
+ graceMs: Math.min(1_000, bridge.timeout_ms),
472
+ env,
473
+ signal: controller.signal,
474
+ })
475
+ } catch {
476
+ if (controller.signal.aborted) return jsonObject({ ok: false, error: 'timed_out' })
477
+ return jsonObject({ ok: false, error: 'spawn_failed' })
478
+ }
479
+ let status: { exitCode: number | null; signal?: string | null }
480
+ try {
481
+ status = await handle!.done
482
+ } catch {
483
+ if (controller.signal.aborted) return jsonObject({ ok: false, error: 'timed_out' })
484
+ return jsonObject({ ok: false, error: 'spawn_failed' })
485
+ }
486
+ if (controller.signal.aborted) return jsonObject({ ok: false, error: 'timed_out' })
487
+ let stdout: { text: string; lossy?: boolean }
488
+ let stderr: { text: string; lossy?: boolean }
489
+ try {
490
+ stdout = handle!.collected.stdout.readFrom(0)
491
+ stderr = handle!.collected.stderr.readFrom(0)
492
+ } catch {
493
+ return jsonObject({
494
+ ok: false,
495
+ error: 'runner_failed',
496
+ exit_code: status.exitCode,
497
+ signal: status.signal ?? null,
498
+ })
499
+ }
500
+ if (stdout.lossy || stderr.lossy) return jsonObject({ ok: false, error: 'output_truncated' })
501
+ if (status.exitCode !== 0) {
502
+ return jsonObject({
503
+ ok: false,
504
+ error: 'runner_failed',
505
+ exit_code: status.exitCode,
506
+ signal: status.signal ?? null,
507
+ })
508
+ }
509
+ const parsed = structuredObject(stdout.text)
510
+ if (!parsed) return jsonObject({ ok: false, error: 'invalid_json' })
511
+ const outputInspection = inspectOutput(parsed)
512
+ if (outputInspection === 'forbidden_key') return jsonObject({ ok: false, error: 'forbidden_output' })
513
+ if (outputInspection === 'structure_limit') return jsonObject({ ok: false, error: 'invalid_output' })
514
+ if (parsed.schema_version !== BENCHMARK_TOOL_RESULT_SCHEMA_VERSION || typeof parsed.status !== 'string') {
515
+ return jsonObject({ ok: false, error: 'invalid_output' })
516
+ }
517
+ if (parsed.status === 'miss' || parsed.status === 'error') {
518
+ if (typeof parsed.code !== 'string' || typeof parsed.recovery !== 'string' || !descriptor.domain_outcomes.some(outcome => outcome.status === parsed.status && outcome.code === parsed.code && outcome.recovery === parsed.recovery)) return jsonObject({ ok: false, error: 'invalid_output' })
519
+ if (Object.keys(parsed).sort().join(',') !== 'code,recovery,schema_version,status') return jsonObject({ ok: false, error: 'invalid_output' })
520
+ return jsonObject({ ok: true, outcome: parsed })
521
+ }
522
+ if (parsed.status !== 'ok' || !Object.hasOwn(parsed, 'result') || Object.keys(parsed).sort().join(',') !== 'result,schema_version,status') return jsonObject({ ok: false, error: 'invalid_output' })
523
+ const visibleResult = parsed.result
524
+ if (!plainObject(visibleResult) && !Array.isArray(visibleResult)) return jsonObject({ ok: false, error: 'invalid_output' })
525
+ if (!inspectAllowedOutput(visibleResult, descriptor.output_keys)) return jsonObject({ ok: false, error: 'forbidden_output' })
526
+ return jsonObject({ ok: true, result: visibleResult })
527
+ } finally {
528
+ clearTimeout(timer)
529
+ }
530
+ },
531
+ }
532
+ register(definition)
533
+ return Object.freeze({
534
+ toolName: 'gotry_benchmark_environment',
535
+ allowedTools: Object.freeze(bridge.tools.map(item => item.name)),
536
+ terminal: Object.freeze({ ...bridge.terminal_output }),
537
+ })
538
+ }