@roj-ai/cli 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +28 -0
- package/dist/commands/answer.d.ts +3 -0
- package/dist/commands/answer.d.ts.map +1 -0
- package/dist/commands/answer.js +15 -0
- package/dist/commands/debug-format.d.ts +12 -0
- package/dist/commands/debug-format.d.ts.map +1 -0
- package/dist/commands/debug-format.js +262 -0
- package/dist/commands/debug.d.ts +14 -0
- package/dist/commands/debug.d.ts.map +1 -0
- package/dist/commands/debug.js +187 -0
- package/dist/commands/messages.d.ts +4 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +77 -0
- package/dist/commands/presets.d.ts +3 -0
- package/dist/commands/presets.d.ts.map +1 -0
- package/dist/commands/presets.js +14 -0
- package/dist/commands/sessions.d.ts +6 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +50 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +277 -0
- package/dist/repl/formatter.d.ts +16 -0
- package/dist/repl/formatter.d.ts.map +1 -0
- package/dist/repl/formatter.js +72 -0
- package/dist/repl/repl.d.ts +3 -0
- package/dist/repl/repl.d.ts.map +1 -0
- package/dist/repl/repl.js +212 -0
- package/dist/repl/session-picker.d.ts +6 -0
- package/dist/repl/session-picker.d.ts.map +1 -0
- package/dist/repl/session-picker.js +60 -0
- package/dist/unwrap.d.ts +4 -0
- package/dist/unwrap.d.ts.map +1 -0
- package/dist/unwrap.js +6 -0
- package/package.json +27 -0
- package/src/client.ts +41 -0
- package/src/commands/answer.ts +27 -0
- package/src/commands/debug-format.ts +299 -0
- package/src/commands/debug.ts +347 -0
- package/src/commands/messages.ts +92 -0
- package/src/commands/presets.ts +22 -0
- package/src/commands/sessions.ts +73 -0
- package/src/main.ts +319 -0
- package/src/repl/formatter.ts +84 -0
- package/src/repl/repl.ts +246 -0
- package/src/repl/session-picker.ts +81 -0
- package/src/unwrap.ts +8 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RpcClient } from '@roj-ai/shared/rpc';
|
|
2
|
+
import type { ProtocolDef } from '@roj-ai/transport';
|
|
3
|
+
import { ClientConnection } from '@roj-ai/transport/client';
|
|
4
|
+
export declare function createCliClient(baseUrl: string): RpcClient;
|
|
5
|
+
export type WsConnection = ClientConnection<ProtocolDef, ProtocolDef>;
|
|
6
|
+
export type NotificationHandlers = Record<string, (payload: unknown) => void>;
|
|
7
|
+
export declare function connectWebSocket(baseUrl: string, sessionId: string, handlers: NotificationHandlers): WsConnection;
|
|
8
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAA;AAExE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAE1D;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;AAErE,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC,CAAA;AAE7E,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,oBAAoB,GAC5B,YAAY,CAuBd"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RpcClient } from '@roj-ai/shared/rpc';
|
|
2
|
+
import { bunWebSocketFactory } from '@roj-ai/transport/bun';
|
|
3
|
+
import { ClientConnection } from '@roj-ai/transport/client';
|
|
4
|
+
export function createCliClient(baseUrl) {
|
|
5
|
+
return new RpcClient(baseUrl);
|
|
6
|
+
}
|
|
7
|
+
export function connectWebSocket(baseUrl, sessionId, handlers) {
|
|
8
|
+
const url = new URL('/ws/spa', baseUrl);
|
|
9
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
10
|
+
url.searchParams.set('sessionId', sessionId);
|
|
11
|
+
const connection = new ClientConnection({
|
|
12
|
+
url: url.toString(),
|
|
13
|
+
wsFactory: bunWebSocketFactory,
|
|
14
|
+
reconnect: {
|
|
15
|
+
baseDelayMs: 1000,
|
|
16
|
+
maxDelayMs: 10000,
|
|
17
|
+
maxAttempts: 10,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const listener = (type, payload) => {
|
|
21
|
+
const handler = handlers[type];
|
|
22
|
+
if (handler) {
|
|
23
|
+
handler(payload);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
connection.setRawMessageListener(listener);
|
|
27
|
+
return connection;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../src/commands/answer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGnD,wBAAsB,aAAa,CAClC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AgentId, ChatMessageId } from '@roj-ai/shared';
|
|
2
|
+
import { unwrap } from '../unwrap.js';
|
|
3
|
+
export async function answerCommand(client, sessionId, questionId, answer, json) {
|
|
4
|
+
const session = unwrap(await client.call('sessions.get', { sessionId }));
|
|
5
|
+
if (!session.entryAgentId) {
|
|
6
|
+
console.error('No entry agent found for session.');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const result = unwrap(await client.call('user-chat.answerQuestion', { sessionId, agentId: AgentId(session.entryAgentId), questionId: ChatMessageId(questionId), answer }));
|
|
10
|
+
if (json) {
|
|
11
|
+
console.log(JSON.stringify(result));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
console.log('Answer submitted.');
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LLMCallLogEntry } from '@roj-ai/sdk';
|
|
2
|
+
import type { DomainEvent } from '@roj-ai/sdk';
|
|
3
|
+
import type { AgentTreeNode, GetAgentDetailResponse, GetMetricsResponse, GlobalMailboxMessage, TimelineItem } from '@roj-ai/shared';
|
|
4
|
+
export declare function truncate(str: string, maxLen: number): string;
|
|
5
|
+
export declare function formatAgentTree(nodes: AgentTreeNode[]): string;
|
|
6
|
+
export declare function formatAgentDetail(detail: GetAgentDetailResponse): string;
|
|
7
|
+
export declare function formatTimelineItem(item: TimelineItem): string;
|
|
8
|
+
export declare function formatMailboxMessage(msg: GlobalMailboxMessage): string;
|
|
9
|
+
export declare function formatMetrics(metrics: GetMetricsResponse): string;
|
|
10
|
+
export declare function formatLLMCallDetail(call: LLMCallLogEntry): string;
|
|
11
|
+
export declare function formatEventRow(event: DomainEvent, index: number): string[];
|
|
12
|
+
//# sourceMappingURL=debug-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-format.d.ts","sourceRoot":"","sources":["../../src/commands/debug-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EACX,aAAa,EAEb,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,MAAM,gBAAgB,CAAA;AAYvB,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAG5D;AAgCD,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,CAO9D;AAmCD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CA8CxE;AAwBD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAsB7D;AAMD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAItE;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAcjE;AAMD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CA0DjE;AAMD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1E"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// ANSI color codes
|
|
2
|
+
const RESET = '\x1b[0m';
|
|
3
|
+
const BOLD = '\x1b[1m';
|
|
4
|
+
const DIM = '\x1b[2m';
|
|
5
|
+
const CYAN = '\x1b[36m';
|
|
6
|
+
const GREEN = '\x1b[32m';
|
|
7
|
+
const YELLOW = '\x1b[33m';
|
|
8
|
+
const RED = '\x1b[31m';
|
|
9
|
+
const MAGENTA = '\x1b[35m';
|
|
10
|
+
export function truncate(str, maxLen) {
|
|
11
|
+
if (str.length <= maxLen)
|
|
12
|
+
return str;
|
|
13
|
+
return str.slice(0, maxLen - 1) + '\u2026';
|
|
14
|
+
}
|
|
15
|
+
function formatDuration(ms) {
|
|
16
|
+
if (ms === undefined)
|
|
17
|
+
return '-';
|
|
18
|
+
if (ms < 1000)
|
|
19
|
+
return `${ms}ms`;
|
|
20
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
21
|
+
}
|
|
22
|
+
function formatTimestamp(ts) {
|
|
23
|
+
return new Date(ts).toLocaleTimeString();
|
|
24
|
+
}
|
|
25
|
+
function statusColor(status) {
|
|
26
|
+
switch (status) {
|
|
27
|
+
case 'idle':
|
|
28
|
+
case 'success':
|
|
29
|
+
return GREEN;
|
|
30
|
+
case 'thinking':
|
|
31
|
+
case 'responding':
|
|
32
|
+
case 'running':
|
|
33
|
+
return YELLOW;
|
|
34
|
+
case 'error':
|
|
35
|
+
return RED;
|
|
36
|
+
default:
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Agent Tree
|
|
42
|
+
// ============================================================================
|
|
43
|
+
export function formatAgentTree(nodes) {
|
|
44
|
+
const lines = [];
|
|
45
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
46
|
+
const isLast = i === nodes.length - 1;
|
|
47
|
+
formatTreeNode(lines, nodes[i], '', isLast);
|
|
48
|
+
}
|
|
49
|
+
return lines.join('\n');
|
|
50
|
+
}
|
|
51
|
+
function formatCost(cost) {
|
|
52
|
+
if (cost >= 1)
|
|
53
|
+
return `$${cost.toFixed(2)}`;
|
|
54
|
+
return `$${cost.toFixed(4)}`;
|
|
55
|
+
}
|
|
56
|
+
function formatTreeNode(lines, node, prefix, isLast) {
|
|
57
|
+
const connector = isLast ? '\u2514\u2500\u2500 ' : '\u251c\u2500\u2500 ';
|
|
58
|
+
const childPrefix = prefix + (isLast ? ' ' : '\u2502 ');
|
|
59
|
+
const color = statusColor(node.status);
|
|
60
|
+
// Line 1: name + status
|
|
61
|
+
lines.push(`${prefix}${connector}${BOLD}${node.definitionName}${RESET} ${color}[${node.status}]${RESET}`);
|
|
62
|
+
// Line 2: cost + badges + id
|
|
63
|
+
const details = [];
|
|
64
|
+
if (node.cost > 0)
|
|
65
|
+
details.push(`${GREEN}${formatCost(node.cost)}${RESET}`);
|
|
66
|
+
if (node.isExecuting)
|
|
67
|
+
details.push(`${YELLOW}executing${RESET}`);
|
|
68
|
+
if (node.mailboxCount > 0)
|
|
69
|
+
details.push(`${CYAN}${node.mailboxCount} msgs${RESET}`);
|
|
70
|
+
if (node.pendingToolCalls > 0)
|
|
71
|
+
details.push(`${MAGENTA}${node.pendingToolCalls} tools${RESET}`);
|
|
72
|
+
const detailStr = details.length > 0 ? details.join(` ${DIM}\u00b7${RESET} `) + ' ' : '';
|
|
73
|
+
lines.push(`${childPrefix}${detailStr}${DIM}${node.id}${RESET}`);
|
|
74
|
+
// Children
|
|
75
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
76
|
+
const childIsLast = i === node.children.length - 1;
|
|
77
|
+
formatTreeNode(lines, node.children[i], childPrefix, childIsLast);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Agent Detail
|
|
82
|
+
// ============================================================================
|
|
83
|
+
export function formatAgentDetail(detail) {
|
|
84
|
+
const lines = [];
|
|
85
|
+
const color = statusColor(detail.status);
|
|
86
|
+
// Header
|
|
87
|
+
lines.push(`${BOLD}Agent: ${detail.definitionName}${RESET}`);
|
|
88
|
+
lines.push(` ID: ${detail.id}`);
|
|
89
|
+
lines.push(` Status: ${color}${detail.status}${RESET}`);
|
|
90
|
+
lines.push(` Parent: ${detail.parentId ?? 'none'}`);
|
|
91
|
+
// Mailbox
|
|
92
|
+
lines.push('');
|
|
93
|
+
lines.push(`${BOLD}Mailbox${RESET} (${detail.mailbox.length} messages)`);
|
|
94
|
+
if (detail.mailbox.length === 0) {
|
|
95
|
+
lines.push(` ${DIM}(empty)${RESET}`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
for (const msg of detail.mailbox) {
|
|
99
|
+
const consumed = msg.consumed ? `${DIM}[consumed]${RESET}` : `${YELLOW}[pending]${RESET}`;
|
|
100
|
+
lines.push(` ${msg.from} ${consumed}: ${truncate(msg.content, 80)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Conversation
|
|
104
|
+
lines.push('');
|
|
105
|
+
lines.push(`${BOLD}Conversation${RESET} (${detail.conversationHistory.length} messages)`);
|
|
106
|
+
if (detail.conversationHistory.length === 0) {
|
|
107
|
+
lines.push(` ${DIM}(empty)${RESET}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
for (const msg of detail.conversationHistory) {
|
|
111
|
+
lines.push(formatConversationMessage(msg));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Pending Tool Calls
|
|
115
|
+
if (detail.pendingToolCalls.length > 0) {
|
|
116
|
+
lines.push('');
|
|
117
|
+
lines.push(`${BOLD}Pending Tool Calls${RESET} (${detail.pendingToolCalls.length})`);
|
|
118
|
+
for (const tc of detail.pendingToolCalls) {
|
|
119
|
+
lines.push(` ${MAGENTA}${tc.name}${RESET} [${tc.status}] ${DIM}${tc.id}${RESET}`);
|
|
120
|
+
if (tc.input) {
|
|
121
|
+
lines.push(` Input: ${truncate(JSON.stringify(tc.input), 100)}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return lines.join('\n');
|
|
126
|
+
}
|
|
127
|
+
function formatConversationMessage(msg) {
|
|
128
|
+
switch (msg.role) {
|
|
129
|
+
case 'user':
|
|
130
|
+
return ` ${GREEN}user:${RESET} ${truncate(typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content), 100)}`;
|
|
131
|
+
case 'assistant': {
|
|
132
|
+
const content = msg.content ? truncate(msg.content, 100) : '';
|
|
133
|
+
const toolsInfo = msg.toolCalls?.length ? ` ${DIM}[${msg.toolCalls.length} tool calls]${RESET}` : '';
|
|
134
|
+
return ` ${CYAN}assistant:${RESET} ${content}${toolsInfo}`;
|
|
135
|
+
}
|
|
136
|
+
case 'tool': {
|
|
137
|
+
const errTag = msg.isError ? `${RED}[error]${RESET} ` : '';
|
|
138
|
+
return ` ${MAGENTA}tool(${msg.toolCallId}):${RESET} ${errTag}${truncate(msg.content, 100)}`;
|
|
139
|
+
}
|
|
140
|
+
case 'system':
|
|
141
|
+
return ` ${DIM}system: ${truncate(msg.content, 100)}${RESET}`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Timeline
|
|
146
|
+
// ============================================================================
|
|
147
|
+
export function formatTimelineItem(item) {
|
|
148
|
+
const status = `${statusColor(item.status)}${item.status}${RESET}`;
|
|
149
|
+
const duration = formatDuration(item.durationMs);
|
|
150
|
+
const time = formatTimestamp(item.startedAt);
|
|
151
|
+
switch (item.type) {
|
|
152
|
+
case 'llm': {
|
|
153
|
+
const model = item.model ?? '-';
|
|
154
|
+
const tokens = item.promptTokens !== undefined ? `${item.promptTokens}/${item.completionTokens}` : '-';
|
|
155
|
+
return `${time} ${CYAN}llm${RESET} ${item.agentName.padEnd(20)} ${status.padEnd(20)} ${duration.padStart(8)} ${model} ${tokens}`;
|
|
156
|
+
}
|
|
157
|
+
case 'tool': {
|
|
158
|
+
const toolName = item.toolName ?? '-';
|
|
159
|
+
return `${time} ${MAGENTA}tool${RESET} ${item.agentName.padEnd(20)} ${status.padEnd(20)} ${duration.padStart(8)} ${toolName}`;
|
|
160
|
+
}
|
|
161
|
+
case 'compaction': {
|
|
162
|
+
const info = item.originalTokens !== undefined
|
|
163
|
+
? `${item.originalTokens} -> ${item.compactedTokens} tokens, ${item.messagesRemoved} msgs removed`
|
|
164
|
+
: '';
|
|
165
|
+
return `${time} ${YELLOW}compact${RESET} ${item.agentName.padEnd(20)} ${status.padEnd(20)} ${DIM}${info}${RESET}`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// ============================================================================
|
|
170
|
+
// Mailbox
|
|
171
|
+
// ============================================================================
|
|
172
|
+
export function formatMailboxMessage(msg) {
|
|
173
|
+
const status = msg.consumed ? `${DIM}[consumed]${RESET}` : `${YELLOW}[pending]${RESET}`;
|
|
174
|
+
const time = formatTimestamp(msg.timestamp);
|
|
175
|
+
return `${time} ${msg.fromAgentName} -> ${msg.toAgentName} ${status} ${truncate(msg.content, 60)}`;
|
|
176
|
+
}
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Metrics
|
|
179
|
+
// ============================================================================
|
|
180
|
+
export function formatMetrics(metrics) {
|
|
181
|
+
const lines = [];
|
|
182
|
+
lines.push(`${BOLD}Session Metrics${RESET}`);
|
|
183
|
+
lines.push(` Total tokens: ${metrics.totalTokens.toLocaleString()}`);
|
|
184
|
+
lines.push(` Prompt tokens: ${metrics.promptTokens.toLocaleString()}`);
|
|
185
|
+
lines.push(` Completion tokens: ${metrics.completionTokens.toLocaleString()}`);
|
|
186
|
+
if (metrics.totalCost !== undefined) {
|
|
187
|
+
lines.push(` Cost: $${metrics.totalCost.toFixed(4)}`);
|
|
188
|
+
}
|
|
189
|
+
lines.push(` LLM calls: ${metrics.llmCalls}`);
|
|
190
|
+
lines.push(` Tool calls: ${metrics.toolCalls}`);
|
|
191
|
+
lines.push(` Agent count: ${metrics.agentCount}`);
|
|
192
|
+
lines.push(` Duration: ${formatDuration(metrics.durationMs)}`);
|
|
193
|
+
return lines.join('\n');
|
|
194
|
+
}
|
|
195
|
+
// ============================================================================
|
|
196
|
+
// LLM Call Detail
|
|
197
|
+
// ============================================================================
|
|
198
|
+
export function formatLLMCallDetail(call) {
|
|
199
|
+
const lines = [];
|
|
200
|
+
lines.push(`${BOLD}LLM Call: ${call.id}${RESET}`);
|
|
201
|
+
lines.push(` Agent: ${call.agentId}`);
|
|
202
|
+
lines.push(` Status: ${statusColor(call.status)}${call.status}${RESET}`);
|
|
203
|
+
lines.push(` Created: ${new Date(call.createdAt).toLocaleString()}`);
|
|
204
|
+
if (call.durationMs !== undefined) {
|
|
205
|
+
lines.push(` Duration: ${formatDuration(call.durationMs)}`);
|
|
206
|
+
}
|
|
207
|
+
// Request
|
|
208
|
+
lines.push('');
|
|
209
|
+
lines.push(`${BOLD}Request${RESET}`);
|
|
210
|
+
lines.push(` Model: ${call.request.model}`);
|
|
211
|
+
lines.push(` Messages: ${call.request.messages.length}`);
|
|
212
|
+
lines.push(` Tools: ${call.request.toolsCount}`);
|
|
213
|
+
if (call.request.systemPrompt) {
|
|
214
|
+
lines.push(` System: ${truncate(call.request.systemPrompt, 100)}`);
|
|
215
|
+
}
|
|
216
|
+
// Response
|
|
217
|
+
if (call.response) {
|
|
218
|
+
lines.push('');
|
|
219
|
+
lines.push(`${BOLD}Response${RESET}`);
|
|
220
|
+
lines.push(` Finish: ${call.response.finishReason}`);
|
|
221
|
+
if (call.response.content) {
|
|
222
|
+
lines.push(` Content: ${truncate(call.response.content, 200)}`);
|
|
223
|
+
}
|
|
224
|
+
if (call.response.toolCalls.length > 0) {
|
|
225
|
+
lines.push(` Tool calls: ${call.response.toolCalls.length}`);
|
|
226
|
+
for (const tc of call.response.toolCalls) {
|
|
227
|
+
lines.push(` ${MAGENTA}${tc.name}${RESET} ${DIM}${tc.id}${RESET}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Metrics
|
|
232
|
+
if (call.metrics) {
|
|
233
|
+
lines.push('');
|
|
234
|
+
lines.push(`${BOLD}Metrics${RESET}`);
|
|
235
|
+
lines.push(` Prompt: ${call.metrics.promptTokens.toLocaleString()} tokens`);
|
|
236
|
+
lines.push(` Completion: ${call.metrics.completionTokens.toLocaleString()} tokens`);
|
|
237
|
+
lines.push(` Total: ${call.metrics.totalTokens.toLocaleString()} tokens`);
|
|
238
|
+
if (call.metrics.cost !== undefined) {
|
|
239
|
+
lines.push(` Cost: $${call.metrics.cost.toFixed(4)}`);
|
|
240
|
+
}
|
|
241
|
+
lines.push(` Latency: ${formatDuration(call.metrics.latencyMs)}`);
|
|
242
|
+
}
|
|
243
|
+
// Error
|
|
244
|
+
if (call.error) {
|
|
245
|
+
lines.push('');
|
|
246
|
+
lines.push(`${RED}${BOLD}Error${RESET}`);
|
|
247
|
+
lines.push(` ${RED}${call.error.type}: ${call.error.message}${RESET}`);
|
|
248
|
+
}
|
|
249
|
+
return lines.join('\n');
|
|
250
|
+
}
|
|
251
|
+
// ============================================================================
|
|
252
|
+
// Event Row
|
|
253
|
+
// ============================================================================
|
|
254
|
+
export function formatEventRow(event, index) {
|
|
255
|
+
const agentId = 'agentId' in event ? String(event.agentId) : '-';
|
|
256
|
+
return [
|
|
257
|
+
String(index),
|
|
258
|
+
event.type,
|
|
259
|
+
truncate(agentId, 24),
|
|
260
|
+
formatTimestamp(event.timestamp),
|
|
261
|
+
];
|
|
262
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SessionId } from '@roj-ai/sdk';
|
|
2
|
+
import type { RpcClient } from '@roj-ai/shared/rpc';
|
|
3
|
+
export declare function eventsCommand(client: RpcClient, sessionId: string, flags: Record<string, string | true>, json: boolean): Promise<void>;
|
|
4
|
+
export declare function llmCallsCommand(client: RpcClient, sessionId: string, flags: Record<string, string | true>, json: boolean): Promise<void>;
|
|
5
|
+
export declare function llmCallCommand(client: RpcClient, sessionId: string, callId: string, json: boolean): Promise<void>;
|
|
6
|
+
export declare function presetAgentsCommand(client: RpcClient, sessionId: SessionId, json: boolean): Promise<void>;
|
|
7
|
+
export declare function debugSendCommand(client: RpcClient, sessionId: string, agentId: string, content: string, flags: Record<string, string | true>, json: boolean): Promise<void>;
|
|
8
|
+
export declare function spawnAgentCommand(client: RpcClient, sessionId: string, definitionName: string, parentId: string, flags: Record<string, string | true>, json: boolean): Promise<void>;
|
|
9
|
+
export declare function agentsCommand(client: RpcClient, sessionId: string, json: boolean): Promise<void>;
|
|
10
|
+
export declare function agentCommand(client: RpcClient, sessionId: string, agentId: string, json: boolean): Promise<void>;
|
|
11
|
+
export declare function mailboxCommand(client: RpcClient, sessionId: string, json: boolean): Promise<void>;
|
|
12
|
+
export declare function timelineCommand(client: RpcClient, sessionId: string, json: boolean): Promise<void>;
|
|
13
|
+
export declare function metricsCommand(client: RpcClient, sessionId: string, json: boolean): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=debug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,SAAS,EAAE,MAAM,aAAa,CAAA;AA0B1E,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,oBAAoB,CAAA;AAmD9D,wBAAsB,aAAa,CAClC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACpC,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED,wBAAsB,eAAe,CACpC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACpC,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,wBAAsB,cAAc,CACnC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,mBAAmB,CACxC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACpC,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,iBAAiB,CACtC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACpC,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAUf;AAMD,wBAAsB,aAAa,CAClC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAef;AAED,wBAAsB,YAAY,CACjC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAef;AAED,wBAAsB,cAAc,CACnC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,eAAe,CACpC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,cAAc,CACnC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAef"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { AgentId, applyEventToAgentDetail, applyEventToAgentRegistry, applyEventToAgentTree, applyEventToMailbox, applyEventToMetrics, applyEventToTimeline, buildAgentTreeFromProjection, createAgentDetailProjectionState, createAgentRegistryState, createAgentTreeProjectionState, createMailboxState, createMetricsState, createTimelineState, getAgentDetail, getMailboxMessages, getTimelineItems, isDomainEvent, metricsStateToResponse, } from '@roj-ai/shared';
|
|
2
|
+
import { formatTable } from '../repl/formatter.js';
|
|
3
|
+
import { unwrap } from '../unwrap.js';
|
|
4
|
+
import { formatAgentDetail, formatAgentTree, formatEventRow, formatLLMCallDetail, formatMailboxMessage, formatMetrics, formatTimelineItem, } from './debug-format.js';
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Helpers
|
|
7
|
+
// ============================================================================
|
|
8
|
+
function isLLMCallLogEntry(data) {
|
|
9
|
+
return typeof data === 'object' && data !== null && 'id' in data && 'status' in data && 'request' in data;
|
|
10
|
+
}
|
|
11
|
+
async function loadProjections(client, sessionId) {
|
|
12
|
+
const { events: rawEvents } = unwrap(await client.call('sessions.getEvents', { sessionId, limit: 10000 }));
|
|
13
|
+
const events = rawEvents.filter(isDomainEvent);
|
|
14
|
+
let registry = createAgentRegistryState();
|
|
15
|
+
let agentTree = createAgentTreeProjectionState();
|
|
16
|
+
let agentDetail = createAgentDetailProjectionState();
|
|
17
|
+
for (const event of events) {
|
|
18
|
+
const e = event;
|
|
19
|
+
registry = applyEventToAgentRegistry(registry, e);
|
|
20
|
+
agentTree = applyEventToAgentTree(agentTree, e);
|
|
21
|
+
agentDetail = applyEventToAgentDetail(agentDetail, e);
|
|
22
|
+
}
|
|
23
|
+
return { registry, agentTree, agentDetail, events };
|
|
24
|
+
}
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Direct RPC Commands
|
|
27
|
+
// ============================================================================
|
|
28
|
+
export async function eventsCommand(client, sessionId, flags, json) {
|
|
29
|
+
const limit = typeof flags.limit === 'string' ? parseInt(flags.limit, 10) : undefined;
|
|
30
|
+
const type = typeof flags.type === 'string' ? flags.type : undefined;
|
|
31
|
+
const agentId = typeof flags.agent === 'string' ? flags.agent : undefined;
|
|
32
|
+
const { events: rawEvents, total } = unwrap(await client.call('sessions.getEvents', { sessionId, limit, type, agentId }));
|
|
33
|
+
const events = rawEvents.filter(isDomainEvent);
|
|
34
|
+
if (json) {
|
|
35
|
+
console.log(JSON.stringify({ events, total }, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (events.length === 0) {
|
|
39
|
+
console.log('No events found.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
console.log(formatTable(['#', 'Type', 'Agent', 'Time'], events.map((e, i) => formatEventRow(e, i))));
|
|
43
|
+
console.log(`\nTotal: ${total} events`);
|
|
44
|
+
}
|
|
45
|
+
export async function llmCallsCommand(client, sessionId, flags, json) {
|
|
46
|
+
const limit = typeof flags.limit === 'string' ? parseInt(flags.limit, 10) : undefined;
|
|
47
|
+
const { calls, total } = unwrap(await client.call('llm.getCalls', { sessionId, limit }));
|
|
48
|
+
if (json) {
|
|
49
|
+
console.log(JSON.stringify({ calls, total }, null, 2));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (calls.length === 0) {
|
|
53
|
+
console.log('No LLM calls found.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const typedCalls = calls.filter(isLLMCallLogEntry);
|
|
57
|
+
console.log(formatTable(['Time', 'Status', 'Model', 'Duration', 'Tokens', 'Cost', 'Agent'], typedCalls.map((c) => {
|
|
58
|
+
const time = new Date(c.createdAt).toLocaleTimeString();
|
|
59
|
+
const duration = c.durationMs !== undefined ? `${(c.durationMs / 1000).toFixed(1)}s` : '-';
|
|
60
|
+
const tokens = c.metrics ? `${c.metrics.promptTokens}/${c.metrics.completionTokens}` : '-';
|
|
61
|
+
const cost = c.metrics?.cost !== undefined ? `$${c.metrics.cost.toFixed(4)}` : '-';
|
|
62
|
+
return [time, c.status, c.request.model, duration, tokens, cost, String(c.agentId)];
|
|
63
|
+
})));
|
|
64
|
+
console.log(`\nTotal: ${total} calls`);
|
|
65
|
+
}
|
|
66
|
+
export async function llmCallCommand(client, sessionId, callId, json) {
|
|
67
|
+
const callData = unwrap(await client.call('llm.getCall', { sessionId, callId }));
|
|
68
|
+
if (json) {
|
|
69
|
+
console.log(JSON.stringify(callData, null, 2));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (!isLLMCallLogEntry(callData)) {
|
|
73
|
+
console.error('Invalid LLM call data.');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
console.log(formatLLMCallDetail(callData));
|
|
77
|
+
}
|
|
78
|
+
export async function presetAgentsCommand(client, sessionId, json) {
|
|
79
|
+
const result = unwrap(await client.call('presets.getAgents', { sessionId }));
|
|
80
|
+
const agents = result.agents;
|
|
81
|
+
if (json) {
|
|
82
|
+
console.log(JSON.stringify(agents, null, 2));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (agents.length === 0) {
|
|
86
|
+
console.log('No agent definitions found.');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log(formatTable(['Name', 'Spawnable By', 'Has Input Schema'], agents.map((a) => [a.name, a.spawnableBy.join(', '), a.hasInputSchema ? 'yes' : 'no'])));
|
|
90
|
+
}
|
|
91
|
+
export async function debugSendCommand(client, sessionId, agentId, content, flags, json) {
|
|
92
|
+
const { messageId } = unwrap(await client.call('user-chat.sendMessage', { sessionId, agentId: AgentId(agentId), content }));
|
|
93
|
+
if (json) {
|
|
94
|
+
console.log(JSON.stringify({ messageId }));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
console.log(`Message sent: ${messageId}`);
|
|
98
|
+
}
|
|
99
|
+
export async function spawnAgentCommand(client, sessionId, definitionName, parentId, flags, json) {
|
|
100
|
+
const message = typeof flags.message === 'string' ? flags.message : undefined;
|
|
101
|
+
const { agentId } = unwrap(await client.call('agents.spawn', { sessionId, definitionName, parentId: AgentId(parentId), message }));
|
|
102
|
+
if (json) {
|
|
103
|
+
console.log(JSON.stringify({ agentId }));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log(`Agent spawned: ${agentId}`);
|
|
107
|
+
}
|
|
108
|
+
// ============================================================================
|
|
109
|
+
// Event-sourced Projection Commands
|
|
110
|
+
// ============================================================================
|
|
111
|
+
export async function agentsCommand(client, sessionId, json) {
|
|
112
|
+
const { agentTree: agentTreeState } = await loadProjections(client, sessionId);
|
|
113
|
+
const tree = buildAgentTreeFromProjection(agentTreeState);
|
|
114
|
+
if (json) {
|
|
115
|
+
console.log(JSON.stringify(tree, null, 2));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (tree.length === 0) {
|
|
119
|
+
console.log('No agents.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
console.log(formatAgentTree(tree));
|
|
123
|
+
}
|
|
124
|
+
export async function agentCommand(client, sessionId, agentId, json) {
|
|
125
|
+
const { agentDetail: agentDetailState } = await loadProjections(client, sessionId);
|
|
126
|
+
const detail = getAgentDetail(agentDetailState, AgentId(agentId));
|
|
127
|
+
if (!detail) {
|
|
128
|
+
console.error(`Agent not found: ${agentId}`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
if (json) {
|
|
132
|
+
console.log(JSON.stringify(detail, null, 2));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
console.log(formatAgentDetail(detail));
|
|
136
|
+
}
|
|
137
|
+
export async function mailboxCommand(client, sessionId, json) {
|
|
138
|
+
const { registry, events } = await loadProjections(client, sessionId);
|
|
139
|
+
let mailboxState = createMailboxState();
|
|
140
|
+
for (const event of events) {
|
|
141
|
+
mailboxState = applyEventToMailbox(mailboxState, event, registry);
|
|
142
|
+
}
|
|
143
|
+
const messages = getMailboxMessages(mailboxState);
|
|
144
|
+
if (json) {
|
|
145
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (messages.length === 0) {
|
|
149
|
+
console.log('No mailbox messages.');
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
for (const msg of messages) {
|
|
153
|
+
console.log(formatMailboxMessage(msg));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export async function timelineCommand(client, sessionId, json) {
|
|
157
|
+
const { registry, events } = await loadProjections(client, sessionId);
|
|
158
|
+
let timelineState = createTimelineState();
|
|
159
|
+
for (const event of events) {
|
|
160
|
+
timelineState = applyEventToTimeline(timelineState, event, registry);
|
|
161
|
+
}
|
|
162
|
+
const items = getTimelineItems(timelineState, registry);
|
|
163
|
+
if (json) {
|
|
164
|
+
console.log(JSON.stringify(items, null, 2));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (items.length === 0) {
|
|
168
|
+
console.log('No timeline items.');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
for (const item of items) {
|
|
172
|
+
console.log(formatTimelineItem(item));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export async function metricsCommand(client, sessionId, json) {
|
|
176
|
+
const { registry, events } = await loadProjections(client, sessionId);
|
|
177
|
+
let metricsState = createMetricsState();
|
|
178
|
+
for (const event of events) {
|
|
179
|
+
metricsState = applyEventToMetrics(metricsState, event);
|
|
180
|
+
}
|
|
181
|
+
const metrics = metricsStateToResponse(metricsState, registry.count);
|
|
182
|
+
if (json) {
|
|
183
|
+
console.log(JSON.stringify(metrics, null, 2));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
console.log(formatMetrics(metrics));
|
|
187
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RpcClient } from '@roj-ai/shared/rpc';
|
|
2
|
+
export declare function messagesCommand(client: RpcClient, sessionId: string, json: boolean): Promise<void>;
|
|
3
|
+
export declare function sendCommand(client: RpcClient, baseUrl: string, sessionId: string, content: string, wait: boolean, json: boolean): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AASnD,wBAAsB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBxG;AAED,wBAAsB,WAAW,CAChC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAqDf"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AgentId } from '@roj-ai/shared';
|
|
2
|
+
import { connectWebSocket } from '../client.js';
|
|
3
|
+
import { formatChatMessage } from '../repl/formatter.js';
|
|
4
|
+
import { unwrap } from '../unwrap.js';
|
|
5
|
+
function isChatMessage(msg) {
|
|
6
|
+
return typeof msg === 'object' && msg !== null && 'type' in msg && 'timestamp' in msg;
|
|
7
|
+
}
|
|
8
|
+
export async function messagesCommand(client, sessionId, json) {
|
|
9
|
+
const { messages: rawMessages } = unwrap(await client.call('user-chat.getMessages', { sessionId }));
|
|
10
|
+
const messages = rawMessages.filter(isChatMessage);
|
|
11
|
+
if (json) {
|
|
12
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (messages.length === 0) {
|
|
16
|
+
console.log('No messages.');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
for (const msg of messages) {
|
|
20
|
+
console.log(formatChatMessage(msg));
|
|
21
|
+
console.log();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function sendCommand(client, baseUrl, sessionId, content, wait, json) {
|
|
25
|
+
const session = unwrap(await client.call('sessions.get', { sessionId }));
|
|
26
|
+
if (!session.entryAgentId) {
|
|
27
|
+
console.error('No entry agent found for session.');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
const { messageId } = unwrap(await client.call('user-chat.sendMessage', { sessionId, agentId: AgentId(session.entryAgentId), content }));
|
|
31
|
+
if (!wait) {
|
|
32
|
+
if (json) {
|
|
33
|
+
console.log(JSON.stringify({ messageId }));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(`Message sent: ${messageId}`);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Wait for agent response via WebSocket
|
|
41
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
42
|
+
const timeout = setTimeout(() => {
|
|
43
|
+
connection.disconnect();
|
|
44
|
+
reject(new Error('Timeout waiting for agent response'));
|
|
45
|
+
}, 120_000);
|
|
46
|
+
const connection = connectWebSocket(baseUrl, sessionId, {
|
|
47
|
+
agentMessage: (payload) => {
|
|
48
|
+
if (typeof payload !== 'object' || payload === null)
|
|
49
|
+
return;
|
|
50
|
+
const input = payload;
|
|
51
|
+
if (typeof input.content !== 'string')
|
|
52
|
+
return;
|
|
53
|
+
clearTimeout(timeout);
|
|
54
|
+
connection.disconnect();
|
|
55
|
+
resolve(input.content);
|
|
56
|
+
},
|
|
57
|
+
error: (payload) => {
|
|
58
|
+
if (typeof payload !== 'object' || payload === null)
|
|
59
|
+
return;
|
|
60
|
+
const input = payload;
|
|
61
|
+
if (typeof input.message !== 'string')
|
|
62
|
+
return;
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
connection.disconnect();
|
|
65
|
+
reject(new Error(input.message));
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
connection.connect().catch(reject);
|
|
69
|
+
});
|
|
70
|
+
const response = await responsePromise;
|
|
71
|
+
if (json) {
|
|
72
|
+
console.log(JSON.stringify({ messageId, response }));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.log(response);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/commands/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAInD,wBAAsB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBpF"}
|