feat: add Ralph Wiggum mode (#484)
Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import type { PermissionMode } from "../../permissions/mode";
|
||||
import { permissionMode } from "../../permissions/mode";
|
||||
import { ANTHROPIC_PROVIDER_NAME } from "../../providers/anthropic-provider";
|
||||
import { ralphMode } from "../../ralph/mode";
|
||||
import { settingsManager } from "../../settings-manager";
|
||||
import { charsToTokens, formatCompact } from "../helpers/format";
|
||||
import { useTerminalWidth } from "../hooks/useTerminalWidth";
|
||||
@@ -56,6 +57,10 @@ export function Input({
|
||||
messageQueue,
|
||||
onEnterQueueEditMode,
|
||||
onEscapeCancel,
|
||||
ralphActive = false,
|
||||
ralphPending = false,
|
||||
ralphPendingYolo = false,
|
||||
onRalphExit,
|
||||
}: {
|
||||
visible?: boolean;
|
||||
streaming: boolean;
|
||||
@@ -75,6 +80,10 @@ export function Input({
|
||||
messageQueue?: string[];
|
||||
onEnterQueueEditMode?: () => void;
|
||||
onEscapeCancel?: () => void;
|
||||
ralphActive?: boolean;
|
||||
ralphPending?: boolean;
|
||||
ralphPendingYolo?: boolean;
|
||||
onRalphExit?: () => void;
|
||||
}) {
|
||||
const [value, setValue] = useState("");
|
||||
const [escapePressed, setEscapePressed] = useState(false);
|
||||
@@ -236,7 +245,7 @@ export function Input({
|
||||
// Note: bash mode entry/exit is implemented inside PasteAwareTextInput so we can
|
||||
// consume the keystroke before it renders (no flicker).
|
||||
|
||||
// Handle Shift+Tab for permission mode cycling
|
||||
// Handle Shift+Tab for permission mode cycling (or ralph mode exit)
|
||||
useInput((_input, key) => {
|
||||
if (!visible) return;
|
||||
// Debug logging for shift+tab detection
|
||||
@@ -247,6 +256,12 @@ export function Input({
|
||||
);
|
||||
}
|
||||
if (key.shift && key.tab) {
|
||||
// If ralph mode is active, exit it first (goes to default mode)
|
||||
if (ralphActive && onRalphExit) {
|
||||
onRalphExit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Cycle through permission modes
|
||||
const modes: PermissionMode[] = [
|
||||
"default",
|
||||
@@ -570,8 +585,43 @@ export function Input({
|
||||
setCursorPos(selectedCommand.length);
|
||||
};
|
||||
|
||||
// Get display name and color for permission mode
|
||||
// Get display name and color for permission mode (ralph modes take precedence)
|
||||
const getModeInfo = () => {
|
||||
// Check ralph pending first (waiting for task input)
|
||||
if (ralphPending) {
|
||||
if (ralphPendingYolo) {
|
||||
return {
|
||||
name: "yolo-ralph (waiting)",
|
||||
color: "#FF8C00", // dark orange
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: "ralph (waiting)",
|
||||
color: "#FEE19C", // yellow (brandColors.statusWarning)
|
||||
};
|
||||
}
|
||||
|
||||
// Check ralph mode active (using prop for reactivity)
|
||||
if (ralphActive) {
|
||||
const ralph = ralphMode.getState();
|
||||
const iterDisplay =
|
||||
ralph.maxIterations > 0
|
||||
? `${ralph.currentIteration}/${ralph.maxIterations}`
|
||||
: `${ralph.currentIteration}`;
|
||||
|
||||
if (ralph.isYolo) {
|
||||
return {
|
||||
name: `yolo-ralph (iter ${iterDisplay})`,
|
||||
color: "#FF8C00", // dark orange
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: `ralph (iter ${iterDisplay})`,
|
||||
color: "#FEE19C", // yellow (brandColors.statusWarning)
|
||||
};
|
||||
}
|
||||
|
||||
// Fall through to permission modes
|
||||
switch (currentMode) {
|
||||
case "acceptEdits":
|
||||
return { name: "accept edits", color: colors.status.processing };
|
||||
@@ -597,6 +647,7 @@ export function Input({
|
||||
const elapsedMinutes = Math.floor(elapsedMs / 60000);
|
||||
|
||||
// Build the status hint text (esc to interrupt · 2m · 1.2k ↑)
|
||||
// In ralph mode, also show "shift+tab to exit"
|
||||
const statusHintText = (() => {
|
||||
const hintColor = chalk.hex(colors.subagent.hint);
|
||||
const hintBold = hintColor.bold;
|
||||
@@ -716,7 +767,7 @@ export function Input({
|
||||
<Text color={modeInfo.color}>⏵⏵ {modeInfo.name}</Text>
|
||||
<Text color={modeInfo.color} dimColor>
|
||||
{" "}
|
||||
(shift+tab to cycle)
|
||||
(shift+tab to {ralphActive || ralphPending ? "exit" : "cycle"})
|
||||
</Text>
|
||||
</Text>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user