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,467 @@
1
+ const DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions";
2
+ export class DeepseekProvider {
3
+ apiKey;
4
+ constructor(apiKey) {
5
+ this.apiKey = apiKey;
6
+ }
7
+ static fromEnv() {
8
+ const apiKey = process.env.DEEPSEEK_API_KEY;
9
+ if (!apiKey) {
10
+ throw new Error("Maestro DeepseekProvider: DEEPSEEK_API_KEY env var is not set");
11
+ }
12
+ return new DeepseekProvider(apiKey);
13
+ }
14
+ async complete(opts) {
15
+ const body = buildRequestBody(opts, false);
16
+ const init = {
17
+ method: "POST",
18
+ headers: this.headers(),
19
+ body: JSON.stringify(body),
20
+ };
21
+ if (opts.abortSignal)
22
+ init.signal = opts.abortSignal;
23
+ const response = await fetch(DEEPSEEK_API_URL, init);
24
+ if (!response.ok) {
25
+ const text = await response.text();
26
+ throw new Error(`DeepSeek API ${response.status}: ${text}`);
27
+ }
28
+ const data = (await response.json());
29
+ const choice = data.choices?.[0];
30
+ if (!choice) {
31
+ throw new Error("DeepSeek API: response missing choices");
32
+ }
33
+ return {
34
+ content: openAiChoiceToBlocks(choice),
35
+ stopReason: mapStopReason(choice.finish_reason),
36
+ usage: mapUsage(data.usage),
37
+ };
38
+ }
39
+ async *stream(opts) {
40
+ const body = buildRequestBody(opts, true);
41
+ const init = {
42
+ method: "POST",
43
+ headers: { ...this.headers(), accept: "text/event-stream" },
44
+ body: JSON.stringify(body),
45
+ };
46
+ if (opts.abortSignal)
47
+ init.signal = opts.abortSignal;
48
+ const response = await fetch(DEEPSEEK_API_URL, init);
49
+ if (!response.ok) {
50
+ const text = await response.text();
51
+ throw new Error(`DeepSeek API ${response.status}: ${text}`);
52
+ }
53
+ if (!response.body) {
54
+ throw new Error("DeepSeek API: streaming response missing body");
55
+ }
56
+ // OpenAI streams parallel tool calls keyed by `delta.tool_calls[*].index`
57
+ // (NOT the Anthropic content-block index — they're separate spaces). We
58
+ // accumulate per-index so a tool's arguments JSON survives across many
59
+ // chunks before we emit the matching `tool_use_complete`.
60
+ const toolAccum = new Map();
61
+ // Reasoning content arrives as `delta.reasoning_content` deltas. The
62
+ // base.ts contract only carries terminal `thinking_complete` blocks
63
+ // (Anthropic delivers thinking deltas inside a content block; we buffer
64
+ // here and emit one consolidated block before `message_complete`).
65
+ let reasoningBuf = "";
66
+ let reasoningSeen = false;
67
+ let stopReason = "end_turn";
68
+ let usage = { inputTokens: 0, outputTokens: 0 };
69
+ for await (const event of parseSseStream(response.body, opts.abortSignal)) {
70
+ const choice = event.choices?.[0];
71
+ if (!choice) {
72
+ // Some chunks (e.g. final usage-only) may lack choices — capture
73
+ // usage and move on.
74
+ if (event.usage)
75
+ usage = mapUsage(event.usage);
76
+ continue;
77
+ }
78
+ const delta = choice.delta ?? {};
79
+ if (typeof delta.content === "string" && delta.content.length > 0) {
80
+ yield { type: "text_delta", text: delta.content };
81
+ }
82
+ if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
83
+ reasoningSeen = true;
84
+ reasoningBuf += delta.reasoning_content;
85
+ }
86
+ if (Array.isArray(delta.tool_calls)) {
87
+ for (const tc of delta.tool_calls) {
88
+ if (typeof tc?.index !== "number")
89
+ continue;
90
+ let entry = toolAccum.get(tc.index);
91
+ if (!entry) {
92
+ entry = { id: "", name: "", args: "", startEmitted: false };
93
+ toolAccum.set(tc.index, entry);
94
+ }
95
+ if (typeof tc.id === "string" && tc.id.length > 0)
96
+ entry.id = tc.id;
97
+ if (typeof tc.function?.name === "string" && tc.function.name.length > 0) {
98
+ entry.name = tc.function.name;
99
+ }
100
+ if (!entry.startEmitted && entry.id.length > 0 && entry.name.length > 0) {
101
+ entry.startEmitted = true;
102
+ yield { type: "tool_use_start", id: entry.id, name: entry.name };
103
+ }
104
+ if (typeof tc.function?.arguments === "string" && tc.function.arguments.length > 0) {
105
+ entry.args += tc.function.arguments;
106
+ if (entry.startEmitted) {
107
+ yield {
108
+ type: "tool_use_input_delta",
109
+ id: entry.id,
110
+ partial_json: tc.function.arguments,
111
+ };
112
+ }
113
+ }
114
+ }
115
+ }
116
+ if (choice.finish_reason) {
117
+ stopReason = mapStopReason(choice.finish_reason);
118
+ }
119
+ if (event.usage)
120
+ usage = mapUsage(event.usage);
121
+ }
122
+ // Flush per-index tool buffers in the order their indexes appeared. If a
123
+ // tool's start was deferred because id/name arrived only in the final
124
+ // chunk, emit it now in [start, input_delta(full), complete] order so the
125
+ // loop's accumulator state machine still gets a coherent sequence.
126
+ const indexes = [...toolAccum.keys()].sort((a, b) => a - b);
127
+ for (const idx of indexes) {
128
+ const entry = toolAccum.get(idx);
129
+ if (!entry || entry.id.length === 0)
130
+ continue;
131
+ if (!entry.startEmitted) {
132
+ yield { type: "tool_use_start", id: entry.id, name: entry.name };
133
+ if (entry.args.length > 0) {
134
+ yield {
135
+ type: "tool_use_input_delta",
136
+ id: entry.id,
137
+ partial_json: entry.args,
138
+ };
139
+ }
140
+ }
141
+ yield { type: "tool_use_complete", id: entry.id, name: entry.name };
142
+ }
143
+ // Emit thinking BEFORE message_complete so the loop pushes it into the
144
+ // assistant block list (loop.ts:155 appends thinking_complete blocks
145
+ // directly into assistantBlocks). Order in history: thinking → text →
146
+ // tool_use, matching Anthropic's interleaved-thinking convention.
147
+ if (reasoningSeen && reasoningBuf.length > 0) {
148
+ yield {
149
+ type: "thinking_complete",
150
+ block: { type: "thinking", thinking: reasoningBuf },
151
+ };
152
+ }
153
+ yield { type: "message_complete", stopReason, usage };
154
+ }
155
+ headers() {
156
+ return {
157
+ "content-type": "application/json",
158
+ authorization: `Bearer ${this.apiKey}`,
159
+ };
160
+ }
161
+ }
162
+ /**
163
+ * Build the JSON request body for both `complete` and `stream` paths. The
164
+ * `stream` flag flips streaming and adds the SSE include_usage option so the
165
+ * final chunk carries usage even on streaming.
166
+ */
167
+ function buildRequestBody(opts, stream) {
168
+ const body = {
169
+ model: opts.model,
170
+ messages: translateMessagesToOpenAI(opts.system, opts.messages),
171
+ max_tokens: opts.maxTokens ?? 4096,
172
+ };
173
+ if (opts.tools && opts.tools.length > 0) {
174
+ body.tools = translateToolsToOpenAI(opts.tools);
175
+ }
176
+ if (stream) {
177
+ body.stream = true;
178
+ // Without `stream_options.include_usage` OpenAI-compatible servers send
179
+ // chunks with `usage: null`; this opt-in makes the terminal chunk include
180
+ // full token counts so the loop's token accounting stays accurate.
181
+ body.stream_options = { include_usage: true };
182
+ }
183
+ const effort = effortForDeepseek(opts.effort);
184
+ if (effort) {
185
+ body.reasoning_effort = effort;
186
+ // `extra_body` is the Python SDK convention; DeepSeek's HTTP API accepts
187
+ // the keys at the top level too. We keep top-level for HTTP simplicity.
188
+ body.thinking = { type: "enabled" };
189
+ }
190
+ return body;
191
+ }
192
+ /**
193
+ * Map the SDK's `EffortLevel` to DeepSeek's `reasoning_effort` string.
194
+ * DeepSeek's API ships four tiers (low/medium/high/max); maestro's
195
+ * `xhigh` and `max` both collapse onto DeepSeek `max` — the thinking
196
+ * depth is identical between them, but their maestro-side `maxIter` caps
197
+ * differ (xhigh=90, max=200), so the user-facing distinction is "how
198
+ * much rope before the loop strangles", not API-side reasoning depth.
199
+ *
200
+ * Returns undefined when effort is unset/unknown so the caller can skip
201
+ * thinking entirely.
202
+ */
203
+ export function effortForDeepseek(e) {
204
+ switch (e) {
205
+ case "low":
206
+ return "low";
207
+ case "medium":
208
+ return "medium";
209
+ case "high":
210
+ return "high";
211
+ case "xhigh":
212
+ return "max";
213
+ case "max":
214
+ return "max";
215
+ default:
216
+ return undefined;
217
+ }
218
+ }
219
+ /**
220
+ * Map OpenAI `finish_reason` to the loose stop_reason string the loop and
221
+ * conversation log carry. The loop itself doesn't branch on the value — it
222
+ * just propagates it into the `result` event — but downstream consumers and
223
+ * tests assert on familiar Anthropic-style names, so we normalize here.
224
+ */
225
+ export function mapStopReason(reason) {
226
+ switch (reason) {
227
+ case "tool_calls":
228
+ return "tool_use";
229
+ case "stop":
230
+ return "end_turn";
231
+ case "length":
232
+ return "max_tokens";
233
+ case "content_filter":
234
+ return "stop";
235
+ case null:
236
+ case undefined:
237
+ case "":
238
+ return "end_turn";
239
+ default:
240
+ return reason;
241
+ }
242
+ }
243
+ function mapUsage(u) {
244
+ if (!u)
245
+ return { inputTokens: 0, outputTokens: 0 };
246
+ const out = {
247
+ inputTokens: u.prompt_tokens ?? 0,
248
+ outputTokens: u.completion_tokens ?? 0,
249
+ };
250
+ if (u.prompt_cache_hit_tokens !== undefined) {
251
+ out.cacheReadInputTokens = u.prompt_cache_hit_tokens;
252
+ }
253
+ return out;
254
+ }
255
+ /**
256
+ * Translate a non-streaming OpenAI choice into the Anthropic-shaped content
257
+ * block list. Order: thinking → text → tool_use, matching the streaming path.
258
+ */
259
+ function openAiChoiceToBlocks(choice) {
260
+ const blocks = [];
261
+ const msg = choice.message;
262
+ if (typeof msg.reasoning_content === "string" && msg.reasoning_content.length > 0) {
263
+ blocks.push({ type: "thinking", thinking: msg.reasoning_content });
264
+ }
265
+ if (typeof msg.content === "string" && msg.content.length > 0) {
266
+ blocks.push({ type: "text", text: msg.content });
267
+ }
268
+ if (Array.isArray(msg.tool_calls)) {
269
+ for (const tc of msg.tool_calls) {
270
+ let input = {};
271
+ if (tc.function?.arguments) {
272
+ try {
273
+ input = JSON.parse(tc.function.arguments);
274
+ }
275
+ catch {
276
+ // Defensive — malformed JSON arguments fall through with an empty
277
+ // input. The loop's tool dispatcher then sees no args, same as
278
+ // Anthropic's analogous failure mode.
279
+ }
280
+ }
281
+ blocks.push({
282
+ type: "tool_use",
283
+ id: tc.id,
284
+ name: tc.function?.name ?? "",
285
+ input,
286
+ });
287
+ }
288
+ }
289
+ return blocks;
290
+ }
291
+ /**
292
+ * Translate Maestro's Anthropic-shaped tool schemas into OpenAI function
293
+ * format. DeepSeek accepts the standard `{type:"function", function:{...}}`
294
+ * shape; we pass `input_schema` through as `parameters` (same JSON Schema
295
+ * subset, just renamed).
296
+ */
297
+ export function translateToolsToOpenAI(tools) {
298
+ return tools.map((t) => ({
299
+ type: "function",
300
+ function: {
301
+ name: t.name,
302
+ description: t.description,
303
+ parameters: t.input_schema,
304
+ },
305
+ }));
306
+ }
307
+ /**
308
+ * Translate Maestro's Anthropic-shaped message history into the OpenAI chat
309
+ * shape DeepSeek expects.
310
+ *
311
+ * Key rules — these are the load-bearing parts of the translation, and the
312
+ * unit tests assert each one:
313
+ *
314
+ * 1. The shared `system` string becomes a leading `{role:"system"}` message.
315
+ * Empty strings are dropped (no message at all).
316
+ *
317
+ * 2. Assistant messages aggregate text blocks into `content` and tool_use
318
+ * blocks into `tool_calls`. `thinking` blocks become `reasoning_content`
319
+ * ONLY when the same message also contains a tool_use; otherwise the
320
+ * thinking is dropped per DeepSeek's multi-turn contract (sending back
321
+ * reasoning_content for a final-answer turn produces a 400 on the next
322
+ * request). `redacted_thinking` has no DeepSeek analog and is always
323
+ * dropped.
324
+ *
325
+ * 3. User messages may carry `tool_result` blocks (Anthropic's convention
326
+ * is to wrap them in a user-role message). In OpenAI shape these become
327
+ * separate `{role:"tool", tool_call_id, content}` messages, one per
328
+ * tool_result, emitted IN PLACE inside the message stream so the
329
+ * ordering with surrounding user/assistant text is preserved. A user
330
+ * message that's nothing but tool_results contributes no user message
331
+ * itself — just the N tool messages.
332
+ *
333
+ * 4. Plain string `content` passes through unchanged.
334
+ */
335
+ export function translateMessagesToOpenAI(system, messages) {
336
+ const out = [];
337
+ if (system && system.length > 0) {
338
+ out.push({ role: "system", content: system });
339
+ }
340
+ for (const msg of messages) {
341
+ if (typeof msg.content === "string") {
342
+ // Empty string content is allowed — preserves the slot but means the
343
+ // model emitted nothing. Both roles handled here.
344
+ out.push({ role: msg.role, content: msg.content });
345
+ continue;
346
+ }
347
+ if (msg.role === "user") {
348
+ // Split user content into text portion + per-tool_result messages,
349
+ // preserving the order the blocks appear in. tool_result blocks need
350
+ // their own role:"tool" messages with `tool_call_id`.
351
+ let userText = "";
352
+ for (const block of msg.content) {
353
+ if (block.type === "text") {
354
+ userText += userText.length > 0 ? `\n${block.text}` : block.text;
355
+ }
356
+ else if (block.type === "tool_result") {
357
+ // Flush any text accumulated before this tool_result so ordering
358
+ // with the tool messages is preserved.
359
+ if (userText.length > 0) {
360
+ out.push({ role: "user", content: userText });
361
+ userText = "";
362
+ }
363
+ out.push({
364
+ role: "tool",
365
+ tool_call_id: block.tool_use_id,
366
+ content: block.content,
367
+ });
368
+ }
369
+ // Other block types (tool_use, thinking) don't legally appear in
370
+ // user messages under our pipeline — silently skip if encountered.
371
+ }
372
+ if (userText.length > 0) {
373
+ out.push({ role: "user", content: userText });
374
+ }
375
+ continue;
376
+ }
377
+ // Assistant role: aggregate text, tool_uses, and (conditionally) thinking.
378
+ let assistantText = "";
379
+ const toolCalls = [];
380
+ let pendingThinking = "";
381
+ let hasToolUse = false;
382
+ for (const block of msg.content) {
383
+ if (block.type === "text") {
384
+ assistantText += assistantText.length > 0 ? `\n${block.text}` : block.text;
385
+ }
386
+ else if (block.type === "tool_use") {
387
+ hasToolUse = true;
388
+ toolCalls.push({
389
+ id: block.id,
390
+ type: "function",
391
+ function: {
392
+ name: block.name,
393
+ arguments: JSON.stringify(block.input ?? {}),
394
+ },
395
+ });
396
+ }
397
+ else if (block.type === "thinking") {
398
+ pendingThinking += pendingThinking.length > 0 ? `\n${block.thinking}` : block.thinking;
399
+ }
400
+ // `redacted_thinking` and `tool_result` are skipped.
401
+ }
402
+ const assistantMsg = { role: "assistant" };
403
+ // OpenAI requires either `content` or `tool_calls`. We always set
404
+ // `content` (empty string if nothing) so the request doesn't trip
405
+ // strict validators.
406
+ assistantMsg.content = assistantText;
407
+ if (toolCalls.length > 0) {
408
+ assistantMsg.tool_calls = toolCalls;
409
+ }
410
+ if (hasToolUse && pendingThinking.length > 0) {
411
+ assistantMsg.reasoning_content = pendingThinking;
412
+ }
413
+ out.push(assistantMsg);
414
+ }
415
+ return out;
416
+ }
417
+ /**
418
+ * Parse an OpenAI-compatible `text/event-stream` body into typed events.
419
+ * The format is identical to Anthropic's framing (`data: <json>\n\n`) except
420
+ * the terminator is the literal `data: [DONE]` line, after which we stop
421
+ * reading. Each `data:` payload's JSON is yielded as-is — the caller switches
422
+ * on `choices[0].finish_reason` and `delta` keys.
423
+ */
424
+ async function* parseSseStream(body, abortSignal) {
425
+ const reader = body.getReader();
426
+ const decoder = new TextDecoder("utf-8");
427
+ let buf = "";
428
+ const onAbort = () => {
429
+ reader.cancel("aborted").catch(() => { });
430
+ };
431
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
432
+ try {
433
+ while (true) {
434
+ const { value, done } = await reader.read();
435
+ if (done)
436
+ break;
437
+ buf += decoder.decode(value, { stream: true });
438
+ let idx = buf.indexOf("\n\n");
439
+ while (idx >= 0) {
440
+ const raw = buf.slice(0, idx);
441
+ buf = buf.slice(idx + 2);
442
+ const dataLine = raw
443
+ .split("\n")
444
+ .find((l) => l.startsWith("data:"))
445
+ ?.slice("data:".length)
446
+ .trim();
447
+ if (dataLine) {
448
+ if (dataLine === "[DONE]")
449
+ return;
450
+ try {
451
+ yield JSON.parse(dataLine);
452
+ }
453
+ catch {
454
+ // Skip malformed frames — DeepSeek shouldn't emit them, and one
455
+ // bad byte shouldn't kill a turn.
456
+ }
457
+ }
458
+ idx = buf.indexOf("\n\n");
459
+ }
460
+ }
461
+ }
462
+ finally {
463
+ abortSignal?.removeEventListener("abort", onAbort);
464
+ reader.releaseLock();
465
+ }
466
+ }
467
+ //# sourceMappingURL=deepseek.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../../src/providers/deepseek.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AgentRegistry } from "./agents/contracts.js";
2
+ export declare const maestroRegistry: AgentRegistry;
3
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAsCxD,eAAO,MAAM,eAAe,EAAE,aAmE7B,CAAC"}
@@ -0,0 +1,94 @@
1
+ import { unlinkSync } from "node:fs";
2
+ import { maestroSessionPath, writeMaestroRollout } from "./session-store.js";
3
+ import { MODEL_DEEPSEEK_V4_FLASH, MODEL_DEEPSEEK_V4_PRO, MODEL_SONNET, } from "./platform/config.js";
4
+ import { logger } from "./platform/logger.js";
5
+ import { readConversation } from "./storage/conversations.js";
6
+ import { MAESTRO_EFFORT_VALUES } from "./types.js";
7
+ /**
8
+ * Maestro registry — wired for multi-turn sessions + cross-agent bridging.
9
+ *
10
+ * Default model stays `sonnet` (Anthropic adapter is the original surface).
11
+ * `deepseek` family aliases land on V4-Flash by default — same model as the
12
+ * default `deepseek-chat` (V3.2-Exp non-thinking) successor, but cheap and
13
+ * fast for general use. Switch via `set_model deepseek-pro` per topic when
14
+ * heavier reasoning is wanted.
15
+ *
16
+ * Session persistence lives at `~/.maestro/sessions/<sessionId>.jsonl` —
17
+ * one ProviderMessage per line. Unlike claude/codex (which delegate
18
+ * persistence to their SDKs), maestro owns its own store, but the
19
+ * `writeRollout` / `forkSession` / `cleanupRollouts` contracts behave
20
+ * identically from the caller's perspective.
21
+ */
22
+ const ALIAS_MAP = {
23
+ sonnet: MODEL_SONNET,
24
+ deepseek: MODEL_DEEPSEEK_V4_FLASH,
25
+ "deepseek-flash": MODEL_DEEPSEEK_V4_FLASH,
26
+ "deepseek-pro": MODEL_DEEPSEEK_V4_PRO,
27
+ };
28
+ const VALID_ALIASES = new Set(Object.keys(ALIAS_MAP));
29
+ const VALID_FULL_IDS = new Set(Object.values(ALIAS_MAP));
30
+ const VALID_EFFORTS = new Set(MAESTRO_EFFORT_VALUES);
31
+ export const maestroRegistry = {
32
+ kind: "maestro",
33
+ defaultModel: "sonnet",
34
+ defaultEffort: "medium",
35
+ expandModelAlias(s) {
36
+ return ALIAS_MAP[s] ?? s;
37
+ },
38
+ validateModel(s) {
39
+ return VALID_ALIASES.has(s) || VALID_FULL_IDS.has(s);
40
+ },
41
+ validEfforts: MAESTRO_EFFORT_VALUES,
42
+ validateEffort(s) {
43
+ return VALID_EFFORTS.has(s);
44
+ },
45
+ footerLabel(model, effort) {
46
+ return effort ? `${model} · ${effort}` : model;
47
+ },
48
+ // `reuseSessionId` (if any) keeps the same file path across set_agent
49
+ // round-trips so prompt-cache continuity and the "one continuous
50
+ // conversation" UX work the same way they do for claude/codex.
51
+ writeRollout(opts) {
52
+ const { sessionId, rolloutPath } = writeMaestroRollout({
53
+ cwd: opts.cwd,
54
+ entries: opts.entries,
55
+ ...(opts.reuseSessionId ? { sessionId: opts.reuseSessionId } : {}),
56
+ });
57
+ return { sessionId, rolloutPath };
58
+ },
59
+ // Maestro has no SDK fork API. We synthesize a session file from the
60
+ // provider-agnostic conversation log (same path as `set_agent` cross-agent
61
+ // bridging). Caveat mirrors codex: extractChatPairs folds tool_use /
62
+ // tool_result into assistant text as `[Tool: ...]` annotations, so
63
+ // structural tool history is lost. Acceptable trade-off — the fork starts
64
+ // with text-level context and the model still sees what ran.
65
+ async forkSession({ cwd, userId, topicName, groupId }) {
66
+ const entries = readConversation(userId, topicName, groupId);
67
+ const { sessionId, rolloutPath } = writeMaestroRollout({ cwd, entries });
68
+ return { forkId: sessionId, rolloutPath };
69
+ },
70
+ // Per-session unlink — no globbing needed since paths are flat under
71
+ // `~/.maestro/sessions/`. ENOENT is ignored; other I/O errors collect into
72
+ // an AggregateError so `purgeTopicLogs` can surface them.
73
+ async cleanupRollouts({ sessionIds }) {
74
+ if (sessionIds.length === 0)
75
+ return;
76
+ const failures = [];
77
+ for (const sid of sessionIds) {
78
+ const path = maestroSessionPath(sid);
79
+ try {
80
+ unlinkSync(path);
81
+ }
82
+ catch (e) {
83
+ if (e?.code !== "ENOENT") {
84
+ logger.warn({ err: e, path }, "maestro cleanupRollouts: unlink failed");
85
+ failures.push(e);
86
+ }
87
+ }
88
+ }
89
+ if (failures.length > 0) {
90
+ throw new AggregateError(failures, "maestro cleanupRollouts failed");
91
+ }
92
+ },
93
+ };
94
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}