@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2

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 (258) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +11 -11
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,348 +1,346 @@
1
1
  import { GoalManager } from "../goal-manager.js";
2
2
  import { createGoalReminderSignal } from "../goal-signal.js";
3
3
  import { autoApprovePolicy } from "./policy.js";
4
+ //#region src/headless/run-mc.ts
4
5
  function extractAssistantText(message) {
5
- return message.content.parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
6
+ return message.content.parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
6
7
  }
7
8
  function exitCodeForStatus(status) {
8
- switch (status) {
9
- case "completed":
10
- case "done":
11
- return 0;
12
- case "timeout":
13
- return 2;
14
- default:
15
- return 1;
16
- }
9
+ switch (status) {
10
+ case "completed":
11
+ case "done": return 0;
12
+ case "timeout": return 2;
13
+ default: return 1;
14
+ }
17
15
  }
18
16
  function aggregate(event, acc) {
19
- switch (event.type) {
20
- case "message_end":
21
- if (event.message.role === "assistant") {
22
- acc.text += extractAssistantText(event.message);
23
- }
24
- break;
25
- case "tool_start":
26
- acc.toolCalls.push({ id: event.toolCallId, name: event.toolName, args: event.args });
27
- break;
28
- case "tool_end": {
29
- const matching = acc.toolCalls.find((c) => c.id === event.toolCallId);
30
- acc.toolResults.push({
31
- id: event.toolCallId,
32
- name: matching?.name ?? "",
33
- result: event.result,
34
- isError: event.isError
35
- });
36
- break;
37
- }
38
- case "usage_update":
39
- acc.usage = {
40
- inputTokens: event.usage.promptTokens,
41
- outputTokens: event.usage.completionTokens,
42
- totalTokens: event.usage.totalTokens
43
- };
44
- break;
45
- case "error":
46
- acc.error = {
47
- name: event.error.name,
48
- message: event.error.message,
49
- stack: event.error.stack
50
- };
51
- break;
52
- }
17
+ switch (event.type) {
18
+ case "message_end":
19
+ if (event.message.role === "assistant") acc.text += extractAssistantText(event.message);
20
+ break;
21
+ case "tool_start":
22
+ acc.toolCalls.push({
23
+ id: event.toolCallId,
24
+ name: event.toolName,
25
+ args: event.args
26
+ });
27
+ break;
28
+ case "tool_end": {
29
+ const matching = acc.toolCalls.find((c) => c.id === event.toolCallId);
30
+ acc.toolResults.push({
31
+ id: event.toolCallId,
32
+ name: matching?.name ?? "",
33
+ result: event.result,
34
+ isError: event.isError
35
+ });
36
+ break;
37
+ }
38
+ case "usage_update":
39
+ acc.usage = {
40
+ inputTokens: event.usage.promptTokens,
41
+ outputTokens: event.usage.completionTokens,
42
+ totalTokens: event.usage.totalTokens
43
+ };
44
+ break;
45
+ case "error":
46
+ acc.error = {
47
+ name: event.error.name,
48
+ message: event.error.message,
49
+ stack: event.error.stack
50
+ };
51
+ break;
52
+ }
53
53
  }
54
+ /** Resolve a thread by its exact ID. Titles are not unique, so we don't match on them. */
54
55
  async function resolveThread(session, threadId) {
55
- const threads = await session.thread.list();
56
- const byId = threads.find((t) => t.id === threadId);
57
- if (byId) return { threadId: byId.id };
58
- return { error: `No thread found with ID "${threadId}"` };
59
- }
60
- class EventQueue {
61
- #buffer = [];
62
- #resolvers = [];
63
- #closed = false;
64
- #maxBuffer;
65
- constructor(maxBuffer = 1e4) {
66
- this.#maxBuffer = maxBuffer;
67
- }
68
- push(value) {
69
- if (this.#closed) return;
70
- const resolve = this.#resolvers.shift();
71
- if (resolve) {
72
- resolve({ value, done: false });
73
- return;
74
- }
75
- this.#buffer.push(value);
76
- if (this.#buffer.length > this.#maxBuffer) {
77
- this.#buffer.shift();
78
- }
79
- }
80
- close() {
81
- if (this.#closed) return;
82
- this.#closed = true;
83
- for (const resolve of this.#resolvers.splice(0)) {
84
- resolve({ value: void 0, done: true });
85
- }
86
- }
87
- [Symbol.asyncIterator]() {
88
- return {
89
- next: () => {
90
- if (this.#buffer.length > 0) {
91
- return Promise.resolve({ value: this.#buffer.shift(), done: false });
92
- }
93
- if (this.#closed) {
94
- return Promise.resolve({ value: void 0, done: true });
95
- }
96
- return new Promise((resolve) => this.#resolvers.push(resolve));
97
- }
98
- };
99
- }
56
+ const byId = (await session.thread.list()).find((t) => t.id === threadId);
57
+ if (byId) return { threadId: byId.id };
58
+ return { error: `No thread found with ID "${threadId}"` };
100
59
  }
60
+ /**
61
+ * A simple back-pressured async queue. Events are pushed in; consumers pull via
62
+ * the async iterator. `close()` ends iteration after draining buffered events.
63
+ *
64
+ * Buffered events are bounded by `maxBuffer`: if a consumer never iterates (the
65
+ * result-only path, `await run.result` without `for await (...)`) — or simply
66
+ * falls far behind — the oldest buffered events are dropped instead of growing
67
+ * without limit. The aggregated {@link RunMCResult} is built independently of
68
+ * this queue, so dropping buffered events never affects the final result.
69
+ */
70
+ var EventQueue = class {
71
+ #buffer = [];
72
+ #resolvers = [];
73
+ #closed = false;
74
+ #maxBuffer;
75
+ constructor(maxBuffer = 1e4) {
76
+ this.#maxBuffer = maxBuffer;
77
+ }
78
+ push(value) {
79
+ if (this.#closed) return;
80
+ const resolve = this.#resolvers.shift();
81
+ if (resolve) {
82
+ resolve({
83
+ value,
84
+ done: false
85
+ });
86
+ return;
87
+ }
88
+ this.#buffer.push(value);
89
+ if (this.#buffer.length > this.#maxBuffer) this.#buffer.shift();
90
+ }
91
+ close() {
92
+ if (this.#closed) return;
93
+ this.#closed = true;
94
+ for (const resolve of this.#resolvers.splice(0)) resolve({
95
+ value: void 0,
96
+ done: true
97
+ });
98
+ }
99
+ [Symbol.asyncIterator]() {
100
+ return { next: () => {
101
+ if (this.#buffer.length > 0) return Promise.resolve({
102
+ value: this.#buffer.shift(),
103
+ done: false
104
+ });
105
+ if (this.#closed) return Promise.resolve({
106
+ value: void 0,
107
+ done: true
108
+ });
109
+ return new Promise((resolve) => this.#resolvers.push(resolve));
110
+ } };
111
+ }
112
+ };
113
+ /**
114
+ * Run a headless MastraCode turn. Returns an {@link MCRun} handle that is
115
+ * async-iterable over controller events and resolves to a {@link RunMCResult}.
116
+ */
101
117
  function runMC(options) {
102
- const { controller, session } = options;
103
- const goal = options.goal;
104
- const policy = options.policy ?? autoApprovePolicy;
105
- const queue = new EventQueue();
106
- const acc = { text: "", toolCalls: [], toolResults: [] };
107
- let timeoutId;
108
- let timedOut = false;
109
- let aborted = false;
110
- let maxTurnsExceeded = false;
111
- let assistantTurns = 0;
112
- let settled = false;
113
- let unsubscribe;
114
- let resolveResult;
115
- const result = new Promise((resolve) => {
116
- resolveResult = resolve;
117
- });
118
- function finish(status, data = {}) {
119
- if (settled) return;
120
- settled = true;
121
- if (timeoutId) clearTimeout(timeoutId);
122
- unsubscribe?.();
123
- queue.close();
124
- resolveResult({
125
- status,
126
- text: acc.text,
127
- finishReason: acc.finishReason,
128
- usage: acc.usage,
129
- toolCalls: acc.toolCalls,
130
- toolResults: acc.toolResults,
131
- threadId: acc.threadId ?? session.thread.getId() ?? void 0,
132
- error: acc.error,
133
- exitCode: exitCodeForStatus(status),
134
- ...data
135
- });
136
- }
137
- function fail(message, name = "Error") {
138
- if (!acc.error) acc.error = { name, message };
139
- finish("error");
140
- }
141
- function abort() {
142
- if (settled) return;
143
- aborted = true;
144
- session.abort();
145
- }
146
- if (options.signal) {
147
- if (options.signal.aborted) {
148
- queueMicrotask(() => abort());
149
- } else {
150
- options.signal.addEventListener("abort", () => abort(), { once: true });
151
- }
152
- }
153
- function armTimeout() {
154
- if (!options.timeoutMs || settled) return;
155
- if (timeoutId) clearTimeout(timeoutId);
156
- timeoutId = setTimeout(() => {
157
- timedOut = true;
158
- session.abort();
159
- if (goal) finish("timeout");
160
- }, options.timeoutMs);
161
- }
162
- void (async () => {
163
- armTimeout();
164
- try {
165
- if (options.model) {
166
- const available = await controller.listAvailableModels();
167
- const match = available.find((m) => m.id === options.model);
168
- if (!match) return fail(`Unknown model: "${options.model}"`);
169
- if (!match.hasApiKey) {
170
- const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : "";
171
- return fail(`Model "${options.model}" has no API key configured.${keyHint}`);
172
- }
173
- await session.model.switch({ modelId: options.model });
174
- } else if (options.mode) {
175
- const modelId = options.modeDefaults?.[options.mode];
176
- if (modelId) {
177
- const available = await controller.listAvailableModels();
178
- const match = available.find((m) => m.id === modelId);
179
- if (!match) return fail(`Unknown model "${modelId}" configured for mode "${options.mode}"`);
180
- if (!match.hasApiKey) {
181
- const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : "";
182
- return fail(`Model "${modelId}" (mode: ${options.mode}) has no API key configured.${keyHint}`);
183
- }
184
- await session.model.switch({ modelId });
185
- }
186
- }
187
- if (options.thinkingLevel) {
188
- await session.state.set({ thinkingLevel: options.thinkingLevel });
189
- }
190
- } catch (err) {
191
- return fail(`Failed to resolve run config: ${err.message}`);
192
- }
193
- unsubscribe = session.subscribe((event) => {
194
- if (settled) return;
195
- if (goal) armTimeout();
196
- if (event.type === "tool_approval_required") {
197
- let decision;
198
- try {
199
- decision = policy.onToolApproval(event);
200
- } catch (err) {
201
- fail(`Resolution policy failed: ${err.message}`);
202
- return;
203
- }
204
- session.respondToToolApproval({
205
- decision: decision === "approve" ? "approve" : "decline",
206
- toolCallId: event.toolCallId
207
- });
208
- queue.push(event);
209
- return;
210
- }
211
- if (event.type === "tool_suspended") {
212
- let outcome;
213
- try {
214
- outcome = policy.onSuspension(event);
215
- } catch (err) {
216
- fail(`Resolution policy failed: ${err.message}`);
217
- return;
218
- }
219
- if ("abort" in outcome) {
220
- queue.push(event);
221
- abort();
222
- return;
223
- }
224
- void session.respondToToolSuspension({ toolCallId: event.toolCallId, resumeData: outcome.resumeData });
225
- queue.push(event);
226
- return;
227
- }
228
- aggregate(event, acc);
229
- queue.push(event);
230
- if (event.type === "error" && goal) {
231
- finish("error");
232
- return;
233
- }
234
- if (event.type === "message_end" && event.message.role === "assistant" && options.maxTurns !== void 0) {
235
- assistantTurns += 1;
236
- if (assistantTurns >= options.maxTurns && !maxTurnsExceeded) {
237
- maxTurnsExceeded = true;
238
- abort();
239
- }
240
- }
241
- if (event.type === "goal_evaluation" && goal && !event.payload.pending) {
242
- if (event.payload.status === "done" || event.payload.status === "paused") {
243
- finish(event.payload.status, {
244
- objective: goal.objective,
245
- goalEvent: event,
246
- reason: event.payload.reason ?? event.payload.results?.[0]?.reason,
247
- iterations: event.payload.iteration,
248
- maxRuns: event.payload.maxRuns
249
- });
250
- }
251
- return;
252
- }
253
- if (event.type === "agent_end") {
254
- acc.finishReason = event.reason;
255
- if (goal) return;
256
- if (timedOut) {
257
- finish("timeout");
258
- } else if (event.reason === "error") {
259
- finish("error");
260
- } else if (maxTurnsExceeded && event.reason !== "complete") {
261
- finish("max_turns");
262
- } else if ((event.reason === "aborted" || aborted) && !maxTurnsExceeded) {
263
- finish("aborted");
264
- } else {
265
- finish("completed");
266
- }
267
- }
268
- });
269
- try {
270
- if (options.resourceId) {
271
- await controller.setResourceId(session, { resourceId: options.resourceId });
272
- }
273
- } catch (err) {
274
- return fail(`Failed to set resource id: ${err.message}`);
275
- }
276
- try {
277
- const thread = options.thread;
278
- if (thread?.id) {
279
- const resolved = await resolveThread(session, thread.id);
280
- if ("error" in resolved) return fail(resolved.error);
281
- await session.thread.switch({ threadId: resolved.threadId });
282
- } else if (thread?.continueLatest) {
283
- const threads = await session.thread.list();
284
- if (threads.length > 0) {
285
- const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
286
- await session.thread.switch({ threadId: sorted[0].id });
287
- }
288
- }
289
- } catch (err) {
290
- return fail(`Failed to select thread: ${err.message}`);
291
- }
292
- if (options.thread?.clone) {
293
- try {
294
- await session.thread.clone();
295
- } catch (err) {
296
- return fail(`Failed to clone thread: ${err.message}`);
297
- }
298
- }
299
- if (options.title) {
300
- try {
301
- await session.thread.rename({ title: options.title });
302
- } catch (err) {
303
- return fail(`Failed to set thread title: ${err.message}`);
304
- }
305
- }
306
- try {
307
- if (goal) {
308
- const threadId = session.thread.getId();
309
- if (!threadId || !await session.thread.getById({ threadId })) {
310
- await session.thread.create();
311
- }
312
- const goalManager = goal.goalManager ?? new GoalManager();
313
- const state = {
314
- controller,
315
- session,
316
- goalManager,
317
- pendingNewThread: false,
318
- planStartedGoalId: void 0
319
- };
320
- const objective = await goalManager.setGoal(state, goal.objective, goal.judgeModelId, goal.maxRuns);
321
- if (!objective) return fail("Failed to set goal.");
322
- const agent = controller.getCurrentAgent(session);
323
- const persisted = await agent.getObjective({ threadId: session.thread.getId() });
324
- if (!persisted || persisted.id !== objective.id) {
325
- return fail("Failed to persist goal objective before sending goal signal.");
326
- }
327
- await goalManager.saveToThread(state);
328
- if (!settled) await session.sendSignal(createGoalReminderSignal(objective)).accepted;
329
- } else {
330
- if (!options.prompt) return fail("A prompt or goal is required.");
331
- await session.sendMessage({ content: options.prompt });
332
- }
333
- } catch (err) {
334
- return fail(`Failed to start run: ${err.message}`);
335
- }
336
- })();
337
- return {
338
- result,
339
- abort,
340
- [Symbol.asyncIterator]() {
341
- return queue[Symbol.asyncIterator]();
342
- }
343
- };
118
+ const { controller, session } = options;
119
+ const goal = options.goal;
120
+ const policy = options.policy ?? autoApprovePolicy;
121
+ const queue = new EventQueue();
122
+ const acc = {
123
+ text: "",
124
+ toolCalls: [],
125
+ toolResults: []
126
+ };
127
+ let timeoutId;
128
+ let timedOut = false;
129
+ let aborted = false;
130
+ let maxTurnsExceeded = false;
131
+ let assistantTurns = 0;
132
+ let settled = false;
133
+ let unsubscribe;
134
+ let resolveResult;
135
+ const result = new Promise((resolve) => {
136
+ resolveResult = resolve;
137
+ });
138
+ function finish(status, data = {}) {
139
+ if (settled) return;
140
+ settled = true;
141
+ if (timeoutId) clearTimeout(timeoutId);
142
+ unsubscribe?.();
143
+ queue.close();
144
+ resolveResult({
145
+ status,
146
+ text: acc.text,
147
+ finishReason: acc.finishReason,
148
+ usage: acc.usage,
149
+ toolCalls: acc.toolCalls,
150
+ toolResults: acc.toolResults,
151
+ threadId: acc.threadId ?? session.thread.getId() ?? void 0,
152
+ error: acc.error,
153
+ exitCode: exitCodeForStatus(status),
154
+ ...data
155
+ });
156
+ }
157
+ function fail(message, name = "Error") {
158
+ if (!acc.error) acc.error = {
159
+ name,
160
+ message
161
+ };
162
+ finish("error");
163
+ }
164
+ function abort() {
165
+ if (settled) return;
166
+ aborted = true;
167
+ session.abort();
168
+ }
169
+ if (options.signal) if (options.signal.aborted) queueMicrotask(() => abort());
170
+ else options.signal.addEventListener("abort", () => abort(), { once: true });
171
+ function armTimeout() {
172
+ if (!options.timeoutMs || settled) return;
173
+ if (timeoutId) clearTimeout(timeoutId);
174
+ timeoutId = setTimeout(() => {
175
+ timedOut = true;
176
+ session.abort();
177
+ if (goal) finish("timeout");
178
+ }, options.timeoutMs);
179
+ }
180
+ (async () => {
181
+ armTimeout();
182
+ try {
183
+ if (options.model) {
184
+ const match = (await controller.listAvailableModels()).find((m) => m.id === options.model);
185
+ if (!match) return fail(`Unknown model: "${options.model}"`);
186
+ if (!match.hasApiKey) {
187
+ const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : "";
188
+ return fail(`Model "${options.model}" has no API key configured.${keyHint}`);
189
+ }
190
+ await session.model.switch({ modelId: options.model });
191
+ } else if (options.mode) {
192
+ const modelId = options.modeDefaults?.[options.mode];
193
+ if (modelId) {
194
+ const match = (await controller.listAvailableModels()).find((m) => m.id === modelId);
195
+ if (!match) return fail(`Unknown model "${modelId}" configured for mode "${options.mode}"`);
196
+ if (!match.hasApiKey) {
197
+ const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : "";
198
+ return fail(`Model "${modelId}" (mode: ${options.mode}) has no API key configured.${keyHint}`);
199
+ }
200
+ await session.model.switch({ modelId });
201
+ }
202
+ }
203
+ if (options.thinkingLevel) await session.state.set({ thinkingLevel: options.thinkingLevel });
204
+ } catch (err) {
205
+ return fail(`Failed to resolve run config: ${err.message}`);
206
+ }
207
+ unsubscribe = session.subscribe((event) => {
208
+ if (settled) return;
209
+ if (goal) armTimeout();
210
+ if (event.type === "tool_approval_required") {
211
+ let decision;
212
+ try {
213
+ decision = policy.onToolApproval(event);
214
+ } catch (err) {
215
+ fail(`Resolution policy failed: ${err.message}`);
216
+ return;
217
+ }
218
+ session.respondToToolApproval({
219
+ decision: decision === "approve" ? "approve" : "decline",
220
+ toolCallId: event.toolCallId
221
+ });
222
+ queue.push(event);
223
+ return;
224
+ }
225
+ if (event.type === "tool_suspended") {
226
+ let outcome;
227
+ try {
228
+ outcome = policy.onSuspension(event);
229
+ } catch (err) {
230
+ fail(`Resolution policy failed: ${err.message}`);
231
+ return;
232
+ }
233
+ if ("abort" in outcome) {
234
+ queue.push(event);
235
+ abort();
236
+ return;
237
+ }
238
+ session.respondToToolSuspension({
239
+ toolCallId: event.toolCallId,
240
+ resumeData: outcome.resumeData
241
+ });
242
+ queue.push(event);
243
+ return;
244
+ }
245
+ aggregate(event, acc);
246
+ queue.push(event);
247
+ if (event.type === "error" && goal) {
248
+ finish("error");
249
+ return;
250
+ }
251
+ if (event.type === "message_end" && event.message.role === "assistant" && options.maxTurns !== void 0) {
252
+ assistantTurns += 1;
253
+ if (assistantTurns >= options.maxTurns && !maxTurnsExceeded) {
254
+ maxTurnsExceeded = true;
255
+ abort();
256
+ }
257
+ }
258
+ if (event.type === "goal_evaluation" && goal && !event.payload.pending) {
259
+ if (event.payload.status === "done" || event.payload.status === "paused") finish(event.payload.status, {
260
+ objective: goal.objective,
261
+ goalEvent: event,
262
+ reason: event.payload.reason ?? event.payload.results?.[0]?.reason,
263
+ iterations: event.payload.iteration,
264
+ maxRuns: event.payload.maxRuns
265
+ });
266
+ return;
267
+ }
268
+ if (event.type === "agent_end") {
269
+ acc.finishReason = event.reason;
270
+ if (goal) return;
271
+ if (timedOut) finish("timeout");
272
+ else if (event.reason === "error") finish("error");
273
+ else if (maxTurnsExceeded && event.reason !== "complete") finish("max_turns");
274
+ else if ((event.reason === "aborted" || aborted) && !maxTurnsExceeded) finish("aborted");
275
+ else finish("completed");
276
+ }
277
+ });
278
+ try {
279
+ if (options.resourceId) await controller.setResourceId(session, { resourceId: options.resourceId });
280
+ } catch (err) {
281
+ return fail(`Failed to set resource id: ${err.message}`);
282
+ }
283
+ try {
284
+ const thread = options.thread;
285
+ if (thread?.id) {
286
+ const resolved = await resolveThread(session, thread.id);
287
+ if ("error" in resolved) return fail(resolved.error);
288
+ await session.thread.switch({ threadId: resolved.threadId });
289
+ } else if (thread?.continueLatest) {
290
+ const threads = await session.thread.list();
291
+ if (threads.length > 0) {
292
+ const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
293
+ await session.thread.switch({ threadId: sorted[0].id });
294
+ }
295
+ }
296
+ } catch (err) {
297
+ return fail(`Failed to select thread: ${err.message}`);
298
+ }
299
+ if (options.thread?.clone) try {
300
+ await session.thread.clone();
301
+ } catch (err) {
302
+ return fail(`Failed to clone thread: ${err.message}`);
303
+ }
304
+ if (options.title) try {
305
+ await session.thread.rename({ title: options.title });
306
+ } catch (err) {
307
+ return fail(`Failed to set thread title: ${err.message}`);
308
+ }
309
+ try {
310
+ if (goal) {
311
+ const threadId = session.thread.getId();
312
+ if (!threadId || !await session.thread.getById({ threadId })) await session.thread.create();
313
+ const goalManager = goal.goalManager ?? new GoalManager();
314
+ const state = {
315
+ controller,
316
+ session,
317
+ goalManager,
318
+ pendingNewThread: false,
319
+ planStartedGoalId: void 0
320
+ };
321
+ const objective = await goalManager.setGoal(state, goal.objective, goal.judgeModelId, goal.maxRuns);
322
+ if (!objective) return fail("Failed to set goal.");
323
+ const persisted = await controller.getCurrentAgent(session).getObjective({ threadId: session.thread.getId() });
324
+ if (!persisted || persisted.id !== objective.id) return fail("Failed to persist goal objective before sending goal signal.");
325
+ await goalManager.saveToThread(state);
326
+ if (!settled) await session.sendSignal(createGoalReminderSignal(objective)).accepted;
327
+ } else {
328
+ if (!options.prompt) return fail("A prompt or goal is required.");
329
+ await session.sendMessage({ content: options.prompt });
330
+ }
331
+ } catch (err) {
332
+ return fail(`Failed to start run: ${err.message}`);
333
+ }
334
+ })();
335
+ return {
336
+ result,
337
+ abort,
338
+ [Symbol.asyncIterator]() {
339
+ return queue[Symbol.asyncIterator]();
340
+ }
341
+ };
344
342
  }
345
- export {
346
- runMC
347
- };
343
+ //#endregion
344
+ export { runMC };
345
+
348
346
  //# sourceMappingURL=run-mc.js.map