@keyou007/agent-bot 0.1.24-alpha.4 → 0.1.24-alpha.5

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +15 -3
  3. package/README.zh.md +15 -3
  4. package/dist/codex/AppServerPermissions.js +34 -0
  5. package/dist/codex/AppServerPermissions.js.map +1 -0
  6. package/dist/codex/CodexLocalActivityDetector.js +37 -5
  7. package/dist/codex/CodexLocalActivityDetector.js.map +1 -1
  8. package/dist/codex/CodexRuntime.js +37 -13
  9. package/dist/codex/CodexRuntime.js.map +1 -1
  10. package/dist/codex/ThreadWriterProcess.js +19 -5
  11. package/dist/codex/ThreadWriterProcess.js.map +1 -1
  12. package/dist/feishu/CardRenderer.js +80 -64
  13. package/dist/feishu/CardRenderer.js.map +1 -1
  14. package/dist/local-files/CsvPreview.js +148 -0
  15. package/dist/local-files/CsvPreview.js.map +1 -0
  16. package/dist/local-files/LocalFileViewerServer.js +53 -10
  17. package/dist/local-files/LocalFileViewerServer.js.map +1 -1
  18. package/dist/local-files/TurnPreviewPage.js +122 -11
  19. package/dist/local-files/TurnPreviewPage.js.map +1 -1
  20. package/dist/presentation/TurnStateReducer.js +39 -0
  21. package/dist/presentation/TurnStateReducer.js.map +1 -1
  22. package/dist/proxy/ProxySessionController.js +152 -46
  23. package/dist/proxy/ProxySessionController.js.map +1 -1
  24. package/docs/technical-reference.md +5 -3
  25. package/docs/technical-reference.zh.md +4 -2
  26. package/npm-shrinkwrap.json +2 -2
  27. package/package.json +1 -1
  28. package/skills/agent-bot/SKILL.md +6 -0
  29. package/src/codex/AppServerPermissions.ts +39 -0
  30. package/src/codex/CodexLocalActivityDetector.ts +34 -4
  31. package/src/codex/CodexRuntime.ts +44 -17
  32. package/src/codex/ThreadWriterProcess.ts +17 -9
  33. package/src/feishu/CardRenderer.ts +78 -64
  34. package/src/local-files/CsvPreview.ts +132 -0
  35. package/src/local-files/LocalFileViewerServer.ts +54 -11
  36. package/src/local-files/TurnPreviewPage.ts +125 -12
  37. package/src/presentation/TurnStateReducer.ts +41 -0
  38. package/src/presentation/turnViewTypes.ts +4 -0
  39. package/src/proxy/ProxySessionController.ts +137 -48
  40. package/src/runtime/types.ts +2 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,39 @@ The project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.24-alpha.5] - 2026-09-24
10
+
11
+ ### 中文
12
+
13
+ - 修复权限切换未同步沙箱策略的问题:下一轮同时应用审批与沙箱设置,无需重启 Agent、Fork 或新建任务,并保留工作区沙箱配置。
14
+ - 修复崩溃后任务持续显示运行中的问题:核实存活写入进程,限制未确认恢复的重试时间,提示写锁冲突,不中断其他客户端任务。
15
+ - Session 列表为运行中任务提供独立 Stop 按钮,发送正常停止信号,保留任务绑定、搜索条件和分页。
16
+ - 支持 CSV 只读表格预览,支持引号内逗号与换行、空单元格,并对超大文件和格式错误给出提示。
17
+ - Markdown 文件预览支持 Mermaid/流程图,提供预览、源码及原大、适应切换,实时更新保留图表状态。
18
+ - Turn Preview 最终回答旁新增下载和复制图标,以原始 Markdown 格式导出,支持局域网 HTTP 页面的复制回退。
19
+ - 简化命令授权卡片:先显示原因,命令默认折叠,过长内容可在 Preview 查看完整原文;授权操作保持不变。
20
+ - Turn Preview 顶部显示上下文大小及按有效 Token 用量更新次数统计的模型调用次数,上下文位于模型调用前面,不再显示压缩统计;支持局部实时更新,不额外读取历史。
21
+
22
+ ### English
23
+
24
+ - Apply both approval and sandbox policies on every App Server Turn start so permission switches take effect on the next Turn without an Agent restart or task replacement. Preserve workspace sandbox options and fail closed when configuration or policy validation fails.
25
+
26
+ - Show per-turn model call counts in Turn Preview headers using effective token-usage updates, with duplicate/regression filtering, cached-usage support, persisted baselines, and live metadata-only updates. Keep Feishu cards unchanged and avoid additional Agent history reads.
27
+
28
+ - Make command approval cards compact: show a short heading and the reason before a collapsed command, avoid repeated command titles, and provide the full original command in read-only Turn Preview. Keep all approval decisions and callbacks unchanged.
29
+
30
+ - Support Mermaid/flowchart diagrams in Markdown file previews using Turn Preview's local renderer, Preview/Source and Actual size/Fit controls, safe source fallback, and preserved diagram state across live file updates.
31
+
32
+ - Add download/copy icon buttons beside Turn Preview's final answer to export original UTF-8 Markdown, with clipboard fallback for HTTP/LAN pages, accessible feedback, and support for live-arriving and historical answers.
33
+
34
+ - Add a direct Stop button to running task details in `/sessions`, including the current task, other Agent Bot tasks, and external tasks. Send the normal interrupt without changing task bindings, preserve search/pagination, and keep running status until the Agent reports completion. Hide unavailable Archive actions while running to keep ten-task cards within Feishu limits.
35
+
36
+ - Preview CSV files as read-only, scrollable tables with row/column labels, safe quoted-field parsing, existing text-encoding support, bounded rendering, code/raw/download access, and preserved scroll positions on live updates.
37
+
38
+ - Fix crash recovery leaving stale tasks running: verify live Codex writers, confirm resume before replacing progress cards, report writer conflicts, and bound unconfirmed recovery retries without interrupting external or already-confirmed live work.
39
+
40
+ - Show the latest reported context token count immediately before model calls in Turn Preview headers, with live incremental updates and exact counts on hover; hide compaction statistics and leave missing context values hidden.
41
+
9
42
  ## [0.1.24-alpha.4] - 2026-09-23
10
43
 
11
44
  ### 中文
package/README.md CHANGED
@@ -292,7 +292,7 @@ Only groups explicitly enabled with `/mute` or `/mute on` supplement ordinary @-
292
292
 
293
293
  `/file` accepts relative paths, absolute paths, and paths beginning with `~`; relative paths resolve from the current task directory.
294
294
 
295
- `/fork` and `/forkgroup` branch from completed work without interrupting a running turn. `/sessions` manages tasks across projects and Providers in pages of up to 10 tasks; switching Provider does not hide a task from the list or search. Use each project menu for `New` and `NewGroup`. Each task’s `SwitchGroup` action creates a new group bound to that same task, preserving its history, title, and execution settings without creating or forking an Agent task. The original conversation stays unchanged. An Agent Bot Turn already in progress keeps replying to its original conversation; new messages from the new group queue until it finishes. Tasks running in an external client cannot be switched until they finish. Expanding a task directly shows the first 50 characters of its latest user Prompt, its update time, and task-specific actions. Use `Turns` to view that task’s history without switching tasks, including tasks not yet bound to Agent Bot; non-current tasks are read-only until you switch to them. `/turns` restores conversation context without reverting local files.
295
+ `/fork` and `/forkgroup` branch from completed work without interrupting a running turn. `/sessions` manages tasks across projects and Providers in pages of up to 10 tasks; switching Provider does not hide a task from the list or search. Use each project menu for `New` and `NewGroup`. Each task’s `SwitchGroup` action creates a new group bound to that same task, preserving its history, title, and execution settings without creating or forking an Agent task. The original conversation stays unchanged. An Agent Bot Turn already in progress keeps replying to its original conversation; new messages from the new group queue until it finishes. Tasks running in an external client cannot be switched until they finish. Expanding a task directly shows the first 50 characters of its latest user Prompt, its update time, and task-specific actions. Running tasks also show a direct `Stop` button, including the current task and tasks running in other conversations or external clients. It sends the normal Agent interrupt without switching tasks or killing processes. The list refresh preserves search and pagination and keeps Stop available until the Agent reports the task idle; Archive is available only when idle. Use `Turns` to view that task’s history without switching tasks, including tasks not yet bound to Agent Bot; non-current tasks are read-only until you switch to them. `/turns` restores conversation context without reverting local files.
296
296
 
297
297
  `/turn` and `/turns` are equivalent. Without an argument they open the history card; `/turn 3` uses its one-based, newest-first index (including a running Turn at the top), and `/turn <Turn ID>` selects a Turn in the current task's history. Viewing details does not Reset, resume, stop, or switch tasks. Saved IDs are read directly; missing history is located through summary pages, stopping at the requested index or the page containing the ID. Fork lookups stay within inherited history. Details show the saved Prompt, status, timing, activities, and results, with Preview when configured; summary-only external Turns cannot show tool activity that Agent Bot never recorded.
298
298
 
@@ -328,7 +328,7 @@ Relative file links in Feishu answers and thinking cards, such as `outputs/repor
328
328
 
329
329
  `/status` cards also include **Preview** beside Refresh and Stop/Switch. It opens the active Turn, or the latest Turn when idle, and updates its target when you refresh the card. For external tasks not yet recorded by Agent Bot, opening Preview loads the selected Turn from the Agent and caches its full execution details. Read failures can be retried by refreshing the page. The button is hidden if there is no Turn, no supported history reader, or the file viewer is unavailable. Viewing another task’s status does not switch or take over that task.
330
330
 
331
- Progress cards include a `Preview` button that opens the saved Turn timeline in a compact, mobile-friendly browser view. Reasoning panels use the content title as their collapsed header and show the text directly on expansion. Tool blocks have a single collapse level and start collapsed with a meaningful one-line command summary, a compact duration (`58s` or `2:32`), and completion status. Expanding a block shows the full command prefixed by `$`, followed directly by its results, images, and changed files. Identical output/error logs appear once. Running Turns update live by patching changed sections in place, preserving expanded or collapsed steps, scroll positions, and unchanged image elements instead of reloading them. Token and other metadata updates do not replace the timeline. Collapsed tool steps and the file-change summary initially contain only their headers; commands, logs, images, and file lists are fetched on expansion. Reopening reuses loaded content, and live updates refresh only expanded details whose content changed. Failed loads offer Retry. Finished Turns do not open a live SSE connection. The waiting-for-progress placeholder is hidden once a response or other visible progress is available, and is never shown for finished Turns. Click a file in the file changes or tool file list to preview its current contents in a new tab; deleted or unavailable files remain plain text. Turn previews use the same signed viewer address and access rules as local file links.
331
+ Progress cards include a `Preview` button that opens the saved Turn timeline in a compact, mobile-friendly browser view. Reasoning panels use the content title as their collapsed header and show the text directly on expansion. Tool blocks have a single collapse level and start collapsed with a meaningful one-line command summary, a compact duration (`58s` or `2:32`), and completion status. Expanding a block shows the full command prefixed by `$`, followed directly by its results, images, and changed files. Identical output/error logs appear once. Running Turns update live by patching changed sections in place, preserving expanded or collapsed steps, scroll positions, and unchanged image elements instead of reloading them. Token and other metadata updates do not replace the timeline. Collapsed tool steps and the file-change summary initially contain only their headers; commands, logs, images, and file lists are fetched on expansion. Reopening reuses loaded content, and live updates refresh only expanded details whose content changed. Failed loads offer Retry. Finished Turns do not open a live SSE connection. The waiting-for-progress placeholder is hidden once a response or other visible progress is available, and is never shown for finished Turns. Click a file in the file changes or tool file list to preview its current contents in a new tab; deleted or unavailable files remain plain text. Turn previews use the same signed viewer address and access rules as local file links. Beside Final answer, download and copy icons export the original Markdown (including formatting, code blocks, and unchanged link targets), not the rendered HTML. Download saves a UTF-8 `.md` file; Copy uses the clipboard with a fallback for HTTP/LAN previews and shows success or failure feedback. Both work on completed pages and when the final answer arrives live.
332
332
 
333
333
  Opening `/turn <ID or index>` or Preview for an imported summary loads that Turn's execution details from its original Agent session and caches the result. Only summary pages and the selected Turn's full record are requested, never the entire full history; source tasks are not resumed or interrupted. Read failures show their reason separately from the Turn's execution status; reopen the details or refresh Preview to retry. Existing detailed snapshots remain unchanged, and unavailable historical timing or token data is not estimated.
334
334
 
@@ -336,7 +336,7 @@ Turn Preview highlights fenced code blocks in common languages such as JavaScrip
336
336
 
337
337
  Turn Preview retains complete recorded execution content without repeatedly saving the whole Turn to the database. Live previews update incrementally; collapsed tools load their full details when opened. Back up the entire Profile data directory to keep execution records as well as task metadata. Existing saved history remains readable.
338
338
 
339
- Mermaid diagrams in Turn Preview have **Preview / Source** controls and default to Preview. Use a `mermaid` fenced code block with `flowchart` or `graph` syntax (`flowchart` fences are also accepted). Your mode selection survives live updates; invalid or incomplete diagrams fall back to source. Rendering runs locally in your browser, without sending diagram content to an external service. Diagrams scale down to the available width by default without enlarging small diagrams. On phones, the preview is capped at roughly half the screen height; scroll vertically for long flows. Use **Actual size / Fit** to inspect details or return to the fitted view. Live updates preserve this choice.
339
+ Mermaid diagrams in Turn Preview and Markdown file previews have **Preview / Source** controls and default to Preview. Use a `mermaid` fenced code block with `flowchart` or `graph` syntax (`flowchart` fences are also accepted). Your mode selection survives live updates; invalid or incomplete diagrams fall back to source. Rendering runs locally in your browser, without sending diagram content to an external service. Diagrams scale down to the available width by default without enlarging small diagrams. On phones, the preview is capped at roughly half the screen height; scroll vertically for long flows. Use **Actual size / Fit** to inspect details or return to the fitted view. Live updates preserve this choice.
340
340
 
341
341
  The compact Turn Preview header uses dot-separated values, keeps the duration label, and abbreviates token counts with K, M, and B units. It wraps to fit narrow screens. Prompt, Commentary, and result text use a regular weight and a slightly larger font than tool calls. Tool commands and outputs preserve line breaks and indentation; long lines scroll horizontally within the tool block without wrapping. Commands and results share one scroll area capped at 30 lines in height. The page reserves space for classic vertical scrollbars so expanding or collapsing tools does not shift the header or timeline horizontally. Thin, subtle scrollbars have no arrow buttons. On desktop they appear on hover or keyboard focus; on touch devices they are hidden while gesture scrolling remains available.
342
342
 
@@ -346,6 +346,8 @@ When an App Server reports only `Read` or `Grep` as the command, available actio
346
346
 
347
347
  Tool titles start with the same status icons as the thinking card: an hourglass while running, a check mark on success, or a cross on failure. Running blocks have an accent border. Header summaries omit shell line-continuation markers while preserving file paths and the full expanded command. Durations remain hidden at zero seconds. The expanded footer shows the execution status, start time, duration, and result character count outside the scroll area; running durations update live in both the header and footer.
348
348
 
349
+ Command approval cards use a short heading and show the reason first, with the command in a collapsed panel instead of repeating it as a long bold title. The summary omits recognized shell wrappers, but the expanded command retains them. Oversized commands and reasons show an explicit truncation notice; check the complete original command in Turn Preview before authorizing. The four approval actions and their permission scope are unchanged. Preview remains read-only and preserves command expansion and scroll position during live updates.
350
+
349
351
  TraeX plan-mode confirmations appear on the existing progress card as **Waiting for approval**, with the plan text and `Approve Plan` (or `Enter Plan Mode`), `Reject`, and `Cancel Request` actions. They require an explicit decision even with automatic permissions; cancelling the request is not the same as stopping the task. Turn Preview shows the plan and pending confirmation but remains read-only: respond in Feishu. Waiting turns remain active and continue to block safe restart until they finish or are explicitly stopped. Notifications missed by an older running version cannot be recovered automatically by this adaptation.
350
352
 
351
353
  Local images in Turn Preview Prompts, Commentary, and results load through signed file URLs, including live updates. Relative image paths resolve from the task's project directory.
@@ -354,8 +356,12 @@ Attached images from initial and appended user messages are saved with the Turn
354
356
 
355
357
  The Turn Preview header shows **Processing** during both normal processing and tool execution; tool details and other status labels are unchanged.
356
358
 
359
+ The header hides compaction statistics and shows **Context** in tokens immediately before **Model calls** (before the tool count when model calls are unavailable) using the Agent's latest reported context size for that Turn, not cumulative token consumption or the model's capacity. It updates in place, including decreases after compaction when reported; hover for the exact count. Historical Turns show their saved value. Missing or invalid values stay hidden, without estimating from other token counts or fetching history.
360
+
357
361
  Turn Preview shows the Provider before the model recorded for each Turn, without a visible Provider prefix. Changing settings affects subsequent Turns, not the running Turn or earlier Turns. Older snapshots without a recorded Provider leave it hidden rather than using the task's current settings.
358
362
 
363
+ The header also shows **Model calls** for the Turn, counting effective token-usage updates: the first positive usage report counts once, and subsequent cumulative increases count once each. Total tokens including cache take precedence, with non-cached usage as a fallback. Duplicate, regressing, invalid, and context-only updates do not add calls. Counts update in place and persist across restarts; Feishu thinking cards are unchanged. Saved Preview events can reconstruct the count during normal replay, but incomplete old snapshots or Agents without usage reports leave it hidden; no additional Agent history or rollout scan is performed.
364
+
359
365
  When reported by the Agent, Turn Preview shows this Turn's total tokens (input plus output, including cached input) alongside the existing non-cached count. The separate cache-hit token count is hidden; underlying token accounting is unchanged. Values update live, use compact units, and show exact counts on hover. Duplicate usage notifications are not counted twice. Missing breakdowns and older snapshots are not estimated or backfilled from task history; Feishu card token counts keep their existing calculation.
360
366
 
361
367
  Markdown previews keep table cells at their content width. Wide tables scroll horizontally within the preview instead of squeezing columns on narrow screens, and live updates preserve each table's horizontal scroll position.
@@ -364,8 +370,12 @@ Local links in rendered Markdown open signed viewer pages for the referenced fil
364
370
 
365
371
  HTML files (`.html` and `.htm`) open in preview mode with a code toggle, line anchors, and live updates. Self-contained HTML can use inline styles, inline scripts, and embedded media inside an isolated frame. External resources, relative local assets, network requests, forms, and access to the outer viewer are not enabled. The rendered document is complete; only the code view is limited to the first 2 MiB.
366
372
 
373
+ CSV files (`.csv`, case-insensitive) open as read-only tables with row numbers, column letters, sticky labels, and horizontal/vertical scrolling. The first row remains data, not an inferred header. Standard comma-separated fields support quoted commas, escaped quotes, embedded newlines, empty cells, and UTF-8/UTF-16 BOM or GB18030 text decoding; numeric strings and formulas remain plain text. Preview reads at most the first 2 MiB and displays up to 500 records, 50 columns, and 4,000 characters per cell, with explicit truncation or malformed-quote notices. Incomplete records at the byte boundary are omitted. The code view displays up to 2,000 physical lines; raw/download links preserve the entire original file. Live updates retain the selected view and table scroll position.
374
+
367
375
  Provider, model, reasoning effort, and permission choices apply to the current task and are also saved under that Agent's `defaults`. If an older configuration has no `defaults` section for that Agent, it is created automatically on the first change. Future tasks that have no same-Agent settings to inherit start with those saved defaults; each configured Agent keeps its own values.
368
376
 
377
+ For App Server tasks, permission changes apply both approval and sandbox policies on the next Turn: `auto` uses no sandbox and no approval prompts; `confirm` uses the workspace-write sandbox and on-request approval. Choose the mode in `/permissions`, or use `agentbot task permissions auto|confirm`. Switching requires no Agent restart, fork, or new task and does not change already-running tool processes or steering requests. Workspace writable roots, network access, and temporary-directory exclusions retain the Agent's configured values.
378
+
369
379
  The execution settings card ends with a one-sentence Markdown blockquote for the selected tab's scope and timing. Agent selection changes only the default for new tasks in that conversation, without migrating the current task. Model, reasoning, and permission changes apply from the next turn. Agent and Provider options show their identifiers without duplicate display names, while retaining current/default indicators. `/provider` opens this card even when only one Provider is available, keeping the Model, Thinking, and Permission tabs accessible.
370
380
 
371
381
  Provider changes require an idle task. Wait for an active turn to finish, or stop it before switching. For a custom Provider, Agent Bot uses its OpenAI-compatible `/models` endpoint when available and shows only that Provider's models. A switch keeps the previous model when the target supports it, otherwise selects the target's default model or its first returned model. Providers without a model-list endpoint remain usable: Agent Bot keeps the current or configured model as the single fallback candidate and lets Codex apply it. Agent Bot unloads only the selected idle thread, resumes it with the resolved Provider and model, and verifies both before saving settings or reporting success. A known fresh, empty thread may be replaced while keeping its task identity, title, and directory; forked or resumed tasks are not treated as empty merely because they have no new messages. If a switch fails, the previous settings are retained and remote recovery is attempted. If recovery also fails, further turns are blocked until a Provider switch succeeds.
@@ -400,6 +410,8 @@ File-change summaries display paths as plain text, preserving Windows separators
400
410
 
401
411
  ## Troubleshooting
402
412
 
413
+ After a crash, an unfinished Codex rollout alone no longer means the task is running: unloaded threads also require a live writer process. Agent Bot confirms session resume before creating a new running card. Writer conflicts stop automatic recovery with an occupancy card; other unconfirmed recovery failures are retried every five seconds for a one-minute window, then marked interrupted with a notification. No external process is closed automatically. Already-confirmed live turns remain monitored, including during temporary connection outages, and are not subject to this recovery timeout.
414
+
403
415
  - **The bot does not respond:** run `agentbot server status` and check today's `~/.agent-bot/logs/agent-bot.YYYY-MM-DD.log`
404
416
  - **The Worker restarted after a Node crash:** check `~/.agent-bot/data/last-crash.json`, that day's `~/.agent-bot/logs/worker.stderr.YYYY-MM-DD.log`, and `~/.agent-bot/data/crash-reports/`
405
417
  - **Feishu permissions are incomplete:** rerun `agentbot init` and follow the displayed authorization steps
package/README.zh.md CHANGED
@@ -293,7 +293,7 @@ Fork 只记录来源任务和分支轮次,不同步完整历史。普通任务
293
293
 
294
294
  `/file` 支持相对路径、绝对路径和以 `~` 开头的用户目录路径;相对路径以当前任务目录为基准。
295
295
 
296
- `/fork` 和 `/forkgroup` 会从已完成的工作创建分支,不会中断正在执行的轮次。`/sessions` 用于跨项目、跨 Provider 管理任务,每页最多显示 10 个任务;切换 Provider 不会让任务从列表或搜索结果中消失。项目菜单提供 `New` 和 `NewGroup`。每个任务的 `SwitchGroup` 会创建新群并绑定同一个任务,保留历史、标题和运行设置,不创建新 Agent 任务,也不 fork,原会话绑定不变。若任务正在 Agent Bot 中执行,本轮回复仍留在原会话,新群发来的消息先排队;正在外部客户端执行的任务需要等待完成后再切换。展开任务后会直接显示最后一个用户 Prompt 的前 50 个字符、更新时间以及任务级操作。点击 `Turns` 可查看对应任务的轮次,包括尚未绑定到 Agent Bot 的任务,不会切换当前任务;非当前任务仅供查看,需要先切换任务才能 Reset。`/turns` 用于恢复对话上下文,不会回退本地文件。
296
+ `/fork` 和 `/forkgroup` 会从已完成的工作创建分支,不会中断正在执行的轮次。`/sessions` 用于跨项目、跨 Provider 管理任务,每页最多显示 10 个任务;切换 Provider 不会让任务从列表或搜索结果中消失。项目菜单提供 `New` 和 `NewGroup`。每个任务的 `SwitchGroup` 会创建新群并绑定同一个任务,保留历史、标题和运行设置,不创建新 Agent 任务,也不 fork,原会话绑定不变。若任务正在 Agent Bot 中执行,本轮回复仍留在原会话,新群发来的消息先排队;正在外部客户端执行的任务需要等待完成后再切换。展开任务后会直接显示最后一个用户 Prompt 的前 50 个字符、更新时间以及任务级操作。运行中任务还会显示独立的 `Stop` 按钮,包括当前任务、其他会话和外部客户端中的任务;点击发送正常的 Agent 中断信号,不切换任务、不结束进程。列表刷新保留搜索条件和页码,并根据 Agent 的实际状态保留或移除 Stop;空闲后才提供 Archive。点击 `Turns` 可查看对应任务的轮次,包括尚未绑定到 Agent Bot 的任务,不会切换当前任务;非当前任务仅供查看,需要先切换任务才能 Reset。`/turns` 用于恢复对话上下文,不会回退本地文件。
297
297
 
298
298
  发送 `/update` 可同时检查最新正式版和 Alpha 版,查看更新简介后,点击 **Update <版本号>** 选择更新。更新简介优先显示对应版本的中文内容(包括随包提供的已发布版本译文),没有中文时回退原文。只有配置的机器人所有者可以执行安装;仅检查不会安装。已安装或低于当前版本的版本不提供更新按钮。下载校验在后台进行,随后等待任务和最终回复完成,再安全重启;失败时沿用现有回滚保护。关闭自动检查后仍可使用此命令;源码或 `npm link` 安装只能查看版本,不能原地更新。选择过期或下载失败后,请重新发送 `/update`。
299
299
 
@@ -323,7 +323,7 @@ Agent Bot 将用户相关文件保存在仓库之外:
323
323
 
324
324
  `/status` 状态卡片底部也提供 **Preview**,与 Refresh、Stop/Switch 放在同一行。点击可查看正在执行的轮次,空闲时则查看最近一轮;刷新卡片后会更新目标。对于尚未被 Agent Bot 记录的外部任务,打开 Preview 时会从 Agent 按需读取所选轮次并缓存完整执行详情;读取失败可刷新页面重试。没有轮次、无法读取历史且无本地记录,或文件预览服务不可用时不显示按钮。查看其他任务的状态不会切换或接管任务。
325
325
 
326
- 思考卡片底部操作区提供 `Preview` 按钮,可在浏览器中查看本轮已保存的执行时间线,采用紧凑布局并适配手机,思考块直接以内容标题作为折叠标题,展开后显示内容。工具块只有一级折叠,默认只显示有意义的单行命令摘要、简短耗时(如 `58s` 或 `2:32`)和完成状态。展开后先显示以 `$` 开头的完整命令,随后直接显示结果、图片和修改文件。相同的输出和错误日志只显示一次。执行中的 Turn 会通过局部更新实时显示变化,保留手动展开状态、滚动位置和未变化的图片节点,避免图片反复加载;Token 等元数据更新不会替换时间线。折叠工具块和文件变更汇总首屏只加载摘要,展开时才请求命令、日志、图片和文件列表;再次展开复用已加载内容,运行中只刷新已展开且内容变化的详情,加载失败可点击重试。已结束的 Turn 不再建立 SSE 实时连接。“正在等待 Agent 返回进度”只在尚无可显示进度时出现,已有回答、其他可见进展或 Turn 已结束时不再显示。点击文件变更列表或工具文件列表中的文件,可在新标签页预览其当前内容;已删除或不可用的文件保留为路径文字。Turn Preview 与本地文件链接共用相同的签名、访问地址和网络范围。
326
+ 思考卡片底部操作区提供 `Preview` 按钮,可在浏览器中查看本轮已保存的执行时间线,采用紧凑布局并适配手机,思考块直接以内容标题作为折叠标题,展开后显示内容。工具块只有一级折叠,默认只显示有意义的单行命令摘要、简短耗时(如 `58s` 或 `2:32`)和完成状态。展开后先显示以 `$` 开头的完整命令,随后直接显示结果、图片和修改文件。相同的输出和错误日志只显示一次。执行中的 Turn 会通过局部更新实时显示变化,保留手动展开状态、滚动位置和未变化的图片节点,避免图片反复加载;Token 等元数据更新不会替换时间线。折叠工具块和文件变更汇总首屏只加载摘要,展开时才请求命令、日志、图片和文件列表;再次展开复用已加载内容,运行中只刷新已展开且内容变化的详情,加载失败可点击重试。已结束的 Turn 不再建立 SSE 实时连接。“正在等待 Agent 返回进度”只在尚无可显示进度时出现,已有回答、其他可见进展或 Turn 已结束时不再显示。点击文件变更列表或工具文件列表中的文件,可在新标签页预览其当前内容;已删除或不可用的文件保留为路径文字。Turn Preview 与本地文件链接共用相同的签名、访问地址和网络范围。“最终回答”旁提供下载、复制两个图标,导出原始 Markdown(保留格式、代码块和原始链接),而非渲染后的网页内容。下载为 UTF-8 `.md` 文件;复制支持 HTTP/局域网页面的回退方式,并显示成功或失败提示。已结束页面及实时到达的最终回答均可使用。
327
327
 
328
328
  Turn Preview 完整保留已记录的执行内容,不再反复把整轮内容写入数据库。页面按增量实时更新,折叠工具展开时加载完整详情。备份时请保留整个 Profile 数据目录,以同时保存执行记录和任务信息;已有历史仍可查看。
329
329
 
@@ -331,7 +331,7 @@ Turn Preview 完整保留已记录的执行内容,不再反复把整轮内容
331
331
 
332
332
  Turn Preview 支持 JavaScript/TypeScript、Python、Shell/PowerShell、JSON/YAML、SQL、HTML/CSS、Go、Rust、Java、C/C++ 等常见语言的代码块高亮,配色跟随系统浅色/深色主题。在代码块开头指定语言即可;未指定、未知语言或超大代码块仍完整显示为纯文本。行内代码和工具日志保持原样。
333
333
 
334
- Turn Preview 中的 Mermaid 图表支持「预览 / 源码」切换,默认显示预览。使用 `mermaid` 代码块和 `flowchart` 或 `graph` 语法即可,也支持 `flowchart` 代码块。实时更新会保留手动选择的模式;语法错误或尚未完整的图表会回退到源码。图表在本地浏览器中渲染,不上传外部服务;图表默认按可用宽度等比缩小,不会放大小图。手机端预览高度最多约半屏,长图可纵向滑动;点击「原大 / 适应」可查看细节或恢复适配,实时更新会保留该选择。
334
+ Turn Preview 和 Markdown 文件预览中的 Mermaid 图表支持「预览 / 源码」切换,默认显示预览。使用 `mermaid` 代码块和 `flowchart` 或 `graph` 语法即可,也支持 `flowchart` 代码块。实时更新会保留手动选择的模式;语法错误或尚未完整的图表会回退到源码。图表在本地浏览器中渲染,不上传外部服务;图表默认按可用宽度等比缩小,不会放大小图。手机端预览高度最多约半屏,长图可纵向滑动;点击「原大 / 适应」可查看细节或恢复适配,实时更新会保留该选择。
335
335
 
336
336
  Turn Preview 顶部用点分隔各项信息,保留“耗时”标签,Token 数量使用 K、M、B 单位简写,窄屏下自动换行。Prompt、Commentary 和结果正文使用普通字重,字号比工具调用大一号。展开后的工具命令和输出保留换行与缩进,长行在工具块内横向滚动,不自动折行。命令和结果共用一个最多 30 行高的滚动区域。页面为占宽度的竖向滚动条预留空间,展开或收起工具时,顶部和正文不再左右跳动。滚动条采用无箭头的浅色细条,鼠标设备上悬停或键盘聚焦时显示,触屏设备隐藏滚动条,仍可用手势滚动。
337
337
 
@@ -341,6 +341,8 @@ Turn Preview 顶部用点分隔各项信息,保留“耗时”标签,Token
341
341
 
342
342
  工具标题开头使用与思考卡片相同的状态图标:执行中为沙漏,成功为对号,失败为叉号;执行中的工具边框突出显示。标题摘要省略命令续行符,保留文件路径和展开后的完整命令。时长为 0 秒时隐藏。展开后的底部显示执行状态、开始时间、耗时和结果字符数,不随内容滚动;执行中标题和底部的耗时都会实时更新。
343
343
 
344
+ 命令授权卡片使用简短的“命令执行确认”标题,优先显示申请原因,命令放入默认折叠的区域,不再把整条命令重复显示为加粗标题。摘要省略可识别的 Shell 包装,展开后仍保留原始包装。命令或说明超长时明确提示截断,请在 Turn Preview 查看完整原始命令后再授权。四个授权操作及其权限范围不变;Preview 保持只读,实时更新保留命令展开状态和滚动位置。
345
+
344
346
  TraeX 请求进入规划模式或确认方案开始执行时,现有思考卡片会显示“等待确认”、方案正文,以及 `Approve Plan`(或 `Enter Plan Mode`)、`Reject`、`Cancel Request` 操作。即使使用自动执行权限,也必须明确确认;取消确认请求不等同于停止任务。Turn Preview 会展示方案及待确认提示,但保持只读,请在飞书卡片中操作。等待确认的轮次仍是活动任务,在完成或被明确停止前继续阻止安全重启。旧版本运行时已经丢失的确认通知无法通过此次适配自动补回。
345
347
 
346
348
  Turn Preview 的 Prompt、Commentary 和结果中的本地图片通过签名文件链接加载,实时更新时同样生效。相对图片路径按任务的项目目录解析。
@@ -349,14 +351,22 @@ Turn Preview 的 Prompt、Commentary 和结果中的本地图片通过签名文
349
351
 
350
352
  Turn Preview 顶部在处理和工具执行期间统一显示“正在处理”;工具详情和其他状态提示保持不变。
351
353
 
354
+ Header 不再显示上下文压缩统计,“上下文”Token 数放在“模型调用”前面(没有模型调用次数时,放在工具数量前面),使用 Agent 在本轮最近一次上报的上下文大小,不是累计消耗或模型容量。数值局部实时更新,压缩后收到较小值时同步下降;悬停可查看精确值。历史轮次显示当时保存的值,未上报或数值无效时隐藏,不从其他 Token 数推算,也不额外读取历史。
355
+
352
356
  Turn Preview 先显示每轮保存的 Provider,再显示模型,不添加可见的 Provider 前缀。切换设置只影响后续轮次,不改变当前轮次或历史轮次的标记;旧快照未记录 Provider 时不显示,也不会用任务当前设置补填。
353
357
 
358
+ Header 还显示本轮“模型调用 N 次”,按有效 Token 用量更新次数统计:首次正用量计一次,之后累计用量每次增长计一次,优先采用含缓存的总用量,缺失时采用非缓存用量。重复、回退、无效及仅上下文变化的通知不增加次数。数值局部实时更新,重启后保留;不修改飞书思考卡片。已有 Preview 事件在正常回放时可还原次数,缺少完整记录的旧快照或未上报用量的 Agent 则不显示;不额外读取 Agent 历史或扫描 rollout。
359
+
354
360
  Agent 提供数据时,Turn Preview 在原有非缓存 Token 数量旁显示本轮总计(输入加输出,包含缓存命中),不再单独显示缓存命中 Token 数;底层统计保持不变。数值实时更新,使用简写单位,悬停可查看精确值;重复用量通知不会重复累计。缺失的明细和旧快照不作推算,也不会读取任务历史补填;飞书卡片的 Token 统计口径保持不变。
355
361
 
356
362
  HTML 文件(`.html`、`.htm`)默认以预览模式打开,并支持切换代码、行号定位和实时更新。自包含 HTML 的内联样式、内联脚本和嵌入媒体可在隔离框架内运行;不开放外部资源、相对路径本地资源、网络请求、表单提交及对外层查看页的访问。预览会渲染完整文档,仅代码视图限制为开头 2 MiB。
357
363
 
364
+ CSV 文件(`.csv`,不区分大小写)默认显示只读表格,带行号、列字母和固定标签,可横向及纵向滚动;首行保留为数据,不自动当作表头。支持标准逗号分隔、引号内逗号和换行、双引号转义、空单元格,以及现有 UTF-8、带 BOM 的 UTF-16、GB18030 编码识别;数字字符串和公式均按普通文本显示。预览最多读取开头 2 MiB,表格最多显示 500 条记录、50 列、每格 4000 个字符,超限或引号格式错误时明确提示,字节边界处不完整的记录不展示。代码视图最多显示 2000 个物理行,原始文件和下载保持完整内容;实时更新保留所选模式和表格滚动位置。
365
+
358
366
  Provider、模型、思考强度和权限设置会作用于当前任务,同时保存到对应 Agent 的 `defaults` 中。以后创建没有同 Agent 设置可继承的新任务时,会使用这些默认值;每个已配置 Agent 分别保存自己的设置。
359
367
 
368
+ App Server 任务切换权限时,下一轮会同时应用审批与沙箱策略:`auto` 为关闭沙箱且不弹审批,`confirm` 为工作区可写沙箱并按需审批。可在 `/permissions` 卡片中选择,或使用 `agentbot task permissions auto|confirm`。切换无需重启 Agent、Fork 或新建任务,不改变已在执行的工具进程,也不会通过追加消息(steer)修改当前轮次沙箱。工作区额外可写目录、网络访问及临时目录排除项保留 Agent 的配置。
369
+
360
370
  运行设置卡片末尾以 Markdown 引用块显示当前选项页的一句重点提示,标明作用范围和生效时机。Agent 只改变本聊天或话题中新任务的默认 Agent,不迁移当前任务;模型、思考强度和权限从下一轮生效。Agent 和 Provider 选项只显示标识,去掉重复的展示名称,保留当前与默认状态标记。只有一个 Provider 时,`/provider` 仍会打开运行设置卡片,可以继续切换到 Model、Thinking 和 Permission 页。
361
371
 
362
372
  切换 Provider 要求任务处于空闲状态;任务执行中请等待完成,或停止任务后再切换。对于自定义 Provider,Agent Bot 会在接口可用时读取其 OpenAI 兼容 `/models` 接口,并只展示该 Provider 返回的模型。切换时优先保留目标 Provider 也支持的原模型;否则选择目标 Provider 的默认模型,没有默认模型时选择返回列表中的第一个模型。未提供模型列表接口的 Provider 仍可使用:Agent Bot 会把当前或已配置模型作为唯一候选交给 Codex 应用。Agent Bot 只卸载选中的空闲任务,再使用解析出的 Provider 和模型恢复,校验两者后才保存设置并提示成功。确认由当前实例新建的空任务可以重建底层线程,但保留本地任务标识、标题和目录;Fork 或恢复的任务不会仅因尚未发送新消息而被当作空任务。切换失败时保留原设置并尝试恢复远端;如果恢复也失败,将阻止后续执行,直到重新切换 Provider 成功。
@@ -391,6 +401,8 @@ Turn Preview 中每个已保存的思考项默认折叠,开头的 Markdown 标
391
401
 
392
402
  ## 常见问题
393
403
 
404
+ 异常崩溃后,不再仅凭 Codex 日志缺少结束事件就把任务判为运行中:未加载的任务还需要确认有存活的写入进程。Agent Bot 确认会话恢复成功后才创建新的运行卡片;写锁冲突会停止自动恢复并显示占用卡片,其他尚未确认恢复成功的故障每 5 秒重试,在 1 分钟重试窗口耗尽后标记中断并通知用户,不会自动关闭外部进程。已经确认仍在执行的轮次继续监控,临时断连也不会被该恢复超时误判为空闲。
405
+
394
406
  - **机器人没有响应:** 运行 `agentbot server status`,并查看当天的 `~/.agent-bot/logs/agent-bot.YYYY-MM-DD.log`
395
407
  - **Node 崩溃后 Worker 被自动重启:** 查看 `~/.agent-bot/data/last-crash.json`、崩溃当天的 `~/.agent-bot/logs/worker.stderr.YYYY-MM-DD.log` 和 `~/.agent-bot/data/crash-reports/`
396
408
  - **飞书权限不完整:** 重新运行 `agentbot init`,完成显示的授权步骤
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ const workspacePolicySchema = z.object({
3
+ type: z.literal("workspaceWrite"),
4
+ writableRoots: z.array(z.string().min(1)),
5
+ networkAccess: z.boolean(),
6
+ excludeTmpdirEnvVar: z.boolean(),
7
+ excludeSlashTmp: z.boolean(),
8
+ });
9
+ const workspaceConfigSchema = z.object({
10
+ sandbox_workspace_write: z.object({
11
+ writable_roots: z.array(z.string().min(1)).default([]),
12
+ network_access: z.boolean().default(false),
13
+ exclude_tmpdir_env_var: z.boolean().default(false),
14
+ exclude_slash_tmp: z.boolean().default(false),
15
+ }).nullish(),
16
+ });
17
+ export function workspaceSandboxFromResponse(sandbox) {
18
+ const parsed = workspacePolicySchema.safeParse(sandbox);
19
+ return parsed.success ? parsed.data : undefined;
20
+ }
21
+ export function workspaceSandboxFromConfig(config) {
22
+ const parsed = workspaceConfigSchema.safeParse(config);
23
+ if (!parsed.success)
24
+ throw new Error("App Server 返回了无效的工作区沙箱配置,未启动新轮次。");
25
+ const settings = parsed.data.sandbox_workspace_write;
26
+ return {
27
+ type: "workspaceWrite",
28
+ writableRoots: settings?.writable_roots ?? [],
29
+ networkAccess: settings?.network_access ?? false,
30
+ excludeTmpdirEnvVar: settings?.exclude_tmpdir_env_var ?? false,
31
+ excludeSlashTmp: settings?.exclude_slash_tmp ?? false,
32
+ };
33
+ }
34
+ //# sourceMappingURL=AppServerPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppServerPermissions.js","sourceRoot":"","sources":["../../src/codex/AppServerPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACzC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE;IAC1B,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE;IAChC,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,uBAAuB,EAAE,CAAC,CAAC,MAAM,CAAC;QAChC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC1C,sBAAsB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAClD,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;KAC9C,CAAC,CAAC,OAAO,EAAE;CACb,CAAC,CAAC;AAKH,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACxD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC;IACrD,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,aAAa,EAAE,QAAQ,EAAE,cAAc,IAAI,EAAE;QAC7C,aAAa,EAAE,QAAQ,EAAE,cAAc,IAAI,KAAK;QAChD,mBAAmB,EAAE,QAAQ,EAAE,sBAAsB,IAAI,KAAK;QAC9D,eAAe,EAAE,QAAQ,EAAE,iBAAiB,IAAI,KAAK;KACtD,CAAC;AACJ,CAAC"}
@@ -1,7 +1,9 @@
1
1
  import { open } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import Database from "better-sqlite3";
4
+ import { SystemThreadWriterProcessController, threadWriterLockPath } from "./ThreadWriterProcess.js";
4
5
  const READ_CHUNK_SIZE = 64 * 1024;
6
+ const WRITER_CHECK_CACHE_MS = 5_000;
5
7
  const TASK_STARTED = Buffer.from('"type":"task_started"');
6
8
  const TASK_COMPLETE = Buffer.from('"type":"task_complete"');
7
9
  const TURN_ABORTED = Buffer.from('"type":"turn_aborted"');
@@ -13,9 +15,15 @@ const PATTERN_OVERLAP = Math.max(TASK_STARTED.length, TASK_COMPLETE.length, TURN
13
15
  */
14
16
  export class CodexLocalActivityDetector {
15
17
  codexHome;
18
+ hasWriter;
16
19
  rollouts = new Map();
17
- constructor(codexHome) {
20
+ writerChecks = new Map();
21
+ constructor(codexHome, hasWriter = async (threadId) => {
22
+ const lockPath = threadWriterLockPath(codexHome, threadId);
23
+ return Boolean(lockPath && (await new SystemThreadWriterProcessController().inspect(lockPath)).length > 0);
24
+ }) {
18
25
  this.codexHome = codexHome;
26
+ this.hasWriter = hasWriter;
19
27
  }
20
28
  async activeThreadIds(threadIds) {
21
29
  return new Set((await this.activeThreads(threadIds)).keys());
@@ -41,13 +49,37 @@ export class CodexLocalActivityDetector {
41
49
  database?.close();
42
50
  }
43
51
  const active = new Map();
44
- for (const row of rows) {
45
- const task = await latestTask(row.rollout_path, this.rollouts);
46
- if (task.active)
47
- active.set(row.id, task.turnId);
52
+ for (let index = 0; index < rows.length; index += 4) {
53
+ await Promise.all(rows.slice(index, index + 4).map(async (row) => {
54
+ const task = await latestTask(row.rollout_path, this.rollouts);
55
+ // An unpaired start survives a crash. It is not evidence of a live process.
56
+ if (task.active && await this.hasLiveWriter(row.id))
57
+ active.set(row.id, task.turnId);
58
+ }));
48
59
  }
49
60
  return active;
50
61
  }
62
+ async hasLiveWriter(threadId) {
63
+ const cached = this.writerChecks.get(threadId);
64
+ if (cached && cached.expiresAt > Date.now())
65
+ return cached.result;
66
+ const result = this.hasWriter(threadId).catch((error) => {
67
+ throw new Error("无法确认任务的写入进程是否仍在运行,请稍后重试。", { cause: error });
68
+ });
69
+ const entry = { expiresAt: Date.now() + WRITER_CHECK_CACHE_MS, result };
70
+ this.writerChecks.delete(threadId);
71
+ this.writerChecks.set(threadId, entry);
72
+ if (this.writerChecks.size > 512)
73
+ this.writerChecks.delete(this.writerChecks.keys().next().value);
74
+ try {
75
+ return await result;
76
+ }
77
+ catch (error) {
78
+ if (this.writerChecks.get(threadId) === entry)
79
+ this.writerChecks.delete(threadId);
80
+ throw error;
81
+ }
82
+ }
51
83
  async threadSettings(threadIds) {
52
84
  const ids = [...new Set(threadIds.filter(Boolean))];
53
85
  if (ids.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"CodexLocalActivityDetector.js","sourceRoot":"","sources":["../../src/codex/CodexLocalActivityDetector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CodexLocalActivityDetector.js","sourceRoot":"","sources":["../../src/codex/CodexLocalActivityDetector.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { statSync } from "node:fs";
2
2
  import { appendGeneratedImageMarkdown } from "../utils/generatedImageMarkdown.js";
3
3
  import { normalizeTaskTitle } from "../utils/taskTitle.js";
4
4
  import { AppServerRequestError } from "./AppServerConnection.js";
5
+ import { workspaceSandboxFromConfig, workspaceSandboxFromResponse } from "./AppServerPermissions.js";
5
6
  import { formatCodexError, mapCodexNotification } from "./CodexEventMapper.js";
6
7
  import { CodexLocalActivityDetector } from "./CodexLocalActivityDetector.js";
7
8
  import { detectProjectlessWorkspace } from "./ProjectlessWorkspace.js";
@@ -54,6 +55,9 @@ export class CodexRuntime {
54
55
  getSession(localSessionId) {
55
56
  return this.sessions.get(localSessionId);
56
57
  }
58
+ forgetSession(localSessionId) {
59
+ this.sessions.delete(localSessionId);
60
+ }
57
61
  getProcessInfo() {
58
62
  return this.provider.getProcessInfo?.() ?? {};
59
63
  }
@@ -147,7 +151,7 @@ export class CodexRuntime {
147
151
  const client = await this.client();
148
152
  await this.ensureSessionResumed(session, client);
149
153
  session.canReplaceEmptyThread = false;
150
- const start = () => client.request("turn/start", {
154
+ const start = async () => client.request("turn/start", {
151
155
  threadId: session.remoteSessionId,
152
156
  input: codexUserInput(prompt),
153
157
  cwd: session.cwd,
@@ -155,6 +159,7 @@ export class CodexRuntime {
155
159
  effort: session.reasoningEffort,
156
160
  summary: "auto",
157
161
  approvalPolicy: session.permissionMode === "auto" ? "never" : "on-request",
162
+ sandboxPolicy: await this.turnSandboxPolicy(session, client),
158
163
  }, SESSION_REQUEST_TIMEOUT_MS);
159
164
  let response;
160
165
  try {
@@ -194,7 +199,7 @@ export class CodexRuntime {
194
199
  return listed;
195
200
  }
196
201
  }));
197
- const activeThreads = await this.localActivityDetector?.activeThreads(sessions.map((session) => session.id));
202
+ const activeThreads = await this.localActivityDetector?.activeThreads(sessions.filter((session) => session.status === "not_loaded").map((session) => session.id));
198
203
  return {
199
204
  sessions: activeThreads
200
205
  ? sessions.map((session) => markLocallyDetectedActive(session, activeThreads))
@@ -375,7 +380,8 @@ export class CodexRuntime {
375
380
  }));
376
381
  }
377
382
  async decorateRemoteSession(remoteSessionId, summary) {
378
- const activeThreads = await this.localActivityDetector?.activeThreads([remoteSessionId]);
383
+ const activeThreads = summary.status === "not_loaded"
384
+ ? await this.localActivityDetector?.activeThreads([remoteSessionId]) : undefined;
379
385
  const activeSummary = activeThreads ? markLocallyDetectedActive(summary, activeThreads) : summary;
380
386
  const settings = await this.localActivityDetector?.threadSettings([remoteSessionId]);
381
387
  return {
@@ -430,20 +436,20 @@ export class CodexRuntime {
430
436
  }
431
437
  }
432
438
  async inspectRemoteSessionActivity(remoteSessionId) {
433
- const [response, activeThreads] = await Promise.all([
434
- (await this.client()).request("thread/read", { threadId: remoteSessionId, includeTurns: false }, SYNC_REQUEST_TIMEOUT_MS),
435
- this.localActivityDetector?.activeThreads([remoteSessionId]),
436
- ]);
439
+ const response = await (await this.client()).request("thread/read", { threadId: remoteSessionId, includeTurns: false }, SYNC_REQUEST_TIMEOUT_MS);
440
+ const status = remoteThreadStatus(response.thread.status?.type);
441
+ const activeThreads = status === "not_loaded"
442
+ ? await this.localActivityDetector?.activeThreads([remoteSessionId]) : undefined;
437
443
  const runtimeSession = [...this.sessions.values()]
438
444
  .find((session) => session.remoteSessionId === remoteSessionId);
439
445
  const detectedTurnId = activeThreads?.get(remoteSessionId);
440
- const active = remoteThreadStatus(response.thread.status?.type) === "active"
441
- || Boolean(runtimeSession?.activeTurnId)
442
- || Boolean(activeThreads?.has(remoteSessionId));
446
+ // A turn started in this process is evidence; a restored activeTurnId alone is not.
447
+ const active = status === "active" || Boolean(activeThreads?.has(remoteSessionId))
448
+ || Boolean(runtimeSession?.activeTurnId && runtimeSession.activeTurnStartedAt !== undefined);
443
449
  const activeTurnId = detectedTurnId ?? runtimeSession?.activeTurnId;
444
450
  return {
445
451
  active,
446
- ...(activeTurnId ? { activeTurnId } : {}),
452
+ ...(active && activeTurnId ? { activeTurnId } : {}),
447
453
  };
448
454
  }
449
455
  async synchronizeSession(sessionId) {
@@ -616,6 +622,7 @@ export class CodexRuntime {
616
622
  threadId: response.thread.id, name: session.title,
617
623
  }, SESSION_REQUEST_TIMEOUT_MS);
618
624
  const candidate = { ...session, ...settings, remoteSessionId: response.thread.id,
625
+ workspaceSandboxPolicy: workspaceSandboxFromResponse(response.sandbox),
619
626
  needsResume: false, settingsRecoveryError: undefined };
620
627
  await persist?.(candidate);
621
628
  Object.assign(session, candidate);
@@ -639,6 +646,7 @@ export class CodexRuntime {
639
646
  if (restored.thread.id !== previous.remoteSessionId)
640
647
  throw new Error("恢复时返回了不同的任务 ID。");
641
648
  session.needsResume = false;
649
+ session.workspaceSandboxPolicy = workspaceSandboxFromResponse(restored.sandbox);
642
650
  session.settingsRecoveryError = undefined;
643
651
  }
644
652
  catch (restoreError) {
@@ -1191,7 +1199,7 @@ export class CodexRuntime {
1191
1199
  session.needsResume = false;
1192
1200
  }
1193
1201
  async resumeAppServerSession(session, client) {
1194
- await client.request("thread/resume", {
1202
+ const response = await client.request("thread/resume", {
1195
1203
  threadId: session.remoteSessionId,
1196
1204
  excludeTurns: true,
1197
1205
  cwd: session.cwd,
@@ -1200,6 +1208,19 @@ export class CodexRuntime {
1200
1208
  ...threadLifecycleParams(session.cwd),
1201
1209
  ...permissionParams(session.permissionMode),
1202
1210
  }, SESSION_REQUEST_TIMEOUT_MS);
1211
+ session.workspaceSandboxPolicy = workspaceSandboxFromResponse(response.sandbox);
1212
+ }
1213
+ async turnSandboxPolicy(session, client) {
1214
+ if (session.permissionMode === "auto")
1215
+ return { type: "dangerFullAccess" };
1216
+ if (!session.workspaceSandboxPolicy) {
1217
+ // Resolve project-specific options once, without resuming or scanning history.
1218
+ const response = await client.request("config/read", {
1219
+ cwd: session.cwd, includeLayers: false,
1220
+ }, CONTROL_REQUEST_TIMEOUT_MS);
1221
+ session.workspaceSandboxPolicy = workspaceSandboxFromConfig(response.config);
1222
+ }
1223
+ return session.workspaceSandboxPolicy;
1203
1224
  }
1204
1225
  async synchronizeSessionNow(sessionId) {
1205
1226
  const session = this.requireSession(sessionId);
@@ -1229,7 +1250,9 @@ export class CodexRuntime {
1229
1250
  }
1230
1251
  if (latestInProgress) {
1231
1252
  this.supersedeTurn(session, activeTurnId);
1232
- this.adoptTurn(session, latestInProgress.id, turnStartedAt(latestInProgress));
1253
+ if (thread.status?.type === "active") {
1254
+ this.adoptTurn(session, latestInProgress.id, turnStartedAt(latestInProgress));
1255
+ }
1233
1256
  return;
1234
1257
  }
1235
1258
  if (!latest) {
@@ -1349,6 +1372,7 @@ export class CodexRuntime {
1349
1372
  messagePhases: new Map(),
1350
1373
  unphasedMessages: new Map(),
1351
1374
  needsResume: false,
1375
+ workspaceSandboxPolicy: workspaceSandboxFromResponse(response.sandbox),
1352
1376
  canReplaceEmptyThread: !("remoteSessionId" in input),
1353
1377
  rolloutPath: stringValue(response.thread.path)?.trim() || undefined,
1354
1378
  turnCount: "remoteSessionId" in input ? undefined : 0,