sintbot 1.4.9 → 1.4.11
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/CHANGELOG.en.json +22 -313
- package/CHANGELOG.json +22 -320
- package/docs/AI-ASSISTED-INSTALL.md +2 -2
- package/docs/install.md +5 -5
- package/docs/zh-CN/AI-ASSISTED-INSTALL.md +2 -2
- package/docs/zh-CN/install.md +5 -5
- package/install.sh +1 -1
- package/package.json +2 -1
- package/src/agent/claudecode.js +39 -5
- package/src/agent/claudefollowup.js +92 -0
- package/src/agent/codexapp.js +6 -0
- package/src/agent/codexcode.js +4 -0
- package/src/agent/privatecore.js +18 -4
- package/src/agent/privatecore.wasm +0 -0
- package/src/c2console.js +1 -1
- package/src/c2install.js +1 -0
- package/src/config.js +2 -2
- package/src/core/c2cardterminalpath.js +6 -4
- package/src/core/c2runnerinput.js +6 -3
- package/src/core/c2terminaleffectbridge.js +4 -2
- package/src/core/c2turnprojection.js +28 -7
- package/src/core/v2engine.js +10 -8
- package/src/ui/console.html +11 -10
- package/src/ui/serverbase.js +6 -5
package/CHANGELOG.json
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.4.11",
|
|
4
|
+
"date": "2026-11-10",
|
|
5
|
+
"name": "统一忙时跟进",
|
|
6
|
+
"items": [
|
|
7
|
+
{
|
|
8
|
+
"t": "Codex 与 Claude Code 默认开启忙时跟进",
|
|
9
|
+
"d": "统一按群开关并持久保存关闭;Claude 确认读取后加入任务,续轮答案合并为一条最终回复。撤回已交给执行器的补话取消整轮,未知送达不重放。"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"version": "1.4.10",
|
|
15
|
+
"date": "2026-11-10",
|
|
16
|
+
"name": "执行中断收尾",
|
|
17
|
+
"items": [
|
|
18
|
+
{
|
|
19
|
+
"t": "修复:模型进程中途退出后群无法继续处理消息",
|
|
20
|
+
"d": "执行器确认退出但未返回最终结果时,原卡片显示中断提示,确认送达后继续处理下一条消息。不会将草稿当答案或自动重跑;已执行的操作需先核对。关闭或发送结果不明时仍保留现场。"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
2
24
|
{
|
|
3
25
|
"version": "1.4.9",
|
|
4
26
|
"date": "2026-11-10",
|
|
@@ -193,325 +215,5 @@
|
|
|
193
215
|
"d": "先重启服务;仍然暂停的群,在服务停止后运行 sintbot incident seal --group 群 ID。原记录原样封存,这个群换一份新记录重新开放,封存前未完成的消息不会再处理。"
|
|
194
216
|
}
|
|
195
217
|
]
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
"version": "1.4.0",
|
|
199
|
-
"date": "2026-11-08",
|
|
200
|
-
"name": "多群、Claude Code 与群内命令",
|
|
201
|
-
"items": [
|
|
202
|
-
{
|
|
203
|
-
"t": "一个应用服务多个群",
|
|
204
|
-
"d": "同一个飞书应用可绑定 1–32 个群,每个群对应一个本地项目,各自记录、互不影响;同时运行的任务数可设上限。"
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
"t": "每个群可选 Codex 或 Claude Code",
|
|
208
|
-
"d": "按群选择执行器和模型;群里发 /model 查看或切换,切换只在本群空闲时进行,并开始新的一段对话。"
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
"t": "群内命令",
|
|
212
|
-
"d": "新增 /help、/status、/new、/hud、/issue,查看状态、额度与用量,开始新对话,记下反馈;不支持的命令只回一句提示,不再中断服务。"
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
"t": "回复卡片边做边更新",
|
|
216
|
-
"d": "模型开始输出后卡片就出现,并随进度刷新。"
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
"t": "本机控制台",
|
|
220
|
-
"d": "带 --ui 启动后可查看各群状态、停止任务、绑定新群、切换空闲群的模型或项目目录、处理群内反馈。"
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
"t": "出错只影响当前群",
|
|
224
|
-
"d": "某一轮模型报错或没有结果时,只在本群提示重新发送,不自动重试,其他群照常;新加的群在重启时自动登记。"
|
|
225
|
-
}
|
|
226
|
-
]
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
"version": "1.3.0",
|
|
230
|
-
"date": "2026-11-08",
|
|
231
|
-
"name": "补充内置核心",
|
|
232
|
-
"items": [
|
|
233
|
-
{
|
|
234
|
-
"t": "补充内置核心",
|
|
235
|
-
"d": "本版支持 macOS 上的飞书单群 Codex 消息;画布、多群和其他平台后续迭代。已有多群安装请保留原版本,按新版安装指南单独配置。"
|
|
236
|
-
}
|
|
237
|
-
]
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
"version": "1.2.1",
|
|
241
|
-
"date": "2026-11-05",
|
|
242
|
-
"name": "修复补话时的误报",
|
|
243
|
-
"items": [
|
|
244
|
-
{
|
|
245
|
-
"t": "刚开始处理时补话不再误报已排队",
|
|
246
|
-
"d": "任务刚开始的几秒内补话,会在通道就绪后并入当前任务,不再先说一句「当前任务结束后处理」。"
|
|
247
|
-
}
|
|
248
|
-
]
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
"version": "1.2.0",
|
|
252
|
-
"date": "2026-11-05",
|
|
253
|
-
"name": "忙时跟进更可靠,出错说得更清楚",
|
|
254
|
-
"items": [
|
|
255
|
-
{
|
|
256
|
-
"t": "回答卡片跟着最新的跟进走",
|
|
257
|
-
"d": "跟进被接受后,回复卡片移到这条消息下面,做完时答案在群底部;卡片搬不了时才发一句「已加入」。"
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
"t": "撤回和重做不再丢消息",
|
|
261
|
-
"d": "撤回还没送达的跟进后不会再单独执行;换会话或切模型重做时,已送达的跟进会一起带上,撤回过的除外。"
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
"t": "Codex 主动请求不再卡住任务",
|
|
265
|
-
"d": "无人值守时按协议拒绝审批和提问请求,任务继续往下走。"
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
"t": "控制台插话可以加入当前任务",
|
|
269
|
-
"d": "勾了「回复」的插话按群成员消息处理;先等群里那行发出去再执行,插话框说明去向,提交后回报落点。"
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
"t": "飞书回答卡显示模型和额度",
|
|
273
|
-
"d": "卡片右下角的小字增加当前模型和账号额度。"
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
"t": "连不上模型、余额不足都说人话",
|
|
277
|
-
"d": "网络不通、余额不足、订阅过期在群里都有清楚的说明;连续网络失败发运维告警,账号类问题可切备用模型。"
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
"t": "续接的会话不见了会自动重做",
|
|
281
|
-
"d": "Claude 和 Codex 群都会清掉失效的会话,在新会话里重做这条,并在群里说一句。"
|
|
282
|
-
}
|
|
283
|
-
]
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
"version": "1.1.0",
|
|
287
|
-
"date": "2026-11-05",
|
|
288
|
-
"name": "Codex 忙时跟进",
|
|
289
|
-
"items": [
|
|
290
|
-
{
|
|
291
|
-
"t": "Codex 可接收任务进行中的后续消息",
|
|
292
|
-
"d": "Codex 群默认开启忙时跟进,通过 App Server 将普通真人后续消息送入当前任务;关联要求及时吸收,独立请求按序分别回应,未确认送达的消息回到队列。可按群关闭;Claude 群及定时、静默、轮询消息维持原行为。"
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
"t": "忙时跟进仅对实际 Codex 后端开放",
|
|
296
|
-
"d": "控制台按当前生效的后端显示开关,服务端也会校验;设置从下一轮开始生效。"
|
|
297
|
-
}
|
|
298
|
-
]
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
"version": "1.0.17",
|
|
302
|
-
"date": "2026-11-05",
|
|
303
|
-
"name": "安装判定和运行稳定性",
|
|
304
|
-
"items": [
|
|
305
|
-
{
|
|
306
|
-
"t": "安装后实际运行一次才算成功",
|
|
307
|
-
"d": "向导装好模型程序后会实际运行一次确认版本,文件存在或安装命令正常退出都不再算成功;校验失败时会说明原因和处理办法。"
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
"t": "体检不再把不能运行的文件当成已安装",
|
|
311
|
-
"d": "没有执行权限的文件不再被识别为可用程序。自动安装时也会带上程序运行所需的平台组件。"
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
"t": "模型程序换位置后自动找回",
|
|
315
|
-
"d": "配置的路径失效时,会在常见安装位置找同一个程序继续运行;哪里都找不到时在群里说明,并发运维告警。"
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
"t": "登录失效和异常退出说得更清楚",
|
|
319
|
-
"d": "登录令牌被吊销算账号问题,可切备用模型并告警;Codex 只输出错误就退出时也走同样的处理。"
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
"t": "修复中文偶尔乱码",
|
|
323
|
-
"d": "输出中的汉字被分块拆开时不再变成乱码。"
|
|
324
|
-
}
|
|
325
|
-
]
|
|
326
|
-
},
|
|
327
|
-
{
|
|
328
|
-
"version": "1.0.16",
|
|
329
|
-
"date": "2026-10-30",
|
|
330
|
-
"name": "AI 安装更安全,设计入口更克制",
|
|
331
|
-
"items": [
|
|
332
|
-
{
|
|
333
|
-
"t": "AI 协助安装更安全",
|
|
334
|
-
"d": "API key 在本机终端输入时会遮蔽回显,避免进入 AI 对话记录。没有交互终端时,缺少合格 Node 就停止;已有 Node 时则跳过模型配置和后台服务并说明后续步骤。"
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
"t": "安装流程与首次使用更清晰",
|
|
338
|
-
"d": "新增中英文 AI 安装与首次使用指南;一键预览会列出操作和确认项,并提示模型试跑可能消耗额度或产生费用。"
|
|
339
|
-
},
|
|
340
|
-
{
|
|
341
|
-
"t": "设计库和图标库按需展示",
|
|
342
|
-
"d": "两类资源默认折叠;仅在从零设计新产品且尚未确定视觉方向时推荐风格预设。"
|
|
343
|
-
}
|
|
344
|
-
]
|
|
345
|
-
},
|
|
346
|
-
{
|
|
347
|
-
"version": "1.0.15",
|
|
348
|
-
"date": "2026-10-30",
|
|
349
|
-
"name": "控制台设置布局更清晰",
|
|
350
|
-
"items": [
|
|
351
|
-
{
|
|
352
|
-
"t": "软件更新与版本历史合并",
|
|
353
|
-
"d": "合并为一张卡片并移到设置页底部;检测到新版时,版本号旁会显示一个提示点。"
|
|
354
|
-
},
|
|
355
|
-
{
|
|
356
|
-
"t": "机器人与网络卡片横跨整行",
|
|
357
|
-
"d": "机器人的名字和网络代理并排显示,后台网络详情可以展开查看。"
|
|
358
|
-
}
|
|
359
|
-
]
|
|
360
|
-
},
|
|
361
|
-
{
|
|
362
|
-
"version": "1.0.14",
|
|
363
|
-
"date": "2026-10-30",
|
|
364
|
-
"name": "服务重装与控制台管理更完善",
|
|
365
|
-
"items": [
|
|
366
|
-
{
|
|
367
|
-
"t": "服务重装更稳定",
|
|
368
|
-
"d": "重装时会等旧后台服务彻底退出后再启动,减少服务卡在未加载状态的情况。"
|
|
369
|
-
},
|
|
370
|
-
{
|
|
371
|
-
"t": "控制台可管理软件更新",
|
|
372
|
-
"d": "启动时及每天自动检查稳定版,也可手动检查。发现新版后由管理员确认,等所有群任务和队列空闲后再安装指定版本。"
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
"t": "访问地址可在控制台管理",
|
|
376
|
-
"d": "可以设置局域网访问密码、切换局域网监听和公网飞书登录。关闭公网登录会让现有飞书登录失效;切换监听失败时会恢复原设置。"
|
|
377
|
-
}
|
|
378
|
-
]
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
"version": "1.0.13",
|
|
382
|
-
"date": "2026-10-28",
|
|
383
|
-
"name": "安装再精简:几乎不用回答问题",
|
|
384
|
-
"items": [
|
|
385
|
-
{
|
|
386
|
-
"t": "能自动做的不再问",
|
|
387
|
-
"d": "一键安装直接升级到最新版;向导缺 Claude Code 直接装、自动选默认模型并试跑一轮,不再问要不要再加模型;Codex 和设计图标库是可选的,只给一行装法。已经登录 Claude 或 Codex 的话,整个安装只问一句要不要装后台服务。"
|
|
388
|
-
},
|
|
389
|
-
{
|
|
390
|
-
"t": "key 和代理自动带进后台服务",
|
|
391
|
-
"d": "装后台服务时,配置里引用的环境变量 key、以及终端里的代理,直接写进服务定义(文件权限 600),不再问。换了 key 或代理重跑一次 sintbot service install。"
|
|
392
|
-
},
|
|
393
|
-
{
|
|
394
|
-
"t": "输出更短",
|
|
395
|
-
"d": "安装过程不再打 npm 的进度和无害警告;后台服务装好只报一行。"
|
|
396
|
-
}
|
|
397
|
-
]
|
|
398
|
-
},
|
|
399
|
-
{
|
|
400
|
-
"version": "1.0.12",
|
|
401
|
-
"date": "2026-10-28",
|
|
402
|
-
"name": "安装更简单:终端只配模型,其余在控制台",
|
|
403
|
-
"items": [
|
|
404
|
-
{
|
|
405
|
-
"t": "终端里只配模型",
|
|
406
|
-
"d": "安装向导不再问这台机器在不在中国大陆,也不要求填代理、项目根目录和聊天平台凭据:终端里只检查环境、配好模型并当场试跑,其余装完在控制台里配。原来那一套问答保留为 sintbot setup --full,给没有浏览器的服务器用。"
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
"t": "装完就有控制台",
|
|
410
|
-
"d": "还没接聊天平台也能装后台服务:服务先只开控制台(http://127.0.0.1:4600),一键安装结束时会在浏览器里打开它。在「设置」里接好平台、保存后,服务几秒内自己重启并连上。概览页新增「开始使用」清单。"
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
"t": "控制台补上机器人名字和网络代理",
|
|
414
|
-
"d": "「设置 → 机器人与网络」可以改机器人的自称、填网络代理;装服务时也可以把终端里的代理一起带进服务。"
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
"t": "中英双语与小修",
|
|
418
|
-
"d": "安装脚本和向导按系统语言出中文或英文(macOS 看系统语言)。智谱、MiniMax 的 key 自动试出属于哪个站。已是最新版不再重装;服务在跑时 sintbot ui 直接打开它。修好向导问题被「> 」盖掉、代理直连名单里多出 *.0.1 的问题。"
|
|
419
|
-
}
|
|
420
|
-
]
|
|
421
|
-
},
|
|
422
|
-
{
|
|
423
|
-
"version": "1.0.11",
|
|
424
|
-
"date": "2026-10-26",
|
|
425
|
-
"name": "安装向导代装设计图标库",
|
|
426
|
-
"items": [
|
|
427
|
-
{
|
|
428
|
-
"t": "向导代装设计图标库",
|
|
429
|
-
"d": "安装向导发现设计图标库(Lucide、Tabler、Phosphor、Pixelarticons)没装时,会问一句要不要一次装齐(约 170 MB);装好后机器人出设计图能按名字取到标准图标,不用自己画。"
|
|
430
|
-
}
|
|
431
|
-
]
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
"version": "1.0.10",
|
|
435
|
-
"date": "2026-10-26",
|
|
436
|
-
"name": "常驻服务装得更稳",
|
|
437
|
-
"items": [
|
|
438
|
-
{
|
|
439
|
-
"t": "没接聊天平台时不装常驻服务",
|
|
440
|
-
"d": "安装时还没接飞书、Slack 或企业微信,就不再装常驻服务(装了也会一启动就退出),而是提示先在控制台里接好平台、绑群,再装服务。"
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
"t": "环境变量里的 key 能带进服务",
|
|
444
|
-
"d": "配置里的 key 取自环境变量时,装常驻服务会问一句要不要把它们写进服务定义(只有你自己能读);不写的话,服务里用这些 key 的模型用不了。"
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
"t": "说法更准",
|
|
448
|
-
"d": "试跑模型时直接显示配置里的型号,不再靠模型自报(第三方模型常自称 Claude);体检里「没配任何聊天平台」单列一行;在本机终端里试跑时,切模型的提示说清楚该怎么切。"
|
|
449
|
-
}
|
|
450
|
-
]
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
"version": "1.0.9",
|
|
454
|
-
"date": "2026-10-26",
|
|
455
|
-
"name": "安装向导更稳",
|
|
456
|
-
"items": [
|
|
457
|
-
{
|
|
458
|
-
"t": "没有终端时向导不再空转",
|
|
459
|
-
"d": "在脚本、容器或持续集成里运行安装向导、拿不到键盘输入时,向导会用默认值走完,不再在选模型那一步反复转圈、把磁盘写满,也不会自己去装 Claude Code;实在走不下去就停下提示,不写入配置。"
|
|
460
|
-
}
|
|
461
|
-
]
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
"version": "1.0.8",
|
|
465
|
-
"date": "2026-10-24",
|
|
466
|
-
"name": "控制台更好用,提炼风格更准",
|
|
467
|
-
"items": [
|
|
468
|
-
{
|
|
469
|
-
"t": "控制台「需要你处理」",
|
|
470
|
-
"d": "概览最上面汇总在等你的事:失败的任务和原因、没人认领的浏览器接管、没处理的反馈、残留的后台进程、没通过的健康检查;没事就不出现,也不往群里多发消息。"
|
|
471
|
-
},
|
|
472
|
-
{
|
|
473
|
-
"t": "实时活动重启不丢",
|
|
474
|
-
"d": "重启或升级之后,概览的实时活动会补回最近的任务记录;出错的任务直接显示原因。"
|
|
475
|
-
},
|
|
476
|
-
{
|
|
477
|
-
"t": "从参考提炼风格更准",
|
|
478
|
-
"d": "贴网址提炼时能读到网站放在其他域名上的样式表,飞书、B 站这类网站也能提炼,需要代理才能访问的网站走配置里的代理;颜色、字体和圆角读得更准,读不到的项不会改动你已经选好的。"
|
|
479
|
-
},
|
|
480
|
-
{
|
|
481
|
-
"t": "英文界面补齐",
|
|
482
|
-
"d": "控制台英文界面补全了企业微信设置、健康检查、定时任务说明等处,内置设计风格也有了英文名称和介绍。"
|
|
483
|
-
}
|
|
484
|
-
]
|
|
485
|
-
},
|
|
486
|
-
{
|
|
487
|
-
"version": "1.0.7",
|
|
488
|
-
"date": "2026-10-24",
|
|
489
|
-
"name": "首个正式版",
|
|
490
|
-
"items": [
|
|
491
|
-
{
|
|
492
|
-
"t": "群即项目",
|
|
493
|
-
"d": "一个飞书、Slack 或企业微信群绑一个项目,群里谁都能派活;每个群有自己的会话、排队和权限。"
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
"t": "模型随时换",
|
|
497
|
-
"d": "Claude、GPT(经 Codex)、DeepSeek、GLM、MiniMax 或自定义端点,每个群各选各的,群里随时切换,项目记忆不丢。"
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
"t": "进度在群里",
|
|
501
|
-
"d": "干活过程实时更新到群里的进度卡片,做完把结果发回群里。"
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
"t": "本地控制台",
|
|
505
|
-
"d": "在浏览器里管理群、模型和聊天平台,可以试跑一轮、查看版本历史;也可以开放到局域网,或经公网入口访问。"
|
|
506
|
-
},
|
|
507
|
-
{
|
|
508
|
-
"t": "上手简单",
|
|
509
|
-
"d": "一键安装;配置向导按你已有的账号推荐模型并当场试跑,体检如实报告哪些能用、哪些要修。"
|
|
510
|
-
},
|
|
511
|
-
{
|
|
512
|
-
"t": "数据留在本机",
|
|
513
|
-
"d": "项目、会话和记忆都在你自己的机器上,发到群里的消息自动脱敏。"
|
|
514
|
-
}
|
|
515
|
-
]
|
|
516
218
|
}
|
|
517
219
|
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Install SintBot 1.4.
|
|
1
|
+
# Install SintBot 1.4.11 with an AI assistant
|
|
2
2
|
|
|
3
3
|
English · [简体中文](./zh-CN/AI-ASSISTED-INSTALL.md)
|
|
4
4
|
|
|
@@ -15,5 +15,5 @@ Use the terminal on the Mac that will run SintBot. A cloud shell cannot install
|
|
|
15
15
|
## Copyable request
|
|
16
16
|
|
|
17
17
|
```text
|
|
18
|
-
Install SintBot 1.4.
|
|
18
|
+
Install SintBot 1.4.11 on this Mac using the one-line installation guide. Preserve existing services, configuration, state and Codex or Claude Code account data. Do not expose credentials. Verify the actual installed executable and binary core, configure the Feishu groups with their runners, and initialize only clean new state. Run the foreground preflight and an authorized read-only group test, check the result, then verify clean stop/restart. Stop temporary processes when finished, and distinguish package installation from successful group acceptance.
|
|
19
19
|
```
|
package/docs/install.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Install SintBot 1.4.
|
|
1
|
+
# Install SintBot 1.4.11
|
|
2
2
|
|
|
3
3
|
English · [简体中文](./zh-CN/install.md)
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ You need a Mac, Node.js 22 or newer, and projects stored on that Mac. Install an
|
|
|
10
10
|
curl -fsSL https://sintbot.com/install.sh | bash
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The installer checks the environment, installs `sintbot@1.4.
|
|
13
|
+
The installer checks the environment, installs `sintbot@1.4.11` into `~/.local/share/sintbot`, and verifies the entry, built-in core and Feishu module. Continue when you see `Installed and verified SintBot 1.4.11`. No sudo is needed.
|
|
14
14
|
|
|
15
15
|
To preview, append `-s -- --dry-run`. To choose another location, set `SINTBOT_INSTALL_DIR` and adjust the executable paths below.
|
|
16
16
|
|
|
@@ -51,7 +51,7 @@ Create a private directory with `mkdir -p ~/.sbot && chmod 700 ~/.sbot`, then cr
|
|
|
51
51
|
"provider": "codex",
|
|
52
52
|
"workdir": "/absolute/path/to/first/project",
|
|
53
53
|
"permissionMode": "dontAsk",
|
|
54
|
-
"
|
|
54
|
+
"steer": true
|
|
55
55
|
},
|
|
56
56
|
"oc_REPLACE_WITH_SECOND_CHAT_ID": {
|
|
57
57
|
"platform": "feishu",
|
|
@@ -99,9 +99,9 @@ Any text message is a task. Replies arrive in a card that appears once the model
|
|
|
99
99
|
| `/issue text` | Log feedback; review and close it in the console overview |
|
|
100
100
|
| `/help` | List commands, with this group's project and model |
|
|
101
101
|
|
|
102
|
-
Send a command as a message of its own; except for `/issue` and `/model`, do not add other text after it. If the Feishu app also subscribes to the message-recall event (the console's setup guide recommends it), recalling your own message cancels it: a queued message is dropped, and the running task stops if that message alone started it;
|
|
102
|
+
Send a command as a message of its own; except for `/issue` and `/model`, do not add other text after it. If the Feishu app also subscribes to the message-recall event (the console's setup guide recommends it), recalling your own message cancels it: a queued message is dropped, and the running task stops if that message alone started it; recalling a follow-up handed to either runner cancels the whole task, including accepted input not yet read.
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
Busy follow-ups default on for both Codex and Claude Code. Set `steer: false` to queue them instead; an explicit `steer` value overrides the legacy Codex setting. Claude Code must advertise the required input capabilities, otherwise messages stay queued. Reading can wait until a long-running tool finishes. The reply card follows confirmed reading, and continuation answers are combined into one final reply. If a turn returns a model error or no result, only that group is asked to resend; there is no automatic retry. If a group's last result cannot be confirmed, such as a reply whose delivery is unknown, only that group is paused and answers new messages with a short notice; other groups keep working. Nothing is replayed or retried.
|
|
105
105
|
|
|
106
106
|
## 6. Console
|
|
107
107
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 用 AI 助手安装 SintBot 1.4.
|
|
1
|
+
# 用 AI 助手安装 SintBot 1.4.11
|
|
2
2
|
|
|
3
3
|
[English](../AI-ASSISTED-INSTALL.md) · 简体中文
|
|
4
4
|
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
## 可复制的请求
|
|
16
16
|
|
|
17
17
|
```text
|
|
18
|
-
按一行安装指南,在这台 Mac 安装 SintBot 1.4.
|
|
18
|
+
按一行安装指南,在这台 Mac 安装 SintBot 1.4.11。保留已有服务、配置、状态和 Codex 或 Claude Code 账号数据,不输出凭据。验证实际入口与二进制核心,配置飞书群及各群的执行器,只对全新状态初始化。运行前台预检和已授权的只读群测试,对照结果,再验证正常停止与重启。完成后停止临时进程,并区分程序包安装与群验收结果。
|
|
19
19
|
```
|
package/docs/zh-CN/install.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 安装 SintBot 1.4.
|
|
1
|
+
# 安装 SintBot 1.4.11
|
|
2
2
|
|
|
3
3
|
[English](../install.md) · 简体中文
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
curl -fsSL https://sintbot.com/install.sh | bash
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
安装器会自动检查环境,把 `sintbot@1.4.
|
|
13
|
+
安装器会自动检查环境,把 `sintbot@1.4.11` 装到 `~/.local/share/sintbot`,并验证程序入口、内置核心和飞书模块。看到 `Installed and verified SintBot 1.4.11` 就可以继续。不需要 sudo。
|
|
14
14
|
|
|
15
15
|
可选预览:在命令末尾加 `-s -- --dry-run`。要自定义安装位置,设置 `SINTBOT_INSTALL_DIR` 环境变量,并同步修改后面的可执行文件路径。
|
|
16
16
|
|
|
@@ -51,7 +51,7 @@ export FEISHU_APP_ID FEISHU_APP_SECRET
|
|
|
51
51
|
"provider": "codex",
|
|
52
52
|
"workdir": "/absolute/path/to/first/project",
|
|
53
53
|
"permissionMode": "dontAsk",
|
|
54
|
-
"
|
|
54
|
+
"steer": true
|
|
55
55
|
},
|
|
56
56
|
"oc_REPLACE_WITH_SECOND_CHAT_ID": {
|
|
57
57
|
"platform": "feishu",
|
|
@@ -99,9 +99,9 @@ SINTBOT="$HOME/.local/share/sintbot/bin/sintbot"
|
|
|
99
99
|
| `/issue 一句话` | 记下问题反馈,在控制台概览里查看和标记处理 |
|
|
100
100
|
| `/help` | 查看可用命令,以及本群的项目和模型 |
|
|
101
101
|
|
|
102
|
-
命令单独发一条;除 `/issue` 和 `/model`
|
|
102
|
+
命令单独发一条;除 `/issue` 和 `/model` 外,后面不要跟别的字。如果飞书应用还订阅了消息撤回事件(控制台接入引导里建议订阅),撤回自己发的消息即取消那件事:还在排队的直接丢弃;当前任务只由这一条触发时会停下;两种执行器中,撤回已交给执行器的补话均会取消整轮,包括已受理但尚未读取的补话。
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
Codex 和 Claude Code 的忙时跟进默认开启;`steer:false` 改为排队,显式 `steer` 优先于旧 Codex 开关。Claude Code 未提供所需输入能力时保留排队。长工具调用可能延迟读取;确认读取后回复卡才跟随补话,续轮答案合并为一条最终回复。某一轮模型报错或没有结果时,只在本群提示重新发送,不会自动重试。某个群上一轮的结果无法确认时(例如回复是否送达不明),只暂停这个群,它收到新消息会回一句说明,其他群照常;不重放、不重试。
|
|
105
105
|
|
|
106
106
|
## 6. 控制台
|
|
107
107
|
|
package/install.sh
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# The function is parsed in full before installation starts, including when piped.
|
|
3
3
|
sintbot_install() (
|
|
4
4
|
set -eu
|
|
5
|
-
version=1.4.
|
|
5
|
+
version=1.4.11
|
|
6
6
|
prefix="${SINTBOT_INSTALL_DIR:-$HOME/.local/share/sintbot}"
|
|
7
7
|
fail() { printf 'SintBot: %s\n' "$*" >&2; exit 1; }
|
|
8
8
|
case "${1:-}" in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sintbot",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Drive your Mac projects from Feishu groups with Codex or Claude Code, using a built-in agent core.",
|
|
6
6
|
"bin": {
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"docs/zh-CN/install.md",
|
|
45
45
|
"install.sh",
|
|
46
46
|
"src/agent/claudecode.js",
|
|
47
|
+
"src/agent/claudefollowup.js",
|
|
47
48
|
"src/agent/claudemodels.js",
|
|
48
49
|
"src/agent/claudestatus.js",
|
|
49
50
|
"src/agent/claudeusage.js",
|
package/src/agent/claudecode.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
const { spawn } = require('node:child_process')
|
|
17
17
|
const { StringDecoder } = require('node:string_decoder')
|
|
18
|
+
const { createClaudeFollowup } = require('./claudefollowup')
|
|
18
19
|
const { ensureProxy, proxyBaseFor } = require('./visionproxy')
|
|
19
20
|
|
|
20
21
|
// Always-on 群项目基础能力: auto-allowed regardless of preset (even read-only) so the
|
|
@@ -35,7 +36,7 @@ const closedRunnerErrors = new WeakSet()
|
|
|
35
36
|
const isClosedRunnerError = error => !!error && typeof error === 'object' && closedRunnerErrors.has(error)
|
|
36
37
|
const closedError = error => { closedRunnerErrors.add(error); return error }
|
|
37
38
|
const PRE_INIT_HOOK_EVENTS = new Set(['hook_started', 'hook_response'])
|
|
38
|
-
const DURABLE_EVENT_TYPES = new Set(['system', 'assistant', 'user', 'result', 'tool_result'])
|
|
39
|
+
const DURABLE_EVENT_TYPES = new Set(['system', 'assistant', 'user', 'result', 'tool_result', 'turn_continue'])
|
|
39
40
|
// Tool output is completion evidence only, never answer text.
|
|
40
41
|
function durableToolResults(ev) {
|
|
41
42
|
const results = Array.isArray(ev.results) ? ev.results : []
|
|
@@ -152,6 +153,8 @@ function runTurn({
|
|
|
152
153
|
log = () => {}, // daemon logger — 与 codex runner 同一个口子(engine 两边都传 this.log)
|
|
153
154
|
spawnFn = spawn, // 可注入,供单测驱动 spawn/解析环路(与 codexcode 同一形状)
|
|
154
155
|
softStopGraceMs = 10000,
|
|
156
|
+
steer = false, onSteerReady, onSteerLanded,
|
|
157
|
+
steerReceiptTimeoutMs = 10000, steerHoldMs = 20000, interruptGraceMs = 2000,
|
|
155
158
|
closeGraceMs = 3000, // short: the grace starts AFTER the answer, so we're only waiting for
|
|
156
159
|
// the OS to close a possibly-clinging pipe (MCP browser children / cmd.exe shim). Claude
|
|
157
160
|
// persists its session continuously, so killing ~3s post-answer is safe → the group frees
|
|
@@ -225,7 +228,7 @@ function runTurn({
|
|
|
225
228
|
}
|
|
226
229
|
// The binary owns the permission, tool allow/deny and argument policy.
|
|
227
230
|
// Node only resolves capability and writes the project-scoped MCP file.
|
|
228
|
-
const args = claudeBuildArgs({ model, providerModel: provider.model, sessionId,
|
|
231
|
+
const args = claudeBuildArgs({ steer, model, providerModel: provider.model, sessionId,
|
|
229
232
|
permissionMode, autocompactTokens, autocompactSupported,
|
|
230
233
|
mcpConfigPath, allowedTools, pluginAllows, disallowedTools,
|
|
231
234
|
appendSystemPrompt, workdir })
|
|
@@ -242,8 +245,14 @@ function runTurn({
|
|
|
242
245
|
// Feed the prompt over stdin instead of as an argv element: cross-platform,
|
|
243
246
|
// and it removes ALL Windows argv/cmd.exe escaping risk for arbitrary chat
|
|
244
247
|
// text (quotes, &, |, %, newlines). Close stdin so `claude -p` starts.
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
let followup = null
|
|
249
|
+
let stdinOpen = true
|
|
250
|
+
const endStdin = () => { if (stdinOpen) { stdinOpen = false; child.stdin.end() } }
|
|
251
|
+
const writeFrame = frame => {
|
|
252
|
+
if (!stdinOpen || childCloseObserved) throw new Error('Claude input is closed')
|
|
253
|
+
child.stdin.write(JSON.stringify(frame) + '\n')
|
|
254
|
+
}
|
|
255
|
+
child.stdin.on('error', error => { if (steer && !settled) followup?.fail(error) })
|
|
247
256
|
|
|
248
257
|
let capturedSessionId = sessionId || null
|
|
249
258
|
let lastResult = null
|
|
@@ -265,7 +274,7 @@ function runTurn({
|
|
|
265
274
|
// Resolution is guarded (exactly once) because a close-grace timer can force the
|
|
266
275
|
// turn to settle before the 'close' event fires — otherwise a lingering pipe would
|
|
267
276
|
// wedge the per-group lock forever (never-hang invariant).
|
|
268
|
-
const finish = (fn) => { if (settled) return; settled = true; if (killTimer) clearTimeout(killTimer); if (closeTimer) clearTimeout(closeTimer); if (signal) signal.removeEventListener('abort', onAbort); fn() }
|
|
277
|
+
const finish = (fn) => { if (settled) return; settled = true; followup?.dispose(); if (killTimer) clearTimeout(killTimer); if (closeTimer) clearTimeout(closeTimer); if (signal) signal.removeEventListener('abort', onAbort); fn() }
|
|
269
278
|
const resolveRun = result => {
|
|
270
279
|
if (childCloseObserved) closedRunnerResults.add(result)
|
|
271
280
|
resolve(result)
|
|
@@ -332,12 +341,21 @@ function runTurn({
|
|
|
332
341
|
// Windows has no POSIX signals, and killing the cmd.exe shim would orphan
|
|
333
342
|
// the real claude process underneath. taskkill /T /F ends the whole tree.
|
|
334
343
|
try { spawn('taskkill', ['/pid', String(child.pid), '/t', '/f'], { stdio: 'ignore', windowsHide: true }) } catch {}
|
|
344
|
+
} else if (followup && stdinOpen) {
|
|
345
|
+
try { followup.stop() } catch { /* close proof remains authoritative */ }
|
|
346
|
+
killTimer = setTimeout(() => {
|
|
347
|
+
try { child.kill('SIGTERM') } catch {}
|
|
348
|
+
killTimer = setTimeout(() => { try { child.kill('SIGKILL') } catch {} }, softStopGraceMs)
|
|
349
|
+
}, interruptGraceMs)
|
|
335
350
|
} else {
|
|
336
351
|
try { child.kill('SIGTERM') } catch { /* already gone */ }
|
|
337
352
|
killTimer = setTimeout(() => { try { child.kill('SIGKILL') } catch {} }, softStopGraceMs)
|
|
338
353
|
}
|
|
339
354
|
armCloseGrace() // even after a kill, 'close' can hang on a clinging pipe — bound it
|
|
340
355
|
}
|
|
356
|
+
if (steer) followup = createClaudeFollowup({ write: writeFrame, end: endStdin,
|
|
357
|
+
onReady: onSteerReady, onLanded: onSteerLanded, onFailure: failDurableEvent,
|
|
358
|
+
receiptTimeoutMs: steerReceiptTimeoutMs, holdMs: steerHoldMs })
|
|
341
359
|
if (signal) {
|
|
342
360
|
if (signal.aborted) onAbort()
|
|
343
361
|
else signal.addEventListener('abort', onAbort, { once: true })
|
|
@@ -370,6 +388,7 @@ function runTurn({
|
|
|
370
388
|
if (!line) continue
|
|
371
389
|
let raw
|
|
372
390
|
try { raw = JSON.parse(line) } catch { continue } // skip non-JSON noise
|
|
391
|
+
if (followup && followup.protocol(raw)) continue
|
|
373
392
|
if (onTurnAccepted && !turnAccepted) {
|
|
374
393
|
// Locally configured session hooks report their own lifecycle before
|
|
375
394
|
// init. They are not model output; skip them and keep waiting.
|
|
@@ -396,6 +415,9 @@ function runTurn({
|
|
|
396
415
|
}
|
|
397
416
|
turnAccepted = true
|
|
398
417
|
}
|
|
418
|
+
if (followup && raw.type === 'system' && raw.subtype === 'init') {
|
|
419
|
+
if (followup.init(raw) === 'unavailable') log('当前模型程序未提供忙时跟进能力,本轮后续消息排队')
|
|
420
|
+
}
|
|
399
421
|
// key 错快速失败(1.0.3):claude 对 401 / 403 默认重试约 3 分钟才放弃,第一次重试时(实测 0.8 秒)就会先报一条
|
|
400
422
|
// `system/api_retry` 带 error_status。只对 API key 型模型(有 baseUrl)当场收尾 —— 订阅登录的 401 可能是
|
|
401
423
|
// Claude Code 自己在刷新登录,让它重试;5xx / 529 这类过载照旧重试。造一条出错 result 交给上层:账号类失败
|
|
@@ -423,6 +445,10 @@ function runTurn({
|
|
|
423
445
|
const last = lastMsgUsage || (ev.usage && Array.isArray(ev.usage.iterations) ? ev.usage.iterations[ev.usage.iterations.length - 1] : null)
|
|
424
446
|
if (last) ev.contextTokens = (last.input_tokens || 0) + (last.cache_read_input_tokens || 0) + (last.cache_creation_input_tokens || 0)
|
|
425
447
|
}
|
|
448
|
+
if (followup && !aborted && ev.type === 'result') {
|
|
449
|
+
ev = followup.result(ev)
|
|
450
|
+
if (ev.type === 'turn_continue') lastMsgUsage = null
|
|
451
|
+
}
|
|
426
452
|
// Only transcript events reach the durable projection. Informational
|
|
427
453
|
// stream additions (for example rate_limit_event) carry no answer.
|
|
428
454
|
// Claude reports several tool results per event, with array content
|
|
@@ -455,6 +481,10 @@ function runTurn({
|
|
|
455
481
|
}))
|
|
456
482
|
|
|
457
483
|
const completeClose = (code) => finish(() => {
|
|
484
|
+
if (onDurableEvent && turnAccepted && !lastResult && !aborted) {
|
|
485
|
+
resolveRun({ sessionId: capturedSessionId, result: null, code, aborted })
|
|
486
|
+
return
|
|
487
|
+
}
|
|
458
488
|
if (code !== 0 && !lastResult && !aborted) {
|
|
459
489
|
return reject(closedError(new Error(`claude exited ${code}: ${stderr.trim().slice(0, 800) || '(no stderr)'}`)))
|
|
460
490
|
}
|
|
@@ -465,6 +495,10 @@ function runTurn({
|
|
|
465
495
|
if (onDurableEvent) durableWork.then(() => { if (!durableFailed) completeClose(code) })
|
|
466
496
|
else completeClose(code)
|
|
467
497
|
})
|
|
498
|
+
if (!aborted) {
|
|
499
|
+
if (followup) followup.start(prompt)
|
|
500
|
+
else child.stdin.end(prompt)
|
|
501
|
+
}
|
|
468
502
|
}
|
|
469
503
|
})
|
|
470
504
|
}
|