@letta-ai/letta-agent-sdk 0.3.3 → 0.5.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/AGENTS.md +0 -3
- package/README.md +8 -1
- package/dist/app-server-management.d.ts +3 -48
- package/dist/app-server-management.d.ts.map +1 -1
- package/dist/app-server-session.d.ts +0 -6
- package/dist/app-server-session.d.ts.map +1 -1
- package/dist/client-base.d.ts +7 -15
- package/dist/client-base.d.ts.map +1 -1
- package/dist/client-entry.js +428 -486
- package/dist/client-entry.js.map +13 -12
- package/dist/client.d.ts +3 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/cloud-session.d.ts +2 -0
- package/dist/cloud-session.d.ts.map +1 -1
- package/dist/cloud-status-transport.d.ts +53 -0
- package/dist/cloud-status-transport.d.ts.map +1 -0
- package/dist/index.d.ts +7 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +911 -1993
- package/dist/index.js.map +18 -18
- package/dist/local-app-server-session.d.ts +1 -1
- package/dist/local-app-server-session.d.ts.map +1 -1
- package/dist/local-app-server.d.ts +11 -0
- package/dist/local-app-server.d.ts.map +1 -1
- package/dist/management.d.ts +0 -7
- package/dist/management.d.ts.map +1 -1
- package/dist/remote-session-protocol.d.ts +2 -0
- package/dist/remote-session-protocol.d.ts.map +1 -1
- package/dist/remote-turn-coordinator.d.ts.map +1 -1
- package/dist/types.d.ts +65 -66
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/app-server-management.ts +20 -256
- package/src/app-server-session.ts +0 -32
- package/src/client-base.ts +47 -73
- package/src/client.ts +31 -70
- package/src/cloud-session.ts +113 -287
- package/src/cloud-status-transport.ts +305 -0
- package/src/index.ts +11 -29
- package/src/local-app-server-session.ts +13 -3
- package/src/local-app-server.ts +97 -3
- package/src/management.ts +0 -7
- package/src/remote-session-protocol.ts +18 -0
- package/src/remote-turn-coordinator.ts +20 -2
- package/src/types.ts +72 -111
- package/src/validation.ts +21 -6
- package/dist/protocol.d.ts +0 -205
- package/dist/protocol.d.ts.map +0 -1
- package/dist/session.d.ts +0 -155
- package/dist/session.d.ts.map +0 -1
- package/dist/transport.d.ts +0 -53
- package/dist/transport.d.ts.map +0 -1
- package/src/protocol.ts +0 -249
- package/src/session.ts +0 -1638
- package/src/transport.ts +0 -484
package/dist/client-entry.js
CHANGED
|
@@ -244,6 +244,18 @@ class RepositoriesClient {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
// node_modules/@letta-ai/letta-code/dist/app-server-client.js
|
|
247
|
+
function isAppServerInfoResponseMessage(message) {
|
|
248
|
+
if (!message || typeof message !== "object" || Array.isArray(message)) {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
const candidate = message;
|
|
252
|
+
const capabilities = candidate.capabilities;
|
|
253
|
+
if (!capabilities || typeof capabilities !== "object" || Array.isArray(capabilities)) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
const capabilityRecord = capabilities;
|
|
257
|
+
return candidate.type === "app_server_info_response" && typeof candidate.request_id === "string" && candidate.request_id.length > 0 && candidate.success === true && (candidate.backend === "local" || candidate.backend === "api") && typeof candidate.letta_code_version === "string" && typeof candidate.protocol_version === "number" && Number.isInteger(candidate.protocol_version) && typeof capabilityRecord.agent_management === "boolean" && typeof capabilityRecord.conversation_management === "boolean" && typeof capabilityRecord.memory_management === "boolean" && typeof capabilityRecord.runtime_start === "boolean" && typeof capabilityRecord.split_channels === "boolean";
|
|
258
|
+
}
|
|
247
259
|
var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
248
260
|
var WEBSOCKET_OPEN_STATE = 1;
|
|
249
261
|
function getGlobalWebSocket() {
|
|
@@ -263,9 +275,9 @@ function normalizeBaseUrl(url) {
|
|
|
263
275
|
}
|
|
264
276
|
return parsed;
|
|
265
277
|
}
|
|
266
|
-
function
|
|
278
|
+
function resolveAppServerUrl(url) {
|
|
267
279
|
const parsed = normalizeBaseUrl(url);
|
|
268
|
-
parsed.searchParams.
|
|
280
|
+
parsed.searchParams.delete("channel");
|
|
269
281
|
return parsed.toString();
|
|
270
282
|
}
|
|
271
283
|
function attachSocketListener(socket, type, listener) {
|
|
@@ -378,6 +390,7 @@ function streamDeltaErrorMessage(message) {
|
|
|
378
390
|
}
|
|
379
391
|
|
|
380
392
|
class AppServerClient {
|
|
393
|
+
socket;
|
|
381
394
|
control;
|
|
382
395
|
stream;
|
|
383
396
|
requestTimeoutMs;
|
|
@@ -396,26 +409,18 @@ class AppServerClient {
|
|
|
396
409
|
}
|
|
397
410
|
this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
398
411
|
const socketOptions = appServerSocketOptions(options.authToken);
|
|
399
|
-
this.
|
|
400
|
-
this.
|
|
401
|
-
|
|
412
|
+
this.socket = new WebSocket(resolveAppServerUrl(options.url), socketOptions);
|
|
413
|
+
this.control = this.socket;
|
|
414
|
+
this.stream = this.socket;
|
|
415
|
+
attachSocketListener(this.socket, "message", (event) => {
|
|
402
416
|
this.handleMessage(event, "control");
|
|
403
417
|
});
|
|
404
|
-
attachSocketListener(this.
|
|
405
|
-
this.handleMessage(event, "stream");
|
|
406
|
-
});
|
|
407
|
-
attachSocketListener(this.control, "close", (event) => {
|
|
418
|
+
attachSocketListener(this.socket, "close", (event) => {
|
|
408
419
|
this.handleDisconnect("control", event);
|
|
409
420
|
});
|
|
410
|
-
attachSocketListener(this.stream, "close", (event) => {
|
|
411
|
-
this.handleDisconnect("stream", event);
|
|
412
|
-
});
|
|
413
421
|
}
|
|
414
422
|
async connect() {
|
|
415
|
-
await
|
|
416
|
-
waitForSocketOpen(this.control),
|
|
417
|
-
waitForSocketOpen(this.stream)
|
|
418
|
-
]);
|
|
423
|
+
await waitForSocketOpen(this.socket);
|
|
419
424
|
return this;
|
|
420
425
|
}
|
|
421
426
|
close() {
|
|
@@ -423,8 +428,7 @@ class AppServerClient {
|
|
|
423
428
|
return;
|
|
424
429
|
this.explicitlyClosed = true;
|
|
425
430
|
this.rejectAllPending("App-server client closed");
|
|
426
|
-
this.
|
|
427
|
-
this.stream.close();
|
|
431
|
+
this.socket.close();
|
|
428
432
|
}
|
|
429
433
|
onMessage(handler) {
|
|
430
434
|
this.messageHandlers.add(handler);
|
|
@@ -443,10 +447,38 @@ class AppServerClient {
|
|
|
443
447
|
return `${prefix}-${this.nextRequestNumber}`;
|
|
444
448
|
}
|
|
445
449
|
send(command) {
|
|
450
|
+
this.writeCommand(command);
|
|
451
|
+
}
|
|
452
|
+
writeCommand(command) {
|
|
446
453
|
for (const handler of this.sendHandlers) {
|
|
447
454
|
handler(command);
|
|
448
455
|
}
|
|
449
|
-
this.
|
|
456
|
+
this.socket.send(JSON.stringify(command));
|
|
457
|
+
}
|
|
458
|
+
sendRaw(command) {
|
|
459
|
+
this.writeCommand(command);
|
|
460
|
+
}
|
|
461
|
+
requestRaw(command, options) {
|
|
462
|
+
const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;
|
|
463
|
+
return new Promise((resolve, reject) => {
|
|
464
|
+
const timeout = setTimeout(() => {
|
|
465
|
+
this.pending.delete(command.request_id);
|
|
466
|
+
reject(new Error(`Timed out waiting for ${command.request_id}`));
|
|
467
|
+
}, timeoutMs);
|
|
468
|
+
this.pending.set(command.request_id, {
|
|
469
|
+
resolve: (message) => resolve(message),
|
|
470
|
+
reject,
|
|
471
|
+
predicate: options.predicate,
|
|
472
|
+
timeout
|
|
473
|
+
});
|
|
474
|
+
try {
|
|
475
|
+
this.sendRaw(command);
|
|
476
|
+
} catch (error) {
|
|
477
|
+
clearTimeout(timeout);
|
|
478
|
+
this.pending.delete(command.request_id);
|
|
479
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
480
|
+
}
|
|
481
|
+
});
|
|
450
482
|
}
|
|
451
483
|
request(commandOrType, bodyOrOptions = {}, maybeOptions = {}) {
|
|
452
484
|
const isTypeRequest = typeof commandOrType === "string";
|
|
@@ -477,6 +509,15 @@ class AppServerClient {
|
|
|
477
509
|
}
|
|
478
510
|
});
|
|
479
511
|
}
|
|
512
|
+
info(options = {}) {
|
|
513
|
+
return this.request({
|
|
514
|
+
type: "app_server_info",
|
|
515
|
+
request_id: this.nextRequestId("app-server-info")
|
|
516
|
+
}, {
|
|
517
|
+
...options,
|
|
518
|
+
predicate: isAppServerInfoResponseMessage
|
|
519
|
+
});
|
|
520
|
+
}
|
|
480
521
|
runtimeStart(command, options = {}) {
|
|
481
522
|
return this.request({
|
|
482
523
|
type: "runtime_start",
|
|
@@ -696,44 +737,6 @@ function applyUniqueRequestIds(client) {
|
|
|
696
737
|
}
|
|
697
738
|
|
|
698
739
|
// src/app-server-management.ts
|
|
699
|
-
var DEFAULT_IDLE_LINGER_MS = 250;
|
|
700
|
-
var registeredTransportsByUrl = new Map;
|
|
701
|
-
function appServerUrlKey(value) {
|
|
702
|
-
try {
|
|
703
|
-
const url = new URL(value);
|
|
704
|
-
if (url.protocol === "http:")
|
|
705
|
-
url.protocol = "ws:";
|
|
706
|
-
if (url.protocol === "https:")
|
|
707
|
-
url.protocol = "wss:";
|
|
708
|
-
url.hash = "";
|
|
709
|
-
url.searchParams.delete("channel");
|
|
710
|
-
return url.toString();
|
|
711
|
-
} catch {
|
|
712
|
-
return value;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
function registerManagementTransport(url, transport) {
|
|
716
|
-
const key = appServerUrlKey(url);
|
|
717
|
-
const registration = { transport };
|
|
718
|
-
const transports = registeredTransportsByUrl.get(key) ?? new Set;
|
|
719
|
-
transports.add(registration);
|
|
720
|
-
registeredTransportsByUrl.set(key, transports);
|
|
721
|
-
return () => {
|
|
722
|
-
transports.delete(registration);
|
|
723
|
-
if (transports.size === 0) {
|
|
724
|
-
registeredTransportsByUrl.delete(key);
|
|
725
|
-
}
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
async function releaseAppServerManagementConnections(url) {
|
|
729
|
-
const key = appServerUrlKey(url);
|
|
730
|
-
while (true) {
|
|
731
|
-
const transports = [...registeredTransportsByUrl.get(key) ?? []];
|
|
732
|
-
if (transports.length === 0)
|
|
733
|
-
return;
|
|
734
|
-
await Promise.all(transports.map(({ transport }) => transport.releaseIdleConnection()));
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
740
|
function ensureResponse(response, value, fallback) {
|
|
738
741
|
if (!response.success || value == null) {
|
|
739
742
|
throw new Error(response.error ?? fallback);
|
|
@@ -770,15 +773,9 @@ function stringRecord(value) {
|
|
|
770
773
|
class AppServerManagementTransport {
|
|
771
774
|
options;
|
|
772
775
|
connectionPromise = null;
|
|
773
|
-
releasePromise = null;
|
|
774
776
|
closingConnections = new Set;
|
|
775
|
-
inFlightRequests = 0;
|
|
776
|
-
idleWaiters = new Set;
|
|
777
|
-
idleTimer = null;
|
|
778
|
-
idleLingerMs;
|
|
779
777
|
constructor(options) {
|
|
780
778
|
this.options = options;
|
|
781
|
-
this.idleLingerMs = options.idleLingerMs ?? DEFAULT_IDLE_LINGER_MS;
|
|
782
779
|
}
|
|
783
780
|
async listAgents(query) {
|
|
784
781
|
const response = await this.request("agent_list", { query }, "agent_list_response");
|
|
@@ -845,73 +842,20 @@ class AppServerManagementTransport {
|
|
|
845
842
|
}
|
|
846
843
|
return { messages: response.messages };
|
|
847
844
|
}
|
|
848
|
-
releaseIdleConnection() {
|
|
849
|
-
this.clearIdleTimer();
|
|
850
|
-
if (this.releasePromise)
|
|
851
|
-
return this.releasePromise;
|
|
852
|
-
const release = this.releaseConnectionWhenIdle();
|
|
853
|
-
this.releasePromise = release;
|
|
854
|
-
release.then(() => {
|
|
855
|
-
if (this.releasePromise === release) {
|
|
856
|
-
this.releasePromise = null;
|
|
857
|
-
}
|
|
858
|
-
}, () => {
|
|
859
|
-
if (this.releasePromise === release) {
|
|
860
|
-
this.releasePromise = null;
|
|
861
|
-
}
|
|
862
|
-
});
|
|
863
|
-
return release;
|
|
864
|
-
}
|
|
865
845
|
async request(type, body, responseType) {
|
|
866
|
-
if (this.releasePromise) {
|
|
867
|
-
await this.releasePromise;
|
|
868
|
-
}
|
|
869
846
|
if (this.closingConnections.size > 0) {
|
|
870
847
|
await Promise.all([...this.closingConnections]);
|
|
871
848
|
}
|
|
872
|
-
this.
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
predicate: (message) => message.type === responseType
|
|
883
|
-
});
|
|
884
|
-
return response;
|
|
885
|
-
} finally {
|
|
886
|
-
this.inFlightRequests -= 1;
|
|
887
|
-
if (this.inFlightRequests === 0) {
|
|
888
|
-
const waiters = [...this.idleWaiters];
|
|
889
|
-
this.idleWaiters.clear();
|
|
890
|
-
for (const resolve of waiters)
|
|
891
|
-
resolve();
|
|
892
|
-
if (!this.releasePromise) {
|
|
893
|
-
this.scheduleIdleRelease();
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
async releaseConnectionWhenIdle() {
|
|
899
|
-
if (this.inFlightRequests > 0) {
|
|
900
|
-
await new Promise((resolve) => {
|
|
901
|
-
this.idleWaiters.add(resolve);
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
this.clearIdleTimer();
|
|
905
|
-
const promise = this.connectionPromise;
|
|
906
|
-
try {
|
|
907
|
-
if (promise) {
|
|
908
|
-
this.connectionPromise = null;
|
|
909
|
-
await this.trackClosingConnection(await promise);
|
|
910
|
-
}
|
|
911
|
-
if (this.closingConnections.size > 0) {
|
|
912
|
-
await Promise.all([...this.closingConnections]);
|
|
913
|
-
}
|
|
914
|
-
} catch {}
|
|
849
|
+
const { client } = await this.acquireConnection();
|
|
850
|
+
const command = {
|
|
851
|
+
type,
|
|
852
|
+
request_id: client.nextRequestId(type),
|
|
853
|
+
...body
|
|
854
|
+
};
|
|
855
|
+
const response = await client.request(command, {
|
|
856
|
+
predicate: (message) => message.type === responseType
|
|
857
|
+
});
|
|
858
|
+
return response;
|
|
915
859
|
}
|
|
916
860
|
acquireConnection() {
|
|
917
861
|
if (this.connectionPromise)
|
|
@@ -936,7 +880,6 @@ class AppServerManagementTransport {
|
|
|
936
880
|
if (!url) {
|
|
937
881
|
throw new Error("App-server management requires a url or connect hook.");
|
|
938
882
|
}
|
|
939
|
-
const unregister = registerManagementTransport(url, this);
|
|
940
883
|
let client = null;
|
|
941
884
|
try {
|
|
942
885
|
client = applyUniqueRequestIds(createAppServerClient({
|
|
@@ -951,29 +894,23 @@ class AppServerManagementTransport {
|
|
|
951
894
|
} catch (error) {
|
|
952
895
|
try {
|
|
953
896
|
if (client) {
|
|
954
|
-
const controlClosed = waitForSocketClose(client.control);
|
|
955
897
|
client.close();
|
|
956
898
|
ownedConnection?.close();
|
|
957
|
-
await controlClosed;
|
|
958
899
|
} else {
|
|
959
900
|
ownedConnection?.close();
|
|
960
901
|
}
|
|
961
|
-
} catch {}
|
|
962
|
-
unregister();
|
|
963
|
-
}
|
|
902
|
+
} catch {}
|
|
964
903
|
throw error;
|
|
965
904
|
}
|
|
966
905
|
return {
|
|
967
906
|
client,
|
|
968
907
|
ownedConnection,
|
|
969
|
-
detachDisconnect: () => {}
|
|
970
|
-
unregister
|
|
908
|
+
detachDisconnect: () => {}
|
|
971
909
|
};
|
|
972
910
|
}
|
|
973
911
|
discardConnection(promise, connection) {
|
|
974
912
|
if (this.connectionPromise === promise) {
|
|
975
913
|
this.connectionPromise = null;
|
|
976
|
-
this.clearIdleTimer();
|
|
977
914
|
}
|
|
978
915
|
this.trackClosingConnection(connection);
|
|
979
916
|
}
|
|
@@ -983,67 +920,11 @@ class AppServerManagementTransport {
|
|
|
983
920
|
closing.then(() => this.closingConnections.delete(closing), () => this.closingConnections.delete(closing));
|
|
984
921
|
return closing;
|
|
985
922
|
}
|
|
986
|
-
scheduleIdleRelease() {
|
|
987
|
-
if (!this.connectionPromise)
|
|
988
|
-
return;
|
|
989
|
-
this.clearIdleTimer();
|
|
990
|
-
const timer = setTimeout(() => {
|
|
991
|
-
this.idleTimer = null;
|
|
992
|
-
this.releaseIdleConnection();
|
|
993
|
-
}, this.idleLingerMs);
|
|
994
|
-
this.idleTimer = timer;
|
|
995
|
-
timer.unref?.();
|
|
996
|
-
}
|
|
997
|
-
clearIdleTimer() {
|
|
998
|
-
if (this.idleTimer === null)
|
|
999
|
-
return;
|
|
1000
|
-
clearTimeout(this.idleTimer);
|
|
1001
|
-
this.idleTimer = null;
|
|
1002
|
-
}
|
|
1003
923
|
}
|
|
1004
924
|
async function closeConnection(connection) {
|
|
1005
925
|
connection.detachDisconnect();
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
connection.client.close();
|
|
1009
|
-
connection.ownedConnection?.close();
|
|
1010
|
-
await controlClosed;
|
|
1011
|
-
} finally {
|
|
1012
|
-
connection.unregister();
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
function waitForSocketClose(socket) {
|
|
1016
|
-
if (socket.readyState === 3)
|
|
1017
|
-
return Promise.resolve();
|
|
1018
|
-
return new Promise((resolve) => {
|
|
1019
|
-
let settled = false;
|
|
1020
|
-
let detach = () => {};
|
|
1021
|
-
const finish = () => {
|
|
1022
|
-
if (settled)
|
|
1023
|
-
return;
|
|
1024
|
-
settled = true;
|
|
1025
|
-
clearTimeout(timeout);
|
|
1026
|
-
detach();
|
|
1027
|
-
resolve();
|
|
1028
|
-
};
|
|
1029
|
-
if (socket.addEventListener) {
|
|
1030
|
-
socket.addEventListener("close", finish);
|
|
1031
|
-
detach = () => socket.removeEventListener?.("close", finish);
|
|
1032
|
-
} else if (socket.once) {
|
|
1033
|
-
socket.once("close", finish);
|
|
1034
|
-
detach = () => socket.off?.("close", finish);
|
|
1035
|
-
} else if (socket.on) {
|
|
1036
|
-
socket.on("close", finish);
|
|
1037
|
-
detach = () => socket.off?.("close", finish);
|
|
1038
|
-
} else {
|
|
1039
|
-
resolve();
|
|
1040
|
-
return;
|
|
1041
|
-
}
|
|
1042
|
-
const timeout = setTimeout(finish, 1000);
|
|
1043
|
-
timeout.unref?.();
|
|
1044
|
-
if (socket.readyState === 3)
|
|
1045
|
-
finish();
|
|
1046
|
-
});
|
|
926
|
+
connection.client.close();
|
|
927
|
+
connection.ownedConnection?.close();
|
|
1047
928
|
}
|
|
1048
929
|
|
|
1049
930
|
// node_modules/@letta-ai/letta-code/dist/agent-presets.js
|
|
@@ -5950,6 +5831,12 @@ function streamDeltaMessageType2(delta) {
|
|
|
5950
5831
|
function streamDeltaRunId2(delta) {
|
|
5951
5832
|
return typeof delta.run_id === "string" ? delta.run_id : undefined;
|
|
5952
5833
|
}
|
|
5834
|
+
function streamDeltaOtid(delta) {
|
|
5835
|
+
return typeof delta.otid === "string" || delta.otid === null ? delta.otid : undefined;
|
|
5836
|
+
}
|
|
5837
|
+
function streamDeltaSeqId(delta) {
|
|
5838
|
+
return typeof delta.seq_id === "number" ? delta.seq_id : undefined;
|
|
5839
|
+
}
|
|
5953
5840
|
function streamDeltaStopReason2(delta) {
|
|
5954
5841
|
return typeof delta.stop_reason === "string" ? delta.stop_reason : undefined;
|
|
5955
5842
|
}
|
|
@@ -6100,6 +5987,7 @@ function toSessionDeviceStatus(status) {
|
|
|
6100
5987
|
isProcessing: status.is_processing,
|
|
6101
5988
|
permissionMode,
|
|
6102
5989
|
workingDirectory: status.current_working_directory,
|
|
5990
|
+
memoryDirectory: typeof status.memory_directory === "string" ? status.memory_directory : null,
|
|
6103
5991
|
pendingControlRequests: pendingControlRequests(status),
|
|
6104
5992
|
raw: { ...status }
|
|
6105
5993
|
};
|
|
@@ -6359,6 +6247,8 @@ class RemoteTurnCoordinator {
|
|
|
6359
6247
|
transformStreamDelta(delta) {
|
|
6360
6248
|
const messageType = typeof delta.message_type === "string" ? delta.message_type : undefined;
|
|
6361
6249
|
const runId = typeof delta.run_id === "string" ? delta.run_id : undefined;
|
|
6250
|
+
const otid = streamDeltaOtid(delta);
|
|
6251
|
+
const seqId = streamDeltaSeqId(delta);
|
|
6362
6252
|
const uuid = typeof delta.id === "string" ? delta.id : `${this.label}-${++this.messageCounter}`;
|
|
6363
6253
|
if (messageType === "assistant_message") {
|
|
6364
6254
|
const content = extractTextFromContent(delta.content);
|
|
@@ -6366,13 +6256,27 @@ class RemoteTurnCoordinator {
|
|
|
6366
6256
|
return null;
|
|
6367
6257
|
if (this.activeTurn)
|
|
6368
6258
|
this.activeTurn.assistantText += content;
|
|
6369
|
-
return {
|
|
6259
|
+
return {
|
|
6260
|
+
type: "assistant",
|
|
6261
|
+
content,
|
|
6262
|
+
uuid,
|
|
6263
|
+
...otid !== undefined ? { otid } : {},
|
|
6264
|
+
...seqId !== undefined ? { seqId } : {},
|
|
6265
|
+
runId
|
|
6266
|
+
};
|
|
6370
6267
|
}
|
|
6371
6268
|
if (messageType === "reasoning_message") {
|
|
6372
6269
|
const content = typeof delta.reasoning === "string" ? delta.reasoning : extractTextFromContent(delta.content);
|
|
6373
6270
|
if (!content)
|
|
6374
6271
|
return null;
|
|
6375
|
-
return {
|
|
6272
|
+
return {
|
|
6273
|
+
type: "reasoning",
|
|
6274
|
+
content,
|
|
6275
|
+
uuid,
|
|
6276
|
+
...otid !== undefined ? { otid } : {},
|
|
6277
|
+
...seqId !== undefined ? { seqId } : {},
|
|
6278
|
+
runId
|
|
6279
|
+
};
|
|
6376
6280
|
}
|
|
6377
6281
|
if (messageType === "tool_call_message" || messageType === "approval_request_message") {
|
|
6378
6282
|
const toolCall = firstToolCall(delta);
|
|
@@ -7075,26 +6979,6 @@ function assertRemoteCreateAgentOptionsSupported(options) {
|
|
|
7075
6979
|
throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
|
|
7076
6980
|
}
|
|
7077
6981
|
}
|
|
7078
|
-
function assertRemoteSessionOptionsSupported(action, options) {
|
|
7079
|
-
if (options.systemPrompt !== undefined) {
|
|
7080
|
-
throw new Error(`App-server ${action}() does not yet support systemPrompt overrides for existing agents.`);
|
|
7081
|
-
}
|
|
7082
|
-
if (options.disallowedTools !== undefined) {
|
|
7083
|
-
throw new Error(`App-server ${action}() does not yet support disallowedTools.`);
|
|
7084
|
-
}
|
|
7085
|
-
if (options.systemInfoReminder !== undefined) {
|
|
7086
|
-
throw new Error(`App-server ${action}() does not yet support systemInfoReminder overrides.`);
|
|
7087
|
-
}
|
|
7088
|
-
if (options.dreaming?.behavior !== undefined) {
|
|
7089
|
-
throw new Error(`App-server ${action}() does not yet support dreaming.behavior overrides.`);
|
|
7090
|
-
}
|
|
7091
|
-
if (options.memfsStartup !== undefined) {
|
|
7092
|
-
throw new Error(`App-server ${action}() does not support memfsStartup.`);
|
|
7093
|
-
}
|
|
7094
|
-
if (options.includePartialMessages !== undefined) {
|
|
7095
|
-
throw new Error(`App-server ${action}() streams app-server deltas directly and does not support includePartialMessages.`);
|
|
7096
|
-
}
|
|
7097
|
-
}
|
|
7098
6982
|
function normalizeMemoryBlock(block) {
|
|
7099
6983
|
const normalized = { ...block };
|
|
7100
6984
|
if (normalized.value === undefined && typeof normalized.content === "string") {
|
|
@@ -7525,9 +7409,7 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
7525
7409
|
return options.memfs !== false;
|
|
7526
7410
|
}
|
|
7527
7411
|
async initializeRuntimeController() {
|
|
7528
|
-
await this.remoteOptions.beforeConnect?.();
|
|
7529
7412
|
const url = await this.resolveAppServerUrl();
|
|
7530
|
-
await releaseAppServerManagementConnections(url);
|
|
7531
7413
|
const client = applyUniqueRequestIds(createAppServerClient({
|
|
7532
7414
|
url,
|
|
7533
7415
|
...this.remoteOptions.authToken !== undefined ? { authToken: this.remoteOptions.authToken } : {},
|
|
@@ -7837,6 +7719,222 @@ class CloudManagementTransport {
|
|
|
7837
7719
|
}
|
|
7838
7720
|
}
|
|
7839
7721
|
|
|
7722
|
+
// src/cloud-status-transport.ts
|
|
7723
|
+
var CONNECTING = 0;
|
|
7724
|
+
var OPEN = 1;
|
|
7725
|
+
var CLOSING = 2;
|
|
7726
|
+
var CLOSED = 3;
|
|
7727
|
+
var MAX_IDEMPOTENCY_KEYS = 1000;
|
|
7728
|
+
function addSocketListener(socket, type, listener) {
|
|
7729
|
+
if (socket.addEventListener) {
|
|
7730
|
+
socket.addEventListener(type, listener);
|
|
7731
|
+
return () => socket.removeEventListener?.(type, listener);
|
|
7732
|
+
}
|
|
7733
|
+
if (socket.on) {
|
|
7734
|
+
socket.on(type, listener);
|
|
7735
|
+
return () => socket.off?.(type, listener);
|
|
7736
|
+
}
|
|
7737
|
+
throw new Error("WebSocket implementation does not support event listeners.");
|
|
7738
|
+
}
|
|
7739
|
+
function messageEventData(event) {
|
|
7740
|
+
if (typeof event === "string")
|
|
7741
|
+
return event;
|
|
7742
|
+
if (!event || typeof event !== "object")
|
|
7743
|
+
return null;
|
|
7744
|
+
const data = event.data;
|
|
7745
|
+
if (typeof data === "string")
|
|
7746
|
+
return data;
|
|
7747
|
+
if (data instanceof ArrayBuffer) {
|
|
7748
|
+
return new TextDecoder().decode(data);
|
|
7749
|
+
}
|
|
7750
|
+
if (data instanceof Uint8Array) {
|
|
7751
|
+
return new TextDecoder().decode(data);
|
|
7752
|
+
}
|
|
7753
|
+
return null;
|
|
7754
|
+
}
|
|
7755
|
+
function channelUrl(url, channel) {
|
|
7756
|
+
const parsed = new URL(url);
|
|
7757
|
+
parsed.searchParams.set("channel", channel);
|
|
7758
|
+
return parsed.toString();
|
|
7759
|
+
}
|
|
7760
|
+
|
|
7761
|
+
class CloudStatusTransport {
|
|
7762
|
+
options;
|
|
7763
|
+
controlSocket;
|
|
7764
|
+
streamSocket;
|
|
7765
|
+
state = CONNECTING;
|
|
7766
|
+
openedChannels = new Set;
|
|
7767
|
+
listeners = new Map;
|
|
7768
|
+
removers = [];
|
|
7769
|
+
seenIdempotencyKeys = new Set;
|
|
7770
|
+
seenIdempotencyOrder = [];
|
|
7771
|
+
lastEventSeq = null;
|
|
7772
|
+
pingTimer = null;
|
|
7773
|
+
closeEmitted = false;
|
|
7774
|
+
constructor(options) {
|
|
7775
|
+
this.options = options;
|
|
7776
|
+
const socketOptions = options.headers ? { headers: options.headers } : undefined;
|
|
7777
|
+
this.controlSocket = new options.WebSocket(channelUrl(options.url, "control"), socketOptions);
|
|
7778
|
+
this.streamSocket = new options.WebSocket(channelUrl(options.url, "stream"), socketOptions);
|
|
7779
|
+
this.bindSocket("control", this.controlSocket);
|
|
7780
|
+
this.bindSocket("stream", this.streamSocket);
|
|
7781
|
+
this.startPing();
|
|
7782
|
+
}
|
|
7783
|
+
get readyState() {
|
|
7784
|
+
return this.state;
|
|
7785
|
+
}
|
|
7786
|
+
send(data) {
|
|
7787
|
+
if (this.state !== OPEN || this.controlSocket.readyState !== OPEN) {
|
|
7788
|
+
throw new Error("Cloud status control socket is not open");
|
|
7789
|
+
}
|
|
7790
|
+
this.controlSocket.send(data);
|
|
7791
|
+
}
|
|
7792
|
+
close() {
|
|
7793
|
+
if (this.state === CLOSED || this.state === CLOSING)
|
|
7794
|
+
return;
|
|
7795
|
+
this.state = CLOSING;
|
|
7796
|
+
this.stopPing();
|
|
7797
|
+
this.closeUnderlyingSockets();
|
|
7798
|
+
this.finishClose({});
|
|
7799
|
+
}
|
|
7800
|
+
addEventListener(type, listener) {
|
|
7801
|
+
let listeners = this.listeners.get(type);
|
|
7802
|
+
if (!listeners) {
|
|
7803
|
+
listeners = new Set;
|
|
7804
|
+
this.listeners.set(type, listeners);
|
|
7805
|
+
}
|
|
7806
|
+
listeners.add(listener);
|
|
7807
|
+
}
|
|
7808
|
+
removeEventListener(type, listener) {
|
|
7809
|
+
this.listeners.get(type)?.delete(listener);
|
|
7810
|
+
}
|
|
7811
|
+
bindSocket(channel, socket) {
|
|
7812
|
+
this.removers.push(addSocketListener(socket, "open", () => {
|
|
7813
|
+
this.openedChannels.add(channel);
|
|
7814
|
+
if (this.openedChannels.size === 2 && this.state === CONNECTING) {
|
|
7815
|
+
this.state = OPEN;
|
|
7816
|
+
this.emit("open", {});
|
|
7817
|
+
}
|
|
7818
|
+
}), addSocketListener(socket, "message", (event) => {
|
|
7819
|
+
if (this.shouldForwardMessage(channel, socket, event)) {
|
|
7820
|
+
this.emit("message", event);
|
|
7821
|
+
}
|
|
7822
|
+
}), addSocketListener(socket, "error", (event) => {
|
|
7823
|
+
this.emit("error", event);
|
|
7824
|
+
}), addSocketListener(socket, "close", (event) => {
|
|
7825
|
+
if (this.state !== CLOSED) {
|
|
7826
|
+
this.state = CLOSING;
|
|
7827
|
+
this.stopPing();
|
|
7828
|
+
this.closeUnderlyingSockets(socket);
|
|
7829
|
+
this.finishClose(event);
|
|
7830
|
+
}
|
|
7831
|
+
}));
|
|
7832
|
+
}
|
|
7833
|
+
shouldForwardMessage(channel, socket, event) {
|
|
7834
|
+
const data = messageEventData(event);
|
|
7835
|
+
if (!data)
|
|
7836
|
+
return true;
|
|
7837
|
+
let message;
|
|
7838
|
+
try {
|
|
7839
|
+
message = JSON.parse(data);
|
|
7840
|
+
} catch {
|
|
7841
|
+
return true;
|
|
7842
|
+
}
|
|
7843
|
+
this.ackIfSequenced(socket, message);
|
|
7844
|
+
if (channel === "control" && message.type === "stream_delta") {
|
|
7845
|
+
return false;
|
|
7846
|
+
}
|
|
7847
|
+
if (this.isDuplicate(message))
|
|
7848
|
+
return false;
|
|
7849
|
+
this.trackEventSequence(message);
|
|
7850
|
+
return true;
|
|
7851
|
+
}
|
|
7852
|
+
ackIfSequenced(socket, message) {
|
|
7853
|
+
if (typeof message.seq !== "number")
|
|
7854
|
+
return;
|
|
7855
|
+
this.sendCommand(socket, { type: "ack", seq: message.seq });
|
|
7856
|
+
}
|
|
7857
|
+
isDuplicate(message) {
|
|
7858
|
+
const key = typeof message.idempotency_key === "string" ? message.idempotency_key : null;
|
|
7859
|
+
if (!key)
|
|
7860
|
+
return false;
|
|
7861
|
+
if (this.seenIdempotencyKeys.has(key))
|
|
7862
|
+
return true;
|
|
7863
|
+
this.seenIdempotencyKeys.add(key);
|
|
7864
|
+
this.seenIdempotencyOrder.push(key);
|
|
7865
|
+
while (this.seenIdempotencyOrder.length > MAX_IDEMPOTENCY_KEYS) {
|
|
7866
|
+
const oldest = this.seenIdempotencyOrder.shift();
|
|
7867
|
+
if (oldest)
|
|
7868
|
+
this.seenIdempotencyKeys.delete(oldest);
|
|
7869
|
+
}
|
|
7870
|
+
return false;
|
|
7871
|
+
}
|
|
7872
|
+
trackEventSequence(message) {
|
|
7873
|
+
if (typeof message.event_seq !== "number")
|
|
7874
|
+
return;
|
|
7875
|
+
if (this.lastEventSeq !== null && message.event_seq > this.lastEventSeq + 1) {
|
|
7876
|
+
this.sendCommand(this.controlSocket, {
|
|
7877
|
+
type: "sync",
|
|
7878
|
+
runtime: this.options.runtime,
|
|
7879
|
+
recover_approvals: true,
|
|
7880
|
+
force_device_status: true
|
|
7881
|
+
});
|
|
7882
|
+
}
|
|
7883
|
+
if (this.lastEventSeq === null || message.event_seq > this.lastEventSeq) {
|
|
7884
|
+
this.lastEventSeq = message.event_seq;
|
|
7885
|
+
}
|
|
7886
|
+
}
|
|
7887
|
+
sendCommand(socket, command) {
|
|
7888
|
+
if (socket.readyState !== OPEN)
|
|
7889
|
+
return;
|
|
7890
|
+
try {
|
|
7891
|
+
socket.send(JSON.stringify(command));
|
|
7892
|
+
} catch {}
|
|
7893
|
+
}
|
|
7894
|
+
startPing() {
|
|
7895
|
+
this.pingTimer = setInterval(() => {
|
|
7896
|
+
this.sendCommand(this.controlSocket, { type: "ping" });
|
|
7897
|
+
this.sendCommand(this.streamSocket, { type: "ping" });
|
|
7898
|
+
}, this.options.pingIntervalMs);
|
|
7899
|
+
this.pingTimer.unref?.();
|
|
7900
|
+
}
|
|
7901
|
+
stopPing() {
|
|
7902
|
+
if (!this.pingTimer)
|
|
7903
|
+
return;
|
|
7904
|
+
clearInterval(this.pingTimer);
|
|
7905
|
+
this.pingTimer = null;
|
|
7906
|
+
}
|
|
7907
|
+
closeUnderlyingSockets(except) {
|
|
7908
|
+
for (const socket of [this.controlSocket, this.streamSocket]) {
|
|
7909
|
+
if (socket !== except && (socket.readyState === CONNECTING || socket.readyState === OPEN)) {
|
|
7910
|
+
socket.close();
|
|
7911
|
+
}
|
|
7912
|
+
}
|
|
7913
|
+
}
|
|
7914
|
+
finishClose(event) {
|
|
7915
|
+
if (this.closeEmitted)
|
|
7916
|
+
return;
|
|
7917
|
+
this.closeEmitted = true;
|
|
7918
|
+
this.state = CLOSED;
|
|
7919
|
+
this.stopPing();
|
|
7920
|
+
for (const remove of this.removers.splice(0))
|
|
7921
|
+
remove();
|
|
7922
|
+
this.emit("close", event);
|
|
7923
|
+
}
|
|
7924
|
+
emit(type, event) {
|
|
7925
|
+
for (const listener of this.listeners.get(type) ?? []) {
|
|
7926
|
+
listener(event);
|
|
7927
|
+
}
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
function createCloudStatusTransportConstructor(options) {
|
|
7931
|
+
return class CloudStatusTransportSocket extends CloudStatusTransport {
|
|
7932
|
+
constructor(_url, _socketOptions) {
|
|
7933
|
+
super(options);
|
|
7934
|
+
}
|
|
7935
|
+
};
|
|
7936
|
+
}
|
|
7937
|
+
|
|
7840
7938
|
// src/remote.ts
|
|
7841
7939
|
function getDefaultApiKey2() {
|
|
7842
7940
|
if (typeof process === "undefined") {
|
|
@@ -8145,191 +8243,6 @@ function buildCloudStatusWebSocketUrl(params) {
|
|
|
8145
8243
|
}
|
|
8146
8244
|
return base.toString();
|
|
8147
8245
|
}
|
|
8148
|
-
function addSocketListener(socket, type, listener) {
|
|
8149
|
-
if (socket.addEventListener) {
|
|
8150
|
-
socket.addEventListener(type, listener);
|
|
8151
|
-
return () => socket.removeEventListener?.(type, listener);
|
|
8152
|
-
}
|
|
8153
|
-
if (socket.on) {
|
|
8154
|
-
socket.on(type, listener);
|
|
8155
|
-
return () => socket.off?.(type, listener);
|
|
8156
|
-
}
|
|
8157
|
-
throw new Error("WebSocket implementation does not support event listeners.");
|
|
8158
|
-
}
|
|
8159
|
-
function messageEventData(event) {
|
|
8160
|
-
if (typeof event === "string")
|
|
8161
|
-
return event;
|
|
8162
|
-
if (event && typeof event === "object") {
|
|
8163
|
-
const data = event.data;
|
|
8164
|
-
if (typeof data === "string")
|
|
8165
|
-
return data;
|
|
8166
|
-
if (data instanceof ArrayBuffer) {
|
|
8167
|
-
return new TextDecoder().decode(data);
|
|
8168
|
-
}
|
|
8169
|
-
if (data instanceof Uint8Array) {
|
|
8170
|
-
return new TextDecoder().decode(data);
|
|
8171
|
-
}
|
|
8172
|
-
}
|
|
8173
|
-
return null;
|
|
8174
|
-
}
|
|
8175
|
-
function createCloudStatusWebSocketConstructor(params) {
|
|
8176
|
-
const WebSocketCtor = getWebSocketConstructor(params.cloudOptions.WebSocket);
|
|
8177
|
-
const authMode = params.cloudOptions.webSocketAuth ?? "header";
|
|
8178
|
-
const cloudHeaders3 = authMode === "header" ? cloudWebSocketHeaders(params.cloudOptions) : undefined;
|
|
8179
|
-
const pingIntervalMs = params.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS;
|
|
8180
|
-
const state = {
|
|
8181
|
-
runtime: params.runtime,
|
|
8182
|
-
seenIdempotencyKeys: new Set,
|
|
8183
|
-
seenIdempotencyOrder: [],
|
|
8184
|
-
lastEventSeq: null,
|
|
8185
|
-
controlSocket: null
|
|
8186
|
-
};
|
|
8187
|
-
|
|
8188
|
-
class CloudStatusSocketAdapter {
|
|
8189
|
-
socket;
|
|
8190
|
-
channel;
|
|
8191
|
-
listenerRemovers = new Map;
|
|
8192
|
-
pingTimer = null;
|
|
8193
|
-
removeCloseListener = null;
|
|
8194
|
-
constructor(url, options) {
|
|
8195
|
-
this.channel = new URL(url).searchParams.get("channel");
|
|
8196
|
-
const mergedHeaders = authMode === "header" ? {
|
|
8197
|
-
...options?.headers ?? {},
|
|
8198
|
-
...cloudHeaders3 ?? {}
|
|
8199
|
-
} : undefined;
|
|
8200
|
-
const socketOptions = mergedHeaders && Object.keys(mergedHeaders).length > 0 ? { headers: mergedHeaders } : undefined;
|
|
8201
|
-
this.socket = new WebSocketCtor(url, socketOptions);
|
|
8202
|
-
if (this.channel === "control") {
|
|
8203
|
-
state.controlSocket = this;
|
|
8204
|
-
}
|
|
8205
|
-
this.removeCloseListener = addSocketListener(this.socket, "close", () => {
|
|
8206
|
-
this.stopPing();
|
|
8207
|
-
if (state.controlSocket === this)
|
|
8208
|
-
state.controlSocket = null;
|
|
8209
|
-
});
|
|
8210
|
-
this.startPing(pingIntervalMs);
|
|
8211
|
-
}
|
|
8212
|
-
get readyState() {
|
|
8213
|
-
return this.socket.readyState;
|
|
8214
|
-
}
|
|
8215
|
-
send(data) {
|
|
8216
|
-
this.socket.send(data);
|
|
8217
|
-
}
|
|
8218
|
-
close() {
|
|
8219
|
-
this.stopPing();
|
|
8220
|
-
this.removeCloseListener?.();
|
|
8221
|
-
this.removeCloseListener = null;
|
|
8222
|
-
if (state.controlSocket === this)
|
|
8223
|
-
state.controlSocket = null;
|
|
8224
|
-
this.socket.close();
|
|
8225
|
-
}
|
|
8226
|
-
addEventListener(type, listener) {
|
|
8227
|
-
const wrapped = type === "message" ? (event) => {
|
|
8228
|
-
if (this.handleIncomingMessage(event)) {
|
|
8229
|
-
listener(event);
|
|
8230
|
-
}
|
|
8231
|
-
} : listener;
|
|
8232
|
-
const remove = addSocketListener(this.socket, type, wrapped);
|
|
8233
|
-
let typeRemovers = this.listenerRemovers.get(type);
|
|
8234
|
-
if (!typeRemovers) {
|
|
8235
|
-
typeRemovers = new Map;
|
|
8236
|
-
this.listenerRemovers.set(type, typeRemovers);
|
|
8237
|
-
}
|
|
8238
|
-
typeRemovers.set(listener, remove);
|
|
8239
|
-
}
|
|
8240
|
-
removeEventListener(type, listener) {
|
|
8241
|
-
const typeRemovers = this.listenerRemovers.get(type);
|
|
8242
|
-
const remove = typeRemovers?.get(listener);
|
|
8243
|
-
if (!remove)
|
|
8244
|
-
return;
|
|
8245
|
-
remove();
|
|
8246
|
-
typeRemovers?.delete(listener);
|
|
8247
|
-
if (typeRemovers?.size === 0) {
|
|
8248
|
-
this.listenerRemovers.delete(type);
|
|
8249
|
-
}
|
|
8250
|
-
}
|
|
8251
|
-
handleIncomingMessage(event) {
|
|
8252
|
-
const data = messageEventData(event);
|
|
8253
|
-
if (!data)
|
|
8254
|
-
return true;
|
|
8255
|
-
let message;
|
|
8256
|
-
try {
|
|
8257
|
-
message = JSON.parse(data);
|
|
8258
|
-
} catch {
|
|
8259
|
-
return true;
|
|
8260
|
-
}
|
|
8261
|
-
this.ackIfSequenced(message);
|
|
8262
|
-
if (this.channel === "control" && message.type === "stream_delta") {
|
|
8263
|
-
return false;
|
|
8264
|
-
}
|
|
8265
|
-
if (this.isDuplicate(message))
|
|
8266
|
-
return false;
|
|
8267
|
-
this.trackEventSeq(message);
|
|
8268
|
-
return true;
|
|
8269
|
-
}
|
|
8270
|
-
ackIfSequenced(message) {
|
|
8271
|
-
if (typeof message.seq !== "number")
|
|
8272
|
-
return;
|
|
8273
|
-
this.sendCloudCommand({ type: "ack", seq: message.seq });
|
|
8274
|
-
}
|
|
8275
|
-
isDuplicate(message) {
|
|
8276
|
-
const idempotencyKey = typeof message.idempotency_key === "string" ? message.idempotency_key : undefined;
|
|
8277
|
-
if (!idempotencyKey)
|
|
8278
|
-
return false;
|
|
8279
|
-
if (state.seenIdempotencyKeys.has(idempotencyKey))
|
|
8280
|
-
return true;
|
|
8281
|
-
state.seenIdempotencyKeys.add(idempotencyKey);
|
|
8282
|
-
state.seenIdempotencyOrder.push(idempotencyKey);
|
|
8283
|
-
while (state.seenIdempotencyOrder.length > 1000) {
|
|
8284
|
-
const oldest = state.seenIdempotencyOrder.shift();
|
|
8285
|
-
if (oldest)
|
|
8286
|
-
state.seenIdempotencyKeys.delete(oldest);
|
|
8287
|
-
}
|
|
8288
|
-
return false;
|
|
8289
|
-
}
|
|
8290
|
-
trackEventSeq(message) {
|
|
8291
|
-
if (typeof message.event_seq !== "number")
|
|
8292
|
-
return;
|
|
8293
|
-
if (state.lastEventSeq !== null && message.event_seq > state.lastEventSeq + 1) {
|
|
8294
|
-
this.sendSync(true);
|
|
8295
|
-
}
|
|
8296
|
-
if (state.lastEventSeq === null || message.event_seq > state.lastEventSeq) {
|
|
8297
|
-
state.lastEventSeq = message.event_seq;
|
|
8298
|
-
}
|
|
8299
|
-
}
|
|
8300
|
-
sendSync(recoverApprovals) {
|
|
8301
|
-
const target = state.controlSocket?.readyState === 1 ? state.controlSocket : this;
|
|
8302
|
-
target.sendCloudCommand({
|
|
8303
|
-
type: "sync",
|
|
8304
|
-
runtime: state.runtime,
|
|
8305
|
-
recover_approvals: recoverApprovals,
|
|
8306
|
-
force_device_status: true
|
|
8307
|
-
});
|
|
8308
|
-
}
|
|
8309
|
-
sendCloudCommand(command) {
|
|
8310
|
-
if (this.readyState !== 1)
|
|
8311
|
-
return;
|
|
8312
|
-
try {
|
|
8313
|
-
this.socket.send(JSON.stringify(command));
|
|
8314
|
-
} catch {}
|
|
8315
|
-
}
|
|
8316
|
-
startPing(intervalMs) {
|
|
8317
|
-
if (this.pingTimer)
|
|
8318
|
-
return;
|
|
8319
|
-
this.pingTimer = setInterval(() => {
|
|
8320
|
-
this.sendCloudCommand({ type: "ping" });
|
|
8321
|
-
}, intervalMs);
|
|
8322
|
-
this.pingTimer.unref?.();
|
|
8323
|
-
}
|
|
8324
|
-
stopPing() {
|
|
8325
|
-
if (!this.pingTimer)
|
|
8326
|
-
return;
|
|
8327
|
-
clearInterval(this.pingTimer);
|
|
8328
|
-
this.pingTimer = null;
|
|
8329
|
-
}
|
|
8330
|
-
}
|
|
8331
|
-
return CloudStatusSocketAdapter;
|
|
8332
|
-
}
|
|
8333
8246
|
function isCloudConversation(value) {
|
|
8334
8247
|
return Boolean(value && typeof value === "object" && typeof value.id === "string");
|
|
8335
8248
|
}
|
|
@@ -8373,24 +8286,6 @@ function assertCloudSessionOptionsSupported(action, options) {
|
|
|
8373
8286
|
if (options.environment !== undefined && options.sandbox !== undefined) {
|
|
8374
8287
|
throw new Error(`Letta Cloud ${action}() cannot specify both environment and sandbox options.`);
|
|
8375
8288
|
}
|
|
8376
|
-
if (options.systemPrompt !== undefined) {
|
|
8377
|
-
throw new Error(`Letta Cloud ${action}() cannot rewrite an existing agent's systemPrompt from the SDK adapter yet.`);
|
|
8378
|
-
}
|
|
8379
|
-
if (options.disallowedTools !== undefined) {
|
|
8380
|
-
throw new Error(`Letta Cloud ${action}() has not wired disallowedTools to the remote device protocol yet.`);
|
|
8381
|
-
}
|
|
8382
|
-
if (options.systemInfoReminder !== undefined) {
|
|
8383
|
-
throw new Error(`Letta Cloud ${action}() has not wired systemInfoReminder to the remote device protocol yet.`);
|
|
8384
|
-
}
|
|
8385
|
-
if (options.dreaming?.behavior !== undefined) {
|
|
8386
|
-
throw new Error(`Letta Cloud ${action}() does not yet support dreaming.behavior overrides.`);
|
|
8387
|
-
}
|
|
8388
|
-
if (options.memfsStartup !== undefined) {
|
|
8389
|
-
throw new Error(`Letta Cloud ${action}() does not support memfsStartup.`);
|
|
8390
|
-
}
|
|
8391
|
-
if (options.includePartialMessages !== undefined) {
|
|
8392
|
-
throw new Error(`Letta Cloud ${action}() streams Remote Client deltas directly; includePartialMessages is not a separate toggle.`);
|
|
8393
|
-
}
|
|
8394
8289
|
}
|
|
8395
8290
|
|
|
8396
8291
|
class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
@@ -8404,6 +8299,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8404
8299
|
sandboxRefreshInFlight = null;
|
|
8405
8300
|
sandboxLifecycleClosing = false;
|
|
8406
8301
|
attachedRepositoryIds = new Set;
|
|
8302
|
+
repositoryIdsRequiringCleanupRecompile = new Set;
|
|
8407
8303
|
cloudMode;
|
|
8408
8304
|
constructor(cloudOptions, mode) {
|
|
8409
8305
|
super(mode, {
|
|
@@ -8417,7 +8313,10 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8417
8313
|
}
|
|
8418
8314
|
async initializeRuntimeController() {
|
|
8419
8315
|
const resolved = await this.resolveRuntime();
|
|
8420
|
-
const connection = await this.resolveConnectionForRuntime(resolved.runtime)
|
|
8316
|
+
const connection = await this.resolveConnectionForRuntime(resolved.runtime).catch(async (error) => {
|
|
8317
|
+
await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
|
|
8318
|
+
throw error;
|
|
8319
|
+
});
|
|
8421
8320
|
this.connectionId = connection.connectionId;
|
|
8422
8321
|
const apiKey = getCloudApiKey2(this.cloudOptions);
|
|
8423
8322
|
const url = buildCloudStatusWebSocketUrl({
|
|
@@ -8430,8 +8329,11 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8430
8329
|
});
|
|
8431
8330
|
const client = applyUniqueRequestIds(createAppServerClient({
|
|
8432
8331
|
url,
|
|
8433
|
-
WebSocket:
|
|
8434
|
-
|
|
8332
|
+
WebSocket: createCloudStatusTransportConstructor({
|
|
8333
|
+
url,
|
|
8334
|
+
WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
|
|
8335
|
+
...(this.cloudOptions.webSocketAuth ?? "header") === "header" ? { headers: cloudWebSocketHeaders(this.cloudOptions) } : {},
|
|
8336
|
+
pingIntervalMs: this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
|
|
8435
8337
|
runtime: resolved.runtime
|
|
8436
8338
|
}),
|
|
8437
8339
|
requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
|
|
@@ -8469,7 +8371,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8469
8371
|
this.removeControlRequestHandler = null;
|
|
8470
8372
|
client.close();
|
|
8471
8373
|
await this.cleanupManagedSandbox();
|
|
8472
|
-
await this.cleanupSessionRepositories(resolved.runtime.agent_id);
|
|
8374
|
+
await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
|
|
8473
8375
|
throw error;
|
|
8474
8376
|
}
|
|
8475
8377
|
}
|
|
@@ -8520,8 +8422,9 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8520
8422
|
this.removeControlRequestHandler?.();
|
|
8521
8423
|
this.removeControlRequestHandler = null;
|
|
8522
8424
|
this.cleanupManagedSandbox();
|
|
8523
|
-
if (this.runtime?.agent_id)
|
|
8524
|
-
this.cleanupSessionRepositories(this.runtime.agent_id);
|
|
8425
|
+
if (this.runtime?.agent_id) {
|
|
8426
|
+
this.cleanupSessionRepositories(this.runtime.agent_id, this.runtime.conversation_id);
|
|
8427
|
+
}
|
|
8525
8428
|
}
|
|
8526
8429
|
async resolveRuntime() {
|
|
8527
8430
|
let agentId = this.cloudMode.agentId;
|
|
@@ -8536,22 +8439,30 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8536
8439
|
if (!agentId) {
|
|
8537
8440
|
throw new Error("Letta Cloud createSession()/resumeSession() requires an agent id or conversation id.");
|
|
8538
8441
|
}
|
|
8539
|
-
await this.attachSessionRepositories(agentId);
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8442
|
+
const shouldRecompileRepositories = await this.attachSessionRepositories(agentId);
|
|
8443
|
+
try {
|
|
8444
|
+
if (this.cloudMode.newConversation) {
|
|
8445
|
+
const conversation = await this.createConversation(agentId);
|
|
8446
|
+
conversationId = conversation.id;
|
|
8447
|
+
} else if (this.cloudMode.defaultConversation) {
|
|
8448
|
+
conversationId = "default";
|
|
8449
|
+
}
|
|
8450
|
+
if (!conversationId) {
|
|
8451
|
+
throw new Error("Letta Cloud createSession()/resumeSession() requires an agent id or conversation id.");
|
|
8452
|
+
}
|
|
8453
|
+
if (shouldRecompileRepositories) {
|
|
8454
|
+
await this.recompileSystemPrompt(agentId, conversationId);
|
|
8455
|
+
}
|
|
8456
|
+
return { runtime: { agent_id: agentId, conversation_id: conversationId } };
|
|
8457
|
+
} catch (error) {
|
|
8458
|
+
await this.cleanupSessionRepositories(agentId, conversationId);
|
|
8459
|
+
throw error;
|
|
8548
8460
|
}
|
|
8549
|
-
return { runtime: { agent_id: agentId, conversation_id: conversationId } };
|
|
8550
8461
|
}
|
|
8551
8462
|
async attachSessionRepositories(agentId) {
|
|
8552
8463
|
const resources = this.repositoryResources();
|
|
8553
8464
|
if (resources.length === 0)
|
|
8554
|
-
return;
|
|
8465
|
+
return false;
|
|
8555
8466
|
const existing = await this.listAgentRepositories(agentId);
|
|
8556
8467
|
const existingIds = new Set(existing.map((repository) => repository.id));
|
|
8557
8468
|
try {
|
|
@@ -8567,15 +8478,42 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8567
8478
|
await this.cleanupSessionRepositories(agentId);
|
|
8568
8479
|
throw error;
|
|
8569
8480
|
}
|
|
8481
|
+
const shouldRecompile = resources.some((resource) => resource.recompile !== false);
|
|
8482
|
+
this.repositoryIdsRequiringCleanupRecompile = new Set(resources.filter((resource) => resource.recompile !== false && this.attachedRepositoryIds.has(resource.repositoryId)).map((resource) => resource.repositoryId));
|
|
8483
|
+
return shouldRecompile;
|
|
8570
8484
|
}
|
|
8571
|
-
async cleanupSessionRepositories(agentId) {
|
|
8485
|
+
async cleanupSessionRepositories(agentId, conversationId) {
|
|
8572
8486
|
const repositoryIds = [...this.attachedRepositoryIds];
|
|
8487
|
+
const repositoryIdsRequiringRecompile = this.repositoryIdsRequiringCleanupRecompile;
|
|
8573
8488
|
this.attachedRepositoryIds.clear();
|
|
8574
|
-
|
|
8489
|
+
this.repositoryIdsRequiringCleanupRecompile = new Set;
|
|
8490
|
+
const recompileAfterDetach = await Promise.all(repositoryIds.map(async (repositoryId) => {
|
|
8575
8491
|
try {
|
|
8576
8492
|
await this.unlinkAgentRepository(agentId, repositoryId);
|
|
8577
|
-
|
|
8493
|
+
return repositoryIdsRequiringRecompile.has(repositoryId);
|
|
8494
|
+
} catch {
|
|
8495
|
+
return false;
|
|
8496
|
+
}
|
|
8578
8497
|
}));
|
|
8498
|
+
if (recompileAfterDetach.some(Boolean)) {
|
|
8499
|
+
try {
|
|
8500
|
+
await this.recompileSystemPrompt(agentId, conversationId);
|
|
8501
|
+
} catch {}
|
|
8502
|
+
}
|
|
8503
|
+
}
|
|
8504
|
+
async recompileSystemPrompt(agentId, conversationId) {
|
|
8505
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
8506
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
8507
|
+
const usesAgentPrompt = !conversationId || conversationId === "default";
|
|
8508
|
+
const path = usesAgentPrompt ? `/v1/agents/${encodeURIComponent(agentId)}/recompile` : `/v1/conversations/${encodeURIComponent(conversationId)}/recompile`;
|
|
8509
|
+
const url = `${baseUrl}${path}`;
|
|
8510
|
+
const response = await fetchImpl(url, {
|
|
8511
|
+
method: "POST",
|
|
8512
|
+
headers: cloudHeaders2(this.cloudOptions),
|
|
8513
|
+
body: JSON.stringify(usesAgentPrompt ? {} : { agent_id: agentId })
|
|
8514
|
+
});
|
|
8515
|
+
const body = await parseJsonResponse3(response);
|
|
8516
|
+
assertOkResponse2(response, body, "Cloud recompile system prompt", url);
|
|
8579
8517
|
}
|
|
8580
8518
|
repositoryResources() {
|
|
8581
8519
|
const resources = this.cloudMode.options.resources ?? [];
|
|
@@ -9019,7 +8957,23 @@ function validateApprovalRecoveryOptions(options) {
|
|
|
9019
8957
|
}
|
|
9020
8958
|
}
|
|
9021
8959
|
function validateRemovedSessionOptions(options) {
|
|
9022
|
-
|
|
8960
|
+
const removedOptions = options;
|
|
8961
|
+
if (removedOptions.systemPrompt !== undefined) {
|
|
8962
|
+
throw new Error("systemPrompt is not supported when opening an existing agent session.");
|
|
8963
|
+
}
|
|
8964
|
+
if (removedOptions.disallowedTools !== undefined) {
|
|
8965
|
+
throw new Error("disallowedTools is not supported when opening an existing agent session.");
|
|
8966
|
+
}
|
|
8967
|
+
if (removedOptions.systemInfoReminder !== undefined) {
|
|
8968
|
+
throw new Error("systemInfoReminder is not supported when opening an existing agent session.");
|
|
8969
|
+
}
|
|
8970
|
+
if (removedOptions.includePartialMessages !== undefined) {
|
|
8971
|
+
throw new Error("includePartialMessages is not supported by app-server sessions.");
|
|
8972
|
+
}
|
|
8973
|
+
if (options.dreaming && "behavior" in options.dreaming && options.dreaming.behavior !== undefined) {
|
|
8974
|
+
throw new Error("dreaming.behavior is not supported when opening an existing agent session.");
|
|
8975
|
+
}
|
|
8976
|
+
if (removedOptions.memfsStartup !== undefined) {
|
|
9023
8977
|
throw new Error("memfsStartup is not supported by the SDK.");
|
|
9024
8978
|
}
|
|
9025
8979
|
}
|
|
@@ -9069,9 +9023,6 @@ function validateReasoningEffort(value) {
|
|
|
9069
9023
|
}
|
|
9070
9024
|
}
|
|
9071
9025
|
function validateCreateSessionOptions(options) {
|
|
9072
|
-
if (options.systemPrompt !== undefined) {
|
|
9073
|
-
validateSystemPromptPreset(options.systemPrompt);
|
|
9074
|
-
}
|
|
9075
9026
|
validateSkillSources(options.skillSources);
|
|
9076
9027
|
validateReasoningEffort(options.reasoningEffort);
|
|
9077
9028
|
validateDreamingOptions(options.dreaming);
|
|
@@ -9127,6 +9078,7 @@ function stripCloudExecutionOptions(options) {
|
|
|
9127
9078
|
const sessionOptions = { ...options };
|
|
9128
9079
|
delete sessionOptions.environment;
|
|
9129
9080
|
delete sessionOptions.sandbox;
|
|
9081
|
+
delete sessionOptions.filesystemConfinement;
|
|
9130
9082
|
return sessionOptions;
|
|
9131
9083
|
}
|
|
9132
9084
|
function hasRepositoryResources(options) {
|
|
@@ -9170,17 +9122,13 @@ class LettaAgentClientBase {
|
|
|
9170
9122
|
}
|
|
9171
9123
|
if (this.backend === "local") {
|
|
9172
9124
|
const localOptions = options;
|
|
9173
|
-
if (
|
|
9174
|
-
throw new Error("
|
|
9125
|
+
if ("transport" in localOptions) {
|
|
9126
|
+
throw new Error("Local transport selection has been removed. The local backend always uses the app-server protocol.");
|
|
9175
9127
|
}
|
|
9176
9128
|
const requestTimeoutMs = localOptions.appServer?.requestTimeoutMs;
|
|
9177
9129
|
if (requestTimeoutMs !== undefined && (!Number.isInteger(requestTimeoutMs) || requestTimeoutMs <= 0)) {
|
|
9178
9130
|
throw new Error("Invalid appServer.requestTimeoutMs. Expected a positive integer.");
|
|
9179
9131
|
}
|
|
9180
|
-
const idleLingerMs = localOptions.appServer?.idleLingerMs;
|
|
9181
|
-
if (idleLingerMs !== undefined && (!Number.isInteger(idleLingerMs) || idleLingerMs < 0)) {
|
|
9182
|
-
throw new Error("Invalid appServer.idleLingerMs. Expected a non-negative integer.");
|
|
9183
|
-
}
|
|
9184
9132
|
const startupTimeoutMs = localOptions.appServer?.startupTimeoutMs;
|
|
9185
9133
|
if (startupTimeoutMs !== undefined && (!Number.isInteger(startupTimeoutMs) || startupTimeoutMs <= 0)) {
|
|
9186
9134
|
throw new Error("Invalid appServer.startupTimeoutMs. Expected a positive integer.");
|
|
@@ -9193,9 +9141,6 @@ class LettaAgentClientBase {
|
|
|
9193
9141
|
if (options.requestTimeoutMs !== undefined && (!Number.isInteger(options.requestTimeoutMs) || options.requestTimeoutMs <= 0)) {
|
|
9194
9142
|
throw new Error("Invalid requestTimeoutMs. Expected a positive integer.");
|
|
9195
9143
|
}
|
|
9196
|
-
if (options.idleLingerMs !== undefined && (!Number.isInteger(options.idleLingerMs) || options.idleLingerMs < 0)) {
|
|
9197
|
-
throw new Error("Invalid idleLingerMs. Expected a non-negative integer.");
|
|
9198
|
-
}
|
|
9199
9144
|
}
|
|
9200
9145
|
if (this.backend === "cloud") {
|
|
9201
9146
|
validateCloudClientOptions(options);
|
|
@@ -9223,40 +9168,35 @@ class LettaAgentClientBase {
|
|
|
9223
9168
|
}
|
|
9224
9169
|
return this.createLocalAgent(options);
|
|
9225
9170
|
}
|
|
9226
|
-
createSession(
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
const sessionOptions = stripCloudExecutionOptions(
|
|
9171
|
+
createSession(agentId, options = {}) {
|
|
9172
|
+
if (typeof agentId !== "string" || agentId.length === 0) {
|
|
9173
|
+
throw new Error("createSession() requires a non-empty agent id.");
|
|
9174
|
+
}
|
|
9175
|
+
const sessionOptions = stripCloudExecutionOptions(options);
|
|
9231
9176
|
validateCreateSessionOptions(sessionOptions);
|
|
9177
|
+
this.assertSessionBackend("createSession", options);
|
|
9232
9178
|
if (this.backend === "remote") {
|
|
9233
|
-
if (!agentId) {
|
|
9234
|
-
throw new Error("App-server createSession() requires an agent id. Call createAgent() first or pass an agent id.");
|
|
9235
|
-
}
|
|
9236
9179
|
return new AppServerSession(this.appServerSessionOptions(), {
|
|
9237
9180
|
kind: "session",
|
|
9238
9181
|
agentId,
|
|
9239
9182
|
newConversation: true,
|
|
9240
|
-
options
|
|
9183
|
+
options
|
|
9241
9184
|
});
|
|
9242
9185
|
}
|
|
9243
9186
|
if (this.backend === "cloud") {
|
|
9244
|
-
if (!agentId) {
|
|
9245
|
-
throw new Error("Letta Cloud createSession() requires an agent id. Call createAgent() first or pass an agent id.");
|
|
9246
|
-
}
|
|
9247
9187
|
return new CloudEnvironmentSession(this.cloudOptions(), {
|
|
9248
9188
|
kind: "session",
|
|
9249
9189
|
agentId,
|
|
9250
9190
|
newConversation: true,
|
|
9251
|
-
options
|
|
9191
|
+
options
|
|
9252
9192
|
});
|
|
9253
9193
|
}
|
|
9254
|
-
return this.createLocalSession(agentId,
|
|
9194
|
+
return this.createLocalSession(agentId, options);
|
|
9255
9195
|
}
|
|
9256
9196
|
resumeSession(id, options = {}) {
|
|
9257
|
-
this.assertSessionBackend("resumeSession", options);
|
|
9258
9197
|
const sessionOptions = stripCloudExecutionOptions(options);
|
|
9259
9198
|
validateCreateSessionOptions(sessionOptions);
|
|
9199
|
+
this.assertSessionBackend("resumeSession", options);
|
|
9260
9200
|
if (this.backend === "remote") {
|
|
9261
9201
|
if (looksLikeConversationId(id)) {
|
|
9262
9202
|
return new AppServerSession(this.appServerSessionOptions(), {
|
|
@@ -9287,10 +9227,10 @@ class LettaAgentClientBase {
|
|
|
9287
9227
|
options
|
|
9288
9228
|
});
|
|
9289
9229
|
}
|
|
9290
|
-
return this.resumeLocalSession(id, options
|
|
9230
|
+
return this.resumeLocalSession(id, options);
|
|
9291
9231
|
}
|
|
9292
9232
|
async prompt(message, agentId, options = {}) {
|
|
9293
|
-
const session =
|
|
9233
|
+
const session = this.createSession(agentId, options);
|
|
9294
9234
|
try {
|
|
9295
9235
|
return await session.runTurn(message);
|
|
9296
9236
|
} finally {
|
|
@@ -9298,6 +9238,9 @@ class LettaAgentClientBase {
|
|
|
9298
9238
|
}
|
|
9299
9239
|
}
|
|
9300
9240
|
assertSessionBackend(action, options) {
|
|
9241
|
+
if (options.filesystemConfinement !== undefined && options.filesystemConfinement !== "memory") {
|
|
9242
|
+
throw new Error(`Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`);
|
|
9243
|
+
}
|
|
9301
9244
|
const effectiveEnvironment = options.environment ?? this.environment;
|
|
9302
9245
|
if (this.backend === "local") {
|
|
9303
9246
|
if (effectiveEnvironment !== undefined) {
|
|
@@ -9309,12 +9252,18 @@ class LettaAgentClientBase {
|
|
|
9309
9252
|
if (hasRepositoryResources(options)) {
|
|
9310
9253
|
throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
|
|
9311
9254
|
}
|
|
9312
|
-
if (
|
|
9313
|
-
|
|
9255
|
+
if (options.filesystemConfinement !== undefined) {
|
|
9256
|
+
const localOptions = this.options;
|
|
9257
|
+
if (localOptions.appServer?.url !== undefined) {
|
|
9258
|
+
throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
|
|
9259
|
+
}
|
|
9314
9260
|
}
|
|
9315
9261
|
return;
|
|
9316
9262
|
}
|
|
9317
9263
|
if (this.backend === "remote") {
|
|
9264
|
+
if (options.filesystemConfinement !== undefined) {
|
|
9265
|
+
throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
|
|
9266
|
+
}
|
|
9318
9267
|
if (options.environment !== undefined) {
|
|
9319
9268
|
throw new Error(`${action}() environment overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
9320
9269
|
}
|
|
@@ -9324,10 +9273,12 @@ class LettaAgentClientBase {
|
|
|
9324
9273
|
if (hasRepositoryResources(options)) {
|
|
9325
9274
|
throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
|
|
9326
9275
|
}
|
|
9327
|
-
assertRemoteSessionOptionsSupported(action, options);
|
|
9328
9276
|
return;
|
|
9329
9277
|
}
|
|
9330
9278
|
if (this.backend === "cloud") {
|
|
9279
|
+
if (options.filesystemConfinement !== undefined) {
|
|
9280
|
+
throw new Error(`${action}() filesystemConfinement is only supported with backend: "local".`);
|
|
9281
|
+
}
|
|
9331
9282
|
const cloudOptions = this.cloudOptions();
|
|
9332
9283
|
if (cloudOptions.environment !== undefined && options.sandbox !== undefined) {
|
|
9333
9284
|
throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default environment.`);
|
|
@@ -9340,16 +9291,13 @@ class LettaAgentClientBase {
|
|
|
9340
9291
|
}
|
|
9341
9292
|
throw new Error(`LettaAgentClient backend '${this.backend}' is not implemented yet. ${action} currently supports backend 'local' only.`);
|
|
9342
9293
|
}
|
|
9343
|
-
useLegacyLocalStdio() {
|
|
9344
|
-
return this.options.transport === "stdio";
|
|
9345
|
-
}
|
|
9346
9294
|
createLocalAgent(_options) {
|
|
9347
9295
|
throw this.localBackendUnavailableError();
|
|
9348
9296
|
}
|
|
9349
|
-
createLocalSession(_agentId, _options
|
|
9297
|
+
createLocalSession(_agentId, _options) {
|
|
9350
9298
|
throw this.localBackendUnavailableError();
|
|
9351
9299
|
}
|
|
9352
|
-
resumeLocalSession(_id, _options
|
|
9300
|
+
resumeLocalSession(_id, _options) {
|
|
9353
9301
|
throw this.localBackendUnavailableError();
|
|
9354
9302
|
}
|
|
9355
9303
|
localBackendUnavailableError() {
|
|
@@ -9365,10 +9313,7 @@ class LettaAgentClientBase {
|
|
|
9365
9313
|
return this.options;
|
|
9366
9314
|
}
|
|
9367
9315
|
appServerSessionOptions() {
|
|
9368
|
-
return
|
|
9369
|
-
...this.remoteOptions(),
|
|
9370
|
-
beforeConnect: () => this.releaseIdleManagementConnection()
|
|
9371
|
-
};
|
|
9316
|
+
return this.remoteOptions();
|
|
9372
9317
|
}
|
|
9373
9318
|
getRepositoriesClient() {
|
|
9374
9319
|
if (this.backend !== "cloud") {
|
|
@@ -9377,9 +9322,6 @@ class LettaAgentClientBase {
|
|
|
9377
9322
|
this.repositoriesClient ??= new RepositoriesClient(this.cloudOptions());
|
|
9378
9323
|
return this.repositoriesClient;
|
|
9379
9324
|
}
|
|
9380
|
-
async releaseIdleManagementConnection() {
|
|
9381
|
-
await this.managementTransport?.releaseIdleConnection?.();
|
|
9382
|
-
}
|
|
9383
9325
|
getManagementTransport() {
|
|
9384
9326
|
if (this.managementTransport)
|
|
9385
9327
|
return this.managementTransport;
|
|
@@ -9487,4 +9429,4 @@ export {
|
|
|
9487
9429
|
CloudManagedSandboxExpiredError
|
|
9488
9430
|
};
|
|
9489
9431
|
|
|
9490
|
-
//# debugId=
|
|
9432
|
+
//# debugId=C4A49597208F4A6464756E2164756E21
|