@voicethere/agent 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -23,30 +23,25 @@ npm install
23
23
  npm run build
24
24
  ```
25
25
 
26
- **Voice E2E:** deploy to the VoiceThere platform or run against your organization's internal agent runner. With a local runner checkout, point it at your bundle:
27
-
28
- ```bash
29
- AGENT_BUNDLE_PATH=/path/to/dist/agent.js npm run start
30
- ```
31
-
32
- Open the runner URL in a browser, connect, and speak.
33
-
34
26
  ## Verify locally (sandbox, no WebRTC)
35
27
 
36
- Before deploying to VoiceThere, confirm your bundle loads and responds under the **same Node sandbox** the runner uses:
28
+ Before deploying to VoiceThere, build your bundle and run sandbox checks (same Node `--permission` flags as production):
37
29
 
38
30
  ```bash
39
- npm run verify:local
31
+ npx @voicethere/agent verify
40
32
  ```
41
33
 
42
- | Script | When to use |
43
- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
44
- | `npm run verify:local` | **Default** — `npm run build`, then fork `dist/agent.js` in the sandbox and assert a `speak` reply to `user_speech_final` |
45
- | `npm run verify:local:only` | Re-run smoke after build; optional `AGENT_BUNDLE_PATH=./dist/agent.js` or `--bundle <path>` |
34
+ This runs a short checklist: Node version, bundle build, sandbox load, IPC `session_start`, `user_speech_final` → `speak`, and no `agent_error`. Failures print which check failed and why.
35
+
36
+ | Command | When to use |
37
+ | ------- | ----------- |
38
+ | `npx @voicethere/agent verify` | **Default** — build `agent.ts` → `dist/agent.js`, then run all checks |
39
+ | `npx @voicethere/agent verify --no-build` | Re-run checks on an existing bundle |
40
+ | `npx @voicethere/agent verify --no-build --bundle ./dist/agent.js` | Verify a specific bundle path |
46
41
 
47
- This checks bundle load, IPC, and Node permission flags. It does **not** replace a voice roundtrip — use the VoiceThere agent runner (platform or internal deployment) for mic/WebRTC E2E.
42
+ Optional flags: `--entry` / `-e`, `--outfile` / `-o` (same as `build`).
48
43
 
49
- Harness: [`scripts/sandbox/`](./scripts/sandbox/) (aligned with the agent runner child launcher).
44
+ This does **not** replace a voice roundtrip with mic/WebRTC — deploy to the VoiceThere platform for full E2E.
50
45
 
51
46
  ## API
52
47
 
@@ -101,14 +96,15 @@ Copy [`templates/agent.ts`](./templates/agent.ts) as a starting point — exhaus
101
96
 
102
97
  ## Building your agent bundle
103
98
 
104
- **Recommended:** single ESM bundle (esbuild or similar):
99
+ **Recommended:** bundle with the package CLI (same esbuild settings VoiceThere uses in production):
105
100
 
106
101
  ```bash
107
- npm install @voicethere/agent esbuild
108
- npx esbuild agent.ts --bundle --platform=node --format=esm --outfile=dist/agent.js
102
+ npm install @voicethere/agent
103
+ npx @voicethere/agent build
104
+ # or: npx @voicethere/agent build --entry src/agent.ts --outfile dist/agent.js
109
105
  ```
110
106
 
111
- Upload `dist/agent.js` (or point `AGENT_BUNDLE_PATH` at it locally). Inlining dependencies avoids runtime `node_modules` resolution inside the sandbox.
107
+ Defaults: entry `agent.ts`, output `dist/agent.js`. Upload the bundle (or point `AGENT_BUNDLE_PATH` at it locally). Inlining dependencies avoids runtime `node_modules` resolution inside the sandbox.
112
108
 
113
109
  ## Sandbox and security model
114
110
 
@@ -213,9 +209,10 @@ Prefer **one esbuild bundle** so production behavior matches `npm run verify:loc
213
209
 
214
210
  **Pre-publish checklist**
215
211
 
216
- 1. `npm run build` — produce `dist/agent.js`
217
- 2. `npm run verify:local` sandbox + IPC smoke (same flags as production child)
218
- 3. Optional: voice E2E with the VoiceThere agent runner (platform or internal deployment)
212
+ 1. `npx @voicethere/agent verify` — build your bundle and run sandbox checks
213
+ 2. Deploy the bundle to VoiceThere (platform upload or CLI when available)
214
+
215
+ For iterative work: `npx @voicethere/agent build` then `npx @voicethere/agent verify --no-build`.
219
216
 
220
217
  ## Build outputs
221
218
 
@@ -227,11 +224,19 @@ Prefer **one esbuild bundle** so production behavior matches `npm run verify:loc
227
224
  ## Scripts
228
225
 
229
226
  ```bash
230
- npm run build # library + example bundle
231
- npm run verify:local # sandbox smoke (build + fork bundle)
227
+ npm run build # compile SDK + example bundle (repo dev)
228
+ npm run build:lib # compile SDK only (tsc dist/)
229
+ npm run verify:local # repo dev: build example + sandbox verify
232
230
  npm run test:ci # typecheck + vitest
233
231
  ```
234
232
 
233
+ Customer project:
234
+
235
+ ```bash
236
+ npx @voicethere/agent build # bundle agent.ts → dist/agent.js
237
+ npx @voicethere/agent verify # build + sandbox checks
238
+ ```
239
+
235
240
  ## Release
236
241
 
237
242
  See [`scripts/RELEASE.md`](./scripts/RELEASE.md) — tag `release/X.Y.Z` triggers npm publish (same workflow pattern as [`node-webrtc-rust`](https://github.com/akirilyuk/node-webrtc-rust)).
@@ -0,0 +1,14 @@
1
+ import * as esbuild from "esbuild";
2
+ export interface BuildAgentBundleOptions {
3
+ /** Agent source entry (TypeScript or JavaScript). */
4
+ entry: string;
5
+ /** Output bundle path (typically `dist/agent.js`). */
6
+ outfile: string;
7
+ /** Working directory for relative paths. Defaults to `process.cwd()`. */
8
+ cwd?: string;
9
+ }
10
+ /**
11
+ * Bundle customer agent source into a single ESM file for the sandboxed child.
12
+ */
13
+ export declare function buildAgentBundle(options: BuildAgentBundleOptions): Promise<esbuild.BuildResult>;
14
+ //# sourceMappingURL=build-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-bundle.d.ts","sourceRoot":"","sources":["../src/build-bundle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,MAAM,WAAW,uBAAuB;IACtC,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAoB9B"}
@@ -0,0 +1,25 @@
1
+ import { existsSync, mkdirSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import * as esbuild from "esbuild";
4
+ /**
5
+ * Bundle customer agent source into a single ESM file for the sandboxed child.
6
+ */
7
+ export async function buildAgentBundle(options) {
8
+ const cwd = options.cwd ?? process.cwd();
9
+ const entry = resolve(cwd, options.entry);
10
+ const outfile = resolve(cwd, options.outfile);
11
+ if (!existsSync(entry)) {
12
+ throw new Error(`Entry not found: ${entry}`);
13
+ }
14
+ mkdirSync(dirname(outfile), { recursive: true });
15
+ return esbuild.build({
16
+ entryPoints: [entry],
17
+ bundle: true,
18
+ platform: "node",
19
+ format: "esm",
20
+ outfile,
21
+ target: "node22",
22
+ logLevel: "warning",
23
+ });
24
+ }
25
+ //# sourceMappingURL=build-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-bundle.js","sourceRoot":"","sources":["../src/build-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAWnC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAgC;IAEhC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjD,OAAO,OAAO,CAAC,KAAK,CAAC;QACnB,WAAW,EAAE,CAAC,KAAK,CAAC;QACpB,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,KAAK;QACb,OAAO;QACP,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;AACL,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Customer-facing CLI — bundle and verify voice agents for VoiceThere.
4
+ *
5
+ * npx @voicethere/agent build
6
+ * npx @voicethere/agent verify
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
package/dist/cli.js ADDED
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Customer-facing CLI — bundle and verify voice agents for VoiceThere.
4
+ *
5
+ * npx @voicethere/agent build
6
+ * npx @voicethere/agent verify
7
+ */
8
+ import { buildAgentBundle } from "./build-bundle.js";
9
+ import { DEFAULT_VERIFY_BUNDLE, DEFAULT_VERIFY_ENTRY, } from "./verify/lib.js";
10
+ import { formatVerifyFailure, runAgentVerify, } from "./verify/run-verify.js";
11
+ const DEFAULT_ENTRY = DEFAULT_VERIFY_ENTRY;
12
+ const DEFAULT_OUTFILE = DEFAULT_VERIFY_BUNDLE;
13
+ function printHelp() {
14
+ process.stdout.write(`@voicethere/agent — bundle and verify your voice agent
15
+
16
+ Usage:
17
+ npx @voicethere/agent
18
+ npx @voicethere/agent build [options]
19
+ npx @voicethere/agent verify [options]
20
+
21
+ Commands:
22
+ build Bundle agent source to a single ESM file
23
+ verify Build (optional) and run sandbox checks on the bundle
24
+
25
+ Build options:
26
+ --entry, -e <path> Agent entry file (default: ${DEFAULT_ENTRY})
27
+ --outfile, -o <path> Output bundle (default: ${DEFAULT_OUTFILE})
28
+
29
+ Verify options:
30
+ --entry, -e <path> Entry for build step (default: ${DEFAULT_ENTRY})
31
+ --outfile, -o <path> Bundle output path (default: ${DEFAULT_OUTFILE})
32
+ --bundle, -b <path> Bundle to verify (default: ${DEFAULT_OUTFILE})
33
+ --no-build Skip build; verify an existing bundle only
34
+ --help, -h Show this help
35
+
36
+ Examples:
37
+ npm install @voicethere/agent
38
+ npx @voicethere/agent build --entry src/agent.ts --outfile dist/agent.js
39
+ npx @voicethere/agent verify
40
+ npx @voicethere/agent verify --no-build --bundle dist/agent.js
41
+ `);
42
+ }
43
+ function parseBuildArgs(argv) {
44
+ let entry = DEFAULT_ENTRY;
45
+ let outfile = DEFAULT_OUTFILE;
46
+ for (let i = 0; i < argv.length; i += 1) {
47
+ const arg = argv[i];
48
+ if (arg === "--help" || arg === "-h") {
49
+ printHelp();
50
+ process.exit(0);
51
+ }
52
+ if (arg === "--entry" || arg === "-e") {
53
+ const value = argv[i + 1];
54
+ if (!value) {
55
+ throw new Error(`${arg} requires a path`);
56
+ }
57
+ entry = value;
58
+ i += 1;
59
+ continue;
60
+ }
61
+ if (arg === "--outfile" || arg === "-o") {
62
+ const value = argv[i + 1];
63
+ if (!value) {
64
+ throw new Error(`${arg} requires a path`);
65
+ }
66
+ outfile = value;
67
+ i += 1;
68
+ continue;
69
+ }
70
+ throw new Error(`Unknown option: ${arg}`);
71
+ }
72
+ return { entry, outfile };
73
+ }
74
+ function parseVerifyArgs(argv) {
75
+ let entry = DEFAULT_ENTRY;
76
+ let outfile = DEFAULT_OUTFILE;
77
+ let noBuild = false;
78
+ let bundleArg;
79
+ for (let i = 0; i < argv.length; i += 1) {
80
+ const arg = argv[i];
81
+ if (arg === "--help" || arg === "-h") {
82
+ printHelp();
83
+ process.exit(0);
84
+ }
85
+ if (arg === "--no-build") {
86
+ noBuild = true;
87
+ continue;
88
+ }
89
+ if (arg === "--entry" || arg === "-e") {
90
+ const value = argv[i + 1];
91
+ if (!value) {
92
+ throw new Error(`${arg} requires a path`);
93
+ }
94
+ entry = value;
95
+ i += 1;
96
+ continue;
97
+ }
98
+ if (arg === "--outfile" || arg === "-o") {
99
+ const value = argv[i + 1];
100
+ if (!value) {
101
+ throw new Error(`${arg} requires a path`);
102
+ }
103
+ outfile = value;
104
+ i += 1;
105
+ continue;
106
+ }
107
+ if (arg === "--bundle" || arg === "-b") {
108
+ const value = argv[i + 1];
109
+ if (!value) {
110
+ throw new Error(`${arg} requires a path`);
111
+ }
112
+ bundleArg = value;
113
+ i += 1;
114
+ continue;
115
+ }
116
+ throw new Error(`Unknown option: ${arg}`);
117
+ }
118
+ return {
119
+ entry,
120
+ outfile,
121
+ bundlePath: bundleArg ?? outfile,
122
+ noBuild,
123
+ };
124
+ }
125
+ async function runBuild(argv) {
126
+ const { entry, outfile } = parseBuildArgs(argv);
127
+ await buildAgentBundle({ entry, outfile });
128
+ process.stdout.write(`Built ${outfile} from ${entry}\n`);
129
+ }
130
+ async function runVerify(argv) {
131
+ const { entry, outfile, bundlePath, noBuild } = parseVerifyArgs(argv);
132
+ const result = await runAgentVerify({
133
+ entry,
134
+ outfile,
135
+ bundlePath,
136
+ noBuild,
137
+ });
138
+ if (!result.ok) {
139
+ process.stderr.write(`[@voicethere/agent verify] FAIL: ${formatVerifyFailure(result)}\n`);
140
+ process.exit(1);
141
+ }
142
+ }
143
+ async function main() {
144
+ const args = process.argv.slice(2);
145
+ if (args.length === 0) {
146
+ printHelp();
147
+ return;
148
+ }
149
+ if (args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
150
+ printHelp();
151
+ return;
152
+ }
153
+ if (args[0] === "build") {
154
+ await runBuild(args.slice(1));
155
+ return;
156
+ }
157
+ if (args[0] === "verify") {
158
+ await runVerify(args.slice(1));
159
+ return;
160
+ }
161
+ if (args[0]?.startsWith("-")) {
162
+ process.stderr.write("Missing command. Use `build` or `verify` before options.\n\n");
163
+ printHelp();
164
+ process.exit(1);
165
+ }
166
+ process.stderr.write(`Unknown command: ${args[0]}\n\n`);
167
+ printHelp();
168
+ process.exit(1);
169
+ }
170
+ main().catch((error) => {
171
+ const message = error instanceof Error ? error.message : String(error);
172
+ process.stderr.write(`[@voicethere/agent] ${message}\n`);
173
+ process.exit(1);
174
+ });
175
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Sandboxed child bootstrap — loads customer bundle under Node --permission.
3
+ *
4
+ * Keep in sync with the agent runner `src/child/loader-entry.js`.
5
+ */
6
+
7
+ const bundlePath = process.env.__CHILD_BUNDLE_PATH__;
8
+ if (!bundlePath) {
9
+ process.stderr.write("[child] missing __CHILD_BUNDLE_PATH__\n");
10
+ process.exit(1);
11
+ }
12
+
13
+ function formatArgs(args) {
14
+ return args.map((value) => String(value)).join(" ");
15
+ }
16
+
17
+ console.log = (...args) => {
18
+ process.send?.({ type: "log", level: "info", message: formatArgs(args) });
19
+ };
20
+
21
+ console.info = console.log;
22
+
23
+ console.error = (...args) => {
24
+ process.send?.({ type: "log", level: "error", message: formatArgs(args) });
25
+ };
26
+
27
+ console.warn = (...args) => {
28
+ process.send?.({
29
+ type: "log",
30
+ level: "info",
31
+ message: `[warn] ${formatArgs(args)}`,
32
+ });
33
+ };
34
+
35
+ const { pathToFileURL } = await import("node:url");
36
+
37
+ try {
38
+ await import(pathToFileURL(bundlePath).href);
39
+ } catch (error) {
40
+ const message = error instanceof Error ? error.message : String(error);
41
+ process.send?.({
42
+ type: "agent_error",
43
+ sessionId: "",
44
+ message: `Bundle load failed: ${message}`,
45
+ });
46
+ process.exit(1);
47
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Node --permission flags for the customer child process.
3
+ *
4
+ * Keep in sync with the agent runner `src/child/sandbox.ts`.
5
+ */
6
+ /**
7
+ * Node --permission flags for the customer child: no subprocesses, no fs writes.
8
+ * `fs` read is limited to the loader + bundle directories (no `--allow-child-process`).
9
+ */
10
+ export declare function buildChildExecArgv(options: {
11
+ loaderDir: string;
12
+ bundlePath: string;
13
+ }): string[];
14
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/sandbox/sandbox.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,EAAE,CAUX"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Node --permission flags for the customer child process.
3
+ *
4
+ * Keep in sync with the agent runner `src/child/sandbox.ts`.
5
+ */
6
+ import { dirname, resolve } from "node:path";
7
+ /**
8
+ * Node --permission flags for the customer child: no subprocesses, no fs writes.
9
+ * `fs` read is limited to the loader + bundle directories (no `--allow-child-process`).
10
+ */
11
+ export function buildChildExecArgv(options) {
12
+ const readDirs = new Set([
13
+ resolve(options.loaderDir),
14
+ resolve(dirname(options.bundlePath)),
15
+ ]);
16
+ return [
17
+ "--permission",
18
+ ...[...readDirs].map((dir) => `--allow-fs-read=${dir}`),
19
+ ];
20
+ }
21
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox/sandbox.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAGlC;IACC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS;QAC/B,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAC1B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;KACrC,CAAC,CAAC;IAEH,OAAO;QACL,cAAc;QACd,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,GAAG,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Fork a customer agent bundle the same way the agent runner does (IPC + sandbox).
3
+ *
4
+ * Keep behavior aligned with runner `src/child/starter.ts`.
5
+ */
6
+ import { type ChildToParentMessage, type ParentToChildMessage } from "../protocol.js";
7
+ export interface StartSandboxedChildOptions {
8
+ sessionId: string;
9
+ bundlePath: string;
10
+ projectId?: string;
11
+ buildId?: string;
12
+ onStderr?: (message: string) => void;
13
+ }
14
+ export interface SandboxedChild {
15
+ pid: number;
16
+ bundlePath: string;
17
+ send(message: ParentToChildMessage): boolean;
18
+ kill(signal?: NodeJS.Signals): void;
19
+ onMessage(handler: (message: ChildToParentMessage) => void): () => void;
20
+ onExit(handler: (code: number | null, signal: NodeJS.Signals | null) => void): () => void;
21
+ }
22
+ export declare function resolveBundlePath(bundlePath: string): string;
23
+ export declare function startSandboxedChild(options: StartSandboxedChildOptions): SandboxedChild;
24
+ //# sourceMappingURL=start-child.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-child.d.ts","sourceRoot":"","sources":["../../src/sandbox/start-child.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AAMxB,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACxE,MAAM,CACJ,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GACpE,MAAM,IAAI,CAAC;CACf;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,cAAc,CAiEhB"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Fork a customer agent bundle the same way the agent runner does (IPC + sandbox).
3
+ *
4
+ * Keep behavior aligned with runner `src/child/starter.ts`.
5
+ */
6
+ import { fork } from "node:child_process";
7
+ import { existsSync } from "node:fs";
8
+ import { dirname, join, resolve } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { ALLOWED_CHILD_ENV_KEYS, } from "../protocol.js";
11
+ import { buildChildExecArgv } from "./sandbox.js";
12
+ const SANDBOX_DIR = dirname(fileURLToPath(import.meta.url));
13
+ const LOADER_ENTRY = join(SANDBOX_DIR, "loader-entry.js");
14
+ export function resolveBundlePath(bundlePath) {
15
+ const resolved = resolve(bundlePath.trim());
16
+ if (!existsSync(resolved)) {
17
+ throw new Error(`Bundle not found: ${resolved}`);
18
+ }
19
+ return resolved;
20
+ }
21
+ export function startSandboxedChild(options) {
22
+ const bundlePath = resolveBundlePath(options.bundlePath);
23
+ const env = {
24
+ NODE_ENV: "production",
25
+ __CHILD_BUNDLE_PATH__: bundlePath,
26
+ };
27
+ for (const key of ALLOWED_CHILD_ENV_KEYS) {
28
+ if (key === "SESSION_ID")
29
+ env[key] = options.sessionId;
30
+ if (key === "PROJECT_ID" && options.projectId)
31
+ env[key] = options.projectId;
32
+ if (key === "BUILD_ID" && options.buildId)
33
+ env[key] = options.buildId;
34
+ }
35
+ const child = fork(LOADER_ENTRY, [], {
36
+ env,
37
+ stdio: ["ignore", "pipe", "pipe", "ipc"],
38
+ execArgv: buildChildExecArgv({
39
+ loaderDir: SANDBOX_DIR,
40
+ bundlePath,
41
+ }),
42
+ });
43
+ child.stderr?.on("data", (chunk) => {
44
+ const message = String(chunk).trim();
45
+ if (message)
46
+ options.onStderr?.(message);
47
+ });
48
+ const messageHandlers = new Set();
49
+ const exitHandlers = new Set();
50
+ child.on("message", (message) => {
51
+ if (!message || typeof message !== "object")
52
+ return;
53
+ const payload = message;
54
+ for (const handler of messageHandlers) {
55
+ handler(payload);
56
+ }
57
+ });
58
+ child.on("exit", (code, signal) => {
59
+ for (const handler of exitHandlers) {
60
+ handler(code, signal);
61
+ }
62
+ });
63
+ return {
64
+ pid: child.pid ?? -1,
65
+ bundlePath,
66
+ send(message) {
67
+ if (!child.connected)
68
+ return false;
69
+ return child.send(message);
70
+ },
71
+ kill(signal = "SIGTERM") {
72
+ child.kill(signal);
73
+ },
74
+ onMessage(handler) {
75
+ messageHandlers.add(handler);
76
+ return () => messageHandlers.delete(handler);
77
+ },
78
+ onExit(handler) {
79
+ exitHandlers.add(handler);
80
+ return () => exitHandlers.delete(handler);
81
+ },
82
+ };
83
+ }
84
+ //# sourceMappingURL=start-child.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-child.js","sourceRoot":"","sources":["../../src/sandbox/start-child.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ChildToParentMessage } from "../protocol.js";
2
+ export declare const VERIFY_SESSION_ID = "local-verify";
3
+ export declare const DEFAULT_VERIFY_BUNDLE = "dist/agent.js";
4
+ export declare const DEFAULT_VERIFY_ENTRY = "agent.ts";
5
+ export declare function parseBundleArg(argv: string[], env?: NodeJS.ProcessEnv, cwd?: string): string;
6
+ export declare function waitForSpeak(messages: ChildToParentMessage[], sessionId: string, timeoutMs: number): Promise<Extract<ChildToParentMessage, {
7
+ type: "speak";
8
+ }>>;
9
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/verify/lib.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAChD,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AACrD,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,GAAG,GAAE,MAAsB,GAC1B,MAAM,CAWR;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,oBAAoB,EAAE,EAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC,CAuB3D"}
@@ -0,0 +1,34 @@
1
+ import { resolve } from "node:path";
2
+ export const VERIFY_SESSION_ID = "local-verify";
3
+ export const DEFAULT_VERIFY_BUNDLE = "dist/agent.js";
4
+ export const DEFAULT_VERIFY_ENTRY = "agent.ts";
5
+ export function parseBundleArg(argv, env = process.env, cwd = process.cwd()) {
6
+ for (let i = 0; i < argv.length; i += 1) {
7
+ const arg = argv[i];
8
+ if ((arg === "--bundle" || arg === "-b") && argv[i + 1]) {
9
+ return resolve(cwd, argv[i + 1]);
10
+ }
11
+ }
12
+ if (env.AGENT_BUNDLE_PATH?.trim()) {
13
+ return resolve(cwd, env.AGENT_BUNDLE_PATH.trim());
14
+ }
15
+ return resolve(cwd, DEFAULT_VERIFY_BUNDLE);
16
+ }
17
+ export function waitForSpeak(messages, sessionId, timeoutMs) {
18
+ return new Promise((resolvePromise, reject) => {
19
+ const started = Date.now();
20
+ const timer = setInterval(() => {
21
+ const speak = messages.find((m) => m.type === "speak" && m.sessionId === sessionId);
22
+ if (speak) {
23
+ clearInterval(timer);
24
+ resolvePromise(speak);
25
+ return;
26
+ }
27
+ if (Date.now() - started >= timeoutMs) {
28
+ clearInterval(timer);
29
+ reject(new Error(`Timed out after ${timeoutMs}ms waiting for child speak IPC`));
30
+ }
31
+ }, 50);
32
+ });
33
+ }
34
+ //# sourceMappingURL=lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../../src/verify/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAChD,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C,MAAM,UAAU,cAAc,CAC5B,IAAc,EACd,MAAyB,OAAO,CAAC,GAAG,EACpC,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACxD,OAAO,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,QAAgC,EAChC,SAAiB,EACjB,SAAiB;IAEjB,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CACzB,CAAC,CAAC,EAAyD,EAAE,CAC3D,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,CAClD,CAAC;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,IAAI,SAAS,EAAE,CAAC;gBACtC,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,MAAM,CACJ,IAAI,KAAK,CACP,mBAAmB,SAAS,gCAAgC,CAC7D,CACF,CAAC;YACJ,CAAC;QACH,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,23 @@
1
+ export interface VerifyAgentOptions {
2
+ cwd?: string;
3
+ entry?: string;
4
+ outfile?: string;
5
+ bundlePath?: string;
6
+ /** When true, skip the build step and verify an existing bundle only. */
7
+ noBuild?: boolean;
8
+ /** When true, suppress per-check log lines (for tests). */
9
+ quiet?: boolean;
10
+ }
11
+ export interface VerifyCheckResult {
12
+ name: string;
13
+ ok: boolean;
14
+ detail?: string;
15
+ }
16
+ export interface VerifyAgentResult {
17
+ ok: boolean;
18
+ checks: VerifyCheckResult[];
19
+ bundlePath: string;
20
+ }
21
+ export declare function runAgentVerify(options?: VerifyAgentOptions): Promise<VerifyAgentResult>;
22
+ export declare function formatVerifyFailure(result: VerifyAgentResult): string;
23
+ //# sourceMappingURL=run-verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-verify.d.ts","sourceRoot":"","sources":["../../src/verify/run-verify.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAqBD,wBAAsB,cAAc,CAClC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAuL5B;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAQrE"}
@@ -0,0 +1,176 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { buildAgentBundle } from "../build-bundle.js";
4
+ import { startSandboxedChild } from "../sandbox/start-child.js";
5
+ import { VERIFY_SESSION_ID, parseBundleArg, waitForSpeak, } from "./lib.js";
6
+ const READY_MS = 300;
7
+ const SPEAK_TIMEOUT_MS = 5000;
8
+ const MIN_NODE_MAJOR = 22;
9
+ function delay(ms) {
10
+ return new Promise((resolveDelay) => setTimeout(resolveDelay, ms));
11
+ }
12
+ function logLine(quiet, message) {
13
+ if (!quiet) {
14
+ process.stdout.write(`${message}\n`);
15
+ }
16
+ }
17
+ function failCheck(checks, name, detail) {
18
+ checks.push({ name, ok: false, detail });
19
+ return { ok: false, checks, bundlePath: "" };
20
+ }
21
+ export async function runAgentVerify(options = {}) {
22
+ const cwd = options.cwd ?? process.cwd();
23
+ const checks = [];
24
+ const quiet = options.quiet;
25
+ const entry = options.entry ?? "agent.ts";
26
+ const outfile = options.outfile ?? "dist/agent.js";
27
+ const bundlePath = options.bundlePath ??
28
+ parseBundleArg([], process.env, cwd);
29
+ logLine(quiet, "[@voicethere/agent verify]");
30
+ const nodeMajor = Number(process.versions.node.split(".")[0]);
31
+ if (!Number.isFinite(nodeMajor) || nodeMajor < MIN_NODE_MAJOR) {
32
+ return failCheck(checks, "Node.js version", `Node ${MIN_NODE_MAJOR}+ required (--permission sandbox); found ${process.version}`);
33
+ }
34
+ checks.push({
35
+ name: "Node.js version",
36
+ ok: true,
37
+ detail: process.version,
38
+ });
39
+ logLine(quiet, `✓ Node.js ${process.version}`);
40
+ if (!options.noBuild) {
41
+ try {
42
+ await buildAgentBundle({ cwd, entry, outfile });
43
+ checks.push({
44
+ name: "Build bundle",
45
+ ok: true,
46
+ detail: `${outfile} from ${entry}`,
47
+ });
48
+ logLine(quiet, `✓ Built ${outfile} from ${entry}`);
49
+ }
50
+ catch (error) {
51
+ const detail = error instanceof Error ? error.message : String(error);
52
+ return failCheck(checks, "Build bundle", detail);
53
+ }
54
+ }
55
+ else {
56
+ checks.push({
57
+ name: "Build bundle",
58
+ ok: true,
59
+ detail: "skipped (--no-build)",
60
+ });
61
+ logLine(quiet, "○ Build bundle (skipped)");
62
+ }
63
+ const resolvedBundle = resolve(cwd, bundlePath);
64
+ if (!existsSync(resolvedBundle)) {
65
+ return failCheck(checks, "Bundle present", `Bundle not found: ${resolvedBundle}`);
66
+ }
67
+ checks.push({
68
+ name: "Bundle present",
69
+ ok: true,
70
+ detail: resolvedBundle,
71
+ });
72
+ logLine(quiet, `✓ Bundle present (${resolvedBundle})`);
73
+ const childMessages = [];
74
+ let childError;
75
+ let earlyExitCode;
76
+ let child;
77
+ try {
78
+ child = startSandboxedChild({
79
+ sessionId: VERIFY_SESSION_ID,
80
+ bundlePath: resolvedBundle,
81
+ onStderr: (message) => {
82
+ if (!quiet) {
83
+ process.stderr.write(`[child stderr] ${message}\n`);
84
+ }
85
+ },
86
+ });
87
+ }
88
+ catch (error) {
89
+ const detail = error instanceof Error ? error.message : String(error);
90
+ return failCheck(checks, "Sandbox spawn", detail);
91
+ }
92
+ checks.push({
93
+ name: "Sandbox spawn",
94
+ ok: true,
95
+ detail: `pid ${child.pid}`,
96
+ });
97
+ logLine(quiet, `✓ Sandbox spawn (pid ${child.pid})`);
98
+ child.onMessage((message) => {
99
+ childMessages.push(message);
100
+ if (message.type === "log" && !quiet) {
101
+ process.stdout.write(`[child ${message.level}] ${message.message}\n`);
102
+ }
103
+ if (message.type === "agent_error") {
104
+ childError = message.message;
105
+ }
106
+ if (message.type === "speak" && !quiet) {
107
+ process.stdout.write(`[child speak] ${message.text}\n`);
108
+ }
109
+ });
110
+ const exitPromise = new Promise((resolveExit) => {
111
+ child.onExit((code) => {
112
+ earlyExitCode = code;
113
+ resolveExit(code);
114
+ });
115
+ });
116
+ child.send({
117
+ type: "session_start",
118
+ sessionId: VERIFY_SESSION_ID,
119
+ env: {
120
+ SESSION_ID: VERIFY_SESSION_ID,
121
+ PROJECT_ID: "local",
122
+ BUILD_ID: "verify",
123
+ },
124
+ });
125
+ await delay(READY_MS);
126
+ if (earlyExitCode !== undefined) {
127
+ return failCheck(checks, "Bundle load", `Child exited early with code ${earlyExitCode ?? "null"}`);
128
+ }
129
+ checks.push({ name: "Bundle load", ok: true });
130
+ logLine(quiet, "✓ Bundle load");
131
+ child.send({
132
+ type: "speech_event",
133
+ sessionId: VERIFY_SESSION_ID,
134
+ event: { type: "user_speech_final", text: "hello from verify" },
135
+ });
136
+ try {
137
+ const speak = await waitForSpeak(childMessages, VERIFY_SESSION_ID, SPEAK_TIMEOUT_MS);
138
+ if (!speak.text.trim()) {
139
+ return failCheck(checks, "Speech response", "Child returned empty speak text for user_speech_final");
140
+ }
141
+ checks.push({
142
+ name: "Speech response",
143
+ ok: true,
144
+ detail: speak.text.trim(),
145
+ });
146
+ logLine(quiet, `✓ Speech response (${speak.text.trim()})`);
147
+ }
148
+ catch (error) {
149
+ const detail = error instanceof Error ? error.message : String(error);
150
+ child.kill("SIGTERM");
151
+ await exitPromise;
152
+ return failCheck(checks, "Speech response", detail);
153
+ }
154
+ if (childError) {
155
+ child.kill("SIGTERM");
156
+ await exitPromise;
157
+ return failCheck(checks, "No agent errors", childError);
158
+ }
159
+ checks.push({ name: "No agent errors", ok: true });
160
+ logLine(quiet, "✓ No agent errors");
161
+ child.send({ type: "session_end", sessionId: VERIFY_SESSION_ID });
162
+ child.kill("SIGTERM");
163
+ await exitPromise;
164
+ logLine(quiet, "[@voicethere/agent verify] All checks passed.");
165
+ return { ok: true, checks, bundlePath: resolvedBundle };
166
+ }
167
+ export function formatVerifyFailure(result) {
168
+ const failed = result.checks.filter((check) => !check.ok);
169
+ if (failed.length === 0) {
170
+ return "Verify failed";
171
+ }
172
+ return failed
173
+ .map((check) => `${check.name}: ${check.detail ?? "failed"}`)
174
+ .join("; ");
175
+ }
176
+ //# sourceMappingURL=run-verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-verify.js","sourceRoot":"","sources":["../../src/verify/run-verify.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voicethere/agent",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "VoiceThere customer agent SDK — IPC types and runtime helpers for sandboxed child bundles",
5
5
  "type": "module",
6
6
  "exports": {
@@ -9,18 +9,21 @@
9
9
  "import": "./dist/index.js"
10
10
  }
11
11
  },
12
+ "bin": "./dist/cli.js",
12
13
  "files": [
13
14
  "dist",
14
15
  "templates",
15
16
  "README.md"
16
17
  ],
17
18
  "scripts": {
18
- "build": "tsc -p tsconfig.json && esbuild examples/agent.ts --bundle --platform=node --format=esm --outfile=dist/agent.js",
19
+ "build:lib": "tsc -p tsconfig.json && mkdir -p dist/sandbox && cp src/sandbox/loader-entry.js dist/sandbox/",
20
+ "build:example": "node dist/cli.js build --entry examples/agent.ts --outfile dist/agent.js",
21
+ "build": "npm run build:lib && npm run build:example",
19
22
  "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json",
20
23
  "test": "vitest run",
21
24
  "test:ci": "npm run typecheck && npm run build && npm run test",
22
- "verify:local": "npm run build && tsx scripts/verify-local.ts",
23
- "verify:local:only": "tsx scripts/verify-local.ts",
25
+ "verify:local": "npm run build && node dist/cli.js verify --no-build --bundle dist/agent.js",
26
+ "verify:local:only": "node dist/cli.js verify --no-build --bundle dist/agent.js",
24
27
  "prepublishOnly": "npm run build"
25
28
  },
26
29
  "repository": {
@@ -45,14 +48,14 @@
45
48
  },
46
49
  "license": "UNLICENSED",
47
50
  "dependencies": {
48
- "@node-webrtc-rust/sdk": "0.5.2"
51
+ "@node-webrtc-rust/sdk": "0.5.2",
52
+ "esbuild": "^0.25.12"
49
53
  },
50
54
  "peerDependencies": {
51
55
  "@node-webrtc-rust/sdk": ">=0.5.2"
52
56
  },
53
57
  "devDependencies": {
54
58
  "@types/node": "^22.10.0",
55
- "esbuild": "^0.25.12",
56
59
  "tsx": "^4.19.2",
57
60
  "typescript": "^5.7.0",
58
61
  "vitest": "^2.1.8"
@@ -17,10 +17,15 @@ Full starter bundle covering every speech event from `@node-webrtc-rust/sdk/voic
17
17
  **Build:**
18
18
 
19
19
  ```bash
20
- npm install @voicethere/agent esbuild
21
- npx esbuild agent.ts --bundle --platform=node --format=esm --outfile=dist/agent.js
20
+ npm install @voicethere/agent
21
+ npx @voicethere/agent build
22
+ # optional: --entry agent.ts --outfile dist/agent.js
22
23
  ```
23
24
 
24
- **Verify sandbox (no WebRTC):** from the agent repo, `npm run verify:local` after building your bundle.
25
+ **Verify sandbox (no WebRTC):**
26
+
27
+ ```bash
28
+ npx @voicethere/agent verify
29
+ ```
25
30
 
26
31
  **Voice E2E:** host with the VoiceThere agent runner (platform or internal deployment) — set `AGENT_BUNDLE_PATH` to your built `dist/agent.js`.
@@ -6,7 +6,10 @@
6
6
  *
7
7
  * Build:
8
8
  * npm install @voicethere/agent
9
- * npx esbuild agent.ts --bundle --platform=node --format=esm --outfile=dist/agent.js
9
+ * npx @voicethere/agent build
10
+ *
11
+ * Verify (sandbox checks, no WebRTC):
12
+ * npx @voicethere/agent verify
10
13
  *
11
14
  * Voice E2E (VoiceThere agent runner — platform or internal deployment):
12
15
  * AGENT_BUNDLE_PATH=./dist/agent.js npm run start