@voicethere/agent 0.5.6 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/game-sync/agent.js +64 -31
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +14 -0
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/registry.d.ts.map +1 -1
- package/dist/templates/registry.js +1 -0
- package/dist/templates/registry.js.map +1 -1
- package/dist/templates/voice-showcase/agent.js +41 -19
- package/package.json +7 -1
- package/templates/README.md +2 -2
- package/templates/game-sync-world-layout.ts +45 -0
- package/templates/game-sync.ts +39 -24
- package/templates/voice-showcase/agent.ts +21 -22
- package/templates/voice-showcase/delivery.ts +57 -0
|
@@ -11460,16 +11460,6 @@ function writeObjectSlot(world, slot, objectId, posX, posY, posZ, posW, dirX, di
|
|
|
11460
11460
|
world[start + 7] = dirZ;
|
|
11461
11461
|
world[start + 8] = dirW;
|
|
11462
11462
|
}
|
|
11463
|
-
function preserveEmptySlots(simulated, authoritative) {
|
|
11464
|
-
for (let slot = 0; slot < MAX_LIVE_OBJECTS; slot += 1) {
|
|
11465
|
-
if (readSlotObjectId(authoritative, slot) === 0) {
|
|
11466
|
-
markSlotFree(simulated, slot);
|
|
11467
|
-
}
|
|
11468
|
-
}
|
|
11469
|
-
}
|
|
11470
|
-
function commitSimulatedWorld(simulated, latestRedis) {
|
|
11471
|
-
preserveEmptySlots(simulated, latestRedis);
|
|
11472
|
-
}
|
|
11473
11463
|
function collectActiveObjectIds(world) {
|
|
11474
11464
|
const ids = [];
|
|
11475
11465
|
for (let slot = 0; slot < MAX_LIVE_OBJECTS; slot += 1) {
|
|
@@ -11480,6 +11470,32 @@ function collectActiveObjectIds(world) {
|
|
|
11480
11470
|
}
|
|
11481
11471
|
return ids;
|
|
11482
11472
|
}
|
|
11473
|
+
function liveWorldSnapshot(world, owners) {
|
|
11474
|
+
const ids = collectActiveObjectIds(world);
|
|
11475
|
+
ids.sort((a, b) => a - b);
|
|
11476
|
+
return ids.map((objectId) => ({
|
|
11477
|
+
objectId,
|
|
11478
|
+
ownerSessionId: owners.get(objectId) ?? ""
|
|
11479
|
+
}));
|
|
11480
|
+
}
|
|
11481
|
+
function planRedisSimTick(options) {
|
|
11482
|
+
if (options.lockAcquired) {
|
|
11483
|
+
return "simulate";
|
|
11484
|
+
}
|
|
11485
|
+
if (options.connectedSessions.size > 0) {
|
|
11486
|
+
return "relay";
|
|
11487
|
+
}
|
|
11488
|
+
return "noop";
|
|
11489
|
+
}
|
|
11490
|
+
function clampSimulationDtSec(elapsedMs, fallbackHz) {
|
|
11491
|
+
const minDt = 1 / fallbackHz;
|
|
11492
|
+
const maxDt = 0.05;
|
|
11493
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs <= 0) {
|
|
11494
|
+
return minDt;
|
|
11495
|
+
}
|
|
11496
|
+
const elapsedSec = elapsedMs / 1e3;
|
|
11497
|
+
return Math.min(maxDt, Math.max(minDt, elapsedSec));
|
|
11498
|
+
}
|
|
11483
11499
|
function normalizeWorldBuffer(raw) {
|
|
11484
11500
|
if (!raw || raw.byteLength === 0) {
|
|
11485
11501
|
return createEmptyWorldBuffer();
|
|
@@ -11718,6 +11734,7 @@ var worldState = createEmptyWorldBuffer();
|
|
|
11718
11734
|
var redis = null;
|
|
11719
11735
|
var broadcastTimer = null;
|
|
11720
11736
|
var worldMutationChain = Promise.resolve();
|
|
11737
|
+
var lastTickTimeMs = 0;
|
|
11721
11738
|
function withWorldMutation(fn) {
|
|
11722
11739
|
const run = worldMutationChain.then(fn);
|
|
11723
11740
|
worldMutationChain = run.then(
|
|
@@ -11902,13 +11919,11 @@ async function unregisterObject(sessionId, objectId) {
|
|
|
11902
11919
|
}
|
|
11903
11920
|
return { ok: true, objectId: target.objectId };
|
|
11904
11921
|
}
|
|
11905
|
-
function
|
|
11906
|
-
const objects =
|
|
11907
|
-
for (const
|
|
11908
|
-
|
|
11922
|
+
function broadcastWorldSnapshot() {
|
|
11923
|
+
const objects = liveWorldSnapshot(worldState, objectOwners);
|
|
11924
|
+
for (const sessionId of connectedSessions) {
|
|
11925
|
+
sendToClient(sessionId, { type: "world_snapshot", objects });
|
|
11909
11926
|
}
|
|
11910
|
-
objects.sort((a, b) => a.objectId - b.objectId);
|
|
11911
|
-
return objects;
|
|
11912
11927
|
}
|
|
11913
11928
|
function notifyObjectRegistered(objectId, ownerSessionId) {
|
|
11914
11929
|
for (const sessionId of connectedSessions) {
|
|
@@ -11952,31 +11967,44 @@ async function saveWorldToRedis(world) {
|
|
|
11952
11967
|
await redis.setBuffer(REDIS_WORLD_KEY, copyWorldBuffer(world));
|
|
11953
11968
|
}
|
|
11954
11969
|
async function runSimulationTick() {
|
|
11970
|
+
const now = Date.now();
|
|
11971
|
+
const dt = clampSimulationDtSec(
|
|
11972
|
+
lastTickTimeMs === 0 ? 0 : now - lastTickTimeMs,
|
|
11973
|
+
BROADCAST_HZ
|
|
11974
|
+
);
|
|
11975
|
+
lastTickTimeMs = now;
|
|
11955
11976
|
if (!redis) {
|
|
11956
11977
|
await withWorldMutation(async () => {
|
|
11957
|
-
|
|
11958
|
-
simulateWorldStep(worldState, 1 / BROADCAST_HZ, activeObjectIds);
|
|
11978
|
+
simulateWorldStep(worldState, dt, collectActiveObjectIds(worldState));
|
|
11959
11979
|
});
|
|
11960
11980
|
broadcastWorldBuffer(worldState);
|
|
11961
11981
|
return;
|
|
11962
11982
|
}
|
|
11963
11983
|
await withWorldMutation(async () => {
|
|
11964
|
-
await withRedisSimLock(
|
|
11984
|
+
const lockResult = await withRedisSimLock(
|
|
11965
11985
|
async () => {
|
|
11966
|
-
const
|
|
11967
|
-
const activeObjectIds = collectActiveObjectIds(
|
|
11968
|
-
simulateWorldStep(
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11986
|
+
const world = await loadWorldFromRedis();
|
|
11987
|
+
const activeObjectIds = collectActiveObjectIds(world);
|
|
11988
|
+
simulateWorldStep(world, dt, activeObjectIds);
|
|
11989
|
+
await saveWorldToRedis(world);
|
|
11990
|
+
worldState = world;
|
|
11991
|
+
broadcastWorldBuffer(world);
|
|
11992
|
+
return true;
|
|
11973
11993
|
},
|
|
11974
11994
|
{ retryUntilAcquired: false }
|
|
11975
11995
|
);
|
|
11996
|
+
if (lockResult === null) {
|
|
11997
|
+
const plan = planRedisSimTick({
|
|
11998
|
+
lockAcquired: false,
|
|
11999
|
+
connectedSessions
|
|
12000
|
+
});
|
|
12001
|
+
if (plan === "relay") {
|
|
12002
|
+
const world = await loadWorldFromRedis();
|
|
12003
|
+
worldState = world;
|
|
12004
|
+
broadcastWorldBuffer(world);
|
|
12005
|
+
}
|
|
12006
|
+
}
|
|
11976
12007
|
});
|
|
11977
|
-
const world = await loadWorldFromRedis();
|
|
11978
|
-
worldState = world;
|
|
11979
|
-
broadcastWorldBuffer(world);
|
|
11980
12008
|
}
|
|
11981
12009
|
function startBroadcastLoopIfNeeded() {
|
|
11982
12010
|
if (broadcastTimer) return;
|
|
@@ -12033,12 +12061,15 @@ defineAgent({
|
|
|
12033
12061
|
startBroadcastLoopIfNeeded();
|
|
12034
12062
|
agentLog("info", "game-sync agent connected to project Redis world buffer");
|
|
12035
12063
|
},
|
|
12036
|
-
onClientJoin({ sessionId }) {
|
|
12064
|
+
async onClientJoin({ sessionId }) {
|
|
12037
12065
|
connectedSessions.add(sessionId);
|
|
12038
12066
|
startBroadcastLoopIfNeeded();
|
|
12067
|
+
if (redis) {
|
|
12068
|
+
worldState = await loadWorldFromRedis();
|
|
12069
|
+
}
|
|
12039
12070
|
sendToClient(sessionId, {
|
|
12040
12071
|
type: "world_snapshot",
|
|
12041
|
-
objects:
|
|
12072
|
+
objects: liveWorldSnapshot(worldState, objectOwners)
|
|
12042
12073
|
});
|
|
12043
12074
|
agentLog("info", `join ${sessionId} connected=${connectedSessions.size}`);
|
|
12044
12075
|
},
|
|
@@ -12081,6 +12112,7 @@ defineAgent({
|
|
|
12081
12112
|
}
|
|
12082
12113
|
sendToClient(ctx.sessionId, { type: "register_ack", objectId });
|
|
12083
12114
|
notifyObjectRegistered(objectId, ctx.sessionId);
|
|
12115
|
+
broadcastWorldSnapshot();
|
|
12084
12116
|
agentLog(
|
|
12085
12117
|
"info",
|
|
12086
12118
|
`register session=${ctx.sessionId} objectId=${objectId}`
|
|
@@ -12105,6 +12137,7 @@ defineAgent({
|
|
|
12105
12137
|
type: "unregister_ack",
|
|
12106
12138
|
objectId: result.objectId
|
|
12107
12139
|
});
|
|
12140
|
+
broadcastWorldSnapshot();
|
|
12108
12141
|
agentLog(
|
|
12109
12142
|
"info",
|
|
12110
12143
|
`unregister_ack session=${ctx.sessionId} objectId=${result.objectId}`
|
|
@@ -13,6 +13,8 @@ export declare function listTemplates(filter?: ListTemplatesFilter): AgentTempla
|
|
|
13
13
|
export declare function getTemplate(id: string): AgentTemplateDefinition;
|
|
14
14
|
export declare function resolveTemplateEntryPath(id: string): string;
|
|
15
15
|
export declare function loadTemplateSources(id: string): TemplateSourceFile[];
|
|
16
|
+
/** Like {@link loadTemplateSources}, but paths match registry `sourceFiles` (e.g. `voice-showcase/agent.ts`). */
|
|
17
|
+
export declare function loadTemplateWorkspaceSources(id: string): TemplateSourceFile[];
|
|
16
18
|
export declare function hasSeedBundle(id: string): boolean;
|
|
17
19
|
export declare function loadTemplateBundle(id: string): Buffer;
|
|
18
20
|
export declare function buildSeedTemplateBundles(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,uBAAuB,EACvB,eAAe,EACf,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAaD,wBAAgB,aAAa,CAC3B,MAAM,CAAC,EAAE,mBAAmB,GAC3B,uBAAuB,EAAE,CAK3B;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAE/D;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAO3D;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAYpE;AAMD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAMjD;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAYrD;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAS9D"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,uBAAuB,EACvB,eAAe,EACf,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAaD,wBAAgB,aAAa,CAC3B,MAAM,CAAC,EAAE,mBAAmB,GAC3B,uBAAuB,EAAE,CAK3B;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAE/D;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAO3D;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAYpE;AAED,iHAAiH;AACjH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAY7E;AAMD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAMjD;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAYrD;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAS9D"}
|
package/dist/templates/index.js
CHANGED
|
@@ -43,6 +43,20 @@ export function loadTemplateSources(id) {
|
|
|
43
43
|
};
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
+
/** Like {@link loadTemplateSources}, but paths match registry `sourceFiles` (e.g. `voice-showcase/agent.ts`). */
|
|
47
|
+
export function loadTemplateWorkspaceSources(id) {
|
|
48
|
+
const template = getTemplateById(id);
|
|
49
|
+
return template.sourceFiles.map((sourceFile) => {
|
|
50
|
+
const absolutePath = join(TEMPLATES_DIR, sourceFile);
|
|
51
|
+
if (!existsSync(absolutePath)) {
|
|
52
|
+
throw new Error(`Template source not found for ${id}: ${absolutePath}`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
path: sourceFile,
|
|
56
|
+
content: readFileSync(absolutePath, "utf8"),
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
46
60
|
function seedBundlePath(id) {
|
|
47
61
|
return join(PACKAGE_ROOT, "dist", "templates", id, "agent.js");
|
|
48
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,EA6HpD,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAMrE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,eAAe,CAEnE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAMnE;AAED,wBAAgB,yBAAyB,IAAI,uBAAuB,EAAE,CAErE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1317,6 +1317,36 @@ async function resolveWeatherTurn(state, city, country, fetchFn) {
|
|
|
1317
1317
|
}
|
|
1318
1318
|
}
|
|
1319
1319
|
|
|
1320
|
+
// templates/voice-showcase/delivery.ts
|
|
1321
|
+
function spokenThenPlayOps(messages, speakLines) {
|
|
1322
|
+
const ops = [];
|
|
1323
|
+
for (const message of messages) {
|
|
1324
|
+
ops.push({ kind: "send", message });
|
|
1325
|
+
}
|
|
1326
|
+
for (const text of speakLines) {
|
|
1327
|
+
ops.push({ kind: "play", text });
|
|
1328
|
+
}
|
|
1329
|
+
return ops;
|
|
1330
|
+
}
|
|
1331
|
+
function greetingOps(sessionId, greeting) {
|
|
1332
|
+
return spokenThenPlayOps(
|
|
1333
|
+
[
|
|
1334
|
+
{ type: "agent_event", event: "session_start", sessionId },
|
|
1335
|
+
{ type: "chat_reply", text: greeting }
|
|
1336
|
+
],
|
|
1337
|
+
[greeting]
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
function applyOutboundOps(sessionId, ops, deps) {
|
|
1341
|
+
for (const op of ops) {
|
|
1342
|
+
if (op.kind === "send") {
|
|
1343
|
+
deps.sendToClient(sessionId, op.message);
|
|
1344
|
+
} else {
|
|
1345
|
+
deps.speak(sessionId, op.text);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1320
1350
|
// templates/voice-showcase/agent.ts
|
|
1321
1351
|
var sessions = /* @__PURE__ */ new Map();
|
|
1322
1352
|
function getState(sessionId) {
|
|
@@ -1335,20 +1365,16 @@ function relaySpeechEvent(sessionId, event) {
|
|
|
1335
1365
|
raw: event
|
|
1336
1366
|
});
|
|
1337
1367
|
}
|
|
1338
|
-
function
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
for (const line of lines) {
|
|
1345
|
-
speak(sessionId, line);
|
|
1346
|
-
}
|
|
1368
|
+
function deliverSpokenThenPlay(sessionId, result) {
|
|
1369
|
+
applyOutboundOps(
|
|
1370
|
+
sessionId,
|
|
1371
|
+
spokenThenPlayOps(result.messages, result.speakLines),
|
|
1372
|
+
{ sendToClient, speak }
|
|
1373
|
+
);
|
|
1347
1374
|
}
|
|
1348
1375
|
async function applyTurn(sessionId, result) {
|
|
1349
1376
|
sessions.set(sessionId, result.state);
|
|
1350
|
-
|
|
1351
|
-
deliverMessages(sessionId, result.messages);
|
|
1377
|
+
deliverSpokenThenPlay(sessionId, result);
|
|
1352
1378
|
if (result.pendingWeather) {
|
|
1353
1379
|
const weatherResult = await resolveWeatherTurn(
|
|
1354
1380
|
result.state,
|
|
@@ -1356,8 +1382,7 @@ async function applyTurn(sessionId, result) {
|
|
|
1356
1382
|
result.pendingWeather.country
|
|
1357
1383
|
);
|
|
1358
1384
|
sessions.set(sessionId, weatherResult.state);
|
|
1359
|
-
|
|
1360
|
-
deliverMessages(sessionId, weatherResult.messages);
|
|
1385
|
+
deliverSpokenThenPlay(sessionId, weatherResult);
|
|
1361
1386
|
}
|
|
1362
1387
|
}
|
|
1363
1388
|
async function onUserText(sessionId, text) {
|
|
@@ -1368,13 +1393,10 @@ async function onUserText(sessionId, text) {
|
|
|
1368
1393
|
defineAgent({
|
|
1369
1394
|
onSessionStart({ sessionId }) {
|
|
1370
1395
|
sessions.set(sessionId, createInitialState());
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
sessionId
|
|
1396
|
+
applyOutboundOps(sessionId, greetingOps(sessionId, GREETING), {
|
|
1397
|
+
sendToClient,
|
|
1398
|
+
speak
|
|
1375
1399
|
});
|
|
1376
|
-
speak(sessionId, GREETING);
|
|
1377
|
-
sendToClient(sessionId, { type: "chat_reply", text: GREETING });
|
|
1378
1400
|
agentLog("info", `voice-showcase session_start ${sessionId}`);
|
|
1379
1401
|
},
|
|
1380
1402
|
onSpeechEvent({ sessionId }, event) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voicethere/agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "VoiceThere customer agent SDK — IPC types and runtime helpers for sandboxed child bundles",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -28,6 +28,12 @@
|
|
|
28
28
|
"require": "./dist/templates/index.js",
|
|
29
29
|
"default": "./dist/templates/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./build": {
|
|
32
|
+
"types": "./dist/build-bundle.d.ts",
|
|
33
|
+
"import": "./dist/build-bundle.js",
|
|
34
|
+
"require": "./dist/build-bundle.js",
|
|
35
|
+
"default": "./dist/build-bundle.js"
|
|
36
|
+
},
|
|
31
37
|
"./templates/redis-sync/world-layout": {
|
|
32
38
|
"types": "./templates/redis-sync/world-layout.ts",
|
|
33
39
|
"import": "./templates/redis-sync/world-layout.ts",
|
package/templates/README.md
CHANGED
|
@@ -63,9 +63,9 @@ When `AGENT_REDIS_URL` is set (project Redis), the world blob is stored at `game
|
|
|
63
63
|
|
|
64
64
|
### `voice-showcase/` (`voice-showcase`)
|
|
65
65
|
|
|
66
|
-
Conversational voice demo for landing and dashboard previews — greets the user, asks for a name, then offers a menu: weather (Open-Meteo, no API key), count 1–10, short recipes, and rotating fun facts. Typed chat and voice finals share the same handler. Sends structured `menu` payloads plus `chat_reply` for the chat log.
|
|
66
|
+
Conversational voice demo for landing and dashboard previews — greets the user, asks for a name, then offers a menu: weather (Open-Meteo, no API key), count 1–10, short recipes, and rotating fun facts. Typed chat and voice finals share the same handler. Sends structured `menu` payloads plus `chat_reply` for the chat log, then triggers TTS play so the client has the spoken text before audio starts.
|
|
67
67
|
|
|
68
|
-
Sources: `voice-showcase/agent.ts` (defineAgent wiring), `conversation.ts` (pure state machine), `weather.ts`, `recipes.ts`, `fun-facts.ts`.
|
|
68
|
+
Sources: `voice-showcase/agent.ts` (defineAgent wiring), `conversation.ts` (pure state machine), `delivery.ts` (send-then-play order), `weather.ts`, `recipes.ts`, `fun-facts.ts`.
|
|
69
69
|
|
|
70
70
|
### `recording-consent/` (`recording-consent`)
|
|
71
71
|
|
|
@@ -162,6 +162,51 @@ export function collectActiveObjectIds(world: Float32Array): number[] {
|
|
|
162
162
|
return ids;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
export interface LiveWorldObjectInfo {
|
|
166
|
+
objectId: number;
|
|
167
|
+
ownerSessionId: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Snapshot occupancy from live world slots; ownerSessionId from map or empty string. */
|
|
171
|
+
export function liveWorldSnapshot(
|
|
172
|
+
world: Float32Array,
|
|
173
|
+
owners: ReadonlyMap<number, string>,
|
|
174
|
+
): LiveWorldObjectInfo[] {
|
|
175
|
+
const ids = collectActiveObjectIds(world);
|
|
176
|
+
ids.sort((a, b) => a - b);
|
|
177
|
+
return ids.map((objectId) => ({
|
|
178
|
+
objectId,
|
|
179
|
+
ownerSessionId: owners.get(objectId) ?? "",
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function planRedisSimTick(options: {
|
|
184
|
+
lockAcquired: boolean;
|
|
185
|
+
connectedSessions: ReadonlySet<string>;
|
|
186
|
+
}): "simulate" | "relay" | "noop" {
|
|
187
|
+
if (options.lockAcquired) {
|
|
188
|
+
return "simulate";
|
|
189
|
+
}
|
|
190
|
+
if (options.connectedSessions.size > 0) {
|
|
191
|
+
return "relay";
|
|
192
|
+
}
|
|
193
|
+
return "noop";
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Finite positive elapsed seconds, clamped to [1/fallbackHz, 0.05]. */
|
|
197
|
+
export function clampSimulationDtSec(
|
|
198
|
+
elapsedMs: number,
|
|
199
|
+
fallbackHz: number,
|
|
200
|
+
): number {
|
|
201
|
+
const minDt = 1 / fallbackHz;
|
|
202
|
+
const maxDt = 0.05;
|
|
203
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs <= 0) {
|
|
204
|
+
return minDt;
|
|
205
|
+
}
|
|
206
|
+
const elapsedSec = elapsedMs / 1000;
|
|
207
|
+
return Math.min(maxDt, Math.max(minDt, elapsedSec));
|
|
208
|
+
}
|
|
209
|
+
|
|
165
210
|
/**
|
|
166
211
|
* Decode a Redis / Node Buffer into a fixed-size world Float32Array.
|
|
167
212
|
*/
|
package/templates/game-sync.ts
CHANGED
|
@@ -61,15 +61,17 @@ import {
|
|
|
61
61
|
simulateWorldStep,
|
|
62
62
|
} from "./game-sync-sim.js";
|
|
63
63
|
import {
|
|
64
|
+
clampSimulationDtSec,
|
|
64
65
|
collectActiveObjectIds,
|
|
65
|
-
commitSimulatedWorld,
|
|
66
66
|
countLiveObjects,
|
|
67
67
|
createEmptyWorldBuffer,
|
|
68
68
|
findFirstEmptySlot,
|
|
69
|
+
liveWorldSnapshot,
|
|
69
70
|
markSlotFree,
|
|
70
71
|
normalizeWorldBuffer,
|
|
71
72
|
objectIdToSlot,
|
|
72
73
|
OBJECT_SLOT_BYTE_LENGTH,
|
|
74
|
+
planRedisSimTick,
|
|
73
75
|
REDIS_SIM_LOCK_KEY,
|
|
74
76
|
REDIS_WORLD_KEY,
|
|
75
77
|
slotToObjectId,
|
|
@@ -92,6 +94,7 @@ let worldState = createEmptyWorldBuffer();
|
|
|
92
94
|
let redis: Redis | null = null;
|
|
93
95
|
let broadcastTimer: NodeJS.Timeout | null = null;
|
|
94
96
|
let worldMutationChain: Promise<void> = Promise.resolve();
|
|
97
|
+
let lastTickTimeMs = 0;
|
|
95
98
|
|
|
96
99
|
function withWorldMutation<T>(fn: () => Promise<T>): Promise<T> {
|
|
97
100
|
const run = worldMutationChain.then(fn);
|
|
@@ -140,11 +143,6 @@ async function withRedisSimLock<T>(
|
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
|
|
143
|
-
interface TrackedObjectInfo {
|
|
144
|
-
objectId: number;
|
|
145
|
-
ownerSessionId: string;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
146
|
function rand(min: number, max: number): number {
|
|
149
147
|
return min + Math.random() * (max - min);
|
|
150
148
|
}
|
|
@@ -315,13 +313,11 @@ async function unregisterObject(
|
|
|
315
313
|
return { ok: true, objectId: target.objectId };
|
|
316
314
|
}
|
|
317
315
|
|
|
318
|
-
function
|
|
319
|
-
const objects
|
|
320
|
-
for (const
|
|
321
|
-
|
|
316
|
+
function broadcastWorldSnapshot(): void {
|
|
317
|
+
const objects = liveWorldSnapshot(worldState, objectOwners);
|
|
318
|
+
for (const sessionId of connectedSessions) {
|
|
319
|
+
sendToClient(sessionId, { type: "world_snapshot", objects });
|
|
322
320
|
}
|
|
323
|
-
objects.sort((a, b) => a.objectId - b.objectId);
|
|
324
|
-
return objects;
|
|
325
321
|
}
|
|
326
322
|
|
|
327
323
|
function notifyObjectRegistered(
|
|
@@ -375,33 +371,47 @@ async function saveWorldToRedis(world: Float32Array): Promise<void> {
|
|
|
375
371
|
}
|
|
376
372
|
|
|
377
373
|
async function runSimulationTick(): Promise<void> {
|
|
374
|
+
const now = Date.now();
|
|
375
|
+
const dt = clampSimulationDtSec(
|
|
376
|
+
lastTickTimeMs === 0 ? 0 : now - lastTickTimeMs,
|
|
377
|
+
BROADCAST_HZ,
|
|
378
|
+
);
|
|
379
|
+
lastTickTimeMs = now;
|
|
380
|
+
|
|
378
381
|
if (!redis) {
|
|
379
382
|
await withWorldMutation(async () => {
|
|
380
|
-
|
|
381
|
-
simulateWorldStep(worldState, 1 / BROADCAST_HZ, activeObjectIds);
|
|
383
|
+
simulateWorldStep(worldState, dt, collectActiveObjectIds(worldState));
|
|
382
384
|
});
|
|
383
385
|
broadcastWorldBuffer(worldState);
|
|
384
386
|
return;
|
|
385
387
|
}
|
|
386
388
|
|
|
387
389
|
await withWorldMutation(async () => {
|
|
388
|
-
await withRedisSimLock(
|
|
390
|
+
const lockResult = await withRedisSimLock(
|
|
389
391
|
async () => {
|
|
390
392
|
const world = await loadWorldFromRedis();
|
|
391
393
|
const activeObjectIds = collectActiveObjectIds(world);
|
|
392
|
-
simulateWorldStep(world,
|
|
393
|
-
const latestRedis = await loadWorldFromRedis();
|
|
394
|
-
commitSimulatedWorld(world, latestRedis);
|
|
394
|
+
simulateWorldStep(world, dt, activeObjectIds);
|
|
395
395
|
await saveWorldToRedis(world);
|
|
396
396
|
worldState = world;
|
|
397
|
+
broadcastWorldBuffer(world);
|
|
398
|
+
return true;
|
|
397
399
|
},
|
|
398
400
|
{ retryUntilAcquired: false },
|
|
399
401
|
);
|
|
400
|
-
});
|
|
401
402
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
403
|
+
if (lockResult === null) {
|
|
404
|
+
const plan = planRedisSimTick({
|
|
405
|
+
lockAcquired: false,
|
|
406
|
+
connectedSessions,
|
|
407
|
+
});
|
|
408
|
+
if (plan === "relay") {
|
|
409
|
+
const world = await loadWorldFromRedis();
|
|
410
|
+
worldState = world;
|
|
411
|
+
broadcastWorldBuffer(world);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
});
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
function startBroadcastLoopIfNeeded(): void {
|
|
@@ -466,12 +476,15 @@ defineAgent({
|
|
|
466
476
|
agentLog("info", "game-sync agent connected to project Redis world buffer");
|
|
467
477
|
},
|
|
468
478
|
|
|
469
|
-
onClientJoin({ sessionId }) {
|
|
479
|
+
async onClientJoin({ sessionId }) {
|
|
470
480
|
connectedSessions.add(sessionId);
|
|
471
481
|
startBroadcastLoopIfNeeded();
|
|
482
|
+
if (redis) {
|
|
483
|
+
worldState = await loadWorldFromRedis();
|
|
484
|
+
}
|
|
472
485
|
sendToClient(sessionId, {
|
|
473
486
|
type: "world_snapshot",
|
|
474
|
-
objects:
|
|
487
|
+
objects: liveWorldSnapshot(worldState, objectOwners),
|
|
475
488
|
});
|
|
476
489
|
agentLog("info", `join ${sessionId} connected=${connectedSessions.size}`);
|
|
477
490
|
},
|
|
@@ -516,6 +529,7 @@ defineAgent({
|
|
|
516
529
|
}
|
|
517
530
|
sendToClient(ctx.sessionId, { type: "register_ack", objectId });
|
|
518
531
|
notifyObjectRegistered(objectId, ctx.sessionId);
|
|
532
|
+
broadcastWorldSnapshot();
|
|
519
533
|
agentLog(
|
|
520
534
|
"info",
|
|
521
535
|
`register session=${ctx.sessionId} objectId=${objectId}`,
|
|
@@ -541,6 +555,7 @@ defineAgent({
|
|
|
541
555
|
type: "unregister_ack",
|
|
542
556
|
objectId: result.objectId,
|
|
543
557
|
});
|
|
558
|
+
broadcastWorldSnapshot();
|
|
544
559
|
agentLog(
|
|
545
560
|
"info",
|
|
546
561
|
`unregister_ack session=${ctx.sessionId} objectId=${result.objectId}`,
|
|
@@ -19,8 +19,13 @@ import {
|
|
|
19
19
|
handleUtterance,
|
|
20
20
|
resolveWeatherTurn,
|
|
21
21
|
type ConversationState,
|
|
22
|
-
type
|
|
22
|
+
type ConversationTurnResult,
|
|
23
23
|
} from "./conversation.js";
|
|
24
|
+
import {
|
|
25
|
+
applyOutboundOps,
|
|
26
|
+
greetingOps,
|
|
27
|
+
spokenThenPlayOps,
|
|
28
|
+
} from "./delivery.js";
|
|
24
29
|
|
|
25
30
|
const sessions = new Map<string, ConversationState>();
|
|
26
31
|
|
|
@@ -42,25 +47,23 @@ function relaySpeechEvent(sessionId: string, event: SpeechEvent): void {
|
|
|
42
47
|
});
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
50
|
+
function deliverSpokenThenPlay(
|
|
51
|
+
sessionId: string,
|
|
52
|
+
result: Pick<ConversationTurnResult, "messages" | "speakLines">,
|
|
53
|
+
): void {
|
|
54
|
+
applyOutboundOps(
|
|
55
|
+
sessionId,
|
|
56
|
+
spokenThenPlayOps(result.messages, result.speakLines),
|
|
57
|
+
{ sendToClient, speak },
|
|
58
|
+
);
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
async function applyTurn(
|
|
58
62
|
sessionId: string,
|
|
59
|
-
result:
|
|
63
|
+
result: ConversationTurnResult,
|
|
60
64
|
): Promise<void> {
|
|
61
65
|
sessions.set(sessionId, result.state);
|
|
62
|
-
|
|
63
|
-
deliverMessages(sessionId, result.messages);
|
|
66
|
+
deliverSpokenThenPlay(sessionId, result);
|
|
64
67
|
|
|
65
68
|
if (result.pendingWeather) {
|
|
66
69
|
const weatherResult = await resolveWeatherTurn(
|
|
@@ -69,8 +72,7 @@ async function applyTurn(
|
|
|
69
72
|
result.pendingWeather.country,
|
|
70
73
|
);
|
|
71
74
|
sessions.set(sessionId, weatherResult.state);
|
|
72
|
-
|
|
73
|
-
deliverMessages(sessionId, weatherResult.messages);
|
|
75
|
+
deliverSpokenThenPlay(sessionId, weatherResult);
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -83,13 +85,10 @@ async function onUserText(sessionId: string, text: string): Promise<void> {
|
|
|
83
85
|
defineAgent({
|
|
84
86
|
onSessionStart({ sessionId }) {
|
|
85
87
|
sessions.set(sessionId, createInitialState());
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
sessionId,
|
|
88
|
+
applyOutboundOps(sessionId, greetingOps(sessionId, GREETING), {
|
|
89
|
+
sendToClient,
|
|
90
|
+
speak,
|
|
90
91
|
});
|
|
91
|
-
speak(sessionId, GREETING);
|
|
92
|
-
sendToClient(sessionId, { type: "chat_reply", text: GREETING });
|
|
93
92
|
agentLog("info", `voice-showcase session_start ${sessionId}`);
|
|
94
93
|
},
|
|
95
94
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice-showcase outbound order: send spoken TTS text to the client first,
|
|
3
|
+
* then trigger TTS play. Parent IPC preserves this order.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { OutboundMessage } from "./conversation.js";
|
|
7
|
+
|
|
8
|
+
export type OutboundOp =
|
|
9
|
+
| { kind: "send"; message: OutboundMessage }
|
|
10
|
+
| { kind: "play"; text: string };
|
|
11
|
+
|
|
12
|
+
export interface OutboundDeps {
|
|
13
|
+
sendToClient: (sessionId: string, payload: unknown) => void;
|
|
14
|
+
speak: (sessionId: string, text: string) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** All DataChannel payloads, then TTS play commands. */
|
|
18
|
+
export function spokenThenPlayOps(
|
|
19
|
+
messages: OutboundMessage[],
|
|
20
|
+
speakLines: string[],
|
|
21
|
+
): OutboundOp[] {
|
|
22
|
+
const ops: OutboundOp[] = [];
|
|
23
|
+
for (const message of messages) {
|
|
24
|
+
ops.push({ kind: "send", message });
|
|
25
|
+
}
|
|
26
|
+
for (const text of speakLines) {
|
|
27
|
+
ops.push({ kind: "play", text });
|
|
28
|
+
}
|
|
29
|
+
return ops;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function greetingOps(
|
|
33
|
+
sessionId: string,
|
|
34
|
+
greeting: string,
|
|
35
|
+
): OutboundOp[] {
|
|
36
|
+
return spokenThenPlayOps(
|
|
37
|
+
[
|
|
38
|
+
{ type: "agent_event", event: "session_start", sessionId },
|
|
39
|
+
{ type: "chat_reply", text: greeting },
|
|
40
|
+
],
|
|
41
|
+
[greeting],
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function applyOutboundOps(
|
|
46
|
+
sessionId: string,
|
|
47
|
+
ops: OutboundOp[],
|
|
48
|
+
deps: OutboundDeps,
|
|
49
|
+
): void {
|
|
50
|
+
for (const op of ops) {
|
|
51
|
+
if (op.kind === "send") {
|
|
52
|
+
deps.sendToClient(sessionId, op.message);
|
|
53
|
+
} else {
|
|
54
|
+
deps.speak(sessionId, op.text);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|