@agent-play/sdk 3.2.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.
@@ -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<{
@@ -341,4 +379,4 @@ declare function mergeSnapshotWithPlayerChainNode(snapshot: AgentPlaySnapshot, n
341
379
  declare const PLAYER_CHAIN_GENESIS_STABLE_KEY: "__genesis__";
342
380
  declare const PLAYER_CHAIN_HEADER_STABLE_KEY: "__header__";
343
381
 
344
- export { type AgentPlaySnapshot as A, clampWorldPosition as B, expandBoundsToMinimumPlayArea as C, type DestinationJourneyStep as D, mergeSnapshotWithPlayerChainNode as E, parsePlayerChainFanoutNotify as F, parsePlayerChainFanoutNotifyFromSsePayload as G, parsePlayerChainNodeRpcBody as H, sortNodeRefsForSerializedFetch as I, type Journey as J, type LangChainAgentRegistration as L, MINIMUM_PLAY_WORLD_BOUNDS as M, type OriginJourneyStep as O, type PlayerChainNodeResponse as P, type RegisteredPlayer as R, type StructureJourneyStep as S, type WorldInteractionRole as W, type YieldEventInfo as Y, type ZoneEventInfo as Z, type AddAgentInput as a, type AddPlayerInput as b, type RecordInteractionInput as c, type AgentPlayWorldMap as d, type AgentPlayWorldMapAgentOccupant as e, type AgentPlayWorldMapBounds as f, type AgentPlayWorldMapMcpOccupant as g, type AssistToolFieldType as h, type AssistToolParameterSpec as i, type AssistToolSpec as j, type JourneyStep as k, PLAYER_CHAIN_GENESIS_STABLE_KEY as l, PLAYER_CHAIN_HEADER_STABLE_KEY as m, type PlatformAgentInformation as n, type PlayAgentInformation as o, type PlayerChainFanoutNotify as p, type PlayerChainGenesisNode as q, type PlayerChainHeaderNode as r, type PlayerChainNotifyNodeRef as s, type PlayerChainOccupantPresentNode as t, type PlayerChainOccupantRemovedNode as u, type PositionedStep as v, type RegisteredAgentSummary as w, type WorldBounds as x, type WorldJourneyUpdate as y, boundsContain as z };
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, M as MINIMUM_PLAY_WORLD_BOUNDS, l as PLAYER_CHAIN_GENESIS_STABLE_KEY, m as PLAYER_CHAIN_HEADER_STABLE_KEY, x as WorldBounds, z as boundsContain, B as clampWorldPosition, C as expandBoundsToMinimumPlayArea, E as mergeSnapshotWithPlayerChainNode, F as parsePlayerChainFanoutNotify, G as parsePlayerChainFanoutNotifyFromSsePayload, H as parsePlayerChainNodeRpcBody, I as sortNodeRefsForSerializedFetch } from './browser-DzS5wcaZ.js';
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
@@ -10,7 +10,7 @@ import {
10
10
  parsePlayerChainFanoutNotifyFromSsePayload,
11
11
  parsePlayerChainNodeRpcBody,
12
12
  sortNodeRefsForSerializedFetch
13
- } from "./chunk-VI2MTCE7.js";
13
+ } from "./chunk-U2M7HNYN.js";
14
14
  export {
15
15
  MINIMUM_PLAY_WORLD_BOUNDS,
16
16
  PLAYER_CHAIN_GENESIS_STABLE_KEY,
@@ -70,10 +70,37 @@ function parseAgentOccupantRow(raw) {
70
70
  } else if (typeof raw.agentType === "string") {
71
71
  platform = raw.agentType;
72
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 };
73
91
  if (platform !== void 0) {
74
- return { ...base, platform };
92
+ out.platform = platform;
75
93
  }
76
- return base;
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;
77
104
  }
78
105
  function parseMcpOccupantRow(raw) {
79
106
  if (typeof raw.id !== "string" || typeof raw.name !== "string") {
@@ -273,4 +300,4 @@ export {
273
300
  parsePlayerChainNodeRpcBody,
274
301
  mergeSnapshotWithPlayerChainNode
275
302
  };
276
- //# sourceMappingURL=chunk-VI2MTCE7.js.map
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, R as RegisteredPlayer, b as AddPlayerInput, c as RecordInteractionInput, J as Journey } from './browser-DzS5wcaZ.js';
2
- export { d as AgentPlayWorldMap, e as AgentPlayWorldMapAgentOccupant, f as AgentPlayWorldMapBounds, g as AgentPlayWorldMapMcpOccupant, h as AssistToolFieldType, i as AssistToolParameterSpec, j as AssistToolSpec, D as DestinationJourneyStep, k as JourneyStep, M as MINIMUM_PLAY_WORLD_BOUNDS, O as OriginJourneyStep, l as PLAYER_CHAIN_GENESIS_STABLE_KEY, m as PLAYER_CHAIN_HEADER_STABLE_KEY, n as PlatformAgentInformation, o as PlayAgentInformation, p as PlayerChainFanoutNotify, q as PlayerChainGenesisNode, r as PlayerChainHeaderNode, s as PlayerChainNotifyNodeRef, t as PlayerChainOccupantPresentNode, u as PlayerChainOccupantRemovedNode, v as PositionedStep, w as RegisteredAgentSummary, S as StructureJourneyStep, x as WorldBounds, y as WorldJourneyUpdate, Y as YieldEventInfo, Z as ZoneEventInfo, z as boundsContain, B as clampWorldPosition, C as expandBoundsToMinimumPlayArea, E as mergeSnapshotWithPlayerChainNode, F as parsePlayerChainFanoutNotify, G as parsePlayerChainFanoutNotifyFromSsePayload, H as parsePlayerChainNodeRpcBody, I as sortNodeRefsForSerializedFetch } from './browser-DzS5wcaZ.js';
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 **`executeTool`** and posting **`intercomResponse`** (**`completed`** / **`failed`**).
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
@@ -13,7 +13,7 @@ import {
13
13
  parsePlayerChainFanoutNotifyFromSsePayload,
14
14
  parsePlayerChainNodeRpcBody,
15
15
  sortNodeRefsForSerializedFetch
16
- } from "./chunk-VI2MTCE7.js";
16
+ } from "./chunk-U2M7HNYN.js";
17
17
 
18
18
  // src/world-events.ts
19
19
  var SESSION_CONNECTED_EVENT = "session:connected";
@@ -249,6 +249,69 @@ function intercomResultRecordFromLangChainInvokeOutput(output) {
249
249
  return { mode: "chat", output: o };
250
250
  }
251
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
+
252
315
  // src/lib/remote-play-world.ts
253
316
  var PLAYER_CONNECTION_HEARTBEAT_MAX_ATTEMPTS = 10;
254
317
  var PLAYER_CONNECTION_HEARTBEAT_RETRY_DELAY_MS = 1e4;
@@ -369,6 +432,30 @@ function parseRegisteredAgentSummary(raw) {
369
432
  flagged: raw.flagged
370
433
  };
371
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
+ }
372
459
  function formatInvalidHoldSecondsError() {
373
460
  return [
374
461
  "RemotePlayWorld.hold().for(seconds): seconds must be a finite number.",
@@ -376,6 +463,17 @@ function formatInvalidHoldSecondsError() {
376
463
  " Example: await world.hold().for(3600)"
377
464
  ].join("\n");
378
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
+ }
379
477
  function getSseEventName(msg) {
380
478
  if (typeof msg !== "object" || msg === null) {
381
479
  return void 0;
@@ -420,6 +518,7 @@ var RemotePlayWorld = class {
420
518
  closed = false;
421
519
  closeListeners = /* @__PURE__ */ new Set();
422
520
  playerConnectionInfo = /* @__PURE__ */ new Map();
521
+ audioInitOptions = null;
423
522
  constructor(options = {}) {
424
523
  const creds = loadAgentPlayCredentialsFileFromPathSync(
425
524
  resolveAgentPlayCredentialsPath()
@@ -601,6 +700,16 @@ var RemotePlayWorld = class {
601
700
  u.search = "";
602
701
  return u.toString();
603
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
+ }
604
713
  async getWorldSnapshot() {
605
714
  const res = await fetch(`${this.apiBase}/api/agent-play/sdk/rpc`, {
606
715
  method: "POST",
@@ -744,6 +853,9 @@ var RemotePlayWorld = class {
744
853
  }
745
854
  /**
746
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`.
747
859
  */
748
860
  async addAgent(input) {
749
861
  const sid = this.getSessionId();
@@ -764,19 +876,48 @@ var RemotePlayWorld = class {
764
876
  const url = `${this.apiBase}/api/agent-play/players?sid=${encodeURIComponent(sid)}`;
765
877
  const connectionId = randomUUID();
766
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);
767
917
  const res = await fetch(url, {
768
918
  method: "POST",
769
919
  headers: this.jsonHeaders(),
770
- body: JSON.stringify({
771
- name: input.name,
772
- type: input.type,
773
- agent: input.agent,
774
- mainNodeId: effectiveMainNodeId,
775
- password: this.password,
776
- agentId: input.nodeId,
777
- connectionId,
778
- leaseTtlSeconds
779
- })
920
+ body: requestBody
780
921
  });
781
922
  const bodyText = await res.text();
782
923
  if (!res.ok) {
@@ -826,6 +967,9 @@ var RemotePlayWorld = class {
826
967
  timer
827
968
  });
828
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);
829
973
  return {
830
974
  id: playerId,
831
975
  name: input.name,
@@ -834,6 +978,8 @@ var RemotePlayWorld = class {
834
978
  updatedAt: now,
835
979
  previewUrl,
836
980
  registeredAgent,
981
+ enableP2a,
982
+ ...realtimeWebrtc !== void 0 ? { realtimeWebrtc } : {},
837
983
  connectionId: bodyConnectionId,
838
984
  leaseTtlSeconds: bodyLeaseTtlSeconds
839
985
  };
@@ -848,6 +994,9 @@ var RemotePlayWorld = class {
848
994
  agent: input.agent,
849
995
  nodeId: input.agentId
850
996
  };
997
+ if (input.enableP2a !== void 0) {
998
+ payload.enableP2a = input.enableP2a;
999
+ }
851
1000
  if (input.version !== void 0) {
852
1001
  payload.version = input.version;
853
1002
  }
@@ -902,7 +1051,8 @@ var RemotePlayWorld = class {
902
1051
  }
903
1052
  }
904
1053
  /**
905
- * 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`**).
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`.
906
1056
  * Uses a **single** SSE connection when **`playerIds`** lists multiple automation agents (recommended for several agents in one process).
907
1057
  * Not invoked automatically by {@link RemotePlayWorld.addAgent}.
908
1058
  */
@@ -988,21 +1138,20 @@ var RemotePlayWorld = class {
988
1138
  kind: cmd.kind,
989
1139
  toolName: cmd.toolName
990
1140
  });
991
- const toolName = cmd.kind === "chat" ? "chat_tool" : cmd.toolName ?? "";
992
- const args = cmd.kind === "chat" ? { text: cmd.text ?? "" } : cmd.args ?? {};
993
- this.logTransport("intercom:executeTool", {
994
- requestId: cmd.requestId,
995
- toolName,
996
- argsPreview: this.truncateForLog(JSON.stringify(args))
997
- });
998
1141
  try {
999
- this.logTransport("intercom:executeTool:started", {
1000
- requestId: cmd.requestId,
1001
- toolName,
1002
- argsPreview: this.truncateForLog(JSON.stringify(args))
1003
- });
1004
1142
  let result;
1005
- if (cmd.kind === "chat" && chatAgentsByPlayerId !== void 0 && chatAgentsByPlayerId.has(cmd.toPlayerId)) {
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)) {
1006
1155
  const lc = chatAgentsByPlayerId.get(cmd.toPlayerId);
1007
1156
  if (lc === void 0) {
1008
1157
  throw new Error("intercom: chatAgentsByPlayerId entry missing");
@@ -1020,17 +1169,36 @@ var RemotePlayWorld = class {
1020
1169
  requestId: cmd.requestId,
1021
1170
  resultPreview: this.truncateForLog(JSON.stringify(result))
1022
1171
  });
1023
- } 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
+ });
1024
1185
  result = await Promise.resolve(
1025
1186
  executeTool({ toolName, args })
1026
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;
1027
1201
  }
1028
- this.logTransport("intercom:executeTool:completed", {
1029
- requestId: cmd.requestId,
1030
- toolName,
1031
- argsPreview: this.truncateForLog(JSON.stringify(args)),
1032
- resultPreview: this.truncateForLog(JSON.stringify(result))
1033
- });
1034
1202
  await this.sendIntercomResponse({
1035
1203
  requestId: cmd.requestId,
1036
1204
  mainNodeId: cmd.mainNodeId,
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 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":"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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":"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","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.2.0",
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": "file:../intercom",
43
+ "@agent-play/intercom": "^3.3.0",
44
44
  "@langchain/core": "^1.1.35",
45
- "@agent-play/node-tools": "file:../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/** 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 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":[]}