@letta-ai/letta-code 0.34.6 → 0.34.8
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/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-oauth.js +2 -2
- package/dist/mcp-oauth.js.map +1 -1
- package/dist/types/agent/approval-execution.d.ts.map +1 -1
- package/dist/types/permissions/checker.d.ts.map +1 -1
- package/dist/types/tools/impl/apply-patch.d.ts.map +1 -1
- package/dist/types/tools/impl/memory.d.ts +14 -0
- package/dist/types/tools/impl/memory.d.ts.map +1 -0
- package/dist/types/tools/impl/truncation.d.ts +1 -0
- package/dist/types/tools/impl/truncation.d.ts.map +1 -1
- package/dist/types/tools/manager.d.ts.map +1 -1
- package/dist/types/tools/tool-definitions.d.ts +1 -0
- package/dist/types/tools/tool-definitions.d.ts.map +1 -1
- package/dist/types/tools/toolset-catalog.d.ts +1 -1
- package/dist/types/tools/toolset-catalog.d.ts.map +1 -1
- package/letta.js +1248 -621
- package/npm-shrinkwrap.json +5 -5
- package/package.json +2 -2
- package/scripts/source-file-size-baseline.json +1 -1
package/letta.js
CHANGED
|
@@ -3930,6 +3930,7 @@ var init_toolset_catalog = __esm(() => {
|
|
|
3930
3930
|
"Wake",
|
|
3931
3931
|
"TaskStop",
|
|
3932
3932
|
"Skill",
|
|
3933
|
+
"Memory",
|
|
3933
3934
|
"Workflow",
|
|
3934
3935
|
"exec_command",
|
|
3935
3936
|
"write_stdin",
|
|
@@ -3964,6 +3965,7 @@ var init_toolset_catalog = __esm(() => {
|
|
|
3964
3965
|
"TaskStop",
|
|
3965
3966
|
"Read",
|
|
3966
3967
|
"Skill",
|
|
3968
|
+
"Memory",
|
|
3967
3969
|
"Workflow",
|
|
3968
3970
|
"Task",
|
|
3969
3971
|
"SendAgentMessage",
|
|
@@ -3990,6 +3992,7 @@ var init_toolset_catalog = __esm(() => {
|
|
|
3990
3992
|
"Wake",
|
|
3991
3993
|
"TaskStop",
|
|
3992
3994
|
"Skill",
|
|
3995
|
+
"Memory",
|
|
3993
3996
|
"Workflow",
|
|
3994
3997
|
"exec_command",
|
|
3995
3998
|
"write_stdin",
|
|
@@ -5724,7 +5727,7 @@ var package_default;
|
|
|
5724
5727
|
var init_package = __esm(() => {
|
|
5725
5728
|
package_default = {
|
|
5726
5729
|
name: "@letta-ai/letta-code",
|
|
5727
|
-
version: "0.34.
|
|
5730
|
+
version: "0.34.8",
|
|
5728
5731
|
lettaStartupLogProtocol: 1,
|
|
5729
5732
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5730
5733
|
type: "module",
|
|
@@ -5999,7 +6002,7 @@ var init_package = __esm(() => {
|
|
|
5999
6002
|
},
|
|
6000
6003
|
lettaLifecycleProtocol: 1,
|
|
6001
6004
|
lettaRuntimeGraphProtocol: 1,
|
|
6002
|
-
lettaRuntimeGraphSha512: "sha512-
|
|
6005
|
+
lettaRuntimeGraphSha512: "sha512-NkEBUY1HKUlzrKrw9Z5465jdqkp+u7tLYNly5lGlHQKUAoN/8N4gGSsIXTsc3u2Eiz9f05ryN0l5zJOf1/q1iA=="
|
|
6003
6006
|
};
|
|
6004
6007
|
});
|
|
6005
6008
|
|
|
@@ -120190,6 +120193,226 @@ var init_personality = __esm(() => {
|
|
|
120190
120193
|
execFile5 = promisify6(execFileCb3);
|
|
120191
120194
|
});
|
|
120192
120195
|
|
|
120196
|
+
// src/browser-discovery-server.ts
|
|
120197
|
+
import {
|
|
120198
|
+
createServer as createServer3
|
|
120199
|
+
} from "node:http";
|
|
120200
|
+
function startBrowserDiscoveryServer(options = {}) {
|
|
120201
|
+
const port = options.port ?? BROWSER_DISCOVERY_PORT;
|
|
120202
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
120203
|
+
let activeServer = null;
|
|
120204
|
+
let pendingServer = null;
|
|
120205
|
+
let retryTimer = null;
|
|
120206
|
+
let stopped = false;
|
|
120207
|
+
let readySettled = false;
|
|
120208
|
+
let resolveReady;
|
|
120209
|
+
let rejectReady;
|
|
120210
|
+
const ready = new Promise((resolve10, reject) => {
|
|
120211
|
+
resolveReady = resolve10;
|
|
120212
|
+
rejectReady = reject;
|
|
120213
|
+
});
|
|
120214
|
+
ready.catch(() => {
|
|
120215
|
+
return;
|
|
120216
|
+
});
|
|
120217
|
+
const scheduleRetry = () => {
|
|
120218
|
+
if (stopped || retryTimer)
|
|
120219
|
+
return;
|
|
120220
|
+
retryTimer = setTimeout(() => {
|
|
120221
|
+
retryTimer = null;
|
|
120222
|
+
attemptListen();
|
|
120223
|
+
}, retryDelayMs);
|
|
120224
|
+
retryTimer.unref();
|
|
120225
|
+
};
|
|
120226
|
+
const attemptListen = () => {
|
|
120227
|
+
if (stopped || activeServer || pendingServer)
|
|
120228
|
+
return;
|
|
120229
|
+
const candidate = createBrowserDiscoveryHttpServer();
|
|
120230
|
+
pendingServer = candidate;
|
|
120231
|
+
const onStartupError = (error4) => {
|
|
120232
|
+
pendingServer = null;
|
|
120233
|
+
candidate.close();
|
|
120234
|
+
if (error4.code === "EADDRINUSE") {
|
|
120235
|
+
scheduleRetry();
|
|
120236
|
+
return;
|
|
120237
|
+
}
|
|
120238
|
+
if (!readySettled) {
|
|
120239
|
+
readySettled = true;
|
|
120240
|
+
rejectReady(error4);
|
|
120241
|
+
}
|
|
120242
|
+
};
|
|
120243
|
+
candidate.once("error", onStartupError);
|
|
120244
|
+
candidate.listen(port, BROWSER_DISCOVERY_HOST, () => {
|
|
120245
|
+
candidate.off("error", onStartupError);
|
|
120246
|
+
if (stopped) {
|
|
120247
|
+
candidate.close();
|
|
120248
|
+
return;
|
|
120249
|
+
}
|
|
120250
|
+
pendingServer = null;
|
|
120251
|
+
activeServer = candidate;
|
|
120252
|
+
candidate.unref();
|
|
120253
|
+
const address = candidate.address();
|
|
120254
|
+
if (!address || typeof address === "string") {
|
|
120255
|
+
candidate.close();
|
|
120256
|
+
return;
|
|
120257
|
+
}
|
|
120258
|
+
if (!readySettled) {
|
|
120259
|
+
readySettled = true;
|
|
120260
|
+
resolveReady(formatDiscoveryAddress(address));
|
|
120261
|
+
}
|
|
120262
|
+
candidate.on("error", () => {
|
|
120263
|
+
if (activeServer !== candidate)
|
|
120264
|
+
return;
|
|
120265
|
+
activeServer = null;
|
|
120266
|
+
candidate.close();
|
|
120267
|
+
scheduleRetry();
|
|
120268
|
+
});
|
|
120269
|
+
candidate.once("close", () => {
|
|
120270
|
+
if (activeServer === candidate)
|
|
120271
|
+
activeServer = null;
|
|
120272
|
+
scheduleRetry();
|
|
120273
|
+
});
|
|
120274
|
+
});
|
|
120275
|
+
};
|
|
120276
|
+
attemptListen();
|
|
120277
|
+
return {
|
|
120278
|
+
ready,
|
|
120279
|
+
close: async () => {
|
|
120280
|
+
if (stopped)
|
|
120281
|
+
return;
|
|
120282
|
+
stopped = true;
|
|
120283
|
+
if (retryTimer) {
|
|
120284
|
+
clearTimeout(retryTimer);
|
|
120285
|
+
retryTimer = null;
|
|
120286
|
+
}
|
|
120287
|
+
if (!readySettled) {
|
|
120288
|
+
readySettled = true;
|
|
120289
|
+
rejectReady(new Error("Browser discovery server stopped before listening"));
|
|
120290
|
+
}
|
|
120291
|
+
const servers = [pendingServer, activeServer].filter((server2) => server2 !== null);
|
|
120292
|
+
pendingServer = null;
|
|
120293
|
+
activeServer = null;
|
|
120294
|
+
await Promise.all(servers.map(closeServer));
|
|
120295
|
+
}
|
|
120296
|
+
};
|
|
120297
|
+
}
|
|
120298
|
+
function createBrowserDiscoveryHttpServer() {
|
|
120299
|
+
let server2;
|
|
120300
|
+
server2 = createServer3((request, response) => {
|
|
120301
|
+
handleBrowserDiscoveryRequest(server2, request, response);
|
|
120302
|
+
});
|
|
120303
|
+
server2.headersTimeout = 5000;
|
|
120304
|
+
server2.requestTimeout = 5000;
|
|
120305
|
+
server2.keepAliveTimeout = 1000;
|
|
120306
|
+
server2.maxHeadersCount = 32;
|
|
120307
|
+
server2.on("connection", (socket) => socket.unref());
|
|
120308
|
+
server2.on("timeout", (socket) => socket.destroy());
|
|
120309
|
+
server2.on("clientError", (_error, socket) => {
|
|
120310
|
+
if (!socket.writable)
|
|
120311
|
+
return;
|
|
120312
|
+
socket.end(`HTTP/1.1 400 Bad Request\r
|
|
120313
|
+
Connection: close\r
|
|
120314
|
+
Content-Length: 0\r
|
|
120315
|
+
\r
|
|
120316
|
+
`);
|
|
120317
|
+
});
|
|
120318
|
+
return server2;
|
|
120319
|
+
}
|
|
120320
|
+
function handleBrowserDiscoveryRequest(server2, request, response) {
|
|
120321
|
+
if (!isLoopbackAddress(request.socket.remoteAddress)) {
|
|
120322
|
+
respond(response, 403, "Browser connection must use loopback");
|
|
120323
|
+
return;
|
|
120324
|
+
}
|
|
120325
|
+
const address = server2.address();
|
|
120326
|
+
const expectedHost = address && typeof address !== "string" ? `${BROWSER_DISCOVERY_HOST}:${address.port}` : null;
|
|
120327
|
+
if (!expectedHost || request.headers.host !== expectedHost) {
|
|
120328
|
+
respond(response, 400, "Invalid discovery host");
|
|
120329
|
+
return;
|
|
120330
|
+
}
|
|
120331
|
+
if (request.url !== BROWSER_DISCOVERY_PATH) {
|
|
120332
|
+
respond(response, 404, "Not found");
|
|
120333
|
+
return;
|
|
120334
|
+
}
|
|
120335
|
+
const requestOrigin = request.headers.origin;
|
|
120336
|
+
const origin = allowedBrowserOrigin(requestOrigin);
|
|
120337
|
+
if (requestOrigin && !origin) {
|
|
120338
|
+
respond(response, 403, "Browser origin is not allowed");
|
|
120339
|
+
return;
|
|
120340
|
+
}
|
|
120341
|
+
if (request.method === "OPTIONS") {
|
|
120342
|
+
if (!origin || request.headers["access-control-request-method"] !== "GET") {
|
|
120343
|
+
respond(response, 403, "Browser preflight is not allowed");
|
|
120344
|
+
return;
|
|
120345
|
+
}
|
|
120346
|
+
response.writeHead(204, {
|
|
120347
|
+
...browserAccessHeaders(origin),
|
|
120348
|
+
"Content-Length": "0"
|
|
120349
|
+
});
|
|
120350
|
+
response.end();
|
|
120351
|
+
return;
|
|
120352
|
+
}
|
|
120353
|
+
if (request.method !== "GET") {
|
|
120354
|
+
response.writeHead(405, {
|
|
120355
|
+
...browserAccessHeaders(origin),
|
|
120356
|
+
Allow: "GET, OPTIONS",
|
|
120357
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
120358
|
+
});
|
|
120359
|
+
response.end("Method not allowed");
|
|
120360
|
+
return;
|
|
120361
|
+
}
|
|
120362
|
+
response.writeHead(200, {
|
|
120363
|
+
...browserAccessHeaders(origin),
|
|
120364
|
+
"Content-Length": String(Buffer.byteLength(STATUS_BODY)),
|
|
120365
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
120366
|
+
});
|
|
120367
|
+
response.end(STATUS_BODY);
|
|
120368
|
+
}
|
|
120369
|
+
function allowedBrowserOrigin(value) {
|
|
120370
|
+
if (!value)
|
|
120371
|
+
return;
|
|
120372
|
+
return ALLOWED_BROWSER_ORIGINS.has(value) || LOCAL_BROWSER_ORIGIN.test(value) ? value : undefined;
|
|
120373
|
+
}
|
|
120374
|
+
function isLoopbackAddress(value) {
|
|
120375
|
+
return value === "127.0.0.1" || value === "::ffff:127.0.0.1";
|
|
120376
|
+
}
|
|
120377
|
+
function browserAccessHeaders(origin) {
|
|
120378
|
+
return {
|
|
120379
|
+
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
|
120380
|
+
...origin ? { "Access-Control-Allow-Origin": origin } : {},
|
|
120381
|
+
"Access-Control-Allow-Private-Network": "true",
|
|
120382
|
+
"Cache-Control": "no-store",
|
|
120383
|
+
Connection: "close",
|
|
120384
|
+
Vary: "Origin, Access-Control-Request-Method, Access-Control-Request-Private-Network"
|
|
120385
|
+
};
|
|
120386
|
+
}
|
|
120387
|
+
function respond(response, statusCode2, body) {
|
|
120388
|
+
response.writeHead(statusCode2, {
|
|
120389
|
+
"Content-Length": String(Buffer.byteLength(body)),
|
|
120390
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
120391
|
+
});
|
|
120392
|
+
response.end(body);
|
|
120393
|
+
}
|
|
120394
|
+
function formatDiscoveryAddress(address) {
|
|
120395
|
+
return {
|
|
120396
|
+
host: BROWSER_DISCOVERY_HOST,
|
|
120397
|
+
port: address.port,
|
|
120398
|
+
url: `http://${BROWSER_DISCOVERY_HOST}:${address.port}${BROWSER_DISCOVERY_PATH}`
|
|
120399
|
+
};
|
|
120400
|
+
}
|
|
120401
|
+
async function closeServer(server2) {
|
|
120402
|
+
server2.closeAllConnections();
|
|
120403
|
+
if (!server2.listening)
|
|
120404
|
+
return;
|
|
120405
|
+
await new Promise((resolve10) => {
|
|
120406
|
+
server2.close(() => resolve10());
|
|
120407
|
+
});
|
|
120408
|
+
}
|
|
120409
|
+
var BROWSER_DISCOVERY_HOST = "127.0.0.1", BROWSER_DISCOVERY_PORT = 32187, BROWSER_DISCOVERY_PATH = "/status", DEFAULT_RETRY_DELAY_MS = 1000, STATUS_BODY, LOCAL_BROWSER_ORIGIN, ALLOWED_BROWSER_ORIGINS;
|
|
120410
|
+
var init_browser_discovery_server = __esm(() => {
|
|
120411
|
+
STATUS_BODY = JSON.stringify({ status: "ok" });
|
|
120412
|
+
LOCAL_BROWSER_ORIGIN = /^https?:\/\/(?:localhost|127\.0\.0\.1)(?::\d+)?$/;
|
|
120413
|
+
ALLOWED_BROWSER_ORIGINS = new Set(["https://chat.letta.com"]);
|
|
120414
|
+
});
|
|
120415
|
+
|
|
120193
120416
|
// src/cli/args.ts
|
|
120194
120417
|
import { parseArgs } from "node:util";
|
|
120195
120418
|
function formatHelpFlagLabel(flagName, definition) {
|
|
@@ -195921,6 +196144,23 @@ Lists files and directories in a given path. The path parameter must be an absol
|
|
|
195921
196144
|
If a directory has more than 1,000 entries, only the first 1,000 will be shown.`;
|
|
195922
196145
|
var init_LS = () => {};
|
|
195923
196146
|
|
|
196147
|
+
// src/tools/descriptions/Memory.md
|
|
196148
|
+
var Memory_default = `Read deferred memory from your memory filesystem.
|
|
196149
|
+
|
|
196150
|
+
Your root memory files are already in your system prompt. Everything else is deferred: the <deferred-memory> section lists directories you have not opened. Use this tool to open them progressively instead of guessing what they contain.
|
|
196151
|
+
|
|
196152
|
+
- Memory("projects") returns projects/MEMORY.md, then the files (<memory_files>) and subdirectories (<deferred-memory>) directly beneath it, with their descriptions.
|
|
196153
|
+
- Memory("projects/code") opens a subdirectory the same way.
|
|
196154
|
+
- Memory("projects/example.md") returns that file.
|
|
196155
|
+
|
|
196156
|
+
Entries are listed most recently edited first, up to 10 per directory.
|
|
196157
|
+
|
|
196158
|
+
Paths are relative to your memory directory. Before acting on a person, project, channel, or topic that your memory index points to, open the matching memory rather than working from assumptions. Open one level at a time and only what the task needs.
|
|
196159
|
+
|
|
196160
|
+
Do not use this tool for root memory files (already loaded) or skills/ (use Skill).
|
|
196161
|
+
`;
|
|
196162
|
+
var init_Memory = () => {};
|
|
196163
|
+
|
|
195924
196164
|
// src/tools/descriptions/Monitor.md
|
|
195925
196165
|
var Monitor_default = 'Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you\'re waiting for the user to answer a question.\n\nPick by how many notifications you need:\n- **One** ("tell me when the server is ready / the build finishes") → use **Bash with `run_in_background`** and a command that exits when the condition is true, e.g. `until grep -q "Ready in" dev.log; do sleep 0.5; done`. You get a single completion notification when it exits.\n- **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") → Monitor with an unbounded command (`tail -f`, `inotifywait -m`, `while true`).\n- **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") → Monitor with a command that emits lines and then exits.\n\nYour script\'s stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered "ERROR"\n # Each file change is an event\n inotifywait -m --format \'%e %f\' /watched/dir\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\nFor open github.com pull requests, use WatchPR instead. It covers the whole PR surface and keeps watching after CI finishes. Use Monitor only when WatchPR does not apply.\n\n**Don\'t use an unbounded command for a single notification.** `tail -f`, `inotifywait -m`, and `while true` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash `run_in_background` with an `until` loop instead (one notification, ends in seconds). Note that `tail -f log | grep -m 1 ...` does *not* fix this: if the log goes quiet after the match, `tail` never receives SIGPIPE and the pipeline hangs anyway.\n\n- Every pipe stage must flush per line or matches sit in its buffer unseen: `grep` needs `--line-buffered`, `awk` needs `fflush()`. `head` cannot flush at all — `| head -N` delivers nothing until N matches accumulate, then ends the stream.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn\'t kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5–1s for local checks.\n- Write a specific `description` — it appears in every notification ("errors in deploy.log" not "watching logs").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered "elapsed_steps="\n # Right — one alternation covering progress + the failure signatures you\'d act on\n tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means "the lines you\'d act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (log tails, long-lived event streams) — the monitor runs until you call TaskStop or the session ends. Use TaskStop to cancel early.\n\n**ws source** — open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.\n ws: {url: \'wss://events.example.com/stream\', protocols: [\'v1\']},\n description: \'deploy events\',\n\nEach text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as `[binary frame, N bytes]` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash — a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.\n\nPrefer this over `command: \'websocat wss://…\'` — it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.\n';
|
|
195926
196166
|
var init_Monitor = () => {};
|
|
@@ -196774,8 +197014,14 @@ function parseUpdateChunk(lines, startIndex, endIndex, allowMissingContext) {
|
|
|
196774
197014
|
}
|
|
196775
197015
|
const oldLines = [];
|
|
196776
197016
|
const newLines = [];
|
|
197017
|
+
const contextLineIndices = [];
|
|
196777
197018
|
let isEndOfFile = false;
|
|
196778
197019
|
let parsedLineCount = 0;
|
|
197020
|
+
const pushContextLine = (text2) => {
|
|
197021
|
+
contextLineIndices.push([oldLines.length, newLines.length]);
|
|
197022
|
+
oldLines.push(text2);
|
|
197023
|
+
newLines.push(text2);
|
|
197024
|
+
};
|
|
196779
197025
|
while (index < endIndex) {
|
|
196780
197026
|
const line = lines[index] ?? "";
|
|
196781
197027
|
if (line === EOF_MARKER) {
|
|
@@ -196788,17 +197034,14 @@ function parseUpdateChunk(lines, startIndex, endIndex, allowMissingContext) {
|
|
|
196788
197034
|
break;
|
|
196789
197035
|
}
|
|
196790
197036
|
if (line.length === 0) {
|
|
196791
|
-
|
|
196792
|
-
newLines.push("");
|
|
197037
|
+
pushContextLine("");
|
|
196793
197038
|
parsedLineCount += 1;
|
|
196794
197039
|
index += 1;
|
|
196795
197040
|
continue;
|
|
196796
197041
|
}
|
|
196797
197042
|
const prefix = line[0];
|
|
196798
197043
|
if (prefix === " ") {
|
|
196799
|
-
|
|
196800
|
-
oldLines.push(text2);
|
|
196801
|
-
newLines.push(text2);
|
|
197044
|
+
pushContextLine(line.slice(1));
|
|
196802
197045
|
parsedLineCount += 1;
|
|
196803
197046
|
index += 1;
|
|
196804
197047
|
continue;
|
|
@@ -196825,6 +197068,7 @@ function parseUpdateChunk(lines, startIndex, endIndex, allowMissingContext) {
|
|
|
196825
197068
|
changeContext,
|
|
196826
197069
|
oldLines,
|
|
196827
197070
|
newLines,
|
|
197071
|
+
contextLineIndices,
|
|
196828
197072
|
isEndOfFile
|
|
196829
197073
|
},
|
|
196830
197074
|
nextIndex: index
|
|
@@ -196898,18 +197142,41 @@ async function deriveNewContentsFromChunks(absolutePath, filePathForErrors, chun
|
|
|
196898
197142
|
const message = error4 instanceof Error ? error4.message : String(error4);
|
|
196899
197143
|
throw new Error(`Failed to read file to update ${filePathForErrors}: ${message}`);
|
|
196900
197144
|
}
|
|
196901
|
-
const
|
|
196902
|
-
|
|
196903
|
-
if (originalLines[originalLines.length - 1] === "") {
|
|
196904
|
-
originalLines.pop();
|
|
196905
|
-
}
|
|
197145
|
+
const sourceFile = parseSourceFile(originalContents);
|
|
197146
|
+
const originalLines = sourceFile.lines.map((line) => line.text);
|
|
196906
197147
|
const replacements = computeReplacements(originalLines, filePathForErrors, chunks);
|
|
196907
|
-
|
|
196908
|
-
|
|
196909
|
-
|
|
197148
|
+
return applyReplacements(sourceFile, replacements).map((line) => `${line.text}${line.ending ?? ""}`).join("");
|
|
197149
|
+
}
|
|
197150
|
+
function parseSourceFile(contents) {
|
|
197151
|
+
const lines = [];
|
|
197152
|
+
let preferredEnding = null;
|
|
197153
|
+
let lineStart = 0;
|
|
197154
|
+
let cursor = 0;
|
|
197155
|
+
while (cursor < contents.length) {
|
|
197156
|
+
const char = contents[cursor];
|
|
197157
|
+
let ending;
|
|
197158
|
+
if (char === "\r") {
|
|
197159
|
+
ending = contents[cursor + 1] === `
|
|
197160
|
+
` ? `\r
|
|
197161
|
+
` : "\r";
|
|
197162
|
+
} else if (char === `
|
|
197163
|
+
`) {
|
|
197164
|
+
ending = `
|
|
197165
|
+
`;
|
|
197166
|
+
} else {
|
|
197167
|
+
cursor += 1;
|
|
197168
|
+
continue;
|
|
197169
|
+
}
|
|
197170
|
+
preferredEnding ??= ending;
|
|
197171
|
+
lines.push({ text: contents.slice(lineStart, cursor), ending });
|
|
197172
|
+
cursor += ending.length;
|
|
197173
|
+
lineStart = cursor;
|
|
196910
197174
|
}
|
|
196911
|
-
|
|
196912
|
-
|
|
197175
|
+
if (lineStart < contents.length) {
|
|
197176
|
+
lines.push({ text: contents.slice(lineStart), ending: null });
|
|
197177
|
+
}
|
|
197178
|
+
return { lines, preferredEnding: preferredEnding ?? `
|
|
197179
|
+
` };
|
|
196913
197180
|
}
|
|
196914
197181
|
function computeReplacements(originalLines, filePathForErrors, chunks) {
|
|
196915
197182
|
const replacements = [];
|
|
@@ -196923,8 +197190,7 @@ function computeReplacements(originalLines, filePathForErrors, chunks) {
|
|
|
196923
197190
|
lineIndex = contextIndex + 1;
|
|
196924
197191
|
}
|
|
196925
197192
|
if (chunk2.oldLines.length === 0) {
|
|
196926
|
-
|
|
196927
|
-
replacements.push([insertionIndex, 0, [...chunk2.newLines]]);
|
|
197193
|
+
replacements.push([originalLines.length, 0, [...chunk2.newLines]]);
|
|
196928
197194
|
continue;
|
|
196929
197195
|
}
|
|
196930
197196
|
let pattern4 = [...chunk2.oldLines];
|
|
@@ -196942,23 +197208,47 @@ function computeReplacements(originalLines, filePathForErrors, chunks) {
|
|
|
196942
197208
|
${chunk2.oldLines.join(`
|
|
196943
197209
|
`)}`);
|
|
196944
197210
|
}
|
|
196945
|
-
|
|
197211
|
+
let oldStart = 0;
|
|
197212
|
+
let newStart = 0;
|
|
197213
|
+
for (const [oldContext, newContext] of chunk2.contextLineIndices) {
|
|
197214
|
+
if (oldContext >= pattern4.length || newContext >= newSlice.length) {
|
|
197215
|
+
break;
|
|
197216
|
+
}
|
|
197217
|
+
if (oldStart !== oldContext || newStart !== newContext) {
|
|
197218
|
+
replacements.push([
|
|
197219
|
+
found + oldStart,
|
|
197220
|
+
oldContext - oldStart,
|
|
197221
|
+
newSlice.slice(newStart, newContext)
|
|
197222
|
+
]);
|
|
197223
|
+
}
|
|
197224
|
+
oldStart = oldContext + 1;
|
|
197225
|
+
newStart = newContext + 1;
|
|
197226
|
+
}
|
|
197227
|
+
if (oldStart !== pattern4.length || newStart !== newSlice.length) {
|
|
197228
|
+
replacements.push([
|
|
197229
|
+
found + oldStart,
|
|
197230
|
+
pattern4.length - oldStart,
|
|
197231
|
+
newSlice.slice(newStart)
|
|
197232
|
+
]);
|
|
197233
|
+
}
|
|
196946
197234
|
lineIndex = found + pattern4.length;
|
|
196947
197235
|
}
|
|
196948
197236
|
replacements.sort((left, right) => left[0] - right[0]);
|
|
196949
197237
|
return replacements;
|
|
196950
197238
|
}
|
|
196951
|
-
function applyReplacements(lines, replacements) {
|
|
196952
|
-
|
|
196953
|
-
|
|
196954
|
-
|
|
196955
|
-
|
|
196956
|
-
|
|
196957
|
-
|
|
196958
|
-
|
|
196959
|
-
|
|
196960
|
-
|
|
196961
|
-
|
|
197239
|
+
function applyReplacements({ lines, preferredEnding }, replacements) {
|
|
197240
|
+
const newLines = [];
|
|
197241
|
+
let sourceIndex = 0;
|
|
197242
|
+
for (const [startIndex, oldLength, newSegment] of replacements) {
|
|
197243
|
+
newLines.push(...lines.slice(sourceIndex, startIndex));
|
|
197244
|
+
newLines.push(...newSegment.map((text2) => ({ text: text2, ending: preferredEnding })));
|
|
197245
|
+
sourceIndex = startIndex + oldLength;
|
|
197246
|
+
}
|
|
197247
|
+
newLines.push(...lines.slice(sourceIndex));
|
|
197248
|
+
return newLines.map((line) => ({
|
|
197249
|
+
text: line.text,
|
|
197250
|
+
ending: line.ending ?? preferredEnding
|
|
197251
|
+
}));
|
|
196962
197252
|
}
|
|
196963
197253
|
function seekSequence(lines, pattern4, start, eof) {
|
|
196964
197254
|
if (pattern4.length === 0) {
|
|
@@ -196968,7 +197258,7 @@ function seekSequence(lines, pattern4, start, eof) {
|
|
|
196968
197258
|
return null;
|
|
196969
197259
|
}
|
|
196970
197260
|
const maxStart = lines.length - pattern4.length;
|
|
196971
|
-
const searchStart = eof && lines.length >= pattern4.length ? lines.length - pattern4.length : start;
|
|
197261
|
+
const searchStart = eof && lines.length >= pattern4.length ? Math.max(lines.length - pattern4.length, start) : start;
|
|
196972
197262
|
const tryMatch = (matches3) => {
|
|
196973
197263
|
for (let index = searchStart;index <= maxStart; index += 1) {
|
|
196974
197264
|
let ok = true;
|
|
@@ -201222,6 +201512,7 @@ var init_truncation = __esm(() => {
|
|
|
201222
201512
|
GREP_OUTPUT_CHARS: 1e4,
|
|
201223
201513
|
GLOB_MAX_FILES: 2000,
|
|
201224
201514
|
LS_MAX_ENTRIES: 1000,
|
|
201515
|
+
MEMORY_MAX_ENTRIES: 10,
|
|
201225
201516
|
TOOL_RETURN_MAX_CHARS: 32000
|
|
201226
201517
|
};
|
|
201227
201518
|
});
|
|
@@ -204618,6 +204909,7 @@ var init_approval_execution = __esm(async () => {
|
|
|
204618
204909
|
"Read",
|
|
204619
204910
|
"ViewImage",
|
|
204620
204911
|
"Grep",
|
|
204912
|
+
"Memory",
|
|
204621
204913
|
"Glob",
|
|
204622
204914
|
"conversation_search",
|
|
204623
204915
|
"web_search",
|
|
@@ -206478,6 +206770,290 @@ var init_tool_name_mapping = __esm(() => {
|
|
|
206478
206770
|
};
|
|
206479
206771
|
});
|
|
206480
206772
|
|
|
206773
|
+
// src/tools/impl/memory.ts
|
|
206774
|
+
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
206775
|
+
import {
|
|
206776
|
+
closeSync as closeSync5,
|
|
206777
|
+
existsSync as existsSync39,
|
|
206778
|
+
openSync as openSync5,
|
|
206779
|
+
readdirSync as readdirSync13,
|
|
206780
|
+
readFileSync as readFileSync32,
|
|
206781
|
+
readSync as readSync3,
|
|
206782
|
+
realpathSync as realpathSync6,
|
|
206783
|
+
statSync as statSync14
|
|
206784
|
+
} from "node:fs";
|
|
206785
|
+
import { extname as extname8, join as join51, sep as sep5 } from "node:path";
|
|
206786
|
+
function resolveMemoryToolDirectory(agentId) {
|
|
206787
|
+
try {
|
|
206788
|
+
const id2 = agentId === undefined ? getCurrentAgentId() : agentId;
|
|
206789
|
+
const memoryDir = id2 ? getActiveMemoryDirectory(id2) : undefined;
|
|
206790
|
+
return memoryDir && detectMemoryFormat(memoryDir, false) === "memfs-v2" ? memoryDir : null;
|
|
206791
|
+
} catch {
|
|
206792
|
+
return null;
|
|
206793
|
+
}
|
|
206794
|
+
}
|
|
206795
|
+
function readDescription(path19) {
|
|
206796
|
+
try {
|
|
206797
|
+
const value = parseFrontmatter(readFileSync32(path19, "utf8")).frontmatter.description;
|
|
206798
|
+
return typeof value === "string" ? value.trim() || undefined : undefined;
|
|
206799
|
+
} catch {
|
|
206800
|
+
return;
|
|
206801
|
+
}
|
|
206802
|
+
}
|
|
206803
|
+
function readIndexDescription(path19) {
|
|
206804
|
+
const fromFrontmatter = readDescription(path19);
|
|
206805
|
+
if (fromFrontmatter)
|
|
206806
|
+
return fromFrontmatter;
|
|
206807
|
+
try {
|
|
206808
|
+
const { body: body3 } = parseFrontmatter(readFileSync32(path19, "utf8"));
|
|
206809
|
+
for (const block of body3.split(/\n\s*\n/)) {
|
|
206810
|
+
const text2 = block.trim();
|
|
206811
|
+
if (!text2 || /^(#|[-*+] |\d+\. |\||```|<)/.test(text2))
|
|
206812
|
+
continue;
|
|
206813
|
+
const paragraph = text2.replace(/\s*\n\s*/g, " ").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1");
|
|
206814
|
+
return paragraph.length > 300 ? `${paragraph.slice(0, 297)}...` : paragraph;
|
|
206815
|
+
}
|
|
206816
|
+
} catch {}
|
|
206817
|
+
return;
|
|
206818
|
+
}
|
|
206819
|
+
function isHidden2(name) {
|
|
206820
|
+
return name.startsWith(".");
|
|
206821
|
+
}
|
|
206822
|
+
function findByBasename(dir, name, root2 = dir, found = []) {
|
|
206823
|
+
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
206824
|
+
if (found.length >= 5)
|
|
206825
|
+
break;
|
|
206826
|
+
if (isHidden2(entry.name) || dir === root2 && entry.name === "skills") {
|
|
206827
|
+
continue;
|
|
206828
|
+
}
|
|
206829
|
+
const path19 = join51(dir, entry.name);
|
|
206830
|
+
if (entry.isDirectory())
|
|
206831
|
+
findByBasename(path19, name, root2, found);
|
|
206832
|
+
else if (entry.isFile() && entry.name === name && dir !== root2) {
|
|
206833
|
+
found.push(path19.slice(root2.length + 1).split(sep5).join("/"));
|
|
206834
|
+
}
|
|
206835
|
+
}
|
|
206836
|
+
return found;
|
|
206837
|
+
}
|
|
206838
|
+
function escapeXmlText2(value) {
|
|
206839
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
206840
|
+
}
|
|
206841
|
+
function descriptionAttr(description) {
|
|
206842
|
+
return description ? ` description="${escapeXmlText2(description).replace(/"/g, """)}"` : "";
|
|
206843
|
+
}
|
|
206844
|
+
function clampContent(content, fullPath, maxChars) {
|
|
206845
|
+
const lines = content.split(`
|
|
206846
|
+
`);
|
|
206847
|
+
const shown = lines.slice(0, LIMITS.READ_MAX_LINES);
|
|
206848
|
+
let longLines = false;
|
|
206849
|
+
let result2 = shown.map((line) => {
|
|
206850
|
+
if (line.length <= LIMITS.READ_MAX_CHARS_PER_LINE)
|
|
206851
|
+
return line;
|
|
206852
|
+
longLines = true;
|
|
206853
|
+
return `${line.slice(0, LIMITS.READ_MAX_CHARS_PER_LINE)}... [line truncated]`;
|
|
206854
|
+
}).join(`
|
|
206855
|
+
`);
|
|
206856
|
+
const byTotal = result2.length > maxChars;
|
|
206857
|
+
if (byTotal)
|
|
206858
|
+
result2 = truncateByChars(result2, maxChars, "Memory").content;
|
|
206859
|
+
const byLines = shown.length < lines.length;
|
|
206860
|
+
const notices = [];
|
|
206861
|
+
if (byLines) {
|
|
206862
|
+
notices.push(`[File truncated: showing lines 1-${shown.length} of ${lines.length} total lines. Use Read with offset and limit on the full file to read other sections.]`);
|
|
206863
|
+
}
|
|
206864
|
+
if (longLines) {
|
|
206865
|
+
notices.push(`[Some lines exceeded ${LIMITS.READ_MAX_CHARS_PER_LINE.toLocaleString()} characters and were truncated.]`);
|
|
206866
|
+
}
|
|
206867
|
+
if (byTotal) {
|
|
206868
|
+
notices.push("[Use Read with offset and limit on the full file to read it in smaller sections.]");
|
|
206869
|
+
}
|
|
206870
|
+
if (notices.length)
|
|
206871
|
+
notices.push(`[Full file: ${fullPath}]`);
|
|
206872
|
+
return notices.length ? `${result2}
|
|
206873
|
+
|
|
206874
|
+
${notices.join(`
|
|
206875
|
+
|
|
206876
|
+
`)}` : result2;
|
|
206877
|
+
}
|
|
206878
|
+
function lastEditedByChild(dir, names2) {
|
|
206879
|
+
const edited = new Map;
|
|
206880
|
+
const bump = (name, time) => {
|
|
206881
|
+
if (time > (edited.get(name) ?? 0))
|
|
206882
|
+
edited.set(name, time);
|
|
206883
|
+
};
|
|
206884
|
+
const git = (args) => execFileSync9("git", ["-C", dir, ...args], {
|
|
206885
|
+
encoding: "utf8",
|
|
206886
|
+
timeout: 5000,
|
|
206887
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
206888
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
206889
|
+
});
|
|
206890
|
+
const walkMtime = (path19, name) => {
|
|
206891
|
+
try {
|
|
206892
|
+
const stat6 = statSync14(path19);
|
|
206893
|
+
if (stat6.isFile())
|
|
206894
|
+
return bump(name, stat6.mtimeMs);
|
|
206895
|
+
if (!stat6.isDirectory())
|
|
206896
|
+
return;
|
|
206897
|
+
for (const entry of readdirSync13(path19, { withFileTypes: true })) {
|
|
206898
|
+
if (!isHidden2(entry.name))
|
|
206899
|
+
walkMtime(join51(path19, entry.name), name);
|
|
206900
|
+
}
|
|
206901
|
+
} catch {}
|
|
206902
|
+
};
|
|
206903
|
+
let dirty;
|
|
206904
|
+
try {
|
|
206905
|
+
let commitTime = 0;
|
|
206906
|
+
for (const line of git([
|
|
206907
|
+
"log",
|
|
206908
|
+
"--format=%x00%ct",
|
|
206909
|
+
"--name-only",
|
|
206910
|
+
"--relative",
|
|
206911
|
+
"--",
|
|
206912
|
+
"."
|
|
206913
|
+
]).split(`
|
|
206914
|
+
`)) {
|
|
206915
|
+
const child = line.split("/")[0] ?? line;
|
|
206916
|
+
if (line.startsWith("\x00"))
|
|
206917
|
+
commitTime = Number(line.slice(1)) * 1000;
|
|
206918
|
+
else if (line && !edited.has(child))
|
|
206919
|
+
edited.set(child, commitTime);
|
|
206920
|
+
}
|
|
206921
|
+
const prefix = git(["rev-parse", "--show-prefix"]).trim();
|
|
206922
|
+
dirty = git([
|
|
206923
|
+
"status",
|
|
206924
|
+
"--porcelain=v1",
|
|
206925
|
+
"-z",
|
|
206926
|
+
"--untracked-files=all",
|
|
206927
|
+
"--",
|
|
206928
|
+
"."
|
|
206929
|
+
]).split("\x00").filter((record4) => record4.length > 3).map((record4) => record4.slice(3)).filter((path19) => path19.startsWith(prefix)).map((path19) => path19.slice(prefix.length));
|
|
206930
|
+
} catch {
|
|
206931
|
+
edited.clear();
|
|
206932
|
+
dirty = names2;
|
|
206933
|
+
}
|
|
206934
|
+
for (const path19 of dirty)
|
|
206935
|
+
walkMtime(join51(dir, path19), path19.split("/")[0] ?? path19);
|
|
206936
|
+
return edited;
|
|
206937
|
+
}
|
|
206938
|
+
function renderDirectory(memoryDir, relPath, fullPath) {
|
|
206939
|
+
const entries = readdirSync13(fullPath, { withFileTypes: true }).filter((entry) => !isHidden2(entry.name) && (entry.isDirectory() || entry.isFile() && entry.name !== INDEX));
|
|
206940
|
+
const edited = lastEditedByChild(fullPath, entries.map((entry) => entry.name));
|
|
206941
|
+
const shown = entries.sort((a2, b3) => (edited.get(b3.name) ?? 0) - (edited.get(a2.name) ?? 0) || a2.name.localeCompare(b3.name)).slice(0, LIMITS.MEMORY_MAX_ENTRIES);
|
|
206942
|
+
const fileLines = shown.filter((entry) => entry.isFile()).map((entry) => {
|
|
206943
|
+
const description = extname8(entry.name) === ".md" ? readDescription(join51(fullPath, entry.name)) : undefined;
|
|
206944
|
+
return ` <file${descriptionAttr(description)}>${escapeXmlText2(`${relPath}/${entry.name}`)}</file>`;
|
|
206945
|
+
});
|
|
206946
|
+
const dirLines = shown.filter((entry) => entry.isDirectory()).map((entry) => {
|
|
206947
|
+
const description = readIndexDescription(join51(fullPath, entry.name, INDEX));
|
|
206948
|
+
return ` <directory${descriptionAttr(description)}>${escapeXmlText2(`${relPath}/${entry.name}`)}</directory>`;
|
|
206949
|
+
});
|
|
206950
|
+
const tail2 = [
|
|
206951
|
+
`Memory directory: ${memoryDir}`,
|
|
206952
|
+
"Paths in this memory are relative to the memory directory."
|
|
206953
|
+
];
|
|
206954
|
+
if (fileLines.length) {
|
|
206955
|
+
tail2.push("", "<memory_files>", ...fileLines, "</memory_files>");
|
|
206956
|
+
}
|
|
206957
|
+
if (dirLines.length) {
|
|
206958
|
+
tail2.push("", "<deferred-memory>", ...dirLines, "</deferred-memory>");
|
|
206959
|
+
}
|
|
206960
|
+
if (entries.length > LIMITS.MEMORY_MAX_ENTRIES) {
|
|
206961
|
+
tail2.push(`[Output truncated: showing ${LIMITS.MEMORY_MAX_ENTRIES.toLocaleString()} of ${entries.length.toLocaleString()} entries.]`, `[Full listing: ${fullPath}]`);
|
|
206962
|
+
}
|
|
206963
|
+
const tailText = tail2.join(`
|
|
206964
|
+
`);
|
|
206965
|
+
const indexPath = join51(fullPath, INDEX);
|
|
206966
|
+
const open4 = `<memory_content path="${escapeXmlText2(relPath).replace(/"/g, """)}">`;
|
|
206967
|
+
const close = "</memory_content>";
|
|
206968
|
+
let head4;
|
|
206969
|
+
if (existsSync39(indexPath)) {
|
|
206970
|
+
const budget = Math.max(2000, LIMITS.READ_OUTPUT_CHARS - tailText.length - open4.length - close.length - 16);
|
|
206971
|
+
head4 = clampContent(readFileSync32(indexPath, "utf8").trimEnd(), indexPath, budget);
|
|
206972
|
+
} else {
|
|
206973
|
+
head4 = `<note>No ${INDEX} index in this directory.</note>`;
|
|
206974
|
+
}
|
|
206975
|
+
return `${open4}
|
|
206976
|
+
${head4}
|
|
206977
|
+
|
|
206978
|
+
${tailText}
|
|
206979
|
+
${close}`;
|
|
206980
|
+
}
|
|
206981
|
+
function readPrefix(path19, bytes) {
|
|
206982
|
+
const fd = openSync5(path19, "r");
|
|
206983
|
+
try {
|
|
206984
|
+
const buffer = Buffer.alloc(bytes);
|
|
206985
|
+
return buffer.subarray(0, readSync3(fd, buffer, 0, bytes, 0));
|
|
206986
|
+
} finally {
|
|
206987
|
+
closeSync5(fd);
|
|
206988
|
+
}
|
|
206989
|
+
}
|
|
206990
|
+
function renderFile(relPath, fullPath) {
|
|
206991
|
+
const content = readFileSync32(fullPath, "utf8").trimEnd();
|
|
206992
|
+
const open4 = `<memory_content path="${escapeXmlText2(relPath).replace(/"/g, """)}"${descriptionAttr(readDescription(fullPath))}>`;
|
|
206993
|
+
const close = "</memory_content>";
|
|
206994
|
+
return `${open4}
|
|
206995
|
+
${clampContent(content, fullPath, LIMITS.READ_OUTPUT_CHARS - open4.length - close.length - 2)}
|
|
206996
|
+
${close}`;
|
|
206997
|
+
}
|
|
206998
|
+
async function memory2(args) {
|
|
206999
|
+
validateRequiredParams(args, ["path"], "Memory");
|
|
207000
|
+
const memoryDir = resolveMemoryToolDirectory();
|
|
207001
|
+
if (!memoryDir) {
|
|
207002
|
+
throw new Error("Memory() is only available for agents with a MemFS v2 memory directory.");
|
|
207003
|
+
}
|
|
207004
|
+
const raw2 = String(args.path).trim();
|
|
207005
|
+
const relPath = raw2.replace(/\\/g, "/").replace(/^(\.\/)+/, "").replace(/\/+$/, "");
|
|
207006
|
+
if (!relPath || relPath === "." || relPath === INDEX) {
|
|
207007
|
+
throw new Error("The memory root is already in your context. Pass a directory from <deferred-memory>.");
|
|
207008
|
+
}
|
|
207009
|
+
if (raw2.startsWith("/") || /^[A-Za-z]:/.test(raw2)) {
|
|
207010
|
+
throw new Error('Paths are relative to the memory directory, e.g. "projects".');
|
|
207011
|
+
}
|
|
207012
|
+
const segments = relPath.split("/");
|
|
207013
|
+
if (segments.some((s3) => s3 === ".." || s3 === "" || isHidden2(s3))) {
|
|
207014
|
+
throw new Error(`Invalid memory path: ${raw2}`);
|
|
207015
|
+
}
|
|
207016
|
+
if (segments[0] === "skills") {
|
|
207017
|
+
throw new Error(`skills/ is reserved for skills. Use Skill("${segments[1] ?? "<name>"}").`);
|
|
207018
|
+
}
|
|
207019
|
+
const fullPath = join51(memoryDir, ...segments);
|
|
207020
|
+
if (!existsSync39(fullPath)) {
|
|
207021
|
+
const candidates2 = !relPath.endsWith(".md") && existsSync39(`${fullPath}.md`) ? [`${relPath}.md`] : findByBasename(memoryDir, segments[segments.length - 1] ?? relPath);
|
|
207022
|
+
const hint = candidates2.length ? ` Did you mean ${candidates2.join(" or ")}? Paths are relative to the memory directory.` : "";
|
|
207023
|
+
throw new Error(`No memory at ${relPath}.${hint}`);
|
|
207024
|
+
}
|
|
207025
|
+
const realRoot = realpathSync6(memoryDir);
|
|
207026
|
+
const realTarget = realpathSync6(fullPath);
|
|
207027
|
+
if (realTarget !== realRoot && !realTarget.startsWith(realRoot + sep5)) {
|
|
207028
|
+
throw new Error(`Invalid memory path: ${raw2}`);
|
|
207029
|
+
}
|
|
207030
|
+
const stat6 = statSync14(fullPath);
|
|
207031
|
+
if (segments.length === 1 && stat6.isFile()) {
|
|
207032
|
+
throw new Error(`${relPath} is root core memory and is already in your context.`);
|
|
207033
|
+
}
|
|
207034
|
+
if (stat6.isDirectory()) {
|
|
207035
|
+
return { content: renderDirectory(memoryDir, relPath, fullPath) };
|
|
207036
|
+
}
|
|
207037
|
+
if (!stat6.isFile()) {
|
|
207038
|
+
throw new Error(`Not a memory file or directory: ${relPath}`);
|
|
207039
|
+
}
|
|
207040
|
+
if (stat6.size > MAX_FILE_BYTES) {
|
|
207041
|
+
throw new Error(`${relPath} is too large: ${stat6.size} bytes (max ${MAX_FILE_BYTES} bytes).`);
|
|
207042
|
+
}
|
|
207043
|
+
if (readPrefix(fullPath, 8000).includes(0)) {
|
|
207044
|
+
throw new Error(`${relPath} is not a text file. Use Read on ${fullPath} instead.`);
|
|
207045
|
+
}
|
|
207046
|
+
return { content: renderFile(relPath, fullPath) };
|
|
207047
|
+
}
|
|
207048
|
+
var INDEX = "MEMORY.md", MAX_FILE_BYTES;
|
|
207049
|
+
var init_memory5 = __esm(() => {
|
|
207050
|
+
init_context();
|
|
207051
|
+
init_memory_format();
|
|
207052
|
+
init_memory_runtime();
|
|
207053
|
+
init_truncation();
|
|
207054
|
+
MAX_FILE_BYTES = 10 * 1024 * 1024;
|
|
207055
|
+
});
|
|
207056
|
+
|
|
206481
207057
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
206482
207058
|
var balanced = (a2, b3, str) => {
|
|
206483
207059
|
const ma = a2 instanceof RegExp ? maybeMatch(a2, str) : a2;
|
|
@@ -207799,7 +208375,7 @@ var minimatch = (p2, pattern4, options = {}) => {
|
|
|
207799
208375
|
}, qmarksTestNoExtDot = ([$0]) => {
|
|
207800
208376
|
const len = $0.length;
|
|
207801
208377
|
return (f4) => f4.length === len && f4 !== "." && f4 !== "..";
|
|
207802
|
-
}, defaultPlatform, path19,
|
|
208378
|
+
}, defaultPlatform, path19, sep6, GLOBSTAR, qmark2 = "[^/]", star2, twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?", twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?", filter2 = (pattern4, options = {}) => (p2) => minimatch(p2, pattern4, options), ext = (a2, b3 = {}) => Object.assign({}, a2, b3), defaults5 = (def) => {
|
|
207803
208379
|
if (!def || typeof def !== "object" || !Object.keys(def).length) {
|
|
207804
208380
|
return minimatch;
|
|
207805
208381
|
}
|
|
@@ -207861,8 +208437,8 @@ var init_esm3 = __esm(() => {
|
|
|
207861
208437
|
win32: { sep: "\\" },
|
|
207862
208438
|
posix: { sep: "/" }
|
|
207863
208439
|
};
|
|
207864
|
-
|
|
207865
|
-
minimatch.sep =
|
|
208440
|
+
sep6 = defaultPlatform === "win32" ? path19.win32.sep : path19.posix.sep;
|
|
208441
|
+
minimatch.sep = sep6;
|
|
207866
208442
|
GLOBSTAR = Symbol("globstar **");
|
|
207867
208443
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
207868
208444
|
star2 = qmark2 + "*?";
|
|
@@ -209753,6 +210329,16 @@ function checkPermissionForEngine(engine4, toolName2, toolArgs, permissions, wor
|
|
|
209753
210329
|
trace
|
|
209754
210330
|
};
|
|
209755
210331
|
}
|
|
210332
|
+
if (toolName2 === "Memory" && !isStrictMode) {
|
|
210333
|
+
traceEvent(trace, "memory-auto-allow", "Memory tool is always allowed");
|
|
210334
|
+
return {
|
|
210335
|
+
result: {
|
|
210336
|
+
decision: "allow",
|
|
210337
|
+
reason: "Memory tool is always allowed (reads own memory)"
|
|
210338
|
+
},
|
|
210339
|
+
trace
|
|
210340
|
+
};
|
|
210341
|
+
}
|
|
209756
210342
|
if (!isStrictMode && isShellToolName(canonicalTool)) {
|
|
209757
210343
|
const shellCommand = extractShellCommand(toolArgs);
|
|
209758
210344
|
if (shellCommand && isReadOnlyShellCommand(shellCommand, {
|
|
@@ -210068,15 +210654,15 @@ __export(exports_loader, {
|
|
|
210068
210654
|
getUserSettingsPaths: () => getUserSettingsPaths
|
|
210069
210655
|
});
|
|
210070
210656
|
import { createHash as createHash4 } from "node:crypto";
|
|
210071
|
-
import { readFileSync as
|
|
210657
|
+
import { readFileSync as readFileSync33, statSync as statSync15, watch } from "node:fs";
|
|
210072
210658
|
import { homedir as homedir26 } from "node:os";
|
|
210073
|
-
import { dirname as dirname21, join as
|
|
210659
|
+
import { dirname as dirname21, join as join52, resolve as resolve25 } from "node:path";
|
|
210074
210660
|
function getUserSettingsPaths(options = {}) {
|
|
210075
210661
|
const homeDir = options.homeDir || homedir26();
|
|
210076
|
-
const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME ||
|
|
210662
|
+
const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME || join52(homeDir, ".config");
|
|
210077
210663
|
return {
|
|
210078
|
-
canonical:
|
|
210079
|
-
legacy:
|
|
210664
|
+
canonical: join52(homeDir, ".letta", "settings.json"),
|
|
210665
|
+
legacy: join52(xdgConfigHome, "letta", "settings.json")
|
|
210080
210666
|
};
|
|
210081
210667
|
}
|
|
210082
210668
|
function getPermissionSourcePaths(workingDirectory) {
|
|
@@ -210084,13 +210670,13 @@ function getPermissionSourcePaths(workingDirectory) {
|
|
|
210084
210670
|
return [
|
|
210085
210671
|
legacyUserSettingsPath,
|
|
210086
210672
|
userSettingsPath,
|
|
210087
|
-
|
|
210088
|
-
|
|
210673
|
+
join52(workingDirectory, ".letta", "settings.json"),
|
|
210674
|
+
join52(workingDirectory, ".letta", "settings.local.json")
|
|
210089
210675
|
];
|
|
210090
210676
|
}
|
|
210091
210677
|
function getFileSignature(path20) {
|
|
210092
210678
|
try {
|
|
210093
|
-
const stat6 =
|
|
210679
|
+
const stat6 = statSync15(path20);
|
|
210094
210680
|
if (!stat6.isFile()) {
|
|
210095
210681
|
return { exists: false };
|
|
210096
210682
|
}
|
|
@@ -210098,7 +210684,7 @@ function getFileSignature(path20) {
|
|
|
210098
210684
|
exists: true,
|
|
210099
210685
|
mtimeMs: stat6.mtimeMs,
|
|
210100
210686
|
size: stat6.size,
|
|
210101
|
-
hash: createHash4("sha256").update(
|
|
210687
|
+
hash: createHash4("sha256").update(readFileSync33(path20)).digest("hex")
|
|
210102
210688
|
};
|
|
210103
210689
|
} catch {
|
|
210104
210690
|
return { exists: false };
|
|
@@ -210279,10 +210865,10 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
|
|
|
210279
210865
|
settingsPath = getUserSettingsPaths().canonical;
|
|
210280
210866
|
break;
|
|
210281
210867
|
case "project":
|
|
210282
|
-
settingsPath =
|
|
210868
|
+
settingsPath = join52(normalizedWorkingDirectory, ".letta", "settings.json");
|
|
210283
210869
|
break;
|
|
210284
210870
|
case "local":
|
|
210285
|
-
settingsPath =
|
|
210871
|
+
settingsPath = join52(normalizedWorkingDirectory, ".letta", "settings.local.json");
|
|
210286
210872
|
break;
|
|
210287
210873
|
}
|
|
210288
210874
|
let settings3 = {};
|
|
@@ -210309,7 +210895,7 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
|
|
|
210309
210895
|
}
|
|
210310
210896
|
}
|
|
210311
210897
|
async function ensureLocalSettingsIgnored(workingDirectory) {
|
|
210312
|
-
const gitignorePath =
|
|
210898
|
+
const gitignorePath = join52(workingDirectory, ".gitignore");
|
|
210313
210899
|
const pattern4 = ".letta/settings.local.json";
|
|
210314
210900
|
try {
|
|
210315
210901
|
let content = "";
|
|
@@ -211262,19 +211848,19 @@ var init_approval_result_normalization = __esm(() => {
|
|
|
211262
211848
|
|
|
211263
211849
|
// src/agent/client-skills-watcher.ts
|
|
211264
211850
|
import {
|
|
211265
|
-
existsSync as
|
|
211266
|
-
readdirSync as
|
|
211267
|
-
realpathSync as
|
|
211268
|
-
statSync as
|
|
211851
|
+
existsSync as existsSync40,
|
|
211852
|
+
readdirSync as readdirSync14,
|
|
211853
|
+
realpathSync as realpathSync7,
|
|
211854
|
+
statSync as statSync16,
|
|
211269
211855
|
watch as watch2
|
|
211270
211856
|
} from "node:fs";
|
|
211271
|
-
import { dirname as dirname23, relative as relative6, resolve as resolve27, sep as
|
|
211857
|
+
import { dirname as dirname23, relative as relative6, resolve as resolve27, sep as sep7 } from "node:path";
|
|
211272
211858
|
function defaultWatchFunction(path20, options, listener) {
|
|
211273
211859
|
return watch2(path20, options, listener);
|
|
211274
211860
|
}
|
|
211275
211861
|
function isDirectory(path20) {
|
|
211276
211862
|
try {
|
|
211277
|
-
return
|
|
211863
|
+
return statSync16(path20).isDirectory();
|
|
211278
211864
|
} catch {
|
|
211279
211865
|
return false;
|
|
211280
211866
|
}
|
|
@@ -211293,7 +211879,7 @@ function findNearestExistingDirectory(path20) {
|
|
|
211293
211879
|
function collectSymlinkDirectoryTargets(path20, targets, visited2) {
|
|
211294
211880
|
let realPath;
|
|
211295
211881
|
try {
|
|
211296
|
-
realPath =
|
|
211882
|
+
realPath = realpathSync7(path20);
|
|
211297
211883
|
} catch {
|
|
211298
211884
|
return;
|
|
211299
211885
|
}
|
|
@@ -211302,7 +211888,7 @@ function collectSymlinkDirectoryTargets(path20, targets, visited2) {
|
|
|
211302
211888
|
}
|
|
211303
211889
|
visited2.add(realPath);
|
|
211304
211890
|
try {
|
|
211305
|
-
const entries =
|
|
211891
|
+
const entries = readdirSync14(path20, {
|
|
211306
211892
|
encoding: "utf8",
|
|
211307
211893
|
withFileTypes: true
|
|
211308
211894
|
});
|
|
@@ -211313,7 +211899,7 @@ function collectSymlinkDirectoryTargets(path20, targets, visited2) {
|
|
|
211313
211899
|
continue;
|
|
211314
211900
|
}
|
|
211315
211901
|
try {
|
|
211316
|
-
targets.add(
|
|
211902
|
+
targets.add(realpathSync7(entryPath));
|
|
211317
211903
|
} catch {
|
|
211318
211904
|
continue;
|
|
211319
211905
|
}
|
|
@@ -211362,13 +211948,13 @@ class ClientSkillsWatcher {
|
|
|
211362
211948
|
const watchPaths = new Set;
|
|
211363
211949
|
let recursive = false;
|
|
211364
211950
|
let awaitedChild = null;
|
|
211365
|
-
if (
|
|
211951
|
+
if (existsSync40(root2)) {
|
|
211366
211952
|
recursive = true;
|
|
211367
211953
|
watchPaths.add(root2);
|
|
211368
211954
|
collectSymlinkDirectoryTargets(root2, watchPaths, new Set);
|
|
211369
211955
|
} else {
|
|
211370
211956
|
watchPaths.add(existingDirectory);
|
|
211371
|
-
awaitedChild = relative6(existingDirectory, root2).split(
|
|
211957
|
+
awaitedChild = relative6(existingDirectory, root2).split(sep7)[0] ?? null;
|
|
211372
211958
|
}
|
|
211373
211959
|
const watchers2 = [];
|
|
211374
211960
|
const invalidate = () => {
|
|
@@ -211415,16 +212001,16 @@ __export(exports_skills2, {
|
|
|
211415
212001
|
PROJECT_SKILLS_DIR: () => PROJECT_SKILLS_DIR,
|
|
211416
212002
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR
|
|
211417
212003
|
});
|
|
211418
|
-
import { existsSync as
|
|
212004
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
211419
212005
|
import { readdir as readdir4, readFile as readFile12, realpath as realpath3, stat as stat6 } from "node:fs/promises";
|
|
211420
|
-
import { dirname as dirname24, join as
|
|
212006
|
+
import { dirname as dirname24, join as join53 } from "node:path";
|
|
211421
212007
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
211422
212008
|
function getBundledSkillsPath() {
|
|
211423
212009
|
const thisDir = dirname24(fileURLToPath6(import.meta.url));
|
|
211424
212010
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
211425
|
-
return
|
|
212011
|
+
return join53(thisDir, "../skills/builtin");
|
|
211426
212012
|
}
|
|
211427
|
-
return
|
|
212013
|
+
return join53(thisDir, "skills");
|
|
211428
212014
|
}
|
|
211429
212015
|
function compareSkills(a2, b3) {
|
|
211430
212016
|
return a2.id.localeCompare(b3.id) || a2.source.localeCompare(b3.source) || a2.path.localeCompare(b3.path);
|
|
@@ -211471,7 +212057,7 @@ function isSkillAvailableForAgent(skill, agentId) {
|
|
|
211471
212057
|
return true;
|
|
211472
212058
|
}
|
|
211473
212059
|
function getAgentSkillsDir(agentId) {
|
|
211474
|
-
return
|
|
212060
|
+
return join53(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
211475
212061
|
}
|
|
211476
212062
|
async function getBundledSkills() {
|
|
211477
212063
|
const bundledPath = getBundledSkillsPath();
|
|
@@ -211480,7 +212066,7 @@ async function getBundledSkills() {
|
|
|
211480
212066
|
}
|
|
211481
212067
|
async function discoverSkillsFromDir(skillsPath, source) {
|
|
211482
212068
|
const errors4 = [];
|
|
211483
|
-
if (!
|
|
212069
|
+
if (!existsSync41(skillsPath)) {
|
|
211484
212070
|
return { skills: [], errors: [] };
|
|
211485
212071
|
}
|
|
211486
212072
|
const skills = [];
|
|
@@ -211494,7 +212080,7 @@ async function discoverSkillsFromDir(skillsPath, source) {
|
|
|
211494
212080
|
}
|
|
211495
212081
|
return { skills, errors: errors4 };
|
|
211496
212082
|
}
|
|
211497
|
-
async function discoverSkills(projectSkillsPath =
|
|
212083
|
+
async function discoverSkills(projectSkillsPath = join53(process.cwd(), SKILLS_DIR), agentId, options) {
|
|
211498
212084
|
const allErrors = [];
|
|
211499
212085
|
const skillsById = new Map;
|
|
211500
212086
|
const sourceSet = new Set(options?.sources ?? ALL_SKILL_SOURCES);
|
|
@@ -211549,7 +212135,7 @@ async function findSkillFiles(currentPath, rootPath, skills, errors4, source, vi
|
|
|
211549
212135
|
try {
|
|
211550
212136
|
const entries = await readdir4(currentPath, { withFileTypes: true });
|
|
211551
212137
|
for (const entry of entries) {
|
|
211552
|
-
const fullPath =
|
|
212138
|
+
const fullPath = join53(currentPath, entry.name);
|
|
211553
212139
|
try {
|
|
211554
212140
|
let isDirectory2 = entry.isDirectory();
|
|
211555
212141
|
let isFile = entry.isFile();
|
|
@@ -211645,13 +212231,13 @@ var init_skills5 = __esm(() => {
|
|
|
211645
212231
|
"managing-shared-memory",
|
|
211646
212232
|
"working-across-computers"
|
|
211647
212233
|
]);
|
|
211648
|
-
PROJECT_SKILLS_DIR =
|
|
211649
|
-
GLOBAL_SKILLS_DIR =
|
|
212234
|
+
PROJECT_SKILLS_DIR = join53(".agents", "skills");
|
|
212235
|
+
GLOBAL_SKILLS_DIR = join53(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
211650
212236
|
});
|
|
211651
212237
|
|
|
211652
212238
|
// src/agent/shared-memory-skills.ts
|
|
211653
|
-
import { existsSync as
|
|
211654
|
-
import { dirname as dirname25, join as
|
|
212239
|
+
import { existsSync as existsSync42 } from "node:fs";
|
|
212240
|
+
import { dirname as dirname25, join as join54 } from "node:path";
|
|
211655
212241
|
function getAttachedRepositoriesCache() {
|
|
211656
212242
|
const global2 = globalThis;
|
|
211657
212243
|
if (!global2[ATTACHED_REPOSITORIES_CACHE_KEY]) {
|
|
@@ -211726,7 +212312,7 @@ async function resolveSharedMemorySkillsContext(options) {
|
|
|
211726
212312
|
for (const repository of repositories.sort((a2, b3) => a2.name.localeCompare(b3.name) || a2.id.localeCompare(b3.id))) {
|
|
211727
212313
|
try {
|
|
211728
212314
|
const repositoryName = validateAgentRepositoryName2(repository.name);
|
|
211729
|
-
skillsDirs.push(
|
|
212315
|
+
skillsDirs.push(join54(getRepositoryMountDir2(agentId, repositoryName), "skills"));
|
|
211730
212316
|
} catch (error4) {
|
|
211731
212317
|
errors4.push({
|
|
211732
212318
|
path: `shared-memory:${repository.name}`,
|
|
@@ -211743,7 +212329,7 @@ async function discoverSharedMemorySkills(skillsDirs) {
|
|
|
211743
212329
|
const repositoryMount = dirname25(dir);
|
|
211744
212330
|
if (isCheckoutPending(repositoryMount))
|
|
211745
212331
|
continue;
|
|
211746
|
-
if (!
|
|
212332
|
+
if (!existsSync42(repositoryMount)) {
|
|
211747
212333
|
errors4.push({
|
|
211748
212334
|
path: repositoryMount,
|
|
211749
212335
|
message: "Attached repository is not mounted locally"
|
|
@@ -211789,8 +212375,8 @@ __export(exports_client_skills, {
|
|
|
211789
212375
|
buildClientSkillsUpdateReminder: () => buildClientSkillsUpdateReminder,
|
|
211790
212376
|
buildClientSkillsPayload: () => buildClientSkillsPayload
|
|
211791
212377
|
});
|
|
211792
|
-
import { existsSync as
|
|
211793
|
-
import { join as
|
|
212378
|
+
import { existsSync as existsSync43 } from "node:fs";
|
|
212379
|
+
import { join as join55, resolve as resolve28 } from "node:path";
|
|
211794
212380
|
function getCache2() {
|
|
211795
212381
|
const global2 = globalThis;
|
|
211796
212382
|
if (!global2[CLIENT_SKILLS_CACHE_KEY]) {
|
|
@@ -211917,12 +212503,12 @@ function buildClientSkillsUpdateReminder(previous, current) {
|
|
|
211917
212503
|
function getMemorySkillsDirs(agentId) {
|
|
211918
212504
|
const dirs = new Set;
|
|
211919
212505
|
const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
|
|
211920
|
-
if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 &&
|
|
211921
|
-
dirs.add(
|
|
212506
|
+
if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync43(scopedMemoryDir)) {
|
|
212507
|
+
dirs.add(join55(scopedMemoryDir.trim(), "skills"));
|
|
211922
212508
|
} else {
|
|
211923
212509
|
const fallbackMemoryDir = (process.env.LETTA_MEMORY_DIR || process.env.MEMORY_DIR || "").trim();
|
|
211924
212510
|
if (fallbackMemoryDir) {
|
|
211925
|
-
dirs.add(
|
|
212511
|
+
dirs.add(join55(fallbackMemoryDir, "skills"));
|
|
211926
212512
|
}
|
|
211927
212513
|
}
|
|
211928
212514
|
return Array.from(dirs);
|
|
@@ -211964,8 +212550,8 @@ function toClientSkill(skill) {
|
|
|
211964
212550
|
function resolveSkillDiscoveryContext(options) {
|
|
211965
212551
|
const workingDirectory = options.workingDirectory ?? process.cwd();
|
|
211966
212552
|
const configuredSkillsDirectory = options.skillsDirectory ?? getSkillsDirectory();
|
|
211967
|
-
const legacySkillsDirectory =
|
|
211968
|
-
const primaryProjectSkillsDirectory =
|
|
212553
|
+
const legacySkillsDirectory = join55(workingDirectory, SKILLS_DIR);
|
|
212554
|
+
const primaryProjectSkillsDirectory = join55(workingDirectory, PROJECT_SKILLS_DIR);
|
|
211969
212555
|
const skillSources = options.skillSources ?? getSkillSources();
|
|
211970
212556
|
return {
|
|
211971
212557
|
workingDirectory,
|
|
@@ -212593,6 +213179,14 @@ function filterToolRegistryByClientAllowlist(registry3, clientToolAllowlist) {
|
|
|
212593
213179
|
const allowSet = new Set(clientToolAllowlist);
|
|
212594
213180
|
return new Map(Array.from(registry3.entries()).filter(([internalName]) => matchesClientToolAllowlistEntry(allowSet, getServerToolName(internalName), internalName)));
|
|
212595
213181
|
}
|
|
213182
|
+
function filterMemoryToolByMemoryFormat(registry3, agentId) {
|
|
213183
|
+
if (!registry3.has("Memory") || resolveMemoryToolDirectory(agentId)) {
|
|
213184
|
+
return registry3;
|
|
213185
|
+
}
|
|
213186
|
+
const filtered = new Map(registry3);
|
|
213187
|
+
filtered.delete("Memory");
|
|
213188
|
+
return filtered;
|
|
213189
|
+
}
|
|
212596
213190
|
function filterExternalToolsByRuntimeContext(externalTools, runtimeContext) {
|
|
212597
213191
|
return new Map(Array.from(externalTools.entries()).filter(([, tool]) => {
|
|
212598
213192
|
const matchesRuntime = !tool.runtime || (tool.runtime.agentId ?? null) === (runtimeContext.agentId ?? null) && tool.runtime.conversationId === runtimeContext.conversationId;
|
|
@@ -212809,7 +213403,7 @@ async function executeExternalTool(toolCallId, toolName2, input, executorOverrid
|
|
|
212809
213403
|
}
|
|
212810
213404
|
}
|
|
212811
213405
|
function getClientToolsFromRegistry() {
|
|
212812
|
-
return buildClientToolsFromSnapshot(toolRegistry, selectModelFacingExternalTools(filterExternalToolsByRuntimeContext(getExternalToolsRegistry(), {})), getAvailableModToolsRegistry());
|
|
213406
|
+
return buildClientToolsFromSnapshot(filterMemoryToolByMemoryFormat(toolRegistry, undefined), selectModelFacingExternalTools(filterExternalToolsByRuntimeContext(getExternalToolsRegistry(), {})), getAvailableModToolsRegistry());
|
|
212813
213407
|
}
|
|
212814
213408
|
function buildClientToolsFromSnapshot(registry3, externalTools, modTools) {
|
|
212815
213409
|
return serializeClientTools(registry3, externalTools, modTools, getServerToolName);
|
|
@@ -212817,7 +213411,7 @@ function buildClientToolsFromSnapshot(registry3, externalTools, modTools) {
|
|
|
212817
213411
|
function capturePreparedToolExecutionContext(snapshot2, options) {
|
|
212818
213412
|
const runtimeContext = buildExecutionRuntimeContextSnapshot(options);
|
|
212819
213413
|
const clientToolAllowlist = options?.clientToolAllowlist ?? toolFilter.getEnabledTools() ?? undefined;
|
|
212820
|
-
const toolRegistrySnapshot = applySubagentToolPolicy(filterToolRegistryByClientAllowlist(snapshot2.toolRegistry, clientToolAllowlist), readSubagentDepth(getRuntimeExecutionEnv(process.env, runtimeContext.executionSettings)));
|
|
213414
|
+
const toolRegistrySnapshot = filterMemoryToolByMemoryFormat(applySubagentToolPolicy(filterToolRegistryByClientAllowlist(snapshot2.toolRegistry, clientToolAllowlist), readSubagentDepth(getRuntimeExecutionEnv(process.env, runtimeContext.executionSettings))), runtimeContext.agentId);
|
|
212821
213415
|
const executionSnapshot = {
|
|
212822
213416
|
toolRegistry: toolRegistrySnapshot,
|
|
212823
213417
|
externalTools: selectModelFacingExternalTools(filterExternalToolsByClientAllowlist(filterExternalToolsByScopeIds(filterExternalToolsByRuntimeContext(snapshot2.externalTools, runtimeContext), options?.externalToolScopeIds), clientToolAllowlist), runtimeContext.connectionId),
|
|
@@ -213859,6 +214453,7 @@ var init_manager2 = __esm(async () => {
|
|
|
213859
214453
|
init_subagent_tool_policy();
|
|
213860
214454
|
init_task_tool_assets();
|
|
213861
214455
|
init_tool_name_mapping();
|
|
214456
|
+
init_memory5();
|
|
213862
214457
|
init_toolset_catalog();
|
|
213863
214458
|
await __promiseAll([
|
|
213864
214459
|
init_approval_execution(),
|
|
@@ -217290,7 +217885,7 @@ var init_LS2 = __esm(() => {
|
|
|
217290
217885
|
|
|
217291
217886
|
// src/tools/impl/ls.ts
|
|
217292
217887
|
import { readdir as readdir7, stat as stat9 } from "node:fs/promises";
|
|
217293
|
-
import { isAbsolute as isAbsolute21, join as
|
|
217888
|
+
import { isAbsolute as isAbsolute21, join as join56, resolve as resolve33 } from "node:path";
|
|
217294
217889
|
async function ls(args) {
|
|
217295
217890
|
validateRequiredParams(args, ["path"], "LS");
|
|
217296
217891
|
validateParamTypes(args, LS_default2, "LS");
|
|
@@ -217301,7 +217896,7 @@ async function ls(args) {
|
|
|
217301
217896
|
const items3 = await readdir7(dirPath);
|
|
217302
217897
|
const filteredItems = items3.filter((item) => !ignore.some((pattern4) => import_picomatch.default.isMatch(item, pattern4)));
|
|
217303
217898
|
const fileInfos = await Promise.all(filteredItems.map(async (item) => {
|
|
217304
|
-
const fullPath =
|
|
217899
|
+
const fullPath = join56(dirPath, item);
|
|
217305
217900
|
try {
|
|
217306
217901
|
const stats = await stat9(fullPath);
|
|
217307
217902
|
return {
|
|
@@ -217523,7 +218118,7 @@ var init_monitor_event_stream = __esm(() => {
|
|
|
217523
218118
|
});
|
|
217524
218119
|
|
|
217525
218120
|
// src/tools/impl/monitor.ts
|
|
217526
|
-
import { appendFileSync as appendFileSync6, readFileSync as
|
|
218121
|
+
import { appendFileSync as appendFileSync6, readFileSync as readFileSync34, writeFileSync as writeFileSync25 } from "node:fs";
|
|
217527
218122
|
import { WebSocket as WebSocket4 } from "ws";
|
|
217528
218123
|
function buildMonitorResult(taskId, timeoutMs, persistent, outputFile) {
|
|
217529
218124
|
const lifetime = persistent ? "persistent — runs until TaskStop or session end" : `timeout ${timeoutMs}ms`;
|
|
@@ -217579,7 +218174,7 @@ class MonitorOutputWriter {
|
|
|
217579
218174
|
[output truncated at ${MONITOR_OUTPUT_FILE_BYTES} bytes]
|
|
217580
218175
|
`, "utf8");
|
|
217581
218176
|
try {
|
|
217582
|
-
const content = validUtf8Prefix(Buffer.concat([
|
|
218177
|
+
const content = validUtf8Prefix(Buffer.concat([readFileSync34(this.path), chunk2]), MONITOR_OUTPUT_FILE_BYTES - marker2.length);
|
|
217583
218178
|
const truncatedOutput = Buffer.concat([content, marker2]);
|
|
217584
218179
|
writeFileSync25(this.path, truncatedOutput);
|
|
217585
218180
|
this.bytesWritten = truncatedOutput.length;
|
|
@@ -219852,7 +220447,7 @@ class CodexAppServerClient {
|
|
|
219852
220447
|
await this.request("initialize", {
|
|
219853
220448
|
clientInfo: {
|
|
219854
220449
|
name: "letta-code",
|
|
219855
|
-
version: "0.34.
|
|
220450
|
+
version: "0.34.8"
|
|
219856
220451
|
},
|
|
219857
220452
|
capabilities: null
|
|
219858
220453
|
});
|
|
@@ -221261,7 +221856,7 @@ var init_engine3 = __esm(() => {
|
|
|
221261
221856
|
|
|
221262
221857
|
// src/tools/impl/native-session-capture.ts
|
|
221263
221858
|
import { createHash as createHash5, randomUUID as randomUUID32 } from "node:crypto";
|
|
221264
|
-
import { readdirSync as
|
|
221859
|
+
import { readdirSync as readdirSync15, rmSync as rmSync14 } from "node:fs";
|
|
221265
221860
|
import {
|
|
221266
221861
|
mkdtemp as mkdtemp4,
|
|
221267
221862
|
open as open4,
|
|
@@ -221270,7 +221865,7 @@ import {
|
|
|
221270
221865
|
stat as stat10
|
|
221271
221866
|
} from "node:fs/promises";
|
|
221272
221867
|
import { homedir as homedir28, tmpdir as tmpdir12 } from "node:os";
|
|
221273
|
-
import { join as
|
|
221868
|
+
import { join as join57 } from "node:path";
|
|
221274
221869
|
async function hashNativeSessionPrefix(input, size2) {
|
|
221275
221870
|
const hash3 = createHash5("sha256");
|
|
221276
221871
|
const buffer = Buffer.allocUnsafe(NATIVE_SESSION_CAPTURE_CHUNK_BYTES);
|
|
@@ -221332,7 +221927,7 @@ function scavengeStaleSpoolDirectories() {
|
|
|
221332
221927
|
staleSpoolsScavenged = true;
|
|
221333
221928
|
let entries;
|
|
221334
221929
|
try {
|
|
221335
|
-
entries =
|
|
221930
|
+
entries = readdirSync15(tmpdir12(), { withFileTypes: true });
|
|
221336
221931
|
} catch {
|
|
221337
221932
|
return;
|
|
221338
221933
|
}
|
|
@@ -221355,7 +221950,7 @@ function scavengeStaleSpoolDirectories() {
|
|
|
221355
221950
|
}
|
|
221356
221951
|
}
|
|
221357
221952
|
if (!ownerIsAlive)
|
|
221358
|
-
cleanupSpoolDirectorySync(
|
|
221953
|
+
cleanupSpoolDirectorySync(join57(tmpdir12(), entry.name));
|
|
221359
221954
|
}
|
|
221360
221955
|
}
|
|
221361
221956
|
function key2(source, sessionId) {
|
|
@@ -221508,9 +222103,9 @@ async function findNativeSessionPath(source, sessionId, env6 = process.env) {
|
|
|
221508
222103
|
return;
|
|
221509
222104
|
const home = env6.HOME || homedir28();
|
|
221510
222105
|
if (source === "claude_code") {
|
|
221511
|
-
const projects =
|
|
222106
|
+
const projects = join57(env6.CLAUDE_CONFIG_DIR || join57(home, ".claude"), "projects");
|
|
221512
222107
|
for (const project of await entries(projects, true)) {
|
|
221513
|
-
const path29 =
|
|
222108
|
+
const path29 = join57(projects, project, `${sessionId}.jsonl`);
|
|
221514
222109
|
try {
|
|
221515
222110
|
if ((await stat10(path29)).isFile())
|
|
221516
222111
|
return path29;
|
|
@@ -221521,14 +222116,14 @@ async function findNativeSessionPath(source, sessionId, env6 = process.env) {
|
|
|
221521
222116
|
}
|
|
221522
222117
|
return;
|
|
221523
222118
|
}
|
|
221524
|
-
const root2 =
|
|
222119
|
+
const root2 = join57(env6.CODEX_HOME || join57(home, ".codex"), "sessions");
|
|
221525
222120
|
for (const year of (await entries(root2, true)).filter((name) => /^\d{4}$/.test(name)))
|
|
221526
|
-
for (const month of (await entries(
|
|
221527
|
-
for (const day of (await entries(
|
|
221528
|
-
const directory =
|
|
222121
|
+
for (const month of (await entries(join57(root2, year), true)).filter((name) => /^\d{2}$/.test(name)))
|
|
222122
|
+
for (const day of (await entries(join57(root2, year, month), true)).filter((name) => /^\d{2}$/.test(name))) {
|
|
222123
|
+
const directory = join57(root2, year, month, day);
|
|
221529
222124
|
for (const file of await entries(directory, false))
|
|
221530
222125
|
if (file.startsWith("rollout-") && file.endsWith(`-${sessionId}.jsonl`))
|
|
221531
|
-
return
|
|
222126
|
+
return join57(directory, file);
|
|
221532
222127
|
}
|
|
221533
222128
|
return;
|
|
221534
222129
|
}
|
|
@@ -221545,9 +222140,9 @@ async function seal(state2, source, sessionId, scope, env6, requestOptions) {
|
|
|
221545
222140
|
throw new Error("Native session file disappeared before EOF capture");
|
|
221546
222141
|
throw error4;
|
|
221547
222142
|
}
|
|
221548
|
-
const directory = await mkdtemp4(
|
|
222143
|
+
const directory = await mkdtemp4(join57(tmpdir12(), `letta-native-session-${process.pid}-${captureProcessInstanceId}-`));
|
|
221549
222144
|
spoolDirectories.add(directory);
|
|
221550
|
-
const spoolPath =
|
|
222145
|
+
const spoolPath = join57(directory, "segment");
|
|
221551
222146
|
let output;
|
|
221552
222147
|
let retained = false;
|
|
221553
222148
|
try {
|
|
@@ -221664,7 +222259,7 @@ async function drain(state2, source, sessionId) {
|
|
|
221664
222259
|
await spool.close();
|
|
221665
222260
|
}
|
|
221666
222261
|
state2.segments.shift();
|
|
221667
|
-
const directory =
|
|
222262
|
+
const directory = join57(segment.path, "..");
|
|
221668
222263
|
await cleanupSpoolDirectory(directory);
|
|
221669
222264
|
}
|
|
221670
222265
|
}
|
|
@@ -221696,7 +222291,7 @@ async function discardRejectedSegment(state2) {
|
|
|
221696
222291
|
const segment = state2.segments.shift();
|
|
221697
222292
|
if (!segment)
|
|
221698
222293
|
return;
|
|
221699
|
-
const directory =
|
|
222294
|
+
const directory = join57(segment.path, "..");
|
|
221700
222295
|
await cleanupSpoolDirectory(directory);
|
|
221701
222296
|
state2.ackedOffset = segment.end;
|
|
221702
222297
|
state2.retryDelayMs = INITIAL_DRAIN_RETRY_MS;
|
|
@@ -222702,20 +223297,20 @@ var init_recall_subagent_local = () => {};
|
|
|
222702
223297
|
|
|
222703
223298
|
// src/utils/transcript-paths.ts
|
|
222704
223299
|
import { homedir as homedir29 } from "node:os";
|
|
222705
|
-
import { join as
|
|
223300
|
+
import { join as join58 } from "node:path";
|
|
222706
223301
|
function getTranscriptRoot() {
|
|
222707
223302
|
const envRoot = process.env[TRANSCRIPT_ROOT_ENV]?.trim();
|
|
222708
223303
|
if (envRoot) {
|
|
222709
223304
|
return envRoot;
|
|
222710
223305
|
}
|
|
222711
|
-
return
|
|
223306
|
+
return join58(homedir29(), ".letta", "transcripts");
|
|
222712
223307
|
}
|
|
222713
223308
|
var TRANSCRIPT_ROOT_ENV = "LETTA_TRANSCRIPT_ROOT";
|
|
222714
223309
|
var init_transcript_paths = () => {};
|
|
222715
223310
|
|
|
222716
223311
|
// src/agent/subagents/sandbox.ts
|
|
222717
223312
|
import { mkdirSync as mkdirSync30 } from "node:fs";
|
|
222718
|
-
import { join as
|
|
223313
|
+
import { join as join59 } from "node:path";
|
|
222719
223314
|
function wrapSubagentLauncher(input) {
|
|
222720
223315
|
const env6 = input.env ?? process.env;
|
|
222721
223316
|
if (!isFsSandboxEnabled(env6))
|
|
@@ -222758,7 +223353,7 @@ function wrapSubagentLauncher(input) {
|
|
|
222758
223353
|
if (!wrapped || wrapped.length === 0)
|
|
222759
223354
|
return null;
|
|
222760
223355
|
const [command, ...args] = wrapped;
|
|
222761
|
-
const scratchRoot =
|
|
223356
|
+
const scratchRoot = join59(getLettaHomeRoot(), "tmp");
|
|
222762
223357
|
mkdirSync30(scratchRoot, { recursive: true });
|
|
222763
223358
|
return {
|
|
222764
223359
|
command,
|
|
@@ -224065,7 +224660,7 @@ var MEMORY_WORKER_SESSION_ENV = "LETTA_MEMORY_WORKER_SESSION";
|
|
|
224065
224660
|
|
|
224066
224661
|
// src/agent/subagents/subagent-launcher.ts
|
|
224067
224662
|
import { homedir as homedir30 } from "node:os";
|
|
224068
|
-
import { join as
|
|
224663
|
+
import { join as join60 } from "node:path";
|
|
224069
224664
|
function resolveSubagentWorkingDirectory(env6 = process.env, fallbackCwd = getCurrentWorkingDirectory(), options = {}) {
|
|
224070
224665
|
if (options.subagentType === "reflection" && options.launchProfile === "memory-subagent" && options.memoryScope) {
|
|
224071
224666
|
return env6.USER_CWD || fallbackCwd;
|
|
@@ -224123,9 +224718,9 @@ function resolveMemorySubagentScratchpad(parentProcessEnv, subagentId) {
|
|
|
224123
224718
|
return configuredScratchpad;
|
|
224124
224719
|
}
|
|
224125
224720
|
const configuredTranscriptRoot = parentProcessEnv[TRANSCRIPT_ROOT_ENV];
|
|
224126
|
-
const transcriptRoot = configuredTranscriptRoot?.trim() ||
|
|
224721
|
+
const transcriptRoot = configuredTranscriptRoot?.trim() || join60(parentProcessEnv.HOME?.trim() || homedir30(), ".letta", "transcripts");
|
|
224127
224722
|
const scope = subagentId ? encodeURIComponent(subagentId) : crypto.randomUUID();
|
|
224128
|
-
return
|
|
224723
|
+
return join60(transcriptRoot, "background", scope);
|
|
224129
224724
|
}
|
|
224130
224725
|
function composeSubagentChildEnv(options) {
|
|
224131
224726
|
const {
|
|
@@ -224695,7 +225290,7 @@ var init_manager4 = __esm(async () => {
|
|
|
224695
225290
|
import { execFile as execFile16 } from "node:child_process";
|
|
224696
225291
|
import { randomUUID as randomUUID36 } from "node:crypto";
|
|
224697
225292
|
import { readFile as readFile15, rm as rm9, writeFile as writeFile13 } from "node:fs/promises";
|
|
224698
|
-
import { join as
|
|
225293
|
+
import { join as join61 } from "node:path";
|
|
224699
225294
|
import { promisify as promisify16 } from "node:util";
|
|
224700
225295
|
async function readOptional(path29) {
|
|
224701
225296
|
try {
|
|
@@ -224716,7 +225311,7 @@ async function describeMemoryConflict(memoryDir, gitDir) {
|
|
|
224716
225311
|
]);
|
|
224717
225312
|
head4 = stdout.trim();
|
|
224718
225313
|
} catch {}
|
|
224719
|
-
const heads = await Promise.all(OPERATION_HEADS.map((name) => readOptional(
|
|
225314
|
+
const heads = await Promise.all(OPERATION_HEADS.map((name) => readOptional(join61(gitDir, name))));
|
|
224720
225315
|
return [head4, ...heads].join(`
|
|
224721
225316
|
`);
|
|
224722
225317
|
}
|
|
@@ -224736,7 +225331,7 @@ ${stdout.trim()}`;
|
|
|
224736
225331
|
}
|
|
224737
225332
|
}
|
|
224738
225333
|
async function attemptPath(memoryDir) {
|
|
224739
|
-
return
|
|
225334
|
+
return join61(await getMemoryGitDir(memoryDir), ATTEMPT_FILE);
|
|
224740
225335
|
}
|
|
224741
225336
|
async function readAttempt(path29) {
|
|
224742
225337
|
try {
|
|
@@ -224770,7 +225365,7 @@ async function claimMemoryConflictRepair(memoryDir, kind = "conflict") {
|
|
|
224770
225365
|
let signature;
|
|
224771
225366
|
try {
|
|
224772
225367
|
const gitDir = await getMemoryGitDir(memoryDir);
|
|
224773
|
-
path29 =
|
|
225368
|
+
path29 = join61(gitDir, ATTEMPT_FILE);
|
|
224774
225369
|
signature = kind === "invalid" ? await describeInvalidMemoryHistory(memoryDir) : await describeMemoryConflict(memoryDir, gitDir);
|
|
224775
225370
|
} catch {
|
|
224776
225371
|
return { status: "claimed", token: token2 };
|
|
@@ -224832,7 +225427,7 @@ var init_memory_conflict_repair = __esm(() => {
|
|
|
224832
225427
|
// src/agent/subagents/memory-handoff.ts
|
|
224833
225428
|
import { randomUUID as randomUUID37 } from "node:crypto";
|
|
224834
225429
|
import { mkdir as mkdir11, rm as rm10, writeFile as writeFile14 } from "node:fs/promises";
|
|
224835
|
-
import { join as
|
|
225430
|
+
import { join as join62 } from "node:path";
|
|
224836
225431
|
async function withMemoryHandoff(params, run) {
|
|
224837
225432
|
const handoff = await prepareMemoryHandoff(params);
|
|
224838
225433
|
try {
|
|
@@ -224867,9 +225462,9 @@ async function prepareMemoryHandoff(params) {
|
|
|
224867
225462
|
break;
|
|
224868
225463
|
after2 = cursor;
|
|
224869
225464
|
}
|
|
224870
|
-
const directory =
|
|
225465
|
+
const directory = join62(getTranscriptRoot(), params.agentId, "memory-handoffs");
|
|
224871
225466
|
await mkdir11(directory, { recursive: true, mode: 448 });
|
|
224872
|
-
transcriptPath =
|
|
225467
|
+
transcriptPath = join62(directory, `${randomUUID37()}.json`);
|
|
224873
225468
|
await writeFile14(transcriptPath, JSON.stringify(messages, null, 2), {
|
|
224874
225469
|
mode: 292,
|
|
224875
225470
|
flag: "wx"
|
|
@@ -224932,9 +225527,9 @@ var init_memory_operation = __esm(() => {
|
|
|
224932
225527
|
// src/agent/memory-worktree.ts
|
|
224933
225528
|
import { execFile as execFileCb4 } from "node:child_process";
|
|
224934
225529
|
import { randomUUID as randomUUID38 } from "node:crypto";
|
|
224935
|
-
import { existsSync as
|
|
225530
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
224936
225531
|
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
224937
|
-
import { dirname as dirname26, isAbsolute as isAbsolute23, join as
|
|
225532
|
+
import { dirname as dirname26, isAbsolute as isAbsolute23, join as join63, resolve as resolve36 } from "node:path";
|
|
224938
225533
|
import { promisify as promisify17 } from "node:util";
|
|
224939
225534
|
async function runGit4(cwd2, args) {
|
|
224940
225535
|
try {
|
|
@@ -224994,9 +225589,9 @@ async function buildReflectionMergeMessage(parentMemoryDir, branchName) {
|
|
|
224994
225589
|
async function createReflectionMemoryWorktree(options) {
|
|
224995
225590
|
const parentMemoryDir = resolve36(options.parentMemoryDir);
|
|
224996
225591
|
const id2 = buildReflectionWorktreeId(options.now);
|
|
224997
|
-
const worktreeBaseDir =
|
|
225592
|
+
const worktreeBaseDir = join63(dirname26(parentMemoryDir), "memory-worktrees");
|
|
224998
225593
|
const label = options.label ?? "reflection";
|
|
224999
|
-
const worktreeDir =
|
|
225594
|
+
const worktreeDir = join63(worktreeBaseDir, `${label}-${id2}`);
|
|
225000
225595
|
const branchName = `letta/${label}/${id2}`;
|
|
225001
225596
|
await mkdir12(worktreeBaseDir, { recursive: true });
|
|
225002
225597
|
const { stdout: baseHeadOut } = await runGit4(parentMemoryDir, [
|
|
@@ -225124,7 +225719,7 @@ async function inspectReflectionMemoryWorktree(worktree) {
|
|
|
225124
225719
|
};
|
|
225125
225720
|
}
|
|
225126
225721
|
async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName, options = {}) {
|
|
225127
|
-
const removedWorktree =
|
|
225722
|
+
const removedWorktree = existsSync44(worktreeDir);
|
|
225128
225723
|
if (removedWorktree) {
|
|
225129
225724
|
await runGit4(parentMemoryDir, [
|
|
225130
225725
|
"worktree",
|
|
@@ -225140,7 +225735,7 @@ async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName
|
|
|
225140
225735
|
]);
|
|
225141
225736
|
}
|
|
225142
225737
|
async function finalizeReflectionMemoryWorktreeUnlocked(worktree, options) {
|
|
225143
|
-
if (!
|
|
225738
|
+
if (!existsSync44(worktree.worktreeDir) && options.knownNoChanges) {
|
|
225144
225739
|
const branchHead = (await tryRunGit(worktree.parentMemoryDir, [
|
|
225145
225740
|
"rev-parse",
|
|
225146
225741
|
"--verify",
|
|
@@ -225327,7 +225922,7 @@ async function integrateMemoryWorkerWorktree(worktree, options = {}) {
|
|
|
225327
225922
|
await cleanup(true);
|
|
225328
225923
|
return { status: "no_changes" };
|
|
225329
225924
|
}
|
|
225330
|
-
if (
|
|
225925
|
+
if (existsSync44(worktree.worktreeDir)) {
|
|
225331
225926
|
await runGit4(worktree.parentMemoryDir, [
|
|
225332
225927
|
"worktree",
|
|
225333
225928
|
"remove",
|
|
@@ -226628,9 +227223,9 @@ __export(exports_skill, {
|
|
|
226628
227223
|
loadRenderedSkillContent: () => loadRenderedSkillContent,
|
|
226629
227224
|
getResolvedSkillsDir: () => getResolvedSkillsDir
|
|
226630
227225
|
});
|
|
226631
|
-
import { existsSync as
|
|
227226
|
+
import { existsSync as existsSync45, readdirSync as readdirSync16 } from "node:fs";
|
|
226632
227227
|
import { readFile as readFile16 } from "node:fs/promises";
|
|
226633
|
-
import { dirname as dirname27, join as
|
|
227228
|
+
import { dirname as dirname27, join as join64 } from "node:path";
|
|
226634
227229
|
async function readSkillFromRoot(skillsRoot, skillId) {
|
|
226635
227230
|
const discovery = await discoverSkills(skillsRoot, undefined, {
|
|
226636
227231
|
sources: ["project"],
|
|
@@ -226650,12 +227245,12 @@ async function readSkillFromRoot(skillsRoot, skillId) {
|
|
|
226650
227245
|
function getMemorySkillsDirs2(agentId) {
|
|
226651
227246
|
const dirs = new Set;
|
|
226652
227247
|
const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
|
|
226653
|
-
if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 &&
|
|
226654
|
-
dirs.add(
|
|
227248
|
+
if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync45(scopedMemoryDir)) {
|
|
227249
|
+
dirs.add(join64(scopedMemoryDir.trim(), "skills"));
|
|
226655
227250
|
} else {
|
|
226656
227251
|
const fallbackMemoryDir = (process.env.LETTA_MEMORY_DIR || process.env.MEMORY_DIR || "").trim();
|
|
226657
227252
|
if (fallbackMemoryDir) {
|
|
226658
|
-
dirs.add(
|
|
227253
|
+
dirs.add(join64(fallbackMemoryDir, "skills"));
|
|
226659
227254
|
}
|
|
226660
227255
|
}
|
|
226661
227256
|
return Array.from(dirs);
|
|
@@ -226667,7 +227262,7 @@ function listSkillResources(skillMdPath) {
|
|
|
226667
227262
|
function walk3(directory, relativeDirectory) {
|
|
226668
227263
|
let entries2;
|
|
226669
227264
|
try {
|
|
226670
|
-
entries2 =
|
|
227265
|
+
entries2 = readdirSync16(directory, { withFileTypes: true });
|
|
226671
227266
|
} catch {
|
|
226672
227267
|
return;
|
|
226673
227268
|
}
|
|
@@ -226681,7 +227276,7 @@ function listSkillResources(skillMdPath) {
|
|
|
226681
227276
|
return;
|
|
226682
227277
|
}
|
|
226683
227278
|
if (entry.isDirectory()) {
|
|
226684
|
-
walk3(
|
|
227279
|
+
walk3(join64(directory, entry.name), relativePath);
|
|
226685
227280
|
if (truncated) {
|
|
226686
227281
|
return;
|
|
226687
227282
|
}
|
|
@@ -226695,7 +227290,7 @@ function listSkillResources(skillMdPath) {
|
|
|
226695
227290
|
}
|
|
226696
227291
|
async function readSkillContent(skillId, skillsDir, agentId, options = {}) {
|
|
226697
227292
|
const projectSkillsDirs = new Set([
|
|
226698
|
-
|
|
227293
|
+
join64(getCurrentWorkingDirectory(), PROJECT_SKILLS_DIR),
|
|
226699
227294
|
skillsDir
|
|
226700
227295
|
]);
|
|
226701
227296
|
for (const projectSkillsDir of projectSkillsDirs) {
|
|
@@ -226743,8 +227338,8 @@ async function readSkillContent(skillId, skillsDir, agentId, options = {}) {
|
|
|
226743
227338
|
} catch {}
|
|
226744
227339
|
}
|
|
226745
227340
|
try {
|
|
226746
|
-
const bundledSkillsDir =
|
|
226747
|
-
const bundledSkillPath =
|
|
227341
|
+
const bundledSkillsDir = join64(process.cwd(), "skills", "skills");
|
|
227342
|
+
const bundledSkillPath = join64(bundledSkillsDir, skillId, "SKILL.md");
|
|
226748
227343
|
const content = await readFile16(bundledSkillPath, "utf-8");
|
|
226749
227344
|
return { content, path: bundledSkillPath };
|
|
226750
227345
|
} catch {
|
|
@@ -226756,7 +227351,7 @@ async function getResolvedSkillsDir() {
|
|
|
226756
227351
|
if (skillsDir) {
|
|
226757
227352
|
return skillsDir;
|
|
226758
227353
|
}
|
|
226759
|
-
return
|
|
227354
|
+
return join64(getCurrentWorkingDirectory(), SKILLS_DIR);
|
|
226760
227355
|
}
|
|
226761
227356
|
function getResolvedAgentId(args) {
|
|
226762
227357
|
if (args.parentScope?.agentId) {
|
|
@@ -226776,7 +227371,7 @@ function renderSkillContent(skillName, skillContent, skillPath, options = {}) {
|
|
|
226776
227371
|
const skillDir = dirname27(skillPath);
|
|
226777
227372
|
const withSkillDir = skillContent.replace(/<SKILL_DIR>/g, skillDir).replace(/\$\{CLAUDE_SKILL_DIR\}/g, skillDir);
|
|
226778
227373
|
const resources = listSkillResources(skillPath);
|
|
226779
|
-
const resourceLines = resources.paths.map((resourcePath) => ` <file>${
|
|
227374
|
+
const resourceLines = resources.paths.map((resourcePath) => ` <file>${escapeXmlText3(resourcePath)}</file>`);
|
|
226780
227375
|
if (resources.truncated) {
|
|
226781
227376
|
resourceLines.push(" <truncated>true</truncated>");
|
|
226782
227377
|
}
|
|
@@ -226796,11 +227391,11 @@ async function loadRenderedSkillContent(skillName, options = {}) {
|
|
|
226796
227391
|
const { content: skillContent, path: skillPath } = await readSkillContent(skillName, skillsDir, options.agentId, options);
|
|
226797
227392
|
return renderSkillContent(skillName, skillContent, skillPath, options);
|
|
226798
227393
|
}
|
|
226799
|
-
function
|
|
227394
|
+
function escapeXmlText3(value) {
|
|
226800
227395
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
226801
227396
|
}
|
|
226802
227397
|
function escapeXmlAttribute3(value) {
|
|
226803
|
-
return
|
|
227398
|
+
return escapeXmlText3(value).replace(/"/g, """);
|
|
226804
227399
|
}
|
|
226805
227400
|
function wrapSkillContent(skillName, content) {
|
|
226806
227401
|
return `<skill_content name="${escapeXmlAttribute3(skillName)}">
|
|
@@ -228740,9 +229335,9 @@ function formatWorkflowSummary(stats) {
|
|
|
228740
229335
|
// src/tools/workflow/journal.ts
|
|
228741
229336
|
import { appendFileSync as appendFileSync7, mkdirSync as mkdirSync31, writeFileSync as writeFileSync26 } from "node:fs";
|
|
228742
229337
|
import { homedir as homedir32 } from "node:os";
|
|
228743
|
-
import { join as
|
|
229338
|
+
import { join as join65 } from "node:path";
|
|
228744
229339
|
function defaultExecutionsDir() {
|
|
228745
|
-
return
|
|
229340
|
+
return join65(homedir32(), ".letta", "workflows", "executions");
|
|
228746
229341
|
}
|
|
228747
229342
|
function newExecutionId() {
|
|
228748
229343
|
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
@@ -228753,17 +229348,17 @@ function newExecutionId() {
|
|
|
228753
229348
|
return `wf-${suffix}`;
|
|
228754
229349
|
}
|
|
228755
229350
|
function createExecutionDir(executionsDir, executionId, script4, args) {
|
|
228756
|
-
const executionDir =
|
|
229351
|
+
const executionDir = join65(executionsDir, executionId);
|
|
228757
229352
|
mkdirSync31(executionDir, { recursive: true, mode: DIR_MODE });
|
|
228758
|
-
const scriptPath =
|
|
229353
|
+
const scriptPath = join65(executionDir, "script.js");
|
|
228759
229354
|
writeFileSync26(scriptPath, script4, { mode: FILE_MODE });
|
|
228760
229355
|
if (args !== undefined) {
|
|
228761
|
-
writeFileSync26(
|
|
229356
|
+
writeFileSync26(join65(executionDir, "args.json"), JSON.stringify(args, null, 2), { mode: FILE_MODE });
|
|
228762
229357
|
}
|
|
228763
229358
|
return {
|
|
228764
229359
|
executionDir,
|
|
228765
229360
|
scriptPath,
|
|
228766
|
-
journalPath:
|
|
229361
|
+
journalPath: join65(executionDir, "journal.jsonl")
|
|
228767
229362
|
};
|
|
228768
229363
|
}
|
|
228769
229364
|
function appendJournalEntry(journalPath, entry) {
|
|
@@ -228873,9 +229468,9 @@ var init_meta3 = __esm(() => {
|
|
|
228873
229468
|
});
|
|
228874
229469
|
|
|
228875
229470
|
// src/tools/workflow/sdk-loader.ts
|
|
228876
|
-
import { existsSync as
|
|
229471
|
+
import { existsSync as existsSync46, readFileSync as readFileSync35 } from "node:fs";
|
|
228877
229472
|
import { createRequire as createRequire6 } from "node:module";
|
|
228878
|
-
import { dirname as dirname28, join as
|
|
229473
|
+
import { dirname as dirname28, join as join66 } from "node:path";
|
|
228879
229474
|
import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
228880
229475
|
function supportsPublishedResume(version2) {
|
|
228881
229476
|
if (!version2 || !MIN_RESUME_SDK_VERSION)
|
|
@@ -228897,14 +229492,14 @@ function preferRunningCliForSubagents() {
|
|
|
228897
229492
|
if (process.env.LETTA_CLI_PATH)
|
|
228898
229493
|
return;
|
|
228899
229494
|
const entry = process.argv[1];
|
|
228900
|
-
if (entry && /(^|[\\/])letta\.js$/.test(entry) &&
|
|
229495
|
+
if (entry && /(^|[\\/])letta\.js$/.test(entry) && existsSync46(entry)) {
|
|
228901
229496
|
process.env.LETTA_CLI_PATH = entry;
|
|
228902
229497
|
}
|
|
228903
229498
|
}
|
|
228904
229499
|
function packageVersion(entry) {
|
|
228905
229500
|
for (let dir = dirname28(entry);; dir = dirname28(dir)) {
|
|
228906
229501
|
try {
|
|
228907
|
-
const manifest = JSON.parse(
|
|
229502
|
+
const manifest = JSON.parse(readFileSync35(join66(dir, "package.json"), "utf8"));
|
|
228908
229503
|
if (manifest.name === SDK_PACKAGE)
|
|
228909
229504
|
return manifest.version;
|
|
228910
229505
|
} catch {}
|
|
@@ -228914,10 +229509,10 @@ function packageVersion(entry) {
|
|
|
228914
229509
|
}
|
|
228915
229510
|
function packageEntry(packageDir) {
|
|
228916
229511
|
try {
|
|
228917
|
-
const manifest = JSON.parse(
|
|
229512
|
+
const manifest = JSON.parse(readFileSync35(join66(packageDir, "package.json"), "utf8"));
|
|
228918
229513
|
const root2 = manifest.exports?.["."];
|
|
228919
229514
|
const entry = typeof root2 === "string" ? root2 : root2?.import ?? root2?.default ?? manifest.main;
|
|
228920
|
-
return entry ?
|
|
229515
|
+
return entry ? join66(packageDir, entry) : null;
|
|
228921
229516
|
} catch {
|
|
228922
229517
|
return null;
|
|
228923
229518
|
}
|
|
@@ -228927,8 +229522,8 @@ function probeInstalledSdkDirs(startDirs) {
|
|
|
228927
229522
|
for (const start of startDirs) {
|
|
228928
229523
|
let dir = start;
|
|
228929
229524
|
while (true) {
|
|
228930
|
-
const candidate =
|
|
228931
|
-
if (
|
|
229525
|
+
const candidate = join66(dir, "node_modules", ...SDK_PACKAGE.split("/"));
|
|
229526
|
+
if (existsSync46(join66(candidate, "package.json")) && !found.includes(candidate)) {
|
|
228932
229527
|
found.push(candidate);
|
|
228933
229528
|
}
|
|
228934
229529
|
const parent = dirname28(dir);
|
|
@@ -228946,7 +229541,7 @@ async function loadAgentSdk() {
|
|
|
228946
229541
|
const specifiers = [];
|
|
228947
229542
|
if (envPath) {
|
|
228948
229543
|
try {
|
|
228949
|
-
const require2 = createRequire6(
|
|
229544
|
+
const require2 = createRequire6(join66(envPath, "noop.js"));
|
|
228950
229545
|
specifiers.push(pathToFileURL3(require2.resolve(envPath)).href);
|
|
228951
229546
|
} catch {
|
|
228952
229547
|
specifiers.push(pathToFileURL3(envPath).href);
|
|
@@ -228957,7 +229552,7 @@ async function loadAgentSdk() {
|
|
|
228957
229552
|
specifiers.push(pathToFileURL3(require2.resolve(SDK_PACKAGE)).href);
|
|
228958
229553
|
} catch {}
|
|
228959
229554
|
try {
|
|
228960
|
-
const require2 = createRequire6(
|
|
229555
|
+
const require2 = createRequire6(join66(process.cwd(), "package.json"));
|
|
228961
229556
|
specifiers.push(pathToFileURL3(require2.resolve(SDK_PACKAGE)).href);
|
|
228962
229557
|
} catch {
|
|
228963
229558
|
specifiers.push(SDK_PACKAGE);
|
|
@@ -246747,12 +247342,12 @@ var init_mcp_client = __esm(() => {
|
|
|
246747
247342
|
init_streamableHttp();
|
|
246748
247343
|
DEFAULT_CLIENT_INFO = {
|
|
246749
247344
|
name: "letta-code",
|
|
246750
|
-
version: "0.34.
|
|
247345
|
+
version: "0.34.8"
|
|
246751
247346
|
};
|
|
246752
247347
|
});
|
|
246753
247348
|
|
|
246754
247349
|
// src/mcp-oauth-callback.ts
|
|
246755
|
-
import { createServer as
|
|
247350
|
+
import { createServer as createServer4 } from "node:http";
|
|
246756
247351
|
async function startOAuthCallbackServer2(preferredPort) {
|
|
246757
247352
|
try {
|
|
246758
247353
|
return await startOAuthCallbackServerOnPort(preferredPort ?? 0);
|
|
@@ -246791,7 +247386,7 @@ async function startOAuthCallbackServerOnPort(port) {
|
|
|
246791
247386
|
codePromise.catch(() => {
|
|
246792
247387
|
return;
|
|
246793
247388
|
});
|
|
246794
|
-
server2 =
|
|
247389
|
+
server2 = createServer4((request, response) => {
|
|
246795
247390
|
if (request.method !== "GET" || !request.url?.startsWith("/") || request.url.startsWith("//") || request.url.includes("\\")) {
|
|
246796
247391
|
response.writeHead(400, { "Content-Type": "text/plain" });
|
|
246797
247392
|
response.end("Invalid request target");
|
|
@@ -246828,7 +247423,7 @@ async function startOAuthCallbackServerOnPort(port) {
|
|
|
246828
247423
|
response.writeHead(400, { "Content-Type": "text/html" });
|
|
246829
247424
|
reject2?.(new Error(`MCP OAuth authorization failed: ${error5}`));
|
|
246830
247425
|
response.end(callbackPage("Authorization failed", error5), () => {
|
|
246831
|
-
|
|
247426
|
+
closeServer2(true);
|
|
246832
247427
|
});
|
|
246833
247428
|
return;
|
|
246834
247429
|
}
|
|
@@ -246840,7 +247435,7 @@ async function startOAuthCallbackServerOnPort(port) {
|
|
|
246840
247435
|
response.writeHead(200, { "Content-Type": "text/html" });
|
|
246841
247436
|
settle3?.(code2);
|
|
246842
247437
|
response.end(callbackPage("Authorization complete", "You can close this tab and return to Letta Code."), () => {
|
|
246843
|
-
|
|
247438
|
+
closeServer2(true);
|
|
246844
247439
|
});
|
|
246845
247440
|
});
|
|
246846
247441
|
server2.on("clientError", (_error, socket) => {
|
|
@@ -246853,7 +247448,7 @@ Content-Length: 0\r
|
|
|
246853
247448
|
`);
|
|
246854
247449
|
});
|
|
246855
247450
|
let serverClosing = false;
|
|
246856
|
-
const
|
|
247451
|
+
const closeServer2 = (force = false) => {
|
|
246857
247452
|
if (serverClosing)
|
|
246858
247453
|
return;
|
|
246859
247454
|
serverClosing = true;
|
|
@@ -246873,7 +247468,7 @@ Content-Length: 0\r
|
|
|
246873
247468
|
}
|
|
246874
247469
|
const timeout = setTimeout(() => {
|
|
246875
247470
|
reject2?.(new Error("Timed out waiting for MCP OAuth authorization"));
|
|
246876
|
-
|
|
247471
|
+
closeServer2(true);
|
|
246877
247472
|
}, CALLBACK_TIMEOUT_MS);
|
|
246878
247473
|
timeout.unref();
|
|
246879
247474
|
return {
|
|
@@ -246884,7 +247479,7 @@ Content-Length: 0\r
|
|
|
246884
247479
|
clearTimeout(timeout);
|
|
246885
247480
|
if (!completed)
|
|
246886
247481
|
reject2?.(new Error("MCP OAuth flow was cancelled"));
|
|
246887
|
-
|
|
247482
|
+
closeServer2(true);
|
|
246888
247483
|
}
|
|
246889
247484
|
};
|
|
246890
247485
|
}
|
|
@@ -248538,8 +249133,8 @@ var init_mcp = __esm(() => {
|
|
|
248538
249133
|
});
|
|
248539
249134
|
|
|
248540
249135
|
// src/tools/impl/workflow.ts
|
|
248541
|
-
import { readFileSync as
|
|
248542
|
-
import { join as
|
|
249136
|
+
import { readFileSync as readFileSync36 } from "node:fs";
|
|
249137
|
+
import { join as join67, resolve as resolve38 } from "node:path";
|
|
248543
249138
|
function isOwningAgentId(value) {
|
|
248544
249139
|
return value?.startsWith("agent-") === true && !value.startsWith("agent-free:");
|
|
248545
249140
|
}
|
|
@@ -248696,7 +249291,7 @@ function formatCompletionResult(run, executionDir) {
|
|
|
248696
249291
|
return [
|
|
248697
249292
|
payload,
|
|
248698
249293
|
"",
|
|
248699
|
-
`Per-call results: ${
|
|
249294
|
+
`Per-call results: ${join67(executionDir, "journal.jsonl")} — one line per completed agent call with its full return value, plus one per decide() API attempt (retries included) with its model, cost, calibration, and tokens.`,
|
|
248700
249295
|
"If the result above is empty or unexpected, read that file BEFORE diagnosing — do not assume agents returned non-empty results."
|
|
248701
249296
|
].join(`
|
|
248702
249297
|
`);
|
|
@@ -248705,7 +249300,7 @@ async function workflow(args) {
|
|
|
248705
249300
|
let script4 = typeof args.script === "string" ? args.script : undefined;
|
|
248706
249301
|
if (typeof args.scriptPath === "string" && args.scriptPath) {
|
|
248707
249302
|
try {
|
|
248708
|
-
script4 =
|
|
249303
|
+
script4 = readFileSync36(resolve38(getCurrentWorkingDirectory(), args.scriptPath), "utf8");
|
|
248709
249304
|
} catch (error5) {
|
|
248710
249305
|
return {
|
|
248711
249306
|
toolReturn: `Cannot read scriptPath ${args.scriptPath}: ${String(error5)}`,
|
|
@@ -249357,6 +249952,23 @@ var init_Grep2 = __esm(() => {
|
|
|
249357
249952
|
};
|
|
249358
249953
|
});
|
|
249359
249954
|
|
|
249955
|
+
// src/tools/schemas/Memory.json
|
|
249956
|
+
var Memory_default2;
|
|
249957
|
+
var init_Memory2 = __esm(() => {
|
|
249958
|
+
Memory_default2 = {
|
|
249959
|
+
type: "object",
|
|
249960
|
+
properties: {
|
|
249961
|
+
path: {
|
|
249962
|
+
type: "string",
|
|
249963
|
+
description: 'Memory directory or file relative to the memory directory, e.g. "projects", "projects/code", or "projects/example.md".'
|
|
249964
|
+
}
|
|
249965
|
+
},
|
|
249966
|
+
required: ["path"],
|
|
249967
|
+
additionalProperties: false,
|
|
249968
|
+
$schema: "https://json-schema.org/draft/2020-12/schema"
|
|
249969
|
+
};
|
|
249970
|
+
});
|
|
249971
|
+
|
|
249360
249972
|
// src/tools/schemas/Monitor.json
|
|
249361
249973
|
var Monitor_default2;
|
|
249362
249974
|
var init_Monitor2 = __esm(() => {
|
|
@@ -249995,6 +250607,7 @@ var init_tool_definitions = __esm(async () => {
|
|
|
249995
250607
|
init_Glob();
|
|
249996
250608
|
init_Grep();
|
|
249997
250609
|
init_LS();
|
|
250610
|
+
init_Memory();
|
|
249998
250611
|
init_Monitor();
|
|
249999
250612
|
init_Read();
|
|
250000
250613
|
init_ReadArtifactFile();
|
|
@@ -250023,6 +250636,7 @@ var init_tool_definitions = __esm(async () => {
|
|
|
250023
250636
|
init_glob();
|
|
250024
250637
|
init_grep();
|
|
250025
250638
|
init_ls();
|
|
250639
|
+
init_memory5();
|
|
250026
250640
|
init_skill();
|
|
250027
250641
|
init_task_create();
|
|
250028
250642
|
init_task_get();
|
|
@@ -250041,6 +250655,7 @@ var init_tool_definitions = __esm(async () => {
|
|
|
250041
250655
|
init_Glob2();
|
|
250042
250656
|
init_Grep2();
|
|
250043
250657
|
init_LS2();
|
|
250658
|
+
init_Memory2();
|
|
250044
250659
|
init_Monitor2();
|
|
250045
250660
|
init_Read2();
|
|
250046
250661
|
init_ReadArtifactFile2();
|
|
@@ -250173,6 +250788,11 @@ ${WINDOWS_UNIFIED_EXEC_GUIDANCE}`;
|
|
|
250173
250788
|
description: SetWorkingDirectory_default.trim(),
|
|
250174
250789
|
impl: set_working_directory
|
|
250175
250790
|
}),
|
|
250791
|
+
Memory: defineTool({
|
|
250792
|
+
schema: Memory_default2,
|
|
250793
|
+
description: Memory_default.trim(),
|
|
250794
|
+
impl: memory2
|
|
250795
|
+
}),
|
|
250176
250796
|
Skill: defineTool({
|
|
250177
250797
|
schema: Skill_default2,
|
|
250178
250798
|
description: Skill_default.trim(),
|
|
@@ -250400,14 +251020,14 @@ var init_interrupted_turn_schema = __esm(async () => {
|
|
|
250400
251020
|
// src/websocket/listener/interrupted-turn-storage.ts
|
|
250401
251021
|
import { createHash as createHash7 } from "node:crypto";
|
|
250402
251022
|
import {
|
|
250403
|
-
closeSync as
|
|
251023
|
+
closeSync as closeSync6,
|
|
250404
251024
|
fsyncSync as fsyncSync3,
|
|
250405
|
-
openSync as
|
|
251025
|
+
openSync as openSync6,
|
|
250406
251026
|
renameSync as renameSync8,
|
|
250407
251027
|
writeFileSync as writeFileSync27
|
|
250408
251028
|
} from "node:fs";
|
|
250409
251029
|
import { homedir as homedir33 } from "node:os";
|
|
250410
|
-
import { join as
|
|
251030
|
+
import { join as join68 } from "node:path";
|
|
250411
251031
|
function writeInterruptedTurnRecordFile(temporary, destination, directory, record6, syncDirectory) {
|
|
250412
251032
|
writeFileSync27(temporary, JSON.stringify(record6), {
|
|
250413
251033
|
mode: 384,
|
|
@@ -250419,11 +251039,11 @@ function writeInterruptedTurnRecordFile(temporary, destination, directory, recor
|
|
|
250419
251039
|
function fsyncInterruptedTurnDirectory(directory, platform9 = process.platform) {
|
|
250420
251040
|
if (platform9 === "win32")
|
|
250421
251041
|
return;
|
|
250422
|
-
const fd =
|
|
251042
|
+
const fd = openSync6(directory, "r");
|
|
250423
251043
|
try {
|
|
250424
251044
|
fsyncSync3(fd);
|
|
250425
251045
|
} finally {
|
|
250426
|
-
|
|
251046
|
+
closeSync6(fd);
|
|
250427
251047
|
}
|
|
250428
251048
|
}
|
|
250429
251049
|
function defaultInterruptedTurnDirectory() {
|
|
@@ -250433,7 +251053,7 @@ function defaultInterruptedTurnDirectory() {
|
|
|
250433
251053
|
} catch {
|
|
250434
251054
|
serverUrl = process.env.LETTA_BASE_URL ?? "uninitialized";
|
|
250435
251055
|
}
|
|
250436
|
-
return
|
|
251056
|
+
return join68(homedir33(), ".letta", "listener-state", createHash7("sha256").update(serverUrl).digest("hex").slice(0, 24));
|
|
250437
251057
|
}
|
|
250438
251058
|
var init_interrupted_turn_storage = __esm(() => {
|
|
250439
251059
|
init_server_url();
|
|
@@ -250502,23 +251122,23 @@ function createRecoveryAuthorityGuard(dependencies4) {
|
|
|
250502
251122
|
// src/websocket/listener/recovery-lineage-sidecar.ts
|
|
250503
251123
|
import { createHash as createHash8, randomUUID as randomUUID40 } from "node:crypto";
|
|
250504
251124
|
import {
|
|
250505
|
-
existsSync as
|
|
251125
|
+
existsSync as existsSync47,
|
|
250506
251126
|
mkdirSync as mkdirSync32,
|
|
250507
|
-
readdirSync as
|
|
250508
|
-
readFileSync as
|
|
251127
|
+
readdirSync as readdirSync17,
|
|
251128
|
+
readFileSync as readFileSync37,
|
|
250509
251129
|
renameSync as renameSync9,
|
|
250510
251130
|
rmSync as rmSync17,
|
|
250511
|
-
statSync as
|
|
251131
|
+
statSync as statSync17,
|
|
250512
251132
|
writeFileSync as writeFileSync28
|
|
250513
251133
|
} from "node:fs";
|
|
250514
|
-
import { join as
|
|
251134
|
+
import { join as join69 } from "node:path";
|
|
250515
251135
|
function createRecoveryLineageSidecarAccess(params) {
|
|
250516
251136
|
const canonicalSidecarName = /\.json\.recovery-[0-9a-f]{24}$/;
|
|
250517
251137
|
const temporarySidecarName = /^(.+\.json)\.recovery-[0-9a-f]{24}\.(\d+)\.([0-9a-f-]{36})\.[0-9a-f-]{36}\.tmp$/;
|
|
250518
251138
|
const legacyTemporarySidecarName = /^(.+\.json)\.recovery-[0-9a-f]{24}\.(\d+)\.[0-9a-f-]{36}\.tmp$/;
|
|
250519
251139
|
const staleTemporaryAgeMs = 60000;
|
|
250520
251140
|
const maximumTemporaryAgeMs = 24 * 60 * 60 * 1000;
|
|
250521
|
-
const path32 = (agentId, conversationId, lineageId) =>
|
|
251141
|
+
const path32 = (agentId, conversationId, lineageId) => join69(params.directory, `${encodeURIComponent(agentId)}_${encodeURIComponent(conversationId)}.json.recovery-${createHash8("sha256").update(lineageId).digest("hex").slice(0, 24)}`);
|
|
250522
251142
|
const isSidecar = (value) => {
|
|
250523
251143
|
if (!value || typeof value !== "object")
|
|
250524
251144
|
return false;
|
|
@@ -250527,7 +251147,7 @@ function createRecoveryLineageSidecarAccess(params) {
|
|
|
250527
251147
|
};
|
|
250528
251148
|
const read2 = (agentId, conversationId, lineageId) => {
|
|
250529
251149
|
try {
|
|
250530
|
-
const parsed = JSON.parse(
|
|
251150
|
+
const parsed = JSON.parse(readFileSync37(path32(agentId, conversationId, lineageId), "utf8"));
|
|
250531
251151
|
if (!isSidecar(parsed) || parsed.agentId !== agentId || parsed.conversationId !== conversationId || parsed.lineageId !== lineageId) {
|
|
250532
251152
|
throw new Error("Invalid recovery-lineage sidecar");
|
|
250533
251153
|
}
|
|
@@ -250797,15 +251417,15 @@ function createRecoveryLineageSidecarAccess(params) {
|
|
|
250797
251417
|
const removeMalformedOrphan = (file) => {
|
|
250798
251418
|
const separator = file.indexOf(".recovery-");
|
|
250799
251419
|
const mainFile = separator >= 0 ? file.slice(0, separator) : "";
|
|
250800
|
-
if (!mainFile ||
|
|
251420
|
+
if (!mainFile || existsSync47(join69(params.directory, mainFile)))
|
|
250801
251421
|
return;
|
|
250802
251422
|
try {
|
|
250803
|
-
rmSync17(
|
|
251423
|
+
rmSync17(join69(params.directory, file), { force: true });
|
|
250804
251424
|
params.syncDirectory(params.directory);
|
|
250805
251425
|
} catch {}
|
|
250806
251426
|
};
|
|
250807
251427
|
try {
|
|
250808
|
-
const files =
|
|
251428
|
+
const files = readdirSync17(params.directory);
|
|
250809
251429
|
for (const file of files) {
|
|
250810
251430
|
const temporaryMatch = file.match(temporarySidecarName) ?? file.match(legacyTemporarySidecarName);
|
|
250811
251431
|
if (!temporaryMatch)
|
|
@@ -250827,13 +251447,13 @@ function createRecoveryLineageSidecarAccess(params) {
|
|
|
250827
251447
|
ownerIsAlive = error5.code !== "ESRCH";
|
|
250828
251448
|
}
|
|
250829
251449
|
}
|
|
250830
|
-
const ageMs = Date.now() -
|
|
251450
|
+
const ageMs = Date.now() - statSync17(join69(params.directory, file)).mtimeMs;
|
|
250831
251451
|
if (!ownerIsCurrentWriter && (!ownerIsAlive && ageMs >= staleTemporaryAgeMs || ageMs >= maximumTemporaryAgeMs)) {
|
|
250832
|
-
const release = acquireDurableFileLock(
|
|
251452
|
+
const release = acquireDurableFileLock(join69(params.directory, mainFile), { waitMs: params.lockWaitMs });
|
|
250833
251453
|
try {
|
|
250834
|
-
const currentAgeMs = Date.now() -
|
|
251454
|
+
const currentAgeMs = Date.now() - statSync17(join69(params.directory, file)).mtimeMs;
|
|
250835
251455
|
if (!ownerIsCurrentWriter && (!ownerIsAlive && currentAgeMs >= staleTemporaryAgeMs || currentAgeMs >= maximumTemporaryAgeMs)) {
|
|
250836
|
-
rmSync17(
|
|
251456
|
+
rmSync17(join69(params.directory, file), { force: true });
|
|
250837
251457
|
params.syncDirectory(params.directory);
|
|
250838
251458
|
}
|
|
250839
251459
|
} finally {
|
|
@@ -250844,8 +251464,8 @@ function createRecoveryLineageSidecarAccess(params) {
|
|
|
250844
251464
|
}
|
|
250845
251465
|
return files.filter((file) => canonicalSidecarName.test(file)).flatMap((file) => {
|
|
250846
251466
|
try {
|
|
250847
|
-
const value = JSON.parse(
|
|
250848
|
-
if (isSidecar(value) &&
|
|
251467
|
+
const value = JSON.parse(readFileSync37(join69(params.directory, file), "utf8"));
|
|
251468
|
+
if (isSidecar(value) && join69(params.directory, file) === path32(value.agentId, value.conversationId, value.lineageId)) {
|
|
250849
251469
|
return [value];
|
|
250850
251470
|
}
|
|
250851
251471
|
removeMalformedOrphan(file);
|
|
@@ -250887,14 +251507,14 @@ var init_recovery_lineage_sidecar = __esm(async () => {
|
|
|
250887
251507
|
// src/websocket/listener/interrupted-turn-record.ts
|
|
250888
251508
|
import { randomUUID as randomUUID41 } from "node:crypto";
|
|
250889
251509
|
import {
|
|
250890
|
-
existsSync as
|
|
251510
|
+
existsSync as existsSync48,
|
|
250891
251511
|
mkdirSync as mkdirSync33,
|
|
250892
|
-
readFileSync as
|
|
251512
|
+
readFileSync as readFileSync38,
|
|
250893
251513
|
rmSync as rmSync18,
|
|
250894
251514
|
unlinkSync as unlinkSync9,
|
|
250895
251515
|
writeFileSync as writeFileSync29
|
|
250896
251516
|
} from "node:fs";
|
|
250897
|
-
import { join as
|
|
251517
|
+
import { join as join70 } from "node:path";
|
|
250898
251518
|
function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(), dependencies4 = {}) {
|
|
250899
251519
|
const sync = dependencies4.fsyncDirectory ?? fsyncInterruptedTurnDirectory;
|
|
250900
251520
|
function persist(destination, record6) {
|
|
@@ -250906,11 +251526,11 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
|
|
|
250906
251526
|
}
|
|
250907
251527
|
}
|
|
250908
251528
|
function path32(agentId, conversationId) {
|
|
250909
|
-
return
|
|
251529
|
+
return join70(directory, `${encodeURIComponent(agentId)}_${encodeURIComponent(conversationId)}.json`);
|
|
250910
251530
|
}
|
|
250911
251531
|
function readRecord2(file) {
|
|
250912
251532
|
try {
|
|
250913
|
-
const value = JSON.parse(
|
|
251533
|
+
const value = JSON.parse(readFileSync38(file, "utf8"));
|
|
250914
251534
|
if (!isInterruptedTurnRecord(value, file, path32)) {
|
|
250915
251535
|
throw new Error("Invalid interrupted-turn record");
|
|
250916
251536
|
}
|
|
@@ -250944,7 +251564,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
|
|
|
250944
251564
|
const recoveryAuthority = createRecoveryAuthorityGuard({
|
|
250945
251565
|
path: path32,
|
|
250946
251566
|
readRecord: readRecord2,
|
|
250947
|
-
exists:
|
|
251567
|
+
exists: existsSync48,
|
|
250948
251568
|
acquire: (destination) => acquireDurableFileLock(destination, {
|
|
250949
251569
|
waitMs: dependencies4.lockWaitMs
|
|
250950
251570
|
}),
|
|
@@ -250978,7 +251598,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
|
|
|
250978
251598
|
});
|
|
250979
251599
|
try {
|
|
250980
251600
|
const current = readRecord2(destination);
|
|
250981
|
-
if (!
|
|
251601
|
+
if (!existsSync48(destination)) {
|
|
250982
251602
|
removeSidecar(sidecar);
|
|
250983
251603
|
} else if (current && current.recoveryClaimCompletion?.lineageId !== sidecar.lineageId) {
|
|
250984
251604
|
removeSidecar(sidecar);
|
|
@@ -251003,7 +251623,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
|
|
|
251003
251623
|
},
|
|
251004
251624
|
listDurableInputOwnership() {
|
|
251005
251625
|
const snapshot2 = rawSnapshot();
|
|
251006
|
-
return collectInterruptedTurnInputOwnershipWithSidecars(snapshot2.records, readMainView, listSidecars(), (agentId, conversationId) =>
|
|
251626
|
+
return collectInterruptedTurnInputOwnershipWithSidecars(snapshot2.records, readMainView, listSidecars(), (agentId, conversationId) => existsSync48(path32(agentId, conversationId)), snapshot2.unreadableScopes);
|
|
251007
251627
|
},
|
|
251008
251628
|
read(agentId, conversationId) {
|
|
251009
251629
|
const current = readRecord2(path32(agentId, conversationId));
|
|
@@ -251262,7 +251882,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
|
|
|
251262
251882
|
}
|
|
251263
251883
|
if (current.revision === params.pendingRevision && !marker2.independentSuccessor) {
|
|
251264
251884
|
const retiredAuthority = retireSidecar(current);
|
|
251265
|
-
const evidence =
|
|
251885
|
+
const evidence = readFileSync38(destination, "utf8");
|
|
251266
251886
|
unlinkSync9(destination);
|
|
251267
251887
|
try {
|
|
251268
251888
|
sync(directory);
|
|
@@ -251317,7 +251937,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
|
|
|
251317
251937
|
if (expectedRevision !== undefined && (current.revision ?? null) !== expectedRevision) {
|
|
251318
251938
|
return false;
|
|
251319
251939
|
}
|
|
251320
|
-
evidence =
|
|
251940
|
+
evidence = readFileSync38(destination, "utf8");
|
|
251321
251941
|
unlinkSync9(destination);
|
|
251322
251942
|
} catch (error5) {
|
|
251323
251943
|
if (error5.code === "ENOENT")
|
|
@@ -253305,10 +253925,10 @@ var init_input_disposition_expiry = __esm(() => {
|
|
|
253305
253925
|
// src/websocket/listener/input-disposition-path.ts
|
|
253306
253926
|
import { createHash as createHash9 } from "node:crypto";
|
|
253307
253927
|
import { homedir as homedir34 } from "node:os";
|
|
253308
|
-
import { join as
|
|
253928
|
+
import { join as join71 } from "node:path";
|
|
253309
253929
|
function inputDispositionPersistentPath(serverUrl) {
|
|
253310
253930
|
const namespace = createHash9("sha256").update(serverUrl).digest("hex").slice(0, 24);
|
|
253311
|
-
return
|
|
253931
|
+
return join71(homedir34(), ".letta", "state", namespace, "input-dispositions-v2.json");
|
|
253312
253932
|
}
|
|
253313
253933
|
var init_input_disposition_path = () => {};
|
|
253314
253934
|
|
|
@@ -253334,14 +253954,14 @@ var init_input_disposition_validation = __esm(async () => {
|
|
|
253334
253954
|
import { randomUUID as randomUUID42 } from "node:crypto";
|
|
253335
253955
|
import {
|
|
253336
253956
|
chmodSync as chmodSync7,
|
|
253337
|
-
closeSync as
|
|
253338
|
-
existsSync as
|
|
253957
|
+
closeSync as closeSync7,
|
|
253958
|
+
existsSync as existsSync49,
|
|
253339
253959
|
fsyncSync as fsyncSync4,
|
|
253340
253960
|
mkdirSync as mkdirSync34,
|
|
253341
|
-
openSync as
|
|
253342
|
-
readFileSync as
|
|
253961
|
+
openSync as openSync7,
|
|
253962
|
+
readFileSync as readFileSync39,
|
|
253343
253963
|
renameSync as renameSync10,
|
|
253344
|
-
statSync as
|
|
253964
|
+
statSync as statSync18,
|
|
253345
253965
|
unlinkSync as unlinkSync10,
|
|
253346
253966
|
writeFileSync as writeFileSync30
|
|
253347
253967
|
} from "node:fs";
|
|
@@ -253479,13 +254099,13 @@ function validateDurableStore(value) {
|
|
|
253479
254099
|
return value;
|
|
253480
254100
|
}
|
|
253481
254101
|
function readDurableStore(path32) {
|
|
253482
|
-
if (!
|
|
254102
|
+
if (!existsSync49(path32))
|
|
253483
254103
|
return emptyDurableStore();
|
|
253484
|
-
const size2 =
|
|
254104
|
+
const size2 = statSync18(path32).size;
|
|
253485
254105
|
if (size2 > MAX_INPUT_DISPOSITION_STORE_BYTES) {
|
|
253486
254106
|
throw new Error("Accepted-input disposition store exceeds its size limit");
|
|
253487
254107
|
}
|
|
253488
|
-
return validateDurableStore(JSON.parse(
|
|
254108
|
+
return validateDurableStore(JSON.parse(readFileSync39(path32, "utf8")));
|
|
253489
254109
|
}
|
|
253490
254110
|
function prepareStateDirectory(path32) {
|
|
253491
254111
|
const dir = dirname30(path32);
|
|
@@ -253501,11 +254121,11 @@ function writeDurableStore(path32, store3) {
|
|
|
253501
254121
|
const temporaryPath = `${path32}.${process.pid}.${randomUUID42()}.tmp`;
|
|
253502
254122
|
try {
|
|
253503
254123
|
writeFileSync30(temporaryPath, serialized, { mode: 384, flag: "wx" });
|
|
253504
|
-
const fd =
|
|
254124
|
+
const fd = openSync7(temporaryPath, "r+");
|
|
253505
254125
|
try {
|
|
253506
254126
|
fsyncSync4(fd);
|
|
253507
254127
|
} finally {
|
|
253508
|
-
|
|
254128
|
+
closeSync7(fd);
|
|
253509
254129
|
}
|
|
253510
254130
|
renameSync10(temporaryPath, path32);
|
|
253511
254131
|
fsyncDirectory(dirname30(path32));
|
|
@@ -253927,18 +254547,18 @@ var init_input_disposition = __esm(async () => {
|
|
|
253927
254547
|
// src/websocket/listener/turn-finished-replay.ts
|
|
253928
254548
|
import { randomUUID as randomUUID43 } from "node:crypto";
|
|
253929
254549
|
import {
|
|
253930
|
-
closeSync as
|
|
254550
|
+
closeSync as closeSync8,
|
|
253931
254551
|
fsyncSync as fsyncSync5,
|
|
253932
254552
|
mkdirSync as mkdirSync35,
|
|
253933
|
-
openSync as
|
|
253934
|
-
readdirSync as
|
|
253935
|
-
readFileSync as
|
|
254553
|
+
openSync as openSync8,
|
|
254554
|
+
readdirSync as readdirSync18,
|
|
254555
|
+
readFileSync as readFileSync40,
|
|
253936
254556
|
renameSync as renameSync11,
|
|
253937
254557
|
rmSync as rmSync19,
|
|
253938
254558
|
writeFileSync as writeFileSync31
|
|
253939
254559
|
} from "node:fs";
|
|
253940
254560
|
import { homedir as homedir35 } from "node:os";
|
|
253941
|
-
import { join as
|
|
254561
|
+
import { join as join72 } from "node:path";
|
|
253942
254562
|
function terminalAuthorityStatus(runtime, terminal, terminals, interruptedStore = createInterruptedTurnStore()) {
|
|
253943
254563
|
const { owner } = terminal;
|
|
253944
254564
|
if (!owner.recoveryLineageId)
|
|
@@ -253978,7 +254598,7 @@ function defaultDirectory() {
|
|
|
253978
254598
|
} catch {
|
|
253979
254599
|
serverUrl = process.env.LETTA_BASE_URL ?? "uninitialized";
|
|
253980
254600
|
}
|
|
253981
|
-
return
|
|
254601
|
+
return join72(homedir35(), ".letta", "listener-terminal-state", Buffer.from(serverUrl).toString("base64url"));
|
|
253982
254602
|
}
|
|
253983
254603
|
function encodeTurnFinishedScope(agentId, conversationId) {
|
|
253984
254604
|
return Buffer.from(JSON.stringify([agentId, conversationId])).toString("base64url");
|
|
@@ -253997,19 +254617,19 @@ function decodeTurnFinishedScope(encoded) {
|
|
|
253997
254617
|
function fsyncDirectory2(directory) {
|
|
253998
254618
|
if (process.platform === "win32")
|
|
253999
254619
|
return;
|
|
254000
|
-
const fd =
|
|
254620
|
+
const fd = openSync8(directory, "r");
|
|
254001
254621
|
try {
|
|
254002
254622
|
fsyncSync5(fd);
|
|
254003
254623
|
} finally {
|
|
254004
|
-
|
|
254624
|
+
closeSync8(fd);
|
|
254005
254625
|
}
|
|
254006
254626
|
}
|
|
254007
254627
|
function createTurnFinishedStore(directory = defaultDirectory(), options = {}) {
|
|
254008
254628
|
const claimantToken = randomUUID43();
|
|
254009
|
-
const path32 = (agentId, conversationId) =>
|
|
254629
|
+
const path32 = (agentId, conversationId) => join72(directory, `${encodeTurnFinishedScope(agentId, conversationId)}.json`);
|
|
254010
254630
|
const readRecord2 = (agentId, conversationId) => {
|
|
254011
254631
|
try {
|
|
254012
|
-
const record6 = JSON.parse(
|
|
254632
|
+
const record6 = JSON.parse(readFileSync40(path32(agentId, conversationId), "utf8"));
|
|
254013
254633
|
if (record6.agentId !== agentId || record6.conversationId !== conversationId || !Array.isArray(record6.terminals) || !record6.terminals.every((terminal) => typeof terminal.id === "string" && Number.isFinite(terminal.createdAt) && terminal.message?.type === "turn_finished" && typeof terminal.message.turn_id === "string" && Array.isArray(terminal.requiredConsumerIds) && terminal.requiredConsumerIds.every((id2) => typeof id2 === "string") && Array.isArray(terminal.acknowledgedConsumerIds) && terminal.acknowledgedConsumerIds.every((id2) => typeof id2 === "string") && !!terminal.owner && (terminal.owner.connectionId === null || typeof terminal.owner.connectionId === "string") && typeof terminal.owner.canRotate === "boolean" && (terminal.owner.terminalIdentity === undefined || typeof terminal.owner.terminalIdentity === "string") && (terminal.owner.interruptedRevision === undefined || typeof terminal.owner.interruptedRevision === "string") && (terminal.owner.recoveryLineageId === undefined || typeof terminal.owner.recoveryLineageId === "string") && (terminal.owner.interruptedAuthorityRevision === undefined || typeof terminal.owner.interruptedAuthorityRevision === "string") && (terminal.owner.preparationSequence === undefined || Number.isSafeInteger(terminal.owner.preparationSequence) && terminal.owner.preparationSequence >= 0))) {
|
|
254014
254634
|
throw new Error("Invalid turn-finished record");
|
|
254015
254635
|
}
|
|
@@ -254075,7 +254695,7 @@ function createTurnFinishedStore(directory = defaultDirectory(), options = {}) {
|
|
|
254075
254695
|
const sweepExpiredRecords = () => {
|
|
254076
254696
|
let entries2;
|
|
254077
254697
|
try {
|
|
254078
|
-
entries2 =
|
|
254698
|
+
entries2 = readdirSync18(directory, { withFileTypes: true });
|
|
254079
254699
|
} catch (error5) {
|
|
254080
254700
|
if (error5.code === "ENOENT")
|
|
254081
254701
|
return;
|
|
@@ -259315,7 +259935,7 @@ function printListenUsage() {
|
|
|
259315
259935
|
}
|
|
259316
259936
|
|
|
259317
259937
|
// src/cli/subcommands/listener-readiness.ts
|
|
259318
|
-
async function completeListenerConnectionStartup(expectedConnection, readiness) {
|
|
259938
|
+
async function completeListenerConnectionStartup(expectedConnection, readiness, startGateway = async () => {}) {
|
|
259319
259939
|
const { getActiveRuntime: getActiveRuntime2 } = await init_runtime6().then(() => exports_runtime);
|
|
259320
259940
|
const runtime = getActiveRuntime2();
|
|
259321
259941
|
const connection = runtime?.connections.get(expectedConnection.id);
|
|
@@ -259325,8 +259945,11 @@ async function completeListenerConnectionStartup(expectedConnection, readiness)
|
|
|
259325
259945
|
const { isListenerTransportOpen: isListenerTransportOpen2 } = await Promise.resolve().then(() => (init_transport(), exports_transport));
|
|
259326
259946
|
if (!isListenerTransportOpen2(connection.writer))
|
|
259327
259947
|
return false;
|
|
259948
|
+
await startGateway();
|
|
259328
259949
|
if (getActiveRuntime2()?.connections.get(connection.id) !== connection)
|
|
259329
259950
|
return false;
|
|
259951
|
+
if (!connection.initialized || !connection.ingressReady || connection.cancellation.signal.aborted || !isListenerTransportOpen2(connection.writer))
|
|
259952
|
+
return false;
|
|
259330
259953
|
readiness.completeCloudStartup(epoch);
|
|
259331
259954
|
return true;
|
|
259332
259955
|
}
|
|
@@ -259448,13 +260071,13 @@ var init_service_protocol = __esm(() => {
|
|
|
259448
260071
|
// src/websocket/listen-log.ts
|
|
259449
260072
|
import {
|
|
259450
260073
|
appendFileSync as appendFileSync8,
|
|
259451
|
-
existsSync as
|
|
260074
|
+
existsSync as existsSync50,
|
|
259452
260075
|
mkdirSync as mkdirSync36,
|
|
259453
|
-
readdirSync as
|
|
260076
|
+
readdirSync as readdirSync19,
|
|
259454
260077
|
unlinkSync as unlinkSync11
|
|
259455
260078
|
} from "node:fs";
|
|
259456
260079
|
import { homedir as homedir36 } from "node:os";
|
|
259457
|
-
import { join as
|
|
260080
|
+
import { join as join73 } from "node:path";
|
|
259458
260081
|
function formatTimestamp2() {
|
|
259459
260082
|
const now2 = new Date;
|
|
259460
260083
|
const h3 = String(now2.getHours()).padStart(2, "0");
|
|
@@ -259468,14 +260091,14 @@ function formatFileTimestamp(now2) {
|
|
|
259468
260091
|
}
|
|
259469
260092
|
function pruneOldLogs(dir, maxFiles) {
|
|
259470
260093
|
try {
|
|
259471
|
-
if (!
|
|
260094
|
+
if (!existsSync50(dir))
|
|
259472
260095
|
return;
|
|
259473
|
-
const files =
|
|
260096
|
+
const files = readdirSync19(dir).filter((f4) => f4.endsWith(".log")).sort();
|
|
259474
260097
|
if (files.length >= maxFiles) {
|
|
259475
260098
|
const toDelete = files.slice(0, files.length - maxFiles + 1);
|
|
259476
260099
|
for (const file of toDelete) {
|
|
259477
260100
|
try {
|
|
259478
|
-
unlinkSync11(
|
|
260101
|
+
unlinkSync11(join73(dir, file));
|
|
259479
260102
|
} catch {}
|
|
259480
260103
|
}
|
|
259481
260104
|
}
|
|
@@ -259514,13 +260137,13 @@ class RemoteSessionLog {
|
|
|
259514
260137
|
freshPath() {
|
|
259515
260138
|
const stamp = formatFileTimestamp(new Date);
|
|
259516
260139
|
const suffix = this.rotation > 0 ? `.${this.rotation}` : "";
|
|
259517
|
-
return
|
|
260140
|
+
return join73(this.dir, `${stamp}${suffix}.log`);
|
|
259518
260141
|
}
|
|
259519
260142
|
rotate() {
|
|
259520
260143
|
const previous = this.path;
|
|
259521
260144
|
this.rotation += 1;
|
|
259522
260145
|
this.path = this.freshPath();
|
|
259523
|
-
while (
|
|
260146
|
+
while (existsSync50(this.path)) {
|
|
259524
260147
|
this.rotation += 1;
|
|
259525
260148
|
this.path = this.freshPath();
|
|
259526
260149
|
}
|
|
@@ -259544,7 +260167,7 @@ class RemoteSessionLog {
|
|
|
259544
260167
|
if (this.dirCreated)
|
|
259545
260168
|
return;
|
|
259546
260169
|
try {
|
|
259547
|
-
if (!
|
|
260170
|
+
if (!existsSync50(this.dir)) {
|
|
259548
260171
|
mkdirSync36(this.dir, { recursive: true });
|
|
259549
260172
|
}
|
|
259550
260173
|
this.dirCreated = true;
|
|
@@ -259553,7 +260176,7 @@ class RemoteSessionLog {
|
|
|
259553
260176
|
}
|
|
259554
260177
|
var REMOTE_LOG_DIR, MAX_LOG_FILES = 10, MAX_LOG_BYTES2;
|
|
259555
260178
|
var init_listen_log = __esm(() => {
|
|
259556
|
-
REMOTE_LOG_DIR =
|
|
260179
|
+
REMOTE_LOG_DIR = join73(homedir36(), ".letta", "logs", "remote");
|
|
259557
260180
|
MAX_LOG_BYTES2 = 10 * 1024 * 1024;
|
|
259558
260181
|
});
|
|
259559
260182
|
|
|
@@ -262296,28 +262919,28 @@ __export(exports_memory_scanner, {
|
|
|
262296
262919
|
readFileContent: () => readFileContent,
|
|
262297
262920
|
getFileNodes: () => getFileNodes
|
|
262298
262921
|
});
|
|
262299
|
-
import { readdirSync as
|
|
262300
|
-
import { join as
|
|
262922
|
+
import { readdirSync as readdirSync20, readFileSync as readFileSync41, statSync as statSync19 } from "node:fs";
|
|
262923
|
+
import { join as join74, relative as relative7 } from "node:path";
|
|
262301
262924
|
function scanMemoryFilesystem(memoryRoot) {
|
|
262302
262925
|
const nodes = [];
|
|
262303
262926
|
const scanDir = (dir, depth, parentIsLast) => {
|
|
262304
262927
|
let entries2;
|
|
262305
262928
|
try {
|
|
262306
|
-
entries2 =
|
|
262929
|
+
entries2 = readdirSync20(dir);
|
|
262307
262930
|
} catch {
|
|
262308
262931
|
return;
|
|
262309
262932
|
}
|
|
262310
262933
|
const filtered = entries2.filter((name) => !name.startsWith("."));
|
|
262311
262934
|
const sorted = filtered.sort((a2, b3) => {
|
|
262312
|
-
const aPath =
|
|
262313
|
-
const bPath =
|
|
262935
|
+
const aPath = join74(dir, a2);
|
|
262936
|
+
const bPath = join74(dir, b3);
|
|
262314
262937
|
let aIsDir = false;
|
|
262315
262938
|
let bIsDir = false;
|
|
262316
262939
|
try {
|
|
262317
|
-
aIsDir =
|
|
262940
|
+
aIsDir = statSync19(aPath).isDirectory();
|
|
262318
262941
|
} catch {}
|
|
262319
262942
|
try {
|
|
262320
|
-
bIsDir =
|
|
262943
|
+
bIsDir = statSync19(bPath).isDirectory();
|
|
262321
262944
|
} catch {}
|
|
262322
262945
|
if (aIsDir !== bIsDir)
|
|
262323
262946
|
return aIsDir ? -1 : 1;
|
|
@@ -262330,10 +262953,10 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
262330
262953
|
return a2.localeCompare(b3);
|
|
262331
262954
|
});
|
|
262332
262955
|
sorted.forEach((name, index) => {
|
|
262333
|
-
const fullPath =
|
|
262956
|
+
const fullPath = join74(dir, name);
|
|
262334
262957
|
let isDir = false;
|
|
262335
262958
|
try {
|
|
262336
|
-
isDir =
|
|
262959
|
+
isDir = statSync19(fullPath).isDirectory();
|
|
262337
262960
|
} catch {
|
|
262338
262961
|
return;
|
|
262339
262962
|
}
|
|
@@ -262361,7 +262984,7 @@ function getFileNodes(nodes) {
|
|
|
262361
262984
|
}
|
|
262362
262985
|
function readFileContent(fullPath) {
|
|
262363
262986
|
try {
|
|
262364
|
-
return
|
|
262987
|
+
return readFileSync41(fullPath, "utf-8");
|
|
262365
262988
|
} catch {
|
|
262366
262989
|
return "(unable to read file)";
|
|
262367
262990
|
}
|
|
@@ -262432,10 +263055,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
262432
263055
|
const isMemfsEnabledOnServer2 = overrides.isMemfsEnabledOnServer ?? actualIsMemfsEnabledOnServer;
|
|
262433
263056
|
const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memory_scanner(), exports_memory_scanner));
|
|
262434
263057
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
|
|
262435
|
-
const { existsSync:
|
|
262436
|
-
const { join:
|
|
263058
|
+
const { existsSync: existsSync51, statSync: statSync20 } = await import("node:fs");
|
|
263059
|
+
const { join: join75, posix: posix3 } = await import("node:path");
|
|
262437
263060
|
const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
|
|
262438
|
-
let memfsInitialized =
|
|
263061
|
+
let memfsInitialized = existsSync51(join75(memoryRoot, ".git"));
|
|
262439
263062
|
const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
262440
263063
|
if (!memfsEnabled) {
|
|
262441
263064
|
safeSocketSend(socket, {
|
|
@@ -262453,7 +263076,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
262453
263076
|
await ensureLocalMemfsCheckout2(parsed.agent_id, {
|
|
262454
263077
|
pullOnExistingRepo: true
|
|
262455
263078
|
});
|
|
262456
|
-
memfsInitialized =
|
|
263079
|
+
memfsInitialized = existsSync51(join75(memoryRoot, ".git"));
|
|
262457
263080
|
if (!memfsInitialized) {
|
|
262458
263081
|
throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
|
|
262459
263082
|
}
|
|
@@ -262529,7 +263152,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
262529
263152
|
if (imageMimeType) {
|
|
262530
263153
|
let size2 = 0;
|
|
262531
263154
|
try {
|
|
262532
|
-
size2 =
|
|
263155
|
+
size2 = statSync20(node.fullPath).size;
|
|
262533
263156
|
} catch {}
|
|
262534
263157
|
return {
|
|
262535
263158
|
relative_path: node.relativePath,
|
|
@@ -262753,34 +263376,34 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
262753
263376
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
262754
263377
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
262755
263378
|
const { readFile: readFile20 } = await import("node:fs/promises");
|
|
262756
|
-
const { existsSync:
|
|
262757
|
-
const { isAbsolute: isAbsolute25, join:
|
|
263379
|
+
const { existsSync: existsSync51 } = await import("node:fs");
|
|
263380
|
+
const { isAbsolute: isAbsolute25, join: join75, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
|
|
262758
263381
|
if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
|
|
262759
263382
|
sendFailure("path must be a non-empty relative path");
|
|
262760
263383
|
return;
|
|
262761
263384
|
}
|
|
262762
263385
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
262763
|
-
const absolutePath = normalize4(
|
|
263386
|
+
const absolutePath = normalize4(join75(memoryRoot, parsed.path));
|
|
262764
263387
|
const rel = relative8(memoryRoot, absolutePath);
|
|
262765
|
-
if (rel.startsWith("..") || rel === "" || isAbsolute25(rel) || rel.split(
|
|
263388
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute25(rel) || rel.split(sep8).includes("..")) {
|
|
262766
263389
|
sendFailure("path must resolve inside the memory root");
|
|
262767
263390
|
return;
|
|
262768
263391
|
}
|
|
262769
|
-
if (!
|
|
263392
|
+
if (!existsSync51(join75(memoryRoot, ".git"))) {
|
|
262770
263393
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
262771
263394
|
if (!enabled) {
|
|
262772
263395
|
sendFailure("memfs is not enabled for this agent");
|
|
262773
263396
|
return;
|
|
262774
263397
|
}
|
|
262775
263398
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
262776
|
-
if (!
|
|
263399
|
+
if (!existsSync51(join75(memoryRoot, ".git"))) {
|
|
262777
263400
|
sendFailure("failed to initialize local memory checkout");
|
|
262778
263401
|
return;
|
|
262779
263402
|
}
|
|
262780
263403
|
}
|
|
262781
263404
|
const buffer = await readFile20(absolutePath);
|
|
262782
263405
|
const content = encoding === "base64" ? buffer.toString("base64") : buffer.toString("utf-8");
|
|
262783
|
-
const pathspec = rel.split(
|
|
263406
|
+
const pathspec = rel.split(sep8).join("/");
|
|
262784
263407
|
safeSocketSend(socket, {
|
|
262785
263408
|
type: "read_memory_file_response",
|
|
262786
263409
|
request_id: parsed.request_id,
|
|
@@ -262819,27 +263442,27 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
262819
263442
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
262820
263443
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
262821
263444
|
const { writeFile: writeFile16, mkdir: mkdir14 } = await import("node:fs/promises");
|
|
262822
|
-
const { existsSync:
|
|
262823
|
-
const { dirname: dirname31, isAbsolute: isAbsolute25, join:
|
|
263445
|
+
const { existsSync: existsSync51 } = await import("node:fs");
|
|
263446
|
+
const { dirname: dirname31, isAbsolute: isAbsolute25, join: join75, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
|
|
262824
263447
|
if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
|
|
262825
263448
|
sendFailure("write_memory_file: path must be a non-empty relative path");
|
|
262826
263449
|
return;
|
|
262827
263450
|
}
|
|
262828
263451
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
262829
|
-
const absolutePath = normalize4(
|
|
263452
|
+
const absolutePath = normalize4(join75(memoryRoot, parsed.path));
|
|
262830
263453
|
const rel = relative8(memoryRoot, absolutePath);
|
|
262831
|
-
if (rel.startsWith("..") || rel === "" || isAbsolute25(rel) || rel.split(
|
|
263454
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute25(rel) || rel.split(sep8).includes("..")) {
|
|
262832
263455
|
sendFailure("write_memory_file: path must resolve inside the memory root");
|
|
262833
263456
|
return;
|
|
262834
263457
|
}
|
|
262835
|
-
if (!
|
|
263458
|
+
if (!existsSync51(join75(memoryRoot, ".git"))) {
|
|
262836
263459
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
262837
263460
|
if (!enabled) {
|
|
262838
263461
|
sendFailure("write_memory_file: memfs is not enabled for this agent");
|
|
262839
263462
|
return;
|
|
262840
263463
|
}
|
|
262841
263464
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
262842
|
-
if (!
|
|
263465
|
+
if (!existsSync51(join75(memoryRoot, ".git"))) {
|
|
262843
263466
|
sendFailure("write_memory_file: failed to initialize local memory checkout");
|
|
262844
263467
|
return;
|
|
262845
263468
|
}
|
|
@@ -262857,7 +263480,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
262857
263480
|
agentName = agent.name.trim();
|
|
262858
263481
|
}
|
|
262859
263482
|
} catch {}
|
|
262860
|
-
const pathspec = rel.split(
|
|
263483
|
+
const pathspec = rel.split(sep8).join("/");
|
|
262861
263484
|
const reason = parsed.commit_message?.trim() || `Update memory file ${pathspec}`;
|
|
262862
263485
|
const commitResult = await commitMemoryWrite2({
|
|
262863
263486
|
memoryDir: memoryRoot,
|
|
@@ -262917,34 +263540,34 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
262917
263540
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
262918
263541
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
262919
263542
|
const { unlink: unlink4 } = await import("node:fs/promises");
|
|
262920
|
-
const { existsSync:
|
|
262921
|
-
const { isAbsolute: isAbsolute25, join:
|
|
263543
|
+
const { existsSync: existsSync51 } = await import("node:fs");
|
|
263544
|
+
const { isAbsolute: isAbsolute25, join: join75, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
|
|
262922
263545
|
if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
|
|
262923
263546
|
sendFailure("delete_memory_file: path must be a non-empty relative path");
|
|
262924
263547
|
return;
|
|
262925
263548
|
}
|
|
262926
263549
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
262927
|
-
const absolutePath = normalize4(
|
|
263550
|
+
const absolutePath = normalize4(join75(memoryRoot, parsed.path));
|
|
262928
263551
|
const rel = relative8(memoryRoot, absolutePath);
|
|
262929
|
-
if (rel.startsWith("..") || rel === "" || isAbsolute25(rel) || rel.split(
|
|
263552
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute25(rel) || rel.split(sep8).includes("..")) {
|
|
262930
263553
|
sendFailure("delete_memory_file: path must resolve inside the memory root");
|
|
262931
263554
|
return;
|
|
262932
263555
|
}
|
|
262933
|
-
if (!
|
|
263556
|
+
if (!existsSync51(join75(memoryRoot, ".git"))) {
|
|
262934
263557
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
262935
263558
|
if (!enabled) {
|
|
262936
263559
|
sendFailure("delete_memory_file: memfs is not enabled for this agent");
|
|
262937
263560
|
return;
|
|
262938
263561
|
}
|
|
262939
263562
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
262940
|
-
if (!
|
|
263563
|
+
if (!existsSync51(join75(memoryRoot, ".git"))) {
|
|
262941
263564
|
sendFailure("delete_memory_file: failed to initialize local memory checkout");
|
|
262942
263565
|
return;
|
|
262943
263566
|
}
|
|
262944
263567
|
}
|
|
262945
|
-
const pathspec = rel.split(
|
|
263568
|
+
const pathspec = rel.split(sep8).join("/");
|
|
262946
263569
|
const removeIfPresent = async () => {
|
|
262947
|
-
if (!
|
|
263570
|
+
if (!existsSync51(absolutePath))
|
|
262948
263571
|
return false;
|
|
262949
263572
|
await unlink4(absolutePath);
|
|
262950
263573
|
return true;
|
|
@@ -263013,7 +263636,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
263013
263636
|
return false;
|
|
263014
263637
|
}
|
|
263015
263638
|
var warnMemoryCommand, WIKI_LINK_REGEX, IMAGE_MIME_BY_EXTENSION, MEMORY_PUSH_AWAIT_CAP_MS = 8000;
|
|
263016
|
-
var
|
|
263639
|
+
var init_memory6 = __esm(async () => {
|
|
263017
263640
|
init_error_reporting();
|
|
263018
263641
|
init_debug();
|
|
263019
263642
|
await init_protocol_inbound();
|
|
@@ -263118,12 +263741,12 @@ __export(exports_remote_model_catalog, {
|
|
|
263118
263741
|
applyCatalogModels: () => applyCatalogModels,
|
|
263119
263742
|
__testResetRemoteModelCatalog: () => __testResetRemoteModelCatalog
|
|
263120
263743
|
});
|
|
263121
|
-
import { existsSync as
|
|
263744
|
+
import { existsSync as existsSync51, mkdirSync as mkdirSync37, readFileSync as readFileSync42, writeFileSync as writeFileSync32 } from "node:fs";
|
|
263122
263745
|
import { homedir as homedir38 } from "node:os";
|
|
263123
|
-
import { dirname as dirname31, join as
|
|
263746
|
+
import { dirname as dirname31, join as join75 } from "node:path";
|
|
263124
263747
|
function catalogCachePath() {
|
|
263125
|
-
const dir = process.env.LETTA_MODEL_CATALOG_CACHE_DIR ||
|
|
263126
|
-
return
|
|
263748
|
+
const dir = process.env.LETTA_MODEL_CATALOG_CACHE_DIR || join75(homedir38(), ".letta", "cache");
|
|
263749
|
+
return join75(dir, "model-catalog.json");
|
|
263127
263750
|
}
|
|
263128
263751
|
function normalizeCatalogSource(source) {
|
|
263129
263752
|
try {
|
|
@@ -263222,10 +263845,10 @@ function persistCatalogCache(entries2, source) {
|
|
|
263222
263845
|
function loadPersistedModelCatalog(source) {
|
|
263223
263846
|
try {
|
|
263224
263847
|
const path33 = catalogCachePath();
|
|
263225
|
-
if (!
|
|
263848
|
+
if (!existsSync51(path33)) {
|
|
263226
263849
|
return false;
|
|
263227
263850
|
}
|
|
263228
|
-
const parsed = JSON.parse(
|
|
263851
|
+
const parsed = JSON.parse(readFileSync42(path33, "utf-8"));
|
|
263229
263852
|
if (parsed.schemaVersion !== CACHE_SCHEMA_VERSION || parsed.source !== normalizeCatalogSource(source) || !Array.isArray(parsed.models)) {
|
|
263230
263853
|
return false;
|
|
263231
263854
|
}
|
|
@@ -263911,7 +264534,7 @@ function recordStaleHandleUse(collector, owner, capability, onDiagnostic) {
|
|
|
263911
264534
|
var MOD_DIAGNOSTICS_MAX_COUNT = 200, MOD_DIAGNOSTICS_RESET_COUNT = 50, MOD_DYNAMIC_CONTEXT_MIGRATION_HINT = "Dynamic context is now passed as ctx to commands, tools, events, permissions, and UI renderers. Use ctx.agent, ctx.cwd, ctx.conversation, ctx.model, etc.", MOD_LETTA_GET_CONTEXT_MIGRATION_HINT = "letta.getContext has been removed. Activation has no dynamic invocation context. Move dynamic work into a command, tool, event, permission, status, or statusline callback that receives ctx, or use explicit/global state such as process.cwd() for activation-time background work.", MOD_CTX_GET_CONTEXT_MIGRATION_HINT = "ctx.getContext has been removed. Use ctx directly; scoped fields are available as ctx.agent, ctx.cwd, ctx.conversation, ctx.model, etc.", MOD_GENERIC_GET_CONTEXT_MIGRATION_HINT = "getContext helpers have been removed. If this is callback ctx, use ctx directly; if activation/background code needs runtime state, move it into a callback that receives ctx or use explicit/global state such as process.cwd().";
|
|
263912
264535
|
|
|
263913
264536
|
// src/mods/paths.ts
|
|
263914
|
-
import { existsSync as
|
|
264537
|
+
import { existsSync as existsSync52 } from "node:fs";
|
|
263915
264538
|
import { homedir as homedir39 } from "node:os";
|
|
263916
264539
|
import path33 from "node:path";
|
|
263917
264540
|
function getGlobalModsDirectory(homeDirectory = homedir39()) {
|
|
@@ -263925,10 +264548,10 @@ function resolveDefaultGlobalModsDirectory(homeDirectory = homedir39(), env6 = p
|
|
|
263925
264548
|
if (environmentDirectory)
|
|
263926
264549
|
return environmentDirectory;
|
|
263927
264550
|
const modsDirectory = getGlobalModsDirectory(homeDirectory);
|
|
263928
|
-
if (
|
|
264551
|
+
if (existsSync52(modsDirectory))
|
|
263929
264552
|
return modsDirectory;
|
|
263930
264553
|
const legacyDirectory = getLegacyGlobalExtensionsDirectory(homeDirectory);
|
|
263931
|
-
if (
|
|
264554
|
+
if (existsSync52(legacyDirectory))
|
|
263932
264555
|
return legacyDirectory;
|
|
263933
264556
|
return modsDirectory;
|
|
263934
264557
|
}
|
|
@@ -272078,7 +272701,7 @@ ${lanes.join(`
|
|
|
272078
272701
|
return process.memoryUsage().heapUsed;
|
|
272079
272702
|
},
|
|
272080
272703
|
getFileSize(path35) {
|
|
272081
|
-
const stat12 =
|
|
272704
|
+
const stat12 = statSync20(path35);
|
|
272082
272705
|
if (stat12 == null ? undefined : stat12.isFile()) {
|
|
272083
272706
|
return stat12.size;
|
|
272084
272707
|
}
|
|
@@ -272121,7 +272744,7 @@ ${lanes.join(`
|
|
|
272121
272744
|
}
|
|
272122
272745
|
};
|
|
272123
272746
|
return nodeSystem;
|
|
272124
|
-
function
|
|
272747
|
+
function statSync20(path35) {
|
|
272125
272748
|
try {
|
|
272126
272749
|
return _fs.statSync(path35, statSyncOptions);
|
|
272127
272750
|
} catch {
|
|
@@ -272173,7 +272796,7 @@ ${lanes.join(`
|
|
|
272173
272796
|
activeSession.post("Profiler.stop", (err, { profile }) => {
|
|
272174
272797
|
var _a10;
|
|
272175
272798
|
if (!err) {
|
|
272176
|
-
if ((_a10 =
|
|
272799
|
+
if ((_a10 = statSync20(profilePath)) == null ? undefined : _a10.isDirectory()) {
|
|
272177
272800
|
profilePath = _path.join(profilePath, `${(/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-")}+P${process.pid}.cpuprofile`);
|
|
272178
272801
|
}
|
|
272179
272802
|
try {
|
|
@@ -272282,7 +272905,7 @@ ${lanes.join(`
|
|
|
272282
272905
|
let stat12;
|
|
272283
272906
|
if (typeof dirent === "string" || dirent.isSymbolicLink()) {
|
|
272284
272907
|
const name = combinePaths(path35, entry);
|
|
272285
|
-
stat12 =
|
|
272908
|
+
stat12 = statSync20(name);
|
|
272286
272909
|
if (!stat12) {
|
|
272287
272910
|
continue;
|
|
272288
272911
|
}
|
|
@@ -272306,7 +272929,7 @@ ${lanes.join(`
|
|
|
272306
272929
|
return matchFiles(path35, extensions, excludes, includes2, useCaseSensitiveFileNames2, process.cwd(), depth, getAccessibleFileSystemEntries, realpath6);
|
|
272307
272930
|
}
|
|
272308
272931
|
function fileSystemEntryExists(path35, entryKind) {
|
|
272309
|
-
const stat12 =
|
|
272932
|
+
const stat12 = statSync20(path35);
|
|
272310
272933
|
if (!stat12) {
|
|
272311
272934
|
return false;
|
|
272312
272935
|
}
|
|
@@ -272340,7 +272963,7 @@ ${lanes.join(`
|
|
|
272340
272963
|
}
|
|
272341
272964
|
function getModifiedTime3(path35) {
|
|
272342
272965
|
var _a10;
|
|
272343
|
-
return (_a10 =
|
|
272966
|
+
return (_a10 = statSync20(path35)) == null ? undefined : _a10.mtime;
|
|
272344
272967
|
}
|
|
272345
272968
|
function setModifiedTime(path35, time3) {
|
|
272346
272969
|
try {
|
|
@@ -295182,7 +295805,7 @@ ${lanes.join(`
|
|
|
295182
295805
|
var contextFlags;
|
|
295183
295806
|
var topLevel = true;
|
|
295184
295807
|
var parseErrorBeforeNextFinishedNode = false;
|
|
295185
|
-
function
|
|
295808
|
+
function parseSourceFile2(fileName2, sourceText2, languageVersion2, syntaxCursor2, setParentNodes = false, scriptKind2, setExternalModuleIndicatorOverride, jsDocParsingMode = 0) {
|
|
295186
295809
|
var _a10;
|
|
295187
295810
|
scriptKind2 = ensureScriptKind(fileName2, scriptKind2);
|
|
295188
295811
|
if (scriptKind2 === 6) {
|
|
@@ -295201,7 +295824,7 @@ ${lanes.join(`
|
|
|
295201
295824
|
clearState();
|
|
295202
295825
|
return result3;
|
|
295203
295826
|
}
|
|
295204
|
-
Parser22.parseSourceFile =
|
|
295827
|
+
Parser22.parseSourceFile = parseSourceFile2;
|
|
295205
295828
|
function parseIsolatedEntityName2(content, languageVersion2) {
|
|
295206
295829
|
initializeState("", content, languageVersion2, undefined, 1, 0);
|
|
295207
295830
|
nextToken();
|
|
@@ -305466,11 +306089,11 @@ ${lanes.join(`
|
|
|
305466
306089
|
if (i4 < rootLength) {
|
|
305467
306090
|
return;
|
|
305468
306091
|
}
|
|
305469
|
-
const
|
|
305470
|
-
if (
|
|
306092
|
+
const sep8 = directory.lastIndexOf(directorySeparator, i4 - 1);
|
|
306093
|
+
if (sep8 === -1) {
|
|
305471
306094
|
return;
|
|
305472
306095
|
}
|
|
305473
|
-
return directory.substr(0, Math.max(
|
|
306096
|
+
return directory.substr(0, Math.max(sep8, rootLength));
|
|
305474
306097
|
}
|
|
305475
306098
|
}
|
|
305476
306099
|
}
|
|
@@ -432746,7 +433369,7 @@ function createModChangeBatcher(onChange) {
|
|
|
432746
433369
|
}
|
|
432747
433370
|
|
|
432748
433371
|
// src/mods/package-manifest.ts
|
|
432749
|
-
import { readFileSync as
|
|
433372
|
+
import { readFileSync as readFileSync43 } from "node:fs";
|
|
432750
433373
|
import path35 from "node:path";
|
|
432751
433374
|
function isRecord15(value) {
|
|
432752
433375
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -432956,7 +433579,7 @@ function parseLettaPackageManifest(packageJson) {
|
|
|
432956
433579
|
}
|
|
432957
433580
|
function readLettaPackageManifest(packageJsonPath) {
|
|
432958
433581
|
try {
|
|
432959
|
-
const packageJson = JSON.parse(
|
|
433582
|
+
const packageJson = JSON.parse(readFileSync43(packageJsonPath, "utf8"));
|
|
432960
433583
|
return parseLettaPackageManifest(packageJson);
|
|
432961
433584
|
} catch (error5) {
|
|
432962
433585
|
return {
|
|
@@ -432986,9 +433609,9 @@ var init_package_manifest = __esm(() => {
|
|
|
432986
433609
|
|
|
432987
433610
|
// src/mods/package-registry.ts
|
|
432988
433611
|
import {
|
|
432989
|
-
existsSync as
|
|
433612
|
+
existsSync as existsSync53,
|
|
432990
433613
|
mkdirSync as mkdirSync39,
|
|
432991
|
-
readFileSync as
|
|
433614
|
+
readFileSync as readFileSync44,
|
|
432992
433615
|
rmSync as rmSync20,
|
|
432993
433616
|
writeFileSync as writeFileSync34
|
|
432994
433617
|
} from "node:fs";
|
|
@@ -433044,7 +433667,7 @@ function parseJsonFile(filePath) {
|
|
|
433044
433667
|
try {
|
|
433045
433668
|
return {
|
|
433046
433669
|
ok: true,
|
|
433047
|
-
value: JSON.parse(
|
|
433670
|
+
value: JSON.parse(readFileSync44(filePath, "utf8"))
|
|
433048
433671
|
};
|
|
433049
433672
|
} catch (error5) {
|
|
433050
433673
|
return {
|
|
@@ -433058,7 +433681,7 @@ function getRegistryPath(modsRoot) {
|
|
|
433058
433681
|
}
|
|
433059
433682
|
function readRegistryObject(modsRoot) {
|
|
433060
433683
|
const registryPath = getRegistryPath(modsRoot);
|
|
433061
|
-
if (!
|
|
433684
|
+
if (!existsSync53(registryPath)) {
|
|
433062
433685
|
return { diagnostics: [], ok: false, registryExists: false, registryPath };
|
|
433063
433686
|
}
|
|
433064
433687
|
const registryResult = parseJsonFile(registryPath);
|
|
@@ -433490,7 +434113,7 @@ function writePackageRegistry(registryPath, registry4) {
|
|
|
433490
434113
|
}
|
|
433491
434114
|
function validateManagedModPackageRegistryForMutation(modsRoot) {
|
|
433492
434115
|
const registryPath = getRegistryPath(modsRoot);
|
|
433493
|
-
const contents =
|
|
434116
|
+
const contents = existsSync53(registryPath) ? readFileSync44(registryPath, "utf8") : null;
|
|
433494
434117
|
const registry4 = readMutablePackageRegistry(modsRoot, {
|
|
433495
434118
|
createIfMissing: true
|
|
433496
434119
|
});
|
|
@@ -433613,12 +434236,12 @@ var init_package_registry = __esm(() => {
|
|
|
433613
434236
|
});
|
|
433614
434237
|
|
|
433615
434238
|
// src/mods/mod-sources.ts
|
|
433616
|
-
import { existsSync as
|
|
434239
|
+
import { existsSync as existsSync54, readdirSync as readdirSync21 } from "node:fs";
|
|
433617
434240
|
import path37 from "node:path";
|
|
433618
434241
|
function listModFiles(directory) {
|
|
433619
|
-
if (!
|
|
434242
|
+
if (!existsSync54(directory))
|
|
433620
434243
|
return [];
|
|
433621
|
-
return
|
|
434244
|
+
return readdirSync21(directory, { withFileTypes: true }).filter((entry) => {
|
|
433622
434245
|
if (!entry.isFile())
|
|
433623
434246
|
return false;
|
|
433624
434247
|
if (entry.name.startsWith("."))
|
|
@@ -433632,7 +434255,7 @@ function resolveLocalModSources(options = {}) {
|
|
|
433632
434255
|
const includeGlobalMods = options.includeGlobalMods !== false;
|
|
433633
434256
|
const managedPackages = includeGlobalMods ? resolveManagedModPackages(globalModsDirectory) : { diagnostics: [], files: [], packages: [] };
|
|
433634
434257
|
const sources = [];
|
|
433635
|
-
if (includeGlobalMods && legacyGlobalExtensionsDirectory && path37.resolve(legacyGlobalExtensionsDirectory) !== path37.resolve(globalModsDirectory) &&
|
|
434258
|
+
if (includeGlobalMods && legacyGlobalExtensionsDirectory && path37.resolve(legacyGlobalExtensionsDirectory) !== path37.resolve(globalModsDirectory) && existsSync54(legacyGlobalExtensionsDirectory)) {
|
|
433636
434259
|
sources.push({
|
|
433637
434260
|
files: listModFiles(legacyGlobalExtensionsDirectory),
|
|
433638
434261
|
legacyMigrationTargetRoot: globalModsDirectory,
|
|
@@ -433811,11 +434434,11 @@ function createNoopModPanelHandle() {
|
|
|
433811
434434
|
// src/mods/mod-engine.ts
|
|
433812
434435
|
import { createHash as createHash12 } from "node:crypto";
|
|
433813
434436
|
import {
|
|
433814
|
-
existsSync as
|
|
434437
|
+
existsSync as existsSync55,
|
|
433815
434438
|
mkdirSync as mkdirSync41,
|
|
433816
|
-
readdirSync as
|
|
433817
|
-
readFileSync as
|
|
433818
|
-
statSync as
|
|
434439
|
+
readdirSync as readdirSync22,
|
|
434440
|
+
readFileSync as readFileSync45,
|
|
434441
|
+
statSync as statSync20,
|
|
433819
434442
|
unlinkSync as unlinkSync13,
|
|
433820
434443
|
writeFileSync as writeFileSync35
|
|
433821
434444
|
} from "node:fs";
|
|
@@ -433990,7 +434613,7 @@ function prepareModForImport(modPath, source) {
|
|
|
433990
434613
|
}
|
|
433991
434614
|
function createImportableModPath(modPath, cacheDirectory, source) {
|
|
433992
434615
|
const importCacheDirectory = getManagedPackageImportCacheDirectory(modPath, source) ?? cacheDirectory;
|
|
433993
|
-
const sourceText =
|
|
434616
|
+
const sourceText = readFileSync45(modPath, "utf8");
|
|
433994
434617
|
const hash3 = createHash12("sha256").update(sourceText).digest("hex").slice(0, 16);
|
|
433995
434618
|
const fileExtension = path39.extname(modPath);
|
|
433996
434619
|
const importableSource = prepareModForImport(modPath, sourceText);
|
|
@@ -434001,11 +434624,11 @@ function createImportableModPath(modPath, cacheDirectory, source) {
|
|
|
434001
434624
|
}
|
|
434002
434625
|
const baseName = path39.basename(modPath, fileExtension).replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
434003
434626
|
const importPath = path39.join(importCacheDirectory, `.letta-mod-${baseName}-${hash3}.mjs`);
|
|
434004
|
-
if (!
|
|
434627
|
+
if (!existsSync55(importPath)) {
|
|
434005
434628
|
writeFileSync35(importPath, importableSource, "utf8");
|
|
434006
434629
|
}
|
|
434007
434630
|
try {
|
|
434008
|
-
for (const entry of
|
|
434631
|
+
for (const entry of readdirSync22(importCacheDirectory)) {
|
|
434009
434632
|
if (entry.startsWith(`.letta-mod-${baseName}-`) && entry !== path39.basename(importPath)) {
|
|
434010
434633
|
unlinkSync13(path39.join(importCacheDirectory, entry));
|
|
434011
434634
|
}
|
|
@@ -434644,8 +435267,8 @@ async function loadLocalMods(options) {
|
|
|
434644
435267
|
recordLegacyExtensionLoadedDiagnostic(registry4, owner, source, options.onDiagnostic);
|
|
434645
435268
|
}
|
|
434646
435269
|
try {
|
|
434647
|
-
const mtimeMs =
|
|
434648
|
-
const sourceText =
|
|
435270
|
+
const mtimeMs = statSync20(modPath).mtimeMs;
|
|
435271
|
+
const sourceText = readFileSync45(modPath, "utf8");
|
|
434649
435272
|
recordDeprecatedContextApiSourceDiagnostics(sourceText, (diagnostic) => {
|
|
434650
435273
|
recordModDiagnostic(registry4, {
|
|
434651
435274
|
...diagnostic,
|
|
@@ -435167,7 +435790,7 @@ var init_memfs_sync = __esm(() => {
|
|
|
435167
435790
|
|
|
435168
435791
|
// src/websocket/listener/mod-adapter.ts
|
|
435169
435792
|
import { createHash as createHash13 } from "node:crypto";
|
|
435170
|
-
import { join as
|
|
435793
|
+
import { join as join76 } from "node:path";
|
|
435171
435794
|
async function getUnavailableListenerClient() {
|
|
435172
435795
|
throw new Error("letta.client is not available in listener mods");
|
|
435173
435796
|
}
|
|
@@ -435243,14 +435866,14 @@ function ensureListenerModAdapter(runtime) {
|
|
|
435243
435866
|
}
|
|
435244
435867
|
function resolveListenerAgentModsDirectory(agentId) {
|
|
435245
435868
|
try {
|
|
435246
|
-
return settingsManager.isMemfsEnabled(agentId) ?
|
|
435869
|
+
return settingsManager.isMemfsEnabled(agentId) ? join76(getScopedMemoryFilesystemRoot(agentId), "mods") : null;
|
|
435247
435870
|
} catch {
|
|
435248
435871
|
return null;
|
|
435249
435872
|
}
|
|
435250
435873
|
}
|
|
435251
435874
|
function resolveListenerAgentModCacheDirectory(agentId) {
|
|
435252
435875
|
const cacheKey = createHash13("sha256").update(agentId).digest("hex");
|
|
435253
|
-
return
|
|
435876
|
+
return join76(getModCacheDirectory(), "listener-agents", cacheKey);
|
|
435254
435877
|
}
|
|
435255
435878
|
async function ensureListenerAgentModAdapter(runtime, agentId) {
|
|
435256
435879
|
runtime.agentModAdapters ??= new Map;
|
|
@@ -436790,7 +437413,8 @@ function finishClaimedTeleport(runtime, pending, commit, options = {}) {
|
|
|
436790
437413
|
agentId: pending.agentId,
|
|
436791
437414
|
conversationId: pending.conversationId,
|
|
436792
437415
|
persistTerminalWithoutConsumers: intentRevision !== undefined,
|
|
436793
|
-
expectedInterruptedRevision: intentRevision
|
|
437416
|
+
expectedInterruptedRevision: intentRevision,
|
|
437417
|
+
teleportHandoff: pending.activeTurn
|
|
436794
437418
|
});
|
|
436795
437419
|
} catch (error5) {
|
|
436796
437420
|
abandonTeleportIntent(runtime.listener, pending, intentRevision);
|
|
@@ -437407,19 +438031,19 @@ function emitSkillsUpdated(socket, safeSocketSend) {
|
|
|
437407
438031
|
}
|
|
437408
438032
|
async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
437409
438033
|
const {
|
|
437410
|
-
existsSync:
|
|
438034
|
+
existsSync: existsSync56,
|
|
437411
438035
|
lstatSync: lstatSync3,
|
|
437412
438036
|
mkdirSync: mkdirSync42,
|
|
437413
438037
|
rmdirSync: rmdirSync2,
|
|
437414
438038
|
symlinkSync: symlinkSync2,
|
|
437415
438039
|
unlinkSync: unlinkSync14
|
|
437416
438040
|
} = await import("node:fs");
|
|
437417
|
-
const { basename: basename21, join:
|
|
437418
|
-
const lettaHome = process.env.LETTA_HOME ||
|
|
437419
|
-
const globalSkillsDir =
|
|
438041
|
+
const { basename: basename21, join: join77 } = await import("node:path");
|
|
438042
|
+
const lettaHome = process.env.LETTA_HOME || join77(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
|
|
438043
|
+
const globalSkillsDir = join77(lettaHome, "skills");
|
|
437420
438044
|
if (parsed.type === "skill_enable") {
|
|
437421
438045
|
try {
|
|
437422
|
-
if (!
|
|
438046
|
+
if (!existsSync56(parsed.skill_path)) {
|
|
437423
438047
|
safeSocketSend(socket, {
|
|
437424
438048
|
type: "skill_enable_response",
|
|
437425
438049
|
request_id: parsed.request_id,
|
|
@@ -437428,8 +438052,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
437428
438052
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
437429
438053
|
return true;
|
|
437430
438054
|
}
|
|
437431
|
-
const skillMdPath =
|
|
437432
|
-
if (!
|
|
438055
|
+
const skillMdPath = join77(parsed.skill_path, "SKILL.md");
|
|
438056
|
+
if (!existsSync56(skillMdPath)) {
|
|
437433
438057
|
safeSocketSend(socket, {
|
|
437434
438058
|
type: "skill_enable_response",
|
|
437435
438059
|
request_id: parsed.request_id,
|
|
@@ -437439,9 +438063,9 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
437439
438063
|
return true;
|
|
437440
438064
|
}
|
|
437441
438065
|
const linkName = basename21(parsed.skill_path);
|
|
437442
|
-
const linkPath =
|
|
438066
|
+
const linkPath = join77(globalSkillsDir, linkName);
|
|
437443
438067
|
mkdirSync42(globalSkillsDir, { recursive: true });
|
|
437444
|
-
if (
|
|
438068
|
+
if (existsSync56(linkPath)) {
|
|
437445
438069
|
const stat12 = lstatSync3(linkPath);
|
|
437446
438070
|
if (stat12.isSymbolicLink()) {
|
|
437447
438071
|
if (process.platform === "win32") {
|
|
@@ -437482,8 +438106,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
437482
438106
|
}
|
|
437483
438107
|
if (parsed.type === "skill_disable") {
|
|
437484
438108
|
try {
|
|
437485
|
-
const linkPath =
|
|
437486
|
-
if (!
|
|
438109
|
+
const linkPath = join77(globalSkillsDir, parsed.name);
|
|
438110
|
+
if (!existsSync56(linkPath)) {
|
|
437487
438111
|
safeSocketSend(socket, {
|
|
437488
438112
|
type: "skill_disable_response",
|
|
437489
438113
|
request_id: parsed.request_id,
|
|
@@ -438403,7 +439027,7 @@ var init_control_inputs = __esm(async () => {
|
|
|
438403
439027
|
});
|
|
438404
439028
|
|
|
438405
439029
|
// src/websocket/terminal-handler.ts
|
|
438406
|
-
import { existsSync as
|
|
439030
|
+
import { existsSync as existsSync56 } from "node:fs";
|
|
438407
439031
|
import * as os7 from "node:os";
|
|
438408
439032
|
import WebSocket6 from "ws";
|
|
438409
439033
|
function getTerminalKey(connectionId, terminalId) {
|
|
@@ -438419,7 +439043,7 @@ function getDefaultShell() {
|
|
|
438419
439043
|
"/bin/bash"
|
|
438420
439044
|
];
|
|
438421
439045
|
for (const candidate of candidates2) {
|
|
438422
|
-
if (candidate &&
|
|
439046
|
+
if (candidate && existsSync56(candidate)) {
|
|
438423
439047
|
return candidate;
|
|
438424
439048
|
}
|
|
438425
439049
|
}
|
|
@@ -440373,14 +440997,14 @@ var init_tui_perf = __esm(() => {
|
|
|
440373
440997
|
|
|
440374
440998
|
// src/cli/helpers/chunk-log.ts
|
|
440375
440999
|
import {
|
|
440376
|
-
existsSync as
|
|
441000
|
+
existsSync as existsSync57,
|
|
440377
441001
|
mkdirSync as mkdirSync43,
|
|
440378
|
-
readdirSync as
|
|
441002
|
+
readdirSync as readdirSync23,
|
|
440379
441003
|
unlinkSync as unlinkSync14,
|
|
440380
441004
|
writeFileSync as writeFileSync36
|
|
440381
441005
|
} from "node:fs";
|
|
440382
441006
|
import { homedir as homedir41 } from "node:os";
|
|
440383
|
-
import { join as
|
|
441007
|
+
import { join as join77 } from "node:path";
|
|
440384
441008
|
function truncateStr(value, maxLen) {
|
|
440385
441009
|
if (value === null || value === undefined)
|
|
440386
441010
|
return "";
|
|
@@ -440444,8 +441068,8 @@ class ChunkLog {
|
|
|
440444
441068
|
agentDir = null;
|
|
440445
441069
|
dirCreated = false;
|
|
440446
441070
|
init(agentId, sessionId) {
|
|
440447
|
-
this.agentDir =
|
|
440448
|
-
this.logPath =
|
|
441071
|
+
this.agentDir = join77(LOG_BASE_DIR, agentId);
|
|
441072
|
+
this.logPath = join77(this.agentDir, `${sessionId}.jsonl`);
|
|
440449
441073
|
this.buffer = [];
|
|
440450
441074
|
this.dirty = false;
|
|
440451
441075
|
this.dirCreated = false;
|
|
@@ -440474,7 +441098,7 @@ class ChunkLog {
|
|
|
440474
441098
|
if (this.dirCreated || !this.agentDir)
|
|
440475
441099
|
return;
|
|
440476
441100
|
try {
|
|
440477
|
-
if (!
|
|
441101
|
+
if (!existsSync57(this.agentDir)) {
|
|
440478
441102
|
mkdirSync43(this.agentDir, { recursive: true });
|
|
440479
441103
|
}
|
|
440480
441104
|
this.dirCreated = true;
|
|
@@ -440499,14 +441123,14 @@ class ChunkLog {
|
|
|
440499
441123
|
if (!this.agentDir)
|
|
440500
441124
|
return;
|
|
440501
441125
|
try {
|
|
440502
|
-
if (!
|
|
441126
|
+
if (!existsSync57(this.agentDir))
|
|
440503
441127
|
return;
|
|
440504
|
-
const files =
|
|
441128
|
+
const files = readdirSync23(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
|
|
440505
441129
|
if (files.length >= MAX_SESSION_FILES2) {
|
|
440506
441130
|
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES2 + 1);
|
|
440507
441131
|
for (const file of toDelete) {
|
|
440508
441132
|
try {
|
|
440509
|
-
unlinkSync14(
|
|
441133
|
+
unlinkSync14(join77(this.agentDir, file));
|
|
440510
441134
|
} catch (e2) {
|
|
440511
441135
|
debugWarn("chunkLog", `Failed to delete old session log ${file}: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
440512
441136
|
}
|
|
@@ -440520,7 +441144,7 @@ class ChunkLog {
|
|
|
440520
441144
|
var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES2 = 5, LOG_BASE_DIR, chunkLog;
|
|
440521
441145
|
var init_chunk_log = __esm(() => {
|
|
440522
441146
|
init_debug();
|
|
440523
|
-
LOG_BASE_DIR =
|
|
441147
|
+
LOG_BASE_DIR = join77(homedir41(), ".letta", "logs", "chunk-logs");
|
|
440524
441148
|
chunkLog = new ChunkLog;
|
|
440525
441149
|
});
|
|
440526
441150
|
|
|
@@ -441904,7 +442528,7 @@ function finishListenerTurn(runtime, lease, options) {
|
|
|
441904
442528
|
type: "turn_finished",
|
|
441905
442529
|
turn_id: options.turnId,
|
|
441906
442530
|
stop_reason: options.stopReason,
|
|
441907
|
-
...options.terminalConsumerIds?.length ? {
|
|
442531
|
+
...options.terminalConsumerIds?.length && !options.teleportHandoff ? {
|
|
441908
442532
|
terminal_consumer_ids: [
|
|
441909
442533
|
...new Set(options.terminalConsumerIds)
|
|
441910
442534
|
]
|
|
@@ -442029,7 +442653,7 @@ function finishListenerTurn(runtime, lease, options) {
|
|
|
442029
442653
|
conversation_id: options.conversationId
|
|
442030
442654
|
});
|
|
442031
442655
|
}
|
|
442032
|
-
if (mayEmit && options.socket && turnFinishedMessage && preparedTurnFinished) {
|
|
442656
|
+
if (mayEmit && options.socket && turnFinishedMessage && preparedTurnFinished && !options.teleportHandoff) {
|
|
442033
442657
|
emitDurableTurnFinished(options.socket, runtime, turnFinishedMessage, TO_SUBSCRIBERS, options.turnFinishedStore, preparedTurnFinished);
|
|
442034
442658
|
}
|
|
442035
442659
|
if (options.stopReason === "end_turn" || options.stopReason === "cancelled" && transition2.interruptionCause !== "transport") {
|
|
@@ -446547,8 +447171,8 @@ var init_turn_approval = __esm(async () => {
|
|
|
446547
447171
|
});
|
|
446548
447172
|
|
|
446549
447173
|
// src/agent/attached-repository-git-sync.ts
|
|
446550
|
-
import { existsSync as
|
|
446551
|
-
import { join as
|
|
447174
|
+
import { existsSync as existsSync58 } from "node:fs";
|
|
447175
|
+
import { join as join78 } from "node:path";
|
|
446552
447176
|
async function getPendingCommitCount(path42) {
|
|
446553
447177
|
const divergence = await getMemoryAheadBehind(path42);
|
|
446554
447178
|
if (divergence) {
|
|
@@ -446578,7 +447202,7 @@ async function syncPendingAttachedRepositoryCommitsUnlocked(params) {
|
|
|
446578
447202
|
path: path42,
|
|
446579
447203
|
permissions: params.repository.permissions ?? "unknown"
|
|
446580
447204
|
};
|
|
446581
|
-
if (!
|
|
447205
|
+
if (!existsSync58(join78(path42, ".git"))) {
|
|
446582
447206
|
return {
|
|
446583
447207
|
...resultBase,
|
|
446584
447208
|
status: "skipped",
|
|
@@ -446748,8 +447372,8 @@ var init_attached_repository_git_sync = __esm(() => {
|
|
|
446748
447372
|
});
|
|
446749
447373
|
|
|
446750
447374
|
// src/reminders/memory-git-sync.ts
|
|
446751
|
-
import { existsSync as
|
|
446752
|
-
import { join as
|
|
447375
|
+
import { existsSync as existsSync59 } from "node:fs";
|
|
447376
|
+
import { join as join79 } from "node:path";
|
|
446753
447377
|
function formatMemoryRepairInProgressReminder(result3) {
|
|
446754
447378
|
return `${SYSTEM_REMINDER_OPEN}
|
|
446755
447379
|
MEMORY REPAIR RUNNING: A background worker is repairing the memory repository.
|
|
@@ -446859,7 +447483,7 @@ async function runPostTurnMemorySync(params, dependencies4 = {}) {
|
|
|
446859
447483
|
if (memorySyncEnabled) {
|
|
446860
447484
|
try {
|
|
446861
447485
|
const memoryDir = getScopedMemoryFilesystemRoot(params.agentId);
|
|
446862
|
-
const release =
|
|
447486
|
+
const release = existsSync59(join79(memoryDir, ".git")) ? await (dependencies4.claimOperation ?? claimMemoryOperation)(memoryDir) : undefined;
|
|
446863
447487
|
if (release !== null) {
|
|
446864
447488
|
try {
|
|
446865
447489
|
const result3 = await syncMemory(params.agentId);
|
|
@@ -449098,7 +449722,7 @@ var init_core5 = __esm(() => {
|
|
|
449098
449722
|
import { spawn as spawn10 } from "node:child_process";
|
|
449099
449723
|
import { accessSync as accessSync2, constants as constants6 } from "node:fs";
|
|
449100
449724
|
import { homedir as homedir42 } from "node:os";
|
|
449101
|
-
import { join as
|
|
449725
|
+
import { join as join80 } from "node:path";
|
|
449102
449726
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
449103
449727
|
async function normalizeCheckpoint(input) {
|
|
449104
449728
|
const { decoded, bounds, filters } = await decodeCheckpoint(input);
|
|
@@ -449122,7 +449746,7 @@ async function decodeCheckpoint(input) {
|
|
|
449122
449746
|
}
|
|
449123
449747
|
async function loadDeepAgentsCheckpoint(checkpoint) {
|
|
449124
449748
|
validateLocation(checkpoint);
|
|
449125
|
-
const path42 = checkpoint.path ??
|
|
449749
|
+
const path42 = checkpoint.path ?? join80(homedir42(), ".deepagents", "sessions.db");
|
|
449126
449750
|
const python = checkpoint.pythonExecutable ?? process.env.PYTHON ?? "python3";
|
|
449127
449751
|
const helper = resolveHelperPath();
|
|
449128
449752
|
return await new Promise((resolve39, reject2) => {
|
|
@@ -449341,8 +449965,8 @@ var init_deepagents = __esm(() => {
|
|
|
449341
449965
|
});
|
|
449342
449966
|
|
|
449343
449967
|
// node_modules/@letta-ai/trajectory/dist/adapters/listing-shared.js
|
|
449344
|
-
import { readdirSync as
|
|
449345
|
-
import { join as
|
|
449968
|
+
import { readdirSync as readdirSync24, statSync as statSync21 } from "node:fs";
|
|
449969
|
+
import { join as join81 } from "node:path";
|
|
449346
449970
|
function sortListings(items3) {
|
|
449347
449971
|
return items3.sort((left, right) => {
|
|
449348
449972
|
const l3 = left.updatedAt ?? "";
|
|
@@ -449354,7 +449978,7 @@ function sortListings(items3) {
|
|
|
449354
449978
|
}
|
|
449355
449979
|
function safeReadDir(path42) {
|
|
449356
449980
|
try {
|
|
449357
|
-
return
|
|
449981
|
+
return readdirSync24(path42, { withFileTypes: true }).map((entry) => ({
|
|
449358
449982
|
name: entry.name,
|
|
449359
449983
|
isDirectory: entry.isDirectory(),
|
|
449360
449984
|
isFile: entry.isFile()
|
|
@@ -449365,7 +449989,7 @@ function safeReadDir(path42) {
|
|
|
449365
449989
|
}
|
|
449366
449990
|
function safeStat(path42) {
|
|
449367
449991
|
try {
|
|
449368
|
-
const stats =
|
|
449992
|
+
const stats = statSync21(path42);
|
|
449369
449993
|
return { mtimeMs: stats.mtimeMs, sizeBytes: stats.size };
|
|
449370
449994
|
} catch {
|
|
449371
449995
|
return;
|
|
@@ -449387,7 +450011,7 @@ function collectFiles(root2, extension, depth) {
|
|
|
449387
450011
|
return [];
|
|
449388
450012
|
const collected = [];
|
|
449389
450013
|
for (const entry of safeReadDir(root2)) {
|
|
449390
|
-
const full =
|
|
450014
|
+
const full = join81(root2, entry.name);
|
|
449391
450015
|
if (entry.isFile && entry.name.endsWith(extension)) {
|
|
449392
450016
|
collected.push(full);
|
|
449393
450017
|
} else if (entry.isDirectory) {
|
|
@@ -449472,18 +450096,18 @@ var init_listing_shared = __esm(() => {
|
|
|
449472
450096
|
|
|
449473
450097
|
// node_modules/@letta-ai/trajectory/dist/adapters/claude-code/list.js
|
|
449474
450098
|
import { homedir as homedir43 } from "node:os";
|
|
449475
|
-
import { basename as basename23, join as
|
|
450099
|
+
import { basename as basename23, join as join82 } from "node:path";
|
|
449476
450100
|
async function listClaudeCodeTrajectories(root2) {
|
|
449477
|
-
const base2 = root2 ??
|
|
450101
|
+
const base2 = root2 ?? join82(homedir43(), ".claude", "projects");
|
|
449478
450102
|
const items3 = [];
|
|
449479
450103
|
for (const project of safeReadDir(base2)) {
|
|
449480
450104
|
if (!project.isDirectory)
|
|
449481
450105
|
continue;
|
|
449482
|
-
const projectPath =
|
|
450106
|
+
const projectPath = join82(base2, project.name);
|
|
449483
450107
|
for (const entry of safeReadDir(projectPath)) {
|
|
449484
450108
|
if (!entry.isFile || !entry.name.endsWith(".jsonl"))
|
|
449485
450109
|
continue;
|
|
449486
|
-
const path42 =
|
|
450110
|
+
const path42 = join82(projectPath, entry.name);
|
|
449487
450111
|
const listing = listingFromFile(basename23(entry.name, ".jsonl"), path42);
|
|
449488
450112
|
if (listing)
|
|
449489
450113
|
items3.push(listing);
|
|
@@ -449497,9 +450121,9 @@ var init_list = __esm(() => {
|
|
|
449497
450121
|
|
|
449498
450122
|
// node_modules/@letta-ai/trajectory/dist/adapters/codex/list.js
|
|
449499
450123
|
import { homedir as homedir44 } from "node:os";
|
|
449500
|
-
import { basename as basename24, join as
|
|
450124
|
+
import { basename as basename24, join as join83 } from "node:path";
|
|
449501
450125
|
async function listCodexTrajectories(root2) {
|
|
449502
|
-
const base2 = root2 ??
|
|
450126
|
+
const base2 = root2 ?? join83(homedir44(), ".codex", "sessions");
|
|
449503
450127
|
const items3 = [];
|
|
449504
450128
|
for (const path42 of collectFiles(base2, ".jsonl", 4)) {
|
|
449505
450129
|
const listing = listingFromFile(basename24(path42, ".jsonl"), path42);
|
|
@@ -449514,7 +450138,7 @@ var init_list2 = __esm(() => {
|
|
|
449514
450138
|
|
|
449515
450139
|
// node_modules/@letta-ai/trajectory/dist/adapters/deepagents/list.js
|
|
449516
450140
|
import { homedir as homedir45 } from "node:os";
|
|
449517
|
-
import { join as
|
|
450141
|
+
import { join as join84 } from "node:path";
|
|
449518
450142
|
async function listDeepAgentsTrajectories(root2) {
|
|
449519
450143
|
const path42 = resolveStorePath(root2);
|
|
449520
450144
|
if (!safeStat(path42))
|
|
@@ -449535,8 +450159,8 @@ async function listDeepAgentsTrajectories(root2) {
|
|
|
449535
450159
|
}
|
|
449536
450160
|
function resolveStorePath(root2) {
|
|
449537
450161
|
if (root2 === undefined)
|
|
449538
|
-
return
|
|
449539
|
-
return root2.endsWith(".db") ? root2 :
|
|
450162
|
+
return join84(homedir45(), ".deepagents", "sessions.db");
|
|
450163
|
+
return root2.endsWith(".db") ? root2 : join84(root2, "sessions.db");
|
|
449540
450164
|
}
|
|
449541
450165
|
var init_list3 = __esm(() => {
|
|
449542
450166
|
init_listing_shared();
|
|
@@ -449544,7 +450168,7 @@ var init_list3 = __esm(() => {
|
|
|
449544
450168
|
|
|
449545
450169
|
// node_modules/@letta-ai/trajectory/dist/adapters/hermes/list.js
|
|
449546
450170
|
import { homedir as homedir46 } from "node:os";
|
|
449547
|
-
import { join as
|
|
450171
|
+
import { join as join85 } from "node:path";
|
|
449548
450172
|
async function listHermesTrajectories(root2) {
|
|
449549
450173
|
const path42 = resolveStorePath2(root2);
|
|
449550
450174
|
if (!safeStat(path42))
|
|
@@ -449571,8 +450195,8 @@ async function listHermesTrajectories(root2) {
|
|
|
449571
450195
|
}
|
|
449572
450196
|
function resolveStorePath2(root2) {
|
|
449573
450197
|
if (root2 === undefined)
|
|
449574
|
-
return
|
|
449575
|
-
return root2.endsWith(".db") ? root2 :
|
|
450198
|
+
return join85(homedir46(), ".hermes", "state.db");
|
|
450199
|
+
return root2.endsWith(".db") ? root2 : join85(root2, "state.db");
|
|
449576
450200
|
}
|
|
449577
450201
|
function numeric2(value) {
|
|
449578
450202
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
@@ -449583,18 +450207,18 @@ var init_list4 = __esm(() => {
|
|
|
449583
450207
|
|
|
449584
450208
|
// node_modules/@letta-ai/trajectory/dist/adapters/letta-code/list.js
|
|
449585
450209
|
import { homedir as homedir47 } from "node:os";
|
|
449586
|
-
import { join as
|
|
450210
|
+
import { join as join86 } from "node:path";
|
|
449587
450211
|
async function listLettaCodeTrajectories(root2) {
|
|
449588
|
-
const base2 = root2 ??
|
|
450212
|
+
const base2 = root2 ?? join86(homedir47(), ".letta", "transcripts");
|
|
449589
450213
|
const items3 = [];
|
|
449590
450214
|
for (const agent of safeReadDir(base2)) {
|
|
449591
450215
|
if (!agent.isDirectory)
|
|
449592
450216
|
continue;
|
|
449593
|
-
const agentPath2 =
|
|
450217
|
+
const agentPath2 = join86(base2, agent.name);
|
|
449594
450218
|
for (const conversation of safeReadDir(agentPath2)) {
|
|
449595
450219
|
if (!conversation.isDirectory)
|
|
449596
450220
|
continue;
|
|
449597
|
-
const path42 =
|
|
450221
|
+
const path42 = join86(agentPath2, conversation.name, "transcript.jsonl");
|
|
449598
450222
|
const listing = listingFromFile(`${agent.name}/${conversation.name}`, path42);
|
|
449599
450223
|
if (listing && (listing.sizeBytes ?? 0) > 0)
|
|
449600
450224
|
items3.push(listing);
|
|
@@ -449607,21 +450231,21 @@ var init_list5 = __esm(() => {
|
|
|
449607
450231
|
});
|
|
449608
450232
|
|
|
449609
450233
|
// node_modules/@letta-ai/trajectory/dist/adapters/openclaw/list.js
|
|
449610
|
-
import { existsSync as
|
|
450234
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
449611
450235
|
import { homedir as homedir48 } from "node:os";
|
|
449612
|
-
import { basename as basename25, join as
|
|
450236
|
+
import { basename as basename25, join as join87 } from "node:path";
|
|
449613
450237
|
async function listOpenClawTrajectories(root2) {
|
|
449614
450238
|
const base2 = root2 ?? defaultStateDir();
|
|
449615
450239
|
const items3 = [];
|
|
449616
|
-
const agentsPath =
|
|
450240
|
+
const agentsPath = join87(base2, "agents");
|
|
449617
450241
|
for (const agent of safeReadDir(agentsPath)) {
|
|
449618
450242
|
if (!agent.isDirectory)
|
|
449619
450243
|
continue;
|
|
449620
|
-
const sessionsPath =
|
|
450244
|
+
const sessionsPath = join87(agentsPath, agent.name, "sessions");
|
|
449621
450245
|
for (const entry of safeReadDir(sessionsPath)) {
|
|
449622
450246
|
if (!entry.isFile || !entry.name.endsWith(".jsonl"))
|
|
449623
450247
|
continue;
|
|
449624
|
-
const path42 =
|
|
450248
|
+
const path42 = join87(sessionsPath, entry.name);
|
|
449625
450249
|
const listing = listingFromFile(basename25(entry.name, ".jsonl"), path42);
|
|
449626
450250
|
if (listing)
|
|
449627
450251
|
items3.push(listing);
|
|
@@ -449633,10 +450257,10 @@ function defaultStateDir() {
|
|
|
449633
450257
|
const override = process.env.OPENCLAW_STATE_DIR?.trim() || process.env.CLAWDBOT_STATE_DIR?.trim();
|
|
449634
450258
|
if (override)
|
|
449635
450259
|
return override;
|
|
449636
|
-
const current =
|
|
449637
|
-
if (
|
|
450260
|
+
const current = join87(homedir48(), ".openclaw");
|
|
450261
|
+
if (existsSync60(current))
|
|
449638
450262
|
return current;
|
|
449639
|
-
return
|
|
450263
|
+
return join87(homedir48(), ".clawdbot");
|
|
449640
450264
|
}
|
|
449641
450265
|
var init_list6 = __esm(() => {
|
|
449642
450266
|
init_listing_shared();
|
|
@@ -449644,14 +450268,14 @@ var init_list6 = __esm(() => {
|
|
|
449644
450268
|
|
|
449645
450269
|
// node_modules/@letta-ai/trajectory/dist/adapters/openhands/list.js
|
|
449646
450270
|
import { homedir as homedir49 } from "node:os";
|
|
449647
|
-
import { join as
|
|
450271
|
+
import { join as join88 } from "node:path";
|
|
449648
450272
|
async function listOpenHandsTrajectories(root2) {
|
|
449649
|
-
const base2 = root2 ??
|
|
450273
|
+
const base2 = root2 ?? join88(homedir49(), ".openhands", "sessions");
|
|
449650
450274
|
const items3 = [];
|
|
449651
450275
|
for (const entry of safeReadDir(base2)) {
|
|
449652
450276
|
if (!entry.isDirectory)
|
|
449653
450277
|
continue;
|
|
449654
|
-
const path42 =
|
|
450278
|
+
const path42 = join88(base2, entry.name);
|
|
449655
450279
|
const facts = safeStat(path42);
|
|
449656
450280
|
items3.push({
|
|
449657
450281
|
id: entry.name,
|
|
@@ -449897,7 +450521,7 @@ import {
|
|
|
449897
450521
|
stat as stat13,
|
|
449898
450522
|
writeFile as writeFile16
|
|
449899
450523
|
} from "node:fs/promises";
|
|
449900
|
-
import { join as
|
|
450524
|
+
import { join as join89 } from "node:path";
|
|
449901
450525
|
function buildReflectionSelectorPrompt(options) {
|
|
449902
450526
|
const lines = [
|
|
449903
450527
|
'You are selecting conversation transcripts for memory reflection. The transcript candidates path is available as the `$TRANSCRIPT_PATH` env var — read it via Bash (e.g. `wc -c "$TRANSCRIPT_PATH"`). Note: `$TRANSCRIPT_PATH` only expands in shell commands; Edit file_path is literal and does NOT expand env vars.',
|
|
@@ -449931,7 +450555,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
449931
450555
|
return a2.name.localeCompare(b3.name);
|
|
449932
450556
|
});
|
|
449933
450557
|
for (const entry of sortedEntries) {
|
|
449934
|
-
const entryPath =
|
|
450558
|
+
const entryPath = join89(currentDir, entry.name);
|
|
449935
450559
|
const relativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
|
|
449936
450560
|
if (entry.isDirectory()) {
|
|
449937
450561
|
await walk3(entryPath, relativePath);
|
|
@@ -450347,17 +450971,17 @@ async function writeState(paths, state2) {
|
|
|
450347
450971
|
}
|
|
450348
450972
|
function buildPayloadPath(rootDir, kind) {
|
|
450349
450973
|
const nonce = Math.random().toString(36).slice(2, 8);
|
|
450350
|
-
return
|
|
450974
|
+
return join89(rootDir, `payload-${kind}-${nonce}.json`);
|
|
450351
450975
|
}
|
|
450352
450976
|
function getAgentTranscriptRoot(agentId) {
|
|
450353
|
-
return
|
|
450977
|
+
return join89(getTranscriptRoot(), sanitizePathSegment2(agentId));
|
|
450354
450978
|
}
|
|
450355
450979
|
function getReflectionTranscriptPaths(agentId, conversationId) {
|
|
450356
|
-
const rootDir =
|
|
450980
|
+
const rootDir = join89(getTranscriptRoot(), sanitizePathSegment2(agentId), sanitizePathSegment2(conversationId));
|
|
450357
450981
|
return {
|
|
450358
450982
|
rootDir,
|
|
450359
|
-
transcriptPath:
|
|
450360
|
-
statePath:
|
|
450983
|
+
transcriptPath: join89(rootDir, "transcript.jsonl"),
|
|
450984
|
+
statePath: join89(rootDir, "state.json")
|
|
450361
450985
|
};
|
|
450362
450986
|
}
|
|
450363
450987
|
async function appendTranscriptDeltaJsonl(agentId, conversationId, lines) {
|
|
@@ -450447,7 +451071,7 @@ async function getTranscriptLastUpdatedAt(paths) {
|
|
|
450447
451071
|
}
|
|
450448
451072
|
}
|
|
450449
451073
|
async function ensureAgentPayloadRoot(agentId) {
|
|
450450
|
-
const root2 =
|
|
451074
|
+
const root2 = join89(getAgentTranscriptRoot(agentId), "multi-reflection-payloads");
|
|
450451
451075
|
await mkdir14(root2, { recursive: true });
|
|
450452
451076
|
return root2;
|
|
450453
451077
|
}
|
|
@@ -455229,9 +455853,9 @@ __export(exports_custom, {
|
|
|
455229
455853
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
455230
455854
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
455231
455855
|
});
|
|
455232
|
-
import { existsSync as
|
|
455856
|
+
import { existsSync as existsSync61 } from "node:fs";
|
|
455233
455857
|
import { readdir as readdir11, readFile as readFile24 } from "node:fs/promises";
|
|
455234
|
-
import { basename as basename27, dirname as dirname33, join as
|
|
455858
|
+
import { basename as basename27, dirname as dirname33, join as join90 } from "node:path";
|
|
455235
455859
|
async function getCustomCommands() {
|
|
455236
455860
|
if (cachedCommands !== null) {
|
|
455237
455861
|
return cachedCommands;
|
|
@@ -455242,7 +455866,7 @@ async function getCustomCommands() {
|
|
|
455242
455866
|
function refreshCustomCommands() {
|
|
455243
455867
|
cachedCommands = null;
|
|
455244
455868
|
}
|
|
455245
|
-
async function discoverCustomCommands(projectPath =
|
|
455869
|
+
async function discoverCustomCommands(projectPath = join90(process.cwd(), COMMANDS_DIR)) {
|
|
455246
455870
|
const commandsById = new Map;
|
|
455247
455871
|
const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
|
|
455248
455872
|
for (const cmd of userCommands) {
|
|
@@ -455263,7 +455887,7 @@ async function discoverCustomCommands(projectPath = join89(process.cwd(), COMMAN
|
|
|
455263
455887
|
return result3;
|
|
455264
455888
|
}
|
|
455265
455889
|
async function discoverFromDirectory(dirPath, source) {
|
|
455266
|
-
if (!
|
|
455890
|
+
if (!existsSync61(dirPath)) {
|
|
455267
455891
|
return [];
|
|
455268
455892
|
}
|
|
455269
455893
|
const commands = [];
|
|
@@ -455274,7 +455898,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source) {
|
|
|
455274
455898
|
try {
|
|
455275
455899
|
const entries2 = await readdir11(currentPath, { withFileTypes: true });
|
|
455276
455900
|
for (const entry of entries2) {
|
|
455277
|
-
const fullPath =
|
|
455901
|
+
const fullPath = join90(currentPath, entry.name);
|
|
455278
455902
|
if (entry.isDirectory()) {
|
|
455279
455903
|
await findCommandFiles(fullPath, rootPath, commands, source);
|
|
455280
455904
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -455359,7 +455983,7 @@ async function findCustomCommand(commandName) {
|
|
|
455359
455983
|
}
|
|
455360
455984
|
var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
|
|
455361
455985
|
var init_custom = __esm(() => {
|
|
455362
|
-
GLOBAL_COMMANDS_DIR =
|
|
455986
|
+
GLOBAL_COMMANDS_DIR = join90(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
|
|
455363
455987
|
});
|
|
455364
455988
|
|
|
455365
455989
|
// src/cli/helpers/doctor-command.ts
|
|
@@ -457001,7 +457625,7 @@ function handleMemfsSyncedMemoryProtocolCommand(parsed, context3) {
|
|
|
457001
457625
|
}
|
|
457002
457626
|
var init_memory_command_sync = __esm(async () => {
|
|
457003
457627
|
init_memfs_sync();
|
|
457004
|
-
await
|
|
457628
|
+
await init_memory6();
|
|
457005
457629
|
});
|
|
457006
457630
|
|
|
457007
457631
|
// src/websocket/listener/commands/queue.ts
|
|
@@ -458052,7 +458676,7 @@ function createListenerMessageHandler(params) {
|
|
|
458052
458676
|
return;
|
|
458053
458677
|
}
|
|
458054
458678
|
if (parsed.type === "runtime_external_tools_update") {
|
|
458055
|
-
const
|
|
458679
|
+
const respond2 = (success, error5) => {
|
|
458056
458680
|
safeSocketSend(socket, {
|
|
458057
458681
|
type: "runtime_external_tools_update_response",
|
|
458058
458682
|
request_id: parsed.request_id,
|
|
@@ -458061,11 +458685,11 @@ function createListenerMessageHandler(params) {
|
|
|
458061
458685
|
}, "runtime_external_tools_update_response", "runtime_external_tools_update");
|
|
458062
458686
|
};
|
|
458063
458687
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
458064
|
-
|
|
458688
|
+
respond2(false, "Runtime is no longer active");
|
|
458065
458689
|
return;
|
|
458066
458690
|
}
|
|
458067
458691
|
updateRuntimeExternalTools(runtime, connectionId, parsed.updates);
|
|
458068
|
-
|
|
458692
|
+
respond2(true);
|
|
458069
458693
|
return;
|
|
458070
458694
|
}
|
|
458071
458695
|
if (parsed.type === "sync") {
|
|
@@ -460613,7 +461237,7 @@ var init_client9 = __esm(async () => {
|
|
|
460613
461237
|
init_approval(),
|
|
460614
461238
|
init_agents_conversations(),
|
|
460615
461239
|
init_cron3(),
|
|
460616
|
-
|
|
461240
|
+
init_memory6(),
|
|
460617
461241
|
init_model_toolset(),
|
|
460618
461242
|
init_runtime_start(),
|
|
460619
461243
|
init_settings3(),
|
|
@@ -462543,7 +463167,7 @@ __export(exports_app_server, {
|
|
|
462543
463167
|
startAppServer: () => startAppServer,
|
|
462544
463168
|
parseAppServerListenUrl: () => parseAppServerListenUrl
|
|
462545
463169
|
});
|
|
462546
|
-
import { createServer as
|
|
463170
|
+
import { createServer as createServer5 } from "node:http";
|
|
462547
463171
|
import { hostname as hostname4 } from "node:os";
|
|
462548
463172
|
import WebSocket11, { WebSocketServer } from "ws";
|
|
462549
463173
|
function getRequiredAddressInfo(server2) {
|
|
@@ -462676,7 +463300,7 @@ async function startAppServer(options = {}) {
|
|
|
462676
463300
|
closeSocket(socket, 1011, "failed to start connection");
|
|
462677
463301
|
});
|
|
462678
463302
|
};
|
|
462679
|
-
const server2 =
|
|
463303
|
+
const server2 = createServer5((request, response) => {
|
|
462680
463304
|
const requestUrl = getRequestUrl(request, listen.host);
|
|
462681
463305
|
if (request.headers.origin) {
|
|
462682
463306
|
options.onLog?.(`Rejecting app-server request with Origin header: ${request.url ?? "/"}`);
|
|
@@ -463601,11 +464225,9 @@ async function runListenSubcommand(argv) {
|
|
|
463601
464225
|
console.log(`[${formatTimestamp3()}] status: ${status}`);
|
|
463602
464226
|
}
|
|
463603
464227
|
},
|
|
463604
|
-
onConnected:
|
|
463605
|
-
await startChannelGateway();
|
|
463606
|
-
},
|
|
464228
|
+
onConnected: () => {},
|
|
463607
464229
|
onConnectionReady: async (connectedId) => {
|
|
463608
|
-
const ready = await completeListenerConnectionStartup(connectedId, readiness);
|
|
464230
|
+
const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
|
|
463609
464231
|
if (!ready)
|
|
463610
464232
|
return;
|
|
463611
464233
|
sessionLog.log("Local channel listener ready.");
|
|
@@ -463708,11 +464330,9 @@ async function runListenSubcommand(argv) {
|
|
|
463708
464330
|
}
|
|
463709
464331
|
},
|
|
463710
464332
|
onLog: logListenerMessage,
|
|
463711
|
-
onConnected:
|
|
463712
|
-
await startChannelGateway();
|
|
463713
|
-
},
|
|
464333
|
+
onConnected: () => {},
|
|
463714
464334
|
onConnectionReady: async (connectedId) => {
|
|
463715
|
-
const ready = await completeListenerConnectionStartup(connectedId, readiness);
|
|
464335
|
+
const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
|
|
463716
464336
|
if (!ready)
|
|
463717
464337
|
return;
|
|
463718
464338
|
sessionLog.log("Connected. Awaiting instructions.");
|
|
@@ -463789,9 +464409,12 @@ async function runListenSubcommand(argv) {
|
|
|
463789
464409
|
updateStatusCallback?.(status);
|
|
463790
464410
|
},
|
|
463791
464411
|
onLog: logListenerMessage,
|
|
463792
|
-
onConnected:
|
|
464412
|
+
onConnected: () => {},
|
|
464413
|
+
onConnectionReady: async (connectedId) => {
|
|
464414
|
+
const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
|
|
464415
|
+
if (!ready)
|
|
464416
|
+
return;
|
|
463793
464417
|
sessionLog.log("Connected. Awaiting instructions.");
|
|
463794
|
-
await startChannelGateway();
|
|
463795
464418
|
clearRetryStatusCallback?.();
|
|
463796
464419
|
updateStatusCallback?.("idle");
|
|
463797
464420
|
},
|
|
@@ -463888,17 +464511,17 @@ var init_listen = __esm(async () => {
|
|
|
463888
464511
|
import { randomUUID as randomUUID51 } from "node:crypto";
|
|
463889
464512
|
import {
|
|
463890
464513
|
copyFileSync as copyFileSync3,
|
|
463891
|
-
existsSync as
|
|
464514
|
+
existsSync as existsSync62,
|
|
463892
464515
|
mkdirSync as mkdirSync44,
|
|
463893
|
-
readdirSync as
|
|
463894
|
-
readFileSync as
|
|
464516
|
+
readdirSync as readdirSync25,
|
|
464517
|
+
readFileSync as readFileSync46,
|
|
463895
464518
|
writeFileSync as writeFileSync37
|
|
463896
464519
|
} from "node:fs";
|
|
463897
|
-
import { join as
|
|
464520
|
+
import { join as join91 } from "node:path";
|
|
463898
464521
|
function readJsonl(path45) {
|
|
463899
|
-
if (!
|
|
464522
|
+
if (!existsSync62(path45))
|
|
463900
464523
|
return [];
|
|
463901
|
-
return
|
|
464524
|
+
return readFileSync46(path45, "utf8").split(`
|
|
463902
464525
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
463903
464526
|
}
|
|
463904
464527
|
function isLegacyUiMessage(value) {
|
|
@@ -464177,23 +464800,23 @@ function convertMessages4(messages, mode, nextId2) {
|
|
|
464177
464800
|
}
|
|
464178
464801
|
function migrateLocalBackendTranscripts(input) {
|
|
464179
464802
|
const storageDir = input.storageDir;
|
|
464180
|
-
const conversationsDir =
|
|
464803
|
+
const conversationsDir = join91(storageDir, "conversations");
|
|
464181
464804
|
const result3 = {
|
|
464182
464805
|
storageDir,
|
|
464183
464806
|
converted: [],
|
|
464184
464807
|
skipped: [],
|
|
464185
464808
|
dryRun: input.dryRun === true
|
|
464186
464809
|
};
|
|
464187
|
-
if (!
|
|
464810
|
+
if (!existsSync62(conversationsDir))
|
|
464188
464811
|
return result3;
|
|
464189
|
-
for (const name of
|
|
464190
|
-
const conversationDir =
|
|
464191
|
-
const messagesPath =
|
|
464192
|
-
const manifestPath =
|
|
464193
|
-
const hasManifest =
|
|
464812
|
+
for (const name of readdirSync25(conversationsDir)) {
|
|
464813
|
+
const conversationDir = join91(conversationsDir, name);
|
|
464814
|
+
const messagesPath = join91(conversationDir, "messages.jsonl");
|
|
464815
|
+
const manifestPath = join91(conversationDir, "manifest.json");
|
|
464816
|
+
const hasManifest = existsSync62(manifestPath);
|
|
464194
464817
|
const existingManifest = hasManifest ? (() => {
|
|
464195
464818
|
try {
|
|
464196
|
-
return JSON.parse(
|
|
464819
|
+
return JSON.parse(readFileSync46(manifestPath, "utf8"));
|
|
464197
464820
|
} catch {
|
|
464198
464821
|
return;
|
|
464199
464822
|
}
|
|
@@ -464232,11 +464855,11 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
464232
464855
|
const backupPath = `${messagesPath}.pre-pi-backup-${timestampSuffix()}`;
|
|
464233
464856
|
if (!input.dryRun) {
|
|
464234
464857
|
copyFileSync3(messagesPath, backupPath);
|
|
464235
|
-
const conversationPath =
|
|
464858
|
+
const conversationPath = join91(conversationDir, "conversation.json");
|
|
464236
464859
|
let conversation;
|
|
464237
|
-
if (
|
|
464860
|
+
if (existsSync62(conversationPath)) {
|
|
464238
464861
|
try {
|
|
464239
|
-
conversation = JSON.parse(
|
|
464862
|
+
conversation = JSON.parse(readFileSync46(conversationPath, "utf8"));
|
|
464240
464863
|
} catch {
|
|
464241
464864
|
conversation = undefined;
|
|
464242
464865
|
}
|
|
@@ -464428,9 +465051,9 @@ var init_memory_tokens = __esm(() => {
|
|
|
464428
465051
|
});
|
|
464429
465052
|
|
|
464430
465053
|
// src/cli/subcommands/memory.ts
|
|
464431
|
-
import { cpSync, existsSync as
|
|
465054
|
+
import { cpSync, existsSync as existsSync63, mkdirSync as mkdirSync45, rmSync as rmSync21, statSync as statSync22 } from "node:fs";
|
|
464432
465055
|
import { readdir as readdir12 } from "node:fs/promises";
|
|
464433
|
-
import { dirname as dirname34, join as
|
|
465056
|
+
import { dirname as dirname34, join as join92 } from "node:path";
|
|
464434
465057
|
import { parseArgs as parseArgs11 } from "node:util";
|
|
464435
465058
|
function printUsage8() {
|
|
464436
465059
|
console.log(`
|
|
@@ -464490,7 +465113,7 @@ function formatBackupTimestamp(date5 = new Date) {
|
|
|
464490
465113
|
}
|
|
464491
465114
|
async function listBackups(agentId) {
|
|
464492
465115
|
const agentRoot = getAgentRoot(agentId);
|
|
464493
|
-
if (!
|
|
465116
|
+
if (!existsSync63(agentRoot)) {
|
|
464494
465117
|
return [];
|
|
464495
465118
|
}
|
|
464496
465119
|
const entries2 = await readdir12(agentRoot, { withFileTypes: true });
|
|
@@ -464500,10 +465123,10 @@ async function listBackups(agentId) {
|
|
|
464500
465123
|
continue;
|
|
464501
465124
|
if (!entry.name.startsWith("memory-backup-"))
|
|
464502
465125
|
continue;
|
|
464503
|
-
const path45 =
|
|
465126
|
+
const path45 = join92(agentRoot, entry.name);
|
|
464504
465127
|
let createdAt = null;
|
|
464505
465128
|
try {
|
|
464506
|
-
const stat15 =
|
|
465129
|
+
const stat15 = statSync22(path45);
|
|
464507
465130
|
createdAt = stat15.mtime.toISOString();
|
|
464508
465131
|
} catch {
|
|
464509
465132
|
createdAt = null;
|
|
@@ -464517,7 +465140,7 @@ function resolveBackupPath(agentId, from) {
|
|
|
464517
465140
|
if (from.startsWith("/") || /^[A-Za-z]:[/\\]/.test(from)) {
|
|
464518
465141
|
return from;
|
|
464519
465142
|
}
|
|
464520
|
-
return
|
|
465143
|
+
return join92(getAgentRoot(agentId), from);
|
|
464521
465144
|
}
|
|
464522
465145
|
async function runMemorySubcommand(argv, deps = {}) {
|
|
464523
465146
|
let parsed;
|
|
@@ -464595,14 +465218,14 @@ async function runMemorySubcommand(argv, deps = {}) {
|
|
|
464595
465218
|
}
|
|
464596
465219
|
if (action3 === "backup") {
|
|
464597
465220
|
const root2 = getMemoryRoot(agentId);
|
|
464598
|
-
if (!
|
|
465221
|
+
if (!existsSync63(root2)) {
|
|
464599
465222
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
464600
465223
|
return 1;
|
|
464601
465224
|
}
|
|
464602
465225
|
const agentRoot = getAgentRoot(agentId);
|
|
464603
465226
|
const backupName = `memory-backup-${formatBackupTimestamp()}`;
|
|
464604
|
-
const backupPath =
|
|
464605
|
-
if (
|
|
465227
|
+
const backupPath = join92(agentRoot, backupName);
|
|
465228
|
+
if (existsSync63(backupPath)) {
|
|
464606
465229
|
console.error(`Backup already exists at ${backupPath}`);
|
|
464607
465230
|
return 1;
|
|
464608
465231
|
}
|
|
@@ -464626,11 +465249,11 @@ async function runMemorySubcommand(argv, deps = {}) {
|
|
|
464626
465249
|
return 1;
|
|
464627
465250
|
}
|
|
464628
465251
|
const backupPath = resolveBackupPath(agentId, from);
|
|
464629
|
-
if (!
|
|
465252
|
+
if (!existsSync63(backupPath)) {
|
|
464630
465253
|
console.error(`Backup not found: ${backupPath}`);
|
|
464631
465254
|
return 1;
|
|
464632
465255
|
}
|
|
464633
|
-
const stat15 =
|
|
465256
|
+
const stat15 = statSync22(backupPath);
|
|
464634
465257
|
if (!stat15.isDirectory()) {
|
|
464635
465258
|
console.error(`Backup path is not a directory: ${backupPath}`);
|
|
464636
465259
|
return 1;
|
|
@@ -464648,12 +465271,12 @@ async function runMemorySubcommand(argv, deps = {}) {
|
|
|
464648
465271
|
return 1;
|
|
464649
465272
|
}
|
|
464650
465273
|
const root2 = getMemoryRoot(agentId);
|
|
464651
|
-
if (!
|
|
465274
|
+
if (!existsSync63(root2)) {
|
|
464652
465275
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
464653
465276
|
return 1;
|
|
464654
465277
|
}
|
|
464655
|
-
if (
|
|
464656
|
-
const stat15 =
|
|
465278
|
+
if (existsSync63(out)) {
|
|
465279
|
+
const stat15 = statSync22(out);
|
|
464657
465280
|
if (stat15.isDirectory()) {
|
|
464658
465281
|
const contents = await readdir12(out);
|
|
464659
465282
|
if (contents.length > 0) {
|
|
@@ -464680,7 +465303,7 @@ async function runMemorySubcommand(argv, deps = {}) {
|
|
|
464680
465303
|
return 1;
|
|
464681
465304
|
}
|
|
464682
465305
|
var MEMORY_OPTIONS;
|
|
464683
|
-
var
|
|
465306
|
+
var init_memory7 = __esm(() => {
|
|
464684
465307
|
init_memory_filesystem2();
|
|
464685
465308
|
init_memory_git();
|
|
464686
465309
|
init_paths();
|
|
@@ -464701,22 +465324,22 @@ var init_memory6 = __esm(() => {
|
|
|
464701
465324
|
});
|
|
464702
465325
|
|
|
464703
465326
|
// src/backend/local/transcript-search.ts
|
|
464704
|
-
import { existsSync as
|
|
464705
|
-
import { join as
|
|
465327
|
+
import { existsSync as existsSync64, readdirSync as readdirSync26, readFileSync as readFileSync47, statSync as statSync23 } from "node:fs";
|
|
465328
|
+
import { join as join93 } from "node:path";
|
|
464706
465329
|
function readJsonFile3(path45) {
|
|
464707
|
-
if (!
|
|
465330
|
+
if (!existsSync64(path45))
|
|
464708
465331
|
return;
|
|
464709
465332
|
try {
|
|
464710
|
-
return JSON.parse(
|
|
465333
|
+
return JSON.parse(readFileSync47(path45, "utf8"));
|
|
464711
465334
|
} catch {
|
|
464712
465335
|
return;
|
|
464713
465336
|
}
|
|
464714
465337
|
}
|
|
464715
465338
|
function readJsonlFile2(path45) {
|
|
464716
|
-
if (!
|
|
465339
|
+
if (!existsSync64(path45))
|
|
464717
465340
|
return [];
|
|
464718
465341
|
try {
|
|
464719
|
-
return
|
|
465342
|
+
return readFileSync47(path45, "utf8").split(`
|
|
464720
465343
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
464721
465344
|
} catch {
|
|
464722
465345
|
return [];
|
|
@@ -464957,11 +465580,11 @@ function collectConversationMessages(input) {
|
|
|
464957
465580
|
return [];
|
|
464958
465581
|
if (input.conversationId && conversation.id !== input.conversationId)
|
|
464959
465582
|
return [];
|
|
464960
|
-
const messagesPath =
|
|
465583
|
+
const messagesPath = join93(conversationDir, "messages.jsonl");
|
|
464961
465584
|
const rows = readJsonlFile2(messagesPath);
|
|
464962
465585
|
if (rows.length === 0)
|
|
464963
465586
|
return [];
|
|
464964
|
-
const manifest2 = readJsonFile3(
|
|
465587
|
+
const manifest2 = readJsonFile3(join93(conversationDir, "manifest.json"));
|
|
464965
465588
|
const format5 = transcriptFormat(manifest2, rows);
|
|
464966
465589
|
if (!format5)
|
|
464967
465590
|
return [];
|
|
@@ -464990,11 +465613,11 @@ function collectConversationMessages(input) {
|
|
|
464990
465613
|
}).filter((record6) => record6.tokens.length > 0);
|
|
464991
465614
|
}
|
|
464992
465615
|
function conversationDirectories(storageDir) {
|
|
464993
|
-
const conversationsDir =
|
|
464994
|
-
if (!
|
|
465616
|
+
const conversationsDir = join93(storageDir, "conversations");
|
|
465617
|
+
if (!existsSync64(conversationsDir))
|
|
464995
465618
|
return [];
|
|
464996
465619
|
try {
|
|
464997
|
-
return
|
|
465620
|
+
return readdirSync26(conversationsDir).map((entry) => join93(conversationsDir, entry)).filter((entryPath) => statSync23(entryPath).isDirectory());
|
|
464998
465621
|
} catch {
|
|
464999
465622
|
return [];
|
|
465000
465623
|
}
|
|
@@ -465021,7 +465644,7 @@ function searchLocalTranscriptMessages(storageDir, body3, options = {}) {
|
|
|
465021
465644
|
const endDate = typeof body3.end_date === "string" ? body3.end_date : undefined;
|
|
465022
465645
|
const includeHidden = body3.include_hidden === true;
|
|
465023
465646
|
const records2 = conversationDirectories(storageDir).flatMap((conversationDir) => {
|
|
465024
|
-
const conversation = conversationSearchRecord(readJsonFile3(
|
|
465647
|
+
const conversation = conversationSearchRecord(readJsonFile3(join93(conversationDir, "conversation.json")));
|
|
465025
465648
|
if (!conversation)
|
|
465026
465649
|
return [];
|
|
465027
465650
|
if (conversation.hidden && !includeHidden)
|
|
@@ -465905,12 +466528,12 @@ var init_model2 = __esm(() => {
|
|
|
465905
466528
|
import { spawn as spawn13 } from "node:child_process";
|
|
465906
466529
|
import {
|
|
465907
466530
|
copyFileSync as copyFileSync4,
|
|
465908
|
-
existsSync as
|
|
466531
|
+
existsSync as existsSync65,
|
|
465909
466532
|
lstatSync as lstatSync3,
|
|
465910
466533
|
mkdirSync as mkdirSync46,
|
|
465911
466534
|
mkdtempSync as mkdtempSync5,
|
|
465912
|
-
readdirSync as
|
|
465913
|
-
readFileSync as
|
|
466535
|
+
readdirSync as readdirSync27,
|
|
466536
|
+
readFileSync as readFileSync48,
|
|
465914
466537
|
renameSync as renameSync12,
|
|
465915
466538
|
rmSync as rmSync22,
|
|
465916
466539
|
writeFileSync as writeFileSync38
|
|
@@ -465929,7 +466552,7 @@ function isPathInsideOrEqual2(childPath, parentPath) {
|
|
|
465929
466552
|
function readPackageJson(packageJsonPath) {
|
|
465930
466553
|
let parsed;
|
|
465931
466554
|
try {
|
|
465932
|
-
parsed = JSON.parse(
|
|
466555
|
+
parsed = JSON.parse(readFileSync48(packageJsonPath, "utf8"));
|
|
465933
466556
|
} catch (error5) {
|
|
465934
466557
|
throw new Error(`Could not read package.json: ${error5 instanceof Error ? error5.message : String(error5)}`);
|
|
465935
466558
|
}
|
|
@@ -466050,7 +466673,7 @@ function validatePackageSource(packageDirectory) {
|
|
|
466050
466673
|
}
|
|
466051
466674
|
function copyPackageDirectory(sourceRoot, targetRoot) {
|
|
466052
466675
|
mkdirSync46(targetRoot, { recursive: true });
|
|
466053
|
-
for (const entry of
|
|
466676
|
+
for (const entry of readdirSync27(sourceRoot, { withFileTypes: true })) {
|
|
466054
466677
|
if (SKIPPED_PACKAGE_COPY_NAMES.has(entry.name))
|
|
466055
466678
|
continue;
|
|
466056
466679
|
const sourcePath = path45.join(sourceRoot, entry.name);
|
|
@@ -466082,7 +466705,7 @@ function shouldSkipDependencyPath(relativeParts, installedPackageName) {
|
|
|
466082
466705
|
function copyDependencyDirectoryFiltered(params) {
|
|
466083
466706
|
let copied = false;
|
|
466084
466707
|
const relativeParts = params.relativeParts ?? [];
|
|
466085
|
-
for (const entry of
|
|
466708
|
+
for (const entry of readdirSync27(params.sourceRoot, { withFileTypes: true })) {
|
|
466086
466709
|
const nextRelativeParts = [...relativeParts, entry.name];
|
|
466087
466710
|
if (shouldSkipDependencyPath(nextRelativeParts, params.installedPackageName)) {
|
|
466088
466711
|
continue;
|
|
@@ -466114,7 +466737,7 @@ function copyDependencyDirectoryFiltered(params) {
|
|
|
466114
466737
|
return copied;
|
|
466115
466738
|
}
|
|
466116
466739
|
function copyDependencyNodeModules(params) {
|
|
466117
|
-
if (!
|
|
466740
|
+
if (!existsSync65(params.sourceNodeModulesDirectory))
|
|
466118
466741
|
return;
|
|
466119
466742
|
copyDependencyDirectoryFiltered({
|
|
466120
466743
|
installedPackageName: params.installedPackageName,
|
|
@@ -466124,7 +466747,7 @@ function copyDependencyNodeModules(params) {
|
|
|
466124
466747
|
}
|
|
466125
466748
|
function copyPackageInternalNodeModules(params) {
|
|
466126
466749
|
const sourceNodeModulesDirectory = path45.join(params.packageDirectory, "node_modules");
|
|
466127
|
-
if (!
|
|
466750
|
+
if (!existsSync65(sourceNodeModulesDirectory))
|
|
466128
466751
|
return;
|
|
466129
466752
|
copyDependencyDirectoryFiltered({
|
|
466130
466753
|
sourceRoot: sourceNodeModulesDirectory,
|
|
@@ -466146,12 +466769,12 @@ function removeIfExists(targetPath) {
|
|
|
466146
466769
|
}
|
|
466147
466770
|
function restoreDestination(params) {
|
|
466148
466771
|
rmSync22(params.destinationRoot, { force: true, recursive: true });
|
|
466149
|
-
if (params.backupRoot &&
|
|
466772
|
+
if (params.backupRoot && existsSync65(params.backupRoot)) {
|
|
466150
466773
|
renameSync12(params.backupRoot, params.destinationRoot);
|
|
466151
466774
|
}
|
|
466152
466775
|
}
|
|
466153
466776
|
function restoreDestinationIfNeeded(params) {
|
|
466154
|
-
if (!params.backupRoot || !
|
|
466777
|
+
if (!params.backupRoot || !existsSync65(params.backupRoot)) {
|
|
466155
466778
|
rmSync22(params.destinationRoot, { force: true, recursive: true });
|
|
466156
466779
|
return;
|
|
466157
466780
|
}
|
|
@@ -466192,7 +466815,7 @@ function installPreparedManagedModPackage(params) {
|
|
|
466192
466815
|
targetPackageRoot: stagingRoot
|
|
466193
466816
|
});
|
|
466194
466817
|
}
|
|
466195
|
-
if (
|
|
466818
|
+
if (existsSync65(destinationRoot)) {
|
|
466196
466819
|
backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
|
|
466197
466820
|
rmSync22(backupRoot, { force: true, recursive: true });
|
|
466198
466821
|
renameSync12(destinationRoot, backupRoot);
|
|
@@ -466477,7 +467100,7 @@ function hasRuntimeDependencies(packageJson) {
|
|
|
466477
467100
|
}
|
|
466478
467101
|
function readPackageJsonIfExists(packageDirectory) {
|
|
466479
467102
|
const packageJsonPath = path45.join(packageDirectory, "package.json");
|
|
466480
|
-
if (!
|
|
467103
|
+
if (!existsSync65(packageJsonPath))
|
|
466481
467104
|
return null;
|
|
466482
467105
|
return readPackageJson(packageJsonPath);
|
|
466483
467106
|
}
|
|
@@ -466491,13 +467114,13 @@ function isRegularModFile(filePath) {
|
|
|
466491
467114
|
}
|
|
466492
467115
|
function inferCompatibilityModEntries(packageDirectory) {
|
|
466493
467116
|
const modsDirectory = path45.join(packageDirectory, "mods");
|
|
466494
|
-
if (
|
|
467117
|
+
if (existsSync65(modsDirectory)) {
|
|
466495
467118
|
const stats = lstatSync3(modsDirectory);
|
|
466496
467119
|
if (stats.isSymbolicLink()) {
|
|
466497
467120
|
throw new Error(`Package mods directory must not be a symlink: mods`);
|
|
466498
467121
|
}
|
|
466499
467122
|
if (stats.isDirectory()) {
|
|
466500
|
-
const entries2 =
|
|
467123
|
+
const entries2 = readdirSync27(modsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && isModFileExtension(path45.extname(entry.name))).map((entry) => `mods/${entry.name}`).sort();
|
|
466501
467124
|
if (entries2.length > 0)
|
|
466502
467125
|
return entries2;
|
|
466503
467126
|
}
|
|
@@ -466766,7 +467389,7 @@ var init_package_installer = __esm(() => {
|
|
|
466766
467389
|
// src/mods/package-scaffolder.ts
|
|
466767
467390
|
import {
|
|
466768
467391
|
copyFileSync as copyFileSync5,
|
|
466769
|
-
existsSync as
|
|
467392
|
+
existsSync as existsSync66,
|
|
466770
467393
|
lstatSync as lstatSync4,
|
|
466771
467394
|
mkdirSync as mkdirSync47,
|
|
466772
467395
|
rmSync as rmSync23,
|
|
@@ -466859,7 +467482,7 @@ function scaffoldLocalModPackage(options) {
|
|
|
466859
467482
|
const sourceFile = readSourceFile(options.sourceFile);
|
|
466860
467483
|
const packageName = assertValidPackageName(options.packageName);
|
|
466861
467484
|
const outputDirectory = path46.resolve(options.outputDirectory ?? defaultOutputDirectory(sourceFile, packageName));
|
|
466862
|
-
if (
|
|
467485
|
+
if (existsSync66(outputDirectory)) {
|
|
466863
467486
|
throw new Error(`Output directory already exists: ${outputDirectory}`);
|
|
466864
467487
|
}
|
|
466865
467488
|
const modFileName = path46.basename(sourceFile);
|
|
@@ -466901,7 +467524,7 @@ var init_package_scaffolder = __esm(() => {
|
|
|
466901
467524
|
});
|
|
466902
467525
|
|
|
466903
467526
|
// src/cli/subcommands/mods.ts
|
|
466904
|
-
import { dirname as dirname35, join as
|
|
467527
|
+
import { dirname as dirname35, join as join94 } from "node:path";
|
|
466905
467528
|
import { parseArgs as parseArgs14 } from "node:util";
|
|
466906
467529
|
function printUsage11() {
|
|
466907
467530
|
console.log(`
|
|
@@ -466940,7 +467563,7 @@ function getExplicitAgentId(values4) {
|
|
|
466940
467563
|
return typeof explicitAgent === "string" && explicitAgent.trim() ? explicitAgent.trim() : null;
|
|
466941
467564
|
}
|
|
466942
467565
|
function getAgentModsDirectory(agentId) {
|
|
466943
|
-
return
|
|
467566
|
+
return join94(getScopedMemoryFilesystemRoot(agentId), "mods");
|
|
466944
467567
|
}
|
|
466945
467568
|
function directFilesForSource(source) {
|
|
466946
467569
|
return source.files.filter((file) => dirname35(file) === source.root);
|
|
@@ -468480,8 +469103,8 @@ var init_setup7 = __esm(async () => {
|
|
|
468480
469103
|
});
|
|
468481
469104
|
|
|
468482
469105
|
// src/cli/subcommands/shared-memory.ts
|
|
468483
|
-
import { existsSync as
|
|
468484
|
-
import { join as
|
|
469106
|
+
import { existsSync as existsSync67 } from "node:fs";
|
|
469107
|
+
import { join as join95 } from "node:path";
|
|
468485
469108
|
import { parseArgs as parseArgs19 } from "node:util";
|
|
468486
469109
|
function printUsage16() {
|
|
468487
469110
|
console.log(`
|
|
@@ -468673,7 +469296,7 @@ async function runSharedMemorySubcommand(argv, deps = {}) {
|
|
|
468673
469296
|
invalidateClientSkills(agentId);
|
|
468674
469297
|
const recompileError = await recompileAndReportFailure(recompileAgent, agentId);
|
|
468675
469298
|
const mountDir = getRepositoryMountDir(agentId, repository.name);
|
|
468676
|
-
const mounted =
|
|
469299
|
+
const mounted = existsSync67(join95(mountDir, ".git"));
|
|
468677
469300
|
console.log(JSON.stringify({
|
|
468678
469301
|
attached: true,
|
|
468679
469302
|
repository: { id: repository.id, name: repository.name },
|
|
@@ -470202,16 +470825,16 @@ var init_AgentSelector = __esm(async () => {
|
|
|
470202
470825
|
// src/cli/subcommands/skills.ts
|
|
470203
470826
|
import {
|
|
470204
470827
|
cpSync as cpSync2,
|
|
470205
|
-
existsSync as
|
|
470828
|
+
existsSync as existsSync68,
|
|
470206
470829
|
mkdtempSync as mkdtempSync6,
|
|
470207
|
-
readFileSync as
|
|
470830
|
+
readFileSync as readFileSync49,
|
|
470208
470831
|
rmSync as rmSync24,
|
|
470209
|
-
statSync as
|
|
470832
|
+
statSync as statSync24,
|
|
470210
470833
|
writeFileSync as writeFileSync40
|
|
470211
470834
|
} from "node:fs";
|
|
470212
470835
|
import { mkdir as mkdir15, readdir as readdir13 } from "node:fs/promises";
|
|
470213
470836
|
import { tmpdir as tmpdir14 } from "node:os";
|
|
470214
|
-
import { basename as basename29, dirname as dirname36, join as
|
|
470837
|
+
import { basename as basename29, dirname as dirname36, join as join96, normalize as normalize4, resolve as resolve41, sep as sep8 } from "node:path";
|
|
470215
470838
|
import { parseArgs as parseArgs20, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
|
|
470216
470839
|
function printUsage17() {
|
|
470217
470840
|
console.log(`
|
|
@@ -470503,14 +471126,14 @@ async function resolveBranchAndSubdir(location) {
|
|
|
470503
471126
|
}
|
|
470504
471127
|
async function cloneSkillSource(location) {
|
|
470505
471128
|
const resolvedLocation = await resolveBranchAndSubdir(location);
|
|
470506
|
-
const tmpDir = mkdtempSync6(
|
|
471129
|
+
const tmpDir = mkdtempSync6(join96(tmpdir14(), "letta-skill-install-"));
|
|
470507
471130
|
const args = ["clone", "--depth", "1"];
|
|
470508
471131
|
if (resolvedLocation.branch) {
|
|
470509
471132
|
args.push("--branch", resolvedLocation.branch);
|
|
470510
471133
|
}
|
|
470511
471134
|
args.push(resolvedLocation.repoUrl, tmpDir);
|
|
470512
471135
|
await execFile22("git", args, { timeout: 120000 });
|
|
470513
|
-
const sourceDir = resolvedLocation.subdir ?
|
|
471136
|
+
const sourceDir = resolvedLocation.subdir ? join96(tmpDir, resolvedLocation.subdir) : tmpDir;
|
|
470514
471137
|
return { tmpDir, sourceDir };
|
|
470515
471138
|
}
|
|
470516
471139
|
function assertDirectSkillFileSize(receivedBytes, maxBytes) {
|
|
@@ -470565,11 +471188,11 @@ async function downloadDirectSkillFileSource(location, options = {}) {
|
|
|
470565
471188
|
throw new Error(`Direct skill file download failed for ${location.url}: ${response.status}`);
|
|
470566
471189
|
}
|
|
470567
471190
|
const skillText = await readResponseTextWithLimit(response, MAX_DIRECT_SKILL_FILE_BYTES);
|
|
470568
|
-
const tmpDir = mkdtempSync6(
|
|
471191
|
+
const tmpDir = mkdtempSync6(join96(tmpdir14(), "letta-direct-skill-"));
|
|
470569
471192
|
try {
|
|
470570
|
-
const sourceDir =
|
|
471193
|
+
const sourceDir = join96(tmpDir, "skill");
|
|
470571
471194
|
await mkdir15(sourceDir, { recursive: true });
|
|
470572
|
-
writeFileSync40(
|
|
471195
|
+
writeFileSync40(join96(sourceDir, "SKILL.md"), skillText, "utf8");
|
|
470573
471196
|
return { tmpDir, sourceDir };
|
|
470574
471197
|
} catch (error5) {
|
|
470575
471198
|
rmSync24(tmpDir, { recursive: true, force: true });
|
|
@@ -470610,9 +471233,9 @@ function assertSafeZipMember(name) {
|
|
|
470610
471233
|
}
|
|
470611
471234
|
async function downloadClawHubSkillSource(location) {
|
|
470612
471235
|
const version3 = await resolveClawHubVersion(location);
|
|
470613
|
-
const tmpDir = mkdtempSync6(
|
|
470614
|
-
const zipPath =
|
|
470615
|
-
const sourceDir =
|
|
471236
|
+
const tmpDir = mkdtempSync6(join96(tmpdir14(), "letta-clawhub-skill-"));
|
|
471237
|
+
const zipPath = join96(tmpDir, "skill.zip");
|
|
471238
|
+
const sourceDir = join96(tmpDir, "skill");
|
|
470616
471239
|
await mkdir15(sourceDir, { recursive: true });
|
|
470617
471240
|
const url2 = new URL(`${CLAWHUB_API_BASE_URL}/download`);
|
|
470618
471241
|
url2.searchParams.set("slug", location.slug);
|
|
@@ -470639,7 +471262,7 @@ async function downloadClawHubSkillSource(location) {
|
|
|
470639
471262
|
function assertInside(parent, child) {
|
|
470640
471263
|
const parentPath = resolve41(parent);
|
|
470641
471264
|
const childPath = resolve41(child);
|
|
470642
|
-
if (childPath !== parentPath && !childPath.startsWith(`${parentPath}${
|
|
471265
|
+
if (childPath !== parentPath && !childPath.startsWith(`${parentPath}${sep8}`)) {
|
|
470643
471266
|
throw new Error(`Resolved path is outside target directory: ${child}`);
|
|
470644
471267
|
}
|
|
470645
471268
|
}
|
|
@@ -470651,7 +471274,7 @@ function sanitizeSkillName(name) {
|
|
|
470651
471274
|
return trimmed;
|
|
470652
471275
|
}
|
|
470653
471276
|
function getSkillName(sourceDir) {
|
|
470654
|
-
const skillMd =
|
|
471277
|
+
const skillMd = readFileSync49(join96(sourceDir, "SKILL.md"), "utf8");
|
|
470655
471278
|
const { frontmatter } = parseFrontmatter(skillMd);
|
|
470656
471279
|
const frontmatterName = frontmatter.name;
|
|
470657
471280
|
const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename29(sourceDir);
|
|
@@ -470660,18 +471283,18 @@ function getSkillName(sourceDir) {
|
|
|
470660
471283
|
async function installSkillDirectory(params) {
|
|
470661
471284
|
const sourceDir = resolve41(params.sourceDir);
|
|
470662
471285
|
const memoryDir = resolve41(params.memoryDir);
|
|
470663
|
-
const skillMdPath =
|
|
470664
|
-
if (!
|
|
471286
|
+
const skillMdPath = join96(sourceDir, "SKILL.md");
|
|
471287
|
+
if (!existsSync68(skillMdPath)) {
|
|
470665
471288
|
throw new Error("No SKILL.md found in the skill directory.");
|
|
470666
471289
|
}
|
|
470667
|
-
if (!
|
|
471290
|
+
if (!statSync24(sourceDir).isDirectory()) {
|
|
470668
471291
|
throw new Error(`Skill source is not a directory: ${sourceDir}`);
|
|
470669
471292
|
}
|
|
470670
471293
|
const name = getSkillName(sourceDir);
|
|
470671
|
-
const skillsDir =
|
|
470672
|
-
const targetPath =
|
|
471294
|
+
const skillsDir = join96(memoryDir, "skills");
|
|
471295
|
+
const targetPath = join96(skillsDir, name);
|
|
470673
471296
|
assertInside(skillsDir, targetPath);
|
|
470674
|
-
if (
|
|
471297
|
+
if (existsSync68(targetPath)) {
|
|
470675
471298
|
if (!params.force) {
|
|
470676
471299
|
throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
|
|
470677
471300
|
}
|
|
@@ -470686,22 +471309,22 @@ async function installSkillDirectory(params) {
|
|
|
470686
471309
|
}
|
|
470687
471310
|
async function listSkillDirectories(params) {
|
|
470688
471311
|
const memoryDir = resolve41(params.memoryDir);
|
|
470689
|
-
const skillsDir =
|
|
470690
|
-
if (!
|
|
471312
|
+
const skillsDir = join96(memoryDir, "skills");
|
|
471313
|
+
if (!existsSync68(skillsDir))
|
|
470691
471314
|
return [];
|
|
470692
471315
|
const entries2 = await readdir13(skillsDir, { withFileTypes: true });
|
|
470693
471316
|
const skills = [];
|
|
470694
471317
|
for (const entry of entries2) {
|
|
470695
471318
|
if (!entry.isDirectory())
|
|
470696
471319
|
continue;
|
|
470697
|
-
const skillDir =
|
|
470698
|
-
const skillMdPath =
|
|
470699
|
-
if (!
|
|
471320
|
+
const skillDir = join96(skillsDir, entry.name);
|
|
471321
|
+
const skillMdPath = join96(skillDir, "SKILL.md");
|
|
471322
|
+
if (!existsSync68(skillMdPath))
|
|
470700
471323
|
continue;
|
|
470701
471324
|
let name = entry.name;
|
|
470702
471325
|
let description;
|
|
470703
471326
|
try {
|
|
470704
|
-
const skillMd =
|
|
471327
|
+
const skillMd = readFileSync49(skillMdPath, "utf8");
|
|
470705
471328
|
const { frontmatter } = parseFrontmatter(skillMd);
|
|
470706
471329
|
if (typeof frontmatter.name === "string" && frontmatter.name.trim()) {
|
|
470707
471330
|
name = frontmatter.name.trim();
|
|
@@ -470716,14 +471339,14 @@ async function listSkillDirectories(params) {
|
|
|
470716
471339
|
}
|
|
470717
471340
|
async function deleteSkillDirectory(params) {
|
|
470718
471341
|
const memoryDir = resolve41(params.memoryDir);
|
|
470719
|
-
const skillsDir =
|
|
471342
|
+
const skillsDir = join96(memoryDir, "skills");
|
|
470720
471343
|
const name = sanitizeSkillName(params.name);
|
|
470721
|
-
const targetPath =
|
|
471344
|
+
const targetPath = join96(skillsDir, name);
|
|
470722
471345
|
assertInside(skillsDir, targetPath);
|
|
470723
|
-
if (!
|
|
471346
|
+
if (!existsSync68(targetPath)) {
|
|
470724
471347
|
throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
|
|
470725
471348
|
}
|
|
470726
|
-
if (!
|
|
471349
|
+
if (!statSync24(targetPath).isDirectory()) {
|
|
470727
471350
|
throw new Error(`Skill path is not a directory: ${targetPath}`);
|
|
470728
471351
|
}
|
|
470729
471352
|
rmSync24(targetPath, { recursive: true, force: true });
|
|
@@ -470769,7 +471392,7 @@ async function installSkill(specifier, agentId, force) {
|
|
|
470769
471392
|
tmpDir = downloaded.tmpDir;
|
|
470770
471393
|
const sourceDir = resolve41(downloaded.sourceDir);
|
|
470771
471394
|
assertInside(tmpDir, sourceDir);
|
|
470772
|
-
if (!
|
|
471395
|
+
if (!existsSync68(sourceDir)) {
|
|
470773
471396
|
const missingPath = source.type === "git" ? source.location.subdir ?? "." : source.type === "direct-file" ? source.location.url : source.location.slug;
|
|
470774
471397
|
throw new Error(`Skill path not found: ${missingPath}`);
|
|
470775
471398
|
}
|
|
@@ -471304,7 +471927,7 @@ var init_teleport2 = __esm(() => {
|
|
|
471304
471927
|
|
|
471305
471928
|
// src/cli/subcommands/trajectories/readers.ts
|
|
471306
471929
|
import { readdir as readdir14, readFile as readFile27, stat as stat16 } from "node:fs/promises";
|
|
471307
|
-
import { join as
|
|
471930
|
+
import { join as join97 } from "node:path";
|
|
471308
471931
|
async function loadSessionTranscript(item) {
|
|
471309
471932
|
const stats = await stat16(item.path);
|
|
471310
471933
|
if (stats.isDirectory()) {
|
|
@@ -471316,13 +471939,13 @@ async function loadSessionTranscript(item) {
|
|
|
471316
471939
|
return readFile27(item.path, "utf-8");
|
|
471317
471940
|
}
|
|
471318
471941
|
async function assembleEventDirectory(sessionDir) {
|
|
471319
|
-
const eventsSubdir =
|
|
471942
|
+
const eventsSubdir = join97(sessionDir, "events");
|
|
471320
471943
|
const eventsDir = (await stat16(eventsSubdir).catch(() => null))?.isDirectory() ? eventsSubdir : sessionDir;
|
|
471321
471944
|
const names2 = (await readdir14(eventsDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a2, b3) => Number.parseInt(a2, 10) - Number.parseInt(b3, 10) || a2.localeCompare(b3));
|
|
471322
471945
|
if (names2.length === 0) {
|
|
471323
471946
|
throw new Error(`No event files found in ${eventsDir}`);
|
|
471324
471947
|
}
|
|
471325
|
-
const events = await Promise.all(names2.map(async (name) => JSON.parse(await readFile27(
|
|
471948
|
+
const events = await Promise.all(names2.map(async (name) => JSON.parse(await readFile27(join97(eventsDir, name), "utf-8"))));
|
|
471326
471949
|
return JSON.stringify(events);
|
|
471327
471950
|
}
|
|
471328
471951
|
async function openReadOnlyDatabase(path47) {
|
|
@@ -471400,7 +472023,7 @@ import {
|
|
|
471400
472023
|
stat as stat17,
|
|
471401
472024
|
writeFile as writeFile19
|
|
471402
472025
|
} from "node:fs/promises";
|
|
471403
|
-
import { basename as basename30, join as
|
|
472026
|
+
import { basename as basename30, join as join98 } from "node:path";
|
|
471404
472027
|
function fileTimestamp(startedAt) {
|
|
471405
472028
|
if (!startedAt)
|
|
471406
472029
|
return "unknown-date";
|
|
@@ -471470,7 +472093,7 @@ async function prepareOutDir(outDir) {
|
|
|
471470
472093
|
throw new Error(`--out ${outDir} is not empty and has no ${MANIFEST_NAME}; refusing to overwrite a directory this tool did not create`);
|
|
471471
472094
|
}
|
|
471472
472095
|
for (const entry of entries2) {
|
|
471473
|
-
await rm12(
|
|
472096
|
+
await rm12(join98(outDir, entry), { recursive: true, force: true });
|
|
471474
472097
|
}
|
|
471475
472098
|
} catch (error5) {
|
|
471476
472099
|
if (error5.code !== "ENOENT")
|
|
@@ -471513,14 +472136,14 @@ async function runTrajectoryExport(options) {
|
|
|
471513
472136
|
}
|
|
471514
472137
|
const sessionId = sessionHash(source, id2);
|
|
471515
472138
|
const base2 = `${fileTimestamp(stats.startedAt)}_${sessionId}`;
|
|
471516
|
-
let file =
|
|
472139
|
+
let file = join98(source, `${base2}.json`);
|
|
471517
472140
|
for (let suffix = 2;usedFiles.has(file); suffix += 1) {
|
|
471518
|
-
file =
|
|
472141
|
+
file = join98(source, `${base2}-${suffix}.json`);
|
|
471519
472142
|
}
|
|
471520
472143
|
usedFiles.add(file);
|
|
471521
472144
|
const body3 = JSON.stringify(records2);
|
|
471522
|
-
await mkdir16(
|
|
471523
|
-
await writeFile19(
|
|
472145
|
+
await mkdir16(join98(options.outDir, source), { recursive: true });
|
|
472146
|
+
await writeFile19(join98(options.outDir, file), body3, "utf-8");
|
|
471524
472147
|
counts.exported += 1;
|
|
471525
472148
|
manifest2.sessions.push({
|
|
471526
472149
|
source,
|
|
@@ -471574,7 +472197,7 @@ async function runTrajectoryExport(options) {
|
|
|
471574
472197
|
await exportCheckpoint(checkpoint, `${basename30(checkpoint.path)}-${checkpoint.threadId}`);
|
|
471575
472198
|
}
|
|
471576
472199
|
manifest2.sessions.sort((a2, b3) => (a2.startedAt ?? "").localeCompare(b3.startedAt ?? ""));
|
|
471577
|
-
await writeFile19(
|
|
472200
|
+
await writeFile19(join98(options.outDir, MANIFEST_NAME), JSON.stringify(manifest2, null, 2), "utf-8");
|
|
471578
472201
|
return manifest2;
|
|
471579
472202
|
}
|
|
471580
472203
|
var MANIFEST_NAME = "manifest.json", FIRST_PROMPT_MAX_CHARS = 200, LIST_PAGE_LIMIT = 1000;
|
|
@@ -471586,13 +472209,13 @@ var init_export = __esm(() => {
|
|
|
471586
472209
|
|
|
471587
472210
|
// src/cli/subcommands/trajectories/review.ts
|
|
471588
472211
|
import { readFile as readFile29 } from "node:fs/promises";
|
|
471589
|
-
import { isAbsolute as isAbsolute26, join as
|
|
472212
|
+
import { isAbsolute as isAbsolute26, join as join99 } from "node:path";
|
|
471590
472213
|
async function readManifest(dir) {
|
|
471591
472214
|
let raw2;
|
|
471592
472215
|
try {
|
|
471593
|
-
raw2 = await readFile29(
|
|
472216
|
+
raw2 = await readFile29(join99(dir, "manifest.json"), "utf-8");
|
|
471594
472217
|
} catch {
|
|
471595
|
-
throw new Error(`No manifest at ${
|
|
472218
|
+
throw new Error(`No manifest at ${join99(dir, "manifest.json")}. Run: letta trajectories export --out ${dir}`);
|
|
471596
472219
|
}
|
|
471597
472220
|
return JSON.parse(raw2);
|
|
471598
472221
|
}
|
|
@@ -471601,7 +472224,7 @@ function filterSessions(sessions3, filter3) {
|
|
|
471601
472224
|
}
|
|
471602
472225
|
async function resolveSessionFile(dir, target2) {
|
|
471603
472226
|
if (target2.endsWith(".json")) {
|
|
471604
|
-
const direct = isAbsolute26(target2) ? target2 :
|
|
472227
|
+
const direct = isAbsolute26(target2) ? target2 : join99(dir, target2);
|
|
471605
472228
|
try {
|
|
471606
472229
|
await readFile29(direct, "utf-8");
|
|
471607
472230
|
return direct;
|
|
@@ -471612,7 +472235,7 @@ async function resolveSessionFile(dir, target2) {
|
|
|
471612
472235
|
if (!entry) {
|
|
471613
472236
|
throw new Error(`No session "${target2}" in ${dir} (pass a file path, a manifest-relative file, or a sessionId)`);
|
|
471614
472237
|
}
|
|
471615
|
-
return
|
|
472238
|
+
return join99(dir, entry.file);
|
|
471616
472239
|
}
|
|
471617
472240
|
function stamp(timestamp) {
|
|
471618
472241
|
return (timestamp ?? "").slice(0, 19);
|
|
@@ -471655,7 +472278,7 @@ async function searchSessions(dir, keyword, options = {}) {
|
|
|
471655
472278
|
for (const session2 of filterSessions(manifest2.sessions, options)) {
|
|
471656
472279
|
let records2;
|
|
471657
472280
|
try {
|
|
471658
|
-
records2 = JSON.parse(await readFile29(
|
|
472281
|
+
records2 = JSON.parse(await readFile29(join99(dir, session2.file), "utf-8"));
|
|
471659
472282
|
} catch {
|
|
471660
472283
|
continue;
|
|
471661
472284
|
}
|
|
@@ -475019,7 +475642,7 @@ var init_message_channel_gateway_tool = __esm(() => {
|
|
|
475019
475642
|
});
|
|
475020
475643
|
|
|
475021
475644
|
// src/channels/custom/scaffolding.ts
|
|
475022
|
-
import { existsSync as
|
|
475645
|
+
import { existsSync as existsSync69, mkdirSync as mkdirSync48, rmSync as rmSync25, writeFileSync as writeFileSync41 } from "node:fs";
|
|
475023
475646
|
function removeUserPlugin(channelId) {
|
|
475024
475647
|
if (FIRST_PARTY_SET.has(channelId)) {
|
|
475025
475648
|
return;
|
|
@@ -475028,7 +475651,7 @@ function removeUserPlugin(channelId) {
|
|
|
475028
475651
|
return;
|
|
475029
475652
|
}
|
|
475030
475653
|
const channelDir = getChannelDir(channelId);
|
|
475031
|
-
if (!
|
|
475654
|
+
if (!existsSync69(channelDir)) {
|
|
475032
475655
|
return;
|
|
475033
475656
|
}
|
|
475034
475657
|
try {
|
|
@@ -476770,7 +477393,7 @@ var init_router = __esm(async () => {
|
|
|
476770
477393
|
init_feedback3();
|
|
476771
477394
|
init_local_backend2();
|
|
476772
477395
|
init_mcp();
|
|
476773
|
-
|
|
477396
|
+
init_memory7();
|
|
476774
477397
|
init_messages10();
|
|
476775
477398
|
init_model2();
|
|
476776
477399
|
init_permissions2();
|
|
@@ -477908,7 +478531,7 @@ function resolveHeadlessMemfsPolicy(options) {
|
|
|
477908
478531
|
}
|
|
477909
478532
|
|
|
477910
478533
|
// src/headless-mod-adapter.ts
|
|
477911
|
-
import { join as
|
|
478534
|
+
import { join as join100 } from "node:path";
|
|
477912
478535
|
function isHeadlessMemfsEnabled(agentId) {
|
|
477913
478536
|
try {
|
|
477914
478537
|
return settingsManager.isMemfsEnabled(agentId);
|
|
@@ -477979,7 +478602,7 @@ function createHeadlessModContext(options) {
|
|
|
477979
478602
|
};
|
|
477980
478603
|
}
|
|
477981
478604
|
function createHeadlessModAdapter(options) {
|
|
477982
|
-
const agentModsDirectory = isHeadlessMemfsEnabled(options.agent.id) ?
|
|
478605
|
+
const agentModsDirectory = isHeadlessMemfsEnabled(options.agent.id) ? join100(getScopedMemoryFilesystemRoot(options.agent.id), "mods") : undefined;
|
|
477983
478606
|
return createModAdapter({
|
|
477984
478607
|
...agentModsDirectory ? { agentModsDirectory } : {},
|
|
477985
478608
|
...options.cacheDirectory ? { cacheDirectory: options.cacheDirectory } : {},
|
|
@@ -482649,10 +483272,10 @@ var init_cli_mod_context = __esm(() => {
|
|
|
482649
483272
|
|
|
482650
483273
|
// src/cli/helpers/reflection-arena-hf-upload.ts
|
|
482651
483274
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
482652
|
-
import { existsSync as
|
|
483275
|
+
import { existsSync as existsSync71 } from "node:fs";
|
|
482653
483276
|
import { appendFile as appendFile2, chmod, mkdir as mkdir17, writeFile as writeFile20 } from "node:fs/promises";
|
|
482654
483277
|
import { homedir as homedir53 } from "node:os";
|
|
482655
|
-
import { join as
|
|
483278
|
+
import { join as join102 } from "node:path";
|
|
482656
483279
|
import { promisify as promisify20 } from "node:util";
|
|
482657
483280
|
function buildGitEnv(token2, askpassPath) {
|
|
482658
483281
|
return {
|
|
@@ -482688,7 +483311,7 @@ async function runGit6(cwd2, args, env6) {
|
|
|
482688
483311
|
}
|
|
482689
483312
|
}
|
|
482690
483313
|
async function writeGitAskpass(repoRoot) {
|
|
482691
|
-
const askpassPath =
|
|
483314
|
+
const askpassPath = join102(repoRoot, "hf-askpass.sh");
|
|
482692
483315
|
await writeFile20(askpassPath, [
|
|
482693
483316
|
"#!/bin/sh",
|
|
482694
483317
|
'case "$1" in',
|
|
@@ -482703,7 +483326,7 @@ async function writeGitAskpass(repoRoot) {
|
|
|
482703
483326
|
}
|
|
482704
483327
|
async function prepareHfRepo(env6) {
|
|
482705
483328
|
await mkdir17(HF_CACHE_ROOT, { recursive: true });
|
|
482706
|
-
if (!
|
|
483329
|
+
if (!existsSync71(join102(HF_REPO_DIR, ".git"))) {
|
|
482707
483330
|
await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env6);
|
|
482708
483331
|
return HF_REPO_DIR;
|
|
482709
483332
|
}
|
|
@@ -482738,8 +483361,8 @@ async function maybeUploadReflectionArenaChoiceToHf(row) {
|
|
|
482738
483361
|
const env6 = buildGitEnv(token2, askpassPath);
|
|
482739
483362
|
try {
|
|
482740
483363
|
const repoDir = await prepareHfRepo(env6);
|
|
482741
|
-
await mkdir17(
|
|
482742
|
-
await appendFile2(
|
|
483364
|
+
await mkdir17(join102(repoDir, "data"), { recursive: true });
|
|
483365
|
+
await appendFile2(join102(repoDir, HF_DATASET_PATH), `${JSON.stringify(row)}
|
|
482743
483366
|
`, {
|
|
482744
483367
|
encoding: "utf-8"
|
|
482745
483368
|
});
|
|
@@ -482767,8 +483390,8 @@ var init_reflection_arena_hf_upload = __esm(() => {
|
|
|
482767
483390
|
init_version();
|
|
482768
483391
|
execFile23 = promisify20(execFileCb5);
|
|
482769
483392
|
HF_REPO_URL = `https://huggingface.co/datasets/${HF_REPO_ID}`;
|
|
482770
|
-
HF_CACHE_ROOT =
|
|
482771
|
-
HF_REPO_DIR =
|
|
483393
|
+
HF_CACHE_ROOT = join102(homedir53(), ".letta", "reflection-arena", "hf-upload");
|
|
483394
|
+
HF_REPO_DIR = join102(HF_CACHE_ROOT, "repo");
|
|
482772
483395
|
});
|
|
482773
483396
|
|
|
482774
483397
|
// src/cli/helpers/reflection-arena.ts
|
|
@@ -482776,7 +483399,7 @@ import { execFile as execFileCb6 } from "node:child_process";
|
|
|
482776
483399
|
import { randomInt as randomInt2, randomUUID as randomUUID57 } from "node:crypto";
|
|
482777
483400
|
import { appendFile as appendFile3, mkdir as mkdir18, readFile as readFile31, writeFile as writeFile21 } from "node:fs/promises";
|
|
482778
483401
|
import { homedir as homedir54 } from "node:os";
|
|
482779
|
-
import { join as
|
|
483402
|
+
import { join as join103 } from "node:path";
|
|
482780
483403
|
import { promisify as promisify21 } from "node:util";
|
|
482781
483404
|
function sampleReflectionArenaComparisonModel(excludedModels = []) {
|
|
482782
483405
|
const excluded = new Set(excludedModels);
|
|
@@ -482825,16 +483448,16 @@ function candidateIsConfirmedNoOp(candidate) {
|
|
|
482825
483448
|
return candidate.result?.success === true && candidate.result.memoryNoChanges === true && candidate.result.memoryHead === candidate.worktree.baseHead;
|
|
482826
483449
|
}
|
|
482827
483450
|
function getReflectionArenaRoot() {
|
|
482828
|
-
return
|
|
483451
|
+
return join103(homedir54(), ".letta", "reflection-arena");
|
|
482829
483452
|
}
|
|
482830
483453
|
function getReflectionArenaRunsDir() {
|
|
482831
|
-
return
|
|
483454
|
+
return join103(getReflectionArenaRoot(), "runs");
|
|
482832
483455
|
}
|
|
482833
483456
|
function getReflectionArenaChoiceLogPath() {
|
|
482834
|
-
return
|
|
483457
|
+
return join103(getReflectionArenaRoot(), "choices.jsonl");
|
|
482835
483458
|
}
|
|
482836
483459
|
function getReflectionArenaRunPath(runId) {
|
|
482837
|
-
return
|
|
483460
|
+
return join103(getReflectionArenaRunsDir(), `${runId}.json`);
|
|
482838
483461
|
}
|
|
482839
483462
|
async function saveReflectionArenaRun(run) {
|
|
482840
483463
|
await mkdir18(getReflectionArenaRunsDir(), { recursive: true });
|
|
@@ -484262,13 +484885,13 @@ __export(exports_terminal_keybinding_installer, {
|
|
|
484262
484885
|
});
|
|
484263
484886
|
import {
|
|
484264
484887
|
copyFileSync as copyFileSync6,
|
|
484265
|
-
existsSync as
|
|
484888
|
+
existsSync as existsSync72,
|
|
484266
484889
|
mkdirSync as mkdirSync50,
|
|
484267
|
-
readFileSync as
|
|
484890
|
+
readFileSync as readFileSync51,
|
|
484268
484891
|
writeFileSync as writeFileSync43
|
|
484269
484892
|
} from "node:fs";
|
|
484270
484893
|
import { homedir as homedir55, platform as platform10 } from "node:os";
|
|
484271
|
-
import { dirname as dirname37, join as
|
|
484894
|
+
import { dirname as dirname37, join as join104 } from "node:path";
|
|
484272
484895
|
function detectTerminalType() {
|
|
484273
484896
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
484274
484897
|
return "cursor";
|
|
@@ -484300,16 +484923,16 @@ function getKeybindingsPath(terminal) {
|
|
|
484300
484923
|
}[terminal];
|
|
484301
484924
|
const os9 = platform10();
|
|
484302
484925
|
if (os9 === "darwin") {
|
|
484303
|
-
return
|
|
484926
|
+
return join104(homedir55(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
484304
484927
|
}
|
|
484305
484928
|
if (os9 === "win32") {
|
|
484306
484929
|
const appData = process.env.APPDATA;
|
|
484307
484930
|
if (!appData)
|
|
484308
484931
|
return null;
|
|
484309
|
-
return
|
|
484932
|
+
return join104(appData, appName, "User", "keybindings.json");
|
|
484310
484933
|
}
|
|
484311
484934
|
if (os9 === "linux") {
|
|
484312
|
-
return
|
|
484935
|
+
return join104(homedir55(), ".config", appName, "User", "keybindings.json");
|
|
484313
484936
|
}
|
|
484314
484937
|
return null;
|
|
484315
484938
|
}
|
|
@@ -484331,10 +484954,10 @@ function parseKeybindings(content) {
|
|
|
484331
484954
|
}
|
|
484332
484955
|
}
|
|
484333
484956
|
function keybindingExists(keybindingsPath) {
|
|
484334
|
-
if (!
|
|
484957
|
+
if (!existsSync72(keybindingsPath))
|
|
484335
484958
|
return false;
|
|
484336
484959
|
try {
|
|
484337
|
-
const content =
|
|
484960
|
+
const content = readFileSync51(keybindingsPath, { encoding: "utf-8" });
|
|
484338
484961
|
const keybindings = parseKeybindings(content);
|
|
484339
484962
|
if (!keybindings)
|
|
484340
484963
|
return false;
|
|
@@ -484344,7 +484967,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
484344
484967
|
}
|
|
484345
484968
|
}
|
|
484346
484969
|
function createBackup(keybindingsPath) {
|
|
484347
|
-
if (!
|
|
484970
|
+
if (!existsSync72(keybindingsPath))
|
|
484348
484971
|
return null;
|
|
484349
484972
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
484350
484973
|
try {
|
|
@@ -484360,14 +484983,14 @@ function installKeybinding(keybindingsPath) {
|
|
|
484360
484983
|
return { success: true, alreadyExists: true };
|
|
484361
484984
|
}
|
|
484362
484985
|
const parentDir = dirname37(keybindingsPath);
|
|
484363
|
-
if (!
|
|
484986
|
+
if (!existsSync72(parentDir)) {
|
|
484364
484987
|
mkdirSync50(parentDir, { recursive: true });
|
|
484365
484988
|
}
|
|
484366
484989
|
let keybindings = [];
|
|
484367
484990
|
let backupPath = null;
|
|
484368
|
-
if (
|
|
484991
|
+
if (existsSync72(keybindingsPath)) {
|
|
484369
484992
|
backupPath = createBackup(keybindingsPath);
|
|
484370
|
-
const content =
|
|
484993
|
+
const content = readFileSync51(keybindingsPath, { encoding: "utf-8" });
|
|
484371
484994
|
const parsed = parseKeybindings(content);
|
|
484372
484995
|
if (parsed === null) {
|
|
484373
484996
|
return {
|
|
@@ -484395,10 +485018,10 @@ function installKeybinding(keybindingsPath) {
|
|
|
484395
485018
|
}
|
|
484396
485019
|
function removeKeybinding(keybindingsPath) {
|
|
484397
485020
|
try {
|
|
484398
|
-
if (!
|
|
485021
|
+
if (!existsSync72(keybindingsPath)) {
|
|
484399
485022
|
return { success: true };
|
|
484400
485023
|
}
|
|
484401
|
-
const content =
|
|
485024
|
+
const content = readFileSync51(keybindingsPath, { encoding: "utf-8" });
|
|
484402
485025
|
const keybindings = parseKeybindings(content);
|
|
484403
485026
|
if (!keybindings) {
|
|
484404
485027
|
return {
|
|
@@ -484462,14 +485085,14 @@ function getWezTermConfigPath() {
|
|
|
484462
485085
|
}
|
|
484463
485086
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
484464
485087
|
if (xdgConfig) {
|
|
484465
|
-
const xdgPath =
|
|
484466
|
-
if (
|
|
485088
|
+
const xdgPath = join104(xdgConfig, "wezterm", "wezterm.lua");
|
|
485089
|
+
if (existsSync72(xdgPath))
|
|
484467
485090
|
return xdgPath;
|
|
484468
485091
|
}
|
|
484469
|
-
const configPath =
|
|
484470
|
-
if (
|
|
485092
|
+
const configPath = join104(homedir55(), ".config", "wezterm", "wezterm.lua");
|
|
485093
|
+
if (existsSync72(configPath))
|
|
484471
485094
|
return configPath;
|
|
484472
|
-
return
|
|
485095
|
+
return join104(homedir55(), ".wezterm.lua");
|
|
484473
485096
|
}
|
|
484474
485097
|
function stripLuaCommentsFromLine(line, blockCommentEnd) {
|
|
484475
485098
|
let code2 = "";
|
|
@@ -484572,10 +485195,10 @@ ${WEZTERM_DELETE_FIX}
|
|
|
484572
485195
|
`;
|
|
484573
485196
|
}
|
|
484574
485197
|
function wezTermDeleteFixExists(configPath) {
|
|
484575
|
-
if (!
|
|
485198
|
+
if (!existsSync72(configPath))
|
|
484576
485199
|
return false;
|
|
484577
485200
|
try {
|
|
484578
|
-
const content =
|
|
485201
|
+
const content = readFileSync51(configPath, { encoding: "utf-8" });
|
|
484579
485202
|
return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
|
|
484580
485203
|
} catch {
|
|
484581
485204
|
return false;
|
|
@@ -484589,14 +485212,14 @@ function installWezTermDeleteFix() {
|
|
|
484589
485212
|
}
|
|
484590
485213
|
let content = "";
|
|
484591
485214
|
let backupPath = null;
|
|
484592
|
-
if (
|
|
485215
|
+
if (existsSync72(configPath)) {
|
|
484593
485216
|
backupPath = `${configPath}.letta-backup`;
|
|
484594
485217
|
copyFileSync6(configPath, backupPath);
|
|
484595
|
-
content =
|
|
485218
|
+
content = readFileSync51(configPath, { encoding: "utf-8" });
|
|
484596
485219
|
}
|
|
484597
485220
|
content = injectWezTermDeleteFix(content);
|
|
484598
485221
|
const parentDir = dirname37(configPath);
|
|
484599
|
-
if (!
|
|
485222
|
+
if (!existsSync72(parentDir)) {
|
|
484600
485223
|
mkdirSync50(parentDir, { recursive: true });
|
|
484601
485224
|
}
|
|
484602
485225
|
writeFileSync43(configPath, content, { encoding: "utf-8" });
|
|
@@ -484648,9 +485271,9 @@ __export(exports_settings2, {
|
|
|
484648
485271
|
getSetting: () => getSetting
|
|
484649
485272
|
});
|
|
484650
485273
|
import { homedir as homedir56 } from "node:os";
|
|
484651
|
-
import { join as
|
|
485274
|
+
import { join as join105 } from "node:path";
|
|
484652
485275
|
function getSettingsPath() {
|
|
484653
|
-
return
|
|
485276
|
+
return join105(homedir56(), ".letta", "settings.json");
|
|
484654
485277
|
}
|
|
484655
485278
|
async function loadSettings() {
|
|
484656
485279
|
const settingsPath = getSettingsPath();
|
|
@@ -484687,7 +485310,7 @@ async function getSetting(key3) {
|
|
|
484687
485310
|
return settings3[key3];
|
|
484688
485311
|
}
|
|
484689
485312
|
function getProjectSettingsPath() {
|
|
484690
|
-
return
|
|
485313
|
+
return join105(process.cwd(), ".letta", "settings.local.json");
|
|
484691
485314
|
}
|
|
484692
485315
|
async function loadProjectSettings() {
|
|
484693
485316
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -484705,7 +485328,7 @@ async function loadProjectSettings() {
|
|
|
484705
485328
|
}
|
|
484706
485329
|
async function saveProjectSettings(settings3) {
|
|
484707
485330
|
const settingsPath = getProjectSettingsPath();
|
|
484708
|
-
const dirPath =
|
|
485331
|
+
const dirPath = join105(process.cwd(), ".letta");
|
|
484709
485332
|
try {
|
|
484710
485333
|
if (!exists(dirPath)) {
|
|
484711
485334
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -486593,9 +487216,9 @@ function getHeaderText(fileEdit) {
|
|
|
486593
487216
|
const relPath = relative13(cwd2, fileEdit.filePath);
|
|
486594
487217
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
486595
487218
|
if (t2 === "write") {
|
|
486596
|
-
const { existsSync:
|
|
487219
|
+
const { existsSync: existsSync73 } = __require("node:fs");
|
|
486597
487220
|
try {
|
|
486598
|
-
if (
|
|
487221
|
+
if (existsSync73(fileEdit.filePath)) {
|
|
486599
487222
|
return `Overwrite ${displayPath}?`;
|
|
486600
487223
|
}
|
|
486601
487224
|
} catch {}
|
|
@@ -495512,20 +496135,20 @@ var init_InputRich = __esm(async () => {
|
|
|
495512
496135
|
});
|
|
495513
496136
|
|
|
495514
496137
|
// src/cli/commands/install-github-app.ts
|
|
495515
|
-
import { execFileSync as
|
|
496138
|
+
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
495516
496139
|
import {
|
|
495517
|
-
existsSync as
|
|
496140
|
+
existsSync as existsSync73,
|
|
495518
496141
|
mkdirSync as mkdirSync51,
|
|
495519
496142
|
mkdtempSync as mkdtempSync7,
|
|
495520
|
-
readFileSync as
|
|
496143
|
+
readFileSync as readFileSync52,
|
|
495521
496144
|
rmSync as rmSync26,
|
|
495522
496145
|
writeFileSync as writeFileSync44
|
|
495523
496146
|
} from "node:fs";
|
|
495524
496147
|
import { tmpdir as tmpdir15 } from "node:os";
|
|
495525
|
-
import { dirname as dirname38, join as
|
|
496148
|
+
import { dirname as dirname38, join as join106 } from "node:path";
|
|
495526
496149
|
function runCommand(command, args, cwd2, input) {
|
|
495527
496150
|
try {
|
|
495528
|
-
return
|
|
496151
|
+
return execFileSync10(command, args, {
|
|
495529
496152
|
cwd: cwd2,
|
|
495530
496153
|
encoding: "utf8",
|
|
495531
496154
|
stdio: [input ? "pipe" : "ignore", "pipe", "pipe"],
|
|
@@ -495743,8 +496366,8 @@ async function createLettaAgent(apiKey, name) {
|
|
|
495743
496366
|
return createMinimalAgent(apiKey, name);
|
|
495744
496367
|
}
|
|
495745
496368
|
function cloneRepoToTemp(repo) {
|
|
495746
|
-
const tempDir = mkdtempSync7(
|
|
495747
|
-
const repoDir =
|
|
496369
|
+
const tempDir = mkdtempSync7(join106(tmpdir15(), "letta-install-github-app-"));
|
|
496370
|
+
const repoDir = join106(tempDir, "repo");
|
|
495748
496371
|
runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
|
|
495749
496372
|
return { tempDir, repoDir };
|
|
495750
496373
|
}
|
|
@@ -495755,14 +496378,14 @@ function runGit7(args, cwd2) {
|
|
|
495755
496378
|
return runCommand("git", args, cwd2);
|
|
495756
496379
|
}
|
|
495757
496380
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
495758
|
-
const absolutePath =
|
|
495759
|
-
if (!
|
|
496381
|
+
const absolutePath = join106(repoDir, workflowPath);
|
|
496382
|
+
if (!existsSync73(dirname38(absolutePath))) {
|
|
495760
496383
|
mkdirSync51(dirname38(absolutePath), { recursive: true });
|
|
495761
496384
|
}
|
|
495762
496385
|
const next = `${content.trimEnd()}
|
|
495763
496386
|
`;
|
|
495764
|
-
if (
|
|
495765
|
-
const previous =
|
|
496387
|
+
if (existsSync73(absolutePath)) {
|
|
496388
|
+
const previous = readFileSync52(absolutePath, "utf8");
|
|
495766
496389
|
if (previous === next) {
|
|
495767
496390
|
return false;
|
|
495768
496391
|
}
|
|
@@ -499651,9 +500274,9 @@ __export(exports_generate_memory_viewer, {
|
|
|
499651
500274
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
499652
500275
|
});
|
|
499653
500276
|
import { execFile as execFileCb7 } from "node:child_process";
|
|
499654
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
500277
|
+
import { chmodSync as chmodSync8, existsSync as existsSync74, mkdirSync as mkdirSync52, writeFileSync as writeFileSync45 } from "node:fs";
|
|
499655
500278
|
import { homedir as homedir58 } from "node:os";
|
|
499656
|
-
import { join as
|
|
500279
|
+
import { join as join107 } from "node:path";
|
|
499657
500280
|
import { promisify as promisify22 } from "node:util";
|
|
499658
500281
|
function messagesFromOverview(overview) {
|
|
499659
500282
|
return overview.messages?.map((message) => ({
|
|
@@ -499962,7 +500585,7 @@ ${m4.body}` : m4.subject;
|
|
|
499962
500585
|
async function generateAndOpenMemoryViewer(agentId, options) {
|
|
499963
500586
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
499964
500587
|
const repoDir = memoryRoot;
|
|
499965
|
-
if (!
|
|
500588
|
+
if (!existsSync74(join107(repoDir, ".git"))) {
|
|
499966
500589
|
throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
|
|
499967
500590
|
}
|
|
499968
500591
|
const data = await collectMemoryData(agentId, repoDir, memoryRoot, options?.conversationId);
|
|
@@ -499972,13 +500595,13 @@ async function generateAndOpenMemoryViewer(agentId, options) {
|
|
|
499972
500595
|
data.context = applyContextUsageSnapshot(data.context, options?.contextUsage);
|
|
499973
500596
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
499974
500597
|
const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
499975
|
-
if (!
|
|
500598
|
+
if (!existsSync74(VIEWERS_DIR)) {
|
|
499976
500599
|
mkdirSync52(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
499977
500600
|
}
|
|
499978
500601
|
try {
|
|
499979
500602
|
chmodSync8(VIEWERS_DIR, 448);
|
|
499980
500603
|
} catch {}
|
|
499981
|
-
const filePath =
|
|
500604
|
+
const filePath = join107(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
499982
500605
|
writeFileSync45(filePath, html5);
|
|
499983
500606
|
chmodSync8(filePath, 384);
|
|
499984
500607
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -500004,13 +500627,13 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
500004
500627
|
init_local_memory_context();
|
|
500005
500628
|
init_memory_viewer_template();
|
|
500006
500629
|
execFile25 = promisify22(execFileCb7);
|
|
500007
|
-
VIEWERS_DIR =
|
|
500630
|
+
VIEWERS_DIR = join107(homedir58(), ".letta", "viewers");
|
|
500008
500631
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
500009
500632
|
});
|
|
500010
500633
|
|
|
500011
500634
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
500012
|
-
import { existsSync as
|
|
500013
|
-
import { join as
|
|
500635
|
+
import { existsSync as existsSync75 } from "node:fs";
|
|
500636
|
+
import { join as join108 } from "node:path";
|
|
500014
500637
|
function renderTreePrefix(node) {
|
|
500015
500638
|
let prefix = "";
|
|
500016
500639
|
for (let i4 = 0;i4 < node.depth; i4++) {
|
|
@@ -500038,8 +500661,8 @@ function MemfsTreeViewer({
|
|
|
500038
500661
|
const [status, setStatus] = import_react88.useState(null);
|
|
500039
500662
|
const statusTimerRef = import_react88.useRef(null);
|
|
500040
500663
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
500041
|
-
const memoryExists =
|
|
500042
|
-
const hasGitRepo = import_react88.useMemo(() =>
|
|
500664
|
+
const memoryExists = existsSync75(memoryRoot);
|
|
500665
|
+
const hasGitRepo = import_react88.useMemo(() => existsSync75(join108(memoryRoot, ".git")), [memoryRoot]);
|
|
500043
500666
|
function showStatus(msg, durationMs) {
|
|
500044
500667
|
if (statusTimerRef.current)
|
|
500045
500668
|
clearTimeout(statusTimerRef.current);
|
|
@@ -502415,10 +503038,10 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
502415
503038
|
// src/utils/aws-credentials.ts
|
|
502416
503039
|
import { readFile as readFile32 } from "node:fs/promises";
|
|
502417
503040
|
import { homedir as homedir59 } from "node:os";
|
|
502418
|
-
import { join as
|
|
503041
|
+
import { join as join109 } from "node:path";
|
|
502419
503042
|
async function parseAwsCredentials() {
|
|
502420
|
-
const credentialsPath =
|
|
502421
|
-
const configPath =
|
|
503043
|
+
const credentialsPath = join109(homedir59(), ".aws", "credentials");
|
|
503044
|
+
const configPath = join109(homedir59(), ".aws", "config");
|
|
502422
503045
|
const profiles = new Map;
|
|
502423
503046
|
try {
|
|
502424
503047
|
const content = await readFile32(credentialsPath, "utf-8");
|
|
@@ -504083,8 +504706,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
504083
504706
|
try {
|
|
504084
504707
|
const { discoverSkills: discoverSkills2, SKILLS_DIR: SKILLS_DIR2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
504085
504708
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
504086
|
-
const { join:
|
|
504087
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
504709
|
+
const { join: join110 } = await import("node:path");
|
|
504710
|
+
const skillsDir = getSkillsDirectory2() || join110(process.cwd(), SKILLS_DIR2);
|
|
504088
504711
|
const result3 = await discoverSkills2(skillsDir, agentId, {
|
|
504089
504712
|
sources: getSkillSources2()
|
|
504090
504713
|
});
|
|
@@ -508407,9 +509030,9 @@ function getFileEditHeader(toolName2, toolArgs) {
|
|
|
508407
509030
|
const relPath = relative13(cwd2, filePath);
|
|
508408
509031
|
const displayPath = relPath.startsWith("..") ? filePath : relPath;
|
|
508409
509032
|
if (t2 === "write") {
|
|
508410
|
-
const { existsSync:
|
|
509033
|
+
const { existsSync: existsSync76 } = __require("node:fs");
|
|
508411
509034
|
try {
|
|
508412
|
-
if (
|
|
509035
|
+
if (existsSync76(filePath)) {
|
|
508413
509036
|
return `Overwrite ${displayPath}?`;
|
|
508414
509037
|
}
|
|
508415
509038
|
} catch {}
|
|
@@ -510177,9 +510800,9 @@ __export(exports_generate_diff_viewer, {
|
|
|
510177
510800
|
generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
|
|
510178
510801
|
});
|
|
510179
510802
|
import { execFile as execFileCb8 } from "node:child_process";
|
|
510180
|
-
import { chmodSync as chmodSync9, existsSync as
|
|
510803
|
+
import { chmodSync as chmodSync9, existsSync as existsSync76, mkdirSync as mkdirSync53, writeFileSync as writeFileSync46 } from "node:fs";
|
|
510181
510804
|
import { homedir as homedir60 } from "node:os";
|
|
510182
|
-
import { isAbsolute as isAbsolute27, join as
|
|
510805
|
+
import { isAbsolute as isAbsolute27, join as join110, resolve as resolve44 } from "node:path";
|
|
510183
510806
|
import { promisify as promisify23 } from "node:util";
|
|
510184
510807
|
async function runGit8(cwd2, args) {
|
|
510185
510808
|
try {
|
|
@@ -510402,13 +511025,13 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
510402
511025
|
};
|
|
510403
511026
|
const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
510404
511027
|
const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
510405
|
-
if (!
|
|
511028
|
+
if (!existsSync76(VIEWERS_DIR2)) {
|
|
510406
511029
|
mkdirSync53(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
510407
511030
|
}
|
|
510408
511031
|
try {
|
|
510409
511032
|
chmodSync9(VIEWERS_DIR2, 448);
|
|
510410
511033
|
} catch {}
|
|
510411
|
-
const filePath =
|
|
511034
|
+
const filePath = join110(VIEWERS_DIR2, `diff-${encodeURIComponent(worktreePath)}.html`);
|
|
510412
511035
|
writeFileSync46(filePath, html5);
|
|
510413
511036
|
chmodSync9(filePath, 384);
|
|
510414
511037
|
const skipOpen = shouldSkipOpen();
|
|
@@ -510477,7 +511100,7 @@ var execFile26, VIEWERS_DIR2, GIT_TIMEOUT_MS3 = 60000, GIT_MAX_BUFFER, MAX_RENDE
|
|
|
510477
511100
|
var init_generate_diff_viewer = __esm(() => {
|
|
510478
511101
|
init_diff_viewer_template();
|
|
510479
511102
|
execFile26 = promisify23(execFileCb8);
|
|
510480
|
-
VIEWERS_DIR2 =
|
|
511103
|
+
VIEWERS_DIR2 = join110(homedir60(), ".letta", "viewers");
|
|
510481
511104
|
GIT_MAX_BUFFER = 50 * 1024 * 1024;
|
|
510482
511105
|
});
|
|
510483
511106
|
|
|
@@ -512422,16 +513045,16 @@ __export(exports_shell_aliases, {
|
|
|
512422
513045
|
expandAliases: () => expandAliases,
|
|
512423
513046
|
clearAliasCache: () => clearAliasCache
|
|
512424
513047
|
});
|
|
512425
|
-
import { existsSync as
|
|
513048
|
+
import { existsSync as existsSync77, readFileSync as readFileSync53 } from "node:fs";
|
|
512426
513049
|
import { homedir as homedir61 } from "node:os";
|
|
512427
|
-
import { join as
|
|
513050
|
+
import { join as join111 } from "node:path";
|
|
512428
513051
|
function parseAliasesFromFile(filePath) {
|
|
512429
513052
|
const aliases = new Map;
|
|
512430
|
-
if (!
|
|
513053
|
+
if (!existsSync77(filePath)) {
|
|
512431
513054
|
return aliases;
|
|
512432
513055
|
}
|
|
512433
513056
|
try {
|
|
512434
|
-
const content =
|
|
513057
|
+
const content = readFileSync53(filePath, "utf-8");
|
|
512435
513058
|
const lines = content.split(`
|
|
512436
513059
|
`);
|
|
512437
513060
|
let inFunction = false;
|
|
@@ -512496,7 +513119,7 @@ function loadAliases(forceReload = false) {
|
|
|
512496
513119
|
const home = homedir61();
|
|
512497
513120
|
const allAliases = new Map;
|
|
512498
513121
|
for (const file of ALIAS_FILES) {
|
|
512499
|
-
const filePath =
|
|
513122
|
+
const filePath = join111(home, file);
|
|
512500
513123
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
512501
513124
|
for (const [name, value] of fileAliases) {
|
|
512502
513125
|
allAliases.set(name, value);
|
|
@@ -520696,9 +521319,9 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
520696
521319
|
|
|
520697
521320
|
// src/cli/app/use-submit-handler.ts
|
|
520698
521321
|
import { randomUUID as randomUUID62 } from "node:crypto";
|
|
520699
|
-
import { existsSync as
|
|
521322
|
+
import { existsSync as existsSync78, readFileSync as readFileSync54, renameSync as renameSync13 } from "node:fs";
|
|
520700
521323
|
import { tmpdir as tmpdir16 } from "node:os";
|
|
520701
|
-
import { join as
|
|
521324
|
+
import { join as join112 } from "node:path";
|
|
520702
521325
|
async function findCustomCommandByName(commandName) {
|
|
520703
521326
|
const { findCustomCommand: findCustomCommand2 } = await Promise.resolve().then(() => (init_custom(), exports_custom));
|
|
520704
521327
|
return findCustomCommand2(commandName);
|
|
@@ -521306,12 +521929,12 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
521306
521929
|
try {
|
|
521307
521930
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
521308
521931
|
const personaCandidates = [
|
|
521309
|
-
|
|
521310
|
-
|
|
521932
|
+
join112(memoryRoot, "system", "persona.md"),
|
|
521933
|
+
join112(memoryRoot, "memory", "system", "persona.md")
|
|
521311
521934
|
];
|
|
521312
|
-
const personaPath = personaCandidates.find((candidate) =>
|
|
521935
|
+
const personaPath = personaCandidates.find((candidate) => existsSync78(candidate));
|
|
521313
521936
|
if (personaPath) {
|
|
521314
|
-
const personaContent =
|
|
521937
|
+
const personaContent = readFileSync54(personaPath, "utf-8");
|
|
521315
521938
|
setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
|
|
521316
521939
|
} else {
|
|
521317
521940
|
setCurrentPersonalityId(null);
|
|
@@ -522155,11 +522778,11 @@ Path: ${memoryDir}`, true);
|
|
|
522155
522778
|
setCommandRunning(true);
|
|
522156
522779
|
try {
|
|
522157
522780
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
522158
|
-
if (!
|
|
522781
|
+
if (!existsSync78(memoryDir)) {
|
|
522159
522782
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
522160
522783
|
return { submitted: true };
|
|
522161
522784
|
}
|
|
522162
|
-
const backupDir =
|
|
522785
|
+
const backupDir = join112(tmpdir16(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
522163
522786
|
renameSync13(memoryDir, backupDir);
|
|
522164
522787
|
if (getBackend().capabilities.localMemfs) {
|
|
522165
522788
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
@@ -523074,7 +523697,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
523074
523697
|
});
|
|
523075
523698
|
|
|
523076
523699
|
// src/cli/app/AppCoordinator.tsx
|
|
523077
|
-
import { join as
|
|
523700
|
+
import { join as join113 } from "node:path";
|
|
523078
523701
|
function buildStartupCommandHints(options) {
|
|
523079
523702
|
const {
|
|
523080
523703
|
isResumingConversation,
|
|
@@ -524356,7 +524979,7 @@ function App2({
|
|
|
524356
524979
|
agentId: a2.agentId ?? null
|
|
524357
524980
|
}))
|
|
524358
524981
|
});
|
|
524359
|
-
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ?
|
|
524982
|
+
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ? join113(modContext.memfs.memoryDir, "mods") : null;
|
|
524360
524983
|
const modAdapter = useLocalModAdapter(modContext, {
|
|
524361
524984
|
agentModsDirectory,
|
|
524362
524985
|
disabled: modsDisabled,
|
|
@@ -525112,9 +525735,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
525112
525735
|
(async () => {
|
|
525113
525736
|
try {
|
|
525114
525737
|
const { watch: watch4 } = await import("node:fs");
|
|
525115
|
-
const { existsSync:
|
|
525738
|
+
const { existsSync: existsSync79 } = await import("node:fs");
|
|
525116
525739
|
const memRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
525117
|
-
if (!
|
|
525740
|
+
if (!existsSync79(memRoot))
|
|
525118
525741
|
return;
|
|
525119
525742
|
watcher2 = watch4(memRoot, { recursive: true }, () => {});
|
|
525120
525743
|
memfsWatcherRef.current = watcher2;
|
|
@@ -526684,12 +527307,12 @@ EXAMPLES
|
|
|
526684
527307
|
console.log(usage);
|
|
526685
527308
|
}
|
|
526686
527309
|
async function printInfo() {
|
|
526687
|
-
const { join:
|
|
527310
|
+
const { join: join114 } = await import("node:path");
|
|
526688
527311
|
const { getVersion: getVersion2 } = await Promise.resolve().then(() => (init_version(), exports_version));
|
|
526689
527312
|
const { SKILLS_DIR: SKILLS_DIR2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
526690
527313
|
const { exists: exists2 } = await Promise.resolve().then(() => (init_fs(), exports_fs));
|
|
526691
527314
|
const cwd2 = process.cwd();
|
|
526692
|
-
const skillsDir =
|
|
527315
|
+
const skillsDir = join114(cwd2, SKILLS_DIR2);
|
|
526693
527316
|
const skillsExist = exists2(skillsDir);
|
|
526694
527317
|
await settingsManager.loadLocalProjectSettings(cwd2);
|
|
526695
527318
|
const pinned = settingsManager.getPinnedAgents();
|
|
@@ -528129,6 +528752,7 @@ var init_src5 = __esm(async () => {
|
|
|
528129
528752
|
init_backend2();
|
|
528130
528753
|
init_metadata();
|
|
528131
528754
|
init_paths();
|
|
528755
|
+
init_browser_discovery_server();
|
|
528132
528756
|
init_args();
|
|
528133
528757
|
init_app_urls();
|
|
528134
528758
|
init_error_formatter();
|
|
@@ -528152,6 +528776,9 @@ var init_src5 = __esm(async () => {
|
|
|
528152
528776
|
EMPTY_APPROVAL_ARRAY = [];
|
|
528153
528777
|
EMPTY_MESSAGE_ARRAY = [];
|
|
528154
528778
|
assertSupportedBunRuntime();
|
|
528779
|
+
startBrowserDiscoveryServer().ready.catch(() => {
|
|
528780
|
+
return;
|
|
528781
|
+
});
|
|
528155
528782
|
main();
|
|
528156
528783
|
});
|
|
528157
528784
|
|
|
@@ -530516,4 +531143,4 @@ function registerBunOAuthFlows() {
|
|
|
530516
531143
|
registerBunOAuthFlows();
|
|
530517
531144
|
await init_src5().then(() => exports_src2);
|
|
530518
531145
|
|
|
530519
|
-
//# debugId=
|
|
531146
|
+
//# debugId=F46164B649518D8764756E2164756E21
|