@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,388 @@
1
+ /**
2
+ * FlyAI API key 配置面(issue #521;供应商 skill setup 体验核心)。
3
+ *
4
+ * 与官方 @fly-ai/flyai-cli 1.0.16 的配置机制严格对齐(解包核实,非猜测):
5
+ * key = env FLYAI_API_KEY(trim 非空)→ env DEBUG_FLYAI_API_KEY(trim 非空)
6
+ * → ~/.flyai/config.json 的 FLYAI_API_KEY 字段 → 内置共享 key(匿名试用);
7
+ * endpoint = env DEBUG_FLYAI_MCP_URL(trim 非空)→ 官方默认;
8
+ * 空串/纯空白 env 一律视为未设置(官方 helper 用 c&&c.trim()!=='' 判定,
9
+ * 不是 nullish 判定)。
10
+ *
11
+ * 文件路径/格式 = 官方 `flyai config set` 的 ~/.flyai/config.json 扁平 JSON;
12
+ * 写时读入整对象只动 FLYAI_API_KEY,其他字段原样保留。
13
+ *
14
+ * 安全契约:
15
+ * - 原配置损坏(坏 JSON/非对象)→ save/clear/write 全部拒绝并保留原字节,
16
+ * 由调用方向用户显式报错;绝不静默覆盖丢字段;
17
+ * - 原子写 = tmp 文件 + rename;finally 中删除本操作拥有的 tmp,
18
+ * rename 失败也不留含明文的残留文件;
19
+ * - 权限是硬要求:目录 0700、文件 0600 必须实测;chmod 失败即整体失败,
20
+ * best-effort 不算安全存储;
21
+ * - 对外面只回显 maskFlyaiKey 脱敏值。
22
+ *
23
+ * @module capabilities/flyai-config
24
+ */
25
+
26
+ import { createHash } from 'node:crypto'
27
+ import {
28
+ chmodSync,
29
+ existsSync,
30
+ lstatSync,
31
+ mkdirSync,
32
+ readFileSync,
33
+ renameSync,
34
+ rmSync,
35
+ statSync,
36
+ writeFileSync,
37
+ } from 'node:fs'
38
+ import { homedir } from 'node:os'
39
+ import { dirname, join } from 'node:path'
40
+
41
+ export type FlyaiKeySource = 'env' | 'env-debug' | 'config' | 'none'
42
+
43
+ export interface FlyaiConfigPaths {
44
+ homeDir?: string
45
+ env?: NodeJS.ProcessEnv
46
+ }
47
+
48
+ export interface ResolvedFlyaiKey {
49
+ key?: string
50
+ source: FlyaiKeySource
51
+ /** ~/.flyai/config.json 绝对路径(无论是否存在) */
52
+ configPath: string
53
+ /** 脱敏值(source!=='none' 时) */
54
+ maskedKey?: string
55
+ }
56
+
57
+ export interface ResolvedFlyaiEndpoint {
58
+ url: string
59
+ /** true = 被 DEBUG_FLYAI_MCP_URL 覆盖(展示必须标注) */
60
+ debug: boolean
61
+ }
62
+
63
+ export interface SaveFlyaiKeyResult {
64
+ ok: boolean
65
+ savedTo?: string
66
+ /** 写入后当前实际生效来源(env 优先时文件写入不改生效来源) */
67
+ source?: FlyaiKeySource
68
+ maskedKey?: string
69
+ error?: string
70
+ envActive?: boolean
71
+ }
72
+
73
+ export interface ClearFlyaiKeyResult {
74
+ ok: boolean
75
+ removedFrom?: string
76
+ source: FlyaiKeySource
77
+ maskedKey?: string
78
+ error?: string
79
+ }
80
+
81
+ export function flyaiConfigPath(homeDir: string): string {
82
+ return join(homeDir, '.flyai', 'config.json')
83
+ }
84
+
85
+ /** ~/.gotry/flyai-verification.json(与 calendar.json 同 ~/.gotry) */
86
+ export function flyaiVerificationPath(homeDir: string): string {
87
+ return join(homeDir, '.gotry', 'flyai-verification.json')
88
+ }
89
+
90
+ /** 与官方 1.0.16 同款:存在且 trim 非空才算值;空串/空白/非字符串 = undefined */
91
+ function nonEmpty(value: unknown): string | undefined {
92
+ if (typeof value !== 'string') return undefined
93
+ const text = value.trim()
94
+ return text || undefined
95
+ }
96
+
97
+ export type FlyaiConfigRead =
98
+ | { ok: true; data: Record<string, unknown> }
99
+ | { ok: false; error: string }
100
+
101
+ /**
102
+ * 严格读取 config.json:
103
+ * 不存在/空文件 → ok+空对象;
104
+ * JSON 损坏/顶层非对象 → ok:false(调用方必须拒绝写入并保留字节)。
105
+ */
106
+ export function readFlyaiConfig(configPath: string): FlyaiConfigRead {
107
+ try {
108
+ if (!existsSync(configPath)) return { ok: true, data: {} }
109
+ const text = readFileSync(configPath, 'utf8')
110
+ if (!text.trim()) return { ok: true, data: {} }
111
+ const parsed: unknown = JSON.parse(text)
112
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
113
+ return { ok: false, error: 'config 顶层不是 JSON 对象' }
114
+ }
115
+ return { ok: true, data: parsed as Record<string, unknown> }
116
+ } catch {
117
+ return { ok: false, error: 'config JSON 解析失败(为保护凭据,不显示原文)' }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * 解析当前生效 FlyAI key(官方 1.0.16 同优先级):
123
+ * FLYAI_API_KEY → DEBUG_FLYAI_API_KEY → config 文件 → none(官方内置共享)。
124
+ */
125
+ export function resolveFlyaiKey(opts: FlyaiConfigPaths = {}): ResolvedFlyaiKey {
126
+ const homeDir = opts.homeDir ?? homedir()
127
+ const env = opts.env ?? process.env
128
+ const configPath = flyaiConfigPath(homeDir)
129
+ const envKey = nonEmpty(env.FLYAI_API_KEY)
130
+ if (envKey) return { key: envKey, source: 'env', configPath, maskedKey: maskFlyaiKey(envKey) }
131
+ const debugKey = nonEmpty(env.DEBUG_FLYAI_API_KEY)
132
+ if (debugKey) return { key: debugKey, source: 'env-debug', configPath, maskedKey: maskFlyaiKey(debugKey) }
133
+ const read = readFlyaiConfig(configPath)
134
+ const fileKey = read.ok ? nonEmpty(read.data.FLYAI_API_KEY) : undefined
135
+ if (fileKey) return { key: fileKey, source: 'config', configPath, maskedKey: maskFlyaiKey(fileKey) }
136
+ return { source: 'none', configPath }
137
+ }
138
+
139
+ /** 解析 endpoint;DEBUG_FLYAI_MCP_URL trim 非空覆盖,显式标注调试态 */
140
+ export function resolveFlyaiEndpoint(opts: FlyaiConfigPaths = {}): ResolvedFlyaiEndpoint {
141
+ const env = opts.env ?? process.env
142
+ const debugUrl = nonEmpty(env.DEBUG_FLYAI_MCP_URL)
143
+ if (debugUrl) return { url: debugUrl, debug: true }
144
+ return { url: 'https://flyai.open.fliggy.com/mcp', debug: false }
145
+ }
146
+
147
+ /** 脱敏:仅尾 4 位;短串(≤4)全掩 */
148
+ export function maskFlyaiKey(key: string): string {
149
+ const text = typeof key === 'string' ? key.trim() : ''
150
+ if (!text) return ''
151
+ if (text.length <= 4) return '****'
152
+ return `****${text.slice(-4)}`
153
+ }
154
+
155
+ export function sha256Hex(value: string): string {
156
+ return createHash('sha256').update(value, 'utf8').digest('hex')
157
+ }
158
+
159
+ /** 明显占位/模板串——拒绝把文档示例当 key */
160
+ export function isPlaceholderFlyaiKey(key: string): boolean {
161
+ const text = key.trim().toLowerCase()
162
+ if (!text) return true
163
+ return /^(your?-?(key|api[._-]?key)|xxxx+|<[^>]+>|sk-[a-z]*$|test|placeholder|changeme|foo|bar)$/.test(text)
164
+ }
165
+
166
+ /**
167
+ * 权限硬校验:dir 必须 0700,file(存在时)必须 0600。
168
+ * Windows 无 POSIX 位:返回 unsupported(调用方按平台说明,不冒充通过)。
169
+ */
170
+ export function verifySecureMode(dir: string, file: string): { ok: boolean; error?: string; unsupported?: boolean } {
171
+ if (process.platform === 'win32') return { ok: false, unsupported: true }
172
+ try {
173
+ const dirMode = statSync(dir).mode & 0o777
174
+ if (dirMode !== 0o700) return { ok: false, error: `目录权限 ${dirMode.toString(8)} ≠ 700` }
175
+ if (existsSync(file)) {
176
+ const fileMode = statSync(file).mode & 0o777
177
+ if (fileMode !== 0o600) return { ok: false, error: `文件权限 ${fileMode.toString(8)} ≠ 600` }
178
+ }
179
+ return { ok: true }
180
+ } catch (e) {
181
+ return { ok: false, error: (e as Error).message }
182
+ }
183
+ }
184
+
185
+ /**
186
+ * 官方 CLI 1.0.16 首次运行可能先创建 ~/.flyai 为 0755,并在其中写入
187
+ * 0600 device-id。仅对当前用户拥有且本身不是 symlink 的配置目录收紧到
188
+ * 0700;验证回执所在 ~/.gotry 仍严格拒绝既有 0755 目录。
189
+ */
190
+ function prepareFlyaiConfigDir(dir: string, file: string): { ok: boolean; error?: string; unsupported?: boolean } {
191
+ if (process.platform === 'win32') return { ok: false, unsupported: true, error: 'Windows 无 0700/0600 权限位,安全写不支持' }
192
+ try {
193
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 })
194
+ const entry = lstatSync(dir)
195
+ if (entry.isSymbolicLink()) return { ok: false, error: '.flyai 目录是符号链接,拒绝写入' }
196
+ if (!entry.isDirectory()) return { ok: false, error: '.flyai 路径不是目录,拒绝写入' }
197
+ if (typeof process.getuid === 'function' && entry.uid !== process.getuid()) {
198
+ return { ok: false, error: '.flyai 目录不属于当前用户,拒绝写入' }
199
+ }
200
+ if ((entry.mode & 0o777) !== 0o700) chmodSync(dir, 0o700)
201
+ const after = lstatSync(dir)
202
+ if (after.isSymbolicLink() || !after.isDirectory()) return { ok: false, error: '.flyai 目录状态发生变化,拒绝写入' }
203
+ if (typeof process.getuid === 'function' && after.uid !== process.getuid()) return { ok: false, error: '.flyai 目录所有者发生变化,拒绝写入' }
204
+ return verifySecureMode(dir, file)
205
+ } catch (e) {
206
+ return { ok: false, error: (e as Error).message }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * 原子写 JSON 文件(本模块 save/clear/verification 共用的唯一写面):
212
+ * 1. dir 不存在则建,chmod 0700;已存在则先按 0700 校验;
213
+ * 2. tmp(同目录,mode 0600)写内容 → 校验 tmp 0600 → rename;
214
+ * 3. rename 后校验目标 0600;任一步失败:删除本 tmp 并返回 error;
215
+ * 4. tmp 清理放在 finally——rename 失败也不留含明文残留。
216
+ * 永不抛错。
217
+ */
218
+ export function atomicWriteJson(path: string, value: unknown): { ok: boolean; error?: string } {
219
+ const dir = dirname(path)
220
+ let tmp: string | undefined
221
+ try {
222
+ const dirExisted = existsSync(dir)
223
+ mkdirSync(dir, { recursive: true })
224
+ if (!dirExisted) chmodSync(dir, 0o700)
225
+ const dirCheck = verifySecureMode(dir, path)
226
+ if (dirCheck.unsupported) return { ok: false, error: 'Windows 无 0700/0600 权限位,安全写不支持' }
227
+ if (!dirCheck.ok) return { ok: false, error: dirCheck.error }
228
+
229
+ tmp = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
230
+ writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
231
+ let modeCheck = verifySecureMode(dir, tmp)
232
+ if (!modeCheck.ok) return { ok: false, error: modeCheck.error }
233
+
234
+ renameSync(tmp, path)
235
+ tmp = undefined
236
+ modeCheck = verifySecureMode(dir, path)
237
+ if (!modeCheck.ok) return { ok: false, error: modeCheck.error }
238
+ return { ok: true }
239
+ } catch (e) {
240
+ return { ok: false, error: (e as Error).message }
241
+ } finally {
242
+ if (tmp) { try { rmSync(tmp, { force: true }) } catch { /* tmp 清理 best effort */ } }
243
+ }
244
+ }
245
+
246
+ /**
247
+ * 保存 key 到 ~/.flyai/config.json:
248
+ * 非空/非占位;原配置损坏 → 拒绝保留字节;只改 FLYAI_API_KEY 字段;
249
+ * 原子写 + 权限硬校验。失败不动旧文件。
250
+ */
251
+ export function saveFlyaiKey(key: string, opts: FlyaiConfigPaths = {}): SaveFlyaiKeyResult {
252
+ const text = typeof key === 'string' ? key.trim() : ''
253
+ const homeDir = opts.homeDir ?? homedir()
254
+ const env = opts.env ?? process.env
255
+ const configPath = flyaiConfigPath(homeDir)
256
+ if (!text) return { ok: false, error: 'API key 不能为空' }
257
+ if (isPlaceholderFlyaiKey(text)) return { ok: false, error: '拒绝保存:这是文档占位串,不是真实 API key' }
258
+
259
+ const read = readFlyaiConfig(configPath)
260
+ if (!read.ok) return { ok: false, error: `原配置损坏,已拒绝覆盖(${read.error});请先人工修复 ${configPath}` }
261
+
262
+ const configDir = prepareFlyaiConfigDir(dirname(configPath), configPath)
263
+ if (!configDir.ok) return { ok: false, error: configDir.error }
264
+ const write = atomicWriteJson(configPath, { ...read.data, FLYAI_API_KEY: text })
265
+ if (!write.ok) return { ok: false, error: write.error }
266
+
267
+ const envKey = nonEmpty(env.FLYAI_API_KEY)
268
+ const debugKey = nonEmpty(env.DEBUG_FLYAI_API_KEY)
269
+ const source: FlyaiKeySource = envKey ? 'env' : debugKey ? 'env-debug' : 'config'
270
+ return {
271
+ ok: true,
272
+ savedTo: configPath,
273
+ source,
274
+ maskedKey: maskFlyaiKey(text),
275
+ ...(envKey || debugKey ? { envActive: true } : {}),
276
+ }
277
+ }
278
+
279
+ /**
280
+ * 清除 config.json 的 FLYAI_API_KEY 字段:
281
+ * 原配置损坏 → 拒绝保留字节;含字段则删(对象空=移除文件,否则原子写保留其他键);
282
+ * 不含字段=幂等成功;env/debug 来源文件操作清不掉,source 如实标注。
283
+ */
284
+ export function clearFlyaiKey(opts: FlyaiConfigPaths = {}): ClearFlyaiKeyResult {
285
+ const homeDir = opts.homeDir ?? homedir()
286
+ const env = opts.env ?? process.env
287
+ const configPath = flyaiConfigPath(homeDir)
288
+ const read = readFlyaiConfig(configPath)
289
+ if (!read.ok) return { ok: false, source: 'none', error: `原配置损坏,已拒绝操作(${read.error});请先人工修复 ${configPath}` }
290
+
291
+ let removedFrom: string | undefined
292
+ if (Object.prototype.hasOwnProperty.call(read.data, 'FLYAI_API_KEY')) {
293
+ const next = { ...read.data }
294
+ delete next.FLYAI_API_KEY
295
+ if (Object.keys(next).length === 0) {
296
+ try { rmSync(configPath, { force: true }) } catch (e) {
297
+ return { ok: false, source: 'none', error: `移除文件失败:${(e as Error).message}` }
298
+ }
299
+ } else {
300
+ const configDir = prepareFlyaiConfigDir(dirname(configPath), configPath)
301
+ if (!configDir.ok) return { ok: false, source: 'none', error: configDir.error }
302
+ const write = atomicWriteJson(configPath, next)
303
+ if (!write.ok) return { ok: false, source: 'none', error: write.error }
304
+ }
305
+ removedFrom = configPath
306
+ }
307
+
308
+ const envKey = nonEmpty(env.FLYAI_API_KEY)
309
+ const debugKey = nonEmpty(env.DEBUG_FLYAI_API_KEY)
310
+ if (envKey) return { ok: true, ...(removedFrom ? { removedFrom } : {}), source: 'env', maskedKey: maskFlyaiKey(envKey) }
311
+ if (debugKey) return { ok: true, ...(removedFrom ? { removedFrom } : {}), source: 'env-debug', maskedKey: maskFlyaiKey(debugKey) }
312
+ return { ok: true, ...(removedFrom ? { removedFrom } : {}), source: 'none' }
313
+ }
314
+
315
+ // ── 验证记录 ~/.gotry/flyai-verification.json ────────────────────────────────
316
+
317
+ export type FlyaiVerificationVerdict =
318
+ | 'verified'
319
+ | 'auth-error'
320
+ | 'forbidden'
321
+ | 'rate-limited'
322
+ | 'timeout'
323
+ | 'error'
324
+ | 'needs-setup'
325
+
326
+ export interface FlyaiVerification {
327
+ schema: 'gotry.flyai-verification.v1'
328
+ source: FlyaiKeySource
329
+ /** 生效 key 的 sha256(只判断回执是否属于当前 key,不可逆) */
330
+ keySha256: string
331
+ maskedKey: string
332
+ verdict: FlyaiVerificationVerdict
333
+ /** 完整归一化 endpoint 的 sha256;不把 userinfo/query 明文落到回执。 */
334
+ endpointFingerprint: string
335
+ /** 旧回执兼容字段;新写入不再保存 endpoint 明文。 */
336
+ endpoint?: string
337
+ /** true = 成绩来自 DEBUG endpoint,不能算官方 endpoint 已验证 */
338
+ endpointDebug: boolean
339
+ at: string
340
+ }
341
+
342
+ export function readFlyaiVerification(homeDir: string): FlyaiVerification | undefined {
343
+ try {
344
+ const path = flyaiVerificationPath(homeDir)
345
+ if (!existsSync(path)) return undefined
346
+ const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'))
347
+ if (!parsed || typeof parsed !== 'object') return undefined
348
+ const v = parsed as FlyaiVerification
349
+ if (v.schema !== 'gotry.flyai-verification.v1' || typeof v.keySha256 !== 'string') return undefined
350
+ return v
351
+ } catch {
352
+ return undefined
353
+ }
354
+ }
355
+
356
+ /** 原子写验证记录(权限硬校验);成功=true;失败不抛错 */
357
+ export function writeFlyaiVerification(entry: FlyaiVerification, homeDir: string): boolean {
358
+ return atomicWriteJson(flyaiVerificationPath(homeDir), entry).ok
359
+ }
360
+
361
+ export function removeFlyaiVerification(homeDir: string): void {
362
+ try { rmSync(flyaiVerificationPath(homeDir), { force: true }) } catch { /* best effort */ }
363
+ }
364
+
365
+ /** 完整归一化 endpoint,保留 path/query 以使其变化使回执失效。 */
366
+ export function normalizeEndpoint(url: string): string | undefined {
367
+ try {
368
+ return new URL(url).href
369
+ } catch {
370
+ return undefined
371
+ }
372
+ }
373
+
374
+ /** endpoint 指纹不可逆,避免调试 URL 的 userinfo/query 落盘。 */
375
+ export function endpointFingerprint(url: string): string | undefined {
376
+ const normalized = normalizeEndpoint(url)
377
+ return normalized ? sha256Hex(normalized) : undefined
378
+ }
379
+
380
+ /** 对外展示 endpoint:移除 userinfo、query、fragment;比较仍使用完整指纹。 */
381
+ export function displayEndpoint(url: string): string {
382
+ try {
383
+ const u = new URL(url)
384
+ return `${u.protocol}//${u.host}${u.pathname || '/'}${u.search || u.hash ? '?(已隐藏敏感参数)' : ''}`
385
+ } catch {
386
+ return '<非法 endpoint>'
387
+ }
388
+ }