@letta-ai/letta-code 0.31.12 → 0.31.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/channels-slack.js +20 -1
- package/dist/channels-slack.js.map +3 -3
- package/dist/gateway-core.js +2 -1
- package/dist/gateway-core.js.map +3 -3
- package/dist/mcp-client.js +4 -4
- package/dist/mcp-client.js.map +2 -2
- package/dist/types/agent/subagents/manager.d.ts.map +1 -1
- package/dist/types/backend/api/client.d.ts.map +1 -1
- package/dist/types/backend/backend.d.ts +1 -0
- package/dist/types/backend/backend.d.ts.map +1 -1
- package/dist/types/channels/message-channel-tool-definition.d.ts.map +1 -1
- package/dist/types/channels/plugin-types.d.ts +1 -1
- package/dist/types/channels/plugin-types.d.ts.map +1 -1
- package/dist/types/channels/slack/internal-types.d.ts +5 -0
- package/dist/types/channels/slack/internal-types.d.ts.map +1 -1
- package/dist/types/channels/slack/message-action-contract.d.ts +2 -0
- package/dist/types/channels/slack/message-action-contract.d.ts.map +1 -1
- package/dist/types/channels/types.d.ts +1 -0
- package/dist/types/channels/types.d.ts.map +1 -1
- package/dist/types/cli/helpers/git-context.d.ts +1 -1
- package/dist/types/cli/helpers/git-context.d.ts.map +1 -1
- package/dist/types/tools/impl/bash.d.ts +2 -0
- package/dist/types/tools/impl/bash.d.ts.map +1 -1
- package/dist/types/tools/impl/exec-command.d.ts +8 -0
- package/dist/types/tools/impl/exec-command.d.ts.map +1 -1
- package/dist/types/websocket/listener/cwd-change.d.ts.map +1 -1
- package/dist/types/websocket/listener/device-git-context.d.ts +17 -0
- package/dist/types/websocket/listener/device-git-context.d.ts.map +1 -0
- package/dist/types/websocket/listener/listener-constants.d.ts.map +1 -1
- package/dist/types/websocket/listener/protocol-outbound.d.ts +1 -0
- package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
- package/dist/types/websocket/listener/stream-observers.d.ts.map +1 -1
- package/dist/types/websocket/listener/worktree-watcher.d.ts.map +1 -1
- package/letta.js +846 -703
- package/package.json +3 -2
- package/scripts/codex-watch/release-analysis.test.ts +87 -0
- package/scripts/codex-watch/release-analysis.ts +57 -7
- package/scripts/postinstall-patches.js +37 -14
- package/scripts/source-file-size-baseline.json +2 -2
- package/skills/dispatching-coding-agents/SKILL.md +6 -6
- package/skills/messaging-agents/SKILL.md +18 -5
- package/dist/types/tools/impl/foreground-sleep.d.ts +0 -13
- package/dist/types/tools/impl/foreground-sleep.d.ts.map +0 -1
package/letta.js
CHANGED
|
@@ -5400,10 +5400,10 @@ var package_default;
|
|
|
5400
5400
|
var init_package = __esm(() => {
|
|
5401
5401
|
package_default = {
|
|
5402
5402
|
name: "@letta-ai/letta-code",
|
|
5403
|
-
version: "0.31.
|
|
5403
|
+
version: "0.31.13",
|
|
5404
5404
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5405
5405
|
type: "module",
|
|
5406
|
-
packageManager: "bun@1.3.
|
|
5406
|
+
packageManager: "bun@1.3.14",
|
|
5407
5407
|
bin: {
|
|
5408
5408
|
letta: "letta.js"
|
|
5409
5409
|
},
|
|
@@ -5522,6 +5522,7 @@ var init_package = __esm(() => {
|
|
|
5522
5522
|
},
|
|
5523
5523
|
license: "Apache-2.0",
|
|
5524
5524
|
engines: {
|
|
5525
|
+
bun: ">=1.3.2",
|
|
5525
5526
|
node: ">=22.19.0"
|
|
5526
5527
|
},
|
|
5527
5528
|
publishConfig: {
|
|
@@ -6670,14 +6671,6 @@ function consumeLastSDKDiagnostic() {
|
|
|
6670
6671
|
function clearLastSDKDiagnostic() {
|
|
6671
6672
|
lastSDKDiagnostic = null;
|
|
6672
6673
|
}
|
|
6673
|
-
function getNodeRoutingHeader() {
|
|
6674
|
-
const raw = process.env.LETTA_NODE;
|
|
6675
|
-
if (raw === undefined || raw.trim() === "") {
|
|
6676
|
-
return {};
|
|
6677
|
-
}
|
|
6678
|
-
const enabled = NODE_HEADER_ENABLED_VALUES.has(raw.trim().toLowerCase());
|
|
6679
|
-
return { "x-letta-node": enabled ? "1" : "0" };
|
|
6680
|
-
}
|
|
6681
6674
|
function getRuntimeEnvironmentDeviceId() {
|
|
6682
6675
|
return process.env[RUNTIME_ENVIRONMENT_DEVICE_ID_ENV]?.trim() || settingsManager.getOrCreateDeviceId();
|
|
6683
6676
|
}
|
|
@@ -6686,7 +6679,6 @@ function getClientDefaultHeaders() {
|
|
|
6686
6679
|
"X-Letta-Source": "letta-code",
|
|
6687
6680
|
"User-Agent": `letta-code/${package_default.version}`,
|
|
6688
6681
|
"X-Letta-Environment-Device-Id": getRuntimeEnvironmentDeviceId(),
|
|
6689
|
-
...getNodeRoutingHeader(),
|
|
6690
6682
|
...process.env.LETTA_MEMFS_BACKEND === "hosted" ? { "x-letta-memfs-backend": "hosted" } : {}
|
|
6691
6683
|
};
|
|
6692
6684
|
}
|
|
@@ -6779,7 +6771,7 @@ If you experience this issue multiple times, move ~/.letta to ~/.letta_backup, a
|
|
|
6779
6771
|
};
|
|
6780
6772
|
return client;
|
|
6781
6773
|
}
|
|
6782
|
-
var SDK_DIAGNOSTIC_MAX_LEN = 400, SDK_DIAGNOSTIC_MAX_LINES = 4, lastSDKDiagnostic = null, _cachedApiKey, _testClientOverride = null, sdkLogger,
|
|
6774
|
+
var SDK_DIAGNOSTIC_MAX_LEN = 400, SDK_DIAGNOSTIC_MAX_LINES = 4, lastSDKDiagnostic = null, _cachedApiKey, _testClientOverride = null, sdkLogger, RUNTIME_ENVIRONMENT_DEVICE_ID_ENV = "LETTA_RUNTIME_ENVIRONMENT_DEVICE_ID";
|
|
6783
6775
|
var init_client2 = __esm(() => {
|
|
6784
6776
|
init_letta_client();
|
|
6785
6777
|
init_oauth();
|
|
@@ -6809,7 +6801,6 @@ var init_client2 = __esm(() => {
|
|
|
6809
6801
|
console.debug(...args);
|
|
6810
6802
|
}
|
|
6811
6803
|
};
|
|
6812
|
-
NODE_HEADER_ENABLED_VALUES = new Set(["1", "true", "yes"]);
|
|
6813
6804
|
});
|
|
6814
6805
|
|
|
6815
6806
|
// src/utils/text-files.ts
|
|
@@ -88360,8 +88351,9 @@ Usage notes:
|
|
|
88360
88351
|
- You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 120000ms (2 minutes).
|
|
88361
88352
|
- Write a clear, concise user-facing description of what this command does. This description may be shown directly in chat as part of a status row like \`Running command: <description>\` or \`Ran command: <description>\`. Describe the command's purpose, not its shell syntax. For simple commands, keep it brief (5-10 words). For complex commands (piped commands, obscure flags, or anything hard to understand at a glance), add enough context to clarify what it does.
|
|
88362
88353
|
- If the output exceeds 30000 characters, output will be truncated before being returned to you.
|
|
88363
|
-
-
|
|
88364
|
-
-
|
|
88354
|
+
- Ordinary commands wait briefly for a result, then automatically continue in the background if they are still running. You will receive a task ID and one completion notification, so do not predict command duration, set \`run_in_background\` merely because a command may be slow, or poll for completion.
|
|
88355
|
+
- Set \`run_in_background\` only when you want the command to return a task ID immediately. You do not need to use '&' at the end of the command.
|
|
88356
|
+
- Pick between Bash and the Monitor tool by how many notifications you need. **One** ("tell me when the server is ready / the build finishes") → Bash with a command that exits when the condition is true, e.g. \`until grep -q "Ready in" dev.log; do sleep 0.5; done\`. Bash automatically yields and sends one completion notification. **One per occurrence** ("tell me every time an ERROR line appears") → use Monitor: each stdout line is an event while you keep working.
|
|
88365
88357
|
|
|
88366
88358
|
- Avoid using Bash with the \`find\`, \`grep\`, \`cat\`, \`head\`, \`tail\`, \`sed\`, \`awk\`, or \`echo\` commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:
|
|
88367
88359
|
- File search: Use Glob (NOT find or ls)
|
|
@@ -88487,61 +88479,7 @@ var EnterWorktree_default = "# EnterWorktree\n\nCreate a fresh isolated git work
|
|
|
88487
88479
|
var init_EnterWorktree = () => {};
|
|
88488
88480
|
|
|
88489
88481
|
// src/tools/descriptions/ExecCommand.md
|
|
88490
|
-
var ExecCommand_default =
|
|
88491
|
-
|
|
88492
|
-
For ordinary one-shot commands, omit \`yield_time_ms\` and let the default wait for completion; set \`yield_time_ms\` only when intentionally returning early from a long-running or interactive command.
|
|
88493
|
-
|
|
88494
|
-
Provide the required \`description\` field as a clear, concise user-facing status label for what the command does. It may be shown directly in chat with no prefix, so make it grammatical by itself and avoid tense-dependent wording. Use an imperative or purpose phrase like \`Find debug log entries\` or \`Search recent logs for errors\`. Describe the command's purpose, not its shell syntax. Keep it brief for simple commands; add only enough context to clarify commands that are hard to parse at a glance.
|
|
88495
|
-
|
|
88496
|
-
# Committing changes with git
|
|
88497
|
-
|
|
88498
|
-
Only create commits when requested by the user. If unclear, ask first. When the user asks you to create a new git commit, follow these steps carefully:
|
|
88499
|
-
|
|
88500
|
-
Git Safety Protocol:
|
|
88501
|
-
- NEVER update the git config
|
|
88502
|
-
- NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them
|
|
88503
|
-
- NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it
|
|
88504
|
-
- NEVER run force push to main/master, warn the user if they request it
|
|
88505
|
-
- CRITICAL: Always create NEW commits rather than amending, unless the user explicitly requests a git amend. When a pre-commit hook fails, the commit did NOT happen -- so --amend would modify the PREVIOUS commit, which may result in destroying work or losing previous changes. Instead, after hook failure, fix the issue, re-stage, and create a NEW commit
|
|
88506
|
-
- When staging files, prefer adding specific files by name rather than using "git add -A" or "git add .", which can accidentally include sensitive files (.env, credentials) or large binaries
|
|
88507
|
-
- NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.
|
|
88508
|
-
|
|
88509
|
-
1. Run the following shell commands in parallel:
|
|
88510
|
-
- Run a git status command to see all untracked files. IMPORTANT: Never use the -uall flag as it can cause memory issues on large repos.
|
|
88511
|
-
- Run a git diff command to see both staged and unstaged changes that will be committed.
|
|
88512
|
-
- Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.
|
|
88513
|
-
2. Analyze all staged changes (both previously staged and newly added) and draft a commit message:
|
|
88514
|
-
- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.). Ensure the message accurately reflects the changes and their purpose (i.e. "add" means a wholly new feature, "update" means an enhancement to an existing feature, "fix" means a bug fix, etc.).
|
|
88515
|
-
- Do not commit files that likely contain secrets (.env, credentials.json, etc). Warn the user if they specifically request to commit those files
|
|
88516
|
-
- Draft a concise (1-2 sentences) commit message that focuses on the "why" rather than the "what"
|
|
88517
|
-
- Ensure it accurately reflects the changes and their purpose
|
|
88518
|
-
3. Run the following commands:
|
|
88519
|
-
- Add relevant untracked files to the staging area.
|
|
88520
|
-
- Create the commit with a message ending with:
|
|
88521
|
-
👾 Generated with [Letta Code](https://letta.com)
|
|
88522
|
-
|
|
88523
|
-
Co-Authored-By: Letta Code <noreply@letta.com>
|
|
88524
|
-
- Run git status after the commit completes to verify success.
|
|
88525
|
-
Note: git status depends on the commit completing, so run it sequentially after the commit.
|
|
88526
|
-
4. If the commit fails due to pre-commit hook: fix the issue and create a NEW commit
|
|
88527
|
-
|
|
88528
|
-
Important notes:
|
|
88529
|
-
- NEVER run additional commands to read or explore code, besides git commands
|
|
88530
|
-
- DO NOT push to the remote repository unless the user explicitly asks you to do so
|
|
88531
|
-
- IMPORTANT: Never use git commands with the -i flag (like git rebase -i or git add -i) since they require interactive input which is not supported.
|
|
88532
|
-
- IMPORTANT: Do not use --no-edit with git rebase commands, as the --no-edit flag is not a valid option for git rebase.
|
|
88533
|
-
- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit
|
|
88534
|
-
- In order to ensure good formatting, ALWAYS pass the commit message as a single-quoted string with embedded newlines, a la this example:
|
|
88535
|
-
<example>
|
|
88536
|
-
git commit -m 'Commit message here.
|
|
88537
|
-
|
|
88538
|
-
👾 Generated with [Letta Code](https://letta.com)
|
|
88539
|
-
|
|
88540
|
-
Co-Authored-By: Letta Code <noreply@letta.com>'
|
|
88541
|
-
</example>
|
|
88542
|
-
|
|
88543
|
-
Use single quotes (not double quotes) and do NOT wrap the message in \`$(...)\` or backticks — single-quoting preserves the message verbatim (including \`$VAR\`, backticks, and other special characters) without needing escapes.
|
|
88544
|
-
`;
|
|
88482
|
+
var ExecCommand_default = "Runs a command in a PTY, returning output or a session ID for ongoing interaction.\n\nFor ordinary one-shot commands, omit `yield_time_ms` and let the default wait for completion; set `yield_time_ms` only when intentionally returning early from a long-running or interactive command.\n\nIf a command is still running when this tool yields, you will receive a notification when it completes. Do not poll the session just to check whether it has finished. Use `write_stdin` only when you need to send input, interrupt the process, or obtain output before you can continue.\n\nProvide the required `description` field as a clear, concise user-facing status label for what the command does. It may be shown directly in chat with no prefix, so make it grammatical by itself and avoid tense-dependent wording. Use an imperative or purpose phrase like `Find debug log entries` or `Search recent logs for errors`. Describe the command's purpose, not its shell syntax. Keep it brief for simple commands; add only enough context to clarify commands that are hard to parse at a glance.\n\n# Committing changes with git\n\nOnly create commits when requested by the user. If unclear, ask first. When the user asks you to create a new git commit, follow these steps carefully:\n\nGit Safety Protocol:\n- NEVER update the git config\n- NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them \n- NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it\n- NEVER run force push to main/master, warn the user if they request it\n- CRITICAL: Always create NEW commits rather than amending, unless the user explicitly requests a git amend. When a pre-commit hook fails, the commit did NOT happen -- so --amend would modify the PREVIOUS commit, which may result in destroying work or losing previous changes. Instead, after hook failure, fix the issue, re-stage, and create a NEW commit\n- When staging files, prefer adding specific files by name rather than using \"git add -A\" or \"git add .\", which can accidentally include sensitive files (.env, credentials) or large binaries\n- NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.\n\n1. Run the following shell commands in parallel:\n - Run a git status command to see all untracked files. IMPORTANT: Never use the -uall flag as it can cause memory issues on large repos.\n - Run a git diff command to see both staged and unstaged changes that will be committed.\n - Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.\n2. Analyze all staged changes (both previously staged and newly added) and draft a commit message:\n - Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.). Ensure the message accurately reflects the changes and their purpose (i.e. \"add\" means a wholly new feature, \"update\" means an enhancement to an existing feature, \"fix\" means a bug fix, etc.).\n - Do not commit files that likely contain secrets (.env, credentials.json, etc). Warn the user if they specifically request to commit those files\n - Draft a concise (1-2 sentences) commit message that focuses on the \"why\" rather than the \"what\"\n - Ensure it accurately reflects the changes and their purpose\n3. Run the following commands:\n - Add relevant untracked files to the staging area.\n - Create the commit with a message ending with:\n 👾 Generated with [Letta Code](https://letta.com)\n\n Co-Authored-By: Letta Code <noreply@letta.com>\n - Run git status after the commit completes to verify success.\n Note: git status depends on the commit completing, so run it sequentially after the commit.\n4. If the commit fails due to pre-commit hook: fix the issue and create a NEW commit\n\nImportant notes:\n- NEVER run additional commands to read or explore code, besides git commands\n- DO NOT push to the remote repository unless the user explicitly asks you to do so\n- IMPORTANT: Never use git commands with the -i flag (like git rebase -i or git add -i) since they require interactive input which is not supported.\n- IMPORTANT: Do not use --no-edit with git rebase commands, as the --no-edit flag is not a valid option for git rebase.\n- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit\n- In order to ensure good formatting, ALWAYS pass the commit message as a single-quoted string with embedded newlines, a la this example:\n<example>\ngit commit -m 'Commit message here.\n\n👾 Generated with [Letta Code](https://letta.com)\n\nCo-Authored-By: Letta Code <noreply@letta.com>'\n</example>\n\nUse single quotes (not double quotes) and do NOT wrap the message in `$(...)` or backticks — single-quoting preserves the message verbatim (including `$VAR`, backticks, and other special characters) without needing escapes.\n";
|
|
88545
88483
|
var init_ExecCommand = () => {};
|
|
88546
88484
|
|
|
88547
88485
|
// src/tools/descriptions/ExitWorktree.md
|
|
@@ -89615,8 +89553,7 @@ The user has the ability to modify \`content\`. If modified, this will be stated
|
|
|
89615
89553
|
var init_WriteFileGemini = () => {};
|
|
89616
89554
|
|
|
89617
89555
|
// src/tools/descriptions/WriteStdin.md
|
|
89618
|
-
var WriteStdin_default =
|
|
89619
|
-
`;
|
|
89556
|
+
var WriteStdin_default = "Writes characters to an existing unified exec session and returns recent output.\n\nUse this tool to send input, interrupt a process, or inspect new output from a long-lived interactive process such as a dev server or REPL. Do not call it with empty `chars` merely to wait for completion; `exec_command` sends a notification when a yielded process completes. If the process needs a completion deadline, create a one-shot scheduled check instead of blocking or polling.\n";
|
|
89620
89557
|
var init_WriteStdin = () => {};
|
|
89621
89558
|
|
|
89622
89559
|
// src/tools/descriptions/WriteTodosGemini.md
|
|
@@ -92790,53 +92727,6 @@ var init_worktree_ownership = __esm(() => {
|
|
|
92790
92727
|
]);
|
|
92791
92728
|
});
|
|
92792
92729
|
|
|
92793
|
-
// src/tools/impl/foreground-sleep.ts
|
|
92794
|
-
function commandRunsForegroundSleep(command) {
|
|
92795
|
-
const segments = splitShellSegmentsAllowCommandSubstitution(command) ?? splitShellSegments(command);
|
|
92796
|
-
if (!segments) {
|
|
92797
|
-
return false;
|
|
92798
|
-
}
|
|
92799
|
-
for (const segment of segments) {
|
|
92800
|
-
for (const word of tokenizeShellWords(segment)) {
|
|
92801
|
-
if (SHELL_KEYWORDS.has(word)) {
|
|
92802
|
-
continue;
|
|
92803
|
-
}
|
|
92804
|
-
if (ASSIGNMENT_PREFIX.test(word)) {
|
|
92805
|
-
continue;
|
|
92806
|
-
}
|
|
92807
|
-
if (word.split("/").pop() === "sleep") {
|
|
92808
|
-
return true;
|
|
92809
|
-
}
|
|
92810
|
-
break;
|
|
92811
|
-
}
|
|
92812
|
-
}
|
|
92813
|
-
return false;
|
|
92814
|
-
}
|
|
92815
|
-
var FOREGROUND_SLEEP_BLOCKED_MESSAGE = 'Foreground `sleep` is blocked — it stalls the session while nothing happens. Run the wait in the background and keep working: 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. For one notification per occurrence ("tell me every time an ERROR line appears"), use the Monitor tool instead. `sleep` inside `run_in_background` commands and Monitor scripts is fine.', SHELL_KEYWORDS, ASSIGNMENT_PREFIX;
|
|
92816
|
-
var init_foreground_sleep = __esm(() => {
|
|
92817
|
-
SHELL_KEYWORDS = new Set([
|
|
92818
|
-
"if",
|
|
92819
|
-
"then",
|
|
92820
|
-
"elif",
|
|
92821
|
-
"else",
|
|
92822
|
-
"fi",
|
|
92823
|
-
"while",
|
|
92824
|
-
"until",
|
|
92825
|
-
"do",
|
|
92826
|
-
"done",
|
|
92827
|
-
"for",
|
|
92828
|
-
"case",
|
|
92829
|
-
"esac",
|
|
92830
|
-
"{",
|
|
92831
|
-
"}",
|
|
92832
|
-
"(",
|
|
92833
|
-
")",
|
|
92834
|
-
"!",
|
|
92835
|
-
"time"
|
|
92836
|
-
]);
|
|
92837
|
-
ASSIGNMENT_PREFIX = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
92838
|
-
});
|
|
92839
|
-
|
|
92840
92730
|
// src/tools/impl/process_manager.ts
|
|
92841
92731
|
var exports_process_manager = {};
|
|
92842
92732
|
__export(exports_process_manager, {
|
|
@@ -95651,6 +95541,7 @@ __export(exports_bash, {
|
|
|
95651
95541
|
getBackgroundLauncher: () => getBackgroundLauncher,
|
|
95652
95542
|
bash: () => bash
|
|
95653
95543
|
});
|
|
95544
|
+
import { rmSync as rmSync4 } from "node:fs";
|
|
95654
95545
|
function rebuildCachedLauncher(command, secretEnv) {
|
|
95655
95546
|
if (!cachedWorkingLauncher)
|
|
95656
95547
|
return null;
|
|
@@ -95799,7 +95690,8 @@ async function bash(args) {
|
|
|
95799
95690
|
signal,
|
|
95800
95691
|
onOutput,
|
|
95801
95692
|
secretEnv,
|
|
95802
|
-
parentScope
|
|
95693
|
+
parentScope,
|
|
95694
|
+
foregroundYieldMs = DEFAULT_FOREGROUND_YIELD_MS
|
|
95803
95695
|
} = args;
|
|
95804
95696
|
const userCwd = getCurrentWorkingDirectory();
|
|
95805
95697
|
const sanitizeOutput = (text) => scrubSecretsFromString(text, secretEnv ?? {});
|
|
@@ -95825,194 +95717,184 @@ async function bash(args) {
|
|
|
95825
95717
|
const recoveredFrom = consumeWorkingDirectoryRecovery();
|
|
95826
95718
|
const recoveryNote = recoveredFrom ? `Note: working directory ${recoveredFrom} no longer exists; running in ${userCwd} instead.
|
|
95827
95719
|
` : "";
|
|
95828
|
-
|
|
95829
|
-
|
|
95830
|
-
|
|
95831
|
-
|
|
95832
|
-
|
|
95833
|
-
|
|
95834
|
-
|
|
95835
|
-
|
|
95836
|
-
text: error4 instanceof Error ? error4.message : String(error4)
|
|
95837
|
-
}
|
|
95838
|
-
],
|
|
95839
|
-
status: "error"
|
|
95840
|
-
};
|
|
95841
|
-
}
|
|
95842
|
-
const bgEnv = secretEnv ? { ...getShellEnv(), ...secretEnv } : getShellEnv();
|
|
95843
|
-
const bgCommand = withStrictShellPrelude(command, bgEnv);
|
|
95844
|
-
const bashId = getNextBashId();
|
|
95845
|
-
const outputFile = createBackgroundOutputFile(bashId);
|
|
95846
|
-
const launcher = getBackgroundLauncher(bgCommand, bgEnv, secretEnv);
|
|
95847
|
-
const [executable] = launcher;
|
|
95848
|
-
if (!executable) {
|
|
95849
|
-
return {
|
|
95850
|
-
content: [{ type: "text", text: "No shell available" }],
|
|
95851
|
-
status: "error"
|
|
95852
|
-
};
|
|
95853
|
-
}
|
|
95854
|
-
noteExpectedWorktreeForLauncher(launcher, userCwd);
|
|
95855
|
-
const sandboxed = applyShellSandbox(launcher, userCwd, bgEnv);
|
|
95856
|
-
let bgProcess;
|
|
95857
|
-
let outputWriteFailed = false;
|
|
95858
|
-
const runningProcess = startShellProcess(sandboxed.launcher, {
|
|
95859
|
-
cwd: userCwd,
|
|
95860
|
-
env: sandboxed.env,
|
|
95861
|
-
timeoutMs: timeout > 0 ? timeout : 0,
|
|
95862
|
-
sourceCommand: command,
|
|
95863
|
-
captureOutput: false,
|
|
95864
|
-
onOutput(text, stream10) {
|
|
95865
|
-
const sanitizedText = sanitizeOutput(text);
|
|
95866
|
-
appendBackgroundProcessOutput(bgProcess, stream10, sanitizedText);
|
|
95867
|
-
const wrote = appendToOutputFile(outputFile, stream10 === "stderr" ? `[stderr] ${sanitizedText}` : sanitizedText);
|
|
95868
|
-
if (!wrote && bgProcess.status === "running") {
|
|
95869
|
-
outputWriteFailed = true;
|
|
95870
|
-
appendBackgroundProcessOutput(bgProcess, "stderr", "[output file write failed; output may be incomplete]");
|
|
95871
|
-
bgProcess.status = "failed";
|
|
95872
|
-
try {
|
|
95873
|
-
runningProcess.process.kill("SIGTERM");
|
|
95874
|
-
} catch {}
|
|
95720
|
+
try {
|
|
95721
|
+
assertBackgroundProcessCapacity();
|
|
95722
|
+
} catch (error4) {
|
|
95723
|
+
return {
|
|
95724
|
+
content: [
|
|
95725
|
+
{
|
|
95726
|
+
type: "text",
|
|
95727
|
+
text: error4 instanceof Error ? error4.message : String(error4)
|
|
95875
95728
|
}
|
|
95876
|
-
|
|
95877
|
-
|
|
95878
|
-
bgProcess = {
|
|
95879
|
-
process: runningProcess.process,
|
|
95880
|
-
command,
|
|
95881
|
-
stdout: [],
|
|
95882
|
-
stderr: [],
|
|
95883
|
-
status: "running",
|
|
95884
|
-
exitCode: null,
|
|
95885
|
-
lastReadIndex: { stdout: 0, stderr: 0 },
|
|
95886
|
-
startTime: new Date,
|
|
95887
|
-
outputFile,
|
|
95888
|
-
totalStdoutLines: 0,
|
|
95889
|
-
totalStderrLines: 0,
|
|
95890
|
-
runtimeScope: parentScope,
|
|
95891
|
-
secrets: secretEnv
|
|
95729
|
+
],
|
|
95730
|
+
status: "error"
|
|
95892
95731
|
};
|
|
95893
|
-
|
|
95894
|
-
|
|
95895
|
-
|
|
95896
|
-
|
|
95897
|
-
|
|
95898
|
-
|
|
95732
|
+
}
|
|
95733
|
+
const bgEnv = secretEnv ? { ...getShellEnv(), ...secretEnv } : getShellEnv();
|
|
95734
|
+
const bgCommand = withStrictShellPrelude(command, bgEnv);
|
|
95735
|
+
const bashId = getNextBashId();
|
|
95736
|
+
const outputFile = createBackgroundOutputFile(bashId);
|
|
95737
|
+
const launcher = getBackgroundLauncher(bgCommand, bgEnv, secretEnv);
|
|
95738
|
+
const [executable] = launcher;
|
|
95739
|
+
if (!executable) {
|
|
95740
|
+
return {
|
|
95741
|
+
content: [{ type: "text", text: "No shell available" }],
|
|
95742
|
+
status: "error"
|
|
95743
|
+
};
|
|
95744
|
+
}
|
|
95745
|
+
noteExpectedWorktreeForLauncher(launcher, userCwd);
|
|
95746
|
+
const sandboxed = applyShellSandbox(launcher, userCwd, bgEnv);
|
|
95747
|
+
let bgProcess;
|
|
95748
|
+
let outputWriteFailed = false;
|
|
95749
|
+
const foregroundOutput = { stdout: "", stderr: "" };
|
|
95750
|
+
const effectiveTimeout = run_in_background ? timeout > 0 ? timeout : 0 : Math.min(Math.max(timeout, 1), 600000);
|
|
95751
|
+
const runningProcess = startShellProcess(sandboxed.launcher, {
|
|
95752
|
+
cwd: userCwd,
|
|
95753
|
+
env: sandboxed.env,
|
|
95754
|
+
timeoutMs: effectiveTimeout,
|
|
95755
|
+
sourceCommand: command,
|
|
95756
|
+
signal: run_in_background ? undefined : signal,
|
|
95757
|
+
captureOutput: false,
|
|
95758
|
+
onOutput(text, stream10) {
|
|
95759
|
+
const sanitizedText = sanitizeOutput(text);
|
|
95760
|
+
if (!run_in_background) {
|
|
95761
|
+
foregroundOutput[stream10] += text;
|
|
95762
|
+
onOutput?.(text, stream10);
|
|
95763
|
+
}
|
|
95764
|
+
appendBackgroundProcessOutput(bgProcess, stream10, sanitizedText);
|
|
95765
|
+
const wrote = appendToOutputFile(outputFile, stream10 === "stderr" ? `[stderr] ${sanitizedText}` : sanitizedText);
|
|
95766
|
+
if (!wrote && bgProcess.status === "running") {
|
|
95767
|
+
outputWriteFailed = true;
|
|
95768
|
+
appendBackgroundProcessOutput(bgProcess, "stderr", "[output file write failed; output may be incomplete]");
|
|
95769
|
+
bgProcess.status = "failed";
|
|
95770
|
+
try {
|
|
95771
|
+
runningProcess.process.kill("SIGTERM");
|
|
95772
|
+
} catch {}
|
|
95773
|
+
}
|
|
95774
|
+
}
|
|
95775
|
+
});
|
|
95776
|
+
bgProcess = {
|
|
95777
|
+
process: runningProcess.process,
|
|
95778
|
+
command,
|
|
95779
|
+
stdout: [],
|
|
95780
|
+
stderr: [],
|
|
95781
|
+
status: "running",
|
|
95782
|
+
exitCode: null,
|
|
95783
|
+
lastReadIndex: { stdout: 0, stderr: 0 },
|
|
95784
|
+
startTime: new Date,
|
|
95785
|
+
outputFile,
|
|
95786
|
+
totalStdoutLines: 0,
|
|
95787
|
+
totalStderrLines: 0,
|
|
95788
|
+
runtimeScope: parentScope,
|
|
95789
|
+
secrets: secretEnv
|
|
95790
|
+
};
|
|
95791
|
+
backgroundProcesses.set(bashId, bgProcess);
|
|
95792
|
+
const notificationScope = resolveNotificationScope(parentScope);
|
|
95793
|
+
const settled = runningProcess.completion.then(({ exitCode }) => {
|
|
95794
|
+
bgProcess.status = exitCode === 0 && !outputWriteFailed ? "completed" : "failed";
|
|
95795
|
+
bgProcess.exitCode = exitCode;
|
|
95796
|
+
appendToOutputFile(outputFile, `
|
|
95899
95797
|
[exit code: ${exitCode}]
|
|
95900
95798
|
`);
|
|
95901
|
-
|
|
95902
|
-
|
|
95903
|
-
|
|
95904
|
-
|
|
95905
|
-
|
|
95906
|
-
|
|
95907
|
-
|
|
95908
|
-
|
|
95909
|
-
|
|
95910
|
-
|
|
95911
|
-
|
|
95912
|
-
|
|
95913
|
-
const err = error4;
|
|
95914
|
-
const message = sanitizeOutput(err.killed ? `Command timed out after ${timeout}ms` : err.message);
|
|
95915
|
-
bgProcess.status = "failed";
|
|
95916
|
-
appendBackgroundProcessOutput(bgProcess, "stderr", message);
|
|
95917
|
-
appendToOutputFile(outputFile, err.killed ? `
|
|
95799
|
+
scrubCompletedBackgroundOutput(bgProcess);
|
|
95800
|
+
return {
|
|
95801
|
+
status: exitCode === 0 && !outputWriteFailed ? "completed" : "failed",
|
|
95802
|
+
detail: outputWriteFailed ? "Output file write failed; output may be incomplete" : exitCode === null ? "Terminated by signal before exiting" : `Exit code: ${exitCode}`,
|
|
95803
|
+
exitCode
|
|
95804
|
+
};
|
|
95805
|
+
}, (error4) => {
|
|
95806
|
+
const err = error4;
|
|
95807
|
+
const message = sanitizeOutput(err.killed ? `Command timed out after ${timeout}ms` : err.message);
|
|
95808
|
+
bgProcess.status = "failed";
|
|
95809
|
+
appendBackgroundProcessOutput(bgProcess, "stderr", message);
|
|
95810
|
+
appendToOutputFile(outputFile, err.killed ? `
|
|
95918
95811
|
[timeout after ${timeout}ms]
|
|
95919
95812
|
` : `
|
|
95920
95813
|
[error] ${message}
|
|
95921
95814
|
`);
|
|
95922
|
-
|
|
95815
|
+
scrubCompletedBackgroundOutput(bgProcess);
|
|
95816
|
+
return {
|
|
95817
|
+
status: "failed",
|
|
95818
|
+
detail: err.killed ? message : `Error: ${message}`,
|
|
95819
|
+
error: err
|
|
95820
|
+
};
|
|
95821
|
+
});
|
|
95822
|
+
const notifyWhenSettled = () => {
|
|
95823
|
+
settled.then(({ status, detail }) => {
|
|
95923
95824
|
notifyBackgroundCompletion({
|
|
95924
95825
|
bashId,
|
|
95925
95826
|
description,
|
|
95926
95827
|
outputFile,
|
|
95927
95828
|
bgProcess,
|
|
95928
95829
|
scope: notificationScope,
|
|
95929
|
-
status
|
|
95930
|
-
detail
|
|
95830
|
+
status,
|
|
95831
|
+
detail
|
|
95931
95832
|
});
|
|
95932
95833
|
scheduleBackgroundProcessCleanup(bashId);
|
|
95933
95834
|
});
|
|
95934
|
-
|
|
95935
|
-
|
|
95936
|
-
|
|
95937
|
-
|
|
95938
|
-
|
|
95939
|
-
|
|
95835
|
+
};
|
|
95836
|
+
if (!run_in_background) {
|
|
95837
|
+
const outcome = await Promise.race([
|
|
95838
|
+
settled.then((result) => ({ type: "settled", result })),
|
|
95839
|
+
new Promise((resolve11) => {
|
|
95840
|
+
const timer = setTimeout(() => resolve11({ type: "yield" }), Math.max(0, foregroundYieldMs));
|
|
95841
|
+
if (typeof timer === "object" && timer !== null && "unref" in timer) {
|
|
95842
|
+
timer.unref();
|
|
95940
95843
|
}
|
|
95941
|
-
|
|
95942
|
-
|
|
95943
|
-
|
|
95944
|
-
|
|
95945
|
-
|
|
95946
|
-
|
|
95947
|
-
|
|
95948
|
-
|
|
95949
|
-
|
|
95950
|
-
|
|
95951
|
-
|
|
95952
|
-
|
|
95953
|
-
|
|
95954
|
-
|
|
95955
|
-
|
|
95956
|
-
|
|
95957
|
-
signal,
|
|
95958
|
-
onOutput,
|
|
95959
|
-
secretEnv
|
|
95960
|
-
});
|
|
95961
|
-
let output = stdout;
|
|
95962
|
-
if (stderr)
|
|
95963
|
-
output = output ? `${output}
|
|
95964
|
-
${stderr}` : stderr;
|
|
95965
|
-
const { content: truncatedOutput } = truncateByChars(output || "(Command completed with no output)", LIMITS.BASH_OUTPUT_CHARS, "Bash", { workingDirectory: userCwd, toolName: "Bash", secrets: secretEnv });
|
|
95966
|
-
if (exitCode !== 0 && exitCode !== null) {
|
|
95967
|
-
return {
|
|
95968
|
-
content: [
|
|
95969
|
-
{
|
|
95970
|
-
type: "text",
|
|
95971
|
-
text: `${recoveryNote}Exit code: ${exitCode}
|
|
95844
|
+
})
|
|
95845
|
+
]);
|
|
95846
|
+
if (outcome.type === "settled") {
|
|
95847
|
+
backgroundProcesses.delete(bashId);
|
|
95848
|
+
rmSync4(outputFile, { force: true });
|
|
95849
|
+
const { result } = outcome;
|
|
95850
|
+
const output = [foregroundOutput.stdout, foregroundOutput.stderr].filter(Boolean).join(`
|
|
95851
|
+
`);
|
|
95852
|
+
const { content: truncatedOutput } = truncateByChars(output || "(Command completed with no output)", LIMITS.BASH_OUTPUT_CHARS, "Bash", { workingDirectory: userCwd, toolName: "Bash", secrets: secretEnv });
|
|
95853
|
+
if (result.status === "failed") {
|
|
95854
|
+
const isAbort = signal?.aborted || "error" in result && (result.error.name === "AbortError" || result.error.code === "ABORT_ERR");
|
|
95855
|
+
return {
|
|
95856
|
+
content: [
|
|
95857
|
+
{
|
|
95858
|
+
type: "text",
|
|
95859
|
+
text: isAbort ? INTERRUPTED_BY_USER : `${recoveryNote}${result.detail}
|
|
95972
95860
|
${truncatedOutput}`
|
|
95973
|
-
|
|
95974
|
-
|
|
95975
|
-
|
|
95861
|
+
}
|
|
95862
|
+
],
|
|
95863
|
+
status: "error"
|
|
95864
|
+
};
|
|
95865
|
+
}
|
|
95866
|
+
return {
|
|
95867
|
+
content: [{ type: "text", text: `${recoveryNote}${truncatedOutput}` }],
|
|
95868
|
+
status: "success"
|
|
95976
95869
|
};
|
|
95977
95870
|
}
|
|
95978
|
-
|
|
95979
|
-
|
|
95980
|
-
status: "success"
|
|
95981
|
-
};
|
|
95982
|
-
} catch (error4) {
|
|
95983
|
-
const err = error4;
|
|
95984
|
-
const isAbort = signal?.aborted || err.code === "ABORT_ERR" || err.name === "AbortError" || err.message === "The operation was aborted";
|
|
95985
|
-
let errorMessage = "";
|
|
95986
|
-
if (isAbort) {
|
|
95987
|
-
errorMessage = INTERRUPTED_BY_USER;
|
|
95988
|
-
} else {
|
|
95989
|
-
if (err.killed && err.signal === "SIGTERM")
|
|
95990
|
-
errorMessage = `Command timed out after ${effectiveTimeout}ms
|
|
95991
|
-
`;
|
|
95992
|
-
if (err.code && typeof err.code === "number")
|
|
95993
|
-
errorMessage += `Exit code: ${err.code}
|
|
95994
|
-
`;
|
|
95995
|
-
if (err.stderr)
|
|
95996
|
-
errorMessage += err.stderr;
|
|
95997
|
-
else if (err.message)
|
|
95998
|
-
errorMessage += err.message;
|
|
95999
|
-
if (err.stdout)
|
|
96000
|
-
errorMessage = `${err.stdout}
|
|
96001
|
-
${errorMessage}`;
|
|
96002
|
-
}
|
|
96003
|
-
const { content: truncatedError } = truncateByChars(errorMessage.trim() || "Command failed with unknown error", LIMITS.BASH_OUTPUT_CHARS, "Bash", { workingDirectory: userCwd, toolName: "Bash", secrets: secretEnv });
|
|
95871
|
+
backgroundProcesses.set(bashId, bgProcess);
|
|
95872
|
+
notifyWhenSettled();
|
|
96004
95873
|
return {
|
|
96005
95874
|
content: [
|
|
96006
95875
|
{
|
|
96007
95876
|
type: "text",
|
|
96008
|
-
text:
|
|
95877
|
+
text: `${recoveryNote}Command is still running with task ID: ${bashId}
|
|
95878
|
+
Output file: ${outputFile}
|
|
95879
|
+
You will be notified when it completes. Do not poll unless you need intermediate output.`
|
|
96009
95880
|
}
|
|
96010
95881
|
],
|
|
96011
|
-
status: "
|
|
95882
|
+
status: "success"
|
|
96012
95883
|
};
|
|
96013
95884
|
}
|
|
95885
|
+
notifyWhenSettled();
|
|
95886
|
+
return {
|
|
95887
|
+
content: [
|
|
95888
|
+
{
|
|
95889
|
+
type: "text",
|
|
95890
|
+
text: `${recoveryNote}Command running in background with ID: ${bashId}
|
|
95891
|
+
Output file: ${outputFile}`
|
|
95892
|
+
}
|
|
95893
|
+
],
|
|
95894
|
+
status: "success"
|
|
95895
|
+
};
|
|
96014
95896
|
}
|
|
96015
|
-
var cachedWorkingLauncher = null, NOTIFICATION_TAIL_LINES = 50;
|
|
95897
|
+
var cachedWorkingLauncher = null, DEFAULT_FOREGROUND_YIELD_MS = 1e4, NOTIFICATION_TAIL_LINES = 50;
|
|
96016
95898
|
var init_bash = __esm(() => {
|
|
96017
95899
|
init_constants2();
|
|
96018
95900
|
init_runtime_context();
|
|
@@ -96020,7 +95902,6 @@ var init_bash = __esm(() => {
|
|
|
96020
95902
|
init_message_queue_bridge();
|
|
96021
95903
|
init_task_notifications();
|
|
96022
95904
|
init_worktree_ownership();
|
|
96023
|
-
init_foreground_sleep();
|
|
96024
95905
|
init_process_manager();
|
|
96025
95906
|
init_shell_env();
|
|
96026
95907
|
init_shell_launchers();
|
|
@@ -96883,98 +96764,6 @@ var init_connection = __esm(() => {
|
|
|
96883
96764
|
resumeStateByRuntime = new WeakMap;
|
|
96884
96765
|
});
|
|
96885
96766
|
|
|
96886
|
-
// src/cli/helpers/git-context.ts
|
|
96887
|
-
import { execFileSync } from "node:child_process";
|
|
96888
|
-
function runGit(args, cwd) {
|
|
96889
|
-
try {
|
|
96890
|
-
return execFileSync("git", args, {
|
|
96891
|
-
cwd,
|
|
96892
|
-
encoding: "utf-8",
|
|
96893
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
96894
|
-
windowsHide: true
|
|
96895
|
-
}).trim();
|
|
96896
|
-
} catch {
|
|
96897
|
-
return null;
|
|
96898
|
-
}
|
|
96899
|
-
}
|
|
96900
|
-
function truncateLines(value, maxLines) {
|
|
96901
|
-
const lines = value.split(`
|
|
96902
|
-
`);
|
|
96903
|
-
if (lines.length <= maxLines) {
|
|
96904
|
-
return value;
|
|
96905
|
-
}
|
|
96906
|
-
return lines.slice(0, maxLines).join(`
|
|
96907
|
-
`) + `
|
|
96908
|
-
... and ${lines.length - maxLines} more changes`;
|
|
96909
|
-
}
|
|
96910
|
-
function formatGitUser(name, email) {
|
|
96911
|
-
if (!name && !email) {
|
|
96912
|
-
return null;
|
|
96913
|
-
}
|
|
96914
|
-
if (name && email) {
|
|
96915
|
-
return `${name} <${email}>`;
|
|
96916
|
-
}
|
|
96917
|
-
return name || email;
|
|
96918
|
-
}
|
|
96919
|
-
function gatherGitContextSnapshot(options = {}) {
|
|
96920
|
-
const cwd = options.cwd ?? process.cwd();
|
|
96921
|
-
const recentCommitLimit = options.recentCommitLimit ?? 3;
|
|
96922
|
-
if (!runGit(["rev-parse", "--git-dir"], cwd)) {
|
|
96923
|
-
return {
|
|
96924
|
-
isGitRepo: false,
|
|
96925
|
-
branch: null,
|
|
96926
|
-
status: null,
|
|
96927
|
-
recentCommits: null,
|
|
96928
|
-
gitUser: null
|
|
96929
|
-
};
|
|
96930
|
-
}
|
|
96931
|
-
const branch = runGit(["branch", "--show-current"], cwd);
|
|
96932
|
-
const fullStatus = runGit(["status", "--short"], cwd);
|
|
96933
|
-
const status = typeof fullStatus === "string" && options.statusLineLimit ? truncateLines(fullStatus, options.statusLineLimit) : fullStatus;
|
|
96934
|
-
const recentCommits = options.recentCommitFormat ? runGit([
|
|
96935
|
-
"log",
|
|
96936
|
-
`--format=${options.recentCommitFormat}`,
|
|
96937
|
-
"-n",
|
|
96938
|
-
String(recentCommitLimit)
|
|
96939
|
-
], cwd) : runGit(["log", "--oneline", "-n", String(recentCommitLimit)], cwd);
|
|
96940
|
-
const userConfig = runGit(["config", "--get-regexp", "^user\\.(name|email)$"], cwd);
|
|
96941
|
-
let userName = null;
|
|
96942
|
-
let userEmail = null;
|
|
96943
|
-
if (userConfig) {
|
|
96944
|
-
for (const line of userConfig.split(`
|
|
96945
|
-
`)) {
|
|
96946
|
-
if (line.startsWith("user.name "))
|
|
96947
|
-
userName = line.slice("user.name ".length);
|
|
96948
|
-
else if (line.startsWith("user.email "))
|
|
96949
|
-
userEmail = line.slice("user.email ".length);
|
|
96950
|
-
}
|
|
96951
|
-
}
|
|
96952
|
-
const gitUser = formatGitUser(userName, userEmail);
|
|
96953
|
-
return {
|
|
96954
|
-
isGitRepo: true,
|
|
96955
|
-
branch,
|
|
96956
|
-
status,
|
|
96957
|
-
recentCommits,
|
|
96958
|
-
gitUser
|
|
96959
|
-
};
|
|
96960
|
-
}
|
|
96961
|
-
function getGitContext(cwd) {
|
|
96962
|
-
if (!runGit(["rev-parse", "--git-dir"], cwd)) {
|
|
96963
|
-
return null;
|
|
96964
|
-
}
|
|
96965
|
-
const branch = runGit(["branch", "--show-current"], cwd);
|
|
96966
|
-
const branchList = runGit([
|
|
96967
|
-
"branch",
|
|
96968
|
-
"--sort=-committerdate",
|
|
96969
|
-
"--format=%(refname:short)",
|
|
96970
|
-
"--no-color"
|
|
96971
|
-
], cwd);
|
|
96972
|
-
const recentBranches = branchList ? branchList.split(`
|
|
96973
|
-
`).map((b) => b.trim()).filter((b) => b.length > 0 && b !== branch).slice(0, 10) : [];
|
|
96974
|
-
return { branch, recent_branches: recentBranches };
|
|
96975
|
-
}
|
|
96976
|
-
var init_git_context = () => {};
|
|
96977
|
-
|
|
96978
96767
|
// src/cli/helpers/memory-reminder.ts
|
|
96979
96768
|
function isValidStepCount(value) {
|
|
96980
96769
|
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value > 0;
|
|
@@ -97415,6 +97204,169 @@ var init_constants3 = __esm(() => {
|
|
|
97415
97204
|
SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
|
|
97416
97205
|
});
|
|
97417
97206
|
|
|
97207
|
+
// src/cli/helpers/git-context.ts
|
|
97208
|
+
import { execFile as execFile2, execFileSync } from "node:child_process";
|
|
97209
|
+
import { promisify as promisify3 } from "node:util";
|
|
97210
|
+
function runGit(args, cwd) {
|
|
97211
|
+
try {
|
|
97212
|
+
return execFileSync("git", args, {
|
|
97213
|
+
cwd,
|
|
97214
|
+
encoding: "utf-8",
|
|
97215
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
97216
|
+
windowsHide: true
|
|
97217
|
+
}).trim();
|
|
97218
|
+
} catch {
|
|
97219
|
+
return null;
|
|
97220
|
+
}
|
|
97221
|
+
}
|
|
97222
|
+
async function runGitAsync(args, cwd) {
|
|
97223
|
+
try {
|
|
97224
|
+
const { stdout } = await execFileAsync("git", args, {
|
|
97225
|
+
cwd,
|
|
97226
|
+
encoding: "utf-8",
|
|
97227
|
+
windowsHide: true
|
|
97228
|
+
});
|
|
97229
|
+
return stdout.trim();
|
|
97230
|
+
} catch {
|
|
97231
|
+
return null;
|
|
97232
|
+
}
|
|
97233
|
+
}
|
|
97234
|
+
function truncateLines(value, maxLines) {
|
|
97235
|
+
const lines = value.split(`
|
|
97236
|
+
`);
|
|
97237
|
+
if (lines.length <= maxLines) {
|
|
97238
|
+
return value;
|
|
97239
|
+
}
|
|
97240
|
+
return lines.slice(0, maxLines).join(`
|
|
97241
|
+
`) + `
|
|
97242
|
+
... and ${lines.length - maxLines} more changes`;
|
|
97243
|
+
}
|
|
97244
|
+
function formatGitUser(name, email) {
|
|
97245
|
+
if (!name && !email) {
|
|
97246
|
+
return null;
|
|
97247
|
+
}
|
|
97248
|
+
if (name && email) {
|
|
97249
|
+
return `${name} <${email}>`;
|
|
97250
|
+
}
|
|
97251
|
+
return name || email;
|
|
97252
|
+
}
|
|
97253
|
+
function gatherGitContextSnapshot(options = {}) {
|
|
97254
|
+
const cwd = options.cwd ?? process.cwd();
|
|
97255
|
+
const recentCommitLimit = options.recentCommitLimit ?? 3;
|
|
97256
|
+
if (!runGit(["rev-parse", "--git-dir"], cwd)) {
|
|
97257
|
+
return {
|
|
97258
|
+
isGitRepo: false,
|
|
97259
|
+
branch: null,
|
|
97260
|
+
status: null,
|
|
97261
|
+
recentCommits: null,
|
|
97262
|
+
gitUser: null
|
|
97263
|
+
};
|
|
97264
|
+
}
|
|
97265
|
+
const branch = runGit(["branch", "--show-current"], cwd);
|
|
97266
|
+
const fullStatus = runGit(["status", "--short"], cwd);
|
|
97267
|
+
const status = typeof fullStatus === "string" && options.statusLineLimit ? truncateLines(fullStatus, options.statusLineLimit) : fullStatus;
|
|
97268
|
+
const recentCommits = options.recentCommitFormat ? runGit([
|
|
97269
|
+
"log",
|
|
97270
|
+
`--format=${options.recentCommitFormat}`,
|
|
97271
|
+
"-n",
|
|
97272
|
+
String(recentCommitLimit)
|
|
97273
|
+
], cwd) : runGit(["log", "--oneline", "-n", String(recentCommitLimit)], cwd);
|
|
97274
|
+
const userConfig = runGit(["config", "--get-regexp", "^user\\.(name|email)$"], cwd);
|
|
97275
|
+
let userName = null;
|
|
97276
|
+
let userEmail = null;
|
|
97277
|
+
if (userConfig) {
|
|
97278
|
+
for (const line of userConfig.split(`
|
|
97279
|
+
`)) {
|
|
97280
|
+
if (line.startsWith("user.name "))
|
|
97281
|
+
userName = line.slice("user.name ".length);
|
|
97282
|
+
else if (line.startsWith("user.email "))
|
|
97283
|
+
userEmail = line.slice("user.email ".length);
|
|
97284
|
+
}
|
|
97285
|
+
}
|
|
97286
|
+
const gitUser = formatGitUser(userName, userEmail);
|
|
97287
|
+
return {
|
|
97288
|
+
isGitRepo: true,
|
|
97289
|
+
branch,
|
|
97290
|
+
status,
|
|
97291
|
+
recentCommits,
|
|
97292
|
+
gitUser
|
|
97293
|
+
};
|
|
97294
|
+
}
|
|
97295
|
+
async function getGitContextAsync(cwd) {
|
|
97296
|
+
if (!await runGitAsync(["rev-parse", "--git-dir"], cwd)) {
|
|
97297
|
+
return null;
|
|
97298
|
+
}
|
|
97299
|
+
const branch = await runGitAsync(["branch", "--show-current"], cwd);
|
|
97300
|
+
const branchList = await runGitAsync([
|
|
97301
|
+
"branch",
|
|
97302
|
+
"--sort=-committerdate",
|
|
97303
|
+
"--format=%(refname:short)",
|
|
97304
|
+
"--no-color"
|
|
97305
|
+
], cwd);
|
|
97306
|
+
const recentBranches = branchList ? branchList.split(`
|
|
97307
|
+
`).map((b) => b.trim()).filter((b) => b.length > 0 && b !== branch).slice(0, 10) : [];
|
|
97308
|
+
return { branch, recent_branches: recentBranches };
|
|
97309
|
+
}
|
|
97310
|
+
var execFileAsync;
|
|
97311
|
+
var init_git_context = __esm(() => {
|
|
97312
|
+
execFileAsync = promisify3(execFile2);
|
|
97313
|
+
});
|
|
97314
|
+
|
|
97315
|
+
// src/websocket/listener/device-git-context.ts
|
|
97316
|
+
class DeviceGitContextCache {
|
|
97317
|
+
load;
|
|
97318
|
+
now;
|
|
97319
|
+
entries = new Map;
|
|
97320
|
+
pending = new Map;
|
|
97321
|
+
constructor(load = getGitContextAsync, now = Date.now) {
|
|
97322
|
+
this.load = load;
|
|
97323
|
+
this.now = now;
|
|
97324
|
+
}
|
|
97325
|
+
read(cwd) {
|
|
97326
|
+
const cached2 = this.entries.get(cwd);
|
|
97327
|
+
if (cached2 && cached2.expiresAt > this.now()) {
|
|
97328
|
+
return cached2.value;
|
|
97329
|
+
}
|
|
97330
|
+
return cached2?.value ?? null;
|
|
97331
|
+
}
|
|
97332
|
+
async refresh(cwd, options = {}) {
|
|
97333
|
+
const cached2 = this.entries.get(cwd);
|
|
97334
|
+
if (!options.force && cached2 && cached2.expiresAt > this.now()) {
|
|
97335
|
+
return cached2.value;
|
|
97336
|
+
}
|
|
97337
|
+
const pending = this.pending.get(cwd);
|
|
97338
|
+
if (pending) {
|
|
97339
|
+
return pending;
|
|
97340
|
+
}
|
|
97341
|
+
const load = this.load(cwd).then((value) => {
|
|
97342
|
+
this.entries.set(cwd, {
|
|
97343
|
+
expiresAt: this.now() + GIT_CONTEXT_CACHE_TTL_MS,
|
|
97344
|
+
value
|
|
97345
|
+
});
|
|
97346
|
+
this.prune();
|
|
97347
|
+
return value;
|
|
97348
|
+
}).finally(() => {
|
|
97349
|
+
this.pending.delete(cwd);
|
|
97350
|
+
});
|
|
97351
|
+
this.pending.set(cwd, load);
|
|
97352
|
+
return load;
|
|
97353
|
+
}
|
|
97354
|
+
prune() {
|
|
97355
|
+
if (this.entries.size <= MAX_GIT_CONTEXT_CACHE_ENTRIES) {
|
|
97356
|
+
return;
|
|
97357
|
+
}
|
|
97358
|
+
const oldestKey = this.entries.keys().next().value;
|
|
97359
|
+
if (oldestKey) {
|
|
97360
|
+
this.entries.delete(oldestKey);
|
|
97361
|
+
}
|
|
97362
|
+
}
|
|
97363
|
+
}
|
|
97364
|
+
var GIT_CONTEXT_CACHE_TTL_MS = 15000, MAX_GIT_CONTEXT_CACHE_ENTRIES = 64, deviceGitContextCache;
|
|
97365
|
+
var init_device_git_context = __esm(() => {
|
|
97366
|
+
init_git_context();
|
|
97367
|
+
deviceGitContextCache = new DeviceGitContextCache;
|
|
97368
|
+
});
|
|
97369
|
+
|
|
97418
97370
|
// src/websocket/listener/device-status-cache.ts
|
|
97419
97371
|
function recordDeviceStatus(transport, scope, status) {
|
|
97420
97372
|
shouldEmitDeviceStatus(transport, scope, status, true);
|
|
@@ -97443,6 +97395,7 @@ var SUPPORTED_REMOTE_COMMANDS;
|
|
|
97443
97395
|
var init_listener_constants = __esm(() => {
|
|
97444
97396
|
SUPPORTED_REMOTE_COMMANDS = [
|
|
97445
97397
|
"clear",
|
|
97398
|
+
"clear-messages",
|
|
97446
97399
|
"doctor",
|
|
97447
97400
|
"init",
|
|
97448
97401
|
"remember",
|
|
@@ -97505,7 +97458,7 @@ function terminateStalledTransport(transport, state, reason) {
|
|
|
97505
97458
|
state.pollTimer = null;
|
|
97506
97459
|
}
|
|
97507
97460
|
recordOutboundQueuePerf("queue:killed", 1);
|
|
97508
|
-
|
|
97461
|
+
debugWarn("Listen Wire", `Terminating stalled transport (${reason})`);
|
|
97509
97462
|
if (getListenerTransportKind(transport) === "websocket") {
|
|
97510
97463
|
const ws = transport;
|
|
97511
97464
|
try {
|
|
@@ -97886,7 +97839,7 @@ function notifyStreamObservers(listener, message, runtimeScope) {
|
|
|
97886
97839
|
try {
|
|
97887
97840
|
observer(observed);
|
|
97888
97841
|
} catch (error4) {
|
|
97889
|
-
|
|
97842
|
+
debugWarn("Listen V2", "Stream observer failed", error4);
|
|
97890
97843
|
}
|
|
97891
97844
|
}
|
|
97892
97845
|
}
|
|
@@ -97901,11 +97854,14 @@ function notifyStreamObserversRuntimeStopped(listener) {
|
|
|
97901
97854
|
try {
|
|
97902
97855
|
observer(observed);
|
|
97903
97856
|
} catch (error4) {
|
|
97904
|
-
|
|
97857
|
+
debugWarn("Listen V2", "Stream observer failed on stop", error4);
|
|
97905
97858
|
}
|
|
97906
97859
|
}
|
|
97907
97860
|
listener.streamObservers.clear();
|
|
97908
97861
|
}
|
|
97862
|
+
var init_stream_observers = __esm(() => {
|
|
97863
|
+
init_debug();
|
|
97864
|
+
});
|
|
97909
97865
|
|
|
97910
97866
|
// src/websocket/listener/inbound-queue.ts
|
|
97911
97867
|
function getInboundClientMessageId(incoming) {
|
|
@@ -98010,6 +97966,7 @@ var init_turn_correlation = __esm(() => {
|
|
|
98010
97966
|
// src/websocket/listener/protocol-outbound.ts
|
|
98011
97967
|
var exports_protocol_outbound = {};
|
|
98012
97968
|
__export(exports_protocol_outbound, {
|
|
97969
|
+
refreshDeviceGitContext: () => refreshDeviceGitContext,
|
|
98013
97970
|
isSystemReminderPart: () => isSystemReminderPart,
|
|
98014
97971
|
emitSubagentStateUpdate: () => emitSubagentStateUpdate,
|
|
98015
97972
|
emitSubagentStateIfOpen: () => emitSubagentStateIfOpen,
|
|
@@ -98048,25 +98005,6 @@ function getProtocolPerfKey(message) {
|
|
|
98048
98005
|
}
|
|
98049
98006
|
return message.type;
|
|
98050
98007
|
}
|
|
98051
|
-
function getCachedDeviceGitContext(cwd) {
|
|
98052
|
-
const now = Date.now();
|
|
98053
|
-
const cached2 = gitContextCache.get(cwd);
|
|
98054
|
-
if (cached2 && cached2.expiresAt > now) {
|
|
98055
|
-
return cached2.value;
|
|
98056
|
-
}
|
|
98057
|
-
const value = getGitContext(cwd);
|
|
98058
|
-
gitContextCache.set(cwd, {
|
|
98059
|
-
expiresAt: now + GIT_CONTEXT_CACHE_TTL_MS,
|
|
98060
|
-
value
|
|
98061
|
-
});
|
|
98062
|
-
if (gitContextCache.size > MAX_GIT_CONTEXT_CACHE_ENTRIES) {
|
|
98063
|
-
const oldestKey = gitContextCache.keys().next().value;
|
|
98064
|
-
if (oldestKey) {
|
|
98065
|
-
gitContextCache.delete(oldestKey);
|
|
98066
|
-
}
|
|
98067
|
-
}
|
|
98068
|
-
return value;
|
|
98069
|
-
}
|
|
98070
98008
|
function getListenerRuntime(runtime) {
|
|
98071
98009
|
if (!runtime)
|
|
98072
98010
|
return null;
|
|
@@ -98081,6 +98019,18 @@ function getScopeForRuntime(runtime, scope) {
|
|
|
98081
98019
|
}
|
|
98082
98020
|
return scope ?? {};
|
|
98083
98021
|
}
|
|
98022
|
+
function getDeviceStatusWorkingDirectory(runtime, params) {
|
|
98023
|
+
const listener = getListenerRuntime(runtime);
|
|
98024
|
+
if (!listener) {
|
|
98025
|
+
return process.cwd();
|
|
98026
|
+
}
|
|
98027
|
+
const scope = getScopeForRuntime(runtime, params);
|
|
98028
|
+
const conversationRuntime = getConversationRuntime(listener, resolveScopedAgentId(listener, scope), resolveScopedConversationId(listener, scope));
|
|
98029
|
+
return conversationRuntime?.activeWorkingDirectory ?? getConversationWorkingDirectory(listener, resolveScopedAgentId(listener, scope), resolveScopedConversationId(listener, scope));
|
|
98030
|
+
}
|
|
98031
|
+
async function refreshDeviceGitContext(runtime, params) {
|
|
98032
|
+
await deviceGitContextCache.refresh(getDeviceStatusWorkingDirectory(runtime, params));
|
|
98033
|
+
}
|
|
98084
98034
|
function emitRuntimeStateUpdates(runtime, scope) {
|
|
98085
98035
|
emitLoopStatusIfOpen(runtime, scope);
|
|
98086
98036
|
emitDeviceStatusIfOpen(runtime, scope);
|
|
@@ -98096,7 +98046,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
98096
98046
|
is_processing: false,
|
|
98097
98047
|
current_permission_mode: permissionMode.getMode(),
|
|
98098
98048
|
current_working_directory: fallbackCwd,
|
|
98099
|
-
git_context:
|
|
98049
|
+
git_context: deviceGitContextCache.read(fallbackCwd),
|
|
98100
98050
|
letta_code_version: process.env.npm_package_version || null,
|
|
98101
98051
|
current_toolset: null,
|
|
98102
98052
|
current_toolset_preference: "auto",
|
|
@@ -98149,7 +98099,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
98149
98099
|
is_processing: !!conversationRuntime?.isProcessing,
|
|
98150
98100
|
current_permission_mode: conversationPermissionModeState.mode,
|
|
98151
98101
|
current_working_directory: resolvedCwd,
|
|
98152
|
-
git_context:
|
|
98102
|
+
git_context: deviceGitContextCache.read(resolvedCwd),
|
|
98153
98103
|
letta_code_version: process.env.npm_package_version || null,
|
|
98154
98104
|
current_toolset: conversationRuntime?.currentToolset ?? (toolsetPreference === "auto" ? null : toolsetPreference),
|
|
98155
98105
|
current_toolset_preference: conversationRuntime?.currentToolset === null ? toolsetPreference : conversationRuntime?.currentToolsetPreference ?? toolsetPreference,
|
|
@@ -98253,7 +98203,7 @@ function emitProtocolV2Message(socket, runtime, message, scope, routing) {
|
|
|
98253
98203
|
try {
|
|
98254
98204
|
payload = JSON.stringify(outbound);
|
|
98255
98205
|
} catch (error4) {
|
|
98256
|
-
|
|
98206
|
+
debugWarn("Listen V2", `Failed to emit ${message.type} (seq=${eventSeq})`, error4);
|
|
98257
98207
|
safeEmitWsEvent("send", "lifecycle", {
|
|
98258
98208
|
type: "_ws_send_error",
|
|
98259
98209
|
message_type: message.type,
|
|
@@ -98266,15 +98216,13 @@ function emitProtocolV2Message(socket, runtime, message, scope, routing) {
|
|
|
98266
98216
|
payload,
|
|
98267
98217
|
perfKey: getProtocolPerfKey(message),
|
|
98268
98218
|
onSent: () => {
|
|
98269
|
-
|
|
98270
|
-
console.log(`[Listen V2] Emitting ${message.type} (seq=${eventSeq})`);
|
|
98271
|
-
}
|
|
98219
|
+
debugLog("Listen V2", `Emitting ${message.type} (seq=${eventSeq})`);
|
|
98272
98220
|
safeEmitWsEvent("send", "protocol", outbound);
|
|
98273
98221
|
}
|
|
98274
98222
|
};
|
|
98275
98223
|
},
|
|
98276
98224
|
onSendError: (error4) => {
|
|
98277
|
-
|
|
98225
|
+
debugWarn("Listen V2", `Failed to emit ${message.type}`, error4);
|
|
98278
98226
|
safeEmitWsEvent("send", "lifecycle", {
|
|
98279
98227
|
type: "_ws_send_error",
|
|
98280
98228
|
message_type: message.type,
|
|
@@ -98580,11 +98528,10 @@ function emitStreamDelta(socket, runtime, delta2, scope, subagentId) {
|
|
|
98580
98528
|
};
|
|
98581
98529
|
emitProtocolV2Message(socket, runtime, message, scope, TO_SUBSCRIBERS);
|
|
98582
98530
|
}
|
|
98583
|
-
var
|
|
98531
|
+
var FROZEN_SUPPORTED_COMMANDS;
|
|
98584
98532
|
var init_protocol_outbound = __esm(() => {
|
|
98585
98533
|
init_memory_filesystem2();
|
|
98586
98534
|
init_subagent_state();
|
|
98587
|
-
init_git_context();
|
|
98588
98535
|
init_memory_reminder();
|
|
98589
98536
|
init_system_prompt_warning();
|
|
98590
98537
|
init_constants2();
|
|
@@ -98597,16 +98544,17 @@ var init_protocol_outbound = __esm(() => {
|
|
|
98597
98544
|
init_connection();
|
|
98598
98545
|
init_constants3();
|
|
98599
98546
|
init_cwd();
|
|
98547
|
+
init_device_git_context();
|
|
98600
98548
|
init_device_status_cache();
|
|
98601
98549
|
init_listener_constants();
|
|
98602
98550
|
init_outbound_wire();
|
|
98603
98551
|
init_permission_mode();
|
|
98604
98552
|
init_protocol_outbound_routing();
|
|
98605
98553
|
init_runtime();
|
|
98554
|
+
init_stream_observers();
|
|
98606
98555
|
init_transport();
|
|
98607
98556
|
init_turn_correlation();
|
|
98608
98557
|
FROZEN_SUPPORTED_COMMANDS = [...SUPPORTED_REMOTE_COMMANDS];
|
|
98609
|
-
gitContextCache = new Map;
|
|
98610
98558
|
});
|
|
98611
98559
|
|
|
98612
98560
|
// src/websocket/listener/cwd-change.ts
|
|
@@ -98651,10 +98599,13 @@ async function switchConversationWorkingDirectory(params) {
|
|
|
98651
98599
|
}
|
|
98652
98600
|
if (params.emitStatus !== false) {
|
|
98653
98601
|
const statusTransport = params.statusSocket ?? getOrCreateProcessTransport(runtime);
|
|
98654
|
-
|
|
98602
|
+
const statusRuntime = params.statusRuntime ?? conversationRuntime ?? runtime;
|
|
98603
|
+
const statusScope = {
|
|
98655
98604
|
agent_id: agentId,
|
|
98656
98605
|
conversation_id: conversationId
|
|
98657
|
-
}
|
|
98606
|
+
};
|
|
98607
|
+
await refreshDeviceGitContext(statusRuntime, statusScope);
|
|
98608
|
+
emitDeviceStatusUpdate(statusTransport, statusRuntime, statusScope);
|
|
98658
98609
|
}
|
|
98659
98610
|
}
|
|
98660
98611
|
var init_cwd_change = __esm(() => {
|
|
@@ -98685,7 +98636,7 @@ function startWorktreeWatcher(params) {
|
|
|
98685
98636
|
}).catch((err) => {
|
|
98686
98637
|
if (err.name === "AbortError")
|
|
98687
98638
|
return;
|
|
98688
|
-
|
|
98639
|
+
debugWarn("WorktreeWatcher", "watch loop error:", err);
|
|
98689
98640
|
});
|
|
98690
98641
|
return state;
|
|
98691
98642
|
}
|
|
@@ -98741,7 +98692,7 @@ async function runWatchLoop(params) {
|
|
|
98741
98692
|
agentId,
|
|
98742
98693
|
conversationId
|
|
98743
98694
|
}).catch((err) => {
|
|
98744
|
-
|
|
98695
|
+
debugWarn("WorktreeWatcher", "failed to handle new worktree:", err);
|
|
98745
98696
|
});
|
|
98746
98697
|
}, DEBOUNCE_MS);
|
|
98747
98698
|
}
|
|
@@ -98761,7 +98712,7 @@ async function handleNewWorktree(params) {
|
|
|
98761
98712
|
return;
|
|
98762
98713
|
}
|
|
98763
98714
|
clearExpectedWorktreePath(conversationRuntime);
|
|
98764
|
-
|
|
98715
|
+
debugLog("WorktreeWatcher", `New worktree detected: ${newWorktreePath} — switching CWD`);
|
|
98765
98716
|
await switchConversationWorkingDirectory({
|
|
98766
98717
|
runtime,
|
|
98767
98718
|
agentId,
|
|
@@ -98794,6 +98745,7 @@ async function safeReaddir(dir) {
|
|
|
98794
98745
|
}
|
|
98795
98746
|
var WORKTREES_DIR = ".letta/worktrees", DEBOUNCE_MS = 500;
|
|
98796
98747
|
var init_worktree_watcher = __esm(() => {
|
|
98748
|
+
init_debug();
|
|
98797
98749
|
init_cwd();
|
|
98798
98750
|
init_cwd_change();
|
|
98799
98751
|
init_runtime();
|
|
@@ -99839,6 +99791,7 @@ function formatExecOutput(params) {
|
|
|
99839
99791
|
}
|
|
99840
99792
|
if (params.sessionId !== null) {
|
|
99841
99793
|
sections.push(`Process running with session ID ${params.sessionId}`);
|
|
99794
|
+
sections.push("You will be notified when the process completes. Do not poll unless you need the output before continuing.");
|
|
99842
99795
|
}
|
|
99843
99796
|
sections.push(`Original token count: ${params.originalTokenCount}`);
|
|
99844
99797
|
sections.push("Output:");
|
|
@@ -99909,7 +99862,7 @@ function createSessionOutputAppender(params) {
|
|
|
99909
99862
|
appendSessionOutput(params.session, `
|
|
99910
99863
|
[output file write failed; output may be incomplete]
|
|
99911
99864
|
`, "stderr");
|
|
99912
|
-
markSessionFailed(params.session);
|
|
99865
|
+
markSessionFailed(params.session, "Output file write failed; output may be incomplete");
|
|
99913
99866
|
const bgProc = backgroundProcesses.get(params.session.id);
|
|
99914
99867
|
if (bgProc) {
|
|
99915
99868
|
try {
|
|
@@ -99919,19 +99872,61 @@ function createSessionOutputAppender(params) {
|
|
|
99919
99872
|
}
|
|
99920
99873
|
};
|
|
99921
99874
|
}
|
|
99922
|
-
function
|
|
99875
|
+
function notifyExecCompletion(session) {
|
|
99876
|
+
if (!session.notificationArmed || session.completionDelivered || session.activeWriteStdinCalls > 0) {
|
|
99877
|
+
return;
|
|
99878
|
+
}
|
|
99879
|
+
const backgroundProcess = backgroundProcesses.get(session.id);
|
|
99880
|
+
if (backgroundProcess?.completionNotificationSuppressed) {
|
|
99881
|
+
session.completionDelivered = true;
|
|
99882
|
+
return;
|
|
99883
|
+
}
|
|
99884
|
+
session.completionDelivered = true;
|
|
99885
|
+
const status = session.status === "completed" ? "completed" : "failed";
|
|
99886
|
+
const unreadOutput = session.output.slice(session.readOffset) || "(no new output)";
|
|
99887
|
+
const { content: result } = truncateByChars(scrubSecretsFromString([
|
|
99888
|
+
`$ ${session.command}`,
|
|
99889
|
+
`Session ID: ${session.id}`,
|
|
99890
|
+
session.completionDetail,
|
|
99891
|
+
unreadOutput
|
|
99892
|
+
].filter(Boolean).join(`
|
|
99893
|
+
|
|
99894
|
+
`), session.secrets), LIMITS.BASH_NOTIFICATION_CHARS, "exec_command", { useMiddleTruncation: true });
|
|
99895
|
+
const durationMs = backgroundProcess?.startTime ? Math.max(0, Date.now() - backgroundProcess.startTime.getTime()) : undefined;
|
|
99896
|
+
addToMessageQueue({
|
|
99897
|
+
kind: "task_notification",
|
|
99898
|
+
text: formatTaskNotification({
|
|
99899
|
+
taskId: `exec_${session.id}`,
|
|
99900
|
+
status,
|
|
99901
|
+
summary: `Exec command "${session.description?.trim() || session.command}" ${status}`,
|
|
99902
|
+
result,
|
|
99903
|
+
outputFile: session.outputFile,
|
|
99904
|
+
usage: durationMs === undefined ? undefined : { durationMs }
|
|
99905
|
+
}),
|
|
99906
|
+
agentId: session.notificationScope?.agentId,
|
|
99907
|
+
conversationId: session.notificationScope?.conversationId
|
|
99908
|
+
});
|
|
99909
|
+
}
|
|
99910
|
+
function markSessionFailed(session, detail) {
|
|
99911
|
+
if (session.status !== "running")
|
|
99912
|
+
return;
|
|
99923
99913
|
session.status = "failed";
|
|
99914
|
+
session.completionDetail = detail;
|
|
99924
99915
|
const bgProcess = backgroundProcesses.get(session.id);
|
|
99925
99916
|
if (bgProcess) {
|
|
99926
99917
|
bgProcess.status = "failed";
|
|
99927
99918
|
scrubCompletedBackgroundOutput(bgProcess);
|
|
99928
99919
|
scheduleBackgroundProcessCleanup(session.id);
|
|
99929
99920
|
}
|
|
99921
|
+
notifyExecCompletion(session);
|
|
99930
99922
|
scheduleExecSessionCleanup(session.id);
|
|
99931
99923
|
}
|
|
99932
99924
|
function markSessionClosed(session, code2) {
|
|
99925
|
+
if (session.status !== "running")
|
|
99926
|
+
return;
|
|
99933
99927
|
session.status = code2 === 0 && !session.outputWriteFailed ? "completed" : "failed";
|
|
99934
99928
|
session.exitCode = code2;
|
|
99929
|
+
session.completionDetail = code2 === null ? "Terminated by signal before exiting" : `Exit code: ${code2}`;
|
|
99935
99930
|
const bgProcess = backgroundProcesses.get(session.id);
|
|
99936
99931
|
if (bgProcess) {
|
|
99937
99932
|
bgProcess.status = session.status;
|
|
@@ -99939,6 +99934,7 @@ function markSessionClosed(session, code2) {
|
|
|
99939
99934
|
scrubCompletedBackgroundOutput(bgProcess);
|
|
99940
99935
|
scheduleBackgroundProcessCleanup(session.id);
|
|
99941
99936
|
}
|
|
99937
|
+
notifyExecCompletion(session);
|
|
99942
99938
|
scheduleExecSessionCleanup(session.id);
|
|
99943
99939
|
}
|
|
99944
99940
|
async function waitForSessionOutput(params) {
|
|
@@ -99986,13 +99982,19 @@ async function startExecSession(args) {
|
|
|
99986
99982
|
const session = {
|
|
99987
99983
|
id: id2,
|
|
99988
99984
|
command: args.cmd,
|
|
99985
|
+
description: args.description,
|
|
99989
99986
|
output: "",
|
|
99987
|
+
outputFile,
|
|
99990
99988
|
chunks: [],
|
|
99991
99989
|
readOffset: 0,
|
|
99992
99990
|
status: "running",
|
|
99993
99991
|
exitCode: null,
|
|
99994
99992
|
tty: args.tty ?? false,
|
|
99995
|
-
secrets: args.secretEnv ?? {}
|
|
99993
|
+
secrets: args.secretEnv ?? {},
|
|
99994
|
+
notificationScope: resolveNotificationScope(args.parentScope),
|
|
99995
|
+
notificationArmed: false,
|
|
99996
|
+
completionDelivered: false,
|
|
99997
|
+
activeWriteStdinCalls: 0
|
|
99996
99998
|
};
|
|
99997
99999
|
execSessions.set(id2, session);
|
|
99998
100000
|
const appendOutput = createSessionOutputAppender({
|
|
@@ -100041,7 +100043,7 @@ async function startExecSession(args) {
|
|
|
100041
100043
|
if (error4 instanceof ShellExecutionError) {
|
|
100042
100044
|
appendOutput(error4.message, "stderr");
|
|
100043
100045
|
}
|
|
100044
|
-
markSessionFailed(session);
|
|
100046
|
+
markSessionFailed(session, `Error: ${error4 instanceof Error ? error4.message : String(error4)}`);
|
|
100045
100047
|
});
|
|
100046
100048
|
return session;
|
|
100047
100049
|
}
|
|
@@ -100060,6 +100062,9 @@ async function exec_command(args) {
|
|
|
100060
100062
|
onOutput: args.onOutput
|
|
100061
100063
|
});
|
|
100062
100064
|
const sessionId = session.status === "running" ? session.id : null;
|
|
100065
|
+
if (sessionId !== null) {
|
|
100066
|
+
session.notificationArmed = true;
|
|
100067
|
+
}
|
|
100063
100068
|
const formattedOutput = formatExecOutput({
|
|
100064
100069
|
chunkId: generateChunkId(),
|
|
100065
100070
|
wallTimeMs,
|
|
@@ -100093,19 +100098,35 @@ async function write_stdin(args) {
|
|
|
100093
100098
|
throw new Error("stdin is closed for this session; rerun exec_command with tty=true to keep stdin open");
|
|
100094
100099
|
}
|
|
100095
100100
|
}
|
|
100096
|
-
|
|
100097
|
-
|
|
100098
|
-
|
|
100101
|
+
session.activeWriteStdinCalls++;
|
|
100102
|
+
let output;
|
|
100103
|
+
let wallTimeMs;
|
|
100104
|
+
let waitCompleted = false;
|
|
100105
|
+
try {
|
|
100106
|
+
if (chars && session.tty) {
|
|
100107
|
+
backgroundProcess.process.write(chars);
|
|
100108
|
+
await sleep9(100, args.signal);
|
|
100109
|
+
}
|
|
100110
|
+
const startOffset = session.readOffset;
|
|
100111
|
+
const yieldTimeMs = clampWriteStdinYieldTime(args.yield_time_ms, chars);
|
|
100112
|
+
({ output, wallTimeMs } = await waitForSessionOutput({
|
|
100113
|
+
session,
|
|
100114
|
+
startOffset,
|
|
100115
|
+
yieldTimeMs,
|
|
100116
|
+
signal: args.signal,
|
|
100117
|
+
onOutput: args.onOutput
|
|
100118
|
+
}));
|
|
100119
|
+
waitCompleted = true;
|
|
100120
|
+
} finally {
|
|
100121
|
+
session.activeWriteStdinCalls--;
|
|
100122
|
+
if (session.status !== "running") {
|
|
100123
|
+
if (waitCompleted) {
|
|
100124
|
+
session.completionDelivered = true;
|
|
100125
|
+
} else {
|
|
100126
|
+
notifyExecCompletion(session);
|
|
100127
|
+
}
|
|
100128
|
+
}
|
|
100099
100129
|
}
|
|
100100
|
-
const startOffset = session.readOffset;
|
|
100101
|
-
const yieldTimeMs = clampWriteStdinYieldTime(args.yield_time_ms, chars);
|
|
100102
|
-
const { output, wallTimeMs } = await waitForSessionOutput({
|
|
100103
|
-
session,
|
|
100104
|
-
startOffset,
|
|
100105
|
-
yieldTimeMs,
|
|
100106
|
-
signal: args.signal,
|
|
100107
|
-
onOutput: args.onOutput
|
|
100108
|
-
});
|
|
100109
100130
|
const nextSessionId = session.status === "running" ? session.id : null;
|
|
100110
100131
|
const formattedOutput = formatExecOutput({
|
|
100111
100132
|
chunkId: generateChunkId(),
|
|
@@ -100128,6 +100149,8 @@ var DEFAULT_EXEC_YIELD_TIME_MS = 1e4, DEFAULT_WRITE_STDIN_YIELD_TIME_MS = 250, M
|
|
|
100128
100149
|
var init_exec_command = __esm(() => {
|
|
100129
100150
|
init_runtime_context();
|
|
100130
100151
|
init_secret_substitution();
|
|
100152
|
+
init_message_queue_bridge();
|
|
100153
|
+
init_task_notifications();
|
|
100131
100154
|
init_worktree_ownership();
|
|
100132
100155
|
init_process_manager();
|
|
100133
100156
|
init_shell();
|
|
@@ -100302,9 +100325,9 @@ var init_exit_worktree = __esm(() => {
|
|
|
100302
100325
|
});
|
|
100303
100326
|
|
|
100304
100327
|
// src/tools/impl/glob.ts
|
|
100305
|
-
import { execFile as
|
|
100328
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
100306
100329
|
import * as path20 from "node:path";
|
|
100307
|
-
import { promisify as
|
|
100330
|
+
import { promisify as promisify4 } from "node:util";
|
|
100308
100331
|
function applyFileLimit(files, workingDirectory) {
|
|
100309
100332
|
const totalFiles = files.length;
|
|
100310
100333
|
if (totalFiles <= LIMITS.GLOB_MAX_FILES) {
|
|
@@ -100342,7 +100365,7 @@ async function glob(args) {
|
|
|
100342
100365
|
baseDir
|
|
100343
100366
|
];
|
|
100344
100367
|
try {
|
|
100345
|
-
const { stdout } = await
|
|
100368
|
+
const { stdout } = await execFileAsync2(rgPath, rgArgs, {
|
|
100346
100369
|
maxBuffer: 50 * 1024 * 1024,
|
|
100347
100370
|
cwd: userCwd,
|
|
100348
100371
|
signal
|
|
@@ -100366,12 +100389,12 @@ async function glob(args) {
|
|
|
100366
100389
|
throw new Error(`Glob failed: ${err.message || "Unknown error"}`);
|
|
100367
100390
|
}
|
|
100368
100391
|
}
|
|
100369
|
-
var
|
|
100392
|
+
var execFileAsync2;
|
|
100370
100393
|
var init_glob = __esm(() => {
|
|
100371
100394
|
init_runtime_context();
|
|
100372
100395
|
init_ripgrep_manager();
|
|
100373
100396
|
init_truncation();
|
|
100374
|
-
|
|
100397
|
+
execFileAsync2 = promisify4(execFile3);
|
|
100375
100398
|
});
|
|
100376
100399
|
|
|
100377
100400
|
// src/tools/impl/glob-gemini.ts
|
|
@@ -100390,9 +100413,9 @@ var init_glob_gemini = __esm(() => {
|
|
|
100390
100413
|
});
|
|
100391
100414
|
|
|
100392
100415
|
// src/tools/impl/grep.ts
|
|
100393
|
-
import { execFile as
|
|
100416
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
100394
100417
|
import * as path21 from "node:path";
|
|
100395
|
-
import { promisify as
|
|
100418
|
+
import { promisify as promisify5 } from "node:util";
|
|
100396
100419
|
function applyOffsetAndLimit(items3, offset, limit3) {
|
|
100397
100420
|
const sliced = items3.slice(offset);
|
|
100398
100421
|
if (limit3 > 0) {
|
|
@@ -100454,7 +100477,7 @@ async function grep(args) {
|
|
|
100454
100477
|
else
|
|
100455
100478
|
rgArgs.push(userCwd);
|
|
100456
100479
|
try {
|
|
100457
|
-
const { stdout } = await
|
|
100480
|
+
const { stdout } = await execFileAsync3(rgPath, rgArgs, {
|
|
100458
100481
|
maxBuffer: 10 * 1024 * 1024,
|
|
100459
100482
|
cwd: userCwd,
|
|
100460
100483
|
signal
|
|
@@ -100549,12 +100572,12 @@ Found 0 total occurrences across 0 files.`,
|
|
|
100549
100572
|
throw new Error(`Grep failed: ${message}`);
|
|
100550
100573
|
}
|
|
100551
100574
|
}
|
|
100552
|
-
var
|
|
100575
|
+
var execFileAsync3;
|
|
100553
100576
|
var init_grep = __esm(() => {
|
|
100554
100577
|
init_runtime_context();
|
|
100555
100578
|
init_ripgrep_manager();
|
|
100556
100579
|
init_truncation();
|
|
100557
|
-
|
|
100580
|
+
execFileAsync3 = promisify5(execFile4);
|
|
100558
100581
|
});
|
|
100559
100582
|
|
|
100560
100583
|
// src/tools/impl/grep-files.ts
|
|
@@ -104406,13 +104429,13 @@ var exports_image_resize_sips = {};
|
|
|
104406
104429
|
__export(exports_image_resize_sips, {
|
|
104407
104430
|
convertHeicToJpegWithSips: () => convertHeicToJpegWithSips
|
|
104408
104431
|
});
|
|
104409
|
-
import { execFile as
|
|
104432
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
104410
104433
|
import { mkdtemp, readFile as readFile10, rm as rm5, writeFile as writeFile8 } from "node:fs/promises";
|
|
104411
104434
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
104412
104435
|
import { join as join23 } from "node:path";
|
|
104413
|
-
function
|
|
104436
|
+
function execFileAsync4(file, args) {
|
|
104414
104437
|
return new Promise((resolve19, reject) => {
|
|
104415
|
-
|
|
104438
|
+
execFile5(file, args, (error4) => {
|
|
104416
104439
|
if (error4) {
|
|
104417
104440
|
reject(error4);
|
|
104418
104441
|
return;
|
|
@@ -104427,7 +104450,7 @@ async function convertHeicToJpegWithSips(buffer) {
|
|
|
104427
104450
|
const outputPath = join23(workDir, "output.jpg");
|
|
104428
104451
|
try {
|
|
104429
104452
|
await writeFile8(inputPath, buffer);
|
|
104430
|
-
await
|
|
104453
|
+
await execFileAsync4("/usr/bin/sips", [
|
|
104431
104454
|
"-s",
|
|
104432
104455
|
"format",
|
|
104433
104456
|
"jpeg",
|
|
@@ -114805,6 +114828,9 @@ function buildSubagentArgs(type3, config, model, userPrompt, existingAgentId, ex
|
|
|
114805
114828
|
}
|
|
114806
114829
|
if (isDeployingExisting) {
|
|
114807
114830
|
if (existingConversationId) {
|
|
114831
|
+
if (existingConversationId === "default" && existingAgentId) {
|
|
114832
|
+
args.push("--agent", existingAgentId);
|
|
114833
|
+
}
|
|
114808
114834
|
args.push("--conv", existingConversationId);
|
|
114809
114835
|
} else if (existingAgentId) {
|
|
114810
114836
|
args.push("--agent", existingAgentId, "--new");
|
|
@@ -116176,7 +116202,7 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
116176
116202
|
},
|
|
116177
116203
|
run_in_background: {
|
|
116178
116204
|
type: "boolean",
|
|
116179
|
-
description: "Set to true
|
|
116205
|
+
description: "Set to true only when the command should return a task ID immediately. Ordinary commands already yield automatically if they are still running after a brief wait, and completion is delivered without polling."
|
|
116180
116206
|
}
|
|
116181
116207
|
},
|
|
116182
116208
|
required: ["command", "description"],
|
|
@@ -116747,7 +116773,7 @@ var init_Monitor2 = __esm(() => {
|
|
|
116747
116773
|
properties: {
|
|
116748
116774
|
description: {
|
|
116749
116775
|
type: "string",
|
|
116750
|
-
description: "
|
|
116776
|
+
description: "Clear, concise user-facing description of the update you are waiting for. This may be shown directly in chat, so make it grammatical by itself. Describe the expected event, not the polling command or monitor implementation. Prefer `CI results and review comments for the auth fix`, `Deployment completion or failure`, or `New errors in the API logs` over internal labels like `PR checks and state transitions`."
|
|
116751
116777
|
},
|
|
116752
116778
|
timeout_ms: {
|
|
116753
116779
|
type: "number",
|
|
@@ -126691,12 +126717,12 @@ import {
|
|
|
126691
126717
|
mkdirSync as mkdirSync15,
|
|
126692
126718
|
readFileSync as readFileSync13,
|
|
126693
126719
|
renameSync as renameSync3,
|
|
126694
|
-
rmSync as
|
|
126720
|
+
rmSync as rmSync5,
|
|
126695
126721
|
writeFileSync as writeFileSync11
|
|
126696
126722
|
} from "node:fs";
|
|
126697
126723
|
import { homedir as homedir21, platform as platform3 } from "node:os";
|
|
126698
126724
|
import { dirname as dirname21, isAbsolute as isAbsolute21, join as join32 } from "node:path";
|
|
126699
|
-
import { promisify as
|
|
126725
|
+
import { promisify as promisify6 } from "node:util";
|
|
126700
126726
|
function getAgentRootDir(agentId) {
|
|
126701
126727
|
return join32(homedir21(), ".letta", "agents", agentId);
|
|
126702
126728
|
}
|
|
@@ -126836,7 +126862,7 @@ async function syncRepoMount(args) {
|
|
|
126836
126862
|
timeoutMs: GIT_CLONE_TIMEOUT_MS
|
|
126837
126863
|
});
|
|
126838
126864
|
} catch (err) {
|
|
126839
|
-
|
|
126865
|
+
rmSync5(args.directory, { recursive: true, force: true });
|
|
126840
126866
|
throw err;
|
|
126841
126867
|
}
|
|
126842
126868
|
} else if (!existsSync25(join32(args.directory, ".git"))) {
|
|
@@ -126974,7 +127000,7 @@ async function runGit3(cwd, args, token, options) {
|
|
|
126974
127000
|
const timeoutMs = options?.timeoutMs ?? GIT_DEFAULT_TIMEOUT_MS;
|
|
126975
127001
|
let result;
|
|
126976
127002
|
try {
|
|
126977
|
-
result = await
|
|
127003
|
+
result = await execFile6("git", allArgs, {
|
|
126978
127004
|
cwd,
|
|
126979
127005
|
env: buildNonInteractiveGitEnv2(),
|
|
126980
127006
|
maxBuffer: 10485760,
|
|
@@ -127572,7 +127598,7 @@ async function cloneMemoryRepo(agentId) {
|
|
|
127572
127598
|
const tmpDir = `${dir}-git-clone-tmp`;
|
|
127573
127599
|
try {
|
|
127574
127600
|
if (existsSync25(tmpDir)) {
|
|
127575
|
-
|
|
127601
|
+
rmSync5(tmpDir, { recursive: true, force: true });
|
|
127576
127602
|
}
|
|
127577
127603
|
mkdirSync15(tmpDir, { recursive: true });
|
|
127578
127604
|
await runGitWithRetry(tmpDir, ["clone", url, "."], token, {
|
|
@@ -127590,7 +127616,7 @@ async function cloneMemoryRepo(agentId) {
|
|
|
127590
127616
|
debugLog("memfs-git", "Migrated existing memory directory to git repo");
|
|
127591
127617
|
} finally {
|
|
127592
127618
|
if (existsSync25(tmpDir)) {
|
|
127593
|
-
|
|
127619
|
+
rmSync5(tmpDir, { recursive: true, force: true });
|
|
127594
127620
|
}
|
|
127595
127621
|
}
|
|
127596
127622
|
}
|
|
@@ -127885,7 +127911,7 @@ async function addGitMemoryTag(agentId, prefetchedAgent) {
|
|
|
127885
127911
|
debugWarn("memfs-git", `Failed to add git-memory tag: ${err instanceof Error ? err.message : String(err)}`);
|
|
127886
127912
|
}
|
|
127887
127913
|
}
|
|
127888
|
-
var
|
|
127914
|
+
var execFile6, RETRYABLE_GIT_HTTP_ERROR_RE, RETRYABLE_GIT_NETWORK_ERROR_RE, MISSING_CWD_GIT_ERROR_RE, NON_FAST_FORWARD_PUSH_ERROR_RE, UNRELATED_HISTORY_PULL_ERROR_RE, NO_UPSTREAM_PULL_ERROR_RE, AGENT_DISPLAY_NAME_TIMEOUT_MS = 3000, HOSTED_BACKEND_HEADER2 = "x-letta-memfs-backend", HOSTED_BACKEND_VALUE2 = "hosted", GIT_DEFAULT_TIMEOUT_MS = 60000, GIT_CLONE_TIMEOUT_MS = 180000, gitConfig = (dir, args) => withSerializedGitConfigMutation(dir, () => runGit3(dir, args)), MEMORY_REPOSITORY_CONFIG_KEY = "letta.memoryRepository.url", MEMORY_REPOSITORY_PUSH_LOG = "memory-repository-push.log";
|
|
127889
127915
|
var init_memory_git = __esm(() => {
|
|
127890
127916
|
init_client2();
|
|
127891
127917
|
init_memfs_git_proxy();
|
|
@@ -127896,7 +127922,7 @@ var init_memory_git = __esm(() => {
|
|
|
127896
127922
|
init_memory_git_config_lock();
|
|
127897
127923
|
init_memory_git_hooks();
|
|
127898
127924
|
init_memory_git_signing();
|
|
127899
|
-
|
|
127925
|
+
execFile6 = promisify6(execFileCb2);
|
|
127900
127926
|
RETRYABLE_GIT_HTTP_ERROR_RE = /(?:\bHTTP\s+(?:520|521|522|523|524)\b|The requested URL returned error:\s*(?:520|521|522|523|524))/i;
|
|
127901
127927
|
RETRYABLE_GIT_NETWORK_ERROR_RE = /(remote end hung up unexpectedly|connection reset by peer|operation timed out|timed out|SIGTERM|ETIMEDOUT)/i;
|
|
127902
127928
|
MISSING_CWD_GIT_ERROR_RE = /(Unable to read current working directory: No such file or directory|\buv_cwd\b|\bcwd\b.*\bENOENT\b)/i;
|
|
@@ -128573,7 +128599,7 @@ import {
|
|
|
128573
128599
|
readdirSync as readdirSync9,
|
|
128574
128600
|
readFileSync as readFileSync14,
|
|
128575
128601
|
readSync,
|
|
128576
|
-
rmSync as
|
|
128602
|
+
rmSync as rmSync6,
|
|
128577
128603
|
statSync as statSync8,
|
|
128578
128604
|
writeFileSync as writeFileSync12
|
|
128579
128605
|
} from "node:fs";
|
|
@@ -129121,7 +129147,7 @@ class LocalStore {
|
|
|
129121
129147
|
this.persistedMessageByMessageIdByConversationKey.delete(key);
|
|
129122
129148
|
this.lastSessionEntryIdByConversationKey.delete(key);
|
|
129123
129149
|
if (this.storageDir) {
|
|
129124
|
-
|
|
129150
|
+
rmSync6(join33(this.storageDir, "conversations", encodePathSegment(key)), {
|
|
129125
129151
|
recursive: true,
|
|
129126
129152
|
force: true
|
|
129127
129153
|
});
|
|
@@ -129129,7 +129155,7 @@ class LocalStore {
|
|
|
129129
129155
|
}
|
|
129130
129156
|
}
|
|
129131
129157
|
if (this.storageDir) {
|
|
129132
|
-
|
|
129158
|
+
rmSync6(join33(this.storageDir, "agents", `${encodePathSegment(agentId)}.json`), { force: true });
|
|
129133
129159
|
}
|
|
129134
129160
|
}
|
|
129135
129161
|
retrieveAgentRecord(agentId) {
|
|
@@ -129440,7 +129466,7 @@ class LocalStore {
|
|
|
129440
129466
|
continue;
|
|
129441
129467
|
this.compiledSystemPromptByConversationKey.delete(key);
|
|
129442
129468
|
if (this.storageDir) {
|
|
129443
|
-
|
|
129469
|
+
rmSync6(join33(this.storageDir, "conversations", encodePathSegment(key), "system-prompt.json"), { force: true });
|
|
129444
129470
|
}
|
|
129445
129471
|
}
|
|
129446
129472
|
}
|
|
@@ -135626,7 +135652,7 @@ var init_local_backend = __esm(() => {
|
|
|
135626
135652
|
});
|
|
135627
135653
|
|
|
135628
135654
|
// src/backend/backend.ts
|
|
135629
|
-
import { mkdtempSync as mkdtempSync2, rmSync as
|
|
135655
|
+
import { mkdtempSync as mkdtempSync2, rmSync as rmSync7 } from "node:fs";
|
|
135630
135656
|
import { homedir as homedir22, tmpdir as tmpdir6 } from "node:os";
|
|
135631
135657
|
import { join as join34 } from "node:path";
|
|
135632
135658
|
function toApiConversationMessageListBody(body) {
|
|
@@ -135657,6 +135683,7 @@ class APIBackend {
|
|
|
135657
135683
|
}
|
|
135658
135684
|
getApiClientOverride;
|
|
135659
135685
|
forkConversationOverride;
|
|
135686
|
+
retrieveAgentInflightByKey = new Map;
|
|
135660
135687
|
constructor(deps = {}) {
|
|
135661
135688
|
this.getApiClientOverride = deps.getClient;
|
|
135662
135689
|
this.forkConversationOverride = deps.forkConversation;
|
|
@@ -135670,7 +135697,24 @@ class APIBackend {
|
|
|
135670
135697
|
}
|
|
135671
135698
|
async retrieveAgent(agentId, options) {
|
|
135672
135699
|
const client = await this.getClient();
|
|
135673
|
-
|
|
135700
|
+
if (options !== undefined) {
|
|
135701
|
+
return client.agents.retrieve(agentId, options);
|
|
135702
|
+
}
|
|
135703
|
+
const inflight2 = this.retrieveAgentInflightByKey.get(agentId);
|
|
135704
|
+
if (inflight2)
|
|
135705
|
+
return inflight2;
|
|
135706
|
+
const request = client.agents.retrieve(agentId, undefined);
|
|
135707
|
+
this.retrieveAgentInflightByKey.set(agentId, request);
|
|
135708
|
+
request.then(() => {
|
|
135709
|
+
if (this.retrieveAgentInflightByKey.get(agentId) === request) {
|
|
135710
|
+
this.retrieveAgentInflightByKey.delete(agentId);
|
|
135711
|
+
}
|
|
135712
|
+
}, () => {
|
|
135713
|
+
if (this.retrieveAgentInflightByKey.get(agentId) === request) {
|
|
135714
|
+
this.retrieveAgentInflightByKey.delete(agentId);
|
|
135715
|
+
}
|
|
135716
|
+
});
|
|
135717
|
+
return request;
|
|
135674
135718
|
}
|
|
135675
135719
|
async listAgentSecrets(agentId) {
|
|
135676
135720
|
const client = await this.getClient();
|
|
@@ -135829,7 +135873,7 @@ function configureEphemeralLocalBackend() {
|
|
|
135829
135873
|
executionMode: localBackendExecutionMode()
|
|
135830
135874
|
});
|
|
135831
135875
|
process.once("exit", () => {
|
|
135832
|
-
|
|
135876
|
+
rmSync7(stateStorageDir, { recursive: true, force: true });
|
|
135833
135877
|
});
|
|
135834
135878
|
}
|
|
135835
135879
|
function isLocalBackendEnabled() {
|
|
@@ -136554,7 +136598,7 @@ __export(exports_personality, {
|
|
|
136554
136598
|
import { execFile as execFileCb3 } from "node:child_process";
|
|
136555
136599
|
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "node:fs";
|
|
136556
136600
|
import { dirname as dirname22, join as join35 } from "node:path";
|
|
136557
|
-
import { promisify as
|
|
136601
|
+
import { promisify as promisify7 } from "node:util";
|
|
136558
136602
|
function ensureTrailingNewline2(content) {
|
|
136559
136603
|
return `${content.trimEnd()}
|
|
136560
136604
|
`;
|
|
@@ -136704,7 +136748,7 @@ async function applyPersonalityToMemory(params) {
|
|
|
136704
136748
|
const isLocalMemfs = getBackend().capabilities.localMemfs;
|
|
136705
136749
|
const blockDefinitions = getPersonalityBlockDefinitions(params.personalityId, isLocalMemfs ? "local" : "cloud");
|
|
136706
136750
|
const repoDir = isLocalMemfs ? getScopedMemoryFilesystemRoot(params.agentId) : getMemoryRepoDir(params.agentId);
|
|
136707
|
-
const statusResult = await
|
|
136751
|
+
const statusResult = await execFile7("git", ["status", "--porcelain"], {
|
|
136708
136752
|
cwd: repoDir,
|
|
136709
136753
|
timeout: 1e4
|
|
136710
136754
|
});
|
|
@@ -136768,7 +136812,7 @@ async function applyPersonalityToMemory(params) {
|
|
|
136768
136812
|
commitMessage
|
|
136769
136813
|
};
|
|
136770
136814
|
}
|
|
136771
|
-
var
|
|
136815
|
+
var execFile7, PRIMARY_PERSONA_RELATIVE_PATH = "system/persona.md", LEGACY_PERSONA_RELATIVE_PATH = "memory/system/persona.md", PRIMARY_HUMAN_RELATIVE_PATH = "system/human.md", LEGACY_HUMAN_RELATIVE_PATH = "memory/system/human.md";
|
|
136772
136816
|
var init_personality = __esm(() => {
|
|
136773
136817
|
init_backend2();
|
|
136774
136818
|
init_settings_manager();
|
|
@@ -136776,7 +136820,7 @@ var init_personality = __esm(() => {
|
|
|
136776
136820
|
init_memory_filesystem2();
|
|
136777
136821
|
init_memory_git();
|
|
136778
136822
|
init_personality_presets();
|
|
136779
|
-
|
|
136823
|
+
execFile7 = promisify7(execFileCb3);
|
|
136780
136824
|
});
|
|
136781
136825
|
|
|
136782
136826
|
// src/cli/args.ts
|
|
@@ -148670,7 +148714,7 @@ Learn more about this warning here: https://reactjs.org/link/legacy-context`, so
|
|
|
148670
148714
|
|
|
148671
148715
|
` + ("" + errorBoundaryMessage);
|
|
148672
148716
|
console["error"](combinedMessage);
|
|
148673
|
-
}
|
|
148717
|
+
}
|
|
148674
148718
|
} catch (e2) {
|
|
148675
148719
|
setTimeout(function() {
|
|
148676
148720
|
throw e2;
|
|
@@ -164543,7 +164587,7 @@ var CAPTURING_REGEX_SOURCE, RegexSource = class {
|
|
|
164543
164587
|
let localIncludedRule = repository[reference.ruleName];
|
|
164544
164588
|
if (localIncludedRule) {
|
|
164545
164589
|
ruleId = _RuleFactory.getCompiledRuleId(localIncludedRule, helper, repository);
|
|
164546
|
-
}
|
|
164590
|
+
}
|
|
164547
164591
|
break;
|
|
164548
164592
|
case 3:
|
|
164549
164593
|
case 4:
|
|
@@ -164555,11 +164599,11 @@ var CAPTURING_REGEX_SOURCE, RegexSource = class {
|
|
|
164555
164599
|
let externalIncludedRule = externalGrammar.repository[externalGrammarInclude];
|
|
164556
164600
|
if (externalIncludedRule) {
|
|
164557
164601
|
ruleId = _RuleFactory.getCompiledRuleId(externalIncludedRule, helper, externalGrammar.repository);
|
|
164558
|
-
}
|
|
164602
|
+
}
|
|
164559
164603
|
} else {
|
|
164560
164604
|
ruleId = _RuleFactory.getCompiledRuleId(externalGrammar.repository.$self, helper, externalGrammar.repository);
|
|
164561
164605
|
}
|
|
164562
|
-
}
|
|
164606
|
+
}
|
|
164563
164607
|
break;
|
|
164564
164608
|
}
|
|
164565
164609
|
} else {
|
|
@@ -175258,7 +175302,7 @@ import {
|
|
|
175258
175302
|
mkdirSync as mkdirSync18,
|
|
175259
175303
|
readdirSync as readdirSync10,
|
|
175260
175304
|
renameSync as renameSync4,
|
|
175261
|
-
rmSync as
|
|
175305
|
+
rmSync as rmSync8,
|
|
175262
175306
|
statSync as statSync10
|
|
175263
175307
|
} from "node:fs";
|
|
175264
175308
|
import { arch as arch2, homedir as homedir23, platform as platform5 } from "node:os";
|
|
@@ -175635,8 +175679,8 @@ async function downloadFd() {
|
|
|
175635
175679
|
chmodSync5(FD_LOCAL_PATH, 493);
|
|
175636
175680
|
}
|
|
175637
175681
|
} finally {
|
|
175638
|
-
|
|
175639
|
-
|
|
175682
|
+
rmSync8(archivePath, { force: true });
|
|
175683
|
+
rmSync8(extractDir, { recursive: true, force: true });
|
|
175640
175684
|
}
|
|
175641
175685
|
return FD_LOCAL_PATH;
|
|
175642
175686
|
}
|
|
@@ -179446,12 +179490,12 @@ __export(exports_auto_update, {
|
|
|
179446
179490
|
buildInstallArgs: () => buildInstallArgs
|
|
179447
179491
|
});
|
|
179448
179492
|
import {
|
|
179449
|
-
execFile as
|
|
179493
|
+
execFile as execFile8
|
|
179450
179494
|
} from "node:child_process";
|
|
179451
179495
|
import { accessSync, constants as constants4, realpathSync as realpathSync4 } from "node:fs";
|
|
179452
179496
|
import { readdir as readdir7, rm as rm6 } from "node:fs/promises";
|
|
179453
179497
|
import { dirname as dirname23, join as join41 } from "node:path";
|
|
179454
|
-
import { promisify as
|
|
179498
|
+
import { promisify as promisify8 } from "node:util";
|
|
179455
179499
|
function debugLog2(...args) {
|
|
179456
179500
|
if (DEBUG) {
|
|
179457
179501
|
console.error("[auto-update]", ...args);
|
|
@@ -179514,7 +179558,7 @@ function buildUpdateExecOptions(timeout, platform6 = process.platform) {
|
|
|
179514
179558
|
};
|
|
179515
179559
|
}
|
|
179516
179560
|
async function runUpdateCommand(command, args, timeout) {
|
|
179517
|
-
return
|
|
179561
|
+
return execFileAsync5(command, args, buildUpdateExecOptions(timeout));
|
|
179518
179562
|
}
|
|
179519
179563
|
function getResolvedEntrypoint() {
|
|
179520
179564
|
const argv = process.argv[1] || "";
|
|
@@ -179837,11 +179881,11 @@ async function manualUpdate(options) {
|
|
|
179837
179881
|
To update manually: ${installCmd}`
|
|
179838
179882
|
};
|
|
179839
179883
|
}
|
|
179840
|
-
var
|
|
179884
|
+
var execFileAsync5, DEBUG, DEFAULT_UPDATE_PACKAGE_NAME = "@letta-ai/letta-code", DEFAULT_UPDATE_REGISTRY_BASE_URL = "https://registry.npmjs.org", UPDATE_PACKAGE_NAME_ENV = "LETTA_UPDATE_PACKAGE_NAME", UPDATE_REGISTRY_BASE_URL_ENV = "LETTA_UPDATE_REGISTRY_BASE_URL", UPDATE_INSTALL_REGISTRY_URL_ENV = "LETTA_UPDATE_INSTALL_REGISTRY_URL", DESKTOP_MANAGED_ENV = "LETTA_CODE_DESKTOP_MANAGED", INSTALL_ARG_PREFIX, VALID_PACKAGE_MANAGERS, NPM_PREFIX_TIMEOUT_MS = 5000, UPDATE_INSTALL_TIMEOUT_MS = 60000;
|
|
179841
179885
|
var init_auto_update = __esm(() => {
|
|
179842
179886
|
init_error_reporting();
|
|
179843
179887
|
init_version();
|
|
179844
|
-
|
|
179888
|
+
execFileAsync5 = promisify8(execFile8);
|
|
179845
179889
|
DEBUG = process.env.LETTA_DEBUG_AUTOUPDATE === "1";
|
|
179846
179890
|
INSTALL_ARG_PREFIX = {
|
|
179847
179891
|
npm: ["install", "-g"],
|
|
@@ -181216,7 +181260,7 @@ __export(exports_transcription, {
|
|
|
181216
181260
|
isTranscriptionConfigured: () => isTranscriptionConfigured
|
|
181217
181261
|
});
|
|
181218
181262
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
181219
|
-
import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync22, rmSync as
|
|
181263
|
+
import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync22, rmSync as rmSync9 } from "node:fs";
|
|
181220
181264
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
181221
181265
|
import { basename as basename12, extname as extname5, join as join43 } from "node:path";
|
|
181222
181266
|
function audioMimeTypeForPath(localPath) {
|
|
@@ -181261,12 +181305,12 @@ function prepareOpenAiTranscriptionFile(localPath) {
|
|
|
181261
181305
|
convertedPath
|
|
181262
181306
|
], { stdio: "ignore", timeout: TRANSCRIPTION_TIMEOUT_MS });
|
|
181263
181307
|
} catch (error4) {
|
|
181264
|
-
|
|
181308
|
+
rmSync9(tempDir, { recursive: true, force: true });
|
|
181265
181309
|
throw new Error(`Unsupported audio format ${extname5(localPath).replace(/^\./, "") || "unknown"}; ffmpeg conversion failed. ffmpeg is required to transcribe this audio format; install ffmpeg on the channel listener machine. ${error4 instanceof Error ? error4.message : String(error4)}`);
|
|
181266
181310
|
}
|
|
181267
181311
|
return {
|
|
181268
181312
|
localPath: convertedPath,
|
|
181269
|
-
cleanup: () =>
|
|
181313
|
+
cleanup: () => rmSync9(tempDir, { recursive: true, force: true })
|
|
181270
181314
|
};
|
|
181271
181315
|
}
|
|
181272
181316
|
function isTranscriptionConfigured() {
|
|
@@ -187270,6 +187314,11 @@ function createSlackAdapter(config) {
|
|
|
187270
187314
|
throw error4;
|
|
187271
187315
|
}
|
|
187272
187316
|
}
|
|
187317
|
+
async function listCustomEmojis() {
|
|
187318
|
+
const client = await ensureWriteClient();
|
|
187319
|
+
const response = await client.emoji.list();
|
|
187320
|
+
return Object.keys(response.emoji ?? {}).sort((left, right) => left.localeCompare(right));
|
|
187321
|
+
}
|
|
187273
187322
|
async function downloadAttachment(params) {
|
|
187274
187323
|
const slackApp = await ensureApp();
|
|
187275
187324
|
return await downloadSlackAttachmentById({
|
|
@@ -187485,6 +187534,7 @@ function createSlackAdapter(config) {
|
|
|
187485
187534
|
await Promise.all(status.getUniqueSources(event.sources).map((source) => status.activate(source, SLACK_ASSISTANT_WORKING_STATUS, activity)));
|
|
187486
187535
|
},
|
|
187487
187536
|
sendMessage,
|
|
187537
|
+
listCustomEmojis,
|
|
187488
187538
|
downloadAttachment,
|
|
187489
187539
|
sendDirectReply,
|
|
187490
187540
|
handleControlRequestEvent,
|
|
@@ -187632,10 +187682,27 @@ async function reactInSlack(context3) {
|
|
|
187632
187682
|
});
|
|
187633
187683
|
return request.remove ? `Reaction removed on slack (message_id: ${result2.messageId})` : `Reaction added on slack (message_id: ${result2.messageId})`;
|
|
187634
187684
|
}
|
|
187685
|
+
async function listSlackCustomEmojis(context3) {
|
|
187686
|
+
const listCustomEmojis = context3.adapter.listCustomEmojis;
|
|
187687
|
+
if (typeof listCustomEmojis !== "function") {
|
|
187688
|
+
return "Error: Running Slack adapter does not support custom emoji discovery.";
|
|
187689
|
+
}
|
|
187690
|
+
try {
|
|
187691
|
+
const names2 = await listCustomEmojis.call(context3.adapter);
|
|
187692
|
+
if (names2.length === 0) {
|
|
187693
|
+
return "This Slack workspace has no custom emoji available to the app.";
|
|
187694
|
+
}
|
|
187695
|
+
return `Available custom Slack emoji (${names2.length}): ${names2.map((name) => `:${name}:`).join(", ")}`;
|
|
187696
|
+
} catch (error4) {
|
|
187697
|
+
const message = error4 instanceof Error ? error4.message : String(error4);
|
|
187698
|
+
return `Error: Could not list custom Slack emoji. ${message}`;
|
|
187699
|
+
}
|
|
187700
|
+
}
|
|
187635
187701
|
function createSlackMessageActionAdapter(options = {}) {
|
|
187636
187702
|
const actions = [
|
|
187637
187703
|
"send",
|
|
187638
187704
|
...options.react ? ["react"] : [],
|
|
187705
|
+
...options.listCustomEmojis ? ["list-custom-emojis"] : [],
|
|
187639
187706
|
...options.uploadFile ? ["upload-file"] : [],
|
|
187640
187707
|
...options.downloadFile ? ["download-file"] : []
|
|
187641
187708
|
];
|
|
@@ -187674,6 +187741,8 @@ function createSlackMessageActionAdapter(options = {}) {
|
|
|
187674
187741
|
return await sendSlackMessage(context3);
|
|
187675
187742
|
case "react":
|
|
187676
187743
|
return options.react ? await reactInSlack(context3) : 'Error: Action "react" is not supported on slack.';
|
|
187744
|
+
case "list-custom-emojis":
|
|
187745
|
+
return options.listCustomEmojis ? await listSlackCustomEmojis(context3) : 'Error: Action "list-custom-emojis" is not supported on slack.';
|
|
187677
187746
|
case "download-file":
|
|
187678
187747
|
return options.downloadFile ? await options.downloadFile(context3) : 'Error: Action "download-file" is not supported on slack.';
|
|
187679
187748
|
default:
|
|
@@ -188064,6 +188133,7 @@ var init_message_actions2 = __esm(() => {
|
|
|
188064
188133
|
init_target_resolution();
|
|
188065
188134
|
slackMessageActions = createSlackMessageActionAdapter({
|
|
188066
188135
|
react: true,
|
|
188136
|
+
listCustomEmojis: true,
|
|
188067
188137
|
uploadFile: true,
|
|
188068
188138
|
downloadFile: downloadSlackFile,
|
|
188069
188139
|
resolveMessageTarget: async (params) => await resolveSlackMessageTarget({
|
|
@@ -188101,7 +188171,7 @@ async function runSlackSetup() {
|
|
|
188101
188171
|
console.log(` 5. Add the /cancel slash command if you want Slack-native cancellation
|
|
188102
188172
|
`);
|
|
188103
188173
|
console.log("Recommended bot token scopes:");
|
|
188104
|
-
console.log(" app_mentions:read, channels:history, chat:write, commands, groups:history, im:history, users:read");
|
|
188174
|
+
console.log(" app_mentions:read, channels:history, chat:write, commands, emoji:read, groups:history, im:history, users:read");
|
|
188105
188175
|
console.log(` reactions:read, reactions:write, files:read, files:write
|
|
188106
188176
|
`);
|
|
188107
188177
|
await ensureSlackRuntimeInstalled();
|
|
@@ -190872,7 +190942,7 @@ var init_state = __esm(() => {
|
|
|
190872
190942
|
});
|
|
190873
190943
|
|
|
190874
190944
|
// src/channels/whatsapp/session.ts
|
|
190875
|
-
import { mkdirSync as mkdirSync24, readFileSync as readFileSync25, rmSync as
|
|
190945
|
+
import { mkdirSync as mkdirSync24, readFileSync as readFileSync25, rmSync as rmSync10, writeFileSync as writeFileSync18 } from "node:fs";
|
|
190876
190946
|
import { homedir as homedir26 } from "node:os";
|
|
190877
190947
|
import { join as join48 } from "node:path";
|
|
190878
190948
|
function shouldDropLine(line) {
|
|
@@ -190984,7 +191054,7 @@ function acquireWhatsAppSessionLease(accountId, options = {}) {
|
|
|
190984
191054
|
if (activeSessionLeases.get(accountId) === lockDir) {
|
|
190985
191055
|
activeSessionLeases.delete(accountId);
|
|
190986
191056
|
}
|
|
190987
|
-
|
|
191057
|
+
rmSync10(lockDir, { recursive: true, force: true });
|
|
190988
191058
|
}
|
|
190989
191059
|
};
|
|
190990
191060
|
} catch (error4) {
|
|
@@ -190993,7 +191063,7 @@ function acquireWhatsAppSessionLease(accountId, options = {}) {
|
|
|
190993
191063
|
}
|
|
190994
191064
|
const owner = readLeaseOwner(lockDir);
|
|
190995
191065
|
if (owner.pid && !isProcessAlive(owner.pid)) {
|
|
190996
|
-
|
|
191066
|
+
rmSync10(lockDir, { recursive: true, force: true });
|
|
190997
191067
|
continue;
|
|
190998
191068
|
}
|
|
190999
191069
|
const ownerLabel = owner.pid ? `PID ${owner.pid}${owner.command ? ` (${owner.command})` : ""}` : "an unknown live process";
|
|
@@ -199871,26 +199941,26 @@ function defineLazyProperty(object3, propertyName, valueGetter) {
|
|
|
199871
199941
|
}
|
|
199872
199942
|
|
|
199873
199943
|
// node_modules/default-browser-id/index.js
|
|
199874
|
-
import { promisify as
|
|
199944
|
+
import { promisify as promisify9 } from "node:util";
|
|
199875
199945
|
import process15 from "node:process";
|
|
199876
|
-
import { execFile as
|
|
199946
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
199877
199947
|
async function defaultBrowserId() {
|
|
199878
199948
|
if (process15.platform !== "darwin") {
|
|
199879
199949
|
throw new Error("macOS only");
|
|
199880
199950
|
}
|
|
199881
|
-
const { stdout } = await
|
|
199951
|
+
const { stdout } = await execFileAsync6("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
|
|
199882
199952
|
const match3 = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
199883
199953
|
return match3?.groups.id ?? "com.apple.Safari";
|
|
199884
199954
|
}
|
|
199885
|
-
var
|
|
199955
|
+
var execFileAsync6;
|
|
199886
199956
|
var init_default_browser_id = __esm(() => {
|
|
199887
|
-
|
|
199957
|
+
execFileAsync6 = promisify9(execFile9);
|
|
199888
199958
|
});
|
|
199889
199959
|
|
|
199890
199960
|
// node_modules/run-applescript/index.js
|
|
199891
199961
|
import process16 from "node:process";
|
|
199892
|
-
import { promisify as
|
|
199893
|
-
import { execFile as
|
|
199962
|
+
import { promisify as promisify10 } from "node:util";
|
|
199963
|
+
import { execFile as execFile10, execFileSync as execFileSync6 } from "node:child_process";
|
|
199894
199964
|
async function runAppleScript(script4, { humanReadableOutput = true, signal } = {}) {
|
|
199895
199965
|
if (process16.platform !== "darwin") {
|
|
199896
199966
|
throw new Error("macOS only");
|
|
@@ -199900,12 +199970,12 @@ async function runAppleScript(script4, { humanReadableOutput = true, signal } =
|
|
|
199900
199970
|
if (signal) {
|
|
199901
199971
|
execOptions.signal = signal;
|
|
199902
199972
|
}
|
|
199903
|
-
const { stdout } = await
|
|
199973
|
+
const { stdout } = await execFileAsync7("osascript", ["-e", script4, outputArguments], execOptions);
|
|
199904
199974
|
return stdout.trim();
|
|
199905
199975
|
}
|
|
199906
|
-
var
|
|
199976
|
+
var execFileAsync7;
|
|
199907
199977
|
var init_run_applescript = __esm(() => {
|
|
199908
|
-
|
|
199978
|
+
execFileAsync7 = promisify10(execFile10);
|
|
199909
199979
|
});
|
|
199910
199980
|
|
|
199911
199981
|
// node_modules/bundle-name/index.js
|
|
@@ -199918,9 +199988,9 @@ var init_bundle_name = __esm(() => {
|
|
|
199918
199988
|
});
|
|
199919
199989
|
|
|
199920
199990
|
// node_modules/default-browser/windows.js
|
|
199921
|
-
import { promisify as
|
|
199922
|
-
import { execFile as
|
|
199923
|
-
async function defaultBrowser(_execFileAsync =
|
|
199991
|
+
import { promisify as promisify11 } from "node:util";
|
|
199992
|
+
import { execFile as execFile11 } from "node:child_process";
|
|
199993
|
+
async function defaultBrowser(_execFileAsync = execFileAsync8) {
|
|
199924
199994
|
const { stdout } = await _execFileAsync("reg", [
|
|
199925
199995
|
"QUERY",
|
|
199926
199996
|
" HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
|
|
@@ -199938,9 +200008,9 @@ async function defaultBrowser(_execFileAsync = execFileAsync7) {
|
|
|
199938
200008
|
}
|
|
199939
200009
|
return browser;
|
|
199940
200010
|
}
|
|
199941
|
-
var
|
|
200011
|
+
var execFileAsync8, windowsBrowserProgIds, UnknownBrowserError;
|
|
199942
200012
|
var init_windows = __esm(() => {
|
|
199943
|
-
|
|
200013
|
+
execFileAsync8 = promisify11(execFile11);
|
|
199944
200014
|
windowsBrowserProgIds = {
|
|
199945
200015
|
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
199946
200016
|
MSEdgeDHTML: { name: "Edge", id: "com.microsoft.edge" },
|
|
@@ -199957,9 +200027,9 @@ var init_windows = __esm(() => {
|
|
|
199957
200027
|
});
|
|
199958
200028
|
|
|
199959
200029
|
// node_modules/default-browser/index.js
|
|
199960
|
-
import { promisify as
|
|
200030
|
+
import { promisify as promisify12 } from "node:util";
|
|
199961
200031
|
import process17 from "node:process";
|
|
199962
|
-
import { execFile as
|
|
200032
|
+
import { execFile as execFile12 } from "node:child_process";
|
|
199963
200033
|
async function defaultBrowser2() {
|
|
199964
200034
|
if (process17.platform === "darwin") {
|
|
199965
200035
|
const id2 = await defaultBrowserId();
|
|
@@ -199967,7 +200037,7 @@ async function defaultBrowser2() {
|
|
|
199967
200037
|
return { name, id: id2 };
|
|
199968
200038
|
}
|
|
199969
200039
|
if (process17.platform === "linux") {
|
|
199970
|
-
const { stdout } = await
|
|
200040
|
+
const { stdout } = await execFileAsync9("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
|
|
199971
200041
|
const id2 = stdout.trim();
|
|
199972
200042
|
const name = titleize(id2.replace(/.desktop$/, "").replace("-", " "));
|
|
199973
200043
|
return { name, id: id2 };
|
|
@@ -199977,12 +200047,12 @@ async function defaultBrowser2() {
|
|
|
199977
200047
|
}
|
|
199978
200048
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
199979
200049
|
}
|
|
199980
|
-
var
|
|
200050
|
+
var execFileAsync9, titleize = (string3) => string3.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x4) => x4.toUpperCase());
|
|
199981
200051
|
var init_default_browser = __esm(() => {
|
|
199982
200052
|
init_default_browser_id();
|
|
199983
200053
|
init_bundle_name();
|
|
199984
200054
|
init_windows();
|
|
199985
|
-
|
|
200055
|
+
execFileAsync9 = promisify12(execFile12);
|
|
199986
200056
|
});
|
|
199987
200057
|
|
|
199988
200058
|
// node_modules/open/index.js
|
|
@@ -199996,14 +200066,14 @@ import process18 from "node:process";
|
|
|
199996
200066
|
import { Buffer as Buffer6 } from "node:buffer";
|
|
199997
200067
|
import path31 from "node:path";
|
|
199998
200068
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
199999
|
-
import { promisify as
|
|
200069
|
+
import { promisify as promisify13 } from "node:util";
|
|
200000
200070
|
import childProcess from "node:child_process";
|
|
200001
200071
|
import fs13, { constants as fsConstants2 } from "node:fs/promises";
|
|
200002
200072
|
async function getWindowsDefaultBrowserFromWsl() {
|
|
200003
200073
|
const powershellPath = await powerShellPath();
|
|
200004
200074
|
const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
200005
200075
|
const encodedCommand = Buffer6.from(rawCommand, "utf16le").toString("base64");
|
|
200006
|
-
const { stdout } = await
|
|
200076
|
+
const { stdout } = await execFile13(powershellPath, [
|
|
200007
200077
|
"-NoProfile",
|
|
200008
200078
|
"-NonInteractive",
|
|
200009
200079
|
"-ExecutionPolicy",
|
|
@@ -200039,7 +200109,7 @@ function detectPlatformBinary({ [platform6]: platformBinary }, { wsl }) {
|
|
|
200039
200109
|
}
|
|
200040
200110
|
return detectArchBinary(platformBinary);
|
|
200041
200111
|
}
|
|
200042
|
-
var
|
|
200112
|
+
var execFile13, __dirname2, localXdgOpenPath, platform6, arch3, pTryEach = async (array2, mapper) => {
|
|
200043
200113
|
let latestError;
|
|
200044
200114
|
for (const item of array2) {
|
|
200045
200115
|
try {
|
|
@@ -200218,7 +200288,7 @@ var init_open = __esm(() => {
|
|
|
200218
200288
|
init_wsl_utils();
|
|
200219
200289
|
init_default_browser();
|
|
200220
200290
|
init_is_inside_container();
|
|
200221
|
-
|
|
200291
|
+
execFile13 = promisify13(childProcess.execFile);
|
|
200222
200292
|
__dirname2 = path31.dirname(fileURLToPath8(import.meta.url));
|
|
200223
200293
|
localXdgOpenPath = path31.join(__dirname2, "xdg-open");
|
|
200224
200294
|
({ platform: platform6, arch: arch3 } = process18);
|
|
@@ -207663,7 +207733,7 @@ import {
|
|
|
207663
207733
|
mkdirSync as mkdirSync28,
|
|
207664
207734
|
readFileSync as readFileSync30,
|
|
207665
207735
|
renameSync as renameSync6,
|
|
207666
|
-
rmSync as
|
|
207736
|
+
rmSync as rmSync11,
|
|
207667
207737
|
statSync as statSync14,
|
|
207668
207738
|
writeFileSync as writeFileSync21
|
|
207669
207739
|
} from "node:fs";
|
|
@@ -207809,7 +207879,7 @@ function isLockStale(lockDir) {
|
|
|
207809
207879
|
}
|
|
207810
207880
|
function stealLock(lockDir) {
|
|
207811
207881
|
try {
|
|
207812
|
-
|
|
207882
|
+
rmSync11(lockDir, { recursive: true, force: true });
|
|
207813
207883
|
} catch {}
|
|
207814
207884
|
}
|
|
207815
207885
|
function acquireLock() {
|
|
@@ -207831,7 +207901,7 @@ function acquireLock() {
|
|
|
207831
207901
|
try {
|
|
207832
207902
|
const current = readLockOwner(lockDir);
|
|
207833
207903
|
if (current && current.token === token2) {
|
|
207834
|
-
|
|
207904
|
+
rmSync11(lockDir, { recursive: true, force: true });
|
|
207835
207905
|
}
|
|
207836
207906
|
} catch {}
|
|
207837
207907
|
}
|
|
@@ -208336,11 +208406,12 @@ function safeAppendCronRunLogForTask(task2, entry) {
|
|
|
208336
208406
|
try {
|
|
208337
208407
|
appendCronRunLogForTask(task2, entry);
|
|
208338
208408
|
} catch (err) {
|
|
208339
|
-
|
|
208409
|
+
debugWarn("Cron", `Error writing run log for task ${task2.id}:`, err instanceof Error ? err.message : err);
|
|
208340
208410
|
}
|
|
208341
208411
|
}
|
|
208342
208412
|
var DEFAULT_CRON_RUN_LOG_MAX_BYTES = 2000000, DEFAULT_CRON_RUN_LOG_KEEP_LINES = 2000;
|
|
208343
208413
|
var init_run_log = __esm(() => {
|
|
208414
|
+
init_debug();
|
|
208344
208415
|
init_cron_file();
|
|
208345
208416
|
});
|
|
208346
208417
|
|
|
@@ -208877,7 +208948,7 @@ function scheduleQueuePump(runtime, socket, opts, processQueuedTurn) {
|
|
|
208877
208948
|
error: error4,
|
|
208878
208949
|
context: "listener_queue_pump"
|
|
208879
208950
|
});
|
|
208880
|
-
|
|
208951
|
+
debugWarn("Listen", "Error in queue pump:", error4);
|
|
208881
208952
|
emitListenerStatus(runtime.listener, opts.onStatusChange, opts.connectionId);
|
|
208882
208953
|
evictConversationRuntimeIfIdle(runtime);
|
|
208883
208954
|
});
|
|
@@ -208885,6 +208956,7 @@ function scheduleQueuePump(runtime, socket, opts, processQueuedTurn) {
|
|
|
208885
208956
|
var init_queue = __esm(async () => {
|
|
208886
208957
|
init_queue_runtime();
|
|
208887
208958
|
init_error_reporting();
|
|
208959
|
+
init_debug();
|
|
208888
208960
|
init_protocol_outbound();
|
|
208889
208961
|
init_runtime();
|
|
208890
208962
|
init_transport();
|
|
@@ -209139,6 +209211,13 @@ function formatCronPrompt(task2, timing2) {
|
|
|
209139
209211
|
var init_prompt = () => {};
|
|
209140
209212
|
|
|
209141
209213
|
// src/cron/scheduler.ts
|
|
209214
|
+
function logScheduler(opts, message) {
|
|
209215
|
+
if (opts.onLog) {
|
|
209216
|
+
opts.onLog(`[Cron] ${message}`);
|
|
209217
|
+
return;
|
|
209218
|
+
}
|
|
209219
|
+
debugWarn("Cron", message);
|
|
209220
|
+
}
|
|
209142
209221
|
function minuteKey(date) {
|
|
209143
209222
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}T${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
209144
209223
|
}
|
|
@@ -209403,7 +209482,7 @@ async function runCronTaskNow(taskId) {
|
|
|
209403
209482
|
}
|
|
209404
209483
|
function tick2(state, socket, opts, processQueuedTurn) {
|
|
209405
209484
|
if (!verifySchedulerLease(state.token)) {
|
|
209406
|
-
|
|
209485
|
+
logScheduler(opts, "Scheduler lease lost. Stopping.");
|
|
209407
209486
|
stopScheduler();
|
|
209408
209487
|
return;
|
|
209409
209488
|
}
|
|
@@ -209440,7 +209519,7 @@ function tick2(state, socket, opts, processQueuedTurn) {
|
|
|
209440
209519
|
return;
|
|
209441
209520
|
const schedulerNow = new Date;
|
|
209442
209521
|
fireCronTask(freshTask, { intendedOccurrence, schedulerNow }, socket, opts, processQueuedTurn, "automatic").catch((err) => {
|
|
209443
|
-
|
|
209522
|
+
logScheduler(opts, `Error firing task ${taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
209444
209523
|
setLastRunOutcome(freshTask.id, {
|
|
209445
209524
|
outcome: "failed",
|
|
209446
209525
|
reason: "scheduler_error",
|
|
@@ -209478,12 +209557,12 @@ function startScheduler(socket, opts, processQueuedTurn, _retryCount = 0) {
|
|
|
209478
209557
|
token2 = claimSchedulerLease();
|
|
209479
209558
|
} catch (err) {
|
|
209480
209559
|
if (_retryCount < MAX_LEASE_RETRIES) {
|
|
209481
|
-
|
|
209482
|
-
|
|
209560
|
+
logScheduler(opts, `Could not claim scheduler lease (attempt ${_retryCount + 1}/${MAX_LEASE_RETRIES + 1}): ${err instanceof Error ? err.message : err}`);
|
|
209561
|
+
logScheduler(opts, "Cron tasks will not fire until the scheduler starts. Retrying...");
|
|
209483
209562
|
setTimeout(() => startScheduler(socket, opts, processQueuedTurn, _retryCount + 1), LEASE_RETRY_MS);
|
|
209484
209563
|
} else {
|
|
209485
|
-
|
|
209486
|
-
|
|
209564
|
+
logScheduler(opts, `Failed to claim scheduler lease after ${MAX_LEASE_RETRIES + 1} attempts. Cron tasks will not fire.`);
|
|
209565
|
+
logScheduler(opts, "Another process may hold the lease. Restart Letta Code to retry.");
|
|
209487
209566
|
}
|
|
209488
209567
|
return;
|
|
209489
209568
|
}
|
|
@@ -209512,7 +209591,7 @@ function startScheduler(socket, opts, processQueuedTurn, _retryCount = 0) {
|
|
|
209512
209591
|
state.lastMtime = 0;
|
|
209513
209592
|
}
|
|
209514
209593
|
} catch (err) {
|
|
209515
|
-
|
|
209594
|
+
logScheduler(opts, `GC error: ${err instanceof Error ? err.message : String(err)}`);
|
|
209516
209595
|
}
|
|
209517
209596
|
}, GC_INTERVAL_MS);
|
|
209518
209597
|
schedulerState = state;
|
|
@@ -209535,6 +209614,7 @@ function stopScheduler() {
|
|
|
209535
209614
|
var schedulerState = null, listenerFireContext = null, TICK_INTERVAL_MS = 60000, GC_INTERVAL_MS, LEASE_RETRY_MS = 30000, MAX_LEASE_RETRIES = 3, NEW_CONVERSATION_TARGET = "new";
|
|
209536
209615
|
var init_scheduler = __esm(async () => {
|
|
209537
209616
|
init_backend2();
|
|
209617
|
+
init_debug();
|
|
209538
209618
|
init_connection();
|
|
209539
209619
|
init_protocol_outbound();
|
|
209540
209620
|
init_runtime();
|
|
@@ -215283,7 +215363,7 @@ async function awaitMemoryPushBounded(commandName, agentId, memoryRoot) {
|
|
|
215283
215363
|
});
|
|
215284
215364
|
const warnOnFailure = (result2) => {
|
|
215285
215365
|
if (result2.status === "push_failed" || result2.status === "conflict") {
|
|
215286
|
-
|
|
215366
|
+
warnMemoryCommand(`[${commandName}] push failed for ${agentId}: ${result2.summary}`);
|
|
215287
215367
|
}
|
|
215288
215368
|
};
|
|
215289
215369
|
let timer;
|
|
@@ -215293,15 +215373,15 @@ async function awaitMemoryPushBounded(commandName, agentId, memoryRoot) {
|
|
|
215293
215373
|
try {
|
|
215294
215374
|
const result2 = await Promise.race([syncPromise, capPromise]);
|
|
215295
215375
|
if (result2 === "timed_out") {
|
|
215296
|
-
|
|
215376
|
+
warnMemoryCommand(`[${commandName}] push still in flight after ${MEMORY_PUSH_AWAIT_CAP_MS}ms for ${agentId}; responding now, push continues in background`);
|
|
215297
215377
|
syncPromise.then(warnOnFailure).catch((err) => {
|
|
215298
|
-
|
|
215378
|
+
warnMemoryCommand(`[${commandName}] background push failed for ${agentId}:`, err instanceof Error ? err.message : err);
|
|
215299
215379
|
});
|
|
215300
215380
|
return;
|
|
215301
215381
|
}
|
|
215302
215382
|
warnOnFailure(result2);
|
|
215303
215383
|
} catch (err) {
|
|
215304
|
-
|
|
215384
|
+
warnMemoryCommand(`[${commandName}] push failed for ${agentId}:`, err instanceof Error ? err.message : err);
|
|
215305
215385
|
} finally {
|
|
215306
215386
|
if (timer)
|
|
215307
215387
|
clearTimeout(timer);
|
|
@@ -215526,15 +215606,15 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215526
215606
|
runDetachedListenerTask("memory_history", async () => {
|
|
215527
215607
|
const { getScopedMemoryFilesystemRoot: getScopedMemoryFilesystemRoot2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
215528
215608
|
const { execFile: execFileCb4 } = await import("node:child_process");
|
|
215529
|
-
const { promisify:
|
|
215530
|
-
const
|
|
215609
|
+
const { promisify: promisify14 } = await import("node:util");
|
|
215610
|
+
const execFileAsync10 = promisify14(execFileCb4);
|
|
215531
215611
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
215532
215612
|
const limit3 = parsed.limit ?? 50;
|
|
215533
215613
|
const gitArgs = ["log", `--max-count=${limit3}`, "--format=%H|%s|%aI|%an"];
|
|
215534
215614
|
if (parsed.file_path) {
|
|
215535
215615
|
gitArgs.push("--", parsed.file_path);
|
|
215536
215616
|
}
|
|
215537
|
-
const { stdout } = await
|
|
215617
|
+
const { stdout } = await execFileAsync10("git", gitArgs, {
|
|
215538
215618
|
cwd: memoryRoot,
|
|
215539
215619
|
timeout: 1e4
|
|
215540
215620
|
});
|
|
@@ -215562,11 +215642,11 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215562
215642
|
runDetachedListenerTask("memory_file_at_ref", async () => {
|
|
215563
215643
|
const { getScopedMemoryFilesystemRoot: getScopedMemoryFilesystemRoot2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
215564
215644
|
const { execFile: execFileCb4 } = await import("node:child_process");
|
|
215565
|
-
const { promisify:
|
|
215566
|
-
const
|
|
215645
|
+
const { promisify: promisify14 } = await import("node:util");
|
|
215646
|
+
const execFileAsync10 = promisify14(execFileCb4);
|
|
215567
215647
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
215568
215648
|
try {
|
|
215569
|
-
const { stdout } = await
|
|
215649
|
+
const { stdout } = await execFileAsync10("git", ["show", `${parsed.ref}:${parsed.file_path}`], { cwd: memoryRoot, timeout: 1e4 });
|
|
215570
215650
|
safeSocketSend(socket, {
|
|
215571
215651
|
type: "memory_file_at_ref_response",
|
|
215572
215652
|
request_id: parsed.request_id,
|
|
@@ -215593,11 +215673,11 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215593
215673
|
runDetachedListenerTask("memory_commit_diff", async () => {
|
|
215594
215674
|
const { getScopedMemoryFilesystemRoot: getScopedMemoryFilesystemRoot2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
215595
215675
|
const { execFile: execFileCb4 } = await import("node:child_process");
|
|
215596
|
-
const { promisify:
|
|
215597
|
-
const
|
|
215676
|
+
const { promisify: promisify14 } = await import("node:util");
|
|
215677
|
+
const execFileAsync10 = promisify14(execFileCb4);
|
|
215598
215678
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
215599
215679
|
try {
|
|
215600
|
-
const { stdout } = await
|
|
215680
|
+
const { stdout } = await execFileAsync10("git", ["show", parsed.sha, "--format=", "--no-color"], { cwd: memoryRoot, timeout: 1e4 });
|
|
215601
215681
|
safeSocketSend(socket, {
|
|
215602
215682
|
type: "memory_commit_diff_response",
|
|
215603
215683
|
request_id: parsed.request_id,
|
|
@@ -215679,7 +215759,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215679
215759
|
}, "listener_read_memory_file_send_failed", "listener_read_memory_file");
|
|
215680
215760
|
} catch (err) {
|
|
215681
215761
|
trackListenerError("listener_read_memory_file_failed", err, "listener_memory_read");
|
|
215682
|
-
|
|
215762
|
+
warnMemoryCommand(`[Listen] read_memory_file error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
215683
215763
|
sendFailure(err instanceof Error ? err.message : "Failed to read memory file");
|
|
215684
215764
|
}
|
|
215685
215765
|
});
|
|
@@ -215778,7 +215858,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215778
215858
|
}, "listener_write_memory_file_send_failed", "listener_write_memory_file");
|
|
215779
215859
|
} catch (err) {
|
|
215780
215860
|
trackListenerError("listener_write_memory_file_failed", err, "listener_memory_write");
|
|
215781
|
-
|
|
215861
|
+
warnMemoryCommand(`[Listen] write_memory_file error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
215782
215862
|
sendFailure(err instanceof Error ? err.message : "Failed to write memory file");
|
|
215783
215863
|
}
|
|
215784
215864
|
});
|
|
@@ -215891,7 +215971,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215891
215971
|
}, "listener_delete_memory_file_send_failed", "listener_delete_memory_file");
|
|
215892
215972
|
} catch (err) {
|
|
215893
215973
|
trackListenerError("listener_delete_memory_file_failed", err, "listener_memory_delete");
|
|
215894
|
-
|
|
215974
|
+
warnMemoryCommand(`[Listen] delete_memory_file error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
215895
215975
|
sendFailure(err instanceof Error ? err.message : "Failed to delete memory file");
|
|
215896
215976
|
}
|
|
215897
215977
|
});
|
|
@@ -215899,10 +215979,12 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
215899
215979
|
}
|
|
215900
215980
|
return false;
|
|
215901
215981
|
}
|
|
215902
|
-
var WIKI_LINK_REGEX, IMAGE_MIME_BY_EXTENSION, MEMORY_PUSH_AWAIT_CAP_MS = 8000;
|
|
215982
|
+
var warnMemoryCommand, WIKI_LINK_REGEX, IMAGE_MIME_BY_EXTENSION, MEMORY_PUSH_AWAIT_CAP_MS = 8000;
|
|
215903
215983
|
var init_memory6 = __esm(() => {
|
|
215904
215984
|
init_error_reporting();
|
|
215985
|
+
init_debug();
|
|
215905
215986
|
init_protocol_inbound();
|
|
215987
|
+
warnMemoryCommand = debugWarn.bind(null, "memory-commands");
|
|
215906
215988
|
WIKI_LINK_REGEX = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
|
|
215907
215989
|
IMAGE_MIME_BY_EXTENSION = {
|
|
215908
215990
|
".gif": "image/gif",
|
|
@@ -300571,7 +300653,7 @@ ${lanes.join(`
|
|
|
300571
300653
|
if (!links2.hasReportedStatementInAmbientContext) {
|
|
300572
300654
|
return links2.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
|
|
300573
300655
|
}
|
|
300574
|
-
}
|
|
300656
|
+
}
|
|
300575
300657
|
}
|
|
300576
300658
|
return false;
|
|
300577
300659
|
}
|
|
@@ -310035,7 +310117,7 @@ ${lanes.join(`
|
|
|
310035
310117
|
], 2));
|
|
310036
310118
|
setParentRecursive(requireStatement, false);
|
|
310037
310119
|
statements = insertStatementAfterCustomPrologue(statements.slice(), requireStatement);
|
|
310038
|
-
}
|
|
310120
|
+
}
|
|
310039
310121
|
}
|
|
310040
310122
|
}
|
|
310041
310123
|
if (statements !== visited2.statements) {
|
|
@@ -385584,7 +385666,7 @@ import {
|
|
|
385584
385666
|
existsSync as existsSync47,
|
|
385585
385667
|
mkdirSync as mkdirSync33,
|
|
385586
385668
|
readFileSync as readFileSync35,
|
|
385587
|
-
rmSync as
|
|
385669
|
+
rmSync as rmSync12,
|
|
385588
385670
|
writeFileSync as writeFileSync25
|
|
385589
385671
|
} from "node:fs";
|
|
385590
385672
|
import path37 from "node:path";
|
|
@@ -386187,7 +386269,7 @@ function removeManagedModPackage(params) {
|
|
|
386187
386269
|
assertSafePackageRemovalRoot(match3.metadata);
|
|
386188
386270
|
registry.packagesValue.splice(match3.index, 1);
|
|
386189
386271
|
writePackageRegistry(registry.registryPath, registry.registry);
|
|
386190
|
-
|
|
386272
|
+
rmSync12(match3.metadata.packageRoot, { force: true, recursive: true });
|
|
386191
386273
|
return {
|
|
386192
386274
|
package: mutationItem(match3.metadata, match3.index, match3.metadata.enabled),
|
|
386193
386275
|
registryPath: registry.registryPath,
|
|
@@ -387701,7 +387783,7 @@ async function syncMemfsForAgent(agentId) {
|
|
|
387701
387783
|
debugLog("memfs-sync", `Agent ${agentId} does not have memfs tag (self-hosted), skipping`);
|
|
387702
387784
|
return;
|
|
387703
387785
|
}
|
|
387704
|
-
|
|
387786
|
+
debugWarn("memfs-sync", `Agent ${agentId} is missing the memfs tag on Letta Cloud — repairing (auto-enabling memfs).`);
|
|
387705
387787
|
await applyMemfsFlags2(agentId, true, {
|
|
387706
387788
|
pullOnExistingRepo: true,
|
|
387707
387789
|
agentTags: agent.tags ?? []
|
|
@@ -390486,7 +390568,7 @@ function markAsFinished(b3, id2) {
|
|
|
390486
390568
|
if (updatedLine.kind === "assistant" && "text" in updatedLine && updatedLine.text) {
|
|
390487
390569
|
b3.lastAssistantMessage = updatedLine.text;
|
|
390488
390570
|
}
|
|
390489
|
-
}
|
|
390571
|
+
}
|
|
390490
390572
|
}
|
|
390491
390573
|
function handleOtidTransition(b3, newOtid) {
|
|
390492
390574
|
if (b3.lastOtid && b3.lastOtid !== newOtid) {
|
|
@@ -390504,7 +390586,7 @@ function markCurrentLineAsFinished(b3) {
|
|
|
390504
390586
|
const prev = b3.byId.get(b3.lastOtid);
|
|
390505
390587
|
if (prev && (prev.kind === "assistant" || prev.kind === "reasoning")) {
|
|
390506
390588
|
markAsFinished(b3, b3.lastOtid);
|
|
390507
|
-
}
|
|
390589
|
+
}
|
|
390508
390590
|
}
|
|
390509
390591
|
function markIncompleteToolsAsCancelled(b3, setInterruptedFlag = true, reason = "internal_cancel", skipMarkCurrentLine = false) {
|
|
390510
390592
|
if (setInterruptedFlag) {
|
|
@@ -397886,12 +397968,12 @@ function rowToolCalls(row, index, diagnostics2) {
|
|
|
397886
397968
|
}
|
|
397887
397969
|
return calls;
|
|
397888
397970
|
}
|
|
397889
|
-
function
|
|
397971
|
+
function contentText(content) {
|
|
397890
397972
|
if (typeof content === "string") {
|
|
397891
397973
|
if (content.startsWith(CONTENT_JSON_PREFIX)) {
|
|
397892
397974
|
const encoded = content.slice(CONTENT_JSON_PREFIX.length);
|
|
397893
397975
|
try {
|
|
397894
|
-
return
|
|
397976
|
+
return contentText(JSON.parse(encoded));
|
|
397895
397977
|
} catch {
|
|
397896
397978
|
return encoded;
|
|
397897
397979
|
}
|
|
@@ -397977,7 +398059,7 @@ var init_hermes = __esm(() => {
|
|
|
397977
398059
|
});
|
|
397978
398060
|
};
|
|
397979
398061
|
if (row.role === "user") {
|
|
397980
|
-
const content =
|
|
398062
|
+
const content = contentText(row.content);
|
|
397981
398063
|
if (content) {
|
|
397982
398064
|
emit({
|
|
397983
398065
|
type: "message",
|
|
@@ -397997,7 +398079,7 @@ var init_hermes = __esm(() => {
|
|
|
397997
398079
|
...timestamp ? { timestamp } : {}
|
|
397998
398080
|
});
|
|
397999
398081
|
}
|
|
398000
|
-
const content =
|
|
398082
|
+
const content = contentText(row.content);
|
|
398001
398083
|
if (content) {
|
|
398002
398084
|
emit({
|
|
398003
398085
|
type: "message",
|
|
@@ -398020,7 +398102,7 @@ var init_hermes = __esm(() => {
|
|
|
398020
398102
|
if (row.role === "tool") {
|
|
398021
398103
|
emit({
|
|
398022
398104
|
type: "tool_result",
|
|
398023
|
-
content:
|
|
398105
|
+
content: contentText(row.content),
|
|
398024
398106
|
...typeof row.tool_call_id === "string" && row.tool_call_id ? { callId: row.tool_call_id } : {},
|
|
398025
398107
|
...timestamp ? { timestamp } : {}
|
|
398026
398108
|
});
|
|
@@ -401381,11 +401463,11 @@ import { randomUUID as randomUUID27 } from "node:crypto";
|
|
|
401381
401463
|
import { existsSync as existsSync53 } from "node:fs";
|
|
401382
401464
|
import { mkdir as mkdir13 } from "node:fs/promises";
|
|
401383
401465
|
import { dirname as dirname28, isAbsolute as isAbsolute26, join as join68, resolve as resolve34 } from "node:path";
|
|
401384
|
-
import { promisify as
|
|
401466
|
+
import { promisify as promisify14 } from "node:util";
|
|
401385
401467
|
async function runGit4(cwd2, args) {
|
|
401386
401468
|
try {
|
|
401387
401469
|
const allArgs = [...GIT_DISABLE_COMMIT_SIGNING_ARGS, ...args];
|
|
401388
|
-
const { stdout, stderr } = await
|
|
401470
|
+
const { stdout, stderr } = await execFile14("git", allArgs, {
|
|
401389
401471
|
cwd: cwd2,
|
|
401390
401472
|
env: {
|
|
401391
401473
|
...process.env,
|
|
@@ -401749,11 +401831,11 @@ async function finalizeReflectionMemoryWorktreeImpl(worktree, options) {
|
|
|
401749
401831
|
async function finalizeReflectionMemoryWorktree(worktree, options) {
|
|
401750
401832
|
return await finalizeReflectionMemoryWorktreeImpl(worktree, options);
|
|
401751
401833
|
}
|
|
401752
|
-
var
|
|
401834
|
+
var execFile14, GIT_TIMEOUT_MS = 30000, HARNESS_GIT_ENV;
|
|
401753
401835
|
var init_memory_worktree = __esm(() => {
|
|
401754
401836
|
init_memory_git_signing();
|
|
401755
401837
|
init_debug();
|
|
401756
|
-
|
|
401838
|
+
execFile14 = promisify14(execFileCb4);
|
|
401757
401839
|
HARNESS_GIT_ENV = {
|
|
401758
401840
|
GIT_AUTHOR_NAME: "Letta Code",
|
|
401759
401841
|
GIT_AUTHOR_EMAIL: "noreply@letta.com",
|
|
@@ -402850,7 +402932,7 @@ function notifyTurnStarted(msg) {
|
|
|
402850
402932
|
try {
|
|
402851
402933
|
hooksByOtid.get(otid)?.onStarted?.();
|
|
402852
402934
|
} catch (error4) {
|
|
402853
|
-
|
|
402935
|
+
debugWarn("Listen V2", "Turn observer onStarted failed", error4);
|
|
402854
402936
|
}
|
|
402855
402937
|
}
|
|
402856
402938
|
}
|
|
@@ -402859,12 +402941,13 @@ function notifyTurnFinished(msg) {
|
|
|
402859
402941
|
try {
|
|
402860
402942
|
hooksByOtid.get(otid)?.onFinished();
|
|
402861
402943
|
} catch (error4) {
|
|
402862
|
-
|
|
402944
|
+
debugWarn("Listen V2", "Turn observer onFinished failed", error4);
|
|
402863
402945
|
}
|
|
402864
402946
|
}
|
|
402865
402947
|
}
|
|
402866
402948
|
var hooksByOtid;
|
|
402867
402949
|
var init_turn_observers = __esm(() => {
|
|
402950
|
+
init_debug();
|
|
402868
402951
|
hooksByOtid = new Map;
|
|
402869
402952
|
});
|
|
402870
402953
|
|
|
@@ -405504,7 +405587,7 @@ function handleTerminalSpawn(msg, socket, cwd2, connectionId = "legacy") {
|
|
|
405504
405587
|
alive = false;
|
|
405505
405588
|
}
|
|
405506
405589
|
if (alive) {
|
|
405507
|
-
|
|
405590
|
+
debugLog("Terminal", `Reusing session (age=${Date.now() - existing.spawnedAt}ms), pid=${existing.pid}`);
|
|
405508
405591
|
sendTerminalMessage(socket, {
|
|
405509
405592
|
type: "terminal_spawned",
|
|
405510
405593
|
terminal_id,
|
|
@@ -405516,18 +405599,18 @@ function handleTerminalSpawn(msg, socket, cwd2, connectionId = "legacy") {
|
|
|
405516
405599
|
}
|
|
405517
405600
|
killTerminal(terminal_id, connectionId);
|
|
405518
405601
|
const shell2 = getDefaultShell();
|
|
405519
|
-
|
|
405602
|
+
debugLog("Terminal", `Spawning PTY (${IS_BUN ? "bun" : "node-pty"}): shell=${shell2}, cwd=${cwd2}, cols=${cols}, rows=${rows}`);
|
|
405520
405603
|
try {
|
|
405521
405604
|
const session = IS_BUN ? spawnBun(shell2, cwd2, cols, rows, terminal_id, connectionId, socket) : spawnNodePty(shell2, cwd2, cols, rows, terminal_id, connectionId, socket);
|
|
405522
405605
|
terminals.set(terminalKey, session);
|
|
405523
|
-
|
|
405606
|
+
debugLog("Terminal", `Session stored for terminal_id=${terminal_id}, pid=${session.pid}`);
|
|
405524
405607
|
sendTerminalMessage(socket, {
|
|
405525
405608
|
type: "terminal_spawned",
|
|
405526
405609
|
terminal_id,
|
|
405527
405610
|
pid: session.pid
|
|
405528
405611
|
});
|
|
405529
405612
|
} catch (error4) {
|
|
405530
|
-
|
|
405613
|
+
debugWarn("Terminal", "Failed to spawn PTY:", error4);
|
|
405531
405614
|
sendTerminalMessage(socket, {
|
|
405532
405615
|
type: "terminal_exited",
|
|
405533
405616
|
terminal_id,
|
|
@@ -405545,7 +405628,7 @@ function handleTerminalResize(msg, connectionId = "legacy") {
|
|
|
405545
405628
|
function handleTerminalKill(msg, connectionId = "legacy") {
|
|
405546
405629
|
const session = terminals.get(getTerminalKey(connectionId, msg.terminal_id));
|
|
405547
405630
|
if (session && Date.now() - session.spawnedAt < 2000) {
|
|
405548
|
-
|
|
405631
|
+
debugLog("Terminal", `Ignoring kill for recently spawned session (age=${Date.now() - session.spawnedAt}ms)`);
|
|
405549
405632
|
return;
|
|
405550
405633
|
}
|
|
405551
405634
|
killTerminal(msg.terminal_id, connectionId);
|
|
@@ -405554,7 +405637,7 @@ function killTerminal(terminalId, connectionId) {
|
|
|
405554
405637
|
const terminalKey = getTerminalKey(connectionId, terminalId);
|
|
405555
405638
|
const session = terminals.get(terminalKey);
|
|
405556
405639
|
if (session) {
|
|
405557
|
-
|
|
405640
|
+
debugLog("Terminal", `killTerminal: terminalId=${terminalId}, pid=${session.pid}`);
|
|
405558
405641
|
session.kill();
|
|
405559
405642
|
terminals.delete(terminalKey);
|
|
405560
405643
|
}
|
|
@@ -405573,6 +405656,7 @@ function killAllTerminals() {
|
|
|
405573
405656
|
}
|
|
405574
405657
|
var IS_BUN, FLUSH_INTERVAL_MS = 16, MAX_BUFFER_BYTES, terminals;
|
|
405575
405658
|
var init_terminal_handler = __esm(() => {
|
|
405659
|
+
init_debug();
|
|
405576
405660
|
IS_BUN = typeof Bun !== "undefined";
|
|
405577
405661
|
MAX_BUFFER_BYTES = 64 * 1024;
|
|
405578
405662
|
terminals = new Map;
|
|
@@ -405682,7 +405766,7 @@ var init_connection_lifecycle = __esm(async () => {
|
|
|
405682
405766
|
});
|
|
405683
405767
|
|
|
405684
405768
|
// src/websocket/listener/connection-state-sync.ts
|
|
405685
|
-
function emitInitialConnectionState(runtime, transport, connectionId, options = {}) {
|
|
405769
|
+
async function emitInitialConnectionState(runtime, transport, connectionId, options = {}) {
|
|
405686
405770
|
if (options.emitInitialState === false)
|
|
405687
405771
|
return;
|
|
405688
405772
|
const routing = toListenerConnection(connectionId);
|
|
@@ -405695,17 +405779,19 @@ function emitInitialConnectionState(runtime, transport, connectionId, options =
|
|
|
405695
405779
|
agent_id: conversationRuntime.agentId,
|
|
405696
405780
|
conversation_id: conversationRuntime.conversationId
|
|
405697
405781
|
};
|
|
405782
|
+
await refreshDeviceGitContext(conversationRuntime, scope);
|
|
405698
405783
|
emitDeviceStatusUpdate(transport, conversationRuntime, scope, routing);
|
|
405699
405784
|
emitLoopStatusUpdate(transport, conversationRuntime, scope, routing);
|
|
405700
405785
|
}
|
|
405701
405786
|
}
|
|
405702
|
-
function replaySubscribedConnectionState(listener, transport, runtime, scope,
|
|
405787
|
+
async function replaySubscribedConnectionState(listener, transport, runtime, scope, options = {}) {
|
|
405788
|
+
await (options.refreshGitContext ?? refreshDeviceGitContext)(listener, scope);
|
|
405703
405789
|
const connection = findListenerConnectionByTransport(listener, transport);
|
|
405704
405790
|
if (connection) {
|
|
405705
405791
|
replayPendingApprovalRequestsToConnection(runtime, connection.id);
|
|
405706
405792
|
}
|
|
405707
405793
|
emitStateSync(transport, listener, scope, {
|
|
405708
|
-
forceDeviceStatus,
|
|
405794
|
+
forceDeviceStatus: options.forceDeviceStatus,
|
|
405709
405795
|
...connection ? { routing: toListenerConnection(connection.id) } : {}
|
|
405710
405796
|
});
|
|
405711
405797
|
}
|
|
@@ -405716,7 +405802,7 @@ var init_connection_state_sync = __esm(() => {
|
|
|
405716
405802
|
});
|
|
405717
405803
|
|
|
405718
405804
|
// src/websocket/listener/grep-in-files.ts
|
|
405719
|
-
import { execFile as
|
|
405805
|
+
import { execFile as execFile15 } from "node:child_process";
|
|
405720
405806
|
import { createRequire as createRequire6 } from "node:module";
|
|
405721
405807
|
import * as path43 from "node:path";
|
|
405722
405808
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
@@ -405772,7 +405858,7 @@ async function runGrepInFiles(args) {
|
|
|
405772
405858
|
}
|
|
405773
405859
|
function runRipgrep(rgArgs) {
|
|
405774
405860
|
return new Promise((resolve35, reject2) => {
|
|
405775
|
-
const child =
|
|
405861
|
+
const child = execFile15(rgPath, rgArgs, {
|
|
405776
405862
|
maxBuffer: 50 * 1024 * 1024
|
|
405777
405863
|
}, (error4, stdout, _stderr) => {
|
|
405778
405864
|
if (error4 && error4.code !== 1) {
|
|
@@ -406240,10 +406326,10 @@ function createFileCommandSession(params) {
|
|
|
406240
406326
|
return true;
|
|
406241
406327
|
}
|
|
406242
406328
|
if (isListInDirectoryCommand(parsed)) {
|
|
406243
|
-
|
|
406329
|
+
logFileCommand(`[Listen] Received list_in_directory command: path=${parsed.path}`);
|
|
406244
406330
|
runDetachedListenerTask("list_in_directory", async () => {
|
|
406245
406331
|
try {
|
|
406246
|
-
|
|
406332
|
+
logFileCommand(`[Listen] Reading directory: ${parsed.path}`);
|
|
406247
406333
|
const { folders: allFolders, files: allFiles } = await listDirectoryDirect(parsed.path, parsed.path, !!parsed.include_files);
|
|
406248
406334
|
const total = allFolders.length + allFiles.length;
|
|
406249
406335
|
const offset = parsed.offset ?? 0;
|
|
@@ -406265,11 +406351,11 @@ function createFileCommandSession(params) {
|
|
|
406265
406351
|
if (parsed.include_files) {
|
|
406266
406352
|
response.files = files;
|
|
406267
406353
|
}
|
|
406268
|
-
|
|
406354
|
+
logFileCommand(`[Listen] Sending list_in_directory_response: ${folders.length} folders, ${files?.length ?? 0} files`);
|
|
406269
406355
|
safeSocketSend(socket, response, "listener_list_directory_send_failed", "listener_list_in_directory");
|
|
406270
406356
|
} catch (err) {
|
|
406271
406357
|
trackListenerError3("listener_list_directory_failed", err, "listener_file_browser");
|
|
406272
|
-
|
|
406358
|
+
warnFileCommand(`[Listen] list_in_directory error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
406273
406359
|
safeSocketSend(socket, {
|
|
406274
406360
|
type: "list_in_directory_response",
|
|
406275
406361
|
path: parsed.path,
|
|
@@ -406284,14 +406370,14 @@ function createFileCommandSession(params) {
|
|
|
406284
406370
|
return true;
|
|
406285
406371
|
}
|
|
406286
406372
|
if (isGetTreeCommand(parsed)) {
|
|
406287
|
-
|
|
406373
|
+
logFileCommand(`[Listen] Received get_tree command: path=${parsed.path}, depth=${parsed.depth}`);
|
|
406288
406374
|
runDetachedListenerTask("get_tree", async () => {
|
|
406289
406375
|
try {
|
|
406290
406376
|
const { entries: results, hasMoreDepth } = await getTreeDirect({
|
|
406291
406377
|
root: parsed.path,
|
|
406292
406378
|
depth: parsed.depth
|
|
406293
406379
|
});
|
|
406294
|
-
|
|
406380
|
+
logFileCommand(`[Listen] Sending get_tree_response: ${results.length} entries, has_more_depth=${hasMoreDepth}`);
|
|
406295
406381
|
safeSocketSend(socket, {
|
|
406296
406382
|
type: "get_tree_response",
|
|
406297
406383
|
path: parsed.path,
|
|
@@ -406302,7 +406388,7 @@ function createFileCommandSession(params) {
|
|
|
406302
406388
|
}, "listener_get_tree_send_failed", "listener_get_tree");
|
|
406303
406389
|
} catch (err) {
|
|
406304
406390
|
trackListenerError3("listener_get_tree_failed", err, "listener_file_browser");
|
|
406305
|
-
|
|
406391
|
+
warnFileCommand(`[Listen] get_tree error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
406306
406392
|
safeSocketSend(socket, {
|
|
406307
406393
|
type: "get_tree_response",
|
|
406308
406394
|
path: parsed.path,
|
|
@@ -406318,7 +406404,7 @@ function createFileCommandSession(params) {
|
|
|
406318
406404
|
}
|
|
406319
406405
|
if (isReadFileCommand(parsed)) {
|
|
406320
406406
|
const encoding = parsed.encoding ?? "utf8";
|
|
406321
|
-
|
|
406407
|
+
logFileCommand(`[Listen] Received read_file command: path=${parsed.path}, encoding=${encoding}, request_id=${parsed.request_id}`);
|
|
406322
406408
|
runDetachedListenerTask("read_file", async () => {
|
|
406323
406409
|
try {
|
|
406324
406410
|
let content;
|
|
@@ -406333,7 +406419,7 @@ function createFileCommandSession(params) {
|
|
|
406333
406419
|
} else {
|
|
406334
406420
|
content = await readUtf8TextStrict(parsed.path);
|
|
406335
406421
|
}
|
|
406336
|
-
|
|
406422
|
+
logFileCommand(`[Listen] read_file success: ${parsed.path} (${content.length} bytes, ${encoding})`);
|
|
406337
406423
|
safeSocketSend(socket, {
|
|
406338
406424
|
type: "read_file_response",
|
|
406339
406425
|
request_id: parsed.request_id,
|
|
@@ -406344,7 +406430,7 @@ function createFileCommandSession(params) {
|
|
|
406344
406430
|
}, "listener_read_file_send_failed", "listener_read_file");
|
|
406345
406431
|
} catch (err) {
|
|
406346
406432
|
trackListenerError3("listener_read_file_failed", err, "listener_file_read");
|
|
406347
|
-
|
|
406433
|
+
warnFileCommand(`[Listen] read_file error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
406348
406434
|
safeSocketSend(socket, {
|
|
406349
406435
|
type: "read_file_response",
|
|
406350
406436
|
request_id: parsed.request_id,
|
|
@@ -406359,7 +406445,7 @@ function createFileCommandSession(params) {
|
|
|
406359
406445
|
return true;
|
|
406360
406446
|
}
|
|
406361
406447
|
if (isWriteFileCommand(parsed)) {
|
|
406362
|
-
|
|
406448
|
+
logFileCommand(`[Listen] Received write_file command: path=${parsed.path}, request_id=${parsed.request_id}`);
|
|
406363
406449
|
runDetachedListenerTask("write_file", async () => {
|
|
406364
406450
|
try {
|
|
406365
406451
|
const { edit: edit3 } = await Promise.resolve().then(() => (init_edit2(), exports_edit));
|
|
@@ -406387,7 +406473,7 @@ function createFileCommandSession(params) {
|
|
|
406387
406473
|
});
|
|
406388
406474
|
}
|
|
406389
406475
|
}
|
|
406390
|
-
|
|
406476
|
+
logFileCommand(`[Listen] write_file success: ${parsed.path} (${parsed.content.length} bytes)`);
|
|
406391
406477
|
safeSocketSend(socket, {
|
|
406392
406478
|
type: "write_file_response",
|
|
406393
406479
|
request_id: parsed.request_id,
|
|
@@ -406395,7 +406481,7 @@ function createFileCommandSession(params) {
|
|
|
406395
406481
|
success: true
|
|
406396
406482
|
}, "listener_write_file_send_failed", "listener_write_file");
|
|
406397
406483
|
} catch (err) {
|
|
406398
|
-
|
|
406484
|
+
warnFileCommand(`[Listen] write_file error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
406399
406485
|
safeSocketSend(socket, {
|
|
406400
406486
|
type: "write_file_response",
|
|
406401
406487
|
request_id: parsed.request_id,
|
|
@@ -406470,11 +406556,11 @@ function createFileCommandSession(params) {
|
|
|
406470
406556
|
return true;
|
|
406471
406557
|
}
|
|
406472
406558
|
if (isEditFileCommand(parsed)) {
|
|
406473
|
-
|
|
406559
|
+
logFileCommand(`[Listen] Received edit_file command: file_path=${parsed.file_path}, request_id=${parsed.request_id}`);
|
|
406474
406560
|
runDetachedListenerTask("edit_file", async () => {
|
|
406475
406561
|
try {
|
|
406476
406562
|
const { edit: edit3 } = await Promise.resolve().then(() => (init_edit2(), exports_edit));
|
|
406477
|
-
|
|
406563
|
+
logFileCommand(`[Listen] Executing edit: old_string="${parsed.old_string.slice(0, 50)}${parsed.old_string.length > 50 ? "..." : ""}"`);
|
|
406478
406564
|
const result2 = await edit3({
|
|
406479
406565
|
file_path: parsed.file_path,
|
|
406480
406566
|
old_string: parsed.old_string,
|
|
@@ -406482,7 +406568,7 @@ function createFileCommandSession(params) {
|
|
|
406482
406568
|
replace_all: parsed.replace_all,
|
|
406483
406569
|
expected_replacements: parsed.expected_replacements
|
|
406484
406570
|
});
|
|
406485
|
-
|
|
406571
|
+
logFileCommand(`[Listen] edit_file success: ${result2.replacements} replacement(s) at line ${result2.startLine}`);
|
|
406486
406572
|
if (result2.replacements > 0) {
|
|
406487
406573
|
try {
|
|
406488
406574
|
const contentAfter = await readUtf8TextStrict(parsed.file_path);
|
|
@@ -406507,7 +406593,7 @@ function createFileCommandSession(params) {
|
|
|
406507
406593
|
}, "listener_edit_file_send_failed", "listener_edit_file");
|
|
406508
406594
|
} catch (err) {
|
|
406509
406595
|
trackListenerError3("listener_edit_file_failed", err, "listener_file_edit");
|
|
406510
|
-
|
|
406596
|
+
warnFileCommand(`[Listen] edit_file error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
406511
406597
|
safeSocketSend(socket, {
|
|
406512
406598
|
type: "edit_file_response",
|
|
406513
406599
|
request_id: parsed.request_id,
|
|
@@ -406527,9 +406613,9 @@ function createFileCommandSession(params) {
|
|
|
406527
406613
|
try {
|
|
406528
406614
|
const content = parsed.document_content;
|
|
406529
406615
|
await writeUtf8Text(parsed.path, content);
|
|
406530
|
-
|
|
406616
|
+
logFileCommand(`[Listen] file_ops: wrote ${content.length} bytes to ${parsed.path}`);
|
|
406531
406617
|
} catch (err) {
|
|
406532
|
-
|
|
406618
|
+
warnFileCommand(`[Listen] file_ops error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
406533
406619
|
}
|
|
406534
406620
|
});
|
|
406535
406621
|
}
|
|
@@ -406539,13 +406625,16 @@ function createFileCommandSession(params) {
|
|
|
406539
406625
|
};
|
|
406540
406626
|
return { handle: handle2, dispose };
|
|
406541
406627
|
}
|
|
406542
|
-
var import_picomatch2, DIR_LISTING_IGNORED_NAMES, RECURSIVE_IGNORED_NAMES, PROTECTED_HOME_NAMES, MAX_SEARCH_VISITED_ENTRIES = 50000, MAX_TREE_ENTRIES = 5000, MAX_SEARCH_RESULTS = 200, MAX_BASE64_READ_BYTES, ignoreConfigCache;
|
|
406628
|
+
var import_picomatch2, logFileCommand, warnFileCommand, DIR_LISTING_IGNORED_NAMES, RECURSIVE_IGNORED_NAMES, PROTECTED_HOME_NAMES, MAX_SEARCH_VISITED_ENTRIES = 50000, MAX_TREE_ENTRIES = 5000, MAX_SEARCH_RESULTS = 200, MAX_BASE64_READ_BYTES, ignoreConfigCache;
|
|
406543
406629
|
var init_file_commands = __esm(() => {
|
|
406544
406630
|
init_error_reporting();
|
|
406631
|
+
init_debug();
|
|
406545
406632
|
init_text_files();
|
|
406546
406633
|
init_grep_in_files();
|
|
406547
406634
|
init_protocol_inbound();
|
|
406548
406635
|
import_picomatch2 = __toESM(require_picomatch(), 1);
|
|
406636
|
+
logFileCommand = debugLog.bind(null, "file-commands");
|
|
406637
|
+
warnFileCommand = debugWarn.bind(null, "file-commands");
|
|
406549
406638
|
DIR_LISTING_IGNORED_NAMES = new Set([".DS_Store", ".git", "Thumbs.db"]);
|
|
406550
406639
|
RECURSIVE_IGNORED_NAMES = new Set([
|
|
406551
406640
|
...DIR_LISTING_IGNORED_NAMES,
|
|
@@ -407489,6 +407578,13 @@ async function handleExecuteCommand(command, socket, conversationRuntime, opts)
|
|
|
407489
407578
|
actingUserId: command.runtime.acting_user_id
|
|
407490
407579
|
});
|
|
407491
407580
|
break;
|
|
407581
|
+
case "clear-messages":
|
|
407582
|
+
output = await handleClearCommand(socket, conversationRuntime, {
|
|
407583
|
+
...opts,
|
|
407584
|
+
actingUserId: command.runtime.acting_user_id,
|
|
407585
|
+
resetAllAgentMessages: true
|
|
407586
|
+
});
|
|
407587
|
+
break;
|
|
407492
407588
|
case "doctor":
|
|
407493
407589
|
output = await handleDoctorCommand(socket, conversationRuntime, opts);
|
|
407494
407590
|
break;
|
|
@@ -407643,7 +407739,7 @@ async function handleUpgradeLettaCodeCommand(opts) {
|
|
|
407643
407739
|
if (opts.onLog) {
|
|
407644
407740
|
opts.onLog(line);
|
|
407645
407741
|
} else {
|
|
407646
|
-
|
|
407742
|
+
debugLog("upgrade-letta-code", message);
|
|
407647
407743
|
}
|
|
407648
407744
|
};
|
|
407649
407745
|
log2(`command received (connectionName=${opts.connectionName ?? "unknown"}, execPath=${process.execPath}, entrypoint=${process.argv[1] ?? "unknown"})`);
|
|
@@ -407787,7 +407883,10 @@ async function handleClearCommand(_socket, conversationRuntime, opts) {
|
|
|
407787
407883
|
if (!agentId) {
|
|
407788
407884
|
throw new Error("No agent ID available for /clear command");
|
|
407789
407885
|
}
|
|
407790
|
-
if (
|
|
407886
|
+
if (opts.resetAllAgentMessages && backend3.capabilities.localModelCatalog) {
|
|
407887
|
+
throw new Error("/clear-messages is not supported by the local backend.");
|
|
407888
|
+
}
|
|
407889
|
+
if (!backend3.capabilities.localModelCatalog && (opts.resetAllAgentMessages || conversationRuntime.conversationId === "default")) {
|
|
407791
407890
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
407792
407891
|
const client = await getClient2();
|
|
407793
407892
|
await client.agents.messages.reset(agentId, {
|
|
@@ -407800,7 +407899,7 @@ async function handleClearCommand(_socket, conversationRuntime, opts) {
|
|
|
407800
407899
|
clearConversationRuntimeState(conversationRuntime);
|
|
407801
407900
|
conversationRuntime.conversationId = conversation.id;
|
|
407802
407901
|
emitListenerStatus(conversationRuntime.listener, opts.onStatusChange, opts.connectionId);
|
|
407803
|
-
return "Agent's in-context messages cleared & moved to conversation history";
|
|
407902
|
+
return opts.resetAllAgentMessages ? "All agent messages reset" : "Agent's in-context messages cleared & moved to conversation history";
|
|
407804
407903
|
}
|
|
407805
407904
|
async function handleDoctorCommand(socket, conversationRuntime, opts) {
|
|
407806
407905
|
const agentId = conversationRuntime.agentId;
|
|
@@ -408070,7 +408169,7 @@ function getCwdScopeKeyFromRuntimeKey(runtimeKey) {
|
|
|
408070
408169
|
const conversationId = runtimeKey.slice(markerIndex + marker.length);
|
|
408071
408170
|
return conversationId === "default" ? runtimeKey : `conversation:${conversationId}`;
|
|
408072
408171
|
}
|
|
408073
|
-
function applyScopeUpdates(socket, runtime) {
|
|
408172
|
+
async function applyScopeUpdates(socket, runtime) {
|
|
408074
408173
|
for (const [runtimeKey, state] of runtime.reminderStateByConversation) {
|
|
408075
408174
|
const scopeKey = getCwdScopeKeyFromRuntimeKey(runtimeKey);
|
|
408076
408175
|
if (!scopeKey || runtime.workingDirectoryByConversation.has(scopeKey)) {
|
|
@@ -408084,10 +408183,12 @@ function applyScopeUpdates(socket, runtime) {
|
|
|
408084
408183
|
if (runtime.workingDirectoryByConversation.has(scopeKey) || conversationRuntime.activeWorkingDirectory) {
|
|
408085
408184
|
continue;
|
|
408086
408185
|
}
|
|
408087
|
-
|
|
408186
|
+
const scope = {
|
|
408088
408187
|
agent_id: conversationRuntime.agentId,
|
|
408089
408188
|
conversation_id: conversationRuntime.conversationId
|
|
408090
|
-
}
|
|
408189
|
+
};
|
|
408190
|
+
await refreshDeviceGitContext(conversationRuntime, scope);
|
|
408191
|
+
emitDeviceStatusUpdate(socket, conversationRuntime, scope);
|
|
408091
408192
|
}
|
|
408092
408193
|
}
|
|
408093
408194
|
async function handleSetBootWorkingDirectoryCommand(command, context3) {
|
|
@@ -408100,7 +408201,7 @@ async function handleSetBootWorkingDirectoryCommand(command, context3) {
|
|
|
408100
408201
|
settingsManager.loadLocalProjectSettings(normalizedPath)
|
|
408101
408202
|
]);
|
|
408102
408203
|
if (setBootWorkingDirectory(runtime, normalizedPath)) {
|
|
408103
|
-
applyScopeUpdates(socket, runtime);
|
|
408204
|
+
await applyScopeUpdates(socket, runtime);
|
|
408104
408205
|
}
|
|
408105
408206
|
safeSocketSend(socket, {
|
|
408106
408207
|
type: "set_boot_working_directory_response",
|
|
@@ -409179,8 +409280,8 @@ var init_connect_providers = __esm(() => {
|
|
|
409179
409280
|
});
|
|
409180
409281
|
|
|
409181
409282
|
// src/websocket/listener/commands/git-branches.ts
|
|
409182
|
-
import { execFile as
|
|
409183
|
-
import { promisify as
|
|
409283
|
+
import { execFile as execFile16 } from "node:child_process";
|
|
409284
|
+
import { promisify as promisify15 } from "node:util";
|
|
409184
409285
|
function handleGitBranchCommand(parsed, context3) {
|
|
409185
409286
|
const { socket, runtime, safeSocketSend, runDetachedListenerTask } = context3;
|
|
409186
409287
|
if (isSearchBranchesCommand(parsed)) {
|
|
@@ -409188,8 +409289,8 @@ function handleGitBranchCommand(parsed, context3) {
|
|
|
409188
409289
|
try {
|
|
409189
409290
|
const cwd2 = parsed.cwd ?? getBootWorkingDirectory(runtime);
|
|
409190
409291
|
const maxResults = parsed.max_results ?? 20;
|
|
409191
|
-
const
|
|
409192
|
-
const { stdout } = await
|
|
409292
|
+
const execFileAsync10 = promisify15(execFile16);
|
|
409293
|
+
const { stdout } = await execFileAsync10("git", ["branch", "-a", "--format=%(refname:short)\t%(HEAD)"], {
|
|
409193
409294
|
cwd: cwd2,
|
|
409194
409295
|
encoding: "utf-8",
|
|
409195
409296
|
timeout: 5000
|
|
@@ -409228,14 +409329,16 @@ function handleGitBranchCommand(parsed, context3) {
|
|
|
409228
409329
|
runDetachedListenerTask("checkout_branch", async () => {
|
|
409229
409330
|
try {
|
|
409230
409331
|
const cwd2 = parsed.cwd ?? getBootWorkingDirectory(runtime);
|
|
409231
|
-
const
|
|
409332
|
+
const execFileAsync10 = promisify15(execFile16);
|
|
409232
409333
|
const args = parsed.create ? ["checkout", "-b", parsed.branch] : ["checkout", parsed.branch];
|
|
409233
|
-
await
|
|
409334
|
+
await execFileAsync10("git", args, {
|
|
409234
409335
|
cwd: cwd2,
|
|
409235
409336
|
encoding: "utf-8",
|
|
409236
409337
|
timeout: 1e4
|
|
409237
409338
|
});
|
|
409238
|
-
const gitCtx =
|
|
409339
|
+
const gitCtx = await deviceGitContextCache.refresh(cwd2, {
|
|
409340
|
+
force: true
|
|
409341
|
+
});
|
|
409239
409342
|
safeSocketSend(socket, {
|
|
409240
409343
|
type: "checkout_branch_response",
|
|
409241
409344
|
request_id: parsed.request_id,
|
|
@@ -409258,8 +409361,8 @@ function handleGitBranchCommand(parsed, context3) {
|
|
|
409258
409361
|
return false;
|
|
409259
409362
|
}
|
|
409260
409363
|
var init_git_branches = __esm(() => {
|
|
409261
|
-
init_git_context();
|
|
409262
409364
|
init_cwd();
|
|
409365
|
+
init_device_git_context();
|
|
409263
409366
|
init_protocol_inbound();
|
|
409264
409367
|
init_protocol_outbound();
|
|
409265
409368
|
});
|
|
@@ -409804,6 +409907,13 @@ var init_split_stream_lifecycle = __esm(() => {
|
|
|
409804
409907
|
});
|
|
409805
409908
|
|
|
409806
409909
|
// src/websocket/listener/message-router.ts
|
|
409910
|
+
function logV2Command(opts, message) {
|
|
409911
|
+
if (opts.onLog) {
|
|
409912
|
+
opts.onLog(`[Listen V2] ${message}`);
|
|
409913
|
+
return;
|
|
409914
|
+
}
|
|
409915
|
+
debugLog("Listen V2", message);
|
|
409916
|
+
}
|
|
409807
409917
|
function createListenerMessageHandler(params) {
|
|
409808
409918
|
const {
|
|
409809
409919
|
runtime,
|
|
@@ -409853,7 +409963,7 @@ function createListenerMessageHandler(params) {
|
|
|
409853
409963
|
if (!parsed) {
|
|
409854
409964
|
return;
|
|
409855
409965
|
}
|
|
409856
|
-
|
|
409966
|
+
logV2Command(opts, `Received ${summarizeV2Command(parsed)}`);
|
|
409857
409967
|
if (parsedScope) {
|
|
409858
409968
|
subscribeListenerConnection(runtime, connectionId, parsedScope);
|
|
409859
409969
|
}
|
|
@@ -409929,7 +410039,7 @@ function createListenerMessageHandler(params) {
|
|
|
409929
410039
|
}
|
|
409930
410040
|
if (parsed.type === "sync") {
|
|
409931
410041
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
409932
|
-
|
|
410042
|
+
logV2Command(opts, "Dropping sync: runtime mismatch or closed");
|
|
409933
410043
|
if (parsed.request_id) {
|
|
409934
410044
|
safeSocketSend(socket, {
|
|
409935
410045
|
type: "sync_response",
|
|
@@ -409983,7 +410093,7 @@ function createListenerMessageHandler(params) {
|
|
|
409983
410093
|
}, "input_accepted_response", "input");
|
|
409984
410094
|
};
|
|
409985
410095
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
409986
|
-
|
|
410096
|
+
logV2Command(opts, "Dropping input: runtime mismatch or closed");
|
|
409987
410097
|
acknowledgeInput(false, "Runtime is no longer active");
|
|
409988
410098
|
return;
|
|
409989
410099
|
}
|
|
@@ -410702,7 +410812,7 @@ async function replaySyncStateForRuntime(listenerRuntime, socket, scope, opts) {
|
|
|
410702
410812
|
}
|
|
410703
410813
|
}
|
|
410704
410814
|
}
|
|
410705
|
-
replaySubscribedConnectionState(listenerRuntime, socket, syncScopedRuntime, scope, opts
|
|
410815
|
+
await replaySubscribedConnectionState(listenerRuntime, socket, syncScopedRuntime, scope, opts);
|
|
410706
410816
|
(opts?.scheduleWarmupsAfterSync ?? scheduleListenerWarmupsAfterSync)(listenerRuntime, scope);
|
|
410707
410817
|
}
|
|
410708
410818
|
function getParsedRuntimeScope(parsed) {
|
|
@@ -410826,7 +410936,7 @@ async function startConnectedListenerRuntime(runtime, transport, opts, processQu
|
|
|
410826
410936
|
runtime.hasSuccessfulConnection = true;
|
|
410827
410937
|
runtime.everConnected = true;
|
|
410828
410938
|
await opts.onConnected(opts.connectionId);
|
|
410829
|
-
emitInitialConnectionState(runtime, transport, opts.connectionId, options);
|
|
410939
|
+
await emitInitialConnectionState(runtime, transport, opts.connectionId, options);
|
|
410830
410940
|
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
410831
410941
|
replayPendingApprovalRequestsToConnection(conversationRuntime, opts.connectionId);
|
|
410832
410942
|
}
|
|
@@ -411284,6 +411394,7 @@ var init_lifecycle = __esm(async () => {
|
|
|
411284
411394
|
init_recovery_sync();
|
|
411285
411395
|
init_runtime();
|
|
411286
411396
|
init_split_stream_lifecycle();
|
|
411397
|
+
init_stream_observers();
|
|
411287
411398
|
init_transport();
|
|
411288
411399
|
init_worktree_watcher();
|
|
411289
411400
|
await __promiseAll([
|
|
@@ -414170,6 +414281,8 @@ async function runListenSubcommand(argv) {
|
|
|
414170
414281
|
return 1;
|
|
414171
414282
|
}
|
|
414172
414283
|
const debugMode = !!values3.debug;
|
|
414284
|
+
if (debugMode)
|
|
414285
|
+
process.env.LETTA_DEBUG = "1";
|
|
414173
414286
|
const skillsDirectory = values3.skills ?? process.env.LETTA_SKILLS_DIRECTORY;
|
|
414174
414287
|
if (values3.help) {
|
|
414175
414288
|
printListenUsage();
|
|
@@ -414265,6 +414378,11 @@ async function runListenSubcommand(argv) {
|
|
|
414265
414378
|
const sessionLog = new RemoteSessionLog;
|
|
414266
414379
|
sessionLog.init();
|
|
414267
414380
|
console.log(`Log file: ${sessionLog.path}`);
|
|
414381
|
+
const logListenerMessage = (message) => {
|
|
414382
|
+
sessionLog.log(message);
|
|
414383
|
+
if (debugMode)
|
|
414384
|
+
console.log(`[${formatTimestamp3()}] ${message}`);
|
|
414385
|
+
};
|
|
414268
414386
|
try {
|
|
414269
414387
|
const deviceId = settingsManager.getOrCreateDeviceId();
|
|
414270
414388
|
const startupMode = await resolveListenerStartupMode(channelNames, channelNames.length > 0 || restoreEnabledChannels);
|
|
@@ -414401,6 +414519,7 @@ async function runListenSubcommand(argv) {
|
|
|
414401
414519
|
connectionId: connectionId2,
|
|
414402
414520
|
deviceId,
|
|
414403
414521
|
connectionName,
|
|
414522
|
+
onLog: logListenerMessage,
|
|
414404
414523
|
onWsEvent: process.env.LETTA_LOG_WS_EVENTS === "1" ? (direction, label, event) => {
|
|
414405
414524
|
sessionLog.wsEvent(direction, label, event);
|
|
414406
414525
|
} : undefined,
|
|
@@ -414501,10 +414620,7 @@ async function runListenSubcommand(argv) {
|
|
|
414501
414620
|
sessionLog.log(`status: ${status}`);
|
|
414502
414621
|
console.log(`[${formatTimestamp3()}] status: ${status}`);
|
|
414503
414622
|
},
|
|
414504
|
-
onLog:
|
|
414505
|
-
sessionLog.log(message);
|
|
414506
|
-
console.log(`[${formatTimestamp3()}] ${message}`);
|
|
414507
|
-
},
|
|
414623
|
+
onLog: logListenerMessage,
|
|
414508
414624
|
onConnected: async () => {
|
|
414509
414625
|
sessionLog.log("Connected. Awaiting instructions.");
|
|
414510
414626
|
await startChannelGateway();
|
|
@@ -414569,10 +414685,7 @@ async function runListenSubcommand(argv) {
|
|
|
414569
414685
|
clearRetryStatusCallback?.();
|
|
414570
414686
|
updateStatusCallback?.(status);
|
|
414571
414687
|
},
|
|
414572
|
-
onLog:
|
|
414573
|
-
sessionLog.log(message);
|
|
414574
|
-
console.log(`[${formatTimestamp3()}] ${message}`);
|
|
414575
|
-
},
|
|
414688
|
+
onLog: logListenerMessage,
|
|
414576
414689
|
onConnected: async () => {
|
|
414577
414690
|
sessionLog.log("Connected. Awaiting instructions.");
|
|
414578
414691
|
await startChannelGateway();
|
|
@@ -419041,7 +419154,7 @@ function finalize(ctx, schema5) {
|
|
|
419041
419154
|
result2.$schema = "http://json-schema.org/draft-07/schema#";
|
|
419042
419155
|
} else if (ctx.target === "draft-04") {
|
|
419043
419156
|
result2.$schema = "http://json-schema.org/draft-04/schema#";
|
|
419044
|
-
} else if (ctx.target === "openapi-3.0") {}
|
|
419157
|
+
} else if (ctx.target === "openapi-3.0") {}
|
|
419045
419158
|
if (ctx.external?.uri) {
|
|
419046
419159
|
const id2 = ctx.external.registry.get(schema5)?.id;
|
|
419047
419160
|
if (!id2)
|
|
@@ -419256,7 +419369,7 @@ var formatMap2, stringProcessor = (schema5, ctx, _json, _params) => {
|
|
|
419256
419369
|
if (val === undefined) {
|
|
419257
419370
|
if (ctx.unrepresentable === "throw") {
|
|
419258
419371
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
419259
|
-
}
|
|
419372
|
+
}
|
|
419260
419373
|
} else if (typeof val === "bigint") {
|
|
419261
419374
|
if (ctx.unrepresentable === "throw") {
|
|
419262
419375
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -431970,7 +432083,7 @@ var init_mcp_client = __esm(() => {
|
|
|
431970
432083
|
init_streamableHttp();
|
|
431971
432084
|
DEFAULT_CLIENT_INFO = {
|
|
431972
432085
|
name: "letta-code",
|
|
431973
|
-
version: "0.31.
|
|
432086
|
+
version: "0.31.13"
|
|
431974
432087
|
};
|
|
431975
432088
|
});
|
|
431976
432089
|
|
|
@@ -433204,7 +433317,7 @@ var init_memory_tokens = __esm(() => {
|
|
|
433204
433317
|
});
|
|
433205
433318
|
|
|
433206
433319
|
// src/cli/subcommands/memory.ts
|
|
433207
|
-
import { cpSync, existsSync as existsSync57, mkdirSync as mkdirSync39, rmSync as
|
|
433320
|
+
import { cpSync, existsSync as existsSync57, mkdirSync as mkdirSync39, rmSync as rmSync13, statSync as statSync19 } from "node:fs";
|
|
433208
433321
|
import { readdir as readdir12 } from "node:fs/promises";
|
|
433209
433322
|
import { dirname as dirname31, join as join72 } from "node:path";
|
|
433210
433323
|
import { parseArgs as parseArgs11 } from "node:util";
|
|
@@ -433341,10 +433454,10 @@ async function runMemorySubcommand(argv) {
|
|
|
433341
433454
|
return 1;
|
|
433342
433455
|
}
|
|
433343
433456
|
const { execFile: execFileCb5 } = await import("node:child_process");
|
|
433344
|
-
const { promisify:
|
|
433345
|
-
const
|
|
433457
|
+
const { promisify: promisify16 } = await import("node:util");
|
|
433458
|
+
const execFile17 = promisify16(execFileCb5);
|
|
433346
433459
|
const dir = getScopedMemoryFilesystemRoot(agentId);
|
|
433347
|
-
const { stdout } = await
|
|
433460
|
+
const { stdout } = await execFile17("git", ["diff"], { cwd: dir });
|
|
433348
433461
|
if (stdout.trim()) {
|
|
433349
433462
|
console.log(stdout);
|
|
433350
433463
|
return 2;
|
|
@@ -433411,7 +433524,7 @@ async function runMemorySubcommand(argv) {
|
|
|
433411
433524
|
return 1;
|
|
433412
433525
|
}
|
|
433413
433526
|
const root2 = getMemoryRoot(agentId);
|
|
433414
|
-
|
|
433527
|
+
rmSync13(root2, { recursive: true, force: true });
|
|
433415
433528
|
cpSync(backupPath, root2, { recursive: true });
|
|
433416
433529
|
console.log(JSON.stringify({ restoredFrom: backupPath }, null, 2));
|
|
433417
433530
|
return 0;
|
|
@@ -434197,7 +434310,7 @@ import {
|
|
|
434197
434310
|
readdirSync as readdirSync22,
|
|
434198
434311
|
readFileSync as readFileSync39,
|
|
434199
434312
|
renameSync as renameSync7,
|
|
434200
|
-
rmSync as
|
|
434313
|
+
rmSync as rmSync14,
|
|
434201
434314
|
writeFileSync as writeFileSync29
|
|
434202
434315
|
} from "node:fs";
|
|
434203
434316
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
@@ -434418,7 +434531,7 @@ function copyPackageInternalNodeModules(params) {
|
|
|
434418
434531
|
}
|
|
434419
434532
|
function restoreRegistry(registryPath, previousContents) {
|
|
434420
434533
|
if (previousContents === null) {
|
|
434421
|
-
|
|
434534
|
+
rmSync14(registryPath, { force: true });
|
|
434422
434535
|
return;
|
|
434423
434536
|
}
|
|
434424
434537
|
mkdirSync40(path46.dirname(registryPath), { recursive: true });
|
|
@@ -434427,17 +434540,17 @@ function restoreRegistry(registryPath, previousContents) {
|
|
|
434427
434540
|
function removeIfExists(targetPath) {
|
|
434428
434541
|
if (!targetPath)
|
|
434429
434542
|
return;
|
|
434430
|
-
|
|
434543
|
+
rmSync14(targetPath, { force: true, recursive: true });
|
|
434431
434544
|
}
|
|
434432
434545
|
function restoreDestination(params) {
|
|
434433
|
-
|
|
434546
|
+
rmSync14(params.destinationRoot, { force: true, recursive: true });
|
|
434434
434547
|
if (params.backupRoot && existsSync59(params.backupRoot)) {
|
|
434435
434548
|
renameSync7(params.backupRoot, params.destinationRoot);
|
|
434436
434549
|
}
|
|
434437
434550
|
}
|
|
434438
434551
|
function restoreDestinationIfNeeded(params) {
|
|
434439
434552
|
if (!params.backupRoot || !existsSync59(params.backupRoot)) {
|
|
434440
|
-
|
|
434553
|
+
rmSync14(params.destinationRoot, { force: true, recursive: true });
|
|
434441
434554
|
return;
|
|
434442
434555
|
}
|
|
434443
434556
|
restoreDestination(params);
|
|
@@ -434479,7 +434592,7 @@ function installPreparedManagedModPackage(params) {
|
|
|
434479
434592
|
}
|
|
434480
434593
|
if (existsSync59(destinationRoot)) {
|
|
434481
434594
|
backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
|
|
434482
|
-
|
|
434595
|
+
rmSync14(backupRoot, { force: true, recursive: true });
|
|
434483
434596
|
renameSync7(destinationRoot, backupRoot);
|
|
434484
434597
|
destinationNeedsRollback = true;
|
|
434485
434598
|
}
|
|
@@ -434930,7 +435043,7 @@ async function installNpmManagedModPackage(params) {
|
|
|
434930
435043
|
packageDirectory
|
|
434931
435044
|
});
|
|
434932
435045
|
} finally {
|
|
434933
|
-
|
|
435046
|
+
rmSync14(tempRoot, { force: true, recursive: true });
|
|
434934
435047
|
}
|
|
434935
435048
|
}
|
|
434936
435049
|
async function installGitManagedModPackage(params) {
|
|
@@ -434962,7 +435075,7 @@ async function installGitManagedModPackage(params) {
|
|
|
434962
435075
|
packageInfo
|
|
434963
435076
|
});
|
|
434964
435077
|
} finally {
|
|
434965
|
-
|
|
435078
|
+
rmSync14(tempRoot, { force: true, recursive: true });
|
|
434966
435079
|
}
|
|
434967
435080
|
}
|
|
434968
435081
|
async function updateNpmManagedModPackage(params) {
|
|
@@ -434993,7 +435106,7 @@ async function updateNpmManagedModPackage(params) {
|
|
|
434993
435106
|
previousVersion: existing.version
|
|
434994
435107
|
};
|
|
434995
435108
|
} finally {
|
|
434996
|
-
|
|
435109
|
+
rmSync14(tempRoot, { force: true, recursive: true });
|
|
434997
435110
|
}
|
|
434998
435111
|
}
|
|
434999
435112
|
async function updateGitManagedModPackage(params) {
|
|
@@ -435035,7 +435148,7 @@ async function updateGitManagedModPackage(params) {
|
|
|
435035
435148
|
previousVersion: existing.version
|
|
435036
435149
|
};
|
|
435037
435150
|
} finally {
|
|
435038
|
-
|
|
435151
|
+
rmSync14(tempRoot, { force: true, recursive: true });
|
|
435039
435152
|
}
|
|
435040
435153
|
}
|
|
435041
435154
|
var SKIPPED_PACKAGE_COPY_NAMES, spawnNpmInstallProcessOverride = null, spawnGitInstallProcess, platformOverride2 = null;
|
|
@@ -435054,7 +435167,7 @@ import {
|
|
|
435054
435167
|
existsSync as existsSync60,
|
|
435055
435168
|
lstatSync as lstatSync4,
|
|
435056
435169
|
mkdirSync as mkdirSync41,
|
|
435057
|
-
rmSync as
|
|
435170
|
+
rmSync as rmSync15,
|
|
435058
435171
|
writeFileSync as writeFileSync30
|
|
435059
435172
|
} from "node:fs";
|
|
435060
435173
|
import path47 from "node:path";
|
|
@@ -435163,7 +435276,7 @@ function scaffoldLocalModPackage(options) {
|
|
|
435163
435276
|
writeFileSync30(readmePath, createReadme(packageName));
|
|
435164
435277
|
writeFileSync30(modGuidePath, createModGuide(packageName, manifestEntry));
|
|
435165
435278
|
} catch (error5) {
|
|
435166
|
-
|
|
435279
|
+
rmSync15(outputDirectory, { force: true, recursive: true });
|
|
435167
435280
|
throw error5;
|
|
435168
435281
|
}
|
|
435169
435282
|
return {
|
|
@@ -438266,7 +438379,7 @@ import {
|
|
|
438266
438379
|
existsSync as existsSync62,
|
|
438267
438380
|
mkdtempSync as mkdtempSync5,
|
|
438268
438381
|
readFileSync as readFileSync40,
|
|
438269
|
-
rmSync as
|
|
438382
|
+
rmSync as rmSync16,
|
|
438270
438383
|
statSync as statSync21,
|
|
438271
438384
|
writeFileSync as writeFileSync31
|
|
438272
438385
|
} from "node:fs";
|
|
@@ -438535,15 +438648,15 @@ function resolveSkillSourceSpecifier(input) {
|
|
|
438535
438648
|
}
|
|
438536
438649
|
return null;
|
|
438537
438650
|
}
|
|
438538
|
-
async function
|
|
438651
|
+
async function execFile17(command, args, options = {}) {
|
|
438539
438652
|
const { execFile: execFileCb5 } = await import("node:child_process");
|
|
438540
|
-
const { promisify:
|
|
438541
|
-
return
|
|
438653
|
+
const { promisify: promisify16 } = await import("node:util");
|
|
438654
|
+
return promisify16(execFileCb5)(command, args, options);
|
|
438542
438655
|
}
|
|
438543
438656
|
async function resolveBranchAndSubdir(location) {
|
|
438544
438657
|
if (!location.subdir)
|
|
438545
438658
|
return location;
|
|
438546
|
-
const { stdout } = await
|
|
438659
|
+
const { stdout } = await execFile17("git", ["ls-remote", "--heads", location.repoUrl], {
|
|
438547
438660
|
timeout: 60000
|
|
438548
438661
|
});
|
|
438549
438662
|
const branches = stdout.split(`
|
|
@@ -438570,7 +438683,7 @@ async function cloneSkillSource(location) {
|
|
|
438570
438683
|
args.push("--branch", resolvedLocation.branch);
|
|
438571
438684
|
}
|
|
438572
438685
|
args.push(resolvedLocation.repoUrl, tmpDir);
|
|
438573
|
-
await
|
|
438686
|
+
await execFile17("git", args, { timeout: 120000 });
|
|
438574
438687
|
const sourceDir = resolvedLocation.subdir ? join76(tmpDir, resolvedLocation.subdir) : tmpDir;
|
|
438575
438688
|
return { tmpDir, sourceDir };
|
|
438576
438689
|
}
|
|
@@ -438633,7 +438746,7 @@ async function downloadDirectSkillFileSource(location, options = {}) {
|
|
|
438633
438746
|
writeFileSync31(join76(sourceDir, "SKILL.md"), skillText, "utf8");
|
|
438634
438747
|
return { tmpDir, sourceDir };
|
|
438635
438748
|
} catch (error5) {
|
|
438636
|
-
|
|
438749
|
+
rmSync16(tmpDir, { recursive: true, force: true });
|
|
438637
438750
|
throw error5;
|
|
438638
438751
|
}
|
|
438639
438752
|
}
|
|
@@ -438683,7 +438796,7 @@ async function downloadClawHubSkillSource(location) {
|
|
|
438683
438796
|
throw new Error(`ClawHub download failed for ${location.slug}@${version2}: ${response.status}`);
|
|
438684
438797
|
}
|
|
438685
438798
|
writeFileSync31(zipPath, Buffer.from(await response.arrayBuffer()));
|
|
438686
|
-
const { stdout } = await
|
|
438799
|
+
const { stdout } = await execFile17("unzip", ["-Z1", zipPath], {
|
|
438687
438800
|
timeout: 30000
|
|
438688
438801
|
});
|
|
438689
438802
|
const members = stdout.split(`
|
|
@@ -438692,7 +438805,7 @@ async function downloadClawHubSkillSource(location) {
|
|
|
438692
438805
|
throw new Error(`ClawHub download was empty for ${location.slug}@${version2}`);
|
|
438693
438806
|
}
|
|
438694
438807
|
members.forEach(assertSafeZipMember);
|
|
438695
|
-
await
|
|
438808
|
+
await execFile17("unzip", ["-q", zipPath, "-d", sourceDir], {
|
|
438696
438809
|
timeout: 30000
|
|
438697
438810
|
});
|
|
438698
438811
|
return { tmpDir, sourceDir };
|
|
@@ -438736,7 +438849,7 @@ async function installSkillDirectory(params) {
|
|
|
438736
438849
|
if (!params.force) {
|
|
438737
438850
|
throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
|
|
438738
438851
|
}
|
|
438739
|
-
|
|
438852
|
+
rmSync16(targetPath, { recursive: true, force: true });
|
|
438740
438853
|
}
|
|
438741
438854
|
await mkdir14(skillsDir, { recursive: true });
|
|
438742
438855
|
cpSync2(sourceDir, targetPath, {
|
|
@@ -438787,7 +438900,7 @@ async function deleteSkillDirectory(params) {
|
|
|
438787
438900
|
if (!statSync21(targetPath).isDirectory()) {
|
|
438788
438901
|
throw new Error(`Skill path is not a directory: ${targetPath}`);
|
|
438789
438902
|
}
|
|
438790
|
-
|
|
438903
|
+
rmSync16(targetPath, { recursive: true, force: true });
|
|
438791
438904
|
return { name, path: normalize5(targetPath) };
|
|
438792
438905
|
}
|
|
438793
438906
|
async function loadSkillMemorySyncFn() {
|
|
@@ -438851,7 +438964,7 @@ async function installSkill(specifier, agentId, force) {
|
|
|
438851
438964
|
};
|
|
438852
438965
|
} finally {
|
|
438853
438966
|
if (tmpDir)
|
|
438854
|
-
|
|
438967
|
+
rmSync16(tmpDir, { recursive: true, force: true });
|
|
438855
438968
|
}
|
|
438856
438969
|
}
|
|
438857
438970
|
async function getAgentMemoryDir(agentId) {
|
|
@@ -441244,7 +441357,9 @@ function bindProactiveSlackThreadRoute(params) {
|
|
|
441244
441357
|
}
|
|
441245
441358
|
}
|
|
441246
441359
|
function createProactiveSlackTransport(params) {
|
|
441360
|
+
const listCustomEmojis = params.adapter.listCustomEmojis?.bind(params.adapter);
|
|
441247
441361
|
return {
|
|
441362
|
+
...listCustomEmojis ? { listCustomEmojis } : {},
|
|
441248
441363
|
sendMessage: async (message) => {
|
|
441249
441364
|
const result2 = await params.adapter.sendMessage(message);
|
|
441250
441365
|
const isRootChannelPost = params.target.chatType === "channel" && !message.threadId?.trim() && !message.replyToMessageId?.trim() && !message.reaction;
|
|
@@ -443088,6 +443203,7 @@ Replies to routed Slack threads stay in the current thread automatically.` : "";
|
|
|
443088
443203
|
Replies to routed Telegram topics stay in the current topic automatically.` : "";
|
|
443089
443204
|
const slackCapabilities = discovery.activeChannels.includes("slack") ? [
|
|
443090
443205
|
hasAction("react") ? 'action="react" with emoji + messageId' : "",
|
|
443206
|
+
hasAction("list-custom-emojis") ? 'action="list-custom-emojis" to discover the workspace custom emoji names available for reactions' : "",
|
|
443091
443207
|
hasAction("upload-file") ? 'action="upload-file" with media' : "",
|
|
443092
443208
|
hasAction("download-file") ? 'action="download-file" with attachmentId + messageId' : ""
|
|
443093
443209
|
].filter(Boolean) : [];
|
|
@@ -443217,7 +443333,7 @@ var init_message_channel_gateway_tool = __esm(() => {
|
|
|
443217
443333
|
});
|
|
443218
443334
|
|
|
443219
443335
|
// src/channels/custom/scaffolding.ts
|
|
443220
|
-
import { existsSync as existsSync63, mkdirSync as mkdirSync42, rmSync as
|
|
443336
|
+
import { existsSync as existsSync63, mkdirSync as mkdirSync42, rmSync as rmSync17, writeFileSync as writeFileSync32 } from "node:fs";
|
|
443221
443337
|
function removeUserPlugin(channelId) {
|
|
443222
443338
|
if (FIRST_PARTY_SET.has(channelId)) {
|
|
443223
443339
|
return;
|
|
@@ -443230,7 +443346,7 @@ function removeUserPlugin(channelId) {
|
|
|
443230
443346
|
return;
|
|
443231
443347
|
}
|
|
443232
443348
|
try {
|
|
443233
|
-
|
|
443349
|
+
rmSync17(channelDir, { recursive: true, force: true });
|
|
443234
443350
|
} catch (err) {
|
|
443235
443351
|
console.error(`[channels] Failed to remove plugin folder ${channelDir}:`, err);
|
|
443236
443352
|
}
|
|
@@ -444971,6 +445087,51 @@ var init_router = __esm(async () => {
|
|
|
444971
445087
|
]);
|
|
444972
445088
|
});
|
|
444973
445089
|
|
|
445090
|
+
// src/utils/version.ts
|
|
445091
|
+
function parseSemver(version2) {
|
|
445092
|
+
const match3 = version2.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
445093
|
+
if (!match3)
|
|
445094
|
+
return null;
|
|
445095
|
+
const [, major, minor, patch2] = match3;
|
|
445096
|
+
return [
|
|
445097
|
+
parseInt(major ?? "0", 10),
|
|
445098
|
+
parseInt(minor ?? "0", 10),
|
|
445099
|
+
parseInt(patch2 ?? "0", 10)
|
|
445100
|
+
];
|
|
445101
|
+
}
|
|
445102
|
+
function compareSemver(a2, b3) {
|
|
445103
|
+
const aParts = parseSemver(a2);
|
|
445104
|
+
const bParts = parseSemver(b3);
|
|
445105
|
+
if (!aParts || !bParts)
|
|
445106
|
+
return null;
|
|
445107
|
+
for (let i4 = 0;i4 < 3; i4++) {
|
|
445108
|
+
const a3 = aParts[i4] ?? 0;
|
|
445109
|
+
const b4 = bParts[i4] ?? 0;
|
|
445110
|
+
if (a3 < b4)
|
|
445111
|
+
return -1;
|
|
445112
|
+
if (a3 > b4)
|
|
445113
|
+
return 1;
|
|
445114
|
+
}
|
|
445115
|
+
return 0;
|
|
445116
|
+
}
|
|
445117
|
+
function isVersionBelow(version2, minimum3) {
|
|
445118
|
+
const result2 = compareSemver(version2, minimum3);
|
|
445119
|
+
return result2 === -1;
|
|
445120
|
+
}
|
|
445121
|
+
|
|
445122
|
+
// src/runtime-version.ts
|
|
445123
|
+
function assertSupportedBunRuntime(bunVersion = process.versions.bun) {
|
|
445124
|
+
if (!bunVersion || !isVersionBelow(bunVersion, MINIMUM_BUN_VERSION)) {
|
|
445125
|
+
return;
|
|
445126
|
+
}
|
|
445127
|
+
throw new Error(`Letta Code cannot run on Bun ${bunVersion}. Bun ${MINIMUM_BUN_VERSION} or newer is required because older versions can stop reading child-process output. Upgrade Bun, or install Letta Code from npm to run it with Node.`);
|
|
445128
|
+
}
|
|
445129
|
+
var MINIMUM_BUN_VERSION;
|
|
445130
|
+
var init_runtime_version = __esm(() => {
|
|
445131
|
+
init_package();
|
|
445132
|
+
MINIMUM_BUN_VERSION = package_default.engines.bun.replace(/^>=/, "");
|
|
445133
|
+
});
|
|
445134
|
+
|
|
444974
445135
|
// src/startup-auto-update.ts
|
|
444975
445136
|
function startStartupAutoUpdateCheck(checkAndAutoUpdate2, logError = console.error) {
|
|
444976
445137
|
return checkAndAutoUpdate2().then((result2) => {
|
|
@@ -445124,38 +445285,6 @@ var init_kitty_protocol_detector = __esm(() => {
|
|
|
445124
445285
|
DISABLED = process.env.LETTA_DISABLE_KITTY === "1";
|
|
445125
445286
|
});
|
|
445126
445287
|
|
|
445127
|
-
// src/utils/version.ts
|
|
445128
|
-
function parseSemver(version2) {
|
|
445129
|
-
const match3 = version2.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
445130
|
-
if (!match3)
|
|
445131
|
-
return null;
|
|
445132
|
-
const [, major, minor, patch2] = match3;
|
|
445133
|
-
return [
|
|
445134
|
-
parseInt(major ?? "0", 10),
|
|
445135
|
-
parseInt(minor ?? "0", 10),
|
|
445136
|
-
parseInt(patch2 ?? "0", 10)
|
|
445137
|
-
];
|
|
445138
|
-
}
|
|
445139
|
-
function compareSemver(a2, b3) {
|
|
445140
|
-
const aParts = parseSemver(a2);
|
|
445141
|
-
const bParts = parseSemver(b3);
|
|
445142
|
-
if (!aParts || !bParts)
|
|
445143
|
-
return null;
|
|
445144
|
-
for (let i4 = 0;i4 < 3; i4++) {
|
|
445145
|
-
const a3 = aParts[i4] ?? 0;
|
|
445146
|
-
const b4 = bParts[i4] ?? 0;
|
|
445147
|
-
if (a3 < b4)
|
|
445148
|
-
return -1;
|
|
445149
|
-
if (a3 > b4)
|
|
445150
|
-
return 1;
|
|
445151
|
-
}
|
|
445152
|
-
return 0;
|
|
445153
|
-
}
|
|
445154
|
-
function isVersionBelow(version2, minimum3) {
|
|
445155
|
-
const result2 = compareSemver(version2, minimum3);
|
|
445156
|
-
return result2 === -1;
|
|
445157
|
-
}
|
|
445158
|
-
|
|
445159
445288
|
// src/startup-docker-check.ts
|
|
445160
445289
|
var exports_startup_docker_check = {};
|
|
445161
445290
|
__export(exports_startup_docker_check, {
|
|
@@ -451323,7 +451452,7 @@ import { existsSync as existsSync67 } from "node:fs";
|
|
|
451323
451452
|
import { appendFile as appendFile2, chmod as chmod2, mkdir as mkdir17, writeFile as writeFile20 } from "node:fs/promises";
|
|
451324
451453
|
import { homedir as homedir46 } from "node:os";
|
|
451325
451454
|
import { join as join84 } from "node:path";
|
|
451326
|
-
import { promisify as
|
|
451455
|
+
import { promisify as promisify16 } from "node:util";
|
|
451327
451456
|
function buildGitEnv(token2, askpassPath) {
|
|
451328
451457
|
return {
|
|
451329
451458
|
...process.env,
|
|
@@ -451346,7 +451475,7 @@ function formatTokenStatus(token2) {
|
|
|
451346
451475
|
}
|
|
451347
451476
|
async function runGit6(cwd2, args, env4) {
|
|
451348
451477
|
try {
|
|
451349
|
-
await
|
|
451478
|
+
await execFile18("git", args, {
|
|
451350
451479
|
cwd: cwd2,
|
|
451351
451480
|
env: env4,
|
|
451352
451481
|
encoding: "utf-8",
|
|
@@ -451431,11 +451560,11 @@ async function maybeUploadReflectionArenaChoiceToHf(row) {
|
|
|
451431
451560
|
};
|
|
451432
451561
|
}
|
|
451433
451562
|
}
|
|
451434
|
-
var
|
|
451563
|
+
var execFile18, HF_REPO_ID = "letta-ai/reflection-arena", HF_REPO_URL, GIT_TIMEOUT_MS2 = 60000, HF_CACHE_ROOT, HF_REPO_DIR, HF_DATASET_PATH = "data/choices.jsonl";
|
|
451435
451564
|
var init_reflection_arena_hf_upload = __esm(() => {
|
|
451436
451565
|
init_secrets_store();
|
|
451437
451566
|
init_version();
|
|
451438
|
-
|
|
451567
|
+
execFile18 = promisify16(execFileCb5);
|
|
451439
451568
|
HF_REPO_URL = `https://huggingface.co/datasets/${HF_REPO_ID}`;
|
|
451440
451569
|
HF_CACHE_ROOT = join84(homedir46(), ".letta", "reflection-arena", "hf-upload");
|
|
451441
451570
|
HF_REPO_DIR = join84(HF_CACHE_ROOT, "repo");
|
|
@@ -451447,7 +451576,7 @@ import { randomInt as randomInt2, randomUUID as randomUUID37 } from "node:crypto
|
|
|
451447
451576
|
import { appendFile as appendFile3, mkdir as mkdir18, readFile as readFile30, writeFile as writeFile21 } from "node:fs/promises";
|
|
451448
451577
|
import { homedir as homedir47 } from "node:os";
|
|
451449
451578
|
import { join as join85 } from "node:path";
|
|
451450
|
-
import { promisify as
|
|
451579
|
+
import { promisify as promisify17 } from "node:util";
|
|
451451
451580
|
function sampleReflectionArenaComparisonModel(excludedModels = []) {
|
|
451452
451581
|
const excluded = new Set(excludedModels);
|
|
451453
451582
|
const candidates2 = REFLECTION_ARENA_COMPARISON_MODEL_POOL.filter((entry) => !excluded.has(entry.model));
|
|
@@ -451464,7 +451593,7 @@ function sampleReflectionArenaComparisonModel(excludedModels = []) {
|
|
|
451464
451593
|
}
|
|
451465
451594
|
async function getGitOutput(cwd2, args) {
|
|
451466
451595
|
try {
|
|
451467
|
-
const { stdout } = await
|
|
451596
|
+
const { stdout } = await execFile19("git", args, {
|
|
451468
451597
|
cwd: cwd2,
|
|
451469
451598
|
encoding: "utf-8",
|
|
451470
451599
|
timeout: 30000,
|
|
@@ -452039,7 +452168,7 @@ async function finalizeReflectionArenaChoice(options) {
|
|
|
452039
452168
|
run: completedRun
|
|
452040
452169
|
};
|
|
452041
452170
|
}
|
|
452042
|
-
var
|
|
452171
|
+
var execFile19, REFLECTION_ARENA_TELEMETRY_TRANSCRIPT_MAX_CHARS = 1e6, REFLECTION_ARENA_MODEL_A_DEFAULT = "letta/auto-memory", REFLECTION_ARENA_COMPARISON_MODEL_POOL, ANSI_BOLD = "\x1B[1m", ANSI_CYAN = "\x1B[36m", ANSI_MAGENTA = "\x1B[35m", ANSI_RESET_BOLD = "\x1B[22m", ANSI_RESET_FOREGROUND = "\x1B[39m", REFLECTION_ARENA_CANDIDATE_COUNT = 2, REFLECTION_ARENA_CHOICE_QUESTION = "Which reflection should be merged?", REFLECTION_ARENA_NOTES_QUESTION = "Optional feedback for this choice?", updateLocks;
|
|
452043
452172
|
var init_reflection_arena = __esm(() => {
|
|
452044
452173
|
init_memory_filesystem2();
|
|
452045
452174
|
init_memory_worktree();
|
|
@@ -452051,7 +452180,7 @@ var init_reflection_arena = __esm(() => {
|
|
|
452051
452180
|
init_reflection_transcript();
|
|
452052
452181
|
init_telemetry();
|
|
452053
452182
|
init_debug();
|
|
452054
|
-
|
|
452183
|
+
execFile19 = promisify17(execFileCb6);
|
|
452055
452184
|
REFLECTION_ARENA_COMPARISON_MODEL_POOL = [
|
|
452056
452185
|
{ model: "lc-anthropic/claude-sonnet-5", weight: 1 },
|
|
452057
452186
|
{ model: "lc-anthropic/claude-opus-4-8", weight: 3 },
|
|
@@ -453283,6 +453412,14 @@ var init_registry2 = __esm(() => {
|
|
|
453283
453412
|
return "Clearing in-context messages...";
|
|
453284
453413
|
}
|
|
453285
453414
|
},
|
|
453415
|
+
"/clear-messages": {
|
|
453416
|
+
desc: "Reset all agent messages (destructive)",
|
|
453417
|
+
hidden: true,
|
|
453418
|
+
noArgs: true,
|
|
453419
|
+
handler: () => {
|
|
453420
|
+
return "Resetting agent messages...";
|
|
453421
|
+
}
|
|
453422
|
+
},
|
|
453286
453423
|
"/chdir": {
|
|
453287
453424
|
desc: "Change working directory for this TUI session (/chdir <path>)",
|
|
453288
453425
|
args: "<path>",
|
|
@@ -464441,7 +464578,7 @@ import {
|
|
|
464441
464578
|
mkdirSync as mkdirSync46,
|
|
464442
464579
|
mkdtempSync as mkdtempSync6,
|
|
464443
464580
|
readFileSync as readFileSync44,
|
|
464444
|
-
rmSync as
|
|
464581
|
+
rmSync as rmSync18,
|
|
464445
464582
|
writeFileSync as writeFileSync36
|
|
464446
464583
|
} from "node:fs";
|
|
464447
464584
|
import { tmpdir as tmpdir12 } from "node:os";
|
|
@@ -464811,7 +464948,7 @@ async function installGithubApp(options) {
|
|
|
464811
464948
|
agentUrl: resolvedAgentId ? buildAgentReference(resolvedAgentId) : null
|
|
464812
464949
|
};
|
|
464813
464950
|
} finally {
|
|
464814
|
-
|
|
464951
|
+
rmSync18(tempDir, { recursive: true, force: true });
|
|
464815
464952
|
}
|
|
464816
464953
|
}
|
|
464817
464954
|
var DEFAULT_WORKFLOW_PATH = ".github/workflows/letta.yml", ALTERNATE_WORKFLOW_PATH = ".github/workflows/letta-code.yml";
|
|
@@ -468577,7 +468714,7 @@ import { execFile as execFileCb7 } from "node:child_process";
|
|
|
468577
468714
|
import { chmodSync as chmodSync7, existsSync as existsSync70, mkdirSync as mkdirSync47, writeFileSync as writeFileSync37 } from "node:fs";
|
|
468578
468715
|
import { homedir as homedir51 } from "node:os";
|
|
468579
468716
|
import { join as join89 } from "node:path";
|
|
468580
|
-
import { promisify as
|
|
468717
|
+
import { promisify as promisify18 } from "node:util";
|
|
468581
468718
|
function messagesFromOverview(overview) {
|
|
468582
468719
|
return overview.messages?.map((message) => ({
|
|
468583
468720
|
id: message.id,
|
|
@@ -468604,7 +468741,7 @@ function contextFromOverview(overview, model, contextWindow) {
|
|
|
468604
468741
|
}
|
|
468605
468742
|
async function runGitSafe(cwd2, args) {
|
|
468606
468743
|
try {
|
|
468607
|
-
const { stdout } = await
|
|
468744
|
+
const { stdout } = await execFile20("git", args, {
|
|
468608
468745
|
cwd: cwd2,
|
|
468609
468746
|
maxBuffer: 10 * 1024 * 1024,
|
|
468610
468747
|
timeout: 60000
|
|
@@ -468915,7 +469052,7 @@ async function generateAndOpenMemoryViewer(agentId, options) {
|
|
|
468915
469052
|
}
|
|
468916
469053
|
return { filePath, opened: !skipOpen };
|
|
468917
469054
|
}
|
|
468918
|
-
var
|
|
469055
|
+
var execFile20, VIEWERS_DIR, MAX_COMMITS = 500, RECENT_DIFF_COUNT = 50, PER_DIFF_CAP = 1e5, TOTAL_PAYLOAD_CAP = 5000000, RECORD_SEP = "\x1E", REFLECTION_PATTERN;
|
|
468919
469056
|
var init_generate_memory_viewer = __esm(() => {
|
|
468920
469057
|
init_memory_filesystem2();
|
|
468921
469058
|
init_memory_scanner();
|
|
@@ -468926,7 +469063,7 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
468926
469063
|
init_context_usage();
|
|
468927
469064
|
init_local_memory_context();
|
|
468928
469065
|
init_memory_viewer_template();
|
|
468929
|
-
|
|
469066
|
+
execFile20 = promisify18(execFileCb7);
|
|
468930
469067
|
VIEWERS_DIR = join89(homedir51(), ".letta", "viewers");
|
|
468931
469068
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
468932
469069
|
});
|
|
@@ -492346,10 +492483,10 @@ import { execFile as execFileCb8 } from "node:child_process";
|
|
|
492346
492483
|
import { chmodSync as chmodSync8, existsSync as existsSync72, mkdirSync as mkdirSync48, writeFileSync as writeFileSync38 } from "node:fs";
|
|
492347
492484
|
import { homedir as homedir53 } from "node:os";
|
|
492348
492485
|
import { isAbsolute as isAbsolute30, join as join92, resolve as resolve42 } from "node:path";
|
|
492349
|
-
import { promisify as
|
|
492486
|
+
import { promisify as promisify19 } from "node:util";
|
|
492350
492487
|
async function runGit8(cwd2, args) {
|
|
492351
492488
|
try {
|
|
492352
|
-
const { stdout } = await
|
|
492489
|
+
const { stdout } = await execFile21("git", args, {
|
|
492353
492490
|
cwd: cwd2,
|
|
492354
492491
|
maxBuffer: GIT_MAX_BUFFER,
|
|
492355
492492
|
timeout: GIT_TIMEOUT_MS3
|
|
@@ -492584,7 +492721,7 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
492584
492721
|
}
|
|
492585
492722
|
return { filePath, opened: !skipOpen, fileCount: rendered.files.length };
|
|
492586
492723
|
}
|
|
492587
|
-
var
|
|
492724
|
+
var execFile21, VIEWERS_DIR2, GIT_TIMEOUT_MS3 = 60000, GIT_MAX_BUFFER, MAX_RENDERED_FILES = 100, DIFF_UNSAFE_CSS = `
|
|
492588
492725
|
:host {
|
|
492589
492726
|
--diffs-addition-color-override: #15803d;
|
|
492590
492727
|
--diffs-deletion-color-override: #b91c1c;
|
|
@@ -492640,7 +492777,7 @@ var init_generate_diff_viewer = __esm(() => {
|
|
|
492640
492777
|
init_dist15();
|
|
492641
492778
|
init_ssr();
|
|
492642
492779
|
init_diff_viewer_template();
|
|
492643
|
-
|
|
492780
|
+
execFile21 = promisify19(execFileCb8);
|
|
492644
492781
|
VIEWERS_DIR2 = join92(homedir53(), ".letta", "viewers");
|
|
492645
492782
|
GIT_MAX_BUFFER = 50 * 1024 * 1024;
|
|
492646
492783
|
});
|
|
@@ -495030,7 +495167,7 @@ function useConfigurationHandlers(ctx) {
|
|
|
495030
495167
|
registryHandle,
|
|
495031
495168
|
contextWindow: selectedContextWindow,
|
|
495032
495169
|
reasoningCapabilities
|
|
495033
|
-
}) : getReasoningTierOptionsForHandle2(
|
|
495170
|
+
}) : getReasoningTierOptionsForHandle2(registryHandle, selectedContextWindow, reasoningCapabilities);
|
|
495034
495171
|
const reasoningTierOptions = baseReasoningTierOptions.map((option2) => {
|
|
495035
495172
|
const optionModel = models3.find((entry) => entry.id === option2.modelId);
|
|
495036
495173
|
const serviceTier = modelUpdateArgs?.service_tier;
|
|
@@ -502627,10 +502764,10 @@ __export(exports_worktree_diff_list, {
|
|
|
502627
502764
|
});
|
|
502628
502765
|
import { execFile as execFileCb9 } from "node:child_process";
|
|
502629
502766
|
import { basename as basename31 } from "node:path";
|
|
502630
|
-
import { promisify as
|
|
502767
|
+
import { promisify as promisify20 } from "node:util";
|
|
502631
502768
|
async function runGit9(cwd2, args) {
|
|
502632
502769
|
try {
|
|
502633
|
-
const { stdout } = await
|
|
502770
|
+
const { stdout } = await execFile22("git", args, {
|
|
502634
502771
|
cwd: cwd2,
|
|
502635
502772
|
maxBuffer: GIT_MAX_BUFFER2,
|
|
502636
502773
|
timeout: GIT_TIMEOUT_MS4
|
|
@@ -502759,9 +502896,9 @@ async function listWorktreeDiffOptions(cwd2 = process.cwd()) {
|
|
|
502759
502896
|
const worktrees = parseWorktreeList(output, currentPath);
|
|
502760
502897
|
return Promise.all(worktrees.map((worktree) => summarizeWorktree(worktree)));
|
|
502761
502898
|
}
|
|
502762
|
-
var
|
|
502899
|
+
var execFile22, GIT_TIMEOUT_MS4 = 60000, GIT_MAX_BUFFER2;
|
|
502763
502900
|
var init_worktree_diff_list = __esm(() => {
|
|
502764
|
-
|
|
502901
|
+
execFile22 = promisify20(execFileCb9);
|
|
502765
502902
|
GIT_MAX_BUFFER2 = 10 * 1024 * 1024;
|
|
502766
502903
|
});
|
|
502767
502904
|
|
|
@@ -504039,15 +504176,19 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
504039
504176
|
});
|
|
504040
504177
|
return { submitted: true };
|
|
504041
504178
|
}
|
|
504042
|
-
|
|
504043
|
-
|
|
504179
|
+
const resetAllAgentMessages = trimmed === "/clear-messages";
|
|
504180
|
+
if (trimmed === "/clear" || resetAllAgentMessages) {
|
|
504181
|
+
const cmd = commandRunner.start(trimmed, resetAllAgentMessages ? "Resetting agent messages..." : "Clearing in-context messages...");
|
|
504044
504182
|
resetPendingReasoningCycle();
|
|
504045
504183
|
setCommandRunning(true);
|
|
504046
504184
|
const clearPrevConversationId = conversationIdRef.current;
|
|
504047
|
-
await runEndHooks("new");
|
|
504048
504185
|
try {
|
|
504049
504186
|
const backend3 = getBackend();
|
|
504050
|
-
if (
|
|
504187
|
+
if (resetAllAgentMessages && backend3.capabilities.localModelCatalog) {
|
|
504188
|
+
throw new Error("/clear-messages is unsupported by local backend.");
|
|
504189
|
+
}
|
|
504190
|
+
await runEndHooks("new");
|
|
504191
|
+
if (!backend3.capabilities.localModelCatalog && (resetAllAgentMessages || conversationIdRef.current === "default")) {
|
|
504051
504192
|
const client = await getClient();
|
|
504052
504193
|
await client.agents.messages.reset(agentId, {
|
|
504053
504194
|
add_default_initial_messages: false
|
|
@@ -504081,7 +504222,7 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
504081
504222
|
previousConversationId: clearPrevConversationId ?? null,
|
|
504082
504223
|
reason: "new"
|
|
504083
504224
|
}, modAdapter.context);
|
|
504084
|
-
cmd.finish("Agent's in-context messages cleared & moved to conversation history", true);
|
|
504225
|
+
cmd.finish(resetAllAgentMessages ? "All agent messages reset" : "Agent's in-context messages cleared & moved to conversation history", true);
|
|
504085
504226
|
} catch (error5) {
|
|
504086
504227
|
const errorDetails = formatErrorDetails2(error5, agentId);
|
|
504087
504228
|
cmd.fail(`Failed: ${errorDetails}`);
|
|
@@ -510717,6 +510858,7 @@ var init_src5 = __esm(async () => {
|
|
|
510717
510858
|
init_terminal_theme();
|
|
510718
510859
|
init_startup_backend_mode();
|
|
510719
510860
|
init_startup();
|
|
510861
|
+
init_runtime_version();
|
|
510720
510862
|
init_settings_manager();
|
|
510721
510863
|
init_startup_auto_update();
|
|
510722
510864
|
init_debug();
|
|
@@ -510730,6 +510872,7 @@ var init_src5 = __esm(async () => {
|
|
|
510730
510872
|
]);
|
|
510731
510873
|
EMPTY_APPROVAL_ARRAY = [];
|
|
510732
510874
|
EMPTY_MESSAGE_ARRAY = [];
|
|
510875
|
+
assertSupportedBunRuntime();
|
|
510733
510876
|
main2();
|
|
510734
510877
|
});
|
|
510735
510878
|
// node_modules/@earendil-works/pi-ai/dist/auth/oauth/oauth-page.js
|
|
@@ -512927,4 +513070,4 @@ function registerBunOAuthFlows() {
|
|
|
512927
513070
|
registerBunOAuthFlows();
|
|
512928
513071
|
await init_src5().then(() => exports_src2);
|
|
512929
513072
|
|
|
512930
|
-
//# debugId=
|
|
513073
|
+
//# debugId=67341FA9FF6344CE64756E2164756E21
|