maestro-agent-sdk 0.1.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 (196) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +24 -0
  3. package/README.md +133 -0
  4. package/dist/agents/contracts.d.ts +49 -0
  5. package/dist/agents/contracts.d.ts.map +1 -0
  6. package/dist/agents/contracts.js +2 -0
  7. package/dist/agents/contracts.js.map +1 -0
  8. package/dist/agents/rollout/shared.d.ts +24 -0
  9. package/dist/agents/rollout/shared.d.ts.map +1 -0
  10. package/dist/agents/rollout/shared.js +105 -0
  11. package/dist/agents/rollout/shared.js.map +1 -0
  12. package/dist/core/agent.d.ts +71 -0
  13. package/dist/core/agent.d.ts.map +1 -0
  14. package/dist/core/agent.js +22 -0
  15. package/dist/core/agent.js.map +1 -0
  16. package/dist/core/loop.d.ts +26 -0
  17. package/dist/core/loop.d.ts.map +1 -0
  18. package/dist/core/loop.js +317 -0
  19. package/dist/core/loop.js.map +1 -0
  20. package/dist/index.d.ts +49 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +53 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/mcp/client.d.ts +79 -0
  25. package/dist/mcp/client.d.ts.map +1 -0
  26. package/dist/mcp/client.js +176 -0
  27. package/dist/mcp/client.js.map +1 -0
  28. package/dist/mcp/pool-cache.d.ts +103 -0
  29. package/dist/mcp/pool-cache.d.ts.map +1 -0
  30. package/dist/mcp/pool-cache.js +249 -0
  31. package/dist/mcp/pool-cache.js.map +1 -0
  32. package/dist/mcp/pool.d.ts +65 -0
  33. package/dist/mcp/pool.d.ts.map +1 -0
  34. package/dist/mcp/pool.js +86 -0
  35. package/dist/mcp/pool.js.map +1 -0
  36. package/dist/media/file-events.d.ts +8 -0
  37. package/dist/media/file-events.d.ts.map +1 -0
  38. package/dist/media/file-events.js +15 -0
  39. package/dist/media/file-events.js.map +1 -0
  40. package/dist/memory/active-task-template.d.ts +34 -0
  41. package/dist/memory/active-task-template.d.ts.map +1 -0
  42. package/dist/memory/active-task-template.js +63 -0
  43. package/dist/memory/active-task-template.js.map +1 -0
  44. package/dist/memory/compressor.d.ts +87 -0
  45. package/dist/memory/compressor.d.ts.map +1 -0
  46. package/dist/memory/compressor.js +164 -0
  47. package/dist/memory/compressor.js.map +1 -0
  48. package/dist/memory/hash.d.ts +17 -0
  49. package/dist/memory/hash.d.ts.map +1 -0
  50. package/dist/memory/hash.js +20 -0
  51. package/dist/memory/hash.js.map +1 -0
  52. package/dist/memory/prune.d.ts +117 -0
  53. package/dist/memory/prune.d.ts.map +1 -0
  54. package/dist/memory/prune.js +416 -0
  55. package/dist/memory/prune.js.map +1 -0
  56. package/dist/memory/reminder.d.ts +57 -0
  57. package/dist/memory/reminder.d.ts.map +1 -0
  58. package/dist/memory/reminder.js +57 -0
  59. package/dist/memory/reminder.js.map +1 -0
  60. package/dist/memory/scrubber.d.ts +28 -0
  61. package/dist/memory/scrubber.d.ts.map +1 -0
  62. package/dist/memory/scrubber.js +147 -0
  63. package/dist/memory/scrubber.js.map +1 -0
  64. package/dist/memory/token-estimate.d.ts +10 -0
  65. package/dist/memory/token-estimate.d.ts.map +1 -0
  66. package/dist/memory/token-estimate.js +69 -0
  67. package/dist/memory/token-estimate.js.map +1 -0
  68. package/dist/platform/config.d.ts +12 -0
  69. package/dist/platform/config.d.ts.map +1 -0
  70. package/dist/platform/config.js +54 -0
  71. package/dist/platform/config.js.map +1 -0
  72. package/dist/platform/jsonl.d.ts +15 -0
  73. package/dist/platform/jsonl.d.ts.map +1 -0
  74. package/dist/platform/jsonl.js +80 -0
  75. package/dist/platform/jsonl.js.map +1 -0
  76. package/dist/platform/lifecycle.d.ts +22 -0
  77. package/dist/platform/lifecycle.d.ts.map +1 -0
  78. package/dist/platform/lifecycle.js +60 -0
  79. package/dist/platform/lifecycle.js.map +1 -0
  80. package/dist/platform/logger.d.ts +26 -0
  81. package/dist/platform/logger.d.ts.map +1 -0
  82. package/dist/platform/logger.js +41 -0
  83. package/dist/platform/logger.js.map +1 -0
  84. package/dist/platform/mcp-config.d.ts +15 -0
  85. package/dist/platform/mcp-config.d.ts.map +1 -0
  86. package/dist/platform/mcp-config.js +8 -0
  87. package/dist/platform/mcp-config.js.map +1 -0
  88. package/dist/provider.d.ts +81 -0
  89. package/dist/provider.d.ts.map +1 -0
  90. package/dist/provider.js +444 -0
  91. package/dist/provider.js.map +1 -0
  92. package/dist/providers/anthropic.d.ts +132 -0
  93. package/dist/providers/anthropic.d.ts.map +1 -0
  94. package/dist/providers/anthropic.js +518 -0
  95. package/dist/providers/anthropic.js.map +1 -0
  96. package/dist/providers/base.d.ts +140 -0
  97. package/dist/providers/base.d.ts.map +1 -0
  98. package/dist/providers/base.js +2 -0
  99. package/dist/providers/base.js.map +1 -0
  100. package/dist/providers/deepseek.d.ts +118 -0
  101. package/dist/providers/deepseek.d.ts.map +1 -0
  102. package/dist/providers/deepseek.js +467 -0
  103. package/dist/providers/deepseek.js.map +1 -0
  104. package/dist/registry.d.ts +3 -0
  105. package/dist/registry.d.ts.map +1 -0
  106. package/dist/registry.js +94 -0
  107. package/dist/registry.js.map +1 -0
  108. package/dist/session-store.d.ts +133 -0
  109. package/dist/session-store.d.ts.map +1 -0
  110. package/dist/session-store.js +277 -0
  111. package/dist/session-store.js.map +1 -0
  112. package/dist/skills/curator.d.ts +104 -0
  113. package/dist/skills/curator.d.ts.map +1 -0
  114. package/dist/skills/curator.js +162 -0
  115. package/dist/skills/curator.js.map +1 -0
  116. package/dist/skills/index-builder.d.ts +42 -0
  117. package/dist/skills/index-builder.d.ts.map +1 -0
  118. package/dist/skills/index-builder.js +94 -0
  119. package/dist/skills/index-builder.js.map +1 -0
  120. package/dist/skills/loader.d.ts +107 -0
  121. package/dist/skills/loader.d.ts.map +1 -0
  122. package/dist/skills/loader.js +286 -0
  123. package/dist/skills/loader.js.map +1 -0
  124. package/dist/skills/preprocess.d.ts +45 -0
  125. package/dist/skills/preprocess.d.ts.map +1 -0
  126. package/dist/skills/preprocess.js +126 -0
  127. package/dist/skills/preprocess.js.map +1 -0
  128. package/dist/skills/usage.d.ts +75 -0
  129. package/dist/skills/usage.d.ts.map +1 -0
  130. package/dist/skills/usage.js +147 -0
  131. package/dist/skills/usage.js.map +1 -0
  132. package/dist/state/todos.d.ts +95 -0
  133. package/dist/state/todos.d.ts.map +1 -0
  134. package/dist/state/todos.js +198 -0
  135. package/dist/state/todos.js.map +1 -0
  136. package/dist/storage/conversations.d.ts +28 -0
  137. package/dist/storage/conversations.d.ts.map +1 -0
  138. package/dist/storage/conversations.js +8 -0
  139. package/dist/storage/conversations.js.map +1 -0
  140. package/dist/sub-agent/runner.d.ts +78 -0
  141. package/dist/sub-agent/runner.d.ts.map +1 -0
  142. package/dist/sub-agent/runner.js +215 -0
  143. package/dist/sub-agent/runner.js.map +1 -0
  144. package/dist/tools/builtin/agent.d.ts +33 -0
  145. package/dist/tools/builtin/agent.d.ts.map +1 -0
  146. package/dist/tools/builtin/agent.js +76 -0
  147. package/dist/tools/builtin/agent.js.map +1 -0
  148. package/dist/tools/builtin/bash.d.ts +11 -0
  149. package/dist/tools/builtin/bash.d.ts.map +1 -0
  150. package/dist/tools/builtin/bash.js +91 -0
  151. package/dist/tools/builtin/bash.js.map +1 -0
  152. package/dist/tools/builtin/edit.d.ts +21 -0
  153. package/dist/tools/builtin/edit.d.ts.map +1 -0
  154. package/dist/tools/builtin/edit.js +238 -0
  155. package/dist/tools/builtin/edit.js.map +1 -0
  156. package/dist/tools/builtin/read.d.ts +17 -0
  157. package/dist/tools/builtin/read.d.ts.map +1 -0
  158. package/dist/tools/builtin/read.js +139 -0
  159. package/dist/tools/builtin/read.js.map +1 -0
  160. package/dist/tools/builtin/sandbox.d.ts +16 -0
  161. package/dist/tools/builtin/sandbox.d.ts.map +1 -0
  162. package/dist/tools/builtin/sandbox.js +58 -0
  163. package/dist/tools/builtin/sandbox.js.map +1 -0
  164. package/dist/tools/builtin/skill_view.d.ts +37 -0
  165. package/dist/tools/builtin/skill_view.d.ts.map +1 -0
  166. package/dist/tools/builtin/skill_view.js +82 -0
  167. package/dist/tools/builtin/skill_view.js.map +1 -0
  168. package/dist/tools/builtin/todo_write.d.ts +29 -0
  169. package/dist/tools/builtin/todo_write.d.ts.map +1 -0
  170. package/dist/tools/builtin/todo_write.js +96 -0
  171. package/dist/tools/builtin/todo_write.js.map +1 -0
  172. package/dist/tools/builtin/web_fetch.d.ts +10 -0
  173. package/dist/tools/builtin/web_fetch.d.ts.map +1 -0
  174. package/dist/tools/builtin/web_fetch.js +150 -0
  175. package/dist/tools/builtin/web_fetch.js.map +1 -0
  176. package/dist/tools/builtin/write.d.ts +35 -0
  177. package/dist/tools/builtin/write.d.ts.map +1 -0
  178. package/dist/tools/builtin/write.js +70 -0
  179. package/dist/tools/builtin/write.js.map +1 -0
  180. package/dist/tools/file-state.d.ts +99 -0
  181. package/dist/tools/file-state.d.ts.map +1 -0
  182. package/dist/tools/file-state.js +133 -0
  183. package/dist/tools/file-state.js.map +1 -0
  184. package/dist/tools/hooks/sandbox-fs.d.ts +25 -0
  185. package/dist/tools/hooks/sandbox-fs.d.ts.map +1 -0
  186. package/dist/tools/hooks/sandbox-fs.js +48 -0
  187. package/dist/tools/hooks/sandbox-fs.js.map +1 -0
  188. package/dist/tools/registry.d.ts +102 -0
  189. package/dist/tools/registry.d.ts.map +1 -0
  190. package/dist/tools/registry.js +93 -0
  191. package/dist/tools/registry.js.map +1 -0
  192. package/dist/types.d.ts +109 -0
  193. package/dist/types.d.ts.map +1 -0
  194. package/dist/types.js +20 -0
  195. package/dist/types.js.map +1 -0
  196. package/package.json +72 -0
@@ -0,0 +1,57 @@
1
+ import { isSandboxEnabled } from "../tools/builtin/sandbox.js";
2
+ import { WORKSPACE_DIR } from "../platform/config.js";
3
+ /**
4
+ * Build the `<system-reminder>` block. Returns a self-contained string that
5
+ * callers attach verbatim as a `text` content block on a user message.
6
+ *
7
+ * Empty extras + sandbox-enabled (default) state renders to ~3 lines so
8
+ * the per-turn token cost is bounded; the catalog of facts only grows as
9
+ * later phases add semantic state (Phase 3.2 task list, etc.).
10
+ */
11
+ export function buildSystemReminder(ctx) {
12
+ const lines = ["<system-reminder>"];
13
+ // Sandbox state — the model needs to know whether file paths outside
14
+ // WORKSPACE_DIR will be rejected, so it can either prefix paths correctly
15
+ // or pre-emptively flag the limitation when the user asks for an
16
+ // out-of-workspace operation. Default is unsandboxed (parity with
17
+ // claude/codex providers); the operator opts in by exporting
18
+ // `MAESTRO_FS_SANDBOX_ENABLED=1`.
19
+ if (isSandboxEnabled()) {
20
+ lines.push(`Filesystem sandbox: enabled. Allowed root: ${WORKSPACE_DIR}`);
21
+ lines.push(" Paths outside this root will be rejected by Read/Write/Edit. " +
22
+ "Prefer relative-to-workspace paths.");
23
+ }
24
+ else {
25
+ lines.push("Filesystem sandbox: disabled (any absolute path may be read/written).");
26
+ }
27
+ // Session id — emitted so cross-session tools (ask_session, tell_session,
28
+ // fork helpers) have a stable handle to reference without round-tripping.
29
+ lines.push(`Session: ${ctx.sessionId}`);
30
+ // TodoWrite read-side: render the current list (if any) so the model
31
+ // doesn't need a `todo_list` tool. Compact one-line-per-entry format
32
+ // tracks `[✓/→/ ] task-N content` — matches the tool result preview
33
+ // so the model sees the same shape it wrote.
34
+ if (ctx.todos && ctx.todos.length > 0) {
35
+ lines.push(`Task list (${todoSummaryCount(ctx.todos)}):`);
36
+ for (const t of ctx.todos) {
37
+ const mark = t.status === "completed" ? "✓" : t.status === "in_progress" ? "→" : " ";
38
+ lines.push(` [${mark}] ${t.id} ${t.content}`);
39
+ }
40
+ lines.push("Update this list with `todo_write` whenever you start a step, finish one, " +
41
+ "or change the plan. Only ONE item may be in_progress at a time.");
42
+ }
43
+ // Caller-supplied tail. Each extra is one line — caller owns formatting.
44
+ for (const e of ctx.extras ?? []) {
45
+ if (e.length > 0)
46
+ lines.push(e);
47
+ }
48
+ lines.push("</system-reminder>");
49
+ return lines.join("\n");
50
+ }
51
+ /** Compact "3/5" style summary — completed over total. Used in the list
52
+ * header so the model gets progress at a glance without re-counting. */
53
+ function todoSummaryCount(todos) {
54
+ const done = todos.filter((t) => t.status === "completed").length;
55
+ return `${done}/${todos.length}`;
56
+ }
57
+ //# sourceMappingURL=reminder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reminder.js","sourceRoot":"","sources":["../../src/memory/reminder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAkDlD;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAA0B;IAC5D,MAAM,KAAK,GAAa,CAAC,mBAAmB,CAAC,CAAC;IAE9C,qEAAqE;IACrE,0EAA0E;IAC1E,iEAAiE;IACjE,kEAAkE;IAClE,6DAA6D;IAC7D,kCAAkC;IAClC,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,8CAA8C,aAAa,EAAE,CAAC,CAAC;QAC1E,KAAK,CAAC,IAAI,CACR,iEAAiE;YAC/D,qCAAqC,CACxC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;IACtF,CAAC;IAED,0EAA0E;IAC1E,0EAA0E;IAC1E,KAAK,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;IAExC,qEAAqE;IACrE,qEAAqE;IACrE,qEAAqE;IACrE,6CAA6C;IAC7C,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,cAAc,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1D,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACrF,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,KAAK,CAAC,IAAI,CACR,4EAA4E;YAC1E,iEAAiE,CACpE,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;yEACyE;AACzE,SAAS,gBAAgB,CAAC,KAA2B;IACnD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IAClE,OAAO,GAAG,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,28 @@
1
+ export declare class StreamingContextScrubber {
2
+ private state;
3
+ private readonly bufferCap;
4
+ /**
5
+ * Push a chunk of streamed text. Returns the bytes that should be
6
+ * emitted downstream (the unscrubbed part). Internal state advances so
7
+ * subsequent calls pick up where the last one left off.
8
+ *
9
+ * Safe on empty chunks (returns empty string).
10
+ */
11
+ feed(chunk: string): string;
12
+ /**
13
+ * Stream ended. Flush any safe-to-emit pending bytes. If we're still
14
+ * matching-open (the model said `<comp` and stopped), flush the buffered
15
+ * candidate (it wasn't a real marker after all). If we're inside a fence
16
+ * that never closed, drop the rest silently — better than leaking
17
+ * partial summary text.
18
+ */
19
+ finish(): string;
20
+ }
21
+ /**
22
+ * One-shot helper for non-streaming cases: scrub an entire string by
23
+ * feeding it through a scrubber and finishing. Used by the
24
+ * `text` (consolidated) UnifiedEvent emit at end-of-turn so non-streaming
25
+ * consumers (recorders, logs) also see the cleaned text.
26
+ */
27
+ export declare function scrubString(input: string): string;
28
+ //# sourceMappingURL=scrubber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrubber.d.ts","sourceRoot":"","sources":["../../src/memory/scrubber.ts"],"names":[],"mappings":"AAgFA,qBAAa,wBAAwB;IACnC,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAE5C;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAqE3B;;;;;;OAMG;IACH,MAAM,IAAI,MAAM;CAUjB;AAmBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD"}
@@ -0,0 +1,147 @@
1
+ import { COMPACTED_MARKER_CLOSE, COMPACTED_MARKER_OPEN, } from "../memory/active-task-template.js";
2
+ /** Anthropic models occasionally surface their chain-of-thought as
3
+ * literal `<thinking>...</thinking>` text in the assistant message body
4
+ * (a pretrained pattern, separate from extended-thinking blocks which we
5
+ * already keep server-side via the `thinking` content type). On telegram
6
+ * this leaks raw reasoning the user explicitly asked to hide. Treat the
7
+ * fence identically to compacted-history: drop entire block including
8
+ * the markers. */
9
+ const THINKING_MARKER_OPEN = "<thinking>";
10
+ const THINKING_MARKER_CLOSE = "</thinking>";
11
+ const MARKERS = [
12
+ { open: COMPACTED_MARKER_OPEN, close: COMPACTED_MARKER_CLOSE },
13
+ { open: THINKING_MARKER_OPEN, close: THINKING_MARKER_CLOSE },
14
+ ];
15
+ /** Longest prefix of any open/close marker we might still be matching.
16
+ * Tracked so we know how many trailing bytes to buffer (waiting for the
17
+ * next chunk) vs. flush. */
18
+ function maxMarkerLen() {
19
+ let m = 0;
20
+ for (const p of MARKERS) {
21
+ if (p.open.length > m)
22
+ m = p.open.length;
23
+ if (p.close.length > m)
24
+ m = p.close.length;
25
+ }
26
+ return m;
27
+ }
28
+ export class StreamingContextScrubber {
29
+ state = { kind: "outside" };
30
+ bufferCap = maxMarkerLen();
31
+ /**
32
+ * Push a chunk of streamed text. Returns the bytes that should be
33
+ * emitted downstream (the unscrubbed part). Internal state advances so
34
+ * subsequent calls pick up where the last one left off.
35
+ *
36
+ * Safe on empty chunks (returns empty string).
37
+ */
38
+ feed(chunk) {
39
+ if (!chunk)
40
+ return "";
41
+ let i = 0;
42
+ let out = "";
43
+ while (i < chunk.length) {
44
+ const remaining = chunk.slice(i);
45
+ if (this.state.kind === "outside") {
46
+ // Look for the earliest start-of-marker candidate in `remaining`.
47
+ const startIdx = findPossibleMarkerStart(remaining);
48
+ if (startIdx < 0) {
49
+ // No partial marker — entire remaining is safe to emit.
50
+ out += remaining;
51
+ break;
52
+ }
53
+ // Emit everything before the candidate position.
54
+ out += remaining.slice(0, startIdx);
55
+ this.state = { kind: "matching-open", buffer: "" };
56
+ i += startIdx;
57
+ continue;
58
+ }
59
+ if (this.state.kind === "matching-open") {
60
+ this.state.buffer += remaining[0];
61
+ i++;
62
+ // Did we complete an open marker?
63
+ const match = MARKERS.find((m) => this.state.kind === "matching-open" && this.state.buffer === m.open);
64
+ if (match) {
65
+ this.state = { kind: "inside", pending: match, buffer: "" };
66
+ continue;
67
+ }
68
+ // Still a viable prefix of any open marker?
69
+ const isViable = MARKERS.some((m) => this.state.kind === "matching-open" && m.open.startsWith(this.state.buffer));
70
+ if (!isViable) {
71
+ // False alarm — flush the buffered candidate and resume outside.
72
+ out += this.state.buffer;
73
+ this.state = { kind: "outside" };
74
+ continue;
75
+ }
76
+ if (this.state.buffer.length >= this.bufferCap) {
77
+ // Saturated without matching — flush and resume.
78
+ out += this.state.buffer;
79
+ this.state = { kind: "outside" };
80
+ }
81
+ continue;
82
+ }
83
+ // state.kind === "inside" — drop bytes until close marker found.
84
+ this.state.buffer += remaining[0];
85
+ i++;
86
+ const closeIdx = this.state.buffer.indexOf(this.state.pending.close);
87
+ if (closeIdx >= 0) {
88
+ // Consumed (and dropped) up to and including the close marker.
89
+ this.state = { kind: "outside" };
90
+ continue;
91
+ }
92
+ // Cap the inside buffer so a runaway (unclosed) fence doesn't grow
93
+ // forever — keep only the last `bufferCap` bytes (enough to detect
94
+ // the close marker spanning into the next chunk).
95
+ if (this.state.buffer.length > this.bufferCap) {
96
+ this.state.buffer = this.state.buffer.slice(-this.bufferCap);
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+ /**
102
+ * Stream ended. Flush any safe-to-emit pending bytes. If we're still
103
+ * matching-open (the model said `<comp` and stopped), flush the buffered
104
+ * candidate (it wasn't a real marker after all). If we're inside a fence
105
+ * that never closed, drop the rest silently — better than leaking
106
+ * partial summary text.
107
+ */
108
+ finish() {
109
+ if (this.state.kind === "matching-open") {
110
+ const tail = this.state.buffer;
111
+ this.state = { kind: "outside" };
112
+ return tail;
113
+ }
114
+ // outside → nothing to flush. inside → drop.
115
+ this.state = { kind: "outside" };
116
+ return "";
117
+ }
118
+ }
119
+ /**
120
+ * Index of the earliest position in `text` where a marker open sequence
121
+ * COULD begin. Looks for the first character of any open marker. Returns
122
+ * -1 when none found. Cheap pre-filter so the scrubber only enters
123
+ * matching-open state when it has a real candidate.
124
+ */
125
+ function findPossibleMarkerStart(text) {
126
+ // All current markers start with `<`. If new marker types are added with
127
+ // a different leading char, extend this set.
128
+ const candidates = new Set();
129
+ for (const m of MARKERS)
130
+ candidates.add(m.open[0]);
131
+ for (let i = 0; i < text.length; i++) {
132
+ if (candidates.has(text[i]))
133
+ return i;
134
+ }
135
+ return -1;
136
+ }
137
+ /**
138
+ * One-shot helper for non-streaming cases: scrub an entire string by
139
+ * feeding it through a scrubber and finishing. Used by the
140
+ * `text` (consolidated) UnifiedEvent emit at end-of-turn so non-streaming
141
+ * consumers (recorders, logs) also see the cleaned text.
142
+ */
143
+ export function scrubString(input) {
144
+ const s = new StreamingContextScrubber();
145
+ return s.feed(input) + s.finish();
146
+ }
147
+ //# sourceMappingURL=scrubber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrubber.js","sourceRoot":"","sources":["../../src/memory/scrubber.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ProviderContentBlock, ProviderMessage } from "../providers/base.js";
2
+ /** Estimate tokens for a single content block. Unknown block types fall back
3
+ * to the text rate since their wire encoding is JSON-ish. */
4
+ export declare function estimateBlockTokens(block: ProviderContentBlock): number;
5
+ /** Estimate tokens for one message. Includes a small overhead per message
6
+ * for the role marker + JSON framing the API adds on the wire. */
7
+ export declare function estimateMessageTokens(msg: ProviderMessage): number;
8
+ /** Estimate total tokens for a message array. */
9
+ export declare function estimateTokens(messages: readonly ProviderMessage[]): number;
10
+ //# sourceMappingURL=token-estimate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-estimate.d.ts","sourceRoot":"","sources":["../../src/memory/token-estimate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA4B9E;8DAC8D;AAC9D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAuBvE;AAED;mEACmE;AACnE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAQlE;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,MAAM,CAI3E"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Cheap token estimator for the maestro compaction trigger.
3
+ *
4
+ * We don't want a tokenizer dependency on the per-turn hot path — running a
5
+ * BPE encoder over every message before each provider call would cost more
6
+ * than the cache hit it saves. Instead we approximate token count by
7
+ * character length divided by a per-content-type factor, calibrated against
8
+ * Claude Sonnet 4 BPE empirics on representative dialogue:
9
+ *
10
+ * plain text: chars / 3.5 (English-leaning; CJK runs lower)
11
+ * tool_use input: chars / 4.0 (JSON literals compress further)
12
+ * tool_result: chars / 3.8 (mix of text + JSON)
13
+ *
14
+ * The estimator is intentionally biased **high** — over-counting triggers
15
+ * compaction slightly earlier than necessary, which is the safer failure
16
+ * mode (compacting a turn early is mildly wasteful; missing a compact and
17
+ * blowing past the context window is a hard 400 error).
18
+ *
19
+ * Upstream reference: `/Users/maestrobot/__KEEP_MAESTRO_AGENT__/agent/context_compressor.py`
20
+ * uses a similar char-based approximation when no tokenizer is plugged in.
21
+ */
22
+ const CHARS_PER_TEXT_TOKEN = 3.5;
23
+ const CHARS_PER_TOOL_USE_TOKEN = 4.0;
24
+ const CHARS_PER_TOOL_RESULT_TOKEN = 3.8;
25
+ /** Estimate tokens for a single content block. Unknown block types fall back
26
+ * to the text rate since their wire encoding is JSON-ish. */
27
+ export function estimateBlockTokens(block) {
28
+ switch (block.type) {
29
+ case "text":
30
+ return Math.ceil(block.text.length / CHARS_PER_TEXT_TOKEN);
31
+ case "tool_use": {
32
+ // name + JSON-stringified input. Don't pretty-print — the wire format
33
+ // is compact and that's what the API actually counts against the cap.
34
+ const len = block.name.length + JSON.stringify(block.input).length;
35
+ return Math.ceil(len / CHARS_PER_TOOL_USE_TOKEN);
36
+ }
37
+ case "tool_result": {
38
+ const content = typeof block.content === "string" ? block.content : JSON.stringify(block.content);
39
+ return Math.ceil(content.length / CHARS_PER_TOOL_RESULT_TOKEN);
40
+ }
41
+ default: {
42
+ // Defensive: unknown future block shapes (e.g. image). JSON-encode and
43
+ // charge the text rate. Better to over-count than to silently zero out
44
+ // a block we don't recognize.
45
+ const json = JSON.stringify(block);
46
+ return Math.ceil(json.length / CHARS_PER_TEXT_TOKEN);
47
+ }
48
+ }
49
+ }
50
+ /** Estimate tokens for one message. Includes a small overhead per message
51
+ * for the role marker + JSON framing the API adds on the wire. */
52
+ export function estimateMessageTokens(msg) {
53
+ const overhead = 4; // role + framing
54
+ if (typeof msg.content === "string") {
55
+ return overhead + Math.ceil(msg.content.length / CHARS_PER_TEXT_TOKEN);
56
+ }
57
+ let sum = overhead;
58
+ for (const block of msg.content)
59
+ sum += estimateBlockTokens(block);
60
+ return sum;
61
+ }
62
+ /** Estimate total tokens for a message array. */
63
+ export function estimateTokens(messages) {
64
+ let sum = 0;
65
+ for (const msg of messages)
66
+ sum += estimateMessageTokens(msg);
67
+ return sum;
68
+ }
69
+ //# sourceMappingURL=token-estimate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-estimate.js","sourceRoot":"","sources":["../../src/memory/token-estimate.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AACrC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAExC;8DAC8D;AAC9D,MAAM,UAAU,mBAAmB,CAAC,KAA2B;IAC7D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,oBAAoB,CAAC,CAAC;QAC7D,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,sEAAsE;YACtE,sEAAsE;YACtE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;YACnE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,wBAAwB,CAAC,CAAC;QACnD,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,OAAO,GACX,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,2BAA2B,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,uEAAuE;YACvE,uEAAuE;YACvE,8BAA8B;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,oBAAoB,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;AACH,CAAC;AAED;mEACmE;AACnE,MAAM,UAAU,qBAAqB,CAAC,GAAoB;IACxD,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,iBAAiB;IACrC,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,oBAAoB,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO;QAAE,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACnE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,QAAoC;IACjE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,GAAG,IAAI,QAAQ;QAAE,GAAG,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC9D,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,12 @@
1
+ export declare const DATA_DIR: string;
2
+ export declare const WORKSPACE_DIR: string;
3
+ export declare const MODEL_HAIKU: string;
4
+ export declare const MODEL_SONNET: string;
5
+ export declare const MODEL_OPUS: string;
6
+ export declare const MODEL_DEEPSEEK_V4_PRO: string;
7
+ export declare const MODEL_DEEPSEEK_V4_FLASH: string;
8
+ export declare const FILE_TAG_REGEX: RegExp;
9
+ /** Returns `process.env` without `CLAUDECODE` so spawned subprocesses don't
10
+ * inherit a nested-claude-code detection flag from a parent harness. */
11
+ export declare function getCleanEnv(): NodeJS.ProcessEnv;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/platform/config.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,QAAQ,EAAE,MAEY,CAAC;AAEpC,eAAO,MAAM,aAAa,EAAE,MAEU,CAAC;AAEvC,eAAO,MAAM,WAAW,EAAE,MAC4C,CAAC;AAKvE,eAAO,MAAM,YAAY,EAAE,MAA4B,CAAC;AACxD,eAAO,MAAM,UAAU,EAAE,MAA0B,CAAC;AAGpD,eAAO,MAAM,qBAAqB,EAAE,MAA0B,CAAC;AAC/D,eAAO,MAAM,uBAAuB,EAAE,MAA4B,CAAC;AAEnE,eAAO,MAAM,cAAc,EAAE,MAAgC,CAAC;AAgB9D;yEACyE;AACzE,wBAAgB,WAAW,IAAI,MAAM,CAAC,UAAU,CAI/C"}
@@ -0,0 +1,54 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { resolve } from "node:path";
4
+ /**
5
+ * SDK runtime configuration — replaces clawgram's bespoke `platform/config`.
6
+ *
7
+ * Values are resolved once at module load. Hosts that need non-default paths
8
+ * must set the corresponding env var (`MAESTRO_DATA_DIR`, `MAESTRO_WORKSPACE_DIR`,
9
+ * `MAESTRO_COMPRESSION_MODEL`) **before** importing any SDK module that
10
+ * depends on them.
11
+ *
12
+ * For per-call overrides, prefer `AgentQueryOptions.cwd` (filesystem root)
13
+ * and `AIAgentConfig.model` (compression model is wired through there too).
14
+ */
15
+ const HOME = homedir();
16
+ export const DATA_DIR = process.env.MAESTRO_DATA_DIR
17
+ ? resolve(process.env.MAESTRO_DATA_DIR)
18
+ : resolve(HOME, ".maestro-agent");
19
+ export const WORKSPACE_DIR = process.env.MAESTRO_WORKSPACE_DIR
20
+ ? resolve(process.env.MAESTRO_WORKSPACE_DIR)
21
+ : resolve(HOME, "maestro-workspace");
22
+ export const MODEL_HAIKU = process.env.MAESTRO_COMPRESSION_MODEL ?? "claude-haiku-4-5-20251001";
23
+ // Canonical model IDs used by the SDK's maestro registry. Hosts can pick a
24
+ // different default per-query via `AgentQueryOptions.model`, so these are
25
+ // just baseline references.
26
+ export const MODEL_SONNET = "claude-sonnet-4-6";
27
+ export const MODEL_OPUS = "claude-opus-4-7";
28
+ // DeepSeek V4 (released 2026-04-24). OpenAI-compatible chat-completions API.
29
+ export const MODEL_DEEPSEEK_V4_PRO = "deepseek-v4-pro";
30
+ export const MODEL_DEEPSEEK_V4_FLASH = "deepseek-v4-flash";
31
+ export const FILE_TAG_REGEX = /\[FILE:(\/[^\]]+)\]/gi;
32
+ // Make sure DATA_DIR and WORKSPACE_DIR exist before any tool/skill code tries
33
+ // to mkdtemp/readdir into them. Idempotent and best-effort — hosts that point
34
+ // these at read-only mount points should override before importing the SDK.
35
+ try {
36
+ mkdirSync(DATA_DIR, { recursive: true });
37
+ }
38
+ catch {
39
+ // ignore — host may have pre-created with stricter perms
40
+ }
41
+ try {
42
+ mkdirSync(WORKSPACE_DIR, { recursive: true });
43
+ }
44
+ catch {
45
+ // ignore — host may have pre-created with stricter perms
46
+ }
47
+ /** Returns `process.env` without `CLAUDECODE` so spawned subprocesses don't
48
+ * inherit a nested-claude-code detection flag from a parent harness. */
49
+ export function getCleanEnv() {
50
+ const env = { ...process.env };
51
+ delete env.CLAUDECODE;
52
+ return env;
53
+ }
54
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/platform/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;GAUG;AAEH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;AAEvB,MAAM,CAAC,MAAM,QAAQ,GAAW,OAAO,CAAC,GAAG,CAAC,gBAAgB;IAC1D,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACvC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;AAEpC,MAAM,CAAC,MAAM,aAAa,GAAW,OAAO,CAAC,GAAG,CAAC,qBAAqB;IACpE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAC5C,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAEvC,MAAM,CAAC,MAAM,WAAW,GACtB,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,2BAA2B,CAAC;AAEvE,2EAA2E;AAC3E,0EAA0E;AAC1E,4BAA4B;AAC5B,MAAM,CAAC,MAAM,YAAY,GAAW,mBAAmB,CAAC;AACxD,MAAM,CAAC,MAAM,UAAU,GAAW,iBAAiB,CAAC;AAEpD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,qBAAqB,GAAW,iBAAiB,CAAC;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAW,mBAAmB,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAW,uBAAuB,CAAC;AAE9D,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,IAAI,CAAC;IACH,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3C,CAAC;AAAC,MAAM,CAAC;IACP,yDAAyD;AAC3D,CAAC;AACD,IAAI,CAAC;IACH,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AAAC,MAAM,CAAC;IACP,yDAAyD;AAC3D,CAAC;AAED;yEACyE;AACzE,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,OAAO,GAAG,CAAC,UAAU,CAAC;IACtB,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Narrowed JSONL helpers for the SDK.
3
+ *
4
+ * Upstream clawgram exposes cross-process append locks via a sidecar
5
+ * `.lock` file and `Bun.sleepSync`. The SDK only ships single-process
6
+ * read/write helpers — the agent loop and session-store never share a
7
+ * JSONL file with another process — so the lock complexity (and Bun
8
+ * dependency) is dropped here.
9
+ */
10
+ export declare function readJsonlLines(filePath: string): string[];
11
+ export declare function parseJsonlText<T = unknown>(raw: string): T[];
12
+ export declare function readJsonFile<T = unknown>(filePath: string): T | null;
13
+ /** Overwrite a JSONL file atomically (write to temp, fsync, rename). */
14
+ export declare function writeJsonlFile(filePath: string, entries: readonly unknown[]): void;
15
+ //# sourceMappingURL=jsonl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../src/platform/jsonl.ts"],"names":[],"mappings":"AAYA;;;;;;;;GAQG;AAEH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD;AAED,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,CAM5D;AAED,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMpE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CA2BlF"}
@@ -0,0 +1,80 @@
1
+ import { closeSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ /**
4
+ * Narrowed JSONL helpers for the SDK.
5
+ *
6
+ * Upstream clawgram exposes cross-process append locks via a sidecar
7
+ * `.lock` file and `Bun.sleepSync`. The SDK only ships single-process
8
+ * read/write helpers — the agent loop and session-store never share a
9
+ * JSONL file with another process — so the lock complexity (and Bun
10
+ * dependency) is dropped here.
11
+ */
12
+ export function readJsonlLines(filePath) {
13
+ return readFileSync(filePath, "utf-8").trim().split("\n").filter(Boolean);
14
+ }
15
+ export function parseJsonlText(raw) {
16
+ return raw
17
+ .trim()
18
+ .split("\n")
19
+ .filter(Boolean)
20
+ .map((line) => JSON.parse(line));
21
+ }
22
+ export function readJsonFile(filePath) {
23
+ try {
24
+ return JSON.parse(readFileSync(filePath, "utf-8"));
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ /** Overwrite a JSONL file atomically (write to temp, fsync, rename). */
31
+ export function writeJsonlFile(filePath, entries) {
32
+ const dir = dirname(filePath);
33
+ mkdirSync(dir, { recursive: true });
34
+ const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}-${Math.random()
35
+ .toString(16)
36
+ .slice(2)}`;
37
+ const payload = `${entries.map((e) => JSON.stringify(e)).join("\n")}\n`;
38
+ let fd = null;
39
+ try {
40
+ fd = openSync(tmpPath, "w");
41
+ writeFileSync(fd, payload);
42
+ fsyncSync(fd);
43
+ closeSync(fd);
44
+ fd = null;
45
+ renameSync(tmpPath, filePath);
46
+ fsyncDirectoryBestEffort(dir);
47
+ }
48
+ catch (err) {
49
+ if (fd !== null) {
50
+ try {
51
+ closeSync(fd);
52
+ }
53
+ catch { }
54
+ }
55
+ try {
56
+ unlinkSync(tmpPath);
57
+ }
58
+ catch { }
59
+ throw err;
60
+ }
61
+ }
62
+ function fsyncDirectoryBestEffort(dir) {
63
+ let fd = null;
64
+ try {
65
+ fd = openSync(dir, "r");
66
+ fsyncSync(fd);
67
+ }
68
+ catch {
69
+ // Directory fsync is not portable across every runtime/filesystem.
70
+ }
71
+ finally {
72
+ if (fd !== null) {
73
+ try {
74
+ closeSync(fd);
75
+ }
76
+ catch { }
77
+ }
78
+ }
79
+ }
80
+ //# sourceMappingURL=jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../src/platform/jsonl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared process-shutdown registry for SDK subsystems (MCP pool, sub-agents).
3
+ *
4
+ * Ported verbatim from clawgram. Modules call `onShutdown(name, priority, fn)`;
5
+ * the first SIGINT/SIGTERM/beforeExit drains them in descending priority order
6
+ * with a per-handler timeout and a hard exit ceiling.
7
+ *
8
+ * Priority convention (rough):
9
+ * - 100+: stateful network/connection resources (MCP pool, DB conns).
10
+ * - 50: subsystems that kill external processes (subprocess pools).
11
+ * - 10: final reporting / metrics flushing.
12
+ */
13
+ export interface ShutdownHandler {
14
+ name: string;
15
+ priority: number;
16
+ fn: () => Promise<void> | void;
17
+ }
18
+ export type SignalReason = "beforeExit" | "SIGINT" | "SIGTERM" | "test";
19
+ export declare function onShutdown(name: string, priority: number, fn: () => Promise<void> | void): void;
20
+ export declare function runShutdown(reason: SignalReason): Promise<void>;
21
+ export declare function __resetForTests(): void;
22
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/platform/lifecycle.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAChC;AASD,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAExE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAG/F;AAgBD,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCrE;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC"}
@@ -0,0 +1,60 @@
1
+ import { logger } from "../platform/logger.js";
2
+ const handlers = [];
3
+ let signalHooksInstalled = false;
4
+ let triggered = false;
5
+ const HANDLER_TIMEOUT_MS = 5_000;
6
+ const HARD_EXIT_TIMEOUT_MS = 15_000;
7
+ export function onShutdown(name, priority, fn) {
8
+ handlers.push({ name, priority, fn });
9
+ ensureSignalHooks();
10
+ }
11
+ function ensureSignalHooks() {
12
+ if (signalHooksInstalled)
13
+ return;
14
+ signalHooksInstalled = true;
15
+ process.once("beforeExit", () => {
16
+ void runShutdown("beforeExit");
17
+ });
18
+ process.once("SIGINT", () => {
19
+ void runShutdown("SIGINT");
20
+ });
21
+ process.once("SIGTERM", () => {
22
+ void runShutdown("SIGTERM");
23
+ });
24
+ }
25
+ export async function runShutdown(reason) {
26
+ if (triggered)
27
+ return;
28
+ triggered = true;
29
+ logger.info({ reason, handlerCount: handlers.length }, "lifecycle: shutdown sequence starting");
30
+ const ordered = handlers
31
+ .map((h, i) => ({ h, i }))
32
+ .sort((a, b) => b.h.priority - a.h.priority || a.i - b.i)
33
+ .map(({ h }) => h);
34
+ const hardExit = setTimeout(() => {
35
+ logger.error({ reason }, "lifecycle: hard-exit ceiling reached, forcing process.exit");
36
+ process.exit(1);
37
+ }, HARD_EXIT_TIMEOUT_MS);
38
+ hardExit.unref?.();
39
+ for (const h of ordered) {
40
+ const start = Date.now();
41
+ try {
42
+ await Promise.race([
43
+ Promise.resolve(h.fn()),
44
+ new Promise((_, reject) => setTimeout(() => reject(new Error("handler timeout")), HANDLER_TIMEOUT_MS)),
45
+ ]);
46
+ logger.info({ handler: h.name, priority: h.priority, ms: Date.now() - start }, "lifecycle: shutdown handler completed");
47
+ }
48
+ catch (err) {
49
+ logger.warn({ err, handler: h.name, priority: h.priority, ms: Date.now() - start }, "lifecycle: shutdown handler failed or timed out (continuing)");
50
+ }
51
+ }
52
+ clearTimeout(hardExit);
53
+ logger.info({ reason }, "lifecycle: shutdown sequence complete");
54
+ }
55
+ export function __resetForTests() {
56
+ handlers.length = 0;
57
+ triggered = false;
58
+ signalHooksInstalled = false;
59
+ }
60
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/platform/lifecycle.ts"],"names":[],"mappings":"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"}