@letta-ai/letta-agent-sdk 0.2.1 → 0.2.5
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/README.md +65 -13
- package/dist/client.d.ts +5 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/cloud-session.d.ts +8 -0
- package/dist/cloud-session.d.ts.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +448 -77
- package/dist/index.js.map +8 -7
- package/dist/repositories.d.ts +32 -0
- package/dist/repositories.d.ts.map +1 -0
- package/dist/types.d.ts +80 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1354,6 +1354,249 @@ ${stderr}` : "";
|
|
|
1354
1354
|
}
|
|
1355
1355
|
}
|
|
1356
1356
|
|
|
1357
|
+
// src/repositories.ts
|
|
1358
|
+
var DEFAULT_CLOUD_API_BASE_URL = "https://api.letta.com";
|
|
1359
|
+
function getDefaultApiKey() {
|
|
1360
|
+
const env = globalThis.process?.env;
|
|
1361
|
+
return env?.LETTA_API_KEY ?? env?.LETTA_CLOUD_API_KEY;
|
|
1362
|
+
}
|
|
1363
|
+
function bearerTokenFromHeaders(headers) {
|
|
1364
|
+
const authorization = headers?.Authorization ?? headers?.authorization;
|
|
1365
|
+
if (!authorization)
|
|
1366
|
+
return;
|
|
1367
|
+
const match = /^Bearer\s+(.+)$/i.exec(authorization);
|
|
1368
|
+
return match?.[1];
|
|
1369
|
+
}
|
|
1370
|
+
function getCloudApiKey(options) {
|
|
1371
|
+
return options.apiKey ?? bearerTokenFromHeaders(options.headers) ?? getDefaultApiKey();
|
|
1372
|
+
}
|
|
1373
|
+
function getFetch(fetchOverride) {
|
|
1374
|
+
const resolved = fetchOverride ?? globalThis.fetch;
|
|
1375
|
+
if (!resolved)
|
|
1376
|
+
throw new Error("No fetch implementation available for cloud backend.");
|
|
1377
|
+
return resolved.bind(globalThis);
|
|
1378
|
+
}
|
|
1379
|
+
function normalizeCloudApiBaseUrl(url) {
|
|
1380
|
+
const parsed = new URL(url ?? DEFAULT_CLOUD_API_BASE_URL);
|
|
1381
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "");
|
|
1382
|
+
parsed.search = "";
|
|
1383
|
+
parsed.hash = "";
|
|
1384
|
+
return parsed.toString().replace(/\/$/, "");
|
|
1385
|
+
}
|
|
1386
|
+
function cloudHeaders(options) {
|
|
1387
|
+
const headers = {
|
|
1388
|
+
"Content-Type": "application/json",
|
|
1389
|
+
...options.headers ?? {}
|
|
1390
|
+
};
|
|
1391
|
+
const apiKey = getCloudApiKey(options);
|
|
1392
|
+
if (apiKey && !headers.Authorization && !headers.authorization) {
|
|
1393
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
1394
|
+
}
|
|
1395
|
+
return headers;
|
|
1396
|
+
}
|
|
1397
|
+
async function parseJsonResponse(response) {
|
|
1398
|
+
const text = await response.text();
|
|
1399
|
+
if (!text)
|
|
1400
|
+
return null;
|
|
1401
|
+
try {
|
|
1402
|
+
return JSON.parse(text);
|
|
1403
|
+
} catch {
|
|
1404
|
+
return text;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
function responseErrorMessage(body, fallback) {
|
|
1408
|
+
if (body && typeof body === "object") {
|
|
1409
|
+
const record = body;
|
|
1410
|
+
const message = record.message ?? record.error ?? record.detail;
|
|
1411
|
+
const reasonText = record.reason_text;
|
|
1412
|
+
const pieces = [message, reasonText].filter((value) => typeof value === "string" && value.length > 0);
|
|
1413
|
+
if (pieces.length > 0)
|
|
1414
|
+
return pieces.join(": ");
|
|
1415
|
+
}
|
|
1416
|
+
return fallback;
|
|
1417
|
+
}
|
|
1418
|
+
function assertOkResponse(response, body, action) {
|
|
1419
|
+
if (!response.ok) {
|
|
1420
|
+
throw new Error(responseErrorMessage(body, `${action} failed with HTTP ${response.status}`));
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
function optionalString(value) {
|
|
1424
|
+
return typeof value === "string" ? value : undefined;
|
|
1425
|
+
}
|
|
1426
|
+
function requireString(value, name) {
|
|
1427
|
+
if (typeof value !== "string")
|
|
1428
|
+
throw new Error(`Cloud repositories response missing ${name}.`);
|
|
1429
|
+
return value;
|
|
1430
|
+
}
|
|
1431
|
+
function toRepository(body) {
|
|
1432
|
+
if (!body || typeof body !== "object") {
|
|
1433
|
+
throw new Error("Cloud repositories response did not include a repository.");
|
|
1434
|
+
}
|
|
1435
|
+
const record = body;
|
|
1436
|
+
return {
|
|
1437
|
+
id: requireString(record.id, "id"),
|
|
1438
|
+
name: requireString(record.name, "name"),
|
|
1439
|
+
createdAt: requireString(record.created_at, "created_at"),
|
|
1440
|
+
updatedAt: requireString(record.updated_at, "updated_at")
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
function toFileMutation(body) {
|
|
1444
|
+
if (!body || typeof body !== "object") {
|
|
1445
|
+
throw new Error("Cloud repositories file response did not include file details.");
|
|
1446
|
+
}
|
|
1447
|
+
const record = body;
|
|
1448
|
+
return {
|
|
1449
|
+
path: requireString(record.path, "path"),
|
|
1450
|
+
contentSha256: requireString(record.content_sha256, "content_sha256"),
|
|
1451
|
+
commitSha: requireString(record.commit_sha, "commit_sha")
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
function addOptionalSearchParam(url, key, value) {
|
|
1455
|
+
if (value !== undefined)
|
|
1456
|
+
url.searchParams.set(key, String(value));
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
class RepositoriesClient {
|
|
1460
|
+
options;
|
|
1461
|
+
constructor(options) {
|
|
1462
|
+
this.options = options;
|
|
1463
|
+
}
|
|
1464
|
+
async create(params) {
|
|
1465
|
+
return toRepository(await this.request("/v1/repositories", "POST", { name: params.name }, "Cloud create repository"));
|
|
1466
|
+
}
|
|
1467
|
+
async list(params = {}) {
|
|
1468
|
+
const url = this.url("/v1/repositories");
|
|
1469
|
+
addOptionalSearchParam(url, "limit", params.limit);
|
|
1470
|
+
addOptionalSearchParam(url, "offset", params.offset);
|
|
1471
|
+
const body = await this.requestUrl(url, "GET", undefined, "Cloud list repositories");
|
|
1472
|
+
if (!body || typeof body !== "object") {
|
|
1473
|
+
throw new Error("Cloud list repositories response did not include repositories.");
|
|
1474
|
+
}
|
|
1475
|
+
const record = body;
|
|
1476
|
+
const repositories = Array.isArray(record.repositories) ? record.repositories.map(toRepository) : [];
|
|
1477
|
+
return {
|
|
1478
|
+
repositories,
|
|
1479
|
+
hasNextPage: record.has_next_page === true
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
async get(repositoryId) {
|
|
1483
|
+
return toRepository(await this.request(`/v1/repositories/${encodeURIComponent(repositoryId)}`, "GET", undefined, "Cloud get repository"));
|
|
1484
|
+
}
|
|
1485
|
+
async delete(repositoryId) {
|
|
1486
|
+
await this.request(`/v1/repositories/${encodeURIComponent(repositoryId)}`, "DELETE", undefined, "Cloud delete repository");
|
|
1487
|
+
}
|
|
1488
|
+
files = {
|
|
1489
|
+
list: async (repositoryId, params = {}) => {
|
|
1490
|
+
const url = this.url(`/v1/repositories/${encodeURIComponent(repositoryId)}/files`);
|
|
1491
|
+
addOptionalSearchParam(url, "path_prefix", params.pathPrefix);
|
|
1492
|
+
addOptionalSearchParam(url, "depth", params.depth);
|
|
1493
|
+
addOptionalSearchParam(url, "ref", params.ref);
|
|
1494
|
+
const body = await this.requestUrl(url, "GET", undefined, "Cloud list repository files");
|
|
1495
|
+
if (!body || typeof body !== "object") {
|
|
1496
|
+
throw new Error("Cloud list repository files response did not include files.");
|
|
1497
|
+
}
|
|
1498
|
+
const record = body;
|
|
1499
|
+
const files = Array.isArray(record.files) ? record.files.map((entry) => {
|
|
1500
|
+
if (!entry || typeof entry !== "object") {
|
|
1501
|
+
throw new Error("Cloud list repository files response included an invalid file entry.");
|
|
1502
|
+
}
|
|
1503
|
+
const file = entry;
|
|
1504
|
+
const type = file.type;
|
|
1505
|
+
if (type !== "file" && type !== "directory") {
|
|
1506
|
+
throw new Error("Cloud list repository files response included an invalid file type.");
|
|
1507
|
+
}
|
|
1508
|
+
return { path: requireString(file.path, "path"), type };
|
|
1509
|
+
}) : [];
|
|
1510
|
+
return { files, ref: requireString(record.ref, "ref") };
|
|
1511
|
+
},
|
|
1512
|
+
create: async (repositoryId, params) => toFileMutation(await this.request(`/v1/repositories/${encodeURIComponent(repositoryId)}/files`, "POST", { path: params.path, content: params.content }, "Cloud create repository file")),
|
|
1513
|
+
read: async (repositoryId, params) => {
|
|
1514
|
+
const url = this.url(`/v1/repositories/${encodeURIComponent(repositoryId)}/files/content`);
|
|
1515
|
+
url.searchParams.set("path", params.path);
|
|
1516
|
+
addOptionalSearchParam(url, "ref", params.ref);
|
|
1517
|
+
const body = await this.requestUrl(url, "GET", undefined, "Cloud read repository file");
|
|
1518
|
+
if (!body || typeof body !== "object") {
|
|
1519
|
+
throw new Error("Cloud read repository file response did not include file content.");
|
|
1520
|
+
}
|
|
1521
|
+
const record = body;
|
|
1522
|
+
return {
|
|
1523
|
+
path: requireString(record.path, "path"),
|
|
1524
|
+
content: requireString(record.content, "content"),
|
|
1525
|
+
contentSha256: requireString(record.content_sha256, "content_sha256"),
|
|
1526
|
+
ref: optionalString(record.ref)
|
|
1527
|
+
};
|
|
1528
|
+
},
|
|
1529
|
+
update: async (repositoryId, params) => toFileMutation(await this.request(`/v1/repositories/${encodeURIComponent(repositoryId)}/files/content`, "POST", {
|
|
1530
|
+
path: params.path,
|
|
1531
|
+
...params.content !== undefined ? { content: params.content } : {},
|
|
1532
|
+
...params.newPath !== undefined ? { new_path: params.newPath } : {},
|
|
1533
|
+
...params.precondition !== undefined ? {
|
|
1534
|
+
precondition: {
|
|
1535
|
+
type: "content_sha256",
|
|
1536
|
+
content_sha256: params.precondition.contentSha256
|
|
1537
|
+
}
|
|
1538
|
+
} : {}
|
|
1539
|
+
}, "Cloud update repository file")),
|
|
1540
|
+
delete: async (repositoryId, params) => {
|
|
1541
|
+
const body = await this.request(`/v1/repositories/${encodeURIComponent(repositoryId)}/files/content`, "DELETE", { path: params.path }, "Cloud delete repository file");
|
|
1542
|
+
if (!body || typeof body !== "object") {
|
|
1543
|
+
throw new Error("Cloud delete repository file response did not include delete details.");
|
|
1544
|
+
}
|
|
1545
|
+
const record = body;
|
|
1546
|
+
return { success: record.success === true, commitSha: requireString(record.commit_sha, "commit_sha") };
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
versions = {
|
|
1550
|
+
list: async (repositoryId, params = {}) => {
|
|
1551
|
+
const url = this.url(`/v1/repositories/${encodeURIComponent(repositoryId)}/versions`);
|
|
1552
|
+
addOptionalSearchParam(url, "path", params.path);
|
|
1553
|
+
addOptionalSearchParam(url, "limit", params.limit);
|
|
1554
|
+
const body = await this.requestUrl(url, "GET", undefined, "Cloud list repository versions");
|
|
1555
|
+
if (Array.isArray(body))
|
|
1556
|
+
return body;
|
|
1557
|
+
if (body && typeof body === "object") {
|
|
1558
|
+
const record = body;
|
|
1559
|
+
if (Array.isArray(record.commits))
|
|
1560
|
+
return record.commits;
|
|
1561
|
+
if (Array.isArray(record.versions))
|
|
1562
|
+
return record.versions;
|
|
1563
|
+
}
|
|
1564
|
+
return [];
|
|
1565
|
+
},
|
|
1566
|
+
get: async (repositoryId, sha, params) => {
|
|
1567
|
+
const url = this.url(`/v1/repositories/${encodeURIComponent(repositoryId)}/versions/${encodeURIComponent(sha)}`);
|
|
1568
|
+
url.searchParams.set("path", params.path);
|
|
1569
|
+
const body = await this.requestUrl(url, "GET", undefined, "Cloud get repository version");
|
|
1570
|
+
if (!body || typeof body !== "object") {
|
|
1571
|
+
throw new Error("Cloud get repository version response did not include file content.");
|
|
1572
|
+
}
|
|
1573
|
+
const record = body;
|
|
1574
|
+
return {
|
|
1575
|
+
path: requireString(record.path, "path"),
|
|
1576
|
+
content: requireString(record.content, "content"),
|
|
1577
|
+
contentSha256: requireString(record.content_sha256, "content_sha256"),
|
|
1578
|
+
ref: requireString(record.sha, "sha")
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
url(path) {
|
|
1583
|
+
return new URL(`${normalizeCloudApiBaseUrl(this.options.apiBaseUrl)}${path}`);
|
|
1584
|
+
}
|
|
1585
|
+
async request(path, method, body, action) {
|
|
1586
|
+
return this.requestUrl(this.url(path), method, body, action);
|
|
1587
|
+
}
|
|
1588
|
+
async requestUrl(url, method, body, action) {
|
|
1589
|
+
const response = await getFetch(this.options.fetch)(url, {
|
|
1590
|
+
method,
|
|
1591
|
+
headers: cloudHeaders(this.options),
|
|
1592
|
+
...body !== undefined ? { body: JSON.stringify(body) } : {}
|
|
1593
|
+
});
|
|
1594
|
+
const parsed = await parseJsonResponse(response);
|
|
1595
|
+
assertOkResponse(response, parsed, action);
|
|
1596
|
+
return parsed;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1357
1600
|
// node_modules/@letta-ai/letta-code/dist/app-server-client.js
|
|
1358
1601
|
var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
1359
1602
|
var WEBSOCKET_OPEN_STATE = 1;
|
|
@@ -2991,11 +3234,11 @@ function createAgentBody(options, settings = {}) {
|
|
|
2991
3234
|
if (options.systemPrompt !== undefined) {
|
|
2992
3235
|
if (typeof options.systemPrompt === "string") {
|
|
2993
3236
|
if (isPresetSystemPrompt(options.systemPrompt)) {
|
|
2994
|
-
throw new Error("
|
|
3237
|
+
throw new Error("createAgent() does not yet support system prompt presets for this backend.");
|
|
2995
3238
|
}
|
|
2996
3239
|
body.system = options.systemPrompt;
|
|
2997
3240
|
} else {
|
|
2998
|
-
throw new Error("
|
|
3241
|
+
throw new Error("createAgent() does not yet support system prompt preset objects for this backend.");
|
|
2999
3242
|
}
|
|
3000
3243
|
}
|
|
3001
3244
|
const memoryBlocks = [];
|
|
@@ -3479,20 +3722,20 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
3479
3722
|
}
|
|
3480
3723
|
|
|
3481
3724
|
// src/remote.ts
|
|
3482
|
-
function
|
|
3725
|
+
function getDefaultApiKey2() {
|
|
3483
3726
|
if (typeof process === "undefined") {
|
|
3484
3727
|
return;
|
|
3485
3728
|
}
|
|
3486
3729
|
return process.env.LETTA_API_KEY;
|
|
3487
3730
|
}
|
|
3488
3731
|
function createHeaders(options) {
|
|
3489
|
-
const apiKey = options.apiKey ??
|
|
3732
|
+
const apiKey = options.apiKey ?? getDefaultApiKey2();
|
|
3490
3733
|
return {
|
|
3491
3734
|
...apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
|
|
3492
3735
|
...options.headers ?? {}
|
|
3493
3736
|
};
|
|
3494
3737
|
}
|
|
3495
|
-
function
|
|
3738
|
+
function getFetch2(options) {
|
|
3496
3739
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3497
3740
|
if (!fetchImpl) {
|
|
3498
3741
|
throw new Error("Remote environments require a fetch implementation");
|
|
@@ -3513,7 +3756,7 @@ function ensureOnline(environment, target) {
|
|
|
3513
3756
|
target
|
|
3514
3757
|
};
|
|
3515
3758
|
}
|
|
3516
|
-
async function
|
|
3759
|
+
async function parseJsonResponse2(response) {
|
|
3517
3760
|
const text = await response.text();
|
|
3518
3761
|
const body = text ? JSON.parse(text) : null;
|
|
3519
3762
|
if (!response.ok) {
|
|
@@ -3530,18 +3773,18 @@ class RemoteEnvironmentClient {
|
|
|
3530
3773
|
constructor(options = {}) {
|
|
3531
3774
|
this.options = options;
|
|
3532
3775
|
this.baseUrl = normalizeBaseUrl2(options.baseUrl);
|
|
3533
|
-
this.fetchImpl =
|
|
3776
|
+
this.fetchImpl = getFetch2(options);
|
|
3534
3777
|
}
|
|
3535
3778
|
async listEnvironments() {
|
|
3536
3779
|
const url = new URL(`${this.baseUrl}/v1/environments`);
|
|
3537
3780
|
const response = await this.fetchImpl(url, {
|
|
3538
3781
|
headers: createHeaders(this.options)
|
|
3539
3782
|
});
|
|
3540
|
-
return
|
|
3783
|
+
return parseJsonResponse2(response);
|
|
3541
3784
|
}
|
|
3542
3785
|
async getEnvironmentByDeviceId(deviceId) {
|
|
3543
3786
|
const response = await this.fetchImpl(`${this.baseUrl}/v1/environments/${encodeURIComponent(deviceId)}`, { headers: createHeaders(this.options) });
|
|
3544
|
-
return
|
|
3787
|
+
return parseJsonResponse2(response);
|
|
3545
3788
|
}
|
|
3546
3789
|
async resolveEnvironment(target) {
|
|
3547
3790
|
if ("connectionId" in target) {
|
|
@@ -3574,7 +3817,7 @@ class RemoteEnvironmentClient {
|
|
|
3574
3817
|
}
|
|
3575
3818
|
|
|
3576
3819
|
// src/cloud-session.ts
|
|
3577
|
-
var
|
|
3820
|
+
var DEFAULT_CLOUD_API_BASE_URL2 = "https://api.letta.com";
|
|
3578
3821
|
var DEFAULT_TURN_TIMEOUT_MS = 120000;
|
|
3579
3822
|
var DEFAULT_PING_INTERVAL_MS = 30000;
|
|
3580
3823
|
var DEFAULT_SANDBOX_TTL_MINUTES = 5;
|
|
@@ -3582,25 +3825,27 @@ var MIN_SANDBOX_TTL_MINUTES = 1;
|
|
|
3582
3825
|
var MAX_SANDBOX_TTL_MINUTES = 60;
|
|
3583
3826
|
var DEFAULT_SANDBOX_READY_TIMEOUT_MS = 120000;
|
|
3584
3827
|
var DEFAULT_SANDBOX_READY_POLL_INTERVAL_MS = 1000;
|
|
3828
|
+
var DEFAULT_REPOSITORY_ATTACH_TIMEOUT_MS = 1e4;
|
|
3829
|
+
var DEFAULT_REPOSITORY_ATTACH_POLL_INTERVAL_MS = 250;
|
|
3585
3830
|
var SDK_AGENT_ORIGIN = "@letta-ai/letta-agent-sdk";
|
|
3586
3831
|
|
|
3587
3832
|
class CloudManagedSandboxOwnershipError extends Error {
|
|
3588
3833
|
}
|
|
3589
|
-
function
|
|
3834
|
+
function getDefaultApiKey3() {
|
|
3590
3835
|
const env = globalThis.process?.env;
|
|
3591
3836
|
return env?.LETTA_API_KEY ?? env?.LETTA_CLOUD_API_KEY;
|
|
3592
3837
|
}
|
|
3593
|
-
function
|
|
3838
|
+
function bearerTokenFromHeaders2(headers) {
|
|
3594
3839
|
const authorization = headers?.Authorization ?? headers?.authorization;
|
|
3595
3840
|
if (!authorization)
|
|
3596
3841
|
return;
|
|
3597
3842
|
const match = /^Bearer\s+(.+)$/i.exec(authorization);
|
|
3598
3843
|
return match?.[1];
|
|
3599
3844
|
}
|
|
3600
|
-
function
|
|
3601
|
-
return options.apiKey ??
|
|
3845
|
+
function getCloudApiKey2(options) {
|
|
3846
|
+
return options.apiKey ?? bearerTokenFromHeaders2(options.headers) ?? getDefaultApiKey3();
|
|
3602
3847
|
}
|
|
3603
|
-
function
|
|
3848
|
+
function getFetch3(fetchOverride) {
|
|
3604
3849
|
const resolved = fetchOverride ?? globalThis.fetch;
|
|
3605
3850
|
if (!resolved) {
|
|
3606
3851
|
throw new Error("No fetch implementation available for cloud backend.");
|
|
@@ -3614,19 +3859,19 @@ function getWebSocketConstructor(websocketOverride) {
|
|
|
3614
3859
|
}
|
|
3615
3860
|
return resolved;
|
|
3616
3861
|
}
|
|
3617
|
-
function
|
|
3618
|
-
const parsed = new URL(url ??
|
|
3862
|
+
function normalizeCloudApiBaseUrl2(url) {
|
|
3863
|
+
const parsed = new URL(url ?? DEFAULT_CLOUD_API_BASE_URL2);
|
|
3619
3864
|
parsed.pathname = parsed.pathname.replace(/\/+$/, "");
|
|
3620
3865
|
parsed.search = "";
|
|
3621
3866
|
parsed.hash = "";
|
|
3622
3867
|
return parsed.toString().replace(/\/$/, "");
|
|
3623
3868
|
}
|
|
3624
|
-
function
|
|
3869
|
+
function cloudHeaders2(options) {
|
|
3625
3870
|
const headers = {
|
|
3626
3871
|
"Content-Type": "application/json",
|
|
3627
3872
|
...options.headers ?? {}
|
|
3628
3873
|
};
|
|
3629
|
-
const apiKey =
|
|
3874
|
+
const apiKey = getCloudApiKey2(options);
|
|
3630
3875
|
if (apiKey && !headers.Authorization && !headers.authorization) {
|
|
3631
3876
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
3632
3877
|
}
|
|
@@ -3636,12 +3881,12 @@ function cloudWebSocketHeaders(options) {
|
|
|
3636
3881
|
const headers = { ...options.headers ?? {} };
|
|
3637
3882
|
delete headers.authorization;
|
|
3638
3883
|
delete headers.Authorization;
|
|
3639
|
-
const apiKey =
|
|
3884
|
+
const apiKey = getCloudApiKey2(options);
|
|
3640
3885
|
if (apiKey)
|
|
3641
3886
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
3642
3887
|
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
3643
3888
|
}
|
|
3644
|
-
async function
|
|
3889
|
+
async function parseJsonResponse3(response) {
|
|
3645
3890
|
const text = await response.text();
|
|
3646
3891
|
if (!text)
|
|
3647
3892
|
return null;
|
|
@@ -3651,7 +3896,7 @@ async function parseJsonResponse2(response) {
|
|
|
3651
3896
|
return text;
|
|
3652
3897
|
}
|
|
3653
3898
|
}
|
|
3654
|
-
function
|
|
3899
|
+
function responseErrorMessage2(body, fallback) {
|
|
3655
3900
|
if (body && typeof body === "object") {
|
|
3656
3901
|
const record = body;
|
|
3657
3902
|
const message = record.message ?? record.error ?? record.detail;
|
|
@@ -3662,9 +3907,9 @@ function responseErrorMessage(body, fallback) {
|
|
|
3662
3907
|
}
|
|
3663
3908
|
return fallback;
|
|
3664
3909
|
}
|
|
3665
|
-
function
|
|
3910
|
+
function assertOkResponse2(response, body, action) {
|
|
3666
3911
|
if (!response.ok) {
|
|
3667
|
-
throw new Error(
|
|
3912
|
+
throw new Error(responseErrorMessage2(body, `${action} failed with HTTP ${response.status}`));
|
|
3668
3913
|
}
|
|
3669
3914
|
}
|
|
3670
3915
|
function validatePositiveInteger(value, name) {
|
|
@@ -3724,7 +3969,7 @@ function environmentToRemoteTarget(environment) {
|
|
|
3724
3969
|
throw new Error("Unknown cloud environment selector.");
|
|
3725
3970
|
}
|
|
3726
3971
|
function buildCloudStatusWebSocketUrl(params) {
|
|
3727
|
-
const base = new URL(
|
|
3972
|
+
const base = new URL(normalizeCloudApiBaseUrl2(params.apiBaseUrl));
|
|
3728
3973
|
if (base.protocol === "http:") {
|
|
3729
3974
|
base.protocol = "ws:";
|
|
3730
3975
|
} else if (base.protocol === "https:") {
|
|
@@ -3771,7 +4016,7 @@ function messageEventData(event) {
|
|
|
3771
4016
|
function createCloudStatusWebSocketConstructor(params) {
|
|
3772
4017
|
const WebSocketCtor = getWebSocketConstructor(params.cloudOptions.WebSocket);
|
|
3773
4018
|
const authMode = params.cloudOptions.webSocketAuth ?? "header";
|
|
3774
|
-
const
|
|
4019
|
+
const cloudHeaders3 = authMode === "header" ? cloudWebSocketHeaders(params.cloudOptions) : undefined;
|
|
3775
4020
|
const pingIntervalMs = params.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS;
|
|
3776
4021
|
const state = {
|
|
3777
4022
|
runtime: params.runtime,
|
|
@@ -3791,7 +4036,7 @@ function createCloudStatusWebSocketConstructor(params) {
|
|
|
3791
4036
|
this.channel = new URL(url).searchParams.get("channel");
|
|
3792
4037
|
const mergedHeaders = authMode === "header" ? {
|
|
3793
4038
|
...options?.headers ?? {},
|
|
3794
|
-
...
|
|
4039
|
+
...cloudHeaders3 ?? {}
|
|
3795
4040
|
} : undefined;
|
|
3796
4041
|
const socketOptions = mergedHeaders && Object.keys(mergedHeaders).length > 0 ? { headers: mergedHeaders } : undefined;
|
|
3797
4042
|
this.socket = new WebSocketCtor(url, socketOptions);
|
|
@@ -3951,10 +4196,10 @@ function externalToolsByName(tools) {
|
|
|
3951
4196
|
}
|
|
3952
4197
|
function cloudHarnessAppServerOptions(clientOptions) {
|
|
3953
4198
|
const appServer = clientOptions.appServer;
|
|
3954
|
-
const apiKey =
|
|
4199
|
+
const apiKey = getCloudApiKey2(clientOptions);
|
|
3955
4200
|
const localEnv = {
|
|
3956
4201
|
...apiKey ? { LETTA_API_KEY: apiKey } : {},
|
|
3957
|
-
...clientOptions.apiBaseUrl ? { LETTA_BASE_URL:
|
|
4202
|
+
...clientOptions.apiBaseUrl ? { LETTA_BASE_URL: normalizeCloudApiBaseUrl2(clientOptions.apiBaseUrl) } : {}
|
|
3958
4203
|
};
|
|
3959
4204
|
return {
|
|
3960
4205
|
local: appServer?.url === undefined,
|
|
@@ -4013,6 +4258,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4013
4258
|
managedSandbox = null;
|
|
4014
4259
|
sandboxRefreshTimer = null;
|
|
4015
4260
|
sandboxRefreshInFlight = null;
|
|
4261
|
+
attachedRepositoryIds = new Set;
|
|
4016
4262
|
cloudMode;
|
|
4017
4263
|
constructor(cloudOptions, mode) {
|
|
4018
4264
|
super(mode, {
|
|
@@ -4028,7 +4274,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4028
4274
|
const resolved = await this.resolveRuntime();
|
|
4029
4275
|
const connection = await this.resolveConnectionForRuntime(resolved.runtime);
|
|
4030
4276
|
this.connectionId = connection.connectionId;
|
|
4031
|
-
const apiKey =
|
|
4277
|
+
const apiKey = getCloudApiKey2(this.cloudOptions);
|
|
4032
4278
|
const url = buildCloudStatusWebSocketUrl({
|
|
4033
4279
|
apiBaseUrl: this.cloudOptions.apiBaseUrl,
|
|
4034
4280
|
connectionId: connection.connectionId,
|
|
@@ -4076,6 +4322,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4076
4322
|
this.removeControlRequestHandler = null;
|
|
4077
4323
|
client.close();
|
|
4078
4324
|
await this.cleanupManagedSandbox();
|
|
4325
|
+
await this.cleanupSessionRepositories(resolved.runtime.agent_id);
|
|
4079
4326
|
throw error;
|
|
4080
4327
|
}
|
|
4081
4328
|
}
|
|
@@ -4123,16 +4370,12 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4123
4370
|
this.removeControlRequestHandler?.();
|
|
4124
4371
|
this.removeControlRequestHandler = null;
|
|
4125
4372
|
this.cleanupManagedSandbox();
|
|
4373
|
+
if (this.runtime?.agent_id)
|
|
4374
|
+
this.cleanupSessionRepositories(this.runtime.agent_id);
|
|
4126
4375
|
}
|
|
4127
4376
|
async resolveRuntime() {
|
|
4128
4377
|
let agentId = this.cloudMode.agentId;
|
|
4129
4378
|
let conversationId = this.cloudMode.conversationId;
|
|
4130
|
-
if (agentId && this.cloudMode.newConversation) {
|
|
4131
|
-
const conversation = await this.createConversation(agentId);
|
|
4132
|
-
conversationId = conversation.id;
|
|
4133
|
-
} else if (agentId && this.cloudMode.defaultConversation) {
|
|
4134
|
-
conversationId = "default";
|
|
4135
|
-
}
|
|
4136
4379
|
if (!agentId && conversationId) {
|
|
4137
4380
|
const conversation = await this.retrieveConversation(conversationId);
|
|
4138
4381
|
if (!conversation.agent_id) {
|
|
@@ -4140,34 +4383,134 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4140
4383
|
}
|
|
4141
4384
|
agentId = conversation.agent_id;
|
|
4142
4385
|
}
|
|
4143
|
-
if (!agentId
|
|
4386
|
+
if (!agentId) {
|
|
4387
|
+
throw new Error("Constellation createSession()/resumeSession() requires an agent id or conversation id.");
|
|
4388
|
+
}
|
|
4389
|
+
await this.attachSessionRepositories(agentId);
|
|
4390
|
+
if (this.cloudMode.newConversation) {
|
|
4391
|
+
const conversation = await this.createConversation(agentId);
|
|
4392
|
+
conversationId = conversation.id;
|
|
4393
|
+
} else if (this.cloudMode.defaultConversation) {
|
|
4394
|
+
conversationId = "default";
|
|
4395
|
+
}
|
|
4396
|
+
if (!conversationId) {
|
|
4144
4397
|
throw new Error("Constellation createSession()/resumeSession() requires an agent id or conversation id.");
|
|
4145
4398
|
}
|
|
4146
4399
|
return { runtime: { agent_id: agentId, conversation_id: conversationId } };
|
|
4147
4400
|
}
|
|
4401
|
+
async attachSessionRepositories(agentId) {
|
|
4402
|
+
const resources = this.repositoryResources();
|
|
4403
|
+
if (resources.length === 0)
|
|
4404
|
+
return;
|
|
4405
|
+
const existing = await this.listAgentRepositories(agentId);
|
|
4406
|
+
const existingIds = new Set(existing.map((repository) => repository.id));
|
|
4407
|
+
try {
|
|
4408
|
+
for (const resource of resources) {
|
|
4409
|
+
if (existingIds.has(resource.repositoryId) || this.attachedRepositoryIds.has(resource.repositoryId)) {
|
|
4410
|
+
continue;
|
|
4411
|
+
}
|
|
4412
|
+
await this.linkAgentRepository(agentId, resource.repositoryId);
|
|
4413
|
+
await this.waitForAgentRepository(agentId, resource.repositoryId);
|
|
4414
|
+
this.attachedRepositoryIds.add(resource.repositoryId);
|
|
4415
|
+
}
|
|
4416
|
+
} catch (error) {
|
|
4417
|
+
await this.cleanupSessionRepositories(agentId);
|
|
4418
|
+
throw error;
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
async cleanupSessionRepositories(agentId) {
|
|
4422
|
+
const repositoryIds = [...this.attachedRepositoryIds];
|
|
4423
|
+
this.attachedRepositoryIds.clear();
|
|
4424
|
+
await Promise.all(repositoryIds.map(async (repositoryId) => {
|
|
4425
|
+
try {
|
|
4426
|
+
await this.unlinkAgentRepository(agentId, repositoryId);
|
|
4427
|
+
} catch {}
|
|
4428
|
+
}));
|
|
4429
|
+
}
|
|
4430
|
+
repositoryResources() {
|
|
4431
|
+
const resources = this.cloudMode.options.resources ?? [];
|
|
4432
|
+
const seen = new Set;
|
|
4433
|
+
const result = [];
|
|
4434
|
+
for (const resource of resources) {
|
|
4435
|
+
if (resource.type !== "repository") {
|
|
4436
|
+
throw new Error(`Unsupported Cloud session resource type: ${String(resource.type)}`);
|
|
4437
|
+
}
|
|
4438
|
+
if (typeof resource.repositoryId !== "string" || resource.repositoryId.length === 0) {
|
|
4439
|
+
throw new Error("Cloud session repository resources require repositoryId.");
|
|
4440
|
+
}
|
|
4441
|
+
if (seen.has(resource.repositoryId))
|
|
4442
|
+
continue;
|
|
4443
|
+
seen.add(resource.repositoryId);
|
|
4444
|
+
result.push(resource);
|
|
4445
|
+
}
|
|
4446
|
+
return result;
|
|
4447
|
+
}
|
|
4448
|
+
async listAgentRepositories(agentId) {
|
|
4449
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4450
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4451
|
+
const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(agentId)}/repositories`, { headers: cloudHeaders2(this.cloudOptions) });
|
|
4452
|
+
const body = await parseJsonResponse3(response);
|
|
4453
|
+
assertOkResponse2(response, body, "Cloud list agent repositories");
|
|
4454
|
+
if (!body || typeof body !== "object")
|
|
4455
|
+
return [];
|
|
4456
|
+
const repositories = body.repositories;
|
|
4457
|
+
return Array.isArray(repositories) ? repositories.filter((repository) => repository !== null && typeof repository === "object" && typeof repository.id === "string") : [];
|
|
4458
|
+
}
|
|
4459
|
+
async waitForAgentRepository(agentId, repositoryId) {
|
|
4460
|
+
const deadline = Date.now() + DEFAULT_REPOSITORY_ATTACH_TIMEOUT_MS;
|
|
4461
|
+
while (true) {
|
|
4462
|
+
const repositories = await this.listAgentRepositories(agentId);
|
|
4463
|
+
if (repositories.some((repository) => repository.id === repositoryId))
|
|
4464
|
+
return;
|
|
4465
|
+
if (Date.now() >= deadline) {
|
|
4466
|
+
throw new Error(`Cloud attach agent repository did not become visible for ${agentId}: ${repositoryId}`);
|
|
4467
|
+
}
|
|
4468
|
+
await sleep(DEFAULT_REPOSITORY_ATTACH_POLL_INTERVAL_MS);
|
|
4469
|
+
}
|
|
4470
|
+
}
|
|
4471
|
+
async linkAgentRepository(agentId, repositoryId) {
|
|
4472
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4473
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4474
|
+
const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(agentId)}/repositories`, {
|
|
4475
|
+
method: "POST",
|
|
4476
|
+
headers: cloudHeaders2(this.cloudOptions),
|
|
4477
|
+
body: JSON.stringify({ repository_id: repositoryId })
|
|
4478
|
+
});
|
|
4479
|
+
const body = await parseJsonResponse3(response);
|
|
4480
|
+
assertOkResponse2(response, body, "Cloud attach agent repository");
|
|
4481
|
+
}
|
|
4482
|
+
async unlinkAgentRepository(agentId, repositoryId) {
|
|
4483
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4484
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4485
|
+
const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(agentId)}/repositories/${encodeURIComponent(repositoryId)}`, { method: "DELETE", headers: cloudHeaders2(this.cloudOptions) });
|
|
4486
|
+
const body = await parseJsonResponse3(response);
|
|
4487
|
+
if (response.status === 404)
|
|
4488
|
+
return;
|
|
4489
|
+
assertOkResponse2(response, body, "Cloud detach agent repository");
|
|
4490
|
+
}
|
|
4148
4491
|
async createConversation(agentId) {
|
|
4149
|
-
const fetchImpl =
|
|
4150
|
-
const baseUrl =
|
|
4492
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4493
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4151
4494
|
const url = new URL(`${baseUrl}/v1/conversations/`);
|
|
4152
4495
|
url.searchParams.set("agent_id", agentId);
|
|
4153
4496
|
const response = await fetchImpl(url, {
|
|
4154
4497
|
method: "POST",
|
|
4155
|
-
headers:
|
|
4498
|
+
headers: cloudHeaders2(this.cloudOptions),
|
|
4156
4499
|
body: JSON.stringify({})
|
|
4157
4500
|
});
|
|
4158
|
-
const body = await
|
|
4159
|
-
|
|
4501
|
+
const body = await parseJsonResponse3(response);
|
|
4502
|
+
assertOkResponse2(response, body, "Cloud createSession()");
|
|
4160
4503
|
if (!isCloudConversation(body)) {
|
|
4161
4504
|
throw new Error("Cloud createSession() response did not include a conversation id.");
|
|
4162
4505
|
}
|
|
4163
4506
|
return { id: body.id, agent_id: body.agent_id };
|
|
4164
4507
|
}
|
|
4165
4508
|
async retrieveConversation(conversationId) {
|
|
4166
|
-
const fetchImpl =
|
|
4167
|
-
const baseUrl =
|
|
4168
|
-
const response = await fetchImpl(`${baseUrl}/v1/conversations/${encodeURIComponent(conversationId)}`, { headers:
|
|
4169
|
-
const body = await
|
|
4170
|
-
|
|
4509
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4510
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4511
|
+
const response = await fetchImpl(`${baseUrl}/v1/conversations/${encodeURIComponent(conversationId)}`, { headers: cloudHeaders2(this.cloudOptions) });
|
|
4512
|
+
const body = await parseJsonResponse3(response);
|
|
4513
|
+
assertOkResponse2(response, body, "Cloud resumeSession()");
|
|
4171
4514
|
if (!isCloudConversation(body)) {
|
|
4172
4515
|
throw new Error(`Cloud resumeSession() could not retrieve conversation ${conversationId}.`);
|
|
4173
4516
|
}
|
|
@@ -4203,15 +4546,15 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4203
4546
|
}
|
|
4204
4547
|
}
|
|
4205
4548
|
async createManagedSandbox(agentId) {
|
|
4206
|
-
const fetchImpl =
|
|
4207
|
-
const baseUrl =
|
|
4549
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4550
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4208
4551
|
const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(agentId)}/sandboxes`, {
|
|
4209
4552
|
method: "POST",
|
|
4210
|
-
headers:
|
|
4553
|
+
headers: cloudHeaders2(this.cloudOptions),
|
|
4211
4554
|
body: JSON.stringify({})
|
|
4212
4555
|
});
|
|
4213
|
-
const body = await
|
|
4214
|
-
|
|
4556
|
+
const body = await parseJsonResponse3(response);
|
|
4557
|
+
assertOkResponse2(response, body, "Cloud create managed sandbox");
|
|
4215
4558
|
if (!isCloudAgentSandbox(body)) {
|
|
4216
4559
|
throw new Error("Cloud create managed sandbox response did not include sandbox connection details.");
|
|
4217
4560
|
}
|
|
@@ -4245,15 +4588,15 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4245
4588
|
}
|
|
4246
4589
|
}
|
|
4247
4590
|
async refreshManagedSandboxOnce(sandbox) {
|
|
4248
|
-
const fetchImpl =
|
|
4249
|
-
const baseUrl =
|
|
4591
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4592
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4250
4593
|
const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(sandbox.agentId)}/sandboxes/refresh`, {
|
|
4251
4594
|
method: "POST",
|
|
4252
|
-
headers:
|
|
4595
|
+
headers: cloudHeaders2(this.cloudOptions),
|
|
4253
4596
|
body: JSON.stringify({ ttlMinutes: sandbox.ttlMinutes })
|
|
4254
4597
|
});
|
|
4255
|
-
const body = await
|
|
4256
|
-
|
|
4598
|
+
const body = await parseJsonResponse3(response);
|
|
4599
|
+
assertOkResponse2(response, body, "Cloud refresh managed sandbox");
|
|
4257
4600
|
if (!isCloudAgentSandboxRefresh(body) || !body.success) {
|
|
4258
4601
|
throw new Error("Cloud refresh managed sandbox response did not confirm refresh.");
|
|
4259
4602
|
}
|
|
@@ -4263,16 +4606,16 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4263
4606
|
}
|
|
4264
4607
|
async terminateManagedSandbox(sandbox) {
|
|
4265
4608
|
await this.refreshManagedSandbox(sandbox);
|
|
4266
|
-
const fetchImpl =
|
|
4267
|
-
const baseUrl =
|
|
4609
|
+
const fetchImpl = getFetch3(this.cloudOptions.fetch);
|
|
4610
|
+
const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
|
|
4268
4611
|
const response = await fetchImpl(`${baseUrl}/v1/agents/${encodeURIComponent(sandbox.agentId)}/sandboxes`, {
|
|
4269
4612
|
method: "DELETE",
|
|
4270
|
-
headers:
|
|
4613
|
+
headers: cloudHeaders2(this.cloudOptions)
|
|
4271
4614
|
});
|
|
4272
|
-
const body = await
|
|
4615
|
+
const body = await parseJsonResponse3(response);
|
|
4273
4616
|
if (response.status === 404)
|
|
4274
4617
|
return;
|
|
4275
|
-
|
|
4618
|
+
assertOkResponse2(response, body, "Cloud terminate managed sandbox");
|
|
4276
4619
|
}
|
|
4277
4620
|
async waitForManagedSandboxConnection(sandbox) {
|
|
4278
4621
|
const deadline = Date.now() + sandbox.readyTimeoutMs;
|
|
@@ -4325,7 +4668,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
4325
4668
|
remoteEnvironmentClient() {
|
|
4326
4669
|
return new RemoteEnvironmentClient({
|
|
4327
4670
|
baseUrl: this.cloudOptions.apiBaseUrl,
|
|
4328
|
-
apiKey:
|
|
4671
|
+
apiKey: getCloudApiKey2(this.cloudOptions),
|
|
4329
4672
|
headers: this.cloudOptions.headers,
|
|
4330
4673
|
fetch: this.cloudOptions.fetch
|
|
4331
4674
|
});
|
|
@@ -4486,17 +4829,24 @@ function stripCloudExecutionOptions(options) {
|
|
|
4486
4829
|
delete sessionOptions.sandbox;
|
|
4487
4830
|
return sessionOptions;
|
|
4488
4831
|
}
|
|
4832
|
+
function hasRepositoryResources(options) {
|
|
4833
|
+
return options.resources !== undefined && options.resources.length > 0;
|
|
4834
|
+
}
|
|
4489
4835
|
function hasCreateAgentEnvironment(options) {
|
|
4490
4836
|
return "environment" in options;
|
|
4491
4837
|
}
|
|
4838
|
+
function hasExplicitCreateAgentModel(options) {
|
|
4839
|
+
return typeof options.model === "string" && options.model.trim().length > 0;
|
|
4840
|
+
}
|
|
4492
4841
|
function looksLikeConversationId(id) {
|
|
4493
4842
|
return id.startsWith("conv-") || id.startsWith("local-conv-");
|
|
4494
4843
|
}
|
|
4495
4844
|
|
|
4496
|
-
class
|
|
4845
|
+
class LettaAgentClient {
|
|
4497
4846
|
backend;
|
|
4498
4847
|
environment;
|
|
4499
4848
|
options;
|
|
4849
|
+
repositoriesClient = null;
|
|
4500
4850
|
constructor(options = {}) {
|
|
4501
4851
|
const backend = options.backend ?? "local";
|
|
4502
4852
|
if (!isLettaCodeBackend(backend)) {
|
|
@@ -4506,13 +4856,13 @@ class LettaCodeClient {
|
|
|
4506
4856
|
this.environment = getOptionsEnvironment(options);
|
|
4507
4857
|
this.options = options;
|
|
4508
4858
|
if (this.backend === "local" && this.environment !== undefined) {
|
|
4509
|
-
throw new Error('
|
|
4859
|
+
throw new Error('LettaAgentClient environment is only valid with backend: "cloud".');
|
|
4510
4860
|
}
|
|
4511
4861
|
if (this.backend === "remote" && this.environment !== undefined) {
|
|
4512
|
-
throw new Error('
|
|
4862
|
+
throw new Error('LettaAgentClient environment is only valid with backend: "cloud"; remote url selects the app-server runtime.');
|
|
4513
4863
|
}
|
|
4514
4864
|
if (this.backend !== "cloud" && options.sandbox !== undefined) {
|
|
4515
|
-
throw new Error('
|
|
4865
|
+
throw new Error('LettaAgentClient sandbox options are only valid with backend: "cloud".');
|
|
4516
4866
|
}
|
|
4517
4867
|
if (this.backend === "local") {
|
|
4518
4868
|
const localOptions = options;
|
|
@@ -4530,7 +4880,7 @@ class LettaCodeClient {
|
|
|
4530
4880
|
}
|
|
4531
4881
|
if (this.backend === "remote") {
|
|
4532
4882
|
if (!("url" in options) || typeof options.url !== "string" || options.url.length === 0) {
|
|
4533
|
-
throw new Error("
|
|
4883
|
+
throw new Error("LettaAgentClient remote backend requires a non-empty url.");
|
|
4534
4884
|
}
|
|
4535
4885
|
if (options.requestTimeoutMs !== undefined && (!Number.isInteger(options.requestTimeoutMs) || options.requestTimeoutMs <= 0)) {
|
|
4536
4886
|
throw new Error("Invalid requestTimeoutMs. Expected a positive integer.");
|
|
@@ -4540,6 +4890,9 @@ class LettaCodeClient {
|
|
|
4540
4890
|
validateCloudClientOptions(options);
|
|
4541
4891
|
}
|
|
4542
4892
|
}
|
|
4893
|
+
get repositories() {
|
|
4894
|
+
return this.getRepositoriesClient();
|
|
4895
|
+
}
|
|
4543
4896
|
async createAgent(options = {}) {
|
|
4544
4897
|
if (hasCreateAgentEnvironment(options)) {
|
|
4545
4898
|
throw new Error("createAgent() does not accept environment. Set a client default or pass environment to resumeSession()/createSession().");
|
|
@@ -4555,6 +4908,9 @@ class LettaCodeClient {
|
|
|
4555
4908
|
return initMsg2.agentId;
|
|
4556
4909
|
}
|
|
4557
4910
|
if (this.backend === "cloud") {
|
|
4911
|
+
if (!hasExplicitCreateAgentModel(options)) {
|
|
4912
|
+
throw new Error('Constellation createAgent() requires an explicit model. Pass model in createAgent({ model: "provider/model" }).');
|
|
4913
|
+
}
|
|
4558
4914
|
return createCloudAgent(this.cloudOptions(), options);
|
|
4559
4915
|
}
|
|
4560
4916
|
this.assertLocalBackend("createAgent");
|
|
@@ -4683,7 +5039,7 @@ class LettaCodeClient {
|
|
|
4683
5039
|
if (this.backend === "local") {
|
|
4684
5040
|
return;
|
|
4685
5041
|
}
|
|
4686
|
-
throw new Error(`
|
|
5042
|
+
throw new Error(`LettaAgentClient backend '${this.backend}' is not implemented yet. ${action} currently supports backend 'local' only.`);
|
|
4687
5043
|
}
|
|
4688
5044
|
assertSessionBackend(action, options) {
|
|
4689
5045
|
const effectiveEnvironment = options.environment ?? this.environment;
|
|
@@ -4694,6 +5050,9 @@ class LettaCodeClient {
|
|
|
4694
5050
|
if (options.sandbox !== undefined) {
|
|
4695
5051
|
throw new Error(`${action}() sandbox options are only valid with backend: "cloud".`);
|
|
4696
5052
|
}
|
|
5053
|
+
if (hasRepositoryResources(options)) {
|
|
5054
|
+
throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
|
|
5055
|
+
}
|
|
4697
5056
|
if (!this.useLegacyLocalStdio()) {
|
|
4698
5057
|
assertRemoteSessionOptionsSupported(action, options);
|
|
4699
5058
|
}
|
|
@@ -4706,6 +5065,9 @@ class LettaCodeClient {
|
|
|
4706
5065
|
if (options.sandbox !== undefined) {
|
|
4707
5066
|
throw new Error(`${action}() sandbox options are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
4708
5067
|
}
|
|
5068
|
+
if (hasRepositoryResources(options)) {
|
|
5069
|
+
throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
|
|
5070
|
+
}
|
|
4709
5071
|
assertRemoteSessionOptionsSupported(action, options);
|
|
4710
5072
|
return;
|
|
4711
5073
|
}
|
|
@@ -4720,7 +5082,7 @@ class LettaCodeClient {
|
|
|
4720
5082
|
assertCloudSessionOptionsSupported(action, options);
|
|
4721
5083
|
return;
|
|
4722
5084
|
}
|
|
4723
|
-
throw new Error(`
|
|
5085
|
+
throw new Error(`LettaAgentClient backend '${this.backend}' is not implemented yet. ${action} currently supports backend 'local' only.`);
|
|
4724
5086
|
}
|
|
4725
5087
|
useLegacyLocalStdio() {
|
|
4726
5088
|
return this.options.transport === "stdio";
|
|
@@ -4730,6 +5092,7 @@ class LettaCodeClient {
|
|
|
4730
5092
|
const appServer = localOptions.appServer;
|
|
4731
5093
|
return {
|
|
4732
5094
|
local: appServer?.url === undefined,
|
|
5095
|
+
localBackend: "local",
|
|
4733
5096
|
...appServer?.url !== undefined ? { url: appServer.url } : {},
|
|
4734
5097
|
...appServer?.WebSocket !== undefined ? { WebSocket: appServer.WebSocket } : {},
|
|
4735
5098
|
...appServer?.requestTimeoutMs !== undefined ? { requestTimeoutMs: appServer.requestTimeoutMs } : {},
|
|
@@ -4743,6 +5106,13 @@ class LettaCodeClient {
|
|
|
4743
5106
|
}
|
|
4744
5107
|
return this.options;
|
|
4745
5108
|
}
|
|
5109
|
+
getRepositoriesClient() {
|
|
5110
|
+
if (this.backend !== "cloud") {
|
|
5111
|
+
throw new Error('client.repositories is only available with backend: "cloud".');
|
|
5112
|
+
}
|
|
5113
|
+
this.repositoriesClient ??= new RepositoriesClient(this.cloudOptions());
|
|
5114
|
+
return this.repositoriesClient;
|
|
5115
|
+
}
|
|
4746
5116
|
cloudOptions() {
|
|
4747
5117
|
if (this.backend !== "cloud") {
|
|
4748
5118
|
throw new Error('Constellation options requested for non-"cloud" backend.');
|
|
@@ -4907,18 +5277,18 @@ function readStringArrayParam(params, key, options = {}) {
|
|
|
4907
5277
|
import { readFileSync } from "node:fs";
|
|
4908
5278
|
async function createAgent(options = {}) {
|
|
4909
5279
|
validateCreateAgentOptions(options);
|
|
4910
|
-
return new
|
|
5280
|
+
return new LettaAgentClient().createAgent(options);
|
|
4911
5281
|
}
|
|
4912
5282
|
function createSession(agentId, options = {}) {
|
|
4913
5283
|
validateCreateSessionOptions(options);
|
|
4914
5284
|
if (agentId) {
|
|
4915
|
-
return new
|
|
5285
|
+
return new LettaAgentClient().createSession(agentId, options);
|
|
4916
5286
|
}
|
|
4917
|
-
return new
|
|
5287
|
+
return new LettaAgentClient({ backend: "local", transport: "stdio" }).createSession(options);
|
|
4918
5288
|
}
|
|
4919
5289
|
function resumeSession(id, options = {}) {
|
|
4920
5290
|
validateCreateSessionOptions(options);
|
|
4921
|
-
return new
|
|
5291
|
+
return new LettaAgentClient().resumeSession(id, options);
|
|
4922
5292
|
}
|
|
4923
5293
|
async function prompt(message, agentId) {
|
|
4924
5294
|
const session = agentId ? createSession(agentId) : createSession();
|
|
@@ -4929,7 +5299,7 @@ async function prompt(message, agentId) {
|
|
|
4929
5299
|
}
|
|
4930
5300
|
}
|
|
4931
5301
|
async function listMessagesDirect(agentId, options = {}) {
|
|
4932
|
-
const session = new
|
|
5302
|
+
const session = new LettaAgentClient().resumeSession(agentId, {
|
|
4933
5303
|
permissionMode: "bypassPermissions"
|
|
4934
5304
|
});
|
|
4935
5305
|
await session.initialize();
|
|
@@ -4988,7 +5358,8 @@ export {
|
|
|
4988
5358
|
createSession,
|
|
4989
5359
|
createAgent,
|
|
4990
5360
|
Session,
|
|
4991
|
-
|
|
5361
|
+
RepositoriesClient,
|
|
5362
|
+
LettaAgentClient
|
|
4992
5363
|
};
|
|
4993
5364
|
|
|
4994
|
-
//# debugId=
|
|
5365
|
+
//# debugId=7B3400A69740F48F64756E2164756E21
|