@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 +30 -25
- package/dist/build-bundle.d.ts +14 -0
- package/dist/build-bundle.d.ts.map +1 -0
- package/dist/build-bundle.js +25 -0
- package/dist/build-bundle.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +175 -0
- package/dist/cli.js.map +1 -0
- package/dist/sandbox/loader-entry.js +47 -0
- package/dist/sandbox/sandbox.d.ts +14 -0
- package/dist/sandbox/sandbox.d.ts.map +1 -0
- package/dist/sandbox/sandbox.js +21 -0
- package/dist/sandbox/sandbox.js.map +1 -0
- package/dist/sandbox/start-child.d.ts +24 -0
- package/dist/sandbox/start-child.d.ts.map +1 -0
- package/dist/sandbox/start-child.js +84 -0
- package/dist/sandbox/start-child.js.map +1 -0
- package/dist/verify/lib.d.ts +9 -0
- package/dist/verify/lib.d.ts.map +1 -0
- package/dist/verify/lib.js +34 -0
- package/dist/verify/lib.js.map +1 -0
- package/dist/verify/run-verify.d.ts +23 -0
- package/dist/verify/run-verify.d.ts.map +1 -0
- package/dist/verify/run-verify.js +176 -0
- package/dist/verify/run-verify.js.map +1 -0
- package/package.json +9 -6
- package/templates/README.md +8 -3
- package/templates/agent.ts +4 -1
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,
|
|
28
|
+
Before deploying to VoiceThere, build your bundle and run sandbox checks (same Node `--permission` flags as production):
|
|
37
29
|
|
|
38
30
|
```bash
|
|
39
|
-
|
|
31
|
+
npx @voicethere/agent verify
|
|
40
32
|
```
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
|
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
|
-
|
|
42
|
+
Optional flags: `--entry` / `-e`, `--outfile` / `-o` (same as `build`).
|
|
48
43
|
|
|
49
|
-
|
|
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:**
|
|
99
|
+
**Recommended:** bundle with the package CLI (same esbuild settings VoiceThere uses in production):
|
|
105
100
|
|
|
106
101
|
```bash
|
|
107
|
-
npm install @voicethere/agent
|
|
108
|
-
npx
|
|
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
|
-
|
|
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. `
|
|
217
|
-
2.
|
|
218
|
-
|
|
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 #
|
|
231
|
-
npm run
|
|
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 @@
|
|
|
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
|
package/dist/cli.js.map
ADDED
|
@@ -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":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAqB,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EACL,sBAAsB,GAGvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;AAqB1D,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAmC;IAEnC,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzD,MAAM,GAAG,GAAsB;QAC7B,QAAQ,EAAE,YAAY;QACtB,qBAAqB,EAAE,UAAU;KAClC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QACzC,IAAI,GAAG,KAAK,YAAY;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;QACvD,IAAI,GAAG,KAAK,YAAY,IAAI,OAAO,CAAC,SAAS;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;QAC5E,IAAI,GAAG,KAAK,UAAU,IAAI,OAAO,CAAC,OAAO;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IACxE,CAAC;IAED,MAAM,KAAK,GAAiB,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE;QACjD,GAAG;QACH,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;QACxC,QAAQ,EAAE,kBAAkB,CAAC;YAC3B,SAAS,EAAE,WAAW;YACtB,UAAU;SACX,CAAC;KACH,CAAC,CAAC;IAEH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QACjC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,OAAO;YAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,IAAI,GAAG,EAA2C,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,GAAG,EAEzB,CAAC;IAEJ,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE;QACvC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO;QACpD,MAAM,OAAO,GAAG,OAA+B,CAAC;QAChD,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;YACtC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;QAChC,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;YACnC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,UAAU;QACV,IAAI,CAAC,OAA6B;YAChC,IAAI,CAAC,KAAK,CAAC,SAAS;gBAAE,OAAO,KAAK,CAAC;YACnC,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,SAAyB,SAAS;YACrC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;QACD,SAAS,CAAC,OAAO;YACf,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC7B,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,CAAC,OAAO;YACZ,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC1B,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -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.
|
|
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 &&
|
|
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 &&
|
|
23
|
-
"verify:local:only": "
|
|
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"
|
package/templates/README.md
CHANGED
|
@@ -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
|
|
21
|
-
npx
|
|
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):**
|
|
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`.
|
package/templates/agent.ts
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Build:
|
|
8
8
|
* npm install @voicethere/agent
|
|
9
|
-
* npx
|
|
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
|