@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/client-entry.js
CHANGED
|
@@ -3177,36 +3177,6 @@ function appServerSocketOptions(authToken) {
|
|
|
3177
3177
|
}
|
|
3178
3178
|
return { headers: { Authorization: `Bearer ${token}` } };
|
|
3179
3179
|
}
|
|
3180
|
-
function sameRuntime(a, b) {
|
|
3181
|
-
return a?.agent_id === b.agent_id && a?.conversation_id === b.conversation_id;
|
|
3182
|
-
}
|
|
3183
|
-
function isWaitingLoopStatus(message) {
|
|
3184
|
-
return message.loop_status.status === "WAITING_ON_INPUT";
|
|
3185
|
-
}
|
|
3186
|
-
function isWaitingOnApprovalLoopStatus(message) {
|
|
3187
|
-
return message.loop_status.status === "WAITING_ON_APPROVAL";
|
|
3188
|
-
}
|
|
3189
|
-
function streamDeltaRunId(message) {
|
|
3190
|
-
const runId = message.delta.run_id;
|
|
3191
|
-
return typeof runId === "string" ? runId : null;
|
|
3192
|
-
}
|
|
3193
|
-
function streamDeltaMessageType(message) {
|
|
3194
|
-
const messageType = message.delta.message_type;
|
|
3195
|
-
return typeof messageType === "string" ? messageType : null;
|
|
3196
|
-
}
|
|
3197
|
-
function streamDeltaStopReason(message) {
|
|
3198
|
-
const stopReason = message.delta.stop_reason;
|
|
3199
|
-
return typeof stopReason === "string" ? stopReason : null;
|
|
3200
|
-
}
|
|
3201
|
-
function streamDeltaErrorMessage(message) {
|
|
3202
|
-
const delta = message.delta;
|
|
3203
|
-
const apiMessage = delta.api_error?.message ?? delta.api_error?.detail;
|
|
3204
|
-
if (typeof apiMessage === "string" && apiMessage.length > 0)
|
|
3205
|
-
return apiMessage;
|
|
3206
|
-
if (typeof delta.message === "string" && delta.message.length > 0)
|
|
3207
|
-
return delta.message;
|
|
3208
|
-
return "App-server turn failed";
|
|
3209
|
-
}
|
|
3210
3180
|
|
|
3211
3181
|
class AppServerClient {
|
|
3212
3182
|
socket;
|
|
@@ -3217,7 +3187,6 @@ class AppServerClient {
|
|
|
3217
3187
|
messageHandlers = new Set;
|
|
3218
3188
|
sendHandlers = new Set;
|
|
3219
3189
|
disconnectHandlers = new Set;
|
|
3220
|
-
activeTurnRuntimes = new Set;
|
|
3221
3190
|
explicitlyClosed = false;
|
|
3222
3191
|
disconnectNotified = false;
|
|
3223
3192
|
nextRequestNumber = 0;
|
|
@@ -3400,111 +3369,15 @@ class AppServerClient {
|
|
|
3400
3369
|
input(command) {
|
|
3401
3370
|
this.send({ type: "input", ...command });
|
|
3402
3371
|
}
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
const runIds = new Set;
|
|
3412
|
-
let observedTurnEvidence = false;
|
|
3413
|
-
let observedRequiresApprovalStop = false;
|
|
3414
|
-
return new Promise((resolve, reject) => {
|
|
3415
|
-
const timeout = setTimeout(() => {
|
|
3416
|
-
cleanup();
|
|
3417
|
-
reject(new Error(`Timed out waiting for app-server turn on ${command.runtime.agent_id}/${command.runtime.conversation_id}`));
|
|
3418
|
-
}, timeoutMs);
|
|
3419
|
-
const cleanup = () => {
|
|
3420
|
-
clearTimeout(timeout);
|
|
3421
|
-
this.activeTurnRuntimes.delete(runtimeKey);
|
|
3422
|
-
offMessage();
|
|
3423
|
-
};
|
|
3424
|
-
const finish = (completedBy, terminalMessage, stopReason) => {
|
|
3425
|
-
cleanup();
|
|
3426
|
-
resolve({
|
|
3427
|
-
runtime: command.runtime,
|
|
3428
|
-
stopReason,
|
|
3429
|
-
runIds: [...runIds],
|
|
3430
|
-
clientMessageIds: commandWithIds.clientMessageIds,
|
|
3431
|
-
completedBy,
|
|
3432
|
-
terminalMessage
|
|
3433
|
-
});
|
|
3434
|
-
};
|
|
3435
|
-
const fail = (error) => {
|
|
3436
|
-
cleanup();
|
|
3437
|
-
reject(error);
|
|
3438
|
-
};
|
|
3439
|
-
const offMessage = this.onMessage((message) => {
|
|
3440
|
-
if (!sameRuntime(message.runtime, command.runtime)) {
|
|
3441
|
-
return;
|
|
3442
|
-
}
|
|
3443
|
-
if (message.type === "stream_delta") {
|
|
3444
|
-
observedTurnEvidence = true;
|
|
3445
|
-
const runId = streamDeltaRunId(message);
|
|
3446
|
-
if (runId)
|
|
3447
|
-
runIds.add(runId);
|
|
3448
|
-
const messageType = streamDeltaMessageType(message);
|
|
3449
|
-
if (messageType === "loop_error" || messageType === "error_message") {
|
|
3450
|
-
fail(new Error(streamDeltaErrorMessage(message)));
|
|
3451
|
-
return;
|
|
3452
|
-
}
|
|
3453
|
-
if (messageType === "stop_reason") {
|
|
3454
|
-
const stopReason = streamDeltaStopReason(message);
|
|
3455
|
-
if (stopReason === "requires_approval") {
|
|
3456
|
-
observedRequiresApprovalStop = true;
|
|
3457
|
-
return;
|
|
3458
|
-
}
|
|
3459
|
-
finish("stop_reason", message, stopReason);
|
|
3460
|
-
}
|
|
3461
|
-
return;
|
|
3462
|
-
}
|
|
3463
|
-
if (message.type === "update_loop_status") {
|
|
3464
|
-
const hadTurnEvidenceBeforeLoopStatus = observedTurnEvidence || observedRequiresApprovalStop;
|
|
3465
|
-
if (!hadTurnEvidenceBeforeLoopStatus && (isWaitingOnApprovalLoopStatus(message) || options.allowLoopStatusFallback === true && isWaitingLoopStatus(message))) {
|
|
3466
|
-
return;
|
|
3467
|
-
}
|
|
3468
|
-
for (const runId of message.loop_status.active_run_ids) {
|
|
3469
|
-
observedTurnEvidence = true;
|
|
3470
|
-
runIds.add(runId);
|
|
3471
|
-
}
|
|
3472
|
-
if (hadTurnEvidenceBeforeLoopStatus && isWaitingOnApprovalLoopStatus(message)) {
|
|
3473
|
-
finish("loop_status_waiting_on_approval", message, "requires_approval");
|
|
3474
|
-
return;
|
|
3475
|
-
}
|
|
3476
|
-
if (options.allowLoopStatusFallback === true && hadTurnEvidenceBeforeLoopStatus && isWaitingLoopStatus(message)) {
|
|
3477
|
-
finish("loop_status_waiting_fallback", message, null);
|
|
3478
|
-
}
|
|
3479
|
-
}
|
|
3480
|
-
});
|
|
3481
|
-
try {
|
|
3482
|
-
this.input(commandWithIds.command);
|
|
3483
|
-
} catch (error) {
|
|
3484
|
-
fail(error instanceof Error ? error : new Error(String(error)));
|
|
3485
|
-
}
|
|
3486
|
-
});
|
|
3487
|
-
}
|
|
3488
|
-
withClientMessageIds(command) {
|
|
3489
|
-
if (command.payload.kind !== "create_message") {
|
|
3490
|
-
return { command, clientMessageIds: [] };
|
|
3491
|
-
}
|
|
3492
|
-
const clientMessageIds = [];
|
|
3493
|
-
const messages = command.payload.messages.map((message) => {
|
|
3494
|
-
if (message.role !== "user")
|
|
3495
|
-
return message;
|
|
3496
|
-
const existing = message.client_message_id;
|
|
3497
|
-
const clientMessageId = typeof existing === "string" && existing.length > 0 ? existing : this.nextRequestId("client-message");
|
|
3498
|
-
clientMessageIds.push(clientMessageId);
|
|
3499
|
-
return { ...message, client_message_id: clientMessageId };
|
|
3372
|
+
submitInput(command, options = {}) {
|
|
3373
|
+
return this.request({
|
|
3374
|
+
type: "input",
|
|
3375
|
+
request_id: command.request_id ?? this.nextRequestId("input"),
|
|
3376
|
+
...command
|
|
3377
|
+
}, {
|
|
3378
|
+
...options,
|
|
3379
|
+
predicate: (message) => message.type === "input_accepted"
|
|
3500
3380
|
});
|
|
3501
|
-
return {
|
|
3502
|
-
command: {
|
|
3503
|
-
...command,
|
|
3504
|
-
payload: { ...command.payload, messages }
|
|
3505
|
-
},
|
|
3506
|
-
clientMessageIds
|
|
3507
|
-
};
|
|
3508
3381
|
}
|
|
3509
3382
|
handleMessage(event, channel) {
|
|
3510
3383
|
const message = parseProtocolMessage(event);
|
|
@@ -6438,6 +6311,73 @@ var models_default = {
|
|
|
6438
6311
|
parallel_tool_calls: true
|
|
6439
6312
|
}
|
|
6440
6313
|
},
|
|
6314
|
+
{
|
|
6315
|
+
id: "opus-5",
|
|
6316
|
+
handle: "anthropic/claude-opus-5",
|
|
6317
|
+
label: "Opus 5",
|
|
6318
|
+
description: "Opus 5 (high reasoning)",
|
|
6319
|
+
updateArgs: {
|
|
6320
|
+
context_window: 200000,
|
|
6321
|
+
max_output_tokens: 128000,
|
|
6322
|
+
enable_reasoner: true,
|
|
6323
|
+
reasoning_effort: "high",
|
|
6324
|
+
parallel_tool_calls: true
|
|
6325
|
+
}
|
|
6326
|
+
},
|
|
6327
|
+
{
|
|
6328
|
+
id: "opus-5-low",
|
|
6329
|
+
handle: "anthropic/claude-opus-5",
|
|
6330
|
+
label: "Opus 5",
|
|
6331
|
+
description: "Opus 5 (low reasoning)",
|
|
6332
|
+
updateArgs: {
|
|
6333
|
+
context_window: 200000,
|
|
6334
|
+
max_output_tokens: 128000,
|
|
6335
|
+
enable_reasoner: true,
|
|
6336
|
+
reasoning_effort: "low",
|
|
6337
|
+
max_reasoning_tokens: 4000,
|
|
6338
|
+
parallel_tool_calls: true
|
|
6339
|
+
}
|
|
6340
|
+
},
|
|
6341
|
+
{
|
|
6342
|
+
id: "opus-5-medium",
|
|
6343
|
+
handle: "anthropic/claude-opus-5",
|
|
6344
|
+
label: "Opus 5",
|
|
6345
|
+
description: "Opus 5 (med reasoning)",
|
|
6346
|
+
updateArgs: {
|
|
6347
|
+
context_window: 200000,
|
|
6348
|
+
max_output_tokens: 128000,
|
|
6349
|
+
enable_reasoner: true,
|
|
6350
|
+
reasoning_effort: "medium",
|
|
6351
|
+
max_reasoning_tokens: 12000,
|
|
6352
|
+
parallel_tool_calls: true
|
|
6353
|
+
}
|
|
6354
|
+
},
|
|
6355
|
+
{
|
|
6356
|
+
id: "opus-5-xhigh",
|
|
6357
|
+
handle: "anthropic/claude-opus-5",
|
|
6358
|
+
label: "Opus 5",
|
|
6359
|
+
description: "Opus 5 (extra-high reasoning)",
|
|
6360
|
+
updateArgs: {
|
|
6361
|
+
context_window: 200000,
|
|
6362
|
+
max_output_tokens: 128000,
|
|
6363
|
+
enable_reasoner: true,
|
|
6364
|
+
reasoning_effort: "xhigh",
|
|
6365
|
+
parallel_tool_calls: true
|
|
6366
|
+
}
|
|
6367
|
+
},
|
|
6368
|
+
{
|
|
6369
|
+
id: "opus-5-max",
|
|
6370
|
+
handle: "anthropic/claude-opus-5",
|
|
6371
|
+
label: "Opus 5",
|
|
6372
|
+
description: "Opus 5 (max reasoning)",
|
|
6373
|
+
updateArgs: {
|
|
6374
|
+
context_window: 200000,
|
|
6375
|
+
max_output_tokens: 128000,
|
|
6376
|
+
enable_reasoner: true,
|
|
6377
|
+
reasoning_effort: "max",
|
|
6378
|
+
parallel_tool_calls: true
|
|
6379
|
+
}
|
|
6380
|
+
},
|
|
6441
6381
|
{
|
|
6442
6382
|
id: "opus",
|
|
6443
6383
|
handle: "anthropic/claude-opus-4-8",
|
|
@@ -6712,7 +6652,7 @@ var models_default = {
|
|
|
6712
6652
|
id: "sonnet-5-xhigh",
|
|
6713
6653
|
handle: "anthropic/claude-sonnet-5",
|
|
6714
6654
|
label: "Sonnet 5",
|
|
6715
|
-
description: "Sonnet 5 (
|
|
6655
|
+
description: "Sonnet 5 (extra-high reasoning)",
|
|
6716
6656
|
updateArgs: {
|
|
6717
6657
|
context_window: 1e6,
|
|
6718
6658
|
max_output_tokens: 128000,
|
|
@@ -6721,6 +6661,19 @@ var models_default = {
|
|
|
6721
6661
|
parallel_tool_calls: true
|
|
6722
6662
|
}
|
|
6723
6663
|
},
|
|
6664
|
+
{
|
|
6665
|
+
id: "sonnet-5-max",
|
|
6666
|
+
handle: "anthropic/claude-sonnet-5",
|
|
6667
|
+
label: "Sonnet 5",
|
|
6668
|
+
description: "Sonnet 5 (max reasoning)",
|
|
6669
|
+
updateArgs: {
|
|
6670
|
+
context_window: 1e6,
|
|
6671
|
+
max_output_tokens: 128000,
|
|
6672
|
+
reasoning_effort: "max",
|
|
6673
|
+
enable_reasoner: true,
|
|
6674
|
+
parallel_tool_calls: true
|
|
6675
|
+
}
|
|
6676
|
+
},
|
|
6724
6677
|
{
|
|
6725
6678
|
id: "sonnet-4.6",
|
|
6726
6679
|
handle: "anthropic/claude-sonnet-4-6",
|
|
@@ -8271,7 +8224,6 @@ var models_default = {
|
|
|
8271
8224
|
]
|
|
8272
8225
|
};
|
|
8273
8226
|
var models = models_default.models;
|
|
8274
|
-
var MODEL_PRESETS = models;
|
|
8275
8227
|
function resolveModel(modelIdentifier) {
|
|
8276
8228
|
const byId = models.find((m) => m.id === modelIdentifier);
|
|
8277
8229
|
if (byId)
|
|
@@ -8499,75 +8451,128 @@ function buildPersonalityMemoryBlocks(personalityId, defaultMemoryBlocks, enviro
|
|
|
8499
8451
|
}
|
|
8500
8452
|
var LETTA_CODE_AGENT_TYPE = "letta_v1_agent";
|
|
8501
8453
|
var DEFAULT_CREATED_AGENT_BASE_TOOLS = ["web_search", "fetch_webpage"];
|
|
8502
|
-
|
|
8503
|
-
const
|
|
8504
|
-
const
|
|
8505
|
-
|
|
8454
|
+
function mergeMemoryBlocks(base, overrides) {
|
|
8455
|
+
const blocks = base.map((block) => ({ ...block }));
|
|
8456
|
+
for (const override of overrides ?? []) {
|
|
8457
|
+
const index = blocks.findIndex((block) => block.label === override.label);
|
|
8458
|
+
if (index >= 0) {
|
|
8459
|
+
blocks[index] = { ...override };
|
|
8460
|
+
} else {
|
|
8461
|
+
blocks.push({ ...override });
|
|
8462
|
+
}
|
|
8463
|
+
}
|
|
8464
|
+
return blocks;
|
|
8465
|
+
}
|
|
8466
|
+
async function buildCreateAgentRequest(options = {}) {
|
|
8467
|
+
const personality = options.personalityId ? getPersonalityOption(options.personalityId) : undefined;
|
|
8468
|
+
const modelIdentifier = options.model ?? personality?.defaultModel;
|
|
8506
8469
|
const modelHandle = modelIdentifier ? resolveModel(modelIdentifier) : getDefaultModel();
|
|
8507
8470
|
if (!modelHandle) {
|
|
8508
8471
|
throw new Error(`Unknown model: ${modelIdentifier}`);
|
|
8509
8472
|
}
|
|
8510
|
-
|
|
8473
|
+
if (!options.isSubagent && options.enableMemfs !== undefined && options.memoryPromptMode !== undefined && options.enableMemfs !== (options.memoryPromptMode !== "standard")) {
|
|
8474
|
+
throw new Error("enableMemfs and memoryPromptMode must describe the same memory mode");
|
|
8475
|
+
}
|
|
8476
|
+
const enableMemfs = options.isSubagent ? false : options.enableMemfs ?? options.memoryPromptMode !== "standard";
|
|
8477
|
+
const memoryPromptMode = options.isSubagent ? "standard" : options.memoryPromptMode ?? (enableMemfs ? "memfs" : "standard");
|
|
8478
|
+
const personalityTags = options.personalityId ? getPersonalityCreationTags(options.personalityId) : [];
|
|
8479
|
+
const personalityBlocks = options.personalityId ? buildPersonalityMemoryBlocks(options.personalityId, await getDefaultMemoryBlocks()) : [];
|
|
8480
|
+
const memoryBlocks = options.isSubagent ? undefined : options.personalityId || options.memoryBlocks !== undefined ? mergeMemoryBlocks(personalityBlocks, options.memoryBlocks) : undefined;
|
|
8481
|
+
const blockIds = options.isSubagent ? undefined : options.blockIds;
|
|
8511
8482
|
return {
|
|
8512
8483
|
agent_type: LETTA_CODE_AGENT_TYPE,
|
|
8513
|
-
name: name ?? personality
|
|
8514
|
-
description: description ?? personality
|
|
8484
|
+
...options.name !== undefined || personality ? { name: options.name ?? personality?.label } : {},
|
|
8485
|
+
...options.description !== undefined || personality ? { description: options.description ?? personality?.description } : {},
|
|
8515
8486
|
model: modelHandle,
|
|
8516
|
-
system: buildSystemPrompt("default",
|
|
8517
|
-
memory_blocks:
|
|
8487
|
+
system: options.system ?? buildSystemPrompt("default", memoryPromptMode),
|
|
8488
|
+
...memoryBlocks !== undefined ? { memory_blocks: memoryBlocks } : {},
|
|
8489
|
+
...blockIds && blockIds.length > 0 ? { block_ids: blockIds } : {},
|
|
8518
8490
|
tags: buildCreatedAgentTags({
|
|
8519
|
-
enableMemfs
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
...extraTags ?? []
|
|
8523
|
-
]
|
|
8491
|
+
enableMemfs,
|
|
8492
|
+
isSubagent: options.isSubagent,
|
|
8493
|
+
tags: [...personalityTags, ...options.extraTags ?? []]
|
|
8524
8494
|
}),
|
|
8525
|
-
tools: [...DEFAULT_CREATED_AGENT_BASE_TOOLS],
|
|
8495
|
+
tools: [...options.baseTools ?? DEFAULT_CREATED_AGENT_BASE_TOOLS],
|
|
8526
8496
|
include_base_tools: false,
|
|
8527
8497
|
include_base_tool_rules: false,
|
|
8528
8498
|
initial_message_sequence: [],
|
|
8529
|
-
parallel_tool_calls: true,
|
|
8530
|
-
compaction_settings: {
|
|
8499
|
+
parallel_tool_calls: options.parallelToolCalls ?? true,
|
|
8500
|
+
compaction_settings: {
|
|
8501
|
+
model: options.compactionModel ?? DEFAULT_SUMMARIZATION_MODEL
|
|
8502
|
+
},
|
|
8503
|
+
...options.embedding !== undefined ? { embedding: options.embedding } : {},
|
|
8504
|
+
...options.isSubagent ? { hidden: true } : options.hidden !== undefined ? { hidden: options.hidden } : {}
|
|
8531
8505
|
};
|
|
8532
8506
|
}
|
|
8533
8507
|
|
|
8534
8508
|
// src/agent-creation.ts
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8509
|
+
function isPresetSystemPrompt(value) {
|
|
8510
|
+
return [
|
|
8511
|
+
"default",
|
|
8512
|
+
"letta-claude",
|
|
8513
|
+
"letta-codex",
|
|
8514
|
+
"letta-gemini",
|
|
8515
|
+
"claude",
|
|
8516
|
+
"codex",
|
|
8517
|
+
"gemini"
|
|
8518
|
+
].includes(value);
|
|
8544
8519
|
}
|
|
8545
|
-
|
|
8546
|
-
if (options.
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8520
|
+
function assertCreateAgentOptionsSupported(options) {
|
|
8521
|
+
if (options.allowedTools !== undefined || options.disallowedTools !== undefined) {
|
|
8522
|
+
throw new Error("App-server createAgent() does not yet support allowedTools/disallowedTools.");
|
|
8523
|
+
}
|
|
8524
|
+
if (options.canUseTool !== undefined) {
|
|
8525
|
+
throw new Error("App-server createAgent() does not yet support canUseTool callbacks.");
|
|
8526
|
+
}
|
|
8527
|
+
if (options.systemInfoReminder !== undefined) {
|
|
8528
|
+
throw new Error("App-server createAgent() does not yet support systemInfoReminder overrides.");
|
|
8529
|
+
}
|
|
8530
|
+
if (options.dreaming?.behavior !== undefined) {
|
|
8531
|
+
throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
|
|
8556
8532
|
}
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8533
|
+
}
|
|
8534
|
+
async function createAgentBody(options) {
|
|
8535
|
+
assertCreateAgentOptionsSupported(options);
|
|
8536
|
+
let system;
|
|
8537
|
+
if (options.systemPrompt !== undefined) {
|
|
8538
|
+
if (typeof options.systemPrompt !== "string" || isPresetSystemPrompt(options.systemPrompt)) {
|
|
8539
|
+
throw new Error("createAgent() does not yet support system prompt presets for this backend.");
|
|
8540
|
+
}
|
|
8541
|
+
system = options.systemPrompt;
|
|
8542
|
+
}
|
|
8543
|
+
const memoryBlocks = [];
|
|
8544
|
+
const blockIds = [];
|
|
8545
|
+
for (const item of options.memory ?? []) {
|
|
8546
|
+
if (typeof item === "string") {
|
|
8547
|
+
throw new Error("App-server createAgent() does not yet support memory preset names.");
|
|
8548
|
+
}
|
|
8549
|
+
if ("blockId" in item) {
|
|
8550
|
+
blockIds.push(item.blockId);
|
|
8551
|
+
} else {
|
|
8552
|
+
memoryBlocks.push({ ...item });
|
|
8553
|
+
}
|
|
8554
|
+
}
|
|
8555
|
+
if (options.persona !== undefined) {
|
|
8556
|
+
memoryBlocks.push({ label: "persona", value: options.persona });
|
|
8557
|
+
}
|
|
8558
|
+
if (options.human !== undefined) {
|
|
8559
|
+
memoryBlocks.push({ label: "human", value: options.human });
|
|
8560
|
+
}
|
|
8561
|
+
const hasMemoryConfiguration = options.memory !== undefined || options.persona !== undefined || options.human !== undefined;
|
|
8562
|
+
return buildCreateAgentRequest({
|
|
8563
|
+
personalityId: options.personality,
|
|
8564
|
+
name: options.name,
|
|
8565
|
+
description: options.description,
|
|
8566
|
+
model: options.model,
|
|
8567
|
+
system,
|
|
8568
|
+
memoryBlocks: hasMemoryConfiguration ? memoryBlocks : undefined,
|
|
8569
|
+
blockIds,
|
|
8570
|
+
extraTags: options.tags,
|
|
8571
|
+
enableMemfs: options.memfs ?? true,
|
|
8572
|
+
baseTools: options.baseTools,
|
|
8573
|
+
embedding: options.embedding,
|
|
8574
|
+
hidden: options.hidden
|
|
8575
|
+
});
|
|
8571
8576
|
}
|
|
8572
8577
|
|
|
8573
8578
|
// src/interactiveToolPolicy.ts
|
|
@@ -8856,7 +8861,7 @@ function firstToolReturn(delta) {
|
|
|
8856
8861
|
}
|
|
8857
8862
|
return;
|
|
8858
8863
|
}
|
|
8859
|
-
function
|
|
8864
|
+
function sameRuntime(message, runtime) {
|
|
8860
8865
|
const msgRuntime = message.runtime;
|
|
8861
8866
|
if (msgRuntime) {
|
|
8862
8867
|
return msgRuntime.agent_id === runtime.agent_id && msgRuntime.conversation_id === runtime.conversation_id;
|
|
@@ -8875,10 +8880,10 @@ function streamDeltaRecord(message) {
|
|
|
8875
8880
|
const delta = message.delta;
|
|
8876
8881
|
return delta && typeof delta === "object" && !Array.isArray(delta) ? delta : null;
|
|
8877
8882
|
}
|
|
8878
|
-
function
|
|
8883
|
+
function streamDeltaMessageType(delta) {
|
|
8879
8884
|
return typeof delta.message_type === "string" ? delta.message_type : undefined;
|
|
8880
8885
|
}
|
|
8881
|
-
function
|
|
8886
|
+
function streamDeltaRunId(delta) {
|
|
8882
8887
|
return typeof delta.run_id === "string" ? delta.run_id : undefined;
|
|
8883
8888
|
}
|
|
8884
8889
|
function streamDeltaOtid(delta) {
|
|
@@ -8887,7 +8892,7 @@ function streamDeltaOtid(delta) {
|
|
|
8887
8892
|
function streamDeltaSeqId(delta) {
|
|
8888
8893
|
return typeof delta.seq_id === "number" ? delta.seq_id : undefined;
|
|
8889
8894
|
}
|
|
8890
|
-
function
|
|
8895
|
+
function streamDeltaStopReason(delta) {
|
|
8891
8896
|
return typeof delta.stop_reason === "string" ? delta.stop_reason : undefined;
|
|
8892
8897
|
}
|
|
8893
8898
|
function loopStatusRecord(message) {
|
|
@@ -9110,7 +9115,7 @@ class RemoteTurnCoordinator {
|
|
|
9110
9115
|
this.activeTurn.abortRequested = true;
|
|
9111
9116
|
}
|
|
9112
9117
|
handleProtocolMessage(message, runtime) {
|
|
9113
|
-
if (!
|
|
9118
|
+
if (!sameRuntime(message, runtime))
|
|
9114
9119
|
return;
|
|
9115
9120
|
const statusRecord = deviceStatusRecord(message);
|
|
9116
9121
|
if (statusRecord) {
|
|
@@ -9137,7 +9142,7 @@ class RemoteTurnCoordinator {
|
|
|
9137
9142
|
const active = this.activateNextTurnFromProtocol();
|
|
9138
9143
|
if (active) {
|
|
9139
9144
|
active.observedTurnEvidence = true;
|
|
9140
|
-
const runId =
|
|
9145
|
+
const runId = streamDeltaRunId(delta);
|
|
9141
9146
|
if (runId)
|
|
9142
9147
|
active.runIds.add(runId);
|
|
9143
9148
|
}
|
|
@@ -9156,6 +9161,24 @@ class RemoteTurnCoordinator {
|
|
|
9156
9161
|
this.streamResolvers.push(resolve);
|
|
9157
9162
|
});
|
|
9158
9163
|
}
|
|
9164
|
+
closeWithError(detail) {
|
|
9165
|
+
if (this.closed)
|
|
9166
|
+
return;
|
|
9167
|
+
const active = this.activeTurn;
|
|
9168
|
+
if (active) {
|
|
9169
|
+
this.failTurn(active, detail);
|
|
9170
|
+
} else {
|
|
9171
|
+
this.enqueue({
|
|
9172
|
+
type: "error",
|
|
9173
|
+
message: detail,
|
|
9174
|
+
errorCode: "error",
|
|
9175
|
+
stopReason: "error",
|
|
9176
|
+
errorDetail: detail,
|
|
9177
|
+
recoverable: false
|
|
9178
|
+
});
|
|
9179
|
+
}
|
|
9180
|
+
this.close();
|
|
9181
|
+
}
|
|
9159
9182
|
close() {
|
|
9160
9183
|
if (this.closed)
|
|
9161
9184
|
return;
|
|
@@ -9273,9 +9296,9 @@ class RemoteTurnCoordinator {
|
|
|
9273
9296
|
const active = this.activeTurn;
|
|
9274
9297
|
if (!active)
|
|
9275
9298
|
return;
|
|
9276
|
-
const messageType =
|
|
9299
|
+
const messageType = streamDeltaMessageType(delta);
|
|
9277
9300
|
if (messageType === "stop_reason") {
|
|
9278
|
-
const stopReason =
|
|
9301
|
+
const stopReason = streamDeltaStopReason(delta) ?? null;
|
|
9279
9302
|
if (stopReason === "requires_approval") {
|
|
9280
9303
|
active.observedRequiresApprovalStop = true;
|
|
9281
9304
|
return;
|
|
@@ -9469,6 +9492,10 @@ class RemoteClientSessionCore {
|
|
|
9469
9492
|
requestTimeoutMs;
|
|
9470
9493
|
initializePromise = null;
|
|
9471
9494
|
removeMessageHandler = null;
|
|
9495
|
+
detachTransportDisconnect = null;
|
|
9496
|
+
idleTransportDisconnected = false;
|
|
9497
|
+
transportRecoveryPromise = null;
|
|
9498
|
+
transportDisconnectGeneration = 0;
|
|
9472
9499
|
turns;
|
|
9473
9500
|
toolNames;
|
|
9474
9501
|
deviceStatusListeners = new Set;
|
|
@@ -9543,6 +9570,8 @@ class RemoteClientSessionCore {
|
|
|
9543
9570
|
cleanupFailedInitialize() {
|
|
9544
9571
|
this.removeMessageHandler?.();
|
|
9545
9572
|
this.removeMessageHandler = null;
|
|
9573
|
+
this.detachTransportDisconnect?.();
|
|
9574
|
+
this.detachTransportDisconnect = null;
|
|
9546
9575
|
this.controller?.close();
|
|
9547
9576
|
this.controller = null;
|
|
9548
9577
|
this.onCoreClose();
|
|
@@ -9556,16 +9585,24 @@ class RemoteClientSessionCore {
|
|
|
9556
9585
|
this.initialized = false;
|
|
9557
9586
|
}
|
|
9558
9587
|
async send(message) {
|
|
9588
|
+
if (this.closed)
|
|
9589
|
+
throw new Error("Session is closed");
|
|
9559
9590
|
if (!this.initialized) {
|
|
9560
9591
|
await this.initialize();
|
|
9561
9592
|
}
|
|
9593
|
+
await this.recoverIdleTransportIfNeeded();
|
|
9562
9594
|
if (!this.controller || !this.runtime) {
|
|
9563
9595
|
throw new Error("Session is not initialized");
|
|
9564
9596
|
}
|
|
9565
9597
|
await this.beforeTurn();
|
|
9566
|
-
const
|
|
9598
|
+
const controller = this.controller;
|
|
9599
|
+
const runtime = this.runtime;
|
|
9600
|
+
if (!controller || !runtime) {
|
|
9601
|
+
throw new Error("Session transport disconnected before the turn was sent");
|
|
9602
|
+
}
|
|
9603
|
+
const turn = this.turns.trackSentTurn(runtime);
|
|
9567
9604
|
try {
|
|
9568
|
-
|
|
9605
|
+
controller.sendTurnMessage(runtime, message, {
|
|
9569
9606
|
clientMessageId: turn.clientMessageId
|
|
9570
9607
|
});
|
|
9571
9608
|
} catch (error) {
|
|
@@ -9830,6 +9867,8 @@ class RemoteClientSessionCore {
|
|
|
9830
9867
|
this.closed = true;
|
|
9831
9868
|
this.removeMessageHandler?.();
|
|
9832
9869
|
this.removeMessageHandler = null;
|
|
9870
|
+
this.detachTransportDisconnect?.();
|
|
9871
|
+
this.detachTransportDisconnect = null;
|
|
9833
9872
|
this.turns.close();
|
|
9834
9873
|
for (const cancel of [...this.deviceStatusRefreshCancels]) {
|
|
9835
9874
|
cancel(new Error(`Session closed while waiting for ${this.label} device status`));
|
|
@@ -9838,6 +9877,7 @@ class RemoteClientSessionCore {
|
|
|
9838
9877
|
this.deviceStatusListeners.clear();
|
|
9839
9878
|
this.controller?.close();
|
|
9840
9879
|
this.controller = null;
|
|
9880
|
+
this.idleTransportDisconnected = false;
|
|
9841
9881
|
this.onCoreClose();
|
|
9842
9882
|
}
|
|
9843
9883
|
get agentId() {
|
|
@@ -9890,6 +9930,78 @@ class RemoteClientSessionCore {
|
|
|
9890
9930
|
}, { predicate: (message) => message.type === "update_toolset_response" });
|
|
9891
9931
|
ensureSuccess(response, "Failed to update toolset");
|
|
9892
9932
|
}
|
|
9933
|
+
watchTransportDisconnect(client, options = {}) {
|
|
9934
|
+
this.detachTransportDisconnect?.();
|
|
9935
|
+
this.detachTransportDisconnect = client.onDisconnect(() => {
|
|
9936
|
+
if (this.closed)
|
|
9937
|
+
return;
|
|
9938
|
+
this.transportDisconnectGeneration += 1;
|
|
9939
|
+
if (options.recoverWhenIdle && !this.turns.hasInFlightTurn()) {
|
|
9940
|
+
this.detachTransportDisconnect?.();
|
|
9941
|
+
this.detachTransportDisconnect = null;
|
|
9942
|
+
this.removeMessageHandler?.();
|
|
9943
|
+
this.removeMessageHandler = null;
|
|
9944
|
+
this.controller?.close();
|
|
9945
|
+
this.controller = null;
|
|
9946
|
+
const error = new Error(`${this.label} connection closed before send`);
|
|
9947
|
+
for (const cancel of [...this.deviceStatusRefreshCancels])
|
|
9948
|
+
cancel(error);
|
|
9949
|
+
this.deviceStatusRefreshCancels.clear();
|
|
9950
|
+
this.onIdleTransportDisconnect();
|
|
9951
|
+
this.idleTransportDisconnected = true;
|
|
9952
|
+
return;
|
|
9953
|
+
}
|
|
9954
|
+
this.turns.closeWithError(`The ${this.label} connection closed unexpectedly; resume the conversation to continue.`);
|
|
9955
|
+
this.close();
|
|
9956
|
+
});
|
|
9957
|
+
}
|
|
9958
|
+
async recoverIdleTransportIfNeeded() {
|
|
9959
|
+
if (!this.idleTransportDisconnected)
|
|
9960
|
+
return;
|
|
9961
|
+
if (this.transportRecoveryPromise) {
|
|
9962
|
+
await this.transportRecoveryPromise;
|
|
9963
|
+
return;
|
|
9964
|
+
}
|
|
9965
|
+
const runtime = this.runtime;
|
|
9966
|
+
if (!runtime)
|
|
9967
|
+
throw new Error("Session transport disconnected without a runtime");
|
|
9968
|
+
const generation = this.transportDisconnectGeneration;
|
|
9969
|
+
const recovery = this.recoverIdleTransport(runtime).then(async (init) => {
|
|
9970
|
+
if (this.closed || generation !== this.transportDisconnectGeneration) {
|
|
9971
|
+
init.controller.close();
|
|
9972
|
+
this.onRecoveredTransportDiscarded();
|
|
9973
|
+
throw new Error(`${this.label} connection closed during recovery`);
|
|
9974
|
+
}
|
|
9975
|
+
if (init.runtime.agent_id !== runtime.agent_id || init.runtime.conversation_id !== runtime.conversation_id) {
|
|
9976
|
+
init.controller.close();
|
|
9977
|
+
this.onRecoveredTransportDiscarded();
|
|
9978
|
+
throw new Error(`${this.label} transport recovered a different runtime`);
|
|
9979
|
+
}
|
|
9980
|
+
this.controller = init.controller;
|
|
9981
|
+
this.runtime = init.runtime;
|
|
9982
|
+
this._modelSettings = init.modelSettings ?? this._modelSettings;
|
|
9983
|
+
if (typeof init.model === "string" && init.model)
|
|
9984
|
+
this._model = init.model;
|
|
9985
|
+
if (init.tools !== undefined)
|
|
9986
|
+
this.toolNames = init.tools;
|
|
9987
|
+
this.removeMessageHandler = this.controller.onMessage((message) => {
|
|
9988
|
+
if (this.runtime)
|
|
9989
|
+
this.turns.handleProtocolMessage(message, this.runtime);
|
|
9990
|
+
});
|
|
9991
|
+
this.idleTransportDisconnected = false;
|
|
9992
|
+
await this.afterRuntimeInitialized();
|
|
9993
|
+
}).finally(() => {
|
|
9994
|
+
if (this.transportRecoveryPromise === recovery)
|
|
9995
|
+
this.transportRecoveryPromise = null;
|
|
9996
|
+
});
|
|
9997
|
+
this.transportRecoveryPromise = recovery;
|
|
9998
|
+
await recovery;
|
|
9999
|
+
}
|
|
10000
|
+
async recoverIdleTransport(_runtime) {
|
|
10001
|
+
throw new Error(`${this.label} sessions do not support idle transport recovery`);
|
|
10002
|
+
}
|
|
10003
|
+
onIdleTransportDisconnect() {}
|
|
10004
|
+
onRecoveredTransportDiscarded() {}
|
|
9893
10005
|
async afterRuntimeInitialized() {}
|
|
9894
10006
|
async beforeTurn() {}
|
|
9895
10007
|
onCoreClose() {}
|
|
@@ -10011,111 +10123,6 @@ function agentToolNames(agent) {
|
|
|
10011
10123
|
return typeof name === "string" && name.length > 0 ? [name] : [];
|
|
10012
10124
|
});
|
|
10013
10125
|
}
|
|
10014
|
-
function isPresetSystemPrompt(value) {
|
|
10015
|
-
return [
|
|
10016
|
-
"default",
|
|
10017
|
-
"letta-claude",
|
|
10018
|
-
"letta-codex",
|
|
10019
|
-
"letta-gemini",
|
|
10020
|
-
"claude",
|
|
10021
|
-
"codex",
|
|
10022
|
-
"gemini"
|
|
10023
|
-
].includes(value);
|
|
10024
|
-
}
|
|
10025
|
-
function assertRemoteCreateAgentOptionsSupported(options) {
|
|
10026
|
-
if (options.allowedTools !== undefined || options.disallowedTools !== undefined) {
|
|
10027
|
-
throw new Error("App-server createAgent() does not yet support allowedTools/disallowedTools.");
|
|
10028
|
-
}
|
|
10029
|
-
if (options.canUseTool !== undefined) {
|
|
10030
|
-
throw new Error("App-server createAgent() does not yet support canUseTool callbacks.");
|
|
10031
|
-
}
|
|
10032
|
-
if (options.systemInfoReminder !== undefined) {
|
|
10033
|
-
throw new Error("App-server createAgent() does not yet support systemInfoReminder overrides.");
|
|
10034
|
-
}
|
|
10035
|
-
if (options.dreaming?.behavior !== undefined) {
|
|
10036
|
-
throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
|
|
10037
|
-
}
|
|
10038
|
-
}
|
|
10039
|
-
function normalizeMemoryBlock(block) {
|
|
10040
|
-
const normalized = { ...block };
|
|
10041
|
-
if (normalized.value === undefined && typeof normalized.content === "string") {
|
|
10042
|
-
normalized.value = normalized.content;
|
|
10043
|
-
}
|
|
10044
|
-
return normalized;
|
|
10045
|
-
}
|
|
10046
|
-
function upsertMemoryBlock(blocks, block) {
|
|
10047
|
-
const label = block.label;
|
|
10048
|
-
if (typeof label === "string") {
|
|
10049
|
-
const existingIndex = blocks.findIndex((candidate) => candidate.label === label);
|
|
10050
|
-
if (existingIndex >= 0) {
|
|
10051
|
-
blocks[existingIndex] = block;
|
|
10052
|
-
return;
|
|
10053
|
-
}
|
|
10054
|
-
}
|
|
10055
|
-
blocks.push(block);
|
|
10056
|
-
}
|
|
10057
|
-
async function createAgentBody(options, settings = {}) {
|
|
10058
|
-
assertRemoteCreateAgentOptionsSupported(options);
|
|
10059
|
-
const includeOriginTag = settings.includeSdkOriginTag ?? true;
|
|
10060
|
-
const body = await buildInitialAgentBody(options);
|
|
10061
|
-
if (Array.isArray(body.tags)) {
|
|
10062
|
-
body.tags = body.tags.filter((tag) => (includeOriginTag || tag !== LETTA_CODE_ORIGIN_TAG) && (options.memfs !== false || tag !== GIT_MEMORY_ENABLED_TAG));
|
|
10063
|
-
}
|
|
10064
|
-
if (options.embedding !== undefined)
|
|
10065
|
-
body.embedding = options.embedding;
|
|
10066
|
-
if (options.hidden !== undefined)
|
|
10067
|
-
body.hidden = options.hidden;
|
|
10068
|
-
if (options.baseTools === undefined) {
|
|
10069
|
-
delete body.tools;
|
|
10070
|
-
delete body.include_base_tools;
|
|
10071
|
-
delete body.include_base_tool_rules;
|
|
10072
|
-
} else {
|
|
10073
|
-
body.tools = options.baseTools;
|
|
10074
|
-
body.include_base_tools = false;
|
|
10075
|
-
body.include_base_tool_rules = false;
|
|
10076
|
-
}
|
|
10077
|
-
if (options.systemPrompt === undefined) {
|
|
10078
|
-
if (options.memfs === false) {
|
|
10079
|
-
body.system = buildSystemPrompt("default", "standard");
|
|
10080
|
-
}
|
|
10081
|
-
} else {
|
|
10082
|
-
if (typeof options.systemPrompt === "string") {
|
|
10083
|
-
if (isPresetSystemPrompt(options.systemPrompt)) {
|
|
10084
|
-
throw new Error("createAgent() does not yet support system prompt presets for this backend.");
|
|
10085
|
-
}
|
|
10086
|
-
body.system = options.systemPrompt;
|
|
10087
|
-
} else {
|
|
10088
|
-
throw new Error("createAgent() does not yet support system prompt preset objects for this backend.");
|
|
10089
|
-
}
|
|
10090
|
-
}
|
|
10091
|
-
const hasMemoryConfiguration = Array.isArray(body.memory_blocks) || options.memory !== undefined || options.persona !== undefined || options.human !== undefined;
|
|
10092
|
-
const memoryBlocks = Array.isArray(body.memory_blocks) ? body.memory_blocks.filter((block) => block !== null && typeof block === "object").map((block) => ({ ...block })) : [];
|
|
10093
|
-
const blockIds = [];
|
|
10094
|
-
for (const item of options.memory ?? []) {
|
|
10095
|
-
if (typeof item === "string") {
|
|
10096
|
-
throw new Error("App-server createAgent() does not yet support memory preset names.");
|
|
10097
|
-
}
|
|
10098
|
-
if ("blockId" in item) {
|
|
10099
|
-
blockIds.push(item.blockId);
|
|
10100
|
-
} else {
|
|
10101
|
-
upsertMemoryBlock(memoryBlocks, normalizeMemoryBlock(item));
|
|
10102
|
-
}
|
|
10103
|
-
}
|
|
10104
|
-
if (options.persona !== undefined) {
|
|
10105
|
-
upsertMemoryBlock(memoryBlocks, {
|
|
10106
|
-
label: "persona",
|
|
10107
|
-
value: options.persona
|
|
10108
|
-
});
|
|
10109
|
-
}
|
|
10110
|
-
if (options.human !== undefined) {
|
|
10111
|
-
upsertMemoryBlock(memoryBlocks, { label: "human", value: options.human });
|
|
10112
|
-
}
|
|
10113
|
-
if (hasMemoryConfiguration)
|
|
10114
|
-
body.memory_blocks = memoryBlocks;
|
|
10115
|
-
if (blockIds.length > 0)
|
|
10116
|
-
body.block_ids = blockIds;
|
|
10117
|
-
return body;
|
|
10118
|
-
}
|
|
10119
10126
|
function externalToolGroups(tools) {
|
|
10120
10127
|
if (!tools || tools.length === 0)
|
|
10121
10128
|
return;
|
|
@@ -10494,6 +10501,7 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
10494
10501
|
if (!response.success || !response.runtime) {
|
|
10495
10502
|
throw new Error(response.error ?? "Failed to start app-server runtime");
|
|
10496
10503
|
}
|
|
10504
|
+
this.watchTransportDisconnect(client);
|
|
10497
10505
|
const tools = agentToolNames(response.agent);
|
|
10498
10506
|
const skillSources = options.skillSources;
|
|
10499
10507
|
const clientToolset = "toolset" in options ? options.toolset : undefined;
|
|
@@ -10576,9 +10584,7 @@ class AppServerSession extends RemoteClientSessionCore {
|
|
|
10576
10584
|
command.external_tools = groups;
|
|
10577
10585
|
if (this.mode.kind === "create-agent") {
|
|
10578
10586
|
command.create_agent = {
|
|
10579
|
-
body: await createAgentBody(this.mode.options,
|
|
10580
|
-
includeSdkOriginTag: this.remoteOptions.includeSdkOriginTag
|
|
10581
|
-
}),
|
|
10587
|
+
body: await createAgentBody(this.mode.options),
|
|
10582
10588
|
pin_global: this.remoteOptions.pinGlobalAgent ?? this.mode.options.hidden !== true,
|
|
10583
10589
|
...this.mode.options.memfs === false ? { memfs: false } : {}
|
|
10584
10590
|
};
|
|
@@ -10739,6 +10745,132 @@ class CloudManagementTransport {
|
|
|
10739
10745
|
}
|
|
10740
10746
|
}
|
|
10741
10747
|
|
|
10748
|
+
// src/remote.ts
|
|
10749
|
+
function ensureOnline(environment, target) {
|
|
10750
|
+
if (!environment.connectionId) {
|
|
10751
|
+
const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
|
|
10752
|
+
throw new Error(`Computer is offline: ${label}`);
|
|
10753
|
+
}
|
|
10754
|
+
return {
|
|
10755
|
+
connectionId: environment.connectionId,
|
|
10756
|
+
environment,
|
|
10757
|
+
target
|
|
10758
|
+
};
|
|
10759
|
+
}
|
|
10760
|
+
|
|
10761
|
+
class RemoteEnvironmentClient {
|
|
10762
|
+
client;
|
|
10763
|
+
constructor(options = {}, client = createCloudClient({
|
|
10764
|
+
backend: "cloud",
|
|
10765
|
+
apiBaseUrl: options.baseUrl,
|
|
10766
|
+
apiKey: options.apiKey,
|
|
10767
|
+
headers: options.headers,
|
|
10768
|
+
fetch: options.fetch
|
|
10769
|
+
})) {
|
|
10770
|
+
this.client = client;
|
|
10771
|
+
}
|
|
10772
|
+
async listEnvironments(options = {}) {
|
|
10773
|
+
return await this.client.environments.list({
|
|
10774
|
+
after: options.after,
|
|
10775
|
+
limit: options.limit === undefined ? undefined : String(options.limit),
|
|
10776
|
+
onlineOnly: options.onlineOnly === undefined ? undefined : String(options.onlineOnly)
|
|
10777
|
+
});
|
|
10778
|
+
}
|
|
10779
|
+
async getEnvironmentByDeviceId(deviceId) {
|
|
10780
|
+
return await this.client.environments.retrieve(deviceId);
|
|
10781
|
+
}
|
|
10782
|
+
async resolveEnvironment(target) {
|
|
10783
|
+
if ("connectionId" in target) {
|
|
10784
|
+
return { connectionId: target.connectionId, target };
|
|
10785
|
+
}
|
|
10786
|
+
if ("deviceId" in target) {
|
|
10787
|
+
return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
|
|
10788
|
+
}
|
|
10789
|
+
const connections = [];
|
|
10790
|
+
let after;
|
|
10791
|
+
do {
|
|
10792
|
+
const page = await this.listEnvironments({ limit: 100, after });
|
|
10793
|
+
connections.push(...page.connections);
|
|
10794
|
+
if (!page.hasNextPage || page.connections.length === 0)
|
|
10795
|
+
break;
|
|
10796
|
+
after = page.connections.at(-1)?.id;
|
|
10797
|
+
} while (after !== undefined);
|
|
10798
|
+
if ("environmentId" in target) {
|
|
10799
|
+
const match = connections.find((env) => env.id === target.environmentId);
|
|
10800
|
+
if (!match) {
|
|
10801
|
+
throw new Error(`Remote environment not found: ${target.environmentId}`);
|
|
10802
|
+
}
|
|
10803
|
+
return ensureOnline(match, target);
|
|
10804
|
+
}
|
|
10805
|
+
const matches = connections.filter((env) => env.connectionName === target.connectionName);
|
|
10806
|
+
if (matches.length === 0) {
|
|
10807
|
+
throw new Error(`Computer not found: ${target.connectionName}`);
|
|
10808
|
+
}
|
|
10809
|
+
const onlineMatches = matches.filter((environment) => environment.connectionId !== null);
|
|
10810
|
+
if (onlineMatches.length === 0) {
|
|
10811
|
+
throw new Error(`Computer is offline: ${target.connectionName}`);
|
|
10812
|
+
}
|
|
10813
|
+
if (onlineMatches.length > 1) {
|
|
10814
|
+
const candidates = onlineMatches.map((environment) => `${environment.connectionName} (${environment.deviceId}, online)`).join(", ");
|
|
10815
|
+
throw new Error(`Computer name is ambiguous: ${target.connectionName}. Matches: ${candidates}. Select one by deviceId.`);
|
|
10816
|
+
}
|
|
10817
|
+
return ensureOnline(onlineMatches[0], target);
|
|
10818
|
+
}
|
|
10819
|
+
}
|
|
10820
|
+
|
|
10821
|
+
// src/computers.ts
|
|
10822
|
+
function selectorToRemoteTarget(selector) {
|
|
10823
|
+
if (typeof selector === "string")
|
|
10824
|
+
return { connectionName: selector };
|
|
10825
|
+
if ("name" in selector)
|
|
10826
|
+
return { connectionName: selector.name };
|
|
10827
|
+
if ("id" in selector)
|
|
10828
|
+
return { environmentId: selector.id };
|
|
10829
|
+
if ("connectionId" in selector) {
|
|
10830
|
+
return { connectionId: selector.connectionId };
|
|
10831
|
+
}
|
|
10832
|
+
return { deviceId: selector.deviceId };
|
|
10833
|
+
}
|
|
10834
|
+
function toComputer(environment) {
|
|
10835
|
+
return {
|
|
10836
|
+
id: environment.id,
|
|
10837
|
+
deviceId: environment.deviceId,
|
|
10838
|
+
connectionId: environment.connectionId,
|
|
10839
|
+
name: environment.connectionName,
|
|
10840
|
+
status: environment.connectionId ? "online" : "offline",
|
|
10841
|
+
connectedAt: environment.connectedAt,
|
|
10842
|
+
lastSeenAt: environment.lastSeenAt,
|
|
10843
|
+
metadata: environment.metadata
|
|
10844
|
+
};
|
|
10845
|
+
}
|
|
10846
|
+
|
|
10847
|
+
class ComputersClientImpl {
|
|
10848
|
+
environments;
|
|
10849
|
+
constructor(client) {
|
|
10850
|
+
this.environments = new RemoteEnvironmentClient({}, client);
|
|
10851
|
+
}
|
|
10852
|
+
async list(options = {}) {
|
|
10853
|
+
const result = await this.environments.listEnvironments(options);
|
|
10854
|
+
return {
|
|
10855
|
+
computers: result.connections.map(toComputer),
|
|
10856
|
+
hasNextPage: result.hasNextPage
|
|
10857
|
+
};
|
|
10858
|
+
}
|
|
10859
|
+
async get(deviceId) {
|
|
10860
|
+
if (typeof deviceId !== "string" || deviceId.trim().length === 0) {
|
|
10861
|
+
throw new Error("Invalid deviceId. Expected a non-empty string.");
|
|
10862
|
+
}
|
|
10863
|
+
return toComputer(await this.environments.getEnvironmentByDeviceId(deviceId));
|
|
10864
|
+
}
|
|
10865
|
+
async resolve(selector) {
|
|
10866
|
+
const result = await this.environments.resolveEnvironment(selectorToRemoteTarget(selector));
|
|
10867
|
+
return {
|
|
10868
|
+
connectionId: result.connectionId,
|
|
10869
|
+
computer: result.environment ? toComputer(result.environment) : undefined
|
|
10870
|
+
};
|
|
10871
|
+
}
|
|
10872
|
+
}
|
|
10873
|
+
|
|
10742
10874
|
// src/cloud-status-transport.ts
|
|
10743
10875
|
var CONNECTING = 0;
|
|
10744
10876
|
var OPEN = 1;
|
|
@@ -10955,66 +11087,6 @@ function createCloudStatusTransportConstructor(options) {
|
|
|
10955
11087
|
};
|
|
10956
11088
|
}
|
|
10957
11089
|
|
|
10958
|
-
// src/remote.ts
|
|
10959
|
-
function ensureOnline(environment, target) {
|
|
10960
|
-
if (!environment.connectionId) {
|
|
10961
|
-
const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
|
|
10962
|
-
throw new Error(`Remote environment is offline: ${label}`);
|
|
10963
|
-
}
|
|
10964
|
-
return {
|
|
10965
|
-
connectionId: environment.connectionId,
|
|
10966
|
-
environment,
|
|
10967
|
-
target
|
|
10968
|
-
};
|
|
10969
|
-
}
|
|
10970
|
-
|
|
10971
|
-
class RemoteEnvironmentClient {
|
|
10972
|
-
client;
|
|
10973
|
-
constructor(options = {}, client = createCloudClient({
|
|
10974
|
-
backend: "cloud",
|
|
10975
|
-
apiBaseUrl: options.baseUrl,
|
|
10976
|
-
apiKey: options.apiKey,
|
|
10977
|
-
headers: options.headers,
|
|
10978
|
-
fetch: options.fetch
|
|
10979
|
-
})) {
|
|
10980
|
-
this.client = client;
|
|
10981
|
-
}
|
|
10982
|
-
async listEnvironments() {
|
|
10983
|
-
return await this.client.environments.list();
|
|
10984
|
-
}
|
|
10985
|
-
async getEnvironmentByDeviceId(deviceId) {
|
|
10986
|
-
return await this.client.environments.retrieve(deviceId);
|
|
10987
|
-
}
|
|
10988
|
-
async resolveEnvironment(target) {
|
|
10989
|
-
if ("connectionId" in target) {
|
|
10990
|
-
return { connectionId: target.connectionId, target };
|
|
10991
|
-
}
|
|
10992
|
-
if ("deviceId" in target) {
|
|
10993
|
-
return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
|
|
10994
|
-
}
|
|
10995
|
-
const { connections } = await this.listEnvironments();
|
|
10996
|
-
if ("environmentId" in target) {
|
|
10997
|
-
const match2 = connections.find((env) => env.id === target.environmentId);
|
|
10998
|
-
if (!match2) {
|
|
10999
|
-
throw new Error(`Remote environment not found: ${target.environmentId}`);
|
|
11000
|
-
}
|
|
11001
|
-
return ensureOnline(match2, target);
|
|
11002
|
-
}
|
|
11003
|
-
const matches = connections.filter((env) => env.connectionName === target.connectionName);
|
|
11004
|
-
if (matches.length === 0) {
|
|
11005
|
-
throw new Error(`Remote environment not found: ${target.connectionName}`);
|
|
11006
|
-
}
|
|
11007
|
-
if (matches.length > 1) {
|
|
11008
|
-
throw new Error(`Remote environment name is ambiguous: ${target.connectionName}`);
|
|
11009
|
-
}
|
|
11010
|
-
const match = matches[0];
|
|
11011
|
-
if (!match) {
|
|
11012
|
-
throw new Error(`Remote environment not found: ${target.connectionName}`);
|
|
11013
|
-
}
|
|
11014
|
-
return ensureOnline(match, target);
|
|
11015
|
-
}
|
|
11016
|
-
}
|
|
11017
|
-
|
|
11018
11090
|
// src/cloud-sandbox.ts
|
|
11019
11091
|
var MIN_TTL_MINUTES = 1;
|
|
11020
11092
|
var MAX_TTL_MINUTES = 60;
|
|
@@ -11113,8 +11185,12 @@ function validatePositiveInteger3(value, name) {
|
|
|
11113
11185
|
function validateCloudClientOptions(options) {
|
|
11114
11186
|
validatePositiveInteger3(options.requestTimeoutMs, "requestTimeoutMs");
|
|
11115
11187
|
validateCloudSandboxOptions(options.sandbox, "sandbox");
|
|
11116
|
-
if (options.
|
|
11117
|
-
throw new Error("Letta Cloud
|
|
11188
|
+
if (options.computer !== undefined && options.environment !== undefined) {
|
|
11189
|
+
throw new Error("Letta Cloud clients cannot specify both computer and deprecated environment.");
|
|
11190
|
+
}
|
|
11191
|
+
if ((options.computer !== undefined || options.environment !== undefined) && options.sandbox !== undefined) {
|
|
11192
|
+
const field = options.computer !== undefined ? "computer" : "environment";
|
|
11193
|
+
throw new Error(`Letta Cloud sessions cannot specify both ${field} and sandbox options.`);
|
|
11118
11194
|
}
|
|
11119
11195
|
if (options.webSocketAuth !== undefined && options.webSocketAuth !== "header" && options.webSocketAuth !== "query") {
|
|
11120
11196
|
throw new Error("Invalid webSocketAuth. Valid values: header, query.");
|
|
@@ -11231,12 +11307,30 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11231
11307
|
throw error;
|
|
11232
11308
|
});
|
|
11233
11309
|
this.connectionId = connection.connectionId;
|
|
11310
|
+
const options = this.currentOptions();
|
|
11311
|
+
this.mcpBridge = await connectMcpServers("mcpServers" in options ? options.mcpServers : undefined, {
|
|
11312
|
+
cwd: options.cwd,
|
|
11313
|
+
reservedToolNames: this.externalTools.keys()
|
|
11314
|
+
});
|
|
11315
|
+
for (const tool of this.mcpBridge.tools) {
|
|
11316
|
+
this.externalTools.set(tool.name, tool);
|
|
11317
|
+
}
|
|
11318
|
+
try {
|
|
11319
|
+
return await this.openCloudTransport(resolved.runtime, connection.connectionId);
|
|
11320
|
+
} catch (error) {
|
|
11321
|
+
await this.closeMcpBridge();
|
|
11322
|
+
await this.cleanupManagedSandbox();
|
|
11323
|
+
await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
|
|
11324
|
+
throw error;
|
|
11325
|
+
}
|
|
11326
|
+
}
|
|
11327
|
+
async openCloudTransport(runtime, connectionId) {
|
|
11234
11328
|
const apiKey = getCloudApiKey(this.cloudOptions);
|
|
11235
11329
|
const url = buildCloudStatusWebSocketUrl({
|
|
11236
11330
|
apiBaseUrl: this.cloudOptions.apiBaseUrl,
|
|
11237
|
-
connectionId
|
|
11238
|
-
agentId:
|
|
11239
|
-
conversationId:
|
|
11331
|
+
connectionId,
|
|
11332
|
+
agentId: runtime.agent_id,
|
|
11333
|
+
conversationId: runtime.conversation_id,
|
|
11240
11334
|
apiKey,
|
|
11241
11335
|
authMode: this.cloudOptions.webSocketAuth ?? "header"
|
|
11242
11336
|
});
|
|
@@ -11247,32 +11341,19 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11247
11341
|
WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
|
|
11248
11342
|
...(this.cloudOptions.webSocketAuth ?? "header") === "header" ? { headers: cloudWebSocketHeaders(this.cloudOptions) } : {},
|
|
11249
11343
|
pingIntervalMs: this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
|
|
11250
|
-
runtime
|
|
11344
|
+
runtime
|
|
11251
11345
|
}),
|
|
11252
11346
|
requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
|
|
11253
11347
|
}));
|
|
11254
11348
|
const options = this.currentOptions();
|
|
11255
|
-
this.
|
|
11256
|
-
cwd: options.cwd,
|
|
11257
|
-
reservedToolNames: this.externalTools.keys()
|
|
11258
|
-
});
|
|
11259
|
-
for (const tool of this.mcpBridge.tools) {
|
|
11260
|
-
this.externalTools.set(tool.name, tool);
|
|
11261
|
-
}
|
|
11262
|
-
this.removeControlRequestHandler = registerAppServerControlRequestHandler({
|
|
11263
|
-
client,
|
|
11264
|
-
getRuntime: () => this.runtime,
|
|
11265
|
-
getOptions: () => this.currentOptions()
|
|
11266
|
-
});
|
|
11267
|
-
if (this.externalTools.size > 0) {
|
|
11268
|
-
this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
|
|
11269
|
-
}
|
|
11349
|
+
this.installTransportHandlers(client);
|
|
11270
11350
|
try {
|
|
11271
11351
|
await client.connect();
|
|
11272
|
-
const response = await this.startCloudRuntime(client,
|
|
11352
|
+
const response = await this.startCloudRuntime(client, runtime);
|
|
11273
11353
|
if (!response.success || !response.runtime) {
|
|
11274
11354
|
throw new Error(response.error ?? "Failed to start Cloud status runtime");
|
|
11275
11355
|
}
|
|
11356
|
+
this.watchTransportDisconnect(client, { recoverWhenIdle: true });
|
|
11276
11357
|
const tools = agentToolNames(response.agent);
|
|
11277
11358
|
const skillSources = options.skillSources;
|
|
11278
11359
|
const clientToolset = "toolset" in options ? options.toolset : undefined;
|
|
@@ -11290,17 +11371,51 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11290
11371
|
...skillSources !== undefined ? { skillSources: [...skillSources] } : {}
|
|
11291
11372
|
};
|
|
11292
11373
|
} catch (error) {
|
|
11293
|
-
this.
|
|
11294
|
-
this.removeExternalToolHandler = null;
|
|
11295
|
-
this.removeControlRequestHandler?.();
|
|
11296
|
-
this.removeControlRequestHandler = null;
|
|
11297
|
-
await this.closeMcpBridge();
|
|
11374
|
+
this.cleanupTransportHandlers();
|
|
11298
11375
|
client.close();
|
|
11299
|
-
await this.cleanupManagedSandbox();
|
|
11300
|
-
await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
|
|
11301
11376
|
throw error;
|
|
11302
11377
|
}
|
|
11303
11378
|
}
|
|
11379
|
+
installTransportHandlers(client) {
|
|
11380
|
+
this.cleanupTransportHandlers();
|
|
11381
|
+
this.removeControlRequestHandler = registerAppServerControlRequestHandler({
|
|
11382
|
+
client,
|
|
11383
|
+
getRuntime: () => this.runtime,
|
|
11384
|
+
getOptions: () => this.currentOptions()
|
|
11385
|
+
});
|
|
11386
|
+
if (this.externalTools.size > 0) {
|
|
11387
|
+
this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
|
|
11388
|
+
}
|
|
11389
|
+
}
|
|
11390
|
+
cleanupTransportHandlers() {
|
|
11391
|
+
this.removeExternalToolHandler?.();
|
|
11392
|
+
this.removeExternalToolHandler = null;
|
|
11393
|
+
this.removeControlRequestHandler?.();
|
|
11394
|
+
this.removeControlRequestHandler = null;
|
|
11395
|
+
}
|
|
11396
|
+
async recoverIdleTransport(runtime) {
|
|
11397
|
+
const connection = await this.resolveRecoveryConnection(runtime);
|
|
11398
|
+
this.connectionId = connection.connectionId;
|
|
11399
|
+
return this.openCloudTransport(runtime, connection.connectionId);
|
|
11400
|
+
}
|
|
11401
|
+
async resolveRecoveryConnection(runtime) {
|
|
11402
|
+
const sandbox = this.managedSandbox;
|
|
11403
|
+
if (sandbox) {
|
|
11404
|
+
await this.refreshManagedSandbox(sandbox);
|
|
11405
|
+
return this.waitForManagedSandboxConnection(sandbox);
|
|
11406
|
+
}
|
|
11407
|
+
const environment = this.effectiveEnvironment();
|
|
11408
|
+
if (!environment) {
|
|
11409
|
+
throw new Error("Cloud idle transport recovery lost its execution target");
|
|
11410
|
+
}
|
|
11411
|
+
return this.resolveExplicitConnection(environment);
|
|
11412
|
+
}
|
|
11413
|
+
onIdleTransportDisconnect() {
|
|
11414
|
+
this.cleanupTransportHandlers();
|
|
11415
|
+
}
|
|
11416
|
+
onRecoveredTransportDiscarded() {
|
|
11417
|
+
this.cleanupTransportHandlers();
|
|
11418
|
+
}
|
|
11304
11419
|
async startCloudRuntime(client, runtime) {
|
|
11305
11420
|
const options = this.currentOptions();
|
|
11306
11421
|
const command = {
|
|
@@ -11343,10 +11458,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11343
11458
|
await this.refreshManagedSandbox(sandbox);
|
|
11344
11459
|
}
|
|
11345
11460
|
onCoreClose() {
|
|
11346
|
-
this.
|
|
11347
|
-
this.removeExternalToolHandler = null;
|
|
11348
|
-
this.removeControlRequestHandler?.();
|
|
11349
|
-
this.removeControlRequestHandler = null;
|
|
11461
|
+
this.cleanupTransportHandlers();
|
|
11350
11462
|
this.mcpCleanup = this.closeMcpBridge();
|
|
11351
11463
|
this.cleanupManagedSandbox();
|
|
11352
11464
|
if (this.runtime?.agent_id) {
|
|
@@ -11670,8 +11782,8 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
|
|
|
11670
11782
|
return new RemoteEnvironmentClient({}, this.apiClient);
|
|
11671
11783
|
}
|
|
11672
11784
|
effectiveEnvironment() {
|
|
11673
|
-
const
|
|
11674
|
-
return
|
|
11785
|
+
const modeComputer = this.mode.kind === "session" ? this.mode.options.computer ?? this.mode.options.environment : undefined;
|
|
11786
|
+
return modeComputer ?? this.cloudOptions.computer ?? this.cloudOptions.environment;
|
|
11675
11787
|
}
|
|
11676
11788
|
effectiveSandboxOptions() {
|
|
11677
11789
|
const modeSandbox = this.mode.kind === "session" ? this.mode.options.sandbox : undefined;
|
|
@@ -11971,14 +12083,17 @@ var VALID_BACKENDS = new Set([
|
|
|
11971
12083
|
function isLettaCodeBackend(value) {
|
|
11972
12084
|
return VALID_BACKENDS.has(value);
|
|
11973
12085
|
}
|
|
11974
|
-
function
|
|
11975
|
-
if ("environment" in options)
|
|
11976
|
-
return
|
|
12086
|
+
function getOptionsComputer(options) {
|
|
12087
|
+
if (!("computer" in options) && !("environment" in options))
|
|
12088
|
+
return;
|
|
12089
|
+
if (options.computer !== undefined && options.environment !== undefined) {
|
|
12090
|
+
throw new Error('Specify either "computer" or deprecated "environment", not both.');
|
|
11977
12091
|
}
|
|
11978
|
-
return;
|
|
12092
|
+
return options.computer ?? options.environment;
|
|
11979
12093
|
}
|
|
11980
12094
|
function stripCloudExecutionOptions(options) {
|
|
11981
12095
|
const sessionOptions = { ...options };
|
|
12096
|
+
delete sessionOptions.computer;
|
|
11982
12097
|
delete sessionOptions.environment;
|
|
11983
12098
|
delete sessionOptions.sandbox;
|
|
11984
12099
|
delete sessionOptions.filesystemConfinement;
|
|
@@ -11996,12 +12111,14 @@ function looksLikeConversationId(id) {
|
|
|
11996
12111
|
|
|
11997
12112
|
class LettaAgentClientBase {
|
|
11998
12113
|
backend;
|
|
12114
|
+
computer;
|
|
11999
12115
|
environment;
|
|
12000
12116
|
agents;
|
|
12001
12117
|
conversations;
|
|
12002
12118
|
models;
|
|
12003
12119
|
options;
|
|
12004
12120
|
repositoriesClient = null;
|
|
12121
|
+
computersClient = null;
|
|
12005
12122
|
agentRepositoriesClient = null;
|
|
12006
12123
|
cloudClient = null;
|
|
12007
12124
|
managementTransport = null;
|
|
@@ -12011,16 +12128,19 @@ class LettaAgentClientBase {
|
|
|
12011
12128
|
throw new Error(`Invalid Letta Code backend '${String(backend)}'. Valid values: local, remote, cloud.`);
|
|
12012
12129
|
}
|
|
12013
12130
|
this.backend = backend;
|
|
12014
|
-
this.
|
|
12131
|
+
this.computer = getOptionsComputer(options);
|
|
12132
|
+
this.environment = this.computer;
|
|
12015
12133
|
this.options = options;
|
|
12016
12134
|
this.agents = createAgentsClient(() => this.getManagementTransport(), () => this.getAgentRepositoriesClient());
|
|
12017
12135
|
this.conversations = createConversationsClient(() => this.getManagementTransport());
|
|
12018
12136
|
this.models = createModelsClient(() => this.getManagementTransport());
|
|
12019
|
-
if (this.backend === "local" && this.
|
|
12020
|
-
|
|
12137
|
+
if (this.backend === "local" && this.computer !== undefined) {
|
|
12138
|
+
const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
|
|
12139
|
+
throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud".`);
|
|
12021
12140
|
}
|
|
12022
|
-
if (this.backend === "remote" && this.
|
|
12023
|
-
|
|
12141
|
+
if (this.backend === "remote" && this.computer !== undefined) {
|
|
12142
|
+
const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
|
|
12143
|
+
throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
12024
12144
|
}
|
|
12025
12145
|
if (this.backend !== "cloud" && options.sandbox !== undefined) {
|
|
12026
12146
|
throw new Error('LettaAgentClient sandbox options are only valid with backend: "cloud".');
|
|
@@ -12054,6 +12174,9 @@ class LettaAgentClientBase {
|
|
|
12054
12174
|
get repositories() {
|
|
12055
12175
|
return this.getRepositoriesClient();
|
|
12056
12176
|
}
|
|
12177
|
+
get computers() {
|
|
12178
|
+
return this.getComputersClient();
|
|
12179
|
+
}
|
|
12057
12180
|
async createAgent(options = {}) {
|
|
12058
12181
|
if (hasCreateAgentEnvironment(options)) {
|
|
12059
12182
|
throw new Error("createAgent() does not accept environment. Set a client default or pass environment to resumeSession()/createSession().");
|
|
@@ -12143,13 +12266,17 @@ class LettaAgentClientBase {
|
|
|
12143
12266
|
}
|
|
12144
12267
|
}
|
|
12145
12268
|
assertSessionBackend(action, options) {
|
|
12269
|
+
if (options.computer !== undefined && options.environment !== undefined) {
|
|
12270
|
+
throw new Error(`${action}() cannot specify both computer and deprecated environment.`);
|
|
12271
|
+
}
|
|
12146
12272
|
if (options.filesystemConfinement !== undefined && options.filesystemConfinement !== "memory") {
|
|
12147
12273
|
throw new Error(`Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`);
|
|
12148
12274
|
}
|
|
12149
|
-
const
|
|
12275
|
+
const effectiveComputer = options.computer ?? options.environment ?? this.computer;
|
|
12150
12276
|
if (this.backend === "local") {
|
|
12151
|
-
if (
|
|
12152
|
-
|
|
12277
|
+
if (effectiveComputer !== undefined) {
|
|
12278
|
+
const field = options.computer !== undefined ? "computer" : "environment";
|
|
12279
|
+
throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud".`);
|
|
12153
12280
|
}
|
|
12154
12281
|
if (options.sandbox !== undefined) {
|
|
12155
12282
|
throw new Error(`${action}() sandbox options are only valid with backend: "cloud".`);
|
|
@@ -12169,8 +12296,9 @@ class LettaAgentClientBase {
|
|
|
12169
12296
|
if (options.filesystemConfinement !== undefined) {
|
|
12170
12297
|
throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
|
|
12171
12298
|
}
|
|
12172
|
-
if (options.environment !== undefined) {
|
|
12173
|
-
|
|
12299
|
+
if (options.computer !== undefined || options.environment !== undefined) {
|
|
12300
|
+
const field = options.computer !== undefined ? "computer" : "environment";
|
|
12301
|
+
throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
12174
12302
|
}
|
|
12175
12303
|
if (options.sandbox !== undefined) {
|
|
12176
12304
|
throw new Error(`${action}() sandbox options are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
|
|
@@ -12185,11 +12313,13 @@ class LettaAgentClientBase {
|
|
|
12185
12313
|
throw new Error(`${action}() filesystemConfinement is only supported with backend: "local".`);
|
|
12186
12314
|
}
|
|
12187
12315
|
const cloudOptions = this.cloudOptions();
|
|
12188
|
-
if (
|
|
12189
|
-
|
|
12316
|
+
if (this.computer !== undefined && options.sandbox !== undefined) {
|
|
12317
|
+
const field = cloudOptions.computer !== undefined ? "computer" : "environment";
|
|
12318
|
+
throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default ${field}.`);
|
|
12190
12319
|
}
|
|
12191
|
-
if (cloudOptions.sandbox !== undefined && options.environment !== undefined) {
|
|
12192
|
-
|
|
12320
|
+
if (cloudOptions.sandbox !== undefined && (options.computer !== undefined || options.environment !== undefined)) {
|
|
12321
|
+
const field = options.computer !== undefined ? "a computer" : "an environment";
|
|
12322
|
+
throw new Error(`Letta Cloud ${action}() cannot specify ${field} when the client has default sandbox options.`);
|
|
12193
12323
|
}
|
|
12194
12324
|
assertCloudSessionOptionsSupported(action, options);
|
|
12195
12325
|
return;
|
|
@@ -12220,6 +12350,13 @@ class LettaAgentClientBase {
|
|
|
12220
12350
|
appServerSessionOptions() {
|
|
12221
12351
|
return this.remoteOptions();
|
|
12222
12352
|
}
|
|
12353
|
+
getComputersClient() {
|
|
12354
|
+
if (this.backend !== "cloud") {
|
|
12355
|
+
throw new Error('client.computers is only available with backend: "cloud".');
|
|
12356
|
+
}
|
|
12357
|
+
this.computersClient ??= new ComputersClientImpl(this.getCloudClient());
|
|
12358
|
+
return this.computersClient;
|
|
12359
|
+
}
|
|
12223
12360
|
getRepositoriesClient() {
|
|
12224
12361
|
if (this.backend !== "cloud") {
|
|
12225
12362
|
throw new Error('client.repositories is only available with backend: "cloud".');
|
|
@@ -12355,4 +12492,4 @@ export {
|
|
|
12355
12492
|
CloudManagedSandboxExpiredError
|
|
12356
12493
|
};
|
|
12357
12494
|
|
|
12358
|
-
//# debugId=
|
|
12495
|
+
//# debugId=6E490415C5923C8964756E2164756E21
|