@whitesands/agent-player 0.2.0 → 1.1.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/CHANGELOG.md +13 -3
- package/README.md +234 -41
- package/dist/index.cjs +116 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +116 -24
- package/dist/index.js.map +1 -1
- package/dist/protocol.cjs +2 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +4 -2
- package/dist/protocol.d.ts +4 -2
- package/dist/protocol.js +2 -1
- package/dist/protocol.js.map +1 -1
- package/dist/testing.cjs +19 -20
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +3 -2
- package/dist/testing.d.ts +3 -2
- package/dist/testing.js +19 -20
- package/dist/testing.js.map +1 -1
- package/dist/{types-DCIs4-gP.d.cts → types-D0p6GrVs.d.cts} +9 -2
- package/dist/{types-DIF8LgGI.d.ts → types-DXM_HZHu.d.ts} +9 -2
- package/package.json +27 -4
package/dist/index.js
CHANGED
|
@@ -41,18 +41,89 @@ function log(logger, level, message, extra) {
|
|
|
41
41
|
logger?.[level]?.(message, extra);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// src/memory.ts
|
|
45
|
+
import { mkdirSync } from "fs";
|
|
46
|
+
import { dirname, resolve } from "path";
|
|
47
|
+
import Database from "better-sqlite3";
|
|
48
|
+
var MAX_DONE = 50;
|
|
49
|
+
var SessionMemory = class {
|
|
50
|
+
db;
|
|
51
|
+
constructor(path) {
|
|
52
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
53
|
+
this.db = new Database(path, { timeout: 5e3 });
|
|
54
|
+
this.db.exec(`
|
|
55
|
+
CREATE TABLE IF NOT EXISTS actions (
|
|
56
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
57
|
+
session_id TEXT NOT NULL,
|
|
58
|
+
character TEXT NOT NULL,
|
|
59
|
+
action TEXT NOT NULL,
|
|
60
|
+
args TEXT NOT NULL,
|
|
61
|
+
ok INTEGER NOT NULL,
|
|
62
|
+
error TEXT
|
|
63
|
+
);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS actions_by_session ON actions(session_id, id);
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
record(sessionId, character, entry) {
|
|
68
|
+
this.db.prepare(
|
|
69
|
+
`INSERT INTO actions (session_id, character, action, args, ok, error)
|
|
70
|
+
VALUES (@sessionId, @character, @action, @args, @ok, @error)`
|
|
71
|
+
).run({
|
|
72
|
+
sessionId,
|
|
73
|
+
character,
|
|
74
|
+
action: entry.action,
|
|
75
|
+
args: JSON.stringify(entry.args),
|
|
76
|
+
ok: entry.ok ? 1 : 0,
|
|
77
|
+
error: entry.error ?? null
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/** Oldest first, capped to the most recent actions for this session. */
|
|
81
|
+
done(sessionId) {
|
|
82
|
+
const rows = this.db.prepare(
|
|
83
|
+
`SELECT action, args, ok, error FROM (
|
|
84
|
+
SELECT id, action, args, ok, error FROM actions
|
|
85
|
+
WHERE session_id = ?
|
|
86
|
+
ORDER BY id DESC
|
|
87
|
+
LIMIT ?
|
|
88
|
+
) ORDER BY id ASC`
|
|
89
|
+
).all(sessionId, MAX_DONE);
|
|
90
|
+
return rows.map((row) => {
|
|
91
|
+
const entry = {
|
|
92
|
+
action: row.action,
|
|
93
|
+
args: JSON.parse(row.args),
|
|
94
|
+
ok: row.ok === 1
|
|
95
|
+
};
|
|
96
|
+
if (row.error) entry.error = row.error;
|
|
97
|
+
return entry;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
close() {
|
|
101
|
+
this.db.close();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
function defaultMemoryPath() {
|
|
105
|
+
return resolve(process.cwd(), ".wsi", "agent-memory.sqlite");
|
|
106
|
+
}
|
|
107
|
+
function viewWithDone(view, done) {
|
|
108
|
+
if (view && typeof view === "object" && !Array.isArray(view)) {
|
|
109
|
+
return { ...view, done };
|
|
110
|
+
}
|
|
111
|
+
return { view, done };
|
|
112
|
+
}
|
|
113
|
+
|
|
44
114
|
// src/platform-connection.ts
|
|
45
115
|
import { randomUUID } from "crypto";
|
|
46
116
|
import WebSocket from "ws";
|
|
47
117
|
|
|
48
118
|
// src/protocol.ts
|
|
49
119
|
var PROTOCOL_VERSION = 1;
|
|
50
|
-
var SDK_VERSION = "
|
|
120
|
+
var SDK_VERSION = "1.1.0";
|
|
51
121
|
var SESSION_RESUME_GRACE_MS = 3e4;
|
|
52
122
|
var DEFAULT_AGENT_INSTRUCTIONS = [
|
|
53
123
|
"You are a remote game agent. Tools are provided by the game.",
|
|
54
124
|
"On every turn: call wait first. It blocks until the game grants your turn and then returns the current view from see.",
|
|
55
125
|
"After wait returns, call exactly one action tool (not see, not wait).",
|
|
126
|
+
"The view's done list is what this character has already called in this session, oldest first. Use it when choosing the next action.",
|
|
56
127
|
"If an action tool returns an error, retry once with a corrected action. A second failure ends the turn as failed."
|
|
57
128
|
].join("\n");
|
|
58
129
|
function assertNever(value) {
|
|
@@ -150,7 +221,7 @@ var PlatformConnection = class {
|
|
|
150
221
|
}
|
|
151
222
|
waitForSessionEvent(sessionId, kind, timeoutMs = 15e3) {
|
|
152
223
|
const key = `session:${sessionId}:${kind}`;
|
|
153
|
-
return new Promise((
|
|
224
|
+
return new Promise((resolve2, reject) => {
|
|
154
225
|
const timer = setTimeout(() => {
|
|
155
226
|
this.pending.delete(key);
|
|
156
227
|
reject(new Error(`Timed out waiting for session ${kind}`));
|
|
@@ -158,7 +229,7 @@ var PlatformConnection = class {
|
|
|
158
229
|
this.pending.set(key, {
|
|
159
230
|
resolve: (envelope) => {
|
|
160
231
|
clearTimeout(timer);
|
|
161
|
-
|
|
232
|
+
resolve2(envelope);
|
|
162
233
|
},
|
|
163
234
|
reject: (error) => {
|
|
164
235
|
clearTimeout(timer);
|
|
@@ -180,13 +251,13 @@ var PlatformConnection = class {
|
|
|
180
251
|
if (!this.ws) return;
|
|
181
252
|
const ws = this.ws;
|
|
182
253
|
this.ws = null;
|
|
183
|
-
await new Promise((
|
|
184
|
-
ws.once("close", () =>
|
|
254
|
+
await new Promise((resolve2) => {
|
|
255
|
+
ws.once("close", () => resolve2());
|
|
185
256
|
ws.close();
|
|
186
257
|
});
|
|
187
258
|
}
|
|
188
259
|
openSocket() {
|
|
189
|
-
return new Promise((
|
|
260
|
+
return new Promise((resolve2, reject) => {
|
|
190
261
|
const ws = new WebSocket(this.url);
|
|
191
262
|
this.ws = ws;
|
|
192
263
|
let settled = false;
|
|
@@ -225,7 +296,7 @@ var PlatformConnection = class {
|
|
|
225
296
|
this.accountName = envelope.accountName;
|
|
226
297
|
this.startHeartbeat();
|
|
227
298
|
this.flushOutbox();
|
|
228
|
-
|
|
299
|
+
resolve2(envelope.accountName);
|
|
229
300
|
return;
|
|
230
301
|
}
|
|
231
302
|
if (envelope.type === "pong") {
|
|
@@ -496,13 +567,17 @@ function createSessionMcpServer(player, gate, options) {
|
|
|
496
567
|
{ name: options?.name ?? "agent-player", version: SDK_VERSION },
|
|
497
568
|
{ capabilities: { tools: {} } }
|
|
498
569
|
);
|
|
570
|
+
const actions = options?.actions;
|
|
571
|
+
const viewed = async () => {
|
|
572
|
+
const view = await player.see.invoke({});
|
|
573
|
+
return actions ? viewWithDone(view, actions.done()) : view;
|
|
574
|
+
};
|
|
499
575
|
server.registerTool(
|
|
500
576
|
"see",
|
|
501
577
|
{ description: player.see.description },
|
|
502
578
|
async () => {
|
|
503
579
|
try {
|
|
504
|
-
|
|
505
|
-
return jsonResult(view);
|
|
580
|
+
return jsonResult(await viewed());
|
|
506
581
|
} catch (error) {
|
|
507
582
|
return toolError(error);
|
|
508
583
|
}
|
|
@@ -514,8 +589,7 @@ function createSessionMcpServer(player, gate, options) {
|
|
|
514
589
|
async () => {
|
|
515
590
|
try {
|
|
516
591
|
await gate.waitForTurn();
|
|
517
|
-
|
|
518
|
-
return jsonResult(view);
|
|
592
|
+
return jsonResult(await viewed());
|
|
519
593
|
} catch (error) {
|
|
520
594
|
return toolError(error);
|
|
521
595
|
}
|
|
@@ -525,8 +599,11 @@ function createSessionMcpServer(player, gate, options) {
|
|
|
525
599
|
const handler = async (args) => {
|
|
526
600
|
try {
|
|
527
601
|
const result = await action.invoke(args);
|
|
602
|
+
actions?.record({ action: action.name, args, ok: true });
|
|
528
603
|
return jsonResult(result ?? { ok: true });
|
|
529
604
|
} catch (error) {
|
|
605
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
606
|
+
actions?.record({ action: action.name, args, ok: false, error: message });
|
|
530
607
|
return toolError(error);
|
|
531
608
|
}
|
|
532
609
|
};
|
|
@@ -571,8 +648,8 @@ var TurnGate = class {
|
|
|
571
648
|
return;
|
|
572
649
|
}
|
|
573
650
|
if (!this.waitPromise) {
|
|
574
|
-
this.waitPromise = new Promise((
|
|
575
|
-
this.waitResolve =
|
|
651
|
+
this.waitPromise = new Promise((resolve2) => {
|
|
652
|
+
this.waitResolve = resolve2;
|
|
576
653
|
});
|
|
577
654
|
}
|
|
578
655
|
await this.waitPromise;
|
|
@@ -594,8 +671,8 @@ var TurnGate = class {
|
|
|
594
671
|
let timeoutId;
|
|
595
672
|
let onAbort;
|
|
596
673
|
const signal = options?.signal;
|
|
597
|
-
this.turnPromise = new Promise((
|
|
598
|
-
this.turnResolve =
|
|
674
|
+
this.turnPromise = new Promise((resolve2, reject) => {
|
|
675
|
+
this.turnResolve = resolve2;
|
|
599
676
|
this.turnReject = reject;
|
|
600
677
|
if (options?.timeoutMs != null) {
|
|
601
678
|
timeoutId = setTimeout(() => {
|
|
@@ -628,11 +705,11 @@ var TurnGate = class {
|
|
|
628
705
|
}
|
|
629
706
|
/** Platform finished one action cycle (success or second failure). */
|
|
630
707
|
completeTurn(outcome) {
|
|
631
|
-
const
|
|
632
|
-
if (!
|
|
708
|
+
const resolve2 = this.turnResolve;
|
|
709
|
+
if (!resolve2) return;
|
|
633
710
|
this.turnResolve = null;
|
|
634
711
|
this.turnReject = null;
|
|
635
|
-
|
|
712
|
+
resolve2(outcome);
|
|
636
713
|
}
|
|
637
714
|
/** Fail an in-flight turn, for example when the connection cannot be resumed. */
|
|
638
715
|
failTurn(error) {
|
|
@@ -656,7 +733,7 @@ var TurnGate = class {
|
|
|
656
733
|
|
|
657
734
|
// src/agent-server.ts
|
|
658
735
|
var DEFAULT_TURN_TIMEOUT_MS = 6e4;
|
|
659
|
-
var
|
|
736
|
+
var PLATFORM_URL = "wss://api.whitesandsint.com";
|
|
660
737
|
var AgentServer = class {
|
|
661
738
|
options;
|
|
662
739
|
platformKey;
|
|
@@ -666,6 +743,7 @@ var AgentServer = class {
|
|
|
666
743
|
sessions = /* @__PURE__ */ new Map();
|
|
667
744
|
listeners = /* @__PURE__ */ new Set();
|
|
668
745
|
inline;
|
|
746
|
+
memory = null;
|
|
669
747
|
started = false;
|
|
670
748
|
closing = false;
|
|
671
749
|
constructor(options = {}) {
|
|
@@ -675,7 +753,7 @@ var AgentServer = class {
|
|
|
675
753
|
}
|
|
676
754
|
this.options = options;
|
|
677
755
|
this.platformKey = platformKey || "inline";
|
|
678
|
-
this.platformUrl = options.platformUrl ??
|
|
756
|
+
this.platformUrl = options.platformUrl ?? PLATFORM_URL;
|
|
679
757
|
this.logger = options.logger;
|
|
680
758
|
this.inline = options.inline;
|
|
681
759
|
if (options.onEvent) this.listeners.add(options.onEvent);
|
|
@@ -713,8 +791,15 @@ var AgentServer = class {
|
|
|
713
791
|
const sessionToken = randomUUID2();
|
|
714
792
|
const gate = new TurnGate();
|
|
715
793
|
const name = options?.name ?? instance.constructor?.name ?? "player";
|
|
794
|
+
const memory = this.actionMemory();
|
|
716
795
|
const server = createSessionMcpServer(reflected, gate, {
|
|
717
|
-
name: `agent-player:${name}
|
|
796
|
+
name: `agent-player:${name}`,
|
|
797
|
+
...memory ? {
|
|
798
|
+
actions: {
|
|
799
|
+
record: (entry) => memory.record(sessionId, name, entry),
|
|
800
|
+
done: () => memory.done(sessionId)
|
|
801
|
+
}
|
|
802
|
+
} : {}
|
|
718
803
|
});
|
|
719
804
|
const instructions = [this.options.instructions ?? DEFAULT_AGENT_INSTRUCTIONS, options?.instructions].filter((part) => Boolean(part && part.length > 0)).join("\n\n");
|
|
720
805
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -917,9 +1002,19 @@ var AgentServer = class {
|
|
|
917
1002
|
await this.connection.close();
|
|
918
1003
|
this.connection = null;
|
|
919
1004
|
}
|
|
1005
|
+
this.memory?.close();
|
|
1006
|
+
this.memory = null;
|
|
920
1007
|
this.started = false;
|
|
921
1008
|
this.closing = false;
|
|
922
1009
|
}
|
|
1010
|
+
actionMemory() {
|
|
1011
|
+
if (this.options.memoryPath === false) return null;
|
|
1012
|
+
if (!this.memory) {
|
|
1013
|
+
const path = this.options.memoryPath ?? defaultMemoryPath();
|
|
1014
|
+
this.memory = new SessionMemory(path);
|
|
1015
|
+
}
|
|
1016
|
+
return this.memory;
|
|
1017
|
+
}
|
|
923
1018
|
async [Symbol.asyncDispose]() {
|
|
924
1019
|
await this.close();
|
|
925
1020
|
}
|
|
@@ -927,11 +1022,8 @@ var AgentServer = class {
|
|
|
927
1022
|
export {
|
|
928
1023
|
AgentServer,
|
|
929
1024
|
ConnectionLostError,
|
|
930
|
-
DEFAULT_AGENT_INSTRUCTIONS,
|
|
931
|
-
PROTOCOL_VERSION,
|
|
932
1025
|
PlatformAuthError,
|
|
933
1026
|
ProtocolVersionError,
|
|
934
|
-
SDK_VERSION,
|
|
935
1027
|
TurnFailedError,
|
|
936
1028
|
TurnTimeoutError
|
|
937
1029
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent-server.ts","../src/errors.ts","../src/logger.ts","../src/platform-connection.ts","../src/protocol.ts","../src/ws-transport.ts","../src/reflect.ts","../src/session-mcp.ts","../src/turn-gate.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { InMemoryTransport } from \"@modelcontextprotocol/sdk/inMemory.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { ConnectionLostError, TurnFailedError } from \"./errors.js\";\nimport type { Logger } from \"./logger.js\";\nimport { log } from \"./logger.js\";\nimport { PlatformConnection } from \"./platform-connection.js\";\nimport {\n DEFAULT_AGENT_INSTRUCTIONS,\n assertNever,\n type Envelope,\n type TurnReport,\n} from \"./protocol.js\";\nimport { reflectPlayer } from \"./reflect.js\";\nimport { createSessionMcpServer } from \"./session-mcp.js\";\nimport { TurnGate } from \"./turn-gate.js\";\nimport type {\n AgentEvent,\n AgentHandle,\n AgentServerOptions,\n EventListener,\n InlinePlatform,\n StartOptions,\n TurnOptions,\n TurnResult,\n} from \"./types.js\";\nimport { SessionMuxTransport } from \"./ws-transport.js\";\n\nconst DEFAULT_TURN_TIMEOUT_MS = 60_000;\nconst DEFAULT_PLATFORM_URL = \"ws://127.0.0.1:8787\";\n\ntype SessionRecord = {\n id: string;\n token: string;\n name: string;\n gate: TurnGate;\n server: McpServer;\n transport: Transport;\n mux?: SessionMuxTransport;\n listeners: Set<EventListener>;\n};\n\n/**\n * One in-process MCP server and one outbound connection to the platform.\n * Every `start()` is its own session and token. The game calls `turn()` to\n * decide whose turn it is; the platform chooses the action.\n */\nexport class AgentServer {\n private readonly options: AgentServerOptions;\n private readonly platformKey: string;\n private readonly platformUrl: string;\n private readonly logger: Logger | undefined;\n private connection: PlatformConnection | null = null;\n private readonly sessions = new Map<string, SessionRecord>();\n private readonly listeners = new Set<EventListener>();\n private readonly inline: InlinePlatform | undefined;\n private started = false;\n private closing = false;\n\n constructor(options: AgentServerOptions = {}) {\n const platformKey = options.platformKey ?? process.env.WSI_PLATFORM_KEY;\n if (!options.inline && !platformKey) {\n throw new Error(\"Set WSI_PLATFORM_KEY or pass platformKey, unless an inline platform is provided\");\n }\n this.options = options;\n this.platformKey = platformKey || \"inline\";\n this.platformUrl = options.platformUrl ?? process.env.WSI_PLATFORM_URL ?? DEFAULT_PLATFORM_URL;\n this.logger = options.logger;\n this.inline = options.inline;\n if (options.onEvent) this.listeners.add(options.onEvent);\n }\n\n /** Ensure the outbound platform connection. No-op for an inline platform. */\n async connect(): Promise<void> {\n if (this.inline || this.started) {\n this.started = true;\n return;\n }\n this.connection = new PlatformConnection(this.platformUrl, this.platformKey, {\n onEnvelope: (envelope) => this.handleEnvelope(envelope),\n onDisconnect: () => this.emit({ type: \"disconnected\" }),\n onReconnect: () => this.emit({ type: \"reconnected\" }),\n onError: (error) => {\n log(this.logger, \"error\", error.message);\n if (error instanceof ConnectionLostError) this.failInflight(error);\n },\n sessions: () => [...this.sessions.values()].map((session) => ({\n sessionId: session.id,\n sessionToken: session.token,\n })),\n }, this.logger);\n await this.connection.connect();\n this.started = true;\n }\n\n /**\n * Reflect the player into tools, register a session, and return a handle.\n * `turn()` on that handle lets the remote model act once.\n */\n async start(instance: object, options?: StartOptions): Promise<AgentHandle> {\n await this.connect();\n\n const reflected = reflectPlayer(instance);\n const sessionId = randomUUID();\n const sessionToken = randomUUID();\n const gate = new TurnGate();\n const name = options?.name ?? instance.constructor?.name ?? \"player\";\n const server = createSessionMcpServer(reflected, gate, {\n name: `agent-player:${name}`,\n });\n const instructions = [this.options.instructions ?? DEFAULT_AGENT_INSTRUCTIONS, options?.instructions]\n .filter((part): part is string => Boolean(part && part.length > 0))\n .join(\"\\n\\n\");\n\n const listeners = new Set<EventListener>();\n const record: SessionRecord = {\n id: sessionId,\n token: sessionToken,\n name,\n gate,\n server,\n transport: undefined as unknown as Transport,\n listeners,\n };\n\n const onTurnResult = (result: TurnReport) => {\n gate.completeTurn(result);\n };\n const onEvent = (event: AgentEvent) => this.emit(event);\n\n if (this.inline) {\n const [serverTransport, clientTransport] = InMemoryTransport.createLinkedPair();\n await server.connect(serverTransport);\n record.transport = serverTransport;\n this.sessions.set(sessionId, record);\n await this.inline.startSession({\n sessionId,\n sessionToken,\n name,\n tools: reflected.tools,\n instructions,\n ...(options?.goal ? { goal: options.goal } : {}),\n ...(this.logger ? { logger: this.logger } : {}),\n transport: clientTransport,\n onTurnResult,\n onEvent,\n });\n } else {\n if (!this.connection) throw new Error(\"Not connected\");\n const mux = this.connection.createTransport(sessionId);\n await server.connect(mux);\n record.transport = mux;\n record.mux = mux;\n this.sessions.set(sessionId, record);\n const started = this.connection.waitForSessionEvent(sessionId, \"start\");\n this.connection.send({\n type: \"start_session\",\n sessionId,\n sessionToken,\n name,\n tools: reflected.tools,\n instructions,\n ...(options?.goal ? { goal: options.goal } : {}),\n });\n await started;\n }\n\n return {\n sessionId,\n turn: (turnOptions?: TurnOptions) => this.turn(sessionId, turnOptions),\n stop: () => this.stopSession(sessionId),\n on: (listener: EventListener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n }\n\n /** Subscribe to every session plus connection events. Returns unsubscribe. */\n on(listener: EventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private async turn(sessionId: string, options?: TurnOptions): Promise<TurnResult> {\n const session = this.sessions.get(sessionId);\n if (!session) throw new Error(`Unknown session ${sessionId}`);\n const timeoutMs = options?.timeoutMs ?? this.options.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;\n let outcome: TurnReport;\n try {\n outcome = await session.gate.runTurn({\n timeoutMs,\n ...(options?.signal ? { signal: options.signal } : {}),\n });\n } catch (error) {\n if (error instanceof ConnectionLostError) throw error;\n throw error;\n }\n if (!outcome.ok) {\n if (outcome.connectionLost) {\n throw new ConnectionLostError(outcome.error ?? \"Connection to the platform was lost\");\n }\n throw new TurnFailedError(outcome.error ?? \"turn failed\", outcome.attemptDetails ?? []);\n }\n return {\n action: outcome.action ?? \"unknown\",\n args: outcome.args ?? {},\n result: outcome.result,\n attempts: outcome.attempts ?? 1,\n usage: outcome.usage ?? { promptTokens: 0, completionTokens: 0 },\n };\n }\n\n private emit(event: AgentEvent): void {\n for (const listener of this.listeners) listener(event);\n if (event.type === \"disconnected\" || event.type === \"reconnected\") return;\n const session = this.sessions.get(event.sessionId);\n if (!session) return;\n for (const listener of session.listeners) listener(event);\n }\n\n private failInflight(error: ConnectionLostError): void {\n for (const session of this.sessions.values()) {\n session.gate.failTurn(error);\n }\n }\n\n private handleEnvelope(envelope: Envelope): void {\n switch (envelope.type) {\n case \"mcp\": {\n const session = this.sessions.get(envelope.sessionId);\n session?.mux?.receive(envelope.message);\n return;\n }\n case \"turn_result\": {\n const session = this.sessions.get(envelope.sessionId);\n session?.gate.completeTurn(envelope);\n return;\n }\n case \"session_event\": {\n if (envelope.event === \"action\") {\n this.emit({\n type: \"action\",\n sessionId: envelope.sessionId,\n action: envelope.action ?? \"unknown\",\n args: envelope.args ?? {},\n });\n return;\n }\n if (envelope.event === \"retry\") {\n this.emit({\n type: \"retry\",\n sessionId: envelope.sessionId,\n action: envelope.action ?? \"unknown\",\n args: envelope.args ?? {},\n error: envelope.error ?? \"action failed\",\n });\n return;\n }\n this.emit({\n type: \"turnFailed\",\n sessionId: envelope.sessionId,\n error: envelope.error ?? \"turn failed\",\n ...(envelope.action ? { action: envelope.action } : {}),\n ...(envelope.args ? { args: envelope.args } : {}),\n });\n return;\n }\n case \"error\":\n log(this.logger, \"error\", envelope.message);\n return;\n case \"session_started\":\n case \"session_stopped\":\n case \"session_resumed\":\n case \"resume_err\":\n case \"hello_ok\":\n case \"hello_err\":\n case \"hello\":\n case \"start_session\":\n case \"stop_session\":\n case \"ping\":\n case \"pong\":\n case \"resume_session\":\n return;\n default: {\n assertNever(envelope);\n }\n }\n }\n\n private async stopSession(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (!session) return;\n this.sessions.delete(sessionId);\n session.gate.reset();\n\n if (this.inline) {\n await this.inline.stopSession(sessionId);\n } else if (this.connection) {\n const stopped = this.connection.waitForSessionEvent(sessionId, \"stop\").catch(() => null);\n try {\n this.connection.send({ type: \"stop_session\", sessionId });\n } catch {\n // connection may already be down\n }\n await stopped;\n }\n\n try {\n await session.server.close();\n } catch {\n // ignore\n }\n }\n\n /** Stop every session and close the platform connection. */\n async close(): Promise<void> {\n if (this.closing) return;\n this.closing = true;\n const ids = [...this.sessions.keys()];\n for (const id of ids) {\n await this.stopSession(id);\n }\n if (this.inline?.close) await this.inline.close();\n if (this.connection) {\n await this.connection.close();\n this.connection = null;\n }\n this.started = false;\n this.closing = false;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n","import type { AttemptRecord } from \"./protocol.js\";\n\nexport class PlatformAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PlatformAuthError\";\n }\n}\n\nexport class ProtocolVersionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ProtocolVersionError\";\n }\n}\n\nexport class TurnFailedError extends Error {\n readonly attempts: AttemptRecord[];\n\n constructor(message: string, attempts: AttemptRecord[] = []) {\n super(message);\n this.name = \"TurnFailedError\";\n this.attempts = attempts;\n }\n}\n\nexport class TurnTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TurnTimeoutError\";\n }\n}\n\nexport class ConnectionLostError extends Error {\n constructor(message = \"Connection to the platform was lost\") {\n super(message);\n this.name = \"ConnectionLostError\";\n }\n}\n","export type Logger = {\n debug?: (message: string, extra?: unknown) => void;\n info?: (message: string, extra?: unknown) => void;\n warn?: (message: string, extra?: unknown) => void;\n error?: (message: string, extra?: unknown) => void;\n};\n\nexport function log(logger: Logger | undefined, level: keyof Logger, message: string, extra?: unknown): void {\n logger?.[level]?.(message, extra);\n}\n","import { randomUUID } from \"node:crypto\";\nimport WebSocket from \"ws\";\nimport { ConnectionLostError, PlatformAuthError, ProtocolVersionError } from \"./errors.js\";\nimport type { Logger } from \"./logger.js\";\nimport { log } from \"./logger.js\";\nimport {\n PROTOCOL_VERSION,\n SDK_VERSION,\n SESSION_RESUME_GRACE_MS,\n type Envelope,\n} from \"./protocol.js\";\nimport { SessionMuxTransport } from \"./ws-transport.js\";\n\nexport type ResumableSession = {\n sessionId: string;\n sessionToken: string;\n};\n\nexport type PlatformConnectionHandlers = {\n onEnvelope: (envelope: Envelope) => void;\n onDisconnect?: () => void;\n onReconnect?: () => void;\n onError?: (error: Error) => void;\n sessions?: () => ResumableSession[];\n};\n\nconst HEARTBEAT_MS = 15_000;\nconst PONG_TIMEOUT_MS = 10_000;\nconst MAX_RECONNECT_ATTEMPTS = 8;\n\n/**\n * Outbound WebSocket to the platform. The game never listens on a public URL.\n * After the first successful hello, a dropped socket reconnects and resumes sessions.\n */\nexport class PlatformConnection {\n private ws: WebSocket | null = null;\n private readonly url: string;\n private readonly platformKey: string;\n readonly clientId = randomUUID();\n private readonly handlers: PlatformConnectionHandlers;\n private readonly logger: Logger | undefined;\n private readonly pending = new Map<\n string,\n { resolve: (envelope: Envelope) => void; reject: (error: Error) => void }\n >();\n private readonly outbox: Envelope[] = [];\n private accountName: string | null = null;\n private closed = false;\n private everConnected = false;\n private reconnecting = false;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private heartbeat: ReturnType<typeof setInterval> | undefined;\n private pongTimer: ReturnType<typeof setTimeout> | undefined;\n private pendingPong: string | null = null;\n\n constructor(\n url: string,\n platformKey: string,\n handlers: PlatformConnectionHandlers,\n logger?: Logger,\n ) {\n this.url = url;\n this.platformKey = platformKey;\n this.handlers = handlers;\n this.logger = logger;\n }\n\n get connected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n async connect(): Promise<string> {\n if (this.closed) throw new Error(\"Platform connection is closed\");\n if (this.connected && this.accountName) return this.accountName;\n const account = await this.openSocket();\n this.everConnected = true;\n this.reconnectAttempt = 0;\n return account;\n }\n\n send(envelope: Envelope): void {\n if (this.connected && this.ws) {\n this.ws.send(JSON.stringify(envelope));\n return;\n }\n if (envelope.type === \"mcp\" || envelope.type === \"ping\") {\n this.outbox.push(envelope);\n return;\n }\n throw new Error(\"Not connected to platform\");\n }\n\n waitForSessionEvent(\n sessionId: string,\n kind: \"start\" | \"stop\" | \"resume\",\n timeoutMs = 15_000,\n ): Promise<Envelope> {\n const key = `session:${sessionId}:${kind}`;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(key);\n reject(new Error(`Timed out waiting for session ${kind}`));\n }, timeoutMs);\n this.pending.set(key, {\n resolve: (envelope) => {\n clearTimeout(timer);\n resolve(envelope);\n },\n reject: (error) => {\n clearTimeout(timer);\n reject(error);\n },\n });\n });\n }\n\n createTransport(sessionId: string): SessionMuxTransport {\n return new SessionMuxTransport(sessionId, (envelope) => this.send(envelope));\n }\n\n async close(): Promise<void> {\n this.closed = true;\n this.stopHeartbeat();\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n this.reconnecting = false;\n this.failWaiters(new Error(\"platform connection closed\"));\n if (!this.ws) return;\n const ws = this.ws;\n this.ws = null;\n await new Promise<void>((resolve) => {\n ws.once(\"close\", () => resolve());\n ws.close();\n });\n }\n\n private openSocket(): Promise<string> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(this.url);\n this.ws = ws;\n let settled = false;\n\n const fail = (error: Error) => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n\n ws.on(\"open\", () => {\n ws.send(JSON.stringify({\n type: \"hello\",\n platformKey: this.platformKey,\n clientId: this.clientId,\n protocolVersion: PROTOCOL_VERSION,\n sdkVersion: SDK_VERSION,\n } satisfies Envelope));\n });\n\n ws.on(\"message\", (data) => {\n let envelope: Envelope;\n try {\n envelope = JSON.parse(data.toString()) as Envelope;\n } catch (error) {\n const parsed = error instanceof Error ? error : new Error(\"Invalid platform message\");\n this.handlers.onError?.(parsed);\n return;\n }\n\n if (!settled && (envelope.type === \"hello_ok\" || envelope.type === \"hello_err\")) {\n settled = true;\n if (envelope.type === \"hello_err\") {\n const error = envelope.code === \"PROTOCOL\"\n ? new ProtocolVersionError(envelope.message)\n : new PlatformAuthError(envelope.message);\n this.closed = true;\n reject(error);\n ws.close();\n return;\n }\n this.accountName = envelope.accountName;\n this.startHeartbeat();\n this.flushOutbox();\n resolve(envelope.accountName);\n return;\n }\n\n if (envelope.type === \"pong\") {\n if (this.pendingPong === envelope.id) {\n this.pendingPong = null;\n if (this.pongTimer) clearTimeout(this.pongTimer);\n this.pongTimer = undefined;\n }\n return;\n }\n\n this.resolveSessionWaiter(envelope);\n this.handlers.onEnvelope(envelope);\n });\n\n ws.on(\"error\", (error) => {\n this.handlers.onError?.(error);\n fail(error);\n });\n\n ws.on(\"close\", () => {\n this.stopHeartbeat();\n if (this.ws === ws) this.ws = null;\n if (!settled) fail(new Error(\"platform connection closed before hello\"));\n if (this.closed || !this.everConnected) {\n this.failWaiters(new Error(\"platform connection closed\"));\n return;\n }\n this.handlers.onDisconnect?.();\n this.scheduleReconnect();\n });\n });\n }\n\n private resolveSessionWaiter(envelope: Envelope): void {\n if (envelope.type === \"session_started\" || envelope.type === \"session_stopped\") {\n const kind = envelope.type === \"session_started\" ? \"start\" : \"stop\";\n const waiter = this.pending.get(`session:${envelope.sessionId}:${kind}`);\n if (!waiter) return;\n this.pending.delete(`session:${envelope.sessionId}:${kind}`);\n waiter.resolve(envelope);\n return;\n }\n if (envelope.type === \"session_resumed\" || envelope.type === \"resume_err\") {\n const waiter = this.pending.get(`session:${envelope.sessionId}:resume`);\n if (!waiter) return;\n this.pending.delete(`session:${envelope.sessionId}:resume`);\n if (envelope.type === \"resume_err\") {\n waiter.reject(new ConnectionLostError(envelope.message));\n return;\n }\n waiter.resolve(envelope);\n }\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnecting) return;\n if (this.reconnectAttempt >= MAX_RECONNECT_ATTEMPTS) {\n this.closed = true;\n const error = new ConnectionLostError(\"Could not reconnect to the platform\");\n this.handlers.onError?.(error);\n this.failWaiters(error);\n return;\n }\n const delay = Math.min(SESSION_RESUME_GRACE_MS, 250 * 2 ** this.reconnectAttempt);\n this.reconnectAttempt += 1;\n this.reconnecting = true;\n log(this.logger, \"warn\", `platform connection dropped; retrying in ${delay}ms`);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n void this.reconnect();\n }, delay);\n this.reconnectTimer.unref?.();\n }\n\n private async reconnect(): Promise<void> {\n try {\n await this.openSocket();\n this.everConnected = true;\n this.reconnectAttempt = 0;\n this.reconnecting = false;\n const sessions = this.handlers.sessions?.() ?? [];\n for (const session of sessions) {\n const resumed = this.waitForSessionEvent(session.sessionId, \"resume\");\n this.send({\n type: \"resume_session\",\n sessionId: session.sessionId,\n sessionToken: session.sessionToken,\n });\n await resumed;\n }\n this.handlers.onReconnect?.();\n } catch (error) {\n this.reconnecting = false;\n if (this.closed) return;\n const wrapped = error instanceof Error ? error : new Error(String(error));\n if (wrapped instanceof PlatformAuthError || wrapped instanceof ProtocolVersionError) {\n this.closed = true;\n this.handlers.onError?.(wrapped);\n this.failWaiters(wrapped);\n return;\n }\n this.scheduleReconnect();\n }\n }\n\n private flushOutbox(): void {\n if (!this.ws || !this.connected) return;\n const pending = this.outbox.splice(0, this.outbox.length);\n for (const envelope of pending) {\n this.ws.send(JSON.stringify(envelope));\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeat = setInterval(() => {\n if (!this.connected) return;\n const id = randomUUID();\n this.pendingPong = id;\n try {\n this.send({ type: \"ping\", id });\n } catch {\n return;\n }\n this.pongTimer = setTimeout(() => {\n if (this.pendingPong === id) {\n log(this.logger, \"warn\", \"platform heartbeat timed out\");\n this.ws?.terminate();\n }\n }, PONG_TIMEOUT_MS);\n this.pongTimer.unref?.();\n }, HEARTBEAT_MS);\n this.heartbeat.unref?.();\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeat) clearInterval(this.heartbeat);\n if (this.pongTimer) clearTimeout(this.pongTimer);\n this.heartbeat = undefined;\n this.pongTimer = undefined;\n this.pendingPong = null;\n }\n\n private failWaiters(error: Error): void {\n for (const [, waiter] of this.pending) waiter.reject(error);\n this.pending.clear();\n }\n}\n","/** Wire protocol between AgentServer (SDK) and agent-platform. Version 1. */\n\nexport const PROTOCOL_VERSION = 1;\nexport const SDK_VERSION = \"0.1.0\";\n\n/** How long a disconnected session can be resumed. Shared by both sides. */\nexport const SESSION_RESUME_GRACE_MS = 30_000;\n\nexport type JsonSchema = {\n type?: string | string[];\n properties?: Record<string, JsonSchema>;\n required?: string[];\n description?: string;\n additionalProperties?: boolean;\n [key: string]: unknown;\n};\n\nexport type ToolDescriptor = {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n};\n\nexport type TokenUsage = {\n promptTokens: number;\n completionTokens: number;\n};\n\nexport type AttemptRecord = {\n action: string;\n args: Record<string, unknown>;\n error: string;\n};\n\nexport type TurnReport = {\n ok: boolean;\n error?: string;\n action?: string;\n args?: Record<string, unknown>;\n result?: unknown;\n attempts?: number;\n attemptDetails?: AttemptRecord[];\n usage?: TokenUsage;\n connectionLost?: boolean;\n};\n\nexport type SessionEventName = \"action\" | \"retry\" | \"turnFailed\";\n\nexport type Envelope =\n | {\n type: \"hello\";\n platformKey: string;\n clientId: string;\n protocolVersion: number;\n sdkVersion: string;\n }\n | {\n type: \"hello_ok\";\n accountName: string;\n protocolVersion: number;\n }\n | {\n type: \"hello_err\";\n message: string;\n code?: \"AUTH\" | \"PROTOCOL\";\n }\n | {\n type: \"start_session\";\n sessionId: string;\n sessionToken: string;\n tools: ToolDescriptor[];\n instructions: string;\n goal?: string;\n name?: string;\n }\n | {\n type: \"session_started\";\n sessionId: string;\n }\n | {\n type: \"stop_session\";\n sessionId: string;\n }\n | {\n type: \"session_stopped\";\n sessionId: string;\n }\n | {\n type: \"mcp\";\n sessionId: string;\n message: unknown;\n }\n | ({\n type: \"turn_result\";\n sessionId: string;\n } & TurnReport)\n | {\n type: \"session_event\";\n sessionId: string;\n event: SessionEventName;\n action?: string;\n args?: Record<string, unknown>;\n error?: string;\n }\n | {\n type: \"ping\";\n id: string;\n }\n | {\n type: \"pong\";\n id: string;\n }\n | {\n type: \"resume_session\";\n sessionId: string;\n sessionToken: string;\n }\n | {\n type: \"session_resumed\";\n sessionId: string;\n }\n | {\n type: \"resume_err\";\n sessionId: string;\n message: string;\n }\n | {\n type: \"error\";\n message: string;\n sessionId?: string;\n };\n\nexport const DEFAULT_AGENT_INSTRUCTIONS = [\n \"You are a remote game agent. Tools are provided by the game.\",\n \"On every turn: call wait first. It blocks until the game grants your turn and then returns the current view from see.\",\n \"After wait returns, call exactly one action tool (not see, not wait).\",\n \"If an action tool returns an error, retry once with a corrected action. A second failure ends the turn as failed.\",\n].join(\"\\n\");\n\nexport function assertNever(value: never): never {\n throw new Error(`Unhandled protocol message: ${JSON.stringify(value)}`);\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Envelope } from \"./protocol.js\";\n\nexport type EnvelopeSender = (envelope: Envelope) => void;\n\n/**\n * MCP Transport that multiplexes JSON-RPC over a shared envelope channel,\n * keyed by sessionId.\n */\nexport class SessionMuxTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n private readonly sid: string;\n private readonly sendEnvelope: EnvelopeSender;\n private started = false;\n private closed = false;\n\n constructor(sessionId: string, sendEnvelope: EnvelopeSender) {\n this.sid = sessionId;\n this.sessionId = sessionId;\n this.sendEnvelope = sendEnvelope;\n }\n\n async start(): Promise<void> {\n if (this.closed) throw new Error(\"Transport already closed\");\n this.started = true;\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.onclose?.();\n }\n\n async send(message: JSONRPCMessage): Promise<void> {\n if (this.closed) throw new Error(\"Transport closed\");\n this.sendEnvelope({ type: \"mcp\", sessionId: this.sid, message });\n }\n\n /** Deliver an inbound MCP message from the platform. */\n receive(message: unknown): void {\n if (this.closed || !this.started) return;\n try {\n this.onmessage?.(message as JSONRPCMessage);\n } catch (error) {\n this.onerror?.(error instanceof Error ? error : new Error(String(error)));\n }\n }\n}\n","import { z, type ZodRawShape, type ZodTypeAny } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport type { JsonSchema, ToolDescriptor } from \"./protocol.js\";\n\nexport type ActionSpec = {\n description: string;\n args?: ZodRawShape;\n};\n\nexport type AgentMetadata = {\n description?: string;\n actions?: Record<string, ActionSpec>;\n};\n\nexport type PlayerTool = {\n name: string;\n description: string;\n paramNames: string[];\n argsSchema?: z.ZodObject<ZodRawShape>;\n descriptor: ToolDescriptor;\n invoke: (args: Record<string, unknown>) => Promise<unknown>;\n};\n\nexport type ReflectedPlayer = {\n /** Class-level description, when the player declared `static agent`. */\n description?: string;\n see: PlayerTool;\n actions: PlayerTool[];\n tools: ToolDescriptor[];\n};\n\nconst SKIP = new Set([\"constructor\"]);\n\nexport const SEE_DESCRIPTION = \"Read the current game view for this player. Prefer wait, which returns this after the game grants a turn.\";\nexport const WAIT_DESCRIPTION = \"Block until the game calls turn() for this session, then return the current see() view.\";\n\n/** Parse parameter names from a function's source. Used only when no arg schema is declared. */\nexport function getParamNames(fn: (...args: never[]) => unknown): string[] {\n const src = fn.toString().replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/\\/\\/.*$/gm, \"\");\n const header =\n src.match(/(?:async\\s+)?(?:function\\s*)?(?:\\w*)\\s*\\(([^)]*)\\)/) ??\n src.match(/^(?:async\\s*)?\\(?([^)=]*)\\)?\\s*=>/);\n if (!header) return [];\n const raw = header[1]?.trim() ?? \"\";\n if (!raw) return [];\n return raw\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => {\n const cleaned = part.replace(/\\s*=\\s*[^,]+$/, \"\").trim();\n const name = cleaned.split(/[:\\s]/)[0]?.replace(/^\\.\\.\\./, \"\") ?? \"\";\n return name;\n })\n .filter((name) => name.length > 0 && name !== \"this\");\n}\n\nfunction collectMethodNames(instance: object): string[] {\n const names = new Set<string>();\n let proto: object | null = Object.getPrototypeOf(instance);\n while (proto && proto !== Object.prototype) {\n for (const name of Object.getOwnPropertyNames(proto)) {\n if (SKIP.has(name) || name.startsWith(\"_\")) continue;\n const desc = Object.getOwnPropertyDescriptor(proto, name);\n if (!desc || typeof desc.value !== \"function\") continue;\n names.add(name);\n }\n proto = Object.getPrototypeOf(proto);\n }\n return [...names].sort();\n}\n\nfunction readMetadata(instance: object): AgentMetadata | undefined {\n const ctor = instance.constructor as { agent?: AgentMetadata };\n return ctor.agent;\n}\n\nfunction toJsonSchema(schema: ZodTypeAny): JsonSchema {\n const json = zodToJsonSchema(schema, { target: \"jsonSchema7\", $refStrategy: \"none\" }) as JsonSchema;\n delete json.$schema;\n return json;\n}\n\nfunction formatZodError(error: z.ZodError): string {\n return error.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"arguments\";\n return `${path}: ${issue.message}`;\n })\n .join(\"; \");\n}\n\nfunction buildTool(\n instance: object,\n name: string,\n description: string,\n spec?: ActionSpec,\n): PlayerTool {\n const fn = (instance as Record<string, unknown>)[name];\n if (typeof fn !== \"function\") {\n throw new Error(`Expected method ${name}`);\n }\n const paramNames = spec?.args ? Object.keys(spec.args) : getParamNames(fn as (...args: never[]) => unknown);\n const shape: ZodRawShape = spec?.args ?? Object.fromEntries(paramNames.map((param) => [param, z.any()]));\n const argsSchema = paramNames.length > 0 || spec?.args ? z.object(shape) : undefined;\n const inputSchema: JsonSchema = spec?.args && argsSchema\n ? toJsonSchema(argsSchema)\n : {\n type: \"object\",\n properties: Object.fromEntries(paramNames.map((param) => [param, {}])),\n ...(paramNames.length > 0 ? { required: paramNames } : {}),\n };\n\n return {\n name,\n description,\n paramNames,\n ...(argsSchema ? { argsSchema } : {}),\n descriptor: { name, description, inputSchema },\n async invoke(args: Record<string, unknown>) {\n let parsed: Record<string, unknown> = args ?? {};\n if (argsSchema) {\n const result = argsSchema.safeParse(args ?? {});\n if (!result.success) {\n throw new Error(formatZodError(result.error));\n }\n parsed = result.data as Record<string, unknown>;\n }\n const ordered = paramNames.map((param) => parsed[param]);\n return await Promise.resolve((fn as (...params: unknown[]) => unknown).apply(instance, ordered));\n },\n };\n}\n\n/**\n * Publish tools from a player instance.\n * - `see` is the state tool (required).\n * - Every other public method is an action tool.\n * - Names starting with `_` and the constructor are skipped.\n * - `static agent` supplies descriptions and zod argument schemas. Undeclared methods stay tools,\n * with unconstrained JSON arguments (no type guessed from the parameter name).\n */\nexport function reflectPlayer(instance: object): ReflectedPlayer {\n const names = collectMethodNames(instance);\n if (!names.includes(\"see\")) {\n throw new Error(\"Player must implement a public see() method\");\n }\n\n const metadata = readMetadata(instance);\n const declared = metadata?.actions ?? {};\n const className = instance.constructor?.name || \"Player\";\n for (const name of Object.keys(declared)) {\n if (!names.includes(name) || name === \"see\") {\n throw new Error(`Declared action \"${name}\" is not a public method on ${className}`);\n }\n }\n\n const see = buildTool(instance, \"see\", SEE_DESCRIPTION);\n const actionNames = names.filter((name) => name !== \"see\");\n const actions = actionNames.map((name) => {\n const spec = declared[name];\n const description = spec?.description ?? `Action: ${name}`;\n return buildTool(instance, name, description, spec);\n });\n\n const wait: ToolDescriptor = {\n name: \"wait\",\n description: WAIT_DESCRIPTION,\n inputSchema: { type: \"object\", properties: {} },\n };\n\n return {\n ...(metadata?.description ? { description: metadata.description } : {}),\n see,\n actions,\n tools: [see.descriptor, ...actions.map((action) => action.descriptor), wait],\n };\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ReflectedPlayer } from \"./reflect.js\";\nimport { WAIT_DESCRIPTION } from \"./reflect.js\";\nimport type { TurnGate } from \"./turn-gate.js\";\nimport { SDK_VERSION } from \"./protocol.js\";\n\nfunction jsonResult(payload: unknown, isError = false) {\n return {\n isError,\n content: [{ type: \"text\" as const, text: JSON.stringify(payload) }],\n };\n}\n\nfunction toolError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return jsonResult({ error: message }, true);\n}\n\n/**\n * Build an in-process MCP server for one player session.\n * Tools come from one definition: see, wait, and every public action.\n */\nexport function createSessionMcpServer(\n player: ReflectedPlayer,\n gate: TurnGate,\n options?: { name?: string },\n): McpServer {\n const server = new McpServer(\n { name: options?.name ?? \"agent-player\", version: SDK_VERSION },\n { capabilities: { tools: {} } },\n );\n\n server.registerTool(\n \"see\",\n { description: player.see.description },\n async () => {\n try {\n const view = await player.see.invoke({});\n return jsonResult(view);\n } catch (error) {\n return toolError(error);\n }\n },\n );\n\n server.registerTool(\n \"wait\",\n { description: WAIT_DESCRIPTION },\n async () => {\n try {\n await gate.waitForTurn();\n const view = await player.see.invoke({});\n return jsonResult(view);\n } catch (error) {\n return toolError(error);\n }\n },\n );\n\n for (const action of player.actions) {\n const handler = async (args: Record<string, unknown>) => {\n try {\n const result = await action.invoke(args);\n return jsonResult(result ?? { ok: true });\n } catch (error) {\n return toolError(error);\n }\n };\n\n if (action.argsSchema) {\n server.registerTool(\n action.name,\n {\n description: action.description,\n inputSchema: action.argsSchema.shape,\n },\n async (args) => handler(args as Record<string, unknown>),\n );\n } else {\n server.registerTool(\n action.name,\n { description: action.description },\n async () => handler({}),\n );\n }\n }\n\n return server;\n}\n","import { TurnTimeoutError } from \"./errors.js\";\nimport type { TurnReport } from \"./protocol.js\";\n\nexport type TurnOutcome = TurnReport;\n\nfunction abortError(signal: AbortSignal): Error {\n const reason: unknown = signal.reason;\n if (reason instanceof Error) return reason;\n if (typeof reason === \"string\" && reason.length > 0) return new Error(reason);\n return new Error(\"turn aborted\");\n}\n\n/**\n * Coordinates game-side turn() with the agent's wait tool.\n * turn() releases wait, then resolves when the platform reports the turn finished.\n */\nexport class TurnGate {\n private waitResolve: (() => void) | null = null;\n private waitPromise: Promise<void> | null = null;\n private turnResolve: ((result: TurnOutcome) => void) | null = null;\n private turnReject: ((error: Error) => void) | null = null;\n private turnPromise: Promise<TurnOutcome> | null = null;\n private released = false;\n\n /** Called by the wait tool. Blocks until turn() releases this session. */\n async waitForTurn(): Promise<void> {\n if (this.released) {\n this.released = false;\n return;\n }\n if (!this.waitPromise) {\n this.waitPromise = new Promise<void>((resolve) => {\n this.waitResolve = resolve;\n });\n }\n await this.waitPromise;\n this.waitPromise = null;\n this.waitResolve = null;\n this.released = false;\n }\n\n /**\n * Unblock wait and wait for the platform's turn report.\n * Rejects on timeout or abort; those do not produce a TurnOutcome.\n */\n async runTurn(options?: { timeoutMs?: number; signal?: AbortSignal }): Promise<TurnOutcome> {\n if (this.turnPromise) {\n throw new Error(\"turn() already in progress for this session\");\n }\n if (options?.signal?.aborted) {\n throw abortError(options.signal);\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let onAbort: (() => void) | undefined;\n const signal = options?.signal;\n\n this.turnPromise = new Promise<TurnOutcome>((resolve, reject) => {\n this.turnResolve = resolve;\n this.turnReject = reject;\n if (options?.timeoutMs != null) {\n timeoutId = setTimeout(() => {\n this.rejectTurn(new TurnTimeoutError(`turn() timed out after ${options.timeoutMs}ms`));\n }, options.timeoutMs);\n }\n if (signal) {\n if (signal.aborted) {\n this.rejectTurn(abortError(signal));\n return;\n }\n onAbort = () => this.rejectTurn(abortError(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n });\n\n this.released = true;\n const release = this.waitResolve;\n this.waitResolve = null;\n this.waitPromise = null;\n release?.();\n\n try {\n return await this.turnPromise;\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n if (signal && onAbort) signal.removeEventListener(\"abort\", onAbort);\n this.turnPromise = null;\n this.turnResolve = null;\n this.turnReject = null;\n }\n }\n\n /** Platform finished one action cycle (success or second failure). */\n completeTurn(outcome: TurnOutcome): void {\n const resolve = this.turnResolve;\n if (!resolve) return;\n this.turnResolve = null;\n this.turnReject = null;\n resolve(outcome);\n }\n\n /** Fail an in-flight turn, for example when the connection cannot be resumed. */\n failTurn(error: Error): void {\n this.rejectTurn(error);\n }\n\n reset(): void {\n this.waitResolve?.();\n this.completeTurn({ ok: false, error: \"session stopped\" });\n this.waitResolve = null;\n this.waitPromise = null;\n this.released = false;\n }\n\n private rejectTurn(error: Error): void {\n const reject = this.turnReject;\n if (!reject) return;\n this.turnResolve = null;\n this.turnReject = null;\n reject(error);\n }\n}\n"],"mappings":"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","names":["randomUUID","randomUUID"]}
|
|
1
|
+
{"version":3,"sources":["../src/agent-server.ts","../src/errors.ts","../src/logger.ts","../src/memory.ts","../src/platform-connection.ts","../src/protocol.ts","../src/ws-transport.ts","../src/reflect.ts","../src/session-mcp.ts","../src/turn-gate.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { InMemoryTransport } from \"@modelcontextprotocol/sdk/inMemory.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { ConnectionLostError, TurnFailedError } from \"./errors.js\";\nimport type { Logger } from \"./logger.js\";\nimport { log } from \"./logger.js\";\nimport { defaultMemoryPath, SessionMemory } from \"./memory.js\";\nimport { PlatformConnection } from \"./platform-connection.js\";\nimport {\n DEFAULT_AGENT_INSTRUCTIONS,\n assertNever,\n type Envelope,\n type TurnReport,\n} from \"./protocol.js\";\nimport { reflectPlayer } from \"./reflect.js\";\nimport { createSessionMcpServer } from \"./session-mcp.js\";\nimport { TurnGate } from \"./turn-gate.js\";\nimport type {\n AgentEvent,\n AgentHandle,\n AgentServerOptions,\n EventListener,\n InlinePlatform,\n StartOptions,\n TurnOptions,\n TurnResult,\n} from \"./types.js\";\nimport { SessionMuxTransport } from \"./ws-transport.js\";\n\nconst DEFAULT_TURN_TIMEOUT_MS = 60_000;\nconst PLATFORM_URL = \"wss://api.whitesandsint.com\";\n\ntype SessionRecord = {\n id: string;\n token: string;\n name: string;\n gate: TurnGate;\n server: McpServer;\n transport: Transport;\n mux?: SessionMuxTransport;\n listeners: Set<EventListener>;\n};\n\n/**\n * One in-process MCP server and one outbound connection to the platform.\n * Every `start()` is its own session and token. The game calls `turn()` to\n * decide whose turn it is; the platform chooses the action.\n */\nexport class AgentServer {\n private readonly options: AgentServerOptions;\n private readonly platformKey: string;\n private readonly platformUrl: string;\n private readonly logger: Logger | undefined;\n private connection: PlatformConnection | null = null;\n private readonly sessions = new Map<string, SessionRecord>();\n private readonly listeners = new Set<EventListener>();\n private readonly inline: InlinePlatform | undefined;\n private memory: SessionMemory | null = null;\n private started = false;\n private closing = false;\n\n constructor(options: AgentServerOptions = {}) {\n const platformKey = options.platformKey ?? process.env.WSI_PLATFORM_KEY;\n if (!options.inline && !platformKey) {\n throw new Error(\"Set WSI_PLATFORM_KEY or pass platformKey, unless an inline platform is provided\");\n }\n this.options = options;\n this.platformKey = platformKey || \"inline\";\n this.platformUrl = options.platformUrl ?? PLATFORM_URL;\n this.logger = options.logger;\n this.inline = options.inline;\n if (options.onEvent) this.listeners.add(options.onEvent);\n }\n\n /** Ensure the outbound platform connection. No-op for an inline platform. */\n async connect(): Promise<void> {\n if (this.inline || this.started) {\n this.started = true;\n return;\n }\n this.connection = new PlatformConnection(this.platformUrl, this.platformKey, {\n onEnvelope: (envelope) => this.handleEnvelope(envelope),\n onDisconnect: () => this.emit({ type: \"disconnected\" }),\n onReconnect: () => this.emit({ type: \"reconnected\" }),\n onError: (error) => {\n log(this.logger, \"error\", error.message);\n if (error instanceof ConnectionLostError) this.failInflight(error);\n },\n sessions: () => [...this.sessions.values()].map((session) => ({\n sessionId: session.id,\n sessionToken: session.token,\n })),\n }, this.logger);\n await this.connection.connect();\n this.started = true;\n }\n\n /**\n * Reflect the player into tools, register a session, and return a handle.\n * `turn()` on that handle lets the remote model act once.\n */\n async start(instance: object, options?: StartOptions): Promise<AgentHandle> {\n await this.connect();\n\n const reflected = reflectPlayer(instance);\n const sessionId = randomUUID();\n const sessionToken = randomUUID();\n const gate = new TurnGate();\n const name = options?.name ?? instance.constructor?.name ?? \"player\";\n const memory = this.actionMemory();\n const server = createSessionMcpServer(reflected, gate, {\n name: `agent-player:${name}`,\n ...(memory\n ? {\n actions: {\n record: (entry) => memory.record(sessionId, name, entry),\n done: () => memory.done(sessionId),\n },\n }\n : {}),\n });\n const instructions = [this.options.instructions ?? DEFAULT_AGENT_INSTRUCTIONS, options?.instructions]\n .filter((part): part is string => Boolean(part && part.length > 0))\n .join(\"\\n\\n\");\n\n const listeners = new Set<EventListener>();\n const record: SessionRecord = {\n id: sessionId,\n token: sessionToken,\n name,\n gate,\n server,\n transport: undefined as unknown as Transport,\n listeners,\n };\n\n const onTurnResult = (result: TurnReport) => {\n gate.completeTurn(result);\n };\n const onEvent = (event: AgentEvent) => this.emit(event);\n\n if (this.inline) {\n const [serverTransport, clientTransport] = InMemoryTransport.createLinkedPair();\n await server.connect(serverTransport);\n record.transport = serverTransport;\n this.sessions.set(sessionId, record);\n await this.inline.startSession({\n sessionId,\n sessionToken,\n name,\n tools: reflected.tools,\n instructions,\n ...(options?.goal ? { goal: options.goal } : {}),\n ...(this.logger ? { logger: this.logger } : {}),\n transport: clientTransport,\n onTurnResult,\n onEvent,\n });\n } else {\n if (!this.connection) throw new Error(\"Not connected\");\n const mux = this.connection.createTransport(sessionId);\n await server.connect(mux);\n record.transport = mux;\n record.mux = mux;\n this.sessions.set(sessionId, record);\n const started = this.connection.waitForSessionEvent(sessionId, \"start\");\n this.connection.send({\n type: \"start_session\",\n sessionId,\n sessionToken,\n name,\n tools: reflected.tools,\n instructions,\n ...(options?.goal ? { goal: options.goal } : {}),\n });\n await started;\n }\n\n return {\n sessionId,\n turn: (turnOptions?: TurnOptions) => this.turn(sessionId, turnOptions),\n stop: () => this.stopSession(sessionId),\n on: (listener: EventListener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n }\n\n /** Subscribe to every session plus connection events. Returns unsubscribe. */\n on(listener: EventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private async turn(sessionId: string, options?: TurnOptions): Promise<TurnResult> {\n const session = this.sessions.get(sessionId);\n if (!session) throw new Error(`Unknown session ${sessionId}`);\n const timeoutMs = options?.timeoutMs ?? this.options.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;\n let outcome: TurnReport;\n try {\n outcome = await session.gate.runTurn({\n timeoutMs,\n ...(options?.signal ? { signal: options.signal } : {}),\n });\n } catch (error) {\n if (error instanceof ConnectionLostError) throw error;\n throw error;\n }\n if (!outcome.ok) {\n if (outcome.connectionLost) {\n throw new ConnectionLostError(outcome.error ?? \"Connection to the platform was lost\");\n }\n throw new TurnFailedError(outcome.error ?? \"turn failed\", outcome.attemptDetails ?? []);\n }\n return {\n action: outcome.action ?? \"unknown\",\n args: outcome.args ?? {},\n result: outcome.result,\n attempts: outcome.attempts ?? 1,\n usage: outcome.usage ?? { promptTokens: 0, completionTokens: 0 },\n };\n }\n\n private emit(event: AgentEvent): void {\n for (const listener of this.listeners) listener(event);\n if (event.type === \"disconnected\" || event.type === \"reconnected\") return;\n const session = this.sessions.get(event.sessionId);\n if (!session) return;\n for (const listener of session.listeners) listener(event);\n }\n\n private failInflight(error: ConnectionLostError): void {\n for (const session of this.sessions.values()) {\n session.gate.failTurn(error);\n }\n }\n\n private handleEnvelope(envelope: Envelope): void {\n switch (envelope.type) {\n case \"mcp\": {\n const session = this.sessions.get(envelope.sessionId);\n session?.mux?.receive(envelope.message);\n return;\n }\n case \"turn_result\": {\n const session = this.sessions.get(envelope.sessionId);\n session?.gate.completeTurn(envelope);\n return;\n }\n case \"session_event\": {\n if (envelope.event === \"action\") {\n this.emit({\n type: \"action\",\n sessionId: envelope.sessionId,\n action: envelope.action ?? \"unknown\",\n args: envelope.args ?? {},\n });\n return;\n }\n if (envelope.event === \"retry\") {\n this.emit({\n type: \"retry\",\n sessionId: envelope.sessionId,\n action: envelope.action ?? \"unknown\",\n args: envelope.args ?? {},\n error: envelope.error ?? \"action failed\",\n });\n return;\n }\n this.emit({\n type: \"turnFailed\",\n sessionId: envelope.sessionId,\n error: envelope.error ?? \"turn failed\",\n ...(envelope.action ? { action: envelope.action } : {}),\n ...(envelope.args ? { args: envelope.args } : {}),\n });\n return;\n }\n case \"error\":\n log(this.logger, \"error\", envelope.message);\n return;\n case \"session_started\":\n case \"session_stopped\":\n case \"session_resumed\":\n case \"resume_err\":\n case \"hello_ok\":\n case \"hello_err\":\n case \"hello\":\n case \"start_session\":\n case \"stop_session\":\n case \"ping\":\n case \"pong\":\n case \"resume_session\":\n return;\n default: {\n assertNever(envelope);\n }\n }\n }\n\n private async stopSession(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (!session) return;\n this.sessions.delete(sessionId);\n session.gate.reset();\n\n if (this.inline) {\n await this.inline.stopSession(sessionId);\n } else if (this.connection) {\n const stopped = this.connection.waitForSessionEvent(sessionId, \"stop\").catch(() => null);\n try {\n this.connection.send({ type: \"stop_session\", sessionId });\n } catch {\n // connection may already be down\n }\n await stopped;\n }\n\n try {\n await session.server.close();\n } catch {\n // ignore\n }\n }\n\n /** Stop every session and close the platform connection. */\n async close(): Promise<void> {\n if (this.closing) return;\n this.closing = true;\n const ids = [...this.sessions.keys()];\n for (const id of ids) {\n await this.stopSession(id);\n }\n if (this.inline?.close) await this.inline.close();\n if (this.connection) {\n await this.connection.close();\n this.connection = null;\n }\n this.memory?.close();\n this.memory = null;\n this.started = false;\n this.closing = false;\n }\n\n private actionMemory(): SessionMemory | null {\n if (this.options.memoryPath === false) return null;\n if (!this.memory) {\n const path = this.options.memoryPath ?? defaultMemoryPath();\n this.memory = new SessionMemory(path);\n }\n return this.memory;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n","import type { AttemptRecord } from \"./protocol.js\";\n\nexport class PlatformAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PlatformAuthError\";\n }\n}\n\nexport class ProtocolVersionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ProtocolVersionError\";\n }\n}\n\nexport class TurnFailedError extends Error {\n readonly attempts: AttemptRecord[];\n\n constructor(message: string, attempts: AttemptRecord[] = []) {\n super(message);\n this.name = \"TurnFailedError\";\n this.attempts = attempts;\n }\n}\n\nexport class TurnTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TurnTimeoutError\";\n }\n}\n\nexport class ConnectionLostError extends Error {\n constructor(message = \"Connection to the platform was lost\") {\n super(message);\n this.name = \"ConnectionLostError\";\n }\n}\n","export type Logger = {\n debug?: (message: string, extra?: unknown) => void;\n info?: (message: string, extra?: unknown) => void;\n warn?: (message: string, extra?: unknown) => void;\n error?: (message: string, extra?: unknown) => void;\n};\n\nexport function log(logger: Logger | undefined, level: keyof Logger, message: string, extra?: unknown): void {\n logger?.[level]?.(message, extra);\n}\n","import { mkdirSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport Database from \"better-sqlite3\";\n\n/** Actions kept on the view. Older rows stay in the file and drop off the prompt. */\nconst MAX_DONE = 50;\n\nexport type DoneAction = {\n action: string;\n args: Record<string, unknown>;\n ok: boolean;\n error?: string;\n};\n\ntype ActionRow = {\n action: string;\n args: string;\n ok: number;\n error: string | null;\n};\n\n/**\n * SQLite log of actions one game process has already called.\n * Each session reads only its own rows, so a new run starts with an empty list.\n */\nexport class SessionMemory {\n private readonly db: Database.Database;\n\n constructor(path: string) {\n mkdirSync(dirname(path), { recursive: true });\n this.db = new Database(path, { timeout: 5000 });\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS actions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n character TEXT NOT NULL,\n action TEXT NOT NULL,\n args TEXT NOT NULL,\n ok INTEGER NOT NULL,\n error TEXT\n );\n CREATE INDEX IF NOT EXISTS actions_by_session ON actions(session_id, id);\n `);\n }\n\n record(sessionId: string, character: string, entry: DoneAction): void {\n this.db\n .prepare(\n `INSERT INTO actions (session_id, character, action, args, ok, error)\n VALUES (@sessionId, @character, @action, @args, @ok, @error)`,\n )\n .run({\n sessionId,\n character,\n action: entry.action,\n args: JSON.stringify(entry.args),\n ok: entry.ok ? 1 : 0,\n error: entry.error ?? null,\n });\n }\n\n /** Oldest first, capped to the most recent actions for this session. */\n done(sessionId: string): DoneAction[] {\n const rows = this.db\n .prepare(\n `SELECT action, args, ok, error FROM (\n SELECT id, action, args, ok, error FROM actions\n WHERE session_id = ?\n ORDER BY id DESC\n LIMIT ?\n ) ORDER BY id ASC`,\n )\n .all(sessionId, MAX_DONE) as ActionRow[];\n return rows.map((row) => {\n const entry: DoneAction = {\n action: row.action,\n args: JSON.parse(row.args) as Record<string, unknown>,\n ok: row.ok === 1,\n };\n if (row.error) entry.error = row.error;\n return entry;\n });\n }\n\n close(): void {\n this.db.close();\n }\n}\n\nexport function defaultMemoryPath(): string {\n return resolve(process.cwd(), \".wsi\", \"agent-memory.sqlite\");\n}\n\n/** Attach this session's action log to a see() payload. */\nexport function viewWithDone(view: unknown, done: DoneAction[]): unknown {\n if (view && typeof view === \"object\" && !Array.isArray(view)) {\n return { ...(view as Record<string, unknown>), done };\n }\n return { view, done };\n}\n","import { randomUUID } from \"node:crypto\";\nimport WebSocket from \"ws\";\nimport { ConnectionLostError, PlatformAuthError, ProtocolVersionError } from \"./errors.js\";\nimport type { Logger } from \"./logger.js\";\nimport { log } from \"./logger.js\";\nimport {\n PROTOCOL_VERSION,\n SDK_VERSION,\n SESSION_RESUME_GRACE_MS,\n type Envelope,\n} from \"./protocol.js\";\nimport { SessionMuxTransport } from \"./ws-transport.js\";\n\nexport type ResumableSession = {\n sessionId: string;\n sessionToken: string;\n};\n\nexport type PlatformConnectionHandlers = {\n onEnvelope: (envelope: Envelope) => void;\n onDisconnect?: () => void;\n onReconnect?: () => void;\n onError?: (error: Error) => void;\n sessions?: () => ResumableSession[];\n};\n\nconst HEARTBEAT_MS = 15_000;\nconst PONG_TIMEOUT_MS = 10_000;\nconst MAX_RECONNECT_ATTEMPTS = 8;\n\n/**\n * Outbound WebSocket to the platform. The game never listens on a public URL.\n * After the first successful hello, a dropped socket reconnects and resumes sessions.\n */\nexport class PlatformConnection {\n private ws: WebSocket | null = null;\n private readonly url: string;\n private readonly platformKey: string;\n readonly clientId = randomUUID();\n private readonly handlers: PlatformConnectionHandlers;\n private readonly logger: Logger | undefined;\n private readonly pending = new Map<\n string,\n { resolve: (envelope: Envelope) => void; reject: (error: Error) => void }\n >();\n private readonly outbox: Envelope[] = [];\n private accountName: string | null = null;\n private closed = false;\n private everConnected = false;\n private reconnecting = false;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private heartbeat: ReturnType<typeof setInterval> | undefined;\n private pongTimer: ReturnType<typeof setTimeout> | undefined;\n private pendingPong: string | null = null;\n\n constructor(\n url: string,\n platformKey: string,\n handlers: PlatformConnectionHandlers,\n logger?: Logger,\n ) {\n this.url = url;\n this.platformKey = platformKey;\n this.handlers = handlers;\n this.logger = logger;\n }\n\n get connected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n async connect(): Promise<string> {\n if (this.closed) throw new Error(\"Platform connection is closed\");\n if (this.connected && this.accountName) return this.accountName;\n const account = await this.openSocket();\n this.everConnected = true;\n this.reconnectAttempt = 0;\n return account;\n }\n\n send(envelope: Envelope): void {\n if (this.connected && this.ws) {\n this.ws.send(JSON.stringify(envelope));\n return;\n }\n if (envelope.type === \"mcp\" || envelope.type === \"ping\") {\n this.outbox.push(envelope);\n return;\n }\n throw new Error(\"Not connected to platform\");\n }\n\n waitForSessionEvent(\n sessionId: string,\n kind: \"start\" | \"stop\" | \"resume\",\n timeoutMs = 15_000,\n ): Promise<Envelope> {\n const key = `session:${sessionId}:${kind}`;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(key);\n reject(new Error(`Timed out waiting for session ${kind}`));\n }, timeoutMs);\n this.pending.set(key, {\n resolve: (envelope) => {\n clearTimeout(timer);\n resolve(envelope);\n },\n reject: (error) => {\n clearTimeout(timer);\n reject(error);\n },\n });\n });\n }\n\n createTransport(sessionId: string): SessionMuxTransport {\n return new SessionMuxTransport(sessionId, (envelope) => this.send(envelope));\n }\n\n async close(): Promise<void> {\n this.closed = true;\n this.stopHeartbeat();\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n this.reconnecting = false;\n this.failWaiters(new Error(\"platform connection closed\"));\n if (!this.ws) return;\n const ws = this.ws;\n this.ws = null;\n await new Promise<void>((resolve) => {\n ws.once(\"close\", () => resolve());\n ws.close();\n });\n }\n\n private openSocket(): Promise<string> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(this.url);\n this.ws = ws;\n let settled = false;\n\n const fail = (error: Error) => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n\n ws.on(\"open\", () => {\n ws.send(JSON.stringify({\n type: \"hello\",\n platformKey: this.platformKey,\n clientId: this.clientId,\n protocolVersion: PROTOCOL_VERSION,\n sdkVersion: SDK_VERSION,\n } satisfies Envelope));\n });\n\n ws.on(\"message\", (data) => {\n let envelope: Envelope;\n try {\n envelope = JSON.parse(data.toString()) as Envelope;\n } catch (error) {\n const parsed = error instanceof Error ? error : new Error(\"Invalid platform message\");\n this.handlers.onError?.(parsed);\n return;\n }\n\n if (!settled && (envelope.type === \"hello_ok\" || envelope.type === \"hello_err\")) {\n settled = true;\n if (envelope.type === \"hello_err\") {\n const error = envelope.code === \"PROTOCOL\"\n ? new ProtocolVersionError(envelope.message)\n : new PlatformAuthError(envelope.message);\n this.closed = true;\n reject(error);\n ws.close();\n return;\n }\n this.accountName = envelope.accountName;\n this.startHeartbeat();\n this.flushOutbox();\n resolve(envelope.accountName);\n return;\n }\n\n if (envelope.type === \"pong\") {\n if (this.pendingPong === envelope.id) {\n this.pendingPong = null;\n if (this.pongTimer) clearTimeout(this.pongTimer);\n this.pongTimer = undefined;\n }\n return;\n }\n\n this.resolveSessionWaiter(envelope);\n this.handlers.onEnvelope(envelope);\n });\n\n ws.on(\"error\", (error) => {\n this.handlers.onError?.(error);\n fail(error);\n });\n\n ws.on(\"close\", () => {\n this.stopHeartbeat();\n if (this.ws === ws) this.ws = null;\n if (!settled) fail(new Error(\"platform connection closed before hello\"));\n if (this.closed || !this.everConnected) {\n this.failWaiters(new Error(\"platform connection closed\"));\n return;\n }\n this.handlers.onDisconnect?.();\n this.scheduleReconnect();\n });\n });\n }\n\n private resolveSessionWaiter(envelope: Envelope): void {\n if (envelope.type === \"session_started\" || envelope.type === \"session_stopped\") {\n const kind = envelope.type === \"session_started\" ? \"start\" : \"stop\";\n const waiter = this.pending.get(`session:${envelope.sessionId}:${kind}`);\n if (!waiter) return;\n this.pending.delete(`session:${envelope.sessionId}:${kind}`);\n waiter.resolve(envelope);\n return;\n }\n if (envelope.type === \"session_resumed\" || envelope.type === \"resume_err\") {\n const waiter = this.pending.get(`session:${envelope.sessionId}:resume`);\n if (!waiter) return;\n this.pending.delete(`session:${envelope.sessionId}:resume`);\n if (envelope.type === \"resume_err\") {\n waiter.reject(new ConnectionLostError(envelope.message));\n return;\n }\n waiter.resolve(envelope);\n }\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnecting) return;\n if (this.reconnectAttempt >= MAX_RECONNECT_ATTEMPTS) {\n this.closed = true;\n const error = new ConnectionLostError(\"Could not reconnect to the platform\");\n this.handlers.onError?.(error);\n this.failWaiters(error);\n return;\n }\n const delay = Math.min(SESSION_RESUME_GRACE_MS, 250 * 2 ** this.reconnectAttempt);\n this.reconnectAttempt += 1;\n this.reconnecting = true;\n log(this.logger, \"warn\", `platform connection dropped; retrying in ${delay}ms`);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n void this.reconnect();\n }, delay);\n this.reconnectTimer.unref?.();\n }\n\n private async reconnect(): Promise<void> {\n try {\n await this.openSocket();\n this.everConnected = true;\n this.reconnectAttempt = 0;\n this.reconnecting = false;\n const sessions = this.handlers.sessions?.() ?? [];\n for (const session of sessions) {\n const resumed = this.waitForSessionEvent(session.sessionId, \"resume\");\n this.send({\n type: \"resume_session\",\n sessionId: session.sessionId,\n sessionToken: session.sessionToken,\n });\n await resumed;\n }\n this.handlers.onReconnect?.();\n } catch (error) {\n this.reconnecting = false;\n if (this.closed) return;\n const wrapped = error instanceof Error ? error : new Error(String(error));\n if (wrapped instanceof PlatformAuthError || wrapped instanceof ProtocolVersionError) {\n this.closed = true;\n this.handlers.onError?.(wrapped);\n this.failWaiters(wrapped);\n return;\n }\n this.scheduleReconnect();\n }\n }\n\n private flushOutbox(): void {\n if (!this.ws || !this.connected) return;\n const pending = this.outbox.splice(0, this.outbox.length);\n for (const envelope of pending) {\n this.ws.send(JSON.stringify(envelope));\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeat = setInterval(() => {\n if (!this.connected) return;\n const id = randomUUID();\n this.pendingPong = id;\n try {\n this.send({ type: \"ping\", id });\n } catch {\n return;\n }\n this.pongTimer = setTimeout(() => {\n if (this.pendingPong === id) {\n log(this.logger, \"warn\", \"platform heartbeat timed out\");\n this.ws?.terminate();\n }\n }, PONG_TIMEOUT_MS);\n this.pongTimer.unref?.();\n }, HEARTBEAT_MS);\n this.heartbeat.unref?.();\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeat) clearInterval(this.heartbeat);\n if (this.pongTimer) clearTimeout(this.pongTimer);\n this.heartbeat = undefined;\n this.pongTimer = undefined;\n this.pendingPong = null;\n }\n\n private failWaiters(error: Error): void {\n for (const [, waiter] of this.pending) waiter.reject(error);\n this.pending.clear();\n }\n}\n","/**\n * Wire protocol between AgentServer (SDK) and the platform. Version 1.\n */\n\nexport const PROTOCOL_VERSION = 1;\nexport const SDK_VERSION = \"1.1.0\";\n\n/** How long a disconnected session can be resumed. Shared by both sides. */\nexport const SESSION_RESUME_GRACE_MS = 30_000;\n\nexport type JsonSchema = {\n type?: string | string[];\n properties?: Record<string, JsonSchema>;\n required?: string[];\n description?: string;\n additionalProperties?: boolean;\n [key: string]: unknown;\n};\n\nexport type ToolDescriptor = {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n};\n\nexport type TokenUsage = {\n promptTokens: number;\n completionTokens: number;\n};\n\nexport type AttemptRecord = {\n action: string;\n args: Record<string, unknown>;\n error: string;\n};\n\nexport type TurnReport = {\n ok: boolean;\n error?: string;\n action?: string;\n args?: Record<string, unknown>;\n result?: unknown;\n attempts?: number;\n attemptDetails?: AttemptRecord[];\n usage?: TokenUsage;\n connectionLost?: boolean;\n};\n\nexport type SessionEventName = \"action\" | \"retry\" | \"turnFailed\";\n\nexport type Envelope =\n | {\n type: \"hello\";\n platformKey: string;\n clientId: string;\n protocolVersion: number;\n sdkVersion: string;\n }\n | {\n type: \"hello_ok\";\n accountName: string;\n protocolVersion: number;\n }\n | {\n type: \"hello_err\";\n message: string;\n code?: \"AUTH\" | \"PROTOCOL\";\n }\n | {\n type: \"start_session\";\n sessionId: string;\n sessionToken: string;\n tools: ToolDescriptor[];\n instructions: string;\n goal?: string;\n name?: string;\n }\n | {\n type: \"session_started\";\n sessionId: string;\n }\n | {\n type: \"stop_session\";\n sessionId: string;\n }\n | {\n type: \"session_stopped\";\n sessionId: string;\n }\n | {\n type: \"mcp\";\n sessionId: string;\n message: unknown;\n }\n | ({\n type: \"turn_result\";\n sessionId: string;\n } & TurnReport)\n | {\n type: \"session_event\";\n sessionId: string;\n event: SessionEventName;\n action?: string;\n args?: Record<string, unknown>;\n error?: string;\n }\n | {\n type: \"ping\";\n id: string;\n }\n | {\n type: \"pong\";\n id: string;\n }\n | {\n type: \"resume_session\";\n sessionId: string;\n sessionToken: string;\n }\n | {\n type: \"session_resumed\";\n sessionId: string;\n }\n | {\n type: \"resume_err\";\n sessionId: string;\n message: string;\n }\n | {\n type: \"error\";\n message: string;\n sessionId?: string;\n };\n\nexport const DEFAULT_AGENT_INSTRUCTIONS = [\n \"You are a remote game agent. Tools are provided by the game.\",\n \"On every turn: call wait first. It blocks until the game grants your turn and then returns the current view from see.\",\n \"After wait returns, call exactly one action tool (not see, not wait).\",\n \"The view's done list is what this character has already called in this session, oldest first. Use it when choosing the next action.\",\n \"If an action tool returns an error, retry once with a corrected action. A second failure ends the turn as failed.\",\n].join(\"\\n\");\n\nexport function assertNever(value: never): never {\n throw new Error(`Unhandled protocol message: ${JSON.stringify(value)}`);\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Envelope } from \"./protocol.js\";\n\nexport type EnvelopeSender = (envelope: Envelope) => void;\n\n/**\n * MCP Transport that multiplexes JSON-RPC over a shared envelope channel,\n * keyed by sessionId.\n */\nexport class SessionMuxTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n private readonly sid: string;\n private readonly sendEnvelope: EnvelopeSender;\n private started = false;\n private closed = false;\n\n constructor(sessionId: string, sendEnvelope: EnvelopeSender) {\n this.sid = sessionId;\n this.sessionId = sessionId;\n this.sendEnvelope = sendEnvelope;\n }\n\n async start(): Promise<void> {\n if (this.closed) throw new Error(\"Transport already closed\");\n this.started = true;\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.onclose?.();\n }\n\n async send(message: JSONRPCMessage): Promise<void> {\n if (this.closed) throw new Error(\"Transport closed\");\n this.sendEnvelope({ type: \"mcp\", sessionId: this.sid, message });\n }\n\n /** Deliver an inbound MCP message from the platform. */\n receive(message: unknown): void {\n if (this.closed || !this.started) return;\n try {\n this.onmessage?.(message as JSONRPCMessage);\n } catch (error) {\n this.onerror?.(error instanceof Error ? error : new Error(String(error)));\n }\n }\n}\n","import { z, type ZodRawShape, type ZodTypeAny } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport type { JsonSchema, ToolDescriptor } from \"./protocol.js\";\n\nexport type ActionSpec = {\n description: string;\n args?: ZodRawShape;\n};\n\nexport type AgentMetadata = {\n description?: string;\n actions?: Record<string, ActionSpec>;\n};\n\nexport type PlayerTool = {\n name: string;\n description: string;\n paramNames: string[];\n argsSchema?: z.ZodObject<ZodRawShape>;\n descriptor: ToolDescriptor;\n invoke: (args: Record<string, unknown>) => Promise<unknown>;\n};\n\nexport type ReflectedPlayer = {\n /** Class-level description, when the player declared `static agent`. */\n description?: string;\n see: PlayerTool;\n actions: PlayerTool[];\n tools: ToolDescriptor[];\n};\n\nconst SKIP = new Set([\"constructor\"]);\n\nexport const SEE_DESCRIPTION = \"Read the current game view for this player. Prefer wait, which returns this after the game grants a turn.\";\nexport const WAIT_DESCRIPTION = \"Block until the game calls turn() for this session, then return the current see() view.\";\n\n/** Parse parameter names from a function's source. Used only when no arg schema is declared. */\nexport function getParamNames(fn: (...args: never[]) => unknown): string[] {\n const src = fn.toString().replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/\\/\\/.*$/gm, \"\");\n const header =\n src.match(/(?:async\\s+)?(?:function\\s*)?(?:\\w*)\\s*\\(([^)]*)\\)/) ??\n src.match(/^(?:async\\s*)?\\(?([^)=]*)\\)?\\s*=>/);\n if (!header) return [];\n const raw = header[1]?.trim() ?? \"\";\n if (!raw) return [];\n return raw\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => {\n const cleaned = part.replace(/\\s*=\\s*[^,]+$/, \"\").trim();\n const name = cleaned.split(/[:\\s]/)[0]?.replace(/^\\.\\.\\./, \"\") ?? \"\";\n return name;\n })\n .filter((name) => name.length > 0 && name !== \"this\");\n}\n\nfunction collectMethodNames(instance: object): string[] {\n const names = new Set<string>();\n let proto: object | null = Object.getPrototypeOf(instance);\n while (proto && proto !== Object.prototype) {\n for (const name of Object.getOwnPropertyNames(proto)) {\n if (SKIP.has(name) || name.startsWith(\"_\")) continue;\n const desc = Object.getOwnPropertyDescriptor(proto, name);\n if (!desc || typeof desc.value !== \"function\") continue;\n names.add(name);\n }\n proto = Object.getPrototypeOf(proto);\n }\n return [...names].sort();\n}\n\nfunction readMetadata(instance: object): AgentMetadata | undefined {\n const ctor = instance.constructor as { agent?: AgentMetadata };\n return ctor.agent;\n}\n\nfunction toJsonSchema(schema: ZodTypeAny): JsonSchema {\n const json = zodToJsonSchema(schema, { target: \"jsonSchema7\", $refStrategy: \"none\" }) as JsonSchema;\n delete json.$schema;\n return json;\n}\n\nfunction formatZodError(error: z.ZodError): string {\n return error.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"arguments\";\n return `${path}: ${issue.message}`;\n })\n .join(\"; \");\n}\n\nfunction buildTool(\n instance: object,\n name: string,\n description: string,\n spec?: ActionSpec,\n): PlayerTool {\n const fn = (instance as Record<string, unknown>)[name];\n if (typeof fn !== \"function\") {\n throw new Error(`Expected method ${name}`);\n }\n const paramNames = spec?.args ? Object.keys(spec.args) : getParamNames(fn as (...args: never[]) => unknown);\n const shape: ZodRawShape = spec?.args ?? Object.fromEntries(paramNames.map((param) => [param, z.any()]));\n const argsSchema = paramNames.length > 0 || spec?.args ? z.object(shape) : undefined;\n const inputSchema: JsonSchema = spec?.args && argsSchema\n ? toJsonSchema(argsSchema)\n : {\n type: \"object\",\n properties: Object.fromEntries(paramNames.map((param) => [param, {}])),\n ...(paramNames.length > 0 ? { required: paramNames } : {}),\n };\n\n return {\n name,\n description,\n paramNames,\n ...(argsSchema ? { argsSchema } : {}),\n descriptor: { name, description, inputSchema },\n async invoke(args: Record<string, unknown>) {\n let parsed: Record<string, unknown> = args ?? {};\n if (argsSchema) {\n const result = argsSchema.safeParse(args ?? {});\n if (!result.success) {\n throw new Error(formatZodError(result.error));\n }\n parsed = result.data as Record<string, unknown>;\n }\n const ordered = paramNames.map((param) => parsed[param]);\n return await Promise.resolve((fn as (...params: unknown[]) => unknown).apply(instance, ordered));\n },\n };\n}\n\n/**\n * Publish tools from a player instance.\n * - `see` is the state tool (required).\n * - Every other public method is an action tool.\n * - Names starting with `_` and the constructor are skipped.\n * - `static agent` supplies descriptions and zod argument schemas. Undeclared methods stay tools,\n * with unconstrained JSON arguments (no type guessed from the parameter name).\n */\nexport function reflectPlayer(instance: object): ReflectedPlayer {\n const names = collectMethodNames(instance);\n if (!names.includes(\"see\")) {\n throw new Error(\"Player must implement a public see() method\");\n }\n\n const metadata = readMetadata(instance);\n const declared = metadata?.actions ?? {};\n const className = instance.constructor?.name || \"Player\";\n for (const name of Object.keys(declared)) {\n if (!names.includes(name) || name === \"see\") {\n throw new Error(`Declared action \"${name}\" is not a public method on ${className}`);\n }\n }\n\n const see = buildTool(instance, \"see\", SEE_DESCRIPTION);\n const actionNames = names.filter((name) => name !== \"see\");\n const actions = actionNames.map((name) => {\n const spec = declared[name];\n const description = spec?.description ?? `Action: ${name}`;\n return buildTool(instance, name, description, spec);\n });\n\n const wait: ToolDescriptor = {\n name: \"wait\",\n description: WAIT_DESCRIPTION,\n inputSchema: { type: \"object\", properties: {} },\n };\n\n return {\n ...(metadata?.description ? { description: metadata.description } : {}),\n see,\n actions,\n tools: [see.descriptor, ...actions.map((action) => action.descriptor), wait],\n };\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DoneAction } from \"./memory.js\";\nimport { viewWithDone } from \"./memory.js\";\nimport type { ReflectedPlayer } from \"./reflect.js\";\nimport { WAIT_DESCRIPTION } from \"./reflect.js\";\nimport type { TurnGate } from \"./turn-gate.js\";\nimport { SDK_VERSION } from \"./protocol.js\";\n\nfunction jsonResult(payload: unknown, isError = false) {\n return {\n isError,\n content: [{ type: \"text\" as const, text: JSON.stringify(payload) }],\n };\n}\n\nfunction toolError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return jsonResult({ error: message }, true);\n}\n\nexport type SessionActionLog = {\n record(entry: DoneAction): void;\n done(): DoneAction[];\n};\n\n/**\n * Build an in-process MCP server for one player session.\n * Tools come from one definition: see, wait, and every public action.\n * When an action log is set, see and wait include what this character already called.\n */\nexport function createSessionMcpServer(\n player: ReflectedPlayer,\n gate: TurnGate,\n options?: { name?: string; actions?: SessionActionLog },\n): McpServer {\n const server = new McpServer(\n { name: options?.name ?? \"agent-player\", version: SDK_VERSION },\n { capabilities: { tools: {} } },\n );\n const actions = options?.actions;\n\n const viewed = async () => {\n const view = await player.see.invoke({});\n return actions ? viewWithDone(view, actions.done()) : view;\n };\n\n server.registerTool(\n \"see\",\n { description: player.see.description },\n async () => {\n try {\n return jsonResult(await viewed());\n } catch (error) {\n return toolError(error);\n }\n },\n );\n\n server.registerTool(\n \"wait\",\n { description: WAIT_DESCRIPTION },\n async () => {\n try {\n await gate.waitForTurn();\n return jsonResult(await viewed());\n } catch (error) {\n return toolError(error);\n }\n },\n );\n\n for (const action of player.actions) {\n const handler = async (args: Record<string, unknown>) => {\n try {\n const result = await action.invoke(args);\n actions?.record({ action: action.name, args, ok: true });\n return jsonResult(result ?? { ok: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n actions?.record({ action: action.name, args, ok: false, error: message });\n return toolError(error);\n }\n };\n\n if (action.argsSchema) {\n server.registerTool(\n action.name,\n {\n description: action.description,\n inputSchema: action.argsSchema.shape,\n },\n async (args) => handler(args as Record<string, unknown>),\n );\n } else {\n server.registerTool(\n action.name,\n { description: action.description },\n async () => handler({}),\n );\n }\n }\n\n return server;\n}\n","import { TurnTimeoutError } from \"./errors.js\";\nimport type { TurnReport } from \"./protocol.js\";\n\nexport type TurnOutcome = TurnReport;\n\nfunction abortError(signal: AbortSignal): Error {\n const reason: unknown = signal.reason;\n if (reason instanceof Error) return reason;\n if (typeof reason === \"string\" && reason.length > 0) return new Error(reason);\n return new Error(\"turn aborted\");\n}\n\n/**\n * Coordinates game-side turn() with the agent's wait tool.\n * turn() releases wait, then resolves when the platform reports the turn finished.\n */\nexport class TurnGate {\n private waitResolve: (() => void) | null = null;\n private waitPromise: Promise<void> | null = null;\n private turnResolve: ((result: TurnOutcome) => void) | null = null;\n private turnReject: ((error: Error) => void) | null = null;\n private turnPromise: Promise<TurnOutcome> | null = null;\n private released = false;\n\n /** Called by the wait tool. Blocks until turn() releases this session. */\n async waitForTurn(): Promise<void> {\n if (this.released) {\n this.released = false;\n return;\n }\n if (!this.waitPromise) {\n this.waitPromise = new Promise<void>((resolve) => {\n this.waitResolve = resolve;\n });\n }\n await this.waitPromise;\n this.waitPromise = null;\n this.waitResolve = null;\n this.released = false;\n }\n\n /**\n * Unblock wait and wait for the platform's turn report.\n * Rejects on timeout or abort; those do not produce a TurnOutcome.\n */\n async runTurn(options?: { timeoutMs?: number; signal?: AbortSignal }): Promise<TurnOutcome> {\n if (this.turnPromise) {\n throw new Error(\"turn() already in progress for this session\");\n }\n if (options?.signal?.aborted) {\n throw abortError(options.signal);\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let onAbort: (() => void) | undefined;\n const signal = options?.signal;\n\n this.turnPromise = new Promise<TurnOutcome>((resolve, reject) => {\n this.turnResolve = resolve;\n this.turnReject = reject;\n if (options?.timeoutMs != null) {\n timeoutId = setTimeout(() => {\n this.rejectTurn(new TurnTimeoutError(`turn() timed out after ${options.timeoutMs}ms`));\n }, options.timeoutMs);\n }\n if (signal) {\n if (signal.aborted) {\n this.rejectTurn(abortError(signal));\n return;\n }\n onAbort = () => this.rejectTurn(abortError(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n });\n\n this.released = true;\n const release = this.waitResolve;\n this.waitResolve = null;\n this.waitPromise = null;\n release?.();\n\n try {\n return await this.turnPromise;\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n if (signal && onAbort) signal.removeEventListener(\"abort\", onAbort);\n this.turnPromise = null;\n this.turnResolve = null;\n this.turnReject = null;\n }\n }\n\n /** Platform finished one action cycle (success or second failure). */\n completeTurn(outcome: TurnOutcome): void {\n const resolve = this.turnResolve;\n if (!resolve) return;\n this.turnResolve = null;\n this.turnReject = null;\n resolve(outcome);\n }\n\n /** Fail an in-flight turn, for example when the connection cannot be resumed. */\n failTurn(error: Error): void {\n this.rejectTurn(error);\n }\n\n reset(): void {\n this.waitResolve?.();\n this.completeTurn({ ok: false, error: \"session stopped\" });\n this.waitResolve = null;\n this.waitPromise = null;\n this.released = false;\n }\n\n private rejectTurn(error: Error): void {\n const reject = this.turnReject;\n if (!reject) return;\n this.turnResolve = null;\n this.turnReject = null;\n reject(error);\n }\n}\n"],"mappings":"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","names":["randomUUID","resolve","resolve","randomUUID"]}
|
package/dist/protocol.cjs
CHANGED
|
@@ -28,12 +28,13 @@ __export(protocol_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(protocol_exports);
|
|
30
30
|
var PROTOCOL_VERSION = 1;
|
|
31
|
-
var SDK_VERSION = "
|
|
31
|
+
var SDK_VERSION = "1.1.0";
|
|
32
32
|
var SESSION_RESUME_GRACE_MS = 3e4;
|
|
33
33
|
var DEFAULT_AGENT_INSTRUCTIONS = [
|
|
34
34
|
"You are a remote game agent. Tools are provided by the game.",
|
|
35
35
|
"On every turn: call wait first. It blocks until the game grants your turn and then returns the current view from see.",
|
|
36
36
|
"After wait returns, call exactly one action tool (not see, not wait).",
|
|
37
|
+
"The view's done list is what this character has already called in this session, oldest first. Use it when choosing the next action.",
|
|
37
38
|
"If an action tool returns an error, retry once with a corrected action. A second failure ends the turn as failed."
|
|
38
39
|
].join("\n");
|
|
39
40
|
function assertNever(value) {
|
package/dist/protocol.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocol.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/protocol.ts"],"sourcesContent":["/**\n * Wire protocol between AgentServer (SDK) and the platform. Version 1.\n */\n\nexport const PROTOCOL_VERSION = 1;\nexport const SDK_VERSION = \"1.1.0\";\n\n/** How long a disconnected session can be resumed. Shared by both sides. */\nexport const SESSION_RESUME_GRACE_MS = 30_000;\n\nexport type JsonSchema = {\n type?: string | string[];\n properties?: Record<string, JsonSchema>;\n required?: string[];\n description?: string;\n additionalProperties?: boolean;\n [key: string]: unknown;\n};\n\nexport type ToolDescriptor = {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n};\n\nexport type TokenUsage = {\n promptTokens: number;\n completionTokens: number;\n};\n\nexport type AttemptRecord = {\n action: string;\n args: Record<string, unknown>;\n error: string;\n};\n\nexport type TurnReport = {\n ok: boolean;\n error?: string;\n action?: string;\n args?: Record<string, unknown>;\n result?: unknown;\n attempts?: number;\n attemptDetails?: AttemptRecord[];\n usage?: TokenUsage;\n connectionLost?: boolean;\n};\n\nexport type SessionEventName = \"action\" | \"retry\" | \"turnFailed\";\n\nexport type Envelope =\n | {\n type: \"hello\";\n platformKey: string;\n clientId: string;\n protocolVersion: number;\n sdkVersion: string;\n }\n | {\n type: \"hello_ok\";\n accountName: string;\n protocolVersion: number;\n }\n | {\n type: \"hello_err\";\n message: string;\n code?: \"AUTH\" | \"PROTOCOL\";\n }\n | {\n type: \"start_session\";\n sessionId: string;\n sessionToken: string;\n tools: ToolDescriptor[];\n instructions: string;\n goal?: string;\n name?: string;\n }\n | {\n type: \"session_started\";\n sessionId: string;\n }\n | {\n type: \"stop_session\";\n sessionId: string;\n }\n | {\n type: \"session_stopped\";\n sessionId: string;\n }\n | {\n type: \"mcp\";\n sessionId: string;\n message: unknown;\n }\n | ({\n type: \"turn_result\";\n sessionId: string;\n } & TurnReport)\n | {\n type: \"session_event\";\n sessionId: string;\n event: SessionEventName;\n action?: string;\n args?: Record<string, unknown>;\n error?: string;\n }\n | {\n type: \"ping\";\n id: string;\n }\n | {\n type: \"pong\";\n id: string;\n }\n | {\n type: \"resume_session\";\n sessionId: string;\n sessionToken: string;\n }\n | {\n type: \"session_resumed\";\n sessionId: string;\n }\n | {\n type: \"resume_err\";\n sessionId: string;\n message: string;\n }\n | {\n type: \"error\";\n message: string;\n sessionId?: string;\n };\n\nexport const DEFAULT_AGENT_INSTRUCTIONS = [\n \"You are a remote game agent. Tools are provided by the game.\",\n \"On every turn: call wait first. It blocks until the game grants your turn and then returns the current view from see.\",\n \"After wait returns, call exactly one action tool (not see, not wait).\",\n \"The view's done list is what this character has already called in this session, oldest first. Use it when choosing the next action.\",\n \"If an action tool returns an error, retry once with a corrected action. A second failure ends the turn as failed.\",\n].join(\"\\n\");\n\nexport function assertNever(value: never): never {\n throw new Error(`Unhandled protocol message: ${JSON.stringify(value)}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,IAAM,mBAAmB;AACzB,IAAM,cAAc;AAGpB,IAAM,0BAA0B;AA8HhC,IAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAEJ,SAAS,YAAY,OAAqB;AAC/C,QAAM,IAAI,MAAM,+BAA+B,KAAK,UAAU,KAAK,CAAC,EAAE;AACxE;","names":[]}
|