@agentuity/cli 2.0.0-beta.1 → 2.0.0
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/bin/cli.ts +3 -1
- package/dist/cmd/build/ci.d.ts +1 -1
- package/dist/cmd/build/ci.d.ts.map +1 -1
- package/dist/cmd/build/ci.js +70 -63
- package/dist/cmd/build/ci.js.map +1 -1
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +0 -3
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.js +26 -2
- package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +5 -0
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +13 -11
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/static-renderer.d.ts +3 -2
- package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
- package/dist/cmd/build/vite/static-renderer.js +28 -58
- package/dist/cmd/build/vite/static-renderer.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +33 -0
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/cloud/deploy-fork.d.ts +10 -0
- package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy-fork.js +71 -32
- package/dist/cmd/cloud/deploy-fork.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +53 -11
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/create.js +5 -0
- package/dist/cmd/cloud/sandbox/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +76 -66
- 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/cmd/cloud/sandbox/run.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +14 -2
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js +2 -2
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/coder/hub-url.d.ts.map +1 -1
- package/dist/cmd/coder/hub-url.js +3 -1
- package/dist/cmd/coder/hub-url.js.map +1 -1
- package/dist/cmd/coder/start.js +6 -6
- package/dist/cmd/coder/start.js.map +1 -1
- package/dist/cmd/coder/tui-init.d.ts +2 -2
- package/dist/cmd/coder/tui-init.js +2 -2
- package/dist/cmd/coder/tui-init.js.map +1 -1
- package/dist/cmd/project/show.d.ts.map +1 -1
- package/dist/cmd/project/show.js +9 -0
- package/dist/cmd/project/show.js.map +1 -1
- package/dist/cmd/support/report.d.ts.map +1 -1
- package/dist/cmd/support/report.js +19 -10
- package/dist/cmd/support/report.js.map +1 -1
- package/dist/errors.d.ts +24 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +42 -12
- package/dist/errors.js.map +1 -1
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-generator.js +2 -12
- package/dist/schema-generator.js.map +1 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +38 -0
- package/dist/steps.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +25 -9
- package/dist/tui.js.map +1 -1
- package/dist/utils/stream-capture.d.ts +9 -0
- package/dist/utils/stream-capture.d.ts.map +1 -0
- package/dist/utils/stream-capture.js +34 -0
- package/dist/utils/stream-capture.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/dist/utils/zip.d.ts.map +1 -1
- package/dist/utils/zip.js +19 -10
- package/dist/utils/zip.js.map +1 -1
- package/package.json +9 -7
- package/src/cmd/build/ci.ts +82 -80
- package/src/cmd/build/index.ts +0 -4
- package/src/cmd/build/vite/agent-discovery.ts +30 -5
- package/src/cmd/build/vite/route-discovery.ts +25 -12
- package/src/cmd/build/vite/static-renderer.ts +33 -64
- package/src/cmd/build/vite/vite-builder.ts +36 -0
- package/src/cmd/cloud/deploy-fork.ts +90 -33
- package/src/cmd/cloud/deploy.ts +68 -12
- package/src/cmd/cloud/sandbox/create.ts +7 -0
- package/src/cmd/cloud/sandbox/exec.ts +102 -90
- package/src/cmd/cloud/sandbox/job/index.ts +12 -1
- package/src/cmd/cloud/sandbox/job/logs.ts +139 -0
- package/src/cmd/cloud/sandbox/run.ts +16 -2
- package/src/cmd/cloud/sandbox/snapshot/build.ts +2 -2
- package/src/cmd/coder/hub-url.ts +3 -1
- package/src/cmd/coder/start.ts +6 -6
- package/src/cmd/coder/tui-init.ts +4 -4
- package/src/cmd/project/show.ts +9 -0
- package/src/cmd/support/report.ts +21 -10
- package/src/errors.ts +44 -12
- package/src/schema-generator.ts +2 -12
- package/src/steps.ts +38 -0
- package/src/tui.ts +24 -9
- package/src/utils/stream-capture.ts +39 -0
- package/src/utils/stream-url.ts +226 -0
- package/src/utils/zip.ts +22 -10
|
@@ -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/dist/utils/zip.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../src/utils/zip.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../src/utils/zip.ts"],"names":[],"mappings":"AAOA,UAAU,OAAO;IAChB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACzD;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,iBAuD1E"}
|
package/dist/utils/zip.js
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createWriteStream, lstatSync } from 'node:fs';
|
|
2
|
+
import { mkdir } from 'node:fs/promises';
|
|
3
|
+
import { dirname, relative } from 'node:path';
|
|
3
4
|
import { Glob } from 'bun';
|
|
4
|
-
import
|
|
5
|
+
import archiver from 'archiver';
|
|
5
6
|
import { toForwardSlash } from './normalize-path';
|
|
6
7
|
export async function zipDir(dir, outdir, options) {
|
|
7
|
-
|
|
8
|
+
await mkdir(dirname(outdir), { recursive: true });
|
|
9
|
+
const output = createWriteStream(outdir);
|
|
10
|
+
const zip = archiver('zip', {
|
|
11
|
+
zlib: { level: 9 },
|
|
12
|
+
});
|
|
13
|
+
const writeDone = new Promise((resolve, reject) => {
|
|
14
|
+
output.on('close', resolve);
|
|
15
|
+
output.on('error', reject);
|
|
16
|
+
zip.on('error', reject);
|
|
17
|
+
});
|
|
18
|
+
zip.pipe(output);
|
|
8
19
|
const files = await Array.fromAsync(new Glob('**/*').scan({ cwd: dir, absolute: true, dot: true, followSymlinks: false }));
|
|
9
20
|
const total = files.length;
|
|
10
21
|
let count = 0;
|
|
@@ -23,11 +34,8 @@ export async function zipDir(dir, outdir, options) {
|
|
|
23
34
|
// across machines and would cause EISDIR errors on extraction.
|
|
24
35
|
const stat = lstatSync(file);
|
|
25
36
|
if (!stat.isSymbolicLink() && !stat.isDirectory()) {
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
// with incorrect Unix permission bits, causing EACCES errors when extracted on Linux.
|
|
29
|
-
const data = readFileSync(file);
|
|
30
|
-
zip.addFile(rel, data, '', 0o644);
|
|
37
|
+
// Set explicit Unix permissions (0o644) for portability across OSes.
|
|
38
|
+
zip.file(file, { name: rel, mode: 0o644 });
|
|
31
39
|
}
|
|
32
40
|
}
|
|
33
41
|
catch (err) {
|
|
@@ -41,7 +49,8 @@ export async function zipDir(dir, outdir, options) {
|
|
|
41
49
|
await Bun.sleep(10); // give some time for the progress bar to render
|
|
42
50
|
}
|
|
43
51
|
}
|
|
44
|
-
await zip.
|
|
52
|
+
await zip.finalize();
|
|
53
|
+
await writeDone;
|
|
45
54
|
if (options?.progress) {
|
|
46
55
|
options.progress(100);
|
|
47
56
|
await Bun.sleep(100); // give some time for the progress bar to render
|
package/dist/utils/zip.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zip.js","sourceRoot":"","sources":["../../src/utils/zip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"zip.js","sourceRoot":"","sources":["../../src/utils/zip.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/cli",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -41,13 +41,15 @@
|
|
|
41
41
|
"prepublishOnly": "bun run clean && bun run build"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@agentuity/auth": "2.0.0
|
|
45
|
-
"@agentuity/core": "2.0.0
|
|
46
|
-
"@agentuity/
|
|
44
|
+
"@agentuity/auth": "2.0.0",
|
|
45
|
+
"@agentuity/core": "2.0.0",
|
|
46
|
+
"@agentuity/frontend": "2.0.0",
|
|
47
|
+
"@agentuity/server": "2.0.0",
|
|
47
48
|
"@datasert/cronjs-parser": "^1.4.0",
|
|
48
49
|
"@vitejs/plugin-react": "^5.1.2",
|
|
49
50
|
"acorn-loose": "^8.5.2",
|
|
50
51
|
"adm-zip": "^0.5.16",
|
|
52
|
+
"archiver": "^7.0.1",
|
|
51
53
|
"astring": "^1.9.0",
|
|
52
54
|
"cli-table3": "^0.6.5",
|
|
53
55
|
"commander": "^14.0.2",
|
|
@@ -58,12 +60,12 @@
|
|
|
58
60
|
"tar-fs": "^3.1.1",
|
|
59
61
|
"typescript": "^5.9.0",
|
|
60
62
|
"vite": "^7.2.7",
|
|
61
|
-
"zod": "^4.3.5"
|
|
62
|
-
"@agentuity/frontend": "2.0.0-beta.1"
|
|
63
|
+
"zod": "^4.3.5"
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
|
-
"@agentuity/test-utils": "2.0.0
|
|
66
|
+
"@agentuity/test-utils": "2.0.0",
|
|
66
67
|
"@types/adm-zip": "^0.5.7",
|
|
68
|
+
"@types/archiver": "^7.0.0",
|
|
67
69
|
"@types/bun": "latest",
|
|
68
70
|
"@types/tar-fs": "^2.0.4",
|
|
69
71
|
"bun-plugin-tailwind": "^0.1.2",
|
package/src/cmd/build/ci.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { ErrorCode } from '../../errors';
|
|
|
7
7
|
import * as tui from '../../tui';
|
|
8
8
|
|
|
9
9
|
export interface CIBuildOptions {
|
|
10
|
-
url
|
|
10
|
+
url?: string;
|
|
11
11
|
directory?: string;
|
|
12
12
|
trigger?: string;
|
|
13
13
|
event?: string;
|
|
@@ -22,44 +22,18 @@ export interface CIBuildOptions {
|
|
|
22
22
|
logsUrl?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
async function streamProcessOutput(proc: ReturnType<typeof spawn>): Promise<void> {
|
|
26
|
-
const forwardStream = async (
|
|
27
|
-
stream: ReadableStream<Uint8Array> | number | undefined,
|
|
28
|
-
isStderr: boolean
|
|
29
|
-
) => {
|
|
30
|
-
if (typeof stream === 'number') return;
|
|
31
|
-
if (!stream) return;
|
|
32
|
-
const reader = stream.getReader();
|
|
33
|
-
const target = isStderr ? process.stderr : process.stdout;
|
|
34
|
-
|
|
35
|
-
while (true) {
|
|
36
|
-
const { done, value } = await reader.read();
|
|
37
|
-
if (done) break;
|
|
38
|
-
target.write(value);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
await Promise.all([
|
|
43
|
-
forwardStream(proc.stdout, false),
|
|
44
|
-
forwardStream(proc.stderr, true),
|
|
45
|
-
proc.exited,
|
|
46
|
-
]);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
25
|
async function runCommand(cmd: string[], cwd: string): Promise<number> {
|
|
50
26
|
const proc = spawn({
|
|
51
27
|
cmd,
|
|
52
28
|
cwd,
|
|
53
29
|
env: { ...process.env, CI: 'true' },
|
|
54
30
|
stdin: 'ignore',
|
|
55
|
-
stdout: '
|
|
56
|
-
stderr: '
|
|
31
|
+
stdout: 'inherit',
|
|
32
|
+
stderr: 'inherit',
|
|
57
33
|
});
|
|
58
|
-
|
|
59
|
-
await streamProcessOutput(proc);
|
|
34
|
+
await proc.exited;
|
|
60
35
|
return proc.exitCode ?? 1;
|
|
61
36
|
}
|
|
62
|
-
|
|
63
37
|
async function downloadSource(url: string, targetPath: string): Promise<void> {
|
|
64
38
|
let lastError: unknown;
|
|
65
39
|
|
|
@@ -105,60 +79,77 @@ function buildDeployArgs(opts: CIBuildOptions): string[] {
|
|
|
105
79
|
|
|
106
80
|
export async function runCIBuild(opts: CIBuildOptions, _logger: Logger): Promise<void> {
|
|
107
81
|
let tempDir = '';
|
|
82
|
+
// Track subprocess exit code so we can clean up in finally before calling process.exit().
|
|
83
|
+
// Bun does not reliably honor process.exitCode, so an explicit process.exit() is required.
|
|
84
|
+
let pendingExitCode: number | undefined;
|
|
108
85
|
|
|
109
86
|
try {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const extractedEntries = await readdir(extractPath, { withFileTypes: true });
|
|
128
|
-
const extractedDirs = extractedEntries.filter((entry) => entry.isDirectory());
|
|
129
|
-
if (extractedDirs.length !== 1) {
|
|
130
|
-
tui.fatal(
|
|
131
|
-
`Expected one root directory after unzip, found ${extractedDirs.length}`,
|
|
132
|
-
ErrorCode.BUILD_FAILED
|
|
87
|
+
let projectDir: string;
|
|
88
|
+
|
|
89
|
+
if (opts.url) {
|
|
90
|
+
// Download and extract source from URL
|
|
91
|
+
tempDir = await mkdtemp(join(tmpdir(), 'agentuity-ci-build-'));
|
|
92
|
+
const sourceZipPath = join(tempDir, 'source.zip');
|
|
93
|
+
const extractPath = join(tempDir, 'build');
|
|
94
|
+
|
|
95
|
+
tui.info('1️⃣ Downloading source code from GitHub...');
|
|
96
|
+
await downloadSource(opts.url, sourceZipPath);
|
|
97
|
+
|
|
98
|
+
tui.info('2️⃣ Unzipping source code from GitHub...');
|
|
99
|
+
await mkdir(extractPath, { recursive: true });
|
|
100
|
+
const unzipExit = await runCommand(
|
|
101
|
+
['unzip', '-q', sourceZipPath, '-d', extractPath],
|
|
102
|
+
tempDir
|
|
133
103
|
);
|
|
134
|
-
|
|
104
|
+
if (unzipExit !== 0 && unzipExit !== 1) {
|
|
105
|
+
tui.error(`Failed to unzip source archive (exit ${unzipExit})`);
|
|
106
|
+
pendingExitCode = unzipExit;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
135
109
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
110
|
+
const extractedEntries = await readdir(extractPath, { withFileTypes: true });
|
|
111
|
+
const extractedDirs = extractedEntries.filter((entry) => entry.isDirectory());
|
|
112
|
+
if (extractedDirs.length !== 1) {
|
|
113
|
+
tui.fatal(
|
|
114
|
+
`Expected one root directory after unzip, found ${extractedDirs.length}`,
|
|
115
|
+
ErrorCode.BUILD_FAILED
|
|
116
|
+
);
|
|
117
|
+
}
|
|
140
118
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
119
|
+
const sourceRoot = extractedDirs.at(0);
|
|
120
|
+
if (!sourceRoot) {
|
|
121
|
+
tui.fatal('Could not determine extracted source directory', ErrorCode.BUILD_FAILED);
|
|
122
|
+
}
|
|
146
123
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
124
|
+
const sourceRootDir = join(extractPath, sourceRoot.name);
|
|
125
|
+
projectDir = sourceRootDir;
|
|
126
|
+
if (opts.directory) {
|
|
127
|
+
projectDir = join(sourceRootDir, opts.directory);
|
|
128
|
+
}
|
|
151
129
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
);
|
|
130
|
+
const projectStats = await stat(projectDir).catch(() => null);
|
|
131
|
+
if (!projectStats?.isDirectory()) {
|
|
132
|
+
tui.fatal(`Build directory not found: ${projectDir}`, ErrorCode.CONFIG_INVALID);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Resolve symlinks and verify the project dir is within the source root
|
|
136
|
+
const realProjectDir = await realpath(projectDir).catch(() => null);
|
|
137
|
+
const realSourceRoot = await realpath(sourceRootDir).catch(() => null);
|
|
138
|
+
if (!realProjectDir || !realSourceRoot || !realProjectDir.startsWith(realSourceRoot)) {
|
|
139
|
+
tui.fatal(
|
|
140
|
+
'Directory path escapes the source root (path traversal denied)',
|
|
141
|
+
ErrorCode.CONFIG_INVALID
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
projectDir = realProjectDir;
|
|
145
|
+
} else {
|
|
146
|
+
// No URL — use current working directory (source already present, e.g. snapshot-based deploy)
|
|
147
|
+
tui.info('1️⃣ Using local source (no download URL provided)...');
|
|
148
|
+
projectDir = process.cwd();
|
|
149
|
+
if (opts.directory) {
|
|
150
|
+
projectDir = join(projectDir, opts.directory);
|
|
151
|
+
}
|
|
160
152
|
}
|
|
161
|
-
projectDir = realProjectDir;
|
|
162
153
|
|
|
163
154
|
const sdkKey = process.env.AGENTUITY_SDK_KEY;
|
|
164
155
|
if (sdkKey) {
|
|
@@ -168,7 +159,9 @@ export async function runCIBuild(opts: CIBuildOptions, _logger: Logger): Promise
|
|
|
168
159
|
tui.info('3️⃣ Installing your project dependencies...');
|
|
169
160
|
const installExit = await runCommand(['bun', 'install'], projectDir);
|
|
170
161
|
if (installExit !== 0) {
|
|
171
|
-
tui.
|
|
162
|
+
tui.error(`Dependency installation failed (exit ${installExit})`);
|
|
163
|
+
pendingExitCode = installExit;
|
|
164
|
+
return;
|
|
172
165
|
}
|
|
173
166
|
|
|
174
167
|
const packageJsonPath = join(projectDir, 'package.json');
|
|
@@ -185,7 +178,9 @@ export async function runCIBuild(opts: CIBuildOptions, _logger: Logger): Promise
|
|
|
185
178
|
tui.info('🔧 Running predeploy script...');
|
|
186
179
|
const predeployExit = await runCommand(['bun', 'run', '--bun', 'predeploy'], projectDir);
|
|
187
180
|
if (predeployExit !== 0) {
|
|
188
|
-
tui.
|
|
181
|
+
tui.error(`Predeploy failed (exit ${predeployExit})`);
|
|
182
|
+
pendingExitCode = predeployExit;
|
|
183
|
+
return;
|
|
189
184
|
}
|
|
190
185
|
}
|
|
191
186
|
|
|
@@ -200,14 +195,18 @@ export async function runCIBuild(opts: CIBuildOptions, _logger: Logger): Promise
|
|
|
200
195
|
tui.info(`Using CLI: ${cliExists ? localCliBin : 'bunx --bun agentuity'}`);
|
|
201
196
|
const deployExit = await runCommand(deployCmd, projectDir);
|
|
202
197
|
if (deployExit !== 0) {
|
|
203
|
-
tui.
|
|
198
|
+
tui.error(`Deploy failed (exit ${deployExit})`);
|
|
199
|
+
pendingExitCode = deployExit;
|
|
200
|
+
return;
|
|
204
201
|
}
|
|
205
202
|
|
|
206
203
|
if (scripts?.postdeploy) {
|
|
207
204
|
tui.info('🔧 Running postdeploy script...');
|
|
208
205
|
const postdeployExit = await runCommand(['bun', 'run', '--bun', 'postdeploy'], projectDir);
|
|
209
206
|
if (postdeployExit !== 0) {
|
|
210
|
-
tui.
|
|
207
|
+
tui.error(`Postdeploy failed (exit ${postdeployExit})`);
|
|
208
|
+
pendingExitCode = postdeployExit;
|
|
209
|
+
return;
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
212
|
|
|
@@ -219,5 +218,8 @@ export async function runCIBuild(opts: CIBuildOptions, _logger: Logger): Promise
|
|
|
219
218
|
if (tempDir) {
|
|
220
219
|
await rm(tempDir, { recursive: true, force: true });
|
|
221
220
|
}
|
|
221
|
+
if (pendingExitCode !== undefined) {
|
|
222
|
+
process.exit(pendingExitCode);
|
|
223
|
+
}
|
|
222
224
|
}
|
|
223
225
|
}
|
package/src/cmd/build/index.ts
CHANGED
|
@@ -58,10 +58,6 @@ export const command = createCommand({
|
|
|
58
58
|
const { opts, projectDir, project } = ctx;
|
|
59
59
|
|
|
60
60
|
if (opts.ci) {
|
|
61
|
-
if (!opts.url) {
|
|
62
|
-
tui.fatal('--url is required when using --ci mode', ErrorCode.CONFIG_INVALID);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
61
|
const { runCIBuild } = await import('./ci');
|
|
66
62
|
await runCIBuild(
|
|
67
63
|
{
|
|
@@ -279,12 +279,25 @@ async function importAgentMetadata(
|
|
|
279
279
|
evals: evals.length > 0 ? evals : undefined,
|
|
280
280
|
};
|
|
281
281
|
} catch (error) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
282
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
283
|
+
throw new Error(
|
|
284
|
+
`Failed to import agent at ${relativeFilename}:\n` +
|
|
285
|
+
` ${errorMsg}\n\n` +
|
|
286
|
+
`Agent files are imported at build time to extract metadata. Code that ` +
|
|
287
|
+
`runs at module scope (outside of setup() or handler()) will execute ` +
|
|
288
|
+
`during the build — including SDK client constructors that require API ` +
|
|
289
|
+
`keys or environment variables.\n\n` +
|
|
290
|
+
`To fix this, move initialization code into setup() or handler():\n\n` +
|
|
291
|
+
` // ❌ Don't do this — runs at import time:\n` +
|
|
292
|
+
` const client = new OpenAI();\n` +
|
|
293
|
+
` export default createAgent('my-agent', { handler: async (ctx) => { ... } });\n\n` +
|
|
294
|
+
` // ✅ Do this instead — runs at request time:\n` +
|
|
295
|
+
` export default createAgent('my-agent', {\n` +
|
|
296
|
+
` setup: (ctx) => ({ client: new OpenAI() }),\n` +
|
|
297
|
+
` handler: async (ctx) => { const { client } = ctx.setup; ... },\n` +
|
|
298
|
+
` });\n\n` +
|
|
299
|
+
`See https://agentuity.dev/docs/agents#setup for more information.`
|
|
286
300
|
);
|
|
287
|
-
return null;
|
|
288
301
|
}
|
|
289
302
|
}
|
|
290
303
|
|
|
@@ -325,6 +338,18 @@ export async function discoverAgents(
|
|
|
325
338
|
continue;
|
|
326
339
|
}
|
|
327
340
|
|
|
341
|
+
// Skip test files (*.test.ts, *.spec.ts) and test directories
|
|
342
|
+
if (
|
|
343
|
+
file.startsWith('test/') ||
|
|
344
|
+
file.includes('/test/') ||
|
|
345
|
+
file.startsWith('__tests__/') ||
|
|
346
|
+
file.includes('/__tests__/') ||
|
|
347
|
+
file.endsWith('.test.ts') ||
|
|
348
|
+
file.endsWith('.spec.ts')
|
|
349
|
+
) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
328
353
|
const relativeFilename = toForwardSlash(relative(rootDir, filePath));
|
|
329
354
|
const agentMetadata = await importAgentMetadata(
|
|
330
355
|
filePath,
|
|
@@ -46,19 +46,23 @@ export function extractPathParams(path: string): string[] {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* Generate a deterministic route ID from project/deployment/path/
|
|
49
|
+
* Generate a deterministic route ID from project/deployment/type/method/filename/path/version.
|
|
50
|
+
* Must match the format used by the platform (prefix: route_, SHA1 hash of all components).
|
|
50
51
|
*/
|
|
51
|
-
function generateRouteId(
|
|
52
|
+
export function generateRouteId(
|
|
52
53
|
projectId: string,
|
|
53
54
|
deploymentId: string,
|
|
55
|
+
type: string,
|
|
56
|
+
method: string,
|
|
57
|
+
filename: string,
|
|
54
58
|
path: string,
|
|
55
|
-
|
|
59
|
+
version: string
|
|
56
60
|
): string {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
return `
|
|
61
|
+
const hasher = new Bun.CryptoHasher('sha1');
|
|
62
|
+
for (const val of [projectId, deploymentId, type, method, filename, path, version]) {
|
|
63
|
+
hasher.update(val);
|
|
64
|
+
}
|
|
65
|
+
return `route_${hasher.digest().toHex()}`;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
/**
|
|
@@ -152,7 +156,7 @@ export async function discoverRoutes(
|
|
|
152
156
|
);
|
|
153
157
|
|
|
154
158
|
for (const route of routeEntries) {
|
|
155
|
-
const method = String(route.method).
|
|
159
|
+
const method = String(route.method).toLowerCase();
|
|
156
160
|
// Combine mount path with route path
|
|
157
161
|
let fullPath = route.path;
|
|
158
162
|
if (mount.path !== '/' && !fullPath.startsWith(mount.path)) {
|
|
@@ -160,18 +164,27 @@ export async function discoverRoutes(
|
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
// Deduplicate (Hono may register same route multiple times for middleware)
|
|
163
|
-
const routeKey = `${method} ${fullPath}`;
|
|
167
|
+
const routeKey = `${method.toUpperCase()} ${fullPath}`;
|
|
164
168
|
if (seenRoutes.has(routeKey)) continue;
|
|
165
169
|
seenRoutes.add(routeKey);
|
|
166
170
|
|
|
167
171
|
const routeType = detectRouteType(route.handler);
|
|
168
|
-
const
|
|
172
|
+
const rel = toForwardSlash(relative(rootDir, mount.routerFile));
|
|
173
|
+
const id = generateRouteId(
|
|
174
|
+
projectId,
|
|
175
|
+
deploymentId,
|
|
176
|
+
routeType,
|
|
177
|
+
method,
|
|
178
|
+
rel,
|
|
179
|
+
fullPath,
|
|
180
|
+
version
|
|
181
|
+
);
|
|
169
182
|
|
|
170
183
|
routes.push({
|
|
171
184
|
id,
|
|
172
185
|
filename: toForwardSlash(relative(rootDir, mount.routerFile)),
|
|
173
186
|
path: fullPath,
|
|
174
|
-
method
|
|
187
|
+
method,
|
|
175
188
|
version,
|
|
176
189
|
type: routeType,
|
|
177
190
|
});
|