@letta-ai/letta-agent-sdk 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-server-management.d.ts +58 -0
- package/dist/app-server-management.d.ts.map +1 -1
- package/dist/app-server-session.d.ts +5 -0
- package/dist/app-server-session.d.ts.map +1 -1
- package/dist/client-base.d.ts +7 -0
- package/dist/client-base.d.ts.map +1 -1
- package/dist/client-entry.js +334 -55
- package/dist/client-entry.js.map +10 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/cloud-session.d.ts.map +1 -1
- package/dist/index.js +382 -64
- package/dist/index.js.map +13 -12
- package/dist/local-app-server-session.d.ts +1 -1
- package/dist/local-app-server-session.d.ts.map +1 -1
- package/dist/management.d.ts +7 -0
- package/dist/management.d.ts.map +1 -1
- package/dist/remote-client-session-core.d.ts +18 -0
- package/dist/remote-client-session-core.d.ts.map +1 -1
- package/dist/request-ids.d.ts +24 -0
- package/dist/request-ids.d.ts.map +1 -0
- package/dist/session.d.ts +10 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -701,7 +701,56 @@ function createAppServerClient(options) {
|
|
|
701
701
|
return new AppServerClient(options);
|
|
702
702
|
}
|
|
703
703
|
|
|
704
|
+
// src/request-ids.ts
|
|
705
|
+
var processRequestCounter = 0;
|
|
706
|
+
function createRequestIdGenerator() {
|
|
707
|
+
const nonce = Math.random().toString(36).slice(2, 10);
|
|
708
|
+
return (prefix = "req") => `${prefix}-${nonce}-${++processRequestCounter}`;
|
|
709
|
+
}
|
|
710
|
+
function applyUniqueRequestIds(client) {
|
|
711
|
+
client.nextRequestId = createRequestIdGenerator();
|
|
712
|
+
return client;
|
|
713
|
+
}
|
|
714
|
+
|
|
704
715
|
// src/app-server-management.ts
|
|
716
|
+
var DEFAULT_IDLE_LINGER_MS = 250;
|
|
717
|
+
var registeredTransportsByUrl = new Map;
|
|
718
|
+
function appServerUrlKey(value) {
|
|
719
|
+
try {
|
|
720
|
+
const url = new URL(value);
|
|
721
|
+
if (url.protocol === "http:")
|
|
722
|
+
url.protocol = "ws:";
|
|
723
|
+
if (url.protocol === "https:")
|
|
724
|
+
url.protocol = "wss:";
|
|
725
|
+
url.hash = "";
|
|
726
|
+
url.searchParams.delete("channel");
|
|
727
|
+
return url.toString();
|
|
728
|
+
} catch {
|
|
729
|
+
return value;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function registerManagementTransport(url, transport) {
|
|
733
|
+
const key = appServerUrlKey(url);
|
|
734
|
+
const registration = { transport };
|
|
735
|
+
const transports = registeredTransportsByUrl.get(key) ?? new Set;
|
|
736
|
+
transports.add(registration);
|
|
737
|
+
registeredTransportsByUrl.set(key, transports);
|
|
738
|
+
return () => {
|
|
739
|
+
transports.delete(registration);
|
|
740
|
+
if (transports.size === 0) {
|
|
741
|
+
registeredTransportsByUrl.delete(key);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
async function releaseAppServerManagementConnections(url) {
|
|
746
|
+
const key = appServerUrlKey(url);
|
|
747
|
+
while (true) {
|
|
748
|
+
const transports = [...registeredTransportsByUrl.get(key) ?? []];
|
|
749
|
+
if (transports.length === 0)
|
|
750
|
+
return;
|
|
751
|
+
await Promise.all(transports.map(({ transport }) => transport.releaseIdleConnection()));
|
|
752
|
+
}
|
|
753
|
+
}
|
|
705
754
|
function ensureResponse(response, value, fallback) {
|
|
706
755
|
if (!response.success || value == null) {
|
|
707
756
|
throw new Error(response.error ?? fallback);
|
|
@@ -737,8 +786,16 @@ function stringRecord(value) {
|
|
|
737
786
|
|
|
738
787
|
class AppServerManagementTransport {
|
|
739
788
|
options;
|
|
789
|
+
connectionPromise = null;
|
|
790
|
+
releasePromise = null;
|
|
791
|
+
closingConnections = new Set;
|
|
792
|
+
inFlightRequests = 0;
|
|
793
|
+
idleWaiters = new Set;
|
|
794
|
+
idleTimer = null;
|
|
795
|
+
idleLingerMs;
|
|
740
796
|
constructor(options) {
|
|
741
797
|
this.options = options;
|
|
798
|
+
this.idleLingerMs = options.idleLingerMs ?? DEFAULT_IDLE_LINGER_MS;
|
|
742
799
|
}
|
|
743
800
|
async listAgents(query) {
|
|
744
801
|
const response = await this.request("agent_list", { query }, "agent_list_response");
|
|
@@ -805,38 +862,206 @@ class AppServerManagementTransport {
|
|
|
805
862
|
}
|
|
806
863
|
return { messages: response.messages };
|
|
807
864
|
}
|
|
865
|
+
releaseIdleConnection() {
|
|
866
|
+
this.clearIdleTimer();
|
|
867
|
+
if (this.releasePromise)
|
|
868
|
+
return this.releasePromise;
|
|
869
|
+
const release = this.releaseConnectionWhenIdle();
|
|
870
|
+
this.releasePromise = release;
|
|
871
|
+
release.then(() => {
|
|
872
|
+
if (this.releasePromise === release) {
|
|
873
|
+
this.releasePromise = null;
|
|
874
|
+
}
|
|
875
|
+
}, () => {
|
|
876
|
+
if (this.releasePromise === release) {
|
|
877
|
+
this.releasePromise = null;
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
return release;
|
|
881
|
+
}
|
|
808
882
|
async request(type, body, responseType) {
|
|
809
|
-
|
|
883
|
+
if (this.releasePromise) {
|
|
884
|
+
await this.releasePromise;
|
|
885
|
+
}
|
|
886
|
+
if (this.closingConnections.size > 0) {
|
|
887
|
+
await Promise.all([...this.closingConnections]);
|
|
888
|
+
}
|
|
889
|
+
this.clearIdleTimer();
|
|
890
|
+
this.inFlightRequests += 1;
|
|
891
|
+
try {
|
|
892
|
+
const { client } = await this.acquireConnection();
|
|
893
|
+
const command = {
|
|
894
|
+
type,
|
|
895
|
+
request_id: client.nextRequestId(type),
|
|
896
|
+
...body
|
|
897
|
+
};
|
|
898
|
+
const response = await client.request(command, {
|
|
899
|
+
predicate: (message) => message.type === responseType
|
|
900
|
+
});
|
|
901
|
+
return response;
|
|
902
|
+
} finally {
|
|
903
|
+
this.inFlightRequests -= 1;
|
|
904
|
+
if (this.inFlightRequests === 0) {
|
|
905
|
+
const waiters = [...this.idleWaiters];
|
|
906
|
+
this.idleWaiters.clear();
|
|
907
|
+
for (const resolve of waiters)
|
|
908
|
+
resolve();
|
|
909
|
+
if (!this.releasePromise) {
|
|
910
|
+
this.scheduleIdleRelease();
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
async releaseConnectionWhenIdle() {
|
|
916
|
+
if (this.inFlightRequests > 0) {
|
|
917
|
+
await new Promise((resolve) => {
|
|
918
|
+
this.idleWaiters.add(resolve);
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
this.clearIdleTimer();
|
|
922
|
+
const promise = this.connectionPromise;
|
|
923
|
+
try {
|
|
924
|
+
if (promise) {
|
|
925
|
+
this.connectionPromise = null;
|
|
926
|
+
await this.trackClosingConnection(await promise);
|
|
927
|
+
}
|
|
928
|
+
if (this.closingConnections.size > 0) {
|
|
929
|
+
await Promise.all([...this.closingConnections]);
|
|
930
|
+
}
|
|
931
|
+
} catch {}
|
|
932
|
+
}
|
|
933
|
+
acquireConnection() {
|
|
934
|
+
if (this.connectionPromise)
|
|
935
|
+
return this.connectionPromise;
|
|
936
|
+
const promise = this.openConnection().then((connection) => {
|
|
937
|
+
connection.detachDisconnect = connection.client.onDisconnect(() => {
|
|
938
|
+
this.discardConnection(promise, connection);
|
|
939
|
+
});
|
|
940
|
+
return connection;
|
|
941
|
+
}, (error) => {
|
|
942
|
+
if (this.connectionPromise === promise) {
|
|
943
|
+
this.connectionPromise = null;
|
|
944
|
+
}
|
|
945
|
+
throw error;
|
|
946
|
+
});
|
|
947
|
+
this.connectionPromise = promise;
|
|
948
|
+
return promise;
|
|
949
|
+
}
|
|
950
|
+
async openConnection() {
|
|
951
|
+
const ownedConnection = this.options.url ? null : await this.options.connect?.() ?? null;
|
|
810
952
|
const url = this.options.url ?? ownedConnection?.url;
|
|
811
953
|
if (!url) {
|
|
812
954
|
throw new Error("App-server management requires a url or connect hook.");
|
|
813
955
|
}
|
|
956
|
+
const unregister = registerManagementTransport(url, this);
|
|
814
957
|
let client = null;
|
|
815
958
|
try {
|
|
816
|
-
client = createAppServerClient({
|
|
959
|
+
client = applyUniqueRequestIds(createAppServerClient({
|
|
817
960
|
url,
|
|
818
961
|
...this.options.authToken !== undefined ? { authToken: this.options.authToken } : {},
|
|
819
962
|
...this.options.WebSocket ? {
|
|
820
963
|
WebSocket: this.options.WebSocket
|
|
821
964
|
} : {},
|
|
822
965
|
...this.options.requestTimeoutMs !== undefined ? { requestTimeoutMs: this.options.requestTimeoutMs } : {}
|
|
823
|
-
});
|
|
966
|
+
}));
|
|
824
967
|
await client.connect();
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
968
|
+
} catch (error) {
|
|
969
|
+
try {
|
|
970
|
+
if (client) {
|
|
971
|
+
const controlClosed = waitForSocketClose(client.control);
|
|
972
|
+
client.close();
|
|
973
|
+
ownedConnection?.close();
|
|
974
|
+
await controlClosed;
|
|
975
|
+
} else {
|
|
976
|
+
ownedConnection?.close();
|
|
977
|
+
}
|
|
978
|
+
} catch {} finally {
|
|
979
|
+
unregister();
|
|
980
|
+
}
|
|
981
|
+
throw error;
|
|
837
982
|
}
|
|
983
|
+
return {
|
|
984
|
+
client,
|
|
985
|
+
ownedConnection,
|
|
986
|
+
detachDisconnect: () => {},
|
|
987
|
+
unregister
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
discardConnection(promise, connection) {
|
|
991
|
+
if (this.connectionPromise === promise) {
|
|
992
|
+
this.connectionPromise = null;
|
|
993
|
+
this.clearIdleTimer();
|
|
994
|
+
}
|
|
995
|
+
this.trackClosingConnection(connection);
|
|
996
|
+
}
|
|
997
|
+
trackClosingConnection(connection) {
|
|
998
|
+
const closing = closeConnection(connection);
|
|
999
|
+
this.closingConnections.add(closing);
|
|
1000
|
+
closing.then(() => this.closingConnections.delete(closing), () => this.closingConnections.delete(closing));
|
|
1001
|
+
return closing;
|
|
1002
|
+
}
|
|
1003
|
+
scheduleIdleRelease() {
|
|
1004
|
+
if (!this.connectionPromise)
|
|
1005
|
+
return;
|
|
1006
|
+
this.clearIdleTimer();
|
|
1007
|
+
const timer = setTimeout(() => {
|
|
1008
|
+
this.idleTimer = null;
|
|
1009
|
+
this.releaseIdleConnection();
|
|
1010
|
+
}, this.idleLingerMs);
|
|
1011
|
+
this.idleTimer = timer;
|
|
1012
|
+
timer.unref?.();
|
|
1013
|
+
}
|
|
1014
|
+
clearIdleTimer() {
|
|
1015
|
+
if (this.idleTimer === null)
|
|
1016
|
+
return;
|
|
1017
|
+
clearTimeout(this.idleTimer);
|
|
1018
|
+
this.idleTimer = null;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
async function closeConnection(connection) {
|
|
1022
|
+
connection.detachDisconnect();
|
|
1023
|
+
const controlClosed = waitForSocketClose(connection.client.control);
|
|
1024
|
+
try {
|
|
1025
|
+
connection.client.close();
|
|
1026
|
+
connection.ownedConnection?.close();
|
|
1027
|
+
await controlClosed;
|
|
1028
|
+
} finally {
|
|
1029
|
+
connection.unregister();
|
|
838
1030
|
}
|
|
839
1031
|
}
|
|
1032
|
+
function waitForSocketClose(socket) {
|
|
1033
|
+
if (socket.readyState === 3)
|
|
1034
|
+
return Promise.resolve();
|
|
1035
|
+
return new Promise((resolve) => {
|
|
1036
|
+
let settled = false;
|
|
1037
|
+
let detach = () => {};
|
|
1038
|
+
const finish = () => {
|
|
1039
|
+
if (settled)
|
|
1040
|
+
return;
|
|
1041
|
+
settled = true;
|
|
1042
|
+
clearTimeout(timeout);
|
|
1043
|
+
detach();
|
|
1044
|
+
resolve();
|
|
1045
|
+
};
|
|
1046
|
+
if (socket.addEventListener) {
|
|
1047
|
+
socket.addEventListener("close", finish);
|
|
1048
|
+
detach = () => socket.removeEventListener?.("close", finish);
|
|
1049
|
+
} else if (socket.once) {
|
|
1050
|
+
socket.once("close", finish);
|
|
1051
|
+
detach = () => socket.off?.("close", finish);
|
|
1052
|
+
} else if (socket.on) {
|
|
1053
|
+
socket.on("close", finish);
|
|
1054
|
+
detach = () => socket.off?.("close", finish);
|
|
1055
|
+
} else {
|
|
1056
|
+
resolve();
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
const timeout = setTimeout(finish, 1000);
|
|
1060
|
+
timeout.unref?.();
|
|
1061
|
+
if (socket.readyState === 3)
|
|
1062
|
+
finish();
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
840
1065
|
|
|
841
1066
|
// node_modules/@letta-ai/letta-code/dist/agent-presets.js
|
|
842
1067
|
var LETTA_CODE_ORIGIN_TAG = "origin:letta-code";
|
|
@@ -5914,6 +6139,7 @@ class RemoteClientSessionCore {
|
|
|
5914
6139
|
_modelSettings = null;
|
|
5915
6140
|
label;
|
|
5916
6141
|
requestTimeoutMs;
|
|
6142
|
+
initializePromise = null;
|
|
5917
6143
|
streamQueue = [];
|
|
5918
6144
|
streamResolvers = [];
|
|
5919
6145
|
removeMessageHandler = null;
|
|
@@ -5931,43 +6157,72 @@ class RemoteClientSessionCore {
|
|
|
5931
6157
|
this.requestTimeoutMs = config.requestTimeoutMs;
|
|
5932
6158
|
}
|
|
5933
6159
|
async initialize() {
|
|
6160
|
+
if (this.closed) {
|
|
6161
|
+
throw new Error("Session is closed");
|
|
6162
|
+
}
|
|
6163
|
+
if (this.initializePromise) {
|
|
6164
|
+
return this.initializePromise;
|
|
6165
|
+
}
|
|
5934
6166
|
if (this.initialized) {
|
|
5935
6167
|
throw new Error("Session already initialized");
|
|
5936
6168
|
}
|
|
6169
|
+
const attempt = this.performInitialize();
|
|
6170
|
+
const memo = attempt.catch((error) => {
|
|
6171
|
+
this.cleanupFailedInitialize();
|
|
6172
|
+
throw error;
|
|
6173
|
+
}).finally(() => {
|
|
6174
|
+
if (this.initializePromise === memo) {
|
|
6175
|
+
this.initializePromise = null;
|
|
6176
|
+
}
|
|
6177
|
+
});
|
|
6178
|
+
this.initializePromise = memo;
|
|
6179
|
+
return memo;
|
|
6180
|
+
}
|
|
6181
|
+
async performInitialize() {
|
|
6182
|
+
const init = await this.initializeRuntimeController();
|
|
6183
|
+
this.controller = init.controller;
|
|
6184
|
+
this.runtime = init.runtime;
|
|
6185
|
+
this._agentId = init.runtime.agent_id;
|
|
6186
|
+
this._conversationId = init.runtime.conversation_id;
|
|
6187
|
+
this._sessionId = `${init.runtime.agent_id}:${init.runtime.conversation_id}`;
|
|
6188
|
+
this._modelSettings = init.modelSettings ?? null;
|
|
6189
|
+
this._model = typeof init.model === "string" ? init.model : typeof this._modelSettings?.model === "string" ? this._modelSettings.model : "";
|
|
6190
|
+
this.toolNames = init.tools;
|
|
6191
|
+
this.removeMessageHandler = this.controller.onMessage(this.handleProtocolMessage);
|
|
6192
|
+
await this.afterRuntimeInitialized();
|
|
6193
|
+
await this.applyPostInitializeOptions();
|
|
5937
6194
|
if (this.closed) {
|
|
5938
6195
|
throw new Error("Session is closed");
|
|
5939
6196
|
}
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
this.
|
|
5945
|
-
|
|
5946
|
-
this.
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
await this.afterRuntimeInitialized();
|
|
5953
|
-
await this.applyPostInitializeOptions();
|
|
5954
|
-
const initMessage = {
|
|
5955
|
-
type: "init",
|
|
5956
|
-
agentId: init.runtime.agent_id,
|
|
5957
|
-
sessionId: this._sessionId,
|
|
5958
|
-
conversationId: init.runtime.conversation_id,
|
|
5959
|
-
model: this._model
|
|
5960
|
-
};
|
|
5961
|
-
if (this.toolNames !== undefined)
|
|
5962
|
-
initMessage.tools = this.toolNames;
|
|
5963
|
-
if (init.skillSources !== undefined) {
|
|
5964
|
-
initMessage.skillSources = init.skillSources;
|
|
5965
|
-
}
|
|
5966
|
-
return initMessage;
|
|
5967
|
-
} catch (error) {
|
|
5968
|
-
this.close();
|
|
5969
|
-
throw error;
|
|
6197
|
+
this.initialized = true;
|
|
6198
|
+
const initMessage = {
|
|
6199
|
+
type: "init",
|
|
6200
|
+
agentId: init.runtime.agent_id,
|
|
6201
|
+
sessionId: this._sessionId,
|
|
6202
|
+
conversationId: init.runtime.conversation_id,
|
|
6203
|
+
model: this._model
|
|
6204
|
+
};
|
|
6205
|
+
if (this.toolNames !== undefined)
|
|
6206
|
+
initMessage.tools = this.toolNames;
|
|
6207
|
+
if (init.skillSources !== undefined) {
|
|
6208
|
+
initMessage.skillSources = init.skillSources;
|
|
5970
6209
|
}
|
|
6210
|
+
return initMessage;
|
|
6211
|
+
}
|
|
6212
|
+
cleanupFailedInitialize() {
|
|
6213
|
+
this.removeMessageHandler?.();
|
|
6214
|
+
this.removeMessageHandler = null;
|
|
6215
|
+
this.controller?.close();
|
|
6216
|
+
this.controller = null;
|
|
6217
|
+
this.onCoreClose();
|
|
6218
|
+
this.runtime = null;
|
|
6219
|
+
this._agentId = null;
|
|
6220
|
+
this._conversationId = null;
|
|
6221
|
+
this._sessionId = null;
|
|
6222
|
+
this._modelSettings = null;
|
|
6223
|
+
this._model = "";
|
|
6224
|
+
this.toolNames = undefined;
|
|
6225
|
+
this.initialized = false;
|
|
5971
6226
|
}
|
|
5972
6227
|
async send(message) {
|
|
5973
6228
|
if (!this.initialized) {
|
|
@@ -6064,6 +6319,12 @@ class RemoteClientSessionCore {
|
|
|
6064
6319
|
if (!this.initialized) {
|
|
6065
6320
|
await this.initialize();
|
|
6066
6321
|
}
|
|
6322
|
+
if (!this.controller || !this.runtime) {
|
|
6323
|
+
throw new Error("Session is not initialized");
|
|
6324
|
+
}
|
|
6325
|
+
return this.applyModelUpdate(update);
|
|
6326
|
+
}
|
|
6327
|
+
async applyModelUpdate(update) {
|
|
6067
6328
|
if (!this.controller || !this.runtime) {
|
|
6068
6329
|
throw new Error("Session is not initialized");
|
|
6069
6330
|
}
|
|
@@ -6480,7 +6741,7 @@ class RemoteClientSessionCore {
|
|
|
6480
6741
|
if (this.mode.kind !== "session")
|
|
6481
6742
|
return;
|
|
6482
6743
|
if (this.mode.options.model !== undefined || this.mode.options.reasoningEffort !== undefined) {
|
|
6483
|
-
await this.
|
|
6744
|
+
await this.applyModelUpdate({
|
|
6484
6745
|
...this.mode.options.model !== undefined ? { model: this.mode.options.model } : {},
|
|
6485
6746
|
...this.mode.options.reasoningEffort !== undefined ? { reasoningEffort: this.mode.options.reasoningEffort } : {}
|
|
6486
6747
|
});
|
|
@@ -7243,13 +7504,15 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
7243
7504
|
return options.memfs !== false;
|
|
7244
7505
|
}
|
|
7245
7506
|
async initializeRuntimeController() {
|
|
7507
|
+
await this.remoteOptions.beforeConnect?.();
|
|
7246
7508
|
const url = await this.resolveAppServerUrl();
|
|
7247
|
-
|
|
7509
|
+
await releaseAppServerManagementConnections(url);
|
|
7510
|
+
const client = applyUniqueRequestIds(createAppServerClient({
|
|
7248
7511
|
url,
|
|
7249
7512
|
...this.remoteOptions.authToken !== undefined ? { authToken: this.remoteOptions.authToken } : {},
|
|
7250
7513
|
...this.remoteOptions.WebSocket ? { WebSocket: this.remoteOptions.WebSocket } : {},
|
|
7251
7514
|
...this.remoteOptions.requestTimeoutMs !== undefined ? { requestTimeoutMs: this.remoteOptions.requestTimeoutMs } : {}
|
|
7252
|
-
});
|
|
7515
|
+
}));
|
|
7253
7516
|
this.removeControlRequestHandler = registerAppServerControlRequestHandler({
|
|
7254
7517
|
client,
|
|
7255
7518
|
getRuntime: () => this.runtime,
|
|
@@ -8120,14 +8383,14 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
8120
8383
|
apiKey,
|
|
8121
8384
|
authMode: this.cloudOptions.webSocketAuth ?? "header"
|
|
8122
8385
|
});
|
|
8123
|
-
const client = createAppServerClient({
|
|
8386
|
+
const client = applyUniqueRequestIds(createAppServerClient({
|
|
8124
8387
|
url,
|
|
8125
8388
|
WebSocket: createCloudStatusWebSocketConstructor({
|
|
8126
8389
|
cloudOptions: this.cloudOptions,
|
|
8127
8390
|
runtime: resolved.runtime
|
|
8128
8391
|
}),
|
|
8129
8392
|
requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
|
|
8130
|
-
});
|
|
8393
|
+
}));
|
|
8131
8394
|
this.removeControlRequestHandler = registerAppServerControlRequestHandler({
|
|
8132
8395
|
client,
|
|
8133
8396
|
getRuntime: () => this.runtime,
|
|
@@ -8865,6 +9128,10 @@ class LettaAgentClientBase {
|
|
|
8865
9128
|
if (requestTimeoutMs !== undefined && (!Number.isInteger(requestTimeoutMs) || requestTimeoutMs <= 0)) {
|
|
8866
9129
|
throw new Error("Invalid appServer.requestTimeoutMs. Expected a positive integer.");
|
|
8867
9130
|
}
|
|
9131
|
+
const idleLingerMs = localOptions.appServer?.idleLingerMs;
|
|
9132
|
+
if (idleLingerMs !== undefined && (!Number.isInteger(idleLingerMs) || idleLingerMs < 0)) {
|
|
9133
|
+
throw new Error("Invalid appServer.idleLingerMs. Expected a non-negative integer.");
|
|
9134
|
+
}
|
|
8868
9135
|
const startupTimeoutMs = localOptions.appServer?.startupTimeoutMs;
|
|
8869
9136
|
if (startupTimeoutMs !== undefined && (!Number.isInteger(startupTimeoutMs) || startupTimeoutMs <= 0)) {
|
|
8870
9137
|
throw new Error("Invalid appServer.startupTimeoutMs. Expected a positive integer.");
|
|
@@ -8877,6 +9144,9 @@ class LettaAgentClientBase {
|
|
|
8877
9144
|
if (options.requestTimeoutMs !== undefined && (!Number.isInteger(options.requestTimeoutMs) || options.requestTimeoutMs <= 0)) {
|
|
8878
9145
|
throw new Error("Invalid requestTimeoutMs. Expected a positive integer.");
|
|
8879
9146
|
}
|
|
9147
|
+
if (options.idleLingerMs !== undefined && (!Number.isInteger(options.idleLingerMs) || options.idleLingerMs < 0)) {
|
|
9148
|
+
throw new Error("Invalid idleLingerMs. Expected a non-negative integer.");
|
|
9149
|
+
}
|
|
8880
9150
|
}
|
|
8881
9151
|
if (this.backend === "cloud") {
|
|
8882
9152
|
validateCloudClientOptions(options);
|
|
@@ -8891,7 +9161,7 @@ class LettaAgentClientBase {
|
|
|
8891
9161
|
}
|
|
8892
9162
|
validateCreateAgentOptions(options);
|
|
8893
9163
|
if (this.backend === "remote") {
|
|
8894
|
-
const session = new AppServerSession(this.
|
|
9164
|
+
const session = new AppServerSession(this.appServerSessionOptions(), {
|
|
8895
9165
|
kind: "create-agent",
|
|
8896
9166
|
options
|
|
8897
9167
|
});
|
|
@@ -8914,7 +9184,7 @@ class LettaAgentClientBase {
|
|
|
8914
9184
|
if (!agentId) {
|
|
8915
9185
|
throw new Error("App-server createSession() requires an agent id. Call createAgent() first or pass an agent id.");
|
|
8916
9186
|
}
|
|
8917
|
-
return new AppServerSession(this.
|
|
9187
|
+
return new AppServerSession(this.appServerSessionOptions(), {
|
|
8918
9188
|
kind: "session",
|
|
8919
9189
|
agentId,
|
|
8920
9190
|
newConversation: true,
|
|
@@ -8940,13 +9210,13 @@ class LettaAgentClientBase {
|
|
|
8940
9210
|
validateCreateSessionOptions(sessionOptions);
|
|
8941
9211
|
if (this.backend === "remote") {
|
|
8942
9212
|
if (looksLikeConversationId(id)) {
|
|
8943
|
-
return new AppServerSession(this.
|
|
9213
|
+
return new AppServerSession(this.appServerSessionOptions(), {
|
|
8944
9214
|
kind: "session",
|
|
8945
9215
|
conversationId: id,
|
|
8946
9216
|
options
|
|
8947
9217
|
});
|
|
8948
9218
|
}
|
|
8949
|
-
return new AppServerSession(this.
|
|
9219
|
+
return new AppServerSession(this.appServerSessionOptions(), {
|
|
8950
9220
|
kind: "session",
|
|
8951
9221
|
agentId: id,
|
|
8952
9222
|
defaultConversation: true,
|
|
@@ -9045,6 +9315,12 @@ class LettaAgentClientBase {
|
|
|
9045
9315
|
}
|
|
9046
9316
|
return this.options;
|
|
9047
9317
|
}
|
|
9318
|
+
appServerSessionOptions() {
|
|
9319
|
+
return {
|
|
9320
|
+
...this.remoteOptions(),
|
|
9321
|
+
beforeConnect: () => this.releaseIdleManagementConnection()
|
|
9322
|
+
};
|
|
9323
|
+
}
|
|
9048
9324
|
getRepositoriesClient() {
|
|
9049
9325
|
if (this.backend !== "cloud") {
|
|
9050
9326
|
throw new Error('client.repositories is only available with backend: "cloud".');
|
|
@@ -9052,6 +9328,9 @@ class LettaAgentClientBase {
|
|
|
9052
9328
|
this.repositoriesClient ??= new RepositoriesClient(this.cloudOptions());
|
|
9053
9329
|
return this.repositoriesClient;
|
|
9054
9330
|
}
|
|
9331
|
+
async releaseIdleManagementConnection() {
|
|
9332
|
+
await this.managementTransport?.releaseIdleConnection?.();
|
|
9333
|
+
}
|
|
9055
9334
|
getManagementTransport() {
|
|
9056
9335
|
if (this.managementTransport)
|
|
9057
9336
|
return this.managementTransport;
|
|
@@ -9201,7 +9480,7 @@ ${output.trim()}` : ""}`));
|
|
|
9201
9480
|
}
|
|
9202
9481
|
|
|
9203
9482
|
// src/local-app-server-session.ts
|
|
9204
|
-
function createLocalAppServerSession(options, mode) {
|
|
9483
|
+
function createLocalAppServerSession(options, mode, beforeConnect) {
|
|
9205
9484
|
const appServer = options ?? {};
|
|
9206
9485
|
const sessionOptions = {
|
|
9207
9486
|
...appServer.url !== undefined ? { url: appServer.url } : {
|
|
@@ -9214,7 +9493,8 @@ function createLocalAppServerSession(options, mode) {
|
|
|
9214
9493
|
},
|
|
9215
9494
|
...appServer.WebSocket !== undefined ? { WebSocket: appServer.WebSocket } : {},
|
|
9216
9495
|
...appServer.requestTimeoutMs !== undefined ? { requestTimeoutMs: appServer.requestTimeoutMs } : {},
|
|
9217
|
-
...appServer.pinGlobalAgent !== undefined ? { pinGlobalAgent: appServer.pinGlobalAgent } : {}
|
|
9496
|
+
...appServer.pinGlobalAgent !== undefined ? { pinGlobalAgent: appServer.pinGlobalAgent } : {},
|
|
9497
|
+
...beforeConnect ? { beforeConnect } : {}
|
|
9218
9498
|
};
|
|
9219
9499
|
return new AppServerSession(sessionOptions, mode);
|
|
9220
9500
|
}
|
|
@@ -9614,6 +9894,8 @@ class Session {
|
|
|
9614
9894
|
_sessionId = null;
|
|
9615
9895
|
_conversationId = null;
|
|
9616
9896
|
initialized = false;
|
|
9897
|
+
closed = false;
|
|
9898
|
+
initializePromise = null;
|
|
9617
9899
|
externalTools = new Map;
|
|
9618
9900
|
streamQueue = [];
|
|
9619
9901
|
streamResolvers = [];
|
|
@@ -9636,9 +9918,28 @@ class Session {
|
|
|
9636
9918
|
}
|
|
9637
9919
|
}
|
|
9638
9920
|
async initialize() {
|
|
9921
|
+
if (this.closed) {
|
|
9922
|
+
throw new Error("Session is closed");
|
|
9923
|
+
}
|
|
9924
|
+
if (this.initializePromise) {
|
|
9925
|
+
return this.initializePromise;
|
|
9926
|
+
}
|
|
9639
9927
|
if (this.initialized) {
|
|
9640
9928
|
throw new Error("Session already initialized");
|
|
9641
9929
|
}
|
|
9930
|
+
const attempt = this.performInitialize();
|
|
9931
|
+
const memo = attempt.catch((error) => {
|
|
9932
|
+
this.cleanupFailedInitialize();
|
|
9933
|
+
throw error;
|
|
9934
|
+
}).finally(() => {
|
|
9935
|
+
if (this.initializePromise === memo) {
|
|
9936
|
+
this.initializePromise = null;
|
|
9937
|
+
}
|
|
9938
|
+
});
|
|
9939
|
+
this.initializePromise = memo;
|
|
9940
|
+
return memo;
|
|
9941
|
+
}
|
|
9942
|
+
async performInitialize() {
|
|
9642
9943
|
sessionLog("init", "connecting transport...");
|
|
9643
9944
|
await this.transport.connect();
|
|
9644
9945
|
sessionLog("init", "transport connected, sending initialize request");
|
|
@@ -9663,11 +9964,14 @@ class Session {
|
|
|
9663
9964
|
this._agentId = initMsg.agent_id;
|
|
9664
9965
|
this._sessionId = initMsg.session_id;
|
|
9665
9966
|
this._conversationId = initMsg.conversation_id;
|
|
9666
|
-
this.initialized = true;
|
|
9667
|
-
this.startBackgroundPump();
|
|
9668
9967
|
if (this.externalTools.size > 0) {
|
|
9669
9968
|
await this.registerExternalTools();
|
|
9670
9969
|
}
|
|
9970
|
+
if (this.closed) {
|
|
9971
|
+
throw new Error("Session is closed");
|
|
9972
|
+
}
|
|
9973
|
+
this.initialized = true;
|
|
9974
|
+
this.startBackgroundPump();
|
|
9671
9975
|
const allTools = [
|
|
9672
9976
|
...initMsg.tools,
|
|
9673
9977
|
...Array.from(this.externalTools.keys())
|
|
@@ -9698,6 +10002,16 @@ ${stderr}` : "";
|
|
|
9698
10002
|
sessionLog("init", `ERROR: transport closed before init message received${detail}`);
|
|
9699
10003
|
throw new Error(`Failed to initialize session - no init message received${detail}`);
|
|
9700
10004
|
}
|
|
10005
|
+
cleanupFailedInitialize() {
|
|
10006
|
+
this.transport.close();
|
|
10007
|
+
this.closed = true;
|
|
10008
|
+
this.initialized = false;
|
|
10009
|
+
this._agentId = null;
|
|
10010
|
+
this._sessionId = null;
|
|
10011
|
+
this._conversationId = null;
|
|
10012
|
+
this.pumpClosed = true;
|
|
10013
|
+
this.resolveAllStreamWaiters(null);
|
|
10014
|
+
}
|
|
9701
10015
|
async send(message) {
|
|
9702
10016
|
if (!this.initialized) {
|
|
9703
10017
|
sessionLog("send", "auto-initializing (not yet initialized)");
|
|
@@ -10374,6 +10688,9 @@ ${stderr}` : "";
|
|
|
10374
10688
|
throw new Error("updateToolset() is not supported by this session. Use a Cloud, Remote, or local agent session.");
|
|
10375
10689
|
}
|
|
10376
10690
|
close() {
|
|
10691
|
+
if (this.closed)
|
|
10692
|
+
return;
|
|
10693
|
+
this.closed = true;
|
|
10377
10694
|
sessionLog("close", `closing session (agent=${this._agentId}, conversation=${this._conversationId})`);
|
|
10378
10695
|
this.transport.close();
|
|
10379
10696
|
this.pumpClosed = true;
|
|
@@ -10571,7 +10888,8 @@ class LettaAgentClient extends LettaAgentClientBase {
|
|
|
10571
10888
|
})
|
|
10572
10889
|
},
|
|
10573
10890
|
...localOptions?.WebSocket !== undefined ? { WebSocket: localOptions.WebSocket } : {},
|
|
10574
|
-
...localOptions?.requestTimeoutMs !== undefined ? { requestTimeoutMs: localOptions.requestTimeoutMs } : {}
|
|
10891
|
+
...localOptions?.requestTimeoutMs !== undefined ? { requestTimeoutMs: localOptions.requestTimeoutMs } : {},
|
|
10892
|
+
...localOptions?.idleLingerMs !== undefined ? { idleLingerMs: localOptions.idleLingerMs } : {}
|
|
10575
10893
|
});
|
|
10576
10894
|
}
|
|
10577
10895
|
async createLocalAgent(options) {
|
|
@@ -10580,7 +10898,7 @@ class LettaAgentClient extends LettaAgentClientBase {
|
|
|
10580
10898
|
const session2 = createLocalAppServerSession(localOptions.appServer, {
|
|
10581
10899
|
kind: "create-agent",
|
|
10582
10900
|
options
|
|
10583
|
-
});
|
|
10901
|
+
}, () => this.releaseIdleManagementConnection());
|
|
10584
10902
|
const initMsg2 = await session2.initialize();
|
|
10585
10903
|
session2.close();
|
|
10586
10904
|
return initMsg2.agentId;
|
|
@@ -10598,7 +10916,7 @@ class LettaAgentClient extends LettaAgentClientBase {
|
|
|
10598
10916
|
agentId,
|
|
10599
10917
|
newConversation: true,
|
|
10600
10918
|
options
|
|
10601
|
-
});
|
|
10919
|
+
}, () => this.releaseIdleManagementConnection());
|
|
10602
10920
|
}
|
|
10603
10921
|
if (agentId) {
|
|
10604
10922
|
return new Session({ ...sessionOptions, agentId, newConversation: true });
|
|
@@ -10613,14 +10931,14 @@ class LettaAgentClient extends LettaAgentClientBase {
|
|
|
10613
10931
|
kind: "session",
|
|
10614
10932
|
conversationId: id,
|
|
10615
10933
|
options
|
|
10616
|
-
});
|
|
10934
|
+
}, () => this.releaseIdleManagementConnection());
|
|
10617
10935
|
}
|
|
10618
10936
|
return createLocalAppServerSession(localOptions.appServer, {
|
|
10619
10937
|
kind: "session",
|
|
10620
10938
|
agentId: id,
|
|
10621
10939
|
defaultConversation: true,
|
|
10622
10940
|
options
|
|
10623
|
-
});
|
|
10941
|
+
}, () => this.releaseIdleManagementConnection());
|
|
10624
10942
|
}
|
|
10625
10943
|
if (looksLikeConversationId2(id)) {
|
|
10626
10944
|
return new Session({ ...sessionOptions, conversationId: id });
|
|
@@ -10888,4 +11206,4 @@ export {
|
|
|
10888
11206
|
CloudManagedSandboxExpiredError
|
|
10889
11207
|
};
|
|
10890
11208
|
|
|
10891
|
-
//# debugId=
|
|
11209
|
+
//# debugId=98DBA625B202A81364756E2164756E21
|