@letta-ai/letta-code 0.16.15 → 0.17.1
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 +1 -1
- package/letta.js +1620 -743
- package/package.json +2 -2
package/letta.js
CHANGED
|
@@ -342,7 +342,7 @@ var init_values = __esm(() => {
|
|
|
342
342
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
343
343
|
|
|
344
344
|
// node_modules/@letta-ai/letta-client/version.mjs
|
|
345
|
-
var VERSION = "1.7.
|
|
345
|
+
var VERSION = "1.7.11";
|
|
346
346
|
|
|
347
347
|
// node_modules/@letta-ai/letta-client/internal/detect-platform.mjs
|
|
348
348
|
function getDetectedPlatform() {
|
|
@@ -868,9 +868,11 @@ var init_stringify = __esm(() => {
|
|
|
868
868
|
sentinel = {};
|
|
869
869
|
});
|
|
870
870
|
|
|
871
|
-
// node_modules/@letta-ai/letta-client/internal/
|
|
872
|
-
|
|
873
|
-
|
|
871
|
+
// node_modules/@letta-ai/letta-client/internal/utils/query.mjs
|
|
872
|
+
function stringifyQuery(query) {
|
|
873
|
+
return stringify(query, { allowDots: true, arrayFormat: "repeat" });
|
|
874
|
+
}
|
|
875
|
+
var init_query = __esm(() => {
|
|
874
876
|
init_stringify();
|
|
875
877
|
});
|
|
876
878
|
|
|
@@ -2273,8 +2275,12 @@ var init_conversations = __esm(() => {
|
|
|
2273
2275
|
delete(conversationID, options) {
|
|
2274
2276
|
return this._client.delete(path`/v1/conversations/${conversationID}`, options);
|
|
2275
2277
|
}
|
|
2276
|
-
cancel(conversationID, options) {
|
|
2277
|
-
|
|
2278
|
+
cancel(conversationID, params = {}, options) {
|
|
2279
|
+
const { agent_id } = params ?? {};
|
|
2280
|
+
return this._client.post(path`/v1/conversations/${conversationID}/cancel`, {
|
|
2281
|
+
query: { agent_id },
|
|
2282
|
+
...options
|
|
2283
|
+
});
|
|
2278
2284
|
}
|
|
2279
2285
|
};
|
|
2280
2286
|
Conversations.Messages = Messages2;
|
|
@@ -2841,7 +2847,7 @@ class Letta {
|
|
|
2841
2847
|
return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]);
|
|
2842
2848
|
}
|
|
2843
2849
|
stringifyQuery(query) {
|
|
2844
|
-
return
|
|
2850
|
+
return stringifyQuery(query);
|
|
2845
2851
|
}
|
|
2846
2852
|
getUserAgent() {
|
|
2847
2853
|
return `${this.constructor.name}/JS ${VERSION}`;
|
|
@@ -3137,7 +3143,7 @@ var init_client = __esm(() => {
|
|
|
3137
3143
|
init_tslib();
|
|
3138
3144
|
init_values();
|
|
3139
3145
|
init_detect_platform();
|
|
3140
|
-
|
|
3146
|
+
init_query();
|
|
3141
3147
|
init_error();
|
|
3142
3148
|
init_pagination();
|
|
3143
3149
|
init_uploads2();
|
|
@@ -3216,7 +3222,7 @@ var package_default;
|
|
|
3216
3222
|
var init_package = __esm(() => {
|
|
3217
3223
|
package_default = {
|
|
3218
3224
|
name: "@letta-ai/letta-code",
|
|
3219
|
-
version: "0.
|
|
3225
|
+
version: "0.17.1",
|
|
3220
3226
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3221
3227
|
type: "module",
|
|
3222
3228
|
bin: {
|
|
@@ -3249,7 +3255,7 @@ var init_package = __esm(() => {
|
|
|
3249
3255
|
access: "public"
|
|
3250
3256
|
},
|
|
3251
3257
|
dependencies: {
|
|
3252
|
-
"@letta-ai/letta-client": "^1.7.
|
|
3258
|
+
"@letta-ai/letta-client": "^1.7.11",
|
|
3253
3259
|
glob: "^13.0.0",
|
|
3254
3260
|
"ink-link": "^5.0.0",
|
|
3255
3261
|
open: "^10.2.0",
|
|
@@ -4695,6 +4701,12 @@ var approval_recovery_alert_default = `<system-reminder>Automated keep-alive pin
|
|
|
4695
4701
|
`;
|
|
4696
4702
|
var init_approval_recovery_alert = () => {};
|
|
4697
4703
|
|
|
4704
|
+
// src/agent/prompts/auto_init_reminder.txt
|
|
4705
|
+
var auto_init_reminder_default = `<system-reminder>
|
|
4706
|
+
A background agent is initializing this agent's memory system. Briefly let the user know that memory is being set up in the background, then respond to their message normally.
|
|
4707
|
+
</system-reminder>`;
|
|
4708
|
+
var init_auto_init_reminder = () => {};
|
|
4709
|
+
|
|
4698
4710
|
// src/agent/prompts/claude.md
|
|
4699
4711
|
var claude_default = `You are Letta Code, a state-of-the-art coding agent running within the Letta Code CLI on a user's computer.
|
|
4700
4712
|
You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
|
|
@@ -7182,6 +7194,7 @@ __export(exports_promptAssets, {
|
|
|
7182
7194
|
MEMORY_PROMPTS: () => MEMORY_PROMPTS,
|
|
7183
7195
|
MEMORY_CHECK_REMINDER: () => MEMORY_CHECK_REMINDER,
|
|
7184
7196
|
INTERRUPT_RECOVERY_ALERT: () => INTERRUPT_RECOVERY_ALERT,
|
|
7197
|
+
AUTO_INIT_REMINDER: () => AUTO_INIT_REMINDER,
|
|
7185
7198
|
APPROVAL_RECOVERY_PROMPT: () => APPROVAL_RECOVERY_PROMPT
|
|
7186
7199
|
});
|
|
7187
7200
|
async function resolveSystemPrompt(systemPromptPreset) {
|
|
@@ -7200,9 +7213,10 @@ async function resolveSystemPrompt(systemPromptPreset) {
|
|
|
7200
7213
|
}
|
|
7201
7214
|
return SYSTEM_PROMPT;
|
|
7202
7215
|
}
|
|
7203
|
-
var SYSTEM_PROMPT, SYSTEM_PROMPT_MEMORY_ADDON, SYSTEM_PROMPT_MEMFS_ADDON, PLAN_MODE_REMINDER, SKILL_CREATOR_PROMPT, REMEMBER_PROMPT, MEMORY_CHECK_REMINDER, MEMORY_REFLECTION_REMINDER, APPROVAL_RECOVERY_PROMPT, INTERRUPT_RECOVERY_ALERT, MEMORY_PROMPTS, SYSTEM_PROMPTS;
|
|
7216
|
+
var SYSTEM_PROMPT, SYSTEM_PROMPT_MEMORY_ADDON, SYSTEM_PROMPT_MEMFS_ADDON, PLAN_MODE_REMINDER, SKILL_CREATOR_PROMPT, REMEMBER_PROMPT, MEMORY_CHECK_REMINDER, MEMORY_REFLECTION_REMINDER, APPROVAL_RECOVERY_PROMPT, AUTO_INIT_REMINDER, INTERRUPT_RECOVERY_ALERT, MEMORY_PROMPTS, SYSTEM_PROMPTS;
|
|
7204
7217
|
var init_promptAssets = __esm(() => {
|
|
7205
7218
|
init_approval_recovery_alert();
|
|
7219
|
+
init_auto_init_reminder();
|
|
7206
7220
|
init_claude();
|
|
7207
7221
|
init_codex();
|
|
7208
7222
|
init_gemini();
|
|
@@ -7235,6 +7249,7 @@ var init_promptAssets = __esm(() => {
|
|
|
7235
7249
|
MEMORY_CHECK_REMINDER = memory_check_reminder_default;
|
|
7236
7250
|
MEMORY_REFLECTION_REMINDER = memory_reflection_reminder_default;
|
|
7237
7251
|
APPROVAL_RECOVERY_PROMPT = approval_recovery_alert_default;
|
|
7252
|
+
AUTO_INIT_REMINDER = auto_init_reminder_default;
|
|
7238
7253
|
INTERRUPT_RECOVERY_ALERT = interrupt_recovery_alert_default;
|
|
7239
7254
|
MEMORY_PROMPTS = {
|
|
7240
7255
|
"persona.mdx": persona_default,
|
|
@@ -7301,6 +7316,20 @@ var init_promptAssets = __esm(() => {
|
|
|
7301
7316
|
var models_default;
|
|
7302
7317
|
var init_models2 = __esm(() => {
|
|
7303
7318
|
models_default = [
|
|
7319
|
+
{
|
|
7320
|
+
id: "auto",
|
|
7321
|
+
handle: "letta/auto",
|
|
7322
|
+
label: "Auto (Beta)",
|
|
7323
|
+
description: "Automatically select the best model",
|
|
7324
|
+
isFeatured: true
|
|
7325
|
+
},
|
|
7326
|
+
{
|
|
7327
|
+
id: "auto-fast",
|
|
7328
|
+
handle: "letta/auto-fast",
|
|
7329
|
+
label: "Auto Fast (Beta)",
|
|
7330
|
+
description: "Automatically select the best fast model",
|
|
7331
|
+
isFeatured: true
|
|
7332
|
+
},
|
|
7304
7333
|
{
|
|
7305
7334
|
id: "sonnet",
|
|
7306
7335
|
handle: "anthropic/claude-sonnet-4-6",
|
|
@@ -7370,6 +7399,19 @@ var init_models2 = __esm(() => {
|
|
|
7370
7399
|
parallel_tool_calls: true
|
|
7371
7400
|
}
|
|
7372
7401
|
},
|
|
7402
|
+
{
|
|
7403
|
+
id: "sonnet-4.6-xhigh",
|
|
7404
|
+
handle: "anthropic/claude-sonnet-4-6",
|
|
7405
|
+
label: "Sonnet 4.6",
|
|
7406
|
+
description: "Sonnet 4.6 (max reasoning)",
|
|
7407
|
+
updateArgs: {
|
|
7408
|
+
context_window: 200000,
|
|
7409
|
+
max_output_tokens: 128000,
|
|
7410
|
+
reasoning_effort: "xhigh",
|
|
7411
|
+
enable_reasoner: true,
|
|
7412
|
+
parallel_tool_calls: true
|
|
7413
|
+
}
|
|
7414
|
+
},
|
|
7373
7415
|
{
|
|
7374
7416
|
id: "sonnet-4.5",
|
|
7375
7417
|
handle: "anthropic/claude-sonnet-4-5-20250929",
|
|
@@ -7449,18 +7491,74 @@ var init_models2 = __esm(() => {
|
|
|
7449
7491
|
parallel_tool_calls: true
|
|
7450
7492
|
}
|
|
7451
7493
|
},
|
|
7494
|
+
{
|
|
7495
|
+
id: "opus-4.6-xhigh",
|
|
7496
|
+
handle: "anthropic/claude-opus-4-6",
|
|
7497
|
+
label: "Opus 4.6",
|
|
7498
|
+
description: "Opus 4.6 (max reasoning)",
|
|
7499
|
+
updateArgs: {
|
|
7500
|
+
context_window: 200000,
|
|
7501
|
+
max_output_tokens: 128000,
|
|
7502
|
+
reasoning_effort: "xhigh",
|
|
7503
|
+
enable_reasoner: true,
|
|
7504
|
+
parallel_tool_calls: true
|
|
7505
|
+
}
|
|
7506
|
+
},
|
|
7452
7507
|
{
|
|
7453
7508
|
id: "opus-4.5",
|
|
7454
7509
|
handle: "anthropic/claude-opus-4-5-20251101",
|
|
7455
7510
|
label: "Opus 4.5",
|
|
7456
|
-
description: "Anthropic's (legacy) best model",
|
|
7511
|
+
description: "Anthropic's (legacy) best model (high reasoning)",
|
|
7457
7512
|
updateArgs: {
|
|
7458
7513
|
context_window: 180000,
|
|
7459
7514
|
max_output_tokens: 64000,
|
|
7515
|
+
reasoning_effort: "high",
|
|
7516
|
+
enable_reasoner: true,
|
|
7460
7517
|
max_reasoning_tokens: 31999,
|
|
7461
7518
|
parallel_tool_calls: true
|
|
7462
7519
|
}
|
|
7463
7520
|
},
|
|
7521
|
+
{
|
|
7522
|
+
id: "opus-4.5-no-reasoning",
|
|
7523
|
+
handle: "anthropic/claude-opus-4-5-20251101",
|
|
7524
|
+
label: "Opus 4.5",
|
|
7525
|
+
description: "Opus 4.5 with no reasoning (faster)",
|
|
7526
|
+
updateArgs: {
|
|
7527
|
+
context_window: 180000,
|
|
7528
|
+
max_output_tokens: 64000,
|
|
7529
|
+
reasoning_effort: "none",
|
|
7530
|
+
enable_reasoner: false,
|
|
7531
|
+
parallel_tool_calls: true
|
|
7532
|
+
}
|
|
7533
|
+
},
|
|
7534
|
+
{
|
|
7535
|
+
id: "opus-4.5-low",
|
|
7536
|
+
handle: "anthropic/claude-opus-4-5-20251101",
|
|
7537
|
+
label: "Opus 4.5",
|
|
7538
|
+
description: "Opus 4.5 (low reasoning)",
|
|
7539
|
+
updateArgs: {
|
|
7540
|
+
context_window: 180000,
|
|
7541
|
+
max_output_tokens: 64000,
|
|
7542
|
+
reasoning_effort: "low",
|
|
7543
|
+
enable_reasoner: true,
|
|
7544
|
+
max_reasoning_tokens: 4000,
|
|
7545
|
+
parallel_tool_calls: true
|
|
7546
|
+
}
|
|
7547
|
+
},
|
|
7548
|
+
{
|
|
7549
|
+
id: "opus-4.5-medium",
|
|
7550
|
+
handle: "anthropic/claude-opus-4-5-20251101",
|
|
7551
|
+
label: "Opus 4.5",
|
|
7552
|
+
description: "Opus 4.5 (med reasoning)",
|
|
7553
|
+
updateArgs: {
|
|
7554
|
+
context_window: 180000,
|
|
7555
|
+
max_output_tokens: 64000,
|
|
7556
|
+
reasoning_effort: "medium",
|
|
7557
|
+
enable_reasoner: true,
|
|
7558
|
+
max_reasoning_tokens: 12000,
|
|
7559
|
+
parallel_tool_calls: true
|
|
7560
|
+
}
|
|
7561
|
+
},
|
|
7464
7562
|
{
|
|
7465
7563
|
id: "bedrock-opus",
|
|
7466
7564
|
handle: "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0",
|
|
@@ -7810,6 +7908,72 @@ var init_models2 = __esm(() => {
|
|
|
7810
7908
|
parallel_tool_calls: true
|
|
7811
7909
|
}
|
|
7812
7910
|
},
|
|
7911
|
+
{
|
|
7912
|
+
id: "gpt-5.4-none",
|
|
7913
|
+
handle: "openai/gpt-5.4",
|
|
7914
|
+
label: "GPT-5.4",
|
|
7915
|
+
description: "OpenAI's most capable model (no reasoning)",
|
|
7916
|
+
updateArgs: {
|
|
7917
|
+
reasoning_effort: "none",
|
|
7918
|
+
verbosity: "medium",
|
|
7919
|
+
context_window: 272000,
|
|
7920
|
+
max_output_tokens: 128000,
|
|
7921
|
+
parallel_tool_calls: true
|
|
7922
|
+
}
|
|
7923
|
+
},
|
|
7924
|
+
{
|
|
7925
|
+
id: "gpt-5.4-low",
|
|
7926
|
+
handle: "openai/gpt-5.4",
|
|
7927
|
+
label: "GPT-5.4",
|
|
7928
|
+
description: "OpenAI's most capable model (low reasoning)",
|
|
7929
|
+
updateArgs: {
|
|
7930
|
+
reasoning_effort: "low",
|
|
7931
|
+
verbosity: "medium",
|
|
7932
|
+
context_window: 272000,
|
|
7933
|
+
max_output_tokens: 128000,
|
|
7934
|
+
parallel_tool_calls: true
|
|
7935
|
+
}
|
|
7936
|
+
},
|
|
7937
|
+
{
|
|
7938
|
+
id: "gpt-5.4-medium",
|
|
7939
|
+
handle: "openai/gpt-5.4",
|
|
7940
|
+
label: "GPT-5.4",
|
|
7941
|
+
description: "OpenAI's most capable model (med reasoning)",
|
|
7942
|
+
updateArgs: {
|
|
7943
|
+
reasoning_effort: "medium",
|
|
7944
|
+
verbosity: "medium",
|
|
7945
|
+
context_window: 272000,
|
|
7946
|
+
max_output_tokens: 128000,
|
|
7947
|
+
parallel_tool_calls: true
|
|
7948
|
+
}
|
|
7949
|
+
},
|
|
7950
|
+
{
|
|
7951
|
+
id: "gpt-5.4-high",
|
|
7952
|
+
handle: "openai/gpt-5.4",
|
|
7953
|
+
label: "GPT-5.4",
|
|
7954
|
+
description: "OpenAI's most capable model (high reasoning)",
|
|
7955
|
+
isFeatured: true,
|
|
7956
|
+
updateArgs: {
|
|
7957
|
+
reasoning_effort: "high",
|
|
7958
|
+
verbosity: "medium",
|
|
7959
|
+
context_window: 272000,
|
|
7960
|
+
max_output_tokens: 128000,
|
|
7961
|
+
parallel_tool_calls: true
|
|
7962
|
+
}
|
|
7963
|
+
},
|
|
7964
|
+
{
|
|
7965
|
+
id: "gpt-5.4-xhigh",
|
|
7966
|
+
handle: "openai/gpt-5.4",
|
|
7967
|
+
label: "GPT-5.4",
|
|
7968
|
+
description: "OpenAI's most capable model (max reasoning)",
|
|
7969
|
+
updateArgs: {
|
|
7970
|
+
reasoning_effort: "xhigh",
|
|
7971
|
+
verbosity: "medium",
|
|
7972
|
+
context_window: 272000,
|
|
7973
|
+
max_output_tokens: 128000,
|
|
7974
|
+
parallel_tool_calls: true
|
|
7975
|
+
}
|
|
7976
|
+
},
|
|
7813
7977
|
{
|
|
7814
7978
|
id: "gpt-5.3-codex-none",
|
|
7815
7979
|
handle: "openai/gpt-5.3-codex",
|
|
@@ -8458,7 +8622,7 @@ function getDefaultModel() {
|
|
|
8458
8622
|
}
|
|
8459
8623
|
function getDefaultModelForTier(billingTier) {
|
|
8460
8624
|
if (billingTier?.toLowerCase() === "free") {
|
|
8461
|
-
const freeDefault = models.find((m) => m.id === "
|
|
8625
|
+
const freeDefault = models.find((m) => m.id === "glm-5");
|
|
8462
8626
|
if (freeDefault)
|
|
8463
8627
|
return freeDefault.handle;
|
|
8464
8628
|
}
|
|
@@ -34613,6 +34777,27 @@ var init_MarkdownDisplay = __esm(async () => {
|
|
|
34613
34777
|
defaultHeaderStyle = { italic: true };
|
|
34614
34778
|
});
|
|
34615
34779
|
|
|
34780
|
+
// src/cli/helpers/appUrls.ts
|
|
34781
|
+
function buildChatUrl(agentId, options) {
|
|
34782
|
+
const base2 = `${APP_BASE}/chat/${agentId}`;
|
|
34783
|
+
const params = new URLSearchParams;
|
|
34784
|
+
if (options?.view) {
|
|
34785
|
+
params.set("view", options.view);
|
|
34786
|
+
}
|
|
34787
|
+
if (options?.deviceId) {
|
|
34788
|
+
params.set("deviceId", options.deviceId);
|
|
34789
|
+
}
|
|
34790
|
+
if (options?.conversationId && options.conversationId !== "default") {
|
|
34791
|
+
params.set("conversation", options.conversationId);
|
|
34792
|
+
}
|
|
34793
|
+
const qs = params.toString();
|
|
34794
|
+
return qs ? `${base2}?${qs}` : base2;
|
|
34795
|
+
}
|
|
34796
|
+
function buildAppUrl(path2) {
|
|
34797
|
+
return `${APP_BASE}${path2}`;
|
|
34798
|
+
}
|
|
34799
|
+
var APP_BASE = "https://app.letta.com";
|
|
34800
|
+
|
|
34616
34801
|
// src/cli/helpers/errorContext.ts
|
|
34617
34802
|
function setErrorContext(context2) {
|
|
34618
34803
|
currentContext = { ...currentContext, ...context2 };
|
|
@@ -34740,7 +34925,7 @@ function getDefaultModel2() {
|
|
|
34740
34925
|
}
|
|
34741
34926
|
function getDefaultModelForTier2(billingTier) {
|
|
34742
34927
|
if (billingTier?.toLowerCase() === "free") {
|
|
34743
|
-
const freeDefault = models2.find((m) => m.id === "
|
|
34928
|
+
const freeDefault = models2.find((m) => m.id === "glm-5");
|
|
34744
34929
|
if (freeDefault)
|
|
34745
34930
|
return freeDefault.handle;
|
|
34746
34931
|
}
|
|
@@ -60259,6 +60444,15 @@ async function getPrimaryAgentModelHandle() {
|
|
|
60259
60444
|
return null;
|
|
60260
60445
|
}
|
|
60261
60446
|
}
|
|
60447
|
+
async function getCurrentBillingTier() {
|
|
60448
|
+
try {
|
|
60449
|
+
const client = await getClient2();
|
|
60450
|
+
const balance = await client.get("/v1/metadata/balance");
|
|
60451
|
+
return balance.billing_tier ?? null;
|
|
60452
|
+
} catch {
|
|
60453
|
+
return null;
|
|
60454
|
+
}
|
|
60455
|
+
}
|
|
60262
60456
|
function isProviderNotSupportedError(errorOutput) {
|
|
60263
60457
|
return errorOutput.includes("Provider") && errorOutput.includes("is not supported") && errorOutput.includes("supported providers:");
|
|
60264
60458
|
}
|
|
@@ -60282,13 +60476,16 @@ function swapProviderPrefix(parentHandle, recommendedHandle) {
|
|
|
60282
60476
|
return `${parentProvider}/${modelPortion}`;
|
|
60283
60477
|
}
|
|
60284
60478
|
async function resolveSubagentModel(options) {
|
|
60285
|
-
const { userModel, recommendedModel, parentModelHandle } = options;
|
|
60479
|
+
const { userModel, recommendedModel, parentModelHandle, billingTier } = options;
|
|
60286
60480
|
if (userModel)
|
|
60287
60481
|
return userModel;
|
|
60288
60482
|
let recommendedHandle = null;
|
|
60289
60483
|
if (recommendedModel && recommendedModel !== "inherit") {
|
|
60290
60484
|
recommendedHandle = resolveModel2(recommendedModel);
|
|
60291
60485
|
}
|
|
60486
|
+
if (recommendedModel !== "inherit" && billingTier?.toLowerCase() === "free") {
|
|
60487
|
+
recommendedHandle = getDefaultModelForTier2(billingTier);
|
|
60488
|
+
}
|
|
60292
60489
|
let availableHandles = options.availableHandles ?? null;
|
|
60293
60490
|
const isAvailable = async (handle) => {
|
|
60294
60491
|
try {
|
|
@@ -60492,6 +60689,7 @@ function buildSubagentArgs(type, config, model, userPrompt, existingAgentId, exi
|
|
|
60492
60689
|
}
|
|
60493
60690
|
} else {
|
|
60494
60691
|
args.push("--new-agent", "--system", type);
|
|
60692
|
+
args.push("--tags", `type:${type}`);
|
|
60495
60693
|
if (model) {
|
|
60496
60694
|
args.push("--model", model);
|
|
60497
60695
|
}
|
|
@@ -60690,10 +60888,12 @@ async function spawnSubagent(type, prompt, userModel, subagentId, signal, existi
|
|
|
60690
60888
|
}
|
|
60691
60889
|
const isDeployingExisting = Boolean(existingAgentId || existingConversationId);
|
|
60692
60890
|
const parentModelHandle = await getPrimaryAgentModelHandle();
|
|
60891
|
+
const billingTier = await getCurrentBillingTier();
|
|
60693
60892
|
const model = isDeployingExisting ? null : await resolveSubagentModel({
|
|
60694
60893
|
userModel,
|
|
60695
60894
|
recommendedModel: config.recommendedModel,
|
|
60696
|
-
parentModelHandle
|
|
60895
|
+
parentModelHandle,
|
|
60896
|
+
billingTier
|
|
60697
60897
|
});
|
|
60698
60898
|
const baseURL = getBaseURL();
|
|
60699
60899
|
let finalPrompt = prompt;
|
|
@@ -65671,7 +65871,7 @@ async function loadSpecificTools(toolNames) {
|
|
|
65671
65871
|
releaseSwitchLock();
|
|
65672
65872
|
}
|
|
65673
65873
|
}
|
|
65674
|
-
async function loadTools(modelIdentifier) {
|
|
65874
|
+
async function loadTools(modelIdentifier, options) {
|
|
65675
65875
|
acquireSwitchLock();
|
|
65676
65876
|
try {
|
|
65677
65877
|
const { toolFilter: toolFilter2 } = await Promise.resolve().then(() => (init_filter(), exports_filter));
|
|
@@ -65692,6 +65892,10 @@ async function loadTools(modelIdentifier) {
|
|
|
65692
65892
|
} else {
|
|
65693
65893
|
baseToolNames = TOOL_NAMES;
|
|
65694
65894
|
}
|
|
65895
|
+
if (options?.exclude && options.exclude.length > 0) {
|
|
65896
|
+
const excludeSet = new Set(options.exclude);
|
|
65897
|
+
baseToolNames = baseToolNames.filter((name) => !excludeSet.has(name));
|
|
65898
|
+
}
|
|
65695
65899
|
const newRegistry = new Map;
|
|
65696
65900
|
for (const name of baseToolNames) {
|
|
65697
65901
|
if (!toolFilter2.isEnabled(name)) {
|
|
@@ -66473,340 +66677,6 @@ var init_approval_execution = __esm(async () => {
|
|
|
66473
66677
|
]);
|
|
66474
66678
|
});
|
|
66475
66679
|
|
|
66476
|
-
// src/agent/check-approval.ts
|
|
66477
|
-
var exports_check_approval = {};
|
|
66478
|
-
__export(exports_check_approval, {
|
|
66479
|
-
prepareMessageHistory: () => prepareMessageHistory2,
|
|
66480
|
-
getResumeData: () => getResumeData2,
|
|
66481
|
-
extractApprovals: () => extractApprovals2
|
|
66482
|
-
});
|
|
66483
|
-
function isPrimaryMessageType2(messageType) {
|
|
66484
|
-
return messageType === "user_message" || messageType === "assistant_message" || messageType === "event_message" || messageType === "summary_message";
|
|
66485
|
-
}
|
|
66486
|
-
function isAnchorMessageType2(messageType) {
|
|
66487
|
-
return messageType === "user_message" || messageType === "assistant_message";
|
|
66488
|
-
}
|
|
66489
|
-
function isBackfillEnabled2() {
|
|
66490
|
-
const val = process.env.LETTA_BACKFILL;
|
|
66491
|
-
return val !== "0" && val !== "false";
|
|
66492
|
-
}
|
|
66493
|
-
function extractApprovals2(messageToCheck) {
|
|
66494
|
-
const approvalMsg = messageToCheck;
|
|
66495
|
-
const toolCalls = Array.isArray(approvalMsg.tool_calls) ? approvalMsg.tool_calls : approvalMsg.tool_call ? [approvalMsg.tool_call] : [];
|
|
66496
|
-
const pendingApprovals = toolCalls.filter((tc) => !!tc && !!tc.tool_call_id).map((tc) => ({
|
|
66497
|
-
toolCallId: tc.tool_call_id,
|
|
66498
|
-
toolName: tc.name || "",
|
|
66499
|
-
toolArgs: tc.arguments || ""
|
|
66500
|
-
}));
|
|
66501
|
-
const pendingApproval = pendingApprovals[0] || null;
|
|
66502
|
-
if (pendingApprovals.length > 0) {
|
|
66503
|
-
debugWarn("check-approval", `Found ${pendingApprovals.length} pending approval(s): ${pendingApprovals.map((a) => a.toolName).join(", ")}`);
|
|
66504
|
-
}
|
|
66505
|
-
return { pendingApproval, pendingApprovals };
|
|
66506
|
-
}
|
|
66507
|
-
function prepareMessageHistory2(messages, opts) {
|
|
66508
|
-
const isRenderable = (msg) => {
|
|
66509
|
-
const t = msg.message_type;
|
|
66510
|
-
if (t === "user_message" || t === "assistant_message" || t === "reasoning_message" || t === "tool_call_message" || t === "tool_return_message" || t === "approval_request_message" || t === "approval_response_message") {
|
|
66511
|
-
return true;
|
|
66512
|
-
}
|
|
66513
|
-
const ts = t;
|
|
66514
|
-
return ts === "event_message" || ts === "summary_message";
|
|
66515
|
-
};
|
|
66516
|
-
const renderable = messages.filter(isRenderable);
|
|
66517
|
-
if (opts?.primaryOnly) {
|
|
66518
|
-
const convo = renderable.filter((m) => isPrimaryMessageType2(m.message_type));
|
|
66519
|
-
let trimmed = convo.slice(-BACKFILL_PRIMARY_MESSAGE_LIMIT2);
|
|
66520
|
-
const hasAssistant = trimmed.some((m) => m.message_type === "assistant_message");
|
|
66521
|
-
if (!hasAssistant) {
|
|
66522
|
-
const lastAssistantIndex = convo.map((m) => m.message_type).lastIndexOf("assistant_message");
|
|
66523
|
-
if (lastAssistantIndex >= 0) {
|
|
66524
|
-
const lastAssistant = convo[lastAssistantIndex];
|
|
66525
|
-
if (lastAssistant) {
|
|
66526
|
-
const tailLimit = Math.max(BACKFILL_PRIMARY_MESSAGE_LIMIT2 - 1, 0);
|
|
66527
|
-
const newestTail = tailLimit > 0 ? convo.slice(-tailLimit) : [];
|
|
66528
|
-
trimmed = [lastAssistant, ...newestTail];
|
|
66529
|
-
}
|
|
66530
|
-
}
|
|
66531
|
-
}
|
|
66532
|
-
if (trimmed.length > 0)
|
|
66533
|
-
return trimmed;
|
|
66534
|
-
const reasoning = renderable.filter((m) => m.message_type === "reasoning_message");
|
|
66535
|
-
if (reasoning.length > 0) {
|
|
66536
|
-
return reasoning.slice(-BACKFILL_PRIMARY_MESSAGE_LIMIT2);
|
|
66537
|
-
}
|
|
66538
|
-
return [];
|
|
66539
|
-
}
|
|
66540
|
-
const isPrimary = (msg) => {
|
|
66541
|
-
const t = msg.message_type;
|
|
66542
|
-
return t === "user_message" || t === "assistant_message" || t === "reasoning_message" || t === "event_message" || t === "summary_message";
|
|
66543
|
-
};
|
|
66544
|
-
let primaryCount = 0;
|
|
66545
|
-
let startIndex = Math.max(0, renderable.length - 1);
|
|
66546
|
-
for (let i = renderable.length - 1;i >= 0; i -= 1) {
|
|
66547
|
-
const msg = renderable[i];
|
|
66548
|
-
if (!msg)
|
|
66549
|
-
continue;
|
|
66550
|
-
if (isPrimary(msg)) {
|
|
66551
|
-
primaryCount += 1;
|
|
66552
|
-
if (primaryCount >= BACKFILL_PRIMARY_MESSAGE_LIMIT2) {
|
|
66553
|
-
startIndex = i;
|
|
66554
|
-
break;
|
|
66555
|
-
}
|
|
66556
|
-
}
|
|
66557
|
-
startIndex = i;
|
|
66558
|
-
}
|
|
66559
|
-
let messageHistory = renderable.slice(startIndex);
|
|
66560
|
-
if (messageHistory.length > BACKFILL_MAX_RENDERABLE_MESSAGES2) {
|
|
66561
|
-
messageHistory = messageHistory.slice(-BACKFILL_MAX_RENDERABLE_MESSAGES2);
|
|
66562
|
-
}
|
|
66563
|
-
if (messageHistory[0]?.message_type === "tool_return_message") {
|
|
66564
|
-
messageHistory = messageHistory.slice(1);
|
|
66565
|
-
}
|
|
66566
|
-
return messageHistory;
|
|
66567
|
-
}
|
|
66568
|
-
function sortChronological2(messages) {
|
|
66569
|
-
return [...messages].sort((a, b) => {
|
|
66570
|
-
const ta = a.date ? new Date(a.date).getTime() : 0;
|
|
66571
|
-
const tb = b.date ? new Date(b.date).getTime() : 0;
|
|
66572
|
-
if (!Number.isFinite(ta) && !Number.isFinite(tb))
|
|
66573
|
-
return 0;
|
|
66574
|
-
if (!Number.isFinite(ta))
|
|
66575
|
-
return -1;
|
|
66576
|
-
if (!Number.isFinite(tb))
|
|
66577
|
-
return 1;
|
|
66578
|
-
return ta - tb;
|
|
66579
|
-
});
|
|
66580
|
-
}
|
|
66581
|
-
async function fetchConversationBackfillMessages2(client, conversationId) {
|
|
66582
|
-
const collected = [];
|
|
66583
|
-
const seen = new Set;
|
|
66584
|
-
let cursorBefore = null;
|
|
66585
|
-
let assistantCount = 0;
|
|
66586
|
-
let anchorCount = 0;
|
|
66587
|
-
for (let pageIndex = 0;pageIndex < BACKFILL_MAX_PAGES2; pageIndex += 1) {
|
|
66588
|
-
const page = await client.conversations.messages.list(conversationId, {
|
|
66589
|
-
limit: BACKFILL_PAGE_LIMIT2,
|
|
66590
|
-
order: "desc",
|
|
66591
|
-
...cursorBefore ? { before: cursorBefore } : {}
|
|
66592
|
-
});
|
|
66593
|
-
const items = page.getPaginatedItems();
|
|
66594
|
-
if (items.length === 0)
|
|
66595
|
-
break;
|
|
66596
|
-
cursorBefore = items[items.length - 1]?.id ?? null;
|
|
66597
|
-
for (const m of items) {
|
|
66598
|
-
if (!m?.id)
|
|
66599
|
-
continue;
|
|
66600
|
-
const key = "otid" in m && m.otid ? `otid:${String(m.otid)}` : `id:${m.id}:${m.message_type ?? ""}`;
|
|
66601
|
-
if (seen.has(key))
|
|
66602
|
-
continue;
|
|
66603
|
-
seen.add(key);
|
|
66604
|
-
collected.push(m);
|
|
66605
|
-
if (m.message_type === "assistant_message")
|
|
66606
|
-
assistantCount += 1;
|
|
66607
|
-
if (isAnchorMessageType2(m.message_type))
|
|
66608
|
-
anchorCount += 1;
|
|
66609
|
-
}
|
|
66610
|
-
if (assistantCount >= BACKFILL_MIN_ASSISTANT2 && anchorCount >= BACKFILL_ANCHOR_MESSAGE_LIMIT2) {
|
|
66611
|
-
break;
|
|
66612
|
-
}
|
|
66613
|
-
if (items.length < BACKFILL_PAGE_LIMIT2)
|
|
66614
|
-
break;
|
|
66615
|
-
}
|
|
66616
|
-
if (assistantCount < BACKFILL_MIN_ASSISTANT2) {
|
|
66617
|
-
debugWarn("check-approval", `Backfill scan found 0 assistant messages in last ${collected.length} messages (tool-heavy conversation?)`);
|
|
66618
|
-
}
|
|
66619
|
-
return sortChronological2(collected);
|
|
66620
|
-
}
|
|
66621
|
-
async function getResumeData2(client, agent, conversationId, options = {}) {
|
|
66622
|
-
try {
|
|
66623
|
-
const includeMessageHistory = options.includeMessageHistory ?? true;
|
|
66624
|
-
let inContextMessageIds;
|
|
66625
|
-
let messages = [];
|
|
66626
|
-
const useConversationsApi = conversationId && conversationId !== "default";
|
|
66627
|
-
if (process.env.DEBUG) {
|
|
66628
|
-
console.log(`[DEBUG] getResumeData: conversationId=${conversationId}, useConversationsApi=${useConversationsApi}, agentId=${agent.id}`);
|
|
66629
|
-
}
|
|
66630
|
-
if (useConversationsApi) {
|
|
66631
|
-
const conversation = await client.conversations.retrieve(conversationId);
|
|
66632
|
-
inContextMessageIds = conversation.in_context_message_ids;
|
|
66633
|
-
if (!inContextMessageIds || inContextMessageIds.length === 0) {
|
|
66634
|
-
debugWarn("check-approval", "No in-context messages - no pending approvals");
|
|
66635
|
-
if (includeMessageHistory && isBackfillEnabled2()) {
|
|
66636
|
-
try {
|
|
66637
|
-
const backfill = await fetchConversationBackfillMessages2(client, conversationId);
|
|
66638
|
-
return {
|
|
66639
|
-
pendingApproval: null,
|
|
66640
|
-
pendingApprovals: [],
|
|
66641
|
-
messageHistory: prepareMessageHistory2(backfill, {
|
|
66642
|
-
primaryOnly: true
|
|
66643
|
-
})
|
|
66644
|
-
};
|
|
66645
|
-
} catch (backfillError) {
|
|
66646
|
-
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
66647
|
-
}
|
|
66648
|
-
}
|
|
66649
|
-
return {
|
|
66650
|
-
pendingApproval: null,
|
|
66651
|
-
pendingApprovals: [],
|
|
66652
|
-
messageHistory: []
|
|
66653
|
-
};
|
|
66654
|
-
}
|
|
66655
|
-
const lastInContextId = inContextMessageIds.at(-1);
|
|
66656
|
-
if (!lastInContextId) {
|
|
66657
|
-
throw new Error("Expected at least one in-context message");
|
|
66658
|
-
}
|
|
66659
|
-
const retrievedMessages = await client.messages.retrieve(lastInContextId);
|
|
66660
|
-
if (includeMessageHistory && isBackfillEnabled2()) {
|
|
66661
|
-
try {
|
|
66662
|
-
messages = await fetchConversationBackfillMessages2(client, conversationId);
|
|
66663
|
-
} catch (backfillError) {
|
|
66664
|
-
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
66665
|
-
}
|
|
66666
|
-
}
|
|
66667
|
-
const messageToCheck = retrievedMessages.find((msg) => msg.message_type === "approval_request_message") ?? retrievedMessages[0];
|
|
66668
|
-
if (messageToCheck) {
|
|
66669
|
-
debugWarn("check-approval", `Found last in-context message: ${messageToCheck.id} (type: ${messageToCheck.message_type})` + (retrievedMessages.length > 1 ? ` - had ${retrievedMessages.length} variants` : ""));
|
|
66670
|
-
if (messageToCheck.message_type === "approval_request_message") {
|
|
66671
|
-
const { pendingApproval, pendingApprovals } = extractApprovals2(messageToCheck);
|
|
66672
|
-
return {
|
|
66673
|
-
pendingApproval,
|
|
66674
|
-
pendingApprovals,
|
|
66675
|
-
messageHistory: prepareMessageHistory2(messages, {
|
|
66676
|
-
primaryOnly: true
|
|
66677
|
-
})
|
|
66678
|
-
};
|
|
66679
|
-
}
|
|
66680
|
-
} else {
|
|
66681
|
-
debugWarn("check-approval", `Last in-context message ${lastInContextId} not found via retrieve`);
|
|
66682
|
-
}
|
|
66683
|
-
return {
|
|
66684
|
-
pendingApproval: null,
|
|
66685
|
-
pendingApprovals: [],
|
|
66686
|
-
messageHistory: prepareMessageHistory2(messages, { primaryOnly: true })
|
|
66687
|
-
};
|
|
66688
|
-
} else {
|
|
66689
|
-
inContextMessageIds = agent.message_ids;
|
|
66690
|
-
if (!inContextMessageIds || inContextMessageIds.length === 0) {
|
|
66691
|
-
debugWarn("check-approval", "No in-context messages (default/agent API) - no pending approvals");
|
|
66692
|
-
return {
|
|
66693
|
-
pendingApproval: null,
|
|
66694
|
-
pendingApprovals: [],
|
|
66695
|
-
messageHistory: []
|
|
66696
|
-
};
|
|
66697
|
-
}
|
|
66698
|
-
const lastInContextId = inContextMessageIds.at(-1);
|
|
66699
|
-
if (!lastInContextId) {
|
|
66700
|
-
throw new Error("Expected at least one in-context message");
|
|
66701
|
-
}
|
|
66702
|
-
const retrievedMessages = await client.messages.retrieve(lastInContextId);
|
|
66703
|
-
if (includeMessageHistory && isBackfillEnabled2()) {
|
|
66704
|
-
try {
|
|
66705
|
-
const messagesPage = await client.conversations.messages.list(agent.id, {
|
|
66706
|
-
limit: BACKFILL_PAGE_LIMIT2,
|
|
66707
|
-
order: "desc"
|
|
66708
|
-
});
|
|
66709
|
-
messages = sortChronological2(messagesPage.getPaginatedItems());
|
|
66710
|
-
if (process.env.DEBUG) {
|
|
66711
|
-
console.log(`[DEBUG] conversations.messages.list(${agent.id}) returned ${messages.length} messages`);
|
|
66712
|
-
}
|
|
66713
|
-
} catch (backfillError) {
|
|
66714
|
-
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
66715
|
-
}
|
|
66716
|
-
}
|
|
66717
|
-
const messageToCheck = retrievedMessages.find((msg) => msg.message_type === "approval_request_message") ?? retrievedMessages[0];
|
|
66718
|
-
if (messageToCheck) {
|
|
66719
|
-
debugWarn("check-approval", `Found last in-context message: ${messageToCheck.id} (type: ${messageToCheck.message_type})` + (retrievedMessages.length > 1 ? ` - had ${retrievedMessages.length} variants` : ""));
|
|
66720
|
-
if (messageToCheck.message_type === "approval_request_message") {
|
|
66721
|
-
const { pendingApproval, pendingApprovals } = extractApprovals2(messageToCheck);
|
|
66722
|
-
return {
|
|
66723
|
-
pendingApproval,
|
|
66724
|
-
pendingApprovals,
|
|
66725
|
-
messageHistory: prepareMessageHistory2(messages, {
|
|
66726
|
-
primaryOnly: true
|
|
66727
|
-
})
|
|
66728
|
-
};
|
|
66729
|
-
}
|
|
66730
|
-
} else {
|
|
66731
|
-
debugWarn("check-approval", `Last in-context message ${lastInContextId} not found via retrieve (default/agent API)`);
|
|
66732
|
-
}
|
|
66733
|
-
return {
|
|
66734
|
-
pendingApproval: null,
|
|
66735
|
-
pendingApprovals: [],
|
|
66736
|
-
messageHistory: prepareMessageHistory2(messages, { primaryOnly: true })
|
|
66737
|
-
};
|
|
66738
|
-
}
|
|
66739
|
-
} catch (error) {
|
|
66740
|
-
if (error instanceof APIError2 && (error.status === 404 || error.status === 422)) {
|
|
66741
|
-
throw error;
|
|
66742
|
-
}
|
|
66743
|
-
console.error("Error getting resume data:", error);
|
|
66744
|
-
return { pendingApproval: null, pendingApprovals: [], messageHistory: [] };
|
|
66745
|
-
}
|
|
66746
|
-
}
|
|
66747
|
-
var BACKFILL_PRIMARY_MESSAGE_LIMIT2 = 12, BACKFILL_MAX_RENDERABLE_MESSAGES2 = 80, BACKFILL_ANCHOR_MESSAGE_LIMIT2 = 6, BACKFILL_PAGE_LIMIT2 = 200, BACKFILL_MAX_PAGES2 = 25, BACKFILL_MIN_ASSISTANT2 = 1;
|
|
66748
|
-
var init_check_approval = __esm(() => {
|
|
66749
|
-
init_error();
|
|
66750
|
-
init_debug();
|
|
66751
|
-
});
|
|
66752
|
-
|
|
66753
|
-
// src/agent/message.ts
|
|
66754
|
-
function getStreamRequestStartTime(stream2) {
|
|
66755
|
-
return streamRequestStartTimes.get(stream2);
|
|
66756
|
-
}
|
|
66757
|
-
function getStreamToolContextId(stream2) {
|
|
66758
|
-
return streamToolContextIds.get(stream2) ?? null;
|
|
66759
|
-
}
|
|
66760
|
-
function getStreamRequestContext(stream2) {
|
|
66761
|
-
return streamRequestContexts.get(stream2);
|
|
66762
|
-
}
|
|
66763
|
-
async function sendMessageStream(conversationId, messages, opts = { streamTokens: true, background: true }, requestOptions = {
|
|
66764
|
-
maxRetries: 0
|
|
66765
|
-
}) {
|
|
66766
|
-
const requestStartTime = isTimingsEnabled() ? performance.now() : undefined;
|
|
66767
|
-
const requestStartedAtMs = Date.now();
|
|
66768
|
-
const client = await getClient2();
|
|
66769
|
-
await waitForToolsetReady();
|
|
66770
|
-
const { clientTools, contextId } = captureToolExecutionContext();
|
|
66771
|
-
const resolvedConversationId = conversationId === "default" ? opts.agentId : conversationId;
|
|
66772
|
-
if (!resolvedConversationId) {
|
|
66773
|
-
throw new Error("agentId is required in opts when using default conversation");
|
|
66774
|
-
}
|
|
66775
|
-
if (process.env.DEBUG) {
|
|
66776
|
-
console.log(`[DEBUG] sendMessageStream: conversationId=${conversationId}, resolved=${resolvedConversationId}`);
|
|
66777
|
-
}
|
|
66778
|
-
const stream2 = await client.conversations.messages.create(resolvedConversationId, {
|
|
66779
|
-
messages,
|
|
66780
|
-
streaming: true,
|
|
66781
|
-
stream_tokens: opts.streamTokens ?? true,
|
|
66782
|
-
background: opts.background ?? true,
|
|
66783
|
-
client_tools: clientTools,
|
|
66784
|
-
include_compaction_messages: true
|
|
66785
|
-
}, requestOptions);
|
|
66786
|
-
if (requestStartTime !== undefined) {
|
|
66787
|
-
streamRequestStartTimes.set(stream2, requestStartTime);
|
|
66788
|
-
}
|
|
66789
|
-
streamToolContextIds.set(stream2, contextId);
|
|
66790
|
-
streamRequestContexts.set(stream2, {
|
|
66791
|
-
conversationId,
|
|
66792
|
-
resolvedConversationId,
|
|
66793
|
-
agentId: opts.agentId ?? null,
|
|
66794
|
-
requestStartedAtMs
|
|
66795
|
-
});
|
|
66796
|
-
return stream2;
|
|
66797
|
-
}
|
|
66798
|
-
var streamRequestStartTimes, streamToolContextIds, streamRequestContexts;
|
|
66799
|
-
var init_message = __esm(async () => {
|
|
66800
|
-
init_timing();
|
|
66801
|
-
await __promiseAll([
|
|
66802
|
-
init_manager3(),
|
|
66803
|
-
init_client2()
|
|
66804
|
-
]);
|
|
66805
|
-
streamRequestStartTimes = new WeakMap;
|
|
66806
|
-
streamToolContextIds = new WeakMap;
|
|
66807
|
-
streamRequestContexts = new WeakMap;
|
|
66808
|
-
});
|
|
66809
|
-
|
|
66810
66680
|
// src/cli/helpers/errorFormatter.ts
|
|
66811
66681
|
function extractReasonList2(value) {
|
|
66812
66682
|
if (!Array.isArray(value))
|
|
@@ -67262,14 +67132,16 @@ function getProviderDisplayName() {
|
|
|
67262
67132
|
return ENDPOINT_TYPE_DISPLAY_NAMES[modelEndpointType] ?? modelEndpointType;
|
|
67263
67133
|
}
|
|
67264
67134
|
function createAgentLink2(runId, agentId, conversationId) {
|
|
67265
|
-
const url =
|
|
67135
|
+
const url = buildChatUrl(agentId, { conversationId });
|
|
67266
67136
|
return `View agent: \x1B]8;;${url}\x1B\\${agentId}\x1B]8;;\x1B\\ (run: ${runId})`;
|
|
67267
67137
|
}
|
|
67268
|
-
var LETTA_USAGE_URL2
|
|
67138
|
+
var LETTA_USAGE_URL2, LETTA_AGENTS_URL2, CLOUDFLARE_EDGE_5XX_MARKER_PATTERN2, CLOUDFLARE_EDGE_5XX_TITLE_PATTERN2, CHATGPT_USAGE_LIMIT_HINT2 = "Switch models with /model, or connect your own provider keys with /connect.", ENCRYPTED_CONTENT_HINT2, DEFAULT_RETRY_MESSAGE = "Unexpected downstream LLM API error, retrying...", ENDPOINT_TYPE_DISPLAY_NAMES;
|
|
67269
67139
|
var init_errorFormatter = __esm(() => {
|
|
67270
67140
|
init_error();
|
|
67271
67141
|
init_errorContext();
|
|
67272
67142
|
init_zaiErrors();
|
|
67143
|
+
LETTA_USAGE_URL2 = buildAppUrl("/settings/organization/usage");
|
|
67144
|
+
LETTA_AGENTS_URL2 = buildAppUrl("/projects/default-project/agents");
|
|
67273
67145
|
CLOUDFLARE_EDGE_5XX_MARKER_PATTERN2 = /(^|\s)(502|52[0-6])\s*<!doctype html|error code\s*(502|52[0-6])/i;
|
|
67274
67146
|
CLOUDFLARE_EDGE_5XX_TITLE_PATTERN2 = /\|\s*(502|52[0-6])\s*:/i;
|
|
67275
67147
|
ENCRYPTED_CONTENT_HINT2 = [
|
|
@@ -67508,6 +67380,359 @@ var init_turn_recovery_policy = __esm(() => {
|
|
|
67508
67380
|
RETRYABLE_429_PATTERN = /Error code:\s*429|rate limit|too many requests/i;
|
|
67509
67381
|
});
|
|
67510
67382
|
|
|
67383
|
+
// src/agent/approval-recovery.ts
|
|
67384
|
+
async function fetchRunErrorDetail(runId) {
|
|
67385
|
+
if (!runId)
|
|
67386
|
+
return null;
|
|
67387
|
+
try {
|
|
67388
|
+
const client = await getClient2();
|
|
67389
|
+
const run = await client.runs.retrieve(runId);
|
|
67390
|
+
const metaError = run.metadata?.error;
|
|
67391
|
+
return metaError?.detail ?? metaError?.message ?? metaError?.error?.detail ?? metaError?.error?.message ?? null;
|
|
67392
|
+
} catch {
|
|
67393
|
+
return null;
|
|
67394
|
+
}
|
|
67395
|
+
}
|
|
67396
|
+
var init_approval_recovery = __esm(async () => {
|
|
67397
|
+
init_turn_recovery_policy();
|
|
67398
|
+
await init_client2();
|
|
67399
|
+
});
|
|
67400
|
+
|
|
67401
|
+
// src/agent/check-approval.ts
|
|
67402
|
+
var exports_check_approval = {};
|
|
67403
|
+
__export(exports_check_approval, {
|
|
67404
|
+
prepareMessageHistory: () => prepareMessageHistory2,
|
|
67405
|
+
getResumeData: () => getResumeData2,
|
|
67406
|
+
extractApprovals: () => extractApprovals2
|
|
67407
|
+
});
|
|
67408
|
+
function isPrimaryMessageType2(messageType) {
|
|
67409
|
+
return messageType === "user_message" || messageType === "assistant_message" || messageType === "event_message" || messageType === "summary_message";
|
|
67410
|
+
}
|
|
67411
|
+
function isAnchorMessageType2(messageType) {
|
|
67412
|
+
return messageType === "user_message" || messageType === "assistant_message";
|
|
67413
|
+
}
|
|
67414
|
+
function isBackfillEnabled2() {
|
|
67415
|
+
const val = process.env.LETTA_BACKFILL;
|
|
67416
|
+
return val !== "0" && val !== "false";
|
|
67417
|
+
}
|
|
67418
|
+
function extractApprovals2(messageToCheck) {
|
|
67419
|
+
const approvalMsg = messageToCheck;
|
|
67420
|
+
const toolCalls = Array.isArray(approvalMsg.tool_calls) ? approvalMsg.tool_calls : approvalMsg.tool_call ? [approvalMsg.tool_call] : [];
|
|
67421
|
+
const pendingApprovals = toolCalls.filter((tc) => !!tc && !!tc.tool_call_id).map((tc) => ({
|
|
67422
|
+
toolCallId: tc.tool_call_id,
|
|
67423
|
+
toolName: tc.name || "",
|
|
67424
|
+
toolArgs: tc.arguments || ""
|
|
67425
|
+
}));
|
|
67426
|
+
const pendingApproval = pendingApprovals[0] || null;
|
|
67427
|
+
if (pendingApprovals.length > 0) {
|
|
67428
|
+
debugWarn("check-approval", `Found ${pendingApprovals.length} pending approval(s): ${pendingApprovals.map((a) => a.toolName).join(", ")}`);
|
|
67429
|
+
}
|
|
67430
|
+
return { pendingApproval, pendingApprovals };
|
|
67431
|
+
}
|
|
67432
|
+
function prepareMessageHistory2(messages, opts) {
|
|
67433
|
+
const isRenderable = (msg) => {
|
|
67434
|
+
const t = msg.message_type;
|
|
67435
|
+
if (t === "user_message" || t === "assistant_message" || t === "reasoning_message" || t === "tool_call_message" || t === "tool_return_message" || t === "approval_request_message" || t === "approval_response_message") {
|
|
67436
|
+
return true;
|
|
67437
|
+
}
|
|
67438
|
+
const ts = t;
|
|
67439
|
+
return ts === "event_message" || ts === "summary_message";
|
|
67440
|
+
};
|
|
67441
|
+
const renderable = messages.filter(isRenderable);
|
|
67442
|
+
if (opts?.primaryOnly) {
|
|
67443
|
+
const convo = renderable.filter((m) => isPrimaryMessageType2(m.message_type));
|
|
67444
|
+
let trimmed = convo.slice(-BACKFILL_PRIMARY_MESSAGE_LIMIT2);
|
|
67445
|
+
const hasAssistant = trimmed.some((m) => m.message_type === "assistant_message");
|
|
67446
|
+
if (!hasAssistant) {
|
|
67447
|
+
const lastAssistantIndex = convo.map((m) => m.message_type).lastIndexOf("assistant_message");
|
|
67448
|
+
if (lastAssistantIndex >= 0) {
|
|
67449
|
+
const lastAssistant = convo[lastAssistantIndex];
|
|
67450
|
+
if (lastAssistant) {
|
|
67451
|
+
const tailLimit = Math.max(BACKFILL_PRIMARY_MESSAGE_LIMIT2 - 1, 0);
|
|
67452
|
+
const newestTail = tailLimit > 0 ? convo.slice(-tailLimit) : [];
|
|
67453
|
+
trimmed = [lastAssistant, ...newestTail];
|
|
67454
|
+
}
|
|
67455
|
+
}
|
|
67456
|
+
}
|
|
67457
|
+
if (trimmed.length > 0)
|
|
67458
|
+
return trimmed;
|
|
67459
|
+
const reasoning = renderable.filter((m) => m.message_type === "reasoning_message");
|
|
67460
|
+
if (reasoning.length > 0) {
|
|
67461
|
+
return reasoning.slice(-BACKFILL_PRIMARY_MESSAGE_LIMIT2);
|
|
67462
|
+
}
|
|
67463
|
+
return [];
|
|
67464
|
+
}
|
|
67465
|
+
const isPrimary = (msg) => {
|
|
67466
|
+
const t = msg.message_type;
|
|
67467
|
+
return t === "user_message" || t === "assistant_message" || t === "reasoning_message" || t === "event_message" || t === "summary_message";
|
|
67468
|
+
};
|
|
67469
|
+
let primaryCount = 0;
|
|
67470
|
+
let startIndex = Math.max(0, renderable.length - 1);
|
|
67471
|
+
for (let i = renderable.length - 1;i >= 0; i -= 1) {
|
|
67472
|
+
const msg = renderable[i];
|
|
67473
|
+
if (!msg)
|
|
67474
|
+
continue;
|
|
67475
|
+
if (isPrimary(msg)) {
|
|
67476
|
+
primaryCount += 1;
|
|
67477
|
+
if (primaryCount >= BACKFILL_PRIMARY_MESSAGE_LIMIT2) {
|
|
67478
|
+
startIndex = i;
|
|
67479
|
+
break;
|
|
67480
|
+
}
|
|
67481
|
+
}
|
|
67482
|
+
startIndex = i;
|
|
67483
|
+
}
|
|
67484
|
+
let messageHistory = renderable.slice(startIndex);
|
|
67485
|
+
if (messageHistory.length > BACKFILL_MAX_RENDERABLE_MESSAGES2) {
|
|
67486
|
+
messageHistory = messageHistory.slice(-BACKFILL_MAX_RENDERABLE_MESSAGES2);
|
|
67487
|
+
}
|
|
67488
|
+
if (messageHistory[0]?.message_type === "tool_return_message") {
|
|
67489
|
+
messageHistory = messageHistory.slice(1);
|
|
67490
|
+
}
|
|
67491
|
+
return messageHistory;
|
|
67492
|
+
}
|
|
67493
|
+
function sortChronological2(messages) {
|
|
67494
|
+
return [...messages].sort((a, b) => {
|
|
67495
|
+
const ta = a.date ? new Date(a.date).getTime() : 0;
|
|
67496
|
+
const tb = b.date ? new Date(b.date).getTime() : 0;
|
|
67497
|
+
if (!Number.isFinite(ta) && !Number.isFinite(tb))
|
|
67498
|
+
return 0;
|
|
67499
|
+
if (!Number.isFinite(ta))
|
|
67500
|
+
return -1;
|
|
67501
|
+
if (!Number.isFinite(tb))
|
|
67502
|
+
return 1;
|
|
67503
|
+
return ta - tb;
|
|
67504
|
+
});
|
|
67505
|
+
}
|
|
67506
|
+
async function fetchConversationBackfillMessages2(client, conversationId) {
|
|
67507
|
+
const collected = [];
|
|
67508
|
+
const seen = new Set;
|
|
67509
|
+
let cursorBefore = null;
|
|
67510
|
+
let assistantCount = 0;
|
|
67511
|
+
let anchorCount = 0;
|
|
67512
|
+
for (let pageIndex = 0;pageIndex < BACKFILL_MAX_PAGES2; pageIndex += 1) {
|
|
67513
|
+
const page = await client.conversations.messages.list(conversationId, {
|
|
67514
|
+
limit: BACKFILL_PAGE_LIMIT2,
|
|
67515
|
+
order: "desc",
|
|
67516
|
+
...cursorBefore ? { before: cursorBefore } : {}
|
|
67517
|
+
});
|
|
67518
|
+
const items = page.getPaginatedItems();
|
|
67519
|
+
if (items.length === 0)
|
|
67520
|
+
break;
|
|
67521
|
+
cursorBefore = items[items.length - 1]?.id ?? null;
|
|
67522
|
+
for (const m of items) {
|
|
67523
|
+
if (!m?.id)
|
|
67524
|
+
continue;
|
|
67525
|
+
const key = "otid" in m && m.otid ? `otid:${String(m.otid)}` : `id:${m.id}:${m.message_type ?? ""}`;
|
|
67526
|
+
if (seen.has(key))
|
|
67527
|
+
continue;
|
|
67528
|
+
seen.add(key);
|
|
67529
|
+
collected.push(m);
|
|
67530
|
+
if (m.message_type === "assistant_message")
|
|
67531
|
+
assistantCount += 1;
|
|
67532
|
+
if (isAnchorMessageType2(m.message_type))
|
|
67533
|
+
anchorCount += 1;
|
|
67534
|
+
}
|
|
67535
|
+
if (assistantCount >= BACKFILL_MIN_ASSISTANT2 && anchorCount >= BACKFILL_ANCHOR_MESSAGE_LIMIT2) {
|
|
67536
|
+
break;
|
|
67537
|
+
}
|
|
67538
|
+
if (items.length < BACKFILL_PAGE_LIMIT2)
|
|
67539
|
+
break;
|
|
67540
|
+
}
|
|
67541
|
+
if (assistantCount < BACKFILL_MIN_ASSISTANT2) {
|
|
67542
|
+
debugWarn("check-approval", `Backfill scan found 0 assistant messages in last ${collected.length} messages (tool-heavy conversation?)`);
|
|
67543
|
+
}
|
|
67544
|
+
return sortChronological2(collected);
|
|
67545
|
+
}
|
|
67546
|
+
async function getResumeData2(client, agent, conversationId, options = {}) {
|
|
67547
|
+
try {
|
|
67548
|
+
const includeMessageHistory = options.includeMessageHistory ?? true;
|
|
67549
|
+
let inContextMessageIds;
|
|
67550
|
+
let messages = [];
|
|
67551
|
+
const useConversationsApi = conversationId && conversationId !== "default";
|
|
67552
|
+
if (useConversationsApi) {
|
|
67553
|
+
const conversation = await client.conversations.retrieve(conversationId);
|
|
67554
|
+
inContextMessageIds = conversation.in_context_message_ids;
|
|
67555
|
+
if (!inContextMessageIds || inContextMessageIds.length === 0) {
|
|
67556
|
+
debugWarn("check-approval", "No in-context messages - no pending approvals");
|
|
67557
|
+
if (includeMessageHistory && isBackfillEnabled2()) {
|
|
67558
|
+
try {
|
|
67559
|
+
const backfill = await fetchConversationBackfillMessages2(client, conversationId);
|
|
67560
|
+
return {
|
|
67561
|
+
pendingApproval: null,
|
|
67562
|
+
pendingApprovals: [],
|
|
67563
|
+
messageHistory: prepareMessageHistory2(backfill, {
|
|
67564
|
+
primaryOnly: true
|
|
67565
|
+
})
|
|
67566
|
+
};
|
|
67567
|
+
} catch (backfillError) {
|
|
67568
|
+
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
67569
|
+
}
|
|
67570
|
+
}
|
|
67571
|
+
return {
|
|
67572
|
+
pendingApproval: null,
|
|
67573
|
+
pendingApprovals: [],
|
|
67574
|
+
messageHistory: []
|
|
67575
|
+
};
|
|
67576
|
+
}
|
|
67577
|
+
const lastInContextId = inContextMessageIds.at(-1);
|
|
67578
|
+
if (!lastInContextId) {
|
|
67579
|
+
throw new Error("Expected at least one in-context message");
|
|
67580
|
+
}
|
|
67581
|
+
const retrievedMessages = await client.messages.retrieve(lastInContextId);
|
|
67582
|
+
if (includeMessageHistory && isBackfillEnabled2()) {
|
|
67583
|
+
try {
|
|
67584
|
+
messages = await fetchConversationBackfillMessages2(client, conversationId);
|
|
67585
|
+
} catch (backfillError) {
|
|
67586
|
+
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
67587
|
+
}
|
|
67588
|
+
}
|
|
67589
|
+
const messageToCheck = retrievedMessages.find((msg) => msg.message_type === "approval_request_message") ?? retrievedMessages[0];
|
|
67590
|
+
if (messageToCheck) {
|
|
67591
|
+
debugWarn("check-approval", `Found last in-context message: ${messageToCheck.id} (type: ${messageToCheck.message_type})` + (retrievedMessages.length > 1 ? ` - had ${retrievedMessages.length} variants` : ""));
|
|
67592
|
+
if (messageToCheck.message_type === "approval_request_message") {
|
|
67593
|
+
const { pendingApproval, pendingApprovals } = extractApprovals2(messageToCheck);
|
|
67594
|
+
return {
|
|
67595
|
+
pendingApproval,
|
|
67596
|
+
pendingApprovals,
|
|
67597
|
+
messageHistory: prepareMessageHistory2(messages, {
|
|
67598
|
+
primaryOnly: true
|
|
67599
|
+
})
|
|
67600
|
+
};
|
|
67601
|
+
}
|
|
67602
|
+
} else {
|
|
67603
|
+
debugWarn("check-approval", `Last in-context message ${lastInContextId} not found via retrieve`);
|
|
67604
|
+
}
|
|
67605
|
+
return {
|
|
67606
|
+
pendingApproval: null,
|
|
67607
|
+
pendingApprovals: [],
|
|
67608
|
+
messageHistory: prepareMessageHistory2(messages, { primaryOnly: true })
|
|
67609
|
+
};
|
|
67610
|
+
} else {
|
|
67611
|
+
inContextMessageIds = agent.message_ids;
|
|
67612
|
+
if (!inContextMessageIds || inContextMessageIds.length === 0) {
|
|
67613
|
+
debugWarn("check-approval", "No in-context messages (default/agent API) - no pending approvals");
|
|
67614
|
+
return {
|
|
67615
|
+
pendingApproval: null,
|
|
67616
|
+
pendingApprovals: [],
|
|
67617
|
+
messageHistory: []
|
|
67618
|
+
};
|
|
67619
|
+
}
|
|
67620
|
+
const lastInContextId = inContextMessageIds.at(-1);
|
|
67621
|
+
if (!lastInContextId) {
|
|
67622
|
+
throw new Error("Expected at least one in-context message");
|
|
67623
|
+
}
|
|
67624
|
+
const retrievedMessages = await client.messages.retrieve(lastInContextId);
|
|
67625
|
+
if (includeMessageHistory && isBackfillEnabled2()) {
|
|
67626
|
+
try {
|
|
67627
|
+
const messagesPage = await client.conversations.messages.list("default", {
|
|
67628
|
+
agent_id: agent.id,
|
|
67629
|
+
limit: BACKFILL_PAGE_LIMIT2,
|
|
67630
|
+
order: "desc"
|
|
67631
|
+
});
|
|
67632
|
+
messages = sortChronological2(messagesPage.getPaginatedItems());
|
|
67633
|
+
if (process.env.DEBUG) {
|
|
67634
|
+
console.log(`[DEBUG] conversations.messages.list(default, agent_id=${agent.id}) returned ${messages.length} messages`);
|
|
67635
|
+
}
|
|
67636
|
+
} catch (backfillError) {
|
|
67637
|
+
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
67638
|
+
}
|
|
67639
|
+
}
|
|
67640
|
+
const messageToCheck = retrievedMessages.find((msg) => msg.message_type === "approval_request_message") ?? retrievedMessages[0];
|
|
67641
|
+
if (messageToCheck) {
|
|
67642
|
+
debugWarn("check-approval", `Found last in-context message: ${messageToCheck.id} (type: ${messageToCheck.message_type})` + (retrievedMessages.length > 1 ? ` - had ${retrievedMessages.length} variants` : ""));
|
|
67643
|
+
if (messageToCheck.message_type === "approval_request_message") {
|
|
67644
|
+
const { pendingApproval, pendingApprovals } = extractApprovals2(messageToCheck);
|
|
67645
|
+
return {
|
|
67646
|
+
pendingApproval,
|
|
67647
|
+
pendingApprovals,
|
|
67648
|
+
messageHistory: prepareMessageHistory2(messages, {
|
|
67649
|
+
primaryOnly: true
|
|
67650
|
+
})
|
|
67651
|
+
};
|
|
67652
|
+
}
|
|
67653
|
+
} else {
|
|
67654
|
+
debugWarn("check-approval", `Last in-context message ${lastInContextId} not found via retrieve (default/agent API)`);
|
|
67655
|
+
}
|
|
67656
|
+
return {
|
|
67657
|
+
pendingApproval: null,
|
|
67658
|
+
pendingApprovals: [],
|
|
67659
|
+
messageHistory: prepareMessageHistory2(messages, { primaryOnly: true })
|
|
67660
|
+
};
|
|
67661
|
+
}
|
|
67662
|
+
} catch (error) {
|
|
67663
|
+
if (error instanceof APIError2 && (error.status === 404 || error.status === 422)) {
|
|
67664
|
+
throw error;
|
|
67665
|
+
}
|
|
67666
|
+
console.error("Error getting resume data:", error);
|
|
67667
|
+
return { pendingApproval: null, pendingApprovals: [], messageHistory: [] };
|
|
67668
|
+
}
|
|
67669
|
+
}
|
|
67670
|
+
var BACKFILL_PRIMARY_MESSAGE_LIMIT2 = 12, BACKFILL_MAX_RENDERABLE_MESSAGES2 = 80, BACKFILL_ANCHOR_MESSAGE_LIMIT2 = 6, BACKFILL_PAGE_LIMIT2 = 200, BACKFILL_MAX_PAGES2 = 25, BACKFILL_MIN_ASSISTANT2 = 1;
|
|
67671
|
+
var init_check_approval = __esm(() => {
|
|
67672
|
+
init_error();
|
|
67673
|
+
init_debug();
|
|
67674
|
+
});
|
|
67675
|
+
|
|
67676
|
+
// src/agent/message.ts
|
|
67677
|
+
function getStreamRequestStartTime(stream2) {
|
|
67678
|
+
return streamRequestStartTimes.get(stream2);
|
|
67679
|
+
}
|
|
67680
|
+
function getStreamToolContextId(stream2) {
|
|
67681
|
+
return streamToolContextIds.get(stream2) ?? null;
|
|
67682
|
+
}
|
|
67683
|
+
function getStreamRequestContext(stream2) {
|
|
67684
|
+
return streamRequestContexts.get(stream2);
|
|
67685
|
+
}
|
|
67686
|
+
async function sendMessageStream(conversationId, messages, opts = { streamTokens: true, background: true }, requestOptions = {
|
|
67687
|
+
maxRetries: 0
|
|
67688
|
+
}) {
|
|
67689
|
+
const requestStartTime = isTimingsEnabled() ? performance.now() : undefined;
|
|
67690
|
+
const requestStartedAtMs = Date.now();
|
|
67691
|
+
const client = await getClient2();
|
|
67692
|
+
await waitForToolsetReady();
|
|
67693
|
+
const { clientTools, contextId } = captureToolExecutionContext();
|
|
67694
|
+
const isDefaultConversation = conversationId === "default";
|
|
67695
|
+
if (isDefaultConversation && !opts.agentId) {
|
|
67696
|
+
throw new Error("agentId is required in opts when using default conversation");
|
|
67697
|
+
}
|
|
67698
|
+
const resolvedConversationId = conversationId;
|
|
67699
|
+
const requestBody = {
|
|
67700
|
+
messages,
|
|
67701
|
+
streaming: true,
|
|
67702
|
+
stream_tokens: opts.streamTokens ?? true,
|
|
67703
|
+
background: opts.background ?? true,
|
|
67704
|
+
client_tools: clientTools,
|
|
67705
|
+
include_compaction_messages: true,
|
|
67706
|
+
...isDefaultConversation ? { agent_id: opts.agentId } : {}
|
|
67707
|
+
};
|
|
67708
|
+
if (process.env.DEBUG) {
|
|
67709
|
+
console.log(`[DEBUG] sendMessageStream: conversationId=${conversationId}, agentId=${opts.agentId ?? "(none)"}`);
|
|
67710
|
+
}
|
|
67711
|
+
const stream2 = await client.conversations.messages.create(resolvedConversationId, requestBody, requestOptions);
|
|
67712
|
+
if (requestStartTime !== undefined) {
|
|
67713
|
+
streamRequestStartTimes.set(stream2, requestStartTime);
|
|
67714
|
+
}
|
|
67715
|
+
streamToolContextIds.set(stream2, contextId);
|
|
67716
|
+
streamRequestContexts.set(stream2, {
|
|
67717
|
+
conversationId,
|
|
67718
|
+
resolvedConversationId,
|
|
67719
|
+
agentId: opts.agentId ?? null,
|
|
67720
|
+
requestStartedAtMs
|
|
67721
|
+
});
|
|
67722
|
+
return stream2;
|
|
67723
|
+
}
|
|
67724
|
+
var streamRequestStartTimes, streamToolContextIds, streamRequestContexts;
|
|
67725
|
+
var init_message = __esm(async () => {
|
|
67726
|
+
init_timing();
|
|
67727
|
+
await __promiseAll([
|
|
67728
|
+
init_manager3(),
|
|
67729
|
+
init_client2()
|
|
67730
|
+
]);
|
|
67731
|
+
streamRequestStartTimes = new WeakMap;
|
|
67732
|
+
streamToolContextIds = new WeakMap;
|
|
67733
|
+
streamRequestContexts = new WeakMap;
|
|
67734
|
+
});
|
|
67735
|
+
|
|
67511
67736
|
// src/cli/helpers/backfill.ts
|
|
67512
67737
|
function getDisplayableToolReturn2(content) {
|
|
67513
67738
|
if (!content)
|
|
@@ -70931,6 +71156,9 @@ function createRuntime() {
|
|
|
70931
71156
|
cancelRequested: false,
|
|
70932
71157
|
isRecoveringApprovals: false,
|
|
70933
71158
|
pendingApprovalBatchByToolCallId: new Map,
|
|
71159
|
+
pendingInterruptedResults: null,
|
|
71160
|
+
pendingInterruptedContext: null,
|
|
71161
|
+
continuationEpoch: 0,
|
|
70934
71162
|
coalescedSkipQueueItemIds: new Set,
|
|
70935
71163
|
pendingTurns: 0,
|
|
70936
71164
|
queueRuntime: null
|
|
@@ -71045,6 +71273,12 @@ function resolvePendingApprovalBatchId(runtime, pendingApprovals) {
|
|
|
71045
71273
|
}
|
|
71046
71274
|
return batchIds.values().next().value ?? null;
|
|
71047
71275
|
}
|
|
71276
|
+
function resolveRecoveryBatchId(runtime, pendingApprovals) {
|
|
71277
|
+
if (runtime.pendingApprovalBatchByToolCallId.size === 0) {
|
|
71278
|
+
return `recovery-${crypto.randomUUID()}`;
|
|
71279
|
+
}
|
|
71280
|
+
return resolvePendingApprovalBatchId(runtime, pendingApprovals);
|
|
71281
|
+
}
|
|
71048
71282
|
function clearPendingApprovalBatchIds(runtime, approvals) {
|
|
71049
71283
|
for (const approval of approvals) {
|
|
71050
71284
|
runtime.pendingApprovalBatchByToolCallId.delete(approval.toolCallId);
|
|
@@ -71059,6 +71293,9 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
71059
71293
|
clearRuntimeTimers(runtime);
|
|
71060
71294
|
rejectPendingApprovalResolvers(runtime, "Listener runtime stopped");
|
|
71061
71295
|
runtime.pendingApprovalBatchByToolCallId.clear();
|
|
71296
|
+
runtime.pendingInterruptedResults = null;
|
|
71297
|
+
runtime.pendingInterruptedContext = null;
|
|
71298
|
+
runtime.continuationEpoch++;
|
|
71062
71299
|
if (!runtime.socket) {
|
|
71063
71300
|
return;
|
|
71064
71301
|
}
|
|
@@ -71243,9 +71480,201 @@ function emitToWS(socket, event) {
|
|
|
71243
71480
|
socket.send(JSON.stringify(outbound));
|
|
71244
71481
|
}
|
|
71245
71482
|
}
|
|
71483
|
+
function normalizeToolReturnValue(value) {
|
|
71484
|
+
if (typeof value === "string") {
|
|
71485
|
+
return value;
|
|
71486
|
+
}
|
|
71487
|
+
if (value === null || value === undefined) {
|
|
71488
|
+
return "";
|
|
71489
|
+
}
|
|
71490
|
+
try {
|
|
71491
|
+
return JSON.stringify(value);
|
|
71492
|
+
} catch {
|
|
71493
|
+
return String(value);
|
|
71494
|
+
}
|
|
71495
|
+
}
|
|
71496
|
+
function extractInterruptToolReturns(approvals) {
|
|
71497
|
+
if (!approvals || approvals.length === 0) {
|
|
71498
|
+
return [];
|
|
71499
|
+
}
|
|
71500
|
+
return approvals.flatMap((approval) => {
|
|
71501
|
+
if (!approval || typeof approval !== "object") {
|
|
71502
|
+
return [];
|
|
71503
|
+
}
|
|
71504
|
+
if ("type" in approval && approval.type === "tool") {
|
|
71505
|
+
const toolCallId = "tool_call_id" in approval && typeof approval.tool_call_id === "string" ? approval.tool_call_id : null;
|
|
71506
|
+
if (!toolCallId) {
|
|
71507
|
+
return [];
|
|
71508
|
+
}
|
|
71509
|
+
const status = "status" in approval && approval.status === "success" ? "success" : "error";
|
|
71510
|
+
const stdout = "stdout" in approval && Array.isArray(approval.stdout) ? approval.stdout.filter((entry) => typeof entry === "string") : undefined;
|
|
71511
|
+
const stderr = "stderr" in approval && Array.isArray(approval.stderr) ? approval.stderr.filter((entry) => typeof entry === "string") : undefined;
|
|
71512
|
+
return [
|
|
71513
|
+
{
|
|
71514
|
+
tool_call_id: toolCallId,
|
|
71515
|
+
status,
|
|
71516
|
+
tool_return: "tool_return" in approval ? normalizeToolReturnValue(approval.tool_return) : "",
|
|
71517
|
+
...stdout ? { stdout } : {},
|
|
71518
|
+
...stderr ? { stderr } : {}
|
|
71519
|
+
}
|
|
71520
|
+
];
|
|
71521
|
+
}
|
|
71522
|
+
if ("type" in approval && approval.type === "approval") {
|
|
71523
|
+
const toolCallId = "tool_call_id" in approval && typeof approval.tool_call_id === "string" ? approval.tool_call_id : null;
|
|
71524
|
+
if (!toolCallId) {
|
|
71525
|
+
return [];
|
|
71526
|
+
}
|
|
71527
|
+
const reason = "reason" in approval && typeof approval.reason === "string" ? approval.reason : "User interrupted the stream";
|
|
71528
|
+
return [
|
|
71529
|
+
{
|
|
71530
|
+
tool_call_id: toolCallId,
|
|
71531
|
+
status: "error",
|
|
71532
|
+
tool_return: reason
|
|
71533
|
+
}
|
|
71534
|
+
];
|
|
71535
|
+
}
|
|
71536
|
+
return [];
|
|
71537
|
+
});
|
|
71538
|
+
}
|
|
71539
|
+
function emitInterruptToolReturnMessage(socket, runtime, approvals, runId, uuidPrefix = "interrupt-tool-return") {
|
|
71540
|
+
const toolReturns = extractInterruptToolReturns(approvals);
|
|
71541
|
+
if (toolReturns.length === 0) {
|
|
71542
|
+
return;
|
|
71543
|
+
}
|
|
71544
|
+
const resolvedRunId = runId ?? runtime.activeRunId ?? undefined;
|
|
71545
|
+
for (const toolReturn of toolReturns) {
|
|
71546
|
+
emitToWS(socket, {
|
|
71547
|
+
type: "message",
|
|
71548
|
+
message_type: "tool_return_message",
|
|
71549
|
+
id: `message-${crypto.randomUUID()}`,
|
|
71550
|
+
date: new Date().toISOString(),
|
|
71551
|
+
run_id: resolvedRunId,
|
|
71552
|
+
tool_call_id: toolReturn.tool_call_id,
|
|
71553
|
+
tool_return: toolReturn.tool_return,
|
|
71554
|
+
status: toolReturn.status,
|
|
71555
|
+
...toolReturn.stdout ? { stdout: toolReturn.stdout } : {},
|
|
71556
|
+
...toolReturn.stderr ? { stderr: toolReturn.stderr } : {},
|
|
71557
|
+
tool_returns: [toolReturn],
|
|
71558
|
+
session_id: runtime.sessionId,
|
|
71559
|
+
uuid: `${uuidPrefix}-${crypto.randomUUID()}`
|
|
71560
|
+
});
|
|
71561
|
+
}
|
|
71562
|
+
}
|
|
71563
|
+
function getInterruptApprovalsForEmission(runtime, params) {
|
|
71564
|
+
if (params.lastExecutionResults && params.lastExecutionResults.length > 0) {
|
|
71565
|
+
return params.lastExecutionResults;
|
|
71566
|
+
}
|
|
71567
|
+
const context3 = runtime.pendingInterruptedContext;
|
|
71568
|
+
if (!context3 || context3.agentId !== params.agentId || context3.conversationId !== params.conversationId || context3.continuationEpoch !== runtime.continuationEpoch) {
|
|
71569
|
+
return null;
|
|
71570
|
+
}
|
|
71571
|
+
if (!runtime.pendingInterruptedResults || runtime.pendingInterruptedResults.length === 0) {
|
|
71572
|
+
return null;
|
|
71573
|
+
}
|
|
71574
|
+
return runtime.pendingInterruptedResults;
|
|
71575
|
+
}
|
|
71576
|
+
function populateInterruptQueue(runtime, input) {
|
|
71577
|
+
const shouldPopulate = !runtime.pendingInterruptedResults || runtime.pendingInterruptedResults.length === 0 || !runtime.pendingInterruptedContext;
|
|
71578
|
+
if (!shouldPopulate)
|
|
71579
|
+
return false;
|
|
71580
|
+
if (input.lastExecutionResults && input.lastExecutionResults.length > 0) {
|
|
71581
|
+
runtime.pendingInterruptedResults = input.lastExecutionResults;
|
|
71582
|
+
runtime.pendingInterruptedContext = {
|
|
71583
|
+
agentId: input.agentId,
|
|
71584
|
+
conversationId: input.conversationId,
|
|
71585
|
+
continuationEpoch: runtime.continuationEpoch
|
|
71586
|
+
};
|
|
71587
|
+
return true;
|
|
71588
|
+
}
|
|
71589
|
+
const batchToolCallIds = [...runtime.pendingApprovalBatchByToolCallId.keys()];
|
|
71590
|
+
const pendingIds = batchToolCallIds.length > 0 ? batchToolCallIds : input.lastNeedsUserInputToolCallIds;
|
|
71591
|
+
if (pendingIds.length > 0) {
|
|
71592
|
+
runtime.pendingInterruptedResults = pendingIds.map((toolCallId) => ({
|
|
71593
|
+
type: "approval",
|
|
71594
|
+
tool_call_id: toolCallId,
|
|
71595
|
+
approve: false,
|
|
71596
|
+
reason: "User interrupted the stream"
|
|
71597
|
+
}));
|
|
71598
|
+
runtime.pendingInterruptedContext = {
|
|
71599
|
+
agentId: input.agentId,
|
|
71600
|
+
conversationId: input.conversationId,
|
|
71601
|
+
continuationEpoch: runtime.continuationEpoch
|
|
71602
|
+
};
|
|
71603
|
+
return true;
|
|
71604
|
+
}
|
|
71605
|
+
if (process.env.DEBUG) {
|
|
71606
|
+
console.warn("[Listen] Cancel during approval loop but no tool_call_ids available " + "for interrupted queue — next turn may hit pre-stream conflict. " + `batchMap=${runtime.pendingApprovalBatchByToolCallId.size}, ` + `lastNeedsUserInput=${input.lastNeedsUserInputToolCallIds.length}`);
|
|
71607
|
+
}
|
|
71608
|
+
return false;
|
|
71609
|
+
}
|
|
71610
|
+
function consumeInterruptQueue(runtime, agentId, conversationId) {
|
|
71611
|
+
if (!runtime.pendingInterruptedResults || runtime.pendingInterruptedResults.length === 0) {
|
|
71612
|
+
return null;
|
|
71613
|
+
}
|
|
71614
|
+
const ctx = runtime.pendingInterruptedContext;
|
|
71615
|
+
let result = null;
|
|
71616
|
+
if (ctx && ctx.agentId === agentId && ctx.conversationId === conversationId && ctx.continuationEpoch === runtime.continuationEpoch) {
|
|
71617
|
+
result = {
|
|
71618
|
+
type: "approval",
|
|
71619
|
+
approvals: runtime.pendingInterruptedResults
|
|
71620
|
+
};
|
|
71621
|
+
}
|
|
71622
|
+
runtime.pendingInterruptedResults = null;
|
|
71623
|
+
runtime.pendingInterruptedContext = null;
|
|
71624
|
+
runtime.pendingApprovalBatchByToolCallId.clear();
|
|
71625
|
+
return result;
|
|
71626
|
+
}
|
|
71627
|
+
async function resolveStaleApprovals(runtime, abortSignal) {
|
|
71628
|
+
if (!runtime.activeAgentId)
|
|
71629
|
+
return;
|
|
71630
|
+
const client = await getClient2();
|
|
71631
|
+
let agent;
|
|
71632
|
+
try {
|
|
71633
|
+
agent = await client.agents.retrieve(runtime.activeAgentId);
|
|
71634
|
+
} catch (err) {
|
|
71635
|
+
if (err instanceof APIError2 && (err.status === 404 || err.status === 422)) {
|
|
71636
|
+
return;
|
|
71637
|
+
}
|
|
71638
|
+
throw err;
|
|
71639
|
+
}
|
|
71640
|
+
const requestedConversationId = runtime.activeConversationId && runtime.activeConversationId !== "default" ? runtime.activeConversationId : undefined;
|
|
71641
|
+
let resumeData;
|
|
71642
|
+
try {
|
|
71643
|
+
resumeData = await getResumeData2(client, agent, requestedConversationId, {
|
|
71644
|
+
includeMessageHistory: false
|
|
71645
|
+
});
|
|
71646
|
+
} catch (err) {
|
|
71647
|
+
if (err instanceof APIError2 && (err.status === 404 || err.status === 422)) {
|
|
71648
|
+
return;
|
|
71649
|
+
}
|
|
71650
|
+
throw err;
|
|
71651
|
+
}
|
|
71652
|
+
const pendingApprovals = resumeData.pendingApprovals || [];
|
|
71653
|
+
if (pendingApprovals.length === 0)
|
|
71654
|
+
return;
|
|
71655
|
+
if (abortSignal.aborted)
|
|
71656
|
+
throw new Error("Cancelled");
|
|
71657
|
+
const denialResults = pendingApprovals.map((approval) => ({
|
|
71658
|
+
type: "approval",
|
|
71659
|
+
tool_call_id: approval.toolCallId,
|
|
71660
|
+
approve: false,
|
|
71661
|
+
reason: "Auto-denied during pre-stream approval recovery"
|
|
71662
|
+
}));
|
|
71663
|
+
const recoveryConversationId = runtime.activeConversationId || "default";
|
|
71664
|
+
const recoveryStream = await sendMessageStream(recoveryConversationId, [{ type: "approval", approvals: denialResults }], {
|
|
71665
|
+
agentId: runtime.activeAgentId,
|
|
71666
|
+
streamTokens: true,
|
|
71667
|
+
background: true
|
|
71668
|
+
}, { maxRetries: 0, signal: abortSignal });
|
|
71669
|
+
const drainResult = await drainStreamWithResume(recoveryStream, createBuffers(runtime.activeAgentId), () => {}, abortSignal);
|
|
71670
|
+
if (drainResult.stopReason === "error") {
|
|
71671
|
+
throw new Error("Pre-stream approval recovery drain ended with error");
|
|
71672
|
+
}
|
|
71673
|
+
}
|
|
71246
71674
|
async function sendMessageStreamWithRetry(conversationId, messages, opts, socket, runtime, abortSignal) {
|
|
71247
71675
|
let transientRetries = 0;
|
|
71248
71676
|
let conversationBusyRetries = 0;
|
|
71677
|
+
let preStreamRecoveryAttempts = 0;
|
|
71249
71678
|
const MAX_CONVERSATION_BUSY_RETRIES = 1;
|
|
71250
71679
|
while (true) {
|
|
71251
71680
|
if (abortSignal?.aborted) {
|
|
@@ -71264,7 +71693,20 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
71264
71693
|
maxTransientRetries: LLM_API_ERROR_MAX_RETRIES
|
|
71265
71694
|
});
|
|
71266
71695
|
if (action === "resolve_approval_pending") {
|
|
71267
|
-
|
|
71696
|
+
if (abortSignal?.aborted)
|
|
71697
|
+
throw new Error("Cancelled by user");
|
|
71698
|
+
if (abortSignal && preStreamRecoveryAttempts < MAX_PRE_STREAM_RECOVERY) {
|
|
71699
|
+
preStreamRecoveryAttempts++;
|
|
71700
|
+
try {
|
|
71701
|
+
await resolveStaleApprovals(runtime, abortSignal);
|
|
71702
|
+
continue;
|
|
71703
|
+
} catch (_recoveryError) {
|
|
71704
|
+
if (abortSignal.aborted)
|
|
71705
|
+
throw new Error("Cancelled by user");
|
|
71706
|
+
}
|
|
71707
|
+
}
|
|
71708
|
+
const detail = await fetchRunErrorDetail(runtime.activeRunId);
|
|
71709
|
+
throw new Error(detail || `Pre-stream approval conflict (resolve_approval_pending) after ${preStreamRecoveryAttempts} recovery attempts`);
|
|
71268
71710
|
}
|
|
71269
71711
|
if (action === "retry_transient") {
|
|
71270
71712
|
const attempt = transientRetries + 1;
|
|
@@ -71406,6 +71848,13 @@ function buildApprovalExecutionPlan(approvalMessage, pendingApprovals) {
|
|
|
71406
71848
|
return { slots, decisions };
|
|
71407
71849
|
}
|
|
71408
71850
|
async function recoverPendingApprovals(runtime, socket, msg) {
|
|
71851
|
+
console.debug("[listener] recover_pending_approvals received", JSON.stringify({
|
|
71852
|
+
agentId: msg.agentId,
|
|
71853
|
+
conversationId: msg.conversationId ?? null,
|
|
71854
|
+
isProcessing: runtime.isProcessing,
|
|
71855
|
+
isRecovering: runtime.isRecoveringApprovals,
|
|
71856
|
+
batchMapSize: runtime.pendingApprovalBatchByToolCallId.size
|
|
71857
|
+
}));
|
|
71409
71858
|
if (runtime.isProcessing || runtime.isRecoveringApprovals) {
|
|
71410
71859
|
return;
|
|
71411
71860
|
}
|
|
@@ -71434,11 +71883,11 @@ async function recoverPendingApprovals(runtime, socket, msg) {
|
|
|
71434
71883
|
if (pendingApprovals.length === 0) {
|
|
71435
71884
|
return;
|
|
71436
71885
|
}
|
|
71437
|
-
const recoveryBatchId =
|
|
71886
|
+
const recoveryBatchId = resolveRecoveryBatchId(runtime, pendingApprovals);
|
|
71438
71887
|
if (!recoveryBatchId) {
|
|
71439
71888
|
emitToWS(socket, {
|
|
71440
71889
|
type: "error",
|
|
71441
|
-
message: "Unable to recover pending approvals
|
|
71890
|
+
message: "Unable to recover pending approvals: ambiguous batch correlation",
|
|
71442
71891
|
stop_reason: "error",
|
|
71443
71892
|
session_id: runtime.sessionId,
|
|
71444
71893
|
uuid: `error-${crypto.randomUUID()}`
|
|
@@ -71481,6 +71930,7 @@ async function recoverPendingApprovals(runtime, socket, msg) {
|
|
|
71481
71930
|
runtime.lastStopReason = "requires_approval";
|
|
71482
71931
|
return;
|
|
71483
71932
|
}
|
|
71933
|
+
runtime.lastStopReason = "requires_approval";
|
|
71484
71934
|
for (const ac of needsUserInput) {
|
|
71485
71935
|
const requestId = `perm-${ac.approval.toolCallId}`;
|
|
71486
71936
|
const diffs = await computeDiffPreviews(ac.approval.toolName, ac.parsedArgs);
|
|
@@ -71693,6 +72143,14 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
71693
72143
|
if (hasPendingApprovals) {
|
|
71694
72144
|
rejectPendingApprovalResolvers(runtime, "Cancelled by user");
|
|
71695
72145
|
}
|
|
72146
|
+
const cancelConversationId = runtime.activeConversationId;
|
|
72147
|
+
const cancelAgentId = runtime.activeAgentId;
|
|
72148
|
+
if (cancelAgentId) {
|
|
72149
|
+
getClient2().then((client) => {
|
|
72150
|
+
const cancelId = cancelConversationId === "default" || !cancelConversationId ? cancelAgentId : cancelConversationId;
|
|
72151
|
+
return client.conversations.cancel(cancelId);
|
|
72152
|
+
}).catch(() => {});
|
|
72153
|
+
}
|
|
71696
72154
|
emitCancelAck(socket, runtime, {
|
|
71697
72155
|
requestId,
|
|
71698
72156
|
accepted: true,
|
|
@@ -71891,6 +72349,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
71891
72349
|
const msgStartTime = performance.now();
|
|
71892
72350
|
let msgTurnCount = 0;
|
|
71893
72351
|
const msgRunIds = [];
|
|
72352
|
+
let lastExecutionResults = null;
|
|
72353
|
+
let lastNeedsUserInputToolCallIds = [];
|
|
71894
72354
|
runtime.isProcessing = true;
|
|
71895
72355
|
runtime.cancelRequested = false;
|
|
71896
72356
|
runtime.activeAbortController = new AbortController;
|
|
@@ -71913,8 +72373,13 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
71913
72373
|
if (connectionId) {
|
|
71914
72374
|
onStatusChange?.("processing", connectionId);
|
|
71915
72375
|
}
|
|
71916
|
-
let messagesToSend =
|
|
72376
|
+
let messagesToSend = [];
|
|
71917
72377
|
let turnToolContextId = null;
|
|
72378
|
+
const consumed = consumeInterruptQueue(runtime, agentId || "", conversationId);
|
|
72379
|
+
if (consumed) {
|
|
72380
|
+
messagesToSend.push(consumed);
|
|
72381
|
+
}
|
|
72382
|
+
messagesToSend.push(...msg.messages);
|
|
71918
72383
|
const firstMessage = msg.messages[0];
|
|
71919
72384
|
const isApprovalMessage = firstMessage && "type" in firstMessage && firstMessage.type === "approval" && "approvals" in firstMessage;
|
|
71920
72385
|
if (isApprovalMessage) {
|
|
@@ -71955,6 +72420,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
71955
72420
|
approvals: rebuiltApprovals
|
|
71956
72421
|
}
|
|
71957
72422
|
];
|
|
72423
|
+
emitInterruptToolReturnMessage(socket, runtime, rebuiltApprovals, runtime.activeRunId ?? undefined, "tool-return");
|
|
71958
72424
|
}
|
|
71959
72425
|
let stream2 = await sendMessageStreamWithRetry(conversationId, messagesToSend, { agentId, streamTokens: true, background: true }, socket, runtime, runtime.activeAbortController.signal);
|
|
71960
72426
|
turnToolContextId = getStreamToolContextId(stream2);
|
|
@@ -72062,13 +72528,45 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72062
72528
|
break;
|
|
72063
72529
|
}
|
|
72064
72530
|
if (stopReason !== "requires_approval") {
|
|
72065
|
-
runtime.
|
|
72531
|
+
const effectiveStopReason = runtime.cancelRequested ? "cancelled" : stopReason || "error";
|
|
72532
|
+
if (effectiveStopReason === "cancelled") {
|
|
72533
|
+
runtime.lastStopReason = "cancelled";
|
|
72534
|
+
runtime.isProcessing = false;
|
|
72535
|
+
clearActiveRunState(runtime);
|
|
72536
|
+
if (runtime.controlResponseCapable) {
|
|
72537
|
+
emitToWS(socket, {
|
|
72538
|
+
type: "result",
|
|
72539
|
+
subtype: "interrupted",
|
|
72540
|
+
agent_id: agentId,
|
|
72541
|
+
conversation_id: conversationId,
|
|
72542
|
+
duration_ms: performance.now() - msgStartTime,
|
|
72543
|
+
duration_api_ms: 0,
|
|
72544
|
+
num_turns: msgTurnCount,
|
|
72545
|
+
result: null,
|
|
72546
|
+
run_ids: msgRunIds,
|
|
72547
|
+
usage: null,
|
|
72548
|
+
stop_reason: "cancelled",
|
|
72549
|
+
session_id: runtime.sessionId,
|
|
72550
|
+
uuid: `result-${crypto.randomUUID()}`
|
|
72551
|
+
});
|
|
72552
|
+
} else {
|
|
72553
|
+
sendClientMessage(socket, {
|
|
72554
|
+
type: "result",
|
|
72555
|
+
success: false,
|
|
72556
|
+
stopReason: "cancelled"
|
|
72557
|
+
});
|
|
72558
|
+
}
|
|
72559
|
+
break;
|
|
72560
|
+
}
|
|
72561
|
+
runtime.lastStopReason = effectiveStopReason;
|
|
72066
72562
|
runtime.isProcessing = false;
|
|
72067
72563
|
clearActiveRunState(runtime);
|
|
72564
|
+
const errorDetail = await fetchRunErrorDetail(runId).catch(() => null);
|
|
72565
|
+
const errorMessage = errorDetail || `Unexpected stop reason: ${stopReason}`;
|
|
72068
72566
|
emitToWS(socket, {
|
|
72069
72567
|
type: "error",
|
|
72070
|
-
message:
|
|
72071
|
-
stop_reason:
|
|
72568
|
+
message: errorMessage,
|
|
72569
|
+
stop_reason: effectiveStopReason,
|
|
72072
72570
|
run_id: runId,
|
|
72073
72571
|
session_id: runtime.sessionId,
|
|
72074
72572
|
uuid: `error-${crypto.randomUUID()}`
|
|
@@ -72085,7 +72583,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72085
72583
|
result: null,
|
|
72086
72584
|
run_ids: msgRunIds,
|
|
72087
72585
|
usage: null,
|
|
72088
|
-
stop_reason:
|
|
72586
|
+
stop_reason: effectiveStopReason,
|
|
72089
72587
|
session_id: runtime.sessionId,
|
|
72090
72588
|
uuid: `result-${crypto.randomUUID()}`
|
|
72091
72589
|
});
|
|
@@ -72093,7 +72591,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72093
72591
|
sendClientMessage(socket, {
|
|
72094
72592
|
type: "result",
|
|
72095
72593
|
success: false,
|
|
72096
|
-
stopReason
|
|
72594
|
+
stopReason: effectiveStopReason
|
|
72097
72595
|
});
|
|
72098
72596
|
}
|
|
72099
72597
|
break;
|
|
@@ -72115,6 +72613,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72115
72613
|
treatAskAsDeny: false,
|
|
72116
72614
|
requireArgsForAutoApprove: true
|
|
72117
72615
|
});
|
|
72616
|
+
lastNeedsUserInputToolCallIds = needsUserInput.map((ac) => ac.approval.toolCallId);
|
|
72617
|
+
lastExecutionResults = null;
|
|
72118
72618
|
for (const ac of autoAllowed) {
|
|
72119
72619
|
emitToWS(socket, {
|
|
72120
72620
|
type: "auto_approval",
|
|
@@ -72209,6 +72709,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72209
72709
|
toolContextId: turnToolContextId ?? undefined,
|
|
72210
72710
|
abortSignal: runtime.activeAbortController.signal
|
|
72211
72711
|
});
|
|
72712
|
+
lastExecutionResults = executionResults;
|
|
72713
|
+
emitInterruptToolReturnMessage(socket, runtime, executionResults, runtime.activeRunId || runId || msgRunIds[msgRunIds.length - 1] || undefined, "tool-return");
|
|
72212
72714
|
clearPendingApprovalBatchIds(runtime, decisions.map((decision) => decision.approval));
|
|
72213
72715
|
stream2 = await sendMessageStreamWithRetry(conversationId, [
|
|
72214
72716
|
{
|
|
@@ -72216,10 +72718,26 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72216
72718
|
approvals: executionResults
|
|
72217
72719
|
}
|
|
72218
72720
|
], { agentId, streamTokens: true, background: true }, socket, runtime, runtime.activeAbortController.signal);
|
|
72721
|
+
lastExecutionResults = null;
|
|
72722
|
+
lastNeedsUserInputToolCallIds = [];
|
|
72219
72723
|
turnToolContextId = getStreamToolContextId(stream2);
|
|
72220
72724
|
}
|
|
72221
72725
|
} catch (error) {
|
|
72222
72726
|
if (runtime.cancelRequested) {
|
|
72727
|
+
populateInterruptQueue(runtime, {
|
|
72728
|
+
lastExecutionResults,
|
|
72729
|
+
lastNeedsUserInputToolCallIds,
|
|
72730
|
+
agentId: agentId || "",
|
|
72731
|
+
conversationId
|
|
72732
|
+
});
|
|
72733
|
+
const approvalsForEmission = getInterruptApprovalsForEmission(runtime, {
|
|
72734
|
+
lastExecutionResults,
|
|
72735
|
+
agentId: agentId || "",
|
|
72736
|
+
conversationId
|
|
72737
|
+
});
|
|
72738
|
+
if (approvalsForEmission) {
|
|
72739
|
+
emitInterruptToolReturnMessage(socket, runtime, approvalsForEmission, runtime.activeRunId || msgRunIds[msgRunIds.length - 1] || undefined);
|
|
72740
|
+
}
|
|
72223
72741
|
runtime.lastStopReason = "cancelled";
|
|
72224
72742
|
runtime.isProcessing = false;
|
|
72225
72743
|
clearActiveRunState(runtime);
|
|
@@ -72251,6 +72769,22 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
72251
72769
|
runtime.lastStopReason = "error";
|
|
72252
72770
|
runtime.isProcessing = false;
|
|
72253
72771
|
clearActiveRunState(runtime);
|
|
72772
|
+
if (msgRunIds.length === 0) {
|
|
72773
|
+
const errorPayload = {
|
|
72774
|
+
message: error instanceof Error ? error.message : String(error)
|
|
72775
|
+
};
|
|
72776
|
+
if (error instanceof APIError2) {
|
|
72777
|
+
errorPayload.status = error.status;
|
|
72778
|
+
if (error.error && typeof error.error === "object") {
|
|
72779
|
+
errorPayload.body = error.error;
|
|
72780
|
+
}
|
|
72781
|
+
}
|
|
72782
|
+
sendClientMessage(socket, {
|
|
72783
|
+
type: "run_request_error",
|
|
72784
|
+
error: errorPayload,
|
|
72785
|
+
batch_id: dequeuedBatchId
|
|
72786
|
+
});
|
|
72787
|
+
}
|
|
72254
72788
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
72255
72789
|
emitToWS(socket, {
|
|
72256
72790
|
type: "error",
|
|
@@ -72301,7 +72835,7 @@ function stopListenerClient() {
|
|
|
72301
72835
|
activeRuntime = null;
|
|
72302
72836
|
stopRuntime(runtime, true);
|
|
72303
72837
|
}
|
|
72304
|
-
var activeRuntime = null, MAX_RETRY_DURATION_MS, INITIAL_RETRY_DELAY_MS = 1000, MAX_RETRY_DELAY_MS = 30000, LLM_API_ERROR_MAX_RETRIES = 3, __listenClientTestUtils;
|
|
72838
|
+
var activeRuntime = null, MAX_RETRY_DURATION_MS, INITIAL_RETRY_DELAY_MS = 1000, MAX_RETRY_DELAY_MS = 30000, LLM_API_ERROR_MAX_RETRIES = 3, MAX_PRE_STREAM_RECOVERY = 2, __listenClientTestUtils;
|
|
72305
72839
|
var init_listen_client = __esm(async () => {
|
|
72306
72840
|
init_error();
|
|
72307
72841
|
init_check_approval();
|
|
@@ -72312,6 +72846,7 @@ var init_listen_client = __esm(async () => {
|
|
|
72312
72846
|
init_interactivePolicy();
|
|
72313
72847
|
await __promiseAll([
|
|
72314
72848
|
init_approval_execution(),
|
|
72849
|
+
init_approval_recovery(),
|
|
72315
72850
|
init_client2(),
|
|
72316
72851
|
init_message(),
|
|
72317
72852
|
init_accumulator(),
|
|
@@ -72327,7 +72862,13 @@ var init_listen_client = __esm(async () => {
|
|
|
72327
72862
|
emitToWS,
|
|
72328
72863
|
rememberPendingApprovalBatchIds,
|
|
72329
72864
|
resolvePendingApprovalBatchId,
|
|
72330
|
-
|
|
72865
|
+
resolveRecoveryBatchId,
|
|
72866
|
+
clearPendingApprovalBatchIds,
|
|
72867
|
+
populateInterruptQueue,
|
|
72868
|
+
consumeInterruptQueue,
|
|
72869
|
+
extractInterruptToolReturns,
|
|
72870
|
+
emitInterruptToolReturnMessage,
|
|
72871
|
+
getInterruptApprovalsForEmission
|
|
72331
72872
|
};
|
|
72332
72873
|
});
|
|
72333
72874
|
|
|
@@ -72353,19 +72894,19 @@ __export(exports_skills2, {
|
|
|
72353
72894
|
SKILLS_DIR: () => SKILLS_DIR2,
|
|
72354
72895
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
72355
72896
|
});
|
|
72356
|
-
import { existsSync as
|
|
72897
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
72357
72898
|
import { readdir as readdir6, readFile as readFile5, realpath as realpath3, stat as stat3 } from "node:fs/promises";
|
|
72358
|
-
import { dirname as dirname8, join as
|
|
72899
|
+
import { dirname as dirname8, join as join22 } from "node:path";
|
|
72359
72900
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
72360
72901
|
function getBundledSkillsPath2() {
|
|
72361
72902
|
const thisDir = dirname8(fileURLToPath8(import.meta.url));
|
|
72362
72903
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
72363
|
-
return
|
|
72904
|
+
return join22(thisDir, "../skills/builtin");
|
|
72364
72905
|
}
|
|
72365
|
-
return
|
|
72906
|
+
return join22(thisDir, "skills");
|
|
72366
72907
|
}
|
|
72367
72908
|
function getAgentSkillsDir2(agentId) {
|
|
72368
|
-
return
|
|
72909
|
+
return join22(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
|
|
72369
72910
|
}
|
|
72370
72911
|
async function getBundledSkills2() {
|
|
72371
72912
|
const bundledPath = getBundledSkillsPath2();
|
|
@@ -72374,7 +72915,7 @@ async function getBundledSkills2() {
|
|
|
72374
72915
|
}
|
|
72375
72916
|
async function discoverSkillsFromDir2(skillsPath, source) {
|
|
72376
72917
|
const errors = [];
|
|
72377
|
-
if (!
|
|
72918
|
+
if (!existsSync13(skillsPath)) {
|
|
72378
72919
|
return { skills: [], errors: [] };
|
|
72379
72920
|
}
|
|
72380
72921
|
const skills = [];
|
|
@@ -72388,7 +72929,7 @@ async function discoverSkillsFromDir2(skillsPath, source) {
|
|
|
72388
72929
|
}
|
|
72389
72930
|
return { skills, errors };
|
|
72390
72931
|
}
|
|
72391
|
-
async function discoverSkills2(projectSkillsPath =
|
|
72932
|
+
async function discoverSkills2(projectSkillsPath = join22(process.cwd(), SKILLS_DIR2), agentId, options) {
|
|
72392
72933
|
const allErrors = [];
|
|
72393
72934
|
const skillsById = new Map;
|
|
72394
72935
|
const sourceSet = new Set(options?.sources ?? ALL_SKILL_SOURCES);
|
|
@@ -72443,7 +72984,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
|
|
|
72443
72984
|
try {
|
|
72444
72985
|
const entries = await readdir6(currentPath, { withFileTypes: true });
|
|
72445
72986
|
for (const entry of entries) {
|
|
72446
|
-
const fullPath =
|
|
72987
|
+
const fullPath = join22(currentPath, entry.name);
|
|
72447
72988
|
try {
|
|
72448
72989
|
let isDirectory = entry.isDirectory();
|
|
72449
72990
|
let isFile = entry.isFile();
|
|
@@ -72532,7 +73073,7 @@ ${lines.join(`
|
|
|
72532
73073
|
var SKILLS_DIR2 = ".skills", GLOBAL_SKILLS_DIR2;
|
|
72533
73074
|
var init_skills2 = __esm(() => {
|
|
72534
73075
|
init_skillSources();
|
|
72535
|
-
GLOBAL_SKILLS_DIR2 =
|
|
73076
|
+
GLOBAL_SKILLS_DIR2 = join22(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
72536
73077
|
});
|
|
72537
73078
|
|
|
72538
73079
|
// src/utils/fs.ts
|
|
@@ -72546,10 +73087,10 @@ __export(exports_fs, {
|
|
|
72546
73087
|
exists: () => exists2
|
|
72547
73088
|
});
|
|
72548
73089
|
import {
|
|
72549
|
-
existsSync as
|
|
73090
|
+
existsSync as existsSync14,
|
|
72550
73091
|
readFileSync as fsReadFileSync2,
|
|
72551
73092
|
writeFileSync as fsWriteFileSync2,
|
|
72552
|
-
mkdirSync as
|
|
73093
|
+
mkdirSync as mkdirSync11
|
|
72553
73094
|
} from "node:fs";
|
|
72554
73095
|
import { dirname as dirname9 } from "node:path";
|
|
72555
73096
|
async function readFile6(path20) {
|
|
@@ -72557,16 +73098,16 @@ async function readFile6(path20) {
|
|
|
72557
73098
|
}
|
|
72558
73099
|
async function writeFile2(path20, content) {
|
|
72559
73100
|
const dir = dirname9(path20);
|
|
72560
|
-
if (!
|
|
72561
|
-
|
|
73101
|
+
if (!existsSync14(dir)) {
|
|
73102
|
+
mkdirSync11(dir, { recursive: true });
|
|
72562
73103
|
}
|
|
72563
73104
|
fsWriteFileSync2(path20, content, { encoding: "utf-8", flush: true });
|
|
72564
73105
|
}
|
|
72565
73106
|
function exists2(path20) {
|
|
72566
|
-
return
|
|
73107
|
+
return existsSync14(path20);
|
|
72567
73108
|
}
|
|
72568
73109
|
async function mkdir2(path20, options) {
|
|
72569
|
-
|
|
73110
|
+
mkdirSync11(path20, options);
|
|
72570
73111
|
}
|
|
72571
73112
|
async function readJsonFile(path20) {
|
|
72572
73113
|
const text = await readFile6(path20);
|
|
@@ -72886,9 +73427,9 @@ __export(exports_auto_update, {
|
|
|
72886
73427
|
import { execFile as execFile9 } from "node:child_process";
|
|
72887
73428
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
72888
73429
|
import { readdir as readdir7, rm } from "node:fs/promises";
|
|
72889
|
-
import { join as
|
|
73430
|
+
import { join as join23 } from "node:path";
|
|
72890
73431
|
import { promisify as promisify9 } from "node:util";
|
|
72891
|
-
function
|
|
73432
|
+
function debugLog3(...args) {
|
|
72892
73433
|
if (DEBUG) {
|
|
72893
73434
|
console.error("[auto-update]", ...args);
|
|
72894
73435
|
}
|
|
@@ -72955,10 +73496,10 @@ function detectPackageManager() {
|
|
|
72955
73496
|
const envOverride = process.env.LETTA_PACKAGE_MANAGER;
|
|
72956
73497
|
if (envOverride) {
|
|
72957
73498
|
if (VALID_PACKAGE_MANAGERS.has(envOverride)) {
|
|
72958
|
-
|
|
73499
|
+
debugLog3("Package manager from LETTA_PACKAGE_MANAGER:", envOverride);
|
|
72959
73500
|
return envOverride;
|
|
72960
73501
|
}
|
|
72961
|
-
|
|
73502
|
+
debugLog3(`Invalid LETTA_PACKAGE_MANAGER="${envOverride}", falling back to path detection`);
|
|
72962
73503
|
}
|
|
72963
73504
|
const argv = process.argv[1] || "";
|
|
72964
73505
|
let resolvedPath = argv;
|
|
@@ -72966,14 +73507,14 @@ function detectPackageManager() {
|
|
|
72966
73507
|
resolvedPath = realpathSync2(argv);
|
|
72967
73508
|
} catch {}
|
|
72968
73509
|
if (/[/\\]\.bun[/\\]/.test(resolvedPath)) {
|
|
72969
|
-
|
|
73510
|
+
debugLog3("Detected package manager from path: bun");
|
|
72970
73511
|
return "bun";
|
|
72971
73512
|
}
|
|
72972
73513
|
if (/[/\\]\.?pnpm[/\\]/.test(resolvedPath)) {
|
|
72973
|
-
|
|
73514
|
+
debugLog3("Detected package manager from path: pnpm");
|
|
72974
73515
|
return "pnpm";
|
|
72975
73516
|
}
|
|
72976
|
-
|
|
73517
|
+
debugLog3("Detected package manager from path: npm (default)");
|
|
72977
73518
|
return "npm";
|
|
72978
73519
|
}
|
|
72979
73520
|
function isAutoUpdateEnabled() {
|
|
@@ -72985,22 +73526,22 @@ function isRunningLocally() {
|
|
|
72985
73526
|
try {
|
|
72986
73527
|
resolvedPath = realpathSync2(argv);
|
|
72987
73528
|
} catch {}
|
|
72988
|
-
|
|
72989
|
-
|
|
73529
|
+
debugLog3("argv[1]:", argv);
|
|
73530
|
+
debugLog3("resolved path:", resolvedPath);
|
|
72990
73531
|
return !resolvedPath.includes("node_modules");
|
|
72991
73532
|
}
|
|
72992
73533
|
async function checkForUpdate() {
|
|
72993
73534
|
const currentVersion = getVersion();
|
|
72994
|
-
|
|
73535
|
+
debugLog3("Current version:", currentVersion);
|
|
72995
73536
|
if (currentVersion.includes("-")) {
|
|
72996
|
-
|
|
73537
|
+
debugLog3("Prerelease version detected, skipping auto-update check");
|
|
72997
73538
|
return { updateAvailable: false, currentVersion };
|
|
72998
73539
|
}
|
|
72999
73540
|
const packageName = resolveUpdatePackageName();
|
|
73000
73541
|
const registryBaseUrl = resolveUpdateRegistryBaseUrl();
|
|
73001
73542
|
const latestUrl = buildLatestVersionUrl(packageName, registryBaseUrl);
|
|
73002
73543
|
try {
|
|
73003
|
-
|
|
73544
|
+
debugLog3("Checking registry for latest version:", latestUrl);
|
|
73004
73545
|
const res = await fetch(latestUrl, {
|
|
73005
73546
|
signal: AbortSignal.timeout(5000)
|
|
73006
73547
|
});
|
|
@@ -73012,18 +73553,18 @@ async function checkForUpdate() {
|
|
|
73012
73553
|
throw new Error("Unexpected registry response shape");
|
|
73013
73554
|
}
|
|
73014
73555
|
const latestVersion = data.version;
|
|
73015
|
-
|
|
73556
|
+
debugLog3("Latest version from registry:", latestVersion);
|
|
73016
73557
|
if (latestVersion !== currentVersion) {
|
|
73017
|
-
|
|
73558
|
+
debugLog3("Update available!");
|
|
73018
73559
|
return {
|
|
73019
73560
|
updateAvailable: true,
|
|
73020
73561
|
latestVersion,
|
|
73021
73562
|
currentVersion
|
|
73022
73563
|
};
|
|
73023
73564
|
}
|
|
73024
|
-
|
|
73565
|
+
debugLog3("Already on latest version");
|
|
73025
73566
|
} catch (error) {
|
|
73026
|
-
|
|
73567
|
+
debugLog3("Failed to check for updates:", error);
|
|
73027
73568
|
return {
|
|
73028
73569
|
updateAvailable: false,
|
|
73029
73570
|
currentVersion,
|
|
@@ -73046,13 +73587,13 @@ async function getNpmGlobalPath() {
|
|
|
73046
73587
|
}
|
|
73047
73588
|
}
|
|
73048
73589
|
async function cleanupOrphanedDirs(globalPath) {
|
|
73049
|
-
const lettaAiDir =
|
|
73590
|
+
const lettaAiDir = join23(globalPath, "lib/node_modules/@letta-ai");
|
|
73050
73591
|
try {
|
|
73051
73592
|
const entries = await readdir7(lettaAiDir);
|
|
73052
73593
|
for (const entry of entries) {
|
|
73053
73594
|
if (entry.startsWith(".letta-code-")) {
|
|
73054
|
-
const orphanPath =
|
|
73055
|
-
|
|
73595
|
+
const orphanPath = join23(lettaAiDir, entry);
|
|
73596
|
+
debugLog3("Cleaning orphaned temp directory:", orphanPath);
|
|
73056
73597
|
await rm(orphanPath, { recursive: true, force: true });
|
|
73057
73598
|
}
|
|
73058
73599
|
}
|
|
@@ -73062,33 +73603,33 @@ async function performUpdate() {
|
|
|
73062
73603
|
const pm = detectPackageManager();
|
|
73063
73604
|
const installCmd = buildInstallCommand(pm);
|
|
73064
73605
|
const installArgs = buildInstallArgs(pm);
|
|
73065
|
-
|
|
73066
|
-
|
|
73606
|
+
debugLog3("Detected package manager:", pm);
|
|
73607
|
+
debugLog3("Install command:", installCmd);
|
|
73067
73608
|
let globalPath = null;
|
|
73068
73609
|
if (pm === "npm") {
|
|
73069
73610
|
globalPath = await getNpmGlobalPath();
|
|
73070
73611
|
if (globalPath) {
|
|
73071
|
-
|
|
73612
|
+
debugLog3("Pre-cleaning orphaned directories in:", globalPath);
|
|
73072
73613
|
await cleanupOrphanedDirs(globalPath);
|
|
73073
73614
|
}
|
|
73074
73615
|
}
|
|
73075
73616
|
try {
|
|
73076
|
-
|
|
73617
|
+
debugLog3(`Running ${installCmd}...`);
|
|
73077
73618
|
await execFileAsync7(pm, installArgs, { timeout: 60000 });
|
|
73078
|
-
|
|
73619
|
+
debugLog3("Update completed successfully");
|
|
73079
73620
|
return { success: true };
|
|
73080
73621
|
} catch (error) {
|
|
73081
73622
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
73082
73623
|
if (pm === "npm" && errorMsg.includes("ENOTEMPTY") && globalPath) {
|
|
73083
|
-
|
|
73624
|
+
debugLog3("ENOTEMPTY detected, attempting cleanup and retry...");
|
|
73084
73625
|
await cleanupOrphanedDirs(globalPath);
|
|
73085
73626
|
try {
|
|
73086
73627
|
await execFileAsync7(pm, installArgs, { timeout: 60000 });
|
|
73087
|
-
|
|
73628
|
+
debugLog3("Update succeeded after cleanup retry");
|
|
73088
73629
|
return { success: true };
|
|
73089
73630
|
} catch (retryError) {
|
|
73090
73631
|
const retryMsg = retryError instanceof Error ? retryError.message : String(retryError);
|
|
73091
|
-
|
|
73632
|
+
debugLog3("Update failed after retry:", retryMsg);
|
|
73092
73633
|
if (retryMsg.includes("ENOTEMPTY")) {
|
|
73093
73634
|
return {
|
|
73094
73635
|
success: false,
|
|
@@ -73101,21 +73642,21 @@ async function performUpdate() {
|
|
|
73101
73642
|
}
|
|
73102
73643
|
const isNpmRaceCondition = pm === "npm" && (errorMsg.includes("TAR_ENTRY_ERROR") || errorMsg.includes("uv_cwd") || errorMsg.includes("spawn sh") && errorMsg.includes("ENOENT"));
|
|
73103
73644
|
if (isNpmRaceCondition) {
|
|
73104
|
-
|
|
73645
|
+
debugLog3("npm race condition detected, cleaning up and retrying...");
|
|
73105
73646
|
if (globalPath) {
|
|
73106
73647
|
await cleanupOrphanedDirs(globalPath);
|
|
73107
73648
|
}
|
|
73108
73649
|
try {
|
|
73109
73650
|
await execFileAsync7(pm, installArgs, { timeout: 60000 });
|
|
73110
|
-
|
|
73651
|
+
debugLog3("Update succeeded after race condition retry");
|
|
73111
73652
|
return { success: true };
|
|
73112
73653
|
} catch (retryError) {
|
|
73113
73654
|
const retryMsg = retryError instanceof Error ? retryError.message : String(retryError);
|
|
73114
|
-
|
|
73655
|
+
debugLog3("Update failed after race condition retry:", retryMsg);
|
|
73115
73656
|
return { success: false, error: retryMsg };
|
|
73116
73657
|
}
|
|
73117
73658
|
}
|
|
73118
|
-
|
|
73659
|
+
debugLog3("Update failed:", error);
|
|
73119
73660
|
return { success: false, error: errorMsg };
|
|
73120
73661
|
}
|
|
73121
73662
|
}
|
|
@@ -73129,16 +73670,16 @@ function isSignificantUpdate(current, latest) {
|
|
|
73129
73670
|
return false;
|
|
73130
73671
|
}
|
|
73131
73672
|
async function checkAndAutoUpdate() {
|
|
73132
|
-
|
|
73133
|
-
|
|
73673
|
+
debugLog3("Auto-update check starting...");
|
|
73674
|
+
debugLog3("isAutoUpdateEnabled:", isAutoUpdateEnabled());
|
|
73134
73675
|
const runningLocally = isRunningLocally();
|
|
73135
|
-
|
|
73676
|
+
debugLog3("isRunningLocally:", runningLocally);
|
|
73136
73677
|
if (!isAutoUpdateEnabled()) {
|
|
73137
|
-
|
|
73678
|
+
debugLog3("Auto-update disabled via DISABLE_AUTOUPDATER=1");
|
|
73138
73679
|
return;
|
|
73139
73680
|
}
|
|
73140
73681
|
if (runningLocally) {
|
|
73141
|
-
|
|
73682
|
+
debugLog3("Running locally, skipping auto-update");
|
|
73142
73683
|
return;
|
|
73143
73684
|
}
|
|
73144
73685
|
const result = await checkForUpdate();
|
|
@@ -73313,6 +73854,7 @@ __export(exports_promptAssets2, {
|
|
|
73313
73854
|
MEMORY_PROMPTS: () => MEMORY_PROMPTS2,
|
|
73314
73855
|
MEMORY_CHECK_REMINDER: () => MEMORY_CHECK_REMINDER2,
|
|
73315
73856
|
INTERRUPT_RECOVERY_ALERT: () => INTERRUPT_RECOVERY_ALERT2,
|
|
73857
|
+
AUTO_INIT_REMINDER: () => AUTO_INIT_REMINDER2,
|
|
73316
73858
|
APPROVAL_RECOVERY_PROMPT: () => APPROVAL_RECOVERY_PROMPT2
|
|
73317
73859
|
});
|
|
73318
73860
|
async function resolveSystemPrompt2(systemPromptPreset) {
|
|
@@ -73331,9 +73873,10 @@ async function resolveSystemPrompt2(systemPromptPreset) {
|
|
|
73331
73873
|
}
|
|
73332
73874
|
return SYSTEM_PROMPT2;
|
|
73333
73875
|
}
|
|
73334
|
-
var SYSTEM_PROMPT2, SYSTEM_PROMPT_MEMORY_ADDON2, SYSTEM_PROMPT_MEMFS_ADDON2, PLAN_MODE_REMINDER2, SKILL_CREATOR_PROMPT2, REMEMBER_PROMPT2, MEMORY_CHECK_REMINDER2, MEMORY_REFLECTION_REMINDER2, APPROVAL_RECOVERY_PROMPT2, INTERRUPT_RECOVERY_ALERT2, MEMORY_PROMPTS2, SYSTEM_PROMPTS2;
|
|
73876
|
+
var SYSTEM_PROMPT2, SYSTEM_PROMPT_MEMORY_ADDON2, SYSTEM_PROMPT_MEMFS_ADDON2, PLAN_MODE_REMINDER2, SKILL_CREATOR_PROMPT2, REMEMBER_PROMPT2, MEMORY_CHECK_REMINDER2, MEMORY_REFLECTION_REMINDER2, APPROVAL_RECOVERY_PROMPT2, AUTO_INIT_REMINDER2, INTERRUPT_RECOVERY_ALERT2, MEMORY_PROMPTS2, SYSTEM_PROMPTS2;
|
|
73335
73877
|
var init_promptAssets2 = __esm(() => {
|
|
73336
73878
|
init_approval_recovery_alert();
|
|
73879
|
+
init_auto_init_reminder();
|
|
73337
73880
|
init_claude();
|
|
73338
73881
|
init_codex();
|
|
73339
73882
|
init_gemini();
|
|
@@ -73366,6 +73909,7 @@ var init_promptAssets2 = __esm(() => {
|
|
|
73366
73909
|
MEMORY_CHECK_REMINDER2 = memory_check_reminder_default;
|
|
73367
73910
|
MEMORY_REFLECTION_REMINDER2 = memory_reflection_reminder_default;
|
|
73368
73911
|
APPROVAL_RECOVERY_PROMPT2 = approval_recovery_alert_default;
|
|
73912
|
+
AUTO_INIT_REMINDER2 = auto_init_reminder_default;
|
|
73369
73913
|
INTERRUPT_RECOVERY_ALERT2 = interrupt_recovery_alert_default;
|
|
73370
73914
|
MEMORY_PROMPTS2 = {
|
|
73371
73915
|
"persona.mdx": persona_default,
|
|
@@ -73438,9 +73982,9 @@ __export(exports_subagents2, {
|
|
|
73438
73982
|
GLOBAL_AGENTS_DIR: () => GLOBAL_AGENTS_DIR2,
|
|
73439
73983
|
AGENTS_DIR: () => AGENTS_DIR2
|
|
73440
73984
|
});
|
|
73441
|
-
import { existsSync as
|
|
73985
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
73442
73986
|
import { readdir as readdir8, readFile as readFile7 } from "node:fs/promises";
|
|
73443
|
-
import { join as
|
|
73987
|
+
import { join as join25 } from "node:path";
|
|
73444
73988
|
function isValidName2(name) {
|
|
73445
73989
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
73446
73990
|
}
|
|
@@ -73522,7 +74066,7 @@ function getBuiltinSubagentNames2() {
|
|
|
73522
74066
|
return new Set(Object.keys(getBuiltinSubagents2()));
|
|
73523
74067
|
}
|
|
73524
74068
|
async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors) {
|
|
73525
|
-
if (!
|
|
74069
|
+
if (!existsSync16(agentsDir)) {
|
|
73526
74070
|
return;
|
|
73527
74071
|
}
|
|
73528
74072
|
try {
|
|
@@ -73531,7 +74075,7 @@ async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors
|
|
|
73531
74075
|
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
73532
74076
|
continue;
|
|
73533
74077
|
}
|
|
73534
|
-
const filePath =
|
|
74078
|
+
const filePath = join25(agentsDir, entry.name);
|
|
73535
74079
|
try {
|
|
73536
74080
|
const config = await parseSubagentFile2(filePath);
|
|
73537
74081
|
if (config) {
|
|
@@ -73563,7 +74107,7 @@ async function discoverSubagents2(workingDirectory = process.cwd()) {
|
|
|
73563
74107
|
const subagents = [];
|
|
73564
74108
|
const seenNames = new Set;
|
|
73565
74109
|
await discoverSubagentsFromDir2(GLOBAL_AGENTS_DIR2, seenNames, subagents, errors);
|
|
73566
|
-
const projectAgentsDir =
|
|
74110
|
+
const projectAgentsDir = join25(workingDirectory, AGENTS_DIR2);
|
|
73567
74111
|
await discoverSubagentsFromDir2(projectAgentsDir, seenNames, subagents, errors);
|
|
73568
74112
|
return { subagents, errors };
|
|
73569
74113
|
}
|
|
@@ -73606,7 +74150,7 @@ var init_subagents2 = __esm(() => {
|
|
|
73606
74150
|
recall_default,
|
|
73607
74151
|
reflection_default
|
|
73608
74152
|
];
|
|
73609
|
-
GLOBAL_AGENTS_DIR2 =
|
|
74153
|
+
GLOBAL_AGENTS_DIR2 = join25(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
|
|
73610
74154
|
VALID_MEMORY_BLOCKS2 = new Set(MEMORY_BLOCK_LABELS);
|
|
73611
74155
|
cache5 = {
|
|
73612
74156
|
builtins: null,
|
|
@@ -73978,24 +74522,6 @@ var init_cli2 = __esm(() => {
|
|
|
73978
74522
|
cliPermissions2 = new CliPermissions2;
|
|
73979
74523
|
});
|
|
73980
74524
|
|
|
73981
|
-
// src/agent/approval-recovery.ts
|
|
73982
|
-
async function fetchRunErrorDetail(runId) {
|
|
73983
|
-
if (!runId)
|
|
73984
|
-
return null;
|
|
73985
|
-
try {
|
|
73986
|
-
const client = await getClient2();
|
|
73987
|
-
const run = await client.runs.retrieve(runId);
|
|
73988
|
-
const metaError = run.metadata?.error;
|
|
73989
|
-
return metaError?.detail ?? metaError?.message ?? metaError?.error?.detail ?? metaError?.error?.message ?? null;
|
|
73990
|
-
} catch {
|
|
73991
|
-
return null;
|
|
73992
|
-
}
|
|
73993
|
-
}
|
|
73994
|
-
var init_approval_recovery = __esm(async () => {
|
|
73995
|
-
init_turn_recovery_policy();
|
|
73996
|
-
await init_client2();
|
|
73997
|
-
});
|
|
73998
|
-
|
|
73999
74525
|
// src/agent/listMessagesRouting.ts
|
|
74000
74526
|
function resolveListMessagesRoute(listReq, sessionConvId, sessionAgentId) {
|
|
74001
74527
|
const targetConvId = listReq.conversation_id ?? sessionConvId;
|
|
@@ -74003,7 +74529,7 @@ function resolveListMessagesRoute(listReq, sessionConvId, sessionAgentId) {
|
|
|
74003
74529
|
return { kind: "conversations", conversationId: targetConvId };
|
|
74004
74530
|
}
|
|
74005
74531
|
const agentId = listReq.agent_id ?? sessionAgentId;
|
|
74006
|
-
return { kind: "conversations", conversationId: agentId };
|
|
74532
|
+
return { kind: "conversations", conversationId: "default", agentId };
|
|
74007
74533
|
}
|
|
74008
74534
|
|
|
74009
74535
|
// src/agent/bootstrapHandler.ts
|
|
@@ -74022,7 +74548,7 @@ async function handleBootstrapSessionState(params) {
|
|
|
74022
74548
|
try {
|
|
74023
74549
|
const route = resolveListMessagesRoute({ conversation_id: undefined, agent_id: sessionContext.agentId }, sessionContext.conversationId, sessionContext.agentId);
|
|
74024
74550
|
const listStart = Date.now();
|
|
74025
|
-
const page = await client.conversations.messages.list(route.conversationId, { limit: limit2, order });
|
|
74551
|
+
const page = await client.conversations.messages.list(route.conversationId, { limit: limit2, order, ...route.agentId ? { agent_id: route.agentId } : {} });
|
|
74026
74552
|
const items = page.getPaginatedItems();
|
|
74027
74553
|
const listEnd = Date.now();
|
|
74028
74554
|
const hasMore = items.length >= limit2;
|
|
@@ -74377,7 +74903,12 @@ async function handleListMessages(params) {
|
|
|
74377
74903
|
};
|
|
74378
74904
|
try {
|
|
74379
74905
|
const route = resolveListMessagesRoute(listReq, sessionConversationId, sessionAgentId);
|
|
74380
|
-
const page = await client.conversations.messages.list(route.conversationId, {
|
|
74906
|
+
const page = await client.conversations.messages.list(route.conversationId, {
|
|
74907
|
+
limit: limit2,
|
|
74908
|
+
order,
|
|
74909
|
+
...route.agentId ? { agent_id: route.agentId } : {},
|
|
74910
|
+
...cursorOpts
|
|
74911
|
+
});
|
|
74381
74912
|
const items = page.getPaginatedItems();
|
|
74382
74913
|
const hasMore = items.length >= limit2;
|
|
74383
74914
|
const oldestId = items.length > 0 ? items[items.length - 1]?.id : undefined;
|
|
@@ -74998,6 +75529,11 @@ var init_catalog = __esm(() => {
|
|
|
74998
75529
|
description: "Compaction-triggered reflection reminder/auto-launch behavior",
|
|
74999
75530
|
modes: ["interactive", "headless-one-shot", "headless-bidirectional"]
|
|
75000
75531
|
},
|
|
75532
|
+
{
|
|
75533
|
+
id: "deep-init",
|
|
75534
|
+
description: "Auto-launch deep memory init after shallow init + turn gate",
|
|
75535
|
+
modes: ["interactive"]
|
|
75536
|
+
},
|
|
75001
75537
|
{
|
|
75002
75538
|
id: "command-io",
|
|
75003
75539
|
description: "Recent slash command input/output context",
|
|
@@ -75007,6 +75543,11 @@ var init_catalog = __esm(() => {
|
|
|
75007
75543
|
id: "toolset-change",
|
|
75008
75544
|
description: "Client-side toolset change context",
|
|
75009
75545
|
modes: ["interactive"]
|
|
75546
|
+
},
|
|
75547
|
+
{
|
|
75548
|
+
id: "auto-init",
|
|
75549
|
+
description: "Auto-init background onboarding notification",
|
|
75550
|
+
modes: ["interactive"]
|
|
75010
75551
|
}
|
|
75011
75552
|
];
|
|
75012
75553
|
SHARED_REMINDER_IDS = SHARED_REMINDER_CATALOG.map((entry) => entry.id);
|
|
@@ -75014,7 +75555,7 @@ var init_catalog = __esm(() => {
|
|
|
75014
75555
|
});
|
|
75015
75556
|
|
|
75016
75557
|
// src/reminders/engine.ts
|
|
75017
|
-
import { join as
|
|
75558
|
+
import { join as join26 } from "node:path";
|
|
75018
75559
|
async function buildAgentInfoReminder(context3) {
|
|
75019
75560
|
if (context3.state.hasSentAgentInfo) {
|
|
75020
75561
|
return null;
|
|
@@ -75046,7 +75587,7 @@ async function buildSkillsReminder(context3) {
|
|
|
75046
75587
|
const previousSkillsReminder = context3.state.cachedSkillsReminder;
|
|
75047
75588
|
let latestSkillsReminder = previousSkillsReminder ?? "";
|
|
75048
75589
|
try {
|
|
75049
|
-
const skillsDir = getSkillsDirectory() ||
|
|
75590
|
+
const skillsDir = getSkillsDirectory() || join26(process.cwd(), SKILLS_DIR);
|
|
75050
75591
|
const { skills } = await discoverSkills(skillsDir, context3.agent.id, {
|
|
75051
75592
|
sources: context3.skillSources
|
|
75052
75593
|
});
|
|
@@ -75129,6 +75670,30 @@ async function buildReflectionCompactionReminder(context3) {
|
|
|
75129
75670
|
}
|
|
75130
75671
|
return buildCompactionMemoryReminder(context3.agent.id);
|
|
75131
75672
|
}
|
|
75673
|
+
async function buildAutoInitReminder(context3) {
|
|
75674
|
+
if (!context3.state.pendingAutoInitReminder)
|
|
75675
|
+
return null;
|
|
75676
|
+
context3.state.pendingAutoInitReminder = false;
|
|
75677
|
+
const { AUTO_INIT_REMINDER: AUTO_INIT_REMINDER3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
|
|
75678
|
+
return AUTO_INIT_REMINDER3;
|
|
75679
|
+
}
|
|
75680
|
+
async function maybeLaunchDeepInit(context3) {
|
|
75681
|
+
if (!DEEP_INIT_AUTO_LAUNCH_ENABLED)
|
|
75682
|
+
return null;
|
|
75683
|
+
if (!context3.state.shallowInitCompleted)
|
|
75684
|
+
return null;
|
|
75685
|
+
if (context3.state.deepInitFired)
|
|
75686
|
+
return null;
|
|
75687
|
+
if (context3.state.turnCount < 8)
|
|
75688
|
+
return null;
|
|
75689
|
+
const memfsEnabled = settingsManager.isMemfsEnabled(context3.agent.id);
|
|
75690
|
+
if (!memfsEnabled)
|
|
75691
|
+
return null;
|
|
75692
|
+
if (context3.maybeLaunchDeepInitSubagent) {
|
|
75693
|
+
await context3.maybeLaunchDeepInitSubagent();
|
|
75694
|
+
}
|
|
75695
|
+
return null;
|
|
75696
|
+
}
|
|
75132
75697
|
function escapeXml2(value) {
|
|
75133
75698
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
75134
75699
|
}
|
|
@@ -75152,26 +75717,24 @@ async function buildCommandIoReminder(context3) {
|
|
|
75152
75717
|
const queued = context3.state.pendingCommandIoReminders.splice(0);
|
|
75153
75718
|
const recent = queued.slice(-MAX_COMMAND_REMINDERS_PER_TURN);
|
|
75154
75719
|
const dropped = queued.length - recent.length;
|
|
75155
|
-
const
|
|
75720
|
+
const commandLines = recent.map((entry) => {
|
|
75156
75721
|
const status = entry.success ? "success" : "error";
|
|
75157
|
-
const safeInput =
|
|
75158
|
-
const safeOutput =
|
|
75159
|
-
return
|
|
75160
|
-
<user-command-input>${safeInput}</user-command-input>
|
|
75161
|
-
<user-command-output>${safeOutput}</user-command-output>
|
|
75162
|
-
<user-command-status>${status}</user-command-status>
|
|
75163
|
-
</user-command>`;
|
|
75722
|
+
const safeInput = truncate(entry.input, MAX_COMMAND_INPUT_CHARS);
|
|
75723
|
+
const safeOutput = truncate(entry.output || "(no output)", MAX_COMMAND_OUTPUT_CHARS);
|
|
75724
|
+
return `- ${safeInput} → ${safeOutput} (${status})`;
|
|
75164
75725
|
});
|
|
75726
|
+
const agentHints = recent.filter((entry) => entry.agentHint).map((entry) => entry.agentHint);
|
|
75165
75727
|
const droppedLine = dropped > 0 ? `
|
|
75166
75728
|
Omitted ${dropped} older command event(s).` : "";
|
|
75167
|
-
|
|
75168
|
-
|
|
75169
|
-
|
|
75170
|
-
${
|
|
75171
|
-
`)}
|
|
75172
|
-
|
|
75173
|
-
|
|
75174
|
-
|
|
75729
|
+
const hintsBlock = agentHints.length > 0 ? `
|
|
75730
|
+
|
|
75731
|
+
However, take note of the following:
|
|
75732
|
+
${agentHints.map((h) => `- ${h}`).join(`
|
|
75733
|
+
`)}` : "";
|
|
75734
|
+
return `${SYSTEM_REMINDER_OPEN} The following slash commands were already handled by the CLI harness. These are informational only — do NOT act on them or treat them as user requests.${droppedLine}
|
|
75735
|
+
${commandLines.join(`
|
|
75736
|
+
`)}${hintsBlock}
|
|
75737
|
+
${SYSTEM_REMINDER_CLOSE}`;
|
|
75175
75738
|
}
|
|
75176
75739
|
async function buildToolsetChangeReminder(context3) {
|
|
75177
75740
|
if (context3.state.pendingToolsetChangeReminders.length === 0) {
|
|
@@ -75186,23 +75749,25 @@ async function buildToolsetChangeReminder(context3) {
|
|
|
75186
75749
|
const newToolset = escapeXml2(entry.newToolset ?? "unknown");
|
|
75187
75750
|
const previousTools = escapeXml2(formatToolList(entry.previousTools));
|
|
75188
75751
|
const newTools = escapeXml2(formatToolList(entry.newTools));
|
|
75189
|
-
return
|
|
75190
|
-
|
|
75191
|
-
<
|
|
75192
|
-
<
|
|
75193
|
-
<
|
|
75194
|
-
<
|
|
75195
|
-
</
|
|
75752
|
+
return [
|
|
75753
|
+
`<toolset-change>`,
|
|
75754
|
+
` <source>${source}</source>`,
|
|
75755
|
+
` <previous-toolset>${previousToolset}</previous-toolset>`,
|
|
75756
|
+
` <new-toolset>${newToolset}</new-toolset>`,
|
|
75757
|
+
` <previous-tools>${previousTools}</previous-tools>`,
|
|
75758
|
+
` <new-tools>${newTools}</new-tools>`,
|
|
75759
|
+
`</toolset-change>`
|
|
75760
|
+
].join(`
|
|
75761
|
+
`);
|
|
75196
75762
|
});
|
|
75197
75763
|
const droppedLine = dropped > 0 ? `
|
|
75198
75764
|
Omitted ${dropped} older toolset change event(s).` : "";
|
|
75199
|
-
return `${SYSTEM_REMINDER_OPEN}
|
|
75200
|
-
|
|
75765
|
+
return `${SYSTEM_REMINDER_OPEN} The user just changed your toolset (specifically, client-side tools that are attached to the Letta Code harness, which may be a subset of your total tools).${droppedLine}
|
|
75766
|
+
|
|
75201
75767
|
${changeBlocks.join(`
|
|
75202
|
-
`)}
|
|
75203
|
-
${SYSTEM_REMINDER_CLOSE}
|
|
75204
75768
|
|
|
75205
|
-
|
|
75769
|
+
`)}
|
|
75770
|
+
${SYSTEM_REMINDER_CLOSE}`;
|
|
75206
75771
|
}
|
|
75207
75772
|
function assertSharedReminderCoverage() {
|
|
75208
75773
|
const catalogIds = new Set(SHARED_REMINDER_CATALOG.map((entry) => entry.id));
|
|
@@ -75250,7 +75815,7 @@ function prependReminderPartsToContent(content, reminderParts) {
|
|
|
75250
75815
|
}
|
|
75251
75816
|
return content;
|
|
75252
75817
|
}
|
|
75253
|
-
var PERMISSION_MODE_DESCRIPTIONS, MAX_COMMAND_REMINDERS_PER_TURN = 10, MAX_TOOLSET_REMINDERS_PER_TURN = 5, MAX_COMMAND_INPUT_CHARS = 2000, MAX_COMMAND_OUTPUT_CHARS = 4000, MAX_TOOL_LIST_CHARS = 3000, sharedReminderProviders;
|
|
75818
|
+
var PERMISSION_MODE_DESCRIPTIONS, DEEP_INIT_AUTO_LAUNCH_ENABLED = false, MAX_COMMAND_REMINDERS_PER_TURN = 10, MAX_TOOLSET_REMINDERS_PER_TURN = 5, MAX_COMMAND_INPUT_CHARS = 2000, MAX_COMMAND_OUTPUT_CHARS = 4000, MAX_TOOL_LIST_CHARS = 3000, sharedReminderProviders;
|
|
75254
75819
|
var init_engine = __esm(async () => {
|
|
75255
75820
|
init_context();
|
|
75256
75821
|
init_skills();
|
|
@@ -75277,8 +75842,10 @@ var init_engine = __esm(async () => {
|
|
|
75277
75842
|
"plan-mode": buildPlanModeReminder,
|
|
75278
75843
|
"reflection-step-count": buildReflectionStepReminder,
|
|
75279
75844
|
"reflection-compaction": buildReflectionCompactionReminder,
|
|
75845
|
+
"deep-init": maybeLaunchDeepInit,
|
|
75280
75846
|
"command-io": buildCommandIoReminder,
|
|
75281
|
-
"toolset-change": buildToolsetChangeReminder
|
|
75847
|
+
"toolset-change": buildToolsetChangeReminder,
|
|
75848
|
+
"auto-init": buildAutoInitReminder
|
|
75282
75849
|
};
|
|
75283
75850
|
assertSharedReminderCoverage();
|
|
75284
75851
|
});
|
|
@@ -75295,8 +75862,11 @@ function createSharedReminderState() {
|
|
|
75295
75862
|
turnCount: 0,
|
|
75296
75863
|
pendingSkillsReinject: false,
|
|
75297
75864
|
pendingReflectionTrigger: false,
|
|
75865
|
+
pendingAutoInitReminder: false,
|
|
75298
75866
|
pendingCommandIoReminders: [],
|
|
75299
|
-
pendingToolsetChangeReminders: []
|
|
75867
|
+
pendingToolsetChangeReminders: [],
|
|
75868
|
+
shallowInitCompleted: false,
|
|
75869
|
+
deepInitFired: false
|
|
75300
75870
|
};
|
|
75301
75871
|
}
|
|
75302
75872
|
function resetSharedReminderState(state) {
|
|
@@ -75480,7 +76050,7 @@ function parseRegistryHandle(handle) {
|
|
|
75480
76050
|
}
|
|
75481
76051
|
async function importAgentFromRegistry(options) {
|
|
75482
76052
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
75483
|
-
const { join:
|
|
76053
|
+
const { join: join27 } = await import("node:path");
|
|
75484
76054
|
const { writeFile: writeFile4, unlink } = await import("node:fs/promises");
|
|
75485
76055
|
const { author, name } = parseRegistryHandle(options.handle);
|
|
75486
76056
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -75492,7 +76062,7 @@ async function importAgentFromRegistry(options) {
|
|
|
75492
76062
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
75493
76063
|
}
|
|
75494
76064
|
const afContent = await response.text();
|
|
75495
|
-
const tempPath =
|
|
76065
|
+
const tempPath = join27(tmpdir3(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
75496
76066
|
await writeFile4(tempPath, afContent, "utf-8");
|
|
75497
76067
|
try {
|
|
75498
76068
|
const result = await importAgentFromFile({
|
|
@@ -75985,6 +76555,7 @@ In headless mode, use:
|
|
|
75985
76555
|
}
|
|
75986
76556
|
if (specifiedConversationId && specifiedConversationId !== "default") {
|
|
75987
76557
|
try {
|
|
76558
|
+
debugLog("conversations", `retrieve(${specifiedConversationId}) [headless conv→agent lookup]`);
|
|
75988
76559
|
const conversation = await client.conversations.retrieve(specifiedConversationId);
|
|
75989
76560
|
agent = await client.agents.retrieve(conversation.agent_id);
|
|
75990
76561
|
} catch (_error) {
|
|
@@ -76162,6 +76733,7 @@ In headless mode, use:
|
|
|
76162
76733
|
conversationId = "default";
|
|
76163
76734
|
} else {
|
|
76164
76735
|
try {
|
|
76736
|
+
debugLog("conversations", `retrieve(${specifiedConversationId}) [headless --conv validate]`);
|
|
76165
76737
|
await client.conversations.retrieve(specifiedConversationId);
|
|
76166
76738
|
conversationId = specifiedConversationId;
|
|
76167
76739
|
} catch {
|
|
@@ -76177,6 +76749,7 @@ In headless mode, use:
|
|
|
76177
76749
|
conversationId = "default";
|
|
76178
76750
|
} else {
|
|
76179
76751
|
try {
|
|
76752
|
+
debugLog("conversations", `retrieve(${lastSession.conversationId}) [headless lastSession resume]`);
|
|
76180
76753
|
await client.conversations.retrieve(lastSession.conversationId);
|
|
76181
76754
|
conversationId = lastSession.conversationId;
|
|
76182
76755
|
} catch {
|
|
@@ -76493,21 +77066,22 @@ ${loadedContents.join(`
|
|
|
76493
77066
|
}
|
|
76494
77067
|
if (preStreamAction === "retry_conversation_busy") {
|
|
76495
77068
|
conversationBusyRetries += 1;
|
|
77069
|
+
const retryDelayMs = CONVERSATION_BUSY_RETRY_BASE_DELAY_MS * 2 ** (conversationBusyRetries - 1);
|
|
76496
77070
|
if (outputFormat === "stream-json") {
|
|
76497
77071
|
const retryMsg = {
|
|
76498
77072
|
type: "retry",
|
|
76499
77073
|
reason: "error",
|
|
76500
77074
|
attempt: conversationBusyRetries,
|
|
76501
77075
|
max_attempts: CONVERSATION_BUSY_MAX_RETRIES,
|
|
76502
|
-
delay_ms:
|
|
77076
|
+
delay_ms: retryDelayMs,
|
|
76503
77077
|
session_id: sessionId,
|
|
76504
77078
|
uuid: `retry-conversation-busy-${randomUUID7()}`
|
|
76505
77079
|
};
|
|
76506
77080
|
console.log(JSON.stringify(retryMsg));
|
|
76507
77081
|
} else {
|
|
76508
|
-
console.error(`Conversation is busy, waiting ${
|
|
77082
|
+
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
76509
77083
|
}
|
|
76510
|
-
await new Promise((resolve25) => setTimeout(resolve25,
|
|
77084
|
+
await new Promise((resolve25) => setTimeout(resolve25, retryDelayMs));
|
|
76511
77085
|
continue;
|
|
76512
77086
|
}
|
|
76513
77087
|
if (preStreamAction === "retry_transient") {
|
|
@@ -77789,7 +78363,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
77789
78363
|
setMessageQueueAdder(null);
|
|
77790
78364
|
process.exit(0);
|
|
77791
78365
|
}
|
|
77792
|
-
var LLM_API_ERROR_MAX_RETRIES2 = 3, EMPTY_RESPONSE_MAX_RETRIES = 2, CONVERSATION_BUSY_MAX_RETRIES =
|
|
78366
|
+
var LLM_API_ERROR_MAX_RETRIES2 = 3, EMPTY_RESPONSE_MAX_RETRIES = 2, CONVERSATION_BUSY_MAX_RETRIES = 3, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 1e4;
|
|
77793
78367
|
var init_headless = __esm(async () => {
|
|
77794
78368
|
init_error();
|
|
77795
78369
|
init_bootstrapHandler();
|
|
@@ -77802,6 +78376,7 @@ var init_headless = __esm(async () => {
|
|
|
77802
78376
|
init_constants();
|
|
77803
78377
|
init_diffPreview();
|
|
77804
78378
|
init_interactivePolicy();
|
|
78379
|
+
init_debug();
|
|
77805
78380
|
init_timing();
|
|
77806
78381
|
await __promiseAll([
|
|
77807
78382
|
init_approval_recovery(),
|
|
@@ -78111,10 +78686,10 @@ __export(exports_settings, {
|
|
|
78111
78686
|
loadProjectSettings: () => loadProjectSettings,
|
|
78112
78687
|
getSetting: () => getSetting
|
|
78113
78688
|
});
|
|
78114
|
-
import { homedir as
|
|
78115
|
-
import { join as
|
|
78689
|
+
import { homedir as homedir21 } from "node:os";
|
|
78690
|
+
import { join as join28 } from "node:path";
|
|
78116
78691
|
function getSettingsPath() {
|
|
78117
|
-
return
|
|
78692
|
+
return join28(homedir21(), ".letta", "settings.json");
|
|
78118
78693
|
}
|
|
78119
78694
|
async function loadSettings() {
|
|
78120
78695
|
const settingsPath = getSettingsPath();
|
|
@@ -78151,7 +78726,7 @@ async function getSetting(key) {
|
|
|
78151
78726
|
return settings[key];
|
|
78152
78727
|
}
|
|
78153
78728
|
function getProjectSettingsPath() {
|
|
78154
|
-
return
|
|
78729
|
+
return join28(process.cwd(), ".letta", "settings.local.json");
|
|
78155
78730
|
}
|
|
78156
78731
|
async function loadProjectSettings() {
|
|
78157
78732
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -78169,7 +78744,7 @@ async function loadProjectSettings() {
|
|
|
78169
78744
|
}
|
|
78170
78745
|
async function saveProjectSettings(settings) {
|
|
78171
78746
|
const settingsPath = getProjectSettingsPath();
|
|
78172
|
-
const dirPath =
|
|
78747
|
+
const dirPath = join28(process.cwd(), ".letta");
|
|
78173
78748
|
try {
|
|
78174
78749
|
if (!exists(dirPath)) {
|
|
78175
78750
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -78671,6 +79246,13 @@ function createCommandRunner({
|
|
|
78671
79246
|
onCommandFinished
|
|
78672
79247
|
}) {
|
|
78673
79248
|
function getHandle(id, input) {
|
|
79249
|
+
const handle = {
|
|
79250
|
+
id,
|
|
79251
|
+
input,
|
|
79252
|
+
update: null,
|
|
79253
|
+
finish: null,
|
|
79254
|
+
fail: null
|
|
79255
|
+
};
|
|
78674
79256
|
const update = (updateData) => {
|
|
78675
79257
|
const previous = buffersRef.current.byId.get(id);
|
|
78676
79258
|
const wasFinished = previous?.kind === "command" && previous.phase === "finished";
|
|
@@ -78687,24 +79269,26 @@ function createCommandRunner({
|
|
|
78687
79269
|
output: next.output,
|
|
78688
79270
|
success: next.success !== false,
|
|
78689
79271
|
dimOutput: next.dimOutput,
|
|
78690
|
-
preformatted: next.preformatted
|
|
79272
|
+
preformatted: next.preformatted,
|
|
79273
|
+
agentHint: handle.agentHint
|
|
78691
79274
|
});
|
|
78692
79275
|
}
|
|
78693
79276
|
refreshDerived();
|
|
78694
79277
|
};
|
|
78695
|
-
|
|
79278
|
+
handle.update = update;
|
|
79279
|
+
handle.finish = (finalOutput, success = true, dimOutput, preformatted) => update({
|
|
78696
79280
|
output: finalOutput,
|
|
78697
79281
|
phase: "finished",
|
|
78698
79282
|
success,
|
|
78699
79283
|
dimOutput,
|
|
78700
79284
|
preformatted
|
|
78701
79285
|
});
|
|
78702
|
-
|
|
79286
|
+
handle.fail = (finalOutput) => update({
|
|
78703
79287
|
output: finalOutput,
|
|
78704
79288
|
phase: "finished",
|
|
78705
79289
|
success: false
|
|
78706
79290
|
});
|
|
78707
|
-
return
|
|
79291
|
+
return handle;
|
|
78708
79292
|
}
|
|
78709
79293
|
function start(input, output) {
|
|
78710
79294
|
const id = createId("cmd");
|
|
@@ -80477,9 +81061,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
80477
81061
|
const relPath = relative9(cwd2, filePath);
|
|
80478
81062
|
const displayPath = relPath.startsWith("..") ? filePath : relPath;
|
|
80479
81063
|
if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
|
|
80480
|
-
const { existsSync:
|
|
81064
|
+
const { existsSync: existsSync18 } = __require("node:fs");
|
|
80481
81065
|
try {
|
|
80482
|
-
if (
|
|
81066
|
+
if (existsSync18(filePath)) {
|
|
80483
81067
|
return `Overwrite ${displayPath}?`;
|
|
80484
81068
|
}
|
|
80485
81069
|
} catch {}
|
|
@@ -81181,9 +81765,9 @@ function getHeaderText(fileEdit) {
|
|
|
81181
81765
|
const relPath = relative9(cwd2, fileEdit.filePath);
|
|
81182
81766
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
81183
81767
|
if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
|
|
81184
|
-
const { existsSync:
|
|
81768
|
+
const { existsSync: existsSync18 } = __require("node:fs");
|
|
81185
81769
|
try {
|
|
81186
|
-
if (
|
|
81770
|
+
if (existsSync18(fileEdit.filePath)) {
|
|
81187
81771
|
return `Overwrite ${displayPath}?`;
|
|
81188
81772
|
}
|
|
81189
81773
|
} catch {}
|
|
@@ -82821,9 +83405,9 @@ html.dark .agent-name { color: var(--text-dim); }
|
|
|
82821
83405
|
var init_plan_viewer_template = () => {};
|
|
82822
83406
|
|
|
82823
83407
|
// src/web/generate-plan-viewer.ts
|
|
82824
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
82825
|
-
import { homedir as
|
|
82826
|
-
import { join as
|
|
83408
|
+
import { chmodSync as chmodSync2, existsSync as existsSync18, mkdirSync as mkdirSync14, writeFileSync as writeFileSync8 } from "node:fs";
|
|
83409
|
+
import { homedir as homedir22 } from "node:os";
|
|
83410
|
+
import { join as join29 } from "node:path";
|
|
82827
83411
|
async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
82828
83412
|
const data = {
|
|
82829
83413
|
agent: { name: options?.agentName ?? "" },
|
|
@@ -82833,13 +83417,13 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
|
82833
83417
|
};
|
|
82834
83418
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
82835
83419
|
const html = plan_viewer_template_default.replace("<!--LETTA_PLAN_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
82836
|
-
if (!
|
|
82837
|
-
|
|
83420
|
+
if (!existsSync18(VIEWERS_DIR)) {
|
|
83421
|
+
mkdirSync14(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
82838
83422
|
}
|
|
82839
83423
|
try {
|
|
82840
83424
|
chmodSync2(VIEWERS_DIR, 448);
|
|
82841
83425
|
} catch {}
|
|
82842
|
-
const filePath =
|
|
83426
|
+
const filePath = join29(VIEWERS_DIR, "plan.html");
|
|
82843
83427
|
writeFileSync8(filePath, html);
|
|
82844
83428
|
chmodSync2(filePath, 384);
|
|
82845
83429
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -82856,7 +83440,7 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
|
82856
83440
|
var VIEWERS_DIR;
|
|
82857
83441
|
var init_generate_plan_viewer = __esm(() => {
|
|
82858
83442
|
init_plan_viewer_template();
|
|
82859
|
-
VIEWERS_DIR =
|
|
83443
|
+
VIEWERS_DIR = join29(homedir22(), ".letta", "viewers");
|
|
82860
83444
|
});
|
|
82861
83445
|
|
|
82862
83446
|
// src/cli/components/StaticPlanApproval.tsx
|
|
@@ -84054,7 +84638,8 @@ function ConversationSelector2({
|
|
|
84054
84638
|
let defaultConversation = null;
|
|
84055
84639
|
if (!afterCursor) {
|
|
84056
84640
|
try {
|
|
84057
|
-
const defaultMessages = await client.conversations.messages.list(
|
|
84641
|
+
const defaultMessages = await client.conversations.messages.list("default", {
|
|
84642
|
+
agent_id: agentId,
|
|
84058
84643
|
limit: 20,
|
|
84059
84644
|
order: "desc"
|
|
84060
84645
|
});
|
|
@@ -84829,9 +85414,9 @@ var init_pasteRegistry = __esm(() => {
|
|
|
84829
85414
|
|
|
84830
85415
|
// src/cli/helpers/clipboard.ts
|
|
84831
85416
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
84832
|
-
import { existsSync as
|
|
85417
|
+
import { existsSync as existsSync19, readFileSync as readFileSync6, statSync as statSync4, unlinkSync as unlinkSync8 } from "node:fs";
|
|
84833
85418
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
84834
|
-
import { basename as basename4, extname as extname5, isAbsolute as isAbsolute16, join as
|
|
85419
|
+
import { basename as basename4, extname as extname5, isAbsolute as isAbsolute16, join as join30, resolve as resolve25 } from "node:path";
|
|
84835
85420
|
function countLines2(text) {
|
|
84836
85421
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
84837
85422
|
}
|
|
@@ -84881,8 +85466,8 @@ function translatePasteForImages(paste) {
|
|
|
84881
85466
|
if (!isAbsolute16(filePath))
|
|
84882
85467
|
filePath = resolve25(process.cwd(), filePath);
|
|
84883
85468
|
const ext3 = extname5(filePath || "").toLowerCase();
|
|
84884
|
-
if (IMAGE_EXTS.has(ext3) &&
|
|
84885
|
-
const buf =
|
|
85469
|
+
if (IMAGE_EXTS.has(ext3) && existsSync19(filePath) && statSync4(filePath).isFile()) {
|
|
85470
|
+
const buf = readFileSync6(filePath);
|
|
84886
85471
|
const b64 = buf.toString("base64");
|
|
84887
85472
|
const mt = ext3 === ".png" ? "image/png" : ext3 === ".jpg" || ext3 === ".jpeg" ? "image/jpeg" : ext3 === ".gif" ? "image/gif" : ext3 === ".webp" ? "image/webp" : ext3 === ".bmp" ? "image/bmp" : ext3 === ".svg" ? "image/svg+xml" : ext3 === ".tif" || ext3 === ".tiff" ? "image/tiff" : ext3 === ".heic" ? "image/heic" : ext3 === ".heif" ? "image/heif" : ext3 === ".avif" ? "image/avif" : "application/octet-stream";
|
|
84888
85473
|
const id = allocateImage({
|
|
@@ -84899,7 +85484,7 @@ function translatePasteForImages(paste) {
|
|
|
84899
85484
|
function getClipboardImageToTempFile() {
|
|
84900
85485
|
if (process.platform !== "darwin")
|
|
84901
85486
|
return null;
|
|
84902
|
-
const tempPath =
|
|
85487
|
+
const tempPath = join30(tmpdir3(), `letta-clipboard-${Date.now()}.bin`);
|
|
84903
85488
|
try {
|
|
84904
85489
|
const jxa = `
|
|
84905
85490
|
ObjC.import('AppKit');
|
|
@@ -84922,13 +85507,13 @@ function getClipboardImageToTempFile() {
|
|
|
84922
85507
|
encoding: "utf8",
|
|
84923
85508
|
stdio: ["ignore", "pipe", "ignore"]
|
|
84924
85509
|
}).trim();
|
|
84925
|
-
if (!uti || !
|
|
85510
|
+
if (!uti || !existsSync19(tempPath))
|
|
84926
85511
|
return null;
|
|
84927
85512
|
return { tempPath, uti };
|
|
84928
85513
|
} catch {
|
|
84929
|
-
if (
|
|
85514
|
+
if (existsSync19(tempPath)) {
|
|
84930
85515
|
try {
|
|
84931
|
-
|
|
85516
|
+
unlinkSync8(tempPath);
|
|
84932
85517
|
} catch {}
|
|
84933
85518
|
}
|
|
84934
85519
|
return null;
|
|
@@ -84942,9 +85527,9 @@ async function tryImportClipboardImageMac() {
|
|
|
84942
85527
|
return null;
|
|
84943
85528
|
const { tempPath, uti } = clipboardResult;
|
|
84944
85529
|
try {
|
|
84945
|
-
const buffer =
|
|
85530
|
+
const buffer = readFileSync6(tempPath);
|
|
84946
85531
|
try {
|
|
84947
|
-
|
|
85532
|
+
unlinkSync8(tempPath);
|
|
84948
85533
|
} catch {}
|
|
84949
85534
|
const mediaType = UTI_TO_MEDIA_TYPE[uti] || "image/png";
|
|
84950
85535
|
const resized = await resizeImageIfNeeded3(buffer, mediaType);
|
|
@@ -84959,9 +85544,9 @@ async function tryImportClipboardImageMac() {
|
|
|
84959
85544
|
height: resized.height
|
|
84960
85545
|
};
|
|
84961
85546
|
} catch (err) {
|
|
84962
|
-
if (
|
|
85547
|
+
if (existsSync19(tempPath)) {
|
|
84963
85548
|
try {
|
|
84964
|
-
|
|
85549
|
+
unlinkSync8(tempPath);
|
|
84965
85550
|
} catch {}
|
|
84966
85551
|
}
|
|
84967
85552
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -85536,13 +86121,13 @@ __export(exports_terminalKeybindingInstaller, {
|
|
|
85536
86121
|
});
|
|
85537
86122
|
import {
|
|
85538
86123
|
copyFileSync,
|
|
85539
|
-
existsSync as
|
|
85540
|
-
mkdirSync as
|
|
85541
|
-
readFileSync as
|
|
86124
|
+
existsSync as existsSync20,
|
|
86125
|
+
mkdirSync as mkdirSync15,
|
|
86126
|
+
readFileSync as readFileSync7,
|
|
85542
86127
|
writeFileSync as writeFileSync9
|
|
85543
86128
|
} from "node:fs";
|
|
85544
|
-
import { homedir as
|
|
85545
|
-
import { dirname as dirname11, join as
|
|
86129
|
+
import { homedir as homedir23, platform as platform4 } from "node:os";
|
|
86130
|
+
import { dirname as dirname11, join as join31 } from "node:path";
|
|
85546
86131
|
function detectTerminalType() {
|
|
85547
86132
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
85548
86133
|
return "cursor";
|
|
@@ -85574,16 +86159,16 @@ function getKeybindingsPath(terminal) {
|
|
|
85574
86159
|
}[terminal];
|
|
85575
86160
|
const os6 = platform4();
|
|
85576
86161
|
if (os6 === "darwin") {
|
|
85577
|
-
return
|
|
86162
|
+
return join31(homedir23(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
85578
86163
|
}
|
|
85579
86164
|
if (os6 === "win32") {
|
|
85580
86165
|
const appData = process.env.APPDATA;
|
|
85581
86166
|
if (!appData)
|
|
85582
86167
|
return null;
|
|
85583
|
-
return
|
|
86168
|
+
return join31(appData, appName, "User", "keybindings.json");
|
|
85584
86169
|
}
|
|
85585
86170
|
if (os6 === "linux") {
|
|
85586
|
-
return
|
|
86171
|
+
return join31(homedir23(), ".config", appName, "User", "keybindings.json");
|
|
85587
86172
|
}
|
|
85588
86173
|
return null;
|
|
85589
86174
|
}
|
|
@@ -85605,10 +86190,10 @@ function parseKeybindings(content) {
|
|
|
85605
86190
|
}
|
|
85606
86191
|
}
|
|
85607
86192
|
function keybindingExists(keybindingsPath) {
|
|
85608
|
-
if (!
|
|
86193
|
+
if (!existsSync20(keybindingsPath))
|
|
85609
86194
|
return false;
|
|
85610
86195
|
try {
|
|
85611
|
-
const content =
|
|
86196
|
+
const content = readFileSync7(keybindingsPath, { encoding: "utf-8" });
|
|
85612
86197
|
const keybindings = parseKeybindings(content);
|
|
85613
86198
|
if (!keybindings)
|
|
85614
86199
|
return false;
|
|
@@ -85618,7 +86203,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
85618
86203
|
}
|
|
85619
86204
|
}
|
|
85620
86205
|
function createBackup(keybindingsPath) {
|
|
85621
|
-
if (!
|
|
86206
|
+
if (!existsSync20(keybindingsPath))
|
|
85622
86207
|
return null;
|
|
85623
86208
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
85624
86209
|
try {
|
|
@@ -85634,14 +86219,14 @@ function installKeybinding(keybindingsPath) {
|
|
|
85634
86219
|
return { success: true, alreadyExists: true };
|
|
85635
86220
|
}
|
|
85636
86221
|
const parentDir = dirname11(keybindingsPath);
|
|
85637
|
-
if (!
|
|
85638
|
-
|
|
86222
|
+
if (!existsSync20(parentDir)) {
|
|
86223
|
+
mkdirSync15(parentDir, { recursive: true });
|
|
85639
86224
|
}
|
|
85640
86225
|
let keybindings = [];
|
|
85641
86226
|
let backupPath = null;
|
|
85642
|
-
if (
|
|
86227
|
+
if (existsSync20(keybindingsPath)) {
|
|
85643
86228
|
backupPath = createBackup(keybindingsPath);
|
|
85644
|
-
const content =
|
|
86229
|
+
const content = readFileSync7(keybindingsPath, { encoding: "utf-8" });
|
|
85645
86230
|
const parsed = parseKeybindings(content);
|
|
85646
86231
|
if (parsed === null) {
|
|
85647
86232
|
return {
|
|
@@ -85669,10 +86254,10 @@ function installKeybinding(keybindingsPath) {
|
|
|
85669
86254
|
}
|
|
85670
86255
|
function removeKeybinding(keybindingsPath) {
|
|
85671
86256
|
try {
|
|
85672
|
-
if (!
|
|
86257
|
+
if (!existsSync20(keybindingsPath)) {
|
|
85673
86258
|
return { success: true };
|
|
85674
86259
|
}
|
|
85675
|
-
const content =
|
|
86260
|
+
const content = readFileSync7(keybindingsPath, { encoding: "utf-8" });
|
|
85676
86261
|
const keybindings = parseKeybindings(content);
|
|
85677
86262
|
if (!keybindings) {
|
|
85678
86263
|
return {
|
|
@@ -85736,20 +86321,20 @@ function getWezTermConfigPath() {
|
|
|
85736
86321
|
}
|
|
85737
86322
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
85738
86323
|
if (xdgConfig) {
|
|
85739
|
-
const xdgPath =
|
|
85740
|
-
if (
|
|
86324
|
+
const xdgPath = join31(xdgConfig, "wezterm", "wezterm.lua");
|
|
86325
|
+
if (existsSync20(xdgPath))
|
|
85741
86326
|
return xdgPath;
|
|
85742
86327
|
}
|
|
85743
|
-
const configPath =
|
|
85744
|
-
if (
|
|
86328
|
+
const configPath = join31(homedir23(), ".config", "wezterm", "wezterm.lua");
|
|
86329
|
+
if (existsSync20(configPath))
|
|
85745
86330
|
return configPath;
|
|
85746
|
-
return
|
|
86331
|
+
return join31(homedir23(), ".wezterm.lua");
|
|
85747
86332
|
}
|
|
85748
86333
|
function wezTermDeleteFixExists(configPath) {
|
|
85749
|
-
if (!
|
|
86334
|
+
if (!existsSync20(configPath))
|
|
85750
86335
|
return false;
|
|
85751
86336
|
try {
|
|
85752
|
-
const content =
|
|
86337
|
+
const content = readFileSync7(configPath, { encoding: "utf-8" });
|
|
85753
86338
|
return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
|
|
85754
86339
|
} catch {
|
|
85755
86340
|
return false;
|
|
@@ -85763,10 +86348,10 @@ function installWezTermDeleteFix() {
|
|
|
85763
86348
|
}
|
|
85764
86349
|
let content = "";
|
|
85765
86350
|
let backupPath = null;
|
|
85766
|
-
if (
|
|
86351
|
+
if (existsSync20(configPath)) {
|
|
85767
86352
|
backupPath = `${configPath}.letta-backup`;
|
|
85768
86353
|
copyFileSync(configPath, backupPath);
|
|
85769
|
-
content =
|
|
86354
|
+
content = readFileSync7(configPath, { encoding: "utf-8" });
|
|
85770
86355
|
}
|
|
85771
86356
|
if (content.includes("return {") && !content.includes("local config")) {
|
|
85772
86357
|
content = content.replace(/return\s*\{/, "local config = {");
|
|
@@ -85793,8 +86378,8 @@ ${WEZTERM_DELETE_FIX}
|
|
|
85793
86378
|
`;
|
|
85794
86379
|
}
|
|
85795
86380
|
const parentDir = dirname11(configPath);
|
|
85796
|
-
if (!
|
|
85797
|
-
|
|
86381
|
+
if (!existsSync20(parentDir)) {
|
|
86382
|
+
mkdirSync15(parentDir, { recursive: true });
|
|
85798
86383
|
}
|
|
85799
86384
|
writeFileSync9(configPath, content, { encoding: "utf-8" });
|
|
85800
86385
|
return {
|
|
@@ -86316,9 +86901,9 @@ __export(exports_custom, {
|
|
|
86316
86901
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
86317
86902
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
86318
86903
|
});
|
|
86319
|
-
import { existsSync as
|
|
86904
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
86320
86905
|
import { readdir as readdir9, readFile as readFile9 } from "node:fs/promises";
|
|
86321
|
-
import { basename as basename5, dirname as dirname12, join as
|
|
86906
|
+
import { basename as basename5, dirname as dirname12, join as join32 } from "node:path";
|
|
86322
86907
|
async function getCustomCommands() {
|
|
86323
86908
|
if (cachedCommands !== null) {
|
|
86324
86909
|
return cachedCommands;
|
|
@@ -86329,7 +86914,7 @@ async function getCustomCommands() {
|
|
|
86329
86914
|
function refreshCustomCommands() {
|
|
86330
86915
|
cachedCommands = null;
|
|
86331
86916
|
}
|
|
86332
|
-
async function discoverCustomCommands(projectPath =
|
|
86917
|
+
async function discoverCustomCommands(projectPath = join32(process.cwd(), COMMANDS_DIR)) {
|
|
86333
86918
|
const commandsById = new Map;
|
|
86334
86919
|
const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
|
|
86335
86920
|
for (const cmd of userCommands) {
|
|
@@ -86350,7 +86935,7 @@ async function discoverCustomCommands(projectPath = join31(process.cwd(), COMMAN
|
|
|
86350
86935
|
return result;
|
|
86351
86936
|
}
|
|
86352
86937
|
async function discoverFromDirectory(dirPath, source) {
|
|
86353
|
-
if (!
|
|
86938
|
+
if (!existsSync21(dirPath)) {
|
|
86354
86939
|
return [];
|
|
86355
86940
|
}
|
|
86356
86941
|
const commands2 = [];
|
|
@@ -86361,7 +86946,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source) {
|
|
|
86361
86946
|
try {
|
|
86362
86947
|
const entries = await readdir9(currentPath, { withFileTypes: true });
|
|
86363
86948
|
for (const entry of entries) {
|
|
86364
|
-
const fullPath =
|
|
86949
|
+
const fullPath = join32(currentPath, entry.name);
|
|
86365
86950
|
if (entry.isDirectory()) {
|
|
86366
86951
|
await findCommandFiles(fullPath, rootPath, commands2, source);
|
|
86367
86952
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -86446,7 +87031,7 @@ async function findCustomCommand(commandName) {
|
|
|
86446
87031
|
}
|
|
86447
87032
|
var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
|
|
86448
87033
|
var init_custom = __esm(() => {
|
|
86449
|
-
GLOBAL_COMMANDS_DIR =
|
|
87034
|
+
GLOBAL_COMMANDS_DIR = join32(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
|
|
86450
87035
|
});
|
|
86451
87036
|
|
|
86452
87037
|
// src/cli/components/HelpDialog.tsx
|
|
@@ -86727,10 +87312,10 @@ var init_HelpDialog = __esm(async () => {
|
|
|
86727
87312
|
});
|
|
86728
87313
|
|
|
86729
87314
|
// src/hooks/writer.ts
|
|
86730
|
-
import { homedir as
|
|
87315
|
+
import { homedir as homedir24 } from "node:os";
|
|
86731
87316
|
import { resolve as resolve26 } from "node:path";
|
|
86732
87317
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
86733
|
-
const home = process.env.HOME ||
|
|
87318
|
+
const home = process.env.HOME || homedir24();
|
|
86734
87319
|
const globalSettingsPath = resolve26(home, ".letta", "settings.json");
|
|
86735
87320
|
const projectSettingsPath = resolve26(workingDirectory, ".letta", "settings.json");
|
|
86736
87321
|
return globalSettingsPath === projectSettingsPath;
|
|
@@ -87782,28 +88367,28 @@ var require_react_jsx_runtime_development = __commonJS((exports) => {
|
|
|
87782
88367
|
return null;
|
|
87783
88368
|
}
|
|
87784
88369
|
var ReactSharedInternals = React14.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
|
87785
|
-
function error(
|
|
88370
|
+
function error(format3) {
|
|
87786
88371
|
{
|
|
87787
88372
|
{
|
|
87788
88373
|
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1;_key2 < _len2; _key2++) {
|
|
87789
88374
|
args[_key2 - 1] = arguments[_key2];
|
|
87790
88375
|
}
|
|
87791
|
-
printWarning("error",
|
|
88376
|
+
printWarning("error", format3, args);
|
|
87792
88377
|
}
|
|
87793
88378
|
}
|
|
87794
88379
|
}
|
|
87795
|
-
function printWarning(level,
|
|
88380
|
+
function printWarning(level, format3, args) {
|
|
87796
88381
|
{
|
|
87797
88382
|
var ReactDebugCurrentFrame2 = ReactSharedInternals.ReactDebugCurrentFrame;
|
|
87798
88383
|
var stack = ReactDebugCurrentFrame2.getStackAddendum();
|
|
87799
88384
|
if (stack !== "") {
|
|
87800
|
-
|
|
88385
|
+
format3 += "%s";
|
|
87801
88386
|
args = args.concat([stack]);
|
|
87802
88387
|
}
|
|
87803
88388
|
var argsWithFormat = args.map(function(item) {
|
|
87804
88389
|
return String(item);
|
|
87805
88390
|
});
|
|
87806
|
-
argsWithFormat.unshift("Warning: " +
|
|
88391
|
+
argsWithFormat.unshift("Warning: " + format3);
|
|
87807
88392
|
Function.prototype.apply.call(console[level], console, argsWithFormat);
|
|
87808
88393
|
}
|
|
87809
88394
|
}
|
|
@@ -89019,7 +89604,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
89019
89604
|
return localPinned.includes(agentId) || globalPinned.includes(agentId);
|
|
89020
89605
|
}, [agentId]);
|
|
89021
89606
|
const isCloudUser = serverUrl?.includes("api.letta.com");
|
|
89022
|
-
const adeConversationUrl = agentId && agentId !== "loading" ?
|
|
89607
|
+
const adeConversationUrl = agentId && agentId !== "loading" ? buildChatUrl(agentId, { conversationId }) : "";
|
|
89023
89608
|
const showBottomBar = agentId && agentId !== "loading";
|
|
89024
89609
|
const reasoningLabel = formatReasoningLabel(currentReasoningEffort);
|
|
89025
89610
|
const modelLine = currentModel ? `${currentModel}${reasoningLabel ? ` (${reasoningLabel})` : ""}` : null;
|
|
@@ -89090,7 +89675,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
89090
89675
|
children: "· "
|
|
89091
89676
|
}, undefined, false, undefined, this),
|
|
89092
89677
|
/* @__PURE__ */ jsx_dev_runtime41.jsxDEV(dist_default4, {
|
|
89093
|
-
url: "
|
|
89678
|
+
url: buildAppUrl("/settings/organization/usage"),
|
|
89094
89679
|
children: /* @__PURE__ */ jsx_dev_runtime41.jsxDEV(Text2, {
|
|
89095
89680
|
children: "View usage ↗"
|
|
89096
89681
|
}, undefined, false, undefined, this)
|
|
@@ -89103,7 +89688,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
89103
89688
|
children: /* @__PURE__ */ jsx_dev_runtime41.jsxDEV(Text2, {
|
|
89104
89689
|
dimColor: true,
|
|
89105
89690
|
wrap: "truncate-end",
|
|
89106
|
-
children: truncateText(`Open in ADE: ${adeConversationUrl} · Usage:
|
|
89691
|
+
children: truncateText(`Open in ADE: ${adeConversationUrl} · Usage: ${buildAppUrl("/settings/organization/usage")}`, rightWidth)
|
|
89107
89692
|
}, undefined, false, undefined, this)
|
|
89108
89693
|
}, undefined, false, undefined, this),
|
|
89109
89694
|
!isCloudUser && /* @__PURE__ */ jsx_dev_runtime41.jsxDEV(Box_default, {
|
|
@@ -89179,8 +89764,8 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
89179
89764
|
});
|
|
89180
89765
|
|
|
89181
89766
|
// src/cli/helpers/fileSearch.ts
|
|
89182
|
-
import { readdirSync as
|
|
89183
|
-
import { join as
|
|
89767
|
+
import { readdirSync as readdirSync9, statSync as statSync5 } from "node:fs";
|
|
89768
|
+
import { join as join33, resolve as resolve27 } from "node:path";
|
|
89184
89769
|
function shouldExcludeEntry(entry) {
|
|
89185
89770
|
if (entry.startsWith(".")) {
|
|
89186
89771
|
return true;
|
|
@@ -89192,13 +89777,13 @@ function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [],
|
|
|
89192
89777
|
return results;
|
|
89193
89778
|
}
|
|
89194
89779
|
try {
|
|
89195
|
-
const entries =
|
|
89780
|
+
const entries = readdirSync9(dir);
|
|
89196
89781
|
for (const entry of entries) {
|
|
89197
89782
|
if (shouldExcludeEntry(entry)) {
|
|
89198
89783
|
continue;
|
|
89199
89784
|
}
|
|
89200
89785
|
try {
|
|
89201
|
-
const fullPath =
|
|
89786
|
+
const fullPath = join33(dir, entry);
|
|
89202
89787
|
const stats = statSync5(fullPath);
|
|
89203
89788
|
const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
|
|
89204
89789
|
const matches = pattern.length === 0 || relativePath.toLowerCase().includes(pattern.toLowerCase());
|
|
@@ -89246,14 +89831,14 @@ async function searchFiles(query, deep = false) {
|
|
|
89246
89831
|
} else {
|
|
89247
89832
|
let entries = [];
|
|
89248
89833
|
try {
|
|
89249
|
-
entries =
|
|
89834
|
+
entries = readdirSync9(searchDir);
|
|
89250
89835
|
} catch {
|
|
89251
89836
|
return [];
|
|
89252
89837
|
}
|
|
89253
89838
|
const matchingEntries = entries.filter((entry) => !shouldExcludeEntry(entry)).filter((entry) => searchPattern.length === 0 || entry.toLowerCase().includes(searchPattern.toLowerCase()));
|
|
89254
89839
|
for (const entry of matchingEntries.slice(0, 50)) {
|
|
89255
89840
|
try {
|
|
89256
|
-
const fullPath =
|
|
89841
|
+
const fullPath = join33(searchDir, entry);
|
|
89257
89842
|
const stats = statSync5(fullPath);
|
|
89258
89843
|
const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
|
|
89259
89844
|
results.push({
|
|
@@ -90899,7 +91484,11 @@ var init_InputRich = __esm(async () => {
|
|
|
90899
91484
|
}, [backgroundAgents.length]);
|
|
90900
91485
|
const bgAgentText = backgroundAgents.length === 0 ? "" : backgroundAgents.map((a) => {
|
|
90901
91486
|
const elapsedS = Math.round((Date.now() - a.startTime) / 1000);
|
|
90902
|
-
|
|
91487
|
+
const agentId = a.agentURL?.match(/\/agents\/([^/]+)/)?.[1];
|
|
91488
|
+
const chatUrl = agentId ? buildChatUrl(agentId) : null;
|
|
91489
|
+
const typeLabel = a.type.toLowerCase();
|
|
91490
|
+
const linkedType = chatUrl ? `\x1B]8;;${chatUrl}\x1B\\${typeLabel}\x1B]8;;\x1B\\` : typeLabel;
|
|
91491
|
+
return `${linkedType} (${elapsedS}s)`;
|
|
90903
91492
|
}).join(" · ");
|
|
90904
91493
|
const bgIndicatorWidth = backgroundAgents.length > 0 ? 2 + stringWidth(bgAgentText) + 3 : 0;
|
|
90905
91494
|
const maxAgentChars = Math.max(10, Math.floor(rightColumnWidth * 0.45));
|
|
@@ -91206,15 +91795,15 @@ var init_InputRich = __esm(async () => {
|
|
|
91206
91795
|
// src/cli/commands/install-github-app.ts
|
|
91207
91796
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
91208
91797
|
import {
|
|
91209
|
-
existsSync as
|
|
91210
|
-
mkdirSync as
|
|
91798
|
+
existsSync as existsSync22,
|
|
91799
|
+
mkdirSync as mkdirSync16,
|
|
91211
91800
|
mkdtempSync,
|
|
91212
|
-
readFileSync as
|
|
91801
|
+
readFileSync as readFileSync8,
|
|
91213
91802
|
rmSync as rmSync3,
|
|
91214
91803
|
writeFileSync as writeFileSync10
|
|
91215
91804
|
} from "node:fs";
|
|
91216
91805
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
91217
|
-
import { dirname as dirname13, join as
|
|
91806
|
+
import { dirname as dirname13, join as join34 } from "node:path";
|
|
91218
91807
|
function runCommand(command, args, cwd2, input) {
|
|
91219
91808
|
try {
|
|
91220
91809
|
return execFileSync3(command, args, {
|
|
@@ -91448,8 +92037,8 @@ async function createLettaAgent(apiKey, name) {
|
|
|
91448
92037
|
return { id: data.id, name: data.name };
|
|
91449
92038
|
}
|
|
91450
92039
|
function cloneRepoToTemp(repo) {
|
|
91451
|
-
const tempDir = mkdtempSync(
|
|
91452
|
-
const repoDir =
|
|
92040
|
+
const tempDir = mkdtempSync(join34(tmpdir4(), "letta-install-github-app-"));
|
|
92041
|
+
const repoDir = join34(tempDir, "repo");
|
|
91453
92042
|
runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
|
|
91454
92043
|
return { tempDir, repoDir };
|
|
91455
92044
|
}
|
|
@@ -91460,14 +92049,14 @@ function runGit2(args, cwd2) {
|
|
|
91460
92049
|
return runCommand("git", args, cwd2);
|
|
91461
92050
|
}
|
|
91462
92051
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
91463
|
-
const absolutePath =
|
|
91464
|
-
if (!
|
|
91465
|
-
|
|
92052
|
+
const absolutePath = join34(repoDir, workflowPath);
|
|
92053
|
+
if (!existsSync22(dirname13(absolutePath))) {
|
|
92054
|
+
mkdirSync16(dirname13(absolutePath), { recursive: true });
|
|
91466
92055
|
}
|
|
91467
92056
|
const next = `${content.trimEnd()}
|
|
91468
92057
|
`;
|
|
91469
|
-
if (
|
|
91470
|
-
const previous =
|
|
92058
|
+
if (existsSync22(absolutePath)) {
|
|
92059
|
+
const previous = readFileSync8(absolutePath, "utf8");
|
|
91471
92060
|
if (previous === next) {
|
|
91472
92061
|
return false;
|
|
91473
92062
|
}
|
|
@@ -91573,7 +92162,7 @@ async function installGithubApp(options) {
|
|
|
91573
92162
|
committed: false,
|
|
91574
92163
|
secretAction: "set",
|
|
91575
92164
|
agentId: resolvedAgentId,
|
|
91576
|
-
agentUrl: resolvedAgentId ?
|
|
92165
|
+
agentUrl: resolvedAgentId ? buildChatUrl(resolvedAgentId) : null
|
|
91577
92166
|
};
|
|
91578
92167
|
}
|
|
91579
92168
|
runGit2(["add", workflowPath], repoDir);
|
|
@@ -91590,7 +92179,7 @@ async function installGithubApp(options) {
|
|
|
91590
92179
|
committed: true,
|
|
91591
92180
|
secretAction: "set",
|
|
91592
92181
|
agentId: resolvedAgentId,
|
|
91593
|
-
agentUrl: resolvedAgentId ?
|
|
92182
|
+
agentUrl: resolvedAgentId ? buildChatUrl(resolvedAgentId) : null
|
|
91594
92183
|
};
|
|
91595
92184
|
} finally {
|
|
91596
92185
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
@@ -93731,21 +94320,21 @@ var init_McpSelector = __esm(async () => {
|
|
|
93731
94320
|
});
|
|
93732
94321
|
|
|
93733
94322
|
// src/agent/memoryScanner.ts
|
|
93734
|
-
import { readdirSync as
|
|
93735
|
-
import { join as
|
|
94323
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
|
|
94324
|
+
import { join as join35, relative as relative9 } from "node:path";
|
|
93736
94325
|
function scanMemoryFilesystem(memoryRoot) {
|
|
93737
94326
|
const nodes = [];
|
|
93738
94327
|
const scanDir = (dir, depth, parentIsLast) => {
|
|
93739
94328
|
let entries;
|
|
93740
94329
|
try {
|
|
93741
|
-
entries =
|
|
94330
|
+
entries = readdirSync10(dir);
|
|
93742
94331
|
} catch {
|
|
93743
94332
|
return;
|
|
93744
94333
|
}
|
|
93745
94334
|
const filtered = entries.filter((name) => !name.startsWith("."));
|
|
93746
94335
|
const sorted = filtered.sort((a, b) => {
|
|
93747
|
-
const aPath =
|
|
93748
|
-
const bPath =
|
|
94336
|
+
const aPath = join35(dir, a);
|
|
94337
|
+
const bPath = join35(dir, b);
|
|
93749
94338
|
let aIsDir = false;
|
|
93750
94339
|
let bIsDir = false;
|
|
93751
94340
|
try {
|
|
@@ -93765,7 +94354,7 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
93765
94354
|
return a.localeCompare(b);
|
|
93766
94355
|
});
|
|
93767
94356
|
sorted.forEach((name, index) => {
|
|
93768
|
-
const fullPath =
|
|
94357
|
+
const fullPath = join35(dir, name);
|
|
93769
94358
|
let isDir = false;
|
|
93770
94359
|
try {
|
|
93771
94360
|
isDir = statSync6(fullPath).isDirectory();
|
|
@@ -93796,7 +94385,7 @@ function getFileNodes(nodes) {
|
|
|
93796
94385
|
}
|
|
93797
94386
|
function readFileContent(fullPath) {
|
|
93798
94387
|
try {
|
|
93799
|
-
return
|
|
94388
|
+
return readFileSync9(fullPath, "utf-8");
|
|
93800
94389
|
} catch {
|
|
93801
94390
|
return "(unable to read file)";
|
|
93802
94391
|
}
|
|
@@ -94758,7 +95347,7 @@ html.dark .warning-badge { background: hsl(42, 30%, 18%); color: hsl(42, 80%, 70
|
|
|
94758
95347
|
} else {
|
|
94759
95348
|
adeBase = 'https://app.letta.com';
|
|
94760
95349
|
}
|
|
94761
|
-
agentIdEl.href = adeBase + '/
|
|
95350
|
+
agentIdEl.href = adeBase + '/chat/' + encodeURIComponent(agentId);
|
|
94762
95351
|
agentIdEl.target = '_blank';
|
|
94763
95352
|
}
|
|
94764
95353
|
document.getElementById('generated-at').textContent = 'Generated ' + new Date(DATA.generatedAt).toLocaleString();
|
|
@@ -95440,9 +96029,9 @@ __export(exports_generate_memory_viewer, {
|
|
|
95440
96029
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
95441
96030
|
});
|
|
95442
96031
|
import { execFile as execFileCb2 } from "node:child_process";
|
|
95443
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
95444
|
-
import { homedir as
|
|
95445
|
-
import { join as
|
|
96032
|
+
import { chmodSync as chmodSync3, existsSync as existsSync23, mkdirSync as mkdirSync17, writeFileSync as writeFileSync11 } from "node:fs";
|
|
96033
|
+
import { homedir as homedir25 } from "node:os";
|
|
96034
|
+
import { join as join36 } from "node:path";
|
|
95446
96035
|
import { promisify as promisify10 } from "node:util";
|
|
95447
96036
|
async function runGitSafe(cwd2, args) {
|
|
95448
96037
|
try {
|
|
@@ -95725,13 +96314,13 @@ async function generateAndOpenMemoryViewer(agentId, options) {
|
|
|
95725
96314
|
}
|
|
95726
96315
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
95727
96316
|
const html = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
95728
|
-
if (!
|
|
95729
|
-
|
|
96317
|
+
if (!existsSync23(VIEWERS_DIR2)) {
|
|
96318
|
+
mkdirSync17(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
95730
96319
|
}
|
|
95731
96320
|
try {
|
|
95732
96321
|
chmodSync3(VIEWERS_DIR2, 448);
|
|
95733
96322
|
} catch {}
|
|
95734
|
-
const filePath =
|
|
96323
|
+
const filePath = join36(VIEWERS_DIR2, `memory-${encodeURIComponent(agentId)}.html`);
|
|
95735
96324
|
writeFileSync11(filePath, html);
|
|
95736
96325
|
chmodSync3(filePath, 384);
|
|
95737
96326
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -95755,12 +96344,12 @@ var init_generate_memory_viewer = __esm(async () => {
|
|
|
95755
96344
|
init_memoryGit()
|
|
95756
96345
|
]);
|
|
95757
96346
|
execFile10 = promisify10(execFileCb2);
|
|
95758
|
-
VIEWERS_DIR2 =
|
|
96347
|
+
VIEWERS_DIR2 = join36(homedir25(), ".letta", "viewers");
|
|
95759
96348
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
95760
96349
|
});
|
|
95761
96350
|
|
|
95762
96351
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
95763
|
-
import { existsSync as
|
|
96352
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
95764
96353
|
function renderTreePrefix(node) {
|
|
95765
96354
|
let prefix = "";
|
|
95766
96355
|
for (let i = 0;i < node.depth; i++) {
|
|
@@ -95778,7 +96367,7 @@ function MemfsTreeViewer({
|
|
|
95778
96367
|
const terminalWidth = useTerminalWidth();
|
|
95779
96368
|
const solidLine = SOLID_LINE18.repeat(Math.max(terminalWidth, 10));
|
|
95780
96369
|
const isTmux = Boolean(process.env.TMUX);
|
|
95781
|
-
const adeUrl =
|
|
96370
|
+
const adeUrl = buildChatUrl(agentId, { view: "memory", conversationId });
|
|
95782
96371
|
const [selectedIndex, setSelectedIndex] = import_react75.useState(0);
|
|
95783
96372
|
const [treeScrollOffset, setTreeScrollOffset] = import_react75.useState(0);
|
|
95784
96373
|
const [viewMode, setViewMode] = import_react75.useState("split");
|
|
@@ -95786,7 +96375,7 @@ function MemfsTreeViewer({
|
|
|
95786
96375
|
const [status, setStatus] = import_react75.useState(null);
|
|
95787
96376
|
const statusTimerRef = import_react75.useRef(null);
|
|
95788
96377
|
const memoryRoot = getMemoryFilesystemRoot(agentId);
|
|
95789
|
-
const memoryExists =
|
|
96378
|
+
const memoryExists = existsSync24(memoryRoot);
|
|
95790
96379
|
const hasGitRepo = import_react75.useMemo(() => isGitRepo(agentId), [agentId]);
|
|
95791
96380
|
function showStatus(msg, durationMs) {
|
|
95792
96381
|
if (statusTimerRef.current)
|
|
@@ -96258,7 +96847,7 @@ function MemoryTabViewer({
|
|
|
96258
96847
|
const terminalWidth = useTerminalWidth();
|
|
96259
96848
|
const solidLine = SOLID_LINE19.repeat(Math.max(terminalWidth, 10));
|
|
96260
96849
|
const isTmux = Boolean(process.env.TMUX);
|
|
96261
|
-
const adeUrl =
|
|
96850
|
+
const adeUrl = buildChatUrl(agentId, { view: "memory", conversationId });
|
|
96262
96851
|
const [selectedTabIndex, setSelectedTabIndex] = import_react76.useState(0);
|
|
96263
96852
|
const [scrollOffset, setScrollOffset] = import_react76.useState(0);
|
|
96264
96853
|
const [freshBlocks, setFreshBlocks] = import_react76.useState(null);
|
|
@@ -97253,12 +97842,22 @@ var init_ModelReasoningSelector = __esm(async () => {
|
|
|
97253
97842
|
});
|
|
97254
97843
|
|
|
97255
97844
|
// src/cli/components/ModelSelector.tsx
|
|
97256
|
-
function getModelCategories(
|
|
97845
|
+
function getModelCategories(_billingTier, isSelfHosted) {
|
|
97257
97846
|
if (isSelfHosted) {
|
|
97258
97847
|
return ["server-recommended", "server-all"];
|
|
97259
97848
|
}
|
|
97260
|
-
|
|
97261
|
-
|
|
97849
|
+
return ["supported", "all", "byok", "byok-all"];
|
|
97850
|
+
}
|
|
97851
|
+
function filterModelsByAvailabilityForSelector(typedModels, availableHandles, allApiHandles) {
|
|
97852
|
+
if (availableHandles === null) {
|
|
97853
|
+
return typedModels.filter((m) => {
|
|
97854
|
+
if (!API_GATED_MODEL_HANDLES.has(m.handle)) {
|
|
97855
|
+
return true;
|
|
97856
|
+
}
|
|
97857
|
+
return allApiHandles.includes(m.handle);
|
|
97858
|
+
});
|
|
97859
|
+
}
|
|
97860
|
+
return typedModels.filter((m) => availableHandles.has(m.handle));
|
|
97262
97861
|
}
|
|
97263
97862
|
function ModelSelector({
|
|
97264
97863
|
currentModelId,
|
|
@@ -97326,11 +97925,10 @@ function ModelSelector({
|
|
|
97326
97925
|
const staticCandidates = typedModels.filter((m) => m.handle === handle);
|
|
97327
97926
|
return staticCandidates.find((m) => m.isDefault) ?? staticCandidates.find((m) => m.isFeatured) ?? staticCandidates.find((m) => m.updateArgs?.reasoning_effort === "medium") ?? staticCandidates.find((m) => m.updateArgs?.reasoning_effort === "high") ?? staticCandidates[0];
|
|
97328
97927
|
}, [typedModels]);
|
|
97329
|
-
const isFreeTier = billingTier?.toLowerCase() === "free";
|
|
97330
97928
|
const supportedModels = import_react79.useMemo(() => {
|
|
97331
97929
|
if (availableHandles === undefined)
|
|
97332
97930
|
return [];
|
|
97333
|
-
let available =
|
|
97931
|
+
let available = filterModelsByAvailabilityForSelector(typedModels, availableHandles, allApiHandles);
|
|
97334
97932
|
if (filterProvider) {
|
|
97335
97933
|
available = available.filter((m) => m.handle.startsWith(`${filterProvider}/`));
|
|
97336
97934
|
}
|
|
@@ -97346,22 +97944,15 @@ function ModelSelector({
|
|
|
97346
97944
|
seen.add(m.handle);
|
|
97347
97945
|
deduped.push(pickPreferredStaticModel(m.handle) ?? m);
|
|
97348
97946
|
}
|
|
97349
|
-
if (isFreeTier) {
|
|
97350
|
-
const freeModels = deduped.filter((m) => m.free);
|
|
97351
|
-
const paidModels = deduped.filter((m) => !m.free);
|
|
97352
|
-
const featured2 = paidModels.filter((m) => m.isFeatured);
|
|
97353
|
-
const nonFeatured2 = paidModels.filter((m) => !m.isFeatured);
|
|
97354
|
-
return [...freeModels, ...featured2, ...nonFeatured2];
|
|
97355
|
-
}
|
|
97356
97947
|
const featured = deduped.filter((m) => m.isFeatured);
|
|
97357
97948
|
const nonFeatured = deduped.filter((m) => !m.isFeatured);
|
|
97358
97949
|
return [...featured, ...nonFeatured];
|
|
97359
97950
|
}, [
|
|
97360
97951
|
typedModels,
|
|
97361
97952
|
availableHandles,
|
|
97953
|
+
allApiHandles,
|
|
97362
97954
|
filterProvider,
|
|
97363
97955
|
searchQuery,
|
|
97364
|
-
isFreeTier,
|
|
97365
97956
|
pickPreferredStaticModel
|
|
97366
97957
|
]);
|
|
97367
97958
|
const isByokHandle = import_react79.useCallback((handle) => BYOK_PROVIDER_PREFIXES.some((prefix) => handle.startsWith(prefix)), []);
|
|
@@ -97816,7 +98407,7 @@ function ModelSelector({
|
|
|
97816
98407
|
]
|
|
97817
98408
|
}, undefined, true, undefined, this);
|
|
97818
98409
|
}
|
|
97819
|
-
var import_react79, jsx_dev_runtime56, SOLID_LINE22 = "─", VISIBLE_ITEMS2 = 8, BYOK_PROVIDER_PREFIXES;
|
|
98410
|
+
var import_react79, jsx_dev_runtime56, SOLID_LINE22 = "─", VISIBLE_ITEMS2 = 8, BYOK_PROVIDER_PREFIXES, API_GATED_MODEL_HANDLES;
|
|
97820
98411
|
var init_ModelSelector = __esm(async () => {
|
|
97821
98412
|
init_useTerminalWidth();
|
|
97822
98413
|
init_colors();
|
|
@@ -97829,6 +98420,7 @@ var init_ModelSelector = __esm(async () => {
|
|
|
97829
98420
|
import_react79 = __toESM(require_react(), 1);
|
|
97830
98421
|
jsx_dev_runtime56 = __toESM(require_jsx_dev_runtime(), 1);
|
|
97831
98422
|
BYOK_PROVIDER_PREFIXES = ["chatgpt-plus-pro/", "lc-"];
|
|
98423
|
+
API_GATED_MODEL_HANDLES = new Set(["letta/auto", "letta/auto-fast"]);
|
|
97832
98424
|
});
|
|
97833
98425
|
|
|
97834
98426
|
// src/cli/components/PinDialog.tsx
|
|
@@ -98238,11 +98830,11 @@ var init_PendingApprovalStub = __esm(async () => {
|
|
|
98238
98830
|
|
|
98239
98831
|
// src/utils/aws-credentials.ts
|
|
98240
98832
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
98241
|
-
import { homedir as
|
|
98242
|
-
import { join as
|
|
98833
|
+
import { homedir as homedir26 } from "node:os";
|
|
98834
|
+
import { join as join37 } from "node:path";
|
|
98243
98835
|
async function parseAwsCredentials() {
|
|
98244
|
-
const credentialsPath =
|
|
98245
|
-
const configPath =
|
|
98836
|
+
const credentialsPath = join37(homedir26(), ".aws", "credentials");
|
|
98837
|
+
const configPath = join37(homedir26(), ".aws", "config");
|
|
98246
98838
|
const profiles = new Map;
|
|
98247
98839
|
try {
|
|
98248
98840
|
const content = await readFile10(credentialsPath, "utf-8");
|
|
@@ -99318,7 +99910,7 @@ function formatUsageStats({
|
|
|
99318
99910
|
const monthlyCredits = Math.round(balance.monthly_credit_balance);
|
|
99319
99911
|
const purchasedCredits = Math.round(balance.purchased_credit_balance);
|
|
99320
99912
|
const toDollars = (credits) => (credits / 1000).toFixed(2);
|
|
99321
|
-
outputLines.push(`Plan: [${balance.billing_tier}]`, "
|
|
99913
|
+
outputLines.push(`Plan: [${balance.billing_tier}]`, buildAppUrl("/settings/organization/usage"), "", `Available credits: ◎${formatNumber(totalCredits)} ($${toDollars(totalCredits)})`, `Monthly credits: ◎${formatNumber(monthlyCredits)} ($${toDollars(monthlyCredits)})`, `Purchased credits: ◎${formatNumber(purchasedCredits)} ($${toDollars(purchasedCredits)})`);
|
|
99322
99914
|
}
|
|
99323
99915
|
return outputLines.join(`
|
|
99324
99916
|
`);
|
|
@@ -99350,8 +99942,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
99350
99942
|
try {
|
|
99351
99943
|
const { discoverSkills: discoverSkills3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
99352
99944
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
99353
|
-
const { join:
|
|
99354
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
99945
|
+
const { join: join38 } = await import("node:path");
|
|
99946
|
+
const skillsDir = getSkillsDirectory2() || join38(process.cwd(), SKILLS_DIR3);
|
|
99355
99947
|
const result = await discoverSkills3(skillsDir, agentId, {
|
|
99356
99948
|
sources: getSkillSources2()
|
|
99357
99949
|
});
|
|
@@ -103295,6 +103887,7 @@ ${recentCommits}
|
|
|
103295
103887
|
}
|
|
103296
103888
|
}
|
|
103297
103889
|
function buildMemoryInitRuntimePrompt(args) {
|
|
103890
|
+
const depth = args.depth ?? "deep";
|
|
103298
103891
|
return `
|
|
103299
103892
|
The user ran /init for the current project.
|
|
103300
103893
|
|
|
@@ -103302,6 +103895,7 @@ Runtime context:
|
|
|
103302
103895
|
- parent_agent_id: ${args.agentId}
|
|
103303
103896
|
- working_directory: ${args.workingDirectory}
|
|
103304
103897
|
- memory_dir: ${args.memoryDir}
|
|
103898
|
+
- research_depth: ${depth}
|
|
103305
103899
|
|
|
103306
103900
|
Git/project context:
|
|
103307
103901
|
${args.gitContext}
|
|
@@ -103309,6 +103903,8 @@ ${args.gitContext}
|
|
|
103309
103903
|
Task:
|
|
103310
103904
|
Initialize or reorganize the parent agent's filesystem-backed memory for this project.
|
|
103311
103905
|
|
|
103906
|
+
${depth === "shallow" ? SHALLOW_INSTRUCTIONS : DEEP_INSTRUCTIONS}
|
|
103907
|
+
|
|
103312
103908
|
Instructions:
|
|
103313
103909
|
- Use the pre-loaded initializing-memory skill as your operating guide
|
|
103314
103910
|
- Inspect existing memory before editing
|
|
@@ -103318,6 +103914,29 @@ Instructions:
|
|
|
103318
103914
|
- If the memory filesystem is unavailable or unsafe to modify, stop and explain why
|
|
103319
103915
|
`.trim();
|
|
103320
103916
|
}
|
|
103917
|
+
async function fireAutoInit(agentId, onComplete) {
|
|
103918
|
+
if (hasActiveInitSubagent())
|
|
103919
|
+
return false;
|
|
103920
|
+
if (!settingsManager.isMemfsEnabled(agentId))
|
|
103921
|
+
return false;
|
|
103922
|
+
const gitContext = gatherGitContext();
|
|
103923
|
+
const initPrompt = buildMemoryInitRuntimePrompt({
|
|
103924
|
+
agentId,
|
|
103925
|
+
workingDirectory: process.cwd(),
|
|
103926
|
+
memoryDir: getMemoryFilesystemRoot(agentId),
|
|
103927
|
+
gitContext,
|
|
103928
|
+
depth: "shallow"
|
|
103929
|
+
});
|
|
103930
|
+
const { spawnBackgroundSubagentTask: spawnBackgroundSubagentTask2 } = await init_Task2().then(() => exports_Task);
|
|
103931
|
+
spawnBackgroundSubagentTask2({
|
|
103932
|
+
subagentType: "init",
|
|
103933
|
+
prompt: initPrompt,
|
|
103934
|
+
description: "Initializing memory",
|
|
103935
|
+
silentCompletion: true,
|
|
103936
|
+
onComplete
|
|
103937
|
+
});
|
|
103938
|
+
return true;
|
|
103939
|
+
}
|
|
103321
103940
|
function buildLegacyInitMessage(args) {
|
|
103322
103941
|
return `${SYSTEM_REMINDER_OPEN}
|
|
103323
103942
|
The user has requested memory initialization via /init.
|
|
@@ -103338,9 +103957,27 @@ Once invoked, follow the instructions from the \`initializing-memory\` skill to
|
|
|
103338
103957
|
${args.gitContext}
|
|
103339
103958
|
${SYSTEM_REMINDER_CLOSE}`;
|
|
103340
103959
|
}
|
|
103341
|
-
var
|
|
103960
|
+
var SHALLOW_INSTRUCTIONS, DEEP_INSTRUCTIONS;
|
|
103961
|
+
var init_initCommand = __esm(async () => {
|
|
103962
|
+
init_memoryFilesystem();
|
|
103342
103963
|
init_constants();
|
|
103343
103964
|
init_subagentState();
|
|
103965
|
+
await init_settings_manager();
|
|
103966
|
+
SHALLOW_INSTRUCTIONS = `
|
|
103967
|
+
Shallow init — fast project basics only (~5 tool calls max):
|
|
103968
|
+
- Only read: CLAUDE.md, AGENTS.md, package.json/pyproject.toml/Cargo.toml, README.md (first 100 lines), top-level directory listing
|
|
103969
|
+
- Detect user identity from the git context provided above (already in the prompt — no extra calls)
|
|
103970
|
+
- Run one git call: git log --format="%an <%ae>" | sort -u | head -5
|
|
103971
|
+
- Write exactly 4 files: project/overview.md, project/commands.md, project/conventions.md, human/identity.md
|
|
103972
|
+
- Skip: deep directory exploration, architecture mapping, config analysis, historical sessions, persona files, reflection/checkpoint phase
|
|
103973
|
+
`.trim();
|
|
103974
|
+
DEEP_INSTRUCTIONS = `
|
|
103975
|
+
Deep init — full exploration (follow the initializing-memory skill fully):
|
|
103976
|
+
- Read all existing memory files first — do NOT recreate what already exists
|
|
103977
|
+
- Then follow the full initializing-memory skill as your operating guide
|
|
103978
|
+
- Expand and deepen existing shallow files, add new ones to reach 15-25 target
|
|
103979
|
+
- If shallow init already ran, build on its output rather than starting over
|
|
103980
|
+
`.trim();
|
|
103344
103981
|
});
|
|
103345
103982
|
|
|
103346
103983
|
// src/cli/helpers/queuedMessageParts.ts
|
|
@@ -103528,9 +104165,11 @@ var init_statusLineSchema = __esm(() => {
|
|
|
103528
104165
|
{ path: "workspace.current_dir" },
|
|
103529
104166
|
{ path: "workspace.project_dir" },
|
|
103530
104167
|
{ path: "session_id" },
|
|
104168
|
+
{ path: "last_run_id" },
|
|
103531
104169
|
{ path: "version" },
|
|
103532
104170
|
{ path: "model.id" },
|
|
103533
104171
|
{ path: "model.display_name" },
|
|
104172
|
+
{ path: "agent.id" },
|
|
103534
104173
|
{ path: "agent.name" },
|
|
103535
104174
|
{ path: "cost.total_duration_ms" },
|
|
103536
104175
|
{ path: "cost.total_api_duration_ms" },
|
|
@@ -103624,6 +104263,7 @@ function buildStatusLinePayload(input) {
|
|
|
103624
104263
|
project_dir: input.projectDirectory
|
|
103625
104264
|
},
|
|
103626
104265
|
...input.sessionId ? { session_id: input.sessionId } : {},
|
|
104266
|
+
last_run_id: input.lastRunId ?? null,
|
|
103627
104267
|
transcript_path: null,
|
|
103628
104268
|
version: getVersion(),
|
|
103629
104269
|
reasoning_effort: input.reasoningEffort ?? null,
|
|
@@ -103654,6 +104294,7 @@ function buildStatusLinePayload(input) {
|
|
|
103654
104294
|
exceeds_200k_tokens: usedContextTokens > 200000,
|
|
103655
104295
|
vim: null,
|
|
103656
104296
|
agent: {
|
|
104297
|
+
id: input.agentId ?? null,
|
|
103657
104298
|
name: input.agentName ?? null
|
|
103658
104299
|
},
|
|
103659
104300
|
permission_mode: input.permissionMode ?? null,
|
|
@@ -104032,7 +104673,9 @@ function toPayloadInput(inputs) {
|
|
|
104032
104673
|
currentDirectory: inputs.currentDirectory,
|
|
104033
104674
|
projectDirectory: inputs.projectDirectory,
|
|
104034
104675
|
sessionId: inputs.sessionId,
|
|
104676
|
+
agentId: inputs.agentId,
|
|
104035
104677
|
agentName: inputs.agentName,
|
|
104678
|
+
lastRunId: inputs.lastRunId,
|
|
104036
104679
|
totalDurationMs: inputs.totalDurationMs,
|
|
104037
104680
|
totalApiDurationMs: inputs.totalApiDurationMs,
|
|
104038
104681
|
totalInputTokens: inputs.totalInputTokens,
|
|
@@ -104238,16 +104881,16 @@ __export(exports_shellAliases, {
|
|
|
104238
104881
|
expandAliases: () => expandAliases,
|
|
104239
104882
|
clearAliasCache: () => clearAliasCache
|
|
104240
104883
|
});
|
|
104241
|
-
import { existsSync as
|
|
104242
|
-
import { homedir as
|
|
104243
|
-
import { join as
|
|
104884
|
+
import { existsSync as existsSync25, readFileSync as readFileSync10 } from "node:fs";
|
|
104885
|
+
import { homedir as homedir27 } from "node:os";
|
|
104886
|
+
import { join as join38 } from "node:path";
|
|
104244
104887
|
function parseAliasesFromFile(filePath) {
|
|
104245
104888
|
const aliases = new Map;
|
|
104246
|
-
if (!
|
|
104889
|
+
if (!existsSync25(filePath)) {
|
|
104247
104890
|
return aliases;
|
|
104248
104891
|
}
|
|
104249
104892
|
try {
|
|
104250
|
-
const content =
|
|
104893
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
104251
104894
|
const lines = content.split(`
|
|
104252
104895
|
`);
|
|
104253
104896
|
let inFunction = false;
|
|
@@ -104309,10 +104952,10 @@ function loadAliases(forceReload = false) {
|
|
|
104309
104952
|
if (aliasCache && !forceReload) {
|
|
104310
104953
|
return aliasCache;
|
|
104311
104954
|
}
|
|
104312
|
-
const home =
|
|
104955
|
+
const home = homedir27();
|
|
104313
104956
|
const allAliases = new Map;
|
|
104314
104957
|
for (const file of ALIAS_FILES) {
|
|
104315
|
-
const filePath =
|
|
104958
|
+
const filePath = join38(home, file);
|
|
104316
104959
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
104317
104960
|
for (const [name, value] of fileAliases) {
|
|
104318
104961
|
allAliases.set(name, value);
|
|
@@ -104802,10 +105445,11 @@ Listener disconnected from Letta Cloud.`, true);
|
|
|
104802
105445
|
return;
|
|
104803
105446
|
}
|
|
104804
105447
|
if (msg.includes("--help") || msg.includes("-h")) {
|
|
104805
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /
|
|
104806
|
-
/
|
|
105448
|
+
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /server [--env-name <name>]
|
|
105449
|
+
/server off
|
|
104807
105450
|
|
|
104808
105451
|
Register this letta-code instance to receive messages from Letta Cloud.
|
|
105452
|
+
Alias: /remote
|
|
104809
105453
|
|
|
104810
105454
|
Options:
|
|
104811
105455
|
--env-name <name> Friendly name for this environment (uses hostname if not provided)
|
|
@@ -104813,9 +105457,9 @@ Options:
|
|
|
104813
105457
|
-h, --help Show this help message
|
|
104814
105458
|
|
|
104815
105459
|
Examples:
|
|
104816
|
-
/
|
|
104817
|
-
/
|
|
104818
|
-
/
|
|
105460
|
+
/server # Start listener with hostname
|
|
105461
|
+
/server --env-name "work-laptop" # Start with custom name
|
|
105462
|
+
/server off # Stop listening
|
|
104819
105463
|
|
|
104820
105464
|
Once connected, this instance will listen for incoming messages from cloud agents.
|
|
104821
105465
|
Messages will be executed locally using your letta-code environment.`, true);
|
|
@@ -104837,11 +105481,10 @@ Messages will be executed locally using your letta-code environment.`, true);
|
|
|
104837
105481
|
const buildConnectionUrl = (connId) => {
|
|
104838
105482
|
if (!ctx.agentId)
|
|
104839
105483
|
return "";
|
|
104840
|
-
|
|
104841
|
-
|
|
104842
|
-
|
|
104843
|
-
}
|
|
104844
|
-
return url;
|
|
105484
|
+
return buildChatUrl(ctx.agentId, {
|
|
105485
|
+
deviceId: connId,
|
|
105486
|
+
conversationId: ctx.conversationId ?? undefined
|
|
105487
|
+
});
|
|
104845
105488
|
};
|
|
104846
105489
|
ctx.setCommandRunning(true);
|
|
104847
105490
|
const cmdId = addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "Connecting to Letta Cloud...", true, "running");
|
|
@@ -105142,9 +105785,9 @@ var exports_App = {};
|
|
|
105142
105785
|
__export(exports_App, {
|
|
105143
105786
|
default: () => App2
|
|
105144
105787
|
});
|
|
105145
|
-
import { existsSync as
|
|
105146
|
-
import { homedir as
|
|
105147
|
-
import { join as
|
|
105788
|
+
import { existsSync as existsSync26, readFileSync as readFileSync11, renameSync as renameSync2, writeFileSync as writeFileSync12 } from "node:fs";
|
|
105789
|
+
import { homedir as homedir28, tmpdir as tmpdir5 } from "node:os";
|
|
105790
|
+
import { join as join39, relative as relative11 } from "node:path";
|
|
105148
105791
|
function deriveReasoningEffort(modelSettings, llmConfig) {
|
|
105149
105792
|
if (modelSettings && "provider_type" in modelSettings) {
|
|
105150
105793
|
if (modelSettings.provider_type === "openai" && "reasoning" in modelSettings && modelSettings.reasoning) {
|
|
@@ -105371,18 +106014,18 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
105371
106014
|
}
|
|
105372
106015
|
function planFileExists() {
|
|
105373
106016
|
const planFilePath = permissionMode.getPlanFilePath();
|
|
105374
|
-
return !!planFilePath &&
|
|
106017
|
+
return !!planFilePath && existsSync26(planFilePath);
|
|
105375
106018
|
}
|
|
105376
106019
|
function _readPlanFile() {
|
|
105377
106020
|
const planFilePath = permissionMode.getPlanFilePath();
|
|
105378
106021
|
if (!planFilePath) {
|
|
105379
106022
|
return "No plan file path set.";
|
|
105380
106023
|
}
|
|
105381
|
-
if (!
|
|
106024
|
+
if (!existsSync26(planFilePath)) {
|
|
105382
106025
|
return `Plan file not found at ${planFilePath}`;
|
|
105383
106026
|
}
|
|
105384
106027
|
try {
|
|
105385
|
-
return
|
|
106028
|
+
return readFileSync11(planFilePath, "utf-8");
|
|
105386
106029
|
} catch {
|
|
105387
106030
|
return `Failed to read plan file at ${planFilePath}`;
|
|
105388
106031
|
}
|
|
@@ -105519,8 +106162,11 @@ function App2({
|
|
|
105519
106162
|
import_react99.useEffect(() => {
|
|
105520
106163
|
conversationIdRef.current = conversationId;
|
|
105521
106164
|
}, [conversationId]);
|
|
106165
|
+
const lastRunIdRef = import_react99.useRef(null);
|
|
105522
106166
|
const resumeKey = useSuspend();
|
|
105523
106167
|
const pendingConversationSwitchRef = import_react99.useRef(null);
|
|
106168
|
+
const autoInitPendingAgentIdsRef = import_react99.useRef(new Set);
|
|
106169
|
+
const startupAutoInitConsumedRef = import_react99.useRef(false);
|
|
105524
106170
|
const prevInitialAgentIdRef = import_react99.useRef(initialAgentId);
|
|
105525
106171
|
const prevInitialAgentStateRef = import_react99.useRef(initialAgentState);
|
|
105526
106172
|
const prevInitialConversationIdRef = import_react99.useRef(initialConversationId);
|
|
@@ -105857,6 +106503,15 @@ function App2({
|
|
|
105857
106503
|
}, []);
|
|
105858
106504
|
const [showExitStats, setShowExitStats] = import_react99.useState(false);
|
|
105859
106505
|
const sharedReminderStateRef = import_react99.useRef(createSharedReminderState());
|
|
106506
|
+
const initProgressByAgentRef = import_react99.useRef(new Map);
|
|
106507
|
+
const updateInitProgress = (forAgentId, update) => {
|
|
106508
|
+
const progress2 = initProgressByAgentRef.current.get(forAgentId) ?? {
|
|
106509
|
+
shallowCompleted: false,
|
|
106510
|
+
deepFired: false
|
|
106511
|
+
};
|
|
106512
|
+
Object.assign(progress2, update);
|
|
106513
|
+
initProgressByAgentRef.current.set(forAgentId, progress2);
|
|
106514
|
+
};
|
|
105860
106515
|
const hasSetConversationSummaryRef = import_react99.useRef(resumedExistingConversation);
|
|
105861
106516
|
const firstUserQueryRef = import_react99.useRef(null);
|
|
105862
106517
|
const resetBootstrapReminderState = import_react99.useCallback(() => {
|
|
@@ -106342,7 +106997,9 @@ function App2({
|
|
|
106342
106997
|
currentDirectory: process.cwd(),
|
|
106343
106998
|
projectDirectory,
|
|
106344
106999
|
sessionId: conversationId,
|
|
107000
|
+
agentId,
|
|
106345
107001
|
agentName,
|
|
107002
|
+
lastRunId: lastRunIdRef.current,
|
|
106346
107003
|
totalDurationMs: sessionStatsSnapshot.totalWallMs,
|
|
106347
107004
|
totalApiDurationMs: sessionStatsSnapshot.totalApiMs,
|
|
106348
107005
|
totalInputTokens: sessionStatsSnapshot.usage.promptTokens,
|
|
@@ -106494,7 +107151,8 @@ function App2({
|
|
|
106494
107151
|
enqueueCommandIoReminder(sharedReminderStateRef.current, {
|
|
106495
107152
|
input,
|
|
106496
107153
|
output: event.output,
|
|
106497
|
-
success: event.success
|
|
107154
|
+
success: event.success,
|
|
107155
|
+
agentHint: event.agentHint
|
|
106498
107156
|
});
|
|
106499
107157
|
}, []);
|
|
106500
107158
|
const maybeRecordToolsetChangeReminder = import_react99.useCallback((params) => {
|
|
@@ -106637,10 +107295,10 @@ function App2({
|
|
|
106637
107295
|
if (!planFilePath)
|
|
106638
107296
|
return;
|
|
106639
107297
|
try {
|
|
106640
|
-
const { readFileSync:
|
|
106641
|
-
if (!
|
|
107298
|
+
const { readFileSync: readFileSync12, existsSync: existsSync27 } = __require("node:fs");
|
|
107299
|
+
if (!existsSync27(planFilePath))
|
|
106642
107300
|
return;
|
|
106643
|
-
const planContent =
|
|
107301
|
+
const planContent = readFileSync12(planFilePath, "utf-8");
|
|
106644
107302
|
const previewItem = {
|
|
106645
107303
|
kind: "approval_preview",
|
|
106646
107304
|
id: `approval-preview-${toolCallId}`,
|
|
@@ -106853,6 +107511,7 @@ function App2({
|
|
|
106853
107511
|
}
|
|
106854
107512
|
try {
|
|
106855
107513
|
const client = await getClient2();
|
|
107514
|
+
debugLog("conversations", `retrieve(${conversationId}) [syncConversationModel]`);
|
|
106856
107515
|
const conversation = await client.conversations.retrieve(conversationId);
|
|
106857
107516
|
if (cancelled)
|
|
106858
107517
|
return;
|
|
@@ -106886,7 +107545,7 @@ function App2({
|
|
|
106886
107545
|
if (cancelled)
|
|
106887
107546
|
return;
|
|
106888
107547
|
debugLog("conversation-model", "Failed to sync conversation model override: %O", error);
|
|
106889
|
-
|
|
107548
|
+
debugLog("conversation-model", "Keeping current model state after sync error (override in DB is authoritative)");
|
|
106890
107549
|
}
|
|
106891
107550
|
};
|
|
106892
107551
|
syncConversationModel();
|
|
@@ -107018,9 +107677,9 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
|
|
|
107018
107677
|
(async () => {
|
|
107019
107678
|
try {
|
|
107020
107679
|
const { watch } = await import("node:fs");
|
|
107021
|
-
const { existsSync:
|
|
107680
|
+
const { existsSync: existsSync27 } = await import("node:fs");
|
|
107022
107681
|
const memRoot = getMemoryFilesystemRoot(agentId);
|
|
107023
|
-
if (!
|
|
107682
|
+
if (!existsSync27(memRoot))
|
|
107024
107683
|
return;
|
|
107025
107684
|
watcher = watch(memRoot, { recursive: true }, () => {});
|
|
107026
107685
|
memfsWatcherRef.current = watcher;
|
|
@@ -107264,7 +107923,7 @@ ${newState.originalPrompt}`
|
|
|
107264
107923
|
}
|
|
107265
107924
|
if (preStreamAction === "retry_conversation_busy") {
|
|
107266
107925
|
conversationBusyRetriesRef.current += 1;
|
|
107267
|
-
const retryDelayMs =
|
|
107926
|
+
const retryDelayMs = CONVERSATION_BUSY_RETRY_BASE_DELAY_MS2 * 2 ** (conversationBusyRetriesRef.current - 1);
|
|
107268
107927
|
telemetry.trackError("retry_conversation_busy", formatTelemetryErrorMessage(errorDetail || "Conversation is busy"), "pre_stream_retry", {
|
|
107269
107928
|
httpStatus: preStreamError instanceof APIError2 ? preStreamError.status : undefined,
|
|
107270
107929
|
modelId: currentModelId || undefined
|
|
@@ -107441,6 +108100,8 @@ ${newState.originalPrompt}`
|
|
|
107441
108100
|
fallbackError
|
|
107442
108101
|
} = await drainStreamWithResume(stream2, buffersRef.current, refreshDerivedThrottled, signal, handleFirstMessage, undefined, contextTrackerRef.current);
|
|
107443
108102
|
currentRunId = lastRunId ?? undefined;
|
|
108103
|
+
if (lastRunId)
|
|
108104
|
+
lastRunIdRef.current = lastRunId;
|
|
107444
108105
|
sessionStatsRef.current.endTurn(apiDurationMs);
|
|
107445
108106
|
const usageDelta = sessionStatsRef.current.updateUsageFromBuffers(buffersRef.current);
|
|
107446
108107
|
const tokenDelta = Math.max(0, buffersRef.current.tokenCount - runTokenStart);
|
|
@@ -108293,8 +108954,12 @@ ${feedback}
|
|
|
108293
108954
|
toolResultsInFlightRef.current = false;
|
|
108294
108955
|
refreshDerived();
|
|
108295
108956
|
getClient2().then((client) => {
|
|
108296
|
-
|
|
108297
|
-
|
|
108957
|
+
if (conversationIdRef.current === "default") {
|
|
108958
|
+
return client.conversations.cancel("default", {
|
|
108959
|
+
agent_id: agentIdRef.current
|
|
108960
|
+
});
|
|
108961
|
+
}
|
|
108962
|
+
return client.conversations.cancel(conversationIdRef.current);
|
|
108298
108963
|
}).catch(() => {});
|
|
108299
108964
|
setTimeout(() => {
|
|
108300
108965
|
userCancelledRef.current = false;
|
|
@@ -108362,8 +109027,12 @@ ${feedback}
|
|
|
108362
109027
|
setAutoHandledResults([]);
|
|
108363
109028
|
setAutoDeniedApprovals([]);
|
|
108364
109029
|
getClient2().then((client) => {
|
|
108365
|
-
|
|
108366
|
-
|
|
109030
|
+
if (conversationIdRef.current === "default") {
|
|
109031
|
+
return client.conversations.cancel("default", {
|
|
109032
|
+
agent_id: agentIdRef.current
|
|
109033
|
+
});
|
|
109034
|
+
}
|
|
109035
|
+
return client.conversations.cancel(conversationIdRef.current);
|
|
108367
109036
|
}).catch(() => {});
|
|
108368
109037
|
setTimeout(() => {
|
|
108369
109038
|
userCancelledRef.current = false;
|
|
@@ -108374,8 +109043,13 @@ ${feedback}
|
|
|
108374
109043
|
setInterruptRequested(true);
|
|
108375
109044
|
try {
|
|
108376
109045
|
const client = await getClient2();
|
|
108377
|
-
|
|
108378
|
-
|
|
109046
|
+
if (conversationIdRef.current === "default") {
|
|
109047
|
+
await client.conversations.cancel("default", {
|
|
109048
|
+
agent_id: agentIdRef.current
|
|
109049
|
+
});
|
|
109050
|
+
} else {
|
|
109051
|
+
await client.conversations.cancel(conversationIdRef.current);
|
|
109052
|
+
}
|
|
108379
109053
|
if (abortControllerRef.current) {
|
|
108380
109054
|
abortControllerRef.current.abort();
|
|
108381
109055
|
abortControllerRef.current = null;
|
|
@@ -108543,6 +109217,9 @@ ${feedback}
|
|
|
108543
109217
|
const { agent } = await createAgent(name);
|
|
108544
109218
|
const { enableMemfsIfCloud: enableMemfsIfCloud2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
108545
109219
|
await enableMemfsIfCloud2(agent.id);
|
|
109220
|
+
if (settingsManager.isMemfsEnabled(agent.id)) {
|
|
109221
|
+
autoInitPendingAgentIdsRef.current.add(agent.id);
|
|
109222
|
+
}
|
|
108546
109223
|
await updateProjectSettings({ lastAgent: agent.id });
|
|
108547
109224
|
const targetConversationId = "default";
|
|
108548
109225
|
settingsManager.setLocalLastSession({ agentId: agent.id, conversationId: targetConversationId }, process.cwd());
|
|
@@ -108550,11 +109227,12 @@ ${feedback}
|
|
|
108550
109227
|
agentId: agent.id,
|
|
108551
109228
|
conversationId: targetConversationId
|
|
108552
109229
|
});
|
|
108553
|
-
const agentUrl =
|
|
109230
|
+
const agentUrl = buildChatUrl(agent.id);
|
|
109231
|
+
const memfsTip = settingsManager.isMemfsEnabled(agent.id) ? "Memory will be auto-initialized on your first message." : "Tip: use /init to initialize your agent's memory system!";
|
|
108554
109232
|
const successOutput = [
|
|
108555
109233
|
`Created **${agent.name || agent.id}** (use /pin to save)`,
|
|
108556
109234
|
`⎿ ${agentUrl}`,
|
|
108557
|
-
`⎿
|
|
109235
|
+
`⎿ ${memfsTip}`
|
|
108558
109236
|
].join(`
|
|
108559
109237
|
`);
|
|
108560
109238
|
cmd.finish(successOutput, true);
|
|
@@ -108969,7 +109647,9 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
108969
109647
|
return { submitted: true };
|
|
108970
109648
|
}
|
|
108971
109649
|
if (trimmed === "/ade") {
|
|
108972
|
-
const adeUrl =
|
|
109650
|
+
const adeUrl = buildChatUrl(agentId, {
|
|
109651
|
+
conversationId: conversationIdRef.current
|
|
109652
|
+
});
|
|
108973
109653
|
const cmd = commandRunner.start("/ade", "Opening ADE...");
|
|
108974
109654
|
Promise.resolve().then(() => (init_open(), exports_open)).then(({ default: open2 }) => open2(adeUrl, { wait: false })).catch(() => {});
|
|
108975
109655
|
cmd.finish(`Opening ADE...
|
|
@@ -109115,7 +109795,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
109115
109795
|
}
|
|
109116
109796
|
return { submitted: true };
|
|
109117
109797
|
}
|
|
109118
|
-
if (trimmed === "/remote" || trimmed.startsWith("/remote ")) {
|
|
109798
|
+
if (trimmed === "/server" || trimmed.startsWith("/server ") || trimmed === "/remote" || trimmed.startsWith("/remote ")) {
|
|
109119
109799
|
const parts = Array.from(trimmed.matchAll(/"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g), (match3) => match3[1] ?? match3[2] ?? match3[3]);
|
|
109120
109800
|
let name;
|
|
109121
109801
|
let _listenAgentId;
|
|
@@ -109241,7 +109921,9 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
109241
109921
|
currentDirectory: wd,
|
|
109242
109922
|
projectDirectory,
|
|
109243
109923
|
sessionId: conversationIdRef.current,
|
|
109924
|
+
agentId,
|
|
109244
109925
|
agentName,
|
|
109926
|
+
lastRunId: lastRunIdRef.current,
|
|
109245
109927
|
totalDurationMs: stats.totalWallMs,
|
|
109246
109928
|
totalApiDurationMs: stats.totalApiMs,
|
|
109247
109929
|
totalInputTokens: stats.usage.promptTokens,
|
|
@@ -109611,8 +110293,12 @@ Type your task to begin the loop.`, true);
|
|
|
109611
110293
|
mode: modeArg
|
|
109612
110294
|
}
|
|
109613
110295
|
} : undefined;
|
|
109614
|
-
const
|
|
109615
|
-
const
|
|
110296
|
+
const compactConversationId = conversationIdRef.current;
|
|
110297
|
+
const compactBody = compactConversationId === "default" ? {
|
|
110298
|
+
agent_id: agentId,
|
|
110299
|
+
...compactParams ?? {}
|
|
110300
|
+
} : compactParams;
|
|
110301
|
+
const result2 = await client.conversations.messages.compact(compactConversationId, compactBody);
|
|
109616
110302
|
const outputLines = [
|
|
109617
110303
|
`Compaction completed${modeDisplay}. Message buffer length reduced from ${result2.num_messages_before} to ${result2.num_messages_after}.`,
|
|
109618
110304
|
"",
|
|
@@ -109708,6 +110394,7 @@ Type your task to begin the loop.`, true);
|
|
|
109708
110394
|
const client = await getClient2();
|
|
109709
110395
|
await client.agents.update(agentId, { name: newValue });
|
|
109710
110396
|
updateAgentName(newValue);
|
|
110397
|
+
cmd.agentHint = `Your name is now "${newValue}" — acknowledge this and save your new name to memory.`;
|
|
109711
110398
|
cmd.finish(`Agent renamed to "${newValue}"`, true);
|
|
109712
110399
|
} catch (error) {
|
|
109713
110400
|
const errorDetails = formatErrorDetails2(error, agentId);
|
|
@@ -110079,7 +110766,7 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
110079
110766
|
try {
|
|
110080
110767
|
const client = await getClient2();
|
|
110081
110768
|
const exportParams = {};
|
|
110082
|
-
if (conversationId !== "default") {
|
|
110769
|
+
if (conversationId !== "default" && conversationId !== agentId) {
|
|
110083
110770
|
exportParams.conversation_id = conversationId;
|
|
110084
110771
|
}
|
|
110085
110772
|
const { packageSkills: packageSkills2 } = await Promise.resolve().then(() => (init_export(), exports_export));
|
|
@@ -110201,11 +110888,11 @@ Path: ${result2.memoryDir}`, true, msg);
|
|
|
110201
110888
|
setCommandRunning(true);
|
|
110202
110889
|
try {
|
|
110203
110890
|
const memoryDir = getMemoryFilesystemRoot(agentId);
|
|
110204
|
-
if (!
|
|
110891
|
+
if (!existsSync26(memoryDir)) {
|
|
110205
110892
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
110206
110893
|
return { submitted: true };
|
|
110207
110894
|
}
|
|
110208
|
-
const backupDir =
|
|
110895
|
+
const backupDir = join39(tmpdir5(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
110209
110896
|
renameSync2(memoryDir, backupDir);
|
|
110210
110897
|
ensureMemoryFilesystemDirs(agentId);
|
|
110211
110898
|
updateMemorySyncCommand(cmdId, `Memory filesystem reset.
|
|
@@ -110233,8 +110920,8 @@ Run \`/memfs sync\` to repopulate from API.`, true, msg);
|
|
|
110233
110920
|
await removeGitMemoryTag2(agentId);
|
|
110234
110921
|
let backupInfo = "";
|
|
110235
110922
|
const memoryDir = getMemoryFilesystemRoot(agentId);
|
|
110236
|
-
if (
|
|
110237
|
-
const backupDir =
|
|
110923
|
+
if (existsSync26(memoryDir)) {
|
|
110924
|
+
const backupDir = join39(tmpdir5(), `letta-memfs-disable-${agentId}-${Date.now()}`);
|
|
110238
110925
|
renameSync2(memoryDir, backupDir);
|
|
110239
110926
|
backupInfo = `
|
|
110240
110927
|
Local files backed up to ${backupDir}`;
|
|
@@ -110358,7 +111045,8 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
110358
111045
|
agentId,
|
|
110359
111046
|
workingDirectory: process.cwd(),
|
|
110360
111047
|
memoryDir: getMemoryFilesystemRoot(agentId),
|
|
110361
|
-
gitContext
|
|
111048
|
+
gitContext,
|
|
111049
|
+
depth: "deep"
|
|
110362
111050
|
});
|
|
110363
111051
|
const { spawnBackgroundSubagentTask: spawnBackgroundSubagentTask2 } = await init_Task2().then(() => exports_Task);
|
|
110364
111052
|
spawnBackgroundSubagentTask2({
|
|
@@ -110367,10 +111055,14 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
110367
111055
|
description: "Initializing memory",
|
|
110368
111056
|
silentCompletion: true,
|
|
110369
111057
|
onComplete: ({ success, error }) => {
|
|
110370
|
-
|
|
111058
|
+
if (success) {
|
|
111059
|
+
updateInitProgress(agentId, { deepFired: true });
|
|
111060
|
+
}
|
|
111061
|
+
const msg2 = success ? "Built a memory palace of you. Visit it with /palace." : `Memory initialization failed: ${error || "Unknown error"}`;
|
|
110371
111062
|
appendTaskNotificationEvents([msg2]);
|
|
110372
111063
|
}
|
|
110373
111064
|
});
|
|
111065
|
+
autoInitPendingAgentIdsRef.current.delete(agentId);
|
|
110374
111066
|
cmd.finish("Learning about you and your codebase in the background. You'll be notified when ready.", true);
|
|
110375
111067
|
const reminders = sharedReminderStateRef.current.pendingCommandIoReminders;
|
|
110376
111068
|
const idx = reminders.findIndex((r) => r.input === "/init");
|
|
@@ -110382,6 +111074,7 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
110382
111074
|
cmd.fail(`Failed to start memory initialization: ${errorDetails}`);
|
|
110383
111075
|
}
|
|
110384
111076
|
} else {
|
|
111077
|
+
autoInitPendingAgentIdsRef.current.delete(agentId);
|
|
110385
111078
|
setCommandRunning(true);
|
|
110386
111079
|
try {
|
|
110387
111080
|
cmd.finish("Assimilating project context and defragmenting memories...", true);
|
|
@@ -110461,6 +111154,21 @@ ${SYSTEM_REMINDER_CLOSE}`)
|
|
|
110461
111154
|
return { submitted: true };
|
|
110462
111155
|
}
|
|
110463
111156
|
}
|
|
111157
|
+
if (autoInitPendingAgentIdsRef.current.has(agentId) && !isSystemOnly) {
|
|
111158
|
+
try {
|
|
111159
|
+
const fired = await fireAutoInit(agentId, ({ success, error }) => {
|
|
111160
|
+
if (success) {
|
|
111161
|
+
updateInitProgress(agentId, { shallowCompleted: true });
|
|
111162
|
+
}
|
|
111163
|
+
const msg2 = success ? "Built a memory palace of you. Visit it with /palace." : `Memory initialization failed: ${error || "Unknown error"}`;
|
|
111164
|
+
appendTaskNotificationEvents([msg2]);
|
|
111165
|
+
});
|
|
111166
|
+
if (fired) {
|
|
111167
|
+
autoInitPendingAgentIdsRef.current.delete(agentId);
|
|
111168
|
+
sharedReminderStateRef.current.pendingAutoInitReminder = true;
|
|
111169
|
+
}
|
|
111170
|
+
} catch {}
|
|
111171
|
+
}
|
|
110464
111172
|
const contentParts = overrideContentParts ?? buildMessageContentFromDisplay(msg);
|
|
110465
111173
|
let ralphModeReminder = "";
|
|
110466
111174
|
if (ralphMode.getState().isActive) {
|
|
@@ -110558,7 +111266,45 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
110558
111266
|
return false;
|
|
110559
111267
|
}
|
|
110560
111268
|
};
|
|
111269
|
+
const maybeLaunchDeepInitSubagent = async () => {
|
|
111270
|
+
if (!memfsEnabledForAgent)
|
|
111271
|
+
return false;
|
|
111272
|
+
if (hasActiveInitSubagent())
|
|
111273
|
+
return false;
|
|
111274
|
+
try {
|
|
111275
|
+
const gitContext = gatherGitContext();
|
|
111276
|
+
const initPrompt = buildMemoryInitRuntimePrompt({
|
|
111277
|
+
agentId,
|
|
111278
|
+
workingDirectory: process.cwd(),
|
|
111279
|
+
memoryDir: getMemoryFilesystemRoot(agentId),
|
|
111280
|
+
gitContext,
|
|
111281
|
+
depth: "deep"
|
|
111282
|
+
});
|
|
111283
|
+
const { spawnBackgroundSubagentTask: spawnBackgroundSubagentTask2 } = await init_Task2().then(() => exports_Task);
|
|
111284
|
+
spawnBackgroundSubagentTask2({
|
|
111285
|
+
subagentType: "init",
|
|
111286
|
+
prompt: initPrompt,
|
|
111287
|
+
description: "Deep memory initialization",
|
|
111288
|
+
silentCompletion: true,
|
|
111289
|
+
onComplete: ({ success, error }) => {
|
|
111290
|
+
if (success) {
|
|
111291
|
+
updateInitProgress(agentId, { deepFired: true });
|
|
111292
|
+
}
|
|
111293
|
+
const msg2 = success ? "Built a memory palace of you. Visit it with /palace." : `Deep memory initialization failed: ${error || "Unknown error"}`;
|
|
111294
|
+
appendTaskNotificationEvents([msg2]);
|
|
111295
|
+
}
|
|
111296
|
+
});
|
|
111297
|
+
debugLog("memory", "Auto-launched deep init subagent");
|
|
111298
|
+
return true;
|
|
111299
|
+
} catch (error) {
|
|
111300
|
+
debugWarn("memory", `Failed to auto-launch deep init subagent: ${error instanceof Error ? error.message : String(error)}`);
|
|
111301
|
+
return false;
|
|
111302
|
+
}
|
|
111303
|
+
};
|
|
110561
111304
|
syncReminderStateFromContextTracker(sharedReminderStateRef.current, contextTrackerRef.current);
|
|
111305
|
+
const initProgress = initProgressByAgentRef.current.get(agentId);
|
|
111306
|
+
sharedReminderStateRef.current.shallowInitCompleted = initProgress?.shallowCompleted ?? false;
|
|
111307
|
+
sharedReminderStateRef.current.deepInitFired = initProgress?.deepFired ?? false;
|
|
110562
111308
|
const { getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
110563
111309
|
const { parts: sharedReminderParts } = await buildSharedReminderParts({
|
|
110564
111310
|
mode: "interactive",
|
|
@@ -110573,7 +111319,8 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
110573
111319
|
reflectionSettings,
|
|
110574
111320
|
skillSources: getSkillSources2(),
|
|
110575
111321
|
resolvePlanModeReminder: getPlanModeReminder,
|
|
110576
|
-
maybeLaunchReflectionSubagent
|
|
111322
|
+
maybeLaunchReflectionSubagent,
|
|
111323
|
+
maybeLaunchDeepInitSubagent
|
|
110577
111324
|
});
|
|
110578
111325
|
for (const part of sharedReminderParts) {
|
|
110579
111326
|
reminderParts.push(part);
|
|
@@ -112307,7 +113054,7 @@ ${guidance}`);
|
|
|
112307
113054
|
}
|
|
112308
113055
|
if (!planFileExists()) {
|
|
112309
113056
|
const planFilePath = permissionMode.getPlanFilePath();
|
|
112310
|
-
const plansDir =
|
|
113057
|
+
const plansDir = join39(homedir28(), ".letta", "plans");
|
|
112311
113058
|
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
112312
113059
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
112313
113060
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
@@ -112512,6 +113259,14 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
112512
113259
|
return estimatedLiveHeight < resumeThreshold;
|
|
112513
113260
|
});
|
|
112514
113261
|
}, [estimatedLiveHeight, terminalRows]);
|
|
113262
|
+
import_react99.useEffect(() => {
|
|
113263
|
+
if (loadingState === "ready" && agentProvenance?.isNew && agentId && !startupAutoInitConsumedRef.current) {
|
|
113264
|
+
startupAutoInitConsumedRef.current = true;
|
|
113265
|
+
if (settingsManager.isMemfsEnabled(agentId)) {
|
|
113266
|
+
autoInitPendingAgentIdsRef.current.add(agentId);
|
|
113267
|
+
}
|
|
113268
|
+
}
|
|
113269
|
+
}, [loadingState, agentProvenance, agentId]);
|
|
112515
113270
|
import_react99.useEffect(() => {
|
|
112516
113271
|
if (loadingState === "ready" && !welcomeCommittedRef.current && messageHistory.length === 0) {
|
|
112517
113272
|
if (!continueSession && !agentProvenance) {
|
|
@@ -112822,7 +113577,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
112822
113577
|
color: colors.link.url,
|
|
112823
113578
|
children: agentName && (settingsManager.getLocalPinnedAgents().includes(agentId) || settingsManager.getGlobalPinnedAgents().includes(agentId)) ? `letta -n "${agentName}"` : `letta --agent ${agentId}`
|
|
112824
113579
|
}, undefined, false, undefined, this),
|
|
112825
|
-
conversationId !== "default" && /* @__PURE__ */ jsx_dev_runtime76.jsxDEV(jsx_dev_runtime76.Fragment, {
|
|
113580
|
+
conversationId !== "default" && conversationId !== agentId && /* @__PURE__ */ jsx_dev_runtime76.jsxDEV(jsx_dev_runtime76.Fragment, {
|
|
112826
113581
|
children: [
|
|
112827
113582
|
/* @__PURE__ */ jsx_dev_runtime76.jsxDEV(Box_default, {
|
|
112828
113583
|
height: 1
|
|
@@ -113446,6 +114201,9 @@ Open /mcp to attach or detach tools for this server.`, true);
|
|
|
113446
114201
|
} else {
|
|
113447
114202
|
settingsManager.pinGlobal(agentId);
|
|
113448
114203
|
}
|
|
114204
|
+
if (newName && newName !== agentName) {
|
|
114205
|
+
cmd.agentHint = `Your name is now "${newName}" — acknowledge this and save your new name to memory.`;
|
|
114206
|
+
}
|
|
113449
114207
|
cmd.finish(`Pinned "${newName || agentName || agentId.slice(0, 12)}" ${scopeText}.`, true);
|
|
113450
114208
|
} catch (error) {
|
|
113451
114209
|
cmd.fail(`Failed to pin: ${error}`);
|
|
@@ -113463,7 +114221,7 @@ Open /mcp to attach or detach tools for this server.`, true);
|
|
|
113463
114221
|
]
|
|
113464
114222
|
}, resumeKey, true, undefined, this);
|
|
113465
114223
|
}
|
|
113466
|
-
var import_react99, jsx_dev_runtime76, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, RESIZE_SETTLE_MS = 250, MIN_CLEAR_INTERVAL_MS = 750, STABLE_WIDTH_SETTLE_MS = 180, TOOL_CALL_COMMIT_DEFER_MS = 50, ANIMATION_RESUME_HYSTERESIS_ROWS = 2, EAGER_CANCEL = true, LLM_API_ERROR_MAX_RETRIES3 = 3, EMPTY_RESPONSE_MAX_RETRIES2 = 2, CONVERSATION_BUSY_MAX_RETRIES2 = 3,
|
|
114224
|
+
var import_react99, jsx_dev_runtime76, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, RESIZE_SETTLE_MS = 250, MIN_CLEAR_INTERVAL_MS = 750, STABLE_WIDTH_SETTLE_MS = 180, TOOL_CALL_COMMIT_DEFER_MS = 50, ANIMATION_RESUME_HYSTERESIS_ROWS = 2, EAGER_CANCEL = true, LLM_API_ERROR_MAX_RETRIES3 = 3, EMPTY_RESPONSE_MAX_RETRIES2 = 2, CONVERSATION_BUSY_MAX_RETRIES2 = 3, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS2 = 1e4, INTERRUPT_MESSAGE = "Interrupted – tell the agent what to do differently. Something went wrong? Use /feedback to report issues.", ERROR_FEEDBACK_HINT = "Something went wrong? Use /feedback to report issues.", OPUS_BEDROCK_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to Bedrock Opus 4.5", PROVIDER_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to another provider", INTERACTIVE_SLASH_COMMANDS, NON_STATE_COMMANDS, APPROVAL_OPTIONS_HEIGHT = 8, APPROVAL_PREVIEW_BUFFER = 4, MIN_WRAP_WIDTH = 10, TEXT_WRAP_GUTTER = 6, DIFF_WRAP_GUTTER = 12, AUTO_REFLECTION_DESCRIPTION = "Reflect on recent conversations", AUTO_REFLECTION_PROMPT = "Review recent conversation history and update memory files with important information worth preserving.";
|
|
113467
114225
|
var init_App2 = __esm(async () => {
|
|
113468
114226
|
init_error();
|
|
113469
114227
|
init_check_approval();
|
|
@@ -113489,7 +114247,6 @@ var init_App2 = __esm(async () => {
|
|
|
113489
114247
|
init_diff2();
|
|
113490
114248
|
init_errorContext();
|
|
113491
114249
|
init_errorFormatter();
|
|
113492
|
-
init_initCommand();
|
|
113493
114250
|
init_messageQueueBridge();
|
|
113494
114251
|
init_pasteRegistry();
|
|
113495
114252
|
init_planName();
|
|
@@ -113563,6 +114320,7 @@ var init_App2 = __esm(async () => {
|
|
|
113563
114320
|
init_accumulator(),
|
|
113564
114321
|
init_approvalClassification(),
|
|
113565
114322
|
init_formatArgsDisplay(),
|
|
114323
|
+
init_initCommand(),
|
|
113566
114324
|
init_memoryReminder(),
|
|
113567
114325
|
init_statusLineConfig(),
|
|
113568
114326
|
init_stream(),
|
|
@@ -113628,13 +114386,13 @@ __export(exports_terminalKeybindingInstaller2, {
|
|
|
113628
114386
|
});
|
|
113629
114387
|
import {
|
|
113630
114388
|
copyFileSync as copyFileSync2,
|
|
113631
|
-
existsSync as
|
|
113632
|
-
mkdirSync as
|
|
113633
|
-
readFileSync as
|
|
114389
|
+
existsSync as existsSync27,
|
|
114390
|
+
mkdirSync as mkdirSync18,
|
|
114391
|
+
readFileSync as readFileSync12,
|
|
113634
114392
|
writeFileSync as writeFileSync13
|
|
113635
114393
|
} from "node:fs";
|
|
113636
|
-
import { homedir as
|
|
113637
|
-
import { dirname as dirname14, join as
|
|
114394
|
+
import { homedir as homedir29, platform as platform5 } from "node:os";
|
|
114395
|
+
import { dirname as dirname14, join as join40 } from "node:path";
|
|
113638
114396
|
function detectTerminalType2() {
|
|
113639
114397
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
113640
114398
|
return "cursor";
|
|
@@ -113666,16 +114424,16 @@ function getKeybindingsPath2(terminal) {
|
|
|
113666
114424
|
}[terminal];
|
|
113667
114425
|
const os7 = platform5();
|
|
113668
114426
|
if (os7 === "darwin") {
|
|
113669
|
-
return
|
|
114427
|
+
return join40(homedir29(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
113670
114428
|
}
|
|
113671
114429
|
if (os7 === "win32") {
|
|
113672
114430
|
const appData = process.env.APPDATA;
|
|
113673
114431
|
if (!appData)
|
|
113674
114432
|
return null;
|
|
113675
|
-
return
|
|
114433
|
+
return join40(appData, appName, "User", "keybindings.json");
|
|
113676
114434
|
}
|
|
113677
114435
|
if (os7 === "linux") {
|
|
113678
|
-
return
|
|
114436
|
+
return join40(homedir29(), ".config", appName, "User", "keybindings.json");
|
|
113679
114437
|
}
|
|
113680
114438
|
return null;
|
|
113681
114439
|
}
|
|
@@ -113697,10 +114455,10 @@ function parseKeybindings2(content) {
|
|
|
113697
114455
|
}
|
|
113698
114456
|
}
|
|
113699
114457
|
function keybindingExists2(keybindingsPath) {
|
|
113700
|
-
if (!
|
|
114458
|
+
if (!existsSync27(keybindingsPath))
|
|
113701
114459
|
return false;
|
|
113702
114460
|
try {
|
|
113703
|
-
const content =
|
|
114461
|
+
const content = readFileSync12(keybindingsPath, { encoding: "utf-8" });
|
|
113704
114462
|
const keybindings = parseKeybindings2(content);
|
|
113705
114463
|
if (!keybindings)
|
|
113706
114464
|
return false;
|
|
@@ -113710,7 +114468,7 @@ function keybindingExists2(keybindingsPath) {
|
|
|
113710
114468
|
}
|
|
113711
114469
|
}
|
|
113712
114470
|
function createBackup2(keybindingsPath) {
|
|
113713
|
-
if (!
|
|
114471
|
+
if (!existsSync27(keybindingsPath))
|
|
113714
114472
|
return null;
|
|
113715
114473
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
113716
114474
|
try {
|
|
@@ -113726,14 +114484,14 @@ function installKeybinding2(keybindingsPath) {
|
|
|
113726
114484
|
return { success: true, alreadyExists: true };
|
|
113727
114485
|
}
|
|
113728
114486
|
const parentDir = dirname14(keybindingsPath);
|
|
113729
|
-
if (!
|
|
113730
|
-
|
|
114487
|
+
if (!existsSync27(parentDir)) {
|
|
114488
|
+
mkdirSync18(parentDir, { recursive: true });
|
|
113731
114489
|
}
|
|
113732
114490
|
let keybindings = [];
|
|
113733
114491
|
let backupPath = null;
|
|
113734
|
-
if (
|
|
114492
|
+
if (existsSync27(keybindingsPath)) {
|
|
113735
114493
|
backupPath = createBackup2(keybindingsPath);
|
|
113736
|
-
const content =
|
|
114494
|
+
const content = readFileSync12(keybindingsPath, { encoding: "utf-8" });
|
|
113737
114495
|
const parsed = parseKeybindings2(content);
|
|
113738
114496
|
if (parsed === null) {
|
|
113739
114497
|
return {
|
|
@@ -113761,10 +114519,10 @@ function installKeybinding2(keybindingsPath) {
|
|
|
113761
114519
|
}
|
|
113762
114520
|
function removeKeybinding2(keybindingsPath) {
|
|
113763
114521
|
try {
|
|
113764
|
-
if (!
|
|
114522
|
+
if (!existsSync27(keybindingsPath)) {
|
|
113765
114523
|
return { success: true };
|
|
113766
114524
|
}
|
|
113767
|
-
const content =
|
|
114525
|
+
const content = readFileSync12(keybindingsPath, { encoding: "utf-8" });
|
|
113768
114526
|
const keybindings = parseKeybindings2(content);
|
|
113769
114527
|
if (!keybindings) {
|
|
113770
114528
|
return {
|
|
@@ -113828,20 +114586,20 @@ function getWezTermConfigPath2() {
|
|
|
113828
114586
|
}
|
|
113829
114587
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
113830
114588
|
if (xdgConfig) {
|
|
113831
|
-
const xdgPath =
|
|
113832
|
-
if (
|
|
114589
|
+
const xdgPath = join40(xdgConfig, "wezterm", "wezterm.lua");
|
|
114590
|
+
if (existsSync27(xdgPath))
|
|
113833
114591
|
return xdgPath;
|
|
113834
114592
|
}
|
|
113835
|
-
const configPath =
|
|
113836
|
-
if (
|
|
114593
|
+
const configPath = join40(homedir29(), ".config", "wezterm", "wezterm.lua");
|
|
114594
|
+
if (existsSync27(configPath))
|
|
113837
114595
|
return configPath;
|
|
113838
|
-
return
|
|
114596
|
+
return join40(homedir29(), ".wezterm.lua");
|
|
113839
114597
|
}
|
|
113840
114598
|
function wezTermDeleteFixExists2(configPath) {
|
|
113841
|
-
if (!
|
|
114599
|
+
if (!existsSync27(configPath))
|
|
113842
114600
|
return false;
|
|
113843
114601
|
try {
|
|
113844
|
-
const content =
|
|
114602
|
+
const content = readFileSync12(configPath, { encoding: "utf-8" });
|
|
113845
114603
|
return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
|
|
113846
114604
|
} catch {
|
|
113847
114605
|
return false;
|
|
@@ -113855,10 +114613,10 @@ function installWezTermDeleteFix2() {
|
|
|
113855
114613
|
}
|
|
113856
114614
|
let content = "";
|
|
113857
114615
|
let backupPath = null;
|
|
113858
|
-
if (
|
|
114616
|
+
if (existsSync27(configPath)) {
|
|
113859
114617
|
backupPath = `${configPath}.letta-backup`;
|
|
113860
114618
|
copyFileSync2(configPath, backupPath);
|
|
113861
|
-
content =
|
|
114619
|
+
content = readFileSync12(configPath, { encoding: "utf-8" });
|
|
113862
114620
|
}
|
|
113863
114621
|
if (content.includes("return {") && !content.includes("local config")) {
|
|
113864
114622
|
content = content.replace(/return\s*\{/, "local config = {");
|
|
@@ -113885,8 +114643,8 @@ ${WEZTERM_DELETE_FIX2}
|
|
|
113885
114643
|
`;
|
|
113886
114644
|
}
|
|
113887
114645
|
const parentDir = dirname14(configPath);
|
|
113888
|
-
if (!
|
|
113889
|
-
|
|
114646
|
+
if (!existsSync27(parentDir)) {
|
|
114647
|
+
mkdirSync18(parentDir, { recursive: true });
|
|
113890
114648
|
}
|
|
113891
114649
|
writeFileSync13(configPath, content, { encoding: "utf-8" });
|
|
113892
114650
|
return {
|
|
@@ -113933,10 +114691,10 @@ __export(exports_settings2, {
|
|
|
113933
114691
|
loadProjectSettings: () => loadProjectSettings2,
|
|
113934
114692
|
getSetting: () => getSetting2
|
|
113935
114693
|
});
|
|
113936
|
-
import { homedir as
|
|
113937
|
-
import { join as
|
|
114694
|
+
import { homedir as homedir30 } from "node:os";
|
|
114695
|
+
import { join as join41 } from "node:path";
|
|
113938
114696
|
function getSettingsPath2() {
|
|
113939
|
-
return
|
|
114697
|
+
return join41(homedir30(), ".letta", "settings.json");
|
|
113940
114698
|
}
|
|
113941
114699
|
async function loadSettings2() {
|
|
113942
114700
|
const settingsPath = getSettingsPath2();
|
|
@@ -113973,7 +114731,7 @@ async function getSetting2(key) {
|
|
|
113973
114731
|
return settings[key];
|
|
113974
114732
|
}
|
|
113975
114733
|
function getProjectSettingsPath2() {
|
|
113976
|
-
return
|
|
114734
|
+
return join41(process.cwd(), ".letta", "settings.local.json");
|
|
113977
114735
|
}
|
|
113978
114736
|
async function loadProjectSettings2() {
|
|
113979
114737
|
const settingsPath = getProjectSettingsPath2();
|
|
@@ -113991,7 +114749,7 @@ async function loadProjectSettings2() {
|
|
|
113991
114749
|
}
|
|
113992
114750
|
async function saveProjectSettings2(settings) {
|
|
113993
114751
|
const settingsPath = getProjectSettingsPath2();
|
|
113994
|
-
const dirPath =
|
|
114752
|
+
const dirPath = join41(process.cwd(), ".letta");
|
|
113995
114753
|
try {
|
|
113996
114754
|
if (!exists(dirPath)) {
|
|
113997
114755
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -114530,7 +115288,7 @@ function parseRegistryHandle2(handle) {
|
|
|
114530
115288
|
}
|
|
114531
115289
|
async function importAgentFromRegistry2(options) {
|
|
114532
115290
|
const { tmpdir: tmpdir6 } = await import("node:os");
|
|
114533
|
-
const { join:
|
|
115291
|
+
const { join: join42 } = await import("node:path");
|
|
114534
115292
|
const { writeFile: writeFile5, unlink } = await import("node:fs/promises");
|
|
114535
115293
|
const { author, name } = parseRegistryHandle2(options.handle);
|
|
114536
115294
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -114542,7 +115300,7 @@ async function importAgentFromRegistry2(options) {
|
|
|
114542
115300
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
114543
115301
|
}
|
|
114544
115302
|
const afContent = await response.text();
|
|
114545
|
-
const tempPath =
|
|
115303
|
+
const tempPath = join42(tmpdir6(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
114546
115304
|
await writeFile5(tempPath, afContent, "utf-8");
|
|
114547
115305
|
try {
|
|
114548
115306
|
const result = await importAgentFromFile2({
|
|
@@ -114582,23 +115340,23 @@ __export(exports_memoryFilesystem2, {
|
|
|
114582
115340
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
|
|
114583
115341
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
114584
115342
|
});
|
|
114585
|
-
import { existsSync as
|
|
114586
|
-
import { homedir as
|
|
114587
|
-
import { join as
|
|
114588
|
-
function getMemoryFilesystemRoot2(agentId, homeDir =
|
|
114589
|
-
return
|
|
115343
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync19 } from "node:fs";
|
|
115344
|
+
import { homedir as homedir31 } from "node:os";
|
|
115345
|
+
import { join as join42 } from "node:path";
|
|
115346
|
+
function getMemoryFilesystemRoot2(agentId, homeDir = homedir31()) {
|
|
115347
|
+
return join42(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
114590
115348
|
}
|
|
114591
|
-
function getMemorySystemDir2(agentId, homeDir =
|
|
114592
|
-
return
|
|
115349
|
+
function getMemorySystemDir2(agentId, homeDir = homedir31()) {
|
|
115350
|
+
return join42(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
114593
115351
|
}
|
|
114594
|
-
function ensureMemoryFilesystemDirs2(agentId, homeDir =
|
|
115352
|
+
function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir31()) {
|
|
114595
115353
|
const root = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
114596
115354
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
114597
|
-
if (!
|
|
114598
|
-
|
|
115355
|
+
if (!existsSync28(root)) {
|
|
115356
|
+
mkdirSync19(root, { recursive: true });
|
|
114599
115357
|
}
|
|
114600
|
-
if (!
|
|
114601
|
-
|
|
115358
|
+
if (!existsSync28(systemDir)) {
|
|
115359
|
+
mkdirSync19(systemDir, { recursive: true });
|
|
114602
115360
|
}
|
|
114603
115361
|
}
|
|
114604
115362
|
function labelFromRelativePath2(relativePath) {
|
|
@@ -114975,9 +115733,6 @@ async function getResumeData(client, agent, conversationId, options = {}) {
|
|
|
114975
115733
|
let inContextMessageIds;
|
|
114976
115734
|
let messages = [];
|
|
114977
115735
|
const useConversationsApi = conversationId && conversationId !== "default";
|
|
114978
|
-
if (process.env.DEBUG) {
|
|
114979
|
-
console.log(`[DEBUG] getResumeData: conversationId=${conversationId}, useConversationsApi=${useConversationsApi}, agentId=${agent.id}`);
|
|
114980
|
-
}
|
|
114981
115736
|
if (useConversationsApi) {
|
|
114982
115737
|
const conversation = await client.conversations.retrieve(conversationId);
|
|
114983
115738
|
inContextMessageIds = conversation.in_context_message_ids;
|
|
@@ -115053,13 +115808,14 @@ async function getResumeData(client, agent, conversationId, options = {}) {
|
|
|
115053
115808
|
const retrievedMessages = await client.messages.retrieve(lastInContextId);
|
|
115054
115809
|
if (includeMessageHistory && isBackfillEnabled()) {
|
|
115055
115810
|
try {
|
|
115056
|
-
const messagesPage = await client.conversations.messages.list(
|
|
115811
|
+
const messagesPage = await client.conversations.messages.list("default", {
|
|
115812
|
+
agent_id: agent.id,
|
|
115057
115813
|
limit: BACKFILL_PAGE_LIMIT,
|
|
115058
115814
|
order: "desc"
|
|
115059
115815
|
});
|
|
115060
115816
|
messages = sortChronological(messagesPage.getPaginatedItems());
|
|
115061
115817
|
if (process.env.DEBUG) {
|
|
115062
|
-
console.log(`[DEBUG] conversations.messages.list(
|
|
115818
|
+
console.log(`[DEBUG] conversations.messages.list(default, agent_id=${agent.id}) returned ${messages.length} messages`);
|
|
115063
115819
|
}
|
|
115064
115820
|
} catch (backfillError) {
|
|
115065
115821
|
debugWarn("check-approval", `Failed to load message history: ${backfillError instanceof Error ? backfillError.message : String(backfillError)}`);
|
|
@@ -115742,7 +116498,8 @@ function ConversationSelector({
|
|
|
115742
116498
|
let defaultConversation = null;
|
|
115743
116499
|
if (!afterCursor) {
|
|
115744
116500
|
try {
|
|
115745
|
-
const defaultMessages = await client.conversations.messages.list(
|
|
116501
|
+
const defaultMessages = await client.conversations.messages.list("default", {
|
|
116502
|
+
agent_id: agentId,
|
|
115746
116503
|
limit: 20,
|
|
115747
116504
|
order: "desc"
|
|
115748
116505
|
});
|
|
@@ -116152,8 +116909,8 @@ function parseJsonArrayFlag(rawValue, flagName) {
|
|
|
116152
116909
|
init_error();
|
|
116153
116910
|
init_errorContext();
|
|
116154
116911
|
init_zaiErrors();
|
|
116155
|
-
var LETTA_USAGE_URL = "
|
|
116156
|
-
var LETTA_AGENTS_URL = "
|
|
116912
|
+
var LETTA_USAGE_URL = buildAppUrl("/settings/organization/usage");
|
|
116913
|
+
var LETTA_AGENTS_URL = buildAppUrl("/projects/default-project/agents");
|
|
116157
116914
|
function extractReasonList(value) {
|
|
116158
116915
|
if (!Array.isArray(value))
|
|
116159
116916
|
return [];
|
|
@@ -116585,7 +117342,7 @@ ${createAgentLink(runId, agentId, conversationId)}` : baseError;
|
|
|
116585
117342
|
return String(e);
|
|
116586
117343
|
}
|
|
116587
117344
|
function createAgentLink(runId, agentId, conversationId) {
|
|
116588
|
-
const url =
|
|
117345
|
+
const url = buildChatUrl(agentId, { conversationId });
|
|
116589
117346
|
return `View agent: \x1B]8;;${url}\x1B\\${agentId}\x1B]8;;\x1B\\ (run: ${runId})`;
|
|
116590
117347
|
}
|
|
116591
117348
|
|
|
@@ -117792,7 +118549,7 @@ async function runListenSubcommand(argv) {
|
|
|
117792
118549
|
});
|
|
117793
118550
|
const debugMode = !!values.debug;
|
|
117794
118551
|
if (values.help) {
|
|
117795
|
-
console.log(`Usage: letta
|
|
118552
|
+
console.log(`Usage: letta server [--env-name <name>] [--debug]
|
|
117796
118553
|
`);
|
|
117797
118554
|
console.log(`Register this letta-code instance to receive messages from Letta Cloud.
|
|
117798
118555
|
`);
|
|
@@ -117802,9 +118559,9 @@ async function runListenSubcommand(argv) {
|
|
|
117802
118559
|
console.log(` -h, --help Show this help message
|
|
117803
118560
|
`);
|
|
117804
118561
|
console.log("Examples:");
|
|
117805
|
-
console.log(" letta
|
|
117806
|
-
console.log(' letta
|
|
117807
|
-
console.log(` letta
|
|
118562
|
+
console.log(" letta server # Uses hostname as default");
|
|
118563
|
+
console.log(' letta server --env-name "work-laptop"');
|
|
118564
|
+
console.log(` letta server --debug # Log all WS events
|
|
117808
118565
|
`);
|
|
117809
118566
|
console.log("Once connected, this instance will listen for incoming messages from cloud agents.");
|
|
117810
118567
|
console.log("Messages will be executed locally using your letta-code environment.");
|
|
@@ -118389,7 +119146,8 @@ async function runMessagesSubcommand(argv) {
|
|
|
118389
119146
|
console.error(`Invalid --order "${orderRaw}". Use "asc" or "desc".`);
|
|
118390
119147
|
return 1;
|
|
118391
119148
|
}
|
|
118392
|
-
const response = await client.conversations.messages.list(
|
|
119149
|
+
const response = await client.conversations.messages.list("default", {
|
|
119150
|
+
agent_id: agentId,
|
|
118393
119151
|
limit: parseLimit3(parsed.values.limit, 20),
|
|
118394
119152
|
after: parsed.values.after,
|
|
118395
119153
|
before: parsed.values.before,
|
|
@@ -118441,6 +119199,7 @@ async function runSubcommand(argv) {
|
|
|
118441
119199
|
return runMessagesSubcommand(rest);
|
|
118442
119200
|
case "blocks":
|
|
118443
119201
|
return runBlocksSubcommand(rest);
|
|
119202
|
+
case "server":
|
|
118444
119203
|
case "remote":
|
|
118445
119204
|
return runListenSubcommand(rest);
|
|
118446
119205
|
case "connect":
|
|
@@ -120032,7 +120791,7 @@ function replaceRegistry2(newTools) {
|
|
|
120032
120791
|
toolRegistry2.set(key, value);
|
|
120033
120792
|
}
|
|
120034
120793
|
}
|
|
120035
|
-
async function loadTools2(modelIdentifier) {
|
|
120794
|
+
async function loadTools2(modelIdentifier, options) {
|
|
120036
120795
|
acquireSwitchLock2();
|
|
120037
120796
|
try {
|
|
120038
120797
|
const { toolFilter: toolFilter2 } = await Promise.resolve().then(() => (init_filter(), exports_filter));
|
|
@@ -120053,6 +120812,10 @@ async function loadTools2(modelIdentifier) {
|
|
|
120053
120812
|
} else {
|
|
120054
120813
|
baseToolNames = TOOL_NAMES2;
|
|
120055
120814
|
}
|
|
120815
|
+
if (options?.exclude && options.exclude.length > 0) {
|
|
120816
|
+
const excludeSet = new Set(options.exclude);
|
|
120817
|
+
baseToolNames = baseToolNames.filter((name) => !excludeSet.has(name));
|
|
120818
|
+
}
|
|
120056
120819
|
const newRegistry = new Map;
|
|
120057
120820
|
for (const name of baseToolNames) {
|
|
120058
120821
|
if (!toolFilter2.isEnabled(name)) {
|
|
@@ -120145,6 +120908,119 @@ ${agentsSection}
|
|
|
120145
120908
|
${after}`;
|
|
120146
120909
|
}
|
|
120147
120910
|
|
|
120911
|
+
// src/utils/debug.ts
|
|
120912
|
+
import {
|
|
120913
|
+
appendFileSync as appendFileSync3,
|
|
120914
|
+
existsSync as existsSync12,
|
|
120915
|
+
mkdirSync as mkdirSync10,
|
|
120916
|
+
readdirSync as readdirSync7,
|
|
120917
|
+
readFileSync as readFileSync4,
|
|
120918
|
+
unlinkSync as unlinkSync6
|
|
120919
|
+
} from "node:fs";
|
|
120920
|
+
import { homedir as homedir18 } from "node:os";
|
|
120921
|
+
import { join as join21 } from "node:path";
|
|
120922
|
+
import { format as format2 } from "node:util";
|
|
120923
|
+
function isDebugEnabled2() {
|
|
120924
|
+
const debug = process.env.LETTA_DEBUG;
|
|
120925
|
+
return debug === "1" || debug === "true";
|
|
120926
|
+
}
|
|
120927
|
+
function getDebugFile2() {
|
|
120928
|
+
const path20 = process.env.LETTA_DEBUG_FILE;
|
|
120929
|
+
return path20 && path20.trim().length > 0 ? path20 : null;
|
|
120930
|
+
}
|
|
120931
|
+
function printDebugLine2(line) {
|
|
120932
|
+
const debugFile = getDebugFile2();
|
|
120933
|
+
if (debugFile) {
|
|
120934
|
+
try {
|
|
120935
|
+
appendFileSync3(debugFile, line, { encoding: "utf8" });
|
|
120936
|
+
return;
|
|
120937
|
+
} catch {}
|
|
120938
|
+
}
|
|
120939
|
+
console.log(line.trimEnd());
|
|
120940
|
+
}
|
|
120941
|
+
var DEBUG_LOG_DIR2 = join21(homedir18(), ".letta", "logs", "debug");
|
|
120942
|
+
var MAX_SESSION_FILES3 = 5;
|
|
120943
|
+
var DEFAULT_TAIL_LINES2 = 50;
|
|
120944
|
+
|
|
120945
|
+
class DebugLogFile2 {
|
|
120946
|
+
logPath = null;
|
|
120947
|
+
agentDir = null;
|
|
120948
|
+
dirCreated = false;
|
|
120949
|
+
init(agentId, sessionId) {
|
|
120950
|
+
const telem = process.env.LETTA_CODE_TELEM;
|
|
120951
|
+
if (telem === "0" || telem === "false")
|
|
120952
|
+
return;
|
|
120953
|
+
this.agentDir = join21(DEBUG_LOG_DIR2, agentId);
|
|
120954
|
+
this.logPath = join21(this.agentDir, `${sessionId}.log`);
|
|
120955
|
+
this.dirCreated = false;
|
|
120956
|
+
this.pruneOldSessions();
|
|
120957
|
+
}
|
|
120958
|
+
appendLine(line) {
|
|
120959
|
+
if (!this.logPath)
|
|
120960
|
+
return;
|
|
120961
|
+
this.ensureDir();
|
|
120962
|
+
try {
|
|
120963
|
+
appendFileSync3(this.logPath, line, { encoding: "utf8" });
|
|
120964
|
+
} catch {}
|
|
120965
|
+
}
|
|
120966
|
+
getTail(maxLines = DEFAULT_TAIL_LINES2) {
|
|
120967
|
+
if (!this.logPath)
|
|
120968
|
+
return;
|
|
120969
|
+
try {
|
|
120970
|
+
if (!existsSync12(this.logPath))
|
|
120971
|
+
return;
|
|
120972
|
+
const content = readFileSync4(this.logPath, "utf8");
|
|
120973
|
+
const lines = content.trimEnd().split(`
|
|
120974
|
+
`);
|
|
120975
|
+
return lines.slice(-maxLines).join(`
|
|
120976
|
+
`);
|
|
120977
|
+
} catch {
|
|
120978
|
+
return;
|
|
120979
|
+
}
|
|
120980
|
+
}
|
|
120981
|
+
ensureDir() {
|
|
120982
|
+
if (this.dirCreated || !this.agentDir)
|
|
120983
|
+
return;
|
|
120984
|
+
try {
|
|
120985
|
+
if (!existsSync12(this.agentDir)) {
|
|
120986
|
+
mkdirSync10(this.agentDir, { recursive: true });
|
|
120987
|
+
}
|
|
120988
|
+
this.dirCreated = true;
|
|
120989
|
+
} catch {}
|
|
120990
|
+
}
|
|
120991
|
+
pruneOldSessions() {
|
|
120992
|
+
if (!this.agentDir)
|
|
120993
|
+
return;
|
|
120994
|
+
try {
|
|
120995
|
+
if (!existsSync12(this.agentDir))
|
|
120996
|
+
return;
|
|
120997
|
+
const files = readdirSync7(this.agentDir).filter((f) => f.endsWith(".log")).sort();
|
|
120998
|
+
if (files.length >= MAX_SESSION_FILES3) {
|
|
120999
|
+
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES3 + 1);
|
|
121000
|
+
for (const file of toDelete) {
|
|
121001
|
+
try {
|
|
121002
|
+
unlinkSync6(join21(this.agentDir, file));
|
|
121003
|
+
} catch {}
|
|
121004
|
+
}
|
|
121005
|
+
}
|
|
121006
|
+
} catch {}
|
|
121007
|
+
}
|
|
121008
|
+
}
|
|
121009
|
+
var debugLogFile2 = new DebugLogFile2;
|
|
121010
|
+
function writeDebugLine2(prefix, message, args) {
|
|
121011
|
+
const ts = new Date().toISOString();
|
|
121012
|
+
const body = format2(`[${prefix}] ${message}`, ...args);
|
|
121013
|
+
const line = `${ts} ${body}
|
|
121014
|
+
`;
|
|
121015
|
+
debugLogFile2.appendLine(line);
|
|
121016
|
+
if (isDebugEnabled2()) {
|
|
121017
|
+
printDebugLine2(line);
|
|
121018
|
+
}
|
|
121019
|
+
}
|
|
121020
|
+
function debugLog2(prefix, message, ...args) {
|
|
121021
|
+
writeDebugLine2(prefix, message, args);
|
|
121022
|
+
}
|
|
121023
|
+
|
|
120148
121024
|
// src/utils/timing.ts
|
|
120149
121025
|
function isTimingsEnabled2() {
|
|
120150
121026
|
const val = process.env.LETTA_DEBUG_TIMINGS;
|
|
@@ -120251,12 +121127,12 @@ EXAMPLES
|
|
|
120251
121127
|
console.log(usage);
|
|
120252
121128
|
}
|
|
120253
121129
|
async function printInfo() {
|
|
120254
|
-
const { join:
|
|
121130
|
+
const { join: join43 } = await import("path");
|
|
120255
121131
|
const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version));
|
|
120256
121132
|
const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills2(), exports_skills2));
|
|
120257
121133
|
const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
|
|
120258
121134
|
const cwd2 = process.cwd();
|
|
120259
|
-
const skillsDir =
|
|
121135
|
+
const skillsDir = join43(cwd2, SKILLS_DIR3);
|
|
120260
121136
|
const skillsExist = exists3(skillsDir);
|
|
120261
121137
|
await settingsManager2.loadLocalProjectSettings(cwd2);
|
|
120262
121138
|
const localPinned = settingsManager2.getLocalPinnedAgents(cwd2);
|
|
@@ -120650,9 +121526,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
120650
121526
|
}
|
|
120651
121527
|
} else {
|
|
120652
121528
|
const { resolve: resolve30 } = await import("path");
|
|
120653
|
-
const { existsSync:
|
|
121529
|
+
const { existsSync: existsSync29 } = await import("fs");
|
|
120654
121530
|
const resolvedPath = resolve30(fromAfFile);
|
|
120655
|
-
if (!
|
|
121531
|
+
if (!existsSync29(resolvedPath)) {
|
|
120656
121532
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
120657
121533
|
process.exit(1);
|
|
120658
121534
|
}
|
|
@@ -120772,7 +121648,7 @@ Error: ${message}`);
|
|
|
120772
121648
|
if (isHeadless) {
|
|
120773
121649
|
markMilestone2("HEADLESS_MODE_START");
|
|
120774
121650
|
const modelForTools = getModelForToolLoading(specifiedModel, specifiedToolset);
|
|
120775
|
-
await loadTools2(modelForTools);
|
|
121651
|
+
await loadTools2(modelForTools, { exclude: ["AskUserQuestion"] });
|
|
120776
121652
|
markMilestone2("TOOLS_LOADED");
|
|
120777
121653
|
const headlessValues = specifiedAgentId && values.agent !== specifiedAgentId ? { ...values, agent: specifiedAgentId } : values;
|
|
120778
121654
|
const { handleHeadlessCommand: handleHeadlessCommand2 } = await init_headless().then(() => exports_headless);
|
|
@@ -120930,6 +121806,7 @@ Error: ${message}`);
|
|
|
120930
121806
|
return;
|
|
120931
121807
|
}
|
|
120932
121808
|
try {
|
|
121809
|
+
debugLog2("conversations", `retrieve(${specifiedConversationId}) [TUI conv\u2192agent lookup]`);
|
|
120933
121810
|
const conversation = await client.conversations.retrieve(specifiedConversationId);
|
|
120934
121811
|
setSelectedGlobalAgentId(conversation.agent_id);
|
|
120935
121812
|
setSelectedConversationId(specifiedConversationId);
|
|
@@ -121531,4 +122408,4 @@ Error during initialization: ${message}`);
|
|
|
121531
122408
|
}
|
|
121532
122409
|
main();
|
|
121533
122410
|
|
|
121534
|
-
//# debugId=
|
|
122411
|
+
//# debugId=FE66CA162A20D40F64756E2164756E21
|