@rivet-dev/agentos-toolchain 0.0.0-nathan-agentos-package-resolution.efc374f → 0.2.5-rc.4

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,1135 @@
1
+ // src/aospkg.ts
2
+ import { readFileSync, writeFileSync } from "fs";
3
+
4
+ // src/generated-package-format.ts
5
+ import * as bare from "@rivetkit/bare-ts";
6
+ var DEFAULT_CONFIG = /* @__PURE__ */ bare.Config({});
7
+ function writeTarEntryKind(bc, x) {
8
+ switch (x) {
9
+ case "File" /* File */: {
10
+ bare.writeU8(bc, 0);
11
+ break;
12
+ }
13
+ case "Directory" /* Directory */: {
14
+ bare.writeU8(bc, 1);
15
+ break;
16
+ }
17
+ case "Symlink" /* Symlink */: {
18
+ bare.writeU8(bc, 2);
19
+ break;
20
+ }
21
+ }
22
+ }
23
+ function write0(bc, x) {
24
+ bare.writeBool(bc, x != null);
25
+ if (x != null) {
26
+ bare.writeString(bc, x);
27
+ }
28
+ }
29
+ function writeTarEntry(bc, x) {
30
+ bare.writeString(bc, x.path);
31
+ writeTarEntryKind(bc, x.kind);
32
+ bare.writeU64(bc, x.offset);
33
+ bare.writeU64(bc, x.size);
34
+ bare.writeU32(bc, x.mode);
35
+ bare.writeU32(bc, x.uid);
36
+ bare.writeU32(bc, x.gid);
37
+ bare.writeI64(bc, x.mtime);
38
+ write0(bc, x.linkTarget);
39
+ }
40
+ function write1(bc, x) {
41
+ bare.writeUintSafe(bc, x.size);
42
+ for (const kv of x) {
43
+ bare.writeString(bc, kv[0]);
44
+ bare.writeString(bc, kv[1]);
45
+ }
46
+ }
47
+ function write2(bc, x) {
48
+ bare.writeUintSafe(bc, x.length);
49
+ for (let i = 0; i < x.length; i++) {
50
+ bare.writeString(bc, x[i]);
51
+ }
52
+ }
53
+ function writeAgentBlock(bc, x) {
54
+ bare.writeString(bc, x.acpEntrypoint);
55
+ bare.writeBool(bc, x.snapshot);
56
+ write1(bc, x.env);
57
+ write2(bc, x.launchArgs);
58
+ }
59
+ function writeCommandTarget(bc, x) {
60
+ bare.writeString(bc, x.command);
61
+ bare.writeString(bc, x.entry);
62
+ }
63
+ function writeManPage(bc, x) {
64
+ bare.writeString(bc, x.section);
65
+ bare.writeString(bc, x.page);
66
+ }
67
+ function writeProvidesFile(bc, x) {
68
+ bare.writeString(bc, x.source);
69
+ bare.writeString(bc, x.target);
70
+ }
71
+ function write3(bc, x) {
72
+ bare.writeUintSafe(bc, x.length);
73
+ for (let i = 0; i < x.length; i++) {
74
+ writeProvidesFile(bc, x[i]);
75
+ }
76
+ }
77
+ function writeProvidesBlock(bc, x) {
78
+ write1(bc, x.env);
79
+ write3(bc, x.files);
80
+ }
81
+ function write4(bc, x) {
82
+ bare.writeBool(bc, x != null);
83
+ if (x != null) {
84
+ writeAgentBlock(bc, x);
85
+ }
86
+ }
87
+ function write5(bc, x) {
88
+ bare.writeBool(bc, x != null);
89
+ if (x != null) {
90
+ writeProvidesBlock(bc, x);
91
+ }
92
+ }
93
+ function write6(bc, x) {
94
+ bare.writeUintSafe(bc, x.length);
95
+ for (let i = 0; i < x.length; i++) {
96
+ writeCommandTarget(bc, x[i]);
97
+ }
98
+ }
99
+ function write7(bc, x) {
100
+ bare.writeUintSafe(bc, x.length);
101
+ for (let i = 0; i < x.length; i++) {
102
+ writeManPage(bc, x[i]);
103
+ }
104
+ }
105
+ function writePackageManifest(bc, x) {
106
+ bare.writeString(bc, x.name);
107
+ bare.writeString(bc, x.version);
108
+ write4(bc, x.agent);
109
+ write5(bc, x.provides);
110
+ write6(bc, x.commands);
111
+ write7(bc, x.manPages);
112
+ write0(bc, x.snapshotBundlePath);
113
+ }
114
+ function encodePackageManifest(x, config) {
115
+ const fullConfig = config != null ? bare.Config(config) : DEFAULT_CONFIG;
116
+ const bc = new bare.ByteCursor(
117
+ new Uint8Array(fullConfig.initialBufferLength),
118
+ fullConfig
119
+ );
120
+ writePackageManifest(bc, x);
121
+ return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset);
122
+ }
123
+ function write8(bc, x) {
124
+ bare.writeUintSafe(bc, x.length);
125
+ for (let i = 0; i < x.length; i++) {
126
+ writeTarEntry(bc, x[i]);
127
+ }
128
+ }
129
+ function writeMountIndex(bc, x) {
130
+ write8(bc, x.tarEntries);
131
+ }
132
+ function encodeMountIndex(x, config) {
133
+ const fullConfig = config != null ? bare.Config(config) : DEFAULT_CONFIG;
134
+ const bc = new bare.ByteCursor(
135
+ new Uint8Array(fullConfig.initialBufferLength),
136
+ fullConfig
137
+ );
138
+ writeMountIndex(bc, x);
139
+ return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset);
140
+ }
141
+
142
+ // src/aospkg.ts
143
+ var AOSPKG_MAGIC = Uint8Array.from([137, 65, 79, 83]);
144
+ var AOSPKG_FORMAT_VERSION = 1;
145
+ var PACKAGE_MANIFEST_VERSION = 1;
146
+ var MANIFEST_JSON_NAME = "agentos-package.json";
147
+ var SNAPSHOT_BUNDLE_PATH = "/dist/sdk-snapshot.js";
148
+ var BLOCK = 512;
149
+ var MAX_PACK_INDEX_ENTRIES = 2e5;
150
+ function byteCompare(a, b) {
151
+ return a < b ? -1 : a > b ? 1 : 0;
152
+ }
153
+ var S_IFDIR = 16384;
154
+ var S_IFREG = 32768;
155
+ var S_IFLNK = 40960;
156
+ function packAospkgFromTar(sourceTar, dest) {
157
+ const source = readFileSync(sourceTar);
158
+ const { bytes, summary } = packAospkgFromTarBytes(source);
159
+ writeFileSync(dest, bytes);
160
+ return summary;
161
+ }
162
+ function packAospkgFromTarBytes(source) {
163
+ const members = parseTarMembers(source);
164
+ let manifestJson;
165
+ let packageJson;
166
+ const keptSlices = [];
167
+ const entries = /* @__PURE__ */ new Map();
168
+ let outOffset = 0;
169
+ for (const member of members) {
170
+ if (member.path === `/${MANIFEST_JSON_NAME}`) {
171
+ manifestJson = memberData(source, member);
172
+ continue;
173
+ }
174
+ if (member.path === "/") {
175
+ continue;
176
+ }
177
+ const indexed = indexEntry(member);
178
+ if (indexed === void 0) {
179
+ continue;
180
+ }
181
+ if (member.path === "/package.json") {
182
+ packageJson = memberData(source, member);
183
+ }
184
+ const record = source.subarray(member.recordStart, member.recordEnd);
185
+ keptSlices.push(record);
186
+ synthesizeParentDirs(member.path, entries);
187
+ entries.set(member.path, {
188
+ ...indexed,
189
+ offset: BigInt(outOffset + member.dataOffsetInRecord)
190
+ });
191
+ outOffset += record.length;
192
+ }
193
+ keptSlices.push(Buffer.alloc(2 * BLOCK));
194
+ const mountTar = Buffer.concat(keptSlices);
195
+ if (!entries.has("/")) {
196
+ entries.set("/", {
197
+ path: "/",
198
+ kind: "Directory" /* Directory */,
199
+ offset: 0n,
200
+ size: 0n,
201
+ mode: S_IFDIR | 493,
202
+ uid: 0,
203
+ gid: 0,
204
+ mtime: 0n,
205
+ linkTarget: null
206
+ });
207
+ }
208
+ if (manifestJson === void 0) {
209
+ throw new Error(`source tar must contain /${MANIFEST_JSON_NAME}`);
210
+ }
211
+ let sourceManifest;
212
+ try {
213
+ sourceManifest = JSON.parse(manifestJson.toString("utf8"));
214
+ } catch (error) {
215
+ throw new Error(`invalid ${MANIFEST_JSON_NAME}: ${String(error)}`);
216
+ }
217
+ const name = sourceManifest.name;
218
+ if (typeof name !== "string" || name.length === 0) {
219
+ throw new Error(`${MANIFEST_JSON_NAME} is missing a valid "name"`);
220
+ }
221
+ const version = sourceManifest.version;
222
+ if (typeof version !== "string" || version.length === 0) {
223
+ throw new Error(`${MANIFEST_JSON_NAME} is missing a valid "version"`);
224
+ }
225
+ if (entries.size > MAX_PACK_INDEX_ENTRIES) {
226
+ throw new Error(
227
+ `package mount index has ${entries.size} entries > MAX_PACK_INDEX_ENTRIES (${MAX_PACK_INDEX_ENTRIES}); the load-side TarFileSystem cap would reject this package at VM configure \u2014 split the package or raise both limits together`
228
+ );
229
+ }
230
+ const sortedPaths = [...entries.keys()].sort(byteCompare);
231
+ const tarEntries = sortedPaths.map((path) => entries.get(path));
232
+ const commands = commandTargets(sortedPaths, packageJson);
233
+ const manPages = manPagesFromIndex(sortedPaths);
234
+ const agent = agentBlock(sourceManifest);
235
+ const snapshotBundlePath = agent?.snapshot && entries.has(SNAPSHOT_BUNDLE_PATH) ? SNAPSHOT_BUNDLE_PATH : null;
236
+ const manifest = {
237
+ name,
238
+ version,
239
+ agent,
240
+ provides: providesBlock(sourceManifest),
241
+ commands,
242
+ manPages,
243
+ snapshotBundlePath
244
+ };
245
+ const manifestChunk = versionedChunk(encodePackageManifest(manifest));
246
+ const indexChunk = versionedChunk(encodeMountIndex({ tarEntries }));
247
+ const header = Buffer.alloc(16);
248
+ Buffer.from(AOSPKG_MAGIC).copy(header, 0);
249
+ header.writeUInt16LE(AOSPKG_FORMAT_VERSION, 4);
250
+ header.writeUInt16LE(0, 6);
251
+ header.writeUInt32LE(manifestChunk.length, 8);
252
+ header.writeUInt32LE(indexChunk.length, 12);
253
+ return {
254
+ bytes: Buffer.concat([header, manifestChunk, indexChunk, mountTar]),
255
+ summary: {
256
+ name,
257
+ version,
258
+ commands: commands.map((target) => target.command)
259
+ }
260
+ };
261
+ }
262
+ function versionedChunk(payload) {
263
+ const chunk = Buffer.alloc(2 + payload.length);
264
+ chunk.writeUInt16LE(PACKAGE_MANIFEST_VERSION, 0);
265
+ Buffer.from(payload).copy(chunk, 2);
266
+ return chunk;
267
+ }
268
+ function agentBlock(manifest) {
269
+ const agent = manifest.agent;
270
+ if (agent === void 0) return null;
271
+ return {
272
+ acpEntrypoint: agent.acpEntrypoint,
273
+ snapshot: agent.snapshot ?? false,
274
+ env: new Map(Object.entries(agent.env ?? {})),
275
+ launchArgs: agent.launchArgs ?? []
276
+ };
277
+ }
278
+ function providesBlock(manifest) {
279
+ const provides = manifest.provides;
280
+ if (provides === void 0) return null;
281
+ return {
282
+ env: new Map(Object.entries(provides.env ?? {})),
283
+ files: (provides.files ?? []).map((file) => ({
284
+ source: file.source,
285
+ target: file.target
286
+ }))
287
+ };
288
+ }
289
+ function indexEntry(member) {
290
+ const mode = member.mode & 4095;
291
+ const base = {
292
+ path: member.path,
293
+ offset: 0n,
294
+ size: 0n,
295
+ uid: member.uid,
296
+ gid: member.gid,
297
+ mtime: BigInt(member.mtime),
298
+ linkTarget: null
299
+ };
300
+ if (member.typeflag === "5") {
301
+ return { ...base, kind: "Directory" /* Directory */, mode: S_IFDIR | mode };
302
+ }
303
+ if (member.typeflag === "2") {
304
+ if (member.linkTarget === void 0) {
305
+ throw new Error(`symlink ${member.path} has no target`);
306
+ }
307
+ return {
308
+ ...base,
309
+ kind: "Symlink" /* Symlink */,
310
+ mode: S_IFLNK | Math.max(mode, 511),
311
+ linkTarget: member.linkTarget
312
+ };
313
+ }
314
+ if (member.typeflag === "0" || member.typeflag === "\0" || member.typeflag === "7") {
315
+ return {
316
+ ...base,
317
+ kind: "File" /* File */,
318
+ mode: S_IFREG | mode,
319
+ size: BigInt(member.size)
320
+ };
321
+ }
322
+ return void 0;
323
+ }
324
+ function synthesizeParentDirs(path, entries) {
325
+ const parts = path.split("/").filter((part) => part.length > 0);
326
+ let current = "";
327
+ for (const part of parts.slice(0, -1)) {
328
+ current += `/${part}`;
329
+ if (!entries.has(current)) {
330
+ entries.set(current, {
331
+ path: current,
332
+ kind: "Directory" /* Directory */,
333
+ offset: 0n,
334
+ size: 0n,
335
+ mode: S_IFDIR | 493,
336
+ uid: 0,
337
+ gid: 0,
338
+ mtime: 0n,
339
+ linkTarget: null
340
+ });
341
+ }
342
+ }
343
+ }
344
+ function commandTargets(sortedPaths, packageJson) {
345
+ if (packageJson !== void 0) {
346
+ try {
347
+ const fromBin = commandTargetsFromPackageJson(
348
+ JSON.parse(packageJson.toString("utf8"))
349
+ );
350
+ if (fromBin !== void 0) return fromBin;
351
+ } catch {
352
+ }
353
+ }
354
+ return sortedPaths.filter(
355
+ (path) => path.startsWith("/bin/") && !path.slice("/bin/".length).includes("/") && isProjectableCommandName(path.slice("/bin/".length))
356
+ ).map((path) => {
357
+ const name = path.slice("/bin/".length);
358
+ return { command: name, entry: `bin/${name}` };
359
+ });
360
+ }
361
+ function commandTargetsFromPackageJson(value) {
362
+ if (typeof value.bin === "string") {
363
+ if (typeof value.name !== "string") return void 0;
364
+ const unscoped = value.name.split("/").pop() ?? value.name;
365
+ return isProjectableCommandName(unscoped) ? [{ command: unscoped, entry: normalizeRel(value.bin) }] : [];
366
+ }
367
+ if (value.bin !== null && typeof value.bin === "object") {
368
+ return Object.entries(value.bin).filter(
369
+ ([name, entry]) => isProjectableCommandName(name) && typeof entry === "string"
370
+ ).map(([name, entry]) => ({
371
+ command: name,
372
+ entry: normalizeRel(entry)
373
+ })).sort((a, b) => byteCompare(a.command, b.command));
374
+ }
375
+ return void 0;
376
+ }
377
+ function manPagesFromIndex(sortedPaths) {
378
+ return sortedPaths.flatMap((path) => {
379
+ const suffix = path.startsWith("/share/man/") ? path.slice("/share/man/".length) : void 0;
380
+ if (suffix === void 0) return [];
381
+ const parts = suffix.split("/");
382
+ if (parts.length !== 2) return [];
383
+ return [{ section: parts[0], page: parts[1] }];
384
+ }).sort((a, b) => byteCompare(a.section, b.section) || byteCompare(a.page, b.page));
385
+ }
386
+ function isProjectableCommandName(name) {
387
+ return !name.startsWith("_") && !name.startsWith(".");
388
+ }
389
+ function normalizeRel(path) {
390
+ return path.startsWith("./") ? path.slice(2) : path;
391
+ }
392
+ function parseTarMembers(source) {
393
+ const members = [];
394
+ let offset = 0;
395
+ let pendingName;
396
+ let pendingLink;
397
+ let pendingSize;
398
+ let recordStart = 0;
399
+ let sawExtension = false;
400
+ while (offset + BLOCK <= source.length) {
401
+ const block = source.subarray(offset, offset + BLOCK);
402
+ if (isZeroBlock(block)) break;
403
+ if (!sawExtension) {
404
+ recordStart = offset;
405
+ }
406
+ const typeflag = String.fromCharCode(block[156]);
407
+ const size = parseOctal(block, 124, 12);
408
+ const dataBlocks = Math.ceil(size / BLOCK);
409
+ const dataStart = offset + BLOCK;
410
+ const next = dataStart + dataBlocks * BLOCK;
411
+ if (typeflag === "L" || typeflag === "K") {
412
+ const value = source.subarray(dataStart, dataStart + size).toString("utf8").replace(/\0+$/, "");
413
+ if (typeflag === "L") pendingName = value;
414
+ else pendingLink = value;
415
+ sawExtension = true;
416
+ offset = next;
417
+ continue;
418
+ }
419
+ if (typeflag === "x" || typeflag === "g") {
420
+ if (typeflag === "x") {
421
+ const records = parsePaxRecords(
422
+ source.subarray(dataStart, dataStart + size)
423
+ );
424
+ if (records.path !== void 0) pendingName = records.path;
425
+ if (records.linkpath !== void 0) pendingLink = records.linkpath;
426
+ if (records.size !== void 0) pendingSize = records.size;
427
+ sawExtension = true;
428
+ } else {
429
+ recordStart = next;
430
+ }
431
+ offset = next;
432
+ continue;
433
+ }
434
+ const memberSize = pendingSize ?? size;
435
+ const memberDataBlocks = Math.ceil(memberSize / BLOCK);
436
+ const memberNext = dataStart + memberDataBlocks * BLOCK;
437
+ const rawName = readCString(block, 0, 100);
438
+ const prefix = isUstar(block) ? readCString(block, 345, 155) : "";
439
+ const name = pendingName ?? (prefix.length > 0 ? `${prefix}/${rawName}` : rawName);
440
+ const linkTarget = pendingLink ?? (typeflag === "2" ? readCString(block, 157, 100) : void 0);
441
+ members.push({
442
+ path: canonicalTarPath(name),
443
+ typeflag,
444
+ mode: parseOctal(block, 100, 8),
445
+ uid: parseOctal(block, 108, 8),
446
+ gid: parseOctal(block, 116, 8),
447
+ mtime: parseOctal(block, 136, 12),
448
+ size: memberSize,
449
+ linkTarget,
450
+ recordStart,
451
+ recordEnd: memberNext,
452
+ dataOffsetInRecord: dataStart - recordStart
453
+ });
454
+ pendingName = void 0;
455
+ pendingLink = void 0;
456
+ pendingSize = void 0;
457
+ sawExtension = false;
458
+ offset = memberNext;
459
+ }
460
+ return members;
461
+ }
462
+ function memberData(source, member) {
463
+ const dataStart = member.recordStart + member.dataOffsetInRecord;
464
+ return source.subarray(dataStart, dataStart + member.size);
465
+ }
466
+ function parsePaxRecords(data) {
467
+ const out = {};
468
+ let offset = 0;
469
+ while (offset < data.length) {
470
+ const space = data.indexOf(32, offset);
471
+ if (space === -1) break;
472
+ const length = Number.parseInt(
473
+ data.subarray(offset, space).toString("latin1"),
474
+ 10
475
+ );
476
+ if (!Number.isFinite(length) || length <= 0) break;
477
+ const record = data.subarray(offset, offset + length);
478
+ const eq = record.indexOf(61);
479
+ if (eq !== -1) {
480
+ const key = record.subarray(space - offset + 1, eq).toString("utf8");
481
+ let value = record.subarray(eq + 1).toString("utf8");
482
+ value = value.endsWith("\n") ? value.slice(0, -1) : value;
483
+ if (key === "path") out.path = value;
484
+ if (key === "linkpath") out.linkpath = value;
485
+ if (key === "size") {
486
+ const parsed = Number.parseInt(value, 10);
487
+ if (Number.isFinite(parsed) && parsed >= 0) out.size = parsed;
488
+ }
489
+ }
490
+ offset += length;
491
+ }
492
+ return out;
493
+ }
494
+ function canonicalTarPath(name) {
495
+ const parts = name.split("/").filter((part) => part.length > 0 && part !== ".");
496
+ for (const part of parts) {
497
+ if (part === "..") {
498
+ throw new Error(`tar member path escapes root: ${name}`);
499
+ }
500
+ }
501
+ return parts.length === 0 ? "/" : `/${parts.join("/")}`;
502
+ }
503
+ function isUstar(block) {
504
+ return block.subarray(257, 262).toString("latin1") === "ustar";
505
+ }
506
+ function isZeroBlock(block) {
507
+ return block.every((byte) => byte === 0);
508
+ }
509
+ function readCString(block, start, length) {
510
+ const slice = block.subarray(start, start + length);
511
+ const nul = slice.indexOf(0);
512
+ return slice.subarray(0, nul === -1 ? length : nul).toString("utf8");
513
+ }
514
+ function parseOctal(block, start, length) {
515
+ const slice = block.subarray(start, start + length);
516
+ if ((slice[0] & 128) !== 0) {
517
+ if (slice[0] !== 128) {
518
+ throw new Error(
519
+ "unsupported base-256 tar numeric field (negative or oversized value)"
520
+ );
521
+ }
522
+ let value2 = 0;
523
+ for (let i = 1; i < length; i += 1) {
524
+ value2 = value2 * 256 + slice[i];
525
+ if (!Number.isSafeInteger(value2)) {
526
+ throw new Error("base-256 tar numeric field exceeds 2^53");
527
+ }
528
+ }
529
+ return value2;
530
+ }
531
+ const text = slice.toString("latin1").replace(/\0.*$/, "").trim();
532
+ if (text.length === 0) return 0;
533
+ const value = Number.parseInt(text, 8);
534
+ return Number.isFinite(value) ? value : 0;
535
+ }
536
+
537
+ // src/manifest.ts
538
+ import { existsSync, readFileSync as readFileSync2 } from "fs";
539
+ import { join } from "path";
540
+ function readManifest(packageDir) {
541
+ const path = join(packageDir, "agentos-package.json");
542
+ if (!existsSync(path)) return void 0;
543
+ let parsed;
544
+ try {
545
+ parsed = JSON.parse(readFileSync2(path, "utf8"));
546
+ } catch (error) {
547
+ throw new Error(`${path} is not valid JSON: ${String(error)}`);
548
+ }
549
+ return parsed;
550
+ }
551
+ function unscopedName(name) {
552
+ return name.replace(/^@[^/]+\//, "");
553
+ }
554
+
555
+ // src/build.ts
556
+ import {
557
+ execFileSync
558
+ } from "child_process";
559
+ import {
560
+ cpSync,
561
+ existsSync as existsSync2,
562
+ mkdirSync,
563
+ readFileSync as readFileSync3,
564
+ readdirSync,
565
+ rmSync,
566
+ statSync,
567
+ writeFileSync as writeFileSync2
568
+ } from "fs";
569
+ import { join as join2, resolve } from "path";
570
+ function build(packageDirInput) {
571
+ const packageDir = resolve(packageDirInput ?? process.cwd());
572
+ const srcPkgPath = join2(packageDir, "package.json");
573
+ if (!existsSync2(srcPkgPath)) {
574
+ throw new Error(`no package.json in ${packageDir}`);
575
+ }
576
+ let srcPkg;
577
+ try {
578
+ srcPkg = JSON.parse(readFileSync3(srcPkgPath, "utf8"));
579
+ } catch (error) {
580
+ throw new Error(
581
+ `package.json in ${packageDir} is not valid JSON: ${String(error)}`
582
+ );
583
+ }
584
+ const name = srcPkg.name;
585
+ const version = srcPkg.version;
586
+ if (typeof name !== "string" || name.length === 0) {
587
+ throw new Error(`package.json in ${packageDir} is missing a valid "name"`);
588
+ }
589
+ if (typeof version !== "string" || version.length === 0) {
590
+ throw new Error(
591
+ `package.json in ${packageDir} is missing a valid "version"`
592
+ );
593
+ }
594
+ const srcManifest = readManifest(packageDir);
595
+ const manifest = {
596
+ name: typeof srcManifest?.name === "string" && srcManifest.name.length > 0 ? srcManifest.name : unscopedName(name),
597
+ version,
598
+ ...srcManifest?.agent !== void 0 ? { agent: srcManifest.agent } : {},
599
+ ...srcManifest?.provides !== void 0 ? { provides: srcManifest.provides } : {}
600
+ };
601
+ const srcBinDir = join2(packageDir, "bin");
602
+ const hasBinDir = existsSync2(srcBinDir) && statSync(srcBinDir).isDirectory();
603
+ const commands = hasBinDir ? readdirSync(srcBinDir, { withFileTypes: true }).filter((entry) => entry.isFile() || entry.isSymbolicLink()).map((entry) => entry.name).sort() : [];
604
+ const outDir = join2(packageDir, "dist", "package");
605
+ rmSync(outDir, { recursive: true, force: true });
606
+ mkdirSync(outDir, { recursive: true });
607
+ if (commands.length > 0) {
608
+ cpSync(srcBinDir, join2(outDir, "bin"), {
609
+ recursive: true,
610
+ verbatimSymlinks: true
611
+ });
612
+ }
613
+ const srcShareDir = join2(packageDir, "share");
614
+ if (existsSync2(srcShareDir) && statSync(srcShareDir).isDirectory()) {
615
+ cpSync(srcShareDir, join2(outDir, "share"), {
616
+ recursive: true,
617
+ verbatimSymlinks: true
618
+ });
619
+ }
620
+ writeFileSync2(
621
+ join2(outDir, "agentos-package.json"),
622
+ `${JSON.stringify(manifest, null, 2)}
623
+ `
624
+ );
625
+ const outTar = join2(packageDir, "dist", "package.tar");
626
+ rmSync(outTar, { force: true });
627
+ execFileSync("tar", ["-cf", outTar, "-C", outDir, "."], { stdio: "pipe" });
628
+ const outAospkg = join2(packageDir, "dist", "package.aospkg");
629
+ rmSync(outAospkg, { force: true });
630
+ packAospkgFromTar(outTar, outAospkg);
631
+ process.stdout.write(
632
+ commands.length > 0 ? `assembled ${name}@${version} -> ${outAospkg}
633
+ commands (${commands.length}): ${commands.join(", ")}
634
+ ` : `assembled ${name}@${version} -> ${outAospkg} (PLANNED: empty placeholder, no bin/ yet \u2014 run stage with a commands dir to populate)
635
+ `
636
+ );
637
+ return { name, version, commands, outDir, outTar, outAospkg };
638
+ }
639
+
640
+ // src/header.ts
641
+ var WASM_MAGIC = Buffer.from([0, 97, 115, 109]);
642
+ var ELF_MAGIC = Buffer.from([127, 69, 76, 70]);
643
+ var MACHO_MAGICS = [
644
+ 4277009102,
645
+ 3472551422,
646
+ 4277009103,
647
+ 3489328638,
648
+ 3405691582,
649
+ 3199925962
650
+ ];
651
+ function detectExecutableKind(head) {
652
+ if (head.length >= 2 && head[0] === 35 && head[1] === 33) {
653
+ return "shebang";
654
+ }
655
+ if (head.length >= 4 && head.subarray(0, 4).equals(WASM_MAGIC)) {
656
+ return "wasm";
657
+ }
658
+ if (head.length >= 4 && head.subarray(0, 4).equals(ELF_MAGIC)) {
659
+ return "native-elf";
660
+ }
661
+ if (head.length >= 4) {
662
+ const be = head.readUInt32BE(0);
663
+ if (be === 3405691582 && head.length >= 8) {
664
+ const next = head.readUInt32BE(4);
665
+ if (next >= 45) return "unknown";
666
+ }
667
+ if (MACHO_MAGICS.includes(be)) return "native-macho";
668
+ }
669
+ if (head.length >= 2 && head[0] === 77 && head[1] === 90) {
670
+ return "native-pe";
671
+ }
672
+ return "unknown";
673
+ }
674
+ function isNativeKind(kind) {
675
+ return kind === "native-elf" || kind === "native-macho" || kind === "native-pe";
676
+ }
677
+ function parseShebangInterpreter(head) {
678
+ if (!(head.length >= 2 && head[0] === 35 && head[1] === 33)) return null;
679
+ const nl = head.indexOf(10);
680
+ const line = head.subarray(2, nl < 0 ? head.length : nl).toString("utf8");
681
+ const trimmed = line.replace(/^\s+/, "");
682
+ const interp = trimmed.split(/\s+/, 1)[0] ?? "";
683
+ return interp.length > 0 ? interp : null;
684
+ }
685
+
686
+ // src/pack.ts
687
+ import { execFileSync as execFileSync2 } from "child_process";
688
+ import {
689
+ chmodSync,
690
+ cpSync as cpSync2,
691
+ existsSync as existsSync3,
692
+ mkdirSync as mkdirSync2,
693
+ mkdtempSync,
694
+ lstatSync,
695
+ openSync,
696
+ readFileSync as readFileSync4,
697
+ readlinkSync,
698
+ readSync,
699
+ closeSync,
700
+ readdirSync as readdirSync2,
701
+ rmSync as rmSync2,
702
+ statSync as statSync2,
703
+ symlinkSync,
704
+ writeFileSync as writeFileSync3
705
+ } from "fs";
706
+ import { tmpdir } from "os";
707
+ import { dirname, isAbsolute, join as join3, relative, resolve as resolve2 } from "path";
708
+ var HEAD_BYTES = 256;
709
+ function npmBinary() {
710
+ const candidates = [
711
+ process.env.AGENTOS_TOOLCHAIN_NPM,
712
+ join3(dirname(process.execPath), "npm"),
713
+ "npm"
714
+ ].filter((value) => typeof value === "string" && value.length > 0);
715
+ return candidates.find((candidate) => candidate === "npm" || existsSync3(candidate)) ?? "npm";
716
+ }
717
+ function readHead(file) {
718
+ const fd = openSync(file, "r");
719
+ try {
720
+ const buf = Buffer.alloc(HEAD_BYTES);
721
+ const n = readSync(fd, buf, 0, HEAD_BYTES, 0);
722
+ return buf.subarray(0, n);
723
+ } finally {
724
+ closeSync(fd);
725
+ }
726
+ }
727
+ function npmInstallFlat(source, into) {
728
+ mkdirSync2(join3(into, "node_modules"), { recursive: true });
729
+ execFileSync2(
730
+ npmBinary(),
731
+ [
732
+ "install",
733
+ source,
734
+ "--omit=dev",
735
+ "--ignore-scripts",
736
+ "--no-audit",
737
+ "--no-fund",
738
+ "--no-package-lock",
739
+ "--install-strategy=hoisted",
740
+ "--prefix",
741
+ into
742
+ ],
743
+ { stdio: "pipe" }
744
+ );
745
+ }
746
+ function resolveInstallSpec(source, scratch) {
747
+ if (!(existsSync3(source) && statSync2(source).isDirectory())) return source;
748
+ const dest = join3(scratch, "tarball");
749
+ mkdirSync2(dest, { recursive: true });
750
+ const out = execFileSync2(
751
+ npmBinary(),
752
+ ["pack", resolve2(source), "--pack-destination", dest, "--ignore-scripts", "--silent"],
753
+ { encoding: "utf8" }
754
+ );
755
+ const file = out.trim().split("\n").pop()?.trim();
756
+ if (!file) throw new Error(`npm pack produced no tarball for ${source}`);
757
+ return join3(dest, file);
758
+ }
759
+ function installedPackageName(source) {
760
+ if (existsSync3(source) && statSync2(source).isDirectory()) {
761
+ const pkg = JSON.parse(readFileSync4(join3(source, "package.json"), "utf8"));
762
+ return pkg.name;
763
+ }
764
+ const at = source.lastIndexOf("@");
765
+ return at > 0 ? source.slice(0, at) : source;
766
+ }
767
+ function readAgentosPackageManifest(source) {
768
+ if (!(existsSync3(source) && statSync2(source).isDirectory())) return void 0;
769
+ const manifestPath = join3(source, "agentos-package.json");
770
+ if (!existsSync3(manifestPath)) return void 0;
771
+ return JSON.parse(readFileSync4(manifestPath, "utf8"));
772
+ }
773
+ function unscopedName2(name) {
774
+ return name.replace(/^@[^/]+\//, "");
775
+ }
776
+ function binEntries(pkgDir) {
777
+ const pkg = JSON.parse(readFileSync4(join3(pkgDir, "package.json"), "utf8"));
778
+ const bin = pkg.bin;
779
+ if (!bin) return {};
780
+ if (typeof bin === "string") {
781
+ return { [pkg.name.replace(/^@[^/]+\//, "")]: bin };
782
+ }
783
+ return bin;
784
+ }
785
+ function findNativeAddons(root) {
786
+ const hits = [];
787
+ const walk = (dir) => {
788
+ for (const entry of readdirSync2(dir, { withFileTypes: true })) {
789
+ const p = join3(dir, entry.name);
790
+ if (entry.isDirectory()) walk(p);
791
+ else if (entry.isFile() && entry.name.endsWith(".node")) hits.push(p);
792
+ }
793
+ };
794
+ if (existsSync3(root)) walk(root);
795
+ return hits;
796
+ }
797
+ function verifyPackageDir(packageDir) {
798
+ const manifestPath = join3(packageDir, "agentos-package.json");
799
+ if (!existsSync3(manifestPath)) {
800
+ throw new Error(`missing required agentos-package.json in ${packageDir}`);
801
+ }
802
+ let manifest;
803
+ try {
804
+ manifest = JSON.parse(readFileSync4(manifestPath, "utf8"));
805
+ } catch (error) {
806
+ throw new Error(
807
+ `agentos-package.json in ${packageDir} is not valid JSON: ${String(error)}`
808
+ );
809
+ }
810
+ if (typeof manifest.name !== "string" || manifest.name.length === 0) {
811
+ throw new Error(
812
+ `agentos-package.json in ${packageDir} is missing a valid "name"`
813
+ );
814
+ }
815
+ if (typeof manifest.version !== "string" || manifest.version.length === 0) {
816
+ throw new Error(
817
+ `agentos-package.json in ${packageDir} is missing a valid "version"`
818
+ );
819
+ }
820
+ const binDir = join3(packageDir, "bin");
821
+ if (!existsSync3(binDir)) {
822
+ throw new Error(`package has no bin/ directory: ${packageDir}`);
823
+ }
824
+ for (const entry of readdirSync2(binDir)) {
825
+ const target = resolve2(binDir, entry);
826
+ const kind = detectExecutableKind(readHead(target));
827
+ if (isNativeKind(kind)) {
828
+ throw new Error(
829
+ `bin/${entry} is a native ${kind} binary, which cannot run in agentOS`
830
+ );
831
+ }
832
+ if (kind === "unknown") {
833
+ throw new Error(
834
+ `bin/${entry} has no recognized header \u2014 JS/script commands need a '#!' shebang`
835
+ );
836
+ }
837
+ }
838
+ const addons = findNativeAddons(join3(packageDir, "node_modules"));
839
+ if (addons.length > 0) {
840
+ throw new Error(
841
+ `package contains native .node addon(s) that won't load in V8: ${addons.map((a) => relative(packageDir, a)).join(", ")}; re-run with --prune-native to drop them if they are unreachable on the V8 code path`
842
+ );
843
+ }
844
+ }
845
+ function isInside(root, target) {
846
+ const rel = relative(root, target);
847
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
848
+ }
849
+ function dereferenceEscapingSymlinks(root) {
850
+ const walk = (dir) => {
851
+ for (const entry of readdirSync2(dir, { withFileTypes: true })) {
852
+ const path = join3(dir, entry.name);
853
+ const stat = lstatSync(path);
854
+ if (stat.isSymbolicLink()) {
855
+ const target = resolve2(dirname(path), readlinkSync(path));
856
+ if (!isInside(root, target)) {
857
+ rmSync2(path, { recursive: true, force: true });
858
+ cpSync2(target, path, {
859
+ recursive: true,
860
+ dereference: true,
861
+ verbatimSymlinks: false
862
+ });
863
+ }
864
+ continue;
865
+ }
866
+ if (stat.isDirectory()) walk(path);
867
+ }
868
+ };
869
+ walk(root);
870
+ }
871
+ function createPackageTar(packageDir, packageTar) {
872
+ rmSync2(packageTar, { recursive: true, force: true });
873
+ mkdirSync2(dirname(packageTar), { recursive: true });
874
+ execFileSync2("tar", ["-cf", packageTar, "-C", packageDir, "."], {
875
+ stdio: "pipe"
876
+ });
877
+ }
878
+ function resolveBinTarget(closureModules, name, entryRel) {
879
+ const nested = join3(closureModules, name, entryRel);
880
+ if (existsSync3(nested)) return nested;
881
+ const hoistedMatch = entryRel.match(/^\.?\/?node_modules\/(.+)$/);
882
+ if (hoistedMatch) {
883
+ const hoisted = join3(closureModules, hoistedMatch[1]);
884
+ if (existsSync3(hoisted)) return hoisted;
885
+ }
886
+ throw new Error(
887
+ `pack: cannot resolve bin target "${entryRel}" for ${name} \u2014 not found nested (${nested}) or hoisted. The declaring package's bin path does not match the installed (hoisted) layout.`
888
+ );
889
+ }
890
+ function pack(options) {
891
+ const { source, out, agent, pruneNative } = options;
892
+ const tmp = mkdtempSync(join3(tmpdir(), "agentos-pack-"));
893
+ try {
894
+ npmInstallFlat(resolveInstallSpec(source, tmp), tmp);
895
+ const name = installedPackageName(source);
896
+ const installedDir = join3(tmp, "node_modules", name);
897
+ const sourceManifest = readAgentosPackageManifest(installedDir);
898
+ const pkg = JSON.parse(readFileSync4(join3(installedDir, "package.json"), "utf8"));
899
+ const version = pkg.version;
900
+ const bins = binEntries(installedDir);
901
+ const commands = Object.keys(bins);
902
+ if (commands.length === 0) {
903
+ throw new Error(`package "${name}" declares no bin commands`);
904
+ }
905
+ if (agent && !commands.includes(agent)) {
906
+ throw new Error(
907
+ `--agent "${agent}" is not one of the package's commands: ${commands.join(", ")}`
908
+ );
909
+ }
910
+ const explicitTarOut = out.endsWith(".tar");
911
+ const packageDir = explicitTarOut ? join3(tmp, "package") : out;
912
+ rmSync2(packageDir, { recursive: true, force: true });
913
+ mkdirSync2(packageDir, { recursive: true });
914
+ const binDir = join3(packageDir, "bin");
915
+ mkdirSync2(binDir, { recursive: true });
916
+ cpSync2(join3(tmp, "node_modules"), join3(packageDir, "node_modules"), {
917
+ recursive: true
918
+ });
919
+ const closureModules = join3(packageDir, "node_modules");
920
+ const binMap = {};
921
+ for (const [cmd, entryRel] of Object.entries(bins)) {
922
+ const targetAbs = resolveBinTarget(closureModules, name, entryRel);
923
+ binMap[cmd] = relative(packageDir, targetAbs).split(/[\\/]/).join("/");
924
+ chmodSync(targetAbs, 493);
925
+ symlinkSync(relative(binDir, targetAbs), join3(binDir, cmd));
926
+ }
927
+ if (pruneNative) {
928
+ const addons = findNativeAddons(join3(packageDir, "node_modules"));
929
+ for (const addon of addons) {
930
+ rmSync2(addon, { force: true });
931
+ }
932
+ if (addons.length > 0) {
933
+ console.warn(
934
+ `[agentos-toolchain] pruned ${addons.length} native .node addon(s) from ${name} (--prune-native); they must be unreachable on the V8 code path`
935
+ );
936
+ }
937
+ }
938
+ writeFileSync3(
939
+ join3(packageDir, "package.json"),
940
+ `${JSON.stringify({ name, version, bin: binMap }, null, 2)}
941
+ `
942
+ );
943
+ const manifest = {
944
+ name: typeof sourceManifest?.name === "string" && sourceManifest.name.length > 0 ? sourceManifest.name : unscopedName2(name),
945
+ ...sourceManifest?.agent !== void 0 ? { agent: sourceManifest.agent } : agent ? { agent: { acpEntrypoint: agent } } : {},
946
+ version,
947
+ ...sourceManifest?.provides !== void 0 ? { provides: sourceManifest.provides } : {}
948
+ };
949
+ writeFileSync3(
950
+ join3(packageDir, "agentos-package.json"),
951
+ `${JSON.stringify(manifest, null, 2)}
952
+ `
953
+ );
954
+ verifyPackageDir(packageDir);
955
+ dereferenceEscapingSymlinks(packageDir);
956
+ const packageTar = out.endsWith(".tar") ? out : `${out}.tar`;
957
+ createPackageTar(packageDir, packageTar);
958
+ const packageAospkg = packageTar.replace(/\.tar$/, ".aospkg");
959
+ packAospkgFromTar(packageTar, packageAospkg);
960
+ return { name, version, packageTar, packageAospkg, commands };
961
+ } finally {
962
+ rmSync2(tmp, { recursive: true, force: true });
963
+ }
964
+ }
965
+
966
+ // src/publish.ts
967
+ import { spawnSync } from "child_process";
968
+ import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
969
+ import { dirname as dirname2, join as join4, resolve as resolve3 } from "path";
970
+ function resolveTag(options) {
971
+ if (options.latest) {
972
+ if (options.tag !== void 0 && options.tag !== "latest") {
973
+ throw new Error(
974
+ `--latest conflicts with --tag ${options.tag}: pass one or the other`
975
+ );
976
+ }
977
+ return "latest";
978
+ }
979
+ if (options.tag === "latest") {
980
+ throw new Error(
981
+ "refusing implicit `--tag latest` \u2014 pass --latest to move the latest pointer"
982
+ );
983
+ }
984
+ return options.tag ?? "dev";
985
+ }
986
+ function findUp(startDir, fileName) {
987
+ let dir = startDir;
988
+ for (; ; ) {
989
+ if (existsSync4(join4(dir, fileName))) return join4(dir, fileName);
990
+ const parent = dirname2(dir);
991
+ if (parent === dir) return void 0;
992
+ dir = parent;
993
+ }
994
+ }
995
+ function publish(options) {
996
+ const packageDir = resolve3(options.packageDir);
997
+ const tag = resolveTag(options);
998
+ const pkgPath = join4(packageDir, "package.json");
999
+ if (!existsSync4(pkgPath)) {
1000
+ throw new Error(`no package.json in ${packageDir}`);
1001
+ }
1002
+ const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
1003
+ if (typeof pkg.name !== "string" || pkg.name.length === 0) {
1004
+ throw new Error(`package.json in ${packageDir} is missing a valid "name"`);
1005
+ }
1006
+ if (options.setVersion !== void 0) {
1007
+ const raw = JSON.parse(readFileSync5(pkgPath, "utf8"));
1008
+ raw.version = options.setVersion;
1009
+ writeFileSync4(pkgPath, `${JSON.stringify(raw, null, " ")}
1010
+ `);
1011
+ pkg.version = options.setVersion;
1012
+ }
1013
+ if (typeof pkg.version !== "string" || pkg.version.length === 0) {
1014
+ throw new Error(
1015
+ `package.json in ${packageDir} is missing a valid "version"`
1016
+ );
1017
+ }
1018
+ if (!existsSync4(join4(packageDir, "dist", "index.js"))) {
1019
+ throw new Error(
1020
+ `${pkg.name} is not built (no dist/index.js in ${packageDir}) \u2014 build it first`
1021
+ );
1022
+ }
1023
+ const inPnpmWorkspace = findUp(packageDir, "pnpm-workspace.yaml") !== void 0;
1024
+ const pm = inPnpmWorkspace ? "pnpm" : "npm";
1025
+ const args = ["publish", "--access", "public", "--tag", tag];
1026
+ if (pm === "pnpm") args.push("--no-git-checks");
1027
+ if (options.dryRun) args.push("--dry-run");
1028
+ process.stdout.write(
1029
+ `publishing ${pkg.name}@${pkg.version} (dist-tag: ${tag}${options.dryRun ? ", dry-run" : ""}) via ${pm}
1030
+ `
1031
+ );
1032
+ const result = spawnSync(pm, args, { cwd: packageDir, stdio: "inherit" });
1033
+ if (result.error) throw result.error;
1034
+ if (result.status !== 0) {
1035
+ throw new Error(`${pm} publish failed for ${pkg.name} (exit ${result.status})`);
1036
+ }
1037
+ return { name: pkg.name, version: pkg.version, tag };
1038
+ }
1039
+
1040
+ // src/stage.ts
1041
+ import {
1042
+ copyFileSync,
1043
+ existsSync as existsSync5,
1044
+ mkdirSync as mkdirSync3,
1045
+ rmSync as rmSync3,
1046
+ statSync as statSync3
1047
+ } from "fs";
1048
+ import { join as join5, resolve as resolve4 } from "path";
1049
+ function stage(options) {
1050
+ const packageDir = resolve4(options.packageDir);
1051
+ const commandsDir = resolve4(options.commandsDir);
1052
+ const ifMissing = options.ifMissing ?? "error";
1053
+ const manifest = readManifest(packageDir);
1054
+ const commands = manifest?.commands ?? [];
1055
+ const aliases = manifest?.aliases ?? {};
1056
+ const stubs = manifest?.stubs ?? [];
1057
+ if (commands.length === 0 && stubs.length === 0 && Object.keys(aliases).length === 0) {
1058
+ process.stdout.write(
1059
+ `stage: no commands declared in ${join5(packageDir, "agentos-package.json")} \u2014 nothing to stage
1060
+ `
1061
+ );
1062
+ return { staged: [], missing: [] };
1063
+ }
1064
+ if (!existsSync5(commandsDir)) {
1065
+ if (ifMissing === "skip") {
1066
+ process.stdout.write(
1067
+ `stage: commands dir not found (${commandsDir}) \u2014 leaving bin/ unstaged (placeholder package)
1068
+ `
1069
+ );
1070
+ return { staged: [], missing: [...commands, ...stubs, ...Object.keys(aliases)] };
1071
+ }
1072
+ throw new Error(`stage: commands dir not found: ${commandsDir}`);
1073
+ }
1074
+ const binDir = join5(packageDir, "bin");
1075
+ rmSync3(binDir, { recursive: true, force: true });
1076
+ mkdirSync3(binDir, { recursive: true });
1077
+ const staged = [];
1078
+ const missing = [];
1079
+ for (const command of commands) {
1080
+ const source = join5(commandsDir, command);
1081
+ if (!existsSync5(source) || !statSync3(source).isFile()) {
1082
+ missing.push(command);
1083
+ continue;
1084
+ }
1085
+ copyFileSync(source, join5(binDir, command));
1086
+ staged.push(command);
1087
+ }
1088
+ const stubsSource = join5(commandsDir, "_stubs");
1089
+ const hasStubsBinary = existsSync5(stubsSource);
1090
+ for (const stub of stubs) {
1091
+ if (!hasStubsBinary) {
1092
+ missing.push(stub);
1093
+ continue;
1094
+ }
1095
+ copyFileSync(stubsSource, join5(binDir, stub));
1096
+ staged.push(stub);
1097
+ }
1098
+ for (const [alias, target] of Object.entries(aliases)) {
1099
+ const source = join5(binDir, target);
1100
+ if (!existsSync5(source)) {
1101
+ missing.push(alias);
1102
+ continue;
1103
+ }
1104
+ copyFileSync(source, join5(binDir, alias));
1105
+ staged.push(alias);
1106
+ }
1107
+ if (missing.length > 0) {
1108
+ const detail = `missing from ${commandsDir}: ${missing.join(", ")}`;
1109
+ if (ifMissing === "error") {
1110
+ throw new Error(`stage: ${detail}`);
1111
+ }
1112
+ process.stdout.write(`stage: WARN ${detail}
1113
+ `);
1114
+ }
1115
+ process.stdout.write(
1116
+ `staged ${staged.length} command(s) into ${binDir}
1117
+ `
1118
+ );
1119
+ return { staged, missing };
1120
+ }
1121
+
1122
+ export {
1123
+ packAospkgFromTar,
1124
+ packAospkgFromTarBytes,
1125
+ readManifest,
1126
+ build,
1127
+ detectExecutableKind,
1128
+ isNativeKind,
1129
+ parseShebangInterpreter,
1130
+ verifyPackageDir,
1131
+ pack,
1132
+ resolveTag,
1133
+ publish,
1134
+ stage
1135
+ };