sintbot 1.4.6 → 1.4.7

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 CHANGED
@@ -1,4 +1,19 @@
1
1
  [
2
+ {
3
+ "version": "1.4.7",
4
+ "date": "2026-11-09",
5
+ "name": "/stop no longer pauses the group",
6
+ "items": [
7
+ {
8
+ "t": "Fix: /stop during a task could pause the whole group",
9
+ "d": "/stop removes the task's reply card, and Feishu then reports that removal as a recall. When it arrived while \"stopped\" was still being sent, it was treated as a fault: the group was paused until an administrator released it, and later /model and /new were refused. The recall now waits for that reply to finish and the group keeps serving."
10
+ },
11
+ {
12
+ "t": "Fix: recalling a queued message could pause the group",
13
+ "d": "Recalling a message while its \"queued\" notice was still being sent also paused the whole group; the message is now cancelled once the notice has been sent."
14
+ }
15
+ ]
16
+ },
2
17
  {
3
18
  "version": "1.4.6",
4
19
  "date": "2026-11-09",
package/CHANGELOG.json CHANGED
@@ -1,4 +1,19 @@
1
1
  [
2
+ {
3
+ "version": "1.4.7",
4
+ "date": "2026-11-09",
5
+ "name": "/stop 后群不再被暂停",
6
+ "items": [
7
+ {
8
+ "t": "修复:任务进行中发 /stop,群可能被整个暂停",
9
+ "d": "/stop 会删掉这条任务的回复卡片,飞书随后把这次删除当作一次撤回通知回来;若它恰好在「已停止」还在发送时到达,此前会被当成故障,群被暂停、要管理员人工解封,后面的 /model、/new 也都不响应。现在会等那条回复发完再处理,群照常服务。"
10
+ },
11
+ {
12
+ "t": "修复:撤回排队中的消息时群可能被暂停",
13
+ "d": "在「已排队」提示还在发送时撤回那条消息,此前也会让整群暂停;现在等提示发完再取消那条消息。"
14
+ }
15
+ ]
16
+ },
2
17
  {
3
18
  "version": "1.4.6",
4
19
  "date": "2026-11-09",
@@ -1,4 +1,4 @@
1
- # Install SintBot 1.4.6 with an AI assistant
1
+ # Install SintBot 1.4.7 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.6 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.
18
+ Install SintBot 1.4.7 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.6
1
+ # Install SintBot 1.4.7
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.6` into `~/.local/share/sintbot`, and verifies the entry, built-in core and Feishu module. Continue when you see `Installed and verified SintBot 1.4.6`. No sudo is needed.
13
+ The installer checks the environment, installs `sintbot@1.4.7` into `~/.local/share/sintbot`, and verifies the entry, built-in core and Feishu module. Continue when you see `Installed and verified SintBot 1.4.7`. 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
 
@@ -1,4 +1,4 @@
1
- # 用 AI 助手安装 SintBot 1.4.6
1
+ # 用 AI 助手安装 SintBot 1.4.7
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.6。保留已有服务、配置、状态和 Codex 或 Claude Code 账号数据,不输出凭据。验证实际入口与二进制核心,配置飞书群及各群的执行器,只对全新状态初始化。运行前台预检和已授权的只读群测试,对照结果,再验证正常停止与重启。完成后停止临时进程,并区分程序包安装与群验收结果。
18
+ 按一行安装指南,在这台 Mac 安装 SintBot 1.4.7。保留已有服务、配置、状态和 Codex 或 Claude Code 账号数据,不输出凭据。验证实际入口与二进制核心,配置飞书群及各群的执行器,只对全新状态初始化。运行前台预检和已授权的只读群测试,对照结果,再验证正常停止与重启。完成后停止临时进程,并区分程序包安装与群验收结果。
19
19
  ```
@@ -1,4 +1,4 @@
1
- # 安装 SintBot 1.4.6
1
+ # 安装 SintBot 1.4.7
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.6` 装到 `~/.local/share/sintbot`,并验证程序入口、内置核心和飞书模块。看到 `Installed and verified SintBot 1.4.6` 就可以继续。不需要 sudo。
13
+ 安装器会自动检查环境,把 `sintbot@1.4.7` 装到 `~/.local/share/sintbot`,并验证程序入口、内置核心和飞书模块。看到 `Installed and verified SintBot 1.4.7` 就可以继续。不需要 sudo。
14
14
 
15
15
  可选预览:在命令末尾加 `-s -- --dry-run`。要自定义安装位置,设置 `SINTBOT_INSTALL_DIR` 环境变量,并同步修改后面的可执行文件路径。
16
16
 
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.6
5
+ version=1.4.7
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.6",
3
+ "version": "1.4.7",
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": {
@@ -324,7 +324,18 @@ function createC2MultiGroupService({ routes, assertWriterLock,
324
324
  return { ignored: true, reason: `unsupported-${source}` }
325
325
  }
326
326
  }
327
- function recall(event) {
327
+ // A reply or card update awaiting its platform response blocks the durable
328
+ // authority only for that moment. The bot's own card deleted by /stop or
329
+ // /skip comes back as a recall exactly then, and a person may recall a
330
+ // queued message while its queue notice is still on its way. The recall
331
+ // waits for that effect to settle; only an authority closed for good after
332
+ // the recall is a fault. The platform does not await this result, so the
333
+ // wait never rejects.
334
+ const RECALL_WAIT_MS = 60_000
335
+ const RECALL_POLL_MS = 25
336
+ const closedForGood = runtime => (runtime?.closed ?? runtime?.blocked) === true
337
+ const effectInFlight = runtime => runtime?.blocked === true && runtime?.closed === false
338
+ function recall(event, waitedMs = 0) {
328
339
  if (suspended.has(event?.chatId)) return { ignored: true, reason: 'group-held' }
329
340
  if (maintenance) return { ignored: true, reason: 'upgrading' }
330
341
  if (!allowed(event?.chatId)) return { ignored: true }
@@ -333,8 +344,20 @@ function createC2MultiGroupService({ routes, assertWriterLock,
333
344
  held()
334
345
  binding = bindings.get(event.chatId)
335
346
  if (!started || stopPromise || !binding) return { ignored: true, reason: 'ingress-closed' }
347
+ if (effectInFlight(binding.runtime)) {
348
+ if (waitedMs >= RECALL_WAIT_MS) {
349
+ log(`group ${event.chatId}: recall not applied; an outbound effect stayed in flight`)
350
+ return { ignored: true, reason: 'recall-effect-in-flight' }
351
+ }
352
+ return new Promise(resolve => setTimeout(resolve, RECALL_POLL_MS))
353
+ .then(() => recall(event, waitedMs + RECALL_POLL_MS))
354
+ .catch(error => {
355
+ log(`group ${event.chatId}: deferred recall failed: ${reasonOf(error)}`)
356
+ return { ignored: true, reason: 'recall-failed' }
357
+ })
358
+ }
336
359
  const handled = binding.engine.handleRecall?.(event) === true
337
- if (binding.runtime?.blocked) throw new Error('Recall closed its durable authority')
360
+ if (closedForGood(binding.runtime)) throw new Error('Recall closed its durable authority')
338
361
  return handled ? { handled: true } : { ignored: true, reason: 'unsupported-or-inactive-recall' }
339
362
  } catch (error) {
340
363
  if (!binding || !writerHeld() || !started || stopPromise) return fatal(error)