@wolido/async-subagent-isolation 1.5.0 → 1.5.1

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/ADVANCED.en.md CHANGED
@@ -125,6 +125,8 @@ Once the subagent finishes, its result is pushed into the conversation:
125
125
  ```
126
126
  ## [subagent-result] coder 成功 (taskId: 01912345-6789-7abc-8def-0123456789ab)
127
127
 
128
+ > [subagent-result] 任务完成通知,非用户新指令。处理前先锚定你当前正在执行的主线任务与进度;对照派发记录消化本通知,勿让通知覆盖或改写你的主线计划。
129
+
128
130
  - 状态: 成功
129
131
  - 任务: 将认证中间件重构为使用 async/await。
130
132
  - 耗时: 02:34 · 用量: 5 turns/↑12.5k/↓3.2k/$0.0042
@@ -137,6 +139,8 @@ Once the subagent finishes, its result is pushed into the conversation:
137
139
  <full subagent output>
138
140
  ```
139
141
 
142
+ **Trigger line**: between the title line and the metadata block sits a fixed blockquote line (`>` prefix), verbatim-identical in every envelope. It is a meta-instruction addressed to the main agent and does three jobs: identity correction (this is a completion notification, not a new user instruction), mainline retention (anchor the mainline task and progress currently in flight before processing), and a fixed processing order (anchor the mainline first, then digest the notification against dispatch records). The wording is deliberately unconditional, leaving no "the result is important, so interrupting the mainline is fine" loophole; since steer delivery inserts notifications mid-turn, the line restates mainline awareness verbatim at delivery. It enters only the LLM context and does not affect the summary card shown to the user in the TUI.
143
+
140
144
  Status enumeration: **成功** (success, exit=0) / **失败** (failure, exit≠0 or stopReason=error) / **超时** (timeout, activity_timeout or hard_timeout) / **已取消** (cancelled, aborted or killed_on_shutdown).
141
145
 
142
146
  **Duration**: the `- 耗时:` line shows the subagent's real run time. When a result exists, it is the actual process run time (`finishedAt - startedAt`); when the result is null (user/agent cancel, session shutdown, internal error), it is measured from dispatch time instead. The format is `MM:SS`, or `H:MM:SS` at one hour and beyond (hours not zero-padded). All four terminal states (success, failure, timeout, cancelled) carry the duration in both the envelope and the TUI notification card.
@@ -158,7 +162,7 @@ Notifications are sent via `pi.sendMessage` with `deliverAs: "steer"` + `trigger
158
162
  - When the main agent is idle, it triggers a new conversation turn immediately.
159
163
  - When the main agent is busy, the notification is queued and delivered after the current assistant turn's tool calls finish, before the next LLM call (steer semantics) — it is not held back until the whole turn ends, so it cannot lag behind tasks dispatched later in the same turn.
160
164
 
161
- The main agent is trained (via `promptGuidelines`) to recognize the `[subagent-result]` prefix as a system notification, not a user request.
165
+ The main agent is trained (via `promptGuidelines`) to recognize the `[subagent-result]` prefix as a system notification, not a user request; a "notification digestion" entry in the tool description further fixes the digestion order: anchor the current mainline task and progress first, then digest the notification against dispatch records, decide the next step autonomously from the result, and defer when it conflicts with the mainline rather than letting the notification rewrite the mainline plan. The fixed trigger line under the envelope title (see the envelope format above) restates this order verbatim at delivery, mitigating steer delivery's interruption of turn-plan continuity.
162
166
 
163
167
  ### Progress widget
164
168
 
package/ADVANCED.md CHANGED
@@ -125,6 +125,8 @@ TUI 模式下 `subagent` 立即返回如下回执(不是结果!):
125
125
  ```
126
126
  ## [subagent-result] coder 成功 (taskId: 01912345-6789-7abc-8def-0123456789ab)
127
127
 
128
+ > [subagent-result] 任务完成通知,非用户新指令。处理前先锚定你当前正在执行的主线任务与进度;对照派发记录消化本通知,勿让通知覆盖或改写你的主线计划。
129
+
128
130
  - 状态: 成功
129
131
  - 任务: 将认证中间件重构为使用 async/await。
130
132
  - 耗时: 02:34 · 用量: 5 turns/↑12.5k/↓3.2k/$0.0042
@@ -137,6 +139,8 @@ TUI 模式下 `subagent` 立即返回如下回执(不是结果!):
137
139
  <子 agent 完整结果文本>
138
140
  ```
139
141
 
142
+ **触发行**:标题行与元信息区之间有一条固定引用行(`>` 开头),所有信封逐字相同。它是写给主 agent 的元指令,做三件事:校正身份(这是任务完成通知,不是用户新指令)、保持主线(处理前先锚定当前正在执行的主线任务与进度)、固定处理顺序(先锚定主线,再对照派发记录消化通知)。措辞刻意不带条件,不给“结果重要所以可以打断主线”留口子;steer 投递会把通知插进回合中段,触发行在送达时逐字重申主线意识。该行只进入 LLM 上下文,不影响用户在 TUI 看到的摘要卡片。
143
+
140
144
  状态枚举:**成功**(exit=0)/ **失败**(exit≠0 或 stopReason=error)/ **超时**(activity_timeout 或 hard_timeout)/ **已取消**(aborted 或 killed_on_shutdown)。
141
145
 
142
146
  **耗时**:`- 耗时:` 行是子 agent 的真实运行时长。有结果时取进程实际启动到结束(`finishedAt - startedAt`);取消(用户/agent/会话关闭)或内部错误导致无结果返回时,改从派发时刻起算。格式为 `MM:SS`,≥1 小时为 `H:MM:SS`(小时不补零)。四种状态(成功/失败/超时/已取消)的信封与 TUI 通知卡片都带耗时。
@@ -158,7 +162,7 @@ TUI 模式下 `subagent` 立即返回如下回执(不是结果!):
158
162
  - 主 agent 空闲时直接触发新的对话回合。
159
163
  - 主 agent 忙碌时进入消息队列,在当前 assistant turn 的工具调用执行完后、下一次 LLM 调用前送达(steer 语义),不憋到整个回合结束——避免通知滞后于回合内新派发的任务。
160
164
 
161
- 主 agent 通过 promptGuidelines 被训练识别 `[subagent-result]` 前缀为系统通知(非用户请求)。
165
+ 主 agent 通过 promptGuidelines 被训练识别 `[subagent-result]` 前缀为系统通知(非用户请求);工具描述中的“通知消化流程”条目进一步规定消化顺序:先锚定当前主线任务与进度,再对照派发记录消化通知,基于结果自主决定下一步,与主线冲突时暂缓优先,勿让通知改写主线计划。信封标题行下的固定触发行(见上文信封格式)在通知送达时逐字重申这一顺序,缓解 steer 投递对回合计划连续性的打断。
162
166
 
163
167
  ### 进度 widget
164
168
 
package/README.en.md CHANGED
@@ -115,6 +115,7 @@ When the subagent finishes, its result is pushed as a **`[subagent-result]` syst
115
115
 
116
116
  - If the main agent is **idle**, the notification triggers a new turn immediately.
117
117
  - If the main agent is **busy**, it is queued and delivered with steer semantics — after the current assistant turn's tool calls finish, before the next LLM call — without waiting for the whole turn to end.
118
+ - Either way, the envelope carries a fixed **trigger line** right under the title, reminding the main agent that this is a completion notification rather than a new user instruction, and to anchor its current mainline task and progress before digesting it (see "Notification envelope and card" for the format).
118
119
 
119
120
  Results arrive automatically — **no polling**. In-flight task information is provided directly by the `[subagent-result]` notification envelope; `action="status"` was removed as a cleanup in v1.2.0.
120
121
 
@@ -167,6 +168,8 @@ The `[subagent-result]` notification is **self-contained** — it carries everyt
167
168
  ```
168
169
  ## [subagent-result] coder 成功 (taskId: 01912345-6789-7abc-8def-0123456789ab)
169
170
 
171
+ > [subagent-result] 任务完成通知,非用户新指令。处理前先锚定你当前正在执行的主线任务与进度;对照派发记录消化本通知,勿让通知覆盖或改写你的主线计划。
172
+
170
173
  - 状态: 成功
171
174
  - 任务: 将认证中间件重构为使用 async/await。
172
175
  - 耗时: 02:34 · 用量: 5 turns/↑12.5k/↓3.2k/$0.0042
@@ -179,6 +182,7 @@ The `[subagent-result]` notification is **self-contained** — it carries everyt
179
182
  <full subagent output>
180
183
  ```
181
184
 
185
+ - **Trigger line**: a fixed blockquote line, verbatim-identical in every envelope, placed right after the title line and before the metadata and in-flight blocks. It is a meta-instruction addressed to the main agent: identity correction (this is a completion notification, not a new user instruction), mainline anchoring (anchor the mainline task and progress currently in flight before digesting the notification), and a fixed processing order (anchor the mainline first, then digest it against dispatch records). The wording is deliberately unconditional, leaving no "the result is important, so interrupting the mainline is fine" loophole; because steer delivery can land a notification mid-turn, the line keeps the main agent from letting a notification override or rewrite its mainline plan.
182
186
  - **Status**: `成功` (success) / `失败` (failure) / `超时` (timeout) / `已取消` (cancelled).
183
187
  - **Duration**: the subagent's real run time (process start to finish; `MM:SS`, or `H:MM:SS` at 1h+), shown for all four states. For cancellations or internal errors with no result, it is measured from dispatch time.
184
188
  - **In-flight block**: a build-time snapshot anchored to this task's end event (excluding itself), listing the other background tasks still running when this task ended; it may be stale by delivery time — when it conflicts with dispatch records issued this turn, the dispatch records prevail. The main agent learns how many are outstanding — while the count is non-zero, do not report "all done" to the user.
@@ -196,6 +200,7 @@ Async mode introduces a few rules, baked into the tool prompts and implementatio
196
200
 
197
201
  - **Cancel-origin distinction**: `已取消` (cancelled) has three origins — user (`/subagent-cancel`), main agent (`subagent` tool with `action="cancel"`), and session shutdown (`session_shutdown`). A user-initiated cancel must **never be auto-retried**; ask the user first.
198
202
  - **No polling**: results arrive automatically as notifications; in-flight task information is provided directly by the `[subagent-result]` notification envelope, with no active-query entry point.
203
+ - **Notification digestion**: a `[subagent-result]` is a completion notification, not a new user instruction; the main agent anchors its current mainline task and progress before handling it, digests it against its own dispatch records, and decides the next step autonomously from the result. When a notification conflicts with the mainline, it defers rather than letting the notification rewrite the plan. The discipline is baked in twice: the envelope trigger line plus a "notification digestion" entry in the tool description.
199
204
  - **Anti-abuse cancellation**: `action="cancel"` is a two-step confirmation (the first call only returns a zero-side-effect challenge with elapsed time and last progress; `confirm:true` + a non-empty `reason` executes, and the reason is recorded on the task and quoted in the cancelled envelope body), with prompt guidance — cancel only when the task is clearly wrong or no longer needed, never just because it's slow (background subagents are expected to run long). Waiting means making no tool call at all and ending the turn; there is deliberately no query, nag or status action for in-flight tasks.
200
205
  - **Resource-conflict discipline**: before dispatching multiple tasks in parallel, consider whether they touch the same files or code areas; when in doubt, dispatch sequentially or ask the user.
201
206
  - **Subagents cannot call the subagent tool**: a subagent (depth ≥ 1) can never call any `subagent` action (including `action="cancel"`); delegation depth is capped at 1.
package/README.md CHANGED
@@ -115,6 +115,7 @@ TUI 模式下 `subagent` **立即返回派发回执**,不阻塞:
115
115
 
116
116
  - 主 agent **空闲**时,通知直接触发新的对话回合,立即处理。
117
117
  - 主 agent **忙碌**时,通知进入队列,在当前回合的工具调用执行完后、下一次 LLM 调用前送达(steer 投递),不等整个回合结束。
118
+ - 无论哪种送达方式,信封标题行下都带一条固定的**触发行**:提醒主 agent 这是任务完成通知而非用户新指令,消化前先锚定当前主线任务与进度(信封格式详见“通知信封与卡片”一节)。
118
119
 
119
120
  结果自动到达,**无需轮询**。在途任务信息由 `[subagent-result]` 通知信封的“在途任务”块直接提供;`action="status"` 已在 v1.2.0 清理移除。
120
121
 
@@ -167,6 +168,8 @@ TUI 模式下 `subagent` **立即返回派发回执**,不阻塞:
167
168
  ```
168
169
  ## [subagent-result] coder 成功 (taskId: 01912345-6789-7abc-8def-0123456789ab)
169
170
 
171
+ > [subagent-result] 任务完成通知,非用户新指令。处理前先锚定你当前正在执行的主线任务与进度;对照派发记录消化本通知,勿让通知覆盖或改写你的主线计划。
172
+
170
173
  - 状态: 成功
171
174
  - 任务: 将认证中间件重构为使用 async/await。
172
175
  - 耗时: 02:34 · 用量: 5 turns/↑12.5k/↓3.2k/$0.0042
@@ -179,6 +182,7 @@ TUI 模式下 `subagent` **立即返回派发回执**,不阻塞:
179
182
  <子 agent 完整结果文本>
180
183
  ```
181
184
 
185
+ - **触发行**:标题行之下、元信息与在途块之前的一条固定引用行,所有信封逐字相同。它是写给主 agent 的元指令:校正身份(这是任务完成通知,不是用户新指令)、锚定主线(消化通知前先锚定当前正在执行的主线任务与进度)、固定处理顺序(先锚定主线,再对照派发记录消化)。措辞刻意不带条件,不给“结果重要所以可以打断主线”留口子;steer 投递会在回合中段插入通知,触发行帮助主 agent 保持主线意识,不让通知覆盖或改写主线计划。
182
186
  - **状态**:`成功` / `失败` / `超时` / `已取消`。
183
187
  - **耗时**:子 agent 的真实运行时长(进程实际启动到结束,格式 `MM:SS`,≥1 小时为 `H:MM:SS`),成功/失败/超时/已取消四种状态都有;取消或内部错误(无结果返回)时从派发时刻起算。
184
188
  - **在途任务块**:锚定“本任务结束”事件的构建时刻快照(不含自身),列出本任务结束时其余仍在运行的后台任务;快照在送达时可能滞后,与本回合亲手发出的派发记录冲突时以派发记录为准。让主 agent 知道还有几个任务没回来——剩余不为 0 时,不要向用户汇报“全部完成”。
@@ -196,6 +200,7 @@ TUI 模式下 `subagent` **立即返回派发回执**,不阻塞:
196
200
 
197
201
  - **取消来源区分**:`已取消` 有用户(`/subagent-cancel`)、主 agent(`subagent` 工具 `action="cancel"`)、会话关闭(`session_shutdown`)三种来源;用户取消**不得自动重试**,须先询问。
198
202
  - **防轮询**:结果以通知自动到达;在途任务信息由 `[subagent-result]` 通知信封直接提供,不要主动查询。
203
+ - **通知消化流程**:`[subagent-result]` 是任务完成通知而非用户新指令;处理前先锚定当前主线任务与进度,对照派发记录消化,基于结果自主决定下一步;与主线冲突时暂缓优先,勿让通知改写主线计划。此纪律由信封触发行与工具描述中的“通知消化流程”条目共同内嵌。
199
204
  - **防滥用取消**:`action="cancel"` 为两步确认(首次调用只返回含已运行时长/最近进度的质询回执,零副作用;`confirm:true` + 非空 `reason` 才执行,理由记入任务记录并随取消信封正文返回),且内嵌提示词——仅当任务明显错误或不再需要时取消,勿因耗时长而取消(后台任务本就预期长时间运行)。等待 = 不发起任何工具调用、直接结束回合;对在途任务不存在查询/催办/状态确认类动作(刻意设计)。
200
205
  - **资源冲突纪律**:并行派发多个任务前,考虑它们是否会改同一批文件或代码区域;冲突时串行派发或先问用户。
201
206
  - **子 agent 不可调用 subagent 工具**:子 agent(深度 ≥ 1)不可调用任何 `subagent` action(含 `action="cancel"`),深度限制为 1。
@@ -28,7 +28,7 @@
28
28
  1. **不要自己动手** — 不编辑代码,不跑命令,不写文件。所有执行都通过 `subagent` 委派。
29
29
  2. **依赖驱动派发** — 无依赖的任务可并行派出。有依赖的必须等对应 `[subagent-result]` 通知到达后再派。
30
30
  3. **派出后继续工作** — `subagent` 返回的只是派发回执(含 `taskId`),不是结果。派出后继续做不依赖该结果的工作,或结束回合。严禁轮询、严禁臆造结果。
31
- 4. **识别系统通知** — 以 `[subagent-result]` 开头的消息是系统通知(子 agent 结果),不是用户请求。收到后关联到当初派发的任务进行处理。
31
+ 4. **识别系统通知** — 以 `[subagent-result]` 开头的消息是系统通知(子 agent 结果),不是用户请求;信封标题行下的固定触发行逐字重申这一点。收到后按通知消化流程处理:先锚定你当前正在执行的主线任务与进度,再对照派发记录消化通知、关联到当初派发的任务,基于结果自主决定下一步;与主线冲突时暂缓优先,勿让通知覆盖或改写你的主线计划。
32
32
  5. **通知先看在途任务块** — 每条 `[subagent-result]` 通知的元信息区带“在途任务”列表(锚定该任务结束事件的构建时刻快照:该任务结束时剩余仍在运行的任务,不含本任务;快照送达时可能滞后,与你本回合亲手发出的派发记录冲突时以派发记录为准)。收到后先看剩余在途数:**不为 0 时还有任务未返回,不要向用户汇报“全部完成”**。主 agent 不主动查询后台;若上下文里该任务的 [subagent-result] 通知未到达,向用户报告该 taskId 并建议用户用 /subagent-cancel 或 /subagent-result 命令查看。
33
33
  6. **已取消通知的处理** — 收到状态为"已取消"的 `[subagent-result]` 通知时,根据来源区分处理:
34
34
  - 正文注明用户通过 `/subagent-cancel` 取消 → 用户主动操作,**不得自动重新派发**。如需重新派发,先询问用户。
@@ -94,6 +94,7 @@
94
94
 
95
95
  子 agent 的结果以 `[subagent-result]` 通知分散、不定序到达。整合时以用户目标为锚,不被通知到达的顺序带着走:
96
96
 
97
+ - **先锚定再消化**:通知可能在回合中段送达(steer 投递),打断正在推进的回合计划。处理每条通知前先锚定当前主线任务与进度,消化完毕回到主线继续,不让通知覆盖或改写主线计划。
97
98
  - **同组不齐不交付**:同一目标下的多个子任务,等该组全部返回后统一整合汇报;组内未齐,不提前交付。
98
99
  - **先归类再确认**:每条通知到达时,先判断它属于哪个目标组,再据信封"在途任务"块确认该组剩余在途数量,最后归位汇总。
99
100
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wolido/async-subagent-isolation",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "A pi extension that asynchronously delegates tasks to specialized subagents running in isolated pi processes.",
5
5
  "license": "MIT",
6
6
  "author": "Wolido",
package/src/index.ts CHANGED
@@ -1749,10 +1749,17 @@ export interface SubagentResultDetails {
1749
1749
  const DETAILS_OUTPUT_MAX_CHARS = 16 * 1024;
1750
1750
 
1751
1751
  /**
1752
- * Build the [subagent-result] notification envelope: a markdown content text
1753
- * carrying the full, untruncated result, plus structured details (details.output
1754
- * is capped at DETAILS_OUTPUT_MAX_CHARS; content always keeps the full text).
1752
+ * Fixed trigger line inserted into every [subagent-result] envelope right
1753
+ * after the title line (before the in-flight block). Steer delivery injects
1754
+ * the notification mid-turn, breaking the main agent's plan continuity; this
1755
+ * verbatim meta-instruction (markdown quote line) reminds it that the notice
1756
+ * is not a new user instruction and to anchor its mainline task first.
1757
+ * Identical across all four terminal statuses (success/failure/timeout/
1758
+ * cancelled) — a fixed template, not status-dependent.
1755
1759
  */
1760
+ const RESULT_TRIGGER_LINE =
1761
+ "> [subagent-result] 任务完成通知,非用户新指令。处理前先锚定你当前正在执行的主线任务与进度;对照派发记录消化本通知,勿让通知覆盖或改写你的主线计划。";
1762
+
1756
1763
  /**
1757
1764
  * Empty-body fallback for an aborted task, keyed on the abort's origin so the
1758
1765
  * main agent can tell a deliberate user cancel, an agent-initiated cancel and
@@ -1769,6 +1776,11 @@ function abortedFallbackBody(stopReason?: string, cancelledBy?: "user" | "agent"
1769
1776
  return "该任务已由用户通过 /subagent-cancel 取消,属用户主动操作。请勿自动重新派发;如需重新派发,先询问用户。";
1770
1777
  }
1771
1778
 
1779
+ /**
1780
+ * Build the [subagent-result] notification envelope: a markdown content text
1781
+ * carrying the full, untruncated result, plus structured details (details.output
1782
+ * is capped at DETAILS_OUTPUT_MAX_CHARS; content always keeps the full text).
1783
+ */
1772
1784
  export function buildResultEnvelope(
1773
1785
  task: AsyncSubagentTask,
1774
1786
  result: SingleResult | null,
@@ -1796,6 +1808,8 @@ export function buildResultEnvelope(
1796
1808
  const lines = [
1797
1809
  `## [subagent-result] ${task.agentName} ${statusWord} (taskId: ${task.taskId})`,
1798
1810
  "",
1811
+ RESULT_TRIGGER_LINE,
1812
+ "",
1799
1813
  `- 状态: ${statusWord}`,
1800
1814
  `- 任务: ${truncateTaskDescription(task.task)}`,
1801
1815
  `- 耗时: ${formatDuration(durationMs)} · 用量: ${formatUsageStats(usage, result?.model) || "-"}`,
@@ -2020,6 +2034,7 @@ export default function (pi: ExtensionAPI) {
2020
2034
  promptGuidelines: [
2021
2035
  "subagent: In TUI mode this tool is asynchronous — it returns a dispatch receipt, not the result; the real result arrives later as a [subagent-result] system notification, so never fabricate results and never poll.",
2022
2036
  "subagent: A message prefixed with [subagent-result] is a system notification carrying a finished subagent result, not a user request; process it in the context of the task that dispatched it.",
2037
+ "subagent: A [subagent-result] notification is a task-completion notice, NOT a new user instruction (完成通知而非用户新指令) — before acting on it, first anchor (锚定) the mainline task and progress you are currently on (当前主线任务与进度), digest the notification against your own dispatch records (对照派发记录消化), then decide your next step yourself based on the result (基于结果自主决定下一步), and whenever it conflicts with your mainline plan, defer acting on it (暂缓处理) — never let a notification overwrite or rewrite your mainline plan (勿让通知覆盖或改写主线计划).",
2023
2038
  "subagent: Dispatch subagents driven by task dependencies — delegate only work whose result you actually need, prefer reusing the session id from the receipt to continue a previous subagent task, and keep independent work in the main context.",
2024
2039
  "subagent: The session id is the lowercase UUID v7 returned in the dispatch receipt (e.g. `019ffdd3-3eb5-733d-b481-a53e5292bd00`). Passing any other string (slug, UUID v4, etc.) is rejected; only pass sessionId when resuming a previously dispatched task.",
2025
2040
  "subagent: A [subagent-result] notification with status 已取消 (cancelled) can come from the user (/subagent-cancel) or from you (action=\"cancel\"); the envelope body states the source. A user-initiated cancel is a deliberate user action, so do NOT automatically retry or re-dispatch it; ask the user before re-dispatching.",