@abaigram/abai-stub 0.0.0-stage → 0.2.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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -2
  3. package/dist/audit.d.ts +102 -0
  4. package/dist/audit.d.ts.map +1 -0
  5. package/dist/audit.js +196 -0
  6. package/dist/audit.js.map +1 -0
  7. package/dist/cells/fit.d.ts +6 -0
  8. package/dist/cells/fit.d.ts.map +1 -0
  9. package/dist/cells/fit.js +44 -0
  10. package/dist/cells/fit.js.map +1 -0
  11. package/dist/content.d.ts +17 -0
  12. package/dist/content.d.ts.map +1 -0
  13. package/dist/content.js +71 -0
  14. package/dist/content.js.map +1 -0
  15. package/dist/endpoint.d.ts +90 -0
  16. package/dist/endpoint.d.ts.map +1 -0
  17. package/dist/endpoint.js +804 -0
  18. package/dist/endpoint.js.map +1 -0
  19. package/dist/entry.d.ts +36 -0
  20. package/dist/entry.d.ts.map +1 -0
  21. package/dist/entry.js +409 -0
  22. package/dist/entry.js.map +1 -0
  23. package/dist/env.d.ts +38 -0
  24. package/dist/env.d.ts.map +1 -0
  25. package/dist/env.js +69 -0
  26. package/dist/env.js.map +1 -0
  27. package/dist/harness-binding.d.ts +235 -0
  28. package/dist/harness-binding.d.ts.map +1 -0
  29. package/dist/harness-binding.js +618 -0
  30. package/dist/harness-binding.js.map +1 -0
  31. package/dist/index.d.ts +17 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +17 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/manifest/index.d.ts +3 -0
  36. package/dist/manifest/index.d.ts.map +1 -0
  37. package/dist/manifest/index.js +3 -0
  38. package/dist/manifest/index.js.map +1 -0
  39. package/dist/manifest/manifest.d.ts +177 -0
  40. package/dist/manifest/manifest.d.ts.map +1 -0
  41. package/dist/manifest/manifest.js +452 -0
  42. package/dist/manifest/manifest.js.map +1 -0
  43. package/dist/manifest/render.d.ts +6 -0
  44. package/dist/manifest/render.d.ts.map +1 -0
  45. package/dist/manifest/render.js +39 -0
  46. package/dist/manifest/render.js.map +1 -0
  47. package/dist/null-harness.d.ts +32 -0
  48. package/dist/null-harness.d.ts.map +1 -0
  49. package/dist/null-harness.js +162 -0
  50. package/dist/null-harness.js.map +1 -0
  51. package/dist/program.d.ts +255 -0
  52. package/dist/program.d.ts.map +1 -0
  53. package/dist/program.js +898 -0
  54. package/dist/program.js.map +1 -0
  55. package/dist/region.d.ts +72 -0
  56. package/dist/region.d.ts.map +1 -0
  57. package/dist/region.js +93 -0
  58. package/dist/region.js.map +1 -0
  59. package/dist/registry.d.ts +60 -0
  60. package/dist/registry.d.ts.map +1 -0
  61. package/dist/registry.js +105 -0
  62. package/dist/registry.js.map +1 -0
  63. package/dist/wire/descriptor.d.ts +38 -0
  64. package/dist/wire/descriptor.d.ts.map +1 -0
  65. package/dist/wire/descriptor.js +144 -0
  66. package/dist/wire/descriptor.js.map +1 -0
  67. package/dist/wire/framing.d.ts +11 -0
  68. package/dist/wire/framing.d.ts.map +1 -0
  69. package/dist/wire/framing.js +42 -0
  70. package/dist/wire/framing.js.map +1 -0
  71. package/dist/wire/index.d.ts +4 -0
  72. package/dist/wire/index.d.ts.map +1 -0
  73. package/dist/wire/index.js +4 -0
  74. package/dist/wire/index.js.map +1 -0
  75. package/dist/wire/protocol.d.ts +257 -0
  76. package/dist/wire/protocol.d.ts.map +1 -0
  77. package/dist/wire/protocol.js +17 -0
  78. package/dist/wire/protocol.js.map +1 -0
  79. package/package.json +36 -5
package/dist/entry.js ADDED
@@ -0,0 +1,409 @@
1
+ // The standard agent entry (abaigrammar section 4.4), the part the stub
2
+ // provides itself: `<prog> abai manifest` prints the effective manifest and
3
+ // `<prog> abai doctor` runs the offline conformance checks. The verbs that
4
+ // need a harness (session, install, config, mcp, run) are delegated once a
5
+ // harness binding exists; until then the usage says so. Never throws;
6
+ // resolves to the exit code.
7
+ import { spawn } from "node:child_process";
8
+ import { accessSync, constants, existsSync, readFileSync, statSync } from "node:fs";
9
+ import { dirname, join, resolve } from "node:path";
10
+ import { findRoot, MANIFEST_FILE } from "./content.js";
11
+ import { ENV_HARNESS, ENV_MODE, expandHome } from "./env.js";
12
+ import { validateManifest } from "./manifest/manifest.js";
13
+ import { parseManifestYaml, renderManifestYaml } from "./manifest/render.js";
14
+ import { harnessBinary, importHarnessModule } from "./program.js";
15
+ export const STUB_VERSION = "0.2.0";
16
+ export const processIo = {
17
+ out: (text) => {
18
+ process.stdout.write(text);
19
+ },
20
+ err: (text) => {
21
+ process.stderr.write(`${text}\n`);
22
+ },
23
+ env: process.env,
24
+ get cwd() {
25
+ return process.cwd();
26
+ },
27
+ };
28
+ function errorMessage(error) {
29
+ return error instanceof Error ? error.message : String(error);
30
+ }
31
+ function usageLines(entry) {
32
+ return [
33
+ `usage: ${entry} open a session`,
34
+ ` ${entry} install run the install touchpoint`,
35
+ ` ${entry} manifest [--json] print the effective manifest`,
36
+ ` ${entry} doctor [--root <dir>] [--offline] [--json]`,
37
+ ` ${entry} config [set ...] the machine-level model configuration`,
38
+ ` ${entry} mcp serve the agent's tools to an MCP client over stdio`,
39
+ ` ${entry} run [--auto] -- ARGS the harness starts this program as its supervised child`,
40
+ "",
41
+ "doctor offline conformance checks: the effective manifest, the checked-in",
42
+ ` ${MANIFEST_FILE}, the identity content, the modes, the audit directory`,
43
+ "",
44
+ "session and install attach a harness and return when none can attach; mcp needs no model,",
45
+ "since the client's own agent is this program's; run is always sidecar launch, with the whole",
46
+ "lifecycle channel and the program's output observed from outside.",
47
+ ];
48
+ }
49
+ /** `--flag`, `--flag value` and `--flag=value`; anything else is a usage error. */
50
+ function parseFlags(args, allowed) {
51
+ const flags = { json: false, root: undefined, offline: false };
52
+ for (let i = 0; i < args.length; i++) {
53
+ const arg = args[i];
54
+ const eq = arg.indexOf("=");
55
+ const name = eq === -1 ? arg : arg.slice(0, eq);
56
+ if (!allowed.includes(name))
57
+ return `unknown option ${arg}`;
58
+ const takeValue = () => {
59
+ if (eq !== -1)
60
+ return arg.slice(eq + 1);
61
+ i += 1;
62
+ return args[i];
63
+ };
64
+ switch (name) {
65
+ case "--json":
66
+ flags.json = true;
67
+ break;
68
+ case "--offline":
69
+ flags.offline = true;
70
+ break;
71
+ case "--root": {
72
+ const value = takeValue();
73
+ if (value === undefined || value === "")
74
+ return "--root needs a directory";
75
+ flags.root = value;
76
+ break;
77
+ }
78
+ default:
79
+ return `unknown option ${arg}`;
80
+ }
81
+ }
82
+ return flags;
83
+ }
84
+ /** The first line at which two texts differ (1-based), or undefined when equal. */
85
+ export function firstDifferingLine(a, b) {
86
+ if (a === b)
87
+ return undefined;
88
+ const linesA = a.split("\n");
89
+ const linesB = b.split("\n");
90
+ const n = Math.max(linesA.length, linesB.length);
91
+ for (let i = 0; i < n; i++) {
92
+ if (linesA[i] !== linesB[i])
93
+ return i + 1;
94
+ }
95
+ return n;
96
+ }
97
+ /** The first existing ancestor of a path (the path itself included). */
98
+ function existingAncestor(path) {
99
+ let current = path;
100
+ while (!existsSync(current)) {
101
+ const parent = dirname(current);
102
+ if (parent === current)
103
+ break;
104
+ current = parent;
105
+ }
106
+ return current;
107
+ }
108
+ /** The offline half of `doctor` (section 4.4), plus the online half when the harness package is installed. Never throws. */
109
+ export async function runDoctor(app, options = {}) {
110
+ const io = options.io ?? processIo;
111
+ const checks = [];
112
+ const add = (name, status, detail) => {
113
+ checks.push({ name, status, detail });
114
+ };
115
+ const { manifest } = app;
116
+ add("entry", "ok", `${manifest.entry} reached (abai stub ${STUB_VERSION})`);
117
+ const violations = validateManifest(manifest);
118
+ let rendered;
119
+ if (violations.length === 0) {
120
+ rendered = renderManifestYaml(manifest);
121
+ add("manifest", "ok", `the effective manifest validates (${manifest.cells.length} cells, ${manifest.events.length} events, ${manifest.capabilities.length} capabilities, ${manifest.decisions.length} decisions, ${manifest.turns.length} turns)`);
122
+ }
123
+ else {
124
+ add("manifest", "fail", `the effective manifest does not validate: ${violations.join("; ")}`);
125
+ }
126
+ const root = options.root !== undefined
127
+ ? resolve(io.cwd, options.root)
128
+ : (findRoot(manifest.name, io.cwd) ??
129
+ (existsSync(join(app.content.root, MANIFEST_FILE)) ? app.content.root : undefined));
130
+ if (root === undefined) {
131
+ add("root", "skip", `no checkout found (pass --root <dir> to check a checked-in ${MANIFEST_FILE})`);
132
+ add(MANIFEST_FILE, "skip", "no checkout");
133
+ add("identity", "skip", "no checkout");
134
+ }
135
+ else {
136
+ add("root", "ok", root);
137
+ const path = join(root, MANIFEST_FILE);
138
+ if (!existsSync(path)) {
139
+ add(MANIFEST_FILE, "fail", `${path} is missing; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`);
140
+ }
141
+ else {
142
+ let text;
143
+ try {
144
+ text = readFileSync(path, "utf8");
145
+ }
146
+ catch (error) {
147
+ add(MANIFEST_FILE, "fail", `${path} could not be read: ${errorMessage(error)}`);
148
+ }
149
+ if (text !== undefined) {
150
+ let parsed;
151
+ let parseError;
152
+ try {
153
+ parsed = parseManifestYaml(text);
154
+ }
155
+ catch (error) {
156
+ parseError = errorMessage(error);
157
+ }
158
+ if (parseError !== undefined) {
159
+ add(MANIFEST_FILE, "fail", `${path} does not parse: ${parseError}`);
160
+ }
161
+ else {
162
+ const fileViolations = validateManifest(parsed);
163
+ if (fileViolations.length > 0) {
164
+ add(MANIFEST_FILE, "fail", `${path} does not validate: ${fileViolations.join("; ")}`);
165
+ }
166
+ else if (rendered !== undefined && text !== rendered) {
167
+ add(MANIFEST_FILE, "fail", `${path} is stale: first difference at line ${firstDifferingLine(text, rendered)}; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`);
168
+ }
169
+ else if (rendered !== undefined) {
170
+ add(MANIFEST_FILE, "ok", `${path} validates and agrees with the code`);
171
+ }
172
+ else {
173
+ add(MANIFEST_FILE, "fail", `${path} validates but the effective manifest does not`);
174
+ }
175
+ }
176
+ }
177
+ }
178
+ const identity = join(root, manifest.content.identity);
179
+ try {
180
+ if (!existsSync(identity))
181
+ add("identity", "fail", `${identity} is missing`);
182
+ else if (readFileSync(identity, "utf8").trim() === "")
183
+ add("identity", "fail", `${identity} is empty`);
184
+ else
185
+ add("identity", "ok", identity);
186
+ }
187
+ catch (error) {
188
+ add("identity", "fail", `${identity} could not be read: ${errorMessage(error)}`);
189
+ }
190
+ }
191
+ if (app.harnessSelectionError !== undefined)
192
+ add("harness", "fail", app.harnessSelectionError);
193
+ else
194
+ add("harness", "ok", `${ENV_HARNESS}: ${app.harnessSelection}`);
195
+ const modes = manifest.modes;
196
+ const selected = io.env[ENV_MODE]?.trim();
197
+ if (selected === undefined || selected === "") {
198
+ add("modes", "ok", `declared: ${modes.join(", ")}; default ${modes[0]}`);
199
+ }
200
+ else if (modes.includes(selected)) {
201
+ add("modes", "ok", `${ENV_MODE}=${selected} is declared (declared: ${modes.join(", ")})`);
202
+ }
203
+ else {
204
+ add("modes", "fail", `${ENV_MODE}=${selected} is not declared (declared: ${modes.join(", ")}); a plain run falls back and counts it`);
205
+ }
206
+ if (app.endpoint !== undefined) {
207
+ // under sidecar the endpoint has been listening since startup; doctor says where, or why not
208
+ try {
209
+ await app.endpoint.ready;
210
+ add("endpoint", "ok", `listening at ${app.endpoint.socketPath}`);
211
+ }
212
+ catch (error) {
213
+ add("endpoint", "fail", `the endpoint could not listen: ${errorMessage(error)}`);
214
+ }
215
+ }
216
+ try {
217
+ const auditPath = expandHome(manifest.audit.path, io.env.HOME ?? "");
218
+ const ancestor = existingAncestor(dirname(resolve(io.cwd, auditPath)));
219
+ if (!statSync(ancestor).isDirectory()) {
220
+ add("audit", "fail", `${ancestor} is not a directory`);
221
+ }
222
+ else {
223
+ accessSync(ancestor, constants.W_OK);
224
+ add("audit", "ok", `${auditPath} (${ancestor} is writable)`);
225
+ }
226
+ }
227
+ catch (error) {
228
+ add("audit", "fail", `the audit directory is not writable: ${errorMessage(error)}`);
229
+ }
230
+ if (options.online === false) {
231
+ add("online", "skip", "not asked (--offline)");
232
+ }
233
+ else {
234
+ const harness = await importHarnessModule(io.env, manifest);
235
+ if (!harness?.doctorOnline) {
236
+ add("online", "skip", "no harness is installed to check the model");
237
+ }
238
+ else {
239
+ try {
240
+ for (const check of await harness.doctorOnline(manifest, io.env))
241
+ add(check.name, check.status, check.detail);
242
+ }
243
+ catch (error) {
244
+ add("online", "fail", `the harness's check failed: ${errorMessage(error)}`);
245
+ }
246
+ }
247
+ }
248
+ return { ok: checks.every((check) => check.status !== "fail"), root: root ?? null, checks };
249
+ }
250
+ function printReport(report, io) {
251
+ for (const check of report.checks)
252
+ io.out(`${check.status.padEnd(4)} ${check.name}: ${check.detail}\n`);
253
+ io.out(report.ok ? "doctor: ok\n" : "doctor: failed\n");
254
+ }
255
+ /**
256
+ * `<prog> abai <verb> ...`. `args` are the arguments after the program's
257
+ * own name; the first must be `abai`. Resolves to the exit code; -1 means
258
+ * the arguments were not an abai entry at all.
259
+ */
260
+ export async function runEntry(app, args, io = processIo) {
261
+ if (args[0] !== "abai") {
262
+ // the entry is one of the five attach places (4.3): a launched program takes up its connection here,
263
+ // before its own work, so its first touchpoint finds the agent present
264
+ if (app.launched)
265
+ await app.attach();
266
+ return -1;
267
+ }
268
+ const { manifest } = app;
269
+ const usage = (problem) => {
270
+ if (problem !== undefined)
271
+ io.err(`${manifest.entry}: ${problem}`);
272
+ for (const line of usageLines(manifest.entry))
273
+ io.err(line);
274
+ return 2;
275
+ };
276
+ try {
277
+ const verb = args[1];
278
+ switch (verb) {
279
+ case "manifest": {
280
+ const flags = parseFlags(args.slice(2), ["--json"]);
281
+ if (typeof flags === "string")
282
+ return usage(flags);
283
+ // a selected mode the manifest does not declare is an error at the entry (section 4.4)
284
+ const selected = io.env[ENV_MODE]?.trim();
285
+ if (selected !== undefined && selected !== "" && !manifest.modes.includes(selected)) {
286
+ io.err(`${manifest.entry}: ${ENV_MODE}=${selected} is not a declared mode (declared: ${manifest.modes.join(", ")})`);
287
+ return 2;
288
+ }
289
+ io.out(flags.json ? `${JSON.stringify(manifest, null, 2)}\n` : renderManifestYaml(manifest));
290
+ return 0;
291
+ }
292
+ case "doctor": {
293
+ const flags = parseFlags(args.slice(2), ["--json", "--root", "--offline"]);
294
+ if (typeof flags === "string")
295
+ return usage(flags);
296
+ const report = await runDoctor(app, { root: flags.root, io, online: !flags.offline });
297
+ if (flags.json)
298
+ io.out(`${JSON.stringify(report, null, 2)}\n`);
299
+ else
300
+ printReport(report, io);
301
+ return report.ok ? 0 : 1;
302
+ }
303
+ case undefined:
304
+ case "session": {
305
+ await app.session();
306
+ if (app.attached)
307
+ return 0;
308
+ io.err(`${manifest.entry}: no harness attached (${app.attachError ?? "unknown reason"})`);
309
+ return 1;
310
+ }
311
+ case "install": {
312
+ await app.install();
313
+ if (app.attached)
314
+ return 0;
315
+ io.err(`${manifest.entry}: no harness attached (${app.attachError ?? "unknown reason"})`);
316
+ return 1;
317
+ }
318
+ case "config": {
319
+ const harness = await importHarnessModule(io.env, manifest);
320
+ if (!harness?.runConfig)
321
+ return usage("config needs the harness package, which is not installed");
322
+ return await harness.runConfig(args.slice(2), io, { program: manifest.name });
323
+ }
324
+ case "mcp": {
325
+ // the program at its entry serves an MCP client: under sidecar through the binary on this
326
+ // process's stdio, otherwise in-process through the installed harness package (section 4.4).
327
+ // ABAI_HARNESS is honoured like everywhere: off attaches nothing, a null harness is attached already
328
+ if (app.harnessSelection === "off") {
329
+ io.err(`${manifest.entry}: no harness attached (${ENV_HARNESS}=off)`);
330
+ return 1;
331
+ }
332
+ if (app.attached) {
333
+ io.err(`${manifest.entry}: ${manifest.name} already has a harness attached`);
334
+ return 1;
335
+ }
336
+ if (app.endpoint !== undefined) {
337
+ const code = await app.serveMcpSidecar(app.endpoint);
338
+ if (code >= 0)
339
+ return code;
340
+ io.err(`${manifest.entry}: no harness attached (${app.attachError ?? "unknown reason"})`);
341
+ return 1;
342
+ }
343
+ const harness = await importHarnessModule(io.env, manifest);
344
+ if (!harness?.serveMcpEmbedded)
345
+ return usage("mcp needs the harness package, which is not installed");
346
+ const binding = app.bind("mcp");
347
+ binding.enterSafepoint();
348
+ try {
349
+ return await harness.serveMcpEmbedded(binding);
350
+ }
351
+ finally {
352
+ binding.leaveSafepoint();
353
+ }
354
+ }
355
+ case "run": {
356
+ // sidecar launch (4.4, 6.3): the harness binary starts this very program again as its child
357
+ if (!manifest.modes.includes("sidecar")) {
358
+ io.err(`${manifest.entry}: run is sidecar launch, and ${manifest.name} declares ${manifest.modes.join(", ")}`);
359
+ return 2;
360
+ }
361
+ const separator = args.indexOf("--");
362
+ const flags = args.slice(2, separator === -1 ? undefined : separator);
363
+ const programArgs = separator === -1 ? [] : args.slice(separator + 1);
364
+ for (const flag of flags) {
365
+ if (flag !== "--auto" && flag !== "--deny-mutate" && flag !== "--all-events") {
366
+ return usage(`unknown option ${flag} (run takes --auto, --deny-mutate, --all-events)`);
367
+ }
368
+ }
369
+ const binary = harnessBinary(io.env, app.content.root);
370
+ const script = process.argv[1];
371
+ if (script === undefined)
372
+ return usage("run cannot tell how this program was started");
373
+ const command = [process.execPath, ...process.execArgv, script, ...programArgs];
374
+ const child = spawn(binary.command, [...binary.args, "run", ...flags, "--", ...command], {
375
+ stdio: "inherit",
376
+ env: { ...process.env, ...io.env },
377
+ });
378
+ // whoever ends this process ends the launcher behind it, which ends the program it supervises
379
+ const forward = (signal) => {
380
+ if (child.exitCode === null && child.signalCode === null)
381
+ child.kill(signal);
382
+ };
383
+ const forwarded = ["SIGTERM", "SIGINT", "SIGHUP"];
384
+ for (const signal of forwarded)
385
+ process.on(signal, forward);
386
+ try {
387
+ return await new Promise((resolve) => {
388
+ child.once("error", (error) => {
389
+ io.err(`${manifest.entry}: the harness binary could not be started: ${errorMessage(error)}`);
390
+ resolve(1);
391
+ });
392
+ child.once("exit", (code) => resolve(code ?? 1));
393
+ });
394
+ }
395
+ finally {
396
+ for (const signal of forwarded)
397
+ process.off(signal, forward);
398
+ }
399
+ }
400
+ default:
401
+ return usage(`unknown verb ${verb}`);
402
+ }
403
+ }
404
+ catch (error) {
405
+ io.err(`${manifest.entry}: ${errorMessage(error)}`);
406
+ return 2;
407
+ }
408
+ }
409
+ //# sourceMappingURL=entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"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","sourcesContent":["// The standard agent entry (abaigrammar section 4.4), the part the stub\n// provides itself: `<prog> abai manifest` prints the effective manifest and\n// `<prog> abai doctor` runs the offline conformance checks. The verbs that\n// need a harness (session, install, config, mcp, run) are delegated once a\n// harness binding exists; until then the usage says so. Never throws;\n// resolves to the exit code.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { findRoot, MANIFEST_FILE } from \"./content.ts\";\nimport { ENV_HARNESS, ENV_MODE, expandHome } from \"./env.ts\";\nimport { validateManifest } from \"./manifest/manifest.ts\";\nimport { parseManifestYaml, renderManifestYaml } from \"./manifest/render.ts\";\nimport { type Abaigram, harnessBinary, importHarnessModule } from \"./program.ts\";\n\nexport const STUB_VERSION = \"0.2.0\";\n\nexport type CheckStatus = \"ok\" | \"fail\" | \"skip\";\n\nexport interface DoctorCheck {\n\tname: string;\n\tstatus: CheckStatus;\n\tdetail: string;\n}\n\nexport interface DoctorReport {\n\tok: boolean;\n\troot: string | null;\n\tchecks: DoctorCheck[];\n}\n\n/** Where the entry writes; injectable for tests. */\nexport interface EntryIo {\n\tout(text: string): void;\n\terr(text: string): void;\n\tenv: NodeJS.ProcessEnv;\n\tcwd: string;\n}\n\nexport const processIo: EntryIo = {\n\tout: (text) => {\n\t\tprocess.stdout.write(text);\n\t},\n\terr: (text) => {\n\t\tprocess.stderr.write(`${text}\\n`);\n\t},\n\tenv: process.env,\n\tget cwd() {\n\t\treturn process.cwd();\n\t},\n};\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction usageLines(entry: string): string[] {\n\treturn [\n\t\t`usage: ${entry} open a session`,\n\t\t` ${entry} install run the install touchpoint`,\n\t\t` ${entry} manifest [--json] print the effective manifest`,\n\t\t` ${entry} doctor [--root <dir>] [--offline] [--json]`,\n\t\t` ${entry} config [set ...] the machine-level model configuration`,\n\t\t` ${entry} mcp serve the agent's tools to an MCP client over stdio`,\n\t\t` ${entry} run [--auto] -- ARGS the harness starts this program as its supervised child`,\n\t\t\"\",\n\t\t\"doctor offline conformance checks: the effective manifest, the checked-in\",\n\t\t` ${MANIFEST_FILE}, the identity content, the modes, the audit directory`,\n\t\t\"\",\n\t\t\"session and install attach a harness and return when none can attach; mcp needs no model,\",\n\t\t\"since the client's own agent is this program's; run is always sidecar launch, with the whole\",\n\t\t\"lifecycle channel and the program's output observed from outside.\",\n\t];\n}\n\ninterface Flags {\n\tjson: boolean;\n\troot: string | undefined;\n\toffline: boolean;\n}\n\n/** `--flag`, `--flag value` and `--flag=value`; anything else is a usage error. */\nfunction parseFlags(args: string[], allowed: readonly string[]): Flags | string {\n\tconst flags: Flags = { json: false, root: undefined, offline: false };\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tconst eq = arg.indexOf(\"=\");\n\t\tconst name = eq === -1 ? arg : arg.slice(0, eq);\n\t\tif (!allowed.includes(name)) return `unknown option ${arg}`;\n\t\tconst takeValue = (): string | undefined => {\n\t\t\tif (eq !== -1) return arg.slice(eq + 1);\n\t\t\ti += 1;\n\t\t\treturn args[i];\n\t\t};\n\t\tswitch (name) {\n\t\t\tcase \"--json\":\n\t\t\t\tflags.json = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--offline\":\n\t\t\t\tflags.offline = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--root\": {\n\t\t\t\tconst value = takeValue();\n\t\t\t\tif (value === undefined || value === \"\") return \"--root needs a directory\";\n\t\t\t\tflags.root = value;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn `unknown option ${arg}`;\n\t\t}\n\t}\n\treturn flags;\n}\n\n/** The first line at which two texts differ (1-based), or undefined when equal. */\nexport function firstDifferingLine(a: string, b: string): number | undefined {\n\tif (a === b) return undefined;\n\tconst linesA = a.split(\"\\n\");\n\tconst linesB = b.split(\"\\n\");\n\tconst n = Math.max(linesA.length, linesB.length);\n\tfor (let i = 0; i < n; i++) {\n\t\tif (linesA[i] !== linesB[i]) return i + 1;\n\t}\n\treturn n;\n}\n\n/** The first existing ancestor of a path (the path itself included). */\nfunction existingAncestor(path: string): string {\n\tlet current = path;\n\twhile (!existsSync(current)) {\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tcurrent = parent;\n\t}\n\treturn current;\n}\n\n/** The offline half of `doctor` (section 4.4), plus the online half when the harness package is installed. Never throws. */\nexport async function runDoctor(\n\tapp: Abaigram,\n\toptions: { root?: string; io?: EntryIo; online?: boolean } = {},\n): Promise<DoctorReport> {\n\tconst io = options.io ?? processIo;\n\tconst checks: DoctorCheck[] = [];\n\tconst add = (name: string, status: CheckStatus, detail: string) => {\n\t\tchecks.push({ name, status, detail });\n\t};\n\tconst { manifest } = app;\n\n\tadd(\"entry\", \"ok\", `${manifest.entry} reached (abai stub ${STUB_VERSION})`);\n\n\tconst violations = validateManifest(manifest);\n\tlet rendered: string | undefined;\n\tif (violations.length === 0) {\n\t\trendered = renderManifestYaml(manifest);\n\t\tadd(\n\t\t\t\"manifest\",\n\t\t\t\"ok\",\n\t\t\t`the effective manifest validates (${manifest.cells.length} cells, ${manifest.events.length} events, ${manifest.capabilities.length} capabilities, ${manifest.decisions.length} decisions, ${manifest.turns.length} turns)`,\n\t\t);\n\t} else {\n\t\tadd(\"manifest\", \"fail\", `the effective manifest does not validate: ${violations.join(\"; \")}`);\n\t}\n\n\tconst root =\n\t\toptions.root !== undefined\n\t\t\t? resolve(io.cwd, options.root)\n\t\t\t: (findRoot(manifest.name, io.cwd) ??\n\t\t\t\t(existsSync(join(app.content.root, MANIFEST_FILE)) ? app.content.root : undefined));\n\tif (root === undefined) {\n\t\tadd(\"root\", \"skip\", `no checkout found (pass --root <dir> to check a checked-in ${MANIFEST_FILE})`);\n\t\tadd(MANIFEST_FILE, \"skip\", \"no checkout\");\n\t\tadd(\"identity\", \"skip\", \"no checkout\");\n\t} else {\n\t\tadd(\"root\", \"ok\", root);\n\t\tconst path = join(root, MANIFEST_FILE);\n\t\tif (!existsSync(path)) {\n\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} is missing; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`);\n\t\t} else {\n\t\t\tlet text: string | undefined;\n\t\t\ttry {\n\t\t\t\ttext = readFileSync(path, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} could not be read: ${errorMessage(error)}`);\n\t\t\t}\n\t\t\tif (text !== undefined) {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\tlet parseError: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = parseManifestYaml(text);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tparseError = errorMessage(error);\n\t\t\t\t}\n\t\t\t\tif (parseError !== undefined) {\n\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} does not parse: ${parseError}`);\n\t\t\t\t} else {\n\t\t\t\t\tconst fileViolations = validateManifest(parsed);\n\t\t\t\t\tif (fileViolations.length > 0) {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} does not validate: ${fileViolations.join(\"; \")}`);\n\t\t\t\t\t} else if (rendered !== undefined && text !== rendered) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tMANIFEST_FILE,\n\t\t\t\t\t\t\t\"fail\",\n\t\t\t\t\t\t\t`${path} is stale: first difference at line ${firstDifferingLine(text, rendered)}; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (rendered !== undefined) {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"ok\", `${path} validates and agrees with the code`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} validates but the effective manifest does not`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst identity = join(root, manifest.content.identity);\n\t\ttry {\n\t\t\tif (!existsSync(identity)) add(\"identity\", \"fail\", `${identity} is missing`);\n\t\t\telse if (readFileSync(identity, \"utf8\").trim() === \"\") add(\"identity\", \"fail\", `${identity} is empty`);\n\t\t\telse add(\"identity\", \"ok\", identity);\n\t\t} catch (error) {\n\t\t\tadd(\"identity\", \"fail\", `${identity} could not be read: ${errorMessage(error)}`);\n\t\t}\n\t}\n\n\tif (app.harnessSelectionError !== undefined) add(\"harness\", \"fail\", app.harnessSelectionError);\n\telse add(\"harness\", \"ok\", `${ENV_HARNESS}: ${app.harnessSelection}`);\n\n\tconst modes = manifest.modes as string[];\n\tconst selected = io.env[ENV_MODE]?.trim();\n\tif (selected === undefined || selected === \"\") {\n\t\tadd(\"modes\", \"ok\", `declared: ${modes.join(\", \")}; default ${modes[0]}`);\n\t} else if (modes.includes(selected)) {\n\t\tadd(\"modes\", \"ok\", `${ENV_MODE}=${selected} is declared (declared: ${modes.join(\", \")})`);\n\t} else {\n\t\tadd(\n\t\t\t\"modes\",\n\t\t\t\"fail\",\n\t\t\t`${ENV_MODE}=${selected} is not declared (declared: ${modes.join(\", \")}); a plain run falls back and counts it`,\n\t\t);\n\t}\n\n\tif (app.endpoint !== undefined) {\n\t\t// under sidecar the endpoint has been listening since startup; doctor says where, or why not\n\t\ttry {\n\t\t\tawait app.endpoint.ready;\n\t\t\tadd(\"endpoint\", \"ok\", `listening at ${app.endpoint.socketPath}`);\n\t\t} catch (error) {\n\t\t\tadd(\"endpoint\", \"fail\", `the endpoint could not listen: ${errorMessage(error)}`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst auditPath = expandHome(manifest.audit.path, io.env.HOME ?? \"\");\n\t\tconst ancestor = existingAncestor(dirname(resolve(io.cwd, auditPath)));\n\t\tif (!statSync(ancestor).isDirectory()) {\n\t\t\tadd(\"audit\", \"fail\", `${ancestor} is not a directory`);\n\t\t} else {\n\t\t\taccessSync(ancestor, constants.W_OK);\n\t\t\tadd(\"audit\", \"ok\", `${auditPath} (${ancestor} is writable)`);\n\t\t}\n\t} catch (error) {\n\t\tadd(\"audit\", \"fail\", `the audit directory is not writable: ${errorMessage(error)}`);\n\t}\n\n\tif (options.online === false) {\n\t\tadd(\"online\", \"skip\", \"not asked (--offline)\");\n\t} else {\n\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\tif (!harness?.doctorOnline) {\n\t\t\tadd(\"online\", \"skip\", \"no harness is installed to check the model\");\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tfor (const check of await harness.doctorOnline(manifest, io.env))\n\t\t\t\t\tadd(check.name, check.status, check.detail);\n\t\t\t} catch (error) {\n\t\t\t\tadd(\"online\", \"fail\", `the harness's check failed: ${errorMessage(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { ok: checks.every((check) => check.status !== \"fail\"), root: root ?? null, checks };\n}\n\nfunction printReport(report: DoctorReport, io: EntryIo): void {\n\tfor (const check of report.checks) io.out(`${check.status.padEnd(4)} ${check.name}: ${check.detail}\\n`);\n\tio.out(report.ok ? \"doctor: ok\\n\" : \"doctor: failed\\n\");\n}\n\n/**\n * `<prog> abai <verb> ...`. `args` are the arguments after the program's\n * own name; the first must be `abai`. Resolves to the exit code; -1 means\n * the arguments were not an abai entry at all.\n */\nexport async function runEntry(app: Abaigram, args: string[], io: EntryIo = processIo): Promise<number> {\n\tif (args[0] !== \"abai\") {\n\t\t// the entry is one of the five attach places (4.3): a launched program takes up its connection here,\n\t\t// before its own work, so its first touchpoint finds the agent present\n\t\tif (app.launched) await app.attach();\n\t\treturn -1;\n\t}\n\tconst { manifest } = app;\n\tconst usage = (problem?: string): number => {\n\t\tif (problem !== undefined) io.err(`${manifest.entry}: ${problem}`);\n\t\tfor (const line of usageLines(manifest.entry)) io.err(line);\n\t\treturn 2;\n\t};\n\ttry {\n\t\tconst verb = args[1];\n\t\tswitch (verb) {\n\t\t\tcase \"manifest\": {\n\t\t\t\tconst flags = parseFlags(args.slice(2), [\"--json\"]);\n\t\t\t\tif (typeof flags === \"string\") return usage(flags);\n\t\t\t\t// a selected mode the manifest does not declare is an error at the entry (section 4.4)\n\t\t\t\tconst selected = io.env[ENV_MODE]?.trim();\n\t\t\t\tif (selected !== undefined && selected !== \"\" && !(manifest.modes as string[]).includes(selected)) {\n\t\t\t\t\tio.err(\n\t\t\t\t\t\t`${manifest.entry}: ${ENV_MODE}=${selected} is not a declared mode (declared: ${manifest.modes.join(\", \")})`,\n\t\t\t\t\t);\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\t\t\t\tio.out(flags.json ? `${JSON.stringify(manifest, null, 2)}\\n` : renderManifestYaml(manifest));\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tcase \"doctor\": {\n\t\t\t\tconst flags = parseFlags(args.slice(2), [\"--json\", \"--root\", \"--offline\"]);\n\t\t\t\tif (typeof flags === \"string\") return usage(flags);\n\t\t\t\tconst report = await runDoctor(app, { root: flags.root, io, online: !flags.offline });\n\t\t\t\tif (flags.json) io.out(`${JSON.stringify(report, null, 2)}\\n`);\n\t\t\t\telse printReport(report, io);\n\t\t\t\treturn report.ok ? 0 : 1;\n\t\t\t}\n\t\t\tcase undefined:\n\t\t\tcase \"session\": {\n\t\t\t\tawait app.session();\n\t\t\t\tif (app.attached) return 0;\n\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tcase \"install\": {\n\t\t\t\tawait app.install();\n\t\t\t\tif (app.attached) return 0;\n\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tcase \"config\": {\n\t\t\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\t\t\tif (!harness?.runConfig) return usage(\"config needs the harness package, which is not installed\");\n\t\t\t\treturn await harness.runConfig(args.slice(2), io, { program: manifest.name });\n\t\t\t}\n\t\t\tcase \"mcp\": {\n\t\t\t\t// the program at its entry serves an MCP client: under sidecar through the binary on this\n\t\t\t\t// process's stdio, otherwise in-process through the installed harness package (section 4.4).\n\t\t\t\t// ABAI_HARNESS is honoured like everywhere: off attaches nothing, a null harness is attached already\n\t\t\t\tif (app.harnessSelection === \"off\") {\n\t\t\t\t\tio.err(`${manifest.entry}: no harness attached (${ENV_HARNESS}=off)`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (app.attached) {\n\t\t\t\t\tio.err(`${manifest.entry}: ${manifest.name} already has a harness attached`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (app.endpoint !== undefined) {\n\t\t\t\t\tconst code = await app.serveMcpSidecar(app.endpoint);\n\t\t\t\t\tif (code >= 0) return code;\n\t\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\t\t\tif (!harness?.serveMcpEmbedded) return usage(\"mcp needs the harness package, which is not installed\");\n\t\t\t\tconst binding = app.bind(\"mcp\");\n\t\t\t\tbinding.enterSafepoint();\n\t\t\t\ttry {\n\t\t\t\t\treturn await harness.serveMcpEmbedded(binding);\n\t\t\t\t} finally {\n\t\t\t\t\tbinding.leaveSafepoint();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"run\": {\n\t\t\t\t// sidecar launch (4.4, 6.3): the harness binary starts this very program again as its child\n\t\t\t\tif (!(manifest.modes as string[]).includes(\"sidecar\")) {\n\t\t\t\t\tio.err(\n\t\t\t\t\t\t`${manifest.entry}: run is sidecar launch, and ${manifest.name} declares ${manifest.modes.join(\", \")}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\t\t\t\tconst separator = args.indexOf(\"--\");\n\t\t\t\tconst flags = args.slice(2, separator === -1 ? undefined : separator);\n\t\t\t\tconst programArgs = separator === -1 ? [] : args.slice(separator + 1);\n\t\t\t\tfor (const flag of flags) {\n\t\t\t\t\tif (flag !== \"--auto\" && flag !== \"--deny-mutate\" && flag !== \"--all-events\") {\n\t\t\t\t\t\treturn usage(`unknown option ${flag} (run takes --auto, --deny-mutate, --all-events)`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst binary = harnessBinary(io.env, app.content.root);\n\t\t\t\tconst script = process.argv[1];\n\t\t\t\tif (script === undefined) return usage(\"run cannot tell how this program was started\");\n\t\t\t\tconst command = [process.execPath, ...process.execArgv, script, ...programArgs];\n\t\t\t\tconst child = spawn(binary.command, [...binary.args, \"run\", ...flags, \"--\", ...command], {\n\t\t\t\t\tstdio: \"inherit\",\n\t\t\t\t\tenv: { ...process.env, ...io.env },\n\t\t\t\t});\n\t\t\t\t// whoever ends this process ends the launcher behind it, which ends the program it supervises\n\t\t\t\tconst forward = (signal: NodeJS.Signals): void => {\n\t\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(signal);\n\t\t\t\t};\n\t\t\t\tconst forwarded: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\t\t\t\tfor (const signal of forwarded) process.on(signal, forward);\n\t\t\t\ttry {\n\t\t\t\t\treturn await new Promise<number>((resolve) => {\n\t\t\t\t\t\tchild.once(\"error\", (error) => {\n\t\t\t\t\t\t\tio.err(`${manifest.entry}: the harness binary could not be started: ${errorMessage(error)}`);\n\t\t\t\t\t\t\tresolve(1);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tchild.once(\"exit\", (code) => resolve(code ?? 1));\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tfor (const signal of forwarded) process.off(signal, forward);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn usage(`unknown verb ${verb}`);\n\t\t}\n\t} catch (error) {\n\t\tio.err(`${manifest.entry}: ${errorMessage(error)}`);\n\t\treturn 2;\n\t}\n}\n"]}
package/dist/env.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import type { Mode } from "./manifest/manifest.ts";
2
+ export declare const ENV_MODE = "ABAI_MODE";
3
+ export declare const ENV_HARNESS = "ABAI_HARNESS";
4
+ /**
5
+ * Set by a harness that launched this program (section 6.3): the socket its
6
+ * endpoint must listen on, where the launcher is already waiting. Its
7
+ * presence is also what makes the full lifecycle channel available (5.5).
8
+ */
9
+ export declare const ENV_LAUNCH_SOCKET = "ABAI_LAUNCH_SOCKET";
10
+ /** Where a sidecar endpoint puts its socket and descriptor; default `<ABAI_HOME or ~/.abai>/run`, the harness's own default. */
11
+ export declare const ENV_RUN_DIR = "ABAI_RUN_DIR";
12
+ /** The harness binary the stub spawns at a touchpoint under sidecar; default: the program's `node_modules/.bin`, else PATH. */
13
+ export declare const ENV_HARNESS_BIN = "ABAI_HARNESS_BIN";
14
+ /** How long a sidecar attach waits for the spawned harness to connect, in milliseconds. */
15
+ export declare const ENV_ATTACH_WAIT_MS = "ABAI_ATTACH_WAIT_MS";
16
+ export declare const DEFAULT_ATTACH_WAIT_MS = 30000;
17
+ /** The run directory for this environment. With no home at all, a private directory under the machine's temp dir. */
18
+ export declare function runDirFrom(env?: NodeJS.ProcessEnv): string;
19
+ /** The attach wait for this environment; an unusable value means the default. */
20
+ export declare function attachWaitMsFrom(env?: NodeJS.ProcessEnv): number;
21
+ export type HarnessSelection = "real" | "off" | "null" | "exercise";
22
+ export interface ModeSelection {
23
+ mode: Mode;
24
+ /** The requested mode was not declared; the default applies and is counted. */
25
+ fallback: boolean;
26
+ /** What `ABAI_MODE` asked for, when set. */
27
+ requested?: string;
28
+ }
29
+ /** The mode for this run: the first declared, unless `ABAI_MODE` names a declared one. */
30
+ export declare function selectMode(modes: readonly Mode[], env?: NodeJS.ProcessEnv): ModeSelection;
31
+ /** The harness for this run. An unknown value selects the real harness and is reported, never thrown: the program runs. */
32
+ export declare function selectHarness(env?: NodeJS.ProcessEnv): {
33
+ selection: HarnessSelection;
34
+ error?: string;
35
+ };
36
+ /** `~` at the start of a path means the home directory. */
37
+ export declare function expandHome(path: string, home?: string): string;
38
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAEnD,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AACtD,gIAAgI;AAChI,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C,+HAA+H;AAC/H,eAAO,MAAM,eAAe,qBAAqB,CAAC;AAClD,2FAA2F;AAC3F,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,qHAAqH;AACrH,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAOvE;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAG7E;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,+EAA+E;IAC/E,QAAQ,EAAE,OAAO,CAAC;IAClB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,CAOtG;AAED,2HAA2H;AAC3H,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG;IAAE,SAAS,EAAE,gBAAgB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAKnH;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAyB,GAAG,MAAM,CAI9E","sourcesContent":["// Mode and harness selection from the environment (abaigrammar section 4.4).\n// `ABAI_MODE` overrides the manifest's default mode; a value the manifest\n// does not declare falls back to the default and is counted. `ABAI_HARNESS`\n// is read only by check runs: unset means the real harness, `off` makes\n// every attach fail at once, `null` and `exercise` select the null harness\n// in its passive and active forms.\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Mode } from \"./manifest/manifest.ts\";\n\nexport const ENV_MODE = \"ABAI_MODE\";\nexport const ENV_HARNESS = \"ABAI_HARNESS\";\n/**\n * Set by a harness that launched this program (section 6.3): the socket its\n * endpoint must listen on, where the launcher is already waiting. Its\n * presence is also what makes the full lifecycle channel available (5.5).\n */\nexport const ENV_LAUNCH_SOCKET = \"ABAI_LAUNCH_SOCKET\";\n/** Where a sidecar endpoint puts its socket and descriptor; default `<ABAI_HOME or ~/.abai>/run`, the harness's own default. */\nexport const ENV_RUN_DIR = \"ABAI_RUN_DIR\";\n/** The harness binary the stub spawns at a touchpoint under sidecar; default: the program's `node_modules/.bin`, else PATH. */\nexport const ENV_HARNESS_BIN = \"ABAI_HARNESS_BIN\";\n/** How long a sidecar attach waits for the spawned harness to connect, in milliseconds. */\nexport const ENV_ATTACH_WAIT_MS = \"ABAI_ATTACH_WAIT_MS\";\nexport const DEFAULT_ATTACH_WAIT_MS = 30_000;\n\n/** The run directory for this environment. With no home at all, a private directory under the machine's temp dir. */\nexport function runDirFrom(env: NodeJS.ProcessEnv = process.env): string {\n\tconst explicit = env[ENV_RUN_DIR]?.trim();\n\tif (explicit) return explicit;\n\tconst home = env.ABAI_HOME?.trim();\n\tif (home) return join(home, \"run\");\n\tconst user = env.HOME?.trim();\n\treturn user ? join(user, \".abai\", \"run\") : join(tmpdir(), \"abai-run\");\n}\n\n/** The attach wait for this environment; an unusable value means the default. */\nexport function attachWaitMsFrom(env: NodeJS.ProcessEnv = process.env): number {\n\tconst value = Number(env[ENV_ATTACH_WAIT_MS]);\n\treturn Number.isInteger(value) && value > 0 ? value : DEFAULT_ATTACH_WAIT_MS;\n}\n\nexport type HarnessSelection = \"real\" | \"off\" | \"null\" | \"exercise\";\n\nexport interface ModeSelection {\n\tmode: Mode;\n\t/** The requested mode was not declared; the default applies and is counted. */\n\tfallback: boolean;\n\t/** What `ABAI_MODE` asked for, when set. */\n\trequested?: string;\n}\n\n/** The mode for this run: the first declared, unless `ABAI_MODE` names a declared one. */\nexport function selectMode(modes: readonly Mode[], env: NodeJS.ProcessEnv = process.env): ModeSelection {\n\tconst requested = env[ENV_MODE]?.trim();\n\tconst first = modes[0];\n\tif (first === undefined) throw new Error(\"the manifest declares no modes\");\n\tif (requested === undefined || requested === \"\") return { mode: first, fallback: false };\n\tif ((modes as readonly string[]).includes(requested)) return { mode: requested as Mode, fallback: false, requested };\n\treturn { mode: first, fallback: true, requested };\n}\n\n/** The harness for this run. An unknown value selects the real harness and is reported, never thrown: the program runs. */\nexport function selectHarness(env: NodeJS.ProcessEnv = process.env): { selection: HarnessSelection; error?: string } {\n\tconst value = env[ENV_HARNESS]?.trim();\n\tif (value === undefined || value === \"\") return { selection: \"real\" };\n\tif (value === \"off\" || value === \"null\" || value === \"exercise\") return { selection: value };\n\treturn { selection: \"real\", error: `${ENV_HARNESS} must be unset, off, null or exercise (got ${value})` };\n}\n\n/** `~` at the start of a path means the home directory. */\nexport function expandHome(path: string, home = process.env.HOME ?? \"\"): string {\n\tif (path === \"~\") return home;\n\tif (path.startsWith(\"~/\")) return `${home}${path.slice(1)}`;\n\treturn path;\n}\n"]}
package/dist/env.js ADDED
@@ -0,0 +1,69 @@
1
+ // Mode and harness selection from the environment (abaigrammar section 4.4).
2
+ // `ABAI_MODE` overrides the manifest's default mode; a value the manifest
3
+ // does not declare falls back to the default and is counted. `ABAI_HARNESS`
4
+ // is read only by check runs: unset means the real harness, `off` makes
5
+ // every attach fail at once, `null` and `exercise` select the null harness
6
+ // in its passive and active forms.
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ export const ENV_MODE = "ABAI_MODE";
10
+ export const ENV_HARNESS = "ABAI_HARNESS";
11
+ /**
12
+ * Set by a harness that launched this program (section 6.3): the socket its
13
+ * endpoint must listen on, where the launcher is already waiting. Its
14
+ * presence is also what makes the full lifecycle channel available (5.5).
15
+ */
16
+ export const ENV_LAUNCH_SOCKET = "ABAI_LAUNCH_SOCKET";
17
+ /** Where a sidecar endpoint puts its socket and descriptor; default `<ABAI_HOME or ~/.abai>/run`, the harness's own default. */
18
+ export const ENV_RUN_DIR = "ABAI_RUN_DIR";
19
+ /** The harness binary the stub spawns at a touchpoint under sidecar; default: the program's `node_modules/.bin`, else PATH. */
20
+ export const ENV_HARNESS_BIN = "ABAI_HARNESS_BIN";
21
+ /** How long a sidecar attach waits for the spawned harness to connect, in milliseconds. */
22
+ export const ENV_ATTACH_WAIT_MS = "ABAI_ATTACH_WAIT_MS";
23
+ export const DEFAULT_ATTACH_WAIT_MS = 30_000;
24
+ /** The run directory for this environment. With no home at all, a private directory under the machine's temp dir. */
25
+ export function runDirFrom(env = process.env) {
26
+ const explicit = env[ENV_RUN_DIR]?.trim();
27
+ if (explicit)
28
+ return explicit;
29
+ const home = env.ABAI_HOME?.trim();
30
+ if (home)
31
+ return join(home, "run");
32
+ const user = env.HOME?.trim();
33
+ return user ? join(user, ".abai", "run") : join(tmpdir(), "abai-run");
34
+ }
35
+ /** The attach wait for this environment; an unusable value means the default. */
36
+ export function attachWaitMsFrom(env = process.env) {
37
+ const value = Number(env[ENV_ATTACH_WAIT_MS]);
38
+ return Number.isInteger(value) && value > 0 ? value : DEFAULT_ATTACH_WAIT_MS;
39
+ }
40
+ /** The mode for this run: the first declared, unless `ABAI_MODE` names a declared one. */
41
+ export function selectMode(modes, env = process.env) {
42
+ const requested = env[ENV_MODE]?.trim();
43
+ const first = modes[0];
44
+ if (first === undefined)
45
+ throw new Error("the manifest declares no modes");
46
+ if (requested === undefined || requested === "")
47
+ return { mode: first, fallback: false };
48
+ if (modes.includes(requested))
49
+ return { mode: requested, fallback: false, requested };
50
+ return { mode: first, fallback: true, requested };
51
+ }
52
+ /** The harness for this run. An unknown value selects the real harness and is reported, never thrown: the program runs. */
53
+ export function selectHarness(env = process.env) {
54
+ const value = env[ENV_HARNESS]?.trim();
55
+ if (value === undefined || value === "")
56
+ return { selection: "real" };
57
+ if (value === "off" || value === "null" || value === "exercise")
58
+ return { selection: value };
59
+ return { selection: "real", error: `${ENV_HARNESS} must be unset, off, null or exercise (got ${value})` };
60
+ }
61
+ /** `~` at the start of a path means the home directory. */
62
+ export function expandHome(path, home = process.env.HOME ?? "") {
63
+ if (path === "~")
64
+ return home;
65
+ if (path.startsWith("~/"))
66
+ return `${home}${path.slice(1)}`;
67
+ return path;
68
+ }
69
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,4EAA4E;AAC5E,wEAAwE;AACxE,2EAA2E;AAC3E,mCAAmC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,CAAC,MAAM,QAAQ,GAAG,WAAW,CAAC;AACpC,MAAM,CAAC,MAAM,WAAW,GAAG,cAAc,CAAC;AAC1C;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AACtD,gIAAgI;AAChI,MAAM,CAAC,MAAM,WAAW,GAAG,cAAc,CAAC;AAC1C,+HAA+H;AAC/H,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAClD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C,qHAAqH;AACrH,MAAM,UAAU,UAAU,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAU;IACxE,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC;IAC1C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;IACnC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9B,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC;AAAA,CACtE;AAED,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAU;IAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,sBAAsB,CAAC;AAAA,CAC7E;AAYD,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAC,KAAsB,EAAE,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAiB;IACvG,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC3E,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACzF,IAAK,KAA2B,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,SAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACrH,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAAA,CAClD;AAED,2HAA2H;AAC3H,MAAM,UAAU,aAAa,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAmD;IACpH,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC;IACvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IACtE,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,8CAA8C,KAAK,GAAG,EAAE,CAAC;AAAA,CAC1G;AAED,2DAA2D;AAC3D,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAU;IAC/E,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,OAAO,IAAI,CAAC;AAAA,CACZ","sourcesContent":["// Mode and harness selection from the environment (abaigrammar section 4.4).\n// `ABAI_MODE` overrides the manifest's default mode; a value the manifest\n// does not declare falls back to the default and is counted. `ABAI_HARNESS`\n// is read only by check runs: unset means the real harness, `off` makes\n// every attach fail at once, `null` and `exercise` select the null harness\n// in its passive and active forms.\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Mode } from \"./manifest/manifest.ts\";\n\nexport const ENV_MODE = \"ABAI_MODE\";\nexport const ENV_HARNESS = \"ABAI_HARNESS\";\n/**\n * Set by a harness that launched this program (section 6.3): the socket its\n * endpoint must listen on, where the launcher is already waiting. Its\n * presence is also what makes the full lifecycle channel available (5.5).\n */\nexport const ENV_LAUNCH_SOCKET = \"ABAI_LAUNCH_SOCKET\";\n/** Where a sidecar endpoint puts its socket and descriptor; default `<ABAI_HOME or ~/.abai>/run`, the harness's own default. */\nexport const ENV_RUN_DIR = \"ABAI_RUN_DIR\";\n/** The harness binary the stub spawns at a touchpoint under sidecar; default: the program's `node_modules/.bin`, else PATH. */\nexport const ENV_HARNESS_BIN = \"ABAI_HARNESS_BIN\";\n/** How long a sidecar attach waits for the spawned harness to connect, in milliseconds. */\nexport const ENV_ATTACH_WAIT_MS = \"ABAI_ATTACH_WAIT_MS\";\nexport const DEFAULT_ATTACH_WAIT_MS = 30_000;\n\n/** The run directory for this environment. With no home at all, a private directory under the machine's temp dir. */\nexport function runDirFrom(env: NodeJS.ProcessEnv = process.env): string {\n\tconst explicit = env[ENV_RUN_DIR]?.trim();\n\tif (explicit) return explicit;\n\tconst home = env.ABAI_HOME?.trim();\n\tif (home) return join(home, \"run\");\n\tconst user = env.HOME?.trim();\n\treturn user ? join(user, \".abai\", \"run\") : join(tmpdir(), \"abai-run\");\n}\n\n/** The attach wait for this environment; an unusable value means the default. */\nexport function attachWaitMsFrom(env: NodeJS.ProcessEnv = process.env): number {\n\tconst value = Number(env[ENV_ATTACH_WAIT_MS]);\n\treturn Number.isInteger(value) && value > 0 ? value : DEFAULT_ATTACH_WAIT_MS;\n}\n\nexport type HarnessSelection = \"real\" | \"off\" | \"null\" | \"exercise\";\n\nexport interface ModeSelection {\n\tmode: Mode;\n\t/** The requested mode was not declared; the default applies and is counted. */\n\tfallback: boolean;\n\t/** What `ABAI_MODE` asked for, when set. */\n\trequested?: string;\n}\n\n/** The mode for this run: the first declared, unless `ABAI_MODE` names a declared one. */\nexport function selectMode(modes: readonly Mode[], env: NodeJS.ProcessEnv = process.env): ModeSelection {\n\tconst requested = env[ENV_MODE]?.trim();\n\tconst first = modes[0];\n\tif (first === undefined) throw new Error(\"the manifest declares no modes\");\n\tif (requested === undefined || requested === \"\") return { mode: first, fallback: false };\n\tif ((modes as readonly string[]).includes(requested)) return { mode: requested as Mode, fallback: false, requested };\n\treturn { mode: first, fallback: true, requested };\n}\n\n/** The harness for this run. An unknown value selects the real harness and is reported, never thrown: the program runs. */\nexport function selectHarness(env: NodeJS.ProcessEnv = process.env): { selection: HarnessSelection; error?: string } {\n\tconst value = env[ENV_HARNESS]?.trim();\n\tif (value === undefined || value === \"\") return { selection: \"real\" };\n\tif (value === \"off\" || value === \"null\" || value === \"exercise\") return { selection: value };\n\treturn { selection: \"real\", error: `${ENV_HARNESS} must be unset, off, null or exercise (got ${value})` };\n}\n\n/** `~` at the start of a path means the home directory. */\nexport function expandHome(path: string, home = process.env.HOME ?? \"\"): string {\n\tif (path === \"~\") return home;\n\tif (path.startsWith(\"~/\")) return `${home}${path.slice(1)}`;\n\treturn path;\n}\n"]}