@agentuity/cli 1.0.63 → 1.0.64
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/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +20 -68
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/index.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/index.js +12 -1
- package/dist/cmd/cloud/sandbox/job/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/logs.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/job/logs.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/job/logs.js +124 -0
- package/dist/cmd/cloud/sandbox/job/logs.js.map +1 -0
- package/dist/utils/stream-url.d.ts +23 -0
- package/dist/utils/stream-url.d.ts.map +1 -0
- package/dist/utils/stream-url.js +153 -0
- package/dist/utils/stream-url.js.map +1 -0
- package/package.json +6 -6
- package/src/cmd/cloud/sandbox/exec.ts +20 -115
- package/src/cmd/cloud/sandbox/job/index.ts +12 -1
- package/src/cmd/cloud/sandbox/job/logs.ts +139 -0
- package/src/utils/stream-url.ts +226 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../../src/cmd/cloud/sandbox/exec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../../src/cmd/cloud/sandbox/exec.ts"],"names":[],"mappings":"AAoCA,eAAO,MAAM,cAAc,sCAwQzB,CAAC;AAgBH,eAAe,cAAc,CAAC"}
|
|
@@ -5,8 +5,8 @@ import { createCommand } from '../../../types';
|
|
|
5
5
|
import * as tui from '../../../tui';
|
|
6
6
|
import { createSandboxClient } from './util';
|
|
7
7
|
import { getCommand } from '../../../command-prefix';
|
|
8
|
-
import { sandboxExecute, executionGet,
|
|
9
|
-
|
|
8
|
+
import { sandboxExecute, executionGet, sandboxResolve } from '@agentuity/server';
|
|
9
|
+
import { streamUrlToWritable } from '../../../utils/stream-url';
|
|
10
10
|
const EXECUTION_WAIT_DURATION = '5m';
|
|
11
11
|
const SandboxExecResponseSchema = z.object({
|
|
12
12
|
executionId: z.string().describe('Unique execution identifier'),
|
|
@@ -64,15 +64,11 @@ export const execSubcommand = createCommand({
|
|
|
64
64
|
},
|
|
65
65
|
async handler(ctx) {
|
|
66
66
|
const { args, opts, options, auth, logger, apiClient } = ctx;
|
|
67
|
-
// Validate timeout format if provided (fail fast before any network calls)
|
|
68
67
|
if (opts.timeout) {
|
|
69
|
-
// Go's time.ParseDuration accepts "0" or one-or-more number+unit tokens.
|
|
70
|
-
// Valid units: ns, us, µs (U+00B5), μs (U+03BC), ms, s, m, h
|
|
71
68
|
if (!/^(?:0|(\d+(\.\d+)?(ns|us|[µμ]s|ms|s|m|h))+)$/.test(opts.timeout)) {
|
|
72
69
|
tui.fatal(`Invalid timeout format '${opts.timeout}': expected duration like '5s', '1m', '1h', '300ms'`, ErrorCode.INVALID_ARGUMENT);
|
|
73
70
|
}
|
|
74
71
|
}
|
|
75
|
-
// Resolve sandbox to get region and orgId using CLI API
|
|
76
72
|
const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
|
|
77
73
|
const { region, orgId } = sandboxInfo;
|
|
78
74
|
const client = createSandboxClient(logger, auth, region);
|
|
@@ -104,11 +100,8 @@ export const execSubcommand = createCommand({
|
|
|
104
100
|
const streamAbortController = new AbortController();
|
|
105
101
|
const streamPromises = [];
|
|
106
102
|
const streamLabels = [];
|
|
107
|
-
// Check if stdout and stderr are the same stream (combined output)
|
|
108
103
|
const isCombinedOutput = stdoutStreamUrl && stderrStreamUrl && stdoutStreamUrl === stderrStreamUrl;
|
|
109
104
|
logger.debug('[exec] stream mode: combined=%s, stdoutUrl=%s, stderrUrl=%s', isCombinedOutput, stdoutStreamUrl ?? 'none', stderrStreamUrl ?? 'none');
|
|
110
|
-
// Set up stream capture — in JSON mode, capture to buffers;
|
|
111
|
-
// when streams are separate, capture stdout/stderr independently
|
|
112
105
|
const outputChunks = [];
|
|
113
106
|
const stdoutChunks = [];
|
|
114
107
|
const stderrChunks = [];
|
|
@@ -116,12 +109,10 @@ export const execSubcommand = createCommand({
|
|
|
116
109
|
let stderrWritable;
|
|
117
110
|
if (options.json) {
|
|
118
111
|
if (isCombinedOutput) {
|
|
119
|
-
// Combined stream: can't distinguish stdout from stderr
|
|
120
112
|
stdoutWritable = createCaptureStream((chunk) => outputChunks.push(chunk));
|
|
121
113
|
stderrWritable = createCaptureStream((chunk) => outputChunks.push(chunk));
|
|
122
114
|
}
|
|
123
115
|
else {
|
|
124
|
-
// Separate streams: capture each independently and also to combined output
|
|
125
116
|
stdoutWritable = createCaptureStream((chunk) => {
|
|
126
117
|
stdoutChunks.push(chunk);
|
|
127
118
|
outputChunks.push(chunk);
|
|
@@ -137,27 +128,38 @@ export const execSubcommand = createCommand({
|
|
|
137
128
|
stderrWritable = process.stderr;
|
|
138
129
|
}
|
|
139
130
|
if (isCombinedOutput) {
|
|
140
|
-
// Stream combined output to stdout only to avoid duplicates
|
|
141
131
|
logger.debug('[exec] starting combined stream: %s', stdoutStreamUrl);
|
|
142
132
|
streamLabels.push('combined');
|
|
143
|
-
streamPromises.push(streamUrlToWritable(
|
|
133
|
+
streamPromises.push(streamUrlToWritable(stdoutStreamUrl, stdoutWritable, logger, {
|
|
134
|
+
signal: streamAbortController.signal,
|
|
135
|
+
label: 'combined',
|
|
136
|
+
raw: true,
|
|
137
|
+
v2: true,
|
|
138
|
+
}).then(() => { }));
|
|
144
139
|
}
|
|
145
140
|
else {
|
|
146
141
|
if (stdoutStreamUrl) {
|
|
147
142
|
logger.debug('[exec] starting stdout stream: %s', stdoutStreamUrl);
|
|
148
143
|
streamLabels.push('stdout');
|
|
149
|
-
streamPromises.push(streamUrlToWritable(
|
|
144
|
+
streamPromises.push(streamUrlToWritable(stdoutStreamUrl, stdoutWritable, logger, {
|
|
145
|
+
signal: streamAbortController.signal,
|
|
146
|
+
label: 'stdout',
|
|
147
|
+
raw: true,
|
|
148
|
+
v2: true,
|
|
149
|
+
}).then(() => { }));
|
|
150
150
|
}
|
|
151
151
|
if (stderrStreamUrl) {
|
|
152
152
|
logger.debug('[exec] starting stderr stream: %s', stderrStreamUrl);
|
|
153
153
|
streamLabels.push('stderr');
|
|
154
|
-
streamPromises.push(streamUrlToWritable(
|
|
154
|
+
streamPromises.push(streamUrlToWritable(stderrStreamUrl, stderrWritable, logger, {
|
|
155
|
+
signal: streamAbortController.signal,
|
|
156
|
+
label: 'stderr',
|
|
157
|
+
raw: true,
|
|
158
|
+
v2: true,
|
|
159
|
+
}).then(() => { }));
|
|
155
160
|
}
|
|
156
161
|
}
|
|
157
162
|
logger.debug('[exec] %d stream(s) started [%s], now long-polling executionGet', streamPromises.length, streamLabels.join(', '));
|
|
158
|
-
// Use server-side long-polling to wait for execution completion
|
|
159
|
-
// This is more efficient than client-side polling and provides immediate
|
|
160
|
-
// error detection if the sandbox is terminated
|
|
161
163
|
let finalExecution;
|
|
162
164
|
const pollStart = Date.now();
|
|
163
165
|
try {
|
|
@@ -168,17 +170,10 @@ export const execSubcommand = createCommand({
|
|
|
168
170
|
});
|
|
169
171
|
}
|
|
170
172
|
catch (err) {
|
|
171
|
-
// Abort any active stream readers before rethrowing so they
|
|
172
|
-
// don't keep running after the execution poll has failed.
|
|
173
173
|
streamAbortController.abort();
|
|
174
174
|
throw err;
|
|
175
175
|
}
|
|
176
176
|
logger.debug('[exec] executionGet returned in %dms: status=%s, exitCode=%s', Date.now() - pollStart, finalExecution.status, finalExecution.exitCode ?? 'undefined');
|
|
177
|
-
// Wait for all streams to reach EOF (Pulse blocks until true EOF).
|
|
178
|
-
// Safety: execution is confirmed complete so all data has been written
|
|
179
|
-
// and complete/v2 sent. If Pulse doesn't close the response within
|
|
180
|
-
// a grace period (e.g. cross-server routing delay, stale metadata
|
|
181
|
-
// cache), abort the streams to prevent an indefinite hang.
|
|
182
177
|
if (streamPromises.length > 0) {
|
|
183
178
|
logger.debug('[exec] waiting for %d stream(s) to EOF', streamPromises.length);
|
|
184
179
|
const streamWaitStart = Date.now();
|
|
@@ -196,7 +191,6 @@ export const execSubcommand = createCommand({
|
|
|
196
191
|
}
|
|
197
192
|
logger.debug('[exec] all streams done in %dms (graceTriggered=%s)', Date.now() - streamWaitStart, graceTriggered);
|
|
198
193
|
}
|
|
199
|
-
// Ensure stdout is fully flushed before continuing
|
|
200
194
|
if (!options.json && process.stdout.writable) {
|
|
201
195
|
await new Promise((resolve) => {
|
|
202
196
|
if (process.stdout.writableNeedDrain) {
|
|
@@ -247,48 +241,6 @@ export const execSubcommand = createCommand({
|
|
|
247
241
|
}
|
|
248
242
|
},
|
|
249
243
|
});
|
|
250
|
-
async function streamUrlToWritable(label, url, writable, signal, logger) {
|
|
251
|
-
const streamStart = Date.now();
|
|
252
|
-
try {
|
|
253
|
-
// Signal to Pulse that this is a v2 stream so it waits for v2 metadata
|
|
254
|
-
// instead of falling back to the legacy download path on a short timeout.
|
|
255
|
-
const v2Url = new URL(url);
|
|
256
|
-
v2Url.searchParams.set('v', '2');
|
|
257
|
-
logger.debug('[stream:%s] fetching: %s', label, v2Url.href);
|
|
258
|
-
const response = await fetch(v2Url.href, { signal });
|
|
259
|
-
logger.debug('[stream:%s] response status=%d in %dms', label, response.status, Date.now() - streamStart);
|
|
260
|
-
if (!response.ok || !response.body) {
|
|
261
|
-
logger.debug('[stream:%s] not ok or no body — returning', label);
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
const reader = response.body.getReader();
|
|
265
|
-
let chunks = 0;
|
|
266
|
-
let totalBytes = 0;
|
|
267
|
-
// Read until EOF - Pulse will block until data is available
|
|
268
|
-
while (true) {
|
|
269
|
-
const { done, value } = await reader.read();
|
|
270
|
-
if (done) {
|
|
271
|
-
logger.debug('[stream:%s] EOF after %dms (%d chunks, %d bytes)', label, Date.now() - streamStart, chunks, totalBytes);
|
|
272
|
-
break;
|
|
273
|
-
}
|
|
274
|
-
if (value) {
|
|
275
|
-
chunks++;
|
|
276
|
-
totalBytes += value.length;
|
|
277
|
-
if (chunks <= 3 || chunks % 100 === 0) {
|
|
278
|
-
logger.debug('[stream:%s] chunk #%d: %d bytes (total: %d bytes, +%dms)', label, chunks, value.length, totalBytes, Date.now() - streamStart);
|
|
279
|
-
}
|
|
280
|
-
await writeAndDrain(writable, value);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
catch (err) {
|
|
285
|
-
if (err instanceof Error && err.name === 'AbortError') {
|
|
286
|
-
logger.debug('[stream:%s] aborted after %dms', label, Date.now() - streamStart);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
logger.debug('[stream:%s] error after %dms: %s', label, Date.now() - streamStart, err);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
244
|
function createCaptureStream(onChunk) {
|
|
293
245
|
return new Writable({
|
|
294
246
|
write(chunk, _encoding, callback) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../../src/cmd/cloud/sandbox/exec.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../../src/cmd/cloud/sandbox/exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/job/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/job/index.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,OAAO,yCA+BlB,CAAC;AAEH,eAAe,OAAO,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { getSubcommand } from './get';
|
|
|
3
3
|
import { listSubcommand } from './list';
|
|
4
4
|
import { createSubcommand } from './create';
|
|
5
5
|
import { destroySubcommand } from './destroy';
|
|
6
|
+
import { logsSubcommand } from './logs';
|
|
6
7
|
import { getCommand } from '../../../../command-prefix';
|
|
7
8
|
export const command = createCommand({
|
|
8
9
|
name: 'job',
|
|
@@ -22,8 +23,18 @@ export const command = createCommand({
|
|
|
22
23
|
command: getCommand('cloud sandbox job destroy sbx_abc123 job_xyz789'),
|
|
23
24
|
description: 'Terminate a running job',
|
|
24
25
|
},
|
|
26
|
+
{
|
|
27
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789'),
|
|
28
|
+
description: 'View logs from a job',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
subcommands: [
|
|
32
|
+
createSubcommand,
|
|
33
|
+
getSubcommand,
|
|
34
|
+
listSubcommand,
|
|
35
|
+
destroySubcommand,
|
|
36
|
+
logsSubcommand,
|
|
25
37
|
],
|
|
26
|
-
subcommands: [createSubcommand, getSubcommand, listSubcommand, destroySubcommand],
|
|
27
38
|
requires: { auth: true, org: true },
|
|
28
39
|
});
|
|
29
40
|
export default command;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/job/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACpC,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,CAAC,MAAM,CAAC;IACjB,WAAW,EAAE,qCAAqC;IAClD,IAAI,EAAE,CAAC,eAAe,CAAC;IACvB,QAAQ,EAAE;QACT;YACC,OAAO,EAAE,UAAU,CAAC,sDAAsD,CAAC;YAC3E,WAAW,EAAE,yBAAyB;SACtC;QACD;YACC,OAAO,EAAE,UAAU,CAAC,mCAAmC,CAAC;YACxD,WAAW,EAAE,yBAAyB;SACtC;QACD;YACC,OAAO,EAAE,UAAU,CAAC,iDAAiD,CAAC;YACtE,WAAW,EAAE,yBAAyB;SACtC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/job/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACpC,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,CAAC,MAAM,CAAC;IACjB,WAAW,EAAE,qCAAqC;IAClD,IAAI,EAAE,CAAC,eAAe,CAAC;IACvB,QAAQ,EAAE;QACT;YACC,OAAO,EAAE,UAAU,CAAC,sDAAsD,CAAC;YAC3E,WAAW,EAAE,yBAAyB;SACtC;QACD;YACC,OAAO,EAAE,UAAU,CAAC,mCAAmC,CAAC;YACxD,WAAW,EAAE,yBAAyB;SACtC;QACD;YACC,OAAO,EAAE,UAAU,CAAC,iDAAiD,CAAC;YACtE,WAAW,EAAE,yBAAyB;SACtC;QACD;YACC,OAAO,EAAE,UAAU,CAAC,8CAA8C,CAAC;YACnE,WAAW,EAAE,sBAAsB;SACnC;KACD;IACD,WAAW,EAAE;QACZ,gBAAgB;QAChB,aAAa;QACb,cAAc;QACd,iBAAiB;QACjB,cAAc;KACd;IACD,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE;CACnC,CAAC,CAAC;AAEH,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/job/logs.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,cAAc,4CAyHzB,CAAC;AAEH,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../../types';
|
|
3
|
+
import * as tui from '../../../../tui';
|
|
4
|
+
import { createSandboxClient } from '../util';
|
|
5
|
+
import { jobGet, sandboxResolve } from '@agentuity/server';
|
|
6
|
+
import { getCommand } from '../../../../command-prefix';
|
|
7
|
+
import { streamUrlToWritable } from '../../../../utils/stream-url';
|
|
8
|
+
const JobLogsResponseSchema = z.object({
|
|
9
|
+
jobId: z.string(),
|
|
10
|
+
sandboxId: z.string(),
|
|
11
|
+
status: z.string(),
|
|
12
|
+
bytesRead: z.number().optional(),
|
|
13
|
+
});
|
|
14
|
+
export const logsSubcommand = createSubcommand({
|
|
15
|
+
name: 'logs',
|
|
16
|
+
aliases: ['log'],
|
|
17
|
+
description: 'Stream logs from a sandbox job',
|
|
18
|
+
tags: ['read-only', 'slow', 'requires-auth'],
|
|
19
|
+
requires: { auth: true, apiClient: true },
|
|
20
|
+
examples: [
|
|
21
|
+
{
|
|
22
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789'),
|
|
23
|
+
description: 'View stdout logs from a job',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --stderr'),
|
|
27
|
+
description: 'View stderr logs from a job',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --follow'),
|
|
31
|
+
description: 'Follow logs in real-time',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --grep error'),
|
|
35
|
+
description: 'Filter logs containing "error"',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --tail 100'),
|
|
39
|
+
description: 'Show last 100 lines',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
schema: {
|
|
43
|
+
args: z.object({
|
|
44
|
+
sandboxId: z.string().describe('Sandbox ID'),
|
|
45
|
+
jobId: z.string().describe('Job ID'),
|
|
46
|
+
}),
|
|
47
|
+
options: z.object({
|
|
48
|
+
stderr: z.boolean().default(false).describe('Show stderr instead of stdout'),
|
|
49
|
+
follow: z.boolean().default(false).describe('Follow logs in real-time (for running jobs)'),
|
|
50
|
+
timestamps: z.boolean().default(true).describe('Show timestamps in output'),
|
|
51
|
+
grep: z.string().optional().describe('Filter logs by pattern (case-insensitive)'),
|
|
52
|
+
tail: z.coerce
|
|
53
|
+
.number()
|
|
54
|
+
.int()
|
|
55
|
+
.min(1)
|
|
56
|
+
.optional()
|
|
57
|
+
.describe('Number of lines to show from the end'),
|
|
58
|
+
}),
|
|
59
|
+
response: JobLogsResponseSchema,
|
|
60
|
+
},
|
|
61
|
+
async handler(ctx) {
|
|
62
|
+
const { args, opts, options, auth, logger, apiClient } = ctx;
|
|
63
|
+
const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
|
|
64
|
+
const { region, orgId } = sandboxInfo;
|
|
65
|
+
const client = createSandboxClient(logger, auth, region);
|
|
66
|
+
const job = await jobGet(client, {
|
|
67
|
+
sandboxId: args.sandboxId,
|
|
68
|
+
jobId: args.jobId,
|
|
69
|
+
orgId,
|
|
70
|
+
});
|
|
71
|
+
const streamUrl = opts.stderr ? job.stderrStreamUrl : job.stdoutStreamUrl;
|
|
72
|
+
const isJson = options.json ?? false;
|
|
73
|
+
if (!streamUrl) {
|
|
74
|
+
if (isJson) {
|
|
75
|
+
return {
|
|
76
|
+
jobId: job.jobId,
|
|
77
|
+
sandboxId: job.sandboxId,
|
|
78
|
+
status: job.status,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
tui.warning(`No ${opts.stderr ? 'stderr' : 'stdout'} stream available for job ${job.jobId}`);
|
|
82
|
+
if (job.status === 'pending') {
|
|
83
|
+
tui.info('Job is still pending - logs will be available once it starts running');
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
jobId: job.jobId,
|
|
87
|
+
sandboxId: job.sandboxId,
|
|
88
|
+
status: job.status,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (!isJson) {
|
|
92
|
+
tui.info(`Streaming ${opts.stderr ? 'stderr' : 'stdout'} for job ${tui.bold(job.jobId)} (status: ${job.status})`);
|
|
93
|
+
}
|
|
94
|
+
const abortController = new AbortController();
|
|
95
|
+
const handleSignal = () => {
|
|
96
|
+
abortController.abort();
|
|
97
|
+
};
|
|
98
|
+
process.on('SIGINT', handleSignal);
|
|
99
|
+
process.on('SIGTERM', handleSignal);
|
|
100
|
+
try {
|
|
101
|
+
const result = await streamUrlToWritable(streamUrl, process.stdout, logger, {
|
|
102
|
+
signal: abortController.signal,
|
|
103
|
+
follow: opts.follow,
|
|
104
|
+
timestamps: opts.timestamps ?? true,
|
|
105
|
+
grep: opts.grep,
|
|
106
|
+
tail: opts.tail,
|
|
107
|
+
json: isJson,
|
|
108
|
+
label: opts.stderr ? 'stderr' : 'stdout',
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
jobId: job.jobId,
|
|
112
|
+
sandboxId: job.sandboxId,
|
|
113
|
+
status: job.status,
|
|
114
|
+
bytesRead: result.bytesRead,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
process.off('SIGINT', handleSignal);
|
|
119
|
+
process.off('SIGTERM', handleSignal);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
export default logsSubcommand;
|
|
124
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/job/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Logger } from '@agentuity/core';
|
|
2
|
+
export interface StreamUrlOptions {
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
follow?: boolean;
|
|
5
|
+
timestamps?: boolean;
|
|
6
|
+
grep?: string;
|
|
7
|
+
tail?: number;
|
|
8
|
+
json?: boolean;
|
|
9
|
+
label?: string;
|
|
10
|
+
raw?: boolean;
|
|
11
|
+
v2?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface StreamUrlResult {
|
|
14
|
+
bytesRead: number;
|
|
15
|
+
chunks: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class StreamFetchError extends Error {
|
|
18
|
+
status: number;
|
|
19
|
+
statusText: string;
|
|
20
|
+
constructor(status: number, statusText: string, message: string);
|
|
21
|
+
}
|
|
22
|
+
export declare function streamUrlToWritable(url: string, writable: NodeJS.WritableStream, logger: Logger, options?: StreamUrlOptions): Promise<StreamUrlResult>;
|
|
23
|
+
//# sourceMappingURL=stream-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-url.d.ts","sourceRoot":"","sources":["../../src/utils/stream-url.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,EAAE,CAAC,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAElC,MAAM,EAAE,MAAM;IACd,UAAU,EAAE,MAAM;gBADlB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EACzB,OAAO,EAAE,MAAM;CAKhB;AAMD,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,CAAC,cAAc,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC,CA8K1B"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { writeAndDrain } from '@agentuity/server';
|
|
2
|
+
import * as tui from '../tui';
|
|
3
|
+
export class StreamFetchError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
statusText;
|
|
6
|
+
constructor(status, statusText, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.statusText = statusText;
|
|
10
|
+
this.name = 'StreamFetchError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function escapeRegExp(str) {
|
|
14
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
15
|
+
}
|
|
16
|
+
export async function streamUrlToWritable(url, writable, logger, options = {}) {
|
|
17
|
+
const { signal, follow, timestamps, grep, tail, json, label = 'stream', raw = false, v2 = false, } = options;
|
|
18
|
+
const streamStart = Date.now();
|
|
19
|
+
let bytesRead = 0;
|
|
20
|
+
let chunks = 0;
|
|
21
|
+
try {
|
|
22
|
+
const fetchUrl = new URL(url);
|
|
23
|
+
if (follow || v2) {
|
|
24
|
+
fetchUrl.searchParams.set('v', '2');
|
|
25
|
+
}
|
|
26
|
+
if (follow) {
|
|
27
|
+
fetchUrl.searchParams.set('follow', 'true');
|
|
28
|
+
}
|
|
29
|
+
const redactedUrl = fetchUrl.origin + fetchUrl.pathname + (fetchUrl.search ? '?REDACTED' : '');
|
|
30
|
+
logger.debug('[%s] fetching: %s', label, redactedUrl);
|
|
31
|
+
const response = await fetch(fetchUrl.href, { signal });
|
|
32
|
+
logger.debug('[%s] response status=%d in %dms', label, response.status, Date.now() - streamStart);
|
|
33
|
+
if (!response.ok || !response.body) {
|
|
34
|
+
logger.debug('[%s] not ok or no body', label);
|
|
35
|
+
if (!json) {
|
|
36
|
+
tui.error(`Failed to fetch stream: ${response.status} ${response.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
throw new StreamFetchError(response.status, response.statusText, `Failed to fetch stream: ${response.status} ${response.statusText}`);
|
|
39
|
+
}
|
|
40
|
+
const reader = response.body.getReader();
|
|
41
|
+
if (raw) {
|
|
42
|
+
while (true) {
|
|
43
|
+
const { done, value } = await reader.read();
|
|
44
|
+
if (done) {
|
|
45
|
+
logger.debug('[%s] EOF after %dms (%d chunks, %d bytes)', label, Date.now() - streamStart, chunks, bytesRead);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
if (value) {
|
|
49
|
+
chunks++;
|
|
50
|
+
bytesRead += value.length;
|
|
51
|
+
if (chunks <= 3 || chunks % 100 === 0) {
|
|
52
|
+
logger.debug('[%s] chunk #%d: %d bytes (total: %d bytes, +%dms)', label, chunks, value.length, bytesRead, Date.now() - streamStart);
|
|
53
|
+
}
|
|
54
|
+
await writeAndDrain(writable, value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const decoder = new TextDecoder();
|
|
60
|
+
let leftover = '';
|
|
61
|
+
const grepPattern = grep ? new RegExp(escapeRegExp(grep), 'i') : null;
|
|
62
|
+
const needsFiltering = tail !== undefined || grepPattern !== null;
|
|
63
|
+
const tailBuffer = [];
|
|
64
|
+
const maxTail = tail ?? Infinity;
|
|
65
|
+
const liveOutput = follow && needsFiltering;
|
|
66
|
+
const outputLine = async (line) => {
|
|
67
|
+
if (json) {
|
|
68
|
+
const obj = {
|
|
69
|
+
timestamp: new Date().toISOString(),
|
|
70
|
+
stream: label,
|
|
71
|
+
message: line,
|
|
72
|
+
};
|
|
73
|
+
await writeAndDrain(writable, Buffer.from(JSON.stringify(obj) + '\n'));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const formatted = timestamps ? formatLineWithTimestamp(line) : line;
|
|
77
|
+
await writeAndDrain(writable, Buffer.from(formatted + '\n'));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const processFilteredLine = async (line) => {
|
|
81
|
+
if (grepPattern && !grepPattern.test(line)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (tail !== undefined) {
|
|
85
|
+
tailBuffer.push(line);
|
|
86
|
+
if (tailBuffer.length > maxTail) {
|
|
87
|
+
tailBuffer.shift();
|
|
88
|
+
}
|
|
89
|
+
if (liveOutput) {
|
|
90
|
+
await outputLine(line);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
await outputLine(line);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
while (true) {
|
|
98
|
+
const { done, value } = await reader.read();
|
|
99
|
+
if (done) {
|
|
100
|
+
if (leftover) {
|
|
101
|
+
if (needsFiltering) {
|
|
102
|
+
await processFilteredLine(leftover);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
await outputLine(leftover);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
logger.debug('[%s] EOF after %dms (%d chunks, %d bytes)', label, Date.now() - streamStart, chunks, bytesRead);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (value) {
|
|
112
|
+
chunks++;
|
|
113
|
+
bytesRead += value.length;
|
|
114
|
+
const text = leftover + decoder.decode(value, { stream: true });
|
|
115
|
+
const lines = text.split('\n');
|
|
116
|
+
leftover = lines.pop() ?? '';
|
|
117
|
+
for (const line of lines) {
|
|
118
|
+
if (needsFiltering) {
|
|
119
|
+
await processFilteredLine(line);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
await outputLine(line);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!liveOutput && needsFiltering && tailBuffer.length > 0) {
|
|
128
|
+
for (const line of tailBuffer) {
|
|
129
|
+
await outputLine(line);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { bytesRead, chunks };
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
137
|
+
logger.debug('[%s] aborted after %dms', label, Date.now() - streamStart);
|
|
138
|
+
return { bytesRead, chunks };
|
|
139
|
+
}
|
|
140
|
+
logger.debug('[%s] error after %dms: %s', label, Date.now() - streamStart, err);
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function formatLineWithTimestamp(line) {
|
|
145
|
+
const timestamp = new Date().toLocaleTimeString('en-US', {
|
|
146
|
+
hour12: false,
|
|
147
|
+
hour: '2-digit',
|
|
148
|
+
minute: '2-digit',
|
|
149
|
+
second: '2-digit',
|
|
150
|
+
});
|
|
151
|
+
return `${tui.muted(timestamp)} ${line}`;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=stream-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-url.js","sourceRoot":"","sources":["../../src/utils/stream-url.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.64",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"prepublishOnly": "bun run clean && bun run build"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@agentuity/auth": "1.0.
|
|
45
|
-
"@agentuity/core": "1.0.
|
|
46
|
-
"@agentuity/server": "1.0.
|
|
44
|
+
"@agentuity/auth": "1.0.64",
|
|
45
|
+
"@agentuity/core": "1.0.64",
|
|
46
|
+
"@agentuity/server": "1.0.64",
|
|
47
47
|
"@datasert/cronjs-parser": "^1.4.0",
|
|
48
48
|
"@vitejs/plugin-react": "^5.1.2",
|
|
49
49
|
"acorn-loose": "^8.5.2",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"typescript": "^5.9.0",
|
|
60
60
|
"vite": "^7.2.7",
|
|
61
61
|
"zod": "^4.3.5",
|
|
62
|
-
"@agentuity/frontend": "1.0.
|
|
62
|
+
"@agentuity/frontend": "1.0.64"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@agentuity/test-utils": "1.0.
|
|
65
|
+
"@agentuity/test-utils": "1.0.64",
|
|
66
66
|
"@types/archiver": "^6.0.3",
|
|
67
67
|
"@types/bun": "latest",
|
|
68
68
|
"@types/tar-fs": "^2.0.4",
|
|
@@ -5,10 +5,9 @@ import { createCommand } from '../../../types';
|
|
|
5
5
|
import * as tui from '../../../tui';
|
|
6
6
|
import { createSandboxClient } from './util';
|
|
7
7
|
import { getCommand } from '../../../command-prefix';
|
|
8
|
-
import { sandboxExecute, executionGet,
|
|
9
|
-
import
|
|
8
|
+
import { sandboxExecute, executionGet, sandboxResolve } from '@agentuity/server';
|
|
9
|
+
import { streamUrlToWritable } from '../../../utils/stream-url';
|
|
10
10
|
|
|
11
|
-
// Server-side long-poll wait duration (max 5 minutes supported by server)
|
|
12
11
|
const EXECUTION_WAIT_DURATION = '5m';
|
|
13
12
|
|
|
14
13
|
const SandboxExecResponseSchema = z.object({
|
|
@@ -71,10 +70,7 @@ export const execSubcommand = createCommand({
|
|
|
71
70
|
async handler(ctx) {
|
|
72
71
|
const { args, opts, options, auth, logger, apiClient } = ctx;
|
|
73
72
|
|
|
74
|
-
// Validate timeout format if provided (fail fast before any network calls)
|
|
75
73
|
if (opts.timeout) {
|
|
76
|
-
// Go's time.ParseDuration accepts "0" or one-or-more number+unit tokens.
|
|
77
|
-
// Valid units: ns, us, µs (U+00B5), μs (U+03BC), ms, s, m, h
|
|
78
74
|
if (!/^(?:0|(\d+(\.\d+)?(ns|us|[µμ]s|ms|s|m|h))+)$/.test(opts.timeout)) {
|
|
79
75
|
tui.fatal(
|
|
80
76
|
`Invalid timeout format '${opts.timeout}': expected duration like '5s', '1m', '1h', '300ms'`,
|
|
@@ -83,7 +79,6 @@ export const execSubcommand = createCommand({
|
|
|
83
79
|
}
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
// Resolve sandbox to get region and orgId using CLI API
|
|
87
82
|
const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
|
|
88
83
|
const { region, orgId } = sandboxInfo;
|
|
89
84
|
|
|
@@ -127,7 +122,6 @@ export const execSubcommand = createCommand({
|
|
|
127
122
|
const streamPromises: Promise<void>[] = [];
|
|
128
123
|
const streamLabels: string[] = [];
|
|
129
124
|
|
|
130
|
-
// Check if stdout and stderr are the same stream (combined output)
|
|
131
125
|
const isCombinedOutput =
|
|
132
126
|
stdoutStreamUrl && stderrStreamUrl && stdoutStreamUrl === stderrStreamUrl;
|
|
133
127
|
logger.debug(
|
|
@@ -137,8 +131,6 @@ export const execSubcommand = createCommand({
|
|
|
137
131
|
stderrStreamUrl ?? 'none'
|
|
138
132
|
);
|
|
139
133
|
|
|
140
|
-
// Set up stream capture — in JSON mode, capture to buffers;
|
|
141
|
-
// when streams are separate, capture stdout/stderr independently
|
|
142
134
|
const outputChunks: string[] = [];
|
|
143
135
|
const stdoutChunks: string[] = [];
|
|
144
136
|
const stderrChunks: string[] = [];
|
|
@@ -148,11 +140,9 @@ export const execSubcommand = createCommand({
|
|
|
148
140
|
|
|
149
141
|
if (options.json) {
|
|
150
142
|
if (isCombinedOutput) {
|
|
151
|
-
// Combined stream: can't distinguish stdout from stderr
|
|
152
143
|
stdoutWritable = createCaptureStream((chunk) => outputChunks.push(chunk));
|
|
153
144
|
stderrWritable = createCaptureStream((chunk) => outputChunks.push(chunk));
|
|
154
145
|
} else {
|
|
155
|
-
// Separate streams: capture each independently and also to combined output
|
|
156
146
|
stdoutWritable = createCaptureStream((chunk) => {
|
|
157
147
|
stdoutChunks.push(chunk);
|
|
158
148
|
outputChunks.push(chunk);
|
|
@@ -168,30 +158,27 @@ export const execSubcommand = createCommand({
|
|
|
168
158
|
}
|
|
169
159
|
|
|
170
160
|
if (isCombinedOutput) {
|
|
171
|
-
// Stream combined output to stdout only to avoid duplicates
|
|
172
161
|
logger.debug('[exec] starting combined stream: %s', stdoutStreamUrl);
|
|
173
162
|
streamLabels.push('combined');
|
|
174
163
|
streamPromises.push(
|
|
175
|
-
streamUrlToWritable(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
)
|
|
164
|
+
streamUrlToWritable(stdoutStreamUrl!, stdoutWritable, logger, {
|
|
165
|
+
signal: streamAbortController.signal,
|
|
166
|
+
label: 'combined',
|
|
167
|
+
raw: true,
|
|
168
|
+
v2: true,
|
|
169
|
+
}).then(() => {})
|
|
182
170
|
);
|
|
183
171
|
} else {
|
|
184
172
|
if (stdoutStreamUrl) {
|
|
185
173
|
logger.debug('[exec] starting stdout stream: %s', stdoutStreamUrl);
|
|
186
174
|
streamLabels.push('stdout');
|
|
187
175
|
streamPromises.push(
|
|
188
|
-
streamUrlToWritable(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
)
|
|
176
|
+
streamUrlToWritable(stdoutStreamUrl, stdoutWritable, logger, {
|
|
177
|
+
signal: streamAbortController.signal,
|
|
178
|
+
label: 'stdout',
|
|
179
|
+
raw: true,
|
|
180
|
+
v2: true,
|
|
181
|
+
}).then(() => {})
|
|
195
182
|
);
|
|
196
183
|
}
|
|
197
184
|
|
|
@@ -199,13 +186,12 @@ export const execSubcommand = createCommand({
|
|
|
199
186
|
logger.debug('[exec] starting stderr stream: %s', stderrStreamUrl);
|
|
200
187
|
streamLabels.push('stderr');
|
|
201
188
|
streamPromises.push(
|
|
202
|
-
streamUrlToWritable(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
)
|
|
189
|
+
streamUrlToWritable(stderrStreamUrl, stderrWritable, logger, {
|
|
190
|
+
signal: streamAbortController.signal,
|
|
191
|
+
label: 'stderr',
|
|
192
|
+
raw: true,
|
|
193
|
+
v2: true,
|
|
194
|
+
}).then(() => {})
|
|
209
195
|
);
|
|
210
196
|
}
|
|
211
197
|
}
|
|
@@ -216,9 +202,6 @@ export const execSubcommand = createCommand({
|
|
|
216
202
|
streamLabels.join(', ')
|
|
217
203
|
);
|
|
218
204
|
|
|
219
|
-
// Use server-side long-polling to wait for execution completion
|
|
220
|
-
// This is more efficient than client-side polling and provides immediate
|
|
221
|
-
// error detection if the sandbox is terminated
|
|
222
205
|
let finalExecution: Awaited<ReturnType<typeof executionGet>>;
|
|
223
206
|
const pollStart = Date.now();
|
|
224
207
|
try {
|
|
@@ -228,8 +211,6 @@ export const execSubcommand = createCommand({
|
|
|
228
211
|
wait: EXECUTION_WAIT_DURATION,
|
|
229
212
|
});
|
|
230
213
|
} catch (err) {
|
|
231
|
-
// Abort any active stream readers before rethrowing so they
|
|
232
|
-
// don't keep running after the execution poll has failed.
|
|
233
214
|
streamAbortController.abort();
|
|
234
215
|
throw err;
|
|
235
216
|
}
|
|
@@ -240,11 +221,6 @@ export const execSubcommand = createCommand({
|
|
|
240
221
|
finalExecution.exitCode ?? 'undefined'
|
|
241
222
|
);
|
|
242
223
|
|
|
243
|
-
// Wait for all streams to reach EOF (Pulse blocks until true EOF).
|
|
244
|
-
// Safety: execution is confirmed complete so all data has been written
|
|
245
|
-
// and complete/v2 sent. If Pulse doesn't close the response within
|
|
246
|
-
// a grace period (e.g. cross-server routing delay, stale metadata
|
|
247
|
-
// cache), abort the streams to prevent an indefinite hang.
|
|
248
224
|
if (streamPromises.length > 0) {
|
|
249
225
|
logger.debug('[exec] waiting for %d stream(s) to EOF', streamPromises.length);
|
|
250
226
|
const streamWaitStart = Date.now();
|
|
@@ -268,7 +244,6 @@ export const execSubcommand = createCommand({
|
|
|
268
244
|
);
|
|
269
245
|
}
|
|
270
246
|
|
|
271
|
-
// Ensure stdout is fully flushed before continuing
|
|
272
247
|
if (!options.json && process.stdout.writable) {
|
|
273
248
|
await new Promise<void>((resolve) => {
|
|
274
249
|
if (process.stdout.writableNeedDrain) {
|
|
@@ -325,76 +300,6 @@ export const execSubcommand = createCommand({
|
|
|
325
300
|
},
|
|
326
301
|
});
|
|
327
302
|
|
|
328
|
-
async function streamUrlToWritable(
|
|
329
|
-
label: string,
|
|
330
|
-
url: string,
|
|
331
|
-
writable: NodeJS.WritableStream,
|
|
332
|
-
signal: AbortSignal,
|
|
333
|
-
logger: Logger
|
|
334
|
-
): Promise<void> {
|
|
335
|
-
const streamStart = Date.now();
|
|
336
|
-
try {
|
|
337
|
-
// Signal to Pulse that this is a v2 stream so it waits for v2 metadata
|
|
338
|
-
// instead of falling back to the legacy download path on a short timeout.
|
|
339
|
-
const v2Url = new URL(url);
|
|
340
|
-
v2Url.searchParams.set('v', '2');
|
|
341
|
-
logger.debug('[stream:%s] fetching: %s', label, v2Url.href);
|
|
342
|
-
const response = await fetch(v2Url.href, { signal });
|
|
343
|
-
logger.debug(
|
|
344
|
-
'[stream:%s] response status=%d in %dms',
|
|
345
|
-
label,
|
|
346
|
-
response.status,
|
|
347
|
-
Date.now() - streamStart
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
if (!response.ok || !response.body) {
|
|
351
|
-
logger.debug('[stream:%s] not ok or no body — returning', label);
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const reader = response.body.getReader();
|
|
356
|
-
let chunks = 0;
|
|
357
|
-
let totalBytes = 0;
|
|
358
|
-
|
|
359
|
-
// Read until EOF - Pulse will block until data is available
|
|
360
|
-
while (true) {
|
|
361
|
-
const { done, value } = await reader.read();
|
|
362
|
-
if (done) {
|
|
363
|
-
logger.debug(
|
|
364
|
-
'[stream:%s] EOF after %dms (%d chunks, %d bytes)',
|
|
365
|
-
label,
|
|
366
|
-
Date.now() - streamStart,
|
|
367
|
-
chunks,
|
|
368
|
-
totalBytes
|
|
369
|
-
);
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (value) {
|
|
374
|
-
chunks++;
|
|
375
|
-
totalBytes += value.length;
|
|
376
|
-
if (chunks <= 3 || chunks % 100 === 0) {
|
|
377
|
-
logger.debug(
|
|
378
|
-
'[stream:%s] chunk #%d: %d bytes (total: %d bytes, +%dms)',
|
|
379
|
-
label,
|
|
380
|
-
chunks,
|
|
381
|
-
value.length,
|
|
382
|
-
totalBytes,
|
|
383
|
-
Date.now() - streamStart
|
|
384
|
-
);
|
|
385
|
-
}
|
|
386
|
-
await writeAndDrain(writable, value);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
} catch (err) {
|
|
390
|
-
if (err instanceof Error && err.name === 'AbortError') {
|
|
391
|
-
logger.debug('[stream:%s] aborted after %dms', label, Date.now() - streamStart);
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
logger.debug('[stream:%s] error after %dms: %s', label, Date.now() - streamStart, err);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
303
|
function createCaptureStream(onChunk: (chunk: string) => void): NodeJS.WritableStream {
|
|
399
304
|
return new Writable({
|
|
400
305
|
write(
|
|
@@ -3,6 +3,7 @@ import { getSubcommand } from './get';
|
|
|
3
3
|
import { listSubcommand } from './list';
|
|
4
4
|
import { createSubcommand } from './create';
|
|
5
5
|
import { destroySubcommand } from './destroy';
|
|
6
|
+
import { logsSubcommand } from './logs';
|
|
6
7
|
import { getCommand } from '../../../../command-prefix';
|
|
7
8
|
|
|
8
9
|
export const command = createCommand({
|
|
@@ -23,8 +24,18 @@ export const command = createCommand({
|
|
|
23
24
|
command: getCommand('cloud sandbox job destroy sbx_abc123 job_xyz789'),
|
|
24
25
|
description: 'Terminate a running job',
|
|
25
26
|
},
|
|
27
|
+
{
|
|
28
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789'),
|
|
29
|
+
description: 'View logs from a job',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
subcommands: [
|
|
33
|
+
createSubcommand,
|
|
34
|
+
getSubcommand,
|
|
35
|
+
listSubcommand,
|
|
36
|
+
destroySubcommand,
|
|
37
|
+
logsSubcommand,
|
|
26
38
|
],
|
|
27
|
-
subcommands: [createSubcommand, getSubcommand, listSubcommand, destroySubcommand],
|
|
28
39
|
requires: { auth: true, org: true },
|
|
29
40
|
});
|
|
30
41
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../../types';
|
|
3
|
+
import * as tui from '../../../../tui';
|
|
4
|
+
import { createSandboxClient } from '../util';
|
|
5
|
+
import { jobGet, sandboxResolve } from '@agentuity/server';
|
|
6
|
+
import { getCommand } from '../../../../command-prefix';
|
|
7
|
+
import { streamUrlToWritable } from '../../../../utils/stream-url';
|
|
8
|
+
|
|
9
|
+
const JobLogsResponseSchema = z.object({
|
|
10
|
+
jobId: z.string(),
|
|
11
|
+
sandboxId: z.string(),
|
|
12
|
+
status: z.string(),
|
|
13
|
+
bytesRead: z.number().optional(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const logsSubcommand = createSubcommand({
|
|
17
|
+
name: 'logs',
|
|
18
|
+
aliases: ['log'],
|
|
19
|
+
description: 'Stream logs from a sandbox job',
|
|
20
|
+
tags: ['read-only', 'slow', 'requires-auth'],
|
|
21
|
+
requires: { auth: true, apiClient: true },
|
|
22
|
+
examples: [
|
|
23
|
+
{
|
|
24
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789'),
|
|
25
|
+
description: 'View stdout logs from a job',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --stderr'),
|
|
29
|
+
description: 'View stderr logs from a job',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --follow'),
|
|
33
|
+
description: 'Follow logs in real-time',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --grep error'),
|
|
37
|
+
description: 'Filter logs containing "error"',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
command: getCommand('cloud sandbox job logs sbx_abc123 job_xyz789 --tail 100'),
|
|
41
|
+
description: 'Show last 100 lines',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
schema: {
|
|
45
|
+
args: z.object({
|
|
46
|
+
sandboxId: z.string().describe('Sandbox ID'),
|
|
47
|
+
jobId: z.string().describe('Job ID'),
|
|
48
|
+
}),
|
|
49
|
+
options: z.object({
|
|
50
|
+
stderr: z.boolean().default(false).describe('Show stderr instead of stdout'),
|
|
51
|
+
follow: z.boolean().default(false).describe('Follow logs in real-time (for running jobs)'),
|
|
52
|
+
timestamps: z.boolean().default(true).describe('Show timestamps in output'),
|
|
53
|
+
grep: z.string().optional().describe('Filter logs by pattern (case-insensitive)'),
|
|
54
|
+
tail: z.coerce
|
|
55
|
+
.number()
|
|
56
|
+
.int()
|
|
57
|
+
.min(1)
|
|
58
|
+
.optional()
|
|
59
|
+
.describe('Number of lines to show from the end'),
|
|
60
|
+
}),
|
|
61
|
+
response: JobLogsResponseSchema,
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
async handler(ctx) {
|
|
65
|
+
const { args, opts, options, auth, logger, apiClient } = ctx;
|
|
66
|
+
|
|
67
|
+
const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
|
|
68
|
+
const { region, orgId } = sandboxInfo;
|
|
69
|
+
|
|
70
|
+
const client = createSandboxClient(logger, auth, region);
|
|
71
|
+
|
|
72
|
+
const job = await jobGet(client, {
|
|
73
|
+
sandboxId: args.sandboxId,
|
|
74
|
+
jobId: args.jobId,
|
|
75
|
+
orgId,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const streamUrl = opts.stderr ? job.stderrStreamUrl : job.stdoutStreamUrl;
|
|
79
|
+
const isJson = options.json ?? false;
|
|
80
|
+
|
|
81
|
+
if (!streamUrl) {
|
|
82
|
+
if (isJson) {
|
|
83
|
+
return {
|
|
84
|
+
jobId: job.jobId,
|
|
85
|
+
sandboxId: job.sandboxId,
|
|
86
|
+
status: job.status,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
tui.warning(
|
|
90
|
+
`No ${opts.stderr ? 'stderr' : 'stdout'} stream available for job ${job.jobId}`
|
|
91
|
+
);
|
|
92
|
+
if (job.status === 'pending') {
|
|
93
|
+
tui.info('Job is still pending - logs will be available once it starts running');
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
jobId: job.jobId,
|
|
97
|
+
sandboxId: job.sandboxId,
|
|
98
|
+
status: job.status,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!isJson) {
|
|
103
|
+
tui.info(
|
|
104
|
+
`Streaming ${opts.stderr ? 'stderr' : 'stdout'} for job ${tui.bold(job.jobId)} (status: ${job.status})`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const abortController = new AbortController();
|
|
109
|
+
const handleSignal = () => {
|
|
110
|
+
abortController.abort();
|
|
111
|
+
};
|
|
112
|
+
process.on('SIGINT', handleSignal);
|
|
113
|
+
process.on('SIGTERM', handleSignal);
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const result = await streamUrlToWritable(streamUrl, process.stdout, logger, {
|
|
117
|
+
signal: abortController.signal,
|
|
118
|
+
follow: opts.follow,
|
|
119
|
+
timestamps: opts.timestamps ?? true,
|
|
120
|
+
grep: opts.grep,
|
|
121
|
+
tail: opts.tail,
|
|
122
|
+
json: isJson,
|
|
123
|
+
label: opts.stderr ? 'stderr' : 'stdout',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
jobId: job.jobId,
|
|
128
|
+
sandboxId: job.sandboxId,
|
|
129
|
+
status: job.status,
|
|
130
|
+
bytesRead: result.bytesRead,
|
|
131
|
+
};
|
|
132
|
+
} finally {
|
|
133
|
+
process.off('SIGINT', handleSignal);
|
|
134
|
+
process.off('SIGTERM', handleSignal);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
export default logsSubcommand;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { writeAndDrain } from '@agentuity/server';
|
|
2
|
+
import type { Logger } from '@agentuity/core';
|
|
3
|
+
import * as tui from '../tui';
|
|
4
|
+
|
|
5
|
+
export interface StreamUrlOptions {
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
follow?: boolean;
|
|
8
|
+
timestamps?: boolean;
|
|
9
|
+
grep?: string;
|
|
10
|
+
tail?: number;
|
|
11
|
+
json?: boolean;
|
|
12
|
+
label?: string;
|
|
13
|
+
raw?: boolean;
|
|
14
|
+
v2?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface StreamUrlResult {
|
|
18
|
+
bytesRead: number;
|
|
19
|
+
chunks: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class StreamFetchError extends Error {
|
|
23
|
+
constructor(
|
|
24
|
+
public status: number,
|
|
25
|
+
public statusText: string,
|
|
26
|
+
message: string
|
|
27
|
+
) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = 'StreamFetchError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function escapeRegExp(str: string): string {
|
|
34
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function streamUrlToWritable(
|
|
38
|
+
url: string,
|
|
39
|
+
writable: NodeJS.WritableStream,
|
|
40
|
+
logger: Logger,
|
|
41
|
+
options: StreamUrlOptions = {}
|
|
42
|
+
): Promise<StreamUrlResult> {
|
|
43
|
+
const {
|
|
44
|
+
signal,
|
|
45
|
+
follow,
|
|
46
|
+
timestamps,
|
|
47
|
+
grep,
|
|
48
|
+
tail,
|
|
49
|
+
json,
|
|
50
|
+
label = 'stream',
|
|
51
|
+
raw = false,
|
|
52
|
+
v2 = false,
|
|
53
|
+
} = options;
|
|
54
|
+
const streamStart = Date.now();
|
|
55
|
+
let bytesRead = 0;
|
|
56
|
+
let chunks = 0;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const fetchUrl = new URL(url);
|
|
60
|
+
|
|
61
|
+
if (follow || v2) {
|
|
62
|
+
fetchUrl.searchParams.set('v', '2');
|
|
63
|
+
}
|
|
64
|
+
if (follow) {
|
|
65
|
+
fetchUrl.searchParams.set('follow', 'true');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const redactedUrl =
|
|
69
|
+
fetchUrl.origin + fetchUrl.pathname + (fetchUrl.search ? '?REDACTED' : '');
|
|
70
|
+
logger.debug('[%s] fetching: %s', label, redactedUrl);
|
|
71
|
+
const response = await fetch(fetchUrl.href, { signal });
|
|
72
|
+
logger.debug(
|
|
73
|
+
'[%s] response status=%d in %dms',
|
|
74
|
+
label,
|
|
75
|
+
response.status,
|
|
76
|
+
Date.now() - streamStart
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (!response.ok || !response.body) {
|
|
80
|
+
logger.debug('[%s] not ok or no body', label);
|
|
81
|
+
if (!json) {
|
|
82
|
+
tui.error(`Failed to fetch stream: ${response.status} ${response.statusText}`);
|
|
83
|
+
}
|
|
84
|
+
throw new StreamFetchError(
|
|
85
|
+
response.status,
|
|
86
|
+
response.statusText,
|
|
87
|
+
`Failed to fetch stream: ${response.status} ${response.statusText}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const reader = response.body.getReader();
|
|
92
|
+
|
|
93
|
+
if (raw) {
|
|
94
|
+
while (true) {
|
|
95
|
+
const { done, value } = await reader.read();
|
|
96
|
+
if (done) {
|
|
97
|
+
logger.debug(
|
|
98
|
+
'[%s] EOF after %dms (%d chunks, %d bytes)',
|
|
99
|
+
label,
|
|
100
|
+
Date.now() - streamStart,
|
|
101
|
+
chunks,
|
|
102
|
+
bytesRead
|
|
103
|
+
);
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (value) {
|
|
108
|
+
chunks++;
|
|
109
|
+
bytesRead += value.length;
|
|
110
|
+
if (chunks <= 3 || chunks % 100 === 0) {
|
|
111
|
+
logger.debug(
|
|
112
|
+
'[%s] chunk #%d: %d bytes (total: %d bytes, +%dms)',
|
|
113
|
+
label,
|
|
114
|
+
chunks,
|
|
115
|
+
value.length,
|
|
116
|
+
bytesRead,
|
|
117
|
+
Date.now() - streamStart
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
await writeAndDrain(writable, value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
const decoder = new TextDecoder();
|
|
125
|
+
let leftover = '';
|
|
126
|
+
const grepPattern = grep ? new RegExp(escapeRegExp(grep), 'i') : null;
|
|
127
|
+
const needsFiltering = tail !== undefined || grepPattern !== null;
|
|
128
|
+
const tailBuffer: string[] = [];
|
|
129
|
+
const maxTail = tail ?? Infinity;
|
|
130
|
+
const liveOutput = follow && needsFiltering;
|
|
131
|
+
|
|
132
|
+
const outputLine = async (line: string) => {
|
|
133
|
+
if (json) {
|
|
134
|
+
const obj = {
|
|
135
|
+
timestamp: new Date().toISOString(),
|
|
136
|
+
stream: label,
|
|
137
|
+
message: line,
|
|
138
|
+
};
|
|
139
|
+
await writeAndDrain(writable, Buffer.from(JSON.stringify(obj) + '\n'));
|
|
140
|
+
} else {
|
|
141
|
+
const formatted = timestamps ? formatLineWithTimestamp(line) : line;
|
|
142
|
+
await writeAndDrain(writable, Buffer.from(formatted + '\n'));
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const processFilteredLine = async (line: string) => {
|
|
147
|
+
if (grepPattern && !grepPattern.test(line)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (tail !== undefined) {
|
|
151
|
+
tailBuffer.push(line);
|
|
152
|
+
if (tailBuffer.length > maxTail) {
|
|
153
|
+
tailBuffer.shift();
|
|
154
|
+
}
|
|
155
|
+
if (liveOutput) {
|
|
156
|
+
await outputLine(line);
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
await outputLine(line);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
while (true) {
|
|
164
|
+
const { done, value } = await reader.read();
|
|
165
|
+
if (done) {
|
|
166
|
+
if (leftover) {
|
|
167
|
+
if (needsFiltering) {
|
|
168
|
+
await processFilteredLine(leftover);
|
|
169
|
+
} else {
|
|
170
|
+
await outputLine(leftover);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
logger.debug(
|
|
174
|
+
'[%s] EOF after %dms (%d chunks, %d bytes)',
|
|
175
|
+
label,
|
|
176
|
+
Date.now() - streamStart,
|
|
177
|
+
chunks,
|
|
178
|
+
bytesRead
|
|
179
|
+
);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (value) {
|
|
184
|
+
chunks++;
|
|
185
|
+
bytesRead += value.length;
|
|
186
|
+
const text = leftover + decoder.decode(value, { stream: true });
|
|
187
|
+
const lines = text.split('\n');
|
|
188
|
+
leftover = lines.pop() ?? '';
|
|
189
|
+
|
|
190
|
+
for (const line of lines) {
|
|
191
|
+
if (needsFiltering) {
|
|
192
|
+
await processFilteredLine(line);
|
|
193
|
+
} else {
|
|
194
|
+
await outputLine(line);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!liveOutput && needsFiltering && tailBuffer.length > 0) {
|
|
201
|
+
for (const line of tailBuffer) {
|
|
202
|
+
await outputLine(line);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return { bytesRead, chunks };
|
|
208
|
+
} catch (err) {
|
|
209
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
210
|
+
logger.debug('[%s] aborted after %dms', label, Date.now() - streamStart);
|
|
211
|
+
return { bytesRead, chunks };
|
|
212
|
+
}
|
|
213
|
+
logger.debug('[%s] error after %dms: %s', label, Date.now() - streamStart, err);
|
|
214
|
+
throw err;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function formatLineWithTimestamp(line: string): string {
|
|
219
|
+
const timestamp = new Date().toLocaleTimeString('en-US', {
|
|
220
|
+
hour12: false,
|
|
221
|
+
hour: '2-digit',
|
|
222
|
+
minute: '2-digit',
|
|
223
|
+
second: '2-digit',
|
|
224
|
+
});
|
|
225
|
+
return `${tui.muted(timestamp)} ${line}`;
|
|
226
|
+
}
|