@agent-play/sdk 3.1.0 → 3.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/dist/{browser-C8UKcztD.d.ts → browser-CvtF5qSC.d.ts} +42 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +5 -1
- package/dist/{chunk-G2WV7OYM.js → chunk-U2M7HNYN.js} +46 -3
- package/dist/chunk-U2M7HNYN.js.map +1 -0
- package/dist/index.d.ts +17 -4
- package/dist/index.js +204 -32
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-G2WV7OYM.js.map +0 -1
|
@@ -73,6 +73,30 @@ type PlatformAgentInformation = {
|
|
|
73
73
|
* It is sent on the wire as `agentId` for server compatibility; treating it as a node id makes the
|
|
74
74
|
* contract explicit for billing, validation, and event attribution.
|
|
75
75
|
*/
|
|
76
|
+
type P2aEnableFlag = "on" | "off";
|
|
77
|
+
type RealtimeWebrtcClientSecret = {
|
|
78
|
+
clientSecret: string;
|
|
79
|
+
expiresAt?: string;
|
|
80
|
+
model: string;
|
|
81
|
+
voice?: string;
|
|
82
|
+
};
|
|
83
|
+
/** OpenAI Realtime minting options used by {@link RemotePlayWorld.initAudio}. */
|
|
84
|
+
type RemotePlayWorldOpenAiAudioOptions = {
|
|
85
|
+
/** Server-side OpenAI key used to mint ephemeral browser client secrets. */
|
|
86
|
+
apiKey?: string;
|
|
87
|
+
/** Realtime model id, defaults to `gpt-realtime`. */
|
|
88
|
+
model?: string;
|
|
89
|
+
/** Realtime voice id, defaults to `marin`. */
|
|
90
|
+
voice?: string;
|
|
91
|
+
/** Explicit system instructions for the realtime session. */
|
|
92
|
+
instructions?: string;
|
|
93
|
+
/** Template fallback for instructions; `{{agentName}}` placeholder is supported. */
|
|
94
|
+
instructionsTemplate?: string;
|
|
95
|
+
};
|
|
96
|
+
/** Configuration payload for enabling SDK-managed realtime audio initialization. */
|
|
97
|
+
type RemotePlayWorldInitAudioOptions = {
|
|
98
|
+
openai: RemotePlayWorldOpenAiAudioOptions;
|
|
99
|
+
};
|
|
76
100
|
type AddAgentInput = PlatformAgentInformation & {
|
|
77
101
|
/** Registration from {@link langchainRegistration}. */
|
|
78
102
|
agent: LangChainAgentRegistration;
|
|
@@ -80,6 +104,11 @@ type AddAgentInput = PlatformAgentInformation & {
|
|
|
80
104
|
mainNodeId?: string;
|
|
81
105
|
/** Agent node id — same value the server stores as registered `agentId`. */
|
|
82
106
|
nodeId: string;
|
|
107
|
+
/**
|
|
108
|
+
* When **`"on"`**, registration enables OpenAI Realtime provisioning for this agent.
|
|
109
|
+
* Omitted or **`"off"`** disables realtime voice for this registration.
|
|
110
|
+
*/
|
|
111
|
+
enableP2a?: P2aEnableFlag;
|
|
83
112
|
};
|
|
84
113
|
/**
|
|
85
114
|
* Register a player (agent) in the world.
|
|
@@ -99,6 +128,8 @@ type AddPlayerInput = PlatformAgentInformation & {
|
|
|
99
128
|
mainNodeId?: string;
|
|
100
129
|
/** Registered agent id (or session-local id without Redis). */
|
|
101
130
|
agentId: string;
|
|
131
|
+
/** @inheritdoc AddAgentInput.enableP2a */
|
|
132
|
+
enableP2a?: P2aEnableFlag;
|
|
102
133
|
};
|
|
103
134
|
/** Zone counter event surfaced on snapshots and signals. */
|
|
104
135
|
type ZoneEventInfo = {
|
|
@@ -124,6 +155,10 @@ type RegisteredAgentSummary = {
|
|
|
124
155
|
type RegisteredPlayer = PlayAgentInformation & {
|
|
125
156
|
previewUrl: string;
|
|
126
157
|
registeredAgent: RegisteredAgentSummary;
|
|
158
|
+
/** Echo of registration-time P2A flag (defaults to **`"off"`**). */
|
|
159
|
+
enableP2a: P2aEnableFlag;
|
|
160
|
+
/** Optional OpenAI Realtime WebRTC client-secret payload for browser-side direct voice. */
|
|
161
|
+
realtimeWebrtc?: RealtimeWebrtcClientSecret;
|
|
127
162
|
connectionId?: string;
|
|
128
163
|
leaseTtlSeconds?: number;
|
|
129
164
|
};
|
|
@@ -190,6 +225,9 @@ type AgentPlayWorldMapAgentOccupant = {
|
|
|
190
225
|
assistToolNames?: string[];
|
|
191
226
|
assistTools?: AssistToolSpec[];
|
|
192
227
|
hasChatTool?: boolean;
|
|
228
|
+
enableP2a?: P2aEnableFlag;
|
|
229
|
+
realtimeInstructions?: string;
|
|
230
|
+
realtimeWebrtc?: RealtimeWebrtcClientSecret;
|
|
193
231
|
stationary?: boolean;
|
|
194
232
|
lastUpdate?: unknown;
|
|
195
233
|
recentInteractions?: Array<{
|
|
@@ -299,6 +337,9 @@ type WorldBounds = {
|
|
|
299
337
|
/** Inclusive maximum Y. */
|
|
300
338
|
maxY: number;
|
|
301
339
|
};
|
|
340
|
+
/** Minimum playable span aligned with the watch canvas scrolling world (~20×20 cells). */
|
|
341
|
+
declare const MINIMUM_PLAY_WORLD_BOUNDS: WorldBounds;
|
|
342
|
+
declare function expandBoundsToMinimumPlayArea(bounds: WorldBounds): WorldBounds;
|
|
302
343
|
/**
|
|
303
344
|
* Clamps a point to lie inside `bounds` along both axes.
|
|
304
345
|
*
|
|
@@ -338,4 +379,4 @@ declare function mergeSnapshotWithPlayerChainNode(snapshot: AgentPlaySnapshot, n
|
|
|
338
379
|
declare const PLAYER_CHAIN_GENESIS_STABLE_KEY: "__genesis__";
|
|
339
380
|
declare const PLAYER_CHAIN_HEADER_STABLE_KEY: "__header__";
|
|
340
381
|
|
|
341
|
-
export { type AgentPlaySnapshot as A,
|
|
382
|
+
export { type AgentPlaySnapshot as A, type RemotePlayWorldOpenAiAudioOptions as B, type WorldBounds as C, type DestinationJourneyStep as D, type WorldJourneyUpdate as E, boundsContain as F, clampWorldPosition as G, expandBoundsToMinimumPlayArea as H, mergeSnapshotWithPlayerChainNode as I, type Journey as J, parsePlayerChainFanoutNotify as K, type LangChainAgentRegistration as L, MINIMUM_PLAY_WORLD_BOUNDS as M, parsePlayerChainFanoutNotifyFromSsePayload as N, type OriginJourneyStep as O, type PlayerChainNodeResponse as P, parsePlayerChainNodeRpcBody as Q, type RemotePlayWorldInitAudioOptions as R, type StructureJourneyStep as S, sortNodeRefsForSerializedFetch as T, type WorldInteractionRole as W, type YieldEventInfo as Y, type ZoneEventInfo as Z, type AddAgentInput as a, type RegisteredPlayer as b, type AddPlayerInput as c, type RecordInteractionInput as d, type AgentPlayWorldMap as e, type AgentPlayWorldMapAgentOccupant as f, type AgentPlayWorldMapBounds as g, type AgentPlayWorldMapMcpOccupant as h, type AssistToolFieldType as i, type AssistToolParameterSpec as j, type AssistToolSpec as k, type JourneyStep as l, type P2aEnableFlag as m, PLAYER_CHAIN_GENESIS_STABLE_KEY as n, PLAYER_CHAIN_HEADER_STABLE_KEY as o, type PlatformAgentInformation as p, type PlayAgentInformation as q, type PlayerChainFanoutNotify as r, type PlayerChainGenesisNode as s, type PlayerChainHeaderNode as t, type PlayerChainNotifyNodeRef as u, type PlayerChainOccupantPresentNode as v, type PlayerChainOccupantRemovedNode as w, type PositionedStep as x, type RealtimeWebrtcClientSecret as y, type RegisteredAgentSummary as z };
|
package/dist/browser.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { A as AgentPlaySnapshot,
|
|
1
|
+
export { A as AgentPlaySnapshot, M as MINIMUM_PLAY_WORLD_BOUNDS, n as PLAYER_CHAIN_GENESIS_STABLE_KEY, o as PLAYER_CHAIN_HEADER_STABLE_KEY, C as WorldBounds, F as boundsContain, G as clampWorldPosition, H as expandBoundsToMinimumPlayArea, I as mergeSnapshotWithPlayerChainNode, K as parsePlayerChainFanoutNotify, N as parsePlayerChainFanoutNotifyFromSsePayload, Q as parsePlayerChainNodeRpcBody, T as sortNodeRefsForSerializedFetch } from './browser-CvtF5qSC.js';
|
package/dist/browser.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MINIMUM_PLAY_WORLD_BOUNDS,
|
|
2
3
|
PLAYER_CHAIN_GENESIS_STABLE_KEY,
|
|
3
4
|
PLAYER_CHAIN_HEADER_STABLE_KEY,
|
|
4
5
|
boundsContain,
|
|
5
6
|
clampWorldPosition,
|
|
7
|
+
expandBoundsToMinimumPlayArea,
|
|
6
8
|
mergeSnapshotWithPlayerChainNode,
|
|
7
9
|
parsePlayerChainFanoutNotify,
|
|
8
10
|
parsePlayerChainFanoutNotifyFromSsePayload,
|
|
9
11
|
parsePlayerChainNodeRpcBody,
|
|
10
12
|
sortNodeRefsForSerializedFetch
|
|
11
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U2M7HNYN.js";
|
|
12
14
|
export {
|
|
15
|
+
MINIMUM_PLAY_WORLD_BOUNDS,
|
|
13
16
|
PLAYER_CHAIN_GENESIS_STABLE_KEY,
|
|
14
17
|
PLAYER_CHAIN_HEADER_STABLE_KEY,
|
|
15
18
|
boundsContain,
|
|
16
19
|
clampWorldPosition,
|
|
20
|
+
expandBoundsToMinimumPlayArea,
|
|
17
21
|
mergeSnapshotWithPlayerChainNode,
|
|
18
22
|
parsePlayerChainFanoutNotify,
|
|
19
23
|
parsePlayerChainFanoutNotifyFromSsePayload,
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
// src/lib/world-bounds.ts
|
|
2
|
+
var MINIMUM_PLAY_WORLD_BOUNDS = {
|
|
3
|
+
minX: 0,
|
|
4
|
+
minY: 0,
|
|
5
|
+
maxX: 19,
|
|
6
|
+
maxY: 19
|
|
7
|
+
};
|
|
8
|
+
function expandBoundsToMinimumPlayArea(bounds) {
|
|
9
|
+
return {
|
|
10
|
+
minX: Math.min(bounds.minX, MINIMUM_PLAY_WORLD_BOUNDS.minX),
|
|
11
|
+
minY: Math.min(bounds.minY, MINIMUM_PLAY_WORLD_BOUNDS.minY),
|
|
12
|
+
maxX: Math.max(bounds.maxX, MINIMUM_PLAY_WORLD_BOUNDS.maxX),
|
|
13
|
+
maxY: Math.max(bounds.maxY, MINIMUM_PLAY_WORLD_BOUNDS.maxY)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
2
16
|
function clampWorldPosition(p, bounds) {
|
|
3
17
|
return {
|
|
4
18
|
x: Math.min(Math.max(p.x, bounds.minX), bounds.maxX),
|
|
@@ -56,10 +70,37 @@ function parseAgentOccupantRow(raw) {
|
|
|
56
70
|
} else if (typeof raw.agentType === "string") {
|
|
57
71
|
platform = raw.agentType;
|
|
58
72
|
}
|
|
73
|
+
const enableP2a = raw.enableP2a === "on" || raw.enableP2a === "off" ? raw.enableP2a : void 0;
|
|
74
|
+
const realtimeInstructions = typeof raw.realtimeInstructions === "string" && raw.realtimeInstructions.trim().length > 0 ? raw.realtimeInstructions : void 0;
|
|
75
|
+
const realtimeRaw = raw.realtimeWebrtc;
|
|
76
|
+
const realtimeWebrtc = typeof realtimeRaw === "object" && realtimeRaw !== null && typeof realtimeRaw.clientSecret === "string" && realtimeRaw.clientSecret.length > 0 && typeof realtimeRaw.model === "string" && realtimeRaw.model.length > 0 ? (() => {
|
|
77
|
+
const record = realtimeRaw;
|
|
78
|
+
const parsed = {
|
|
79
|
+
clientSecret: record.clientSecret,
|
|
80
|
+
model: record.model
|
|
81
|
+
};
|
|
82
|
+
if (typeof record.expiresAt === "string" && record.expiresAt.length > 0) {
|
|
83
|
+
parsed.expiresAt = record.expiresAt;
|
|
84
|
+
}
|
|
85
|
+
if (typeof record.voice === "string" && record.voice.length > 0) {
|
|
86
|
+
parsed.voice = record.voice;
|
|
87
|
+
}
|
|
88
|
+
return parsed;
|
|
89
|
+
})() : void 0;
|
|
90
|
+
const out = { ...base };
|
|
59
91
|
if (platform !== void 0) {
|
|
60
|
-
|
|
92
|
+
out.platform = platform;
|
|
61
93
|
}
|
|
62
|
-
|
|
94
|
+
if (enableP2a !== void 0) {
|
|
95
|
+
out.enableP2a = enableP2a;
|
|
96
|
+
}
|
|
97
|
+
if (realtimeInstructions !== void 0) {
|
|
98
|
+
out.realtimeInstructions = realtimeInstructions;
|
|
99
|
+
}
|
|
100
|
+
if (realtimeWebrtc !== void 0) {
|
|
101
|
+
out.realtimeWebrtc = realtimeWebrtc;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
63
104
|
}
|
|
64
105
|
function parseMcpOccupantRow(raw) {
|
|
65
106
|
if (typeof raw.id !== "string" || typeof raw.name !== "string") {
|
|
@@ -244,6 +285,8 @@ function mergeSnapshotWithPlayerChainNode(snapshot, node) {
|
|
|
244
285
|
}
|
|
245
286
|
|
|
246
287
|
export {
|
|
288
|
+
MINIMUM_PLAY_WORLD_BOUNDS,
|
|
289
|
+
expandBoundsToMinimumPlayArea,
|
|
247
290
|
clampWorldPosition,
|
|
248
291
|
boundsContain,
|
|
249
292
|
parseHumanOccupantRow,
|
|
@@ -257,4 +300,4 @@ export {
|
|
|
257
300
|
parsePlayerChainNodeRpcBody,
|
|
258
301
|
mergeSnapshotWithPlayerChainNode
|
|
259
302
|
};
|
|
260
|
-
//# sourceMappingURL=chunk-
|
|
303
|
+
//# sourceMappingURL=chunk-U2M7HNYN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/world-bounds.ts","../src/lib/world-chain-keys.ts","../src/lib/parse-occupant-row.ts","../src/lib/player-chain-merge.ts"],"sourcesContent":["/**\n * Axis-aligned rectangle in world coordinates (grid units). Used by the server to clamp paths\n * and by the watch UI to clamp joystick-driven movement.\n *\n * @remarks **Consumers:** {@link clampWorldPosition}, {@link boundsContain}; server `PlayWorld` and\n * play-ui canvas both import these helpers from `@agent-play/sdk`.\n */\nexport type WorldBounds = {\n /** Inclusive minimum X. */\n minX: number;\n /** Inclusive minimum Y. */\n minY: number;\n /** Inclusive maximum X. */\n maxX: number;\n /** Inclusive maximum Y. */\n maxY: number;\n};\n\n/** Minimum playable span aligned with the watch canvas scrolling world (~20×20 cells). */\nexport const MINIMUM_PLAY_WORLD_BOUNDS: WorldBounds = {\n minX: 0,\n minY: 0,\n maxX: 19,\n maxY: 19,\n};\n\nexport function expandBoundsToMinimumPlayArea(bounds: WorldBounds): WorldBounds {\n return {\n minX: Math.min(bounds.minX, MINIMUM_PLAY_WORLD_BOUNDS.minX),\n minY: Math.min(bounds.minY, MINIMUM_PLAY_WORLD_BOUNDS.minY),\n maxX: Math.max(bounds.maxX, MINIMUM_PLAY_WORLD_BOUNDS.maxX),\n maxY: Math.max(bounds.maxY, MINIMUM_PLAY_WORLD_BOUNDS.maxY),\n };\n}\n\n/**\n * Clamps a point to lie inside `bounds` along both axes.\n *\n * @param p - Position with `x` and `y` in world units.\n * @param bounds - Valid rectangle (`min` ≤ `max` per axis).\n * @returns Same point if inside, otherwise clamped to the nearest edge.\n *\n * @remarks **Callers:** server `PlayWorld` path enrichment; play-ui joystick and preview. **Callees:** `Math.min/Math.max`.\n */\nexport function clampWorldPosition(\n p: { x: number; y: number },\n bounds: WorldBounds\n): { x: number; y: number } {\n return {\n x: Math.min(Math.max(p.x, bounds.minX), bounds.maxX),\n y: Math.min(Math.max(p.y, bounds.minY), bounds.maxY),\n };\n}\n\n/**\n * @returns Whether `p` lies inside or on the border of `bounds`.\n *\n * @remarks **Callers:** optional UI checks. **Callees:** none.\n */\nexport function boundsContain(\n bounds: WorldBounds,\n p: { x: number; y: number }\n): boolean {\n return (\n p.x >= bounds.minX &&\n p.x <= bounds.maxX &&\n p.y >= bounds.minY &&\n p.y <= bounds.maxY\n );\n}\n","export const PLAYER_CHAIN_GENESIS_STABLE_KEY = \"__genesis__\" as const;\nexport const PLAYER_CHAIN_HEADER_STABLE_KEY = \"__header__\" as const;\n","import type {\n AgentPlayWorldMapHumanOccupant,\n AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapMcpOccupant,\n} from \"../public-types.js\";\n\nexport function parseHumanOccupantRow(\n raw: Record<string, unknown>\n): AgentPlayWorldMapHumanOccupant {\n if (typeof raw.id !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"occupant: human needs id and name\");\n }\n if (typeof raw.x !== \"number\" || typeof raw.y !== \"number\") {\n throw new Error(\"occupant: human needs numeric x and y\");\n }\n const base: AgentPlayWorldMapHumanOccupant = {\n kind: \"human\",\n id: raw.id,\n name: raw.name,\n x: raw.x,\n y: raw.y,\n };\n if (typeof raw.interactive === \"boolean\") {\n return { ...base, interactive: raw.interactive };\n }\n return base;\n}\n\nexport function parseAgentOccupantRow(\n raw: Record<string, unknown>\n): AgentPlayWorldMapAgentOccupant {\n if (typeof raw.agentId !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"occupant: agent needs agentId and name\");\n }\n if (typeof raw.x !== \"number\" || typeof raw.y !== \"number\") {\n throw new Error(\"occupant: agent needs numeric x and y\");\n }\n const base: AgentPlayWorldMapAgentOccupant = {\n kind: \"agent\",\n agentId: raw.agentId,\n name: raw.name,\n x: raw.x,\n y: raw.y,\n };\n if (typeof raw.nodeId === \"string\" && raw.nodeId.length > 0) {\n base.nodeId = raw.nodeId;\n }\n let platform: string | undefined;\n if (typeof raw.platform === \"string\") {\n platform = raw.platform;\n } else if (typeof raw.agentType === \"string\") {\n platform = raw.agentType;\n }\n const enableP2a =\n raw.enableP2a === \"on\" || raw.enableP2a === \"off\" ? raw.enableP2a : undefined;\n const realtimeInstructions =\n typeof raw.realtimeInstructions === \"string\" &&\n raw.realtimeInstructions.trim().length > 0\n ? raw.realtimeInstructions\n : undefined;\n const realtimeRaw = raw.realtimeWebrtc;\n const realtimeWebrtc =\n typeof realtimeRaw === \"object\" &&\n realtimeRaw !== null &&\n typeof (realtimeRaw as Record<string, unknown>).clientSecret === \"string\" &&\n ((realtimeRaw as Record<string, unknown>).clientSecret as string).length > 0 &&\n typeof (realtimeRaw as Record<string, unknown>).model === \"string\" &&\n ((realtimeRaw as Record<string, unknown>).model as string).length > 0\n ? (() => {\n const record = realtimeRaw as Record<string, unknown>;\n const parsed: {\n clientSecret: string;\n model: string;\n expiresAt?: string;\n voice?: string;\n } = {\n clientSecret: record.clientSecret as string,\n model: record.model as string,\n };\n if (typeof record.expiresAt === \"string\" && record.expiresAt.length > 0) {\n parsed.expiresAt = record.expiresAt;\n }\n if (typeof record.voice === \"string\" && record.voice.length > 0) {\n parsed.voice = record.voice;\n }\n return parsed;\n })()\n : undefined;\n\n const out: AgentPlayWorldMapAgentOccupant = { ...base };\n if (platform !== undefined) {\n out.platform = platform;\n }\n if (enableP2a !== undefined) {\n out.enableP2a = enableP2a;\n }\n if (realtimeInstructions !== undefined) {\n out.realtimeInstructions = realtimeInstructions;\n }\n if (realtimeWebrtc !== undefined) {\n out.realtimeWebrtc = realtimeWebrtc;\n }\n return out;\n}\n\nexport function parseMcpOccupantRow(\n raw: Record<string, unknown>\n): AgentPlayWorldMapMcpOccupant {\n if (typeof raw.id !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"occupant: mcp needs id and name\");\n }\n if (typeof raw.x !== \"number\" || typeof raw.y !== \"number\") {\n throw new Error(\"occupant: mcp needs numeric x and y\");\n }\n const base: AgentPlayWorldMapMcpOccupant = {\n kind: \"mcp\",\n id: raw.id,\n name: raw.name,\n x: raw.x,\n y: raw.y,\n };\n if (typeof raw.url === \"string\") {\n return { ...base, url: raw.url };\n }\n return base;\n}\n","/**\n * Parses **`playerChainNotify`** envelopes and merges {@link PlayerChainNodeResponse} slices into {@link AgentPlaySnapshot} (pure functions + fetch ordering for serialized RPC).\n */\n\nimport type {\n AgentPlaySnapshot,\n AgentPlayWorldMapHumanOccupant,\n AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapMcpOccupant,\n PlayerChainFanoutNotify,\n PlayerChainNotifyNodeRef,\n PlayerChainNodeResponse,\n} from \"../public-types.js\";\nimport {\n parseHumanOccupantRow,\n parseAgentOccupantRow,\n parseMcpOccupantRow,\n} from \"./parse-occupant-row.js\";\nimport {\n PLAYER_CHAIN_GENESIS_STABLE_KEY,\n PLAYER_CHAIN_HEADER_STABLE_KEY,\n} from \"./world-chain-keys.js\";\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null;\n}\n\nfunction stableOccupantSortKey(\n occ:\n | AgentPlayWorldMapHumanOccupant\n | AgentPlayWorldMapAgentOccupant\n | AgentPlayWorldMapMcpOccupant\n): string {\n if (occ.kind === \"human\") {\n return `human:${occ.id}`;\n }\n if (occ.kind === \"agent\") {\n const nodeId = occ.nodeId;\n if (typeof nodeId !== \"string\" || nodeId.length === 0) {\n throw new Error(\"stableOccupantSortKey: invalid agent nodeId\");\n }\n return `agent:${nodeId}:${occ.agentId}`;\n }\n return `mcp:${occ.id}`;\n}\n\nexport function sortNodeRefsForSerializedFetch(\n nodes: ReadonlyArray<PlayerChainNotifyNodeRef>\n): PlayerChainNotifyNodeRef[] {\n const removed = nodes.filter((n) => n.removed === true);\n const rest = nodes.filter((n) => n.removed !== true);\n removed.sort((a, b) => b.leafIndex - a.leafIndex);\n rest.sort((a, b) => a.leafIndex - b.leafIndex);\n return [...removed, ...rest];\n}\n\nexport function parsePlayerChainFanoutNotify(\n raw: unknown\n): PlayerChainFanoutNotify | undefined {\n if (!isRecord(raw)) {\n return undefined;\n }\n if (typeof raw.updatedAt !== \"string\" || raw.updatedAt.length === 0) {\n return undefined;\n }\n if (!Array.isArray(raw.nodes)) {\n return undefined;\n }\n const nodes: PlayerChainNotifyNodeRef[] = [];\n for (const row of raw.nodes) {\n if (!isRecord(row)) {\n return undefined;\n }\n if (typeof row.stableKey !== \"string\" || row.stableKey.length === 0) {\n return undefined;\n }\n if (typeof row.leafIndex !== \"number\" || !Number.isFinite(row.leafIndex)) {\n return undefined;\n }\n const ref: PlayerChainNotifyNodeRef = {\n stableKey: row.stableKey,\n leafIndex: row.leafIndex,\n };\n if (row.removed === true) {\n ref.removed = true;\n }\n if (typeof row.updatedAt === \"string\" && row.updatedAt.length > 0) {\n ref.updatedAt = row.updatedAt;\n }\n nodes.push(ref);\n }\n return { updatedAt: raw.updatedAt, nodes };\n}\n\nexport function parsePlayerChainFanoutNotifyFromSsePayload(\n sseData: unknown\n): PlayerChainFanoutNotify | undefined {\n if (!isRecord(sseData)) {\n return undefined;\n }\n return parsePlayerChainFanoutNotify(sseData.playerChainNotify);\n}\n\nexport function parsePlayerChainNodeRpcBody(json: unknown): PlayerChainNodeResponse {\n if (!isRecord(json) || !isRecord(json.node)) {\n throw new Error(\"getPlayerChainNode: invalid response shape\");\n }\n const n = json.node;\n if (n.kind === \"genesis\") {\n if (\n n.stableKey !== PLAYER_CHAIN_GENESIS_STABLE_KEY ||\n typeof n.text !== \"string\"\n ) {\n throw new Error(\"getPlayerChainNode: invalid genesis node\");\n }\n return {\n kind: \"genesis\",\n stableKey: PLAYER_CHAIN_GENESIS_STABLE_KEY,\n text: n.text,\n };\n }\n if (n.kind === \"header\") {\n if (\n n.stableKey !== PLAYER_CHAIN_HEADER_STABLE_KEY ||\n typeof n.sid !== \"string\"\n ) {\n throw new Error(\"getPlayerChainNode: invalid header node\");\n }\n const b = n.bounds;\n if (!isRecord(b)) {\n throw new Error(\"getPlayerChainNode: invalid header bounds\");\n }\n const { minX, minY, maxX, maxY } = b;\n if (\n typeof minX !== \"number\" ||\n typeof minY !== \"number\" ||\n typeof maxX !== \"number\" ||\n typeof maxY !== \"number\"\n ) {\n throw new Error(\"getPlayerChainNode: invalid header bounds\");\n }\n return {\n kind: \"header\",\n stableKey: PLAYER_CHAIN_HEADER_STABLE_KEY,\n sid: n.sid,\n bounds: { minX, minY, maxX, maxY },\n };\n }\n if (n.kind !== \"occupant\") {\n throw new Error(\"getPlayerChainNode: unknown node kind\");\n }\n if (typeof n.stableKey !== \"string\" || n.stableKey.length === 0) {\n throw new Error(\"getPlayerChainNode: invalid occupant stableKey\");\n }\n if (n.removed === true) {\n return { kind: \"occupant\", stableKey: n.stableKey, removed: true };\n }\n const occ = n.occupant;\n if (\n !isRecord(occ) ||\n (occ.kind !== \"human\" && occ.kind !== \"agent\" && occ.kind !== \"mcp\")\n ) {\n throw new Error(\"getPlayerChainNode: invalid occupant payload\");\n }\n const occupant =\n occ.kind === \"human\"\n ? parseHumanOccupantRow(occ)\n : occ.kind === \"agent\"\n ? parseAgentOccupantRow(occ)\n : parseMcpOccupantRow(occ);\n return {\n kind: \"occupant\",\n stableKey: n.stableKey,\n removed: false,\n occupant,\n };\n}\n\nexport function mergeSnapshotWithPlayerChainNode(\n snapshot: AgentPlaySnapshot,\n node: PlayerChainNodeResponse\n): AgentPlaySnapshot {\n if (node.kind === \"genesis\") {\n return snapshot;\n }\n if (node.kind === \"header\") {\n return {\n ...snapshot,\n sid: node.sid,\n worldMap: {\n ...snapshot.worldMap,\n bounds: node.bounds,\n },\n };\n }\n if (node.removed === true) {\n return {\n ...snapshot,\n worldMap: {\n ...snapshot.worldMap,\n occupants: snapshot.worldMap.occupants.filter(\n (o) => stableOccupantSortKey(o) !== node.stableKey\n ),\n },\n };\n }\n if (node.removed !== false) {\n throw new Error(\"mergeSnapshotWithPlayerChainNode: invalid occupant node\");\n }\n const occ = node.occupant;\n const key = stableOccupantSortKey(occ);\n const occupants = snapshot.worldMap.occupants.filter(\n (o) => stableOccupantSortKey(o) !== key\n );\n return {\n ...snapshot,\n worldMap: {\n ...snapshot.worldMap,\n occupants: [...occupants, occ],\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { W as WorldInteractionRole, L as LangChainAgentRegistration, A as AgentPlaySnapshot, P as PlayerChainNodeResponse, a as AddAgentInput,
|
|
2
|
-
export {
|
|
1
|
+
import { W as WorldInteractionRole, L as LangChainAgentRegistration, R as RemotePlayWorldInitAudioOptions, A as AgentPlaySnapshot, P as PlayerChainNodeResponse, a as AddAgentInput, b as RegisteredPlayer, c as AddPlayerInput, d as RecordInteractionInput, J as Journey } from './browser-CvtF5qSC.js';
|
|
2
|
+
export { e as AgentPlayWorldMap, f as AgentPlayWorldMapAgentOccupant, g as AgentPlayWorldMapBounds, h as AgentPlayWorldMapMcpOccupant, i as AssistToolFieldType, j as AssistToolParameterSpec, k as AssistToolSpec, D as DestinationJourneyStep, l as JourneyStep, M as MINIMUM_PLAY_WORLD_BOUNDS, O as OriginJourneyStep, m as P2aEnableFlag, n as PLAYER_CHAIN_GENESIS_STABLE_KEY, o as PLAYER_CHAIN_HEADER_STABLE_KEY, p as PlatformAgentInformation, q as PlayAgentInformation, r as PlayerChainFanoutNotify, s as PlayerChainGenesisNode, t as PlayerChainHeaderNode, u as PlayerChainNotifyNodeRef, v as PlayerChainOccupantPresentNode, w as PlayerChainOccupantRemovedNode, x as PositionedStep, y as RealtimeWebrtcClientSecret, z as RegisteredAgentSummary, B as RemotePlayWorldOpenAiAudioOptions, S as StructureJourneyStep, C as WorldBounds, E as WorldJourneyUpdate, Y as YieldEventInfo, Z as ZoneEventInfo, F as boundsContain, G as clampWorldPosition, H as expandBoundsToMinimumPlayArea, I as mergeSnapshotWithPlayerChainNode, K as parsePlayerChainFanoutNotify, N as parsePlayerChainFanoutNotifyFromSsePayload, Q as parsePlayerChainNodeRpcBody, T as sortNodeRefsForSerializedFetch } from './browser-CvtF5qSC.js';
|
|
3
3
|
import { WorldIntercomEventPayload, IntercomResponsePayload } from '@agent-play/intercom';
|
|
4
4
|
export { AgentPlayAgentNodeEntry, AgentPlayCredentialsFile, loadAgentPlayCredentialsFileFromPath, loadAgentPlayCredentialsFileFromPathSync, loadRootKey, nodeCredentialsMaterialFromHumanPassphrase, parseAgentPlayCredentialsJson, resolveAgentPlayCredentialsPath } from '@agent-play/node-tools';
|
|
5
5
|
|
|
@@ -167,6 +167,7 @@ type SubscribeIntercomCommandsOptions = ({
|
|
|
167
167
|
* Authenticates like the CLI: **`x-node-id`** (derived node id) and **`x-node-passw`** (hashed passphrase material) on every request.
|
|
168
168
|
*
|
|
169
169
|
* Register automation agents with {@link RemotePlayWorld.addAgent} (`nodeId` is the agent node id; the server stores it as `agentId`).
|
|
170
|
+
* Call {@link RemotePlayWorld.initAudio} before `addAgent` to have the SDK mint per-agent OpenAI Realtime client secrets and forward them on registration.
|
|
170
171
|
*
|
|
171
172
|
* Incremental updates: {@link RemotePlayWorld.subscribeWorldState} listens for **`playerChainNotify`** in SSE `data`, then fetches each changed leaf via {@link RemotePlayWorld.getPlayerChainNode} and merges with {@link mergeSnapshotWithPlayerChainNode}.
|
|
172
173
|
*
|
|
@@ -187,6 +188,7 @@ declare class RemotePlayWorld {
|
|
|
187
188
|
private closed;
|
|
188
189
|
private readonly closeListeners;
|
|
189
190
|
private readonly playerConnectionInfo;
|
|
191
|
+
private audioInitOptions;
|
|
190
192
|
constructor(options?: RemotePlayWorldOptions);
|
|
191
193
|
private logTransport;
|
|
192
194
|
private truncateForLog;
|
|
@@ -205,6 +207,13 @@ declare class RemotePlayWorld {
|
|
|
205
207
|
close(): Promise<void>;
|
|
206
208
|
getSessionId(): string;
|
|
207
209
|
getPreviewUrl(): string;
|
|
210
|
+
/**
|
|
211
|
+
* Enables SDK-managed OpenAI Realtime client secret minting for subsequent {@link addAgent} calls.
|
|
212
|
+
*
|
|
213
|
+
* When set and `addAgent({ enableP2a: "on" })` is used, the SDK mints a short-lived client secret
|
|
214
|
+
* and includes it in the players registration payload as `realtimeWebrtc`.
|
|
215
|
+
*/
|
|
216
|
+
initAudio(options: RemotePlayWorldInitAudioOptions): this;
|
|
208
217
|
getWorldSnapshot(): Promise<AgentPlaySnapshot>;
|
|
209
218
|
/**
|
|
210
219
|
* Fetches one player-chain node (genesis, header, occupant row, or removal) for `stableKey`, same snapshot scope as {@link RemotePlayWorld.getWorldSnapshot}.
|
|
@@ -222,6 +231,9 @@ declare class RemotePlayWorld {
|
|
|
222
231
|
};
|
|
223
232
|
/**
|
|
224
233
|
* Registers an automation agent using **agent node id** (`nodeId`), sent to the server as `agentId`.
|
|
234
|
+
*
|
|
235
|
+
* If {@link initAudio} was called and **`enableP2a`** is **`"on"`**, this call mints a per-agent
|
|
236
|
+
* OpenAI Realtime client secret and forwards it as `realtimeWebrtc`.
|
|
225
237
|
*/
|
|
226
238
|
addAgent(input: AddAgentInput): Promise<RegisteredPlayer>;
|
|
227
239
|
/**
|
|
@@ -232,7 +244,8 @@ declare class RemotePlayWorld {
|
|
|
232
244
|
recordJourney(playerId: string, journey: Journey): Promise<void>;
|
|
233
245
|
sendIntercomResponse(payload: IntercomResponsePayload): Promise<void>;
|
|
234
246
|
/**
|
|
235
|
-
* Subscribes to the session SSE stream and handles **`forwarded`** intercom commands whose **`toPlayerId`** is in **`playerId`** or **`playerIds`**, invoking
|
|
247
|
+
* Subscribes to the session SSE stream and handles **`forwarded`** intercom commands whose **`toPlayerId`** is in **`playerId`** or **`playerIds`**, invoking assist/chat execution and posting **`intercomResponse`** (**`completed`** / **`failed`**).
|
|
248
|
+
* Realtime commands mint ephemeral WebRTC credentials in the agent process and return them through `intercomResponse`.
|
|
236
249
|
* Uses a **single** SSE connection when **`playerIds`** lists multiple automation agents (recommended for several agents in one process).
|
|
237
250
|
* Not invoked automatically by {@link RemotePlayWorld.addAgent}.
|
|
238
251
|
*/
|
|
@@ -253,4 +266,4 @@ declare class RemotePlayWorld {
|
|
|
253
266
|
*/
|
|
254
267
|
declare function intercomResultRecordFromLangChainInvokeOutput(output: unknown): Record<string, unknown>;
|
|
255
268
|
|
|
256
|
-
export { AddAgentInput, AddPlayerInput, AgentPlaySnapshot, type IntercomToolExecutor, Journey, LangChainAgentRegistration, PLAYER_ADDED_EVENT, PlayerChainNodeResponse, RecordInteractionInput, RegisteredPlayer, RemotePlayWorld, type RemotePlayWorldConnectOptions, type RemotePlayWorldHold, type RemotePlayWorldLogging, type RemotePlayWorldNodeCredentials, type RemotePlayWorldOptions, type RemotePlayWorldSessionEvent, SESSION_CLOSED_EVENT, SESSION_CONNECTED_EVENT, SESSION_INVALID_EVENT, SESSION_SSE_ERROR_EVENT, SESSION_SSE_OPEN_EVENT, type SubscribeIntercomCommandsOptions, WORLD_AGENT_SIGNAL_EVENT, WORLD_INTERACTION_EVENT, WORLD_JOURNEY_EVENT, type WorldAgentSignalPayload, type WorldInteractionPayload, WorldInteractionRole, agentPlayDebug, configureAgentPlayDebug, intercomResultRecordFromLangChainInvokeOutput, isAgentPlayDebugEnabled, langchainRegistration, resetAgentPlayDebug };
|
|
269
|
+
export { AddAgentInput, AddPlayerInput, AgentPlaySnapshot, type IntercomToolExecutor, Journey, LangChainAgentRegistration, PLAYER_ADDED_EVENT, PlayerChainNodeResponse, RecordInteractionInput, RegisteredPlayer, RemotePlayWorld, type RemotePlayWorldConnectOptions, type RemotePlayWorldHold, RemotePlayWorldInitAudioOptions, type RemotePlayWorldLogging, type RemotePlayWorldNodeCredentials, type RemotePlayWorldOptions, type RemotePlayWorldSessionEvent, SESSION_CLOSED_EVENT, SESSION_CONNECTED_EVENT, SESSION_INVALID_EVENT, SESSION_SSE_ERROR_EVENT, SESSION_SSE_OPEN_EVENT, type SubscribeIntercomCommandsOptions, WORLD_AGENT_SIGNAL_EVENT, WORLD_INTERACTION_EVENT, WORLD_JOURNEY_EVENT, type WorldAgentSignalPayload, type WorldInteractionPayload, WorldInteractionRole, agentPlayDebug, configureAgentPlayDebug, intercomResultRecordFromLangChainInvokeOutput, isAgentPlayDebugEnabled, langchainRegistration, resetAgentPlayDebug };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MINIMUM_PLAY_WORLD_BOUNDS,
|
|
2
3
|
PLAYER_CHAIN_GENESIS_STABLE_KEY,
|
|
3
4
|
PLAYER_CHAIN_HEADER_STABLE_KEY,
|
|
4
5
|
boundsContain,
|
|
5
6
|
clampWorldPosition,
|
|
7
|
+
expandBoundsToMinimumPlayArea,
|
|
6
8
|
mergeSnapshotWithPlayerChainNode,
|
|
7
9
|
parseAgentOccupantRow,
|
|
8
10
|
parseHumanOccupantRow,
|
|
@@ -11,7 +13,7 @@ import {
|
|
|
11
13
|
parsePlayerChainFanoutNotifyFromSsePayload,
|
|
12
14
|
parsePlayerChainNodeRpcBody,
|
|
13
15
|
sortNodeRefsForSerializedFetch
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-U2M7HNYN.js";
|
|
15
17
|
|
|
16
18
|
// src/world-events.ts
|
|
17
19
|
var SESSION_CONNECTED_EVENT = "session:connected";
|
|
@@ -247,6 +249,69 @@ function intercomResultRecordFromLangChainInvokeOutput(output) {
|
|
|
247
249
|
return { mode: "chat", output: o };
|
|
248
250
|
}
|
|
249
251
|
|
|
252
|
+
// src/lib/openai-realtime-client-secret.ts
|
|
253
|
+
function resolveRealtimeInstructions(options) {
|
|
254
|
+
const explicit = options.openai.instructions?.trim();
|
|
255
|
+
if (explicit !== void 0 && explicit.length > 0) {
|
|
256
|
+
return explicit;
|
|
257
|
+
}
|
|
258
|
+
const template = options.openai.instructionsTemplate?.trim();
|
|
259
|
+
if (template !== void 0 && template.length > 0) {
|
|
260
|
+
return template.replaceAll("{{agentName}}", options.agentName);
|
|
261
|
+
}
|
|
262
|
+
return `You are ${options.agentName}. Keep responses short, clear, and conversational unless asked for detail.`;
|
|
263
|
+
}
|
|
264
|
+
async function mintOpenAiRealtimeClientSecretForSdk(options) {
|
|
265
|
+
const apiKey = options.openai.apiKey?.trim() ?? "";
|
|
266
|
+
if (apiKey.length === 0) {
|
|
267
|
+
throw new Error("OPENAI_API_KEY is required when world.initAudio() is enabled");
|
|
268
|
+
}
|
|
269
|
+
const model = options.openai.model?.trim() || "gpt-realtime";
|
|
270
|
+
const voice = options.openai.voice?.trim() || "marin";
|
|
271
|
+
const instructions = resolveRealtimeInstructions(options);
|
|
272
|
+
const res = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
|
|
273
|
+
method: "POST",
|
|
274
|
+
headers: {
|
|
275
|
+
Authorization: `Bearer ${apiKey}`,
|
|
276
|
+
"Content-Type": "application/json"
|
|
277
|
+
},
|
|
278
|
+
body: JSON.stringify({
|
|
279
|
+
session: {
|
|
280
|
+
type: "realtime",
|
|
281
|
+
model,
|
|
282
|
+
...instructions !== void 0 && instructions.length > 0 ? { instructions } : {},
|
|
283
|
+
audio: { output: { voice } }
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
});
|
|
287
|
+
const text = await res.text();
|
|
288
|
+
if (!res.ok) {
|
|
289
|
+
throw new Error(`openai realtime client secret failed: ${res.status} ${text}`);
|
|
290
|
+
}
|
|
291
|
+
let parsed;
|
|
292
|
+
try {
|
|
293
|
+
parsed = JSON.parse(text);
|
|
294
|
+
} catch {
|
|
295
|
+
throw new Error("openai realtime client secret failed: invalid JSON");
|
|
296
|
+
}
|
|
297
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
298
|
+
throw new Error("openai realtime client secret failed: invalid payload");
|
|
299
|
+
}
|
|
300
|
+
const record = parsed;
|
|
301
|
+
if (typeof record.value !== "string" || record.value.length === 0) {
|
|
302
|
+
throw new Error("openai realtime client secret failed: missing value");
|
|
303
|
+
}
|
|
304
|
+
const out = {
|
|
305
|
+
clientSecret: record.value,
|
|
306
|
+
model,
|
|
307
|
+
voice
|
|
308
|
+
};
|
|
309
|
+
if (typeof record.expires_at === "string" && record.expires_at.length > 0) {
|
|
310
|
+
out.expiresAt = record.expires_at;
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
|
|
250
315
|
// src/lib/remote-play-world.ts
|
|
251
316
|
var PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS = 10;
|
|
252
317
|
var PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS = 1e4;
|
|
@@ -367,6 +432,30 @@ function parseRegisteredAgentSummary(raw) {
|
|
|
367
432
|
flagged: raw.flagged
|
|
368
433
|
};
|
|
369
434
|
}
|
|
435
|
+
function parseRealtimeWebrtcClientSecret(raw) {
|
|
436
|
+
if (!isRecord(raw)) {
|
|
437
|
+
return void 0;
|
|
438
|
+
}
|
|
439
|
+
const clientSecret = raw.clientSecret;
|
|
440
|
+
const model = raw.model;
|
|
441
|
+
if (typeof clientSecret !== "string" || clientSecret.length === 0) {
|
|
442
|
+
return void 0;
|
|
443
|
+
}
|
|
444
|
+
if (typeof model !== "string" || model.length === 0) {
|
|
445
|
+
return void 0;
|
|
446
|
+
}
|
|
447
|
+
const parsed = {
|
|
448
|
+
clientSecret,
|
|
449
|
+
model
|
|
450
|
+
};
|
|
451
|
+
if (typeof raw.expiresAt === "string" && raw.expiresAt.length > 0) {
|
|
452
|
+
parsed.expiresAt = raw.expiresAt;
|
|
453
|
+
}
|
|
454
|
+
if (typeof raw.voice === "string" && raw.voice.length > 0) {
|
|
455
|
+
parsed.voice = raw.voice;
|
|
456
|
+
}
|
|
457
|
+
return parsed;
|
|
458
|
+
}
|
|
370
459
|
function formatInvalidHoldSecondsError() {
|
|
371
460
|
return [
|
|
372
461
|
"RemotePlayWorld.hold().for(seconds): seconds must be a finite number.",
|
|
@@ -374,6 +463,17 @@ function formatInvalidHoldSecondsError() {
|
|
|
374
463
|
" Example: await world.hold().for(3600)"
|
|
375
464
|
].join("\n");
|
|
376
465
|
}
|
|
466
|
+
async function resolveRealtimeWebrtcForIntercom(options) {
|
|
467
|
+
if (options.audioInitOptions === null) {
|
|
468
|
+
throw new Error(
|
|
469
|
+
"intercom realtime requires initAudio({ openai: ... }) in the agent process"
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
return mintOpenAiRealtimeClientSecretForSdk({
|
|
473
|
+
openai: options.audioInitOptions,
|
|
474
|
+
agentName: options.playerId
|
|
475
|
+
});
|
|
476
|
+
}
|
|
377
477
|
function getSseEventName(msg) {
|
|
378
478
|
if (typeof msg !== "object" || msg === null) {
|
|
379
479
|
return void 0;
|
|
@@ -418,6 +518,7 @@ var RemotePlayWorld = class {
|
|
|
418
518
|
closed = false;
|
|
419
519
|
closeListeners = /* @__PURE__ */ new Set();
|
|
420
520
|
playerConnectionInfo = /* @__PURE__ */ new Map();
|
|
521
|
+
audioInitOptions = null;
|
|
421
522
|
constructor(options = {}) {
|
|
422
523
|
const creds = loadAgentPlayCredentialsFileFromPathSync(
|
|
423
524
|
resolveAgentPlayCredentialsPath()
|
|
@@ -599,6 +700,16 @@ var RemotePlayWorld = class {
|
|
|
599
700
|
u.search = "";
|
|
600
701
|
return u.toString();
|
|
601
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Enables SDK-managed OpenAI Realtime client secret minting for subsequent {@link addAgent} calls.
|
|
705
|
+
*
|
|
706
|
+
* When set and `addAgent({ enableP2a: "on" })` is used, the SDK mints a short-lived client secret
|
|
707
|
+
* and includes it in the players registration payload as `realtimeWebrtc`.
|
|
708
|
+
*/
|
|
709
|
+
initAudio(options) {
|
|
710
|
+
this.audioInitOptions = { ...options.openai };
|
|
711
|
+
return this;
|
|
712
|
+
}
|
|
602
713
|
async getWorldSnapshot() {
|
|
603
714
|
const res = await fetch(`${this.apiBase}/api/agent-play/sdk/rpc`, {
|
|
604
715
|
method: "POST",
|
|
@@ -742,6 +853,9 @@ var RemotePlayWorld = class {
|
|
|
742
853
|
}
|
|
743
854
|
/**
|
|
744
855
|
* Registers an automation agent using **agent node id** (`nodeId`), sent to the server as `agentId`.
|
|
856
|
+
*
|
|
857
|
+
* If {@link initAudio} was called and **`enableP2a`** is **`"on"`**, this call mints a per-agent
|
|
858
|
+
* OpenAI Realtime client secret and forwards it as `realtimeWebrtc`.
|
|
745
859
|
*/
|
|
746
860
|
async addAgent(input) {
|
|
747
861
|
const sid = this.getSessionId();
|
|
@@ -762,19 +876,48 @@ var RemotePlayWorld = class {
|
|
|
762
876
|
const url = `${this.apiBase}/api/agent-play/players?sid=${encodeURIComponent(sid)}`;
|
|
763
877
|
const connectionId = randomUUID();
|
|
764
878
|
const leaseTtlSeconds = 45;
|
|
879
|
+
let realtimeWebrtcFromInit;
|
|
880
|
+
let realtimeInstructionsFromInit;
|
|
881
|
+
if (input.enableP2a === "on" && this.audioInitOptions !== null) {
|
|
882
|
+
console.log("resolving realtime instructions for agent", input.name);
|
|
883
|
+
realtimeInstructionsFromInit = resolveRealtimeInstructions({
|
|
884
|
+
openai: this.audioInitOptions,
|
|
885
|
+
agentName: input.name
|
|
886
|
+
});
|
|
887
|
+
realtimeWebrtcFromInit = await mintOpenAiRealtimeClientSecretForSdk({
|
|
888
|
+
openai: this.audioInitOptions,
|
|
889
|
+
agentName: input.name
|
|
890
|
+
});
|
|
891
|
+
this.logTransport("addAgent:p2a_enabled", {
|
|
892
|
+
agentName: input.name,
|
|
893
|
+
model: this.audioInitOptions.model,
|
|
894
|
+
voice: this.audioInitOptions.voice
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
console.log("realtimeWebrtcFromInit", realtimeWebrtcFromInit);
|
|
898
|
+
console.log("realtimeInstructionsFromInit", realtimeInstructionsFromInit);
|
|
899
|
+
const requestPayload = {
|
|
900
|
+
name: input.name,
|
|
901
|
+
type: input.type,
|
|
902
|
+
agent: input.agent,
|
|
903
|
+
mainNodeId: effectiveMainNodeId,
|
|
904
|
+
password: this.password,
|
|
905
|
+
agentId: input.nodeId,
|
|
906
|
+
connectionId,
|
|
907
|
+
leaseTtlSeconds,
|
|
908
|
+
...input.enableP2a !== void 0 ? { enableP2a: input.enableP2a } : {},
|
|
909
|
+
...realtimeWebrtcFromInit !== void 0 ? { realtimeWebrtc: realtimeWebrtcFromInit } : {},
|
|
910
|
+
...realtimeInstructionsFromInit !== void 0 ? { realtimeInstructions: realtimeInstructionsFromInit } : {}
|
|
911
|
+
};
|
|
912
|
+
this.logTransport("addAgent:request_payload", {
|
|
913
|
+
url,
|
|
914
|
+
payload: requestPayload
|
|
915
|
+
});
|
|
916
|
+
const requestBody = JSON.stringify(requestPayload);
|
|
765
917
|
const res = await fetch(url, {
|
|
766
918
|
method: "POST",
|
|
767
919
|
headers: this.jsonHeaders(),
|
|
768
|
-
body:
|
|
769
|
-
name: input.name,
|
|
770
|
-
type: input.type,
|
|
771
|
-
agent: input.agent,
|
|
772
|
-
mainNodeId: effectiveMainNodeId,
|
|
773
|
-
password: this.password,
|
|
774
|
-
agentId: input.nodeId,
|
|
775
|
-
connectionId,
|
|
776
|
-
leaseTtlSeconds
|
|
777
|
-
})
|
|
920
|
+
body: requestBody
|
|
778
921
|
});
|
|
779
922
|
const bodyText = await res.text();
|
|
780
923
|
if (!res.ok) {
|
|
@@ -824,6 +967,9 @@ var RemotePlayWorld = class {
|
|
|
824
967
|
timer
|
|
825
968
|
});
|
|
826
969
|
const now = /* @__PURE__ */ new Date();
|
|
970
|
+
const enableP2aFromBody = body.enableP2a === "on" || body.enableP2a === "off" ? body.enableP2a : void 0;
|
|
971
|
+
const enableP2a = enableP2aFromBody ?? input.enableP2a ?? "off";
|
|
972
|
+
const realtimeWebrtc = parseRealtimeWebrtcClientSecret(body.realtimeWebrtc);
|
|
827
973
|
return {
|
|
828
974
|
id: playerId,
|
|
829
975
|
name: input.name,
|
|
@@ -832,6 +978,8 @@ var RemotePlayWorld = class {
|
|
|
832
978
|
updatedAt: now,
|
|
833
979
|
previewUrl,
|
|
834
980
|
registeredAgent,
|
|
981
|
+
enableP2a,
|
|
982
|
+
...realtimeWebrtc !== void 0 ? { realtimeWebrtc } : {},
|
|
835
983
|
connectionId: bodyConnectionId,
|
|
836
984
|
leaseTtlSeconds: bodyLeaseTtlSeconds
|
|
837
985
|
};
|
|
@@ -846,6 +994,9 @@ var RemotePlayWorld = class {
|
|
|
846
994
|
agent: input.agent,
|
|
847
995
|
nodeId: input.agentId
|
|
848
996
|
};
|
|
997
|
+
if (input.enableP2a !== void 0) {
|
|
998
|
+
payload.enableP2a = input.enableP2a;
|
|
999
|
+
}
|
|
849
1000
|
if (input.version !== void 0) {
|
|
850
1001
|
payload.version = input.version;
|
|
851
1002
|
}
|
|
@@ -900,7 +1051,8 @@ var RemotePlayWorld = class {
|
|
|
900
1051
|
}
|
|
901
1052
|
}
|
|
902
1053
|
/**
|
|
903
|
-
* Subscribes to the session SSE stream and handles **`forwarded`** intercom commands whose **`toPlayerId`** is in **`playerId`** or **`playerIds`**, invoking
|
|
1054
|
+
* Subscribes to the session SSE stream and handles **`forwarded`** intercom commands whose **`toPlayerId`** is in **`playerId`** or **`playerIds`**, invoking assist/chat execution and posting **`intercomResponse`** (**`completed`** / **`failed`**).
|
|
1055
|
+
* Realtime commands mint ephemeral WebRTC credentials in the agent process and return them through `intercomResponse`.
|
|
904
1056
|
* Uses a **single** SSE connection when **`playerIds`** lists multiple automation agents (recommended for several agents in one process).
|
|
905
1057
|
* Not invoked automatically by {@link RemotePlayWorld.addAgent}.
|
|
906
1058
|
*/
|
|
@@ -986,21 +1138,20 @@ var RemotePlayWorld = class {
|
|
|
986
1138
|
kind: cmd.kind,
|
|
987
1139
|
toolName: cmd.toolName
|
|
988
1140
|
});
|
|
989
|
-
const toolName = cmd.kind === "chat" ? "chat_tool" : cmd.toolName ?? "";
|
|
990
|
-
const args = cmd.kind === "chat" ? { text: cmd.text ?? "" } : cmd.args ?? {};
|
|
991
|
-
this.logTransport("intercom:executeTool", {
|
|
992
|
-
requestId: cmd.requestId,
|
|
993
|
-
toolName,
|
|
994
|
-
argsPreview: this.truncateForLog(JSON.stringify(args))
|
|
995
|
-
});
|
|
996
1141
|
try {
|
|
997
|
-
this.logTransport("intercom:executeTool:started", {
|
|
998
|
-
requestId: cmd.requestId,
|
|
999
|
-
toolName,
|
|
1000
|
-
argsPreview: this.truncateForLog(JSON.stringify(args))
|
|
1001
|
-
});
|
|
1002
1142
|
let result;
|
|
1003
|
-
|
|
1143
|
+
const commandKind = `${cmd.kind}`;
|
|
1144
|
+
if (commandKind === "realtime" || commandKind === "audio") {
|
|
1145
|
+
const realtimeWebrtc = await resolveRealtimeWebrtcForIntercom({
|
|
1146
|
+
audioInitOptions: this.audioInitOptions,
|
|
1147
|
+
playerId: cmd.toPlayerId
|
|
1148
|
+
});
|
|
1149
|
+
result = {
|
|
1150
|
+
messageKind: "text",
|
|
1151
|
+
message: "Realtime credentials ready.",
|
|
1152
|
+
realtimeWebrtc
|
|
1153
|
+
};
|
|
1154
|
+
} else if (cmd.kind === "chat" && chatAgentsByPlayerId !== void 0 && chatAgentsByPlayerId.has(cmd.toPlayerId)) {
|
|
1004
1155
|
const lc = chatAgentsByPlayerId.get(cmd.toPlayerId);
|
|
1005
1156
|
if (lc === void 0) {
|
|
1006
1157
|
throw new Error("intercom: chatAgentsByPlayerId entry missing");
|
|
@@ -1018,17 +1169,36 @@ var RemotePlayWorld = class {
|
|
|
1018
1169
|
requestId: cmd.requestId,
|
|
1019
1170
|
resultPreview: this.truncateForLog(JSON.stringify(result))
|
|
1020
1171
|
});
|
|
1021
|
-
} else {
|
|
1172
|
+
} else if (cmd.kind === "assist" || cmd.kind === "chat") {
|
|
1173
|
+
const toolName = cmd.kind === "chat" ? "chat_tool" : cmd.toolName ?? "";
|
|
1174
|
+
const args = cmd.kind === "chat" ? { text: cmd.text ?? "" } : cmd.args ?? {};
|
|
1175
|
+
this.logTransport("intercom:executeTool", {
|
|
1176
|
+
requestId: cmd.requestId,
|
|
1177
|
+
toolName,
|
|
1178
|
+
argsPreview: this.truncateForLog(JSON.stringify(args))
|
|
1179
|
+
});
|
|
1180
|
+
this.logTransport("intercom:executeTool:started", {
|
|
1181
|
+
requestId: cmd.requestId,
|
|
1182
|
+
toolName,
|
|
1183
|
+
argsPreview: this.truncateForLog(JSON.stringify(args))
|
|
1184
|
+
});
|
|
1022
1185
|
result = await Promise.resolve(
|
|
1023
1186
|
executeTool({ toolName, args })
|
|
1024
1187
|
);
|
|
1188
|
+
this.logTransport("intercom:executeTool:completed", {
|
|
1189
|
+
requestId: cmd.requestId,
|
|
1190
|
+
toolName,
|
|
1191
|
+
argsPreview: this.truncateForLog(JSON.stringify(args)),
|
|
1192
|
+
resultPreview: this.truncateForLog(JSON.stringify(result))
|
|
1193
|
+
});
|
|
1194
|
+
} else {
|
|
1195
|
+
this.logTransport("intercom:unsupported_kind:ignored", {
|
|
1196
|
+
requestId: cmd.requestId,
|
|
1197
|
+
kind: cmd.kind,
|
|
1198
|
+
toPlayerId: cmd.toPlayerId
|
|
1199
|
+
});
|
|
1200
|
+
continue;
|
|
1025
1201
|
}
|
|
1026
|
-
this.logTransport("intercom:executeTool:completed", {
|
|
1027
|
-
requestId: cmd.requestId,
|
|
1028
|
-
toolName,
|
|
1029
|
-
argsPreview: this.truncateForLog(JSON.stringify(args)),
|
|
1030
|
-
resultPreview: this.truncateForLog(JSON.stringify(result))
|
|
1031
|
-
});
|
|
1032
1202
|
await this.sendIntercomResponse({
|
|
1033
1203
|
requestId: cmd.requestId,
|
|
1034
1204
|
mainNodeId: cmd.mainNodeId,
|
|
@@ -1201,6 +1371,7 @@ import {
|
|
|
1201
1371
|
resolveAgentPlayCredentialsPath as resolveAgentPlayCredentialsPath2
|
|
1202
1372
|
} from "@agent-play/node-tools";
|
|
1203
1373
|
export {
|
|
1374
|
+
MINIMUM_PLAY_WORLD_BOUNDS,
|
|
1204
1375
|
PLAYER_ADDED_EVENT,
|
|
1205
1376
|
PLAYER_CHAIN_GENESIS_STABLE_KEY,
|
|
1206
1377
|
PLAYER_CHAIN_HEADER_STABLE_KEY,
|
|
@@ -1217,6 +1388,7 @@ export {
|
|
|
1217
1388
|
boundsContain,
|
|
1218
1389
|
clampWorldPosition,
|
|
1219
1390
|
configureAgentPlayDebug,
|
|
1391
|
+
expandBoundsToMinimumPlayArea,
|
|
1220
1392
|
intercomResultRecordFromLangChainInvokeOutput,
|
|
1221
1393
|
isAgentPlayDebugEnabled,
|
|
1222
1394
|
langchainRegistration,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/world-events.ts","../src/lib/agent-play-debug.ts","../src/platforms/langchain.ts","../src/lib/remote-play-world.ts","../src/lib/intercom-langchain-chat-result.ts","../src/index.ts"],"sourcesContent":["/**\n * String constants and payload shapes for SSE and in-process world events.\n *\n * @remarks **Emitters:** server `PlayWorld` and Redis fanout. **Consumers:** watch UI `EventSource`,\n * integration tests, and any host that forwards `POST` events.\n *\n * **Session vs world:** names prefixed with **`session:`** concern the HTTP/SDK session (`sid`) and\n * transport; names prefixed with **`world:`** concern occupants, chat, and map-visible state.\n */\nimport type { WorldInteractionRole } from \"./public-types.js\";\n\n/** After `RemotePlayWorld.connect()` assigns a `sid` (and optional detail such as `sid`). */\nexport const SESSION_CONNECTED_EVENT = \"session:connected\";\n\n/** RPC or transport rejected the session (e.g. 401/403); optional `detail.status`. */\nexport const SESSION_INVALID_EVENT = \"session:invalid\";\n\n/** After `RemotePlayWorld.close()` completes teardown. */\nexport const SESSION_CLOSED_EVENT = \"session:closed\";\n\n/** SSE subscription opened (optional; emitted when wired). */\nexport const SESSION_SSE_OPEN_EVENT = \"session:sse_open\";\n\n/** SSE subscription error (optional; emitted when wired). */\nexport const SESSION_SSE_ERROR_EVENT = \"session:sse_error\";\n\nexport type RemotePlayWorldSessionEvent = {\n name: string;\n detail?: Record<string, unknown>;\n};\n\n/** Fired when `addAgent` / `addPlayer` completes; payload includes snapshot row for the new player. */\nexport const PLAYER_ADDED_EVENT = \"world:player_added\";\n\n/** Fired for each new chat/interaction line. */\nexport const WORLD_INTERACTION_EVENT = \"world:interaction\";\n\n/** Lightweight signals (zone, yield, assist, journey metadata, etc.). */\nexport const WORLD_AGENT_SIGNAL_EVENT = \"world:agent_signal\";\n\n/** Full journey + path update for a player. */\nexport const WORLD_JOURNEY_EVENT = \"world:journey\";\n\n/**\n * Payload for {@link WORLD_AGENT_SIGNAL_EVENT}.\n *\n * @property playerId - Target player.\n * @property kind - Signal category; `journey` often carries `{ stepCount }` in `data`.\n * @property data - Optional free-form metadata.\n */\nexport type WorldAgentSignalPayload = {\n playerId: string;\n kind: \"zone\" | \"yield\" | \"assist\" | \"chat\" | \"metadata\" | \"journey\";\n data?: Record<string, unknown>;\n};\n\n/**\n * Payload for {@link WORLD_INTERACTION_EVENT}.\n *\n * @property seq - Monotonic sequence for ordering in the UI.\n */\nexport type WorldInteractionPayload = {\n playerId: string;\n role: WorldInteractionRole;\n text: string;\n at: string;\n seq: number;\n};\n","/**\n * Optional structured `console.debug` for SDK internals; gated by {@link configureAgentPlayDebug} or `AGENT_PLAY_DEBUG=1`.\n */\ntype DebugConfigure = {\n /** When set, overrides environment: `true` forces debug on, `false` forces off. */\n debug?: boolean;\n};\n\n/**\n * In-memory override for debug enablement (undefined = follow env only).\n *\n * @remarks **Writers:** {@link configureAgentPlayDebug}, {@link resetAgentPlayDebug}.\n * **Readers:** {@link isAgentPlayDebugEnabled}.\n */\nlet configuredDebug: boolean | undefined;\n\n/**\n * Sets whether SDK debug logging is enabled regardless of `AGENT_PLAY_DEBUG`.\n *\n * @param opts - Optional `{ debug }`: `true` / `false` forces logging; omit `debug` to clear override.\n *\n * @remarks **Callers:** tests and user code. **Callees:** none.\n */\nexport function configureAgentPlayDebug(opts: DebugConfigure): void {\n configuredDebug = opts.debug ?? undefined;\n}\n\n/**\n * Clears the in-memory override so only `AGENT_PLAY_DEBUG` applies.\n *\n * @remarks **Callers:** tests. **Callees:** none.\n */\nexport function resetAgentPlayDebug(): void {\n configuredDebug = undefined;\n}\n\n/**\n * @returns Whether debug logging should run: override wins, else `AGENT_PLAY_DEBUG === \"1\"`.\n *\n * @remarks **Callers:** {@link agentPlayDebug}. **Callees:** `process.env` read.\n */\nexport function isAgentPlayDebugEnabled(): boolean {\n if (configuredDebug === false) return false;\n if (configuredDebug === true) return true;\n return process.env.AGENT_PLAY_DEBUG === \"1\";\n}\n\n/** Max length of JSON detail string before truncation in the internal `safeSerialize` helper. */\nconst MAX_JSON_LENGTH = 2000;\n\n/**\n * Serializes `detail` for log lines, truncating long JSON and handling circular refs.\n *\n * @internal\n * @remarks **Callers:** {@link agentPlayDebug} only. **Callees:** `JSON.stringify` with replacer.\n */\nfunction safeSerialize(detail: unknown): string {\n if (detail === undefined) return \"\";\n try {\n const seen = new WeakSet<object>();\n const json = JSON.stringify(detail, (_k, v: unknown) => {\n if (typeof v === \"object\" && v !== null) {\n if (seen.has(v)) return \"[Circular]\";\n seen.add(v);\n }\n if (typeof v === \"bigint\") return String(v);\n return v;\n });\n if (typeof json !== \"string\") return String(detail);\n return json.length > MAX_JSON_LENGTH\n ? `${json.slice(0, MAX_JSON_LENGTH)}…`\n : json;\n } catch {\n return String(detail);\n }\n}\n\n/**\n * Emits `console.debug` when {@link isAgentPlayDebugEnabled} is true.\n *\n * @param scope - Short label (e.g. `\"langchain\"`).\n * @param message - Human-readable message.\n * @param detail - Optional object serialized by the internal truncation helper (see source).\n *\n * @remarks **Callers:** {@link langchainRegistration} and other SDK modules. **Callees:** {@link isAgentPlayDebugEnabled} and the internal serializer.\n */\nexport function agentPlayDebug(\n scope: string,\n message: string,\n detail?: unknown\n): void {\n if (!isAgentPlayDebugEnabled()) return;\n const tail =\n detail === undefined ? \"\" : ` ${safeSerialize(detail)}`;\n console.debug(`[agent-play:${scope}] ${message}${tail}`);\n}\n","/**\n * LangChain adapter: derives tool names and assist metadata from a LangChain agent for\n * {@link LangChainAgentRegistration}.\n *\n * @remarks **Primary export:** {@link langchainRegistration}. Private helpers build error strings and\n * `AssistToolSpec` rows from Zod schemas when available.\n */\nimport { agentPlayDebug } from \"../lib/agent-play-debug.js\";\nimport type {\n AssistToolFieldType,\n AssistToolSpec,\n LangChainAgentRegistration,\n} from \"../public-types.js\";\n\n/** Required tool name enforced by the watch UI contract. */\nconst CHAT_TOOL = \"chat_tool\";\n\n/**\n * Error text when the agent has no `tools` array.\n *\n * @remarks **Callers:** {@link langchainRegistration}. **Callees:** none.\n */\nfunction formatMissingAgentToolsError(): string {\n return [\n \"langchainRegistration: expected a LangChain agent with a tools array.\",\n \"\",\n \" Pass the object returned from createAgent({ tools: [...] }) (or equivalent) so tool names are available for the play world.\",\n \" The tools array must include named tools; see the separate message if \\\"chat_tool\\\" or assist_* tools are missing.\",\n ].join(\"\\n\");\n}\n\n/**\n * Error text when `chat_tool` is missing from tool names.\n *\n * @remarks **Callers:** {@link langchainRegistration}. **Callees:** none.\n */\nfunction formatMissingChatToolError(): string {\n return [\n \"langchainRegistration: missing required tool \\\"chat_tool\\\".\",\n \"\",\n \" Add a tool named \\\"chat_tool\\\" to your LangChain agent so the play world can show chat and proximity interactions.\",\n \" Example: tool(() => \\\"…\\\", { name: \\\"chat_tool\\\", description: \\\"…\\\", schema: z.object({ … }) })\",\n \"\",\n \" Tools whose names start with \\\"assist_\\\" are listed as assist actions on the watch UI; give each a Zod object schema so parameters can be shown in the UI.\",\n ].join(\"\\n\");\n}\n\ntype ZodDef = {\n typeName?: string;\n innerType?: unknown;\n schema?: unknown;\n};\n\nfunction unwrapZodCell(cell: unknown): unknown {\n let current: unknown = cell;\n for (let depth = 0; depth < 32; depth++) {\n if (current === null || typeof current !== \"object\") {\n return current;\n }\n const def = (current as { _def?: ZodDef })._def;\n if (!def || typeof def.typeName !== \"string\") {\n return current;\n }\n const { typeName } = def;\n if (\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\" ||\n typeName === \"ZodDefault\"\n ) {\n const inner = def.innerType;\n current =\n inner !== null && typeof inner === \"object\" ? inner : undefined;\n continue;\n }\n if (typeName === \"ZodEffects\") {\n current = def.schema;\n continue;\n }\n return current;\n }\n return current;\n}\n\nfunction fieldTypeFromZodCell(cell: unknown): AssistToolFieldType {\n const base = unwrapZodCell(cell);\n if (base === null || typeof base !== \"object\") {\n return \"string\";\n }\n const typeName = (base as { _def?: { typeName?: string } })._def?.typeName;\n if (typeName === \"ZodNumber\") {\n return \"number\";\n }\n if (typeName === \"ZodBoolean\") {\n return \"boolean\";\n }\n if (typeName === \"ZodString\") {\n return \"string\";\n }\n return \"string\";\n}\n\n/**\n * Best-effort parameter shape from a Zod object schema’s `shape()` for UI hints.\n *\n * @remarks **Callers:** {@link describeTool}. **Callees:** none.\n */\nfunction parametersFromSchema(schema: unknown): Record<string, unknown> {\n if (schema === null || typeof schema !== \"object\") {\n return {};\n }\n const z = schema as {\n _def?: { typeName?: string; shape?: () => Record<string, unknown> };\n };\n if (typeof z._def?.shape !== \"function\") {\n return { _note: \"Pass a Zod object schema on each tool for parameter hints in the watch UI.\" };\n }\n const shape = z._def.shape();\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(shape)) {\n out[key] = {\n field: key,\n fieldType: fieldTypeFromZodCell(shape[key]),\n };\n }\n return out;\n}\n\n/**\n * Builds an {@link AssistToolSpec} from a LangChain tool descriptor.\n *\n * @remarks **Callers:** {@link langchainRegistration} for `assist_*` tools only. **Callees:** {@link parametersFromSchema}.\n */\nfunction describeTool(t: {\n name: string;\n description?: string;\n schema?: unknown;\n}): AssistToolSpec {\n return {\n name: t.name,\n description:\n typeof t.description === \"string\" && t.description.length > 0\n ? t.description\n : t.name,\n parameters: parametersFromSchema(t.schema),\n };\n}\n\n/**\n * Reads `agent.tools` or `agent.options.tools` from common LangChain agent shapes.\n *\n * @returns The tools array, or `null` if not found.\n *\n * @remarks **Callers:** {@link langchainRegistration} only. **Callees:** none.\n */\nfunction extractToolsArray(agent: unknown): unknown[] | null {\n if (typeof agent !== \"object\" || agent === null) {\n return null;\n }\n const a = agent as {\n tools?: unknown;\n options?: { tools?: unknown };\n };\n if (Array.isArray(a.tools)) {\n return a.tools;\n }\n if (\n a.options !== undefined &&\n typeof a.options === \"object\" &&\n a.options !== null &&\n \"tools\" in a.options &&\n Array.isArray((a.options as { tools: unknown }).tools)\n ) {\n return (a.options as { tools: unknown[] }).tools;\n }\n return null;\n}\n\n/**\n * Validates a LangChain-style agent exposes tools (including required `chat_tool`) and returns\n * a {@link LangChainAgentRegistration} for `RemotePlayWorld.addAgent`.\n *\n * @param agent - Return value from `createAgent` (or equivalent) with a `tools` array.\n * @throws Error if tools are missing or `chat_tool` is not present.\n *\n * @remarks **Callers:** user code before `RemotePlayWorld.addAgent`. **Callees:** internal validation helpers and {@link agentPlayDebug}.\n */\nexport function langchainRegistration(\n agent: unknown\n): LangChainAgentRegistration {\n const rawTools = extractToolsArray(agent);\n if (rawTools === null) {\n throw new Error(formatMissingAgentToolsError());\n }\n const tools =\n rawTools as readonly { name: string; description?: string; schema?: unknown }[];\n const names = tools.map((x) => x.name);\n if (!names.includes(CHAT_TOOL)) {\n throw new Error(formatMissingChatToolError());\n }\n const assistTools = tools\n .filter((t) => t.name.startsWith(\"assist_\"))\n .map((t) => describeTool(t));\n agentPlayDebug(\"langchain\", \"langchainRegistration\", {\n toolCount: names.length,\n assistCount: assistTools.length,\n });\n return {\n type: \"langchain\",\n toolNames: names,\n assistTools,\n };\n}\n","import type {\n AddAgentInput,\n AddPlayerInput,\n AgentPlaySnapshot,\n AgentPlayWorldMap,\n AgentPlayWorldMapBounds,\n Journey,\n RecordInteractionInput,\n RegisteredAgentSummary,\n RegisteredPlayer,\n PlayerChainNodeResponse,\n} from \"../public-types.js\";\nimport { agentPlayDebug } from \"./agent-play-debug.js\";\nimport {\n SESSION_CLOSED_EVENT,\n SESSION_CONNECTED_EVENT,\n type RemotePlayWorldSessionEvent,\n} from \"../world-events.js\";\nimport { randomUUID } from \"node:crypto\";\nimport {\n deriveNodeIdFromPassword,\n loadAgentPlayCredentialsFileFromPathSync,\n loadRootKey,\n nodeCredentialsMaterialFromHumanPassphrase,\n resolveAgentPlayCredentialsPath,\n} from \"@agent-play/node-tools\";\nimport {\n parseHumanOccupantRow,\n parseAgentOccupantRow,\n parseMcpOccupantRow,\n} from \"./parse-occupant-row.js\";\nimport {\n mergeSnapshotWithPlayerChainNode,\n parsePlayerChainFanoutNotifyFromSsePayload,\n parsePlayerChainNodeRpcBody,\n sortNodeRefsForSerializedFetch,\n} from \"./player-chain-merge.js\";\nimport { HumanMessage } from \"@langchain/core/messages\";\nimport {\n INTERCOM_RESPONSE_OP,\n type IntercomResponsePayload,\n parseWorldIntercomEventPayload,\n type WorldIntercomEventPayload,\n WORLD_INTERCOM_EVENT,\n} from \"@agent-play/intercom\";\nimport { intercomResultRecordFromLangChainInvokeOutput } from \"./intercom-langchain-chat-result.js\";\n\nconst PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS = 10;\nconst PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS = 10_000;\n\n/**\n * Root key (from `.root`) plus **human** passphrase as stored in **`~/.agent-play/credentials.json`**\n * after **`agent-play create-main-node`**. Material for node id and wire auth is\n * **`nodeCredentialsMaterialFromHumanPassphrase(passw)`** (SHA-256 hex; same as CLI **`hashNodePassword`**).\n */\nexport type RemotePlayWorldNodeCredentials = {\n rootKey: string;\n passw: string;\n};\n\nexport type RemotePlayWorldLogging = \"off\" | \"on\";\n\nexport type RemotePlayWorldOptions = {\n baseUrl?: string;\n /**\n * `rootKey` from `.root` and **`passw`** human phrase from **`credentials.json`** (see **`loadAgentPlayCredentialsFileFromPathSync`** in **@agent-play/node-tools**).\n */\n nodeCredentials?: RemotePlayWorldNodeCredentials;\n /** Called for session lifecycle events (`session:connected`, `session:closed`; see `world-events`). */\n onSessionEvent?: (event: RemotePlayWorldSessionEvent) => void;\n /**\n * When **`\"on\"`**, prints **`console.info`** lines for session events, SSE messages, intercom command matching/skips, and **`sendIntercomResponse`** payloads (for request tracing). Default **`\"off\"`**.\n */\n logging?: RemotePlayWorldLogging;\n};\n\n/** Options for {@link RemotePlayWorld.connect}. */\nexport type RemotePlayWorldConnectOptions = {\n /**\n * Parent **main** node id. When set, `connect` runs `POST /api/nodes/validate` first, then `GET /api/agent-play/session`.\n * When omitted, only `GET /api/agent-play/session` runs.\n */\n mainNodeId?: string;\n};\n\nfunction formatMissingCredentialsError(): string {\n return [\n \"RemotePlayWorld: provide nodeCredentials: { rootKey, passw },\",\n \"or run agent-play create-main-node so ~/.agent-play/credentials.json exists.\",\n ].join(\" \");\n}\n\nfunction formatMissingBaseUrlError(): string {\n return [\n \"RemotePlayWorld: baseUrl is missing.\",\n \"Provide options.baseUrl, or ensure credentials.json contains serverUrl.\",\n ].join(\" \");\n}\n\nfunction normalizeBaseUrl(url: string): string {\n return url.replace(/\\/$/, \"\");\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null;\n}\n\nfunction parseBounds(raw: unknown): AgentPlayWorldMapBounds {\n if (!isRecord(raw)) {\n throw new Error(\"getWorldSnapshot: worldMap.bounds must be an object\");\n }\n const { minX, minY, maxX, maxY } = raw;\n if (\n typeof minX !== \"number\" ||\n typeof minY !== \"number\" ||\n typeof maxX !== \"number\" ||\n typeof maxY !== \"number\"\n ) {\n throw new Error(\n \"getWorldSnapshot: bounds need numeric minX, minY, maxX, maxY\"\n );\n }\n return { minX, minY, maxX, maxY };\n}\n\nfunction parseWorldMap(raw: unknown): AgentPlayWorldMap {\n if (!isRecord(raw)) {\n throw new Error(\"getWorldSnapshot: worldMap must be an object\");\n }\n const bounds = parseBounds(raw.bounds);\n const occ = raw.occupants;\n if (!Array.isArray(occ)) {\n throw new Error(\"getWorldSnapshot: worldMap.occupants must be an array\");\n }\n const occupants: AgentPlayWorldMap[\"occupants\"] = [];\n const coordKeys = new Set<string>();\n for (const row of occ) {\n if (\n !isRecord(row) ||\n (row.kind !== \"human\" && row.kind !== \"agent\" && row.kind !== \"mcp\")\n ) {\n throw new Error(\n \"getWorldSnapshot: each occupant must have kind human, agent, or mcp\"\n );\n }\n const xy =\n typeof row.x === \"number\" && typeof row.y === \"number\"\n ? `${row.x},${row.y}`\n : \"\";\n if (xy.length === 0) {\n throw new Error(\"getWorldSnapshot: occupant missing coordinates\");\n }\n if (coordKeys.has(xy)) {\n throw new Error(\"getWorldSnapshot: duplicate world map coordinate\");\n }\n coordKeys.add(xy);\n if (row.kind === \"human\") {\n occupants.push(parseHumanOccupantRow(row));\n } else if (row.kind === \"agent\") {\n occupants.push(parseAgentOccupantRow(row));\n } else {\n occupants.push(parseMcpOccupantRow(row));\n }\n }\n return { bounds, occupants };\n}\n\nfunction parseAgentPlaySnapshot(snapshot: unknown): AgentPlaySnapshot {\n if (!isRecord(snapshot) || typeof snapshot.sid !== \"string\") {\n throw new Error(\"getWorldSnapshot: invalid snapshot\");\n }\n const worldMap = parseWorldMap(snapshot.worldMap);\n const out: AgentPlaySnapshot = { sid: snapshot.sid, worldMap };\n if (\"mcpServers\" in snapshot && Array.isArray(snapshot.mcpServers)) {\n const servers: NonNullable<AgentPlaySnapshot[\"mcpServers\"]> = [];\n for (const m of snapshot.mcpServers) {\n if (!isRecord(m) || typeof m.id !== \"string\" || typeof m.name !== \"string\") {\n continue;\n }\n const row: { id: string; name: string; url?: string } = {\n id: m.id,\n name: m.name,\n };\n if (typeof m.url === \"string\") row.url = m.url;\n servers.push(row);\n }\n if (servers.length > 0) out.mcpServers = servers;\n }\n return out;\n}\n\nfunction parseRegisteredAgentSummary(raw: unknown): RegisteredAgentSummary {\n if (!isRecord(raw)) {\n throw new Error(\"registerAgent: registeredAgent missing\");\n }\n if (typeof raw.agentId !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"registerAgent: registeredAgent.agentId and name required\");\n }\n if (!Array.isArray(raw.toolNames)) {\n throw new Error(\"registerAgent: registeredAgent.toolNames must be an array\");\n }\n const toolNames: string[] = [];\n for (const t of raw.toolNames) {\n if (typeof t !== \"string\") {\n throw new Error(\"registerAgent: registeredAgent.toolNames must be strings\");\n }\n toolNames.push(t);\n }\n if (\n typeof raw.zoneCount !== \"number\" ||\n typeof raw.yieldCount !== \"number\" ||\n typeof raw.flagged !== \"boolean\"\n ) {\n throw new Error(\"registerAgent: registeredAgent counters invalid\");\n }\n return {\n agentId: raw.agentId,\n name: raw.name,\n toolNames,\n zoneCount: raw.zoneCount,\n yieldCount: raw.yieldCount,\n flagged: raw.flagged,\n };\n}\n\nfunction formatInvalidHoldSecondsError(): string {\n return [\n \"RemotePlayWorld.hold().for(seconds): seconds must be a finite number.\",\n \"\",\n \" Example: await world.hold().for(3600)\",\n ].join(\"\\n\");\n}\n\nexport type RemotePlayWorldHold = {\n for: (seconds: number) => Promise<void>;\n};\n\nexport type IntercomToolExecutor = (input: {\n toolName: string;\n args: Record<string, unknown>;\n}) => Record<string, unknown> | Promise<Record<string, unknown>>;\n\ntype SubscribeIntercomChatAgents = {\n /**\n * Same LangChain agent instances passed to **`langchainRegistration`** (e.g. **`createAgent`** return values).\n * For **`kind: chat`**, **`invoke({ messages: [HumanMessage(text)] })`** is called with **`.call(agent, input)`** (no wrapping).\n */\n chatAgentsByPlayerId?: ReadonlyMap<string, unknown>;\n};\n\nexport type SubscribeIntercomCommandsOptions =\n | ({ playerId: string; executeTool: IntercomToolExecutor } & SubscribeIntercomChatAgents)\n | ({ playerIds: readonly string[]; executeTool: IntercomToolExecutor } &\n SubscribeIntercomChatAgents);\n\nfunction getSseEventName(msg: unknown): string | undefined {\n if (typeof msg !== \"object\" || msg === null) {\n return undefined;\n }\n const m = msg as Record<string, unknown>;\n if (typeof m.event === \"string\" && m.event.length > 0) {\n return m.event;\n }\n if (typeof m.type === \"string\" && m.type.length > 0) {\n return m.type;\n }\n return undefined;\n}\n\nfunction invokeLangChainChatAgent(\n agent: unknown,\n input: unknown\n): Promise<unknown> {\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"intercom: chat agent must be a non-null object\");\n }\n const inv = (agent as { invoke?: unknown }).invoke;\n if (typeof inv !== \"function\") {\n throw new Error(\"intercom: chat agent must have invoke()\");\n }\n return Promise.resolve(\n (inv as (this: unknown, i: unknown) => unknown).call(agent, input)\n );\n}\n\nfunction normalizeIntercomSubscribePlayerIds(\n options: SubscribeIntercomCommandsOptions\n): Set<string> {\n const raw =\n \"playerIds\" in options ? [...options.playerIds] : [options.playerId];\n return new Set(\n raw.map((id) => id.trim()).filter((id) => id.length > 0)\n );\n}\n\n/**\n * HTTP client for the Agent Play web UI: session, snapshot RPC, mutating RPC with `sid`, and optional SSE subscription.\n *\n * Authenticates like the CLI: **`x-node-id`** (derived node id) and **`x-node-passw`** (hashed passphrase material) on every request.\n *\n * Register automation agents with {@link RemotePlayWorld.addAgent} (`nodeId` is the agent node id; the server stores it as `agentId`).\n *\n * Incremental updates: {@link RemotePlayWorld.subscribeWorldState} listens for **`playerChainNotify`** in SSE `data`, then fetches each changed leaf via {@link RemotePlayWorld.getPlayerChainNode} and merges with {@link mergeSnapshotWithPlayerChainNode}.\n *\n * Human→agent intercom (Assist/Chat from the watch UI) is delivered as SSE **`world:intercom`** payloads with status **`forwarded`**. Call {@link RemotePlayWorld.subscribeIntercomCommands} with **`playerId`** or **`playerIds`** (one SSE stream; routes **`forwarded`** commands by **`toPlayerId`**) so your process runs tools and posts **`intercomResponse`** via {@link RemotePlayWorld.sendIntercomResponse} (the subscription does this when **`executeTool`** resolves).\n *\n * Set **`logging: \"on\"`** to trace **`forwarded`** commands for subscribed ids and **`sendIntercomResponse`** HTTP results.\n */\nexport class RemotePlayWorld {\n private readonly apiBase: string;\n private readonly rootKey: string;\n /** Node id derived from hashed passphrase material + root (main or agent node id). */\n private readonly derivedNodeId: string;\n /** Hex password material (`hashNodePassword` on normalized human phrase); sent as `password` for repository addAgent. */\n private readonly password: string;\n private readonly onSessionEvent:\n | ((event: RemotePlayWorldSessionEvent) => void)\n | undefined;\n private readonly transportLog: boolean;\n private sid: string | null = null;\n private closed = false;\n private readonly closeListeners = new Set<() => void>();\n private readonly playerConnectionInfo = new Map<\n string,\n { connectionId: string; leaseTtlSeconds: number; timer: ReturnType<typeof setInterval> }\n >();\n\n constructor(options: RemotePlayWorldOptions = {}) {\n const creds = loadAgentPlayCredentialsFileFromPathSync(\n resolveAgentPlayCredentialsPath()\n );\n const resolvedBaseUrl = options.baseUrl ?? creds?.serverUrl;\n if (resolvedBaseUrl === undefined || resolvedBaseUrl.trim().length === 0) {\n throw new Error(formatMissingBaseUrlError());\n }\n this.apiBase = normalizeBaseUrl(resolvedBaseUrl);\n this.onSessionEvent = options.onSessionEvent;\n this.transportLog = options.logging === \"on\";\n\n const nc =\n options.nodeCredentials ??\n (creds === null ? undefined : { rootKey: loadRootKey(), passw: creds.passw });\n if (\n nc !== undefined &&\n typeof nc.rootKey === \"string\" &&\n nc.rootKey.trim().length > 0 &&\n typeof nc.passw === \"string\" &&\n nc.passw.length > 0\n ) {\n this.rootKey = nc.rootKey.trim().toLowerCase();\n const material = nodeCredentialsMaterialFromHumanPassphrase(nc.passw);\n this.password = material;\n this.derivedNodeId = deriveNodeIdFromPassword({\n password: material,\n rootKey: this.rootKey,\n });\n return;\n }\n\n throw new Error(formatMissingCredentialsError());\n }\n\n private logTransport(event: string, detail: Record<string, unknown>): void {\n if (!this.transportLog) {\n return;\n }\n console.info(`[agent-play:RemotePlayWorld] ${event}`, detail);\n }\n\n private truncateForLog(value: string, max = 1600): string {\n return value.length <= max ? value : `${value.slice(0, max)}…`;\n }\n\n private emitSessionEvent(event: RemotePlayWorldSessionEvent): void {\n this.logTransport(\"session:event\", {\n name: event.name,\n detail: event.detail ?? {},\n });\n this.onSessionEvent?.(event);\n }\n\n onClose(handler: () => void): () => void {\n this.closeListeners.add(handler);\n return () => {\n this.closeListeners.delete(handler);\n };\n }\n\n hold(): RemotePlayWorldHold {\n return {\n for: async (seconds: number) => {\n if (typeof seconds !== \"number\" || !Number.isFinite(seconds)) {\n throw new Error(formatInvalidHoldSecondsError());\n }\n const ms = Math.max(0, seconds) * 1000;\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n },\n };\n }\n\n private authHeaders(): Record<string, string> {\n return {\n \"x-node-id\": this.derivedNodeId,\n \"x-node-passw\": this.password,\n };\n }\n\n private jsonHeaders(): Record<string, string> {\n return {\n \"content-type\": \"application/json\",\n ...this.authHeaders(),\n };\n }\n\n private mergeAuthFetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const headers = new Headers(init?.headers);\n const auth = this.authHeaders();\n for (const [k, v] of Object.entries(auth)) {\n headers.set(k, v);\n }\n return fetch(input, { ...init, headers });\n }\n\n private async validateNodeIdentity(options: {\n nodeId: string;\n mainNodeId: string | undefined;\n }): Promise<{ nodeKind?: string }> {\n const body: { nodeId: string; rootKey: string; mainNodeId?: string } = {\n nodeId: options.nodeId,\n rootKey: this.rootKey,\n };\n if (options.mainNodeId !== undefined && options.mainNodeId.trim().length > 0) {\n body.mainNodeId = options.mainNodeId.trim();\n }\n const res = await fetch(`${this.apiBase}/api/nodes/validate`, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify(body),\n });\n let json: unknown;\n try {\n json = (await res.json()) as unknown;\n } catch {\n throw new Error(`node validation failed: ${String(res.status)} invalid JSON`);\n }\n if (!isRecord(json) || json.ok !== true) {\n const reason =\n isRecord(json) && typeof json.reason === \"string\" ? json.reason : `HTTP ${String(res.status)}`;\n throw new Error(`node validation failed: ${reason}`);\n }\n const nodeKind =\n isRecord(json) && typeof json.nodeKind === \"string\" ? json.nodeKind : undefined;\n agentPlayDebug(\"remote-play-world\", \"node identity validated\", {\n nodeKind,\n derivedNodeIdPrefix: `${this.derivedNodeId.slice(0, 8)}…`,\n });\n return nodeKind !== undefined ? { nodeKind } : {};\n }\n\n /**\n * Establishes the HTTP session via `GET /api/agent-play/session`. With {@link RemotePlayWorldConnectOptions.mainNodeId},\n * validates node identity with `POST /api/nodes/validate` first.\n */\n async connect(options?: RemotePlayWorldConnectOptions): Promise<void> {\n const mainNodeIdOpt = options?.mainNodeId?.trim();\n if (mainNodeIdOpt !== undefined && mainNodeIdOpt.length > 0) {\n const validation = await this.validateNodeIdentity({\n nodeId: this.derivedNodeId,\n mainNodeId: mainNodeIdOpt,\n });\n console.info(\n `[agent-play] Node identity validated (${validation.nodeKind ?? \"unknown\"}).`\n );\n }\n const res = await fetch(`${this.apiBase}/api/agent-play/session`, {\n headers: this.authHeaders(),\n });\n if (!res.ok) {\n throw new Error(`session failed: ${res.status}`);\n }\n const json: unknown = await res.json();\n if (!isRecord(json) || typeof json.sid !== \"string\" || json.sid.length === 0) {\n throw new Error(\"session: invalid response\");\n }\n this.sid = json.sid;\n this.logTransport(\"connect:session\", {\n sid: this.sid,\n apiBase: this.apiBase,\n });\n this.emitSessionEvent({\n name: SESSION_CONNECTED_EVENT,\n detail: { sid: this.sid },\n });\n }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n for (const [playerId, connection] of Array.from(\n this.playerConnectionInfo.entries()\n )) {\n clearInterval(connection.timer);\n try {\n await this.disconnectPlayerConnection({\n playerId,\n connectionId: connection.connectionId,\n });\n } catch {\n // ignore disconnect errors during close\n }\n }\n this.playerConnectionInfo.clear();\n this.closed = true;\n this.emitSessionEvent({ name: SESSION_CLOSED_EVENT });\n for (const handler of Array.from(this.closeListeners)) {\n try {\n handler();\n } catch {\n // ignore listener errors\n }\n }\n }\n\n getSessionId(): string {\n if (this.sid === null) {\n throw new Error(\"RemotePlayWorld.connect() must be called first\");\n }\n return this.sid;\n }\n\n getPreviewUrl(): string {\n const u = new URL(\"/agent-play/watch\", this.apiBase);\n u.search = \"\";\n return u.toString();\n }\n\n async getWorldSnapshot(): Promise<AgentPlaySnapshot> {\n const res = await fetch(`${this.apiBase}/api/agent-play/sdk/rpc`, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({ op: \"getWorldSnapshot\", payload: {} }),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`getWorldSnapshot: ${res.status} ${text}`);\n }\n let json: unknown;\n try {\n json = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"getWorldSnapshot: invalid JSON\");\n }\n if (!isRecord(json) || !(\"snapshot\" in json)) {\n throw new Error(\"getWorldSnapshot: invalid response shape\");\n }\n return parseAgentPlaySnapshot(json.snapshot);\n }\n\n /**\n * Fetches one player-chain node (genesis, header, occupant row, or removal) for `stableKey`, same snapshot scope as {@link RemotePlayWorld.getWorldSnapshot}.\n */\n async getPlayerChainNode(stableKey: string): Promise<PlayerChainNodeResponse> {\n const trimmed = stableKey.trim();\n if (trimmed.length === 0) {\n throw new Error(\"getPlayerChainNode: stableKey is required\");\n }\n const res = await fetch(`${this.apiBase}/api/agent-play/sdk/rpc`, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({\n op: \"getPlayerChainNode\",\n payload: { stableKey: trimmed },\n }),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`getPlayerChainNode: ${res.status} ${text}`);\n }\n let json: unknown;\n try {\n json = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"getPlayerChainNode: invalid JSON\");\n }\n return parsePlayerChainNodeRpcBody(json);\n }\n\n /**\n * Opens the session SSE stream, emits an initial snapshot from {@link RemotePlayWorld.getWorldSnapshot}, then on each **`playerChainNotify`** merges nodes in deterministic order via {@link RemotePlayWorld.getPlayerChainNode}.\n */\n subscribeWorldState(callbacks: {\n onSnapshot: (snapshot: AgentPlaySnapshot) => void;\n onError?: (err: Error) => void;\n onIntercomEvent?: (payload: WorldIntercomEventPayload) => void;\n }): { close: () => void } {\n let closeSource: (() => void) | null = null;\n const task = (async () => {\n try {\n const { createEventSource } = await import(\"eventsource-client\");\n let snapshot = await this.getWorldSnapshot();\n callbacks.onSnapshot(snapshot);\n const sseUrl = `${this.apiBase}/api/agent-play/events?sid=${encodeURIComponent(\n this.getSessionId()\n )}`;\n this.logTransport(\"subscribeWorldState:sse_open\", { sseUrl });\n const source = createEventSource({\n url: sseUrl,\n fetch: (input, init) => this.mergeAuthFetch(input, init),\n });\n closeSource = () => {\n source.close();\n };\n for await (const msg of source) {\n const eventType =\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n typeof (msg as { type?: unknown }).type === \"string\"\n ? (msg as { type: string }).type\n : \"(no type)\";\n if (typeof msg.data !== \"string\") {\n this.logTransport(\"sse:worldState:skip\", {\n reason: \"data_not_string\",\n eventType,\n });\n continue;\n }\n this.logTransport(\"sse:worldState:message\", {\n eventType,\n dataLength: msg.data.length,\n dataPreview: this.truncateForLog(msg.data),\n });\n let data: unknown;\n try {\n data = JSON.parse(msg.data) as unknown;\n } catch {\n this.logTransport(\"sse:worldState:parseJson\", {\n reason: \"invalid_json\",\n eventType,\n });\n continue;\n }\n if (callbacks.onIntercomEvent) {\n try {\n const inter = parseWorldIntercomEventPayload(data);\n this.logTransport(\"sse:worldState:intercom\", {\n status: inter.status,\n requestId: inter.requestId,\n kind: inter.kind,\n channelKey: inter.channelKey,\n });\n callbacks.onIntercomEvent(inter);\n } catch {\n this.logTransport(\"sse:worldState:intercom\", {\n reason: \"not_world_intercom_payload\",\n });\n }\n }\n const notify = parsePlayerChainFanoutNotifyFromSsePayload(data);\n if (notify === undefined || notify.nodes.length === 0) {\n continue;\n }\n this.logTransport(\"sse:worldState:playerChainNotify\", {\n nodeCount: notify.nodes.length,\n stableKeys: notify.nodes.map((n) => n.stableKey),\n });\n const ordered = sortNodeRefsForSerializedFetch(notify.nodes);\n for (const ref of ordered) {\n const node = await this.getPlayerChainNode(ref.stableKey);\n snapshot = mergeSnapshotWithPlayerChainNode(snapshot, node);\n }\n callbacks.onSnapshot(snapshot);\n }\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n this.logTransport(\"sse:worldState:error\", {\n message: err.message,\n });\n callbacks.onError?.(err);\n }\n })();\n return {\n close: () => {\n this.logTransport(\"subscribeWorldState:close\", {});\n closeSource?.();\n void task;\n },\n };\n }\n\n /**\n * Registers an automation agent using **agent node id** (`nodeId`), sent to the server as `agentId`.\n */\n async addAgent(input: AddAgentInput): Promise<RegisteredPlayer> {\n const sid = this.getSessionId();\n const effectiveMainNodeId = this.derivedNodeId;\n const validation = await this.validateNodeIdentity({\n nodeId: input.nodeId,\n mainNodeId: effectiveMainNodeId,\n });\n console.info(\n [\n \"Agent Node Connection\",\n ` status : validated`,\n ` nodeId : ${input.nodeId}`,\n ` nodeKind : ${validation.nodeKind ?? \"unknown\"}`,\n ` mainNode : ${effectiveMainNodeId}`,\n ].join(\"\\n\")\n );\n const url = `${this.apiBase}/api/agent-play/players?sid=${encodeURIComponent(sid)}`;\n const connectionId = randomUUID();\n const leaseTtlSeconds = 45;\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({\n name: input.name,\n type: input.type,\n agent: input.agent,\n mainNodeId: effectiveMainNodeId,\n password: this.password,\n agentId: input.nodeId,\n connectionId,\n leaseTtlSeconds,\n }),\n });\n const bodyText = await res.text();\n if (!res.ok) {\n throw new Error(`addAgent: ${res.status} ${bodyText}`);\n }\n let body: unknown;\n try {\n body = JSON.parse(bodyText) as unknown;\n } catch {\n throw new Error(\"addAgent: invalid JSON\");\n }\n if (!isRecord(body)) {\n throw new Error(\"addAgent: invalid response shape\");\n }\n const playerId = body.playerId;\n const previewUrl = body.previewUrl;\n if (typeof playerId !== \"string\" || typeof previewUrl !== \"string\") {\n throw new Error(\"addAgent: missing playerId or previewUrl\");\n }\n const registeredAgent = parseRegisteredAgentSummary(body.registeredAgent);\n const bodyConnectionId =\n typeof body.connectionId === \"string\" && body.connectionId.length > 0\n ? body.connectionId\n : connectionId;\n const bodyLeaseTtlSeconds =\n typeof body.leaseTtlSeconds === \"number\" && Number.isFinite(body.leaseTtlSeconds)\n ? body.leaseTtlSeconds\n : leaseTtlSeconds;\n const existingConnection = this.playerConnectionInfo.get(playerId);\n if (existingConnection !== undefined) {\n clearInterval(existingConnection.timer);\n }\n const timer = setInterval(() => {\n void this.heartbeatPlayerConnection({\n playerId,\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n }).catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n console.error(\"[agent-play:RemotePlayWorld] heartbeat:exhausted\", {\n playerId,\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n attempts: PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS,\n retryDelayMs: PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS,\n error: message,\n });\n });\n }, 12_000);\n this.playerConnectionInfo.set(playerId, {\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n timer,\n });\n const now = new Date();\n return {\n id: playerId,\n name: input.name,\n sid,\n createdAt: now,\n updatedAt: now,\n previewUrl,\n registeredAgent,\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n };\n }\n\n /**\n * @deprecated Use {@link addAgent} with `nodeId` (agent node id) for integrations and automation.\n */\n async addPlayer(input: AddPlayerInput): Promise<RegisteredPlayer> {\n const payload: AddAgentInput = {\n name: input.name,\n type: input.type,\n agent: input.agent,\n nodeId: input.agentId,\n };\n if (input.version !== undefined) {\n payload.version = input.version;\n }\n if (input.createdAt !== undefined) {\n payload.createdAt = input.createdAt;\n }\n if (input.updatedAt !== undefined) {\n payload.updatedAt = input.updatedAt;\n }\n if (input.mainNodeId !== undefined) {\n payload.mainNodeId = input.mainNodeId;\n }\n return this.addAgent(payload);\n }\n\n async recordInteraction(input: RecordInteractionInput): Promise<void> {\n await this.rpc(\"recordInteraction\", {\n playerId: input.playerId,\n role: input.role,\n text: input.text,\n });\n }\n\n async recordJourney(playerId: string, journey: Journey): Promise<void> {\n await this.rpc(\"recordJourney\", { playerId, journey });\n }\n\n async sendIntercomResponse(payload: IntercomResponsePayload): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/sdk/rpc?sid=${encodeURIComponent(sid)}`;\n this.logTransport(\"intercom:sendResponse:request\", {\n url,\n requestId: payload.requestId,\n toPlayerId: payload.toPlayerId,\n fromPlayerId: payload.fromPlayerId,\n kind: payload.kind,\n status: payload.status,\n toolName: payload.toolName,\n error: payload.error,\n resultPreview:\n payload.result !== undefined\n ? this.truncateForLog(JSON.stringify(payload.result))\n : undefined,\n });\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({ op: INTERCOM_RESPONSE_OP, payload }),\n });\n const okText = await res.text();\n this.logTransport(\"intercom:sendResponse:http\", {\n requestId: payload.requestId,\n httpStatus: res.status,\n bodyPreview: this.truncateForLog(okText),\n });\n if (!res.ok) {\n throw new Error(`intercomResponse: ${res.status} ${okText}`);\n }\n }\n\n /**\n * Subscribes to the session SSE stream and handles **`forwarded`** intercom commands whose **`toPlayerId`** is in **`playerId`** or **`playerIds`**, invoking **`executeTool`** and posting **`intercomResponse`** (**`completed`** / **`failed`**).\n * Uses a **single** SSE connection when **`playerIds`** lists multiple automation agents (recommended for several agents in one process).\n * Not invoked automatically by {@link RemotePlayWorld.addAgent}.\n */\n subscribeIntercomCommands(\n options: SubscribeIntercomCommandsOptions\n ): { close: () => void } {\n const subscribed = normalizeIntercomSubscribePlayerIds(options);\n const playerIdsSorted = Array.from(subscribed).sort();\n if (subscribed.size === 0) {\n this.logTransport(\"subscribeIntercomCommands:skip\", {\n reason: \"empty_player_ids\",\n });\n return { close: () => {} };\n }\n this.logTransport(\"subscribeIntercomCommands:start\", {\n playerIds: playerIdsSorted,\n });\n const { executeTool, chatAgentsByPlayerId } = options;\n let closeSource: (() => void) | null = null;\n const task = (async () => {\n try {\n const { createEventSource } = await import(\"eventsource-client\");\n const sseUrl = `${this.apiBase}/api/agent-play/events?sid=${encodeURIComponent(\n this.getSessionId()\n )}`;\n this.logTransport(\"subscribeIntercomCommands:sse_open\", {\n sseUrl,\n subscribePlayerIds: playerIdsSorted,\n });\n const source = createEventSource({\n url: sseUrl,\n fetch: (input, init) => this.mergeAuthFetch(input, init),\n });\n closeSource = () => {\n source.close();\n };\n for await (const msg of source) {\n const sseEvent = getSseEventName(msg);\n if (\n sseEvent !== undefined &&\n sseEvent !== WORLD_INTERCOM_EVENT\n ) {\n continue;\n }\n if (typeof msg.data !== \"string\") {\n const eventLabel = sseEvent ?? \"(unset)\";\n this.logTransport(\"sse:intercomCommands:skip\", {\n reason: \"data_not_string\",\n sseEvent: eventLabel,\n });\n continue;\n }\n let data: unknown;\n try {\n data = JSON.parse(msg.data) as unknown;\n } catch {\n this.logTransport(\"sse:intercomCommands:parseJson\", {\n reason: \"invalid_json\",\n sseEvent: sseEvent ?? \"(unset)\",\n });\n continue;\n }\n let inter: WorldIntercomEventPayload;\n try {\n inter = parseWorldIntercomEventPayload(data);\n } catch {\n continue;\n }\n if (inter.status !== \"forwarded\") {\n continue;\n }\n const cmd = inter.command;\n if (cmd === undefined) {\n this.logTransport(\"sse:intercomCommands:skip\", {\n reason: \"missing_command\",\n requestId: inter.requestId,\n });\n continue;\n }\n if (!subscribed.has(cmd.toPlayerId)) {\n continue;\n }\n this.logTransport(\"sse:intercomCommands:forwarded\", {\n requestId: cmd.requestId,\n fromPlayerId: cmd.fromPlayerId,\n toPlayerId: cmd.toPlayerId,\n kind: cmd.kind,\n toolName: cmd.toolName,\n });\n const toolName =\n cmd.kind === \"chat\" ? \"chat_tool\" : cmd.toolName ?? \"\";\n const args =\n cmd.kind === \"chat\" ? { text: cmd.text ?? \"\" } : (cmd.args ?? {});\n this.logTransport(\"intercom:executeTool\", {\n requestId: cmd.requestId,\n toolName,\n argsPreview: this.truncateForLog(JSON.stringify(args)),\n });\n try {\n this.logTransport(\"intercom:executeTool:started\", {\n requestId: cmd.requestId,\n toolName,\n argsPreview: this.truncateForLog(JSON.stringify(args)),\n });\n let result: Record<string, unknown>;\n if (\n cmd.kind === \"chat\" &&\n chatAgentsByPlayerId !== undefined &&\n chatAgentsByPlayerId.has(cmd.toPlayerId)\n ) {\n const lc = chatAgentsByPlayerId.get(cmd.toPlayerId);\n if (lc === undefined) {\n throw new Error(\"intercom: chatAgentsByPlayerId entry missing\");\n }\n this.logTransport(\"intercom:langchain:invoke\", {\n requestId: cmd.requestId,\n toPlayerId: cmd.toPlayerId,\n textPreview: this.truncateForLog(cmd.text ?? \"\"),\n });\n const rawOut = await invokeLangChainChatAgent(lc, {\n messages: [new HumanMessage(cmd.text ?? \"\")],\n });\n result = intercomResultRecordFromLangChainInvokeOutput(rawOut);\n this.logTransport(\"intercom:langchain:invoke:completed\", {\n requestId: cmd.requestId,\n resultPreview: this.truncateForLog(JSON.stringify(result)),\n });\n } else {\n result = await Promise.resolve(\n executeTool({ toolName, args })\n );\n }\n this.logTransport(\"intercom:executeTool:completed\", {\n requestId: cmd.requestId,\n toolName,\n argsPreview: this.truncateForLog(JSON.stringify(args)),\n resultPreview: this.truncateForLog(JSON.stringify(result)),\n });\n await this.sendIntercomResponse({\n requestId: cmd.requestId,\n mainNodeId: cmd.mainNodeId,\n toPlayerId: cmd.fromPlayerId,\n fromPlayerId: cmd.toPlayerId,\n kind: cmd.kind,\n status: \"completed\",\n toolName: cmd.toolName,\n ts: new Date().toISOString(),\n result,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logTransport(\"intercom:executeTool:error\", {\n requestId: cmd.requestId,\n message,\n });\n await this.sendIntercomResponse({\n requestId: cmd.requestId,\n mainNodeId: cmd.mainNodeId,\n toPlayerId: cmd.fromPlayerId,\n fromPlayerId: cmd.toPlayerId,\n kind: cmd.kind,\n status: \"failed\",\n toolName: cmd.toolName,\n error: message,\n ts: new Date().toISOString(),\n });\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logTransport(\"sse:intercomCommands:stream_error\", { message });\n }\n })();\n return {\n close: () => {\n this.logTransport(\"subscribeIntercomCommands:close\", {\n playerIds: playerIdsSorted,\n });\n closeSource?.();\n void task;\n },\n };\n }\n\n async registerMcp(options: { name: string; url?: string }): Promise<string> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/mcp/register?sid=${encodeURIComponent(sid)}`;\n const body: { name: string; url?: string } = { name: options.name };\n if (options.url !== undefined) {\n body.url = options.url;\n }\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify(body),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`registerMcp: ${res.status} ${text}`);\n }\n let json: unknown;\n try {\n json = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"registerMcp: invalid JSON\");\n }\n if (!isRecord(json) || typeof json.id !== \"string\") {\n throw new Error(\"registerMcp: invalid response\");\n }\n return json.id;\n }\n\n private async rpc(op: string, payload: unknown): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/sdk/rpc?sid=${encodeURIComponent(sid)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({ op, payload }),\n });\n if (!res.ok) {\n const t = await res.text();\n throw new Error(`rpc ${op}: ${res.status} ${t}`);\n }\n }\n\n private async heartbeatPlayerConnection(input: {\n playerId: string;\n connectionId: string;\n leaseTtlSeconds: number;\n }): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/players/heartbeat?sid=${encodeURIComponent(sid)}`;\n const bodyJson = JSON.stringify({\n playerId: input.playerId,\n connectionId: input.connectionId,\n leaseTtlSeconds: input.leaseTtlSeconds,\n });\n let lastError: Error = new Error(\"heartbeat: no attempts completed\");\n\n for (let attempt = 1; attempt <= PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS; attempt += 1) {\n const attemptStartedAt = Date.now();\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: bodyJson,\n });\n const text = await res.text();\n if (res.ok) {\n if (attempt > 1) {\n console.info(\"[agent-play:RemotePlayWorld] heartbeat:retry_recovered\", {\n playerId: input.playerId,\n connectionId: input.connectionId,\n leaseTtlSeconds: input.leaseTtlSeconds,\n sid,\n url,\n successfulAttempt: attempt,\n attemptsUsed: attempt,\n maxAttempts: PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS,\n durationMs: Date.now() - attemptStartedAt,\n });\n }\n return;\n }\n lastError = new Error(`heartbeat: ${res.status} ${text}`);\n } catch (err: unknown) {\n lastError =\n err instanceof Error ? err : new Error(String(err));\n }\n\n const willRetry = attempt < PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS;\n console.warn(\"[agent-play:RemotePlayWorld] heartbeat:attempt_failed\", {\n phase: \"player_connection_lease_refresh\",\n playerId: input.playerId,\n connectionId: input.connectionId,\n leaseTtlSeconds: input.leaseTtlSeconds,\n sid,\n url,\n attempt,\n maxAttempts: PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS,\n remainingAttemptsAfterThisFailure:\n PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS - attempt,\n errorMessage: lastError.message,\n requestBodyBytes: bodyJson.length,\n attemptDurationMs: Date.now() - attemptStartedAt,\n nextAction: willRetry\n ? `sleep ${PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS}ms then retry`\n : \"no more retries; will throw\",\n retryDelayMs: willRetry\n ? PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS\n : 0,\n });\n\n if (!willRetry) {\n throw lastError;\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS);\n });\n }\n }\n\n private async disconnectPlayerConnection(input: {\n playerId: string;\n connectionId: string;\n }): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/players/disconnect?sid=${encodeURIComponent(sid)}`;\n await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({\n playerId: input.playerId,\n connectionId: input.connectionId,\n }),\n });\n }\n}\n","function contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .map((block) => {\n if (typeof block === \"string\") {\n return block;\n }\n if (typeof block === \"object\" && block !== null && \"text\" in block) {\n const t = (block as { text?: unknown }).text;\n return typeof t === \"string\" ? t : \"\";\n }\n return \"\";\n })\n .join(\"\");\n }\n if (content !== null && typeof content === \"object\" && \"text\" in content) {\n const t = (content as { text?: unknown }).text;\n return typeof t === \"string\" ? t : JSON.stringify(content);\n }\n return JSON.stringify(content);\n}\n\n/**\n * Maps a LangChain agent **`invoke`** result to a plain object suitable for **`intercomResponse`** **`result`**.\n */\nexport function intercomResultRecordFromLangChainInvokeOutput(\n output: unknown\n): Record<string, unknown> {\n if (output === null || typeof output !== \"object\") {\n return { mode: \"chat\", message: String(output) };\n }\n const o = output as Record<string, unknown>;\n if (\"structuredResponse\" in o && o.structuredResponse !== undefined) {\n const sr = o.structuredResponse;\n if (sr !== null && typeof sr === \"object\" && !Array.isArray(sr)) {\n return { ...sr };\n }\n return { mode: \"chat\", structuredResponse: sr };\n }\n const messages = o.messages;\n if (Array.isArray(messages) && messages.length > 0) {\n const last = messages[messages.length - 1];\n if (last !== null && typeof last === \"object\" && \"content\" in last) {\n const text = contentToText((last as { content: unknown }).content);\n if (text.trim().length > 0) {\n return { mode: \"chat\", message: text };\n }\n }\n }\n return { mode: \"chat\", output: o };\n}\n","/**\n * @packageDocumentation\n * Public entry for **@agent-play/sdk** (Node.js and browser `browser` export).\n *\n * **Primary APIs**\n * - {@link RemotePlayWorld} — HTTP client: load **`nodeCredentials`** (`rootKey`, human **`passw`**) from **`~/.agent-play/credentials.json`** via **@agent-play/node-tools**, then **`connect`**, **`getWorldSnapshot`**, **`addAgent`**, **`subscribeIntercomCommands`** (for automation agents handling intercom **`forwarded`** commands), **`recordInteraction`**, **`recordJourney`**, **`registerMcp`**, **`hold`**, **`onClose`**.\n * - {@link langchainRegistration} — build LangChain **`agent`** payloads for **`addAgent`**.\n * - {@link clampWorldPosition}, {@link WorldBounds} — shared world bounds for server and canvas.\n *\n * **Events** — Session and world events: {@link WORLD_INTERACTION_EVENT}, {@link SESSION_CONNECTED_EVENT}, and related symbols from this module.\n *\n * **Transport** — **`RemotePlayWorld`** uses `fetch`; **`subscribeWorldState`** consumes SSE **`playerChainNotify`** and **`getPlayerChainNode`** for incremental merges.\n *\n * **Wire note** — Fanout and SSE use **`playerChainNotify`** (node references). Legacy **`playerChainDelta`**-style digests on the wire are not used; use **`getWorldSnapshot`** if you need a full snapshot only.\n */\n\nexport type {\n AddAgentInput,\n AddPlayerInput,\n AgentPlaySnapshot,\n AgentPlayWorldMap,\n AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapBounds,\n AgentPlayWorldMapMcpOccupant,\n AssistToolFieldType,\n AssistToolParameterSpec,\n AssistToolSpec,\n LangChainAgentRegistration,\n PlayerChainFanoutNotify,\n PlayerChainGenesisNode,\n PlayerChainHeaderNode,\n PlayerChainNodeResponse,\n PlayerChainNotifyNodeRef,\n PlayerChainOccupantPresentNode,\n PlayerChainOccupantRemovedNode,\n PlayAgentInformation,\n PlatformAgentInformation,\n RecordInteractionInput,\n RegisteredAgentSummary,\n RegisteredPlayer,\n WorldInteractionRole,\n YieldEventInfo,\n ZoneEventInfo,\n} from \"./public-types.js\";\nexport type {\n DestinationJourneyStep,\n Journey,\n JourneyStep,\n OriginJourneyStep,\n PositionedStep,\n StructureJourneyStep,\n WorldJourneyUpdate,\n} from \"./public-types.js\";\nexport {\n PLAYER_ADDED_EVENT,\n SESSION_CLOSED_EVENT,\n SESSION_CONNECTED_EVENT,\n SESSION_INVALID_EVENT,\n SESSION_SSE_ERROR_EVENT,\n SESSION_SSE_OPEN_EVENT,\n WORLD_AGENT_SIGNAL_EVENT,\n WORLD_INTERACTION_EVENT,\n WORLD_JOURNEY_EVENT,\n type RemotePlayWorldSessionEvent,\n type WorldAgentSignalPayload,\n type WorldInteractionPayload,\n} from \"./world-events.js\";\nexport {\n clampWorldPosition,\n boundsContain,\n type WorldBounds,\n} from \"./lib/world-bounds.js\";\nexport {\n agentPlayDebug,\n configureAgentPlayDebug,\n isAgentPlayDebugEnabled,\n resetAgentPlayDebug,\n} from \"./lib/agent-play-debug.js\";\nexport { langchainRegistration } from \"./platforms/langchain.js\";\nexport {\n RemotePlayWorld,\n type IntercomToolExecutor,\n type RemotePlayWorldConnectOptions,\n type RemotePlayWorldHold,\n type RemotePlayWorldLogging,\n type RemotePlayWorldNodeCredentials,\n type RemotePlayWorldOptions,\n type SubscribeIntercomCommandsOptions,\n} from \"./lib/remote-play-world.js\";\nexport { intercomResultRecordFromLangChainInvokeOutput } from \"./lib/intercom-langchain-chat-result.js\";\nexport {\n mergeSnapshotWithPlayerChainNode,\n parsePlayerChainFanoutNotify,\n parsePlayerChainFanoutNotifyFromSsePayload,\n parsePlayerChainNodeRpcBody,\n sortNodeRefsForSerializedFetch,\n} from \"./lib/player-chain-merge.js\";\nexport {\n PLAYER_CHAIN_GENESIS_STABLE_KEY,\n PLAYER_CHAIN_HEADER_STABLE_KEY,\n} from \"./lib/world-chain-keys.js\";\nexport {\n type AgentPlayAgentNodeEntry,\n type AgentPlayCredentialsFile,\n loadAgentPlayCredentialsFileFromPath,\n loadAgentPlayCredentialsFileFromPathSync,\n loadRootKey,\n nodeCredentialsMaterialFromHumanPassphrase,\n parseAgentPlayCredentialsJson,\n resolveAgentPlayCredentialsPath,\n} from \"@agent-play/node-tools\";\n"],"mappings":"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","names":["loadAgentPlayCredentialsFileFromPathSync","loadRootKey","nodeCredentialsMaterialFromHumanPassphrase","resolveAgentPlayCredentialsPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/world-events.ts","../src/lib/agent-play-debug.ts","../src/platforms/langchain.ts","../src/lib/remote-play-world.ts","../src/lib/intercom-langchain-chat-result.ts","../src/lib/openai-realtime-client-secret.ts","../src/index.ts"],"sourcesContent":["/**\n * String constants and payload shapes for SSE and in-process world events.\n *\n * @remarks **Emitters:** server `PlayWorld` and Redis fanout. **Consumers:** watch UI `EventSource`,\n * integration tests, and any host that forwards `POST` events.\n *\n * **Session vs world:** names prefixed with **`session:`** concern the HTTP/SDK session (`sid`) and\n * transport; names prefixed with **`world:`** concern occupants, chat, and map-visible state.\n */\nimport type { WorldInteractionRole } from \"./public-types.js\";\n\n/** After `RemotePlayWorld.connect()` assigns a `sid` (and optional detail such as `sid`). */\nexport const SESSION_CONNECTED_EVENT = \"session:connected\";\n\n/** RPC or transport rejected the session (e.g. 401/403); optional `detail.status`. */\nexport const SESSION_INVALID_EVENT = \"session:invalid\";\n\n/** After `RemotePlayWorld.close()` completes teardown. */\nexport const SESSION_CLOSED_EVENT = \"session:closed\";\n\n/** SSE subscription opened (optional; emitted when wired). */\nexport const SESSION_SSE_OPEN_EVENT = \"session:sse_open\";\n\n/** SSE subscription error (optional; emitted when wired). */\nexport const SESSION_SSE_ERROR_EVENT = \"session:sse_error\";\n\nexport type RemotePlayWorldSessionEvent = {\n name: string;\n detail?: Record<string, unknown>;\n};\n\n/** Fired when `addAgent` / `addPlayer` completes; payload includes snapshot row for the new player. */\nexport const PLAYER_ADDED_EVENT = \"world:player_added\";\n\n/** Fired for each new chat/interaction line. */\nexport const WORLD_INTERACTION_EVENT = \"world:interaction\";\n\n/** Lightweight signals (zone, yield, assist, journey metadata, etc.). */\nexport const WORLD_AGENT_SIGNAL_EVENT = \"world:agent_signal\";\n\n/** Full journey + path update for a player. */\nexport const WORLD_JOURNEY_EVENT = \"world:journey\";\n\n/**\n * Payload for {@link WORLD_AGENT_SIGNAL_EVENT}.\n *\n * @property playerId - Target player.\n * @property kind - Signal category; `journey` often carries `{ stepCount }` in `data`.\n * @property data - Optional free-form metadata.\n */\nexport type WorldAgentSignalPayload = {\n playerId: string;\n kind: \"zone\" | \"yield\" | \"assist\" | \"chat\" | \"metadata\" | \"journey\";\n data?: Record<string, unknown>;\n};\n\n/**\n * Payload for {@link WORLD_INTERACTION_EVENT}.\n *\n * @property seq - Monotonic sequence for ordering in the UI.\n */\nexport type WorldInteractionPayload = {\n playerId: string;\n role: WorldInteractionRole;\n text: string;\n at: string;\n seq: number;\n};\n","/**\n * Optional structured `console.debug` for SDK internals; gated by {@link configureAgentPlayDebug} or `AGENT_PLAY_DEBUG=1`.\n */\ntype DebugConfigure = {\n /** When set, overrides environment: `true` forces debug on, `false` forces off. */\n debug?: boolean;\n};\n\n/**\n * In-memory override for debug enablement (undefined = follow env only).\n *\n * @remarks **Writers:** {@link configureAgentPlayDebug}, {@link resetAgentPlayDebug}.\n * **Readers:** {@link isAgentPlayDebugEnabled}.\n */\nlet configuredDebug: boolean | undefined;\n\n/**\n * Sets whether SDK debug logging is enabled regardless of `AGENT_PLAY_DEBUG`.\n *\n * @param opts - Optional `{ debug }`: `true` / `false` forces logging; omit `debug` to clear override.\n *\n * @remarks **Callers:** tests and user code. **Callees:** none.\n */\nexport function configureAgentPlayDebug(opts: DebugConfigure): void {\n configuredDebug = opts.debug ?? undefined;\n}\n\n/**\n * Clears the in-memory override so only `AGENT_PLAY_DEBUG` applies.\n *\n * @remarks **Callers:** tests. **Callees:** none.\n */\nexport function resetAgentPlayDebug(): void {\n configuredDebug = undefined;\n}\n\n/**\n * @returns Whether debug logging should run: override wins, else `AGENT_PLAY_DEBUG === \"1\"`.\n *\n * @remarks **Callers:** {@link agentPlayDebug}. **Callees:** `process.env` read.\n */\nexport function isAgentPlayDebugEnabled(): boolean {\n if (configuredDebug === false) return false;\n if (configuredDebug === true) return true;\n return process.env.AGENT_PLAY_DEBUG === \"1\";\n}\n\n/** Max length of JSON detail string before truncation in the internal `safeSerialize` helper. */\nconst MAX_JSON_LENGTH = 2000;\n\n/**\n * Serializes `detail` for log lines, truncating long JSON and handling circular refs.\n *\n * @internal\n * @remarks **Callers:** {@link agentPlayDebug} only. **Callees:** `JSON.stringify` with replacer.\n */\nfunction safeSerialize(detail: unknown): string {\n if (detail === undefined) return \"\";\n try {\n const seen = new WeakSet<object>();\n const json = JSON.stringify(detail, (_k, v: unknown) => {\n if (typeof v === \"object\" && v !== null) {\n if (seen.has(v)) return \"[Circular]\";\n seen.add(v);\n }\n if (typeof v === \"bigint\") return String(v);\n return v;\n });\n if (typeof json !== \"string\") return String(detail);\n return json.length > MAX_JSON_LENGTH\n ? `${json.slice(0, MAX_JSON_LENGTH)}…`\n : json;\n } catch {\n return String(detail);\n }\n}\n\n/**\n * Emits `console.debug` when {@link isAgentPlayDebugEnabled} is true.\n *\n * @param scope - Short label (e.g. `\"langchain\"`).\n * @param message - Human-readable message.\n * @param detail - Optional object serialized by the internal truncation helper (see source).\n *\n * @remarks **Callers:** {@link langchainRegistration} and other SDK modules. **Callees:** {@link isAgentPlayDebugEnabled} and the internal serializer.\n */\nexport function agentPlayDebug(\n scope: string,\n message: string,\n detail?: unknown\n): void {\n if (!isAgentPlayDebugEnabled()) return;\n const tail =\n detail === undefined ? \"\" : ` ${safeSerialize(detail)}`;\n console.debug(`[agent-play:${scope}] ${message}${tail}`);\n}\n","/**\n * LangChain adapter: derives tool names and assist metadata from a LangChain agent for\n * {@link LangChainAgentRegistration}.\n *\n * @remarks **Primary export:** {@link langchainRegistration}. Private helpers build error strings and\n * `AssistToolSpec` rows from Zod schemas when available.\n */\nimport { agentPlayDebug } from \"../lib/agent-play-debug.js\";\nimport type {\n AssistToolFieldType,\n AssistToolSpec,\n LangChainAgentRegistration,\n} from \"../public-types.js\";\n\n/** Required tool name enforced by the watch UI contract. */\nconst CHAT_TOOL = \"chat_tool\";\n\n/**\n * Error text when the agent has no `tools` array.\n *\n * @remarks **Callers:** {@link langchainRegistration}. **Callees:** none.\n */\nfunction formatMissingAgentToolsError(): string {\n return [\n \"langchainRegistration: expected a LangChain agent with a tools array.\",\n \"\",\n \" Pass the object returned from createAgent({ tools: [...] }) (or equivalent) so tool names are available for the play world.\",\n \" The tools array must include named tools; see the separate message if \\\"chat_tool\\\" or assist_* tools are missing.\",\n ].join(\"\\n\");\n}\n\n/**\n * Error text when `chat_tool` is missing from tool names.\n *\n * @remarks **Callers:** {@link langchainRegistration}. **Callees:** none.\n */\nfunction formatMissingChatToolError(): string {\n return [\n \"langchainRegistration: missing required tool \\\"chat_tool\\\".\",\n \"\",\n \" Add a tool named \\\"chat_tool\\\" to your LangChain agent so the play world can show chat and proximity interactions.\",\n \" Example: tool(() => \\\"…\\\", { name: \\\"chat_tool\\\", description: \\\"…\\\", schema: z.object({ … }) })\",\n \"\",\n \" Tools whose names start with \\\"assist_\\\" are listed as assist actions on the watch UI; give each a Zod object schema so parameters can be shown in the UI.\",\n ].join(\"\\n\");\n}\n\ntype ZodDef = {\n typeName?: string;\n innerType?: unknown;\n schema?: unknown;\n};\n\nfunction unwrapZodCell(cell: unknown): unknown {\n let current: unknown = cell;\n for (let depth = 0; depth < 32; depth++) {\n if (current === null || typeof current !== \"object\") {\n return current;\n }\n const def = (current as { _def?: ZodDef })._def;\n if (!def || typeof def.typeName !== \"string\") {\n return current;\n }\n const { typeName } = def;\n if (\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\" ||\n typeName === \"ZodDefault\"\n ) {\n const inner = def.innerType;\n current =\n inner !== null && typeof inner === \"object\" ? inner : undefined;\n continue;\n }\n if (typeName === \"ZodEffects\") {\n current = def.schema;\n continue;\n }\n return current;\n }\n return current;\n}\n\nfunction fieldTypeFromZodCell(cell: unknown): AssistToolFieldType {\n const base = unwrapZodCell(cell);\n if (base === null || typeof base !== \"object\") {\n return \"string\";\n }\n const typeName = (base as { _def?: { typeName?: string } })._def?.typeName;\n if (typeName === \"ZodNumber\") {\n return \"number\";\n }\n if (typeName === \"ZodBoolean\") {\n return \"boolean\";\n }\n if (typeName === \"ZodString\") {\n return \"string\";\n }\n return \"string\";\n}\n\n/**\n * Best-effort parameter shape from a Zod object schema’s `shape()` for UI hints.\n *\n * @remarks **Callers:** {@link describeTool}. **Callees:** none.\n */\nfunction parametersFromSchema(schema: unknown): Record<string, unknown> {\n if (schema === null || typeof schema !== \"object\") {\n return {};\n }\n const z = schema as {\n _def?: { typeName?: string; shape?: () => Record<string, unknown> };\n };\n if (typeof z._def?.shape !== \"function\") {\n return { _note: \"Pass a Zod object schema on each tool for parameter hints in the watch UI.\" };\n }\n const shape = z._def.shape();\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(shape)) {\n out[key] = {\n field: key,\n fieldType: fieldTypeFromZodCell(shape[key]),\n };\n }\n return out;\n}\n\n/**\n * Builds an {@link AssistToolSpec} from a LangChain tool descriptor.\n *\n * @remarks **Callers:** {@link langchainRegistration} for `assist_*` tools only. **Callees:** {@link parametersFromSchema}.\n */\nfunction describeTool(t: {\n name: string;\n description?: string;\n schema?: unknown;\n}): AssistToolSpec {\n return {\n name: t.name,\n description:\n typeof t.description === \"string\" && t.description.length > 0\n ? t.description\n : t.name,\n parameters: parametersFromSchema(t.schema),\n };\n}\n\n/**\n * Reads `agent.tools` or `agent.options.tools` from common LangChain agent shapes.\n *\n * @returns The tools array, or `null` if not found.\n *\n * @remarks **Callers:** {@link langchainRegistration} only. **Callees:** none.\n */\nfunction extractToolsArray(agent: unknown): unknown[] | null {\n if (typeof agent !== \"object\" || agent === null) {\n return null;\n }\n const a = agent as {\n tools?: unknown;\n options?: { tools?: unknown };\n };\n if (Array.isArray(a.tools)) {\n return a.tools;\n }\n if (\n a.options !== undefined &&\n typeof a.options === \"object\" &&\n a.options !== null &&\n \"tools\" in a.options &&\n Array.isArray((a.options as { tools: unknown }).tools)\n ) {\n return (a.options as { tools: unknown[] }).tools;\n }\n return null;\n}\n\n/**\n * Validates a LangChain-style agent exposes tools (including required `chat_tool`) and returns\n * a {@link LangChainAgentRegistration} for `RemotePlayWorld.addAgent`.\n *\n * @param agent - Return value from `createAgent` (or equivalent) with a `tools` array.\n * @throws Error if tools are missing or `chat_tool` is not present.\n *\n * @remarks **Callers:** user code before `RemotePlayWorld.addAgent`. **Callees:** internal validation helpers and {@link agentPlayDebug}.\n */\nexport function langchainRegistration(\n agent: unknown\n): LangChainAgentRegistration {\n const rawTools = extractToolsArray(agent);\n if (rawTools === null) {\n throw new Error(formatMissingAgentToolsError());\n }\n const tools =\n rawTools as readonly { name: string; description?: string; schema?: unknown }[];\n const names = tools.map((x) => x.name);\n if (!names.includes(CHAT_TOOL)) {\n throw new Error(formatMissingChatToolError());\n }\n const assistTools = tools\n .filter((t) => t.name.startsWith(\"assist_\"))\n .map((t) => describeTool(t));\n agentPlayDebug(\"langchain\", \"langchainRegistration\", {\n toolCount: names.length,\n assistCount: assistTools.length,\n });\n return {\n type: \"langchain\",\n toolNames: names,\n assistTools,\n };\n}\n","import {\n type AddAgentInput,\n type AddPlayerInput,\n type AgentPlaySnapshot,\n type P2aEnableFlag,\n type RealtimeWebrtcClientSecret,\n type AgentPlayWorldMap,\n type AgentPlayWorldMapBounds,\n type Journey,\n type RecordInteractionInput,\n type RegisteredAgentSummary,\n type RegisteredPlayer,\n type PlayerChainNodeResponse,\n type RemotePlayWorldInitAudioOptions,\n type RemotePlayWorldOpenAiAudioOptions,\n} from \"../public-types.js\";\nimport { agentPlayDebug } from \"./agent-play-debug.js\";\nimport {\n SESSION_CLOSED_EVENT,\n SESSION_CONNECTED_EVENT,\n type RemotePlayWorldSessionEvent,\n} from \"../world-events.js\";\nimport { randomUUID } from \"node:crypto\";\nimport {\n deriveNodeIdFromPassword,\n loadAgentPlayCredentialsFileFromPathSync,\n loadRootKey,\n nodeCredentialsMaterialFromHumanPassphrase,\n resolveAgentPlayCredentialsPath,\n} from \"@agent-play/node-tools\";\nimport {\n parseHumanOccupantRow,\n parseAgentOccupantRow,\n parseMcpOccupantRow,\n} from \"./parse-occupant-row.js\";\nimport {\n mergeSnapshotWithPlayerChainNode,\n parsePlayerChainFanoutNotifyFromSsePayload,\n parsePlayerChainNodeRpcBody,\n sortNodeRefsForSerializedFetch,\n} from \"./player-chain-merge.js\";\nimport { HumanMessage } from \"@langchain/core/messages\";\nimport {\n INTERCOM_RESPONSE_OP,\n type IntercomResponsePayload,\n parseWorldIntercomEventPayload,\n type WorldIntercomEventPayload,\n WORLD_INTERCOM_EVENT,\n} from \"@agent-play/intercom\";\nimport { intercomResultRecordFromLangChainInvokeOutput } from \"./intercom-langchain-chat-result.js\";\nimport {\n mintOpenAiRealtimeClientSecretForSdk,\n resolveRealtimeInstructions,\n} from \"./openai-realtime-client-secret.js\";\n\nconst PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS = 10;\nconst PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS = 10_000;\n\n/**\n * Root key (from `.root`) plus **human** passphrase as stored in **`~/.agent-play/credentials.json`**\n * after **`agent-play create-main-node`**. Material for node id and wire auth is\n * **`nodeCredentialsMaterialFromHumanPassphrase(passw)`** (SHA-256 hex; same as CLI **`hashNodePassword`**).\n */\nexport type RemotePlayWorldNodeCredentials = {\n rootKey: string;\n passw: string;\n};\n\nexport type RemotePlayWorldLogging = \"off\" | \"on\";\n\nexport type RemotePlayWorldOptions = {\n baseUrl?: string;\n /**\n * `rootKey` from `.root` and **`passw`** human phrase from **`credentials.json`** (see **`loadAgentPlayCredentialsFileFromPathSync`** in **@agent-play/node-tools**).\n */\n nodeCredentials?: RemotePlayWorldNodeCredentials;\n /** Called for session lifecycle events (`session:connected`, `session:closed`; see `world-events`). */\n onSessionEvent?: (event: RemotePlayWorldSessionEvent) => void;\n /**\n * When **`\"on\"`**, prints **`console.info`** lines for session events, SSE messages, intercom command matching/skips, and **`sendIntercomResponse`** payloads (for request tracing). Default **`\"off\"`**.\n */\n logging?: RemotePlayWorldLogging;\n};\n\n/** Options for {@link RemotePlayWorld.connect}. */\nexport type RemotePlayWorldConnectOptions = {\n /**\n * Parent **main** node id. When set, `connect` runs `POST /api/nodes/validate` first, then `GET /api/agent-play/session`.\n * When omitted, only `GET /api/agent-play/session` runs.\n */\n mainNodeId?: string;\n};\n\nfunction formatMissingCredentialsError(): string {\n return [\n \"RemotePlayWorld: provide nodeCredentials: { rootKey, passw },\",\n \"or run agent-play create-main-node so ~/.agent-play/credentials.json exists.\",\n ].join(\" \");\n}\n\nfunction formatMissingBaseUrlError(): string {\n return [\n \"RemotePlayWorld: baseUrl is missing.\",\n \"Provide options.baseUrl, or ensure credentials.json contains serverUrl.\",\n ].join(\" \");\n}\n\nfunction normalizeBaseUrl(url: string): string {\n return url.replace(/\\/$/, \"\");\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null;\n}\n\nfunction parseBounds(raw: unknown): AgentPlayWorldMapBounds {\n if (!isRecord(raw)) {\n throw new Error(\"getWorldSnapshot: worldMap.bounds must be an object\");\n }\n const { minX, minY, maxX, maxY } = raw;\n if (\n typeof minX !== \"number\" ||\n typeof minY !== \"number\" ||\n typeof maxX !== \"number\" ||\n typeof maxY !== \"number\"\n ) {\n throw new Error(\n \"getWorldSnapshot: bounds need numeric minX, minY, maxX, maxY\"\n );\n }\n return { minX, minY, maxX, maxY };\n}\n\nfunction parseWorldMap(raw: unknown): AgentPlayWorldMap {\n if (!isRecord(raw)) {\n throw new Error(\"getWorldSnapshot: worldMap must be an object\");\n }\n const bounds = parseBounds(raw.bounds);\n const occ = raw.occupants;\n if (!Array.isArray(occ)) {\n throw new Error(\"getWorldSnapshot: worldMap.occupants must be an array\");\n }\n const occupants: AgentPlayWorldMap[\"occupants\"] = [];\n const coordKeys = new Set<string>();\n for (const row of occ) {\n if (\n !isRecord(row) ||\n (row.kind !== \"human\" && row.kind !== \"agent\" && row.kind !== \"mcp\")\n ) {\n throw new Error(\n \"getWorldSnapshot: each occupant must have kind human, agent, or mcp\"\n );\n }\n const xy =\n typeof row.x === \"number\" && typeof row.y === \"number\"\n ? `${row.x},${row.y}`\n : \"\";\n if (xy.length === 0) {\n throw new Error(\"getWorldSnapshot: occupant missing coordinates\");\n }\n if (coordKeys.has(xy)) {\n throw new Error(\"getWorldSnapshot: duplicate world map coordinate\");\n }\n coordKeys.add(xy);\n if (row.kind === \"human\") {\n occupants.push(parseHumanOccupantRow(row));\n } else if (row.kind === \"agent\") {\n occupants.push(parseAgentOccupantRow(row));\n } else {\n occupants.push(parseMcpOccupantRow(row));\n }\n }\n return { bounds, occupants };\n}\n\nfunction parseAgentPlaySnapshot(snapshot: unknown): AgentPlaySnapshot {\n if (!isRecord(snapshot) || typeof snapshot.sid !== \"string\") {\n throw new Error(\"getWorldSnapshot: invalid snapshot\");\n }\n const worldMap = parseWorldMap(snapshot.worldMap);\n const out: AgentPlaySnapshot = { sid: snapshot.sid, worldMap };\n if (\"mcpServers\" in snapshot && Array.isArray(snapshot.mcpServers)) {\n const servers: NonNullable<AgentPlaySnapshot[\"mcpServers\"]> = [];\n for (const m of snapshot.mcpServers) {\n if (!isRecord(m) || typeof m.id !== \"string\" || typeof m.name !== \"string\") {\n continue;\n }\n const row: { id: string; name: string; url?: string } = {\n id: m.id,\n name: m.name,\n };\n if (typeof m.url === \"string\") row.url = m.url;\n servers.push(row);\n }\n if (servers.length > 0) out.mcpServers = servers;\n }\n return out;\n}\n\nfunction parseRegisteredAgentSummary(raw: unknown): RegisteredAgentSummary {\n if (!isRecord(raw)) {\n throw new Error(\"registerAgent: registeredAgent missing\");\n }\n if (typeof raw.agentId !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"registerAgent: registeredAgent.agentId and name required\");\n }\n if (!Array.isArray(raw.toolNames)) {\n throw new Error(\"registerAgent: registeredAgent.toolNames must be an array\");\n }\n const toolNames: string[] = [];\n for (const t of raw.toolNames) {\n if (typeof t !== \"string\") {\n throw new Error(\"registerAgent: registeredAgent.toolNames must be strings\");\n }\n toolNames.push(t);\n }\n if (\n typeof raw.zoneCount !== \"number\" ||\n typeof raw.yieldCount !== \"number\" ||\n typeof raw.flagged !== \"boolean\"\n ) {\n throw new Error(\"registerAgent: registeredAgent counters invalid\");\n }\n return {\n agentId: raw.agentId,\n name: raw.name,\n toolNames,\n zoneCount: raw.zoneCount,\n yieldCount: raw.yieldCount,\n flagged: raw.flagged,\n };\n}\n\nfunction parseRealtimeWebrtcClientSecret(\n raw: unknown\n): RealtimeWebrtcClientSecret | undefined {\n if (!isRecord(raw)) {\n return undefined;\n }\n const clientSecret = raw.clientSecret;\n const model = raw.model;\n if (typeof clientSecret !== \"string\" || clientSecret.length === 0) {\n return undefined;\n }\n if (typeof model !== \"string\" || model.length === 0) {\n return undefined;\n }\n const parsed: RealtimeWebrtcClientSecret = {\n clientSecret,\n model,\n };\n if (typeof raw.expiresAt === \"string\" && raw.expiresAt.length > 0) {\n parsed.expiresAt = raw.expiresAt;\n }\n if (typeof raw.voice === \"string\" && raw.voice.length > 0) {\n parsed.voice = raw.voice;\n }\n return parsed;\n}\n\nfunction formatInvalidHoldSecondsError(): string {\n return [\n \"RemotePlayWorld.hold().for(seconds): seconds must be a finite number.\",\n \"\",\n \" Example: await world.hold().for(3600)\",\n ].join(\"\\n\");\n}\n\nexport type RemotePlayWorldHold = {\n for: (seconds: number) => Promise<void>;\n};\n\nexport type IntercomToolExecutor = (input: {\n toolName: string;\n args: Record<string, unknown>;\n}) => Record<string, unknown> | Promise<Record<string, unknown>>;\n\ntype SubscribeIntercomChatAgents = {\n /**\n * Same LangChain agent instances passed to **`langchainRegistration`** (e.g. **`createAgent`** return values).\n * For **`kind: chat`**, **`invoke({ messages: [HumanMessage(text)] })`** is called with **`.call(agent, input)`** (no wrapping).\n */\n chatAgentsByPlayerId?: ReadonlyMap<string, unknown>;\n};\n\nexport type SubscribeIntercomCommandsOptions =\n | ({ playerId: string; executeTool: IntercomToolExecutor } & SubscribeIntercomChatAgents)\n | ({ playerIds: readonly string[]; executeTool: IntercomToolExecutor } &\n SubscribeIntercomChatAgents);\n\nasync function resolveRealtimeWebrtcForIntercom(options: {\n audioInitOptions: RemotePlayWorldOpenAiAudioOptions | null;\n playerId: string;\n}): Promise<RealtimeWebrtcClientSecret> {\n if (options.audioInitOptions === null) {\n throw new Error(\n \"intercom realtime requires initAudio({ openai: ... }) in the agent process\"\n );\n }\n return mintOpenAiRealtimeClientSecretForSdk({\n openai: options.audioInitOptions,\n agentName: options.playerId,\n });\n}\n\nfunction getSseEventName(msg: unknown): string | undefined {\n if (typeof msg !== \"object\" || msg === null) {\n return undefined;\n }\n const m = msg as Record<string, unknown>;\n if (typeof m.event === \"string\" && m.event.length > 0) {\n return m.event;\n }\n if (typeof m.type === \"string\" && m.type.length > 0) {\n return m.type;\n }\n return undefined;\n}\n\nfunction invokeLangChainChatAgent(\n agent: unknown,\n input: unknown\n): Promise<unknown> {\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"intercom: chat agent must be a non-null object\");\n }\n const inv = (agent as { invoke?: unknown }).invoke;\n if (typeof inv !== \"function\") {\n throw new Error(\"intercom: chat agent must have invoke()\");\n }\n return Promise.resolve(\n (inv as (this: unknown, i: unknown) => unknown).call(agent, input)\n );\n}\n\nfunction normalizeIntercomSubscribePlayerIds(\n options: SubscribeIntercomCommandsOptions\n): Set<string> {\n const raw =\n \"playerIds\" in options ? [...options.playerIds] : [options.playerId];\n return new Set(\n raw.map((id) => id.trim()).filter((id) => id.length > 0)\n );\n}\n\n/**\n * HTTP client for the Agent Play web UI: session, snapshot RPC, mutating RPC with `sid`, and optional SSE subscription.\n *\n * Authenticates like the CLI: **`x-node-id`** (derived node id) and **`x-node-passw`** (hashed passphrase material) on every request.\n *\n * Register automation agents with {@link RemotePlayWorld.addAgent} (`nodeId` is the agent node id; the server stores it as `agentId`).\n * Call {@link RemotePlayWorld.initAudio} before `addAgent` to have the SDK mint per-agent OpenAI Realtime client secrets and forward them on registration.\n *\n * Incremental updates: {@link RemotePlayWorld.subscribeWorldState} listens for **`playerChainNotify`** in SSE `data`, then fetches each changed leaf via {@link RemotePlayWorld.getPlayerChainNode} and merges with {@link mergeSnapshotWithPlayerChainNode}.\n *\n * Human→agent intercom (Assist/Chat from the watch UI) is delivered as SSE **`world:intercom`** payloads with status **`forwarded`**. Call {@link RemotePlayWorld.subscribeIntercomCommands} with **`playerId`** or **`playerIds`** (one SSE stream; routes **`forwarded`** commands by **`toPlayerId`**) so your process runs tools and posts **`intercomResponse`** via {@link RemotePlayWorld.sendIntercomResponse} (the subscription does this when **`executeTool`** resolves).\n *\n * Set **`logging: \"on\"`** to trace **`forwarded`** commands for subscribed ids and **`sendIntercomResponse`** HTTP results.\n */\nexport class RemotePlayWorld {\n private readonly apiBase: string;\n private readonly rootKey: string;\n /** Node id derived from hashed passphrase material + root (main or agent node id). */\n private readonly derivedNodeId: string;\n /** Hex password material (`hashNodePassword` on normalized human phrase); sent as `password` for repository addAgent. */\n private readonly password: string;\n private readonly onSessionEvent:\n | ((event: RemotePlayWorldSessionEvent) => void)\n | undefined;\n private readonly transportLog: boolean;\n private sid: string | null = null;\n private closed = false;\n private readonly closeListeners = new Set<() => void>();\n private readonly playerConnectionInfo = new Map<\n string,\n { connectionId: string; leaseTtlSeconds: number; timer: ReturnType<typeof setInterval> }\n >();\n private audioInitOptions: RemotePlayWorldOpenAiAudioOptions | null = null;\n\n constructor(options: RemotePlayWorldOptions = {}) {\n const creds = loadAgentPlayCredentialsFileFromPathSync(\n resolveAgentPlayCredentialsPath()\n );\n const resolvedBaseUrl = options.baseUrl ?? creds?.serverUrl;\n if (resolvedBaseUrl === undefined || resolvedBaseUrl.trim().length === 0) {\n throw new Error(formatMissingBaseUrlError());\n }\n this.apiBase = normalizeBaseUrl(resolvedBaseUrl);\n this.onSessionEvent = options.onSessionEvent;\n this.transportLog = options.logging === \"on\";\n\n const nc =\n options.nodeCredentials ??\n (creds === null ? undefined : { rootKey: loadRootKey(), passw: creds.passw });\n if (\n nc !== undefined &&\n typeof nc.rootKey === \"string\" &&\n nc.rootKey.trim().length > 0 &&\n typeof nc.passw === \"string\" &&\n nc.passw.length > 0\n ) {\n this.rootKey = nc.rootKey.trim().toLowerCase();\n const material = nodeCredentialsMaterialFromHumanPassphrase(nc.passw);\n this.password = material;\n this.derivedNodeId = deriveNodeIdFromPassword({\n password: material,\n rootKey: this.rootKey,\n });\n return;\n }\n\n throw new Error(formatMissingCredentialsError());\n }\n\n private logTransport(event: string, detail: Record<string, unknown>): void {\n if (!this.transportLog) {\n return;\n }\n console.info(`[agent-play:RemotePlayWorld] ${event}`, detail);\n }\n\n private truncateForLog(value: string, max = 1600): string {\n return value.length <= max ? value : `${value.slice(0, max)}…`;\n }\n\n private emitSessionEvent(event: RemotePlayWorldSessionEvent): void {\n this.logTransport(\"session:event\", {\n name: event.name,\n detail: event.detail ?? {},\n });\n this.onSessionEvent?.(event);\n }\n\n onClose(handler: () => void): () => void {\n this.closeListeners.add(handler);\n return () => {\n this.closeListeners.delete(handler);\n };\n }\n\n hold(): RemotePlayWorldHold {\n return {\n for: async (seconds: number) => {\n if (typeof seconds !== \"number\" || !Number.isFinite(seconds)) {\n throw new Error(formatInvalidHoldSecondsError());\n }\n const ms = Math.max(0, seconds) * 1000;\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n },\n };\n }\n\n private authHeaders(): Record<string, string> {\n return {\n \"x-node-id\": this.derivedNodeId,\n \"x-node-passw\": this.password,\n };\n }\n\n private jsonHeaders(): Record<string, string> {\n return {\n \"content-type\": \"application/json\",\n ...this.authHeaders(),\n };\n }\n\n private mergeAuthFetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const headers = new Headers(init?.headers);\n const auth = this.authHeaders();\n for (const [k, v] of Object.entries(auth)) {\n headers.set(k, v);\n }\n return fetch(input, { ...init, headers });\n }\n\n private async validateNodeIdentity(options: {\n nodeId: string;\n mainNodeId: string | undefined;\n }): Promise<{ nodeKind?: string }> {\n const body: { nodeId: string; rootKey: string; mainNodeId?: string } = {\n nodeId: options.nodeId,\n rootKey: this.rootKey,\n };\n if (options.mainNodeId !== undefined && options.mainNodeId.trim().length > 0) {\n body.mainNodeId = options.mainNodeId.trim();\n }\n const res = await fetch(`${this.apiBase}/api/nodes/validate`, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify(body),\n });\n let json: unknown;\n try {\n json = (await res.json()) as unknown;\n } catch {\n throw new Error(`node validation failed: ${String(res.status)} invalid JSON`);\n }\n if (!isRecord(json) || json.ok !== true) {\n const reason =\n isRecord(json) && typeof json.reason === \"string\" ? json.reason : `HTTP ${String(res.status)}`;\n throw new Error(`node validation failed: ${reason}`);\n }\n const nodeKind =\n isRecord(json) && typeof json.nodeKind === \"string\" ? json.nodeKind : undefined;\n agentPlayDebug(\"remote-play-world\", \"node identity validated\", {\n nodeKind,\n derivedNodeIdPrefix: `${this.derivedNodeId.slice(0, 8)}…`,\n });\n return nodeKind !== undefined ? { nodeKind } : {};\n }\n\n /**\n * Establishes the HTTP session via `GET /api/agent-play/session`. With {@link RemotePlayWorldConnectOptions.mainNodeId},\n * validates node identity with `POST /api/nodes/validate` first.\n */\n async connect(options?: RemotePlayWorldConnectOptions): Promise<void> {\n const mainNodeIdOpt = options?.mainNodeId?.trim();\n if (mainNodeIdOpt !== undefined && mainNodeIdOpt.length > 0) {\n const validation = await this.validateNodeIdentity({\n nodeId: this.derivedNodeId,\n mainNodeId: mainNodeIdOpt,\n });\n console.info(\n `[agent-play] Node identity validated (${validation.nodeKind ?? \"unknown\"}).`\n );\n }\n const res = await fetch(`${this.apiBase}/api/agent-play/session`, {\n headers: this.authHeaders(),\n });\n if (!res.ok) {\n throw new Error(`session failed: ${res.status}`);\n }\n const json: unknown = await res.json();\n if (!isRecord(json) || typeof json.sid !== \"string\" || json.sid.length === 0) {\n throw new Error(\"session: invalid response\");\n }\n this.sid = json.sid;\n this.logTransport(\"connect:session\", {\n sid: this.sid,\n apiBase: this.apiBase,\n });\n this.emitSessionEvent({\n name: SESSION_CONNECTED_EVENT,\n detail: { sid: this.sid },\n });\n }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n for (const [playerId, connection] of Array.from(\n this.playerConnectionInfo.entries()\n )) {\n clearInterval(connection.timer);\n try {\n await this.disconnectPlayerConnection({\n playerId,\n connectionId: connection.connectionId,\n });\n } catch {\n // ignore disconnect errors during close\n }\n }\n this.playerConnectionInfo.clear();\n this.closed = true;\n this.emitSessionEvent({ name: SESSION_CLOSED_EVENT });\n for (const handler of Array.from(this.closeListeners)) {\n try {\n handler();\n } catch {\n // ignore listener errors\n }\n }\n }\n\n getSessionId(): string {\n if (this.sid === null) {\n throw new Error(\"RemotePlayWorld.connect() must be called first\");\n }\n return this.sid;\n }\n\n getPreviewUrl(): string {\n const u = new URL(\"/agent-play/watch\", this.apiBase);\n u.search = \"\";\n return u.toString();\n }\n\n /**\n * Enables SDK-managed OpenAI Realtime client secret minting for subsequent {@link addAgent} calls.\n *\n * When set and `addAgent({ enableP2a: \"on\" })` is used, the SDK mints a short-lived client secret\n * and includes it in the players registration payload as `realtimeWebrtc`.\n */\n initAudio(options: RemotePlayWorldInitAudioOptions): this {\n this.audioInitOptions = { ...options.openai };\n return this;\n }\n\n async getWorldSnapshot(): Promise<AgentPlaySnapshot> {\n const res = await fetch(`${this.apiBase}/api/agent-play/sdk/rpc`, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({ op: \"getWorldSnapshot\", payload: {} }),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`getWorldSnapshot: ${res.status} ${text}`);\n }\n let json: unknown;\n try {\n json = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"getWorldSnapshot: invalid JSON\");\n }\n if (!isRecord(json) || !(\"snapshot\" in json)) {\n throw new Error(\"getWorldSnapshot: invalid response shape\");\n }\n return parseAgentPlaySnapshot(json.snapshot);\n }\n\n /**\n * Fetches one player-chain node (genesis, header, occupant row, or removal) for `stableKey`, same snapshot scope as {@link RemotePlayWorld.getWorldSnapshot}.\n */\n async getPlayerChainNode(stableKey: string): Promise<PlayerChainNodeResponse> {\n const trimmed = stableKey.trim();\n if (trimmed.length === 0) {\n throw new Error(\"getPlayerChainNode: stableKey is required\");\n }\n const res = await fetch(`${this.apiBase}/api/agent-play/sdk/rpc`, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({\n op: \"getPlayerChainNode\",\n payload: { stableKey: trimmed },\n }),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`getPlayerChainNode: ${res.status} ${text}`);\n }\n let json: unknown;\n try {\n json = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"getPlayerChainNode: invalid JSON\");\n }\n return parsePlayerChainNodeRpcBody(json);\n }\n\n /**\n * Opens the session SSE stream, emits an initial snapshot from {@link RemotePlayWorld.getWorldSnapshot}, then on each **`playerChainNotify`** merges nodes in deterministic order via {@link RemotePlayWorld.getPlayerChainNode}.\n */\n subscribeWorldState(callbacks: {\n onSnapshot: (snapshot: AgentPlaySnapshot) => void;\n onError?: (err: Error) => void;\n onIntercomEvent?: (payload: WorldIntercomEventPayload) => void;\n }): { close: () => void } {\n let closeSource: (() => void) | null = null;\n const task = (async () => {\n try {\n const { createEventSource } = await import(\"eventsource-client\");\n let snapshot = await this.getWorldSnapshot();\n callbacks.onSnapshot(snapshot);\n const sseUrl = `${this.apiBase}/api/agent-play/events?sid=${encodeURIComponent(\n this.getSessionId()\n )}`;\n this.logTransport(\"subscribeWorldState:sse_open\", { sseUrl });\n const source = createEventSource({\n url: sseUrl,\n fetch: (input, init) => this.mergeAuthFetch(input, init),\n });\n closeSource = () => {\n source.close();\n };\n for await (const msg of source) {\n const eventType =\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n typeof (msg as { type?: unknown }).type === \"string\"\n ? (msg as { type: string }).type\n : \"(no type)\";\n if (typeof msg.data !== \"string\") {\n this.logTransport(\"sse:worldState:skip\", {\n reason: \"data_not_string\",\n eventType,\n });\n continue;\n }\n this.logTransport(\"sse:worldState:message\", {\n eventType,\n dataLength: msg.data.length,\n dataPreview: this.truncateForLog(msg.data),\n });\n let data: unknown;\n try {\n data = JSON.parse(msg.data) as unknown;\n } catch {\n this.logTransport(\"sse:worldState:parseJson\", {\n reason: \"invalid_json\",\n eventType,\n });\n continue;\n }\n if (callbacks.onIntercomEvent) {\n try {\n const inter = parseWorldIntercomEventPayload(data);\n this.logTransport(\"sse:worldState:intercom\", {\n status: inter.status,\n requestId: inter.requestId,\n kind: inter.kind,\n channelKey: inter.channelKey,\n });\n callbacks.onIntercomEvent(inter);\n } catch {\n this.logTransport(\"sse:worldState:intercom\", {\n reason: \"not_world_intercom_payload\",\n });\n }\n }\n const notify = parsePlayerChainFanoutNotifyFromSsePayload(data);\n if (notify === undefined || notify.nodes.length === 0) {\n continue;\n }\n this.logTransport(\"sse:worldState:playerChainNotify\", {\n nodeCount: notify.nodes.length,\n stableKeys: notify.nodes.map((n) => n.stableKey),\n });\n const ordered = sortNodeRefsForSerializedFetch(notify.nodes);\n for (const ref of ordered) {\n const node = await this.getPlayerChainNode(ref.stableKey);\n snapshot = mergeSnapshotWithPlayerChainNode(snapshot, node);\n }\n callbacks.onSnapshot(snapshot);\n }\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n this.logTransport(\"sse:worldState:error\", {\n message: err.message,\n });\n callbacks.onError?.(err);\n }\n })();\n return {\n close: () => {\n this.logTransport(\"subscribeWorldState:close\", {});\n closeSource?.();\n void task;\n },\n };\n }\n\n /**\n * Registers an automation agent using **agent node id** (`nodeId`), sent to the server as `agentId`.\n *\n * If {@link initAudio} was called and **`enableP2a`** is **`\"on\"`**, this call mints a per-agent\n * OpenAI Realtime client secret and forwards it as `realtimeWebrtc`.\n */\n async addAgent(input: AddAgentInput): Promise<RegisteredPlayer> {\n const sid = this.getSessionId();\n const effectiveMainNodeId = this.derivedNodeId;\n const validation = await this.validateNodeIdentity({\n nodeId: input.nodeId,\n mainNodeId: effectiveMainNodeId,\n });\n console.info(\n [\n \"Agent Node Connection\",\n ` status : validated`,\n ` nodeId : ${input.nodeId}`,\n ` nodeKind : ${validation.nodeKind ?? \"unknown\"}`,\n ` mainNode : ${effectiveMainNodeId}`,\n ].join(\"\\n\")\n );\n const url = `${this.apiBase}/api/agent-play/players?sid=${encodeURIComponent(sid)}`;\n const connectionId = randomUUID();\n const leaseTtlSeconds = 45;\n let realtimeWebrtcFromInit: RealtimeWebrtcClientSecret | undefined;\n let realtimeInstructionsFromInit: string | undefined;\n if (input.enableP2a === \"on\" && this.audioInitOptions !== null) {\n console.log(\"resolving realtime instructions for agent\", input.name);\n realtimeInstructionsFromInit = resolveRealtimeInstructions({\n openai: this.audioInitOptions,\n agentName: input.name,\n });\n realtimeWebrtcFromInit = await mintOpenAiRealtimeClientSecretForSdk({\n openai: this.audioInitOptions,\n agentName: input.name,\n });\n this.logTransport(\"addAgent:p2a_enabled\", {\n agentName: input.name,\n model: this.audioInitOptions.model,\n voice: this.audioInitOptions.voice,\n });\n }\n console.log(\"realtimeWebrtcFromInit\", realtimeWebrtcFromInit);\n console.log(\"realtimeInstructionsFromInit\", realtimeInstructionsFromInit);\n const requestPayload = {\n name: input.name,\n type: input.type,\n agent: input.agent,\n mainNodeId: effectiveMainNodeId,\n password: this.password,\n agentId: input.nodeId,\n connectionId,\n leaseTtlSeconds,\n ...(input.enableP2a !== undefined ? { enableP2a: input.enableP2a } : {}),\n ...(realtimeWebrtcFromInit !== undefined\n ? { realtimeWebrtc: realtimeWebrtcFromInit }\n : {}),\n ...(realtimeInstructionsFromInit !== undefined\n ? { realtimeInstructions: realtimeInstructionsFromInit }\n : {}),\n };\n this.logTransport(\"addAgent:request_payload\", {\n url,\n payload: requestPayload,\n });\n const requestBody = JSON.stringify(requestPayload);\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: requestBody,\n });\n const bodyText = await res.text();\n if (!res.ok) {\n throw new Error(`addAgent: ${res.status} ${bodyText}`);\n }\n let body: unknown;\n try {\n body = JSON.parse(bodyText) as unknown;\n } catch {\n throw new Error(\"addAgent: invalid JSON\");\n }\n if (!isRecord(body)) {\n throw new Error(\"addAgent: invalid response shape\");\n }\n const playerId = body.playerId;\n const previewUrl = body.previewUrl;\n if (typeof playerId !== \"string\" || typeof previewUrl !== \"string\") {\n throw new Error(\"addAgent: missing playerId or previewUrl\");\n }\n const registeredAgent = parseRegisteredAgentSummary(body.registeredAgent);\n const bodyConnectionId =\n typeof body.connectionId === \"string\" && body.connectionId.length > 0\n ? body.connectionId\n : connectionId;\n const bodyLeaseTtlSeconds =\n typeof body.leaseTtlSeconds === \"number\" && Number.isFinite(body.leaseTtlSeconds)\n ? body.leaseTtlSeconds\n : leaseTtlSeconds;\n const existingConnection = this.playerConnectionInfo.get(playerId);\n if (existingConnection !== undefined) {\n clearInterval(existingConnection.timer);\n }\n const timer = setInterval(() => {\n void this.heartbeatPlayerConnection({\n playerId,\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n }).catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n console.error(\"[agent-play:RemotePlayWorld] heartbeat:exhausted\", {\n playerId,\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n attempts: PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS,\n retryDelayMs: PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS,\n error: message,\n });\n });\n }, 12_000);\n this.playerConnectionInfo.set(playerId, {\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n timer,\n });\n const now = new Date();\n const enableP2aFromBody =\n body.enableP2a === \"on\" || body.enableP2a === \"off\"\n ? body.enableP2a\n : undefined;\n const enableP2a: P2aEnableFlag = enableP2aFromBody ?? input.enableP2a ?? \"off\";\n const realtimeWebrtc = parseRealtimeWebrtcClientSecret(body.realtimeWebrtc);\n return {\n id: playerId,\n name: input.name,\n sid,\n createdAt: now,\n updatedAt: now,\n previewUrl,\n registeredAgent,\n enableP2a,\n ...(realtimeWebrtc !== undefined ? { realtimeWebrtc } : {}),\n connectionId: bodyConnectionId,\n leaseTtlSeconds: bodyLeaseTtlSeconds,\n };\n }\n\n /**\n * @deprecated Use {@link addAgent} with `nodeId` (agent node id) for integrations and automation.\n */\n async addPlayer(input: AddPlayerInput): Promise<RegisteredPlayer> {\n const payload: AddAgentInput = {\n name: input.name,\n type: input.type,\n agent: input.agent,\n nodeId: input.agentId,\n };\n if (input.enableP2a !== undefined) {\n payload.enableP2a = input.enableP2a;\n }\n if (input.version !== undefined) {\n payload.version = input.version;\n }\n if (input.createdAt !== undefined) {\n payload.createdAt = input.createdAt;\n }\n if (input.updatedAt !== undefined) {\n payload.updatedAt = input.updatedAt;\n }\n if (input.mainNodeId !== undefined) {\n payload.mainNodeId = input.mainNodeId;\n }\n return this.addAgent(payload);\n }\n\n async recordInteraction(input: RecordInteractionInput): Promise<void> {\n await this.rpc(\"recordInteraction\", {\n playerId: input.playerId,\n role: input.role,\n text: input.text,\n });\n }\n\n async recordJourney(playerId: string, journey: Journey): Promise<void> {\n await this.rpc(\"recordJourney\", { playerId, journey });\n }\n\n async sendIntercomResponse(payload: IntercomResponsePayload): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/sdk/rpc?sid=${encodeURIComponent(sid)}`;\n this.logTransport(\"intercom:sendResponse:request\", {\n url,\n requestId: payload.requestId,\n toPlayerId: payload.toPlayerId,\n fromPlayerId: payload.fromPlayerId,\n kind: payload.kind,\n status: payload.status,\n toolName: payload.toolName,\n error: payload.error,\n resultPreview:\n payload.result !== undefined\n ? this.truncateForLog(JSON.stringify(payload.result))\n : undefined,\n });\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({ op: INTERCOM_RESPONSE_OP, payload }),\n });\n const okText = await res.text();\n this.logTransport(\"intercom:sendResponse:http\", {\n requestId: payload.requestId,\n httpStatus: res.status,\n bodyPreview: this.truncateForLog(okText),\n });\n if (!res.ok) {\n throw new Error(`intercomResponse: ${res.status} ${okText}`);\n }\n }\n\n /**\n * Subscribes to the session SSE stream and handles **`forwarded`** intercom commands whose **`toPlayerId`** is in **`playerId`** or **`playerIds`**, invoking assist/chat execution and posting **`intercomResponse`** (**`completed`** / **`failed`**).\n * Realtime commands mint ephemeral WebRTC credentials in the agent process and return them through `intercomResponse`.\n * Uses a **single** SSE connection when **`playerIds`** lists multiple automation agents (recommended for several agents in one process).\n * Not invoked automatically by {@link RemotePlayWorld.addAgent}.\n */\n subscribeIntercomCommands(\n options: SubscribeIntercomCommandsOptions\n ): { close: () => void } {\n const subscribed = normalizeIntercomSubscribePlayerIds(options);\n const playerIdsSorted = Array.from(subscribed).sort();\n if (subscribed.size === 0) {\n this.logTransport(\"subscribeIntercomCommands:skip\", {\n reason: \"empty_player_ids\",\n });\n return { close: () => {} };\n }\n this.logTransport(\"subscribeIntercomCommands:start\", {\n playerIds: playerIdsSorted,\n });\n const { executeTool, chatAgentsByPlayerId } = options;\n let closeSource: (() => void) | null = null;\n const task = (async () => {\n try {\n const { createEventSource } = await import(\"eventsource-client\");\n const sseUrl = `${this.apiBase}/api/agent-play/events?sid=${encodeURIComponent(\n this.getSessionId()\n )}`;\n this.logTransport(\"subscribeIntercomCommands:sse_open\", {\n sseUrl,\n subscribePlayerIds: playerIdsSorted,\n });\n const source = createEventSource({\n url: sseUrl,\n fetch: (input, init) => this.mergeAuthFetch(input, init),\n });\n closeSource = () => {\n source.close();\n };\n for await (const msg of source) {\n const sseEvent = getSseEventName(msg);\n if (\n sseEvent !== undefined &&\n sseEvent !== WORLD_INTERCOM_EVENT\n ) {\n continue;\n }\n if (typeof msg.data !== \"string\") {\n const eventLabel = sseEvent ?? \"(unset)\";\n this.logTransport(\"sse:intercomCommands:skip\", {\n reason: \"data_not_string\",\n sseEvent: eventLabel,\n });\n continue;\n }\n let data: unknown;\n try {\n data = JSON.parse(msg.data) as unknown;\n } catch {\n this.logTransport(\"sse:intercomCommands:parseJson\", {\n reason: \"invalid_json\",\n sseEvent: sseEvent ?? \"(unset)\",\n });\n continue;\n }\n let inter: WorldIntercomEventPayload;\n try {\n inter = parseWorldIntercomEventPayload(data);\n } catch {\n continue;\n }\n if (inter.status !== \"forwarded\") {\n continue;\n }\n const cmd = inter.command;\n if (cmd === undefined) {\n this.logTransport(\"sse:intercomCommands:skip\", {\n reason: \"missing_command\",\n requestId: inter.requestId,\n });\n continue;\n }\n if (!subscribed.has(cmd.toPlayerId)) {\n continue;\n }\n this.logTransport(\"sse:intercomCommands:forwarded\", {\n requestId: cmd.requestId,\n fromPlayerId: cmd.fromPlayerId,\n toPlayerId: cmd.toPlayerId,\n kind: cmd.kind,\n toolName: cmd.toolName,\n });\n try {\n let result: Record<string, unknown>;\n const commandKind = `${cmd.kind}`;\n if (commandKind === \"realtime\" || commandKind === \"audio\") {\n const realtimeWebrtc = await resolveRealtimeWebrtcForIntercom({\n audioInitOptions: this.audioInitOptions,\n playerId: cmd.toPlayerId,\n });\n result = {\n messageKind: \"text\",\n message: \"Realtime credentials ready.\",\n realtimeWebrtc,\n };\n } else if (\n cmd.kind === \"chat\" &&\n chatAgentsByPlayerId !== undefined &&\n chatAgentsByPlayerId.has(cmd.toPlayerId)\n ) {\n const lc = chatAgentsByPlayerId.get(cmd.toPlayerId);\n if (lc === undefined) {\n throw new Error(\"intercom: chatAgentsByPlayerId entry missing\");\n }\n this.logTransport(\"intercom:langchain:invoke\", {\n requestId: cmd.requestId,\n toPlayerId: cmd.toPlayerId,\n textPreview: this.truncateForLog(cmd.text ?? \"\"),\n });\n const rawOut = await invokeLangChainChatAgent(lc, {\n messages: [new HumanMessage(cmd.text ?? \"\")],\n });\n result = intercomResultRecordFromLangChainInvokeOutput(rawOut);\n this.logTransport(\"intercom:langchain:invoke:completed\", {\n requestId: cmd.requestId,\n resultPreview: this.truncateForLog(JSON.stringify(result)),\n });\n } else if (cmd.kind === \"assist\" || cmd.kind === \"chat\") {\n const toolName =\n cmd.kind === \"chat\" ? \"chat_tool\" : cmd.toolName ?? \"\";\n const args =\n cmd.kind === \"chat\"\n ? { text: cmd.text ?? \"\" }\n : (cmd.args ?? {});\n this.logTransport(\"intercom:executeTool\", {\n requestId: cmd.requestId,\n toolName,\n argsPreview: this.truncateForLog(JSON.stringify(args)),\n });\n this.logTransport(\"intercom:executeTool:started\", {\n requestId: cmd.requestId,\n toolName,\n argsPreview: this.truncateForLog(JSON.stringify(args)),\n });\n result = await Promise.resolve(\n executeTool({ toolName, args })\n );\n this.logTransport(\"intercom:executeTool:completed\", {\n requestId: cmd.requestId,\n toolName,\n argsPreview: this.truncateForLog(JSON.stringify(args)),\n resultPreview: this.truncateForLog(JSON.stringify(result)),\n });\n } else {\n this.logTransport(\"intercom:unsupported_kind:ignored\", {\n requestId: cmd.requestId,\n kind: cmd.kind,\n toPlayerId: cmd.toPlayerId,\n });\n continue;\n }\n await this.sendIntercomResponse({\n requestId: cmd.requestId,\n mainNodeId: cmd.mainNodeId,\n toPlayerId: cmd.fromPlayerId,\n fromPlayerId: cmd.toPlayerId,\n kind: cmd.kind,\n status: \"completed\",\n toolName: cmd.toolName,\n ts: new Date().toISOString(),\n result,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logTransport(\"intercom:executeTool:error\", {\n requestId: cmd.requestId,\n message,\n });\n await this.sendIntercomResponse({\n requestId: cmd.requestId,\n mainNodeId: cmd.mainNodeId,\n toPlayerId: cmd.fromPlayerId,\n fromPlayerId: cmd.toPlayerId,\n kind: cmd.kind,\n status: \"failed\",\n toolName: cmd.toolName,\n error: message,\n ts: new Date().toISOString(),\n });\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logTransport(\"sse:intercomCommands:stream_error\", { message });\n }\n })();\n return {\n close: () => {\n this.logTransport(\"subscribeIntercomCommands:close\", {\n playerIds: playerIdsSorted,\n });\n closeSource?.();\n void task;\n },\n };\n }\n\n async registerMcp(options: { name: string; url?: string }): Promise<string> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/mcp/register?sid=${encodeURIComponent(sid)}`;\n const body: { name: string; url?: string } = { name: options.name };\n if (options.url !== undefined) {\n body.url = options.url;\n }\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify(body),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`registerMcp: ${res.status} ${text}`);\n }\n let json: unknown;\n try {\n json = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"registerMcp: invalid JSON\");\n }\n if (!isRecord(json) || typeof json.id !== \"string\") {\n throw new Error(\"registerMcp: invalid response\");\n }\n return json.id;\n }\n\n private async rpc(op: string, payload: unknown): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/sdk/rpc?sid=${encodeURIComponent(sid)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({ op, payload }),\n });\n if (!res.ok) {\n const t = await res.text();\n throw new Error(`rpc ${op}: ${res.status} ${t}`);\n }\n }\n\n private async heartbeatPlayerConnection(input: {\n playerId: string;\n connectionId: string;\n leaseTtlSeconds: number;\n }): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/players/heartbeat?sid=${encodeURIComponent(sid)}`;\n const bodyJson = JSON.stringify({\n playerId: input.playerId,\n connectionId: input.connectionId,\n leaseTtlSeconds: input.leaseTtlSeconds,\n });\n let lastError: Error = new Error(\"heartbeat: no attempts completed\");\n\n for (let attempt = 1; attempt <= PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS; attempt += 1) {\n const attemptStartedAt = Date.now();\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: bodyJson,\n });\n const text = await res.text();\n if (res.ok) {\n if (attempt > 1) {\n console.info(\"[agent-play:RemotePlayWorld] heartbeat:retry_recovered\", {\n playerId: input.playerId,\n connectionId: input.connectionId,\n leaseTtlSeconds: input.leaseTtlSeconds,\n sid,\n url,\n successfulAttempt: attempt,\n attemptsUsed: attempt,\n maxAttempts: PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS,\n durationMs: Date.now() - attemptStartedAt,\n });\n }\n return;\n }\n lastError = new Error(`heartbeat: ${res.status} ${text}`);\n } catch (err: unknown) {\n lastError =\n err instanceof Error ? err : new Error(String(err));\n }\n\n const willRetry = attempt < PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS;\n console.warn(\"[agent-play:RemotePlayWorld] heartbeat:attempt_failed\", {\n phase: \"player_connection_lease_refresh\",\n playerId: input.playerId,\n connectionId: input.connectionId,\n leaseTtlSeconds: input.leaseTtlSeconds,\n sid,\n url,\n attempt,\n maxAttempts: PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS,\n remainingAttemptsAfterThisFailure:\n PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS - attempt,\n errorMessage: lastError.message,\n requestBodyBytes: bodyJson.length,\n attemptDurationMs: Date.now() - attemptStartedAt,\n nextAction: willRetry\n ? `sleep ${PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS}ms then retry`\n : \"no more retries; will throw\",\n retryDelayMs: willRetry\n ? PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS\n : 0,\n });\n\n if (!willRetry) {\n throw lastError;\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS);\n });\n }\n }\n\n private async disconnectPlayerConnection(input: {\n playerId: string;\n connectionId: string;\n }): Promise<void> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/players/disconnect?sid=${encodeURIComponent(sid)}`;\n await fetch(url, {\n method: \"POST\",\n headers: this.jsonHeaders(),\n body: JSON.stringify({\n playerId: input.playerId,\n connectionId: input.connectionId,\n }),\n });\n }\n}\n","function contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .map((block) => {\n if (typeof block === \"string\") {\n return block;\n }\n if (typeof block === \"object\" && block !== null && \"text\" in block) {\n const t = (block as { text?: unknown }).text;\n return typeof t === \"string\" ? t : \"\";\n }\n return \"\";\n })\n .join(\"\");\n }\n if (content !== null && typeof content === \"object\" && \"text\" in content) {\n const t = (content as { text?: unknown }).text;\n return typeof t === \"string\" ? t : JSON.stringify(content);\n }\n return JSON.stringify(content);\n}\n\n/**\n * Maps a LangChain agent **`invoke`** result to a plain object suitable for **`intercomResponse`** **`result`**.\n */\nexport function intercomResultRecordFromLangChainInvokeOutput(\n output: unknown\n): Record<string, unknown> {\n if (output === null || typeof output !== \"object\") {\n return { mode: \"chat\", message: String(output) };\n }\n const o = output as Record<string, unknown>;\n if (\"structuredResponse\" in o && o.structuredResponse !== undefined) {\n const sr = o.structuredResponse;\n if (sr !== null && typeof sr === \"object\" && !Array.isArray(sr)) {\n return { ...sr };\n }\n return { mode: \"chat\", structuredResponse: sr };\n }\n const messages = o.messages;\n if (Array.isArray(messages) && messages.length > 0) {\n const last = messages[messages.length - 1];\n if (last !== null && typeof last === \"object\" && \"content\" in last) {\n const text = contentToText((last as { content: unknown }).content);\n if (text.trim().length > 0) {\n return { mode: \"chat\", message: text };\n }\n }\n }\n return { mode: \"chat\", output: o };\n}\n","import type {\n RealtimeWebrtcClientSecret,\n RemotePlayWorldOpenAiAudioOptions,\n} from \"../public-types.js\";\n\nexport type ResolveRealtimeInstructionsOptions = {\n openai: RemotePlayWorldOpenAiAudioOptions;\n agentName: string;\n};\n\n/** Resolves OpenAI realtime instructions, preferring explicit text then template fallback. */\nexport function resolveRealtimeInstructions(\n options: ResolveRealtimeInstructionsOptions\n): string | undefined {\n const explicit = options.openai.instructions?.trim();\n if (explicit !== undefined && explicit.length > 0) {\n return explicit;\n }\n const template = options.openai.instructionsTemplate?.trim();\n if (template !== undefined && template.length > 0) {\n return template.replaceAll(\"{{agentName}}\", options.agentName);\n }\n return `You are ${options.agentName}. Keep responses short, clear, and conversational unless asked for detail.`;\n}\n\ntype MintOptions = ResolveRealtimeInstructionsOptions;\n\n/**\n * Mints a short-lived OpenAI Realtime client secret for a single agent registration.\n *\n * This helper is Node-only and intended for `RemotePlayWorld.initAudio()` driven flows.\n */\nexport async function mintOpenAiRealtimeClientSecretForSdk(\n options: MintOptions\n): Promise<RealtimeWebrtcClientSecret> {\n const apiKey = options.openai.apiKey?.trim() ?? \"\";\n if (apiKey.length === 0) {\n throw new Error(\"OPENAI_API_KEY is required when world.initAudio() is enabled\");\n }\n const model = options.openai.model?.trim() || \"gpt-realtime\";\n const voice = options.openai.voice?.trim() || \"marin\";\n const instructions = resolveRealtimeInstructions(options);\n const res = await fetch(\"https://api.openai.com/v1/realtime/client_secrets\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n session: {\n type: \"realtime\",\n model,\n ...(instructions !== undefined && instructions.length > 0 ? { instructions } : {}),\n audio: { output: { voice } },\n },\n }),\n });\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`openai realtime client secret failed: ${res.status} ${text}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n throw new Error(\"openai realtime client secret failed: invalid JSON\");\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n throw new Error(\"openai realtime client secret failed: invalid payload\");\n }\n const record = parsed as Record<string, unknown>;\n if (typeof record.value !== \"string\" || record.value.length === 0) {\n throw new Error(\"openai realtime client secret failed: missing value\");\n }\n const out: RealtimeWebrtcClientSecret = {\n clientSecret: record.value,\n model,\n voice,\n };\n if (typeof record.expires_at === \"string\" && record.expires_at.length > 0) {\n out.expiresAt = record.expires_at;\n }\n return out;\n}\n","/**\n * @packageDocumentation\n * Public entry for **@agent-play/sdk** (Node.js and browser `browser` export).\n *\n * **Primary APIs**\n * - {@link RemotePlayWorld} — HTTP client: load **`nodeCredentials`** (`rootKey`, human **`passw`**) from **`~/.agent-play/credentials.json`** via **@agent-play/node-tools**, then **`connect`**, **`getWorldSnapshot`**, **`addAgent`**, **`subscribeIntercomCommands`** (for automation agents handling intercom **`forwarded`** commands), **`recordInteraction`**, **`recordJourney`**, **`registerMcp`**, **`hold`**, **`onClose`**.\n * - {@link langchainRegistration} — build LangChain **`agent`** payloads for **`addAgent`**.\n * - {@link clampWorldPosition}, {@link WorldBounds} — shared world bounds for server and canvas.\n *\n * **Events** — Session and world events: {@link WORLD_INTERACTION_EVENT}, {@link SESSION_CONNECTED_EVENT}, and related symbols from this module.\n *\n * **Transport** — **`RemotePlayWorld`** uses `fetch`; **`subscribeWorldState`** consumes SSE **`playerChainNotify`** and **`getPlayerChainNode`** for incremental merges.\n *\n * **Wire note** — Fanout and SSE use **`playerChainNotify`** (node references). Legacy **`playerChainDelta`**-style digests on the wire are not used; use **`getWorldSnapshot`** if you need a full snapshot only.\n */\n\nexport type {\n AddAgentInput,\n AddPlayerInput,\n AgentPlaySnapshot,\n AgentPlayWorldMap,\n AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapBounds,\n AgentPlayWorldMapMcpOccupant,\n AssistToolFieldType,\n AssistToolParameterSpec,\n AssistToolSpec,\n LangChainAgentRegistration,\n P2aEnableFlag,\n PlayerChainFanoutNotify,\n PlayerChainGenesisNode,\n PlayerChainHeaderNode,\n PlayerChainNodeResponse,\n PlayerChainNotifyNodeRef,\n PlayerChainOccupantPresentNode,\n PlayerChainOccupantRemovedNode,\n PlayAgentInformation,\n PlatformAgentInformation,\n RecordInteractionInput,\n RealtimeWebrtcClientSecret,\n RemotePlayWorldInitAudioOptions,\n RemotePlayWorldOpenAiAudioOptions,\n RegisteredAgentSummary,\n RegisteredPlayer,\n WorldInteractionRole,\n YieldEventInfo,\n ZoneEventInfo,\n} from \"./public-types.js\";\nexport type {\n DestinationJourneyStep,\n Journey,\n JourneyStep,\n OriginJourneyStep,\n PositionedStep,\n StructureJourneyStep,\n WorldJourneyUpdate,\n} from \"./public-types.js\";\nexport {\n PLAYER_ADDED_EVENT,\n SESSION_CLOSED_EVENT,\n SESSION_CONNECTED_EVENT,\n SESSION_INVALID_EVENT,\n SESSION_SSE_ERROR_EVENT,\n SESSION_SSE_OPEN_EVENT,\n WORLD_AGENT_SIGNAL_EVENT,\n WORLD_INTERACTION_EVENT,\n WORLD_JOURNEY_EVENT,\n type RemotePlayWorldSessionEvent,\n type WorldAgentSignalPayload,\n type WorldInteractionPayload,\n} from \"./world-events.js\";\nexport {\n clampWorldPosition,\n boundsContain,\n expandBoundsToMinimumPlayArea,\n MINIMUM_PLAY_WORLD_BOUNDS,\n type WorldBounds,\n} from \"./lib/world-bounds.js\";\nexport {\n agentPlayDebug,\n configureAgentPlayDebug,\n isAgentPlayDebugEnabled,\n resetAgentPlayDebug,\n} from \"./lib/agent-play-debug.js\";\nexport { langchainRegistration } from \"./platforms/langchain.js\";\nexport {\n RemotePlayWorld,\n type IntercomToolExecutor,\n type RemotePlayWorldConnectOptions,\n type RemotePlayWorldHold,\n type RemotePlayWorldLogging,\n type RemotePlayWorldNodeCredentials,\n type RemotePlayWorldOptions,\n type SubscribeIntercomCommandsOptions,\n} from \"./lib/remote-play-world.js\";\nexport { intercomResultRecordFromLangChainInvokeOutput } from \"./lib/intercom-langchain-chat-result.js\";\nexport {\n mergeSnapshotWithPlayerChainNode,\n parsePlayerChainFanoutNotify,\n parsePlayerChainFanoutNotifyFromSsePayload,\n parsePlayerChainNodeRpcBody,\n sortNodeRefsForSerializedFetch,\n} from \"./lib/player-chain-merge.js\";\nexport {\n PLAYER_CHAIN_GENESIS_STABLE_KEY,\n PLAYER_CHAIN_HEADER_STABLE_KEY,\n} from \"./lib/world-chain-keys.js\";\nexport {\n type AgentPlayAgentNodeEntry,\n type AgentPlayCredentialsFile,\n loadAgentPlayCredentialsFileFromPath,\n loadAgentPlayCredentialsFileFromPathSync,\n loadRootKey,\n nodeCredentialsMaterialFromHumanPassphrase,\n parseAgentPlayCredentialsJson,\n resolveAgentPlayCredentialsPath,\n} from \"@agent-play/node-tools\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAYO,IAAM,0BAA0B;AAGhC,IAAM,wBAAwB;AAG9B,IAAM,uBAAuB;AAG7B,IAAM,yBAAyB;AAG/B,IAAM,0BAA0B;AAQhC,IAAM,qBAAqB;AAG3B,IAAM,0BAA0B;AAGhC,IAAM,2BAA2B;AAGjC,IAAM,sBAAsB;;;AC3BnC,IAAI;AASG,SAAS,wBAAwB,MAA4B;AAClE,oBAAkB,KAAK,SAAS;AAClC;AAOO,SAAS,sBAA4B;AAC1C,oBAAkB;AACpB;AAOO,SAAS,0BAAmC;AACjD,MAAI,oBAAoB,MAAO,QAAO;AACtC,MAAI,oBAAoB,KAAM,QAAO;AACrC,SAAO,QAAQ,IAAI,qBAAqB;AAC1C;AAGA,IAAM,kBAAkB;AAQxB,SAAS,cAAc,QAAyB;AAC9C,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI;AACF,UAAM,OAAO,oBAAI,QAAgB;AACjC,UAAM,OAAO,KAAK,UAAU,QAAQ,CAAC,IAAI,MAAe;AACtD,UAAI,OAAO,MAAM,YAAY,MAAM,MAAM;AACvC,YAAI,KAAK,IAAI,CAAC,EAAG,QAAO;AACxB,aAAK,IAAI,CAAC;AAAA,MACZ;AACA,UAAI,OAAO,MAAM,SAAU,QAAO,OAAO,CAAC;AAC1C,aAAO;AAAA,IACT,CAAC;AACD,QAAI,OAAO,SAAS,SAAU,QAAO,OAAO,MAAM;AAClD,WAAO,KAAK,SAAS,kBACjB,GAAG,KAAK,MAAM,GAAG,eAAe,CAAC,WACjC;AAAA,EACN,QAAQ;AACN,WAAO,OAAO,MAAM;AAAA,EACtB;AACF;AAWO,SAAS,eACd,OACA,SACA,QACM;AACN,MAAI,CAAC,wBAAwB,EAAG;AAChC,QAAM,OACJ,WAAW,SAAY,KAAK,IAAI,cAAc,MAAM,CAAC;AACvD,UAAQ,MAAM,eAAe,KAAK,KAAK,OAAO,GAAG,IAAI,EAAE;AACzD;;;AChFA,IAAM,YAAY;AAOlB,SAAS,+BAAuC;AAC9C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAOA,SAAS,6BAAqC;AAC5C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAQA,SAAS,cAAc,MAAwB;AAC7C,MAAI,UAAmB;AACvB,WAAS,QAAQ,GAAG,QAAQ,IAAI,SAAS;AACvC,QAAI,YAAY,QAAQ,OAAO,YAAY,UAAU;AACnD,aAAO;AAAA,IACT;AACA,UAAM,MAAO,QAA8B;AAC3C,QAAI,CAAC,OAAO,OAAO,IAAI,aAAa,UAAU;AAC5C,aAAO;AAAA,IACT;AACA,UAAM,EAAE,SAAS,IAAI;AACrB,QACE,aAAa,iBACb,aAAa,iBACb,aAAa,cACb;AACA,YAAM,QAAQ,IAAI;AAClB,gBACE,UAAU,QAAQ,OAAO,UAAU,WAAW,QAAQ;AACxD;AAAA,IACF;AACA,QAAI,aAAa,cAAc;AAC7B,gBAAU,IAAI;AACd;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,MAAoC;AAChE,QAAM,OAAO,cAAc,IAAI;AAC/B,MAAI,SAAS,QAAQ,OAAO,SAAS,UAAU;AAC7C,WAAO;AAAA,EACT;AACA,QAAM,WAAY,KAA0C,MAAM;AAClE,MAAI,aAAa,aAAa;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,aAAa,cAAc;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,aAAa,aAAa;AAC5B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOA,SAAS,qBAAqB,QAA0C;AACtE,MAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,WAAO,CAAC;AAAA,EACV;AACA,QAAM,IAAI;AAGV,MAAI,OAAO,EAAE,MAAM,UAAU,YAAY;AACvC,WAAO,EAAE,OAAO,6EAA6E;AAAA,EAC/F;AACA,QAAM,QAAQ,EAAE,KAAK,MAAM;AAC3B,QAAM,MAA+B,CAAC;AACtC,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,GAAG,IAAI;AAAA,MACT,OAAO;AAAA,MACP,WAAW,qBAAqB,MAAM,GAAG,CAAC;AAAA,IAC5C;AAAA,EACF;AACA,SAAO;AACT;AAOA,SAAS,aAAa,GAIH;AACjB,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IACR,aACE,OAAO,EAAE,gBAAgB,YAAY,EAAE,YAAY,SAAS,IACxD,EAAE,cACF,EAAE;AAAA,IACR,YAAY,qBAAqB,EAAE,MAAM;AAAA,EAC3C;AACF;AASA,SAAS,kBAAkB,OAAkC;AAC3D,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAIV,MAAI,MAAM,QAAQ,EAAE,KAAK,GAAG;AAC1B,WAAO,EAAE;AAAA,EACX;AACA,MACE,EAAE,YAAY,UACd,OAAO,EAAE,YAAY,YACrB,EAAE,YAAY,QACd,WAAW,EAAE,WACb,MAAM,QAAS,EAAE,QAA+B,KAAK,GACrD;AACA,WAAQ,EAAE,QAAiC;AAAA,EAC7C;AACA,SAAO;AACT;AAWO,SAAS,sBACd,OAC4B;AAC5B,QAAM,WAAW,kBAAkB,KAAK;AACxC,MAAI,aAAa,MAAM;AACrB,UAAM,IAAI,MAAM,6BAA6B,CAAC;AAAA,EAChD;AACA,QAAM,QACJ;AACF,QAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AACrC,MAAI,CAAC,MAAM,SAAS,SAAS,GAAG;AAC9B,UAAM,IAAI,MAAM,2BAA2B,CAAC;AAAA,EAC9C;AACA,QAAM,cAAc,MACjB,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,SAAS,CAAC,EAC1C,IAAI,CAAC,MAAM,aAAa,CAAC,CAAC;AAC7B,iBAAe,aAAa,yBAAyB;AAAA,IACnD,WAAW,MAAM;AAAA,IACjB,aAAa,YAAY;AAAA,EAC3B,CAAC;AACD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX;AAAA,EACF;AACF;;;AC7LA,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYP,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EAEA;AAAA,EAEA;AAAA,OACK;;;AChDP,SAAS,cAAc,SAA0B;AAC/C,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,WAAO,QACJ,IAAI,CAAC,UAAU;AACd,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT;AACA,UAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,OAAO;AAClE,cAAM,IAAK,MAA6B;AACxC,eAAO,OAAO,MAAM,WAAW,IAAI;AAAA,MACrC;AACA,aAAO;AAAA,IACT,CAAC,EACA,KAAK,EAAE;AAAA,EACZ;AACA,MAAI,YAAY,QAAQ,OAAO,YAAY,YAAY,UAAU,SAAS;AACxE,UAAM,IAAK,QAA+B;AAC1C,WAAO,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,OAAO;AAAA,EAC3D;AACA,SAAO,KAAK,UAAU,OAAO;AAC/B;AAKO,SAAS,8CACd,QACyB;AACzB,MAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,WAAO,EAAE,MAAM,QAAQ,SAAS,OAAO,MAAM,EAAE;AAAA,EACjD;AACA,QAAM,IAAI;AACV,MAAI,wBAAwB,KAAK,EAAE,uBAAuB,QAAW;AACnE,UAAM,KAAK,EAAE;AACb,QAAI,OAAO,QAAQ,OAAO,OAAO,YAAY,CAAC,MAAM,QAAQ,EAAE,GAAG;AAC/D,aAAO,EAAE,GAAG,GAAG;AAAA,IACjB;AACA,WAAO,EAAE,MAAM,QAAQ,oBAAoB,GAAG;AAAA,EAChD;AACA,QAAM,WAAW,EAAE;AACnB,MAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AAClD,UAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,QAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,aAAa,MAAM;AAClE,YAAM,OAAO,cAAe,KAA8B,OAAO;AACjE,UAAI,KAAK,KAAK,EAAE,SAAS,GAAG;AAC1B,eAAO,EAAE,MAAM,QAAQ,SAAS,KAAK;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,MAAM,QAAQ,QAAQ,EAAE;AACnC;;;AC1CO,SAAS,4BACd,SACoB;AACpB,QAAM,WAAW,QAAQ,OAAO,cAAc,KAAK;AACnD,MAAI,aAAa,UAAa,SAAS,SAAS,GAAG;AACjD,WAAO;AAAA,EACT;AACA,QAAM,WAAW,QAAQ,OAAO,sBAAsB,KAAK;AAC3D,MAAI,aAAa,UAAa,SAAS,SAAS,GAAG;AACjD,WAAO,SAAS,WAAW,iBAAiB,QAAQ,SAAS;AAAA,EAC/D;AACA,SAAO,WAAW,QAAQ,SAAS;AACrC;AASA,eAAsB,qCACpB,SACqC;AACrC,QAAM,SAAS,QAAQ,OAAO,QAAQ,KAAK,KAAK;AAChD,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AACA,QAAM,QAAQ,QAAQ,OAAO,OAAO,KAAK,KAAK;AAC9C,QAAM,QAAQ,QAAQ,OAAO,OAAO,KAAK,KAAK;AAC9C,QAAM,eAAe,4BAA4B,OAAO;AACxD,QAAM,MAAM,MAAM,MAAM,qDAAqD;AAAA,IAC3E,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,UAAU,MAAM;AAAA,MAC/B,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,SAAS;AAAA,QACP,MAAM;AAAA,QACN;AAAA,QACA,GAAI,iBAAiB,UAAa,aAAa,SAAS,IAAI,EAAE,aAAa,IAAI,CAAC;AAAA,QAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,yCAAyC,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,EAC/E;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,WAAW,GAAG;AACjE,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,QAAM,MAAkC;AAAA,IACtC,cAAc,OAAO;AAAA,IACrB;AAAA,IACA;AAAA,EACF;AACA,MAAI,OAAO,OAAO,eAAe,YAAY,OAAO,WAAW,SAAS,GAAG;AACzE,QAAI,YAAY,OAAO;AAAA,EACzB;AACA,SAAO;AACT;;;AF5BA,IAAM,2CAA2C;AACjD,IAAM,6CAA6C;AAqCnD,SAAS,gCAAwC;AAC/C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF,EAAE,KAAK,GAAG;AACZ;AAEA,SAAS,4BAAoC;AAC3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF,EAAE,KAAK,GAAG;AACZ;AAEA,SAAS,iBAAiB,KAAqB;AAC7C,SAAO,IAAI,QAAQ,OAAO,EAAE;AAC9B;AAEA,SAAS,SAAS,GAA0C;AAC1D,SAAO,OAAO,MAAM,YAAY,MAAM;AACxC;AAEA,SAAS,YAAY,KAAuC;AAC1D,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,QAAM,EAAE,MAAM,MAAM,MAAM,KAAK,IAAI;AACnC,MACE,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS,UAChB;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK;AAClC;AAEA,SAAS,cAAc,KAAiC;AACtD,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,QAAM,SAAS,YAAY,IAAI,MAAM;AACrC,QAAM,MAAM,IAAI;AAChB,MAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;AACvB,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,QAAM,YAA4C,CAAC;AACnD,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,OAAO,KAAK;AACrB,QACE,CAAC,SAAS,GAAG,KACZ,IAAI,SAAS,WAAW,IAAI,SAAS,WAAW,IAAI,SAAS,OAC9D;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,KACJ,OAAO,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,WAC1C,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,KACjB;AACN,QAAI,GAAG,WAAW,GAAG;AACnB,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,QAAI,UAAU,IAAI,EAAE,GAAG;AACrB,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACpE;AACA,cAAU,IAAI,EAAE;AAChB,QAAI,IAAI,SAAS,SAAS;AACxB,gBAAU,KAAK,sBAAsB,GAAG,CAAC;AAAA,IAC3C,WAAW,IAAI,SAAS,SAAS;AAC/B,gBAAU,KAAK,sBAAsB,GAAG,CAAC;AAAA,IAC3C,OAAO;AACL,gBAAU,KAAK,oBAAoB,GAAG,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,UAAU;AAC7B;AAEA,SAAS,uBAAuB,UAAsC;AACpE,MAAI,CAAC,SAAS,QAAQ,KAAK,OAAO,SAAS,QAAQ,UAAU;AAC3D,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,QAAM,WAAW,cAAc,SAAS,QAAQ;AAChD,QAAM,MAAyB,EAAE,KAAK,SAAS,KAAK,SAAS;AAC7D,MAAI,gBAAgB,YAAY,MAAM,QAAQ,SAAS,UAAU,GAAG;AAClE,UAAM,UAAwD,CAAC;AAC/D,eAAW,KAAK,SAAS,YAAY;AACnC,UAAI,CAAC,SAAS,CAAC,KAAK,OAAO,EAAE,OAAO,YAAY,OAAO,EAAE,SAAS,UAAU;AAC1E;AAAA,MACF;AACA,YAAM,MAAkD;AAAA,QACtD,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,MACV;AACA,UAAI,OAAO,EAAE,QAAQ,SAAU,KAAI,MAAM,EAAE;AAC3C,cAAQ,KAAK,GAAG;AAAA,IAClB;AACA,QAAI,QAAQ,SAAS,EAAG,KAAI,aAAa;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,4BAA4B,KAAsC;AACzE,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,MAAI,OAAO,IAAI,YAAY,YAAY,OAAO,IAAI,SAAS,UAAU;AACnE,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AACA,MAAI,CAAC,MAAM,QAAQ,IAAI,SAAS,GAAG;AACjC,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,QAAM,YAAsB,CAAC;AAC7B,aAAW,KAAK,IAAI,WAAW;AAC7B,QAAI,OAAO,MAAM,UAAU;AACzB,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,cAAU,KAAK,CAAC;AAAA,EAClB;AACA,MACE,OAAO,IAAI,cAAc,YACzB,OAAO,IAAI,eAAe,YAC1B,OAAO,IAAI,YAAY,WACvB;AACA,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AACA,SAAO;AAAA,IACL,SAAS,IAAI;AAAA,IACb,MAAM,IAAI;AAAA,IACV;AAAA,IACA,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,SAAS,IAAI;AAAA,EACf;AACF;AAEA,SAAS,gCACP,KACwC;AACxC,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,WAAO;AAAA,EACT;AACA,QAAM,eAAe,IAAI;AACzB,QAAM,QAAQ,IAAI;AAClB,MAAI,OAAO,iBAAiB,YAAY,aAAa,WAAW,GAAG;AACjE,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GAAG;AACnD,WAAO;AAAA,EACT;AACA,QAAM,SAAqC;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AACA,MAAI,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,SAAS,GAAG;AACjE,WAAO,YAAY,IAAI;AAAA,EACzB;AACA,MAAI,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,SAAS,GAAG;AACzD,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAAS,gCAAwC;AAC/C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAwBA,eAAe,iCAAiC,SAGR;AACtC,MAAI,QAAQ,qBAAqB,MAAM;AACrC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,qCAAqC;AAAA,IAC1C,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,EACrB,CAAC;AACH;AAEA,SAAS,gBAAgB,KAAkC;AACzD,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,SAAS,GAAG;AACrD,WAAO,EAAE;AAAA,EACX;AACA,MAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,SAAS,GAAG;AACnD,WAAO,EAAE;AAAA,EACX;AACA,SAAO;AACT;AAEA,SAAS,yBACP,OACA,OACkB;AAClB,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,QAAM,MAAO,MAA+B;AAC5C,MAAI,OAAO,QAAQ,YAAY;AAC7B,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,SAAO,QAAQ;AAAA,IACZ,IAA+C,KAAK,OAAO,KAAK;AAAA,EACnE;AACF;AAEA,SAAS,oCACP,SACa;AACb,QAAM,MACJ,eAAe,UAAU,CAAC,GAAG,QAAQ,SAAS,IAAI,CAAC,QAAQ,QAAQ;AACrE,SAAO,IAAI;AAAA,IACT,IAAI,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,EACzD;AACF;AAgBO,IAAM,kBAAN,MAAsB;AAAA,EACV;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EAGA;AAAA,EACT,MAAqB;AAAA,EACrB,SAAS;AAAA,EACA,iBAAiB,oBAAI,IAAgB;AAAA,EACrC,uBAAuB,oBAAI,IAG1C;AAAA,EACM,mBAA6D;AAAA,EAErE,YAAY,UAAkC,CAAC,GAAG;AAChD,UAAM,QAAQ;AAAA,MACZ,gCAAgC;AAAA,IAClC;AACA,UAAM,kBAAkB,QAAQ,WAAW,OAAO;AAClD,QAAI,oBAAoB,UAAa,gBAAgB,KAAK,EAAE,WAAW,GAAG;AACxE,YAAM,IAAI,MAAM,0BAA0B,CAAC;AAAA,IAC7C;AACA,SAAK,UAAU,iBAAiB,eAAe;AAC/C,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,eAAe,QAAQ,YAAY;AAExC,UAAM,KACJ,QAAQ,oBACP,UAAU,OAAO,SAAY,EAAE,SAAS,YAAY,GAAG,OAAO,MAAM,MAAM;AAC7E,QACE,OAAO,UACP,OAAO,GAAG,YAAY,YACtB,GAAG,QAAQ,KAAK,EAAE,SAAS,KAC3B,OAAO,GAAG,UAAU,YACpB,GAAG,MAAM,SAAS,GAClB;AACA,WAAK,UAAU,GAAG,QAAQ,KAAK,EAAE,YAAY;AAC7C,YAAM,WAAW,2CAA2C,GAAG,KAAK;AACpE,WAAK,WAAW;AAChB,WAAK,gBAAgB,yBAAyB;AAAA,QAC5C,UAAU;AAAA,QACV,SAAS,KAAK;AAAA,MAChB,CAAC;AACD;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,8BAA8B,CAAC;AAAA,EACjD;AAAA,EAEQ,aAAa,OAAe,QAAuC;AACzE,QAAI,CAAC,KAAK,cAAc;AACtB;AAAA,IACF;AACA,YAAQ,KAAK,gCAAgC,KAAK,IAAI,MAAM;AAAA,EAC9D;AAAA,EAEQ,eAAe,OAAe,MAAM,MAAc;AACxD,WAAO,MAAM,UAAU,MAAM,QAAQ,GAAG,MAAM,MAAM,GAAG,GAAG,CAAC;AAAA,EAC7D;AAAA,EAEQ,iBAAiB,OAA0C;AACjE,SAAK,aAAa,iBAAiB;AAAA,MACjC,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM,UAAU,CAAC;AAAA,IAC3B,CAAC;AACD,SAAK,iBAAiB,KAAK;AAAA,EAC7B;AAAA,EAEA,QAAQ,SAAiC;AACvC,SAAK,eAAe,IAAI,OAAO;AAC/B,WAAO,MAAM;AACX,WAAK,eAAe,OAAO,OAAO;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,OAA4B;AAC1B,WAAO;AAAA,MACL,KAAK,OAAO,YAAoB;AAC9B,YAAI,OAAO,YAAY,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG;AAC5D,gBAAM,IAAI,MAAM,8BAA8B,CAAC;AAAA,QACjD;AACA,cAAM,KAAK,KAAK,IAAI,GAAG,OAAO,IAAI;AAClC,cAAM,IAAI,QAAc,CAAC,YAAY;AACnC,qBAAW,SAAS,EAAE;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAsC;AAC5C,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,gBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,cAAsC;AAC5C,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,GAAG,KAAK,YAAY;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,eACN,OACA,MACmB;AACnB,UAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,UAAM,OAAO,KAAK,YAAY;AAC9B,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,GAAG;AACzC,cAAQ,IAAI,GAAG,CAAC;AAAA,IAClB;AACA,WAAO,MAAM,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC;AAAA,EAC1C;AAAA,EAEA,MAAc,qBAAqB,SAGA;AACjC,UAAM,OAAiE;AAAA,MACrE,QAAQ,QAAQ;AAAA,MAChB,SAAS,KAAK;AAAA,IAChB;AACA,QAAI,QAAQ,eAAe,UAAa,QAAQ,WAAW,KAAK,EAAE,SAAS,GAAG;AAC5E,WAAK,aAAa,QAAQ,WAAW,KAAK;AAAA,IAC5C;AACA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,uBAAuB;AAAA,MAC5D,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,QAAI;AACJ,QAAI;AACF,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB,QAAQ;AACN,YAAM,IAAI,MAAM,2BAA2B,OAAO,IAAI,MAAM,CAAC,eAAe;AAAA,IAC9E;AACA,QAAI,CAAC,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM;AACvC,YAAM,SACJ,SAAS,IAAI,KAAK,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS,QAAQ,OAAO,IAAI,MAAM,CAAC;AAC9F,YAAM,IAAI,MAAM,2BAA2B,MAAM,EAAE;AAAA,IACrD;AACA,UAAM,WACJ,SAAS,IAAI,KAAK,OAAO,KAAK,aAAa,WAAW,KAAK,WAAW;AACxE,mBAAe,qBAAqB,2BAA2B;AAAA,MAC7D;AAAA,MACA,qBAAqB,GAAG,KAAK,cAAc,MAAM,GAAG,CAAC,CAAC;AAAA,IACxD,CAAC;AACD,WAAO,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,SAAwD;AACpE,UAAM,gBAAgB,SAAS,YAAY,KAAK;AAChD,QAAI,kBAAkB,UAAa,cAAc,SAAS,GAAG;AAC3D,YAAM,aAAa,MAAM,KAAK,qBAAqB;AAAA,QACjD,QAAQ,KAAK;AAAA,QACb,YAAY;AAAA,MACd,CAAC;AACD,cAAQ;AAAA,QACN,yCAAyC,WAAW,YAAY,SAAS;AAAA,MAC3E;AAAA,IACF;AACA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MAChE,SAAS,KAAK,YAAY;AAAA,IAC5B,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,mBAAmB,IAAI,MAAM,EAAE;AAAA,IACjD;AACA,UAAM,OAAgB,MAAM,IAAI,KAAK;AACrC,QAAI,CAAC,SAAS,IAAI,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,IAAI,WAAW,GAAG;AAC5E,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AACA,SAAK,MAAM,KAAK;AAChB,SAAK,aAAa,mBAAmB;AAAA,MACnC,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,IAChB,CAAC;AACD,SAAK,iBAAiB;AAAA,MACpB,MAAM;AAAA,MACN,QAAQ,EAAE,KAAK,KAAK,IAAI;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,eAAW,CAAC,UAAU,UAAU,KAAK,MAAM;AAAA,MACzC,KAAK,qBAAqB,QAAQ;AAAA,IACpC,GAAG;AACD,oBAAc,WAAW,KAAK;AAC9B,UAAI;AACF,cAAM,KAAK,2BAA2B;AAAA,UACpC;AAAA,UACA,cAAc,WAAW;AAAA,QAC3B,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,qBAAqB,MAAM;AAChC,SAAK,SAAS;AACd,SAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpD,eAAW,WAAW,MAAM,KAAK,KAAK,cAAc,GAAG;AACrD,UAAI;AACF,gBAAQ;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAuB;AACrB,QAAI,KAAK,QAAQ,MAAM;AACrB,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAAwB;AACtB,UAAM,IAAI,IAAI,IAAI,qBAAqB,KAAK,OAAO;AACnD,MAAE,SAAS;AACX,WAAO,EAAE,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,SAAgD;AACxD,SAAK,mBAAmB,EAAE,GAAG,QAAQ,OAAO;AAC5C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,mBAA+C;AACnD,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,EAAE,IAAI,oBAAoB,SAAS,CAAC,EAAE,CAAC;AAAA,IAC9D,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,qBAAqB,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,IAC3D;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,QAAI,CAAC,SAAS,IAAI,KAAK,EAAE,cAAc,OAAO;AAC5C,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,WAAO,uBAAuB,KAAK,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,WAAqD;AAC5E,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU;AAAA,QACnB,IAAI;AAAA,QACJ,SAAS,EAAE,WAAW,QAAQ;AAAA,MAChC,CAAC;AAAA,IACH,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,IAC7D;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AACA,WAAO,4BAA4B,IAAI;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,WAIM;AACxB,QAAI,cAAmC;AACvC,UAAM,QAAQ,YAAY;AACxB,UAAI;AACF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,oBAAoB;AAC/D,YAAI,WAAW,MAAM,KAAK,iBAAiB;AAC3C,kBAAU,WAAW,QAAQ;AAC7B,cAAM,SAAS,GAAG,KAAK,OAAO,8BAA8B;AAAA,UAC1D,KAAK,aAAa;AAAA,QACpB,CAAC;AACD,aAAK,aAAa,gCAAgC,EAAE,OAAO,CAAC;AAC5D,cAAM,SAAS,kBAAkB;AAAA,UAC/B,KAAK;AAAA,UACL,OAAO,CAAC,OAAO,SAAS,KAAK,eAAe,OAAO,IAAI;AAAA,QACzD,CAAC;AACD,sBAAc,MAAM;AAClB,iBAAO,MAAM;AAAA,QACf;AACA,yBAAiB,OAAO,QAAQ;AAC9B,gBAAM,YACJ,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,OAAQ,IAA2B,SAAS,WACvC,IAAyB,OAC1B;AACN,cAAI,OAAO,IAAI,SAAS,UAAU;AAChC,iBAAK,aAAa,uBAAuB;AAAA,cACvC,QAAQ;AAAA,cACR;AAAA,YACF,CAAC;AACD;AAAA,UACF;AACA,eAAK,aAAa,0BAA0B;AAAA,YAC1C;AAAA,YACA,YAAY,IAAI,KAAK;AAAA,YACrB,aAAa,KAAK,eAAe,IAAI,IAAI;AAAA,UAC3C,CAAC;AACD,cAAI;AACJ,cAAI;AACF,mBAAO,KAAK,MAAM,IAAI,IAAI;AAAA,UAC5B,QAAQ;AACN,iBAAK,aAAa,4BAA4B;AAAA,cAC5C,QAAQ;AAAA,cACR;AAAA,YACF,CAAC;AACD;AAAA,UACF;AACA,cAAI,UAAU,iBAAiB;AAC7B,gBAAI;AACF,oBAAM,QAAQ,+BAA+B,IAAI;AACjD,mBAAK,aAAa,2BAA2B;AAAA,gBAC3C,QAAQ,MAAM;AAAA,gBACd,WAAW,MAAM;AAAA,gBACjB,MAAM,MAAM;AAAA,gBACZ,YAAY,MAAM;AAAA,cACpB,CAAC;AACD,wBAAU,gBAAgB,KAAK;AAAA,YACjC,QAAQ;AACN,mBAAK,aAAa,2BAA2B;AAAA,gBAC3C,QAAQ;AAAA,cACV,CAAC;AAAA,YACH;AAAA,UACF;AACA,gBAAM,SAAS,2CAA2C,IAAI;AAC9D,cAAI,WAAW,UAAa,OAAO,MAAM,WAAW,GAAG;AACrD;AAAA,UACF;AACA,eAAK,aAAa,oCAAoC;AAAA,YACpD,WAAW,OAAO,MAAM;AAAA,YACxB,YAAY,OAAO,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS;AAAA,UACjD,CAAC;AACD,gBAAM,UAAU,+BAA+B,OAAO,KAAK;AAC3D,qBAAW,OAAO,SAAS;AACzB,kBAAM,OAAO,MAAM,KAAK,mBAAmB,IAAI,SAAS;AACxD,uBAAW,iCAAiC,UAAU,IAAI;AAAA,UAC5D;AACA,oBAAU,WAAW,QAAQ;AAAA,QAC/B;AAAA,MACF,SAAS,GAAG;AACV,cAAM,MAAM,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AACxD,aAAK,aAAa,wBAAwB;AAAA,UACxC,SAAS,IAAI;AAAA,QACf,CAAC;AACD,kBAAU,UAAU,GAAG;AAAA,MACzB;AAAA,IACF,GAAG;AACH,WAAO;AAAA,MACL,OAAO,MAAM;AACX,aAAK,aAAa,6BAA6B,CAAC,CAAC;AACjD,sBAAc;AACd,aAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAS,OAAiD;AAC9D,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,sBAAsB,KAAK;AACjC,UAAM,aAAa,MAAM,KAAK,qBAAqB;AAAA,MACjD,QAAQ,MAAM;AAAA,MACd,YAAY;AAAA,IACd,CAAC;AACD,YAAQ;AAAA,MACN;AAAA,QACE;AAAA,QACA;AAAA,QACA,gBAAgB,MAAM,MAAM;AAAA,QAC5B,gBAAgB,WAAW,YAAY,SAAS;AAAA,QAChD,gBAAgB,mBAAmB;AAAA,MACrC,EAAE,KAAK,IAAI;AAAA,IACb;AACA,UAAM,MAAM,GAAG,KAAK,OAAO,+BAA+B,mBAAmB,GAAG,CAAC;AACjF,UAAM,eAAe,WAAW;AAChC,UAAM,kBAAkB;AACxB,QAAI;AACJ,QAAI;AACJ,QAAI,MAAM,cAAc,QAAQ,KAAK,qBAAqB,MAAM;AAC9D,cAAQ,IAAI,6CAA6C,MAAM,IAAI;AACnE,qCAA+B,4BAA4B;AAAA,QACzD,QAAQ,KAAK;AAAA,QACb,WAAW,MAAM;AAAA,MACnB,CAAC;AACD,+BAAyB,MAAM,qCAAqC;AAAA,QAClE,QAAQ,KAAK;AAAA,QACb,WAAW,MAAM;AAAA,MACnB,CAAC;AACD,WAAK,aAAa,wBAAwB;AAAA,QACxC,WAAW,MAAM;AAAA,QACjB,OAAO,KAAK,iBAAiB;AAAA,QAC7B,OAAO,KAAK,iBAAiB;AAAA,MAC/B,CAAC;AAAA,IACH;AACA,YAAQ,IAAI,0BAA0B,sBAAsB;AAC5D,YAAQ,IAAI,gCAAgC,4BAA4B;AACxE,UAAM,iBAAiB;AAAA,MACrB,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,OAAO,MAAM;AAAA,MACb,YAAY;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,MACA,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,MACtE,GAAI,2BAA2B,SAC3B,EAAE,gBAAgB,uBAAuB,IACzC,CAAC;AAAA,MACL,GAAI,iCAAiC,SACjC,EAAE,sBAAsB,6BAA6B,IACrD,CAAC;AAAA,IACP;AACA,SAAK,aAAa,4BAA4B;AAAA,MAC5C;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,UAAM,cAAc,KAAK,UAAU,cAAc;AACjD,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM;AAAA,IACR,CAAC;AACD,UAAM,WAAW,MAAM,IAAI,KAAK;AAChC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,aAAa,IAAI,MAAM,IAAI,QAAQ,EAAE;AAAA,IACvD;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,QAAQ;AAAA,IAC5B,QAAQ;AACN,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AACA,QAAI,CAAC,SAAS,IAAI,GAAG;AACnB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AACA,UAAM,WAAW,KAAK;AACtB,UAAM,aAAa,KAAK;AACxB,QAAI,OAAO,aAAa,YAAY,OAAO,eAAe,UAAU;AAClE,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,UAAM,kBAAkB,4BAA4B,KAAK,eAAe;AACxE,UAAM,mBACJ,OAAO,KAAK,iBAAiB,YAAY,KAAK,aAAa,SAAS,IAChE,KAAK,eACL;AACN,UAAM,sBACJ,OAAO,KAAK,oBAAoB,YAAY,OAAO,SAAS,KAAK,eAAe,IAC5E,KAAK,kBACL;AACN,UAAM,qBAAqB,KAAK,qBAAqB,IAAI,QAAQ;AACjE,QAAI,uBAAuB,QAAW;AACpC,oBAAc,mBAAmB,KAAK;AAAA,IACxC;AACA,UAAM,QAAQ,YAAY,MAAM;AAC9B,WAAK,KAAK,0BAA0B;AAAA,QAClC;AAAA,QACA,cAAc;AAAA,QACd,iBAAiB;AAAA,MACnB,CAAC,EAAE,MAAM,CAAC,QAAiB;AACzB,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,gBAAQ,MAAM,oDAAoD;AAAA,UAChE;AAAA,UACA,cAAc;AAAA,UACd,iBAAiB;AAAA,UACjB,UAAU;AAAA,UACV,cAAc;AAAA,UACd,OAAO;AAAA,QACT,CAAC;AAAA,MACH,CAAC;AAAA,IACH,GAAG,IAAM;AACT,SAAK,qBAAqB,IAAI,UAAU;AAAA,MACtC,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB;AAAA,IACF,CAAC;AACD,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,oBACJ,KAAK,cAAc,QAAQ,KAAK,cAAc,QAC1C,KAAK,YACL;AACN,UAAM,YAA2B,qBAAqB,MAAM,aAAa;AACzE,UAAM,iBAAiB,gCAAgC,KAAK,cAAc;AAC1E,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,MAAM;AAAA,MACZ;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,mBAAmB,SAAY,EAAE,eAAe,IAAI,CAAC;AAAA,MACzD,cAAc;AAAA,MACd,iBAAiB;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,OAAkD;AAChE,UAAM,UAAyB;AAAA,MAC7B,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,OAAO,MAAM;AAAA,MACb,QAAQ,MAAM;AAAA,IAChB;AACA,QAAI,MAAM,cAAc,QAAW;AACjC,cAAQ,YAAY,MAAM;AAAA,IAC5B;AACA,QAAI,MAAM,YAAY,QAAW;AAC/B,cAAQ,UAAU,MAAM;AAAA,IAC1B;AACA,QAAI,MAAM,cAAc,QAAW;AACjC,cAAQ,YAAY,MAAM;AAAA,IAC5B;AACA,QAAI,MAAM,cAAc,QAAW;AACjC,cAAQ,YAAY,MAAM;AAAA,IAC5B;AACA,QAAI,MAAM,eAAe,QAAW;AAClC,cAAQ,aAAa,MAAM;AAAA,IAC7B;AACA,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B;AAAA,EAEA,MAAM,kBAAkB,OAA8C;AACpE,UAAM,KAAK,IAAI,qBAAqB;AAAA,MAClC,UAAU,MAAM;AAAA,MAChB,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,UAAkB,SAAiC;AACrE,UAAM,KAAK,IAAI,iBAAiB,EAAE,UAAU,QAAQ,CAAC;AAAA,EACvD;AAAA,EAEA,MAAM,qBAAqB,SAAiD;AAC1E,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,+BAA+B,mBAAmB,GAAG,CAAC;AACjF,SAAK,aAAa,iCAAiC;AAAA,MACjD;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ;AAAA,MACpB,cAAc,QAAQ;AAAA,MACtB,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,OAAO,QAAQ;AAAA,MACf,eACE,QAAQ,WAAW,SACf,KAAK,eAAe,KAAK,UAAU,QAAQ,MAAM,CAAC,IAClD;AAAA,IACR,CAAC;AACD,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,EAAE,IAAI,sBAAsB,QAAQ,CAAC;AAAA,IAC5D,CAAC;AACD,UAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,SAAK,aAAa,8BAA8B;AAAA,MAC9C,WAAW,QAAQ;AAAA,MACnB,YAAY,IAAI;AAAA,MAChB,aAAa,KAAK,eAAe,MAAM;AAAA,IACzC,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,qBAAqB,IAAI,MAAM,IAAI,MAAM,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,0BACE,SACuB;AACvB,UAAM,aAAa,oCAAoC,OAAO;AAC9D,UAAM,kBAAkB,MAAM,KAAK,UAAU,EAAE,KAAK;AACpD,QAAI,WAAW,SAAS,GAAG;AACzB,WAAK,aAAa,kCAAkC;AAAA,QAClD,QAAQ;AAAA,MACV,CAAC;AACD,aAAO,EAAE,OAAO,MAAM;AAAA,MAAC,EAAE;AAAA,IAC3B;AACA,SAAK,aAAa,mCAAmC;AAAA,MACnD,WAAW;AAAA,IACb,CAAC;AACD,UAAM,EAAE,aAAa,qBAAqB,IAAI;AAC9C,QAAI,cAAmC;AACvC,UAAM,QAAQ,YAAY;AACxB,UAAI;AACF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,oBAAoB;AAC/D,cAAM,SAAS,GAAG,KAAK,OAAO,8BAA8B;AAAA,UAC1D,KAAK,aAAa;AAAA,QACpB,CAAC;AACD,aAAK,aAAa,sCAAsC;AAAA,UACtD;AAAA,UACA,oBAAoB;AAAA,QACtB,CAAC;AACD,cAAM,SAAS,kBAAkB;AAAA,UAC/B,KAAK;AAAA,UACL,OAAO,CAAC,OAAO,SAAS,KAAK,eAAe,OAAO,IAAI;AAAA,QACzD,CAAC;AACD,sBAAc,MAAM;AAClB,iBAAO,MAAM;AAAA,QACf;AACA,yBAAiB,OAAO,QAAQ;AAC9B,gBAAM,WAAW,gBAAgB,GAAG;AACpC,cACE,aAAa,UACb,aAAa,sBACb;AACA;AAAA,UACF;AACA,cAAI,OAAO,IAAI,SAAS,UAAU;AAChC,kBAAM,aAAa,YAAY;AAC/B,iBAAK,aAAa,6BAA6B;AAAA,cAC7C,QAAQ;AAAA,cACR,UAAU;AAAA,YACZ,CAAC;AACD;AAAA,UACF;AACA,cAAI;AACJ,cAAI;AACF,mBAAO,KAAK,MAAM,IAAI,IAAI;AAAA,UAC5B,QAAQ;AACN,iBAAK,aAAa,kCAAkC;AAAA,cAClD,QAAQ;AAAA,cACR,UAAU,YAAY;AAAA,YACxB,CAAC;AACD;AAAA,UACF;AACA,cAAI;AACJ,cAAI;AACF,oBAAQ,+BAA+B,IAAI;AAAA,UAC7C,QAAQ;AACN;AAAA,UACF;AACA,cAAI,MAAM,WAAW,aAAa;AAChC;AAAA,UACF;AACA,gBAAM,MAAM,MAAM;AAClB,cAAI,QAAQ,QAAW;AACrB,iBAAK,aAAa,6BAA6B;AAAA,cAC7C,QAAQ;AAAA,cACR,WAAW,MAAM;AAAA,YACnB,CAAC;AACD;AAAA,UACF;AACA,cAAI,CAAC,WAAW,IAAI,IAAI,UAAU,GAAG;AACnC;AAAA,UACF;AACA,eAAK,aAAa,kCAAkC;AAAA,YAClD,WAAW,IAAI;AAAA,YACf,cAAc,IAAI;AAAA,YAClB,YAAY,IAAI;AAAA,YAChB,MAAM,IAAI;AAAA,YACV,UAAU,IAAI;AAAA,UAChB,CAAC;AACD,cAAI;AACF,gBAAI;AACJ,kBAAM,cAAc,GAAG,IAAI,IAAI;AAC/B,gBAAI,gBAAgB,cAAc,gBAAgB,SAAS;AACzD,oBAAM,iBAAiB,MAAM,iCAAiC;AAAA,gBAC5D,kBAAkB,KAAK;AAAA,gBACvB,UAAU,IAAI;AAAA,cAChB,CAAC;AACD,uBAAS;AAAA,gBACP,aAAa;AAAA,gBACb,SAAS;AAAA,gBACT;AAAA,cACF;AAAA,YACF,WACE,IAAI,SAAS,UACb,yBAAyB,UACzB,qBAAqB,IAAI,IAAI,UAAU,GACvC;AACA,oBAAM,KAAK,qBAAqB,IAAI,IAAI,UAAU;AAClD,kBAAI,OAAO,QAAW;AACpB,sBAAM,IAAI,MAAM,8CAA8C;AAAA,cAChE;AACA,mBAAK,aAAa,6BAA6B;AAAA,gBAC7C,WAAW,IAAI;AAAA,gBACf,YAAY,IAAI;AAAA,gBAChB,aAAa,KAAK,eAAe,IAAI,QAAQ,EAAE;AAAA,cACjD,CAAC;AACD,oBAAM,SAAS,MAAM,yBAAyB,IAAI;AAAA,gBAChD,UAAU,CAAC,IAAI,aAAa,IAAI,QAAQ,EAAE,CAAC;AAAA,cAC7C,CAAC;AACD,uBAAS,8CAA8C,MAAM;AAC7D,mBAAK,aAAa,uCAAuC;AAAA,gBACvD,WAAW,IAAI;AAAA,gBACf,eAAe,KAAK,eAAe,KAAK,UAAU,MAAM,CAAC;AAAA,cAC3D,CAAC;AAAA,YACH,WAAW,IAAI,SAAS,YAAY,IAAI,SAAS,QAAQ;AACvD,oBAAM,WACJ,IAAI,SAAS,SAAS,cAAc,IAAI,YAAY;AACtD,oBAAM,OACJ,IAAI,SAAS,SACT,EAAE,MAAM,IAAI,QAAQ,GAAG,IACtB,IAAI,QAAQ,CAAC;AACpB,mBAAK,aAAa,wBAAwB;AAAA,gBACxC,WAAW,IAAI;AAAA,gBACf;AAAA,gBACA,aAAa,KAAK,eAAe,KAAK,UAAU,IAAI,CAAC;AAAA,cACvD,CAAC;AACD,mBAAK,aAAa,gCAAgC;AAAA,gBAChD,WAAW,IAAI;AAAA,gBACf;AAAA,gBACA,aAAa,KAAK,eAAe,KAAK,UAAU,IAAI,CAAC;AAAA,cACvD,CAAC;AACD,uBAAS,MAAM,QAAQ;AAAA,gBACrB,YAAY,EAAE,UAAU,KAAK,CAAC;AAAA,cAChC;AACA,mBAAK,aAAa,kCAAkC;AAAA,gBAClD,WAAW,IAAI;AAAA,gBACf;AAAA,gBACA,aAAa,KAAK,eAAe,KAAK,UAAU,IAAI,CAAC;AAAA,gBACrD,eAAe,KAAK,eAAe,KAAK,UAAU,MAAM,CAAC;AAAA,cAC3D,CAAC;AAAA,YACH,OAAO;AACL,mBAAK,aAAa,qCAAqC;AAAA,gBACrD,WAAW,IAAI;AAAA,gBACf,MAAM,IAAI;AAAA,gBACV,YAAY,IAAI;AAAA,cAClB,CAAC;AACD;AAAA,YACF;AACA,kBAAM,KAAK,qBAAqB;AAAA,cAC9B,WAAW,IAAI;AAAA,cACf,YAAY,IAAI;AAAA,cAChB,YAAY,IAAI;AAAA,cAChB,cAAc,IAAI;AAAA,cAClB,MAAM,IAAI;AAAA,cACV,QAAQ;AAAA,cACR,UAAU,IAAI;AAAA,cACd,KAAI,oBAAI,KAAK,GAAE,YAAY;AAAA,cAC3B;AAAA,YACF,CAAC;AAAA,UACH,SAAS,KAAK;AACZ,kBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,iBAAK,aAAa,8BAA8B;AAAA,cAC9C,WAAW,IAAI;AAAA,cACf;AAAA,YACF,CAAC;AACD,kBAAM,KAAK,qBAAqB;AAAA,cAC9B,WAAW,IAAI;AAAA,cACf,YAAY,IAAI;AAAA,cAChB,YAAY,IAAI;AAAA,cAChB,cAAc,IAAI;AAAA,cAClB,MAAM,IAAI;AAAA,cACV,QAAQ;AAAA,cACR,UAAU,IAAI;AAAA,cACd,OAAO;AAAA,cACP,KAAI,oBAAI,KAAK,GAAE,YAAY;AAAA,YAC7B,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,aAAK,aAAa,qCAAqC,EAAE,QAAQ,CAAC;AAAA,MACpE;AAAA,IACF,GAAG;AACH,WAAO;AAAA,MACL,OAAO,MAAM;AACX,aAAK,aAAa,mCAAmC;AAAA,UACnD,WAAW;AAAA,QACb,CAAC;AACD,sBAAc;AACd,aAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,SAA0D;AAC1E,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,oCAAoC,mBAAmB,GAAG,CAAC;AACtF,UAAM,OAAuC,EAAE,MAAM,QAAQ,KAAK;AAClE,QAAI,QAAQ,QAAQ,QAAW;AAC7B,WAAK,MAAM,QAAQ;AAAA,IACrB;AACA,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,gBAAgB,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,IACtD;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AACA,QAAI,CAAC,SAAS,IAAI,KAAK,OAAO,KAAK,OAAO,UAAU;AAClD,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,IAAI,IAAY,SAAiC;AAC7D,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,+BAA+B,mBAAmB,GAAG,CAAC;AACjF,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,EAAE,IAAI,QAAQ,CAAC;AAAA,IACtC,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,IAAI,KAAK;AACzB,YAAM,IAAI,MAAM,OAAO,EAAE,KAAK,IAAI,MAAM,IAAI,CAAC,EAAE;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAc,0BAA0B,OAItB;AAChB,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,yCAAyC,mBAAmB,GAAG,CAAC;AAC3F,UAAM,WAAW,KAAK,UAAU;AAAA,MAC9B,UAAU,MAAM;AAAA,MAChB,cAAc,MAAM;AAAA,MACpB,iBAAiB,MAAM;AAAA,IACzB,CAAC;AACD,QAAI,YAAmB,IAAI,MAAM,kCAAkC;AAEnE,aAAS,UAAU,GAAG,WAAW,0CAA0C,WAAW,GAAG;AACvF,YAAM,mBAAmB,KAAK,IAAI;AAClC,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,KAAK;AAAA,UAC3B,QAAQ;AAAA,UACR,SAAS,KAAK,YAAY;AAAA,UAC1B,MAAM;AAAA,QACR,CAAC;AACD,cAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAI,IAAI,IAAI;AACV,cAAI,UAAU,GAAG;AACf,oBAAQ,KAAK,0DAA0D;AAAA,cACrE,UAAU,MAAM;AAAA,cAChB,cAAc,MAAM;AAAA,cACpB,iBAAiB,MAAM;AAAA,cACvB;AAAA,cACA;AAAA,cACA,mBAAmB;AAAA,cACnB,cAAc;AAAA,cACd,aAAa;AAAA,cACb,YAAY,KAAK,IAAI,IAAI;AAAA,YAC3B,CAAC;AAAA,UACH;AACA;AAAA,QACF;AACA,oBAAY,IAAI,MAAM,cAAc,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,MAC1D,SAAS,KAAc;AACrB,oBACE,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,MACtD;AAEA,YAAM,YAAY,UAAU;AAC5B,cAAQ,KAAK,yDAAyD;AAAA,QACpE,OAAO;AAAA,QACP,UAAU,MAAM;AAAA,QAChB,cAAc,MAAM;AAAA,QACpB,iBAAiB,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa;AAAA,QACb,mCACE,2CAA2C;AAAA,QAC7C,cAAc,UAAU;AAAA,QACxB,kBAAkB,SAAS;AAAA,QAC3B,mBAAmB,KAAK,IAAI,IAAI;AAAA,QAChC,YAAY,YACR,SAAS,0CAA0C,kBACnD;AAAA,QACJ,cAAc,YACV,6CACA;AAAA,MACN,CAAC;AAED,UAAI,CAAC,WAAW;AACd,cAAM;AAAA,MACR;AAEA,YAAM,IAAI,QAAc,CAAC,YAAY;AACnC,mBAAW,SAAS,0CAA0C;AAAA,MAChE,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,2BAA2B,OAGvB;AAChB,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,0CAA0C,mBAAmB,GAAG,CAAC;AAC5F,UAAM,MAAM,KAAK;AAAA,MACf,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU;AAAA,QACnB,UAAU,MAAM;AAAA,QAChB,cAAc,MAAM;AAAA,MACtB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;;;AG9rCA;AAAA,EAGE;AAAA,EACA,4CAAAA;AAAA,EACA,eAAAC;AAAA,EACA,8CAAAC;AAAA,EACA;AAAA,EACA,mCAAAC;AAAA,OACK;","names":["loadAgentPlayCredentialsFileFromPathSync","loadRootKey","nodeCredentialsMaterialFromHumanPassphrase","resolveAgentPlayCredentialsPath"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-play/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.1
|
|
4
|
+
"version": "3.2.1",
|
|
5
5
|
"description": "Node.js SDK to register agents, stream world state, and connect to the Agent Play web UI over HTTP.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"test": "vitest run"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@agent-play/intercom": "
|
|
43
|
+
"@agent-play/intercom": "^3.3.0",
|
|
44
44
|
"@langchain/core": "^1.1.35",
|
|
45
|
-
"@agent-play/node-tools": "
|
|
45
|
+
"@agent-play/node-tools": "^3.1.0",
|
|
46
46
|
"@langchain/openai": "^1.3.0",
|
|
47
47
|
"dotenv": "^17.3.1",
|
|
48
48
|
"eventsource-client": "^1.2.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/world-bounds.ts","../src/lib/world-chain-keys.ts","../src/lib/parse-occupant-row.ts","../src/lib/player-chain-merge.ts"],"sourcesContent":["/**\n * Axis-aligned rectangle in world coordinates (grid units). Used by the server to clamp paths\n * and by the watch UI to clamp joystick-driven movement.\n *\n * @remarks **Consumers:** {@link clampWorldPosition}, {@link boundsContain}; server `PlayWorld` and\n * play-ui canvas both import these helpers from `@agent-play/sdk`.\n */\nexport type WorldBounds = {\n /** Inclusive minimum X. */\n minX: number;\n /** Inclusive minimum Y. */\n minY: number;\n /** Inclusive maximum X. */\n maxX: number;\n /** Inclusive maximum Y. */\n maxY: number;\n};\n\n/**\n * Clamps a point to lie inside `bounds` along both axes.\n *\n * @param p - Position with `x` and `y` in world units.\n * @param bounds - Valid rectangle (`min` ≤ `max` per axis).\n * @returns Same point if inside, otherwise clamped to the nearest edge.\n *\n * @remarks **Callers:** server `PlayWorld` path enrichment; play-ui joystick and preview. **Callees:** `Math.min/Math.max`.\n */\nexport function clampWorldPosition(\n p: { x: number; y: number },\n bounds: WorldBounds\n): { x: number; y: number } {\n return {\n x: Math.min(Math.max(p.x, bounds.minX), bounds.maxX),\n y: Math.min(Math.max(p.y, bounds.minY), bounds.maxY),\n };\n}\n\n/**\n * @returns Whether `p` lies inside or on the border of `bounds`.\n *\n * @remarks **Callers:** optional UI checks. **Callees:** none.\n */\nexport function boundsContain(\n bounds: WorldBounds,\n p: { x: number; y: number }\n): boolean {\n return (\n p.x >= bounds.minX &&\n p.x <= bounds.maxX &&\n p.y >= bounds.minY &&\n p.y <= bounds.maxY\n );\n}\n","export const PLAYER_CHAIN_GENESIS_STABLE_KEY = \"__genesis__\" as const;\nexport const PLAYER_CHAIN_HEADER_STABLE_KEY = \"__header__\" as const;\n","import type {\n AgentPlayWorldMapHumanOccupant,\n AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapMcpOccupant,\n} from \"../public-types.js\";\n\nexport function parseHumanOccupantRow(\n raw: Record<string, unknown>\n): AgentPlayWorldMapHumanOccupant {\n if (typeof raw.id !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"occupant: human needs id and name\");\n }\n if (typeof raw.x !== \"number\" || typeof raw.y !== \"number\") {\n throw new Error(\"occupant: human needs numeric x and y\");\n }\n const base: AgentPlayWorldMapHumanOccupant = {\n kind: \"human\",\n id: raw.id,\n name: raw.name,\n x: raw.x,\n y: raw.y,\n };\n if (typeof raw.interactive === \"boolean\") {\n return { ...base, interactive: raw.interactive };\n }\n return base;\n}\n\nexport function parseAgentOccupantRow(\n raw: Record<string, unknown>\n): AgentPlayWorldMapAgentOccupant {\n if (typeof raw.agentId !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"occupant: agent needs agentId and name\");\n }\n if (typeof raw.x !== \"number\" || typeof raw.y !== \"number\") {\n throw new Error(\"occupant: agent needs numeric x and y\");\n }\n const base: AgentPlayWorldMapAgentOccupant = {\n kind: \"agent\",\n agentId: raw.agentId,\n name: raw.name,\n x: raw.x,\n y: raw.y,\n };\n if (typeof raw.nodeId === \"string\" && raw.nodeId.length > 0) {\n base.nodeId = raw.nodeId;\n }\n let platform: string | undefined;\n if (typeof raw.platform === \"string\") {\n platform = raw.platform;\n } else if (typeof raw.agentType === \"string\") {\n platform = raw.agentType;\n }\n if (platform !== undefined) {\n return { ...base, platform };\n }\n return base;\n}\n\nexport function parseMcpOccupantRow(\n raw: Record<string, unknown>\n): AgentPlayWorldMapMcpOccupant {\n if (typeof raw.id !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"occupant: mcp needs id and name\");\n }\n if (typeof raw.x !== \"number\" || typeof raw.y !== \"number\") {\n throw new Error(\"occupant: mcp needs numeric x and y\");\n }\n const base: AgentPlayWorldMapMcpOccupant = {\n kind: \"mcp\",\n id: raw.id,\n name: raw.name,\n x: raw.x,\n y: raw.y,\n };\n if (typeof raw.url === \"string\") {\n return { ...base, url: raw.url };\n }\n return base;\n}\n","/**\n * Parses **`playerChainNotify`** envelopes and merges {@link PlayerChainNodeResponse} slices into {@link AgentPlaySnapshot} (pure functions + fetch ordering for serialized RPC).\n */\n\nimport type {\n AgentPlaySnapshot,\n AgentPlayWorldMapHumanOccupant,\n AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapMcpOccupant,\n PlayerChainFanoutNotify,\n PlayerChainNotifyNodeRef,\n PlayerChainNodeResponse,\n} from \"../public-types.js\";\nimport {\n parseHumanOccupantRow,\n parseAgentOccupantRow,\n parseMcpOccupantRow,\n} from \"./parse-occupant-row.js\";\nimport {\n PLAYER_CHAIN_GENESIS_STABLE_KEY,\n PLAYER_CHAIN_HEADER_STABLE_KEY,\n} from \"./world-chain-keys.js\";\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null;\n}\n\nfunction stableOccupantSortKey(\n occ:\n | AgentPlayWorldMapHumanOccupant\n | AgentPlayWorldMapAgentOccupant\n | AgentPlayWorldMapMcpOccupant\n): string {\n if (occ.kind === \"human\") {\n return `human:${occ.id}`;\n }\n if (occ.kind === \"agent\") {\n const nodeId = occ.nodeId;\n if (typeof nodeId !== \"string\" || nodeId.length === 0) {\n throw new Error(\"stableOccupantSortKey: invalid agent nodeId\");\n }\n return `agent:${nodeId}:${occ.agentId}`;\n }\n return `mcp:${occ.id}`;\n}\n\nexport function sortNodeRefsForSerializedFetch(\n nodes: ReadonlyArray<PlayerChainNotifyNodeRef>\n): PlayerChainNotifyNodeRef[] {\n const removed = nodes.filter((n) => n.removed === true);\n const rest = nodes.filter((n) => n.removed !== true);\n removed.sort((a, b) => b.leafIndex - a.leafIndex);\n rest.sort((a, b) => a.leafIndex - b.leafIndex);\n return [...removed, ...rest];\n}\n\nexport function parsePlayerChainFanoutNotify(\n raw: unknown\n): PlayerChainFanoutNotify | undefined {\n if (!isRecord(raw)) {\n return undefined;\n }\n if (typeof raw.updatedAt !== \"string\" || raw.updatedAt.length === 0) {\n return undefined;\n }\n if (!Array.isArray(raw.nodes)) {\n return undefined;\n }\n const nodes: PlayerChainNotifyNodeRef[] = [];\n for (const row of raw.nodes) {\n if (!isRecord(row)) {\n return undefined;\n }\n if (typeof row.stableKey !== \"string\" || row.stableKey.length === 0) {\n return undefined;\n }\n if (typeof row.leafIndex !== \"number\" || !Number.isFinite(row.leafIndex)) {\n return undefined;\n }\n const ref: PlayerChainNotifyNodeRef = {\n stableKey: row.stableKey,\n leafIndex: row.leafIndex,\n };\n if (row.removed === true) {\n ref.removed = true;\n }\n if (typeof row.updatedAt === \"string\" && row.updatedAt.length > 0) {\n ref.updatedAt = row.updatedAt;\n }\n nodes.push(ref);\n }\n return { updatedAt: raw.updatedAt, nodes };\n}\n\nexport function parsePlayerChainFanoutNotifyFromSsePayload(\n sseData: unknown\n): PlayerChainFanoutNotify | undefined {\n if (!isRecord(sseData)) {\n return undefined;\n }\n return parsePlayerChainFanoutNotify(sseData.playerChainNotify);\n}\n\nexport function parsePlayerChainNodeRpcBody(json: unknown): PlayerChainNodeResponse {\n if (!isRecord(json) || !isRecord(json.node)) {\n throw new Error(\"getPlayerChainNode: invalid response shape\");\n }\n const n = json.node;\n if (n.kind === \"genesis\") {\n if (\n n.stableKey !== PLAYER_CHAIN_GENESIS_STABLE_KEY ||\n typeof n.text !== \"string\"\n ) {\n throw new Error(\"getPlayerChainNode: invalid genesis node\");\n }\n return {\n kind: \"genesis\",\n stableKey: PLAYER_CHAIN_GENESIS_STABLE_KEY,\n text: n.text,\n };\n }\n if (n.kind === \"header\") {\n if (\n n.stableKey !== PLAYER_CHAIN_HEADER_STABLE_KEY ||\n typeof n.sid !== \"string\"\n ) {\n throw new Error(\"getPlayerChainNode: invalid header node\");\n }\n const b = n.bounds;\n if (!isRecord(b)) {\n throw new Error(\"getPlayerChainNode: invalid header bounds\");\n }\n const { minX, minY, maxX, maxY } = b;\n if (\n typeof minX !== \"number\" ||\n typeof minY !== \"number\" ||\n typeof maxX !== \"number\" ||\n typeof maxY !== \"number\"\n ) {\n throw new Error(\"getPlayerChainNode: invalid header bounds\");\n }\n return {\n kind: \"header\",\n stableKey: PLAYER_CHAIN_HEADER_STABLE_KEY,\n sid: n.sid,\n bounds: { minX, minY, maxX, maxY },\n };\n }\n if (n.kind !== \"occupant\") {\n throw new Error(\"getPlayerChainNode: unknown node kind\");\n }\n if (typeof n.stableKey !== \"string\" || n.stableKey.length === 0) {\n throw new Error(\"getPlayerChainNode: invalid occupant stableKey\");\n }\n if (n.removed === true) {\n return { kind: \"occupant\", stableKey: n.stableKey, removed: true };\n }\n const occ = n.occupant;\n if (\n !isRecord(occ) ||\n (occ.kind !== \"human\" && occ.kind !== \"agent\" && occ.kind !== \"mcp\")\n ) {\n throw new Error(\"getPlayerChainNode: invalid occupant payload\");\n }\n const occupant =\n occ.kind === \"human\"\n ? parseHumanOccupantRow(occ)\n : occ.kind === \"agent\"\n ? parseAgentOccupantRow(occ)\n : parseMcpOccupantRow(occ);\n return {\n kind: \"occupant\",\n stableKey: n.stableKey,\n removed: false,\n occupant,\n };\n}\n\nexport function mergeSnapshotWithPlayerChainNode(\n snapshot: AgentPlaySnapshot,\n node: PlayerChainNodeResponse\n): AgentPlaySnapshot {\n if (node.kind === \"genesis\") {\n return snapshot;\n }\n if (node.kind === \"header\") {\n return {\n ...snapshot,\n sid: node.sid,\n worldMap: {\n ...snapshot.worldMap,\n bounds: node.bounds,\n },\n };\n }\n if (node.removed === true) {\n return {\n ...snapshot,\n worldMap: {\n ...snapshot.worldMap,\n occupants: snapshot.worldMap.occupants.filter(\n (o) => stableOccupantSortKey(o) !== node.stableKey\n ),\n },\n };\n }\n if (node.removed !== false) {\n throw new Error(\"mergeSnapshotWithPlayerChainNode: invalid occupant node\");\n }\n const occ = node.occupant;\n const key = stableOccupantSortKey(occ);\n const occupants = snapshot.worldMap.occupants.filter(\n (o) => stableOccupantSortKey(o) !== key\n );\n return {\n ...snapshot,\n worldMap: {\n ...snapshot.worldMap,\n occupants: [...occupants, occ],\n },\n };\n}\n"],"mappings":"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","names":[]}
|