magpie-ima-local-auth 0.1.1 → 0.3.0
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/AGENTS.md +24 -23
- package/CHANGELOG.md +15 -0
- package/README.md +12 -9
- package/docs/evaluation.md +95 -55
- package/docs/internals.md +29 -13
- package/index.mjs +42 -0
- package/package.json +1 -1
- package/scripts/import-cdp.mjs +115 -113
- package/src/api.mjs +2 -2
- package/src/context.mjs +13 -5
- package/src/login.mjs +240 -238
- package/src/models.mjs +17 -1
- package/src/tools.mjs +325 -0
package/AGENTS.md
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
# AGENTS.md —— 给维护者的入口
|
|
2
|
-
|
|
3
|
-
这个仓库是 `magpie-plugin-scaffold` 的派生插件。动手前先读:
|
|
4
|
-
|
|
5
|
-
1. `README.md` —— 用户看什么、支持哪些模型、怎么登录。
|
|
6
|
-
2. `docs/internals.md` —— 协议证据、IUA 的必要性、被否掉的方案。
|
|
7
|
-
3. `docs/evaluation.md` —— 反代价值评估与实测数字。
|
|
8
|
-
4. `node scripts/check.mjs` —— 合规定稿检查,退出码必须 0。
|
|
9
|
-
5. `node --test` —— 语义锁(bkn / 模型 / SSE / DSH 上下文过滤)。
|
|
10
|
-
|
|
11
|
-
## 会静默出错的四条
|
|
12
|
-
|
|
13
|
-
| 症状 | 判据 | 出处 |
|
|
14
|
-
|---|---|---|
|
|
15
|
-
| 模型目录退回
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`
|
|
1
|
+
# AGENTS.md —— 给维护者的入口
|
|
2
|
+
|
|
3
|
+
这个仓库是 `magpie-plugin-scaffold` 的派生插件。动手前先读:
|
|
4
|
+
|
|
5
|
+
1. `README.md` —— 用户看什么、支持哪些模型、怎么登录。
|
|
6
|
+
2. `docs/internals.md` —— 协议证据、IUA 的必要性、被否掉的方案。
|
|
7
|
+
3. `docs/evaluation.md` —— 反代价值评估与实测数字。
|
|
8
|
+
4. `node scripts/check.mjs` —— 合规定稿检查,退出码必须 0。
|
|
9
|
+
5. `node --test` —— 语义锁(bkn / 模型 / SSE / DSH 上下文过滤)。
|
|
10
|
+
|
|
11
|
+
## 会静默出错的四条
|
|
12
|
+
|
|
13
|
+
| 症状 | 判据 | 出处 |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| 模型目录退回 V3.2 / HY2.0,Copilot `scene:1` 只有默认模型 | `CLIENT-TYPE=256021` 指纹缺失;`src/api.mjs` 的 `cookieFor()` 默认带 | `docs/internals.md` 第 3 节 |
|
|
16
|
+
| 模型目录退回 V4.1 / Hy3 / Hy4 / GLM(匿名默认),问答 200 但没正文 | `IMA-IUA` 缺失;`defaultIua()` 永远补 | `docs/internals.md` 第 3 节 |
|
|
17
|
+
| 回复答非所问,像是在回答“技能目录” | DSH 把 AGENTS/技能目录作为 user 消息追加;`isContextMessage()` 必须把它们从问题/历史里滤掉 | `src/chat.mjs`、`docs/internals.md` |
|
|
18
|
+
| 流式客户端报 `Stream ended without finish_reason` | `finish()` 必须先发带 `finish_reason:"stop"` 的帧,再置 `closed`;`frame()` 不能提前 return | `src/chat.mjs` |
|
|
19
|
+
| 登录后模型 0 个 / 401 | 用 `importLocalLogin()` 的种子或 profile;`provider.models` 调用 `ensureFresh` 后续期 | `src/login.mjs`、`src/api.mjs` |
|
|
20
|
+
|
|
21
|
+
## 发版
|
|
22
|
+
|
|
23
|
+
`scripts/release.mjs`(预演 → `--yes`),或按 scaffold 的 `UPDATING.md` 七步走。
|
|
24
|
+
`git push` 只是第 4 步;npm publish、tag + GitHub Release、四条验证一个都不能少。
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# 更新记录
|
|
2
2
|
|
|
3
|
+
## 0.3.0 — 2026-10-28
|
|
4
|
+
|
|
5
|
+
- **工具调用**:新增 `src/tools.mjs` 文本工具协议。把 OpenAI tools 写成提示,解析模型输出
|
|
6
|
+
`{"tool_calls":[...]}`,转成 OpenAI `tool_calls`;支持 `role:"tool"` 结果回灌、流式/非流式;
|
|
7
|
+
模型条目声明 `toolcall: true`。实测 `task_plan` / `subagent_spawn` 5/5,DSH `write` 端到端成功。
|
|
8
|
+
- 工具模式每个请求用全新 ima session + 完整历史,避免单问 session 丢工具上下文。
|
|
9
|
+
- README / docs 修正:ima 不是裸 LLM,但正常工具契约可用;sovereign 破甲会触发注入检测,不要用。
|
|
10
|
+
|
|
11
|
+
## 0.2.0 — 2026-10-28
|
|
12
|
+
|
|
13
|
+
- **修复客户端指纹**:`x-ima-cookie` 的 `CLIENT-TYPE` 改为 ima 2.6.15 实际值 `256021`。没有它,服务端静默退回旧目录(DeepSeek V3.2 / HY 2.0,Copilot 只有默认模型);有了它,免费目录变为 **DeepSeek-V4.1-Flash / Hy3 / Hy4 preview / GLM-5.3-Flash(各带 Think 变体)**,Copilot `scene:1` 也能读到完整积分目录。
|
|
14
|
+
- 静态兜底模型同步为 V4.1-Flash / Hy3 / Hy4 preview / GLM-5.3-Flash。
|
|
15
|
+
- `scripts/import-cdp.mjs` 写入 `clientType`;`IMA_CLIENT_TYPE` 可覆盖指纹。
|
|
16
|
+
- README / docs 更正“V4.1 标签实际是 V3.2”的错误归因:那是旧 `CLIENT-TYPE` 造成的降级。
|
|
17
|
+
|
|
3
18
|
## 0.1.1 — 2026-10-28
|
|
4
19
|
|
|
5
20
|
- 兼容 ima 客户端 UI 新版的 `STRUCTURED_BLOCK` 流事件(`Data.text_message` 正文 / `Data.thinking_message` 思考),与旧版 `MESSAGE` / `THINKING` 同时支持。
|
package/README.md
CHANGED
|
@@ -28,16 +28,19 @@
|
|
|
28
28
|
|
|
29
29
|
| 发行商 | 代表模型 | 思考 | 计费 |
|
|
30
30
|
|---|---|---|---|
|
|
31
|
-
| DeepSeek | `deepseek-
|
|
32
|
-
|
|
|
33
|
-
| Tencent | `
|
|
34
|
-
|
|
|
31
|
+
| DeepSeek | `deepseek-v4.1-flash` | 客户端可切快速/深度 | 免费(知识库问答) |
|
|
32
|
+
| Tencent | `hy3` | 同上 | 免费(知识库问答) |
|
|
33
|
+
| Tencent | `hy4-preview` | 同上 | 免费(知识库问答) |
|
|
34
|
+
| 智谱 | `glm-5.3-flash` | 同上 | 免费(知识库问答) |
|
|
35
35
|
|
|
36
|
-
>
|
|
36
|
+
> 每个基础模型在 ima 目录里还带一个深度思考变体(`deepseek-v4.1-flash-think` 等);
|
|
37
|
+
> 插件会从 `sub_model_infos` 自动生成。真实目录由 `provider.models` 在登录后整份替换;
|
|
37
38
|
> 装好以后 `magpie plugin list` / 模型选择器里看到的才是账号当前的全部。
|
|
38
39
|
|
|
39
|
-
**Copilot 积分模型默认不列。**
|
|
40
|
-
|
|
40
|
+
**Copilot 积分模型默认不列。** 用 `CLIENT-TYPE=256021` 的客户端指纹可以读到完整 Copilot
|
|
41
|
+
目录(Hy3 ×0.2、Hy4 preview ×0.9、DeepSeek-V4.1-Flash ×0.4 峰时、MiMo / GLM / MiniMax / Kimi…),
|
|
42
|
+
但 Copilot 是 ima 的云端 agent(`robot_type=15`),不是模型通道;本插件按“不做云端 agent”的
|
|
43
|
+
定位不接它。免费目录已经包含 V4.1-Flash / Hy3 / Hy4 / GLM-5.3,不需要为了这些模型开 Copilot。
|
|
41
44
|
|
|
42
45
|
---
|
|
43
46
|
|
|
@@ -93,10 +96,10 @@ magpie plugin list
|
|
|
93
96
|
不用。登录导入之后,magpie 用 refresh token 续期;客户端只在导入那一下需要存在。
|
|
94
97
|
|
|
95
98
|
**Q:为什么没有 Copilot 的模型?**
|
|
96
|
-
Copilot 是 ima 的云端 agent(`robot_type=15
|
|
99
|
+
Copilot 是 ima 的云端 agent(`robot_type=15`),不是模型通道。它的 V4.1 / Hy3 / Hy4 / GLM / MiMo / MiniMax / Kimi 目录确实存在、也支持流式思考;插件按“模型供应商”定位,不把 agent 包装成模型。
|
|
97
100
|
|
|
98
101
|
**Q:支持工具调用 / 图片吗?**
|
|
99
|
-
|
|
102
|
+
**工具调用支持**:ima 的问答接口没有原生 tools 字段,插件用文本工具协议模拟——把调用方的工具表写进问题,模型输出 `{"tool_calls":[...]}`,插件再转成 OpenAI 的 `tool_calls`;工具结果会作为 `role:"tool"` 回灌。已用 `task_plan` / `subagent_spawn` 和 DSH 的 `todo_write` / `write` 实测。图片**不支持**(`attachment: false`)。
|
|
100
103
|
|
|
101
104
|
**Q:上下文窗口是多少?**
|
|
102
105
|
ima 的模型目录不下发窗口大小。插件把 `limit.context` 留 0,让 magpie 用它自己的模型库;不写一个猜的数字。
|
package/docs/evaluation.md
CHANGED
|
@@ -7,28 +7,69 @@
|
|
|
7
7
|
|
|
8
8
|
| 反代对象 | 价值 | 判定 |
|
|
9
9
|
|---|---|---|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
10
|
+
| **免费模型**(DeepSeek-V4.1-Flash / Hy3 / Hy4 preview / GLM-5.3-Flash + 4 个 Think 变体) | **高** | 4 个基础模型 + 4 个思考变体、不扣算力、支持流式;质量已接近/覆盖 CodeBuddy 免费 HY3 这一档 |
|
|
11
|
+
| **Copilot 积分模型**(Hy3 / Hy4 / V4.1 / MiMo / GLM / MiniMax / Kimi…) | **模型能力高,但本插件不接** | Copilot 是 ima 的云端 agent(`robot_type=15` + `command_info.type=2000`),正是 today 式结果的来源;即使能拿到完整目录也默认不列 |
|
|
12
12
|
| 知识库文件 / 文档管理 | 低(本次不做) | 是 ima 的知识库业务,不是模型;对 magpie 供应商没有直接价值 |
|
|
13
|
-
| 图片生成 / 播客等 | 低(本次不做) | 与 magpie 的 chat
|
|
13
|
+
| 图片生成 / 播客等 | 低(本次不做) | 与 magpie 的 chat 供应商无关 |
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
**一句话:免费模型这一层的价值是真实的(V4.1-Flash / Hy3 / Hy4 / GLM-5.3 免费);
|
|
16
|
+
Copilot 积分模型能力更强,但它是云端 agent,按“不能是云端 agent”的约束不接。**
|
|
17
|
+
|
|
18
|
+
## 关键发现:`CLIENT-TYPE=256021` 是指纹钥匙
|
|
19
|
+
|
|
20
|
+
同一账号、同一 token,只改 `x-ima-cookie` 里的 `CLIENT-TYPE`,`model_manage/get_models`
|
|
21
|
+
返回的目录完全不同:
|
|
22
|
+
|
|
23
|
+
| `CLIENT-TYPE` | `{}`(免费目录) | `{"scene":1}`(Copilot 目录) |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `windows` | DeepSeek V3.2 / V3.2 Think / Tencent HY 2.0 / HY 2.0 Think | 只有 `默认模型 ×1.0` |
|
|
26
|
+
| **`256021`**(客户端实际值) | **DeepSeek-V4.1-Flash / Hy3 / Hy4 preview / GLM-5.3-Flash** | **完整:Hy3 ×0.2、Hy4 preview ×0.9、DeepSeek-V4.1-Flash ×0.4 峰时、Xiaomi MiMo、GLM-5.3、MiniMax-M3、Kimi…共 12 个** |
|
|
27
|
+
|
|
28
|
+
这正对应“像超级麦吉要组织指纹 key”的猜测:ima 的客户端类型/指纹就是 `CLIENT-TYPE=256021`。
|
|
29
|
+
没有它,服务端不报错,只会退回旧目录,Copilot 也只给默认模型——这就是之前
|
|
30
|
+
「本机 Copilot 暂不支持 / 模型只有 V3.2」现象的根因。
|
|
31
|
+
|
|
32
|
+
> 2026-10-28 从 ima 2.6.15 客户端真实请求头抓包得到;不同客户端版本可能变化,
|
|
33
|
+
> 可用 `IMA_CLIENT_TYPE` 覆盖。
|
|
16
34
|
|
|
17
35
|
## 实测证据
|
|
18
36
|
|
|
19
|
-
### 免费模型目录(`POST /cgi-bin/model_manage/get_models`,body `{}`)
|
|
37
|
+
### 免费模型目录(`POST /cgi-bin/model_manage/get_models`,body `{}`,`CLIENT-TYPE=256021`)
|
|
20
38
|
|
|
21
39
|
| model_type | model_id | 显示名 | 倍率字段 |
|
|
22
40
|
|---|---|---|---|
|
|
23
|
-
| 3 | official_3 | DeepSeek
|
|
24
|
-
| 1 | official_1 | DeepSeek
|
|
25
|
-
| 0 | official_0 |
|
|
26
|
-
| 2 | official_2 |
|
|
41
|
+
| 3 | official_3 | DeepSeek-V4.1-Flash | 空 |
|
|
42
|
+
| 1 | official_1 | DeepSeek-V4.1-Flash Think | 空 |
|
|
43
|
+
| 0 | official_0 | Hy3 | 空 |
|
|
44
|
+
| 2 | official_2 | Hy3 Think | 空 |
|
|
45
|
+
| 1001 | official_1001 | Hy4 preview | 空 |
|
|
46
|
+
| 1002 | official_1002 | Hy4 preview Think | 空 |
|
|
47
|
+
| 3000 | official_3000 | GLM-5.3-Flash | 空 |
|
|
48
|
+
| 3001 | official_3001 | GLM-5.3-Flash Think | 空 |
|
|
49
|
+
|
|
50
|
+
`model_token_copywriting` 为空 = 不扣算力。实测问答后 `token_manager/get_balance`
|
|
51
|
+
仍为 500。
|
|
27
52
|
|
|
28
|
-
|
|
29
|
-
`token_manager/get_balance` 仍为 500,说明免费不是“暂时没扣”。
|
|
53
|
+
### Copilot 目录(`{"scene":1}`,`CLIENT-TYPE=256021`)
|
|
30
54
|
|
|
31
|
-
|
|
55
|
+
`自动选择最优模型 ×1.0`、`Hy3 ×0.2`、`Hy4 preview ×0.9`、`DeepSeek-V4.1-Flash ×0.4 峰时`、
|
|
56
|
+
`Xiaomi MiMo-V2.6-Flash ×0.2`、`Xiaomi MiMo-V2.6-Pro ×0.6`、`GLM-5.3-Flash ×0.2`、
|
|
57
|
+
`GLM-5.3 ×2.2`、`MiniMax-M3.1-Flash ×0.2`、`MiniMax-M3 ×0.6`、
|
|
58
|
+
`Kimi-K2.8-Preview ×1.9`、`Kimi-K3.1-Pro ×3.8`。
|
|
59
|
+
|
|
60
|
+
Copilot 的实际请求(抓包):
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
POST /cgi-bin/assistant/qa
|
|
64
|
+
{"robot_type":15,"command_info":{"type":2000,"copilot_qa_info":{}},
|
|
65
|
+
"model_info":{"model_id":"official_paid_ep-i2azx8ko","model_type":110000,"enable_enhancement":false}}
|
|
66
|
+
→ SSE STRUCTURED_BLOCK(blockThinking / text_message)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
DeepSeek-V4.1-Flash 在 Copilot 里是真实模型(`official_paid_ep-i2azx8ko` / type 110000),
|
|
70
|
+
`STRUCTURED_BLOCK` 里能看到流式思考;但它始终是 Copilot agent。
|
|
71
|
+
|
|
72
|
+
### 问答与流式
|
|
32
73
|
|
|
33
74
|
```
|
|
34
75
|
POST /cgi-bin/session_logic/init_session
|
|
@@ -38,12 +79,14 @@ POST /cgi-bin/session_logic/init_session
|
|
|
38
79
|
POST /cgi-bin/assistant/qa (SSE)
|
|
39
80
|
{"session_id":"…","robot_type":10000,"question":"…","question_type":2,
|
|
40
81
|
"command_info":{"question_info":{}},"model_info":{"model_type":3,"model_id":"official_3"}}
|
|
41
|
-
→ MESSAGE {"Text":"
|
|
82
|
+
→ MESSAGE {"Text":"…"} / STRUCTURED_BLOCK {"Data":{"text_message":{"Text":"…"}}}
|
|
83
|
+
→ COMPLETED {"Code":0}
|
|
42
84
|
```
|
|
43
85
|
|
|
44
86
|
- 多轮:同一 session 第一问“记住 7391”、第二问“刚才的数字”返回 7391。
|
|
45
|
-
-
|
|
46
|
-
-
|
|
87
|
+
- 长回答:多个增量事件拼出完整 1..20。
|
|
88
|
+
- 思考:`THINKING {"Message":"…","Status":1}` / `STRUCTURED_BLOCK.blockThinking` 增量;
|
|
89
|
+
最后一条 `Status:2` 是结束标记。
|
|
47
90
|
- `SUGGEST_QUESTION` 是建议列表,不是答案。
|
|
48
91
|
|
|
49
92
|
### 登录态
|
|
@@ -53,44 +96,40 @@ profile 的 `tencent.wxlogin.account_secret_encrypted`(DPAPI)。插件读后
|
|
|
53
96
|
不开 CDP、不要求粘贴 cookie。读到的 `token` 约 2 小时,`refresh_token` 约一年;
|
|
54
97
|
`/auth_login/refresh` 实测可换新 token(返回相对 7200 秒)。
|
|
55
98
|
|
|
56
|
-
|
|
99
|
+
## UI 标签 vs 账号目录(修正)
|
|
57
100
|
|
|
58
|
-
`
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
(`PR=IMA&PP=com.tencent.imawin&PPVN=<版本>&PL=WIN&COVC=<Chromium 版本>&EV=`)
|
|
62
|
-
就按账号目录回答。所以插件永远补 IUA。
|
|
101
|
+
之前用 `CLIENT-TYPE=windows` 抓包时,UI 选 V4.1-Flash 发出的 `official_3` 被账号目录标成
|
|
102
|
+
V3.2;把客户端真实的 `CLIENT-TYPE=256021` 带上后,同一 `official_3` 的目录名是
|
|
103
|
+
**DeepSeek-V4.1-Flash**。所以:
|
|
63
104
|
|
|
64
|
-
|
|
105
|
+
- **UI 的 V4.1-Flash 是真 V4.1**;之前的“背后是 V3.2”是**我们的请求缺客户端指纹**造成的
|
|
106
|
+
服务端降级,不是 UI 造假。
|
|
107
|
+
- Copilot 的 V4.1(`official_paid_ep-i2azx8ko`)也是真 V4.1;两条通道不同,但都真实存在。
|
|
65
108
|
|
|
66
|
-
|
|
67
|
-
`POST /cgi-bin/assistant/qa` 请求是:
|
|
109
|
+
## 工具协议与系统提示词测试(2026-10-28)
|
|
68
110
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
| 快速 | `{"model_type":3,"model_id":"official_3","enable_enhancement":true}` |
|
|
72
|
-
| 深度 | `{"model_type":1,"model_id":"official_1","enable_enhancement":true}` |
|
|
111
|
+
关键修正:ima 的模型不是裸 LLM(有自己的身份/安全包装),但**正常工具契约可以工作**;
|
|
112
|
+
sovereign 破甲反而触发它的注入检测,不要用。
|
|
73
113
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`
|
|
114
|
+
| 测试 | 结果 |
|
|
115
|
+
|---|---|
|
|
116
|
+
| 免费 V4.1 + `task_plan` / `subagent_spawn` 工具表 | **5/5 输出合法裸 JSON `tool_calls`**(非流式);流式同样返回 tool_calls 帧 |
|
|
117
|
+
| Copilot V4.1 + 同一工具表 | 同样输出合法 `tool_calls`(`task_plan` 参数补全了 goal/steps) |
|
|
118
|
+
| DSH headless + `write` 工具 | 模型实际调用 DSH 的 `write`,文件被创建并回复 `DSH-BASH-OK` |
|
|
119
|
+
| 工具结果回灌 | assistant tool_calls + role=tool 的消息被拼回提示,模型输出最终正文 |
|
|
120
|
+
| sovereign 破甲 + 强制改身份 | 免费/Copilot 都识别为注入并拒绝,**不要用破甲** |
|
|
77
121
|
|
|
78
|
-
|
|
79
|
-
|
|
122
|
+
实现:`src/tools.mjs` 把 OpenAI tools 写成提示,解析 `{"tool_calls":[...]}` 转成
|
|
123
|
+
OpenAI tool_calls;`toolcall: true`;流式工具请求先攒后发(工具 JSON 必须完整)。
|
|
124
|
+
工具调用不是 ima 原生能力,是文本协议模拟,但已达到正常 API 的可用形态。
|
|
80
125
|
|
|
81
126
|
## 与 CodeBuddy / 其它免费源的对比
|
|
82
127
|
|
|
83
|
-
腾讯 CodeBuddy(CB)已经免费提供 HY3;本机 ima 账号的免费目录只有 DeepSeek V3.2 / Tencent HY 2.0,
|
|
84
|
-
档位明显更旧。把两者放在一起:
|
|
85
|
-
|
|
86
128
|
| 免费源 | 档位 | 接入成本 | 结论 |
|
|
87
129
|
|---|---|---|---|
|
|
88
|
-
| CodeBuddy 免费 HY3 | HY3
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
92
|
-
**所以“免费”本身不是护城河。** 只有当某个 ima 账号的目录里有别人没有的模型,
|
|
93
|
-
或者需要一个独立于 CB 的备用账号时,这个插件才有超出“技术演示”的价值。
|
|
130
|
+
| CodeBuddy 免费 HY3 | HY3 | 现成插件/账号 | 可作主力免费源 |
|
|
131
|
+
| ima 免费目录(本插件) | V4.1-Flash / Hy3 / Hy4 preview / GLM-5.3-Flash | 本插件 + 本机客户端 | **同档,多模型;有真实价值** |
|
|
132
|
+
| ima Copilot(积分) | V4.1 / Hy3 / Hy4 / MiMo / GLM / MiniMax / Kimi | 需要开 Copilot agent | 能力更高,但 agent 约束下不接 |
|
|
94
133
|
|
|
95
134
|
## 与现有实现的关系
|
|
96
135
|
|
|
@@ -98,26 +137,27 @@ profile 的 `tencent.wxlogin.account_secret_encrypted`(DPAPI)。插件读后
|
|
|
98
137
|
|---|---|---|
|
|
99
138
|
| `magpie-ima-auth`(npm) | 浏览器 cookie → 云端 `assistant/qa` | 登录要手工复制 `x-ima-cookie`;本质是把 ima 的云端 agent 会话包装成 chat(单问、无工具、system prompt 受限) |
|
|
100
139
|
| `opencli-plugin-ima` | 直接 API + WebContents/UI | 主要面向知识库问答;Windows 直接 API 遇到 600001;需要客户端/UI 自动化 |
|
|
101
|
-
| 本插件 | 本机客户端 profile → DPAPI 登录态 →
|
|
140
|
+
| 本插件 | 本机客户端 profile → DPAPI 登录态 → 伪装请求头(含 `CLIENT-TYPE=256021`) | 不粘贴 cookie、运行时不需要 CDP;只走 `robot_type=10000` 的普通问答;模型目录/流式/思考/续期都按模型供应商做 |
|
|
102
141
|
|
|
103
142
|
## 限制(如实写)
|
|
104
143
|
|
|
105
|
-
- **单问 session
|
|
106
|
-
|
|
107
|
-
-
|
|
144
|
+
- **单问 session**:`assistant/qa` 一次只收一个问题,没有 messages 数组;插件用 session
|
|
145
|
+
保持多轮,但 system prompt 只在 session 第一问里发。
|
|
146
|
+
- **工具调用是文本协议模拟**:ima 没有原生 tools 字段;插件把工具表写进提示,模型输出
|
|
147
|
+
`{"tool_calls":[...]}` 后转成 OpenAI `tool_calls`,工具由 DSH 执行。平台升级后需重新验证。
|
|
108
148
|
- **没有 token 计数**:ima 不返回 usage;插件不按字符数编,返回 0。
|
|
109
149
|
- **没有上下文窗口**:模型目录不下发;`limit.context` 留 0,交给 magpie 的模型库。
|
|
110
|
-
-
|
|
150
|
+
- **私有接口 + 指纹**:`CLIENT-TYPE=256021` 是抓包值,客户端升级可能变;可用
|
|
151
|
+
`IMA_CLIENT_TYPE` 覆盖。API 本身也可能随时变。
|
|
111
152
|
- **登录导入平台**:DPAPI 解密目前只做 Windows;macOS 用种子文件 / `IMA_COPILOT_LOGIN_FILE`。
|
|
112
|
-
- **Copilot
|
|
153
|
+
- **Copilot 不进默认目录**:它可用、流式思考也正常,但它是 agent,不是模型通道。
|
|
113
154
|
|
|
114
155
|
## 已完成的验收
|
|
115
156
|
|
|
116
157
|
- `node scripts/check.mjs`:通过 29 · 警告 0 · 失败 0
|
|
117
|
-
- `node --test`:
|
|
118
|
-
- magpie 0.1.1814 安装后 `ima (ima,
|
|
119
|
-
- 网关:`POST /v1/chat/completions`(`ima/deepseek-
|
|
120
|
-
流式返回 role/content/`finish_reason:"stop"
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
`DSH-IMA-OK`。
|
|
158
|
+
- `node --test`:17/17
|
|
159
|
+
- magpie 0.1.1814 安装后 `ima (ima, 8 models) signed in as 001ab…`
|
|
160
|
+
- 网关:`POST /v1/chat/completions`(`ima/deepseek-v4.1-flash`)返回 `GATEWAY-V41`;
|
|
161
|
+
流式返回 role/content/`finish_reason:"stop"`;思考模型返回 `reasoning_content`。
|
|
162
|
+
- DSH headless(`dsh --profile headless` + patch,模型 `ima/hy3` 或 `ima/deepseek-v4.1-flash`)
|
|
163
|
+
返回 `DSH-IMA-OK`。
|
package/docs/internals.md
CHANGED
|
@@ -42,7 +42,7 @@ ima 的 token 有两份:
|
|
|
42
42
|
实测(2026-10-28,ima 2.6.15.5280 / Chromium 150.0.7871.5469):
|
|
43
43
|
|
|
44
44
|
```
|
|
45
|
-
x-ima-cookie: PLATFORM=H5; CLIENT-TYPE=
|
|
45
|
+
x-ima-cookie: PLATFORM=H5; CLIENT-TYPE=256021; WEB-VERSION=5.16.12;
|
|
46
46
|
IMA-GUID=...; IMA-UID=...; IMA-TOKEN=...; IMA-REFRESH-TOKEN=...;
|
|
47
47
|
UID-TYPE=2; TOKEN-TYPE=14; IMA-IUA=PR=IMA&PP=com.tencent.imawin&PPVN=...
|
|
48
48
|
from_browser_ima: 1
|
|
@@ -50,7 +50,12 @@ extension_version: 5.16.12
|
|
|
50
50
|
x-ima-bkn: djb2(IMA-TOKEN) & 0x7fffffff
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
**`
|
|
53
|
+
**`CLIENT-TYPE=256021` 是指纹钥匙。** 它是 ima 2.6.15 客户端抓包得到的客户端类型;
|
|
54
|
+
用它 `model_manage/get_models` 才会返回账号当前目录(V4.1-Flash / Hy3 / Hy4 / GLM-5.3),
|
|
55
|
+
`{"scene":1}` 才会返回完整 Copilot 目录。用 `windows` 会静默退回旧目录
|
|
56
|
+
(V3.2 / HY2.0,Copilot 只有默认模型)。可用 `IMA_CLIENT_TYPE` 覆盖。
|
|
57
|
+
|
|
58
|
+
**`IMA-IUA` 也关键。** 少了它,服务端不会报错,只会把整套请求当成匿名:
|
|
54
59
|
`model_manage/get_models` 返回默认目录(DeepSeek-V4.1-Flash / Hy3 / Hy4 / GLM),
|
|
55
60
|
`assistant/qa` 返回 200 但没有 `MESSAGE` 正文。实测只要 IUA 以
|
|
56
61
|
`PR=IMA&PP=com.tencent.imawin&PPVN=<版本>&PL=WIN&COVC=<Chromium 版本>&EV=` 的形式存在,
|
|
@@ -82,14 +87,23 @@ HEARTBEAT
|
|
|
82
87
|
|
|
83
88
|
| model_type | model_id | 名字 | model_token_copywriting |
|
|
84
89
|
|---|---|---|---|
|
|
85
|
-
| 3 | official_3 | DeepSeek
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
90
|
+
| 3 | official_3 | DeepSeek-V4.1-Flash | 空 |
|
|
91
|
+
| 0 | official_0 | Hy3 | 空 |
|
|
92
|
+
| 1001 | official_1001 | Hy4 preview | 空 |
|
|
93
|
+
| 3000 | official_3000 | GLM-5.3-Flash | 空 |
|
|
89
94
|
|
|
90
95
|
`model_token_copywriting` 为空 = 不扣算力,插件标 `free: true`;`×1.0` 之类是积分模型,
|
|
91
|
-
插件标 `rate
|
|
92
|
-
|
|
96
|
+
插件标 `rate`。`CLIENT-TYPE=256021` 下 `scene:1` 返回完整 Copilot 目录(12 个,含
|
|
97
|
+
V4.1-Flash `official_paid_ep-i2azx8ko`);但 Copilot 走 `robot_type=15`,是 ima 的云端
|
|
98
|
+
agent,所以默认不列。
|
|
99
|
+
|
|
100
|
+
### 5.1 工具调用协议
|
|
101
|
+
|
|
102
|
+
ima 没有 OpenAI 的 `tools` 字段。`src/tools.mjs` 把工具表写进问题,要求模型输出
|
|
103
|
+
`{"tool_calls":[{"name":"...","arguments":{...}}]}`;插件解析后转成 OpenAI `tool_calls`。
|
|
104
|
+
工具结果(`role:"tool"`)会被拼回下一次问题。已实测 `task_plan` / `subagent_spawn` 5/5、
|
|
105
|
+
DSH 的 `write` 端到端成功。sovereign 破甲不要用——它反而触发 ima 的注入检测,正常工具契约
|
|
106
|
+
就够了。工具模式每个请求开新 ima session,避免单问 session 丢工具上下文。
|
|
93
107
|
|
|
94
108
|
## 6. 被否掉的方案
|
|
95
109
|
|
|
@@ -99,16 +113,18 @@ HEARTBEAT
|
|
|
99
113
|
实例是否拿到登录态不稳定;每次使用还要拉起/重启客户端。不用。
|
|
100
114
|
- **扫描客户端进程内存**:能找到字符串常量,但 token 不在可检索的明文里;且需要
|
|
101
115
|
ReadProcessMemory 权限,跨版本极脆。不用。
|
|
102
|
-
- **Copilot
|
|
103
|
-
|
|
116
|
+
- **Copilot 积分模型**:`CLIENT-TYPE=256021` 下已确认可用(V4.1-Flash / Hy3 / Hy4 / MiMo /
|
|
117
|
+
GLM / MiniMax / Kimi,SSE `STRUCTURED_BLOCK` 流式思考)。但它是 agent 通道
|
|
118
|
+
(`robot_type=15` + `command_info.type=2000`,today 式结果),按当前约束默认不接。
|
|
104
119
|
|
|
105
120
|
## 7. 已验证
|
|
106
121
|
|
|
107
122
|
2026-10-28,本机 ima 2.6.15.5280:
|
|
108
123
|
|
|
109
|
-
- 从 profile 导入登录态 → `model_manage/get_models` 返回
|
|
110
|
-
-
|
|
111
|
-
- `
|
|
124
|
+
- 从 profile 导入登录态 → `CLIENT-TYPE=256021` 下 `model_manage/get_models` 返回
|
|
125
|
+
V4.1-Flash / Hy3 / Hy4 preview / GLM-5.3-Flash 四个免费模型
|
|
126
|
+
- `assistant/qa`(robot 10000, model_type=3)返回 `V41-OK`
|
|
127
|
+
- `THINKING` / `STRUCTURED_BLOCK.blockThinking` 进 `reasoning_content`;`COMPLETED Code 0` 正常结束
|
|
112
128
|
- `token_manager/get_balance` 返回算力余额
|
|
113
129
|
- `auth.refresh` 成功换到新 access token(`token_valid_time` 为相对 7200 秒)
|
|
114
130
|
- 插件 factory 的 loader 流式/非流式都返回 200
|
package/index.mjs
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
transcript,
|
|
34
34
|
} from "./src/chat.mjs"
|
|
35
35
|
import { buildModels } from "./src/models.mjs"
|
|
36
|
+
import { aggregateToolResponse, buildToolPrompt, streamToolResponse } from "./src/tools.mjs"
|
|
36
37
|
import { importLocalLogin, saveSeed } from "./src/login.mjs"
|
|
37
38
|
|
|
38
39
|
const SESSION_TTL_MS = 30 * 60 * 1000
|
|
@@ -114,6 +115,25 @@ function authError(e, message) {
|
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
/** 选一条 session 路径,失败时按 session/auth 各重试一次 */
|
|
118
|
+
async function sendToolTurn(auth, { model, question, save }) {
|
|
119
|
+
try {
|
|
120
|
+
const id = await initSession(auth, question)
|
|
121
|
+
return await ask(auth, { sessionId: id, question, model })
|
|
122
|
+
} catch (e) {
|
|
123
|
+
if (!(e instanceof ImaError)) throw e
|
|
124
|
+
if (e.auth) {
|
|
125
|
+
const next = await refreshToken(auth)
|
|
126
|
+
save?.({ ...auth, access: next.access, refresh: next.refresh, expires: next.expires })
|
|
127
|
+
return await sendToolTurn({ ...auth, ...next }, { model, question, save })
|
|
128
|
+
}
|
|
129
|
+
if (e.session) {
|
|
130
|
+
const id = await initSession(auth, question)
|
|
131
|
+
return await ask(auth, { sessionId: id, question, model })
|
|
132
|
+
}
|
|
133
|
+
throw e
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
117
137
|
async function sendTurn(auth, { model, question, conv, instructions, carried, save }) {
|
|
118
138
|
const key = auth.uid + "|" + (conv || "anon")
|
|
119
139
|
let entry = getSession(key)
|
|
@@ -226,6 +246,28 @@ export const ImaLocalAuthPlugin = async ({ client } = {}) => {
|
|
|
226
246
|
if (!model) {
|
|
227
247
|
return errorResponse(404, `ima: 没有模型 ${String(chat.model ?? "")}`, {})
|
|
228
248
|
}
|
|
249
|
+
|
|
250
|
+
const tools = Array.isArray(chat.tools) ? chat.tools : []
|
|
251
|
+
const hasToolHistory = Array.isArray(chat.messages) && chat.messages.some(
|
|
252
|
+
(m) => m?.role === "tool" || (m?.role === "assistant" && Array.isArray(m?.tool_calls) && m.tool_calls.length > 0),
|
|
253
|
+
)
|
|
254
|
+
const toolMode = tools.length > 0 && (chat.tool_choice !== "none" || hasToolHistory)
|
|
255
|
+
if (toolMode) {
|
|
256
|
+
const { question } = buildToolPrompt(chat.messages, tools, chat.tool_choice)
|
|
257
|
+
try {
|
|
258
|
+
const res = await sendToolTurn(auth, { model, question, save: saveAuth })
|
|
259
|
+
if (chat.stream === false) return await aggregateToolResponse(res, model.id, tools)
|
|
260
|
+
return streamToolResponse(res, model.id, tools, {
|
|
261
|
+
includeUsage: chat.stream_options?.include_usage === true,
|
|
262
|
+
})
|
|
263
|
+
} catch (e) {
|
|
264
|
+
if (e instanceof ImaError && e.auth) {
|
|
265
|
+
return errorResponse(401, `ima 登录被拒:${e.message}`, { signIn: "expired" })
|
|
266
|
+
}
|
|
267
|
+
return errorResponse(502, `ima: ${e?.message ?? e}`, {})
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
229
271
|
const { text, index } = lastUser(chat.messages)
|
|
230
272
|
if (!text) return errorResponse(400, "ima: 这轮没有 user 消息", {})
|
|
231
273
|
const instructions = systemText(chat.messages)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magpie-ima-local-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "magpie / OpenCode provider plugin for the ima.copilot desktop app: its free DeepSeek and Tencent HY models, imported from the client already signed in on this machine, without pasting cookies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|