@tetsuo-ai/agenc 0.2.0 → 0.2.1

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,246 @@
1
+ import { spawn } from "node:child_process";
2
+ import { readFile } from "node:fs/promises";
3
+ import { createRequire } from "node:module";
4
+ import { homedir } from "node:os";
5
+ import { dirname, join, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const DEFAULT_READY_TIMEOUT_MS = 2000;
9
+ const DEFAULT_POLL_MS = 25;
10
+ const READY_TIMEOUT_ENV = "AGENC_DAEMON_READY_TIMEOUT_MS";
11
+ const AUTOSTART_ENV = "AGENC_DAEMON_AUTOSTART";
12
+
13
+ const requireFromLauncher = createRequire(import.meta.url);
14
+
15
+ export function shouldAutostartDaemon(env = process.env) {
16
+ const raw = env[AUTOSTART_ENV]?.trim().toLowerCase();
17
+ if (raw === undefined || raw.length === 0) return true;
18
+ return raw !== "0" && raw !== "false" && raw !== "off";
19
+ }
20
+
21
+ export function resolveReadyTimeoutMs(env = process.env) {
22
+ const raw = env[READY_TIMEOUT_ENV]?.trim();
23
+ if (raw === undefined || raw.length === 0) return DEFAULT_READY_TIMEOUT_MS;
24
+ const parsed = Number.parseInt(raw, 10);
25
+ if (!Number.isInteger(parsed) || String(parsed) !== raw || parsed <= 0) {
26
+ throw new Error(`${READY_TIMEOUT_ENV} must be a positive integer`);
27
+ }
28
+ return parsed;
29
+ }
30
+
31
+ export function resolveAgenCHome(env = process.env, userHome = homedir()) {
32
+ const configured = env.AGENC_HOME?.trim();
33
+ return configured && configured.length > 0
34
+ ? configured
35
+ : join(userHome, ".agenc");
36
+ }
37
+
38
+ export function resolveDaemonPidPath(env = process.env, userHome = homedir()) {
39
+ return join(resolveAgenCHome(env, userHome), "daemon.pid");
40
+ }
41
+
42
+ export function resolveDaemonCookiePath(env = process.env, userHome = homedir()) {
43
+ return join(resolveAgenCHome(env, userHome), "daemon.cookie");
44
+ }
45
+
46
+ export async function readDaemonPid(pidPath, readText = readFile) {
47
+ try {
48
+ const raw = (await readText(pidPath, "utf8")).trim();
49
+ if (!/^\d+$/.test(raw)) return null;
50
+ const pid = Number.parseInt(raw, 10);
51
+ return pid > 0 ? pid : null;
52
+ } catch (error) {
53
+ if (error?.code === "ENOENT") return null;
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ export function isPidRunning(pid, signalPid = process.kill) {
59
+ try {
60
+ signalPid(pid, 0);
61
+ return true;
62
+ } catch (error) {
63
+ return error?.code === "EPERM";
64
+ }
65
+ }
66
+
67
+ export function isDaemonCommand(argv) {
68
+ return argv[0] === "daemon";
69
+ }
70
+
71
+ // Dev path: the `file:`-linked @tetsuo-ai/runtime resolves locally. Returns
72
+ // null in a published install where runtime is NOT an npm dependency (it's the
73
+ // downloaded GitHub-Releases artifact instead).
74
+ export function resolveRuntimeBin(requireFn = requireFromLauncher) {
75
+ try {
76
+ const runtimeEntry = requireFn.resolve("@tetsuo-ai/runtime");
77
+ return resolve(dirname(runtimeEntry), "../bin/agenc");
78
+ } catch (error) {
79
+ if (
80
+ error?.code === "MODULE_NOT_FOUND" ||
81
+ error?.code === "ERR_MODULE_NOT_FOUND"
82
+ ) {
83
+ return null;
84
+ }
85
+ throw error;
86
+ }
87
+ }
88
+
89
+ // Resolve the runtime entry for either mode: prefer the dev file:-link, else
90
+ // ensure (download + verify + extract) the published per-platform runtime.
91
+ export async function resolveRuntimeBinAsync({
92
+ requireFn = requireFromLauncher,
93
+ ensureFn,
94
+ } = {}) {
95
+ const dev = resolveRuntimeBin(requireFn);
96
+ if (dev !== null) return dev;
97
+ const ensureRuntime =
98
+ ensureFn ?? (await import("../lib/runtime-manager.mjs")).ensureRuntime;
99
+ return ensureRuntime();
100
+ }
101
+
102
+ export async function spawnNodeScript(
103
+ scriptPath,
104
+ args,
105
+ {
106
+ env = process.env,
107
+ cwd = process.cwd(),
108
+ stdio = "inherit",
109
+ spawnFn = spawn,
110
+ } = {},
111
+ ) {
112
+ return new Promise((resolveExit, reject) => {
113
+ const child = spawnFn(process.execPath, [scriptPath, ...args], {
114
+ cwd,
115
+ env,
116
+ stdio,
117
+ });
118
+ child.once("error", reject);
119
+ child.once("exit", (code, signal) => {
120
+ if (signal !== null) {
121
+ reject(new Error(`agenc runtime exited from signal ${signal}`));
122
+ return;
123
+ }
124
+ resolveExit(code ?? 1);
125
+ });
126
+ });
127
+ }
128
+
129
+ export async function spawnDaemon(runtimeBin, options = {}) {
130
+ const exitCode = await spawnNodeScript(runtimeBin, ["daemon", "start"], {
131
+ ...options,
132
+ stdio: ["ignore", "ignore", "inherit"],
133
+ });
134
+ if (exitCode !== 0) {
135
+ throw new Error(`AgenC daemon start failed with exit code ${exitCode}`);
136
+ }
137
+ }
138
+
139
+ export async function isDaemonReady(
140
+ {
141
+ env = process.env,
142
+ userHome = homedir(),
143
+ readText = readFile,
144
+ signalPid = process.kill,
145
+ } = {},
146
+ ) {
147
+ const pidPath = resolveDaemonPidPath(env, userHome);
148
+ const cookiePath = resolveDaemonCookiePath(env, userHome);
149
+ const pid = await readDaemonPid(pidPath, readText);
150
+ if (pid === null || !isPidRunning(pid, signalPid)) return false;
151
+ try {
152
+ return (await readText(cookiePath, "utf8")).trim().length > 0;
153
+ } catch (error) {
154
+ if (error?.code === "ENOENT") return false;
155
+ throw error;
156
+ }
157
+ }
158
+
159
+ export async function waitForDaemonReady(options = {}) {
160
+ const timeoutMs = options.timeoutMs ?? resolveReadyTimeoutMs(options.env);
161
+ const pollMs = options.pollMs ?? DEFAULT_POLL_MS;
162
+ const startedAt = Date.now();
163
+ const sleep = options.sleep ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
164
+
165
+ while (Date.now() - startedAt < timeoutMs) {
166
+ if (await isDaemonReady(options)) return true;
167
+ await sleep(pollMs);
168
+ }
169
+ return isDaemonReady(options);
170
+ }
171
+
172
+ export async function ensureDaemonForLaunch({
173
+ argv = process.argv.slice(2),
174
+ env = process.env,
175
+ cwd = process.cwd(),
176
+ runtimeBin = resolveRuntimeBin(),
177
+ userHome = homedir(),
178
+ readText = readFile,
179
+ signalPid = process.kill,
180
+ spawnDaemonFn = spawnDaemon,
181
+ waitForReadyFn = waitForDaemonReady,
182
+ } = {}) {
183
+ if (isDaemonCommand(argv)) return { status: "skipped-daemon-command" };
184
+ if (!shouldAutostartDaemon(env)) return { status: "disabled" };
185
+
186
+ if (
187
+ await waitForReadyFn({
188
+ env,
189
+ userHome,
190
+ readText,
191
+ signalPid,
192
+ timeoutMs: 1,
193
+ pollMs: 1,
194
+ sleep: async () => {},
195
+ })
196
+ ) {
197
+ return { status: "already-running" };
198
+ }
199
+
200
+ await spawnDaemonFn(runtimeBin, { env, cwd });
201
+ const ready = await waitForReadyFn({ env, userHome, readText, signalPid });
202
+ if (!ready) {
203
+ throw new Error("AgenC daemon did not become ready before timeout");
204
+ }
205
+ return { status: "started" };
206
+ }
207
+
208
+ export async function main(
209
+ argv = process.argv.slice(2),
210
+ {
211
+ env = process.env,
212
+ cwd = process.cwd(),
213
+ runtimeBin,
214
+ userHome = homedir(),
215
+ } = {},
216
+ ) {
217
+ // Resolve (and, in a published install, download + verify) the runtime before
218
+ // anything tries to spawn it. Sync default is avoided: it returns null when
219
+ // runtime isn't an npm dep, which is the normal published case.
220
+ let resolvedBin = runtimeBin;
221
+ try {
222
+ resolvedBin ??= await resolveRuntimeBinAsync();
223
+ } catch (error) {
224
+ process.stderr.write(
225
+ `agenc: could not obtain runtime: ${
226
+ error instanceof Error ? error.message : String(error)
227
+ }\n`,
228
+ );
229
+ return 1;
230
+ }
231
+ try {
232
+ await ensureDaemonForLaunch({ argv, env, cwd, runtimeBin: resolvedBin, userHome });
233
+ } catch (error) {
234
+ process.stderr.write(
235
+ `agenc: daemon autostart failed: ${
236
+ error instanceof Error ? error.message : String(error)
237
+ }\n`,
238
+ );
239
+ return 1;
240
+ }
241
+ return spawnNodeScript(resolvedBin, argv, { env, cwd, stdio: "inherit" });
242
+ }
243
+
244
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
245
+ process.exitCode = await main();
246
+ }
package/README.md DELETED
@@ -1,144 +0,0 @@
1
- # agenc
2
-
3
- Public CLI and launcher for the AgenC framework.
4
-
5
- This package owns the user-facing global install surface:
6
-
7
- ```bash
8
- npm install -g @tetsuo-ai/agenc
9
- agenc onboard
10
- agenc start
11
- agenc
12
- agenc ui
13
- ```
14
-
15
- `agenc onboard` is the canonical first-run path. It opens an interactive
16
- terminal onboarding flow that:
17
-
18
- - validates an xAI API key
19
- - lets the operator shape the agent name, mission, role, soul, and tool posture
20
- - writes the canonical config at `~/.agenc/config.json`
21
- - generates the curated workspace markdown profile under `~/.agenc/workspace/`
22
-
23
- It does not expose the runtime source tree directly. Instead, it installs and
24
- launches the matching AgenC runtime artifact for the current supported
25
- platform.
26
-
27
- The supported npm install identity is `@tetsuo-ai/agenc`. The unscoped
28
- `agenc` package name is not part of the supported public release contract.
29
-
30
- Current public support is intentionally narrow:
31
-
32
- - Linux `x64`
33
- - Node `>=18.0.0`
34
-
35
- Current validated release-gate lanes:
36
-
37
- - Node `18` minimum floor
38
- - Node `20` mainline lane
39
-
40
- Production release channel:
41
-
42
- - npm package: `@tetsuo-ai/agenc`
43
- - runtime artifact host: GitHub Releases on `tetsuo-ai/agenc-core`
44
- - trust: embedded signed manifest + embedded public key + embedded trust policy
45
-
46
- After the matching runtime artifact is installed, `agenc` can continue to run
47
- offline against the local install. The npm package name is scoped, but the CLI
48
- binary remains `agenc`.
49
-
50
- `agenc` exposes two primary local operator surfaces against the same daemon:
51
-
52
- - `agenc` attaches the terminal operator console
53
- - `agenc ui` opens or prints the local dashboard URL on `/ui/`
54
-
55
- For automation or remote shells, use:
56
-
57
- ```bash
58
- agenc ui --no-open
59
- ```
60
-
61
- ## First-party connector lifecycle
62
-
63
- The first V1 connector is Telegram. It is managed through the same daemon as the
64
- CLI and dashboard; there is no separate connector service to start.
65
-
66
- ```bash
67
- agenc connector list
68
- agenc connector status telegram
69
- agenc connector add telegram --bot-token-env TELEGRAM_BOT_TOKEN
70
- agenc connector remove telegram
71
- ```
72
-
73
- For non-interactive shells or secret managers, you can pipe the bot token on
74
- stdin instead:
75
-
76
- ```bash
77
- printf '%s' "$TELEGRAM_BOT_TOKEN" | agenc connector add telegram --bot-token-stdin
78
- ```
79
-
80
- Connector health and pending-restart state are exposed through both:
81
-
82
- - `agenc connector status telegram`
83
- - `agenc ui` on the dashboard status view
84
-
85
- ## Wrapper-local runtime management
86
-
87
- ```bash
88
- agenc runtime where
89
- agenc runtime install
90
- agenc runtime update
91
- agenc runtime uninstall
92
- ```
93
-
94
- ## First-use devnet marketplace rehearsal
95
-
96
- For public release-path docs and operator rehearsal, use the top-level `agenc`
97
- commands. `agenc-runtime` remains available as a compatibility alias after the
98
- runtime is installed, but it is not the primary public wrapper path.
99
-
100
- Supported release-path boundary:
101
-
102
- - Linux `x64`
103
- - Node `>=18.0.0`
104
-
105
- Manual prerequisites that still live outside the wrapper:
106
-
107
- - Solana CLI available on `PATH`
108
- - funded devnet keypair at `SOLANA_KEYPAIR_PATH` or `~/.config/solana/id.json`
109
- - `--rpc` or `AGENC_RUNTIME_RPC_URL`
110
- - optional `--program-id` or `AGENC_RUNTIME_PROGRAM_ID` when testing a non-default deployment
111
- - a second funded signer plus a second agent registration if you want a separate worker identity for `claim` and `complete`
112
-
113
- Minimal creator flow:
114
-
115
- ```bash
116
- export AGENC_RUNTIME_RPC_URL=https://api.devnet.solana.com
117
- agenc onboard
118
- agenc runtime install
119
- agenc start
120
- agenc agent register --rpc "$AGENC_RUNTIME_RPC_URL"
121
- agenc market tasks create --description "public task" --reward 50000000 --rpc "$AGENC_RUNTIME_RPC_URL"
122
- agenc market tasks list --rpc "$AGENC_RUNTIME_RPC_URL"
123
- agenc market tui --rpc "$AGENC_RUNTIME_RPC_URL"
124
- ```
125
-
126
- Claim and complete from a worker signer:
127
-
128
- ```bash
129
- export SOLANA_KEYPAIR_PATH=/path/to/worker.json
130
- agenc agent register --rpc "$AGENC_RUNTIME_RPC_URL"
131
- agenc market tasks claim <taskPda> --rpc "$AGENC_RUNTIME_RPC_URL"
132
- agenc market tasks complete <taskPda> --result-data "completed via public wrapper" --rpc "$AGENC_RUNTIME_RPC_URL"
133
- ```
134
-
135
- Notes:
136
-
137
- - `tasks claim|complete|dispute` require the signer wallet to already control a registered agent.
138
- - `disputes resolve` is not part of the public first-use rehearsal; it requires the protocol authority wallet.
139
-
140
- ## Development
141
-
142
- The embedded runtime manifest in `generated/` is produced by the `agenc-core`
143
- artifact preparation scripts. Local smoke tests use the same packaged manifest
144
- flow as publish/release preparation.
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import { runAgencRuntimeWrapper } from "../lib/cli.js";
3
-
4
- const exitCode = await runAgencRuntimeWrapper();
5
- process.exitCode = exitCode;
package/bin/agenc.js DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import { runAgencWrapper } from "../lib/cli.js";
3
-
4
- const exitCode = await runAgencWrapper();
5
- process.exitCode = exitCode;
@@ -1 +0,0 @@
1
- nyIC/iBXuyr5jy7GThy5GsYjD9GgmmnSnbD54CpupYwr97qdAhmRuxrA0cqxOegFwN1pAu6Lu+qOYHyaePBEAw==
@@ -1,3 +0,0 @@
1
- -----BEGIN PUBLIC KEY-----
2
- MCowBQYDK2VwAyEAIMA9t7a75CBcuD4UTUkwjxThcPLZZO53Qg/zfpiwm4c=
3
- -----END PUBLIC KEY-----
@@ -1,9 +0,0 @@
1
- {
2
- "wrapperVersion": "0.2.0",
3
- "keyId": "agenc-v0.2.0",
4
- "releaseChannel": "github-releases",
5
- "releaseRepository": "tetsuo-ai/agenc-core",
6
- "releaseTag": "agenc-v0.2.0",
7
- "revokedManifestDigests": [],
8
- "revokedRuntimeVersions": []
9
- }
package/lib/cli.js DELETED
@@ -1,261 +0,0 @@
1
- import process from "node:process";
2
- import {
3
- describeRuntimeInstall,
4
- ensureRuntimeFromSource,
5
- ensureRuntimeInstalled,
6
- RuntimeInstallError,
7
- spawnInstalledRuntimeBin,
8
- spawnInstalledRuntimeBinFromSource,
9
- uninstallRuntime,
10
- } from "./runtime-manager.js";
11
-
12
- function writeLine(stream, value) {
13
- stream.write(`${value}\n`);
14
- }
15
-
16
- function buildAgencHelp() {
17
- return [
18
- "agenc [runtime-command] [options]",
19
- "agenc runtime <where|install|update|uninstall>",
20
- "",
21
- "Examples:",
22
- " agenc onboard",
23
- " agenc ui",
24
- " agenc start",
25
- " agenc status",
26
- " agenc logs",
27
- " agenc runtime where",
28
- "",
29
- "Marketplace / devnet examples:",
30
- " agenc agent register --rpc https://api.devnet.solana.com",
31
- " agenc market tasks create --description 'public task' --reward 50000000 --rpc https://api.devnet.solana.com",
32
- " agenc market tui",
33
- "",
34
- "Supported public wrapper tuple:",
35
- " Linux x64, Node >=18.0.0",
36
- "",
37
- "Compatibility alias:",
38
- " agenc-runtime remains available after install, but public docs should use agenc.",
39
- "",
40
- "Dev / from-source:",
41
- " agenc start --from-source",
42
- " agenc start --from-source --source-dir /path/to/agenc-core/runtime",
43
- " Builds runtime/dist locally and points ~/.agenc/runtime/current at it.",
44
- ].join("\n");
45
- }
46
-
47
- function buildAgencRuntimeHelp() {
48
- return [
49
- "agenc-runtime [runtime-command] [options]",
50
- "",
51
- "Compatibility alias for the installed AgenC runtime CLI.",
52
- "",
53
- "Dev flags:",
54
- " --from-source build the local agenc-core/runtime tree",
55
- " and run the daemon from there",
56
- " --source-dir <path> explicit runtime/ source path",
57
- ].join("\n");
58
- }
59
-
60
- async function runRuntimeAdmin(argv, io, deps, runtimeOptions) {
61
- const command = argv[0];
62
- const force = argv.includes("--force");
63
- if (!command || command === "help" || command === "--help" || command === "-h") {
64
- writeLine(
65
- io.stdout,
66
- "agenc runtime <where|install|update|uninstall> [--force]",
67
- );
68
- return 0;
69
- }
70
-
71
- if (command === "where") {
72
- const description = await deps.describeRuntimeInstall(runtimeOptions);
73
- writeLine(
74
- io.stdout,
75
- JSON.stringify(
76
- {
77
- runtimeHome: description.runtimeHome,
78
- installed: description.installed,
79
- releaseDir: description.releaseDir,
80
- currentDir: description.currentDir,
81
- manifestSource: description.manifestSource,
82
- manifestDigest: description.manifestDigest,
83
- trustPolicy: description.trustPolicy
84
- ? {
85
- wrapperVersion: description.trustPolicy.wrapperVersion,
86
- keyId: description.trustPolicy.keyId,
87
- releaseChannel: description.trustPolicy.releaseChannel ?? null,
88
- releaseRepository:
89
- description.trustPolicy.releaseRepository ?? null,
90
- releaseTag: description.trustPolicy.releaseTag ?? null,
91
- revokedManifestDigests:
92
- description.trustPolicy.revokedManifestDigests,
93
- revokedRuntimeVersions:
94
- description.trustPolicy.revokedRuntimeVersions,
95
- }
96
- : null,
97
- selectedArtifact: description.selectedArtifact
98
- ? {
99
- runtimeVersion: description.selectedArtifact.runtimeVersion,
100
- platform: description.selectedArtifact.platform,
101
- arch: description.selectedArtifact.arch,
102
- nodeRange: description.selectedArtifact.nodeRange,
103
- }
104
- : null,
105
- },
106
- null,
107
- 2,
108
- ),
109
- );
110
- return 0;
111
- }
112
-
113
- if (command === "install" || command === "update") {
114
- const installation = await deps.ensureRuntimeInstalled({
115
- ...runtimeOptions,
116
- force: command === "update",
117
- });
118
- writeLine(
119
- io.stdout,
120
- `Installed AgenC runtime ${installation.selectedArtifact.runtimeVersion} at ${installation.releaseDir}`,
121
- );
122
- return 0;
123
- }
124
-
125
- if (command === "uninstall") {
126
- const result = await deps.uninstallRuntime({ ...runtimeOptions, force });
127
- writeLine(
128
- io.stdout,
129
- result.removed
130
- ? `Removed AgenC runtime at ${result.releaseDir}\nPreserved: ${result.preservedPaths.join(", ")}`
131
- : "No installed AgenC runtime found for the current platform",
132
- );
133
- return 0;
134
- }
135
-
136
- writeLine(io.stderr, `Unknown agenc runtime command: ${command}`);
137
- return 2;
138
- }
139
-
140
- const DEFAULT_DEPS = {
141
- ensureRuntimeInstalled,
142
- ensureRuntimeFromSource,
143
- describeRuntimeInstall,
144
- uninstallRuntime,
145
- spawnInstalledRuntimeBin,
146
- spawnInstalledRuntimeBinFromSource,
147
- };
148
-
149
- /**
150
- * Cut 6.1: detect and strip the `--from-source` flag (and the optional
151
- * `--source-dir <path>`) from the wrapper argv. Returns the remaining argv
152
- * plus the parsed flag values so the rest of the dispatcher can continue
153
- * to operate on a clean argument list.
154
- */
155
- function extractFromSourceFlags(argv) {
156
- const remaining = [];
157
- let fromSource = false;
158
- let sourceDir;
159
- for (let i = 0; i < argv.length; i++) {
160
- const arg = argv[i];
161
- if (arg === "--from-source") {
162
- fromSource = true;
163
- continue;
164
- }
165
- if (arg === "--source-dir" && i + 1 < argv.length) {
166
- sourceDir = argv[++i];
167
- fromSource = true;
168
- continue;
169
- }
170
- if (typeof arg === "string" && arg.startsWith("--source-dir=")) {
171
- sourceDir = arg.slice("--source-dir=".length);
172
- fromSource = true;
173
- continue;
174
- }
175
- remaining.push(arg);
176
- }
177
- return { argv: remaining, fromSource, sourceDir };
178
- }
179
-
180
- function formatRuntimeInstallError(error) {
181
- if (error instanceof RuntimeInstallError) {
182
- return error.message;
183
- }
184
- return error instanceof Error ? error.message : String(error);
185
- }
186
-
187
- export async function runAgencWrapper(options = {}, deps = DEFAULT_DEPS) {
188
- const rawArgv = options.argv ?? process.argv.slice(2);
189
- const { argv, fromSource, sourceDir } = extractFromSourceFlags(rawArgv);
190
- const stdout = options.stdout ?? process.stdout;
191
- const stderr = options.stderr ?? process.stderr;
192
- const runtimeOptions = {
193
- env: options.env ?? process.env,
194
- cwd: options.cwd ?? process.cwd(),
195
- homeDir: options.homeDir,
196
- packageRoot: options.packageRoot,
197
- sourceDir,
198
- };
199
-
200
- try {
201
- if (argv[0] === "runtime") {
202
- return await runRuntimeAdmin(
203
- argv.slice(1),
204
- { stdout, stderr },
205
- deps,
206
- runtimeOptions,
207
- );
208
- }
209
- if (argv[0] === "--help" || argv[0] === "-h" || argv[0] === "help") {
210
- writeLine(stdout, buildAgencHelp());
211
- return 0;
212
- }
213
- if (fromSource) {
214
- return await deps.spawnInstalledRuntimeBinFromSource(
215
- "agenc",
216
- argv,
217
- runtimeOptions,
218
- );
219
- }
220
- return await deps.spawnInstalledRuntimeBin("agenc", argv, runtimeOptions);
221
- } catch (error) {
222
- writeLine(stderr, formatRuntimeInstallError(error));
223
- return 1;
224
- }
225
- }
226
-
227
- export async function runAgencRuntimeWrapper(options = {}, deps = DEFAULT_DEPS) {
228
- const rawArgv = options.argv ?? process.argv.slice(2);
229
- const { argv, fromSource, sourceDir } = extractFromSourceFlags(rawArgv);
230
- const stdout = options.stdout ?? process.stdout;
231
- const stderr = options.stderr ?? process.stderr;
232
- const runtimeOptions = {
233
- env: options.env ?? process.env,
234
- cwd: options.cwd ?? process.cwd(),
235
- homeDir: options.homeDir,
236
- packageRoot: options.packageRoot,
237
- sourceDir,
238
- };
239
-
240
- try {
241
- if (argv[0] === "--help" || argv[0] === "-h" || argv[0] === "help") {
242
- writeLine(stdout, buildAgencRuntimeHelp());
243
- return 0;
244
- }
245
- if (fromSource) {
246
- return await deps.spawnInstalledRuntimeBinFromSource(
247
- "agenc-runtime",
248
- argv,
249
- runtimeOptions,
250
- );
251
- }
252
- return await deps.spawnInstalledRuntimeBin(
253
- "agenc-runtime",
254
- argv,
255
- runtimeOptions,
256
- );
257
- } catch (error) {
258
- writeLine(stderr, formatRuntimeInstallError(error));
259
- return 1;
260
- }
261
- }