@agentos-software/apps-builder 0.0.0-fix-core-spawn-keep-stdin-open.242e11c
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/agentos-package.json +3 -0
- package/cli/apps-builder.mjs +553 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/package.aospkg +0 -0
- package/package.json +41 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import {
|
|
5
|
+
copyFile,
|
|
6
|
+
cp,
|
|
7
|
+
mkdir,
|
|
8
|
+
readFile,
|
|
9
|
+
readdir,
|
|
10
|
+
rename,
|
|
11
|
+
rm,
|
|
12
|
+
stat,
|
|
13
|
+
writeFile,
|
|
14
|
+
} from "node:fs/promises";
|
|
15
|
+
import { builtinModules, createRequire } from "node:module";
|
|
16
|
+
import { dirname, extname, join, relative, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
import * as esbuild from "esbuild-wasm/esm/browser.js";
|
|
19
|
+
|
|
20
|
+
const MANIFEST_VERSION = 1;
|
|
21
|
+
const MAX_DIAGNOSTIC_BYTES = 2 * 1024 * 1024;
|
|
22
|
+
const OPTIONAL_RUNTIME_MODULES = new Set([
|
|
23
|
+
"bufferutil",
|
|
24
|
+
"cbor-extract",
|
|
25
|
+
"utf-8-validate",
|
|
26
|
+
"ws",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const configPath = process.argv[2];
|
|
30
|
+
if (!configPath) {
|
|
31
|
+
throw new Error("usage: apps-builder <config.json>");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const config = JSON.parse(await readFile(configPath, "utf8"));
|
|
35
|
+
const workspace = resolve(config.workspace);
|
|
36
|
+
const release = resolve(config.release);
|
|
37
|
+
const entrypoint = resolve(workspace, config.entrypoint);
|
|
38
|
+
const maxOutputBytes = positiveInteger(config.maxOutputBytes, "maxOutputBytes");
|
|
39
|
+
const maxOutputFiles = positiveInteger(config.maxOutputFiles, "maxOutputFiles");
|
|
40
|
+
const maxFileBytes = positiveInteger(config.maxFileBytes, "maxFileBytes");
|
|
41
|
+
|
|
42
|
+
await rm(release, { recursive: true, force: true });
|
|
43
|
+
await mkdir(join(release, "modules"), { recursive: true });
|
|
44
|
+
|
|
45
|
+
const define = {
|
|
46
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
47
|
+
};
|
|
48
|
+
const require = createRequire(pathToFileURL(entrypoint));
|
|
49
|
+
const builderRequire = createRequire(import.meta.url);
|
|
50
|
+
if (config.usesRivetKit) {
|
|
51
|
+
const wasmSource = require.resolve(
|
|
52
|
+
"@rivetkit/rivetkit-wasm/rivetkit_wasm_bg.wasm",
|
|
53
|
+
);
|
|
54
|
+
const wasmBytes = await readFile(wasmSource);
|
|
55
|
+
const hash = sha256(wasmBytes);
|
|
56
|
+
const wasmName = `rivetkit-${hash.slice(0, 16)}.wasm`;
|
|
57
|
+
await copyFile(wasmSource, join(release, "modules", wasmName));
|
|
58
|
+
define.__AGENTOS_RIVETKIT_WASM_PATH__ = JSON.stringify(
|
|
59
|
+
`./modules/${wasmName}`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The Node entrypoint for esbuild-wasm starts a child process. AgentOS supports
|
|
64
|
+
// child processes, but the bundler does not need that extra transport layer.
|
|
65
|
+
// Run the browser service in-process and resolve files through this bounded
|
|
66
|
+
// platform-owned plugin instead.
|
|
67
|
+
globalThis.self ??= globalThis;
|
|
68
|
+
const esbuildWasm = await readFile(
|
|
69
|
+
builderRequire.resolve("esbuild-wasm/esbuild.wasm"),
|
|
70
|
+
);
|
|
71
|
+
await esbuild.initialize({
|
|
72
|
+
wasmModule: new WebAssembly.Module(esbuildWasm),
|
|
73
|
+
worker: false,
|
|
74
|
+
});
|
|
75
|
+
const build = await esbuild.build({
|
|
76
|
+
entryPoints: [entrypoint],
|
|
77
|
+
outfile: join(release, "main.mjs"),
|
|
78
|
+
bundle: true,
|
|
79
|
+
format: "esm",
|
|
80
|
+
platform: "node",
|
|
81
|
+
target: "node22",
|
|
82
|
+
banner: {
|
|
83
|
+
js: 'import { createRequire as __agentOSCreateRequire } from "node:module"; const require = __agentOSCreateRequire(import.meta.url);',
|
|
84
|
+
},
|
|
85
|
+
treeShaking: true,
|
|
86
|
+
minify: true,
|
|
87
|
+
sourcemap: "external",
|
|
88
|
+
// esbuild-wasm's in-process browser service attempts to JSON-decode an empty
|
|
89
|
+
// metafile before reporting build errors. The release manifest below carries
|
|
90
|
+
// the production provenance and hashes we need.
|
|
91
|
+
metafile: false,
|
|
92
|
+
write: false,
|
|
93
|
+
logLevel: "silent",
|
|
94
|
+
define,
|
|
95
|
+
assetNames: "modules/[name]-[hash]",
|
|
96
|
+
loader: {
|
|
97
|
+
".wasm": "file",
|
|
98
|
+
".bin": "file",
|
|
99
|
+
".sql": "text",
|
|
100
|
+
".txt": "text",
|
|
101
|
+
},
|
|
102
|
+
plugins: [nodeFileSystemPlugin()],
|
|
103
|
+
});
|
|
104
|
+
await esbuild.stop();
|
|
105
|
+
|
|
106
|
+
for (const output of build.outputFiles ?? []) {
|
|
107
|
+
const outputPath = resolve(output.path);
|
|
108
|
+
if (
|
|
109
|
+
outputPath !== join(release, "main.mjs") &&
|
|
110
|
+
!outputPath.startsWith(`${release}/`)
|
|
111
|
+
) {
|
|
112
|
+
throw new Error(`App Bundle output escapes release root: ${output.path}`);
|
|
113
|
+
}
|
|
114
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
115
|
+
await writeFile(outputPath, output.contents);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const unsupported = build.warnings.filter((warning) =>
|
|
119
|
+
/dynamic import|not be bundled|unsupported/i.test(warning.text),
|
|
120
|
+
);
|
|
121
|
+
if (unsupported.length > 0) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`unsupported non-analyzable import: ${formatMessages(unsupported)}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const sourceMap = join(release, "main.mjs.map");
|
|
128
|
+
await rename(sourceMap, `${configPath}.map`).catch(async (error) => {
|
|
129
|
+
if (error?.code !== "ENOENT") throw error;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const staticRoot =
|
|
133
|
+
config.staticRoot ??
|
|
134
|
+
((await stat(join(workspace, "public")).catch(() => null))?.isDirectory()
|
|
135
|
+
? "public"
|
|
136
|
+
: undefined);
|
|
137
|
+
if (staticRoot === ".") {
|
|
138
|
+
for (const sourcePath of config.sourceFiles ?? []) {
|
|
139
|
+
const source = resolve(workspace, sourcePath);
|
|
140
|
+
const target = resolve(join(release, "public"), sourcePath);
|
|
141
|
+
if (
|
|
142
|
+
!source.startsWith(`${workspace}/`) ||
|
|
143
|
+
!target.startsWith(`${join(release, "public")}/`)
|
|
144
|
+
) {
|
|
145
|
+
throw new Error(`static source path escapes its root: ${sourcePath}`);
|
|
146
|
+
}
|
|
147
|
+
const info = await stat(source);
|
|
148
|
+
await mkdir(dirname(target), { recursive: true });
|
|
149
|
+
if (info.isDirectory()) {
|
|
150
|
+
await cp(source, target, { recursive: true, force: false });
|
|
151
|
+
} else if (info.isFile()) {
|
|
152
|
+
await copyFile(source, target);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
} else if (staticRoot) {
|
|
156
|
+
const staticSource = resolve(workspace, staticRoot);
|
|
157
|
+
const staticInfo = await stat(staticSource);
|
|
158
|
+
if (!staticInfo.isDirectory()) {
|
|
159
|
+
throw new Error(`static root is not a directory: ${staticRoot}`);
|
|
160
|
+
}
|
|
161
|
+
await cp(staticSource, join(release, "public"), {
|
|
162
|
+
recursive: true,
|
|
163
|
+
force: false,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const entries = await walkRelease(release);
|
|
168
|
+
if (entries.length > maxOutputFiles) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`App Bundle emitted ${entries.length} files, limit is maxOutputFiles ${maxOutputFiles}`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
let totalBytes = 0;
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
if (entry.size > maxFileBytes) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`App Bundle file ${entry.path} is ${entry.size} bytes, limit is maxFileBytes ${maxFileBytes}`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
totalBytes += entry.size;
|
|
181
|
+
}
|
|
182
|
+
if (totalBytes > maxOutputBytes) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
`App Bundle is ${totalBytes} bytes, limit is maxOutputBytes ${maxOutputBytes}`,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const manifest = {
|
|
189
|
+
version: MANIFEST_VERSION,
|
|
190
|
+
mainModule: "main.mjs",
|
|
191
|
+
modules: entries
|
|
192
|
+
.filter((entry) => !entry.path.startsWith("public/"))
|
|
193
|
+
.map((entry) => ({
|
|
194
|
+
path: entry.path,
|
|
195
|
+
type: entry.path.endsWith(".wasm")
|
|
196
|
+
? "wasm"
|
|
197
|
+
: entry.path.endsWith(".mjs") || entry.path.endsWith(".js")
|
|
198
|
+
? "esm"
|
|
199
|
+
: "data",
|
|
200
|
+
size: entry.size,
|
|
201
|
+
hash: entry.hash,
|
|
202
|
+
})),
|
|
203
|
+
assets: entries
|
|
204
|
+
.filter((entry) => entry.path.startsWith("public/"))
|
|
205
|
+
.map((entry) => ({
|
|
206
|
+
path: entry.path,
|
|
207
|
+
size: entry.size,
|
|
208
|
+
hash: entry.hash,
|
|
209
|
+
})),
|
|
210
|
+
};
|
|
211
|
+
await writeFile(
|
|
212
|
+
join(release, "manifest.json"),
|
|
213
|
+
`${JSON.stringify(manifest, null, 2)}\n`,
|
|
214
|
+
);
|
|
215
|
+
await writeFile(
|
|
216
|
+
join(release, "agentos-package.json"),
|
|
217
|
+
`${JSON.stringify({
|
|
218
|
+
name: "agentos-app",
|
|
219
|
+
version: String(config.version),
|
|
220
|
+
})}\n`,
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
function positiveInteger(value, name) {
|
|
224
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
225
|
+
throw new TypeError(`${name} must be a positive safe integer`);
|
|
226
|
+
}
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function sha256(bytes) {
|
|
231
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function walkRelease(root) {
|
|
235
|
+
const files = [];
|
|
236
|
+
const walk = async (directory) => {
|
|
237
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
238
|
+
const path = join(directory, entry.name);
|
|
239
|
+
if (entry.isDirectory()) {
|
|
240
|
+
await walk(path);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (!entry.isFile()) {
|
|
244
|
+
throw new Error(`App Bundle contains unsupported entry: ${path}`);
|
|
245
|
+
}
|
|
246
|
+
const bytes = await readFile(path);
|
|
247
|
+
files.push({
|
|
248
|
+
path: relative(root, path).split("\\").join("/"),
|
|
249
|
+
size: bytes.byteLength,
|
|
250
|
+
hash: sha256(bytes),
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
await walk(root);
|
|
255
|
+
return files.sort((a, b) => a.path.localeCompare(b.path));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function formatMessages(messages) {
|
|
259
|
+
return messages
|
|
260
|
+
.map((message) => message.text)
|
|
261
|
+
.join("\n")
|
|
262
|
+
.slice(0, MAX_DIAGNOSTIC_BYTES);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function nodeFileSystemPlugin() {
|
|
266
|
+
const builtins = new Set([
|
|
267
|
+
...builtinModules,
|
|
268
|
+
...builtinModules.map((name) => `node:${name}`),
|
|
269
|
+
]);
|
|
270
|
+
return {
|
|
271
|
+
name: "agentos-node-filesystem",
|
|
272
|
+
setup(build) {
|
|
273
|
+
build.onResolve({ filter: /.*/ }, async (args) => {
|
|
274
|
+
if (builtins.has(args.path)) {
|
|
275
|
+
return { path: args.path, external: true };
|
|
276
|
+
}
|
|
277
|
+
const importer =
|
|
278
|
+
args.kind === "entry-point" || !args.importer
|
|
279
|
+
? entrypoint
|
|
280
|
+
: args.importer;
|
|
281
|
+
try {
|
|
282
|
+
if (
|
|
283
|
+
args.kind === "import-statement" ||
|
|
284
|
+
args.kind === "dynamic-import"
|
|
285
|
+
) {
|
|
286
|
+
return {
|
|
287
|
+
path: await resolveEsmImport(args.path, importer),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const resolver = createRequire(pathToFileURL(importer));
|
|
291
|
+
return { path: resolver.resolve(args.path) };
|
|
292
|
+
} catch (error) {
|
|
293
|
+
if (OPTIONAL_RUNTIME_MODULES.has(args.path)) {
|
|
294
|
+
return { path: args.path, external: true };
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
errors: [
|
|
298
|
+
{
|
|
299
|
+
text: `could not resolve ${JSON.stringify(args.path)} from ${importer}: ${error instanceof Error ? error.message : String(error)}`,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
build.onLoad({ filter: /.*/ }, async (args) => {
|
|
306
|
+
const extension = extname(args.path).toLowerCase();
|
|
307
|
+
if (extension === ".node") {
|
|
308
|
+
return {
|
|
309
|
+
errors: [
|
|
310
|
+
{
|
|
311
|
+
text: `native Node addon is unsupported in AgentOS Apps: ${args.path}`,
|
|
312
|
+
},
|
|
313
|
+
],
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
let contents = await readFile(args.path);
|
|
317
|
+
if (
|
|
318
|
+
config.usesRivetKit &&
|
|
319
|
+
(extension === ".js" ||
|
|
320
|
+
extension === ".mjs" ||
|
|
321
|
+
extension === ".ts")
|
|
322
|
+
) {
|
|
323
|
+
// RivetKit deliberately hides this optional dependency from
|
|
324
|
+
// ordinary bundlers. Apps always select the WASM runtime, so
|
|
325
|
+
// make that one runtime edge statically analyzable while
|
|
326
|
+
// leaving the native and engine-CLI fallbacks unreachable.
|
|
327
|
+
const source = contents.toString("utf8");
|
|
328
|
+
contents = Buffer.from(
|
|
329
|
+
source.replaceAll(
|
|
330
|
+
'import(["@rivetkit", "rivetkit-wasm"].join("/"))',
|
|
331
|
+
'import("@rivetkit/rivetkit-wasm")',
|
|
332
|
+
),
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
contents,
|
|
337
|
+
loader:
|
|
338
|
+
extension === ".json"
|
|
339
|
+
? "json"
|
|
340
|
+
: extension === ".ts" || extension === ".cts"
|
|
341
|
+
? "ts"
|
|
342
|
+
: extension === ".tsx"
|
|
343
|
+
? "tsx"
|
|
344
|
+
: extension === ".jsx"
|
|
345
|
+
? "jsx"
|
|
346
|
+
: extension === ".css"
|
|
347
|
+
? "css"
|
|
348
|
+
: extension === ".sql" || extension === ".txt"
|
|
349
|
+
? "text"
|
|
350
|
+
: extension === ".wasm" || extension === ".bin"
|
|
351
|
+
? "file"
|
|
352
|
+
: "js",
|
|
353
|
+
};
|
|
354
|
+
});
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function resolveEsmImport(specifier, importer) {
|
|
360
|
+
if (specifier.startsWith("file:")) return fileURLToPath(specifier);
|
|
361
|
+
if (
|
|
362
|
+
specifier.startsWith("./") ||
|
|
363
|
+
specifier.startsWith("../") ||
|
|
364
|
+
specifier.startsWith("/")
|
|
365
|
+
) {
|
|
366
|
+
return resolveModuleFile(
|
|
367
|
+
specifier.startsWith("/")
|
|
368
|
+
? specifier
|
|
369
|
+
: resolve(dirname(importer), specifier),
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
if (specifier.startsWith("#")) {
|
|
373
|
+
return resolvePackageImport(specifier, importer);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const parts = specifier.split("/");
|
|
377
|
+
const packageName = specifier.startsWith("@")
|
|
378
|
+
? parts.slice(0, 2).join("/")
|
|
379
|
+
: parts[0];
|
|
380
|
+
const packageSubpath = parts.slice(packageName.startsWith("@") ? 2 : 1);
|
|
381
|
+
let directory = dirname(importer);
|
|
382
|
+
for (;;) {
|
|
383
|
+
const packageRoot = join(directory, "node_modules", packageName);
|
|
384
|
+
const packageJsonPath = join(packageRoot, "package.json");
|
|
385
|
+
const packageJsonText = await readFile(packageJsonPath, "utf8").catch(
|
|
386
|
+
(error) => {
|
|
387
|
+
if (error?.code === "ENOENT") return undefined;
|
|
388
|
+
throw error;
|
|
389
|
+
},
|
|
390
|
+
);
|
|
391
|
+
if (packageJsonText !== undefined) {
|
|
392
|
+
const packageJson = JSON.parse(packageJsonText);
|
|
393
|
+
const subpath = packageSubpath.length
|
|
394
|
+
? `./${packageSubpath.join("/")}`
|
|
395
|
+
: ".";
|
|
396
|
+
const exported = selectPackageExport(packageJson.exports, subpath);
|
|
397
|
+
if (exported) return resolveModuleFile(resolve(packageRoot, exported));
|
|
398
|
+
const fallback = packageSubpath.length
|
|
399
|
+
? join(packageRoot, ...packageSubpath)
|
|
400
|
+
: resolve(
|
|
401
|
+
packageRoot,
|
|
402
|
+
typeof packageJson.module === "string"
|
|
403
|
+
? packageJson.module
|
|
404
|
+
: typeof packageJson.main === "string"
|
|
405
|
+
? packageJson.main
|
|
406
|
+
: "index.js",
|
|
407
|
+
);
|
|
408
|
+
return resolveModuleFile(fallback);
|
|
409
|
+
}
|
|
410
|
+
const parent = dirname(directory);
|
|
411
|
+
if (parent === directory) break;
|
|
412
|
+
directory = parent;
|
|
413
|
+
}
|
|
414
|
+
throw new Error(
|
|
415
|
+
`Cannot find package ${JSON.stringify(packageName)} imported from ${importer}`,
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
async function resolvePackageImport(specifier, importer) {
|
|
420
|
+
let directory = dirname(importer);
|
|
421
|
+
for (;;) {
|
|
422
|
+
const packageJsonPath = join(directory, "package.json");
|
|
423
|
+
const packageJsonText = await readFile(packageJsonPath, "utf8").catch(
|
|
424
|
+
(error) => {
|
|
425
|
+
if (error?.code === "ENOENT") return undefined;
|
|
426
|
+
throw error;
|
|
427
|
+
},
|
|
428
|
+
);
|
|
429
|
+
if (packageJsonText !== undefined) {
|
|
430
|
+
const packageJson = JSON.parse(packageJsonText);
|
|
431
|
+
const imports = packageJson.imports;
|
|
432
|
+
if (imports && typeof imports === "object" && !Array.isArray(imports)) {
|
|
433
|
+
const exact = imports[specifier];
|
|
434
|
+
if (exact !== undefined) {
|
|
435
|
+
const selected = selectConditionalExport(exact);
|
|
436
|
+
if (selected) return resolveModuleFile(resolve(directory, selected));
|
|
437
|
+
}
|
|
438
|
+
for (const [key, value] of Object.entries(imports)) {
|
|
439
|
+
const star = key.indexOf("*");
|
|
440
|
+
if (
|
|
441
|
+
star < 0 ||
|
|
442
|
+
!specifier.startsWith(key.slice(0, star)) ||
|
|
443
|
+
!specifier.endsWith(key.slice(star + 1))
|
|
444
|
+
) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
const matched = specifier.slice(
|
|
448
|
+
star,
|
|
449
|
+
specifier.length - (key.length - star - 1),
|
|
450
|
+
);
|
|
451
|
+
const selected = selectConditionalExport(value);
|
|
452
|
+
if (selected) {
|
|
453
|
+
return resolveModuleFile(
|
|
454
|
+
resolve(directory, selected.replaceAll("*", matched)),
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const parent = dirname(directory);
|
|
461
|
+
if (parent === directory) break;
|
|
462
|
+
directory = parent;
|
|
463
|
+
}
|
|
464
|
+
throw new Error(
|
|
465
|
+
`Cannot resolve package import ${JSON.stringify(specifier)} from ${importer}`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function selectPackageExport(exportsValue, subpath) {
|
|
470
|
+
if (typeof exportsValue === "string") {
|
|
471
|
+
return subpath === "." ? exportsValue : undefined;
|
|
472
|
+
}
|
|
473
|
+
if (Array.isArray(exportsValue)) {
|
|
474
|
+
for (const value of exportsValue) {
|
|
475
|
+
const selected = selectPackageExport(value, subpath);
|
|
476
|
+
if (selected) return selected;
|
|
477
|
+
}
|
|
478
|
+
return undefined;
|
|
479
|
+
}
|
|
480
|
+
if (
|
|
481
|
+
!exportsValue ||
|
|
482
|
+
typeof exportsValue !== "object"
|
|
483
|
+
) {
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
486
|
+
const entries = Object.entries(exportsValue);
|
|
487
|
+
if (entries.some(([key]) => key.startsWith("."))) {
|
|
488
|
+
const exact = exportsValue[subpath];
|
|
489
|
+
if (exact !== undefined) return selectConditionalExport(exact);
|
|
490
|
+
for (const [key, value] of entries) {
|
|
491
|
+
const star = key.indexOf("*");
|
|
492
|
+
if (
|
|
493
|
+
star < 0 ||
|
|
494
|
+
!subpath.startsWith(key.slice(0, star)) ||
|
|
495
|
+
!subpath.endsWith(key.slice(star + 1))
|
|
496
|
+
) {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const matched = subpath.slice(star, subpath.length - (key.length - star - 1));
|
|
500
|
+
const selected = selectConditionalExport(value);
|
|
501
|
+
return selected?.replaceAll("*", matched);
|
|
502
|
+
}
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
return subpath === "." ? selectConditionalExport(exportsValue) : undefined;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function selectConditionalExport(value) {
|
|
509
|
+
if (typeof value === "string") return value;
|
|
510
|
+
if (Array.isArray(value)) {
|
|
511
|
+
for (const entry of value) {
|
|
512
|
+
const selected = selectConditionalExport(entry);
|
|
513
|
+
if (selected) return selected;
|
|
514
|
+
}
|
|
515
|
+
return undefined;
|
|
516
|
+
}
|
|
517
|
+
if (!value || typeof value !== "object") return undefined;
|
|
518
|
+
for (const [condition, target] of Object.entries(value)) {
|
|
519
|
+
if (
|
|
520
|
+
condition === "import" ||
|
|
521
|
+
condition === "node" ||
|
|
522
|
+
condition === "production" ||
|
|
523
|
+
condition === "default"
|
|
524
|
+
) {
|
|
525
|
+
const selected = selectConditionalExport(target);
|
|
526
|
+
if (selected) return selected;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return undefined;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
async function resolveModuleFile(candidate) {
|
|
533
|
+
const candidates = extname(candidate)
|
|
534
|
+
? [candidate]
|
|
535
|
+
: [
|
|
536
|
+
candidate,
|
|
537
|
+
`${candidate}.mjs`,
|
|
538
|
+
`${candidate}.js`,
|
|
539
|
+
`${candidate}.ts`,
|
|
540
|
+
`${candidate}.tsx`,
|
|
541
|
+
join(candidate, "index.mjs"),
|
|
542
|
+
join(candidate, "index.js"),
|
|
543
|
+
join(candidate, "index.ts"),
|
|
544
|
+
];
|
|
545
|
+
for (const path of candidates) {
|
|
546
|
+
const info = await stat(path).catch((error) => {
|
|
547
|
+
if (error?.code === "ENOENT") return undefined;
|
|
548
|
+
throw error;
|
|
549
|
+
});
|
|
550
|
+
if (info?.isFile()) return path;
|
|
551
|
+
}
|
|
552
|
+
throw new Error(`Cannot resolve module file ${candidate}`);
|
|
553
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
2
|
+
const packagePath = new URL("./package.aospkg", import.meta.url).pathname;
|
|
3
|
+
export const appsBuilderVersion = packageJson.version;
|
|
4
|
+
export const appBundleManifestVersion = 1;
|
|
5
|
+
export default { packagePath };
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentos-software/apps-builder",
|
|
3
|
+
"version": "0.0.0-fix-core-spawn-keep-stdin-open.242e11c",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"description": "Platform-owned AgentOS Apps release bundler",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"apps-builder": "./cli/apps-builder.mjs"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"cli",
|
|
21
|
+
"dist",
|
|
22
|
+
"agentos-package.json",
|
|
23
|
+
"!dist/package",
|
|
24
|
+
"!dist/package.tar"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc && rm -f dist/package.aospkg && agentos-toolchain pack . --out dist/package --prune-native",
|
|
28
|
+
"check-types": "tsc --noEmit",
|
|
29
|
+
"test": "vitest run test/ --passWithNoTests"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"esbuild-wasm": "0.27.4"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@agentos-software/manifest": "0.0.0-fix-core-spawn-keep-stdin-open.242e11c",
|
|
36
|
+
"@rivet-dev/agentos-toolchain": "0.0.0-fix-core-spawn-keep-stdin-open.242e11c",
|
|
37
|
+
"@types/node": "^22.19.15",
|
|
38
|
+
"typescript": "^5.7.3",
|
|
39
|
+
"vitest": "^2.1.9"
|
|
40
|
+
}
|
|
41
|
+
}
|