@letta-ai/letta-agent-sdk 0.8.79 → 0.8.81

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.
@@ -9481,18 +9481,39 @@ function onceSocketEvent(socket, type, listener) {
9481
9481
  });
9482
9482
  return detach;
9483
9483
  }
9484
- function waitForSocketOpen(socket) {
9484
+ function waitForSocketOpen(socket, timeoutMs) {
9485
9485
  if (socket.readyState === WEBSOCKET_OPEN_STATE) {
9486
9486
  return Promise.resolve();
9487
9487
  }
9488
- return new Promise((resolve, reject) => {
9488
+ return new Promise((resolvePromise, rejectPromise) => {
9489
+ let settled = false;
9490
+ const resolve = () => {
9491
+ if (settled)
9492
+ return;
9493
+ settled = true;
9494
+ resolvePromise();
9495
+ };
9496
+ const reject = (error) => {
9497
+ if (settled)
9498
+ return;
9499
+ settled = true;
9500
+ rejectPromise(error);
9501
+ };
9489
9502
  let detachOpen = () => {};
9490
9503
  let detachError = () => {};
9504
+ let detachClose = () => {};
9491
9505
  let detachResponse = () => {};
9492
9506
  let detachBody = () => {};
9507
+ let upgradeRejected = false;
9508
+ const timer = timeoutMs > 0 ? setTimeout(() => {
9509
+ cleanup();
9510
+ reject(new Error(`App-server WebSocket failed to open: timed out after ${timeoutMs}ms`));
9511
+ }, timeoutMs) : undefined;
9493
9512
  const cleanup = () => {
9513
+ clearTimeout(timer);
9494
9514
  detachOpen();
9495
9515
  detachError();
9516
+ detachClose();
9496
9517
  detachResponse();
9497
9518
  detachBody();
9498
9519
  };
@@ -9504,6 +9525,7 @@ function waitForSocketOpen(socket) {
9504
9525
  const onResponse = (_request, response) => {
9505
9526
  if (!response)
9506
9527
  return;
9528
+ upgradeRejected = true;
9507
9529
  const request = _request;
9508
9530
  let body = Buffer.alloc(0);
9509
9531
  let finished = false;
@@ -9545,6 +9567,12 @@ function waitForSocketOpen(socket) {
9545
9567
  cleanup();
9546
9568
  reject(new Error(`App-server WebSocket failed to open: ${String(event)}`));
9547
9569
  });
9570
+ detachClose = onceSocketEvent(socket, "close", () => {
9571
+ if (upgradeRejected)
9572
+ return;
9573
+ cleanup();
9574
+ reject(new Error("App-server WebSocket failed to open: closed before opening"));
9575
+ });
9548
9576
  });
9549
9577
  }
9550
9578
  function rawEventData(event) {
@@ -9612,7 +9640,7 @@ class AppServerClient {
9612
9640
  });
9613
9641
  }
9614
9642
  async connect() {
9615
- await waitForSocketOpen(this.socket);
9643
+ await waitForSocketOpen(this.socket, this.requestTimeoutMs);
9616
9644
  return this;
9617
9645
  }
9618
9646
  close() {
@@ -13236,6 +13264,7 @@ function externalToolGroups(tools) {
13236
13264
  return;
13237
13265
  return [
13238
13266
  {
13267
+ capabilities: { external_tool_call_cancel: true },
13239
13268
  tools: tools.map((tool) => ({
13240
13269
  name: tool.name,
13241
13270
  label: tool.label,
@@ -13248,14 +13277,14 @@ function externalToolGroups(tools) {
13248
13277
  var MAX_REMEMBERED_EXTERNAL_TOOL_CALLS = 200;
13249
13278
  function createExternalToolCallHandler(externalTools, fallbackRuntime) {
13250
13279
  const calls = new Map;
13251
- const execute = async (request) => {
13280
+ const execute = async (request, signal) => {
13252
13281
  const tool = externalTools.get(request.tool_name);
13253
13282
  if (!tool) {
13254
13283
  throw new Error(`Unknown external tool: ${request.tool_name}`);
13255
13284
  }
13256
13285
  const runtime = request.runtime ?? fallbackRuntime?.() ?? null;
13257
13286
  const context = runtime ? { toolCallId: request.tool_call_id, agentId: runtime.agent_id, conversationId: runtime.conversation_id } : undefined;
13258
- const result = await tool.execute(request.tool_call_id, request.input, undefined, undefined, context);
13287
+ const result = await tool.execute(request.tool_call_id, request.input, signal, undefined, context);
13259
13288
  return {
13260
13289
  content: result.content.map((part) => ({
13261
13290
  type: part.type,
@@ -13266,15 +13295,15 @@ function createExternalToolCallHandler(externalTools, fallbackRuntime) {
13266
13295
  ...result.isError === true ? { is_error: true } : {}
13267
13296
  };
13268
13297
  };
13269
- return (request) => {
13298
+ return (request, signal) => {
13270
13299
  const requestId = request.request_id;
13271
13300
  if (typeof requestId !== "string" || requestId.length === 0) {
13272
- return execute(request);
13301
+ return execute(request, signal);
13273
13302
  }
13274
13303
  const existing = calls.get(requestId);
13275
13304
  if (existing)
13276
13305
  return existing;
13277
- const call = execute(request);
13306
+ const call = execute(request, signal);
13278
13307
  calls.set(requestId, call);
13279
13308
  while (calls.size > MAX_REMEMBERED_EXTERNAL_TOOL_CALLS) {
13280
13309
  const oldest = calls.keys().next().value;
@@ -13285,6 +13314,49 @@ function createExternalToolCallHandler(externalTools, fallbackRuntime) {
13285
13314
  return call;
13286
13315
  };
13287
13316
  }
13317
+ function registerExternalToolCallHandler(client, handler) {
13318
+ const pending = new Map;
13319
+ const completed = new Set;
13320
+ const remove = client.onMessage((raw, channel) => {
13321
+ if (channel !== "control")
13322
+ return;
13323
+ const message = raw;
13324
+ const requestId = message.request_id;
13325
+ if (typeof requestId !== "string")
13326
+ return;
13327
+ if (message.type === "external_tool_call_cancel") {
13328
+ const call = pending.get(requestId);
13329
+ if (!call)
13330
+ return;
13331
+ call.finish({ error: "cancelled" });
13332
+ call.controller.abort(message.reason);
13333
+ return;
13334
+ }
13335
+ if (message.type !== "external_tool_call_request" || pending.has(requestId) || completed.has(requestId))
13336
+ return;
13337
+ const controller = new AbortController;
13338
+ const finish = (response) => {
13339
+ if (!pending.delete(requestId))
13340
+ return;
13341
+ completed.add(requestId);
13342
+ if (completed.size > MAX_REMEMBERED_EXTERNAL_TOOL_CALLS)
13343
+ completed.delete(completed.values().next().value);
13344
+ client.send({ type: "external_tool_call_response", request_id: requestId, ...response });
13345
+ };
13346
+ pending.set(requestId, { controller, finish });
13347
+ try {
13348
+ Promise.resolve(handler(raw, controller.signal)).then((result) => finish({ result }), (error) => finish({ error: error instanceof Error ? error.message : String(error) }));
13349
+ } catch (error) {
13350
+ finish({ error: error instanceof Error ? error.message : String(error) });
13351
+ }
13352
+ });
13353
+ return () => {
13354
+ remove();
13355
+ for (const call of pending.values())
13356
+ call.controller.abort();
13357
+ pending.clear();
13358
+ };
13359
+ }
13288
13360
 
13289
13361
  // src/runtime-tool-policy.ts
13290
13362
  var RUNTIME_TOOL_POLICY_CAPABILITY = "runtime_tool_policy";
@@ -15109,7 +15181,7 @@ class AppServerSession extends RemoteClientSessionCore {
15109
15181
  getOptions: () => this.currentOptions()
15110
15182
  });
15111
15183
  if (this.externalTools.size > 0 || this.inheritedTools) {
15112
- this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools, () => this.runtime));
15184
+ this.removeExternalToolHandler = registerExternalToolCallHandler(client, createExternalToolCallHandler(this.externalTools, () => this.runtime));
15113
15185
  }
15114
15186
  try {
15115
15187
  await client.connect();
@@ -16214,7 +16286,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
16214
16286
  getOptions: () => this.currentOptions()
16215
16287
  });
16216
16288
  if (this.externalTools.size > 0) {
16217
- this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools, () => this.runtime));
16289
+ this.removeExternalToolHandler = registerExternalToolCallHandler(client, createExternalToolCallHandler(this.externalTools, () => this.runtime));
16218
16290
  }
16219
16291
  }
16220
16292
  cleanupTransportHandlers() {
@@ -16972,12 +17044,12 @@ class ToolRegistry {
16972
17044
  ...this.options.WebSocket ? { WebSocket: this.options.WebSocket } : {},
16973
17045
  ...this.options.requestTimeoutMs !== undefined ? { requestTimeoutMs: this.options.requestTimeoutMs } : {}
16974
17046
  }));
16975
- client.onExternalToolCall(async (request) => {
17047
+ registerExternalToolCallHandler(client, async (request, signal) => {
16976
17048
  const runtime = request.runtime;
16977
17049
  const entry = runtime && [...this.entries].find((candidate) => candidate.runtimes.some((r) => runtimeKey(r) === runtimeKey(runtime)));
16978
17050
  if (!entry)
16979
17051
  throw new Error(`No tools registered for conversation ${runtime?.conversation_id}`);
16980
- return entry.call(request);
17052
+ return entry.call(request, signal);
16981
17053
  });
16982
17054
  try {
16983
17055
  await client.connect();
@@ -18278,4 +18350,4 @@ export {
18278
18350
  CloudManagedSandboxExpiredError
18279
18351
  };
18280
18352
 
18281
- //# debugId=6F04BC66F4049A5B64756E2164756E21
18353
+ //# debugId=56DE4B3DCF03FA0964756E2164756E21