@letta-ai/letta-code 0.23.0 → 0.23.2
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 +472 -250
- package/package.json +1 -1
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.23.
|
|
3272
|
+
version: "0.23.2",
|
|
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: {
|
|
@@ -41452,10 +41452,22 @@ var init_runtime2 = __esm(() => {
|
|
|
41452
41452
|
// src/channels/slack/adapter.ts
|
|
41453
41453
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
41454
41454
|
import { basename as basename4, extname as extname3 } from "node:path";
|
|
41455
|
+
function isConstructorFunction(value) {
|
|
41456
|
+
return typeof value === "function";
|
|
41457
|
+
}
|
|
41458
|
+
function resolveSlackAppModule(value) {
|
|
41459
|
+
if (!value || typeof value !== "object") {
|
|
41460
|
+
return null;
|
|
41461
|
+
}
|
|
41462
|
+
const app = Reflect.get(value, "App");
|
|
41463
|
+
return isConstructorFunction(app) ? app : null;
|
|
41464
|
+
}
|
|
41455
41465
|
function resolveSlackAppConstructor(mod) {
|
|
41456
|
-
const
|
|
41466
|
+
const defaultExport = mod && typeof mod === "object" ? Reflect.get(mod, "default") : undefined;
|
|
41467
|
+
const nestedDefault = defaultExport && typeof defaultExport === "object" ? Reflect.get(defaultExport, "default") : undefined;
|
|
41468
|
+
const App2 = resolveSlackAppModule(mod) ?? resolveSlackAppModule(defaultExport) ?? resolveSlackAppModule(nestedDefault) ?? (isConstructorFunction(defaultExport) ? defaultExport : null);
|
|
41457
41469
|
if (!App2) {
|
|
41458
|
-
throw new Error('Installed Slack runtime did not export
|
|
41470
|
+
throw new Error('Installed Slack runtime did not export constructor "App".');
|
|
41459
41471
|
}
|
|
41460
41472
|
return App2;
|
|
41461
41473
|
}
|
|
@@ -43143,6 +43155,7 @@ __export(exports_service, {
|
|
|
43143
43155
|
removeChannelAccountLive: () => removeChannelAccountLive,
|
|
43144
43156
|
refreshChannelAccountDisplayNameLive: () => refreshChannelAccountDisplayNameLive,
|
|
43145
43157
|
listPendingPairingSnapshots: () => listPendingPairingSnapshots,
|
|
43158
|
+
listEnabledChannelIds: () => listEnabledChannelIds,
|
|
43146
43159
|
listChannelTargetSnapshots: () => listChannelTargetSnapshots,
|
|
43147
43160
|
listChannelSummaries: () => listChannelSummaries,
|
|
43148
43161
|
listChannelRouteSnapshots: () => listChannelRouteSnapshots,
|
|
@@ -43400,6 +43413,9 @@ function listChannelSummaries() {
|
|
|
43400
43413
|
};
|
|
43401
43414
|
});
|
|
43402
43415
|
}
|
|
43416
|
+
function listEnabledChannelIds() {
|
|
43417
|
+
return getSupportedChannelIds().filter((channelId) => listChannelAccounts(channelId).some((account) => account.enabled));
|
|
43418
|
+
}
|
|
43403
43419
|
function getChannelConfigSnapshot(channelId, accountId) {
|
|
43404
43420
|
assertSupportedChannelId(channelId);
|
|
43405
43421
|
const account = getSelectedChannelAccount(channelId, accountId);
|
|
@@ -55627,7 +55643,8 @@ async function executeSingleDecision(decision, onChunk, options) {
|
|
|
55627
55643
|
toolCallId: decision.approval.toolCallId,
|
|
55628
55644
|
toolContextId: options?.toolContextId,
|
|
55629
55645
|
parentScope: options?.parentScope,
|
|
55630
|
-
onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined
|
|
55646
|
+
onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined,
|
|
55647
|
+
onFileWrite: options?.onFileWrite
|
|
55631
55648
|
});
|
|
55632
55649
|
if (onChunk) {
|
|
55633
55650
|
onChunk({
|
|
@@ -77520,6 +77537,8 @@ var init_analyzer = __esm(() => {
|
|
|
77520
77537
|
});
|
|
77521
77538
|
|
|
77522
77539
|
// src/tools/manager.ts
|
|
77540
|
+
import * as nodeFs from "node:fs/promises";
|
|
77541
|
+
import * as nodePath from "node:path";
|
|
77523
77542
|
function maybeAppendChannelTools(toolNames) {
|
|
77524
77543
|
if (getActiveChannelIds().length > 0 && !toolNames.includes("MessageChannel")) {
|
|
77525
77544
|
return [...toolNames, "MessageChannel"];
|
|
@@ -77590,8 +77609,8 @@ function acquireSwitchLock() {
|
|
|
77590
77609
|
const lock = getSwitchLock();
|
|
77591
77610
|
lock.refCount++;
|
|
77592
77611
|
if (lock.refCount === 1) {
|
|
77593
|
-
lock.promise = new Promise((
|
|
77594
|
-
lock.resolve =
|
|
77612
|
+
lock.promise = new Promise((resolve25) => {
|
|
77613
|
+
lock.resolve = resolve25;
|
|
77595
77614
|
});
|
|
77596
77615
|
}
|
|
77597
77616
|
}
|
|
@@ -78120,6 +78139,16 @@ async function executeTool(name, args, options) {
|
|
|
78120
78139
|
const result = await withExecutionWorkingDirectory(workingDirectory, () => tool.fn(enhancedArgs));
|
|
78121
78140
|
const duration = Date.now() - startTime;
|
|
78122
78141
|
refreshFileIndex();
|
|
78142
|
+
if (options?.onFileWrite && FILE_MUTATING_TOOLS.has(internalName)) {
|
|
78143
|
+
const filePath = enhancedArgs.file_path;
|
|
78144
|
+
if (filePath) {
|
|
78145
|
+
try {
|
|
78146
|
+
const resolvedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.resolve(process.env.USER_CWD || process.cwd(), filePath);
|
|
78147
|
+
const content = await nodeFs.readFile(resolvedPath, "utf-8");
|
|
78148
|
+
options.onFileWrite(resolvedPath, content);
|
|
78149
|
+
} catch {}
|
|
78150
|
+
}
|
|
78151
|
+
}
|
|
78123
78152
|
const recordResult = isRecord(result) ? result : undefined;
|
|
78124
78153
|
const stdoutValue = recordResult?.stdout;
|
|
78125
78154
|
const stderrValue = recordResult?.stderr;
|
|
@@ -78253,7 +78282,7 @@ function clearToolsWithLock() {
|
|
|
78253
78282
|
releaseSwitchLock();
|
|
78254
78283
|
}
|
|
78255
78284
|
}
|
|
78256
|
-
var TOOL_NAMES, STREAMING_SHELL_TOOLS, TOOL_NAME_MAPPINGS, ANTHROPIC_DEFAULT_TOOLS, OPENAI_DEFAULT_TOOLS, GEMINI_DEFAULT_TOOLS, OPENAI_PASCAL_TOOLS, GEMINI_PASCAL_TOOLS, REGISTRY_KEY, SWITCH_LOCK_KEY, EXECUTION_CONTEXTS_KEY, toolRegistry, toolExecutionContextCounter = 0, EXTERNAL_TOOLS_KEY, EXTERNAL_EXECUTOR_KEY;
|
|
78285
|
+
var TOOL_NAMES, STREAMING_SHELL_TOOLS, FILE_MUTATING_TOOLS, TOOL_NAME_MAPPINGS, ANTHROPIC_DEFAULT_TOOLS, OPENAI_DEFAULT_TOOLS, GEMINI_DEFAULT_TOOLS, OPENAI_PASCAL_TOOLS, GEMINI_PASCAL_TOOLS, REGISTRY_KEY, SWITCH_LOCK_KEY, EXECUTION_CONTEXTS_KEY, toolRegistry, toolExecutionContextCounter = 0, EXTERNAL_TOOLS_KEY, EXTERNAL_EXECUTOR_KEY;
|
|
78257
78286
|
var init_manager3 = __esm(async () => {
|
|
78258
78287
|
init_model2();
|
|
78259
78288
|
init_subagents();
|
|
@@ -78283,6 +78312,7 @@ var init_manager3 = __esm(async () => {
|
|
|
78283
78312
|
"run_shell_command",
|
|
78284
78313
|
"RunShellCommand"
|
|
78285
78314
|
]);
|
|
78315
|
+
FILE_MUTATING_TOOLS = new Set(["Edit", "Write", "MultiEdit", "replace"]);
|
|
78286
78316
|
TOOL_NAME_MAPPINGS = {
|
|
78287
78317
|
glob_gemini: "glob",
|
|
78288
78318
|
write_todos: "write_todos",
|
|
@@ -81705,7 +81735,7 @@ import {
|
|
|
81705
81735
|
appendFile,
|
|
81706
81736
|
mkdir as mkdir7,
|
|
81707
81737
|
readdir as readdir5,
|
|
81708
|
-
readFile as
|
|
81738
|
+
readFile as readFile10,
|
|
81709
81739
|
writeFile as writeFile7
|
|
81710
81740
|
} from "node:fs/promises";
|
|
81711
81741
|
import { homedir as homedir21, tmpdir as tmpdir3 } from "node:os";
|
|
@@ -81752,7 +81782,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
81752
81782
|
continue;
|
|
81753
81783
|
}
|
|
81754
81784
|
try {
|
|
81755
|
-
const content = await
|
|
81785
|
+
const content = await readFile10(entryPath, "utf-8");
|
|
81756
81786
|
const { frontmatter } = parseFrontmatter(content);
|
|
81757
81787
|
const description = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
|
|
81758
81788
|
files.push({
|
|
@@ -82012,7 +82042,7 @@ async function ensurePaths(paths) {
|
|
|
82012
82042
|
}
|
|
82013
82043
|
async function readState(paths) {
|
|
82014
82044
|
try {
|
|
82015
|
-
const raw = await
|
|
82045
|
+
const raw = await readFile10(paths.statePath, "utf-8");
|
|
82016
82046
|
const parsed = parseJsonLine(raw);
|
|
82017
82047
|
if (!parsed) {
|
|
82018
82048
|
return defaultState();
|
|
@@ -82032,7 +82062,7 @@ async function writeState(paths, state) {
|
|
|
82032
82062
|
}
|
|
82033
82063
|
async function readTranscriptLines(paths) {
|
|
82034
82064
|
try {
|
|
82035
|
-
const raw = await
|
|
82065
|
+
const raw = await readFile10(paths.transcriptPath, "utf-8");
|
|
82036
82066
|
return raw.split(`
|
|
82037
82067
|
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
82038
82068
|
} catch {
|
|
@@ -82391,11 +82421,11 @@ async function discoverFallbackRunIdWithTimeout(client, ctx) {
|
|
|
82391
82421
|
return withTimeout(discoverFallbackRunIdForResume(client, ctx), FALLBACK_RUN_DISCOVERY_TIMEOUT_MS, `Fallback run discovery timed out after ${FALLBACK_RUN_DISCOVERY_TIMEOUT_MS}ms`);
|
|
82392
82422
|
}
|
|
82393
82423
|
function withTimeout(promise, timeoutMs, timeoutMessage) {
|
|
82394
|
-
return new Promise((
|
|
82424
|
+
return new Promise((resolve25, reject) => {
|
|
82395
82425
|
const timer = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
|
|
82396
82426
|
promise.then((value) => {
|
|
82397
82427
|
clearTimeout(timer);
|
|
82398
|
-
|
|
82428
|
+
resolve25(value);
|
|
82399
82429
|
}, (error) => {
|
|
82400
82430
|
clearTimeout(timer);
|
|
82401
82431
|
reject(error);
|
|
@@ -83535,7 +83565,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
83535
83565
|
if (isInterrupted()) {
|
|
83536
83566
|
return Promise.reject(new Error("Cancelled by user"));
|
|
83537
83567
|
}
|
|
83538
|
-
return new Promise((
|
|
83568
|
+
return new Promise((resolve25, reject) => {
|
|
83539
83569
|
let settled = false;
|
|
83540
83570
|
const cleanupAbortListener = () => {
|
|
83541
83571
|
abortSignal?.removeEventListener("abort", handleAbort);
|
|
@@ -83546,7 +83576,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
83546
83576
|
}
|
|
83547
83577
|
settled = true;
|
|
83548
83578
|
cleanupAbortListener();
|
|
83549
|
-
|
|
83579
|
+
resolve25(response);
|
|
83550
83580
|
};
|
|
83551
83581
|
const wrappedReject = (error) => {
|
|
83552
83582
|
if (settled) {
|
|
@@ -87209,7 +87239,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
87209
87239
|
conversationId
|
|
87210
87240
|
});
|
|
87211
87241
|
}
|
|
87212
|
-
await new Promise((
|
|
87242
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
87213
87243
|
if (abortSignal?.aborted) {
|
|
87214
87244
|
throw new Error("Cancelled by user");
|
|
87215
87245
|
}
|
|
@@ -87264,7 +87294,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
87264
87294
|
agentId: runtime.agentId ?? undefined,
|
|
87265
87295
|
conversationId
|
|
87266
87296
|
});
|
|
87267
|
-
await new Promise((
|
|
87297
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
87268
87298
|
if (abortSignal?.aborted) {
|
|
87269
87299
|
throw new Error("Cancelled by user");
|
|
87270
87300
|
}
|
|
@@ -87339,7 +87369,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
87339
87369
|
retryAfterMs
|
|
87340
87370
|
});
|
|
87341
87371
|
transientRetries = attempt;
|
|
87342
|
-
await new Promise((
|
|
87372
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
87343
87373
|
if (abortSignal?.aborted) {
|
|
87344
87374
|
throw new Error("Cancelled by user");
|
|
87345
87375
|
}
|
|
@@ -87384,7 +87414,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
87384
87414
|
category: "conversation_busy",
|
|
87385
87415
|
attempt: conversationBusyRetries
|
|
87386
87416
|
});
|
|
87387
|
-
await new Promise((
|
|
87417
|
+
await new Promise((resolve25) => setTimeout(resolve25, retryDelayMs));
|
|
87388
87418
|
if (abortSignal?.aborted) {
|
|
87389
87419
|
throw new Error("Cancelled by user");
|
|
87390
87420
|
}
|
|
@@ -87422,6 +87452,7 @@ var init_send = __esm(async () => {
|
|
|
87422
87452
|
});
|
|
87423
87453
|
|
|
87424
87454
|
// src/websocket/listener/turn-approval.ts
|
|
87455
|
+
import WebSocket2 from "ws";
|
|
87425
87456
|
async function handleApprovalStop(params) {
|
|
87426
87457
|
const {
|
|
87427
87458
|
approvals,
|
|
@@ -87647,11 +87678,24 @@ async function handleApprovalStop(params) {
|
|
|
87647
87678
|
if (shouldInterrupt()) {
|
|
87648
87679
|
return interruptTermination();
|
|
87649
87680
|
}
|
|
87681
|
+
const onFileWrite = (filePath, content) => {
|
|
87682
|
+
if (socket.readyState === WebSocket2.OPEN) {
|
|
87683
|
+
socket.send(JSON.stringify({
|
|
87684
|
+
type: "file_ops",
|
|
87685
|
+
path: filePath,
|
|
87686
|
+
cg_entries: [],
|
|
87687
|
+
ops: [],
|
|
87688
|
+
source: "agent",
|
|
87689
|
+
document_content: content
|
|
87690
|
+
}));
|
|
87691
|
+
}
|
|
87692
|
+
};
|
|
87650
87693
|
const executionResults = await executeApprovalBatch(decisions, undefined, {
|
|
87651
87694
|
toolContextId: turnToolContextId ?? undefined,
|
|
87652
87695
|
abortSignal: abortController.signal,
|
|
87653
87696
|
workingDirectory: turnWorkingDirectory,
|
|
87654
|
-
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined
|
|
87697
|
+
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined,
|
|
87698
|
+
onFileWrite
|
|
87655
87699
|
});
|
|
87656
87700
|
const persistedExecutionResults = normalizeExecutionResultsForInterruptParity(runtime, executionResults, lastExecutingToolCallIds);
|
|
87657
87701
|
validateApprovalResultIds(decisions.map((decision) => ({
|
|
@@ -88276,7 +88320,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
88276
88320
|
agentId,
|
|
88277
88321
|
conversationId
|
|
88278
88322
|
});
|
|
88279
|
-
await new Promise((
|
|
88323
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
88280
88324
|
if (turnAbortSignal.aborted) {
|
|
88281
88325
|
throw new Error("Cancelled by user");
|
|
88282
88326
|
}
|
|
@@ -88321,7 +88365,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
88321
88365
|
agentId,
|
|
88322
88366
|
conversationId
|
|
88323
88367
|
});
|
|
88324
|
-
await new Promise((
|
|
88368
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
88325
88369
|
if (turnAbortSignal.aborted) {
|
|
88326
88370
|
throw new Error("Cancelled by user");
|
|
88327
88371
|
}
|
|
@@ -88811,7 +88855,7 @@ var init_commands = __esm(async () => {
|
|
|
88811
88855
|
});
|
|
88812
88856
|
|
|
88813
88857
|
// src/websocket/listener/protocol-outbound.ts
|
|
88814
|
-
import
|
|
88858
|
+
import WebSocket3 from "ws";
|
|
88815
88859
|
function getCachedDeviceGitContext(cwd2) {
|
|
88816
88860
|
const now = Date.now();
|
|
88817
88861
|
const cached = gitContextCache.get(cwd2);
|
|
@@ -88928,7 +88972,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
88928
88972
|
return {
|
|
88929
88973
|
current_connection_id: listener.connectionId,
|
|
88930
88974
|
connection_name: listener.connectionName,
|
|
88931
|
-
is_online: listener.socket?.readyState ===
|
|
88975
|
+
is_online: listener.socket?.readyState === WebSocket3.OPEN,
|
|
88932
88976
|
is_processing: !!conversationRuntime?.isProcessing,
|
|
88933
88977
|
current_permission_mode: conversationPermissionModeState.mode,
|
|
88934
88978
|
current_working_directory: resolvedCwd,
|
|
@@ -88996,7 +89040,7 @@ function setLoopStatus(runtime, status, scope) {
|
|
|
88996
89040
|
emitLoopStatusIfOpen(runtime, scope);
|
|
88997
89041
|
}
|
|
88998
89042
|
function emitProtocolV2Message(socket, runtime, message, scope) {
|
|
88999
|
-
if (socket.readyState !==
|
|
89043
|
+
if (socket.readyState !== WebSocket3.OPEN) {
|
|
89000
89044
|
return;
|
|
89001
89045
|
}
|
|
89002
89046
|
const listener = getListenerRuntime(runtime);
|
|
@@ -89048,13 +89092,13 @@ function emitLoopStatusUpdate(socket, runtime, scope) {
|
|
|
89048
89092
|
}
|
|
89049
89093
|
function emitLoopStatusIfOpen(runtime, scope) {
|
|
89050
89094
|
const listener = getListenerRuntime(runtime);
|
|
89051
|
-
if (listener?.socket?.readyState ===
|
|
89095
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89052
89096
|
emitLoopStatusUpdate(listener.socket, runtime, scope);
|
|
89053
89097
|
}
|
|
89054
89098
|
}
|
|
89055
89099
|
function emitDeviceStatusIfOpen(runtime, scope) {
|
|
89056
89100
|
const listener = getListenerRuntime(runtime);
|
|
89057
|
-
if (listener?.socket?.readyState ===
|
|
89101
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89058
89102
|
emitDeviceStatusUpdate(listener.socket, runtime, scope);
|
|
89059
89103
|
}
|
|
89060
89104
|
}
|
|
@@ -89113,7 +89157,7 @@ function emitDequeuedUserMessage(socket, runtime, incoming, batch) {
|
|
|
89113
89157
|
}
|
|
89114
89158
|
function emitQueueUpdateIfOpen(runtime, scope) {
|
|
89115
89159
|
const listener = getListenerRuntime(runtime);
|
|
89116
|
-
if (listener?.socket?.readyState ===
|
|
89160
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89117
89161
|
emitQueueUpdate(listener.socket, runtime, scope);
|
|
89118
89162
|
}
|
|
89119
89163
|
}
|
|
@@ -89169,7 +89213,7 @@ function emitSubagentStateUpdate(socket, runtime, scope) {
|
|
|
89169
89213
|
}
|
|
89170
89214
|
function emitSubagentStateIfOpen(runtime, scope) {
|
|
89171
89215
|
const listener = getListenerRuntime(runtime);
|
|
89172
|
-
if (listener?.socket?.readyState ===
|
|
89216
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89173
89217
|
emitSubagentStateUpdate(listener.socket, runtime, scope);
|
|
89174
89218
|
}
|
|
89175
89219
|
}
|
|
@@ -89787,7 +89831,7 @@ var init_toolset_labels = __esm(() => {
|
|
|
89787
89831
|
|
|
89788
89832
|
// src/websocket/terminalHandler.ts
|
|
89789
89833
|
import * as os4 from "node:os";
|
|
89790
|
-
import
|
|
89834
|
+
import WebSocket4 from "ws";
|
|
89791
89835
|
function getDefaultShell() {
|
|
89792
89836
|
if (os4.platform() === "win32") {
|
|
89793
89837
|
return process.env.COMSPEC || "cmd.exe";
|
|
@@ -89795,7 +89839,7 @@ function getDefaultShell() {
|
|
|
89795
89839
|
return process.env.SHELL || "/bin/zsh";
|
|
89796
89840
|
}
|
|
89797
89841
|
function sendTerminalMessage(socket, message) {
|
|
89798
|
-
if (socket.readyState ===
|
|
89842
|
+
if (socket.readyState === WebSocket4.OPEN) {
|
|
89799
89843
|
socket.send(JSON.stringify(message));
|
|
89800
89844
|
}
|
|
89801
89845
|
}
|
|
@@ -90163,6 +90207,12 @@ function isEditFileCommand(value) {
|
|
|
90163
90207
|
const c = value;
|
|
90164
90208
|
return c.type === "edit_file" && typeof c.file_path === "string" && typeof c.old_string === "string" && typeof c.new_string === "string" && typeof c.request_id === "string" && (c.replace_all === undefined || typeof c.replace_all === "boolean") && (c.expected_replacements === undefined || typeof c.expected_replacements === "number" && Number.isInteger(c.expected_replacements) && c.expected_replacements > 0);
|
|
90165
90209
|
}
|
|
90210
|
+
function isFileOpsCommand(value) {
|
|
90211
|
+
if (!value || typeof value !== "object")
|
|
90212
|
+
return false;
|
|
90213
|
+
const c = value;
|
|
90214
|
+
return c.type === "file_ops" && typeof c.path === "string" && Array.isArray(c.cg_entries) && Array.isArray(c.ops) && typeof c.source === "string";
|
|
90215
|
+
}
|
|
90166
90216
|
function isListMemoryCommand(value) {
|
|
90167
90217
|
if (!value || typeof value !== "object")
|
|
90168
90218
|
return false;
|
|
@@ -90453,7 +90503,7 @@ function parseServerMessage(data) {
|
|
|
90453
90503
|
try {
|
|
90454
90504
|
const raw = typeof data === "string" ? data : data.toString();
|
|
90455
90505
|
const parsed = JSON.parse(raw);
|
|
90456
|
-
if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isUpdateModelCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isChannelsListCommand(parsed) || isChannelAccountsListCommand(parsed) || isChannelAccountCreateCommand(parsed) || isChannelAccountUpdateCommand(parsed) || isChannelAccountBindCommand(parsed) || isChannelAccountUnbindCommand(parsed) || isChannelAccountDeleteCommand(parsed) || isChannelAccountStartCommand(parsed) || isChannelAccountStopCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelTargetsListCommand(parsed) || isChannelTargetBindCommand(parsed) || isChannelRouteUpdateCommand(parsed) || isChannelRouteRemoveCommand(parsed) || isExecuteCommandCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed)) {
|
|
90506
|
+
if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isFileOpsCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isUpdateModelCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isChannelsListCommand(parsed) || isChannelAccountsListCommand(parsed) || isChannelAccountCreateCommand(parsed) || isChannelAccountUpdateCommand(parsed) || isChannelAccountBindCommand(parsed) || isChannelAccountUnbindCommand(parsed) || isChannelAccountDeleteCommand(parsed) || isChannelAccountStartCommand(parsed) || isChannelAccountStopCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelTargetsListCommand(parsed) || isChannelTargetBindCommand(parsed) || isChannelRouteUpdateCommand(parsed) || isChannelRouteRemoveCommand(parsed) || isExecuteCommandCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed)) {
|
|
90457
90507
|
return parsed;
|
|
90458
90508
|
}
|
|
90459
90509
|
const invalidInput = getInvalidInputReason(parsed);
|
|
@@ -90474,6 +90524,135 @@ var init_protocol_inbound = __esm(async () => {
|
|
|
90474
90524
|
await init_approval();
|
|
90475
90525
|
});
|
|
90476
90526
|
|
|
90527
|
+
// src/websocket/listener/worktree-watcher.ts
|
|
90528
|
+
import { readdir as readdir6, stat as stat5, watch } from "node:fs/promises";
|
|
90529
|
+
import path22 from "node:path";
|
|
90530
|
+
function startWorktreeWatcher(params) {
|
|
90531
|
+
const { runtime, agentId, conversationId } = params;
|
|
90532
|
+
const cwd2 = getConversationWorkingDirectory(runtime, agentId, conversationId);
|
|
90533
|
+
const worktreesDir = path22.join(cwd2, WORKTREES_DIR);
|
|
90534
|
+
const abort = new AbortController;
|
|
90535
|
+
const state = { abort, watchedDir: worktreesDir };
|
|
90536
|
+
runWatchLoop({
|
|
90537
|
+
worktreesDir,
|
|
90538
|
+
abort,
|
|
90539
|
+
runtime,
|
|
90540
|
+
agentId,
|
|
90541
|
+
conversationId
|
|
90542
|
+
}).catch((err) => {
|
|
90543
|
+
if (err.name === "AbortError")
|
|
90544
|
+
return;
|
|
90545
|
+
console.error("[WorktreeWatcher] watch loop error:", err);
|
|
90546
|
+
});
|
|
90547
|
+
return state;
|
|
90548
|
+
}
|
|
90549
|
+
function stopWorktreeWatcher(state) {
|
|
90550
|
+
state.abort.abort();
|
|
90551
|
+
}
|
|
90552
|
+
function stopAllWorktreeWatchers(runtime) {
|
|
90553
|
+
for (const watcher of runtime.worktreeWatcherByConversation.values()) {
|
|
90554
|
+
stopWorktreeWatcher(watcher);
|
|
90555
|
+
}
|
|
90556
|
+
runtime.worktreeWatcherByConversation.clear();
|
|
90557
|
+
}
|
|
90558
|
+
function restartWorktreeWatcher(params) {
|
|
90559
|
+
const { runtime, agentId, conversationId } = params;
|
|
90560
|
+
const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
|
|
90561
|
+
const existing = runtime.worktreeWatcherByConversation.get(scopeKey);
|
|
90562
|
+
if (existing) {
|
|
90563
|
+
stopWorktreeWatcher(existing);
|
|
90564
|
+
runtime.worktreeWatcherByConversation.delete(scopeKey);
|
|
90565
|
+
}
|
|
90566
|
+
const state = startWorktreeWatcher(params);
|
|
90567
|
+
if (state) {
|
|
90568
|
+
runtime.worktreeWatcherByConversation.set(scopeKey, state);
|
|
90569
|
+
}
|
|
90570
|
+
}
|
|
90571
|
+
async function runWatchLoop(params) {
|
|
90572
|
+
const { worktreesDir, abort, runtime, agentId, conversationId } = params;
|
|
90573
|
+
const dirExists = await directoryExists(worktreesDir);
|
|
90574
|
+
if (!dirExists) {
|
|
90575
|
+
const lettaDir = path22.dirname(worktreesDir);
|
|
90576
|
+
const lettaDirExists = await directoryExists(lettaDir);
|
|
90577
|
+
if (!lettaDirExists) {
|
|
90578
|
+
return;
|
|
90579
|
+
}
|
|
90580
|
+
await waitForDirectoryCreation(lettaDir, "worktrees", abort.signal);
|
|
90581
|
+
}
|
|
90582
|
+
const existingEntries = new Set(await safeReaddir(worktreesDir));
|
|
90583
|
+
let debounceTimer = null;
|
|
90584
|
+
const watcher = watch(worktreesDir, { signal: abort.signal });
|
|
90585
|
+
for await (const event of watcher) {
|
|
90586
|
+
if (event.eventType !== "rename" || !event.filename)
|
|
90587
|
+
continue;
|
|
90588
|
+
if (existingEntries.has(event.filename))
|
|
90589
|
+
continue;
|
|
90590
|
+
if (debounceTimer)
|
|
90591
|
+
clearTimeout(debounceTimer);
|
|
90592
|
+
const filename = event.filename;
|
|
90593
|
+
debounceTimer = setTimeout(() => {
|
|
90594
|
+
handleNewWorktree({
|
|
90595
|
+
worktreesDir,
|
|
90596
|
+
filename,
|
|
90597
|
+
runtime,
|
|
90598
|
+
agentId,
|
|
90599
|
+
conversationId
|
|
90600
|
+
});
|
|
90601
|
+
}, DEBOUNCE_MS);
|
|
90602
|
+
}
|
|
90603
|
+
}
|
|
90604
|
+
async function handleNewWorktree(params) {
|
|
90605
|
+
const { worktreesDir, filename, runtime, agentId, conversationId } = params;
|
|
90606
|
+
const newWorktreePath = path22.join(worktreesDir, filename);
|
|
90607
|
+
if (!await directoryExists(newWorktreePath))
|
|
90608
|
+
return;
|
|
90609
|
+
const currentCwd = getConversationWorkingDirectory(runtime, agentId, conversationId);
|
|
90610
|
+
if (currentCwd === newWorktreePath)
|
|
90611
|
+
return;
|
|
90612
|
+
console.log(`[WorktreeWatcher] New worktree detected: ${newWorktreePath} — switching CWD`);
|
|
90613
|
+
setConversationWorkingDirectory(runtime, agentId, conversationId, newWorktreePath);
|
|
90614
|
+
const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
|
|
90615
|
+
const reminderState = runtime.reminderStateByConversation.get(scopeKey);
|
|
90616
|
+
if (reminderState) {
|
|
90617
|
+
reminderState.hasSentSessionContext = false;
|
|
90618
|
+
reminderState.pendingSessionContextReason = "cwd_changed";
|
|
90619
|
+
}
|
|
90620
|
+
if (runtime.socket) {
|
|
90621
|
+
emitDeviceStatusUpdate(runtime.socket, runtime, {
|
|
90622
|
+
agent_id: agentId,
|
|
90623
|
+
conversation_id: conversationId
|
|
90624
|
+
});
|
|
90625
|
+
}
|
|
90626
|
+
}
|
|
90627
|
+
async function waitForDirectoryCreation(parentDir, targetName, signal) {
|
|
90628
|
+
const watcher = watch(parentDir, { signal });
|
|
90629
|
+
for await (const event of watcher) {
|
|
90630
|
+
if (event.eventType === "rename" && event.filename === targetName && await directoryExists(path22.join(parentDir, targetName))) {
|
|
90631
|
+
return;
|
|
90632
|
+
}
|
|
90633
|
+
}
|
|
90634
|
+
}
|
|
90635
|
+
async function directoryExists(dir) {
|
|
90636
|
+
try {
|
|
90637
|
+
const stats = await stat5(dir);
|
|
90638
|
+
return stats.isDirectory();
|
|
90639
|
+
} catch {
|
|
90640
|
+
return false;
|
|
90641
|
+
}
|
|
90642
|
+
}
|
|
90643
|
+
async function safeReaddir(dir) {
|
|
90644
|
+
try {
|
|
90645
|
+
return await readdir6(dir);
|
|
90646
|
+
} catch {
|
|
90647
|
+
return [];
|
|
90648
|
+
}
|
|
90649
|
+
}
|
|
90650
|
+
var WORKTREES_DIR = ".letta/worktrees", DEBOUNCE_MS = 500;
|
|
90651
|
+
var init_worktree_watcher = __esm(async () => {
|
|
90652
|
+
init_cwd();
|
|
90653
|
+
await init_protocol_outbound();
|
|
90654
|
+
});
|
|
90655
|
+
|
|
90477
90656
|
// src/agent/memoryScanner.ts
|
|
90478
90657
|
var exports_memoryScanner = {};
|
|
90479
90658
|
__export(exports_memoryScanner, {
|
|
@@ -90555,10 +90734,10 @@ var init_memoryScanner = () => {};
|
|
|
90555
90734
|
|
|
90556
90735
|
// src/websocket/listener/client.ts
|
|
90557
90736
|
import { execFile as execFile13 } from "node:child_process";
|
|
90558
|
-
import { realpath as realpath3, stat as
|
|
90559
|
-
import
|
|
90737
|
+
import { realpath as realpath3, stat as stat6 } from "node:fs/promises";
|
|
90738
|
+
import path23 from "node:path";
|
|
90560
90739
|
import { promisify as promisify13 } from "node:util";
|
|
90561
|
-
import
|
|
90740
|
+
import WebSocket5 from "ws";
|
|
90562
90741
|
async function loadChannelsService() {
|
|
90563
90742
|
if (channelsServiceLoaderOverride) {
|
|
90564
90743
|
return channelsServiceLoaderOverride();
|
|
@@ -90573,7 +90752,7 @@ function trackListenerError(errorType, error, context3) {
|
|
|
90573
90752
|
});
|
|
90574
90753
|
}
|
|
90575
90754
|
function safeSocketSend(socket, payload, errorType, context3) {
|
|
90576
|
-
if (socket.readyState !==
|
|
90755
|
+
if (socket.readyState !== WebSocket5.OPEN) {
|
|
90577
90756
|
return false;
|
|
90578
90757
|
}
|
|
90579
90758
|
try {
|
|
@@ -91760,8 +91939,8 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
91760
91939
|
const linkPath = join31(globalSkillsDir, linkName);
|
|
91761
91940
|
mkdirSync19(globalSkillsDir, { recursive: true });
|
|
91762
91941
|
if (existsSync26(linkPath)) {
|
|
91763
|
-
const
|
|
91764
|
-
if (
|
|
91942
|
+
const stat7 = lstatSync2(linkPath);
|
|
91943
|
+
if (stat7.isSymbolicLink()) {
|
|
91765
91944
|
if (process.platform === "win32") {
|
|
91766
91945
|
rmdirSync(linkPath);
|
|
91767
91946
|
} else {
|
|
@@ -91810,8 +91989,8 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
91810
91989
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
91811
91990
|
return true;
|
|
91812
91991
|
}
|
|
91813
|
-
const
|
|
91814
|
-
if (!
|
|
91992
|
+
const stat7 = lstatSync2(linkPath);
|
|
91993
|
+
if (!stat7.isSymbolicLink()) {
|
|
91815
91994
|
safeSocketSend(socket, {
|
|
91816
91995
|
type: "skill_disable_response",
|
|
91817
91996
|
request_id: parsed.request_id,
|
|
@@ -92263,9 +92442,9 @@ async function handleCwdChange(msg, socket, runtime) {
|
|
|
92263
92442
|
if (!requestedPath) {
|
|
92264
92443
|
throw new Error("Working directory cannot be empty");
|
|
92265
92444
|
}
|
|
92266
|
-
const resolvedPath =
|
|
92445
|
+
const resolvedPath = path23.isAbsolute(requestedPath) ? requestedPath : path23.resolve(currentWorkingDirectory, requestedPath);
|
|
92267
92446
|
const normalizedPath = await realpath3(resolvedPath);
|
|
92268
|
-
const stats = await
|
|
92447
|
+
const stats = await stat6(normalizedPath);
|
|
92269
92448
|
if (!stats.isDirectory()) {
|
|
92270
92449
|
throw new Error(`Not a directory: ${normalizedPath}`);
|
|
92271
92450
|
}
|
|
@@ -92276,10 +92455,16 @@ async function handleCwdChange(msg, socket, runtime) {
|
|
|
92276
92455
|
if (!normalizedPath.startsWith(currentRoot)) {
|
|
92277
92456
|
setIndexRoot(normalizedPath);
|
|
92278
92457
|
}
|
|
92458
|
+
ensureFileIndex2();
|
|
92279
92459
|
emitDeviceStatusUpdate(socket, runtime, {
|
|
92280
92460
|
agent_id: agentId,
|
|
92281
92461
|
conversation_id: conversationId
|
|
92282
92462
|
});
|
|
92463
|
+
restartWorktreeWatcher({
|
|
92464
|
+
runtime: runtime.listener,
|
|
92465
|
+
agentId,
|
|
92466
|
+
conversationId
|
|
92467
|
+
});
|
|
92283
92468
|
} catch (error) {
|
|
92284
92469
|
emitLoopErrorNotice(socket, runtime, {
|
|
92285
92470
|
message: error instanceof Error ? error.message : "Working directory change failed",
|
|
@@ -92309,6 +92494,7 @@ function createRuntime() {
|
|
|
92309
92494
|
reminderState: createSharedReminderState(),
|
|
92310
92495
|
bootWorkingDirectory,
|
|
92311
92496
|
workingDirectoryByConversation: loadPersistedCwdMap(),
|
|
92497
|
+
worktreeWatcherByConversation: new Map,
|
|
92312
92498
|
permissionModeByConversation: loadPersistedPermissionModeMap(),
|
|
92313
92499
|
reminderStateByConversation: new Map,
|
|
92314
92500
|
contextTrackerByConversation: new Map,
|
|
@@ -92340,6 +92526,7 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
92340
92526
|
runtime.contextTrackerByConversation.clear();
|
|
92341
92527
|
runtime.systemPromptRecompileByConversation.clear();
|
|
92342
92528
|
runtime.queuedSystemPromptRecompileByConversation.clear();
|
|
92529
|
+
stopAllWorktreeWatchers(runtime);
|
|
92343
92530
|
if (!runtime.socket) {
|
|
92344
92531
|
return;
|
|
92345
92532
|
}
|
|
@@ -92348,7 +92535,7 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
92348
92535
|
if (suppressCallbacks) {
|
|
92349
92536
|
socket.removeAllListeners();
|
|
92350
92537
|
}
|
|
92351
|
-
if (socket.readyState ===
|
|
92538
|
+
if (socket.readyState === WebSocket5.OPEN || socket.readyState === WebSocket5.CONNECTING) {
|
|
92352
92539
|
socket.close();
|
|
92353
92540
|
}
|
|
92354
92541
|
}
|
|
@@ -92383,8 +92570,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92383
92570
|
const delay = Math.min(INITIAL_RETRY_DELAY_MS * 2 ** (attempt - 1), MAX_RETRY_DELAY_MS);
|
|
92384
92571
|
const maxAttempts = Math.ceil(Math.log2(MAX_RETRY_DURATION_MS / INITIAL_RETRY_DELAY_MS));
|
|
92385
92572
|
opts.onRetrying?.(attempt, maxAttempts, delay, opts.connectionId);
|
|
92386
|
-
await new Promise((
|
|
92387
|
-
runtime.reconnectTimeout = setTimeout(
|
|
92573
|
+
await new Promise((resolve25) => {
|
|
92574
|
+
runtime.reconnectTimeout = setTimeout(resolve25, delay);
|
|
92388
92575
|
});
|
|
92389
92576
|
runtime.reconnectTimeout = null;
|
|
92390
92577
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
@@ -92403,7 +92590,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92403
92590
|
const url = new URL(opts.wsUrl);
|
|
92404
92591
|
url.searchParams.set("deviceId", opts.deviceId);
|
|
92405
92592
|
url.searchParams.set("connectionName", opts.connectionName);
|
|
92406
|
-
const socket = new
|
|
92593
|
+
const socket = new WebSocket5(url.toString(), {
|
|
92407
92594
|
headers: {
|
|
92408
92595
|
Authorization: `Bearer ${apiKey}`
|
|
92409
92596
|
}
|
|
@@ -92457,7 +92644,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92457
92644
|
});
|
|
92458
92645
|
runtime._unsubscribeSubagentStreamEvents?.();
|
|
92459
92646
|
runtime._unsubscribeSubagentStreamEvents = subscribeToStreamEvents((subagentId, event) => {
|
|
92460
|
-
if (socket.readyState !==
|
|
92647
|
+
if (socket.readyState !== WebSocket5.OPEN)
|
|
92461
92648
|
return;
|
|
92462
92649
|
const subagent = getSubagents().find((entry) => entry.id === subagentId);
|
|
92463
92650
|
if (subagent?.silent === true) {
|
|
@@ -92483,7 +92670,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92483
92670
|
scheduleQueuePump(targetRuntime, socket, opts, processQueuedTurn);
|
|
92484
92671
|
});
|
|
92485
92672
|
runtime.heartbeatInterval = setInterval(() => {
|
|
92486
|
-
if (socket.readyState ===
|
|
92673
|
+
if (socket.readyState === WebSocket5.OPEN) {
|
|
92487
92674
|
safeSocketSend(socket, { type: "ping" }, "listener_ping_send_failed", "listener_heartbeat");
|
|
92488
92675
|
}
|
|
92489
92676
|
}, 30000);
|
|
@@ -92644,14 +92831,14 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92644
92831
|
try {
|
|
92645
92832
|
if (parsed.cwd) {
|
|
92646
92833
|
const currentRoot = getIndexRoot();
|
|
92647
|
-
if (!parsed.cwd.startsWith(currentRoot +
|
|
92834
|
+
if (!parsed.cwd.startsWith(currentRoot + path23.sep) && parsed.cwd !== currentRoot) {
|
|
92648
92835
|
setIndexRoot(parsed.cwd);
|
|
92649
92836
|
}
|
|
92650
92837
|
}
|
|
92651
92838
|
await ensureFileIndex2();
|
|
92652
92839
|
let searchDir = ".";
|
|
92653
92840
|
if (parsed.cwd) {
|
|
92654
|
-
const rel =
|
|
92841
|
+
const rel = path23.relative(getIndexRoot(), parsed.cwd);
|
|
92655
92842
|
if (rel && !rel.startsWith("..") && rel !== "") {
|
|
92656
92843
|
searchDir = rel;
|
|
92657
92844
|
}
|
|
@@ -92685,9 +92872,9 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92685
92872
|
console.log(`[Listen] Received list_in_directory command: path=${parsed.path}`);
|
|
92686
92873
|
runDetachedListenerTask("list_in_directory", async () => {
|
|
92687
92874
|
try {
|
|
92688
|
-
const { readdir:
|
|
92875
|
+
const { readdir: readdir7 } = await import("node:fs/promises");
|
|
92689
92876
|
console.log(`[Listen] Reading directory: ${parsed.path}`);
|
|
92690
|
-
const entries = await
|
|
92877
|
+
const entries = await readdir7(parsed.path, { withFileTypes: true });
|
|
92691
92878
|
console.log(`[Listen] Directory read success, ${entries.length} entries`);
|
|
92692
92879
|
const IGNORED_NAMES = new Set([
|
|
92693
92880
|
".DS_Store",
|
|
@@ -92746,8 +92933,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92746
92933
|
console.log(`[Listen] Received read_file command: path=${parsed.path}, request_id=${parsed.request_id}`);
|
|
92747
92934
|
runDetachedListenerTask("read_file", async () => {
|
|
92748
92935
|
try {
|
|
92749
|
-
const { readFile:
|
|
92750
|
-
const content = await
|
|
92936
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
92937
|
+
const content = await readFile11(parsed.path, "utf-8");
|
|
92751
92938
|
console.log(`[Listen] read_file success: ${parsed.path} (${content.length} bytes)`);
|
|
92752
92939
|
safeSocketSend(socket, {
|
|
92753
92940
|
type: "read_file_response",
|
|
@@ -92777,10 +92964,10 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92777
92964
|
try {
|
|
92778
92965
|
const { edit: edit2 } = await Promise.resolve().then(() => (init_Edit2(), exports_Edit));
|
|
92779
92966
|
const { write: write2 } = await Promise.resolve().then(() => (init_Write2(), exports_Write));
|
|
92780
|
-
const { readFile:
|
|
92967
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
92781
92968
|
let currentContent = null;
|
|
92782
92969
|
try {
|
|
92783
|
-
currentContent = await
|
|
92970
|
+
currentContent = await readFile11(parsed.path, "utf-8");
|
|
92784
92971
|
} catch (readErr) {
|
|
92785
92972
|
const e = readErr;
|
|
92786
92973
|
if (e.code !== "ENOENT")
|
|
@@ -92829,11 +93016,11 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92829
93016
|
return;
|
|
92830
93017
|
}
|
|
92831
93018
|
try {
|
|
92832
|
-
const { watch } = await import("node:fs");
|
|
92833
|
-
const { stat:
|
|
93019
|
+
const { watch: watch2 } = await import("node:fs");
|
|
93020
|
+
const { stat: stat7 } = await import("node:fs/promises");
|
|
92834
93021
|
if (cancelledWatches.delete(parsed.path))
|
|
92835
93022
|
return;
|
|
92836
|
-
const watcher =
|
|
93023
|
+
const watcher = watch2(parsed.path, { persistent: false }, (eventType) => {
|
|
92837
93024
|
if (eventType !== "change" && eventType !== "rename")
|
|
92838
93025
|
return;
|
|
92839
93026
|
const existing2 = watchDebounceTimers.get(parsed.path);
|
|
@@ -92841,7 +93028,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92841
93028
|
clearTimeout(existing2);
|
|
92842
93029
|
watchDebounceTimers.set(parsed.path, setTimeout(() => {
|
|
92843
93030
|
watchDebounceTimers.delete(parsed.path);
|
|
92844
|
-
|
|
93031
|
+
stat7(parsed.path).then((s) => {
|
|
92845
93032
|
safeSocketSend(socket, {
|
|
92846
93033
|
type: "file_changed",
|
|
92847
93034
|
path: parsed.path,
|
|
@@ -92887,6 +93074,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92887
93074
|
console.log(`[Listen] Received edit_file command: file_path=${parsed.file_path}, request_id=${parsed.request_id}`);
|
|
92888
93075
|
runDetachedListenerTask("edit_file", async () => {
|
|
92889
93076
|
try {
|
|
93077
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
92890
93078
|
const { edit: edit2 } = await Promise.resolve().then(() => (init_Edit2(), exports_Edit));
|
|
92891
93079
|
console.log(`[Listen] Executing edit: old_string="${parsed.old_string.slice(0, 50)}${parsed.old_string.length > 50 ? "..." : ""}"`);
|
|
92892
93080
|
const result = await edit2({
|
|
@@ -92897,6 +93085,19 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92897
93085
|
expected_replacements: parsed.expected_replacements
|
|
92898
93086
|
});
|
|
92899
93087
|
console.log(`[Listen] edit_file success: ${result.replacements} replacement(s) at line ${result.startLine}`);
|
|
93088
|
+
if (result.replacements > 0) {
|
|
93089
|
+
try {
|
|
93090
|
+
const contentAfter = await readFile11(parsed.file_path, "utf-8");
|
|
93091
|
+
safeSocketSend(socket, {
|
|
93092
|
+
type: "file_ops",
|
|
93093
|
+
path: parsed.file_path,
|
|
93094
|
+
cg_entries: [],
|
|
93095
|
+
ops: [],
|
|
93096
|
+
source: "agent",
|
|
93097
|
+
document_content: contentAfter
|
|
93098
|
+
}, "listener_edit_file_ops_send_failed", "listener_edit_file");
|
|
93099
|
+
} catch {}
|
|
93100
|
+
}
|
|
92900
93101
|
safeSocketSend(socket, {
|
|
92901
93102
|
type: "edit_file_response",
|
|
92902
93103
|
request_id: parsed.request_id,
|
|
@@ -92922,6 +93123,21 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92922
93123
|
});
|
|
92923
93124
|
return;
|
|
92924
93125
|
}
|
|
93126
|
+
if (isFileOpsCommand(parsed)) {
|
|
93127
|
+
if (parsed.document_content !== undefined) {
|
|
93128
|
+
runDetachedListenerTask("file_ops", async () => {
|
|
93129
|
+
try {
|
|
93130
|
+
const { writeFile: writeFile9 } = await import("node:fs/promises");
|
|
93131
|
+
const content = parsed.document_content;
|
|
93132
|
+
await writeFile9(parsed.path, content, "utf-8");
|
|
93133
|
+
console.log(`[Listen] file_ops: wrote ${content.length} bytes to ${parsed.path}`);
|
|
93134
|
+
} catch (err) {
|
|
93135
|
+
console.error(`[Listen] file_ops error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
93136
|
+
}
|
|
93137
|
+
});
|
|
93138
|
+
}
|
|
93139
|
+
return;
|
|
93140
|
+
}
|
|
92925
93141
|
if (isListMemoryCommand(parsed)) {
|
|
92926
93142
|
runDetachedListenerTask("list_memory", async () => {
|
|
92927
93143
|
try {
|
|
@@ -93606,6 +93822,12 @@ function createLegacyTestRuntime() {
|
|
|
93606
93822
|
listener.memfsSyncedAgents = value;
|
|
93607
93823
|
}
|
|
93608
93824
|
},
|
|
93825
|
+
worktreeWatcherByConversation: {
|
|
93826
|
+
get: () => listener.worktreeWatcherByConversation,
|
|
93827
|
+
set: (value) => {
|
|
93828
|
+
listener.worktreeWatcherByConversation = value;
|
|
93829
|
+
}
|
|
93830
|
+
},
|
|
93609
93831
|
lastEmittedStatus: {
|
|
93610
93832
|
get: () => listener.lastEmittedStatus,
|
|
93611
93833
|
set: (value) => {
|
|
@@ -93675,6 +93897,7 @@ var init_client4 = __esm(async () => {
|
|
|
93675
93897
|
init_recovery(),
|
|
93676
93898
|
init_send(),
|
|
93677
93899
|
init_turn(),
|
|
93900
|
+
init_worktree_watcher(),
|
|
93678
93901
|
init_approval(),
|
|
93679
93902
|
init_protocol_inbound(),
|
|
93680
93903
|
init_protocol_outbound()
|
|
@@ -93788,8 +94011,8 @@ function isDebugEnabled2() {
|
|
|
93788
94011
|
return lettaDebug === "1" || lettaDebug === "true" || legacyDebug === "1" || legacyDebug === "true";
|
|
93789
94012
|
}
|
|
93790
94013
|
function getDebugFile2() {
|
|
93791
|
-
const
|
|
93792
|
-
return
|
|
94014
|
+
const path24 = process.env.LETTA_DEBUG_FILE;
|
|
94015
|
+
return path24 && path24.trim().length > 0 ? path24 : null;
|
|
93793
94016
|
}
|
|
93794
94017
|
function printDebugLine2(line, level = "log") {
|
|
93795
94018
|
const debugFile = getDebugFile2();
|
|
@@ -93913,7 +94136,7 @@ __export(exports_skills2, {
|
|
|
93913
94136
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
93914
94137
|
});
|
|
93915
94138
|
import { existsSync as existsSync28 } from "node:fs";
|
|
93916
|
-
import { readdir as
|
|
94139
|
+
import { readdir as readdir8, readFile as readFile11, realpath as realpath4, stat as stat7 } from "node:fs/promises";
|
|
93917
94140
|
import { dirname as dirname13, join as join35 } from "node:path";
|
|
93918
94141
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
93919
94142
|
function getBundledSkillsPath2() {
|
|
@@ -94003,14 +94226,14 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
|
|
|
94003
94226
|
return;
|
|
94004
94227
|
}
|
|
94005
94228
|
try {
|
|
94006
|
-
const entries = await
|
|
94229
|
+
const entries = await readdir8(currentPath, { withFileTypes: true });
|
|
94007
94230
|
for (const entry of entries) {
|
|
94008
94231
|
const fullPath = join35(currentPath, entry.name);
|
|
94009
94232
|
try {
|
|
94010
94233
|
let isDirectory = entry.isDirectory();
|
|
94011
94234
|
let isFile = entry.isFile();
|
|
94012
94235
|
if (entry.isSymbolicLink()) {
|
|
94013
|
-
const entryStat = await
|
|
94236
|
+
const entryStat = await stat7(fullPath);
|
|
94014
94237
|
isDirectory = entryStat.isDirectory();
|
|
94015
94238
|
isFile = entryStat.isFile();
|
|
94016
94239
|
}
|
|
@@ -94044,7 +94267,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
|
|
|
94044
94267
|
}
|
|
94045
94268
|
}
|
|
94046
94269
|
async function parseSkillFile2(filePath, rootPath, source) {
|
|
94047
|
-
const content = await
|
|
94270
|
+
const content = await readFile11(filePath, "utf-8");
|
|
94048
94271
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
94049
94272
|
const normalizedRoot = rootPath.endsWith("/") ? rootPath.slice(0, -1) : rootPath;
|
|
94050
94273
|
const relativePath = filePath.slice(normalizedRoot.length + 1);
|
|
@@ -94103,7 +94326,7 @@ __export(exports_fs, {
|
|
|
94103
94326
|
writeJsonFile: () => writeJsonFile,
|
|
94104
94327
|
writeFile: () => writeFile10,
|
|
94105
94328
|
readJsonFile: () => readJsonFile,
|
|
94106
|
-
readFile: () =>
|
|
94329
|
+
readFile: () => readFile12,
|
|
94107
94330
|
mkdir: () => mkdir9,
|
|
94108
94331
|
exists: () => exists2
|
|
94109
94332
|
});
|
|
@@ -94114,31 +94337,31 @@ import {
|
|
|
94114
94337
|
mkdirSync as mkdirSync21
|
|
94115
94338
|
} from "node:fs";
|
|
94116
94339
|
import { dirname as dirname14 } from "node:path";
|
|
94117
|
-
async function
|
|
94118
|
-
return fsReadFileSync2(
|
|
94340
|
+
async function readFile12(path24) {
|
|
94341
|
+
return fsReadFileSync2(path24, { encoding: "utf-8" });
|
|
94119
94342
|
}
|
|
94120
|
-
async function writeFile10(
|
|
94121
|
-
const dir = dirname14(
|
|
94343
|
+
async function writeFile10(path24, content) {
|
|
94344
|
+
const dir = dirname14(path24);
|
|
94122
94345
|
if (!existsSync29(dir)) {
|
|
94123
94346
|
mkdirSync21(dir, { recursive: true });
|
|
94124
94347
|
}
|
|
94125
|
-
fsWriteFileSync2(
|
|
94348
|
+
fsWriteFileSync2(path24, content, { encoding: "utf-8", flush: true });
|
|
94126
94349
|
}
|
|
94127
|
-
function exists2(
|
|
94128
|
-
return existsSync29(
|
|
94350
|
+
function exists2(path24) {
|
|
94351
|
+
return existsSync29(path24);
|
|
94129
94352
|
}
|
|
94130
|
-
async function mkdir9(
|
|
94131
|
-
mkdirSync21(
|
|
94353
|
+
async function mkdir9(path24, options) {
|
|
94354
|
+
mkdirSync21(path24, options);
|
|
94132
94355
|
}
|
|
94133
|
-
async function readJsonFile(
|
|
94134
|
-
const text = await
|
|
94356
|
+
async function readJsonFile(path24) {
|
|
94357
|
+
const text = await readFile12(path24);
|
|
94135
94358
|
return JSON.parse(text);
|
|
94136
94359
|
}
|
|
94137
|
-
async function writeJsonFile(
|
|
94360
|
+
async function writeJsonFile(path24, data, options) {
|
|
94138
94361
|
const indent = options?.indent ?? 2;
|
|
94139
94362
|
const content = `${JSON.stringify(data, null, indent)}
|
|
94140
94363
|
`;
|
|
94141
|
-
await writeFile10(
|
|
94364
|
+
await writeFile10(path24, content);
|
|
94142
94365
|
}
|
|
94143
94366
|
var init_fs2 = () => {};
|
|
94144
94367
|
|
|
@@ -94163,7 +94386,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94163
94386
|
}
|
|
94164
94387
|
const wasRaw = process.stdin.isRaw;
|
|
94165
94388
|
const wasFlowing = process.stdin.readableFlowing;
|
|
94166
|
-
return new Promise((
|
|
94389
|
+
return new Promise((resolve27) => {
|
|
94167
94390
|
let response = "";
|
|
94168
94391
|
let resolved = false;
|
|
94169
94392
|
const cleanup = () => {
|
|
@@ -94180,7 +94403,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94180
94403
|
};
|
|
94181
94404
|
const timeout = setTimeout(() => {
|
|
94182
94405
|
cleanup();
|
|
94183
|
-
|
|
94406
|
+
resolve27(null);
|
|
94184
94407
|
}, timeoutMs);
|
|
94185
94408
|
const onData = (data) => {
|
|
94186
94409
|
response += data.toString();
|
|
@@ -94190,7 +94413,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94190
94413
|
if (match3) {
|
|
94191
94414
|
clearTimeout(timeout);
|
|
94192
94415
|
cleanup();
|
|
94193
|
-
|
|
94416
|
+
resolve27({
|
|
94194
94417
|
r: parseHexComponent(match3[1] ?? "0"),
|
|
94195
94418
|
g: parseHexComponent(match3[2] ?? "0"),
|
|
94196
94419
|
b: parseHexComponent(match3[3] ?? "0")
|
|
@@ -94205,7 +94428,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94205
94428
|
} catch {
|
|
94206
94429
|
clearTimeout(timeout);
|
|
94207
94430
|
cleanup();
|
|
94208
|
-
|
|
94431
|
+
resolve27(null);
|
|
94209
94432
|
}
|
|
94210
94433
|
});
|
|
94211
94434
|
}
|
|
@@ -94291,7 +94514,7 @@ __export(exports_manager2, {
|
|
|
94291
94514
|
lspManager: () => lspManager2,
|
|
94292
94515
|
LSPManager: () => LSPManager2
|
|
94293
94516
|
});
|
|
94294
|
-
import * as
|
|
94517
|
+
import * as path24 from "node:path";
|
|
94295
94518
|
|
|
94296
94519
|
class LSPManager2 {
|
|
94297
94520
|
static instance = null;
|
|
@@ -94319,7 +94542,7 @@ class LSPManager2 {
|
|
|
94319
94542
|
async getOrStartServer(filePath) {
|
|
94320
94543
|
if (!this.enabled)
|
|
94321
94544
|
return null;
|
|
94322
|
-
const ext3 =
|
|
94545
|
+
const ext3 = path24.extname(filePath).toLowerCase();
|
|
94323
94546
|
const serverDef = this.serverDefinitions.find((s) => s.extensions.includes(ext3));
|
|
94324
94547
|
if (!serverDef) {
|
|
94325
94548
|
return null;
|
|
@@ -94387,7 +94610,7 @@ class LSPManager2 {
|
|
|
94387
94610
|
const client = await this.getOrStartServer(filePath);
|
|
94388
94611
|
if (!client)
|
|
94389
94612
|
return;
|
|
94390
|
-
const absolutePath =
|
|
94613
|
+
const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
|
|
94391
94614
|
const uri = `file://${absolutePath}`;
|
|
94392
94615
|
const existing = this.openDocuments.get(absolutePath);
|
|
94393
94616
|
if (!existing) {
|
|
@@ -94415,7 +94638,7 @@ class LSPManager2 {
|
|
|
94415
94638
|
if (!this.enabled)
|
|
94416
94639
|
return [];
|
|
94417
94640
|
if (filePath) {
|
|
94418
|
-
const absolutePath =
|
|
94641
|
+
const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
|
|
94419
94642
|
return this.diagnostics.get(absolutePath) || [];
|
|
94420
94643
|
}
|
|
94421
94644
|
const all = [];
|
|
@@ -94425,7 +94648,7 @@ class LSPManager2 {
|
|
|
94425
94648
|
return all;
|
|
94426
94649
|
}
|
|
94427
94650
|
getLanguageId(filePath) {
|
|
94428
|
-
const ext3 =
|
|
94651
|
+
const ext3 = path24.extname(filePath).toLowerCase();
|
|
94429
94652
|
const languageMap = {
|
|
94430
94653
|
".ts": "typescript",
|
|
94431
94654
|
".tsx": "typescriptreact",
|
|
@@ -94476,7 +94699,7 @@ __export(exports_auto_update, {
|
|
|
94476
94699
|
});
|
|
94477
94700
|
import { execFile as execFile14 } from "node:child_process";
|
|
94478
94701
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
94479
|
-
import { readdir as
|
|
94702
|
+
import { readdir as readdir9, rm as rm3 } from "node:fs/promises";
|
|
94480
94703
|
import { join as join37 } from "node:path";
|
|
94481
94704
|
import { promisify as promisify14 } from "node:util";
|
|
94482
94705
|
function debugLog4(...args) {
|
|
@@ -94644,7 +94867,7 @@ async function getNpmGlobalPath() {
|
|
|
94644
94867
|
async function cleanupOrphanedDirs(globalPath) {
|
|
94645
94868
|
const lettaAiDir = join37(globalPath, "lib/node_modules/@letta-ai");
|
|
94646
94869
|
try {
|
|
94647
|
-
const entries = await
|
|
94870
|
+
const entries = await readdir9(lettaAiDir);
|
|
94648
94871
|
for (const entry of entries) {
|
|
94649
94872
|
if (entry.startsWith(".letta-code-")) {
|
|
94650
94873
|
const orphanPath = join37(lettaAiDir, entry);
|
|
@@ -94895,13 +95118,13 @@ __export(exports_overflow, {
|
|
|
94895
95118
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
94896
95119
|
import * as fs15 from "node:fs";
|
|
94897
95120
|
import * as os5 from "node:os";
|
|
94898
|
-
import * as
|
|
95121
|
+
import * as path25 from "node:path";
|
|
94899
95122
|
function getOverflowDirectory2(workingDirectory) {
|
|
94900
95123
|
const homeDir = os5.homedir();
|
|
94901
|
-
const lettaDir =
|
|
94902
|
-
const normalizedPath =
|
|
95124
|
+
const lettaDir = path25.join(homeDir, ".letta");
|
|
95125
|
+
const normalizedPath = path25.normalize(workingDirectory);
|
|
94903
95126
|
const sanitizedPath = normalizedPath.replace(/^[/\\]/, "").replace(/[/\\:]/g, "_").replace(/\s+/g, "_");
|
|
94904
|
-
const overflowDir =
|
|
95127
|
+
const overflowDir = path25.join(lettaDir, "projects", sanitizedPath, "agent-tools");
|
|
94905
95128
|
return overflowDir;
|
|
94906
95129
|
}
|
|
94907
95130
|
function ensureOverflowDirectory2(workingDirectory) {
|
|
@@ -94915,7 +95138,7 @@ function writeOverflowFile2(content, workingDirectory, toolName) {
|
|
|
94915
95138
|
const overflowDir = ensureOverflowDirectory2(workingDirectory);
|
|
94916
95139
|
const uuid = randomUUID10();
|
|
94917
95140
|
const filename = toolName ? `${toolName.toLowerCase()}-${uuid}.txt` : `${uuid}.txt`;
|
|
94918
|
-
const filePath =
|
|
95141
|
+
const filePath = path25.join(overflowDir, filename);
|
|
94919
95142
|
fs15.writeFileSync(filePath, content, "utf-8");
|
|
94920
95143
|
return filePath;
|
|
94921
95144
|
}
|
|
@@ -94933,7 +95156,7 @@ function cleanupOldOverflowFiles(workingDirectory, maxAgeMs = 24 * 60 * 60 * 100
|
|
|
94933
95156
|
const now = Date.now();
|
|
94934
95157
|
let deletedCount = 0;
|
|
94935
95158
|
for (const file of files) {
|
|
94936
|
-
const filePath =
|
|
95159
|
+
const filePath = path25.join(overflowDir, file);
|
|
94937
95160
|
try {
|
|
94938
95161
|
const stats = fs15.statSync(filePath);
|
|
94939
95162
|
if (stats.isDirectory()) {
|
|
@@ -94960,7 +95183,7 @@ function getOverflowStats(workingDirectory) {
|
|
|
94960
95183
|
const files = fs15.readdirSync(overflowDir);
|
|
94961
95184
|
let totalSize = 0;
|
|
94962
95185
|
for (const file of files) {
|
|
94963
|
-
const filePath =
|
|
95186
|
+
const filePath = path25.join(overflowDir, file);
|
|
94964
95187
|
const stats = fs15.statSync(filePath);
|
|
94965
95188
|
totalSize += stats.size;
|
|
94966
95189
|
}
|
|
@@ -95438,10 +95661,10 @@ __export(exports_setup, {
|
|
|
95438
95661
|
runSetup: () => runSetup
|
|
95439
95662
|
});
|
|
95440
95663
|
async function runSetup() {
|
|
95441
|
-
return new Promise((
|
|
95664
|
+
return new Promise((resolve28) => {
|
|
95442
95665
|
const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
|
|
95443
95666
|
onComplete: () => {
|
|
95444
|
-
|
|
95667
|
+
resolve28();
|
|
95445
95668
|
}
|
|
95446
95669
|
}));
|
|
95447
95670
|
waitUntilExit().catch((error) => {
|
|
@@ -95936,8 +96159,8 @@ __export(exports_github_utils, {
|
|
|
95936
96159
|
parseDirNames: () => parseDirNames,
|
|
95937
96160
|
fetchGitHubContents: () => fetchGitHubContents
|
|
95938
96161
|
});
|
|
95939
|
-
async function fetchGitHubContents(owner, repo, branch,
|
|
95940
|
-
const apiPath =
|
|
96162
|
+
async function fetchGitHubContents(owner, repo, branch, path26) {
|
|
96163
|
+
const apiPath = path26 ? `repos/${owner}/${repo}/contents/${path26}?ref=${branch}` : `repos/${owner}/${repo}/contents?ref=${branch}`;
|
|
95941
96164
|
try {
|
|
95942
96165
|
const { execSync: execSync2 } = await import("node:child_process");
|
|
95943
96166
|
const result = execSync2(`gh api ${apiPath}`, {
|
|
@@ -95946,7 +96169,7 @@ async function fetchGitHubContents(owner, repo, branch, path25) {
|
|
|
95946
96169
|
});
|
|
95947
96170
|
return JSON.parse(result);
|
|
95948
96171
|
} catch {}
|
|
95949
|
-
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${
|
|
96172
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path26}?ref=${branch}`;
|
|
95950
96173
|
const response = await fetch(url, {
|
|
95951
96174
|
headers: {
|
|
95952
96175
|
Accept: "application/vnd.github.v3+json",
|
|
@@ -95954,7 +96177,7 @@ async function fetchGitHubContents(owner, repo, branch, path25) {
|
|
|
95954
96177
|
}
|
|
95955
96178
|
});
|
|
95956
96179
|
if (!response.ok) {
|
|
95957
|
-
throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${
|
|
96180
|
+
throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${path26}: ${response.statusText}`);
|
|
95958
96181
|
}
|
|
95959
96182
|
return await response.json();
|
|
95960
96183
|
}
|
|
@@ -95970,11 +96193,11 @@ __export(exports_import, {
|
|
|
95970
96193
|
extractSkillsFromAf: () => extractSkillsFromAf
|
|
95971
96194
|
});
|
|
95972
96195
|
import { createReadStream } from "node:fs";
|
|
95973
|
-
import { chmod, mkdir as mkdir10, readFile as
|
|
95974
|
-
import { dirname as dirname15, resolve as
|
|
96196
|
+
import { chmod, mkdir as mkdir10, readFile as readFile13, writeFile as writeFile11 } from "node:fs/promises";
|
|
96197
|
+
import { dirname as dirname15, resolve as resolve28 } from "node:path";
|
|
95975
96198
|
async function importAgentFromFile(options) {
|
|
95976
96199
|
const client = await getClient();
|
|
95977
|
-
const resolvedPath =
|
|
96200
|
+
const resolvedPath = resolve28(options.filePath);
|
|
95978
96201
|
const file = createReadStream(resolvedPath);
|
|
95979
96202
|
const importResponse = await client.agents.importFile({
|
|
95980
96203
|
file,
|
|
@@ -96003,13 +96226,13 @@ async function importAgentFromFile(options) {
|
|
|
96003
96226
|
}
|
|
96004
96227
|
async function extractSkillsFromAf(afPath, destDir) {
|
|
96005
96228
|
const extracted = [];
|
|
96006
|
-
const content = await
|
|
96229
|
+
const content = await readFile13(afPath, "utf-8");
|
|
96007
96230
|
const afData = JSON.parse(content);
|
|
96008
96231
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
96009
96232
|
return [];
|
|
96010
96233
|
}
|
|
96011
96234
|
for (const skill2 of afData.skills) {
|
|
96012
|
-
const skillDir =
|
|
96235
|
+
const skillDir = resolve28(destDir, skill2.name);
|
|
96013
96236
|
await mkdir10(skillDir, { recursive: true });
|
|
96014
96237
|
if (skill2.files) {
|
|
96015
96238
|
await writeSkillFiles(skillDir, skill2.files);
|
|
@@ -96029,7 +96252,7 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
96029
96252
|
}
|
|
96030
96253
|
}
|
|
96031
96254
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
96032
|
-
const fullPath =
|
|
96255
|
+
const fullPath = resolve28(skillDir, filePath);
|
|
96033
96256
|
await mkdir10(dirname15(fullPath), { recursive: true });
|
|
96034
96257
|
await writeFile11(fullPath, content, "utf-8");
|
|
96035
96258
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
@@ -96048,13 +96271,13 @@ async function fetchSkillFromUrl(skillDir, sourceUrl) {
|
|
|
96048
96271
|
const owner = parts[0];
|
|
96049
96272
|
const repo = parts[1];
|
|
96050
96273
|
const branch = parts[2];
|
|
96051
|
-
const
|
|
96274
|
+
const path26 = parts.slice(3).join("/");
|
|
96052
96275
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
96053
|
-
const entries = await fetchGitHubContents2(owner, repo, branch,
|
|
96276
|
+
const entries = await fetchGitHubContents2(owner, repo, branch, path26);
|
|
96054
96277
|
if (!Array.isArray(entries)) {
|
|
96055
96278
|
throw new Error(`Expected directory at ${sourceUrl}, got file`);
|
|
96056
96279
|
}
|
|
96057
|
-
await downloadGitHubDirectory(entries, skillDir, owner, repo, branch,
|
|
96280
|
+
await downloadGitHubDirectory(entries, skillDir, owner, repo, branch, path26);
|
|
96058
96281
|
}
|
|
96059
96282
|
async function downloadGitHubDirectory(entries, destDir, owner, repo, branch, basePath) {
|
|
96060
96283
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
@@ -96361,12 +96584,12 @@ async function prepareHeadlessToolExecutionContext(params) {
|
|
|
96361
96584
|
};
|
|
96362
96585
|
}
|
|
96363
96586
|
async function flushAndExit(code) {
|
|
96364
|
-
const flushWritable = (stream2) => new Promise((
|
|
96587
|
+
const flushWritable = (stream2) => new Promise((resolve29) => {
|
|
96365
96588
|
if (stream2.destroyed || stream2.writableEnded) {
|
|
96366
|
-
|
|
96589
|
+
resolve29();
|
|
96367
96590
|
return;
|
|
96368
96591
|
}
|
|
96369
|
-
stream2.write("", () =>
|
|
96592
|
+
stream2.write("", () => resolve29());
|
|
96370
96593
|
});
|
|
96371
96594
|
await Promise.allSettled([
|
|
96372
96595
|
flushWritable(process.stdout),
|
|
@@ -97325,7 +97548,7 @@ ${loadedContents.join(`
|
|
|
97325
97548
|
} else {
|
|
97326
97549
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
97327
97550
|
}
|
|
97328
|
-
await new Promise((
|
|
97551
|
+
await new Promise((resolve29) => setTimeout(resolve29, retryDelayMs));
|
|
97329
97552
|
continue;
|
|
97330
97553
|
}
|
|
97331
97554
|
}
|
|
@@ -97374,7 +97597,7 @@ ${loadedContents.join(`
|
|
|
97374
97597
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97375
97598
|
console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97376
97599
|
}
|
|
97377
|
-
await new Promise((
|
|
97600
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97378
97601
|
conversationBusyRetries = 0;
|
|
97379
97602
|
continue;
|
|
97380
97603
|
}
|
|
@@ -97613,7 +97836,7 @@ ${loadedContents.join(`
|
|
|
97613
97836
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97614
97837
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97615
97838
|
}
|
|
97616
|
-
await new Promise((
|
|
97839
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97617
97840
|
refreshCurrentInputOtids();
|
|
97618
97841
|
continue;
|
|
97619
97842
|
}
|
|
@@ -97703,7 +97926,7 @@ ${loadedContents.join(`
|
|
|
97703
97926
|
} else {
|
|
97704
97927
|
console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
97705
97928
|
}
|
|
97706
|
-
await new Promise((
|
|
97929
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97707
97930
|
refreshCurrentInputOtids();
|
|
97708
97931
|
continue;
|
|
97709
97932
|
}
|
|
@@ -97731,7 +97954,7 @@ ${loadedContents.join(`
|
|
|
97731
97954
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97732
97955
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97733
97956
|
}
|
|
97734
|
-
await new Promise((
|
|
97957
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97735
97958
|
refreshCurrentInputOtids();
|
|
97736
97959
|
continue;
|
|
97737
97960
|
}
|
|
@@ -97761,7 +97984,7 @@ ${loadedContents.join(`
|
|
|
97761
97984
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97762
97985
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97763
97986
|
}
|
|
97764
|
-
await new Promise((
|
|
97987
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97765
97988
|
refreshCurrentInputOtids();
|
|
97766
97989
|
continue;
|
|
97767
97990
|
}
|
|
@@ -98101,9 +98324,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98101
98324
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
98102
98325
|
maybeNotifyBlocked(syntheticUserLine);
|
|
98103
98326
|
if (lineResolver) {
|
|
98104
|
-
const
|
|
98327
|
+
const resolve29 = lineResolver;
|
|
98105
98328
|
lineResolver = null;
|
|
98106
|
-
|
|
98329
|
+
resolve29(syntheticUserLine);
|
|
98107
98330
|
return;
|
|
98108
98331
|
}
|
|
98109
98332
|
lineQueue.push(syntheticUserLine);
|
|
@@ -98111,9 +98334,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98111
98334
|
rl.on("line", (line) => {
|
|
98112
98335
|
maybeNotifyBlocked(line);
|
|
98113
98336
|
if (lineResolver) {
|
|
98114
|
-
const
|
|
98337
|
+
const resolve29 = lineResolver;
|
|
98115
98338
|
lineResolver = null;
|
|
98116
|
-
|
|
98339
|
+
resolve29(line);
|
|
98117
98340
|
} else {
|
|
98118
98341
|
lineQueue.push(line);
|
|
98119
98342
|
}
|
|
@@ -98122,17 +98345,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98122
98345
|
setMessageQueueAdder(null);
|
|
98123
98346
|
msgQueueRuntime.clear("shutdown");
|
|
98124
98347
|
if (lineResolver) {
|
|
98125
|
-
const
|
|
98348
|
+
const resolve29 = lineResolver;
|
|
98126
98349
|
lineResolver = null;
|
|
98127
|
-
|
|
98350
|
+
resolve29(null);
|
|
98128
98351
|
}
|
|
98129
98352
|
});
|
|
98130
98353
|
async function getNextLine() {
|
|
98131
98354
|
if (lineQueue.length > 0) {
|
|
98132
98355
|
return lineQueue.shift() ?? null;
|
|
98133
98356
|
}
|
|
98134
|
-
return new Promise((
|
|
98135
|
-
lineResolver =
|
|
98357
|
+
return new Promise((resolve29) => {
|
|
98358
|
+
lineResolver = resolve29;
|
|
98136
98359
|
});
|
|
98137
98360
|
}
|
|
98138
98361
|
async function requestPermission(toolCallId, toolName, toolInput) {
|
|
@@ -98623,7 +98846,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98623
98846
|
uuid: `retry-bidir-${randomUUID13()}`
|
|
98624
98847
|
};
|
|
98625
98848
|
console.log(JSON.stringify(retryMsg));
|
|
98626
|
-
await new Promise((
|
|
98849
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
98627
98850
|
continue;
|
|
98628
98851
|
}
|
|
98629
98852
|
throw preStreamError;
|
|
@@ -98925,10 +99148,10 @@ async function detectAndEnableKittyProtocol() {
|
|
|
98925
99148
|
detectionComplete = true;
|
|
98926
99149
|
return;
|
|
98927
99150
|
}
|
|
98928
|
-
return new Promise((
|
|
99151
|
+
return new Promise((resolve29) => {
|
|
98929
99152
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
98930
99153
|
detectionComplete = true;
|
|
98931
|
-
|
|
99154
|
+
resolve29();
|
|
98932
99155
|
return;
|
|
98933
99156
|
}
|
|
98934
99157
|
const originalRawMode = process.stdin.isRaw;
|
|
@@ -98961,7 +99184,7 @@ async function detectAndEnableKittyProtocol() {
|
|
|
98961
99184
|
console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
|
|
98962
99185
|
}
|
|
98963
99186
|
detectionComplete = true;
|
|
98964
|
-
|
|
99187
|
+
resolve29();
|
|
98965
99188
|
};
|
|
98966
99189
|
const handleData = (data) => {
|
|
98967
99190
|
if (timeoutId === undefined) {
|
|
@@ -99174,13 +99397,13 @@ var init_reconcileExistingAgentState = __esm(() => {
|
|
|
99174
99397
|
// src/agent/sessionHistory.ts
|
|
99175
99398
|
import * as fs17 from "node:fs";
|
|
99176
99399
|
import * as os6 from "node:os";
|
|
99177
|
-
import * as
|
|
99400
|
+
import * as path26 from "node:path";
|
|
99178
99401
|
function getHistoryDir() {
|
|
99179
99402
|
const homeDir = os6.homedir();
|
|
99180
|
-
return
|
|
99403
|
+
return path26.join(homeDir, ".letta");
|
|
99181
99404
|
}
|
|
99182
99405
|
function getHistoryFilePath() {
|
|
99183
|
-
return
|
|
99406
|
+
return path26.join(getHistoryDir(), "sessions.jsonl");
|
|
99184
99407
|
}
|
|
99185
99408
|
function recordSessionEnd(agentId, sessionId, stats, sessionInfo, cost, metadata) {
|
|
99186
99409
|
const entry = {
|
|
@@ -117444,8 +117667,8 @@ function getHeader(command) {
|
|
|
117444
117667
|
return `Run memory ${command}?`;
|
|
117445
117668
|
}
|
|
117446
117669
|
}
|
|
117447
|
-
function displayPath(
|
|
117448
|
-
return
|
|
117670
|
+
function displayPath(path27) {
|
|
117671
|
+
return path27.replace(/\.md$/, "");
|
|
117449
117672
|
}
|
|
117450
117673
|
function truncate2(text, max) {
|
|
117451
117674
|
if (text.length <= max)
|
|
@@ -117549,7 +117772,7 @@ var init_InlineMemoryApproval = __esm(async () => {
|
|
|
117549
117772
|
const {
|
|
117550
117773
|
command,
|
|
117551
117774
|
reason,
|
|
117552
|
-
path:
|
|
117775
|
+
path: path27,
|
|
117553
117776
|
oldPath,
|
|
117554
117777
|
newPath,
|
|
117555
117778
|
oldString,
|
|
@@ -117596,9 +117819,9 @@ var init_InlineMemoryApproval = __esm(async () => {
|
|
|
117596
117819
|
}, undefined, false, undefined, this)
|
|
117597
117820
|
]
|
|
117598
117821
|
}, undefined, true, undefined, this)
|
|
117599
|
-
}, undefined, false, undefined, this) :
|
|
117822
|
+
}, undefined, false, undefined, this) : path27 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text2, {
|
|
117600
117823
|
bold: true,
|
|
117601
|
-
children: displayPath(
|
|
117824
|
+
children: displayPath(path27)
|
|
117602
117825
|
}, undefined, false, undefined, this),
|
|
117603
117826
|
command === "str_replace" && oldString != null && newString != null && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
|
|
117604
117827
|
flexDirection: "column",
|
|
@@ -121237,7 +121460,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
121237
121460
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
121238
121461
|
import { existsSync as existsSync34, readFileSync as readFileSync20, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
|
|
121239
121462
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
121240
|
-
import { basename as basename9, extname as extname8, isAbsolute as
|
|
121463
|
+
import { basename as basename9, extname as extname8, isAbsolute as isAbsolute20, join as join42, resolve as resolve29 } from "node:path";
|
|
121241
121464
|
function countLines2(text) {
|
|
121242
121465
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
121243
121466
|
}
|
|
@@ -121284,8 +121507,8 @@ function translatePasteForImages(paste) {
|
|
|
121284
121507
|
}
|
|
121285
121508
|
} catch {}
|
|
121286
121509
|
}
|
|
121287
|
-
if (!
|
|
121288
|
-
filePath =
|
|
121510
|
+
if (!isAbsolute20(filePath))
|
|
121511
|
+
filePath = resolve29(process.cwd(), filePath);
|
|
121289
121512
|
const ext3 = extname8(filePath || "").toLowerCase();
|
|
121290
121513
|
if (IMAGE_EXTS.has(ext3) && existsSync34(filePath) && statSync10(filePath).isFile()) {
|
|
121291
121514
|
const buf = readFileSync20(filePath);
|
|
@@ -122220,14 +122443,14 @@ function installKeybindingForCurrentTerminal() {
|
|
|
122220
122443
|
error: "Not running in a VS Code-like terminal"
|
|
122221
122444
|
};
|
|
122222
122445
|
}
|
|
122223
|
-
const
|
|
122224
|
-
if (!
|
|
122446
|
+
const path27 = getKeybindingsPath(terminal);
|
|
122447
|
+
if (!path27) {
|
|
122225
122448
|
return {
|
|
122226
122449
|
success: false,
|
|
122227
122450
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
122228
122451
|
};
|
|
122229
122452
|
}
|
|
122230
|
-
return installKeybinding(
|
|
122453
|
+
return installKeybinding(path27);
|
|
122231
122454
|
}
|
|
122232
122455
|
function removeKeybindingForCurrentTerminal() {
|
|
122233
122456
|
const terminal = detectTerminalType();
|
|
@@ -122237,14 +122460,14 @@ function removeKeybindingForCurrentTerminal() {
|
|
|
122237
122460
|
error: "Not running in a VS Code-like terminal"
|
|
122238
122461
|
};
|
|
122239
122462
|
}
|
|
122240
|
-
const
|
|
122241
|
-
if (!
|
|
122463
|
+
const path27 = getKeybindingsPath(terminal);
|
|
122464
|
+
if (!path27) {
|
|
122242
122465
|
return {
|
|
122243
122466
|
success: false,
|
|
122244
122467
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
122245
122468
|
};
|
|
122246
122469
|
}
|
|
122247
|
-
return removeKeybinding(
|
|
122470
|
+
return removeKeybinding(path27);
|
|
122248
122471
|
}
|
|
122249
122472
|
function isWezTerm() {
|
|
122250
122473
|
return process.env.TERM_PROGRAM === "WezTerm";
|
|
@@ -122900,7 +123123,7 @@ __export(exports_custom, {
|
|
|
122900
123123
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
122901
123124
|
});
|
|
122902
123125
|
import { existsSync as existsSync36 } from "node:fs";
|
|
122903
|
-
import { readdir as
|
|
123126
|
+
import { readdir as readdir10, readFile as readFile14 } from "node:fs/promises";
|
|
122904
123127
|
import { basename as basename10, dirname as dirname17, join as join44 } from "node:path";
|
|
122905
123128
|
async function getCustomCommands() {
|
|
122906
123129
|
if (cachedCommands !== null) {
|
|
@@ -122942,7 +123165,7 @@ async function discoverFromDirectory(dirPath, source2) {
|
|
|
122942
123165
|
}
|
|
122943
123166
|
async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
122944
123167
|
try {
|
|
122945
|
-
const entries = await
|
|
123168
|
+
const entries = await readdir10(currentPath, { withFileTypes: true });
|
|
122946
123169
|
for (const entry of entries) {
|
|
122947
123170
|
const fullPath = join44(currentPath, entry.name);
|
|
122948
123171
|
if (entry.isDirectory()) {
|
|
@@ -122959,7 +123182,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
|
122959
123182
|
} catch (_error) {}
|
|
122960
123183
|
}
|
|
122961
123184
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
122962
|
-
const content = await
|
|
123185
|
+
const content = await readFile14(filePath, "utf-8");
|
|
122963
123186
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
122964
123187
|
const id = basename10(filePath, ".md");
|
|
122965
123188
|
const relativePath = dirname17(filePath).slice(rootPath.length);
|
|
@@ -123311,11 +123534,11 @@ var init_HelpDialog = __esm(async () => {
|
|
|
123311
123534
|
|
|
123312
123535
|
// src/hooks/writer.ts
|
|
123313
123536
|
import { homedir as homedir34 } from "node:os";
|
|
123314
|
-
import { resolve as
|
|
123537
|
+
import { resolve as resolve30 } from "node:path";
|
|
123315
123538
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
123316
123539
|
const home = process.env.HOME || homedir34();
|
|
123317
|
-
const globalSettingsPath =
|
|
123318
|
-
const projectSettingsPath =
|
|
123540
|
+
const globalSettingsPath = resolve30(home, ".letta", "settings.json");
|
|
123541
|
+
const projectSettingsPath = resolve30(workingDirectory, ".letta", "settings.json");
|
|
123319
123542
|
return globalSettingsPath === projectSettingsPath;
|
|
123320
123543
|
}
|
|
123321
123544
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -125953,7 +126176,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
125953
126176
|
|
|
125954
126177
|
// src/cli/helpers/fileSearch.ts
|
|
125955
126178
|
import { readdirSync as readdirSync12, statSync as statSync11 } from "node:fs";
|
|
125956
|
-
import { join as join45, relative as relative16, resolve as
|
|
126179
|
+
import { join as join45, relative as relative16, resolve as resolve31 } from "node:path";
|
|
125957
126180
|
function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
|
|
125958
126181
|
if (results.length >= maxResults || depth >= maxDepth) {
|
|
125959
126182
|
return results;
|
|
@@ -125996,7 +126219,7 @@ async function searchFiles(query, deep = false) {
|
|
|
125996
126219
|
const dirPart = query.slice(0, lastSlashIndex);
|
|
125997
126220
|
const pattern = query.slice(lastSlashIndex + 1);
|
|
125998
126221
|
try {
|
|
125999
|
-
const resolvedDir =
|
|
126222
|
+
const resolvedDir = resolve31(getIndexRoot(), dirPart);
|
|
126000
126223
|
try {
|
|
126001
126224
|
statSync11(resolvedDir);
|
|
126002
126225
|
searchDir = resolvedDir;
|
|
@@ -128321,9 +128544,9 @@ function buildInstallPrBody(workflowPath) {
|
|
|
128321
128544
|
].join(`
|
|
128322
128545
|
`);
|
|
128323
128546
|
}
|
|
128324
|
-
function checkRemoteFileExists(repo,
|
|
128547
|
+
function checkRemoteFileExists(repo, path27) {
|
|
128325
128548
|
try {
|
|
128326
|
-
runCommand("gh", ["api", `repos/${repo}/contents/${
|
|
128549
|
+
runCommand("gh", ["api", `repos/${repo}/contents/${path27}`]);
|
|
128327
128550
|
return true;
|
|
128328
128551
|
} catch {
|
|
128329
128552
|
return false;
|
|
@@ -135684,7 +135907,7 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
135684
135907
|
});
|
|
135685
135908
|
|
|
135686
135909
|
// src/utils/aws-credentials.ts
|
|
135687
|
-
import { readFile as
|
|
135910
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
135688
135911
|
import { homedir as homedir36 } from "node:os";
|
|
135689
135912
|
import { join as join48 } from "node:path";
|
|
135690
135913
|
async function parseAwsCredentials() {
|
|
@@ -135692,11 +135915,11 @@ async function parseAwsCredentials() {
|
|
|
135692
135915
|
const configPath = join48(homedir36(), ".aws", "config");
|
|
135693
135916
|
const profiles = new Map;
|
|
135694
135917
|
try {
|
|
135695
|
-
const content = await
|
|
135918
|
+
const content = await readFile15(credentialsPath, "utf-8");
|
|
135696
135919
|
parseIniFile(content, profiles, false);
|
|
135697
135920
|
} catch {}
|
|
135698
135921
|
try {
|
|
135699
|
-
const content = await
|
|
135922
|
+
const content = await readFile15(configPath, "utf-8");
|
|
135700
135923
|
parseIniFile(content, profiles, true);
|
|
135701
135924
|
} catch {}
|
|
135702
135925
|
return Array.from(profiles.values());
|
|
@@ -138303,8 +138526,8 @@ function MemoryDiffRenderer({
|
|
|
138303
138526
|
}, undefined, false, undefined, this);
|
|
138304
138527
|
}
|
|
138305
138528
|
const command = args.command;
|
|
138306
|
-
const
|
|
138307
|
-
const blockName =
|
|
138529
|
+
const path27 = args.path || args.old_path || "unknown";
|
|
138530
|
+
const blockName = path27.split("/").pop() || path27;
|
|
138308
138531
|
switch (command) {
|
|
138309
138532
|
case "str_replace": {
|
|
138310
138533
|
const oldStr = args.old_string || args.old_str || "";
|
|
@@ -141176,7 +141399,7 @@ async function executeStatusLineCommand(command, payload, options) {
|
|
|
141176
141399
|
};
|
|
141177
141400
|
}
|
|
141178
141401
|
function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
|
|
141179
|
-
return new Promise((
|
|
141402
|
+
return new Promise((resolve32, reject) => {
|
|
141180
141403
|
const [executable, ...args] = launcher;
|
|
141181
141404
|
if (!executable) {
|
|
141182
141405
|
reject(new Error("Empty launcher"));
|
|
@@ -141189,7 +141412,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
|
|
|
141189
141412
|
const safeResolve = (result) => {
|
|
141190
141413
|
if (!resolved) {
|
|
141191
141414
|
resolved = true;
|
|
141192
|
-
|
|
141415
|
+
resolve32(result);
|
|
141193
141416
|
}
|
|
141194
141417
|
};
|
|
141195
141418
|
let child;
|
|
@@ -142361,28 +142584,28 @@ var exports_export = {};
|
|
|
142361
142584
|
__export(exports_export, {
|
|
142362
142585
|
packageSkills: () => packageSkills
|
|
142363
142586
|
});
|
|
142364
|
-
import { readdir as
|
|
142365
|
-
import { relative as relative17, resolve as
|
|
142587
|
+
import { readdir as readdir11, readFile as readFile16 } from "node:fs/promises";
|
|
142588
|
+
import { relative as relative17, resolve as resolve32 } from "node:path";
|
|
142366
142589
|
async function packageSkills(agentId, skillsDir) {
|
|
142367
142590
|
const skills = [];
|
|
142368
142591
|
const skillNames = new Set;
|
|
142369
142592
|
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
142370
142593
|
agentId && getAgentSkillsDir(agentId),
|
|
142371
|
-
|
|
142372
|
-
|
|
142594
|
+
resolve32(process.cwd(), ".skills"),
|
|
142595
|
+
resolve32(process.env.HOME || "~", ".letta", "skills")
|
|
142373
142596
|
].filter((dir) => Boolean(dir));
|
|
142374
142597
|
for (const baseDir of dirsToCheck) {
|
|
142375
142598
|
try {
|
|
142376
|
-
const entries = await
|
|
142599
|
+
const entries = await readdir11(baseDir, { withFileTypes: true });
|
|
142377
142600
|
for (const entry of entries) {
|
|
142378
142601
|
if (!entry.isDirectory())
|
|
142379
142602
|
continue;
|
|
142380
142603
|
if (skillNames.has(entry.name))
|
|
142381
142604
|
continue;
|
|
142382
|
-
const skillDir =
|
|
142383
|
-
const skillMdPath =
|
|
142605
|
+
const skillDir = resolve32(baseDir, entry.name);
|
|
142606
|
+
const skillMdPath = resolve32(skillDir, "SKILL.md");
|
|
142384
142607
|
try {
|
|
142385
|
-
await
|
|
142608
|
+
await readFile16(skillMdPath, "utf-8");
|
|
142386
142609
|
} catch {
|
|
142387
142610
|
console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
|
|
142388
142611
|
continue;
|
|
@@ -142408,13 +142631,13 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
142408
142631
|
async function readSkillFiles(skillDir) {
|
|
142409
142632
|
const files = {};
|
|
142410
142633
|
async function walk(dir) {
|
|
142411
|
-
const entries = await
|
|
142634
|
+
const entries = await readdir11(dir, { withFileTypes: true });
|
|
142412
142635
|
for (const entry of entries) {
|
|
142413
|
-
const fullPath =
|
|
142636
|
+
const fullPath = resolve32(dir, entry.name);
|
|
142414
142637
|
if (entry.isDirectory()) {
|
|
142415
142638
|
await walk(fullPath);
|
|
142416
142639
|
} else {
|
|
142417
|
-
const content = await
|
|
142640
|
+
const content = await readFile16(fullPath, "utf-8");
|
|
142418
142641
|
const relativePath = relative17(skillDir, fullPath).replace(/\\/g, "/");
|
|
142419
142642
|
files[relativePath] = content;
|
|
142420
142643
|
}
|
|
@@ -142434,8 +142657,8 @@ async function findSkillSourceUrl(skillName) {
|
|
|
142434
142657
|
}
|
|
142435
142658
|
return null;
|
|
142436
142659
|
}
|
|
142437
|
-
async function fetchGitHubDirs(
|
|
142438
|
-
const [owner, repo, branch, ...pathParts] =
|
|
142660
|
+
async function fetchGitHubDirs(path27) {
|
|
142661
|
+
const [owner, repo, branch, ...pathParts] = path27.split("/");
|
|
142439
142662
|
if (!owner || !repo || !branch)
|
|
142440
142663
|
return new Set;
|
|
142441
142664
|
try {
|
|
@@ -144592,12 +144815,12 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
|
|
|
144592
144815
|
let watcher = null;
|
|
144593
144816
|
(async () => {
|
|
144594
144817
|
try {
|
|
144595
|
-
const { watch } = await import("node:fs");
|
|
144818
|
+
const { watch: watch2 } = await import("node:fs");
|
|
144596
144819
|
const { existsSync: existsSync43 } = await import("node:fs");
|
|
144597
144820
|
const memRoot = getMemoryFilesystemRoot(agentId);
|
|
144598
144821
|
if (!existsSync43(memRoot))
|
|
144599
144822
|
return;
|
|
144600
|
-
watcher =
|
|
144823
|
+
watcher = watch2(memRoot, { recursive: true }, () => {});
|
|
144601
144824
|
memfsWatcherRef.current = watcher;
|
|
144602
144825
|
debugLog("memfs", `Watching memory directory: ${memRoot}`);
|
|
144603
144826
|
watcher.on("error", (err) => {
|
|
@@ -144924,7 +145147,7 @@ ${newState.originalPrompt}`,
|
|
|
144924
145147
|
cancelled = true;
|
|
144925
145148
|
break;
|
|
144926
145149
|
}
|
|
144927
|
-
await new Promise((
|
|
145150
|
+
await new Promise((resolve33) => setTimeout(resolve33, 100));
|
|
144928
145151
|
}
|
|
144929
145152
|
buffersRef.current.byId.delete(statusId);
|
|
144930
145153
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
@@ -144988,7 +145211,7 @@ ${newState.originalPrompt}`,
|
|
|
144988
145211
|
cancelled = true;
|
|
144989
145212
|
break;
|
|
144990
145213
|
}
|
|
144991
|
-
await new Promise((
|
|
145214
|
+
await new Promise((resolve33) => setTimeout(resolve33, 100));
|
|
144992
145215
|
}
|
|
144993
145216
|
if (retryStatusId) {
|
|
144994
145217
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -145746,7 +145969,7 @@ ${feedback}
|
|
|
145746
145969
|
});
|
|
145747
145970
|
buffersRef.current.order.push(statusId);
|
|
145748
145971
|
refreshDerived();
|
|
145749
|
-
await new Promise((
|
|
145972
|
+
await new Promise((resolve33) => setTimeout(resolve33, delayMs));
|
|
145750
145973
|
buffersRef.current.byId.delete(statusId);
|
|
145751
145974
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
145752
145975
|
refreshDerived();
|
|
@@ -145806,7 +146029,7 @@ ${feedback}
|
|
|
145806
146029
|
cancelled = true;
|
|
145807
146030
|
break;
|
|
145808
146031
|
}
|
|
145809
|
-
await new Promise((
|
|
146032
|
+
await new Promise((resolve33) => setTimeout(resolve33, 100));
|
|
145810
146033
|
}
|
|
145811
146034
|
if (retryStatusId) {
|
|
145812
146035
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -152514,14 +152737,14 @@ function installKeybindingForCurrentTerminal2() {
|
|
|
152514
152737
|
error: "Not running in a VS Code-like terminal"
|
|
152515
152738
|
};
|
|
152516
152739
|
}
|
|
152517
|
-
const
|
|
152518
|
-
if (!
|
|
152740
|
+
const path27 = getKeybindingsPath2(terminal);
|
|
152741
|
+
if (!path27) {
|
|
152519
152742
|
return {
|
|
152520
152743
|
success: false,
|
|
152521
152744
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
152522
152745
|
};
|
|
152523
152746
|
}
|
|
152524
|
-
return installKeybinding2(
|
|
152747
|
+
return installKeybinding2(path27);
|
|
152525
152748
|
}
|
|
152526
152749
|
function removeKeybindingForCurrentTerminal2() {
|
|
152527
152750
|
const terminal = detectTerminalType2();
|
|
@@ -152531,14 +152754,14 @@ function removeKeybindingForCurrentTerminal2() {
|
|
|
152531
152754
|
error: "Not running in a VS Code-like terminal"
|
|
152532
152755
|
};
|
|
152533
152756
|
}
|
|
152534
|
-
const
|
|
152535
|
-
if (!
|
|
152757
|
+
const path27 = getKeybindingsPath2(terminal);
|
|
152758
|
+
if (!path27) {
|
|
152536
152759
|
return {
|
|
152537
152760
|
success: false,
|
|
152538
152761
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
152539
152762
|
};
|
|
152540
152763
|
}
|
|
152541
|
-
return removeKeybinding2(
|
|
152764
|
+
return removeKeybinding2(path27);
|
|
152542
152765
|
}
|
|
152543
152766
|
function isWezTerm2() {
|
|
152544
152767
|
return process.env.TERM_PROGRAM === "WezTerm";
|
|
@@ -153174,11 +153397,11 @@ __export(exports_import2, {
|
|
|
153174
153397
|
extractSkillsFromAf: () => extractSkillsFromAf2
|
|
153175
153398
|
});
|
|
153176
153399
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
153177
|
-
import { chmod as chmod2, mkdir as mkdir11, readFile as
|
|
153178
|
-
import { dirname as dirname20, resolve as
|
|
153400
|
+
import { chmod as chmod2, mkdir as mkdir11, readFile as readFile17, writeFile as writeFile12 } from "node:fs/promises";
|
|
153401
|
+
import { dirname as dirname20, resolve as resolve33 } from "node:path";
|
|
153179
153402
|
async function importAgentFromFile2(options) {
|
|
153180
153403
|
const client = await getClient();
|
|
153181
|
-
const resolvedPath =
|
|
153404
|
+
const resolvedPath = resolve33(options.filePath);
|
|
153182
153405
|
const file = createReadStream2(resolvedPath);
|
|
153183
153406
|
const importResponse = await client.agents.importFile({
|
|
153184
153407
|
file,
|
|
@@ -153207,13 +153430,13 @@ async function importAgentFromFile2(options) {
|
|
|
153207
153430
|
}
|
|
153208
153431
|
async function extractSkillsFromAf2(afPath, destDir) {
|
|
153209
153432
|
const extracted = [];
|
|
153210
|
-
const content = await
|
|
153433
|
+
const content = await readFile17(afPath, "utf-8");
|
|
153211
153434
|
const afData = JSON.parse(content);
|
|
153212
153435
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
153213
153436
|
return [];
|
|
153214
153437
|
}
|
|
153215
153438
|
for (const skill2 of afData.skills) {
|
|
153216
|
-
const skillDir =
|
|
153439
|
+
const skillDir = resolve33(destDir, skill2.name);
|
|
153217
153440
|
await mkdir11(skillDir, { recursive: true });
|
|
153218
153441
|
if (skill2.files) {
|
|
153219
153442
|
await writeSkillFiles2(skillDir, skill2.files);
|
|
@@ -153233,7 +153456,7 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
153233
153456
|
}
|
|
153234
153457
|
}
|
|
153235
153458
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
153236
|
-
const fullPath =
|
|
153459
|
+
const fullPath = resolve33(skillDir, filePath);
|
|
153237
153460
|
await mkdir11(dirname20(fullPath), { recursive: true });
|
|
153238
153461
|
await writeFile12(fullPath, content, "utf-8");
|
|
153239
153462
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
@@ -153252,13 +153475,13 @@ async function fetchSkillFromUrl2(skillDir, sourceUrl) {
|
|
|
153252
153475
|
const owner = parts[0];
|
|
153253
153476
|
const repo = parts[1];
|
|
153254
153477
|
const branch = parts[2];
|
|
153255
|
-
const
|
|
153478
|
+
const path27 = parts.slice(3).join("/");
|
|
153256
153479
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
153257
|
-
const entries = await fetchGitHubContents2(owner, repo, branch,
|
|
153480
|
+
const entries = await fetchGitHubContents2(owner, repo, branch, path27);
|
|
153258
153481
|
if (!Array.isArray(entries)) {
|
|
153259
153482
|
throw new Error(`Expected directory at ${sourceUrl}, got file`);
|
|
153260
153483
|
}
|
|
153261
|
-
await downloadGitHubDirectory2(entries, skillDir, owner, repo, branch,
|
|
153484
|
+
await downloadGitHubDirectory2(entries, skillDir, owner, repo, branch, path27);
|
|
153262
153485
|
}
|
|
153263
153486
|
async function downloadGitHubDirectory2(entries, destDir, owner, repo, branch, basePath) {
|
|
153264
153487
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
@@ -158271,23 +158494,21 @@ async function runListenSubcommand(argv) {
|
|
|
158271
158494
|
process.exit(code);
|
|
158272
158495
|
};
|
|
158273
158496
|
await settingsManager.loadLocalProjectSettings();
|
|
158274
|
-
|
|
158275
|
-
|
|
158276
|
-
if (
|
|
158277
|
-
|
|
158278
|
-
|
|
158279
|
-
|
|
158280
|
-
|
|
158281
|
-
|
|
158282
|
-
|
|
158283
|
-
return 1;
|
|
158284
|
-
}
|
|
158285
|
-
await ensureChannelRuntimeInstalled2(channelName);
|
|
158497
|
+
const channelNames = values.channels ? values.channels.split(",").map((s) => s.trim()).filter(Boolean) : process.env.LETTA_RESTORE_ENABLED_CHANNELS === "1" ? (await Promise.resolve().then(() => (init_service(), exports_service))).listEnabledChannelIds() : [];
|
|
158498
|
+
if (channelNames.length > 0) {
|
|
158499
|
+
if (values.channels && values["install-channel-runtimes"]) {
|
|
158500
|
+
const { ensureChannelRuntimeInstalled: ensureChannelRuntimeInstalled2 } = await Promise.resolve().then(() => (init_runtimeDeps(), exports_runtimeDeps));
|
|
158501
|
+
const { isSupportedChannelId: isSupportedChannelId2 } = await Promise.resolve().then(() => (init_pluginRegistry(), exports_pluginRegistry));
|
|
158502
|
+
for (const channelName of channelNames) {
|
|
158503
|
+
if (!isSupportedChannelId2(channelName)) {
|
|
158504
|
+
console.error(`Unknown channel "${channelName}" passed to --channels.`);
|
|
158505
|
+
return 1;
|
|
158286
158506
|
}
|
|
158507
|
+
await ensureChannelRuntimeInstalled2(channelName);
|
|
158287
158508
|
}
|
|
158288
|
-
const { initializeChannels: initializeChannels2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
158289
|
-
await initializeChannels2(channelNames);
|
|
158290
158509
|
}
|
|
158510
|
+
const { initializeChannels: initializeChannels2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
158511
|
+
await initializeChannels2(channelNames);
|
|
158291
158512
|
}
|
|
158292
158513
|
let connectionName;
|
|
158293
158514
|
if (values["env-name"]) {
|
|
@@ -158301,11 +158522,11 @@ async function runListenSubcommand(argv) {
|
|
|
158301
158522
|
connectionName = hostname3();
|
|
158302
158523
|
settingsManager.setListenerEnvName(connectionName);
|
|
158303
158524
|
} else {
|
|
158304
|
-
connectionName = await new Promise((
|
|
158525
|
+
connectionName = await new Promise((resolve25) => {
|
|
158305
158526
|
const { unmount } = render_default(/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(PromptEnvName, {
|
|
158306
158527
|
onSubmit: (name) => {
|
|
158307
158528
|
unmount();
|
|
158308
|
-
|
|
158529
|
+
resolve25(name);
|
|
158309
158530
|
}
|
|
158310
158531
|
}, undefined, false, undefined, this));
|
|
158311
158532
|
});
|
|
@@ -158508,7 +158729,7 @@ async function runListenSubcommand(argv) {
|
|
|
158508
158729
|
// src/cli/subcommands/memfs.ts
|
|
158509
158730
|
init_memoryGit();
|
|
158510
158731
|
import { cpSync, existsSync as existsSync26, mkdirSync as mkdirSync19, rmSync as rmSync3, statSync as statSync8 } from "node:fs";
|
|
158511
|
-
import { readdir as
|
|
158732
|
+
import { readdir as readdir7 } from "node:fs/promises";
|
|
158512
158733
|
import { homedir as homedir24 } from "node:os";
|
|
158513
158734
|
import { join as join31 } from "node:path";
|
|
158514
158735
|
import { parseArgs as parseArgs8 } from "node:util";
|
|
@@ -158575,22 +158796,22 @@ async function listBackups(agentId) {
|
|
|
158575
158796
|
if (!existsSync26(agentRoot)) {
|
|
158576
158797
|
return [];
|
|
158577
158798
|
}
|
|
158578
|
-
const entries = await
|
|
158799
|
+
const entries = await readdir7(agentRoot, { withFileTypes: true });
|
|
158579
158800
|
const backups = [];
|
|
158580
158801
|
for (const entry of entries) {
|
|
158581
158802
|
if (!entry.isDirectory())
|
|
158582
158803
|
continue;
|
|
158583
158804
|
if (!entry.name.startsWith("memory-backup-"))
|
|
158584
158805
|
continue;
|
|
158585
|
-
const
|
|
158806
|
+
const path24 = join31(agentRoot, entry.name);
|
|
158586
158807
|
let createdAt = null;
|
|
158587
158808
|
try {
|
|
158588
|
-
const
|
|
158589
|
-
createdAt =
|
|
158809
|
+
const stat7 = statSync8(path24);
|
|
158810
|
+
createdAt = stat7.mtime.toISOString();
|
|
158590
158811
|
} catch {
|
|
158591
158812
|
createdAt = null;
|
|
158592
158813
|
}
|
|
158593
|
-
backups.push({ name: entry.name, path:
|
|
158814
|
+
backups.push({ name: entry.name, path: path24, createdAt });
|
|
158594
158815
|
}
|
|
158595
158816
|
backups.sort((a, b) => a.name.localeCompare(b.name));
|
|
158596
158817
|
return backups;
|
|
@@ -158694,8 +158915,8 @@ async function runMemfsSubcommand(argv) {
|
|
|
158694
158915
|
console.error(`Backup not found: ${backupPath}`);
|
|
158695
158916
|
return 1;
|
|
158696
158917
|
}
|
|
158697
|
-
const
|
|
158698
|
-
if (!
|
|
158918
|
+
const stat7 = statSync8(backupPath);
|
|
158919
|
+
if (!stat7.isDirectory()) {
|
|
158699
158920
|
console.error(`Backup path is not a directory: ${backupPath}`);
|
|
158700
158921
|
return 1;
|
|
158701
158922
|
}
|
|
@@ -158717,9 +158938,9 @@ async function runMemfsSubcommand(argv) {
|
|
|
158717
158938
|
return 1;
|
|
158718
158939
|
}
|
|
158719
158940
|
if (existsSync26(out)) {
|
|
158720
|
-
const
|
|
158721
|
-
if (
|
|
158722
|
-
const contents = await
|
|
158941
|
+
const stat7 = statSync8(out);
|
|
158942
|
+
if (stat7.isDirectory()) {
|
|
158943
|
+
const contents = await readdir7(out);
|
|
158723
158944
|
if (contents.length > 0) {
|
|
158724
158945
|
console.error(`Export directory not empty: ${out}`);
|
|
158725
158946
|
return 1;
|
|
@@ -158748,7 +158969,7 @@ async function runMemfsSubcommand(argv) {
|
|
|
158748
158969
|
init_client2();
|
|
158749
158970
|
init_settings_manager();
|
|
158750
158971
|
import { writeFile as writeFile9 } from "node:fs/promises";
|
|
158751
|
-
import { resolve as
|
|
158972
|
+
import { resolve as resolve25 } from "node:path";
|
|
158752
158973
|
import { parseArgs as parseArgs9 } from "node:util";
|
|
158753
158974
|
function printUsage6() {
|
|
158754
158975
|
console.log(`
|
|
@@ -159053,7 +159274,7 @@ async function runMessagesSubcommand(argv) {
|
|
|
159053
159274
|
|
|
159054
159275
|
`).trim();
|
|
159055
159276
|
if (outputPathRaw && typeof outputPathRaw === "string") {
|
|
159056
|
-
const outputPath =
|
|
159277
|
+
const outputPath = resolve25(process.cwd(), outputPathRaw);
|
|
159057
159278
|
await writeFile9(outputPath, `${transcript}
|
|
159058
159279
|
`, "utf-8");
|
|
159059
159280
|
console.log(JSON.stringify({
|
|
@@ -159115,13 +159336,13 @@ init_memoryScope();
|
|
|
159115
159336
|
init_readOnlyShell();
|
|
159116
159337
|
init_shell_command_normalization();
|
|
159117
159338
|
import { homedir as homedir25 } from "node:os";
|
|
159118
|
-
import { isAbsolute as
|
|
159339
|
+
import { isAbsolute as isAbsolute18, join as join32, relative as relative13 } from "node:path";
|
|
159119
159340
|
var MODE_KEY2 = Symbol.for("@letta/permissionMode");
|
|
159120
159341
|
var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
|
|
159121
159342
|
var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
|
|
159122
159343
|
function everyResolvedTargetIsWithinRoots2(candidatePaths, roots, workingDirectory) {
|
|
159123
|
-
return candidatePaths.length > 0 && candidatePaths.every((
|
|
159124
|
-
const resolvedPath = resolveScopedTargetPath(
|
|
159344
|
+
return candidatePaths.length > 0 && candidatePaths.every((path24) => {
|
|
159345
|
+
const resolvedPath = resolveScopedTargetPath(path24, workingDirectory);
|
|
159125
159346
|
return resolvedPath ? isPathWithinRoots(resolvedPath, roots) : false;
|
|
159126
159347
|
});
|
|
159127
159348
|
}
|
|
@@ -159155,11 +159376,11 @@ function setGlobalModeBeforePlan2(value) {
|
|
|
159155
159376
|
function resolvePlanTargetPath2(targetPath, workingDirectory) {
|
|
159156
159377
|
return resolveScopedTargetPath(targetPath, workingDirectory);
|
|
159157
159378
|
}
|
|
159158
|
-
function isPathInPlansDir2(
|
|
159159
|
-
if (!
|
|
159379
|
+
function isPathInPlansDir2(path24, plansDir) {
|
|
159380
|
+
if (!path24.endsWith(".md"))
|
|
159160
159381
|
return false;
|
|
159161
|
-
const rel = relative13(plansDir,
|
|
159162
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
159382
|
+
const rel = relative13(plansDir, path24);
|
|
159383
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute18(rel);
|
|
159163
159384
|
}
|
|
159164
159385
|
function extractApplyPatchPaths2(input) {
|
|
159165
159386
|
const paths = [];
|
|
@@ -159260,8 +159481,8 @@ class PermissionModeManager2 {
|
|
|
159260
159481
|
getMode() {
|
|
159261
159482
|
return this.currentMode;
|
|
159262
159483
|
}
|
|
159263
|
-
setPlanFilePath(
|
|
159264
|
-
setGlobalPlanFilePath2(
|
|
159484
|
+
setPlanFilePath(path24) {
|
|
159485
|
+
setGlobalPlanFilePath2(path24);
|
|
159265
159486
|
}
|
|
159266
159487
|
getPlanFilePath() {
|
|
159267
159488
|
return getGlobalPlanFilePath2();
|
|
@@ -159356,8 +159577,8 @@ class PermissionModeManager2 {
|
|
|
159356
159577
|
} else if (typeof targetPath === "string") {
|
|
159357
159578
|
candidatePaths = [targetPath];
|
|
159358
159579
|
}
|
|
159359
|
-
if (candidatePaths.length > 0 && candidatePaths.every((
|
|
159360
|
-
const resolvedPath = resolvePlanTargetPath2(
|
|
159580
|
+
if (candidatePaths.length > 0 && candidatePaths.every((path24) => {
|
|
159581
|
+
const resolvedPath = resolvePlanTargetPath2(path24, workingDirectory);
|
|
159361
159582
|
return resolvedPath ? isPathInPlansDir2(resolvedPath, plansDir) : false;
|
|
159362
159583
|
})) {
|
|
159363
159584
|
return "allow";
|
|
@@ -159516,7 +159737,7 @@ init_fs();
|
|
|
159516
159737
|
init_secrets();
|
|
159517
159738
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
159518
159739
|
import { homedir as homedir26 } from "node:os";
|
|
159519
|
-
import { join as join33, resolve as
|
|
159740
|
+
import { join as join33, resolve as resolve26 } from "node:path";
|
|
159520
159741
|
var DEFAULT_SETTINGS3 = {
|
|
159521
159742
|
lastAgent: null,
|
|
159522
159743
|
tokenStreaming: false,
|
|
@@ -159970,7 +160191,7 @@ class SettingsManager2 {
|
|
|
159970
160191
|
return join33(workingDirectory, ".letta", "settings.json");
|
|
159971
160192
|
}
|
|
159972
160193
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
159973
|
-
return
|
|
160194
|
+
return resolve26(this.getProjectSettingsPath(workingDirectory)) === resolve26(this.getSettingsPath());
|
|
159974
160195
|
}
|
|
159975
160196
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
159976
160197
|
return join33(workingDirectory, ".letta", "settings.local.json");
|
|
@@ -160915,6 +161136,7 @@ var STREAMING_SHELL_TOOLS2 = new Set([
|
|
|
160915
161136
|
"run_shell_command",
|
|
160916
161137
|
"RunShellCommand"
|
|
160917
161138
|
]);
|
|
161139
|
+
var FILE_MUTATING_TOOLS2 = new Set(["Edit", "Write", "MultiEdit", "replace"]);
|
|
160918
161140
|
var ANTHROPIC_DEFAULT_TOOLS2 = [
|
|
160919
161141
|
"AskUserQuestion",
|
|
160920
161142
|
"Bash",
|
|
@@ -160985,8 +161207,8 @@ function acquireSwitchLock2() {
|
|
|
160985
161207
|
const lock = getSwitchLock2();
|
|
160986
161208
|
lock.refCount++;
|
|
160987
161209
|
if (lock.refCount === 1) {
|
|
160988
|
-
lock.promise = new Promise((
|
|
160989
|
-
lock.resolve =
|
|
161210
|
+
lock.promise = new Promise((resolve27) => {
|
|
161211
|
+
lock.resolve = resolve27;
|
|
160990
161212
|
});
|
|
160991
161213
|
}
|
|
160992
161214
|
}
|
|
@@ -161475,7 +161697,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
161475
161697
|
printHelp();
|
|
161476
161698
|
const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
|
|
161477
161699
|
if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
|
|
161478
|
-
await new Promise((
|
|
161700
|
+
await new Promise((resolve34) => setTimeout(resolve34, helpDelayMs));
|
|
161479
161701
|
}
|
|
161480
161702
|
process.exit(0);
|
|
161481
161703
|
}
|
|
@@ -161697,9 +161919,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
161697
161919
|
process.exit(1);
|
|
161698
161920
|
}
|
|
161699
161921
|
} else {
|
|
161700
|
-
const { resolve:
|
|
161922
|
+
const { resolve: resolve34 } = await import("path");
|
|
161701
161923
|
const { existsSync: existsSync45 } = await import("fs");
|
|
161702
|
-
const resolvedPath =
|
|
161924
|
+
const resolvedPath = resolve34(fromAfFile);
|
|
161703
161925
|
if (!existsSync45(resolvedPath)) {
|
|
161704
161926
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
161705
161927
|
process.exit(1);
|
|
@@ -162579,4 +162801,4 @@ Error during initialization: ${message}`);
|
|
|
162579
162801
|
}
|
|
162580
162802
|
main();
|
|
162581
162803
|
|
|
162582
|
-
//# debugId=
|
|
162804
|
+
//# debugId=50A69FA1631D153664756E2164756E21
|