@agent-play/sdk 3.0.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/world-events.ts","../src/lib/world-bounds.ts","../src/lib/agent-play-debug.ts","../src/platforms/langchain.ts","../src/lib/parse-occupant-row.ts","../src/lib/world-chain-keys.ts","../src/lib/player-chain-merge.ts","../src/lib/remote-play-world.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 */\nimport type { WorldInteractionRole } from \"./public-types.js\";\n\n/** Fired when `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 * Axis-aligned rectangle in world coordinates (grid units). Used by the server to clamp paths\n * and by the watch UI to clamp joystick-driven movement.\n *\n * @remarks **Consumers:** {@link clampWorldPosition}, {@link boundsContain}; server `PlayWorld` and\n * play-ui canvas both import these helpers from `@agent-play/sdk`.\n */\nexport type WorldBounds = {\n /** Inclusive minimum X. */\n minX: number;\n /** Inclusive minimum Y. */\n minY: number;\n /** Inclusive maximum X. */\n maxX: number;\n /** Inclusive maximum Y. */\n maxY: number;\n};\n\n/**\n * Clamps a point to lie inside `bounds` along both axes.\n *\n * @param p - Position with `x` and `y` in world units.\n * @param bounds - Valid rectangle (`min` ≤ `max` per axis).\n * @returns Same point if inside, otherwise clamped to the nearest edge.\n *\n * @remarks **Callers:** server `PlayWorld` path enrichment; play-ui joystick and preview. **Callees:** `Math.min/Math.max`.\n */\nexport function clampWorldPosition(\n p: { x: number; y: number },\n bounds: WorldBounds\n): { x: number; y: number } {\n return {\n x: Math.min(Math.max(p.x, bounds.minX), bounds.maxX),\n y: Math.min(Math.max(p.y, bounds.minY), bounds.maxY),\n };\n}\n\n/**\n * @returns Whether `p` lies inside or on the border of `bounds`.\n *\n * @remarks **Callers:** optional UI checks. **Callees:** none.\n */\nexport function boundsContain(\n bounds: WorldBounds,\n p: { x: number; y: number }\n): boolean {\n return (\n p.x >= bounds.minX &&\n p.x <= bounds.maxX &&\n p.y >= bounds.minY &&\n p.y <= bounds.maxY\n );\n}\n","/**\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.debug - `true` / `false` to force; omit 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 {@link safeSerialize}. */\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 {@link safeSerialize}.\n *\n * @remarks **Callers:** {@link langchainRegistration} and other SDK modules. **Callees:** {@link isAgentPlayDebugEnabled}, {@link safeSerialize}.\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 import(\"../public-types.js\").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 { AssistToolSpec, LangChainAgentRegistration } 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\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] = { field: key };\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 `addPlayer`.\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.addPlayer`. **Callees:** {@link extractToolsArray},\n * {@link formatMissingAgentToolsError}, {@link formatMissingChatToolError}, {@link describeTool}, {@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 AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapMcpOccupant,\n} from \"../public-types.js\";\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 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","export const PLAYER_CHAIN_GENESIS_STABLE_KEY = \"__genesis__\" as const;\nexport const PLAYER_CHAIN_HEADER_STABLE_KEY = \"__header__\" as const;\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 AgentPlayWorldMapAgentOccupant,\n AgentPlayWorldMapMcpOccupant,\n PlayerChainFanoutNotify,\n PlayerChainNotifyNodeRef,\n PlayerChainNodeResponse,\n} from \"../public-types.js\";\nimport {\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: AgentPlayWorldMapAgentOccupant | AgentPlayWorldMapMcpOccupant\n): string {\n if (occ.kind === \"agent\") {\n return `agent:${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 (!isRecord(occ) || (occ.kind !== \"agent\" && occ.kind !== \"mcp\")) {\n throw new Error(\"getPlayerChainNode: invalid occupant payload\");\n }\n const occupant =\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","import type {\n AddPlayerInput,\n AgentPlaySnapshot,\n AgentPlayWorldMap,\n AgentPlayWorldMapBounds,\n Journey,\n RecordInteractionInput,\n RegisteredAgentSummary,\n RegisteredPlayer,\n PlayerChainNodeResponse,\n} from \"../public-types.js\";\nimport {\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\";\n\nexport type RemotePlayWorldOptions = {\n baseUrl: string;\n apiKey: string;\n authToken?: string;\n};\n\nfunction formatMissingApiKeyError(): string {\n return [\n \"RemotePlayWorld: options.apiKey is required.\",\n \"\",\n \" Register an agent with `agent-play create` (after `agent-play login`) and use the printed API key.\",\n \" Pass it here so addPlayer can authenticate against the server repository when Redis is enabled.\",\n \" If the server has no agent repository (local dev), still pass a non-empty placeholder string.\",\n ].join(\"\\n\");\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 (!isRecord(row) || (row.kind !== \"agent\" && row.kind !== \"mcp\")) {\n throw new Error(\"getWorldSnapshot: each occupant must have kind agent or mcp\");\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 === \"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(\"addPlayer: registeredAgent missing\");\n }\n if (typeof raw.agentId !== \"string\" || typeof raw.name !== \"string\") {\n throw new Error(\"addPlayer: registeredAgent.agentId and name required\");\n }\n if (!Array.isArray(raw.toolNames)) {\n throw new Error(\"addPlayer: 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(\"addPlayer: 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(\"addPlayer: 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\n/**\n * HTTP client for the Agent Play web UI: session, snapshot RPC, mutating RPC with `sid`, and optional SSE subscription.\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 */\nexport class RemotePlayWorld {\n private readonly apiBase: string;\n private readonly apiKey: string;\n private readonly authToken: string | undefined;\n private sid: string | null = null;\n private closed = false;\n private readonly closeListeners = new Set<() => void>();\n\n constructor(options: RemotePlayWorldOptions) {\n if (typeof options.apiKey !== \"string\" || options.apiKey.trim().length === 0) {\n throw new Error(formatMissingApiKeyError());\n }\n this.apiBase = normalizeBaseUrl(options.baseUrl);\n this.apiKey = options.apiKey.trim();\n this.authToken = options.authToken;\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 if (this.authToken === undefined) return {};\n return { Authorization: `Bearer ${this.authToken}` };\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 async connect(): Promise<void> {\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 }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n this.closed = true;\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 }): { 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 source = createEventSource({\n url: `${this.apiBase}/api/agent-play/events?sid=${encodeURIComponent(\n this.getSessionId()\n )}`,\n fetch: (input, init) => this.mergeAuthFetch(input, init),\n });\n closeSource = () => {\n source.close();\n };\n for await (const msg of source) {\n if (typeof msg.data !== \"string\") {\n continue;\n }\n let data: unknown;\n try {\n data = JSON.parse(msg.data) as unknown;\n } catch {\n continue;\n }\n const notify = parsePlayerChainFanoutNotifyFromSsePayload(data);\n if (notify === undefined || notify.nodes.length === 0) {\n continue;\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 callbacks.onError?.(\n e instanceof Error ? e : new Error(String(e))\n );\n }\n })();\n return {\n close: () => {\n closeSource?.();\n void task;\n },\n };\n }\n\n async addPlayer(input: AddPlayerInput): Promise<RegisteredPlayer> {\n const sid = this.getSessionId();\n const url = `${this.apiBase}/api/agent-play/players?sid=${encodeURIComponent(sid)}`;\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 apiKey: this.apiKey,\n agentId: input.agentId,\n }),\n });\n const bodyText = await res.text();\n if (!res.ok) {\n throw new Error(`addPlayer: ${res.status} ${bodyText}`);\n }\n let body: unknown;\n try {\n body = JSON.parse(bodyText) as unknown;\n } catch {\n throw new Error(\"addPlayer: invalid JSON\");\n }\n if (!isRecord(body)) {\n throw new Error(\"addPlayer: 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(\"addPlayer: missing playerId or previewUrl\");\n }\n const registeredAgent = parseRegisteredAgentSummary(body.registeredAgent);\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 };\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 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"],"mappings":";AASO,IAAM,qBAAqB;AAG3B,IAAM,0BAA0B;AAGhC,IAAM,2BAA2B;AAGjC,IAAM,sBAAsB;;;ACS5B,SAAS,mBACd,GACA,QAC0B;AAC1B,SAAO;AAAA,IACL,GAAG,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,OAAO,IAAI,GAAG,OAAO,IAAI;AAAA,IACnD,GAAG,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,OAAO,IAAI,GAAG,OAAO,IAAI;AAAA,EACrD;AACF;AAOO,SAAS,cACd,QACA,GACS;AACT,SACE,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO;AAElB;;;ACtCA,IAAI;AASG,SAAS,wBAAwB,MAA4B;AAClE,oBAAkB,KAAK,SAAS;AAClC;AAOO,SAAS,sBAA4B;AAC1C,oBAAkB;AACpB;AAOO,SAAS,0BAAmC;AACjD,MAAI,oBAAoB,MAAO,QAAO;AACtC,MAAI,oBAAoB,KAAM,QAAO;AACrC,SAAO,QAAQ,IAAI,qBAAqB;AAC1C;AAGA,IAAM,kBAAkB;AAQxB,SAAS,cAAc,QAAyB;AAC9C,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI;AACF,UAAM,OAAO,oBAAI,QAAgB;AACjC,UAAM,OAAO,KAAK,UAAU,QAAQ,CAAC,IAAI,MAAe;AACtD,UAAI,OAAO,MAAM,YAAY,MAAM,MAAM;AACvC,YAAI,KAAK,IAAI,CAAC,EAAG,QAAO;AACxB,aAAK,IAAI,CAAC;AAAA,MACZ;AACA,UAAI,OAAO,MAAM,SAAU,QAAO,OAAO,CAAC;AAC1C,aAAO;AAAA,IACT,CAAC;AACD,QAAI,OAAO,SAAS,SAAU,QAAO,OAAO,MAAM;AAClD,WAAO,KAAK,SAAS,kBACjB,GAAG,KAAK,MAAM,GAAG,eAAe,CAAC,WACjC;AAAA,EACN,QAAQ;AACN,WAAO,OAAO,MAAM;AAAA,EACtB;AACF;AAWO,SAAS,eACd,OACA,SACA,QACM;AACN,MAAI,CAAC,wBAAwB,EAAG;AAChC,QAAM,OACJ,WAAW,SAAY,KAAK,IAAI,cAAc,MAAM,CAAC;AACvD,UAAQ,MAAM,eAAe,KAAK,KAAK,OAAO,GAAG,IAAI,EAAE;AACzD;;;ACpFA,IAAM,YAAY;AAOlB,SAAS,+BAAuC;AAC9C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAOA,SAAS,6BAAqC;AAC5C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAOA,SAAS,qBAAqB,QAA0C;AACtE,MAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,WAAO,CAAC;AAAA,EACV;AACA,QAAM,IAAI;AAGV,MAAI,OAAO,EAAE,MAAM,UAAU,YAAY;AACvC,WAAO,EAAE,OAAO,6EAA6E;AAAA,EAC/F;AACA,QAAM,QAAQ,EAAE,KAAK,MAAM;AAC3B,QAAM,MAA+B,CAAC;AACtC,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,GAAG,IAAI,EAAE,OAAO,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAOA,SAAS,aAAa,GAIH;AACjB,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IACR,aACE,OAAO,EAAE,gBAAgB,YAAY,EAAE,YAAY,SAAS,IACxD,EAAE,cACF,EAAE;AAAA,IACR,YAAY,qBAAqB,EAAE,MAAM;AAAA,EAC3C;AACF;AASA,SAAS,kBAAkB,OAAkC;AAC3D,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAIV,MAAI,MAAM,QAAQ,EAAE,KAAK,GAAG;AAC1B,WAAO,EAAE;AAAA,EACX;AACA,MACE,EAAE,YAAY,UACd,OAAO,EAAE,YAAY,YACrB,EAAE,YAAY,QACd,WAAW,EAAE,WACb,MAAM,QAAS,EAAE,QAA+B,KAAK,GACrD;AACA,WAAQ,EAAE,QAAiC;AAAA,EAC7C;AACA,SAAO;AACT;AAYO,SAAS,sBACd,OAC4B;AAC5B,QAAM,WAAW,kBAAkB,KAAK;AACxC,MAAI,aAAa,MAAM;AACrB,UAAM,IAAI,MAAM,6BAA6B,CAAC;AAAA,EAChD;AACA,QAAM,QACJ;AACF,QAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AACrC,MAAI,CAAC,MAAM,SAAS,SAAS,GAAG;AAC9B,UAAM,IAAI,MAAM,2BAA2B,CAAC;AAAA,EAC9C;AACA,QAAM,cAAc,MACjB,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,SAAS,CAAC,EAC1C,IAAI,CAAC,MAAM,aAAa,CAAC,CAAC;AAC7B,iBAAe,aAAa,yBAAyB;AAAA,IACnD,WAAW,MAAM;AAAA,IACjB,aAAa,YAAY;AAAA,EAC3B,CAAC;AACD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX;AAAA,EACF;AACF;;;AClJO,SAAS,sBACd,KACgC;AAChC,MAAI,OAAO,IAAI,YAAY,YAAY,OAAO,IAAI,SAAS,UAAU;AACnE,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,MAAI,OAAO,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,UAAU;AAC1D,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AACA,QAAM,OAAuC;AAAA,IAC3C,MAAM;AAAA,IACN,SAAS,IAAI;AAAA,IACb,MAAM,IAAI;AAAA,IACV,GAAG,IAAI;AAAA,IACP,GAAG,IAAI;AAAA,EACT;AACA,MAAI;AACJ,MAAI,OAAO,IAAI,aAAa,UAAU;AACpC,eAAW,IAAI;AAAA,EACjB,WAAW,OAAO,IAAI,cAAc,UAAU;AAC5C,eAAW,IAAI;AAAA,EACjB;AACA,MAAI,aAAa,QAAW;AAC1B,WAAO,EAAE,GAAG,MAAM,SAAS;AAAA,EAC7B;AACA,SAAO;AACT;AAEO,SAAS,oBACd,KAC8B;AAC9B,MAAI,OAAO,IAAI,OAAO,YAAY,OAAO,IAAI,SAAS,UAAU;AAC9D,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AACA,MAAI,OAAO,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,UAAU;AAC1D,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,QAAM,OAAqC;AAAA,IACzC,MAAM;AAAA,IACN,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,GAAG,IAAI;AAAA,IACP,GAAG,IAAI;AAAA,EACT;AACA,MAAI,OAAO,IAAI,QAAQ,UAAU;AAC/B,WAAO,EAAE,GAAG,MAAM,KAAK,IAAI,IAAI;AAAA,EACjC;AACA,SAAO;AACT;;;ACrDO,IAAM,kCAAkC;AACxC,IAAM,iCAAiC;;;ACoB9C,SAAS,SAAS,GAA0C;AAC1D,SAAO,OAAO,MAAM,YAAY,MAAM;AACxC;AAEA,SAAS,sBACP,KACQ;AACR,MAAI,IAAI,SAAS,SAAS;AACxB,WAAO,SAAS,IAAI,OAAO;AAAA,EAC7B;AACA,SAAO,OAAO,IAAI,EAAE;AACtB;AAEO,SAAS,+BACd,OAC4B;AAC5B,QAAM,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI;AACtD,QAAM,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI;AACnD,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAChD,OAAK,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAC7C,SAAO,CAAC,GAAG,SAAS,GAAG,IAAI;AAC7B;AAEO,SAAS,6BACd,KACqC;AACrC,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,WAAW,GAAG;AACnE,WAAO;AAAA,EACT;AACA,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,GAAG;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,QAAoC,CAAC;AAC3C,aAAW,OAAO,IAAI,OAAO;AAC3B,QAAI,CAAC,SAAS,GAAG,GAAG;AAClB,aAAO;AAAA,IACT;AACA,QAAI,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,WAAW,GAAG;AACnE,aAAO;AAAA,IACT;AACA,QAAI,OAAO,IAAI,cAAc,YAAY,CAAC,OAAO,SAAS,IAAI,SAAS,GAAG;AACxE,aAAO;AAAA,IACT;AACA,UAAM,MAAgC;AAAA,MACpC,WAAW,IAAI;AAAA,MACf,WAAW,IAAI;AAAA,IACjB;AACA,QAAI,IAAI,YAAY,MAAM;AACxB,UAAI,UAAU;AAAA,IAChB;AACA,QAAI,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,SAAS,GAAG;AACjE,UAAI,YAAY,IAAI;AAAA,IACtB;AACA,UAAM,KAAK,GAAG;AAAA,EAChB;AACA,SAAO,EAAE,WAAW,IAAI,WAAW,MAAM;AAC3C;AAEO,SAAS,2CACd,SACqC;AACrC,MAAI,CAAC,SAAS,OAAO,GAAG;AACtB,WAAO;AAAA,EACT;AACA,SAAO,6BAA6B,QAAQ,iBAAiB;AAC/D;AAEO,SAAS,4BAA4B,MAAwC;AAClF,MAAI,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,GAAG;AAC3C,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,QAAM,IAAI,KAAK;AACf,MAAI,EAAE,SAAS,WAAW;AACxB,QACE,EAAE,cAAc,mCAChB,OAAO,EAAE,SAAS,UAClB;AACA,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AACA,MAAI,EAAE,SAAS,UAAU;AACvB,QACE,EAAE,cAAc,kCAChB,OAAO,EAAE,QAAQ,UACjB;AACA,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,UAAM,IAAI,EAAE;AACZ,QAAI,CAAC,SAAS,CAAC,GAAG;AAChB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,UAAM,EAAE,MAAM,MAAM,MAAM,KAAK,IAAI;AACnC,QACE,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS,UAChB;AACA,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,KAAK,EAAE;AAAA,MACP,QAAQ,EAAE,MAAM,MAAM,MAAM,KAAK;AAAA,IACnC;AAAA,EACF;AACA,MAAI,EAAE,SAAS,YAAY;AACzB,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AACA,MAAI,OAAO,EAAE,cAAc,YAAY,EAAE,UAAU,WAAW,GAAG;AAC/D,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,MAAI,EAAE,YAAY,MAAM;AACtB,WAAO,EAAE,MAAM,YAAY,WAAW,EAAE,WAAW,SAAS,KAAK;AAAA,EACnE;AACA,QAAM,MAAM,EAAE;AACd,MAAI,CAAC,SAAS,GAAG,KAAM,IAAI,SAAS,WAAW,IAAI,SAAS,OAAQ;AAClE,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,QAAM,WACJ,IAAI,SAAS,UACT,sBAAsB,GAAG,IACzB,oBAAoB,GAAG;AAC7B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,EAAE;AAAA,IACb,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,iCACd,UACA,MACmB;AACnB,MAAI,KAAK,SAAS,WAAW;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,KAAK,KAAK;AAAA,MACV,UAAU;AAAA,QACR,GAAG,SAAS;AAAA,QACZ,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,YAAY,MAAM;AACzB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU;AAAA,QACR,GAAG,SAAS;AAAA,QACZ,WAAW,SAAS,SAAS,UAAU;AAAA,UACrC,CAAC,MAAM,sBAAsB,CAAC,MAAM,KAAK;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,YAAY,OAAO;AAC1B,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,MAAM,KAAK;AACjB,QAAM,MAAM,sBAAsB,GAAG;AACrC,QAAM,YAAY,SAAS,SAAS,UAAU;AAAA,IAC5C,CAAC,MAAM,sBAAsB,CAAC,MAAM;AAAA,EACtC;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,SAAS;AAAA,MACZ,WAAW,CAAC,GAAG,WAAW,GAAG;AAAA,IAC/B;AAAA,EACF;AACF;;;AChLA,SAAS,2BAAmC;AAC1C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,iBAAiB,KAAqB;AAC7C,SAAO,IAAI,QAAQ,OAAO,EAAE;AAC9B;AAEA,SAASA,UAAS,GAA0C;AAC1D,SAAO,OAAO,MAAM,YAAY,MAAM;AACxC;AAEA,SAAS,YAAY,KAAuC;AAC1D,MAAI,CAACA,UAAS,GAAG,GAAG;AAClB,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,QAAM,EAAE,MAAM,MAAM,MAAM,KAAK,IAAI;AACnC,MACE,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS,UAChB;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK;AAClC;AAEA,SAAS,cAAc,KAAiC;AACtD,MAAI,CAACA,UAAS,GAAG,GAAG;AAClB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,QAAM,SAAS,YAAY,IAAI,MAAM;AACrC,QAAM,MAAM,IAAI;AAChB,MAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;AACvB,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,QAAM,YAA4C,CAAC;AACnD,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,OAAO,KAAK;AACrB,QAAI,CAACA,UAAS,GAAG,KAAM,IAAI,SAAS,WAAW,IAAI,SAAS,OAAQ;AAClE,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AACA,UAAM,KACJ,OAAO,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,WAC1C,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,KACjB;AACN,QAAI,GAAG,WAAW,GAAG;AACnB,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,QAAI,UAAU,IAAI,EAAE,GAAG;AACrB,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACpE;AACA,cAAU,IAAI,EAAE;AAChB,QAAI,IAAI,SAAS,SAAS;AACxB,gBAAU,KAAK,sBAAsB,GAAG,CAAC;AAAA,IAC3C,OAAO;AACL,gBAAU,KAAK,oBAAoB,GAAG,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,UAAU;AAC7B;AAEA,SAAS,uBAAuB,UAAsC;AACpE,MAAI,CAACA,UAAS,QAAQ,KAAK,OAAO,SAAS,QAAQ,UAAU;AAC3D,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,QAAM,WAAW,cAAc,SAAS,QAAQ;AAChD,QAAM,MAAyB,EAAE,KAAK,SAAS,KAAK,SAAS;AAC7D,MAAI,gBAAgB,YAAY,MAAM,QAAQ,SAAS,UAAU,GAAG;AAClE,UAAM,UAAwD,CAAC;AAC/D,eAAW,KAAK,SAAS,YAAY;AACnC,UAAI,CAACA,UAAS,CAAC,KAAK,OAAO,EAAE,OAAO,YAAY,OAAO,EAAE,SAAS,UAAU;AAC1E;AAAA,MACF;AACA,YAAM,MAAkD;AAAA,QACtD,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,MACV;AACA,UAAI,OAAO,EAAE,QAAQ,SAAU,KAAI,MAAM,EAAE;AAC3C,cAAQ,KAAK,GAAG;AAAA,IAClB;AACA,QAAI,QAAQ,SAAS,EAAG,KAAI,aAAa;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,4BAA4B,KAAsC;AACzE,MAAI,CAACA,UAAS,GAAG,GAAG;AAClB,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,MAAI,OAAO,IAAI,YAAY,YAAY,OAAO,IAAI,SAAS,UAAU;AACnE,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,MAAI,CAAC,MAAM,QAAQ,IAAI,SAAS,GAAG;AACjC,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,QAAM,YAAsB,CAAC;AAC7B,aAAW,KAAK,IAAI,WAAW;AAC7B,QAAI,OAAO,MAAM,UAAU;AACzB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AACA,cAAU,KAAK,CAAC;AAAA,EAClB;AACA,MACE,OAAO,IAAI,cAAc,YACzB,OAAO,IAAI,eAAe,YAC1B,OAAO,IAAI,YAAY,WACvB;AACA,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AAAA,IACL,SAAS,IAAI;AAAA,IACb,MAAM,IAAI;AAAA,IACV;AAAA,IACA,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,SAAS,IAAI;AAAA,EACf;AACF;AAEA,SAAS,gCAAwC;AAC/C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAWO,IAAM,kBAAN,MAAsB;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACT,MAAqB;AAAA,EACrB,SAAS;AAAA,EACA,iBAAiB,oBAAI,IAAgB;AAAA,EAEtD,YAAY,SAAiC;AAC3C,QAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,OAAO,KAAK,EAAE,WAAW,GAAG;AAC5E,YAAM,IAAI,MAAM,yBAAyB,CAAC;AAAA,IAC5C;AACA,SAAK,UAAU,iBAAiB,QAAQ,OAAO;AAC/C,SAAK,SAAS,QAAQ,OAAO,KAAK;AAClC,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA,EAEA,QAAQ,SAAiC;AACvC,SAAK,eAAe,IAAI,OAAO;AAC/B,WAAO,MAAM;AACX,WAAK,eAAe,OAAO,OAAO;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,OAA4B;AAC1B,WAAO;AAAA,MACL,KAAK,OAAO,YAAoB;AAC9B,YAAI,OAAO,YAAY,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG;AAC5D,gBAAM,IAAI,MAAM,8BAA8B,CAAC;AAAA,QACjD;AACA,cAAM,KAAK,KAAK,IAAI,GAAG,OAAO,IAAI;AAClC,cAAM,IAAI,QAAc,CAAC,YAAY;AACnC,qBAAW,SAAS,EAAE;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAsC;AAC5C,QAAI,KAAK,cAAc,OAAW,QAAO,CAAC;AAC1C,WAAO,EAAE,eAAe,UAAU,KAAK,SAAS,GAAG;AAAA,EACrD;AAAA,EAEQ,cAAsC;AAC5C,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,GAAG,KAAK,YAAY;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,eACN,OACA,MACmB;AACnB,UAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,UAAM,OAAO,KAAK,YAAY;AAC9B,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,GAAG;AACzC,cAAQ,IAAI,GAAG,CAAC;AAAA,IAClB;AACA,WAAO,MAAM,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC;AAAA,EAC1C;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MAChE,SAAS,KAAK,YAAY;AAAA,IAC5B,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,mBAAmB,IAAI,MAAM,EAAE;AAAA,IACjD;AACA,UAAM,OAAgB,MAAM,IAAI,KAAK;AACrC,QAAI,CAACA,UAAS,IAAI,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,IAAI,WAAW,GAAG;AAC5E,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AACA,SAAK,MAAM,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,SAAK,SAAS;AACd,eAAW,WAAW,MAAM,KAAK,KAAK,cAAc,GAAG;AACrD,UAAI;AACF,gBAAQ;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAuB;AACrB,QAAI,KAAK,QAAQ,MAAM;AACrB,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAAwB;AACtB,UAAM,IAAI,IAAI,IAAI,qBAAqB,KAAK,OAAO;AACnD,MAAE,SAAS;AACX,WAAO,EAAE,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,mBAA+C;AACnD,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,EAAE,IAAI,oBAAoB,SAAS,CAAC,EAAE,CAAC;AAAA,IAC9D,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,qBAAqB,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,IAC3D;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,QAAI,CAACA,UAAS,IAAI,KAAK,EAAE,cAAc,OAAO;AAC5C,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,WAAO,uBAAuB,KAAK,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,WAAqD;AAC5E,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU;AAAA,QACnB,IAAI;AAAA,QACJ,SAAS,EAAE,WAAW,QAAQ;AAAA,MAChC,CAAC;AAAA,IACH,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,IAC7D;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AACA,WAAO,4BAA4B,IAAI;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,WAGM;AACxB,QAAI,cAAmC;AACvC,UAAM,QAAQ,YAAY;AACxB,UAAI;AACF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,oBAAoB;AAC/D,YAAI,WAAW,MAAM,KAAK,iBAAiB;AAC3C,kBAAU,WAAW,QAAQ;AAC7B,cAAM,SAAS,kBAAkB;AAAA,UAC/B,KAAK,GAAG,KAAK,OAAO,8BAA8B;AAAA,YAChD,KAAK,aAAa;AAAA,UACpB,CAAC;AAAA,UACD,OAAO,CAAC,OAAO,SAAS,KAAK,eAAe,OAAO,IAAI;AAAA,QACzD,CAAC;AACD,sBAAc,MAAM;AAClB,iBAAO,MAAM;AAAA,QACf;AACA,yBAAiB,OAAO,QAAQ;AAC9B,cAAI,OAAO,IAAI,SAAS,UAAU;AAChC;AAAA,UACF;AACA,cAAI;AACJ,cAAI;AACF,mBAAO,KAAK,MAAM,IAAI,IAAI;AAAA,UAC5B,QAAQ;AACN;AAAA,UACF;AACA,gBAAM,SAAS,2CAA2C,IAAI;AAC9D,cAAI,WAAW,UAAa,OAAO,MAAM,WAAW,GAAG;AACrD;AAAA,UACF;AACA,gBAAM,UAAU,+BAA+B,OAAO,KAAK;AAC3D,qBAAW,OAAO,SAAS;AACzB,kBAAM,OAAO,MAAM,KAAK,mBAAmB,IAAI,SAAS;AACxD,uBAAW,iCAAiC,UAAU,IAAI;AAAA,UAC5D;AACA,oBAAU,WAAW,QAAQ;AAAA,QAC/B;AAAA,MACF,SAAS,GAAG;AACV,kBAAU;AAAA,UACR,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF,GAAG;AACH,WAAO;AAAA,MACL,OAAO,MAAM;AACX,sBAAc;AACd,aAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,OAAkD;AAChE,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,+BAA+B,mBAAmB,GAAG,CAAC;AACjF,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU;AAAA,QACnB,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,SAAS,MAAM;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AACD,UAAM,WAAW,MAAM,IAAI,KAAK;AAChC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,cAAc,IAAI,MAAM,IAAI,QAAQ,EAAE;AAAA,IACxD;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,QAAQ;AAAA,IAC5B,QAAQ;AACN,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AACA,QAAI,CAACA,UAAS,IAAI,GAAG;AACnB,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AACA,UAAM,WAAW,KAAK;AACtB,UAAM,aAAa,KAAK;AACxB,QAAI,OAAO,aAAa,YAAY,OAAO,eAAe,UAAU;AAClE,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,UAAM,kBAAkB,4BAA4B,KAAK,eAAe;AACxE,UAAM,MAAM,oBAAI,KAAK;AACrB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,MAAM;AAAA,MACZ;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,OAA8C;AACpE,UAAM,KAAK,IAAI,qBAAqB;AAAA,MAClC,UAAU,MAAM;AAAA,MAChB,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,UAAkB,SAAiC;AACrE,UAAM,KAAK,IAAI,iBAAiB,EAAE,UAAU,QAAQ,CAAC;AAAA,EACvD;AAAA,EAEA,MAAM,YAAY,SAA0D;AAC1E,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,oCAAoC,mBAAmB,GAAG,CAAC;AACtF,UAAM,OAAuC,EAAE,MAAM,QAAQ,KAAK;AAClE,QAAI,QAAQ,QAAQ,QAAW;AAC7B,WAAK,MAAM,QAAQ;AAAA,IACrB;AACA,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,gBAAgB,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,IACtD;AACA,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AACA,QAAI,CAACA,UAAS,IAAI,KAAK,OAAO,KAAK,OAAO,UAAU;AAClD,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,IAAI,IAAY,SAAiC;AAC7D,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,MAAM,GAAG,KAAK,OAAO,+BAA+B,mBAAmB,GAAG,CAAC;AACjF,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,MAC1B,MAAM,KAAK,UAAU,EAAE,IAAI,QAAQ,CAAC;AAAA,IACtC,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,IAAI,KAAK;AACzB,YAAM,IAAI,MAAM,OAAO,EAAE,KAAK,IAAI,MAAM,IAAI,CAAC,EAAE;AAAA,IACjD;AAAA,EACF;AACF;","names":["isRecord"]}
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"]}
@@ -8,25 +8,42 @@
8
8
  * Prerequisites
9
9
  * - Start the app: `npm run dev -w @agent-play/web-ui` (from repo root). Optional: Redis for
10
10
  * durable sessions; see docs for `REDIS_URL`.
11
- * - If the server uses registered agents (Redis + repository), run `agent-play login`,
12
- * `agent-play create-key`, then `agent-play create`, then pass **`agentId`** and set
13
- * **`AGENT_PLAY_API_KEY`** on **`RemotePlayWorld`** (see SDK `AddPlayerInput` and
14
- * `RemotePlayWorldOptions` JSDoc).
11
+ * - Run **`agent-play create-main-node`** so **`~/.agent-play/credentials.json`** exists (human **`passw`**).
12
+ * This script loads it via **`loadAgentPlayCredentialsFileFromPathSync`**, with **`AGENT_PLAY_ROOT_KEY`** /
13
+ * **`AGENT_PLAY_NODE_PASSW`** as optional overrides. **`passw`** is hashed with **`hashNodePassword`** (see
14
+ * **`nodeCredentialsMaterialFromHumanPassphrase`** in **@agent-play/node-tools**) before node id derivation.
15
+ * For agent nodes under a main account, **`connect({ mainNodeId })`** uses the parent main node id (see
16
+ * `EXAMPLE_MAIN_NODE_ID` below).
17
+ * - If the server uses registered agents (Redis + repository), run `agent-play bootstrap-node`,
18
+ * then `agent-play create-agent-node`, and pass **`AGENT_PLAY_AGENT_NODE_ID`** for `addAgent`.
19
+ * The SDK validates that agent node id via `/api/nodes/validate` before registration.
15
20
  * - `OPENAI_API_KEY` is only needed if you extend this script to call the model; registration-only
16
21
  * runs use a placeholder below.
17
22
  *
18
23
  * Run (from `packages/sdk` or via `npm run example` at repo root):
19
24
  * `tsx -r dotenv/config examples/01-remote-web-ui-langchain.ts`
20
25
  *
21
- * Env: `AGENT_PLAY_WEB_UI_URL`, `AGENT_PLAY_API_KEY`, `AGENT_PLAY_HOLD_SECONDS` (default 3600),
22
- * `AGENT_PLAY_AGENT_ID` when using a registered agent repository, optional `OPENAI_API_KEY`.
26
+ * Env: `AGENT_PLAY_WEB_UI_URL`, optional `AGENT_PLAY_CREDENTIALS_PATH`, optional overrides `AGENT_PLAY_ROOT_KEY` /
27
+ * `AGENT_PLAY_NODE_PASSW`, `AGENT_PLAY_HOLD_SECONDS` (default 3600), `AGENT_PLAY_AGENT_NODE_ID` when using Redis,
28
+ * optional `OPENAI_API_KEY`.
23
29
  */
24
30
 
25
- import { RemotePlayWorld, langchainRegistration } from "../src/index.js";
31
+ import {
32
+ RemotePlayWorld,
33
+ type IntercomToolExecutor,
34
+ langchainRegistration,
35
+ loadAgentPlayCredentialsFileFromPathSync,
36
+ loadRootKey,
37
+ resolveAgentPlayCredentialsPath,
38
+ } from "../src/index.js";
26
39
  import { createAgent, tool } from "langchain";
27
40
  import { ChatOpenAI } from "@langchain/openai";
28
41
  import { z } from "zod";
29
42
 
43
+ /** Example parent main node id (replace with your deployment’s main id when using agent credentials). */
44
+ const EXAMPLE_MAIN_NODE_ID =
45
+ "810be53fb0153087438401ecd63e72e56701d43307955d57af196ccae5cdbf81";
46
+
30
47
  const model = new ChatOpenAI({
31
48
  apiKey: process.env.OPENAI_API_KEY ?? "unused-registration-only",
32
49
  model: "gpt-4.1",
@@ -57,27 +74,71 @@ const agent = createAgent({
57
74
  systemPrompt: "Use increment when the user asks to bump a number.",
58
75
  });
59
76
 
77
+ const executeIntercomTool: IntercomToolExecutor = ({ toolName, args }) => {
78
+ if (toolName === "chat_tool") {
79
+ const text = typeof args.text === "string" ? args.text : "";
80
+ return { message: `echo:${text}` };
81
+ }
82
+ if (toolName === "increment") {
83
+ const n = args.n;
84
+ const num = typeof n === "number" ? n : Number(n);
85
+ if (!Number.isFinite(num)) {
86
+ throw new Error("increment: n must be a finite number");
87
+ }
88
+ return { result: String(num + 1) };
89
+ }
90
+ throw new Error(`unknown tool for intercom: ${toolName}`);
91
+ };
92
+
60
93
  async function main() {
61
- const base = process.env.AGENT_PLAY_WEB_UI_URL ?? "http://127.0.0.1:3000";
62
- const apiKey = process.env.AGENT_PLAY_API_KEY ?? "dev-placeholder";
94
+ const stored = loadAgentPlayCredentialsFileFromPathSync(
95
+ resolveAgentPlayCredentialsPath()
96
+ );
97
+ const rootKey =
98
+ process.env.AGENT_PLAY_ROOT_KEY?.trim() ??
99
+ (stored === null ? "" : loadRootKey());
100
+ const passw =
101
+ typeof process.env.AGENT_PLAY_NODE_PASSW === "string" &&
102
+ process.env.AGENT_PLAY_NODE_PASSW.length > 0
103
+ ? process.env.AGENT_PLAY_NODE_PASSW
104
+ : (stored?.passw ?? "");
105
+ const base = (
106
+ process.env.AGENT_PLAY_WEB_UI_URL ??
107
+ stored?.serverUrl ??
108
+ "http://127.0.0.1:3000"
109
+ ).replace(/\/$/, "");
110
+ if (rootKey.length === 0 || passw.length === 0) {
111
+ throw new Error(
112
+ "Missing credentials: run `agent-play create-main-node` or set AGENT_PLAY_ROOT_KEY + AGENT_PLAY_NODE_PASSW"
113
+ );
114
+ }
63
115
  const holdSeconds = Number(process.env.AGENT_PLAY_HOLD_SECONDS ?? 3600);
64
116
 
65
- const world = new RemotePlayWorld({ baseUrl: base, apiKey });
117
+ const world = new RemotePlayWorld();
118
+ let closeIntercom: (() => void) | undefined;
66
119
  world.onClose(() => {
120
+ closeIntercom?.();
67
121
  console.log("RemotePlayWorld closed.");
68
122
  });
69
- await world.connect();
123
+ await world.connect({ mainNodeId: EXAMPLE_MAIN_NODE_ID });
70
124
 
71
- const agentId =
72
- process.env.AGENT_PLAY_AGENT_ID?.trim() ?? "example-local-agent-1";
125
+ const agentNodeId =
126
+ process.env.AGENT_PLAY_AGENT_NODE_ID?.trim() ??
127
+ process.env.AGENT_PLAY_AGENT_ID?.trim() ??
128
+ "4fda036ff28e27a1df7529ebd765bc23dec4228b1e9be3fff4cea57bbc9b8dc4";
73
129
 
74
- const player = await world.addPlayer({
75
- name: "remote-demo",
130
+ const player = await world.addAgent({
131
+ name: "francis",
76
132
  type: "langchain",
77
133
  agent: langchainRegistration(agent),
78
- agentId,
134
+ nodeId: agentNodeId,
79
135
  });
80
136
 
137
+ closeIntercom = world.subscribeIntercomCommands({
138
+ playerId: player.id,
139
+ executeTool: executeIntercomTool,
140
+ }).close;
141
+
81
142
  console.log("Open the watch UI (session is server-side; UI resolves session via API):");
82
143
  console.log(player.previewUrl);
83
144
  console.log(`Holding the process for ${String(holdSeconds)}s (set AGENT_PLAY_HOLD_SECONDS to change).`);
@@ -3,26 +3,37 @@
3
3
  *
4
4
  * Same architecture as example 01: **RemotePlayWorld** talks to **@agent-play/web-ui** over HTTP
5
5
  * (`/api/agent-play/session`, `/api/agent-play/players`, `/api/agent-play/sdk/rpc`). One session
6
- * (`sid`) holds multiple players; each `addPlayer` uses a required **`agentId`** (from **`agent-play create`** when
7
- * using a repository, or the example defaults locally).
6
+ * (`sid`) holds multiple players; each `addAgent` uses a required **`nodeId`** (agent node id from **`agent-play create`** when
7
+ * using a repository, or the example defaults locally). The server stores it as `agentId`, and the SDK validates the node id with
8
+ * `/api/nodes/validate` before calling `/api/agent-play/players`.
8
9
  *
9
10
  * Open the printed preview URL once: both avatars share the same world and session.
10
11
  *
11
12
  * Prerequisites: web-ui running (`npm run dev -w @agent-play/web-ui`). With Redis-backed agents,
12
- * run `agent-play login`, `agent-play create-key`, then `agent-play create` twice (max 2 agents
13
- * per account), pass each **`agentId`** on **`addPlayer`**, and set **`AGENT_PLAY_API_KEY`** on
14
- * **`RemotePlayWorld`** (one account key for both).
13
+ * run `agent-play bootstrap-node`, then `agent-play create` twice (max 2 agents
14
+ * per node), pass each agent **`nodeId`** on **`addAgent`**, and set **`AGENT_PLAY_ROOT_KEY`** /
15
+ * **`AGENT_PLAY_NODE_PASSW`** for **`RemotePlayWorld`** (same credentials for both registrations).
15
16
  *
16
17
  * Run: `tsx -r dotenv/config examples/02-remote-two-players-langchain.ts`
17
- * Env: `AGENT_PLAY_WEB_UI_URL`, `AGENT_PLAY_API_KEY`, `AGENT_PLAY_HOLD_SECONDS` (default 3600),
18
- * `AGENT_PLAY_AGENT_ID_ALPHA` / `AGENT_PLAY_AGENT_ID_BETA` when using a registered repository.
18
+ * Env: default **`~/.agent-play/credentials.json`** (or `AGENT_PLAY_CREDENTIALS_PATH`), optional `AGENT_PLAY_WEB_UI_URL` /
19
+ * `AGENT_PLAY_ROOT_KEY` / `AGENT_PLAY_NODE_PASSW` overrides, `AGENT_PLAY_HOLD_SECONDS` (default 3600),
20
+ * `AGENT_PLAY_AGENT_NODE_ID_*` when using a registered repository.
19
21
  */
20
22
 
21
- import { RemotePlayWorld, langchainRegistration } from "../src/index.js";
23
+ import {
24
+ RemotePlayWorld,
25
+ langchainRegistration,
26
+ loadAgentPlayCredentialsFileFromPathSync,
27
+ loadRootKey,
28
+ resolveAgentPlayCredentialsPath,
29
+ } from "../src/index.js";
22
30
  import { createAgent, tool } from "langchain";
23
31
  import { ChatOpenAI } from "@langchain/openai";
24
32
  import { z } from "zod";
25
33
 
34
+ const EXAMPLE_MAIN_NODE_ID =
35
+ "810be53fb0153087438401ecd63e72e56701d43307955d57af196ccae5cdbf81";
36
+
26
37
  const model = new ChatOpenAI({
27
38
  apiKey: process.env.OPENAI_API_KEY ?? "unused-registration-only",
28
39
  model: "gpt-4.1",
@@ -79,29 +90,55 @@ const agentBeta = createAgent({
79
90
  });
80
91
 
81
92
  async function main() {
82
- const base = process.env.AGENT_PLAY_WEB_UI_URL ?? "http://127.0.0.1:3000";
83
- const apiKey = process.env.AGENT_PLAY_API_KEY ?? "dev-placeholder";
93
+ const stored = loadAgentPlayCredentialsFileFromPathSync(
94
+ resolveAgentPlayCredentialsPath()
95
+ );
96
+ const rootKey =
97
+ process.env.AGENT_PLAY_ROOT_KEY?.trim() ??
98
+ (stored === null ? "" : loadRootKey());
99
+ const passw =
100
+ typeof process.env.AGENT_PLAY_NODE_PASSW === "string" &&
101
+ process.env.AGENT_PLAY_NODE_PASSW.length > 0
102
+ ? process.env.AGENT_PLAY_NODE_PASSW
103
+ : (stored?.passw ?? "");
104
+ const base = (
105
+ process.env.AGENT_PLAY_WEB_UI_URL ??
106
+ stored?.serverUrl ??
107
+ "http://127.0.0.1:3000"
108
+ ).replace(/\/$/, "");
109
+ if (rootKey.length === 0 || passw.length === 0) {
110
+ throw new Error(
111
+ "Missing credentials: run `agent-play create-main-node` or set AGENT_PLAY_ROOT_KEY + AGENT_PLAY_NODE_PASSW"
112
+ );
113
+ }
84
114
  const holdSeconds = Number(process.env.AGENT_PLAY_HOLD_SECONDS ?? 3600);
85
115
 
86
- const world = new RemotePlayWorld({ baseUrl: base, apiKey });
87
- await world.connect();
116
+ const world = new RemotePlayWorld({
117
+ baseUrl: base,
118
+ nodeCredentials: { rootKey, passw },
119
+ });
120
+ await world.connect({ mainNodeId: EXAMPLE_MAIN_NODE_ID });
88
121
 
89
- const agentIdA =
90
- process.env.AGENT_PLAY_AGENT_ID_ALPHA?.trim() ?? "example-local-agent-alpha";
91
- const agentIdB =
92
- process.env.AGENT_PLAY_AGENT_ID_BETA?.trim() ?? "example-local-agent-beta";
122
+ const nodeIdA =
123
+ process.env.AGENT_PLAY_AGENT_NODE_ID_ALPHA?.trim() ??
124
+ process.env.AGENT_PLAY_AGENT_ID_ALPHA?.trim() ??
125
+ "example-local-agent-alpha";
126
+ const nodeIdB =
127
+ process.env.AGENT_PLAY_AGENT_NODE_ID_BETA?.trim() ??
128
+ process.env.AGENT_PLAY_AGENT_ID_BETA?.trim() ??
129
+ "example-local-agent-beta";
93
130
 
94
- const playerA = await world.addPlayer({
131
+ const playerA = await world.addAgent({
95
132
  name: "alpha",
96
133
  type: "langchain",
97
134
  agent: langchainRegistration(agentAlpha),
98
- agentId: agentIdA,
135
+ nodeId: nodeIdA,
99
136
  });
100
- const playerB = await world.addPlayer({
137
+ const playerB = await world.addAgent({
101
138
  name: "beta",
102
139
  type: "langchain",
103
140
  agent: langchainRegistration(agentBeta),
104
- agentId: agentIdB,
141
+ nodeId: nodeIdB,
105
142
  });
106
143
 
107
144
  console.log("Session id:", world.getSessionId());
@@ -9,7 +9,7 @@ Run the **web UI** first so APIs exist:
9
9
  npm run dev -w @agent-play/web-ui
10
10
  ```
11
11
 
12
- With a **registered-agent** repository (**`REDIS_URL`** on the server): run **`agent-play login`**, **`agent-play create-key`** (once per account), **`agent-play create`** for each agent. Set **`AGENT_PLAY_API_KEY`** and pass **`AGENT_PLAY_AGENT_ID`** (and **`AGENT_PLAY_AGENT_ID_ALPHA`** / **`AGENT_PLAY_AGENT_ID_BETA`** for example 02) so **`addPlayer`** uses real ids from **`agent-play create`**. Without Redis, the examples default to stable local **`agentId`** strings.
12
+ With a **registered-agent** repository (**`REDIS_URL`** on the server): run **`agent-play bootstrap-node`** and **`agent-play create`** for each agent. Use **`~/.agent-play/credentials.json`** (from **`create-main-node`**) for **`passw`** and **`.root`** for **`rootKey`**, or set **`AGENT_PLAY_ROOT_KEY`** / **`AGENT_PLAY_NODE_PASSW`** to override. Pass **`AGENT_PLAY_AGENT_NODE_ID`** (or legacy **`AGENT_PLAY_AGENT_ID`**) and for example 02 **`AGENT_PLAY_AGENT_NODE_ID_ALPHA`** / **`_BETA`** so **`addAgent`** uses real agent node ids from **`agent-play create`**. Without Redis, the examples default to stable local **`nodeId`** strings.
13
13
 
14
14
  | Order | File | Purpose |
15
15
  |------:|------|---------|
@@ -18,10 +18,12 @@ With a **registered-agent** repository (**`REDIS_URL`** on the server): run **`a
18
18
 
19
19
  ## Environment
20
20
 
21
- - `AGENT_PLAY_WEB_UI_URL` — Base URL of the running app (default `http://127.0.0.1:3000`).
22
- - `AGENT_PLAY_API_KEY` — Account API key for **`RemotePlayWorld`** (use a dev placeholder if the server has no repository).
21
+ - `AGENT_PLAY_WEB_UI_URL` — Base URL of the running app (overrides **`serverUrl`** from credentials when set).
22
+ - `AGENT_PLAY_CREDENTIALS_PATH` — Optional path to **`credentials.json`** (default **`~/.agent-play/credentials.json`**).
23
+ - `AGENT_PLAY_ROOT_KEY` — Optional override: hex **`rootKey`** from **`.root`** (otherwise loaded via **`loadRootKey()`** when credentials exist).
24
+ - `AGENT_PLAY_NODE_PASSW` — Optional override: human **`passw`** from the credentials file (otherwise read from that file).
23
25
  - `AGENT_PLAY_HOLD_SECONDS` — How long **`hold().for()`** waits (default `3600`).
24
- - `AGENT_PLAY_AGENT_ID` / `AGENT_PLAY_AGENT_ID_ALPHA` / `AGENT_PLAY_AGENT_ID_BETA` — Registered agent ids when using Redis.
26
+ - `AGENT_PLAY_AGENT_NODE_ID` (or `AGENT_PLAY_AGENT_ID`) / `AGENT_PLAY_AGENT_NODE_ID_ALPHA` / `AGENT_PLAY_AGENT_NODE_ID_BETA` (or `AGENT_PLAY_AGENT_ID_*`) Agent node ids when using Redis.
25
27
  - `OPENAI_API_KEY` — Only if you extend the scripts to call the model; registration-only runs use a placeholder.
26
28
  - `AGENT_PLAY_DEBUG=1` — Verbose SDK logging (see `configureAgentPlayDebug` in package exports).
27
29