@tetsuo-ai/agenc 0.9.2 → 0.11.2
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/generated/agenc-runtime-manifest-v2.json +118 -109
- package/lib/generated-wrapper.d.mts +2 -0
- package/lib/generated-wrapper.mjs +53 -9
- package/lib/runtime-archive.d.mts +58 -0
- package/lib/runtime-archive.mjs +250 -0
- package/lib/runtime-manager.mjs +121 -32
- package/lib/runtime-release-contract.d.mts +14 -1
- package/lib/runtime-release-contract.mjs +56 -1
- package/package.json +3 -2
- package/src/launcher.mjs +104 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tetsuo-ai/agenc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Public AgenC CLI launcher package",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"lib/activation-lock-identity.mjs",
|
|
24
24
|
"lib/generated-wrapper.d.mts",
|
|
25
25
|
"lib/generated-wrapper.mjs",
|
|
26
|
+
"lib/runtime-archive.d.mts",
|
|
26
27
|
"lib/runtime-archive.mjs",
|
|
27
28
|
"lib/runtime-compatibility.mjs",
|
|
28
29
|
"lib/runtime-manager.mjs",
|
|
@@ -47,6 +48,6 @@
|
|
|
47
48
|
"@tetsuo-ai/runtime": "file:../../runtime"
|
|
48
49
|
},
|
|
49
50
|
"engines": {
|
|
50
|
-
"node": ">=
|
|
51
|
+
"node": ">=26.5.0 <27.0.0"
|
|
51
52
|
}
|
|
52
53
|
}
|
package/src/launcher.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
2
3
|
import { readFile } from "node:fs/promises";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import { homedir } from "node:os";
|
|
5
|
-
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
|
|
8
9
|
const DEFAULT_READY_TIMEOUT_MS = 2000;
|
|
@@ -74,11 +75,17 @@ export function isDaemonCommand(argv) {
|
|
|
74
75
|
export function resolveRuntimeBin(requireFn = requireFromLauncher) {
|
|
75
76
|
try {
|
|
76
77
|
const runtimeEntry = requireFn.resolve("@tetsuo-ai/runtime");
|
|
78
|
+
const runtimeRoot = realpathSync(resolve(dirname(runtimeEntry), ".."));
|
|
79
|
+
const repositoryRuntimeRoot = realpathSync(
|
|
80
|
+
resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "runtime"),
|
|
81
|
+
);
|
|
82
|
+
if (runtimeRoot !== repositoryRuntimeRoot) return null;
|
|
77
83
|
return resolve(dirname(runtimeEntry), "../bin/agenc");
|
|
78
84
|
} catch (error) {
|
|
79
85
|
if (
|
|
80
86
|
error?.code === "MODULE_NOT_FOUND" ||
|
|
81
|
-
error?.code === "ERR_MODULE_NOT_FOUND"
|
|
87
|
+
error?.code === "ERR_MODULE_NOT_FOUND" ||
|
|
88
|
+
error?.code === "ENOENT"
|
|
82
89
|
) {
|
|
83
90
|
return null;
|
|
84
91
|
}
|
|
@@ -86,8 +93,41 @@ export function resolveRuntimeBin(requireFn = requireFromLauncher) {
|
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
function hostRuntimeLaunch(runtimeBin) {
|
|
97
|
+
return { runtimeBin, nodeBin: process.execPath };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function requireRuntimeLaunch(value) {
|
|
101
|
+
if (
|
|
102
|
+
value === null ||
|
|
103
|
+
typeof value !== "object" ||
|
|
104
|
+
typeof value.runtimeBin !== "string" ||
|
|
105
|
+
typeof value.nodeBin !== "string" ||
|
|
106
|
+
(
|
|
107
|
+
value.nodeLibraryPath !== undefined &&
|
|
108
|
+
typeof value.nodeLibraryPath !== "string"
|
|
109
|
+
)
|
|
110
|
+
) {
|
|
111
|
+
throw new Error("agenc: runtime manager returned an invalid launch contract");
|
|
112
|
+
}
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Resolve every path needed to execute the runtime. Development file: links
|
|
117
|
+
// intentionally use the current Node process; published artifacts always
|
|
118
|
+
// return their embedded Node (and the Linux compatibility-library directory).
|
|
119
|
+
export async function resolveRuntimeLaunchAsync({
|
|
120
|
+
requireFn = requireFromLauncher,
|
|
121
|
+
ensureFn,
|
|
122
|
+
} = {}) {
|
|
123
|
+
const dev = resolveRuntimeBin(requireFn);
|
|
124
|
+
if (dev !== null) return hostRuntimeLaunch(dev);
|
|
125
|
+
const ensureRuntimeLaunch =
|
|
126
|
+
ensureFn ?? (await import("../lib/runtime-manager.mjs")).ensureRuntimeLaunch;
|
|
127
|
+
return requireRuntimeLaunch(await ensureRuntimeLaunch());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Retained for callers that only need the script path.
|
|
91
131
|
export async function resolveRuntimeBinAsync({
|
|
92
132
|
requireFn = requireFromLauncher,
|
|
93
133
|
ensureFn,
|
|
@@ -96,7 +136,10 @@ export async function resolveRuntimeBinAsync({
|
|
|
96
136
|
if (dev !== null) return dev;
|
|
97
137
|
const ensureRuntime =
|
|
98
138
|
ensureFn ?? (await import("../lib/runtime-manager.mjs")).ensureRuntime;
|
|
99
|
-
|
|
139
|
+
const ensured = await ensureRuntime();
|
|
140
|
+
return typeof ensured === "string"
|
|
141
|
+
? ensured
|
|
142
|
+
: requireRuntimeLaunch(ensured).runtimeBin;
|
|
100
143
|
}
|
|
101
144
|
|
|
102
145
|
export async function spawnNodeScript(
|
|
@@ -107,12 +150,27 @@ export async function spawnNodeScript(
|
|
|
107
150
|
cwd = process.cwd(),
|
|
108
151
|
stdio = "inherit",
|
|
109
152
|
spawnFn = spawn,
|
|
153
|
+
nodeBin = process.execPath,
|
|
154
|
+
nodeLibraryPath,
|
|
110
155
|
} = {},
|
|
111
156
|
) {
|
|
157
|
+
const childEnv = { ...env };
|
|
158
|
+
const pathKey =
|
|
159
|
+
Object.keys(childEnv).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
160
|
+
const nodeDir = dirname(nodeBin);
|
|
161
|
+
childEnv[pathKey] = childEnv[pathKey]
|
|
162
|
+
? `${nodeDir}${delimiter}${childEnv[pathKey]}`
|
|
163
|
+
: nodeDir;
|
|
164
|
+
if (nodeLibraryPath !== undefined) {
|
|
165
|
+
// The embedded Linux Node requires the artifact's pinned libatomic. Do not
|
|
166
|
+
// search an operator-controlled ambient library path before that exact
|
|
167
|
+
// directory.
|
|
168
|
+
childEnv.LD_LIBRARY_PATH = nodeLibraryPath;
|
|
169
|
+
}
|
|
112
170
|
return new Promise((resolveExit, reject) => {
|
|
113
|
-
const child = spawnFn(
|
|
171
|
+
const child = spawnFn(nodeBin, [scriptPath, ...args], {
|
|
114
172
|
cwd,
|
|
115
|
-
env,
|
|
173
|
+
env: childEnv,
|
|
116
174
|
stdio,
|
|
117
175
|
});
|
|
118
176
|
child.once("error", reject);
|
|
@@ -174,6 +232,8 @@ export async function ensureDaemonForLaunch({
|
|
|
174
232
|
env = process.env,
|
|
175
233
|
cwd = process.cwd(),
|
|
176
234
|
runtimeBin = resolveRuntimeBin(),
|
|
235
|
+
runtimeNodeBin = process.execPath,
|
|
236
|
+
runtimeNodeLibraryPath,
|
|
177
237
|
userHome = homedir(),
|
|
178
238
|
readText = readFile,
|
|
179
239
|
signalPid = process.kill,
|
|
@@ -197,7 +257,12 @@ export async function ensureDaemonForLaunch({
|
|
|
197
257
|
return { status: "already-running" };
|
|
198
258
|
}
|
|
199
259
|
|
|
200
|
-
await spawnDaemonFn(runtimeBin, {
|
|
260
|
+
await spawnDaemonFn(runtimeBin, {
|
|
261
|
+
env,
|
|
262
|
+
cwd,
|
|
263
|
+
nodeBin: runtimeNodeBin,
|
|
264
|
+
nodeLibraryPath: runtimeNodeLibraryPath,
|
|
265
|
+
});
|
|
201
266
|
const ready = await waitForReadyFn({ env, userHome, readText, signalPid });
|
|
202
267
|
if (!ready) {
|
|
203
268
|
throw new Error("AgenC daemon did not become ready before timeout");
|
|
@@ -210,16 +275,29 @@ export async function main(
|
|
|
210
275
|
{
|
|
211
276
|
env = process.env,
|
|
212
277
|
cwd = process.cwd(),
|
|
278
|
+
runtimeLaunch,
|
|
213
279
|
runtimeBin,
|
|
280
|
+
runtimeNodeBin = process.execPath,
|
|
281
|
+
runtimeNodeLibraryPath,
|
|
214
282
|
userHome = homedir(),
|
|
215
283
|
} = {},
|
|
216
284
|
) {
|
|
217
285
|
// Resolve (and, in a published install, download + verify) the runtime before
|
|
218
286
|
// anything tries to spawn it. Sync default is avoided: it returns null when
|
|
219
287
|
// runtime isn't an npm dep, which is the normal published case.
|
|
220
|
-
let
|
|
288
|
+
let resolvedLaunch = runtimeLaunch ??
|
|
289
|
+
(runtimeBin === undefined
|
|
290
|
+
? undefined
|
|
291
|
+
: {
|
|
292
|
+
runtimeBin,
|
|
293
|
+
nodeBin: runtimeNodeBin,
|
|
294
|
+
...(runtimeNodeLibraryPath === undefined
|
|
295
|
+
? {}
|
|
296
|
+
: { nodeLibraryPath: runtimeNodeLibraryPath }),
|
|
297
|
+
});
|
|
221
298
|
try {
|
|
222
|
-
|
|
299
|
+
resolvedLaunch ??= await resolveRuntimeLaunchAsync();
|
|
300
|
+
resolvedLaunch = requireRuntimeLaunch(resolvedLaunch);
|
|
223
301
|
} catch (error) {
|
|
224
302
|
process.stderr.write(
|
|
225
303
|
`agenc: could not obtain runtime: ${
|
|
@@ -229,7 +307,15 @@ export async function main(
|
|
|
229
307
|
return 1;
|
|
230
308
|
}
|
|
231
309
|
try {
|
|
232
|
-
await ensureDaemonForLaunch({
|
|
310
|
+
await ensureDaemonForLaunch({
|
|
311
|
+
argv,
|
|
312
|
+
env,
|
|
313
|
+
cwd,
|
|
314
|
+
runtimeBin: resolvedLaunch.runtimeBin,
|
|
315
|
+
runtimeNodeBin: resolvedLaunch.nodeBin,
|
|
316
|
+
runtimeNodeLibraryPath: resolvedLaunch.nodeLibraryPath,
|
|
317
|
+
userHome,
|
|
318
|
+
});
|
|
233
319
|
} catch (error) {
|
|
234
320
|
// The launcher is transport, not policy: a daemon that cannot start must
|
|
235
321
|
// not block daemon-independent commands. `agenc update` is the canonical
|
|
@@ -245,7 +331,13 @@ export async function main(
|
|
|
245
331
|
"agenc: continuing without the daemon; commands that require it will report the failure\n",
|
|
246
332
|
);
|
|
247
333
|
}
|
|
248
|
-
return spawnNodeScript(
|
|
334
|
+
return spawnNodeScript(resolvedLaunch.runtimeBin, argv, {
|
|
335
|
+
env,
|
|
336
|
+
cwd,
|
|
337
|
+
stdio: "inherit",
|
|
338
|
+
nodeBin: resolvedLaunch.nodeBin,
|
|
339
|
+
nodeLibraryPath: resolvedLaunch.nodeLibraryPath,
|
|
340
|
+
});
|
|
249
341
|
}
|
|
250
342
|
|
|
251
343
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|