@whitesands/agent-player 0.0.0-stage → 1.0.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.
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/testing.ts
21
+ var testing_exports = {};
22
+ __export(testing_exports, {
23
+ SessionLoop: () => SessionLoop,
24
+ createScriptedModel: () => createScriptedModel,
25
+ createTestPlatform: () => createTestPlatform,
26
+ loopEventToAgentEvent: () => loopEventToAgentEvent
27
+ });
28
+ module.exports = __toCommonJS(testing_exports);
29
+
30
+ // src/loop/model.ts
31
+ function createScriptedModel(script) {
32
+ let index = 0;
33
+ return {
34
+ async decide() {
35
+ const call = script[index] ?? { name: "wait", arguments: {} };
36
+ index += 1;
37
+ return {
38
+ toolCall: call,
39
+ usage: { promptTokens: 1, completionTokens: 1 }
40
+ };
41
+ }
42
+ };
43
+ }
44
+
45
+ // src/loop/session-loop.ts
46
+ var import_client = require("@modelcontextprotocol/sdk/client/index.js");
47
+
48
+ // src/logger.ts
49
+ function log(logger, level, message, extra) {
50
+ logger?.[level]?.(message, extra);
51
+ }
52
+
53
+ // src/protocol.ts
54
+ var SDK_VERSION = "1.0.0";
55
+ var DEFAULT_AGENT_INSTRUCTIONS = [
56
+ "You are a remote game agent. Tools are provided by the game.",
57
+ "On every turn: call wait first. It blocks until the game grants your turn and then returns the current view from see.",
58
+ "After wait returns, call exactly one action tool (not see, not wait).",
59
+ "The view's done list is what this character has already called in this session, oldest first. Use it when choosing the next action.",
60
+ "If an action tool returns an error, retry once with a corrected action. A second failure ends the turn as failed."
61
+ ].join("\n");
62
+
63
+ // src/loop/session-loop.ts
64
+ function loopEventToAgentEvent(sessionId, event) {
65
+ if (event.event === "action") {
66
+ return {
67
+ type: "action",
68
+ sessionId,
69
+ action: event.action ?? "unknown",
70
+ args: event.args ?? {}
71
+ };
72
+ }
73
+ if (event.event === "retry") {
74
+ return {
75
+ type: "retry",
76
+ sessionId,
77
+ action: event.action ?? "unknown",
78
+ args: event.args ?? {},
79
+ error: event.error ?? "action failed"
80
+ };
81
+ }
82
+ return {
83
+ type: "turnFailed",
84
+ sessionId,
85
+ error: event.error ?? "turn failed",
86
+ ...event.action ? { action: event.action } : {},
87
+ ...event.args ? { args: event.args } : {}
88
+ };
89
+ }
90
+ function parseToolPayload(result) {
91
+ const text = result.content.filter((entry) => entry.type === "text" && typeof entry.text === "string").map((entry) => entry.text).join("\n");
92
+ let json = text;
93
+ try {
94
+ json = JSON.parse(text);
95
+ } catch {
96
+ }
97
+ return { isError: Boolean(result.isError), text, json };
98
+ }
99
+ function toolErrorMessage(result) {
100
+ if (typeof result.json === "object" && result.json && "error" in result.json) {
101
+ return String(result.json.error);
102
+ }
103
+ return result.text;
104
+ }
105
+ function composeInstructions(instructions, goal) {
106
+ if (!goal) return instructions;
107
+ return `${instructions}
108
+
109
+ Your goal: ${goal}`;
110
+ }
111
+ var SessionLoop = class {
112
+ options;
113
+ client = null;
114
+ stopped = false;
115
+ runPromise = null;
116
+ constructor(options) {
117
+ this.options = options;
118
+ }
119
+ async start() {
120
+ if (this.runPromise) return;
121
+ const client = new import_client.Client({ name: "agent-player", version: SDK_VERSION });
122
+ await client.connect(this.options.transport);
123
+ this.client = client;
124
+ this.runPromise = this.run().catch((error) => {
125
+ if (this.stopped) return;
126
+ const message = error instanceof Error ? error.message : String(error);
127
+ log(this.options.logger, "error", `session ${this.options.sessionId} crashed: ${message}`);
128
+ this.options.onTurnResult({ ok: false, error: message, attempts: 0 });
129
+ });
130
+ }
131
+ async stop() {
132
+ this.stopped = true;
133
+ try {
134
+ await this.client?.close();
135
+ } catch {
136
+ }
137
+ this.client = null;
138
+ await this.runPromise?.catch(() => void 0);
139
+ this.runPromise = null;
140
+ }
141
+ async callTool(name, args) {
142
+ if (!this.client) throw new Error("Client not connected");
143
+ const result = await this.client.callTool({ name, arguments: args });
144
+ return parseToolPayload(result);
145
+ }
146
+ async decideAction(tools, messages, usage) {
147
+ const decision = await this.options.model.decide({
148
+ instructions: composeInstructions(this.options.instructions, this.options.goal),
149
+ tools,
150
+ messages
151
+ });
152
+ usage.promptTokens += decision.usage.promptTokens;
153
+ usage.completionTokens += decision.usage.completionTokens;
154
+ const total = decision.usage.promptTokens + decision.usage.completionTokens;
155
+ await this.options.onUsage(total);
156
+ return decision.toolCall;
157
+ }
158
+ emit(event) {
159
+ this.options.onEvent?.(event);
160
+ }
161
+ async run() {
162
+ if (!this.client) return;
163
+ const listed = await this.client.listTools();
164
+ const tools = listed.tools.map((tool) => ({
165
+ name: tool.name,
166
+ description: tool.description ?? tool.name,
167
+ inputSchema: tool.inputSchema
168
+ }));
169
+ const actionTools = tools.filter((tool) => tool.name !== "wait" && tool.name !== "see");
170
+ while (!this.stopped) {
171
+ const waitResult = await this.callTool("wait", {});
172
+ if (this.stopped) break;
173
+ if (waitResult.isError) {
174
+ this.options.onTurnResult({ ok: false, error: waitResult.text, attempts: 0 });
175
+ continue;
176
+ }
177
+ const usage = { promptTokens: 0, completionTokens: 0 };
178
+ const attemptDetails = [];
179
+ const messages = [
180
+ {
181
+ role: "user",
182
+ content: `It is your turn. Current view:
183
+ ${waitResult.text}
184
+ Call exactly one action tool.`
185
+ }
186
+ ];
187
+ let action = await this.decideAction(actionTools, messages, usage);
188
+ let result;
189
+ let firstError;
190
+ if (action.name === "wait" || action.name === "see") {
191
+ firstError = `${action.name} is not an action`;
192
+ } else {
193
+ this.emit({ event: "action", action: action.name, args: action.arguments });
194
+ result = await this.callTool(action.name, action.arguments);
195
+ if (!result.isError) {
196
+ this.options.onTurnResult({
197
+ ok: true,
198
+ action: action.name,
199
+ args: action.arguments,
200
+ result: result.json,
201
+ attempts: 1,
202
+ usage
203
+ });
204
+ continue;
205
+ }
206
+ firstError = toolErrorMessage(result);
207
+ }
208
+ attemptDetails.push({ action: action.name, args: action.arguments, error: firstError });
209
+ log(this.options.logger, "warn", `session ${this.options.sessionId} action ${action.name} failed: ${firstError}; retrying once`);
210
+ this.emit({ event: "retry", action: action.name, args: action.arguments, error: firstError });
211
+ messages.push({
212
+ role: "assistant",
213
+ content: `Called ${action.name}(${JSON.stringify(action.arguments)})`
214
+ });
215
+ messages.push({
216
+ role: "tool",
217
+ name: action.name,
218
+ content: result?.text ?? firstError,
219
+ isError: true
220
+ });
221
+ messages.push({
222
+ role: "user",
223
+ content: [
224
+ `Action ${action.name} failed: ${firstError}`,
225
+ "Retry once with a different legal action (or different arguments).",
226
+ "Do not repeat the same failing call. Do not call wait or see.",
227
+ `Current view was:
228
+ ${waitResult.text}`
229
+ ].join("\n")
230
+ });
231
+ const retry = await this.decideAction(actionTools, messages, usage);
232
+ if (retry.name === "wait" || retry.name === "see") {
233
+ const error = `Retry returned ${retry.name} instead of an action (after: ${firstError})`;
234
+ this.emit({ event: "turnFailed", error });
235
+ this.options.onTurnResult({
236
+ ok: false,
237
+ error,
238
+ attempts: 1,
239
+ attemptDetails,
240
+ usage
241
+ });
242
+ continue;
243
+ }
244
+ this.emit({ event: "action", action: retry.name, args: retry.arguments });
245
+ result = await this.callTool(retry.name, retry.arguments);
246
+ if (!result.isError) {
247
+ this.options.onTurnResult({
248
+ ok: true,
249
+ action: retry.name,
250
+ args: retry.arguments,
251
+ result: result.json,
252
+ attempts: 2,
253
+ usage
254
+ });
255
+ continue;
256
+ }
257
+ const secondError = toolErrorMessage(result);
258
+ attemptDetails.push({ action: retry.name, args: retry.arguments, error: secondError });
259
+ log(this.options.logger, "warn", `session ${this.options.sessionId} retry ${retry.name} failed: ${secondError}`);
260
+ this.emit({ event: "turnFailed", action: retry.name, args: retry.arguments, error: secondError });
261
+ this.options.onTurnResult({
262
+ ok: false,
263
+ error: secondError,
264
+ attempts: 2,
265
+ attemptDetails,
266
+ usage
267
+ });
268
+ }
269
+ }
270
+ };
271
+
272
+ // src/loop/test-platform.ts
273
+ function createTestPlatform(script) {
274
+ const model = createScriptedModel(script);
275
+ const loops = /* @__PURE__ */ new Map();
276
+ return {
277
+ async startSession(request) {
278
+ const loop = new SessionLoop({
279
+ sessionId: request.sessionId,
280
+ transport: request.transport,
281
+ instructions: request.instructions,
282
+ ...request.goal ? { goal: request.goal } : {},
283
+ model,
284
+ ...request.logger ? { logger: request.logger } : {},
285
+ onUsage: async (tokens) => {
286
+ await request.onUsage?.(tokens);
287
+ },
288
+ onTurnResult: request.onTurnResult,
289
+ onEvent: (event) => {
290
+ request.onEvent?.(loopEventToAgentEvent(request.sessionId, event));
291
+ }
292
+ });
293
+ loops.set(request.sessionId, loop);
294
+ await loop.start();
295
+ },
296
+ async stopSession(sessionId) {
297
+ const loop = loops.get(sessionId);
298
+ if (!loop) return;
299
+ loops.delete(sessionId);
300
+ await loop.stop();
301
+ },
302
+ async close() {
303
+ const ids = [...loops.keys()];
304
+ for (const id of ids) {
305
+ const loop = loops.get(id);
306
+ loops.delete(id);
307
+ await loop?.stop();
308
+ }
309
+ }
310
+ };
311
+ }
312
+ // Annotate the CommonJS export names for ESM import in node:
313
+ 0 && (module.exports = {
314
+ SessionLoop,
315
+ createScriptedModel,
316
+ createTestPlatform,
317
+ loopEventToAgentEvent
318
+ });
319
+ //# sourceMappingURL=testing.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/testing.ts","../src/loop/model.ts","../src/loop/session-loop.ts","../src/logger.ts","../src/protocol.ts","../src/loop/test-platform.ts"],"sourcesContent":["export type { InlinePlatform, StartSessionRequest } from \"./types.js\";\nexport { createTestPlatform } from \"./loop/test-platform.js\";\nexport { SessionLoop, loopEventToAgentEvent, type SessionLoopOptions, type LoopEvent } from \"./loop/session-loop.js\";\nexport {\n createScriptedModel,\n type ModelClient,\n type ModelDecision,\n type ModelMessage,\n type ToolCallRequest,\n} from \"./loop/model.js\";\n","export type ToolCallRequest = {\n name: string;\n arguments: Record<string, unknown>;\n};\n\nexport type ModelMessage =\n | { role: \"system\"; content: string }\n | { role: \"user\"; content: string }\n | { role: \"assistant\"; content: string }\n | { role: \"tool\"; name: string; content: string; isError?: boolean };\n\nexport type ModelDecision = {\n toolCall: ToolCallRequest;\n usage: { promptTokens: number; completionTokens: number };\n};\n\nexport type ModelClient = {\n /** Ask the model to choose exactly one tool call. */\n decide(args: {\n instructions: string;\n tools: Array<{ name: string; description: string; inputSchema: unknown }>;\n messages: ModelMessage[];\n }): Promise<ModelDecision>;\n};\n\n/**\n * Scripted model for tests: returns predetermined tool calls in order.\n * When the queue is exhausted, always returns wait.\n */\nexport function createScriptedModel(script: ToolCallRequest[]): ModelClient {\n let index = 0;\n return {\n async decide() {\n const call = script[index] ?? { name: \"wait\", arguments: {} };\n index += 1;\n return {\n toolCall: call,\n usage: { promptTokens: 1, completionTokens: 1 },\n };\n },\n };\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { Logger } from \"../logger.js\";\nimport { log } from \"../logger.js\";\nimport type { AgentEvent } from \"../types.js\";\nimport type { AttemptRecord, SessionEventName, TokenUsage, TurnReport } from \"../protocol.js\";\nimport { SDK_VERSION } from \"../protocol.js\";\nimport type { ModelClient, ModelMessage, ToolCallRequest } from \"./model.js\";\n\nexport type LoopEvent = {\n event: SessionEventName;\n action?: string;\n args?: Record<string, unknown>;\n error?: string;\n};\n\nexport function loopEventToAgentEvent(sessionId: string, event: LoopEvent): AgentEvent {\n if (event.event === \"action\") {\n return {\n type: \"action\",\n sessionId,\n action: event.action ?? \"unknown\",\n args: event.args ?? {},\n };\n }\n if (event.event === \"retry\") {\n return {\n type: \"retry\",\n sessionId,\n action: event.action ?? \"unknown\",\n args: event.args ?? {},\n error: event.error ?? \"action failed\",\n };\n }\n return {\n type: \"turnFailed\",\n sessionId,\n error: event.error ?? \"turn failed\",\n ...(event.action ? { action: event.action } : {}),\n ...(event.args ? { args: event.args } : {}),\n };\n}\n\nexport type SessionLoopOptions = {\n sessionId: string;\n transport: Transport;\n instructions: string;\n goal?: string;\n model: ModelClient;\n logger?: Logger;\n onUsage: (tokens: number) => void | Promise<void>;\n onTurnResult: (result: TurnReport) => void;\n onEvent?: (event: LoopEvent) => void;\n};\n\ntype ToolPayload = { isError: boolean; text: string; json: unknown };\n\nfunction parseToolPayload(result: {\n isError?: boolean;\n content: Array<{ type: string; text?: string }>;\n}): ToolPayload {\n const text = result.content\n .filter((entry) => entry.type === \"text\" && typeof entry.text === \"string\")\n .map((entry) => entry.text!)\n .join(\"\\n\");\n let json: unknown = text;\n try {\n json = JSON.parse(text);\n } catch {\n // keep text\n }\n return { isError: Boolean(result.isError), text, json };\n}\n\nfunction toolErrorMessage(result: ToolPayload): string {\n if (typeof result.json === \"object\" && result.json && \"error\" in result.json) {\n return String((result.json as { error: unknown }).error);\n }\n return result.text;\n}\n\nfunction composeInstructions(instructions: string, goal?: string): string {\n if (!goal) return instructions;\n return `${instructions}\\n\\nYour goal: ${goal}`;\n}\n\n/**\n * Per-session MCP client loop:\n * wait → read view → ask model → one action → retry once on error → report turn.\n */\nexport class SessionLoop {\n private readonly options: SessionLoopOptions;\n private client: Client | null = null;\n private stopped = false;\n private runPromise: Promise<void> | null = null;\n\n constructor(options: SessionLoopOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n if (this.runPromise) return;\n const client = new Client({ name: \"agent-player\", version: SDK_VERSION });\n await client.connect(this.options.transport);\n this.client = client;\n this.runPromise = this.run().catch((error) => {\n if (this.stopped) return;\n const message = error instanceof Error ? error.message : String(error);\n log(this.options.logger, \"error\", `session ${this.options.sessionId} crashed: ${message}`);\n this.options.onTurnResult({ ok: false, error: message, attempts: 0 });\n });\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n try {\n await this.client?.close();\n } catch {\n // ignore\n }\n this.client = null;\n await this.runPromise?.catch(() => undefined);\n this.runPromise = null;\n }\n\n private async callTool(name: string, args: Record<string, unknown>): Promise<ToolPayload> {\n if (!this.client) throw new Error(\"Client not connected\");\n const result = await this.client.callTool({ name, arguments: args });\n return parseToolPayload(result as {\n isError?: boolean;\n content: Array<{ type: string; text?: string }>;\n });\n }\n\n private async decideAction(\n tools: Array<{ name: string; description: string; inputSchema: unknown }>,\n messages: ModelMessage[],\n usage: TokenUsage,\n ): Promise<ToolCallRequest> {\n const decision = await this.options.model.decide({\n instructions: composeInstructions(this.options.instructions, this.options.goal),\n tools,\n messages,\n });\n usage.promptTokens += decision.usage.promptTokens;\n usage.completionTokens += decision.usage.completionTokens;\n const total = decision.usage.promptTokens + decision.usage.completionTokens;\n await this.options.onUsage(total);\n return decision.toolCall;\n }\n\n private emit(event: LoopEvent): void {\n this.options.onEvent?.(event);\n }\n\n private async run(): Promise<void> {\n if (!this.client) return;\n\n const listed = await this.client.listTools();\n const tools = listed.tools.map((tool) => ({\n name: tool.name,\n description: tool.description ?? tool.name,\n inputSchema: tool.inputSchema,\n }));\n const actionTools = tools.filter((tool) => tool.name !== \"wait\" && tool.name !== \"see\");\n\n while (!this.stopped) {\n const waitResult = await this.callTool(\"wait\", {});\n if (this.stopped) break;\n if (waitResult.isError) {\n this.options.onTurnResult({ ok: false, error: waitResult.text, attempts: 0 });\n continue;\n }\n\n const usage: TokenUsage = { promptTokens: 0, completionTokens: 0 };\n const attemptDetails: AttemptRecord[] = [];\n const messages: ModelMessage[] = [\n {\n role: \"user\",\n content: `It is your turn. Current view:\\n${waitResult.text}\\nCall exactly one action tool.`,\n },\n ];\n\n let action = await this.decideAction(actionTools, messages, usage);\n let result: ToolPayload | undefined;\n let firstError: string;\n if (action.name === \"wait\" || action.name === \"see\") {\n // wait and see are how the loop reads state. They are not a move.\n firstError = `${action.name} is not an action`;\n } else {\n this.emit({ event: \"action\", action: action.name, args: action.arguments });\n result = await this.callTool(action.name, action.arguments);\n if (!result.isError) {\n this.options.onTurnResult({\n ok: true,\n action: action.name,\n args: action.arguments,\n result: result.json,\n attempts: 1,\n usage,\n });\n continue;\n }\n firstError = toolErrorMessage(result);\n }\n attemptDetails.push({ action: action.name, args: action.arguments, error: firstError });\n log(this.options.logger, \"warn\", `session ${this.options.sessionId} action ${action.name} failed: ${firstError}; retrying once`);\n this.emit({ event: \"retry\", action: action.name, args: action.arguments, error: firstError });\n\n messages.push({\n role: \"assistant\",\n content: `Called ${action.name}(${JSON.stringify(action.arguments)})`,\n });\n messages.push({\n role: \"tool\",\n name: action.name,\n content: result?.text ?? firstError,\n isError: true,\n });\n messages.push({\n role: \"user\",\n content: [\n `Action ${action.name} failed: ${firstError}`,\n \"Retry once with a different legal action (or different arguments).\",\n \"Do not repeat the same failing call. Do not call wait or see.\",\n `Current view was:\\n${waitResult.text}`,\n ].join(\"\\n\"),\n });\n\n const retry = await this.decideAction(actionTools, messages, usage);\n if (retry.name === \"wait\" || retry.name === \"see\") {\n const error = `Retry returned ${retry.name} instead of an action (after: ${firstError})`;\n this.emit({ event: \"turnFailed\", error });\n this.options.onTurnResult({\n ok: false,\n error,\n attempts: 1,\n attemptDetails,\n usage,\n });\n continue;\n }\n\n this.emit({ event: \"action\", action: retry.name, args: retry.arguments });\n result = await this.callTool(retry.name, retry.arguments);\n if (!result.isError) {\n this.options.onTurnResult({\n ok: true,\n action: retry.name,\n args: retry.arguments,\n result: result.json,\n attempts: 2,\n usage,\n });\n continue;\n }\n\n const secondError = toolErrorMessage(result);\n attemptDetails.push({ action: retry.name, args: retry.arguments, error: secondError });\n log(this.options.logger, \"warn\", `session ${this.options.sessionId} retry ${retry.name} failed: ${secondError}`);\n this.emit({ event: \"turnFailed\", action: retry.name, args: retry.arguments, error: secondError });\n this.options.onTurnResult({\n ok: false,\n error: secondError,\n attempts: 2,\n attemptDetails,\n usage,\n });\n }\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","/**\n * Wire protocol between AgentServer (SDK) and the platform. Version 1.\n * The platform's Go copy lives in White-Sands-Interactive/Platform, internal/protocol.\n */\n\nexport const PROTOCOL_VERSION = 1;\nexport const SDK_VERSION = \"1.0.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 { InlinePlatform, StartSessionRequest } from \"../types.js\";\nimport { createScriptedModel, type ToolCallRequest } from \"./model.js\";\nimport { loopEventToAgentEvent, SessionLoop } from \"./session-loop.js\";\n\n/**\n * In-process platform that replays a script of tool calls.\n * Same session loop as production; no network and no platform key.\n */\nexport function createTestPlatform(script: ToolCallRequest[]): InlinePlatform {\n const model = createScriptedModel(script);\n const loops = new Map<string, SessionLoop>();\n\n return {\n async startSession(request: StartSessionRequest) {\n const loop = new SessionLoop({\n sessionId: request.sessionId,\n transport: request.transport,\n instructions: request.instructions,\n ...(request.goal ? { goal: request.goal } : {}),\n model,\n ...(request.logger ? { logger: request.logger } : {}),\n onUsage: async (tokens) => {\n await request.onUsage?.(tokens);\n },\n onTurnResult: request.onTurnResult,\n onEvent: (event) => {\n request.onEvent?.(loopEventToAgentEvent(request.sessionId, event));\n },\n });\n loops.set(request.sessionId, loop);\n await loop.start();\n },\n\n async stopSession(sessionId: string) {\n const loop = loops.get(sessionId);\n if (!loop) return;\n loops.delete(sessionId);\n await loop.stop();\n },\n\n async close() {\n const ids = [...loops.keys()];\n for (const id of ids) {\n const loop = loops.get(id);\n loops.delete(id);\n await loop?.stop();\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,92 @@
1
+ import { I as InlinePlatform, L as Logger, b as AgentEvent } from './types-B4iGtwwk.cjs';
2
+ export { d as StartSessionRequest } from './types-B4iGtwwk.cjs';
3
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
4
+ import { SessionEventName, TurnReport } from './protocol.cjs';
5
+
6
+ type ToolCallRequest = {
7
+ name: string;
8
+ arguments: Record<string, unknown>;
9
+ };
10
+ type ModelMessage = {
11
+ role: "system";
12
+ content: string;
13
+ } | {
14
+ role: "user";
15
+ content: string;
16
+ } | {
17
+ role: "assistant";
18
+ content: string;
19
+ } | {
20
+ role: "tool";
21
+ name: string;
22
+ content: string;
23
+ isError?: boolean;
24
+ };
25
+ type ModelDecision = {
26
+ toolCall: ToolCallRequest;
27
+ usage: {
28
+ promptTokens: number;
29
+ completionTokens: number;
30
+ };
31
+ };
32
+ type ModelClient = {
33
+ /** Ask the model to choose exactly one tool call. */
34
+ decide(args: {
35
+ instructions: string;
36
+ tools: Array<{
37
+ name: string;
38
+ description: string;
39
+ inputSchema: unknown;
40
+ }>;
41
+ messages: ModelMessage[];
42
+ }): Promise<ModelDecision>;
43
+ };
44
+ /**
45
+ * Scripted model for tests: returns predetermined tool calls in order.
46
+ * When the queue is exhausted, always returns wait.
47
+ */
48
+ declare function createScriptedModel(script: ToolCallRequest[]): ModelClient;
49
+
50
+ /**
51
+ * In-process platform that replays a script of tool calls.
52
+ * Same session loop as production; no network and no platform key.
53
+ */
54
+ declare function createTestPlatform(script: ToolCallRequest[]): InlinePlatform;
55
+
56
+ type LoopEvent = {
57
+ event: SessionEventName;
58
+ action?: string;
59
+ args?: Record<string, unknown>;
60
+ error?: string;
61
+ };
62
+ declare function loopEventToAgentEvent(sessionId: string, event: LoopEvent): AgentEvent;
63
+ type SessionLoopOptions = {
64
+ sessionId: string;
65
+ transport: Transport;
66
+ instructions: string;
67
+ goal?: string;
68
+ model: ModelClient;
69
+ logger?: Logger;
70
+ onUsage: (tokens: number) => void | Promise<void>;
71
+ onTurnResult: (result: TurnReport) => void;
72
+ onEvent?: (event: LoopEvent) => void;
73
+ };
74
+ /**
75
+ * Per-session MCP client loop:
76
+ * wait → read view → ask model → one action → retry once on error → report turn.
77
+ */
78
+ declare class SessionLoop {
79
+ private readonly options;
80
+ private client;
81
+ private stopped;
82
+ private runPromise;
83
+ constructor(options: SessionLoopOptions);
84
+ start(): Promise<void>;
85
+ stop(): Promise<void>;
86
+ private callTool;
87
+ private decideAction;
88
+ private emit;
89
+ private run;
90
+ }
91
+
92
+ export { InlinePlatform, type LoopEvent, type ModelClient, type ModelDecision, type ModelMessage, SessionLoop, type SessionLoopOptions, type ToolCallRequest, createScriptedModel, createTestPlatform, loopEventToAgentEvent };
@@ -0,0 +1,92 @@
1
+ import { I as InlinePlatform, L as Logger, b as AgentEvent } from './types-BgUxWDKm.js';
2
+ export { d as StartSessionRequest } from './types-BgUxWDKm.js';
3
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
4
+ import { SessionEventName, TurnReport } from './protocol.js';
5
+
6
+ type ToolCallRequest = {
7
+ name: string;
8
+ arguments: Record<string, unknown>;
9
+ };
10
+ type ModelMessage = {
11
+ role: "system";
12
+ content: string;
13
+ } | {
14
+ role: "user";
15
+ content: string;
16
+ } | {
17
+ role: "assistant";
18
+ content: string;
19
+ } | {
20
+ role: "tool";
21
+ name: string;
22
+ content: string;
23
+ isError?: boolean;
24
+ };
25
+ type ModelDecision = {
26
+ toolCall: ToolCallRequest;
27
+ usage: {
28
+ promptTokens: number;
29
+ completionTokens: number;
30
+ };
31
+ };
32
+ type ModelClient = {
33
+ /** Ask the model to choose exactly one tool call. */
34
+ decide(args: {
35
+ instructions: string;
36
+ tools: Array<{
37
+ name: string;
38
+ description: string;
39
+ inputSchema: unknown;
40
+ }>;
41
+ messages: ModelMessage[];
42
+ }): Promise<ModelDecision>;
43
+ };
44
+ /**
45
+ * Scripted model for tests: returns predetermined tool calls in order.
46
+ * When the queue is exhausted, always returns wait.
47
+ */
48
+ declare function createScriptedModel(script: ToolCallRequest[]): ModelClient;
49
+
50
+ /**
51
+ * In-process platform that replays a script of tool calls.
52
+ * Same session loop as production; no network and no platform key.
53
+ */
54
+ declare function createTestPlatform(script: ToolCallRequest[]): InlinePlatform;
55
+
56
+ type LoopEvent = {
57
+ event: SessionEventName;
58
+ action?: string;
59
+ args?: Record<string, unknown>;
60
+ error?: string;
61
+ };
62
+ declare function loopEventToAgentEvent(sessionId: string, event: LoopEvent): AgentEvent;
63
+ type SessionLoopOptions = {
64
+ sessionId: string;
65
+ transport: Transport;
66
+ instructions: string;
67
+ goal?: string;
68
+ model: ModelClient;
69
+ logger?: Logger;
70
+ onUsage: (tokens: number) => void | Promise<void>;
71
+ onTurnResult: (result: TurnReport) => void;
72
+ onEvent?: (event: LoopEvent) => void;
73
+ };
74
+ /**
75
+ * Per-session MCP client loop:
76
+ * wait → read view → ask model → one action → retry once on error → report turn.
77
+ */
78
+ declare class SessionLoop {
79
+ private readonly options;
80
+ private client;
81
+ private stopped;
82
+ private runPromise;
83
+ constructor(options: SessionLoopOptions);
84
+ start(): Promise<void>;
85
+ stop(): Promise<void>;
86
+ private callTool;
87
+ private decideAction;
88
+ private emit;
89
+ private run;
90
+ }
91
+
92
+ export { InlinePlatform, type LoopEvent, type ModelClient, type ModelDecision, type ModelMessage, SessionLoop, type SessionLoopOptions, type ToolCallRequest, createScriptedModel, createTestPlatform, loopEventToAgentEvent };