@letta-ai/letta-agent-sdk 0.6.1 → 0.6.3
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 +37 -1
- package/dist/agent-creation.d.ts +3 -7
- package/dist/agent-creation.d.ts.map +1 -1
- package/dist/app-server-session.d.ts +0 -5
- 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.d.ts +1 -0
- package/dist/client-entry.d.ts.map +1 -1
- package/dist/client-entry.js +557 -420
- package/dist/client-entry.js.map +14 -13
- package/dist/cloud-session.d.ts +8 -1
- package/dist/cloud-session.d.ts.map +1 -1
- package/dist/computers.d.ts +67 -0
- package/dist/computers.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +558 -421
- package/dist/index.js.map +15 -14
- package/dist/remote-client-session-core.d.ts +17 -0
- package/dist/remote-client-session-core.d.ts.map +1 -1
- package/dist/remote-turn-coordinator.d.ts +10 -0
- package/dist/remote-turn-coordinator.d.ts.map +1 -1
- package/dist/remote.d.ts +6 -1
- package/dist/remote.d.ts.map +1 -1
- package/dist/types.d.ts +12 -20
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/agent-creation.ts +93 -55
- package/src/app-server-session.ts +4 -151
- package/src/client-base.ts +66 -19
- package/src/client-entry.ts +9 -0
- package/src/cloud-session.ts +113 -45
- package/src/computers.ts +132 -0
- package/src/index.ts +9 -0
- package/src/remote-client-session-core.ts +107 -2
- package/src/remote-turn-coordinator.ts +27 -0
- package/src/remote.ts +41 -12
- package/src/types.ts +12 -17
package/dist/index.js
CHANGED
|
@@ -3195,36 +3195,6 @@ function appServerSocketOptions(authToken) {
|
|
|
3195
3195
|
}
|
|
3196
3196
|
return { headers: { Authorization: `Bearer ${token}` } };
|
|
3197
3197
|
}
|
|
3198
|
-
function sameRuntime(a, b) {
|
|
3199
|
-
return a?.agent_id === b.agent_id && a?.conversation_id === b.conversation_id;
|
|
3200
|
-
}
|
|
3201
|
-
function isWaitingLoopStatus(message) {
|
|
3202
|
-
return message.loop_status.status === "WAITING_ON_INPUT";
|
|
3203
|
-
}
|
|
3204
|
-
function isWaitingOnApprovalLoopStatus(message) {
|
|
3205
|
-
return message.loop_status.status === "WAITING_ON_APPROVAL";
|
|
3206
|
-
}
|
|
3207
|
-
function streamDeltaRunId(message) {
|
|
3208
|
-
const runId = message.delta.run_id;
|
|
3209
|
-
return typeof runId === "string" ? runId : null;
|
|
3210
|
-
}
|
|
3211
|
-
function streamDeltaMessageType(message) {
|
|
3212
|
-
const messageType = message.delta.message_type;
|
|
3213
|
-
return typeof messageType === "string" ? messageType : null;
|
|
3214
|
-
}
|
|
3215
|
-
function streamDeltaStopReason(message) {
|
|
3216
|
-
const stopReason = message.delta.stop_reason;
|
|
3217
|
-
return typeof stopReason === "string" ? stopReason : null;
|
|
3218
|
-
}
|
|
3219
|
-
function streamDeltaErrorMessage(message) {
|
|
3220
|
-
const delta = message.delta;
|
|
3221
|
-
const apiMessage = delta.api_error?.message ?? delta.api_error?.detail;
|
|
3222
|
-
if (typeof apiMessage === "string" && apiMessage.length > 0)
|
|
3223
|
-
return apiMessage;
|
|
3224
|
-
if (typeof delta.message === "string" && delta.message.length > 0)
|
|
3225
|
-
return delta.message;
|
|
3226
|
-
return "App-server turn failed";
|
|
3227
|
-
}
|
|
3228
3198
|
|
|
3229
3199
|
class AppServerClient {
|
|
3230
3200
|
socket;
|
|
@@ -3235,7 +3205,6 @@ class AppServerClient {
|
|
|
3235
3205
|
messageHandlers = new Set;
|
|
3236
3206
|
sendHandlers = new Set;
|
|
3237
3207
|
disconnectHandlers = new Set;
|
|
3238
|
-
activeTurnRuntimes = new Set;
|
|
3239
3208
|
explicitlyClosed = false;
|
|
3240
3209
|
disconnectNotified = false;
|
|
3241
3210
|
nextRequestNumber = 0;
|
|
@@ -3418,111 +3387,15 @@ class AppServerClient {
|
|
|
3418
3387
|
input(command) {
|
|
3419
3388
|
this.send({ type: "input", ...command });
|
|
3420
3389
|
}
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
const runIds = new Set;
|
|
3430
|
-
let observedTurnEvidence = false;
|
|
3431
|
-
let observedRequiresApprovalStop = false;
|
|
3432
|
-
return new Promise((resolve, reject) => {
|
|
3433
|
-
const timeout = setTimeout(() => {
|
|
3434
|
-
cleanup();
|
|
3435
|
-
reject(new Error(`Timed out waiting for app-server turn on ${command.runtime.agent_id}/${command.runtime.conversation_id}`));
|
|
3436
|
-
}, timeoutMs);
|
|
3437
|
-
const cleanup = () => {
|
|
3438
|
-
clearTimeout(timeout);
|
|
3439
|
-
this.activeTurnRuntimes.delete(runtimeKey);
|
|
3440
|
-
offMessage();
|
|
3441
|
-
};
|
|
3442
|
-
const finish = (completedBy, terminalMessage, stopReason) => {
|
|
3443
|
-
cleanup();
|
|
3444
|
-
resolve({
|
|
3445
|
-
runtime: command.runtime,
|
|
3446
|
-
stopReason,
|
|
3447
|
-
runIds: [...runIds],
|
|
3448
|
-
clientMessageIds: commandWithIds.clientMessageIds,
|
|
3449
|
-
completedBy,
|
|
3450
|
-
terminalMessage
|
|
3451
|
-
});
|
|
3452
|
-
};
|
|
3453
|
-
const fail = (error) => {
|
|
3454
|
-
cleanup();
|
|
3455
|
-
reject(error);
|
|
3456
|
-
};
|
|
3457
|
-
const offMessage = this.onMessage((message) => {
|
|
3458
|
-
if (!sameRuntime(message.runtime, command.runtime)) {
|
|
3459
|
-
return;
|
|
3460
|
-
}
|
|
3461
|
-
if (message.type === "stream_delta") {
|
|
3462
|
-
observedTurnEvidence = true;
|
|
3463
|
-
const runId = streamDeltaRunId(message);
|
|
3464
|
-
if (runId)
|
|
3465
|
-
runIds.add(runId);
|
|
3466
|
-
const messageType = streamDeltaMessageType(message);
|
|
3467
|
-
if (messageType === "loop_error" || messageType === "error_message") {
|
|
3468
|
-
fail(new Error(streamDeltaErrorMessage(message)));
|
|
3469
|
-
return;
|
|
3470
|
-
}
|
|
3471
|
-
if (messageType === "stop_reason") {
|
|
3472
|
-
const stopReason = streamDeltaStopReason(message);
|
|
3473
|
-
if (stopReason === "requires_approval") {
|
|
3474
|
-
observedRequiresApprovalStop = true;
|
|
3475
|
-
return;
|
|
3476
|
-
}
|
|
3477
|
-
finish("stop_reason", message, stopReason);
|
|
3478
|
-
}
|
|
3479
|
-
return;
|
|
3480
|
-
}
|
|
3481
|
-
if (message.type === "update_loop_status") {
|
|
3482
|
-
const hadTurnEvidenceBeforeLoopStatus = observedTurnEvidence || observedRequiresApprovalStop;
|
|
3483
|
-
if (!hadTurnEvidenceBeforeLoopStatus && (isWaitingOnApprovalLoopStatus(message) || options.allowLoopStatusFallback === true && isWaitingLoopStatus(message))) {
|
|
3484
|
-
return;
|
|
3485
|
-
}
|
|
3486
|
-
for (const runId of message.loop_status.active_run_ids) {
|
|
3487
|
-
observedTurnEvidence = true;
|
|
3488
|
-
runIds.add(runId);
|
|
3489
|
-
}
|
|
3490
|
-
if (hadTurnEvidenceBeforeLoopStatus && isWaitingOnApprovalLoopStatus(message)) {
|
|
3491
|
-
finish("loop_status_waiting_on_approval", message, "requires_approval");
|
|
3492
|
-
return;
|
|
3493
|
-
}
|
|
3494
|
-
if (options.allowLoopStatusFallback === true && hadTurnEvidenceBeforeLoopStatus && isWaitingLoopStatus(message)) {
|
|
3495
|
-
finish("loop_status_waiting_fallback", message, null);
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
});
|
|
3499
|
-
try {
|
|
3500
|
-
this.input(commandWithIds.command);
|
|
3501
|
-
} catch (error) {
|
|
3502
|
-
fail(error instanceof Error ? error : new Error(String(error)));
|
|
3503
|
-
}
|
|
3504
|
-
});
|
|
3505
|
-
}
|
|
3506
|
-
withClientMessageIds(command) {
|
|
3507
|
-
if (command.payload.kind !== "create_message") {
|
|
3508
|
-
return { command, clientMessageIds: [] };
|
|
3509
|
-
}
|
|
3510
|
-
const clientMessageIds = [];
|
|
3511
|
-
const messages = command.payload.messages.map((message) => {
|
|
3512
|
-
if (message.role !== "user")
|
|
3513
|
-
return message;
|
|
3514
|
-
const existing = message.client_message_id;
|
|
3515
|
-
const clientMessageId = typeof existing === "string" && existing.length > 0 ? existing : this.nextRequestId("client-message");
|
|
3516
|
-
clientMessageIds.push(clientMessageId);
|
|
3517
|
-
return { ...message, client_message_id: clientMessageId };
|
|
3390
|
+
submitInput(command, options = {}) {
|
|
3391
|
+
return this.request({
|
|
3392
|
+
type: "input",
|
|
3393
|
+
request_id: command.request_id ?? this.nextRequestId("input"),
|
|
3394
|
+
...command
|
|
3395
|
+
}, {
|
|
3396
|
+
...options,
|
|
3397
|
+
predicate: (message) => message.type === "input_accepted"
|
|
3518
3398
|
});
|
|
3519
|
-
return {
|
|
3520
|
-
command: {
|
|
3521
|
-
...command,
|
|
3522
|
-
payload: { ...command.payload, messages }
|
|
3523
|
-
},
|
|
3524
|
-
clientMessageIds
|
|
3525
|
-
};
|
|
3526
3399
|
}
|
|
3527
3400
|
handleMessage(event, channel) {
|
|
3528
3401
|
const message = parseProtocolMessage(event);
|
|
@@ -6456,6 +6329,73 @@ var models_default = {
|
|
|
6456
6329
|
parallel_tool_calls: true
|
|
6457
6330
|
}
|
|
6458
6331
|
},
|
|
6332
|
+
{
|
|
6333
|
+
id: "opus-5",
|
|
6334
|
+
handle: "anthropic/claude-opus-5",
|
|
6335
|
+
label: "Opus 5",
|
|
6336
|
+
description: "Opus 5 (high reasoning)",
|
|
6337
|
+
updateArgs: {
|
|
6338
|
+
context_window: 200000,
|
|
6339
|
+
max_output_tokens: 128000,
|
|
6340
|
+
enable_reasoner: true,
|
|
6341
|
+
reasoning_effort: "high",
|
|
6342
|
+
parallel_tool_calls: true
|
|
6343
|
+
}
|
|
6344
|
+
},
|
|
6345
|
+
{
|
|
6346
|
+
id: "opus-5-low",
|
|
6347
|
+
handle: "anthropic/claude-opus-5",
|
|
6348
|
+
label: "Opus 5",
|
|
6349
|
+
description: "Opus 5 (low reasoning)",
|
|
6350
|
+
updateArgs: {
|
|
6351
|
+
context_window: 200000,
|
|
6352
|
+
max_output_tokens: 128000,
|
|
6353
|
+
enable_reasoner: true,
|
|
6354
|
+
reasoning_effort: "low",
|
|
6355
|
+
max_reasoning_tokens: 4000,
|
|
6356
|
+
parallel_tool_calls: true
|
|
6357
|
+
}
|
|
6358
|
+
},
|
|
6359
|
+
{
|
|
6360
|
+
id: "opus-5-medium",
|
|
6361
|
+
handle: "anthropic/claude-opus-5",
|
|
6362
|
+
label: "Opus 5",
|
|
6363
|
+
description: "Opus 5 (med reasoning)",
|
|
6364
|
+
updateArgs: {
|
|
6365
|
+
context_window: 200000,
|
|
6366
|
+
max_output_tokens: 128000,
|
|
6367
|
+
enable_reasoner: true,
|
|
6368
|
+
reasoning_effort: "medium",
|
|
6369
|
+
max_reasoning_tokens: 12000,
|
|
6370
|
+
parallel_tool_calls: true
|
|
6371
|
+
}
|
|
6372
|
+
},
|
|
6373
|
+
{
|
|
6374
|
+
id: "opus-5-xhigh",
|
|
6375
|
+
handle: "anthropic/claude-opus-5",
|
|
6376
|
+
label: "Opus 5",
|
|
6377
|
+
description: "Opus 5 (extra-high reasoning)",
|
|
6378
|
+
updateArgs: {
|
|
6379
|
+
context_window: 200000,
|
|
6380
|
+
max_output_tokens: 128000,
|
|
6381
|
+
enable_reasoner: true,
|
|
6382
|
+
reasoning_effort: "xhigh",
|
|
6383
|
+
parallel_tool_calls: true
|
|
6384
|
+
}
|
|
6385
|
+
},
|
|
6386
|
+
{
|
|
6387
|
+
id: "opus-5-max",
|
|
6388
|
+
handle: "anthropic/claude-opus-5",
|
|
6389
|
+
label: "Opus 5",
|
|
6390
|
+
description: "Opus 5 (max reasoning)",
|
|
6391
|
+
updateArgs: {
|
|
6392
|
+
context_window: 200000,
|
|
6393
|
+
max_output_tokens: 128000,
|
|
6394
|
+
enable_reasoner: true,
|
|
6395
|
+
reasoning_effort: "max",
|
|
6396
|
+
parallel_tool_calls: true
|
|
6397
|
+
}
|
|
6398
|
+
},
|
|
6459
6399
|
{
|
|
6460
6400
|
id: "opus",
|
|
6461
6401
|
handle: "anthropic/claude-opus-4-8",
|
|
@@ -6730,7 +6670,7 @@ var models_default = {
|
|
|
6730
6670
|
id: "sonnet-5-xhigh",
|
|
6731
6671
|
handle: "anthropic/claude-sonnet-5",
|
|
6732
6672
|
label: "Sonnet 5",
|
|
6733
|
-
description: "Sonnet 5 (
|
|
6673
|
+
description: "Sonnet 5 (extra-high reasoning)",
|
|
6734
6674
|
updateArgs: {
|
|
6735
6675
|
context_window: 1e6,
|
|
6736
6676
|
max_output_tokens: 128000,
|
|
@@ -6739,6 +6679,19 @@ var models_default = {
|
|
|
6739
6679
|
parallel_tool_calls: true
|
|
6740
6680
|
}
|
|
6741
6681
|
},
|
|
6682
|
+
{
|
|
6683
|
+
id: "sonnet-5-max",
|
|
6684
|
+
handle: "anthropic/claude-sonnet-5",
|
|
6685
|
+
label: "Sonnet 5",
|
|
6686
|
+
description: "Sonnet 5 (max reasoning)",
|
|
6687
|
+
updateArgs: {
|
|
6688
|
+
context_window: 1e6,
|
|
6689
|
+
max_output_tokens: 128000,
|
|
6690
|
+
reasoning_effort: "max",
|
|
6691
|
+
enable_reasoner: true,
|
|
6692
|
+
parallel_tool_calls: true
|
|
6693
|
+
}
|
|
6694
|
+
},
|
|
6742
6695
|
{
|
|
6743
6696
|
id: "sonnet-4.6",
|
|
6744
6697
|
handle: "anthropic/claude-sonnet-4-6",
|
|
@@ -8289,7 +8242,6 @@ var models_default = {
|
|
|
8289
8242
|
]
|
|
8290
8243
|
};
|
|
8291
8244
|
var models = models_default.models;
|
|
8292
|
-
var MODEL_PRESETS = models;
|
|
8293
8245
|
function resolveModel(modelIdentifier) {
|
|
8294
8246
|
const byId = models.find((m) => m.id === modelIdentifier);
|
|
8295
8247
|
if (byId)
|
|
@@ -8517,75 +8469,128 @@ function buildPersonalityMemoryBlocks(personalityId, defaultMemoryBlocks, enviro
|
|
|
8517
8469
|
}
|
|
8518
8470
|
var LETTA_CODE_AGENT_TYPE = "letta_v1_agent";
|
|
8519
8471
|
var DEFAULT_CREATED_AGENT_BASE_TOOLS = ["web_search", "fetch_webpage"];
|
|
8520
|
-
|
|
8521
|
-
const
|
|
8522
|
-
const
|
|
8523
|
-
|
|
8472
|
+
function mergeMemoryBlocks(base, overrides) {
|
|
8473
|
+
const blocks = base.map((block) => ({ ...block }));
|
|
8474
|
+
for (const override of overrides ?? []) {
|
|
8475
|
+
const index = blocks.findIndex((block) => block.label === override.label);
|
|
8476
|
+
if (index >= 0) {
|
|
8477
|
+
blocks[index] = { ...override };
|
|
8478
|
+
} else {
|
|
8479
|
+
blocks.push({ ...override });
|
|
8480
|
+
}
|
|
8481
|
+
}
|
|
8482
|
+
return blocks;
|
|
8483
|
+
}
|
|
8484
|
+
async function buildCreateAgentRequest(options = {}) {
|
|
8485
|
+
const personality = options.personalityId ? getPersonalityOption(options.personalityId) : undefined;
|
|
8486
|
+
const modelIdentifier = options.model ?? personality?.defaultModel;
|
|
8524
8487
|
const modelHandle = modelIdentifier ? resolveModel(modelIdentifier) : getDefaultModel();
|
|
8525
8488
|
if (!modelHandle) {
|
|
8526
8489
|
throw new Error(`Unknown model: ${modelIdentifier}`);
|
|
8527
8490
|
}
|
|
8528
|
-
|
|
8491
|
+
if (!options.isSubagent && options.enableMemfs !== undefined && options.memoryPromptMode !== undefined && options.enableMemfs !== (options.memoryPromptMode !== "standard")) {
|
|
8492
|
+
throw new Error("enableMemfs and memoryPromptMode must describe the same memory mode");
|
|
8493
|
+
}
|
|
8494
|
+
const enableMemfs = options.isSubagent ? false : options.enableMemfs ?? options.memoryPromptMode !== "standard";
|
|
8495
|
+
const memoryPromptMode = options.isSubagent ? "standard" : options.memoryPromptMode ?? (enableMemfs ? "memfs" : "standard");
|
|
8496
|
+
const personalityTags = options.personalityId ? getPersonalityCreationTags(options.personalityId) : [];
|
|
8497
|
+
const personalityBlocks = options.personalityId ? buildPersonalityMemoryBlocks(options.personalityId, await getDefaultMemoryBlocks()) : [];
|
|
8498
|
+
const memoryBlocks = options.isSubagent ? undefined : options.personalityId || options.memoryBlocks !== undefined ? mergeMemoryBlocks(personalityBlocks, options.memoryBlocks) : undefined;
|
|
8499
|
+
const blockIds = options.isSubagent ? undefined : options.blockIds;
|
|
8529
8500
|
return {
|
|
8530
8501
|
agent_type: LETTA_CODE_AGENT_TYPE,
|
|
8531
|
-
name: name ?? personality
|
|
8532
|
-
description: description ?? personality
|
|
8502
|
+
...options.name !== undefined || personality ? { name: options.name ?? personality?.label } : {},
|
|
8503
|
+
...options.description !== undefined || personality ? { description: options.description ?? personality?.description } : {},
|
|
8533
8504
|
model: modelHandle,
|
|
8534
|
-
system: buildSystemPrompt("default",
|
|
8535
|
-
memory_blocks:
|
|
8505
|
+
system: options.system ?? buildSystemPrompt("default", memoryPromptMode),
|
|
8506
|
+
...memoryBlocks !== undefined ? { memory_blocks: memoryBlocks } : {},
|
|
8507
|
+
...blockIds && blockIds.length > 0 ? { block_ids: blockIds } : {},
|
|
8536
8508
|
tags: buildCreatedAgentTags({
|
|
8537
|
-
enableMemfs
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
...extraTags ?? []
|
|
8541
|
-
]
|
|
8509
|
+
enableMemfs,
|
|
8510
|
+
isSubagent: options.isSubagent,
|
|
8511
|
+
tags: [...personalityTags, ...options.extraTags ?? []]
|
|
8542
8512
|
}),
|
|
8543
|
-
tools: [...DEFAULT_CREATED_AGENT_BASE_TOOLS],
|
|
8513
|
+
tools: [...options.baseTools ?? DEFAULT_CREATED_AGENT_BASE_TOOLS],
|
|
8544
8514
|
include_base_tools: false,
|
|
8545
8515
|
include_base_tool_rules: false,
|
|
8546
8516
|
initial_message_sequence: [],
|
|
8547
|
-
parallel_tool_calls: true,
|
|
8548
|
-
compaction_settings: {
|
|
8517
|
+
parallel_tool_calls: options.parallelToolCalls ?? true,
|
|
8518
|
+
compaction_settings: {
|
|
8519
|
+
model: options.compactionModel ?? DEFAULT_SUMMARIZATION_MODEL
|
|
8520
|
+
},
|
|
8521
|
+
...options.embedding !== undefined ? { embedding: options.embedding } : {},
|
|
8522
|
+
...options.isSubagent ? { hidden: true } : options.hidden !== undefined ? { hidden: options.hidden } : {}
|
|
8549
8523
|
};
|
|
8550
8524
|
}
|
|
8551
8525
|
|
|
8552
8526
|
// src/agent-creation.ts
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8527
|
+
function isPresetSystemPrompt(value) {
|
|
8528
|
+
return [
|
|
8529
|
+
"default",
|
|
8530
|
+
"letta-claude",
|
|
8531
|
+
"letta-codex",
|
|
8532
|
+
"letta-gemini",
|
|
8533
|
+
"claude",
|
|
8534
|
+
"codex",
|
|
8535
|
+
"gemini"
|
|
8536
|
+
].includes(value);
|
|
8562
8537
|
}
|
|
8563
|
-
|
|
8564
|
-
if (options.
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8538
|
+
function assertCreateAgentOptionsSupported(options) {
|
|
8539
|
+
if (options.allowedTools !== undefined || options.disallowedTools !== undefined) {
|
|
8540
|
+
throw new Error("App-server createAgent() does not yet support allowedTools/disallowedTools.");
|
|
8541
|
+
}
|
|
8542
|
+
if (options.canUseTool !== undefined) {
|
|
8543
|
+
throw new Error("App-server createAgent() does not yet support canUseTool callbacks.");
|
|
8544
|
+
}
|
|
8545
|
+
if (options.systemInfoReminder !== undefined) {
|
|
8546
|
+
throw new Error("App-server createAgent() does not yet support systemInfoReminder overrides.");
|
|
8547
|
+
}
|
|
8548
|
+
if (options.dreaming?.behavior !== undefined) {
|
|
8549
|
+
throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
|
|
8574
8550
|
}
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8551
|
+
}
|
|
8552
|
+
async function createAgentBody(options) {
|
|
8553
|
+
assertCreateAgentOptionsSupported(options);
|
|
8554
|
+
let system;
|
|
8555
|
+
if (options.systemPrompt !== undefined) {
|
|
8556
|
+
if (typeof options.systemPrompt !== "string" || isPresetSystemPrompt(options.systemPrompt)) {
|
|
8557
|
+
throw new Error("createAgent() does not yet support system prompt presets for this backend.");
|
|
8558
|
+
}
|
|
8559
|
+
system = options.systemPrompt;
|
|
8560
|
+
}
|
|
8561
|
+
const memoryBlocks = [];
|
|
8562
|
+
const blockIds = [];
|
|
8563
|
+
for (const item of options.memory ?? []) {
|
|
8564
|
+
if (typeof item === "string") {
|
|
8565
|
+
throw new Error("App-server createAgent() does not yet support memory preset names.");
|
|
8566
|
+
}
|
|
8567
|
+
if ("blockId" in item) {
|
|
8568
|
+
blockIds.push(item.blockId);
|
|
8569
|
+
} else {
|
|
8570
|
+
memoryBlocks.push({ ...item });
|
|
8571
|
+
}
|
|
8572
|
+
}
|
|
8573
|
+
if (options.persona !== undefined) {
|
|
8574
|
+
memoryBlocks.push({ label: "persona", value: options.persona });
|
|
8575
|
+
}
|
|
8576
|
+
if (options.human !== undefined) {
|
|
8577
|
+
memoryBlocks.push({ label: "human", value: options.human });
|
|
8578
|
+
}
|
|
8579
|
+
const hasMemoryConfiguration = options.memory !== undefined || options.persona !== undefined || options.human !== undefined;
|
|
8580
|
+
return buildCreateAgentRequest({
|
|
8581
|
+
personalityId: options.personality,
|
|
8582
|
+
name: options.name,
|
|
8583
|
+
description: options.description,
|
|
8584
|
+
model: options.model,
|
|
8585
|
+
system,
|
|
8586
|
+
memoryBlocks: hasMemoryConfiguration ? memoryBlocks : undefined,
|
|
8587
|
+
blockIds,
|
|
8588
|
+
extraTags: options.tags,
|
|
8589
|
+
enableMemfs: options.memfs ?? true,
|
|
8590
|
+
baseTools: options.baseTools,
|
|
8591
|
+
embedding: options.embedding,
|
|
8592
|
+
hidden: options.hidden
|
|
8593
|
+
});
|
|
8589
8594
|
}
|
|
8590
8595
|
|
|
8591
8596
|
// src/interactiveToolPolicy.ts
|
|
@@ -8877,7 +8882,7 @@ function firstToolReturn(delta) {
|
|
|
8877
8882
|
}
|
|
8878
8883
|
return;
|
|
8879
8884
|
}
|
|
8880
|
-
function
|
|
8885
|
+
function sameRuntime(message, runtime) {
|
|
8881
8886
|
const msgRuntime = message.runtime;
|
|
8882
8887
|
if (msgRuntime) {
|
|
8883
8888
|
return msgRuntime.agent_id === runtime.agent_id && msgRuntime.conversation_id === runtime.conversation_id;
|
|
@@ -8896,10 +8901,10 @@ function streamDeltaRecord(message) {
|
|
|
8896
8901
|
const delta = message.delta;
|
|
8897
8902
|
return delta && typeof delta === "object" && !Array.isArray(delta) ? delta : null;
|
|
8898
8903
|
}
|
|
8899
|
-
function
|
|
8904
|
+
function streamDeltaMessageType(delta) {
|
|
8900
8905
|
return typeof delta.message_type === "string" ? delta.message_type : undefined;
|
|
8901
8906
|
}
|
|
8902
|
-
function
|
|
8907
|
+
function streamDeltaRunId(delta) {
|
|
8903
8908
|
return typeof delta.run_id === "string" ? delta.run_id : undefined;
|
|
8904
8909
|
}
|
|
8905
8910
|
function streamDeltaOtid(delta) {
|
|
@@ -8908,7 +8913,7 @@ function streamDeltaOtid(delta) {
|
|
|
8908
8913
|
function streamDeltaSeqId(delta) {
|
|
8909
8914
|
return typeof delta.seq_id === "number" ? delta.seq_id : undefined;
|
|
8910
8915
|
}
|
|
8911
|
-
function
|
|
8916
|
+
function streamDeltaStopReason(delta) {
|
|
8912
8917
|
return typeof delta.stop_reason === "string" ? delta.stop_reason : undefined;
|
|
8913
8918
|
}
|
|
8914
8919
|
function loopStatusRecord(message) {
|
|
@@ -9131,7 +9136,7 @@ class RemoteTurnCoordinator {
|
|
|
9131
9136
|
this.activeTurn.abortRequested = true;
|
|
9132
9137
|
}
|
|
9133
9138
|
handleProtocolMessage(message, runtime) {
|
|
9134
|
-
if (!
|
|
9139
|
+
if (!sameRuntime(message, runtime))
|
|
9135
9140
|
return;
|
|
9136
9141
|
const statusRecord = deviceStatusRecord(message);
|
|
9137
9142
|
if (statusRecord) {
|
|
@@ -9158,7 +9163,7 @@ class RemoteTurnCoordinator {
|
|
|
9158
9163
|
const active = this.activateNextTurnFromProtocol();
|
|
9159
9164
|
if (active) {
|
|
9160
9165
|
active.observedTurnEvidence = true;
|
|
9161
|
-
const runId =
|
|
9166
|
+
const runId = streamDeltaRunId(delta);
|
|
9162
9167
|
if (runId)
|
|
9163
9168
|
active.runIds.add(runId);
|
|
9164
9169
|
}
|
|
@@ -9177,6 +9182,24 @@ class RemoteTurnCoordinator {
|
|
|
9177
9182
|
this.streamResolvers.push(resolve);
|
|
9178
9183
|
});
|
|
9179
9184
|
}
|
|
9185
|
+
closeWithError(detail) {
|
|
9186
|
+
if (this.closed)
|
|
9187
|
+
return;
|
|
9188
|
+
const active = this.activeTurn;
|
|
9189
|
+
if (active) {
|
|
9190
|
+
this.failTurn(active, detail);
|
|
9191
|
+
} else {
|
|
9192
|
+
this.enqueue({
|
|
9193
|
+
type: "error",
|
|
9194
|
+
message: detail,
|
|
9195
|
+
errorCode: "error",
|
|
9196
|
+
stopReason: "error",
|
|
9197
|
+
errorDetail: detail,
|
|
9198
|
+
recoverable: false
|
|
9199
|
+
});
|
|
9200
|
+
}
|
|
9201
|
+
this.close();
|
|
9202
|
+
}
|
|
9180
9203
|
close() {
|
|
9181
9204
|
if (this.closed)
|
|
9182
9205
|
return;
|
|
@@ -9294,9 +9317,9 @@ class RemoteTurnCoordinator {
|
|
|
9294
9317
|
const active = this.activeTurn;
|
|
9295
9318
|
if (!active)
|
|
9296
9319
|
return;
|
|
9297
|
-
const messageType =
|
|
9320
|
+
const messageType = streamDeltaMessageType(delta);
|
|
9298
9321
|
if (messageType === "stop_reason") {
|
|
9299
|
-
const stopReason =
|
|
9322
|
+
const stopReason = streamDeltaStopReason(delta) ?? null;
|
|
9300
9323
|
if (stopReason === "requires_approval") {
|
|
9301
9324
|
active.observedRequiresApprovalStop = true;
|
|
9302
9325
|
return;
|
|
@@ -9490,6 +9513,10 @@ class RemoteClientSessionCore {
|
|
|
9490
9513
|
requestTimeoutMs;
|
|
9491
9514
|
initializePromise = null;
|
|
9492
9515
|
removeMessageHandler = null;
|
|
9516
|
+
detachTransportDisconnect = null;
|
|
9517
|
+
idleTransportDisconnected = false;
|
|
9518
|
+
transportRecoveryPromise = null;
|
|
9519
|
+
transportDisconnectGeneration = 0;
|
|
9493
9520
|
turns;
|
|
9494
9521
|
toolNames;
|
|
9495
9522
|
deviceStatusListeners = new Set;
|
|
@@ -9564,6 +9591,8 @@ class RemoteClientSessionCore {
|
|
|
9564
9591
|
cleanupFailedInitialize() {
|
|
9565
9592
|
this.removeMessageHandler?.();
|
|
9566
9593
|
this.removeMessageHandler = null;
|
|
9594
|
+
this.detachTransportDisconnect?.();
|
|
9595
|
+
this.detachTransportDisconnect = null;
|
|
9567
9596
|
this.controller?.close();
|
|
9568
9597
|
this.controller = null;
|
|
9569
9598
|
this.onCoreClose();
|
|
@@ -9577,16 +9606,24 @@ class RemoteClientSessionCore {
|
|
|
9577
9606
|
this.initialized = false;
|
|
9578
9607
|
}
|
|
9579
9608
|
async send(message) {
|
|
9609
|
+
if (this.closed)
|
|
9610
|
+
throw new Error("Session is closed");
|
|
9580
9611
|
if (!this.initialized) {
|
|
9581
9612
|
await this.initialize();
|
|
9582
9613
|
}
|
|
9614
|
+
await this.recoverIdleTransportIfNeeded();
|
|
9583
9615
|
if (!this.controller || !this.runtime) {
|
|
9584
9616
|
throw new Error("Session is not initialized");
|
|
9585
9617
|
}
|
|
9586
9618
|
await this.beforeTurn();
|
|
9587
|
-
const
|
|
9619
|
+
const controller = this.controller;
|
|
9620
|
+
const runtime = this.runtime;
|
|
9621
|
+
if (!controller || !runtime) {
|
|
9622
|
+
throw new Error("Session transport disconnected before the turn was sent");
|
|
9623
|
+
}
|
|
9624
|
+
const turn = this.turns.trackSentTurn(runtime);
|
|
9588
9625
|
try {
|
|
9589
|
-
|
|
9626
|
+
controller.sendTurnMessage(runtime, message, {
|
|
9590
9627
|
clientMessageId: turn.clientMessageId
|
|
9591
9628
|
});
|
|
9592
9629
|
} catch (error) {
|
|
@@ -9851,6 +9888,8 @@ class RemoteClientSessionCore {
|
|
|
9851
9888
|
this.closed = true;
|
|
9852
9889
|
this.removeMessageHandler?.();
|
|
9853
9890
|
this.removeMessageHandler = null;
|
|
9891
|
+
this.detachTransportDisconnect?.();
|
|
9892
|
+
this.detachTransportDisconnect = null;
|
|
9854
9893
|
this.turns.close();
|
|
9855
9894
|
for (const cancel of [...this.deviceStatusRefreshCancels]) {
|
|
9856
9895
|
cancel(new Error(`Session closed while waiting for ${this.label} device status`));
|
|
@@ -9859,6 +9898,7 @@ class RemoteClientSessionCore {
|
|
|
9859
9898
|
this.deviceStatusListeners.clear();
|
|
9860
9899
|
this.controller?.close();
|
|
9861
9900
|
this.controller = null;
|
|
9901
|
+
this.idleTransportDisconnected = false;
|
|
9862
9902
|
this.onCoreClose();
|
|
9863
9903
|
}
|
|
9864
9904
|
get agentId() {
|
|
@@ -9911,6 +9951,78 @@ class RemoteClientSessionCore {
|
|
|
9911
9951
|
}, { predicate: (message) => message.type === "update_toolset_response" });
|
|
9912
9952
|
ensureSuccess(response, "Failed to update toolset");
|
|
9913
9953
|
}
|
|
9954
|
+
watchTransportDisconnect(client, options = {}) {
|
|
9955
|
+
this.detachTransportDisconnect?.();
|
|
9956
|
+
this.detachTransportDisconnect = client.onDisconnect(() => {
|
|
9957
|
+
if (this.closed)
|
|
9958
|
+
return;
|
|
9959
|
+
this.transportDisconnectGeneration += 1;
|
|
9960
|
+
if (options.recoverWhenIdle && !this.turns.hasInFlightTurn()) {
|
|
9961
|
+
this.detachTransportDisconnect?.();
|
|
9962
|
+
this.detachTransportDisconnect = null;
|
|
9963
|
+
this.removeMessageHandler?.();
|
|
9964
|
+
this.removeMessageHandler = null;
|
|
9965
|
+
this.controller?.close();
|
|
9966
|
+
this.controller = null;
|
|
9967
|
+
const error = new Error(`${this.label} connection closed before send`);
|
|
9968
|
+
for (const cancel of [...this.deviceStatusRefreshCancels])
|
|
9969
|
+
cancel(error);
|
|
9970
|
+
this.deviceStatusRefreshCancels.clear();
|
|
9971
|
+
this.onIdleTransportDisconnect();
|
|
9972
|
+
this.idleTransportDisconnected = true;
|
|
9973
|
+
return;
|
|
9974
|
+
}
|
|
9975
|
+
this.turns.closeWithError(`The ${this.label} connection closed unexpectedly; resume the conversation to continue.`);
|
|
9976
|
+
this.close();
|
|
9977
|
+
});
|
|
9978
|
+
}
|
|
9979
|
+
async recoverIdleTransportIfNeeded() {
|
|
9980
|
+
if (!this.idleTransportDisconnected)
|
|
9981
|
+
return;
|
|
9982
|
+
if (this.transportRecoveryPromise) {
|
|
9983
|
+
await this.transportRecoveryPromise;
|
|
9984
|
+
return;
|
|
9985
|
+
}
|
|
9986
|
+
const runtime = this.runtime;
|
|
9987
|
+
if (!runtime)
|
|
9988
|
+
throw new Error("Session transport disconnected without a runtime");
|
|
9989
|
+
const generation = this.transportDisconnectGeneration;
|
|
9990
|
+
const recovery = this.recoverIdleTransport(runtime).then(async (init) => {
|
|
9991
|
+
if (this.closed || generation !== this.transportDisconnectGeneration) {
|
|
9992
|
+
init.controller.close();
|
|
9993
|
+
this.onRecoveredTransportDiscarded();
|
|
9994
|
+
throw new Error(`${this.label} connection closed during recovery`);
|
|
9995
|
+
}
|
|
9996
|
+
if (init.runtime.agent_id !== runtime.agent_id || init.runtime.conversation_id !== runtime.conversation_id) {
|
|
9997
|
+
init.controller.close();
|
|
9998
|
+
this.onRecoveredTransportDiscarded();
|
|
9999
|
+
throw new Error(`${this.label} transport recovered a different runtime`);
|
|
10000
|
+
}
|
|
10001
|
+
this.controller = init.controller;
|
|
10002
|
+
this.runtime = init.runtime;
|
|
10003
|
+
this._modelSettings = init.modelSettings ?? this._modelSettings;
|
|
10004
|
+
if (typeof init.model === "string" && init.model)
|
|
10005
|
+
this._model = init.model;
|
|
10006
|
+
if (init.tools !== undefined)
|
|
10007
|
+
this.toolNames = init.tools;
|
|
10008
|
+
this.removeMessageHandler = this.controller.onMessage((message) => {
|
|
10009
|
+
if (this.runtime)
|
|
10010
|
+
this.turns.handleProtocolMessage(message, this.runtime);
|
|
10011
|
+
});
|
|
10012
|
+
this.idleTransportDisconnected = false;
|
|
10013
|
+
await this.afterRuntimeInitialized();
|
|
10014
|
+
}).finally(() => {
|
|
10015
|
+
if (this.transportRecoveryPromise === recovery)
|
|
10016
|
+
this.transportRecoveryPromise = null;
|
|
10017
|
+
});
|
|
10018
|
+
this.transportRecoveryPromise = recovery;
|
|
10019
|
+
await recovery;
|
|
10020
|
+
}
|
|
10021
|
+
async recoverIdleTransport(_runtime) {
|
|
10022
|
+
throw new Error(`${this.label} sessions do not support idle transport recovery`);
|
|
10023
|
+
}
|
|
10024
|
+
onIdleTransportDisconnect() {}
|
|
10025
|
+
onRecoveredTransportDiscarded() {}
|
|
9914
10026
|
async afterRuntimeInitialized() {}
|
|
9915
10027
|
async beforeTurn() {}
|
|
9916
10028
|
onCoreClose() {}
|
|
@@ -10032,111 +10144,6 @@ function agentToolNames(agent) {
|
|
|
10032
10144
|
return typeof name === "string" && name.length > 0 ? [name] : [];
|
|
10033
10145
|
});
|
|
10034
10146
|
}
|
|
10035
|
-
function isPresetSystemPrompt(value) {
|
|
10036
|
-
return [
|
|
10037
|
-
"default",
|
|
10038
|
-
"letta-claude",
|
|
10039
|
-
"letta-codex",
|
|
10040
|
-
"letta-gemini",
|
|
10041
|
-
"claude",
|
|
10042
|
-
"codex",
|
|
10043
|
-
"gemini"
|
|
10044
|
-
].includes(value);
|
|
10045
|
-
}
|
|
10046
|
-
function assertRemoteCreateAgentOptionsSupported(options) {
|
|
10047
|
-
if (options.allowedTools !== undefined || options.disallowedTools !== undefined) {
|
|
10048
|
-
throw new Error("App-server createAgent() does not yet support allowedTools/disallowedTools.");
|
|
10049
|
-
}
|
|
10050
|
-
if (options.canUseTool !== undefined) {
|
|
10051
|
-
throw new Error("App-server createAgent() does not yet support canUseTool callbacks.");
|
|
10052
|
-
}
|
|
10053
|
-
if (options.systemInfoReminder !== undefined) {
|
|
10054
|
-
throw new Error("App-server createAgent() does not yet support systemInfoReminder overrides.");
|
|
10055
|
-
}
|
|
10056
|
-
if (options.dreaming?.behavior !== undefined) {
|
|
10057
|
-
throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
|
|
10058
|
-
}
|
|
10059
|
-
}
|
|
10060
|
-
function normalizeMemoryBlock(block) {
|
|
10061
|
-
const normalized = { ...block };
|
|
10062
|
-
if (normalized.value === undefined && typeof normalized.content === "string") {
|
|
10063
|
-
normalized.value = normalized.content;
|
|
10064
|
-
}
|
|
10065
|
-
return normalized;
|
|
10066
|
-
}
|
|
10067
|
-
function upsertMemoryBlock(blocks, block) {
|
|
10068
|
-
const label = block.label;
|
|
10069
|
-
if (typeof label === "string") {
|
|
10070
|
-
const existingIndex = blocks.findIndex((candidate) => candidate.label === label);
|
|
10071
|
-
if (existingIndex >= 0) {
|
|
10072
|
-
blocks[existingIndex] = block;
|
|
10073
|
-
return;
|
|
10074
|
-
}
|
|
10075
|
-
}
|
|
10076
|
-
blocks.push(block);
|
|
10077
|
-
}
|
|
10078
|
-
async function createAgentBody(options, settings = {}) {
|
|
10079
|
-
assertRemoteCreateAgentOptionsSupported(options);
|
|
10080
|
-
const includeOriginTag = settings.includeSdkOriginTag ?? true;
|
|
10081
|
-
const body = await buildInitialAgentBody(options);
|
|
10082
|
-
if (Array.isArray(body.tags)) {
|
|
10083
|
-
body.tags = body.tags.filter((tag) => (includeOriginTag || tag !== LETTA_CODE_ORIGIN_TAG) && (options.memfs !== false || tag !== GIT_MEMORY_ENABLED_TAG));
|
|
10084
|
-
}
|
|
10085
|
-
if (options.embedding !== undefined)
|
|
10086
|
-
body.embedding = options.embedding;
|
|
10087
|
-
if (options.hidden !== undefined)
|
|
10088
|
-
body.hidden = options.hidden;
|
|
10089
|
-
if (options.baseTools === undefined) {
|
|
10090
|
-
delete body.tools;
|
|
10091
|
-
delete body.include_base_tools;
|
|
10092
|
-
delete body.include_base_tool_rules;
|
|
10093
|
-
} else {
|
|
10094
|
-
body.tools = options.baseTools;
|
|
10095
|
-
body.include_base_tools = false;
|
|
10096
|
-
body.include_base_tool_rules = false;
|
|
10097
|
-
}
|
|
10098
|
-
if (options.systemPrompt === undefined) {
|
|
10099
|
-
if (options.memfs === false) {
|
|
10100
|
-
body.system = buildSystemPrompt("default", "standard");
|
|
10101
|
-
}
|
|
10102
|
-
} else {
|
|
10103
|
-
if (typeof options.systemPrompt === "string") {
|
|
10104
|
-
if (isPresetSystemPrompt(options.systemPrompt)) {
|
|
10105
|
-
throw new Error("createAgent() does not yet support system prompt presets for this backend.");
|
|
10106
|
-
}
|
|
10107
|
-
body.system = options.systemPrompt;
|
|
10108
|
-
} else {
|
|
10109
|
-
throw new Error("createAgent() does not yet support system prompt preset objects for this backend.");
|
|
10110
|
-
}
|
|
10111
|
-
}
|
|
10112
|
-
const hasMemoryConfiguration = Array.isArray(body.memory_blocks) || options.memory !== undefined || options.persona !== undefined || options.human !== undefined;
|
|
10113
|
-
const memoryBlocks = Array.isArray(body.memory_blocks) ? body.memory_blocks.filter((block) => block !== null && typeof block === "object").map((block) => ({ ...block })) : [];
|
|
10114
|
-
const blockIds = [];
|
|
10115
|
-
for (const item of options.memory ?? []) {
|
|
10116
|
-
if (typeof item === "string") {
|
|
10117
|
-
throw new Error("App-server createAgent() does not yet support memory preset names.");
|
|
10118
|
-
}
|
|
10119
|
-
if ("blockId" in item) {
|
|
10120
|
-
blockIds.push(item.blockId);
|
|
10121
|
-
} else {
|
|
10122
|
-
upsertMemoryBlock(memoryBlocks, normalizeMemoryBlock(item));
|
|
10123
|
-
}
|
|
10124
|
-
}
|
|
10125
|
-
if (options.persona !== undefined) {
|
|
10126
|
-
upsertMemoryBlock(memoryBlocks, {
|
|
10127
|
-
label: "persona",
|
|
10128
|
-
value: options.persona
|
|
10129
|
-
});
|
|
10130
|
-
}
|
|
10131
|
-
if (options.human !== undefined) {
|
|
10132
|
-
upsertMemoryBlock(memoryBlocks, { label: "human", value: options.human });
|
|
10133
|
-
}
|
|
10134
|
-
if (hasMemoryConfiguration)
|
|
10135
|
-
body.memory_blocks = memoryBlocks;
|
|
10136
|
-
if (blockIds.length > 0)
|
|
10137
|
-
body.block_ids = blockIds;
|
|
10138
|
-
return body;
|
|
10139
|
-
}
|
|
10140
10147
|
function externalToolGroups(tools) {
|
|
10141
10148
|
if (!tools || tools.length === 0)
|
|
10142
10149
|
return;
|
|
@@ -10515,6 +10522,7 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
10515
10522
|
if (!response.success || !response.runtime) {
|
|
10516
10523
|
throw new Error(response.error ?? "Failed to start app-server runtime");
|
|
10517
10524
|
}
|
|
10525
|
+
this.watchTransportDisconnect(client);
|
|
10518
10526
|
const tools = agentToolNames(response.agent);
|
|
10519
10527
|
const skillSources = options.skillSources;
|
|
10520
10528
|
const clientToolset = "toolset" in options ? options.toolset : undefined;
|
|
@@ -10597,9 +10605,7 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
10597
10605
|
command.external_tools = groups;
|
|
10598
10606
|
if (this.mode.kind === "create-agent") {
|
|
10599
10607
|
command.create_agent = {
|
|
10600
|
-
body: await createAgentBody(this.mode.options,
|
|
10601
|
-
includeSdkOriginTag: this.remoteOptions.includeSdkOriginTag
|
|
10602
|
-
}),
|
|
10608
|
+
body: await createAgentBody(this.mode.options),
|
|
10603
10609
|
pin_global: this.remoteOptions.pinGlobalAgent ?? this.mode.options.hidden !== true,
|
|
10604
10610
|
...this.mode.options.memfs === false ? { memfs: false } : {}
|
|
10605
10611
|
};
|
|
@@ -10760,6 +10766,132 @@ class CloudManagementTransport {
|
|
|
10760
10766
|
}
|
|
10761
10767
|
}
|
|
10762
10768
|
|
|
10769
|
+
// src/remote.ts
|
|
10770
|
+
function ensureOnline(environment, target) {
|
|
10771
|
+
if (!environment.connectionId) {
|
|
10772
|
+
const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
|
|
10773
|
+
throw new Error(`Computer is offline: ${label}`);
|
|
10774
|
+
}
|
|
10775
|
+
return {
|
|
10776
|
+
connectionId: environment.connectionId,
|
|
10777
|
+
environment,
|
|
10778
|
+
target
|
|
10779
|
+
};
|
|
10780
|
+
}
|
|
10781
|
+
|
|
10782
|
+
class RemoteEnvironmentClient {
|
|
10783
|
+
client;
|
|
10784
|
+
constructor(options = {}, client = createCloudClient({
|
|
10785
|
+
backend: "cloud",
|
|
10786
|
+
apiBaseUrl: options.baseUrl,
|
|
10787
|
+
apiKey: options.apiKey,
|
|
10788
|
+
headers: options.headers,
|
|
10789
|
+
fetch: options.fetch
|
|
10790
|
+
})) {
|
|
10791
|
+
this.client = client;
|
|
10792
|
+
}
|
|
10793
|
+
async listEnvironments(options = {}) {
|
|
10794
|
+
return await this.client.environments.list({
|
|
10795
|
+
after: options.after,
|
|
10796
|
+
limit: options.limit === undefined ? undefined : String(options.limit),
|
|
10797
|
+
onlineOnly: options.onlineOnly === undefined ? undefined : String(options.onlineOnly)
|
|
10798
|
+
});
|
|
10799
|
+
}
|
|
10800
|
+
async getEnvironmentByDeviceId(deviceId) {
|
|
10801
|
+
return await this.client.environments.retrieve(deviceId);
|
|
10802
|
+
}
|
|
10803
|
+
async resolveEnvironment(target) {
|
|
10804
|
+
if ("connectionId" in target) {
|
|
10805
|
+
return { connectionId: target.connectionId, target };
|
|
10806
|
+
}
|
|
10807
|
+
if ("deviceId" in target) {
|
|
10808
|
+
return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
|
|
10809
|
+
}
|
|
10810
|
+
const connections = [];
|
|
10811
|
+
let after;
|
|
10812
|
+
do {
|
|
10813
|
+
const page = await this.listEnvironments({ limit: 100, after });
|
|
10814
|
+
connections.push(...page.connections);
|
|
10815
|
+
if (!page.hasNextPage || page.connections.length === 0)
|
|
10816
|
+
break;
|
|
10817
|
+
after = page.connections.at(-1)?.id;
|
|
10818
|
+
} while (after !== undefined);
|
|
10819
|
+
if ("environmentId" in target) {
|
|
10820
|
+
const match = connections.find((env) => env.id === target.environmentId);
|
|
10821
|
+
if (!match) {
|
|
10822
|
+
throw new Error(`Remote environment not found: ${target.environmentId}`);
|
|
10823
|
+
}
|
|
10824
|
+
return ensureOnline(match, target);
|
|
10825
|
+
}
|
|
10826
|
+
const matches = connections.filter((env) => env.connectionName === target.connectionName);
|
|
10827
|
+
if (matches.length === 0) {
|
|
10828
|
+
throw new Error(`Computer not found: ${target.connectionName}`);
|
|
10829
|
+
}
|
|
10830
|
+
const onlineMatches = matches.filter((environment) => environment.connectionId !== null);
|
|
10831
|
+
if (onlineMatches.length === 0) {
|
|
10832
|
+
throw new Error(`Computer is offline: ${target.connectionName}`);
|
|
10833
|
+
}
|
|
10834
|
+
if (onlineMatches.length > 1) {
|
|
10835
|
+
const candidates = onlineMatches.map((environment) => `${environment.connectionName} (${environment.deviceId}, online)`).join(", ");
|
|
10836
|
+
throw new Error(`Computer name is ambiguous: ${target.connectionName}. Matches: ${candidates}. Select one by deviceId.`);
|
|
10837
|
+
}
|
|
10838
|
+
return ensureOnline(onlineMatches[0], target);
|
|
10839
|
+
}
|
|
10840
|
+
}
|
|
10841
|
+
|
|
10842
|
+
// src/computers.ts
|
|
10843
|
+
function selectorToRemoteTarget(selector) {
|
|
10844
|
+
if (typeof selector === "string")
|
|
10845
|
+
return { connectionName: selector };
|
|
10846
|
+
if ("name" in selector)
|
|
10847
|
+
return { connectionName: selector.name };
|
|
10848
|
+
if ("id" in selector)
|
|
10849
|
+
return { environmentId: selector.id };
|
|
10850
|
+
if ("connectionId" in selector) {
|
|
10851
|
+
return { connectionId: selector.connectionId };
|
|
10852
|
+
}
|
|
10853
|
+
return { deviceId: selector.deviceId };
|
|
10854
|
+
}
|
|
10855
|
+
function toComputer(environment) {
|
|
10856
|
+
return {
|
|
10857
|
+
id: environment.id,
|
|
10858
|
+
deviceId: environment.deviceId,
|
|
10859
|
+
connectionId: environment.connectionId,
|
|
10860
|
+
name: environment.connectionName,
|
|
10861
|
+
status: environment.connectionId ? "online" : "offline",
|
|
10862
|
+
connectedAt: environment.connectedAt,
|
|
10863
|
+
lastSeenAt: environment.lastSeenAt,
|
|
10864
|
+
metadata: environment.metadata
|
|
10865
|
+
};
|
|
10866
|
+
}
|
|
10867
|
+
|
|
10868
|
+
class ComputersClientImpl {
|
|
10869
|
+
environments;
|
|
10870
|
+
constructor(client) {
|
|
10871
|
+
this.environments = new RemoteEnvironmentClient({}, client);
|
|
10872
|
+
}
|
|
10873
|
+
async list(options = {}) {
|
|
10874
|
+
const result = await this.environments.listEnvironments(options);
|
|
10875
|
+
return {
|
|
10876
|
+
computers: result.connections.map(toComputer),
|
|
10877
|
+
hasNextPage: result.hasNextPage
|
|
10878
|
+
};
|
|
10879
|
+
}
|
|
10880
|
+
async get(deviceId) {
|
|
10881
|
+
if (typeof deviceId !== "string" || deviceId.trim().length === 0) {
|
|
10882
|
+
throw new Error("Invalid deviceId. Expected a non-empty string.");
|
|
10883
|
+
}
|
|
10884
|
+
return toComputer(await this.environments.getEnvironmentByDeviceId(deviceId));
|
|
10885
|
+
}
|
|
10886
|
+
async resolve(selector) {
|
|
10887
|
+
const result = await this.environments.resolveEnvironment(selectorToRemoteTarget(selector));
|
|
10888
|
+
return {
|
|
10889
|
+
connectionId: result.connectionId,
|
|
10890
|
+
computer: result.environment ? toComputer(result.environment) : undefined
|
|
10891
|
+
};
|
|
10892
|
+
}
|
|
10893
|
+
}
|
|
10894
|
+
|
|
10763
10895
|
// src/cloud-status-transport.ts
|
|
10764
10896
|
var CONNECTING = 0;
|
|
10765
10897
|
var OPEN = 1;
|
|
@@ -10976,66 +11108,6 @@ function createCloudStatusTransportConstructor(options) {
|
|
|
10976
11108
|
};
|
|
10977
11109
|
}
|
|
10978
11110
|
|
|
10979
|
-
// src/remote.ts
|
|
10980
|
-
function ensureOnline(environment, target) {
|
|
10981
|
-
if (!environment.connectionId) {
|
|
10982
|
-
const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
|
|
10983
|
-
throw new Error(`Remote environment is offline: ${label}`);
|
|
10984
|
-
}
|
|
10985
|
-
return {
|
|
10986
|
-
connectionId: environment.connectionId,
|
|
10987
|
-
environment,
|
|
10988
|
-
target
|
|
10989
|
-
};
|
|
10990
|
-
}
|
|
10991
|
-
|
|
10992
|
-
class RemoteEnvironmentClient {
|
|
10993
|
-
client;
|
|
10994
|
-
constructor(options = {}, client = createCloudClient({
|
|
10995
|
-
backend: "cloud",
|
|
10996
|
-
apiBaseUrl: options.baseUrl,
|
|
10997
|
-
apiKey: options.apiKey,
|
|
10998
|
-
headers: options.headers,
|
|
10999
|
-
fetch: options.fetch
|
|
11000
|
-
})) {
|
|
11001
|
-
this.client = client;
|
|
11002
|
-
}
|
|
11003
|
-
async listEnvironments() {
|
|
11004
|
-
return await this.client.environments.list();
|
|
11005
|
-
}
|
|
11006
|
-
async getEnvironmentByDeviceId(deviceId) {
|
|
11007
|
-
return await this.client.environments.retrieve(deviceId);
|
|
11008
|
-
}
|
|
11009
|
-
async resolveEnvironment(target) {
|
|
11010
|
-
if ("connectionId" in target) {
|
|
11011
|
-
return { connectionId: target.connectionId, target };
|
|
11012
|
-
}
|
|
11013
|
-
if ("deviceId" in target) {
|
|
11014
|
-
return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
|
|
11015
|
-
}
|
|
11016
|
-
const { connections } = await this.listEnvironments();
|
|
11017
|
-
if ("environmentId" in target) {
|
|
11018
|
-
const match2 = connections.find((env) => env.id === target.environmentId);
|
|
11019
|
-
if (!match2) {
|
|
11020
|
-
throw new Error(`Remote environment not found: ${target.environmentId}`);
|
|
11021
|
-
}
|
|
11022
|
-
return ensureOnline(match2, target);
|
|
11023
|
-
}
|
|
11024
|
-
const matches = connections.filter((env) => env.connectionName === target.connectionName);
|
|
11025
|
-
if (matches.length === 0) {
|
|
11026
|
-
throw new Error(`Remote environment not found: ${target.connectionName}`);
|
|
11027
|
-
}
|
|
11028
|
-
if (matches.length > 1) {
|
|
11029
|
-
throw new Error(`Remote environment name is ambiguous: ${target.connectionName}`);
|
|
11030
|
-
}
|
|
11031
|
-
const match = matches[0];
|
|
11032
|
-
if (!match) {
|
|
11033
|
-
throw new Error(`Remote environment not found: ${target.connectionName}`);
|
|
11034
|
-
}
|
|
11035
|
-
return ensureOnline(match, target);
|
|
11036
|
-
}
|
|
11037
|
-
}
|
|
11038
|
-
|
|
11039
11111
|
// src/cloud-sandbox.ts
|
|
11040
11112
|
var MIN_TTL_MINUTES = 1;
|
|
11041
11113
|
var MAX_TTL_MINUTES = 60;
|
|
@@ -11134,8 +11206,12 @@ function validatePositiveInteger3(value, name) {
|
|
|
11134
11206
|
function validateCloudClientOptions(options) {
|
|
11135
11207
|
validatePositiveInteger3(options.requestTimeoutMs, "requestTimeoutMs");
|
|
11136
11208
|
validateCloudSandboxOptions(options.sandbox, "sandbox");
|
|
11137
|
-
if (options.
|
|
11138
|
-
throw new Error("Letta Cloud
|
|
11209
|
+
if (options.computer !== undefined && options.environment !== undefined) {
|
|
11210
|
+
throw new Error("Letta Cloud clients cannot specify both computer and deprecated environment.");
|
|
11211
|
+
}
|
|
11212
|
+
if ((options.computer !== undefined || options.environment !== undefined) && options.sandbox !== undefined) {
|
|
11213
|
+
const field = options.computer !== undefined ? "computer" : "environment";
|
|
11214
|
+
throw new Error(`Letta Cloud sessions cannot specify both ${field} and sandbox options.`);
|
|
11139
11215
|
}
|
|
11140
11216
|
if (options.webSocketAuth !== undefined && options.webSocketAuth !== "header" && options.webSocketAuth !== "query") {
|
|
11141
11217
|
throw new Error("Invalid webSocketAuth. Valid values: header, query.");
|
|
@@ -11252,12 +11328,30 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11252
11328
|
throw error;
|
|
11253
11329
|
});
|
|
11254
11330
|
this.connectionId = connection.connectionId;
|
|
11331
|
+
const options = this.currentOptions();
|
|
11332
|
+
this.mcpBridge = await connectMcpServers("mcpServers" in options ? options.mcpServers : undefined, {
|
|
11333
|
+
cwd: options.cwd,
|
|
11334
|
+
reservedToolNames: this.externalTools.keys()
|
|
11335
|
+
});
|
|
11336
|
+
for (const tool of this.mcpBridge.tools) {
|
|
11337
|
+
this.externalTools.set(tool.name, tool);
|
|
11338
|
+
}
|
|
11339
|
+
try {
|
|
11340
|
+
return await this.openCloudTransport(resolved.runtime, connection.connectionId);
|
|
11341
|
+
} catch (error) {
|
|
11342
|
+
await this.closeMcpBridge();
|
|
11343
|
+
await this.cleanupManagedSandbox();
|
|
11344
|
+
await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
|
|
11345
|
+
throw error;
|
|
11346
|
+
}
|
|
11347
|
+
}
|
|
11348
|
+
async openCloudTransport(runtime, connectionId) {
|
|
11255
11349
|
const apiKey = getCloudApiKey(this.cloudOptions);
|
|
11256
11350
|
const url = buildCloudStatusWebSocketUrl({
|
|
11257
11351
|
apiBaseUrl: this.cloudOptions.apiBaseUrl,
|
|
11258
|
-
connectionId
|
|
11259
|
-
agentId:
|
|
11260
|
-
conversationId:
|
|
11352
|
+
connectionId,
|
|
11353
|
+
agentId: runtime.agent_id,
|
|
11354
|
+
conversationId: runtime.conversation_id,
|
|
11261
11355
|
apiKey,
|
|
11262
11356
|
authMode: this.cloudOptions.webSocketAuth ?? "header"
|
|
11263
11357
|
});
|
|
@@ -11268,32 +11362,19 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11268
11362
|
WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
|
|
11269
11363
|
...(this.cloudOptions.webSocketAuth ?? "header") === "header" ? { headers: cloudWebSocketHeaders(this.cloudOptions) } : {},
|
|
11270
11364
|
pingIntervalMs: this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
|
|
11271
|
-
runtime
|
|
11365
|
+
runtime
|
|
11272
11366
|
}),
|
|
11273
11367
|
requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
|
|
11274
11368
|
}));
|
|
11275
11369
|
const options = this.currentOptions();
|
|
11276
|
-
this.
|
|
11277
|
-
cwd: options.cwd,
|
|
11278
|
-
reservedToolNames: this.externalTools.keys()
|
|
11279
|
-
});
|
|
11280
|
-
for (const tool of this.mcpBridge.tools) {
|
|
11281
|
-
this.externalTools.set(tool.name, tool);
|
|
11282
|
-
}
|
|
11283
|
-
this.removeControlRequestHandler = registerAppServerControlRequestHandler({
|
|
11284
|
-
client,
|
|
11285
|
-
getRuntime: () => this.runtime,
|
|
11286
|
-
getOptions: () => this.currentOptions()
|
|
11287
|
-
});
|
|
11288
|
-
if (this.externalTools.size > 0) {
|
|
11289
|
-
this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
|
|
11290
|
-
}
|
|
11370
|
+
this.installTransportHandlers(client);
|
|
11291
11371
|
try {
|
|
11292
11372
|
await client.connect();
|
|
11293
|
-
const response = await this.startCloudRuntime(client,
|
|
11373
|
+
const response = await this.startCloudRuntime(client, runtime);
|
|
11294
11374
|
if (!response.success || !response.runtime) {
|
|
11295
11375
|
throw new Error(response.error ?? "Failed to start Cloud status runtime");
|
|
11296
11376
|
}
|
|
11377
|
+
this.watchTransportDisconnect(client, { recoverWhenIdle: true });
|
|
11297
11378
|
const tools = agentToolNames(response.agent);
|
|
11298
11379
|
const skillSources = options.skillSources;
|
|
11299
11380
|
const clientToolset = "toolset" in options ? options.toolset : undefined;
|
|
@@ -11311,17 +11392,51 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11311
11392
|
...skillSources !== undefined ? { skillSources: [...skillSources] } : {}
|
|
11312
11393
|
};
|
|
11313
11394
|
} catch (error) {
|
|
11314
|
-
this.
|
|
11315
|
-
this.removeExternalToolHandler = null;
|
|
11316
|
-
this.removeControlRequestHandler?.();
|
|
11317
|
-
this.removeControlRequestHandler = null;
|
|
11318
|
-
await this.closeMcpBridge();
|
|
11395
|
+
this.cleanupTransportHandlers();
|
|
11319
11396
|
client.close();
|
|
11320
|
-
await this.cleanupManagedSandbox();
|
|
11321
|
-
await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
|
|
11322
11397
|
throw error;
|
|
11323
11398
|
}
|
|
11324
11399
|
}
|
|
11400
|
+
installTransportHandlers(client) {
|
|
11401
|
+
this.cleanupTransportHandlers();
|
|
11402
|
+
this.removeControlRequestHandler = registerAppServerControlRequestHandler({
|
|
11403
|
+
client,
|
|
11404
|
+
getRuntime: () => this.runtime,
|
|
11405
|
+
getOptions: () => this.currentOptions()
|
|
11406
|
+
});
|
|
11407
|
+
if (this.externalTools.size > 0) {
|
|
11408
|
+
this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
|
|
11409
|
+
}
|
|
11410
|
+
}
|
|
11411
|
+
cleanupTransportHandlers() {
|
|
11412
|
+
this.removeExternalToolHandler?.();
|
|
11413
|
+
this.removeExternalToolHandler = null;
|
|
11414
|
+
this.removeControlRequestHandler?.();
|
|
11415
|
+
this.removeControlRequestHandler = null;
|
|
11416
|
+
}
|
|
11417
|
+
async recoverIdleTransport(runtime) {
|
|
11418
|
+
const connection = await this.resolveRecoveryConnection(runtime);
|
|
11419
|
+
this.connectionId = connection.connectionId;
|
|
11420
|
+
return this.openCloudTransport(runtime, connection.connectionId);
|
|
11421
|
+
}
|
|
11422
|
+
async resolveRecoveryConnection(runtime) {
|
|
11423
|
+
const sandbox = this.managedSandbox;
|
|
11424
|
+
if (sandbox) {
|
|
11425
|
+
await this.refreshManagedSandbox(sandbox);
|
|
11426
|
+
return this.waitForManagedSandboxConnection(sandbox);
|
|
11427
|
+
}
|
|
11428
|
+
const environment = this.effectiveEnvironment();
|
|
11429
|
+
if (!environment) {
|
|
11430
|
+
throw new Error("Cloud idle transport recovery lost its execution target");
|
|
11431
|
+
}
|
|
11432
|
+
return this.resolveExplicitConnection(environment);
|
|
11433
|
+
}
|
|
11434
|
+
onIdleTransportDisconnect() {
|
|
11435
|
+
this.cleanupTransportHandlers();
|
|
11436
|
+
}
|
|
11437
|
+
onRecoveredTransportDiscarded() {
|
|
11438
|
+
this.cleanupTransportHandlers();
|
|
11439
|
+
}
|
|
11325
11440
|
async startCloudRuntime(client, runtime) {
|
|
11326
11441
|
const options = this.currentOptions();
|
|
11327
11442
|
const command = {
|
|
@@ -11364,10 +11479,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11364
11479
|
await this.refreshManagedSandbox(sandbox);
|
|
11365
11480
|
}
|
|
11366
11481
|
onCoreClose() {
|
|
11367
|
-
this.
|
|
11368
|
-
this.removeExternalToolHandler = null;
|
|
11369
|
-
this.removeControlRequestHandler?.();
|
|
11370
|
-
this.removeControlRequestHandler = null;
|
|
11482
|
+
this.cleanupTransportHandlers();
|
|
11371
11483
|
this.mcpCleanup = this.closeMcpBridge();
|
|
11372
11484
|
this.cleanupManagedSandbox();
|
|
11373
11485
|
if (this.runtime?.agent_id) {
|
|
@@ -11691,8 +11803,8 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11691
11803
|
return new RemoteEnvironmentClient({}, this.apiClient);
|
|
11692
11804
|
}
|
|
11693
11805
|
effectiveEnvironment() {
|
|
11694
|
-
const
|
|
11695
|
-
return
|
|
11806
|
+
const modeComputer = this.mode.kind === "session" ? this.mode.options.computer ?? this.mode.options.environment : undefined;
|
|
11807
|
+
return modeComputer ?? this.cloudOptions.computer ?? this.cloudOptions.environment;
|
|
11696
11808
|
}
|
|
11697
11809
|
effectiveSandboxOptions() {
|
|
11698
11810
|
const modeSandbox = this.mode.kind === "session" ? this.mode.options.sandbox : undefined;
|
|
@@ -11992,14 +12104,17 @@ var VALID_BACKENDS = new Set([
|
|
|
11992
12104
|
function isLettaCodeBackend(value) {
|
|
11993
12105
|
return VALID_BACKENDS.has(value);
|
|
11994
12106
|
}
|
|
11995
|
-
function
|
|
11996
|
-
if ("environment" in options)
|
|
11997
|
-
return
|
|
12107
|
+
function getOptionsComputer(options) {
|
|
12108
|
+
if (!("computer" in options) && !("environment" in options))
|
|
12109
|
+
return;
|
|
12110
|
+
if (options.computer !== undefined && options.environment !== undefined) {
|
|
12111
|
+
throw new Error('Specify either "computer" or deprecated "environment", not both.');
|
|
11998
12112
|
}
|
|
11999
|
-
return;
|
|
12113
|
+
return options.computer ?? options.environment;
|
|
12000
12114
|
}
|
|
12001
12115
|
function stripCloudExecutionOptions(options) {
|
|
12002
12116
|
const sessionOptions = { ...options };
|
|
12117
|
+
delete sessionOptions.computer;
|
|
12003
12118
|
delete sessionOptions.environment;
|
|
12004
12119
|
delete sessionOptions.sandbox;
|
|
12005
12120
|
delete sessionOptions.filesystemConfinement;
|
|
@@ -12017,12 +12132,14 @@ function looksLikeConversationId(id) {
|
|
|
12017
12132
|
|
|
12018
12133
|
class LettaAgentClientBase {
|
|
12019
12134
|
backend;
|
|
12135
|
+
computer;
|
|
12020
12136
|
environment;
|
|
12021
12137
|
agents;
|
|
12022
12138
|
conversations;
|
|
12023
12139
|
models;
|
|
12024
12140
|
options;
|
|
12025
12141
|
repositoriesClient = null;
|
|
12142
|
+
computersClient = null;
|
|
12026
12143
|
agentRepositoriesClient = null;
|
|
12027
12144
|
cloudClient = null;
|
|
12028
12145
|
managementTransport = null;
|
|
@@ -12032,16 +12149,19 @@ class LettaAgentClientBase {
|
|
|
12032
12149
|
throw new Error(`Invalid Letta Code backend '${String(backend)}'. Valid values: local, remote, cloud.`);
|
|
12033
12150
|
}
|
|
12034
12151
|
this.backend = backend;
|
|
12035
|
-
this.
|
|
12152
|
+
this.computer = getOptionsComputer(options);
|
|
12153
|
+
this.environment = this.computer;
|
|
12036
12154
|
this.options = options;
|
|
12037
12155
|
this.agents = createAgentsClient(() => this.getManagementTransport(), () => this.getAgentRepositoriesClient());
|
|
12038
12156
|
this.conversations = createConversationsClient(() => this.getManagementTransport());
|
|
12039
12157
|
this.models = createModelsClient(() => this.getManagementTransport());
|
|
12040
|
-
if (this.backend === "local" && this.
|
|
12041
|
-
|
|
12158
|
+
if (this.backend === "local" && this.computer !== undefined) {
|
|
12159
|
+
const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
|
|
12160
|
+
throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud".`);
|
|
12042
12161
|
}
|
|
12043
|
-
if (this.backend === "remote" && this.
|
|
12044
|
-
|
|
12162
|
+
if (this.backend === "remote" && this.computer !== undefined) {
|
|
12163
|
+
const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
|
|
12164
|
+
throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
12045
12165
|
}
|
|
12046
12166
|
if (this.backend !== "cloud" && options.sandbox !== undefined) {
|
|
12047
12167
|
throw new Error('LettaAgentClient sandbox options are only valid with backend: "cloud".');
|
|
@@ -12075,6 +12195,9 @@ class LettaAgentClientBase {
|
|
|
12075
12195
|
get repositories() {
|
|
12076
12196
|
return this.getRepositoriesClient();
|
|
12077
12197
|
}
|
|
12198
|
+
get computers() {
|
|
12199
|
+
return this.getComputersClient();
|
|
12200
|
+
}
|
|
12078
12201
|
async createAgent(options = {}) {
|
|
12079
12202
|
if (hasCreateAgentEnvironment(options)) {
|
|
12080
12203
|
throw new Error("createAgent() does not accept environment. Set a client default or pass environment to resumeSession()/createSession().");
|
|
@@ -12164,13 +12287,17 @@ class LettaAgentClientBase {
|
|
|
12164
12287
|
}
|
|
12165
12288
|
}
|
|
12166
12289
|
assertSessionBackend(action, options) {
|
|
12290
|
+
if (options.computer !== undefined && options.environment !== undefined) {
|
|
12291
|
+
throw new Error(`${action}() cannot specify both computer and deprecated environment.`);
|
|
12292
|
+
}
|
|
12167
12293
|
if (options.filesystemConfinement !== undefined && options.filesystemConfinement !== "memory") {
|
|
12168
12294
|
throw new Error(`Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`);
|
|
12169
12295
|
}
|
|
12170
|
-
const
|
|
12296
|
+
const effectiveComputer = options.computer ?? options.environment ?? this.computer;
|
|
12171
12297
|
if (this.backend === "local") {
|
|
12172
|
-
if (
|
|
12173
|
-
|
|
12298
|
+
if (effectiveComputer !== undefined) {
|
|
12299
|
+
const field = options.computer !== undefined ? "computer" : "environment";
|
|
12300
|
+
throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud".`);
|
|
12174
12301
|
}
|
|
12175
12302
|
if (options.sandbox !== undefined) {
|
|
12176
12303
|
throw new Error(`${action}() sandbox options are only valid with backend: "cloud".`);
|
|
@@ -12190,8 +12317,9 @@ class LettaAgentClientBase {
|
|
|
12190
12317
|
if (options.filesystemConfinement !== undefined) {
|
|
12191
12318
|
throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
|
|
12192
12319
|
}
|
|
12193
|
-
if (options.environment !== undefined) {
|
|
12194
|
-
|
|
12320
|
+
if (options.computer !== undefined || options.environment !== undefined) {
|
|
12321
|
+
const field = options.computer !== undefined ? "computer" : "environment";
|
|
12322
|
+
throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
12195
12323
|
}
|
|
12196
12324
|
if (options.sandbox !== undefined) {
|
|
12197
12325
|
throw new Error(`${action}() sandbox options are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
@@ -12206,11 +12334,13 @@ class LettaAgentClientBase {
|
|
|
12206
12334
|
throw new Error(`${action}() filesystemConfinement is only supported with backend: "local".`);
|
|
12207
12335
|
}
|
|
12208
12336
|
const cloudOptions = this.cloudOptions();
|
|
12209
|
-
if (
|
|
12210
|
-
|
|
12337
|
+
if (this.computer !== undefined && options.sandbox !== undefined) {
|
|
12338
|
+
const field = cloudOptions.computer !== undefined ? "computer" : "environment";
|
|
12339
|
+
throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default ${field}.`);
|
|
12211
12340
|
}
|
|
12212
|
-
if (cloudOptions.sandbox !== undefined && options.environment !== undefined) {
|
|
12213
|
-
|
|
12341
|
+
if (cloudOptions.sandbox !== undefined && (options.computer !== undefined || options.environment !== undefined)) {
|
|
12342
|
+
const field = options.computer !== undefined ? "a computer" : "an environment";
|
|
12343
|
+
throw new Error(`Letta Cloud ${action}() cannot specify ${field} when the client has default sandbox options.`);
|
|
12214
12344
|
}
|
|
12215
12345
|
assertCloudSessionOptionsSupported(action, options);
|
|
12216
12346
|
return;
|
|
@@ -12241,6 +12371,13 @@ class LettaAgentClientBase {
|
|
|
12241
12371
|
appServerSessionOptions() {
|
|
12242
12372
|
return this.remoteOptions();
|
|
12243
12373
|
}
|
|
12374
|
+
getComputersClient() {
|
|
12375
|
+
if (this.backend !== "cloud") {
|
|
12376
|
+
throw new Error('client.computers is only available with backend: "cloud".');
|
|
12377
|
+
}
|
|
12378
|
+
this.computersClient ??= new ComputersClientImpl(this.getCloudClient());
|
|
12379
|
+
return this.computersClient;
|
|
12380
|
+
}
|
|
12244
12381
|
getRepositoriesClient() {
|
|
12245
12382
|
if (this.backend !== "cloud") {
|
|
12246
12383
|
throw new Error('client.repositories is only available with backend: "cloud".');
|
|
@@ -29499,7 +29636,7 @@ class StreamableHTTPClientTransport {
|
|
|
29499
29636
|
}
|
|
29500
29637
|
var DEFAULT_CLIENT_INFO = {
|
|
29501
29638
|
name: "letta-code",
|
|
29502
|
-
version: "0.30.
|
|
29639
|
+
version: "0.30.5"
|
|
29503
29640
|
};
|
|
29504
29641
|
async function connectMcpServer(config2, options = {}) {
|
|
29505
29642
|
let client = new Client(options.clientInfo ?? DEFAULT_CLIENT_INFO);
|
|
@@ -29997,4 +30134,4 @@ export {
|
|
|
29997
30134
|
CloudManagedSandboxExpiredError
|
|
29998
30135
|
};
|
|
29999
30136
|
|
|
30000
|
-
//# debugId=
|
|
30137
|
+
//# debugId=C079C2D0B42E0C4F64756E2164756E21
|