@sema-agent/core 3.0.0 → 5.0.0

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 (153) hide show
  1. package/CHANGELOG.md +2382 -0
  2. package/dist/agents/cascade.d.ts +3 -1
  3. package/dist/agents/cascade.js +31 -32
  4. package/dist/agents/cumulative-stats.d.ts +29 -0
  5. package/dist/agents/cumulative-stats.js +29 -0
  6. package/dist/agents/observer.d.ts +4 -0
  7. package/dist/agents/observer.js +11 -10
  8. package/dist/agents/repair-loop.d.ts +2 -0
  9. package/dist/agents/repair-loop.js +48 -24
  10. package/dist/agents/retain-ledger.d.ts +2 -0
  11. package/dist/agents/retain-ledger.js +6 -5
  12. package/dist/agents/roster-store.d.ts +1 -0
  13. package/dist/agents/roster-store.js +3 -5
  14. package/dist/agents/send-message-tool.d.ts +1 -0
  15. package/dist/agents/send-message-tool.js +2 -0
  16. package/dist/agents/subagent.d.ts +3 -1
  17. package/dist/agents/subagent.js +79 -94
  18. package/dist/agents/teacher.d.ts +1 -9
  19. package/dist/agents/teacher.js +21 -24
  20. package/dist/agents/tool-filter.js +6 -7
  21. package/dist/agents/verify.d.ts +1 -0
  22. package/dist/agents/verify.js +15 -14
  23. package/dist/brain/anthropic.js +24 -21
  24. package/dist/brain/openai.js +24 -21
  25. package/dist/brain/stream-engine.js +5 -2
  26. package/dist/brain/stream-shared.d.ts +1 -0
  27. package/dist/brain/stream-shared.js +14 -0
  28. package/dist/brain/terminal-cause.d.ts +4 -0
  29. package/dist/brain/terminal-cause.js +12 -0
  30. package/dist/brain/tool-call-id.d.ts +1 -0
  31. package/dist/brain/tool-call-id.js +3 -0
  32. package/dist/brain/tool-call-repair.js +2 -1
  33. package/dist/core/arg-summary.d.ts +21 -1
  34. package/dist/core/arg-summary.js +61 -14
  35. package/dist/core/auto-compaction.d.ts +1 -0
  36. package/dist/core/auto-compaction.js +16 -25
  37. package/dist/core/background-agent-store.d.ts +22 -22
  38. package/dist/core/background-agent-store.js +19 -23
  39. package/dist/core/checkpoint-store.d.ts +6 -13
  40. package/dist/core/checkpoint-store.js +11 -5
  41. package/dist/core/file-snapshot-store.d.ts +8 -0
  42. package/dist/core/file-snapshot-store.js +4 -3
  43. package/dist/core/fs-write-gate-policy.js +2 -3
  44. package/dist/core/hooks.d.ts +4 -1
  45. package/dist/core/hooks.js +8 -18
  46. package/dist/core/lsp.js +4 -3
  47. package/dist/core/mailbox-store.d.ts +7 -10
  48. package/dist/core/mcp.d.ts +7 -10
  49. package/dist/core/mcp.js +7 -9
  50. package/dist/core/memory-engine/engine.d.ts +0 -1
  51. package/dist/core/memory-engine/engine.js +24 -34
  52. package/dist/core/memory-engine/file-backend.d.ts +1 -2
  53. package/dist/core/memory-engine/file-backend.js +25 -36
  54. package/dist/core/memory-engine/layout.d.ts +8 -0
  55. package/dist/core/memory-engine/layout.js +60 -4
  56. package/dist/core/memory-engine/scope-contract.js +9 -3
  57. package/dist/core/memory-engine/types.d.ts +1 -1
  58. package/dist/core/permission-rules.js +2 -3
  59. package/dist/core/runner/active-skill-scope.d.ts +0 -1
  60. package/dist/core/runner/active-skill-scope.js +2 -17
  61. package/dist/core/runner/assemble-result.d.ts +2 -7
  62. package/dist/core/runner/assemble-result.js +3 -4
  63. package/dist/core/runner/compaction-call-options.d.ts +7 -0
  64. package/dist/core/runner/compaction-call-options.js +30 -0
  65. package/dist/core/runner/prepare-task.d.ts +6 -23
  66. package/dist/core/runner/prepare-task.js +36 -61
  67. package/dist/core/runner/runtask.d.ts +1 -0
  68. package/dist/core/runner/runtask.js +84 -172
  69. package/dist/core/runner/session-rule-policy.js +7 -5
  70. package/dist/core/runner/teardown-bounded.d.ts +7 -0
  71. package/dist/core/runner/teardown-bounded.js +36 -0
  72. package/dist/core/runner/tool-disclosure.d.ts +2 -5
  73. package/dist/core/runner/turn-attachments.d.ts +5 -15
  74. package/dist/core/runner/turn-attachments.js +1 -1
  75. package/dist/core/safe-notify.d.ts +17 -0
  76. package/dist/core/safe-notify.js +59 -0
  77. package/dist/core/sensitive-path-policy.js +4 -4
  78. package/dist/core/session-reconcile.js +1 -2
  79. package/dist/core/skill-tool-specifier.js +2 -3
  80. package/dist/core/skills-directory.js +2 -3
  81. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  82. package/dist/core/stub-env.d.ts +2 -6
  83. package/dist/core/surrogate-safe-slice.d.ts +4 -0
  84. package/dist/core/surrogate-safe-slice.js +18 -0
  85. package/dist/core/task-registry-monitor.js +8 -13
  86. package/dist/core/task-registry-shared.d.ts +23 -1
  87. package/dist/core/task-registry-shared.js +16 -0
  88. package/dist/core/task-registry.d.ts +6 -1
  89. package/dist/core/task-registry.js +52 -87
  90. package/dist/core/task-tool-shape.d.ts +0 -2
  91. package/dist/core/task-tool-shape.js +2 -5
  92. package/dist/core/tool-errors.js +5 -4
  93. package/dist/core/tool-name-aliases.d.ts +1 -2
  94. package/dist/core/tool-name-aliases.js +42 -59
  95. package/dist/core/tool-policy.js +21 -17
  96. package/dist/core/tool-result-store.d.ts +1 -0
  97. package/dist/core/tool-result-store.js +17 -1
  98. package/dist/core/trace.d.ts +9 -9
  99. package/dist/core/types.d.ts +15 -12
  100. package/dist/core/untrusted-egress.d.ts +4 -2
  101. package/dist/core/untrusted-egress.js +28 -14
  102. package/dist/core/workflow-journal-store.d.ts +9 -20
  103. package/dist/core/workflow-run-store.d.ts +11 -10
  104. package/dist/core/workflow-run-store.js +22 -16
  105. package/dist/engine/compaction/utils.js +4 -2
  106. package/dist/engine/execution-env/node-execution-env.d.ts +2 -24
  107. package/dist/engine/execution-env/node-execution-env.js +1 -1
  108. package/dist/engine/harness/agent-harness.d.ts +1 -0
  109. package/dist/engine/harness/agent-harness.js +13 -33
  110. package/dist/engine/harness/types.d.ts +29 -67
  111. package/dist/engine/llm/types.d.ts +1 -1
  112. package/dist/engine/loop/agent-loop.js +12 -14
  113. package/dist/engine/loop/types.d.ts +11 -9
  114. package/dist/engine/session/memory-repo.d.ts +2 -6
  115. package/dist/engine/session/session.d.ts +5 -30
  116. package/dist/index.d.ts +6 -3
  117. package/dist/index.js +4 -3
  118. package/dist/internal/harness-types.d.ts +3 -1
  119. package/dist/orchestration/run-spec.js +6 -4
  120. package/dist/orchestration/run-workflow-tool.js +3 -36
  121. package/dist/orchestration/workflow-governance.js +2 -1
  122. package/dist/orchestration/workflow.d.ts +4 -11
  123. package/dist/orchestration/workflow.js +164 -204
  124. package/dist/prompt-assembly/packs/sema-default.js +1 -3
  125. package/dist/prompt-assembly/tool-catalog.d.ts +10 -9
  126. package/dist/prompt-assembly/turn-snapshot.d.ts +2 -5
  127. package/dist/prompts/default.js +1 -3
  128. package/dist/prompts/simple-sections.d.ts +0 -1
  129. package/dist/prompts/simple-sections.js +0 -1
  130. package/dist/stores/file/background-agent-store.d.ts +3 -12
  131. package/dist/stores/file/background-agent-store.js +3 -41
  132. package/dist/stores/file/checkpoint-store.js +6 -6
  133. package/dist/stores/file/mailbox-store.d.ts +2 -6
  134. package/dist/stores/file/session-policy-store.js +15 -1
  135. package/dist/stores/file/session-store.d.ts +2 -6
  136. package/dist/stores/file/workflow-journal-store.d.ts +3 -11
  137. package/dist/stores/file/workflow-run-store.d.ts +3 -7
  138. package/dist/stores/file/workflow-run-store.js +4 -17
  139. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -0
  140. package/dist/tools/fs/bash-readonly-classifier.js +60 -25
  141. package/dist/tools/fs/fs-bash.js +330 -104
  142. package/dist/tools/fs/fs-pdf.d.ts +2 -12
  143. package/dist/tools/fs/fs-shared.js +2 -2
  144. package/dist/tools/fs/fs-write.js +0 -1
  145. package/dist/tools/fs/notebook.d.ts +2 -5
  146. package/dist/tools/fs/safety.d.ts +3 -0
  147. package/dist/tools/fs/safety.js +43 -14
  148. package/dist/tools/fs/search.js +5 -5
  149. package/dist/tools/monitor.d.ts +1 -0
  150. package/dist/tools/monitor.js +7 -5
  151. package/dist/tools/worktree.d.ts +2 -7
  152. package/dist/tools/worktree.js +3 -1
  153. package/package.json +6 -2
@@ -1,3 +1,4 @@
1
+ import type { McpDroppedTool } from "../mcp.js";
1
2
  import { type SkillListingEntry } from "./synthetic-tools.js";
2
3
  export declare const TODO_REMINDER_CONFIG: {
3
4
  readonly TURNS_SINCE_WRITE: 10;
@@ -112,11 +113,7 @@ export interface AttachmentInputs {
112
113
  }>;
113
114
  removed: readonly string[];
114
115
  };
115
- mcpDroppedTools?: ReadonlyArray<{
116
- server: string;
117
- tool: string;
118
- reason: string;
119
- }>;
116
+ mcpDroppedTools?: ReadonlyArray<McpDroppedTool>;
120
117
  }
121
118
  export declare function collectDueAttachments(state: AttachmentState, inp: AttachmentInputs): readonly TurnAttachment[];
122
119
  export declare function renderToolSearchUsageReminder(undiscovered: readonly string[]): string;
@@ -178,14 +175,7 @@ export declare function renderMcpInstructionsDelta(added: ReadonlyArray<{
178
175
  server: string;
179
176
  text: string;
180
177
  }>, removed: readonly string[]): string | undefined;
181
- export declare function renderMcpDroppedTools(entries: ReadonlyArray<{
182
- server: string;
183
- tool: string;
184
- reason: string;
185
- }>): string;
178
+ export declare function renderMcpDroppedTools(entries: ReadonlyArray<McpDroppedTool>): string;
186
179
  export declare const MCP_DROPPED_BATCH_MAX_BYTES = 4096;
187
- export declare function selectMcpDroppedBatch<T extends {
188
- server: string;
189
- tool: string;
190
- reason: string;
191
- }>(entries: ReadonlyArray<T>): T[];
180
+ export declare function selectMcpDroppedBatch<T extends McpDroppedTool>(entries: ReadonlyArray<T>): T[];
181
+ export declare function clipToBytes(s: string, maxBytes: number): string;
@@ -634,7 +634,7 @@ function capAttachments(atts) {
634
634
  }
635
635
  return out;
636
636
  }
637
- function clipToBytes(s, maxBytes) {
637
+ export function clipToBytes(s, maxBytes) {
638
638
  if (Buffer.byteLength(s, "utf8") <= maxBytes)
639
639
  return s;
640
640
  let lo = 0;
@@ -0,0 +1,17 @@
1
+ export interface SafeNotifyFailure {
2
+ readonly site: string;
3
+ readonly error: Error;
4
+ readonly failures: number;
5
+ }
6
+ export interface SafeNotifierOptions {
7
+ readonly onError?: (failure: SafeNotifyFailure) => void;
8
+ }
9
+ export interface SafeNotifier {
10
+ notify(run: () => void, site: string): boolean;
11
+ notifyAsync(run: () => unknown, site: string): Promise<boolean>;
12
+ readonly failures: number;
13
+ failuresAt(site: string): number;
14
+ lastErrorAt(site: string): Error | undefined;
15
+ failedSites(): readonly string[];
16
+ }
17
+ export declare function createSafeNotifier(opts?: SafeNotifierOptions): SafeNotifier;
@@ -0,0 +1,59 @@
1
+ export function createSafeNotifier(opts) {
2
+ const onError = opts?.onError;
3
+ let sites;
4
+ let total = 0;
5
+ const record = (site, thrown) => {
6
+ const error = thrown instanceof Error ? thrown : new Error(String(thrown));
7
+ total += 1;
8
+ if (sites === undefined)
9
+ sites = new Map();
10
+ const state = sites.get(site);
11
+ if (state !== undefined) {
12
+ state.count += 1;
13
+ state.last = error;
14
+ return;
15
+ }
16
+ sites.set(site, { count: 1, last: error });
17
+ if (onError === undefined)
18
+ return;
19
+ try {
20
+ onError({ site, error, failures: 1 });
21
+ }
22
+ catch {
23
+ }
24
+ };
25
+ return {
26
+ notify(run, site) {
27
+ try {
28
+ run();
29
+ return true;
30
+ }
31
+ catch (e) {
32
+ record(site, e);
33
+ return false;
34
+ }
35
+ },
36
+ async notifyAsync(run, site) {
37
+ try {
38
+ await run();
39
+ return true;
40
+ }
41
+ catch (e) {
42
+ record(site, e);
43
+ return false;
44
+ }
45
+ },
46
+ get failures() {
47
+ return total;
48
+ },
49
+ failuresAt(site) {
50
+ return sites?.get(site)?.count ?? 0;
51
+ },
52
+ lastErrorAt(site) {
53
+ return sites?.get(site)?.last;
54
+ },
55
+ failedSites() {
56
+ return sites === undefined ? [] : [...sites.keys()];
57
+ },
58
+ };
59
+ }
@@ -1,5 +1,4 @@
1
1
  import { canonicalizeTarget, writeTargetPath } from "../tools/fs/safety.js";
2
- import { canonicalToolName } from "./tool-name-aliases.js";
3
2
  const DEFAULT_GUARDED_TOOLS = ["Write", "Edit", "MultiEdit", "NotebookEdit"];
4
3
  export const RECOMMENDED_SENSITIVE_PATTERNS = [
5
4
  ".env",
@@ -28,8 +27,9 @@ export const RECOMMENDED_SENSITIVE_PATTERNS = [
28
27
  ];
29
28
  function segmentGlobToRegExp(segment) {
30
29
  const escaped = segment.replace(/[.+^${}()|[\]\\?]/g, "\\$&").replace(/\*/g, "[^/]*");
31
- return new RegExp(`^${escaped}$`);
30
+ return new RegExp(`^${escaped}$`, CASE_INSENSITIVE_FS ? "i" : "");
32
31
  }
32
+ const CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
33
33
  function compilePatterns(patterns) {
34
34
  const out = [];
35
35
  for (const raw of patterns) {
@@ -55,10 +55,10 @@ function matchSensitive(canonicalKey, compiled) {
55
55
  }
56
56
  export function createSensitivePathPolicy(opts) {
57
57
  const compiled = compilePatterns(opts.patterns);
58
- const guarded = new Set((opts.tools ?? DEFAULT_GUARDED_TOOLS).map(canonicalToolName));
58
+ const guarded = new Set(opts.tools ?? DEFAULT_GUARDED_TOOLS);
59
59
  return {
60
60
  async check(req, signal) {
61
- const canonical = canonicalToolName(req.toolName);
61
+ const canonical = req.toolName;
62
62
  if (compiled.length === 0 || !guarded.has(canonical))
63
63
  return { action: "allow" };
64
64
  const path = writeTargetPath(canonical, req.args);
@@ -1,4 +1,3 @@
1
- import { canonicalToolName } from "./tool-name-aliases.js";
2
1
  const INTERRUPTED_UNKNOWN = "[INTERRUPTED] The previous run ended before this tool call's result was recorded. Its outcome " +
3
2
  "is UNKNOWN — the action may have completed, partially completed, or never run. Do not assume " +
4
3
  "success or failure. Before relying on it: if it is safe to read, query the current state to " +
@@ -72,7 +71,7 @@ export async function reconcileInterruptedSession(session, toolEffects, suspende
72
71
  const orphans = findOrphanToolCalls(messages, suspendedBatch).filter((o) => o.kind !== "result");
73
72
  const recovered = [];
74
73
  for (const orphan of orphans) {
75
- const effect = toolEffects?.get(canonicalToolName(orphan.toolName)) ?? "write";
74
+ const effect = toolEffects?.get(orphan.toolName) ?? "write";
76
75
  const effectText = effect === "read" ? INTERRUPTED_SAFE : effect === "idempotent" ? INTERRUPTED_IDEMPOTENT : INTERRUPTED_UNKNOWN;
77
76
  const neverStarted = startedToolCallIds !== undefined && !startedToolCallIds.has(orphan.toolCallId);
78
77
  const text = neverStarted ? INTERRUPTED_NEVER_STARTED : effectText;
@@ -1,11 +1,10 @@
1
1
  import { parsePermissionRule, wildcardMatch } from "./permission-rules.js";
2
- import { canonicalToolName } from "./tool-name-aliases.js";
3
2
  import { COARSE_SHELL_TOOLS } from "./tool-policy.js";
4
3
  import { parseLeadingCommandName } from "../tools/fs/bash-readonly-classifier.js";
5
- const SPECIFIER_ENFORCED_TOOLS = new Set(COARSE_SHELL_TOOLS.map(canonicalToolName));
4
+ const SPECIFIER_ENFORCED_TOOLS = new Set(COARSE_SHELL_TOOLS);
6
5
  export function parseSkillToolEntry(entry) {
7
6
  const parsed = parsePermissionRule(entry);
8
- const name = canonicalToolName(parsed.toolName);
7
+ const name = parsed.toolName;
9
8
  return parsed.ruleContent === undefined ? { raw: entry, name } : { raw: entry, name, specifier: parsed.ruleContent };
10
9
  }
11
10
  export function isSkillSpecifierEnforced(canonicalName) {
@@ -1,6 +1,5 @@
1
1
  import { readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
2
2
  import { isAbsolute, join, relative } from "node:path";
3
- import { canonicalToolName } from "./tool-name-aliases.js";
4
3
  import { isSkillSpecifierEnforced, parseSkillToolEntry } from "./skill-tool-specifier.js";
5
4
  const SKILL_FILE = "SKILL.md";
6
5
  const RESOURCE_DIRS = ["assets", "references", "scripts"];
@@ -340,7 +339,7 @@ function manifestFromAllowedTools(declared, disallowed, skillName, deployedTools
340
339
  return undefined;
341
340
  let allowTools = names;
342
341
  if (deployedTools !== undefined) {
343
- const mounted = new Set(deployedTools.map(canonicalToolName));
342
+ const mounted = new Set(deployedTools);
344
343
  allowTools = names.filter((n) => mounted.has(parseSkillToolEntry(n).name));
345
344
  for (const n of names) {
346
345
  if (!mounted.has(parseSkillToolEntry(n).name)) {
@@ -353,7 +352,7 @@ function manifestFromAllowedTools(declared, disallowed, skillName, deployedTools
353
352
  }
354
353
  }
355
354
  if (disallowed.length > 0) {
356
- const denied = new Set(disallowed.map(canonicalToolName));
355
+ const denied = new Set(disallowed);
357
356
  allowTools = allowTools.filter((n) => !denied.has(parseSkillToolEntry(n).name));
358
357
  }
359
358
  return { allowTools, lineageId: `skill:${skillName}` };
@@ -20,7 +20,7 @@ export function createCheckpointFixture(over = {}) {
20
20
  },
21
21
  state: {
22
22
  activeTools: [],
23
- nestedStats: { tokens: 0, turns: 0, tasks: 0, costMicroUsd: 0 },
23
+ nestedStats: { tokens: 0, turns: 0, tasks: 0, costMicroUsd: 0, anyUnpriced: false },
24
24
  },
25
25
  status: "pending",
26
26
  createdAt: 1_700_000_000_000,
@@ -1,4 +1,4 @@
1
- import { type ExecutionEnv, ExecutionError, FileError, type FileInfo, type Result } from "../internal/harness.js";
1
+ import { type ExecResult, type ExecutionEnv, ExecutionError, FileError, type FileInfo, type Result } from "../internal/harness.js";
2
2
  export declare class StubExecutionEnv implements ExecutionEnv {
3
3
  cwd: string;
4
4
  constructor(cwd?: string);
@@ -18,10 +18,6 @@ export declare class StubExecutionEnv implements ExecutionEnv {
18
18
  remove(path: string): Promise<Result<void, FileError>>;
19
19
  createTempDir(): Promise<Result<string, FileError>>;
20
20
  createTempFile(): Promise<Result<string, FileError>>;
21
- exec(): Promise<Result<{
22
- stdout: string;
23
- stderr: string;
24
- exitCode: number;
25
- }, ExecutionError>>;
21
+ exec(): Promise<Result<ExecResult, ExecutionError>>;
26
22
  cleanup(): Promise<void>;
27
23
  }
@@ -0,0 +1,4 @@
1
+ export declare const isHighSurrogate: (c: number) => boolean;
2
+ export declare const isLowSurrogate: (c: number) => boolean;
3
+ export declare function sliceHeadSafe(s: string, keep: number): string;
4
+ export declare function sliceTailSafe(s: string, keep: number): string;
@@ -0,0 +1,18 @@
1
+ export const isHighSurrogate = (c) => c >= 0xd800 && c <= 0xdbff;
2
+ export const isLowSurrogate = (c) => c >= 0xdc00 && c <= 0xdfff;
3
+ export function sliceHeadSafe(s, keep) {
4
+ if (keep <= 0)
5
+ return "";
6
+ if (s.length <= keep)
7
+ return s;
8
+ const head = s.slice(0, keep);
9
+ return keep > 0 && isHighSurrogate(head.charCodeAt(keep - 1)) ? head.slice(0, -1) : head;
10
+ }
11
+ export function sliceTailSafe(s, keep) {
12
+ if (keep <= 0)
13
+ return "";
14
+ if (s.length <= keep)
15
+ return s;
16
+ const tail = s.slice(-keep);
17
+ return keep > 0 && isLowSurrogate(tail.charCodeAt(0)) ? tail.slice(1) : tail;
18
+ }
@@ -1,5 +1,5 @@
1
1
  import { delimitUntrusted } from "./untrusted-text.js";
2
- import { assertOwnership, defaultMonitorTimers, MONITOR_MAX_TIMEOUT_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_BATCH_WINDOW_MS, MONITOR_MAX_BATCHES_PER_MINUTE, MONITOR_STORM_BURST, MONITOR_STORM_KILL_AFTER_MS, MONITOR_LINE_BUF_CAP, MONITOR_SPILL_CAP_CHARS, TASK_OUTPUT_MAX_CHARS, mintCompletionId, clipMonitorEvent, clipMonitorLine, terminalTaskSummary, accountDroppedBytes, rollSpoolText, statusFromBackground, droppedGapNote, firstDropNote, alreadyTerminalStopNote, clipTaskOutput, sleepPollStep, } from "./task-registry-shared.js";
2
+ import { assertOwnership, defaultMonitorTimers, MONITOR_MAX_TIMEOUT_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_BATCH_WINDOW_MS, MONITOR_MAX_BATCHES_PER_MINUTE, MONITOR_STORM_BURST, MONITOR_STORM_KILL_AFTER_MS, MONITOR_LINE_BUF_CAP, MONITOR_SPILL_CAP_CHARS, TASK_OUTPUT_MAX_CHARS, mintCompletionId, clipMonitorEvent, clipMonitorLine, terminalTaskSummary, accountDroppedBytes, renderSpoolBody, rollSpoolText, statusFromBackground, droppedGapNote, firstDropNote, alreadyTerminalStopNote, clipTaskOutput, sleepPollStep, } from "./task-registry-shared.js";
3
3
  import { buildToolResultRef, OFFLOAD_TOOL_NAME } from "./tool-result-store.js";
4
4
  export function registerMonitorLane(core, input) {
5
5
  assertOwnership(input, "registerMonitor");
@@ -318,18 +318,13 @@ export async function pollMonitorLane(handle, filter, deadline, signal) {
318
318
  const shape = (text) => clipTaskOutput(rx ? text.split(/\r?\n/).filter((l) => rx.test(l)).join("\n") : text, handle.outputFile);
319
319
  const running = handle.status === "running";
320
320
  const retrieval = running && deadline !== undefined && Date.now() >= deadline ? "timeout" : "success";
321
- const timedOutClause = spool.timedOut === true ? ` (timed out after ${spool.timeoutSec !== undefined ? `${spool.timeoutSec}s` : "its background time budget"})` : "";
322
- const displayStatus = (spool.exitCode !== undefined ? `exited(code ${spool.exitCode})` : running ? "running" : handle.status) + timedOutClause;
323
- const rolledNote = spool.rolledChars > 0 ? `[!] ${spool.rolledChars} earlier char(s) dropped from the spool (memory bound)${monitorSpillNote(handle)}\n` : "";
324
- const droppedNote = (spool.droppedBytes ?? 0) > 0
325
- ? `[!] ${spool.droppedBytes} earlier byte(s) permanently dropped before this window (8MB buffer evicted)\n`
326
- : spool.dropUnknown === true
327
- ? "[!] an unknown amount of earlier output was permanently dropped before this window (buffer evicted)\n"
328
- : "";
329
- const drainNote = spool.drainFailed === true ? "[!] the final output drain at stop failed — the tail of the output may be missing\n" : "";
330
- const stdoutHeading = droppedNote !== "" || drainNote !== "" ? "stdout (re-readable spool — INCOMPLETE, see note above)" : "stdout (full, re-readable)";
331
- const body = `status: ${displayStatus}\n${rolledNote}${droppedNote}${drainNote}--- ${stdoutHeading} ---\n${shape(spool.stdout) || "(none)"}\n` +
332
- `--- stderr ---\n${shape(spool.stderr) || "(none)"}`;
321
+ const body = renderSpoolBody(spool, {
322
+ running,
323
+ handleStatus: handle.status,
324
+ shape,
325
+ rolledExtraClause: monitorSpillNote(handle),
326
+ drainNote: spool.drainFailed === true ? "[!] the final output drain at stop failed — the tail of the output may be missing\n" : "",
327
+ });
333
328
  return {
334
329
  content: delimitUntrusted(`TaskOutput ${handle.id}`, body),
335
330
  details: {
@@ -104,7 +104,7 @@ export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
104
104
  durable?: DurableAgentLane;
105
105
  notify?: (notification: import("./task-notification.js").TaskNotificationPayload, opts?: {
106
106
  priority?: import("./task-notification.js").SystemInjectionPriority;
107
- }) => void | "queued" | "parked" | "dropped_duplicate" | Promise<"queued" | "parked" | "dropped_duplicate">;
107
+ }) => "queued" | "parked" | "dropped_duplicate" | Promise<"queued" | "parked" | "dropped_duplicate">;
108
108
  retainedContinuation?: boolean;
109
109
  reviveCycle?: number;
110
110
  cycleSeq?: number;
@@ -252,6 +252,28 @@ export declare function accountDroppedBytes(spool: {
252
252
  truncated?: boolean;
253
253
  bytesDroppedBeforeCursor?: number;
254
254
  }): void;
255
+ export declare function spoolDropNote(acct: {
256
+ droppedBytes?: number;
257
+ dropUnknown?: true;
258
+ }): string;
259
+ export interface RenderableSpool {
260
+ stdout: string;
261
+ stderr: string;
262
+ rolledChars: number;
263
+ exitCode?: number;
264
+ timedOut?: boolean;
265
+ timeoutSec?: number;
266
+ droppedBytes?: number;
267
+ dropUnknown?: true;
268
+ }
269
+ export interface SpoolBodyOptions {
270
+ running: boolean;
271
+ handleStatus: SemaTaskStatus;
272
+ shape: (text: string) => string;
273
+ rolledExtraClause: string;
274
+ drainNote: string;
275
+ }
276
+ export declare function renderSpoolBody(spool: RenderableSpool, opts: SpoolBodyOptions): string;
255
277
  export declare function droppedGapNote(spool: {
256
278
  droppedBytes?: number;
257
279
  dropUnknown?: true;
@@ -102,6 +102,22 @@ export function accountDroppedBytes(spool, poll) {
102
102
  else if (poll.truncated === true)
103
103
  spool.dropUnknown = true;
104
104
  }
105
+ export function spoolDropNote(acct) {
106
+ if ((acct.droppedBytes ?? 0) > 0)
107
+ return `[!] ${acct.droppedBytes} earlier byte(s) permanently dropped before this window (8MB buffer evicted)\n`;
108
+ if (acct.dropUnknown === true)
109
+ return "[!] an unknown amount of earlier output was permanently dropped before this window (buffer evicted)\n";
110
+ return "";
111
+ }
112
+ export function renderSpoolBody(spool, opts) {
113
+ const timedOutClause = spool.timedOut === true ? ` (timed out after ${spool.timeoutSec !== undefined ? `${spool.timeoutSec}s` : "its background time budget"})` : "";
114
+ const displayStatus = (spool.exitCode !== undefined ? `exited(code ${spool.exitCode})` : opts.running ? "running" : opts.handleStatus) + timedOutClause;
115
+ const rolledNote = spool.rolledChars > 0 ? `[!] ${spool.rolledChars} earlier char(s) dropped from the spool (memory bound)${opts.rolledExtraClause}\n` : "";
116
+ const droppedNote = spoolDropNote(spool);
117
+ const stdoutHeading = droppedNote !== "" || opts.drainNote !== "" ? "stdout (re-readable spool — INCOMPLETE, see note above)" : "stdout (full, re-readable)";
118
+ return (`status: ${displayStatus}\n${rolledNote}${droppedNote}${opts.drainNote}--- ${stdoutHeading} ---\n${opts.shape(spool.stdout) || "(none)"}\n` +
119
+ `--- stderr ---\n${opts.shape(spool.stderr) || "(none)"}`);
120
+ }
105
121
  export function droppedGapNote(spool) {
106
122
  if ((spool.droppedBytes ?? 0) > 0)
107
123
  return ` [!] ${spool.droppedBytes} earlier byte(s) of output were permanently dropped before this window (execution-environment tail buffer evicted) — the event stream and this spool are INCOMPLETE.`;
@@ -63,12 +63,17 @@ export interface AccessibleTaskRow {
63
63
  parentTaskId?: string;
64
64
  parentSessionId?: string;
65
65
  rootSessionId?: string;
66
+ createdAt?: number;
66
67
  }
67
68
  export declare class TaskRegistry {
68
69
  private handles;
69
70
  private sessionReapHooks;
70
71
  private bgQuiescenceWatchers;
71
- private legacyToTaskId;
72
+ private readonly notifier;
73
+ notifierFailureCounts(): ReadonlyArray<{
74
+ site: string;
75
+ count: number;
76
+ }>;
72
77
  private readonly core;
73
78
  durableAgentArmed(id: string): boolean;
74
79
  durableAgentRowProbe(id: string): (() => Promise<boolean>) | undefined;