@letta-ai/letta-code 0.24.1 → 0.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +740 -155
- package/package.json +1 -1
- package/skills/migrating-memory/SKILL.md +15 -9
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.24.
|
|
3272
|
+
version: "0.24.3",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -9157,6 +9157,72 @@ var init_models2 = __esm(() => {
|
|
|
9157
9157
|
parallel_tool_calls: true
|
|
9158
9158
|
}
|
|
9159
9159
|
},
|
|
9160
|
+
{
|
|
9161
|
+
id: "gpt-5.5-none",
|
|
9162
|
+
handle: "openai/gpt-5.5",
|
|
9163
|
+
label: "GPT-5.5",
|
|
9164
|
+
description: "OpenAI's most capable model (no reasoning)",
|
|
9165
|
+
updateArgs: {
|
|
9166
|
+
reasoning_effort: "none",
|
|
9167
|
+
verbosity: "medium",
|
|
9168
|
+
context_window: 272000,
|
|
9169
|
+
max_output_tokens: 128000,
|
|
9170
|
+
parallel_tool_calls: true
|
|
9171
|
+
}
|
|
9172
|
+
},
|
|
9173
|
+
{
|
|
9174
|
+
id: "gpt-5.5-low",
|
|
9175
|
+
handle: "openai/gpt-5.5",
|
|
9176
|
+
label: "GPT-5.5",
|
|
9177
|
+
description: "OpenAI's most capable model (low reasoning)",
|
|
9178
|
+
updateArgs: {
|
|
9179
|
+
reasoning_effort: "low",
|
|
9180
|
+
verbosity: "medium",
|
|
9181
|
+
context_window: 272000,
|
|
9182
|
+
max_output_tokens: 128000,
|
|
9183
|
+
parallel_tool_calls: true
|
|
9184
|
+
}
|
|
9185
|
+
},
|
|
9186
|
+
{
|
|
9187
|
+
id: "gpt-5.5-medium",
|
|
9188
|
+
handle: "openai/gpt-5.5",
|
|
9189
|
+
label: "GPT-5.5",
|
|
9190
|
+
description: "OpenAI's most capable model (med reasoning)",
|
|
9191
|
+
updateArgs: {
|
|
9192
|
+
reasoning_effort: "medium",
|
|
9193
|
+
verbosity: "medium",
|
|
9194
|
+
context_window: 272000,
|
|
9195
|
+
max_output_tokens: 128000,
|
|
9196
|
+
parallel_tool_calls: true
|
|
9197
|
+
}
|
|
9198
|
+
},
|
|
9199
|
+
{
|
|
9200
|
+
id: "gpt-5.5-high",
|
|
9201
|
+
handle: "openai/gpt-5.5",
|
|
9202
|
+
label: "GPT-5.5",
|
|
9203
|
+
description: "OpenAI's most capable model (high reasoning)",
|
|
9204
|
+
isFeatured: true,
|
|
9205
|
+
updateArgs: {
|
|
9206
|
+
reasoning_effort: "high",
|
|
9207
|
+
verbosity: "medium",
|
|
9208
|
+
context_window: 272000,
|
|
9209
|
+
max_output_tokens: 128000,
|
|
9210
|
+
parallel_tool_calls: true
|
|
9211
|
+
}
|
|
9212
|
+
},
|
|
9213
|
+
{
|
|
9214
|
+
id: "gpt-5.5-xhigh",
|
|
9215
|
+
handle: "openai/gpt-5.5",
|
|
9216
|
+
label: "GPT-5.5",
|
|
9217
|
+
description: "OpenAI's most capable model (max reasoning)",
|
|
9218
|
+
updateArgs: {
|
|
9219
|
+
reasoning_effort: "xhigh",
|
|
9220
|
+
verbosity: "medium",
|
|
9221
|
+
context_window: 272000,
|
|
9222
|
+
max_output_tokens: 128000,
|
|
9223
|
+
parallel_tool_calls: true
|
|
9224
|
+
}
|
|
9225
|
+
},
|
|
9160
9226
|
{
|
|
9161
9227
|
id: "gpt-5.4-none",
|
|
9162
9228
|
handle: "openai/gpt-5.4",
|
|
@@ -9288,6 +9354,46 @@ var init_models2 = __esm(() => {
|
|
|
9288
9354
|
parallel_tool_calls: true
|
|
9289
9355
|
}
|
|
9290
9356
|
},
|
|
9357
|
+
{
|
|
9358
|
+
id: "gpt-5.5-pro-medium",
|
|
9359
|
+
handle: "openai/gpt-5.5-pro",
|
|
9360
|
+
label: "GPT-5.5 Pro",
|
|
9361
|
+
description: "GPT-5.5 Pro — max performance variant (med reasoning)",
|
|
9362
|
+
updateArgs: {
|
|
9363
|
+
reasoning_effort: "medium",
|
|
9364
|
+
verbosity: "medium",
|
|
9365
|
+
context_window: 272000,
|
|
9366
|
+
max_output_tokens: 128000,
|
|
9367
|
+
parallel_tool_calls: true
|
|
9368
|
+
}
|
|
9369
|
+
},
|
|
9370
|
+
{
|
|
9371
|
+
id: "gpt-5.5-pro-high",
|
|
9372
|
+
handle: "openai/gpt-5.5-pro",
|
|
9373
|
+
label: "GPT-5.5 Pro",
|
|
9374
|
+
description: "GPT-5.5 Pro — max performance variant (high reasoning)",
|
|
9375
|
+
updateArgs: {
|
|
9376
|
+
reasoning_effort: "high",
|
|
9377
|
+
verbosity: "medium",
|
|
9378
|
+
context_window: 272000,
|
|
9379
|
+
max_output_tokens: 128000,
|
|
9380
|
+
parallel_tool_calls: true
|
|
9381
|
+
},
|
|
9382
|
+
isFeatured: true
|
|
9383
|
+
},
|
|
9384
|
+
{
|
|
9385
|
+
id: "gpt-5.5-pro-xhigh",
|
|
9386
|
+
handle: "openai/gpt-5.5-pro",
|
|
9387
|
+
label: "GPT-5.5 Pro",
|
|
9388
|
+
description: "GPT-5.5 Pro — max performance variant (max reasoning)",
|
|
9389
|
+
updateArgs: {
|
|
9390
|
+
reasoning_effort: "xhigh",
|
|
9391
|
+
verbosity: "medium",
|
|
9392
|
+
context_window: 272000,
|
|
9393
|
+
max_output_tokens: 128000,
|
|
9394
|
+
parallel_tool_calls: true
|
|
9395
|
+
}
|
|
9396
|
+
},
|
|
9291
9397
|
{
|
|
9292
9398
|
id: "gpt-5.4-pro-medium",
|
|
9293
9399
|
handle: "openai/gpt-5.4-pro",
|
|
@@ -51336,7 +51442,8 @@ var init_readOnlyShell = __esm(() => {
|
|
|
51336
51442
|
"sleep"
|
|
51337
51443
|
]);
|
|
51338
51444
|
SAFE_LETTA_COMMANDS = {
|
|
51339
|
-
|
|
51445
|
+
memory: new Set(["status", "help", "backups", "export", "tokens"]),
|
|
51446
|
+
memfs: new Set(["status", "help", "backups", "export", "tokens"]),
|
|
51340
51447
|
agents: new Set(["list", "help"]),
|
|
51341
51448
|
messages: new Set(["search", "list", "help"]),
|
|
51342
51449
|
blocks: new Set(["list", "help"])
|
|
@@ -79649,6 +79756,20 @@ var init_byok_providers = __esm(() => {
|
|
|
79649
79756
|
providerType: "google_ai",
|
|
79650
79757
|
providerName: "lc-gemini"
|
|
79651
79758
|
},
|
|
79759
|
+
{
|
|
79760
|
+
id: "moonshot",
|
|
79761
|
+
displayName: "Moonshot AI",
|
|
79762
|
+
description: "Connect a Moonshot AI API key",
|
|
79763
|
+
providerType: "moonshot",
|
|
79764
|
+
providerName: "lc-moonshot"
|
|
79765
|
+
},
|
|
79766
|
+
{
|
|
79767
|
+
id: "kimi-code",
|
|
79768
|
+
displayName: "Kimi Code",
|
|
79769
|
+
description: "Connect a Kimi Code API key",
|
|
79770
|
+
providerType: "moonshot_coding",
|
|
79771
|
+
providerName: "lc-kimi-code"
|
|
79772
|
+
},
|
|
79652
79773
|
{
|
|
79653
79774
|
id: "openrouter",
|
|
79654
79775
|
displayName: "OpenRouter API",
|
|
@@ -79699,6 +79820,8 @@ var init_byok_providers = __esm(() => {
|
|
|
79699
79820
|
google_ai: "google_ai",
|
|
79700
79821
|
google_vertex: "google_vertex",
|
|
79701
79822
|
minimax: "minimax",
|
|
79823
|
+
moonshot: "moonshot",
|
|
79824
|
+
moonshot_coding: "moonshot_coding",
|
|
79702
79825
|
openrouter: "openrouter",
|
|
79703
79826
|
bedrock: "bedrock"
|
|
79704
79827
|
};
|
|
@@ -79768,6 +79891,8 @@ var init_connect_normalize = __esm(() => {
|
|
|
79768
79891
|
zai: "zai",
|
|
79769
79892
|
"zai-coding": "zai-coding",
|
|
79770
79893
|
minimax: "minimax",
|
|
79894
|
+
moonshot: "moonshot",
|
|
79895
|
+
"kimi-code": "kimi-code",
|
|
79771
79896
|
gemini: "gemini",
|
|
79772
79897
|
openrouter: "openrouter",
|
|
79773
79898
|
bedrock: "bedrock"
|
|
@@ -79779,6 +79904,8 @@ var init_connect_normalize = __esm(() => {
|
|
|
79779
79904
|
"zai",
|
|
79780
79905
|
"zai-coding",
|
|
79781
79906
|
"minimax",
|
|
79907
|
+
"moonshot",
|
|
79908
|
+
"kimi-code",
|
|
79782
79909
|
"gemini",
|
|
79783
79910
|
"openrouter",
|
|
79784
79911
|
"bedrock"
|
|
@@ -83366,46 +83493,58 @@ var init_memoryReminder = __esm(() => {
|
|
|
83366
83493
|
};
|
|
83367
83494
|
});
|
|
83368
83495
|
|
|
83369
|
-
// src/
|
|
83496
|
+
// src/utils/systemPromptSize.ts
|
|
83370
83497
|
import { existsSync as existsSync26, readdirSync as readdirSync8, readFileSync as readFileSync19 } from "node:fs";
|
|
83371
83498
|
import { join as join29 } from "node:path";
|
|
83372
83499
|
function estimateSystemTokens(text) {
|
|
83373
|
-
return Math.ceil(Buffer.byteLength(text, "utf8") /
|
|
83500
|
+
return Math.ceil(Buffer.byteLength(text, "utf8") / SYSTEM_PROMPT_BYTES_PER_TOKEN);
|
|
83374
83501
|
}
|
|
83375
|
-
function
|
|
83376
|
-
|
|
83377
|
-
|
|
83378
|
-
|
|
83502
|
+
function normalizePath2(value) {
|
|
83503
|
+
return value.replaceAll("\\", "/");
|
|
83504
|
+
}
|
|
83505
|
+
function walkMarkdownFiles(dir) {
|
|
83506
|
+
if (!existsSync26(dir)) {
|
|
83507
|
+
return [];
|
|
83379
83508
|
}
|
|
83380
|
-
const
|
|
83381
|
-
|
|
83382
|
-
|
|
83509
|
+
const out = [];
|
|
83510
|
+
const entries = readdirSync8(dir, { withFileTypes: true });
|
|
83511
|
+
for (const entry of entries) {
|
|
83512
|
+
if (entry.name.startsWith(".")) {
|
|
83513
|
+
continue;
|
|
83383
83514
|
}
|
|
83384
|
-
const
|
|
83385
|
-
|
|
83386
|
-
|
|
83387
|
-
|
|
83388
|
-
continue;
|
|
83389
|
-
}
|
|
83390
|
-
const full = join29(dir, entry.name);
|
|
83391
|
-
if (entry.isDirectory()) {
|
|
83392
|
-
if (entry.name === ".git") {
|
|
83393
|
-
continue;
|
|
83394
|
-
}
|
|
83395
|
-
out.push(...walkMarkdownFiles(full));
|
|
83396
|
-
continue;
|
|
83397
|
-
}
|
|
83398
|
-
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
83399
|
-
out.push(full);
|
|
83400
|
-
}
|
|
83515
|
+
const full = join29(dir, entry.name);
|
|
83516
|
+
if (entry.isDirectory()) {
|
|
83517
|
+
out.push(...walkMarkdownFiles(full));
|
|
83518
|
+
continue;
|
|
83401
83519
|
}
|
|
83402
|
-
|
|
83403
|
-
|
|
83404
|
-
|
|
83520
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
83521
|
+
out.push(full);
|
|
83522
|
+
}
|
|
83523
|
+
}
|
|
83524
|
+
return out;
|
|
83525
|
+
}
|
|
83526
|
+
function estimateSystemPromptSize(memoryDir) {
|
|
83527
|
+
const systemDir = join29(memoryDir, "system");
|
|
83528
|
+
if (!existsSync26(systemDir)) {
|
|
83529
|
+
return { total: 0, files: [] };
|
|
83530
|
+
}
|
|
83531
|
+
const files = walkMarkdownFiles(systemDir).sort();
|
|
83532
|
+
const rows = [];
|
|
83533
|
+
for (const filePath of files) {
|
|
83405
83534
|
const text = readFileSync19(filePath, "utf8");
|
|
83406
|
-
|
|
83407
|
-
|
|
83535
|
+
const rel = normalizePath2(filePath.slice(memoryDir.length + 1));
|
|
83536
|
+
rows.push({ path: rel, tokens: estimateSystemTokens(text) });
|
|
83537
|
+
}
|
|
83538
|
+
const total = rows.reduce((sum, row) => sum + row.tokens, 0);
|
|
83539
|
+
return { total, files: rows };
|
|
83540
|
+
}
|
|
83541
|
+
function estimateSystemPromptTokensFromMemoryDir(memoryDir) {
|
|
83542
|
+
return estimateSystemPromptSize(memoryDir).total;
|
|
83408
83543
|
}
|
|
83544
|
+
var SYSTEM_PROMPT_BYTES_PER_TOKEN = 4;
|
|
83545
|
+
var init_systemPromptSize = () => {};
|
|
83546
|
+
|
|
83547
|
+
// src/cli/helpers/systemPromptWarning.ts
|
|
83409
83548
|
function setSystemPromptDoctorState(agentId, estimatedTokens) {
|
|
83410
83549
|
const nextState = {
|
|
83411
83550
|
estimated_tokens: estimatedTokens,
|
|
@@ -83448,11 +83587,12 @@ function buildStartupSystemPromptWarning(agentState) {
|
|
|
83448
83587
|
}
|
|
83449
83588
|
return null;
|
|
83450
83589
|
}
|
|
83451
|
-
var STARTUP_SYSTEM_PROMPT_WARNING_THRESHOLD_TOKENS = 30000,
|
|
83590
|
+
var STARTUP_SYSTEM_PROMPT_WARNING_THRESHOLD_TOKENS = 30000, systemPromptDoctorStateByAgent;
|
|
83452
83591
|
var init_systemPromptWarning = __esm(() => {
|
|
83453
83592
|
init_memoryFilesystem();
|
|
83454
83593
|
init_settings_manager();
|
|
83455
83594
|
init_debug();
|
|
83595
|
+
init_systemPromptSize();
|
|
83456
83596
|
systemPromptDoctorStateByAgent = new Map;
|
|
83457
83597
|
});
|
|
83458
83598
|
|
|
@@ -87057,10 +87197,132 @@ var init_reflectionTranscript = __esm(() => {
|
|
|
87057
87197
|
init_directoryLimits();
|
|
87058
87198
|
});
|
|
87059
87199
|
|
|
87200
|
+
// src/utils/tuiPerf.ts
|
|
87201
|
+
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync20 } from "node:fs";
|
|
87202
|
+
import { dirname as dirname14 } from "node:path";
|
|
87203
|
+
function ensureExitHook() {
|
|
87204
|
+
if (tuiPerfExitHookRegistered) {
|
|
87205
|
+
return;
|
|
87206
|
+
}
|
|
87207
|
+
tuiPerfExitHookRegistered = true;
|
|
87208
|
+
process.once("beforeExit", () => {
|
|
87209
|
+
flushTuiPerfTelemetry();
|
|
87210
|
+
});
|
|
87211
|
+
}
|
|
87212
|
+
function scheduleTuiPerfFlush() {
|
|
87213
|
+
if (tuiPerfFlushTimer) {
|
|
87214
|
+
return;
|
|
87215
|
+
}
|
|
87216
|
+
tuiPerfFlushTimer = setTimeout(() => {
|
|
87217
|
+
tuiPerfFlushTimer = null;
|
|
87218
|
+
flushTuiPerfTelemetry();
|
|
87219
|
+
}, TUI_PERF_FLUSH_INTERVAL_MS);
|
|
87220
|
+
const timerWithUnref = tuiPerfFlushTimer;
|
|
87221
|
+
timerWithUnref.unref?.();
|
|
87222
|
+
}
|
|
87223
|
+
function recordTuiPerf(key, sample) {
|
|
87224
|
+
if (!TUI_PERF_ENABLED || !TUI_PERF_FILE) {
|
|
87225
|
+
return;
|
|
87226
|
+
}
|
|
87227
|
+
ensureExitHook();
|
|
87228
|
+
if (tuiPerfWindowStartedAt === 0) {
|
|
87229
|
+
tuiPerfWindowStartedAt = Date.now();
|
|
87230
|
+
}
|
|
87231
|
+
const bytes = sample?.bytes ?? 0;
|
|
87232
|
+
const ms = sample?.ms ?? 0;
|
|
87233
|
+
const bucket = tuiPerfBuckets.get(key) ?? {
|
|
87234
|
+
count: 0,
|
|
87235
|
+
bytes: 0,
|
|
87236
|
+
ms: 0,
|
|
87237
|
+
maxBytes: 0,
|
|
87238
|
+
maxMs: 0
|
|
87239
|
+
};
|
|
87240
|
+
bucket.count += 1;
|
|
87241
|
+
bucket.bytes += bytes;
|
|
87242
|
+
bucket.ms += ms;
|
|
87243
|
+
bucket.maxBytes = Math.max(bucket.maxBytes, bytes);
|
|
87244
|
+
bucket.maxMs = Math.max(bucket.maxMs, ms);
|
|
87245
|
+
tuiPerfBuckets.set(key, bucket);
|
|
87246
|
+
scheduleTuiPerfFlush();
|
|
87247
|
+
}
|
|
87248
|
+
function recordTuiJsonPayload(key, value) {
|
|
87249
|
+
if (!TUI_PERF_ENABLED || !TUI_PERF_FILE) {
|
|
87250
|
+
return;
|
|
87251
|
+
}
|
|
87252
|
+
try {
|
|
87253
|
+
recordTuiPerf(key, { bytes: Buffer.byteLength(JSON.stringify(value)) });
|
|
87254
|
+
} catch {
|
|
87255
|
+
recordTuiPerf(key);
|
|
87256
|
+
}
|
|
87257
|
+
}
|
|
87258
|
+
function flushTuiPerfTelemetry() {
|
|
87259
|
+
if (tuiPerfBuckets.size === 0) {
|
|
87260
|
+
tuiPerfWindowStartedAt = 0;
|
|
87261
|
+
return;
|
|
87262
|
+
}
|
|
87263
|
+
const filePath = TUI_PERF_FILE;
|
|
87264
|
+
if (!filePath) {
|
|
87265
|
+
tuiPerfBuckets.clear();
|
|
87266
|
+
tuiPerfWindowStartedAt = 0;
|
|
87267
|
+
return;
|
|
87268
|
+
}
|
|
87269
|
+
const windowMs = Math.max(1, Date.now() - tuiPerfWindowStartedAt);
|
|
87270
|
+
const totals = {
|
|
87271
|
+
count: 0,
|
|
87272
|
+
bytes: 0,
|
|
87273
|
+
ms: 0,
|
|
87274
|
+
maxBytes: 0,
|
|
87275
|
+
maxMs: 0
|
|
87276
|
+
};
|
|
87277
|
+
const buckets = {};
|
|
87278
|
+
for (const [key, bucket] of [...tuiPerfBuckets.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
87279
|
+
totals.count += bucket.count;
|
|
87280
|
+
totals.bytes += bucket.bytes;
|
|
87281
|
+
totals.ms += bucket.ms;
|
|
87282
|
+
totals.maxBytes = Math.max(totals.maxBytes, bucket.maxBytes);
|
|
87283
|
+
totals.maxMs = Math.max(totals.maxMs, bucket.maxMs);
|
|
87284
|
+
buckets[key] = {
|
|
87285
|
+
...bucket,
|
|
87286
|
+
avg_bytes: bucket.count > 0 ? bucket.bytes / bucket.count : 0,
|
|
87287
|
+
avg_ms: bucket.count > 0 ? bucket.ms / bucket.count : 0
|
|
87288
|
+
};
|
|
87289
|
+
}
|
|
87290
|
+
try {
|
|
87291
|
+
const dir = dirname14(filePath);
|
|
87292
|
+
if (tuiPerfFileDirEnsured !== dir) {
|
|
87293
|
+
mkdirSync20(dir, { recursive: true });
|
|
87294
|
+
tuiPerfFileDirEnsured = dir;
|
|
87295
|
+
}
|
|
87296
|
+
appendFileSync3(filePath, `${JSON.stringify({
|
|
87297
|
+
ts: new Date().toISOString(),
|
|
87298
|
+
event: "tui_activity",
|
|
87299
|
+
window_ms: windowMs,
|
|
87300
|
+
totals,
|
|
87301
|
+
buckets
|
|
87302
|
+
})}
|
|
87303
|
+
`, { encoding: "utf8" });
|
|
87304
|
+
} catch (error) {
|
|
87305
|
+
if (!tuiPerfWarningEmitted) {
|
|
87306
|
+
tuiPerfWarningEmitted = true;
|
|
87307
|
+
console.error(`[TUI Perf] Failed to write LETTA_TUI_PERF_FILE=${filePath}`, error);
|
|
87308
|
+
}
|
|
87309
|
+
} finally {
|
|
87310
|
+
tuiPerfBuckets.clear();
|
|
87311
|
+
tuiPerfWindowStartedAt = 0;
|
|
87312
|
+
}
|
|
87313
|
+
}
|
|
87314
|
+
var TUI_PERF_FLUSH_INTERVAL_MS = 1000, TUI_PERF_ENV_VALUES, TUI_PERF_ENABLED, TUI_PERF_FILE, tuiPerfBuckets, tuiPerfFlushTimer = null, tuiPerfWindowStartedAt = 0, tuiPerfFileDirEnsured = null, tuiPerfWarningEmitted = false, tuiPerfExitHookRegistered = false;
|
|
87315
|
+
var init_tuiPerf = __esm(() => {
|
|
87316
|
+
TUI_PERF_ENV_VALUES = new Set(["1", "true", "yes"]);
|
|
87317
|
+
TUI_PERF_ENABLED = TUI_PERF_ENV_VALUES.has((process.env.LETTA_TUI_PERF ?? "").toLowerCase());
|
|
87318
|
+
TUI_PERF_FILE = process.env.LETTA_TUI_PERF_FILE?.trim() || null;
|
|
87319
|
+
tuiPerfBuckets = new Map;
|
|
87320
|
+
});
|
|
87321
|
+
|
|
87060
87322
|
// src/cli/helpers/chunkLog.ts
|
|
87061
87323
|
import {
|
|
87062
87324
|
existsSync as existsSync28,
|
|
87063
|
-
mkdirSync as
|
|
87325
|
+
mkdirSync as mkdirSync21,
|
|
87064
87326
|
readdirSync as readdirSync9,
|
|
87065
87327
|
unlinkSync as unlinkSync7,
|
|
87066
87328
|
writeFileSync as writeFileSync16
|
|
@@ -87161,7 +87423,7 @@ class ChunkLog {
|
|
|
87161
87423
|
return;
|
|
87162
87424
|
try {
|
|
87163
87425
|
if (!existsSync28(this.agentDir)) {
|
|
87164
|
-
|
|
87426
|
+
mkdirSync21(this.agentDir, { recursive: true });
|
|
87165
87427
|
}
|
|
87166
87428
|
this.dirCreated = true;
|
|
87167
87429
|
} catch (e) {
|
|
@@ -87400,6 +87662,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
87400
87662
|
}
|
|
87401
87663
|
try {
|
|
87402
87664
|
for await (const chunk of stream2) {
|
|
87665
|
+
recordTuiJsonPayload(`stream_chunk:${chunk.message_type ?? "unknown"}`, chunk);
|
|
87403
87666
|
if ((buffers.abortGeneration || 0) !== startAbortGen) {
|
|
87404
87667
|
stopReason = "cancelled";
|
|
87405
87668
|
queueMicrotask(refresh);
|
|
@@ -87455,6 +87718,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
87455
87718
|
shouldAccumulate = shouldOutputChunk;
|
|
87456
87719
|
}
|
|
87457
87720
|
if (shouldAccumulate) {
|
|
87721
|
+
recordTuiJsonPayload(`stream_accumulate:${chunk.message_type ?? "unknown"}`, chunk);
|
|
87458
87722
|
onChunk(buffers, chunk, contextTracker);
|
|
87459
87723
|
queueMicrotask(refresh);
|
|
87460
87724
|
}
|
|
@@ -87537,6 +87801,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
87537
87801
|
}
|
|
87538
87802
|
async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker, seenSeqIdThreshold) {
|
|
87539
87803
|
const overallStartTime = performance.now();
|
|
87804
|
+
recordTuiPerf("stream_lifecycle:start");
|
|
87540
87805
|
const streamRequestContext = getStreamRequestContext(stream2);
|
|
87541
87806
|
const streamOtid = streamRequestContext?.otid ?? null;
|
|
87542
87807
|
let _client;
|
|
@@ -87659,6 +87924,9 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
|
|
|
87659
87924
|
markCurrentLineAsFinished(buffers);
|
|
87660
87925
|
}
|
|
87661
87926
|
result.apiDurationMs = performance.now() - overallStartTime;
|
|
87927
|
+
recordTuiPerf(`stream_lifecycle:end:${result.stopReason}`, {
|
|
87928
|
+
ms: result.apiDurationMs
|
|
87929
|
+
});
|
|
87662
87930
|
return result;
|
|
87663
87931
|
}
|
|
87664
87932
|
var FALLBACK_RUN_DISCOVERY_TIMEOUT_MS = 5000;
|
|
@@ -87669,6 +87937,7 @@ var init_stream = __esm(async () => {
|
|
|
87669
87937
|
init_debug();
|
|
87670
87938
|
init_streamAbortRelay();
|
|
87671
87939
|
init_timing();
|
|
87940
|
+
init_tuiPerf();
|
|
87672
87941
|
init_chunkLog();
|
|
87673
87942
|
await __promiseAll([
|
|
87674
87943
|
init_message(),
|
|
@@ -88767,22 +89036,12 @@ function emitToolExecutionFinishedEvents(socket, runtime, params) {
|
|
|
88767
89036
|
}
|
|
88768
89037
|
function createToolExecutionOutputEmitter(socket, runtime, params) {
|
|
88769
89038
|
const outputByToolCallId = new Map;
|
|
88770
|
-
|
|
88771
|
-
if (!
|
|
89039
|
+
const emitToolOutput = (toolCallId, outputState) => {
|
|
89040
|
+
if (!outputState.dirty) {
|
|
88772
89041
|
return;
|
|
88773
89042
|
}
|
|
88774
|
-
|
|
88775
|
-
|
|
88776
|
-
messageId: `message-tool-return-stream-${toolCallId}`,
|
|
88777
|
-
stdout: "",
|
|
88778
|
-
stderr: ""
|
|
88779
|
-
};
|
|
88780
|
-
if (isStderr) {
|
|
88781
|
-
outputState.stderr = appendStreamingOutputWithCap(outputState.stderr, chunk);
|
|
88782
|
-
} else {
|
|
88783
|
-
outputState.stdout = appendStreamingOutputWithCap(outputState.stdout, chunk);
|
|
88784
|
-
}
|
|
88785
|
-
outputByToolCallId.set(toolCallId, outputState);
|
|
89043
|
+
outputState.dirty = false;
|
|
89044
|
+
outputState.lastEmittedAt = Date.now();
|
|
88786
89045
|
const stdout = normalizeStreamingOutputLines(outputState.stdout);
|
|
88787
89046
|
const stderr = normalizeStreamingOutputLines(outputState.stderr);
|
|
88788
89047
|
const toolReturn = [stdout?.join(`
|
|
@@ -88812,6 +89071,52 @@ function createToolExecutionOutputEmitter(socket, runtime, params) {
|
|
|
88812
89071
|
conversation_id: params.conversationId
|
|
88813
89072
|
});
|
|
88814
89073
|
};
|
|
89074
|
+
const flushToolOutput = (toolCallId, outputState) => {
|
|
89075
|
+
if (outputState.timer) {
|
|
89076
|
+
clearTimeout(outputState.timer);
|
|
89077
|
+
outputState.timer = null;
|
|
89078
|
+
}
|
|
89079
|
+
emitToolOutput(toolCallId, outputState);
|
|
89080
|
+
};
|
|
89081
|
+
const emitter = (toolCallId, chunk, isStderr = false) => {
|
|
89082
|
+
if (!toolCallId || chunk.length === 0) {
|
|
89083
|
+
return;
|
|
89084
|
+
}
|
|
89085
|
+
const existing = outputByToolCallId.get(toolCallId);
|
|
89086
|
+
const outputState = existing ?? {
|
|
89087
|
+
messageId: `message-tool-return-stream-${toolCallId}`,
|
|
89088
|
+
stdout: "",
|
|
89089
|
+
stderr: "",
|
|
89090
|
+
dirty: false,
|
|
89091
|
+
lastEmittedAt: 0,
|
|
89092
|
+
timer: null
|
|
89093
|
+
};
|
|
89094
|
+
if (isStderr) {
|
|
89095
|
+
outputState.stderr = appendStreamingOutputWithCap(outputState.stderr, chunk);
|
|
89096
|
+
} else {
|
|
89097
|
+
outputState.stdout = appendStreamingOutputWithCap(outputState.stdout, chunk);
|
|
89098
|
+
}
|
|
89099
|
+
outputByToolCallId.set(toolCallId, outputState);
|
|
89100
|
+
outputState.dirty = true;
|
|
89101
|
+
const now = Date.now();
|
|
89102
|
+
const elapsed = now - outputState.lastEmittedAt;
|
|
89103
|
+
if (elapsed >= STREAMING_TOOL_OUTPUT_EMIT_INTERVAL_MS) {
|
|
89104
|
+
flushToolOutput(toolCallId, outputState);
|
|
89105
|
+
return;
|
|
89106
|
+
}
|
|
89107
|
+
if (!outputState.timer) {
|
|
89108
|
+
outputState.timer = setTimeout(() => {
|
|
89109
|
+
outputState.timer = null;
|
|
89110
|
+
emitToolOutput(toolCallId, outputState);
|
|
89111
|
+
}, STREAMING_TOOL_OUTPUT_EMIT_INTERVAL_MS - elapsed);
|
|
89112
|
+
}
|
|
89113
|
+
};
|
|
89114
|
+
emitter.flush = () => {
|
|
89115
|
+
for (const [toolCallId, outputState] of outputByToolCallId.entries()) {
|
|
89116
|
+
flushToolOutput(toolCallId, outputState);
|
|
89117
|
+
}
|
|
89118
|
+
};
|
|
89119
|
+
return emitter;
|
|
88815
89120
|
}
|
|
88816
89121
|
function getInterruptApprovalsForEmission(runtime, params) {
|
|
88817
89122
|
if (params.lastExecutionResults && params.lastExecutionResults.length > 0) {
|
|
@@ -88929,7 +89234,7 @@ function stashRecoveredApprovalInterrupts(runtime, recovered) {
|
|
|
88929
89234
|
clearRecoveredApprovalState(runtime);
|
|
88930
89235
|
return true;
|
|
88931
89236
|
}
|
|
88932
|
-
var INTERRUPT_TOOL_RETURN_MAX_CHARS, STREAMING_TOOL_OUTPUT_MAX_CHARS;
|
|
89237
|
+
var INTERRUPT_TOOL_RETURN_MAX_CHARS, STREAMING_TOOL_OUTPUT_MAX_CHARS, STREAMING_TOOL_OUTPUT_EMIT_INTERVAL_MS = 100;
|
|
88933
89238
|
var init_interrupts = __esm(async () => {
|
|
88934
89239
|
init_approval_result_normalization();
|
|
88935
89240
|
init_constants();
|
|
@@ -89766,16 +90071,21 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
89766
90071
|
runtime.currentToolsetPreference = preparedToolContext.toolsetPreference;
|
|
89767
90072
|
runtime.currentLoadedTools = preparedToolContext.preparedToolContext.loadedToolNames;
|
|
89768
90073
|
try {
|
|
89769
|
-
|
|
89770
|
-
|
|
89771
|
-
|
|
89772
|
-
|
|
89773
|
-
|
|
89774
|
-
|
|
89775
|
-
|
|
89776
|
-
|
|
89777
|
-
|
|
89778
|
-
|
|
90074
|
+
let approvalResults;
|
|
90075
|
+
try {
|
|
90076
|
+
approvalResults = await executeApprovalBatch(decisions, undefined, {
|
|
90077
|
+
abortSignal: recoveryAbortController.signal,
|
|
90078
|
+
onStreamingOutput: emitToolExecutionOutput,
|
|
90079
|
+
toolContextId: preparedToolContext.preparedToolContext.contextId,
|
|
90080
|
+
workingDirectory,
|
|
90081
|
+
parentScope: recovered.agentId && recovered.conversationId ? {
|
|
90082
|
+
agentId: recovered.agentId,
|
|
90083
|
+
conversationId: recovered.conversationId
|
|
90084
|
+
} : undefined
|
|
90085
|
+
});
|
|
90086
|
+
} finally {
|
|
90087
|
+
emitToolExecutionOutput.flush();
|
|
90088
|
+
}
|
|
89779
90089
|
emitToolExecutionFinishedEvents(socket, runtime, {
|
|
89780
90090
|
approvals: approvalResults,
|
|
89781
90091
|
runId: runtime.activeRunId ?? undefined,
|
|
@@ -89789,7 +90099,8 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
89789
90099
|
const continuationMessages = [
|
|
89790
90100
|
{
|
|
89791
90101
|
type: "approval",
|
|
89792
|
-
approvals: approvalResults
|
|
90102
|
+
approvals: approvalResults,
|
|
90103
|
+
otid: crypto.randomUUID()
|
|
89793
90104
|
}
|
|
89794
90105
|
];
|
|
89795
90106
|
let continuationBatchId = `batch-recovered-${crypto.randomUUID()}`;
|
|
@@ -90183,6 +90494,18 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
90183
90494
|
retryAfterMs
|
|
90184
90495
|
});
|
|
90185
90496
|
transientRetries = attempt;
|
|
90497
|
+
const retryMessage = getRetryStatusMessage(errorDetail);
|
|
90498
|
+
if (retryMessage) {
|
|
90499
|
+
emitRetryDelta(socket, runtime, {
|
|
90500
|
+
message: retryMessage,
|
|
90501
|
+
reason: "error",
|
|
90502
|
+
attempt,
|
|
90503
|
+
maxAttempts: LLM_API_ERROR_MAX_RETRIES,
|
|
90504
|
+
delayMs,
|
|
90505
|
+
agentId: runtime.agentId ?? undefined,
|
|
90506
|
+
conversationId
|
|
90507
|
+
});
|
|
90508
|
+
}
|
|
90186
90509
|
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
90187
90510
|
if (abortSignal?.aborted) {
|
|
90188
90511
|
throw new Error("Cancelled by user");
|
|
@@ -90228,6 +90551,15 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
90228
90551
|
category: "conversation_busy",
|
|
90229
90552
|
attempt: conversationBusyRetries
|
|
90230
90553
|
});
|
|
90554
|
+
emitRetryDelta(socket, runtime, {
|
|
90555
|
+
message: "Conversation is busy, waiting and retrying…",
|
|
90556
|
+
reason: "error",
|
|
90557
|
+
attempt: conversationBusyRetries,
|
|
90558
|
+
maxAttempts: MAX_CONVERSATION_BUSY_RETRIES,
|
|
90559
|
+
delayMs: retryDelayMs,
|
|
90560
|
+
agentId: runtime.agentId ?? undefined,
|
|
90561
|
+
conversationId
|
|
90562
|
+
});
|
|
90231
90563
|
await new Promise((resolve27) => setTimeout(resolve27, retryDelayMs));
|
|
90232
90564
|
if (abortSignal?.aborted) {
|
|
90233
90565
|
throw new Error("Cancelled by user");
|
|
@@ -92584,14 +92916,19 @@ async function handleApprovalStop(params) {
|
|
|
92584
92916
|
}));
|
|
92585
92917
|
}
|
|
92586
92918
|
};
|
|
92587
|
-
|
|
92588
|
-
|
|
92589
|
-
|
|
92590
|
-
|
|
92591
|
-
|
|
92592
|
-
|
|
92593
|
-
|
|
92594
|
-
|
|
92919
|
+
let executionResults;
|
|
92920
|
+
try {
|
|
92921
|
+
executionResults = await executeApprovalBatch(decisions, undefined, {
|
|
92922
|
+
toolContextId: turnToolContextId ?? undefined,
|
|
92923
|
+
abortSignal: abortController.signal,
|
|
92924
|
+
onStreamingOutput: emitToolExecutionOutput,
|
|
92925
|
+
workingDirectory: turnWorkingDirectory,
|
|
92926
|
+
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined,
|
|
92927
|
+
onFileWrite
|
|
92928
|
+
});
|
|
92929
|
+
} finally {
|
|
92930
|
+
emitToolExecutionOutput.flush();
|
|
92931
|
+
}
|
|
92595
92932
|
const persistedExecutionResults = normalizeExecutionResultsForInterruptParity(runtime, executionResults, lastExecutingToolCallIds);
|
|
92596
92933
|
validateApprovalResultIds(decisions.map((decision) => ({
|
|
92597
92934
|
approval: {
|
|
@@ -92612,7 +92949,8 @@ async function handleApprovalStop(params) {
|
|
|
92612
92949
|
const nextInput = [
|
|
92613
92950
|
{
|
|
92614
92951
|
type: "approval",
|
|
92615
|
-
approvals: persistedExecutionResults
|
|
92952
|
+
approvals: persistedExecutionResults,
|
|
92953
|
+
otid: crypto.randomUUID()
|
|
92616
92954
|
}
|
|
92617
92955
|
];
|
|
92618
92956
|
let continuationBatchId = dequeuedBatchId;
|
|
@@ -93772,7 +94110,115 @@ var init_commands = __esm(async () => {
|
|
|
93772
94110
|
});
|
|
93773
94111
|
|
|
93774
94112
|
// src/websocket/listener/protocol-outbound.ts
|
|
94113
|
+
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync22 } from "node:fs";
|
|
94114
|
+
import { dirname as dirname15 } from "node:path";
|
|
94115
|
+
import { performance as performance2 } from "node:perf_hooks";
|
|
93775
94116
|
import WebSocket3 from "ws";
|
|
94117
|
+
function getProtocolPerfKey(message) {
|
|
94118
|
+
if (message.type === "stream_delta" && "delta" in message) {
|
|
94119
|
+
const delta = message.delta;
|
|
94120
|
+
return `${message.type}:${String(delta.message_type ?? "unknown")}`;
|
|
94121
|
+
}
|
|
94122
|
+
return message.type;
|
|
94123
|
+
}
|
|
94124
|
+
function scheduleProtocolPerfFlush() {
|
|
94125
|
+
if (protocolPerfFlushTimer) {
|
|
94126
|
+
return;
|
|
94127
|
+
}
|
|
94128
|
+
protocolPerfFlushTimer = setTimeout(() => {
|
|
94129
|
+
protocolPerfFlushTimer = null;
|
|
94130
|
+
flushProtocolPerfTelemetry();
|
|
94131
|
+
}, PROTOCOL_PERF_FLUSH_INTERVAL_MS);
|
|
94132
|
+
const timerWithUnref = protocolPerfFlushTimer;
|
|
94133
|
+
timerWithUnref.unref?.();
|
|
94134
|
+
}
|
|
94135
|
+
function recordProtocolPerfTelemetry(key, sample) {
|
|
94136
|
+
if (protocolPerfWindowStartedAt === 0) {
|
|
94137
|
+
protocolPerfWindowStartedAt = Date.now();
|
|
94138
|
+
}
|
|
94139
|
+
const bucket = protocolPerfBuckets.get(key) ?? {
|
|
94140
|
+
count: 0,
|
|
94141
|
+
bytes: 0,
|
|
94142
|
+
stringifyMs: 0,
|
|
94143
|
+
sendMs: 0,
|
|
94144
|
+
maxBufferedBefore: 0,
|
|
94145
|
+
maxBufferedAfter: 0
|
|
94146
|
+
};
|
|
94147
|
+
bucket.count += 1;
|
|
94148
|
+
bucket.bytes += sample.bytes;
|
|
94149
|
+
bucket.stringifyMs += sample.stringifyMs;
|
|
94150
|
+
bucket.sendMs += sample.sendMs;
|
|
94151
|
+
bucket.maxBufferedBefore = Math.max(bucket.maxBufferedBefore, sample.bufferedBefore);
|
|
94152
|
+
bucket.maxBufferedAfter = Math.max(bucket.maxBufferedAfter, sample.bufferedAfter);
|
|
94153
|
+
protocolPerfBuckets.set(key, bucket);
|
|
94154
|
+
scheduleProtocolPerfFlush();
|
|
94155
|
+
}
|
|
94156
|
+
function writeProtocolPerfFile(record, fallbackLine) {
|
|
94157
|
+
const filePath = PROTOCOL_PERF_FILE;
|
|
94158
|
+
if (!filePath) {
|
|
94159
|
+
console.error(fallbackLine);
|
|
94160
|
+
return;
|
|
94161
|
+
}
|
|
94162
|
+
try {
|
|
94163
|
+
const dir = dirname15(filePath);
|
|
94164
|
+
if (protocolPerfFileDirEnsured !== dir) {
|
|
94165
|
+
mkdirSync22(dir, { recursive: true });
|
|
94166
|
+
protocolPerfFileDirEnsured = dir;
|
|
94167
|
+
}
|
|
94168
|
+
appendFileSync4(filePath, `${JSON.stringify(record)}
|
|
94169
|
+
`, {
|
|
94170
|
+
encoding: "utf8"
|
|
94171
|
+
});
|
|
94172
|
+
} catch (error) {
|
|
94173
|
+
if (!protocolPerfFileWarningEmitted) {
|
|
94174
|
+
protocolPerfFileWarningEmitted = true;
|
|
94175
|
+
console.error(`[Listen Perf] Failed to write LETTA_LISTENER_PERF_FILE=${filePath}`, error);
|
|
94176
|
+
}
|
|
94177
|
+
console.error(fallbackLine);
|
|
94178
|
+
}
|
|
94179
|
+
}
|
|
94180
|
+
function flushProtocolPerfTelemetry() {
|
|
94181
|
+
if (protocolPerfBuckets.size === 0) {
|
|
94182
|
+
protocolPerfWindowStartedAt = 0;
|
|
94183
|
+
return;
|
|
94184
|
+
}
|
|
94185
|
+
const windowMs = Math.max(1, Date.now() - protocolPerfWindowStartedAt);
|
|
94186
|
+
const totals = {
|
|
94187
|
+
count: 0,
|
|
94188
|
+
bytes: 0,
|
|
94189
|
+
stringifyMs: 0,
|
|
94190
|
+
sendMs: 0,
|
|
94191
|
+
maxBufferedBefore: 0,
|
|
94192
|
+
maxBufferedAfter: 0
|
|
94193
|
+
};
|
|
94194
|
+
const buckets = {};
|
|
94195
|
+
const parts = [...protocolPerfBuckets.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([key, bucket]) => {
|
|
94196
|
+
totals.count += bucket.count;
|
|
94197
|
+
totals.bytes += bucket.bytes;
|
|
94198
|
+
totals.stringifyMs += bucket.stringifyMs;
|
|
94199
|
+
totals.sendMs += bucket.sendMs;
|
|
94200
|
+
totals.maxBufferedBefore = Math.max(totals.maxBufferedBefore, bucket.maxBufferedBefore);
|
|
94201
|
+
totals.maxBufferedAfter = Math.max(totals.maxBufferedAfter, bucket.maxBufferedAfter);
|
|
94202
|
+
buckets[key] = {
|
|
94203
|
+
...bucket,
|
|
94204
|
+
avg_bytes: bucket.count > 0 ? bucket.bytes / bucket.count : 0,
|
|
94205
|
+
avg_stringify_ms: bucket.count > 0 ? bucket.stringifyMs / bucket.count : 0,
|
|
94206
|
+
avg_send_ms: bucket.count > 0 ? bucket.sendMs / bucket.count : 0
|
|
94207
|
+
};
|
|
94208
|
+
const stringifyMs = bucket.stringifyMs.toFixed(2);
|
|
94209
|
+
const sendMs = bucket.sendMs.toFixed(2);
|
|
94210
|
+
return `${key}{count=${bucket.count},bytes=${bucket.bytes},stringify_ms=${stringifyMs},send_ms=${sendMs},max_buffered_before=${bucket.maxBufferedBefore},max_buffered_after=${bucket.maxBufferedAfter}}`;
|
|
94211
|
+
});
|
|
94212
|
+
writeProtocolPerfFile({
|
|
94213
|
+
ts: new Date().toISOString(),
|
|
94214
|
+
event: "protocol_emit",
|
|
94215
|
+
window_ms: windowMs,
|
|
94216
|
+
totals,
|
|
94217
|
+
buckets
|
|
94218
|
+
}, `[Listen Perf] protocol_emit window_ms=${windowMs} ${parts.join(" ")}`);
|
|
94219
|
+
protocolPerfBuckets.clear();
|
|
94220
|
+
protocolPerfWindowStartedAt = 0;
|
|
94221
|
+
}
|
|
93776
94222
|
function getCachedDeviceGitContext(cwd2) {
|
|
93777
94223
|
const now = Date.now();
|
|
93778
94224
|
const cached = gitContextCache.get(cwd2);
|
|
@@ -93979,8 +94425,24 @@ function emitProtocolV2Message(socket, runtime, message, scope) {
|
|
|
93979
94425
|
emitted_at: new Date().toISOString(),
|
|
93980
94426
|
idempotency_key: `${message.type}:${eventSeq}:${crypto.randomUUID()}`
|
|
93981
94427
|
};
|
|
94428
|
+
const perfEnabled = PROTOCOL_PERF_ENABLED;
|
|
94429
|
+
const stringifyStartedAt = perfEnabled ? performance2.now() : 0;
|
|
94430
|
+
let payload;
|
|
93982
94431
|
try {
|
|
93983
|
-
|
|
94432
|
+
payload = JSON.stringify(outbound);
|
|
94433
|
+
const stringifyMs = perfEnabled ? performance2.now() - stringifyStartedAt : 0;
|
|
94434
|
+
const bufferedBefore = perfEnabled ? socket.bufferedAmount : 0;
|
|
94435
|
+
const sendStartedAt = perfEnabled ? performance2.now() : 0;
|
|
94436
|
+
socket.send(payload);
|
|
94437
|
+
if (perfEnabled) {
|
|
94438
|
+
recordProtocolPerfTelemetry(getProtocolPerfKey(message), {
|
|
94439
|
+
bytes: Buffer.byteLength(payload),
|
|
94440
|
+
stringifyMs,
|
|
94441
|
+
sendMs: performance2.now() - sendStartedAt,
|
|
94442
|
+
bufferedBefore,
|
|
94443
|
+
bufferedAfter: socket.bufferedAmount
|
|
94444
|
+
});
|
|
94445
|
+
}
|
|
93984
94446
|
} catch (error) {
|
|
93985
94447
|
console.error(`[Listen V2] Failed to emit ${message.type} (seq=${eventSeq})`, error);
|
|
93986
94448
|
safeEmitWsEvent("send", "lifecycle", {
|
|
@@ -94214,7 +94676,7 @@ function emitStreamDelta(socket, runtime, delta, scope, subagentId) {
|
|
|
94214
94676
|
};
|
|
94215
94677
|
emitProtocolV2Message(socket, runtime, message, scope);
|
|
94216
94678
|
}
|
|
94217
|
-
var GIT_CONTEXT_CACHE_TTL_MS = 15000, MAX_GIT_CONTEXT_CACHE_ENTRIES = 64, gitContextCache;
|
|
94679
|
+
var GIT_CONTEXT_CACHE_TTL_MS = 15000, MAX_GIT_CONTEXT_CACHE_ENTRIES = 64, PROTOCOL_PERF_FLUSH_INTERVAL_MS = 1000, PROTOCOL_PERF_ENV_VALUES, PROTOCOL_PERF_ENABLED, PROTOCOL_PERF_FILE, protocolPerfBuckets, protocolPerfFlushTimer = null, protocolPerfWindowStartedAt = 0, protocolPerfFileDirEnsured = null, protocolPerfFileWarningEmitted = false, gitContextCache;
|
|
94218
94680
|
var init_protocol_outbound = __esm(async () => {
|
|
94219
94681
|
init_memoryFilesystem();
|
|
94220
94682
|
init_gitContext();
|
|
@@ -94230,6 +94692,10 @@ var init_protocol_outbound = __esm(async () => {
|
|
|
94230
94692
|
init_permissionMode();
|
|
94231
94693
|
init_runtime4();
|
|
94232
94694
|
await init_commands();
|
|
94695
|
+
PROTOCOL_PERF_ENV_VALUES = new Set(["1", "true", "yes"]);
|
|
94696
|
+
PROTOCOL_PERF_ENABLED = PROTOCOL_PERF_ENV_VALUES.has((process.env.LETTA_LISTENER_PERF ?? "").toLowerCase());
|
|
94697
|
+
PROTOCOL_PERF_FILE = process.env.LETTA_LISTENER_PERF_FILE?.trim() || null;
|
|
94698
|
+
protocolPerfBuckets = new Map;
|
|
94233
94699
|
gitContextCache = new Map;
|
|
94234
94700
|
});
|
|
94235
94701
|
|
|
@@ -97429,7 +97895,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
97429
97895
|
const {
|
|
97430
97896
|
existsSync: existsSync30,
|
|
97431
97897
|
lstatSync: lstatSync2,
|
|
97432
|
-
mkdirSync:
|
|
97898
|
+
mkdirSync: mkdirSync23,
|
|
97433
97899
|
rmdirSync,
|
|
97434
97900
|
symlinkSync,
|
|
97435
97901
|
unlinkSync: unlinkSync8
|
|
@@ -97460,7 +97926,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
97460
97926
|
}
|
|
97461
97927
|
const linkName = basename13(parsed.skill_path);
|
|
97462
97928
|
const linkPath = join34(globalSkillsDir, linkName);
|
|
97463
|
-
|
|
97929
|
+
mkdirSync23(globalSkillsDir, { recursive: true });
|
|
97464
97930
|
if (existsSync30(linkPath)) {
|
|
97465
97931
|
const stat7 = lstatSync2(linkPath);
|
|
97466
97932
|
if (stat7.isSymbolicLink()) {
|
|
@@ -99660,9 +100126,9 @@ __export(exports_debug2, {
|
|
|
99660
100126
|
debugLog: () => debugLog3
|
|
99661
100127
|
});
|
|
99662
100128
|
import {
|
|
99663
|
-
appendFileSync as
|
|
100129
|
+
appendFileSync as appendFileSync5,
|
|
99664
100130
|
existsSync as existsSync31,
|
|
99665
|
-
mkdirSync as
|
|
100131
|
+
mkdirSync as mkdirSync24,
|
|
99666
100132
|
readdirSync as readdirSync11,
|
|
99667
100133
|
readFileSync as readFileSync22,
|
|
99668
100134
|
unlinkSync as unlinkSync8
|
|
@@ -99683,7 +100149,7 @@ function printDebugLine2(line, level = "log") {
|
|
|
99683
100149
|
const debugFile = getDebugFile2();
|
|
99684
100150
|
if (debugFile) {
|
|
99685
100151
|
try {
|
|
99686
|
-
|
|
100152
|
+
appendFileSync5(debugFile, line, { encoding: "utf8" });
|
|
99687
100153
|
return;
|
|
99688
100154
|
} catch {}
|
|
99689
100155
|
}
|
|
@@ -99709,7 +100175,7 @@ class DebugLogFile2 {
|
|
|
99709
100175
|
return;
|
|
99710
100176
|
this.ensureDir();
|
|
99711
100177
|
try {
|
|
99712
|
-
|
|
100178
|
+
appendFileSync5(this.logPath, line, { encoding: "utf8" });
|
|
99713
100179
|
} catch {}
|
|
99714
100180
|
}
|
|
99715
100181
|
getTail(maxLines = DEFAULT_TAIL_LINES2) {
|
|
@@ -99732,7 +100198,7 @@ class DebugLogFile2 {
|
|
|
99732
100198
|
return;
|
|
99733
100199
|
try {
|
|
99734
100200
|
if (!existsSync31(this.agentDir)) {
|
|
99735
|
-
|
|
100201
|
+
mkdirSync24(this.agentDir, { recursive: true });
|
|
99736
100202
|
}
|
|
99737
100203
|
this.dirCreated = true;
|
|
99738
100204
|
} catch {}
|
|
@@ -99802,10 +100268,10 @@ __export(exports_skills2, {
|
|
|
99802
100268
|
});
|
|
99803
100269
|
import { existsSync as existsSync32 } from "node:fs";
|
|
99804
100270
|
import { readdir as readdir8, readFile as readFile13, realpath as realpath4, stat as stat7 } from "node:fs/promises";
|
|
99805
|
-
import { dirname as
|
|
100271
|
+
import { dirname as dirname16, join as join38 } from "node:path";
|
|
99806
100272
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
99807
100273
|
function getBundledSkillsPath2() {
|
|
99808
|
-
const thisDir =
|
|
100274
|
+
const thisDir = dirname16(fileURLToPath9(import.meta.url));
|
|
99809
100275
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
99810
100276
|
return join38(thisDir, "../skills/builtin");
|
|
99811
100277
|
}
|
|
@@ -99999,16 +100465,16 @@ import {
|
|
|
99999
100465
|
existsSync as existsSync33,
|
|
100000
100466
|
readFileSync as fsReadFileSync2,
|
|
100001
100467
|
writeFileSync as fsWriteFileSync2,
|
|
100002
|
-
mkdirSync as
|
|
100468
|
+
mkdirSync as mkdirSync25
|
|
100003
100469
|
} from "node:fs";
|
|
100004
|
-
import { dirname as
|
|
100470
|
+
import { dirname as dirname17 } from "node:path";
|
|
100005
100471
|
async function readFile14(path26) {
|
|
100006
100472
|
return fsReadFileSync2(path26, { encoding: "utf-8" });
|
|
100007
100473
|
}
|
|
100008
100474
|
async function writeFile12(path26, content) {
|
|
100009
|
-
const dir =
|
|
100475
|
+
const dir = dirname17(path26);
|
|
100010
100476
|
if (!existsSync33(dir)) {
|
|
100011
|
-
|
|
100477
|
+
mkdirSync25(dir, { recursive: true });
|
|
100012
100478
|
}
|
|
100013
100479
|
fsWriteFileSync2(path26, content, { encoding: "utf-8", flush: true });
|
|
100014
100480
|
}
|
|
@@ -100016,7 +100482,7 @@ function exists2(path26) {
|
|
|
100016
100482
|
return existsSync33(path26);
|
|
100017
100483
|
}
|
|
100018
100484
|
async function mkdir9(path26, options) {
|
|
100019
|
-
|
|
100485
|
+
mkdirSync25(path26, options);
|
|
100020
100486
|
}
|
|
100021
100487
|
async function readJsonFile(path26) {
|
|
100022
100488
|
const text = await readFile14(path26);
|
|
@@ -100149,7 +100615,7 @@ var exports_bootstrap_tools = {};
|
|
|
100149
100615
|
__export(exports_bootstrap_tools, {
|
|
100150
100616
|
bootstrapBaseToolsIfNeeded: () => bootstrapBaseToolsIfNeeded
|
|
100151
100617
|
});
|
|
100152
|
-
import { existsSync as existsSync34, mkdirSync as
|
|
100618
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync26, writeFileSync as writeFileSync17 } from "node:fs";
|
|
100153
100619
|
import { homedir as homedir27 } from "node:os";
|
|
100154
100620
|
import { join as join39 } from "node:path";
|
|
100155
100621
|
async function bootstrapBaseToolsIfNeeded() {
|
|
@@ -100159,7 +100625,7 @@ async function bootstrapBaseToolsIfNeeded() {
|
|
|
100159
100625
|
try {
|
|
100160
100626
|
const success = await addBaseToolsToServer();
|
|
100161
100627
|
if (success) {
|
|
100162
|
-
|
|
100628
|
+
mkdirSync26(join39(homedir27(), ".letta"), { recursive: true });
|
|
100163
100629
|
writeFileSync17(MARKER_PATH, new Date().toISOString(), "utf-8");
|
|
100164
100630
|
}
|
|
100165
100631
|
} catch (err) {
|
|
@@ -101863,7 +102329,7 @@ __export(exports_import, {
|
|
|
101863
102329
|
});
|
|
101864
102330
|
import { createReadStream } from "node:fs";
|
|
101865
102331
|
import { chmod, mkdir as mkdir10, readFile as readFile15, writeFile as writeFile13 } from "node:fs/promises";
|
|
101866
|
-
import { dirname as
|
|
102332
|
+
import { dirname as dirname18, resolve as resolve30 } from "node:path";
|
|
101867
102333
|
async function importAgentFromFile(options) {
|
|
101868
102334
|
const client = await getClient();
|
|
101869
102335
|
const resolvedPath = resolve30(options.filePath);
|
|
@@ -101922,7 +102388,7 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
101922
102388
|
}
|
|
101923
102389
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
101924
102390
|
const fullPath = resolve30(skillDir, filePath);
|
|
101925
|
-
await mkdir10(
|
|
102391
|
+
await mkdir10(dirname18(fullPath), { recursive: true });
|
|
101926
102392
|
await writeFile13(fullPath, content, "utf-8");
|
|
101927
102393
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
101928
102394
|
if (isScript) {
|
|
@@ -102276,6 +102742,15 @@ async function flushAndExit(code) {
|
|
|
102276
102742
|
]);
|
|
102277
102743
|
process.exit(code);
|
|
102278
102744
|
}
|
|
102745
|
+
async function writeFinalHeadlessStdout(text) {
|
|
102746
|
+
await new Promise((resolve31) => {
|
|
102747
|
+
if (process.stdout.destroyed || process.stdout.writableEnded) {
|
|
102748
|
+
resolve31();
|
|
102749
|
+
return;
|
|
102750
|
+
}
|
|
102751
|
+
process.stdout.write(text, () => resolve31());
|
|
102752
|
+
});
|
|
102753
|
+
}
|
|
102279
102754
|
async function handleHeadlessCommand(parsedArgs, model, skillsDirectoryOverride, skillSourcesOverride, systemInfoReminderEnabledOverride) {
|
|
102280
102755
|
const { values, positionals } = parsedArgs;
|
|
102281
102756
|
telemetry.setSurface("headless");
|
|
@@ -103734,7 +104209,8 @@ ${loadedContents.join(`
|
|
|
103734
104209
|
conversation_id: conversationId,
|
|
103735
104210
|
usage
|
|
103736
104211
|
};
|
|
103737
|
-
|
|
104212
|
+
await writeFinalHeadlessStdout(`${JSON.stringify(output, null, 2)}
|
|
104213
|
+
`);
|
|
103738
104214
|
} else if (outputFormat === "stream-json") {
|
|
103739
104215
|
const allRunIds = new Set;
|
|
103740
104216
|
for (const line of toLines(buffers)) {
|
|
@@ -103763,7 +104239,8 @@ ${loadedContents.join(`
|
|
|
103763
104239
|
console.error("No assistant response found");
|
|
103764
104240
|
await exitHeadless(1, "headless_missing_result_text");
|
|
103765
104241
|
}
|
|
103766
|
-
|
|
104242
|
+
await writeFinalHeadlessStdout(`${resultText}
|
|
104243
|
+
`);
|
|
103767
104244
|
}
|
|
103768
104245
|
markMilestone("HEADLESS_COMPLETE");
|
|
103769
104246
|
reportAllMilestones();
|
|
@@ -124566,7 +125043,7 @@ html.dark .agent-name { color: var(--text-dim); }
|
|
|
124566
125043
|
var init_plan_viewer_template = () => {};
|
|
124567
125044
|
|
|
124568
125045
|
// src/web/generate-plan-viewer.ts
|
|
124569
|
-
import { chmodSync as chmodSync2, existsSync as existsSync37, mkdirSync as
|
|
125046
|
+
import { chmodSync as chmodSync2, existsSync as existsSync37, mkdirSync as mkdirSync29, writeFileSync as writeFileSync20 } from "node:fs";
|
|
124570
125047
|
import { homedir as homedir31 } from "node:os";
|
|
124571
125048
|
import { join as join44 } from "node:path";
|
|
124572
125049
|
async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
@@ -124579,7 +125056,7 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
|
124579
125056
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
124580
125057
|
const html = plan_viewer_template_default.replace("<!--LETTA_PLAN_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
124581
125058
|
if (!existsSync37(VIEWERS_DIR)) {
|
|
124582
|
-
|
|
125059
|
+
mkdirSync29(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
124583
125060
|
}
|
|
124584
125061
|
try {
|
|
124585
125062
|
chmodSync2(VIEWERS_DIR, 448);
|
|
@@ -127889,12 +128366,12 @@ __export(exports_terminalKeybindingInstaller, {
|
|
|
127889
128366
|
import {
|
|
127890
128367
|
copyFileSync,
|
|
127891
128368
|
existsSync as existsSync39,
|
|
127892
|
-
mkdirSync as
|
|
128369
|
+
mkdirSync as mkdirSync30,
|
|
127893
128370
|
readFileSync as readFileSync25,
|
|
127894
128371
|
writeFileSync as writeFileSync21
|
|
127895
128372
|
} from "node:fs";
|
|
127896
128373
|
import { homedir as homedir32, platform as platform6 } from "node:os";
|
|
127897
|
-
import { dirname as
|
|
128374
|
+
import { dirname as dirname19, join as join46 } from "node:path";
|
|
127898
128375
|
function detectTerminalType() {
|
|
127899
128376
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
127900
128377
|
return "cursor";
|
|
@@ -127985,9 +128462,9 @@ function installKeybinding(keybindingsPath) {
|
|
|
127985
128462
|
if (keybindingExists(keybindingsPath)) {
|
|
127986
128463
|
return { success: true, alreadyExists: true };
|
|
127987
128464
|
}
|
|
127988
|
-
const parentDir =
|
|
128465
|
+
const parentDir = dirname19(keybindingsPath);
|
|
127989
128466
|
if (!existsSync39(parentDir)) {
|
|
127990
|
-
|
|
128467
|
+
mkdirSync30(parentDir, { recursive: true });
|
|
127991
128468
|
}
|
|
127992
128469
|
let keybindings = [];
|
|
127993
128470
|
let backupPath = null;
|
|
@@ -128144,9 +128621,9 @@ return config`);
|
|
|
128144
128621
|
${WEZTERM_DELETE_FIX}
|
|
128145
128622
|
`;
|
|
128146
128623
|
}
|
|
128147
|
-
const parentDir =
|
|
128624
|
+
const parentDir = dirname19(configPath);
|
|
128148
128625
|
if (!existsSync39(parentDir)) {
|
|
128149
|
-
|
|
128626
|
+
mkdirSync30(parentDir, { recursive: true });
|
|
128150
128627
|
}
|
|
128151
128628
|
writeFileSync21(configPath, content, { encoding: "utf-8" });
|
|
128152
128629
|
return {
|
|
@@ -128744,7 +129221,7 @@ __export(exports_custom, {
|
|
|
128744
129221
|
});
|
|
128745
129222
|
import { existsSync as existsSync40 } from "node:fs";
|
|
128746
129223
|
import { readdir as readdir10, readFile as readFile16 } from "node:fs/promises";
|
|
128747
|
-
import { basename as basename14, dirname as
|
|
129224
|
+
import { basename as basename14, dirname as dirname20, join as join47 } from "node:path";
|
|
128748
129225
|
async function getCustomCommands() {
|
|
128749
129226
|
if (cachedCommands !== null) {
|
|
128750
129227
|
return cachedCommands;
|
|
@@ -128805,7 +129282,7 @@ async function parseCommandFile(filePath, rootPath, source2) {
|
|
|
128805
129282
|
const content = await readFile16(filePath, "utf-8");
|
|
128806
129283
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
128807
129284
|
const id = basename14(filePath, ".md");
|
|
128808
|
-
const relativePath =
|
|
129285
|
+
const relativePath = dirname20(filePath).slice(rootPath.length);
|
|
128809
129286
|
const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
|
|
128810
129287
|
let description = getStringField(frontmatter, "description");
|
|
128811
129288
|
if (!description) {
|
|
@@ -133965,14 +134442,14 @@ var init_InputRich = __esm(async () => {
|
|
|
133965
134442
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
133966
134443
|
import {
|
|
133967
134444
|
existsSync as existsSync41,
|
|
133968
|
-
mkdirSync as
|
|
134445
|
+
mkdirSync as mkdirSync31,
|
|
133969
134446
|
mkdtempSync,
|
|
133970
134447
|
readFileSync as readFileSync26,
|
|
133971
134448
|
rmSync as rmSync4,
|
|
133972
134449
|
writeFileSync as writeFileSync22
|
|
133973
134450
|
} from "node:fs";
|
|
133974
134451
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
133975
|
-
import { dirname as
|
|
134452
|
+
import { dirname as dirname21, join as join49 } from "node:path";
|
|
133976
134453
|
function runCommand(command, args, cwd2, input) {
|
|
133977
134454
|
try {
|
|
133978
134455
|
return execFileSync4(command, args, {
|
|
@@ -134219,8 +134696,8 @@ function runGit3(args, cwd2) {
|
|
|
134219
134696
|
}
|
|
134220
134697
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
134221
134698
|
const absolutePath = join49(repoDir, workflowPath);
|
|
134222
|
-
if (!existsSync41(
|
|
134223
|
-
|
|
134699
|
+
if (!existsSync41(dirname21(absolutePath))) {
|
|
134700
|
+
mkdirSync31(dirname21(absolutePath), { recursive: true });
|
|
134224
134701
|
}
|
|
134225
134702
|
const next = `${content.trimEnd()}
|
|
134226
134703
|
`;
|
|
@@ -138462,7 +138939,7 @@ __export(exports_generate_memory_viewer, {
|
|
|
138462
138939
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
138463
138940
|
});
|
|
138464
138941
|
import { execFile as execFileCb3 } from "node:child_process";
|
|
138465
|
-
import { chmodSync as chmodSync3, existsSync as existsSync42, mkdirSync as
|
|
138942
|
+
import { chmodSync as chmodSync3, existsSync as existsSync42, mkdirSync as mkdirSync32, writeFileSync as writeFileSync23 } from "node:fs";
|
|
138466
138943
|
import { homedir as homedir34 } from "node:os";
|
|
138467
138944
|
import { join as join50 } from "node:path";
|
|
138468
138945
|
import { promisify as promisify13 } from "node:util";
|
|
@@ -138783,7 +139260,7 @@ async function generateAndOpenMemoryViewer(agentId, options) {
|
|
|
138783
139260
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
138784
139261
|
const html = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
138785
139262
|
if (!existsSync42(VIEWERS_DIR2)) {
|
|
138786
|
-
|
|
139263
|
+
mkdirSync32(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
138787
139264
|
}
|
|
138788
139265
|
try {
|
|
138789
139266
|
chmodSync3(VIEWERS_DIR2, 448);
|
|
@@ -142593,7 +143070,7 @@ function formatDuration3(ms) {
|
|
|
142593
143070
|
}
|
|
142594
143071
|
return `${(ms / 1000).toFixed(1)}s`;
|
|
142595
143072
|
}
|
|
142596
|
-
function
|
|
143073
|
+
function formatNumber2(n) {
|
|
142597
143074
|
return n.toLocaleString();
|
|
142598
143075
|
}
|
|
142599
143076
|
function formatUsageStats({
|
|
@@ -142615,7 +143092,7 @@ function formatUsageStats({
|
|
|
142615
143092
|
const monthlyCredits = Math.round(balance.monthly_credit_balance);
|
|
142616
143093
|
const purchasedCredits = Math.round(balance.purchased_credit_balance);
|
|
142617
143094
|
const toDollars = (credits) => (credits / 1000).toFixed(2);
|
|
142618
|
-
outputLines.push(`Plan: [${balance.billing_tier}]`, buildAppUrl("/settings/organization/usage"), "", `Available credits: ◎${
|
|
143095
|
+
outputLines.push(`Plan: [${balance.billing_tier}]`, buildAppUrl("/settings/organization/usage"), "", `Available credits: ◎${formatNumber2(totalCredits)} ($${toDollars(totalCredits)})`, `Monthly credits: ◎${formatNumber2(monthlyCredits)} ($${toDollars(monthlyCredits)})`, `Purchased credits: ◎${formatNumber2(purchasedCredits)} ($${toDollars(purchasedCredits)})`);
|
|
142619
143096
|
}
|
|
142620
143097
|
return outputLines.join(`
|
|
142621
143098
|
`);
|
|
@@ -149886,6 +150363,7 @@ function App2({
|
|
|
149886
150363
|
streamingRefreshTimeoutRef.current = setTimeout(() => {
|
|
149887
150364
|
streamingRefreshTimeoutRef.current = null;
|
|
149888
150365
|
if (!buffersRef.current.interrupted) {
|
|
150366
|
+
recordTuiPerf("ui_refresh:tool_output");
|
|
149889
150367
|
refreshDerived();
|
|
149890
150368
|
}
|
|
149891
150369
|
}, 100);
|
|
@@ -149898,6 +150376,9 @@ function App2({
|
|
|
149898
150376
|
};
|
|
149899
150377
|
}, []);
|
|
149900
150378
|
const updateStreamingOutput = import_react104.useCallback((toolCallId, chunk, isStderr = false) => {
|
|
150379
|
+
recordTuiPerf(`tool_output:${isStderr ? "stderr" : "stdout"}`, {
|
|
150380
|
+
bytes: Buffer.byteLength(chunk)
|
|
150381
|
+
});
|
|
149901
150382
|
const lineId = buffersRef.current.toolCallIdToLineId.get(toolCallId);
|
|
149902
150383
|
if (!lineId)
|
|
149903
150384
|
return;
|
|
@@ -149918,6 +150399,7 @@ function App2({
|
|
|
149918
150399
|
setTimeout(() => {
|
|
149919
150400
|
buffersRef.current.pendingRefresh = false;
|
|
149920
150401
|
if (!buffersRef.current.interrupted && (buffersRef.current.commitGeneration || 0) === capturedGeneration) {
|
|
150402
|
+
recordTuiPerf("ui_refresh:stream");
|
|
149921
150403
|
refreshDerived();
|
|
149922
150404
|
}
|
|
149923
150405
|
}, 16);
|
|
@@ -157431,6 +157913,7 @@ var init_App2 = __esm(async () => {
|
|
|
157431
157913
|
init_telemetry();
|
|
157432
157914
|
init_toolset_labels();
|
|
157433
157915
|
init_debug();
|
|
157916
|
+
init_tuiPerf();
|
|
157434
157917
|
init_version();
|
|
157435
157918
|
init_mcp();
|
|
157436
157919
|
init_profile();
|
|
@@ -157611,12 +158094,12 @@ __export(exports_terminalKeybindingInstaller2, {
|
|
|
157611
158094
|
import {
|
|
157612
158095
|
copyFileSync as copyFileSync2,
|
|
157613
158096
|
existsSync as existsSync46,
|
|
157614
|
-
mkdirSync as
|
|
158097
|
+
mkdirSync as mkdirSync33,
|
|
157615
158098
|
readFileSync as readFileSync29,
|
|
157616
158099
|
writeFileSync as writeFileSync25
|
|
157617
158100
|
} from "node:fs";
|
|
157618
158101
|
import { homedir as homedir38, platform as platform7 } from "node:os";
|
|
157619
|
-
import { dirname as
|
|
158102
|
+
import { dirname as dirname22, join as join54 } from "node:path";
|
|
157620
158103
|
function detectTerminalType2() {
|
|
157621
158104
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
157622
158105
|
return "cursor";
|
|
@@ -157707,9 +158190,9 @@ function installKeybinding2(keybindingsPath) {
|
|
|
157707
158190
|
if (keybindingExists2(keybindingsPath)) {
|
|
157708
158191
|
return { success: true, alreadyExists: true };
|
|
157709
158192
|
}
|
|
157710
|
-
const parentDir =
|
|
158193
|
+
const parentDir = dirname22(keybindingsPath);
|
|
157711
158194
|
if (!existsSync46(parentDir)) {
|
|
157712
|
-
|
|
158195
|
+
mkdirSync33(parentDir, { recursive: true });
|
|
157713
158196
|
}
|
|
157714
158197
|
let keybindings = [];
|
|
157715
158198
|
let backupPath = null;
|
|
@@ -157866,9 +158349,9 @@ return config`);
|
|
|
157866
158349
|
${WEZTERM_DELETE_FIX2}
|
|
157867
158350
|
`;
|
|
157868
158351
|
}
|
|
157869
|
-
const parentDir =
|
|
158352
|
+
const parentDir = dirname22(configPath);
|
|
157870
158353
|
if (!existsSync46(parentDir)) {
|
|
157871
|
-
|
|
158354
|
+
mkdirSync33(parentDir, { recursive: true });
|
|
157872
158355
|
}
|
|
157873
158356
|
writeFileSync25(configPath, content, { encoding: "utf-8" });
|
|
157874
158357
|
return {
|
|
@@ -158436,7 +158919,7 @@ __export(exports_import2, {
|
|
|
158436
158919
|
});
|
|
158437
158920
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
158438
158921
|
import { chmod as chmod2, mkdir as mkdir11, readFile as readFile19, writeFile as writeFile14 } from "node:fs/promises";
|
|
158439
|
-
import { dirname as
|
|
158922
|
+
import { dirname as dirname23, resolve as resolve35 } from "node:path";
|
|
158440
158923
|
async function importAgentFromFile2(options) {
|
|
158441
158924
|
const client = await getClient();
|
|
158442
158925
|
const resolvedPath = resolve35(options.filePath);
|
|
@@ -158495,7 +158978,7 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
158495
158978
|
}
|
|
158496
158979
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
158497
158980
|
const fullPath = resolve35(skillDir, filePath);
|
|
158498
|
-
await mkdir11(
|
|
158981
|
+
await mkdir11(dirname23(fullPath), { recursive: true });
|
|
158499
158982
|
await writeFile14(fullPath, content, "utf-8");
|
|
158500
158983
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
158501
158984
|
if (isScript) {
|
|
@@ -158605,7 +159088,7 @@ __export(exports_memoryFilesystem2, {
|
|
|
158605
159088
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
|
|
158606
159089
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
158607
159090
|
});
|
|
158608
|
-
import { existsSync as existsSync47, mkdirSync as
|
|
159091
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync34 } from "node:fs";
|
|
158609
159092
|
import { homedir as homedir40 } from "node:os";
|
|
158610
159093
|
import { join as join56, resolve as resolve36 } from "node:path";
|
|
158611
159094
|
function getMemoryFilesystemRoot2(agentId, homeDir = homedir40()) {
|
|
@@ -158641,10 +159124,10 @@ function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir40()) {
|
|
|
158641
159124
|
const root = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
158642
159125
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
158643
159126
|
if (!existsSync47(root)) {
|
|
158644
|
-
|
|
159127
|
+
mkdirSync34(root, { recursive: true });
|
|
158645
159128
|
}
|
|
158646
159129
|
if (!existsSync47(systemDir)) {
|
|
158647
|
-
|
|
159130
|
+
mkdirSync34(systemDir, { recursive: true });
|
|
158648
159131
|
}
|
|
158649
159132
|
}
|
|
158650
159133
|
async function isMemfsEnabledOnServer2(agentId) {
|
|
@@ -163965,51 +164448,141 @@ async function runListenSubcommand(argv) {
|
|
|
163965
164448
|
}
|
|
163966
164449
|
}
|
|
163967
164450
|
|
|
163968
|
-
// src/cli/subcommands/
|
|
164451
|
+
// src/cli/subcommands/memory.ts
|
|
163969
164452
|
init_memoryGit();
|
|
163970
|
-
import { cpSync, existsSync as existsSync30, mkdirSync as
|
|
164453
|
+
import { cpSync, existsSync as existsSync30, mkdirSync as mkdirSync23, rmSync as rmSync3, statSync as statSync8 } from "node:fs";
|
|
163971
164454
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
163972
164455
|
import { homedir as homedir23 } from "node:os";
|
|
163973
164456
|
import { join as join34 } from "node:path";
|
|
163974
164457
|
import { parseArgs as parseArgs8 } from "node:util";
|
|
164458
|
+
|
|
164459
|
+
// src/cli/subcommands/memoryTokens.ts
|
|
164460
|
+
init_systemPromptSize();
|
|
164461
|
+
var DEFAULT_TOP = 20;
|
|
164462
|
+
var USAGE_EXIT = 64;
|
|
164463
|
+
var IO_EXIT = 65;
|
|
164464
|
+
function parsePositiveInt(raw, fallback) {
|
|
164465
|
+
if (raw === undefined)
|
|
164466
|
+
return fallback;
|
|
164467
|
+
if (!/^\d+$/.test(raw))
|
|
164468
|
+
return null;
|
|
164469
|
+
return Number.parseInt(raw, 10);
|
|
164470
|
+
}
|
|
164471
|
+
function formatNumber(value) {
|
|
164472
|
+
return value.toLocaleString("en-US");
|
|
164473
|
+
}
|
|
164474
|
+
function printText(total, files, top, quiet) {
|
|
164475
|
+
console.log("System prompt token estimate");
|
|
164476
|
+
console.log(` Total: ${formatNumber(total)} tokens`);
|
|
164477
|
+
if (quiet || top <= 0 || files.length === 0) {
|
|
164478
|
+
return;
|
|
164479
|
+
}
|
|
164480
|
+
const ranked = [...files].sort((a, b) => b.tokens - a.tokens);
|
|
164481
|
+
const limited = ranked.slice(0, top);
|
|
164482
|
+
console.log("");
|
|
164483
|
+
console.log("Top files:");
|
|
164484
|
+
console.log(` ${"tokens".padStart(8)} path`);
|
|
164485
|
+
for (const row of limited) {
|
|
164486
|
+
console.log(` ${formatNumber(row.tokens).padStart(8)} ${row.path}`);
|
|
164487
|
+
}
|
|
164488
|
+
}
|
|
164489
|
+
function printJson(total, files) {
|
|
164490
|
+
console.log(JSON.stringify({
|
|
164491
|
+
total_tokens: total,
|
|
164492
|
+
files
|
|
164493
|
+
}, null, 2));
|
|
164494
|
+
}
|
|
164495
|
+
function resolveMemoryDir3(options) {
|
|
164496
|
+
if (options.memoryDir)
|
|
164497
|
+
return options.memoryDir;
|
|
164498
|
+
if (process.env.MEMORY_DIR)
|
|
164499
|
+
return process.env.MEMORY_DIR;
|
|
164500
|
+
if (options.agentMemoryDir)
|
|
164501
|
+
return options.agentMemoryDir;
|
|
164502
|
+
return null;
|
|
164503
|
+
}
|
|
164504
|
+
async function runMemoryTokensAction(options) {
|
|
164505
|
+
const format2 = options.format ?? "text";
|
|
164506
|
+
if (format2 !== "text" && format2 !== "json") {
|
|
164507
|
+
console.error(`Invalid --format: ${format2} (expected text or json)`);
|
|
164508
|
+
return USAGE_EXIT;
|
|
164509
|
+
}
|
|
164510
|
+
const top = parsePositiveInt(options.top, DEFAULT_TOP);
|
|
164511
|
+
if (top === null) {
|
|
164512
|
+
console.error(`Invalid --top: ${options.top} (expected non-negative integer)`);
|
|
164513
|
+
return USAGE_EXIT;
|
|
164514
|
+
}
|
|
164515
|
+
const memoryDir = resolveMemoryDir3(options);
|
|
164516
|
+
if (!memoryDir) {
|
|
164517
|
+
console.error("Missing memory dir. Set --memory-dir, --agent, $MEMORY_DIR, or $LETTA_AGENT_ID.");
|
|
164518
|
+
return USAGE_EXIT;
|
|
164519
|
+
}
|
|
164520
|
+
let estimate;
|
|
164521
|
+
try {
|
|
164522
|
+
estimate = estimateSystemPromptSize(memoryDir);
|
|
164523
|
+
} catch (error) {
|
|
164524
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
164525
|
+
console.error(`Failed to read memory dir: ${message}`);
|
|
164526
|
+
return IO_EXIT;
|
|
164527
|
+
}
|
|
164528
|
+
const { total, files } = estimate;
|
|
164529
|
+
if (format2 === "json") {
|
|
164530
|
+
printJson(total, files);
|
|
164531
|
+
} else {
|
|
164532
|
+
printText(total, files, top, options.quiet);
|
|
164533
|
+
}
|
|
164534
|
+
return 0;
|
|
164535
|
+
}
|
|
164536
|
+
|
|
164537
|
+
// src/cli/subcommands/memory.ts
|
|
163975
164538
|
function printUsage5() {
|
|
163976
164539
|
console.log(`
|
|
163977
164540
|
Usage:
|
|
163978
|
-
letta
|
|
163979
|
-
letta
|
|
163980
|
-
letta
|
|
163981
|
-
letta
|
|
163982
|
-
letta
|
|
163983
|
-
letta
|
|
163984
|
-
letta
|
|
164541
|
+
letta memory status [--agent <id>]
|
|
164542
|
+
letta memory diff [--agent <id>]
|
|
164543
|
+
letta memory backup [--agent <id>]
|
|
164544
|
+
letta memory backups [--agent <id>]
|
|
164545
|
+
letta memory restore --from <backup> --force [--agent <id>]
|
|
164546
|
+
letta memory export --agent <id> --out <dir>
|
|
164547
|
+
letta memory pull [--agent <id>]
|
|
164548
|
+
letta memory tokens [--memory-dir <path>] [--agent <id>] [--top <N>]
|
|
164549
|
+
[--format text|json] [--quiet]
|
|
163985
164550
|
|
|
163986
164551
|
Notes:
|
|
163987
|
-
-
|
|
163988
|
-
-
|
|
164552
|
+
- Most actions require agent id via --agent or LETTA_AGENT_ID and output JSON.
|
|
164553
|
+
- \`tokens\` additionally accepts --memory-dir or $MEMORY_DIR; reports the
|
|
164554
|
+
estimated token size of system/. Policy (whether a size is concerning) is
|
|
164555
|
+
up to the caller.
|
|
163989
164556
|
- Memory is git-backed. Use git commands for commit/push.
|
|
163990
164557
|
|
|
163991
164558
|
Examples:
|
|
163992
|
-
LETTA_AGENT_ID=agent-123 letta
|
|
163993
|
-
letta
|
|
163994
|
-
letta
|
|
163995
|
-
letta
|
|
164559
|
+
LETTA_AGENT_ID=agent-123 letta memory status
|
|
164560
|
+
letta memory pull --agent agent-123
|
|
164561
|
+
letta memory backup --agent agent-123
|
|
164562
|
+
letta memory export --agent agent-123 --out /tmp/letta-memory-agent-123
|
|
164563
|
+
letta memory tokens
|
|
164564
|
+
letta memory tokens --memory-dir ~/.letta/agents/agent-123/memory --format json
|
|
163996
164565
|
`.trim());
|
|
163997
164566
|
}
|
|
163998
164567
|
function getAgentId5(agentFromArgs, agentIdFromArgs) {
|
|
163999
164568
|
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
164000
164569
|
}
|
|
164001
|
-
var
|
|
164570
|
+
var MEMORY_OPTIONS = {
|
|
164002
164571
|
help: { type: "boolean", short: "h" },
|
|
164003
164572
|
agent: { type: "string" },
|
|
164004
164573
|
"agent-id": { type: "string" },
|
|
164005
164574
|
from: { type: "string" },
|
|
164006
164575
|
force: { type: "boolean" },
|
|
164007
|
-
out: { type: "string" }
|
|
164576
|
+
out: { type: "string" },
|
|
164577
|
+
"memory-dir": { type: "string" },
|
|
164578
|
+
top: { type: "string" },
|
|
164579
|
+
format: { type: "string" },
|
|
164580
|
+
quiet: { type: "boolean" }
|
|
164008
164581
|
};
|
|
164009
|
-
function
|
|
164582
|
+
function parseMemoryArgs(argv) {
|
|
164010
164583
|
return parseArgs8({
|
|
164011
164584
|
args: argv,
|
|
164012
|
-
options:
|
|
164585
|
+
options: MEMORY_OPTIONS,
|
|
164013
164586
|
strict: true,
|
|
164014
164587
|
allowPositionals: true
|
|
164015
164588
|
});
|
|
@@ -164061,10 +164634,10 @@ function resolveBackupPath(agentId, from) {
|
|
|
164061
164634
|
}
|
|
164062
164635
|
return join34(getAgentRoot(agentId), from);
|
|
164063
164636
|
}
|
|
164064
|
-
async function
|
|
164637
|
+
async function runMemorySubcommand(argv) {
|
|
164065
164638
|
let parsed;
|
|
164066
164639
|
try {
|
|
164067
|
-
parsed =
|
|
164640
|
+
parsed = parseMemoryArgs(argv);
|
|
164068
164641
|
} catch (error) {
|
|
164069
164642
|
const message = error instanceof Error ? error.message : String(error);
|
|
164070
164643
|
console.error(`Error: ${message}`);
|
|
@@ -164077,6 +164650,15 @@ async function runMemfsSubcommand(argv) {
|
|
|
164077
164650
|
return 0;
|
|
164078
164651
|
}
|
|
164079
164652
|
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
164653
|
+
if (action === "tokens") {
|
|
164654
|
+
return runMemoryTokensAction({
|
|
164655
|
+
memoryDir: parsed.values["memory-dir"],
|
|
164656
|
+
agentMemoryDir: agentId ? getMemoryRoot(agentId) : undefined,
|
|
164657
|
+
top: parsed.values.top,
|
|
164658
|
+
format: parsed.values.format,
|
|
164659
|
+
quiet: Boolean(parsed.values.quiet)
|
|
164660
|
+
});
|
|
164661
|
+
}
|
|
164080
164662
|
if (!agentId) {
|
|
164081
164663
|
console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
164082
164664
|
return 1;
|
|
@@ -164189,7 +164771,7 @@ async function runMemfsSubcommand(argv) {
|
|
|
164189
164771
|
return 1;
|
|
164190
164772
|
}
|
|
164191
164773
|
} else {
|
|
164192
|
-
|
|
164774
|
+
mkdirSync23(out, { recursive: true });
|
|
164193
164775
|
}
|
|
164194
164776
|
cpSync(root, out, { recursive: true });
|
|
164195
164777
|
console.log(JSON.stringify({ exportedFrom: root, exportedTo: out, agentId }, null, 2));
|
|
@@ -164548,8 +165130,9 @@ async function runSubcommand(argv) {
|
|
|
164548
165130
|
return null;
|
|
164549
165131
|
}
|
|
164550
165132
|
switch (command) {
|
|
165133
|
+
case "memory":
|
|
164551
165134
|
case "memfs":
|
|
164552
|
-
return
|
|
165135
|
+
return runMemorySubcommand(rest);
|
|
164553
165136
|
case "agents":
|
|
164554
165137
|
return runAgentsSubcommand(rest);
|
|
164555
165138
|
case "messages":
|
|
@@ -166718,7 +167301,7 @@ USAGE
|
|
|
166718
167301
|
|
|
166719
167302
|
# maintenance
|
|
166720
167303
|
letta update Manually check for updates and install if available
|
|
166721
|
-
letta
|
|
167304
|
+
letta memory ... Memory filesystem subcommands
|
|
166722
167305
|
letta agents ... Agents subcommands (JSON-only)
|
|
166723
167306
|
letta messages ... Messages subcommands (JSON-only)
|
|
166724
167307
|
letta blocks ... Blocks subcommands (JSON-only)
|
|
@@ -166727,14 +167310,16 @@ USAGE
|
|
|
166727
167310
|
OPTIONS
|
|
166728
167311
|
${renderCliOptionsHelp()}
|
|
166729
167312
|
|
|
166730
|
-
SUBCOMMANDS
|
|
166731
|
-
letta
|
|
166732
|
-
letta
|
|
166733
|
-
letta
|
|
166734
|
-
letta
|
|
166735
|
-
letta
|
|
166736
|
-
letta
|
|
166737
|
-
letta
|
|
167313
|
+
SUBCOMMANDS
|
|
167314
|
+
letta memory status --agent <id>
|
|
167315
|
+
letta memory diff --agent <id>
|
|
167316
|
+
letta memory resolve --agent <id> --resolutions '<JSON>'
|
|
167317
|
+
letta memory backup --agent <id>
|
|
167318
|
+
letta memory backups --agent <id>
|
|
167319
|
+
letta memory restore --agent <id> --from <backup> --force
|
|
167320
|
+
letta memory export --agent <id> --out <dir>
|
|
167321
|
+
letta memory pull --agent <id>
|
|
167322
|
+
letta memory tokens [--memory-dir <path>] [--agent <id>] [--format text|json]
|
|
166738
167323
|
letta agents list [--query <text> | --name <name> | --tags <tags>]
|
|
166739
167324
|
letta messages search --query <text> [--all-agents]
|
|
166740
167325
|
letta messages list [--agent <id>]
|
|
@@ -168068,4 +168653,4 @@ Error during initialization: ${message}`);
|
|
|
168068
168653
|
}
|
|
168069
168654
|
main();
|
|
168070
168655
|
|
|
168071
|
-
//# debugId=
|
|
168656
|
+
//# debugId=22CE2EBE31776A7764756E2164756E21
|