@voicethere/agent 0.1.14 → 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.
- package/README.md +103 -1
- package/dist/agent.js +17 -0
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js.map +1 -1
- package/dist/runner.d.ts +3 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +3 -0
- package/dist/runner.js.map +1 -0
- package/dist/runtime.d.ts +9 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +19 -0
- package/dist/runtime.js.map +1 -1
- package/dist/sandbox/start-child.d.ts +7 -3
- package/dist/sandbox/start-child.d.ts.map +1 -1
- package/dist/sandbox/start-child.js +14 -4
- package/dist/sandbox/start-child.js.map +1 -1
- package/package.json +18 -3
- package/templates/README.md +18 -0
- package/templates/game-sync.ts +377 -51
package/README.md
CHANGED
|
@@ -43,6 +43,92 @@ Optional flags: `--entry` / `-e`, `--outfile` / `-o` (same as `build`).
|
|
|
43
43
|
|
|
44
44
|
This does **not** replace a voice roundtrip with mic/WebRTC — deploy to the VoiceThere platform for full E2E.
|
|
45
45
|
|
|
46
|
+
For repository-local verify scripts, `dist/cli.js` is generated from `src/cli.ts` by `npm run build:lib`.
|
|
47
|
+
That is the package-local `@voicethere/agent` CLI artifact (not `@voicethere/cli`).
|
|
48
|
+
|
|
49
|
+
## Live browser test page (local stack)
|
|
50
|
+
|
|
51
|
+
The live harness runs fully from the `agent` repo:
|
|
52
|
+
|
|
53
|
+
1. local starter (`node-webrtc-rust` signaling + voice pipeline + sandboxed child bundle)
|
|
54
|
+
2. built child bundle (`dist/agent.js`)
|
|
55
|
+
3. browser page (`examples/live-test/index.html`, served by the starter)
|
|
56
|
+
|
|
57
|
+
### One-time setup
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# 1) agent live-test config (optional overrides for scripts)
|
|
61
|
+
cd agent
|
|
62
|
+
cp .env.live-test.example .env.live-test
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Configure STT/TTS for local live testing
|
|
66
|
+
|
|
67
|
+
The starter reads env in this order: shell env → `agent/.env.live-test`.
|
|
68
|
+
|
|
69
|
+
For local Sherpa, at minimum ensure:
|
|
70
|
+
|
|
71
|
+
- `SHERPA_STT_MODEL_PATH`
|
|
72
|
+
- `SHERPA_TTS_MODEL_PATH`
|
|
73
|
+
- optional: `SHERPA_STT_LANGUAGE`, `SHERPA_TTS_SPEAKER`
|
|
74
|
+
|
|
75
|
+
Where the paths come from:
|
|
76
|
+
|
|
77
|
+
- Sherpa bundles are downloaded into:
|
|
78
|
+
- `agent/.models/`
|
|
79
|
+
- Catalog/source list:
|
|
80
|
+
- `agent/scripts/sherpa-stt-catalog.json` (STT)
|
|
81
|
+
- `agent/scripts/sherpa-tts-catalog.json` (TTS)
|
|
82
|
+
|
|
83
|
+
Use the agent helper to select models, download if missing, and emit absolute env exports:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm run live-test:models
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The script writes selected values into `agent/.env.live-test`.
|
|
90
|
+
|
|
91
|
+
To use hosted providers instead of local Sherpa, set in `agent/.env.live-test`:
|
|
92
|
+
|
|
93
|
+
- `VOICE_STT_PROVIDER` (`openai` | `deepgram` | `assemblyai` | `google`)
|
|
94
|
+
- `VOICE_TTS_PROVIDER` (`openai` | `elevenlabs` | `cartesia` | `google`)
|
|
95
|
+
- provider API keys (`OPENAI_API_KEY`, `DEEPGRAM_API_KEY`, `ASSEMBLYAI_API_KEY`, `ELEVENLABS_API_KEY`, `CARTESIA_API_KEY`, `GOOGLE_API_KEY`)
|
|
96
|
+
- optional model/voice overrides: `VOICE_STT_MODEL`, `VOICE_TTS_MODEL`, `VOICE_TTS_VOICE`, `VOICE_STT_LANGUAGE`
|
|
97
|
+
|
|
98
|
+
Vendor setup reference: https://github.com/akirilyuk/node-webrtc-rust#stttts-vendors-and-config
|
|
99
|
+
|
|
100
|
+
### Start local stack
|
|
101
|
+
|
|
102
|
+
From `agent/`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm install
|
|
106
|
+
npm run live-test:models # select/download sherpa models and export env values
|
|
107
|
+
npm run live-test:stack:echo # voice echo template
|
|
108
|
+
# or
|
|
109
|
+
npm run live-test:stack:game # data-only game-sync template
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This starts the local starter with your sandboxed bundle and serves the page.
|
|
113
|
+
|
|
114
|
+
Live-test scripts load optional overrides from `agent/.env.live-test` (or `LIVE_TEST_ENV_FILE`).
|
|
115
|
+
|
|
116
|
+
Open:
|
|
117
|
+
|
|
118
|
+
`http://127.0.0.1:8080/examples/live-test/index.html`
|
|
119
|
+
|
|
120
|
+
If you prefer separate terminals:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Terminal A (agent starter + bundle + signaling)
|
|
124
|
+
npm run live-test:starter
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The page uses `@voicethere/client/browser` (loaded via esm.sh) and renders two visualizers:
|
|
128
|
+
|
|
129
|
+
- local microphone input
|
|
130
|
+
- incoming remote/agent audio
|
|
131
|
+
|
|
46
132
|
## API
|
|
47
133
|
|
|
48
134
|
```typescript
|
|
@@ -78,6 +164,22 @@ defineAgent({
|
|
|
78
164
|
| `agentLog` | Forward structured logs to parent |
|
|
79
165
|
| `ParentToChildMessage` / `ChildToParentMessage` | IPC contract shared with the VoiceThere agent runner |
|
|
80
166
|
|
|
167
|
+
### Runner runtime subpath (minimal shared sandbox API)
|
|
168
|
+
|
|
169
|
+
For runner-side child bootstrap reuse, `@voicethere/agent` exposes:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import {
|
|
173
|
+
buildChildExecArgv,
|
|
174
|
+
collectAllowFsReadDirs,
|
|
175
|
+
resolveBundlePath,
|
|
176
|
+
startSandboxedChild,
|
|
177
|
+
} from "@voicethere/agent/runner";
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
This subpath is intentionally narrow: sandbox/startup primitives only. Runner-specific
|
|
181
|
+
session orchestration and crash policy remain in the runner codebase.
|
|
182
|
+
|
|
81
183
|
### Speech events (parent → child)
|
|
82
184
|
|
|
83
185
|
Forwarded from the runner voice pipeline as SDK `SpeechEvent` payloads on `speech_event.event` (`event.type`, optional `text` / `error`):
|
|
@@ -104,7 +206,7 @@ The runtime processes parent IPC **in order per `sessionId`** while different se
|
|
|
104
206
|
|
|
105
207
|
For isolated voice agents (default), leave **`shared_child_per_session`** disabled — each session gets its own child process.
|
|
106
208
|
|
|
107
|
-
See [`templates/game-sync.ts`](./templates/game-sync.ts) for a data-only authoritative server example.
|
|
209
|
+
See [`templates/game-sync.ts`](./templates/game-sync.ts) for a data-only authoritative server example (60Hz server-side movement + collisions, client render-only).
|
|
108
210
|
|
|
109
211
|
## Building your agent bundle
|
|
110
212
|
|
package/dist/agent.js
CHANGED
|
@@ -182,6 +182,9 @@ function speak(sessionId, text) {
|
|
|
182
182
|
if (endedSessionIds.has(sessionId)) return;
|
|
183
183
|
process.send?.({ type: "speak", sessionId, text });
|
|
184
184
|
}
|
|
185
|
+
function sendToClient(sessionId, payload) {
|
|
186
|
+
process.send?.({ type: "send_to_client", sessionId, payload });
|
|
187
|
+
}
|
|
185
188
|
function agentLog(level, message, sessionId) {
|
|
186
189
|
const resolvedSessionId = sessionId ?? agentLogSessionContext.getStore();
|
|
187
190
|
process.send?.({
|
|
@@ -191,6 +194,13 @@ function agentLog(level, message, sessionId) {
|
|
|
191
194
|
...resolvedSessionId ? { sessionId: resolvedSessionId } : {}
|
|
192
195
|
});
|
|
193
196
|
}
|
|
197
|
+
function parseChatText(message) {
|
|
198
|
+
if (!message || typeof message !== "object") return null;
|
|
199
|
+
const record = message;
|
|
200
|
+
if (record.type !== "chat" || typeof record.text !== "string") return null;
|
|
201
|
+
const trimmed = record.text.trim();
|
|
202
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
203
|
+
}
|
|
194
204
|
|
|
195
205
|
// examples/agent.ts
|
|
196
206
|
var peers = /* @__PURE__ */ new Map();
|
|
@@ -283,6 +293,13 @@ defineAgent({
|
|
|
283
293
|
onUserSpeechFinal({ sessionId, text }) {
|
|
284
294
|
speak(sessionId, `You said: ${text}`);
|
|
285
295
|
},
|
|
296
|
+
onDataChannelMessage({ sessionId, message }) {
|
|
297
|
+
const text = parseChatText(message);
|
|
298
|
+
if (!text) return;
|
|
299
|
+
agentLog("info", `[${sessionId}] chat_received "${text}"`);
|
|
300
|
+
speak(sessionId, `You wrote: ${text}`);
|
|
301
|
+
sendToClient(sessionId, { type: "chat_echo", text });
|
|
302
|
+
},
|
|
286
303
|
onSessionEnd({ sessionId }) {
|
|
287
304
|
peers.delete(sessionId);
|
|
288
305
|
agentLog("info", `session_end ${sessionId}`);
|
package/dist/protocol.d.ts
CHANGED
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA2MH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,YAAY;IACZ,YAAY;IACZ,UAAU;IACV,kBAAkB;IAClB,wEAAwE;IACxE,wBAAwB;CAChB,CAAC"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GAGpB,MAAM,0BAA0B,CAAC"}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -81,6 +81,15 @@ export declare function speak(sessionId: string, text: string): void;
|
|
|
81
81
|
export declare function sendToClient(sessionId: string, payload: unknown): void;
|
|
82
82
|
/** Send raw bytes to the browser peer via the runner parent. */
|
|
83
83
|
export declare function sendBinaryToClient(sessionId: string, data: Buffer | Uint8Array, channel?: DataChannelKind): void;
|
|
84
|
+
/**
|
|
85
|
+
* Broadcasts binary data to specified clients over a specific data channel.
|
|
86
|
+
*
|
|
87
|
+
* @param data The binary data to be sent, either as a Buffer or Uint8Array.
|
|
88
|
+
* @param sessionIds An array of session IDs representing the target clients.
|
|
89
|
+
* @param channel The data channel over which the binary data is sent. Defaults to "sync".
|
|
90
|
+
* @return void
|
|
91
|
+
*/
|
|
92
|
+
export declare function broadCastBinaryToClients(data: Buffer | Uint8Array, sessionIds: readonly string[], channel?: DataChannelKind): void;
|
|
84
93
|
/** Send the same JSON payload to one or more browser peers. */
|
|
85
94
|
export declare function broadcastToClients(payload: unknown, sessionIds: readonly string[]): void;
|
|
86
95
|
/** Structured log forwarded to the runner parent (includes session when in a handler). */
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime.js
CHANGED
|
@@ -208,6 +208,25 @@ export function sendBinaryToClient(sessionId, data, channel = "sync") {
|
|
|
208
208
|
channel,
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Broadcasts binary data to specified clients over a specific data channel.
|
|
213
|
+
*
|
|
214
|
+
* @param data The binary data to be sent, either as a Buffer or Uint8Array.
|
|
215
|
+
* @param sessionIds An array of session IDs representing the target clients.
|
|
216
|
+
* @param channel The data channel over which the binary data is sent. Defaults to "sync".
|
|
217
|
+
* @return void
|
|
218
|
+
*/
|
|
219
|
+
export function broadCastBinaryToClients(data, sessionIds, channel = "sync") {
|
|
220
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
221
|
+
for (const sessionId of sessionIds) {
|
|
222
|
+
process.send?.({
|
|
223
|
+
type: "send_binary_to_client",
|
|
224
|
+
sessionId,
|
|
225
|
+
data: buffer,
|
|
226
|
+
channel,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
211
230
|
/** Send the same JSON payload to one or more browser peers. */
|
|
212
231
|
export function broadcastToClients(payload, sessionIds) {
|
|
213
232
|
for (const sessionId of sessionIds) {
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
import { type ChildToParentMessage, type ParentToChildMessage } from "../protocol.js";
|
|
7
7
|
export interface StartSandboxedChildOptions {
|
|
8
8
|
sessionId: string;
|
|
9
|
-
|
|
9
|
+
/** Absolute path to customer bundle. If omitted, uses `defaultBundlePath`. */
|
|
10
|
+
bundlePath?: string;
|
|
11
|
+
/** Optional fallback bundle when `bundlePath` is not provided. */
|
|
12
|
+
defaultBundlePath?: string;
|
|
10
13
|
projectId?: string;
|
|
11
14
|
buildId?: string;
|
|
12
|
-
|
|
15
|
+
allowlistedEnv?: Record<string, string>;
|
|
16
|
+
onStderr?: (message: string, childPid: number) => void;
|
|
13
17
|
}
|
|
14
18
|
export interface SandboxedChild {
|
|
15
19
|
pid: number;
|
|
@@ -19,6 +23,6 @@ export interface SandboxedChild {
|
|
|
19
23
|
onMessage(handler: (message: ChildToParentMessage) => void): () => void;
|
|
20
24
|
onExit(handler: (code: number | null, signal: NodeJS.Signals | null) => void): () => void;
|
|
21
25
|
}
|
|
22
|
-
export declare function resolveBundlePath(bundlePath
|
|
26
|
+
export declare function resolveBundlePath(bundlePath?: string, defaultBundlePath?: string): string;
|
|
23
27
|
export declare function startSandboxedChild(options: StartSandboxedChildOptions): SandboxedChild;
|
|
24
28
|
//# sourceMappingURL=start-child.d.ts.map
|
|
@@ -1 +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;
|
|
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,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;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,CAC/B,UAAU,CAAC,EAAE,MAAM,EACnB,iBAAiB,CAAC,EAAE,MAAM,GACzB,MAAM,CAcR;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,cAAc,CA6EhB"}
|
|
@@ -11,8 +11,12 @@ import { ALLOWED_CHILD_ENV_KEYS, } from "../protocol.js";
|
|
|
11
11
|
import { buildChildExecArgv } from "./sandbox.js";
|
|
12
12
|
const SANDBOX_DIR = dirname(fileURLToPath(import.meta.url));
|
|
13
13
|
const LOADER_ENTRY = join(SANDBOX_DIR, "loader-entry.js");
|
|
14
|
-
export function resolveBundlePath(bundlePath) {
|
|
15
|
-
const
|
|
14
|
+
export function resolveBundlePath(bundlePath, defaultBundlePath) {
|
|
15
|
+
const raw = bundlePath?.trim() || defaultBundlePath?.trim();
|
|
16
|
+
if (!raw) {
|
|
17
|
+
throw new Error("Bundle path is required");
|
|
18
|
+
}
|
|
19
|
+
const resolved = resolve(raw);
|
|
16
20
|
if (!existsSync(resolved)) {
|
|
17
21
|
throw new Error(`Bundle not found: ${resolved}`);
|
|
18
22
|
}
|
|
@@ -24,7 +28,7 @@ export function resolveBundlePath(bundlePath) {
|
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
export function startSandboxedChild(options) {
|
|
27
|
-
const bundlePath = resolveBundlePath(options.bundlePath);
|
|
31
|
+
const bundlePath = resolveBundlePath(options.bundlePath, options.defaultBundlePath);
|
|
28
32
|
const env = {
|
|
29
33
|
NODE_ENV: "production",
|
|
30
34
|
__CHILD_BUNDLE_PATH__: bundlePath,
|
|
@@ -37,6 +41,12 @@ export function startSandboxedChild(options) {
|
|
|
37
41
|
if (key === "BUILD_ID" && options.buildId)
|
|
38
42
|
env[key] = options.buildId;
|
|
39
43
|
}
|
|
44
|
+
for (const [key, value] of Object.entries(options.allowlistedEnv ?? {})) {
|
|
45
|
+
if (ALLOWED_CHILD_ENV_KEYS.includes(key) ||
|
|
46
|
+
key.startsWith("AGENT_")) {
|
|
47
|
+
env[key] = value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
40
50
|
const child = fork(LOADER_ENTRY, [], {
|
|
41
51
|
env,
|
|
42
52
|
stdio: ["ignore", "pipe", "pipe", "ipc"],
|
|
@@ -48,7 +58,7 @@ export function startSandboxedChild(options) {
|
|
|
48
58
|
child.stderr?.on("data", (chunk) => {
|
|
49
59
|
const message = String(chunk).trim();
|
|
50
60
|
if (message)
|
|
51
|
-
options.onStderr?.(message);
|
|
61
|
+
options.onStderr?.(message, child.pid ?? -1);
|
|
52
62
|
});
|
|
53
63
|
const messageHandlers = new Set();
|
|
54
64
|
const exitHandlers = new Set();
|
|
@@ -1 +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,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,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;
|
|
1
|
+
{"version":3,"file":"start-child.js","sourceRoot":"","sources":["../../src/sandbox/start-child.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.2.1",
|
|
4
4
|
"description": "VoiceThere customer agent SDK — IPC types and runtime helpers for sandboxed child bundles",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
"require": "./dist/index.js",
|
|
11
11
|
"default": "./dist/index.js"
|
|
12
12
|
},
|
|
13
|
+
"./runner": {
|
|
14
|
+
"types": "./dist/runner.d.ts",
|
|
15
|
+
"import": "./dist/runner.js",
|
|
16
|
+
"require": "./dist/runner.js",
|
|
17
|
+
"default": "./dist/runner.js"
|
|
18
|
+
},
|
|
13
19
|
"./verify": {
|
|
14
20
|
"types": "./dist/verify/run-verify.d.ts",
|
|
15
21
|
"import": "./dist/verify/run-verify.js",
|
|
@@ -31,8 +37,14 @@
|
|
|
31
37
|
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json",
|
|
32
38
|
"test": "vitest run",
|
|
33
39
|
"test:ci": "npm run typecheck && npm run build && npm run test && node scripts/ci/verify-package-exports.mjs",
|
|
34
|
-
"verify:local": "npm run build && node dist/cli.js verify --no-build --bundle dist/agent.js",
|
|
35
|
-
"verify:local:only": "node dist/cli.js verify --no-build --bundle dist/agent.js",
|
|
40
|
+
"verify:local": "npm run build && node ./dist/cli.js verify --no-build --bundle ./dist/agent.js",
|
|
41
|
+
"verify:local:only": "node ./dist/cli.js verify --no-build --bundle ./dist/agent.js",
|
|
42
|
+
"live-test:models": "bash ./scripts/select-sherpa-models.sh",
|
|
43
|
+
"live-test:page": "bash ./scripts/live-test-page.sh",
|
|
44
|
+
"live-test:starter": "bash ./scripts/live-test-starter.sh",
|
|
45
|
+
"live-test:stack": "npm run live-test:stack:echo",
|
|
46
|
+
"live-test:stack:echo": "LIVE_TEST_AGENT_ENTRY=examples/agent.ts LIVE_TEST_PAGE_PATH=/examples/live-test/index.html LIVE_TEST_SESSION_MODE=voice bash ./scripts/live-test-stack.sh",
|
|
47
|
+
"live-test:stack:game": "LIVE_TEST_AGENT_ENTRY=templates/game-sync.ts LIVE_TEST_PAGE_PATH=/examples/live-test/game-sync.html LIVE_TEST_SESSION_MODE=data-only bash ./scripts/live-test-stack.sh",
|
|
36
48
|
"prepublishOnly": "npm run build"
|
|
37
49
|
},
|
|
38
50
|
"repository": {
|
|
@@ -63,8 +75,11 @@
|
|
|
63
75
|
"@node-webrtc-rust/sdk": ">=0.6.5"
|
|
64
76
|
},
|
|
65
77
|
"devDependencies": {
|
|
78
|
+
"@node-webrtc-rust/helpers": "0.6.5",
|
|
66
79
|
"@node-webrtc-rust/sdk": "0.6.5",
|
|
80
|
+
"@node-webrtc-rust/signaling": "0.6.5",
|
|
67
81
|
"@types/node": "^22.10.0",
|
|
82
|
+
"http-server": "^14.1.1",
|
|
68
83
|
"tsx": "^4.19.2",
|
|
69
84
|
"typescript": "^5.7.0",
|
|
70
85
|
"vitest": "^2.1.8"
|
package/templates/README.md
CHANGED
|
@@ -46,3 +46,21 @@ npx @voicethere/agent verify
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
**Voice E2E:** host with the VoiceThere agent runner (platform or internal deployment) — set `AGENT_BUNDLE_PATH` to your built `dist/agent.js`.
|
|
49
|
+
|
|
50
|
+
## `game-sync.ts`
|
|
51
|
+
|
|
52
|
+
Authoritative multi-object sync sample for real-time games/simulations:
|
|
53
|
+
|
|
54
|
+
- register tracked objects via control DC (`{ type: "register" }`)
|
|
55
|
+
- receive `register_ack` + `object_registered` ownership notifications
|
|
56
|
+
- run server-authoritative simulation (position + velocity) at 60Hz
|
|
57
|
+
- resolve wall bounce + object-object collisions on the server
|
|
58
|
+
- broadcast world-state snapshots to clients over binary sync channel (9-float records)
|
|
59
|
+
- ignore client binary writes by default (safe base for adding intent/input messages later)
|
|
60
|
+
- reuse freed slots on leave to keep world state compact
|
|
61
|
+
|
|
62
|
+
Build:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx @voicethere/agent build --entry templates/game-sync.ts
|
|
66
|
+
```
|
package/templates/game-sync.ts
CHANGED
|
@@ -1,68 +1,394 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Multiplayer object-sync template with ownership checks.
|
|
3
|
+
*
|
|
4
|
+
* World layout:
|
|
5
|
+
* - one global Float32Array
|
|
6
|
+
* - each tracked object uses exactly 9 floats:
|
|
7
|
+
* [objectId, posX, posY, posZ, posW, dirX, dirY, dirZ, dirW]
|
|
8
|
+
*
|
|
9
|
+
* Control messages:
|
|
10
|
+
* - `{ type: "register" }` -> allocates (or reuses) one 9-float slot
|
|
11
|
+
* - server replies `{ type: "register_ack", objectId }`
|
|
12
|
+
*
|
|
13
|
+
* Simulation:
|
|
14
|
+
* - server-authoritative movement at 60Hz
|
|
15
|
+
* - wall bounce + object-object elastic collisions on server
|
|
16
|
+
* - clients render server snapshots; client binary writes are ignored
|
|
17
|
+
*
|
|
18
|
+
* Broadcast:
|
|
19
|
+
* - 60Hz world-state broadcast starts when at least 1 client is connected
|
|
20
|
+
* - stops when connected client count drops below 1
|
|
3
21
|
*
|
|
4
22
|
* Build:
|
|
5
23
|
* npx @voicethere/agent build --entry templates/game-sync.ts
|
|
6
24
|
*/
|
|
7
25
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
type DataChannelContext,
|
|
26
|
+
agentLog,
|
|
27
|
+
defineAgent,
|
|
28
|
+
sendBinaryToClient,
|
|
29
|
+
sendToClient,
|
|
13
30
|
} from "@voicethere/agent";
|
|
14
31
|
|
|
15
|
-
|
|
16
|
-
const
|
|
32
|
+
const OBJECT_STRIDE = 9;
|
|
33
|
+
const BROADCAST_HZ = 60;
|
|
34
|
+
const BROADCAST_INTERVAL_MS = Math.floor(1000 / BROADCAST_HZ);
|
|
35
|
+
const BOARD_WIDTH = 1280;
|
|
36
|
+
const BOARD_HEIGHT = 720;
|
|
37
|
+
const OBJECT_RADIUS = 25;
|
|
38
|
+
const MIN_SPEED = 90;
|
|
39
|
+
const MAX_SPEED = 180;
|
|
40
|
+
const COLLISION_RESTITUTION = 1.0;
|
|
41
|
+
|
|
42
|
+
const connectedSessions = new Set<string>();
|
|
43
|
+
const objectOwners = new Map<number, string>(); // objectId -> sessionId
|
|
44
|
+
const sessionObjects = new Map<string, Set<number>>(); // sessionId -> owned objectIds
|
|
45
|
+
// Slots we can recycle. Keeping a free-list avoids unbounded array growth when
|
|
46
|
+
// clients churn (join/leave repeatedly).
|
|
47
|
+
const freeSlots: number[] = [];
|
|
48
|
+
|
|
49
|
+
let worldState = new Float32Array(0);
|
|
50
|
+
let broadcastTimer: NodeJS.Timeout | null = null;
|
|
51
|
+
|
|
52
|
+
interface TrackedObjectInfo {
|
|
53
|
+
objectId: number;
|
|
54
|
+
ownerSessionId: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function rand(min: number, max: number): number {
|
|
58
|
+
return min + Math.random() * (max - min);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function randomVelocity(): number {
|
|
62
|
+
return (Math.random() < 0.5 ? -1 : 1) * rand(MIN_SPEED, MAX_SPEED);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function slotToObjectId(slot: number): number {
|
|
66
|
+
// Object ids are 1-based so 0 can represent "unused".
|
|
67
|
+
return slot + 1;
|
|
68
|
+
}
|
|
17
69
|
|
|
18
|
-
function
|
|
19
|
-
|
|
70
|
+
function objectIdToSlot(objectId: number): number {
|
|
71
|
+
// Inverse of slotToObjectId().
|
|
72
|
+
return objectId - 1;
|
|
20
73
|
}
|
|
21
74
|
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
75
|
+
function markSlotFree(slot: number): void {
|
|
76
|
+
// Zero the entire record. Slot is still allocated in array length terms,
|
|
77
|
+
// but logically available for reuse.
|
|
78
|
+
const start = slot * OBJECT_STRIDE;
|
|
79
|
+
for (let i = 0; i < OBJECT_STRIDE; i += 1) {
|
|
80
|
+
worldState[start + i] = 0;
|
|
81
|
+
}
|
|
28
82
|
}
|
|
29
83
|
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
84
|
+
function allocateSlot(): number {
|
|
85
|
+
// Prefer recycling old slots before growing worldState.
|
|
86
|
+
const reused = freeSlots.shift();
|
|
87
|
+
if (reused !== undefined) return reused;
|
|
88
|
+
|
|
89
|
+
// Grow by exactly one object record (9 floats).
|
|
90
|
+
const next = new Float32Array(worldState.length + OBJECT_STRIDE);
|
|
91
|
+
next.set(worldState);
|
|
92
|
+
worldState = next;
|
|
93
|
+
return worldState.length / OBJECT_STRIDE - 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function attachObjectToSession(sessionId: string, objectId: number): void {
|
|
97
|
+
// Tracks ownership in both directions so validation and cleanup are O(1).
|
|
98
|
+
let owned = sessionObjects.get(sessionId);
|
|
99
|
+
if (!owned) {
|
|
100
|
+
owned = new Set<number>();
|
|
101
|
+
sessionObjects.set(sessionId, owned);
|
|
102
|
+
}
|
|
103
|
+
owned.add(objectId);
|
|
104
|
+
objectOwners.set(objectId, sessionId);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function releaseObject(objectId: number): void {
|
|
108
|
+
// Remove reverse-ownership references first.
|
|
109
|
+
const owner = objectOwners.get(objectId);
|
|
110
|
+
if (owner) {
|
|
111
|
+
const owned = sessionObjects.get(owner);
|
|
112
|
+
owned?.delete(objectId);
|
|
113
|
+
if (owned && owned.size === 0) {
|
|
114
|
+
sessionObjects.delete(owner);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
objectOwners.delete(objectId);
|
|
119
|
+
|
|
120
|
+
const slot = objectIdToSlot(objectId);
|
|
121
|
+
if (slot < 0) return;
|
|
122
|
+
if (slot >= worldState.length / OBJECT_STRIDE) return;
|
|
123
|
+
|
|
124
|
+
// Free slot contents and push slot into free-list for future register() calls.
|
|
125
|
+
markSlotFree(slot);
|
|
126
|
+
if (!freeSlots.includes(slot)) {
|
|
127
|
+
freeSlots.push(slot);
|
|
128
|
+
freeSlots.sort((a, b) => a - b);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function registerObject(sessionId: string): number {
|
|
133
|
+
// Allocate (or reuse) one slot and stamp object id plus initial state.
|
|
134
|
+
const slot = allocateSlot();
|
|
135
|
+
const objectId = slotToObjectId(slot);
|
|
136
|
+
const start = slot * OBJECT_STRIDE;
|
|
137
|
+
worldState[start] = objectId;
|
|
138
|
+
worldState[start + 1] = rand(OBJECT_RADIUS, BOARD_WIDTH - OBJECT_RADIUS);
|
|
139
|
+
worldState[start + 2] = rand(OBJECT_RADIUS, BOARD_HEIGHT - OBJECT_RADIUS);
|
|
140
|
+
worldState[start + 3] = 0;
|
|
141
|
+
worldState[start + 4] = 1;
|
|
142
|
+
worldState[start + 5] = randomVelocity();
|
|
143
|
+
worldState[start + 6] = randomVelocity();
|
|
144
|
+
worldState[start + 7] = 0;
|
|
145
|
+
worldState[start + 8] = 0;
|
|
146
|
+
attachObjectToSession(sessionId, objectId);
|
|
147
|
+
return objectId;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function parseRegisterCommand(message: unknown): boolean {
|
|
151
|
+
if (!message || typeof message !== "object") return false;
|
|
152
|
+
const record = message as { type?: unknown };
|
|
153
|
+
return record.type === "register";
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function parseChatCommand(
|
|
157
|
+
message: unknown,
|
|
158
|
+
): { text: string } | null {
|
|
159
|
+
if (!message || typeof message !== "object") return null;
|
|
160
|
+
const record = message as { type?: unknown; text?: unknown };
|
|
161
|
+
if (record.type !== "chat" || typeof record.text !== "string") return null;
|
|
162
|
+
const text = record.text.trim();
|
|
163
|
+
if (!text) return null;
|
|
164
|
+
return {text};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function trackedObjectsSnapshot(): TrackedObjectInfo[] {
|
|
168
|
+
const objects: TrackedObjectInfo[] = [];
|
|
169
|
+
for (const [objectId, ownerSessionId] of objectOwners) {
|
|
170
|
+
objects.push({objectId, ownerSessionId});
|
|
171
|
+
}
|
|
172
|
+
objects.sort((a, b) => a.objectId - b.objectId);
|
|
173
|
+
return objects;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function notifyObjectRegistered(objectId: number, ownerSessionId: string): void {
|
|
177
|
+
for (const sessionId of connectedSessions) {
|
|
178
|
+
if (sessionId === ownerSessionId) continue;
|
|
179
|
+
sendToClient(sessionId, {
|
|
180
|
+
type: "object_registered",
|
|
181
|
+
objectId,
|
|
182
|
+
ownerSessionId,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function notifyObjectReleased(objectId: number, ownerSessionId: string): void {
|
|
188
|
+
for (const sessionId of connectedSessions) {
|
|
189
|
+
if (sessionId === ownerSessionId) continue;
|
|
190
|
+
sendToClient(sessionId, {
|
|
191
|
+
type: "object_released",
|
|
192
|
+
objectId,
|
|
193
|
+
ownerSessionId,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function broadcastWorldState(): void {
|
|
199
|
+
if (connectedSessions.size === 0) return;
|
|
200
|
+
// Copy to a detached buffer so downstream sends cannot observe mutations
|
|
201
|
+
// from subsequent writes in the same event loop tick.
|
|
202
|
+
const payload = Buffer.from(worldState.buffer.slice(0));
|
|
203
|
+
for (const sessionId of connectedSessions) {
|
|
204
|
+
sendBinaryToClient(sessionId, payload, "sync");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function simulateWorldStep(dtSec: number): void {
|
|
209
|
+
const activeObjectIds = [...objectOwners.keys()];
|
|
210
|
+
for (const objectId of activeObjectIds) {
|
|
211
|
+
const slot = objectIdToSlot(objectId);
|
|
212
|
+
const start = slot * OBJECT_STRIDE;
|
|
213
|
+
if (start < 0 || start + OBJECT_STRIDE > worldState.length) continue;
|
|
214
|
+
|
|
215
|
+
let x = worldState[start + 1] ?? 0;
|
|
216
|
+
let y = worldState[start + 2] ?? 0;
|
|
217
|
+
let vx = worldState[start + 5] ?? 0;
|
|
218
|
+
let vy = worldState[start + 6] ?? 0;
|
|
219
|
+
|
|
220
|
+
x += vx * dtSec;
|
|
221
|
+
y += vy * dtSec;
|
|
222
|
+
|
|
223
|
+
if (x < OBJECT_RADIUS || x > BOARD_WIDTH - OBJECT_RADIUS) {
|
|
224
|
+
vx *= -1;
|
|
225
|
+
x = Math.max(OBJECT_RADIUS, Math.min(BOARD_WIDTH - OBJECT_RADIUS, x));
|
|
226
|
+
}
|
|
227
|
+
if (y < OBJECT_RADIUS || y > BOARD_HEIGHT - OBJECT_RADIUS) {
|
|
228
|
+
vy *= -1;
|
|
229
|
+
y = Math.max(OBJECT_RADIUS, Math.min(BOARD_HEIGHT - OBJECT_RADIUS, y));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
worldState[start + 1] = x;
|
|
233
|
+
worldState[start + 2] = y;
|
|
234
|
+
worldState[start + 5] = vx;
|
|
235
|
+
worldState[start + 6] = vy;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
for (let i = 0; i < activeObjectIds.length; i += 1) {
|
|
239
|
+
const aId = activeObjectIds[i];
|
|
240
|
+
const aSlot = objectIdToSlot(aId);
|
|
241
|
+
const aStart = aSlot * OBJECT_STRIDE;
|
|
242
|
+
if (aStart < 0 || aStart + OBJECT_STRIDE > worldState.length) continue;
|
|
243
|
+
for (let j = i + 1; j < activeObjectIds.length; j += 1) {
|
|
244
|
+
const bId = activeObjectIds[j];
|
|
245
|
+
const bSlot = objectIdToSlot(bId);
|
|
246
|
+
const bStart = bSlot * OBJECT_STRIDE;
|
|
247
|
+
if (bStart < 0 || bStart + OBJECT_STRIDE > worldState.length) continue;
|
|
248
|
+
|
|
249
|
+
let ax = worldState[aStart + 1] ?? 0;
|
|
250
|
+
let ay = worldState[aStart + 2] ?? 0;
|
|
251
|
+
let avx = worldState[aStart + 5] ?? 0;
|
|
252
|
+
let avy = worldState[aStart + 6] ?? 0;
|
|
253
|
+
let bx = worldState[bStart + 1] ?? 0;
|
|
254
|
+
let by = worldState[bStart + 2] ?? 0;
|
|
255
|
+
let bvx = worldState[bStart + 5] ?? 0;
|
|
256
|
+
let bvy = worldState[bStart + 6] ?? 0;
|
|
257
|
+
|
|
258
|
+
let dx = bx - ax;
|
|
259
|
+
let dy = by - ay;
|
|
260
|
+
let distSq = dx * dx + dy * dy;
|
|
261
|
+
const minDist = OBJECT_RADIUS * 2;
|
|
262
|
+
const minDistSq = minDist * minDist;
|
|
263
|
+
if (!(distSq > 0 && distSq < minDistSq)) continue;
|
|
264
|
+
|
|
265
|
+
let dist = Math.sqrt(distSq);
|
|
266
|
+
if (dist === 0) {
|
|
267
|
+
// Deterministic fallback axis when centers overlap exactly.
|
|
268
|
+
dx = 1;
|
|
269
|
+
dy = 0;
|
|
270
|
+
dist = 1;
|
|
271
|
+
distSq = 1;
|
|
272
|
+
}
|
|
273
|
+
const nx = dx / dist;
|
|
274
|
+
const ny = dy / dist;
|
|
275
|
+
|
|
276
|
+
// Positional correction prevents objects from remaining overlapped.
|
|
277
|
+
const overlap = minDist - dist;
|
|
278
|
+
const half = overlap * 0.5;
|
|
279
|
+
ax -= nx * half;
|
|
280
|
+
ay -= ny * half;
|
|
281
|
+
bx += nx * half;
|
|
282
|
+
by += ny * half;
|
|
283
|
+
|
|
284
|
+
const rvx = bvx - avx;
|
|
285
|
+
const rvy = bvy - avy;
|
|
286
|
+
const velAlongNormal = rvx * nx + rvy * ny;
|
|
287
|
+
if (velAlongNormal < 0) {
|
|
288
|
+
const impulse = (-(1 + COLLISION_RESTITUTION) * velAlongNormal) / 2;
|
|
289
|
+
avx -= impulse * nx;
|
|
290
|
+
avy -= impulse * ny;
|
|
291
|
+
bvx += impulse * nx;
|
|
292
|
+
bvy += impulse * ny;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
worldState[aStart + 1] = Math.max(OBJECT_RADIUS, Math.min(BOARD_WIDTH - OBJECT_RADIUS, ax));
|
|
296
|
+
worldState[aStart + 2] = Math.max(OBJECT_RADIUS, Math.min(BOARD_HEIGHT - OBJECT_RADIUS, ay));
|
|
297
|
+
worldState[aStart + 5] = avx;
|
|
298
|
+
worldState[aStart + 6] = avy;
|
|
299
|
+
worldState[bStart + 1] = Math.max(OBJECT_RADIUS, Math.min(BOARD_WIDTH - OBJECT_RADIUS, bx));
|
|
300
|
+
worldState[bStart + 2] = Math.max(OBJECT_RADIUS, Math.min(BOARD_HEIGHT - OBJECT_RADIUS, by));
|
|
301
|
+
worldState[bStart + 5] = bvx;
|
|
302
|
+
worldState[bStart + 6] = bvy;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function startBroadcastLoopIfNeeded(): void {
|
|
308
|
+
if (broadcastTimer) return;
|
|
309
|
+
if (connectedSessions.size < 1) return;
|
|
310
|
+
|
|
311
|
+
broadcastTimer = setInterval(() => {
|
|
312
|
+
if (connectedSessions.size < 1) {
|
|
313
|
+
if (broadcastTimer) {
|
|
314
|
+
clearInterval(broadcastTimer);
|
|
315
|
+
broadcastTimer = null;
|
|
316
|
+
}
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
simulateWorldStep(1 / BROADCAST_HZ);
|
|
320
|
+
broadcastWorldState();
|
|
321
|
+
}, BROADCAST_INTERVAL_MS);
|
|
322
|
+
|
|
323
|
+
agentLog("info", `world loop started (${BROADCAST_HZ}Hz)`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function stopBroadcastLoopIfNeeded(): void {
|
|
327
|
+
if (connectedSessions.size >= 1) return;
|
|
328
|
+
if (!broadcastTimer) return;
|
|
329
|
+
clearInterval(broadcastTimer);
|
|
330
|
+
broadcastTimer = null;
|
|
331
|
+
agentLog("info", "world loop stopped");
|
|
43
332
|
}
|
|
44
333
|
|
|
45
334
|
defineAgent({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
335
|
+
onClientJoin({sessionId}) {
|
|
336
|
+
connectedSessions.add(sessionId);
|
|
337
|
+
startBroadcastLoopIfNeeded();
|
|
338
|
+
// New client receives the current ownership map so it can assign stable
|
|
339
|
+
// colors per owner and immediately render known tracked objects.
|
|
340
|
+
sendToClient(sessionId, {
|
|
341
|
+
type: "world_snapshot",
|
|
342
|
+
objects: trackedObjectsSnapshot(),
|
|
343
|
+
});
|
|
344
|
+
agentLog("info", `join ${sessionId} connected=${connectedSessions.size}`);
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
onClientLeave({sessionId}) {
|
|
348
|
+
connectedSessions.delete(sessionId);
|
|
349
|
+
|
|
350
|
+
const owned = sessionObjects.get(sessionId);
|
|
351
|
+
if (owned) {
|
|
352
|
+
for (const objectId of [...owned]) {
|
|
353
|
+
notifyObjectReleased(objectId, sessionId);
|
|
354
|
+
releaseObject(objectId);
|
|
355
|
+
}
|
|
356
|
+
sessionObjects.delete(sessionId);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
stopBroadcastLoopIfNeeded();
|
|
360
|
+
agentLog(
|
|
361
|
+
"info",
|
|
362
|
+
`leave ${sessionId} connected=${connectedSessions.size} worldFloats=${worldState.length} freeSlots=${freeSlots.length}`,
|
|
363
|
+
);
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
onDataChannelMessage(ctx) {
|
|
367
|
+
// Register is a control-plane message over JSON data channel.
|
|
368
|
+
// Binary channel is reserved for high-frequency state deltas.
|
|
369
|
+
if (parseRegisterCommand(ctx.message)) {
|
|
370
|
+
const objectId = registerObject(ctx.sessionId);
|
|
371
|
+
sendToClient(ctx.sessionId, {type: "register_ack", objectId});
|
|
372
|
+
notifyObjectRegistered(objectId, ctx.sessionId);
|
|
373
|
+
agentLog("info", `register session=${ctx.sessionId} objectId=${objectId}`);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Optional chat mode for debugging/coordinating live test sessions.
|
|
378
|
+
const chat = parseChatCommand(ctx.message);
|
|
379
|
+
if (!chat) return;
|
|
380
|
+
for (const sessionId of connectedSessions) {
|
|
381
|
+
sendToClient(sessionId, {
|
|
382
|
+
type: "chat_broadcast",
|
|
383
|
+
senderSessionId: ctx.sessionId,
|
|
384
|
+
text: chat.text,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
onDataChannelBinary(ctx) {
|
|
390
|
+
// Server-authoritative simulation: ignore client binary state writes.
|
|
391
|
+
// Keeping the hook makes intent-based controls easy to add later.
|
|
392
|
+
void ctx;
|
|
393
|
+
},
|
|
68
394
|
});
|