@evalops/maestro 0.10.37 → 0.10.39

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.
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-mode.d.ts","sourceRoot":"","sources":["../../src/cli/rpc-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AA2B/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAqC5D;;;;;GAKG;AACH,wBAAsB,UAAU,CAC/B,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,cAAc,GAC5B,OAAO,CAAC,IAAI,CAAC,CA8If"}
1
+ {"version":3,"file":"rpc-mode.d.ts","sourceRoot":"","sources":["../../src/cli/rpc-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AA2B/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAqC5D;;;;;GAKG;AACH,wBAAsB,UAAU,CAC/B,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,cAAc,GAC5B,OAAO,CAAC,IAAI,CAAC,CAqKf"}
@@ -63,8 +63,11 @@ export async function runRpcMode(agent, sessionManager) {
63
63
  });
64
64
  // Process incoming RPC commands line by line
65
65
  rl.on("line", async (line) => {
66
+ let requestId;
67
+ const withRequestId = (response) => requestId ? { id: requestId, ...response } : response;
66
68
  try {
67
69
  const input = JSON.parse(line);
70
+ requestId = typeof input.id === "string" ? input.id : undefined;
68
71
  if (input.type === "prompt" && input.message) {
69
72
  await runUserPromptWithRecovery({
70
73
  agent,
@@ -84,13 +87,13 @@ export async function runRpcMode(agent, sessionManager) {
84
87
  agent.abort();
85
88
  }
86
89
  else if (input.type === "get_messages") {
87
- console.log(JSON.stringify({
90
+ console.log(JSON.stringify(withRequestId({
88
91
  type: "messages",
89
92
  messages: agent.state.messages,
90
- }));
93
+ })));
91
94
  }
92
95
  else if (input.type === "get_state") {
93
- console.log(JSON.stringify({
96
+ console.log(JSON.stringify(withRequestId({
94
97
  type: "state",
95
98
  state: {
96
99
  model: agent.state.model,
@@ -101,7 +104,7 @@ export async function runRpcMode(agent, sessionManager) {
101
104
  session: agent.state.session,
102
105
  queuedMessageCount: agent.getQueuedMessageCount(),
103
106
  },
104
- }));
107
+ })));
105
108
  }
106
109
  else if (input.type === "continue") {
107
110
  await runWithPromptRecovery({
@@ -135,14 +138,14 @@ export async function runRpcMode(agent, sessionManager) {
135
138
  },
136
139
  });
137
140
  if (!result.success) {
138
- console.log(JSON.stringify({
141
+ console.log(JSON.stringify(withRequestId({
139
142
  type: "error",
140
143
  error: result.error,
141
- }));
144
+ })));
142
145
  return;
143
146
  }
144
147
  // Emit compaction event
145
- const compactionEvent = {
148
+ const compactionEvent = withRequestId({
146
149
  type: "compaction",
147
150
  summary: result.summary ?? `Compacted ${result.compactedCount} messages`,
148
151
  firstKeptEntryIndex: result.firstKeptEntryIndex ?? 0,
@@ -150,13 +153,20 @@ export async function runRpcMode(agent, sessionManager) {
150
153
  auto: false,
151
154
  customInstructions,
152
155
  timestamp: new Date().toISOString(),
153
- };
156
+ });
154
157
  console.log(JSON.stringify(compactionEvent));
155
158
  }
159
+ else {
160
+ const commandType = typeof input.type === "string" && input.type ? input.type : "unknown";
161
+ console.log(JSON.stringify(withRequestId({
162
+ type: "error",
163
+ error: `Unknown RPC command: ${commandType}`,
164
+ })));
165
+ }
156
166
  }
157
167
  catch (error) {
158
168
  const message = error instanceof Error ? error.message : String(error);
159
- console.log(JSON.stringify({ type: "error", error: message }));
169
+ console.log(JSON.stringify(withRequestId({ type: "error", error: message })));
160
170
  }
161
171
  });
162
172
  // Keep process alive indefinitely - exits when stdin closes
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-mode.js","sourceRoot":"","sources":["../../src/cli/rpc-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RPC Mode - JSON-over-stdio protocol for programmatic agent control.\n *\n * Moved from main.ts. Provides a line-based JSON protocol for IDE integrations,\n * language servers, and other tools that embed Maestro functionality.\n *\n * ## Protocol\n *\n * **Input (stdin)**: JSON objects, one per line\n * ```json\n * {\"type\": \"prompt\", \"message\": \"Hello\"}\n * {\"type\": \"abort\"}\n * {\"type\": \"compact\", \"customInstructions\": \"Focus on...\"}\n * ```\n *\n * **Output (stdout)**: Agent events as JSON objects, one per line\n *\n * @module cli/rpc-mode\n */\n\nimport type { Agent } from \"../agent/agent.js\";\nimport { buildCompactionHookContext } from \"../agent/compaction-hooks.js\";\nimport {\n\tcollectBackgroundTaskMessagesForCompaction,\n\tcollectMcpMessagesForCompaction,\n\tcollectPlanMessagesForCompaction,\n} from \"../agent/compaction-restoration.js\";\nimport { performCompaction } from \"../agent/compaction.js\";\nimport {\n\tbuildCompactionEvent,\n\trunWithPromptRecovery,\n} from \"../agent/prompt-recovery.js\";\nimport type {\n\tAgentEvent,\n\tAppMessage,\n\tAssistantMessage,\n} from \"../agent/types.js\";\nimport {\n\tcollectPersistedSessionStartHookMessages,\n\trunUserPromptWithRecovery,\n} from \"../agent/user-prompt-runtime.js\";\nimport {\n\tcreateRenderableMessage,\n\trenderMessageToPlainText,\n} from \"../conversation/render-model.js\";\nimport { mcpManager } from \"../mcp/index.js\";\nimport { withMcpPostKeepMessages } from \"../mcp/prompt-recovery.js\";\nimport type { SessionManager } from \"../session/manager.js\";\n\nasync function collectRpcPostKeepMessages(\n\tsessionManager: SessionManager,\n\tcwd: string,\n\tpreservedMessages: AppMessage[],\n): Promise<AppMessage[]> {\n\tconst [\n\t\tplanMessages,\n\t\tbackgroundTaskMessages,\n\t\tmcpMessages,\n\t\tsessionStartMessages,\n\t] = await Promise.all([\n\t\tPromise.resolve(collectPlanMessagesForCompaction(preservedMessages)),\n\t\tPromise.resolve(\n\t\t\tcollectBackgroundTaskMessagesForCompaction(preservedMessages),\n\t\t),\n\t\tPromise.resolve(\n\t\t\tcollectMcpMessagesForCompaction(\n\t\t\t\tpreservedMessages,\n\t\t\t\tmcpManager.getStatus().servers,\n\t\t\t),\n\t\t),\n\t\tcollectPersistedSessionStartHookMessages({\n\t\t\tsessionManager,\n\t\t\tcwd,\n\t\t\tsource: \"compact\",\n\t\t}),\n\t]);\n\treturn [\n\t\t...planMessages,\n\t\t...backgroundTaskMessages,\n\t\t...mcpMessages,\n\t\t...sessionStartMessages,\n\t];\n}\n\n/**\n * Run the CLI in RPC mode.\n *\n * The process runs indefinitely until stdin closes or it receives\n * a termination signal.\n */\nexport async function runRpcMode(\n\tagent: Agent,\n\tsessionManager: SessionManager,\n): Promise<void> {\n\t// Subscribe to all events and emit as JSON for client consumption\n\tagent.subscribe((event) => {\n\t\tconsole.log(JSON.stringify(event));\n\t});\n\n\t// Set up JSON-over-stdin readline interface\n\tconst readline = await import(\"node:readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t\tterminal: false,\n\t});\n\n\t// Process incoming RPC commands line by line\n\trl.on(\"line\", async (line: string) => {\n\t\ttry {\n\t\t\tconst input = JSON.parse(line);\n\n\t\t\tif (input.type === \"prompt\" && input.message) {\n\t\t\t\tawait runUserPromptWithRecovery({\n\t\t\t\t\tagent,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\tprompt: input.message,\n\t\t\t\t\texecute: () => agent.prompt(input.message),\n\t\t\t\t\tgetPostKeepMessages: withMcpPostKeepMessages(),\n\t\t\t\t\tcallbacks: {\n\t\t\t\t\t\tonCompacted: (result) => {\n\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\tJSON.stringify(buildCompactionEvent(result, { auto: true })),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else if (input.type === \"abort\") {\n\t\t\t\tagent.abort();\n\t\t\t} else if (input.type === \"get_messages\") {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\ttype: \"messages\",\n\t\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else if (input.type === \"get_state\") {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\ttype: \"state\",\n\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\tmodel: agent.state.model,\n\t\t\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t\t\t\tisStreaming: agent.state.isStreaming,\n\t\t\t\t\t\t\terror: agent.state.error,\n\t\t\t\t\t\t\tthinkingLevel: agent.state.thinkingLevel,\n\t\t\t\t\t\t\tsession: agent.state.session,\n\t\t\t\t\t\t\tqueuedMessageCount: agent.getQueuedMessageCount(),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else if (input.type === \"continue\") {\n\t\t\t\tawait runWithPromptRecovery({\n\t\t\t\t\tagent,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\thookContext: buildCompactionHookContext(\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t),\n\t\t\t\t\texecute: () => agent.continue(input.options),\n\t\t\t\t\tgetPostKeepMessages: (preservedMessages) =>\n\t\t\t\t\t\tcollectRpcPostKeepMessages(\n\t\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t\t\tpreservedMessages,\n\t\t\t\t\t\t),\n\t\t\t\t\tcallbacks: {\n\t\t\t\t\t\tonCompacted: (result) => {\n\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\tJSON.stringify(buildCompactionEvent(result, { auto: true })),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else if (input.type === \"compact\") {\n\t\t\t\tconst customInstructions = input.customInstructions as\n\t\t\t\t\t| string\n\t\t\t\t\t| undefined;\n\n\t\t\t\tconst result = await performCompaction({\n\t\t\t\t\tagent,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tauto: false,\n\t\t\t\t\ttrigger: \"manual\",\n\t\t\t\t\thookContext: buildCompactionHookContext(\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t),\n\t\t\t\t\tgetPostKeepMessages: (preservedMessages) =>\n\t\t\t\t\t\tcollectRpcPostKeepMessages(\n\t\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t\t\tpreservedMessages,\n\t\t\t\t\t\t),\n\t\t\t\t\tcustomInstructions,\n\t\t\t\t\trenderSummaryText: (summary: AssistantMessage) => {\n\t\t\t\t\t\tconst renderable = createRenderableMessage(summary as AppMessage);\n\t\t\t\t\t\treturn renderable\n\t\t\t\t\t\t\t? renderMessageToPlainText(renderable).trim()\n\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tif (!result.success) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Emit compaction event\n\t\t\t\tconst compactionEvent: AgentEvent = {\n\t\t\t\t\ttype: \"compaction\",\n\t\t\t\t\tsummary:\n\t\t\t\t\t\tresult.summary ?? `Compacted ${result.compactedCount} messages`,\n\t\t\t\t\tfirstKeptEntryIndex: result.firstKeptEntryIndex ?? 0,\n\t\t\t\t\ttokensBefore: result.tokensBefore ?? 0,\n\t\t\t\t\tauto: false,\n\t\t\t\t\tcustomInstructions,\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t};\n\t\t\t\tconsole.log(JSON.stringify(compactionEvent));\n\t\t\t}\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.log(JSON.stringify({ type: \"error\", error: message }));\n\t\t}\n\t});\n\n\t// Keep process alive indefinitely - exits when stdin closes\n\treturn new Promise(() => {});\n}\n"]}
1
+ {"version":3,"file":"rpc-mode.js","sourceRoot":"","sources":["../../src/cli/rpc-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RPC Mode - JSON-over-stdio protocol for programmatic agent control.\n *\n * Moved from main.ts. Provides a line-based JSON protocol for IDE integrations,\n * language servers, and other tools that embed Maestro functionality.\n *\n * ## Protocol\n *\n * **Input (stdin)**: JSON objects, one per line\n * ```json\n * {\"type\": \"prompt\", \"message\": \"Hello\"}\n * {\"type\": \"abort\"}\n * {\"type\": \"compact\", \"customInstructions\": \"Focus on...\"}\n * ```\n *\n * **Output (stdout)**: Agent events as JSON objects, one per line\n *\n * @module cli/rpc-mode\n */\n\nimport type { Agent } from \"../agent/agent.js\";\nimport { buildCompactionHookContext } from \"../agent/compaction-hooks.js\";\nimport {\n\tcollectBackgroundTaskMessagesForCompaction,\n\tcollectMcpMessagesForCompaction,\n\tcollectPlanMessagesForCompaction,\n} from \"../agent/compaction-restoration.js\";\nimport { performCompaction } from \"../agent/compaction.js\";\nimport {\n\tbuildCompactionEvent,\n\trunWithPromptRecovery,\n} from \"../agent/prompt-recovery.js\";\nimport type {\n\tAgentEvent,\n\tAppMessage,\n\tAssistantMessage,\n} from \"../agent/types.js\";\nimport {\n\tcollectPersistedSessionStartHookMessages,\n\trunUserPromptWithRecovery,\n} from \"../agent/user-prompt-runtime.js\";\nimport {\n\tcreateRenderableMessage,\n\trenderMessageToPlainText,\n} from \"../conversation/render-model.js\";\nimport { mcpManager } from \"../mcp/index.js\";\nimport { withMcpPostKeepMessages } from \"../mcp/prompt-recovery.js\";\nimport type { SessionManager } from \"../session/manager.js\";\n\nasync function collectRpcPostKeepMessages(\n\tsessionManager: SessionManager,\n\tcwd: string,\n\tpreservedMessages: AppMessage[],\n): Promise<AppMessage[]> {\n\tconst [\n\t\tplanMessages,\n\t\tbackgroundTaskMessages,\n\t\tmcpMessages,\n\t\tsessionStartMessages,\n\t] = await Promise.all([\n\t\tPromise.resolve(collectPlanMessagesForCompaction(preservedMessages)),\n\t\tPromise.resolve(\n\t\t\tcollectBackgroundTaskMessagesForCompaction(preservedMessages),\n\t\t),\n\t\tPromise.resolve(\n\t\t\tcollectMcpMessagesForCompaction(\n\t\t\t\tpreservedMessages,\n\t\t\t\tmcpManager.getStatus().servers,\n\t\t\t),\n\t\t),\n\t\tcollectPersistedSessionStartHookMessages({\n\t\t\tsessionManager,\n\t\t\tcwd,\n\t\t\tsource: \"compact\",\n\t\t}),\n\t]);\n\treturn [\n\t\t...planMessages,\n\t\t...backgroundTaskMessages,\n\t\t...mcpMessages,\n\t\t...sessionStartMessages,\n\t];\n}\n\n/**\n * Run the CLI in RPC mode.\n *\n * The process runs indefinitely until stdin closes or it receives\n * a termination signal.\n */\nexport async function runRpcMode(\n\tagent: Agent,\n\tsessionManager: SessionManager,\n): Promise<void> {\n\t// Subscribe to all events and emit as JSON for client consumption\n\tagent.subscribe((event) => {\n\t\tconsole.log(JSON.stringify(event));\n\t});\n\n\t// Set up JSON-over-stdin readline interface\n\tconst readline = await import(\"node:readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t\tterminal: false,\n\t});\n\n\t// Process incoming RPC commands line by line\n\trl.on(\"line\", async (line: string) => {\n\t\tlet requestId: string | undefined;\n\t\tconst withRequestId = <T extends Record<string, unknown>>(response: T) =>\n\t\t\trequestId ? { id: requestId, ...response } : response;\n\t\ttry {\n\t\t\tconst input = JSON.parse(line);\n\t\t\trequestId = typeof input.id === \"string\" ? input.id : undefined;\n\n\t\t\tif (input.type === \"prompt\" && input.message) {\n\t\t\t\tawait runUserPromptWithRecovery({\n\t\t\t\t\tagent,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\tprompt: input.message,\n\t\t\t\t\texecute: () => agent.prompt(input.message),\n\t\t\t\t\tgetPostKeepMessages: withMcpPostKeepMessages(),\n\t\t\t\t\tcallbacks: {\n\t\t\t\t\t\tonCompacted: (result) => {\n\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\tJSON.stringify(buildCompactionEvent(result, { auto: true })),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else if (input.type === \"abort\") {\n\t\t\t\tagent.abort();\n\t\t\t} else if (input.type === \"get_messages\") {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\twithRequestId({\n\t\t\t\t\t\t\ttype: \"messages\",\n\t\t\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else if (input.type === \"get_state\") {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\twithRequestId({\n\t\t\t\t\t\t\ttype: \"state\",\n\t\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\t\tmodel: agent.state.model,\n\t\t\t\t\t\t\t\tmessages: agent.state.messages,\n\t\t\t\t\t\t\t\tisStreaming: agent.state.isStreaming,\n\t\t\t\t\t\t\t\terror: agent.state.error,\n\t\t\t\t\t\t\t\tthinkingLevel: agent.state.thinkingLevel,\n\t\t\t\t\t\t\t\tsession: agent.state.session,\n\t\t\t\t\t\t\t\tqueuedMessageCount: agent.getQueuedMessageCount(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else if (input.type === \"continue\") {\n\t\t\t\tawait runWithPromptRecovery({\n\t\t\t\t\tagent,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\thookContext: buildCompactionHookContext(\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t),\n\t\t\t\t\texecute: () => agent.continue(input.options),\n\t\t\t\t\tgetPostKeepMessages: (preservedMessages) =>\n\t\t\t\t\t\tcollectRpcPostKeepMessages(\n\t\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t\t\tpreservedMessages,\n\t\t\t\t\t\t),\n\t\t\t\t\tcallbacks: {\n\t\t\t\t\t\tonCompacted: (result) => {\n\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\tJSON.stringify(buildCompactionEvent(result, { auto: true })),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else if (input.type === \"compact\") {\n\t\t\t\tconst customInstructions = input.customInstructions as\n\t\t\t\t\t| string\n\t\t\t\t\t| undefined;\n\n\t\t\t\tconst result = await performCompaction({\n\t\t\t\t\tagent,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tauto: false,\n\t\t\t\t\ttrigger: \"manual\",\n\t\t\t\t\thookContext: buildCompactionHookContext(\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t),\n\t\t\t\t\tgetPostKeepMessages: (preservedMessages) =>\n\t\t\t\t\t\tcollectRpcPostKeepMessages(\n\t\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t\t\tpreservedMessages,\n\t\t\t\t\t\t),\n\t\t\t\t\tcustomInstructions,\n\t\t\t\t\trenderSummaryText: (summary: AssistantMessage) => {\n\t\t\t\t\t\tconst renderable = createRenderableMessage(summary as AppMessage);\n\t\t\t\t\t\treturn renderable\n\t\t\t\t\t\t\t? renderMessageToPlainText(renderable).trim()\n\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tif (!result.success) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\twithRequestId({\n\t\t\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Emit compaction event\n\t\t\t\tconst compactionEvent: AgentEvent & { id?: string } = withRequestId({\n\t\t\t\t\ttype: \"compaction\" as const,\n\t\t\t\t\tsummary:\n\t\t\t\t\t\tresult.summary ?? `Compacted ${result.compactedCount} messages`,\n\t\t\t\t\tfirstKeptEntryIndex: result.firstKeptEntryIndex ?? 0,\n\t\t\t\t\ttokensBefore: result.tokensBefore ?? 0,\n\t\t\t\t\tauto: false,\n\t\t\t\t\tcustomInstructions,\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t\tconsole.log(JSON.stringify(compactionEvent));\n\t\t\t} else {\n\t\t\t\tconst commandType =\n\t\t\t\t\ttypeof input.type === \"string\" && input.type ? input.type : \"unknown\";\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\twithRequestId({\n\t\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\t\terror: `Unknown RPC command: ${commandType}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify(withRequestId({ type: \"error\", error: message })),\n\t\t\t);\n\t\t}\n\t});\n\n\t// Keep process alive indefinitely - exits when stdin closes\n\treturn new Promise(() => {});\n}\n"]}
package/dist/cli.js CHANGED
@@ -49041,7 +49041,7 @@ var init_maestro_event_catalog = __esm2(() => {
49041
49041
  [
49042
49042
  "maestro.events.tool_call.attempted"
49043
49043
  /* ToolCallAttempted */
49044
- ]: entry("maestro.events.tool_call.attempted", "tool", "ToolCallAttempt", ["meter.maestro-tool-call-events"]),
49044
+ ]: entry("maestro.events.tool_call.attempted", "tool", "ToolCallAttempt", ["meter.maestro-tool-call-events", "release.maestro-tool-attempt-gates"]),
49045
49045
  [
49046
49046
  "maestro.events.tool_call.completed"
49047
49047
  /* ToolCallCompleted */
@@ -49162,6 +49162,7 @@ var init_maestro_event_catalog = __esm2(() => {
49162
49162
  /* SessionClosed */
49163
49163
  ],
49164
49164
  tool: [
49165
+ "maestro.events.tool_call.attempted",
49165
49166
  "maestro.events.tool_call.completed",
49166
49167
  "maestro.events.tool_call.failed"
49167
49168
  /* ToolCallFailed */
@@ -60509,80 +60510,80 @@ async function checkNetworkRestrictionsDetailed(url, network) {
60509
60510
  const parsed = new URL(url);
60510
60511
  const host = parsed.hostname.toLowerCase();
60511
60512
  const normalizedHost = host.replace(/^\[|\]$/g, "");
60512
- const resolvedIPs = [];
60513
- const isIP2 = parseIPv4(normalizedHost) !== null || parseIPv4MappedHex(normalizedHost) !== null || normalizedHost.includes(":");
60514
- if (!isIP2) {
60515
- try {
60516
- const addresses = await lookup(normalizedHost, { all: true });
60517
- resolvedIPs.push(...addresses.map(({ address }) => address));
60518
- } catch {
60519
- if (network.blockPrivateIPs || network.blockLocalhost) {
60513
+ if (network.blockedHosts?.length) {
60514
+ for (const blockedHost of network.blockedHosts) {
60515
+ const lowerBlocked = blockedHost.toLowerCase();
60516
+ if (host === lowerBlocked || host.endsWith(`.${lowerBlocked}`)) {
60520
60517
  return {
60521
60518
  allowed: false,
60522
- reason: `DNS resolution failed for "${host}" and network policy requires IP validation (blockPrivateIPs/blockLocalhost enabled). Access blocked.`,
60519
+ reason: `Host "${host}" is blocked by enterprise policy.`,
60523
60520
  host,
60524
60521
  normalizedHost,
60525
- resolvedIPs
60522
+ resolvedIPs: []
60526
60523
  };
60527
60524
  }
60528
60525
  }
60529
- } else {
60530
- resolvedIPs.push(normalizedHost);
60531
60526
  }
60532
- if (network.blockLocalhost) {
60533
- if (isLocalhostAlias(normalizedHost) || resolvedIPs.some(isLoopbackIP)) {
60527
+ if (network.allowedHosts) {
60528
+ if (network.allowedHosts.length === 0) {
60534
60529
  return {
60535
60530
  allowed: false,
60536
- reason: "Access to localhost is blocked by enterprise policy.",
60531
+ reason: `Host "${host}" is not in the allowed hosts list.`,
60537
60532
  host,
60538
60533
  normalizedHost,
60539
- resolvedIPs
60534
+ resolvedIPs: []
60540
60535
  };
60541
60536
  }
60542
- }
60543
- if (network.blockPrivateIPs) {
60544
- if (resolvedIPs.some(isPrivateIP)) {
60537
+ const isAllowed = network.allowedHosts.some((allowedHost) => {
60538
+ const lowerAllowed = allowedHost.toLowerCase();
60539
+ return host === lowerAllowed || host.endsWith(`.${lowerAllowed}`);
60540
+ });
60541
+ if (!isAllowed) {
60545
60542
  return {
60546
60543
  allowed: false,
60547
- reason: "Access to private IP addresses is blocked by enterprise policy.",
60544
+ reason: `Host "${host}" is not in the allowed hosts list.`,
60548
60545
  host,
60549
60546
  normalizedHost,
60550
- resolvedIPs
60547
+ resolvedIPs: []
60551
60548
  };
60552
60549
  }
60553
60550
  }
60554
- if (network.blockedHosts?.length) {
60555
- for (const blockedHost of network.blockedHosts) {
60556
- const lowerBlocked = blockedHost.toLowerCase();
60557
- if (host === lowerBlocked || host.endsWith(`.${lowerBlocked}`)) {
60551
+ const resolvedIPs = [];
60552
+ const isIP2 = parseIPv4(normalizedHost) !== null || parseIPv4MappedHex(normalizedHost) !== null || normalizedHost.includes(":");
60553
+ if (!isIP2) {
60554
+ try {
60555
+ const addresses = await lookup(normalizedHost, { all: true });
60556
+ resolvedIPs.push(...addresses.map(({ address }) => address));
60557
+ } catch {
60558
+ if (network.blockPrivateIPs || network.blockLocalhost) {
60558
60559
  return {
60559
60560
  allowed: false,
60560
- reason: `Host "${host}" is blocked by enterprise policy.`,
60561
+ reason: `DNS resolution failed for "${host}" and network policy requires IP validation (blockPrivateIPs/blockLocalhost enabled). Access blocked.`,
60561
60562
  host,
60562
60563
  normalizedHost,
60563
60564
  resolvedIPs
60564
60565
  };
60565
60566
  }
60566
60567
  }
60568
+ } else {
60569
+ resolvedIPs.push(normalizedHost);
60567
60570
  }
60568
- if (network.allowedHosts) {
60569
- if (network.allowedHosts.length === 0) {
60571
+ if (network.blockLocalhost) {
60572
+ if (isLocalhostAlias(normalizedHost) || resolvedIPs.some(isLoopbackIP)) {
60570
60573
  return {
60571
60574
  allowed: false,
60572
- reason: `Host "${host}" is not in the allowed hosts list.`,
60575
+ reason: "Access to localhost is blocked by enterprise policy.",
60573
60576
  host,
60574
60577
  normalizedHost,
60575
60578
  resolvedIPs
60576
60579
  };
60577
60580
  }
60578
- const isAllowed = network.allowedHosts.some((allowedHost) => {
60579
- const lowerAllowed = allowedHost.toLowerCase();
60580
- return host === lowerAllowed || host.endsWith(`.${lowerAllowed}`);
60581
- });
60582
- if (!isAllowed) {
60581
+ }
60582
+ if (network.blockPrivateIPs) {
60583
+ if (resolvedIPs.some(isPrivateIP)) {
60583
60584
  return {
60584
60585
  allowed: false,
60585
- reason: `Host "${host}" is not in the allowed hosts list.`,
60586
+ reason: "Access to private IP addresses is blocked by enterprise policy.",
60586
60587
  host,
60587
60588
  normalizedHost,
60588
60589
  resolvedIPs
@@ -158628,6 +158629,14 @@ var init_extract_document = __esm2(() => {
158628
158629
  }
158629
158630
  });
158630
158631
  });
158632
+ function toolInstallAbortError(config2) {
158633
+ return new Error(`${config2.name} installation aborted`);
158634
+ }
158635
+ function throwIfToolInstallAborted(config2, signal) {
158636
+ if (signal?.aborted) {
158637
+ throw toolInstallAbortError(config2);
158638
+ }
158639
+ }
158631
158640
  function commandExists2(cmd) {
158632
158641
  try {
158633
158642
  const result2 = spawnSync9(cmd, ["--version"], { stdio: "pipe" });
@@ -158649,24 +158658,38 @@ function getToolPath(tool) {
158649
158658
  }
158650
158659
  return null;
158651
158660
  }
158652
- async function fetchWithTimeout(url, init2) {
158661
+ async function fetchWithTimeout(url, init2, signal) {
158653
158662
  const controller = new AbortController();
158654
158663
  const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
158664
+ const onAbort = () => {
158665
+ controller.abort(signal?.reason);
158666
+ };
158667
+ if (signal?.aborted) {
158668
+ onAbort();
158669
+ } else {
158670
+ signal?.addEventListener("abort", onAbort, { once: true });
158671
+ }
158672
+ const clearFetchTimeout = () => clearTimeout(timeout);
158673
+ const cleanup = () => {
158674
+ clearFetchTimeout();
158675
+ signal?.removeEventListener("abort", onAbort);
158676
+ };
158655
158677
  try {
158656
158678
  const response = await fetch(url, { ...init2, signal: controller.signal });
158657
158679
  return {
158658
158680
  response,
158659
- clearTimeout: () => clearTimeout(timeout)
158681
+ clearTimeout: clearFetchTimeout,
158682
+ cleanup
158660
158683
  };
158661
158684
  } catch (error) {
158662
- clearTimeout(timeout);
158685
+ cleanup();
158663
158686
  throw error;
158664
158687
  }
158665
158688
  }
158666
- async function getLatestVersion(repo) {
158667
- const { response, clearTimeout: clearFetchTimeout } = await fetchWithTimeout(`https://api.github.com/repos/${repo}/releases/latest`, {
158689
+ async function getLatestVersion(repo, signal) {
158690
+ const { response, cleanup: cleanupFetch } = await fetchWithTimeout(`https://api.github.com/repos/${repo}/releases/latest`, {
158668
158691
  headers: { "User-Agent": "composer-coding-agent" }
158669
- });
158692
+ }, signal);
158670
158693
  try {
158671
158694
  if (!response.ok) {
158672
158695
  throw new Error(`GitHub API error: ${response.status}`);
@@ -158674,11 +158697,15 @@ async function getLatestVersion(repo) {
158674
158697
  const data = await response.json();
158675
158698
  return data.tag_name.replace(/^v/, "");
158676
158699
  } finally {
158677
- clearFetchTimeout();
158700
+ cleanupFetch();
158678
158701
  }
158679
158702
  }
158680
- async function downloadFile2(url, dest) {
158681
- const { response, clearTimeout: clearFetchTimeout } = await fetchWithTimeout(url);
158703
+ async function downloadFile2(url, dest, signal) {
158704
+ const {
158705
+ response,
158706
+ clearTimeout: clearFetchTimeout,
158707
+ cleanup: cleanupFetch
158708
+ } = await fetchWithTimeout(url, void 0, signal);
158682
158709
  try {
158683
158710
  if (!response.ok) {
158684
158711
  throw new Error(`Failed to download: ${response.status}`);
@@ -158690,6 +158717,11 @@ async function downloadFile2(url, dest) {
158690
158717
  const stream = Readable2.fromWeb(response.body);
158691
158718
  const fileStream = createWriteStream3(dest);
158692
158719
  let idleTimeoutId = null;
158720
+ const onAbort = () => {
158721
+ const error = new Error("Tool download aborted");
158722
+ stream.destroy(error);
158723
+ fileStream.destroy(error);
158724
+ };
158693
158725
  const clearIdleTimeout = () => {
158694
158726
  if (idleTimeoutId) {
158695
158727
  clearTimeout(idleTimeoutId);
@@ -158709,6 +158741,11 @@ async function downloadFile2(url, dest) {
158709
158741
  clearIdleTimeout();
158710
158742
  };
158711
158743
  resetIdleTimeout();
158744
+ if (signal?.aborted) {
158745
+ onAbort();
158746
+ } else {
158747
+ signal?.addEventListener("abort", onAbort, { once: true });
158748
+ }
158712
158749
  stream.on("data", resetIdleTimeout);
158713
158750
  stream.on("end", onStreamEnd);
158714
158751
  stream.on("close", onStreamEnd);
@@ -158720,10 +158757,11 @@ async function downloadFile2(url, dest) {
158720
158757
  stream.off("end", onStreamEnd);
158721
158758
  stream.off("close", onStreamEnd);
158722
158759
  stream.off("error", onStreamEnd);
158760
+ signal?.removeEventListener("abort", onAbort);
158723
158761
  clearIdleTimeout();
158724
158762
  }
158725
158763
  } finally {
158726
- clearFetchTimeout();
158764
+ cleanupFetch();
158727
158765
  }
158728
158766
  }
158729
158767
  function runExtractor(command, args, description) {
@@ -158759,13 +158797,15 @@ function findBinary(root, binaryName) {
158759
158797
  }
158760
158798
  return null;
158761
158799
  }
158762
- async function downloadTool(tool) {
158800
+ async function downloadTool(tool, signal) {
158763
158801
  const config2 = TOOLS[tool];
158764
158802
  if (!config2)
158765
158803
  throw new Error(`Unknown tool: ${tool}`);
158804
+ throwIfToolInstallAborted(config2, signal);
158766
158805
  const plat = platform3();
158767
158806
  const architecture = arch2();
158768
- const version3 = await getLatestVersion(config2.repo);
158807
+ const version3 = await getLatestVersion(config2.repo, signal);
158808
+ throwIfToolInstallAborted(config2, signal);
158769
158809
  const assetName = config2.getAssetName(version3, plat, architecture);
158770
158810
  if (!assetName) {
158771
158811
  throw new Error(`Unsupported platform: ${plat}/${architecture}`);
@@ -158775,7 +158815,8 @@ async function downloadTool(tool) {
158775
158815
  const archivePath = join79(TOOLS_DIR, assetName);
158776
158816
  const binaryExt = plat === "win32" ? ".exe" : "";
158777
158817
  const binaryPath = join79(TOOLS_DIR, config2.binaryName + binaryExt);
158778
- await downloadFile2(downloadUrl, archivePath);
158818
+ await downloadFile2(downloadUrl, archivePath, signal);
158819
+ throwIfToolInstallAborted(config2, signal);
158779
158820
  const extractDir = mkdtempSync2(join79(TOOLS_DIR, "extract-"));
158780
158821
  try {
158781
158822
  if (assetName.endsWith(".tar.gz")) {
@@ -158799,24 +158840,28 @@ async function downloadTool(tool) {
158799
158840
  }
158800
158841
  return binaryPath;
158801
158842
  }
158802
- async function ensureTool(tool, silent = false) {
158843
+ async function ensureTool(tool, silent = false, signal) {
158844
+ const config2 = TOOLS[tool];
158845
+ if (!config2)
158846
+ return null;
158847
+ throwIfToolInstallAborted(config2, signal);
158803
158848
  const existingPath = getToolPath(tool);
158804
158849
  if (existingPath) {
158805
158850
  return existingPath;
158806
158851
  }
158807
- const config2 = TOOLS[tool];
158808
- if (!config2)
158809
- return null;
158810
158852
  if (!silent) {
158811
158853
  console.log(chalk62.dim(`${config2.name} not found. Downloading...`));
158812
158854
  }
158813
158855
  try {
158814
- const path3 = await downloadTool(tool);
158856
+ const path3 = await downloadTool(tool, signal);
158815
158857
  if (!silent) {
158816
158858
  console.log(chalk62.dim(`${config2.name} installed to ${path3}`));
158817
158859
  }
158818
158860
  return path3;
158819
158861
  } catch (e2) {
158862
+ if (signal?.aborted) {
158863
+ throw toolInstallAbortError(config2);
158864
+ }
158820
158865
  if (!silent) {
158821
158866
  console.log(chalk62.yellow(`Failed to download ${config2.name}: ${e2 instanceof Error ? e2.message : e2}`));
158822
158867
  }
@@ -159121,7 +159166,7 @@ var init_find = __esm2(() => {
159121
159166
  throw new Error("Operation aborted");
159122
159167
  }
159123
159168
  const { pattern, path: searchDir, limit, includeHidden = true } = params;
159124
- const fdPath = await ensureTool("fd", true);
159169
+ const fdPath = await ensureTool("fd", true, signal);
159125
159170
  if (!fdPath) {
159126
159171
  return respond.error("fd is not available and could not be downloaded").detail({
159127
159172
  command: "fd",
@@ -160325,6 +160370,84 @@ function toArray(value) {
160325
160370
  }
160326
160371
  return Array.isArray(value) ? value : [value];
160327
160372
  }
160373
+ function ripgrepAbortError() {
160374
+ return new Error("ripgrep search aborted before start");
160375
+ }
160376
+ function resetRipgrepExecutablePromise() {
160377
+ ripgrepExecutablePromise = null;
160378
+ ripgrepInstallController = null;
160379
+ }
160380
+ function getRipgrepExecutablePromise() {
160381
+ if (!ripgrepExecutablePromise) {
160382
+ const controller = new AbortController();
160383
+ ripgrepInstallController = controller;
160384
+ const promise = ensureTool("rg", true, controller.signal).then((executable) => {
160385
+ if (ripgrepInstallController === controller) {
160386
+ ripgrepInstallController = null;
160387
+ }
160388
+ if (ripgrepExecutablePromise === promise && !executable) {
160389
+ ripgrepExecutablePromise = null;
160390
+ }
160391
+ return executable;
160392
+ }, (error) => {
160393
+ if (ripgrepInstallController === controller) {
160394
+ ripgrepInstallController = null;
160395
+ }
160396
+ if (ripgrepExecutablePromise === promise) {
160397
+ ripgrepExecutablePromise = null;
160398
+ }
160399
+ throw error;
160400
+ });
160401
+ ripgrepExecutablePromise = promise;
160402
+ }
160403
+ return ripgrepExecutablePromise;
160404
+ }
160405
+ function releaseRipgrepExecutableWaiter(signal) {
160406
+ ripgrepExecutableWaiters = Math.max(0, ripgrepExecutableWaiters - 1);
160407
+ if (signal?.aborted && ripgrepExecutableWaiters === 0) {
160408
+ const controller = ripgrepInstallController;
160409
+ resetRipgrepExecutablePromise();
160410
+ controller?.abort(signal.reason);
160411
+ }
160412
+ }
160413
+ async function waitForRipgrepExecutableWithAbort(promise, signal) {
160414
+ throwIfRipgrepAborted(signal);
160415
+ return await new Promise((resolve532, reject) => {
160416
+ const onAbort = () => {
160417
+ signal.removeEventListener("abort", onAbort);
160418
+ reject(ripgrepAbortError());
160419
+ };
160420
+ signal.addEventListener("abort", onAbort, { once: true });
160421
+ promise.then(resolve532, reject).finally(() => {
160422
+ signal.removeEventListener("abort", onAbort);
160423
+ });
160424
+ });
160425
+ }
160426
+ async function resolveRipgrepExecutable(signal) {
160427
+ ripgrepExecutableWaiters += 1;
160428
+ try {
160429
+ const promise = getRipgrepExecutablePromise();
160430
+ const executable = signal ? await waitForRipgrepExecutableWithAbort(promise, signal) : await promise;
160431
+ if (!executable) {
160432
+ throw new Error("ripgrep is not available and could not be downloaded");
160433
+ }
160434
+ return executable;
160435
+ } finally {
160436
+ releaseRipgrepExecutableWaiter(signal);
160437
+ }
160438
+ }
160439
+ function throwIfRipgrepAborted(signal) {
160440
+ if (signal?.aborted) {
160441
+ throw ripgrepAbortError();
160442
+ }
160443
+ }
160444
+ async function resolveRipgrepExecutableWithAbort(signal) {
160445
+ throwIfRipgrepAborted(signal);
160446
+ if (!signal) {
160447
+ return await resolveRipgrepExecutable();
160448
+ }
160449
+ return await resolveRipgrepExecutable(signal);
160450
+ }
160328
160451
  function shellQuoteArg(value) {
160329
160452
  if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value)) {
160330
160453
  return value;
@@ -160335,7 +160458,9 @@ function formatRipgrepCommand(args) {
160335
160458
  return ["rg", ...args].map(shellQuoteArg).join(" ");
160336
160459
  }
160337
160460
  async function runRipgrep(args, signal, cwd) {
160338
- const child = spawn17("rg", args, {
160461
+ const executable = await resolveRipgrepExecutableWithAbort(signal);
160462
+ throwIfRipgrepAborted(signal);
160463
+ const child = spawn17(executable, args, {
160339
160464
  cwd: cwd ?? process.cwd(),
160340
160465
  stdio: ["ignore", "pipe", "pipe"],
160341
160466
  signal
@@ -160401,8 +160526,12 @@ function parseRipgrepJson(output) {
160401
160526
  var pathSchema;
160402
160527
  var globSchema;
160403
160528
  var MAX_RIPGREP_OUTPUT_BYTES = 2e6;
160529
+ var ripgrepExecutablePromise = null;
160530
+ var ripgrepInstallController = null;
160531
+ var ripgrepExecutableWaiters = 0;
160404
160532
  var init_ripgrep_utils = __esm2(() => {
160405
160533
  init_json();
160534
+ init_tools_manager();
160406
160535
  pathSchema = Type25.Optional(Type25.Union([
160407
160536
  Type25.String({
160408
160537
  description: "Directory or file to search",
@@ -202353,8 +202482,11 @@ async function runRpcMode(agent, sessionManager) {
202353
202482
  terminal: false
202354
202483
  });
202355
202484
  rl.on("line", async (line) => {
202485
+ let requestId;
202486
+ const withRequestId = (response) => requestId ? { id: requestId, ...response } : response;
202356
202487
  try {
202357
202488
  const input = JSON.parse(line);
202489
+ requestId = typeof input.id === "string" ? input.id : void 0;
202358
202490
  if (input.type === "prompt" && input.message) {
202359
202491
  await runUserPromptWithRecovery({
202360
202492
  agent,
@@ -202372,12 +202504,12 @@ async function runRpcMode(agent, sessionManager) {
202372
202504
  } else if (input.type === "abort") {
202373
202505
  agent.abort();
202374
202506
  } else if (input.type === "get_messages") {
202375
- console.log(JSON.stringify({
202507
+ console.log(JSON.stringify(withRequestId({
202376
202508
  type: "messages",
202377
202509
  messages: agent.state.messages
202378
- }));
202510
+ })));
202379
202511
  } else if (input.type === "get_state") {
202380
- console.log(JSON.stringify({
202512
+ console.log(JSON.stringify(withRequestId({
202381
202513
  type: "state",
202382
202514
  state: {
202383
202515
  model: agent.state.model,
@@ -202388,7 +202520,7 @@ async function runRpcMode(agent, sessionManager) {
202388
202520
  session: agent.state.session,
202389
202521
  queuedMessageCount: agent.getQueuedMessageCount()
202390
202522
  }
202391
- }));
202523
+ })));
202392
202524
  } else if (input.type === "continue") {
202393
202525
  await runWithPromptRecovery({
202394
202526
  agent,
@@ -202418,13 +202550,13 @@ async function runRpcMode(agent, sessionManager) {
202418
202550
  }
202419
202551
  });
202420
202552
  if (!result2.success) {
202421
- console.log(JSON.stringify({
202553
+ console.log(JSON.stringify(withRequestId({
202422
202554
  type: "error",
202423
202555
  error: result2.error
202424
- }));
202556
+ })));
202425
202557
  return;
202426
202558
  }
202427
- const compactionEvent = {
202559
+ const compactionEvent = withRequestId({
202428
202560
  type: "compaction",
202429
202561
  summary: result2.summary ?? `Compacted ${result2.compactedCount} messages`,
202430
202562
  firstKeptEntryIndex: result2.firstKeptEntryIndex ?? 0,
@@ -202432,12 +202564,18 @@ async function runRpcMode(agent, sessionManager) {
202432
202564
  auto: false,
202433
202565
  customInstructions,
202434
202566
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
202435
- };
202567
+ });
202436
202568
  console.log(JSON.stringify(compactionEvent));
202569
+ } else {
202570
+ const commandType = typeof input.type === "string" && input.type ? input.type : "unknown";
202571
+ console.log(JSON.stringify(withRequestId({
202572
+ type: "error",
202573
+ error: `Unknown RPC command: ${commandType}`
202574
+ })));
202437
202575
  }
202438
202576
  } catch (error) {
202439
202577
  const message = error instanceof Error ? error.message : String(error);
202440
- console.log(JSON.stringify({ type: "error", error: message }));
202578
+ console.log(JSON.stringify(withRequestId({ type: "error", error: message })));
202441
202579
  }
202442
202580
  });
202443
202581
  return new Promise(() => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evalops/contracts",
3
- "version": "0.10.37",
3
+ "version": "0.10.39",
4
4
  "description": "Shared Maestro contracts for frontend/backend integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evalops/tui",
3
- "version": "0.10.37",
3
+ "version": "0.10.39",
4
4
  "description": "Terminal UI library with differential rendering for Maestro",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",