praxis-agent 0.5.2 → 0.7.0
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 +7 -5
- package/dist/cli/interactive.d.ts +10 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +287 -5
- package/dist/cli/interactive.js.map +1 -1
- package/dist/cli/tui/claude-style.d.ts +20 -0
- package/dist/cli/tui/claude-style.d.ts.map +1 -1
- package/dist/cli/tui/claude-style.js +66 -0
- package/dist/cli/tui/claude-style.js.map +1 -1
- package/dist/cli/tui/hook-settings.d.ts +33 -0
- package/dist/cli/tui/hook-settings.d.ts.map +1 -0
- package/dist/cli/tui/hook-settings.js +200 -0
- package/dist/cli/tui/hook-settings.js.map +1 -0
- package/dist/cli/tui/memory-files.d.ts +25 -0
- package/dist/cli/tui/memory-files.d.ts.map +1 -0
- package/dist/cli/tui/memory-files.js +141 -0
- package/dist/cli/tui/memory-files.js.map +1 -0
- package/dist/cli/tui/slash-commands.d.ts.map +1 -1
- package/dist/cli/tui/slash-commands.js +10 -0
- package/dist/cli/tui/slash-commands.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +44 -5
- package/dist/cli.js.map +1 -1
- package/dist/compatibility/claude/shared-resources.d.ts +7 -0
- package/dist/compatibility/claude/shared-resources.d.ts.map +1 -1
- package/dist/compatibility/claude/shared-resources.js +102 -4
- package/dist/compatibility/claude/shared-resources.js.map +1 -1
- package/dist/plugins/claude-plugin-runtime.d.ts +1 -0
- package/dist/plugins/claude-plugin-runtime.d.ts.map +1 -1
- package/dist/plugins/claude-plugin-runtime.js +49 -21
- package/dist/plugins/claude-plugin-runtime.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -83,10 +83,11 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
|
83
83
|
restored active-branch conversation history, streaming and expandable
|
|
84
84
|
thinking, grouped multi-file reads, globally expandable tool results,
|
|
85
85
|
command-specific `/add-dir`, `/copy`, `/branch`, `/rename`, `/export`,
|
|
86
|
-
provider-
|
|
86
|
+
provider-free read-only shared `/hooks`, provider-backed `/compact`, native
|
|
87
|
+
`/rewind`, runtime `/cd`, transcript-free
|
|
87
88
|
`/btw` side questions with background-Agent handoff, interactive
|
|
88
|
-
`/background` terminal handoff, `/config`, `/usage`, `/mcp`,
|
|
89
|
-
extension-reload controls,
|
|
89
|
+
`/background` terminal handoff, `/config`, `/usage`, `/mcp`, `/memory` shared
|
|
90
|
+
instruction and auto-memory access, and live extension-reload controls,
|
|
90
91
|
cursor/history composer, per-session model/effort/permission controls,
|
|
91
92
|
context/status/skill/task dashboards, prompt stash and continuation shortcuts,
|
|
92
93
|
filterable `@` file and agent references, composer undo, `Ctrl+G` external
|
|
@@ -103,8 +104,9 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
|
103
104
|
credential redaction, and sanitized child processes.
|
|
104
105
|
- **Durable local work** — resumable sessions, full-history forks, file
|
|
105
106
|
checkpoints, tasks, foreground/background subagents, and top-level agents.
|
|
106
|
-
- **Claude-compatible ecosystem** — shared instructions
|
|
107
|
-
commands, agents, hooks, settings, MCP servers,
|
|
107
|
+
- **Claude-compatible ecosystem** — shared instructions with recursive `@`
|
|
108
|
+
imports, memory, skills, commands, agents, hooks, settings, MCP servers,
|
|
109
|
+
plugins, and transcript data.
|
|
108
110
|
- **Provider-neutral models** — native Anthropic Messages and OpenAI-compatible
|
|
109
111
|
streaming adapters with explicit capability checks and metering controls.
|
|
110
112
|
|
|
@@ -4,9 +4,11 @@ import type { CliElicitationRequest, CliElicitationResult, CliRuntimeInfo } from
|
|
|
4
4
|
import type { ClaudeInteractiveToolCallbacks } from '../tools/claude-interactive-tools.js';
|
|
5
5
|
import type { ClaudePermissionMode } from '../permissions/claude-permission-resolver.js';
|
|
6
6
|
import { type TranscriptItem, type TuiDisplayMetadata } from './tui/claude-style.js';
|
|
7
|
+
import { type TuiMemoryFiles } from './tui/memory-files.js';
|
|
7
8
|
import { type TuiDiffSnapshot } from './tui/git-diff.js';
|
|
8
9
|
import { type TuiPermissionBehavior, type TuiPermissionRule } from './tui/permission-settings.js';
|
|
9
10
|
import type { ClaudeResourceScope } from '../compatibility/claude/shared-resources.js';
|
|
11
|
+
import type { TuiHookConfiguration } from './tui/hook-settings.js';
|
|
10
12
|
import { type TuiSlashCommand } from './tui/slash-commands.js';
|
|
11
13
|
import { type TuiAgentEntry, type TuiFileEntry } from './tui/file-picker.js';
|
|
12
14
|
import { type TuiEditorOptions, type TuiEditorResult } from './tui/external-editor.js';
|
|
@@ -34,6 +36,7 @@ interface InteractiveSessionCommands {
|
|
|
34
36
|
rename?(sessionId: string, name: string): Promise<void>;
|
|
35
37
|
sessionNameSuggestion?(sessionId: string, signal?: AbortSignal): Promise<string | null>;
|
|
36
38
|
workflows?(): readonly Record<string, unknown>[];
|
|
39
|
+
hookConfiguration?(): Promise<TuiHookConfiguration>;
|
|
37
40
|
slashCommands?(): readonly TuiSlashCommand[];
|
|
38
41
|
agentDefinitions?(): readonly TuiAgentEntry[];
|
|
39
42
|
runtimeInfo?(): CliRuntimeInfo;
|
|
@@ -49,6 +52,7 @@ export interface InteractiveServiceFactory {
|
|
|
49
52
|
createService(options: {
|
|
50
53
|
eventSink: RuntimeEventSink;
|
|
51
54
|
requireProvider: boolean;
|
|
55
|
+
hooksOnly?: boolean;
|
|
52
56
|
approveRecovery?: (call: ModelToolCall) => boolean | Promise<boolean>;
|
|
53
57
|
approveTool?: (call: ModelToolCall) => boolean | Promise<boolean>;
|
|
54
58
|
onElicitation?: (request: CliElicitationRequest) => Promise<CliElicitationResult>;
|
|
@@ -110,6 +114,11 @@ interface InteractiveAppProps {
|
|
|
110
114
|
keybindingsEditor?: (path: string, options: TuiEditorOptions) => Promise<{
|
|
111
115
|
editorName: string;
|
|
112
116
|
}>;
|
|
117
|
+
memoryFilesLoader?: (configRoot: string, cwd: string) => Promise<TuiMemoryFiles>;
|
|
118
|
+
memoryEditor?: (path: string, options: TuiEditorOptions) => Promise<{
|
|
119
|
+
editorName: string;
|
|
120
|
+
}>;
|
|
121
|
+
memoryFolderOpener?: (path: string) => Promise<void>;
|
|
113
122
|
suspendProcess?: () => void | Promise<void>;
|
|
114
123
|
clipboardReader?: () => Promise<TuiClipboardContent>;
|
|
115
124
|
clipboardWriter?: (text: string) => Promise<void>;
|
|
@@ -127,7 +136,7 @@ interface InteractiveAppProps {
|
|
|
127
136
|
workspaceDirectoryResolver?: typeof resolveTuiWorkspaceDirectory;
|
|
128
137
|
workspaceDirectoryCompleter?: typeof completeTuiWorkspaceDirectory;
|
|
129
138
|
}
|
|
130
|
-
export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, workspaceDirectoryResolver, workspaceDirectoryCompleter, }: InteractiveAppProps): import("react").JSX.Element;
|
|
139
|
+
export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, workspaceDirectoryResolver, workspaceDirectoryCompleter, }: InteractiveAppProps): import("react").JSX.Element;
|
|
131
140
|
export declare function runInteractive(options: {
|
|
132
141
|
factory: InteractiveServiceFactory;
|
|
133
142
|
initialPrompt?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,UAAU,EACV,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EAGb,gBAAgB,EACjB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACf,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EACV,8BAA8B,EAI/B,MAAM,sCAAsC,CAAA;AAC7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAA;AAKxF,OAAO,
|
|
1
|
+
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.tsx"],"names":[],"mappings":"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"}
|
package/dist/cli/interactive.js
CHANGED
|
@@ -5,7 +5,8 @@ import { useEffect, useMemo, useRef, useState } from 'react';
|
|
|
5
5
|
import { Box, Text, render, useApp, useInput } from 'ink';
|
|
6
6
|
import { AgentRunCancelledError } from '../core/runtime.js';
|
|
7
7
|
import { redactSensitiveText, sensitiveEnvironmentValues, } from '../platform/sensitive-data.js';
|
|
8
|
-
import { CommandPalette, BtwPanel, Composer, DiffDashboard, DialogFrame, ExternalEditorWait, HelpMenu, ListDashboard, MentionPicker, PermissionDashboard, SelectionMenu, SessionPicker, StatusDashboard, Transcript, WelcomePanel, useTerminalWidth, } from './tui/claude-style.js';
|
|
8
|
+
import { CommandPalette, BtwPanel, Composer, DiffDashboard, DialogFrame, ExternalEditorWait, HelpMenu, HookDashboard, ListDashboard, MemoryDashboard, MentionPicker, PermissionDashboard, SelectionMenu, SessionPicker, StatusDashboard, Transcript, WelcomePanel, useTerminalWidth, } from './tui/claude-style.js';
|
|
9
|
+
import { loadTuiMemoryFiles, openTuiMemoryFolder, } from './tui/memory-files.js';
|
|
9
10
|
import { loadGitDiff, visiblePatchLines, } from './tui/git-diff.js';
|
|
10
11
|
import { addTuiPermissionRule, loadTuiPermissionRules, removeTuiPermissionRule, } from './tui/permission-settings.js';
|
|
11
12
|
import { filterTuiSlashCommands, mergeTuiSlashCommands, slashCommandQuery, } from './tui/slash-commands.js';
|
|
@@ -186,7 +187,7 @@ function ordinal(value) {
|
|
|
186
187
|
return `${value}th`;
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
|
-
export function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory = [], signal, onCancel, onTurnChange, onCleanup, onBackground, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, sideQuestionClipboardWriter = writeTuiOsc52Clipboard, exportWriter = writeConversationExport, permissionRuleStore, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, }) {
|
|
190
|
+
export function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory = [], signal, onCancel, onTurnChange, onCleanup, onBackground, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, memoryFilesLoader = (configRoot, cwd) => loadTuiMemoryFiles({ configRoot, cwd }), memoryEditor = openTuiEditorFile, memoryFolderOpener = openTuiMemoryFolder, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, sideQuestionClipboardWriter = writeTuiOsc52Clipboard, exportWriter = writeConversationExport, permissionRuleStore, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, }) {
|
|
190
191
|
const { exit, suspendTerminal, waitUntilRenderFlush } = useApp();
|
|
191
192
|
const width = useTerminalWidth(terminalWidth);
|
|
192
193
|
const keybindingsRoot = useMemo(() => resolve(keybindingsConfigRoot ??
|
|
@@ -240,6 +241,10 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
240
241
|
const [shortcutsVisible, setShortcutsVisible] = useState(false);
|
|
241
242
|
const [externalEditorRequest, setExternalEditorRequest] = useState(null);
|
|
242
243
|
const [keybindingsEditing, setKeybindingsEditing] = useState(false);
|
|
244
|
+
const [memoryEditorRequest, setMemoryEditorRequest] = useState(null);
|
|
245
|
+
const memoryEditorRequestRef = useRef(null);
|
|
246
|
+
const memoryMenuGenerationRef = useRef(0);
|
|
247
|
+
const memoryFolderOpeningRef = useRef(null);
|
|
243
248
|
const [keybindings, setKeybindings] = useState(defaultTuiKeybindings);
|
|
244
249
|
const keySequenceRef = useRef(null);
|
|
245
250
|
const [processSuspendRequested, setProcessSuspendRequested] = useState(false);
|
|
@@ -605,6 +610,37 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
605
610
|
onTurnChange?.(editing);
|
|
606
611
|
void editing.finally(() => onTurnChange?.(null));
|
|
607
612
|
}, [keybindingsEditing]);
|
|
613
|
+
useEffect(() => {
|
|
614
|
+
if (memoryEditorRequest === null)
|
|
615
|
+
return;
|
|
616
|
+
const editing = (async () => {
|
|
617
|
+
try {
|
|
618
|
+
await waitUntilRenderFlush();
|
|
619
|
+
let editorName = 'your editor';
|
|
620
|
+
await suspendTerminal(async () => {
|
|
621
|
+
const editor = await memoryEditor(memoryEditorRequest.path, {
|
|
622
|
+
cwd: runtimeCwdRef.current,
|
|
623
|
+
...(signal === undefined ? {} : { signal }),
|
|
624
|
+
});
|
|
625
|
+
editorName = editor.editorName;
|
|
626
|
+
});
|
|
627
|
+
append({
|
|
628
|
+
kind: 'local-result',
|
|
629
|
+
text: `Opened memory file at ${memoryEditorRequest.displayPath}\n\n ▎ Using ${editorName}. To change editor, set $EDITOR or $VISUAL environment variable.`,
|
|
630
|
+
});
|
|
631
|
+
await retireService();
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
warn(error);
|
|
635
|
+
}
|
|
636
|
+
finally {
|
|
637
|
+
memoryEditorRequestRef.current = null;
|
|
638
|
+
setMemoryEditorRequest(null);
|
|
639
|
+
}
|
|
640
|
+
})();
|
|
641
|
+
onTurnChange?.(editing);
|
|
642
|
+
void editing.finally(() => onTurnChange?.(null));
|
|
643
|
+
}, [memoryEditorRequest]);
|
|
608
644
|
useEffect(() => {
|
|
609
645
|
if (!processSuspendRequested)
|
|
610
646
|
return;
|
|
@@ -2196,7 +2232,63 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
2196
2232
|
}
|
|
2197
2233
|
return;
|
|
2198
2234
|
}
|
|
2199
|
-
|
|
2235
|
+
const earlyMenu = menuRef.current;
|
|
2236
|
+
if (earlyMenu?.kind === 'memory') {
|
|
2237
|
+
if (key.escape || value === '\u001B') {
|
|
2238
|
+
updateMenu(null);
|
|
2239
|
+
append({ kind: 'local-result', text: 'Cancelled memory editing' });
|
|
2240
|
+
return;
|
|
2241
|
+
}
|
|
2242
|
+
if (earlyMenu.loading)
|
|
2243
|
+
return;
|
|
2244
|
+
if (key.upArrow || key.downArrow) {
|
|
2245
|
+
updateMenu({
|
|
2246
|
+
...earlyMenu,
|
|
2247
|
+
selectedIndex: Math.max(0, Math.min(Math.max(0, earlyMenu.entries.length - 1), earlyMenu.selectedIndex + (key.upArrow ? -1 : 1))),
|
|
2248
|
+
});
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
const numericIndex = /^[1-9]$/u.test(value) ? Number(value) - 1 : null;
|
|
2252
|
+
if (!key.return && numericIndex === null)
|
|
2253
|
+
return;
|
|
2254
|
+
const selectedIndex = numericIndex ?? earlyMenu.selectedIndex;
|
|
2255
|
+
const entry = earlyMenu.entries[selectedIndex];
|
|
2256
|
+
if (!entry)
|
|
2257
|
+
return;
|
|
2258
|
+
if (entry.kind === 'folder') {
|
|
2259
|
+
const generation = earlyMenu.generation;
|
|
2260
|
+
if (memoryFolderOpeningRef.current?.generation === generation)
|
|
2261
|
+
return;
|
|
2262
|
+
memoryFolderOpeningRef.current = { generation, index: selectedIndex };
|
|
2263
|
+
const opening = memoryFolderOpener(entry.path).then(() => {
|
|
2264
|
+
if (menuRef.current?.kind === 'memory' &&
|
|
2265
|
+
menuRef.current.generation === generation) {
|
|
2266
|
+
updateMenu({
|
|
2267
|
+
...menuRef.current,
|
|
2268
|
+
selectedIndex,
|
|
2269
|
+
openedIndex: selectedIndex,
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
});
|
|
2273
|
+
onTurnChange?.(opening);
|
|
2274
|
+
void opening.catch(warn).finally(() => {
|
|
2275
|
+
if (memoryFolderOpeningRef.current?.generation === generation &&
|
|
2276
|
+
memoryFolderOpeningRef.current.index === selectedIndex) {
|
|
2277
|
+
memoryFolderOpeningRef.current = null;
|
|
2278
|
+
onTurnChange?.(null);
|
|
2279
|
+
}
|
|
2280
|
+
});
|
|
2281
|
+
}
|
|
2282
|
+
else {
|
|
2283
|
+
updateMenu(null);
|
|
2284
|
+
memoryEditorRequestRef.current = entry;
|
|
2285
|
+
setMemoryEditorRequest(entry);
|
|
2286
|
+
}
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
if (externalEditorRequest !== null ||
|
|
2290
|
+
keybindingsEditing ||
|
|
2291
|
+
memoryEditorRequestRef.current !== null)
|
|
2200
2292
|
return;
|
|
2201
2293
|
if (clipboardPendingRef.current > 0) {
|
|
2202
2294
|
if (isKeybinding('chat:imagePaste'))
|
|
@@ -2754,6 +2846,101 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
2754
2846
|
}
|
|
2755
2847
|
return;
|
|
2756
2848
|
}
|
|
2849
|
+
if (activeMenu.kind === 'hooks') {
|
|
2850
|
+
const event = activeMenu.configuration.events[activeMenu.eventIndex];
|
|
2851
|
+
const matcher = event?.matchers[activeMenu.matcherIndex];
|
|
2852
|
+
const length = activeMenu.depth === 'events'
|
|
2853
|
+
? activeMenu.configuration.events.length
|
|
2854
|
+
: activeMenu.depth === 'matchers'
|
|
2855
|
+
? (event?.matchers.length ?? 0)
|
|
2856
|
+
: activeMenu.depth === 'hooks'
|
|
2857
|
+
? (matcher?.hooks.length ?? 0)
|
|
2858
|
+
: 0;
|
|
2859
|
+
if (key.escape || value === '\u001B') {
|
|
2860
|
+
updateMenu(activeMenu.depth === 'detail'
|
|
2861
|
+
? { ...activeMenu, depth: 'hooks' }
|
|
2862
|
+
: activeMenu.depth === 'hooks'
|
|
2863
|
+
? { ...activeMenu, depth: 'matchers', hookIndex: 0 }
|
|
2864
|
+
: activeMenu.depth === 'matchers'
|
|
2865
|
+
? {
|
|
2866
|
+
...activeMenu,
|
|
2867
|
+
depth: 'events',
|
|
2868
|
+
matcherIndex: 0,
|
|
2869
|
+
hookIndex: 0,
|
|
2870
|
+
}
|
|
2871
|
+
: null);
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
const numericIndex = /^[1-9]$/u.test(value) ? Number(value) - 1 : null;
|
|
2875
|
+
if (numericIndex !== null) {
|
|
2876
|
+
if (numericIndex >= length)
|
|
2877
|
+
return;
|
|
2878
|
+
if (activeMenu.depth === 'events') {
|
|
2879
|
+
updateMenu({
|
|
2880
|
+
...activeMenu,
|
|
2881
|
+
eventIndex: numericIndex,
|
|
2882
|
+
matcherIndex: 0,
|
|
2883
|
+
hookIndex: 0,
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2886
|
+
else if (activeMenu.depth === 'matchers') {
|
|
2887
|
+
updateMenu({
|
|
2888
|
+
...activeMenu,
|
|
2889
|
+
matcherIndex: numericIndex,
|
|
2890
|
+
hookIndex: 0,
|
|
2891
|
+
});
|
|
2892
|
+
}
|
|
2893
|
+
else if (activeMenu.depth === 'hooks') {
|
|
2894
|
+
updateMenu({ ...activeMenu, hookIndex: numericIndex });
|
|
2895
|
+
}
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
if (key.upArrow || key.downArrow) {
|
|
2899
|
+
if (length === 0)
|
|
2900
|
+
return;
|
|
2901
|
+
const delta = key.upArrow ? -1 : 1;
|
|
2902
|
+
if (activeMenu.depth === 'events') {
|
|
2903
|
+
updateMenu({
|
|
2904
|
+
...activeMenu,
|
|
2905
|
+
eventIndex: Math.max(0, Math.min(length - 1, activeMenu.eventIndex + delta)),
|
|
2906
|
+
matcherIndex: 0,
|
|
2907
|
+
hookIndex: 0,
|
|
2908
|
+
});
|
|
2909
|
+
}
|
|
2910
|
+
else if (activeMenu.depth === 'matchers') {
|
|
2911
|
+
updateMenu({
|
|
2912
|
+
...activeMenu,
|
|
2913
|
+
matcherIndex: Math.max(0, Math.min(length - 1, activeMenu.matcherIndex + delta)),
|
|
2914
|
+
hookIndex: 0,
|
|
2915
|
+
});
|
|
2916
|
+
}
|
|
2917
|
+
else if (activeMenu.depth === 'hooks') {
|
|
2918
|
+
updateMenu({
|
|
2919
|
+
...activeMenu,
|
|
2920
|
+
hookIndex: Math.max(0, Math.min(length - 1, activeMenu.hookIndex + delta)),
|
|
2921
|
+
});
|
|
2922
|
+
}
|
|
2923
|
+
return;
|
|
2924
|
+
}
|
|
2925
|
+
if (key.return) {
|
|
2926
|
+
if (activeMenu.depth === 'events') {
|
|
2927
|
+
updateMenu({
|
|
2928
|
+
...activeMenu,
|
|
2929
|
+
depth: 'matchers',
|
|
2930
|
+
matcherIndex: 0,
|
|
2931
|
+
hookIndex: 0,
|
|
2932
|
+
});
|
|
2933
|
+
}
|
|
2934
|
+
else if (activeMenu.depth === 'matchers' && matcher) {
|
|
2935
|
+
updateMenu({ ...activeMenu, depth: 'hooks', hookIndex: 0 });
|
|
2936
|
+
}
|
|
2937
|
+
else if (activeMenu.depth === 'hooks' &&
|
|
2938
|
+
matcher?.hooks[activeMenu.hookIndex]) {
|
|
2939
|
+
updateMenu({ ...activeMenu, depth: 'detail' });
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2757
2944
|
if (activeMenu.kind === 'list') {
|
|
2758
2945
|
if (key.escape || value === '\u001B') {
|
|
2759
2946
|
updateMenu(null);
|
|
@@ -3110,6 +3297,50 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
3110
3297
|
else if (prompt === '/keybindings') {
|
|
3111
3298
|
setKeybindingsEditing(true);
|
|
3112
3299
|
}
|
|
3300
|
+
else if (prompt === '/memory') {
|
|
3301
|
+
append({ kind: 'user', text: prompt });
|
|
3302
|
+
const generation = ++memoryMenuGenerationRef.current;
|
|
3303
|
+
updateMenu({
|
|
3304
|
+
kind: 'memory',
|
|
3305
|
+
generation,
|
|
3306
|
+
loading: true,
|
|
3307
|
+
autoMemoryEnabled: true,
|
|
3308
|
+
entries: [],
|
|
3309
|
+
selectedIndex: 0,
|
|
3310
|
+
openedIndex: null,
|
|
3311
|
+
});
|
|
3312
|
+
const loading = (async () => {
|
|
3313
|
+
setBusy(true);
|
|
3314
|
+
try {
|
|
3315
|
+
const files = await memoryFilesLoader(keybindingsRoot, runtimeCwdRef.current);
|
|
3316
|
+
if (menuRef.current?.kind === 'memory' &&
|
|
3317
|
+
menuRef.current.generation === generation) {
|
|
3318
|
+
updateMenu({
|
|
3319
|
+
kind: 'memory',
|
|
3320
|
+
generation,
|
|
3321
|
+
loading: false,
|
|
3322
|
+
autoMemoryEnabled: files.autoMemoryEnabled,
|
|
3323
|
+
entries: files.entries,
|
|
3324
|
+
selectedIndex: 0,
|
|
3325
|
+
openedIndex: null,
|
|
3326
|
+
});
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
catch (error) {
|
|
3330
|
+
if (menuRef.current?.kind === 'memory' &&
|
|
3331
|
+
menuRef.current.generation === generation) {
|
|
3332
|
+
updateMenu(null);
|
|
3333
|
+
warn(error);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
finally {
|
|
3337
|
+
if (memoryMenuGenerationRef.current === generation)
|
|
3338
|
+
setBusy(false);
|
|
3339
|
+
}
|
|
3340
|
+
})();
|
|
3341
|
+
onTurnChange?.(loading);
|
|
3342
|
+
void loading.finally(() => onTurnChange?.(null));
|
|
3343
|
+
}
|
|
3113
3344
|
else if (prompt === '/add-dir') {
|
|
3114
3345
|
openWorkspaceDirectoryInput();
|
|
3115
3346
|
}
|
|
@@ -3169,6 +3400,55 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
3169
3400
|
onTurnChange?.(loading);
|
|
3170
3401
|
void loading.finally(() => onTurnChange?.(null));
|
|
3171
3402
|
}
|
|
3403
|
+
else if (prompt === '/hooks') {
|
|
3404
|
+
const loading = (async () => {
|
|
3405
|
+
setBusy(true);
|
|
3406
|
+
setStatus('loading hooks');
|
|
3407
|
+
let localService;
|
|
3408
|
+
try {
|
|
3409
|
+
const preferences = runtimePreferencesRef.current;
|
|
3410
|
+
localService = await factory.createService({
|
|
3411
|
+
eventSink: handleEvent,
|
|
3412
|
+
requireProvider: false,
|
|
3413
|
+
hooksOnly: true,
|
|
3414
|
+
...(preferences.model === undefined
|
|
3415
|
+
? {}
|
|
3416
|
+
: { model: preferences.model }),
|
|
3417
|
+
effort: preferences.effort,
|
|
3418
|
+
permissionMode: preferences.permissionMode,
|
|
3419
|
+
additionalDirectories: preferences.additionalDirectories,
|
|
3420
|
+
cwd: runtimeCwdRef.current,
|
|
3421
|
+
...(signal ? { signal } : {}),
|
|
3422
|
+
});
|
|
3423
|
+
if (!localService.hookConfiguration)
|
|
3424
|
+
throw new Error('Hook configuration is unavailable.');
|
|
3425
|
+
const configuration = await localService.hookConfiguration();
|
|
3426
|
+
updateMenu({
|
|
3427
|
+
kind: 'hooks',
|
|
3428
|
+
configuration,
|
|
3429
|
+
depth: 'events',
|
|
3430
|
+
eventIndex: 0,
|
|
3431
|
+
matcherIndex: 0,
|
|
3432
|
+
hookIndex: 0,
|
|
3433
|
+
});
|
|
3434
|
+
}
|
|
3435
|
+
catch (error) {
|
|
3436
|
+
warn(error);
|
|
3437
|
+
}
|
|
3438
|
+
finally {
|
|
3439
|
+
try {
|
|
3440
|
+
await localService?.close?.();
|
|
3441
|
+
}
|
|
3442
|
+
catch (error) {
|
|
3443
|
+
warn(error);
|
|
3444
|
+
}
|
|
3445
|
+
setBusy(false);
|
|
3446
|
+
setStatus('ready');
|
|
3447
|
+
}
|
|
3448
|
+
})();
|
|
3449
|
+
onTurnChange?.(loading);
|
|
3450
|
+
void loading.finally(() => onTurnChange?.(null));
|
|
3451
|
+
}
|
|
3172
3452
|
else if (prompt === '/resume' || prompt === '/sessions') {
|
|
3173
3453
|
pickerIncludesNewSessionRef.current = false;
|
|
3174
3454
|
setPickerIncludesNewSession(false);
|
|
@@ -3306,7 +3586,9 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
3306
3586
|
}
|
|
3307
3587
|
editComposer();
|
|
3308
3588
|
});
|
|
3309
|
-
return (_jsx(Box, { flexDirection: "column", children: selectingSession ? (_jsx(SessionPicker, { sessions: filteredPickerChoices, selectedIndex: selectedIndex, screenReader: axScreenReader, query: sessionSearch })) : (_jsxs(_Fragment, { children: [!axScreenReader && history.length === 0 && !sessionId ? (_jsx(WelcomePanel, { display: runtimeDisplay, width: width })) : null, sessionId ? (_jsxs(Text, { dimColor: true, children: ["Session ", sessionId.slice(0, 8)] })) : null, _jsx(Transcript, { items: history, activeText: activeText, activeThinking: activeThinking, thinkingExpanded: thinkingExpanded, detailedTranscript: thinkingExpanded, screenReader: axScreenReader }), externalEditorRequest !== null ||
|
|
3589
|
+
return (_jsx(Box, { flexDirection: "column", children: selectingSession ? (_jsx(SessionPicker, { sessions: filteredPickerChoices, selectedIndex: selectedIndex, screenReader: axScreenReader, query: sessionSearch })) : (_jsxs(_Fragment, { children: [!axScreenReader && history.length === 0 && !sessionId ? (_jsx(WelcomePanel, { display: runtimeDisplay, width: width })) : null, sessionId ? (_jsxs(Text, { dimColor: true, children: ["Session ", sessionId.slice(0, 8)] })) : null, _jsx(Transcript, { items: history, activeText: activeText, activeThinking: activeThinking, thinkingExpanded: thinkingExpanded, detailedTranscript: thinkingExpanded, screenReader: axScreenReader }), externalEditorRequest !== null ||
|
|
3590
|
+
keybindingsEditing ||
|
|
3591
|
+
memoryEditorRequest !== null ? (_jsx(ExternalEditorWait, { screenReader: axScreenReader })) : permission ? (_jsxs(DialogFrame, { title: permission.kind === 'recovery'
|
|
3310
3592
|
? `Retry interrupted ${permission.call.name}?`
|
|
3311
3593
|
: `Allow ${permission.call.name}?`, screenReader: axScreenReader, children: [_jsx(Text, { bold: true, children: describeTool(permission.call, sensitiveValues) }), _jsx(Text, { children: "\u276F 1. Yes" }), _jsx(Text, { children: " 2. No" }), _jsx(Text, { dimColor: true, children: "Enter/Esc declines \u00B7 y/n quick response" })] })) : planApproval ? (_jsxs(DialogFrame, { title: "Approve this plan and begin implementation?", screenReader: axScreenReader, children: [_jsx(Text, { dimColor: true, children: planApproval.request.planPath }), planApproval.request.plan ? (_jsx(Box, { marginY: 1, children: _jsx(Text, { children: planApproval.request.plan }) })) : null, _jsx(Text, { children: "\u276F 1. Yes, implement the plan" }), _jsx(Text, { children: " 2. No, keep planning" })] })) : question ? (_jsxs(DialogFrame, { title: `${question.questions[question.index]?.header}: ${question.questions[question.index]?.question}`, screenReader: axScreenReader, children: [question.questions[question.index]?.options.map((option, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [index === 0 ? '❯ ' : ' ', index + 1, ". ", option.label, " \u2014 ", option.description] }), option.preview ? (_jsx(Text, { dimColor: true, children: option.preview })) : null] }, `${index}-${option.label}`))), _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: question.questions[question.index]?.multiSelect
|
|
3312
3594
|
? 'Enter comma-separated option numbers or custom text · Esc cancels'
|
|
@@ -3345,7 +3627,7 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
3345
3627
|
label: 'User settings',
|
|
3346
3628
|
description: 'Saved in at ~/.claude/settings.json',
|
|
3347
3629
|
},
|
|
3348
|
-
], selectedIndex: menu.selectedIndex, footer: "Enter to confirm \u00B7 Esc to cancel", width: width, screenReader: axScreenReader })) : menu.kind === 'status' ? (_jsx(StatusDashboard, { tabIndex: menu.tabIndex, version: runtimeDisplay.version, sessionId: sessionId, display: runtimeDisplay, ...(usage === undefined ? {} : { usage }), ...(costUsd === undefined ? {} : { costUsd }), turnCount: turnNumberRef.current, toolCount: history.filter((item) => item.kind === 'tool').length, commandCount: allSlashCommands.length, detailedTranscript: thinkingExpanded, width: width, screenReader: axScreenReader })) : menu.kind === 'list' ? (_jsx(ListDashboard, { title: menu.title, rows: menu.rows, emptyText: menu.emptyText, selectedIndex: menu.selectedIndex, width: width, screenReader: axScreenReader })) : menu.kind === 'model' ? (_jsx(SelectionMenu, { title: "Select model", description: `Effort: ${runtimePreferences.effort}`, options: modelOptions, selectedIndex: menu.selectedIndex, footer: "\u2191/\u2193 select \u00B7 \u2190/\u2192 effort \u00B7 Enter applies to this session \u00B7 Esc cancels", width: width, screenReader: axScreenReader })) : menu.kind === 'effort' ? (_jsx(SelectionMenu, { title: "Select effort", description: "Controls how much reasoning effort the provider should use.", options: EFFORT_OPTIONS.map((option) => ({
|
|
3630
|
+
], selectedIndex: menu.selectedIndex, footer: "Enter to confirm \u00B7 Esc to cancel", width: width, screenReader: axScreenReader })) : menu.kind === 'status' ? (_jsx(StatusDashboard, { tabIndex: menu.tabIndex, version: runtimeDisplay.version, sessionId: sessionId, display: runtimeDisplay, ...(usage === undefined ? {} : { usage }), ...(costUsd === undefined ? {} : { costUsd }), turnCount: turnNumberRef.current, toolCount: history.filter((item) => item.kind === 'tool').length, commandCount: allSlashCommands.length, detailedTranscript: thinkingExpanded, width: width, screenReader: axScreenReader })) : menu.kind === 'memory' ? (_jsx(MemoryDashboard, { autoMemoryEnabled: menu.autoMemoryEnabled, entries: menu.entries, selectedIndex: menu.selectedIndex, openedIndex: menu.openedIndex, loading: menu.loading, width: width, screenReader: axScreenReader })) : menu.kind === 'hooks' ? (_jsx(HookDashboard, { configuration: menu.configuration, depth: menu.depth, eventIndex: menu.eventIndex, matcherIndex: menu.matcherIndex, hookIndex: menu.hookIndex, width: width, screenReader: axScreenReader })) : menu.kind === 'list' ? (_jsx(ListDashboard, { title: menu.title, rows: menu.rows, emptyText: menu.emptyText, selectedIndex: menu.selectedIndex, width: width, screenReader: axScreenReader })) : menu.kind === 'model' ? (_jsx(SelectionMenu, { title: "Select model", description: `Effort: ${runtimePreferences.effort}`, options: modelOptions, selectedIndex: menu.selectedIndex, footer: "\u2191/\u2193 select \u00B7 \u2190/\u2192 effort \u00B7 Enter applies to this session \u00B7 Esc cancels", width: width, screenReader: axScreenReader })) : menu.kind === 'effort' ? (_jsx(SelectionMenu, { title: "Select effort", description: "Controls how much reasoning effort the provider should use.", options: EFFORT_OPTIONS.map((option) => ({
|
|
3349
3631
|
label: option,
|
|
3350
3632
|
description: option === 'low'
|
|
3351
3633
|
? 'Fastest and least deliberative.'
|