@letta-ai/letta-code 0.23.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +457 -248
- 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.1",
|
|
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: {
|
|
@@ -43143,6 +43143,7 @@ __export(exports_service, {
|
|
|
43143
43143
|
removeChannelAccountLive: () => removeChannelAccountLive,
|
|
43144
43144
|
refreshChannelAccountDisplayNameLive: () => refreshChannelAccountDisplayNameLive,
|
|
43145
43145
|
listPendingPairingSnapshots: () => listPendingPairingSnapshots,
|
|
43146
|
+
listEnabledChannelIds: () => listEnabledChannelIds,
|
|
43146
43147
|
listChannelTargetSnapshots: () => listChannelTargetSnapshots,
|
|
43147
43148
|
listChannelSummaries: () => listChannelSummaries,
|
|
43148
43149
|
listChannelRouteSnapshots: () => listChannelRouteSnapshots,
|
|
@@ -43400,6 +43401,9 @@ function listChannelSummaries() {
|
|
|
43400
43401
|
};
|
|
43401
43402
|
});
|
|
43402
43403
|
}
|
|
43404
|
+
function listEnabledChannelIds() {
|
|
43405
|
+
return getSupportedChannelIds().filter((channelId) => listChannelAccounts(channelId).some((account) => account.enabled));
|
|
43406
|
+
}
|
|
43403
43407
|
function getChannelConfigSnapshot(channelId, accountId) {
|
|
43404
43408
|
assertSupportedChannelId(channelId);
|
|
43405
43409
|
const account = getSelectedChannelAccount(channelId, accountId);
|
|
@@ -55627,7 +55631,8 @@ async function executeSingleDecision(decision, onChunk, options) {
|
|
|
55627
55631
|
toolCallId: decision.approval.toolCallId,
|
|
55628
55632
|
toolContextId: options?.toolContextId,
|
|
55629
55633
|
parentScope: options?.parentScope,
|
|
55630
|
-
onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined
|
|
55634
|
+
onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined,
|
|
55635
|
+
onFileWrite: options?.onFileWrite
|
|
55631
55636
|
});
|
|
55632
55637
|
if (onChunk) {
|
|
55633
55638
|
onChunk({
|
|
@@ -77520,6 +77525,8 @@ var init_analyzer = __esm(() => {
|
|
|
77520
77525
|
});
|
|
77521
77526
|
|
|
77522
77527
|
// src/tools/manager.ts
|
|
77528
|
+
import * as nodeFs from "node:fs/promises";
|
|
77529
|
+
import * as nodePath from "node:path";
|
|
77523
77530
|
function maybeAppendChannelTools(toolNames) {
|
|
77524
77531
|
if (getActiveChannelIds().length > 0 && !toolNames.includes("MessageChannel")) {
|
|
77525
77532
|
return [...toolNames, "MessageChannel"];
|
|
@@ -77590,8 +77597,8 @@ function acquireSwitchLock() {
|
|
|
77590
77597
|
const lock = getSwitchLock();
|
|
77591
77598
|
lock.refCount++;
|
|
77592
77599
|
if (lock.refCount === 1) {
|
|
77593
|
-
lock.promise = new Promise((
|
|
77594
|
-
lock.resolve =
|
|
77600
|
+
lock.promise = new Promise((resolve25) => {
|
|
77601
|
+
lock.resolve = resolve25;
|
|
77595
77602
|
});
|
|
77596
77603
|
}
|
|
77597
77604
|
}
|
|
@@ -78120,6 +78127,16 @@ async function executeTool(name, args, options) {
|
|
|
78120
78127
|
const result = await withExecutionWorkingDirectory(workingDirectory, () => tool.fn(enhancedArgs));
|
|
78121
78128
|
const duration = Date.now() - startTime;
|
|
78122
78129
|
refreshFileIndex();
|
|
78130
|
+
if (options?.onFileWrite && FILE_MUTATING_TOOLS.has(internalName)) {
|
|
78131
|
+
const filePath = enhancedArgs.file_path;
|
|
78132
|
+
if (filePath) {
|
|
78133
|
+
try {
|
|
78134
|
+
const resolvedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.resolve(process.env.USER_CWD || process.cwd(), filePath);
|
|
78135
|
+
const content = await nodeFs.readFile(resolvedPath, "utf-8");
|
|
78136
|
+
options.onFileWrite(resolvedPath, content);
|
|
78137
|
+
} catch {}
|
|
78138
|
+
}
|
|
78139
|
+
}
|
|
78123
78140
|
const recordResult = isRecord(result) ? result : undefined;
|
|
78124
78141
|
const stdoutValue = recordResult?.stdout;
|
|
78125
78142
|
const stderrValue = recordResult?.stderr;
|
|
@@ -78253,7 +78270,7 @@ function clearToolsWithLock() {
|
|
|
78253
78270
|
releaseSwitchLock();
|
|
78254
78271
|
}
|
|
78255
78272
|
}
|
|
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;
|
|
78273
|
+
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
78274
|
var init_manager3 = __esm(async () => {
|
|
78258
78275
|
init_model2();
|
|
78259
78276
|
init_subagents();
|
|
@@ -78283,6 +78300,7 @@ var init_manager3 = __esm(async () => {
|
|
|
78283
78300
|
"run_shell_command",
|
|
78284
78301
|
"RunShellCommand"
|
|
78285
78302
|
]);
|
|
78303
|
+
FILE_MUTATING_TOOLS = new Set(["Edit", "Write", "MultiEdit", "replace"]);
|
|
78286
78304
|
TOOL_NAME_MAPPINGS = {
|
|
78287
78305
|
glob_gemini: "glob",
|
|
78288
78306
|
write_todos: "write_todos",
|
|
@@ -81705,7 +81723,7 @@ import {
|
|
|
81705
81723
|
appendFile,
|
|
81706
81724
|
mkdir as mkdir7,
|
|
81707
81725
|
readdir as readdir5,
|
|
81708
|
-
readFile as
|
|
81726
|
+
readFile as readFile10,
|
|
81709
81727
|
writeFile as writeFile7
|
|
81710
81728
|
} from "node:fs/promises";
|
|
81711
81729
|
import { homedir as homedir21, tmpdir as tmpdir3 } from "node:os";
|
|
@@ -81752,7 +81770,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
81752
81770
|
continue;
|
|
81753
81771
|
}
|
|
81754
81772
|
try {
|
|
81755
|
-
const content = await
|
|
81773
|
+
const content = await readFile10(entryPath, "utf-8");
|
|
81756
81774
|
const { frontmatter } = parseFrontmatter(content);
|
|
81757
81775
|
const description = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
|
|
81758
81776
|
files.push({
|
|
@@ -82012,7 +82030,7 @@ async function ensurePaths(paths) {
|
|
|
82012
82030
|
}
|
|
82013
82031
|
async function readState(paths) {
|
|
82014
82032
|
try {
|
|
82015
|
-
const raw = await
|
|
82033
|
+
const raw = await readFile10(paths.statePath, "utf-8");
|
|
82016
82034
|
const parsed = parseJsonLine(raw);
|
|
82017
82035
|
if (!parsed) {
|
|
82018
82036
|
return defaultState();
|
|
@@ -82032,7 +82050,7 @@ async function writeState(paths, state) {
|
|
|
82032
82050
|
}
|
|
82033
82051
|
async function readTranscriptLines(paths) {
|
|
82034
82052
|
try {
|
|
82035
|
-
const raw = await
|
|
82053
|
+
const raw = await readFile10(paths.transcriptPath, "utf-8");
|
|
82036
82054
|
return raw.split(`
|
|
82037
82055
|
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
82038
82056
|
} catch {
|
|
@@ -82391,11 +82409,11 @@ async function discoverFallbackRunIdWithTimeout(client, ctx) {
|
|
|
82391
82409
|
return withTimeout(discoverFallbackRunIdForResume(client, ctx), FALLBACK_RUN_DISCOVERY_TIMEOUT_MS, `Fallback run discovery timed out after ${FALLBACK_RUN_DISCOVERY_TIMEOUT_MS}ms`);
|
|
82392
82410
|
}
|
|
82393
82411
|
function withTimeout(promise, timeoutMs, timeoutMessage) {
|
|
82394
|
-
return new Promise((
|
|
82412
|
+
return new Promise((resolve25, reject) => {
|
|
82395
82413
|
const timer = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
|
|
82396
82414
|
promise.then((value) => {
|
|
82397
82415
|
clearTimeout(timer);
|
|
82398
|
-
|
|
82416
|
+
resolve25(value);
|
|
82399
82417
|
}, (error) => {
|
|
82400
82418
|
clearTimeout(timer);
|
|
82401
82419
|
reject(error);
|
|
@@ -83535,7 +83553,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
83535
83553
|
if (isInterrupted()) {
|
|
83536
83554
|
return Promise.reject(new Error("Cancelled by user"));
|
|
83537
83555
|
}
|
|
83538
|
-
return new Promise((
|
|
83556
|
+
return new Promise((resolve25, reject) => {
|
|
83539
83557
|
let settled = false;
|
|
83540
83558
|
const cleanupAbortListener = () => {
|
|
83541
83559
|
abortSignal?.removeEventListener("abort", handleAbort);
|
|
@@ -83546,7 +83564,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
83546
83564
|
}
|
|
83547
83565
|
settled = true;
|
|
83548
83566
|
cleanupAbortListener();
|
|
83549
|
-
|
|
83567
|
+
resolve25(response);
|
|
83550
83568
|
};
|
|
83551
83569
|
const wrappedReject = (error) => {
|
|
83552
83570
|
if (settled) {
|
|
@@ -87209,7 +87227,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
87209
87227
|
conversationId
|
|
87210
87228
|
});
|
|
87211
87229
|
}
|
|
87212
|
-
await new Promise((
|
|
87230
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
87213
87231
|
if (abortSignal?.aborted) {
|
|
87214
87232
|
throw new Error("Cancelled by user");
|
|
87215
87233
|
}
|
|
@@ -87264,7 +87282,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
87264
87282
|
agentId: runtime.agentId ?? undefined,
|
|
87265
87283
|
conversationId
|
|
87266
87284
|
});
|
|
87267
|
-
await new Promise((
|
|
87285
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
87268
87286
|
if (abortSignal?.aborted) {
|
|
87269
87287
|
throw new Error("Cancelled by user");
|
|
87270
87288
|
}
|
|
@@ -87339,7 +87357,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
87339
87357
|
retryAfterMs
|
|
87340
87358
|
});
|
|
87341
87359
|
transientRetries = attempt;
|
|
87342
|
-
await new Promise((
|
|
87360
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
87343
87361
|
if (abortSignal?.aborted) {
|
|
87344
87362
|
throw new Error("Cancelled by user");
|
|
87345
87363
|
}
|
|
@@ -87384,7 +87402,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
87384
87402
|
category: "conversation_busy",
|
|
87385
87403
|
attempt: conversationBusyRetries
|
|
87386
87404
|
});
|
|
87387
|
-
await new Promise((
|
|
87405
|
+
await new Promise((resolve25) => setTimeout(resolve25, retryDelayMs));
|
|
87388
87406
|
if (abortSignal?.aborted) {
|
|
87389
87407
|
throw new Error("Cancelled by user");
|
|
87390
87408
|
}
|
|
@@ -87422,6 +87440,7 @@ var init_send = __esm(async () => {
|
|
|
87422
87440
|
});
|
|
87423
87441
|
|
|
87424
87442
|
// src/websocket/listener/turn-approval.ts
|
|
87443
|
+
import WebSocket2 from "ws";
|
|
87425
87444
|
async function handleApprovalStop(params) {
|
|
87426
87445
|
const {
|
|
87427
87446
|
approvals,
|
|
@@ -87647,11 +87666,24 @@ async function handleApprovalStop(params) {
|
|
|
87647
87666
|
if (shouldInterrupt()) {
|
|
87648
87667
|
return interruptTermination();
|
|
87649
87668
|
}
|
|
87669
|
+
const onFileWrite = (filePath, content) => {
|
|
87670
|
+
if (socket.readyState === WebSocket2.OPEN) {
|
|
87671
|
+
socket.send(JSON.stringify({
|
|
87672
|
+
type: "file_ops",
|
|
87673
|
+
path: filePath,
|
|
87674
|
+
cg_entries: [],
|
|
87675
|
+
ops: [],
|
|
87676
|
+
source: "agent",
|
|
87677
|
+
document_content: content
|
|
87678
|
+
}));
|
|
87679
|
+
}
|
|
87680
|
+
};
|
|
87650
87681
|
const executionResults = await executeApprovalBatch(decisions, undefined, {
|
|
87651
87682
|
toolContextId: turnToolContextId ?? undefined,
|
|
87652
87683
|
abortSignal: abortController.signal,
|
|
87653
87684
|
workingDirectory: turnWorkingDirectory,
|
|
87654
|
-
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined
|
|
87685
|
+
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined,
|
|
87686
|
+
onFileWrite
|
|
87655
87687
|
});
|
|
87656
87688
|
const persistedExecutionResults = normalizeExecutionResultsForInterruptParity(runtime, executionResults, lastExecutingToolCallIds);
|
|
87657
87689
|
validateApprovalResultIds(decisions.map((decision) => ({
|
|
@@ -88276,7 +88308,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
88276
88308
|
agentId,
|
|
88277
88309
|
conversationId
|
|
88278
88310
|
});
|
|
88279
|
-
await new Promise((
|
|
88311
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
88280
88312
|
if (turnAbortSignal.aborted) {
|
|
88281
88313
|
throw new Error("Cancelled by user");
|
|
88282
88314
|
}
|
|
@@ -88321,7 +88353,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
88321
88353
|
agentId,
|
|
88322
88354
|
conversationId
|
|
88323
88355
|
});
|
|
88324
|
-
await new Promise((
|
|
88356
|
+
await new Promise((resolve25) => setTimeout(resolve25, delayMs));
|
|
88325
88357
|
if (turnAbortSignal.aborted) {
|
|
88326
88358
|
throw new Error("Cancelled by user");
|
|
88327
88359
|
}
|
|
@@ -88811,7 +88843,7 @@ var init_commands = __esm(async () => {
|
|
|
88811
88843
|
});
|
|
88812
88844
|
|
|
88813
88845
|
// src/websocket/listener/protocol-outbound.ts
|
|
88814
|
-
import
|
|
88846
|
+
import WebSocket3 from "ws";
|
|
88815
88847
|
function getCachedDeviceGitContext(cwd2) {
|
|
88816
88848
|
const now = Date.now();
|
|
88817
88849
|
const cached = gitContextCache.get(cwd2);
|
|
@@ -88928,7 +88960,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
88928
88960
|
return {
|
|
88929
88961
|
current_connection_id: listener.connectionId,
|
|
88930
88962
|
connection_name: listener.connectionName,
|
|
88931
|
-
is_online: listener.socket?.readyState ===
|
|
88963
|
+
is_online: listener.socket?.readyState === WebSocket3.OPEN,
|
|
88932
88964
|
is_processing: !!conversationRuntime?.isProcessing,
|
|
88933
88965
|
current_permission_mode: conversationPermissionModeState.mode,
|
|
88934
88966
|
current_working_directory: resolvedCwd,
|
|
@@ -88996,7 +89028,7 @@ function setLoopStatus(runtime, status, scope) {
|
|
|
88996
89028
|
emitLoopStatusIfOpen(runtime, scope);
|
|
88997
89029
|
}
|
|
88998
89030
|
function emitProtocolV2Message(socket, runtime, message, scope) {
|
|
88999
|
-
if (socket.readyState !==
|
|
89031
|
+
if (socket.readyState !== WebSocket3.OPEN) {
|
|
89000
89032
|
return;
|
|
89001
89033
|
}
|
|
89002
89034
|
const listener = getListenerRuntime(runtime);
|
|
@@ -89048,13 +89080,13 @@ function emitLoopStatusUpdate(socket, runtime, scope) {
|
|
|
89048
89080
|
}
|
|
89049
89081
|
function emitLoopStatusIfOpen(runtime, scope) {
|
|
89050
89082
|
const listener = getListenerRuntime(runtime);
|
|
89051
|
-
if (listener?.socket?.readyState ===
|
|
89083
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89052
89084
|
emitLoopStatusUpdate(listener.socket, runtime, scope);
|
|
89053
89085
|
}
|
|
89054
89086
|
}
|
|
89055
89087
|
function emitDeviceStatusIfOpen(runtime, scope) {
|
|
89056
89088
|
const listener = getListenerRuntime(runtime);
|
|
89057
|
-
if (listener?.socket?.readyState ===
|
|
89089
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89058
89090
|
emitDeviceStatusUpdate(listener.socket, runtime, scope);
|
|
89059
89091
|
}
|
|
89060
89092
|
}
|
|
@@ -89113,7 +89145,7 @@ function emitDequeuedUserMessage(socket, runtime, incoming, batch) {
|
|
|
89113
89145
|
}
|
|
89114
89146
|
function emitQueueUpdateIfOpen(runtime, scope) {
|
|
89115
89147
|
const listener = getListenerRuntime(runtime);
|
|
89116
|
-
if (listener?.socket?.readyState ===
|
|
89148
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89117
89149
|
emitQueueUpdate(listener.socket, runtime, scope);
|
|
89118
89150
|
}
|
|
89119
89151
|
}
|
|
@@ -89169,7 +89201,7 @@ function emitSubagentStateUpdate(socket, runtime, scope) {
|
|
|
89169
89201
|
}
|
|
89170
89202
|
function emitSubagentStateIfOpen(runtime, scope) {
|
|
89171
89203
|
const listener = getListenerRuntime(runtime);
|
|
89172
|
-
if (listener?.socket?.readyState ===
|
|
89204
|
+
if (listener?.socket?.readyState === WebSocket3.OPEN) {
|
|
89173
89205
|
emitSubagentStateUpdate(listener.socket, runtime, scope);
|
|
89174
89206
|
}
|
|
89175
89207
|
}
|
|
@@ -89787,7 +89819,7 @@ var init_toolset_labels = __esm(() => {
|
|
|
89787
89819
|
|
|
89788
89820
|
// src/websocket/terminalHandler.ts
|
|
89789
89821
|
import * as os4 from "node:os";
|
|
89790
|
-
import
|
|
89822
|
+
import WebSocket4 from "ws";
|
|
89791
89823
|
function getDefaultShell() {
|
|
89792
89824
|
if (os4.platform() === "win32") {
|
|
89793
89825
|
return process.env.COMSPEC || "cmd.exe";
|
|
@@ -89795,7 +89827,7 @@ function getDefaultShell() {
|
|
|
89795
89827
|
return process.env.SHELL || "/bin/zsh";
|
|
89796
89828
|
}
|
|
89797
89829
|
function sendTerminalMessage(socket, message) {
|
|
89798
|
-
if (socket.readyState ===
|
|
89830
|
+
if (socket.readyState === WebSocket4.OPEN) {
|
|
89799
89831
|
socket.send(JSON.stringify(message));
|
|
89800
89832
|
}
|
|
89801
89833
|
}
|
|
@@ -90163,6 +90195,12 @@ function isEditFileCommand(value) {
|
|
|
90163
90195
|
const c = value;
|
|
90164
90196
|
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
90197
|
}
|
|
90198
|
+
function isFileOpsCommand(value) {
|
|
90199
|
+
if (!value || typeof value !== "object")
|
|
90200
|
+
return false;
|
|
90201
|
+
const c = value;
|
|
90202
|
+
return c.type === "file_ops" && typeof c.path === "string" && Array.isArray(c.cg_entries) && Array.isArray(c.ops) && typeof c.source === "string";
|
|
90203
|
+
}
|
|
90166
90204
|
function isListMemoryCommand(value) {
|
|
90167
90205
|
if (!value || typeof value !== "object")
|
|
90168
90206
|
return false;
|
|
@@ -90453,7 +90491,7 @@ function parseServerMessage(data) {
|
|
|
90453
90491
|
try {
|
|
90454
90492
|
const raw = typeof data === "string" ? data : data.toString();
|
|
90455
90493
|
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)) {
|
|
90494
|
+
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
90495
|
return parsed;
|
|
90458
90496
|
}
|
|
90459
90497
|
const invalidInput = getInvalidInputReason(parsed);
|
|
@@ -90474,6 +90512,135 @@ var init_protocol_inbound = __esm(async () => {
|
|
|
90474
90512
|
await init_approval();
|
|
90475
90513
|
});
|
|
90476
90514
|
|
|
90515
|
+
// src/websocket/listener/worktree-watcher.ts
|
|
90516
|
+
import { readdir as readdir6, stat as stat5, watch } from "node:fs/promises";
|
|
90517
|
+
import path22 from "node:path";
|
|
90518
|
+
function startWorktreeWatcher(params) {
|
|
90519
|
+
const { runtime, agentId, conversationId } = params;
|
|
90520
|
+
const cwd2 = getConversationWorkingDirectory(runtime, agentId, conversationId);
|
|
90521
|
+
const worktreesDir = path22.join(cwd2, WORKTREES_DIR);
|
|
90522
|
+
const abort = new AbortController;
|
|
90523
|
+
const state = { abort, watchedDir: worktreesDir };
|
|
90524
|
+
runWatchLoop({
|
|
90525
|
+
worktreesDir,
|
|
90526
|
+
abort,
|
|
90527
|
+
runtime,
|
|
90528
|
+
agentId,
|
|
90529
|
+
conversationId
|
|
90530
|
+
}).catch((err) => {
|
|
90531
|
+
if (err.name === "AbortError")
|
|
90532
|
+
return;
|
|
90533
|
+
console.error("[WorktreeWatcher] watch loop error:", err);
|
|
90534
|
+
});
|
|
90535
|
+
return state;
|
|
90536
|
+
}
|
|
90537
|
+
function stopWorktreeWatcher(state) {
|
|
90538
|
+
state.abort.abort();
|
|
90539
|
+
}
|
|
90540
|
+
function stopAllWorktreeWatchers(runtime) {
|
|
90541
|
+
for (const watcher of runtime.worktreeWatcherByConversation.values()) {
|
|
90542
|
+
stopWorktreeWatcher(watcher);
|
|
90543
|
+
}
|
|
90544
|
+
runtime.worktreeWatcherByConversation.clear();
|
|
90545
|
+
}
|
|
90546
|
+
function restartWorktreeWatcher(params) {
|
|
90547
|
+
const { runtime, agentId, conversationId } = params;
|
|
90548
|
+
const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
|
|
90549
|
+
const existing = runtime.worktreeWatcherByConversation.get(scopeKey);
|
|
90550
|
+
if (existing) {
|
|
90551
|
+
stopWorktreeWatcher(existing);
|
|
90552
|
+
runtime.worktreeWatcherByConversation.delete(scopeKey);
|
|
90553
|
+
}
|
|
90554
|
+
const state = startWorktreeWatcher(params);
|
|
90555
|
+
if (state) {
|
|
90556
|
+
runtime.worktreeWatcherByConversation.set(scopeKey, state);
|
|
90557
|
+
}
|
|
90558
|
+
}
|
|
90559
|
+
async function runWatchLoop(params) {
|
|
90560
|
+
const { worktreesDir, abort, runtime, agentId, conversationId } = params;
|
|
90561
|
+
const dirExists = await directoryExists(worktreesDir);
|
|
90562
|
+
if (!dirExists) {
|
|
90563
|
+
const lettaDir = path22.dirname(worktreesDir);
|
|
90564
|
+
const lettaDirExists = await directoryExists(lettaDir);
|
|
90565
|
+
if (!lettaDirExists) {
|
|
90566
|
+
return;
|
|
90567
|
+
}
|
|
90568
|
+
await waitForDirectoryCreation(lettaDir, "worktrees", abort.signal);
|
|
90569
|
+
}
|
|
90570
|
+
const existingEntries = new Set(await safeReaddir(worktreesDir));
|
|
90571
|
+
let debounceTimer = null;
|
|
90572
|
+
const watcher = watch(worktreesDir, { signal: abort.signal });
|
|
90573
|
+
for await (const event of watcher) {
|
|
90574
|
+
if (event.eventType !== "rename" || !event.filename)
|
|
90575
|
+
continue;
|
|
90576
|
+
if (existingEntries.has(event.filename))
|
|
90577
|
+
continue;
|
|
90578
|
+
if (debounceTimer)
|
|
90579
|
+
clearTimeout(debounceTimer);
|
|
90580
|
+
const filename = event.filename;
|
|
90581
|
+
debounceTimer = setTimeout(() => {
|
|
90582
|
+
handleNewWorktree({
|
|
90583
|
+
worktreesDir,
|
|
90584
|
+
filename,
|
|
90585
|
+
runtime,
|
|
90586
|
+
agentId,
|
|
90587
|
+
conversationId
|
|
90588
|
+
});
|
|
90589
|
+
}, DEBOUNCE_MS);
|
|
90590
|
+
}
|
|
90591
|
+
}
|
|
90592
|
+
async function handleNewWorktree(params) {
|
|
90593
|
+
const { worktreesDir, filename, runtime, agentId, conversationId } = params;
|
|
90594
|
+
const newWorktreePath = path22.join(worktreesDir, filename);
|
|
90595
|
+
if (!await directoryExists(newWorktreePath))
|
|
90596
|
+
return;
|
|
90597
|
+
const currentCwd = getConversationWorkingDirectory(runtime, agentId, conversationId);
|
|
90598
|
+
if (currentCwd === newWorktreePath)
|
|
90599
|
+
return;
|
|
90600
|
+
console.log(`[WorktreeWatcher] New worktree detected: ${newWorktreePath} — switching CWD`);
|
|
90601
|
+
setConversationWorkingDirectory(runtime, agentId, conversationId, newWorktreePath);
|
|
90602
|
+
const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
|
|
90603
|
+
const reminderState = runtime.reminderStateByConversation.get(scopeKey);
|
|
90604
|
+
if (reminderState) {
|
|
90605
|
+
reminderState.hasSentSessionContext = false;
|
|
90606
|
+
reminderState.pendingSessionContextReason = "cwd_changed";
|
|
90607
|
+
}
|
|
90608
|
+
if (runtime.socket) {
|
|
90609
|
+
emitDeviceStatusUpdate(runtime.socket, runtime, {
|
|
90610
|
+
agent_id: agentId,
|
|
90611
|
+
conversation_id: conversationId
|
|
90612
|
+
});
|
|
90613
|
+
}
|
|
90614
|
+
}
|
|
90615
|
+
async function waitForDirectoryCreation(parentDir, targetName, signal) {
|
|
90616
|
+
const watcher = watch(parentDir, { signal });
|
|
90617
|
+
for await (const event of watcher) {
|
|
90618
|
+
if (event.eventType === "rename" && event.filename === targetName && await directoryExists(path22.join(parentDir, targetName))) {
|
|
90619
|
+
return;
|
|
90620
|
+
}
|
|
90621
|
+
}
|
|
90622
|
+
}
|
|
90623
|
+
async function directoryExists(dir) {
|
|
90624
|
+
try {
|
|
90625
|
+
const stats = await stat5(dir);
|
|
90626
|
+
return stats.isDirectory();
|
|
90627
|
+
} catch {
|
|
90628
|
+
return false;
|
|
90629
|
+
}
|
|
90630
|
+
}
|
|
90631
|
+
async function safeReaddir(dir) {
|
|
90632
|
+
try {
|
|
90633
|
+
return await readdir6(dir);
|
|
90634
|
+
} catch {
|
|
90635
|
+
return [];
|
|
90636
|
+
}
|
|
90637
|
+
}
|
|
90638
|
+
var WORKTREES_DIR = ".letta/worktrees", DEBOUNCE_MS = 500;
|
|
90639
|
+
var init_worktree_watcher = __esm(async () => {
|
|
90640
|
+
init_cwd();
|
|
90641
|
+
await init_protocol_outbound();
|
|
90642
|
+
});
|
|
90643
|
+
|
|
90477
90644
|
// src/agent/memoryScanner.ts
|
|
90478
90645
|
var exports_memoryScanner = {};
|
|
90479
90646
|
__export(exports_memoryScanner, {
|
|
@@ -90555,10 +90722,10 @@ var init_memoryScanner = () => {};
|
|
|
90555
90722
|
|
|
90556
90723
|
// src/websocket/listener/client.ts
|
|
90557
90724
|
import { execFile as execFile13 } from "node:child_process";
|
|
90558
|
-
import { realpath as realpath3, stat as
|
|
90559
|
-
import
|
|
90725
|
+
import { realpath as realpath3, stat as stat6 } from "node:fs/promises";
|
|
90726
|
+
import path23 from "node:path";
|
|
90560
90727
|
import { promisify as promisify13 } from "node:util";
|
|
90561
|
-
import
|
|
90728
|
+
import WebSocket5 from "ws";
|
|
90562
90729
|
async function loadChannelsService() {
|
|
90563
90730
|
if (channelsServiceLoaderOverride) {
|
|
90564
90731
|
return channelsServiceLoaderOverride();
|
|
@@ -90573,7 +90740,7 @@ function trackListenerError(errorType, error, context3) {
|
|
|
90573
90740
|
});
|
|
90574
90741
|
}
|
|
90575
90742
|
function safeSocketSend(socket, payload, errorType, context3) {
|
|
90576
|
-
if (socket.readyState !==
|
|
90743
|
+
if (socket.readyState !== WebSocket5.OPEN) {
|
|
90577
90744
|
return false;
|
|
90578
90745
|
}
|
|
90579
90746
|
try {
|
|
@@ -91760,8 +91927,8 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
91760
91927
|
const linkPath = join31(globalSkillsDir, linkName);
|
|
91761
91928
|
mkdirSync19(globalSkillsDir, { recursive: true });
|
|
91762
91929
|
if (existsSync26(linkPath)) {
|
|
91763
|
-
const
|
|
91764
|
-
if (
|
|
91930
|
+
const stat7 = lstatSync2(linkPath);
|
|
91931
|
+
if (stat7.isSymbolicLink()) {
|
|
91765
91932
|
if (process.platform === "win32") {
|
|
91766
91933
|
rmdirSync(linkPath);
|
|
91767
91934
|
} else {
|
|
@@ -91810,8 +91977,8 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
91810
91977
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
91811
91978
|
return true;
|
|
91812
91979
|
}
|
|
91813
|
-
const
|
|
91814
|
-
if (!
|
|
91980
|
+
const stat7 = lstatSync2(linkPath);
|
|
91981
|
+
if (!stat7.isSymbolicLink()) {
|
|
91815
91982
|
safeSocketSend(socket, {
|
|
91816
91983
|
type: "skill_disable_response",
|
|
91817
91984
|
request_id: parsed.request_id,
|
|
@@ -92263,9 +92430,9 @@ async function handleCwdChange(msg, socket, runtime) {
|
|
|
92263
92430
|
if (!requestedPath) {
|
|
92264
92431
|
throw new Error("Working directory cannot be empty");
|
|
92265
92432
|
}
|
|
92266
|
-
const resolvedPath =
|
|
92433
|
+
const resolvedPath = path23.isAbsolute(requestedPath) ? requestedPath : path23.resolve(currentWorkingDirectory, requestedPath);
|
|
92267
92434
|
const normalizedPath = await realpath3(resolvedPath);
|
|
92268
|
-
const stats = await
|
|
92435
|
+
const stats = await stat6(normalizedPath);
|
|
92269
92436
|
if (!stats.isDirectory()) {
|
|
92270
92437
|
throw new Error(`Not a directory: ${normalizedPath}`);
|
|
92271
92438
|
}
|
|
@@ -92280,6 +92447,11 @@ async function handleCwdChange(msg, socket, runtime) {
|
|
|
92280
92447
|
agent_id: agentId,
|
|
92281
92448
|
conversation_id: conversationId
|
|
92282
92449
|
});
|
|
92450
|
+
restartWorktreeWatcher({
|
|
92451
|
+
runtime: runtime.listener,
|
|
92452
|
+
agentId,
|
|
92453
|
+
conversationId
|
|
92454
|
+
});
|
|
92283
92455
|
} catch (error) {
|
|
92284
92456
|
emitLoopErrorNotice(socket, runtime, {
|
|
92285
92457
|
message: error instanceof Error ? error.message : "Working directory change failed",
|
|
@@ -92309,6 +92481,7 @@ function createRuntime() {
|
|
|
92309
92481
|
reminderState: createSharedReminderState(),
|
|
92310
92482
|
bootWorkingDirectory,
|
|
92311
92483
|
workingDirectoryByConversation: loadPersistedCwdMap(),
|
|
92484
|
+
worktreeWatcherByConversation: new Map,
|
|
92312
92485
|
permissionModeByConversation: loadPersistedPermissionModeMap(),
|
|
92313
92486
|
reminderStateByConversation: new Map,
|
|
92314
92487
|
contextTrackerByConversation: new Map,
|
|
@@ -92340,6 +92513,7 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
92340
92513
|
runtime.contextTrackerByConversation.clear();
|
|
92341
92514
|
runtime.systemPromptRecompileByConversation.clear();
|
|
92342
92515
|
runtime.queuedSystemPromptRecompileByConversation.clear();
|
|
92516
|
+
stopAllWorktreeWatchers(runtime);
|
|
92343
92517
|
if (!runtime.socket) {
|
|
92344
92518
|
return;
|
|
92345
92519
|
}
|
|
@@ -92348,7 +92522,7 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
92348
92522
|
if (suppressCallbacks) {
|
|
92349
92523
|
socket.removeAllListeners();
|
|
92350
92524
|
}
|
|
92351
|
-
if (socket.readyState ===
|
|
92525
|
+
if (socket.readyState === WebSocket5.OPEN || socket.readyState === WebSocket5.CONNECTING) {
|
|
92352
92526
|
socket.close();
|
|
92353
92527
|
}
|
|
92354
92528
|
}
|
|
@@ -92383,8 +92557,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92383
92557
|
const delay = Math.min(INITIAL_RETRY_DELAY_MS * 2 ** (attempt - 1), MAX_RETRY_DELAY_MS);
|
|
92384
92558
|
const maxAttempts = Math.ceil(Math.log2(MAX_RETRY_DURATION_MS / INITIAL_RETRY_DELAY_MS));
|
|
92385
92559
|
opts.onRetrying?.(attempt, maxAttempts, delay, opts.connectionId);
|
|
92386
|
-
await new Promise((
|
|
92387
|
-
runtime.reconnectTimeout = setTimeout(
|
|
92560
|
+
await new Promise((resolve25) => {
|
|
92561
|
+
runtime.reconnectTimeout = setTimeout(resolve25, delay);
|
|
92388
92562
|
});
|
|
92389
92563
|
runtime.reconnectTimeout = null;
|
|
92390
92564
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
@@ -92403,7 +92577,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92403
92577
|
const url = new URL(opts.wsUrl);
|
|
92404
92578
|
url.searchParams.set("deviceId", opts.deviceId);
|
|
92405
92579
|
url.searchParams.set("connectionName", opts.connectionName);
|
|
92406
|
-
const socket = new
|
|
92580
|
+
const socket = new WebSocket5(url.toString(), {
|
|
92407
92581
|
headers: {
|
|
92408
92582
|
Authorization: `Bearer ${apiKey}`
|
|
92409
92583
|
}
|
|
@@ -92457,7 +92631,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92457
92631
|
});
|
|
92458
92632
|
runtime._unsubscribeSubagentStreamEvents?.();
|
|
92459
92633
|
runtime._unsubscribeSubagentStreamEvents = subscribeToStreamEvents((subagentId, event) => {
|
|
92460
|
-
if (socket.readyState !==
|
|
92634
|
+
if (socket.readyState !== WebSocket5.OPEN)
|
|
92461
92635
|
return;
|
|
92462
92636
|
const subagent = getSubagents().find((entry) => entry.id === subagentId);
|
|
92463
92637
|
if (subagent?.silent === true) {
|
|
@@ -92483,7 +92657,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92483
92657
|
scheduleQueuePump(targetRuntime, socket, opts, processQueuedTurn);
|
|
92484
92658
|
});
|
|
92485
92659
|
runtime.heartbeatInterval = setInterval(() => {
|
|
92486
|
-
if (socket.readyState ===
|
|
92660
|
+
if (socket.readyState === WebSocket5.OPEN) {
|
|
92487
92661
|
safeSocketSend(socket, { type: "ping" }, "listener_ping_send_failed", "listener_heartbeat");
|
|
92488
92662
|
}
|
|
92489
92663
|
}, 30000);
|
|
@@ -92644,14 +92818,14 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92644
92818
|
try {
|
|
92645
92819
|
if (parsed.cwd) {
|
|
92646
92820
|
const currentRoot = getIndexRoot();
|
|
92647
|
-
if (!parsed.cwd.startsWith(currentRoot +
|
|
92821
|
+
if (!parsed.cwd.startsWith(currentRoot + path23.sep) && parsed.cwd !== currentRoot) {
|
|
92648
92822
|
setIndexRoot(parsed.cwd);
|
|
92649
92823
|
}
|
|
92650
92824
|
}
|
|
92651
92825
|
await ensureFileIndex2();
|
|
92652
92826
|
let searchDir = ".";
|
|
92653
92827
|
if (parsed.cwd) {
|
|
92654
|
-
const rel =
|
|
92828
|
+
const rel = path23.relative(getIndexRoot(), parsed.cwd);
|
|
92655
92829
|
if (rel && !rel.startsWith("..") && rel !== "") {
|
|
92656
92830
|
searchDir = rel;
|
|
92657
92831
|
}
|
|
@@ -92685,9 +92859,9 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92685
92859
|
console.log(`[Listen] Received list_in_directory command: path=${parsed.path}`);
|
|
92686
92860
|
runDetachedListenerTask("list_in_directory", async () => {
|
|
92687
92861
|
try {
|
|
92688
|
-
const { readdir:
|
|
92862
|
+
const { readdir: readdir7 } = await import("node:fs/promises");
|
|
92689
92863
|
console.log(`[Listen] Reading directory: ${parsed.path}`);
|
|
92690
|
-
const entries = await
|
|
92864
|
+
const entries = await readdir7(parsed.path, { withFileTypes: true });
|
|
92691
92865
|
console.log(`[Listen] Directory read success, ${entries.length} entries`);
|
|
92692
92866
|
const IGNORED_NAMES = new Set([
|
|
92693
92867
|
".DS_Store",
|
|
@@ -92746,8 +92920,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92746
92920
|
console.log(`[Listen] Received read_file command: path=${parsed.path}, request_id=${parsed.request_id}`);
|
|
92747
92921
|
runDetachedListenerTask("read_file", async () => {
|
|
92748
92922
|
try {
|
|
92749
|
-
const { readFile:
|
|
92750
|
-
const content = await
|
|
92923
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
92924
|
+
const content = await readFile11(parsed.path, "utf-8");
|
|
92751
92925
|
console.log(`[Listen] read_file success: ${parsed.path} (${content.length} bytes)`);
|
|
92752
92926
|
safeSocketSend(socket, {
|
|
92753
92927
|
type: "read_file_response",
|
|
@@ -92777,10 +92951,10 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92777
92951
|
try {
|
|
92778
92952
|
const { edit: edit2 } = await Promise.resolve().then(() => (init_Edit2(), exports_Edit));
|
|
92779
92953
|
const { write: write2 } = await Promise.resolve().then(() => (init_Write2(), exports_Write));
|
|
92780
|
-
const { readFile:
|
|
92954
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
92781
92955
|
let currentContent = null;
|
|
92782
92956
|
try {
|
|
92783
|
-
currentContent = await
|
|
92957
|
+
currentContent = await readFile11(parsed.path, "utf-8");
|
|
92784
92958
|
} catch (readErr) {
|
|
92785
92959
|
const e = readErr;
|
|
92786
92960
|
if (e.code !== "ENOENT")
|
|
@@ -92829,11 +93003,11 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92829
93003
|
return;
|
|
92830
93004
|
}
|
|
92831
93005
|
try {
|
|
92832
|
-
const { watch } = await import("node:fs");
|
|
92833
|
-
const { stat:
|
|
93006
|
+
const { watch: watch2 } = await import("node:fs");
|
|
93007
|
+
const { stat: stat7 } = await import("node:fs/promises");
|
|
92834
93008
|
if (cancelledWatches.delete(parsed.path))
|
|
92835
93009
|
return;
|
|
92836
|
-
const watcher =
|
|
93010
|
+
const watcher = watch2(parsed.path, { persistent: false }, (eventType) => {
|
|
92837
93011
|
if (eventType !== "change" && eventType !== "rename")
|
|
92838
93012
|
return;
|
|
92839
93013
|
const existing2 = watchDebounceTimers.get(parsed.path);
|
|
@@ -92841,7 +93015,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92841
93015
|
clearTimeout(existing2);
|
|
92842
93016
|
watchDebounceTimers.set(parsed.path, setTimeout(() => {
|
|
92843
93017
|
watchDebounceTimers.delete(parsed.path);
|
|
92844
|
-
|
|
93018
|
+
stat7(parsed.path).then((s) => {
|
|
92845
93019
|
safeSocketSend(socket, {
|
|
92846
93020
|
type: "file_changed",
|
|
92847
93021
|
path: parsed.path,
|
|
@@ -92887,6 +93061,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92887
93061
|
console.log(`[Listen] Received edit_file command: file_path=${parsed.file_path}, request_id=${parsed.request_id}`);
|
|
92888
93062
|
runDetachedListenerTask("edit_file", async () => {
|
|
92889
93063
|
try {
|
|
93064
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
92890
93065
|
const { edit: edit2 } = await Promise.resolve().then(() => (init_Edit2(), exports_Edit));
|
|
92891
93066
|
console.log(`[Listen] Executing edit: old_string="${parsed.old_string.slice(0, 50)}${parsed.old_string.length > 50 ? "..." : ""}"`);
|
|
92892
93067
|
const result = await edit2({
|
|
@@ -92897,6 +93072,19 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92897
93072
|
expected_replacements: parsed.expected_replacements
|
|
92898
93073
|
});
|
|
92899
93074
|
console.log(`[Listen] edit_file success: ${result.replacements} replacement(s) at line ${result.startLine}`);
|
|
93075
|
+
if (result.replacements > 0) {
|
|
93076
|
+
try {
|
|
93077
|
+
const contentAfter = await readFile11(parsed.file_path, "utf-8");
|
|
93078
|
+
safeSocketSend(socket, {
|
|
93079
|
+
type: "file_ops",
|
|
93080
|
+
path: parsed.file_path,
|
|
93081
|
+
cg_entries: [],
|
|
93082
|
+
ops: [],
|
|
93083
|
+
source: "agent",
|
|
93084
|
+
document_content: contentAfter
|
|
93085
|
+
}, "listener_edit_file_ops_send_failed", "listener_edit_file");
|
|
93086
|
+
} catch {}
|
|
93087
|
+
}
|
|
92900
93088
|
safeSocketSend(socket, {
|
|
92901
93089
|
type: "edit_file_response",
|
|
92902
93090
|
request_id: parsed.request_id,
|
|
@@ -92922,6 +93110,21 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
92922
93110
|
});
|
|
92923
93111
|
return;
|
|
92924
93112
|
}
|
|
93113
|
+
if (isFileOpsCommand(parsed)) {
|
|
93114
|
+
if (parsed.document_content !== undefined) {
|
|
93115
|
+
runDetachedListenerTask("file_ops", async () => {
|
|
93116
|
+
try {
|
|
93117
|
+
const { writeFile: writeFile9 } = await import("node:fs/promises");
|
|
93118
|
+
const content = parsed.document_content;
|
|
93119
|
+
await writeFile9(parsed.path, content, "utf-8");
|
|
93120
|
+
console.log(`[Listen] file_ops: wrote ${content.length} bytes to ${parsed.path}`);
|
|
93121
|
+
} catch (err) {
|
|
93122
|
+
console.error(`[Listen] file_ops error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
93123
|
+
}
|
|
93124
|
+
});
|
|
93125
|
+
}
|
|
93126
|
+
return;
|
|
93127
|
+
}
|
|
92925
93128
|
if (isListMemoryCommand(parsed)) {
|
|
92926
93129
|
runDetachedListenerTask("list_memory", async () => {
|
|
92927
93130
|
try {
|
|
@@ -93606,6 +93809,12 @@ function createLegacyTestRuntime() {
|
|
|
93606
93809
|
listener.memfsSyncedAgents = value;
|
|
93607
93810
|
}
|
|
93608
93811
|
},
|
|
93812
|
+
worktreeWatcherByConversation: {
|
|
93813
|
+
get: () => listener.worktreeWatcherByConversation,
|
|
93814
|
+
set: (value) => {
|
|
93815
|
+
listener.worktreeWatcherByConversation = value;
|
|
93816
|
+
}
|
|
93817
|
+
},
|
|
93609
93818
|
lastEmittedStatus: {
|
|
93610
93819
|
get: () => listener.lastEmittedStatus,
|
|
93611
93820
|
set: (value) => {
|
|
@@ -93675,6 +93884,7 @@ var init_client4 = __esm(async () => {
|
|
|
93675
93884
|
init_recovery(),
|
|
93676
93885
|
init_send(),
|
|
93677
93886
|
init_turn(),
|
|
93887
|
+
init_worktree_watcher(),
|
|
93678
93888
|
init_approval(),
|
|
93679
93889
|
init_protocol_inbound(),
|
|
93680
93890
|
init_protocol_outbound()
|
|
@@ -93788,8 +93998,8 @@ function isDebugEnabled2() {
|
|
|
93788
93998
|
return lettaDebug === "1" || lettaDebug === "true" || legacyDebug === "1" || legacyDebug === "true";
|
|
93789
93999
|
}
|
|
93790
94000
|
function getDebugFile2() {
|
|
93791
|
-
const
|
|
93792
|
-
return
|
|
94001
|
+
const path24 = process.env.LETTA_DEBUG_FILE;
|
|
94002
|
+
return path24 && path24.trim().length > 0 ? path24 : null;
|
|
93793
94003
|
}
|
|
93794
94004
|
function printDebugLine2(line, level = "log") {
|
|
93795
94005
|
const debugFile = getDebugFile2();
|
|
@@ -93913,7 +94123,7 @@ __export(exports_skills2, {
|
|
|
93913
94123
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
93914
94124
|
});
|
|
93915
94125
|
import { existsSync as existsSync28 } from "node:fs";
|
|
93916
|
-
import { readdir as
|
|
94126
|
+
import { readdir as readdir8, readFile as readFile11, realpath as realpath4, stat as stat7 } from "node:fs/promises";
|
|
93917
94127
|
import { dirname as dirname13, join as join35 } from "node:path";
|
|
93918
94128
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
93919
94129
|
function getBundledSkillsPath2() {
|
|
@@ -94003,14 +94213,14 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
|
|
|
94003
94213
|
return;
|
|
94004
94214
|
}
|
|
94005
94215
|
try {
|
|
94006
|
-
const entries = await
|
|
94216
|
+
const entries = await readdir8(currentPath, { withFileTypes: true });
|
|
94007
94217
|
for (const entry of entries) {
|
|
94008
94218
|
const fullPath = join35(currentPath, entry.name);
|
|
94009
94219
|
try {
|
|
94010
94220
|
let isDirectory = entry.isDirectory();
|
|
94011
94221
|
let isFile = entry.isFile();
|
|
94012
94222
|
if (entry.isSymbolicLink()) {
|
|
94013
|
-
const entryStat = await
|
|
94223
|
+
const entryStat = await stat7(fullPath);
|
|
94014
94224
|
isDirectory = entryStat.isDirectory();
|
|
94015
94225
|
isFile = entryStat.isFile();
|
|
94016
94226
|
}
|
|
@@ -94044,7 +94254,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
|
|
|
94044
94254
|
}
|
|
94045
94255
|
}
|
|
94046
94256
|
async function parseSkillFile2(filePath, rootPath, source) {
|
|
94047
|
-
const content = await
|
|
94257
|
+
const content = await readFile11(filePath, "utf-8");
|
|
94048
94258
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
94049
94259
|
const normalizedRoot = rootPath.endsWith("/") ? rootPath.slice(0, -1) : rootPath;
|
|
94050
94260
|
const relativePath = filePath.slice(normalizedRoot.length + 1);
|
|
@@ -94103,7 +94313,7 @@ __export(exports_fs, {
|
|
|
94103
94313
|
writeJsonFile: () => writeJsonFile,
|
|
94104
94314
|
writeFile: () => writeFile10,
|
|
94105
94315
|
readJsonFile: () => readJsonFile,
|
|
94106
|
-
readFile: () =>
|
|
94316
|
+
readFile: () => readFile12,
|
|
94107
94317
|
mkdir: () => mkdir9,
|
|
94108
94318
|
exists: () => exists2
|
|
94109
94319
|
});
|
|
@@ -94114,31 +94324,31 @@ import {
|
|
|
94114
94324
|
mkdirSync as mkdirSync21
|
|
94115
94325
|
} from "node:fs";
|
|
94116
94326
|
import { dirname as dirname14 } from "node:path";
|
|
94117
|
-
async function
|
|
94118
|
-
return fsReadFileSync2(
|
|
94327
|
+
async function readFile12(path24) {
|
|
94328
|
+
return fsReadFileSync2(path24, { encoding: "utf-8" });
|
|
94119
94329
|
}
|
|
94120
|
-
async function writeFile10(
|
|
94121
|
-
const dir = dirname14(
|
|
94330
|
+
async function writeFile10(path24, content) {
|
|
94331
|
+
const dir = dirname14(path24);
|
|
94122
94332
|
if (!existsSync29(dir)) {
|
|
94123
94333
|
mkdirSync21(dir, { recursive: true });
|
|
94124
94334
|
}
|
|
94125
|
-
fsWriteFileSync2(
|
|
94335
|
+
fsWriteFileSync2(path24, content, { encoding: "utf-8", flush: true });
|
|
94126
94336
|
}
|
|
94127
|
-
function exists2(
|
|
94128
|
-
return existsSync29(
|
|
94337
|
+
function exists2(path24) {
|
|
94338
|
+
return existsSync29(path24);
|
|
94129
94339
|
}
|
|
94130
|
-
async function mkdir9(
|
|
94131
|
-
mkdirSync21(
|
|
94340
|
+
async function mkdir9(path24, options) {
|
|
94341
|
+
mkdirSync21(path24, options);
|
|
94132
94342
|
}
|
|
94133
|
-
async function readJsonFile(
|
|
94134
|
-
const text = await
|
|
94343
|
+
async function readJsonFile(path24) {
|
|
94344
|
+
const text = await readFile12(path24);
|
|
94135
94345
|
return JSON.parse(text);
|
|
94136
94346
|
}
|
|
94137
|
-
async function writeJsonFile(
|
|
94347
|
+
async function writeJsonFile(path24, data, options) {
|
|
94138
94348
|
const indent = options?.indent ?? 2;
|
|
94139
94349
|
const content = `${JSON.stringify(data, null, indent)}
|
|
94140
94350
|
`;
|
|
94141
|
-
await writeFile10(
|
|
94351
|
+
await writeFile10(path24, content);
|
|
94142
94352
|
}
|
|
94143
94353
|
var init_fs2 = () => {};
|
|
94144
94354
|
|
|
@@ -94163,7 +94373,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94163
94373
|
}
|
|
94164
94374
|
const wasRaw = process.stdin.isRaw;
|
|
94165
94375
|
const wasFlowing = process.stdin.readableFlowing;
|
|
94166
|
-
return new Promise((
|
|
94376
|
+
return new Promise((resolve27) => {
|
|
94167
94377
|
let response = "";
|
|
94168
94378
|
let resolved = false;
|
|
94169
94379
|
const cleanup = () => {
|
|
@@ -94180,7 +94390,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94180
94390
|
};
|
|
94181
94391
|
const timeout = setTimeout(() => {
|
|
94182
94392
|
cleanup();
|
|
94183
|
-
|
|
94393
|
+
resolve27(null);
|
|
94184
94394
|
}, timeoutMs);
|
|
94185
94395
|
const onData = (data) => {
|
|
94186
94396
|
response += data.toString();
|
|
@@ -94190,7 +94400,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94190
94400
|
if (match3) {
|
|
94191
94401
|
clearTimeout(timeout);
|
|
94192
94402
|
cleanup();
|
|
94193
|
-
|
|
94403
|
+
resolve27({
|
|
94194
94404
|
r: parseHexComponent(match3[1] ?? "0"),
|
|
94195
94405
|
g: parseHexComponent(match3[2] ?? "0"),
|
|
94196
94406
|
b: parseHexComponent(match3[3] ?? "0")
|
|
@@ -94205,7 +94415,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
94205
94415
|
} catch {
|
|
94206
94416
|
clearTimeout(timeout);
|
|
94207
94417
|
cleanup();
|
|
94208
|
-
|
|
94418
|
+
resolve27(null);
|
|
94209
94419
|
}
|
|
94210
94420
|
});
|
|
94211
94421
|
}
|
|
@@ -94291,7 +94501,7 @@ __export(exports_manager2, {
|
|
|
94291
94501
|
lspManager: () => lspManager2,
|
|
94292
94502
|
LSPManager: () => LSPManager2
|
|
94293
94503
|
});
|
|
94294
|
-
import * as
|
|
94504
|
+
import * as path24 from "node:path";
|
|
94295
94505
|
|
|
94296
94506
|
class LSPManager2 {
|
|
94297
94507
|
static instance = null;
|
|
@@ -94319,7 +94529,7 @@ class LSPManager2 {
|
|
|
94319
94529
|
async getOrStartServer(filePath) {
|
|
94320
94530
|
if (!this.enabled)
|
|
94321
94531
|
return null;
|
|
94322
|
-
const ext3 =
|
|
94532
|
+
const ext3 = path24.extname(filePath).toLowerCase();
|
|
94323
94533
|
const serverDef = this.serverDefinitions.find((s) => s.extensions.includes(ext3));
|
|
94324
94534
|
if (!serverDef) {
|
|
94325
94535
|
return null;
|
|
@@ -94387,7 +94597,7 @@ class LSPManager2 {
|
|
|
94387
94597
|
const client = await this.getOrStartServer(filePath);
|
|
94388
94598
|
if (!client)
|
|
94389
94599
|
return;
|
|
94390
|
-
const absolutePath =
|
|
94600
|
+
const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
|
|
94391
94601
|
const uri = `file://${absolutePath}`;
|
|
94392
94602
|
const existing = this.openDocuments.get(absolutePath);
|
|
94393
94603
|
if (!existing) {
|
|
@@ -94415,7 +94625,7 @@ class LSPManager2 {
|
|
|
94415
94625
|
if (!this.enabled)
|
|
94416
94626
|
return [];
|
|
94417
94627
|
if (filePath) {
|
|
94418
|
-
const absolutePath =
|
|
94628
|
+
const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
|
|
94419
94629
|
return this.diagnostics.get(absolutePath) || [];
|
|
94420
94630
|
}
|
|
94421
94631
|
const all = [];
|
|
@@ -94425,7 +94635,7 @@ class LSPManager2 {
|
|
|
94425
94635
|
return all;
|
|
94426
94636
|
}
|
|
94427
94637
|
getLanguageId(filePath) {
|
|
94428
|
-
const ext3 =
|
|
94638
|
+
const ext3 = path24.extname(filePath).toLowerCase();
|
|
94429
94639
|
const languageMap = {
|
|
94430
94640
|
".ts": "typescript",
|
|
94431
94641
|
".tsx": "typescriptreact",
|
|
@@ -94476,7 +94686,7 @@ __export(exports_auto_update, {
|
|
|
94476
94686
|
});
|
|
94477
94687
|
import { execFile as execFile14 } from "node:child_process";
|
|
94478
94688
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
94479
|
-
import { readdir as
|
|
94689
|
+
import { readdir as readdir9, rm as rm3 } from "node:fs/promises";
|
|
94480
94690
|
import { join as join37 } from "node:path";
|
|
94481
94691
|
import { promisify as promisify14 } from "node:util";
|
|
94482
94692
|
function debugLog4(...args) {
|
|
@@ -94644,7 +94854,7 @@ async function getNpmGlobalPath() {
|
|
|
94644
94854
|
async function cleanupOrphanedDirs(globalPath) {
|
|
94645
94855
|
const lettaAiDir = join37(globalPath, "lib/node_modules/@letta-ai");
|
|
94646
94856
|
try {
|
|
94647
|
-
const entries = await
|
|
94857
|
+
const entries = await readdir9(lettaAiDir);
|
|
94648
94858
|
for (const entry of entries) {
|
|
94649
94859
|
if (entry.startsWith(".letta-code-")) {
|
|
94650
94860
|
const orphanPath = join37(lettaAiDir, entry);
|
|
@@ -94895,13 +95105,13 @@ __export(exports_overflow, {
|
|
|
94895
95105
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
94896
95106
|
import * as fs15 from "node:fs";
|
|
94897
95107
|
import * as os5 from "node:os";
|
|
94898
|
-
import * as
|
|
95108
|
+
import * as path25 from "node:path";
|
|
94899
95109
|
function getOverflowDirectory2(workingDirectory) {
|
|
94900
95110
|
const homeDir = os5.homedir();
|
|
94901
|
-
const lettaDir =
|
|
94902
|
-
const normalizedPath =
|
|
95111
|
+
const lettaDir = path25.join(homeDir, ".letta");
|
|
95112
|
+
const normalizedPath = path25.normalize(workingDirectory);
|
|
94903
95113
|
const sanitizedPath = normalizedPath.replace(/^[/\\]/, "").replace(/[/\\:]/g, "_").replace(/\s+/g, "_");
|
|
94904
|
-
const overflowDir =
|
|
95114
|
+
const overflowDir = path25.join(lettaDir, "projects", sanitizedPath, "agent-tools");
|
|
94905
95115
|
return overflowDir;
|
|
94906
95116
|
}
|
|
94907
95117
|
function ensureOverflowDirectory2(workingDirectory) {
|
|
@@ -94915,7 +95125,7 @@ function writeOverflowFile2(content, workingDirectory, toolName) {
|
|
|
94915
95125
|
const overflowDir = ensureOverflowDirectory2(workingDirectory);
|
|
94916
95126
|
const uuid = randomUUID10();
|
|
94917
95127
|
const filename = toolName ? `${toolName.toLowerCase()}-${uuid}.txt` : `${uuid}.txt`;
|
|
94918
|
-
const filePath =
|
|
95128
|
+
const filePath = path25.join(overflowDir, filename);
|
|
94919
95129
|
fs15.writeFileSync(filePath, content, "utf-8");
|
|
94920
95130
|
return filePath;
|
|
94921
95131
|
}
|
|
@@ -94933,7 +95143,7 @@ function cleanupOldOverflowFiles(workingDirectory, maxAgeMs = 24 * 60 * 60 * 100
|
|
|
94933
95143
|
const now = Date.now();
|
|
94934
95144
|
let deletedCount = 0;
|
|
94935
95145
|
for (const file of files) {
|
|
94936
|
-
const filePath =
|
|
95146
|
+
const filePath = path25.join(overflowDir, file);
|
|
94937
95147
|
try {
|
|
94938
95148
|
const stats = fs15.statSync(filePath);
|
|
94939
95149
|
if (stats.isDirectory()) {
|
|
@@ -94960,7 +95170,7 @@ function getOverflowStats(workingDirectory) {
|
|
|
94960
95170
|
const files = fs15.readdirSync(overflowDir);
|
|
94961
95171
|
let totalSize = 0;
|
|
94962
95172
|
for (const file of files) {
|
|
94963
|
-
const filePath =
|
|
95173
|
+
const filePath = path25.join(overflowDir, file);
|
|
94964
95174
|
const stats = fs15.statSync(filePath);
|
|
94965
95175
|
totalSize += stats.size;
|
|
94966
95176
|
}
|
|
@@ -95438,10 +95648,10 @@ __export(exports_setup, {
|
|
|
95438
95648
|
runSetup: () => runSetup
|
|
95439
95649
|
});
|
|
95440
95650
|
async function runSetup() {
|
|
95441
|
-
return new Promise((
|
|
95651
|
+
return new Promise((resolve28) => {
|
|
95442
95652
|
const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
|
|
95443
95653
|
onComplete: () => {
|
|
95444
|
-
|
|
95654
|
+
resolve28();
|
|
95445
95655
|
}
|
|
95446
95656
|
}));
|
|
95447
95657
|
waitUntilExit().catch((error) => {
|
|
@@ -95936,8 +96146,8 @@ __export(exports_github_utils, {
|
|
|
95936
96146
|
parseDirNames: () => parseDirNames,
|
|
95937
96147
|
fetchGitHubContents: () => fetchGitHubContents
|
|
95938
96148
|
});
|
|
95939
|
-
async function fetchGitHubContents(owner, repo, branch,
|
|
95940
|
-
const apiPath =
|
|
96149
|
+
async function fetchGitHubContents(owner, repo, branch, path26) {
|
|
96150
|
+
const apiPath = path26 ? `repos/${owner}/${repo}/contents/${path26}?ref=${branch}` : `repos/${owner}/${repo}/contents?ref=${branch}`;
|
|
95941
96151
|
try {
|
|
95942
96152
|
const { execSync: execSync2 } = await import("node:child_process");
|
|
95943
96153
|
const result = execSync2(`gh api ${apiPath}`, {
|
|
@@ -95946,7 +96156,7 @@ async function fetchGitHubContents(owner, repo, branch, path25) {
|
|
|
95946
96156
|
});
|
|
95947
96157
|
return JSON.parse(result);
|
|
95948
96158
|
} catch {}
|
|
95949
|
-
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${
|
|
96159
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path26}?ref=${branch}`;
|
|
95950
96160
|
const response = await fetch(url, {
|
|
95951
96161
|
headers: {
|
|
95952
96162
|
Accept: "application/vnd.github.v3+json",
|
|
@@ -95954,7 +96164,7 @@ async function fetchGitHubContents(owner, repo, branch, path25) {
|
|
|
95954
96164
|
}
|
|
95955
96165
|
});
|
|
95956
96166
|
if (!response.ok) {
|
|
95957
|
-
throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${
|
|
96167
|
+
throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${path26}: ${response.statusText}`);
|
|
95958
96168
|
}
|
|
95959
96169
|
return await response.json();
|
|
95960
96170
|
}
|
|
@@ -95970,11 +96180,11 @@ __export(exports_import, {
|
|
|
95970
96180
|
extractSkillsFromAf: () => extractSkillsFromAf
|
|
95971
96181
|
});
|
|
95972
96182
|
import { createReadStream } from "node:fs";
|
|
95973
|
-
import { chmod, mkdir as mkdir10, readFile as
|
|
95974
|
-
import { dirname as dirname15, resolve as
|
|
96183
|
+
import { chmod, mkdir as mkdir10, readFile as readFile13, writeFile as writeFile11 } from "node:fs/promises";
|
|
96184
|
+
import { dirname as dirname15, resolve as resolve28 } from "node:path";
|
|
95975
96185
|
async function importAgentFromFile(options) {
|
|
95976
96186
|
const client = await getClient();
|
|
95977
|
-
const resolvedPath =
|
|
96187
|
+
const resolvedPath = resolve28(options.filePath);
|
|
95978
96188
|
const file = createReadStream(resolvedPath);
|
|
95979
96189
|
const importResponse = await client.agents.importFile({
|
|
95980
96190
|
file,
|
|
@@ -96003,13 +96213,13 @@ async function importAgentFromFile(options) {
|
|
|
96003
96213
|
}
|
|
96004
96214
|
async function extractSkillsFromAf(afPath, destDir) {
|
|
96005
96215
|
const extracted = [];
|
|
96006
|
-
const content = await
|
|
96216
|
+
const content = await readFile13(afPath, "utf-8");
|
|
96007
96217
|
const afData = JSON.parse(content);
|
|
96008
96218
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
96009
96219
|
return [];
|
|
96010
96220
|
}
|
|
96011
96221
|
for (const skill2 of afData.skills) {
|
|
96012
|
-
const skillDir =
|
|
96222
|
+
const skillDir = resolve28(destDir, skill2.name);
|
|
96013
96223
|
await mkdir10(skillDir, { recursive: true });
|
|
96014
96224
|
if (skill2.files) {
|
|
96015
96225
|
await writeSkillFiles(skillDir, skill2.files);
|
|
@@ -96029,7 +96239,7 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
96029
96239
|
}
|
|
96030
96240
|
}
|
|
96031
96241
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
96032
|
-
const fullPath =
|
|
96242
|
+
const fullPath = resolve28(skillDir, filePath);
|
|
96033
96243
|
await mkdir10(dirname15(fullPath), { recursive: true });
|
|
96034
96244
|
await writeFile11(fullPath, content, "utf-8");
|
|
96035
96245
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
@@ -96048,13 +96258,13 @@ async function fetchSkillFromUrl(skillDir, sourceUrl) {
|
|
|
96048
96258
|
const owner = parts[0];
|
|
96049
96259
|
const repo = parts[1];
|
|
96050
96260
|
const branch = parts[2];
|
|
96051
|
-
const
|
|
96261
|
+
const path26 = parts.slice(3).join("/");
|
|
96052
96262
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
96053
|
-
const entries = await fetchGitHubContents2(owner, repo, branch,
|
|
96263
|
+
const entries = await fetchGitHubContents2(owner, repo, branch, path26);
|
|
96054
96264
|
if (!Array.isArray(entries)) {
|
|
96055
96265
|
throw new Error(`Expected directory at ${sourceUrl}, got file`);
|
|
96056
96266
|
}
|
|
96057
|
-
await downloadGitHubDirectory(entries, skillDir, owner, repo, branch,
|
|
96267
|
+
await downloadGitHubDirectory(entries, skillDir, owner, repo, branch, path26);
|
|
96058
96268
|
}
|
|
96059
96269
|
async function downloadGitHubDirectory(entries, destDir, owner, repo, branch, basePath) {
|
|
96060
96270
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
@@ -96361,12 +96571,12 @@ async function prepareHeadlessToolExecutionContext(params) {
|
|
|
96361
96571
|
};
|
|
96362
96572
|
}
|
|
96363
96573
|
async function flushAndExit(code) {
|
|
96364
|
-
const flushWritable = (stream2) => new Promise((
|
|
96574
|
+
const flushWritable = (stream2) => new Promise((resolve29) => {
|
|
96365
96575
|
if (stream2.destroyed || stream2.writableEnded) {
|
|
96366
|
-
|
|
96576
|
+
resolve29();
|
|
96367
96577
|
return;
|
|
96368
96578
|
}
|
|
96369
|
-
stream2.write("", () =>
|
|
96579
|
+
stream2.write("", () => resolve29());
|
|
96370
96580
|
});
|
|
96371
96581
|
await Promise.allSettled([
|
|
96372
96582
|
flushWritable(process.stdout),
|
|
@@ -97325,7 +97535,7 @@ ${loadedContents.join(`
|
|
|
97325
97535
|
} else {
|
|
97326
97536
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
97327
97537
|
}
|
|
97328
|
-
await new Promise((
|
|
97538
|
+
await new Promise((resolve29) => setTimeout(resolve29, retryDelayMs));
|
|
97329
97539
|
continue;
|
|
97330
97540
|
}
|
|
97331
97541
|
}
|
|
@@ -97374,7 +97584,7 @@ ${loadedContents.join(`
|
|
|
97374
97584
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97375
97585
|
console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97376
97586
|
}
|
|
97377
|
-
await new Promise((
|
|
97587
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97378
97588
|
conversationBusyRetries = 0;
|
|
97379
97589
|
continue;
|
|
97380
97590
|
}
|
|
@@ -97613,7 +97823,7 @@ ${loadedContents.join(`
|
|
|
97613
97823
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97614
97824
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97615
97825
|
}
|
|
97616
|
-
await new Promise((
|
|
97826
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97617
97827
|
refreshCurrentInputOtids();
|
|
97618
97828
|
continue;
|
|
97619
97829
|
}
|
|
@@ -97703,7 +97913,7 @@ ${loadedContents.join(`
|
|
|
97703
97913
|
} else {
|
|
97704
97914
|
console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
97705
97915
|
}
|
|
97706
|
-
await new Promise((
|
|
97916
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97707
97917
|
refreshCurrentInputOtids();
|
|
97708
97918
|
continue;
|
|
97709
97919
|
}
|
|
@@ -97731,7 +97941,7 @@ ${loadedContents.join(`
|
|
|
97731
97941
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97732
97942
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97733
97943
|
}
|
|
97734
|
-
await new Promise((
|
|
97944
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97735
97945
|
refreshCurrentInputOtids();
|
|
97736
97946
|
continue;
|
|
97737
97947
|
}
|
|
@@ -97761,7 +97971,7 @@ ${loadedContents.join(`
|
|
|
97761
97971
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
97762
97972
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
97763
97973
|
}
|
|
97764
|
-
await new Promise((
|
|
97974
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
97765
97975
|
refreshCurrentInputOtids();
|
|
97766
97976
|
continue;
|
|
97767
97977
|
}
|
|
@@ -98101,9 +98311,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98101
98311
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
98102
98312
|
maybeNotifyBlocked(syntheticUserLine);
|
|
98103
98313
|
if (lineResolver) {
|
|
98104
|
-
const
|
|
98314
|
+
const resolve29 = lineResolver;
|
|
98105
98315
|
lineResolver = null;
|
|
98106
|
-
|
|
98316
|
+
resolve29(syntheticUserLine);
|
|
98107
98317
|
return;
|
|
98108
98318
|
}
|
|
98109
98319
|
lineQueue.push(syntheticUserLine);
|
|
@@ -98111,9 +98321,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98111
98321
|
rl.on("line", (line) => {
|
|
98112
98322
|
maybeNotifyBlocked(line);
|
|
98113
98323
|
if (lineResolver) {
|
|
98114
|
-
const
|
|
98324
|
+
const resolve29 = lineResolver;
|
|
98115
98325
|
lineResolver = null;
|
|
98116
|
-
|
|
98326
|
+
resolve29(line);
|
|
98117
98327
|
} else {
|
|
98118
98328
|
lineQueue.push(line);
|
|
98119
98329
|
}
|
|
@@ -98122,17 +98332,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98122
98332
|
setMessageQueueAdder(null);
|
|
98123
98333
|
msgQueueRuntime.clear("shutdown");
|
|
98124
98334
|
if (lineResolver) {
|
|
98125
|
-
const
|
|
98335
|
+
const resolve29 = lineResolver;
|
|
98126
98336
|
lineResolver = null;
|
|
98127
|
-
|
|
98337
|
+
resolve29(null);
|
|
98128
98338
|
}
|
|
98129
98339
|
});
|
|
98130
98340
|
async function getNextLine() {
|
|
98131
98341
|
if (lineQueue.length > 0) {
|
|
98132
98342
|
return lineQueue.shift() ?? null;
|
|
98133
98343
|
}
|
|
98134
|
-
return new Promise((
|
|
98135
|
-
lineResolver =
|
|
98344
|
+
return new Promise((resolve29) => {
|
|
98345
|
+
lineResolver = resolve29;
|
|
98136
98346
|
});
|
|
98137
98347
|
}
|
|
98138
98348
|
async function requestPermission(toolCallId, toolName, toolInput) {
|
|
@@ -98623,7 +98833,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
98623
98833
|
uuid: `retry-bidir-${randomUUID13()}`
|
|
98624
98834
|
};
|
|
98625
98835
|
console.log(JSON.stringify(retryMsg));
|
|
98626
|
-
await new Promise((
|
|
98836
|
+
await new Promise((resolve29) => setTimeout(resolve29, delayMs));
|
|
98627
98837
|
continue;
|
|
98628
98838
|
}
|
|
98629
98839
|
throw preStreamError;
|
|
@@ -98925,10 +99135,10 @@ async function detectAndEnableKittyProtocol() {
|
|
|
98925
99135
|
detectionComplete = true;
|
|
98926
99136
|
return;
|
|
98927
99137
|
}
|
|
98928
|
-
return new Promise((
|
|
99138
|
+
return new Promise((resolve29) => {
|
|
98929
99139
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
98930
99140
|
detectionComplete = true;
|
|
98931
|
-
|
|
99141
|
+
resolve29();
|
|
98932
99142
|
return;
|
|
98933
99143
|
}
|
|
98934
99144
|
const originalRawMode = process.stdin.isRaw;
|
|
@@ -98961,7 +99171,7 @@ async function detectAndEnableKittyProtocol() {
|
|
|
98961
99171
|
console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
|
|
98962
99172
|
}
|
|
98963
99173
|
detectionComplete = true;
|
|
98964
|
-
|
|
99174
|
+
resolve29();
|
|
98965
99175
|
};
|
|
98966
99176
|
const handleData = (data) => {
|
|
98967
99177
|
if (timeoutId === undefined) {
|
|
@@ -99174,13 +99384,13 @@ var init_reconcileExistingAgentState = __esm(() => {
|
|
|
99174
99384
|
// src/agent/sessionHistory.ts
|
|
99175
99385
|
import * as fs17 from "node:fs";
|
|
99176
99386
|
import * as os6 from "node:os";
|
|
99177
|
-
import * as
|
|
99387
|
+
import * as path26 from "node:path";
|
|
99178
99388
|
function getHistoryDir() {
|
|
99179
99389
|
const homeDir = os6.homedir();
|
|
99180
|
-
return
|
|
99390
|
+
return path26.join(homeDir, ".letta");
|
|
99181
99391
|
}
|
|
99182
99392
|
function getHistoryFilePath() {
|
|
99183
|
-
return
|
|
99393
|
+
return path26.join(getHistoryDir(), "sessions.jsonl");
|
|
99184
99394
|
}
|
|
99185
99395
|
function recordSessionEnd(agentId, sessionId, stats, sessionInfo, cost, metadata) {
|
|
99186
99396
|
const entry = {
|
|
@@ -117444,8 +117654,8 @@ function getHeader(command) {
|
|
|
117444
117654
|
return `Run memory ${command}?`;
|
|
117445
117655
|
}
|
|
117446
117656
|
}
|
|
117447
|
-
function displayPath(
|
|
117448
|
-
return
|
|
117657
|
+
function displayPath(path27) {
|
|
117658
|
+
return path27.replace(/\.md$/, "");
|
|
117449
117659
|
}
|
|
117450
117660
|
function truncate2(text, max) {
|
|
117451
117661
|
if (text.length <= max)
|
|
@@ -117549,7 +117759,7 @@ var init_InlineMemoryApproval = __esm(async () => {
|
|
|
117549
117759
|
const {
|
|
117550
117760
|
command,
|
|
117551
117761
|
reason,
|
|
117552
|
-
path:
|
|
117762
|
+
path: path27,
|
|
117553
117763
|
oldPath,
|
|
117554
117764
|
newPath,
|
|
117555
117765
|
oldString,
|
|
@@ -117596,9 +117806,9 @@ var init_InlineMemoryApproval = __esm(async () => {
|
|
|
117596
117806
|
}, undefined, false, undefined, this)
|
|
117597
117807
|
]
|
|
117598
117808
|
}, undefined, true, undefined, this)
|
|
117599
|
-
}, undefined, false, undefined, this) :
|
|
117809
|
+
}, undefined, false, undefined, this) : path27 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text2, {
|
|
117600
117810
|
bold: true,
|
|
117601
|
-
children: displayPath(
|
|
117811
|
+
children: displayPath(path27)
|
|
117602
117812
|
}, undefined, false, undefined, this),
|
|
117603
117813
|
command === "str_replace" && oldString != null && newString != null && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
|
|
117604
117814
|
flexDirection: "column",
|
|
@@ -121237,7 +121447,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
121237
121447
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
121238
121448
|
import { existsSync as existsSync34, readFileSync as readFileSync20, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
|
|
121239
121449
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
121240
|
-
import { basename as basename9, extname as extname8, isAbsolute as
|
|
121450
|
+
import { basename as basename9, extname as extname8, isAbsolute as isAbsolute20, join as join42, resolve as resolve29 } from "node:path";
|
|
121241
121451
|
function countLines2(text) {
|
|
121242
121452
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
121243
121453
|
}
|
|
@@ -121284,8 +121494,8 @@ function translatePasteForImages(paste) {
|
|
|
121284
121494
|
}
|
|
121285
121495
|
} catch {}
|
|
121286
121496
|
}
|
|
121287
|
-
if (!
|
|
121288
|
-
filePath =
|
|
121497
|
+
if (!isAbsolute20(filePath))
|
|
121498
|
+
filePath = resolve29(process.cwd(), filePath);
|
|
121289
121499
|
const ext3 = extname8(filePath || "").toLowerCase();
|
|
121290
121500
|
if (IMAGE_EXTS.has(ext3) && existsSync34(filePath) && statSync10(filePath).isFile()) {
|
|
121291
121501
|
const buf = readFileSync20(filePath);
|
|
@@ -122220,14 +122430,14 @@ function installKeybindingForCurrentTerminal() {
|
|
|
122220
122430
|
error: "Not running in a VS Code-like terminal"
|
|
122221
122431
|
};
|
|
122222
122432
|
}
|
|
122223
|
-
const
|
|
122224
|
-
if (!
|
|
122433
|
+
const path27 = getKeybindingsPath(terminal);
|
|
122434
|
+
if (!path27) {
|
|
122225
122435
|
return {
|
|
122226
122436
|
success: false,
|
|
122227
122437
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
122228
122438
|
};
|
|
122229
122439
|
}
|
|
122230
|
-
return installKeybinding(
|
|
122440
|
+
return installKeybinding(path27);
|
|
122231
122441
|
}
|
|
122232
122442
|
function removeKeybindingForCurrentTerminal() {
|
|
122233
122443
|
const terminal = detectTerminalType();
|
|
@@ -122237,14 +122447,14 @@ function removeKeybindingForCurrentTerminal() {
|
|
|
122237
122447
|
error: "Not running in a VS Code-like terminal"
|
|
122238
122448
|
};
|
|
122239
122449
|
}
|
|
122240
|
-
const
|
|
122241
|
-
if (!
|
|
122450
|
+
const path27 = getKeybindingsPath(terminal);
|
|
122451
|
+
if (!path27) {
|
|
122242
122452
|
return {
|
|
122243
122453
|
success: false,
|
|
122244
122454
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
122245
122455
|
};
|
|
122246
122456
|
}
|
|
122247
|
-
return removeKeybinding(
|
|
122457
|
+
return removeKeybinding(path27);
|
|
122248
122458
|
}
|
|
122249
122459
|
function isWezTerm() {
|
|
122250
122460
|
return process.env.TERM_PROGRAM === "WezTerm";
|
|
@@ -122900,7 +123110,7 @@ __export(exports_custom, {
|
|
|
122900
123110
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
122901
123111
|
});
|
|
122902
123112
|
import { existsSync as existsSync36 } from "node:fs";
|
|
122903
|
-
import { readdir as
|
|
123113
|
+
import { readdir as readdir10, readFile as readFile14 } from "node:fs/promises";
|
|
122904
123114
|
import { basename as basename10, dirname as dirname17, join as join44 } from "node:path";
|
|
122905
123115
|
async function getCustomCommands() {
|
|
122906
123116
|
if (cachedCommands !== null) {
|
|
@@ -122942,7 +123152,7 @@ async function discoverFromDirectory(dirPath, source2) {
|
|
|
122942
123152
|
}
|
|
122943
123153
|
async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
122944
123154
|
try {
|
|
122945
|
-
const entries = await
|
|
123155
|
+
const entries = await readdir10(currentPath, { withFileTypes: true });
|
|
122946
123156
|
for (const entry of entries) {
|
|
122947
123157
|
const fullPath = join44(currentPath, entry.name);
|
|
122948
123158
|
if (entry.isDirectory()) {
|
|
@@ -122959,7 +123169,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
|
122959
123169
|
} catch (_error) {}
|
|
122960
123170
|
}
|
|
122961
123171
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
122962
|
-
const content = await
|
|
123172
|
+
const content = await readFile14(filePath, "utf-8");
|
|
122963
123173
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
122964
123174
|
const id = basename10(filePath, ".md");
|
|
122965
123175
|
const relativePath = dirname17(filePath).slice(rootPath.length);
|
|
@@ -123311,11 +123521,11 @@ var init_HelpDialog = __esm(async () => {
|
|
|
123311
123521
|
|
|
123312
123522
|
// src/hooks/writer.ts
|
|
123313
123523
|
import { homedir as homedir34 } from "node:os";
|
|
123314
|
-
import { resolve as
|
|
123524
|
+
import { resolve as resolve30 } from "node:path";
|
|
123315
123525
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
123316
123526
|
const home = process.env.HOME || homedir34();
|
|
123317
|
-
const globalSettingsPath =
|
|
123318
|
-
const projectSettingsPath =
|
|
123527
|
+
const globalSettingsPath = resolve30(home, ".letta", "settings.json");
|
|
123528
|
+
const projectSettingsPath = resolve30(workingDirectory, ".letta", "settings.json");
|
|
123319
123529
|
return globalSettingsPath === projectSettingsPath;
|
|
123320
123530
|
}
|
|
123321
123531
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -125953,7 +126163,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
125953
126163
|
|
|
125954
126164
|
// src/cli/helpers/fileSearch.ts
|
|
125955
126165
|
import { readdirSync as readdirSync12, statSync as statSync11 } from "node:fs";
|
|
125956
|
-
import { join as join45, relative as relative16, resolve as
|
|
126166
|
+
import { join as join45, relative as relative16, resolve as resolve31 } from "node:path";
|
|
125957
126167
|
function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
|
|
125958
126168
|
if (results.length >= maxResults || depth >= maxDepth) {
|
|
125959
126169
|
return results;
|
|
@@ -125996,7 +126206,7 @@ async function searchFiles(query, deep = false) {
|
|
|
125996
126206
|
const dirPart = query.slice(0, lastSlashIndex);
|
|
125997
126207
|
const pattern = query.slice(lastSlashIndex + 1);
|
|
125998
126208
|
try {
|
|
125999
|
-
const resolvedDir =
|
|
126209
|
+
const resolvedDir = resolve31(getIndexRoot(), dirPart);
|
|
126000
126210
|
try {
|
|
126001
126211
|
statSync11(resolvedDir);
|
|
126002
126212
|
searchDir = resolvedDir;
|
|
@@ -128321,9 +128531,9 @@ function buildInstallPrBody(workflowPath) {
|
|
|
128321
128531
|
].join(`
|
|
128322
128532
|
`);
|
|
128323
128533
|
}
|
|
128324
|
-
function checkRemoteFileExists(repo,
|
|
128534
|
+
function checkRemoteFileExists(repo, path27) {
|
|
128325
128535
|
try {
|
|
128326
|
-
runCommand("gh", ["api", `repos/${repo}/contents/${
|
|
128536
|
+
runCommand("gh", ["api", `repos/${repo}/contents/${path27}`]);
|
|
128327
128537
|
return true;
|
|
128328
128538
|
} catch {
|
|
128329
128539
|
return false;
|
|
@@ -135684,7 +135894,7 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
135684
135894
|
});
|
|
135685
135895
|
|
|
135686
135896
|
// src/utils/aws-credentials.ts
|
|
135687
|
-
import { readFile as
|
|
135897
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
135688
135898
|
import { homedir as homedir36 } from "node:os";
|
|
135689
135899
|
import { join as join48 } from "node:path";
|
|
135690
135900
|
async function parseAwsCredentials() {
|
|
@@ -135692,11 +135902,11 @@ async function parseAwsCredentials() {
|
|
|
135692
135902
|
const configPath = join48(homedir36(), ".aws", "config");
|
|
135693
135903
|
const profiles = new Map;
|
|
135694
135904
|
try {
|
|
135695
|
-
const content = await
|
|
135905
|
+
const content = await readFile15(credentialsPath, "utf-8");
|
|
135696
135906
|
parseIniFile(content, profiles, false);
|
|
135697
135907
|
} catch {}
|
|
135698
135908
|
try {
|
|
135699
|
-
const content = await
|
|
135909
|
+
const content = await readFile15(configPath, "utf-8");
|
|
135700
135910
|
parseIniFile(content, profiles, true);
|
|
135701
135911
|
} catch {}
|
|
135702
135912
|
return Array.from(profiles.values());
|
|
@@ -138303,8 +138513,8 @@ function MemoryDiffRenderer({
|
|
|
138303
138513
|
}, undefined, false, undefined, this);
|
|
138304
138514
|
}
|
|
138305
138515
|
const command = args.command;
|
|
138306
|
-
const
|
|
138307
|
-
const blockName =
|
|
138516
|
+
const path27 = args.path || args.old_path || "unknown";
|
|
138517
|
+
const blockName = path27.split("/").pop() || path27;
|
|
138308
138518
|
switch (command) {
|
|
138309
138519
|
case "str_replace": {
|
|
138310
138520
|
const oldStr = args.old_string || args.old_str || "";
|
|
@@ -141176,7 +141386,7 @@ async function executeStatusLineCommand(command, payload, options) {
|
|
|
141176
141386
|
};
|
|
141177
141387
|
}
|
|
141178
141388
|
function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
|
|
141179
|
-
return new Promise((
|
|
141389
|
+
return new Promise((resolve32, reject) => {
|
|
141180
141390
|
const [executable, ...args] = launcher;
|
|
141181
141391
|
if (!executable) {
|
|
141182
141392
|
reject(new Error("Empty launcher"));
|
|
@@ -141189,7 +141399,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
|
|
|
141189
141399
|
const safeResolve = (result) => {
|
|
141190
141400
|
if (!resolved) {
|
|
141191
141401
|
resolved = true;
|
|
141192
|
-
|
|
141402
|
+
resolve32(result);
|
|
141193
141403
|
}
|
|
141194
141404
|
};
|
|
141195
141405
|
let child;
|
|
@@ -142361,28 +142571,28 @@ var exports_export = {};
|
|
|
142361
142571
|
__export(exports_export, {
|
|
142362
142572
|
packageSkills: () => packageSkills
|
|
142363
142573
|
});
|
|
142364
|
-
import { readdir as
|
|
142365
|
-
import { relative as relative17, resolve as
|
|
142574
|
+
import { readdir as readdir11, readFile as readFile16 } from "node:fs/promises";
|
|
142575
|
+
import { relative as relative17, resolve as resolve32 } from "node:path";
|
|
142366
142576
|
async function packageSkills(agentId, skillsDir) {
|
|
142367
142577
|
const skills = [];
|
|
142368
142578
|
const skillNames = new Set;
|
|
142369
142579
|
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
142370
142580
|
agentId && getAgentSkillsDir(agentId),
|
|
142371
|
-
|
|
142372
|
-
|
|
142581
|
+
resolve32(process.cwd(), ".skills"),
|
|
142582
|
+
resolve32(process.env.HOME || "~", ".letta", "skills")
|
|
142373
142583
|
].filter((dir) => Boolean(dir));
|
|
142374
142584
|
for (const baseDir of dirsToCheck) {
|
|
142375
142585
|
try {
|
|
142376
|
-
const entries = await
|
|
142586
|
+
const entries = await readdir11(baseDir, { withFileTypes: true });
|
|
142377
142587
|
for (const entry of entries) {
|
|
142378
142588
|
if (!entry.isDirectory())
|
|
142379
142589
|
continue;
|
|
142380
142590
|
if (skillNames.has(entry.name))
|
|
142381
142591
|
continue;
|
|
142382
|
-
const skillDir =
|
|
142383
|
-
const skillMdPath =
|
|
142592
|
+
const skillDir = resolve32(baseDir, entry.name);
|
|
142593
|
+
const skillMdPath = resolve32(skillDir, "SKILL.md");
|
|
142384
142594
|
try {
|
|
142385
|
-
await
|
|
142595
|
+
await readFile16(skillMdPath, "utf-8");
|
|
142386
142596
|
} catch {
|
|
142387
142597
|
console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
|
|
142388
142598
|
continue;
|
|
@@ -142408,13 +142618,13 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
142408
142618
|
async function readSkillFiles(skillDir) {
|
|
142409
142619
|
const files = {};
|
|
142410
142620
|
async function walk(dir) {
|
|
142411
|
-
const entries = await
|
|
142621
|
+
const entries = await readdir11(dir, { withFileTypes: true });
|
|
142412
142622
|
for (const entry of entries) {
|
|
142413
|
-
const fullPath =
|
|
142623
|
+
const fullPath = resolve32(dir, entry.name);
|
|
142414
142624
|
if (entry.isDirectory()) {
|
|
142415
142625
|
await walk(fullPath);
|
|
142416
142626
|
} else {
|
|
142417
|
-
const content = await
|
|
142627
|
+
const content = await readFile16(fullPath, "utf-8");
|
|
142418
142628
|
const relativePath = relative17(skillDir, fullPath).replace(/\\/g, "/");
|
|
142419
142629
|
files[relativePath] = content;
|
|
142420
142630
|
}
|
|
@@ -142434,8 +142644,8 @@ async function findSkillSourceUrl(skillName) {
|
|
|
142434
142644
|
}
|
|
142435
142645
|
return null;
|
|
142436
142646
|
}
|
|
142437
|
-
async function fetchGitHubDirs(
|
|
142438
|
-
const [owner, repo, branch, ...pathParts] =
|
|
142647
|
+
async function fetchGitHubDirs(path27) {
|
|
142648
|
+
const [owner, repo, branch, ...pathParts] = path27.split("/");
|
|
142439
142649
|
if (!owner || !repo || !branch)
|
|
142440
142650
|
return new Set;
|
|
142441
142651
|
try {
|
|
@@ -144592,12 +144802,12 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
|
|
|
144592
144802
|
let watcher = null;
|
|
144593
144803
|
(async () => {
|
|
144594
144804
|
try {
|
|
144595
|
-
const { watch } = await import("node:fs");
|
|
144805
|
+
const { watch: watch2 } = await import("node:fs");
|
|
144596
144806
|
const { existsSync: existsSync43 } = await import("node:fs");
|
|
144597
144807
|
const memRoot = getMemoryFilesystemRoot(agentId);
|
|
144598
144808
|
if (!existsSync43(memRoot))
|
|
144599
144809
|
return;
|
|
144600
|
-
watcher =
|
|
144810
|
+
watcher = watch2(memRoot, { recursive: true }, () => {});
|
|
144601
144811
|
memfsWatcherRef.current = watcher;
|
|
144602
144812
|
debugLog("memfs", `Watching memory directory: ${memRoot}`);
|
|
144603
144813
|
watcher.on("error", (err) => {
|
|
@@ -144924,7 +145134,7 @@ ${newState.originalPrompt}`,
|
|
|
144924
145134
|
cancelled = true;
|
|
144925
145135
|
break;
|
|
144926
145136
|
}
|
|
144927
|
-
await new Promise((
|
|
145137
|
+
await new Promise((resolve33) => setTimeout(resolve33, 100));
|
|
144928
145138
|
}
|
|
144929
145139
|
buffersRef.current.byId.delete(statusId);
|
|
144930
145140
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
@@ -144988,7 +145198,7 @@ ${newState.originalPrompt}`,
|
|
|
144988
145198
|
cancelled = true;
|
|
144989
145199
|
break;
|
|
144990
145200
|
}
|
|
144991
|
-
await new Promise((
|
|
145201
|
+
await new Promise((resolve33) => setTimeout(resolve33, 100));
|
|
144992
145202
|
}
|
|
144993
145203
|
if (retryStatusId) {
|
|
144994
145204
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -145746,7 +145956,7 @@ ${feedback}
|
|
|
145746
145956
|
});
|
|
145747
145957
|
buffersRef.current.order.push(statusId);
|
|
145748
145958
|
refreshDerived();
|
|
145749
|
-
await new Promise((
|
|
145959
|
+
await new Promise((resolve33) => setTimeout(resolve33, delayMs));
|
|
145750
145960
|
buffersRef.current.byId.delete(statusId);
|
|
145751
145961
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
145752
145962
|
refreshDerived();
|
|
@@ -145806,7 +146016,7 @@ ${feedback}
|
|
|
145806
146016
|
cancelled = true;
|
|
145807
146017
|
break;
|
|
145808
146018
|
}
|
|
145809
|
-
await new Promise((
|
|
146019
|
+
await new Promise((resolve33) => setTimeout(resolve33, 100));
|
|
145810
146020
|
}
|
|
145811
146021
|
if (retryStatusId) {
|
|
145812
146022
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -152514,14 +152724,14 @@ function installKeybindingForCurrentTerminal2() {
|
|
|
152514
152724
|
error: "Not running in a VS Code-like terminal"
|
|
152515
152725
|
};
|
|
152516
152726
|
}
|
|
152517
|
-
const
|
|
152518
|
-
if (!
|
|
152727
|
+
const path27 = getKeybindingsPath2(terminal);
|
|
152728
|
+
if (!path27) {
|
|
152519
152729
|
return {
|
|
152520
152730
|
success: false,
|
|
152521
152731
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
152522
152732
|
};
|
|
152523
152733
|
}
|
|
152524
|
-
return installKeybinding2(
|
|
152734
|
+
return installKeybinding2(path27);
|
|
152525
152735
|
}
|
|
152526
152736
|
function removeKeybindingForCurrentTerminal2() {
|
|
152527
152737
|
const terminal = detectTerminalType2();
|
|
@@ -152531,14 +152741,14 @@ function removeKeybindingForCurrentTerminal2() {
|
|
|
152531
152741
|
error: "Not running in a VS Code-like terminal"
|
|
152532
152742
|
};
|
|
152533
152743
|
}
|
|
152534
|
-
const
|
|
152535
|
-
if (!
|
|
152744
|
+
const path27 = getKeybindingsPath2(terminal);
|
|
152745
|
+
if (!path27) {
|
|
152536
152746
|
return {
|
|
152537
152747
|
success: false,
|
|
152538
152748
|
error: `Could not determine keybindings.json path for ${terminal}`
|
|
152539
152749
|
};
|
|
152540
152750
|
}
|
|
152541
|
-
return removeKeybinding2(
|
|
152751
|
+
return removeKeybinding2(path27);
|
|
152542
152752
|
}
|
|
152543
152753
|
function isWezTerm2() {
|
|
152544
152754
|
return process.env.TERM_PROGRAM === "WezTerm";
|
|
@@ -153174,11 +153384,11 @@ __export(exports_import2, {
|
|
|
153174
153384
|
extractSkillsFromAf: () => extractSkillsFromAf2
|
|
153175
153385
|
});
|
|
153176
153386
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
153177
|
-
import { chmod as chmod2, mkdir as mkdir11, readFile as
|
|
153178
|
-
import { dirname as dirname20, resolve as
|
|
153387
|
+
import { chmod as chmod2, mkdir as mkdir11, readFile as readFile17, writeFile as writeFile12 } from "node:fs/promises";
|
|
153388
|
+
import { dirname as dirname20, resolve as resolve33 } from "node:path";
|
|
153179
153389
|
async function importAgentFromFile2(options) {
|
|
153180
153390
|
const client = await getClient();
|
|
153181
|
-
const resolvedPath =
|
|
153391
|
+
const resolvedPath = resolve33(options.filePath);
|
|
153182
153392
|
const file = createReadStream2(resolvedPath);
|
|
153183
153393
|
const importResponse = await client.agents.importFile({
|
|
153184
153394
|
file,
|
|
@@ -153207,13 +153417,13 @@ async function importAgentFromFile2(options) {
|
|
|
153207
153417
|
}
|
|
153208
153418
|
async function extractSkillsFromAf2(afPath, destDir) {
|
|
153209
153419
|
const extracted = [];
|
|
153210
|
-
const content = await
|
|
153420
|
+
const content = await readFile17(afPath, "utf-8");
|
|
153211
153421
|
const afData = JSON.parse(content);
|
|
153212
153422
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
153213
153423
|
return [];
|
|
153214
153424
|
}
|
|
153215
153425
|
for (const skill2 of afData.skills) {
|
|
153216
|
-
const skillDir =
|
|
153426
|
+
const skillDir = resolve33(destDir, skill2.name);
|
|
153217
153427
|
await mkdir11(skillDir, { recursive: true });
|
|
153218
153428
|
if (skill2.files) {
|
|
153219
153429
|
await writeSkillFiles2(skillDir, skill2.files);
|
|
@@ -153233,7 +153443,7 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
153233
153443
|
}
|
|
153234
153444
|
}
|
|
153235
153445
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
153236
|
-
const fullPath =
|
|
153446
|
+
const fullPath = resolve33(skillDir, filePath);
|
|
153237
153447
|
await mkdir11(dirname20(fullPath), { recursive: true });
|
|
153238
153448
|
await writeFile12(fullPath, content, "utf-8");
|
|
153239
153449
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
@@ -153252,13 +153462,13 @@ async function fetchSkillFromUrl2(skillDir, sourceUrl) {
|
|
|
153252
153462
|
const owner = parts[0];
|
|
153253
153463
|
const repo = parts[1];
|
|
153254
153464
|
const branch = parts[2];
|
|
153255
|
-
const
|
|
153465
|
+
const path27 = parts.slice(3).join("/");
|
|
153256
153466
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
153257
|
-
const entries = await fetchGitHubContents2(owner, repo, branch,
|
|
153467
|
+
const entries = await fetchGitHubContents2(owner, repo, branch, path27);
|
|
153258
153468
|
if (!Array.isArray(entries)) {
|
|
153259
153469
|
throw new Error(`Expected directory at ${sourceUrl}, got file`);
|
|
153260
153470
|
}
|
|
153261
|
-
await downloadGitHubDirectory2(entries, skillDir, owner, repo, branch,
|
|
153471
|
+
await downloadGitHubDirectory2(entries, skillDir, owner, repo, branch, path27);
|
|
153262
153472
|
}
|
|
153263
153473
|
async function downloadGitHubDirectory2(entries, destDir, owner, repo, branch, basePath) {
|
|
153264
153474
|
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
@@ -158271,23 +158481,21 @@ async function runListenSubcommand(argv) {
|
|
|
158271
158481
|
process.exit(code);
|
|
158272
158482
|
};
|
|
158273
158483
|
await settingsManager.loadLocalProjectSettings();
|
|
158274
|
-
|
|
158275
|
-
|
|
158276
|
-
if (
|
|
158277
|
-
|
|
158278
|
-
|
|
158279
|
-
|
|
158280
|
-
|
|
158281
|
-
|
|
158282
|
-
|
|
158283
|
-
return 1;
|
|
158284
|
-
}
|
|
158285
|
-
await ensureChannelRuntimeInstalled2(channelName);
|
|
158484
|
+
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() : [];
|
|
158485
|
+
if (channelNames.length > 0) {
|
|
158486
|
+
if (values.channels && values["install-channel-runtimes"]) {
|
|
158487
|
+
const { ensureChannelRuntimeInstalled: ensureChannelRuntimeInstalled2 } = await Promise.resolve().then(() => (init_runtimeDeps(), exports_runtimeDeps));
|
|
158488
|
+
const { isSupportedChannelId: isSupportedChannelId2 } = await Promise.resolve().then(() => (init_pluginRegistry(), exports_pluginRegistry));
|
|
158489
|
+
for (const channelName of channelNames) {
|
|
158490
|
+
if (!isSupportedChannelId2(channelName)) {
|
|
158491
|
+
console.error(`Unknown channel "${channelName}" passed to --channels.`);
|
|
158492
|
+
return 1;
|
|
158286
158493
|
}
|
|
158494
|
+
await ensureChannelRuntimeInstalled2(channelName);
|
|
158287
158495
|
}
|
|
158288
|
-
const { initializeChannels: initializeChannels2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
158289
|
-
await initializeChannels2(channelNames);
|
|
158290
158496
|
}
|
|
158497
|
+
const { initializeChannels: initializeChannels2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
158498
|
+
await initializeChannels2(channelNames);
|
|
158291
158499
|
}
|
|
158292
158500
|
let connectionName;
|
|
158293
158501
|
if (values["env-name"]) {
|
|
@@ -158301,11 +158509,11 @@ async function runListenSubcommand(argv) {
|
|
|
158301
158509
|
connectionName = hostname3();
|
|
158302
158510
|
settingsManager.setListenerEnvName(connectionName);
|
|
158303
158511
|
} else {
|
|
158304
|
-
connectionName = await new Promise((
|
|
158512
|
+
connectionName = await new Promise((resolve25) => {
|
|
158305
158513
|
const { unmount } = render_default(/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(PromptEnvName, {
|
|
158306
158514
|
onSubmit: (name) => {
|
|
158307
158515
|
unmount();
|
|
158308
|
-
|
|
158516
|
+
resolve25(name);
|
|
158309
158517
|
}
|
|
158310
158518
|
}, undefined, false, undefined, this));
|
|
158311
158519
|
});
|
|
@@ -158508,7 +158716,7 @@ async function runListenSubcommand(argv) {
|
|
|
158508
158716
|
// src/cli/subcommands/memfs.ts
|
|
158509
158717
|
init_memoryGit();
|
|
158510
158718
|
import { cpSync, existsSync as existsSync26, mkdirSync as mkdirSync19, rmSync as rmSync3, statSync as statSync8 } from "node:fs";
|
|
158511
|
-
import { readdir as
|
|
158719
|
+
import { readdir as readdir7 } from "node:fs/promises";
|
|
158512
158720
|
import { homedir as homedir24 } from "node:os";
|
|
158513
158721
|
import { join as join31 } from "node:path";
|
|
158514
158722
|
import { parseArgs as parseArgs8 } from "node:util";
|
|
@@ -158575,22 +158783,22 @@ async function listBackups(agentId) {
|
|
|
158575
158783
|
if (!existsSync26(agentRoot)) {
|
|
158576
158784
|
return [];
|
|
158577
158785
|
}
|
|
158578
|
-
const entries = await
|
|
158786
|
+
const entries = await readdir7(agentRoot, { withFileTypes: true });
|
|
158579
158787
|
const backups = [];
|
|
158580
158788
|
for (const entry of entries) {
|
|
158581
158789
|
if (!entry.isDirectory())
|
|
158582
158790
|
continue;
|
|
158583
158791
|
if (!entry.name.startsWith("memory-backup-"))
|
|
158584
158792
|
continue;
|
|
158585
|
-
const
|
|
158793
|
+
const path24 = join31(agentRoot, entry.name);
|
|
158586
158794
|
let createdAt = null;
|
|
158587
158795
|
try {
|
|
158588
|
-
const
|
|
158589
|
-
createdAt =
|
|
158796
|
+
const stat7 = statSync8(path24);
|
|
158797
|
+
createdAt = stat7.mtime.toISOString();
|
|
158590
158798
|
} catch {
|
|
158591
158799
|
createdAt = null;
|
|
158592
158800
|
}
|
|
158593
|
-
backups.push({ name: entry.name, path:
|
|
158801
|
+
backups.push({ name: entry.name, path: path24, createdAt });
|
|
158594
158802
|
}
|
|
158595
158803
|
backups.sort((a, b) => a.name.localeCompare(b.name));
|
|
158596
158804
|
return backups;
|
|
@@ -158694,8 +158902,8 @@ async function runMemfsSubcommand(argv) {
|
|
|
158694
158902
|
console.error(`Backup not found: ${backupPath}`);
|
|
158695
158903
|
return 1;
|
|
158696
158904
|
}
|
|
158697
|
-
const
|
|
158698
|
-
if (!
|
|
158905
|
+
const stat7 = statSync8(backupPath);
|
|
158906
|
+
if (!stat7.isDirectory()) {
|
|
158699
158907
|
console.error(`Backup path is not a directory: ${backupPath}`);
|
|
158700
158908
|
return 1;
|
|
158701
158909
|
}
|
|
@@ -158717,9 +158925,9 @@ async function runMemfsSubcommand(argv) {
|
|
|
158717
158925
|
return 1;
|
|
158718
158926
|
}
|
|
158719
158927
|
if (existsSync26(out)) {
|
|
158720
|
-
const
|
|
158721
|
-
if (
|
|
158722
|
-
const contents = await
|
|
158928
|
+
const stat7 = statSync8(out);
|
|
158929
|
+
if (stat7.isDirectory()) {
|
|
158930
|
+
const contents = await readdir7(out);
|
|
158723
158931
|
if (contents.length > 0) {
|
|
158724
158932
|
console.error(`Export directory not empty: ${out}`);
|
|
158725
158933
|
return 1;
|
|
@@ -158748,7 +158956,7 @@ async function runMemfsSubcommand(argv) {
|
|
|
158748
158956
|
init_client2();
|
|
158749
158957
|
init_settings_manager();
|
|
158750
158958
|
import { writeFile as writeFile9 } from "node:fs/promises";
|
|
158751
|
-
import { resolve as
|
|
158959
|
+
import { resolve as resolve25 } from "node:path";
|
|
158752
158960
|
import { parseArgs as parseArgs9 } from "node:util";
|
|
158753
158961
|
function printUsage6() {
|
|
158754
158962
|
console.log(`
|
|
@@ -159053,7 +159261,7 @@ async function runMessagesSubcommand(argv) {
|
|
|
159053
159261
|
|
|
159054
159262
|
`).trim();
|
|
159055
159263
|
if (outputPathRaw && typeof outputPathRaw === "string") {
|
|
159056
|
-
const outputPath =
|
|
159264
|
+
const outputPath = resolve25(process.cwd(), outputPathRaw);
|
|
159057
159265
|
await writeFile9(outputPath, `${transcript}
|
|
159058
159266
|
`, "utf-8");
|
|
159059
159267
|
console.log(JSON.stringify({
|
|
@@ -159115,13 +159323,13 @@ init_memoryScope();
|
|
|
159115
159323
|
init_readOnlyShell();
|
|
159116
159324
|
init_shell_command_normalization();
|
|
159117
159325
|
import { homedir as homedir25 } from "node:os";
|
|
159118
|
-
import { isAbsolute as
|
|
159326
|
+
import { isAbsolute as isAbsolute18, join as join32, relative as relative13 } from "node:path";
|
|
159119
159327
|
var MODE_KEY2 = Symbol.for("@letta/permissionMode");
|
|
159120
159328
|
var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
|
|
159121
159329
|
var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
|
|
159122
159330
|
function everyResolvedTargetIsWithinRoots2(candidatePaths, roots, workingDirectory) {
|
|
159123
|
-
return candidatePaths.length > 0 && candidatePaths.every((
|
|
159124
|
-
const resolvedPath = resolveScopedTargetPath(
|
|
159331
|
+
return candidatePaths.length > 0 && candidatePaths.every((path24) => {
|
|
159332
|
+
const resolvedPath = resolveScopedTargetPath(path24, workingDirectory);
|
|
159125
159333
|
return resolvedPath ? isPathWithinRoots(resolvedPath, roots) : false;
|
|
159126
159334
|
});
|
|
159127
159335
|
}
|
|
@@ -159155,11 +159363,11 @@ function setGlobalModeBeforePlan2(value) {
|
|
|
159155
159363
|
function resolvePlanTargetPath2(targetPath, workingDirectory) {
|
|
159156
159364
|
return resolveScopedTargetPath(targetPath, workingDirectory);
|
|
159157
159365
|
}
|
|
159158
|
-
function isPathInPlansDir2(
|
|
159159
|
-
if (!
|
|
159366
|
+
function isPathInPlansDir2(path24, plansDir) {
|
|
159367
|
+
if (!path24.endsWith(".md"))
|
|
159160
159368
|
return false;
|
|
159161
|
-
const rel = relative13(plansDir,
|
|
159162
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
159369
|
+
const rel = relative13(plansDir, path24);
|
|
159370
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute18(rel);
|
|
159163
159371
|
}
|
|
159164
159372
|
function extractApplyPatchPaths2(input) {
|
|
159165
159373
|
const paths = [];
|
|
@@ -159260,8 +159468,8 @@ class PermissionModeManager2 {
|
|
|
159260
159468
|
getMode() {
|
|
159261
159469
|
return this.currentMode;
|
|
159262
159470
|
}
|
|
159263
|
-
setPlanFilePath(
|
|
159264
|
-
setGlobalPlanFilePath2(
|
|
159471
|
+
setPlanFilePath(path24) {
|
|
159472
|
+
setGlobalPlanFilePath2(path24);
|
|
159265
159473
|
}
|
|
159266
159474
|
getPlanFilePath() {
|
|
159267
159475
|
return getGlobalPlanFilePath2();
|
|
@@ -159356,8 +159564,8 @@ class PermissionModeManager2 {
|
|
|
159356
159564
|
} else if (typeof targetPath === "string") {
|
|
159357
159565
|
candidatePaths = [targetPath];
|
|
159358
159566
|
}
|
|
159359
|
-
if (candidatePaths.length > 0 && candidatePaths.every((
|
|
159360
|
-
const resolvedPath = resolvePlanTargetPath2(
|
|
159567
|
+
if (candidatePaths.length > 0 && candidatePaths.every((path24) => {
|
|
159568
|
+
const resolvedPath = resolvePlanTargetPath2(path24, workingDirectory);
|
|
159361
159569
|
return resolvedPath ? isPathInPlansDir2(resolvedPath, plansDir) : false;
|
|
159362
159570
|
})) {
|
|
159363
159571
|
return "allow";
|
|
@@ -159516,7 +159724,7 @@ init_fs();
|
|
|
159516
159724
|
init_secrets();
|
|
159517
159725
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
159518
159726
|
import { homedir as homedir26 } from "node:os";
|
|
159519
|
-
import { join as join33, resolve as
|
|
159727
|
+
import { join as join33, resolve as resolve26 } from "node:path";
|
|
159520
159728
|
var DEFAULT_SETTINGS3 = {
|
|
159521
159729
|
lastAgent: null,
|
|
159522
159730
|
tokenStreaming: false,
|
|
@@ -159970,7 +160178,7 @@ class SettingsManager2 {
|
|
|
159970
160178
|
return join33(workingDirectory, ".letta", "settings.json");
|
|
159971
160179
|
}
|
|
159972
160180
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
159973
|
-
return
|
|
160181
|
+
return resolve26(this.getProjectSettingsPath(workingDirectory)) === resolve26(this.getSettingsPath());
|
|
159974
160182
|
}
|
|
159975
160183
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
159976
160184
|
return join33(workingDirectory, ".letta", "settings.local.json");
|
|
@@ -160915,6 +161123,7 @@ var STREAMING_SHELL_TOOLS2 = new Set([
|
|
|
160915
161123
|
"run_shell_command",
|
|
160916
161124
|
"RunShellCommand"
|
|
160917
161125
|
]);
|
|
161126
|
+
var FILE_MUTATING_TOOLS2 = new Set(["Edit", "Write", "MultiEdit", "replace"]);
|
|
160918
161127
|
var ANTHROPIC_DEFAULT_TOOLS2 = [
|
|
160919
161128
|
"AskUserQuestion",
|
|
160920
161129
|
"Bash",
|
|
@@ -160985,8 +161194,8 @@ function acquireSwitchLock2() {
|
|
|
160985
161194
|
const lock = getSwitchLock2();
|
|
160986
161195
|
lock.refCount++;
|
|
160987
161196
|
if (lock.refCount === 1) {
|
|
160988
|
-
lock.promise = new Promise((
|
|
160989
|
-
lock.resolve =
|
|
161197
|
+
lock.promise = new Promise((resolve27) => {
|
|
161198
|
+
lock.resolve = resolve27;
|
|
160990
161199
|
});
|
|
160991
161200
|
}
|
|
160992
161201
|
}
|
|
@@ -161475,7 +161684,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
161475
161684
|
printHelp();
|
|
161476
161685
|
const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
|
|
161477
161686
|
if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
|
|
161478
|
-
await new Promise((
|
|
161687
|
+
await new Promise((resolve34) => setTimeout(resolve34, helpDelayMs));
|
|
161479
161688
|
}
|
|
161480
161689
|
process.exit(0);
|
|
161481
161690
|
}
|
|
@@ -161697,9 +161906,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
161697
161906
|
process.exit(1);
|
|
161698
161907
|
}
|
|
161699
161908
|
} else {
|
|
161700
|
-
const { resolve:
|
|
161909
|
+
const { resolve: resolve34 } = await import("path");
|
|
161701
161910
|
const { existsSync: existsSync45 } = await import("fs");
|
|
161702
|
-
const resolvedPath =
|
|
161911
|
+
const resolvedPath = resolve34(fromAfFile);
|
|
161703
161912
|
if (!existsSync45(resolvedPath)) {
|
|
161704
161913
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
161705
161914
|
process.exit(1);
|
|
@@ -162579,4 +162788,4 @@ Error during initialization: ${message}`);
|
|
|
162579
162788
|
}
|
|
162580
162789
|
main();
|
|
162581
162790
|
|
|
162582
|
-
//# debugId=
|
|
162791
|
+
//# debugId=6821E41BE6A3D26164756E2164756E21
|