@sagmans/dsh-tui 0.6.0 → 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/.agents/skills/dsh-tui-dogfood/SKILL.md +83 -0
- package/.agents/skills/dsh-tui-dogfood/references/home-state.md +78 -0
- package/.agents/skills/dsh-tui-dogfood/scripts/clone-links.mjs +133 -0
- package/.agents/skills/dsh-tui-dogfood/scripts/run-plugin-from-worktree.sh +417 -0
- package/.agents/skills/dsh-tui-update-models/SKILL.md +121 -0
- package/.agents/skills/dsh-tui-update-models/references/model-wiring.md +162 -0
- package/.agents/skills/dsh-tui-update-models/scripts/dump-model-catalog.mjs +178 -0
- package/README.md +99 -5
- package/lib/agent/present.d.ts.map +1 -1
- package/lib/agent/present.js +2 -1
- package/lib/agent/present.js.map +1 -1
- package/lib/cards/composition.d.ts +68 -0
- package/lib/cards/composition.d.ts.map +1 -0
- package/lib/cards/composition.js +117 -0
- package/lib/cards/composition.js.map +1 -0
- package/lib/cards/presenter.d.ts +23 -0
- package/lib/cards/presenter.d.ts.map +1 -0
- package/lib/cards/presenter.js +394 -0
- package/lib/cards/presenter.js.map +1 -0
- package/lib/cards/preview.d.ts +42 -0
- package/lib/cards/preview.d.ts.map +1 -0
- package/lib/cards/preview.js +51 -0
- package/lib/cards/preview.js.map +1 -0
- package/lib/cards.d.ts +12 -120
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +4 -556
- package/lib/cards.js.map +1 -1
- package/lib/compat/section.d.ts +29 -0
- package/lib/compat/section.d.ts.map +1 -0
- package/lib/compat/section.js +82 -0
- package/lib/compat/section.js.map +1 -0
- package/lib/config.d.ts +27 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +61 -1
- package/lib/config.js.map +1 -1
- package/lib/contracts.d.ts +28 -0
- package/lib/contracts.d.ts.map +1 -1
- package/lib/fold-cursor.d.ts +8 -0
- package/lib/fold-cursor.d.ts.map +1 -1
- package/lib/fold-cursor.js +18 -0
- package/lib/fold-cursor.js.map +1 -1
- package/lib/gates/question-card.d.ts +77 -0
- package/lib/gates/question-card.d.ts.map +1 -0
- package/lib/gates/question-card.js +113 -0
- package/lib/gates/question-card.js.map +1 -0
- package/lib/gates/questions.d.ts +127 -0
- package/lib/gates/questions.d.ts.map +1 -0
- package/lib/gates/questions.js +418 -0
- package/lib/gates/questions.js.map +1 -0
- package/lib/gates.d.ts +1 -113
- package/lib/gates.d.ts.map +1 -1
- package/lib/gates.js +1 -484
- package/lib/gates.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +343 -2602
- package/lib/index.js.map +1 -1
- package/lib/input/action-catalog.d.ts +74 -0
- package/lib/input/action-catalog.d.ts.map +1 -0
- package/lib/input/action-catalog.js +137 -0
- package/lib/input/action-catalog.js.map +1 -0
- package/lib/input/actions.d.ts +5 -81
- package/lib/input/actions.d.ts.map +1 -1
- package/lib/input/actions.js +4 -625
- package/lib/input/actions.js.map +1 -1
- package/lib/input/completion.d.ts +1 -1
- package/lib/input/completion.d.ts.map +1 -1
- package/lib/input/completion.js +2 -1
- package/lib/input/completion.js.map +1 -1
- package/lib/input/file-index.d.ts +40 -0
- package/lib/input/file-index.d.ts.map +1 -0
- package/lib/input/file-index.js +141 -0
- package/lib/input/file-index.js.map +1 -0
- package/lib/input/file-search.d.ts +1 -38
- package/lib/input/file-search.d.ts.map +1 -1
- package/lib/input/file-search.js +1 -487
- package/lib/input/file-search.js.map +1 -1
- package/lib/input/key-press.d.ts +57 -0
- package/lib/input/key-press.d.ts.map +1 -0
- package/lib/input/key-press.js +218 -0
- package/lib/input/key-press.js.map +1 -0
- package/lib/input/keymap-conflicts.d.ts +59 -0
- package/lib/input/keymap-conflicts.d.ts.map +1 -0
- package/lib/input/keymap-conflicts.js +292 -0
- package/lib/input/keymap-conflicts.js.map +1 -0
- package/lib/input/keymap-settings.js +1 -1
- package/lib/input/keymap-settings.js.map +1 -1
- package/lib/input/keymap.d.ts.map +1 -1
- package/lib/input/keymap.js +3 -1
- package/lib/input/keymap.js.map +1 -1
- package/lib/input/workspace-files.d.ts +10 -0
- package/lib/input/workspace-files.d.ts.map +1 -0
- package/lib/input/workspace-files.js +359 -0
- package/lib/input/workspace-files.js.map +1 -0
- package/lib/install-skills.d.ts +20 -0
- package/lib/install-skills.d.ts.map +1 -0
- package/lib/install-skills.js +198 -0
- package/lib/install-skills.js.map +1 -0
- package/lib/keys-command.d.ts +2 -1
- package/lib/keys-command.d.ts.map +1 -1
- package/lib/keys-command.js +2 -1
- package/lib/keys-command.js.map +1 -1
- package/lib/model-list.d.ts +37 -0
- package/lib/model-list.d.ts.map +1 -0
- package/lib/model-list.js +60 -0
- package/lib/model-list.js.map +1 -0
- package/lib/startup.d.ts +8 -0
- package/lib/startup.d.ts.map +1 -1
- package/lib/startup.js +120 -24
- package/lib/startup.js.map +1 -1
- package/lib/subagents.d.ts +7 -3
- package/lib/subagents.d.ts.map +1 -1
- package/lib/subagents.js +28 -4
- package/lib/subagents.js.map +1 -1
- package/lib/surface/appearance-preferences.d.ts +26 -0
- package/lib/surface/appearance-preferences.d.ts.map +1 -0
- package/lib/surface/appearance-preferences.js +139 -0
- package/lib/surface/appearance-preferences.js.map +1 -0
- package/lib/surface/appearance.d.ts +87 -0
- package/lib/surface/appearance.d.ts.map +1 -0
- package/lib/surface/appearance.js +353 -0
- package/lib/surface/appearance.js.map +1 -0
- package/lib/surface/background-work.d.ts +49 -0
- package/lib/surface/background-work.d.ts.map +1 -0
- package/lib/surface/background-work.js +146 -0
- package/lib/surface/background-work.js.map +1 -0
- package/lib/surface/commands.d.ts +80 -0
- package/lib/surface/commands.d.ts.map +1 -0
- package/lib/surface/commands.js +364 -0
- package/lib/surface/commands.js.map +1 -0
- package/lib/surface/modal-input.d.ts +58 -0
- package/lib/surface/modal-input.d.ts.map +1 -0
- package/lib/surface/modal-input.js +237 -0
- package/lib/surface/modal-input.js.map +1 -0
- package/lib/surface/model-choice.d.ts +54 -0
- package/lib/surface/model-choice.d.ts.map +1 -0
- package/lib/surface/model-choice.js +325 -0
- package/lib/surface/model-choice.js.map +1 -0
- package/lib/surface/preset-choice.d.ts +78 -0
- package/lib/surface/preset-choice.d.ts.map +1 -0
- package/lib/surface/preset-choice.js +163 -0
- package/lib/surface/preset-choice.js.map +1 -0
- package/lib/surface/prompt-input.d.ts +97 -0
- package/lib/surface/prompt-input.d.ts.map +1 -0
- package/lib/surface/prompt-input.js +215 -0
- package/lib/surface/prompt-input.js.map +1 -0
- package/lib/surface/prompt-memory.d.ts +76 -0
- package/lib/surface/prompt-memory.d.ts.map +1 -0
- package/lib/surface/prompt-memory.js +167 -0
- package/lib/surface/prompt-memory.js.map +1 -0
- package/lib/surface/session-lifecycle.d.ts +120 -0
- package/lib/surface/session-lifecycle.d.ts.map +1 -0
- package/lib/surface/session-lifecycle.js +321 -0
- package/lib/surface/session-lifecycle.js.map +1 -0
- package/lib/surface/session-picker.d.ts +39 -0
- package/lib/surface/session-picker.d.ts.map +1 -0
- package/lib/surface/session-picker.js +107 -0
- package/lib/surface/session-picker.js.map +1 -0
- package/lib/surface/session-view.d.ts +86 -0
- package/lib/surface/session-view.d.ts.map +1 -0
- package/lib/surface/session-view.js +215 -0
- package/lib/surface/session-view.js.map +1 -0
- package/lib/surface/staged-turns.d.ts +81 -0
- package/lib/surface/staged-turns.d.ts.map +1 -0
- package/lib/surface/staged-turns.js +206 -0
- package/lib/surface/staged-turns.js.map +1 -0
- package/lib/surface/terminal-lifecycle.d.ts +76 -0
- package/lib/surface/terminal-lifecycle.d.ts.map +1 -0
- package/lib/surface/terminal-lifecycle.js +222 -0
- package/lib/surface/terminal-lifecycle.js.map +1 -0
- package/lib/terminal-text/scan.d.ts +44 -0
- package/lib/terminal-text/scan.d.ts.map +1 -0
- package/lib/terminal-text/scan.js +195 -0
- package/lib/terminal-text/scan.js.map +1 -0
- package/lib/terminal-text/sgr.d.ts +32 -0
- package/lib/terminal-text/sgr.d.ts.map +1 -0
- package/lib/terminal-text/sgr.js +203 -0
- package/lib/terminal-text/sgr.js.map +1 -0
- package/lib/terminal-text.d.ts +1 -1
- package/lib/terminal-text.d.ts.map +1 -1
- package/lib/terminal-text.js +2 -379
- package/lib/terminal-text.js.map +1 -1
- package/lib/theme-command.js +2 -1
- package/lib/theme-command.js.map +1 -1
- package/lib/theme-defaults.d.ts +64 -0
- package/lib/theme-defaults.d.ts.map +1 -0
- package/lib/theme-defaults.js +248 -0
- package/lib/theme-defaults.js.map +1 -0
- package/lib/theme-resolver.d.ts +36 -0
- package/lib/theme-resolver.d.ts.map +1 -0
- package/lib/theme-resolver.js +112 -0
- package/lib/theme-resolver.js.map +1 -0
- package/lib/theme-schema.d.ts.map +1 -1
- package/lib/theme-schema.js +3 -2
- package/lib/theme-schema.js.map +1 -1
- package/lib/theme-settings.d.ts +5 -7
- package/lib/theme-settings.d.ts.map +1 -1
- package/lib/theme-settings.js +27 -19
- package/lib/theme-settings.js.map +1 -1
- package/lib/theme-tokens.d.ts +0 -89
- package/lib/theme-tokens.d.ts.map +1 -1
- package/lib/theme-tokens.js +0 -356
- package/lib/theme-tokens.js.map +1 -1
- package/lib/theme.d.ts +1 -1
- package/lib/theme.d.ts.map +1 -1
- package/lib/theme.js +2 -1
- package/lib/theme.js.map +1 -1
- package/lib/tool-display.d.ts.map +1 -1
- package/lib/tool-display.js +2 -1
- package/lib/tool-display.js.map +1 -1
- package/lib/transcript/message-content.d.ts +21 -0
- package/lib/transcript/message-content.d.ts.map +1 -0
- package/lib/transcript/message-content.js +61 -0
- package/lib/transcript/message-content.js.map +1 -0
- package/lib/transcript/tool-calls.d.ts +106 -0
- package/lib/transcript/tool-calls.d.ts.map +1 -0
- package/lib/transcript/tool-calls.js +254 -0
- package/lib/transcript/tool-calls.js.map +1 -0
- package/lib/transcript.d.ts +14 -55
- package/lib/transcript.d.ts.map +1 -1
- package/lib/transcript.js +31 -253
- package/lib/transcript.js.map +1 -1
- package/lib/ui/dock.d.ts +14 -2
- package/lib/ui/dock.d.ts.map +1 -1
- package/lib/ui/dock.js +52 -10
- package/lib/ui/dock.js.map +1 -1
- package/lib/ui/editor.d.ts.map +1 -1
- package/lib/ui/editor.js +2 -1
- package/lib/ui/editor.js.map +1 -1
- package/lib/ui/keymap-picker.d.ts +2 -1
- package/lib/ui/keymap-picker.d.ts.map +1 -1
- package/lib/ui/keymap-picker.js +1 -0
- package/lib/ui/keymap-picker.js.map +1 -1
- package/lib/ui/view/gate-card.d.ts +21 -0
- package/lib/ui/view/gate-card.d.ts.map +1 -0
- package/lib/ui/view/gate-card.js +104 -0
- package/lib/ui/view/gate-card.js.map +1 -0
- package/lib/ui/view/tool-card.d.ts +138 -0
- package/lib/ui/view/tool-card.d.ts.map +1 -0
- package/lib/ui/view/tool-card.js +413 -0
- package/lib/ui/view/tool-card.js.map +1 -0
- package/lib/ui/view/transcript-message.d.ts +62 -0
- package/lib/ui/view/transcript-message.d.ts.map +1 -0
- package/lib/ui/view/transcript-message.js +158 -0
- package/lib/ui/view/transcript-message.js.map +1 -0
- package/lib/ui/view.d.ts +80 -220
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +81 -675
- package/lib/ui/view.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type KeyId } from '@earendil-works/pi-tui';
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
4
|
+
import { type Keymap } from '../input/actions.ts';
|
|
5
|
+
import { type RegisteredCommand } from '../input/completion.ts';
|
|
6
|
+
import { type Submission } from '../input/submission.ts';
|
|
7
|
+
import type { WarningSafeTui } from '../terminal/warning-screen.ts';
|
|
8
|
+
import type { GateInputBar } from '../ui/gate-input.ts';
|
|
9
|
+
import type { PromptBar } from '../ui/prompt.ts';
|
|
10
|
+
/**
|
|
11
|
+
* What the prompt-input owner needs from the surface that composes it.
|
|
12
|
+
*
|
|
13
|
+
* Every read is taken at call time. The keys, their prefix and the chord window
|
|
14
|
+
* belong to the settings document, which is hot-reloaded, so a copy kept here
|
|
15
|
+
* would answer the reader's next press with the map of the day this loaded. The
|
|
16
|
+
* terminal and the bar are reached through readers for the opposite reason: the
|
|
17
|
+
* settings scope applies before either exists, and the chord it has to end is
|
|
18
|
+
* armed at that moment.
|
|
19
|
+
*/
|
|
20
|
+
export interface PromptInputPorts {
|
|
21
|
+
/** The keys in force; the settings document owns them and the surface holds them. */
|
|
22
|
+
readonly keymap: () => Keymap;
|
|
23
|
+
/** The keys that start a chord, and how long one waits; the settings document owns all of it. */
|
|
24
|
+
readonly prefixKeys: () => readonly KeyId[];
|
|
25
|
+
readonly prefixWindowMs: () => number;
|
|
26
|
+
readonly tui: () => WarningSafeTui;
|
|
27
|
+
/** The bar the reader types in, and the question that borrows it. */
|
|
28
|
+
readonly editor: () => GateInputBar;
|
|
29
|
+
readonly promptBar: () => PromptBar;
|
|
30
|
+
/** Drive an open gate or picker; false hands the press back. */
|
|
31
|
+
readonly modalHandleKey: (data: string) => boolean;
|
|
32
|
+
/** Flip one of the folds the transcript is drawn with. */
|
|
33
|
+
readonly toggleCards: () => void;
|
|
34
|
+
readonly toggleSubCalls: () => void;
|
|
35
|
+
readonly toggleReasoning: () => void;
|
|
36
|
+
readonly openEffortPicker: () => void;
|
|
37
|
+
readonly openHistoryPicker: () => void;
|
|
38
|
+
/** Return to this session's own transcript, when a child is on screen. */
|
|
39
|
+
readonly back: () => void;
|
|
40
|
+
/** What the agent has not started yet, which one press takes back. */
|
|
41
|
+
readonly queuedPrompts: () => readonly string[];
|
|
42
|
+
readonly turnRunning: () => boolean;
|
|
43
|
+
readonly viewingChild: () => boolean;
|
|
44
|
+
readonly interrupt: () => void;
|
|
45
|
+
readonly notice: (message: string) => void;
|
|
46
|
+
readonly requestExit: (code: number) => void;
|
|
47
|
+
/** Remember one submitted line; the prompt's own memory owns the store. */
|
|
48
|
+
readonly recordPrompt: (text: string) => void;
|
|
49
|
+
/** Carry out one classified line; the command routing owner takes it over later. */
|
|
50
|
+
readonly runSubmission: (submission: Submission) => void;
|
|
51
|
+
/** The agent this terminal drives, or undefined while it starts. */
|
|
52
|
+
readonly drivenAgent: () => Agent | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The commands that agent can run, or undefined when no registry answers.
|
|
55
|
+
*
|
|
56
|
+
* A scoped list operation rather than the registry itself: the registry is
|
|
57
|
+
* read through its own owner, and this one only ever needs what is offered.
|
|
58
|
+
*/
|
|
59
|
+
readonly registeredCommands: (agent: Agent) => readonly RegisteredCommand[] | undefined;
|
|
60
|
+
}
|
|
61
|
+
/** The presses, menus and the submit line the composing surface routes here. */
|
|
62
|
+
export interface PromptInput {
|
|
63
|
+
/**
|
|
64
|
+
* Install the reader's keys where the library reads them.
|
|
65
|
+
*
|
|
66
|
+
* Installed where the library reads it, so a remap lands on the next press
|
|
67
|
+
* rather than at the next restart.
|
|
68
|
+
*/
|
|
69
|
+
readonly installBindings: () => void;
|
|
70
|
+
/** A chord armed under the keymap the reader just replaced is not their chord. */
|
|
71
|
+
readonly disarmChord: () => void;
|
|
72
|
+
/** The armed chord as the footer prints it, or undefined when nothing is armed. */
|
|
73
|
+
readonly chordHint: () => string | undefined;
|
|
74
|
+
/** Register this owner's press listener; the answer takes it back off. */
|
|
75
|
+
readonly inputListener: () => () => void;
|
|
76
|
+
/** Give the bar the menu the role it is in calls for. */
|
|
77
|
+
readonly applyCompletion: () => void;
|
|
78
|
+
/** Rebuild both menus from whatever this session can run right now. */
|
|
79
|
+
readonly installCompletion: () => void;
|
|
80
|
+
/** Register the rebuild a newly registered command asks for. */
|
|
81
|
+
readonly commandListeners: () => readonly (() => void)[];
|
|
82
|
+
/** Classify a submitted line, remember it, and hand it to the surface. */
|
|
83
|
+
readonly attachSubmit: () => void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The prompt bar's own presses: the chord, the keys the surface answers itself,
|
|
87
|
+
* and the line it submits.
|
|
88
|
+
*
|
|
89
|
+
* A press reaches the surface's listener before any focused component sees it,
|
|
90
|
+
* so everything that answers a key held at the bar is decided in one place:
|
|
91
|
+
* what a chord may finish, which keys are consumed outright, and where a
|
|
92
|
+
* submitted line goes. The two completion menus share the same seam because
|
|
93
|
+
* they follow the bar's role rather than a session, and the command registry
|
|
94
|
+
* that fills one of them is read live.
|
|
95
|
+
*/
|
|
96
|
+
export declare function createPromptInput(ctx: Context, ports: PromptInputPorts): PromptInput;
|
|
97
|
+
//# sourceMappingURL=prompt-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-input.d.ts","sourceRoot":"","sources":["../../src/surface/prompt-input.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { isKeyRelease, matchesKey, } from '@earendil-works/pi-tui';
|
|
2
|
+
import { surfaceBindings } from "../input/actions.js";
|
|
3
|
+
import { cancelStep, quitStep } from "../input/cancel.js";
|
|
4
|
+
import { createAnswerCompletionProvider, createCompletionProvider } from "../input/completion.js";
|
|
5
|
+
import { createFileIndex } from "../input/file-index.js";
|
|
6
|
+
import { ChordReader, chordBindings, installKeybindings } from "../input/keymap.js";
|
|
7
|
+
import { classifySubmission } from "../input/submission.js";
|
|
8
|
+
/**
|
|
9
|
+
* The prompt bar's own presses: the chord, the keys the surface answers itself,
|
|
10
|
+
* and the line it submits.
|
|
11
|
+
*
|
|
12
|
+
* A press reaches the surface's listener before any focused component sees it,
|
|
13
|
+
* so everything that answers a key held at the bar is decided in one place:
|
|
14
|
+
* what a chord may finish, which keys are consumed outright, and where a
|
|
15
|
+
* submitted line goes. The two completion menus share the same seam because
|
|
16
|
+
* they follow the bar's role rather than a session, and the command registry
|
|
17
|
+
* that fills one of them is read live.
|
|
18
|
+
*/
|
|
19
|
+
export function createPromptInput(ctx, ports) {
|
|
20
|
+
/**
|
|
21
|
+
* The chord between a prefix and the action that follows it.
|
|
22
|
+
*
|
|
23
|
+
* Built before the terminal exists, because the settings scope applies first
|
|
24
|
+
* and has to be able to end a chord armed under the keymap it replaced. The
|
|
25
|
+
* repaint the window also wants is late-bound: only a key press reaches it,
|
|
26
|
+
* and no key can arrive before the surface has started.
|
|
27
|
+
*/
|
|
28
|
+
const keyChord = new ChordReader(() => ports.prefixKeys(), () => chordBindings(ports.keymap()), () => ports.prefixWindowMs(), () => ports.tui().requestRender());
|
|
29
|
+
/**
|
|
30
|
+
* Whether the bar holds anything the reader wrote.
|
|
31
|
+
*
|
|
32
|
+
* Whitespace counts: it is a character the editor holds, and a press that
|
|
33
|
+
* clears it is the press the reader asked for. A paste counts expanded,
|
|
34
|
+
* because a marker is content rather than an absence of it.
|
|
35
|
+
*/
|
|
36
|
+
const barHasText = () => ports.editor().getExpandedText() !== '';
|
|
37
|
+
/**
|
|
38
|
+
* What each key the surface answers itself does; false hands the press back.
|
|
39
|
+
*
|
|
40
|
+
* Keyed by the table's own ids, so a key added to {@link SURFACE_ACTIONS}
|
|
41
|
+
* without a handler here fails to compile rather than doing nothing.
|
|
42
|
+
*/
|
|
43
|
+
const surfaceActions = {
|
|
44
|
+
toolDetail: () => {
|
|
45
|
+
ports.toggleCards();
|
|
46
|
+
ports.tui().requestRender();
|
|
47
|
+
return true;
|
|
48
|
+
},
|
|
49
|
+
subCalls: () => {
|
|
50
|
+
ports.toggleSubCalls();
|
|
51
|
+
ports.tui().requestRender();
|
|
52
|
+
return true;
|
|
53
|
+
},
|
|
54
|
+
reasoning: () => {
|
|
55
|
+
ports.toggleReasoning();
|
|
56
|
+
ports.tui().requestRender();
|
|
57
|
+
return true;
|
|
58
|
+
},
|
|
59
|
+
effort: () => {
|
|
60
|
+
ports.openEffortPicker();
|
|
61
|
+
return true;
|
|
62
|
+
},
|
|
63
|
+
history: () => {
|
|
64
|
+
ports.openHistoryPicker();
|
|
65
|
+
return true;
|
|
66
|
+
},
|
|
67
|
+
back: () => {
|
|
68
|
+
ports.back();
|
|
69
|
+
return true;
|
|
70
|
+
},
|
|
71
|
+
interrupt: () => {
|
|
72
|
+
// In raw mode Ctrl+C never reaches the process as SIGINT, so the surface
|
|
73
|
+
// decides what one press takes back — and a press with nothing left to
|
|
74
|
+
// cancel is handed back rather than spent on leaving.
|
|
75
|
+
const queued = ports.queuedPrompts();
|
|
76
|
+
const step = cancelStep({
|
|
77
|
+
barHasText: barHasText(),
|
|
78
|
+
queuedPrompts: queued.length,
|
|
79
|
+
turnRunning: ports.turnRunning(),
|
|
80
|
+
viewingChild: ports.viewingChild(),
|
|
81
|
+
});
|
|
82
|
+
switch (step) {
|
|
83
|
+
case 'clear-editor':
|
|
84
|
+
ports.editor().setText('');
|
|
85
|
+
ports.tui().requestRender();
|
|
86
|
+
return true;
|
|
87
|
+
case 'reclaim-queued':
|
|
88
|
+
// The interrupt drops whatever the agent had not started, so the words
|
|
89
|
+
// are read before it is stopped and handed back to the bar: a key that
|
|
90
|
+
// means "stop" must not be the key that loses the reader's own prompts.
|
|
91
|
+
ports.interrupt();
|
|
92
|
+
ports.editor().setText(queued.join('\n'));
|
|
93
|
+
ports.notice(`interrupt requested · ${queued.length} queued ${queued.length === 1 ? 'prompt' : 'prompts'} back in the bar`);
|
|
94
|
+
ports.tui().requestRender();
|
|
95
|
+
return true;
|
|
96
|
+
case 'interrupt-turn':
|
|
97
|
+
ports.interrupt();
|
|
98
|
+
ports.notice('interrupt requested');
|
|
99
|
+
ports.tui().requestRender();
|
|
100
|
+
return true;
|
|
101
|
+
case 'leave-child-view':
|
|
102
|
+
ports.back();
|
|
103
|
+
return true;
|
|
104
|
+
case 'hand-back':
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
quit: () => {
|
|
109
|
+
// The only key that leaves. Text in the bar keeps it for the editor, so
|
|
110
|
+
// the library's delete forward is never taken from a reader who is editing.
|
|
111
|
+
switch (quitStep({ barHasText: barHasText(), overlayOpen: ports.tui().hasOverlay(), turnRunning: ports.turnRunning() })) {
|
|
112
|
+
case 'cancel-then-quit':
|
|
113
|
+
// An exit that waits on a tool call is not an exit, so the turn is
|
|
114
|
+
// asked to stop and the leave does not wait for the answer.
|
|
115
|
+
ports.interrupt();
|
|
116
|
+
ports.requestExit(0);
|
|
117
|
+
return true;
|
|
118
|
+
case 'quit':
|
|
119
|
+
ports.requestExit(0);
|
|
120
|
+
return true;
|
|
121
|
+
case 'hand-back':
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
/** One scan of the workspace, shared by both menus: the listing is read-only and cached. */
|
|
127
|
+
const fileIndex = createFileIndex(process.cwd());
|
|
128
|
+
/** The menu the prompt bar offers: the commands this session can run, and the workspace's files. */
|
|
129
|
+
let promptCompletion;
|
|
130
|
+
/** The menu an answer offers, which is the same menu without the commands. */
|
|
131
|
+
let answerCompletion;
|
|
132
|
+
/**
|
|
133
|
+
* Give the bar the menu its current role calls for.
|
|
134
|
+
*
|
|
135
|
+
* A question borrows the prompt bar's editor rather than drawing its own, so
|
|
136
|
+
* the provider has to follow the borrow: a slash command is a line this
|
|
137
|
+
* surface would run, and an answer is text the model reads, so the two roles
|
|
138
|
+
* must not share one menu.
|
|
139
|
+
*/
|
|
140
|
+
const applyCompletion = () => {
|
|
141
|
+
const chosen = ports.promptBar().isBorrowed() ? answerCompletion : promptCompletion;
|
|
142
|
+
if (chosen !== undefined)
|
|
143
|
+
ports.editor().setAutocompleteProvider(chosen);
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Offer completion for whatever this session can run right now.
|
|
147
|
+
*
|
|
148
|
+
* The registry is agent-scoped and still empty while the agent starts, so the
|
|
149
|
+
* menu is rebuilt when the agent arrives and whenever a package registers
|
|
150
|
+
* another command. Both providers are built here because the answer's is the
|
|
151
|
+
* prompt bar's own minus the commands, and a rebuild while a question is open
|
|
152
|
+
* must not leave the answer menu unreachable.
|
|
153
|
+
*/
|
|
154
|
+
const installCompletion = () => {
|
|
155
|
+
const current = ports.drivenAgent();
|
|
156
|
+
if (current === undefined)
|
|
157
|
+
return;
|
|
158
|
+
const commands = ports.registeredCommands(current);
|
|
159
|
+
if (commands === undefined)
|
|
160
|
+
return;
|
|
161
|
+
answerCompletion = createAnswerCompletionProvider(process.cwd(), fileIndex);
|
|
162
|
+
promptCompletion = createCompletionProvider(commands, process.cwd(), fileIndex);
|
|
163
|
+
applyCompletion();
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
installBindings: () => installKeybindings(ports.keymap()),
|
|
167
|
+
disarmChord: () => keyChord.disarm(),
|
|
168
|
+
chordHint: () => keyChord.hint(),
|
|
169
|
+
applyCompletion,
|
|
170
|
+
installCompletion,
|
|
171
|
+
commandListeners: () => [ctx.on('commands/change', () => installCompletion())],
|
|
172
|
+
inputListener: () => ports.tui().addInputListener(data => {
|
|
173
|
+
// A key arrives as a press and a release once the surface asks the terminal
|
|
174
|
+
// to report key events, and this library drops the release only for the
|
|
175
|
+
// focused component: a listener sees both halves, so an arrow key that is
|
|
176
|
+
// acted on twice steps a picker two rows and answers a question two options
|
|
177
|
+
// on. Falls through rather than consuming, which leaves a component that
|
|
178
|
+
// asked for releases its own half.
|
|
179
|
+
if (isKeyRelease(data))
|
|
180
|
+
return undefined;
|
|
181
|
+
if (ports.modalHandleKey(data))
|
|
182
|
+
return { consume: true };
|
|
183
|
+
// A chord is the surface's second key: the prefix is consumed and the
|
|
184
|
+
// footer names what may follow, while a key that finishes nothing is handed
|
|
185
|
+
// on. Detail the reader asked for is always available, even mid-turn: the
|
|
186
|
+
// collapsed view is a default, not the only state.
|
|
187
|
+
const chorded = keyChord.handle(data);
|
|
188
|
+
if (chorded !== undefined) {
|
|
189
|
+
if (chorded.kind === 'action')
|
|
190
|
+
ports.runSubmission(chorded.binding.submission);
|
|
191
|
+
ports.tui().requestRender();
|
|
192
|
+
return { consume: true };
|
|
193
|
+
}
|
|
194
|
+
for (const binding of surfaceBindings(ports.keymap())) {
|
|
195
|
+
if (!matchesKey(data, binding.key))
|
|
196
|
+
continue;
|
|
197
|
+
return surfaceActions[binding.action]() ? { consume: true } : undefined;
|
|
198
|
+
}
|
|
199
|
+
return undefined;
|
|
200
|
+
}),
|
|
201
|
+
attachSubmit: () => {
|
|
202
|
+
ports.editor().onSubmit = text => {
|
|
203
|
+
const submission = classifySubmission(text);
|
|
204
|
+
if (submission.kind === 'empty')
|
|
205
|
+
return;
|
|
206
|
+
// The library's own history feeds the up/down keys; the store below feeds
|
|
207
|
+
// ghost completion and reverse search, and is global rather than per-session.
|
|
208
|
+
ports.editor().addToHistory(text);
|
|
209
|
+
ports.recordPrompt(text);
|
|
210
|
+
ports.runSubmission(submission);
|
|
211
|
+
};
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=prompt-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-input.js","sourceRoot":"","sources":["../../src/surface/prompt-input.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,UAAU,GAGX,MAAM,wBAAwB,CAAA;AAM/B,OAAO,EAAE,eAAe,EAAe,MAAM,qBAAqB,CAAA;AAElE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,8BAA8B,EAAE,wBAAwB,EAA0B,MAAM,wBAAwB,CAAA;AACzH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAmB,MAAM,wBAAwB,CAAA;AAkF5E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY,EAAE,KAAuB;IACrE;;;;;;;OAOG;IACH,MAAM,QAAQ,GAAG,IAAI,WAAW,CAC9B,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EACxB,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EACnC,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAC5B,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAClC,CAAA;IAED;;;;;;OAMG;IACH,MAAM,UAAU,GAAG,GAAY,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,CAAA;IAEzE;;;;;OAKG;IACH,MAAM,cAAc,GAAqD;QACvE,UAAU,EAAE,GAAG,EAAE;YACf,KAAK,CAAC,WAAW,EAAE,CAAA;YACnB,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;YAC3B,OAAO,IAAI,CAAA;QACb,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,KAAK,CAAC,cAAc,EAAE,CAAA;YACtB,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;YAC3B,OAAO,IAAI,CAAA;QACb,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,KAAK,CAAC,eAAe,EAAE,CAAA;YACvB,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;YAC3B,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,EAAE,GAAG,EAAE;YACX,KAAK,CAAC,gBAAgB,EAAE,CAAA;YACxB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACZ,KAAK,CAAC,iBAAiB,EAAE,CAAA;YACzB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,KAAK,CAAC,IAAI,EAAE,CAAA;YACZ,OAAO,IAAI,CAAA;QACb,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,yEAAyE;YACzE,uEAAuE;YACvE,sDAAsD;YACtD,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa,EAAE,CAAA;YACpC,MAAM,IAAI,GAAG,UAAU,CAAC;gBACtB,UAAU,EAAE,UAAU,EAAE;gBACxB,aAAa,EAAE,MAAM,CAAC,MAAM;gBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE;gBAChC,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE;aACnC,CAAC,CAAA;YACF,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,cAAc;oBACjB,KAAK,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;oBAC1B,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;oBAC3B,OAAO,IAAI,CAAA;gBACb,KAAK,gBAAgB;oBACnB,uEAAuE;oBACvE,uEAAuE;oBACvE,wEAAwE;oBACxE,KAAK,CAAC,SAAS,EAAE,CAAA;oBACjB,KAAK,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;oBACzC,KAAK,CAAC,MAAM,CAAC,yBAAyB,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,kBAAkB,CAAC,CAAA;oBAC3H,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;oBAC3B,OAAO,IAAI,CAAA;gBACb,KAAK,gBAAgB;oBACnB,KAAK,CAAC,SAAS,EAAE,CAAA;oBACjB,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAA;oBACnC,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;oBAC3B,OAAO,IAAI,CAAA;gBACb,KAAK,kBAAkB;oBACrB,KAAK,CAAC,IAAI,EAAE,CAAA;oBACZ,OAAO,IAAI,CAAA;gBACb,KAAK,WAAW;oBACd,OAAO,KAAK,CAAA;YAChB,CAAC;QACH,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,wEAAwE;YACxE,4EAA4E;YAC5E,QAAQ,QAAQ,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC;gBACxH,KAAK,kBAAkB;oBACrB,mEAAmE;oBACnE,4DAA4D;oBAC5D,KAAK,CAAC,SAAS,EAAE,CAAA;oBACjB,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;oBACpB,OAAO,IAAI,CAAA;gBACb,KAAK,MAAM;oBACT,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;oBACpB,OAAO,IAAI,CAAA;gBACb,KAAK,WAAW;oBACd,OAAO,KAAK,CAAA;YAChB,CAAC;QACH,CAAC;KACF,CAAA;IAED,4FAA4F;IAC5F,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAChD,oGAAoG;IACpG,IAAI,gBAA0D,CAAA;IAC9D,8EAA8E;IAC9E,IAAI,gBAA0D,CAAA;IAE9D;;;;;;;OAOG;IACH,MAAM,eAAe,GAAG,GAAS,EAAE;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAA;QACnF,IAAI,MAAM,KAAK,SAAS;YAAE,KAAK,CAAC,MAAM,EAAE,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAA;IAC1E,CAAC,CAAA;IAED;;;;;;;;OAQG;IACH,MAAM,iBAAiB,GAAG,GAAS,EAAE;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;QACnC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAM;QACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QAClD,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAM;QAClC,gBAAgB,GAAG,8BAA8B,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;QAC3E,gBAAgB,GAAG,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;QAC/E,eAAe,EAAE,CAAA;IACnB,CAAC,CAAA;IAED,OAAO;QACL,eAAe,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACzD,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE;QACpC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;QAChC,eAAe;QACf,iBAAiB;QACjB,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC9E,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE;YACvD,4EAA4E;YAC5E,wEAAwE;YACxE,0EAA0E;YAC1E,4EAA4E;YAC5E,yEAAyE;YACzE,mCAAmC;YACnC,IAAI,YAAY,CAAC,IAAI,CAAC;gBAAE,OAAO,SAAS,CAAA;YACxC,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YACxD,sEAAsE;YACtE,4EAA4E;YAC5E,0EAA0E;YAC1E,mDAAmD;YACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;oBAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;gBAC9E,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAA;gBAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YAC1B,CAAC;YACD,KAAK,MAAM,OAAO,IAAI,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;gBACtD,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;oBAAE,SAAQ;gBAC5C,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;YACzE,CAAC;YACD,OAAO,SAAS,CAAA;QAClB,CAAC,CAAC;QACF,YAAY,EAAE,GAAG,EAAE;YACjB,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE;gBAC/B,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;gBAC3C,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO;oBAAE,OAAM;gBACvC,0EAA0E;gBAC1E,8EAA8E;gBAC9E,KAAK,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;gBACjC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;gBACxB,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;YACjC,CAAC,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
2
|
+
import type { Keymap } from '../input/actions.ts';
|
|
3
|
+
import { PromptStash } from '../stash.ts';
|
|
4
|
+
import type { TuiTheme } from '../theme.ts';
|
|
5
|
+
import type { GhostBrush } from '../ui/editor.ts';
|
|
6
|
+
import type { PickerAction, PickerCard } from '../ui/picker.ts';
|
|
7
|
+
/**
|
|
8
|
+
* What a list has to answer to be driven by whoever owns the keyboard.
|
|
9
|
+
*
|
|
10
|
+
* This owner raises the lists and hands them over; the overlay they are drawn
|
|
11
|
+
* in, the vetting of a pick, and how long a list may hold the keyboard stay
|
|
12
|
+
* with the modal owner, which is why they arrive as a port.
|
|
13
|
+
*/
|
|
14
|
+
export interface MemoryPicker {
|
|
15
|
+
handleKey(data: string): PickerAction | undefined;
|
|
16
|
+
card(window?: number): PickerCard;
|
|
17
|
+
setNote(text: string | undefined): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What the prompt's memory needs from the surface that composes it.
|
|
21
|
+
*
|
|
22
|
+
* The history switches are read at call time rather than captured: the
|
|
23
|
+
* settings document is hot-reloaded, and a copy taken here would pin this
|
|
24
|
+
* surface to the settings of the day it loaded. The theme is read through its
|
|
25
|
+
* delegate for the same reason, and the editor and the picker are ports
|
|
26
|
+
* because the widget and the keyboard lifetime are the surface's own.
|
|
27
|
+
*/
|
|
28
|
+
export interface PromptMemoryPorts {
|
|
29
|
+
readonly historyEnabled: () => boolean;
|
|
30
|
+
readonly historyGhost: () => boolean;
|
|
31
|
+
readonly historyMaxEntries: () => number;
|
|
32
|
+
readonly theme: TuiTheme;
|
|
33
|
+
readonly keymap: () => Keymap;
|
|
34
|
+
readonly notice: (message: string) => void;
|
|
35
|
+
readonly render: () => void;
|
|
36
|
+
/** The draft as written, with a pasted block expanded back to its text. */
|
|
37
|
+
readonly editorText: () => string;
|
|
38
|
+
readonly setEditorText: (text: string) => void;
|
|
39
|
+
/** Whether the prompt bar belongs to the reader rather than to a question. */
|
|
40
|
+
readonly editorAvailable: () => boolean;
|
|
41
|
+
/** The session this surface drives, which is the one its drafts belong to. */
|
|
42
|
+
readonly activeSession: () => SessionId;
|
|
43
|
+
readonly openPicker: (picker: MemoryPicker) => Promise<string | undefined>;
|
|
44
|
+
}
|
|
45
|
+
/** The prompt's memory of itself, and the operations the surface routes to it. */
|
|
46
|
+
export interface PromptMemory {
|
|
47
|
+
/** The dimmed completion the editor draws from recorded prompts. */
|
|
48
|
+
readonly ghostBrush: GhostBrush;
|
|
49
|
+
/** Reverse search over recorded prompts, seeded with whatever is in the bar. */
|
|
50
|
+
readonly openHistoryPicker: () => Promise<void>;
|
|
51
|
+
/** Record a submitted line; the setting decides whether any of it is kept. */
|
|
52
|
+
readonly record: (text: string) => void;
|
|
53
|
+
/** Show where history is kept, or forget it; the file is global to this machine. */
|
|
54
|
+
readonly runHistoryCommand: (argument: string) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Build the bank for the session this surface drives, and hand it back.
|
|
57
|
+
*
|
|
58
|
+
* Handed back rather than kept here alone: the surface's status count and the
|
|
59
|
+
* parked-draft commands it routes read the same instance, and both exist
|
|
60
|
+
* before a pick could reach a picker — which is why the bank cannot be built
|
|
61
|
+
* with the rest of this owner.
|
|
62
|
+
*/
|
|
63
|
+
readonly buildStash: () => PromptStash;
|
|
64
|
+
/** Follow the session just opened, so the footer counts that session's drafts. */
|
|
65
|
+
readonly sessionOpened: () => void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The memory the prompt keeps of what was typed, and what it offers back.
|
|
69
|
+
*
|
|
70
|
+
* Two stores, one subject: the prompt history is global and written from every
|
|
71
|
+
* submitted line, while the stash parks a draft for the session in force. Both
|
|
72
|
+
* are read through the same editor and both answer in a list, so they share the
|
|
73
|
+
* one owner that knows what the reader is looking at.
|
|
74
|
+
*/
|
|
75
|
+
export declare function createPromptMemory(ports: PromptMemoryPorts): PromptMemory;
|
|
76
|
+
//# sourceMappingURL=prompt-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-memory.d.ts","sourceRoot":"","sources":["../../src/surface/prompt-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAG3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAM/D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAA;IACjD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAA;IACjC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAA;CACxC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,OAAO,CAAA;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,OAAO,CAAA;IACpC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,MAAM,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,CAAA;IACjC,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,MAAM,OAAO,CAAA;IACvC,8EAA8E;IAC9E,QAAQ,CAAC,aAAa,EAAE,MAAM,SAAS,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAC3E;AAED,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,oFAAoF;IACpF,QAAQ,CAAC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACtD;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,WAAW,CAAA;IACtC,kFAAkF;IAClF,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAA;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CA0JzE"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { createPromptHistory } from "../agent/prompt-history.js";
|
|
2
|
+
import { ghostSuffix } from "../input/ghost.js";
|
|
3
|
+
import { PromptStash } from "../stash.js";
|
|
4
|
+
import { resetSequence } from "../theme-resolver.js";
|
|
5
|
+
import { TUI_SETTINGS_NAMESPACE } from "../theme-settings.js";
|
|
6
|
+
import { HistoryPicker } from "../ui/history-picker.js";
|
|
7
|
+
import { confirmedClear, StashConfirmPicker, StashPicker } from "../ui/stash-picker.js";
|
|
8
|
+
/** Reverse video for the cell the cursor occupies, so a ghost keeps the cursor visible. */
|
|
9
|
+
const GHOST_CURSOR_PREFIX = '\u001b[7m';
|
|
10
|
+
/**
|
|
11
|
+
* The memory the prompt keeps of what was typed, and what it offers back.
|
|
12
|
+
*
|
|
13
|
+
* Two stores, one subject: the prompt history is global and written from every
|
|
14
|
+
* submitted line, while the stash parks a draft for the session in force. Both
|
|
15
|
+
* are read through the same editor and both answer in a list, so they share the
|
|
16
|
+
* one owner that knows what the reader is looking at.
|
|
17
|
+
*/
|
|
18
|
+
export function createPromptMemory(ports) {
|
|
19
|
+
/**
|
|
20
|
+
* The reader's prompt history: global across projects, recorded from every
|
|
21
|
+
* submitted line, and offered back as they type. Built before the bar exists
|
|
22
|
+
* so its first load cannot race the first suggestion.
|
|
23
|
+
*/
|
|
24
|
+
const promptHistory = createPromptHistory({
|
|
25
|
+
cap: () => ports.historyMaxEntries(),
|
|
26
|
+
warn: message => {
|
|
27
|
+
ports.notice(message);
|
|
28
|
+
ports.render();
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* The dimmed completion drawn from recorded prompts.
|
|
33
|
+
*
|
|
34
|
+
* Colour is the affordance: with styling off the suggestion would be
|
|
35
|
+
* unreadable text the reader could still accept, which is worse than none.
|
|
36
|
+
* The cursor cell is also reversed so the cursor stays visible on the ghost.
|
|
37
|
+
*/
|
|
38
|
+
const ghostBrush = {
|
|
39
|
+
enabled: () => ports.historyEnabled() && ports.historyGhost() && ports.theme.color && ports.theme.visible('editor.ghost'),
|
|
40
|
+
suggestion: input => ghostSuffix({ entries: promptHistory.entries(), ...input }),
|
|
41
|
+
paint: (text, cell) => {
|
|
42
|
+
const styled = ports.theme.style('editor.ghost', text);
|
|
43
|
+
return cell === 'cursor' ? GHOST_CURSOR_PREFIX + styled + resetSequence() : styled;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The bank the surface asked for, as this owner's own reference to it.
|
|
48
|
+
*
|
|
49
|
+
* Late-bound because the surface builds it where a pick can reach a picker:
|
|
50
|
+
* this reference exists before the bank does, and a session opened before
|
|
51
|
+
* then has none to follow.
|
|
52
|
+
*/
|
|
53
|
+
let stash;
|
|
54
|
+
/**
|
|
55
|
+
* Reverse search over recorded prompts, seeded with whatever is in the bar.
|
|
56
|
+
*
|
|
57
|
+
* A pick replaces the draft; a cancel leaves it exactly as it was, because the
|
|
58
|
+
* list was opened to look rather than to lose what is already typed.
|
|
59
|
+
*/
|
|
60
|
+
const openHistoryPicker = async () => {
|
|
61
|
+
if (!ports.historyEnabled()) {
|
|
62
|
+
ports.notice('prompt history is disabled in ' + TUI_SETTINGS_NAMESPACE + ' settings');
|
|
63
|
+
ports.render();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (promptHistory.entries().length === 0) {
|
|
67
|
+
const blocked = promptHistory.blockedReason();
|
|
68
|
+
ports.notice(blocked === undefined ? 'no prompt history yet' : 'prompt history is unavailable: ' + blocked);
|
|
69
|
+
ports.render();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// The expanded text is what the reader wrote; a large paste sits in the bar
|
|
73
|
+
// as a marker, and seeding with it would filter out the prompt it came from.
|
|
74
|
+
const picked = await ports.openPicker(new HistoryPicker(() => promptHistory.entries(), ports.editorText(), () => ports.keymap()));
|
|
75
|
+
if (picked === undefined)
|
|
76
|
+
return;
|
|
77
|
+
ports.setEditorText(picked);
|
|
78
|
+
ports.render();
|
|
79
|
+
};
|
|
80
|
+
/** Show where history is kept, or forget it; the file is global to this machine. */
|
|
81
|
+
const runHistoryCommand = (argument) => {
|
|
82
|
+
// The line that asked for this is recorded before the command runs, but that
|
|
83
|
+
// write rides the store's queue; waiting for it lets the count describe the
|
|
84
|
+
// file the reader has, not the state before their own line landed.
|
|
85
|
+
void promptHistory.flush().then(() => {
|
|
86
|
+
if (argument === '') {
|
|
87
|
+
const count = promptHistory.entries().length;
|
|
88
|
+
const blocked = promptHistory.blockedReason();
|
|
89
|
+
ports.notice([
|
|
90
|
+
count + (count === 1 ? ' prompt recorded' : ' prompts recorded'),
|
|
91
|
+
promptHistory.path(),
|
|
92
|
+
blocked === undefined ? undefined : 'writes disabled: ' + blocked,
|
|
93
|
+
].filter(part => part !== undefined).join(' · '));
|
|
94
|
+
ports.render();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (argument !== 'clear') {
|
|
98
|
+
ports.notice('usage: /history shows where history is kept · /history clear forgets every prompt');
|
|
99
|
+
ports.render();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// A refused write cannot remove anything, so saying "forgot 0 prompts"
|
|
103
|
+
// would describe a successful clear the file never had.
|
|
104
|
+
const blocked = promptHistory.blockedReason();
|
|
105
|
+
if (blocked !== undefined) {
|
|
106
|
+
ports.notice('prompt history is unavailable: ' + blocked);
|
|
107
|
+
ports.render();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
return promptHistory.clear().then(removed => {
|
|
111
|
+
ports.notice('forgot ' + removed + (removed === 1 ? ' prompt' : ' prompts'));
|
|
112
|
+
ports.render();
|
|
113
|
+
});
|
|
114
|
+
}).catch(error => {
|
|
115
|
+
// The store keeps what the file still holds, so the reader is told the
|
|
116
|
+
// clear failed rather than being shown a count that never landed.
|
|
117
|
+
ports.notice('could not clear prompt history: ' + (error instanceof Error ? error.message : String(error)));
|
|
118
|
+
ports.render();
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* The prompt bank for the session this surface drives.
|
|
123
|
+
*
|
|
124
|
+
* The surface owns the editor, the picker, and the notices, so the bank is
|
|
125
|
+
* handed the few things it needs to reach them and nothing else: the commands
|
|
126
|
+
* stay free of terminal state and are exercised without one in the tests.
|
|
127
|
+
*/
|
|
128
|
+
const buildStash = () => {
|
|
129
|
+
stash = new PromptStash({
|
|
130
|
+
getEditorText: () => ports.editorText(),
|
|
131
|
+
setEditorText: text => ports.setEditorText(text),
|
|
132
|
+
editorIsAvailable: () => ports.editorAvailable(),
|
|
133
|
+
notice: message => ports.notice(message),
|
|
134
|
+
pick: (entries, label) => ports.openPicker(new StashPicker(entries, label, () => ports.keymap())),
|
|
135
|
+
confirm: async (count) => confirmedClear(await ports.openPicker(new StashConfirmPicker(count, () => ports.keymap()))),
|
|
136
|
+
render: () => ports.render(),
|
|
137
|
+
},
|
|
138
|
+
// The bank follows the session this surface drives, not the directory it
|
|
139
|
+
// runs in: two terminals in one checkout keep separate drafts, and a resume
|
|
140
|
+
// finds the ones it parked. Read per command so a switch retargets it.
|
|
141
|
+
{ sessionId: () => String(ports.activeSession()) });
|
|
142
|
+
return stash;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Follow the session the surface has just opened.
|
|
146
|
+
*
|
|
147
|
+
* The bank follows the session, so the footer stops counting the drafts of
|
|
148
|
+
* the session just left and the next command reads this session's file.
|
|
149
|
+
*/
|
|
150
|
+
const sessionOpened = () => {
|
|
151
|
+
void stash?.open();
|
|
152
|
+
};
|
|
153
|
+
/** Record a submitted line, when the reader has recording on at all. */
|
|
154
|
+
const record = (text) => {
|
|
155
|
+
if (ports.historyEnabled())
|
|
156
|
+
promptHistory.record(text);
|
|
157
|
+
};
|
|
158
|
+
return {
|
|
159
|
+
ghostBrush,
|
|
160
|
+
openHistoryPicker,
|
|
161
|
+
record,
|
|
162
|
+
runHistoryCommand,
|
|
163
|
+
buildStash,
|
|
164
|
+
sessionOpened,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=prompt-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-memory.js","sourceRoot":"","sources":["../../src/surface/prompt-memory.ts"],"names":[],"mappings":"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"}
|