@danceiny/gotry 0.0.1-rc.5 → 0.0.1-rc.6

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 (49) hide show
  1. package/README.md +1 -1
  2. package/bin/gotry-inner.js +56 -23
  3. package/cordis.gotry-patch.yml +2 -2
  4. package/data/flights_2026.json +215 -0
  5. package/data/golden_erhai.json +92 -0
  6. package/data/golden_trip_2026.json +75 -0
  7. package/data/hotels_2026.json +64 -0
  8. package/data/openflights-skeleton.json +895 -0
  9. package/data/yunnan-pack.json +201 -0
  10. package/dist/capabilities/agent-reach-deep.js +172 -0
  11. package/dist/capabilities/agent-reach.js +204 -0
  12. package/dist/capabilities/anything.js +139 -0
  13. package/dist/capabilities/hbcli.js +138 -0
  14. package/dist/capabilities/incident-log.js +99 -0
  15. package/dist/capabilities/opensky.js +74 -0
  16. package/dist/capabilities/weather.js +180 -0
  17. package/dist/scripts/agent-reach-deep-tests.js +54 -0
  18. package/dist/scripts/agent-reach-tests.js +38 -0
  19. package/dist/scripts/agent-reach-wrapper-tests.js +79 -0
  20. package/dist/scripts/anything-tests.js +95 -0
  21. package/dist/scripts/async-collect.js +18 -0
  22. package/dist/scripts/diff-test.js +39 -0
  23. package/dist/scripts/engine-run.js +14 -0
  24. package/dist/scripts/engine-tests.js +45 -0
  25. package/dist/scripts/hbcli-tests.js +85 -0
  26. package/dist/scripts/incident-tests.js +96 -0
  27. package/dist/scripts/journey-tests.js +45 -0
  28. package/dist/scripts/opensky-check.js +20 -0
  29. package/dist/scripts/opensky-tests.js +52 -0
  30. package/dist/scripts/probe-poi-tests.js +79 -0
  31. package/dist/scripts/replay-async.js +44 -0
  32. package/dist/scripts/replay-real.js +38 -0
  33. package/dist/scripts/replay.js +44 -0
  34. package/dist/scripts/skeleton-check.js +35 -0
  35. package/dist/scripts/skeleton-integration-test.js +22 -0
  36. package/dist/scripts/smoke.js +90 -0
  37. package/dist/scripts/unified-tests.js +49 -0
  38. package/dist/scripts/weather-tests.js +48 -0
  39. package/dist/src/bridge.js +34 -0
  40. package/dist/src/contracts.js +64 -0
  41. package/dist/src/dsh-llm.js +154 -0
  42. package/dist/src/engine.js +331 -0
  43. package/dist/src/index.js +760 -0
  44. package/dist/src/journey.js +147 -0
  45. package/dist/src/loop.js +296 -0
  46. package/dist/src/mock-llm.js +98 -0
  47. package/dist/src/model.js +134 -0
  48. package/dist/src/unified.js +536 -0
  49. package/package.json +3 -1
package/README.md CHANGED
@@ -260,7 +260,7 @@ npm pack --dry-run --registry=https://registry.npmjs.org/
260
260
  npm publish --access public --registry=https://registry.npmjs.org/
261
261
 
262
262
  # 5. 发布成功后任何用户:
263
- npx gotry web # 一行启动
263
+ npx @danceiny/gotry web # 一行启动(0.0.1-rc.5 已发 npmjs)
264
264
  ```
265
265
 
266
266
  > ⚠️ **注意**: publish 后**不可逆**(30 天内可 `npm unpublish` 但会污染历史)。建议先在 main 打 `v0.0.1-rc.3` tag + GitHub release,再 publish,保证 npm 包与仓库 tag 同步。
@@ -1,30 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * gotry CLI 入口(v0.0.1-rc.2 ):
3
+ * gotry CLI 入口(v0.0.1-rc.2 起;rc.6 起支持 npm 安装运行):
4
4
  * gotry web # dsh Web 浏览器界面(:3080)
5
5
  * gotry "I want 2 days in Phuket" # headless one-shot
6
6
  * gotry help # help
7
7
  *
8
8
  * 工作流程:
9
9
  * 1. 解析 argv + .env(provider-neutral → DEEPSEEK_API_KEY)
10
- * 2. spawn vendored dsh(`ts/dsh-runtime/node_modules/@deepseek-ai/dsh/lib/bin.js`)
11
- * —— 不是 npx。原因:corids patch plugin 路径硬编码到仓库根。
12
- * 3. --patch 指向仓库根的 cordis.gotry-patch.yml
13
- *
14
- * 路线选择说明: 为什么不用 `npx dsh`?
15
- * dsh 0.1.1-rc.2 cordis-loader 在子进程 cwd(~/.dsh/profiles/web/)求值 plugin name;
16
- * patch name 用 './ts/src/index.ts' 或 '@gotry/plugin' 都会因为 cwd 不在仓库
17
- * 而失败。最稳的方案就是走 vendored runtime。要走 npx 一键启 dsh 需要 dsh 上游
18
- * 修 cordis 的 cwd 解析(或我们写一个 dsh-cwd-plugin);留到下个 tick。
10
+ * 2. 定位 dsh runtime:
11
+ * a. repo checkout vendored ts/dsh-runtime/node_modules/...
12
+ * b. npm 安装 → createRequire 解析依赖 @deepseek-ai/dsh(不走 npx:
13
+ * dsh cordis-loader 在子 cwd 求值 plugin name,必须绝对路径 patch)
14
+ * 3. 运行时生成 patch(os.tmpdir):把 gotry-tools 插件路径重写为按本包
15
+ * 位置解析的绝对路径 —— 仓内 cordis.gotry-patch.yml 里的 name 行只是
16
+ * 占位(本机绝对路径),随 tarball 分发后对其他机器必错。
19
17
  */
20
18
 
21
19
  import { spawn } from 'node:child_process'
22
- import { existsSync, readFileSync } from 'node:fs'
20
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
23
21
  import { fileURLToPath } from 'node:url'
24
22
  import { dirname, join } from 'node:path'
23
+ import { tmpdir } from 'node:os'
24
+ import { createRequire } from 'node:module'
25
25
 
26
26
  const here = dirname(fileURLToPath(import.meta.url))
27
27
  const repoRoot = join(here, '..')
28
+ const require_ = createRequire(import.meta.url)
28
29
 
29
30
  // --- 环境 .env 加载(provider-neutral) ---
30
31
  const envPath = join(repoRoot, '.env')
@@ -67,20 +68,48 @@ const isLiteral = literal.has(args[0])
67
68
  const mode = isLiteral ? args[0] : 'headless'
68
69
  const rest = isLiteral ? args.slice(1) : args
69
70
 
70
- const patchPath = join(repoRoot, 'cordis.gotry-patch.yml')
71
- const dshBin = join(repoRoot, 'ts/dsh-runtime/node_modules/@deepseek-ai/dsh/lib/bin.js')
71
+ // --- dsh runtime 定位:repo checkout(vendored)优先,npm 安装走依赖解析 ---
72
+ const vendoredDsh = join(repoRoot, 'ts/dsh-runtime/node_modules/@deepseek-ai/dsh/lib/bin.js')
73
+ let dshBin = ''
74
+ let dshCwd = ''
75
+ if (existsSync(vendoredDsh)) {
76
+ dshBin = vendoredDsh
77
+ dshCwd = join(repoRoot, 'ts/dsh-runtime')
78
+ } else {
79
+ try {
80
+ dshBin = require_.resolve('@deepseek-ai/dsh/lib/bin.js')
81
+ dshCwd = process.cwd() // npm 安装:gotry-state 落在用户调用目录
82
+ } catch {
83
+ dshBin = ''
84
+ }
85
+ }
86
+
87
+ if (!dshBin) {
88
+ console.error(`[gotry] 找不到 dsh runtime(既无 vendored ${vendoredDsh},依赖里也没有 @deepseek-ai/dsh)。`)
89
+ console.error('repo checkout: cd ts/dsh-runtime && pnpm install;npm 安装: npm install(检查 node_modules)。')
90
+ process.exit(1)
91
+ }
72
92
 
73
- if (!existsSync(dshBin)) {
74
- console.error(`[gotry] 找不到 vendored dsh runtime: ${dshBin}`)
75
- console.error('请确认你 clone 了完整仓库(ts/dsh-runtime/ 应存在)。')
76
- console.error('或运行: cd ts/dsh-runtime && pnpm install')
93
+ // --- 运行时 patch:插件路径按本包位置重写为绝对路径 ---
94
+ // npm 模式指向 dist/ 纯 JS(Node 拒绝 strip node_modules 下的 .ts);
95
+ // repo 检出指向 .ts 源码(vendored runtime 下天然可行)。
96
+ const distEntry = join(repoRoot, 'dist/src/index.js')
97
+ const tsEntry = join(repoRoot, 'ts/src/index.ts')
98
+ const npmMode = !existsSync(vendoredDsh)
99
+ const pluginEntry = npmMode && existsSync(distEntry) ? distEntry : tsEntry
100
+ const staticPatch = join(repoRoot, 'cordis.gotry-patch.yml')
101
+ if (!existsSync(staticPatch)) {
102
+ console.error(`[gotry] 找不到 patch 配置: ${staticPatch}`)
77
103
  process.exit(1)
78
104
  }
79
- if (!existsSync(patchPath)) {
80
- console.error(`[gotry] 找不到 patch 配置: ${patchPath}`)
81
- console.error('请确认你在仓库根目录运行。')
105
+ if (!existsSync(pluginEntry)) {
106
+ console.error(`[gotry] 找不到插件入口: ${pluginEntry}(包不完整?)`)
82
107
  process.exit(1)
83
108
  }
109
+ const patchRaw = readFileSync(staticPatch, 'utf-8')
110
+ .replace(/(name:\s*)'[^']*ts\/src\/index\.ts'/, `$1'${pluginEntry}'`)
111
+ const patchPath = join(tmpdir(), `cordis.gotry.${process.pid}.yml`)
112
+ writeFileSync(patchPath, patchRaw)
84
113
  if (!process.env.DEEPSEEK_API_KEY && mode !== 'help') {
85
114
  console.error('[gotry] 需要 DEEPSEEK_API_KEY(或 LLM_API_KEY)— 检查 .env 或环境变量。')
86
115
  process.exit(1)
@@ -95,18 +124,22 @@ const binJs = mode === 'web'
95
124
  const child = spawn(process.execPath, [dshBin, ...binJs], {
96
125
  stdio: 'inherit',
97
126
  env: process.env,
98
- cwd: join(repoRoot, 'ts/dsh-runtime'),
127
+ cwd: dshCwd,
99
128
  })
100
129
  if (process.env.GOTRY_DEBUG) {
101
130
  console.error('[gotry-debug] exec:', process.execPath, dshBin)
102
131
  console.error('[gotry-debug] argv:', binJs)
103
- console.error('[gotry-debug] cwd:', join(repoRoot, 'ts/dsh-runtime'))
132
+ console.error('[gotry-debug] cwd:', dshCwd)
104
133
  console.error('[gotry-debug] patch exists:', existsSync(patchPath), patchPath)
105
134
  }
106
135
  child.on('exit', (code, signal) => {
107
136
  if (code !== 0 || signal) {
108
137
  // D-NEW 护栏:dsh 异常退出也写一条 incident,留现场而非沉默
109
- import('../ts/capabilities/incident-log.ts').then(({ recordIncident }) => {
138
+ // npm 模式 import dist JS(node_modules 下的 .ts 会被 Node strip)
139
+ const incidentModule = npmMode && existsSync(join(repoRoot, 'dist/capabilities/incident-log.js'))
140
+ ? '../dist/capabilities/incident-log.js'
141
+ : '../ts/capabilities/incident-log.ts'
142
+ import(incidentModule).then(({ recordIncident }) => {
110
143
  recordIncident({
111
144
  ts: new Date().toISOString(),
112
145
  kind: 'plugin_error',
@@ -4,8 +4,8 @@
4
4
  # (从 npm 安装: npx gotry web 自动应用本 patch)
5
5
  - insert:
6
6
  - id: gotry-tools
7
- name: '/Users/bytedance/work/gotry/ts/src/index.ts' # 绝对路径(本地开发);
8
- # vendored dsh runtime(ts/dsh-runtime/)下文件路径固定,无需重写
7
+ name: 'placeholder/ts/src/index.ts' # 占位:bin/gotry-inner.js 运行时
8
+ # 重写为按本包位置解析的绝对路径(repo npm 安装均正确)
9
9
  config:
10
10
  stateRoot: '.'
11
11
  timeoutMs: 30000
@@ -0,0 +1,215 @@
1
+ {
2
+ "meta": {
3
+ "note": "静态数据包(P0-3):公开渠道调研的真实班期;价格为估算区间标记,非实时报价(真实 API 属 T3)。日期为 2026-07/08 重放场景。",
4
+ "sources": [
5
+ "阿联酋航空官网-深圳迪拜航线: EK329 SZX 00:45 → DXB 04:20(每日,B777);EK328 DXB 11:00 → SZX 22:40",
6
+ "新华网 2025-07-01:阿联酋航空开通深圳直飞迪拜(开航时刻 23:55→03:40,后调整为 00:45→04:20)",
7
+ "携程/国泰时刻表: CX771 HKG 08:05→HKT 10:50;CX773 HKG 14:45→HKT 17:20;香港航空 HX741 约 20:20→23:05(有取消记录,出行前需确认)"
8
+ ],
9
+ "roundtrip_note": "7.17 22:40 落地深圳与 EK328(DXB 11:00→SZX 22:40)完全吻合——发起人入境段即该航线,demo 与真实对账的第一处交叉验证",
10
+ "work_window": {
11
+ "note": "M-1:发起人工作时间(家=迪拜 UTC+4)10:00-19:00,周一至周五",
12
+ "home_tz_offset_min": 240,
13
+ "start_min": 600,
14
+ "end_min": 1140,
15
+ "workdays": [
16
+ 0,
17
+ 1,
18
+ 2,
19
+ 3,
20
+ 4
21
+ ]
22
+ },
23
+ "reconcil": [
24
+ "f3 真实:8.4 周二 FD582 DMK 08:10→KMG 11:25 + 昆明转飞丽江(Kimi 终轮四方案对比后采纳)",
25
+ "f2 起点真实:8.1 从甲米(奥南)出发,周末换防模式:Rawai 7.18-8.1 主基地 + 8.1-3 奥南 2 晚 + 8.7-9 奥南 2 晚(共 3 晚)",
26
+ "住宿模式:Rawai 拉威基地 7.18-8.1,周末甲米换防 2 段(非整体搬迁);demo 主基地+中途换防结构命中",
27
+ "f2 起点真实:8.1 从甲米 KBV 机场出发(不是 HKT)——周末换防 7.31 普吉→甲米,2 晚奥南,8.3 甲米→曼谷(从 KBV 飞,不是本 leg 的 HKT→DMK)",
28
+ "auto-guess 2026-08-24 吸收:f1=HX741 20:20 / f4-SZX≈22:00 / EK329→家 1.5h(docs/decisions-needed.md D-2 auto-guess 块,founder 校正任意行即改)"
29
+ ]
30
+ },
31
+ "legs": [
32
+ {
33
+ "id": "f1",
34
+ "note": "7.18 香港办证后飞普吉,当天与女朋友会合",
35
+ "date": "2026-07-18",
36
+ "services": [
37
+ {
38
+ "id": "CX773",
39
+ "dep": "14:45",
40
+ "arr": "17:20",
41
+ "price_cny": 2300,
42
+ "price_note": "7 月旺季经济舱估算"
43
+ },
44
+ {
45
+ "id": "HX741",
46
+ "dep": "20:20",
47
+ "arr": "23:05",
48
+ "price_cny": 1600,
49
+ "price_note": "低价备选;准点率弱于国泰"
50
+ }
51
+ ],
52
+ "buffer_min": 90,
53
+ "origin_transfer_min": 60,
54
+ "dest_transfer_min": 45,
55
+ "arrive_by": "23:59",
56
+ "anchors_note": "办证预计 12:00 前完成:CX773 需 12:15 离开港岛(满打满算);HX741 需 18:50 前",
57
+ "origin_tz_offset_min": 480,
58
+ "evidence": [
59
+ {
60
+ "tag": "[auto-guess:2026-08-24]",
61
+ "note": "f1 实际=HX741 20:20(晚班;Kimi 7.18 当天飞+早高峰,CX773 12:15 过紧)—founder 校正即改"
62
+ }
63
+ ]
64
+ },
65
+ {
66
+ "id": "f5",
67
+ "note": "8.10 凌晨红眼回迪拜,落地直奔办公室(真实锚点)",
68
+ "date": "2026-08-10",
69
+ "services": [
70
+ {
71
+ "id": "EK329",
72
+ "dep": "00:45",
73
+ "arr": "04:20",
74
+ "price_cny": 3400,
75
+ "price_note": "单程估算;往返约 ¥3825 起"
76
+ }
77
+ ],
78
+ "buffer_min": 120,
79
+ "origin_transfer_min": 60,
80
+ "dest_transfer_min": 45,
81
+ "arrive_by": "08:30",
82
+ "red_eye": true,
83
+ "red_eye_duration_min": 455,
84
+ "anchors_note": "8.9 22:45 离开住处即可;DXB 04:20 落地,09:00 上班前余量 4.5h;时差迪拜 -4h",
85
+ "tz_offset_min": -240,
86
+ "origin_tz_offset_min": 480,
87
+ "evidence": [
88
+ {
89
+ "tag": "[auto-guess:2026-08-24]",
90
+ "note": "EK329 落地→躺床上≈1.5h(SZX→南山车程;D-6 精力模型落地端附加 1.5h 口径)—founder 校正即改"
91
+ }
92
+ ]
93
+ },
94
+ {
95
+ "id": "f2",
96
+ "note": "普吉→曼谷度周末(gate q3:7.31 周五晚 vs 8.1 周六早,引擎双选项都保留)",
97
+ "date": "2026-07-31 或 08-01",
98
+ "services": [
99
+ {
100
+ "id": "VZ303",
101
+ "dep": "09:00",
102
+ "arr": "10:30",
103
+ "price_cny": 350,
104
+ "price_note": "泰越捷,行李另购",
105
+ "weekday": "sat"
106
+ },
107
+ {
108
+ "id": "TG216",
109
+ "dep": "16:55",
110
+ "arr": "18:25",
111
+ "price_cny": 750,
112
+ "price_note": "周五晚班,最大化周末",
113
+ "weekday": "fri"
114
+ },
115
+ {
116
+ "id": "TG218",
117
+ "dep": "19:15",
118
+ "arr": "20:50",
119
+ "price_cny": 800,
120
+ "price_note": "周五最晚班",
121
+ "weekday": "fri"
122
+ }
123
+ ],
124
+ "buffer_min": 75,
125
+ "origin_transfer_min": 45,
126
+ "dest_transfer_min": 60,
127
+ "arrive_by": "21:30",
128
+ "anchors_note": "HKT→BKK 每天约 15 班(泰航 5-7 + 泰越捷 8 + 曼航/亚航),频次极高;此处只列代表性班次",
129
+ "origin_tz_offset_min": 420,
130
+ "evidence": [
131
+ {
132
+ "tag": "[demo-reconcil:已]",
133
+ "note": "真实 8.1 从甲米(奥南)出发:7.31 普吉→甲米短驳 + 8.3 甲米→曼谷(本腿的 VZ303 8.1 选项在甲米机场 KBV 出发,不是 HKT)。Demo 数据包按\"普吉→曼谷\"标注为抽象段;M-2 reconcile 时 f2 起点切 KBV"
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "id": "f3",
139
+ "note": "曼谷→昆明,云南一周开始(8.3 周日 MU6088 demo 备选 / 8.4 周二 FD582 真实选)",
140
+ "date": "2026-08-02 或 08-03",
141
+ "services": [
142
+ {
143
+ "id": "MU9622",
144
+ "dep": "07:50",
145
+ "arr": "11:15",
146
+ "price_cny": 1100,
147
+ "price_note": "到达为北京时间(泰国慢 1h)"
148
+ },
149
+ {
150
+ "id": "MU6088",
151
+ "dep": "13:20",
152
+ "arr": "16:50",
153
+ "price_cny": 950,
154
+ "price_note": "午后班,周末收尾从容"
155
+ }
156
+ ],
157
+ "buffer_min": 120,
158
+ "origin_transfer_min": 60,
159
+ "dest_transfer_min": 45,
160
+ "arrive_by": "18:00",
161
+ "anchors_note": "BKK→KMG 每天约 6 班,飞行约 2h25m + 时差 1h",
162
+ "tz_offset_min": 60,
163
+ "origin_tz_offset_min": 420,
164
+ "evidence": [
165
+ {
166
+ "tag": "[demo-reconcil:已]",
167
+ "note": "8.4 周二 FD582 DMK 08:10→KMG 11:25 + KMG 转飞丽江(已挖,对话第 12 轮)"
168
+ },
169
+ {
170
+ "tag": "[demo-reconcil:已]",
171
+ "note": "8.4 FD582 DMK 08:10→KMG 11:25 是真实选择(demo 8.3 MU6088 是备选);但 journey 求解器当前仅用 f3 services 内的 data,FD582 改后触发 journey §3 回归(DZ6252 选深夜班)。FD582 真实值移到 flights_2026.json 的 meta 备查 + yunnan-pack 的 yn0 衔接仍写,引擎层不挂接直至 f4 真值校准(M4 待 founder 答 4 题)"
172
+ }
173
+ ]
174
+ },
175
+ {
176
+ "id": "f4",
177
+ "note": "昆明→深圳,衔接 8.10 凌晨红眼(EK329 需 ~22:45 前到 SZX 值机)",
178
+ "date": "2026-08-09",
179
+ "services": [
180
+ {
181
+ "id": "ZH9108",
182
+ "dep": "09:05",
183
+ "arr": "11:20",
184
+ "price_cny": 1150,
185
+ "price_note": "早班,深圳白天还能休整"
186
+ },
187
+ {
188
+ "id": "MU5233",
189
+ "dep": "16:20",
190
+ "arr": "18:35",
191
+ "price_cny": 980,
192
+ "price_note": "午后班"
193
+ },
194
+ {
195
+ "id": "DZ6252",
196
+ "dep": "22:40",
197
+ "arr": "01:20",
198
+ "price_cny": 700,
199
+ "price_note": "深夜班——到达晚于红眼值机截止,应被引擎的 arrive_by 锚点排除"
200
+ }
201
+ ],
202
+ "buffer_min": 90,
203
+ "origin_transfer_min": 60,
204
+ "dest_transfer_min": 0,
205
+ "anchors_note": "KMG→SZX 每天约 16 班(06:55-23:00),约 2h15m;深夜班是负例,验证锚点排除能力",
206
+ "origin_tz_offset_min": 480,
207
+ "evidence": [
208
+ {
209
+ "tag": "[auto-guess:2026-08-24]",
210
+ "note": "f4 实际到达 SZX≈22:00(MU6088/DZ6252 中间值,给 EK329 红眼留 4h 缓冲)—founder 校正即改"
211
+ }
212
+ ]
213
+ }
214
+ ]
215
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "request": {
3
+ "note": "想去这儿(素材:一张大理洱海的照片,湖边什么都不干的感觉)",
4
+ "home": {
5
+ "city": "上海",
6
+ "hubs": {
7
+ "PVG": { "to_hub_min": 90 },
8
+ "Hongqiao": { "to_hub_min": 40 }
9
+ }
10
+ },
11
+ "motivation": {
12
+ "weights": { "escape_rest": 0.7, "curiosity": 0.3 },
13
+ "hard": { "wake_not_before": "06:30", "min_arrival_energy_pct": 40 }
14
+ },
15
+ "window_days": 2,
16
+ "budget_cny": 3000
17
+ },
18
+ "candidates": [
19
+ {
20
+ "id": "dali",
21
+ "name": "大理·洱海",
22
+ "hub": "PVG",
23
+ "buffer_out_min": 90,
24
+ "buffer_ret_min": 90,
25
+ "services_out": [
26
+ { "id": "MU9712", "dep": "07:50", "arr": "12:20", "price_cny": 980 },
27
+ { "id": "MU9714", "dep": "11:30", "arr": "16:05", "price_cny": 1180 }
28
+ ],
29
+ "services_ret": [
30
+ { "id": "MU9713", "dep": "13:40", "arr": "17:10", "price_cny": 890 },
31
+ { "id": "MU9715", "dep": "17:20", "arr": "20:45", "price_cny": 950 }
32
+ ],
33
+ "dest_transfers": [
34
+ { "mode": "taxi", "min": 75, "price_cny": 120 },
35
+ { "mode": "bus_plus_taxi", "min": 105, "price_cny": 40 }
36
+ ],
37
+ "stay_cny_per_night": 450,
38
+ "local_daily_cny": 200,
39
+ "min_days_for_purpose": 5,
40
+ "imagery_match": 0.95,
41
+ "best_months": [3, 4, 5, 9, 10, 11]
42
+ },
43
+ {
44
+ "id": "qiandao",
45
+ "name": "千岛湖",
46
+ "hub": "Hongqiao",
47
+ "buffer_out_min": 20,
48
+ "buffer_ret_min": 20,
49
+ "services_out": [
50
+ { "id": "G7315", "dep": "07:35", "arr": "09:47", "price_cny": 120 },
51
+ { "id": "G7481", "dep": "08:53", "arr": "11:02", "price_cny": 126 }
52
+ ],
53
+ "services_ret": [
54
+ { "id": "G7482", "dep": "16:36", "arr": "18:52", "price_cny": 126 },
55
+ { "id": "G7316", "dep": "18:40", "arr": "20:58", "price_cny": 120 }
56
+ ],
57
+ "dest_transfers": [
58
+ { "mode": "taxi", "min": 25, "price_cny": 30 },
59
+ { "mode": "bus", "min": 40, "price_cny": 8 }
60
+ ],
61
+ "stay_cny_per_night": 380,
62
+ "local_daily_cny": 180,
63
+ "min_days_for_purpose": 2,
64
+ "imagery_match": 0.8,
65
+ "best_months": [4, 5, 9, 10]
66
+ },
67
+ {
68
+ "id": "taihu",
69
+ "name": "苏州·太湖",
70
+ "hub": "Hongqiao",
71
+ "buffer_out_min": 20,
72
+ "buffer_ret_min": 20,
73
+ "services_out": [
74
+ { "id": "G101", "dep": "08:12", "arr": "08:47", "price_cny": 42 },
75
+ { "id": "G103", "dep": "09:05", "arr": "09:41", "price_cny": 42 }
76
+ ],
77
+ "services_ret": [
78
+ { "id": "G110", "dep": "17:22", "arr": "18:05", "price_cny": 42 },
79
+ { "id": "G112", "dep": "19:10", "arr": "19:55", "price_cny": 42 }
80
+ ],
81
+ "dest_transfers": [
82
+ { "mode": "taxi", "min": 35, "price_cny": 45 },
83
+ { "mode": "bus", "min": 55, "price_cny": 6 }
84
+ ],
85
+ "stay_cny_per_night": 320,
86
+ "local_daily_cny": 150,
87
+ "min_days_for_purpose": 2,
88
+ "imagery_match": 0.6,
89
+ "best_months": [4, 5, 9, 10]
90
+ }
91
+ ]
92
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "meta": {
3
+ "case": "gotry-demo-1:普吉岛 workation 多段行程(真实任务重放,2026-07/08)",
4
+ "note": "日期为 2026 年(已过去):这是重放评测用例,发起人知道真实答案,用于对账。2026-07-17 是周五、08-01 是周六、08-09 是周日、08-10 是周一。",
5
+ "source_brief": "7.17周五22:40落地深圳;7.18早上去香港办银行开户&保险签约;争取7.18当天飞泰国普吉岛,跟女朋友在普吉岛见面;在普吉岛和附近(对岸有个万xx的海边小城听说也不错)待两周,居家办公,女朋友潜水出海;周五晚或周六早到曼谷,周末在曼谷;周日或周一飞昆明,云南玩一周(请假);8.9赶到深圳,8.10周一凌晨(周日晚)从深圳起飞,周一上班前到迪拜(机场回来直接上班)。请做机票和酒店的行程规划和推荐。"
6
+ },
7
+ "traveler": {
8
+ "home_base": "迪拜(工作地);中国护照",
9
+ "profile_notes": "远程办公者(workation);女朋友先在普吉岛;请假期=云南一周",
10
+ "motivation": {
11
+ "weights": { "relationship": 0.35, "work_efficiency": 0.25, "curiosity": 0.2, "instrumental": 0.2 },
12
+ "taxonomy_note": "复合动机:关系陪伴(与女朋友会合)+ workation 工作效率 + 云南探索 + 工具性目标(香港办证)。instrumental 子目标不进动机谱系,固化为硬锚点(legs.hard_anchors)。"
13
+ }
14
+ },
15
+ "hard_anchors": [
16
+ { "id": "a1", "time": "2026-07-17T22:40", "place": "深圳宝安国际机场(T1/T2 待确认)", "event": "航班落地", "note": "上游航段不在本规划范围" },
17
+ { "id": "a2", "time": "2026-07-18 上午(银行营业 09:00-12:00 区间)", "place": "香港", "event": "银行开户 + 保险签约", "note": "时效型事务:决定 7.18 必须一早过境;开户通常需 1-3 小时,签约可能同网点" },
18
+ { "id": "a3", "time": "2026-07-18 晚间", "place": "普吉岛(HKT)", "event": "与女朋友会合", "note": "争取当天飞;软锚点,若不可行则 7.19 早班(但损耗一天 workation)" },
19
+ { "id": "a4", "time": "2026-07-31(周五)晚 或 2026-08-01(周六)早", "place": "曼谷", "event": "抵达曼谷度周末", "note": "08-01 是周六;周五晚出发可最大化周末" },
20
+ { "id": "a5", "time": "2026-08-02(周日) 或 08-03(周一)", "place": "昆明(KMG)", "event": "飞抵昆明,云南一周开始", "note": "请假周 8.3-8.9" },
21
+ { "id": "a6", "time": "2026-08-09(周日) 全天", "place": "深圳", "event": "必须赶到深圳", "note": "云南→深圳当日航段;需为凌晨红眼留接驳余量" },
22
+ { "id": "a7", "time": "2026-08-09 深夜 ~ 08-10 凌晨起飞,08-10 周一 06:00 前落地", "place": "深圳 → 迪拜(DXB)", "event": "红眼航班,落地直奔办公室(09:00 前到岗)", "note": "全成本红旗:整段旅行的『充电』以最大生物钟破坏收尾;引擎职责是把代价摆上桌(当日精力预估),不是禁止" }
23
+ ],
24
+ "stay_blocks": [
25
+ {
26
+ "id": "s1", "place": "香港/深圳边境侧", "nights": 1,
27
+ "window": "7.17 深夜 - 7.18 清晨过境",
28
+ "requirements": ["落地 22:40 后可达", "靠近口岸(福田/深圳湾)", "极早退房或行李寄存"],
29
+ "note": "落地太晚,多数口岸已关或即将关闭;宿深圳口岸侧最稳"
30
+ },
31
+ {
32
+ "id": "s2", "place": "普吉岛(+对岸『万xx』海边小城,候选:考拉克 Khao Lak / 甲米·奥南 Krabi-Ao Nang / 董里 Trang)", "nights": 13,
33
+ "window": "7.18 - 7.31(约两周,7.20-7.31 含 10 个工作日)",
34
+ "requirements": [
35
+ "workstation 级住宿:稳定 WiFi(≥50Mbps/低延迟)、书桌、安静、可长住(服务式公寓/公寓式酒店优于酒店)",
36
+ "女朋友出海便利:靠近潜店码头(Chalong/查龙一带或奥南)",
37
+ "长住价格谈断(14 晚连住折扣)",
38
+ "『万xx』为模糊引用:素材是憧憬表达式,候选地待研究阶段以 workation+潜水双需求打分裁决"
39
+ ],
40
+ "note": "workation 是本行程的最大住宿决策:按『办公室』标准而非『度假房』标准选"
41
+ },
42
+ {
43
+ "id": "s3", "place": "曼谷", "nights": 2,
44
+ "window": "8.1(或 7.31 晚)- 8.2/8.3",
45
+ "requirements": ["周末生活圈(BTS 沿线/Sukhumvit/暹罗)", "近地铁站", "退房时间衔接周日或周一航班"]
46
+ },
47
+ {
48
+ "id": "s4", "place": "云南(昆明起始,一周环线)", "nights": 6,
49
+ "window": "8.3 - 8.9",
50
+ "requirements": ["请假周纯旅行:昆明为航点,环线候选(大理/丽江/香格里拉)由动机『curiosity+关系』裁决", "8.9 需回到昆明机场飞深圳(或环线终点直飞)"],
51
+ "note": "此段是全行程唯一的『纯休整/探索』段——动机权重在此最高"
52
+ }
53
+ ],
54
+ "flight_legs": [
55
+ { "id": "f1", "from": "香港 HKG", "to": "普吉 HKT", "date": "2026-07-18", "pattern": "午后/傍晚直飞(约 3h10m-3h40m);办证完成后口岸→机场接驳约 60-90min", "open": "直飞 vs 经 BKK 中转;当天达是软锚点" },
56
+ { "id": "f2", "from": "普吉 HKT(或万xx候选地机场如 KBV 甲米)", "to": "曼谷 BKK/DMK", "date": "2026-07-31 晚 或 08-01 早", "pattern": "高频短途(1h25m),周五晚班或周六首班", "open": "出发机场取决于 s2 的最终选址" },
57
+ { "id": "f3", "from": "曼谷 BKK", "to": "昆明 KMG", "date": "2026-08-02 或 08-03", "pattern": "直飞约 2h30m(泰航/东航/昆航等);周日班衔接周末,周一班衔接工作日心态" },
58
+ { "id": "f4", "from": "昆明 KMG(或云南环线机场)", "to": "深圳 SZX", "date": "2026-08-09", "pattern": "白天直飞约 2h;需为 a7 红眼留接驳与休整余量" },
59
+ { "id": "f5", "from": "深圳 SZX", "to": "迪拜 DXB", "date": "2026-08-09 深夜(~23:00-01:00 起飞)", "pattern": "红眼直飞约 8h30m,08-10 清晨落地;『机场回来直接去上班』" }
60
+ ],
61
+ "constraints": {
62
+ "budget": null,
63
+ "budget_note": "未提供——demo 应输出分层预算(经济/舒适/便利三档)而不是替用户猜",
64
+ "documents": ["中国护照;泰国免签时限需确认(2026 政策)", "香港办证所需材料不在引擎范围,列为前置检查项"],
65
+ "work": ["7.20-7.31 为远程工作日(10 个),每天需要 workstation 与会议静音环境"],
66
+ "energy_red_flags": ["a7 红眼+直奔办公室:落地精力预估 <40%,当日不宜安排重要会议(全成本模型的招牌场景)"]
67
+ },
68
+ "open_questions": [
69
+ { "id": "q1", "q": "『万xx』海边小城是哪?(素材模糊引用)", "candidates": ["Khao Lak 考拉克", "Krabi/Ao Nang 甲米·奥南", "Trang 董里"], "resolve_by": "研究阶段:以 workation 质量 + 潜水便利双维度打分" },
70
+ { "id": "q2", "q": "预算档位?", "options": ["经济", "舒适", "便利优先"], "resolve_by": "回访选择题(gate)" },
71
+ { "id": "q3", "q": "7.31 晚走还是 8.1 早走去曼谷?", "options": ["周五晚(最大化周末,但终结 workation 傍晚)", "周六早(多一夜普吉)"], "resolve_by": "回访选择题(gate)" },
72
+ { "id": "q4", "q": "云南环线选向(大理/丽江/香格里拉组合)?", "resolve_by": "研究阶段+动机匹配" }
73
+ ],
74
+ "engine_status": "本用例为 multi-leg 扩展的需求输入:当前引擎(单 leg×候选)不足以直接求解,leg 链/跨日/串联全成本核算为 P0 第二项"
75
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "meta": {
3
+ "note": "四个住宿块的价格档(经济/舒适/便利),公开渠道估算,非实时报价。workation 块按『办公室标准』建模。",
4
+ "sources": [
5
+ "HOMA/PropertyScout:查龙服务式公寓月租 27,720-165,000 THB;本地公寓 5,000-10,000 THB/月(6-12 月约)",
6
+ "Expedia/Airbnb:卡塔/卡伦公寓 $18-25/晚起;两周连住议价空间 20-30%",
7
+ "Reddit 数字游民:普吉『工作+海滩』区域排名 Rawai/查龙/普吉老城/卡塔卡伦;查龙骑摩托出行方便、租金更低",
8
+ "Trip.com:曼谷周末三星约 RM388(≈¥240)/晚,四星约 RM765(≈¥528)/晚",
9
+ "Booking:大理短租均价 ¥408/晚,淡季包周民宿 ¥1,000-2,500;丽江月租淡季 ¥1,500/月",
10
+ "携程:深圳机场雅斯特(免费接送机)¥218 起;航站楼内凯悦系人均 ¥150 起;乐港计时休息室 ¥283 起"
11
+ ],
12
+ "key_finding": "查龙(Chalong)同时是数字游民聚集区与潜水出海主码头——发起人 workation 与女朋友潜水的双需求在同一点交汇,是 s2 基地的首选;『万xx』候选(考拉克/甲米奥南/董里)作为中途换防的备选而非主基地"
13
+ },
14
+ "stays": [
15
+ {
16
+ "id": "s1",
17
+ "note": "7.17 深夜落地后的过夜(次日一早过境香港)",
18
+ "nights": 1,
19
+ "options": [
20
+ { "tier": "经济", "name": "雅斯特国际酒店(深圳机场 T3 店)", "price_cny": 218, "why": "免费接送机;但次日需先回市区再过境" },
21
+ { "tier": "便利", "name": "福田口岸侧连锁酒店", "price_cny": 320, "why": "落地后打车约 1h ¥120;清晨 06:30 步行过境,为办证锚点买时间" },
22
+ { "tier": "舒适", "name": "深圳机场凯悦嘉寓(航站楼内)", "price_cny": 450, "why": "落地即睡;但次晨需赶早过境" }
23
+ ],
24
+ "recommendation": "便利档(口岸侧):a2 办证锚点 09:00 开门,住口岸侧是唯一能睡到 6:40 还从容的选择(全成本视角:落地夜的门到门已耗尽精力,次晨多睡 1h 价值最高)"
25
+ },
26
+ {
27
+ "id": "s2",
28
+ "note": "普吉岛 workation 两周(13 晚,含 10 个工作日)+ 女朋友潜水出海",
29
+ "nights": 13,
30
+ "location_decision": "查龙/Rawai 基地(数字游民区+潜水码头双吻合);『万xx』候选(考拉克/甲米奥南/董里)留作中途换防 2-3 晚的选项,待 gate 裁决",
31
+ "options": [
32
+ { "tier": "经济", "name": "卡塔/卡伦公寓式(自炊)", "price_per_night_cny": 140, "why": "$18-25/晚;离查龙码头 20-30min 车程" },
33
+ { "tier": "舒适", "name": "查龙/Rawai 服务式公寓(带共享办公)", "price_per_night_cny": 300, "why": "HOMA 类;workstation 标准:WiFi+办公区+潜水码头 10min 内;两周连住可议价 20-30%" },
34
+ { "tier": "高端", "name": "海滨度假公寓(带办公桌)", "price_per_night_cny": 550, "why": "工作体验与度假体验兼得" }
35
+ ],
36
+ "requirements_check": ["WiFi ≥50Mbps 且有备用(共享办公区)", "书桌+静音(10 个工作日的会议)", "近查龙码头(女朋友潜水集合点)", "长住议价"]
37
+ },
38
+ {
39
+ "id": "s3",
40
+ "note": "曼谷周末(2 晚)",
41
+ "nights": 2,
42
+ "options": [
43
+ { "tier": "经济", "name": "BTS 沿线三星(Mo Chit/素坤逸)", "price_per_night_cny": 240 },
44
+ { "tier": "舒适", "name": "素坤逸/暹罗四星(直通 BTS)", "price_per_night_cny": 528 }
45
+ ]
46
+ },
47
+ {
48
+ "id": "s4",
49
+ "note": "云南一周(6 晚,请假纯旅行;昆明为进出航点,环线待 gate)",
50
+ "nights": 6,
51
+ "options": [
52
+ { "tier": "经济", "name": "大理/丽江淡季包周民宿", "total_cny": 1200, "why": "淡季月租可低至 ¥900-1500/月,包周约 ¥200/晚" },
53
+ { "tier": "舒适", "name": "洱海/古城景观民宿", "total_cny": 2400, "why": "均价 ¥408/晚,一周议价后约 ¥400/晚" }
54
+ ]
55
+ }
56
+ ],
57
+ "budget_tiers_summary": {
58
+ "note": "机票(五段联算 ¥8,380)+ 住宿的分层总预算(gate q2 的决策材料)",
59
+ "经济": { "flights": 8380, "hotels": 4200, "total": 12580 },
60
+ "舒适": { "flights": 8380, "hotels": 7900, "total": 16280 },
61
+ "hotel_breakdown_economy": "218(或 320 便利档)+140×13+240×2+1200",
62
+ "hotel_breakdown_comfort": "450+300×13+528×2+2400"
63
+ }
64
+ }