@rivet-dev/agentos-toolchain 0.0.0-nathan-agentos-package-resolution.efc374f

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.
@@ -0,0 +1,282 @@
1
+ // src/bundle.ts
2
+ import { buildSync } from "esbuild";
3
+ import { chmodSync, readFileSync, writeFileSync } from "fs";
4
+ var SHEBANG = "#!/usr/bin/env node\n";
5
+ function bundleEntry(entryFile, outFile) {
6
+ const source = readFileSync(entryFile, "utf8");
7
+ const withoutShebang = source.startsWith("#!") ? source.slice(source.indexOf("\n") + 1) : source;
8
+ const META_SHIM = "const __agentos_import_meta_url = require('url').pathToFileURL(__filename).href;";
9
+ buildSync({
10
+ stdin: {
11
+ contents: withoutShebang,
12
+ resolveDir: entryFile.slice(0, entryFile.lastIndexOf("/")),
13
+ sourcefile: entryFile,
14
+ loader: "js"
15
+ },
16
+ bundle: true,
17
+ platform: "node",
18
+ format: "cjs",
19
+ target: "node20",
20
+ outfile: outFile,
21
+ banner: { js: `${SHEBANG.trimEnd()}
22
+ ${META_SHIM}` },
23
+ define: { "import.meta.url": "__agentos_import_meta_url" },
24
+ logLevel: "silent"
25
+ });
26
+ chmodSync(outFile, 493);
27
+ const out = readFileSync(outFile, "utf8");
28
+ if (!out.startsWith(SHEBANG)) {
29
+ writeFileSync(outFile, `${SHEBANG}${out.replace(/^#![^\n]*\n?/, "")}`);
30
+ chmodSync(outFile, 493);
31
+ }
32
+ }
33
+
34
+ // src/header.ts
35
+ var WASM_MAGIC = Buffer.from([0, 97, 115, 109]);
36
+ var ELF_MAGIC = Buffer.from([127, 69, 76, 70]);
37
+ var MACHO_MAGICS = [
38
+ 4277009102,
39
+ 3472551422,
40
+ 4277009103,
41
+ 3489328638,
42
+ 3405691582,
43
+ 3199925962
44
+ ];
45
+ function detectExecutableKind(head) {
46
+ if (head.length >= 2 && head[0] === 35 && head[1] === 33) {
47
+ return "shebang";
48
+ }
49
+ if (head.length >= 4 && head.subarray(0, 4).equals(WASM_MAGIC)) {
50
+ return "wasm";
51
+ }
52
+ if (head.length >= 4 && head.subarray(0, 4).equals(ELF_MAGIC)) {
53
+ return "native-elf";
54
+ }
55
+ if (head.length >= 4) {
56
+ const be = head.readUInt32BE(0);
57
+ if (be === 3405691582 && head.length >= 8) {
58
+ const next = head.readUInt32BE(4);
59
+ if (next >= 45) return "unknown";
60
+ }
61
+ if (MACHO_MAGICS.includes(be)) return "native-macho";
62
+ }
63
+ if (head.length >= 2 && head[0] === 77 && head[1] === 90) {
64
+ return "native-pe";
65
+ }
66
+ return "unknown";
67
+ }
68
+ function isNativeKind(kind) {
69
+ return kind === "native-elf" || kind === "native-macho" || kind === "native-pe";
70
+ }
71
+ function parseShebangInterpreter(head) {
72
+ if (!(head.length >= 2 && head[0] === 35 && head[1] === 33)) return null;
73
+ const nl = head.indexOf(10);
74
+ const line = head.subarray(2, nl < 0 ? head.length : nl).toString("utf8");
75
+ const trimmed = line.replace(/^\s+/, "");
76
+ const interp = trimmed.split(/\s+/, 1)[0] ?? "";
77
+ return interp.length > 0 ? interp : null;
78
+ }
79
+
80
+ // src/manifest.ts
81
+ function makeManifest(name, version, acpEntrypoint) {
82
+ const manifest = { name, version };
83
+ if (acpEntrypoint) {
84
+ manifest.agent = { acpEntrypoint };
85
+ }
86
+ return manifest;
87
+ }
88
+ function manifestJson(manifest) {
89
+ return `${JSON.stringify(manifest, null, 2)}
90
+ `;
91
+ }
92
+
93
+ // src/pack.ts
94
+ import { execFileSync } from "child_process";
95
+ import {
96
+ cpSync,
97
+ existsSync,
98
+ mkdirSync,
99
+ mkdtempSync,
100
+ openSync,
101
+ readFileSync as readFileSync2,
102
+ readSync,
103
+ closeSync,
104
+ lstatSync,
105
+ readdirSync,
106
+ rmSync,
107
+ statSync,
108
+ symlinkSync,
109
+ unlinkSync,
110
+ writeFileSync as writeFileSync2
111
+ } from "fs";
112
+ import { tmpdir } from "os";
113
+ import { join, relative, resolve } from "path";
114
+ var HEAD_BYTES = 256;
115
+ function readHead(file) {
116
+ const fd = openSync(file, "r");
117
+ try {
118
+ const buf = Buffer.alloc(HEAD_BYTES);
119
+ const n = readSync(fd, buf, 0, HEAD_BYTES, 0);
120
+ return buf.subarray(0, n);
121
+ } finally {
122
+ closeSync(fd);
123
+ }
124
+ }
125
+ function npmInstallFlat(source, into) {
126
+ mkdirSync(join(into, "node_modules"), { recursive: true });
127
+ execFileSync(
128
+ "npm",
129
+ [
130
+ "install",
131
+ source,
132
+ "--omit=dev",
133
+ "--ignore-scripts",
134
+ "--no-audit",
135
+ "--no-fund",
136
+ "--no-package-lock",
137
+ "--install-strategy=hoisted",
138
+ "--prefix",
139
+ into
140
+ ],
141
+ { stdio: "pipe" }
142
+ );
143
+ }
144
+ function installedPackageName(source) {
145
+ if (existsSync(source) && statSync(source).isDirectory()) {
146
+ const pkg = JSON.parse(readFileSync2(join(source, "package.json"), "utf8"));
147
+ return pkg.name;
148
+ }
149
+ const at = source.lastIndexOf("@");
150
+ return at > 0 ? source.slice(0, at) : source;
151
+ }
152
+ function binEntries(pkgDir) {
153
+ const pkg = JSON.parse(readFileSync2(join(pkgDir, "package.json"), "utf8"));
154
+ const bin = pkg.bin;
155
+ if (!bin) return {};
156
+ if (typeof bin === "string") {
157
+ return { [pkg.name.replace(/^@[^/]+\//, "")]: bin };
158
+ }
159
+ return bin;
160
+ }
161
+ function findNativeAddons(root) {
162
+ const hits = [];
163
+ const walk = (dir) => {
164
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
165
+ const p = join(dir, entry.name);
166
+ if (entry.isDirectory()) walk(p);
167
+ else if (entry.isFile() && entry.name.endsWith(".node")) hits.push(p);
168
+ }
169
+ };
170
+ if (existsSync(root)) walk(root);
171
+ return hits;
172
+ }
173
+ function verifyPackageDir(packageDir) {
174
+ if (!existsSync(join(packageDir, "agentos-package.json"))) {
175
+ throw new Error(`missing required agentos-package.json in ${packageDir}`);
176
+ }
177
+ const binDir = join(packageDir, "bin");
178
+ if (!existsSync(binDir)) {
179
+ throw new Error(`package has no bin/ directory: ${packageDir}`);
180
+ }
181
+ for (const entry of readdirSync(binDir)) {
182
+ const target = resolve(binDir, entry);
183
+ const kind = detectExecutableKind(readHead(target));
184
+ if (isNativeKind(kind)) {
185
+ throw new Error(
186
+ `bin/${entry} is a native ${kind} binary, which cannot run in agentOS`
187
+ );
188
+ }
189
+ if (kind === "unknown") {
190
+ throw new Error(
191
+ `bin/${entry} has no recognized header \u2014 JS/script commands need a '#!' shebang`
192
+ );
193
+ }
194
+ }
195
+ const addons = findNativeAddons(join(packageDir, "node_modules"));
196
+ if (addons.length > 0) {
197
+ throw new Error(
198
+ `package contains native .node addons (won't load in V8): ${addons.map((a) => relative(packageDir, a)).join(", ")}`
199
+ );
200
+ }
201
+ }
202
+ function pack(options) {
203
+ const { source, out, agent, bundle, pruneNative } = options;
204
+ const tmp = mkdtempSync(join(tmpdir(), "agentos-pack-"));
205
+ try {
206
+ const absSource = existsSync(source) && statSync(source).isDirectory() ? resolve(source) : source;
207
+ npmInstallFlat(absSource, tmp);
208
+ const name = installedPackageName(source);
209
+ const installedDir = join(tmp, "node_modules", name);
210
+ const pkg = JSON.parse(readFileSync2(join(installedDir, "package.json"), "utf8"));
211
+ const version = pkg.version;
212
+ const bins = binEntries(installedDir);
213
+ const commands = Object.keys(bins);
214
+ if (commands.length === 0) {
215
+ throw new Error(`package "${name}" declares no bin commands`);
216
+ }
217
+ if (agent && !commands.includes(agent)) {
218
+ throw new Error(
219
+ `--agent "${agent}" is not one of the package's commands: ${commands.join(", ")}`
220
+ );
221
+ }
222
+ const packageDir = join(out, name, version);
223
+ rmSync(packageDir, { recursive: true, force: true });
224
+ mkdirSync(packageDir, { recursive: true });
225
+ const binDir = join(packageDir, "bin");
226
+ mkdirSync(binDir, { recursive: true });
227
+ if (bundle) {
228
+ for (const [cmd, entryRel] of Object.entries(bins)) {
229
+ const entryAbs = join(installedDir, entryRel);
230
+ bundleEntry(entryAbs, join(binDir, cmd));
231
+ }
232
+ } else {
233
+ cpSync(join(tmp, "node_modules"), join(packageDir, "node_modules"), {
234
+ recursive: true
235
+ });
236
+ for (const [cmd, entryRel] of Object.entries(bins)) {
237
+ const targetAbs = join(packageDir, "node_modules", name, entryRel);
238
+ symlinkSync(relative(binDir, targetAbs), join(binDir, cmd));
239
+ }
240
+ if (pruneNative) {
241
+ const addons = findNativeAddons(join(packageDir, "node_modules"));
242
+ for (const addon of addons) {
243
+ rmSync(addon, { force: true });
244
+ }
245
+ if (addons.length > 0) {
246
+ console.warn(
247
+ `[agentos-toolchain] pruned ${addons.length} native .node addon(s) from ${name} (--prune-native); they must be unreachable on the V8 code path`
248
+ );
249
+ }
250
+ }
251
+ }
252
+ writeFileSync2(
253
+ join(packageDir, "agentos-package.json"),
254
+ manifestJson(makeManifest(name, version, agent))
255
+ );
256
+ const currentLink = join(out, name, "current");
257
+ try {
258
+ if (lstatSync(currentLink).isSymbolicLink()) {
259
+ unlinkSync(currentLink);
260
+ } else {
261
+ rmSync(currentLink, { recursive: true, force: true });
262
+ }
263
+ } catch {
264
+ }
265
+ symlinkSync(version, currentLink);
266
+ verifyPackageDir(packageDir);
267
+ return { name, version, packageDir, commands };
268
+ } finally {
269
+ rmSync(tmp, { recursive: true, force: true });
270
+ }
271
+ }
272
+
273
+ export {
274
+ bundleEntry,
275
+ detectExecutableKind,
276
+ isNativeKind,
277
+ parseShebangInterpreter,
278
+ makeManifest,
279
+ manifestJson,
280
+ verifyPackageDir,
281
+ pack
282
+ };
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ pack
4
+ } from "./chunk-CSSRRHDX.js";
5
+
6
+ // src/cli.ts
7
+ import { existsSync, statSync } from "fs";
8
+ import { basename, resolve } from "path";
9
+ var USAGE = `agentos-toolchain \u2014 build agentOS packages
10
+
11
+ Usage:
12
+ agentos-toolchain pack <npm-pkg | ./local-dir> [options]
13
+
14
+ Options:
15
+ --agent <command> mark a bin command as the package's ACP entrypoint
16
+ --out <dir> output dir for the package itself (FLAT;
17
+ default: ./<input-name>-package)
18
+ --prune-native delete unreachable native .node addons from the flat closure
19
+ -h, --help show this help
20
+ `;
21
+ function defaultOutName(source) {
22
+ if (existsSync(source) && statSync(source).isDirectory()) {
23
+ return `./${basename(resolve(source))}-package`;
24
+ }
25
+ const at = source.lastIndexOf("@");
26
+ const name = at > 0 ? source.slice(0, at) : source;
27
+ return `./${name.replace(/^@[^/]+\//, "")}-package`;
28
+ }
29
+ function parseArgs(argv) {
30
+ const [cmd, ...rest] = argv;
31
+ let source;
32
+ let agent;
33
+ let out;
34
+ let pruneNative = false;
35
+ for (let i = 0; i < rest.length; i++) {
36
+ const a = rest[i];
37
+ if (a === "--agent") agent = rest[++i];
38
+ else if (a === "--out") out = rest[++i];
39
+ else if (a === "--prune-native") pruneNative = true;
40
+ else if (a === "-h" || a === "--help") {
41
+ process.stdout.write(USAGE);
42
+ process.exit(0);
43
+ } else if (!a.startsWith("-") && source === void 0) source = a;
44
+ else throw new Error(`unexpected argument: ${a}`);
45
+ }
46
+ return { cmd, source, agent, out, pruneNative };
47
+ }
48
+ function main() {
49
+ const args = parseArgs(process.argv.slice(2));
50
+ if (args.cmd === void 0 || args.cmd === "-h" || args.cmd === "--help") {
51
+ process.stdout.write(USAGE);
52
+ process.exit(args.cmd === void 0 ? 1 : 0);
53
+ }
54
+ if (args.cmd !== "pack") {
55
+ throw new Error(`unknown command "${args.cmd}" (only "pack" is supported)`);
56
+ }
57
+ if (!args.source) throw new Error("pack requires a <npm-pkg | ./local-dir> argument");
58
+ const result = pack({
59
+ source: args.source,
60
+ out: resolve(args.out ?? defaultOutName(args.source)),
61
+ agent: args.agent,
62
+ pruneNative: args.pruneNative
63
+ });
64
+ process.stdout.write(
65
+ `packed ${result.name}@${result.version} \u2192 ${result.packageDir}
66
+ commands: ${result.commands.join(", ")}
67
+ `
68
+ );
69
+ }
70
+ try {
71
+ main();
72
+ } catch (error) {
73
+ process.stderr.write(`error: ${error instanceof Error ? error.message : String(error)}
74
+ `);
75
+ process.exit(1);
76
+ }
@@ -0,0 +1,50 @@
1
+ interface PackOptions {
2
+ /** npm package spec (`name`, `name@version`) or a local directory path. */
3
+ source: string;
4
+ /**
5
+ * Output dir for the package itself (FLAT): the package lands directly at
6
+ * `<out>/{bin/, node_modules/, package.json}`. The versioned
7
+ * `/opt/agentos/<name>/<version>` + `current` layout is the sidecar
8
+ * projection's job (name from the descriptor, version from this package.json).
9
+ */
10
+ out: string;
11
+ /** Mark a bin command as the package's ACP entrypoint (validated against bin/). */
12
+ agent?: string;
13
+ /**
14
+ * Delete native `.node` addons from the flat closure instead of failing.
15
+ * Use when a package's dependency tree contains optional/platform native
16
+ * addons (e.g. `koffi`, `clipboard-*`) that are never loaded on the code path
17
+ * that runs in V8. The JS closure (including dynamically-required modules) is
18
+ * kept; only the V8-incompatible `.node` files are removed. If a pruned addon
19
+ * IS reached at runtime it fails then — so this is opt-in.
20
+ */
21
+ pruneNative?: boolean;
22
+ }
23
+ interface PackResult {
24
+ name: string;
25
+ version: string;
26
+ packageDir: string;
27
+ commands: string[];
28
+ }
29
+ /**
30
+ * Verify a finished package directory satisfies the agentOS package format:
31
+ * every `bin/` entry has a recognized, non-native header, and the tree has no
32
+ * native `.node` addons. Throws with a clear message on the first violation.
33
+ */
34
+ declare function verifyPackageDir(packageDir: string): void;
35
+ declare function pack(options: PackOptions): PackResult;
36
+
37
+ /**
38
+ * Executable header detection — the same binfmt rules the runtime uses.
39
+ *
40
+ * Runtime is decided by the file's leading bytes, never its name or extension:
41
+ * a `#!` shebang, the `\0asm` WebAssembly magic, or a native object-file magic
42
+ * (ELF / Mach-O / PE) which agentOS cannot execute (no native-arch handler).
43
+ */
44
+ type ExecutableKind = "shebang" | "wasm" | "native-elf" | "native-macho" | "native-pe" | "unknown";
45
+ declare function detectExecutableKind(head: Buffer): ExecutableKind;
46
+ declare function isNativeKind(kind: ExecutableKind): boolean;
47
+ /** The interpreter named on a shebang line, taken literally (no PATH search). */
48
+ declare function parseShebangInterpreter(head: Buffer): string | null;
49
+
50
+ export { type ExecutableKind, type PackOptions, type PackResult, detectExecutableKind, isNativeKind, pack, parseShebangInterpreter, verifyPackageDir };
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ import {
2
+ detectExecutableKind,
3
+ isNativeKind,
4
+ pack,
5
+ parseShebangInterpreter,
6
+ verifyPackageDir
7
+ } from "./chunk-CSSRRHDX.js";
8
+ export {
9
+ detectExecutableKind,
10
+ isNativeKind,
11
+ pack,
12
+ parseShebangInterpreter,
13
+ verifyPackageDir
14
+ };
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@rivet-dev/agentos-toolchain",
3
+ "version": "0.0.0-nathan-agentos-package-resolution.efc374f",
4
+ "description": "Build toolchain for agentOS packages (pack npm packages/scripts into self-contained agentOS packages).",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "bin": {
8
+ "agentos-toolchain": "./dist/cli.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "import": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "package.json",
21
+ "README.md"
22
+ ],
23
+ "devDependencies": {
24
+ "@types/node": "^22.10.2",
25
+ "tsup": "^8.3.5",
26
+ "typescript": "^5.7.2",
27
+ "vitest": "^2.1.9"
28
+ },
29
+ "scripts": {
30
+ "build": "tsup src/index.ts src/cli.ts --format esm --dts",
31
+ "check-types": "tsc --noEmit",
32
+ "test": "vitest run"
33
+ }
34
+ }