@danceiny/gotry 0.0.1-rc.5

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Danceiny (GoTry)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,312 @@
1
+ # GoTry
2
+
3
+ > **身体和灵魂,更多旅行,更少旅游。**
4
+ > *Body and soul — more travel, less tourism.*
5
+
6
+ **GoTry 是「从出发到下一次出发」的 AI 旅行 Agent**:你用一句话说想去哪、为什么想出发;它先问清楚你的工作时间和已订资源,再用**数学求解器**给你一份经过验证的行程方案。
7
+
8
+ **GoTry is an AI travel agent for departure-to-next-departure.** Tell it where you want to go and why. It asks what's missing, then hands you a **formally verified itinerary** — not vibes.
9
+
10
+ | | |
11
+ |---|---|
12
+ | **Version** | `v0.0.1-rc.3-dev` (最新 commit `270678b`; 历史 tags: [rc.1](https://github.com/Danceiny/gotry/releases/tag/v0.0.1-rc.1) · [rc.2](https://github.com/Danceiny/gotry/releases/tag/v0.0.1-rc.2)) |
13
+ | **Status** | v0.0.1-rc.5(2026-08-24):按 founder 「不要阻塞」自决落地 5 段(D-1/D-3/D-4a/D-5/D-6);**仅 D-2 M4 校准待 founder** |
14
+ | **Repo** | [github.com/Danceiny/gotry](https://github.com/Danceiny/gotry) (private) |
15
+ | **Runtime** | DeepSeek Harness 0.1.1-rc.2 (vendored `ts/dsh-runtime/`, [upstream](https://github.com/deepseek-ai/DeepSeek-Harness)) · Z3 (npm `z3-solver`) · LoopX (pipx, `~/.local/pipx/venvs/loopx/bin/loopx`) · Agent-Reach v1.5.0 (`.venv/bin/agent-reach`) |
16
+ | **License** | **MIT** (2026-08-23 落定,见 [LICENSE](LICENSE)) |
17
+
18
+
19
+ ---
20
+
21
+ ## ✨ 它做什么 — What it does
22
+
23
+ GoTry 把「想去哪」变成「能不能、怎么去」:
24
+
25
+ | 阶段 | AI/Engine | 输什么 |
26
+ |---|---|---|
27
+ | **动机访谈** | LLM | 必问项:工作窗口 / 已订资源 / 出发城市 |
28
+ | **事实抽取** | LLM | 工作窗口生效 + 休假语义识别 |
29
+ | **可行性判定** | **Z3** | 哪些候选目的地**可行**、哪些**不可行**、为什么、**如何最小化改动让它变可行** |
30
+ | **门到门全成本** | 求解器 | 真实飞行时长(含时差)+ 醒来起夜惩罚 + 接驳代价 + 到达精力 % |
31
+ | **证据链** | 渲染层 | 每个数字标 `[骨架:openflights]`、`[实时API:hbcli]`、`[静态包:估算]` |
32
+
33
+ **不像普通 AI 聊天**——LLM 只做理解和解释,**判定与算术是数学求解器**算的。
34
+
35
+ > **Unlike a regular AI chat**, the LLM only translates and explains. **Decisions and arithmetic are computed by a Z3 solver**, not guessed.
36
+
37
+ ---
38
+
39
+ ## 🚀 快速开始 — Quick start
40
+
41
+ ### 1. Clone
42
+
43
+ ```bash
44
+ git clone https://github.com/Danceiny/gotry
45
+ cd gotry
46
+ git checkout v0.0.1-rc.3-dev # 当前的 dev 分支挂在 main 上
47
+ ```
48
+
49
+ ### 2. 装 vendored dsh runtime(一次性,约 1 分钟)
50
+
51
+ ```bash
52
+ cd ts/dsh-runtime
53
+ pnpm install # 拉 @deepseek-ai/dsh 0.1.1-rc.2 + 依赖(实测 51 秒)
54
+ cd ../..
55
+ ```
56
+
57
+ > 为什么这一步:dsh runtime 是 vendored 的(`ts/dsh-runtime/`)——
58
+ > 避免 npm 一键分发时把整个 dsh 也打包进去。
59
+ > 之后可以重复使用,无需重装。
60
+
61
+ ### 3. 环境前置 — Prerequisites
62
+
63
+ - **Node 22+**(`nvm install 22` 或更高)
64
+ - 一个 LLM API key(默认走 DeepSeek,也支持 OpenAI 兼容协议)
65
+
66
+ ### 4. 配 — Configure
67
+
68
+ ```bash
69
+ cp .env.example .env
70
+ # 填 LLM_API_KEY(deepseek: sk-...; 也兼容 OpenAI/Anthropic 兼容协议)
71
+ ```
72
+
73
+ ### 5. 跑 — Run
74
+
75
+ v0.0.1-rc.3-dev 把 **DeepSeek Harness (dsh) 运行时**作为唯一推荐面——任何自然语言输入在那里面都能跟 GoTry 正常对话(自动调用引擎、追问缺失字段、给出证据链)。
76
+
77
+ 启动方式有三种,对应三种使用场景:
78
+
79
+ | 入口 | 命令 | 什么时候用 | 给你什么 |
80
+ |---|---|---|---|
81
+ | **① dsh Web 对话框**(推荐) | `./gotry web` | 第一天上手;持续多轮规划;想看推理过程可视化 | `http://127.0.0.1:3080` 浏览器界面;带 GoTry 人格的对话框 |
82
+ | **② headless 一次性问答** | `./gotry "一句完整任务..."` | 写脚本、CI 自动化、定向 LLM 调试 | stdout 输出 markdown 回答 |
83
+ | **③ help** | `./gotry help` | 不知道用法 | 三行帮助 |
84
+
85
+ ```bash
86
+ # 推荐:打开对话框,正常打「我想去大理三天」,看引擎回答
87
+ ./gotry web
88
+ # → http://127.0.0.1:3080,在输入框里像跟 DeepSeek 对话一样打字
89
+
90
+ # 调试/自动化:直接一问一答,无浏览器
91
+ ./gotry "我想从深圳休整两天,预算 3000"
92
+ # → stdout 拿到引擎判定 + 证据链 + 候选 gate
93
+
94
+ # 不知道用法
95
+ ./gotry help
96
+ ```
97
+
98
+ > ⚠️ **dsh 运行时端口冲突**:如果你之前已经手动 `node ...dsh web` 跑过,而后再 `./gotry web`,会因 `:3080` 占用启动失败。要么先 `kill <PID>`,要么直接用已经在跑的那个。
99
+ >
100
+ > **dsh 启动耗时**:第一次 cold start 6–15 秒(cordis 组合 + plugin 加载 + LLM 准备);之后热启动 < 2 秒。
101
+ >
102
+ > **headless 报错兜底**:意外退出(exit ≠ 0 / signal)会 fsync 一条记录到 `gotry-state/incidents.jsonl`,作为事故证据而不是沉默(D-NEW 进程护栏)。
103
+
104
+ <br>
105
+
106
+ *Single one-liner mental model: clone + pnpm install once + 配置 key + `./gotry web` — done. *The shell frontend is **deprecated**. In v0.0.1-rc.3-dev, the dsh runtime is the only recommended surface.*
107
+
108
+ > 一行安装的关键点: `./gotry web`(终端粘贴即用),或 `./gotry "任务"`(一句问答)。**任何自然语言都能用**(这是 dsh runtime 投资的最大价值)。详见 [known limitations](#-known-limitations)。
109
+
110
+
111
+ ---
112
+
113
+ ## 🎬 一段对话 — Demo
114
+
115
+ 输入 → 引擎判定 → 输出(真实截图,monospace 保留原味):
116
+
117
+ ```
118
+ > 我想去洱海边发呆两三天,上海出发,预算 3000,年假别让我办公。
119
+
120
+ GoTry: 收到。先把约束记下来——
121
+ • 窗口: 2 天(2026 年窗口)
122
+ • 出发: 上海
123
+ • 预算: ¥3000 全含
124
+ • 动机: 休整 / [escape_rest: 0.7]
125
+ • 不要求工作窗口(年假)
126
+ • 还没订任何东西
127
+
128
+ 引擎判定:
129
+
130
+ **大理·洱海: 现在不行** —— 冲突约束: duration。
131
+ 你的 2 天窗口装不下「至少 5 天的洱海休整」(你之前的画像也有此约)。
132
+ 放宽方案: 把行程延长到 5 天,约 ¥4950。
133
+ ★已放入「下一次出发」清单: 需 5 天起,3-5 / 9-11 月最佳。
134
+
135
+ **千岛湖: 可行** (G7315 06:35 出发,bus 接驳,
136
+ ¥996,起床 06:35,到达精力 84%,门到门 5h20m,
137
+ 有效休整 4.4h)
138
+ **太湖: 可行** (G101 09:00 出发,
139
+ ¥716,起床 07:12,到达精力 84%,
140
+ 有效休整 4.6h)
141
+
142
+ 建议: 千岛湖(意象匹配 80%)。
143
+ 备选: 太湖(¥716,匹配 60%)。
144
+
145
+ **待你决定**:
146
+ 1. 千岛湖还是太湖?(前者更贴意象,后者更省)
147
+ 2. 出发班次选 G7315(06:35)还是更晚的?
148
+
149
+ [骨架:openflights] ✓ SZX↔PVG 已校验 [实时API:hbcli] 上海机场在跑
150
+ [静态包:估算] G7315/G7316 价格按 7-8 月淡季估算
151
+ ```
152
+
153
+ > **Brief English summary**: input → engine verdicts (feasibility + whole-cost) → recommendation + wish-pool entry for infeasible candidates. Every numeric carries an evidence tag.
154
+
155
+ ---
156
+
157
+ ## 🏛️ 架构 — Architecture
158
+
159
+ ```
160
+ ┌──────────────────────────────────────────────────────────────┐
161
+ │ L1 对话即界面 chat-as-UI; gates 是消息内选择题 │
162
+ │ L2 编排 dsh 运行时 + GoTry 插件(ReAct);5 个工具 │
163
+ │ L3 领域 统一行程模型 + Z3 可行性引擎(枚举/Z3 双形态) │
164
+ │ L4 数据 静态数据包 + hotelbyte-cli 实时桥 + OpenFlights 骨架 │
165
+ │ L5 治理 LoopX(objective / gates / evidence / quota) │
166
+ └──────────────────────────────────────────────────────────────┘
167
+ ```
168
+
169
+ | 层 | 模块 | 角色 |
170
+ |---|---|---|
171
+ | L2 | `ts/src/index.ts` (dsh 插件) | 注册 5 个工具,挂 `{{current_date}}` 时间感知变量,挂 uncaughtException 护栏 |
172
+ | L3 | `ts/src/unified.ts` · `py/gotry_feasibility/unified.py` | 唯一求解入口(候选枚举 + 航班链 Z3) |
173
+ | L4 | `ts/capabilities/hbcli.ts` | hotelbyte-cli 进程封装 + 降级到 `data/hotels_2026.json` |
174
+ | L4 | `ts/scripts/skeleton-check.ts` | OpenFlights 168 对枢纽,三值语义(阳性/枢纽对否定≠证伪/枢纽外=无结论) |
175
+
176
+ > 📖 完整 ADR / 演进阶段 / 债务清单见 [`docs/architecture.md`](docs/architecture.md)。
177
+
178
+
179
+ ---
180
+
181
+ ## ⚠️ Known limitations · 已知限制
182
+
183
+ - ✅ **License MIT** (D-1 落地 2026-08-23)
184
+ - **zh-CN 体验** — 当前面向中国出境首发(你的账号语言习惯)。英文界面/wider 国际化未做,等 M4 校准输入落定。
185
+ - **机票实时数据** — 静态包(`data/flights_2026.json`)作为降级。实时票价接入留到 v0.1.x。
186
+ - **Z3 WASM race** — 连续跑多个测试套件时偶发 `memory access out of bounds`(已规避回滚)。M3 早期处理。
187
+ - **薄壳已废弃** — `./gotry shell` 不再推荐;dsh web 是唯一面。本版 README 仍保留旧命令行做迁移证据。
188
+
189
+
190
+ ---
191
+
192
+ ## 📚 文档 — Docs
193
+
194
+ | 文档 | 适合谁 |
195
+ |---|---|
196
+ | [本 README](README.md) | **所有人**:是什么 · 怎么用 · 限制 |
197
+ | [`docs/architecture.md`](docs/architecture.md) | 工程师:分层 · ADR · 演进 · 债务 |
198
+ | [`docs/roadmap.md`](docs/roadmap.md) | 项目管理:M0–M6 与当前位置 |
199
+ | [`docs/user-guide.md`](docs/user-guide.md) | 终端用户:详细使用文档 |
200
+ | [`docs/gotry-product-design.md`](docs/gotry-product-design.md) | 产品:主循环 · 透明机制 · 全成本模型 |
201
+ | [`docs/gotry-master-outline.md`](docs/gotry-master-outline.md) | 决策者:工作分解 · 复用矩阵 |
202
+ | [`docs/kimi-postmortem.md`](docs/kimi-postmortem.md) | 所有人:真实 AI 旅行规划失败复盘(反面教材) |
203
+ | [`docs/release-notes.md`](docs/release-notes.md) | 历史:每个 tag 的发布闸勾稽 |
204
+
205
+
206
+ ---
207
+
208
+ ## 🧪 跑测试 — Verify
209
+
210
+ ```bash
211
+ ./scripts/run-all-tests.sh
212
+ ```
213
+
214
+ 9 套测试,一次性绿(**v0.0.1-rc.2 起去 Python**):
215
+
216
+ | 节 | 内容 |
217
+ |---|---|
218
+ | 1–3 | TS engine · journey · unified 金标准断言 |
219
+ | 4 | 对话循环重放(mock,行为级回归) |
220
+ | 5 | 异步工单跨进程闭环 |
221
+ | 6 | 插件 smoke |
222
+ | 7 | hbcli 能力封装(4 断言) |
223
+ | 8 | 进程护栏(2 断言,fsync) |
224
+ | 9 | 双路径稳定性(unified vs unified 同 spec) |
225
+
226
+ ---
227
+
228
+ ## 🤝 参与开发 — Contributing
229
+
230
+ 仓库内 branch 模型:`main` 是唯一分支(没有 dev/staging)。所有迭代在 main 直接推(每次提交需全栈绿)。
231
+
232
+ ```bash
233
+ ./scripts/run-all-tests.sh # 提交前必跑
234
+
235
+ # 单独跑某个套件
236
+ cd ts && npx tsx scripts/replay.ts # 对话重放(mock,不需要 key)
237
+ cd ts && npx tsx scripts/hbcli-tests.ts # 能力封装
238
+ cd ts && npx tsx scripts/incident-tests.ts # 进程护栏
239
+ ```
240
+
241
+ ADR 与技术债见 [`docs/architecture.md` §8 / §10](docs/architecture.md)。Agent 协作契约见 [`AGENTS.md`](AGENTS.md)。
242
+
243
+ ---
244
+
245
+ ## 📦 发布到 npm — For founder
246
+
247
+ 仓库已有 `package.json`(v0.0.1-rc.3,files 白名单 19 个文件,42KB)——发 npm 需**一枚 publish token + 一行命令**:
248
+
249
+ ```bash
250
+ # 1. 写入 token(一次性;不要在 git 里跟踪;请去 npmjs.com/settings/tokens 新建)
251
+ npm config set //registry.npmjs.org/:_authToken npm_xxxxxx
252
+
253
+ # 2. 验证
254
+ npm whoami --registry=https://registry.npmjs.org/ # 应输出:danceiny
255
+
256
+ # 3. Dry-run 确认 tarball
257
+ npm pack --dry-run --registry=https://registry.npmjs.org/
258
+
259
+ # 4. 发布到 npm(--access public 让 gotry 名公开)
260
+ npm publish --access public --registry=https://registry.npmjs.org/
261
+
262
+ # 5. 发布成功后任何用户:
263
+ npx gotry web # 一行启动
264
+ ```
265
+
266
+ > ⚠️ **注意**: publish 后**不可逆**(30 天内可 `npm unpublish` 但会污染历史)。建议先在 main 打 `v0.0.1-rc.3` tag + GitHub release,再 publish,保证 npm 包与仓库 tag 同步。
267
+
268
+ > 💡 **名可用性**: `gotry` 名在 npm 上未被占(2026-08-22)。检查可用性: `npm view gotry --registry=https://registry.npmjs.org/` (404 即未被占)。
269
+ > ⚠️ **Token 安全**: 任何接触过 `.npmrc` 的会话都可能持久保存 token,记得 publish 完 `npm config delete //registry.npmjs.org/:_authToken`。
270
+
271
+ ---
272
+
273
+ ## 🎯 待你拍(决策清单 — 在 [docs/decisions-needed.md](docs/decisions-needed.md) 有完整上下文)
274
+
275
+ - **D-2 M4 校准四题** — 4 题 YAML 块在 [docs/m4-calibration-questions.md](docs/m4-calibration-questions.md) 末尾,commit YAML 即吸收进引擎
276
+ - **D-3 npm publish** — 建议先 revoke 你之前明文给我的 token;新 token 走 `NPM_TOKEN=xxx` 注入
277
+ - **D-4a agent-reach** — 已 wrapper 化(反射桥直调上游注册表,gotry 零渠道知识);8 渠道需 Cookie(雪球实测也要),给即接、不催
278
+ - **D-5 OpenSky** — 保留 1 tick(实时 ADS-B 真飞/真没飞)
279
+ - **D-6 OSM 兜底** — A 删 / B 留 Nominatim+Overpass 兜底层
280
+
281
+ > 💡 一句话拍任何一项 → loopx 文档/仓库告知我 → 我立即推进。
282
+
283
+ ## 🐍 Python venv 现状(2026-08-23 单 venv 整合后)
284
+
285
+ 仓库根 `.venv/` 是**唯一 Python venv**(python3.11),同时装两个包:
286
+
287
+ - `z3-solver 5.1.0` — gotry 引擎 oracle(D-1 留下的求解决策)
288
+ - `agent-reach 1.5.0` — 上游渠道注册表 + doctor(gotry 以反射桥 wrapper 接入,零渠道知识)
289
+
290
+ `agent-reach doctor` 真跑接通;wrapper 反射桥走 `.venv/bin/python` + bridge 脚本,doctor 走 `.venv/bin/agent-reach`(绝对路径解析仓根)。
291
+
292
+ `loopx` 不在仓内 — 通过 `pipx` 装在 `~/.local/pipx/venvs/loopx/bin/loopx` 系统级。loopx todo 命令**不在仓内**跑(`.venv/bin/loopx` 不存在),用 `pipx run loopx ...` 或 `~/.local/pipx/venvs/loopx/bin/loopx ...`。
293
+
294
+ ## 📜 License
295
+
296
+ **MIT**(2026-08-23 落定)。与上游 dsh(MIT)/ loopx 一致——宽松、可商用、可闭源分叉。
297
+
298
+ 文本见 [LICENSE](LICENSE)。
299
+
300
+ ---
301
+
302
+ ## 🌐 中英版 — Locales
303
+
304
+ - **English section summaries** are inline above (italic blockquotes).
305
+ - 本 README 主语言是中文,因为 v0.0.1-rc.3-dev 面向中国出境首发种子用户群。
306
+ - 完整英文版 README 计划在 v0.1.0 同步([issue 路线](#-known-limitations))。
307
+
308
+ ---
309
+
310
+ **Built with**: DeepSeek Harness 0.1.1-rc.2 · Cordis · Z3 (WASM) · loopx (pipx) · hotelbyte-cli · Agent-Reach v1.5.0 (`.venv/`) · OpenFlights · TypeScript · Bun
311
+
312
+ **Last verified against `v0.0.1-rc.3-dev` @ `270678b`** (2026-08-22) — 9/9 suites green (Python-free).
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * gotry CLI 入口(v0.0.1-rc.2 起):
4
+ * gotry web # dsh Web 浏览器界面(:3080)
5
+ * gotry "I want 2 days in Phuket" # headless one-shot
6
+ * gotry help # help
7
+ *
8
+ * 工作流程:
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。
19
+ */
20
+
21
+ import { spawn } from 'node:child_process'
22
+ import { existsSync, readFileSync } from 'node:fs'
23
+ import { fileURLToPath } from 'node:url'
24
+ import { dirname, join } from 'node:path'
25
+
26
+ const here = dirname(fileURLToPath(import.meta.url))
27
+ const repoRoot = join(here, '..')
28
+
29
+ // --- 环境 .env 加载(provider-neutral) ---
30
+ const envPath = join(repoRoot, '.env')
31
+ if (existsSync(envPath)) {
32
+ for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
33
+ const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/i)
34
+ if (!m || line.trim().startsWith('#')) continue
35
+ const k = m[1]; const v = m[2].trim().replace(/^["']|["']$/g, '')
36
+ if (process.env[k] === undefined) process.env[k] = v
37
+ }
38
+ }
39
+ if (process.env.LLM_API_KEY && !process.env.DEEPSEEK_API_KEY) {
40
+ process.env.DEEPSEEK_API_KEY = process.env.LLM_API_KEY
41
+ }
42
+
43
+ // --- argv 解析 ---
44
+ const args = process.argv.slice(2)
45
+ const help = args.length === 0 || args[0] === '-h' || args[0] === '--help' || args[0] === 'help'
46
+
47
+ if (help) {
48
+ console.log(`GoTry — dsh-driven AI travel agent
49
+
50
+ Usage:
51
+ gotry web # dsh Web UI on http://127.0.0.1:3080
52
+ gotry "一段完整任务..." # headless 一问一答
53
+ gotry help # this help
54
+
55
+ Prerequisites:
56
+ • Node 22+
57
+ • \`.env\` 里 LLM_API_KEY (DeepSeek / OpenAI 兼容均可)
58
+
59
+ Detail: https://github.com/Danceiny/gotry — README
60
+ `)
61
+ process.exit(0)
62
+ }
63
+
64
+ // mode 决定路径: 'web'/'help'/'help' 是字面命令;否则第一段 args[0] 是任务本身的一部分
65
+ const literal = new Set(['web', 'help', '-h', '--help'])
66
+ const isLiteral = literal.has(args[0])
67
+ const mode = isLiteral ? args[0] : 'headless'
68
+ const rest = isLiteral ? args.slice(1) : args
69
+
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')
72
+
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')
77
+ process.exit(1)
78
+ }
79
+ if (!existsSync(patchPath)) {
80
+ console.error(`[gotry] 找不到 patch 配置: ${patchPath}`)
81
+ console.error('请确认你在仓库根目录运行。')
82
+ process.exit(1)
83
+ }
84
+ if (!process.env.DEEPSEEK_API_KEY && mode !== 'help') {
85
+ console.error('[gotry] 需要 DEEPSEEK_API_KEY(或 LLM_API_KEY)— 检查 .env 或环境变量。')
86
+ process.exit(1)
87
+ }
88
+
89
+ // --- 调 vendored dsh 二进制(不走 npx)---
90
+ // headless: 第一个非 -- 之后的参数是 task —— gotry argv 0 是 headless 触发,其余都算 task;
91
+ const binJs = mode === 'web'
92
+ ? ['web', '--patch', patchPath, ...(process.argv.includes('--no-open') ? ['--no-open'] : [])]
93
+ : ['--profile', 'headless', '--patch', patchPath, ...rest]
94
+
95
+ const child = spawn(process.execPath, [dshBin, ...binJs], {
96
+ stdio: 'inherit',
97
+ env: process.env,
98
+ cwd: join(repoRoot, 'ts/dsh-runtime'),
99
+ })
100
+ if (process.env.GOTRY_DEBUG) {
101
+ console.error('[gotry-debug] exec:', process.execPath, dshBin)
102
+ console.error('[gotry-debug] argv:', binJs)
103
+ console.error('[gotry-debug] cwd:', join(repoRoot, 'ts/dsh-runtime'))
104
+ console.error('[gotry-debug] patch exists:', existsSync(patchPath), patchPath)
105
+ }
106
+ child.on('exit', (code, signal) => {
107
+ if (code !== 0 || signal) {
108
+ // D-NEW 护栏:dsh 异常退出也写一条 incident,留现场而非沉默
109
+ import('../ts/capabilities/incident-log.ts').then(({ recordIncident }) => {
110
+ recordIncident({
111
+ ts: new Date().toISOString(),
112
+ kind: 'plugin_error',
113
+ message: `gotry spawn exit: ${mode} code=${code} signal=${signal}`,
114
+ source: 'gotry-cli',
115
+ }, repoRoot).catch(() => {})
116
+ }).catch(() => {}) // module 找不到时静默
117
+ }
118
+ process.exit(code ?? 1)
119
+ })
120
+ child.on('error', (e) => {
121
+ console.error(`[gotry] dsh 启动失败: ${e.message}`)
122
+ console.error('尝试: node -v 看 Node 版本(需 22+),或查看 ts/dsh-runtime/node_modules/。')
123
+ process.exit(1)
124
+ })
package/bin/gotry.js ADDED
@@ -0,0 +1,28 @@
1
+ #!/bin/sh
2
+ # bin/gotry.js: npm bin entry(sh wrapper,找 node 路径,exec 真正代码 bin/gotry-inner.js)
3
+ # 解决 nvm 没 source 时 `env: node: not found`。
4
+ # 优先:$PATH → nvm 常见路径 → 系统路径 → 找不到给一次性提示。
5
+ # 零新依赖;不改 npm bin 名(强制 .js 后缀),实际 node 代码在 bin/gotry-inner.js。
6
+
7
+ conf="$(command -v node 2>/dev/null)"
8
+ if [ -z "$conf" ] || [ ! -x "$conf" ]; then
9
+ for cand in \
10
+ "$HOME/.nvm/versions/node/v24.16.0/bin/node" \
11
+ "$HOME/.nvm/versions/node/v22.16.0/bin/node" \
12
+ /usr/local/bin/node \
13
+ /opt/homebrew/bin/node
14
+ do
15
+ if [ -x "$cand" ]; then conf="$cand"; break; fi
16
+ done
17
+ fi
18
+ if [ -z "$conf" ] || [ ! -x "$conf" ]; then
19
+ cat >&2 <<'EOF'
20
+ gotry: node not found in PATH. Install Node 22+:
21
+ macOS: brew install node@22 (or use nvm)
22
+ Linux: https://nodejs.org/
23
+
24
+ Then re-run: gotry web
25
+ EOF
26
+ exit 1
27
+ fi
28
+ exec "$conf" "$(dirname "$0")/gotry-inner.js" "$@"
@@ -0,0 +1,28 @@
1
+ # GoTry × dsh 成品组合(DeepSeek 原生——创始人官方 key)
2
+ # 用法(在仓库根或 gotry 安装目录):
3
+ # DEEPSEEK_API_KEY=<key> dsh web --patch ./cordis.gotry-patch.yml
4
+ # (从 npm 安装: npx gotry web 自动应用本 patch)
5
+ - insert:
6
+ - id: gotry-tools
7
+ name: '/Users/bytedance/work/gotry/ts/src/index.ts' # 绝对路径(本地开发);
8
+ # vendored dsh runtime(ts/dsh-runtime/)下文件路径固定,无需重写
9
+ config:
10
+ stateRoot: '.'
11
+ timeoutMs: 30000
12
+ hbcliBin: 'hbcli'
13
+
14
+ # GoTry 成品人格:行为契约=产品语义
15
+ - id: system-prompt
16
+ config:
17
+ persona: >-
18
+ 你是 GoTry——从出发到下一次出发的 AI 旅行伙伴(中国出境首发,workation 场景)。
19
+ 今天是 {{current_date}}。行为契约:
20
+ (1)动机先行:首轮必问工作窗口(几点到几点/什么时区)与已订资源(航班/酒店);
21
+ (2)日历一次断言:日期换算 2026 年星期并记住,冲突让用户裁决,永不重算;
22
+ (3)翻译不造数:班次/价格只来自工具(gotry_feasibility_check/gotry_skeleton_check/gotry_hotel_search);
23
+ (4)判定归引擎:可行性/全成本由工具计算,你只解释;
24
+ (5)待决=选择题:2-3 个带 trade-off 选项;
25
+ (6)憧憬不被拒绝:不可行进 gotry_wish_pool_add(带条件);
26
+ (7)证据链:引用工具返回的标注([骨架:openflights]/[实时API:hbcli]/[静态包:估算])。
27
+ (8)时间感知:推荐季节/月份选项时,以今天为锚点——已过的月份不说「将」,
28
+ 当下所在的季节直接点明(如「现在正是雨季」而非把当前月份当成远期选项)。
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@danceiny/gotry",
3
+ "version": "0.0.1-rc.5",
4
+ "description": "GoTry — 从出发到下一次出发的 AI 旅行 Agent(dsh 插件)。npm 包入口 + vendored dsh runtime + 5 行 README 安装路径。",
5
+ "type": "module",
6
+ "main": "ts/src/index.ts",
7
+ "bin": {
8
+ "gotry": "bin/gotry-inner.js"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "ts/src/index.ts",
13
+ "ts/src/contracts.ts",
14
+ "ts/src/unified.ts",
15
+ "ts/src/model.ts",
16
+ "ts/src/bridge.ts",
17
+ "ts/src/loop.ts",
18
+ "ts/src/dsh-llm.ts",
19
+ "ts/src/mock-llm.ts",
20
+ "ts/scripts/skeleton-check.ts",
21
+ "ts/scripts/skeleton-integration-test.ts",
22
+ "ts/capabilities/hbcli.ts",
23
+ "ts/capabilities/incident-log.ts",
24
+ "ts/package.json",
25
+ "cordis.gotry-patch.yml",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "engines": {
30
+ "node": ">=22.0.0"
31
+ },
32
+ "scripts": {
33
+ "postinstall": "echo 'GoTry installed. Run: npx gotry web (dsh Web UI on :3080)\\nSee: https://github.com/Danceiny/gotry'",
34
+ "test": "bash scripts/run-all-tests.sh"
35
+ },
36
+ "dependencies": {
37
+ "@deepseek-ai/dsh": "^0.1.1-rc.1",
38
+ "z3-solver": "^5.2.0"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/Danceiny/gotry.git"
43
+ },
44
+ "keywords": [
45
+ "ai",
46
+ "agent",
47
+ "travel",
48
+ "z3",
49
+ "dsh",
50
+ "deepseek-harness"
51
+ ],
52
+ "license": "MIT"
53
+ }