@danceiny/gotry 0.0.1-rc.12 → 0.0.1-rc.13
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/README.md +110 -157
- package/cordis.gotry-patch.yml +2 -2
- package/dist/capabilities/session/transport.js +11 -1
- package/dist/capabilities/session-login.js +17 -1
- package/dist/capabilities/session-search.js +2 -1
- package/dist/scripts/session-tests.js +2 -0
- package/dist/src/index.js +1 -1
- package/package.json +1 -1
- package/ts/capabilities/session/transport.ts +22 -1
- package/ts/capabilities/session-login.ts +17 -1
- package/ts/capabilities/session-search.ts +2 -1
- package/ts/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -2,171 +2,89 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/Danceiny/gotry/actions/workflows/ci.yml)
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> **身体和灵魂,更多旅行,更少旅游。**
|
|
6
6
|
> *Body and soul — more travel, less tourism.*
|
|
7
7
|
|
|
8
|
-
**GoTry 是「从出发到下一次出发」的 AI 旅行 Agent
|
|
8
|
+
**GoTry 是「从出发到下一次出发」的 AI 旅行 Agent**:你用一句话说想去哪、为什么想出发;它先问清楚你的工作时间和已订资源,再用**数学求解器**给你一份经过验证的行程方案。
|
|
9
9
|
|
|
10
10
|
**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.
|
|
11
11
|
|
|
12
|
-
| | |
|
|
13
|
-
|---|---|
|
|
14
|
-
| **Version** | `v0.0.1-rc.11`(npm **latest 直指本版**,`npx @danceiny/gotry` 即得;[release notes](docs/release-notes.md)) |
|
|
15
|
-
| **Status** | **M3 工程与分发面已就绪,但真实种子用户 evidence 未收口,M3 Exit 仍开放;M4 记忆域由 founder 授权并行推进,不构成 M3 Exit 证明;M5/M6 仅在各自 Entry gate 满足后启动。** M4 Issue #20 的 paired-cohort/active-planning/experience-reflux 证据合同与 synthetic fixture scorer 已接入 run-all §34(合成 N=3 不充当 Exit,真实 `observed_private` N≥5 paired cohort 待积累);18 工具(2026-08-29 +`gotry_session_login`);事务化状态账本(ADR-15,`gotry_async_terminal.v1`:4/4→`succeeded`/ledger `settled`/exit 0,非 4/4→`failed`/ledger `failed`/exit 2,终态复诵零重算)+ 双形态架构冻结(ADR-16:本地+Web 一套账本语义,tenant_id 一等字段);**会话数据面 #21**:字段 fixture scorer、双源合同与 waiting-attach no-spend 已进确定性回归,真实 sf-01..08 尚未验收;**2026-08-29 已知限制清算第一刀**:Z3 WASM race 根治(`z3-shared.ts` 单一实例+会话级互斥,run-all §1 重试止血退役+§30 并发回归闸)、薄壳遗留(`shell/`)物理删除;**2026-08-29 第二批:OTA 扁平化 + 账号授权闸 + 登录产品化**——飞猪 `search-hotel` 接入(酒店实时报价)、OTA 工具面去「主/降级」路由话术、会话检索授权闸(每会话一次 + 拒绝即会话内吊销)、`gotry_session_login` 登录产品化(登录在携程官网完成,gotry 只读票据名零值过手);全栈回归以 `scripts/run-all-tests.sh` 为准 |
|
|
16
|
-
| **Repo** | [github.com/Danceiny/gotry](https://github.com/Danceiny/gotry) · CI: typecheck + 全栈回归(Node 22/24) |
|
|
17
|
-
| **Runtime** | DeepSeek Harness **0.1.2-alpha.1**(vendored 源码 tarball `ts/dsh-runtime/vendor/`,上游 npm 未发版、从 GitHub tag `dsh-v0.1.2-alpha.1` 构建,溯源见 [`ts/dsh-runtime/vendor/README.md`](ts/dsh-runtime/vendor/README.md);[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`) |
|
|
18
|
-
| **License** | **MIT** (2026-08-23 落定,见 [LICENSE](LICENSE)) |
|
|
19
|
-
|
|
20
|
-
|
|
21
12
|
---
|
|
22
13
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
GoTry 把「想去哪」变成「能不能、怎么去」:
|
|
26
|
-
|
|
27
|
-
| 阶段 | AI/Engine | 输什么 |
|
|
28
|
-
|---|---|---|
|
|
29
|
-
| **动机访谈** | LLM | 必问项:工作窗口 / 已订资源 / 出发城市 |
|
|
30
|
-
| **事实抽取** | LLM | 工作窗口生效 + 休假语义识别 |
|
|
31
|
-
| **可行性判定** | **Z3** | 哪些候选目的地**可行**、哪些**不可行**、为什么、**如何最小化改动让它变可行** |
|
|
32
|
-
| **门到门全成本** | 求解器 | 真实飞行时长(含时差)+ 醒来起夜惩罚 + 接驳代价 + 到达精力 % |
|
|
33
|
-
| **证据链** | 渲染层 | 每个数字标 `[骨架:openflights]`、`[实时API:hbcli]`、`[静态包:估算]` |
|
|
34
|
-
|
|
35
|
-
**不像普通 AI 聊天**——LLM 只做理解和解释,**判定与算术是数学求解器**算的。
|
|
36
|
-
|
|
37
|
-
> **Unlike a regular AI chat**, the LLM only translates and explains. **Decisions and arithmetic are computed by a Z3 solver**, not guessed.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## 🚀 快速开始 — Quick start
|
|
42
|
-
|
|
43
|
-
### 一行启动(npm,推荐)
|
|
14
|
+
## 🚀 30 秒上手
|
|
44
15
|
|
|
45
16
|
```bash
|
|
46
|
-
npx @danceiny/gotry web
|
|
17
|
+
npx @danceiny/gotry web
|
|
18
|
+
# 首跑会提示建 .env:LLM_API_KEY=<DeepSeek key 或 OpenAI 兼容 key>
|
|
19
|
+
# → 浏览器打开 http://127.0.0.1:3080,像聊天一样说「我想去大理三天」
|
|
47
20
|
```
|
|
48
21
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
### 源码安装(开发者)
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
git clone https://github.com/Danceiny/gotry
|
|
58
|
-
cd gotry
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
#### A. 装 vendored dsh runtime(一次性,约 1 分钟)
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
cd ts/dsh-runtime
|
|
65
|
-
pnpm install # 装 vendored dsh 0.1.2-alpha.1 + 第三方依赖 (tarball 在 vendor/, 溯源见 vendor/README.md)
|
|
66
|
-
cd ../..
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
> 为什么这一步:dsh runtime 是 vendored 的(`ts/dsh-runtime/`)——
|
|
70
|
-
> 避免 npm 一键分发时把整个 dsh 也打包进去。
|
|
71
|
-
> 之后可以重复使用,无需重装。
|
|
72
|
-
|
|
73
|
-
#### B. 环境前置 — Prerequisites
|
|
74
|
-
|
|
75
|
-
- **Node 22+**(`nvm install 22` 或更高)
|
|
76
|
-
- 一个 LLM API key(默认走 DeepSeek,也支持 OpenAI 兼容协议)
|
|
77
|
-
|
|
78
|
-
#### C. 配 — Configure
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
cp .env.example .env
|
|
82
|
-
# 填 LLM_API_KEY(deepseek: sk-...; 也兼容 OpenAI/Anthropic 兼容协议)
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
#### D. 跑 — Run(仓内入口,开发者)
|
|
86
|
-
|
|
87
|
-
gotry 把 **DeepSeek Harness (dsh) 运行时**作为唯一推荐面——任何自然语言输入在那里面都能跟 GoTry 正常对话(自动调用引擎、追问缺失字段、给出证据链)。
|
|
22
|
+
| 你想要的 | 命令 |
|
|
23
|
+
|---|---|
|
|
24
|
+
| 🖥️ 对话规划(推荐) | `npx @danceiny/gotry web` → :3080 对话界面 |
|
|
25
|
+
| 🤖 脚本/一次性问答 | `npx @danceiny/gotry "我想从深圳休整两天,预算 3000"` |
|
|
26
|
+
| 🛠️ 开发者:仓内运行 | 见下方[源码安装](#-快速开始) |
|
|
88
27
|
|
|
89
|
-
|
|
28
|
+
- 前置:Node 22+;一个 LLM API key。零成本启动——dsh 运行时以 cordis patch 自动挂载,无额外配置。
|
|
29
|
+
- 例外提示:`:3080` 端口被占时先 `kill <PID>`;首启 6–15 秒属正常冷启动;异常退出会留证据到 `gotry-state/incidents.jsonl`(不静默)。
|
|
90
30
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
| **① dsh Web 对话框**(推荐) | `./gotry web` | 第一天上手;持续多轮规划;想看推理过程可视化 | `http://127.0.0.1:3080` 浏览器界面;带 GoTry 人格的对话框 |
|
|
94
|
-
| **② headless 一次性问答** | `./gotry "一句完整任务..."` | 写脚本、CI 自动化、定向 LLM 调试 | stdout 输出 markdown 回答 |
|
|
95
|
-
| **③ help** | `./gotry help` | 不知道用法 | 三行帮助 |
|
|
31
|
+
<details>
|
|
32
|
+
<summary>🛠️ 开发者:源码安装(仓内运行)</summary>
|
|
96
33
|
|
|
97
34
|
```bash
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
# 调试/自动化:直接一问一答,无浏览器
|
|
103
|
-
./gotry "我想从深圳休整两天,预算 3000"
|
|
104
|
-
# → stdout 拿到引擎判定 + 证据链 + 候选 gate
|
|
105
|
-
|
|
106
|
-
# 不知道用法
|
|
107
|
-
./gotry help
|
|
35
|
+
git clone https://github.com/Danceiny/gotry && cd gotry
|
|
36
|
+
cd ts/dsh-runtime && pnpm install && cd ../.. # ① vendored dsh 0.1.2-alpha.1(一次性)
|
|
37
|
+
cp .env.example .env # ② 填 LLM_API_KEY
|
|
38
|
+
./gotry web # ③ 仓内入口,同 npm 形态
|
|
108
39
|
```
|
|
109
40
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
41
|
+
| 入口 | 命令 | 什么时候用 |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| dsh Web 对话(推荐) | `./gotry web` | 持续多轮规划,看推理可视化 → :3080 |
|
|
44
|
+
| headless 一问一答 | `./gotry "一句任务"` | 脚本 / CI / 定向调试 → stdout |
|
|
45
|
+
| help | `./gotry help` | 三行帮助 |
|
|
115
46
|
|
|
116
|
-
|
|
47
|
+
为什么源码模式要先装 runtime:dsh 以 vendored tarball 进 git(`ts/dsh-runtime/`),npm 一键分发不打包它;源码检出读 `.ts` 源码,装完一次重复可用。
|
|
117
48
|
|
|
118
|
-
|
|
49
|
+
</details>
|
|
119
50
|
|
|
120
|
-
|
|
51
|
+
---
|
|
121
52
|
|
|
122
|
-
|
|
53
|
+
## ✨ 它做什么 — What it does
|
|
123
54
|
|
|
124
|
-
|
|
55
|
+
GoTry 把「想去哪」变成「能不能、怎么去」:
|
|
125
56
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
57
|
+
| 阶段 | 由谁做 | 给你什么 |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| **动机访谈** | LLM | 必问项:工作窗口 / 已订资源 / 出发城市 |
|
|
60
|
+
| **事实抽取** | LLM | 工作窗口生效 + 休假语义识别 |
|
|
61
|
+
| **可行性判定** | **Z3 求解器** | 哪些候选可行、哪些不可行、为什么、**最小改动让它可行** |
|
|
62
|
+
| **门到门全成本** | 求解器 | 真实飞行时长(含时差)+ 醒来起夜惩罚 + 接驳代价 + 到达精力 % |
|
|
63
|
+
| **证据链** | 渲染层 | 每个数字带标签:`[骨架:openflights]` / `[实时API:flyai]` / `[静态包:估算]` |
|
|
129
64
|
|
|
130
|
-
|
|
65
|
+
**不像普通 AI 聊天**——LLM 只做理解和解释,**判定与算术是数学求解器**算的。
|
|
131
66
|
|
|
67
|
+
> **Unlike a regular AI chat**, the LLM only translates and explains. **Decisions and arithmetic are computed by a Z3 solver**, not guessed.
|
|
132
68
|
|
|
133
69
|
---
|
|
134
70
|
|
|
135
71
|
## 🎬 一段对话 — Demo
|
|
136
72
|
|
|
137
|
-
输入 → 引擎判定 →
|
|
73
|
+
输入 → 引擎判定 → 输出(真实输出,milliseconds 保留原味):
|
|
138
74
|
|
|
139
75
|
```
|
|
140
|
-
>
|
|
76
|
+
> 我想去洱海边发呆两三天,上海出发,预算 3000,年假别让我办公。
|
|
141
77
|
|
|
142
78
|
GoTry: 收到。先把约束记下来——
|
|
143
|
-
• 窗口: 2 天(2026 年窗口)
|
|
144
|
-
•
|
|
145
|
-
• 预算: ¥3000 全含
|
|
146
|
-
• 动机: 休整 / [escape_rest: 0.7]
|
|
147
|
-
• 不要求工作窗口(年假)
|
|
148
|
-
• 还没订任何东西
|
|
79
|
+
• 窗口: 2 天(2026 年窗口) • 出发: 上海 • 预算: ¥3000 全含
|
|
80
|
+
• 动机: 休整 / [escape_rest: 0.7] • 还没订任何东西
|
|
149
81
|
|
|
150
82
|
引擎判定:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
★已放入「下一次出发」清单: 需 5 天起,3-5 / 9-11 月最佳。
|
|
156
|
-
|
|
157
|
-
**千岛湖: 可行** (G7315 06:35 出发,bus 接驳,
|
|
158
|
-
¥996,起床 06:35,到达精力 84%,门到门 5h20m,
|
|
159
|
-
有效休整 4.4h)
|
|
160
|
-
**太湖: 可行** (G101 09:00 出发,
|
|
161
|
-
¥716,起床 07:12,到达精力 84%,
|
|
162
|
-
有效休整 4.6h)
|
|
163
|
-
|
|
83
|
+
**大理·洱海: 现在不行** —— 2 天窗口装不下「至少 5 天的洱海休整」。
|
|
84
|
+
放宽方案: 行程延长到 5 天,约 ¥4950。★已放入「下一次出发」清单。
|
|
85
|
+
**千岛湖: 可行** (G7315 06:35 出发,¥996,到达精力 84%,有效休整 4.4h)
|
|
86
|
+
**太湖: 可行** (G101 09:00 出发,¥716,有效休整 4.6h)
|
|
164
87
|
建议: 千岛湖(意象匹配 80%)。
|
|
165
|
-
备选: 太湖(¥716,匹配 60%)。
|
|
166
|
-
|
|
167
|
-
**待你决定**:
|
|
168
|
-
1. 千岛湖还是太湖?(前者更贴意象,后者更省)
|
|
169
|
-
2. 出发班次选 G7315(06:35)还是更晚的?
|
|
170
88
|
|
|
171
89
|
[骨架:openflights] ✓ SZX↔PVG 已校验 [实时API:hbcli] 上海机场在跑
|
|
172
90
|
[静态包:估算] G7315/G7316 价格按 7-8 月淡季估算
|
|
@@ -176,6 +94,39 @@ GoTry: 收到。先把约束记下来——
|
|
|
176
94
|
|
|
177
95
|
---
|
|
178
96
|
|
|
97
|
+
## 🧰 18 个工具 — Tools
|
|
98
|
+
|
|
99
|
+
| 组 | 工具 | 干什么 |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| **实时检索(OTA/官方只读)** | `gotry_flyai_search` | 机票/火车/酒店实时报价(飞猪官方通道;酒店价格为上游打码展示,真实价以 jumpUrl 为准) |
|
|
102
|
+
| | `gotry_session_search` | 在**用户本人登录态**里查携程机票(授权后,只读) |
|
|
103
|
+
| | `gotry_session_login` | 登录引导:自动检测已登录与否,未登录才在用户 Chrome 弹登录入口(**零终端**) |
|
|
104
|
+
| | `gotry_weather_check` | Open-Meteo 预报≤16 天 + 历史气候基线 |
|
|
105
|
+
| | `gotry_flight_verify` | OpenSky ADS-B 航班实时观测(三值) |
|
|
106
|
+
| | `gotry_skeleton_check` | OpenFlights 168 对枢纽通航性(三值) |
|
|
107
|
+
| **库存与目录** | `gotry_hotel_search` | hotel-byte 实时桥,降级静态包(证据标注) |
|
|
108
|
+
| | `gotry_anything_search` | 城市/酒店/地标混合目录(hotel-be Anything) |
|
|
109
|
+
| **判定引擎** | `gotry_feasibility_check` | 门到门真成本可行性(Z3),逐候选判定 |
|
|
110
|
+
| **记忆与触达** | `gotry_motivation_save` | 动机画像落盘(evidence 强制,反幻觉) |
|
|
111
|
+
| | `gotry_wish_pool_add` / `gotry_wish_pool_list` | 「下一次出发」愿望池 + 0..1 条件召回 |
|
|
112
|
+
| | `gotry_companion_save` · `gotry_trip_log` | 同行人档案 / 旅行时间线 |
|
|
113
|
+
| **通用外部** | `gotry_web_search` · `gotry_video_subtitle` · `gotry_github_search` · `gotry_agent_reach` | 网页/字幕/GitHub/全渠道外部信息(经 Agent-Reach) |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 🔐 账号会话:授权与隐私 — Account consent
|
|
118
|
+
|
|
119
|
+
会话检索使用**你本人已登录的 Chrome**读取酒店/机票实时数据,为此立了四条 hard 规则:
|
|
120
|
+
|
|
121
|
+
1. **登录在外部网站完成** —— gotry 从不提供、不代填、不收集任何密码/验证码/cookie 值。它只回答一个布尔问题:"登录票据 cookie 存在吗"(只读**名字**,0 值过手)。
|
|
122
|
+
2. **授权卡,每会话一次** —— 首次动用账号会话会弹运行时审批卡;批准后会话内记住,拒绝即本会话吊销,不再打扰。总闸 `sessionAccess: ask|allow|off` 随时可关。
|
|
123
|
+
3. **物理只读** —— ReadGuard 在网络层中止一切写请求(下单/支付在传输层不可达),agent 永不接触凭证与验证码;遇到验证码立即停,交还给你。
|
|
124
|
+
4. **绝不劫持你的浏览器** —— 检索/登录只开自己的独立标签页,登录页置前台、留在你那;例行动测试永不自动开浏览器窗。
|
|
125
|
+
|
|
126
|
+
> 前置(一次性):日常 Chrome 打开 `chrome://inspect/#remote-debugging` 打开开关(Chrome 144+),并保持 Chrome 在线。未开启时工具返回 `needs-attach` 并给出指引,不消耗执行配额。
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
179
130
|
## 🏛️ 架构 — Architecture
|
|
180
131
|
|
|
181
132
|
```
|
|
@@ -190,26 +141,37 @@ GoTry: 收到。先把约束记下来——
|
|
|
190
141
|
|
|
191
142
|
| 层 | 模块 | 角色 |
|
|
192
143
|
|---|---|---|
|
|
193
|
-
| L2 | `ts/src/index.ts`
|
|
194
|
-
| L3 | `ts/src/unified.ts` · `py/gotry_feasibility
|
|
195
|
-
| L4 | `ts/capabilities/hbcli.ts`
|
|
196
|
-
|
|
|
197
|
-
|
|
198
|
-
> 📖 完整 ADR / 演进阶段 / 债务清单见 [`docs/architecture.md`](docs/architecture.md)。
|
|
144
|
+
| L2 | `ts/src/index.ts`(dsh 插件) | 注册 18 工具,挂时间锚点/记忆 brief 变量;execute 异常隔离 + 授权闸 + 进程护栏 |
|
|
145
|
+
| L3 | `ts/src/unified.ts` · `py/gotry_feasibility/` | 唯一求解入口(候选枚举 + 航班链 Z3) |
|
|
146
|
+
| L4 | `ts/capabilities/hbcli.ts` · `skeleton-check.ts` | 实时库存桥 + OpenFlights 骨架(三值语义) |
|
|
147
|
+
| L5 | loopx 治理面 | objective / gates / evidence / quota |
|
|
199
148
|
|
|
149
|
+
> 📖 完整 ADR / 演进 / 债务清单: [`docs/architecture.md`](docs/architecture.md)
|
|
200
150
|
|
|
201
151
|
---
|
|
202
152
|
|
|
203
|
-
## ⚠️
|
|
153
|
+
## ⚠️ 状态与限制 — Status & limitations
|
|
204
154
|
|
|
205
|
-
|
|
206
|
-
- ✅ **英文面(工程层)已就绪** — 求解确定性输出面(候选/航班链 answer_md、放宽建议、排除理由)i18n catalog 化:`GOTRY_LOCALE=en` 或 `setLocale('en')` 即英文,默认 zh-CN 与金标准逐字节一致(run-all §32:en 零缺键/切换数据不动)。**残余(诚实声明)**:dsh web 界面属宿主、工具结果卡与人格对话面等 M4 校准输入落定后随校准样本补齐——种子市场仍是中国出境(G1)
|
|
207
|
-
- ✅ **机票实时数据已接入** — dated 航班链段可经 FlyAI 官方只读通道取实时票价覆写(`GOTRY_REALTIME_PRICING=1`,证据链 `[实时API:flyai@ts]`,miss/error/打码价一律降级回静态包 `data/flights_2026.json`);静态包由「唯一来源」变为「显式降级」,零 key 可用
|
|
208
|
-
- ✅ **酒店实时报价已接入(OTA 平铺)** — `gotry_flyai_search` kind=hotel 直连飞猪官方 `search-hotel`(2026-08-29 实测:结构化 名称/档级/打码价);未鉴权价格上游打码(如 ¥7xx),工具保 priceRaw 原值不伪装成数字价,真实价以 jumpUrl 酒店页为准;OTA 工具面平铺,无「主链路/降级」路由——按查询取用,证据链逐源标注
|
|
209
|
-
- ✅ **账号登录已产品化(第 18 工具)** — `gotry_session_login`:会话检索遇 `needs-login` 时 agent 直接调它,在你的 Chrome 弹出携程登录页、等你在**携程官网**完成登录——全程无需终端。**登录永远发生在外部网站、不在 gotry 里进行;gotry 永不收集/存储/传输密码、验证码或任何 cookie 值,只读「票据 cookie 是否存在」这一个事实(名称级,0 值过手)**。授权闸 v2:每会话首次调用弹审批卡、会话内记住;拒绝 = 本会话吊销;`sessionAccess: ask|allow|off` 总闸随时可关(session-tests §I/§J + smoke §13 验证)
|
|
210
|
-
- ✅ **Z3 WASM race 已根治** — 三模块各自持 WASM 实例 + 候选求解 `Promise.all` 共 Context 并发是双重根因;现收敛 `ts/src/z3-shared.ts`(单一实例+单一 Context+会话级互斥门),run-all §1 的「重试一次」止血已退役,新增 §30 进程内三形态并发回归闸 ×12(D-17)
|
|
211
|
-
- ✅ **薄壳已删除** — `shell/` 目录与 `./gotry shell` 分支已移除(2026-08-29 清理;dsh web 唯一产品面,旧命令行在 git 历史/rc.6 文档内可考)
|
|
155
|
+
**已就绪(全绿可验)**:
|
|
212
156
|
|
|
157
|
+
- ✅ **Z3 WASM race 已根治**(`z3-shared.ts` 单实例+会话级互斥;run-all §30 并发回归闸)
|
|
158
|
+
- ✅ **实时机票/酒店/会话检索**已接入:FlyAI 官方通道(机/火/酒;`GOTRY_REALTIME_PRICING=1` 可选把实时票价覆写进求解)
|
|
159
|
+
- ✅ **英文面(工程层)**:`GOTRY_LOCALE=en` 一键切换,en 零缺键,金标准行为不变
|
|
160
|
+
- ✅ **账号会话:授权闸 + 登录产品化 + 自动检测**(见上方 [🔐 账号会话](#-账号会话授权与隐私--account-consent))
|
|
161
|
+
- ✅ License MIT;薄壳遗留已删除(dsh web 唯一产品面)
|
|
162
|
+
|
|
163
|
+
**未收口(诚实清单)**:
|
|
164
|
+
|
|
165
|
+
- ⏳ **M3 Exit 未关闭** —— 工程与分发面就绪,但真实种子用户 evidence(50–200 人 cohort)未积累;合成 fixture 只证明合同不证明 business pass
|
|
166
|
+
- ⏳ **中文之外的界面残余** —— dsh web 界面属宿主;工具结果卡与人格对话面的英文校准件挂 M4 校准样本
|
|
167
|
+
- ⏳ **携程酒店/美团会话适配器** —— 机票已通,酒店会话面等登录态实测回填(下一 tick)
|
|
168
|
+
|
|
169
|
+
<details>
|
|
170
|
+
<summary>📖 展开完整状态表(账本/证据合同/里程碑口径)</summary>
|
|
171
|
+
|
|
172
|
+
事务化状态账本(ADR-15,`gotry_async_terminal.v1`:4/4→`succeeded`/ledger `settled`/exit 0,非 4/4→`failed`/`failed`/exit 2,终态复诵零重算);双形态架构冻结(ADR-16:本地+Web 一套账本语义,tenant_id 一等字段);会话数据面 #21 的字段 fixture scorer、双源合同与 waiting-attach no-spend 已进确定性回归,真实 sf-01..08 尚未验收;里程碑口径(2026-08-29):M3 工程与分发面已就绪但真实种子用户 evidence 未收口,M4 由 founder 授权并行推进不构成 M3 Exit 证明,M5/M6 仅在各自 Entry gate 满足后启动——细则见 [`docs/roadmap.md`](docs/roadmap.md) 与 [`docs/architecture.md`](docs/architecture.md)。
|
|
173
|
+
|
|
174
|
+
</details>
|
|
213
175
|
|
|
214
176
|
---
|
|
215
177
|
|
|
@@ -226,7 +188,6 @@ GoTry: 收到。先把约束记下来——
|
|
|
226
188
|
| [`docs/kimi-postmortem.md`](docs/kimi-postmortem.md) | 所有人:真实 AI 旅行规划失败复盘(反面教材) |
|
|
227
189
|
| [`docs/release-notes.md`](docs/release-notes.md) | 历史:每个 tag 的发布闸勾稽 |
|
|
228
190
|
|
|
229
|
-
|
|
230
191
|
---
|
|
231
192
|
|
|
232
193
|
## 🧪 跑测试 — Verify
|
|
@@ -235,11 +196,7 @@ GoTry: 收到。先把约束记下来——
|
|
|
235
196
|
./scripts/run-all-tests.sh
|
|
236
197
|
```
|
|
237
198
|
|
|
238
|
-
全栈一次性绿(纯 TS,无 Python 依赖):engine/journey/unified 金标准 · 对话重放 ·
|
|
239
|
-
异步工单跨进程 · 插件 smoke · hbcli · 进程护栏(含工具异常隔离) · 天气 · 航班 ·
|
|
240
|
-
Anything · probePoi · agent-reach(web/deep/wrapper)· 双路径稳定性 ·
|
|
241
|
-
时间感评测(锚点卡/槽位过期校验/评分器/mock 回放;真模型巡检 `time-eval-tests.ts --real`)·
|
|
242
|
-
记忆域(动机合并守门/效用 sidecar/只读指标投影)· **Z3 并发竞态(§30)· 实时票价桥(§31)· i18n 目录(§32)· M3 cohort 证据合同(§33)· M4 价值证据合同(§34)**。
|
|
199
|
+
全栈一次性绿(纯 TS,无 Python 依赖):engine/journey/unified 金标准 · 对话重放 · 异步工单跨进程 · 插件 smoke · hbcli · 进程护栏(含工具异常隔离)· 天气 · 航班 · Anything · probePoi · agent-reach(web/deep/wrapper)· 双路径稳定性 · 时间感评测(锚点卡/槽位过期校验/评分器/mock 回放;真模型巡检 `time-eval-tests.ts --real`)· 记忆域(动机合并守门/效用 sidecar/只读指标投影)· **Z3 并发竞态(§30)· 实时票价桥(§31)· i18n 目录(§32)· M3 cohort 证据合同(§33)· M4 价值证据合同(§34)**。
|
|
243
200
|
|
|
244
201
|
---
|
|
245
202
|
|
|
@@ -247,21 +204,17 @@ Anything · probePoi · agent-reach(web/deep/wrapper)· 双路径稳定性 ·
|
|
|
247
204
|
|
|
248
205
|
> *PR-based flow: branch off the latest `main`, full suite green, open a Pull Request — `main` never takes direct pushes; merge after review. Full guide: [CONTRIBUTING.md](CONTRIBUTING.md).*
|
|
249
206
|
|
|
250
|
-
标准开源流程:**`main` 不直接推**——从最新 `main` 切出 `feat/ · fix/ · docs/ · chore/` 分支,本地全栈绿后开 Pull Request,CI
|
|
207
|
+
标准开源流程:**`main` 不直接推**——从最新 `main` 切出 `feat/ · fix/ · docs/ · chore/` 分支,本地全栈绿后开 Pull Request,CI(Node 22/24,typecheck + 全部套件)与维护者 review 双绿后 squash 合入。**测试红着不许合。**
|
|
251
208
|
|
|
252
209
|
- 完整贡献指南(环境搭建 · 测试 · 分支与提交约定 · PR 流程): **[CONTRIBUTING.md](CONTRIBUTING.md)**
|
|
253
210
|
- Bug / 功能建议:[issue 模板](.github/ISSUE_TEMPLATE/bug_report.yml)(搜过既有 issue 再提)
|
|
254
211
|
- 行为或架构改动先立 ADR(`docs/architecture.md` §8);多 agent 协作契约见 [`AGENTS.md`](AGENTS.md)
|
|
255
212
|
|
|
256
|
-
单套件快捷命令等测试细节见上面的 [🧪 跑测试 — Verify](#-跑测试--verify)。
|
|
257
|
-
|
|
258
213
|
---
|
|
259
214
|
|
|
260
215
|
## 📜 License
|
|
261
216
|
|
|
262
|
-
**MIT
|
|
263
|
-
|
|
264
|
-
文本见 [LICENSE](LICENSE)。
|
|
217
|
+
**MIT**(2026-08-23 落定)。与上游 dsh(MIT)/ loopx 一致——宽松、可商用、可闭源分叉。文本见 [LICENSE](LICENSE)。
|
|
265
218
|
|
|
266
219
|
---
|
|
267
220
|
|
|
@@ -269,10 +222,10 @@ Anything · probePoi · agent-reach(web/deep/wrapper)· 双路径稳定性 ·
|
|
|
269
222
|
|
|
270
223
|
- **English section summaries** are inline above (italic blockquotes).
|
|
271
224
|
- 本 README 主语言是中文,面向中国出境首发种子用户群。
|
|
272
|
-
- 完整英文版 README 计划在 v0.1.0
|
|
225
|
+
- 完整英文版 README 计划在 v0.1.0 同步。
|
|
273
226
|
|
|
274
227
|
---
|
|
275
228
|
|
|
276
|
-
**Built with**: DeepSeek Harness 0.1.2-alpha.1 (vendored) · Cordis · Z3 (WASM) · loopx (pipx) · hotelbyte-cli · Agent-Reach v1.5.0 (`.venv/`) · OpenFlights · TypeScript
|
|
229
|
+
**Built with**: DeepSeek Harness 0.1.2-alpha.1 (vendored) · Cordis · Z3 (WASM) · loopx (pipx) · hotelbyte-cli · Agent-Reach v1.5.0 (`.venv/`) · OpenFlights · TypeScript
|
|
277
230
|
|
|
278
|
-
**Last verified against `v0.0.1-rc.
|
|
231
|
+
**Last verified against `v0.0.1-rc.13`(已发布,2026-08-29)** — 全栈回归全绿 §1-§34(发布流程见 `scripts/publish-npm.sh`)。
|
package/cordis.gotry-patch.yml
CHANGED
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
登录态,现携程机票):**首次调用**经运行时审批卡向用户请求授权,本会话
|
|
85
85
|
内记住、不再重复弹卡;用户拒绝即本会话吊销——不再请求也不再执行,改走
|
|
86
86
|
其他工具推进;无审批通道(headless)不执行。返回 needs-login→调
|
|
87
|
-
gotry_session_login 产品工具(
|
|
88
|
-
|
|
87
|
+
gotry_session_login 产品工具(先自动检测票据——已登录则直接确认零弹窗;未登录才
|
|
88
|
+
打开登录入口等待其完成,不需要任何终端命令;**登录永远发生在携程官网、不在 gotry
|
|
89
89
|
里进行**——gotry 永不收集/存储/传输密码、验证码或任何 cookie 值,只检查
|
|
90
90
|
"是否已登录"这一个事实;向用户说明这一点),完成前用官方源推进,不反复
|
|
91
91
|
开页探测;返回 challenged→立即停手如实告知,绝不重试
|
|
@@ -87,7 +87,14 @@ export async function openSession(opts = {}) {
|
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
let ownPage = false;
|
|
91
|
+
let page;
|
|
92
|
+
if (opts.newPage) {
|
|
93
|
+
page = await browser.newPage();
|
|
94
|
+
ownPage = true;
|
|
95
|
+
} else {
|
|
96
|
+
page = (await browser.pages())[0] ?? await browser.newPage();
|
|
97
|
+
}
|
|
91
98
|
return {
|
|
92
99
|
ok: true,
|
|
93
100
|
browser,
|
|
@@ -97,6 +104,9 @@ export async function openSession(opts = {}) {
|
|
|
97
104
|
requestCount: ()=>0
|
|
98
105
|
},
|
|
99
106
|
close: async ()=>{
|
|
107
|
+
if (ownPage && (opts.closeOwnPage ?? true)) {
|
|
108
|
+
await page.close().catch(()=>{});
|
|
109
|
+
}
|
|
100
110
|
await (isCdp ? browser.disconnect() : browser.close()).catch(()=>{});
|
|
101
111
|
}
|
|
102
112
|
};
|
|
@@ -57,12 +57,28 @@ export async function sessionLogin(q = {}) {
|
|
|
57
57
|
}
|
|
58
58
|
const evidenceTag = `[会话:${site}-login@${ts}]`;
|
|
59
59
|
try {
|
|
60
|
+
const pre = await pollTicketNames(t.browser, target);
|
|
61
|
+
if (pre.length > 0) {
|
|
62
|
+
await t.close();
|
|
63
|
+
return {
|
|
64
|
+
ok: true,
|
|
65
|
+
via: 'session-login',
|
|
66
|
+
latencyMs: Date.now() - started,
|
|
67
|
+
verdict: 'logged-in',
|
|
68
|
+
site,
|
|
69
|
+
tickets: pre,
|
|
70
|
+
evidence: `${evidenceTag} 自动检测:票据 cookie 已在(先前登录已生效)——[${pre.join(', ')}](只读名字,0 网页交互)`
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const page = await t.browser.newPage();
|
|
74
|
+
await page.bringToFront().catch(()=>{});
|
|
60
75
|
try {
|
|
61
|
-
await
|
|
76
|
+
await page.goto(target.entryUrl, {
|
|
62
77
|
waitUntil: 'domcontentloaded',
|
|
63
78
|
timeout: 30_000
|
|
64
79
|
});
|
|
65
80
|
} catch {}
|
|
81
|
+
console.log(`[session-login] ${target.label} 登录入口已在新标签页置前打开`);
|
|
66
82
|
const waitMs = Math.min(Math.max(q.waitMs ?? 90_000, 0), 300_000);
|
|
67
83
|
const pollMs = Math.min(Math.max(q.pollMs ?? 3_000, 500), 10_000);
|
|
68
84
|
const deadline = Date.now() + waitMs;
|
|
@@ -34,7 +34,8 @@ export async function sessionFlightSearch(q) {
|
|
|
34
34
|
profileDir: q.profileDir,
|
|
35
35
|
headless: q.headless,
|
|
36
36
|
auditPath: q.auditPath,
|
|
37
|
-
mode: q.profileDir ? 'persistent' : 'cdp'
|
|
37
|
+
mode: q.profileDir ? 'persistent' : 'cdp',
|
|
38
|
+
newPage: true
|
|
38
39
|
});
|
|
39
40
|
if (!t.ok) {
|
|
40
41
|
return err(classifyTransportFailure(t.summary, q.profileDir === undefined), t.summary);
|
|
@@ -387,6 +387,8 @@ console.log('H. flyaiSearch hotel(飞猪官方 search-hotel)');
|
|
|
387
387
|
});
|
|
388
388
|
if (lr.verdict === 'needs-attach') {
|
|
389
389
|
assert(lr.ok === false && /chrome:\/\/inspect/.test(lr.error ?? ''), 'live:Chrome 未开调试 → needs-attach + 一次性指引', lr);
|
|
390
|
+
} else if (lr.verdict === 'logged-in') {
|
|
391
|
+
assert(lr.ok === true && (lr.tickets?.length ?? 0) > 0, 'live:已登录自动检测 → logged-in(零弹窗,票据名级)', lr);
|
|
390
392
|
} else {
|
|
391
393
|
assert(lr.ok === true && lr.verdict === 'pending', 'live:attach 成功不交互 → pending(入口已开,等人登录)', lr);
|
|
392
394
|
const evidenceTagRe = /\[会话:ctrip-flight-login@/;
|
package/dist/src/index.js
CHANGED
|
@@ -906,7 +906,7 @@ export function apply(ctx, config) {
|
|
|
906
906
|
}));
|
|
907
907
|
registerGuarded(defineTool({
|
|
908
908
|
name: 'gotry_session_login',
|
|
909
|
-
description: 'Productized login bootstrap for the account session channel (call this when gotry_session_search returns needs-login — the user never needs a terminal). ' + 'OPENS the site login entry in the USER\'S OWN Chrome and waits for the user to finish logging in on the external site. ' + 'GoTry NEVER collects, stores, or transmits credentials: no passwords, no SMS codes, no cookie values — it only checks the boolean fact "already logged in" (reads cookie NAMES only, zero values). ' + 'verdict logged-in (tickets detected) | pending (login tab opened, user not done yet — offer to re-check later) | needs-attach (one-time Chrome remote-debugging switch instructions). ' + 'Evidence [会话:<site>-login@ts].',
|
|
909
|
+
description: 'Productized login bootstrap for the account session channel (call this when gotry_session_search returns needs-login — the user never needs a terminal). ' + 'AUTO-DETECTION FIRST: it reads ticket-cookie NAMES before anything else — if the user already logged in (on the external site) it confirms instantly WITHOUT opening any page. ' + 'OPENS the site login entry in the USER\'S OWN Chrome and waits for the user to finish logging in on the external site. ' + 'GoTry NEVER collects, stores, or transmits credentials: no passwords, no SMS codes, no cookie values — it only checks the boolean fact "already logged in" (reads cookie NAMES only, zero values). ' + 'verdict logged-in (tickets detected) | pending (login tab opened, user not done yet — offer to re-check later) | needs-attach (one-time Chrome remote-debugging switch instructions). ' + 'Evidence [会话:<site>-login@ts].',
|
|
910
910
|
parameters: {
|
|
911
911
|
query: {
|
|
912
912
|
type: 'json',
|
package/package.json
CHANGED
|
@@ -57,6 +57,14 @@ export interface TransportOptions {
|
|
|
57
57
|
* 凭证流的中间(隐私+可靠性双输)。该形态下不发起任何检索导航、不落审计。
|
|
58
58
|
*/
|
|
59
59
|
guard?: boolean
|
|
60
|
+
/**
|
|
61
|
+
* 开**自己的新标签页**(默认 false=沿用既有首页——那是用户的页面!)。
|
|
62
|
+
* 人机共治纪律(2026-08-29 founder:「我根本就看不到登录页面」):登录与检索一律
|
|
63
|
+
* newPage 开自己的页,绝不劫持用户已有标签页;closeOwnPage 控制收尾是否关掉自己开的页。
|
|
64
|
+
*/
|
|
65
|
+
newPage?: boolean
|
|
66
|
+
/** newPage:true 时,close() 是否连自己开的标签页一起关(默认 true;登录引导保持 false——把登录页留给用户) */
|
|
67
|
+
closeOwnPage?: boolean
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
function devtoolsWsEndpoint(): { ws: string } | { err: string } {
|
|
@@ -111,14 +119,27 @@ export async function openSession(opts: TransportOptions = {}): Promise<SessionT
|
|
|
111
119
|
return { ok: false, summary: `read-guard attach failed: ${e instanceof Error ? e.message.split('\n')[0] : String(e)}` }
|
|
112
120
|
}
|
|
113
121
|
}
|
|
114
|
-
|
|
122
|
+
// 标签页纪律:ownPage=自己开的新页(newPage:true)——用它,收尾按 closeOwnPage 关;
|
|
123
|
+
// 否则沿用既有首页(仅 persistent 兼容形态;cdp 检索/登录一律 newPage)
|
|
124
|
+
let ownPage: boolean = false
|
|
125
|
+
let page
|
|
126
|
+
if (opts.newPage) {
|
|
127
|
+
page = await browser.newPage()
|
|
128
|
+
ownPage = true
|
|
129
|
+
} else {
|
|
130
|
+
page = (await browser.pages())[0] ?? await browser.newPage()
|
|
131
|
+
}
|
|
115
132
|
return {
|
|
116
133
|
ok: true,
|
|
117
134
|
browser,
|
|
118
135
|
page,
|
|
119
136
|
guard: guard ?? { blockedCount: () => 0, requestCount: () => 0 },
|
|
120
137
|
close: async () => {
|
|
138
|
+
// 自己开的标签页按 closeOwnPage 收尾(登录引导保持 false——登录页留给用户);
|
|
121
139
|
// cdp:只断开连接,绝不关用户浏览器;persistent:关自己拉起的实例
|
|
140
|
+
if (ownPage && (opts.closeOwnPage ?? true)) {
|
|
141
|
+
await (page as { close(): Promise<void> }).close().catch(() => { /* ignore */ })
|
|
142
|
+
}
|
|
122
143
|
await (isCdp ? browser.disconnect() : browser.close()).catch(() => { /* ignore */ })
|
|
123
144
|
},
|
|
124
145
|
}
|
|
@@ -84,6 +84,8 @@ export async function sessionLogin(q: SessionLoginQuery = {}): Promise<SessionLo
|
|
|
84
84
|
if (!target) {
|
|
85
85
|
return err(site, 'error', `未知站点 ${site}(可选 ${Object.keys(LOGIN_TARGETS).join('/')})`, started, ts)
|
|
86
86
|
}
|
|
87
|
+
// 人机共治纪律:开自己的新标签页并置前台——用户必须看见登录页(2026-08-29 founder:
|
|
88
|
+
// 「我根本就看不到登录页面」,此前误劫持用户既有标签页);closeOwnPage=false 把登录页留给用户
|
|
87
89
|
const t = await openSession({ mode: 'cdp', guard: false })
|
|
88
90
|
if (!t.ok) {
|
|
89
91
|
const needsAttach = /chrome:\/\/inspect|DevToolsActivePort|cdp attach 失败/.test(t.summary)
|
|
@@ -98,11 +100,25 @@ export async function sessionLogin(q: SessionLoginQuery = {}): Promise<SessionLo
|
|
|
98
100
|
}
|
|
99
101
|
const evidenceTag = `[会话:${site}-login@${ts}]`
|
|
100
102
|
try {
|
|
103
|
+
// 自动检测优先(2026-08-29 founder「UI 里有自动检测吗」):先只读票据名——
|
|
104
|
+
// 已登录则**零弹窗**直接确认,不打开任何页面;登录状态由用户在携程官网自然留存
|
|
105
|
+
const pre = await pollTicketNames(t.browser as unknown as { cookies(): Promise<CookieLike[]> }, target)
|
|
106
|
+
if (pre.length > 0) {
|
|
107
|
+
await t.close()
|
|
108
|
+
return {
|
|
109
|
+
ok: true, via: 'session-login', latencyMs: Date.now() - started, verdict: 'logged-in', site, tickets: pre,
|
|
110
|
+
evidence: `${evidenceTag} 自动检测:票据 cookie 已在(先前登录已生效)——[${pre.join(', ')}](只读名字,0 网页交互)`,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// 未检出 → 开自己的新标签页并置前台(绝不劫持用户既有页面),等待用户在官网完成登录
|
|
114
|
+
const page = await t.browser.newPage()
|
|
115
|
+
await (page as unknown as { bringToFront(): Promise<void> }).bringToFront().catch(() => { /* 某些环境不可置前 */ })
|
|
101
116
|
try {
|
|
102
|
-
await
|
|
117
|
+
await page.goto(target.entryUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 })
|
|
103
118
|
} catch {
|
|
104
119
|
// 站点慢不致命:入口标签已打开,用户手动登录即可
|
|
105
120
|
}
|
|
121
|
+
console.log(`[session-login] ${target.label} 登录入口已在新标签页置前打开`)
|
|
106
122
|
const waitMs = Math.min(Math.max(q.waitMs ?? 90_000, 0), 300_000)
|
|
107
123
|
const pollMs = Math.min(Math.max(q.pollMs ?? 3_000, 500), 10_000)
|
|
108
124
|
const deadline = Date.now() + waitMs
|
|
@@ -74,7 +74,8 @@ export async function sessionFlightSearch(q: SessionFlightQuery): Promise<Sessio
|
|
|
74
74
|
return err('error', `unresolved entry: ${(entry.unresolved ?? []).join('/')} 不在城市码表`)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
// 人机共治纪律:检索一律开自己的新标签页(绝不劫持用户已有页面),用完关自己的页
|
|
78
|
+
const t = await openSession({ profileDir: q.profileDir, headless: q.headless, auditPath: q.auditPath, mode: q.profileDir ? 'persistent' : 'cdp', newPage: true })
|
|
78
79
|
if (!t.ok) {
|
|
79
80
|
// cdp 未开端口或握手失败 → needs-attach(一次性用户动作);persistent 启动失败仍走 error。
|
|
80
81
|
// transport 的“端口未开”在连接前返回,文案不含 `cdp attach 失败`,两种形态都要归入同一用户门禁。
|
package/ts/src/index.ts
CHANGED
|
@@ -736,7 +736,7 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
736
736
|
registerGuarded(defineTool({
|
|
737
737
|
name: 'gotry_session_login',
|
|
738
738
|
description:
|
|
739
|
-
'Productized login bootstrap for the account session channel (call this when gotry_session_search returns needs-login — the user never needs a terminal). '
|
|
739
|
+
'Productized login bootstrap for the account session channel (call this when gotry_session_search returns needs-login — the user never needs a terminal). ' + 'AUTO-DETECTION FIRST: it reads ticket-cookie NAMES before anything else — if the user already logged in (on the external site) it confirms instantly WITHOUT opening any page. '
|
|
740
740
|
+ 'OPENS the site login entry in the USER\'S OWN Chrome and waits for the user to finish logging in on the external site. '
|
|
741
741
|
+ 'GoTry NEVER collects, stores, or transmits credentials: no passwords, no SMS codes, no cookie values — it only checks the boolean fact "already logged in" (reads cookie NAMES only, zero values). '
|
|
742
742
|
+ 'verdict logged-in (tickets detected) | pending (login tab opened, user not done yet — offer to re-check later) | needs-attach (one-time Chrome remote-debugging switch instructions). '
|