@orchagent/cli 0.3.112 → 0.3.114
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/commands/logs.js +128 -32
- package/dist/commands/service.js +9 -0
- package/package.json +1 -1
package/dist/commands/logs.js
CHANGED
|
@@ -79,6 +79,57 @@ function isUuid(value) {
|
|
|
79
79
|
function isShortUuid(value) {
|
|
80
80
|
return /^[0-9a-f]{7,}$/i.test(value) && !value.includes('/');
|
|
81
81
|
}
|
|
82
|
+
function severityColor(severity, message) {
|
|
83
|
+
switch (severity.toUpperCase()) {
|
|
84
|
+
case 'ERROR':
|
|
85
|
+
case 'CRITICAL':
|
|
86
|
+
return chalk_1.default.red(message);
|
|
87
|
+
case 'WARNING':
|
|
88
|
+
return chalk_1.default.yellow(message);
|
|
89
|
+
case 'INFO':
|
|
90
|
+
return chalk_1.default.white(message);
|
|
91
|
+
default:
|
|
92
|
+
return chalk_1.default.gray(message);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Find an always-on service for a given agent name in the workspace. */
|
|
96
|
+
async function findServiceForAgent(config, workspaceId, agentName) {
|
|
97
|
+
try {
|
|
98
|
+
const result = await (0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/services?limit=100`);
|
|
99
|
+
return result.services.find((s) => s.agent_name === agentName && s.current_state !== 'deleted') ?? null;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Fetch and display logs from an always-on service. */
|
|
106
|
+
async function showServiceLogs(config, workspaceId, service, limit, json) {
|
|
107
|
+
const params = new URLSearchParams();
|
|
108
|
+
params.set('limit', limit);
|
|
109
|
+
const qs = `?${params.toString()}`;
|
|
110
|
+
const result = await (0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/services/${service.id}/logs${qs}`);
|
|
111
|
+
if (json) {
|
|
112
|
+
(0, output_1.printJson)({
|
|
113
|
+
service_id: service.id,
|
|
114
|
+
service_name: service.service_name,
|
|
115
|
+
agent_name: service.agent_name,
|
|
116
|
+
agent_version: service.agent_version,
|
|
117
|
+
logs: result.logs,
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (!result.logs.length) {
|
|
122
|
+
process.stdout.write(chalk_1.default.gray('No service logs available yet.\n'));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
for (const entry of result.logs) {
|
|
126
|
+
const ts = entry.timestamp
|
|
127
|
+
? new Date(entry.timestamp).toISOString().replace('T', ' ').replace('Z', '')
|
|
128
|
+
: '???';
|
|
129
|
+
const sev = entry.severity.padEnd(7);
|
|
130
|
+
process.stdout.write(`${chalk_1.default.gray(ts)} ${severityColor(entry.severity, sev)} ${entry.message}\n`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
82
133
|
// ============================================
|
|
83
134
|
// COMMAND REGISTRATION
|
|
84
135
|
// ============================================
|
|
@@ -89,6 +140,7 @@ function registerLogsCommand(program) {
|
|
|
89
140
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
90
141
|
.option('--status <status>', 'Filter by status: running, completed, failed, timeout')
|
|
91
142
|
.option('--limit <n>', 'Number of runs to show (default: 20)', '20')
|
|
143
|
+
.option('--live', 'Show live logs from always-on service (skips run history)')
|
|
92
144
|
.option('--json', 'Output as JSON')
|
|
93
145
|
.action(async (target, options) => {
|
|
94
146
|
const config = await (0, config_1.getResolvedConfig)();
|
|
@@ -131,6 +183,24 @@ async function resolveShortRunId(config, workspaceId, shortId) {
|
|
|
131
183
|
// LIST RUNS
|
|
132
184
|
// ============================================
|
|
133
185
|
async function listRuns(config, workspaceId, agentName, options) {
|
|
186
|
+
// When filtering by agent name, check for an always-on service in parallel
|
|
187
|
+
const servicePromise = agentName
|
|
188
|
+
? findServiceForAgent(config, workspaceId, agentName)
|
|
189
|
+
: Promise.resolve(null);
|
|
190
|
+
// --live: skip run history and show only service logs
|
|
191
|
+
if (options.live) {
|
|
192
|
+
const service = await servicePromise;
|
|
193
|
+
if (!service) {
|
|
194
|
+
const msg = agentName
|
|
195
|
+
? `No always-on service found for agent '${agentName}'.`
|
|
196
|
+
: 'Specify an agent name with --live (e.g. orch logs my-agent --live).';
|
|
197
|
+
throw new errors_1.CliError(msg);
|
|
198
|
+
}
|
|
199
|
+
process.stdout.write(chalk_1.default.bold(`\nLive logs: ${service.service_name}`) +
|
|
200
|
+
` (${service.agent_name}@${service.agent_version})\n\n`);
|
|
201
|
+
await showServiceLogs(config, workspaceId, service, options.limit ?? '100', options.json);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
134
204
|
const params = new URLSearchParams();
|
|
135
205
|
if (agentName)
|
|
136
206
|
params.set('agent_name', agentName);
|
|
@@ -139,12 +209,24 @@ async function listRuns(config, workspaceId, agentName, options) {
|
|
|
139
209
|
const limit = parseInt(options.limit ?? '20', 10);
|
|
140
210
|
params.set('limit', String(Math.min(Math.max(1, limit), 200)));
|
|
141
211
|
const qs = params.toString() ? `?${params.toString()}` : '';
|
|
142
|
-
const result = await
|
|
212
|
+
const [result, service] = await Promise.all([
|
|
213
|
+
(0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/runs${qs}`),
|
|
214
|
+
servicePromise,
|
|
215
|
+
]);
|
|
143
216
|
if (options.json) {
|
|
144
|
-
|
|
217
|
+
const payload = { ...result };
|
|
218
|
+
if (service) {
|
|
219
|
+
payload.service = {
|
|
220
|
+
id: service.id,
|
|
221
|
+
service_name: service.service_name,
|
|
222
|
+
current_state: service.current_state,
|
|
223
|
+
health_status: service.health_status,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
(0, output_1.printJson)(payload);
|
|
145
227
|
return;
|
|
146
228
|
}
|
|
147
|
-
if (result.runs.length === 0) {
|
|
229
|
+
if (result.runs.length === 0 && !service) {
|
|
148
230
|
if (agentName) {
|
|
149
231
|
process.stdout.write(`No runs found for agent '${agentName}'.\n`);
|
|
150
232
|
}
|
|
@@ -153,36 +235,50 @@ async function listRuns(config, workspaceId, agentName, options) {
|
|
|
153
235
|
}
|
|
154
236
|
return;
|
|
155
237
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
process.stdout.write(
|
|
238
|
+
// Show runs table if there are any
|
|
239
|
+
if (result.runs.length > 0) {
|
|
240
|
+
const table = new cli_table3_1.default({
|
|
241
|
+
head: [
|
|
242
|
+
chalk_1.default.bold('Run ID'),
|
|
243
|
+
chalk_1.default.bold('Agent'),
|
|
244
|
+
chalk_1.default.bold('Status'),
|
|
245
|
+
chalk_1.default.bold('Duration'),
|
|
246
|
+
chalk_1.default.bold('Source'),
|
|
247
|
+
chalk_1.default.bold('Started'),
|
|
248
|
+
chalk_1.default.bold('Error'),
|
|
249
|
+
],
|
|
250
|
+
});
|
|
251
|
+
result.runs.forEach((r) => {
|
|
252
|
+
const errorPreview = r.error_message
|
|
253
|
+
? chalk_1.default.red(r.error_message.length > 50 ? r.error_message.slice(0, 50) + '...' : r.error_message)
|
|
254
|
+
: chalk_1.default.gray('-');
|
|
255
|
+
table.push([
|
|
256
|
+
r.id.slice(0, 8),
|
|
257
|
+
`${r.agent_name}@${r.agent_version}`,
|
|
258
|
+
statusColor(r.status),
|
|
259
|
+
formatDuration(r.duration_ms),
|
|
260
|
+
r.trigger_source ?? '-',
|
|
261
|
+
formatDate(r.started_at || r.created_at),
|
|
262
|
+
errorPreview,
|
|
263
|
+
]);
|
|
264
|
+
});
|
|
265
|
+
process.stdout.write(table.toString() + '\n');
|
|
266
|
+
if (result.total > result.runs.length) {
|
|
267
|
+
process.stdout.write(chalk_1.default.gray(`\nShowing ${result.runs.length} of ${result.total} runs. Use --limit to see more.\n`));
|
|
268
|
+
}
|
|
269
|
+
process.stdout.write(chalk_1.default.gray('\nView detailed logs for a run: orch logs <run-id> · Replay a run: orch replay <run-id>\n'));
|
|
270
|
+
}
|
|
271
|
+
// If an always-on service exists for this agent, show its live logs
|
|
272
|
+
if (service) {
|
|
273
|
+
if (result.runs.length > 0) {
|
|
274
|
+
process.stdout.write('\n');
|
|
275
|
+
}
|
|
276
|
+
process.stdout.write(chalk_1.default.bold.cyan(`--- always-on service: ${service.service_name} ---`) + '\n' +
|
|
277
|
+
`State: ${statusColor(service.current_state)} ` +
|
|
278
|
+
`Agent: ${service.agent_name}@${service.agent_version}\n\n`);
|
|
279
|
+
await showServiceLogs(config, workspaceId, service, '50');
|
|
280
|
+
process.stdout.write(chalk_1.default.gray(`\nFull service logs: orch logs ${agentName} --live · More options: orch service logs ${service.id}\n`));
|
|
184
281
|
}
|
|
185
|
-
process.stdout.write(chalk_1.default.gray('\nView detailed logs for a run: orch logs <run-id> · Replay a run: orch replay <run-id>\n'));
|
|
186
282
|
}
|
|
187
283
|
// ============================================
|
|
188
284
|
// SHOW RUN LOGS
|
package/dist/commands/service.js
CHANGED
|
@@ -203,10 +203,16 @@ function registerServiceCommand(program) {
|
|
|
203
203
|
process.stdout.write(` ${chalk_1.default.bold('Agent:')} ${svc.agent_name}@${svc.agent_version}\n`);
|
|
204
204
|
process.stdout.write(` ${chalk_1.default.bold('State:')} ${stateColor(svc.current_state)}\n`);
|
|
205
205
|
process.stdout.write(` ${chalk_1.default.bold('Tier:')} ${formatServiceTier(svc)}\n`);
|
|
206
|
+
if (svc.service_url) {
|
|
207
|
+
process.stdout.write(` ${chalk_1.default.bold('URL:')} ${chalk_1.default.cyan(svc.service_url)}\n`);
|
|
208
|
+
}
|
|
206
209
|
if (options.pin) {
|
|
207
210
|
process.stdout.write(` ${chalk_1.default.bold('Pinned:')} ${chalk_1.default.yellow(`yes (won't auto-update on publish)`)}\n`);
|
|
208
211
|
}
|
|
209
212
|
process.stdout.write(`\n`);
|
|
213
|
+
if (svc.service_url) {
|
|
214
|
+
process.stdout.write(chalk_1.default.gray(`Public URL: ${svc.service_url}\n`));
|
|
215
|
+
}
|
|
210
216
|
process.stdout.write(chalk_1.default.gray(`View logs: orch service logs ${svc.id}\n`));
|
|
211
217
|
}
|
|
212
218
|
catch (e) {
|
|
@@ -357,6 +363,9 @@ function registerServiceCommand(program) {
|
|
|
357
363
|
process.stdout.write(` Agent: ${svc.agent_name}@${svc.agent_version}\n`);
|
|
358
364
|
process.stdout.write(` State: ${stateColor(svc.current_state)}\n`);
|
|
359
365
|
process.stdout.write(` Health: ${healthColor(svc.health_status)}\n`);
|
|
366
|
+
if (svc.service_url) {
|
|
367
|
+
process.stdout.write(` URL: ${chalk_1.default.cyan(svc.service_url)}\n`);
|
|
368
|
+
}
|
|
360
369
|
if (svc.auto_paused_at) {
|
|
361
370
|
process.stdout.write(` ${chalk_1.default.bgRed.white(' CRASH-LOOP ')} auto-paused at ${formatDate(svc.auto_paused_at)}\n`);
|
|
362
371
|
}
|
package/package.json
CHANGED