@brainpilot/runtime 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +61 -0
  2. package/dist/agent-error.d.ts +51 -0
  3. package/dist/agent-error.d.ts.map +1 -0
  4. package/dist/agent-error.js +163 -0
  5. package/dist/agent-error.js.map +1 -0
  6. package/dist/agent-factory.d.ts.map +1 -1
  7. package/dist/agent-factory.js +36 -6
  8. package/dist/agent-factory.js.map +1 -1
  9. package/dist/events.d.ts +22 -0
  10. package/dist/events.d.ts.map +1 -1
  11. package/dist/events.js +32 -0
  12. package/dist/events.js.map +1 -1
  13. package/dist/extensions/agent-status.d.ts +91 -0
  14. package/dist/extensions/agent-status.d.ts.map +1 -0
  15. package/dist/extensions/agent-status.js +103 -0
  16. package/dist/extensions/agent-status.js.map +1 -0
  17. package/dist/extensions/trace-reminder.d.ts +94 -0
  18. package/dist/extensions/trace-reminder.d.ts.map +1 -0
  19. package/dist/extensions/trace-reminder.js +153 -0
  20. package/dist/extensions/trace-reminder.js.map +1 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/mailbox.d.ts +37 -1
  26. package/dist/mailbox.d.ts.map +1 -1
  27. package/dist/mailbox.js +79 -2
  28. package/dist/mailbox.js.map +1 -1
  29. package/dist/mas-agent.d.ts +74 -12
  30. package/dist/mas-agent.d.ts.map +1 -1
  31. package/dist/mas-agent.js +158 -33
  32. package/dist/mas-agent.js.map +1 -1
  33. package/dist/materialize-skills.d.ts +40 -0
  34. package/dist/materialize-skills.d.ts.map +1 -0
  35. package/dist/materialize-skills.js +141 -0
  36. package/dist/materialize-skills.js.map +1 -0
  37. package/dist/mock-agent.d.ts.map +1 -1
  38. package/dist/mock-agent.js +13 -1
  39. package/dist/mock-agent.js.map +1 -1
  40. package/dist/personas.d.ts +16 -0
  41. package/dist/personas.d.ts.map +1 -1
  42. package/dist/personas.js +651 -8
  43. package/dist/personas.js.map +1 -1
  44. package/dist/pi-provider.d.ts +5 -0
  45. package/dist/pi-provider.d.ts.map +1 -1
  46. package/dist/pi-provider.js +7 -1
  47. package/dist/pi-provider.js.map +1 -1
  48. package/dist/provider-config.d.ts +5 -0
  49. package/dist/provider-config.d.ts.map +1 -1
  50. package/dist/provider-config.js +2 -0
  51. package/dist/provider-config.js.map +1 -1
  52. package/dist/server.d.ts +2 -2
  53. package/dist/server.d.ts.map +1 -1
  54. package/dist/server.js +82 -8
  55. package/dist/server.js.map +1 -1
  56. package/dist/session-manager.d.ts +311 -8
  57. package/dist/session-manager.d.ts.map +1 -1
  58. package/dist/session-manager.js +901 -39
  59. package/dist/session-manager.js.map +1 -1
  60. package/dist/tools/skill-search.d.ts +53 -0
  61. package/dist/tools/skill-search.d.ts.map +1 -0
  62. package/dist/tools/skill-search.js +269 -0
  63. package/dist/tools/skill-search.js.map +1 -0
  64. package/dist/tools/system-tools.d.ts +22 -1
  65. package/dist/tools/system-tools.d.ts.map +1 -1
  66. package/dist/tools/system-tools.js +149 -21
  67. package/dist/tools/system-tools.js.map +1 -1
  68. package/dist/trace.d.ts +27 -1
  69. package/dist/trace.d.ts.map +1 -1
  70. package/dist/trace.js +60 -3
  71. package/dist/trace.js.map +1 -1
  72. package/dist/types.d.ts +51 -5
  73. package/dist/types.d.ts.map +1 -1
  74. package/package.json +7 -3
@@ -0,0 +1,103 @@
1
+ /**
2
+ * agent-status — a Pi-native extension that injects a fresh team-status block
3
+ * at the top of EVERY turn for the agent it is registered on (#97).
4
+ *
5
+ * Why an extension / the `context` hook (not the system prompt):
6
+ * - The per-role persona is injected via `appendSystemPrompt`, which Pi
7
+ * evaluates ONCE at session creation. A team-status snapshot put there would
8
+ * be frozen at "session start" and go stale immediately.
9
+ * - Pi's `context` hook fires before EACH LLM call (every turn within a run)
10
+ * and lets an extension non-destructively rewrite the `messages` array that
11
+ * is sent to the model. That rewrite is per-turn EPHEMERAL — it is applied to
12
+ * a local copy and is NOT persisted to the session history (events.jsonl).
13
+ * So a status block injected here is recomputed and current on every turn,
14
+ * and never accumulates stale snapshots on disk.
15
+ *
16
+ * Mechanism (Pi SDK, verified against the docs corpus):
17
+ * - Registered per-AgentSession via DefaultResourceLoader.extensionFactories,
18
+ * same as trace-reminder. Closure state is naturally per-agent.
19
+ * - `context` handler receives `{ messages }` (a safe-to-mutate copy) and may
20
+ * return `{ messages }` to replace what the model sees this turn.
21
+ * - Because the host appends a NEW block each turn, we first STRIP any block we
22
+ * injected on a previous turn (identified by the `<agent_status>` opener) so
23
+ * the model only ever sees the latest snapshot, not a pile of old ones.
24
+ *
25
+ * Only the real factory loads this — the mock has no Pi event loop, so the
26
+ * behavioural injection is verified in real mode. The pure block renderer
27
+ * (`renderAgentStatusBlock`) and the strip/inject logic are unit-tested here via
28
+ * a fake `pi`.
29
+ */
30
+ /** Opening tag — also the marker used to recognise a block we injected before. */
31
+ const TAG_OPEN = "<agent_status>";
32
+ const TAG_CLOSE = "</agent_status>";
33
+ /**
34
+ * Build the team-status block as a natural-language list (#97, option B). The
35
+ * wording is self-explanatory so the model needs no schema knowledge: each line
36
+ * names an agent, its status, and how many messages are still waiting unread in
37
+ * its inbox. Returns "" when there is nothing to report (caller skips injection).
38
+ *
39
+ * `lines` should already be filtered by the caller (trace agent excluded,
40
+ * stopped agents excluded). Order is preserved.
41
+ */
42
+ export function renderAgentStatusBlock(lines) {
43
+ if (lines.length === 0)
44
+ return "";
45
+ const body = lines
46
+ .map((l) => {
47
+ const n = l.unread;
48
+ const msg = `${n} unread message${n === 1 ? "" : "s"}`;
49
+ return `- ${l.name}: ${l.status}, ${msg}`;
50
+ })
51
+ .join("\n");
52
+ return (`${TAG_OPEN}\n` +
53
+ `Current agents (status, and how many messages are still waiting unread in each inbox):\n` +
54
+ `${body}\n` +
55
+ `${TAG_CLOSE}`);
56
+ }
57
+ /**
58
+ * Collect the status lines for a team snapshot from the live agents (#97).
59
+ * Includes every agent — INCLUDING the principal, so it sees its own backlog —
60
+ * except the trace agent (an internal recorder) and any stopped agent
61
+ * (destroyed; irrelevant to coordination). `unreadOf` returns the number of
62
+ * messages still queued unread in that agent's inbox. Order follows iteration.
63
+ */
64
+ export function collectAgentStatusLines(agents, unreadOf) {
65
+ const lines = [];
66
+ for (const a of agents) {
67
+ if (a.role === "trace")
68
+ continue;
69
+ if (a.status === "stopped")
70
+ continue;
71
+ lines.push({ name: a.name, status: a.status, unread: unreadOf(a.name) });
72
+ }
73
+ return lines;
74
+ }
75
+ /** True for a `user` message whose text is a status block we injected earlier. */
76
+ function isStatusMessage(m) {
77
+ return (m.role === "user" &&
78
+ m.content.some((c) => c.type === "text" && (c.text ?? "").startsWith(TAG_OPEN)));
79
+ }
80
+ /**
81
+ * Build the extension factory for one agent. The returned function is what Pi
82
+ * calls with the per-session `ExtensionAPI`.
83
+ */
84
+ export function makeAgentStatusExt(deps) {
85
+ return (pi) => {
86
+ pi.on("context", (e) => {
87
+ const block = deps.renderStatus();
88
+ // Strip any block we injected on a previous turn so only the latest
89
+ // snapshot survives (the context copy is ephemeral — this never touches
90
+ // persisted history).
91
+ const stripped = e.messages.filter((m) => !isStatusMessage(m));
92
+ const removedSome = stripped.length !== e.messages.length;
93
+ if (!block) {
94
+ // Nothing to report this turn. Only return a rewrite if we actually
95
+ // removed a stale block; otherwise leave the messages untouched.
96
+ return removedSome ? { messages: stripped } : undefined;
97
+ }
98
+ stripped.push({ role: "user", content: [{ type: "text", text: block }] });
99
+ return { messages: stripped };
100
+ });
101
+ };
102
+ }
103
+ //# sourceMappingURL=agent-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-status.js","sourceRoot":"","sources":["../../src/extensions/agent-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * trace-reminder — the one Pi-native extension (replaces #79 captureMilestone).
3
+ *
4
+ * Philosophy (vs. #79): the host no longer writes trace nodes on the agent's
5
+ * behalf. Instead we REMIND the agent at the right moment and let it decide:
6
+ * - 意图一 (work leaves a trace): if a run ended without record_trace, nudge.
7
+ * Applies to BOTH principal and expert (every non-trace role), not just PI.
8
+ * - 意图二 (expert results flow back): if an expert run produced work but never
9
+ * send_message'd the principal, nudge; if it still won't, the host writes a
10
+ * fallback note into the principal's mailbox so the PI never dead-waits.
11
+ * - 意图三 (PI keeps to delegation): if the principal does substantive work
12
+ * directly without delegating, append a soft reminder to the tool result.
13
+ * - 意图四 (resource awareness): on a tool error, append a soft hint that the
14
+ * knowledge tools / record_trace exist. (Static identity lives in personas.)
15
+ *
16
+ * 意图一 and 意图二 are ORTHOGONAL checks (B): an expert can owe both a trace
17
+ * and a reply. They limit independently (A — separate counters), but when BOTH
18
+ * lapse at the same run end they collapse into ONE merged reminder rather than
19
+ * two separate followUps (fewer round-trips).
20
+ *
21
+ * Mechanism (Pi SDK v0.79, verified against installed d.ts + real provider):
22
+ * - Registered per-AgentSession via DefaultResourceLoader.extensionFactories.
23
+ * Closure state is therefore naturally isolated per agent.
24
+ * - One prompt() == one agent loop (agent_start…agent_end) spanning MANY turns.
25
+ * "Did the work" flags are RUN-scoped (reset on agent_start, accumulated
26
+ * across turns) — resetting them on turn_start was the false-report bug.
27
+ * - `agent_end` / `turn_*` are pure notifications (no return value, cannot
28
+ * block). The ONLY "force continue" lever is `pi.sendUserMessage(text,
29
+ * {deliverAs:"followUp"})` inside `agent_end`: it releases the current stop
30
+ * and starts a NEW agent loop (a fresh agent_start) — which is why the
31
+ * anti-loop counters must NOT reset on agent_start.
32
+ * - `tool_result` MAY return `{content}` to rewrite the result text — used for
33
+ * the soft reminders (意图三/四).
34
+ */
35
+ import type { AgentRole } from "../types.js";
36
+ /** Minimal structural surface of Pi's ExtensionAPI we depend on. */
37
+ interface PiExtensionApi {
38
+ on(event: "agent_start", handler: () => void): void;
39
+ on(event: "tool_execution_start", handler: (e: {
40
+ toolName: string;
41
+ args?: unknown;
42
+ }) => void): void;
43
+ on(event: "tool_execution_end", handler: (e: {
44
+ toolName: string;
45
+ isError: boolean;
46
+ }) => void): void;
47
+ on(event: "tool_result", handler: (e: {
48
+ toolName: string;
49
+ isError: boolean;
50
+ content: Array<{
51
+ type: string;
52
+ text?: string;
53
+ }>;
54
+ }) => {
55
+ content: Array<{
56
+ type: "text";
57
+ text: string;
58
+ }>;
59
+ } | void): void;
60
+ on(event: "agent_end", handler: (e: AgentEndLike) => void): void;
61
+ sendUserMessage(content: string, options?: {
62
+ deliverAs?: "steer" | "followUp";
63
+ }): void;
64
+ }
65
+ /**
66
+ * Structural slice of Pi's `AgentEndEvent` we read: the run's message list, used
67
+ * only to detect whether the run ENDED IN AN ERROR (last assistant message's
68
+ * `stopReason`). A provider failure (401, retry exhausted, mid-stream error) is
69
+ * encoded by Pi as a final AssistantMessage with `stopReason: "error" |
70
+ * "aborted"` — it does NOT throw. When that's the case the host owns recovery
71
+ * (#97 self-retry / escalation), so this extension must NOT also nudge/followUp.
72
+ */
73
+ interface AgentEndLike {
74
+ messages?: Array<{
75
+ role?: string;
76
+ stopReason?: string;
77
+ }>;
78
+ }
79
+ export interface TraceReminderDeps {
80
+ role: AgentRole;
81
+ name: string;
82
+ /**
83
+ * 意图二 fallback: invoked when an expert was reminded once and STILL did not
84
+ * report back. The host writes a note into the principal's mailbox.
85
+ */
86
+ onUnreplied: (agentName: string) => void;
87
+ }
88
+ /**
89
+ * Build the extension factory for one agent. The returned function is what Pi
90
+ * calls with the per-session `ExtensionAPI`.
91
+ */
92
+ export declare function makeTraceReminderExt(deps: TraceReminderDeps): (pi: PiExtensionApi) => void;
93
+ export {};
94
+ //# sourceMappingURL=trace-reminder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-reminder.d.ts","sourceRoot":"","sources":["../../src/extensions/trace-reminder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,oEAAoE;AACpE,UAAU,cAAc;IACtB,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACpD,EAAE,CAAC,KAAK,EAAE,sBAAsB,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IACpG,EAAE,CAAC,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IACpG,EAAE,CACA,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,CAAC,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACjD,KAAK;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,GAAG,IAAI,GAC9D,IAAI,CAAC;IACR,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;CACxF;AAED;;;;;;;GAOG;AACH,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D;AAeD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AA2BD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,CAAC,EAAE,EAAE,cAAc,KAAK,IAAI,CAyH1F"}
@@ -0,0 +1,153 @@
1
+ /** True when the run's last assistant message ended in an error/abort. */
2
+ function endedInError(e) {
3
+ const msgs = e.messages;
4
+ if (!Array.isArray(msgs))
5
+ return false;
6
+ for (let i = msgs.length - 1; i >= 0; i--) {
7
+ const m = msgs[i];
8
+ if (m?.role === "assistant") {
9
+ return m.stopReason === "error" || m.stopReason === "aborted";
10
+ }
11
+ }
12
+ return false;
13
+ }
14
+ /**
15
+ * Management/coordination tools that are legitimate for a principal to call
16
+ * directly — they don't count as "doing the work itself" (意图三 exemption).
17
+ */
18
+ const MGMT_TOOLS = new Set([
19
+ "create_agent",
20
+ "destroy_agent",
21
+ "record_trace",
22
+ "send_message",
23
+ "ask_user",
24
+ "get_trace_graph",
25
+ ]);
26
+ const TRACE_REMINDER = "你本轮做了实质工作但尚未调用 record_trace。如果这步值得留痕,请调用 record_trace 记录后再结束。";
27
+ const EXPERT_REPLY_REMINDER = "你尚未通过 send_message(to=\"principal\", ...) 把结果回交给 Principal。请回交结果,否则 Principal 收不到你的产出。";
28
+ const MERGED_REMINDER = "你本轮尚未回交结果,也未记录关键决策。结束前请:" +
29
+ "① 用 send_message(to=\"principal\", ...) 回交结果;" +
30
+ "② 用 record_trace 记录关键决策。";
31
+ const DELEGATE_REMINDER = "[提醒:作为 Principal,实质工作应委派给专家,而不是自己埋头执行。]";
32
+ const TOOL_FAILURE_REMINDER = "[提醒:该工具调用失败。可用 record_trace 记录这次失败,或借助知识库/检索工具寻找替代方案。]";
33
+ /**
34
+ * Build the extension factory for one agent. The returned function is what Pi
35
+ * calls with the per-session `ExtensionAPI`.
36
+ */
37
+ export function makeTraceReminderExt(deps) {
38
+ return (pi) => {
39
+ // Per-RUN flags — reset on agent_start (NOT turn_start). A single prompt()
40
+ // is one agent loop (agent_start…agent_end) spanning MANY turns, and a model
41
+ // naturally calls a tool in one turn then writes its closing sentence in the
42
+ // NEXT (tool-less) turn. Resetting on turn_start wiped the earlier turn's
43
+ // success, so agent_end only ever saw the last turn and falsely reported the
44
+ // work as undone. Keyed to the run, these accumulate across all its turns.
45
+ let traced = false;
46
+ let replied = false;
47
+ let delegated = false;
48
+ let delegateRemindCount = 0;
49
+ // ⚠️ Cross-run-CHAIN counters — MUST NOT reset on agent_start/turn_start nor
50
+ // at the top of agent_end. sendUserMessage(followUp) starts a NEW agent loop
51
+ // (verified: a followUp fires a fresh agent_start) whose end re-enters
52
+ // agent_end; if these were cleared we would re-remind forever. They are reset
53
+ // ONLY at the terminal exits below (dimension satisfied, or already reminded
54
+ // once → fallback/let-go). Decoupled per dimension (A) so a trace reminder
55
+ // and a reply reminder limit independently.
56
+ let traceRemindCount = 0;
57
+ let replyRemindCount = 0;
58
+ pi.on("agent_start", () => {
59
+ traced = false;
60
+ replied = false;
61
+ delegated = false;
62
+ delegateRemindCount = 0;
63
+ });
64
+ // tool_execution_start: nothing required for accounting (we key off
65
+ // tool_execution_end which carries success/failure). Kept as a no-op anchor
66
+ // so the wiring is obvious if richer arg capture is needed later.
67
+ pi.on("tool_execution_end", (e) => {
68
+ if (e.isError)
69
+ return; // only successful calls count toward "did the work"
70
+ const t = e.toolName;
71
+ if (t === "record_trace" || t.startsWith("create_trace"))
72
+ traced = true;
73
+ if (t === "send_message")
74
+ replied = true;
75
+ if (t === "create_agent")
76
+ delegated = true;
77
+ });
78
+ pi.on("tool_result", (e) => {
79
+ // 意图四 (failure hint) takes precedence; 意图三 (over-step) can stack.
80
+ let suffix = "";
81
+ if (e.isError) {
82
+ suffix += `\n${TOOL_FAILURE_REMINDER}`;
83
+ }
84
+ if (deps.role === "principal" &&
85
+ !delegated &&
86
+ !MGMT_TOOLS.has(e.toolName) &&
87
+ delegateRemindCount < 1) {
88
+ delegateRemindCount++;
89
+ suffix += `\n${DELEGATE_REMINDER}`;
90
+ }
91
+ if (!suffix)
92
+ return; // no rewrite — leave the result untouched
93
+ // Rewrite by appending to the existing text content; the tool still ran.
94
+ const text = e.content.map((c) => (c.type === "text" ? c.text ?? "" : "")).join("");
95
+ return { content: [{ type: "text", text: `${text}${suffix}` }] };
96
+ });
97
+ pi.on("agent_end", (e) => {
98
+ if (deps.role === "trace")
99
+ return; // the recorder itself — never nudge.
100
+ // #97: if THIS run ended in an error (provider 401 / retry exhausted /
101
+ // mid-stream failure), bail entirely. A followUp here would just re-hit the
102
+ // broken provider, and onUnreplied would mislabel an error as silence. The
103
+ // host's delivery-loop error path owns recovery (self-retry / escalation).
104
+ if (endedInError(e))
105
+ return;
106
+ // Two ORTHOGONAL checks (B). Both can be true for one expert (it produced
107
+ // work worth tracing AND owes the principal a reply).
108
+ // - 留痕 (trace): every non-trace role is nudged unconditionally when it
109
+ // ends a run without a record_trace.
110
+ // - 回交 (reply): only an expert has a principal to report back to.
111
+ const needTrace = !traced;
112
+ const needReply = deps.role !== "principal" && !replied;
113
+ // A satisfied dimension resets its own counter (so a later real lapse is
114
+ // nudged afresh).
115
+ if (!needTrace)
116
+ traceRemindCount = 0;
117
+ if (!needReply)
118
+ replyRemindCount = 0;
119
+ const canTrace = needTrace && traceRemindCount < 1;
120
+ const canReply = needReply && replyRemindCount < 1;
121
+ // Both lapsed and both still nudge-able → ONE merged reminder, not two.
122
+ if (canTrace && canReply) {
123
+ traceRemindCount++;
124
+ replyRemindCount++;
125
+ pi.sendUserMessage(MERGED_REMINDER, { deliverAs: "followUp" });
126
+ return;
127
+ }
128
+ if (canReply) {
129
+ replyRemindCount++;
130
+ pi.sendUserMessage(EXPERT_REPLY_REMINDER, { deliverAs: "followUp" });
131
+ return;
132
+ }
133
+ if (canTrace) {
134
+ traceRemindCount++;
135
+ pi.sendUserMessage(TRACE_REMINDER, { deliverAs: "followUp" });
136
+ return;
137
+ }
138
+ // Nothing left to nudge (each lapsed dimension was already reminded once).
139
+ // Terminal handling per dimension:
140
+ // - reply has a host fallback so the principal never dead-waits;
141
+ // - trace has none (PI/expert self-decides) — just let it go.
142
+ // ⚠️ counters reset only here (the already-reminded terminal exit).
143
+ if (needReply) {
144
+ deps.onUnreplied(deps.name);
145
+ replyRemindCount = 0;
146
+ }
147
+ if (needTrace) {
148
+ traceRemindCount = 0;
149
+ }
150
+ });
151
+ };
152
+ }
153
+ //# sourceMappingURL=trace-reminder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-reminder.js","sourceRoot":"","sources":["../../src/extensions/trace-reminder.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -23,5 +23,7 @@ export { createServer, startServer } from "./server.js";
23
23
  export type { StartServerOptions } from "./server.js";
24
24
  export { McpBridge, loadMcpServersConfig, defaultMcpConnect } from "./mcp-bridge.js";
25
25
  export type { McpServersConfig, McpServerSpec, McpClientLike, McpConnectFn } from "./mcp-bridge.js";
26
+ export { materializeSkills, resolveBundledSkillsDir } from "./materialize-skills.js";
27
+ export type { MaterializeSkillsResult } from "./materialize-skills.js";
26
28
  export type { AgentRole, IAgentSession, AgentSessionFactory, PiAgentEvent, PiAssistantMessageEvent, SystemTool, SystemToolResult, EventListener, } from "./types.js";
27
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,wBAAwB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EACL,QAAQ,EACR,qBAAqB,EACrB,UAAU,GACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrF,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpG,YAAY,EACV,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,wBAAwB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EACL,QAAQ,EACR,qBAAqB,EACrB,UAAU,GACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrF,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpG,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACrF,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEvE,YAAY,EACV,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -17,4 +17,5 @@ export { allSystemTools, systemToolsForRole, systemToolNamesForRole, builtinTool
17
17
  export { PERSONAS, BUILTIN_PERSONA_NAMES, personaFor, } from "./personas.js";
18
18
  export { createServer, startServer } from "./server.js";
19
19
  export { McpBridge, loadMcpServersConfig, defaultMcpConnect } from "./mcp-bridge.js";
20
+ export { materializeSkills, resolveBundledSkillsDir } from "./materialize-skills.js";
20
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,QAAQ,EACR,qBAAqB,EACrB,UAAU,GACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,QAAQ,EACR,qBAAqB,EACrB,UAAU,GACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGrF,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/mailbox.d.ts CHANGED
@@ -6,6 +6,23 @@ export interface MailboxMessage {
6
6
  msgType: MsgType;
7
7
  timestamp: number;
8
8
  }
9
+ /** Per-agent inbox capacity (#76). A write past this is rejected. */
10
+ export declare const MAX_INBOX = 20;
11
+ /**
12
+ * Default batch limits for one delivery turn (#76). The loop drains at most
13
+ * `BATCH_MAX_MESSAGES`, and stops early once the accumulated content would
14
+ * exceed `BATCH_MAX_CHARS` — except the FIRST message is always taken even if it
15
+ * alone exceeds the budget (so an oversized message is delivered on its own
16
+ * rather than stranded forever).
17
+ */
18
+ export declare const BATCH_MAX_MESSAGES = 3;
19
+ export declare const BATCH_MAX_CHARS = 24000;
20
+ /** Thrown by `write` when the target inbox is at capacity. */
21
+ export declare class MailboxFullError extends Error {
22
+ readonly agent: string;
23
+ readonly limit: number;
24
+ constructor(agent: string, limit: number);
25
+ }
9
26
  export declare class Mailbox {
10
27
  readonly sessionId: string;
11
28
  private readonly baseDir?;
@@ -13,12 +30,31 @@ export declare class Mailbox {
13
30
  private writeChain;
14
31
  constructor(sessionId: string, baseDir?: string | undefined);
15
32
  private inbox;
16
- /** Write a message to `toAgent`'s inbox (in-memory + persisted). */
33
+ /**
34
+ * Write a message to `toAgent`'s inbox (in-memory + persisted). Throws
35
+ * `MailboxFullError` when the inbox is already at `MAX_INBOX` (#76 backpressure
36
+ * — keeps a runaway ping-pong from growing the inbox without bound).
37
+ */
17
38
  write(msg: Omit<MailboxMessage, "timestamp"> & {
18
39
  timestamp?: number;
19
40
  }): Promise<void>;
20
41
  /** Atomically drain `agent`'s inbox (returns messages, clears the box). */
21
42
  read(agent: string): Promise<MailboxMessage[]>;
43
+ /**
44
+ * Drain a bounded batch from the FRONT of `agent`'s inbox (#76). Takes up to
45
+ * `maxMessages`, stopping early once including the next message would push the
46
+ * accumulated content past `maxChars` — except the first message is always
47
+ * taken (an oversized message ships alone rather than stranding). Remaining
48
+ * messages stay queued in order for the next turn. FIFO preserved.
49
+ */
50
+ readBatch(agent: string, maxMessages?: number, maxChars?: number): Promise<MailboxMessage[]>;
51
+ /**
52
+ * Drain EVERY inbox (in-memory + persisted) so no queued message can re-wake
53
+ * an agent. Used by whole-session interrupt (#90 Stop): after aborting all
54
+ * agents we clear their mailboxes, otherwise the delivery loop would re-deliver
55
+ * pending messages and revive the agents the user just stopped.
56
+ */
57
+ clearAll(): Promise<void>;
22
58
  /** Non-destructive peek. */
23
59
  peek(agent: string): readonly MailboxMessage[];
24
60
  count(agent: string): number;
@@ -1 +1 @@
1
- {"version":3,"file":"mailbox.d.ts","sourceRoot":"","sources":["../src/mailbox.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,OAAO,GACf,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,aAAa,GACb,QAAQ,CAAC;AAEb,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,OAAO;IAKhB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IAL3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,UAAU,CAAoC;gBAG3C,SAAS,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,MAAM,YAAA;IAGnC,OAAO,CAAC,KAAK;IASb,oEAAoE;IAC9D,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3F,2EAA2E;IACrE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAOpD,4BAA4B;IAC5B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE;IAI9C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI5B,OAAO,CAAC,SAAS;YAKH,OAAO;IAarB,4EAA4E;IACtE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"mailbox.d.ts","sourceRoot":"","sources":["../src/mailbox.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,OAAO,GACf,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,aAAa,GACb,QAAQ,CAAC;AAEb,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qEAAqE;AACrE,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC,8DAA8D;AAC9D,qBAAa,gBAAiB,SAAQ,KAAK;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM;gBAArC,KAAK,EAAE,MAAM,EAAW,KAAK,EAAE,MAAM;CAI3D;AAED,qBAAa,OAAO;IAKhB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IAL3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,UAAU,CAAoC;gBAG3C,SAAS,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,MAAM,YAAA;IAGnC,OAAO,CAAC,KAAK;IASb;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3F,2EAA2E;IACrE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAOpD;;;;;;OAMG;IACG,SAAS,CACb,KAAK,EAAE,MAAM,EACb,WAAW,SAAqB,EAChC,QAAQ,SAAkB,GACzB,OAAO,CAAC,cAAc,EAAE,CAAC;IAkB5B;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAU/B,4BAA4B;IAC5B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE;IAI9C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI5B,OAAO,CAAC,SAAS;YAKH,OAAO;IAarB,4EAA4E;IACtE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
package/dist/mailbox.js CHANGED
@@ -7,9 +7,36 @@
7
7
  *
8
8
  * Delivery semantics (ported from legacy `mailbox.py`): reading an inbox
9
9
  * atomically drains it (avoids re-delivery). Writes append.
10
+ *
11
+ * Backpressure (#76): an inbox is capped at `MAX_INBOX` messages. A write past
12
+ * the cap throws `MailboxFullError` so the sending tool surfaces the failure to
13
+ * its agent (Pi signals tool failure by throwing) instead of letting a runaway
14
+ * agent↔agent ping-pong grow the inbox without bound.
10
15
  */
11
16
  import { mkdir, readFile, writeFile, readdir } from "node:fs/promises";
12
17
  import { join } from "node:path";
18
+ /** Per-agent inbox capacity (#76). A write past this is rejected. */
19
+ export const MAX_INBOX = 20;
20
+ /**
21
+ * Default batch limits for one delivery turn (#76). The loop drains at most
22
+ * `BATCH_MAX_MESSAGES`, and stops early once the accumulated content would
23
+ * exceed `BATCH_MAX_CHARS` — except the FIRST message is always taken even if it
24
+ * alone exceeds the budget (so an oversized message is delivered on its own
25
+ * rather than stranded forever).
26
+ */
27
+ export const BATCH_MAX_MESSAGES = 3;
28
+ export const BATCH_MAX_CHARS = 24_000;
29
+ /** Thrown by `write` when the target inbox is at capacity. */
30
+ export class MailboxFullError extends Error {
31
+ agent;
32
+ limit;
33
+ constructor(agent, limit) {
34
+ super(`mailbox for "${agent}" is full (limit ${limit}); message rejected`);
35
+ this.agent = agent;
36
+ this.limit = limit;
37
+ this.name = "MailboxFullError";
38
+ }
39
+ }
13
40
  export class Mailbox {
14
41
  sessionId;
15
42
  baseDir;
@@ -27,10 +54,17 @@ export class Mailbox {
27
54
  }
28
55
  return box;
29
56
  }
30
- /** Write a message to `toAgent`'s inbox (in-memory + persisted). */
57
+ /**
58
+ * Write a message to `toAgent`'s inbox (in-memory + persisted). Throws
59
+ * `MailboxFullError` when the inbox is already at `MAX_INBOX` (#76 backpressure
60
+ * — keeps a runaway ping-pong from growing the inbox without bound).
61
+ */
31
62
  async write(msg) {
63
+ const box = this.inbox(msg.toAgent);
64
+ if (box.length >= MAX_INBOX)
65
+ throw new MailboxFullError(msg.toAgent, MAX_INBOX);
32
66
  const full = { ...msg, timestamp: msg.timestamp ?? Date.now() };
33
- this.inbox(full.toAgent).push(full);
67
+ box.push(full);
34
68
  await this.persist(full.toAgent);
35
69
  }
36
70
  /** Atomically drain `agent`'s inbox (returns messages, clears the box). */
@@ -41,6 +75,49 @@ export class Mailbox {
41
75
  await this.persist(agent);
42
76
  return out;
43
77
  }
78
+ /**
79
+ * Drain a bounded batch from the FRONT of `agent`'s inbox (#76). Takes up to
80
+ * `maxMessages`, stopping early once including the next message would push the
81
+ * accumulated content past `maxChars` — except the first message is always
82
+ * taken (an oversized message ships alone rather than stranding). Remaining
83
+ * messages stay queued in order for the next turn. FIFO preserved.
84
+ */
85
+ async readBatch(agent, maxMessages = BATCH_MAX_MESSAGES, maxChars = BATCH_MAX_CHARS) {
86
+ const box = this.inbox(agent);
87
+ if (box.length === 0)
88
+ return [];
89
+ const take = [];
90
+ let chars = 0;
91
+ for (const m of box) {
92
+ if (take.length >= maxMessages)
93
+ break;
94
+ const next = chars + m.content.length;
95
+ // Always take the first; otherwise respect the char budget.
96
+ if (take.length > 0 && next > maxChars)
97
+ break;
98
+ take.push(m);
99
+ chars = next;
100
+ }
101
+ box.splice(0, take.length);
102
+ await this.persist(agent);
103
+ return take;
104
+ }
105
+ /**
106
+ * Drain EVERY inbox (in-memory + persisted) so no queued message can re-wake
107
+ * an agent. Used by whole-session interrupt (#90 Stop): after aborting all
108
+ * agents we clear their mailboxes, otherwise the delivery loop would re-deliver
109
+ * pending messages and revive the agents the user just stopped.
110
+ */
111
+ async clearAll() {
112
+ const agents = [...this.inboxes.keys()];
113
+ for (const agent of agents) {
114
+ const box = this.inbox(agent);
115
+ if (box.length === 0)
116
+ continue;
117
+ box.length = 0;
118
+ await this.persist(agent);
119
+ }
120
+ }
44
121
  /** Non-destructive peek. */
45
122
  peek(agent) {
46
123
  return [...this.inbox(agent)];
@@ -1 +1 @@
1
- {"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../src/mailbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../src/mailbox.ts"],"names":[],"mappings":"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"}