@agentuity/cli 1.0.11 → 1.0.13
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/ai/opencode/dashboard.d.ts +3 -0
- package/dist/cmd/ai/opencode/dashboard.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/dashboard.js +580 -0
- package/dist/cmd/ai/opencode/dashboard.js.map +1 -0
- package/dist/cmd/ai/opencode/db.d.ts +11 -0
- package/dist/cmd/ai/opencode/db.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/db.js +63 -0
- package/dist/cmd/ai/opencode/db.js.map +1 -0
- package/dist/cmd/ai/opencode/index.d.ts.map +1 -1
- package/dist/cmd/ai/opencode/index.js +17 -1
- package/dist/cmd/ai/opencode/index.js.map +1 -1
- package/dist/cmd/ai/opencode/inspect.d.ts +3 -0
- package/dist/cmd/ai/opencode/inspect.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/inspect.js +405 -0
- package/dist/cmd/ai/opencode/inspect.js.map +1 -0
- package/dist/cmd/build/ast.js +1 -1
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/cloud/db/list.d.ts.map +1 -1
- package/dist/cmd/cloud/db/list.js +10 -7
- package/dist/cmd/cloud/db/list.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/stats.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/stats.js +78 -5
- package/dist/cmd/cloud/keyvalue/stats.js.map +1 -1
- package/dist/cmd/cloud/queue/list.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/list.js +15 -9
- package/dist/cmd/cloud/queue/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/list.js +10 -9
- package/dist/cmd/cloud/sandbox/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/runtime/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/runtime/list.js +1 -4
- package/dist/cmd/cloud/sandbox/runtime/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.js +2 -5
- package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
- package/dist/cmd/cloud/session/list.d.ts.map +1 -1
- package/dist/cmd/cloud/session/list.js +1 -4
- package/dist/cmd/cloud/session/list.js.map +1 -1
- package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/list.js +16 -9
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/list.js +8 -9
- package/dist/cmd/cloud/stream/list.js.map +1 -1
- package/dist/cmd/cloud/thread/list.d.ts.map +1 -1
- package/dist/cmd/cloud/thread/list.js +1 -4
- package/dist/cmd/cloud/thread/list.js.map +1 -1
- package/dist/cmd/cloud/vector/stats.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/stats.js +28 -4
- package/dist/cmd/cloud/vector/stats.js.map +1 -1
- package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
- package/dist/cmd/dev/file-watcher.js +42 -0
- package/dist/cmd/dev/file-watcher.js.map +1 -1
- package/dist/cmd/upgrade/index.d.ts.map +1 -1
- package/dist/cmd/upgrade/index.js +14 -8
- package/dist/cmd/upgrade/index.js.map +1 -1
- package/dist/cmd/upgrade/npm-availability.d.ts +12 -0
- package/dist/cmd/upgrade/npm-availability.d.ts.map +1 -1
- package/dist/cmd/upgrade/npm-availability.js +85 -6
- package/dist/cmd/upgrade/npm-availability.js.map +1 -1
- package/dist/cmd/upgrade/npm-availability.test.d.ts +2 -0
- package/dist/cmd/upgrade/npm-availability.test.d.ts.map +1 -0
- package/dist/cmd/upgrade/npm-availability.test.js +48 -0
- package/dist/cmd/upgrade/npm-availability.test.js.map +1 -0
- package/dist/version-check.js +3 -6
- package/dist/version-check.js.map +1 -1
- package/package.json +6 -6
- package/src/cmd/ai/opencode/dashboard.ts +772 -0
- package/src/cmd/ai/opencode/db.ts +66 -0
- package/src/cmd/ai/opencode/index.ts +17 -1
- package/src/cmd/ai/opencode/inspect.ts +516 -0
- package/src/cmd/build/ast.ts +1 -1
- package/src/cmd/cloud/db/list.ts +10 -7
- package/src/cmd/cloud/keyvalue/stats.ts +105 -11
- package/src/cmd/cloud/queue/list.ts +15 -9
- package/src/cmd/cloud/sandbox/list.ts +10 -9
- package/src/cmd/cloud/sandbox/runtime/list.ts +1 -4
- package/src/cmd/cloud/sandbox/snapshot/list.ts +2 -5
- package/src/cmd/cloud/session/list.ts +17 -20
- package/src/cmd/cloud/storage/list.ts +16 -9
- package/src/cmd/cloud/stream/list.ts +18 -19
- package/src/cmd/cloud/thread/list.ts +8 -11
- package/src/cmd/cloud/vector/stats.ts +39 -4
- package/src/cmd/dev/file-watcher.ts +44 -0
- package/src/cmd/upgrade/index.ts +20 -8
- package/src/cmd/upgrade/npm-availability.test.ts +57 -0
- package/src/cmd/upgrade/npm-availability.ts +101 -6
- package/src/version-check.ts +6 -6
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { test, expect, beforeAll, afterAll } from 'bun:test';
|
|
2
|
+
import { spawnWithTimeout } from './npm-availability';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
// bun info requires a package.json in its cwd, and isVersionAvailableOnNpm
|
|
7
|
+
// uses tmpdir() as cwd. Ensure a minimal package.json exists there for tests.
|
|
8
|
+
const tmpPackageJson = join(tmpdir(), 'package.json');
|
|
9
|
+
let createdPackageJson = false;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
const file = Bun.file(tmpPackageJson);
|
|
13
|
+
if (!(await file.exists())) {
|
|
14
|
+
await Bun.write(file, '{}');
|
|
15
|
+
createdPackageJson = true;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterAll(async () => {
|
|
20
|
+
if (createdPackageJson) {
|
|
21
|
+
const { unlink } = await import('node:fs/promises');
|
|
22
|
+
await unlink(tmpPackageJson).catch(() => {});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('spawnWithTimeout kills process on timeout', async () => {
|
|
27
|
+
// spawn a command that hangs with a short timeout (500ms)
|
|
28
|
+
await expect(
|
|
29
|
+
spawnWithTimeout(['bun', '-e', 'setTimeout(()=>{},60000)'], { timeout: 500 })
|
|
30
|
+
).rejects.toThrow(/timed out/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('spawnWithTimeout returns result when command completes in time', async () => {
|
|
34
|
+
const result = await spawnWithTimeout(['bun', '-e', "console.log('hello')"], {
|
|
35
|
+
timeout: 5_000,
|
|
36
|
+
});
|
|
37
|
+
expect(result.exitCode).toBe(0);
|
|
38
|
+
expect(result.stdout.toString().trim()).toBe('hello');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('spawnWithTimeout returns non-zero exit code without throwing', async () => {
|
|
42
|
+
const result = await spawnWithTimeout(['bun', '-e', 'process.exit(1)'], { timeout: 5_000 });
|
|
43
|
+
expect(result.exitCode).not.toBe(0);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('isVersionAvailableOnNpm returns true for a known version', async () => {
|
|
47
|
+
const { isVersionAvailableOnNpm } = await import('./npm-availability');
|
|
48
|
+
// Use a known-good old version that definitely exists
|
|
49
|
+
const result = await isVersionAvailableOnNpm('1.0.10');
|
|
50
|
+
expect(result).toBe(true);
|
|
51
|
+
}, 15_000); // generous test timeout but the function itself has 10s subprocess timeout
|
|
52
|
+
|
|
53
|
+
test('isVersionAvailableOnNpm returns false for non-existent version', async () => {
|
|
54
|
+
const { isVersionAvailableOnNpm } = await import('./npm-availability');
|
|
55
|
+
const result = await isVersionAvailableOnNpm('999.999.999');
|
|
56
|
+
expect(result).toBe(false);
|
|
57
|
+
}, 15_000);
|
|
@@ -3,11 +3,91 @@
|
|
|
3
3
|
* Used to verify a version is available via bun's resolver before attempting upgrade.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { $ } from 'bun';
|
|
7
6
|
import { tmpdir } from 'node:os';
|
|
8
7
|
|
|
9
8
|
const PACKAGE_SPEC = '@agentuity/cli';
|
|
10
9
|
|
|
10
|
+
/** Default timeout for `bun info` subprocess calls (10 seconds) */
|
|
11
|
+
const BUN_INFO_TIMEOUT_MS = 10_000;
|
|
12
|
+
|
|
13
|
+
/** Default timeout for install (`bun add -g`) subprocess calls (30 seconds) */
|
|
14
|
+
const INSTALL_TIMEOUT_MS = 30_000;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Run a command via Bun.spawn with a timeout that kills the process.
|
|
18
|
+
* Returns { exitCode, stdout, stderr } similar to Bun's $ shell result.
|
|
19
|
+
*/
|
|
20
|
+
export async function spawnWithTimeout(
|
|
21
|
+
cmd: string[],
|
|
22
|
+
options: { cwd?: string; timeout: number }
|
|
23
|
+
): Promise<{ exitCode: number; stdout: Buffer; stderr: Buffer }> {
|
|
24
|
+
const proc = Bun.spawn(cmd, {
|
|
25
|
+
cwd: options.cwd,
|
|
26
|
+
stdout: 'pipe',
|
|
27
|
+
stderr: 'pipe',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
let timedOut = false;
|
|
31
|
+
const timer = setTimeout(() => {
|
|
32
|
+
timedOut = true;
|
|
33
|
+
proc.kill();
|
|
34
|
+
}, options.timeout);
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const [exitCode, stdoutBytes, stderrBytes] = await Promise.all([
|
|
38
|
+
proc.exited,
|
|
39
|
+
new Response(proc.stdout).arrayBuffer(),
|
|
40
|
+
new Response(proc.stderr).arrayBuffer(),
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
if (timedOut) {
|
|
44
|
+
throw new Error(`Command timed out after ${options.timeout}ms: ${cmd.join(' ')}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
exitCode,
|
|
49
|
+
stdout: Buffer.from(stdoutBytes),
|
|
50
|
+
stderr: Buffer.from(stderrBytes),
|
|
51
|
+
};
|
|
52
|
+
} finally {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Sentinel error thrown exclusively by withTimeout so the retry loop can
|
|
59
|
+
* distinguish a genuine timeout from other failures (e.g. permission errors).
|
|
60
|
+
*/
|
|
61
|
+
class TimeoutError extends Error {
|
|
62
|
+
constructor(description: string, timeoutMs: number) {
|
|
63
|
+
super(`${description} timed out after ${timeoutMs}ms`);
|
|
64
|
+
this.name = 'TimeoutError';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Race a promise against a timeout. Unlike spawnWithTimeout (which kills a process),
|
|
70
|
+
* this is a generic wrapper for any async operation (e.g. the installFn callback).
|
|
71
|
+
*
|
|
72
|
+
* Throws a {@link TimeoutError} (not a plain Error) so callers can tell
|
|
73
|
+
* timeouts apart from other exceptions.
|
|
74
|
+
*/
|
|
75
|
+
async function withTimeout<T>(
|
|
76
|
+
promise: Promise<T>,
|
|
77
|
+
timeoutMs: number,
|
|
78
|
+
description: string
|
|
79
|
+
): Promise<T> {
|
|
80
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
81
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
82
|
+
timer = setTimeout(() => reject(new TimeoutError(description, timeoutMs)), timeoutMs);
|
|
83
|
+
});
|
|
84
|
+
try {
|
|
85
|
+
return await Promise.race([promise, timeoutPromise]);
|
|
86
|
+
} finally {
|
|
87
|
+
clearTimeout(timer!);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
11
91
|
/**
|
|
12
92
|
* Check if a specific version of @agentuity/cli is resolvable by bun.
|
|
13
93
|
* Uses `bun info` to verify bun's own resolver/CDN can see the version,
|
|
@@ -20,10 +100,10 @@ const PACKAGE_SPEC = '@agentuity/cli';
|
|
|
20
100
|
export async function isVersionAvailableOnNpm(version: string): Promise<boolean> {
|
|
21
101
|
const normalizedVersion = version.replace(/^v/, '');
|
|
22
102
|
try {
|
|
23
|
-
const result = await
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
103
|
+
const result = await spawnWithTimeout(
|
|
104
|
+
['bun', 'info', `${PACKAGE_SPEC}@${normalizedVersion}`, '--json'],
|
|
105
|
+
{ cwd: tmpdir(), timeout: BUN_INFO_TIMEOUT_MS }
|
|
106
|
+
);
|
|
27
107
|
if (result.exitCode !== 0) {
|
|
28
108
|
return false;
|
|
29
109
|
}
|
|
@@ -147,7 +227,22 @@ export async function installWithRetry(
|
|
|
147
227
|
let delay = initialDelayMs;
|
|
148
228
|
|
|
149
229
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
150
|
-
|
|
230
|
+
let result: { exitCode: number; stderr: Buffer };
|
|
231
|
+
try {
|
|
232
|
+
result = await withTimeout(installFn(), INSTALL_TIMEOUT_MS, 'Install command');
|
|
233
|
+
} catch (error) {
|
|
234
|
+
// Only retry on timeouts — non-timeout errors (permissions, disk, etc.) are fatal
|
|
235
|
+
if (!(error instanceof TimeoutError)) {
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
if (attempt === maxAttempts) {
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
onRetry?.(attempt, delay);
|
|
242
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
243
|
+
delay = Math.min(Math.round(delay * multiplier), maxDelayMs);
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
151
246
|
|
|
152
247
|
if (result.exitCode === 0) {
|
|
153
248
|
return result;
|
package/src/version-check.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { fetchLatestVersion } from './cmd/upgrade';
|
|
|
4
4
|
import { getVersion, getCompareUrl, getReleaseUrl, toTag } from './version';
|
|
5
5
|
import * as tui from './tui';
|
|
6
6
|
import { saveConfig } from './config';
|
|
7
|
-
import { $ } from 'bun';
|
|
8
7
|
import { tmpdir } from 'node:os';
|
|
9
8
|
import { getExecutingAgent } from './agent-detection';
|
|
10
9
|
|
|
@@ -174,13 +173,14 @@ async function performUpgrade(logger: Logger, targetVersion: string): Promise<vo
|
|
|
174
173
|
|
|
175
174
|
// Use bun to install the specific version globally with retry for CDN propagation delays
|
|
176
175
|
// Run from tmpdir to avoid interference from any local package.json/node_modules
|
|
177
|
-
const { installWithRetry } = await import('./cmd/upgrade/npm-availability');
|
|
176
|
+
const { installWithRetry, spawnWithTimeout } = await import('./cmd/upgrade/npm-availability');
|
|
178
177
|
await installWithRetry(
|
|
179
178
|
async () => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
// spawnWithTimeout kills the process if it exceeds 30s
|
|
180
|
+
const result = await spawnWithTimeout(
|
|
181
|
+
['bun', 'add', '-g', `@agentuity/cli@${npmVersion}`],
|
|
182
|
+
{ cwd: tmpdir(), timeout: 30_000 }
|
|
183
|
+
);
|
|
184
184
|
return { exitCode: result.exitCode, stderr: result.stderr };
|
|
185
185
|
},
|
|
186
186
|
{
|