praxis-agent 0.3.0 → 0.5.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 +4 -2
- package/dist/application/session-service.d.ts +29 -0
- package/dist/application/session-service.d.ts.map +1 -1
- package/dist/application/session-service.js +431 -31
- package/dist/application/session-service.js.map +1 -1
- package/dist/application/top-level-agent-manager.d.ts +15 -1
- package/dist/application/top-level-agent-manager.d.ts.map +1 -1
- package/dist/application/top-level-agent-manager.js +101 -34
- package/dist/application/top-level-agent-manager.js.map +1 -1
- package/dist/cli/agents-dashboard.d.ts.map +1 -1
- package/dist/cli/agents-dashboard.js +22 -6
- package/dist/cli/agents-dashboard.js.map +1 -1
- package/dist/cli/interactive.d.ts +22 -2
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +311 -5
- package/dist/cli/interactive.js.map +1 -1
- package/dist/cli/tui/claude-style.d.ts +15 -0
- package/dist/cli/tui/claude-style.d.ts.map +1 -1
- package/dist/cli/tui/claude-style.js +26 -0
- package/dist/cli/tui/claude-style.js.map +1 -1
- package/dist/cli/tui/clipboard.d.ts +3 -0
- package/dist/cli/tui/clipboard.d.ts.map +1 -1
- package/dist/cli/tui/clipboard.js +12 -0
- package/dist/cli/tui/clipboard.js.map +1 -1
- 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 +11 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +25 -1
- package/dist/cli.js.map +1 -1
- package/dist/compatibility/claude/schema.d.ts.map +1 -1
- package/dist/compatibility/claude/schema.js +11 -1
- package/dist/compatibility/claude/schema.js.map +1 -1
- package/dist/persistence/claude-job-store.d.ts +11 -1
- package/dist/persistence/claude-job-store.d.ts.map +1 -1
- package/dist/persistence/claude-job-store.js +23 -2
- package/dist/persistence/claude-job-store.js.map +1 -1
- package/dist/persistence/claude-transcript-store.d.ts.map +1 -1
- package/dist/persistence/claude-transcript-store.js +8 -2
- package/dist/persistence/claude-transcript-store.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ForkResult, ManualCompactResult, ManualCompactSelection, RewindPoint, SessionRunResult, SessionSummary } from '../application/session-service.js';
|
|
1
|
+
import type { ForkResult, ManualCompactResult, ManualCompactSelection, RewindPoint, SessionForkCheckpoint, SessionRunResult, SessionSummary, SideQuestionForkResult, SideQuestionResult } from '../application/session-service.js';
|
|
2
2
|
import type { ModelImage, ModelToolCall, RuntimeEventSink } from '../core/runtime.js';
|
|
3
3
|
import type { CliElicitationRequest, CliElicitationResult, CliRuntimeInfo } from './protocol.js';
|
|
4
4
|
import type { ClaudeInteractiveToolCallbacks } from '../tools/claude-interactive-tools.js';
|
|
@@ -26,6 +26,11 @@ interface InteractiveSessionCommands {
|
|
|
26
26
|
rewindPoints?(sessionId: string): Promise<RewindPoint[]>;
|
|
27
27
|
changeCwd?(sessionId: string | undefined, cwd: string): Promise<string>;
|
|
28
28
|
recordCdUsage?(sessionId: string): Promise<void>;
|
|
29
|
+
answerSideQuestion?(sessionId: string | undefined, question: string, signal?: AbortSignal, onDelta?: (delta: string) => void, permissionMode?: ClaudePermissionMode): Promise<SideQuestionResult>;
|
|
30
|
+
recordBtwUsage?(sessionId: string | undefined, permissionMode?: ClaudePermissionMode): Promise<string>;
|
|
31
|
+
recordBackgroundUsage?(sessionId: string | undefined, permissionMode?: ClaudePermissionMode): Promise<string>;
|
|
32
|
+
recordBackgroundLaunch?(sessionId: string): Promise<SessionForkCheckpoint>;
|
|
33
|
+
forkSideQuestion?(sessionId: string, question: string, signal?: AbortSignal): Promise<SideQuestionForkResult>;
|
|
29
34
|
rename?(sessionId: string, name: string): Promise<void>;
|
|
30
35
|
sessionNameSuggestion?(sessionId: string, signal?: AbortSignal): Promise<string | null>;
|
|
31
36
|
workflows?(): readonly Record<string, unknown>[];
|
|
@@ -66,6 +71,17 @@ export interface InteractiveResumeOptions {
|
|
|
66
71
|
forkSessionId?: string;
|
|
67
72
|
retryInterruptedTools?: boolean;
|
|
68
73
|
}
|
|
74
|
+
export interface InteractiveBackgroundRequest {
|
|
75
|
+
sourceSessionId: string;
|
|
76
|
+
sourceCheckpoint: SessionForkCheckpoint;
|
|
77
|
+
prompt: string;
|
|
78
|
+
detail: string;
|
|
79
|
+
cwd: string;
|
|
80
|
+
}
|
|
81
|
+
export interface InteractiveBackgroundResult {
|
|
82
|
+
id: string;
|
|
83
|
+
sessionId: string;
|
|
84
|
+
}
|
|
69
85
|
interface InteractiveAppProps {
|
|
70
86
|
factory: InteractiveServiceFactory;
|
|
71
87
|
initialSessions: readonly SessionSummary[];
|
|
@@ -75,6 +91,7 @@ interface InteractiveAppProps {
|
|
|
75
91
|
onCancel?: () => void;
|
|
76
92
|
onTurnChange?: (turn: Promise<void> | null) => void;
|
|
77
93
|
onCleanup?: (closing: Promise<void>) => void;
|
|
94
|
+
onBackground?: (request: InteractiveBackgroundRequest) => Promise<InteractiveBackgroundResult>;
|
|
78
95
|
axScreenReader?: boolean;
|
|
79
96
|
allowNewSession?: boolean;
|
|
80
97
|
resume?: InteractiveResumeOptions;
|
|
@@ -96,6 +113,7 @@ interface InteractiveAppProps {
|
|
|
96
113
|
suspendProcess?: () => void | Promise<void>;
|
|
97
114
|
clipboardReader?: () => Promise<TuiClipboardContent>;
|
|
98
115
|
clipboardWriter?: (text: string) => Promise<void>;
|
|
116
|
+
sideQuestionClipboardWriter?: (text: string) => Promise<void>;
|
|
99
117
|
exportWriter?: (path: string, text: string) => Promise<void>;
|
|
100
118
|
permissionRuleStore?: {
|
|
101
119
|
load(): Promise<readonly TuiPermissionRule[]>;
|
|
@@ -109,7 +127,7 @@ interface InteractiveAppProps {
|
|
|
109
127
|
workspaceDirectoryResolver?: typeof resolveTuiWorkspaceDirectory;
|
|
110
128
|
workspaceDirectoryCompleter?: typeof completeTuiWorkspaceDirectory;
|
|
111
129
|
}
|
|
112
|
-
export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, suspendProcess, clipboardReader, clipboardWriter, exportWriter, permissionRuleStore, workspaceDirectoryResolver, workspaceDirectoryCompleter, }: InteractiveAppProps): import("react").JSX.Element;
|
|
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;
|
|
113
131
|
export declare function runInteractive(options: {
|
|
114
132
|
factory: InteractiveServiceFactory;
|
|
115
133
|
initialPrompt?: string;
|
|
@@ -122,6 +140,8 @@ export declare function runInteractive(options: {
|
|
|
122
140
|
requireSession?: boolean;
|
|
123
141
|
missingSessionMessage?: string;
|
|
124
142
|
resume?: InteractiveResumeOptions;
|
|
143
|
+
onBackground?: (request: InteractiveBackgroundRequest) => Promise<InteractiveBackgroundResult>;
|
|
144
|
+
onBackgrounded?: (result: InteractiveBackgroundResult) => void;
|
|
125
145
|
}): Promise<number>;
|
|
126
146
|
export {};
|
|
127
147
|
//# sourceMappingURL=interactive.d.ts.map
|
|
@@ -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,gBAAgB,EAChB,cAAc,
|
|
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,EAiBL,KAAK,cAAc,EAEnB,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAA;AACtF,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAA;AAShC,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAA;AAQ3B,OAAO,EAIL,kBAAkB,EAGlB,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC7B,MAAM,gCAAgC,CAAA;AAQvC,UAAU,0BAA0B;IAClC,GAAG,CACD,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC5B,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC5B,QAAQ,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC3E,WAAW,CAAC,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC5B,IAAI,CACF,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,MAAM,EACxB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,UAAU,CAAC,CAAA;IACtB,QAAQ,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IACrC,UAAU,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IACzD,OAAO,CAAC,CACN,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,EACpB,SAAS,CAAC,EAAE,sBAAsB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC/B,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrE,YAAY,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IACxD,SAAS,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACvE,aAAa,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,kBAAkB,CAAC,CACjB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,cAAc,CAAC,EAAE,oBAAoB,GACpC,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC9B,cAAc,CAAC,CACb,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,cAAc,CAAC,EAAE,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,qBAAqB,CAAC,CACpB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,cAAc,CAAC,EAAE,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,sBAAsB,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAC1E,gBAAgB,CAAC,CACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAAA;IAClC,MAAM,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvD,qBAAqB,CAAC,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACzB,SAAS,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAChD,aAAa,CAAC,IAAI,SAAS,eAAe,EAAE,CAAA;IAC5C,gBAAgB,CAAC,IAAI,SAAS,aAAa,EAAE,CAAA;IAC7C,WAAW,CAAC,IAAI,cAAc,CAAA;IAC9B,iBAAiB,CAAC,CAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,mBAAmB,CAAC,CAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IACjD,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,aAAa,CAAC,OAAO,EAAE;QACrB,SAAS,EAAE,gBAAgB,CAAA;QAC3B,eAAe,EAAE,OAAO,CAAA;QACxB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;QACrE,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;QACjE,aAAa,CAAC,EAAE,CACd,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAA;QAClC,OAAO,CAAC,EAAE,8BAA8B,CAAC,SAAS,CAAC,CAAA;QACnD,WAAW,CAAC,EAAE,8BAA8B,CAAC,aAAa,CAAC,CAAA;QAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;QACpD,cAAc,CAAC,EAAE,oBAAoB,CAAA;QACrC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QACzC,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,MAAM,CAAC,EAAE,WAAW,CAAA;KACrB,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC;AAED,MAAM,WAAW,4BAA4B;IAC3C,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,qBAAqB,CAAA;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,mBAAmB;IAC3B,OAAO,EAAE,yBAAyB,CAAA;IAClC,eAAe,EAAE,SAAS,cAAc,EAAE,CAAA;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IAC1C,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;IACnD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;IAC5C,YAAY,CAAC,EAAE,CACb,OAAO,EAAE,4BAA4B,KAClC,OAAO,CAAC,2BAA2B,CAAC,CAAA;IACzC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,MAAM,CAAC,EAAE,wBAAwB,CAAA;IACjC,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAC1C,MAAM,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IACjC,+BAA+B,CAAC,EAAE,OAAO,CAAA;IACzC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAA;IAC3C,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC,CAAA;IACnD,cAAc,CAAC,EAAE,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC,eAAe,CAAC,CAAA;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACrE,iBAAiB,CAAC,EAAE,OAAO,kBAAkB,CAAA;IAC7C,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpC,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACpD,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,2BAA2B,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,mBAAmB,CAAC,EAAE;QACpB,IAAI,IAAI,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAA;QAC7C,GAAG,CAAC,KAAK,EAAE;YACT,QAAQ,EAAE,qBAAqB,CAAA;YAC/B,IAAI,EAAE,MAAM,CAAA;YACZ,KAAK,EAAE,mBAAmB,CAAA;SAC3B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QACjB,MAAM,CAAC,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAChD,CAAA;IACD,0BAA0B,CAAC,EAAE,OAAO,4BAA4B,CAAA;IAChE,2BAA2B,CAAC,EAAE,OAAO,6BAA6B,CAAA;CACnE;AAgVD,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,eAAe,EACf,aAAa,EACb,cAAmB,EACnB,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,cAAsB,EACtB,eAAsB,EACtB,MAAM,EACN,OAAgD,EAChD,aAAa,EACb,aAAoC,EACpC,MAAqB,EACrB,+BAAuC,EACvC,qBAA0B,EAC1B,UAAU,EACV,UAAU,EACV,cAA8B,EAC9B,qBAAqB,EACrB,eAA0C,EAC1C,iBAAsC,EACtC,iBAAqC,EACrC,cAAkC,EAClC,eAAkC,EAClC,eAAmC,EACnC,2BAAoD,EACpD,YAAsC,EACtC,mBAAmB,EACnB,0BAAyD,EACzD,2BAA2D,GAC5D,EAAE,mBAAmB,+BAk6HrB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,OAAO,EAAE,yBAAyB,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+BAA+B,CAAC,EAAE,OAAO,CAAA;IACzC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzC,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAA;IACpD,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,MAAM,CAAC,EAAE,wBAAwB,CAAA;IACjC,YAAY,CAAC,EAAE,CACb,OAAO,EAAE,4BAA4B,KAClC,OAAO,CAAC,2BAA2B,CAAC,CAAA;IACzC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,2BAA2B,KAAK,IAAI,CAAA;CAC/D,GAAG,OAAO,CAAC,MAAM,CAAC,CAiHlB"}
|
package/dist/cli/interactive.js
CHANGED
|
@@ -3,8 +3,9 @@ import { homedir } from 'node:os';
|
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
5
5
|
import { Box, Text, render, useApp, useInput } from 'ink';
|
|
6
|
+
import { AgentRunCancelledError } from '../core/runtime.js';
|
|
6
7
|
import { redactSensitiveText, sensitiveEnvironmentValues, } from '../platform/sensitive-data.js';
|
|
7
|
-
import { CommandPalette, 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, ListDashboard, MentionPicker, PermissionDashboard, SelectionMenu, SessionPicker, StatusDashboard, Transcript, WelcomePanel, useTerminalWidth, } from './tui/claude-style.js';
|
|
8
9
|
import { loadGitDiff, visiblePatchLines, } from './tui/git-diff.js';
|
|
9
10
|
import { addTuiPermissionRule, loadTuiPermissionRules, removeTuiPermissionRule, } from './tui/permission-settings.js';
|
|
10
11
|
import { filterTuiSlashCommands, mergeTuiSlashCommands, slashCommandQuery, } from './tui/slash-commands.js';
|
|
@@ -12,7 +13,7 @@ import { createComposerEditor, deleteComposerToEnd, deleteComposerToStart, delet
|
|
|
12
13
|
import { applyMentionReference, fileReferenceAtCursor, filterTuiMentionEntries, loadTuiFileEntries, } from './tui/file-picker.js';
|
|
13
14
|
import { editTuiPrompt, openTuiEditorFile, } from './tui/external-editor.js';
|
|
14
15
|
import { suspendTuiProcess } from './tui/terminal-suspend.js';
|
|
15
|
-
import { readTuiClipboard, writeTuiClipboard, } from './tui/clipboard.js';
|
|
16
|
+
import { readTuiClipboard, writeTuiClipboard, writeTuiOsc52Clipboard, } from './tui/clipboard.js';
|
|
16
17
|
import { composerImageIds, deleteComposerImageBackward, deleteComposerImageForward, insertComposerImageMarker, moveComposerCursorAcrossImages, } from './tui/composer-images.js';
|
|
17
18
|
import { defaultTuiKeybindings, ensureTuiKeybindingsFile, hasTuiKeybindingPrefix, loadTuiKeybindings, resolveTuiKeybinding, tuiKeyChord, } from './tui/keybindings.js';
|
|
18
19
|
import { completeTuiWorkspaceDirectory, resolveTuiWorkspaceDirectory, } from './tui/workspace-directories.js';
|
|
@@ -185,7 +186,7 @@ function ordinal(value) {
|
|
|
185
186
|
return `${value}th`;
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
|
-
export function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory = [], signal, onCancel, onTurnChange, onCleanup, 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, exportWriter = writeConversationExport, permissionRuleStore, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, }) {
|
|
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, }) {
|
|
189
190
|
const { exit, suspendTerminal, waitUntilRenderFlush } = useApp();
|
|
190
191
|
const width = useTerminalWidth(terminalWidth);
|
|
191
192
|
const keybindingsRoot = useMemo(() => resolve(keybindingsConfigRoot ??
|
|
@@ -246,6 +247,12 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
246
247
|
const [editorFooterMessage, setEditorFooterMessage] = useState();
|
|
247
248
|
const [availableSlashCommands, setAvailableSlashCommands] = useState(slashCommands);
|
|
248
249
|
const [availableAgents, setAvailableAgents] = useState(agents);
|
|
250
|
+
const [btwHistory, setBtwHistory] = useState([]);
|
|
251
|
+
const btwHistoryRef = useRef([]);
|
|
252
|
+
const btwIdRef = useRef(0);
|
|
253
|
+
const btwControllerRef = useRef(null);
|
|
254
|
+
const [btwCopied, setBtwCopied] = useState(false);
|
|
255
|
+
const btwCopiedTimerRef = useRef(null);
|
|
249
256
|
const [menu, setMenu] = useState(null);
|
|
250
257
|
const menuRef = useRef(null);
|
|
251
258
|
const [busy, setBusy] = useState(false);
|
|
@@ -427,8 +434,11 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
427
434
|
planApprovalRef.current?.resolve(false);
|
|
428
435
|
if (exitConfirmationTimerRef.current)
|
|
429
436
|
clearTimeout(exitConfirmationTimerRef.current);
|
|
437
|
+
if (btwCopiedTimerRef.current)
|
|
438
|
+
clearTimeout(btwCopiedTimerRef.current);
|
|
430
439
|
scheduledWaitRef.current?.abort();
|
|
431
440
|
turnControllerRef.current?.abort();
|
|
441
|
+
btwControllerRef.current?.abort();
|
|
432
442
|
const closing = serviceRef.current?.close?.() ?? Promise.resolve();
|
|
433
443
|
if (onCleanupRef.current)
|
|
434
444
|
onCleanupRef.current(closing);
|
|
@@ -619,6 +629,11 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
619
629
|
menuRef.current = next;
|
|
620
630
|
setMenu(next);
|
|
621
631
|
};
|
|
632
|
+
const updateBtwHistory = (updater) => {
|
|
633
|
+
const next = updater(btwHistoryRef.current);
|
|
634
|
+
btwHistoryRef.current = next;
|
|
635
|
+
setBtwHistory(next);
|
|
636
|
+
};
|
|
622
637
|
useEffect(() => {
|
|
623
638
|
if (menu?.kind !== 'compact-progress')
|
|
624
639
|
return;
|
|
@@ -1015,6 +1030,27 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
1015
1030
|
}
|
|
1016
1031
|
}
|
|
1017
1032
|
};
|
|
1033
|
+
const withLocalCommands = async (operation) => {
|
|
1034
|
+
if (serviceRef.current)
|
|
1035
|
+
return operation(serviceRef.current);
|
|
1036
|
+
const preferences = runtimePreferencesRef.current;
|
|
1037
|
+
const commands = await factory.createService({
|
|
1038
|
+
eventSink: handleEvent,
|
|
1039
|
+
requireProvider: false,
|
|
1040
|
+
...(preferences.model === undefined ? {} : { model: preferences.model }),
|
|
1041
|
+
effort: preferences.effort,
|
|
1042
|
+
permissionMode: preferences.permissionMode,
|
|
1043
|
+
additionalDirectories: preferences.additionalDirectories,
|
|
1044
|
+
cwd: runtimeCwdRef.current,
|
|
1045
|
+
...(signal ? { signal } : {}),
|
|
1046
|
+
});
|
|
1047
|
+
try {
|
|
1048
|
+
return await operation(commands);
|
|
1049
|
+
}
|
|
1050
|
+
finally {
|
|
1051
|
+
await commands.close?.();
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1018
1054
|
const openSession = (nextSessionId) => {
|
|
1019
1055
|
setSessionId(nextSessionId);
|
|
1020
1056
|
const loadId = sessionLoadRef.current + 1;
|
|
@@ -1288,6 +1324,189 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
1288
1324
|
onTurnChange?.(showing);
|
|
1289
1325
|
void showing.finally(() => onTurnChange?.(null));
|
|
1290
1326
|
};
|
|
1327
|
+
const showBtwUsage = () => {
|
|
1328
|
+
appendPromptHistory('/btw');
|
|
1329
|
+
const showing = (async () => {
|
|
1330
|
+
try {
|
|
1331
|
+
const activeSessionId = await (await service()).recordBtwUsage?.(sessionId ?? undefined, runtimePreferencesRef.current.permissionMode);
|
|
1332
|
+
if (activeSessionId)
|
|
1333
|
+
setSessionId(activeSessionId);
|
|
1334
|
+
append({ kind: 'user', text: '/btw' });
|
|
1335
|
+
append({ kind: 'local-result', text: 'Usage: /btw <your question>' });
|
|
1336
|
+
}
|
|
1337
|
+
catch (error) {
|
|
1338
|
+
warn(error);
|
|
1339
|
+
}
|
|
1340
|
+
})();
|
|
1341
|
+
onTurnChange?.(showing);
|
|
1342
|
+
void showing.finally(() => onTurnChange?.(null));
|
|
1343
|
+
};
|
|
1344
|
+
const backgroundSession = () => {
|
|
1345
|
+
appendPromptHistory('/background');
|
|
1346
|
+
const backgrounding = (async () => {
|
|
1347
|
+
setBusy(true);
|
|
1348
|
+
try {
|
|
1349
|
+
const hasModelTurn = history.some((item) => item.kind === 'assistant');
|
|
1350
|
+
if (!sessionId || !hasModelTurn) {
|
|
1351
|
+
const activeSessionId = await withLocalCommands(async (commands) => {
|
|
1352
|
+
if (!commands.recordBackgroundUsage) {
|
|
1353
|
+
throw new Error('Background sessions are unavailable.');
|
|
1354
|
+
}
|
|
1355
|
+
return commands.recordBackgroundUsage(sessionId ?? undefined, runtimePreferencesRef.current.permissionMode);
|
|
1356
|
+
});
|
|
1357
|
+
setSessionId(activeSessionId);
|
|
1358
|
+
append({
|
|
1359
|
+
kind: 'local-result',
|
|
1360
|
+
text: 'Nothing to background yet — send a message first.',
|
|
1361
|
+
});
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
if (!onBackground) {
|
|
1365
|
+
throw new Error('Background sessions are unavailable.');
|
|
1366
|
+
}
|
|
1367
|
+
const prompt = [...history]
|
|
1368
|
+
.reverse()
|
|
1369
|
+
.find((item) => item.kind === 'user');
|
|
1370
|
+
const detail = [...history]
|
|
1371
|
+
.reverse()
|
|
1372
|
+
.find((item) => item.kind === 'assistant' || item.kind === 'thinking');
|
|
1373
|
+
const sourceCheckpoint = await withLocalCommands(async (commands) => {
|
|
1374
|
+
if (!commands.recordBackgroundLaunch) {
|
|
1375
|
+
throw new Error('Background sessions are unavailable.');
|
|
1376
|
+
}
|
|
1377
|
+
return commands.recordBackgroundLaunch(sessionId);
|
|
1378
|
+
});
|
|
1379
|
+
setStatus('Backgrounding…');
|
|
1380
|
+
append({ kind: 'notice', text: 'Backgrounding…' });
|
|
1381
|
+
await waitUntilRenderFlush();
|
|
1382
|
+
await onBackground({
|
|
1383
|
+
sourceSessionId: sessionId,
|
|
1384
|
+
sourceCheckpoint,
|
|
1385
|
+
prompt: prompt && 'text' in prompt
|
|
1386
|
+
? prompt.text
|
|
1387
|
+
: 'empty-background-command',
|
|
1388
|
+
detail: detail && 'text' in detail ? detail.text : '',
|
|
1389
|
+
cwd: runtimeCwdRef.current,
|
|
1390
|
+
});
|
|
1391
|
+
await retireService();
|
|
1392
|
+
exit();
|
|
1393
|
+
}
|
|
1394
|
+
catch (error) {
|
|
1395
|
+
warn(error);
|
|
1396
|
+
}
|
|
1397
|
+
finally {
|
|
1398
|
+
if (componentMountedRef.current) {
|
|
1399
|
+
setBusy(false);
|
|
1400
|
+
setStatus('ready');
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
})();
|
|
1404
|
+
onTurnChange?.(backgrounding);
|
|
1405
|
+
void backgrounding.finally(() => onTurnChange?.(null));
|
|
1406
|
+
};
|
|
1407
|
+
const askSideQuestion = (question) => {
|
|
1408
|
+
const id = btwIdRef.current + 1;
|
|
1409
|
+
btwIdRef.current = id;
|
|
1410
|
+
appendPromptHistory(`/btw ${question}`);
|
|
1411
|
+
const entry = {
|
|
1412
|
+
id,
|
|
1413
|
+
question,
|
|
1414
|
+
answer: '',
|
|
1415
|
+
status: 'answering',
|
|
1416
|
+
};
|
|
1417
|
+
updateBtwHistory((entries) => [...entries, entry]);
|
|
1418
|
+
updateMenu({
|
|
1419
|
+
kind: 'btw',
|
|
1420
|
+
selectedIndex: btwHistoryRef.current.length - 1,
|
|
1421
|
+
scrollOffset: 0,
|
|
1422
|
+
});
|
|
1423
|
+
setBtwCopied(false);
|
|
1424
|
+
const controller = new AbortController();
|
|
1425
|
+
btwControllerRef.current?.abort();
|
|
1426
|
+
btwControllerRef.current = controller;
|
|
1427
|
+
const sideSignal = signal
|
|
1428
|
+
? AbortSignal.any([signal, controller.signal])
|
|
1429
|
+
: controller.signal;
|
|
1430
|
+
const answering = (async () => {
|
|
1431
|
+
try {
|
|
1432
|
+
const commands = await service();
|
|
1433
|
+
if (!commands.answerSideQuestion) {
|
|
1434
|
+
throw new Error('Side questions are unavailable.');
|
|
1435
|
+
}
|
|
1436
|
+
const result = await commands.answerSideQuestion(sessionId ?? undefined, question, sideSignal, (delta) => updateBtwHistory((entries) => entries.map((item) => item.id === id
|
|
1437
|
+
? { ...item, answer: item.answer + delta }
|
|
1438
|
+
: item)), runtimePreferencesRef.current.permissionMode);
|
|
1439
|
+
if (result.sessionId)
|
|
1440
|
+
setSessionId(result.sessionId);
|
|
1441
|
+
updateBtwHistory((entries) => entries.map((item) => item.id === id ? { ...item, status: 'complete' } : item));
|
|
1442
|
+
if (sideSignal.aborted)
|
|
1443
|
+
throw new AgentRunCancelledError();
|
|
1444
|
+
setUsage((current) => ({
|
|
1445
|
+
inputTokens: (current?.inputTokens ?? 0) + result.usage.inputTokens,
|
|
1446
|
+
outputTokens: (current?.outputTokens ?? 0) + result.usage.outputTokens,
|
|
1447
|
+
cacheReadInputTokens: (current?.cacheReadInputTokens ?? 0) +
|
|
1448
|
+
(result.usage.cacheReadInputTokens ?? 0),
|
|
1449
|
+
cacheCreationInputTokens: (current?.cacheCreationInputTokens ?? 0) +
|
|
1450
|
+
(result.usage.cacheCreationInputTokens ?? 0),
|
|
1451
|
+
}));
|
|
1452
|
+
if (result.costUsd !== undefined) {
|
|
1453
|
+
const sideCostUsd = result.costUsd;
|
|
1454
|
+
setCostUsd((current) => (current ?? 0) + sideCostUsd);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
catch (error) {
|
|
1458
|
+
updateBtwHistory((entries) => entries.map((item) => item.id === id
|
|
1459
|
+
? {
|
|
1460
|
+
...item,
|
|
1461
|
+
status: 'error',
|
|
1462
|
+
error: sideSignal.aborted
|
|
1463
|
+
? 'Cancelled'
|
|
1464
|
+
: error instanceof Error
|
|
1465
|
+
? error.message
|
|
1466
|
+
: String(error),
|
|
1467
|
+
}
|
|
1468
|
+
: item));
|
|
1469
|
+
}
|
|
1470
|
+
finally {
|
|
1471
|
+
if (btwControllerRef.current === controller) {
|
|
1472
|
+
btwControllerRef.current = null;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
})();
|
|
1476
|
+
onTurnChange?.(answering);
|
|
1477
|
+
void answering.finally(() => onTurnChange?.(null));
|
|
1478
|
+
};
|
|
1479
|
+
const forkSideQuestion = (entry) => {
|
|
1480
|
+
updateBtwHistory((entries) => entries.map((item) => item.id === entry.id ? { ...item, status: 'forking' } : item));
|
|
1481
|
+
const forking = (async () => {
|
|
1482
|
+
try {
|
|
1483
|
+
if (!sessionId) {
|
|
1484
|
+
throw new Error('Start a conversation before forking a side question.');
|
|
1485
|
+
}
|
|
1486
|
+
const commands = await service();
|
|
1487
|
+
if (!commands.forkSideQuestion) {
|
|
1488
|
+
throw new Error('Side-question forking is unavailable.');
|
|
1489
|
+
}
|
|
1490
|
+
const result = await commands.forkSideQuestion(sessionId, entry.question);
|
|
1491
|
+
updateMenu(null);
|
|
1492
|
+
append({
|
|
1493
|
+
kind: 'local-result',
|
|
1494
|
+
text: `⑂ forked ${result.name} (${result.agentId.slice(-4)})`,
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
catch (error) {
|
|
1498
|
+
updateBtwHistory((entries) => entries.map((item) => item.id === entry.id
|
|
1499
|
+
? {
|
|
1500
|
+
...item,
|
|
1501
|
+
status: 'error',
|
|
1502
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1503
|
+
}
|
|
1504
|
+
: item));
|
|
1505
|
+
}
|
|
1506
|
+
})();
|
|
1507
|
+
onTurnChange?.(forking);
|
|
1508
|
+
void forking.finally(() => onTurnChange?.(null));
|
|
1509
|
+
};
|
|
1291
1510
|
const renameSession = (requestedName) => {
|
|
1292
1511
|
const renaming = (async () => {
|
|
1293
1512
|
if (!sessionId) {
|
|
@@ -2019,6 +2238,69 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
2019
2238
|
}
|
|
2020
2239
|
const activeMenu = menuRef.current;
|
|
2021
2240
|
if (activeMenu) {
|
|
2241
|
+
if (activeMenu.kind === 'btw') {
|
|
2242
|
+
const selected = btwHistoryRef.current[activeMenu.selectedIndex];
|
|
2243
|
+
if (key.escape || value === '\u001B') {
|
|
2244
|
+
btwControllerRef.current?.abort();
|
|
2245
|
+
btwControllerRef.current = null;
|
|
2246
|
+
updateMenu(null);
|
|
2247
|
+
return;
|
|
2248
|
+
}
|
|
2249
|
+
if (key.leftArrow || key.rightArrow) {
|
|
2250
|
+
updateMenu({
|
|
2251
|
+
...activeMenu,
|
|
2252
|
+
selectedIndex: Math.max(0, Math.min(btwHistoryRef.current.length - 1, activeMenu.selectedIndex + (key.leftArrow ? -1 : 1))),
|
|
2253
|
+
scrollOffset: 0,
|
|
2254
|
+
});
|
|
2255
|
+
setBtwCopied(false);
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
if (key.upArrow || key.downArrow) {
|
|
2259
|
+
const maxOffset = Math.max(0, (selected?.answer.split('\n').length ?? 0) - 16);
|
|
2260
|
+
updateMenu({
|
|
2261
|
+
...activeMenu,
|
|
2262
|
+
scrollOffset: Math.max(0, Math.min(maxOffset, activeMenu.scrollOffset + (key.upArrow ? -1 : 1))),
|
|
2263
|
+
});
|
|
2264
|
+
return;
|
|
2265
|
+
}
|
|
2266
|
+
if (lower === 'x' && btwHistoryRef.current.length > 1 && selected) {
|
|
2267
|
+
updateBtwHistory(() => [selected]);
|
|
2268
|
+
updateMenu({ kind: 'btw', selectedIndex: 0, scrollOffset: 0 });
|
|
2269
|
+
setBtwCopied(false);
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
if (lower === 'c' && selected?.status === 'complete') {
|
|
2273
|
+
const copying = sideQuestionClipboardWriter(selected.answer).then(() => {
|
|
2274
|
+
if (!componentMountedRef.current)
|
|
2275
|
+
return;
|
|
2276
|
+
setBtwCopied(true);
|
|
2277
|
+
if (btwCopiedTimerRef.current) {
|
|
2278
|
+
clearTimeout(btwCopiedTimerRef.current);
|
|
2279
|
+
}
|
|
2280
|
+
btwCopiedTimerRef.current = setTimeout(() => {
|
|
2281
|
+
if (componentMountedRef.current)
|
|
2282
|
+
setBtwCopied(false);
|
|
2283
|
+
btwCopiedTimerRef.current = null;
|
|
2284
|
+
}, 1500);
|
|
2285
|
+
btwCopiedTimerRef.current.unref?.();
|
|
2286
|
+
}, (error) => updateBtwHistory((entries) => entries.map((item) => item.id === selected.id
|
|
2287
|
+
? {
|
|
2288
|
+
...item,
|
|
2289
|
+
status: 'error',
|
|
2290
|
+
error: error instanceof Error
|
|
2291
|
+
? error.message
|
|
2292
|
+
: String(error),
|
|
2293
|
+
}
|
|
2294
|
+
: item)));
|
|
2295
|
+
onTurnChange?.(copying);
|
|
2296
|
+
void copying.finally(() => onTurnChange?.(null));
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
if (lower === 'f' && selected?.status === 'complete') {
|
|
2300
|
+
forkSideQuestion(selected);
|
|
2301
|
+
}
|
|
2302
|
+
return;
|
|
2303
|
+
}
|
|
2022
2304
|
if (activeMenu.kind === 'help') {
|
|
2023
2305
|
if (key.escape) {
|
|
2024
2306
|
updateMenu(null);
|
|
@@ -2790,6 +3072,7 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
2790
3072
|
const copyCommand = /^\/copy(?:\s+(\d+))?$/u.exec(prompt);
|
|
2791
3073
|
const renameCommand = /^\/rename(?:\s+(.+))?$/u.exec(prompt);
|
|
2792
3074
|
const cdCommand = /^\/cd(?:\s+(.+))?$/u.exec(prompt);
|
|
3075
|
+
const btwCommand = /^\/btw(?:\s+([\s\S]+))?$/u.exec(prompt);
|
|
2793
3076
|
if (prompt === '/exit') {
|
|
2794
3077
|
exit();
|
|
2795
3078
|
}
|
|
@@ -2830,6 +3113,16 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
2830
3113
|
else if (prompt === '/add-dir') {
|
|
2831
3114
|
openWorkspaceDirectoryInput();
|
|
2832
3115
|
}
|
|
3116
|
+
else if (btwCommand) {
|
|
3117
|
+
const sideQuestion = btwCommand[1]?.trim();
|
|
3118
|
+
if (sideQuestion)
|
|
3119
|
+
askSideQuestion(sideQuestion);
|
|
3120
|
+
else
|
|
3121
|
+
showBtwUsage();
|
|
3122
|
+
}
|
|
3123
|
+
else if (prompt === '/background') {
|
|
3124
|
+
backgroundSession();
|
|
3125
|
+
}
|
|
2833
3126
|
else if (cdCommand) {
|
|
2834
3127
|
append({ kind: 'user', text: prompt });
|
|
2835
3128
|
const requestedCwd = cdCommand[1]?.trim();
|
|
@@ -3017,7 +3310,7 @@ export function InteractiveApp({ factory, initialSessions, initialPrompt, initia
|
|
|
3017
3310
|
? `Retry interrupted ${permission.call.name}?`
|
|
3018
3311
|
: `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
|
|
3019
3312
|
? 'Enter comma-separated option numbers or custom text · Esc cancels'
|
|
3020
|
-
: 'Enter one option number or custom text · Esc cancels' })] })) : elicitation ? (_jsxs(DialogFrame, { title: `MCP elicitation (${elicitation.request.serverName})`, screenReader: axScreenReader, children: [_jsx(Text, { children: elicitation.request.message }), elicitation.request.url ? (_jsx(Text, { children: elicitation.request.url })) : null, elicitation.request.requestedSchema ? (_jsx(Text, { dimColor: true, children: JSON.stringify(elicitation.request.requestedSchema) })) : null, _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter JSON object to accept \u00B7 Esc to cancel" })] })) : menu?.kind === 'model-input' ? (_jsxs(DialogFrame, { title: "Enter model ID", screenReader: axScreenReader, children: [_jsx(Text, { dimColor: true, children: "Enter a model ID supported by the configured provider." }), _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter confirms \u00B7 Esc cancels" })] })) : menu?.kind === 'export-filename' ? (_jsxs(DialogFrame, { title: "Enter filename:", screenReader: axScreenReader, children: [_jsxs(Text, { children: ["> ", input] }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc to go back" })] })) : menu?.kind === 'compact-progress' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "\u273B Compacting conversation\u2026" }), _jsxs(Text, { children: ['▰'.repeat(Math.floor(compactProgress / 2)), '▱'.repeat(50 - Math.floor(compactProgress / 2)), ' ', compactProgress, "%"] })] })) : menu?.kind === 'rewind' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: " Rewind" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', "Restore the code and/or conversation to the point before\u2026"] }), _jsx(Text, { children: " " }), (() => {
|
|
3313
|
+
: 'Enter one option number or custom text · Esc cancels' })] })) : elicitation ? (_jsxs(DialogFrame, { title: `MCP elicitation (${elicitation.request.serverName})`, screenReader: axScreenReader, children: [_jsx(Text, { children: elicitation.request.message }), elicitation.request.url ? (_jsx(Text, { children: elicitation.request.url })) : null, elicitation.request.requestedSchema ? (_jsx(Text, { dimColor: true, children: JSON.stringify(elicitation.request.requestedSchema) })) : null, _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter JSON object to accept \u00B7 Esc to cancel" })] })) : menu?.kind === 'model-input' ? (_jsxs(DialogFrame, { title: "Enter model ID", screenReader: axScreenReader, children: [_jsx(Text, { dimColor: true, children: "Enter a model ID supported by the configured provider." }), _jsxs(Text, { children: ["\u203A ", input] }), _jsx(Text, { dimColor: true, children: "Enter confirms \u00B7 Esc cancels" })] })) : menu?.kind === 'export-filename' ? (_jsxs(DialogFrame, { title: "Enter filename:", screenReader: axScreenReader, children: [_jsxs(Text, { children: ["> ", input] }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc to go back" })] })) : menu?.kind === 'compact-progress' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "\u273B Compacting conversation\u2026" }), _jsxs(Text, { children: ['▰'.repeat(Math.floor(compactProgress / 2)), '▱'.repeat(50 - Math.floor(compactProgress / 2)), ' ', compactProgress, "%"] })] })) : menu?.kind === 'btw' ? (_jsx(BtwPanel, { entries: btwHistory, selectedIndex: menu.selectedIndex, scrollOffset: menu.scrollOffset, copied: btwCopied, width: width, screenReader: axScreenReader })) : menu?.kind === 'rewind' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: " Rewind" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', "Restore the code and/or conversation to the point before\u2026"] }), _jsx(Text, { children: " " }), (() => {
|
|
3021
3314
|
const window = rewindPointWindow(menu.points, menu.selectedIndex);
|
|
3022
3315
|
return (_jsxs(_Fragment, { children: [window.start > 0 ? (_jsxs(Text, { dimColor: true, children: [" \u2191 ", window.start, " more above"] })) : null, menu.points
|
|
3023
3316
|
.slice(window.start, window.end)
|
|
@@ -3133,13 +3426,24 @@ export async function runInteractive(options) {
|
|
|
3133
3426
|
await listing.close?.();
|
|
3134
3427
|
let activeTurn = null;
|
|
3135
3428
|
let cleanup = null;
|
|
3429
|
+
let backgrounded;
|
|
3136
3430
|
const instance = render(_jsx(InteractiveApp, { factory: options.factory, initialSessions: initialSessions, slashCommands: initialSlashCommands, agents: initialAgents, initialHistory: initialHistory, ...(options.initialPrompt === undefined
|
|
3137
3431
|
? {}
|
|
3138
3432
|
: { initialPrompt: options.initialPrompt }), signal: signal, onCancel: () => controller.abort(), onTurnChange: (turn) => {
|
|
3139
3433
|
activeTurn = turn;
|
|
3140
3434
|
}, onCleanup: (closing) => {
|
|
3141
3435
|
cleanup = closing;
|
|
3142
|
-
},
|
|
3436
|
+
}, ...(options.onBackground === undefined
|
|
3437
|
+
? {}
|
|
3438
|
+
: {
|
|
3439
|
+
onBackground: async (request) => {
|
|
3440
|
+
const result = await options.onBackground?.(request);
|
|
3441
|
+
if (!result)
|
|
3442
|
+
throw new Error('Background launch returned no job');
|
|
3443
|
+
backgrounded = result;
|
|
3444
|
+
return result;
|
|
3445
|
+
},
|
|
3446
|
+
}), allowNewSession: !options.requireSession, ...(options.additionalDirectories === undefined
|
|
3143
3447
|
? {}
|
|
3144
3448
|
: { additionalDirectories: options.additionalDirectories }), ...(resume === undefined ? {} : { resume }), ...(options.display === undefined ? {} : { display: options.display }), ...(options.axScreenReader ? { axScreenReader: true } : {}), ...(options.allowDangerouslySkipPermissions
|
|
3145
3449
|
? { allowDangerouslySkipPermissions: true }
|
|
@@ -3153,6 +3457,8 @@ export async function runInteractive(options) {
|
|
|
3153
3457
|
await activeTurn;
|
|
3154
3458
|
if (cleanup)
|
|
3155
3459
|
await cleanup;
|
|
3460
|
+
if (backgrounded)
|
|
3461
|
+
options.onBackgrounded?.(backgrounded);
|
|
3156
3462
|
return signal.aborted ? 130 : 0;
|
|
3157
3463
|
}
|
|
3158
3464
|
//# sourceMappingURL=interactive.js.map
|