@compilr-dev/cli 0.5.4 → 0.5.6
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/.tsbuildinfo.app +1 -1
- package/dist/.tsbuildinfo.data +1 -1
- package/dist/.tsbuildinfo.domain +1 -1
- package/dist/.tsbuildinfo.foundation +1 -1
- package/dist/agent.js +225 -16
- package/dist/commands-v2/handlers/project.js +35 -5
- package/dist/commands-v2/handlers/settings.js +13 -7
- package/dist/compilr-diff-companion.vsix +0 -0
- package/dist/multi-agent/capability-loader.d.ts +29 -0
- package/dist/multi-agent/capability-loader.js +54 -0
- package/dist/repl-v2.js +8 -1
- package/dist/settings/index.d.ts +11 -0
- package/dist/settings/index.js +24 -1
- package/dist/tool-names.d.ts +1 -0
- package/dist/tool-names.js +2 -0
- package/dist/tools/meta-tools.d.ts +5 -0
- package/dist/tools/meta-tools.js +11 -0
- package/dist/tools.d.ts +6 -0
- package/dist/tools.js +9 -1
- package/dist/ui/keyboard-handler.d.ts +6 -4
- package/dist/ui/keyboard-handler.js +11 -11
- package/dist/ui/live-region-facade.js +1 -0
- package/dist/ui/overlay/impl/config-overlay-v2.js +6 -5
- package/dist/ui/terminal-render-item.js +25 -3
- package/dist/ui/terminal-types.d.ts +3 -0
- package/dist/ui/terminal-types.js +1 -0
- package/dist/ui/terminal-ui.d.ts +6 -6
- package/dist/ui/terminal-ui.js +38 -24
- package/dist/ui/tool-formatters.js +368 -0
- package/dist/utils/readonly-tools.d.ts +8 -0
- package/dist/utils/readonly-tools.js +29 -0
- package/package.json +3 -3
package/dist/settings/index.js
CHANGED
|
@@ -29,6 +29,7 @@ const DEFAULT_SETTINGS = {
|
|
|
29
29
|
showTips: true, // TODO: Not yet implemented
|
|
30
30
|
reviseCode: true, // TODO: Not yet implemented
|
|
31
31
|
verbose: false,
|
|
32
|
+
verbosity: 'normal',
|
|
32
33
|
progressBar: true,
|
|
33
34
|
// Update defaults
|
|
34
35
|
checkUpdates: true, // Check for updates on startup
|
|
@@ -112,7 +113,16 @@ export function getSettings() {
|
|
|
112
113
|
return settingsCache;
|
|
113
114
|
}
|
|
114
115
|
const stored = loadFromDisk();
|
|
116
|
+
let needsSave = false;
|
|
117
|
+
// Migration: convert verbose boolean to verbosity string (before merge with defaults)
|
|
118
|
+
if (!('verbosity' in stored) && stored.verbose === true) {
|
|
119
|
+
stored.verbosity = 'verbose';
|
|
120
|
+
needsSave = true;
|
|
121
|
+
}
|
|
115
122
|
settingsCache = { ...DEFAULT_SETTINGS, ...stored };
|
|
123
|
+
if (needsSave) {
|
|
124
|
+
saveToDisk(settingsCache);
|
|
125
|
+
}
|
|
116
126
|
// Migration: convert deprecated 'cwd' to 'off'
|
|
117
127
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
128
|
if (settingsCache.projectStartup === 'cwd') {
|
|
@@ -179,7 +189,8 @@ export const getDefaultModel = () => getSetting('defaultModel');
|
|
|
179
189
|
export const isAutoCompactEnabled = () => getSetting('autoCompact');
|
|
180
190
|
export const isShowTipsEnabled = () => getSetting('showTips'); // TODO: Not yet implemented
|
|
181
191
|
export const isReviseCodeEnabled = () => getSetting('reviseCode'); // TODO: Not yet implemented
|
|
182
|
-
export const
|
|
192
|
+
export const getVerbosity = () => getSetting('verbosity');
|
|
193
|
+
export const isVerboseEnabled = () => getVerbosity() === 'verbose';
|
|
183
194
|
export const isProgressBarEnabled = () => getSetting('progressBar');
|
|
184
195
|
export const isTelemetryEnabled = () => getSetting('telemetryEnabled');
|
|
185
196
|
// Update getters
|
|
@@ -378,6 +389,18 @@ export function displayToSessionRetention(display) {
|
|
|
378
389
|
return parseInt(match[1], 10);
|
|
379
390
|
return 30; // Default fallback
|
|
380
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Map internal verbosity to display value
|
|
394
|
+
*/
|
|
395
|
+
export function verbosityToDisplay(v) {
|
|
396
|
+
return v === 'normal' ? 'Normal' : v === 'focused' ? 'Focused' : 'Verbose';
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Map display value to internal verbosity
|
|
400
|
+
*/
|
|
401
|
+
export function displayToVerbosity(d) {
|
|
402
|
+
return d === 'Focused' ? 'focused' : d === 'Verbose' ? 'verbose' : 'normal';
|
|
403
|
+
}
|
|
381
404
|
/**
|
|
382
405
|
* Map internal compact mode to display value
|
|
383
406
|
*/
|
package/dist/tool-names.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export declare const TOOL_NAMES: {
|
|
|
97
97
|
readonly APP_MODEL_VALIDATE: "app_model_validate";
|
|
98
98
|
readonly FACTORY_SCAFFOLD: "factory_scaffold";
|
|
99
99
|
readonly FACTORY_LIST_TOOLKITS: "factory_list_toolkits";
|
|
100
|
+
readonly LOAD_CAPABILITY: "load_capability";
|
|
100
101
|
};
|
|
101
102
|
/** Type for all valid tool names */
|
|
102
103
|
export type ToolName = (typeof TOOL_NAMES)[keyof typeof TOOL_NAMES];
|
package/dist/tool-names.js
CHANGED
|
@@ -118,6 +118,8 @@ export const TOOL_NAMES = {
|
|
|
118
118
|
APP_MODEL_VALIDATE: 'app_model_validate',
|
|
119
119
|
FACTORY_SCAFFOLD: 'factory_scaffold',
|
|
120
120
|
FACTORY_LIST_TOOLKITS: 'factory_list_toolkits',
|
|
121
|
+
// Capability loading
|
|
122
|
+
LOAD_CAPABILITY: 'load_capability',
|
|
121
123
|
};
|
|
122
124
|
/** Array of all direct tool names (always available) */
|
|
123
125
|
export const DIRECT_TOOL_NAMES = [
|
|
@@ -23,4 +23,9 @@ export declare const getToolInfoTool: Tool<object>;
|
|
|
23
23
|
export declare const useToolTool: Tool<object>;
|
|
24
24
|
export declare const metaTools: Tool<object>[];
|
|
25
25
|
export declare function createMetaToolFallback(): (name: string, input: Record<string, unknown>) => Promise<ToolExecutionResult | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Generate a filtered tool index showing only tools in the given set.
|
|
28
|
+
* Sets the registry filter, generates the index, then restores the previous filter.
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateFilteredToolIndex(activeToolNames: string[]): string;
|
|
26
31
|
export declare const META_TOOLS_SYSTEM_PROMPT_PREFIX = "\n## Tool Index (Specialized Tools)\n\nThese tools are called **exactly like direct tools** \u2014 just use the tool name with parameters. No special syntax or wrapper needed. The system routes them automatically.\n\n**IMPORTANT \u2014 These are CLI system tools, NOT your project's backend. Never use localhost/curl to access them.**\n\n**Parameter Rules:**\n- For **zero-parameter calls**: call the tool directly (e.g., `workitem_query()`, `git_status()`).\n- For **calls WITH parameters**: you MUST call `get_tool_info(\"tool_name\")` first to get parameter details. The signatures below are summaries only \u2014 do NOT guess parameter structure from them.\n- After a failed tool call, always call `get_tool_info()` before retrying.\n\n";
|
package/dist/tools/meta-tools.js
CHANGED
|
@@ -44,4 +44,15 @@ export const metaTools = [listToolsTool, getToolInfoTool, useToolTool];
|
|
|
44
44
|
export function createMetaToolFallback() {
|
|
45
45
|
return metaToolSet.createFallback();
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Generate a filtered tool index showing only tools in the given set.
|
|
49
|
+
* Sets the registry filter, generates the index, then restores the previous filter.
|
|
50
|
+
*/
|
|
51
|
+
export function generateFilteredToolIndex(activeToolNames) {
|
|
52
|
+
const previousFilter = registry.getFilter();
|
|
53
|
+
registry.setFilter(activeToolNames);
|
|
54
|
+
const index = registry.generateToolIndex();
|
|
55
|
+
registry.setFilter(previousFilter ? [...previousFilter] : null);
|
|
56
|
+
return index;
|
|
57
|
+
}
|
|
47
58
|
export const META_TOOLS_SYSTEM_PROMPT_PREFIX = SDK_META_TOOLS_SYSTEM_PROMPT_PREFIX;
|
package/dist/tools.d.ts
CHANGED
|
@@ -70,6 +70,12 @@ export declare function initializeMetaTools(includeWarmTools?: boolean): void;
|
|
|
70
70
|
* This lists all meta-registry tools with their signatures.
|
|
71
71
|
*/
|
|
72
72
|
export declare function getToolIndexForSystemPrompt(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Get a filtered tool index for the system prompt.
|
|
75
|
+
* Only includes tools whose names are in the given set.
|
|
76
|
+
* Used by the capability-aware BeforeLLM hook.
|
|
77
|
+
*/
|
|
78
|
+
export declare function getFilteredToolIndexForSystemPrompt(activeToolNames: string[]): string;
|
|
73
79
|
/**
|
|
74
80
|
* Get count of meta-registry tools.
|
|
75
81
|
*/
|
package/dist/tools.js
CHANGED
|
@@ -129,7 +129,7 @@ import { guideTool } from './tools/guide-tool.js';
|
|
|
129
129
|
// DB tools for project, work item, document, plan, backlog, anchor, artifact, and episode management
|
|
130
130
|
import { allDbTools, allFactoryTools } from './tools/db-tools.js';
|
|
131
131
|
// Meta-tools for dynamic tool loading
|
|
132
|
-
import { initializeMetaToolRegistry, generateToolIndex, getMetaToolCount, META_TOOLS_SYSTEM_PROMPT_PREFIX, setMetaToolFilter, getRegisteredMetaTools, createMetaToolFallback, getToolInfoTool, } from './tools/meta-tools.js';
|
|
132
|
+
import { initializeMetaToolRegistry, generateToolIndex, generateFilteredToolIndex, getMetaToolCount, META_TOOLS_SYSTEM_PROMPT_PREFIX, setMetaToolFilter, getRegisteredMetaTools, createMetaToolFallback, getToolInfoTool, } from './tools/meta-tools.js';
|
|
133
133
|
// Re-export for use in agent.ts
|
|
134
134
|
export { setMetaToolFilter, getRegisteredMetaTools };
|
|
135
135
|
/**
|
|
@@ -324,6 +324,14 @@ export function initializeMetaTools(includeWarmTools) {
|
|
|
324
324
|
export function getToolIndexForSystemPrompt() {
|
|
325
325
|
return META_TOOLS_SYSTEM_PROMPT_PREFIX + generateToolIndex();
|
|
326
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Get a filtered tool index for the system prompt.
|
|
329
|
+
* Only includes tools whose names are in the given set.
|
|
330
|
+
* Used by the capability-aware BeforeLLM hook.
|
|
331
|
+
*/
|
|
332
|
+
export function getFilteredToolIndexForSystemPrompt(activeToolNames) {
|
|
333
|
+
return META_TOOLS_SYSTEM_PROMPT_PREFIX + generateFilteredToolIndex(activeToolNames);
|
|
334
|
+
}
|
|
327
335
|
/**
|
|
328
336
|
* Get count of meta-registry tools.
|
|
329
337
|
*/
|
|
@@ -11,11 +11,13 @@ import type { AutocompleteController } from './autocomplete-controller.js';
|
|
|
11
11
|
import type { OverlayManager } from './overlay-manager.js';
|
|
12
12
|
import type { StatusBarController } from './status-bar-controller.js';
|
|
13
13
|
import type { Overlay } from './overlay/index.js';
|
|
14
|
+
import type { Verbosity } from '../settings/index.js';
|
|
14
15
|
export interface KeyboardHandlerHost {
|
|
15
16
|
isGuardActive(): boolean;
|
|
16
17
|
isAgentRunning(): boolean;
|
|
17
|
-
getViewMode(): 'normal' | 'verbose-temp';
|
|
18
|
-
setViewMode(mode: 'normal' | 'verbose-temp'): void;
|
|
18
|
+
getViewMode(): 'normal' | 'focused-temp' | 'verbose-temp';
|
|
19
|
+
setViewMode(mode: 'normal' | 'focused-temp' | 'verbose-temp'): void;
|
|
20
|
+
getPersistedVerbosity(): Verbosity;
|
|
19
21
|
requestRender(): void;
|
|
20
22
|
emit(event: string, ...args: unknown[]): void;
|
|
21
23
|
readonly input: InputController;
|
|
@@ -28,10 +30,10 @@ export interface KeyboardHandlerHost {
|
|
|
28
30
|
backgroundBashCommand(): void;
|
|
29
31
|
hasRestoredHistory(): boolean;
|
|
30
32
|
showRestoredHistory(): void;
|
|
31
|
-
|
|
33
|
+
cycleVerbosityView(): void;
|
|
32
34
|
toggleLiveRegionExpanded(): void;
|
|
33
35
|
toggleTodos(): void;
|
|
34
|
-
|
|
36
|
+
reRenderConversationWithVerbosity(verbosity: Verbosity): void;
|
|
35
37
|
}
|
|
36
38
|
export declare class KeyboardHandler {
|
|
37
39
|
private keyHandler;
|
|
@@ -126,10 +126,10 @@ export class KeyboardHandler {
|
|
|
126
126
|
handleEscape() {
|
|
127
127
|
const host = this.host;
|
|
128
128
|
const { input, ac } = host;
|
|
129
|
-
// In
|
|
130
|
-
if (host.getViewMode()
|
|
129
|
+
// In temp mode, escape returns to persisted verbosity
|
|
130
|
+
if (host.getViewMode() !== 'normal') {
|
|
131
131
|
host.setViewMode('normal');
|
|
132
|
-
host.
|
|
132
|
+
host.reRenderConversationWithVerbosity(host.getPersistedVerbosity());
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
135
|
// Route escape to active overlay if present
|
|
@@ -261,17 +261,17 @@ export class KeyboardHandler {
|
|
|
261
261
|
host.statusBar.handleKey(str, key);
|
|
262
262
|
return;
|
|
263
263
|
}
|
|
264
|
-
// In verbose-temp
|
|
265
|
-
if (host.getViewMode()
|
|
266
|
-
// Ctrl+O
|
|
264
|
+
// In temp mode (focused-temp or verbose-temp), any key (except Ctrl+O) returns to persisted
|
|
265
|
+
if (host.getViewMode() !== 'normal') {
|
|
266
|
+
// Ctrl+O cycles to next temp mode
|
|
267
267
|
if (key.ctrl && key.name === 'o') {
|
|
268
|
-
host.
|
|
268
|
+
host.cycleVerbosityView();
|
|
269
269
|
host.toggleLiveRegionExpanded();
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
|
-
// Any other key returns to
|
|
272
|
+
// Any other key returns to persisted verbosity
|
|
273
273
|
host.setViewMode('normal');
|
|
274
|
-
host.
|
|
274
|
+
host.reRenderConversationWithVerbosity(host.getPersistedVerbosity());
|
|
275
275
|
// Don't consume the key - let it be processed normally
|
|
276
276
|
}
|
|
277
277
|
// Ctrl+C - interrupt/exit
|
|
@@ -284,9 +284,9 @@ export class KeyboardHandler {
|
|
|
284
284
|
host.toggleTodos();
|
|
285
285
|
return;
|
|
286
286
|
}
|
|
287
|
-
// Ctrl+O -
|
|
287
|
+
// Ctrl+O - cycle verbosity view mode AND LiveRegion expansion
|
|
288
288
|
if (key.ctrl && key.name === 'o') {
|
|
289
|
-
host.
|
|
289
|
+
host.cycleVerbosityView();
|
|
290
290
|
host.toggleLiveRegionExpanded();
|
|
291
291
|
return;
|
|
292
292
|
}
|
|
@@ -15,7 +15,7 @@ import * as path from 'path';
|
|
|
15
15
|
import { execSync } from 'child_process';
|
|
16
16
|
import { BaseOverlayV2, isEscape, isTab, isShiftTab, isEnter, isSpace, isCtrlC, isNavigateUp, isNavigateDown, isBackspace, getNumberKey, isPrintable, extractPrintable, renderProgressBar, formatTokens, truncate, } from '../../base/index.js';
|
|
17
17
|
import { getCurrentTheme, } from '../../../themes/index.js';
|
|
18
|
-
import { getSettings, setSetting, permissionModeToDisplay, displayToPermissionMode, notificationModeToDisplay, displayToNotificationMode, projectStartupModeToDisplay, displayToProjectStartupMode, projectSessionModeToDisplay, displayToProjectSessionMode, sessionRetentionToDisplay, displayToSessionRetention, compactModeToDisplay, displayToCompactMode, } from '../../../settings/index.js';
|
|
18
|
+
import { getSettings, setSetting, permissionModeToDisplay, displayToPermissionMode, notificationModeToDisplay, displayToNotificationMode, projectStartupModeToDisplay, displayToProjectStartupMode, projectSessionModeToDisplay, displayToProjectSessionMode, sessionRetentionToDisplay, displayToSessionRetention, compactModeToDisplay, displayToCompactMode, verbosityToDisplay, displayToVerbosity, } from '../../../settings/index.js';
|
|
19
19
|
import { getResolvedPathConfig, setDeleteProtection, setProjectMatchRequired, setWorkspacePath, setProjectsPath, setDataPath, } from '../../../settings/paths.js';
|
|
20
20
|
import { MASCOT_LABELS, } from '../../mascot/index.js';
|
|
21
21
|
import { ThemeOverlayV2 } from './theme-overlay-v2.js';
|
|
@@ -128,7 +128,7 @@ function getConfigItems(currentModel) {
|
|
|
128
128
|
// { id: 'showTips', label: 'Show tips', type: 'boolean', value: settings.showTips },
|
|
129
129
|
// TODO: Implement checkpoints/rewind feature (Claude Code v2.0)
|
|
130
130
|
// { id: 'reviseCode', label: 'Revise code (checkpoints)', type: 'boolean', value: settings.reviseCode },
|
|
131
|
-
{ id: '
|
|
131
|
+
{ id: 'verbosity', label: 'Verbosity', type: 'cycle', value: verbosityToDisplay(settings.verbosity), options: ['Normal', 'Focused', 'Verbose'] },
|
|
132
132
|
{ id: 'progressBar', label: 'Terminal progress bar', type: 'boolean', value: settings.progressBar },
|
|
133
133
|
{
|
|
134
134
|
id: 'permissionMode',
|
|
@@ -623,9 +623,7 @@ export class ConfigOverlayV2 extends BaseOverlayV2 {
|
|
|
623
623
|
case 'autoCompact':
|
|
624
624
|
setSetting('autoCompact', newValue);
|
|
625
625
|
break;
|
|
626
|
-
|
|
627
|
-
setSetting('verbose', newValue);
|
|
628
|
-
break;
|
|
626
|
+
// verbose: removed — now a 'cycle' item as 'verbosity'
|
|
629
627
|
case 'progressBar':
|
|
630
628
|
setSetting('progressBar', newValue);
|
|
631
629
|
break;
|
|
@@ -680,6 +678,9 @@ export class ConfigOverlayV2 extends BaseOverlayV2 {
|
|
|
680
678
|
case 'compactMode':
|
|
681
679
|
setSetting('compactMode', displayToCompactMode(newValue));
|
|
682
680
|
break;
|
|
681
|
+
case 'verbosity':
|
|
682
|
+
setSetting('verbosity', displayToVerbosity(newValue));
|
|
683
|
+
break;
|
|
683
684
|
}
|
|
684
685
|
return null;
|
|
685
686
|
}
|
|
@@ -63,7 +63,7 @@ export function renderItem(item, config) {
|
|
|
63
63
|
}
|
|
64
64
|
case 'thinking':
|
|
65
65
|
// Only show thinking in verbose mode
|
|
66
|
-
if (config.verbose) {
|
|
66
|
+
if (config.verbosity === 'verbose') {
|
|
67
67
|
console.log(s.muted(`∴ Thinking…`));
|
|
68
68
|
console.log('');
|
|
69
69
|
// Indent thinking text
|
|
@@ -76,6 +76,9 @@ export function renderItem(item, config) {
|
|
|
76
76
|
// If not verbose, skip entirely (but still stored in history)
|
|
77
77
|
break;
|
|
78
78
|
case 'tool-start': {
|
|
79
|
+
// In focused mode, spinner already shows tool name — skip scroll output
|
|
80
|
+
if (config.verbosity === 'focused')
|
|
81
|
+
break;
|
|
79
82
|
// Truncate long params (e.g., long bash commands)
|
|
80
83
|
const maxLen = Math.min(60, terminal.getTerminalWidth() - 15);
|
|
81
84
|
let params = item.params;
|
|
@@ -94,6 +97,25 @@ export function renderItem(item, config) {
|
|
|
94
97
|
break;
|
|
95
98
|
}
|
|
96
99
|
case 'tool-result': {
|
|
100
|
+
// === FOCUSED MODE ===
|
|
101
|
+
if (config.verbosity === 'focused') {
|
|
102
|
+
// Errors always visible
|
|
103
|
+
if (item.success === false) {
|
|
104
|
+
console.log(s.info(`● ${item.name}`) + s.error(` — ${item.summary}`));
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
else if (item.readOnly) {
|
|
108
|
+
// Read-only tools: spinner-only, no scroll output
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Write/mutation tools: single summary line
|
|
113
|
+
console.log(s.info(`● ${item.name}`) + s.muted(` — ${item.summary}`));
|
|
114
|
+
console.log('');
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
// === NORMAL & VERBOSE MODES ===
|
|
97
119
|
// Truncate long params (e.g., long bash commands)
|
|
98
120
|
const maxParamsLen = Math.min(60, terminal.getTerminalWidth() - 15);
|
|
99
121
|
let paramsDisplay = item.params;
|
|
@@ -114,7 +136,7 @@ export function renderItem(item, config) {
|
|
|
114
136
|
// Diff lines: render directly (already ANSI-formatted by diff.ts)
|
|
115
137
|
if (item.diffLines && item.diffLines.length > 0) {
|
|
116
138
|
const maxDiffPreview = 10;
|
|
117
|
-
if (config.verbose || item.diffLines.length <= maxDiffPreview) {
|
|
139
|
+
if (config.verbosity === 'verbose' || item.diffLines.length <= maxDiffPreview) {
|
|
118
140
|
for (const line of item.diffLines) {
|
|
119
141
|
console.log(` ${line}`);
|
|
120
142
|
}
|
|
@@ -130,7 +152,7 @@ export function renderItem(item, config) {
|
|
|
130
152
|
else if (item.content) {
|
|
131
153
|
const contentLines = item.content.split('\n').filter((l) => l.length > 0);
|
|
132
154
|
const maxPreviewLines = 3;
|
|
133
|
-
if (config.verbose) {
|
|
155
|
+
if (config.verbosity === 'verbose') {
|
|
134
156
|
// Verbose: show all lines
|
|
135
157
|
for (const line of contentLines) {
|
|
136
158
|
console.log(s.muted(` ⎿ ${line}`));
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { CommandOption } from './types.js';
|
|
8
8
|
import type { FileMatch } from './file-autocomplete.js';
|
|
9
|
+
import type { Verbosity } from '../settings/index.js';
|
|
9
10
|
/**
|
|
10
11
|
* Message to be sent to the agent from a command.
|
|
11
12
|
* Allows commands to invoke the agent with a detailed prompt while
|
|
@@ -39,6 +40,7 @@ export interface TerminalUIEvents {
|
|
|
39
40
|
*/
|
|
40
41
|
export interface TerminalUIConfig {
|
|
41
42
|
verbose: boolean;
|
|
43
|
+
verbosity: Verbosity;
|
|
42
44
|
theme: string;
|
|
43
45
|
showMascot: boolean;
|
|
44
46
|
}
|
|
@@ -121,6 +123,7 @@ export type PrintableItem = {
|
|
|
121
123
|
content?: string;
|
|
122
124
|
diffLines?: string[];
|
|
123
125
|
success?: boolean;
|
|
126
|
+
readOnly?: boolean;
|
|
124
127
|
agentId?: string;
|
|
125
128
|
} | {
|
|
126
129
|
type: 'tool-error';
|
package/dist/ui/terminal-ui.d.ts
CHANGED
|
@@ -224,15 +224,15 @@ export declare class TerminalUI extends EventEmitter {
|
|
|
224
224
|
*/
|
|
225
225
|
getShowTodos(): boolean;
|
|
226
226
|
/**
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
* Any key returns to
|
|
227
|
+
* Cycle verbosity view mode (Ctrl+O)
|
|
228
|
+
* Cycles: normal → focused-temp → verbose-temp → normal
|
|
229
|
+
* Any non-Ctrl+O key returns to persisted verbosity.
|
|
230
230
|
*/
|
|
231
|
-
|
|
231
|
+
cycleVerbosityView(): void;
|
|
232
232
|
/**
|
|
233
|
-
* Re-render conversation with temporary
|
|
233
|
+
* Re-render conversation with temporary verbosity setting.
|
|
234
234
|
*/
|
|
235
|
-
private
|
|
235
|
+
private reRenderConversationWithVerbosity;
|
|
236
236
|
/**
|
|
237
237
|
* Store restored conversation items for Ctrl+R history view.
|
|
238
238
|
* Called when a session is resumed/restored.
|
package/dist/ui/terminal-ui.js
CHANGED
|
@@ -83,9 +83,10 @@ export class TerminalUI extends EventEmitter {
|
|
|
83
83
|
activeTeamAgent = null;
|
|
84
84
|
// Todo visibility (Ctrl+T to toggle)
|
|
85
85
|
showTodos = true;
|
|
86
|
-
// View mode (Ctrl+O to
|
|
87
|
-
// normal:
|
|
88
|
-
//
|
|
86
|
+
// View mode (Ctrl+O to cycle: normal → focused-temp → verbose-temp → normal)
|
|
87
|
+
// normal: use persisted verbosity setting
|
|
88
|
+
// focused-temp: temporarily show focused mode (any key returns to persisted)
|
|
89
|
+
// verbose-temp: temporarily show verbose mode (any key returns to persisted)
|
|
89
90
|
viewMode = 'normal';
|
|
90
91
|
// Status bar navigation (down arrow into footer indicators)
|
|
91
92
|
statusBar = new StatusBarController({
|
|
@@ -104,7 +105,7 @@ export class TerminalUI extends EventEmitter {
|
|
|
104
105
|
isFooterRenderAllowed: () => this.isRunning && !this.isPaused && !this.overlay.hasActiveOverlay(),
|
|
105
106
|
getRenderData: () => ({
|
|
106
107
|
liveRegion: this.live.region,
|
|
107
|
-
liveVerbose: this.config.verbose,
|
|
108
|
+
liveVerbose: this.config.verbosity === 'verbose',
|
|
108
109
|
agentRunning: this.agentRunning,
|
|
109
110
|
currentTool: this.currentTool,
|
|
110
111
|
spinnerText: this.spinnerText,
|
|
@@ -136,6 +137,7 @@ export class TerminalUI extends EventEmitter {
|
|
|
136
137
|
isAgentRunning: () => this.agentRunning,
|
|
137
138
|
getViewMode: () => this.viewMode,
|
|
138
139
|
setViewMode: (mode) => { this.viewMode = mode; },
|
|
140
|
+
getPersistedVerbosity: () => this.config.verbosity,
|
|
139
141
|
requestRender: () => { this.needsRender = true; },
|
|
140
142
|
emit: (event, ...args) => { this.emit(event, ...args); },
|
|
141
143
|
input: this.input,
|
|
@@ -148,10 +150,10 @@ export class TerminalUI extends EventEmitter {
|
|
|
148
150
|
backgroundBashCommand: () => { this.backgroundBashCommand(); },
|
|
149
151
|
hasRestoredHistory: () => this.conversation.hasRestoredHistory(),
|
|
150
152
|
showRestoredHistory: () => { this.showRestoredHistory(); },
|
|
151
|
-
|
|
153
|
+
cycleVerbosityView: () => { this.cycleVerbosityView(); },
|
|
152
154
|
toggleLiveRegionExpanded: () => { this.toggleLiveRegionExpanded(); },
|
|
153
155
|
toggleTodos: () => { this.toggleTodos(); },
|
|
154
|
-
|
|
156
|
+
reRenderConversationWithVerbosity: (verbosity) => { this.reRenderConversationWithVerbosity(verbosity); },
|
|
155
157
|
});
|
|
156
158
|
constructor(options = {}) {
|
|
157
159
|
super();
|
|
@@ -517,42 +519,50 @@ export class TerminalUI extends EventEmitter {
|
|
|
517
519
|
return this.showTodos;
|
|
518
520
|
}
|
|
519
521
|
/**
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
* Any key returns to
|
|
522
|
+
* Cycle verbosity view mode (Ctrl+O)
|
|
523
|
+
* Cycles: normal → focused-temp → verbose-temp → normal
|
|
524
|
+
* Any non-Ctrl+O key returns to persisted verbosity.
|
|
523
525
|
*/
|
|
524
|
-
|
|
526
|
+
cycleVerbosityView() {
|
|
525
527
|
if (this.viewMode === 'normal') {
|
|
528
|
+
this.viewMode = 'focused-temp';
|
|
529
|
+
this.reRenderConversationWithVerbosity('focused');
|
|
530
|
+
}
|
|
531
|
+
else if (this.viewMode === 'focused-temp') {
|
|
526
532
|
this.viewMode = 'verbose-temp';
|
|
527
|
-
this.
|
|
533
|
+
this.reRenderConversationWithVerbosity('verbose');
|
|
528
534
|
}
|
|
529
535
|
else {
|
|
530
536
|
this.viewMode = 'normal';
|
|
531
|
-
this.
|
|
537
|
+
this.reRenderConversationWithVerbosity(this.config.verbosity);
|
|
532
538
|
}
|
|
533
539
|
}
|
|
534
540
|
/**
|
|
535
|
-
* Re-render conversation with temporary
|
|
541
|
+
* Re-render conversation with temporary verbosity setting.
|
|
536
542
|
*/
|
|
537
|
-
|
|
543
|
+
reRenderConversationWithVerbosity(verbosity) {
|
|
538
544
|
const s = getStyles();
|
|
539
545
|
// Clear screen and scrollback buffer
|
|
540
546
|
process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
|
|
541
547
|
// Reset footer state
|
|
542
548
|
this.footer.resetRenderState();
|
|
543
|
-
// Show mode indicator at top
|
|
544
|
-
if (
|
|
545
|
-
console.log(s.info(`[
|
|
549
|
+
// Show mode indicator at top for temp modes
|
|
550
|
+
if (this.viewMode === 'focused-temp') {
|
|
551
|
+
console.log(s.info(`[Focused View] Press any key to return`));
|
|
552
|
+
console.log('');
|
|
553
|
+
}
|
|
554
|
+
else if (this.viewMode === 'verbose-temp') {
|
|
555
|
+
console.log(s.info(`[Verbose View] Press any key to return`));
|
|
546
556
|
console.log('');
|
|
547
557
|
}
|
|
548
|
-
// Re-render all items with temporary
|
|
549
|
-
const
|
|
550
|
-
this.config.
|
|
558
|
+
// Re-render all items with temporary verbosity override
|
|
559
|
+
const originalVerbosity = this.config.verbosity;
|
|
560
|
+
this.config.verbosity = verbosity;
|
|
551
561
|
for (const item of this.conversation.history) {
|
|
552
562
|
this.renderItemToConsole(item);
|
|
553
563
|
}
|
|
554
564
|
// Restore original config
|
|
555
|
-
this.config.
|
|
565
|
+
this.config.verbosity = originalVerbosity;
|
|
556
566
|
// Footer will be re-rendered by the render loop
|
|
557
567
|
this.needsRender = true;
|
|
558
568
|
}
|
|
@@ -604,10 +614,14 @@ export class TerminalUI extends EventEmitter {
|
|
|
604
614
|
* If verbose changes, re-renders the entire conversation.
|
|
605
615
|
*/
|
|
606
616
|
setConfig(newConfig) {
|
|
607
|
-
const
|
|
617
|
+
const oldVerbosity = this.config.verbosity;
|
|
608
618
|
this.config = { ...this.config, ...newConfig };
|
|
609
|
-
//
|
|
610
|
-
if (newConfig.
|
|
619
|
+
// Keep legacy verbose in sync with verbosity
|
|
620
|
+
if (newConfig.verbosity !== undefined) {
|
|
621
|
+
this.config.verbose = newConfig.verbosity === 'verbose';
|
|
622
|
+
}
|
|
623
|
+
// If verbosity changed, re-render entire conversation
|
|
624
|
+
if (newConfig.verbosity !== undefined && newConfig.verbosity !== oldVerbosity) {
|
|
611
625
|
this.reRenderConversation();
|
|
612
626
|
}
|
|
613
627
|
// Theme change requires prompt refresh
|