@mastra/code-sdk 0.2.0-alpha.2 → 0.2.0-alpha.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @mastra/code-sdk
2
2
 
3
+ ## 0.2.0-alpha.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed ACP clients dropping standalone signal messages such as system reminders and notification summaries, while preserving assistant text deltas across interleaved signals without inserting separators. ([#18783](https://github.com/mastra-ai/mastra/pull/18783))
8
+
9
+ - Updated dependencies [[`1426af2`](https://github.com/mastra-ai/mastra/commit/1426af24975879c000d13ac75673f630fcc970c1), [`975295d`](https://github.com/mastra-ai/mastra/commit/975295d418552f0d46a59edfef4c3ee555f9930a), [`85e4fb5`](https://github.com/mastra-ai/mastra/commit/85e4fb50087a81c74df3a762f53b56373db0b912), [`19881f5`](https://github.com/mastra-ai/mastra/commit/19881f5d6a09437cf5b947d2e8be3bd8745df767), [`ef03c0c`](https://github.com/mastra-ai/mastra/commit/ef03c0cfc62367a458e4cc56462e2148b35681c5), [`4fb4d88`](https://github.com/mastra-ai/mastra/commit/4fb4d881bc107acee13890ad4d78661016c510ed), [`4eba27a`](https://github.com/mastra-ai/mastra/commit/4eba27adcf60f991df0e62f94b3e75b4e67f3b4b), [`c701be3`](https://github.com/mastra-ai/mastra/commit/c701be32d7d9aa94a66da8c6cc38dcac6856f464)]:
10
+ - @mastra/core@1.52.0-alpha.3
11
+ - @mastra/pg@1.16.1-alpha.0
12
+
3
13
  ## 0.2.0-alpha.2
4
14
 
5
15
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"event-mapper.d.ts","sourceRoot":"","sources":["../../src/acp/event-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiD,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACnH,OAAO,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAI/F;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEnD;AA4BD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,KAAK,IAAI,CAAC;CAC3E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,OAAO,GACf,IAAI,CAyEN"}
1
+ {"version":3,"file":"event-mapper.d.ts","sourceRoot":"","sources":["../../src/acp/event-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiD,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACnH,OAAO,KAAK,EAAE,oBAAoB,EAAmB,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAyBhH;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEnD;AA4BD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,KAAK,IAAI,CAAC;CAC3E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,OAAO,GACf,IAAI,CAkFN"}
@@ -1,3 +1,15 @@
1
+ import { mastraDBMessageToSignal } from "@mastra/core/signals";
2
+ function getMessageText(message) {
3
+ const content = message.content;
4
+ if (typeof content === "string" || !content?.parts) return "";
5
+ return content.parts.filter((part) => part.type === "text").map((part) => part.text).join("");
6
+ }
7
+ function getSignalText(message) {
8
+ const contents = mastraDBMessageToSignal(message).contents;
9
+ if (typeof contents === "string") return contents;
10
+ if (!Array.isArray(contents)) return "";
11
+ return contents.filter((part) => part.type === "text").map((part) => part.text).join("\n");
12
+ }
1
13
  let autoApprove = false;
2
14
  function setAutoApprove(value) {
3
15
  autoApprove = value;
@@ -22,9 +34,20 @@ function handleAgentControllerEvent(event, state, connection, session) {
22
34
  case "agent_start":
23
35
  state.lastTextLength = 0;
24
36
  break;
37
+ case "message_start": {
38
+ if (event.message.role !== "signal") break;
39
+ const text = getSignalText(event.message);
40
+ if (text) {
41
+ sendUpdate(connection, state.sessionId, {
42
+ sessionUpdate: "agent_message_chunk",
43
+ content: { type: "text", text }
44
+ });
45
+ }
46
+ break;
47
+ }
25
48
  case "message_update": {
26
49
  if (event.message.role !== "assistant") break;
27
- const fullText = event.message.content.filter((c) => c.type === "text").map((p) => p.text).join("");
50
+ const fullText = getMessageText(event.message);
28
51
  if (fullText.length > state.lastTextLength) {
29
52
  const delta = fullText.slice(state.lastTextLength);
30
53
  state.lastTextLength = fullText.length;
@@ -36,7 +59,7 @@ function handleAgentControllerEvent(event, state, connection, session) {
36
59
  break;
37
60
  }
38
61
  case "message_end":
39
- state.lastTextLength = 0;
62
+ if (event.message.role === "assistant") state.lastTextLength = 0;
40
63
  break;
41
64
  case "tool_start":
42
65
  sendUpdate(connection, state.sessionId, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/acp/event-mapper.ts"],"sourcesContent":["import type { SessionNotification, RequestPermissionRequest, AgentSideConnection } from '@agentclientprotocol/sdk';\nimport type { AgentControllerEvent, Session, TokenUsage } from '@mastra/core/agent-controller';\n\nlet autoApprove = false;\n\n/**\n * Enable or disable automatic tool approval (set via --dangerous-auto-approve CLI flag).\n */\nexport function setAutoApprove(value: boolean): void {\n autoApprove = value;\n}\n\n/**\n * Map a mastracode tool name to an ACP ToolKind.\n */\nfunction mapToolKind(\n toolName: string,\n): 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'other' {\n const name = toolName.toLowerCase();\n if (name.includes('edit') || name.includes('write') || name.includes('replace') || name.includes('patch'))\n return 'edit';\n if (name.includes('read') || name.includes('view') || name.includes('list') || name.includes('find')) return 'read';\n if (name.includes('delete') || name.includes('remove')) return 'delete';\n if (name.includes('search') || name.includes('grep') || name.includes('query')) return 'search';\n if (name.includes('execute') || name.includes('run') || name.includes('command') || name.includes('shell'))\n return 'execute';\n if (\n name.includes('fetch') ||\n name.includes('curl') ||\n name.includes('http') ||\n name.includes('browse') ||\n name.includes('navigate')\n )\n return 'fetch';\n if (name.includes('think') || name.includes('reason')) return 'think';\n return 'other';\n}\n\n/**\n * Accumulated state for an active prompt turn.\n */\nexport interface PromptState {\n sessionId: string;\n lastTextLength: number;\n usage: TokenUsage;\n resolve: (reason: 'complete' | 'aborted' | 'error' | 'suspended') => void;\n}\n\n/**\n * Translate an AgentControllerEvent into an ACP SessionNotification and send it\n * via the provided connection. Returns null for events that don't produce\n * a session update.\n */\nexport function handleAgentControllerEvent(\n event: AgentControllerEvent,\n state: PromptState | null,\n connection: AgentSideConnection,\n session: Session,\n): void {\n if (!state) return;\n\n switch (event.type) {\n case 'agent_start':\n state.lastTextLength = 0;\n break;\n\n case 'message_update': {\n if (event.message.role !== 'assistant') break;\n const fullText = event.message.content\n .filter((c): c is { type: 'text'; text: string } => c.type === 'text')\n .map(p => p.text)\n .join('');\n if (fullText.length > state.lastTextLength) {\n const delta = fullText.slice(state.lastTextLength);\n state.lastTextLength = fullText.length;\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: delta },\n });\n }\n break;\n }\n\n case 'message_end':\n state.lastTextLength = 0;\n break;\n\n case 'tool_start':\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'tool_call',\n toolCallId: event.toolCallId,\n title: event.toolName,\n kind: mapToolKind(event.toolName),\n status: 'in_progress',\n rawInput: JSON.stringify(event.args),\n });\n break;\n\n case 'tool_end':\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'tool_call_update',\n toolCallId: event.toolCallId,\n status: event.isError ? 'failed' : 'completed',\n rawOutput: typeof event.result === 'string' ? event.result : JSON.stringify(event.result),\n });\n break;\n\n case 'tool_approval_required':\n void handleToolApproval(state, connection, session, event).catch(err => {\n process.stderr.write(`[acp] handleToolApproval error: ${err}\\n`);\n });\n break;\n\n case 'tool_suspended':\n void handleToolSuspended(state, connection, session, event).catch(err => {\n process.stderr.write(`[acp] handleToolSuspended error: ${err}\\n`);\n });\n break;\n\n case 'usage_update':\n accumulateUsage(state.usage, event.usage);\n break;\n\n case 'agent_end':\n state.resolve(event.reason ?? 'complete');\n break;\n\n // Ignored in v1: om_*, subagent_*, workspace_*, task_updated, etc.\n default:\n break;\n }\n}\n\nfunction sendUpdate(connection: AgentSideConnection, sessionId: string, update: SessionNotification['update']): void {\n connection.sessionUpdate({ sessionId, update }).catch(err => {\n process.stderr.write(`[acp] sessionUpdate error: ${err}\\n`);\n });\n}\n\nasync function handleToolApproval(\n state: PromptState,\n connection: AgentSideConnection,\n session: Session,\n event: Extract<AgentControllerEvent, { type: 'tool_approval_required' }>,\n): Promise<void> {\n // Auto-approve if --dangerous-auto-approve flag is set\n if (autoApprove) {\n session.respondToToolApproval({ decision: 'approve' });\n return;\n }\n\n const req: RequestPermissionRequest = {\n sessionId: state.sessionId,\n toolCall: {\n toolCallId: event.toolCallId,\n title: event.toolName,\n rawInput: JSON.stringify(event.args),\n },\n options: [\n { optionId: 'approve', name: 'Allow', kind: 'allow_once' },\n { optionId: 'reject', name: 'Reject', kind: 'reject_once' },\n ],\n };\n\n try {\n const resp = await connection.requestPermission(req);\n if (resp.outcome.outcome === 'selected') {\n const decision = resp.outcome.optionId === 'approve' ? 'approve' : 'decline';\n session.respondToToolApproval({ decision });\n } else {\n session.respondToToolApproval({ decision: 'decline' });\n }\n } catch (err) {\n process.stderr.write(`[acp] requestPermission error: ${err}\\n`);\n session.respondToToolApproval({ decision: 'decline' });\n }\n}\n\nasync function handleToolSuspended(\n state: PromptState,\n connection: AgentSideConnection,\n session: Session,\n event: Extract<AgentControllerEvent, { type: 'tool_suspended' }>,\n): Promise<void> {\n const { toolCallId, toolName, args, suspendPayload } = event;\n\n // Auto-resolve certain suspensions (mirrors headless.ts autoResolve)\n if (toolName === 'request_access' || (suspendPayload as any)?.kind === 'sandbox_access_request') {\n void session.respondToToolSuspension({ toolCallId, resumeData: 'Yes' });\n return;\n }\n\n if (toolName === 'submit_plan') {\n // Request permission for plan approval\n const req: RequestPermissionRequest = {\n sessionId: state.sessionId,\n toolCall: {\n toolCallId,\n title: toolName,\n rawInput: JSON.stringify(args),\n },\n options: [\n { optionId: 'approve', name: 'Approve Plan', kind: 'allow_once' },\n { optionId: 'reject', name: 'Reject Plan', kind: 'reject_once' },\n ],\n };\n\n try {\n const resp = await connection.requestPermission(req);\n const action =\n resp.outcome.outcome === 'selected' && resp.outcome.optionId === 'approve' ? 'approved' : 'rejected';\n void session.respondToToolSuspension({ toolCallId, resumeData: { action } });\n } catch {\n void session.respondToToolSuspension({ toolCallId, resumeData: { action: 'rejected' } });\n }\n return;\n }\n\n // For ask_user and other suspensions, auto-resolve\n void session.respondToToolSuspension({\n toolCallId,\n resumeData: 'Proceed with your best judgment. Do not ask further questions.',\n });\n}\n\nfunction accumulateUsage(target: TokenUsage, usage: TokenUsage): void {\n target.promptTokens += usage.promptTokens;\n target.completionTokens += usage.completionTokens;\n target.totalTokens += usage.totalTokens;\n if (usage.reasoningTokens) target.reasoningTokens = (target.reasoningTokens ?? 0) + usage.reasoningTokens;\n if (usage.cachedInputTokens) target.cachedInputTokens = (target.cachedInputTokens ?? 0) + usage.cachedInputTokens;\n if (usage.cacheCreationInputTokens) {\n target.cacheCreationInputTokens = (target.cacheCreationInputTokens ?? 0) + usage.cacheCreationInputTokens;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/acp/event-mapper.ts"],"sourcesContent":["import type { SessionNotification, RequestPermissionRequest, AgentSideConnection } from '@agentclientprotocol/sdk';\nimport type { AgentControllerEvent, MastraDBMessage, Session, TokenUsage } from '@mastra/core/agent-controller';\nimport { mastraDBMessageToSignal } from '@mastra/core/signals';\n\n/** Concatenate the text of all `text` parts on a DB-native assistant message. */\nfunction getMessageText(message: MastraDBMessage): string {\n const content = message.content;\n if (typeof content === 'string' || !content?.parts) return '';\n return content.parts\n .filter((part): part is Extract<(typeof content.parts)[number], { type: 'text' }> => part.type === 'text')\n .map(part => part.text)\n .join('');\n}\n\nfunction getSignalText(message: MastraDBMessage): string {\n const contents = mastraDBMessageToSignal(message).contents;\n if (typeof contents === 'string') return contents;\n if (!Array.isArray(contents)) return '';\n return contents\n .filter((part): part is Extract<(typeof contents)[number], { type: 'text' }> => part.type === 'text')\n .map(part => part.text)\n .join('\\n');\n}\n\nlet autoApprove = false;\n\n/**\n * Enable or disable automatic tool approval (set via --dangerous-auto-approve CLI flag).\n */\nexport function setAutoApprove(value: boolean): void {\n autoApprove = value;\n}\n\n/**\n * Map a mastracode tool name to an ACP ToolKind.\n */\nfunction mapToolKind(\n toolName: string,\n): 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'other' {\n const name = toolName.toLowerCase();\n if (name.includes('edit') || name.includes('write') || name.includes('replace') || name.includes('patch'))\n return 'edit';\n if (name.includes('read') || name.includes('view') || name.includes('list') || name.includes('find')) return 'read';\n if (name.includes('delete') || name.includes('remove')) return 'delete';\n if (name.includes('search') || name.includes('grep') || name.includes('query')) return 'search';\n if (name.includes('execute') || name.includes('run') || name.includes('command') || name.includes('shell'))\n return 'execute';\n if (\n name.includes('fetch') ||\n name.includes('curl') ||\n name.includes('http') ||\n name.includes('browse') ||\n name.includes('navigate')\n )\n return 'fetch';\n if (name.includes('think') || name.includes('reason')) return 'think';\n return 'other';\n}\n\n/**\n * Accumulated state for an active prompt turn.\n */\nexport interface PromptState {\n sessionId: string;\n lastTextLength: number;\n usage: TokenUsage;\n resolve: (reason: 'complete' | 'aborted' | 'error' | 'suspended') => void;\n}\n\n/**\n * Translate an AgentControllerEvent into an ACP SessionNotification and send it\n * via the provided connection. Returns null for events that don't produce\n * a session update.\n */\nexport function handleAgentControllerEvent(\n event: AgentControllerEvent,\n state: PromptState | null,\n connection: AgentSideConnection,\n session: Session,\n): void {\n if (!state) return;\n\n switch (event.type) {\n case 'agent_start':\n state.lastTextLength = 0;\n break;\n\n case 'message_start': {\n if (event.message.role !== 'signal') break;\n const text = getSignalText(event.message);\n if (text) {\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text },\n });\n }\n break;\n }\n\n case 'message_update': {\n if (event.message.role !== 'assistant') break;\n const fullText = getMessageText(event.message);\n if (fullText.length > state.lastTextLength) {\n const delta = fullText.slice(state.lastTextLength);\n state.lastTextLength = fullText.length;\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: delta },\n });\n }\n break;\n }\n\n case 'message_end':\n if (event.message.role === 'assistant') state.lastTextLength = 0;\n break;\n\n case 'tool_start':\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'tool_call',\n toolCallId: event.toolCallId,\n title: event.toolName,\n kind: mapToolKind(event.toolName),\n status: 'in_progress',\n rawInput: JSON.stringify(event.args),\n });\n break;\n\n case 'tool_end':\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'tool_call_update',\n toolCallId: event.toolCallId,\n status: event.isError ? 'failed' : 'completed',\n rawOutput: typeof event.result === 'string' ? event.result : JSON.stringify(event.result),\n });\n break;\n\n case 'tool_approval_required':\n void handleToolApproval(state, connection, session, event).catch(err => {\n process.stderr.write(`[acp] handleToolApproval error: ${err}\\n`);\n });\n break;\n\n case 'tool_suspended':\n void handleToolSuspended(state, connection, session, event).catch(err => {\n process.stderr.write(`[acp] handleToolSuspended error: ${err}\\n`);\n });\n break;\n\n case 'usage_update':\n accumulateUsage(state.usage, event.usage);\n break;\n\n case 'agent_end':\n state.resolve(event.reason ?? 'complete');\n break;\n\n // Ignored in v1: om_*, subagent_*, workspace_*, task_updated, etc.\n default:\n break;\n }\n}\n\nfunction sendUpdate(connection: AgentSideConnection, sessionId: string, update: SessionNotification['update']): void {\n connection.sessionUpdate({ sessionId, update }).catch(err => {\n process.stderr.write(`[acp] sessionUpdate error: ${err}\\n`);\n });\n}\n\nasync function handleToolApproval(\n state: PromptState,\n connection: AgentSideConnection,\n session: Session,\n event: Extract<AgentControllerEvent, { type: 'tool_approval_required' }>,\n): Promise<void> {\n // Auto-approve if --dangerous-auto-approve flag is set\n if (autoApprove) {\n session.respondToToolApproval({ decision: 'approve' });\n return;\n }\n\n const req: RequestPermissionRequest = {\n sessionId: state.sessionId,\n toolCall: {\n toolCallId: event.toolCallId,\n title: event.toolName,\n rawInput: JSON.stringify(event.args),\n },\n options: [\n { optionId: 'approve', name: 'Allow', kind: 'allow_once' },\n { optionId: 'reject', name: 'Reject', kind: 'reject_once' },\n ],\n };\n\n try {\n const resp = await connection.requestPermission(req);\n if (resp.outcome.outcome === 'selected') {\n const decision = resp.outcome.optionId === 'approve' ? 'approve' : 'decline';\n session.respondToToolApproval({ decision });\n } else {\n session.respondToToolApproval({ decision: 'decline' });\n }\n } catch (err) {\n process.stderr.write(`[acp] requestPermission error: ${err}\\n`);\n session.respondToToolApproval({ decision: 'decline' });\n }\n}\n\nasync function handleToolSuspended(\n state: PromptState,\n connection: AgentSideConnection,\n session: Session,\n event: Extract<AgentControllerEvent, { type: 'tool_suspended' }>,\n): Promise<void> {\n const { toolCallId, toolName, args, suspendPayload } = event;\n\n // Auto-resolve certain suspensions (mirrors headless.ts autoResolve)\n if (toolName === 'request_access' || (suspendPayload as any)?.kind === 'sandbox_access_request') {\n void session.respondToToolSuspension({ toolCallId, resumeData: 'Yes' });\n return;\n }\n\n if (toolName === 'submit_plan') {\n // Request permission for plan approval\n const req: RequestPermissionRequest = {\n sessionId: state.sessionId,\n toolCall: {\n toolCallId,\n title: toolName,\n rawInput: JSON.stringify(args),\n },\n options: [\n { optionId: 'approve', name: 'Approve Plan', kind: 'allow_once' },\n { optionId: 'reject', name: 'Reject Plan', kind: 'reject_once' },\n ],\n };\n\n try {\n const resp = await connection.requestPermission(req);\n const action =\n resp.outcome.outcome === 'selected' && resp.outcome.optionId === 'approve' ? 'approved' : 'rejected';\n void session.respondToToolSuspension({ toolCallId, resumeData: { action } });\n } catch {\n void session.respondToToolSuspension({ toolCallId, resumeData: { action: 'rejected' } });\n }\n return;\n }\n\n // For ask_user and other suspensions, auto-resolve\n void session.respondToToolSuspension({\n toolCallId,\n resumeData: 'Proceed with your best judgment. Do not ask further questions.',\n });\n}\n\nfunction accumulateUsage(target: TokenUsage, usage: TokenUsage): void {\n target.promptTokens += usage.promptTokens;\n target.completionTokens += usage.completionTokens;\n target.totalTokens += usage.totalTokens;\n if (usage.reasoningTokens) target.reasoningTokens = (target.reasoningTokens ?? 0) + usage.reasoningTokens;\n if (usage.cachedInputTokens) target.cachedInputTokens = (target.cachedInputTokens ?? 0) + usage.cachedInputTokens;\n if (usage.cacheCreationInputTokens) {\n target.cacheCreationInputTokens = (target.cacheCreationInputTokens ?? 0) + usage.cacheCreationInputTokens;\n }\n}\n"],"mappings":"AAEA,SAAS,+BAA+B;AAGxC,SAAS,eAAe,SAAkC;AACxD,QAAM,UAAU,QAAQ;AACxB,MAAI,OAAO,YAAY,YAAY,CAAC,SAAS,MAAO,QAAO;AAC3D,SAAO,QAAQ,MACZ,OAAO,CAAC,SAA4E,KAAK,SAAS,MAAM,EACxG,IAAI,UAAQ,KAAK,IAAI,EACrB,KAAK,EAAE;AACZ;AAEA,SAAS,cAAc,SAAkC;AACvD,QAAM,WAAW,wBAAwB,OAAO,EAAE;AAClD,MAAI,OAAO,aAAa,SAAU,QAAO;AACzC,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO;AACrC,SAAO,SACJ,OAAO,CAAC,SAAuE,KAAK,SAAS,MAAM,EACnG,IAAI,UAAQ,KAAK,IAAI,EACrB,KAAK,IAAI;AACd;AAEA,IAAI,cAAc;AAKX,SAAS,eAAe,OAAsB;AACnD,gBAAc;AAChB;AAKA,SAAS,YACP,UAC0F;AAC1F,QAAM,OAAO,SAAS,YAAY;AAClC,MAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,OAAO;AACtG,WAAO;AACT,MAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,MAAM,EAAG,QAAO;AAC7G,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,QAAQ,EAAG,QAAO;AAC/D,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,OAAO,EAAG,QAAO;AACvF,MAAI,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,OAAO;AACvG,WAAO;AACT,MACE,KAAK,SAAS,OAAO,KACrB,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,QAAQ,KACtB,KAAK,SAAS,UAAU;AAExB,WAAO;AACT,MAAI,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,QAAQ,EAAG,QAAO;AAC9D,SAAO;AACT;AAiBO,SAAS,2BACd,OACA,OACA,YACA,SACM;AACN,MAAI,CAAC,MAAO;AAEZ,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,YAAM,iBAAiB;AACvB;AAAA,IAEF,KAAK,iBAAiB;AACpB,UAAI,MAAM,QAAQ,SAAS,SAAU;AACrC,YAAM,OAAO,cAAc,MAAM,OAAO;AACxC,UAAI,MAAM;AACR,mBAAW,YAAY,MAAM,WAAW;AAAA,UACtC,eAAe;AAAA,UACf,SAAS,EAAE,MAAM,QAAQ,KAAK;AAAA,QAChC,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IAEA,KAAK,kBAAkB;AACrB,UAAI,MAAM,QAAQ,SAAS,YAAa;AACxC,YAAM,WAAW,eAAe,MAAM,OAAO;AAC7C,UAAI,SAAS,SAAS,MAAM,gBAAgB;AAC1C,cAAM,QAAQ,SAAS,MAAM,MAAM,cAAc;AACjD,cAAM,iBAAiB,SAAS;AAChC,mBAAW,YAAY,MAAM,WAAW;AAAA,UACtC,eAAe;AAAA,UACf,SAAS,EAAE,MAAM,QAAQ,MAAM,MAAM;AAAA,QACvC,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IAEA,KAAK;AACH,UAAI,MAAM,QAAQ,SAAS,YAAa,OAAM,iBAAiB;AAC/D;AAAA,IAEF,KAAK;AACH,iBAAW,YAAY,MAAM,WAAW;AAAA,QACtC,eAAe;AAAA,QACf,YAAY,MAAM;AAAA,QAClB,OAAO,MAAM;AAAA,QACb,MAAM,YAAY,MAAM,QAAQ;AAAA,QAChC,QAAQ;AAAA,QACR,UAAU,KAAK,UAAU,MAAM,IAAI;AAAA,MACrC,CAAC;AACD;AAAA,IAEF,KAAK;AACH,iBAAW,YAAY,MAAM,WAAW;AAAA,QACtC,eAAe;AAAA,QACf,YAAY,MAAM;AAAA,QAClB,QAAQ,MAAM,UAAU,WAAW;AAAA,QACnC,WAAW,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS,KAAK,UAAU,MAAM,MAAM;AAAA,MAC1F,CAAC;AACD;AAAA,IAEF,KAAK;AACH,WAAK,mBAAmB,OAAO,YAAY,SAAS,KAAK,EAAE,MAAM,SAAO;AACtE,gBAAQ,OAAO,MAAM,mCAAmC,GAAG;AAAA,CAAI;AAAA,MACjE,CAAC;AACD;AAAA,IAEF,KAAK;AACH,WAAK,oBAAoB,OAAO,YAAY,SAAS,KAAK,EAAE,MAAM,SAAO;AACvE,gBAAQ,OAAO,MAAM,oCAAoC,GAAG;AAAA,CAAI;AAAA,MAClE,CAAC;AACD;AAAA,IAEF,KAAK;AACH,sBAAgB,MAAM,OAAO,MAAM,KAAK;AACxC;AAAA,IAEF,KAAK;AACH,YAAM,QAAQ,MAAM,UAAU,UAAU;AACxC;AAAA;AAAA,IAGF;AACE;AAAA,EACJ;AACF;AAEA,SAAS,WAAW,YAAiC,WAAmB,QAA6C;AACnH,aAAW,cAAc,EAAE,WAAW,OAAO,CAAC,EAAE,MAAM,SAAO;AAC3D,YAAQ,OAAO,MAAM,8BAA8B,GAAG;AAAA,CAAI;AAAA,EAC5D,CAAC;AACH;AAEA,eAAe,mBACb,OACA,YACA,SACA,OACe;AAEf,MAAI,aAAa;AACf,YAAQ,sBAAsB,EAAE,UAAU,UAAU,CAAC;AACrD;AAAA,EACF;AAEA,QAAM,MAAgC;AAAA,IACpC,WAAW,MAAM;AAAA,IACjB,UAAU;AAAA,MACR,YAAY,MAAM;AAAA,MAClB,OAAO,MAAM;AAAA,MACb,UAAU,KAAK,UAAU,MAAM,IAAI;AAAA,IACrC;AAAA,IACA,SAAS;AAAA,MACP,EAAE,UAAU,WAAW,MAAM,SAAS,MAAM,aAAa;AAAA,MACzD,EAAE,UAAU,UAAU,MAAM,UAAU,MAAM,cAAc;AAAA,IAC5D;AAAA,EACF;AAEA,MAAI;AACF,UAAM,OAAO,MAAM,WAAW,kBAAkB,GAAG;AACnD,QAAI,KAAK,QAAQ,YAAY,YAAY;AACvC,YAAM,WAAW,KAAK,QAAQ,aAAa,YAAY,YAAY;AACnE,cAAQ,sBAAsB,EAAE,SAAS,CAAC;AAAA,IAC5C,OAAO;AACL,cAAQ,sBAAsB,EAAE,UAAU,UAAU,CAAC;AAAA,IACvD;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,OAAO,MAAM,kCAAkC,GAAG;AAAA,CAAI;AAC9D,YAAQ,sBAAsB,EAAE,UAAU,UAAU,CAAC;AAAA,EACvD;AACF;AAEA,eAAe,oBACb,OACA,YACA,SACA,OACe;AACf,QAAM,EAAE,YAAY,UAAU,MAAM,eAAe,IAAI;AAGvD,MAAI,aAAa,oBAAqB,gBAAwB,SAAS,0BAA0B;AAC/F,SAAK,QAAQ,wBAAwB,EAAE,YAAY,YAAY,MAAM,CAAC;AACtE;AAAA,EACF;AAEA,MAAI,aAAa,eAAe;AAE9B,UAAM,MAAgC;AAAA,MACpC,WAAW,MAAM;AAAA,MACjB,UAAU;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,UAAU,KAAK,UAAU,IAAI;AAAA,MAC/B;AAAA,MACA,SAAS;AAAA,QACP,EAAE,UAAU,WAAW,MAAM,gBAAgB,MAAM,aAAa;AAAA,QAChE,EAAE,UAAU,UAAU,MAAM,eAAe,MAAM,cAAc;AAAA,MACjE;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAO,MAAM,WAAW,kBAAkB,GAAG;AACnD,YAAM,SACJ,KAAK,QAAQ,YAAY,cAAc,KAAK,QAAQ,aAAa,YAAY,aAAa;AAC5F,WAAK,QAAQ,wBAAwB,EAAE,YAAY,YAAY,EAAE,OAAO,EAAE,CAAC;AAAA,IAC7E,QAAQ;AACN,WAAK,QAAQ,wBAAwB,EAAE,YAAY,YAAY,EAAE,QAAQ,WAAW,EAAE,CAAC;AAAA,IACzF;AACA;AAAA,EACF;AAGA,OAAK,QAAQ,wBAAwB;AAAA,IACnC;AAAA,IACA,YAAY;AAAA,EACd,CAAC;AACH;AAEA,SAAS,gBAAgB,QAAoB,OAAyB;AACpE,SAAO,gBAAgB,MAAM;AAC7B,SAAO,oBAAoB,MAAM;AACjC,SAAO,eAAe,MAAM;AAC5B,MAAI,MAAM,gBAAiB,QAAO,mBAAmB,OAAO,mBAAmB,KAAK,MAAM;AAC1F,MAAI,MAAM,kBAAmB,QAAO,qBAAqB,OAAO,qBAAqB,KAAK,MAAM;AAChG,MAAI,MAAM,0BAA0B;AAClC,WAAO,4BAA4B,OAAO,4BAA4B,KAAK,MAAM;AAAA,EACnF;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/headless/format.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,gBAAgB,GAAG,eAAe,CAkDjG;AAOD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMhF;AAED,uFAAuF;AACvF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAc5D"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/headless/format.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAsC,MAAM,+BAA+B,CAAC;AAE9G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAUD,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,gBAAgB,GAAG,eAAe,CA4CjG;AAOD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMhF;AAED,uFAAuF;AACvF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAc5D"}
@@ -1,6 +1,9 @@
1
1
  function truncate(s, max) {
2
2
  return s.length > max ? s.slice(0, max) + "..." : s;
3
3
  }
4
+ function messageText(message) {
5
+ return message.content.parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
6
+ }
4
7
  function createHumanFormatState() {
5
8
  return { lastTextLength: 0 };
6
9
  }
@@ -10,7 +13,7 @@ function formatHuman(event, state) {
10
13
  state.lastTextLength = 0;
11
14
  return {};
12
15
  case "message_update": {
13
- const fullText = event.message.content.filter((c) => c.type === "text").map((p) => p.text).join("");
16
+ const fullText = messageText(event.message);
14
17
  if (fullText.length > state.lastTextLength) {
15
18
  const delta = fullText.slice(state.lastTextLength);
16
19
  state.lastTextLength = fullText.length;
@@ -20,7 +23,7 @@ function formatHuman(event, state) {
20
23
  }
21
24
  case "message_end": {
22
25
  if (event.message.role !== "assistant") return {};
23
- const fullText = event.message.content.filter((c) => c.type === "text").map((p) => p.text).join("");
26
+ const fullText = messageText(event.message);
24
27
  const delta = fullText.length > state.lastTextLength ? fullText.slice(state.lastTextLength) : "";
25
28
  state.lastTextLength = 0;
26
29
  return { stdout: delta + "\n" };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/headless/format.ts"],"sourcesContent":["/**\n * Output formatters for headless runs. All functions here are pure — they take\n * an event (or a final result) and return strings / plain objects. They never\n * touch `process.*`; the CLI adapter owns the sinks.\n */\nimport type { AgentControllerEvent } from '@mastra/core/agent-controller';\n\nimport type { RunMCResult } from './types.js';\n\n/** Truncate a string to `max` characters, appending \"...\" if truncated. */\nexport function truncate(s: string, max: number): string {\n return s.length > max ? s.slice(0, max) + '...' : s;\n}\n\n/** Mutable per-stream cursor used by {@link formatHuman} to stream assistant text. */\nexport interface HumanFormatState {\n lastTextLength: number;\n}\n\nexport function createHumanFormatState(): HumanFormatState {\n return { lastTextLength: 0 };\n}\n\n/** A chunk of formatted output destined for stdout and/or stderr. */\nexport interface FormattedOutput {\n stdout?: string;\n stderr?: string;\n}\n\n/**\n * Human-readable streaming formatter (the historical default). Assistant text\n * streams to stdout; tool/subagent/shell/error activity goes to stderr. The\n * `state` cursor is mutated so repeated `message_update` events only emit the\n * newly-appended text.\n */\nexport function formatHuman(event: AgentControllerEvent, state: HumanFormatState): FormattedOutput {\n switch (event.type) {\n case 'agent_start':\n state.lastTextLength = 0;\n return {};\n case 'message_update': {\n const fullText = event.message.content\n .filter((c): c is { type: 'text'; text: string } => c.type === 'text')\n .map(p => p.text)\n .join('');\n if (fullText.length > state.lastTextLength) {\n const delta = fullText.slice(state.lastTextLength);\n state.lastTextLength = fullText.length;\n return { stdout: delta };\n }\n return {};\n }\n case 'message_end': {\n // Only assistant messages produce stdout. The controller also emits\n // message_end for the echoed user prompt (and system messages); emitting\n // those here would duplicate the prompt to stdout and corrupt the stream.\n if (event.message.role !== 'assistant') return {};\n // Emit any assistant text the message_update stream didn't already cover\n // (e.g. a run that only delivered the final text on message_end), then\n // terminate the line.\n const fullText = event.message.content\n .filter((c): c is { type: 'text'; text: string } => c.type === 'text')\n .map(p => p.text)\n .join('');\n const delta = fullText.length > state.lastTextLength ? fullText.slice(state.lastTextLength) : '';\n state.lastTextLength = 0;\n return { stdout: delta + '\\n' };\n }\n case 'tool_start':\n return { stderr: `[tool] ${event.toolName}\\n` };\n case 'tool_end':\n return event.isError ? { stderr: `[tool error] ${truncate(String(event.result), 200)}\\n` } : {};\n case 'shell_output':\n return { stderr: event.output };\n case 'subagent_start':\n return {\n stderr: `[subagent:${event.forked ? 'forked:' : ''}${event.agentType}] ${truncate(event.task, 100)}\\n`,\n };\n case 'subagent_end':\n return event.isError ? { stderr: `[subagent error] ${truncate(event.result, 200)}\\n` } : {};\n case 'error':\n return { stderr: `[error] ${event.error.message}\\n` };\n default:\n return {};\n }\n}\n\n/** Convert an `Error` instance into a JSON-serializable plain object. */\nfunction serializeError(err: Error): { name: string; message: string; stack?: string } {\n return { name: err.name, message: err.message, stack: err.stack };\n}\n\n/**\n * JSONL (stream-json) formatter — returns a plain object to be `JSON.stringify`'d\n * as one line per event by the sink. `Error` instances are normalized so their\n * `name`/`message`/`stack` survive serialization (`JSON.stringify` turns a raw\n * `Error` into `{}`).\n */\nexport function formatJsonl(event: AgentControllerEvent): Record<string, unknown> {\n const out: Record<string, unknown> = { ...event };\n if ('error' in event && event.error instanceof Error) {\n out.error = serializeError(event.error);\n }\n return out;\n}\n\n/** Render the final result for `--output text`: assistant text, newline-terminated. */\nexport function renderTextResult(result: RunMCResult): string {\n return result.text.endsWith('\\n') ? result.text : result.text + '\\n';\n}\n\n/** Render the final result for `--output json`: one JSON object. */\nexport function renderJsonResult(result: RunMCResult): string {\n return (\n JSON.stringify({\n status: result.status,\n text: result.text,\n finishReason: result.finishReason,\n usage: result.usage,\n toolCalls: result.toolCalls,\n toolResults: result.toolResults,\n error: result.error,\n threadId: result.threadId,\n exitCode: result.exitCode,\n }) + '\\n'\n );\n}\n"],"mappings":"AAUO,SAAS,SAAS,GAAW,KAAqB;AACvD,SAAO,EAAE,SAAS,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,QAAQ;AACpD;AAOO,SAAS,yBAA2C;AACzD,SAAO,EAAE,gBAAgB,EAAE;AAC7B;AAcO,SAAS,YAAY,OAA6B,OAA0C;AACjG,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,YAAM,iBAAiB;AACvB,aAAO,CAAC;AAAA,IACV,KAAK,kBAAkB;AACrB,YAAM,WAAW,MAAM,QAAQ,QAC5B,OAAO,CAAC,MAA2C,EAAE,SAAS,MAAM,EACpE,IAAI,OAAK,EAAE,IAAI,EACf,KAAK,EAAE;AACV,UAAI,SAAS,SAAS,MAAM,gBAAgB;AAC1C,cAAM,QAAQ,SAAS,MAAM,MAAM,cAAc;AACjD,cAAM,iBAAiB,SAAS;AAChC,eAAO,EAAE,QAAQ,MAAM;AAAA,MACzB;AACA,aAAO,CAAC;AAAA,IACV;AAAA,IACA,KAAK,eAAe;AAIlB,UAAI,MAAM,QAAQ,SAAS,YAAa,QAAO,CAAC;AAIhD,YAAM,WAAW,MAAM,QAAQ,QAC5B,OAAO,CAAC,MAA2C,EAAE,SAAS,MAAM,EACpE,IAAI,OAAK,EAAE,IAAI,EACf,KAAK,EAAE;AACV,YAAM,QAAQ,SAAS,SAAS,MAAM,iBAAiB,SAAS,MAAM,MAAM,cAAc,IAAI;AAC9F,YAAM,iBAAiB;AACvB,aAAO,EAAE,QAAQ,QAAQ,KAAK;AAAA,IAChC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,QAAQ,UAAU,MAAM,QAAQ;AAAA,EAAK;AAAA,IAChD,KAAK;AACH,aAAO,MAAM,UAAU,EAAE,QAAQ,gBAAgB,SAAS,OAAO,MAAM,MAAM,GAAG,GAAG,CAAC;AAAA,EAAK,IAAI,CAAC;AAAA,IAChG,KAAK;AACH,aAAO,EAAE,QAAQ,MAAM,OAAO;AAAA,IAChC,KAAK;AACH,aAAO;AAAA,QACL,QAAQ,aAAa,MAAM,SAAS,YAAY,EAAE,GAAG,MAAM,SAAS,KAAK,SAAS,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA,MACpG;AAAA,IACF,KAAK;AACH,aAAO,MAAM,UAAU,EAAE,QAAQ,oBAAoB,SAAS,MAAM,QAAQ,GAAG,CAAC;AAAA,EAAK,IAAI,CAAC;AAAA,IAC5F,KAAK;AACH,aAAO,EAAE,QAAQ,WAAW,MAAM,MAAM,OAAO;AAAA,EAAK;AAAA,IACtD;AACE,aAAO,CAAC;AAAA,EACZ;AACF;AAGA,SAAS,eAAe,KAA+D;AACrF,SAAO,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,SAAS,OAAO,IAAI,MAAM;AAClE;AAQO,SAAS,YAAY,OAAsD;AAChF,QAAM,MAA+B,EAAE,GAAG,MAAM;AAChD,MAAI,WAAW,SAAS,MAAM,iBAAiB,OAAO;AACpD,QAAI,QAAQ,eAAe,MAAM,KAAK;AAAA,EACxC;AACA,SAAO;AACT;AAGO,SAAS,iBAAiB,QAA6B;AAC5D,SAAO,OAAO,KAAK,SAAS,IAAI,IAAI,OAAO,OAAO,OAAO,OAAO;AAClE;AAGO,SAAS,iBAAiB,QAA6B;AAC5D,SACE,KAAK,UAAU;AAAA,IACb,QAAQ,OAAO;AAAA,IACf,MAAM,OAAO;AAAA,IACb,cAAc,OAAO;AAAA,IACrB,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,aAAa,OAAO;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB,UAAU,OAAO;AAAA,EACnB,CAAC,IAAI;AAET;","names":[]}
1
+ {"version":3,"sources":["../../src/headless/format.ts"],"sourcesContent":["/**\n * Output formatters for headless runs. All functions here are pure — they take\n * an event (or a final result) and return strings / plain objects. They never\n * touch `process.*`; the CLI adapter owns the sinks.\n */\nimport type { AgentControllerEvent, MastraDBMessage, MastraMessagePart } from '@mastra/core/agent-controller';\n\nimport type { RunMCResult } from './types.js';\n\n/** Truncate a string to `max` characters, appending \"...\" if truncated. */\nexport function truncate(s: string, max: number): string {\n return s.length > max ? s.slice(0, max) + '...' : s;\n}\n\n/** Concatenate the text of an assistant message's nested content parts. */\nfunction messageText(message: MastraDBMessage): string {\n return message.content.parts\n .filter((p): p is MastraMessagePart & { text: string } => p.type === 'text' && typeof p.text === 'string')\n .map(p => p.text)\n .join('');\n}\n\n/** Mutable per-stream cursor used by {@link formatHuman} to stream assistant text. */\nexport interface HumanFormatState {\n lastTextLength: number;\n}\n\nexport function createHumanFormatState(): HumanFormatState {\n return { lastTextLength: 0 };\n}\n\n/** A chunk of formatted output destined for stdout and/or stderr. */\nexport interface FormattedOutput {\n stdout?: string;\n stderr?: string;\n}\n\n/**\n * Human-readable streaming formatter (the historical default). Assistant text\n * streams to stdout; tool/subagent/shell/error activity goes to stderr. The\n * `state` cursor is mutated so repeated `message_update` events only emit the\n * newly-appended text.\n */\nexport function formatHuman(event: AgentControllerEvent, state: HumanFormatState): FormattedOutput {\n switch (event.type) {\n case 'agent_start':\n state.lastTextLength = 0;\n return {};\n case 'message_update': {\n const fullText = messageText(event.message);\n if (fullText.length > state.lastTextLength) {\n const delta = fullText.slice(state.lastTextLength);\n state.lastTextLength = fullText.length;\n return { stdout: delta };\n }\n return {};\n }\n case 'message_end': {\n // Only assistant messages produce stdout. The controller also emits\n // message_end for the echoed user prompt (and system messages); emitting\n // those here would duplicate the prompt to stdout and corrupt the stream.\n if (event.message.role !== 'assistant') return {};\n // Emit any assistant text the message_update stream didn't already cover\n // (e.g. a run that only delivered the final text on message_end), then\n // terminate the line.\n const fullText = messageText(event.message);\n const delta = fullText.length > state.lastTextLength ? fullText.slice(state.lastTextLength) : '';\n state.lastTextLength = 0;\n return { stdout: delta + '\\n' };\n }\n case 'tool_start':\n return { stderr: `[tool] ${event.toolName}\\n` };\n case 'tool_end':\n return event.isError ? { stderr: `[tool error] ${truncate(String(event.result), 200)}\\n` } : {};\n case 'shell_output':\n return { stderr: event.output };\n case 'subagent_start':\n return {\n stderr: `[subagent:${event.forked ? 'forked:' : ''}${event.agentType}] ${truncate(event.task, 100)}\\n`,\n };\n case 'subagent_end':\n return event.isError ? { stderr: `[subagent error] ${truncate(event.result, 200)}\\n` } : {};\n case 'error':\n return { stderr: `[error] ${event.error.message}\\n` };\n default:\n return {};\n }\n}\n\n/** Convert an `Error` instance into a JSON-serializable plain object. */\nfunction serializeError(err: Error): { name: string; message: string; stack?: string } {\n return { name: err.name, message: err.message, stack: err.stack };\n}\n\n/**\n * JSONL (stream-json) formatter — returns a plain object to be `JSON.stringify`'d\n * as one line per event by the sink. `Error` instances are normalized so their\n * `name`/`message`/`stack` survive serialization (`JSON.stringify` turns a raw\n * `Error` into `{}`).\n */\nexport function formatJsonl(event: AgentControllerEvent): Record<string, unknown> {\n const out: Record<string, unknown> = { ...event };\n if ('error' in event && event.error instanceof Error) {\n out.error = serializeError(event.error);\n }\n return out;\n}\n\n/** Render the final result for `--output text`: assistant text, newline-terminated. */\nexport function renderTextResult(result: RunMCResult): string {\n return result.text.endsWith('\\n') ? result.text : result.text + '\\n';\n}\n\n/** Render the final result for `--output json`: one JSON object. */\nexport function renderJsonResult(result: RunMCResult): string {\n return (\n JSON.stringify({\n status: result.status,\n text: result.text,\n finishReason: result.finishReason,\n usage: result.usage,\n toolCalls: result.toolCalls,\n toolResults: result.toolResults,\n error: result.error,\n threadId: result.threadId,\n exitCode: result.exitCode,\n }) + '\\n'\n );\n}\n"],"mappings":"AAUO,SAAS,SAAS,GAAW,KAAqB;AACvD,SAAO,EAAE,SAAS,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,QAAQ;AACpD;AAGA,SAAS,YAAY,SAAkC;AACrD,SAAO,QAAQ,QAAQ,MACpB,OAAO,CAAC,MAAiD,EAAE,SAAS,UAAU,OAAO,EAAE,SAAS,QAAQ,EACxG,IAAI,OAAK,EAAE,IAAI,EACf,KAAK,EAAE;AACZ;AAOO,SAAS,yBAA2C;AACzD,SAAO,EAAE,gBAAgB,EAAE;AAC7B;AAcO,SAAS,YAAY,OAA6B,OAA0C;AACjG,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,YAAM,iBAAiB;AACvB,aAAO,CAAC;AAAA,IACV,KAAK,kBAAkB;AACrB,YAAM,WAAW,YAAY,MAAM,OAAO;AAC1C,UAAI,SAAS,SAAS,MAAM,gBAAgB;AAC1C,cAAM,QAAQ,SAAS,MAAM,MAAM,cAAc;AACjD,cAAM,iBAAiB,SAAS;AAChC,eAAO,EAAE,QAAQ,MAAM;AAAA,MACzB;AACA,aAAO,CAAC;AAAA,IACV;AAAA,IACA,KAAK,eAAe;AAIlB,UAAI,MAAM,QAAQ,SAAS,YAAa,QAAO,CAAC;AAIhD,YAAM,WAAW,YAAY,MAAM,OAAO;AAC1C,YAAM,QAAQ,SAAS,SAAS,MAAM,iBAAiB,SAAS,MAAM,MAAM,cAAc,IAAI;AAC9F,YAAM,iBAAiB;AACvB,aAAO,EAAE,QAAQ,QAAQ,KAAK;AAAA,IAChC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,QAAQ,UAAU,MAAM,QAAQ;AAAA,EAAK;AAAA,IAChD,KAAK;AACH,aAAO,MAAM,UAAU,EAAE,QAAQ,gBAAgB,SAAS,OAAO,MAAM,MAAM,GAAG,GAAG,CAAC;AAAA,EAAK,IAAI,CAAC;AAAA,IAChG,KAAK;AACH,aAAO,EAAE,QAAQ,MAAM,OAAO;AAAA,IAChC,KAAK;AACH,aAAO;AAAA,QACL,QAAQ,aAAa,MAAM,SAAS,YAAY,EAAE,GAAG,MAAM,SAAS,KAAK,SAAS,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA,MACpG;AAAA,IACF,KAAK;AACH,aAAO,MAAM,UAAU,EAAE,QAAQ,oBAAoB,SAAS,MAAM,QAAQ,GAAG,CAAC;AAAA,EAAK,IAAI,CAAC;AAAA,IAC5F,KAAK;AACH,aAAO,EAAE,QAAQ,WAAW,MAAM,MAAM,OAAO;AAAA,EAAK;AAAA,IACtD;AACE,aAAO,CAAC;AAAA,EACZ;AACF;AAGA,SAAS,eAAe,KAA+D;AACrF,SAAO,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,SAAS,OAAO,IAAI,MAAM;AAClE;AAQO,SAAS,YAAY,OAAsD;AAChF,QAAM,MAA+B,EAAE,GAAG,MAAM;AAChD,MAAI,WAAW,SAAS,MAAM,iBAAiB,OAAO;AACpD,QAAI,QAAQ,eAAe,MAAM,KAAK;AAAA,EACxC;AACA,SAAO;AACT;AAGO,SAAS,iBAAiB,QAA6B;AAC5D,SAAO,OAAO,KAAK,SAAS,IAAI,IAAI,OAAO,OAAO,OAAO,OAAO;AAClE;AAGO,SAAS,iBAAiB,QAA6B;AAC5D,SACE,KAAK,UAAU;AAAA,IACb,QAAQ,OAAO;AAAA,IACf,MAAM,OAAO;AAAA,IACb,cAAc,OAAO;AAAA,IACrB,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,aAAa,OAAO;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB,UAAU,OAAO;AAAA,EACnB,CAAC,IAAI;AAET;","names":[]}
@@ -2,7 +2,7 @@ import { GoalManager } from "../goal-manager.js";
2
2
  import { createGoalReminderSignal } from "../goal-signal.js";
3
3
  import { autoApprovePolicy } from "./policy.js";
4
4
  function extractAssistantText(message) {
5
- return message.content.filter((c) => c.type === "text").map((c) => c.text).join("");
5
+ return message.content.parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
6
6
  }
7
7
  function exitCodeForStatus(status) {
8
8
  switch (status) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/headless/run-mc.ts"],"sourcesContent":["/**\n * Core programmatic runner for MastraCode headless runs.\n *\n * `runMC` is a pure async runner: it takes an already-built `controller` +\n * `session` (from `createMastraCode(...)`), resolves run config, subscribes to\n * the session, applies a {@link ResolutionPolicy} for approvals/suspensions,\n * sends the prompt, and aggregates events into a {@link RunMCResult}.\n *\n * It never touches `process.*` and never calls `process.exit`. The returned\n * {@link MCRun} is async-iterable over controller events and also resolves to a\n * final result via `result`.\n */\nimport type { AgentControllerEvent, AgentControllerMessage, Session } from '@mastra/core/agent-controller';\n\nimport { GoalManager } from '../goal-manager.js';\nimport { createGoalReminderSignal } from '../goal-signal.js';\n\nimport { autoApprovePolicy } from './policy.js';\nimport type { MCRun, ResolutionPolicy, RunMCOptions, RunMCResult, RunMCStatus } from './types.js';\n\nfunction extractAssistantText(message: AgentControllerMessage): string {\n return message.content\n .filter((c): c is { type: 'text'; text: string } => c.type === 'text')\n .map(c => c.text)\n .join('');\n}\n\nfunction exitCodeForStatus(status: RunMCStatus): number {\n switch (status) {\n case 'completed':\n case 'done':\n return 0;\n case 'timeout':\n return 2;\n default:\n return 1;\n }\n}\n\ninterface MutableResult {\n text: string;\n finishReason?: string;\n usage?: RunMCResult['usage'];\n toolCalls: RunMCResult['toolCalls'];\n toolResults: RunMCResult['toolResults'];\n error?: RunMCResult['error'];\n threadId?: string;\n}\n\nfunction aggregate(event: AgentControllerEvent, acc: MutableResult): void {\n switch (event.type) {\n case 'message_end':\n if (event.message.role === 'assistant') {\n acc.text += extractAssistantText(event.message);\n }\n break;\n case 'tool_start':\n acc.toolCalls.push({ id: event.toolCallId, name: event.toolName, args: event.args });\n break;\n case 'tool_end': {\n const matching = acc.toolCalls.find(c => c.id === event.toolCallId);\n acc.toolResults.push({\n id: event.toolCallId,\n name: matching?.name ?? '',\n result: event.result,\n isError: event.isError,\n });\n break;\n }\n case 'usage_update':\n acc.usage = {\n inputTokens: event.usage.promptTokens,\n outputTokens: event.usage.completionTokens,\n totalTokens: event.usage.totalTokens,\n };\n break;\n case 'error':\n acc.error = {\n name: event.error.name,\n message: event.error.message,\n stack: event.error.stack,\n };\n break;\n }\n}\n\n/** Resolve a thread by its exact ID. Titles are not unique, so we don't match on them. */\nasync function resolveThread<TState extends Record<string, unknown>>(\n session: Session<TState>,\n threadId: string,\n): Promise<{ threadId: string } | { error: string }> {\n const threads = await session.thread.list();\n\n const byId = threads.find(t => t.id === threadId);\n if (byId) return { threadId: byId.id };\n\n return { error: `No thread found with ID \"${threadId}\"` };\n}\n\n/**\n * A simple back-pressured async queue. Events are pushed in; consumers pull via\n * the async iterator. `close()` ends iteration after draining buffered events.\n *\n * Buffered events are bounded by `maxBuffer`: if a consumer never iterates (the\n * result-only path, `await run.result` without `for await (...)`) — or simply\n * falls far behind — the oldest buffered events are dropped instead of growing\n * without limit. The aggregated {@link RunMCResult} is built independently of\n * this queue, so dropping buffered events never affects the final result.\n */\nclass EventQueue<T> {\n #buffer: T[] = [];\n #resolvers: Array<(r: IteratorResult<T>) => void> = [];\n #closed = false;\n readonly #maxBuffer: number;\n\n constructor(maxBuffer = 10_000) {\n this.#maxBuffer = maxBuffer;\n }\n\n push(value: T): void {\n if (this.#closed) return;\n const resolve = this.#resolvers.shift();\n if (resolve) {\n resolve({ value, done: false });\n return;\n }\n this.#buffer.push(value);\n if (this.#buffer.length > this.#maxBuffer) {\n // Bound memory: drop the oldest event once over the cap.\n this.#buffer.shift();\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n for (const resolve of this.#resolvers.splice(0)) {\n resolve({ value: undefined as unknown as T, done: true });\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: (): Promise<IteratorResult<T>> => {\n if (this.#buffer.length > 0) {\n return Promise.resolve({ value: this.#buffer.shift()!, done: false });\n }\n if (this.#closed) {\n return Promise.resolve({ value: undefined as unknown as T, done: true });\n }\n return new Promise<IteratorResult<T>>(resolve => this.#resolvers.push(resolve));\n },\n };\n }\n}\n\n/**\n * Run a headless MastraCode turn. Returns an {@link MCRun} handle that is\n * async-iterable over controller events and resolves to a {@link RunMCResult}.\n */\nexport function runMC<TState extends Record<string, unknown>>(options: RunMCOptions<TState>): MCRun {\n const { controller, session } = options;\n const goal = options.goal;\n const policy: ResolutionPolicy = options.policy ?? autoApprovePolicy;\n\n const queue = new EventQueue<AgentControllerEvent>();\n const acc: MutableResult = { text: '', toolCalls: [], toolResults: [] };\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n let aborted = false;\n let maxTurnsExceeded = false;\n let assistantTurns = 0;\n let settled = false;\n let unsubscribe: (() => void) | undefined;\n let resolveResult!: (r: RunMCResult) => void;\n\n const result = new Promise<RunMCResult>(resolve => {\n resolveResult = resolve;\n });\n\n function finish(status: RunMCStatus, data: Partial<RunMCResult> = {}): void {\n if (settled) return;\n settled = true;\n if (timeoutId) clearTimeout(timeoutId);\n unsubscribe?.();\n queue.close();\n resolveResult({\n status,\n text: acc.text,\n finishReason: acc.finishReason,\n usage: acc.usage,\n toolCalls: acc.toolCalls,\n toolResults: acc.toolResults,\n threadId: acc.threadId ?? session.thread.getId() ?? undefined,\n error: acc.error,\n exitCode: exitCodeForStatus(status),\n ...data,\n });\n }\n\n function fail(message: string, name = 'Error'): void {\n if (!acc.error) acc.error = { name, message };\n finish('error');\n }\n\n function abort(): void {\n if (settled) return;\n aborted = true;\n session.abort();\n }\n\n if (options.signal) {\n if (options.signal.aborted) {\n // Defer so the caller can attach iteration / result handlers first.\n queueMicrotask(() => abort());\n } else {\n options.signal.addEventListener('abort', () => abort(), { once: true });\n }\n }\n\n function armTimeout(): void {\n if (!options.timeoutMs || settled) return;\n if (timeoutId) clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n timedOut = true;\n session.abort();\n if (goal) finish('timeout');\n }, options.timeoutMs);\n }\n\n // Kick off the run asynchronously so the MCRun handle is returned synchronously.\n void (async () => {\n armTimeout();\n\n // --- Config resolution (model / mode / thinking) ---\n try {\n if (options.model) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === options.model);\n if (!match) return fail(`Unknown model: \"${options.model}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${options.model}\" has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId: options.model });\n } else if (options.mode) {\n const modelId = options.modeDefaults?.[options.mode];\n if (modelId) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === modelId);\n if (!match) return fail(`Unknown model \"${modelId}\" configured for mode \"${options.mode}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${modelId}\" (mode: ${options.mode}) has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId });\n }\n // No configured model for mode → fall through to default (no failure).\n }\n\n if (options.thinkingLevel) {\n await session.state.set({ thinkingLevel: options.thinkingLevel } as unknown as Partial<TState>);\n }\n } catch (err) {\n return fail(`Failed to resolve run config: ${(err as Error).message}`);\n }\n\n // --- Subscribe ---\n unsubscribe = session.subscribe(event => {\n if (settled) return;\n if (goal) armTimeout();\n\n if (event.type === 'tool_approval_required') {\n let decision: 'approve' | 'deny';\n try {\n decision = policy.onToolApproval(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n session.respondToToolApproval({\n decision: decision === 'approve' ? 'approve' : 'decline',\n toolCallId: event.toolCallId,\n });\n queue.push(event);\n return;\n }\n\n if (event.type === 'tool_suspended') {\n let outcome: ReturnType<ResolutionPolicy['onSuspension']>;\n try {\n outcome = policy.onSuspension(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n if ('abort' in outcome) {\n queue.push(event);\n abort();\n return;\n }\n void session.respondToToolSuspension({ toolCallId: event.toolCallId, resumeData: outcome.resumeData });\n queue.push(event);\n return;\n }\n\n aggregate(event, acc);\n queue.push(event);\n\n if (event.type === 'error' && goal) {\n finish('error');\n return;\n }\n\n // Count agentic turns (one assistant response = one turn). When the cap is\n // reached, abort the run; agent_end then resolves as 'max_turns'.\n if (event.type === 'message_end' && event.message.role === 'assistant' && options.maxTurns !== undefined) {\n assistantTurns += 1;\n if (assistantTurns >= options.maxTurns && !maxTurnsExceeded) {\n maxTurnsExceeded = true;\n abort();\n }\n }\n\n if (event.type === 'goal_evaluation' && goal && !event.payload.pending) {\n if (event.payload.status === 'done' || event.payload.status === 'paused') {\n finish(event.payload.status, {\n objective: goal.objective,\n goalEvent: event,\n reason: event.payload.reason ?? event.payload.results?.[0]?.reason,\n iterations: event.payload.iteration,\n maxRuns: event.payload.maxRuns,\n });\n }\n return;\n }\n\n if (event.type === 'agent_end') {\n acc.finishReason = event.reason;\n // Goal evaluations can arrive after the agent stream ends, so goal runs\n // remain active until a terminal goal_evaluation is emitted.\n if (goal) return;\n if (timedOut) {\n finish('timeout');\n } else if (event.reason === 'error') {\n finish('error');\n } else if (maxTurnsExceeded && event.reason !== 'complete') {\n // The cap forced an abort while the agent still had work to do.\n finish('max_turns');\n } else if ((event.reason === 'aborted' || aborted) && !maxTurnsExceeded) {\n finish('aborted');\n } else {\n finish('completed');\n }\n }\n });\n\n // --- Resource id ---\n try {\n if (options.resourceId) {\n await controller.setResourceId(session, { resourceId: options.resourceId });\n }\n } catch (err) {\n return fail(`Failed to set resource id: ${(err as Error).message}`);\n }\n\n // --- Thread selection ---\n try {\n const thread = options.thread;\n if (thread?.id) {\n const resolved = await resolveThread(session, thread.id);\n if ('error' in resolved) return fail(resolved.error);\n await session.thread.switch({ threadId: resolved.threadId });\n } else if (thread?.continueLatest) {\n const threads = await session.thread.list();\n if (threads.length > 0) {\n const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());\n await session.thread.switch({ threadId: sorted[0]!.id });\n }\n }\n } catch (err) {\n return fail(`Failed to select thread: ${(err as Error).message}`);\n }\n\n // --- Clone ---\n if (options.thread?.clone) {\n try {\n await session.thread.clone();\n } catch (err) {\n return fail(`Failed to clone thread: ${(err as Error).message}`);\n }\n }\n\n // --- Title ---\n if (options.title) {\n try {\n await session.thread.rename({ title: options.title });\n } catch (err) {\n return fail(`Failed to set thread title: ${(err as Error).message}`);\n }\n }\n\n // --- Start ---\n try {\n if (goal) {\n const threadId = session.thread.getId();\n if (!threadId || !(await session.thread.getById({ threadId }))) {\n await session.thread.create();\n }\n\n const goalManager = goal.goalManager ?? new GoalManager();\n const state = {\n controller,\n session,\n goalManager,\n pendingNewThread: false,\n planStartedGoalId: undefined,\n } as any;\n const objective = await goalManager.setGoal(state, goal.objective, goal.judgeModelId, goal.maxRuns);\n if (!objective) return fail('Failed to set goal.');\n\n const agent = controller.getCurrentAgent(session);\n const persisted = await agent.getObjective({ threadId: session.thread.getId()! });\n if (!persisted || persisted.id !== objective.id) {\n return fail('Failed to persist goal objective before sending goal signal.');\n }\n\n await goalManager.saveToThread(state);\n if (!settled) await session.sendSignal(createGoalReminderSignal(objective)).accepted;\n } else {\n if (!options.prompt) return fail('A prompt or goal is required.');\n await session.sendMessage({ content: options.prompt });\n }\n } catch (err) {\n return fail(`Failed to start run: ${(err as Error).message}`);\n }\n })();\n\n return {\n result,\n abort,\n [Symbol.asyncIterator](): AsyncIterator<AgentControllerEvent> {\n return queue[Symbol.asyncIterator]();\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/headless/run-mc.ts"],"sourcesContent":["/**\n * Core programmatic runner for MastraCode headless runs.\n *\n * `runMC` is a pure async runner: it takes an already-built `controller` +\n * `session` (from `createMastraCode(...)`), resolves run config, subscribes to\n * the session, applies a {@link ResolutionPolicy} for approvals/suspensions,\n * sends the prompt, and aggregates events into a {@link RunMCResult}.\n *\n * It never touches `process.*` and never calls `process.exit`. The returned\n * {@link MCRun} is async-iterable over controller events and also resolves to a\n * final result via `result`.\n */\nimport type { AgentControllerEvent, MastraDBMessage, MastraMessagePart, Session } from '@mastra/core/agent-controller';\n\nimport { GoalManager } from '../goal-manager.js';\nimport { createGoalReminderSignal } from '../goal-signal.js';\n\nimport { autoApprovePolicy } from './policy.js';\nimport type { MCRun, ResolutionPolicy, RunMCOptions, RunMCResult, RunMCStatus } from './types.js';\n\nfunction extractAssistantText(message: MastraDBMessage): string {\n return message.content.parts\n .filter((p): p is MastraMessagePart & { text: string } => p.type === 'text' && typeof p.text === 'string')\n .map(p => p.text)\n .join('');\n}\n\nfunction exitCodeForStatus(status: RunMCStatus): number {\n switch (status) {\n case 'completed':\n case 'done':\n return 0;\n case 'timeout':\n return 2;\n default:\n return 1;\n }\n}\n\ninterface MutableResult {\n text: string;\n finishReason?: string;\n usage?: RunMCResult['usage'];\n toolCalls: RunMCResult['toolCalls'];\n toolResults: RunMCResult['toolResults'];\n error?: RunMCResult['error'];\n threadId?: string;\n}\n\nfunction aggregate(event: AgentControllerEvent, acc: MutableResult): void {\n switch (event.type) {\n case 'message_end':\n if (event.message.role === 'assistant') {\n acc.text += extractAssistantText(event.message);\n }\n break;\n case 'tool_start':\n acc.toolCalls.push({ id: event.toolCallId, name: event.toolName, args: event.args });\n break;\n case 'tool_end': {\n const matching = acc.toolCalls.find(c => c.id === event.toolCallId);\n acc.toolResults.push({\n id: event.toolCallId,\n name: matching?.name ?? '',\n result: event.result,\n isError: event.isError,\n });\n break;\n }\n case 'usage_update':\n acc.usage = {\n inputTokens: event.usage.promptTokens,\n outputTokens: event.usage.completionTokens,\n totalTokens: event.usage.totalTokens,\n };\n break;\n case 'error':\n acc.error = {\n name: event.error.name,\n message: event.error.message,\n stack: event.error.stack,\n };\n break;\n }\n}\n\n/** Resolve a thread by its exact ID. Titles are not unique, so we don't match on them. */\nasync function resolveThread<TState extends Record<string, unknown>>(\n session: Session<TState>,\n threadId: string,\n): Promise<{ threadId: string } | { error: string }> {\n const threads = await session.thread.list();\n\n const byId = threads.find(t => t.id === threadId);\n if (byId) return { threadId: byId.id };\n\n return { error: `No thread found with ID \"${threadId}\"` };\n}\n\n/**\n * A simple back-pressured async queue. Events are pushed in; consumers pull via\n * the async iterator. `close()` ends iteration after draining buffered events.\n *\n * Buffered events are bounded by `maxBuffer`: if a consumer never iterates (the\n * result-only path, `await run.result` without `for await (...)`) — or simply\n * falls far behind — the oldest buffered events are dropped instead of growing\n * without limit. The aggregated {@link RunMCResult} is built independently of\n * this queue, so dropping buffered events never affects the final result.\n */\nclass EventQueue<T> {\n #buffer: T[] = [];\n #resolvers: Array<(r: IteratorResult<T>) => void> = [];\n #closed = false;\n readonly #maxBuffer: number;\n\n constructor(maxBuffer = 10_000) {\n this.#maxBuffer = maxBuffer;\n }\n\n push(value: T): void {\n if (this.#closed) return;\n const resolve = this.#resolvers.shift();\n if (resolve) {\n resolve({ value, done: false });\n return;\n }\n this.#buffer.push(value);\n if (this.#buffer.length > this.#maxBuffer) {\n // Bound memory: drop the oldest event once over the cap.\n this.#buffer.shift();\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n for (const resolve of this.#resolvers.splice(0)) {\n resolve({ value: undefined as unknown as T, done: true });\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: (): Promise<IteratorResult<T>> => {\n if (this.#buffer.length > 0) {\n return Promise.resolve({ value: this.#buffer.shift()!, done: false });\n }\n if (this.#closed) {\n return Promise.resolve({ value: undefined as unknown as T, done: true });\n }\n return new Promise<IteratorResult<T>>(resolve => this.#resolvers.push(resolve));\n },\n };\n }\n}\n\n/**\n * Run a headless MastraCode turn. Returns an {@link MCRun} handle that is\n * async-iterable over controller events and resolves to a {@link RunMCResult}.\n */\nexport function runMC<TState extends Record<string, unknown>>(options: RunMCOptions<TState>): MCRun {\n const { controller, session } = options;\n const goal = options.goal;\n const policy: ResolutionPolicy = options.policy ?? autoApprovePolicy;\n\n const queue = new EventQueue<AgentControllerEvent>();\n const acc: MutableResult = { text: '', toolCalls: [], toolResults: [] };\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n let aborted = false;\n let maxTurnsExceeded = false;\n let assistantTurns = 0;\n let settled = false;\n let unsubscribe: (() => void) | undefined;\n let resolveResult!: (r: RunMCResult) => void;\n\n const result = new Promise<RunMCResult>(resolve => {\n resolveResult = resolve;\n });\n\n function finish(status: RunMCStatus, data: Partial<RunMCResult> = {}): void {\n if (settled) return;\n settled = true;\n if (timeoutId) clearTimeout(timeoutId);\n unsubscribe?.();\n queue.close();\n resolveResult({\n status,\n text: acc.text,\n finishReason: acc.finishReason,\n usage: acc.usage,\n toolCalls: acc.toolCalls,\n toolResults: acc.toolResults,\n threadId: acc.threadId ?? session.thread.getId() ?? undefined,\n error: acc.error,\n exitCode: exitCodeForStatus(status),\n ...data,\n });\n }\n\n function fail(message: string, name = 'Error'): void {\n if (!acc.error) acc.error = { name, message };\n finish('error');\n }\n\n function abort(): void {\n if (settled) return;\n aborted = true;\n session.abort();\n }\n\n if (options.signal) {\n if (options.signal.aborted) {\n // Defer so the caller can attach iteration / result handlers first.\n queueMicrotask(() => abort());\n } else {\n options.signal.addEventListener('abort', () => abort(), { once: true });\n }\n }\n\n function armTimeout(): void {\n if (!options.timeoutMs || settled) return;\n if (timeoutId) clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n timedOut = true;\n session.abort();\n if (goal) finish('timeout');\n }, options.timeoutMs);\n }\n\n // Kick off the run asynchronously so the MCRun handle is returned synchronously.\n void (async () => {\n armTimeout();\n\n // --- Config resolution (model / mode / thinking) ---\n try {\n if (options.model) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === options.model);\n if (!match) return fail(`Unknown model: \"${options.model}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${options.model}\" has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId: options.model });\n } else if (options.mode) {\n const modelId = options.modeDefaults?.[options.mode];\n if (modelId) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === modelId);\n if (!match) return fail(`Unknown model \"${modelId}\" configured for mode \"${options.mode}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${modelId}\" (mode: ${options.mode}) has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId });\n }\n // No configured model for mode → fall through to default (no failure).\n }\n\n if (options.thinkingLevel) {\n await session.state.set({ thinkingLevel: options.thinkingLevel } as unknown as Partial<TState>);\n }\n } catch (err) {\n return fail(`Failed to resolve run config: ${(err as Error).message}`);\n }\n\n // --- Subscribe ---\n unsubscribe = session.subscribe(event => {\n if (settled) return;\n if (goal) armTimeout();\n\n if (event.type === 'tool_approval_required') {\n let decision: 'approve' | 'deny';\n try {\n decision = policy.onToolApproval(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n session.respondToToolApproval({\n decision: decision === 'approve' ? 'approve' : 'decline',\n toolCallId: event.toolCallId,\n });\n queue.push(event);\n return;\n }\n\n if (event.type === 'tool_suspended') {\n let outcome: ReturnType<ResolutionPolicy['onSuspension']>;\n try {\n outcome = policy.onSuspension(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n if ('abort' in outcome) {\n queue.push(event);\n abort();\n return;\n }\n void session.respondToToolSuspension({ toolCallId: event.toolCallId, resumeData: outcome.resumeData });\n queue.push(event);\n return;\n }\n\n aggregate(event, acc);\n queue.push(event);\n\n if (event.type === 'error' && goal) {\n finish('error');\n return;\n }\n\n // Count agentic turns (one assistant response = one turn). When the cap is\n // reached, abort the run; agent_end then resolves as 'max_turns'.\n if (event.type === 'message_end' && event.message.role === 'assistant' && options.maxTurns !== undefined) {\n assistantTurns += 1;\n if (assistantTurns >= options.maxTurns && !maxTurnsExceeded) {\n maxTurnsExceeded = true;\n abort();\n }\n }\n\n if (event.type === 'goal_evaluation' && goal && !event.payload.pending) {\n if (event.payload.status === 'done' || event.payload.status === 'paused') {\n finish(event.payload.status, {\n objective: goal.objective,\n goalEvent: event,\n reason: event.payload.reason ?? event.payload.results?.[0]?.reason,\n iterations: event.payload.iteration,\n maxRuns: event.payload.maxRuns,\n });\n }\n return;\n }\n\n if (event.type === 'agent_end') {\n acc.finishReason = event.reason;\n // Goal evaluations can arrive after the agent stream ends, so goal runs\n // remain active until a terminal goal_evaluation is emitted.\n if (goal) return;\n if (timedOut) {\n finish('timeout');\n } else if (event.reason === 'error') {\n finish('error');\n } else if (maxTurnsExceeded && event.reason !== 'complete') {\n // The cap forced an abort while the agent still had work to do.\n finish('max_turns');\n } else if ((event.reason === 'aborted' || aborted) && !maxTurnsExceeded) {\n finish('aborted');\n } else {\n finish('completed');\n }\n }\n });\n\n // --- Resource id ---\n try {\n if (options.resourceId) {\n await controller.setResourceId(session, { resourceId: options.resourceId });\n }\n } catch (err) {\n return fail(`Failed to set resource id: ${(err as Error).message}`);\n }\n\n // --- Thread selection ---\n try {\n const thread = options.thread;\n if (thread?.id) {\n const resolved = await resolveThread(session, thread.id);\n if ('error' in resolved) return fail(resolved.error);\n await session.thread.switch({ threadId: resolved.threadId });\n } else if (thread?.continueLatest) {\n const threads = await session.thread.list();\n if (threads.length > 0) {\n const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());\n await session.thread.switch({ threadId: sorted[0]!.id });\n }\n }\n } catch (err) {\n return fail(`Failed to select thread: ${(err as Error).message}`);\n }\n\n // --- Clone ---\n if (options.thread?.clone) {\n try {\n await session.thread.clone();\n } catch (err) {\n return fail(`Failed to clone thread: ${(err as Error).message}`);\n }\n }\n\n // --- Title ---\n if (options.title) {\n try {\n await session.thread.rename({ title: options.title });\n } catch (err) {\n return fail(`Failed to set thread title: ${(err as Error).message}`);\n }\n }\n\n // --- Start ---\n try {\n if (goal) {\n const threadId = session.thread.getId();\n if (!threadId || !(await session.thread.getById({ threadId }))) {\n await session.thread.create();\n }\n\n const goalManager = goal.goalManager ?? new GoalManager();\n const state = {\n controller,\n session,\n goalManager,\n pendingNewThread: false,\n planStartedGoalId: undefined,\n } as any;\n const objective = await goalManager.setGoal(state, goal.objective, goal.judgeModelId, goal.maxRuns);\n if (!objective) return fail('Failed to set goal.');\n\n const agent = controller.getCurrentAgent(session);\n const persisted = await agent.getObjective({ threadId: session.thread.getId()! });\n if (!persisted || persisted.id !== objective.id) {\n return fail('Failed to persist goal objective before sending goal signal.');\n }\n\n await goalManager.saveToThread(state);\n if (!settled) await session.sendSignal(createGoalReminderSignal(objective)).accepted;\n } else {\n if (!options.prompt) return fail('A prompt or goal is required.');\n await session.sendMessage({ content: options.prompt });\n }\n } catch (err) {\n return fail(`Failed to start run: ${(err as Error).message}`);\n }\n })();\n\n return {\n result,\n abort,\n [Symbol.asyncIterator](): AsyncIterator<AgentControllerEvent> {\n return queue[Symbol.asyncIterator]();\n },\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/code-sdk",
3
- "version": "0.2.0-alpha.2",
3
+ "version": "0.2.0-alpha.3",
4
4
  "description": "Mastra Code SDK: the agent core behind Mastra Code (everything except the TUI) — build your own UIs and surfaces on top of it",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -57,15 +57,15 @@
57
57
  "yaml": "^2.7.1",
58
58
  "zod": "^4.3.6",
59
59
  "@mastra/agent-browser": "0.4.1",
60
- "@mastra/core": "1.52.0-alpha.2",
61
60
  "@mastra/duckdb": "1.5.1",
62
- "@mastra/github-signals": "0.2.2",
63
- "@mastra/libsql": "1.16.0",
64
- "@mastra/memory": "1.23.1-alpha.0",
65
- "@mastra/observability": "1.16.1",
66
61
  "@mastra/fastembed": "1.2.0",
67
- "@mastra/pg": "1.16.0",
62
+ "@mastra/core": "1.52.0-alpha.3",
63
+ "@mastra/libsql": "1.16.0",
64
+ "@mastra/github-signals": "0.2.2",
68
65
  "@mastra/mcp": "1.15.0-alpha.0",
66
+ "@mastra/observability": "1.16.1",
67
+ "@mastra/memory": "1.23.1-alpha.0",
68
+ "@mastra/pg": "1.16.1-alpha.0",
69
69
  "@mastra/schema-compat": "1.3.4",
70
70
  "@mastra/stagehand": "0.3.1-alpha.0",
71
71
  "@mastra/tavily": "1.1.0"
@@ -79,8 +79,8 @@
79
79
  "typescript": "^6.0.3",
80
80
  "typescript-eslint": "^8.57.0",
81
81
  "vitest": "4.1.10",
82
- "@internal/types-builder": "0.0.89",
83
- "@internal/lint": "0.0.114"
82
+ "@internal/lint": "0.0.114",
83
+ "@internal/types-builder": "0.0.89"
84
84
  },
85
85
  "engines": {
86
86
  "node": ">=22.19.0"