@namzu/cli 34.1.0 → 35.0.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/CHANGELOG.md +58 -0
- package/README.md +21 -7
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +179 -6
- package/dist/commands/mcp.js.map +1 -1
- package/dist/doctor/checks/credentials.d.ts.map +1 -1
- package/dist/doctor/checks/credentials.js +19 -4
- package/dist/doctor/checks/credentials.js.map +1 -1
- package/dist/integrations/mcp/servers.d.ts.map +1 -1
- package/dist/integrations/mcp/servers.js +107 -15
- package/dist/integrations/mcp/servers.js.map +1 -1
- package/dist/integrations/providers/harness-credentials.d.ts +2 -0
- package/dist/integrations/providers/harness-credentials.d.ts.map +1 -1
- package/dist/integrations/providers/harness-credentials.js +8 -5
- package/dist/integrations/providers/harness-credentials.js.map +1 -1
- package/dist/integrations/providers/setup.d.ts.map +1 -1
- package/dist/integrations/providers/setup.js +3 -1
- package/dist/integrations/providers/setup.js.map +1 -1
- package/dist/integrations/resident/session-step.d.ts.map +1 -1
- package/dist/integrations/resident/session-step.js +13 -8
- package/dist/integrations/resident/session-step.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +385 -95
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/BackgroundJobsPanel.d.ts +26 -0
- package/dist/tui/BackgroundJobsPanel.d.ts.map +1 -0
- package/dist/tui/BackgroundJobsPanel.js +129 -0
- package/dist/tui/BackgroundJobsPanel.js.map +1 -0
- package/dist/tui/Composer.d.ts +7 -2
- package/dist/tui/Composer.d.ts.map +1 -1
- package/dist/tui/Composer.js +65 -34
- package/dist/tui/Composer.js.map +1 -1
- package/dist/tui/PendingInputPanel.d.ts +34 -0
- package/dist/tui/PendingInputPanel.d.ts.map +1 -0
- package/dist/tui/PendingInputPanel.js +108 -0
- package/dist/tui/PendingInputPanel.js.map +1 -0
- package/dist/tui/agent.d.ts +10 -3
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +78 -12
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/slashCommands.d.ts +5 -1
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +9 -8
- package/dist/tui/slashCommands.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BackgroundJob, BackgroundJobOutput } from '@namzu/sdk';
|
|
2
|
+
export interface BackgroundJobsPanelProps {
|
|
3
|
+
readonly jobs: readonly BackgroundJob[];
|
|
4
|
+
/** The highlighted row in the list. An ended job remains selectable. */
|
|
5
|
+
readonly selectedJobId: string | null;
|
|
6
|
+
/** Null shows the list; an id shows that job's details and retained output. */
|
|
7
|
+
readonly detailJobId: string | null;
|
|
8
|
+
/** Physical output rows to stay above the live tail. Zero follows new output. */
|
|
9
|
+
readonly tailOffset: number;
|
|
10
|
+
/** Bound to the current session by the host. Reading must never start a job. */
|
|
11
|
+
readonly readJob: (id: string) => BackgroundJobOutput | undefined;
|
|
12
|
+
readonly rows: number;
|
|
13
|
+
readonly columns: number;
|
|
14
|
+
readonly now?: number;
|
|
15
|
+
readonly busyJobId?: string | null;
|
|
16
|
+
readonly notice?: string | null;
|
|
17
|
+
}
|
|
18
|
+
/** A list row per job, with room left for the composer and its footer. */
|
|
19
|
+
export declare function backgroundJobsPageSize(rows: number): number;
|
|
20
|
+
/** Detail output grows on taller terminals, while retaining the surrounding UI. */
|
|
21
|
+
export declare function backgroundJobOutputPageSize(rows: number): number;
|
|
22
|
+
/** The exact physical lines the output pager uses; App uses the same count for keys. */
|
|
23
|
+
export declare function backgroundJobOutputRows(output: BackgroundJobOutput | undefined, columns: number): readonly string[];
|
|
24
|
+
export declare function maxBackgroundJobTailOffset(output: BackgroundJobOutput | undefined, rows: number, columns: number): number;
|
|
25
|
+
export declare function BackgroundJobsPanel({ jobs, selectedJobId, detailJobId, tailOffset, readJob, rows, columns, now, busyJobId, notice, }: BackgroundJobsPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
//# sourceMappingURL=BackgroundJobsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackgroundJobsPanel.d.ts","sourceRoot":"","sources":["../../src/tui/BackgroundJobsPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAWpE,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAA;IACvC,wEAAwE;IACxE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,mBAAmB,GAAG,SAAS,CAAA;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,mFAAmF;AACnF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhE;AAgBD,wFAAwF;AACxF,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,OAAO,EAAE,MAAM,GACb,SAAS,MAAM,EAAE,CAgBnB;AAED,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACb,MAAM,CAER;AAuBD,wBAAgB,mBAAmB,CAAC,EACnC,IAAI,EACJ,aAAa,EACb,WAAW,EACX,UAAU,EACV,OAAO,EACP,IAAI,EACJ,OAAO,EACP,GAAgB,EAChB,SAAgB,EAChB,MAAa,GACb,EAAE,wBAAwB,2CAmH1B"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { permissionReviewRows } from './permission-review.js';
|
|
4
|
+
import { terminalDisplayText } from './terminal-display.js';
|
|
5
|
+
import { choiceDisplayWidth, truncateChoiceText } from './terminal-choice-text.js';
|
|
6
|
+
import { theme } from './theme.js';
|
|
7
|
+
/** Keep a live log readable without projecting a whole retained 1 MiB on every repaint. */
|
|
8
|
+
const MAX_VISIBLE_OUTPUT_BYTES = 32 * 1024;
|
|
9
|
+
/** A list row per job, with room left for the composer and its footer. */
|
|
10
|
+
export function backgroundJobsPageSize(rows) {
|
|
11
|
+
return Math.max(1, Math.min(8, Math.floor(rows) - 11));
|
|
12
|
+
}
|
|
13
|
+
/** Detail output grows on taller terminals, while retaining the surrounding UI. */
|
|
14
|
+
export function backgroundJobOutputPageSize(rows) {
|
|
15
|
+
return Math.max(1, Math.min(18, Math.floor(rows) - 16));
|
|
16
|
+
}
|
|
17
|
+
function elapsed(job, now) {
|
|
18
|
+
const seconds = Math.max(0, Math.floor(((job.exitedAt ?? now) - job.startedAt) / 1000));
|
|
19
|
+
if (seconds < 60)
|
|
20
|
+
return `${seconds}s`;
|
|
21
|
+
const minutes = Math.floor(seconds / 60);
|
|
22
|
+
if (minutes < 60)
|
|
23
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
24
|
+
return `${Math.floor(minutes / 60)}h ${minutes % 60}m`;
|
|
25
|
+
}
|
|
26
|
+
function jobState(job, now) {
|
|
27
|
+
if (job.status === 'running')
|
|
28
|
+
return `running · ${elapsed(job, now)}`;
|
|
29
|
+
if (job.status === 'killed')
|
|
30
|
+
return `stopped · ${elapsed(job, now)}`;
|
|
31
|
+
return `exited ${job.exitCode ?? '?'} · ${elapsed(job, now)}`;
|
|
32
|
+
}
|
|
33
|
+
/** The exact physical lines the output pager uses; App uses the same count for keys. */
|
|
34
|
+
export function backgroundJobOutputRows(output, columns) {
|
|
35
|
+
if (!output)
|
|
36
|
+
return ['Output unavailable.'];
|
|
37
|
+
const bytes = Buffer.from(output.chunk, 'utf8');
|
|
38
|
+
const omittedHere = Math.max(0, bytes.length - MAX_VISIBLE_OUTPUT_BYTES);
|
|
39
|
+
const latest = bytes.subarray(omittedHere).toString('utf8').replace(/\n$/u, '');
|
|
40
|
+
const lines = [
|
|
41
|
+
...(output.droppedBytes > 0
|
|
42
|
+
? [`Earlier output discarded by the job buffer (${output.droppedBytes} bytes).`]
|
|
43
|
+
: []),
|
|
44
|
+
...(omittedHere > 0 ? [`Showing the latest ${MAX_VISIBLE_OUTPUT_BYTES} bytes.`] : []),
|
|
45
|
+
latest.length > 0 ? latest : 'No output yet.',
|
|
46
|
+
];
|
|
47
|
+
// This wrapper preserves shell spacing and splits long lines before Ink can
|
|
48
|
+
// wrap them below the panel's row budget. It also makes terminal controls
|
|
49
|
+
// visible instead of letting process output move the cursor.
|
|
50
|
+
return permissionReviewRows(lines.join('\n').replace(/\t/gu, ' '), columns).map((row) => row.text);
|
|
51
|
+
}
|
|
52
|
+
export function maxBackgroundJobTailOffset(output, rows, columns) {
|
|
53
|
+
return Math.max(0, backgroundJobOutputRows(output, columns).length - backgroundJobOutputPageSize(rows));
|
|
54
|
+
}
|
|
55
|
+
function readOutput(readJob, id) {
|
|
56
|
+
try {
|
|
57
|
+
return readJob(id);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// A session can close between a status snapshot and a render. The host
|
|
61
|
+
// still owns the error and the panel stays navigable.
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Keep the exit key readable when a narrow terminal cannot carry every hint. */
|
|
66
|
+
function fitClosingHint(candidates, columns) {
|
|
67
|
+
for (const candidate of candidates) {
|
|
68
|
+
if (choiceDisplayWidth(candidate) <= columns)
|
|
69
|
+
return candidate;
|
|
70
|
+
}
|
|
71
|
+
return truncateChoiceText(candidates.at(-1) ?? 'esc', columns);
|
|
72
|
+
}
|
|
73
|
+
export function BackgroundJobsPanel({ jobs, selectedJobId, detailJobId, tailOffset, readJob, rows, columns, now = Date.now(), busyJobId = null, notice = null, }) {
|
|
74
|
+
const running = jobs.filter((job) => job.status === 'running').length;
|
|
75
|
+
const selected = jobs.find((job) => job.id === selectedJobId) ?? jobs[0];
|
|
76
|
+
const detailed = detailJobId ? jobs.find((job) => job.id === detailJobId) : undefined;
|
|
77
|
+
const innerColumns = Math.max(1, columns - 6);
|
|
78
|
+
const narrow = columns < 56;
|
|
79
|
+
if (!detailJobId || !detailed) {
|
|
80
|
+
const pageSize = backgroundJobsPageSize(rows);
|
|
81
|
+
const selectedIndex = selected ? jobs.findIndex((job) => job.id === selected.id) : 0;
|
|
82
|
+
const start = Math.max(0, Math.min(selectedIndex - Math.floor(pageSize / 2), jobs.length - pageSize));
|
|
83
|
+
const shown = jobs.slice(start, start + pageSize);
|
|
84
|
+
const stop = selected?.status === 'running' && !busyJobId ? ' · x stop' : '';
|
|
85
|
+
const listHint = jobs.length === 0
|
|
86
|
+
? 'esc close'
|
|
87
|
+
: fitClosingHint([
|
|
88
|
+
`↑↓ select · enter details${stop} · esc close`,
|
|
89
|
+
`↑↓ move · enter${stop} · esc`,
|
|
90
|
+
`enter${stop} · esc`,
|
|
91
|
+
`${stop ? 'x stop · ' : ''}esc`,
|
|
92
|
+
'esc',
|
|
93
|
+
], innerColumns);
|
|
94
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.border.default, paddingX: 1, children: [_jsx(Text, { bold: true, color: theme.accent.system, wrap: "truncate-end", children: truncateChoiceText(`Shell jobs · ${running} running`, innerColumns) }), jobs.length === 0 ? (_jsx(Text, { color: theme.text.secondary, children: "No shell jobs in this session." })) : (shown.map((job) => {
|
|
95
|
+
const focused = job.id === selected?.id;
|
|
96
|
+
const label = narrow
|
|
97
|
+
? `${focused ? '>' : ' '} ${job.id} · ${job.status} · ${job.command}`
|
|
98
|
+
: `${focused ? '>' : ' '} ${job.id} · ${jobState(job, now)} · ${job.command}`;
|
|
99
|
+
return (_jsx(Text, { color: focused ? theme.accent.user : theme.text.secondary, wrap: "truncate-end", children: truncateChoiceText(label, innerColumns) }, job.id));
|
|
100
|
+
})), jobs.length > pageSize ? (_jsx(Text, { color: theme.text.muted, wrap: "truncate-end", children: `${start + 1}–${Math.min(start + pageSize, jobs.length)}/${jobs.length}` })) : null, notice ? _jsx(Text, { color: theme.status.warn, wrap: "truncate-end", children: truncateChoiceText(notice, innerColumns) }) : null, _jsx(Text, { color: theme.text.muted, wrap: "truncate-end", children: listHint })] }));
|
|
101
|
+
}
|
|
102
|
+
const output = readOutput(readJob, detailed.id);
|
|
103
|
+
const outputRows = backgroundJobOutputRows(output, columns);
|
|
104
|
+
const pageSize = backgroundJobOutputPageSize(rows);
|
|
105
|
+
const maxOffset = Math.max(0, outputRows.length - pageSize);
|
|
106
|
+
const offset = Math.max(0, Math.min(tailOffset, maxOffset));
|
|
107
|
+
const end = outputRows.length - offset;
|
|
108
|
+
const start = Math.max(0, end - pageSize);
|
|
109
|
+
const allCommandRows = permissionReviewRows(terminalDisplayText(detailed.command).replace(/\t/gu, ' '), columns);
|
|
110
|
+
const commandRows = allCommandRows.slice(0, 2);
|
|
111
|
+
const commandMore = allCommandRows.length > 2;
|
|
112
|
+
const shownOutput = outputRows.map((text, index) => ({ index, text })).slice(start, end);
|
|
113
|
+
const canStop = detailed.status === 'running' && !busyJobId;
|
|
114
|
+
const earlierOutputOmitted = (output?.droppedBytes ?? 0) > 0 ||
|
|
115
|
+
(output?.chunk !== undefined && Buffer.byteLength(output.chunk) > MAX_VISIBLE_OUTPUT_BYTES);
|
|
116
|
+
const pageLabel = `${start + 1}–${end}/${outputRows.length}`;
|
|
117
|
+
const stopHint = canStop ? ' · x stop' : '';
|
|
118
|
+
const footer = fitClosingHint([
|
|
119
|
+
`${pageLabel} · ↑↓ scroll · PgUp/PgDn · g/G${stopHint} · esc jobs · q close`,
|
|
120
|
+
`${pageLabel} · ↑↓ scroll${stopHint} · esc jobs`,
|
|
121
|
+
`↑↓ scroll${stopHint} · esc jobs`,
|
|
122
|
+
`↑↓${stopHint} · esc jobs`,
|
|
123
|
+
`${canStop ? 'x stop · ' : ''}esc jobs`,
|
|
124
|
+
'esc jobs',
|
|
125
|
+
'esc',
|
|
126
|
+
], innerColumns);
|
|
127
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.border.focus, paddingX: 1, children: [_jsx(Text, { bold: true, color: theme.accent.system, wrap: "truncate-end", children: truncateChoiceText(`Shell details · ${detailed.id}`, innerColumns) }), _jsx(Text, { color: detailed.status === 'running' ? theme.status.ok : theme.text.secondary, wrap: "truncate-end", children: truncateChoiceText(busyJobId === detailed.id ? 'Stopping…' : jobState(detailed, now), innerColumns) }), _jsx(Text, { color: theme.text.muted, children: "Command" }), commandRows.map((row) => (_jsx(Text, { color: theme.text.primary, wrap: "truncate-end", children: row.text || ' ' }, row.index))), commandMore ? _jsx(Text, { color: theme.text.muted, children: "\u2026 command continues" }) : null, _jsx(Text, { color: theme.text.muted, wrap: "truncate-end", children: truncateChoiceText(earlierOutputOmitted ? 'Output · earlier bytes omitted' : 'Output', innerColumns) }), shownOutput.map((row) => (_jsx(Text, { color: theme.text.secondary, wrap: "truncate-end", children: row.text || ' ' }, row.index))), notice ? _jsx(Text, { color: theme.status.warn, wrap: "truncate-end", children: truncateChoiceText(notice, innerColumns) }) : null, _jsx(Text, { color: theme.text.muted, wrap: "truncate-end", children: footer })] }));
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=BackgroundJobsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackgroundJobsPanel.js","sourceRoot":"","sources":["../../src/tui/BackgroundJobsPanel.tsx"],"names":[],"mappings":"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"}
|
package/dist/tui/Composer.d.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* autocomplete dropdown is open), Tab completes that command or queues the
|
|
7
7
|
* draft, Esc clears / closes the dropdown, ↑/↓ navigate the dropdown when open
|
|
8
8
|
* else browse history, Ctrl+R/Ctrl+S search history, Ctrl+W rubs out a word,
|
|
9
|
-
* Ctrl+G edits the draft in VISUAL/EDITOR,
|
|
9
|
+
* Ctrl+G edits the draft in VISUAL/EDITOR, Alt+Up recalls the latest queued
|
|
10
|
+
* message into an empty composer, Backspace deletes, Alt+W drops or
|
|
10
11
|
* arms the composer trigger nearest the cursor (`./triggers/`).
|
|
11
12
|
*/
|
|
12
13
|
import type { MessageAttachment } from '@namzu/sdk';
|
|
@@ -78,6 +79,8 @@ export interface ComposerProps {
|
|
|
78
79
|
* is the host's answer to give, not a value this key press can hold.
|
|
79
80
|
*/
|
|
80
81
|
readonly onOpenAgentPanel?: () => void;
|
|
82
|
+
/** Recall the latest operator-authored next-turn message into an empty draft. */
|
|
83
|
+
readonly onRecallQueued?: () => Omit<ComposerDraft, 'token'> | null;
|
|
81
84
|
/** Shift+Tab. Absent means the key does nothing, which the composer footer then does not advertise. */
|
|
82
85
|
readonly onCycleMode?: () => void;
|
|
83
86
|
/**
|
|
@@ -143,6 +146,8 @@ export interface ComposerDraft {
|
|
|
143
146
|
readonly token: number;
|
|
144
147
|
readonly text: string;
|
|
145
148
|
readonly attachments?: readonly MessageAttachment[];
|
|
149
|
+
/** Keep a queued message's explicit trigger decisions when it is recalled. */
|
|
150
|
+
readonly triggers?: readonly TriggerId[];
|
|
146
151
|
}
|
|
147
152
|
/**
|
|
148
153
|
* Visible rows in a completion menu for this terminal height.
|
|
@@ -162,5 +167,5 @@ export declare function suggestionWindowSize(rows: number | undefined): number;
|
|
|
162
167
|
* operators already bring to this key.
|
|
163
168
|
*/
|
|
164
169
|
export declare function deletePreviousWord(source: string): string;
|
|
165
|
-
export declare function Composer({ disabled, reasoningEffortLevels, onSubmit, history, userCommands, builtins, mentionCandidates, hidden, escapeInterrupts, onNotice, onStepReasoningEffort, onExternalEdit, onEditPrevious, draftToRestore, onDraftRestored, onDraftPresenceChange, onOpenAgentPanel, onCycleMode, triggers, turnActive, }: ComposerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
170
|
+
export declare function Composer({ disabled, reasoningEffortLevels, onSubmit, history, userCommands, builtins, mentionCandidates, hidden, escapeInterrupts, onNotice, onStepReasoningEffort, onExternalEdit, onEditPrevious, draftToRestore, onDraftRestored, onDraftPresenceChange, onOpenAgentPanel, onRecallQueued, onCycleMode, triggers, turnActive, }: ComposerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
166
171
|
//# sourceMappingURL=Composer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Composer.d.ts","sourceRoot":"","sources":["../../src/tui/Composer.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"Composer.d.ts","sourceRoot":"","sources":["../../src/tui/Composer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAKnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAG5D,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,oBAAoB,CAAA;AAI1E,OAAO,EAGN,KAAK,cAAc,EAGnB,MAAM,sBAAsB,CAAA;AAW7B,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExE,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClD,QAAQ,CAAC,QAAQ,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,EACrD,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,UAAU,KACZ,IAAI,CAAA;IACT,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;IAC9C,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC3C,sEAAsE;IACtE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;OAQG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,KAAK,IAAI,CAAA;IACvE,yEAAyE;IACzE,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IACpC,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IAC9C,+EAA+E;IAC/E,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClD;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC5D;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IACtC,iFAAiF;IACjF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACnE,uGAAuG;IACvG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAC3C,kGAAkG;IAClG,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;IAClC,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,kGAAkG;IAClG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,mGAAmG;IACnG,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,wFAAwF;AACxF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEnD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GACrB,UAAU,GACV,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,GACf,YAAY,CAAA;AAEf;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GACnB;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAA;IAC1C;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC7B,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;CAAE,CAAA;AAEzD,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACnD,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;CACxC;AA4FD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAMrE;AA8HD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD;AAmDD,wBAAgB,QAAQ,CAAC,EACxB,QAAgB,EAChB,qBAAqB,EACrB,QAAQ,EACR,OAAO,EACP,YAAiB,EACjB,QAAQ,EACR,iBAAsB,EACtB,MAAc,EACd,gBAAwB,EACxB,QAAQ,EACR,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,cAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,QAAQ,EACR,UAAkB,GAClB,EAAE,aAAa,kDA22Bf"}
|
package/dist/tui/Composer.js
CHANGED
|
@@ -232,7 +232,7 @@ function deleteNextWordAt(source, cursor) {
|
|
|
232
232
|
const end = nextWordBoundary(source, cursor);
|
|
233
233
|
return { value: source.slice(0, cursor) + source.slice(end), cursor };
|
|
234
234
|
}
|
|
235
|
-
export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, history, userCommands = [], builtins, mentionCandidates = [], hidden = false, escapeInterrupts = false, onNotice, onStepReasoningEffort, onExternalEdit, onEditPrevious, draftToRestore = null, onDraftRestored, onDraftPresenceChange, onOpenAgentPanel, onCycleMode, triggers, turnActive = false, }) {
|
|
235
|
+
export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, history, userCommands = [], builtins, mentionCandidates = [], hidden = false, escapeInterrupts = false, onNotice, onStepReasoningEffort, onExternalEdit, onEditPrevious, draftToRestore = null, onDraftRestored, onDraftPresenceChange, onOpenAgentPanel, onRecallQueued, onCycleMode, triggers, turnActive = false, }) {
|
|
236
236
|
const terminal = useWindowSize();
|
|
237
237
|
const [value, setValueState] = useState('');
|
|
238
238
|
const valueRef = useRef('');
|
|
@@ -256,9 +256,21 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
256
256
|
// Large pastes are held as attachments (shown as chips) instead of being
|
|
257
257
|
// dumped into the input, then folded into the message on submit.
|
|
258
258
|
const [pastes, setPastes] = useState([]);
|
|
259
|
+
const pastesRef = useRef([]);
|
|
260
|
+
const replacePastes = useCallback((next) => {
|
|
261
|
+
const resolved = typeof next === 'function' ? next(pastesRef.current) : next;
|
|
262
|
+
pastesRef.current = resolved;
|
|
263
|
+
setPastes(resolved);
|
|
264
|
+
}, []);
|
|
259
265
|
// Pasted images and restored durable attachments, shown as chips and sent
|
|
260
266
|
// back in the exact SDK union on submit.
|
|
261
267
|
const [attachments, setAttachments] = useState([]);
|
|
268
|
+
const attachmentsRef = useRef([]);
|
|
269
|
+
const replaceAttachments = useCallback((next) => {
|
|
270
|
+
const resolved = typeof next === 'function' ? next(attachmentsRef.current) : next;
|
|
271
|
+
attachmentsRef.current = resolved;
|
|
272
|
+
setAttachments(resolved);
|
|
273
|
+
}, []);
|
|
262
274
|
const [editPreviousArmed, setEditPreviousArmed] = useState(false);
|
|
263
275
|
const restoredTokenRef = useRef(null);
|
|
264
276
|
const draftPresenceRef = useRef(false);
|
|
@@ -366,32 +378,40 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
366
378
|
setBuffer('', 0, 'typed');
|
|
367
379
|
setHistoryIndex(-1);
|
|
368
380
|
setSelectedIndex(0);
|
|
369
|
-
|
|
370
|
-
|
|
381
|
+
replacePastes([]);
|
|
382
|
+
replaceAttachments([]);
|
|
371
383
|
setEditPreviousArmed(false);
|
|
372
|
-
}, [setBuffer, setHistoryIndex, setHistorySearch, setSelectedIndex]);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
384
|
+
}, [replaceAttachments, replacePastes, setBuffer, setHistoryIndex, setHistorySearch, setSelectedIndex]);
|
|
385
|
+
/** Restore synchronously when Alt+Up is pressed, before the next typed key. */
|
|
386
|
+
const restoreDraft = useCallback((draft) => {
|
|
387
|
+
setBuffer(draft.text, draft.text.length, 'restored');
|
|
388
|
+
if (triggers && draft.triggers?.length) {
|
|
389
|
+
const selected = new Set(draft.triggers);
|
|
390
|
+
const hits = detectTriggers(draft.text, triggers.registry, triggers.context, {
|
|
391
|
+
nonTyped: spansRef.current,
|
|
392
|
+
suggest: true,
|
|
393
|
+
}).hits;
|
|
394
|
+
overridesRef.current = hits
|
|
395
|
+
.filter((hit) => selected.has(hit.id))
|
|
396
|
+
.map((hit) => ({ id: hit.id, start: hit.start, end: hit.end, state: 'armed' }));
|
|
397
|
+
setTriggerVersion((version) => version + 1);
|
|
398
|
+
}
|
|
378
399
|
setHistoryIndex(-1);
|
|
379
400
|
setSelectedIndex(0);
|
|
380
401
|
verticalColumnRef.current = null;
|
|
381
402
|
historyDraftRef.current = null;
|
|
382
403
|
setHistorySearch(null);
|
|
383
|
-
|
|
384
|
-
|
|
404
|
+
replacePastes([]);
|
|
405
|
+
replaceAttachments(draft.attachments ? [...draft.attachments] : []);
|
|
385
406
|
setEditPreviousArmed(false);
|
|
407
|
+
}, [replaceAttachments, replacePastes, setBuffer, setHistoryIndex, setHistorySearch, setSelectedIndex, triggers]);
|
|
408
|
+
useEffect(() => {
|
|
409
|
+
if (!draftToRestore || restoredTokenRef.current === draftToRestore.token)
|
|
410
|
+
return;
|
|
411
|
+
restoredTokenRef.current = draftToRestore.token;
|
|
412
|
+
restoreDraft(draftToRestore);
|
|
386
413
|
onDraftRestored?.(draftToRestore.token);
|
|
387
|
-
}, [
|
|
388
|
-
draftToRestore,
|
|
389
|
-
onDraftRestored,
|
|
390
|
-
setBuffer,
|
|
391
|
-
setHistoryIndex,
|
|
392
|
-
setHistorySearch,
|
|
393
|
-
setSelectedIndex,
|
|
394
|
-
]);
|
|
414
|
+
}, [draftToRestore, onDraftRestored, restoreDraft]);
|
|
395
415
|
// Bracketed paste is one event even when the terminal splits its bytes.
|
|
396
416
|
// Its newlines are content, never Enter/shortcut events.
|
|
397
417
|
usePaste((text) => {
|
|
@@ -401,7 +421,7 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
401
421
|
if (normalized.length === 0)
|
|
402
422
|
return;
|
|
403
423
|
if (normalized.includes('\n') || normalized.length > PASTE_THRESHOLD) {
|
|
404
|
-
|
|
424
|
+
replacePastes((previous) => [...previous, normalized]);
|
|
405
425
|
return;
|
|
406
426
|
}
|
|
407
427
|
const position = cursorRef.current;
|
|
@@ -448,6 +468,16 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
448
468
|
}
|
|
449
469
|
return false;
|
|
450
470
|
};
|
|
471
|
+
if (key.meta && key.upArrow && onRecallQueued) {
|
|
472
|
+
if (valueRef.current.length > 0 || pastesRef.current.length > 0 || attachmentsRef.current.length > 0) {
|
|
473
|
+
onNotice?.('Send or clear the current draft before recalling a queued message.');
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const recalled = onRecallQueued();
|
|
477
|
+
if (recalled)
|
|
478
|
+
restoreDraft(recalled);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
451
481
|
if (!hasLiveSuggestions &&
|
|
452
482
|
onStepReasoningEffort &&
|
|
453
483
|
((key.shift && key.downArrow) || (key.meta && input === ','))) {
|
|
@@ -463,13 +493,14 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
463
493
|
if (!key.escape && editPreviousArmed)
|
|
464
494
|
setEditPreviousArmed(false);
|
|
465
495
|
const submit = (mode) => {
|
|
466
|
-
const message = [valueRef.current, ...
|
|
496
|
+
const message = [valueRef.current, ...pastesRef.current]
|
|
467
497
|
.map((s) => s.trim())
|
|
468
498
|
.filter(Boolean)
|
|
469
499
|
.join('\n\n');
|
|
470
|
-
|
|
500
|
+
const currentAttachments = attachmentsRef.current;
|
|
501
|
+
if (message.length === 0 && currentAttachments.length === 0)
|
|
471
502
|
return false;
|
|
472
|
-
const submittedAttachments =
|
|
503
|
+
const submittedAttachments = currentAttachments.length > 0 ? currentAttachments : undefined;
|
|
473
504
|
// Read again from what the last key left, not from the last render.
|
|
474
505
|
const detection = detect(valueRef.current);
|
|
475
506
|
// The message is the draft trimmed: offsets move by what the trim took.
|
|
@@ -480,7 +511,7 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
480
511
|
onSubmit(message, submittedAttachments, mode, {
|
|
481
512
|
source: 'composer',
|
|
482
513
|
triggers: armed,
|
|
483
|
-
onlyTriggers: armed.length > 0 && detection.onlyTriggers &&
|
|
514
|
+
onlyTriggers: armed.length > 0 && detection.onlyTriggers && pastesRef.current.length === 0 && currentAttachments.length === 0,
|
|
484
515
|
});
|
|
485
516
|
reset();
|
|
486
517
|
return true;
|
|
@@ -561,7 +592,7 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
561
592
|
setHistorySearch(null);
|
|
562
593
|
return;
|
|
563
594
|
}
|
|
564
|
-
const empty = valueRef.current.length === 0 &&
|
|
595
|
+
const empty = valueRef.current.length === 0 && pastesRef.current.length === 0 && attachmentsRef.current.length === 0;
|
|
565
596
|
if (empty && onEditPrevious) {
|
|
566
597
|
if (editPreviousArmed) {
|
|
567
598
|
setEditPreviousArmed(false);
|
|
@@ -587,12 +618,12 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
587
618
|
if (key.backspace) {
|
|
588
619
|
// Backspace on an empty line removes the last durable attachment first,
|
|
589
620
|
// then pasted text.
|
|
590
|
-
if (valueRef.current.length === 0 &&
|
|
591
|
-
|
|
621
|
+
if (valueRef.current.length === 0 && attachmentsRef.current.length > 0) {
|
|
622
|
+
replaceAttachments((p) => p.slice(0, -1));
|
|
592
623
|
return;
|
|
593
624
|
}
|
|
594
|
-
if (valueRef.current.length === 0 &&
|
|
595
|
-
|
|
625
|
+
if (valueRef.current.length === 0 && pastesRef.current.length > 0) {
|
|
626
|
+
replacePastes((p) => p.slice(0, -1));
|
|
596
627
|
return;
|
|
597
628
|
}
|
|
598
629
|
const position = cursorRef.current;
|
|
@@ -707,7 +738,7 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
707
738
|
}
|
|
708
739
|
verticalColumnRef.current = null;
|
|
709
740
|
if (historyIndexRef.current < 0) {
|
|
710
|
-
if (valueRef.current.length === 0 &&
|
|
741
|
+
if (valueRef.current.length === 0 && pastesRef.current.length === 0 && attachmentsRef.current.length === 0) {
|
|
711
742
|
onOpenAgentPanel?.();
|
|
712
743
|
}
|
|
713
744
|
return;
|
|
@@ -729,14 +760,14 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
729
760
|
onNotice?.('External editor support is unavailable in this terminal.');
|
|
730
761
|
return;
|
|
731
762
|
}
|
|
732
|
-
const seed = [valueRef.current, ...
|
|
763
|
+
const seed = [valueRef.current, ...pastesRef.current]
|
|
733
764
|
.map((part) => part.trim())
|
|
734
765
|
.filter(Boolean)
|
|
735
766
|
.join('\n\n');
|
|
736
767
|
void onExternalEdit(seed)
|
|
737
768
|
.then((edited) => {
|
|
738
769
|
const cleaned = edited.trimEnd();
|
|
739
|
-
|
|
770
|
+
replacePastes([]);
|
|
740
771
|
setHistoryIndex(-1);
|
|
741
772
|
setHistorySearch(null);
|
|
742
773
|
setSelectedIndex(0);
|
|
@@ -758,7 +789,7 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
758
789
|
if ((key.ctrl || key.meta) && input === 'v') {
|
|
759
790
|
const read = readClipboardImage();
|
|
760
791
|
if (read.kind === 'image') {
|
|
761
|
-
|
|
792
|
+
replaceAttachments((p) => [...p, read.image]);
|
|
762
793
|
}
|
|
763
794
|
else if (read.kind === 'empty') {
|
|
764
795
|
onNotice?.('No image on the clipboard. Copy one, then press Ctrl+V.');
|
|
@@ -831,7 +862,7 @@ export function Composer({ disabled = false, reasoningEffortLevels, onSubmit, hi
|
|
|
831
862
|
// the model received. A real paste reaches `usePaste` above, where a
|
|
832
863
|
// long one is still a chip.
|
|
833
864
|
if (input.includes('\n')) {
|
|
834
|
-
|
|
865
|
+
replacePastes((p) => [...p, input]);
|
|
835
866
|
return;
|
|
836
867
|
}
|
|
837
868
|
setSelectedIndex(0);
|