@letta-ai/letta-code 0.12.0 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +889 -179
- package/package.json +1 -1
package/letta.js
CHANGED
|
@@ -3237,7 +3237,7 @@ var package_default;
|
|
|
3237
3237
|
var init_package = __esm(() => {
|
|
3238
3238
|
package_default = {
|
|
3239
3239
|
name: "@letta-ai/letta-code",
|
|
3240
|
-
version: "0.12.
|
|
3240
|
+
version: "0.12.2",
|
|
3241
3241
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3242
3242
|
type: "module",
|
|
3243
3243
|
bin: {
|
|
@@ -29951,6 +29951,10 @@ var init_WelcomeScreen = __esm(async () => {
|
|
|
29951
29951
|
});
|
|
29952
29952
|
|
|
29953
29953
|
// src/permissions/readOnlyShell.ts
|
|
29954
|
+
function isReadOnlySkillScript(scriptPath) {
|
|
29955
|
+
const normalized = scriptPath.replace(/\\/g, "/");
|
|
29956
|
+
return BUNDLED_READ_ONLY_SCRIPTS.some((pattern) => normalized.endsWith(pattern));
|
|
29957
|
+
}
|
|
29954
29958
|
function isReadOnlyShellCommand(command) {
|
|
29955
29959
|
if (!command) {
|
|
29956
29960
|
return false;
|
|
@@ -30018,6 +30022,13 @@ function isSafeSegment(segment) {
|
|
|
30018
30022
|
if (command === "sort") {
|
|
30019
30023
|
return !/\s-o\b/.test(segment);
|
|
30020
30024
|
}
|
|
30025
|
+
if (command === "npx" && tokens[1] === "tsx") {
|
|
30026
|
+
const scriptPath = tokens[2];
|
|
30027
|
+
if (scriptPath && isReadOnlySkillScript(scriptPath)) {
|
|
30028
|
+
return true;
|
|
30029
|
+
}
|
|
30030
|
+
return false;
|
|
30031
|
+
}
|
|
30021
30032
|
return false;
|
|
30022
30033
|
}
|
|
30023
30034
|
return true;
|
|
@@ -30050,7 +30061,7 @@ function extractDashCArgument(tokens) {
|
|
|
30050
30061
|
}
|
|
30051
30062
|
return;
|
|
30052
30063
|
}
|
|
30053
|
-
var ALWAYS_SAFE_COMMANDS, SAFE_GIT_SUBCOMMANDS, DANGEROUS_OPERATOR_PATTERN;
|
|
30064
|
+
var ALWAYS_SAFE_COMMANDS, SAFE_GIT_SUBCOMMANDS, BUNDLED_READ_ONLY_SCRIPTS, DANGEROUS_OPERATOR_PATTERN;
|
|
30054
30065
|
var init_readOnlyShell = __esm(() => {
|
|
30055
30066
|
ALWAYS_SAFE_COMMANDS = new Set([
|
|
30056
30067
|
"cat",
|
|
@@ -30113,6 +30124,12 @@ var init_readOnlyShell = __esm(() => {
|
|
|
30113
30124
|
"tag",
|
|
30114
30125
|
"remote"
|
|
30115
30126
|
]);
|
|
30127
|
+
BUNDLED_READ_ONLY_SCRIPTS = [
|
|
30128
|
+
"/skills/searching-messages/scripts/search-messages.ts",
|
|
30129
|
+
"/skills/searching-messages/scripts/get-messages.ts",
|
|
30130
|
+
"/skills/builtin/searching-messages/scripts/search-messages.ts",
|
|
30131
|
+
"/skills/builtin/searching-messages/scripts/get-messages.ts"
|
|
30132
|
+
];
|
|
30116
30133
|
DANGEROUS_OPERATOR_PATTERN = /(>>|>|\$\(|`)/;
|
|
30117
30134
|
});
|
|
30118
30135
|
|
|
@@ -31629,6 +31646,46 @@ Remember: You're planning, not implementing. Don't make changes, just create a r
|
|
|
31629
31646
|
`;
|
|
31630
31647
|
var init_plan = () => {};
|
|
31631
31648
|
|
|
31649
|
+
// src/agent/subagents/builtin/recall.md
|
|
31650
|
+
var recall_default = `---
|
|
31651
|
+
name: recall
|
|
31652
|
+
description: Search conversation history to recall past discussions, decisions, and context
|
|
31653
|
+
tools: Skill, Bash, Read, BashOutput
|
|
31654
|
+
model: haiku
|
|
31655
|
+
memoryBlocks: human, persona
|
|
31656
|
+
mode: stateless
|
|
31657
|
+
---
|
|
31658
|
+
|
|
31659
|
+
You are a subagent launched via the Task tool to search conversation history. You run autonomously and return a single final report when done. You CANNOT ask questions mid-execution.
|
|
31660
|
+
|
|
31661
|
+
## Instructions
|
|
31662
|
+
|
|
31663
|
+
### Step 1: Load the searching-messages skill
|
|
31664
|
+
\`\`\`
|
|
31665
|
+
Skill({ command: "load", skills: ["searching-messages"] })
|
|
31666
|
+
\`\`\`
|
|
31667
|
+
|
|
31668
|
+
The skill content will appear in your loaded_skills block with script paths and search strategies.
|
|
31669
|
+
|
|
31670
|
+
### Step 2: Search the parent agent's history
|
|
31671
|
+
|
|
31672
|
+
**CRITICAL - Two rules:**
|
|
31673
|
+
|
|
31674
|
+
1. **DO NOT use \`conversation_search\`** - That tool only searches YOUR history (empty). You MUST use the Bash scripts from the skill.
|
|
31675
|
+
|
|
31676
|
+
2. **ALWAYS add \`--agent-id $LETTA_PARENT_AGENT_ID\`** - This searches the parent agent's history. The only exception is \`--all-agents\` searches.
|
|
31677
|
+
|
|
31678
|
+
Follow the strategies documented in the loaded skill.
|
|
31679
|
+
|
|
31680
|
+
## Output Format
|
|
31681
|
+
|
|
31682
|
+
1. **Direct answer** - What the user asked about
|
|
31683
|
+
2. **Key findings** - Relevant quotes or summaries from past conversations
|
|
31684
|
+
3. **When discussed** - Timestamps of relevant discussions
|
|
31685
|
+
4. **Outcome/Decision** - What was decided or concluded (if applicable)
|
|
31686
|
+
`;
|
|
31687
|
+
var init_recall = () => {};
|
|
31688
|
+
|
|
31632
31689
|
// src/agent/subagents/index.ts
|
|
31633
31690
|
var exports_subagents = {};
|
|
31634
31691
|
__export(exports_subagents, {
|
|
@@ -31793,7 +31850,13 @@ var init_subagents = __esm(() => {
|
|
|
31793
31850
|
init_explore();
|
|
31794
31851
|
init_general_purpose();
|
|
31795
31852
|
init_plan();
|
|
31796
|
-
|
|
31853
|
+
init_recall();
|
|
31854
|
+
BUILTIN_SOURCES = [
|
|
31855
|
+
explore_default,
|
|
31856
|
+
general_purpose_default,
|
|
31857
|
+
plan_default,
|
|
31858
|
+
recall_default
|
|
31859
|
+
];
|
|
31797
31860
|
GLOBAL_AGENTS_DIR = join3(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
|
|
31798
31861
|
VALID_MEMORY_BLOCKS = new Set(MEMORY_BLOCK_LABELS);
|
|
31799
31862
|
cache3 = {
|
|
@@ -33424,6 +33487,82 @@ var init_shellEnv = __esm(async () => {
|
|
|
33424
33487
|
await init_settings_manager();
|
|
33425
33488
|
});
|
|
33426
33489
|
|
|
33490
|
+
// src/tools/impl/shellLaunchers.ts
|
|
33491
|
+
function pushUnique(list, seen, entry) {
|
|
33492
|
+
if (!entry.length || !entry[0])
|
|
33493
|
+
return;
|
|
33494
|
+
const key = entry.join(SEP2);
|
|
33495
|
+
if (seen.has(key))
|
|
33496
|
+
return;
|
|
33497
|
+
seen.add(key);
|
|
33498
|
+
list.push(entry);
|
|
33499
|
+
}
|
|
33500
|
+
function windowsLaunchers(command) {
|
|
33501
|
+
const trimmed = command.trim();
|
|
33502
|
+
if (!trimmed)
|
|
33503
|
+
return [];
|
|
33504
|
+
const launchers = [];
|
|
33505
|
+
const seen = new Set;
|
|
33506
|
+
pushUnique(launchers, seen, [
|
|
33507
|
+
"powershell.exe",
|
|
33508
|
+
"-NoProfile",
|
|
33509
|
+
"-Command",
|
|
33510
|
+
trimmed
|
|
33511
|
+
]);
|
|
33512
|
+
pushUnique(launchers, seen, ["pwsh", "-NoProfile", "-Command", trimmed]);
|
|
33513
|
+
const envComSpecRaw = process.env.ComSpec || process.env.COMSPEC;
|
|
33514
|
+
const envComSpec = envComSpecRaw?.trim();
|
|
33515
|
+
if (envComSpec) {
|
|
33516
|
+
pushUnique(launchers, seen, [envComSpec, "/d", "/s", "/c", trimmed]);
|
|
33517
|
+
}
|
|
33518
|
+
pushUnique(launchers, seen, ["cmd.exe", "/d", "/s", "/c", trimmed]);
|
|
33519
|
+
return launchers;
|
|
33520
|
+
}
|
|
33521
|
+
function unixLaunchers(command) {
|
|
33522
|
+
const trimmed = command.trim();
|
|
33523
|
+
if (!trimmed)
|
|
33524
|
+
return [];
|
|
33525
|
+
const launchers = [];
|
|
33526
|
+
const seen = new Set;
|
|
33527
|
+
if (process.platform === "darwin") {
|
|
33528
|
+
pushUnique(launchers, seen, ["/bin/zsh", "-c", trimmed]);
|
|
33529
|
+
}
|
|
33530
|
+
const envShell = process.env.SHELL?.trim();
|
|
33531
|
+
if (envShell) {
|
|
33532
|
+
pushUnique(launchers, seen, [envShell, "-c", trimmed]);
|
|
33533
|
+
}
|
|
33534
|
+
const defaults2 = process.platform === "darwin" ? [
|
|
33535
|
+
["/bin/zsh", "-c", trimmed],
|
|
33536
|
+
["bash", "-c", trimmed],
|
|
33537
|
+
["/bin/bash", "-c", trimmed],
|
|
33538
|
+
["/usr/bin/bash", "-c", trimmed],
|
|
33539
|
+
["/bin/sh", "-c", trimmed],
|
|
33540
|
+
["/bin/ash", "-c", trimmed],
|
|
33541
|
+
["/usr/bin/env", "zsh", "-c", trimmed],
|
|
33542
|
+
["/usr/bin/env", "bash", "-c", trimmed],
|
|
33543
|
+
["/usr/bin/env", "sh", "-c", trimmed],
|
|
33544
|
+
["/usr/bin/env", "ash", "-c", trimmed]
|
|
33545
|
+
] : [
|
|
33546
|
+
["/bin/bash", "-c", trimmed],
|
|
33547
|
+
["/usr/bin/bash", "-c", trimmed],
|
|
33548
|
+
["/bin/zsh", "-c", trimmed],
|
|
33549
|
+
["/bin/sh", "-c", trimmed],
|
|
33550
|
+
["/bin/ash", "-c", trimmed],
|
|
33551
|
+
["/usr/bin/env", "bash", "-c", trimmed],
|
|
33552
|
+
["/usr/bin/env", "zsh", "-c", trimmed],
|
|
33553
|
+
["/usr/bin/env", "sh", "-c", trimmed],
|
|
33554
|
+
["/usr/bin/env", "ash", "-c", trimmed]
|
|
33555
|
+
];
|
|
33556
|
+
for (const entry of defaults2) {
|
|
33557
|
+
pushUnique(launchers, seen, entry);
|
|
33558
|
+
}
|
|
33559
|
+
return launchers;
|
|
33560
|
+
}
|
|
33561
|
+
function buildShellLaunchers(command) {
|
|
33562
|
+
return process.platform === "win32" ? windowsLaunchers(command) : unixLaunchers(command);
|
|
33563
|
+
}
|
|
33564
|
+
var SEP2 = "\x00";
|
|
33565
|
+
|
|
33427
33566
|
// src/tools/impl/truncation.ts
|
|
33428
33567
|
function truncateByChars(text, maxChars, _toolName = "output") {
|
|
33429
33568
|
if (text.length <= maxChars) {
|
|
@@ -33457,35 +33596,24 @@ __export(exports_Bash, {
|
|
|
33457
33596
|
bash: () => bash
|
|
33458
33597
|
});
|
|
33459
33598
|
import { spawn } from "node:child_process";
|
|
33460
|
-
|
|
33461
|
-
|
|
33462
|
-
|
|
33463
|
-
|
|
33464
|
-
|
|
33465
|
-
|
|
33466
|
-
cachedShellConfig = {
|
|
33467
|
-
executable: "powershell.exe",
|
|
33468
|
-
args: (cmd) => ["-NoProfile", "-Command", cmd]
|
|
33469
|
-
};
|
|
33470
|
-
return cachedShellConfig;
|
|
33471
|
-
}
|
|
33472
|
-
if (process.platform === "darwin" && existsSync4("/bin/zsh")) {
|
|
33473
|
-
cachedShellConfig = {
|
|
33474
|
-
executable: "/bin/zsh",
|
|
33475
|
-
args: (cmd) => ["-c", cmd]
|
|
33476
|
-
};
|
|
33477
|
-
return cachedShellConfig;
|
|
33599
|
+
function getBackgroundLauncher(command) {
|
|
33600
|
+
if (cachedWorkingLauncher) {
|
|
33601
|
+
const [executable, ...launcherArgs] = cachedWorkingLauncher;
|
|
33602
|
+
if (executable) {
|
|
33603
|
+
return [executable, ...launcherArgs.slice(0, -1), command];
|
|
33604
|
+
}
|
|
33478
33605
|
}
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
args: (cmd) => ["-c", cmd]
|
|
33482
|
-
};
|
|
33483
|
-
return cachedShellConfig;
|
|
33606
|
+
const launchers = buildShellLaunchers(command);
|
|
33607
|
+
return launchers[0] || [];
|
|
33484
33608
|
}
|
|
33485
|
-
function
|
|
33609
|
+
function spawnWithLauncher(launcher, options) {
|
|
33486
33610
|
return new Promise((resolve2, reject) => {
|
|
33487
|
-
const
|
|
33488
|
-
|
|
33611
|
+
const [executable, ...args] = launcher;
|
|
33612
|
+
if (!executable) {
|
|
33613
|
+
reject(new Error("Empty launcher"));
|
|
33614
|
+
return;
|
|
33615
|
+
}
|
|
33616
|
+
const childProcess = spawn(executable, args, {
|
|
33489
33617
|
cwd: options.cwd,
|
|
33490
33618
|
env: options.env,
|
|
33491
33619
|
shell: false,
|
|
@@ -33547,6 +33675,52 @@ function spawnCommand(command, options) {
|
|
|
33547
33675
|
});
|
|
33548
33676
|
});
|
|
33549
33677
|
}
|
|
33678
|
+
async function spawnCommand(command, options) {
|
|
33679
|
+
if (process.platform !== "win32") {
|
|
33680
|
+
const executable = process.platform === "darwin" ? "/bin/zsh" : "bash";
|
|
33681
|
+
return spawnWithLauncher([executable, "-c", command], options);
|
|
33682
|
+
}
|
|
33683
|
+
if (cachedWorkingLauncher) {
|
|
33684
|
+
const [executable, ...launcherArgs] = cachedWorkingLauncher;
|
|
33685
|
+
if (executable) {
|
|
33686
|
+
const newLauncher = [executable, ...launcherArgs.slice(0, -1), command];
|
|
33687
|
+
try {
|
|
33688
|
+
const result = await spawnWithLauncher(newLauncher, options);
|
|
33689
|
+
return result;
|
|
33690
|
+
} catch (error) {
|
|
33691
|
+
const err = error;
|
|
33692
|
+
if (err.code !== "ENOENT") {
|
|
33693
|
+
throw error;
|
|
33694
|
+
}
|
|
33695
|
+
cachedWorkingLauncher = null;
|
|
33696
|
+
}
|
|
33697
|
+
}
|
|
33698
|
+
}
|
|
33699
|
+
const launchers = buildShellLaunchers(command);
|
|
33700
|
+
if (launchers.length === 0) {
|
|
33701
|
+
throw new Error("No shell launchers available");
|
|
33702
|
+
}
|
|
33703
|
+
const tried = [];
|
|
33704
|
+
let lastError = null;
|
|
33705
|
+
for (const launcher of launchers) {
|
|
33706
|
+
try {
|
|
33707
|
+
const result = await spawnWithLauncher(launcher, options);
|
|
33708
|
+
cachedWorkingLauncher = launcher;
|
|
33709
|
+
return result;
|
|
33710
|
+
} catch (error) {
|
|
33711
|
+
const err = error;
|
|
33712
|
+
if (err.code === "ENOENT") {
|
|
33713
|
+
tried.push(launcher[0] || "unknown");
|
|
33714
|
+
lastError = err;
|
|
33715
|
+
continue;
|
|
33716
|
+
}
|
|
33717
|
+
throw error;
|
|
33718
|
+
}
|
|
33719
|
+
}
|
|
33720
|
+
const suffix = tried.filter(Boolean).join(", ");
|
|
33721
|
+
const reason = lastError?.message || "Shell unavailable";
|
|
33722
|
+
throw new Error(suffix ? `${reason} (tried: ${suffix})` : reason);
|
|
33723
|
+
}
|
|
33550
33724
|
async function bash(args) {
|
|
33551
33725
|
validateRequiredParams(args, ["command"], "Bash");
|
|
33552
33726
|
const {
|
|
@@ -33578,8 +33752,15 @@ async function bash(args) {
|
|
|
33578
33752
|
}
|
|
33579
33753
|
if (run_in_background) {
|
|
33580
33754
|
const bashId = getNextBashId();
|
|
33581
|
-
const
|
|
33582
|
-
const
|
|
33755
|
+
const launcher = getBackgroundLauncher(command);
|
|
33756
|
+
const [executable, ...launcherArgs] = launcher;
|
|
33757
|
+
if (!executable) {
|
|
33758
|
+
return {
|
|
33759
|
+
content: [{ type: "text", text: "No shell available" }],
|
|
33760
|
+
status: "error"
|
|
33761
|
+
};
|
|
33762
|
+
}
|
|
33763
|
+
const childProcess = spawn(executable, launcherArgs, {
|
|
33583
33764
|
shell: false,
|
|
33584
33765
|
cwd: userCwd,
|
|
33585
33766
|
env: getShellEnv()
|
|
@@ -33692,7 +33873,7 @@ ${errorMessage}`;
|
|
|
33692
33873
|
};
|
|
33693
33874
|
}
|
|
33694
33875
|
}
|
|
33695
|
-
var
|
|
33876
|
+
var cachedWorkingLauncher = null;
|
|
33696
33877
|
var init_Bash2 = __esm(async () => {
|
|
33697
33878
|
init_constants();
|
|
33698
33879
|
init_process_manager();
|
|
@@ -34017,6 +34198,20 @@ class PermissionModeManager2 {
|
|
|
34017
34198
|
return "allow";
|
|
34018
34199
|
}
|
|
34019
34200
|
}
|
|
34201
|
+
const readOnlySubagentTypes = new Set([
|
|
34202
|
+
"explore",
|
|
34203
|
+
"Explore",
|
|
34204
|
+
"plan",
|
|
34205
|
+
"Plan",
|
|
34206
|
+
"recall",
|
|
34207
|
+
"Recall"
|
|
34208
|
+
]);
|
|
34209
|
+
if (toolName === "Task" || toolName === "task") {
|
|
34210
|
+
const subagentType = toolArgs?.subagent_type;
|
|
34211
|
+
if (subagentType && readOnlySubagentTypes.has(subagentType)) {
|
|
34212
|
+
return "allow";
|
|
34213
|
+
}
|
|
34214
|
+
}
|
|
34020
34215
|
const shellTools = [
|
|
34021
34216
|
"Bash",
|
|
34022
34217
|
"shell",
|
|
@@ -42096,69 +42291,6 @@ var init_SearchFileContentGemini2 = __esm(() => {
|
|
|
42096
42291
|
init_Grep2();
|
|
42097
42292
|
});
|
|
42098
42293
|
|
|
42099
|
-
// src/tools/impl/shellLaunchers.ts
|
|
42100
|
-
function pushUnique(list, seen, entry) {
|
|
42101
|
-
if (!entry.length || !entry[0])
|
|
42102
|
-
return;
|
|
42103
|
-
const key = entry.join(SEP2);
|
|
42104
|
-
if (seen.has(key))
|
|
42105
|
-
return;
|
|
42106
|
-
seen.add(key);
|
|
42107
|
-
list.push(entry);
|
|
42108
|
-
}
|
|
42109
|
-
function windowsLaunchers(command) {
|
|
42110
|
-
const trimmed = command.trim();
|
|
42111
|
-
if (!trimmed)
|
|
42112
|
-
return [];
|
|
42113
|
-
const launchers = [];
|
|
42114
|
-
const seen = new Set;
|
|
42115
|
-
pushUnique(launchers, seen, [
|
|
42116
|
-
"powershell.exe",
|
|
42117
|
-
"-NoProfile",
|
|
42118
|
-
"-Command",
|
|
42119
|
-
trimmed
|
|
42120
|
-
]);
|
|
42121
|
-
pushUnique(launchers, seen, ["pwsh", "-NoProfile", "-Command", trimmed]);
|
|
42122
|
-
const envComSpecRaw = process.env.ComSpec || process.env.COMSPEC;
|
|
42123
|
-
const envComSpec = envComSpecRaw?.trim();
|
|
42124
|
-
if (envComSpec) {
|
|
42125
|
-
pushUnique(launchers, seen, [envComSpec, "/d", "/s", "/c", trimmed]);
|
|
42126
|
-
}
|
|
42127
|
-
pushUnique(launchers, seen, ["cmd.exe", "/d", "/s", "/c", trimmed]);
|
|
42128
|
-
return launchers;
|
|
42129
|
-
}
|
|
42130
|
-
function unixLaunchers(command) {
|
|
42131
|
-
const trimmed = command.trim();
|
|
42132
|
-
if (!trimmed)
|
|
42133
|
-
return [];
|
|
42134
|
-
const launchers = [];
|
|
42135
|
-
const seen = new Set;
|
|
42136
|
-
const envShell = process.env.SHELL?.trim();
|
|
42137
|
-
if (envShell) {
|
|
42138
|
-
pushUnique(launchers, seen, [envShell, "-lc", trimmed]);
|
|
42139
|
-
pushUnique(launchers, seen, [envShell, "-c", trimmed]);
|
|
42140
|
-
}
|
|
42141
|
-
const defaults3 = [
|
|
42142
|
-
["/bin/bash", "-lc", trimmed],
|
|
42143
|
-
["/usr/bin/bash", "-lc", trimmed],
|
|
42144
|
-
["/bin/zsh", "-lc", trimmed],
|
|
42145
|
-
["/bin/sh", "-c", trimmed],
|
|
42146
|
-
["/bin/ash", "-c", trimmed],
|
|
42147
|
-
["/usr/bin/env", "bash", "-lc", trimmed],
|
|
42148
|
-
["/usr/bin/env", "zsh", "-lc", trimmed],
|
|
42149
|
-
["/usr/bin/env", "sh", "-c", trimmed],
|
|
42150
|
-
["/usr/bin/env", "ash", "-c", trimmed]
|
|
42151
|
-
];
|
|
42152
|
-
for (const entry of defaults3) {
|
|
42153
|
-
pushUnique(launchers, seen, entry);
|
|
42154
|
-
}
|
|
42155
|
-
return launchers;
|
|
42156
|
-
}
|
|
42157
|
-
function buildShellLaunchers(command) {
|
|
42158
|
-
return process.platform === "win32" ? windowsLaunchers(command) : unixLaunchers(command);
|
|
42159
|
-
}
|
|
42160
|
-
var SEP2 = "\x00";
|
|
42161
|
-
|
|
42162
42294
|
// src/tools/impl/Shell.ts
|
|
42163
42295
|
import { spawn as spawn2 } from "node:child_process";
|
|
42164
42296
|
import * as path12 from "node:path";
|
|
@@ -42363,7 +42495,7 @@ __export(exports_skills, {
|
|
|
42363
42495
|
SKILLS_DIR: () => SKILLS_DIR,
|
|
42364
42496
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR
|
|
42365
42497
|
});
|
|
42366
|
-
import { existsSync as
|
|
42498
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
42367
42499
|
import { readdir as readdir4, readFile as readFile3 } from "node:fs/promises";
|
|
42368
42500
|
import { dirname as dirname4, join as join7 } from "node:path";
|
|
42369
42501
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
@@ -42381,7 +42513,7 @@ async function getBundledSkills() {
|
|
|
42381
42513
|
}
|
|
42382
42514
|
async function discoverSkillsFromDir(skillsPath, source) {
|
|
42383
42515
|
const errors = [];
|
|
42384
|
-
if (!
|
|
42516
|
+
if (!existsSync4(skillsPath)) {
|
|
42385
42517
|
return { skills: [], errors: [] };
|
|
42386
42518
|
}
|
|
42387
42519
|
const skills = [];
|
|
@@ -43281,11 +43413,16 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
|
|
|
43281
43413
|
try {
|
|
43282
43414
|
const cliArgs = buildSubagentArgs(type, config, model, userPrompt);
|
|
43283
43415
|
const lettaCmd = process.env.LETTA_CODE_BIN || "letta";
|
|
43416
|
+
let parentAgentId;
|
|
43417
|
+
try {
|
|
43418
|
+
parentAgentId = getCurrentAgentId();
|
|
43419
|
+
} catch {}
|
|
43284
43420
|
const proc2 = spawn3(lettaCmd, cliArgs, {
|
|
43285
43421
|
cwd: process.cwd(),
|
|
43286
43422
|
env: {
|
|
43287
43423
|
...process.env,
|
|
43288
|
-
LETTA_CODE_AGENT_ROLE: "subagent"
|
|
43424
|
+
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
43425
|
+
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
43289
43426
|
}
|
|
43290
43427
|
});
|
|
43291
43428
|
let wasAborted = false;
|
|
@@ -44943,7 +45080,7 @@ __export(exports_skills2, {
|
|
|
44943
45080
|
SKILLS_DIR: () => SKILLS_DIR2,
|
|
44944
45081
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
44945
45082
|
});
|
|
44946
|
-
import { existsSync as
|
|
45083
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
44947
45084
|
import { readdir as readdir5, readFile as readFile5 } from "node:fs/promises";
|
|
44948
45085
|
import { dirname as dirname7, join as join9 } from "node:path";
|
|
44949
45086
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
@@ -44961,7 +45098,7 @@ async function getBundledSkills2() {
|
|
|
44961
45098
|
}
|
|
44962
45099
|
async function discoverSkillsFromDir2(skillsPath, source) {
|
|
44963
45100
|
const errors = [];
|
|
44964
|
-
if (!
|
|
45101
|
+
if (!existsSync5(skillsPath)) {
|
|
44965
45102
|
return { skills: [], errors: [] };
|
|
44966
45103
|
}
|
|
44967
45104
|
const skills = [];
|
|
@@ -45201,7 +45338,7 @@ __export(exports_fs, {
|
|
|
45201
45338
|
exists: () => exists2
|
|
45202
45339
|
});
|
|
45203
45340
|
import {
|
|
45204
|
-
existsSync as
|
|
45341
|
+
existsSync as existsSync6,
|
|
45205
45342
|
readFileSync as fsReadFileSync2,
|
|
45206
45343
|
writeFileSync as fsWriteFileSync2,
|
|
45207
45344
|
mkdirSync as mkdirSync2
|
|
@@ -45212,13 +45349,13 @@ async function readFile6(path14) {
|
|
|
45212
45349
|
}
|
|
45213
45350
|
async function writeFile2(path14, content) {
|
|
45214
45351
|
const dir = dirname8(path14);
|
|
45215
|
-
if (!
|
|
45352
|
+
if (!existsSync6(dir)) {
|
|
45216
45353
|
mkdirSync2(dir, { recursive: true });
|
|
45217
45354
|
}
|
|
45218
45355
|
fsWriteFileSync2(path14, content, { encoding: "utf-8", flush: true });
|
|
45219
45356
|
}
|
|
45220
45357
|
function exists2(path14) {
|
|
45221
|
-
return
|
|
45358
|
+
return existsSync6(path14);
|
|
45222
45359
|
}
|
|
45223
45360
|
async function mkdir2(path14, options) {
|
|
45224
45361
|
mkdirSync2(path14, options);
|
|
@@ -45490,7 +45627,7 @@ __export(exports_subagents2, {
|
|
|
45490
45627
|
GLOBAL_AGENTS_DIR: () => GLOBAL_AGENTS_DIR2,
|
|
45491
45628
|
AGENTS_DIR: () => AGENTS_DIR2
|
|
45492
45629
|
});
|
|
45493
|
-
import { existsSync as
|
|
45630
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
45494
45631
|
import { readdir as readdir6, readFile as readFile7 } from "node:fs/promises";
|
|
45495
45632
|
import { join as join10 } from "node:path";
|
|
45496
45633
|
function isValidName2(name) {
|
|
@@ -45573,7 +45710,7 @@ function getBuiltinSubagentNames2() {
|
|
|
45573
45710
|
return new Set(Object.keys(getBuiltinSubagents2()));
|
|
45574
45711
|
}
|
|
45575
45712
|
async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors) {
|
|
45576
|
-
if (!
|
|
45713
|
+
if (!existsSync7(agentsDir)) {
|
|
45577
45714
|
return;
|
|
45578
45715
|
}
|
|
45579
45716
|
try {
|
|
@@ -45644,7 +45781,13 @@ var init_subagents2 = __esm(() => {
|
|
|
45644
45781
|
init_explore();
|
|
45645
45782
|
init_general_purpose();
|
|
45646
45783
|
init_plan();
|
|
45647
|
-
|
|
45784
|
+
init_recall();
|
|
45785
|
+
BUILTIN_SOURCES2 = [
|
|
45786
|
+
explore_default,
|
|
45787
|
+
general_purpose_default,
|
|
45788
|
+
plan_default,
|
|
45789
|
+
recall_default
|
|
45790
|
+
];
|
|
45648
45791
|
GLOBAL_AGENTS_DIR2 = join10(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
|
|
45649
45792
|
VALID_MEMORY_BLOCKS2 = new Set(MEMORY_BLOCK_LABELS);
|
|
45650
45793
|
cache4 = {
|
|
@@ -48326,7 +48469,9 @@ var init_checker = __esm(() => {
|
|
|
48326
48469
|
"explore",
|
|
48327
48470
|
"Explore",
|
|
48328
48471
|
"plan",
|
|
48329
|
-
"Plan"
|
|
48472
|
+
"Plan",
|
|
48473
|
+
"recall",
|
|
48474
|
+
"Recall"
|
|
48330
48475
|
]);
|
|
48331
48476
|
});
|
|
48332
48477
|
|
|
@@ -49510,7 +49655,7 @@ var init_create = __esm(async () => {
|
|
|
49510
49655
|
});
|
|
49511
49656
|
|
|
49512
49657
|
// src/agent/message.ts
|
|
49513
|
-
async function sendMessageStream(agentId, messages, opts = { streamTokens: true, background: true }) {
|
|
49658
|
+
async function sendMessageStream(agentId, messages, opts = { streamTokens: true, background: true }, requestOptions = { maxRetries: 0 }) {
|
|
49514
49659
|
const client = await getClient2();
|
|
49515
49660
|
return client.agents.messages.create(agentId, {
|
|
49516
49661
|
messages,
|
|
@@ -49518,7 +49663,7 @@ async function sendMessageStream(agentId, messages, opts = { streamTokens: true,
|
|
|
49518
49663
|
stream_tokens: opts.streamTokens ?? true,
|
|
49519
49664
|
background: opts.background ?? true,
|
|
49520
49665
|
client_tools: getClientToolsFromRegistry()
|
|
49521
|
-
});
|
|
49666
|
+
}, requestOptions);
|
|
49522
49667
|
}
|
|
49523
49668
|
var init_message = __esm(async () => {
|
|
49524
49669
|
await __promiseAll([
|
|
@@ -49636,8 +49781,10 @@ function markCurrentLineAsFinished(b) {
|
|
|
49636
49781
|
markAsFinished(b, b.lastOtid);
|
|
49637
49782
|
} else {}
|
|
49638
49783
|
}
|
|
49639
|
-
function markIncompleteToolsAsCancelled(b) {
|
|
49640
|
-
|
|
49784
|
+
function markIncompleteToolsAsCancelled(b, setInterruptedFlag = true) {
|
|
49785
|
+
if (setInterruptedFlag) {
|
|
49786
|
+
b.interrupted = true;
|
|
49787
|
+
}
|
|
49641
49788
|
let anyToolsCancelled = false;
|
|
49642
49789
|
for (const [id, line] of b.byId.entries()) {
|
|
49643
49790
|
if (line.kind === "tool_call" && line.phase !== "finished") {
|
|
@@ -50032,6 +50179,10 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
50032
50179
|
queueMicrotask(refresh);
|
|
50033
50180
|
break;
|
|
50034
50181
|
}
|
|
50182
|
+
const errObj = chunk.error;
|
|
50183
|
+
if (errObj?.detail?.includes("No tool call is currently awaiting approval")) {
|
|
50184
|
+
continue;
|
|
50185
|
+
}
|
|
50035
50186
|
onChunk(buffers, chunk);
|
|
50036
50187
|
queueMicrotask(refresh);
|
|
50037
50188
|
if (chunk.message_type === "stop_reason") {
|
|
@@ -50113,7 +50264,7 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
|
|
|
50113
50264
|
const resumeStream = await client.runs.messages.stream(result.lastRunId, {
|
|
50114
50265
|
starting_after: result.lastSeqId,
|
|
50115
50266
|
batch_size: 1000
|
|
50116
|
-
});
|
|
50267
|
+
}, { maxRetries: 0 });
|
|
50117
50268
|
const resumeResult = await drainStream(resumeStream, buffers, refresh, abortSignal);
|
|
50118
50269
|
result = resumeResult;
|
|
50119
50270
|
} catch (_e) {
|
|
@@ -52088,6 +52239,89 @@ var init_available_models = __esm(async () => {
|
|
|
52088
52239
|
CACHE_TTL_MS = 5 * 60 * 1000;
|
|
52089
52240
|
});
|
|
52090
52241
|
|
|
52242
|
+
// src/ralph/mode.ts
|
|
52243
|
+
function getDefaultState() {
|
|
52244
|
+
return {
|
|
52245
|
+
isActive: false,
|
|
52246
|
+
isYolo: false,
|
|
52247
|
+
originalPrompt: "",
|
|
52248
|
+
completionPromise: null,
|
|
52249
|
+
maxIterations: 0,
|
|
52250
|
+
currentIteration: 0
|
|
52251
|
+
};
|
|
52252
|
+
}
|
|
52253
|
+
function getGlobalState() {
|
|
52254
|
+
const global2 = globalThis;
|
|
52255
|
+
if (!global2[RALPH_KEY]) {
|
|
52256
|
+
global2[RALPH_KEY] = getDefaultState();
|
|
52257
|
+
}
|
|
52258
|
+
return global2[RALPH_KEY];
|
|
52259
|
+
}
|
|
52260
|
+
function setGlobalState(state) {
|
|
52261
|
+
const global2 = globalThis;
|
|
52262
|
+
global2[RALPH_KEY] = state;
|
|
52263
|
+
}
|
|
52264
|
+
|
|
52265
|
+
class RalphModeManager {
|
|
52266
|
+
activate(prompt, completionPromise, maxIterations, isYolo) {
|
|
52267
|
+
let resolvedPromise;
|
|
52268
|
+
if (completionPromise === undefined) {
|
|
52269
|
+
resolvedPromise = DEFAULT_COMPLETION_PROMISE;
|
|
52270
|
+
} else if (completionPromise === null || completionPromise === "" || completionPromise.toLowerCase() === "none") {
|
|
52271
|
+
resolvedPromise = null;
|
|
52272
|
+
} else {
|
|
52273
|
+
resolvedPromise = completionPromise;
|
|
52274
|
+
}
|
|
52275
|
+
setGlobalState({
|
|
52276
|
+
isActive: true,
|
|
52277
|
+
isYolo,
|
|
52278
|
+
originalPrompt: prompt,
|
|
52279
|
+
completionPromise: resolvedPromise,
|
|
52280
|
+
maxIterations,
|
|
52281
|
+
currentIteration: 1
|
|
52282
|
+
});
|
|
52283
|
+
}
|
|
52284
|
+
deactivate() {
|
|
52285
|
+
setGlobalState(getDefaultState());
|
|
52286
|
+
}
|
|
52287
|
+
getState() {
|
|
52288
|
+
return getGlobalState();
|
|
52289
|
+
}
|
|
52290
|
+
incrementIteration() {
|
|
52291
|
+
const state = getGlobalState();
|
|
52292
|
+
setGlobalState({
|
|
52293
|
+
...state,
|
|
52294
|
+
currentIteration: state.currentIteration + 1
|
|
52295
|
+
});
|
|
52296
|
+
}
|
|
52297
|
+
checkForPromise(text) {
|
|
52298
|
+
const state = getGlobalState();
|
|
52299
|
+
if (!state.completionPromise)
|
|
52300
|
+
return false;
|
|
52301
|
+
const match3 = text.match(/<promise>([\s\S]*?)<\/promise>/i);
|
|
52302
|
+
if (!match3 || match3[1] === undefined)
|
|
52303
|
+
return false;
|
|
52304
|
+
const promiseText = match3[1].trim().replace(/\s+/g, " ");
|
|
52305
|
+
const expected = state.completionPromise.trim().replace(/\s+/g, " ");
|
|
52306
|
+
return promiseText === expected;
|
|
52307
|
+
}
|
|
52308
|
+
shouldContinue() {
|
|
52309
|
+
const state = getGlobalState();
|
|
52310
|
+
if (!state.isActive)
|
|
52311
|
+
return false;
|
|
52312
|
+
if (state.maxIterations > 0 && state.currentIteration >= state.maxIterations) {
|
|
52313
|
+
return false;
|
|
52314
|
+
}
|
|
52315
|
+
return true;
|
|
52316
|
+
}
|
|
52317
|
+
}
|
|
52318
|
+
var DEFAULT_COMPLETION_PROMISE, RALPH_KEY, ralphMode;
|
|
52319
|
+
var init_mode2 = __esm(() => {
|
|
52320
|
+
DEFAULT_COMPLETION_PROMISE = "The task is complete. All requirements have been implemented and verified working. " + "Any tests that were relevant have been run and are passing. The implementation is " + "clean and production-ready. I have not taken any shortcuts or faked anything to " + "meet these requirements.";
|
|
52321
|
+
RALPH_KEY = Symbol.for("@letta/ralphMode");
|
|
52322
|
+
ralphMode = new RalphModeManager;
|
|
52323
|
+
});
|
|
52324
|
+
|
|
52091
52325
|
// src/settings.ts
|
|
52092
52326
|
var exports_settings = {};
|
|
52093
52327
|
__export(exports_settings, {
|
|
@@ -55419,9 +55653,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
55419
55653
|
const relPath = relative4(cwd2, filePath);
|
|
55420
55654
|
const displayPath = relPath.startsWith("..") ? filePath : relPath;
|
|
55421
55655
|
if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
|
|
55422
|
-
const { existsSync:
|
|
55656
|
+
const { existsSync: existsSync8 } = __require("node:fs");
|
|
55423
55657
|
try {
|
|
55424
|
-
if (
|
|
55658
|
+
if (existsSync8(filePath)) {
|
|
55425
55659
|
return `Overwrite ${displayPath}?`;
|
|
55426
55660
|
}
|
|
55427
55661
|
} catch {}
|
|
@@ -56191,7 +56425,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
56191
56425
|
|
|
56192
56426
|
// src/cli/helpers/clipboard.ts
|
|
56193
56427
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
56194
|
-
import { existsSync as
|
|
56428
|
+
import { existsSync as existsSync8, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
56195
56429
|
import { basename as basename2, extname, isAbsolute as isAbsolute10, resolve as resolve16 } from "node:path";
|
|
56196
56430
|
function countLines2(text) {
|
|
56197
56431
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
@@ -56242,7 +56476,7 @@ function translatePasteForImages(paste) {
|
|
|
56242
56476
|
if (!isAbsolute10(filePath))
|
|
56243
56477
|
filePath = resolve16(process.cwd(), filePath);
|
|
56244
56478
|
const ext3 = extname(filePath || "").toLowerCase();
|
|
56245
|
-
if (IMAGE_EXTS.has(ext3) &&
|
|
56479
|
+
if (IMAGE_EXTS.has(ext3) && existsSync8(filePath) && statSync(filePath).isFile()) {
|
|
56246
56480
|
const buf = readFileSync2(filePath);
|
|
56247
56481
|
const b64 = buf.toString("base64");
|
|
56248
56482
|
const mt = ext3 === ".png" ? "image/png" : ext3 === ".jpg" || ext3 === ".jpeg" ? "image/jpeg" : ext3 === ".gif" ? "image/gif" : ext3 === ".webp" ? "image/webp" : ext3 === ".bmp" ? "image/bmp" : ext3 === ".svg" ? "image/svg+xml" : ext3 === ".tif" || ext3 === ".tiff" ? "image/tiff" : ext3 === ".heic" ? "image/heic" : ext3 === ".heif" ? "image/heif" : ext3 === ".avif" ? "image/avif" : "application/octet-stream";
|
|
@@ -56830,7 +57064,7 @@ __export(exports_terminalKeybindingInstaller, {
|
|
|
56830
57064
|
});
|
|
56831
57065
|
import {
|
|
56832
57066
|
copyFileSync,
|
|
56833
|
-
existsSync as
|
|
57067
|
+
existsSync as existsSync9,
|
|
56834
57068
|
mkdirSync as mkdirSync3,
|
|
56835
57069
|
readFileSync as readFileSync3,
|
|
56836
57070
|
writeFileSync
|
|
@@ -56899,7 +57133,7 @@ function parseKeybindings(content) {
|
|
|
56899
57133
|
}
|
|
56900
57134
|
}
|
|
56901
57135
|
function keybindingExists(keybindingsPath) {
|
|
56902
|
-
if (!
|
|
57136
|
+
if (!existsSync9(keybindingsPath))
|
|
56903
57137
|
return false;
|
|
56904
57138
|
try {
|
|
56905
57139
|
const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -56912,7 +57146,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
56912
57146
|
}
|
|
56913
57147
|
}
|
|
56914
57148
|
function createBackup(keybindingsPath) {
|
|
56915
|
-
if (!
|
|
57149
|
+
if (!existsSync9(keybindingsPath))
|
|
56916
57150
|
return null;
|
|
56917
57151
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
56918
57152
|
try {
|
|
@@ -56928,12 +57162,12 @@ function installKeybinding(keybindingsPath) {
|
|
|
56928
57162
|
return { success: true, alreadyExists: true };
|
|
56929
57163
|
}
|
|
56930
57164
|
const parentDir = dirname10(keybindingsPath);
|
|
56931
|
-
if (!
|
|
57165
|
+
if (!existsSync9(parentDir)) {
|
|
56932
57166
|
mkdirSync3(parentDir, { recursive: true });
|
|
56933
57167
|
}
|
|
56934
57168
|
let keybindings = [];
|
|
56935
57169
|
let backupPath = null;
|
|
56936
|
-
if (
|
|
57170
|
+
if (existsSync9(keybindingsPath)) {
|
|
56937
57171
|
backupPath = createBackup(keybindingsPath);
|
|
56938
57172
|
const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
|
|
56939
57173
|
const parsed = parseKeybindings(content);
|
|
@@ -56963,7 +57197,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
56963
57197
|
}
|
|
56964
57198
|
function removeKeybinding(keybindingsPath) {
|
|
56965
57199
|
try {
|
|
56966
|
-
if (!
|
|
57200
|
+
if (!existsSync9(keybindingsPath)) {
|
|
56967
57201
|
return { success: true };
|
|
56968
57202
|
}
|
|
56969
57203
|
const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -57031,16 +57265,16 @@ function getWezTermConfigPath() {
|
|
|
57031
57265
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
57032
57266
|
if (xdgConfig) {
|
|
57033
57267
|
const xdgPath = join14(xdgConfig, "wezterm", "wezterm.lua");
|
|
57034
|
-
if (
|
|
57268
|
+
if (existsSync9(xdgPath))
|
|
57035
57269
|
return xdgPath;
|
|
57036
57270
|
}
|
|
57037
57271
|
const configPath = join14(homedir7(), ".config", "wezterm", "wezterm.lua");
|
|
57038
|
-
if (
|
|
57272
|
+
if (existsSync9(configPath))
|
|
57039
57273
|
return configPath;
|
|
57040
57274
|
return join14(homedir7(), ".wezterm.lua");
|
|
57041
57275
|
}
|
|
57042
57276
|
function wezTermDeleteFixExists(configPath) {
|
|
57043
|
-
if (!
|
|
57277
|
+
if (!existsSync9(configPath))
|
|
57044
57278
|
return false;
|
|
57045
57279
|
try {
|
|
57046
57280
|
const content = readFileSync3(configPath, { encoding: "utf-8" });
|
|
@@ -57057,7 +57291,7 @@ function installWezTermDeleteFix() {
|
|
|
57057
57291
|
}
|
|
57058
57292
|
let content = "";
|
|
57059
57293
|
let backupPath = null;
|
|
57060
|
-
if (
|
|
57294
|
+
if (existsSync9(configPath)) {
|
|
57061
57295
|
backupPath = `${configPath}.letta-backup`;
|
|
57062
57296
|
copyFileSync(configPath, backupPath);
|
|
57063
57297
|
content = readFileSync3(configPath, { encoding: "utf-8" });
|
|
@@ -57087,7 +57321,7 @@ ${WEZTERM_DELETE_FIX}
|
|
|
57087
57321
|
`;
|
|
57088
57322
|
}
|
|
57089
57323
|
const parentDir = dirname10(configPath);
|
|
57090
|
-
if (!
|
|
57324
|
+
if (!existsSync9(parentDir)) {
|
|
57091
57325
|
mkdirSync3(parentDir, { recursive: true });
|
|
57092
57326
|
}
|
|
57093
57327
|
writeFileSync(configPath, content, { encoding: "utf-8" });
|
|
@@ -57393,6 +57627,20 @@ Location: ${keybindingsPath}`;
|
|
|
57393
57627
|
return "Clearing credentials...";
|
|
57394
57628
|
}
|
|
57395
57629
|
},
|
|
57630
|
+
"/ralph": {
|
|
57631
|
+
desc: 'Start Ralph Wiggum loop (/ralph [prompt] [--completion-promise "X"] [--max-iterations N])',
|
|
57632
|
+
order: 45,
|
|
57633
|
+
handler: () => {
|
|
57634
|
+
return "Activating ralph mode...";
|
|
57635
|
+
}
|
|
57636
|
+
},
|
|
57637
|
+
"/yolo-ralph": {
|
|
57638
|
+
desc: "Start Ralph loop with bypass permissions (yolo + ralph)",
|
|
57639
|
+
order: 46,
|
|
57640
|
+
handler: () => {
|
|
57641
|
+
return "Activating yolo-ralph mode...";
|
|
57642
|
+
}
|
|
57643
|
+
},
|
|
57396
57644
|
"/stream": {
|
|
57397
57645
|
desc: "Toggle token streaming on/off",
|
|
57398
57646
|
hidden: true,
|
|
@@ -57457,7 +57705,7 @@ __export(exports_custom, {
|
|
|
57457
57705
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
57458
57706
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
57459
57707
|
});
|
|
57460
|
-
import { existsSync as
|
|
57708
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
57461
57709
|
import { readdir as readdir7, readFile as readFile8 } from "node:fs/promises";
|
|
57462
57710
|
import { basename as basename3, dirname as dirname11, join as join15 } from "node:path";
|
|
57463
57711
|
async function getCustomCommands() {
|
|
@@ -57491,7 +57739,7 @@ async function discoverCustomCommands(projectPath = join15(process.cwd(), COMMAN
|
|
|
57491
57739
|
return result;
|
|
57492
57740
|
}
|
|
57493
57741
|
async function discoverFromDirectory(dirPath, source) {
|
|
57494
|
-
if (!
|
|
57742
|
+
if (!existsSync10(dirPath)) {
|
|
57495
57743
|
return [];
|
|
57496
57744
|
}
|
|
57497
57745
|
const commands2 = [];
|
|
@@ -58239,9 +58487,9 @@ function getHeaderText(fileEdit) {
|
|
|
58239
58487
|
const relPath = relative4(cwd2, fileEdit.filePath);
|
|
58240
58488
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
58241
58489
|
if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
|
|
58242
|
-
const { existsSync:
|
|
58490
|
+
const { existsSync: existsSync11 } = __require("node:fs");
|
|
58243
58491
|
try {
|
|
58244
|
-
if (
|
|
58492
|
+
if (existsSync11(fileEdit.filePath)) {
|
|
58245
58493
|
return `Overwrite ${displayPath}?`;
|
|
58246
58494
|
}
|
|
58247
58495
|
} catch {}
|
|
@@ -63208,7 +63456,11 @@ function Input({
|
|
|
63208
63456
|
currentModelProvider,
|
|
63209
63457
|
messageQueue,
|
|
63210
63458
|
onEnterQueueEditMode,
|
|
63211
|
-
onEscapeCancel
|
|
63459
|
+
onEscapeCancel,
|
|
63460
|
+
ralphActive = false,
|
|
63461
|
+
ralphPending = false,
|
|
63462
|
+
ralphPendingYolo = false,
|
|
63463
|
+
onRalphExit
|
|
63212
63464
|
}) {
|
|
63213
63465
|
const [value, setValue] = import_react54.useState("");
|
|
63214
63466
|
const [escapePressed, setEscapePressed] = import_react54.useState(false);
|
|
@@ -63330,6 +63582,10 @@ function Input({
|
|
|
63330
63582
|
console.error(`[debug:InputRich] shift=${key.shift} tab=${key.tab} visible=${visible}`);
|
|
63331
63583
|
}
|
|
63332
63584
|
if (key.shift && key.tab) {
|
|
63585
|
+
if (ralphActive && onRalphExit) {
|
|
63586
|
+
onRalphExit();
|
|
63587
|
+
return;
|
|
63588
|
+
}
|
|
63333
63589
|
const modes = [
|
|
63334
63590
|
"default",
|
|
63335
63591
|
"acceptEdits",
|
|
@@ -63546,6 +63802,32 @@ function Input({
|
|
|
63546
63802
|
setCursorPos(selectedCommand.length);
|
|
63547
63803
|
};
|
|
63548
63804
|
const getModeInfo = () => {
|
|
63805
|
+
if (ralphPending) {
|
|
63806
|
+
if (ralphPendingYolo) {
|
|
63807
|
+
return {
|
|
63808
|
+
name: "yolo-ralph (waiting)",
|
|
63809
|
+
color: "#FF8C00"
|
|
63810
|
+
};
|
|
63811
|
+
}
|
|
63812
|
+
return {
|
|
63813
|
+
name: "ralph (waiting)",
|
|
63814
|
+
color: "#FEE19C"
|
|
63815
|
+
};
|
|
63816
|
+
}
|
|
63817
|
+
if (ralphActive) {
|
|
63818
|
+
const ralph = ralphMode.getState();
|
|
63819
|
+
const iterDisplay = ralph.maxIterations > 0 ? `${ralph.currentIteration}/${ralph.maxIterations}` : `${ralph.currentIteration}`;
|
|
63820
|
+
if (ralph.isYolo) {
|
|
63821
|
+
return {
|
|
63822
|
+
name: `yolo-ralph (iter ${iterDisplay})`,
|
|
63823
|
+
color: "#FF8C00"
|
|
63824
|
+
};
|
|
63825
|
+
}
|
|
63826
|
+
return {
|
|
63827
|
+
name: `ralph (iter ${iterDisplay})`,
|
|
63828
|
+
color: "#FEE19C"
|
|
63829
|
+
};
|
|
63830
|
+
}
|
|
63549
63831
|
switch (currentMode) {
|
|
63550
63832
|
case "acceptEdits":
|
|
63551
63833
|
return { name: "accept edits", color: colors.status.processing };
|
|
@@ -63710,7 +63992,9 @@ function Input({
|
|
|
63710
63992
|
dimColor: true,
|
|
63711
63993
|
children: [
|
|
63712
63994
|
" ",
|
|
63713
|
-
"(shift+tab to
|
|
63995
|
+
"(shift+tab to ",
|
|
63996
|
+
ralphActive || ralphPending ? "exit" : "cycle",
|
|
63997
|
+
")"
|
|
63714
63998
|
]
|
|
63715
63999
|
}, undefined, true, undefined, this)
|
|
63716
64000
|
]
|
|
@@ -63744,6 +64028,7 @@ var init_InputRich = __esm(async () => {
|
|
|
63744
64028
|
init_oauth();
|
|
63745
64029
|
init_constants();
|
|
63746
64030
|
init_mode();
|
|
64031
|
+
init_mode2();
|
|
63747
64032
|
init_useTerminalWidth();
|
|
63748
64033
|
init_colors();
|
|
63749
64034
|
await __promiseAll([
|
|
@@ -70372,7 +70657,7 @@ var exports_App = {};
|
|
|
70372
70657
|
__export(exports_App, {
|
|
70373
70658
|
default: () => App2
|
|
70374
70659
|
});
|
|
70375
|
-
import { existsSync as
|
|
70660
|
+
import { existsSync as existsSync11, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
70376
70661
|
function uid4(prefix) {
|
|
70377
70662
|
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
70378
70663
|
}
|
|
@@ -70470,7 +70755,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|
|
70470
70755
|
}
|
|
70471
70756
|
function planFileExists() {
|
|
70472
70757
|
const planFilePath = permissionMode2.getPlanFilePath();
|
|
70473
|
-
return !!planFilePath &&
|
|
70758
|
+
return !!planFilePath && existsSync11(planFilePath);
|
|
70474
70759
|
}
|
|
70475
70760
|
function getQuestionsFromApproval(approval) {
|
|
70476
70761
|
const parsed = safeJsonParseOr(approval.toolArgs, {});
|
|
@@ -70484,6 +70769,71 @@ function getSkillUnloadReminder() {
|
|
|
70484
70769
|
}
|
|
70485
70770
|
return "";
|
|
70486
70771
|
}
|
|
70772
|
+
function parseRalphArgs(input) {
|
|
70773
|
+
let rest = input.replace(/^\/(yolo-)?ralph\s*/, "");
|
|
70774
|
+
let completionPromise;
|
|
70775
|
+
const promiseMatch = rest.match(/--completion-promise\s+["']([^"']*)["']/);
|
|
70776
|
+
if (promiseMatch) {
|
|
70777
|
+
const val = promiseMatch[1] ?? "";
|
|
70778
|
+
completionPromise = val === "" || val.toLowerCase() === "none" ? null : val;
|
|
70779
|
+
rest = rest.replace(/--completion-promise\s+["'][^"']*["']\s*/, "");
|
|
70780
|
+
}
|
|
70781
|
+
const maxMatch = rest.match(/--max-iterations\s+(\d+)/);
|
|
70782
|
+
const maxIterations = maxMatch?.[1] ? parseInt(maxMatch[1], 10) : 0;
|
|
70783
|
+
rest = rest.replace(/--max-iterations\s+\d+\s*/, "");
|
|
70784
|
+
const prompt = rest.trim().replace(/^["']|["']$/g, "") || null;
|
|
70785
|
+
return { prompt, completionPromise, maxIterations };
|
|
70786
|
+
}
|
|
70787
|
+
function buildRalphFirstTurnReminder(state) {
|
|
70788
|
+
const iterInfo = state.maxIterations > 0 ? `${state.currentIteration}/${state.maxIterations}` : `${state.currentIteration}`;
|
|
70789
|
+
let reminder = `<system-reminder>
|
|
70790
|
+
\uD83D\uDD04 Ralph Wiggum mode activated (iteration ${iterInfo})
|
|
70791
|
+
`;
|
|
70792
|
+
if (state.completionPromise) {
|
|
70793
|
+
reminder += `
|
|
70794
|
+
═══════════════════════════════════════════════════════════
|
|
70795
|
+
RALPH LOOP COMPLETION PROMISE
|
|
70796
|
+
═══════════════════════════════════════════════════════════
|
|
70797
|
+
|
|
70798
|
+
To complete this loop, output this EXACT text:
|
|
70799
|
+
<promise>${state.completionPromise}</promise>
|
|
70800
|
+
|
|
70801
|
+
STRICT REQUIREMENTS (DO NOT VIOLATE):
|
|
70802
|
+
✓ Use <promise> XML tags EXACTLY as shown above
|
|
70803
|
+
✓ The statement MUST be completely and unequivocally TRUE
|
|
70804
|
+
✓ Do NOT output false statements to exit the loop
|
|
70805
|
+
✓ Do NOT lie even if you think you should exit
|
|
70806
|
+
|
|
70807
|
+
IMPORTANT - Do not circumvent the loop:
|
|
70808
|
+
Even if you believe you're stuck, the task is impossible,
|
|
70809
|
+
or you've been running too long - you MUST NOT output a
|
|
70810
|
+
false promise statement. The loop is designed to continue
|
|
70811
|
+
until the promise is GENUINELY TRUE. Trust the process.
|
|
70812
|
+
|
|
70813
|
+
If the loop should stop, the promise statement will become
|
|
70814
|
+
true naturally. Do not force it by lying.
|
|
70815
|
+
═══════════════════════════════════════════════════════════
|
|
70816
|
+
`;
|
|
70817
|
+
} else {
|
|
70818
|
+
reminder += `
|
|
70819
|
+
No completion promise set - loop runs until --max-iterations or ESC/Shift+Tab to exit.
|
|
70820
|
+
`;
|
|
70821
|
+
}
|
|
70822
|
+
reminder += `</system-reminder>`;
|
|
70823
|
+
return reminder;
|
|
70824
|
+
}
|
|
70825
|
+
function buildRalphContinuationReminder(state) {
|
|
70826
|
+
const iterInfo = state.maxIterations > 0 ? `${state.currentIteration}/${state.maxIterations}` : `${state.currentIteration}`;
|
|
70827
|
+
if (state.completionPromise) {
|
|
70828
|
+
return `<system-reminder>
|
|
70829
|
+
\uD83D\uDD04 Ralph iteration ${iterInfo} | To stop: output <promise>${state.completionPromise}</promise> (ONLY when statement is TRUE - do not lie to exit!)
|
|
70830
|
+
</system-reminder>`;
|
|
70831
|
+
} else {
|
|
70832
|
+
return `<system-reminder>
|
|
70833
|
+
\uD83D\uDD04 Ralph iteration ${iterInfo} | No completion promise set - loop runs infinitely
|
|
70834
|
+
</system-reminder>`;
|
|
70835
|
+
}
|
|
70836
|
+
}
|
|
70487
70837
|
function App2({
|
|
70488
70838
|
agentId: initialAgentId,
|
|
70489
70839
|
agentState: initialAgentState,
|
|
@@ -70528,6 +70878,7 @@ function App2({
|
|
|
70528
70878
|
}, [agentId]);
|
|
70529
70879
|
const [streaming, setStreaming, streamingRef] = useSyncedState(false);
|
|
70530
70880
|
const processingConversationRef = import_react76.useRef(0);
|
|
70881
|
+
const conversationGenerationRef = import_react76.useRef(0);
|
|
70531
70882
|
const [interruptRequested, setInterruptRequested] = import_react76.useState(false);
|
|
70532
70883
|
const [commandRunning, setCommandRunning, commandRunningRef] = useSyncedState(false);
|
|
70533
70884
|
const [profileConfirmPending, setProfileConfirmPending] = import_react76.useState(null);
|
|
@@ -70540,6 +70891,8 @@ function App2({
|
|
|
70540
70891
|
const [autoHandledResults, setAutoHandledResults] = import_react76.useState([]);
|
|
70541
70892
|
const [autoDeniedApprovals, setAutoDeniedApprovals] = import_react76.useState([]);
|
|
70542
70893
|
const bashCommandCacheRef = import_react76.useRef([]);
|
|
70894
|
+
const [pendingRalphConfig, setPendingRalphConfig] = import_react76.useState(null);
|
|
70895
|
+
const [uiRalphActive, setUiRalphActive] = import_react76.useState(ralphMode.getState().isActive);
|
|
70543
70896
|
const currentApproval = pendingApprovals[approvalResults.length];
|
|
70544
70897
|
const currentApprovalContext = approvalContexts[approvalResults.length];
|
|
70545
70898
|
const activeApprovalId = currentApproval?.toolCallId ?? null;
|
|
@@ -70791,8 +71144,8 @@ function App2({
|
|
|
70791
71144
|
if (!planFilePath)
|
|
70792
71145
|
return;
|
|
70793
71146
|
try {
|
|
70794
|
-
const { readFileSync: readFileSync5, existsSync:
|
|
70795
|
-
if (!
|
|
71147
|
+
const { readFileSync: readFileSync5, existsSync: existsSync12 } = __require("node:fs");
|
|
71148
|
+
if (!existsSync12(planFilePath))
|
|
70796
71149
|
return;
|
|
70797
71150
|
const planContent = readFileSync5(planFilePath, "utf-8");
|
|
70798
71151
|
const previewItem = {
|
|
@@ -70915,8 +71268,70 @@ function App2({
|
|
|
70915
71268
|
}
|
|
70916
71269
|
}, [refreshDerived, currentModelId]);
|
|
70917
71270
|
const processConversation = import_react76.useCallback(async (initialInput, options) => {
|
|
71271
|
+
const handleRalphContinuation = () => {
|
|
71272
|
+
const ralphState = ralphMode.getState();
|
|
71273
|
+
const lines2 = toLines(buffersRef.current);
|
|
71274
|
+
const assistantLines = lines2.filter((l) => l.kind === "assistant");
|
|
71275
|
+
const lastAssistantText = assistantLines.length > 0 ? assistantLines[assistantLines.length - 1]?.text ?? "" : "";
|
|
71276
|
+
if (ralphMode.checkForPromise(lastAssistantText)) {
|
|
71277
|
+
const wasYolo = ralphState.isYolo;
|
|
71278
|
+
ralphMode.deactivate();
|
|
71279
|
+
setUiRalphActive(false);
|
|
71280
|
+
if (wasYolo) {
|
|
71281
|
+
permissionMode2.setMode("default");
|
|
71282
|
+
}
|
|
71283
|
+
const statusId = uid4("status");
|
|
71284
|
+
buffersRef.current.byId.set(statusId, {
|
|
71285
|
+
kind: "status",
|
|
71286
|
+
id: statusId,
|
|
71287
|
+
lines: [
|
|
71288
|
+
`✅ Ralph loop complete: promise detected after ${ralphState.currentIteration} iteration(s)`
|
|
71289
|
+
]
|
|
71290
|
+
});
|
|
71291
|
+
buffersRef.current.order.push(statusId);
|
|
71292
|
+
refreshDerived();
|
|
71293
|
+
return;
|
|
71294
|
+
}
|
|
71295
|
+
if (!ralphMode.shouldContinue()) {
|
|
71296
|
+
const wasYolo = ralphState.isYolo;
|
|
71297
|
+
ralphMode.deactivate();
|
|
71298
|
+
setUiRalphActive(false);
|
|
71299
|
+
if (wasYolo) {
|
|
71300
|
+
permissionMode2.setMode("default");
|
|
71301
|
+
}
|
|
71302
|
+
const statusId = uid4("status");
|
|
71303
|
+
buffersRef.current.byId.set(statusId, {
|
|
71304
|
+
kind: "status",
|
|
71305
|
+
id: statusId,
|
|
71306
|
+
lines: [
|
|
71307
|
+
`\uD83D\uDED1 Ralph loop: Max iterations (${ralphState.maxIterations}) reached`
|
|
71308
|
+
]
|
|
71309
|
+
});
|
|
71310
|
+
buffersRef.current.order.push(statusId);
|
|
71311
|
+
refreshDerived();
|
|
71312
|
+
return;
|
|
71313
|
+
}
|
|
71314
|
+
ralphMode.incrementIteration();
|
|
71315
|
+
const newState = ralphMode.getState();
|
|
71316
|
+
const systemMsg = buildRalphContinuationReminder(newState);
|
|
71317
|
+
setTimeout(() => {
|
|
71318
|
+
processConversation([
|
|
71319
|
+
{
|
|
71320
|
+
type: "message",
|
|
71321
|
+
role: "user",
|
|
71322
|
+
content: `${systemMsg}
|
|
71323
|
+
|
|
71324
|
+
${newState.originalPrompt}`
|
|
71325
|
+
}
|
|
71326
|
+
], { allowReentry: true });
|
|
71327
|
+
}, 0);
|
|
71328
|
+
};
|
|
70918
71329
|
const currentInput = [...initialInput];
|
|
70919
71330
|
const allowReentry = options?.allowReentry ?? false;
|
|
71331
|
+
const myGeneration = options?.submissionGeneration ?? conversationGenerationRef.current;
|
|
71332
|
+
if (myGeneration !== conversationGenerationRef.current) {
|
|
71333
|
+
return;
|
|
71334
|
+
}
|
|
70920
71335
|
if (processingConversationRef.current > 0 && !allowReentry) {
|
|
70921
71336
|
return;
|
|
70922
71337
|
}
|
|
@@ -70930,20 +71345,29 @@ function App2({
|
|
|
70930
71345
|
userCancelledRef.current = false;
|
|
70931
71346
|
return;
|
|
70932
71347
|
}
|
|
71348
|
+
if (myGeneration !== conversationGenerationRef.current) {
|
|
71349
|
+
return;
|
|
71350
|
+
}
|
|
70933
71351
|
setStreaming(true);
|
|
70934
71352
|
abortControllerRef.current = new AbortController;
|
|
70935
|
-
markIncompleteToolsAsCancelled(buffersRef.current);
|
|
71353
|
+
markIncompleteToolsAsCancelled(buffersRef.current, false);
|
|
70936
71354
|
buffersRef.current.interrupted = false;
|
|
70937
71355
|
clearCompletedSubagents();
|
|
70938
71356
|
while (true) {
|
|
70939
71357
|
const signal = abortControllerRef.current?.signal;
|
|
70940
71358
|
if (signal?.aborted) {
|
|
70941
|
-
|
|
71359
|
+
const isStaleAtAbort = myGeneration !== conversationGenerationRef.current;
|
|
71360
|
+
if (!isStaleAtAbort) {
|
|
71361
|
+
setStreaming(false);
|
|
71362
|
+
}
|
|
70942
71363
|
return;
|
|
70943
71364
|
}
|
|
70944
71365
|
const stream2 = await sendMessageStream(agentIdRef.current, currentInput);
|
|
70945
71366
|
if (signal?.aborted) {
|
|
70946
|
-
|
|
71367
|
+
const isStaleAtAbort = myGeneration !== conversationGenerationRef.current;
|
|
71368
|
+
if (!isStaleAtAbort) {
|
|
71369
|
+
setStreaming(false);
|
|
71370
|
+
}
|
|
70947
71371
|
return;
|
|
70948
71372
|
}
|
|
70949
71373
|
const syncAgentState = async () => {
|
|
@@ -70987,6 +71411,10 @@ function App2({
|
|
|
70987
71411
|
const wasInterrupted = !!buffersRef.current.interrupted;
|
|
70988
71412
|
const wasAborted = !!signal?.aborted;
|
|
70989
71413
|
let stopReasonToHandle = wasAborted ? "cancelled" : stopReason;
|
|
71414
|
+
const isStaleAfterDrain = myGeneration !== conversationGenerationRef.current;
|
|
71415
|
+
if (isStaleAfterDrain) {
|
|
71416
|
+
return;
|
|
71417
|
+
}
|
|
70990
71418
|
if (!wasInterrupted) {
|
|
70991
71419
|
refreshDerived();
|
|
70992
71420
|
}
|
|
@@ -71013,6 +71441,10 @@ function App2({
|
|
|
71013
71441
|
waitingForQueueCancelRef.current = false;
|
|
71014
71442
|
queueSnapshotRef.current = [];
|
|
71015
71443
|
}
|
|
71444
|
+
if (ralphMode.getState().isActive) {
|
|
71445
|
+
handleRalphContinuation();
|
|
71446
|
+
return;
|
|
71447
|
+
}
|
|
71016
71448
|
return;
|
|
71017
71449
|
}
|
|
71018
71450
|
if (stopReasonToHandle === "cancelled") {
|
|
@@ -71034,6 +71466,18 @@ function App2({
|
|
|
71034
71466
|
if (!EAGER_CANCEL) {
|
|
71035
71467
|
appendError(INTERRUPT_MESSAGE, true);
|
|
71036
71468
|
}
|
|
71469
|
+
if (ralphMode.getState().isActive) {
|
|
71470
|
+
const statusId = uid4("status");
|
|
71471
|
+
buffersRef.current.byId.set(statusId, {
|
|
71472
|
+
kind: "status",
|
|
71473
|
+
id: statusId,
|
|
71474
|
+
lines: [
|
|
71475
|
+
`⏸️ Ralph loop paused - type to continue or shift+tab to exit`
|
|
71476
|
+
]
|
|
71477
|
+
});
|
|
71478
|
+
buffersRef.current.order.push(statusId);
|
|
71479
|
+
refreshDerived();
|
|
71480
|
+
}
|
|
71037
71481
|
}
|
|
71038
71482
|
return;
|
|
71039
71483
|
}
|
|
@@ -71306,7 +71750,8 @@ function App2({
|
|
|
71306
71750
|
sendDesktopNotification();
|
|
71307
71751
|
return;
|
|
71308
71752
|
}
|
|
71309
|
-
const
|
|
71753
|
+
const hasApprovalInPayload = currentInput.some((item) => item?.type === "approval");
|
|
71754
|
+
const isApprovalOnlyPayload = hasApprovalInPayload && currentInput.length === 1;
|
|
71310
71755
|
let latestErrorText = null;
|
|
71311
71756
|
for (let i = buffersRef.current.order.length - 1;i >= 0; i -= 1) {
|
|
71312
71757
|
const id = buffersRef.current.order[i];
|
|
@@ -71321,7 +71766,7 @@ function App2({
|
|
|
71321
71766
|
const detailFromRun = await fetchRunErrorDetail(lastRunId);
|
|
71322
71767
|
const desyncDetected = isApprovalStateDesyncError(detailFromRun) || isApprovalStateDesyncError(latestErrorText);
|
|
71323
71768
|
const lastFailureMessage = latestErrorText || detailFromRun || null;
|
|
71324
|
-
if (
|
|
71769
|
+
if (hasApprovalInPayload && desyncDetected) {
|
|
71325
71770
|
if (llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES2) {
|
|
71326
71771
|
llmApiErrorRetriesRef.current += 1;
|
|
71327
71772
|
const statusId = uid4("status");
|
|
@@ -71334,7 +71779,16 @@ function App2({
|
|
|
71334
71779
|
});
|
|
71335
71780
|
buffersRef.current.order.push(statusId);
|
|
71336
71781
|
refreshDerived();
|
|
71337
|
-
|
|
71782
|
+
if (isApprovalOnlyPayload) {
|
|
71783
|
+
currentInput.splice(0, currentInput.length, buildApprovalRecoveryMessage());
|
|
71784
|
+
} else {
|
|
71785
|
+
const messageItems = currentInput.filter((item) => item?.type !== "approval");
|
|
71786
|
+
if (messageItems.length > 0) {
|
|
71787
|
+
currentInput.splice(0, currentInput.length, ...messageItems);
|
|
71788
|
+
} else {
|
|
71789
|
+
currentInput.splice(0, currentInput.length, buildApprovalRecoveryMessage());
|
|
71790
|
+
}
|
|
71791
|
+
}
|
|
71338
71792
|
buffersRef.current.byId.delete(statusId);
|
|
71339
71793
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
71340
71794
|
refreshDerived();
|
|
@@ -71451,8 +71905,11 @@ function App2({
|
|
|
71451
71905
|
sendDesktopNotification();
|
|
71452
71906
|
refreshDerived();
|
|
71453
71907
|
} finally {
|
|
71908
|
+
const isStale = myGeneration !== conversationGenerationRef.current;
|
|
71454
71909
|
abortControllerRef.current = null;
|
|
71455
|
-
|
|
71910
|
+
if (!isStale) {
|
|
71911
|
+
processingConversationRef.current = Math.max(0, processingConversationRef.current - 1);
|
|
71912
|
+
}
|
|
71456
71913
|
}
|
|
71457
71914
|
}, [
|
|
71458
71915
|
appendError,
|
|
@@ -71495,8 +71952,9 @@ function App2({
|
|
|
71495
71952
|
}, 50);
|
|
71496
71953
|
return;
|
|
71497
71954
|
}
|
|
71498
|
-
if (!streaming || interruptRequested)
|
|
71955
|
+
if (!streaming || interruptRequested) {
|
|
71499
71956
|
return;
|
|
71957
|
+
}
|
|
71500
71958
|
if (waitingForQueueCancelRef.current) {
|
|
71501
71959
|
setRestoreQueueOnCancel(true);
|
|
71502
71960
|
}
|
|
@@ -71509,11 +71967,22 @@ function App2({
|
|
|
71509
71967
|
abortControllerRef.current = null;
|
|
71510
71968
|
}
|
|
71511
71969
|
userCancelledRef.current = true;
|
|
71970
|
+
conversationGenerationRef.current += 1;
|
|
71971
|
+
processingConversationRef.current = 0;
|
|
71512
71972
|
setStreaming(false);
|
|
71513
71973
|
if (!toolsCancelled) {
|
|
71514
71974
|
appendError(INTERRUPT_MESSAGE, true);
|
|
71515
71975
|
}
|
|
71516
71976
|
refreshDerived();
|
|
71977
|
+
if (pendingApprovals.length > 0) {
|
|
71978
|
+
const denialResults = pendingApprovals.map((approval) => ({
|
|
71979
|
+
type: "approval",
|
|
71980
|
+
tool_call_id: approval.toolCallId,
|
|
71981
|
+
approve: false,
|
|
71982
|
+
reason: "User interrupted the stream"
|
|
71983
|
+
}));
|
|
71984
|
+
setQueuedApprovalResults(denialResults);
|
|
71985
|
+
}
|
|
71517
71986
|
setPendingApprovals([]);
|
|
71518
71987
|
setApprovalContexts([]);
|
|
71519
71988
|
setApprovalResults([]);
|
|
@@ -71546,7 +72015,8 @@ function App2({
|
|
|
71546
72015
|
appendError,
|
|
71547
72016
|
isExecutingTool,
|
|
71548
72017
|
refreshDerived,
|
|
71549
|
-
setStreaming
|
|
72018
|
+
setStreaming,
|
|
72019
|
+
pendingApprovals
|
|
71550
72020
|
]);
|
|
71551
72021
|
const processConversationRef = import_react76.useRef(processConversation);
|
|
71552
72022
|
import_react76.useEffect(() => {
|
|
@@ -71761,6 +72231,96 @@ function App2({
|
|
|
71761
72231
|
}
|
|
71762
72232
|
refreshDerived();
|
|
71763
72233
|
}, [refreshDerived]);
|
|
72234
|
+
const checkPendingApprovalsForSlashCommand = import_react76.useCallback(async () => {
|
|
72235
|
+
if (!CHECK_PENDING_APPROVALS_BEFORE_SEND) {
|
|
72236
|
+
return { blocked: false };
|
|
72237
|
+
}
|
|
72238
|
+
try {
|
|
72239
|
+
const client = await getClient2();
|
|
72240
|
+
const agent = await client.agents.retrieve(agentId);
|
|
72241
|
+
const { pendingApprovals: existingApprovals } = await getResumeData2(client, agent);
|
|
72242
|
+
if (!existingApprovals || existingApprovals.length === 0) {
|
|
72243
|
+
return { blocked: false };
|
|
72244
|
+
}
|
|
72245
|
+
const approvalResults2 = await Promise.all(existingApprovals.map(async (approvalItem) => {
|
|
72246
|
+
if (!approvalItem.toolName) {
|
|
72247
|
+
return {
|
|
72248
|
+
approval: approvalItem,
|
|
72249
|
+
permission: {
|
|
72250
|
+
decision: "deny",
|
|
72251
|
+
reason: "Tool call incomplete - missing name"
|
|
72252
|
+
},
|
|
72253
|
+
context: null
|
|
72254
|
+
};
|
|
72255
|
+
}
|
|
72256
|
+
const parsedArgs = safeJsonParseOr(approvalItem.toolArgs, {});
|
|
72257
|
+
const permission = await checkToolPermission(approvalItem.toolName, parsedArgs);
|
|
72258
|
+
const context3 = await analyzeToolApproval(approvalItem.toolName, parsedArgs);
|
|
72259
|
+
return { approval: approvalItem, permission, context: context3 };
|
|
72260
|
+
}));
|
|
72261
|
+
const needsUserInput = [];
|
|
72262
|
+
const autoAllowed = [];
|
|
72263
|
+
const autoDenied = [];
|
|
72264
|
+
for (const ac of approvalResults2) {
|
|
72265
|
+
const { approval, permission } = ac;
|
|
72266
|
+
let decision = permission.decision;
|
|
72267
|
+
if (alwaysRequiresUserInput(approval.toolName) && decision === "allow") {
|
|
72268
|
+
decision = "ask";
|
|
72269
|
+
}
|
|
72270
|
+
if (decision === "ask") {
|
|
72271
|
+
needsUserInput.push(ac);
|
|
72272
|
+
} else if (decision === "deny") {
|
|
72273
|
+
autoDenied.push(ac);
|
|
72274
|
+
} else {
|
|
72275
|
+
autoAllowed.push(ac);
|
|
72276
|
+
}
|
|
72277
|
+
}
|
|
72278
|
+
if (needsUserInput.length > 0) {
|
|
72279
|
+
setPendingApprovals(needsUserInput.map((ac) => ac.approval));
|
|
72280
|
+
setApprovalContexts(needsUserInput.map((ac) => ac.context).filter((ctx) => ctx !== null));
|
|
72281
|
+
return { blocked: true };
|
|
72282
|
+
}
|
|
72283
|
+
const allResults = [];
|
|
72284
|
+
if (autoAllowed.length > 0) {
|
|
72285
|
+
const autoAllowedResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk));
|
|
72286
|
+
allResults.push(...autoAllowedResults.map((ar) => ({
|
|
72287
|
+
type: "tool",
|
|
72288
|
+
tool_call_id: ar.toolCallId,
|
|
72289
|
+
tool_return: ar.result.toolReturn,
|
|
72290
|
+
status: ar.result.status,
|
|
72291
|
+
stdout: ar.result.stdout,
|
|
72292
|
+
stderr: ar.result.stderr
|
|
72293
|
+
})));
|
|
72294
|
+
}
|
|
72295
|
+
for (const ac of autoDenied) {
|
|
72296
|
+
const reason = ac.permission.reason || "Permission denied";
|
|
72297
|
+
onChunk(buffersRef.current, {
|
|
72298
|
+
message_type: "tool_return_message",
|
|
72299
|
+
id: "dummy",
|
|
72300
|
+
date: new Date().toISOString(),
|
|
72301
|
+
tool_call_id: ac.approval.toolCallId,
|
|
72302
|
+
tool_return: `Error: request to call tool denied. User reason: ${reason}`,
|
|
72303
|
+
status: "error",
|
|
72304
|
+
stdout: null,
|
|
72305
|
+
stderr: null
|
|
72306
|
+
});
|
|
72307
|
+
allResults.push({
|
|
72308
|
+
type: "approval",
|
|
72309
|
+
tool_call_id: ac.approval.toolCallId,
|
|
72310
|
+
approve: false,
|
|
72311
|
+
reason
|
|
72312
|
+
});
|
|
72313
|
+
}
|
|
72314
|
+
if (allResults.length > 0) {
|
|
72315
|
+
await processConversation([
|
|
72316
|
+
{ type: "approval", approvals: allResults }
|
|
72317
|
+
]);
|
|
72318
|
+
}
|
|
72319
|
+
return { blocked: false };
|
|
72320
|
+
} catch {
|
|
72321
|
+
return { blocked: false };
|
|
72322
|
+
}
|
|
72323
|
+
}, [agentId, processConversation]);
|
|
71764
72324
|
const onSubmit = import_react76.useCallback(async (message) => {
|
|
71765
72325
|
const msg = message?.trim() ?? "";
|
|
71766
72326
|
if (profileConfirmPending && !msg) {
|
|
@@ -71789,6 +72349,7 @@ function App2({
|
|
|
71789
72349
|
}
|
|
71790
72350
|
if (!msg)
|
|
71791
72351
|
return { submitted: false };
|
|
72352
|
+
const submissionGeneration = conversationGenerationRef.current;
|
|
71792
72353
|
telemetry2.trackUserInput(msg, "user", currentModelId || "unknown");
|
|
71793
72354
|
if (pendingApprovals.length > 0) {
|
|
71794
72355
|
return { submitted: false };
|
|
@@ -71801,6 +72362,9 @@ function App2({
|
|
|
71801
72362
|
if (!isSlashCommand && streamingRef.current && !waitingForQueueCancelRef.current) {
|
|
71802
72363
|
waitingForQueueCancelRef.current = true;
|
|
71803
72364
|
queueSnapshotRef.current = [...newQueue];
|
|
72365
|
+
if (toolAbortControllerRef.current) {
|
|
72366
|
+
toolAbortControllerRef.current.abort();
|
|
72367
|
+
}
|
|
71804
72368
|
getClient2().then((client) => client.agents.messages.cancel(agentId)).then(() => {}).catch(() => {
|
|
71805
72369
|
waitingForQueueCancelRef.current = false;
|
|
71806
72370
|
});
|
|
@@ -71809,6 +72373,30 @@ function App2({
|
|
|
71809
72373
|
});
|
|
71810
72374
|
return { submitted: true };
|
|
71811
72375
|
}
|
|
72376
|
+
let justActivatedRalph = false;
|
|
72377
|
+
if (pendingRalphConfig && !msg.startsWith("/")) {
|
|
72378
|
+
const { completionPromise, maxIterations, isYolo } = pendingRalphConfig;
|
|
72379
|
+
ralphMode.activate(msg, completionPromise, maxIterations, isYolo);
|
|
72380
|
+
setUiRalphActive(true);
|
|
72381
|
+
setPendingRalphConfig(null);
|
|
72382
|
+
justActivatedRalph = true;
|
|
72383
|
+
if (isYolo) {
|
|
72384
|
+
permissionMode2.setMode("bypassPermissions");
|
|
72385
|
+
}
|
|
72386
|
+
const ralphState = ralphMode.getState();
|
|
72387
|
+
const statusId = uid4("status");
|
|
72388
|
+
const promiseDisplay = ralphState.completionPromise ? `"${ralphState.completionPromise.slice(0, 50)}${ralphState.completionPromise.length > 50 ? "..." : ""}"` : "(none)";
|
|
72389
|
+
buffersRef.current.byId.set(statusId, {
|
|
72390
|
+
kind: "status",
|
|
72391
|
+
id: statusId,
|
|
72392
|
+
lines: [
|
|
72393
|
+
`\uD83D\uDD04 ${isYolo ? "yolo-ralph" : "ralph"} mode started (iter 1/${maxIterations || "∞"})`,
|
|
72394
|
+
`Promise: ${promiseDisplay}`
|
|
72395
|
+
]
|
|
72396
|
+
});
|
|
72397
|
+
buffersRef.current.order.push(statusId);
|
|
72398
|
+
refreshDerived();
|
|
72399
|
+
}
|
|
71812
72400
|
let aliasedMsg = msg;
|
|
71813
72401
|
if (msg === "exit" || msg === "quit") {
|
|
71814
72402
|
aliasedMsg = "/exit";
|
|
@@ -72029,6 +72617,59 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
72029
72617
|
}
|
|
72030
72618
|
return { submitted: true };
|
|
72031
72619
|
}
|
|
72620
|
+
if (trimmed.startsWith("/yolo-ralph") || trimmed.startsWith("/ralph")) {
|
|
72621
|
+
const isYolo = trimmed.startsWith("/yolo-ralph");
|
|
72622
|
+
const { prompt, completionPromise, maxIterations } = parseRalphArgs(trimmed);
|
|
72623
|
+
const cmdId2 = uid4("cmd");
|
|
72624
|
+
if (prompt) {
|
|
72625
|
+
ralphMode.activate(prompt, completionPromise, maxIterations, isYolo);
|
|
72626
|
+
setUiRalphActive(true);
|
|
72627
|
+
if (isYolo) {
|
|
72628
|
+
permissionMode2.setMode("bypassPermissions");
|
|
72629
|
+
}
|
|
72630
|
+
const ralphState = ralphMode.getState();
|
|
72631
|
+
const promiseDisplay = ralphState.completionPromise ? `"${ralphState.completionPromise.slice(0, 50)}${ralphState.completionPromise.length > 50 ? "..." : ""}"` : "(none)";
|
|
72632
|
+
buffersRef.current.byId.set(cmdId2, {
|
|
72633
|
+
kind: "command",
|
|
72634
|
+
id: cmdId2,
|
|
72635
|
+
input: trimmed,
|
|
72636
|
+
output: `\uD83D\uDD04 ${isYolo ? "yolo-ralph" : "ralph"} mode activated (iter 1/${maxIterations || "∞"})
|
|
72637
|
+
Promise: ${promiseDisplay}`,
|
|
72638
|
+
phase: "finished",
|
|
72639
|
+
success: true
|
|
72640
|
+
});
|
|
72641
|
+
buffersRef.current.order.push(cmdId2);
|
|
72642
|
+
refreshDerived();
|
|
72643
|
+
const systemMsg = buildRalphFirstTurnReminder(ralphState);
|
|
72644
|
+
processConversation([
|
|
72645
|
+
{
|
|
72646
|
+
type: "message",
|
|
72647
|
+
role: "user",
|
|
72648
|
+
content: `${systemMsg}
|
|
72649
|
+
|
|
72650
|
+
${prompt}`
|
|
72651
|
+
}
|
|
72652
|
+
]);
|
|
72653
|
+
} else {
|
|
72654
|
+
setPendingRalphConfig({ completionPromise, maxIterations, isYolo });
|
|
72655
|
+
const defaultPromisePreview = DEFAULT_COMPLETION_PROMISE.slice(0, 40);
|
|
72656
|
+
buffersRef.current.byId.set(cmdId2, {
|
|
72657
|
+
kind: "command",
|
|
72658
|
+
id: cmdId2,
|
|
72659
|
+
input: trimmed,
|
|
72660
|
+
output: `\uD83D\uDD04 ${isYolo ? "yolo-ralph" : "ralph"} mode ready (waiting for task)
|
|
72661
|
+
Max iterations: ${maxIterations || "unlimited"}
|
|
72662
|
+
Promise: ${completionPromise === null ? "(none)" : completionPromise ?? `"${defaultPromisePreview}..." (default)`}
|
|
72663
|
+
|
|
72664
|
+
Type your task to begin the loop.`,
|
|
72665
|
+
phase: "finished",
|
|
72666
|
+
success: true
|
|
72667
|
+
});
|
|
72668
|
+
buffersRef.current.order.push(cmdId2);
|
|
72669
|
+
refreshDerived();
|
|
72670
|
+
}
|
|
72671
|
+
return { submitted: true };
|
|
72672
|
+
}
|
|
72032
72673
|
if (msg.trim() === "/stream") {
|
|
72033
72674
|
const newValue = !tokenStreamingEnabled;
|
|
72034
72675
|
const cmdId2 = uid4("cmd");
|
|
@@ -72479,6 +73120,10 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
72479
73120
|
return { submitted: true };
|
|
72480
73121
|
}
|
|
72481
73122
|
if (trimmed.startsWith("/skill")) {
|
|
73123
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
73124
|
+
if (approvalCheck.blocked) {
|
|
73125
|
+
return { submitted: false };
|
|
73126
|
+
}
|
|
72482
73127
|
const cmdId2 = uid4("cmd");
|
|
72483
73128
|
const [, ...rest] = trimmed.split(/\s+/);
|
|
72484
73129
|
const description = rest.join(" ").trim();
|
|
@@ -72537,6 +73182,10 @@ ${SKILL_CREATOR_PROMPT3}${userDescriptionLine}
|
|
|
72537
73182
|
return { submitted: true };
|
|
72538
73183
|
}
|
|
72539
73184
|
if (trimmed.startsWith("/remember")) {
|
|
73185
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
73186
|
+
if (approvalCheck.blocked) {
|
|
73187
|
+
return { submitted: false };
|
|
73188
|
+
}
|
|
72540
73189
|
const cmdId2 = uid4("cmd");
|
|
72541
73190
|
const [, ...rest] = trimmed.split(/\s+/);
|
|
72542
73191
|
const userText = rest.join(" ").trim();
|
|
@@ -72593,6 +73242,10 @@ The user did not specify what to remember. Look at the recent conversation conte
|
|
|
72593
73242
|
return { submitted: true };
|
|
72594
73243
|
}
|
|
72595
73244
|
if (trimmed === "/init") {
|
|
73245
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
73246
|
+
if (approvalCheck.blocked) {
|
|
73247
|
+
return { submitted: false };
|
|
73248
|
+
}
|
|
72596
73249
|
const cmdId2 = uid4("cmd");
|
|
72597
73250
|
buffersRef.current.byId.set(cmdId2, {
|
|
72598
73251
|
kind: "command",
|
|
@@ -72709,6 +73362,10 @@ ${gitContext}
|
|
|
72709
73362
|
const commandName = trimmed.split(/\s+/)[0]?.slice(1) || "";
|
|
72710
73363
|
const matchedCustom = await findCustomCommand2(commandName);
|
|
72711
73364
|
if (matchedCustom) {
|
|
73365
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
73366
|
+
if (approvalCheck.blocked) {
|
|
73367
|
+
return { submitted: false };
|
|
73368
|
+
}
|
|
72712
73369
|
const cmdId2 = uid4("cmd");
|
|
72713
73370
|
const args = trimmed.slice(`/${matchedCustom.id}`.length).trim();
|
|
72714
73371
|
let prompt = substituteArguments2(matchedCustom.content, args);
|
|
@@ -72799,6 +73456,21 @@ ${prompt}
|
|
|
72799
73456
|
}
|
|
72800
73457
|
const contentParts = buildMessageContentFromDisplay(msg);
|
|
72801
73458
|
const planModeReminder = getPlanModeReminder();
|
|
73459
|
+
let ralphModeReminder = "";
|
|
73460
|
+
if (ralphMode.getState().isActive) {
|
|
73461
|
+
if (justActivatedRalph) {
|
|
73462
|
+
const ralphState = ralphMode.getState();
|
|
73463
|
+
ralphModeReminder = `${buildRalphFirstTurnReminder(ralphState)}
|
|
73464
|
+
|
|
73465
|
+
`;
|
|
73466
|
+
} else {
|
|
73467
|
+
ralphMode.incrementIteration();
|
|
73468
|
+
const ralphState = ralphMode.getState();
|
|
73469
|
+
ralphModeReminder = `${buildRalphContinuationReminder(ralphState)}
|
|
73470
|
+
|
|
73471
|
+
`;
|
|
73472
|
+
}
|
|
73473
|
+
}
|
|
72802
73474
|
const skillUnloadReminder = getSkillUnloadReminder();
|
|
72803
73475
|
let sessionContextReminder = "";
|
|
72804
73476
|
const sessionContextEnabled = settingsManager.getSetting("sessionContextEnabled");
|
|
@@ -72830,7 +73502,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
72830
73502
|
}
|
|
72831
73503
|
const memoryReminderContent = await buildMemoryReminder(turnCountRef.current);
|
|
72832
73504
|
turnCountRef.current += 1;
|
|
72833
|
-
const allReminders = sessionContextReminder + planModeReminder + skillUnloadReminder + bashCommandPrefix + memoryReminderContent;
|
|
73505
|
+
const allReminders = sessionContextReminder + planModeReminder + ralphModeReminder + skillUnloadReminder + bashCommandPrefix + memoryReminderContent;
|
|
72834
73506
|
const messageContent = allReminders && typeof contentParts === "string" ? allReminders + contentParts : Array.isArray(contentParts) && allReminders ? [{ type: "text", text: allReminders }, ...contentParts] : contentParts;
|
|
72835
73507
|
const userId = uid4("user");
|
|
72836
73508
|
buffersRef.current.byId.set(userId, {
|
|
@@ -73108,7 +73780,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73108
73780
|
role: "user",
|
|
73109
73781
|
content: messageContent
|
|
73110
73782
|
});
|
|
73111
|
-
await processConversation(initialInput);
|
|
73783
|
+
await processConversation(initialInput, { submissionGeneration });
|
|
73112
73784
|
clearPlaceholdersInText(msg);
|
|
73113
73785
|
return { submitted: true };
|
|
73114
73786
|
}, [
|
|
@@ -73129,7 +73801,8 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73129
73801
|
tokenStreamingEnabled,
|
|
73130
73802
|
isAgentBusy,
|
|
73131
73803
|
setStreaming,
|
|
73132
|
-
setCommandRunning
|
|
73804
|
+
setCommandRunning,
|
|
73805
|
+
pendingRalphConfig
|
|
73133
73806
|
]);
|
|
73134
73807
|
const onSubmitRef = import_react76.useRef(onSubmit);
|
|
73135
73808
|
import_react76.useEffect(() => {
|
|
@@ -73230,6 +73903,8 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73230
73903
|
setQueuedApprovalResults(allResults);
|
|
73231
73904
|
}
|
|
73232
73905
|
setStreaming(false);
|
|
73906
|
+
waitingForQueueCancelRef.current = false;
|
|
73907
|
+
queueSnapshotRef.current = [];
|
|
73233
73908
|
} else {
|
|
73234
73909
|
await processConversation([
|
|
73235
73910
|
{
|
|
@@ -73727,6 +74402,18 @@ Consider switching to a different system prompt using /system to match.` : null;
|
|
|
73727
74402
|
}
|
|
73728
74403
|
}, [profileConfirmPending, refreshDerived]);
|
|
73729
74404
|
const [uiPermissionMode, setUiPermissionMode] = import_react76.useState(permissionMode2.getMode());
|
|
74405
|
+
const handleRalphExit = import_react76.useCallback(() => {
|
|
74406
|
+
const ralph = ralphMode.getState();
|
|
74407
|
+
if (ralph.isActive) {
|
|
74408
|
+
const wasYolo = ralph.isYolo;
|
|
74409
|
+
ralphMode.deactivate();
|
|
74410
|
+
setUiRalphActive(false);
|
|
74411
|
+
if (wasYolo) {
|
|
74412
|
+
permissionMode2.setMode("default");
|
|
74413
|
+
setUiPermissionMode("default");
|
|
74414
|
+
}
|
|
74415
|
+
}
|
|
74416
|
+
}, []);
|
|
73730
74417
|
const handlePermissionModeChange = import_react76.useCallback((mode) => {
|
|
73731
74418
|
if (mode === "plan") {
|
|
73732
74419
|
const planPath = generatePlanFilePath();
|
|
@@ -74001,7 +74688,6 @@ Plan file path: ${planFilePath}`;
|
|
|
74001
74688
|
]);
|
|
74002
74689
|
return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
|
|
74003
74690
|
flexDirection: "column",
|
|
74004
|
-
gap: 1,
|
|
74005
74691
|
children: [
|
|
74006
74692
|
/* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Static, {
|
|
74007
74693
|
items: staticItems,
|
|
@@ -74047,7 +74733,6 @@ Plan file path: ${planFilePath}`;
|
|
|
74047
74733
|
}, staticRenderEpoch, false, undefined, this),
|
|
74048
74734
|
/* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
|
|
74049
74735
|
flexDirection: "column",
|
|
74050
|
-
gap: 1,
|
|
74051
74736
|
children: [
|
|
74052
74737
|
loadingState !== "ready" && /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(WelcomeScreen, {
|
|
74053
74738
|
loadingState,
|
|
@@ -74242,7 +74927,7 @@ Plan file path: ${planFilePath}`;
|
|
|
74242
74927
|
]
|
|
74243
74928
|
}, undefined, true, undefined, this),
|
|
74244
74929
|
/* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
|
|
74245
|
-
marginTop:
|
|
74930
|
+
marginTop: 1,
|
|
74246
74931
|
children: /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Input, {
|
|
74247
74932
|
visible: !showExitStats && pendingApprovals.length === 0 && !anySelectorOpen,
|
|
74248
74933
|
streaming: streaming && !abortControllerRef.current?.signal.aborted,
|
|
@@ -74261,7 +74946,11 @@ Plan file path: ${planFilePath}`;
|
|
|
74261
74946
|
currentModelProvider,
|
|
74262
74947
|
messageQueue,
|
|
74263
74948
|
onEnterQueueEditMode: handleEnterQueueEditMode,
|
|
74264
|
-
onEscapeCancel: profileConfirmPending ? handleProfileEscapeCancel : undefined
|
|
74949
|
+
onEscapeCancel: profileConfirmPending ? handleProfileEscapeCancel : undefined,
|
|
74950
|
+
ralphActive: uiRalphActive,
|
|
74951
|
+
ralphPending: pendingRalphConfig !== null,
|
|
74952
|
+
ralphPendingYolo: pendingRalphConfig?.isYolo ?? false,
|
|
74953
|
+
onRalphExit: handleRalphExit
|
|
74265
74954
|
}, undefined, false, undefined, this)
|
|
74266
74955
|
}, undefined, false, undefined, this),
|
|
74267
74956
|
activeOverlay === "model" && /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(ModelSelector, {
|
|
@@ -74426,6 +75115,7 @@ var init_App2 = __esm(async () => {
|
|
|
74426
75115
|
init_context();
|
|
74427
75116
|
init_model();
|
|
74428
75117
|
init_mode();
|
|
75118
|
+
init_mode2();
|
|
74429
75119
|
init_settings();
|
|
74430
75120
|
init_colors();
|
|
74431
75121
|
init_SessionStats();
|
|
@@ -74514,7 +75204,7 @@ __export(exports_terminalKeybindingInstaller2, {
|
|
|
74514
75204
|
});
|
|
74515
75205
|
import {
|
|
74516
75206
|
copyFileSync as copyFileSync2,
|
|
74517
|
-
existsSync as
|
|
75207
|
+
existsSync as existsSync12,
|
|
74518
75208
|
mkdirSync as mkdirSync4,
|
|
74519
75209
|
readFileSync as readFileSync5,
|
|
74520
75210
|
writeFileSync as writeFileSync3
|
|
@@ -74583,7 +75273,7 @@ function parseKeybindings2(content) {
|
|
|
74583
75273
|
}
|
|
74584
75274
|
}
|
|
74585
75275
|
function keybindingExists2(keybindingsPath) {
|
|
74586
|
-
if (!
|
|
75276
|
+
if (!existsSync12(keybindingsPath))
|
|
74587
75277
|
return false;
|
|
74588
75278
|
try {
|
|
74589
75279
|
const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -74596,7 +75286,7 @@ function keybindingExists2(keybindingsPath) {
|
|
|
74596
75286
|
}
|
|
74597
75287
|
}
|
|
74598
75288
|
function createBackup2(keybindingsPath) {
|
|
74599
|
-
if (!
|
|
75289
|
+
if (!existsSync12(keybindingsPath))
|
|
74600
75290
|
return null;
|
|
74601
75291
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
74602
75292
|
try {
|
|
@@ -74612,12 +75302,12 @@ function installKeybinding2(keybindingsPath) {
|
|
|
74612
75302
|
return { success: true, alreadyExists: true };
|
|
74613
75303
|
}
|
|
74614
75304
|
const parentDir = dirname12(keybindingsPath);
|
|
74615
|
-
if (!
|
|
75305
|
+
if (!existsSync12(parentDir)) {
|
|
74616
75306
|
mkdirSync4(parentDir, { recursive: true });
|
|
74617
75307
|
}
|
|
74618
75308
|
let keybindings = [];
|
|
74619
75309
|
let backupPath = null;
|
|
74620
|
-
if (
|
|
75310
|
+
if (existsSync12(keybindingsPath)) {
|
|
74621
75311
|
backupPath = createBackup2(keybindingsPath);
|
|
74622
75312
|
const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
|
|
74623
75313
|
const parsed = parseKeybindings2(content);
|
|
@@ -74647,7 +75337,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
74647
75337
|
}
|
|
74648
75338
|
function removeKeybinding2(keybindingsPath) {
|
|
74649
75339
|
try {
|
|
74650
|
-
if (!
|
|
75340
|
+
if (!existsSync12(keybindingsPath)) {
|
|
74651
75341
|
return { success: true };
|
|
74652
75342
|
}
|
|
74653
75343
|
const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -74715,16 +75405,16 @@ function getWezTermConfigPath2() {
|
|
|
74715
75405
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
74716
75406
|
if (xdgConfig) {
|
|
74717
75407
|
const xdgPath = join17(xdgConfig, "wezterm", "wezterm.lua");
|
|
74718
|
-
if (
|
|
75408
|
+
if (existsSync12(xdgPath))
|
|
74719
75409
|
return xdgPath;
|
|
74720
75410
|
}
|
|
74721
75411
|
const configPath = join17(homedir8(), ".config", "wezterm", "wezterm.lua");
|
|
74722
|
-
if (
|
|
75412
|
+
if (existsSync12(configPath))
|
|
74723
75413
|
return configPath;
|
|
74724
75414
|
return join17(homedir8(), ".wezterm.lua");
|
|
74725
75415
|
}
|
|
74726
75416
|
function wezTermDeleteFixExists2(configPath) {
|
|
74727
|
-
if (!
|
|
75417
|
+
if (!existsSync12(configPath))
|
|
74728
75418
|
return false;
|
|
74729
75419
|
try {
|
|
74730
75420
|
const content = readFileSync5(configPath, { encoding: "utf-8" });
|
|
@@ -74741,7 +75431,7 @@ function installWezTermDeleteFix2() {
|
|
|
74741
75431
|
}
|
|
74742
75432
|
let content = "";
|
|
74743
75433
|
let backupPath = null;
|
|
74744
|
-
if (
|
|
75434
|
+
if (existsSync12(configPath)) {
|
|
74745
75435
|
backupPath = `${configPath}.letta-backup`;
|
|
74746
75436
|
copyFileSync2(configPath, backupPath);
|
|
74747
75437
|
content = readFileSync5(configPath, { encoding: "utf-8" });
|
|
@@ -74771,7 +75461,7 @@ ${WEZTERM_DELETE_FIX2}
|
|
|
74771
75461
|
`;
|
|
74772
75462
|
}
|
|
74773
75463
|
const parentDir = dirname12(configPath);
|
|
74774
|
-
if (!
|
|
75464
|
+
if (!existsSync12(parentDir)) {
|
|
74775
75465
|
mkdirSync4(parentDir, { recursive: true });
|
|
74776
75466
|
}
|
|
74777
75467
|
writeFileSync3(configPath, content, { encoding: "utf-8" });
|
|
@@ -75941,6 +76631,20 @@ class PermissionModeManager {
|
|
|
75941
76631
|
return "allow";
|
|
75942
76632
|
}
|
|
75943
76633
|
}
|
|
76634
|
+
const readOnlySubagentTypes = new Set([
|
|
76635
|
+
"explore",
|
|
76636
|
+
"Explore",
|
|
76637
|
+
"plan",
|
|
76638
|
+
"Plan",
|
|
76639
|
+
"recall",
|
|
76640
|
+
"Recall"
|
|
76641
|
+
]);
|
|
76642
|
+
if (toolName === "Task" || toolName === "task") {
|
|
76643
|
+
const subagentType = toolArgs?.subagent_type;
|
|
76644
|
+
if (subagentType && readOnlySubagentTypes.has(subagentType)) {
|
|
76645
|
+
return "allow";
|
|
76646
|
+
}
|
|
76647
|
+
}
|
|
75944
76648
|
const shellTools = [
|
|
75945
76649
|
"Bash",
|
|
75946
76650
|
"shell",
|
|
@@ -77314,9 +78018,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
77314
78018
|
process.exit(1);
|
|
77315
78019
|
}
|
|
77316
78020
|
const { resolve: resolve19 } = await import("path");
|
|
77317
|
-
const { existsSync:
|
|
78021
|
+
const { existsSync: existsSync13 } = await import("fs");
|
|
77318
78022
|
const resolvedPath = resolve19(fromAfFile);
|
|
77319
|
-
if (!
|
|
78023
|
+
if (!existsSync13(resolvedPath)) {
|
|
77320
78024
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
77321
78025
|
process.exit(1);
|
|
77322
78026
|
}
|
|
@@ -77556,13 +78260,19 @@ Error: ${message}`);
|
|
|
77556
78260
|
try {
|
|
77557
78261
|
await client.agents.retrieve(localProjectSettings.lastAgent);
|
|
77558
78262
|
resumingAgentId = localProjectSettings.lastAgent;
|
|
77559
|
-
} catch {
|
|
78263
|
+
} catch {
|
|
78264
|
+
setLoadingState("selecting_global");
|
|
78265
|
+
return;
|
|
78266
|
+
}
|
|
77560
78267
|
}
|
|
77561
78268
|
if (!resumingAgentId && continueSession && settings.lastAgent) {
|
|
77562
78269
|
try {
|
|
77563
78270
|
await client.agents.retrieve(settings.lastAgent);
|
|
77564
78271
|
resumingAgentId = settings.lastAgent;
|
|
77565
|
-
} catch {
|
|
78272
|
+
} catch {
|
|
78273
|
+
setLoadingState("selecting_global");
|
|
78274
|
+
return;
|
|
78275
|
+
}
|
|
77566
78276
|
}
|
|
77567
78277
|
if (!resumingAgentId && selectedGlobalAgentId) {
|
|
77568
78278
|
try {
|
|
@@ -77617,22 +78327,22 @@ Error: ${message}`);
|
|
|
77617
78327
|
agent = result.agent;
|
|
77618
78328
|
setAgentProvenance(result.provenance);
|
|
77619
78329
|
}
|
|
77620
|
-
if (!agent) {
|
|
77621
|
-
|
|
77622
|
-
|
|
77623
|
-
|
|
77624
|
-
|
|
77625
|
-
|
|
77626
|
-
|
|
77627
|
-
console.error(`Project agent ${localProjectSettings.lastAgent} not found (error: ${JSON.stringify(error)}), creating new one...`);
|
|
77628
|
-
}
|
|
78330
|
+
if (!agent && resumingAgentId) {
|
|
78331
|
+
try {
|
|
78332
|
+
agent = await client.agents.retrieve(resumingAgentId);
|
|
78333
|
+
} catch (error) {
|
|
78334
|
+
console.error(`Agent ${resumingAgentId} not found (error: ${JSON.stringify(error)})`);
|
|
78335
|
+
setLoadingState("selecting_global");
|
|
78336
|
+
return;
|
|
77629
78337
|
}
|
|
77630
78338
|
}
|
|
77631
78339
|
if (!agent && continueSession && settings.lastAgent) {
|
|
77632
78340
|
try {
|
|
77633
78341
|
agent = await client.agents.retrieve(settings.lastAgent);
|
|
77634
78342
|
} catch (error) {
|
|
77635
|
-
console.error(`Previous agent ${settings.lastAgent} not found (error: ${JSON.stringify(error)})
|
|
78343
|
+
console.error(`Previous agent ${settings.lastAgent} not found (error: ${JSON.stringify(error)})`);
|
|
78344
|
+
setLoadingState("selecting_global");
|
|
78345
|
+
return;
|
|
77636
78346
|
}
|
|
77637
78347
|
}
|
|
77638
78348
|
if (!agent) {
|
|
@@ -77795,4 +78505,4 @@ Error during initialization: ${message}`);
|
|
|
77795
78505
|
}
|
|
77796
78506
|
main();
|
|
77797
78507
|
|
|
77798
|
-
//# debugId=
|
|
78508
|
+
//# debugId=D15B3A68114566C264756E2164756E21
|