@letta-ai/letta-agent-sdk 0.3.2 → 0.3.3

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.
Files changed (49) hide show
  1. package/AGENTS.md +47 -0
  2. package/README.md +17 -0
  3. package/dist/client-entry.js +800 -732
  4. package/dist/client-entry.js.map +8 -5
  5. package/dist/cloud-sandbox.d.ts +33 -0
  6. package/dist/cloud-sandbox.d.ts.map +1 -0
  7. package/dist/cloud-session.d.ts.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +799 -732
  11. package/dist/index.js.map +9 -6
  12. package/dist/remote-client-session-core.d.ts +6 -93
  13. package/dist/remote-client-session-core.d.ts.map +1 -1
  14. package/dist/remote-session-protocol.d.ts +130 -0
  15. package/dist/remote-session-protocol.d.ts.map +1 -0
  16. package/dist/remote-turn-coordinator.d.ts +49 -0
  17. package/dist/remote-turn-coordinator.d.ts.map +1 -0
  18. package/dist/types.d.ts +2 -20
  19. package/dist/types.d.ts.map +1 -1
  20. package/package.json +5 -2
  21. package/src/app-server-management.ts +641 -0
  22. package/src/app-server-session.ts +948 -0
  23. package/src/cli-resolver.ts +46 -0
  24. package/src/client-base.ts +482 -0
  25. package/src/client-entry.ts +31 -0
  26. package/src/client.ts +138 -0
  27. package/src/cloud-management.ts +360 -0
  28. package/src/cloud-sandbox.ts +117 -0
  29. package/src/cloud-session.ts +1313 -0
  30. package/src/index.ts +440 -0
  31. package/src/interactiveToolPolicy.ts +62 -0
  32. package/src/local-app-server-session.ts +39 -0
  33. package/src/local-app-server.ts +137 -0
  34. package/src/management-types.ts +133 -0
  35. package/src/management.ts +206 -0
  36. package/src/protocol.ts +249 -0
  37. package/src/remote-client-session-core.ts +786 -0
  38. package/src/remote-session-protocol.ts +660 -0
  39. package/src/remote-turn-coordinator.ts +505 -0
  40. package/src/remote.ts +177 -0
  41. package/src/repositories.ts +340 -0
  42. package/src/request-ids.ts +33 -0
  43. package/src/session.ts +1638 -0
  44. package/src/stream-events.ts +88 -0
  45. package/src/tool-helpers.ts +147 -0
  46. package/src/transport.ts +484 -0
  47. package/src/types.ts +1328 -0
  48. package/src/validation.ts +223 -0
  49. package/src/websocket.ts +22 -0
@@ -1,3 +1,5 @@
1
+ // Generated bundle. Canonical modules are published under src/ and maintained in the letta-agent-sdk repository.
2
+
1
3
  // src/repositories.ts
2
4
  var DEFAULT_CLOUD_API_BASE_URL = "https://api.letta.com";
3
5
  function getDefaultApiKey() {
@@ -5711,7 +5713,7 @@ function buildCanUseToolContext(request, requestId) {
5711
5713
  return context;
5712
5714
  }
5713
5715
 
5714
- // src/remote-client-session-core.ts
5716
+ // src/remote-session-protocol.ts
5715
5717
  var FAILURE_STOP_REASONS = new Set([
5716
5718
  "error",
5717
5719
  "llm_api_error",
@@ -6106,218 +6108,606 @@ function normalizeSendMessage(message) {
6106
6108
  return message;
6107
6109
  }
6108
6110
 
6109
- class RemoteClientSessionCore {
6110
- mode;
6111
- controller = null;
6112
- runtime = null;
6113
- initialized = false;
6114
- closed = false;
6115
- activeTurnStartedAt = 0;
6116
- _agentId = null;
6117
- _sessionId = null;
6118
- _conversationId = null;
6119
- _model = "";
6120
- _modelSettings = null;
6111
+ // src/remote-turn-coordinator.ts
6112
+ class RemoteTurnCoordinator {
6121
6113
  label;
6122
6114
  requestTimeoutMs;
6123
- initializePromise = null;
6115
+ onDeviceStatus;
6124
6116
  streamQueue = [];
6125
6117
  streamResolvers = [];
6126
- removeMessageHandler = null;
6127
6118
  activeTurn = null;
6128
6119
  pendingTurns = [];
6129
6120
  nextTurnId = 0;
6130
6121
  messageCounter = 0;
6131
6122
  clientMessageCounter = 0;
6132
- toolNames;
6133
- deviceStatusListeners = new Set;
6134
- deviceStatusRefreshCancels = new Set;
6135
- constructor(mode, config) {
6136
- this.mode = mode;
6123
+ closed = false;
6124
+ _activeTurnStartedAt = 0;
6125
+ constructor(config) {
6137
6126
  this.label = config.label;
6138
6127
  this.requestTimeoutMs = config.requestTimeoutMs;
6128
+ this.onDeviceStatus = config.onDeviceStatus;
6139
6129
  }
6140
- async initialize() {
6141
- if (this.closed) {
6142
- throw new Error("Session is closed");
6143
- }
6144
- if (this.initializePromise) {
6145
- return this.initializePromise;
6146
- }
6147
- if (this.initialized) {
6148
- throw new Error("Session already initialized");
6149
- }
6150
- const attempt = this.performInitialize();
6151
- const memo = attempt.catch((error) => {
6152
- this.cleanupFailedInitialize();
6153
- throw error;
6154
- }).finally(() => {
6155
- if (this.initializePromise === memo) {
6156
- this.initializePromise = null;
6157
- }
6158
- });
6159
- this.initializePromise = memo;
6160
- return memo;
6161
- }
6162
- async performInitialize() {
6163
- const init = await this.initializeRuntimeController();
6164
- this.controller = init.controller;
6165
- this.runtime = init.runtime;
6166
- this._agentId = init.runtime.agent_id;
6167
- this._conversationId = init.runtime.conversation_id;
6168
- this._sessionId = `${init.runtime.agent_id}:${init.runtime.conversation_id}`;
6169
- this._modelSettings = init.modelSettings ?? null;
6170
- this._model = typeof init.model === "string" ? init.model : typeof this._modelSettings?.model === "string" ? this._modelSettings.model : "";
6171
- this.toolNames = init.tools;
6172
- this.removeMessageHandler = this.controller.onMessage(this.handleProtocolMessage);
6173
- await this.afterRuntimeInitialized();
6174
- await this.applyPostInitializeOptions();
6175
- if (this.closed) {
6176
- throw new Error("Session is closed");
6177
- }
6178
- this.initialized = true;
6179
- const initMessage = {
6180
- type: "init",
6181
- agentId: init.runtime.agent_id,
6182
- sessionId: this._sessionId,
6183
- conversationId: init.runtime.conversation_id,
6184
- model: this._model
6185
- };
6186
- if (this.toolNames !== undefined)
6187
- initMessage.tools = this.toolNames;
6188
- if (init.skillSources !== undefined) {
6189
- initMessage.skillSources = init.skillSources;
6190
- }
6191
- return initMessage;
6192
- }
6193
- cleanupFailedInitialize() {
6194
- this.removeMessageHandler?.();
6195
- this.removeMessageHandler = null;
6196
- this.controller?.close();
6197
- this.controller = null;
6198
- this.onCoreClose();
6199
- this.runtime = null;
6200
- this._agentId = null;
6201
- this._conversationId = null;
6202
- this._sessionId = null;
6203
- this._modelSettings = null;
6204
- this._model = "";
6205
- this.toolNames = undefined;
6206
- this.initialized = false;
6130
+ get activeTurnStartedAt() {
6131
+ return this._activeTurnStartedAt;
6207
6132
  }
6208
- async send(message) {
6209
- if (!this.initialized) {
6210
- await this.initialize();
6211
- }
6212
- if (!this.controller || !this.runtime) {
6213
- throw new Error("Session is not initialized");
6214
- }
6215
- await this.beforeTurn();
6216
- const turn = this.trackSentTurn(this.runtime);
6217
- try {
6218
- this.controller.sendTurnMessage(this.runtime, message, {
6219
- clientMessageId: turn.clientMessageId
6220
- });
6221
- } catch (error) {
6222
- this.removeTrackedTurn(turn);
6223
- throw error;
6224
- }
6133
+ hasInFlightTurn() {
6134
+ return this.activeTurn !== null || this.pendingTurns.length > 0;
6225
6135
  }
6226
- async runTurn(message, _options = {}) {
6227
- if (this.activeTurn || this.pendingTurns.length > 0) {
6228
- throw new Error(`A turn is already in flight for this ${this.label} session. Use send() and stream() to let the listener queue messages.`);
6229
- }
6230
- await this.send(message);
6231
- for await (const msg of this.stream()) {
6232
- if (msg.type === "result") {
6233
- return msg;
6234
- }
6235
- }
6236
- return {
6237
- type: "result",
6238
- success: false,
6239
- error: "stream_closed",
6240
- errorCode: "stream_closed",
6241
- recoverable: false,
6242
- errorDetail: "Stream ended before terminal result",
6243
- durationMs: Date.now() - this.activeTurnStartedAt,
6244
- conversationId: this._conversationId
6136
+ trackSentTurn(runtime) {
6137
+ const turn = {
6138
+ id: ++this.nextTurnId,
6139
+ runtime,
6140
+ clientMessageId: `sdk-message-${Date.now()}-${++this.clientMessageCounter}`,
6141
+ queuedAt: Date.now(),
6142
+ startedAt: 0,
6143
+ assistantText: "",
6144
+ runIds: new Set,
6145
+ observedTurnEvidence: false,
6146
+ observedRequiresApprovalStop: false,
6147
+ abortRequested: false,
6148
+ timeout: null
6245
6149
  };
6246
- }
6247
- async* stream() {
6248
- while (true) {
6249
- const msg = await this.nextMessage();
6250
- if (!msg)
6251
- break;
6252
- yield msg;
6253
- if (msg.type === "result")
6254
- break;
6150
+ if (this.activeTurn) {
6151
+ this.pendingTurns.push(turn);
6152
+ } else {
6153
+ this.activateTurn(turn);
6255
6154
  }
6155
+ return turn;
6256
6156
  }
6257
- async abort() {
6258
- if (!this.initialized)
6259
- return;
6260
- if (!this.controller || !this.runtime)
6157
+ removeTrackedTurn(turn) {
6158
+ if (turn.timeout)
6159
+ clearTimeout(turn.timeout);
6160
+ if (this.activeTurn === turn) {
6161
+ this.activeTurn = null;
6261
6162
  return;
6163
+ }
6164
+ const index = this.pendingTurns.indexOf(turn);
6165
+ if (index !== -1)
6166
+ this.pendingTurns.splice(index, 1);
6167
+ }
6168
+ markAbortRequested() {
6262
6169
  if (this.activeTurn)
6263
6170
  this.activeTurn.abortRequested = true;
6264
- await this.controller.abort(this.runtime);
6265
6171
  }
6266
- async sendCommand(command, options) {
6267
- if (!this.initialized) {
6268
- await this.initialize();
6269
- }
6270
- if (!this.controller) {
6271
- throw new Error("Session is not initialized");
6172
+ handleProtocolMessage(message, runtime) {
6173
+ if (!sameRuntime2(message, runtime))
6174
+ return;
6175
+ const statusRecord = deviceStatusRecord(message);
6176
+ if (statusRecord) {
6177
+ const status = toSessionDeviceStatus(statusRecord);
6178
+ if (status)
6179
+ this.onDeviceStatus(status);
6180
+ return;
6272
6181
  }
6273
- if (!command || typeof command !== "object" || Array.isArray(command)) {
6274
- throw new Error("Invalid command. Expected a protocol command object.");
6182
+ if (message.type === "update_queue") {
6183
+ const sdkMessage2 = {
6184
+ type: "queue_update",
6185
+ queue: queueItems(message)
6186
+ };
6187
+ this.enqueue(sdkMessage2);
6188
+ return;
6275
6189
  }
6276
- if (typeof command.type !== "string" || command.type.length === 0) {
6277
- throw new Error("Invalid command. Expected a non-empty type.");
6190
+ if (message.type === "update_loop_status") {
6191
+ this.handleLoopStatusMessage(message);
6192
+ return;
6278
6193
  }
6279
- if (!options || !options.responseType && !options.predicate && options.timeoutMs === undefined) {
6280
- this.controller.send(command);
6194
+ const delta = streamDeltaRecord(message);
6195
+ if (!delta)
6281
6196
  return;
6197
+ const active = this.activateNextTurnFromProtocol();
6198
+ if (active) {
6199
+ active.observedTurnEvidence = true;
6200
+ const runId = streamDeltaRunId2(delta);
6201
+ if (runId)
6202
+ active.runIds.add(runId);
6282
6203
  }
6283
- const { type, ...body } = command;
6284
- const response = await this.controller.request(type, body, {
6285
- ...options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {},
6286
- predicate: options.predicate ? (message) => options.predicate?.(message) === true : options.responseType ? (message) => message.type === options.responseType : undefined
6204
+ const sdkMessage = this.transformStreamDelta(delta);
6205
+ if (sdkMessage)
6206
+ this.enqueue(sdkMessage);
6207
+ this.handleTurnTerminalDelta(delta, sdkMessage);
6208
+ }
6209
+ nextMessage() {
6210
+ const next = this.streamQueue.shift();
6211
+ if (next)
6212
+ return Promise.resolve(next);
6213
+ if (this.closed)
6214
+ return Promise.resolve(null);
6215
+ return new Promise((resolve) => {
6216
+ this.streamResolvers.push(resolve);
6287
6217
  });
6288
- return response;
6289
6218
  }
6290
- async listModels() {
6291
- if (!this.initialized) {
6292
- await this.initialize();
6293
- }
6294
- if (!this.controller) {
6295
- throw new Error("Session is not initialized");
6219
+ close() {
6220
+ if (this.closed)
6221
+ return;
6222
+ this.closed = true;
6223
+ if (this.activeTurn?.timeout)
6224
+ clearTimeout(this.activeTurn.timeout);
6225
+ for (const turn of this.pendingTurns) {
6226
+ if (turn.timeout)
6227
+ clearTimeout(turn.timeout);
6296
6228
  }
6297
- return this.controller.listModels();
6229
+ this.activeTurn = null;
6230
+ this.pendingTurns.length = 0;
6231
+ this.resolveAll(null);
6298
6232
  }
6299
- async updateModel(update) {
6300
- if (!this.initialized) {
6301
- await this.initialize();
6302
- }
6303
- if (!this.controller || !this.runtime) {
6304
- throw new Error("Session is not initialized");
6233
+ activateTurn(turn) {
6234
+ this.activeTurn = turn;
6235
+ turn.startedAt = Date.now();
6236
+ this._activeTurnStartedAt = turn.startedAt;
6237
+ if (this.requestTimeoutMs !== undefined) {
6238
+ turn.timeout = setTimeout(() => {
6239
+ this.failTurn(turn, `Timed out waiting for ${this.label} turn`);
6240
+ }, this.requestTimeoutMs);
6241
+ turn.timeout.unref?.();
6305
6242
  }
6306
- return this.applyModelUpdate(update);
6307
6243
  }
6308
- async applyModelUpdate(update) {
6309
- if (!this.controller || !this.runtime) {
6310
- throw new Error("Session is not initialized");
6311
- }
6312
- const normalized = normalizeUpdateModelInput(update);
6313
- const payload = await this.resolveUpdateModelPayload(normalized);
6314
- const result = await this.controller.updateModel(this.runtime, payload);
6315
- if (result.modelHandle !== undefined) {
6316
- this._model = result.modelHandle;
6317
- } else if (payload.model_handle !== undefined) {
6318
- this._model = payload.model_handle;
6319
- } else if (typeof result.modelSettings?.model === "string") {
6320
- this._model = result.modelSettings.model;
6244
+ activateNextTurnFromProtocol() {
6245
+ if (this.activeTurn)
6246
+ return this.activeTurn;
6247
+ const next = this.pendingTurns.shift();
6248
+ if (!next)
6249
+ return null;
6250
+ this.activateTurn(next);
6251
+ return next;
6252
+ }
6253
+ failTurn(turn, detail) {
6254
+ if (this.activeTurn !== turn)
6255
+ return;
6256
+ this.enqueue({
6257
+ type: "error",
6258
+ message: detail,
6259
+ errorCode: "error",
6260
+ stopReason: "error",
6261
+ errorDetail: detail,
6262
+ recoverable: false
6263
+ });
6264
+ this.completeActiveTurn({
6265
+ runtime: turn.runtime,
6266
+ stopReason: "error",
6267
+ runIds: [...turn.runIds],
6268
+ success: false,
6269
+ detail,
6270
+ errorCode: "error"
6271
+ });
6272
+ }
6273
+ completeActiveTurn(turn) {
6274
+ const active = this.activeTurn;
6275
+ if (!active)
6276
+ return;
6277
+ if (active.timeout) {
6278
+ clearTimeout(active.timeout);
6279
+ active.timeout = null;
6280
+ }
6281
+ this.enqueue(this.resultFromTurn(turn, active));
6282
+ this.activeTurn = null;
6283
+ }
6284
+ handleLoopStatusMessage(message) {
6285
+ const status = loopStatusValue(message);
6286
+ if (!status)
6287
+ return;
6288
+ const activeRunIds = loopStatusRunIds(message);
6289
+ const sdkMessage = {
6290
+ type: "loop_status",
6291
+ status,
6292
+ activeRunIds
6293
+ };
6294
+ this.enqueue(sdkMessage);
6295
+ const active = this.activeTurn;
6296
+ if (!active)
6297
+ return;
6298
+ for (const runId of activeRunIds)
6299
+ active.runIds.add(runId);
6300
+ const hadTurnEvidence = active.observedTurnEvidence || active.observedRequiresApprovalStop;
6301
+ if (!hadTurnEvidence)
6302
+ return;
6303
+ if (status === "WAITING_ON_APPROVAL") {
6304
+ this.completeActiveTurn({
6305
+ runtime: active.runtime,
6306
+ stopReason: "requires_approval",
6307
+ runIds: [...active.runIds]
6308
+ });
6309
+ return;
6310
+ }
6311
+ if (status === "WAITING_ON_INPUT" && active.abortRequested) {
6312
+ this.completeActiveTurn({
6313
+ runtime: active.runtime,
6314
+ stopReason: "interrupted",
6315
+ runIds: [...active.runIds],
6316
+ success: false,
6317
+ detail: "Interrupted",
6318
+ errorCode: "interrupted"
6319
+ });
6320
+ return;
6321
+ }
6322
+ if (status === "WAITING_ON_INPUT" && active.observedTurnEvidence) {
6323
+ this.completeActiveTurn({
6324
+ runtime: active.runtime,
6325
+ stopReason: null,
6326
+ runIds: [...active.runIds]
6327
+ });
6328
+ }
6329
+ }
6330
+ handleTurnTerminalDelta(delta, sdkMessage) {
6331
+ const active = this.activeTurn;
6332
+ if (!active)
6333
+ return;
6334
+ const messageType = streamDeltaMessageType2(delta);
6335
+ if (messageType === "stop_reason") {
6336
+ const stopReason = streamDeltaStopReason2(delta) ?? null;
6337
+ if (stopReason === "requires_approval") {
6338
+ active.observedRequiresApprovalStop = true;
6339
+ return;
6340
+ }
6341
+ this.completeActiveTurn({
6342
+ runtime: active.runtime,
6343
+ stopReason,
6344
+ runIds: [...active.runIds]
6345
+ });
6346
+ return;
6347
+ }
6348
+ if (sdkMessage?.type === "error") {
6349
+ this.completeActiveTurn({
6350
+ runtime: active.runtime,
6351
+ stopReason: sdkMessage.stopReason,
6352
+ runIds: [...active.runIds],
6353
+ success: false,
6354
+ detail: sdkMessage.errorDetail ?? sdkMessage.message,
6355
+ errorCode: sdkMessage.errorCode
6356
+ });
6357
+ }
6358
+ }
6359
+ transformStreamDelta(delta) {
6360
+ const messageType = typeof delta.message_type === "string" ? delta.message_type : undefined;
6361
+ const runId = typeof delta.run_id === "string" ? delta.run_id : undefined;
6362
+ const uuid = typeof delta.id === "string" ? delta.id : `${this.label}-${++this.messageCounter}`;
6363
+ if (messageType === "assistant_message") {
6364
+ const content = extractTextFromContent(delta.content);
6365
+ if (!content)
6366
+ return null;
6367
+ if (this.activeTurn)
6368
+ this.activeTurn.assistantText += content;
6369
+ return { type: "assistant", content, uuid, runId };
6370
+ }
6371
+ if (messageType === "reasoning_message") {
6372
+ const content = typeof delta.reasoning === "string" ? delta.reasoning : extractTextFromContent(delta.content);
6373
+ if (!content)
6374
+ return null;
6375
+ return { type: "reasoning", content, uuid, runId };
6376
+ }
6377
+ if (messageType === "tool_call_message" || messageType === "approval_request_message") {
6378
+ const toolCall = firstToolCall(delta);
6379
+ if (!toolCall)
6380
+ return null;
6381
+ const fn = toolCall.function && typeof toolCall.function === "object" ? toolCall.function : undefined;
6382
+ const toolCallId = (typeof toolCall.tool_call_id === "string" ? toolCall.tool_call_id : undefined) ?? (typeof toolCall.id === "string" ? toolCall.id : undefined);
6383
+ if (!toolCallId) {
6384
+ const detail = `Missing tool_call_id in ${messageType} (uuid=${uuid})`;
6385
+ return {
6386
+ type: "error",
6387
+ message: detail,
6388
+ errorCode: "protocol_error",
6389
+ stopReason: "protocol_error",
6390
+ runId,
6391
+ recoverable: false,
6392
+ errorDetail: detail
6393
+ };
6394
+ }
6395
+ const toolName = (typeof toolCall.name === "string" ? toolCall.name : undefined) ?? (typeof fn?.name === "string" ? fn.name : undefined) ?? "?";
6396
+ const { input, raw } = toolInputFromArguments(toolCall.arguments ?? fn?.arguments);
6397
+ return {
6398
+ type: "tool_call",
6399
+ toolCallId,
6400
+ toolName,
6401
+ toolInput: input,
6402
+ rawArguments: raw,
6403
+ uuid,
6404
+ runId
6405
+ };
6406
+ }
6407
+ if (messageType === "tool_return_message") {
6408
+ const toolReturn = firstToolReturn(delta) ?? delta;
6409
+ const toolCallId = (typeof delta.tool_call_id === "string" ? delta.tool_call_id : undefined) ?? (typeof toolReturn.tool_call_id === "string" ? toolReturn.tool_call_id : undefined);
6410
+ if (!toolCallId)
6411
+ return null;
6412
+ const content = extractTextFromContent(delta.tool_return ?? toolReturn.tool_return ?? toolReturn.content) ?? "";
6413
+ const status = typeof delta.status === "string" ? delta.status : toolReturn.status;
6414
+ return {
6415
+ type: "tool_result",
6416
+ toolCallId,
6417
+ content,
6418
+ isError: status === "error",
6419
+ uuid,
6420
+ runId
6421
+ };
6422
+ }
6423
+ if (messageType === "error_message" || messageType === "loop_error") {
6424
+ const detail = (typeof delta.detail === "string" ? delta.detail : undefined) ?? (typeof delta.message === "string" ? delta.message : undefined) ?? `${this.label} turn failed`;
6425
+ const stopReason = (typeof delta.stop_reason === "string" ? delta.stop_reason : undefined) ?? (typeof delta.error_type === "string" ? delta.error_type : undefined) ?? "error";
6426
+ const approvalConflict = isApprovalConflictSignal({
6427
+ detail,
6428
+ message: typeof delta.message === "string" ? delta.message : undefined,
6429
+ stopReason
6430
+ });
6431
+ return {
6432
+ type: "error",
6433
+ message: detail,
6434
+ errorCode: approvalConflict ? "approval_conflict" : toSdkErrorCode(stopReason),
6435
+ approvalConflict: approvalConflict || undefined,
6436
+ recoverable: approvalConflict ? true : false,
6437
+ errorDetail: detail,
6438
+ stopReason,
6439
+ runId
6440
+ };
6441
+ }
6442
+ if (messageType === "retry") {
6443
+ return {
6444
+ type: "retry",
6445
+ reason: typeof delta.reason === "string" ? delta.reason : "error",
6446
+ attempt: typeof delta.attempt === "number" ? delta.attempt : 0,
6447
+ maxAttempts: typeof delta.max_attempts === "number" ? delta.max_attempts : 0,
6448
+ delayMs: typeof delta.delay_ms === "number" ? delta.delay_ms : 0,
6449
+ runId
6450
+ };
6451
+ }
6452
+ if (messageType === "stop_reason" || messageType === "ping") {
6453
+ return null;
6454
+ }
6455
+ return {
6456
+ type: "stream_event",
6457
+ event: delta,
6458
+ uuid
6459
+ };
6460
+ }
6461
+ resultFromTurn(turn, tracker) {
6462
+ const stopReason = turn.stopReason ?? (turn.success === false ? "error" : undefined);
6463
+ const approvalConflict = isApprovalConflictSignal({
6464
+ detail: turn.detail,
6465
+ stopReason
6466
+ });
6467
+ const success = turn.success !== undefined ? turn.success && !approvalConflict && !FAILURE_STOP_REASONS.has(stopReason ?? "") : !approvalConflict && !FAILURE_STOP_REASONS.has(stopReason ?? "");
6468
+ const errorCode = approvalConflict ? "approval_conflict" : turn.errorCode ?? toSdkErrorCode(stopReason);
6469
+ return {
6470
+ type: "result",
6471
+ success,
6472
+ result: success ? tracker?.assistantText || undefined : undefined,
6473
+ error: success ? undefined : errorCode ?? stopReason ?? "error",
6474
+ errorCode: success ? undefined : errorCode ?? "error",
6475
+ approvalConflict: approvalConflict || undefined,
6476
+ recoverable: approvalConflict ? true : success ? undefined : false,
6477
+ errorDetail: success ? undefined : turn.detail,
6478
+ stopReason,
6479
+ durationMs: Date.now() - (tracker?.startedAt || this._activeTurnStartedAt),
6480
+ conversationId: turn.runtime.conversation_id,
6481
+ runIds: turn.runIds.length > 0 ? turn.runIds : undefined
6482
+ };
6483
+ }
6484
+ enqueue(message) {
6485
+ const resolver = this.streamResolvers.shift();
6486
+ if (resolver) {
6487
+ resolver(message);
6488
+ return;
6489
+ }
6490
+ this.streamQueue.push(message);
6491
+ }
6492
+ resolveAll(value) {
6493
+ for (const resolve of this.streamResolvers.splice(0)) {
6494
+ resolve(value);
6495
+ }
6496
+ }
6497
+ }
6498
+ // src/remote-client-session-core.ts
6499
+ class RemoteClientSessionCore {
6500
+ mode;
6501
+ controller = null;
6502
+ runtime = null;
6503
+ initialized = false;
6504
+ closed = false;
6505
+ _agentId = null;
6506
+ _sessionId = null;
6507
+ _conversationId = null;
6508
+ _model = "";
6509
+ _modelSettings = null;
6510
+ label;
6511
+ requestTimeoutMs;
6512
+ initializePromise = null;
6513
+ removeMessageHandler = null;
6514
+ turns;
6515
+ toolNames;
6516
+ deviceStatusListeners = new Set;
6517
+ deviceStatusRefreshCancels = new Set;
6518
+ constructor(mode, config) {
6519
+ this.mode = mode;
6520
+ this.label = config.label;
6521
+ this.requestTimeoutMs = config.requestTimeoutMs;
6522
+ this.turns = new RemoteTurnCoordinator({
6523
+ label: config.label,
6524
+ requestTimeoutMs: config.requestTimeoutMs,
6525
+ onDeviceStatus: (status) => this.emitDeviceStatus(status)
6526
+ });
6527
+ }
6528
+ async initialize() {
6529
+ if (this.closed) {
6530
+ throw new Error("Session is closed");
6531
+ }
6532
+ if (this.initializePromise) {
6533
+ return this.initializePromise;
6534
+ }
6535
+ if (this.initialized) {
6536
+ throw new Error("Session already initialized");
6537
+ }
6538
+ const attempt = this.performInitialize();
6539
+ const memo = attempt.catch((error) => {
6540
+ this.cleanupFailedInitialize();
6541
+ throw error;
6542
+ }).finally(() => {
6543
+ if (this.initializePromise === memo) {
6544
+ this.initializePromise = null;
6545
+ }
6546
+ });
6547
+ this.initializePromise = memo;
6548
+ return memo;
6549
+ }
6550
+ async performInitialize() {
6551
+ const init = await this.initializeRuntimeController();
6552
+ this.controller = init.controller;
6553
+ this.runtime = init.runtime;
6554
+ this._agentId = init.runtime.agent_id;
6555
+ this._conversationId = init.runtime.conversation_id;
6556
+ this._sessionId = `${init.runtime.agent_id}:${init.runtime.conversation_id}`;
6557
+ this._modelSettings = init.modelSettings ?? null;
6558
+ this._model = typeof init.model === "string" ? init.model : typeof this._modelSettings?.model === "string" ? this._modelSettings.model : "";
6559
+ this.toolNames = init.tools;
6560
+ this.removeMessageHandler = this.controller.onMessage((message) => {
6561
+ if (this.runtime)
6562
+ this.turns.handleProtocolMessage(message, this.runtime);
6563
+ });
6564
+ await this.afterRuntimeInitialized();
6565
+ await this.applyPostInitializeOptions();
6566
+ if (this.closed) {
6567
+ throw new Error("Session is closed");
6568
+ }
6569
+ this.initialized = true;
6570
+ const initMessage = {
6571
+ type: "init",
6572
+ agentId: init.runtime.agent_id,
6573
+ sessionId: this._sessionId,
6574
+ conversationId: init.runtime.conversation_id,
6575
+ model: this._model
6576
+ };
6577
+ if (this.toolNames !== undefined)
6578
+ initMessage.tools = this.toolNames;
6579
+ if (init.skillSources !== undefined) {
6580
+ initMessage.skillSources = init.skillSources;
6581
+ }
6582
+ return initMessage;
6583
+ }
6584
+ cleanupFailedInitialize() {
6585
+ this.removeMessageHandler?.();
6586
+ this.removeMessageHandler = null;
6587
+ this.controller?.close();
6588
+ this.controller = null;
6589
+ this.onCoreClose();
6590
+ this.runtime = null;
6591
+ this._agentId = null;
6592
+ this._conversationId = null;
6593
+ this._sessionId = null;
6594
+ this._modelSettings = null;
6595
+ this._model = "";
6596
+ this.toolNames = undefined;
6597
+ this.initialized = false;
6598
+ }
6599
+ async send(message) {
6600
+ if (!this.initialized) {
6601
+ await this.initialize();
6602
+ }
6603
+ if (!this.controller || !this.runtime) {
6604
+ throw new Error("Session is not initialized");
6605
+ }
6606
+ await this.beforeTurn();
6607
+ const turn = this.turns.trackSentTurn(this.runtime);
6608
+ try {
6609
+ this.controller.sendTurnMessage(this.runtime, message, {
6610
+ clientMessageId: turn.clientMessageId
6611
+ });
6612
+ } catch (error) {
6613
+ this.turns.removeTrackedTurn(turn);
6614
+ throw error;
6615
+ }
6616
+ }
6617
+ async runTurn(message, _options = {}) {
6618
+ if (this.turns.hasInFlightTurn()) {
6619
+ throw new Error(`A turn is already in flight for this ${this.label} session. Use send() and stream() to let the listener queue messages.`);
6620
+ }
6621
+ await this.send(message);
6622
+ for await (const msg of this.stream()) {
6623
+ if (msg.type === "result") {
6624
+ return msg;
6625
+ }
6626
+ }
6627
+ return {
6628
+ type: "result",
6629
+ success: false,
6630
+ error: "stream_closed",
6631
+ errorCode: "stream_closed",
6632
+ recoverable: false,
6633
+ errorDetail: "Stream ended before terminal result",
6634
+ durationMs: Date.now() - this.turns.activeTurnStartedAt,
6635
+ conversationId: this._conversationId
6636
+ };
6637
+ }
6638
+ async* stream() {
6639
+ while (true) {
6640
+ const msg = await this.turns.nextMessage();
6641
+ if (!msg)
6642
+ break;
6643
+ yield msg;
6644
+ if (msg.type === "result")
6645
+ break;
6646
+ }
6647
+ }
6648
+ async abort() {
6649
+ if (!this.initialized)
6650
+ return;
6651
+ if (!this.controller || !this.runtime)
6652
+ return;
6653
+ this.turns.markAbortRequested();
6654
+ await this.controller.abort(this.runtime);
6655
+ }
6656
+ async sendCommand(command, options) {
6657
+ if (!this.initialized) {
6658
+ await this.initialize();
6659
+ }
6660
+ if (!this.controller) {
6661
+ throw new Error("Session is not initialized");
6662
+ }
6663
+ if (!command || typeof command !== "object" || Array.isArray(command)) {
6664
+ throw new Error("Invalid command. Expected a protocol command object.");
6665
+ }
6666
+ if (typeof command.type !== "string" || command.type.length === 0) {
6667
+ throw new Error("Invalid command. Expected a non-empty type.");
6668
+ }
6669
+ if (!options || !options.responseType && !options.predicate && options.timeoutMs === undefined) {
6670
+ this.controller.send(command);
6671
+ return;
6672
+ }
6673
+ const { type, ...body } = command;
6674
+ const response = await this.controller.request(type, body, {
6675
+ ...options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {},
6676
+ predicate: options.predicate ? (message) => options.predicate?.(message) === true : options.responseType ? (message) => message.type === options.responseType : undefined
6677
+ });
6678
+ return response;
6679
+ }
6680
+ async listModels() {
6681
+ if (!this.initialized) {
6682
+ await this.initialize();
6683
+ }
6684
+ if (!this.controller) {
6685
+ throw new Error("Session is not initialized");
6686
+ }
6687
+ return this.controller.listModels();
6688
+ }
6689
+ async updateModel(update) {
6690
+ if (!this.initialized) {
6691
+ await this.initialize();
6692
+ }
6693
+ if (!this.controller || !this.runtime) {
6694
+ throw new Error("Session is not initialized");
6695
+ }
6696
+ return this.applyModelUpdate(update);
6697
+ }
6698
+ async applyModelUpdate(update) {
6699
+ if (!this.controller || !this.runtime) {
6700
+ throw new Error("Session is not initialized");
6701
+ }
6702
+ const normalized = normalizeUpdateModelInput(update);
6703
+ const payload = await this.resolveUpdateModelPayload(normalized);
6704
+ const result = await this.controller.updateModel(this.runtime, payload);
6705
+ if (result.modelHandle !== undefined) {
6706
+ this._model = result.modelHandle;
6707
+ } else if (payload.model_handle !== undefined) {
6708
+ this._model = payload.model_handle;
6709
+ } else if (typeof result.modelSettings?.model === "string") {
6710
+ this._model = result.modelSettings.model;
6321
6711
  }
6322
6712
  if ("modelSettings" in result) {
6323
6713
  this._modelSettings = result.modelSettings ?? null;
@@ -6436,562 +6826,212 @@ class RemoteClientSessionCore {
6436
6826
  rejectOnce(error instanceof Error ? error : new Error(String(error)));
6437
6827
  });
6438
6828
  });
6439
- }
6440
- async listMessages(options = {}) {
6441
- if (!this.initialized) {
6442
- await this.initialize();
6443
- }
6444
- if (!this.controller) {
6445
- throw new Error("Session is not initialized");
6446
- }
6447
- const conversationId = options.conversationId ?? this._conversationId;
6448
- if (!conversationId) {
6449
- throw new Error("No conversation id available for listMessages()");
6450
- }
6451
- return this.controller.listMessages(conversationId, options);
6452
- }
6453
- async bootstrapState(options = {}) {
6454
- if (!this.initialized) {
6455
- await this.initialize();
6456
- }
6457
- const page = await this.listMessages({
6458
- limit: options.limit,
6459
- order: options.order
6460
- });
6461
- const state = {
6462
- agentId: this._agentId ?? "",
6463
- conversationId: this._conversationId ?? "",
6464
- model: this._model,
6465
- messages: page.messages
6466
- };
6467
- if (this.toolNames !== undefined) {
6468
- state.tools = this.toolNames;
6469
- }
6470
- if (page.nextBefore !== undefined) {
6471
- state.nextBefore = page.nextBefore;
6472
- }
6473
- if (page.hasMore !== undefined) {
6474
- state.hasMore = page.hasMore;
6475
- }
6476
- return state;
6477
- }
6478
- close() {
6479
- if (this.closed)
6480
- return;
6481
- this.closed = true;
6482
- this.removeMessageHandler?.();
6483
- this.removeMessageHandler = null;
6484
- if (this.activeTurn?.timeout)
6485
- clearTimeout(this.activeTurn.timeout);
6486
- for (const turn of this.pendingTurns) {
6487
- if (turn.timeout)
6488
- clearTimeout(turn.timeout);
6489
- }
6490
- this.activeTurn = null;
6491
- this.pendingTurns.length = 0;
6492
- for (const cancel of [...this.deviceStatusRefreshCancels]) {
6493
- cancel(new Error(`Session closed while waiting for ${this.label} device status`));
6494
- }
6495
- this.deviceStatusRefreshCancels.clear();
6496
- this.deviceStatusListeners.clear();
6497
- this.controller?.close();
6498
- this.controller = null;
6499
- this.onCoreClose();
6500
- this.resolveAll(null);
6501
- }
6502
- get agentId() {
6503
- return this._agentId;
6504
- }
6505
- get sessionId() {
6506
- return this._sessionId;
6507
- }
6508
- get conversationId() {
6509
- return this._conversationId;
6510
- }
6511
- async[Symbol.asyncDispose]() {
6512
- this.close();
6513
- }
6514
- async changeDeviceState(updates) {
6515
- if (!this.initialized) {
6516
- await this.initialize();
6517
- }
6518
- if (!this.controller || !this.runtime) {
6519
- throw new Error("Session is not initialized");
6520
- }
6521
- const payload = {};
6522
- if (updates.cwd !== undefined)
6523
- payload.cwd = updates.cwd;
6524
- if (updates.permissionMode !== undefined) {
6525
- const mode = mapPermissionMode(updates.permissionMode);
6526
- if (mode !== undefined)
6527
- payload.mode = mode;
6528
- }
6529
- if (Object.keys(payload).length === 0) {
6530
- throw new Error("Invalid device state update. Expected cwd or permissionMode.");
6531
- }
6532
- this.controller.send({
6533
- type: "change_device_state",
6534
- runtime: this.runtime,
6535
- payload
6536
- });
6537
- }
6538
- async updateToolset(toolsetPreference) {
6539
- if (!this.initialized) {
6540
- await this.initialize();
6541
- }
6542
- if (!this.controller || !this.runtime) {
6543
- throw new Error("Session is not initialized");
6544
- }
6545
- const response = await this.controller.request("update_toolset", {
6546
- runtime: this.runtime,
6547
- toolset_preference: toolsetPreference
6548
- }, { predicate: (message) => message.type === "update_toolset_response" });
6549
- ensureSuccess(response, "Failed to update toolset");
6550
- }
6551
- async afterRuntimeInitialized() {}
6552
- async beforeTurn() {}
6553
- onCoreClose() {}
6554
- currentOptions() {
6555
- return this.mode.options;
6556
- }
6557
- shouldEnableMemfs(options) {
6558
- return false;
6559
- }
6560
- enableMemfsBody() {
6561
- if (!this.runtime)
6562
- return {};
6563
- return { agent_id: this.runtime.agent_id };
6564
- }
6565
- setModel(model) {
6566
- this._model = model;
6567
- }
6568
- trackSentTurn(runtime) {
6569
- const turn = {
6570
- id: ++this.nextTurnId,
6571
- runtime,
6572
- clientMessageId: `sdk-message-${Date.now()}-${++this.clientMessageCounter}`,
6573
- queuedAt: Date.now(),
6574
- startedAt: 0,
6575
- assistantText: "",
6576
- runIds: new Set,
6577
- observedTurnEvidence: false,
6578
- observedRequiresApprovalStop: false,
6579
- abortRequested: false,
6580
- timeout: null
6581
- };
6582
- if (this.activeTurn) {
6583
- this.pendingTurns.push(turn);
6584
- } else {
6585
- this.activateTurn(turn);
6586
- }
6587
- return turn;
6588
- }
6589
- activateTurn(turn) {
6590
- this.activeTurn = turn;
6591
- turn.startedAt = Date.now();
6592
- this.activeTurnStartedAt = turn.startedAt;
6593
- if (this.requestTimeoutMs !== undefined) {
6594
- turn.timeout = setTimeout(() => {
6595
- this.failTurn(turn, `Timed out waiting for ${this.label} turn`);
6596
- }, this.requestTimeoutMs);
6597
- turn.timeout.unref?.();
6598
- }
6599
- }
6600
- activateNextTurnFromProtocol() {
6601
- if (this.activeTurn)
6602
- return this.activeTurn;
6603
- const next = this.pendingTurns.shift();
6604
- if (!next)
6605
- return null;
6606
- this.activateTurn(next);
6607
- return next;
6608
- }
6609
- removeTrackedTurn(turn) {
6610
- if (turn.timeout)
6611
- clearTimeout(turn.timeout);
6612
- if (this.activeTurn === turn) {
6613
- this.activeTurn = null;
6614
- return;
6615
- }
6616
- const index = this.pendingTurns.indexOf(turn);
6617
- if (index !== -1)
6618
- this.pendingTurns.splice(index, 1);
6619
- }
6620
- failTurn(turn, detail) {
6621
- if (this.activeTurn !== turn)
6622
- return;
6623
- this.enqueue({
6624
- type: "error",
6625
- message: detail,
6626
- errorCode: "error",
6627
- stopReason: "error",
6628
- errorDetail: detail,
6629
- recoverable: false
6630
- });
6631
- this.completeActiveTurn({
6632
- runtime: turn.runtime,
6633
- stopReason: "error",
6634
- runIds: [...turn.runIds],
6635
- success: false,
6636
- detail,
6637
- errorCode: "error"
6638
- });
6639
- }
6640
- completeActiveTurn(turn) {
6641
- const active = this.activeTurn;
6642
- if (!active)
6643
- return;
6644
- if (active.timeout) {
6645
- clearTimeout(active.timeout);
6646
- active.timeout = null;
6647
- }
6648
- this.enqueue(this.resultFromTurn(turn, active));
6649
- this.activeTurn = null;
6650
- }
6651
- async resolveUpdateModelPayload(input) {
6652
- if (input.reasoningEffort === undefined) {
6653
- return modelPayloadWithoutReasoning(input);
6829
+ }
6830
+ async listMessages(options = {}) {
6831
+ if (!this.initialized) {
6832
+ await this.initialize();
6654
6833
  }
6655
6834
  if (!this.controller) {
6656
6835
  throw new Error("Session is not initialized");
6657
6836
  }
6658
- const catalog = await this.controller.listModels();
6659
- const byId = new Map(catalog.entries.map((entry) => [entry.id, entry]));
6660
- const aliases = catalog.byokProviderAliases;
6661
- let baseEntry;
6662
- let explicitHandle;
6663
- let targetHandle;
6664
- if (input.modelId !== undefined) {
6665
- baseEntry = byId.get(input.modelId);
6666
- explicitHandle = input.modelHandle;
6667
- targetHandle = baseEntry?.handle ?? toBaseModelHandle(input.modelHandle, aliases);
6668
- } else if (input.modelHandle !== undefined) {
6669
- explicitHandle = input.modelHandle;
6670
- targetHandle = toBaseModelHandle(input.modelHandle, aliases);
6671
- } else if (input.model !== undefined) {
6672
- baseEntry = byId.get(input.model);
6673
- if (baseEntry) {
6674
- targetHandle = baseEntry.handle;
6675
- } else {
6676
- explicitHandle = input.model;
6677
- targetHandle = toBaseModelHandle(input.model, aliases);
6678
- }
6679
- } else {
6680
- explicitHandle = this._model || undefined;
6681
- targetHandle = toBaseModelHandle(this._model || undefined, aliases);
6837
+ const conversationId = options.conversationId ?? this._conversationId;
6838
+ if (!conversationId) {
6839
+ throw new Error("No conversation id available for listMessages()");
6682
6840
  }
6683
- if (!targetHandle) {
6684
- throw new Error("reasoningEffort requires a current model or explicit model/modelId/modelHandle.");
6841
+ return this.controller.listMessages(conversationId, options);
6842
+ }
6843
+ async bootstrapState(options = {}) {
6844
+ if (!this.initialized) {
6845
+ await this.initialize();
6685
6846
  }
6686
- const candidates = catalog.entries.filter((entry) => entry.handle === targetHandle || entry.handle === explicitHandle);
6687
- if (candidates.length === 0) {
6688
- throw new Error(`reasoningEffort requires a model from listModels(); no catalog entry found for ${targetHandle}.`);
6847
+ const page = await this.listMessages({
6848
+ limit: options.limit,
6849
+ order: options.order
6850
+ });
6851
+ const state = {
6852
+ agentId: this._agentId ?? "",
6853
+ conversationId: this._conversationId ?? "",
6854
+ model: this._model,
6855
+ messages: page.messages
6856
+ };
6857
+ if (this.toolNames !== undefined) {
6858
+ state.tools = this.toolNames;
6689
6859
  }
6690
- const contextWindow = getContextWindow(baseEntry?.updateArgs) ?? getContextWindow(this._modelSettings);
6691
- const scopedCandidates = sameContextCandidates(candidates, contextWindow);
6692
- const matchingEntry = scopedCandidates.find((entry) => getReasoningEffort(entry) === input.reasoningEffort) ?? candidates.find((entry) => getReasoningEffort(entry) === input.reasoningEffort);
6693
- if (!matchingEntry) {
6694
- throw new Error(`No ${input.reasoningEffort} reasoning tier found for model ${targetHandle}.`);
6860
+ if (page.nextBefore !== undefined) {
6861
+ state.nextBefore = page.nextBefore;
6695
6862
  }
6696
- const payload = { model_id: matchingEntry.id };
6697
- if (explicitHandle !== undefined) {
6698
- payload.model_handle = explicitHandle;
6863
+ if (page.hasMore !== undefined) {
6864
+ state.hasMore = page.hasMore;
6699
6865
  }
6700
- return payload;
6866
+ return state;
6701
6867
  }
6702
- async applyPostInitializeOptions() {
6703
- if (!this.controller || !this.runtime)
6704
- return;
6705
- const options = this.currentOptions();
6706
- if (this.shouldEnableMemfs(options)) {
6707
- const response = await this.controller.request("enable_memfs", this.enableMemfsBody(), {
6708
- predicate: (message) => message.type === "enable_memfs_response",
6709
- timeoutMs: 180000
6710
- });
6711
- ensureSuccess(response, "Failed to enable memfs");
6712
- }
6713
- const dreamingSettings = resolveDreamingSettings(options.dreaming);
6714
- if (dreamingSettings) {
6715
- const response = await this.controller.request("set_reflection_settings", {
6716
- runtime: this.runtime,
6717
- settings: dreamingSettings,
6718
- scope: "both"
6719
- }, { predicate: (message) => message.type === "set_reflection_settings_response" });
6720
- ensureSuccess(response, "Failed to update dreaming settings");
6721
- }
6722
- if (this.mode.kind !== "session")
6868
+ close() {
6869
+ if (this.closed)
6723
6870
  return;
6724
- if (this.mode.options.model !== undefined || this.mode.options.reasoningEffort !== undefined) {
6725
- await this.applyModelUpdate({
6726
- ...this.mode.options.model !== undefined ? { model: this.mode.options.model } : {},
6727
- ...this.mode.options.reasoningEffort !== undefined ? { reasoningEffort: this.mode.options.reasoningEffort } : {}
6728
- });
6871
+ this.closed = true;
6872
+ this.removeMessageHandler?.();
6873
+ this.removeMessageHandler = null;
6874
+ this.turns.close();
6875
+ for (const cancel of [...this.deviceStatusRefreshCancels]) {
6876
+ cancel(new Error(`Session closed while waiting for ${this.label} device status`));
6729
6877
  }
6878
+ this.deviceStatusRefreshCancels.clear();
6879
+ this.deviceStatusListeners.clear();
6880
+ this.controller?.close();
6881
+ this.controller = null;
6882
+ this.onCoreClose();
6730
6883
  }
6731
- handleProtocolMessage = (message) => {
6732
- if (!this.runtime || !sameRuntime2(message, this.runtime))
6733
- return;
6734
- const deviceStatus = deviceStatusRecord(message);
6735
- if (deviceStatus) {
6736
- const status = toSessionDeviceStatus(deviceStatus);
6737
- if (!status)
6738
- return;
6739
- for (const listener of [...this.deviceStatusListeners]) {
6740
- try {
6741
- listener(status);
6742
- } catch {}
6743
- }
6744
- return;
6745
- }
6746
- if (message.type === "update_queue") {
6747
- const sdkMessage2 = {
6748
- type: "queue_update",
6749
- queue: queueItems(message)
6750
- };
6751
- this.enqueue(sdkMessage2);
6752
- return;
6753
- }
6754
- if (message.type === "update_loop_status") {
6755
- this.handleLoopStatusMessage(message);
6756
- return;
6757
- }
6758
- const delta = streamDeltaRecord(message);
6759
- if (!delta)
6760
- return;
6761
- const active = this.activateNextTurnFromProtocol();
6762
- if (active) {
6763
- active.observedTurnEvidence = true;
6764
- const runId = streamDeltaRunId2(delta);
6765
- if (runId)
6766
- active.runIds.add(runId);
6767
- }
6768
- const sdkMessage = this.transformStreamDelta(delta);
6769
- if (sdkMessage) {
6770
- this.enqueue(sdkMessage);
6884
+ get agentId() {
6885
+ return this._agentId;
6886
+ }
6887
+ get sessionId() {
6888
+ return this._sessionId;
6889
+ }
6890
+ get conversationId() {
6891
+ return this._conversationId;
6892
+ }
6893
+ async[Symbol.asyncDispose]() {
6894
+ this.close();
6895
+ }
6896
+ async changeDeviceState(updates) {
6897
+ if (!this.initialized) {
6898
+ await this.initialize();
6771
6899
  }
6772
- this.handleTurnTerminalDelta(delta, sdkMessage);
6773
- };
6774
- handleLoopStatusMessage(message) {
6775
- const status = loopStatusValue(message);
6776
- if (!status)
6777
- return;
6778
- const activeRunIds = loopStatusRunIds(message);
6779
- const sdkMessage = {
6780
- type: "loop_status",
6781
- status,
6782
- activeRunIds
6783
- };
6784
- this.enqueue(sdkMessage);
6785
- const active = this.activeTurn;
6786
- if (!active)
6787
- return;
6788
- for (const runId of activeRunIds)
6789
- active.runIds.add(runId);
6790
- const hadTurnEvidence = active.observedTurnEvidence || active.observedRequiresApprovalStop;
6791
- if (!hadTurnEvidence)
6792
- return;
6793
- if (status === "WAITING_ON_APPROVAL") {
6794
- this.completeActiveTurn({
6795
- runtime: active.runtime,
6796
- stopReason: "requires_approval",
6797
- runIds: [...active.runIds]
6798
- });
6799
- return;
6900
+ if (!this.controller || !this.runtime) {
6901
+ throw new Error("Session is not initialized");
6800
6902
  }
6801
- if (status === "WAITING_ON_INPUT" && active.abortRequested) {
6802
- this.completeActiveTurn({
6803
- runtime: active.runtime,
6804
- stopReason: "interrupted",
6805
- runIds: [...active.runIds],
6806
- success: false,
6807
- detail: "Interrupted",
6808
- errorCode: "interrupted"
6809
- });
6810
- return;
6903
+ const payload = {};
6904
+ if (updates.cwd !== undefined)
6905
+ payload.cwd = updates.cwd;
6906
+ if (updates.permissionMode !== undefined) {
6907
+ const mode = mapPermissionMode(updates.permissionMode);
6908
+ if (mode !== undefined)
6909
+ payload.mode = mode;
6811
6910
  }
6812
- if (status === "WAITING_ON_INPUT" && active.observedTurnEvidence) {
6813
- this.completeActiveTurn({
6814
- runtime: active.runtime,
6815
- stopReason: null,
6816
- runIds: [...active.runIds]
6817
- });
6911
+ if (Object.keys(payload).length === 0) {
6912
+ throw new Error("Invalid device state update. Expected cwd or permissionMode.");
6818
6913
  }
6914
+ this.controller.send({
6915
+ type: "change_device_state",
6916
+ runtime: this.runtime,
6917
+ payload
6918
+ });
6819
6919
  }
6820
- handleTurnTerminalDelta(delta, sdkMessage) {
6821
- const active = this.activeTurn;
6822
- if (!active)
6823
- return;
6824
- const messageType = streamDeltaMessageType2(delta);
6825
- if (messageType === "stop_reason") {
6826
- const stopReason = streamDeltaStopReason2(delta) ?? null;
6827
- if (stopReason === "requires_approval") {
6828
- active.observedRequiresApprovalStop = true;
6829
- return;
6830
- }
6831
- this.completeActiveTurn({
6832
- runtime: active.runtime,
6833
- stopReason,
6834
- runIds: [...active.runIds]
6835
- });
6836
- return;
6920
+ async updateToolset(toolsetPreference) {
6921
+ if (!this.initialized) {
6922
+ await this.initialize();
6837
6923
  }
6838
- if (sdkMessage?.type === "error") {
6839
- this.completeActiveTurn({
6840
- runtime: active.runtime,
6841
- stopReason: sdkMessage.stopReason,
6842
- runIds: [...active.runIds],
6843
- success: false,
6844
- detail: sdkMessage.errorDetail ?? sdkMessage.message,
6845
- errorCode: sdkMessage.errorCode
6846
- });
6924
+ if (!this.controller || !this.runtime) {
6925
+ throw new Error("Session is not initialized");
6847
6926
  }
6927
+ const response = await this.controller.request("update_toolset", {
6928
+ runtime: this.runtime,
6929
+ toolset_preference: toolsetPreference
6930
+ }, { predicate: (message) => message.type === "update_toolset_response" });
6931
+ ensureSuccess(response, "Failed to update toolset");
6932
+ }
6933
+ async afterRuntimeInitialized() {}
6934
+ async beforeTurn() {}
6935
+ onCoreClose() {}
6936
+ currentOptions() {
6937
+ return this.mode.options;
6938
+ }
6939
+ shouldEnableMemfs(options) {
6940
+ return false;
6941
+ }
6942
+ enableMemfsBody() {
6943
+ if (!this.runtime)
6944
+ return {};
6945
+ return { agent_id: this.runtime.agent_id };
6848
6946
  }
6849
- transformStreamDelta(delta) {
6850
- const messageType = typeof delta.message_type === "string" ? delta.message_type : undefined;
6851
- const runId = typeof delta.run_id === "string" ? delta.run_id : undefined;
6852
- const uuid = typeof delta.id === "string" ? delta.id : `${this.label}-${++this.messageCounter}`;
6853
- if (messageType === "assistant_message") {
6854
- const content = extractTextFromContent(delta.content);
6855
- if (!content)
6856
- return null;
6857
- if (this.activeTurn)
6858
- this.activeTurn.assistantText += content;
6859
- return { type: "assistant", content, uuid, runId };
6947
+ setModel(model) {
6948
+ this._model = model;
6949
+ }
6950
+ async resolveUpdateModelPayload(input) {
6951
+ if (input.reasoningEffort === undefined) {
6952
+ return modelPayloadWithoutReasoning(input);
6860
6953
  }
6861
- if (messageType === "reasoning_message") {
6862
- const content = typeof delta.reasoning === "string" ? delta.reasoning : extractTextFromContent(delta.content);
6863
- if (!content)
6864
- return null;
6865
- return { type: "reasoning", content, uuid, runId };
6954
+ if (!this.controller) {
6955
+ throw new Error("Session is not initialized");
6866
6956
  }
6867
- if (messageType === "tool_call_message" || messageType === "approval_request_message") {
6868
- const toolCall = firstToolCall(delta);
6869
- if (!toolCall)
6870
- return null;
6871
- const fn = toolCall.function && typeof toolCall.function === "object" ? toolCall.function : undefined;
6872
- const toolCallId = (typeof toolCall.tool_call_id === "string" ? toolCall.tool_call_id : undefined) ?? (typeof toolCall.id === "string" ? toolCall.id : undefined);
6873
- if (!toolCallId) {
6874
- const detail = `Missing tool_call_id in ${messageType} (uuid=${uuid})`;
6875
- return {
6876
- type: "error",
6877
- message: detail,
6878
- errorCode: "protocol_error",
6879
- stopReason: "protocol_error",
6880
- runId,
6881
- recoverable: false,
6882
- errorDetail: detail
6883
- };
6957
+ const catalog = await this.controller.listModels();
6958
+ const byId = new Map(catalog.entries.map((entry) => [entry.id, entry]));
6959
+ const aliases = catalog.byokProviderAliases;
6960
+ let baseEntry;
6961
+ let explicitHandle;
6962
+ let targetHandle;
6963
+ if (input.modelId !== undefined) {
6964
+ baseEntry = byId.get(input.modelId);
6965
+ explicitHandle = input.modelHandle;
6966
+ targetHandle = baseEntry?.handle ?? toBaseModelHandle(input.modelHandle, aliases);
6967
+ } else if (input.modelHandle !== undefined) {
6968
+ explicitHandle = input.modelHandle;
6969
+ targetHandle = toBaseModelHandle(input.modelHandle, aliases);
6970
+ } else if (input.model !== undefined) {
6971
+ baseEntry = byId.get(input.model);
6972
+ if (baseEntry) {
6973
+ targetHandle = baseEntry.handle;
6974
+ } else {
6975
+ explicitHandle = input.model;
6976
+ targetHandle = toBaseModelHandle(input.model, aliases);
6884
6977
  }
6885
- const toolName = (typeof toolCall.name === "string" ? toolCall.name : undefined) ?? (typeof fn?.name === "string" ? fn.name : undefined) ?? "?";
6886
- const { input, raw } = toolInputFromArguments(toolCall.arguments ?? fn?.arguments);
6887
- return {
6888
- type: "tool_call",
6889
- toolCallId,
6890
- toolName,
6891
- toolInput: input,
6892
- rawArguments: raw,
6893
- uuid,
6894
- runId
6895
- };
6978
+ } else {
6979
+ explicitHandle = this._model || undefined;
6980
+ targetHandle = toBaseModelHandle(this._model || undefined, aliases);
6896
6981
  }
6897
- if (messageType === "tool_return_message") {
6898
- const toolReturn = firstToolReturn(delta) ?? delta;
6899
- const toolCallId = (typeof delta.tool_call_id === "string" ? delta.tool_call_id : undefined) ?? (typeof toolReturn.tool_call_id === "string" ? toolReturn.tool_call_id : undefined);
6900
- if (!toolCallId)
6901
- return null;
6902
- const content = extractTextFromContent(delta.tool_return ?? toolReturn.tool_return ?? toolReturn.content) ?? "";
6903
- const status = typeof delta.status === "string" ? delta.status : toolReturn.status;
6904
- return {
6905
- type: "tool_result",
6906
- toolCallId,
6907
- content,
6908
- isError: status === "error",
6909
- uuid,
6910
- runId
6911
- };
6982
+ if (!targetHandle) {
6983
+ throw new Error("reasoningEffort requires a current model or explicit model/modelId/modelHandle.");
6912
6984
  }
6913
- if (messageType === "error_message" || messageType === "loop_error") {
6914
- const detail = (typeof delta.detail === "string" ? delta.detail : undefined) ?? (typeof delta.message === "string" ? delta.message : undefined) ?? `${this.label} turn failed`;
6915
- const stopReason = (typeof delta.stop_reason === "string" ? delta.stop_reason : undefined) ?? (typeof delta.error_type === "string" ? delta.error_type : undefined) ?? "error";
6916
- const approvalConflict = isApprovalConflictSignal({
6917
- detail,
6918
- message: typeof delta.message === "string" ? delta.message : undefined,
6919
- stopReason
6920
- });
6921
- return {
6922
- type: "error",
6923
- message: detail,
6924
- errorCode: approvalConflict ? "approval_conflict" : toSdkErrorCode(stopReason),
6925
- approvalConflict: approvalConflict || undefined,
6926
- recoverable: approvalConflict ? true : false,
6927
- errorDetail: detail,
6928
- stopReason,
6929
- runId
6930
- };
6985
+ const candidates = catalog.entries.filter((entry) => entry.handle === targetHandle || entry.handle === explicitHandle);
6986
+ if (candidates.length === 0) {
6987
+ throw new Error(`reasoningEffort requires a model from listModels(); no catalog entry found for ${targetHandle}.`);
6931
6988
  }
6932
- if (messageType === "retry") {
6933
- return {
6934
- type: "retry",
6935
- reason: typeof delta.reason === "string" ? delta.reason : "error",
6936
- attempt: typeof delta.attempt === "number" ? delta.attempt : 0,
6937
- maxAttempts: typeof delta.max_attempts === "number" ? delta.max_attempts : 0,
6938
- delayMs: typeof delta.delay_ms === "number" ? delta.delay_ms : 0,
6939
- runId
6940
- };
6989
+ const contextWindow = getContextWindow(baseEntry?.updateArgs) ?? getContextWindow(this._modelSettings);
6990
+ const scopedCandidates = sameContextCandidates(candidates, contextWindow);
6991
+ const matchingEntry = scopedCandidates.find((entry) => getReasoningEffort(entry) === input.reasoningEffort) ?? candidates.find((entry) => getReasoningEffort(entry) === input.reasoningEffort);
6992
+ if (!matchingEntry) {
6993
+ throw new Error(`No ${input.reasoningEffort} reasoning tier found for model ${targetHandle}.`);
6941
6994
  }
6942
- if (messageType === "stop_reason" || messageType === "ping") {
6943
- return null;
6995
+ const payload = { model_id: matchingEntry.id };
6996
+ if (explicitHandle !== undefined) {
6997
+ payload.model_handle = explicitHandle;
6944
6998
  }
6945
- return {
6946
- type: "stream_event",
6947
- event: delta,
6948
- uuid
6949
- };
6950
- }
6951
- resultFromTurn(turn, tracker) {
6952
- const stopReason = turn.stopReason ?? (turn.success === false ? "error" : undefined);
6953
- const approvalConflict = isApprovalConflictSignal({
6954
- detail: turn.detail,
6955
- stopReason
6956
- });
6957
- const success = turn.success !== undefined ? turn.success && !approvalConflict && !FAILURE_STOP_REASONS.has(stopReason ?? "") : !approvalConflict && !FAILURE_STOP_REASONS.has(stopReason ?? "");
6958
- const errorCode = approvalConflict ? "approval_conflict" : turn.errorCode ?? toSdkErrorCode(stopReason);
6959
- return {
6960
- type: "result",
6961
- success,
6962
- result: success ? tracker?.assistantText || undefined : undefined,
6963
- error: success ? undefined : errorCode ?? stopReason ?? "error",
6964
- errorCode: success ? undefined : errorCode ?? "error",
6965
- approvalConflict: approvalConflict || undefined,
6966
- recoverable: approvalConflict ? true : success ? undefined : false,
6967
- errorDetail: success ? undefined : turn.detail,
6968
- stopReason,
6969
- durationMs: Date.now() - (tracker?.startedAt || this.activeTurnStartedAt),
6970
- conversationId: turn.runtime.conversation_id,
6971
- runIds: turn.runIds.length > 0 ? turn.runIds : undefined
6972
- };
6999
+ return payload;
6973
7000
  }
6974
- enqueue(message) {
6975
- const resolver = this.streamResolvers.shift();
6976
- if (resolver) {
6977
- resolver(message);
7001
+ async applyPostInitializeOptions() {
7002
+ if (!this.controller || !this.runtime)
6978
7003
  return;
7004
+ const options = this.currentOptions();
7005
+ if (this.shouldEnableMemfs(options)) {
7006
+ const response = await this.controller.request("enable_memfs", this.enableMemfsBody(), {
7007
+ predicate: (message) => message.type === "enable_memfs_response",
7008
+ timeoutMs: 180000
7009
+ });
7010
+ ensureSuccess(response, "Failed to enable memfs");
7011
+ }
7012
+ const dreamingSettings = resolveDreamingSettings(options.dreaming);
7013
+ if (dreamingSettings) {
7014
+ const response = await this.controller.request("set_reflection_settings", {
7015
+ runtime: this.runtime,
7016
+ settings: dreamingSettings,
7017
+ scope: "both"
7018
+ }, { predicate: (message) => message.type === "set_reflection_settings_response" });
7019
+ ensureSuccess(response, "Failed to update dreaming settings");
7020
+ }
7021
+ if (this.mode.kind !== "session")
7022
+ return;
7023
+ if (this.mode.options.model !== undefined || this.mode.options.reasoningEffort !== undefined) {
7024
+ await this.applyModelUpdate({
7025
+ ...this.mode.options.model !== undefined ? { model: this.mode.options.model } : {},
7026
+ ...this.mode.options.reasoningEffort !== undefined ? { reasoningEffort: this.mode.options.reasoningEffort } : {}
7027
+ });
6979
7028
  }
6980
- this.streamQueue.push(message);
6981
- }
6982
- nextMessage() {
6983
- const next = this.streamQueue.shift();
6984
- if (next)
6985
- return Promise.resolve(next);
6986
- if (this.closed)
6987
- return Promise.resolve(null);
6988
- return new Promise((resolve) => {
6989
- this.streamResolvers.push(resolve);
6990
- });
6991
7029
  }
6992
- resolveAll(value) {
6993
- for (const resolve of this.streamResolvers.splice(0)) {
6994
- resolve(value);
7030
+ emitDeviceStatus(status) {
7031
+ for (const listener of [...this.deviceStatusListeners]) {
7032
+ try {
7033
+ listener(status);
7034
+ } catch {}
6995
7035
  }
6996
7036
  }
6997
7037
  }
@@ -7892,13 +7932,58 @@ class RemoteEnvironmentClient {
7892
7932
  }
7893
7933
  }
7894
7934
 
7935
+ // src/cloud-sandbox.ts
7936
+ var MIN_TTL_MINUTES = 1;
7937
+ var MAX_TTL_MINUTES = 60;
7938
+ var MAX_GITHUB_REPOSITORIES = 10;
7939
+ var GITHUB_OWNER_PATTERN = /^[A-Za-z0-9-]+$/;
7940
+ var GITHUB_REPOSITORY_PATTERN = /^[A-Za-z0-9._-]+$/;
7941
+ function validatePositiveInteger(value, name) {
7942
+ if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {
7943
+ throw new Error(`Invalid ${name}. Expected a positive integer.`);
7944
+ }
7945
+ }
7946
+ function validateCloudSandboxOptions(options, name) {
7947
+ if (options === undefined)
7948
+ return;
7949
+ if (options === null || typeof options !== "object" || Array.isArray(options)) {
7950
+ throw new Error(`Invalid ${name}. Expected an object.`);
7951
+ }
7952
+ if (options.ttlMinutes !== undefined && (!Number.isInteger(options.ttlMinutes) || options.ttlMinutes < MIN_TTL_MINUTES || options.ttlMinutes > MAX_TTL_MINUTES)) {
7953
+ throw new Error(`Invalid ${name}.ttlMinutes. Expected an integer between ${MIN_TTL_MINUTES} and ${MAX_TTL_MINUTES}.`);
7954
+ }
7955
+ validatePositiveInteger(options.readyTimeoutMs, `${name}.readyTimeoutMs`);
7956
+ validatePositiveInteger(options.readyPollIntervalMs, `${name}.readyPollIntervalMs`);
7957
+ validatePositiveInteger(options.refreshIntervalMs, `${name}.refreshIntervalMs`);
7958
+ if (options.githubRepositories !== undefined) {
7959
+ if (!Array.isArray(options.githubRepositories)) {
7960
+ throw new Error(`Invalid ${name}.githubRepositories. Expected an array.`);
7961
+ }
7962
+ if (options.githubRepositories.length > MAX_GITHUB_REPOSITORIES) {
7963
+ throw new Error(`Invalid ${name}.githubRepositories. Expected at most ${MAX_GITHUB_REPOSITORIES} repositories.`);
7964
+ }
7965
+ for (const [index, repository] of options.githubRepositories.entries()) {
7966
+ if (repository === null || typeof repository !== "object" || Array.isArray(repository)) {
7967
+ throw new Error(`Invalid ${name}.githubRepositories[${index}]. Expected an object.`);
7968
+ }
7969
+ if (typeof repository.owner !== "string" || !GITHUB_OWNER_PATTERN.test(repository.owner)) {
7970
+ throw new Error(`Invalid ${name}.githubRepositories[${index}].owner.`);
7971
+ }
7972
+ if (typeof repository.repo !== "string" || !GITHUB_REPOSITORY_PATTERN.test(repository.repo)) {
7973
+ throw new Error(`Invalid ${name}.githubRepositories[${index}].repo.`);
7974
+ }
7975
+ }
7976
+ }
7977
+ if (options.terminateOnClose !== undefined && typeof options.terminateOnClose !== "boolean") {
7978
+ throw new Error(`Invalid ${name}.terminateOnClose. Expected a boolean.`);
7979
+ }
7980
+ }
7981
+
7895
7982
  // src/cloud-session.ts
7896
7983
  var DEFAULT_CLOUD_API_BASE_URL3 = "https://api.letta.com";
7897
7984
  var DEFAULT_TURN_TIMEOUT_MS = 120000;
7898
7985
  var DEFAULT_PING_INTERVAL_MS = 30000;
7899
7986
  var DEFAULT_SANDBOX_TTL_MINUTES = 5;
7900
- var MIN_SANDBOX_TTL_MINUTES = 1;
7901
- var MAX_SANDBOX_TTL_MINUTES = 60;
7902
7987
  var DEFAULT_SANDBOX_READY_TIMEOUT_MS = 120000;
7903
7988
  var DEFAULT_SANDBOX_READY_POLL_INTERVAL_MS = 1000;
7904
7989
  var DEFAULT_REPOSITORY_ATTACH_TIMEOUT_MS = 1e4;
@@ -8009,34 +8094,13 @@ function assertOkResponse2(response, body, action, url) {
8009
8094
  throw new Error(parts.join(" — "));
8010
8095
  }
8011
8096
  }
8012
- function validatePositiveInteger(value, name) {
8097
+ function validatePositiveInteger2(value, name) {
8013
8098
  if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {
8014
8099
  throw new Error(`Invalid ${name}. Expected a positive integer.`);
8015
8100
  }
8016
8101
  }
8017
- function validateIntegerRange(value, name, min, max) {
8018
- if (value === undefined)
8019
- return;
8020
- if (!Number.isInteger(value) || value < min || value > max) {
8021
- throw new Error(`Invalid ${name}. Expected an integer between ${min} and ${max}.`);
8022
- }
8023
- }
8024
- function validateCloudSandboxOptions(options, name) {
8025
- if (options === undefined)
8026
- return;
8027
- if (options === null || typeof options !== "object" || Array.isArray(options)) {
8028
- throw new Error(`Invalid ${name}. Expected an object.`);
8029
- }
8030
- validateIntegerRange(options.ttlMinutes, `${name}.ttlMinutes`, MIN_SANDBOX_TTL_MINUTES, MAX_SANDBOX_TTL_MINUTES);
8031
- validatePositiveInteger(options.readyTimeoutMs, `${name}.readyTimeoutMs`);
8032
- validatePositiveInteger(options.readyPollIntervalMs, `${name}.readyPollIntervalMs`);
8033
- validatePositiveInteger(options.refreshIntervalMs, `${name}.refreshIntervalMs`);
8034
- if (options.terminateOnClose !== undefined && typeof options.terminateOnClose !== "boolean") {
8035
- throw new Error(`Invalid ${name}.terminateOnClose. Expected a boolean.`);
8036
- }
8037
- }
8038
8102
  function validateCloudClientOptions(options) {
8039
- validatePositiveInteger(options.requestTimeoutMs, "requestTimeoutMs");
8103
+ validatePositiveInteger2(options.requestTimeoutMs, "requestTimeoutMs");
8040
8104
  validateCloudSandboxOptions(options.sandbox, "sandbox");
8041
8105
  if (options.environment !== undefined && options.sandbox !== undefined) {
8042
8106
  throw new Error("Letta Cloud sessions cannot specify both environment and sandbox options.");
@@ -8639,10 +8703,15 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8639
8703
  async createManagedSandbox(agentId, conversationId) {
8640
8704
  const fetchImpl = getFetch3(this.cloudOptions.fetch);
8641
8705
  const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
8706
+ const sandboxOptions = this.resolvedSandboxOptions();
8707
+ const githubRepositories = sandboxOptions.githubRepositories;
8642
8708
  const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(agentId)}/sandboxes`, {
8643
8709
  method: "POST",
8644
8710
  headers: cloudHeaders2(this.cloudOptions),
8645
- body: JSON.stringify(conversationId ? { conversationId } : {})
8711
+ body: JSON.stringify({
8712
+ ...conversationId ? { conversationId } : {},
8713
+ ...githubRepositories && githubRepositories.length > 0 ? { githubRepositories } : {}
8714
+ })
8646
8715
  });
8647
8716
  const body = await parseJsonResponse3(response);
8648
8717
  assertOkResponse2(response, body, "Cloud create managed sandbox", `${baseUrl}/v1/agents/${encodeURIComponent(agentId)}/sandboxes`);
@@ -8653,7 +8722,6 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8653
8722
  if (responseConversationId !== null && responseConversationId !== conversationId) {
8654
8723
  throw new Error(`Cloud managed sandbox response conversation mismatch: expected ${conversationId ?? "none"}, got ${responseConversationId}.`);
8655
8724
  }
8656
- const sandboxOptions = this.resolvedSandboxOptions();
8657
8725
  const ttlMinutes = sandboxOptions.ttlMinutes ?? DEFAULT_SANDBOX_TTL_MINUTES;
8658
8726
  const readyTimeoutMs = sandboxOptions.readyTimeoutMs ?? DEFAULT_SANDBOX_READY_TIMEOUT_MS;
8659
8727
  const readyPollIntervalMs = sandboxOptions.readyPollIntervalMs ?? DEFAULT_SANDBOX_READY_POLL_INTERVAL_MS;
@@ -9419,4 +9487,4 @@ export {
9419
9487
  CloudManagedSandboxExpiredError
9420
9488
  };
9421
9489
 
9422
- //# debugId=EACEDA2AA17A075B64756E2164756E21
9490
+ //# debugId=0186899B952456A764756E2164756E21