@danceiny/gotry 0.0.1-rc.18 → 0.0.1-rc.19

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 (137) hide show
  1. package/README.md +42 -16
  2. package/README.zh-CN.md +37 -15
  3. package/bin/gotry-bootstrap.js +236 -3
  4. package/bin/gotry-inner.js +66 -20
  5. package/bin/gotry-runtime-resolution.d.ts +1 -1
  6. package/bin/gotry-runtime-resolution.js +7 -8
  7. package/cordis.gotry-patch.yml +15 -5
  8. package/data/stations-12306-verify.json +524 -0
  9. package/dist/capabilities/agent-reach.js +4 -4
  10. package/dist/capabilities/channel-health.js +103 -0
  11. package/dist/capabilities/channel-registry.js +213 -0
  12. package/dist/capabilities/doctor.js +285 -0
  13. package/dist/capabilities/effect.js +178 -5
  14. package/dist/capabilities/flyai.js +13 -0
  15. package/dist/capabilities/session/adapters/ctrip-hotel.js +207 -0
  16. package/dist/capabilities/session/adapters/rail-12306.js +285 -0
  17. package/dist/capabilities/session/extension-bridge.js +14 -1
  18. package/dist/capabilities/session/extension-channel.js +4 -2
  19. package/dist/capabilities/session/extension-distribution.js +1 -1
  20. package/dist/capabilities/session-search.js +311 -0
  21. package/dist/capabilities/visa-policy.js +126 -0
  22. package/dist/scripts/agent-planning-turn-deadline-e2e.js +304 -0
  23. package/dist/scripts/agent-planning-turn-deadline-tests.js +281 -0
  24. package/dist/scripts/benchmark-environment-bridge-e2e.js +5 -10
  25. package/dist/scripts/benchmark-environment-bridge-tests.js +148 -142
  26. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +26 -26
  27. package/dist/scripts/{booking-copilot-availability-policy-v2-tests.js → booking-copilot-availability-policy-tests.js} +115 -115
  28. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +41 -1
  29. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +75 -120
  30. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +370 -61
  31. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +2 -2
  32. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +7 -3
  33. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +15 -9
  34. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +19 -11
  35. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +16 -52
  36. package/dist/scripts/booking-copilot-runtime-proof-tests.js +3953 -155
  37. package/dist/scripts/booking-copilot-server-proof-tests.js +58 -23
  38. package/dist/scripts/booking-copilot-startup-proof-tests.js +10 -119
  39. package/dist/scripts/booking-surface-contract-proof-tests.js +1154 -326
  40. package/dist/scripts/bootstrap-tests.js +87 -2
  41. package/dist/scripts/build-metrics-report.js +339 -0
  42. package/dist/scripts/channel-probe-tests.js +148 -0
  43. package/dist/scripts/channel-probe.js +252 -0
  44. package/dist/scripts/channel-registry-tests.js +262 -0
  45. package/dist/scripts/doctor-tests.js +121 -0
  46. package/dist/scripts/effect-tests.js +274 -1
  47. package/dist/scripts/extension-tests.js +129 -11
  48. package/dist/scripts/fact-gate-tests.js +91 -2
  49. package/dist/scripts/flyai-tests.js +17 -1
  50. package/dist/scripts/hbcli-e2e-tests.js +1 -3
  51. package/dist/scripts/metrics-report-tests.js +288 -0
  52. package/dist/scripts/persona-surface-guard-tests.js +19 -0
  53. package/dist/scripts/session-tests.js +401 -1
  54. package/dist/scripts/smoke.js +100 -83
  55. package/dist/scripts/turn-handoff-collect-tests.js +216 -0
  56. package/dist/scripts/turn-handoff-collect.js +189 -0
  57. package/dist/scripts/turn-policy-tests.js +56 -0
  58. package/dist/scripts/typed-contract-canary.js +261 -0
  59. package/dist/scripts/visa-policy-tests.js +75 -0
  60. package/dist/scripts/wish-channel-gate-tests.js +111 -0
  61. package/dist/src/artifact-gate.js +91 -3
  62. package/dist/src/benchmark-agent-conformance.js +7 -4
  63. package/dist/src/benchmark-environment-bridge.js +68 -7
  64. package/dist/src/bookable-facts.js +62 -3
  65. package/dist/src/booking-surface/{availability-policy-v2.js → availability-policy.js} +89 -89
  66. package/dist/src/booking-surface/canonical-schema.js +8 -22
  67. package/dist/src/booking-surface/contracts.js +70 -19
  68. package/dist/src/booking-surface/dsh-planner.js +310 -177
  69. package/dist/src/booking-surface/dsh-plugin.js +3 -3
  70. package/dist/src/booking-surface/index.js +1 -5
  71. package/dist/src/booking-surface/profile.js +1 -1
  72. package/dist/src/booking-surface/runtime.js +1682 -247
  73. package/dist/src/booking-surface/server.js +371 -185
  74. package/dist/src/booking-surface/startup.js +17 -27
  75. package/dist/src/booking-surface/validation.js +270 -760
  76. package/dist/src/index.js +735 -149
  77. package/dist/src/turn-deadline.js +292 -0
  78. package/dist/src/turn-policy.js +146 -0
  79. package/dist/src/wish-pool.js +5 -0
  80. package/extension/background.js +23 -4
  81. package/extension/content-main.js +47 -9
  82. package/extension/manifest.json +27 -9
  83. package/package.json +6 -26
  84. package/schemas/booking.surface.schema.json +2593 -0
  85. package/ts/capabilities/agent-reach.ts +4 -4
  86. package/ts/capabilities/flyai.ts +21 -3
  87. package/ts/capabilities/session/action-cache.ts +1 -1
  88. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  89. package/ts/capabilities/session/adapters/rail-12306.ts +293 -0
  90. package/ts/capabilities/session/extension-bridge.ts +32 -2
  91. package/ts/capabilities/session/extension-channel.ts +9 -8
  92. package/ts/capabilities/session/extension-distribution.ts +3 -1
  93. package/ts/capabilities/session/health-watch.ts +1 -1
  94. package/ts/capabilities/session/read-guard.ts +1 -1
  95. package/ts/capabilities/session/wizard.ts +1 -1
  96. package/ts/capabilities/session-search.ts +323 -1
  97. package/ts/package.json +1 -0
  98. package/ts/scripts/turn-handoff-collect.ts +178 -0
  99. package/ts/src/artifact-gate.ts +82 -2
  100. package/ts/src/benchmark-agent-conformance.ts +14 -6
  101. package/ts/src/benchmark-environment-bridge.ts +29 -10
  102. package/ts/src/bookable-facts.ts +109 -5
  103. package/ts/src/booking-saga.ts +1 -1
  104. package/ts/src/booking-surface/{availability-policy-v2.ts → availability-policy.ts} +124 -125
  105. package/ts/src/booking-surface/canonical-schema.js +8 -22
  106. package/ts/src/booking-surface/contracts.ts +278 -239
  107. package/ts/src/booking-surface/dsh-planner.ts +333 -194
  108. package/ts/src/booking-surface/dsh-plugin.js +3 -3
  109. package/ts/src/booking-surface/index.ts +1 -5
  110. package/ts/src/booking-surface/profile.ts +11 -11
  111. package/ts/src/booking-surface/runtime.ts +1351 -351
  112. package/ts/src/booking-surface/server.ts +282 -175
  113. package/ts/src/booking-surface/startup.ts +36 -48
  114. package/ts/src/booking-surface/validation.ts +194 -442
  115. package/ts/src/contracts.ts +1 -1
  116. package/ts/src/index.ts +489 -171
  117. package/ts/src/loop.ts +1 -1
  118. package/ts/src/state-ledger.ts +1 -1
  119. package/ts/src/turn-deadline.ts +361 -0
  120. package/ts/src/turn-policy.ts +154 -0
  121. package/ts/src/wish-pool.ts +17 -4
  122. package/dist/scripts/agent-planning-budget-e2e.js +0 -227
  123. package/dist/scripts/agent-planning-budget-tests.js +0 -173
  124. package/dist/scripts/booking-copilot-v2-runtime-proof-tests.js +0 -3935
  125. package/dist/scripts/booking-surface-v2-contract-proof-tests.js +0 -1174
  126. package/dist/src/booking-surface/contracts-v2.js +0 -89
  127. package/dist/src/booking-surface/runtime-v2.js +0 -1771
  128. package/dist/src/booking-surface/server-v2.js +0 -334
  129. package/dist/src/booking-surface/validation-v2.js +0 -319
  130. package/dist/src/tool-budget.js +0 -136
  131. package/schemas/booking.surface.v1.schema.json +0 -927
  132. package/schemas/booking.surface.v2.schema.json +0 -61
  133. package/ts/src/booking-surface/contracts-v2.ts +0 -118
  134. package/ts/src/booking-surface/runtime-v2.ts +0 -1466
  135. package/ts/src/booking-surface/server-v2.ts +0 -247
  136. package/ts/src/booking-surface/validation-v2.ts +0 -205
  137. package/ts/src/tool-budget.ts +0 -165
@@ -9,8 +9,8 @@
9
9
  * 1. 解析 argv + .env(provider-neutral → DEEPSEEK_API_KEY/DEEPSEEK_BASE_URL)
10
10
  * 2. 定位 dsh runtime:
11
11
  * a. repo checkout / npm 安装 → root package 解析锁定的 @deepseek-ai/dsh
12
- * b. benchmark root 缺失时 legacy vendored node_modules fallback(不走 npx:
13
- * dsh cordis-loader 在子 cwd 求值 plugin name,必须绝对路径 patch)
12
+ * b. legacy vendored fallback 已按 D-27 移除(issue #120)——root 缺失即
13
+ * fail-closed 报错指重装,不再有「解析成功却跑不起来」的玄学形态
14
14
  * 3. 运行时生成 patch(os.tmpdir):把 gotry-tools 插件路径重写为按本包
15
15
  * 位置解析的绝对路径 —— 仓内 cordis.gotry-patch.yml 里的 name 行只是
16
16
  * 占位(本机绝对路径),随 tarball 分发后对其他机器必错。
@@ -20,7 +20,7 @@ import { spawn, spawnSync } from 'node:child_process'
20
20
  import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
21
21
  import { fileURLToPath, pathToFileURL } from 'node:url'
22
22
  import { dirname, join } from 'node:path'
23
- import { tmpdir } from 'node:os'
23
+ import { homedir, tmpdir } from 'node:os'
24
24
  import { createRequire } from 'node:module'
25
25
  import {
26
26
  benchmarkRuntimeSupported,
@@ -39,8 +39,7 @@ const rootRequire = createRequire(join(repoRoot, 'package.json'))
39
39
  // --- 环境 .env 加载(provider-neutral) ---
40
40
  // npm 安装模式优先读用户当前目录的 .env(包目录内不该有凭证);repo 检出读仓根。
41
41
  const sourceDshEarly = resolveDshPackage(rootRequire)
42
- const vendoredDshEarly = !sourceDshEarly && existsSync(join(repoRoot, 'ts/dsh-runtime/node_modules/@deepseek-ai/dsh/lib/bin.js'))
43
- const envCandidates = sourceCheckoutMode || vendoredDshEarly
42
+ const envCandidates = sourceCheckoutMode || sourceDshEarly
44
43
  ? [join(repoRoot, '.env')]
45
44
  : [join(process.cwd(), '.env'), join(repoRoot, '.env')]
46
45
  const envLines = []
@@ -82,24 +81,37 @@ if (help) {
82
81
 
83
82
  Usage:
84
83
  gotry web # dsh Web UI on http://127.0.0.1:3080
85
- gotry setup # 安装可选外部依赖(hbcli 官方脚本 / agent-reach pip;装时已自动跑过)
84
+ gotry setup # 扩展就位检查/指引(商店一键装)
85
+ <<<<<<< HEAD
86
+ gotry setup calendar # 可选日历(CalDAV 工作窗口)挂载开关:默认关;--off 关闭;--status 查看
87
+ =======
88
+ >>>>>>> origin/main
89
+ gotry doctor # 可选依赖体检:扩展/agent-reach/hbcli/flyai/sidebar 状态 + 补装指引
90
+ gotry doctor --fix # 体检 + 按报告补装(hbcli 官方脚本 / agent-reach pip / sidebar 插件)
86
91
  gotry "一段完整任务..." # headless 一问一答
87
92
  gotry help # this help
93
+ gotry --version # 版本号(bug 报告必填项)
88
94
 
89
95
  Detail: https://github.com/Danceiny/gotry — README
90
96
  `)
91
97
  process.exit(0)
92
98
  }
93
99
 
94
- // mode 决定路径: 'web'/'setup'/'help' 是字面命令;否则第一段 args[0] 是任务本身的一部分
95
- const literal = new Set(['web', 'setup', 'help', '-h', '--help'])
100
+ // repoRoot npm 安装与源码检出两种形态下都是包根,version 统一从这里取
101
+ if (args[0] === '-v' || args[0] === '--version') {
102
+ console.log(JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf-8')).version)
103
+ process.exit(0)
104
+ }
105
+
106
+ // mode 决定路径: 'web'/'setup'/'doctor'/'help' 是字面命令;否则第一段 args[0] 是任务本身的一部分
107
+ const literal = new Set(['web', 'setup', 'doctor', 'help', '-h', '--help'])
96
108
  const isLiteral = literal.has(args[0])
97
109
  const mode = isLiteral ? args[0] : 'headless'
98
110
  const rest = isLiteral ? args.slice(1) : args
99
111
 
100
- // setup:外部依赖自举(hbcli/agent-reach),不需要 dsh runtime 与 LLM key,同步分发后即退
101
- if (mode === 'setup') {
102
- const r = spawnSync(process.execPath, [join(here, 'gotry-bootstrap.js'), ...rest], { stdio: 'inherit' })
112
+ // setup/doctor:外部依赖自举与体检,不需要 dsh runtime 与 LLM key,同步分发后即退
113
+ if (mode === 'setup' || mode === 'doctor') {
114
+ const r = spawnSync(process.execPath, [join(here, 'gotry-bootstrap.js'), mode, ...rest], { stdio: 'inherit' })
103
115
  process.exit(r.status ?? (r.error ? 1 : 0))
104
116
  }
105
117
 
@@ -109,8 +121,7 @@ if (!supportsNodeVersion(process.versions.node)) {
109
121
  process.exit(1)
110
122
  }
111
123
 
112
- // --- dsh runtime 定位:root manifest/require.resolve 优先;旧 vendored 仅作 legacy fallback ---
113
- const vendoredDsh = join(repoRoot, 'ts/dsh-runtime/node_modules/@deepseek-ai/dsh/lib/bin.js')
124
+ // --- dsh runtime 定位(D-27 清偿,issue #120):仅 root manifest/依赖解析;legacy vendored 回退已移除 ---
114
125
  const installedPackageMode = !sourceCheckoutMode
115
126
  const selectedDsh = selectDshRuntime({
116
127
  repoRoot,
@@ -133,7 +144,7 @@ if (!dshBin) {
133
144
  console.error('[gotry] benchmark dsh runtime unavailable')
134
145
  process.exit(1)
135
146
  }
136
- console.error(`[gotry] 找不到 dsh runtime(既无 vendored ${vendoredDsh},依赖里也没有 @deepseek-ai/dsh)。`)
147
+ console.error('[gotry] 找不到 dsh runtime(依赖里没有 @deepseek-ai/dsh;legacy vendored 回退已按 D-27 移除)。')
137
148
  console.error('repo checkout: npm ci && npm --prefix ts ci && node scripts/build-dist.mjs;npm 安装: npm install(检查 node_modules)。')
138
149
  process.exit(1)
139
150
  }
@@ -144,12 +155,12 @@ if (benchmarkEnvironmentConfig && !benchmarkRuntimeSupported(selectedDsh)) {
144
155
 
145
156
  // --- 运行时 patch:插件路径按本包位置重写为绝对路径 ---
146
157
  // 安装包始终指向 dist/ 纯 JS(Node 拒绝 strip node_modules 下的 .ts)。
147
- // repo 检出仅在 vendored runtime 或显式 tsx loader 可用时走 .ts;否则
158
+ // repo 检出仅在显式 tsx loader 可用时走 .ts;否则
148
159
  // 使用当前 worktree 已构建的 dist,避免 Node strip-only 拒绝参数属性语法。
149
160
  const distEntry = join(repoRoot, 'dist/src/index.js')
150
161
  const tsEntry = join(repoRoot, 'ts/src/index.ts')
151
162
  const tsxLoaderActive = /(?:^|\s)--(?:import|loader)(?:=|\s)(?:"[^"]*tsx[^"]*"|'[^']*tsx[^']*'|\S*tsx\S*)/.test(process.env.NODE_OPTIONS ?? '')
152
- const sourceTypeScriptMode = !installedPackageMode && (dshSource === 'legacy-vendored' || tsxLoaderActive)
163
+ const sourceTypeScriptMode = !installedPackageMode && tsxLoaderActive
153
164
  const pluginEntry = !sourceTypeScriptMode && existsSync(distEntry) ? distEntry : tsEntry
154
165
  const distModuleMode = pluginEntry === distEntry
155
166
  const staticPatch = join(repoRoot, 'cordis.gotry-patch.yml')
@@ -368,6 +379,10 @@ if (!benchmarkEnvironmentConfig) {
368
379
  // npm 布局:子路径可能被 exports 挡(resolve 抛错不能留下旧值),裸包名返回真实入口
369
380
  try { mapEntry = require_.resolve('dsh-map-tools/lib/index.js') } catch { mapEntry = '' }
370
381
  if (!mapEntry) { try { mapEntry = require_.resolve('dsh-map-tools') } catch { mapEntry = '' } }
382
+ if (!mapEntry) {
383
+ // ts/node_modules 回退(source 模式:dsh-map-tools 安装在 ts/package.json)
384
+ try { mapEntry = require_.resolve(join(repoRoot, 'ts/node_modules/dsh-map-tools')) } catch { mapEntry = '' }
385
+ }
371
386
  }
372
387
  }
373
388
  // 结构化澄清卡(T2):ask_user_question 工具 + user-questions 服务,从 dsh 包
@@ -399,8 +414,16 @@ if (mapEntry) {
399
414
  patchRaw = patchRaw.replace(/\n\s*- id: dsh-map-tools\n\s*name: 'placeholder\/dsh-map-tools'\n/, '\n')
400
415
  }
401
416
 
402
- // dsh-calendar 宿主插件(CalDAV 工作窗口读取;未配置时工具报错降级,不挡启动)
403
- // 离线预算 E2E 显式禁用可选宿主插件,避免测试依赖真实 CalDAV 账号。
417
+ // dsh-calendar 宿主插件(CalDAV 工作窗口读取)——D-9 拍板(issue #106):默认不挂载。
418
+ // 未配置的日历工具是纯负资产(会话中段才撞「未配置 username」报错),gotry 对它的
419
+ // 唯一诉求(工作窗口)由访谈首轮覆盖。挂载与否由 **setup 状态面**决定(founder
420
+ // 2026-09-03 纠偏:禁止环境变量控制产品行为;可选依赖进 setup 状态管理,与扩展
421
+ // manifest 同居 ~/.gotry)——`npx gotry setup calendar` 写 ~/.gotry/calendar.json,
422
+ // `--off` 删除恢复默认;doctor 报告三态。
423
+ let calEnabled = false
424
+ try {
425
+ calEnabled = JSON.parse(readFileSync(join(homedir(), '.gotry', 'calendar.json'), 'utf-8'))?.enabled === true
426
+ } catch { /* 缺文件/坏文件 = 默认不挂载 */ }
404
427
  let calEntry = ''
405
428
  if (!benchmarkEnvironmentConfig) {
406
429
  const vendoredCal = join(repoRoot, 'ts/dsh-runtime/node_modules/dsh-calendar/lib/index.js')
@@ -411,7 +434,7 @@ if (!benchmarkEnvironmentConfig) {
411
434
  if (!calEntry) { try { calEntry = require_.resolve('dsh-calendar') } catch { calEntry = '' } }
412
435
  }
413
436
  }
414
- if (calEntry && process.env.GOTRY_DISABLE_OPTIONAL_CALENDAR !== '1') {
437
+ if (calEntry && calEnabled) {
415
438
  patchRaw = patchRaw.replace(/(name:\s*)'placeholder\/dsh-calendar'/, `$1'${calEntry}'`)
416
439
  } else {
417
440
  patchRaw = patchRaw.replace(/\n\s*- id: dsh-calendar\n\s*name: 'placeholder\/dsh-calendar'\n/, '\n')
@@ -423,9 +446,21 @@ if (calEntry && process.env.GOTRY_DISABLE_OPTIONAL_CALENDAR !== '1') {
423
446
  // 两条目标在 headless/web profile 均有(dsh-base 声明 llm-deepseek、两 profile 均声明
424
447
  // agent-default-model)。llm-deepseek 目录整体替换为单条目:显式指定模型的场景多为
425
448
  // 中转/兼容端点,默认 v4-* 目录对其是误导;不硬编码上游 DEFAULT_MODELS 防漂移。
449
+ let llmMaxTokens
426
450
  if (process.env.GOTRY_LLM_MODEL) {
451
+ const rawMax = process.env.LLM_MAX_TOKENS
452
+ if (rawMax !== undefined && rawMax !== '') {
453
+ llmMaxTokens = Number.parseInt(rawMax, 10)
454
+ if (!Number.isSafeInteger(llmMaxTokens) || llmMaxTokens <= 0) {
455
+ throw new Error(`invalid LLM_MAX_TOKENS: ${JSON.stringify(rawMax)} (expected a positive safe integer)`)
456
+ }
457
+ }
427
458
  const modelYaml = `'${process.env.GOTRY_LLM_MODEL.replace(/'/g, "''")}'`
428
- patchRaw += `\n# LLM_MODEL 指定模型(issue #77):dsh 会话面默认模型 + 模型目录\n- id: agent-default-model\n config:\n provider: deepseek-official\n model: ${modelYaml}\n- id: llm-deepseek\n config:\n models:\n - id: ${modelYaml}\n name: ${modelYaml}\n`
459
+ // LLM_MAX_TOKENS(Round 9,#100/#102):中转/兼容端点模型常带低于 dsh 未知模型
460
+ // 默认 256K 预算的输出上限(MiniMax 2013 实测);目录条目 maxTokens 元数据是
461
+ // dsh-llm-deepseek defaultMaxTokens 的官方通道(web UI 模型同源)。
462
+ const maxTokensYaml = llmMaxTokens === undefined ? '' : `\n maxTokens: ${llmMaxTokens}`
463
+ patchRaw += `\n# LLM_MODEL 指定模型(issue #77):dsh 会话面默认模型 + 模型目录\n- id: agent-default-model\n config:\n provider: deepseek-official\n model: ${modelYaml}\n- id: llm-deepseek\n config:\n models:\n - id: ${modelYaml}\n name: ${modelYaml}${maxTokensYaml}\n`
429
464
  }
430
465
  // Keep the patch private and short-lived. mkdtempSync creates a 0700 directory;
431
466
  // wx prevents accidental reuse/races if a process is started concurrently.
@@ -477,6 +512,17 @@ const childStdio = mode === 'web'
477
512
  let benchmarkCapturedBytes = 0
478
513
  let benchmarkDiagnosticBuffer = Buffer.alloc(0)
479
514
  let benchmarkOutputTruncated = false
515
+ // 启动一次性 doctor 摘要(issue #114,design §3.1③):分离子进程后台跑只读体检,
516
+ // 有待处理项打一行 stderr(stderr 继承,不污染 stdout;benchmark 面保持零杂音)。
517
+ // detached+unref:不阻塞不拖慢启动;inner 生命周期天然一次,不重复刷;失败静默。
518
+ if (!benchmarkEnvironmentConfig) {
519
+ try {
520
+ spawn(process.execPath, [join(here, 'gotry-bootstrap.js'), 'doctor', '--summary'], {
521
+ detached: true,
522
+ stdio: ['ignore', 'ignore', 'inherit'],
523
+ }).unref()
524
+ } catch { /* 体检不可用不挡启动 */ }
525
+ }
480
526
  child = spawn(process.execPath, [dshBin, ...binJs], {
481
527
  stdio: childStdio,
482
528
  env: childEnv,
@@ -5,7 +5,7 @@ export type DshResolver = {
5
5
  export type DshRuntime = {
6
6
  bin: string
7
7
  version: string
8
- source: 'root' | 'legacy-vendored'
8
+ source: 'root'
9
9
  }
10
10
 
11
11
  export const REQUIRED_BENCHMARK_DSH_VERSION: '0.1.2-alpha.3'
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync } from 'node:fs'
1
+ import { readFileSync } from 'node:fs'
2
2
  import { dirname, join } from 'node:path'
3
3
 
4
4
  export const REQUIRED_BENCHMARK_DSH_VERSION = '0.1.2-alpha.3'
@@ -29,15 +29,14 @@ export function supportsNodeVersion(version) {
29
29
  return major > 22 || (major === 22 && minor >= 15)
30
30
  }
31
31
 
32
- export function selectDshRuntime({ repoRoot, rootResolver, benchmark }) {
32
+ export function selectDshRuntime({ rootResolver }) {
33
33
  const root = resolveDshPackage(rootResolver)
34
34
  if (root) return { ...root, source: 'root' }
35
- if (benchmark) return null
36
-
37
- const vendoredBin = join(repoRoot, 'ts/dsh-runtime/node_modules/@deepseek-ai/dsh/lib/bin.js')
38
- if (!existsSync(vendoredBin)) return null
39
- const vendored = readDshPackage(vendoredBin)
40
- return vendored ? { ...vendored, source: 'legacy-vendored' } : null
35
+ // D-27 清偿(issue #120):legacy vendored 回退路径已移除——该形态的 Node 兼容窗口
36
+ // 断裂(Round 5 起「不承诺可运行」),解析成功只会把「dsh 缺失」变成下游玄学失败。
37
+ // 唯一受支持形态 = root manifest / 依赖解析(216 精确依赖闭包);找不到即 fail-closed,
38
+ // 由调用方给明确重装指引。benchmark 原本就禁用回退,语义不变(入参保留以稳调用面)
39
+ return null
41
40
  }
42
41
 
43
42
  export function benchmarkRuntimeSupported(runtime) {
@@ -34,6 +34,9 @@
34
34
  {{motivation_brief}}
35
35
  行为契约:
36
36
  (1)动机先行:首轮必问工作窗口(几点到几点/什么时区)与已订资源(航班/酒店);
37
+ 行程涉及同行人(见面/汇合/结伴)时,同行人是第二条到达链,同样必问——从哪出发/是否
38
+ 已订/有无自己的时间窗;问明即落同行人档案(gotry_companion_save),到达账与预算按各自
39
+ 的链分开算;
37
40
  (2)日历一次断言:日期换算以锚点卡为准并记住,冲突让用户裁决,永不重算;
38
41
  (3)翻译不造数:班次/价格只来自工具(gotry_feasibility_check/gotry_skeleton_check/gotry_hotel_search);
39
42
  (4)判定归引擎:可行性/全成本由工具计算,你只解释;
@@ -70,6 +73,10 @@
70
73
  工具链,绝不因关键词(差旅/年假/IRW)路由进宿主其他 skill(如 cis-cli);
71
74
  只有用户明确要查公司系统(假期余额/出差订单/报销审批)时才调对应 skill;
72
75
  交界场景(用年假去旅行)分两步——余额查询归公司 skill,去哪/怎么去归 gotry。
76
+ 表层规则:gotry 的全部能力一律是【工具调用】(gotry_ 前缀,直接作为 tool
77
+ 发起),不是宿主 skill——绝不把 gotry_* 名字传给 skill 加载器(skill 面只装
78
+ 宿主技能;skill 调用返回 invalid/unknown 即说明用错了面,改回 tool call,
79
+ 不得换名重试 skill)。
73
80
  (17)判定前背景调查:给可行性结论前,先对每个候选目的地取气候背景
74
81
  (gotry_weather_check 的 climate 模式);季节性/天气论断必须带
75
82
  [实时API:open-meteo@ts] 证据,没查过就不写天气相关理由。
@@ -78,11 +85,11 @@
78
85
  evidence=用户原话),不等确认;班次/房型/落脚点等开放性选择不外问
79
86
  用户——基于已知动机与约束给出最有说服力的方案并说明理由,用户否决
80
87
  才改。校准类疑问永不阻塞推进。
81
- (19)OTA 检索(平铺工具,无预设路由优先级):实时机票/火车用
82
- gotry_flyai_search(kind=flight|train),实时酒店报价也用它
83
- (kind=hotel;未鉴权价格多为打码如 ¥7xx,如实以区间呈现并请用户到
84
- jumpUrl 酒店页核实真实价)。账号会话面 gotry_session_search(用户本人
85
- 登录态,现携程机票):**首次调用**经运行时审批卡向用户请求授权,本会话
88
+ (19)OTA 检索(工具平铺,路由查卡):机/火/酒检索通道与当前顺位看
89
+ {{channel_routing_card}}——不背优先级;某次检索 verdict≠hit 时,按该结果内
90
+ routing 字段改道下一通道,同一通道本会话不盲试第二次。
91
+ 账号会话面 gotry_session_search(用户本人
92
+ 登录态,现携程机票/酒店 + 12306 火车(公开查询面),kind=flight|hotel|train):**首次调用**经运行时审批卡向用户请求授权,本会话
86
93
  内记住、不再重复弹卡;用户拒绝即本会话吊销——不再请求也不再执行,改走
87
94
  其他工具推进;无审批通道(headless)不执行。返回 needs-login→调
88
95
  gotry_session_login 产品工具(先自动检测票据——已登录则直接确认零弹窗;未登录才
@@ -105,3 +112,6 @@
105
112
  (21)工具循环收敛:第 16 次工具调用收到 TOOL_BUDGET_SOFT 提示后立即整理并给出最终答复;
106
113
  每个对话轮次最多允许 18 次真实工具派发,第 19 次起收到结构化 TOOL_BUDGET_EXHAUSTED
107
114
  拒绝结果且不得再调用工具。达到闸值后只能基于已有结果输出最终答复,不得重试或改调其他工具。
115
+ (22)到达账必达:红眼/凌晨起飞、或落地当天有硬安排(上班/办事)的航段,解释方案时必须
116
+ 显式给出到达账——当地到达时刻(含日期偏移)、时差、到达精力与落地后可用时长,并主动给
117
+ 前一晚落脚建议;时刻表正确不等于行程可行。