sintbot 1.4.11 → 1.4.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/CHANGELOG.en.json CHANGED
@@ -1,4 +1,58 @@
1
1
  [
2
+ {
3
+ "version": "1.4.13",
4
+ "date": "2026-11-10",
5
+ "name": "Reliability and task follow-up improvements",
6
+ "items": [
7
+ {
8
+ "t": "Restore Claude Code health information",
9
+ "d": "Visible Claude Code models show executor version and probe results. Hidden models do not trigger extra probes."
10
+ },
11
+ {
12
+ "t": "Retry failed upgrades safely",
13
+ "d": "Keep failed installations for inspection. Retry in a separate directory and verify before switching, without overwriting existing installations."
14
+ },
15
+ {
16
+ "t": "Align runtime version, model and capability information",
17
+ "d": "Each turn receives the running service version and its exact tool entry. Distinguish service, global installation and available updates; consistently resolve group model overrides and defaults."
18
+ },
19
+ {
20
+ "t": "Read locally retained group replies",
21
+ "d": "Look up this group’s recorded replies by source message or turn, with explicit provenance, status, truncation and retention limits. Unreadable Feishu cards are never reconstructed by guesswork."
22
+ },
23
+ {
24
+ "t": "Apply concurrency and maintenance checks to trials",
25
+ "d": "Allow one console trial within shared model capacity. Refuse starts during maintenance, abort and skip saving after writer loss, and retain capacity when process closure is unknown."
26
+ },
27
+ {
28
+ "t": "Handle early timeout callbacks",
29
+ "d": "If a timer callback arrives before the deadline, wait for the remaining interval. Abort only with elapsed-time evidence so a normal timeout is not misclassified as a fault."
30
+ },
31
+ {
32
+ "t": "Send console messages while a task is running",
33
+ "d": "Project messages use the same followup or queue path as group messages. The console distinguishes acceptance, waiting for the model to read, and confirmed joining; repeated submissions are deduplicated."
34
+ },
35
+ {
36
+ "t": "Continue output after moving a reply card",
37
+ "d": "Busy follow-ups preserve already displayed text on the relocated card, then stream subsequent output without replaying the old text. Updates arriving during the move and the final answer remain ordered."
38
+ }
39
+ ]
40
+ },
41
+ {
42
+ "version": "1.4.12",
43
+ "date": "2026-11-10",
44
+ "name": "Projects and live activity",
45
+ "items": [
46
+ {
47
+ "t": "Projects, concurrency and context in one panel",
48
+ "d": "Show project paths, runtime, configured reasoning and context together; restore row icon actions and display task tools, reply and compact metrics after selecting a group. Remove the top available-controls notice."
49
+ },
50
+ {
51
+ "t": "Actual task details and reported context",
52
+ "d": "Shows requests, follow-ups, progress, replies and the latest reported context. Reuses existing events without extra model calls; details load on demand and restored samples are labeled historical."
53
+ }
54
+ ]
55
+ },
2
56
  {
3
57
  "version": "1.4.11",
4
58
  "date": "2026-11-10",
package/CHANGELOG.json CHANGED
@@ -1,4 +1,58 @@
1
1
  [
2
+ {
3
+ "version": "1.4.13",
4
+ "date": "2026-11-10",
5
+ "name": "可靠性与任务跟进体验",
6
+ "items": [
7
+ {
8
+ "t": "恢复 Claude Code 健康信息",
9
+ "d": "可见的 Claude Code 模型显示执行器版本与探测结果;主动隐藏的模型不额外探测。"
10
+ },
11
+ {
12
+ "t": "升级失败可重新尝试",
13
+ "d": "失败安装保留供排查;重试使用独立目录,校验后才能切换,不覆盖已有安装。"
14
+ },
15
+ {
16
+ "t": "统一运行版本、模型与能力说明",
17
+ "d": "每轮注入当前服务版本和准确工具入口,区分服务、全局安装与可用更新;群模型覆盖和执行器默认值统一展示。"
18
+ },
19
+ {
20
+ "t": "读取本群已保存答复",
21
+ "d": "可按消息或轮次读取本机保存的答复,明确来源、状态、截断与保留范围,不补造不可读的飞书卡片。"
22
+ },
23
+ {
24
+ "t": "试运行纳入并发与维护准入",
25
+ "d": "最多一项控制台试运行,共享模型并发名额;维护时拒绝启动,失去写入权限后中止且不保存结果,进程关闭未知时保留名额。"
26
+ },
27
+ {
28
+ "t": "修正硬超时提前触发",
29
+ "d": "计时回调早于截止时间时继续等待;获得超时证明后才中止任务,避免正常超时被误判为异常收尾。"
30
+ },
31
+ {
32
+ "t": "任务进行中可从控制台插话",
33
+ "d": "群项目列表不再因任务忙碌禁用插话;沿用群内跟进或排队流程,区分已受理、等待模型读取与已加入,重复提交不重复处理。"
34
+ },
35
+ {
36
+ "t": "卡片移位后接续输出",
37
+ "d": "收到忙时补充后,新卡直接保留已显示内容,后续输出继续追加,避免旧内容从头打字;移位期间的新内容和最终结果保持顺序。"
38
+ }
39
+ ]
40
+ },
41
+ {
42
+ "version": "1.4.12",
43
+ "date": "2026-11-10",
44
+ "name": "群项目与实时活动",
45
+ "items": [
46
+ {
47
+ "t": "群项目、并发与上下文集中展示",
48
+ "d": "群项目、运行耗时、项目路径、模型思考深度与上下文集中展示;恢复群行图标操作,选择群后查看任务,详情采用工具标签、回复正文和紧凑统计。 移除顶部当前可用操作说明卡片。"
49
+ },
50
+ {
51
+ "t": "真实任务详情与可信上下文",
52
+ "d": "展示请求、补话、进度、回复及最近上报的上下文。使用既有事件,不额外请求模型;详情按需加载,重启后历史采样明确标注。"
53
+ }
54
+ ]
55
+ },
2
56
  {
3
57
  "version": "1.4.11",
4
58
  "date": "2026-11-10",
package/bin/sintbot-v2.js CHANGED
@@ -114,6 +114,7 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
114
114
  let configControl
115
115
  let updater
116
116
  let liveTransport
117
+ let activity
117
118
  let onSigint, onSigterm
118
119
  try {
119
120
  const migrationFence = require('../src/c2migration').loadC2MigrationFence({ stateDir, routes })
@@ -139,6 +140,9 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
139
140
  // All group Engines must share this exact object: separate Store caches
140
141
  // would overwrite sibling sessions when they save the same state file.
141
142
  const store = new StateStore(path.join(stateDir, 'state.json'))
143
+ activity = require('../src/ui/liveactivity').createLiveActivity({
144
+ file: path.join(stateDir, 'activity-v1.json'), canWrite: assertWriterLock,
145
+ log: message => process.stderr.write(`Console · ${message}\n`) })
142
146
  const closeChecks = {
143
147
  claude: require('../src/agent/claudecode').isClosedRunnerResult,
144
148
  'codex-exec': require('../src/agent/codexcode').isClosedRunnerResult,
@@ -154,11 +158,12 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
154
158
  const limits = { maxEventCount: 100_000, maxJournalBytes: 64 * 1024 * 1024,
155
159
  maxCompletionEvents: 1_000, maxCompletionBytes: 8 * 1024 * 1024 }
156
160
  let finishing = false
157
- const finish = result => {
161
+ const finish = async result => {
158
162
  if (finishing) return
159
163
  finishing = true
160
164
  ui?.close()
161
165
  updater?.close()
166
+ await activity?.close()
162
167
  lock.release()
163
168
  process.stderr.write(`C2 multi-group · ${result.reason}; platform stopped=${result.platformStopped}; runner drained=${result.drained}\n`,
164
169
  () => process.exit(result.code))
@@ -230,7 +235,7 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
230
235
  return result
231
236
  }
232
237
  engine = new Engine({ ...cfg, groups: { [route.chatId]: route.group } }, {
233
- store, log: message => process.stderr.write(`C2 v2 · ${message}\n`),
238
+ store, activity, log: message => process.stderr.write(`C2 v2 · ${message}\n`),
234
239
  durableV2Runtime: runtime, durableV2Payloads: handles,
235
240
  durableV2StartTurn: startTurn, durableV2ApplyLocalEffect: applyLocalEffect,
236
241
  durableV2VerifyRunnerClosed: ({ result, error }) => result
@@ -249,6 +254,8 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
249
254
  },
250
255
  durableV2UsageProbe: usageProbe, durableV2Issues: issues,
251
256
  durableV2Version: require('../package.json').version,
257
+ durableV2DataDir: stateDir,
258
+ durableV2ConsoleEnabled: uiEnabled,
252
259
  durableV2NormalRoute: true, durableV2StreamFrames: streamFrames(cfg) })
253
260
  return { journal, gate, runtime, engine, handles }
254
261
  } catch (error) { gate.stop(); throw error }
@@ -284,9 +291,10 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
284
291
  process.on('SIGTERM', onSigterm)
285
292
  if (uiEnabled && !preflightOnly) {
286
293
  ui = require('../src/c2console').createC2Console({
287
- configPath: cfg._path, stateDir, host: uiHost,
294
+ configPath: cfg._path, stateDir, host: uiHost, activity, store,
288
295
  getConfig: () => cfg, getBindings: () => service.bindings,
289
296
  getHeld: () => service.held, getCapacity: () => capacity.snapshot(),
297
+ acquireCapacity: options => capacity.acquire(options),
290
298
  getConnHealth: () => liveTransport?.platform.connHealth?.() || {},
291
299
  // Console injection enters through the same ingress as a group
292
300
  // message, posted and answered with that group's own adapter.
@@ -339,6 +347,7 @@ async function startMultiGroupService({ installation, preflightOnly, uiEnabled =
339
347
  throw error
340
348
  } finally {
341
349
  if (!running) {
350
+ await activity?.close()
342
351
  updater?.close()
343
352
  if (onSigint) process.off('SIGINT', onSigint)
344
353
  if (onSigterm) process.off('SIGTERM', onSigterm)
@@ -1,4 +1,4 @@
1
- # Install SintBot 1.4.11 with an AI assistant
1
+ # Install SintBot 1.4.13 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.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.
18
+ Install SintBot 1.4.13 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.11
1
+ # Install SintBot 1.4.13
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.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.
13
+ The installer checks the environment, installs `sintbot@1.4.13` into `~/.local/share/sintbot`, and verifies the entry, built-in core and Feishu module. Continue when you see `Installed and verified SintBot 1.4.13`. 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
 
@@ -103,11 +103,21 @@ Send a command as a message of its own; except for `/issue` and `/model`, do not
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
+ When the reply card moves below a confirmed follow-up, its existing text is shown immediately and subsequent output continues from that point. Moving the card does not restart the task.
107
+
106
108
  ## 6. Console
107
109
 
108
- With `--ui`, open `http://127.0.0.1:4600` on this Mac. The console shows each group (a paused group shows Needs attention), stops tasks, starts a new conversation for an idle group, binds new groups, switches the model or project folder of an idle group, and adds or configures models. For LAN access, set a console password in its settings first, then enable LAN access.
110
+ The overview combines group projects and concurrency. Each row shows the runner, state and elapsed time, project folder, model and configured reasoning effort, and the latest reported context usage. Select a group to view its tasks, then expand a task for tools, reply and usage. Context is a session sample, not cumulative token consumption; unknown capacity and older samples are labeled. Row icons provide console messages, stop and new-session controls according to the current group state.
111
+
112
+ With `--ui`, open `http://127.0.0.1:4600` on this Mac. The console shows each group, stops tasks, starts a new conversation for an idle group, binds new groups, switches the model or project folder of an idle group, and adds or configures models. For LAN access, set a console password in its settings first, then enable LAN access.
113
+
114
+ The Message action also works while a group is busy. It follows the group’s follow-up setting: the message waits for model reading or joins the queue. “Accepted” does not yet confirm that the model has read it. New sessions and model changes still require an idle group.
115
+
116
+ Settings → Software updates checks for new releases. In the foreground setup above it shows the upgrade steps: press Ctrl-C and wait for exit, rerun the one-line installer, then start again with the same command. If your own launchd agent starts SintBot, Upgrade now waits until every group is idle and settled, installs the new version into an isolated release directory and switches the agent to it; if the new version does not connect every group within 90 seconds, the previous one is restored. A window shows each step, reconnects by itself while the service restarts and can be left running in the background. On the first start after an upgrade, each serving group gets one card listing what changed; to turn this off, clear "Announce upgrades in groups" under The Message action also works while a group is busy. It follows the group’s follow-up setting: the message waits for model reading or joins the queue. “Accepted” does not yet confirm that the model has read it. New sessions and model changes still require an idle group.
117
+
118
+ Settings → Software updates.
109
119
 
110
- Settings → Software updates checks for new releases. In the foreground setup above it shows the upgrade steps: press Ctrl-C and wait for exit, rerun the one-line installer, then start again with the same command. If your own launchd agent starts SintBot, Upgrade now waits until every group is idle and settled, installs the new version into `~/.local/share/sintbot/releases/<version>` and switches the agent to it; if the new version does not connect every group within 90 seconds, the previous one is restored. A window shows each step, reconnects by itself while the service restarts and can be left running in the background. On the first start after an upgrade, each serving group gets one card listing what changed; to turn this off, clear "Announce upgrades in groups" under Settings → Software updates.
120
+ If an installation fails, retry uses a fresh directory and preserves the failed attempt for diagnosis. It switches only after verification.
111
121
 
112
122
  You can also add a group without the console: add it to the configuration, stop the service and run `start` again; the new group is registered automatically. Bound groups cannot be removed or renamed by editing the configuration.
113
123
 
@@ -1,4 +1,4 @@
1
- # 用 AI 助手安装 SintBot 1.4.11
1
+ # 用 AI 助手安装 SintBot 1.4.13
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.11。保留已有服务、配置、状态和 Codex 或 Claude Code 账号数据,不输出凭据。验证实际入口与二进制核心,配置飞书群及各群的执行器,只对全新状态初始化。运行前台预检和已授权的只读群测试,对照结果,再验证正常停止与重启。完成后停止临时进程,并区分程序包安装与群验收结果。
18
+ 按一行安装指南,在这台 Mac 安装 SintBot 1.4.13。保留已有服务、配置、状态和 Codex 或 Claude Code 账号数据,不输出凭据。验证实际入口与二进制核心,配置飞书群及各群的执行器,只对全新状态初始化。运行前台预检和已授权的只读群测试,对照结果,再验证正常停止与重启。完成后停止临时进程,并区分程序包安装与群验收结果。
19
19
  ```
@@ -1,4 +1,4 @@
1
- # 安装 SintBot 1.4.11
1
+ # 安装 SintBot 1.4.13
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.11` 装到 `~/.local/share/sintbot`,并验证程序入口、内置核心和飞书模块。看到 `Installed and verified SintBot 1.4.11` 就可以继续。不需要 sudo。
13
+ 安装器会自动检查环境,把 `sintbot@1.4.13` 装到 `~/.local/share/sintbot`,并验证程序入口、内置核心和飞书模块。看到 `Installed and verified SintBot 1.4.13` 就可以继续。不需要 sudo。
14
14
 
15
15
  可选预览:在命令末尾加 `-s -- --dry-run`。要自定义安装位置,设置 `SINTBOT_INSTALL_DIR` 环境变量,并同步修改后面的可执行文件路径。
16
16
 
@@ -103,14 +103,22 @@ SINTBOT="$HOME/.local/share/sintbot/bin/sintbot"
103
103
 
104
104
  Codex 和 Claude Code 的忙时跟进默认开启;`steer:false` 改为排队,显式 `steer` 优先于旧 Codex 开关。Claude Code 未提供所需输入能力时保留排队。长工具调用可能延迟读取;确认读取后回复卡才跟随补话,续轮答案合并为一条最终回复。某一轮模型报错或没有结果时,只在本群提示重新发送,不会自动重试。某个群上一轮的结果无法确认时(例如回复是否送达不明),只暂停这个群,它收到新消息会回一句说明,其他群照常;不重放、不重试。
105
105
 
106
+ 回复卡移到已确认读取的补话下方时,会立即保留已有文字,后续输出继续更新;移动卡片不会重新启动任务。
107
+
106
108
  ## 6. 控制台
107
109
 
108
- 带 `--ui` 启动后,在本机浏览器打开 `http://127.0.0.1:4600`。控制台可以查看各群状态(暂停的群显示「需要处理」)、停止任务、给空闲的群开新会话、绑定新群、给空闲的群切换模型或项目目录、添加和设置模型。要从局域网访问,先在控制台的设置里设访问密码,再开启局域网访问。
110
+ 概览合并群项目与并发信息,每行显示执行器、状态与耗时、项目目录、模型和配置的思考深度、最近上报的上下文用量。选择群后查看对应任务,展开任务查看工具、回复和用量。上下文是当前会话采样,不是累计消耗;容量未知或历史采样会明确标注。群行图标按当前状态提供插话、停止与新会话操作。
111
+
112
+ 带 `--ui` 启动后,在本机浏览器打开 `http://127.0.0.1:4600`。控制台可以查看各群状态、停止任务、给空闲的群开新会话、绑定新群、给空闲的群切换模型或项目目录、添加和设置模型。要从局域网访问,先在控制台的设置里设访问密码,再开启局域网访问。
109
113
 
110
- 「设置 → 软件更新」会检查新版本。按上面前台方式运行时,卡片给出升级步骤:按 Ctrl-C 等待退出,重新运行一行安装命令,再用原来的命令启动。如果用你自己的 launchd 后台任务启动 SintBot,「现在升级」会等所有群空闲、记录结清后,把新版本装到 `~/.local/share/sintbot/releases/<版本>` 并切换过去;新版本 90 秒内没连上全部群会自动换回旧版。升级时窗口逐步显示进度,服务重启时页面自动重连,也可以放到后台继续。升级后首次启动会在每个在服务的群发一张版本公告卡,列出这一版的更新;不想播报就在「设置 → 软件更新」取消「升级后向群里播报」。
114
+ 群忙时也可以使用控制台「插话」:按本群跟进设置,等待模型读取或进入队列。「已受理」不代表模型已经读取。新会话与模型切换仍需等待群空闲。
115
+
116
+ 「设置 → 软件更新」会检查新版本。按上面前台方式运行时,卡片给出升级步骤:按 Ctrl-C 等待退出,重新运行一行安装命令,再用原来的命令启动。如果用你自己的 launchd 后台任务启动 SintBot,「现在升级」会等所有群空闲、记录结清后,把新版本装到独立的发行目录并切换过去;新版本 90 秒内没连上全部群会自动换回旧版。升级时窗口逐步显示进度,服务重启时页面自动重连,也可以放到后台继续。升级后首次启动会在每个在服务的群发一张版本公告卡,列出这一版的更新;不想播报就在「设置 → 软件更新」取消「升级后向群里播报」。
111
117
 
112
118
  不用控制台也能加群:在配置里加上新群,停止后重新 `start` 即可,新群会自动登记。已绑定的群不能通过改配置删除或改名。
113
119
 
120
+ 升级安装失败后可重新尝试:重试使用新目录,保留失败产物供排查,校验成功后才切换。
121
+
114
122
  ## 停止与重启
115
123
 
116
124
  按 Ctrl-C 并等待退出。确认飞书环境变量已设置,再执行:
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.11
5
+ version=1.4.13
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.11",
3
+ "version": "1.4.13",
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": {
@@ -69,6 +69,7 @@
69
69
  "src/cdp.js",
70
70
  "src/config.js",
71
71
  "src/consolesay.js",
72
+ "src/consoletrials.js",
72
73
  "src/core/c2cardeffectbridge.js",
73
74
  "src/core/c2cardterminalpath.js",
74
75
  "src/core/c2durableingress.js",
@@ -113,6 +114,7 @@
113
114
  "src/feishucli.js",
114
115
  "src/gitrepo.js",
115
116
  "src/leftover.js",
117
+ "src/modelcontext.js",
116
118
  "src/platform/board.js",
117
119
  "src/platform/feishu.js",
118
120
  "src/platform/multi.js",
@@ -128,6 +130,8 @@
128
130
  "src/preview.js",
129
131
  "src/projectmemory.js",
130
132
  "src/projectsroot.js",
133
+ "src/recordedanswers.js",
134
+ "src/runtimefacts.js",
131
135
  "src/setupmodels.js",
132
136
  "src/ui/auth.js",
133
137
  "src/ui/browser.html",
@@ -135,6 +139,8 @@
135
139
  "src/ui/console.html",
136
140
  "src/ui/dashboard.js",
137
141
  "src/ui/feishulogin.js",
142
+ "src/ui/liveactivity-client.js",
143
+ "src/ui/liveactivity.js",
138
144
  "src/ui/serverbase.js",
139
145
  "src/ui/sessions.js",
140
146
  "src/ui/takeover.js",
@@ -229,6 +229,8 @@ function runTurn({
229
229
  // The binary owns the permission, tool allow/deny and argument policy.
230
230
  // Node only resolves capability and writes the project-scoped MCP file.
231
231
  const args = claudeBuildArgs({ steer, model, providerModel: provider.model, sessionId,
232
+ runtimeCommand: extraEnv?.SBOT_RUNTIME_ENTRY
233
+ ? require('../runtimefacts').runtimeCommand(extraEnv.SBOT_RUNTIME_ENTRY) : '',
232
234
  permissionMode, autocompactTokens, autocompactSupported,
233
235
  mcpConfigPath, allowedTools, pluginAllows, disallowedTools,
234
236
  appendSystemPrompt, workdir })
@@ -439,6 +441,10 @@ function runTurn({
439
441
  ev.contextTokens = (lastMsgUsage.input_tokens || 0) + (lastMsgUsage.cache_read_input_tokens || 0) + (lastMsgUsage.cache_creation_input_tokens || 0)
440
442
  }
441
443
  if (ev.type === 'result') {
444
+ const windows = Object.values(raw.modelUsage || {}).map(value => value?.contextWindow)
445
+ // No model-name guesses; a single reported capacity is unambiguous.
446
+ if (windows.length && windows.every(value => Number.isFinite(value) && value > 0) &&
447
+ new Set(windows).size === 1) ev.contextWindowTokens = windows[0]
442
448
  // 当前上下文规模 = 最后一次 API 请求的输入侧总量(未命中 + 缓存读 + 缓存写)。
443
449
  // result.usage 是整轮跨请求聚合、不能当上下文用;逐请求数在 assistant 事件的
444
450
  // message.usage 里(2.1.222 真机核对),兜底走 usage.iterations 末元素(同一形状)。
@@ -143,6 +143,9 @@ function runTurn(opts = {}) {
143
143
  totalUsage = usageFromTotal(usage.total)
144
144
  if (Number.isFinite(usage.last && usage.last.inputTokens) && usage.last.inputTokens > 0) contextTokens = usage.last.inputTokens
145
145
  if (Number.isFinite(usage.modelContextWindow) && usage.modelContextWindow > 0) contextWindowTokens = usage.modelContextWindow
146
+ // Observational only: do not add telemetry to the durable transcript.
147
+ if (!completed && contextTokens > 0) legacyEmit({ type: 'system', subtype: 'context',
148
+ sessionId: capturedSessionId, contextTokens, contextWindowTokens })
146
149
  }
147
150
  const write = (obj) => {
148
151
  if (child.stdin.destroyed) throw new Error('codex app-server stdin closed')
@@ -402,7 +405,8 @@ function runTurn(opts = {}) {
402
405
  const next = appDeltaNext(messageDeltas.get(params.itemId) || '', delta)
403
406
  if (next !== null) {
404
407
  messageDeltas.set(params.itemId, next)
405
- emit({ type: 'assistant', text: delta, contextTokens })
408
+ emit({ type: 'assistant', text: delta,
409
+ ...(contextTokens > 0 ? { contextTokens, contextWindowTokens, contextSampled: false } : {}) })
406
410
  }
407
411
  } else if (action === 4) {
408
412
  const item = params.item
@@ -3,7 +3,7 @@ const fs = require('node:fs')
3
3
  const path = require('node:path')
4
4
  const { createHash } = require('node:crypto')
5
5
 
6
- const EXPECTED_SHA256 = '9c29c9123b38aa75b9c47066c809d844f938baca41779372b77c02fa7baa9989'
6
+ const EXPECTED_SHA256 = 'a7ad2bd9210906ee6f5d7893ed3d9632769b6e2dbec285c1102492e3ba1257b5'
7
7
  let bytes
8
8
  try {
9
9
  bytes = fs.readFileSync(path.join(__dirname, 'privatecore.wasm'))
Binary file
@@ -17,4 +17,6 @@ function runTurn(opts) {
17
17
  return claudeAgent.runTurn(opts)
18
18
  }
19
19
 
20
- module.exports = { runTurn, probeVersion: claudeAgent.probeVersion }
20
+ const isClosedRunnerResult = value => [claudeAgent, codexAgent, codexApp].some(agent => agent.isClosedRunnerResult(value))
21
+ const isClosedRunnerError = value => [claudeAgent, codexAgent, codexApp].some(agent => agent.isClosedRunnerError(value))
22
+ module.exports = { runTurn, probeVersion: claudeAgent.probeVersion, isClosedRunnerResult, isClosedRunnerError }