moderado 0.4.46 → 0.4.50
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/dist/commands/chat.js +2 -2
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/chat_slash.d.ts +1 -1
- package/dist/commands/chat_slash.d.ts.map +1 -1
- package/dist/commands/chat_slash.js +1 -0
- package/dist/commands/chat_slash.js.map +1 -1
- package/dist/ui/composer.d.ts.map +1 -1
- package/dist/ui/composer.js +165 -44
- package/dist/ui/composer.js.map +1 -1
- package/dist/ui/help_content.d.ts +1 -1
- package/dist/ui/help_content.js +1 -1
- package/dist/ui/help_content.js.map +1 -1
- package/dist/ui/welcome.d.ts +57 -7
- package/dist/ui/welcome.d.ts.map +1 -1
- package/dist/ui/welcome.js +174 -22
- package/dist/ui/welcome.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/welcome.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface WelcomeLayoutOptions {
|
|
|
12
12
|
input?: string;
|
|
13
13
|
inputCaret?: number;
|
|
14
14
|
width?: number;
|
|
15
|
+
/** Input rows the composer may paint before it scrolls; defaults to the terminal height. */
|
|
16
|
+
maxInputRows?: number;
|
|
15
17
|
/** When set, render the full chat window (question row 1 + answer) instead of the logo header. */
|
|
16
18
|
chatQuestion?: string;
|
|
17
19
|
chatAnswer?: string;
|
|
@@ -50,10 +52,55 @@ export declare function stripAnsi(str: string): string;
|
|
|
50
52
|
export declare const MOUSE_REPORT_PATTERN: RegExp;
|
|
51
53
|
export declare const MOUSE_REPORT_ON = "\u001B[?1000h\u001B[?1006h";
|
|
52
54
|
export declare const MOUSE_REPORT_OFF = "\u001B[?1000l\u001B[?1006l";
|
|
53
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Ask the terminal to report keys whose legacy encoding is ambiguous
|
|
57
|
+
* (XTMODKEYS level 1), which is the only way Shift+Enter can be told apart from
|
|
58
|
+
* Enter. Level 1 leaves unambiguous keys — plain Ctrl+C, Shift+Tab, shifted
|
|
59
|
+
* letters — on their legacy bytes, so nothing else changes behaviour.
|
|
60
|
+
*/
|
|
61
|
+
export declare const KEY_MODIFIER_REPORT_ON = "\u001B[>4;1m";
|
|
62
|
+
export declare const KEY_MODIFIER_REPORT_OFF = "\u001B[>4;0m";
|
|
63
|
+
/**
|
|
64
|
+
* One visual row of the composer input, as a slice of the raw text. Keeping the
|
|
65
|
+
* offsets means the caret, a click, and a repaint all address the same string
|
|
66
|
+
* instead of a re-flowed copy of it.
|
|
67
|
+
*/
|
|
68
|
+
export interface ComposerRow {
|
|
54
69
|
text: string;
|
|
70
|
+
/** Index in the raw input where the row starts. */
|
|
71
|
+
start: number;
|
|
72
|
+
/** Index where the row ends (exclusive). */
|
|
73
|
+
end: number;
|
|
74
|
+
}
|
|
75
|
+
/** Split the composer text into the rows the card paints, wrapping at words. */
|
|
76
|
+
export declare function wrapComposerInput(input: string, width: number): ComposerRow[];
|
|
77
|
+
export interface ComposerView {
|
|
78
|
+
/** Rows to paint, already windowed to the rows the terminal can spare. */
|
|
79
|
+
rows: ComposerRow[];
|
|
80
|
+
/** Row index of the caret inside `rows`. */
|
|
81
|
+
caretRow: number;
|
|
82
|
+
/** Cell offset of the caret inside its row, 0 being the first text cell. */
|
|
55
83
|
caretColumn: number;
|
|
56
|
-
|
|
84
|
+
/** Rows scrolled out of view above and below the window. */
|
|
85
|
+
hiddenAbove: number;
|
|
86
|
+
hiddenBelow: number;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve the composer text into painted rows plus the caret's place in them.
|
|
90
|
+
* The window follows the caret, so a long prompt scrolls inside the box instead
|
|
91
|
+
* of growing the card past the bottom of the terminal.
|
|
92
|
+
*/
|
|
93
|
+
export declare function composerView(input: string, caret: number, width: number, maxRows?: number): ComposerView;
|
|
94
|
+
/** Caret index for a click `cells` into a painted row. */
|
|
95
|
+
export declare function composerCaretIndex(input: string, rows: ComposerRow[], rowOffset: number, cells: number): number;
|
|
96
|
+
/**
|
|
97
|
+
* Input rows the composer may show before it scrolls in place.
|
|
98
|
+
*
|
|
99
|
+
* The chat frame needs eight rows above the card (header, question, status,
|
|
100
|
+
* answer) and the card keeps four rows of its own furniture, so anything taller
|
|
101
|
+
* than this would scroll the composer off the screen.
|
|
102
|
+
*/
|
|
103
|
+
export declare function getComposerInputMaxRows(height?: number): number;
|
|
57
104
|
/** Card width: nearly full terminal width, like OpenCode/Cline. */
|
|
58
105
|
export declare function getWelcomeCardWidth(width?: number): number;
|
|
59
106
|
/** Chat fills the available columns; the startup Welcome card keeps its own width. */
|
|
@@ -148,11 +195,12 @@ export declare function wrapText(text: string, maxWidth: number): string[];
|
|
|
148
195
|
*/
|
|
149
196
|
export declare function renderChatScreen(options: WelcomeLayoutOptions, height?: number): string;
|
|
150
197
|
/**
|
|
151
|
-
* Place the terminal cursor on the
|
|
152
|
-
* `composerTop` addresses the row absolutely, which stays correct
|
|
153
|
-
* queued-commands box
|
|
198
|
+
* Place the terminal cursor on the caret's row inside the input box. Passing
|
|
199
|
+
* the layout's `composerTop` addresses the row absolutely, which stays correct
|
|
200
|
+
* when the card grows (a queued-commands box or a wrapped prompt); the relative
|
|
201
|
+
* form is the legacy path.
|
|
154
202
|
*/
|
|
155
|
-
export declare function renderChatComposerCursor(options: Pick<WelcomeLayoutOptions, 'width'>,
|
|
203
|
+
export declare function renderChatComposerCursor(options: Pick<WelcomeLayoutOptions, 'width'>, input: string, composerTop?: number): string;
|
|
156
204
|
export declare function navigateQuestionHistory(history: string[], direction: -1 | 1, index: number, draft: string): {
|
|
157
205
|
input: string;
|
|
158
206
|
index: number;
|
|
@@ -315,7 +363,9 @@ export declare function getWelcomeBottomPadding(options: WelcomeLayoutOptions, h
|
|
|
315
363
|
export declare function renderCenteredWelcomeScreen(options: WelcomeLayoutOptions, height?: number): string;
|
|
316
364
|
/** Compose an OpenCode-style popup layer without losing the welcome background. */
|
|
317
365
|
export declare function renderWelcomePopupLayer(options: WelcomeLayoutOptions, popupLines: string[], width?: number, height?: number): string;
|
|
318
|
-
export declare function renderHelpPopupBox(
|
|
366
|
+
export declare function renderHelpPopupBox(_version: string, workspace: string, width?: number): string[];
|
|
367
|
+
/** Render a centered "About" popup with version and copyright info. */
|
|
368
|
+
export declare function renderAboutPopupBox(version: string): string[];
|
|
319
369
|
export declare let terminalCleanExitDone: boolean;
|
|
320
370
|
/** Mark that a clean exit already restored + cleared the terminal (guards the process 'exit' hook). */
|
|
321
371
|
export declare function notifyCleanExit(): void;
|
package/dist/ui/welcome.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/ui/welcome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAQ1E,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kGAAkG;IAClG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,mBAAmB,UAM/B,CAAC;AAEF,eAAO,MAAM,YAAY,yIACmG,CAAC;AAE7H,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAOD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,QAAoC,CAAC;AACtE,eAAO,MAAM,eAAe,+BAA2B,CAAC;AACxD,eAAO,MAAM,gBAAgB,+BAA2B,CAAC;AAEzD,
|
|
1
|
+
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/ui/welcome.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/welcome.js
CHANGED
|
@@ -7,7 +7,7 @@ import { overlayCentered, dimLines, shadowUnder } from './popup.js';
|
|
|
7
7
|
import { getHelpCommandGroups } from './help_content.js';
|
|
8
8
|
export const MODERADO_ASCII_LOGO = [
|
|
9
9
|
'\x1b[38;5;75m __ _______ ____ __________ ___ ____ ____ \x1b[0m',
|
|
10
|
-
'\x1b[38;5;75m / |/ / __ \\/ __ \\/ ____/ __ \\/ | / __ \\/ __
|
|
10
|
+
'\x1b[38;5;75m / |/ / __ \\/ __ \\/ ____/ __ \\/ | / __ \\/ __ \x1b[0m',
|
|
11
11
|
'\x1b[38;5;81m / /|_/ / / / / / / / __/ / /_/ / /| | / / / / / / /\x1b[0m',
|
|
12
12
|
'\x1b[38;5;81m / / / / /_/ / /_/ / /___/ _, _/ ___ |/ /_/ / /_/ / \x1b[0m',
|
|
13
13
|
'\x1b[38;5;87m/_/ /_/\\____/_____/_____/_/ |_/_/ |_/_____/\\____/ \x1b[0m',
|
|
@@ -31,10 +31,125 @@ function visibleLen(str) {
|
|
|
31
31
|
export const MOUSE_REPORT_PATTERN = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
|
32
32
|
export const MOUSE_REPORT_ON = '\x1b[?1000h\x1b[?1006h';
|
|
33
33
|
export const MOUSE_REPORT_OFF = '\x1b[?1000l\x1b[?1006l';
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Ask the terminal to report keys whose legacy encoding is ambiguous
|
|
36
|
+
* (XTMODKEYS level 1), which is the only way Shift+Enter can be told apart from
|
|
37
|
+
* Enter. Level 1 leaves unambiguous keys — plain Ctrl+C, Shift+Tab, shifted
|
|
38
|
+
* letters — on their legacy bytes, so nothing else changes behaviour.
|
|
39
|
+
*/
|
|
40
|
+
export const KEY_MODIFIER_REPORT_ON = '\x1b[>4;1m';
|
|
41
|
+
export const KEY_MODIFIER_REPORT_OFF = '\x1b[>4;0m';
|
|
42
|
+
/**
|
|
43
|
+
* Cells a composer row spends on its `❯ ` marker, plus one spare so a full row
|
|
44
|
+
* never reaches the last column (a terminal that wraps on the final cell would
|
|
45
|
+
* push the whole card down a row).
|
|
46
|
+
*/
|
|
47
|
+
const COMPOSER_ROW_OVERHEAD = 3;
|
|
48
|
+
/** Split the composer text into the rows the card paints, wrapping at words. */
|
|
49
|
+
export function wrapComposerInput(input, width) {
|
|
50
|
+
const capacity = Math.max(1, width - COMPOSER_ROW_OVERHEAD);
|
|
51
|
+
const rows = [];
|
|
52
|
+
let segmentStart = 0;
|
|
53
|
+
for (;;) {
|
|
54
|
+
const newline = input.indexOf('\n', segmentStart);
|
|
55
|
+
const segmentEnd = newline === -1 ? input.length : newline;
|
|
56
|
+
if (segmentStart === segmentEnd) {
|
|
57
|
+
// An empty line (a bare line feed, or the tail after a trailing one) is
|
|
58
|
+
// still a row: the caret has to have somewhere to sit.
|
|
59
|
+
rows.push({ text: '', start: segmentStart, end: segmentStart });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
let cursor = segmentStart;
|
|
63
|
+
while (cursor < segmentEnd) {
|
|
64
|
+
let end = cursor;
|
|
65
|
+
let cells = 0;
|
|
66
|
+
let lastSpace = -1;
|
|
67
|
+
while (end < segmentEnd) {
|
|
68
|
+
const char = String.fromCodePoint(input.codePointAt(end));
|
|
69
|
+
const charWidth = displayWidth(char);
|
|
70
|
+
if (cells + charWidth > capacity)
|
|
71
|
+
break;
|
|
72
|
+
cells += charWidth;
|
|
73
|
+
end += char.length;
|
|
74
|
+
if (char === ' ')
|
|
75
|
+
lastSpace = end;
|
|
76
|
+
}
|
|
77
|
+
if (end >= segmentEnd) {
|
|
78
|
+
rows.push({ text: input.slice(cursor, segmentEnd), start: cursor, end: segmentEnd });
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
// Break after the last space so words stay whole; the space itself is
|
|
82
|
+
// swallowed by the break rather than trailing the row. A row that would
|
|
83
|
+
// come out empty (a space at the wrap point) falls through to a hard
|
|
84
|
+
// break instead of emitting a blank row.
|
|
85
|
+
if (lastSpace - 1 > cursor) {
|
|
86
|
+
rows.push({ text: input.slice(cursor, lastSpace - 1), start: cursor, end: lastSpace - 1 });
|
|
87
|
+
cursor = lastSpace;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
rows.push({ text: input.slice(cursor, end), start: cursor, end });
|
|
91
|
+
cursor = end;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (newline === -1)
|
|
96
|
+
return rows;
|
|
97
|
+
segmentStart = newline + 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolve the composer text into painted rows plus the caret's place in them.
|
|
102
|
+
* The window follows the caret, so a long prompt scrolls inside the box instead
|
|
103
|
+
* of growing the card past the bottom of the terminal.
|
|
104
|
+
*/
|
|
105
|
+
export function composerView(input, caret, width, maxRows = Number.POSITIVE_INFINITY) {
|
|
106
|
+
const all = wrapComposerInput(input, width);
|
|
107
|
+
const clampedCaret = Math.max(0, Math.min(caret, input.length));
|
|
108
|
+
// The last row whose slice contains the caret: at a hard wrap the caret
|
|
109
|
+
// belongs to the row that starts there, at a swallowed space to the row that
|
|
110
|
+
// ends there.
|
|
111
|
+
let caretRow = 0;
|
|
112
|
+
for (let index = 0; index < all.length; index += 1) {
|
|
113
|
+
if (all[index].start <= clampedCaret && clampedCaret <= all[index].end)
|
|
114
|
+
caretRow = index;
|
|
115
|
+
}
|
|
116
|
+
const limit = Math.max(1, Math.floor(maxRows));
|
|
117
|
+
const start = Math.max(0, Math.min(caretRow - limit + 1, all.length - limit));
|
|
118
|
+
const rows = all.slice(start, start + limit);
|
|
119
|
+
const row = all[caretRow];
|
|
120
|
+
return {
|
|
121
|
+
rows,
|
|
122
|
+
caretRow: caretRow - start,
|
|
123
|
+
caretColumn: Math.min(Math.max(1, width - COMPOSER_ROW_OVERHEAD), displayWidth(input.slice(row.start, clampedCaret))),
|
|
124
|
+
hiddenAbove: start,
|
|
125
|
+
hiddenBelow: all.length - start - rows.length,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Caret index for a click `cells` into a painted row. */
|
|
129
|
+
export function composerCaretIndex(input, rows, rowOffset, cells) {
|
|
130
|
+
const row = rows[Math.max(0, Math.min(rows.length - 1, rowOffset))];
|
|
131
|
+
let index = row.start;
|
|
132
|
+
let used = 0;
|
|
133
|
+
while (index < row.end) {
|
|
134
|
+
const char = String.fromCodePoint(input.codePointAt(index));
|
|
135
|
+
const charWidth = displayWidth(char);
|
|
136
|
+
if (used + charWidth > cells)
|
|
137
|
+
break;
|
|
138
|
+
used += charWidth;
|
|
139
|
+
index += char.length;
|
|
140
|
+
}
|
|
141
|
+
return index;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Input rows the composer may show before it scrolls in place.
|
|
145
|
+
*
|
|
146
|
+
* The chat frame needs eight rows above the card (header, question, status,
|
|
147
|
+
* answer) and the card keeps four rows of its own furniture, so anything taller
|
|
148
|
+
* than this would scroll the composer off the screen.
|
|
149
|
+
*/
|
|
150
|
+
export function getComposerInputMaxRows(height) {
|
|
151
|
+
const terminalHeight = height ?? process.stdout.rows ?? 24;
|
|
152
|
+
return Math.max(1, terminalHeight - 13);
|
|
38
153
|
}
|
|
39
154
|
/** Card width: nearly full terminal width, like OpenCode/Cline. */
|
|
40
155
|
export function getWelcomeCardWidth(width) {
|
|
@@ -249,11 +364,14 @@ export function renderWelcomeCard(options) {
|
|
|
249
364
|
? getWelcomeCardWidth(options.width)
|
|
250
365
|
: getChatCardWidth(options.width);
|
|
251
366
|
const indent = ' '.repeat(getWelcomeIndent(width, options.width));
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
367
|
+
const inputText = options.input ?? '';
|
|
368
|
+
const inputView = composerView(inputText, options.inputCaret ?? inputText.length, width, options.maxInputRows ?? getComposerInputMaxRows());
|
|
369
|
+
// The placeholder owns the first row only; a typed prompt is wrapped into as
|
|
370
|
+
// many rows as it needs, so the box grows instead of scrolling sideways.
|
|
371
|
+
const inputRows = inputText.length > 0
|
|
372
|
+
? inputView.rows.map((row) => row.text)
|
|
373
|
+
: ['\x1b[38;5;242mAsk anything, I am all ears...\x1b[0m'];
|
|
255
374
|
const promptMarker = '\x1b[1;38;5;75m' + String.fromCodePoint(0x276F) + '\x1b[0;48;5;236m';
|
|
256
|
-
const textBox = `${promptMarker} ${displayInput}`;
|
|
257
375
|
const surface = '\x1b[48;5;236m';
|
|
258
376
|
const surfaceLine = (content = '') => {
|
|
259
377
|
const preserved = content.replace(/\x1b\[0m/g, '\x1b[0;48;5;236m');
|
|
@@ -341,7 +459,10 @@ export function renderWelcomeCard(options) {
|
|
|
341
459
|
if (matching.length)
|
|
342
460
|
cardLines.push(...renderSuggestionsBox(matching, width, options.commandSelection ?? 0).map(line => indent + line));
|
|
343
461
|
}
|
|
344
|
-
cardLines.push(indent + surfaceLine(),
|
|
462
|
+
cardLines.push(indent + surfaceLine(),
|
|
463
|
+
// Continuation rows keep the marker's two cells, so wrapped text lines up
|
|
464
|
+
// under the first row's text instead of under the ❯.
|
|
465
|
+
...inputRows.map((rowText, index) => indent + surfaceLine(`${index === 0 ? promptMarker : ' '} ${rowText}`)), indent + surfaceLine(), indent + line4, indent + line5);
|
|
345
466
|
if (options.mentionFiles && options.mentionFiles.length > 0) {
|
|
346
467
|
cardLines.push(...renderMentionSuggestionsBox(options.mentionFiles, options.mentionSelection ?? 0, width).map((line) => indent + line));
|
|
347
468
|
}
|
|
@@ -361,7 +482,8 @@ export const SLASH_COMMANDS = [
|
|
|
361
482
|
{ name: '/budget', desc: 'Set a per-task token limit' },
|
|
362
483
|
{ name: '/skills', desc: 'List skills; enable or disable user skills' },
|
|
363
484
|
{ name: '/clear', desc: 'Reset conversation memory' },
|
|
364
|
-
{ name: '/
|
|
485
|
+
{ name: '/about', desc: 'Show version and copyright info' },
|
|
486
|
+
{ name: '/help', desc: 'Display commands & shortcuts' },
|
|
365
487
|
{ name: '/exit', desc: 'Exit Moderado' },
|
|
366
488
|
];
|
|
367
489
|
export function getMatchingCommands(input) {
|
|
@@ -517,7 +639,10 @@ export function renderChatScreen(options, height) {
|
|
|
517
639
|
// The composer is measured before the layout: a queued-commands box or a
|
|
518
640
|
// mention box makes the card taller, and the answer area must give up those
|
|
519
641
|
// rows instead of pushing the card past the bottom of the viewport.
|
|
520
|
-
const
|
|
642
|
+
const cardOptions = options.maxInputRows === undefined
|
|
643
|
+
? { ...options, maxInputRows: getComposerInputMaxRows(terminalHeight) }
|
|
644
|
+
: options;
|
|
645
|
+
const composer = renderWelcomeCard(cardOptions).split('\n');
|
|
521
646
|
const layout = getChatLayout(terminalWidth, terminalHeight, question, composer.length);
|
|
522
647
|
const area = layout.area;
|
|
523
648
|
const indent = ' '.repeat(area.indent);
|
|
@@ -594,17 +719,19 @@ export function renderChatScreen(options, height) {
|
|
|
594
719
|
return lines.join('\n') + '\n';
|
|
595
720
|
}
|
|
596
721
|
/**
|
|
597
|
-
* Place the terminal cursor on the
|
|
598
|
-
* `composerTop` addresses the row absolutely, which stays correct
|
|
599
|
-
* queued-commands box
|
|
722
|
+
* Place the terminal cursor on the caret's row inside the input box. Passing
|
|
723
|
+
* the layout's `composerTop` addresses the row absolutely, which stays correct
|
|
724
|
+
* when the card grows (a queued-commands box or a wrapped prompt); the relative
|
|
725
|
+
* form is the legacy path.
|
|
600
726
|
*/
|
|
601
|
-
export function renderChatComposerCursor(options,
|
|
727
|
+
export function renderChatComposerCursor(options, input, composerTop) {
|
|
602
728
|
const width = getChatCardWidth(options.width);
|
|
603
729
|
const indent = getWelcomeIndent(width, options.width);
|
|
604
|
-
const
|
|
730
|
+
const view = composerView(input, input.length, width, getComposerInputMaxRows());
|
|
731
|
+
const caretColumn = indent + 2 + view.caretColumn;
|
|
605
732
|
if (composerTop !== undefined)
|
|
606
|
-
return `\x1b[1 q\x1b[?25h\x1b[${composerTop + 1};${caretColumn}H`;
|
|
607
|
-
return `\x1b[1 q\x1b[?25h\x1b[
|
|
733
|
+
return `\x1b[1 q\x1b[?25h\x1b[${composerTop + 1 + view.caretRow};${caretColumn + 1}H`;
|
|
734
|
+
return `\x1b[1 q\x1b[?25h\x1b[${4 + view.caretRow}A\r\x1b[${caretColumn}C`;
|
|
608
735
|
}
|
|
609
736
|
export function navigateQuestionHistory(history, direction, index, draft) {
|
|
610
737
|
const nextIndex = Math.max(0, Math.min(history.length, index + direction));
|
|
@@ -934,7 +1061,7 @@ export function renderWelcomePopupLayer(options, popupLines, width, height) {
|
|
|
934
1061
|
const lightPopup = popupLines.map((line) => surface + line.replace(/\x1b\[0m/g, `\x1b[0m${surface}`) + '\x1b[0m');
|
|
935
1062
|
return background + shadowUnder(lightPopup, cols, rows) + overlayCentered(lightPopup, cols, rows);
|
|
936
1063
|
}
|
|
937
|
-
export function renderHelpPopupBox(
|
|
1064
|
+
export function renderHelpPopupBox(_version, workspace, width) {
|
|
938
1065
|
const terminalWidth = width ?? (process.stdout.columns || 80);
|
|
939
1066
|
const targetWidth = 82;
|
|
940
1067
|
const boxWidth = Math.max(76, Math.min(terminalWidth, targetWidth));
|
|
@@ -952,6 +1079,7 @@ export function renderHelpPopupBox(version, workspace, width) {
|
|
|
952
1079
|
'\x1b[1;38;5;114mKeyboard Shortcuts:\x1b[0m',
|
|
953
1080
|
'\x1b[1mTab\x1b[0m Toggle between [Plan] and [Execute] mode',
|
|
954
1081
|
'\x1b[1mShift+Tab\x1b[0m Toggle Auto-approval on / off for actions',
|
|
1082
|
+
'\x1b[1mShift+Enter\x1b[0m Insert a line break (Ctrl+J works everywhere)',
|
|
955
1083
|
'\x1b[1mCtrl+C\x1b[0m Cancel active inference or exit session',
|
|
956
1084
|
'\x1b[1mEsc\x1b[0m Stop the active task',
|
|
957
1085
|
'\x1b[1mLeft/Right\x1b[0m Move the caret inside the bottom input line',
|
|
@@ -959,7 +1087,6 @@ export function renderHelpPopupBox(version, workspace, width) {
|
|
|
959
1087
|
'\x1b[1mMouse click\x1b[0m Place the caret on the input line',
|
|
960
1088
|
'',
|
|
961
1089
|
`\x1b[38;5;245mWorkspace:\x1b[0m \x1b[38;5;253m${shortWs}\x1b[0m`,
|
|
962
|
-
`\x1b[38;5;245mVersion:\x1b[0m \x1b[1;38;5;75m${version}\x1b[0m`,
|
|
963
1090
|
'',
|
|
964
1091
|
'\x1b[38;5;244mPress \x1b[1;38;5;75m[Esc]\x1b[0;38;5;244m or \x1b[1;38;5;75m[Enter]\x1b[0;38;5;244m to close\x1b[0m',
|
|
965
1092
|
];
|
|
@@ -978,6 +1105,31 @@ export function renderHelpPopupBox(version, workspace, width) {
|
|
|
978
1105
|
lines.push('\x1b[38;5;240m╰' + '─'.repeat(boxWidth - 2) + '╯\x1b[0m');
|
|
979
1106
|
return lines;
|
|
980
1107
|
}
|
|
1108
|
+
/** Render a centered "About" popup with version and copyright info. */
|
|
1109
|
+
export function renderAboutPopupBox(version) {
|
|
1110
|
+
const boxWidth = 52;
|
|
1111
|
+
const innerW = boxWidth - 4;
|
|
1112
|
+
const titleStr = 'About Moderado';
|
|
1113
|
+
const remainingDashes = Math.max(0, boxWidth - titleStr.length - 5);
|
|
1114
|
+
// Strip the Alfazen build suffix (`+261024h`) so only `v<major.minor.patch>` shows.
|
|
1115
|
+
const semverOnly = version.split('+')[0];
|
|
1116
|
+
const content = [
|
|
1117
|
+
'Moderado CLI',
|
|
1118
|
+
semverOnly,
|
|
1119
|
+
'',
|
|
1120
|
+
'(c) 2026 Moderado AI, an Alfazen Product',
|
|
1121
|
+
];
|
|
1122
|
+
const lines = [];
|
|
1123
|
+
lines.push('\x1b[38;5;240m╭─ \x1b[1;38;5;75m' + titleStr + '\x1b[0;38;5;240m ' + '─'.repeat(remainingDashes) + '╮\x1b[0m');
|
|
1124
|
+
for (const item of content) {
|
|
1125
|
+
const plain = item.replace(/\x1b\\[[0-9;]*[a-zA-Z]/g, '');
|
|
1126
|
+
const leftPad = Math.max(0, Math.floor((innerW - plain.length) / 2));
|
|
1127
|
+
const rightPad = Math.max(0, innerW - plain.length - leftPad);
|
|
1128
|
+
lines.push('\x1b[38;5;240m│\x1b[0m' + ' '.repeat(leftPad) + item + ' '.repeat(rightPad) + '\x1b[38;5;240m│\x1b[0m');
|
|
1129
|
+
}
|
|
1130
|
+
lines.push('\x1b[38;5;240m╰' + '─'.repeat(boxWidth - 2) + '╯\x1b[0m');
|
|
1131
|
+
return lines;
|
|
1132
|
+
}
|
|
981
1133
|
export let terminalCleanExitDone = false;
|
|
982
1134
|
/** Mark that a clean exit already restored + cleared the terminal (guards the process 'exit' hook). */
|
|
983
1135
|
export function notifyCleanExit() {
|
|
@@ -1005,7 +1157,7 @@ export async function exitCleanly(message) {
|
|
|
1005
1157
|
notifyCleanExit();
|
|
1006
1158
|
const stdout = process.stdout;
|
|
1007
1159
|
const payload = stdout.isTTY
|
|
1008
|
-
? MOUSE_REPORT_OFF + '\x1b[?25h\x1b[?1049l\x1b[0 q\x1b[0m\x1b[2J\x1b[3J\x1b[H' + renderExitMessage(message)
|
|
1160
|
+
? KEY_MODIFIER_REPORT_OFF + MOUSE_REPORT_OFF + '\x1b[?25h\x1b[?1049l\x1b[0 q\x1b[0m\x1b[2J\x1b[3J\x1b[H' + renderExitMessage(message)
|
|
1009
1161
|
: renderExitMessage(message);
|
|
1010
1162
|
try {
|
|
1011
1163
|
fs.writeSync(1, payload);
|