@letta-ai/letta-agent-sdk 0.3.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +0 -3
- package/README.md +12 -0
- 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 +369 -468
- 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.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 +896 -2019
- 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 +57 -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 +9 -267
- 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 +14 -0
- package/src/remote-turn-coordinator.ts +20 -2
- package/src/types.ts +64 -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
|
}
|
|
@@ -6359,6 +6246,8 @@ class RemoteTurnCoordinator {
|
|
|
6359
6246
|
transformStreamDelta(delta) {
|
|
6360
6247
|
const messageType = typeof delta.message_type === "string" ? delta.message_type : undefined;
|
|
6361
6248
|
const runId = typeof delta.run_id === "string" ? delta.run_id : undefined;
|
|
6249
|
+
const otid = streamDeltaOtid(delta);
|
|
6250
|
+
const seqId = streamDeltaSeqId(delta);
|
|
6362
6251
|
const uuid = typeof delta.id === "string" ? delta.id : `${this.label}-${++this.messageCounter}`;
|
|
6363
6252
|
if (messageType === "assistant_message") {
|
|
6364
6253
|
const content = extractTextFromContent(delta.content);
|
|
@@ -6366,13 +6255,27 @@ class RemoteTurnCoordinator {
|
|
|
6366
6255
|
return null;
|
|
6367
6256
|
if (this.activeTurn)
|
|
6368
6257
|
this.activeTurn.assistantText += content;
|
|
6369
|
-
return {
|
|
6258
|
+
return {
|
|
6259
|
+
type: "assistant",
|
|
6260
|
+
content,
|
|
6261
|
+
uuid,
|
|
6262
|
+
...otid !== undefined ? { otid } : {},
|
|
6263
|
+
...seqId !== undefined ? { seqId } : {},
|
|
6264
|
+
runId
|
|
6265
|
+
};
|
|
6370
6266
|
}
|
|
6371
6267
|
if (messageType === "reasoning_message") {
|
|
6372
6268
|
const content = typeof delta.reasoning === "string" ? delta.reasoning : extractTextFromContent(delta.content);
|
|
6373
6269
|
if (!content)
|
|
6374
6270
|
return null;
|
|
6375
|
-
return {
|
|
6271
|
+
return {
|
|
6272
|
+
type: "reasoning",
|
|
6273
|
+
content,
|
|
6274
|
+
uuid,
|
|
6275
|
+
...otid !== undefined ? { otid } : {},
|
|
6276
|
+
...seqId !== undefined ? { seqId } : {},
|
|
6277
|
+
runId
|
|
6278
|
+
};
|
|
6376
6279
|
}
|
|
6377
6280
|
if (messageType === "tool_call_message" || messageType === "approval_request_message") {
|
|
6378
6281
|
const toolCall = firstToolCall(delta);
|
|
@@ -7075,26 +6978,6 @@ function assertRemoteCreateAgentOptionsSupported(options) {
|
|
|
7075
6978
|
throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
|
|
7076
6979
|
}
|
|
7077
6980
|
}
|
|
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
6981
|
function normalizeMemoryBlock(block) {
|
|
7099
6982
|
const normalized = { ...block };
|
|
7100
6983
|
if (normalized.value === undefined && typeof normalized.content === "string") {
|
|
@@ -7525,9 +7408,7 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
7525
7408
|
return options.memfs !== false;
|
|
7526
7409
|
}
|
|
7527
7410
|
async initializeRuntimeController() {
|
|
7528
|
-
await this.remoteOptions.beforeConnect?.();
|
|
7529
7411
|
const url = await this.resolveAppServerUrl();
|
|
7530
|
-
await releaseAppServerManagementConnections(url);
|
|
7531
7412
|
const client = applyUniqueRequestIds(createAppServerClient({
|
|
7532
7413
|
url,
|
|
7533
7414
|
...this.remoteOptions.authToken !== undefined ? { authToken: this.remoteOptions.authToken } : {},
|
|
@@ -7837,6 +7718,222 @@ class CloudManagementTransport {
|
|
|
7837
7718
|
}
|
|
7838
7719
|
}
|
|
7839
7720
|
|
|
7721
|
+
// src/cloud-status-transport.ts
|
|
7722
|
+
var CONNECTING = 0;
|
|
7723
|
+
var OPEN = 1;
|
|
7724
|
+
var CLOSING = 2;
|
|
7725
|
+
var CLOSED = 3;
|
|
7726
|
+
var MAX_IDEMPOTENCY_KEYS = 1000;
|
|
7727
|
+
function addSocketListener(socket, type, listener) {
|
|
7728
|
+
if (socket.addEventListener) {
|
|
7729
|
+
socket.addEventListener(type, listener);
|
|
7730
|
+
return () => socket.removeEventListener?.(type, listener);
|
|
7731
|
+
}
|
|
7732
|
+
if (socket.on) {
|
|
7733
|
+
socket.on(type, listener);
|
|
7734
|
+
return () => socket.off?.(type, listener);
|
|
7735
|
+
}
|
|
7736
|
+
throw new Error("WebSocket implementation does not support event listeners.");
|
|
7737
|
+
}
|
|
7738
|
+
function messageEventData(event) {
|
|
7739
|
+
if (typeof event === "string")
|
|
7740
|
+
return event;
|
|
7741
|
+
if (!event || typeof event !== "object")
|
|
7742
|
+
return null;
|
|
7743
|
+
const data = event.data;
|
|
7744
|
+
if (typeof data === "string")
|
|
7745
|
+
return data;
|
|
7746
|
+
if (data instanceof ArrayBuffer) {
|
|
7747
|
+
return new TextDecoder().decode(data);
|
|
7748
|
+
}
|
|
7749
|
+
if (data instanceof Uint8Array) {
|
|
7750
|
+
return new TextDecoder().decode(data);
|
|
7751
|
+
}
|
|
7752
|
+
return null;
|
|
7753
|
+
}
|
|
7754
|
+
function channelUrl(url, channel) {
|
|
7755
|
+
const parsed = new URL(url);
|
|
7756
|
+
parsed.searchParams.set("channel", channel);
|
|
7757
|
+
return parsed.toString();
|
|
7758
|
+
}
|
|
7759
|
+
|
|
7760
|
+
class CloudStatusTransport {
|
|
7761
|
+
options;
|
|
7762
|
+
controlSocket;
|
|
7763
|
+
streamSocket;
|
|
7764
|
+
state = CONNECTING;
|
|
7765
|
+
openedChannels = new Set;
|
|
7766
|
+
listeners = new Map;
|
|
7767
|
+
removers = [];
|
|
7768
|
+
seenIdempotencyKeys = new Set;
|
|
7769
|
+
seenIdempotencyOrder = [];
|
|
7770
|
+
lastEventSeq = null;
|
|
7771
|
+
pingTimer = null;
|
|
7772
|
+
closeEmitted = false;
|
|
7773
|
+
constructor(options) {
|
|
7774
|
+
this.options = options;
|
|
7775
|
+
const socketOptions = options.headers ? { headers: options.headers } : undefined;
|
|
7776
|
+
this.controlSocket = new options.WebSocket(channelUrl(options.url, "control"), socketOptions);
|
|
7777
|
+
this.streamSocket = new options.WebSocket(channelUrl(options.url, "stream"), socketOptions);
|
|
7778
|
+
this.bindSocket("control", this.controlSocket);
|
|
7779
|
+
this.bindSocket("stream", this.streamSocket);
|
|
7780
|
+
this.startPing();
|
|
7781
|
+
}
|
|
7782
|
+
get readyState() {
|
|
7783
|
+
return this.state;
|
|
7784
|
+
}
|
|
7785
|
+
send(data) {
|
|
7786
|
+
if (this.state !== OPEN || this.controlSocket.readyState !== OPEN) {
|
|
7787
|
+
throw new Error("Cloud status control socket is not open");
|
|
7788
|
+
}
|
|
7789
|
+
this.controlSocket.send(data);
|
|
7790
|
+
}
|
|
7791
|
+
close() {
|
|
7792
|
+
if (this.state === CLOSED || this.state === CLOSING)
|
|
7793
|
+
return;
|
|
7794
|
+
this.state = CLOSING;
|
|
7795
|
+
this.stopPing();
|
|
7796
|
+
this.closeUnderlyingSockets();
|
|
7797
|
+
this.finishClose({});
|
|
7798
|
+
}
|
|
7799
|
+
addEventListener(type, listener) {
|
|
7800
|
+
let listeners = this.listeners.get(type);
|
|
7801
|
+
if (!listeners) {
|
|
7802
|
+
listeners = new Set;
|
|
7803
|
+
this.listeners.set(type, listeners);
|
|
7804
|
+
}
|
|
7805
|
+
listeners.add(listener);
|
|
7806
|
+
}
|
|
7807
|
+
removeEventListener(type, listener) {
|
|
7808
|
+
this.listeners.get(type)?.delete(listener);
|
|
7809
|
+
}
|
|
7810
|
+
bindSocket(channel, socket) {
|
|
7811
|
+
this.removers.push(addSocketListener(socket, "open", () => {
|
|
7812
|
+
this.openedChannels.add(channel);
|
|
7813
|
+
if (this.openedChannels.size === 2 && this.state === CONNECTING) {
|
|
7814
|
+
this.state = OPEN;
|
|
7815
|
+
this.emit("open", {});
|
|
7816
|
+
}
|
|
7817
|
+
}), addSocketListener(socket, "message", (event) => {
|
|
7818
|
+
if (this.shouldForwardMessage(channel, socket, event)) {
|
|
7819
|
+
this.emit("message", event);
|
|
7820
|
+
}
|
|
7821
|
+
}), addSocketListener(socket, "error", (event) => {
|
|
7822
|
+
this.emit("error", event);
|
|
7823
|
+
}), addSocketListener(socket, "close", (event) => {
|
|
7824
|
+
if (this.state !== CLOSED) {
|
|
7825
|
+
this.state = CLOSING;
|
|
7826
|
+
this.stopPing();
|
|
7827
|
+
this.closeUnderlyingSockets(socket);
|
|
7828
|
+
this.finishClose(event);
|
|
7829
|
+
}
|
|
7830
|
+
}));
|
|
7831
|
+
}
|
|
7832
|
+
shouldForwardMessage(channel, socket, event) {
|
|
7833
|
+
const data = messageEventData(event);
|
|
7834
|
+
if (!data)
|
|
7835
|
+
return true;
|
|
7836
|
+
let message;
|
|
7837
|
+
try {
|
|
7838
|
+
message = JSON.parse(data);
|
|
7839
|
+
} catch {
|
|
7840
|
+
return true;
|
|
7841
|
+
}
|
|
7842
|
+
this.ackIfSequenced(socket, message);
|
|
7843
|
+
if (channel === "control" && message.type === "stream_delta") {
|
|
7844
|
+
return false;
|
|
7845
|
+
}
|
|
7846
|
+
if (this.isDuplicate(message))
|
|
7847
|
+
return false;
|
|
7848
|
+
this.trackEventSequence(message);
|
|
7849
|
+
return true;
|
|
7850
|
+
}
|
|
7851
|
+
ackIfSequenced(socket, message) {
|
|
7852
|
+
if (typeof message.seq !== "number")
|
|
7853
|
+
return;
|
|
7854
|
+
this.sendCommand(socket, { type: "ack", seq: message.seq });
|
|
7855
|
+
}
|
|
7856
|
+
isDuplicate(message) {
|
|
7857
|
+
const key = typeof message.idempotency_key === "string" ? message.idempotency_key : null;
|
|
7858
|
+
if (!key)
|
|
7859
|
+
return false;
|
|
7860
|
+
if (this.seenIdempotencyKeys.has(key))
|
|
7861
|
+
return true;
|
|
7862
|
+
this.seenIdempotencyKeys.add(key);
|
|
7863
|
+
this.seenIdempotencyOrder.push(key);
|
|
7864
|
+
while (this.seenIdempotencyOrder.length > MAX_IDEMPOTENCY_KEYS) {
|
|
7865
|
+
const oldest = this.seenIdempotencyOrder.shift();
|
|
7866
|
+
if (oldest)
|
|
7867
|
+
this.seenIdempotencyKeys.delete(oldest);
|
|
7868
|
+
}
|
|
7869
|
+
return false;
|
|
7870
|
+
}
|
|
7871
|
+
trackEventSequence(message) {
|
|
7872
|
+
if (typeof message.event_seq !== "number")
|
|
7873
|
+
return;
|
|
7874
|
+
if (this.lastEventSeq !== null && message.event_seq > this.lastEventSeq + 1) {
|
|
7875
|
+
this.sendCommand(this.controlSocket, {
|
|
7876
|
+
type: "sync",
|
|
7877
|
+
runtime: this.options.runtime,
|
|
7878
|
+
recover_approvals: true,
|
|
7879
|
+
force_device_status: true
|
|
7880
|
+
});
|
|
7881
|
+
}
|
|
7882
|
+
if (this.lastEventSeq === null || message.event_seq > this.lastEventSeq) {
|
|
7883
|
+
this.lastEventSeq = message.event_seq;
|
|
7884
|
+
}
|
|
7885
|
+
}
|
|
7886
|
+
sendCommand(socket, command) {
|
|
7887
|
+
if (socket.readyState !== OPEN)
|
|
7888
|
+
return;
|
|
7889
|
+
try {
|
|
7890
|
+
socket.send(JSON.stringify(command));
|
|
7891
|
+
} catch {}
|
|
7892
|
+
}
|
|
7893
|
+
startPing() {
|
|
7894
|
+
this.pingTimer = setInterval(() => {
|
|
7895
|
+
this.sendCommand(this.controlSocket, { type: "ping" });
|
|
7896
|
+
this.sendCommand(this.streamSocket, { type: "ping" });
|
|
7897
|
+
}, this.options.pingIntervalMs);
|
|
7898
|
+
this.pingTimer.unref?.();
|
|
7899
|
+
}
|
|
7900
|
+
stopPing() {
|
|
7901
|
+
if (!this.pingTimer)
|
|
7902
|
+
return;
|
|
7903
|
+
clearInterval(this.pingTimer);
|
|
7904
|
+
this.pingTimer = null;
|
|
7905
|
+
}
|
|
7906
|
+
closeUnderlyingSockets(except) {
|
|
7907
|
+
for (const socket of [this.controlSocket, this.streamSocket]) {
|
|
7908
|
+
if (socket !== except && (socket.readyState === CONNECTING || socket.readyState === OPEN)) {
|
|
7909
|
+
socket.close();
|
|
7910
|
+
}
|
|
7911
|
+
}
|
|
7912
|
+
}
|
|
7913
|
+
finishClose(event) {
|
|
7914
|
+
if (this.closeEmitted)
|
|
7915
|
+
return;
|
|
7916
|
+
this.closeEmitted = true;
|
|
7917
|
+
this.state = CLOSED;
|
|
7918
|
+
this.stopPing();
|
|
7919
|
+
for (const remove of this.removers.splice(0))
|
|
7920
|
+
remove();
|
|
7921
|
+
this.emit("close", event);
|
|
7922
|
+
}
|
|
7923
|
+
emit(type, event) {
|
|
7924
|
+
for (const listener of this.listeners.get(type) ?? []) {
|
|
7925
|
+
listener(event);
|
|
7926
|
+
}
|
|
7927
|
+
}
|
|
7928
|
+
}
|
|
7929
|
+
function createCloudStatusTransportConstructor(options) {
|
|
7930
|
+
return class CloudStatusTransportSocket extends CloudStatusTransport {
|
|
7931
|
+
constructor(_url, _socketOptions) {
|
|
7932
|
+
super(options);
|
|
7933
|
+
}
|
|
7934
|
+
};
|
|
7935
|
+
}
|
|
7936
|
+
|
|
7840
7937
|
// src/remote.ts
|
|
7841
7938
|
function getDefaultApiKey2() {
|
|
7842
7939
|
if (typeof process === "undefined") {
|
|
@@ -8145,191 +8242,6 @@ function buildCloudStatusWebSocketUrl(params) {
|
|
|
8145
8242
|
}
|
|
8146
8243
|
return base.toString();
|
|
8147
8244
|
}
|
|
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
8245
|
function isCloudConversation(value) {
|
|
8334
8246
|
return Boolean(value && typeof value === "object" && typeof value.id === "string");
|
|
8335
8247
|
}
|
|
@@ -8373,24 +8285,6 @@ function assertCloudSessionOptionsSupported(action, options) {
|
|
|
8373
8285
|
if (options.environment !== undefined && options.sandbox !== undefined) {
|
|
8374
8286
|
throw new Error(`Letta Cloud ${action}() cannot specify both environment and sandbox options.`);
|
|
8375
8287
|
}
|
|
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
8288
|
}
|
|
8395
8289
|
|
|
8396
8290
|
class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
@@ -8430,8 +8324,11 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8430
8324
|
});
|
|
8431
8325
|
const client = applyUniqueRequestIds(createAppServerClient({
|
|
8432
8326
|
url,
|
|
8433
|
-
WebSocket:
|
|
8434
|
-
|
|
8327
|
+
WebSocket: createCloudStatusTransportConstructor({
|
|
8328
|
+
url,
|
|
8329
|
+
WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
|
|
8330
|
+
...(this.cloudOptions.webSocketAuth ?? "header") === "header" ? { headers: cloudWebSocketHeaders(this.cloudOptions) } : {},
|
|
8331
|
+
pingIntervalMs: this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
|
|
8435
8332
|
runtime: resolved.runtime
|
|
8436
8333
|
}),
|
|
8437
8334
|
requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
|
|
@@ -9019,7 +8916,23 @@ function validateApprovalRecoveryOptions(options) {
|
|
|
9019
8916
|
}
|
|
9020
8917
|
}
|
|
9021
8918
|
function validateRemovedSessionOptions(options) {
|
|
9022
|
-
|
|
8919
|
+
const removedOptions = options;
|
|
8920
|
+
if (removedOptions.systemPrompt !== undefined) {
|
|
8921
|
+
throw new Error("systemPrompt is not supported when opening an existing agent session.");
|
|
8922
|
+
}
|
|
8923
|
+
if (removedOptions.disallowedTools !== undefined) {
|
|
8924
|
+
throw new Error("disallowedTools is not supported when opening an existing agent session.");
|
|
8925
|
+
}
|
|
8926
|
+
if (removedOptions.systemInfoReminder !== undefined) {
|
|
8927
|
+
throw new Error("systemInfoReminder is not supported when opening an existing agent session.");
|
|
8928
|
+
}
|
|
8929
|
+
if (removedOptions.includePartialMessages !== undefined) {
|
|
8930
|
+
throw new Error("includePartialMessages is not supported by app-server sessions.");
|
|
8931
|
+
}
|
|
8932
|
+
if (options.dreaming && "behavior" in options.dreaming && options.dreaming.behavior !== undefined) {
|
|
8933
|
+
throw new Error("dreaming.behavior is not supported when opening an existing agent session.");
|
|
8934
|
+
}
|
|
8935
|
+
if (removedOptions.memfsStartup !== undefined) {
|
|
9023
8936
|
throw new Error("memfsStartup is not supported by the SDK.");
|
|
9024
8937
|
}
|
|
9025
8938
|
}
|
|
@@ -9069,9 +8982,6 @@ function validateReasoningEffort(value) {
|
|
|
9069
8982
|
}
|
|
9070
8983
|
}
|
|
9071
8984
|
function validateCreateSessionOptions(options) {
|
|
9072
|
-
if (options.systemPrompt !== undefined) {
|
|
9073
|
-
validateSystemPromptPreset(options.systemPrompt);
|
|
9074
|
-
}
|
|
9075
8985
|
validateSkillSources(options.skillSources);
|
|
9076
8986
|
validateReasoningEffort(options.reasoningEffort);
|
|
9077
8987
|
validateDreamingOptions(options.dreaming);
|
|
@@ -9127,6 +9037,7 @@ function stripCloudExecutionOptions(options) {
|
|
|
9127
9037
|
const sessionOptions = { ...options };
|
|
9128
9038
|
delete sessionOptions.environment;
|
|
9129
9039
|
delete sessionOptions.sandbox;
|
|
9040
|
+
delete sessionOptions.filesystemConfinement;
|
|
9130
9041
|
return sessionOptions;
|
|
9131
9042
|
}
|
|
9132
9043
|
function hasRepositoryResources(options) {
|
|
@@ -9170,17 +9081,13 @@ class LettaAgentClientBase {
|
|
|
9170
9081
|
}
|
|
9171
9082
|
if (this.backend === "local") {
|
|
9172
9083
|
const localOptions = options;
|
|
9173
|
-
if (
|
|
9174
|
-
throw new Error("
|
|
9084
|
+
if ("transport" in localOptions) {
|
|
9085
|
+
throw new Error("Local transport selection has been removed. The local backend always uses the app-server protocol.");
|
|
9175
9086
|
}
|
|
9176
9087
|
const requestTimeoutMs = localOptions.appServer?.requestTimeoutMs;
|
|
9177
9088
|
if (requestTimeoutMs !== undefined && (!Number.isInteger(requestTimeoutMs) || requestTimeoutMs <= 0)) {
|
|
9178
9089
|
throw new Error("Invalid appServer.requestTimeoutMs. Expected a positive integer.");
|
|
9179
9090
|
}
|
|
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
9091
|
const startupTimeoutMs = localOptions.appServer?.startupTimeoutMs;
|
|
9185
9092
|
if (startupTimeoutMs !== undefined && (!Number.isInteger(startupTimeoutMs) || startupTimeoutMs <= 0)) {
|
|
9186
9093
|
throw new Error("Invalid appServer.startupTimeoutMs. Expected a positive integer.");
|
|
@@ -9193,9 +9100,6 @@ class LettaAgentClientBase {
|
|
|
9193
9100
|
if (options.requestTimeoutMs !== undefined && (!Number.isInteger(options.requestTimeoutMs) || options.requestTimeoutMs <= 0)) {
|
|
9194
9101
|
throw new Error("Invalid requestTimeoutMs. Expected a positive integer.");
|
|
9195
9102
|
}
|
|
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
9103
|
}
|
|
9200
9104
|
if (this.backend === "cloud") {
|
|
9201
9105
|
validateCloudClientOptions(options);
|
|
@@ -9223,40 +9127,35 @@ class LettaAgentClientBase {
|
|
|
9223
9127
|
}
|
|
9224
9128
|
return this.createLocalAgent(options);
|
|
9225
9129
|
}
|
|
9226
|
-
createSession(
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
const sessionOptions = stripCloudExecutionOptions(
|
|
9130
|
+
createSession(agentId, options = {}) {
|
|
9131
|
+
if (typeof agentId !== "string" || agentId.length === 0) {
|
|
9132
|
+
throw new Error("createSession() requires a non-empty agent id.");
|
|
9133
|
+
}
|
|
9134
|
+
const sessionOptions = stripCloudExecutionOptions(options);
|
|
9231
9135
|
validateCreateSessionOptions(sessionOptions);
|
|
9136
|
+
this.assertSessionBackend("createSession", options);
|
|
9232
9137
|
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
9138
|
return new AppServerSession(this.appServerSessionOptions(), {
|
|
9237
9139
|
kind: "session",
|
|
9238
9140
|
agentId,
|
|
9239
9141
|
newConversation: true,
|
|
9240
|
-
options
|
|
9142
|
+
options
|
|
9241
9143
|
});
|
|
9242
9144
|
}
|
|
9243
9145
|
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
9146
|
return new CloudEnvironmentSession(this.cloudOptions(), {
|
|
9248
9147
|
kind: "session",
|
|
9249
9148
|
agentId,
|
|
9250
9149
|
newConversation: true,
|
|
9251
|
-
options
|
|
9150
|
+
options
|
|
9252
9151
|
});
|
|
9253
9152
|
}
|
|
9254
|
-
return this.createLocalSession(agentId,
|
|
9153
|
+
return this.createLocalSession(agentId, options);
|
|
9255
9154
|
}
|
|
9256
9155
|
resumeSession(id, options = {}) {
|
|
9257
|
-
this.assertSessionBackend("resumeSession", options);
|
|
9258
9156
|
const sessionOptions = stripCloudExecutionOptions(options);
|
|
9259
9157
|
validateCreateSessionOptions(sessionOptions);
|
|
9158
|
+
this.assertSessionBackend("resumeSession", options);
|
|
9260
9159
|
if (this.backend === "remote") {
|
|
9261
9160
|
if (looksLikeConversationId(id)) {
|
|
9262
9161
|
return new AppServerSession(this.appServerSessionOptions(), {
|
|
@@ -9287,10 +9186,10 @@ class LettaAgentClientBase {
|
|
|
9287
9186
|
options
|
|
9288
9187
|
});
|
|
9289
9188
|
}
|
|
9290
|
-
return this.resumeLocalSession(id, options
|
|
9189
|
+
return this.resumeLocalSession(id, options);
|
|
9291
9190
|
}
|
|
9292
9191
|
async prompt(message, agentId, options = {}) {
|
|
9293
|
-
const session =
|
|
9192
|
+
const session = this.createSession(agentId, options);
|
|
9294
9193
|
try {
|
|
9295
9194
|
return await session.runTurn(message);
|
|
9296
9195
|
} finally {
|
|
@@ -9298,6 +9197,9 @@ class LettaAgentClientBase {
|
|
|
9298
9197
|
}
|
|
9299
9198
|
}
|
|
9300
9199
|
assertSessionBackend(action, options) {
|
|
9200
|
+
if (options.filesystemConfinement !== undefined && options.filesystemConfinement !== "memory") {
|
|
9201
|
+
throw new Error(`Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`);
|
|
9202
|
+
}
|
|
9301
9203
|
const effectiveEnvironment = options.environment ?? this.environment;
|
|
9302
9204
|
if (this.backend === "local") {
|
|
9303
9205
|
if (effectiveEnvironment !== undefined) {
|
|
@@ -9309,12 +9211,18 @@ class LettaAgentClientBase {
|
|
|
9309
9211
|
if (hasRepositoryResources(options)) {
|
|
9310
9212
|
throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
|
|
9311
9213
|
}
|
|
9312
|
-
if (
|
|
9313
|
-
|
|
9214
|
+
if (options.filesystemConfinement !== undefined) {
|
|
9215
|
+
const localOptions = this.options;
|
|
9216
|
+
if (localOptions.appServer?.url !== undefined) {
|
|
9217
|
+
throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
|
|
9218
|
+
}
|
|
9314
9219
|
}
|
|
9315
9220
|
return;
|
|
9316
9221
|
}
|
|
9317
9222
|
if (this.backend === "remote") {
|
|
9223
|
+
if (options.filesystemConfinement !== undefined) {
|
|
9224
|
+
throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
|
|
9225
|
+
}
|
|
9318
9226
|
if (options.environment !== undefined) {
|
|
9319
9227
|
throw new Error(`${action}() environment overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
9320
9228
|
}
|
|
@@ -9324,10 +9232,12 @@ class LettaAgentClientBase {
|
|
|
9324
9232
|
if (hasRepositoryResources(options)) {
|
|
9325
9233
|
throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
|
|
9326
9234
|
}
|
|
9327
|
-
assertRemoteSessionOptionsSupported(action, options);
|
|
9328
9235
|
return;
|
|
9329
9236
|
}
|
|
9330
9237
|
if (this.backend === "cloud") {
|
|
9238
|
+
if (options.filesystemConfinement !== undefined) {
|
|
9239
|
+
throw new Error(`${action}() filesystemConfinement is only supported with backend: "local".`);
|
|
9240
|
+
}
|
|
9331
9241
|
const cloudOptions = this.cloudOptions();
|
|
9332
9242
|
if (cloudOptions.environment !== undefined && options.sandbox !== undefined) {
|
|
9333
9243
|
throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default environment.`);
|
|
@@ -9340,16 +9250,13 @@ class LettaAgentClientBase {
|
|
|
9340
9250
|
}
|
|
9341
9251
|
throw new Error(`LettaAgentClient backend '${this.backend}' is not implemented yet. ${action} currently supports backend 'local' only.`);
|
|
9342
9252
|
}
|
|
9343
|
-
useLegacyLocalStdio() {
|
|
9344
|
-
return this.options.transport === "stdio";
|
|
9345
|
-
}
|
|
9346
9253
|
createLocalAgent(_options) {
|
|
9347
9254
|
throw this.localBackendUnavailableError();
|
|
9348
9255
|
}
|
|
9349
|
-
createLocalSession(_agentId, _options
|
|
9256
|
+
createLocalSession(_agentId, _options) {
|
|
9350
9257
|
throw this.localBackendUnavailableError();
|
|
9351
9258
|
}
|
|
9352
|
-
resumeLocalSession(_id, _options
|
|
9259
|
+
resumeLocalSession(_id, _options) {
|
|
9353
9260
|
throw this.localBackendUnavailableError();
|
|
9354
9261
|
}
|
|
9355
9262
|
localBackendUnavailableError() {
|
|
@@ -9365,10 +9272,7 @@ class LettaAgentClientBase {
|
|
|
9365
9272
|
return this.options;
|
|
9366
9273
|
}
|
|
9367
9274
|
appServerSessionOptions() {
|
|
9368
|
-
return
|
|
9369
|
-
...this.remoteOptions(),
|
|
9370
|
-
beforeConnect: () => this.releaseIdleManagementConnection()
|
|
9371
|
-
};
|
|
9275
|
+
return this.remoteOptions();
|
|
9372
9276
|
}
|
|
9373
9277
|
getRepositoriesClient() {
|
|
9374
9278
|
if (this.backend !== "cloud") {
|
|
@@ -9377,9 +9281,6 @@ class LettaAgentClientBase {
|
|
|
9377
9281
|
this.repositoriesClient ??= new RepositoriesClient(this.cloudOptions());
|
|
9378
9282
|
return this.repositoriesClient;
|
|
9379
9283
|
}
|
|
9380
|
-
async releaseIdleManagementConnection() {
|
|
9381
|
-
await this.managementTransport?.releaseIdleConnection?.();
|
|
9382
|
-
}
|
|
9383
9284
|
getManagementTransport() {
|
|
9384
9285
|
if (this.managementTransport)
|
|
9385
9286
|
return this.managementTransport;
|
|
@@ -9487,4 +9388,4 @@ export {
|
|
|
9487
9388
|
CloudManagedSandboxExpiredError
|
|
9488
9389
|
};
|
|
9489
9390
|
|
|
9490
|
-
//# debugId=
|
|
9391
|
+
//# debugId=AAFE1DD6848E90C364756E2164756E21
|