@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.
@@ -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 (0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/runs${qs}`);
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
- (0, output_1.printJson)(result);
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
- const table = new cli_table3_1.default({
157
- head: [
158
- chalk_1.default.bold('Run ID'),
159
- chalk_1.default.bold('Agent'),
160
- chalk_1.default.bold('Status'),
161
- chalk_1.default.bold('Duration'),
162
- chalk_1.default.bold('Source'),
163
- chalk_1.default.bold('Started'),
164
- chalk_1.default.bold('Error'),
165
- ],
166
- });
167
- result.runs.forEach((r) => {
168
- const errorPreview = r.error_message
169
- ? chalk_1.default.red(r.error_message.length > 50 ? r.error_message.slice(0, 50) + '...' : r.error_message)
170
- : chalk_1.default.gray('-');
171
- table.push([
172
- r.id.slice(0, 8),
173
- `${r.agent_name}@${r.agent_version}`,
174
- statusColor(r.status),
175
- formatDuration(r.duration_ms),
176
- r.trigger_source ?? '-',
177
- formatDate(r.started_at || r.created_at),
178
- errorPreview,
179
- ]);
180
- });
181
- process.stdout.write(table.toString() + '\n');
182
- if (result.total > result.runs.length) {
183
- process.stdout.write(chalk_1.default.gray(`\nShowing ${result.runs.length} of ${result.total} runs. Use --limit to see more.\n`));
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
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchagent/cli",
3
- "version": "0.3.112",
3
+ "version": "0.3.114",
4
4
  "description": "Command-line interface for orchagent — deploy and run AI agents for your team",
5
5
  "license": "MIT",
6
6
  "author": "orchagent <hello@orchagent.io>",