sandbox-agent 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +18 -4
- package/dist/index.js +76 -19
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -798,16 +798,26 @@ type QueryParams<T> = T extends {
|
|
|
798
798
|
};
|
|
799
799
|
} ? Q : never;
|
|
800
800
|
|
|
801
|
-
interface
|
|
802
|
-
|
|
801
|
+
interface SandboxAgentConnectCommonOptions {
|
|
802
|
+
headers?: HeadersInit;
|
|
803
|
+
persist?: SessionPersistDriver;
|
|
804
|
+
replayMaxEvents?: number;
|
|
805
|
+
replayMaxChars?: number;
|
|
803
806
|
token?: string;
|
|
807
|
+
}
|
|
808
|
+
type SandboxAgentConnectOptions = (SandboxAgentConnectCommonOptions & {
|
|
809
|
+
baseUrl: string;
|
|
810
|
+
fetch?: typeof fetch;
|
|
811
|
+
}) | (SandboxAgentConnectCommonOptions & {
|
|
812
|
+
fetch: typeof fetch;
|
|
813
|
+
baseUrl?: string;
|
|
814
|
+
});
|
|
815
|
+
interface SandboxAgentStartOptions {
|
|
804
816
|
fetch?: typeof fetch;
|
|
805
817
|
headers?: HeadersInit;
|
|
806
818
|
persist?: SessionPersistDriver;
|
|
807
819
|
replayMaxEvents?: number;
|
|
808
820
|
replayMaxChars?: number;
|
|
809
|
-
}
|
|
810
|
-
interface SandboxAgentStartOptions extends Omit<SandboxAgentConnectOptions, "baseUrl" | "token"> {
|
|
811
821
|
spawn?: SandboxAgentSpawnOptions | boolean;
|
|
812
822
|
}
|
|
813
823
|
interface SessionCreateRequest {
|
|
@@ -856,6 +866,8 @@ declare class LiveAcpConnection {
|
|
|
856
866
|
private readonly pendingNewSessionLocals;
|
|
857
867
|
private readonly pendingRequestSessionById;
|
|
858
868
|
private readonly pendingReplayByLocalSessionId;
|
|
869
|
+
private lastAdapterExit;
|
|
870
|
+
private lastAdapterExitAt;
|
|
859
871
|
private readonly onObservedEnvelope;
|
|
860
872
|
private constructor();
|
|
861
873
|
static create(options: {
|
|
@@ -874,6 +886,7 @@ declare class LiveAcpConnection {
|
|
|
874
886
|
createRemoteSession(localSessionId: string, sessionInit: Omit<NewSessionRequest, "_meta">): Promise<NewSessionResponse>;
|
|
875
887
|
sendSessionMethod(localSessionId: string, method: string, params: Record<string, unknown>, options: SessionSendOptions): Promise<unknown>;
|
|
876
888
|
private handleEnvelope;
|
|
889
|
+
private handleAdapterNotification;
|
|
877
890
|
private resolveSessionId;
|
|
878
891
|
private localFromEnvelopeParams;
|
|
879
892
|
}
|
|
@@ -887,6 +900,7 @@ declare class SandboxAgent {
|
|
|
887
900
|
private readonly replayMaxChars;
|
|
888
901
|
private spawnHandle?;
|
|
889
902
|
private readonly liveConnections;
|
|
903
|
+
private readonly pendingLiveConnections;
|
|
890
904
|
private readonly sessionHandles;
|
|
891
905
|
private readonly eventListeners;
|
|
892
906
|
private readonly nextSessionEventIndexBySession;
|
package/dist/index.js
CHANGED
|
@@ -121,6 +121,7 @@ function parseCursor(cursor) {
|
|
|
121
121
|
// src/client.ts
|
|
122
122
|
var API_PREFIX = "/v1";
|
|
123
123
|
var FS_PATH = `${API_PREFIX}/fs`;
|
|
124
|
+
var DEFAULT_BASE_URL = "http://sandbox-agent";
|
|
124
125
|
var DEFAULT_REPLAY_MAX_EVENTS = 50;
|
|
125
126
|
var DEFAULT_REPLAY_MAX_CHARS = 12e3;
|
|
126
127
|
var EVENT_INDEX_SCAN_EVENTS_LIMIT = 500;
|
|
@@ -197,6 +198,8 @@ var LiveAcpConnection = class _LiveAcpConnection {
|
|
|
197
198
|
pendingNewSessionLocals = [];
|
|
198
199
|
pendingRequestSessionById = /* @__PURE__ */ new Map();
|
|
199
200
|
pendingReplayByLocalSessionId = /* @__PURE__ */ new Map();
|
|
201
|
+
lastAdapterExit = null;
|
|
202
|
+
lastAdapterExitAt = 0;
|
|
200
203
|
onObservedEnvelope;
|
|
201
204
|
constructor(agent, connectionId, acp, onObservedEnvelope) {
|
|
202
205
|
this.agent = agent;
|
|
@@ -218,6 +221,10 @@ var LiveAcpConnection = class _LiveAcpConnection {
|
|
|
218
221
|
},
|
|
219
222
|
client: {
|
|
220
223
|
sessionUpdate: async (_notification) => {
|
|
224
|
+
},
|
|
225
|
+
extNotification: async (method, params) => {
|
|
226
|
+
if (!live) return;
|
|
227
|
+
live.handleAdapterNotification(method, params);
|
|
221
228
|
}
|
|
222
229
|
},
|
|
223
230
|
onEnvelope: (envelope, direction) => {
|
|
@@ -265,6 +272,7 @@ var LiveAcpConnection = class _LiveAcpConnection {
|
|
|
265
272
|
this.pendingReplayByLocalSessionId.set(localSessionId, replayText);
|
|
266
273
|
}
|
|
267
274
|
async createRemoteSession(localSessionId, sessionInit) {
|
|
275
|
+
const createStartedAt = Date.now();
|
|
268
276
|
this.pendingNewSessionLocals.push(localSessionId);
|
|
269
277
|
try {
|
|
270
278
|
const response = await this.acp.newSession(sessionInit);
|
|
@@ -275,6 +283,11 @@ var LiveAcpConnection = class _LiveAcpConnection {
|
|
|
275
283
|
if (index !== -1) {
|
|
276
284
|
this.pendingNewSessionLocals.splice(index, 1);
|
|
277
285
|
}
|
|
286
|
+
const adapterExit = this.lastAdapterExit;
|
|
287
|
+
if (adapterExit && this.lastAdapterExitAt >= createStartedAt) {
|
|
288
|
+
const suffix = adapterExit.code == null ? "" : ` (code ${adapterExit.code})`;
|
|
289
|
+
throw new Error(`Agent process exited while creating session${suffix}`);
|
|
290
|
+
}
|
|
278
291
|
throw error;
|
|
279
292
|
}
|
|
280
293
|
}
|
|
@@ -316,6 +329,16 @@ var LiveAcpConnection = class _LiveAcpConnection {
|
|
|
316
329
|
const localSessionId = this.resolveSessionId(envelope, direction);
|
|
317
330
|
this.onObservedEnvelope(this, envelope, direction, localSessionId);
|
|
318
331
|
}
|
|
332
|
+
handleAdapterNotification(method, params) {
|
|
333
|
+
if (method !== "_adapter/agent_exited") {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
this.lastAdapterExit = {
|
|
337
|
+
success: params.success === true,
|
|
338
|
+
code: typeof params.code === "number" ? params.code : null
|
|
339
|
+
};
|
|
340
|
+
this.lastAdapterExitAt = Date.now();
|
|
341
|
+
}
|
|
319
342
|
resolveSessionId(envelope, direction) {
|
|
320
343
|
const id = envelopeId(envelope);
|
|
321
344
|
const method = envelopeMethod(envelope);
|
|
@@ -364,21 +387,27 @@ var SandboxAgent = class _SandboxAgent {
|
|
|
364
387
|
replayMaxChars;
|
|
365
388
|
spawnHandle;
|
|
366
389
|
liveConnections = /* @__PURE__ */ new Map();
|
|
390
|
+
pendingLiveConnections = /* @__PURE__ */ new Map();
|
|
367
391
|
sessionHandles = /* @__PURE__ */ new Map();
|
|
368
392
|
eventListeners = /* @__PURE__ */ new Map();
|
|
369
393
|
nextSessionEventIndexBySession = /* @__PURE__ */ new Map();
|
|
370
394
|
seedSessionEventIndexBySession = /* @__PURE__ */ new Map();
|
|
371
395
|
constructor(options) {
|
|
372
|
-
|
|
396
|
+
const baseUrl = options.baseUrl?.trim();
|
|
397
|
+
if (!baseUrl && !options.fetch) {
|
|
398
|
+
throw new Error("baseUrl is required unless fetch is provided.");
|
|
399
|
+
}
|
|
400
|
+
this.baseUrl = (baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
373
401
|
this.token = options.token;
|
|
374
|
-
|
|
402
|
+
const resolvedFetch = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
403
|
+
if (!resolvedFetch) {
|
|
404
|
+
throw new Error("Fetch API is not available; provide a fetch implementation.");
|
|
405
|
+
}
|
|
406
|
+
this.fetcher = resolvedFetch;
|
|
375
407
|
this.defaultHeaders = options.headers;
|
|
376
408
|
this.persist = options.persist ?? new InMemorySessionPersistDriver();
|
|
377
409
|
this.replayMaxEvents = normalizePositiveInt(options.replayMaxEvents, DEFAULT_REPLAY_MAX_EVENTS);
|
|
378
410
|
this.replayMaxChars = normalizePositiveInt(options.replayMaxChars, DEFAULT_REPLAY_MAX_CHARS);
|
|
379
|
-
if (!this.fetcher) {
|
|
380
|
-
throw new Error("Fetch API is not available; provide a fetch implementation.");
|
|
381
|
-
}
|
|
382
411
|
}
|
|
383
412
|
static async connect(options) {
|
|
384
413
|
return new _SandboxAgent(options);
|
|
@@ -389,7 +418,8 @@ var SandboxAgent = class _SandboxAgent {
|
|
|
389
418
|
throw new Error("SandboxAgent.start requires spawn to be enabled.");
|
|
390
419
|
}
|
|
391
420
|
const { spawnSandboxAgent } = await import("./spawn-BQVVCZX7.js");
|
|
392
|
-
const
|
|
421
|
+
const resolvedFetch = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
422
|
+
const handle = await spawnSandboxAgent(spawnOptions, resolvedFetch);
|
|
393
423
|
const client = new _SandboxAgent({
|
|
394
424
|
baseUrl: handle.baseUrl,
|
|
395
425
|
token: handle.token,
|
|
@@ -405,6 +435,14 @@ var SandboxAgent = class _SandboxAgent {
|
|
|
405
435
|
async dispose() {
|
|
406
436
|
const connections = [...this.liveConnections.values()];
|
|
407
437
|
this.liveConnections.clear();
|
|
438
|
+
const pending = [...this.pendingLiveConnections.values()];
|
|
439
|
+
this.pendingLiveConnections.clear();
|
|
440
|
+
const pendingSettled = await Promise.allSettled(pending);
|
|
441
|
+
for (const item of pendingSettled) {
|
|
442
|
+
if (item.status === "fulfilled") {
|
|
443
|
+
connections.push(item.value);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
408
446
|
await Promise.all(
|
|
409
447
|
connections.map(async (connection) => {
|
|
410
448
|
await connection.close();
|
|
@@ -614,20 +652,39 @@ var SandboxAgent = class _SandboxAgent {
|
|
|
614
652
|
if (existing) {
|
|
615
653
|
return existing;
|
|
616
654
|
}
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
655
|
+
const pending = this.pendingLiveConnections.get(agent);
|
|
656
|
+
if (pending) {
|
|
657
|
+
return pending;
|
|
658
|
+
}
|
|
659
|
+
const creating = (async () => {
|
|
660
|
+
const serverId = `sdk-${agent}-${randomId()}`;
|
|
661
|
+
const created = await LiveAcpConnection.create({
|
|
662
|
+
baseUrl: this.baseUrl,
|
|
663
|
+
token: this.token,
|
|
664
|
+
fetcher: this.fetcher,
|
|
665
|
+
headers: this.defaultHeaders,
|
|
666
|
+
agent,
|
|
667
|
+
serverId,
|
|
668
|
+
onObservedEnvelope: (connection, envelope, direction, localSessionId) => {
|
|
669
|
+
void this.persistObservedEnvelope(connection, envelope, direction, localSessionId);
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
const raced = this.liveConnections.get(agent);
|
|
673
|
+
if (raced) {
|
|
674
|
+
await created.close();
|
|
675
|
+
return raced;
|
|
627
676
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
677
|
+
this.liveConnections.set(agent, created);
|
|
678
|
+
return created;
|
|
679
|
+
})();
|
|
680
|
+
this.pendingLiveConnections.set(agent, creating);
|
|
681
|
+
try {
|
|
682
|
+
return await creating;
|
|
683
|
+
} finally {
|
|
684
|
+
if (this.pendingLiveConnections.get(agent) === creating) {
|
|
685
|
+
this.pendingLiveConnections.delete(agent);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
631
688
|
}
|
|
632
689
|
async persistObservedEnvelope(connection, envelope, direction, localSessionId) {
|
|
633
690
|
if (!localSessionId) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/types.ts","../src/index.ts","../src/inspector.ts"],"sourcesContent":["import {\n AcpHttpClient,\n PROTOCOL_VERSION,\n type AcpEnvelopeDirection,\n type AnyMessage,\n type AuthMethod,\n type CancelNotification,\n type NewSessionRequest,\n type NewSessionResponse,\n type PromptRequest,\n type PromptResponse,\n type SessionNotification,\n type SetSessionConfigOptionRequest,\n type SetSessionModeRequest,\n} from \"acp-http-client\";\nimport type { SandboxAgentSpawnHandle, SandboxAgentSpawnOptions } from \"./spawn.ts\";\nimport {\n type AcpServerListResponse,\n type AgentInfo,\n type AgentInstallRequest,\n type AgentInstallResponse,\n type AgentListResponse,\n type FsActionResponse,\n type FsDeleteQuery,\n type FsEntriesQuery,\n type FsEntry,\n type FsMoveRequest,\n type FsMoveResponse,\n type FsPathQuery,\n type FsStat,\n type FsUploadBatchQuery,\n type FsUploadBatchResponse,\n type FsWriteResponse,\n type HealthResponse,\n InMemorySessionPersistDriver,\n type ListEventsRequest,\n type ListPage,\n type ListPageRequest,\n type McpConfigQuery,\n type McpServerConfig,\n type ProblemDetails,\n type SessionEvent,\n type SessionPersistDriver,\n type SessionRecord,\n type SkillsConfig,\n type SkillsConfigQuery,\n} from \"./types.ts\";\n\nconst API_PREFIX = \"/v1\";\nconst FS_PATH = `${API_PREFIX}/fs`;\n\nconst DEFAULT_REPLAY_MAX_EVENTS = 50;\nconst DEFAULT_REPLAY_MAX_CHARS = 12_000;\nconst EVENT_INDEX_SCAN_EVENTS_LIMIT = 500;\n\nexport interface SandboxAgentConnectOptions {\n baseUrl: string;\n token?: string;\n fetch?: typeof fetch;\n headers?: HeadersInit;\n persist?: SessionPersistDriver;\n replayMaxEvents?: number;\n replayMaxChars?: number;\n}\n\nexport interface SandboxAgentStartOptions extends Omit<SandboxAgentConnectOptions, \"baseUrl\" | \"token\"> {\n spawn?: SandboxAgentSpawnOptions | boolean;\n}\n\nexport interface SessionCreateRequest {\n id?: string;\n agent: string;\n sessionInit?: Omit<NewSessionRequest, \"_meta\">;\n}\n\nexport interface SessionResumeOrCreateRequest {\n id: string;\n agent: string;\n sessionInit?: Omit<NewSessionRequest, \"_meta\">;\n}\n\nexport interface SessionSendOptions {\n notification?: boolean;\n}\n\nexport type SessionEventListener = (event: SessionEvent) => void;\n\nexport class SandboxAgentError extends Error {\n readonly status: number;\n readonly problem?: ProblemDetails;\n readonly response: Response;\n\n constructor(status: number, problem: ProblemDetails | undefined, response: Response) {\n super(problem?.title ?? `Request failed with status ${status}`);\n this.name = \"SandboxAgentError\";\n this.status = status;\n this.problem = problem;\n this.response = response;\n }\n}\n\nexport class Session {\n private record: SessionRecord;\n private readonly sandbox: SandboxAgent;\n\n constructor(sandbox: SandboxAgent, record: SessionRecord) {\n this.sandbox = sandbox;\n this.record = { ...record };\n }\n\n get id(): string {\n return this.record.id;\n }\n\n get agent(): string {\n return this.record.agent;\n }\n\n get agentSessionId(): string {\n return this.record.agentSessionId;\n }\n\n get lastConnectionId(): string {\n return this.record.lastConnectionId;\n }\n\n get createdAt(): number {\n return this.record.createdAt;\n }\n\n get destroyedAt(): number | undefined {\n return this.record.destroyedAt;\n }\n\n async refresh(): Promise<Session> {\n const latest = await this.sandbox.getSession(this.id);\n if (!latest) {\n throw new Error(`session '${this.id}' no longer exists`);\n }\n this.apply(latest.toRecord());\n return this;\n }\n\n async send(method: string, params: Record<string, unknown> = {}, options: SessionSendOptions = {}): Promise<unknown> {\n const updated = await this.sandbox.sendSessionMethod(this.id, method, params, options);\n this.apply(updated.session.toRecord());\n return updated.response;\n }\n\n async prompt(prompt: PromptRequest[\"prompt\"]): Promise<PromptResponse> {\n const response = await this.send(\"session/prompt\", { prompt });\n return response as PromptResponse;\n }\n\n onEvent(listener: SessionEventListener): () => void {\n return this.sandbox.onSessionEvent(this.id, listener);\n }\n\n toRecord(): SessionRecord {\n return { ...this.record };\n }\n\n apply(record: SessionRecord): void {\n this.record = { ...record };\n }\n}\n\nexport class LiveAcpConnection {\n readonly connectionId: string;\n readonly agent: string;\n\n private readonly acp: AcpHttpClient;\n private readonly sessionByLocalId = new Map<string, string>();\n private readonly localByAgentSessionId = new Map<string, string>();\n private readonly pendingNewSessionLocals: string[] = [];\n private readonly pendingRequestSessionById = new Map<string, string>();\n private readonly pendingReplayByLocalSessionId = new Map<string, string>();\n\n private readonly onObservedEnvelope: (\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ) => void;\n\n private constructor(\n agent: string,\n connectionId: string,\n acp: AcpHttpClient,\n onObservedEnvelope: (\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ) => void,\n ) {\n this.agent = agent;\n this.connectionId = connectionId;\n this.acp = acp;\n this.onObservedEnvelope = onObservedEnvelope;\n }\n\n static async create(options: {\n baseUrl: string;\n token?: string;\n fetcher: typeof fetch;\n headers?: HeadersInit;\n agent: string;\n serverId: string;\n onObservedEnvelope: (\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ) => void;\n }): Promise<LiveAcpConnection> {\n const connectionId = randomId();\n\n let live: LiveAcpConnection | null = null;\n const acp = new AcpHttpClient({\n baseUrl: options.baseUrl,\n token: options.token,\n fetch: options.fetcher,\n headers: options.headers,\n transport: {\n path: `${API_PREFIX}/acp/${encodeURIComponent(options.serverId)}`,\n bootstrapQuery: { agent: options.agent },\n },\n client: {\n sessionUpdate: async (_notification: SessionNotification) => {\n // Session updates are observed via envelope persistence.\n },\n },\n onEnvelope: (envelope, direction) => {\n if (!live) {\n return;\n }\n live.handleEnvelope(envelope, direction);\n },\n });\n\n live = new LiveAcpConnection(options.agent, connectionId, acp, options.onObservedEnvelope);\n\n const initResult = await acp.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientInfo: {\n name: \"sandbox-agent-sdk\",\n version: \"v1\",\n },\n });\n if (initResult.authMethods && initResult.authMethods.length > 0) {\n await autoAuthenticate(acp, initResult.authMethods);\n }\n return live;\n }\n\n async close(): Promise<void> {\n await this.acp.disconnect();\n }\n\n hasBoundSession(localSessionId: string, agentSessionId?: string): boolean {\n const bound = this.sessionByLocalId.get(localSessionId);\n if (!bound) {\n return false;\n }\n if (agentSessionId && bound !== agentSessionId) {\n return false;\n }\n return true;\n }\n\n bindSession(localSessionId: string, agentSessionId: string): void {\n this.sessionByLocalId.set(localSessionId, agentSessionId);\n this.localByAgentSessionId.set(agentSessionId, localSessionId);\n }\n\n queueReplay(localSessionId: string, replayText: string | null): void {\n if (!replayText) {\n this.pendingReplayByLocalSessionId.delete(localSessionId);\n return;\n }\n this.pendingReplayByLocalSessionId.set(localSessionId, replayText);\n }\n\n async createRemoteSession(\n localSessionId: string,\n sessionInit: Omit<NewSessionRequest, \"_meta\">,\n ): Promise<NewSessionResponse> {\n this.pendingNewSessionLocals.push(localSessionId);\n\n try {\n const response = await this.acp.newSession(sessionInit);\n this.bindSession(localSessionId, response.sessionId);\n return response;\n } catch (error) {\n const index = this.pendingNewSessionLocals.indexOf(localSessionId);\n if (index !== -1) {\n this.pendingNewSessionLocals.splice(index, 1);\n }\n throw error;\n }\n }\n\n async sendSessionMethod(\n localSessionId: string,\n method: string,\n params: Record<string, unknown>,\n options: SessionSendOptions,\n ): Promise<unknown> {\n const agentSessionId = this.sessionByLocalId.get(localSessionId);\n if (!agentSessionId) {\n throw new Error(`session '${localSessionId}' is not bound to live ACP connection '${this.connectionId}'`);\n }\n\n const mappedParams = mapSessionParams(params, agentSessionId);\n\n if (method === \"session/prompt\") {\n const replayText = this.pendingReplayByLocalSessionId.get(localSessionId);\n if (replayText) {\n // TODO: Replace this synthesized replay text with ACP-native restore once standardized.\n this.pendingReplayByLocalSessionId.delete(localSessionId);\n injectReplayPrompt(mappedParams, replayText);\n }\n\n if (options.notification) {\n await this.acp.extNotification(method, mappedParams);\n return undefined;\n }\n\n return this.acp.prompt(mappedParams as PromptRequest);\n }\n\n if (method === \"session/cancel\") {\n await this.acp.cancel(mappedParams as CancelNotification);\n return undefined;\n }\n\n if (method === \"session/set_mode\") {\n return this.acp.setSessionMode(mappedParams as SetSessionModeRequest);\n }\n\n if (method === \"session/set_config_option\") {\n return this.acp.setSessionConfigOption(mappedParams as SetSessionConfigOptionRequest);\n }\n\n if (options.notification) {\n await this.acp.extNotification(method, mappedParams);\n return undefined;\n }\n\n return this.acp.extMethod(method, mappedParams);\n }\n\n private handleEnvelope(envelope: AnyMessage, direction: AcpEnvelopeDirection): void {\n const localSessionId = this.resolveSessionId(envelope, direction);\n this.onObservedEnvelope(this, envelope, direction, localSessionId);\n }\n\n private resolveSessionId(envelope: AnyMessage, direction: AcpEnvelopeDirection): string | null {\n const id = envelopeId(envelope);\n const method = envelopeMethod(envelope);\n\n if (direction === \"outbound\") {\n if (id && method === \"session/new\") {\n const localSessionId = this.pendingNewSessionLocals.shift() ?? null;\n if (localSessionId) {\n this.pendingRequestSessionById.set(id, localSessionId);\n }\n return localSessionId;\n }\n\n const localFromParams = this.localFromEnvelopeParams(envelope);\n if (id && localFromParams) {\n this.pendingRequestSessionById.set(id, localFromParams);\n }\n return localFromParams;\n }\n\n if (id) {\n const pending = this.pendingRequestSessionById.get(id) ?? null;\n if (pending) {\n this.pendingRequestSessionById.delete(id);\n const sessionIdFromResult = envelopeSessionIdFromResult(envelope);\n if (sessionIdFromResult) {\n this.bindSession(pending, sessionIdFromResult);\n }\n return pending;\n }\n }\n\n return this.localFromEnvelopeParams(envelope);\n }\n\n private localFromEnvelopeParams(envelope: AnyMessage): string | null {\n const agentSessionId = envelopeSessionIdFromParams(envelope);\n if (!agentSessionId) {\n return null;\n }\n return this.localByAgentSessionId.get(agentSessionId) ?? null;\n }\n}\n\nexport class SandboxAgent {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly fetcher: typeof fetch;\n private readonly defaultHeaders?: HeadersInit;\n\n private readonly persist: SessionPersistDriver;\n private readonly replayMaxEvents: number;\n private readonly replayMaxChars: number;\n\n private spawnHandle?: SandboxAgentSpawnHandle;\n\n private readonly liveConnections = new Map<string, LiveAcpConnection>();\n private readonly sessionHandles = new Map<string, Session>();\n private readonly eventListeners = new Map<string, Set<SessionEventListener>>();\n private readonly nextSessionEventIndexBySession = new Map<string, number>();\n private readonly seedSessionEventIndexBySession = new Map<string, Promise<void>>();\n\n constructor(options: SandboxAgentConnectOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n this.fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.defaultHeaders = options.headers;\n this.persist = options.persist ?? new InMemorySessionPersistDriver();\n\n this.replayMaxEvents = normalizePositiveInt(options.replayMaxEvents, DEFAULT_REPLAY_MAX_EVENTS);\n this.replayMaxChars = normalizePositiveInt(options.replayMaxChars, DEFAULT_REPLAY_MAX_CHARS);\n\n if (!this.fetcher) {\n throw new Error(\"Fetch API is not available; provide a fetch implementation.\");\n }\n }\n\n static async connect(options: SandboxAgentConnectOptions): Promise<SandboxAgent> {\n return new SandboxAgent(options);\n }\n\n static async start(options: SandboxAgentStartOptions = {}): Promise<SandboxAgent> {\n const spawnOptions = normalizeSpawnOptions(options.spawn, true);\n if (!spawnOptions.enabled) {\n throw new Error(\"SandboxAgent.start requires spawn to be enabled.\");\n }\n\n const { spawnSandboxAgent } = await import(\"./spawn.js\");\n const handle = await spawnSandboxAgent(spawnOptions, options.fetch ?? globalThis.fetch);\n\n const client = new SandboxAgent({\n baseUrl: handle.baseUrl,\n token: handle.token,\n fetch: options.fetch,\n headers: options.headers,\n persist: options.persist,\n replayMaxEvents: options.replayMaxEvents,\n replayMaxChars: options.replayMaxChars,\n });\n\n client.spawnHandle = handle;\n return client;\n }\n\n async dispose(): Promise<void> {\n const connections = [...this.liveConnections.values()];\n this.liveConnections.clear();\n\n await Promise.all(\n connections.map(async (connection) => {\n await connection.close();\n }),\n );\n\n if (this.spawnHandle) {\n await this.spawnHandle.dispose();\n this.spawnHandle = undefined;\n }\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<Session>> {\n const page = await this.persist.listSessions(request);\n return {\n items: page.items.map((record) => this.upsertSessionHandle(record)),\n nextCursor: page.nextCursor,\n };\n }\n\n async getSession(id: string): Promise<Session | null> {\n const record = await this.persist.getSession(id);\n if (!record) {\n return null;\n }\n return this.upsertSessionHandle(record);\n }\n\n async getEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n return this.persist.listEvents(request);\n }\n\n async createSession(request: SessionCreateRequest): Promise<Session> {\n if (!request.agent.trim()) {\n throw new Error(\"createSession requires a non-empty agent\");\n }\n\n const localSessionId = request.id?.trim() || randomId();\n const live = await this.getLiveConnection(request.agent.trim());\n const sessionInit = normalizeSessionInit(request.sessionInit);\n\n const response = await live.createRemoteSession(localSessionId, sessionInit);\n\n const record: SessionRecord = {\n id: localSessionId,\n agent: request.agent.trim(),\n agentSessionId: response.sessionId,\n lastConnectionId: live.connectionId,\n createdAt: nowMs(),\n sessionInit,\n };\n\n await this.persist.updateSession(record);\n this.nextSessionEventIndexBySession.set(record.id, 1);\n live.bindSession(record.id, record.agentSessionId);\n return this.upsertSessionHandle(record);\n }\n\n async resumeSession(id: string): Promise<Session> {\n const existing = await this.persist.getSession(id);\n if (!existing) {\n throw new Error(`session '${id}' not found`);\n }\n\n const live = await this.getLiveConnection(existing.agent);\n if (existing.lastConnectionId === live.connectionId && live.hasBoundSession(id, existing.agentSessionId)) {\n return this.upsertSessionHandle(existing);\n }\n\n const replaySource = await this.collectReplayEvents(existing.id, this.replayMaxEvents);\n const replayText = buildReplayText(replaySource, this.replayMaxChars);\n\n const recreated = await live.createRemoteSession(existing.id, normalizeSessionInit(existing.sessionInit));\n\n const updated: SessionRecord = {\n ...existing,\n agentSessionId: recreated.sessionId,\n lastConnectionId: live.connectionId,\n destroyedAt: undefined,\n };\n\n await this.persist.updateSession(updated);\n live.bindSession(updated.id, updated.agentSessionId);\n live.queueReplay(updated.id, replayText);\n\n return this.upsertSessionHandle(updated);\n }\n\n async resumeOrCreateSession(request: SessionResumeOrCreateRequest): Promise<Session> {\n const existing = await this.persist.getSession(request.id);\n if (existing) {\n return this.resumeSession(existing.id);\n }\n return this.createSession(request);\n }\n\n async destroySession(id: string): Promise<Session> {\n const existing = await this.persist.getSession(id);\n if (!existing) {\n throw new Error(`session '${id}' not found`);\n }\n\n const updated: SessionRecord = {\n ...existing,\n destroyedAt: nowMs(),\n };\n\n await this.persist.updateSession(updated);\n return this.upsertSessionHandle(updated);\n }\n\n async sendSessionMethod(\n sessionId: string,\n method: string,\n params: Record<string, unknown>,\n options: SessionSendOptions = {},\n ): Promise<{ session: Session; response: unknown }> {\n const record = await this.persist.getSession(sessionId);\n if (!record) {\n throw new Error(`session '${sessionId}' not found`);\n }\n\n const live = await this.getLiveConnection(record.agent);\n if (!live.hasBoundSession(record.id, record.agentSessionId)) {\n // The persisted session points at a stale connection; restore lazily.\n const restored = await this.resumeSession(record.id);\n return this.sendSessionMethod(restored.id, method, params, options);\n }\n\n const response = await live.sendSessionMethod(record.id, method, params, options);\n const refreshed = await this.requireSessionRecord(record.id);\n return {\n session: this.upsertSessionHandle(refreshed),\n response,\n };\n }\n\n onSessionEvent(sessionId: string, listener: SessionEventListener): () => void {\n const listeners = this.eventListeners.get(sessionId) ?? new Set<SessionEventListener>();\n listeners.add(listener);\n this.eventListeners.set(sessionId, listeners);\n\n return () => {\n const set = this.eventListeners.get(sessionId);\n if (!set) {\n return;\n }\n set.delete(listener);\n if (set.size === 0) {\n this.eventListeners.delete(sessionId);\n }\n };\n }\n\n async getHealth(): Promise<HealthResponse> {\n return this.requestJson(\"GET\", `${API_PREFIX}/health`);\n }\n\n async listAgents(options?: { config?: boolean }): Promise<AgentListResponse> {\n return this.requestJson(\"GET\", `${API_PREFIX}/agents`, {\n query: options?.config ? { config: \"true\" } : undefined,\n });\n }\n\n async getAgent(agent: string, options?: { config?: boolean }): Promise<AgentInfo> {\n return this.requestJson(\"GET\", `${API_PREFIX}/agents/${encodeURIComponent(agent)}`, {\n query: options?.config ? { config: \"true\" } : undefined,\n });\n }\n\n async installAgent(agent: string, request: AgentInstallRequest = {}): Promise<AgentInstallResponse> {\n return this.requestJson(\"POST\", `${API_PREFIX}/agents/${encodeURIComponent(agent)}/install`, {\n body: request,\n });\n }\n\n async listAcpServers(): Promise<AcpServerListResponse> {\n return this.requestJson(\"GET\", `${API_PREFIX}/acp`);\n }\n\n async listFsEntries(query: FsEntriesQuery = {}): Promise<FsEntry[]> {\n return this.requestJson(\"GET\", `${FS_PATH}/entries`, {\n query,\n });\n }\n\n async readFsFile(query: FsPathQuery): Promise<Uint8Array> {\n const response = await this.requestRaw(\"GET\", `${FS_PATH}/file`, {\n query,\n accept: \"application/octet-stream\",\n });\n const buffer = await response.arrayBuffer();\n return new Uint8Array(buffer);\n }\n\n async writeFsFile(query: FsPathQuery, body: BodyInit): Promise<FsWriteResponse> {\n const response = await this.requestRaw(\"PUT\", `${FS_PATH}/file`, {\n query,\n rawBody: body,\n contentType: \"application/octet-stream\",\n accept: \"application/json\",\n });\n return (await response.json()) as FsWriteResponse;\n }\n\n async deleteFsEntry(query: FsDeleteQuery): Promise<FsActionResponse> {\n return this.requestJson(\"DELETE\", `${FS_PATH}/entry`, { query });\n }\n\n async mkdirFs(query: FsPathQuery): Promise<FsActionResponse> {\n return this.requestJson(\"POST\", `${FS_PATH}/mkdir`, { query });\n }\n\n async moveFs(request: FsMoveRequest): Promise<FsMoveResponse> {\n return this.requestJson(\"POST\", `${FS_PATH}/move`, { body: request });\n }\n\n async statFs(query: FsPathQuery): Promise<FsStat> {\n return this.requestJson(\"GET\", `${FS_PATH}/stat`, { query });\n }\n\n async uploadFsBatch(body: BodyInit, query?: FsUploadBatchQuery): Promise<FsUploadBatchResponse> {\n const response = await this.requestRaw(\"POST\", `${FS_PATH}/upload-batch`, {\n query,\n rawBody: body,\n contentType: \"application/x-tar\",\n accept: \"application/json\",\n });\n return (await response.json()) as FsUploadBatchResponse;\n }\n\n async getMcpConfig(query: McpConfigQuery): Promise<McpServerConfig> {\n return this.requestJson(\"GET\", `${API_PREFIX}/config/mcp`, { query });\n }\n\n async setMcpConfig(query: McpConfigQuery, config: McpServerConfig): Promise<void> {\n await this.requestRaw(\"PUT\", `${API_PREFIX}/config/mcp`, { query, body: config });\n }\n\n async deleteMcpConfig(query: McpConfigQuery): Promise<void> {\n await this.requestRaw(\"DELETE\", `${API_PREFIX}/config/mcp`, { query });\n }\n\n async getSkillsConfig(query: SkillsConfigQuery): Promise<SkillsConfig> {\n return this.requestJson(\"GET\", `${API_PREFIX}/config/skills`, { query });\n }\n\n async setSkillsConfig(query: SkillsConfigQuery, config: SkillsConfig): Promise<void> {\n await this.requestRaw(\"PUT\", `${API_PREFIX}/config/skills`, { query, body: config });\n }\n\n async deleteSkillsConfig(query: SkillsConfigQuery): Promise<void> {\n await this.requestRaw(\"DELETE\", `${API_PREFIX}/config/skills`, { query });\n }\n\n private async getLiveConnection(agent: string): Promise<LiveAcpConnection> {\n const existing = this.liveConnections.get(agent);\n if (existing) {\n return existing;\n }\n\n const serverId = `sdk-${agent}-${randomId()}`;\n const created = await LiveAcpConnection.create({\n baseUrl: this.baseUrl,\n token: this.token,\n fetcher: this.fetcher,\n headers: this.defaultHeaders,\n agent,\n serverId,\n onObservedEnvelope: (connection, envelope, direction, localSessionId) => {\n void this.persistObservedEnvelope(connection, envelope, direction, localSessionId);\n },\n });\n\n this.liveConnections.set(agent, created);\n return created;\n }\n\n private async persistObservedEnvelope(\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ): Promise<void> {\n if (!localSessionId) {\n return;\n }\n\n const event: SessionEvent = {\n id: randomId(),\n eventIndex: await this.allocateSessionEventIndex(localSessionId),\n sessionId: localSessionId,\n createdAt: nowMs(),\n connectionId: connection.connectionId,\n sender: direction === \"outbound\" ? \"client\" : \"agent\",\n payload: cloneEnvelope(envelope),\n };\n\n await this.persist.insertEvent(event);\n\n const listeners = this.eventListeners.get(localSessionId);\n if (!listeners || listeners.size === 0) {\n return;\n }\n\n for (const listener of listeners) {\n listener(event);\n }\n }\n\n private async allocateSessionEventIndex(sessionId: string): Promise<number> {\n await this.ensureSessionEventIndexSeeded(sessionId);\n const nextIndex = this.nextSessionEventIndexBySession.get(sessionId) ?? 1;\n this.nextSessionEventIndexBySession.set(sessionId, nextIndex + 1);\n return nextIndex;\n }\n\n private async ensureSessionEventIndexSeeded(sessionId: string): Promise<void> {\n if (this.nextSessionEventIndexBySession.has(sessionId)) {\n return;\n }\n\n if (!this.seedSessionEventIndexBySession.has(sessionId)) {\n const pending = (async () => {\n const maxPersistedIndex = await this.findMaxPersistedSessionEventIndex(sessionId);\n this.nextSessionEventIndexBySession.set(sessionId, Math.max(1, maxPersistedIndex + 1));\n })().finally(() => {\n this.seedSessionEventIndexBySession.delete(sessionId);\n });\n this.seedSessionEventIndexBySession.set(sessionId, pending);\n }\n\n const pending = this.seedSessionEventIndexBySession.get(sessionId);\n if (pending) {\n await pending;\n }\n }\n\n private async findMaxPersistedSessionEventIndex(sessionId: string): Promise<number> {\n let maxIndex = 0;\n let eventCursor: string | undefined;\n\n while (true) {\n const eventsPage = await this.persist.listEvents({\n sessionId,\n cursor: eventCursor,\n limit: EVENT_INDEX_SCAN_EVENTS_LIMIT,\n });\n\n for (const event of eventsPage.items) {\n if (Number.isFinite(event.eventIndex) && event.eventIndex > maxIndex) {\n maxIndex = Math.floor(event.eventIndex);\n }\n }\n\n if (!eventsPage.nextCursor) {\n break;\n }\n eventCursor = eventsPage.nextCursor;\n }\n\n return maxIndex;\n }\n\n private async collectReplayEvents(sessionId: string, maxEvents: number): Promise<SessionEvent[]> {\n const all: SessionEvent[] = [];\n let cursor: string | undefined;\n\n while (true) {\n const page = await this.persist.listEvents({\n sessionId,\n cursor,\n limit: Math.max(100, maxEvents),\n });\n\n all.push(...page.items);\n\n if (!page.nextCursor) {\n break;\n }\n\n cursor = page.nextCursor;\n }\n\n return all.slice(-maxEvents);\n }\n\n private upsertSessionHandle(record: SessionRecord): Session {\n const existing = this.sessionHandles.get(record.id);\n if (existing) {\n existing.apply(record);\n return existing;\n }\n\n const created = new Session(this, record);\n this.sessionHandles.set(record.id, created);\n return created;\n }\n\n private async requireSessionRecord(id: string): Promise<SessionRecord> {\n const record = await this.persist.getSession(id);\n if (!record) {\n throw new Error(`session '${id}' not found`);\n }\n return record;\n }\n\n private async requestJson<T>(method: string, path: string, options: RequestOptions = {}): Promise<T> {\n const response = await this.requestRaw(method, path, {\n query: options.query,\n body: options.body,\n headers: options.headers,\n accept: options.accept ?? \"application/json\",\n signal: options.signal,\n });\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return (await response.json()) as T;\n }\n\n private async requestRaw(method: string, path: string, options: RequestOptions = {}): Promise<Response> {\n const url = this.buildUrl(path, options.query);\n const headers = this.buildHeaders(options.headers);\n\n if (options.accept) {\n headers.set(\"Accept\", options.accept);\n }\n\n const init: RequestInit = {\n method,\n headers,\n signal: options.signal,\n };\n\n if (options.rawBody !== undefined && options.body !== undefined) {\n throw new Error(\"requestRaw received both rawBody and body\");\n }\n\n if (options.rawBody !== undefined) {\n if (options.contentType) {\n headers.set(\"Content-Type\", options.contentType);\n }\n init.body = options.rawBody;\n } else if (options.body !== undefined) {\n headers.set(\"Content-Type\", \"application/json\");\n init.body = JSON.stringify(options.body);\n }\n\n const response = await this.fetcher(url, init);\n if (!response.ok) {\n const problem = await readProblem(response);\n throw new SandboxAgentError(response.status, problem, response);\n }\n\n return response;\n }\n\n private buildHeaders(extra?: HeadersInit): Headers {\n const headers = new Headers(this.defaultHeaders ?? undefined);\n\n if (this.token) {\n headers.set(\"Authorization\", `Bearer ${this.token}`);\n }\n\n if (extra) {\n const merged = new Headers(extra);\n merged.forEach((value, key) => headers.set(key, value));\n }\n\n return headers;\n }\n\n private buildUrl(path: string, query?: Record<string, QueryValue>): string {\n const url = new URL(`${this.baseUrl}${path}`);\n\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n url.searchParams.set(key, String(value));\n });\n }\n\n return url.toString();\n }\n}\n\ntype QueryValue = string | number | boolean | null | undefined;\n\ntype RequestOptions = {\n query?: Record<string, QueryValue>;\n body?: unknown;\n rawBody?: BodyInit;\n contentType?: string;\n headers?: HeadersInit;\n accept?: string;\n signal?: AbortSignal;\n};\n\n/**\n * Auto-select and call `authenticate` based on the agent's advertised auth methods.\n * Prefers env-var-based methods that the server process already has configured.\n */\nasync function autoAuthenticate(acp: AcpHttpClient, methods: AuthMethod[]): Promise<void> {\n // Only attempt env-var-based methods that the server process can satisfy\n // automatically. Interactive methods (e.g. \"claude-login\") cannot be\n // fulfilled programmatically and must be skipped.\n const envBased = methods.find(\n (m) =>\n m.id === \"codex-api-key\" ||\n m.id === \"openai-api-key\" ||\n m.id === \"anthropic-api-key\",\n );\n\n if (!envBased) {\n return;\n }\n\n try {\n await acp.authenticate({ methodId: envBased.id });\n } catch {\n // Authentication is best-effort; the agent may already have credentials\n // from env vars or credential files configured on the server side.\n }\n}\n\nfunction normalizeSessionInit(\n value: Omit<NewSessionRequest, \"_meta\"> | undefined,\n): Omit<NewSessionRequest, \"_meta\"> {\n if (!value) {\n return {\n cwd: defaultCwd(),\n mcpServers: [],\n };\n }\n\n return {\n ...value,\n cwd: value.cwd ?? defaultCwd(),\n mcpServers: value.mcpServers ?? [],\n };\n}\n\nfunction mapSessionParams(params: Record<string, unknown>, agentSessionId: string): Record<string, unknown> {\n return {\n ...params,\n sessionId: agentSessionId,\n };\n}\n\nfunction injectReplayPrompt(params: Record<string, unknown>, replayText: string): void {\n const prompt = Array.isArray(params.prompt) ? [...params.prompt] : [];\n prompt.unshift({\n type: \"text\",\n text: replayText,\n });\n params.prompt = prompt;\n}\n\nfunction buildReplayText(events: SessionEvent[], maxChars: number): string | null {\n if (events.length === 0) {\n return null;\n }\n\n const prefix =\n \"Previous session history is replayed below as JSON-RPC envelopes. Use it as context before responding to the latest user prompt.\\n\";\n let text = prefix;\n\n for (const event of events) {\n const line = JSON.stringify({\n createdAt: event.createdAt,\n sender: event.sender,\n payload: event.payload,\n });\n\n if (text.length + line.length + 1 > maxChars) {\n text += \"\\n[history truncated]\";\n break;\n }\n\n text += `${line}\\n`;\n }\n\n return text;\n}\n\nfunction envelopeMethod(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"method\" in message) || typeof message[\"method\"] !== \"string\") {\n return null;\n }\n return message[\"method\"];\n}\n\nfunction envelopeId(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"id\" in message) || message[\"id\"] === undefined || message[\"id\"] === null) {\n return null;\n }\n return String(message[\"id\"]);\n}\n\nfunction envelopeSessionIdFromParams(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"params\" in message) || !isRecord(message[\"params\"])) {\n return null;\n }\n\n const params = message[\"params\"];\n if (typeof params.sessionId === \"string\" && params.sessionId.length > 0) {\n return params.sessionId;\n }\n\n return null;\n}\n\nfunction envelopeSessionIdFromResult(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"result\" in message) || !isRecord(message[\"result\"])) {\n return null;\n }\n\n const result = message[\"result\"];\n if (typeof result.sessionId === \"string\" && result.sessionId.length > 0) {\n return result.sessionId;\n }\n\n return null;\n}\n\nfunction cloneEnvelope(envelope: AnyMessage): AnyMessage {\n return JSON.parse(JSON.stringify(envelope)) as AnyMessage;\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction randomId(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction defaultCwd(): string {\n if (typeof process !== \"undefined\" && typeof process.cwd === \"function\") {\n return process.cwd();\n }\n return \"/\";\n}\n\nfunction normalizePositiveInt(value: number | undefined, fallback: number): number {\n if (!Number.isFinite(value) || (value ?? 0) < 1) {\n return fallback;\n }\n return Math.floor(value as number);\n}\n\nfunction normalizeSpawnOptions(\n spawn: SandboxAgentSpawnOptions | boolean | undefined,\n defaultEnabled: boolean,\n): SandboxAgentSpawnOptions & { enabled: boolean } {\n if (spawn === false) {\n return { enabled: false };\n }\n\n if (spawn === true || spawn === undefined) {\n return { enabled: defaultEnabled };\n }\n\n return {\n ...spawn,\n enabled: spawn.enabled ?? defaultEnabled,\n };\n}\n\nasync function readProblem(response: Response): Promise<ProblemDetails | undefined> {\n try {\n const text = await response.clone().text();\n if (!text) {\n return undefined;\n }\n return JSON.parse(text) as ProblemDetails;\n } catch {\n return undefined;\n }\n}\n","import type { AnyMessage, NewSessionRequest } from \"acp-http-client\";\nimport type { components, operations } from \"./generated/openapi.ts\";\n\nexport type ProblemDetails = components[\"schemas\"][\"ProblemDetails\"];\n\nexport type HealthResponse = JsonResponse<operations[\"get_v1_health\"], 200>;\nexport type AgentListResponse = JsonResponse<operations[\"get_v1_agents\"], 200>;\nexport type AgentInfo = components[\"schemas\"][\"AgentInfo\"];\nexport type AgentInstallRequest = JsonRequestBody<operations[\"post_v1_agent_install\"]>;\nexport type AgentInstallResponse = JsonResponse<operations[\"post_v1_agent_install\"], 200>;\n\nexport type AcpEnvelope = components[\"schemas\"][\"AcpEnvelope\"];\nexport type AcpServerInfo = components[\"schemas\"][\"AcpServerInfo\"];\nexport type AcpServerListResponse = JsonResponse<operations[\"get_v1_acp_servers\"], 200>;\n\nexport type FsEntriesQuery = QueryParams<operations[\"get_v1_fs_entries\"]>;\nexport type FsEntry = components[\"schemas\"][\"FsEntry\"];\nexport type FsPathQuery = QueryParams<operations[\"get_v1_fs_file\"]>;\nexport type FsDeleteQuery = QueryParams<operations[\"delete_v1_fs_entry\"]>;\nexport type FsUploadBatchQuery = QueryParams<operations[\"post_v1_fs_upload_batch\"]>;\nexport type FsWriteResponse = JsonResponse<operations[\"put_v1_fs_file\"], 200>;\nexport type FsActionResponse = JsonResponse<operations[\"delete_v1_fs_entry\"], 200>;\nexport type FsMoveRequest = JsonRequestBody<operations[\"post_v1_fs_move\"]>;\nexport type FsMoveResponse = JsonResponse<operations[\"post_v1_fs_move\"], 200>;\nexport type FsStat = JsonResponse<operations[\"get_v1_fs_stat\"], 200>;\nexport type FsUploadBatchResponse = JsonResponse<operations[\"post_v1_fs_upload_batch\"], 200>;\n\nexport type McpConfigQuery = QueryParams<operations[\"get_v1_config_mcp\"]>;\nexport type McpServerConfig = components[\"schemas\"][\"McpServerConfig\"];\n\nexport type SkillsConfigQuery = QueryParams<operations[\"get_v1_config_skills\"]>;\nexport type SkillsConfig = components[\"schemas\"][\"SkillsConfig\"];\n\nexport interface SessionRecord {\n id: string;\n agent: string;\n agentSessionId: string;\n lastConnectionId: string;\n createdAt: number;\n destroyedAt?: number;\n sessionInit?: Omit<NewSessionRequest, \"_meta\">;\n}\n\nexport type SessionEventSender = \"client\" | \"agent\";\n\nexport interface SessionEvent {\n // Stable unique event id. For ordering, sort by (sessionId, eventIndex).\n id: string;\n eventIndex: number;\n sessionId: string;\n createdAt: number;\n connectionId: string;\n sender: SessionEventSender;\n payload: AnyMessage;\n}\n\nexport interface ListPageRequest {\n cursor?: string;\n limit?: number;\n}\n\nexport interface ListPage<T> {\n items: T[];\n nextCursor?: string;\n}\n\nexport interface ListEventsRequest extends ListPageRequest {\n sessionId: string;\n}\n\nexport interface SessionPersistDriver {\n getSession(id: string): Promise<SessionRecord | null>;\n listSessions(request?: ListPageRequest): Promise<ListPage<SessionRecord>>;\n updateSession(session: SessionRecord): Promise<void>;\n listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>>;\n insertEvent(event: SessionEvent): Promise<void>;\n}\n\nexport interface InMemorySessionPersistDriverOptions {\n maxSessions?: number;\n maxEventsPerSession?: number;\n}\n\nconst DEFAULT_MAX_SESSIONS = 1024;\nconst DEFAULT_MAX_EVENTS_PER_SESSION = 500;\nconst DEFAULT_LIST_LIMIT = 100;\n\nexport class InMemorySessionPersistDriver implements SessionPersistDriver {\n private readonly maxSessions: number;\n private readonly maxEventsPerSession: number;\n private readonly sessions = new Map<string, SessionRecord>();\n private readonly eventsBySession = new Map<string, SessionEvent[]>();\n\n constructor(options: InMemorySessionPersistDriverOptions = {}) {\n this.maxSessions = normalizeCap(options.maxSessions, DEFAULT_MAX_SESSIONS);\n this.maxEventsPerSession = normalizeCap(\n options.maxEventsPerSession,\n DEFAULT_MAX_EVENTS_PER_SESSION,\n );\n }\n\n async getSession(id: string): Promise<SessionRecord | null> {\n const session = this.sessions.get(id);\n return session ? cloneSessionRecord(session) : null;\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<SessionRecord>> {\n const sorted = [...this.sessions.values()].sort((a, b) => {\n if (a.createdAt !== b.createdAt) {\n return a.createdAt - b.createdAt;\n }\n return a.id.localeCompare(b.id);\n });\n const page = paginate(sorted, request);\n return {\n items: page.items.map(cloneSessionRecord),\n nextCursor: page.nextCursor,\n };\n }\n\n async updateSession(session: SessionRecord): Promise<void> {\n this.sessions.set(session.id, { ...session });\n\n if (!this.eventsBySession.has(session.id)) {\n this.eventsBySession.set(session.id, []);\n }\n\n if (this.sessions.size <= this.maxSessions) {\n return;\n }\n\n const overflow = this.sessions.size - this.maxSessions;\n const removable = [...this.sessions.values()]\n .sort((a, b) => {\n if (a.createdAt !== b.createdAt) {\n return a.createdAt - b.createdAt;\n }\n return a.id.localeCompare(b.id);\n })\n .slice(0, overflow)\n .map((sessionToRemove) => sessionToRemove.id);\n\n for (const sessionId of removable) {\n this.sessions.delete(sessionId);\n this.eventsBySession.delete(sessionId);\n }\n }\n\n async listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n const all = [...(this.eventsBySession.get(request.sessionId) ?? [])].sort((a, b) => {\n if (a.eventIndex !== b.eventIndex) {\n return a.eventIndex - b.eventIndex;\n }\n return a.id.localeCompare(b.id);\n });\n const page = paginate(all, request);\n return {\n items: page.items.map(cloneSessionEvent),\n nextCursor: page.nextCursor,\n };\n }\n\n async insertEvent(event: SessionEvent): Promise<void> {\n const events = this.eventsBySession.get(event.sessionId) ?? [];\n events.push(cloneSessionEvent(event));\n\n if (events.length > this.maxEventsPerSession) {\n events.splice(0, events.length - this.maxEventsPerSession);\n }\n\n this.eventsBySession.set(event.sessionId, events);\n }\n}\n\nfunction cloneSessionRecord(session: SessionRecord): SessionRecord {\n return {\n ...session,\n sessionInit: session.sessionInit\n ? (JSON.parse(JSON.stringify(session.sessionInit)) as SessionRecord[\"sessionInit\"])\n : undefined,\n };\n}\n\nfunction cloneSessionEvent(event: SessionEvent): SessionEvent {\n return {\n ...event,\n payload: JSON.parse(JSON.stringify(event.payload)) as AnyMessage,\n };\n}\n\ntype ResponsesOf<T> = T extends { responses: infer R } ? R : never;\ntype JsonResponse<T, StatusCode extends keyof ResponsesOf<T>> = ResponsesOf<T>[StatusCode] extends {\n content: { \"application/json\": infer B };\n}\n ? B\n : never;\n\ntype JsonRequestBody<T> = T extends {\n requestBody: { content: { \"application/json\": infer B } };\n}\n ? B\n : never;\n\ntype QueryParams<T> = T extends { parameters: { query: infer Q } }\n ? Q\n : T extends { parameters: { query?: infer Q } }\n ? Q\n : never;\n\nfunction normalizeCap(value: number | undefined, fallback: number): number {\n if (!Number.isFinite(value) || (value ?? 0) < 1) {\n return fallback;\n }\n return Math.floor(value as number);\n}\n\nfunction paginate<T>(items: T[], request: ListPageRequest): ListPage<T> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeCap(request.limit, DEFAULT_LIST_LIMIT);\n const slice = items.slice(offset, offset + limit);\n const nextOffset = offset + slice.length;\n return {\n items: slice,\n nextCursor: nextOffset < items.length ? String(nextOffset) : undefined,\n };\n}\n\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) {\n return 0;\n }\n const parsed = Number.parseInt(cursor, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return 0;\n }\n return parsed;\n}\n","export {\n LiveAcpConnection,\n SandboxAgent,\n SandboxAgentError,\n Session,\n} from \"./client.ts\";\n\nexport { AcpRpcError } from \"acp-http-client\";\n\nexport { buildInspectorUrl } from \"./inspector.ts\";\n\nexport type {\n SandboxAgentConnectOptions,\n SandboxAgentStartOptions,\n SessionCreateRequest,\n SessionResumeOrCreateRequest,\n SessionSendOptions,\n SessionEventListener,\n} from \"./client.ts\";\n\nexport type { InspectorUrlOptions } from \"./inspector.ts\";\n\nexport {\n InMemorySessionPersistDriver,\n} from \"./types.ts\";\n\nexport type {\n AcpEnvelope,\n AcpServerInfo,\n AcpServerListResponse,\n AgentInfo,\n AgentInstallRequest,\n AgentInstallResponse,\n AgentListResponse,\n FsActionResponse,\n FsDeleteQuery,\n FsEntriesQuery,\n FsEntry,\n FsMoveRequest,\n FsMoveResponse,\n FsPathQuery,\n FsStat,\n FsUploadBatchQuery,\n FsUploadBatchResponse,\n FsWriteResponse,\n HealthResponse,\n InMemorySessionPersistDriverOptions,\n ListEventsRequest,\n ListPage,\n ListPageRequest,\n McpConfigQuery,\n McpServerConfig,\n ProblemDetails,\n SessionEvent,\n SessionPersistDriver,\n SessionRecord,\n SkillsConfig,\n SkillsConfigQuery,\n} from \"./types.ts\";\n\nexport type {\n SandboxAgentSpawnLogMode,\n SandboxAgentSpawnOptions,\n} from \"./spawn.ts\";\n","export interface InspectorUrlOptions {\n /**\n * Base URL of the sandbox-agent server.\n */\n baseUrl: string;\n /**\n * Optional bearer token for authentication.\n */\n token?: string;\n /**\n * Optional extra headers to pass to the sandbox-agent server.\n * Will be JSON-encoded in the URL.\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Builds a URL to the sandbox-agent inspector UI with the given connection parameters.\n * The inspector UI is served at /ui/ on the sandbox-agent server.\n */\nexport function buildInspectorUrl(options: InspectorUrlOptions): string {\n const normalized = options.baseUrl.replace(/\\/+$/, \"\");\n const params = new URLSearchParams();\n if (options.token) {\n params.set(\"token\", options.token);\n }\n if (options.headers && Object.keys(options.headers).length > 0) {\n params.set(\"headers\", JSON.stringify(options.headers));\n }\n const queryString = params.toString();\n return `${normalized}/ui/${queryString ? `?${queryString}` : \"\"}`;\n}\n"],"mappings":"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","names":["pending"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/types.ts","../src/index.ts","../src/inspector.ts"],"sourcesContent":["import {\n AcpHttpClient,\n PROTOCOL_VERSION,\n type AcpEnvelopeDirection,\n type AnyMessage,\n type AuthMethod,\n type CancelNotification,\n type NewSessionRequest,\n type NewSessionResponse,\n type PromptRequest,\n type PromptResponse,\n type SessionNotification,\n type SetSessionConfigOptionRequest,\n type SetSessionModeRequest,\n} from \"acp-http-client\";\nimport type { SandboxAgentSpawnHandle, SandboxAgentSpawnOptions } from \"./spawn.ts\";\nimport {\n type AcpServerListResponse,\n type AgentInfo,\n type AgentInstallRequest,\n type AgentInstallResponse,\n type AgentListResponse,\n type FsActionResponse,\n type FsDeleteQuery,\n type FsEntriesQuery,\n type FsEntry,\n type FsMoveRequest,\n type FsMoveResponse,\n type FsPathQuery,\n type FsStat,\n type FsUploadBatchQuery,\n type FsUploadBatchResponse,\n type FsWriteResponse,\n type HealthResponse,\n InMemorySessionPersistDriver,\n type ListEventsRequest,\n type ListPage,\n type ListPageRequest,\n type McpConfigQuery,\n type McpServerConfig,\n type ProblemDetails,\n type SessionEvent,\n type SessionPersistDriver,\n type SessionRecord,\n type SkillsConfig,\n type SkillsConfigQuery,\n} from \"./types.ts\";\n\nconst API_PREFIX = \"/v1\";\nconst FS_PATH = `${API_PREFIX}/fs`;\nconst DEFAULT_BASE_URL = \"http://sandbox-agent\";\n\nconst DEFAULT_REPLAY_MAX_EVENTS = 50;\nconst DEFAULT_REPLAY_MAX_CHARS = 12_000;\nconst EVENT_INDEX_SCAN_EVENTS_LIMIT = 500;\n\ninterface SandboxAgentConnectCommonOptions {\n headers?: HeadersInit;\n persist?: SessionPersistDriver;\n replayMaxEvents?: number;\n replayMaxChars?: number;\n token?: string;\n}\n\nexport type SandboxAgentConnectOptions =\n | (SandboxAgentConnectCommonOptions & {\n baseUrl: string;\n fetch?: typeof fetch;\n })\n | (SandboxAgentConnectCommonOptions & {\n fetch: typeof fetch;\n baseUrl?: string;\n });\n\nexport interface SandboxAgentStartOptions {\n fetch?: typeof fetch;\n headers?: HeadersInit;\n persist?: SessionPersistDriver;\n replayMaxEvents?: number;\n replayMaxChars?: number;\n spawn?: SandboxAgentSpawnOptions | boolean;\n}\n\nexport interface SessionCreateRequest {\n id?: string;\n agent: string;\n sessionInit?: Omit<NewSessionRequest, \"_meta\">;\n}\n\nexport interface SessionResumeOrCreateRequest {\n id: string;\n agent: string;\n sessionInit?: Omit<NewSessionRequest, \"_meta\">;\n}\n\nexport interface SessionSendOptions {\n notification?: boolean;\n}\n\nexport type SessionEventListener = (event: SessionEvent) => void;\n\nexport class SandboxAgentError extends Error {\n readonly status: number;\n readonly problem?: ProblemDetails;\n readonly response: Response;\n\n constructor(status: number, problem: ProblemDetails | undefined, response: Response) {\n super(problem?.title ?? `Request failed with status ${status}`);\n this.name = \"SandboxAgentError\";\n this.status = status;\n this.problem = problem;\n this.response = response;\n }\n}\n\nexport class Session {\n private record: SessionRecord;\n private readonly sandbox: SandboxAgent;\n\n constructor(sandbox: SandboxAgent, record: SessionRecord) {\n this.sandbox = sandbox;\n this.record = { ...record };\n }\n\n get id(): string {\n return this.record.id;\n }\n\n get agent(): string {\n return this.record.agent;\n }\n\n get agentSessionId(): string {\n return this.record.agentSessionId;\n }\n\n get lastConnectionId(): string {\n return this.record.lastConnectionId;\n }\n\n get createdAt(): number {\n return this.record.createdAt;\n }\n\n get destroyedAt(): number | undefined {\n return this.record.destroyedAt;\n }\n\n async refresh(): Promise<Session> {\n const latest = await this.sandbox.getSession(this.id);\n if (!latest) {\n throw new Error(`session '${this.id}' no longer exists`);\n }\n this.apply(latest.toRecord());\n return this;\n }\n\n async send(method: string, params: Record<string, unknown> = {}, options: SessionSendOptions = {}): Promise<unknown> {\n const updated = await this.sandbox.sendSessionMethod(this.id, method, params, options);\n this.apply(updated.session.toRecord());\n return updated.response;\n }\n\n async prompt(prompt: PromptRequest[\"prompt\"]): Promise<PromptResponse> {\n const response = await this.send(\"session/prompt\", { prompt });\n return response as PromptResponse;\n }\n\n onEvent(listener: SessionEventListener): () => void {\n return this.sandbox.onSessionEvent(this.id, listener);\n }\n\n toRecord(): SessionRecord {\n return { ...this.record };\n }\n\n apply(record: SessionRecord): void {\n this.record = { ...record };\n }\n}\n\nexport class LiveAcpConnection {\n readonly connectionId: string;\n readonly agent: string;\n\n private readonly acp: AcpHttpClient;\n private readonly sessionByLocalId = new Map<string, string>();\n private readonly localByAgentSessionId = new Map<string, string>();\n private readonly pendingNewSessionLocals: string[] = [];\n private readonly pendingRequestSessionById = new Map<string, string>();\n private readonly pendingReplayByLocalSessionId = new Map<string, string>();\n private lastAdapterExit: { success: boolean; code: number | null } | null = null;\n private lastAdapterExitAt = 0;\n\n private readonly onObservedEnvelope: (\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ) => void;\n\n private constructor(\n agent: string,\n connectionId: string,\n acp: AcpHttpClient,\n onObservedEnvelope: (\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ) => void,\n ) {\n this.agent = agent;\n this.connectionId = connectionId;\n this.acp = acp;\n this.onObservedEnvelope = onObservedEnvelope;\n }\n\n static async create(options: {\n baseUrl: string;\n token?: string;\n fetcher: typeof fetch;\n headers?: HeadersInit;\n agent: string;\n serverId: string;\n onObservedEnvelope: (\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ) => void;\n }): Promise<LiveAcpConnection> {\n const connectionId = randomId();\n\n let live: LiveAcpConnection | null = null;\n const acp = new AcpHttpClient({\n baseUrl: options.baseUrl,\n token: options.token,\n fetch: options.fetcher,\n headers: options.headers,\n transport: {\n path: `${API_PREFIX}/acp/${encodeURIComponent(options.serverId)}`,\n bootstrapQuery: { agent: options.agent },\n },\n client: {\n sessionUpdate: async (_notification: SessionNotification) => {\n // Session updates are observed via envelope persistence.\n },\n extNotification: async (method: string, params: Record<string, unknown>) => {\n if (!live) return;\n live.handleAdapterNotification(method, params);\n },\n },\n onEnvelope: (envelope, direction) => {\n if (!live) {\n return;\n }\n live.handleEnvelope(envelope, direction);\n },\n });\n\n live = new LiveAcpConnection(options.agent, connectionId, acp, options.onObservedEnvelope);\n\n const initResult = await acp.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientInfo: {\n name: \"sandbox-agent-sdk\",\n version: \"v1\",\n },\n });\n if (initResult.authMethods && initResult.authMethods.length > 0) {\n await autoAuthenticate(acp, initResult.authMethods);\n }\n return live;\n }\n\n async close(): Promise<void> {\n await this.acp.disconnect();\n }\n\n hasBoundSession(localSessionId: string, agentSessionId?: string): boolean {\n const bound = this.sessionByLocalId.get(localSessionId);\n if (!bound) {\n return false;\n }\n if (agentSessionId && bound !== agentSessionId) {\n return false;\n }\n return true;\n }\n\n bindSession(localSessionId: string, agentSessionId: string): void {\n this.sessionByLocalId.set(localSessionId, agentSessionId);\n this.localByAgentSessionId.set(agentSessionId, localSessionId);\n }\n\n queueReplay(localSessionId: string, replayText: string | null): void {\n if (!replayText) {\n this.pendingReplayByLocalSessionId.delete(localSessionId);\n return;\n }\n this.pendingReplayByLocalSessionId.set(localSessionId, replayText);\n }\n\n async createRemoteSession(\n localSessionId: string,\n sessionInit: Omit<NewSessionRequest, \"_meta\">,\n ): Promise<NewSessionResponse> {\n const createStartedAt = Date.now();\n this.pendingNewSessionLocals.push(localSessionId);\n\n try {\n const response = await this.acp.newSession(sessionInit);\n this.bindSession(localSessionId, response.sessionId);\n return response;\n } catch (error) {\n const index = this.pendingNewSessionLocals.indexOf(localSessionId);\n if (index !== -1) {\n this.pendingNewSessionLocals.splice(index, 1);\n }\n const adapterExit = this.lastAdapterExit;\n if (adapterExit && this.lastAdapterExitAt >= createStartedAt) {\n const suffix = adapterExit.code == null ? \"\" : ` (code ${adapterExit.code})`;\n throw new Error(`Agent process exited while creating session${suffix}`);\n }\n throw error;\n }\n }\n\n async sendSessionMethod(\n localSessionId: string,\n method: string,\n params: Record<string, unknown>,\n options: SessionSendOptions,\n ): Promise<unknown> {\n const agentSessionId = this.sessionByLocalId.get(localSessionId);\n if (!agentSessionId) {\n throw new Error(`session '${localSessionId}' is not bound to live ACP connection '${this.connectionId}'`);\n }\n\n const mappedParams = mapSessionParams(params, agentSessionId);\n\n if (method === \"session/prompt\") {\n const replayText = this.pendingReplayByLocalSessionId.get(localSessionId);\n if (replayText) {\n // TODO: Replace this synthesized replay text with ACP-native restore once standardized.\n this.pendingReplayByLocalSessionId.delete(localSessionId);\n injectReplayPrompt(mappedParams, replayText);\n }\n\n if (options.notification) {\n await this.acp.extNotification(method, mappedParams);\n return undefined;\n }\n\n return this.acp.prompt(mappedParams as PromptRequest);\n }\n\n if (method === \"session/cancel\") {\n await this.acp.cancel(mappedParams as CancelNotification);\n return undefined;\n }\n\n if (method === \"session/set_mode\") {\n return this.acp.setSessionMode(mappedParams as SetSessionModeRequest);\n }\n\n if (method === \"session/set_config_option\") {\n return this.acp.setSessionConfigOption(mappedParams as SetSessionConfigOptionRequest);\n }\n\n if (options.notification) {\n await this.acp.extNotification(method, mappedParams);\n return undefined;\n }\n\n return this.acp.extMethod(method, mappedParams);\n }\n\n private handleEnvelope(envelope: AnyMessage, direction: AcpEnvelopeDirection): void {\n const localSessionId = this.resolveSessionId(envelope, direction);\n this.onObservedEnvelope(this, envelope, direction, localSessionId);\n }\n\n private handleAdapterNotification(method: string, params: Record<string, unknown>): void {\n if (method !== \"_adapter/agent_exited\") {\n return;\n }\n this.lastAdapterExit = {\n success: params.success === true,\n code: typeof params.code === \"number\" ? params.code : null,\n };\n this.lastAdapterExitAt = Date.now();\n }\n\n private resolveSessionId(envelope: AnyMessage, direction: AcpEnvelopeDirection): string | null {\n const id = envelopeId(envelope);\n const method = envelopeMethod(envelope);\n\n if (direction === \"outbound\") {\n if (id && method === \"session/new\") {\n const localSessionId = this.pendingNewSessionLocals.shift() ?? null;\n if (localSessionId) {\n this.pendingRequestSessionById.set(id, localSessionId);\n }\n return localSessionId;\n }\n\n const localFromParams = this.localFromEnvelopeParams(envelope);\n if (id && localFromParams) {\n this.pendingRequestSessionById.set(id, localFromParams);\n }\n return localFromParams;\n }\n\n if (id) {\n const pending = this.pendingRequestSessionById.get(id) ?? null;\n if (pending) {\n this.pendingRequestSessionById.delete(id);\n const sessionIdFromResult = envelopeSessionIdFromResult(envelope);\n if (sessionIdFromResult) {\n this.bindSession(pending, sessionIdFromResult);\n }\n return pending;\n }\n }\n\n return this.localFromEnvelopeParams(envelope);\n }\n\n private localFromEnvelopeParams(envelope: AnyMessage): string | null {\n const agentSessionId = envelopeSessionIdFromParams(envelope);\n if (!agentSessionId) {\n return null;\n }\n return this.localByAgentSessionId.get(agentSessionId) ?? null;\n }\n}\n\nexport class SandboxAgent {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly fetcher: typeof fetch;\n private readonly defaultHeaders?: HeadersInit;\n\n private readonly persist: SessionPersistDriver;\n private readonly replayMaxEvents: number;\n private readonly replayMaxChars: number;\n\n private spawnHandle?: SandboxAgentSpawnHandle;\n\n private readonly liveConnections = new Map<string, LiveAcpConnection>();\n private readonly pendingLiveConnections = new Map<string, Promise<LiveAcpConnection>>();\n private readonly sessionHandles = new Map<string, Session>();\n private readonly eventListeners = new Map<string, Set<SessionEventListener>>();\n private readonly nextSessionEventIndexBySession = new Map<string, number>();\n private readonly seedSessionEventIndexBySession = new Map<string, Promise<void>>();\n\n constructor(options: SandboxAgentConnectOptions) {\n const baseUrl = options.baseUrl?.trim();\n if (!baseUrl && !options.fetch) {\n throw new Error(\"baseUrl is required unless fetch is provided.\");\n }\n this.baseUrl = (baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n this.token = options.token;\n const resolvedFetch = options.fetch ?? globalThis.fetch?.bind(globalThis);\n if (!resolvedFetch) {\n throw new Error(\"Fetch API is not available; provide a fetch implementation.\");\n }\n this.fetcher = resolvedFetch;\n this.defaultHeaders = options.headers;\n this.persist = options.persist ?? new InMemorySessionPersistDriver();\n\n this.replayMaxEvents = normalizePositiveInt(options.replayMaxEvents, DEFAULT_REPLAY_MAX_EVENTS);\n this.replayMaxChars = normalizePositiveInt(options.replayMaxChars, DEFAULT_REPLAY_MAX_CHARS);\n }\n\n static async connect(options: SandboxAgentConnectOptions): Promise<SandboxAgent> {\n return new SandboxAgent(options);\n }\n\n static async start(options: SandboxAgentStartOptions = {}): Promise<SandboxAgent> {\n const spawnOptions = normalizeSpawnOptions(options.spawn, true);\n if (!spawnOptions.enabled) {\n throw new Error(\"SandboxAgent.start requires spawn to be enabled.\");\n }\n\n const { spawnSandboxAgent } = await import(\"./spawn.js\");\n const resolvedFetch = options.fetch ?? globalThis.fetch?.bind(globalThis);\n const handle = await spawnSandboxAgent(spawnOptions, resolvedFetch);\n\n const client = new SandboxAgent({\n baseUrl: handle.baseUrl,\n token: handle.token,\n fetch: options.fetch,\n headers: options.headers,\n persist: options.persist,\n replayMaxEvents: options.replayMaxEvents,\n replayMaxChars: options.replayMaxChars,\n });\n\n client.spawnHandle = handle;\n return client;\n }\n\n async dispose(): Promise<void> {\n const connections = [...this.liveConnections.values()];\n this.liveConnections.clear();\n const pending = [...this.pendingLiveConnections.values()];\n this.pendingLiveConnections.clear();\n\n const pendingSettled = await Promise.allSettled(pending);\n for (const item of pendingSettled) {\n if (item.status === \"fulfilled\") {\n connections.push(item.value);\n }\n }\n\n await Promise.all(\n connections.map(async (connection) => {\n await connection.close();\n }),\n );\n\n if (this.spawnHandle) {\n await this.spawnHandle.dispose();\n this.spawnHandle = undefined;\n }\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<Session>> {\n const page = await this.persist.listSessions(request);\n return {\n items: page.items.map((record) => this.upsertSessionHandle(record)),\n nextCursor: page.nextCursor,\n };\n }\n\n async getSession(id: string): Promise<Session | null> {\n const record = await this.persist.getSession(id);\n if (!record) {\n return null;\n }\n return this.upsertSessionHandle(record);\n }\n\n async getEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n return this.persist.listEvents(request);\n }\n\n async createSession(request: SessionCreateRequest): Promise<Session> {\n if (!request.agent.trim()) {\n throw new Error(\"createSession requires a non-empty agent\");\n }\n\n const localSessionId = request.id?.trim() || randomId();\n const live = await this.getLiveConnection(request.agent.trim());\n const sessionInit = normalizeSessionInit(request.sessionInit);\n\n const response = await live.createRemoteSession(localSessionId, sessionInit);\n\n const record: SessionRecord = {\n id: localSessionId,\n agent: request.agent.trim(),\n agentSessionId: response.sessionId,\n lastConnectionId: live.connectionId,\n createdAt: nowMs(),\n sessionInit,\n };\n\n await this.persist.updateSession(record);\n this.nextSessionEventIndexBySession.set(record.id, 1);\n live.bindSession(record.id, record.agentSessionId);\n return this.upsertSessionHandle(record);\n }\n\n async resumeSession(id: string): Promise<Session> {\n const existing = await this.persist.getSession(id);\n if (!existing) {\n throw new Error(`session '${id}' not found`);\n }\n\n const live = await this.getLiveConnection(existing.agent);\n if (existing.lastConnectionId === live.connectionId && live.hasBoundSession(id, existing.agentSessionId)) {\n return this.upsertSessionHandle(existing);\n }\n\n const replaySource = await this.collectReplayEvents(existing.id, this.replayMaxEvents);\n const replayText = buildReplayText(replaySource, this.replayMaxChars);\n\n const recreated = await live.createRemoteSession(existing.id, normalizeSessionInit(existing.sessionInit));\n\n const updated: SessionRecord = {\n ...existing,\n agentSessionId: recreated.sessionId,\n lastConnectionId: live.connectionId,\n destroyedAt: undefined,\n };\n\n await this.persist.updateSession(updated);\n live.bindSession(updated.id, updated.agentSessionId);\n live.queueReplay(updated.id, replayText);\n\n return this.upsertSessionHandle(updated);\n }\n\n async resumeOrCreateSession(request: SessionResumeOrCreateRequest): Promise<Session> {\n const existing = await this.persist.getSession(request.id);\n if (existing) {\n return this.resumeSession(existing.id);\n }\n return this.createSession(request);\n }\n\n async destroySession(id: string): Promise<Session> {\n const existing = await this.persist.getSession(id);\n if (!existing) {\n throw new Error(`session '${id}' not found`);\n }\n\n const updated: SessionRecord = {\n ...existing,\n destroyedAt: nowMs(),\n };\n\n await this.persist.updateSession(updated);\n return this.upsertSessionHandle(updated);\n }\n\n async sendSessionMethod(\n sessionId: string,\n method: string,\n params: Record<string, unknown>,\n options: SessionSendOptions = {},\n ): Promise<{ session: Session; response: unknown }> {\n const record = await this.persist.getSession(sessionId);\n if (!record) {\n throw new Error(`session '${sessionId}' not found`);\n }\n\n const live = await this.getLiveConnection(record.agent);\n if (!live.hasBoundSession(record.id, record.agentSessionId)) {\n // The persisted session points at a stale connection; restore lazily.\n const restored = await this.resumeSession(record.id);\n return this.sendSessionMethod(restored.id, method, params, options);\n }\n\n const response = await live.sendSessionMethod(record.id, method, params, options);\n const refreshed = await this.requireSessionRecord(record.id);\n return {\n session: this.upsertSessionHandle(refreshed),\n response,\n };\n }\n\n onSessionEvent(sessionId: string, listener: SessionEventListener): () => void {\n const listeners = this.eventListeners.get(sessionId) ?? new Set<SessionEventListener>();\n listeners.add(listener);\n this.eventListeners.set(sessionId, listeners);\n\n return () => {\n const set = this.eventListeners.get(sessionId);\n if (!set) {\n return;\n }\n set.delete(listener);\n if (set.size === 0) {\n this.eventListeners.delete(sessionId);\n }\n };\n }\n\n async getHealth(): Promise<HealthResponse> {\n return this.requestJson(\"GET\", `${API_PREFIX}/health`);\n }\n\n async listAgents(options?: { config?: boolean }): Promise<AgentListResponse> {\n return this.requestJson(\"GET\", `${API_PREFIX}/agents`, {\n query: options?.config ? { config: \"true\" } : undefined,\n });\n }\n\n async getAgent(agent: string, options?: { config?: boolean }): Promise<AgentInfo> {\n return this.requestJson(\"GET\", `${API_PREFIX}/agents/${encodeURIComponent(agent)}`, {\n query: options?.config ? { config: \"true\" } : undefined,\n });\n }\n\n async installAgent(agent: string, request: AgentInstallRequest = {}): Promise<AgentInstallResponse> {\n return this.requestJson(\"POST\", `${API_PREFIX}/agents/${encodeURIComponent(agent)}/install`, {\n body: request,\n });\n }\n\n async listAcpServers(): Promise<AcpServerListResponse> {\n return this.requestJson(\"GET\", `${API_PREFIX}/acp`);\n }\n\n async listFsEntries(query: FsEntriesQuery = {}): Promise<FsEntry[]> {\n return this.requestJson(\"GET\", `${FS_PATH}/entries`, {\n query,\n });\n }\n\n async readFsFile(query: FsPathQuery): Promise<Uint8Array> {\n const response = await this.requestRaw(\"GET\", `${FS_PATH}/file`, {\n query,\n accept: \"application/octet-stream\",\n });\n const buffer = await response.arrayBuffer();\n return new Uint8Array(buffer);\n }\n\n async writeFsFile(query: FsPathQuery, body: BodyInit): Promise<FsWriteResponse> {\n const response = await this.requestRaw(\"PUT\", `${FS_PATH}/file`, {\n query,\n rawBody: body,\n contentType: \"application/octet-stream\",\n accept: \"application/json\",\n });\n return (await response.json()) as FsWriteResponse;\n }\n\n async deleteFsEntry(query: FsDeleteQuery): Promise<FsActionResponse> {\n return this.requestJson(\"DELETE\", `${FS_PATH}/entry`, { query });\n }\n\n async mkdirFs(query: FsPathQuery): Promise<FsActionResponse> {\n return this.requestJson(\"POST\", `${FS_PATH}/mkdir`, { query });\n }\n\n async moveFs(request: FsMoveRequest): Promise<FsMoveResponse> {\n return this.requestJson(\"POST\", `${FS_PATH}/move`, { body: request });\n }\n\n async statFs(query: FsPathQuery): Promise<FsStat> {\n return this.requestJson(\"GET\", `${FS_PATH}/stat`, { query });\n }\n\n async uploadFsBatch(body: BodyInit, query?: FsUploadBatchQuery): Promise<FsUploadBatchResponse> {\n const response = await this.requestRaw(\"POST\", `${FS_PATH}/upload-batch`, {\n query,\n rawBody: body,\n contentType: \"application/x-tar\",\n accept: \"application/json\",\n });\n return (await response.json()) as FsUploadBatchResponse;\n }\n\n async getMcpConfig(query: McpConfigQuery): Promise<McpServerConfig> {\n return this.requestJson(\"GET\", `${API_PREFIX}/config/mcp`, { query });\n }\n\n async setMcpConfig(query: McpConfigQuery, config: McpServerConfig): Promise<void> {\n await this.requestRaw(\"PUT\", `${API_PREFIX}/config/mcp`, { query, body: config });\n }\n\n async deleteMcpConfig(query: McpConfigQuery): Promise<void> {\n await this.requestRaw(\"DELETE\", `${API_PREFIX}/config/mcp`, { query });\n }\n\n async getSkillsConfig(query: SkillsConfigQuery): Promise<SkillsConfig> {\n return this.requestJson(\"GET\", `${API_PREFIX}/config/skills`, { query });\n }\n\n async setSkillsConfig(query: SkillsConfigQuery, config: SkillsConfig): Promise<void> {\n await this.requestRaw(\"PUT\", `${API_PREFIX}/config/skills`, { query, body: config });\n }\n\n async deleteSkillsConfig(query: SkillsConfigQuery): Promise<void> {\n await this.requestRaw(\"DELETE\", `${API_PREFIX}/config/skills`, { query });\n }\n\n private async getLiveConnection(agent: string): Promise<LiveAcpConnection> {\n const existing = this.liveConnections.get(agent);\n if (existing) {\n return existing;\n }\n\n const pending = this.pendingLiveConnections.get(agent);\n if (pending) {\n return pending;\n }\n\n const creating = (async () => {\n const serverId = `sdk-${agent}-${randomId()}`;\n const created = await LiveAcpConnection.create({\n baseUrl: this.baseUrl,\n token: this.token,\n fetcher: this.fetcher,\n headers: this.defaultHeaders,\n agent,\n serverId,\n onObservedEnvelope: (connection, envelope, direction, localSessionId) => {\n void this.persistObservedEnvelope(connection, envelope, direction, localSessionId);\n },\n });\n\n const raced = this.liveConnections.get(agent);\n if (raced) {\n await created.close();\n return raced;\n }\n\n this.liveConnections.set(agent, created);\n return created;\n })();\n\n this.pendingLiveConnections.set(agent, creating);\n try {\n return await creating;\n } finally {\n if (this.pendingLiveConnections.get(agent) === creating) {\n this.pendingLiveConnections.delete(agent);\n }\n }\n }\n\n private async persistObservedEnvelope(\n connection: LiveAcpConnection,\n envelope: AnyMessage,\n direction: AcpEnvelopeDirection,\n localSessionId: string | null,\n ): Promise<void> {\n if (!localSessionId) {\n return;\n }\n\n const event: SessionEvent = {\n id: randomId(),\n eventIndex: await this.allocateSessionEventIndex(localSessionId),\n sessionId: localSessionId,\n createdAt: nowMs(),\n connectionId: connection.connectionId,\n sender: direction === \"outbound\" ? \"client\" : \"agent\",\n payload: cloneEnvelope(envelope),\n };\n\n await this.persist.insertEvent(event);\n\n const listeners = this.eventListeners.get(localSessionId);\n if (!listeners || listeners.size === 0) {\n return;\n }\n\n for (const listener of listeners) {\n listener(event);\n }\n }\n\n private async allocateSessionEventIndex(sessionId: string): Promise<number> {\n await this.ensureSessionEventIndexSeeded(sessionId);\n const nextIndex = this.nextSessionEventIndexBySession.get(sessionId) ?? 1;\n this.nextSessionEventIndexBySession.set(sessionId, nextIndex + 1);\n return nextIndex;\n }\n\n private async ensureSessionEventIndexSeeded(sessionId: string): Promise<void> {\n if (this.nextSessionEventIndexBySession.has(sessionId)) {\n return;\n }\n\n if (!this.seedSessionEventIndexBySession.has(sessionId)) {\n const pending = (async () => {\n const maxPersistedIndex = await this.findMaxPersistedSessionEventIndex(sessionId);\n this.nextSessionEventIndexBySession.set(sessionId, Math.max(1, maxPersistedIndex + 1));\n })().finally(() => {\n this.seedSessionEventIndexBySession.delete(sessionId);\n });\n this.seedSessionEventIndexBySession.set(sessionId, pending);\n }\n\n const pending = this.seedSessionEventIndexBySession.get(sessionId);\n if (pending) {\n await pending;\n }\n }\n\n private async findMaxPersistedSessionEventIndex(sessionId: string): Promise<number> {\n let maxIndex = 0;\n let eventCursor: string | undefined;\n\n while (true) {\n const eventsPage = await this.persist.listEvents({\n sessionId,\n cursor: eventCursor,\n limit: EVENT_INDEX_SCAN_EVENTS_LIMIT,\n });\n\n for (const event of eventsPage.items) {\n if (Number.isFinite(event.eventIndex) && event.eventIndex > maxIndex) {\n maxIndex = Math.floor(event.eventIndex);\n }\n }\n\n if (!eventsPage.nextCursor) {\n break;\n }\n eventCursor = eventsPage.nextCursor;\n }\n\n return maxIndex;\n }\n\n private async collectReplayEvents(sessionId: string, maxEvents: number): Promise<SessionEvent[]> {\n const all: SessionEvent[] = [];\n let cursor: string | undefined;\n\n while (true) {\n const page = await this.persist.listEvents({\n sessionId,\n cursor,\n limit: Math.max(100, maxEvents),\n });\n\n all.push(...page.items);\n\n if (!page.nextCursor) {\n break;\n }\n\n cursor = page.nextCursor;\n }\n\n return all.slice(-maxEvents);\n }\n\n private upsertSessionHandle(record: SessionRecord): Session {\n const existing = this.sessionHandles.get(record.id);\n if (existing) {\n existing.apply(record);\n return existing;\n }\n\n const created = new Session(this, record);\n this.sessionHandles.set(record.id, created);\n return created;\n }\n\n private async requireSessionRecord(id: string): Promise<SessionRecord> {\n const record = await this.persist.getSession(id);\n if (!record) {\n throw new Error(`session '${id}' not found`);\n }\n return record;\n }\n\n private async requestJson<T>(method: string, path: string, options: RequestOptions = {}): Promise<T> {\n const response = await this.requestRaw(method, path, {\n query: options.query,\n body: options.body,\n headers: options.headers,\n accept: options.accept ?? \"application/json\",\n signal: options.signal,\n });\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return (await response.json()) as T;\n }\n\n private async requestRaw(method: string, path: string, options: RequestOptions = {}): Promise<Response> {\n const url = this.buildUrl(path, options.query);\n const headers = this.buildHeaders(options.headers);\n\n if (options.accept) {\n headers.set(\"Accept\", options.accept);\n }\n\n const init: RequestInit = {\n method,\n headers,\n signal: options.signal,\n };\n\n if (options.rawBody !== undefined && options.body !== undefined) {\n throw new Error(\"requestRaw received both rawBody and body\");\n }\n\n if (options.rawBody !== undefined) {\n if (options.contentType) {\n headers.set(\"Content-Type\", options.contentType);\n }\n init.body = options.rawBody;\n } else if (options.body !== undefined) {\n headers.set(\"Content-Type\", \"application/json\");\n init.body = JSON.stringify(options.body);\n }\n\n const response = await this.fetcher(url, init);\n if (!response.ok) {\n const problem = await readProblem(response);\n throw new SandboxAgentError(response.status, problem, response);\n }\n\n return response;\n }\n\n private buildHeaders(extra?: HeadersInit): Headers {\n const headers = new Headers(this.defaultHeaders ?? undefined);\n\n if (this.token) {\n headers.set(\"Authorization\", `Bearer ${this.token}`);\n }\n\n if (extra) {\n const merged = new Headers(extra);\n merged.forEach((value, key) => headers.set(key, value));\n }\n\n return headers;\n }\n\n private buildUrl(path: string, query?: Record<string, QueryValue>): string {\n const url = new URL(`${this.baseUrl}${path}`);\n\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n url.searchParams.set(key, String(value));\n });\n }\n\n return url.toString();\n }\n}\n\ntype QueryValue = string | number | boolean | null | undefined;\n\ntype RequestOptions = {\n query?: Record<string, QueryValue>;\n body?: unknown;\n rawBody?: BodyInit;\n contentType?: string;\n headers?: HeadersInit;\n accept?: string;\n signal?: AbortSignal;\n};\n\n/**\n * Auto-select and call `authenticate` based on the agent's advertised auth methods.\n * Prefers env-var-based methods that the server process already has configured.\n */\nasync function autoAuthenticate(acp: AcpHttpClient, methods: AuthMethod[]): Promise<void> {\n // Only attempt env-var-based methods that the server process can satisfy\n // automatically. Interactive methods (e.g. \"claude-login\") cannot be\n // fulfilled programmatically and must be skipped.\n const envBased = methods.find(\n (m) =>\n m.id === \"codex-api-key\" ||\n m.id === \"openai-api-key\" ||\n m.id === \"anthropic-api-key\",\n );\n\n if (!envBased) {\n return;\n }\n\n try {\n await acp.authenticate({ methodId: envBased.id });\n } catch {\n // Authentication is best-effort; the agent may already have credentials\n // from env vars or credential files configured on the server side.\n }\n}\n\nfunction normalizeSessionInit(\n value: Omit<NewSessionRequest, \"_meta\"> | undefined,\n): Omit<NewSessionRequest, \"_meta\"> {\n if (!value) {\n return {\n cwd: defaultCwd(),\n mcpServers: [],\n };\n }\n\n return {\n ...value,\n cwd: value.cwd ?? defaultCwd(),\n mcpServers: value.mcpServers ?? [],\n };\n}\n\nfunction mapSessionParams(params: Record<string, unknown>, agentSessionId: string): Record<string, unknown> {\n return {\n ...params,\n sessionId: agentSessionId,\n };\n}\n\nfunction injectReplayPrompt(params: Record<string, unknown>, replayText: string): void {\n const prompt = Array.isArray(params.prompt) ? [...params.prompt] : [];\n prompt.unshift({\n type: \"text\",\n text: replayText,\n });\n params.prompt = prompt;\n}\n\nfunction buildReplayText(events: SessionEvent[], maxChars: number): string | null {\n if (events.length === 0) {\n return null;\n }\n\n const prefix =\n \"Previous session history is replayed below as JSON-RPC envelopes. Use it as context before responding to the latest user prompt.\\n\";\n let text = prefix;\n\n for (const event of events) {\n const line = JSON.stringify({\n createdAt: event.createdAt,\n sender: event.sender,\n payload: event.payload,\n });\n\n if (text.length + line.length + 1 > maxChars) {\n text += \"\\n[history truncated]\";\n break;\n }\n\n text += `${line}\\n`;\n }\n\n return text;\n}\n\nfunction envelopeMethod(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"method\" in message) || typeof message[\"method\"] !== \"string\") {\n return null;\n }\n return message[\"method\"];\n}\n\nfunction envelopeId(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"id\" in message) || message[\"id\"] === undefined || message[\"id\"] === null) {\n return null;\n }\n return String(message[\"id\"]);\n}\n\nfunction envelopeSessionIdFromParams(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"params\" in message) || !isRecord(message[\"params\"])) {\n return null;\n }\n\n const params = message[\"params\"];\n if (typeof params.sessionId === \"string\" && params.sessionId.length > 0) {\n return params.sessionId;\n }\n\n return null;\n}\n\nfunction envelopeSessionIdFromResult(message: AnyMessage): string | null {\n if (!isRecord(message) || !(\"result\" in message) || !isRecord(message[\"result\"])) {\n return null;\n }\n\n const result = message[\"result\"];\n if (typeof result.sessionId === \"string\" && result.sessionId.length > 0) {\n return result.sessionId;\n }\n\n return null;\n}\n\nfunction cloneEnvelope(envelope: AnyMessage): AnyMessage {\n return JSON.parse(JSON.stringify(envelope)) as AnyMessage;\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction randomId(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction defaultCwd(): string {\n if (typeof process !== \"undefined\" && typeof process.cwd === \"function\") {\n return process.cwd();\n }\n return \"/\";\n}\n\nfunction normalizePositiveInt(value: number | undefined, fallback: number): number {\n if (!Number.isFinite(value) || (value ?? 0) < 1) {\n return fallback;\n }\n return Math.floor(value as number);\n}\n\nfunction normalizeSpawnOptions(\n spawn: SandboxAgentSpawnOptions | boolean | undefined,\n defaultEnabled: boolean,\n): SandboxAgentSpawnOptions & { enabled: boolean } {\n if (spawn === false) {\n return { enabled: false };\n }\n\n if (spawn === true || spawn === undefined) {\n return { enabled: defaultEnabled };\n }\n\n return {\n ...spawn,\n enabled: spawn.enabled ?? defaultEnabled,\n };\n}\n\nasync function readProblem(response: Response): Promise<ProblemDetails | undefined> {\n try {\n const text = await response.clone().text();\n if (!text) {\n return undefined;\n }\n return JSON.parse(text) as ProblemDetails;\n } catch {\n return undefined;\n }\n}\n","import type { AnyMessage, NewSessionRequest } from \"acp-http-client\";\nimport type { components, operations } from \"./generated/openapi.ts\";\n\nexport type ProblemDetails = components[\"schemas\"][\"ProblemDetails\"];\n\nexport type HealthResponse = JsonResponse<operations[\"get_v1_health\"], 200>;\nexport type AgentListResponse = JsonResponse<operations[\"get_v1_agents\"], 200>;\nexport type AgentInfo = components[\"schemas\"][\"AgentInfo\"];\nexport type AgentInstallRequest = JsonRequestBody<operations[\"post_v1_agent_install\"]>;\nexport type AgentInstallResponse = JsonResponse<operations[\"post_v1_agent_install\"], 200>;\n\nexport type AcpEnvelope = components[\"schemas\"][\"AcpEnvelope\"];\nexport type AcpServerInfo = components[\"schemas\"][\"AcpServerInfo\"];\nexport type AcpServerListResponse = JsonResponse<operations[\"get_v1_acp_servers\"], 200>;\n\nexport type FsEntriesQuery = QueryParams<operations[\"get_v1_fs_entries\"]>;\nexport type FsEntry = components[\"schemas\"][\"FsEntry\"];\nexport type FsPathQuery = QueryParams<operations[\"get_v1_fs_file\"]>;\nexport type FsDeleteQuery = QueryParams<operations[\"delete_v1_fs_entry\"]>;\nexport type FsUploadBatchQuery = QueryParams<operations[\"post_v1_fs_upload_batch\"]>;\nexport type FsWriteResponse = JsonResponse<operations[\"put_v1_fs_file\"], 200>;\nexport type FsActionResponse = JsonResponse<operations[\"delete_v1_fs_entry\"], 200>;\nexport type FsMoveRequest = JsonRequestBody<operations[\"post_v1_fs_move\"]>;\nexport type FsMoveResponse = JsonResponse<operations[\"post_v1_fs_move\"], 200>;\nexport type FsStat = JsonResponse<operations[\"get_v1_fs_stat\"], 200>;\nexport type FsUploadBatchResponse = JsonResponse<operations[\"post_v1_fs_upload_batch\"], 200>;\n\nexport type McpConfigQuery = QueryParams<operations[\"get_v1_config_mcp\"]>;\nexport type McpServerConfig = components[\"schemas\"][\"McpServerConfig\"];\n\nexport type SkillsConfigQuery = QueryParams<operations[\"get_v1_config_skills\"]>;\nexport type SkillsConfig = components[\"schemas\"][\"SkillsConfig\"];\n\nexport interface SessionRecord {\n id: string;\n agent: string;\n agentSessionId: string;\n lastConnectionId: string;\n createdAt: number;\n destroyedAt?: number;\n sessionInit?: Omit<NewSessionRequest, \"_meta\">;\n}\n\nexport type SessionEventSender = \"client\" | \"agent\";\n\nexport interface SessionEvent {\n // Stable unique event id. For ordering, sort by (sessionId, eventIndex).\n id: string;\n eventIndex: number;\n sessionId: string;\n createdAt: number;\n connectionId: string;\n sender: SessionEventSender;\n payload: AnyMessage;\n}\n\nexport interface ListPageRequest {\n cursor?: string;\n limit?: number;\n}\n\nexport interface ListPage<T> {\n items: T[];\n nextCursor?: string;\n}\n\nexport interface ListEventsRequest extends ListPageRequest {\n sessionId: string;\n}\n\nexport interface SessionPersistDriver {\n getSession(id: string): Promise<SessionRecord | null>;\n listSessions(request?: ListPageRequest): Promise<ListPage<SessionRecord>>;\n updateSession(session: SessionRecord): Promise<void>;\n listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>>;\n insertEvent(event: SessionEvent): Promise<void>;\n}\n\nexport interface InMemorySessionPersistDriverOptions {\n maxSessions?: number;\n maxEventsPerSession?: number;\n}\n\nconst DEFAULT_MAX_SESSIONS = 1024;\nconst DEFAULT_MAX_EVENTS_PER_SESSION = 500;\nconst DEFAULT_LIST_LIMIT = 100;\n\nexport class InMemorySessionPersistDriver implements SessionPersistDriver {\n private readonly maxSessions: number;\n private readonly maxEventsPerSession: number;\n private readonly sessions = new Map<string, SessionRecord>();\n private readonly eventsBySession = new Map<string, SessionEvent[]>();\n\n constructor(options: InMemorySessionPersistDriverOptions = {}) {\n this.maxSessions = normalizeCap(options.maxSessions, DEFAULT_MAX_SESSIONS);\n this.maxEventsPerSession = normalizeCap(\n options.maxEventsPerSession,\n DEFAULT_MAX_EVENTS_PER_SESSION,\n );\n }\n\n async getSession(id: string): Promise<SessionRecord | null> {\n const session = this.sessions.get(id);\n return session ? cloneSessionRecord(session) : null;\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<SessionRecord>> {\n const sorted = [...this.sessions.values()].sort((a, b) => {\n if (a.createdAt !== b.createdAt) {\n return a.createdAt - b.createdAt;\n }\n return a.id.localeCompare(b.id);\n });\n const page = paginate(sorted, request);\n return {\n items: page.items.map(cloneSessionRecord),\n nextCursor: page.nextCursor,\n };\n }\n\n async updateSession(session: SessionRecord): Promise<void> {\n this.sessions.set(session.id, { ...session });\n\n if (!this.eventsBySession.has(session.id)) {\n this.eventsBySession.set(session.id, []);\n }\n\n if (this.sessions.size <= this.maxSessions) {\n return;\n }\n\n const overflow = this.sessions.size - this.maxSessions;\n const removable = [...this.sessions.values()]\n .sort((a, b) => {\n if (a.createdAt !== b.createdAt) {\n return a.createdAt - b.createdAt;\n }\n return a.id.localeCompare(b.id);\n })\n .slice(0, overflow)\n .map((sessionToRemove) => sessionToRemove.id);\n\n for (const sessionId of removable) {\n this.sessions.delete(sessionId);\n this.eventsBySession.delete(sessionId);\n }\n }\n\n async listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n const all = [...(this.eventsBySession.get(request.sessionId) ?? [])].sort((a, b) => {\n if (a.eventIndex !== b.eventIndex) {\n return a.eventIndex - b.eventIndex;\n }\n return a.id.localeCompare(b.id);\n });\n const page = paginate(all, request);\n return {\n items: page.items.map(cloneSessionEvent),\n nextCursor: page.nextCursor,\n };\n }\n\n async insertEvent(event: SessionEvent): Promise<void> {\n const events = this.eventsBySession.get(event.sessionId) ?? [];\n events.push(cloneSessionEvent(event));\n\n if (events.length > this.maxEventsPerSession) {\n events.splice(0, events.length - this.maxEventsPerSession);\n }\n\n this.eventsBySession.set(event.sessionId, events);\n }\n}\n\nfunction cloneSessionRecord(session: SessionRecord): SessionRecord {\n return {\n ...session,\n sessionInit: session.sessionInit\n ? (JSON.parse(JSON.stringify(session.sessionInit)) as SessionRecord[\"sessionInit\"])\n : undefined,\n };\n}\n\nfunction cloneSessionEvent(event: SessionEvent): SessionEvent {\n return {\n ...event,\n payload: JSON.parse(JSON.stringify(event.payload)) as AnyMessage,\n };\n}\n\ntype ResponsesOf<T> = T extends { responses: infer R } ? R : never;\ntype JsonResponse<T, StatusCode extends keyof ResponsesOf<T>> = ResponsesOf<T>[StatusCode] extends {\n content: { \"application/json\": infer B };\n}\n ? B\n : never;\n\ntype JsonRequestBody<T> = T extends {\n requestBody: { content: { \"application/json\": infer B } };\n}\n ? B\n : never;\n\ntype QueryParams<T> = T extends { parameters: { query: infer Q } }\n ? Q\n : T extends { parameters: { query?: infer Q } }\n ? Q\n : never;\n\nfunction normalizeCap(value: number | undefined, fallback: number): number {\n if (!Number.isFinite(value) || (value ?? 0) < 1) {\n return fallback;\n }\n return Math.floor(value as number);\n}\n\nfunction paginate<T>(items: T[], request: ListPageRequest): ListPage<T> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeCap(request.limit, DEFAULT_LIST_LIMIT);\n const slice = items.slice(offset, offset + limit);\n const nextOffset = offset + slice.length;\n return {\n items: slice,\n nextCursor: nextOffset < items.length ? String(nextOffset) : undefined,\n };\n}\n\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) {\n return 0;\n }\n const parsed = Number.parseInt(cursor, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return 0;\n }\n return parsed;\n}\n","export {\n LiveAcpConnection,\n SandboxAgent,\n SandboxAgentError,\n Session,\n} from \"./client.ts\";\n\nexport { AcpRpcError } from \"acp-http-client\";\n\nexport { buildInspectorUrl } from \"./inspector.ts\";\n\nexport type {\n SandboxAgentConnectOptions,\n SandboxAgentStartOptions,\n SessionCreateRequest,\n SessionResumeOrCreateRequest,\n SessionSendOptions,\n SessionEventListener,\n} from \"./client.ts\";\n\nexport type { InspectorUrlOptions } from \"./inspector.ts\";\n\nexport {\n InMemorySessionPersistDriver,\n} from \"./types.ts\";\n\nexport type {\n AcpEnvelope,\n AcpServerInfo,\n AcpServerListResponse,\n AgentInfo,\n AgentInstallRequest,\n AgentInstallResponse,\n AgentListResponse,\n FsActionResponse,\n FsDeleteQuery,\n FsEntriesQuery,\n FsEntry,\n FsMoveRequest,\n FsMoveResponse,\n FsPathQuery,\n FsStat,\n FsUploadBatchQuery,\n FsUploadBatchResponse,\n FsWriteResponse,\n HealthResponse,\n InMemorySessionPersistDriverOptions,\n ListEventsRequest,\n ListPage,\n ListPageRequest,\n McpConfigQuery,\n McpServerConfig,\n ProblemDetails,\n SessionEvent,\n SessionPersistDriver,\n SessionRecord,\n SkillsConfig,\n SkillsConfigQuery,\n} from \"./types.ts\";\n\nexport type {\n SandboxAgentSpawnLogMode,\n SandboxAgentSpawnOptions,\n} from \"./spawn.ts\";\n","export interface InspectorUrlOptions {\n /**\n * Base URL of the sandbox-agent server.\n */\n baseUrl: string;\n /**\n * Optional bearer token for authentication.\n */\n token?: string;\n /**\n * Optional extra headers to pass to the sandbox-agent server.\n * Will be JSON-encoded in the URL.\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Builds a URL to the sandbox-agent inspector UI with the given connection parameters.\n * The inspector UI is served at /ui/ on the sandbox-agent server.\n */\nexport function buildInspectorUrl(options: InspectorUrlOptions): string {\n const normalized = options.baseUrl.replace(/\\/+$/, \"\");\n const params = new URLSearchParams();\n if (options.token) {\n params.set(\"token\", options.token);\n }\n if (options.headers && Object.keys(options.headers).length > 0) {\n params.set(\"headers\", JSON.stringify(options.headers));\n }\n const queryString = params.toString();\n return `${normalized}/ui/${queryString ? `?${queryString}` : \"\"}`;\n}\n"],"mappings":"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","names":["pending"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sandbox-agent",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Universal API for automatic coding agents in sandboxes. Supports Claude Code, Codex, OpenCode, and Amp.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"acp-http-client": "0.1
|
|
21
|
-
"@sandbox-agent/cli-shared": "0.2.
|
|
20
|
+
"acp-http-client": "0.2.1",
|
|
21
|
+
"@sandbox-agent/cli-shared": "0.2.1"
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"dist"
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"vitest": "^3.0.0"
|
|
32
32
|
},
|
|
33
33
|
"optionalDependencies": {
|
|
34
|
-
"@sandbox-agent/cli": "0.2.
|
|
34
|
+
"@sandbox-agent/cli": "0.2.1"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"generate:openapi": "SANDBOX_AGENT_SKIP_INSPECTOR=1 cargo run -p sandbox-agent-openapi-gen -- --out ../../docs/openapi.json",
|
|
38
38
|
"generate:types": "openapi-typescript ../../docs/openapi.json -o src/generated/openapi.ts && node ./scripts/patch-openapi-types.mjs",
|
|
39
39
|
"generate": "pnpm run generate:openapi && pnpm run generate:types",
|
|
40
|
-
"build": "pnpm --filter acp-http-client build && if [ -z \"$SKIP_OPENAPI_GEN\" ]; then pnpm run generate:openapi; fi && pnpm run generate:types && tsup",
|
|
40
|
+
"build": "pnpm --filter acp-http-client build && pnpm --filter @sandbox-agent/cli-shared build && if [ -z \"$SKIP_OPENAPI_GEN\" ]; then pnpm run generate:openapi; fi && pnpm run generate:types && tsup",
|
|
41
41
|
"typecheck": "tsc --noEmit",
|
|
42
42
|
"test": "vitest run",
|
|
43
43
|
"test:watch": "vitest"
|