@kinqs/brainrouter-cli 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -52
- package/agents/architect.json +18 -0
- package/agents/explorer.json +18 -0
- package/agents/reviewer.json +18 -0
- package/agents/verifier.json +18 -0
- package/agents/worker.json +18 -0
- package/dist/agent/agent.d.ts +12 -1
- package/dist/agent/agent.js +134 -18
- package/dist/cli/banner.d.ts +20 -0
- package/dist/cli/banner.js +47 -14
- package/dist/cli/cliPrompt.d.ts +40 -3
- package/dist/cli/cliPrompt.js +52 -25
- package/dist/cli/commands/_context.d.ts +3 -1
- package/dist/cli/commands/_helpers.d.ts +1 -1
- package/dist/cli/commands/config.d.ts +46 -0
- package/dist/cli/commands/config.js +1042 -0
- package/dist/cli/commands/init.d.ts +20 -0
- package/dist/cli/commands/init.js +64 -0
- package/dist/cli/commands/login.d.ts +13 -0
- package/dist/cli/commands/login.js +179 -0
- package/dist/cli/commands/mcp.d.ts +13 -11
- package/dist/cli/commands/mcp.js +239 -74
- package/dist/cli/commands/orchestration.js +18 -0
- package/dist/cli/commands/ui.js +117 -58
- package/dist/cli/commands/workflow.d.ts +2 -0
- package/dist/cli/commands/workflow.js +54 -8
- package/dist/cli/ink/ChatApp.d.ts +206 -0
- package/dist/cli/ink/ChatApp.js +493 -0
- package/dist/cli/ink/Frame.d.ts +26 -0
- package/dist/cli/ink/Frame.js +5 -0
- package/dist/cli/ink/Picker.d.ts +65 -0
- package/dist/cli/ink/Picker.js +133 -0
- package/dist/cli/ink/SlashPalette.d.ts +51 -0
- package/dist/cli/ink/SlashPalette.js +136 -0
- package/dist/cli/ink/TextField.d.ts +34 -0
- package/dist/cli/ink/TextField.js +47 -0
- package/dist/cli/ink/WizardApp.d.ts +7 -0
- package/dist/cli/ink/WizardApp.js +422 -0
- package/dist/cli/ink/ambientChat.d.ts +34 -0
- package/dist/cli/ink/ambientChat.js +7 -0
- package/dist/cli/ink/consoleCapture.d.ts +11 -0
- package/dist/cli/ink/consoleCapture.js +33 -0
- package/dist/cli/ink/markdownRender.d.ts +41 -0
- package/dist/cli/ink/markdownRender.js +278 -0
- package/dist/cli/ink/renderWithResizeClear.d.ts +14 -0
- package/dist/cli/ink/renderWithResizeClear.js +33 -0
- package/dist/cli/ink/runChat.d.ts +34 -0
- package/dist/cli/ink/runChat.js +571 -0
- package/dist/cli/ink/runPicker.d.ts +31 -0
- package/dist/cli/ink/runPicker.js +139 -0
- package/dist/cli/ink/runSlashPalette.d.ts +23 -0
- package/dist/cli/ink/runSlashPalette.js +33 -0
- package/dist/cli/ink/runWizard.d.ts +22 -0
- package/dist/cli/ink/runWizard.js +133 -0
- package/dist/cli/ink/stdinHandoff.d.ts +51 -0
- package/dist/cli/ink/stdinHandoff.js +78 -0
- package/dist/cli/ink/toolFormat.d.ts +73 -0
- package/dist/cli/ink/toolFormat.js +180 -0
- package/dist/cli/ink/useTerminalSize.d.ts +35 -0
- package/dist/cli/ink/useTerminalSize.js +26 -0
- package/dist/cli/repl.d.ts +25 -3
- package/dist/cli/repl.js +43 -712
- package/dist/cli/slashSuggest.d.ts +32 -0
- package/dist/cli/slashSuggest.js +146 -0
- package/dist/cli/wizard/modelsApi.d.ts +72 -0
- package/dist/cli/wizard/modelsApi.js +166 -0
- package/dist/cli/wizard/picker.d.ts +202 -0
- package/dist/cli/wizard/picker.js +547 -0
- package/dist/cli/wizard/providers.d.ts +86 -0
- package/dist/cli/wizard/providers.js +190 -0
- package/dist/cli/wizard/runner.d.ts +13 -0
- package/dist/cli/wizard/runner.js +488 -0
- package/dist/cli/wizard/types.d.ts +122 -0
- package/dist/cli/wizard/types.js +109 -0
- package/dist/config/config.d.ts +12 -0
- package/dist/config/config.js +45 -3
- package/dist/index.js +148 -206
- package/dist/memory/briefing.d.ts +1 -1
- package/dist/memory/consolidation.d.ts +1 -1
- package/dist/orchestration/agentRegistry.d.ts +36 -0
- package/dist/orchestration/agentRegistry.js +64 -0
- package/dist/orchestration/orchestrator.d.ts +7 -0
- package/dist/orchestration/orchestrator.js +2 -0
- package/dist/orchestration/tools.d.ts +10 -1
- package/dist/orchestration/tools.js +48 -4
- package/dist/prompt/skillCatalog.d.ts +11 -0
- package/dist/prompt/skillCatalog.js +134 -0
- package/dist/prompt/skillRunner.d.ts +2 -2
- package/dist/prompt/skillRunner.js +2 -31
- package/dist/prompt/systemPrompt.js +5 -1
- package/dist/runtime/mcpClient.js +14 -11
- package/dist/runtime/mcpPool.d.ts +162 -0
- package/dist/runtime/mcpPool.js +423 -0
- package/dist/runtime/mcpUtils.d.ts +3 -1
- package/package.json +8 -2
- package/.env.example +0 -116
|
@@ -17,6 +17,7 @@ import { askYesNo } from '../cliPrompt.js';
|
|
|
17
17
|
import { formatPlan, readPlan, updatePlan } from '../../state/taskStore.js';
|
|
18
18
|
import { getLoopState, parseInterval, startLoop, stopLoop } from '../../runtime/loopRunner.js';
|
|
19
19
|
import { SLASH_TO_SKILL } from '../../prompt/skillRunner.js';
|
|
20
|
+
import { listFilesystemSkills, mergeSkillLists } from '../../prompt/skillCatalog.js';
|
|
20
21
|
import { buildGoalKickoffPrompt, runSkillByName, runSkillCommand } from './_helpers.js';
|
|
21
22
|
// Promise-flavored exec for case bodies that shell out.
|
|
22
23
|
const execPromise = promisify(exec);
|
|
@@ -83,16 +84,29 @@ export async function tryHandleWorkflowCommand(ctx) {
|
|
|
83
84
|
switch (command) {
|
|
84
85
|
case '/skills':
|
|
85
86
|
{
|
|
87
|
+
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
86
88
|
const spinner = makeSpinner(chalk.gray('Fetching skills...')).start();
|
|
87
89
|
try {
|
|
88
90
|
const res = await callMcpTool(mcpClient, 'list_skills', { scope: 'all' });
|
|
89
91
|
spinner.stop();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
const mcpSkills = !res.isError ? normalizeSkillsList(res.parsed) : undefined;
|
|
93
|
+
const filesystemSkills = listFilesystemSkills(agent.workspaceRoot);
|
|
94
|
+
const skillsList = mcpSkills
|
|
95
|
+
? mergeSkillLists(mcpSkills, filesystemSkills)
|
|
96
|
+
: filesystemSkills;
|
|
97
|
+
if (skillsList) {
|
|
98
|
+
console.log(chalk.bold(`\n🧠 BrainRouter Skills (${skillsList.length}):`));
|
|
93
99
|
if (skillsList.length > 0) {
|
|
94
100
|
for (const skill of skillsList) {
|
|
95
|
-
|
|
101
|
+
const category = skill.category ? `${skill.category}/` : '';
|
|
102
|
+
const suffix = verbose && skill.description ? ` - ${skill.description}` : '';
|
|
103
|
+
console.log(` • ${chalk.cyan(`${category}${skill.name}`)} (${chalk.gray(skill.scope ?? 'unknown')})${suffix}`);
|
|
104
|
+
}
|
|
105
|
+
if (mcpSkills && skillsList.length > mcpSkills.length) {
|
|
106
|
+
console.log(chalk.gray(` Showing ${skillsList.length} skills (${mcpSkills.length} from MCP, ${skillsList.length - mcpSkills.length} filled from local files).`));
|
|
107
|
+
}
|
|
108
|
+
else if (!mcpSkills && filesystemSkills.length > 0) {
|
|
109
|
+
console.log(chalk.gray(' MCP list unavailable; showing local filesystem skills.'));
|
|
96
110
|
}
|
|
97
111
|
}
|
|
98
112
|
else {
|
|
@@ -101,6 +115,8 @@ export async function tryHandleWorkflowCommand(ctx) {
|
|
|
101
115
|
}
|
|
102
116
|
else {
|
|
103
117
|
console.log(chalk.red('\nFailed to parse skills list response.'));
|
|
118
|
+
if (res.text)
|
|
119
|
+
console.log(chalk.gray(` ${res.text.slice(0, 300)}`));
|
|
104
120
|
}
|
|
105
121
|
}
|
|
106
122
|
catch (err) {
|
|
@@ -112,24 +128,29 @@ export async function tryHandleWorkflowCommand(ctx) {
|
|
|
112
128
|
}
|
|
113
129
|
case '/tools':
|
|
114
130
|
{
|
|
115
|
-
|
|
131
|
+
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
132
|
+
console.log(chalk.bold(`\nLocal Workspace Tools (${LOCAL_TOOLS.length}):`));
|
|
116
133
|
for (const tool of LOCAL_TOOLS) {
|
|
117
|
-
|
|
134
|
+
const suffix = verbose ? ` - ${tool.description}` : '';
|
|
135
|
+
console.log(` • ${chalk.cyan(tool.name)}${suffix}`);
|
|
118
136
|
}
|
|
119
137
|
const spinner = makeSpinner(chalk.gray('Fetching MCP tools...')).start();
|
|
120
138
|
try {
|
|
121
139
|
const res = await mcpClient.listTools();
|
|
122
140
|
spinner.stop();
|
|
123
141
|
const tools = res.tools || [];
|
|
124
|
-
console.log(chalk.bold(
|
|
142
|
+
console.log(chalk.bold(`\nMCP Tools (${tools.length}):`));
|
|
125
143
|
if (tools.length === 0) {
|
|
126
144
|
console.log(chalk.yellow(' No MCP tools exposed by the active server.'));
|
|
127
145
|
}
|
|
128
146
|
else {
|
|
129
147
|
for (const tool of tools) {
|
|
130
|
-
|
|
148
|
+
const suffix = verbose ? ` - ${tool.description || 'No description'}` : '';
|
|
149
|
+
console.log(` • ${chalk.cyan(tool.name)}${suffix}`);
|
|
131
150
|
}
|
|
132
151
|
}
|
|
152
|
+
if (!verbose)
|
|
153
|
+
console.log(chalk.gray(' Use /tools --verbose to include descriptions.'));
|
|
133
154
|
}
|
|
134
155
|
catch (err) {
|
|
135
156
|
spinner.fail(chalk.red('Failed to list MCP tools.'));
|
|
@@ -960,3 +981,28 @@ export async function tryHandleWorkflowCommand(ctx) {
|
|
|
960
981
|
}
|
|
961
982
|
return false;
|
|
962
983
|
}
|
|
984
|
+
export function normalizeSkillsList(payload) {
|
|
985
|
+
const list = Array.isArray(payload)
|
|
986
|
+
? payload
|
|
987
|
+
: Array.isArray(payload?.skills)
|
|
988
|
+
? payload.skills
|
|
989
|
+
: Array.isArray(payload?.items)
|
|
990
|
+
? payload.items
|
|
991
|
+
: Array.isArray(payload?.results)
|
|
992
|
+
? payload.results
|
|
993
|
+
: undefined;
|
|
994
|
+
if (!Array.isArray(list))
|
|
995
|
+
return undefined;
|
|
996
|
+
return list
|
|
997
|
+
.filter((item) => item && typeof item === 'object' && typeof item.name === 'string')
|
|
998
|
+
.map((item) => {
|
|
999
|
+
const normalized = { name: item.name };
|
|
1000
|
+
if (typeof item.scope === 'string')
|
|
1001
|
+
normalized.scope = item.scope;
|
|
1002
|
+
if (typeof item.category === 'string')
|
|
1003
|
+
normalized.category = item.category;
|
|
1004
|
+
if (typeof item.description === 'string')
|
|
1005
|
+
normalized.description = item.description;
|
|
1006
|
+
return normalized;
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type SlashCommandDef } from './SlashPalette.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ink-based chat REPL — replaces the readline-based `startREPL` shell.
|
|
5
|
+
*
|
|
6
|
+
* Layout (matches claude-code's chrome):
|
|
7
|
+
*
|
|
8
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
9
|
+
* │ banner (one-time, at top of scrollback) │
|
|
10
|
+
* │ ⏺ assistant turn 1 │
|
|
11
|
+
* │ ⎿ tool call result │
|
|
12
|
+
* │ ❯ user: what about X? │
|
|
13
|
+
* │ ⏺ assistant turn 2 │
|
|
14
|
+
* │ ... │
|
|
15
|
+
* │ │
|
|
16
|
+
* ├──────────────────────────────────────────────────────────────┤
|
|
17
|
+
* │ ❯ <input cursor here> │ ← composer
|
|
18
|
+
* ├──────────────────────────────────────────────────────────────┤
|
|
19
|
+
* │ model · session · ◉ effort ? for shortcuts │ ← footer
|
|
20
|
+
* └──────────────────────────────────────────────────────────────┘
|
|
21
|
+
*
|
|
22
|
+
* Scrollback stays in Ink's normal render tree. It is tempting to use
|
|
23
|
+
* `<Static>` for finished entries, but a chat shell has a permanently
|
|
24
|
+
* live composer below it; on terminal resize, the Static/dynamic split
|
|
25
|
+
* can leave old composer frames behind because the resize clear only
|
|
26
|
+
* applies to Ink's live region. Keeping the full frame diffable makes
|
|
27
|
+
* resize redraw exactly one prompt block.
|
|
28
|
+
*
|
|
29
|
+
* Slash palette is a child component: when the input buffer becomes
|
|
30
|
+
* `/`, the palette renders BELOW the composer with the filtered
|
|
31
|
+
* command list. No more readline detach/Ink mount cycle — Ink owns
|
|
32
|
+
* stdin for the entire REPL lifetime.
|
|
33
|
+
*
|
|
34
|
+
* State machine:
|
|
35
|
+
* - phase: 'idle' | 'turn-running' | 'side-conversation'
|
|
36
|
+
* - scrollback: ScrollbackEntry[] — completed entries (banner, turns, slash output)
|
|
37
|
+
* - composerValue: string — current input buffer
|
|
38
|
+
* - palette: 'closed' | 'open' — visible when value starts with `/`
|
|
39
|
+
*/
|
|
40
|
+
export interface ChatAppProps {
|
|
41
|
+
initialBanner: string;
|
|
42
|
+
initialOfflineWarning?: string;
|
|
43
|
+
initialHint: string;
|
|
44
|
+
/** Static description of the slash commands the user can run. */
|
|
45
|
+
slashCommands: SlashCommandDef[];
|
|
46
|
+
/** Initial prompt label, e.g. "brainrouter[effort:low]". */
|
|
47
|
+
promptLabel: string;
|
|
48
|
+
/** Accent color (hex) for chrome. */
|
|
49
|
+
accentColor?: string;
|
|
50
|
+
/** Called when the user submits a line (slash command OR free-form prompt). */
|
|
51
|
+
onSubmit: (text: string, push: PushScrollback) => Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Imperative hook — invoked once during mount with a controller object the
|
|
54
|
+
* orchestrator can use to push scrollback / footer updates from outside the
|
|
55
|
+
* React tree (e.g. when the parent-turn closure wants to print a side-channel
|
|
56
|
+
* message after `agent.runTurn` resolved but before the next prompt cycle).
|
|
57
|
+
*/
|
|
58
|
+
onReady?: (controller: ChatController) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Cycle the access mode (read → write → shell → read). Returned label is
|
|
61
|
+
* appended to the footer pill. Called when the user presses Shift+Tab.
|
|
62
|
+
*/
|
|
63
|
+
onAccessModeCycle?: () => string;
|
|
64
|
+
/**
|
|
65
|
+
* Initial access mode for the footer pill — kept in sync via
|
|
66
|
+
* `controller.setFooter({ accessMode })`. Defaults to 'read'.
|
|
67
|
+
*/
|
|
68
|
+
initialAccessMode?: 'read' | 'write' | 'shell';
|
|
69
|
+
/**
|
|
70
|
+
* Initial extra footer segments (model, session, effort, branch). Updated
|
|
71
|
+
* after each turn via `controller.setFooter`.
|
|
72
|
+
*/
|
|
73
|
+
initialFooter?: FooterState;
|
|
74
|
+
}
|
|
75
|
+
export interface FooterState {
|
|
76
|
+
/** e.g. "gpt-4o-mini". */
|
|
77
|
+
model?: string;
|
|
78
|
+
/** e.g. "rep-2026-…-abc123". Truncated for display. */
|
|
79
|
+
session?: string;
|
|
80
|
+
/** e.g. "main". */
|
|
81
|
+
branch?: string;
|
|
82
|
+
/** "low" | "medium" | "high". Rendered as a pill. */
|
|
83
|
+
effort?: string;
|
|
84
|
+
/** Free-form right-side text (statusline segments). */
|
|
85
|
+
rightExtra?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface ChatController {
|
|
88
|
+
/** Push entries from outside the React tree (e.g. after the parent turn ended). */
|
|
89
|
+
push: PushScrollback;
|
|
90
|
+
/** Replace the startup banner row without clearing the chat scrollback. */
|
|
91
|
+
replaceBanner: (text: string) => void;
|
|
92
|
+
/** Update the footer status row (model, session, access mode, effort, etc.). */
|
|
93
|
+
setFooter: (patch: Partial<FooterState & {
|
|
94
|
+
accessMode: 'read' | 'write' | 'shell';
|
|
95
|
+
}>) => void;
|
|
96
|
+
/** Programmatically inject text into the composer (e.g. workflow.ts loop tick). */
|
|
97
|
+
setComposer: (text: string) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Render `node` as an overlay above the chat composer. The composer
|
|
100
|
+
* hides while the overlay is active so the overlay's own useInput
|
|
101
|
+
* handlers own keystrokes. Used by `runPicker` / `runTextField` to
|
|
102
|
+
* show /config, /login, /init pickers WITHOUT mounting a second Ink
|
|
103
|
+
* instance (which would race the chat for stdin and terminal state).
|
|
104
|
+
* Promise resolves when `clearOverlay()` is called.
|
|
105
|
+
*/
|
|
106
|
+
showOverlay: (node: React.ReactElement) => Promise<void>;
|
|
107
|
+
/** Remove whatever overlay is currently shown; safe to call when none is set. */
|
|
108
|
+
clearOverlay: () => void;
|
|
109
|
+
/** Exit the chat app gracefully. */
|
|
110
|
+
exit: () => void;
|
|
111
|
+
}
|
|
112
|
+
export type ScrollbackEntry = {
|
|
113
|
+
id: number;
|
|
114
|
+
kind: 'raw';
|
|
115
|
+
text: string;
|
|
116
|
+
noWrap?: boolean;
|
|
117
|
+
} | {
|
|
118
|
+
id: number;
|
|
119
|
+
kind: 'user';
|
|
120
|
+
text: string;
|
|
121
|
+
} | {
|
|
122
|
+
id: number;
|
|
123
|
+
kind: 'assistant';
|
|
124
|
+
text: string;
|
|
125
|
+
raw?: boolean;
|
|
126
|
+
durationMs?: number;
|
|
127
|
+
tokensIn?: number;
|
|
128
|
+
tokensOut?: number;
|
|
129
|
+
calls?: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Tool call result row — claude-code style:
|
|
133
|
+
* ⏺ Read(src/foo.ts) (green ⏺ when ok, red when failed)
|
|
134
|
+
* ⎿ <preview line 1> (if preview present, with ⎿ connector)
|
|
135
|
+
* <preview line 2> (continuation lines plain indent)
|
|
136
|
+
* (+N more lines hidden) (truncation hint)
|
|
137
|
+
* `header` is the formatToolCall'd string. `kind` of preview rendering
|
|
138
|
+
* is derived: if the preview looks like a diff, lines colored +green/-red.
|
|
139
|
+
*/
|
|
140
|
+
| {
|
|
141
|
+
id: number;
|
|
142
|
+
kind: 'tool';
|
|
143
|
+
header: string;
|
|
144
|
+
ok: boolean;
|
|
145
|
+
durationMs?: number;
|
|
146
|
+
preview?: string;
|
|
147
|
+
} | {
|
|
148
|
+
id: number;
|
|
149
|
+
kind: 'memory';
|
|
150
|
+
level: 'info' | 'warn';
|
|
151
|
+
text: string;
|
|
152
|
+
}
|
|
153
|
+
/** Plan rendering: optional `explanation` renders above the checklist as a dim line. */
|
|
154
|
+
| {
|
|
155
|
+
id: number;
|
|
156
|
+
kind: 'plan';
|
|
157
|
+
items: {
|
|
158
|
+
step: string;
|
|
159
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
160
|
+
}[];
|
|
161
|
+
explanation?: string;
|
|
162
|
+
}
|
|
163
|
+
/** Notice severity: info → gray dim · warn → yellow · error → red bold. */
|
|
164
|
+
| {
|
|
165
|
+
id: number;
|
|
166
|
+
kind: 'notice';
|
|
167
|
+
text: string;
|
|
168
|
+
level?: 'info' | 'warn' | 'error';
|
|
169
|
+
};
|
|
170
|
+
export interface PushScrollback {
|
|
171
|
+
raw(text: string, opts?: {
|
|
172
|
+
noWrap?: boolean;
|
|
173
|
+
}): void;
|
|
174
|
+
user(text: string): void;
|
|
175
|
+
/** `raw: true` skips marked-terminal rendering (use when caller already pre-rendered or user wants raw scrollback). */
|
|
176
|
+
assistant(text: string, meta?: {
|
|
177
|
+
raw?: boolean;
|
|
178
|
+
durationMs?: number;
|
|
179
|
+
tokensIn?: number;
|
|
180
|
+
tokensOut?: number;
|
|
181
|
+
calls?: number;
|
|
182
|
+
}): void;
|
|
183
|
+
/**
|
|
184
|
+
* `header` is the formatted call (e.g. `Read(src/foo.ts)` from
|
|
185
|
+
* `formatToolCall` in toolFormat.ts), NOT the raw tool name. Pass the
|
|
186
|
+
* full result preview unmodified — the renderer applies diff coloring
|
|
187
|
+
* + truncation hints.
|
|
188
|
+
*/
|
|
189
|
+
tool(header: string, ok: boolean, opts?: {
|
|
190
|
+
preview?: string;
|
|
191
|
+
durationMs?: number;
|
|
192
|
+
}): void;
|
|
193
|
+
memory(level: 'info' | 'warn', text: string): void;
|
|
194
|
+
plan(items: {
|
|
195
|
+
step: string;
|
|
196
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
197
|
+
}[], explanation?: string): void;
|
|
198
|
+
/** Severity defaults to 'info' when omitted (back-compat). */
|
|
199
|
+
notice(text: string, level?: 'info' | 'warn' | 'error'): void;
|
|
200
|
+
/** Update the live spinner label (e.g. "Thinking 5s 1.2k↑ 0.4k↓"). */
|
|
201
|
+
setStatus(label: string): void;
|
|
202
|
+
/** Show / hide the spinner without pushing a scrollback entry. */
|
|
203
|
+
setPhase(phase: 'idle' | 'turn-running'): void;
|
|
204
|
+
}
|
|
205
|
+
export declare function ChatApp({ initialBanner, initialOfflineWarning, initialHint, slashCommands, promptLabel, accentColor, onSubmit, onReady, onAccessModeCycle, initialAccessMode, initialFooter, }: ChatAppProps): import("react/jsx-runtime").JSX.Element;
|
|
206
|
+
export declare function filterPaletteCommands(commands: SlashCommandDef[], query: string): SlashCommandDef[];
|