ai-cli-mcp 2.13.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ import { homedir } from 'node:os';
17
17
  import { buildCliCommand, type BuildCliCommandOptions } from './cli-builder.js';
18
18
  import { findClaudeCli, findCodexCli, findForgeCli, findGeminiCli } from './cli-utils.js';
19
19
  import { parseClaudeOutput, parseCodexOutput, parseForgeOutput, parseGeminiOutput } from './parsers.js';
20
+ import { buildProcessResult } from './process-result.js';
20
21
  import type { AgentType, ProcessListItem } from './process-service.js';
21
22
 
22
23
  interface StoredProcess {
@@ -183,7 +184,7 @@ export class CliProcessService {
183
184
  }
184
185
  }
185
186
 
186
- const response: any = {
187
+ return buildProcessResult({
187
188
  pid,
188
189
  agent: refreshed.toolType,
189
190
  status: refreshed.status,
@@ -192,27 +193,12 @@ export class CliProcessService {
192
193
  workFolder: refreshed.workFolder,
193
194
  prompt: refreshed.prompt,
194
195
  model: refreshed.model,
195
- };
196
-
197
- if (agentOutput) {
198
- if (!verbose && agentOutput.tools) {
199
- const { tools, ...rest } = agentOutput;
200
- response.agentOutput = rest;
201
- } else {
202
- response.agentOutput = agentOutput;
203
- }
204
- if (agentOutput.session_id) {
205
- response.session_id = agentOutput.session_id;
206
- }
207
- } else {
208
- response.stdout = stdout;
209
- response.stderr = stderr;
210
- }
211
-
212
- return response;
196
+ stdout,
197
+ stderr,
198
+ }, agentOutput, verbose);
213
199
  }
214
200
 
215
- async waitForProcesses(pids: number[], timeoutSeconds = 180): Promise<any[]> {
201
+ async waitForProcesses(pids: number[], timeoutSeconds = 180, verbose = false): Promise<any[]> {
216
202
  const start = Date.now();
217
203
  for (const pid of pids) {
218
204
  this.readProcess(pid);
@@ -221,7 +207,7 @@ export class CliProcessService {
221
207
  while (true) {
222
208
  const statuses = pids.map((pid) => this.refreshStatus(this.readProcess(pid)).status);
223
209
  if (statuses.every((status) => status !== 'running')) {
224
- return Promise.all(pids.map((pid) => this.getProcessResult(pid, false)));
210
+ return Promise.all(pids.map((pid) => this.getProcessResult(pid, verbose)));
225
211
  }
226
212
 
227
213
  if (Date.now() - start >= timeoutSeconds * 1000) {
@@ -0,0 +1,79 @@
1
+ import type { AgentType, ProcessStatus } from './process-service.js';
2
+
3
+ interface ProcessResultContext {
4
+ pid: number;
5
+ agent: AgentType;
6
+ status: ProcessStatus;
7
+ exitCode?: number;
8
+ startTime: string;
9
+ workFolder: string;
10
+ prompt: string;
11
+ model?: string;
12
+ stdout: string;
13
+ stderr: string;
14
+ }
15
+
16
+ function compactAgentOutput(agentOutput: any): any | null {
17
+ if (!agentOutput || typeof agentOutput !== 'object') {
18
+ return null;
19
+ }
20
+
21
+ const { tools: _tools, ...rest } = agentOutput;
22
+ const compact = Object.fromEntries(Object.entries(rest).filter(([, value]) => value !== undefined && value !== null));
23
+ return Object.keys(compact).length > 0 ? compact : null;
24
+ }
25
+
26
+ function hasMeaningfulParsedOutput(agentOutput: any): boolean {
27
+ if (!agentOutput || typeof agentOutput !== 'object') {
28
+ return false;
29
+ }
30
+
31
+ return Object.entries(agentOutput).some(([key, value]) => {
32
+ if (value === undefined || value === null) {
33
+ return false;
34
+ }
35
+
36
+ if (key === 'session_id') {
37
+ return false;
38
+ }
39
+
40
+ if (key === 'tools') {
41
+ return Array.isArray(value) ? value.length > 0 : true;
42
+ }
43
+
44
+ return true;
45
+ });
46
+ }
47
+
48
+ export function buildProcessResult(context: ProcessResultContext, agentOutput: any, verbose = false): any {
49
+ const response: any = {
50
+ pid: context.pid,
51
+ agent: context.agent,
52
+ status: context.status,
53
+ exitCode: context.exitCode ?? null,
54
+ model: context.model ?? null,
55
+ };
56
+
57
+ if (verbose) {
58
+ response.startTime = context.startTime;
59
+ response.workFolder = context.workFolder;
60
+ response.prompt = context.prompt;
61
+ }
62
+
63
+ if (agentOutput?.session_id) {
64
+ response.session_id = agentOutput.session_id;
65
+ }
66
+
67
+ const shapedAgentOutput = verbose ? agentOutput : compactAgentOutput(agentOutput);
68
+
69
+ if (hasMeaningfulParsedOutput(shapedAgentOutput)) {
70
+ response.agentOutput = shapedAgentOutput;
71
+ }
72
+
73
+ if (!response.agentOutput) {
74
+ response.stdout = context.stdout;
75
+ response.stderr = context.stderr;
76
+ }
77
+
78
+ return response;
79
+ }
@@ -1,6 +1,7 @@
1
1
  import { spawn, type ChildProcess } from 'node:child_process';
2
2
  import { buildCliCommand, type BuildCliCommandOptions } from './cli-builder.js';
3
3
  import { parseClaudeOutput, parseCodexOutput, parseForgeOutput, parseGeminiOutput } from './parsers.js';
4
+ import { buildProcessResult } from './process-result.js';
4
5
 
5
6
  export type AgentType = 'claude' | 'codex' | 'gemini' | 'forge';
6
7
  export type ProcessStatus = 'running' | 'completed' | 'failed';
@@ -149,7 +150,7 @@ export class ProcessService {
149
150
  }
150
151
  }
151
152
 
152
- const response: any = {
153
+ return buildProcessResult({
153
154
  pid,
154
155
  agent: process.toolType,
155
156
  status: process.status,
@@ -158,28 +159,12 @@ export class ProcessService {
158
159
  workFolder: process.workFolder,
159
160
  prompt: process.prompt,
160
161
  model: process.model,
161
- };
162
-
163
- if (agentOutput) {
164
- if (!verbose && agentOutput.tools) {
165
- const { tools, ...rest } = agentOutput;
166
- response.agentOutput = rest;
167
- } else {
168
- response.agentOutput = agentOutput;
169
- }
170
-
171
- if (agentOutput.session_id) {
172
- response.session_id = agentOutput.session_id;
173
- }
174
- } else {
175
- response.stdout = process.stdout;
176
- response.stderr = process.stderr;
177
- }
178
-
179
- return response;
162
+ stdout: process.stdout,
163
+ stderr: process.stderr,
164
+ }, agentOutput, verbose);
180
165
  }
181
166
 
182
- async waitForProcesses(pids: number[], timeoutSeconds = 180): Promise<any[]> {
167
+ async waitForProcesses(pids: number[], timeoutSeconds = 180, verbose = false): Promise<any[]> {
183
168
  for (const pid of pids) {
184
169
  if (!this.processManager.has(pid)) {
185
170
  throw new Error(`Process with PID ${pid} not found`);
@@ -211,7 +196,7 @@ export class ProcessService {
211
196
 
212
197
  try {
213
198
  await Promise.race([Promise.all(waitPromises), timeoutPromise]);
214
- return pids.map((pid) => this.getProcessResult(pid, false));
199
+ return pids.map((pid) => this.getProcessResult(pid, verbose));
215
200
  } finally {
216
201
  if (timeoutHandle) {
217
202
  clearTimeout(timeoutHandle);