linco-connect 1.1.7 → 1.1.9

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 CHANGED
@@ -1,209 +1,130 @@
1
- # linco
1
+ # Linco Connect
2
2
 
3
- Linco / Linco 对接 Claude Code Codex 的本机 Agent 连接器。
3
+ Linco Connect 是运行在用户电脑上的本机 Agent 连接器,用于把 Linco IM 消息转发给本机 Agent CLI,并把回复、工具调用、权限确认、附件和生成文件回传到 IM。
4
4
 
5
- 它运行在用户自己的电脑上,负责把 Linco IM 服务端的消息转发给本机 Agent CLI,并把 Agent 的回复、工具调用、权限确认、附件和生成文件回传给 IM。仓库内置的 Web 页面只是本地自测页面,不是正式 IM 前端。
5
+ 它不是鉴权服务,也不是托管式多租户服务。用户凭证保存在本机配置文件中,连接地址默认由程序内置;普通用户不需要在 README 或配置中手动填写服务端地址。
6
6
 
7
- ## 定位
7
+ ## 功能
8
8
 
9
- - 本插件是**本机 Agent 连接器**,不是鉴权服务,也不是托管式多租户服务。
10
- - Linco IM 服务端负责校验连接 query 中的 `token=appId:appSecret`。
11
- - 插件连接 IM 时会把本机配置的 `appId/appSecret` 拼成单个 `token` 查询参数传给服务端。
12
- - IM WebSocket 地址由代码内置,并按 Agent 类型区分:
13
-
14
- ```text
15
- Claude Code: wss://chat.ddjf.info/socket/ai/claude
16
- Codex: wss://chat.ddjf.info/socket/ai/codex
17
- ```
18
-
19
- 普通用户初始化时不需要填写 `wsUrl`,私有化部署可在 `.linco/config.json` 中覆盖。
20
-
21
- ## 功能特性
22
-
23
- - npm CLI 安装和启动:支持 `linco-connect init/start/stop/doctor`,可用 `start --daemon` 后台运行。
24
- - 远端 IM 默认按配置连接,用户只需配置 `appId/appSecret`。
25
- - 本地测试页的模拟前端 IM 默认不连接:需要本地页面联调时需显式添加 `--local-im` 或 `--mock-im`。
26
- - 内置 Linco IM WebSocket 地址:用户只需配置 `appId/appSecret`,插件会在连接时拼成 `token=appId:appSecret`。
27
- - 多 Agent 连接:一个进程可同时连接 Claude Code 和 Codex 对应的 Linco 端点。
28
- - 本地自测页面:用于调试本机 Agent 桥接能力。
29
- - 本地访问 token:首次启动自动生成 `localToken`,保护本地测试页和本地 WebSocket。
30
- - Claude Code 流式桥接:使用 `stream-json` 输入/输出格式实时推送回复。
31
- - Codex 桥接:第一版使用系统安装的 `codex exec --json`,沿用系统 Codex 登录和配置。
32
- - 会话隔离:每个 Agent 和远端 session 都创建独立 session、workspace、attachments、outbox。
33
- - Markdown 展示:支持 GFM Markdown、代码块、表格、引用和安全链接。
34
- - 工具调用展示:Agent 工具输入、输出和错误以可折叠卡片展示。
35
- - 权限确认:工具/命令权限请求和危险操作确认默认自动允许;可用 `/approve off` 为当前会话恢复手动确认。
36
- - 附件上传:支持普通文件和图片;图片作为多模态内容发送,普通文件保存为本地路径引用。
37
- - 图片粘贴:支持从剪贴板粘贴图片。
38
- - 文件下发:Agent 生成文件放入 outbox 后,前端自动展示下载/预览卡片。
39
- - 斜杠命令:内置 `/help`、`/pwd`、`/cd`、`/new`、`/stop`、`/base`、`/status`、`/list`、`/approve`。
40
- - Windows Git Bash 检测:Windows 下自动查找 Git Bash,也可手动指定。
9
+ - 支持 Claude Code、Codex、Hermes、OpenClaw 等 Agent
10
+ - 支持远端 IM 连接,也支持本地测试页调试。
11
+ - 支持文本、图片和常见文档附件上传。
12
+ - 支持 Agent 生成文件自动下发:把文件放入当前会话的 outbox 目录即可推送给前端。
13
+ - 支持工具/命令权限确认和危险操作确认,默认自动审批,可在会话内切换。
14
+ - 支持会话历史查看、切换、删除和 Token 用量查看。
41
15
 
42
16
  ## 前置条件
43
17
 
44
18
  - Node.js 18+
45
- - 已安装 Claude Code CLI,终端可执行 `claude`
46
- - Claude Code 已完成登录或 API Key 配置
47
- - 如需启用 Codex:已安装 Codex CLI,终端可执行 `codex`,并已完成系统 Codex 登录或配置
48
- - Windows 用户建议安装 Git for Windows
19
+ - 已安装需要使用的 Agent CLI,并完成对应登录或配置:
20
+ - `claude`
21
+ - `codex`
22
+ - `hermes`
23
+ - `openclaw`
24
+ - Windows 用户建议安装 Git for Windows。
25
+
26
+ 只需要安装实际启用的 Agent。
49
27
 
50
28
  ## 安装
51
29
 
52
- 开发源码运行:
30
+ 源码运行:
53
31
 
54
32
  ```bash
55
33
  npm install
56
34
  npm start
57
35
  ```
58
36
 
59
- 作为 npm CLI 使用时:
37
+ 作为 CLI 使用:
60
38
 
61
39
  ```bash
62
40
  npm install -g linco-connect
63
- linco-connect init --token "appId:appSecret" --agent claude
64
- linco-connect doctor
65
- linco-connect start
66
- # 后台运行
67
- linco-connect start --daemon
68
- # 停止后台服务
69
- linco-connect stop
70
41
  ```
71
42
 
72
- 本地开发也可以用:
43
+ 本地源码也可以直接运行 CLI:
73
44
 
74
45
  ```bash
75
- node bin/linco-connect.js init --token "appId:appSecret" --agent claude
76
- node bin/linco-connect.js doctor
77
- node bin/linco-connect.js start
46
+ node bin/linco-connect.js --help
78
47
  ```
79
48
 
80
- ## 初始化配置
49
+ ## 初始化
81
50
 
82
- 推荐方式:
51
+ 推荐使用 token 初始化:
83
52
 
84
53
  ```bash
85
- linco-connect init --token "appId:appSecret" --agent claude
54
+ linco-connect init --token "<appId>:<appSecret>" --agent claude
86
55
  ```
87
56
 
88
- 可选参数:
57
+ 也可以分别传入:
89
58
 
90
59
  ```bash
91
- linco-connect init \
92
- --token "appId:appSecret" \
93
- --agent claude \
94
- --account default \
95
- --force
60
+ linco-connect init --app-id "<appId>" --app-secret "<appSecret>" --agent codex
96
61
  ```
97
62
 
98
- 说明:
63
+ 常用参数:
99
64
 
100
- - `--token` 格式为 `appId:appSecret`。
101
- - `--agent` 必填,指定 Agent 类型(如 `claude` 或 `codex`)。
102
- - token 按第一个冒号切分,所以 `appSecret` 内部可以包含冒号。
103
- - `--force` 用于覆盖已有账号配置。
104
- - 初始化不会询问或写入 `wsUrl`。
105
- - 多次执行 `init` 并传入不同 `--agent` 可在同一账号下启用多个 Agent。
65
+ | 参数 | 说明 |
66
+ | --- | --- |
67
+ | `--agent <类型>` | 启用指定 Agent,如 `claude`、`codex`、`hermes`、`openclaw` |
68
+ | `--account <名称>` | 指定账号名,默认 `default` |
69
+ | `--force` | 覆盖已有配置 |
106
70
 
107
- ### Hermes Agent 初始化
71
+ 如需启用多个 Agent,可多次执行 `init`,每次传入不同的 `--agent`。
108
72
 
109
- Hermes 使用本机 Hermes Gateway。默认情况下,`ddchat-connect` 会在第一次 Hermes 对话前自动检查 Gateway;如果未运行,会参考 Hermes Web UI 的方式自动补齐当前 Hermes profile 的 `platforms.api_server` 配置,生成本机 API key,并执行 `hermes gateway run --replace`。
73
+ ## 启动和停止
110
74
 
111
- 最小配置只需要启用 Hermes:
75
+ 前台启动:
112
76
 
113
- ```json
114
- {
115
- "agents": {
116
- "hermes": {
117
- "enabled": true
118
- }
119
- }
120
- }
77
+ ```bash
78
+ linco-connect start
121
79
  ```
122
80
 
123
- 如需覆盖默认值,可配置:
81
+ 后台启动:
124
82
 
125
- ```json
126
- {
127
- "agents": {
128
- "hermes": {
129
- "enabled": true,
130
- "gatewayUrl": "http://127.0.0.1:8642",
131
- "autoStartGateway": true,
132
- "hermesBin": "hermes",
133
- "profile": "default"
134
- }
135
- }
136
- }
83
+ ```bash
84
+ linco-connect start --daemon
137
85
  ```
138
86
 
139
- 如果已经有外部 Gateway,可关闭自动启动:
87
+ 停止后台服务:
140
88
 
141
- ```json
142
- {
143
- "agents": {
144
- "hermes": {
145
- "enabled": true,
146
- "gatewayUrl": "http://127.0.0.1:9000",
147
- "autoStartGateway": false
148
- }
149
- }
150
- }
89
+ ```bash
90
+ linco-connect stop
151
91
  ```
152
92
 
153
- 可通过 `linco-connect doctor` 检查 Hermes Gateway 状态;Gateway 未运行但自动启动开启时,发送 Hermes 消息会自动启动。
93
+ 检查本机环境:
154
94
 
155
- #### 接口鉴权
156
-
157
- 如果 Hermes 的 `api_server` 配置了 `key`(接口鉴权),需要在 `~/.linco/config.json` 中添加对应的 API Key:
158
-
159
- ```json
160
- {
161
- "agents": {
162
- "hermes": {
163
- "enabled": true,
164
- "apiKey": "你的API_SERVER_KEY值"
165
- }
166
- }
167
- }
95
+ ```bash
96
+ linco-connect doctor
168
97
  ```
169
98
 
170
- 或设置环境变量:
99
+ 本地测试页默认不连接模拟 IM。需要本地联调时显式开启:
171
100
 
172
101
  ```bash
173
- export LINCO_HERMES_API_KEY=你的API_SERVER_KEY值
102
+ linco-connect start --local-im
174
103
  ```
175
104
 
176
- 如果连接时报 `401`,请检查 Hermes `api_server.key` 是否与 `LINCO_HERMES_API_KEY` / `agents.hermes.apiKey` 一致。自动启动会保留用户已有 key;如果 key 缺失,会生成新的本机 API key,当前和后续连接器进程会从 Hermes 配置中读取并使用。
177
-
178
- ## 配置文件
105
+ 启动后终端会输出带访问 token 的本地测试页地址。不要把该地址或 token 发给不可信的人。
179
106
 
180
- 配置统一保存在用户主目录下的 `.linco` 根目录:
107
+ ## 配置
181
108
 
182
- ```text
183
- ~/.linco/config.json
184
- ```
109
+ 配置默认保存在用户目录下的 `.linco/config.json`。初始化命令会自动写入凭证和本地测试 token,一般不需要手动编辑。
185
110
 
186
- Windows 示例:
187
-
188
- ```text
189
- C:\Users\<用户名>\.linco\config.json
190
- ```
191
-
192
- 示例结构:
111
+ 最小配置结构示例:
193
112
 
194
113
  ```json
195
114
  {
196
- "localWeb": {
197
- "token": "auto-generated-local-token"
198
- },
199
115
  "defaultChannel": "linco",
200
- "defaultAccount": "default",
201
116
  "channels": {
202
117
  "linco": {
203
- "accounts": {
204
- "default": {
205
- "appId": "your-app-id",
206
- "appSecret": "your-app-secret"
118
+ "agents": {
119
+ "claude": {
120
+ "defaultAccount": "default",
121
+ "accounts": {
122
+ "default": {
123
+ "appId": "<appId>",
124
+ "appSecret": "<appSecret>",
125
+ "enabled": true
126
+ }
127
+ }
207
128
  }
208
129
  }
209
130
  }
@@ -211,341 +132,73 @@ C:\Users\<用户名>\.linco\config.json
211
132
  }
212
133
  ```
213
134
 
214
- 配置含义:
215
-
216
- - `localWeb.token`:本地测试页访问 token,首次启动或初始化时自动生成。
217
- - `defaultAccount`:默认账号名。
218
- - `appId/appSecret`:本机保存的 Linco 应用凭证;插件连接 Linco IM 时会拼成 query 参数 `token=appId:appSecret`。
219
- - `agents.claude` / `agents.codex`:按 Agent 配置启用状态、CLI 命令和可选私有化 `wsUrl` 覆盖。
220
-
221
- 默认不需要把内置 `wsUrl` 写入配置文件。启用 Codex 的最小配置示例:
222
-
223
- ```json
224
- {
225
- "agents": {
226
- "codex": {
227
- "enabled": true,
228
- "bin": "codex"
229
- }
230
- }
231
- }
232
- ```
233
-
234
- 私有化部署可覆盖某个 Agent 的连接地址:
235
-
236
- ```json
237
- {
238
- "agents": {
239
- "codex": {
240
- "enabled": true,
241
- "bin": "codex",
242
- "wsUrl": "wss://example.internal/socket/ai/codex"
243
- }
244
- }
245
- }
246
- ```
247
-
248
- ## 启动
135
+ 常用环境变量:
249
136
 
250
- 默认启动本地服务,并按配置连接远端 IM;本地测试页不会自动连接模拟前端 IM:
251
-
252
- ```bash
253
- linco-connect start
254
- ```
255
-
256
- 如果 Linco Connect 已经在运行,再次执行 `linco-connect start` `npm start` 会先停止旧进程,再启动新的进程,相当于一次 restart。
257
-
258
- 需要使用本地测试页模拟前端 IM 时,显式启用:
259
-
260
- ```bash
261
- linco-connect start --local-im
262
- # 等价写法
263
- linco-connect start --mock-im
264
- ```
265
-
266
- 后台启动:
267
-
268
- ```bash
269
- linco-connect start --daemon
270
- ```
271
-
272
- 如果后台服务已经在运行,再次执行 `linco-connect start --daemon` 也会先停止旧进程,再启动新的后台进程。
273
-
274
- 后台启动并启用本地模拟前端 IM:
275
-
276
- ```bash
277
- linco-connect start --daemon --local-im
278
- ```
279
-
280
- 停止后台服务:
281
-
282
- ```bash
283
- linco-connect stop
284
- ```
285
-
286
- 后台模式会把 PID 和日志写入:
287
-
288
- ```text
289
- ~/.linco/linco-connect.pid
290
- ~/.linco/logs/daemon.out.log
291
- ~/.linco/logs/daemon.err.log
292
- ```
293
-
294
- 启动后终端会输出本地测试页地址,例如:
295
-
296
- ```text
297
- 本地测试页: http://127.0.0.1:3000/?localToken=xxxx
298
- ```
299
-
300
- 请使用这条带 `localToken` 的地址打开测试页面。直接访问 `http://127.0.0.1:3000` 会被拒绝。
301
-
302
- 源码开发时也可以继续使用:
303
-
304
- ```bash
305
- npm start
306
- ```
307
-
308
- 源码开发后台运行:
309
-
310
- ```bash
311
- npm start -- --daemon
312
- ```
313
-
314
- ## 环境检查
315
-
316
- ```bash
317
- linco-connect doctor
318
- ```
319
-
320
- 会检查:
321
-
322
- - Node.js 版本
323
- - 配置文件是否存在
324
- - `appId/appSecret` 是否已配置为 Linco token 来源
325
- - 本地测试 token 是否已生成
326
- - 已启用 Agent 的 CLI 是否可用
327
- - Windows Git Bash 是否可用
328
- - `Linco Home`、sessions 目录是否可写
329
-
330
- `doctor` 不会请求真实 IM 服务端做鉴权;`token=appId:appSecret` 的鉴权由 Linco IM 服务端负责。
331
-
332
- ## 本地自测页面
333
-
334
- 本地页面仅用于开发和自测:
335
-
336
- - 页面通过本机 WebSocket 连接当前插件服务。
337
- - 页面不会直接连接供应商 IM WebSocket。
338
- - 页面需要 `localToken` 才能访问。
339
- - 页面可测试消息、附件、工具调用、权限确认和 outbox 文件下发。
340
-
341
- ## 附件上传
137
+ | 变量 | 说明 |
138
+ | --- | --- |
139
+ | `LINCO_TOKEN` | `<appId>:<appSecret>` 简写形式 |
140
+ | `LINCO_AGENT` | 当前默认 Agent 类型 |
141
+ | `LINCO_ACCOUNT` | 当前账号名 |
142
+ | `LINCO_HOME` | 运行数据目录 |
143
+ | `LINCO_LOCAL_AGENT` | 本地测试页默认 Agent |
144
+ | `LINCO_CLAUDE_ENABLED` | 是否启用 Claude |
145
+ | `LINCO_CODEX_ENABLED` | 是否启用 Codex |
146
+ | `LINCO_HERMES_ENABLED` | 是否启用 Hermes |
147
+ | `LINCO_OPENCLAW_ENABLED` | 是否启用 OpenClaw |
148
+ | `LINCO_<AGENT>_BIN` | 覆盖对应 Agent CLI 命令或路径 |
149
+ | `LINCO_<AGENT>_WS_URL` | 私有化部署时覆盖对应 Agent 的连接地址 |
150
+
151
+ ## 附件和文件下发
152
+
153
+ 默认支持常见图片、文本、表格、文档、PDF、压缩包等附件。高风险可执行文件和脚本扩展名默认会被拦截。
342
154
 
343
155
  默认限制:
344
156
 
345
- - 单次最多 50 个附件
346
- - 单文件最大 50 MB
347
- - 单次附件总大小最大 250 MB
348
- - 默认拦截可执行文件和高风险脚本扩展名,例如 `.exe`、`.bat`、`.cmd`、`.ps1`、`.dll`
349
-
350
- 图片附件会直接作为当前 Agent 的多模态图片输入;Codex 当前会降级为文本占位提示。普通文件会保存到当前 session 的附件目录,并把本地路径附加给 Agent。
351
-
352
- ## Agent 生成文件下发
353
-
354
- 每个 session 都有独立 outbox 目录。Agent 如果需要把文件发给用户,应保存或复制到该目录。服务端会自动扫描新文件并推送到前端显示。
355
-
356
- 可通过本地命令查看路径:
357
-
358
- ```text
359
- /base
360
- ```
361
-
362
- 输出中会包含:
157
+ | 项目 | 限制 |
158
+ | --- | --- |
159
+ | 单次附件数量 | 50 |
160
+ | 单文件大小 | 50 MB |
161
+ | 单次附件总大小 | 250 MB |
162
+ | outbox 单文件大小 | 50 MB |
363
163
 
364
- ```text
365
- 附件目录: .../attachments
366
- outbox 目录: .../outbox
367
- ```
164
+ Agent 需要把文件发给用户时,可先执行 `/base` 查看当前会话目录,然后把文件保存或复制到 outbox 目录。连接器会自动扫描新文件并推送到前端。
368
165
 
369
166
  ## 斜杠命令
370
167
 
371
168
  | 命令 | 说明 |
372
169
  | --- | --- |
373
- | `/help` | 显示可用命令和附件说明 |
374
- | `/commands` | 显示本地命令和当前 Agent 原生命令说明 |
170
+ | `/help` | 显示快速帮助 |
171
+ | `/commands` | 显示本地命令和 Agent 原生命令说明 |
375
172
  | `/status` | 显示当前会话状态 |
376
173
  | `/pwd` | 显示当前工作目录 |
377
174
  | `/cd` | 列出当前目录内容 |
378
- | `/cd <路径>` | 切换工作目录,并开启新的 Agent 会话 |
175
+ | `/cd <路径>` | 切换工作目录并开启新 Agent 会话 |
379
176
  | `/new` | 开启新 Agent 会话,清除上下文 |
380
- | `/stop` | 停止当前 Agent 进程,下次消息尝试恢复当前会话 |
381
- | `/base` | 显示 Linco 运行目录、附件目录和 outbox 目录 |
382
- | `/list` | 列出当前 IM 会话最近 10 Agent Session 历史 |
383
- | `/list <条数>` | 按指定条数列出最近的 Agent Session 历史 |
177
+ | `/stop` | 停止当前 Agent 进程,保留可恢复会话 ID |
178
+ | `/reload` | 刷新当前 Agent 记忆,下次消息重新加载本地历史;也可使用 `/refresh` |
179
+ | `/pc` | 显示 PC 端打开当前 Claude 会话的命令;目前仅支持 Claude |
180
+ | `/base` | 显示运行目录、附件目录和 outbox 目录 |
181
+ | `/list [条数]` | 列出当前 IM 会话下最近的 Agent Session 历史 |
182
+ | `/switch <序号或ID>` | 切换到指定 Agent Session,恢复上下文 |
183
+ | `/delete <序号或ID>` | 从历史记录中删除指定 Agent Session |
384
184
  | `/approve` | 显示当前自动审批状态 |
385
- | `/approve on` | 开启当前会话自动审批,后续工具/命令权限请求和危险操作确认自动允许(默认) |
386
- | `/approve off` | 关闭当前会话自动审批,恢复手动确认 |
387
-
388
- 除上述本地命令外,其他 `/xxx` 会透传给当前 Agent CLI。
389
-
390
- ## 常用环境变量
391
-
392
- | 变量 | 默认值 | 说明 |
393
- | --- | --- | --- |
394
- | `PORT` | `3000` | 本地 HTTP 服务端口 |
395
- | `HOST` | `127.0.0.1` | 本地 HTTP 服务监听地址 |
396
- | `CLAUDE_BIN` | `claude` | Claude Code CLI 命令或路径 |
397
- | `CODEX_BIN` | `codex` | Codex CLI 命令或路径 |
398
- | `LINCO_CLAUDE_ENABLED` | 无配置文件时为启用 | 是否启用 Claude 连接器 |
399
- | `LINCO_CODEX_ENABLED` | `false` | 是否启用 Codex 连接器 |
400
- | `LINCO_HERMES_ENABLED` | `false` | 是否启用 Hermes 连接器 |
401
- | `LINCO_HERMES_GATEWAY_URL` | `http://127.0.0.1:8642` | Hermes Gateway 地址 |
402
- | `LINCO_HERMES_AUTO_START_GATEWAY` | `true` | Gateway 未运行时是否自动补齐配置并启动 |
403
- | `LINCO_HERMES_BIN` / `HERMES_BIN` | `hermes` | Hermes CLI 命令或路径 |
404
- | `LINCO_HERMES_PROFILE` | `default` | Hermes profile 名称 |
405
- | `LINCO_HERMES_HOME` / `HERMES_HOME` | 自动检测 | Hermes home 目录 |
406
- | `LINCO_HERMES_API_KEY` | 无 | Hermes Gateway 接口鉴权 Key |
407
- | `LINCO_CLAUDE_WS_URL` | `wss://chat.ddjf.info/socket/ai/claude` | Claude 端点覆盖 |
408
- | `LINCO_CODEX_WS_URL` | `wss://chat.ddjf.info/socket/ai/codex` | Codex 端点覆盖 |
409
- | `LINCO_LOCAL_AGENT` | `claude` | 本地测试页默认使用的 Agent |
410
- | `CLAUDE_SYSTEM_PROMPT` | 内置中文 Markdown 输出提示词 | 附加给 Claude 的系统提示词 |
411
- | `CLAUDE_CODE_GIT_BASH_PATH` | 自动检测 | Windows 下 Git Bash 路径 |
412
- | `MAX_WS_PAYLOAD_BYTES` | `367001600` | WebSocket 最大消息体大小 |
413
- | `MAX_ATTACHMENT_COUNT` | `50` | 单次最大附件数量 |
414
- | `MAX_ATTACHMENT_BYTES` | `52428800` | 单附件大小限制 |
415
- | `MAX_TOTAL_ATTACHMENT_BYTES` | `262144000` | 单次附件总大小限制 |
416
- | `MAX_OUTGOING_ATTACHMENT_BYTES` | `52428800` | outbox 单文件下发大小限制 |
417
- | `MAX_MESSAGE_QUEUE` | `10` | Claude 忙碌时的最大排队消息数 |
418
- | `ATTACHMENTS_DIR_NAME` | `attachments` | session 运行目录下的附件目录名 |
419
- | `OUTBOX_DIR_NAME` | `outbox` | session 运行目录下的下发目录名 |
420
- | `ALLOW_UNSAFE_ATTACHMENTS` | `0` | 设置为 `1` 时允许上传默认拦截的高风险扩展名 |
421
- | `UNSAFE_ATTACHMENT_EXTENSIONS` | 内置扩展名列表 | 逗号分隔的高风险扩展名列表 |
422
- | `LINCO_CHANNEL` | `linco` | 选择配置文件中的 IM 渠道 |
423
- | `LINCO_ACCOUNT` | `default` | 选择配置文件中的 IM 账号 |
424
- | `LINCO_TOKEN` | 空 | `appId:appSecret` 简写形式;连接 Linco 时作为 query 参数 `token` 发送 |
425
- | `LINCO_APP_ID` | 配置文件值 | Linco IM 应用 ID |
426
- | `LINCO_APP_SECRET` | 配置文件值 | Linco IM 应用密钥 |
427
- | `LINCO_AGENT_ID` | `main` | Linco 连接器标识,可由配置文件或环境变量指定 |
428
- | `LINCO_WS_URL` | `wss://chat.ddjf.info/socket/ai/claude` | Claude 旧版端点覆盖,普通用户不需要配置 |
429
- | `LINCO_HOME` | `~/.linco` | 运行数据根目录 |
430
- | `LINCO_SESSIONS_DIR` | `~/.linco/sessions` | session 数据目录 |
431
- | `CLAUDE_GRACEFUL_SHUTDOWN_MS` | `3000` | Claude 进程优雅关闭时间 |
432
-
433
- ## 运行目录
434
-
435
- 默认目录结构:
436
-
437
- ```text
438
- ~/.linco/
439
- ├── config.json
440
- ├── claude/
441
- │ └── sessions/
442
- │ └── sid_xxxxxxxx/
443
- │ ├── session.json
444
- │ ├── workspace/
445
- │ ├── attachments/
446
- │ └── outbox/
447
- └── codex/
448
- └── sessions/
449
- └── sid_xxxxxxxx/
450
- ├── session.json
451
- ├── workspace/
452
- ├── attachments/
453
- └── outbox/
454
- ```
185
+ | `/approve on` | 开启自动审批 |
186
+ | `/approve off` | 关闭自动审批,恢复手动确认 |
187
+ | `/usage` | 显示 Token 用量统计;部分 Agent 可能暂不提供 |
455
188
 
456
- 说明:
189
+ 除上述本地命令外,其他 `/xxx` 会透传给当前 Agent。部分 Agent 原生命令只适合交互式 CLI/TUI,在桥接模式下可能没有输出。
457
190
 
458
- - `config.json` 保存用户配置和本地测试 token。
459
- - `claude/sessions/` 和 `codex/sessions/` 分别保存对应 Agent 的会话元数据、工作目录、上传附件和下发文件。
460
- - `attachments/` 保存用户上传的普通文件。
461
- - `outbox/` 用于 Agent 生成文件并自动下发给前端。
462
- - Codex 默认使用系统安装时的认证和配置,不会创建项目托管的 `codex-home`。
191
+ ## 安全注意
463
192
 
464
- ## 故障排查
465
-
466
- ### Hermes 模式报 "fetch failed" 错误
467
-
468
- 默认情况下,`ddchat-connect` 会在第一次 Hermes 对话前自动检查并启动 Hermes Gateway。如果仍然报 **"Hermes 错误: fetch failed"**,通常是 Hermes CLI 不可用、Hermes 自身模型配置异常、端口被占用,或配置了外部 Gateway 但未运行。
469
-
470
- 先运行:
471
-
472
- ```bash
473
- linco-connect doctor
474
- ```
475
-
476
- 排查方向:
477
-
478
- - 确认终端可执行 `hermes`,或通过 `agents.hermes.hermesBin` / `LINCO_HERMES_BIN` 配置 Hermes 可执行文件路径。
479
- - 确认 Hermes 自身模型、账号或 provider 配置可用。
480
- - 确认 `gatewayUrl` 对应端口未被其他程序占用。
481
- - 如果使用 hermes-web-ui 已启动的 Gateway,确认 `gatewayUrl` 和 `profile` 与 web-ui 当前 Gateway 一致。
482
- - 如果返回 `401`,确认 `agents.hermes.apiKey` / `LINCO_HERMES_API_KEY` 与 Hermes `api_server.key` 一致。
483
-
484
- 高级排障时可手动检查 Hermes profile 的 `config.yaml`,Gateway 配置应使用 `extra.host` / `extra.port`:
485
-
486
- ```yaml
487
- platforms:
488
- api_server:
489
- enabled: true
490
- key: '<本机 API key>'
491
- cors_origins: 'http://127.0.0.1:*'
492
- extra:
493
- host: 127.0.0.1
494
- port: 8642
495
- ```
496
-
497
- 确认 Gateway 健康:
498
-
499
- ```bash
500
- curl http://127.0.0.1:8642/health
501
- ```
502
-
503
-
504
- ## 安全注意事项
505
-
506
- - 默认只监听 `127.0.0.1`,不建议直接暴露到公网。
507
- - 本地测试页受 `localToken` 保护,请不要把带 token 的 URL 发给不可信的人。
508
- - `appSecret` 保存在本机 `~/.linco/config.json`,请保护好用户电脑和配置文件。
509
- - 插件不负责校验 `token=appId:appSecret`;真实鉴权由 Linco IM 服务端完成。
510
- - Agent 的工具权限请求会转发给前端确认,但最终权限边界仍取决于本机 Agent 配置和用户批准。
511
- - 危险命令检测只是基础提示,不应视为完整沙箱或安全隔离机制。
512
- - 上传附件会落盘到本机,请不要上传或下发不应保存在本机的敏感文件。
513
-
514
- ## 项目结构
515
-
516
- ```text
517
- .
518
- ├── bin/
519
- │ └── linco.js # npm CLI 入口
520
- ├── public/
521
- │ └── index.html # 本地自测页面
522
- ├── src/
523
- │ ├── agentRunner.js # Agent 运行器门面
524
- │ ├── agents/ # Claude/Codex Provider
525
- │ ├── attachmentHandler.js # 上传附件保存、校验和 Agent 输入构造
526
- │ ├── claudeRunner.js # Claude Code 子进程、stream-json 解析、权限处理
527
- │ ├── config.js # 配置文件、环境变量和 Git Bash 检测
528
- │ ├── danger.js # 高风险命令文本检测
529
- │ ├── httpStatic.js # 静态文件、本地 client config 和 outbox 下载接口
530
- │ ├── localAuth.js # 本地测试 token 生成和校验
531
- │ ├── outgoingAttachmentHandler.js # outbox 扫描和附件下发
532
- │ ├── protocol.js # WebSocket 消息封装
533
- │ ├── serverApp.js # 可复用服务启动入口
534
- │ ├── session.js # session 状态和 Agent 进程清理
535
- │ ├── slashCommands.js # /help、/cd、/new 等斜杠命令
536
- │ └── wsServer.js # WebSocket 连接、消息分发和 session 生命周期
537
- ├── server.js # 兼容 npm start 的入口
538
- ├── package.json
539
- └── package-lock.json
540
- ```
193
+ - 不要公开配置文件、访问 token、`appSecret` 或带 token 的本地测试页地址。
194
+ - 本地测试页只用于开发和自测。
195
+ - 自动审批会允许后续工具/命令权限请求和危险操作确认;如需人工确认,请在会话内执行 `/approve off`。
196
+ - 附件会保存到本机,请避免上传不应落盘的敏感文件。
541
197
 
542
198
  ## 开发命令
543
199
 
544
200
  ```bash
545
201
  npm install
546
202
  npm start
547
- node bin/linco-connect.js --help
548
203
  node bin/linco-connect.js doctor
549
204
  ```
550
-
551
- 当前项目没有配置测试、lint 或构建脚本。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linco-connect",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "自研 IM 桥接多 Agent 服务",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -108,7 +108,11 @@ async function runOpenClawTurn(input, ws, session, config) {
108
108
  await done;
109
109
  } catch (err) {
110
110
  if (session.isTurnActive) {
111
- if (!isClosedAbort(err)) sendError(ws, `OpenClaw error: ${err.message}`);
111
+ if (!isClosedAbort(err)) {
112
+ const message = `OpenClaw error: ${err.message}`;
113
+ sendError(ws, message);
114
+ sendTurnEnd(ws, session, 'error', { error: message });
115
+ }
112
116
  finishTurn(ws, session, config, { drain: !isClosedAbort(err) });
113
117
  }
114
118
  }
@@ -1,4 +1,5 @@
1
1
  const fs = require('fs');
2
+ const os = require('os');
2
3
  const path = require('path');
3
4
  const { resetOutgoingAttachments, startOutboxWatcher, stopOutboxWatcher } = require('./outgoingAttachmentHandler');
4
5
  const { sendError, sendSystem, sendTurnEnd } = require('./protocol');
@@ -16,6 +17,8 @@ function localCommandsHelp() {
16
17
  /cd - 列出当前目录内容
17
18
  /new - 开启新 Agent 会话(清除上下文)
18
19
  /stop - 停止当前 Agent 进程,保留可恢复会话 ID
20
+ /reload - 刷新当前 Agent 记忆,下次消息重新 resume
21
+ /pc - 显示 PC 端 Claude Code 打开当前会话的命令
19
22
  /base - 显示 Linco 运行目录信息
20
23
  /list [条数] - 列出当前 IM 会话下最近的 Agent Session 历史(默认 10 条)
21
24
  /switch <序号> - 切换到指定 Agent Session(恢复上下文)
@@ -77,6 +80,15 @@ function handleSlashCommand(text, ws, session, config) {
77
80
  sendSystem(ws, '⏹️ 已停止当前 Agent 进程,下次消息会尝试恢复当前会话。');
78
81
  return completeLocalCommand(ws, session);
79
82
 
83
+ case '/reload':
84
+ case '/refresh':
85
+ handleReload(ws, session);
86
+ return completeLocalCommand(ws, session);
87
+
88
+ case '/pc':
89
+ handlePc(ws, session);
90
+ return completeLocalCommand(ws, session);
91
+
80
92
  case '/base':
81
93
  sendSystem(ws, `🗄️ Linco 运行信息:
82
94
  当前工作目录: ${session.workspace}
@@ -149,6 +161,61 @@ function sendHermesWorkspaceNotice(ws) {
149
161
  sendSystem(ws, 'Hermes 模式下工作目录由 Hermes Gateway/Agent 自身决定,/pwd 与 /cd 不在插件侧处理。');
150
162
  }
151
163
 
164
+ function handleReload(ws, session) {
165
+ const agentType = session.agentType || 'claude';
166
+ const resumeId = session.agentSessionId || session.claudeSessionId || '';
167
+ stopAgentProcess(session, { clearAgentSession: false });
168
+ sendSystem(ws, [
169
+ `🔄 已刷新当前 ${agentType} 会话。`,
170
+ resumeId ? `保留的 Session ID: ${resumeId}` : '当前还没有可恢复的 Session ID。',
171
+ '下次消息会重新加载本地 Agent 历史。'
172
+ ].join('\n'));
173
+ }
174
+
175
+ function handlePc(ws, session) {
176
+ const agentType = session.agentType || 'claude';
177
+ if (agentType !== 'claude') {
178
+ sendError(ws, '/pc 目前只支持 Claude 模式。');
179
+ return;
180
+ }
181
+
182
+ const resumeId = session.agentSessionId || session.claudeSessionId;
183
+ if (!resumeId) {
184
+ sendError(ws, '当前还没有 Claude Session ID。请先发送一条消息建立会话后再使用 /pc。');
185
+ return;
186
+ }
187
+
188
+ const transcriptPath = resolveClaudeTranscriptPath(session.workspace, resumeId);
189
+ const transcriptStatus = fs.existsSync(transcriptPath) ? 'Claude 历史文件' : 'Claude 历史文件(预计位置,当前未检测到)';
190
+
191
+ sendSystem(ws, [
192
+ '💻 PC 端可以用下面的命令打开当前 Claude 会话:',
193
+ '',
194
+ '```powershell',
195
+ `claude --resume ${resumeId}`,
196
+ '```',
197
+ '',
198
+ `工作目录: ${session.workspace}`,
199
+ `${transcriptStatus}: ${transcriptPath}`,
200
+ '',
201
+ '如果 PowerShell 提示 claude.ps1 被执行策略拦截,可以改用:',
202
+ `cmd /c claude --resume ${resumeId}`,
203
+ '',
204
+ 'PC 端聊完后,回到 IM 发送 /reload,再继续提问。'
205
+ ].join('\n'));
206
+ }
207
+
208
+ function resolveClaudeTranscriptPath(workspace, sessionId) {
209
+ const projectDir = encodeClaudeProjectDir(workspace || process.cwd());
210
+ return path.join(os.homedir(), '.claude', 'projects', projectDir, `${sessionId}.jsonl`);
211
+ }
212
+
213
+ function encodeClaudeProjectDir(workspace) {
214
+ return path.resolve(workspace)
215
+ .replace(/:/g, '-')
216
+ .replace(/[\\/]/g, '-');
217
+ }
218
+
152
219
  function handleCd(targetPath, ws, session, config) {
153
220
  if (!targetPath) {
154
221
  try {