praxis-agent 0.34.0 → 0.36.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/README.md +9 -1
- package/dist/application/background-agent-manager.d.ts +16 -6
- package/dist/application/background-agent-manager.js +139 -97
- package/dist/application/context-engine.d.ts +56 -0
- package/dist/application/context-engine.js +129 -0
- package/dist/application/session-service.d.ts +8 -5
- package/dist/application/session-service.js +1824 -1728
- package/dist/application/subagent-service.js +385 -193
- package/dist/application/top-level-agent-manager.d.ts +1 -0
- package/dist/application/top-level-agent-manager.js +1025 -403
- package/dist/application/transcript-projection.d.ts +33 -0
- package/dist/application/transcript-projection.js +110 -0
- package/dist/application/turn-lifecycle.d.ts +40 -0
- package/dist/application/turn-lifecycle.js +36 -0
- package/dist/application/turn-memory-coordinator.d.ts +43 -0
- package/dist/application/turn-memory-coordinator.js +98 -0
- package/dist/cli/agents-dashboard.js +10 -5
- package/dist/cli/interactive.js +279 -209
- package/dist/cli/protocol.js +5 -2
- package/dist/cli/tui/claude-style.d.ts +5 -48
- package/dist/cli/tui/claude-style.js +167 -197
- package/dist/cli/tui/task-panel.js +10 -1
- package/dist/cli/tui/theme.d.ts +46 -3
- package/dist/cli/tui/theme.js +414 -56
- package/dist/cli/tui/tool-permission.js +9 -5
- package/dist/cli/tui/transcript-presentation.d.ts +89 -0
- package/dist/cli/tui/transcript-presentation.js +169 -0
- package/dist/cli/tui/transcript-viewport.d.ts +5 -34
- package/dist/cli/tui/transcript-viewport.js +639 -158
- package/dist/cli/tui/tui-interaction-router.d.ts +78 -0
- package/dist/cli/tui/tui-interaction-router.js +127 -0
- package/dist/cli/tui/tui-view-model.d.ts +6 -2
- package/dist/cli/tui/tui-view-model.js +23 -6
- package/dist/cli-runtime.d.ts +2 -2
- package/dist/compatibility/claude/context.d.ts +2 -2
- package/dist/compatibility/claude/context.js +2 -14
- package/dist/compatibility/claude/data-plane-adapter.d.ts +9 -0
- package/dist/compatibility/claude/data-plane-adapter.js +44 -0
- package/dist/compatibility/claude/paths.js +2 -2
- package/dist/compatibility/claude/shared-resources.d.ts +7 -38
- package/dist/compatibility/claude/transcript-codec.d.ts +21 -0
- package/dist/compatibility/claude/transcript-codec.js +512 -0
- package/dist/core/agent-orchestration.d.ts +31 -0
- package/dist/core/agent-orchestration.js +235 -0
- package/dist/core/context.d.ts +25 -7
- package/dist/core/context.js +46 -0
- package/dist/core/prompt-composer.d.ts +8 -16
- package/dist/core/prompt-composer.js +65 -25
- package/dist/core/resources.d.ts +39 -0
- package/dist/core/resources.js +2 -0
- package/dist/core/runtime.d.ts +6 -1
- package/dist/core/runtime.js +15 -1
- package/dist/core/session.d.ts +2 -0
- package/dist/core/session.js +5 -0
- package/dist/core/transcript-codec.d.ts +70 -0
- package/dist/core/transcript-codec.js +60 -0
- package/dist/core/transcript-event.d.ts +33 -0
- package/dist/core/transcript-event.js +198 -0
- package/dist/persistence/claude-job-store.d.ts +58 -0
- package/dist/persistence/claude-job-store.js +483 -1
- package/dist/persistence/data-plane-adapter.d.ts +32 -0
- package/dist/persistence/data-plane-adapter.js +2 -0
- package/dist/persistence/data-plane.d.ts +4 -20
- package/dist/persistence/data-plane.js +10 -47
- package/dist/persistence/native-data-plane-adapter.d.ts +9 -0
- package/dist/persistence/native-data-plane-adapter.js +39 -0
- package/dist/persistence/native-resources.d.ts +4 -4
- package/dist/persistence/native-transcript-codec.d.ts +13 -0
- package/dist/persistence/native-transcript-codec.js +102 -0
- package/dist/persistence/native-transcript-reader.d.ts +53 -0
- package/dist/persistence/native-transcript-reader.js +283 -0
- package/dist/persistence/subagent-lifecycle-store.d.ts +41 -8
- package/dist/persistence/subagent-lifecycle-store.js +373 -146
- package/dist/platform/exclusive-file-lease.d.ts +3 -0
- package/dist/platform/exclusive-file-lease.js +3 -0
- package/dist/tools/claude-user-message.d.ts +0 -1
- package/dist/tools/claude-user-message.js +0 -1
- package/package.json +6 -2
|
@@ -5,7 +5,7 @@ import { composerEditorSegments } from './composer-editor.js';
|
|
|
5
5
|
import { composerLayoutForWidth } from './composer-layout.js';
|
|
6
6
|
import { visiblePatchLines } from './git-diff.js';
|
|
7
7
|
import { TUI_HOOK_MENU } from './hook-settings.js';
|
|
8
|
-
import {
|
|
8
|
+
import { resolveTuiTheme, tuiSyntaxStyle, useTuiTheme, } from './theme.js';
|
|
9
9
|
const SPINNER = ['✳', '✢', '✣', '✤', '✥'];
|
|
10
10
|
export function useTerminalWidth(override) {
|
|
11
11
|
const { stdout } = useStdout();
|
|
@@ -106,8 +106,13 @@ function selectionPrefix(selected, screenReader) {
|
|
|
106
106
|
return screenReader ? 'Selected: ' : ' ❯ ';
|
|
107
107
|
return screenReader ? '' : ' ';
|
|
108
108
|
}
|
|
109
|
+
function dashboardSelectionPrefix(selected, screenReader, noColor) {
|
|
110
|
+
if (selected)
|
|
111
|
+
return screenReader || noColor ? 'Selected: ' : '❯ ';
|
|
112
|
+
return screenReader || noColor ? '' : ' ';
|
|
113
|
+
}
|
|
109
114
|
export function WelcomePanel({ display, width, showTips, dataPlane = 'claude', }) {
|
|
110
|
-
const
|
|
115
|
+
const theme = useTuiTheme();
|
|
111
116
|
if (!showTips)
|
|
112
117
|
return null;
|
|
113
118
|
const panelWidth = Math.min(100, Math.max(32, width));
|
|
@@ -124,7 +129,7 @@ export function WelcomePanel({ display, width, showTips, dataPlane = 'claude', }
|
|
|
124
129
|
const fill = Math.max(1, panelWidth - title.length - 6);
|
|
125
130
|
const leftWidth = Math.max(12, Math.floor((panelWidth - 4) / 2));
|
|
126
131
|
const rightWidth = Math.max(12, panelWidth - leftWidth - 4);
|
|
127
|
-
return (_jsxs(Box, { flexDirection: "column", width: panelWidth, children: [_jsxs(Text, {
|
|
132
|
+
return (_jsxs(Box, { flexDirection: "column", width: panelWidth, children: [_jsxs(Text, { ...theme.text.muted, children: ['╭───', _jsx(Text, { ...theme.text.productIdentity, bold: true, children: brand }), ` Code v${display.version} `, _jsx(Text, { dimColor: true, children: '─'.repeat(fill) }), '╮'] }), _jsxs(Box, { borderStyle: "round", ...theme.surface.neutralBorder, borderTop: false, flexDirection: wide ? 'row' : 'column', width: panelWidth, paddingX: 1, children: [_jsxs(Box, { alignItems: wide ? 'center' : undefined, flexDirection: "column", width: wide ? leftWidth : '100%', children: [_jsx(Text, { children: " " }), _jsxs(Text, { bold: true, children: ["Welcome to ", brand] }), _jsx(Text, { children: " " }), _jsx(Text, { ...theme.text.productIdentity, bold: true, children: "\u2590\u259B\u2588\u2588\u2588\u259C\u258C" }), _jsx(Text, { ...theme.text.productIdentity, children: "\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598" }), _jsx(Text, { ...theme.text.productIdentity, children: " \u2598\u2598 \u259D\u259D" }), _jsx(Text, { children: " " }), _jsxs(Text, { wrap: "truncate-end", children: [model, effort] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd })] }), _jsxs(Box, { flexDirection: "column", width: wide ? rightWidth : '100%', marginTop: wide ? 0 : 1, children: [_jsx(Text, { bold: true, children: "Get started" }), _jsxs(Text, { wrap: "truncate-end", children: ["/init to create ", dataPlane === 'native' ? 'PRAXIS.md' : 'CLAUDE.md'] }), _jsx(Text, { wrap: "truncate-end", children: "/config to open settings" }), _jsx(Text, { dimColor: true, children: " " }), _jsx(Text, { bold: true, children: dataPlane === 'native'
|
|
128
133
|
? 'Stored by Praxis'
|
|
129
134
|
: 'Shared with Claude Code' }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: "Sessions \u00B7 memory \u00B7 skills" })] })] })] }));
|
|
130
135
|
}
|
|
@@ -132,12 +137,12 @@ export function WelcomePanel({ display, width, showTips, dataPlane = 'claude', }
|
|
|
132
137
|
// conversation content. Keeps the same product/model/cwd facts as WelcomePanel
|
|
133
138
|
// in a small fixed footprint, truncating every line to the supplied width.
|
|
134
139
|
export function SessionIdentity({ display, width, }) {
|
|
135
|
-
const
|
|
140
|
+
const theme = useTuiTheme();
|
|
136
141
|
const identityWidth = Math.max(1, Math.floor(width));
|
|
137
142
|
const model = display.model ?? 'provider default';
|
|
138
143
|
const effort = display.effort ? ` · ${display.effort} effort` : '';
|
|
139
144
|
const cwd = compactPath(display.cwd);
|
|
140
|
-
return (_jsxs(Box, { flexDirection: "column", width: identityWidth, children: [_jsx(Text, { wrap: "truncate-end", children: _jsx(Text, {
|
|
145
|
+
return (_jsxs(Box, { flexDirection: "column", width: identityWidth, children: [_jsx(Text, { wrap: "truncate-end", children: _jsx(Text, { ...theme.text.productIdentity, bold: true, children: `Praxis Code v${display.version}` }) }), _jsxs(Text, { wrap: "truncate-end", children: [model, effort] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd })] }));
|
|
141
146
|
}
|
|
142
147
|
const INLINE_SEGMENT_CACHE_MAX = 4096;
|
|
143
148
|
const inlineSegmentCache = new Map();
|
|
@@ -168,14 +173,14 @@ function cachedInlineSegments(text) {
|
|
|
168
173
|
}
|
|
169
174
|
return segments;
|
|
170
175
|
}
|
|
171
|
-
function inlineTextElement(text,
|
|
176
|
+
function inlineTextElement(text, theme) {
|
|
172
177
|
return (_jsx(Text, { children: cachedInlineSegments(text).map((segment, index) => {
|
|
173
178
|
if (segment.kind === 'code')
|
|
174
|
-
return (_jsx(Text, {
|
|
179
|
+
return (_jsx(Text, { ...theme.text.info, children: segment.text }, index));
|
|
175
180
|
if (segment.kind === 'bold')
|
|
176
181
|
return (_jsx(Text, { bold: true, children: segment.text }, index));
|
|
177
182
|
if (segment.kind === 'link')
|
|
178
|
-
return (_jsx(Text, {
|
|
183
|
+
return (_jsx(Text, { ...theme.text.link, underline: true, children: segment.text }, index));
|
|
179
184
|
return segment.text;
|
|
180
185
|
}) }));
|
|
181
186
|
}
|
|
@@ -211,35 +216,40 @@ function cachedMarkdownLineShape(line) {
|
|
|
211
216
|
return shape;
|
|
212
217
|
}
|
|
213
218
|
const ELEMENT_CACHE_KEY_SEPARATOR = String.fromCharCode(0);
|
|
214
|
-
function markdownLineStyleSignature(
|
|
215
|
-
return [
|
|
219
|
+
function markdownLineStyleSignature(theme) {
|
|
220
|
+
return [
|
|
221
|
+
theme.text.focusMarker.color,
|
|
222
|
+
theme.text.productIdentity.color,
|
|
223
|
+
theme.text.info.color,
|
|
224
|
+
theme.text.link.color,
|
|
225
|
+
].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
216
226
|
}
|
|
217
227
|
const MARKDOWN_LINE_ELEMENT_CACHE_MAX = 4096;
|
|
218
228
|
const markdownLineElementCache = new Map();
|
|
219
|
-
function buildMarkdownLine(line,
|
|
229
|
+
function buildMarkdownLine(line, theme) {
|
|
220
230
|
const shape = cachedMarkdownLineShape(line);
|
|
221
231
|
if (shape.role === 'h3')
|
|
222
|
-
return _jsx(Text, { bold: true, children: inlineTextElement(shape.content,
|
|
232
|
+
return _jsx(Text, { bold: true, children: inlineTextElement(shape.content, theme) });
|
|
223
233
|
if (shape.role === 'h2')
|
|
224
|
-
return (_jsx(Text, { bold: true,
|
|
234
|
+
return (_jsx(Text, { bold: true, ...theme.text.focusMarker, children: inlineTextElement(shape.content, theme) }));
|
|
225
235
|
if (shape.role === 'h1')
|
|
226
|
-
return (_jsx(Text, { bold: true,
|
|
236
|
+
return (_jsx(Text, { bold: true, ...theme.text.productIdentity, children: inlineTextElement(shape.content, theme) }));
|
|
227
237
|
if (shape.role === 'bullet')
|
|
228
|
-
return (_jsxs(Text, { children: [' • ', inlineTextElement(shape.content,
|
|
238
|
+
return (_jsxs(Text, { children: [' • ', inlineTextElement(shape.content, theme)] }));
|
|
229
239
|
if (shape.role === 'ordered')
|
|
230
|
-
return (_jsxs(Text, { children: [' ', inlineTextElement(shape.content,
|
|
240
|
+
return (_jsxs(Text, { children: [' ', inlineTextElement(shape.content, theme)] }));
|
|
231
241
|
if (shape.role === 'quote')
|
|
232
|
-
return (_jsxs(Text, { dimColor: true, children: ['│ ', inlineTextElement(shape.content,
|
|
242
|
+
return (_jsxs(Text, { dimColor: true, children: ['│ ', inlineTextElement(shape.content, theme)] }));
|
|
233
243
|
if (shape.role === 'plain')
|
|
234
|
-
return inlineTextElement(shape.content,
|
|
244
|
+
return inlineTextElement(shape.content, theme);
|
|
235
245
|
return _jsx(Text, { children: " " });
|
|
236
246
|
}
|
|
237
|
-
function cachedMarkdownLineElement(line,
|
|
238
|
-
const key = [line, markdownLineStyleSignature(
|
|
247
|
+
function cachedMarkdownLineElement(line, theme) {
|
|
248
|
+
const key = [line, markdownLineStyleSignature(theme)].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
239
249
|
const cached = markdownLineElementCache.get(key);
|
|
240
250
|
if (cached)
|
|
241
251
|
return cached;
|
|
242
|
-
const element = buildMarkdownLine(line,
|
|
252
|
+
const element = buildMarkdownLine(line, theme);
|
|
243
253
|
markdownLineElementCache.set(key, element);
|
|
244
254
|
if (markdownLineElementCache.size > MARKDOWN_LINE_ELEMENT_CACHE_MAX) {
|
|
245
255
|
const oldest = markdownLineElementCache.keys().next().value;
|
|
@@ -271,6 +281,7 @@ const CODE_KEYWORDS = new Set([
|
|
|
271
281
|
const CODE_TOKEN_PATTERN = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\b(?:async|await|class|const|else|export|false|from|function|if|import|let|new|null|return|true|undefined|var)\b|\b[A-Za-z_$][\w$]*(?=\s*\())/gu;
|
|
272
282
|
const SYNTAX_TOKEN_CACHE_MAX = 2048;
|
|
273
283
|
const syntaxTokenCache = new Map();
|
|
284
|
+
const syntaxStyleSignatureCache = new WeakMap();
|
|
274
285
|
function cachedSyntaxTokens(text) {
|
|
275
286
|
const cached = syntaxTokenCache.get(text);
|
|
276
287
|
if (cached)
|
|
@@ -293,37 +304,42 @@ function cachedSyntaxTokens(text) {
|
|
|
293
304
|
}
|
|
294
305
|
return tokens;
|
|
295
306
|
}
|
|
296
|
-
function syntaxStyleSignature(
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
syntax
|
|
303
|
-
syntax
|
|
304
|
-
syntax
|
|
305
|
-
syntax
|
|
307
|
+
function syntaxStyleSignature(theme) {
|
|
308
|
+
const cached = syntaxStyleSignatureCache.get(theme);
|
|
309
|
+
if (cached)
|
|
310
|
+
return cached;
|
|
311
|
+
const signature = [
|
|
312
|
+
theme.syntaxHighlightingDisabled ? '1' : '0',
|
|
313
|
+
JSON.stringify(theme.syntax('text')),
|
|
314
|
+
JSON.stringify(theme.syntax('keyword')),
|
|
315
|
+
JSON.stringify(theme.syntax('identifier')),
|
|
316
|
+
JSON.stringify(theme.syntax('string')),
|
|
317
|
+
JSON.stringify(theme.syntax('text', 'removed')),
|
|
318
|
+
JSON.stringify(theme.syntax('text', 'added')),
|
|
319
|
+
JSON.stringify(theme.syntax('addedHighlight')),
|
|
306
320
|
].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
321
|
+
syntaxStyleSignatureCache.set(theme, signature);
|
|
322
|
+
return signature;
|
|
307
323
|
}
|
|
308
324
|
const SYNTAX_LINE_ELEMENT_CACHE_MAX = 4096;
|
|
309
325
|
const syntaxLineElementCache = new Map();
|
|
310
|
-
function buildSyntaxCodeLine(text, prefix, change,
|
|
311
|
-
if (
|
|
326
|
+
function buildSyntaxCodeLine(text, prefix, change, theme) {
|
|
327
|
+
if (theme.syntaxHighlightingDisabled) {
|
|
312
328
|
return (_jsxs(Text, { children: [prefix, text || ' '] }));
|
|
313
329
|
}
|
|
314
|
-
const lineStyle = tuiSyntaxStyle(
|
|
330
|
+
const lineStyle = tuiSyntaxStyle(theme, 'text', change);
|
|
315
331
|
return (_jsxs(Text, { children: [prefix, _jsx(Text, { ...lineStyle, children: cachedSyntaxTokens(text).map(({ kind, token }, index) => {
|
|
316
332
|
if (kind === 'text')
|
|
317
333
|
return token;
|
|
318
|
-
return (_jsx(Text, { ...tuiSyntaxStyle(
|
|
334
|
+
return (_jsx(Text, { ...tuiSyntaxStyle(theme, kind), children: token }, index));
|
|
319
335
|
}) })] }));
|
|
320
336
|
}
|
|
321
|
-
function cachedSyntaxCodeLine(text, prefix, change,
|
|
322
|
-
const key = [text, prefix, change ?? '', syntaxStyleSignature(
|
|
337
|
+
function cachedSyntaxCodeLine(text, prefix, change, theme) {
|
|
338
|
+
const key = [text, prefix, change ?? '', syntaxStyleSignature(theme)].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
323
339
|
const cached = syntaxLineElementCache.get(key);
|
|
324
340
|
if (cached)
|
|
325
341
|
return cached;
|
|
326
|
-
const element = buildSyntaxCodeLine(text, prefix, change,
|
|
342
|
+
const element = buildSyntaxCodeLine(text, prefix, change, theme);
|
|
327
343
|
syntaxLineElementCache.set(key, element);
|
|
328
344
|
if (syntaxLineElementCache.size > SYNTAX_LINE_ELEMENT_CACHE_MAX) {
|
|
329
345
|
const oldest = syntaxLineElementCache.keys().next().value;
|
|
@@ -333,14 +349,12 @@ function cachedSyntaxCodeLine(text, prefix, change, palette) {
|
|
|
333
349
|
return element;
|
|
334
350
|
}
|
|
335
351
|
function SyntaxCodeLine({ text, prefix = '', change, }) {
|
|
336
|
-
const
|
|
337
|
-
return cachedSyntaxCodeLine(text, prefix, change,
|
|
352
|
+
const theme = useTuiTheme();
|
|
353
|
+
return cachedSyntaxCodeLine(text, prefix, change, theme);
|
|
338
354
|
}
|
|
339
355
|
function ToolResultText({ text, prefix = '', }) {
|
|
340
|
-
const
|
|
341
|
-
return (_jsx(Box, { flexDirection: "column", children: text.split('\n').map((line, index) => line.startsWith('+') && !line.startsWith('+++') ? (_jsx(SyntaxCodeLine, { prefix: index === 0 ? prefix : prefix ? ' ' : '', text: line, change: "added" }, index)) : line.startsWith('-') && !line.startsWith('---') ? (_jsx(SyntaxCodeLine, { prefix: index === 0 ? prefix : prefix ? ' ' : '', text: line, change: "removed" }, index)) : (_jsxs(Text, { ...(line.startsWith('@@')
|
|
342
|
-
? { color: palette.info }
|
|
343
|
-
: { dimColor: true }), children: [index === 0 ? prefix : prefix ? ' ' : '', line || ' '] }, index))) }));
|
|
356
|
+
const theme = useTuiTheme();
|
|
357
|
+
return (_jsx(Box, { flexDirection: "column", children: text.split('\n').map((line, index) => line.startsWith('+') && !line.startsWith('+++') ? (_jsx(SyntaxCodeLine, { prefix: index === 0 ? prefix : prefix ? ' ' : '', text: line, change: "added" }, index)) : line.startsWith('-') && !line.startsWith('---') ? (_jsx(SyntaxCodeLine, { prefix: index === 0 ? prefix : prefix ? ' ' : '', text: line, change: "removed" }, index)) : (_jsxs(Text, { ...(line.startsWith('@@') ? theme.text.info : { dimColor: true }), children: [index === 0 ? prefix : prefix ? ' ' : '', line || ' '] }, index))) }));
|
|
344
358
|
}
|
|
345
359
|
function inputString(call, key) {
|
|
346
360
|
const value = call.input[key];
|
|
@@ -362,7 +376,7 @@ function toolHeading(call) {
|
|
|
362
376
|
return call.name;
|
|
363
377
|
}
|
|
364
378
|
function ToolTranscriptEntry({ call, detail, result, detailed, }) {
|
|
365
|
-
const
|
|
379
|
+
const theme = useTuiTheme();
|
|
366
380
|
const displayResult = call.name === 'Read' &&
|
|
367
381
|
result?.text.startsWith('Wasted call — file unchanged since your last Read')
|
|
368
382
|
? 'Unchanged since last read'
|
|
@@ -380,15 +394,24 @@ function ToolTranscriptEntry({ call, detail, result, detailed, }) {
|
|
|
380
394
|
: displayResult;
|
|
381
395
|
const oldLines = contentLines(inputString(call, 'old_string'));
|
|
382
396
|
const newLines = contentLines(inputString(call, 'new_string'));
|
|
383
|
-
|
|
397
|
+
const markerStyle = result
|
|
398
|
+
? result.isError
|
|
399
|
+
? theme.text.error
|
|
400
|
+
: theme.text.success
|
|
401
|
+
: theme.text.active;
|
|
402
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { children: [_jsx(Text, { ...markerStyle, children: "\u23FA" }), ' ', _jsx(Text, { ...theme.text.heading, bold: true, children: toolHeading(call) })] }), !['Bash', 'Read', 'Edit'].includes(call.name) && detail ? (_jsxs(Text, { dimColor: true, children: [" ", detail] })) : null, result ? (_jsx(Box, { marginLeft: 2, flexDirection: "column", children: result.isError ? (_jsxs(Text, { ...theme.text.error, children: ["\u23BF Error: ", errorText] })) : call.name === 'Edit' ? (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: ["\u23BF Added ", newLines.length, " line", newLines.length === 1 ? '' : 's', ", removed ", oldLines.length, " line", oldLines.length === 1 ? '' : 's'] }), detailed &&
|
|
384
403
|
oldLines.map((line, index) => (_jsx(SyntaxCodeLine, { prefix: ` ${index + 1} -`, text: line, change: "removed" }, `old-${index}`))), detailed &&
|
|
385
404
|
newLines.map((line, index) => (_jsx(SyntaxCodeLine, { prefix: ` ${index + 1} +`, text: line, change: "added" }, `new-${index}`)))] })) : resultIsDiff ? (_jsx(ToolResultText, { text: visible.join('\n'), prefix: "\u23BF " })) : (_jsxs(_Fragment, { children: [visible.map((line, index) => (_jsxs(Text, { dimColor: true, children: [index === 0 ? '⎿ ' : ' ', line || ' '] }, index))), hidden > 0 ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2026 +", hidden, " lines (ctrl+o to expand)"] })) : null] })) })) : null] }));
|
|
386
405
|
}
|
|
387
406
|
function ThinkingBlock({ text, active, expanded, screenReader, }) {
|
|
388
|
-
const
|
|
407
|
+
const theme = useTuiTheme();
|
|
389
408
|
const summary = text.replace(/\s+/gu, ' ').trim();
|
|
390
409
|
const showFull = screenReader || active || expanded;
|
|
391
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { ...(
|
|
410
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { ...(active
|
|
411
|
+
? theme.text.active
|
|
412
|
+
: !screenReader
|
|
413
|
+
? theme.text.focusMarker
|
|
414
|
+
: {}), dimColor: !screenReader, italic: !screenReader, children: [screenReader ? 'Thinking:' : '✻ ', active ? 'Thinking…' : 'Thought for a moment', !showFull && summary ? ` · ${summary.slice(0, 160)}` : ''] }), showFull && text ? (_jsx(Box, { marginLeft: screenReader ? 0 : 2, flexDirection: "column", children: _jsx(MarkdownText, { text: text }) })) : !screenReader && summary.length > 160 ? (_jsx(Text, { dimColor: true, children: " ctrl+o to expand thinking" })) : null] }));
|
|
392
415
|
}
|
|
393
416
|
function compactTokens(tokens) {
|
|
394
417
|
if (tokens >= 1_000_000)
|
|
@@ -401,16 +424,17 @@ function percent(tokens, total) {
|
|
|
401
424
|
return `${Math.round((tokens / Math.max(1, total)) * 100 * 10) / 10}%`;
|
|
402
425
|
}
|
|
403
426
|
function ContextUsageBlock({ usedTokens, contextWindowTokens, model, skills, memoryFiles, screenReader, }) {
|
|
427
|
+
const theme = useTuiTheme();
|
|
404
428
|
const totalTokens = Math.max(1, contextWindowTokens);
|
|
405
429
|
const compactBuffer = Math.round(totalTokens * 0.165);
|
|
406
430
|
const usable = Math.max(1, totalTokens - compactBuffer);
|
|
407
431
|
if (screenReader) {
|
|
408
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Context Usage" }), _jsxs(Text, { children: [model ?? 'provider default', " \u00B7 ", usedTokens.toLocaleString(), "/", totalTokens.toLocaleString(), " tokens (", percent(usedTokens, totalTokens), ")"] }), _jsxs(Text, { children: ["Autocompact buffer: ", compactBuffer.toLocaleString(), " tokens"] }), _jsxs(Text, { children: ["Skills: ", skills.map(({ name }) => name).join(', ') || 'none'] })] }));
|
|
432
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { ...theme.text.heading, children: "Context Usage" }), _jsxs(Text, { children: [model ?? 'provider default', " \u00B7 ", usedTokens.toLocaleString(), "/", totalTokens.toLocaleString(), " tokens (", percent(usedTokens, totalTokens), ")"] }), _jsxs(Text, { children: ["Autocompact buffer: ", compactBuffer.toLocaleString(), " tokens"] }), _jsxs(Text, { children: ["Skills: ", skills.map(({ name }) => name).join(', ') || 'none'] })] }));
|
|
409
433
|
}
|
|
410
434
|
const usedCells = Math.min(25, Math.round((usedTokens / totalTokens) * 25));
|
|
411
435
|
const bufferCells = Math.min(25 - usedCells, Math.round((compactBuffer / totalTokens) * 25));
|
|
412
436
|
const cells = Array.from({ length: 25 }, (_, index) => index < usedCells ? '⛁' : index >= 25 - bufferCells ? '⛝' : '⛶');
|
|
413
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginLeft: 2, children: [_jsx(Text, { bold: true, children: "Context Usage" }), _jsxs(Box, { children: [_jsx(Box, { flexDirection: "column", marginRight: 2, children: Array.from({ length: 5 }, (_, row) => (_jsx(Text, { children: cells.slice(row * 5, row * 5 + 5).join(' ') }, row))) }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: [model ?? 'provider default', " \u00B7 ", compactTokens(usedTokens), "/", compactTokens(totalTokens), " tokens (", percent(usedTokens, totalTokens), ")"] }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, italic: true, children: "Estimated usage by category" }), _jsxs(Text, { children: ["\u26C1 Messages and other context: ", compactTokens(usedTokens), " tokens (", percent(usedTokens, totalTokens), ")"] }), _jsxs(Text, { children: ["\u26F6 Free space: ", compactTokens(Math.max(0, usable - usedTokens)), " (", percent(Math.max(0, usable - usedTokens), totalTokens), ")"] }), _jsxs(Text, { children: ["\u26DD Autocompact buffer: ", compactTokens(compactBuffer), " tokens (", percent(compactBuffer, totalTokens), ")"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Memory files \u00B7 /memory" }), memoryFiles.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u2514 No memory files" })) : (memoryFiles.map((file, index) => (_jsxs(Text, { dimColor: true, children: [index === memoryFiles.length - 1 ? '└' : '├', " ", file.path, ":", ' ', file.tokens, " tokens"] }, file.path)))), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Skills \u00B7 /skills" }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Loaded" }), skills.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u2514 No skills loaded" })) : (skills.map((skill, index) => (_jsxs(Text, { dimColor: true, children: [index === skills.length - 1 ? '└' : '├', " ", skill.name, ": ~", skill.tokens, " tokens"] }, skill.name))))] }));
|
|
437
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginLeft: 2, children: [_jsx(Text, { ...theme.text.heading, bold: true, children: "Context Usage" }), _jsxs(Box, { children: [_jsx(Box, { flexDirection: "column", marginRight: 2, children: Array.from({ length: 5 }, (_, row) => (_jsx(Text, { children: cells.slice(row * 5, row * 5 + 5).join(' ') }, row))) }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: [model ?? 'provider default', " \u00B7 ", compactTokens(usedTokens), "/", compactTokens(totalTokens), " tokens (", percent(usedTokens, totalTokens), ")"] }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, italic: true, children: "Estimated usage by category" }), _jsxs(Text, { children: ["\u26C1 Messages and other context: ", compactTokens(usedTokens), " tokens (", percent(usedTokens, totalTokens), ")"] }), _jsxs(Text, { children: ["\u26F6 Free space: ", compactTokens(Math.max(0, usable - usedTokens)), " (", percent(Math.max(0, usable - usedTokens), totalTokens), ")"] }), _jsxs(Text, { children: ["\u26DD Autocompact buffer: ", compactTokens(compactBuffer), " tokens (", percent(compactBuffer, totalTokens), ")"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { ...theme.text.heading, bold: true, children: "Memory files \u00B7 /memory" }), memoryFiles.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u2514 No memory files" })) : (memoryFiles.map((file, index) => (_jsxs(Text, { dimColor: true, children: [index === memoryFiles.length - 1 ? '└' : '├', " ", file.path, ":", ' ', file.tokens, " tokens"] }, file.path)))), _jsx(Text, { children: " " }), _jsx(Text, { ...theme.text.heading, bold: true, children: "Skills \u00B7 /skills" }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Loaded" }), skills.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u2514 No skills loaded" })) : (skills.map((skill, index) => (_jsxs(Text, { dimColor: true, children: [index === skills.length - 1 ? '└' : '├', " ", skill.name, ": ~", skill.tokens, " tokens"] }, skill.name))))] }));
|
|
414
438
|
}
|
|
415
439
|
const MARKDOWN_TEXT_CACHE_MAX = 2048;
|
|
416
440
|
const markdownTextCache = new Map();
|
|
@@ -439,33 +463,30 @@ function cachedMarkdownText(text) {
|
|
|
439
463
|
}
|
|
440
464
|
return parsed;
|
|
441
465
|
}
|
|
442
|
-
function markdownTextStyleSignature(
|
|
443
|
-
return [
|
|
444
|
-
syntaxStyleSignature(palette),
|
|
445
|
-
markdownLineStyleSignature(palette),
|
|
446
|
-
].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
466
|
+
function markdownTextStyleSignature(theme) {
|
|
467
|
+
return [syntaxStyleSignature(theme), markdownLineStyleSignature(theme)].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
447
468
|
}
|
|
448
469
|
const MARKDOWN_TEXT_ELEMENT_CACHE_MAX = 4096;
|
|
449
470
|
const markdownTextElementCache = new Map();
|
|
450
|
-
function buildMarkdownText(text,
|
|
471
|
+
function buildMarkdownText(text, theme) {
|
|
451
472
|
return (_jsx(Box, { flexDirection: "column", children: cachedMarkdownText(text).map((line, index) => {
|
|
452
473
|
if (line.type === 'fence-open')
|
|
453
474
|
return (_jsx(Text, { dimColor: true, children: `╭─ ${line.label}` }, index));
|
|
454
475
|
if (line.type === 'fence-close')
|
|
455
476
|
return (_jsx(Text, { dimColor: true, children: '╰─' }, index));
|
|
456
477
|
if (line.type === 'code')
|
|
457
|
-
return cloneElement(cachedSyntaxCodeLine(line.text, '│ ', undefined,
|
|
458
|
-
return cloneElement(cachedMarkdownLineElement(line.line,
|
|
478
|
+
return cloneElement(cachedSyntaxCodeLine(line.text, '│ ', undefined, theme), { key: index });
|
|
479
|
+
return cloneElement(cachedMarkdownLineElement(line.line, theme), {
|
|
459
480
|
key: index,
|
|
460
481
|
});
|
|
461
482
|
}) }));
|
|
462
483
|
}
|
|
463
|
-
function cachedMarkdownTextElement(text,
|
|
464
|
-
const key = [text, markdownTextStyleSignature(
|
|
484
|
+
function cachedMarkdownTextElement(text, theme) {
|
|
485
|
+
const key = [text, markdownTextStyleSignature(theme)].join(ELEMENT_CACHE_KEY_SEPARATOR);
|
|
465
486
|
const cached = markdownTextElementCache.get(key);
|
|
466
487
|
if (cached)
|
|
467
488
|
return cached;
|
|
468
|
-
const element = buildMarkdownText(text,
|
|
489
|
+
const element = buildMarkdownText(text, theme);
|
|
469
490
|
markdownTextElementCache.set(key, element);
|
|
470
491
|
if (markdownTextElementCache.size > MARKDOWN_TEXT_ELEMENT_CACHE_MAX) {
|
|
471
492
|
const oldest = markdownTextElementCache.keys().next().value;
|
|
@@ -475,8 +496,8 @@ function cachedMarkdownTextElement(text, palette) {
|
|
|
475
496
|
return element;
|
|
476
497
|
}
|
|
477
498
|
export function MarkdownText({ text }) {
|
|
478
|
-
const
|
|
479
|
-
return cachedMarkdownTextElement(text,
|
|
499
|
+
const theme = useTuiTheme();
|
|
500
|
+
return cachedMarkdownTextElement(text, theme);
|
|
480
501
|
}
|
|
481
502
|
// Bounded streaming-text presentation. While a turn is in progress the active
|
|
482
503
|
// assistant text grows on every frame; re-parsing the entire Markdown document
|
|
@@ -516,94 +537,42 @@ function ActiveStreamText({ text }) {
|
|
|
516
537
|
const { stableText, pendingText, truncated } = activeStreamWindow(text);
|
|
517
538
|
return (_jsxs(Box, { flexDirection: "column", children: [truncated ? _jsx(Text, { dimColor: true, children: "\u2026 earlier streaming content \u2026" }) : null, stableText ? _jsx(MarkdownText, { text: stableText }) : null, pendingText ? _jsx(Text, { children: pendingText }) : null] }));
|
|
518
539
|
}
|
|
519
|
-
export function Transcript({
|
|
520
|
-
const
|
|
540
|
+
export function Transcript({ entries, activeText, activeThinking = '', activeStreamVisible = true, thinkingExpanded = false, detailedTranscript = false, screenReader, }) {
|
|
541
|
+
const theme = useTuiTheme();
|
|
521
542
|
const detailed = thinkingExpanded || detailedTranscript;
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
const pairedResults = new Set(items
|
|
526
|
-
.filter((item) => item.kind === 'tool' && results.has(item.call.id))
|
|
527
|
-
.map((item) => item.call.id));
|
|
528
|
-
const shellResults = new Map(items
|
|
529
|
-
.filter((item) => item.kind === 'shell-result')
|
|
530
|
-
.map((item) => [item.callId, item]));
|
|
531
|
-
const pairedShellResults = new Set(items
|
|
532
|
-
.filter((item) => item.kind === 'shell' && shellResults.has(item.callId))
|
|
533
|
-
.map((item) => item.callId));
|
|
534
|
-
const readGroupStarts = new Map();
|
|
535
|
-
const groupedReadTools = new Set();
|
|
536
|
-
if (!detailed && !screenReader) {
|
|
537
|
-
for (let index = 0; index < items.length; index += 1) {
|
|
538
|
-
const first = items[index];
|
|
539
|
-
if (first?.kind !== 'tool' || first.call.name !== 'Read')
|
|
540
|
-
continue;
|
|
541
|
-
let cursor = index;
|
|
542
|
-
const memberIndexes = [];
|
|
543
|
-
const memberCallIds = new Set();
|
|
544
|
-
while (cursor < items.length) {
|
|
545
|
-
const candidate = items[cursor];
|
|
546
|
-
if (candidate?.kind === 'tool' && candidate.call.name === 'Read') {
|
|
547
|
-
const result = results.get(candidate.call.id);
|
|
548
|
-
if (!result || result.isError)
|
|
549
|
-
break;
|
|
550
|
-
memberIndexes.push(cursor);
|
|
551
|
-
memberCallIds.add(candidate.call.id);
|
|
552
|
-
cursor += 1;
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
if (candidate?.kind === 'tool-result' &&
|
|
556
|
-
memberCallIds.has(candidate.callId)) {
|
|
557
|
-
cursor += 1;
|
|
558
|
-
continue;
|
|
559
|
-
}
|
|
560
|
-
break;
|
|
561
|
-
}
|
|
562
|
-
if (memberIndexes.length === 0)
|
|
563
|
-
continue;
|
|
564
|
-
readGroupStarts.set(index, memberIndexes.length);
|
|
565
|
-
for (const memberIndex of memberIndexes.slice(1)) {
|
|
566
|
-
groupedReadTools.add(memberIndex);
|
|
567
|
-
}
|
|
568
|
-
index = cursor - 1;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
return (_jsxs(Box, { flexDirection: "column", children: [items.map((item, index) => {
|
|
572
|
-
const readCount = readGroupStarts.get(index);
|
|
573
|
-
if (readCount !== undefined) {
|
|
574
|
-
return (_jsxs(Text, { children: [' ', "Read ", readCount, " file", readCount === 1 ? '' : 's', ' ', _jsx(Text, { dimColor: true, children: "(ctrl+o to expand)" })] }, index));
|
|
543
|
+
return (_jsxs(Box, { flexDirection: "column", children: [entries.map((entry, index) => {
|
|
544
|
+
if (entry.kind === 'read-summary') {
|
|
545
|
+
return (_jsxs(Text, { children: [' ', "Read ", entry.count, " file", entry.count === 1 ? '' : 's', ' ', _jsx(Text, { dimColor: true, children: "(ctrl+o to expand)" })] }, entry.key));
|
|
575
546
|
}
|
|
576
|
-
|
|
577
|
-
return null;
|
|
547
|
+
const item = entry.item;
|
|
578
548
|
if (item.kind === 'user') {
|
|
579
|
-
return (_jsxs(Box, { marginTop: index === 0 ? 0 : 1, children: [_jsx(Text, {
|
|
549
|
+
return (_jsxs(Box, { marginTop: index === 0 ? 0 : 1, children: [_jsx(Text, { ...theme.text.productIdentity, bold: true, children: screenReader ? 'You: ' : '❯ ' }), _jsx(Text, { bold: true, children: item.text })] }, entry.key));
|
|
580
550
|
}
|
|
581
551
|
if (item.kind === 'assistant') {
|
|
582
|
-
return (_jsxs(Box, { marginTop: 1, children: [screenReader ? _jsx(Text, { children: "Praxis:" }) : null, !screenReader ? _jsx(Text, {
|
|
552
|
+
return (_jsxs(Box, { marginTop: 1, children: [screenReader ? (_jsx(Text, { ...theme.text.heading, children: "Praxis:" })) : null, !screenReader ? (_jsx(Text, { ...theme.text.focusMarker, children: "\u23FA " })) : null, _jsx(MarkdownText, { text: item.text })] }, entry.key));
|
|
583
553
|
}
|
|
584
554
|
if (item.kind === 'thinking') {
|
|
585
|
-
return (_jsx(ThinkingBlock, { text: item.text, active: false, expanded: detailed, screenReader: screenReader },
|
|
555
|
+
return (_jsx(ThinkingBlock, { text: item.text, active: false, expanded: detailed, screenReader: screenReader }, entry.key));
|
|
586
556
|
}
|
|
587
557
|
if (item.kind === 'compact') {
|
|
588
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, {
|
|
558
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { ...theme.text.focusMarker, italic: true, children: screenReader
|
|
589
559
|
? 'Conversation compacted'
|
|
590
|
-
: '✻ Conversation compacted (ctrl+o for history)' }), detailed ? (_jsx(Box, { marginLeft: screenReader ? 0 : 2, children: _jsx(MarkdownText, { text: item.summary }) })) : null] },
|
|
560
|
+
: '✻ Conversation compacted (ctrl+o for history)' }), detailed ? (_jsx(Box, { marginLeft: screenReader ? 0 : 2, children: _jsx(MarkdownText, { text: item.summary }) })) : null] }, entry.key));
|
|
591
561
|
}
|
|
592
562
|
if (item.kind === 'context') {
|
|
593
|
-
return (_jsx(ContextUsageBlock, { ...item, screenReader: screenReader },
|
|
563
|
+
return (_jsx(ContextUsageBlock, { ...item, screenReader: screenReader }, entry.key));
|
|
594
564
|
}
|
|
595
565
|
if (item.kind === 'tool') {
|
|
596
|
-
|
|
597
|
-
|
|
566
|
+
return (_jsx(ToolTranscriptEntry, { call: item.call, detail: item.detail, ...(entry.kind === 'tool' && entry.result
|
|
567
|
+
? { result: entry.result }
|
|
568
|
+
: {}), detailed: detailed || screenReader }, entry.key));
|
|
598
569
|
}
|
|
599
570
|
if (item.kind === 'tool-result') {
|
|
600
|
-
if (pairedResults.has(item.callId))
|
|
601
|
-
return null;
|
|
602
571
|
const text = item.text.length > 500 ? `${item.text.slice(0, 497)}...` : item.text;
|
|
603
|
-
return (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, {
|
|
572
|
+
return (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, { ...(item.isError ? theme.text.error : theme.text.muted), children: item.isError ? '└ Error' : '└ Result' }), item.isError ? (_jsx(Text, { ...theme.text.error, children: text })) : (_jsx(ToolResultText, { text: text }))] }, entry.key));
|
|
604
573
|
}
|
|
605
574
|
if (item.kind === 'shell') {
|
|
606
|
-
const result =
|
|
575
|
+
const result = entry.kind === 'shell' ? entry.result : undefined;
|
|
607
576
|
const output = result
|
|
608
577
|
? [result.stdout, result.stderr]
|
|
609
578
|
.filter(Boolean)
|
|
@@ -616,22 +585,20 @@ export function Transcript({ items, activeText, activeThinking = '', activeStrea
|
|
|
616
585
|
const lines = contentLines(output);
|
|
617
586
|
const visible = detailed || screenReader ? lines : lines.slice(0, 3);
|
|
618
587
|
const hidden = lines.length - visible.length;
|
|
619
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { children: _jsxs(Text, { bold: true, children: [screenReader ? 'Shell command: ' : '! ', item.command] }) }), result ? (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [lines.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u23BF " })) : (visible.map((line, lineIndex) => (_jsxs(Text, { ...(result.isError ?
|
|
588
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { children: _jsxs(Text, { bold: true, children: [screenReader ? 'Shell command: ' : '! ', item.command] }) }), result ? (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [lines.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u23BF " })) : (visible.map((line, lineIndex) => (_jsxs(Text, { ...(result.isError ? theme.text.error : {}), dimColor: !result.isError, children: [lineIndex === 0 ? '⎿ ' : ' ', line || ' '] }, lineIndex)))), hidden > 0 ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2026 +", hidden, " lines (ctrl+o to expand)"] })) : null] })) : null] }, entry.key));
|
|
620
589
|
}
|
|
621
590
|
if (item.kind === 'shell-result') {
|
|
622
|
-
if (pairedShellResults.has(item.callId))
|
|
623
|
-
return null;
|
|
624
591
|
const output = [item.stdout, item.stderr].filter(Boolean).join('\n');
|
|
625
|
-
return (_jsxs(Text, { ...(item.isError ?
|
|
592
|
+
return (_jsxs(Text, { ...(item.isError ? theme.text.error : {}), children: ["\u23BF ", output] }, entry.key));
|
|
626
593
|
}
|
|
627
594
|
if (item.kind === 'local-result') {
|
|
628
|
-
return (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { dimColor: true, children: ["\u23BF ", item.text] }) },
|
|
595
|
+
return (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { dimColor: true, children: ["\u23BF ", item.text] }) }, entry.key));
|
|
629
596
|
}
|
|
630
|
-
return (_jsxs(Text, { ...(item.kind === 'warning' ?
|
|
631
|
-
}), activeStreamVisible && activeThinking ? (_jsx(ThinkingBlock, { text: activeThinking, active: true, expanded: detailed, screenReader: screenReader })) : activeStreamVisible && activeText ? (_jsxs(Box, { marginTop: 1, children: [screenReader ? (_jsx(Text, { children: "Praxis: " })) : (_jsx(Text, {
|
|
597
|
+
return (_jsxs(Text, { ...(item.kind === 'warning' ? theme.text.error : {}), dimColor: item.kind === 'notice', children: [item.kind === 'warning' ? '⚠ ' : '· ', item.text] }, entry.key));
|
|
598
|
+
}), activeStreamVisible && activeThinking ? (_jsx(ThinkingBlock, { text: activeThinking, active: true, expanded: detailed, screenReader: screenReader })) : activeStreamVisible && activeText ? (_jsxs(Box, { marginTop: 1, children: [screenReader ? (_jsx(Text, { ...theme.text.active, children: "Praxis: " })) : (_jsx(Text, { ...theme.text.active, children: "\u2733 " })), screenReader ? (_jsx(MarkdownText, { text: activeText })) : (_jsx(ActiveStreamText, { text: activeText }))] })) : null] }));
|
|
632
599
|
}
|
|
633
600
|
export function DiffDashboard({ snapshots, sourceIndex, selectedIndex, viewingFile, scrollOffset, width, screenReader, }) {
|
|
634
|
-
const
|
|
601
|
+
const theme = useTuiTheme();
|
|
635
602
|
const source = snapshots[sourceIndex];
|
|
636
603
|
const snapshot = source?.snapshot ?? { files: [], additions: 0, deletions: 0 };
|
|
637
604
|
const selected = snapshot.files[selectedIndex];
|
|
@@ -639,11 +606,12 @@ export function DiffDashboard({ snapshots, sourceIndex, selectedIndex, viewingFi
|
|
|
639
606
|
const line = '─'.repeat(panelWidth);
|
|
640
607
|
if (viewingFile && selected) {
|
|
641
608
|
const lines = visiblePatchLines(selected.patch).slice(scrollOffset, scrollOffset + 18);
|
|
642
|
-
return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null,
|
|
609
|
+
return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', "Uncommitted changes (git diff HEAD)"] }), _jsxs(Text, { children: [' ', snapshots.map((item, index) => (_jsxs(Text, { ...(index === sourceIndex ? theme.text.selectedTab : {}), children: [screenReader && index === sourceIndex ? 'Current source: ' : ' ', item.label, ' '] }, item.label)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', selected.path] }), !screenReader ? (_jsxs(Text, { dimColor: true, children: [" ", '─'.repeat(Math.max(1, panelWidth - 4))] })) : null, lines.map((patchLine, index) => patchLine.startsWith('+') && !patchLine.startsWith('+++') ? (_jsx(SyntaxCodeLine, { prefix: " ", text: patchLine, change: "added" }, `${scrollOffset}-${index}`)) : patchLine.startsWith('-') && !patchLine.startsWith('---') ? (_jsx(SyntaxCodeLine, { prefix: " ", text: patchLine, change: "removed" }, `${scrollOffset}-${index}`)) : (_jsxs(Text, { dimColor: true, children: [' ', patchLine] }, `${scrollOffset}-${index}`))), _jsx(Text, { dimColor: true, children: " \u2191/\u2193 to scroll \u00B7 Esc to back" })] }));
|
|
643
610
|
}
|
|
644
|
-
return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null,
|
|
611
|
+
return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', "Uncommitted changes (git diff HEAD)"] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', snapshots.map((item, index) => (_jsxs(Text, { ...(index === sourceIndex ? theme.text.selectedTab : {}), children: [screenReader && index === sourceIndex ? 'Current source: ' : ' ', item.label, ' '] }, item.label)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', snapshot.files.length, " file", snapshot.files.length === 1 ? '' : 's', ' ', "changed ", _jsxs(Text, { ...theme.text.diffAdded, children: ["+", snapshot.additions] }), ' ', _jsxs(Text, { ...theme.text.diffRemoved, children: ["-", snapshot.deletions] })] }), _jsx(Text, { children: " " }), snapshot.files.length === 0 ? (_jsx(Text, { dimColor: true, children: " No uncommitted changes." })) : (snapshot.files.map((file, index) => (_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [selectionPrefix(index === selectedIndex, screenReader), file.path, ' ', _jsxs(Text, { ...(!screenReader ? theme.text.diffAdded : {}), children: ["+", file.additions] }), ' ', _jsxs(Text, { ...(!screenReader ? theme.text.diffRemoved : {}), children: ["-", file.deletions] })] }, file.path)))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2190/\u2192 to switch source \u00B7 \u2191/\u2193 to select \u00B7 Enter to view \u00B7 Esc to close" })] }));
|
|
645
612
|
}
|
|
646
613
|
export function PermissionDashboard({ tabIndex, selectedIndex, query, rules, recentDenied, retryingDeniedId, workspaceDirectories, width, screenReader, }) {
|
|
614
|
+
const theme = useTuiTheme();
|
|
647
615
|
const tabs = ['Recently denied', 'Allow', 'Ask', 'Deny', 'Workspace'];
|
|
648
616
|
const behavior = ['allow', 'ask', 'deny'][tabIndex - 1];
|
|
649
617
|
const normalizedQuery = query.trim().toLowerCase();
|
|
@@ -667,7 +635,9 @@ export function PermissionDashboard({ tabIndex, selectedIndex, query, rules, rec
|
|
|
667
635
|
: tabIndex === 3
|
|
668
636
|
? 'Praxis Code will reject requests to use denied tools.'
|
|
669
637
|
: 'Praxis Code can read files in the workspace, and make edits when auto-accept edits is on.';
|
|
670
|
-
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null,
|
|
638
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, _jsxs(Text, { ...theme.text.navigation, bold: true, children: [' ', "Permissions"] }), _jsxs(Text, { children: [' ', tabs.map((tab, index) => (_jsxs(Text, { ...(index === tabIndex ? theme.text.selectedTab : {}), children: [screenReader && index === tabIndex ? 'Current tab: ' : ' ', tab, ' '] }, tab)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [" ", description] }), tabIndex >= 1 && tabIndex <= 3 ? (_jsx(Box, { borderStyle: screenReader ? undefined : 'round', paddingX: 1, marginY: 1, children: _jsxs(Text, { ...(query ? {} : { dimColor: true }), children: [screenReader ? 'Search: ' : '⌕ ', query || 'Search…'] }) })) : (_jsx(Text, { children: " " })), tabIndex >= 1 && tabIndex <= 3 ? (['Add a new rule…', ...rows].map((row, index) => (_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [selectionPrefix(index === selectedIndex, screenReader), index + 1, ". ", row] }, `${index}-${row}`)))) : tabIndex === 0 ? (recentDenied.map((action, index) => (_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [selectionPrefix(index === selectedIndex, screenReader), index + 1, ". ", action.id === retryingDeniedId ? '✔' : '✘', ' ', action.display, action.id === retryingDeniedId ? ' (retry)' : '', action.reason ? ` ${action.reason}` : ''] }, action.id)))) : tabIndex === 4 ? (_jsxs(_Fragment, { children: [originalWorkspace ? (_jsxs(Text, { children: [' - ', originalWorkspace.path, " (Original working directory)"] })) : null, additionalWorkspaces.map((directory, index) => (_jsxs(Text, { ...(selectedIndex === index ? theme.text.selectedRow : {}), children: [selectionPrefix(selectedIndex === index, screenReader), index + 1, ". ", directory.path] }, directory.path))), _jsxs(Text, { ...(selectedIndex === additionalWorkspaces.length
|
|
639
|
+
? theme.text.selectedRow
|
|
640
|
+
: {}), children: [selectionPrefix(selectedIndex === additionalWorkspaces.length, screenReader), additionalWorkspaces.length + 1, ". Add directory\u2026"] })] })) : rows.length > 0 ? (rows.map((row, index) => (_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [selectionPrefix(index === selectedIndex, screenReader), index + 1, ". ", row] }, `${index}-${row}`)))) : null, _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: tabIndex === 0 && recentDenied.length > 0
|
|
671
641
|
? 'Enter to approve · r to retry · ↑/↓ to navigate · Esc to cancel'
|
|
672
642
|
: selectedIndex >= 0
|
|
673
643
|
? '↑/↓ navigate · Enter to select · ←/→ to switch · Esc to cancel'
|
|
@@ -683,6 +653,7 @@ const THEME_OPTIONS = [
|
|
|
683
653
|
{ theme: 'light-ansi', label: 'Light mode (ANSI colors only)' },
|
|
684
654
|
];
|
|
685
655
|
export function ThemePicker({ currentTheme, selectedIndex, syntaxHighlightingDisabled, customThemes = [], allowCustomThemes = true, width, screenReader, }) {
|
|
656
|
+
const theme = useTuiTheme();
|
|
686
657
|
const options = [
|
|
687
658
|
...THEME_OPTIONS.map((option) => ({ ...option, customTheme: undefined })),
|
|
688
659
|
...customThemes.map((theme) => ({
|
|
@@ -702,43 +673,45 @@ export function ThemePicker({ currentTheme, selectedIndex, syntaxHighlightingDis
|
|
|
702
673
|
? 'dark'
|
|
703
674
|
: (selected?.theme ??
|
|
704
675
|
(currentTheme.startsWith('custom:') ? 'dark' : currentTheme));
|
|
705
|
-
const preview =
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
: { backgroundColor: syntax.addedHighlight }), children: "Claude" }), _jsx(Text, { ...syntaxColor(syntax.string), children: "!\"" }), '); '] })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 3 " }), _jsx(Text, { ...syntaxColor(syntax.text), children: '}' })] }), _jsxs(Text, { dimColor: true, children: [' ', '╌'.repeat(Math.max(1, Math.min(96, width - 3)))] })] })) : null, _jsxs(Text, { dimColor: true, children: [' ', selected?.theme === '__new__'
|
|
676
|
+
const preview = resolveTuiTheme({
|
|
677
|
+
theme: previewTheme,
|
|
678
|
+
syntaxHighlightingDisabled,
|
|
679
|
+
...(selectedCustomTheme === undefined
|
|
680
|
+
? {}
|
|
681
|
+
: { customTheme: selectedCustomTheme }),
|
|
682
|
+
}, { environment: process.env, screenReader });
|
|
683
|
+
const syntaxColor = (token, change) => preview.syntax(token, change);
|
|
684
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { children: '▔'.repeat(Math.min(100, width)) }) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', "Theme"] }), _jsx(Text, { children: " " }), _jsx(Text, { children: " Choose the text style that looks best with your terminal" }), _jsx(Text, { children: " " }), options.map((option, index) => screenReader ? (_jsxs(Text, { children: [index + 1, ". ", option.label, option.theme === currentTheme ? ' (current)' : '', index === selectedIndex ? ' (focused)' : ''] }, option.theme)) : (_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [index === selectedIndex ? ' ❯ ' : ' ', index + 1, ". ", option.label, option.theme === currentTheme ? ' ✔' : ''] }, option.theme))), _jsx(Text, { children: " " }), screenReader ? (_jsxs(Text, { children: ["Selected: ", options[selectedIndex]?.label] })) : null, !screenReader ? (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: [' ', '╌'.repeat(Math.max(1, Math.min(96, width - 3)))] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 1 " }), _jsx(Text, { ...syntaxColor('keyword'), children: "function" }), _jsx(Text, { ...syntaxColor('text'), children: " " }), _jsx(Text, { ...syntaxColor('identifier'), children: "greet" }), _jsx(Text, { ...syntaxColor('text'), children: '() {' })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 2 - " }), _jsx(Text, { ...syntaxColor('text', 'removed'), children: ' console.log("Hello, World!"); ' })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 2 + " }), _jsxs(Text, { ...syntaxColor('text', 'added'), children: [' console.', _jsx(Text, { ...syntaxColor('identifier'), children: "log" }), '(', _jsx(Text, { ...syntaxColor('string'), children: "\"Hello, " }), _jsx(Text, { ...syntaxColor('addedHighlight'), children: "Claude" }), _jsx(Text, { ...syntaxColor('string'), children: "!\"" }), '); '] })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 3 " }), _jsx(Text, { ...syntaxColor('text'), children: '}' })] }), _jsxs(Text, { dimColor: true, children: [' ', '╌'.repeat(Math.max(1, Math.min(96, width - 3)))] })] })) : null, _jsxs(Text, { dimColor: true, children: [' ', selected?.theme === '__new__'
|
|
715
685
|
? 'Enter to create a custom theme'
|
|
716
686
|
: syntaxHighlightingDisabled
|
|
717
687
|
? 'Syntax highlighting disabled (ctrl+t to enable)'
|
|
718
688
|
: `Syntax theme: ${preview.syntaxTheme} (ctrl+t to disable)`] }), _jsx(Text, { dimColor: true, children: " Enter to select \u00B7 Esc to cancel" })] }));
|
|
719
689
|
}
|
|
720
690
|
export function CustomThemeEditor({ theme, token, value, tokens = [], selectedIndex = 0, query = '', width, screenReader, }) {
|
|
721
|
-
|
|
691
|
+
const semanticTheme = useTuiTheme();
|
|
692
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [_jsx(Text, { ...semanticTheme.text.heading, bold: true, children: theme.name }), token ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsxs(Text, { children: ["\u2588\u2588 ", token] }), _jsxs(Text, { dimColor: true, children: ["preset: ", value || '(not customized)'] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["Value: ", value] }), _jsx(Text, { dimColor: true, children: "Accepts rgb(r,g,b), #rrggbb, ansi256(n), or ansi:name" }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc to cancel" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: ["\u2315 ", query || 'Filter color tokens…'] }), tokens
|
|
722
693
|
.slice(selectedIndex, selectedIndex + 8)
|
|
723
|
-
.map((entry, index) => (_jsxs(Text, {
|
|
694
|
+
.map((entry, index) => (_jsxs(Text, { ...(index === 0 ? semanticTheme.text.selectedRow : {}), children: [dashboardSelectionPrefix(index === 0, screenReader, semanticTheme.noColor), "\u2588\u2588 ", entry, theme.overrides[entry] === undefined ? '' : ' (custom)'] }, entry))), _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to nav \u00B7 Enter to edit \u00B7 Tab to reset \u00B7 Esc to done" })] })), screenReader ? _jsx(Text, { children: "Editing custom theme token" }) : null] }));
|
|
724
695
|
}
|
|
725
696
|
export function ListDashboard({ title, rows, emptyText, selectedIndex, width, screenReader, }) {
|
|
726
|
-
|
|
697
|
+
const theme = useTuiTheme();
|
|
698
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', title] }), _jsx(Text, { children: " " }), rows.length === 0 ? (_jsxs(Text, { dimColor: true, children: [" ", emptyText] })) : (rows.map((row, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [dashboardSelectionPrefix(index === selectedIndex, screenReader, theme.noColor), row.label] }), row.description ? _jsxs(Text, { dimColor: true, children: [" ", row.description] }) : null] }, `${index}-${row.label}`)))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to select \u00B7 Esc to close" })] }));
|
|
727
699
|
}
|
|
728
700
|
export function MemoryDashboard({ autoMemoryEnabled, entries, selectedIndex, openedIndex, loading = false, width, screenReader, dataPlane = 'claude', }) {
|
|
729
|
-
const
|
|
701
|
+
const theme = useTuiTheme();
|
|
730
702
|
const panelWidth = Math.min(100, width);
|
|
731
|
-
return (_jsxs(Box, { flexDirection: "column", width: panelWidth, children: [!screenReader ? (_jsx(Text, {
|
|
703
|
+
return (_jsxs(Box, { flexDirection: "column", width: panelWidth, children: [!screenReader ? (_jsx(Text, { ...theme.text.focusMarker, children: '─'.repeat(panelWidth) })) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', "Memory"] }), _jsx(Text, { children: " " }), loading ? (_jsx(Text, { dimColor: true, children: " \u2736 Loading memory files\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [" Auto-memory: ", autoMemoryEnabled ? 'on' : 'off'] }), _jsx(Text, { children: " " }), entries.map((entry, index) => (_jsxs(Box, { children: [_jsx(Box, { width: Math.max(24, Math.min(52, panelWidth - 28)), children: _jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [dashboardSelectionPrefix(index === selectedIndex, screenReader, theme.noColor), index + 1, ". ", entry.label, openedIndex === index ? ' ✔' : ''] }) }), entry.annotation ? (_jsx(Text, { dimColor: true, children: entry.annotation })) : null] }, `${entry.kind}-${entry.path}`)))] })), _jsx(Text, { children: " " }), dataPlane === 'claude' ? (_jsxs(Text, { dimColor: true, children: [' ', "Learn more: https://code.claude.com/docs/en/memory"] })) : null, _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, italic: true, children: "Enter to confirm \u00B7 Esc to cancel" })] }));
|
|
732
704
|
}
|
|
733
705
|
function selectedWindow(length, selectedIndex, size) {
|
|
734
706
|
return Math.max(0, Math.min(selectedIndex - Math.floor(size / 2), Math.max(0, length - size)));
|
|
735
707
|
}
|
|
736
708
|
export function HookDashboard({ configuration, depth, eventIndex, matcherIndex, hookIndex, width, screenReader, }) {
|
|
709
|
+
const theme = useTuiTheme();
|
|
737
710
|
const event = configuration.events[eventIndex];
|
|
738
711
|
const matcher = event?.matchers[matcherIndex];
|
|
739
712
|
const hook = matcher?.hooks[hookIndex];
|
|
740
713
|
if (depth === 'detail') {
|
|
741
|
-
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.max(12, Math.min(100, width))) })) : null,
|
|
714
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.max(12, Math.min(100, width))) })) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', "Hook details"] }), _jsxs(Text, { children: [" Event: ", event?.name ?? 'Hooks'] }), _jsxs(Text, { children: [" Matcher: ", matcher?.matcher ?? '(all)'] }), _jsxs(Text, { children: [" Type: ", hook?.type ?? 'command'] }), _jsxs(Text, { children: [" Source: ", hook?.scopeLabel ?? 'Settings'] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [" ", hook?.label ?? ''] }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "Esc to go back" })] }));
|
|
742
715
|
}
|
|
743
716
|
const rows = depth === 'events'
|
|
744
717
|
? configuration.events
|
|
@@ -754,7 +727,7 @@ export function HookDashboard({ configuration, depth, eventIndex, matcherIndex,
|
|
|
754
727
|
const start = selectedWindow(rows.length, selectedIndex, maxVisible);
|
|
755
728
|
const visible = rows.slice(start, start + maxVisible);
|
|
756
729
|
const line = '─'.repeat(Math.max(12, Math.min(100, width)));
|
|
757
|
-
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Text, { bold: true, children: [' ', depth === 'events'
|
|
730
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', depth === 'events'
|
|
758
731
|
? TUI_HOOK_MENU.title
|
|
759
732
|
: depth === 'matchers'
|
|
760
733
|
? `${event?.name ?? 'Hooks'} - Matchers`
|
|
@@ -765,7 +738,7 @@ export function HookDashboard({ configuration, depth, eventIndex, matcherIndex,
|
|
|
765
738
|
const selected = index === selectedIndex;
|
|
766
739
|
if (depth === 'events') {
|
|
767
740
|
const item = row;
|
|
768
|
-
return (_jsxs(Box, { children: [_jsx(Box, { width: 30, children: _jsxs(Text, {
|
|
741
|
+
return (_jsxs(Box, { children: [_jsx(Box, { width: 30, children: _jsxs(Text, { ...(selected ? theme.text.selectedRow : {}), children: [screenReader && selected
|
|
769
742
|
? 'Selected: '
|
|
770
743
|
: selected
|
|
771
744
|
? '❯ '
|
|
@@ -775,14 +748,14 @@ export function HookDashboard({ configuration, depth, eventIndex, matcherIndex,
|
|
|
775
748
|
}
|
|
776
749
|
if (depth === 'matchers') {
|
|
777
750
|
const item = row;
|
|
778
|
-
return (_jsxs(Text, {
|
|
751
|
+
return (_jsxs(Text, { ...(selected ? theme.text.selectedRow : {}), children: [screenReader && selected
|
|
779
752
|
? 'Selected: '
|
|
780
753
|
: selected
|
|
781
754
|
? '❯ '
|
|
782
755
|
: ' ', index + 1, ". [", item.scope, "] ", item.matcher, " ", item.hooks.length, ' ', item.hooks.length === 1 ? 'hook' : 'hooks'] }, `${item.scope}-${item.matcher}-${index}`));
|
|
783
756
|
}
|
|
784
757
|
const item = row;
|
|
785
|
-
return (_jsxs(Box, { children: [_jsx(Box, { flexGrow: 1, children: _jsxs(Text, {
|
|
758
|
+
return (_jsxs(Box, { children: [_jsx(Box, { flexGrow: 1, children: _jsxs(Text, { ...(selected ? theme.text.selectedRow : {}), wrap: "truncate-end", children: [screenReader && selected
|
|
786
759
|
? 'Selected: '
|
|
787
760
|
: selected
|
|
788
761
|
? '❯ '
|
|
@@ -792,7 +765,7 @@ export function HookDashboard({ configuration, depth, eventIndex, matcherIndex,
|
|
|
792
765
|
: 'Enter to confirm · Esc to cancel' })] }));
|
|
793
766
|
}
|
|
794
767
|
export function BtwPanel({ entries, selectedIndex, scrollOffset, copied, width, screenReader, }) {
|
|
795
|
-
const
|
|
768
|
+
const theme = useTuiTheme();
|
|
796
769
|
const selected = entries[selectedIndex];
|
|
797
770
|
const lines = selected?.answer.split('\n') ?? [];
|
|
798
771
|
const visibleLines = lines.slice(scrollOffset, scrollOffset + 16);
|
|
@@ -816,22 +789,22 @@ export function BtwPanel({ entries, selectedIndex, scrollOffset, copied, width,
|
|
|
816
789
|
].join(' · ');
|
|
817
790
|
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, entries.map((entry, index) => (_jsxs(Text, { dimColor: index !== selectedIndex, children: [' ', "/btw ", entry.question] }, entry.id))), _jsx(Text, { children: " " }), selected?.status === 'answering' ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [" ", ' ', "\u00B7 Answering\u2026"] }), selected.answer
|
|
818
791
|
? visibleLines.map((line, index) => (_jsxs(Text, { children: [' ', ' ', line || ' '] }, `${scrollOffset + index}-${line}`)))
|
|
819
|
-
: null] })) : selected?.status === 'forking' ? (_jsxs(Text, { children: [" ", ' ', "\u00B7 Forking\u2026"] })) : selected?.status === 'error' ? (_jsxs(Text, {
|
|
792
|
+
: null] })) : selected?.status === 'forking' ? (_jsxs(Text, { children: [" ", ' ', "\u00B7 Forking\u2026"] })) : selected?.status === 'error' ? (_jsxs(Text, { ...theme.text.error, children: [' ', ' ', selected.error ?? 'Side question failed'] })) : (visibleLines.map((line, index) => (_jsxs(Text, { children: [' ', ' ', line || ' '] }, `${scrollOffset + index}-${line}`)))), _jsx(Text, { children: " " }), _jsxs(Text, { dimColor: true, children: [" ", footer] })] }));
|
|
820
793
|
}
|
|
821
794
|
export function SessionPicker({ sessions, selectedIndex, screenReader, query = '', }) {
|
|
822
|
-
const
|
|
795
|
+
const theme = useTuiTheme();
|
|
823
796
|
const maxVisible = 8;
|
|
824
797
|
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), sessions.length - maxVisible));
|
|
825
798
|
const visible = sessions.slice(start, start + maxVisible);
|
|
826
|
-
return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: '─'.repeat(80) }) : null,
|
|
799
|
+
return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: '─'.repeat(80) }) : null, _jsxs(Text, { ...theme.text.heading, bold: true, children: [' ', "Resume session"] }), _jsx(Box, { borderStyle: screenReader ? undefined : 'round', ...theme.surface.neutralBorder, paddingX: screenReader ? 0 : 1, marginY: 1, children: _jsxs(Text, { ...(query ? {} : { dimColor: true }), children: ["\u2315 ", query || 'Search…'] }) }), start > 0 ? _jsxs(Text, { dimColor: true, children: [" \u2191 ", start, " earlier"] }) : null, visible.length === 0 ? _jsx(Text, { dimColor: true, children: "No sessions found." }) : null, visible.map((session, visibleIndex) => {
|
|
827
800
|
const index = start + visibleIndex;
|
|
828
|
-
return (_jsxs(Box, { children: [_jsxs(Text, { ...(index === selectedIndex ?
|
|
801
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), bold: index === selectedIndex, children: [dashboardSelectionPrefix(index === selectedIndex, screenReader, theme.noColor), session
|
|
829
802
|
? (session.name ?? session.lastPrompt ?? 'Untitled')
|
|
830
803
|
: 'Start a new session'] }), session ? (_jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", session.sessionId, " \u00B7 ", session.status] })) : null] }, session?.sessionId ?? 'new'));
|
|
831
804
|
}), start + visible.length < sessions.length ? (_jsxs(Text, { dimColor: true, children: [" \u2193 ", sessions.length - start - visible.length, " more"] })) : null, !screenReader ? (_jsx(Text, { dimColor: true, children: "\u2191/\u2193 to navigate \u00B7 Enter to select \u00B7 Type to search \u00B7 Esc to cancel" })) : null] }));
|
|
832
805
|
}
|
|
833
806
|
export function CommandPalette({ commands, selectedIndex, width, screenReader, }) {
|
|
834
|
-
const
|
|
807
|
+
const theme = useTuiTheme();
|
|
835
808
|
const paletteWidth = Math.max(1, Math.min(100, width));
|
|
836
809
|
const nameWidth = Math.min(30, paletteWidth);
|
|
837
810
|
const descriptionWidth = Math.max(0, paletteWidth - nameWidth);
|
|
@@ -844,19 +817,21 @@ export function CommandPalette({ commands, selectedIndex, width, screenReader, }
|
|
|
844
817
|
return (_jsx(Box, { flexDirection: "column", width: paletteWidth, children: visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No matching commands." })) : (visible.map((command, visibleIndex) => {
|
|
845
818
|
const index = start + visibleIndex;
|
|
846
819
|
const selected = index === selectedIndex;
|
|
847
|
-
return (_jsxs(Box, { flexDirection: "row", width: paletteWidth, children: [_jsx(Box, { width: nameWidth, flexShrink: 0, children: _jsxs(Text, { wrap: "truncate-end", ...(selected ?
|
|
820
|
+
return (_jsxs(Box, { flexDirection: "row", width: paletteWidth, children: [_jsx(Box, { width: nameWidth, flexShrink: 0, children: _jsxs(Text, { wrap: "truncate-end", ...(selected ? theme.text.selectedRow : {}), children: ["/", command.name] }) }), _jsx(Box, { width: descriptionWidth, flexShrink: 1, children: _jsx(Text, { dimColor: true, wrap: "truncate-end", children: command.description }) })] }, command.name));
|
|
848
821
|
})) }));
|
|
849
822
|
}
|
|
850
823
|
export function FilePicker({ entries, selectedIndex, width, screenReader, }) {
|
|
824
|
+
const theme = useTuiTheme();
|
|
851
825
|
const maxVisible = 12;
|
|
852
826
|
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, entries.length - maxVisible)));
|
|
853
827
|
const visible = entries.slice(start, start + maxVisible);
|
|
854
828
|
return (_jsx(Box, { flexDirection: "column", width: Math.min(100, width), children: visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No matching files." })) : (visible.map((entry, visibleIndex) => {
|
|
855
829
|
const index = start + visibleIndex;
|
|
856
|
-
return (_jsxs(Text, {
|
|
830
|
+
return (_jsxs(Text, { ...(index === selectedIndex ? theme.text.selectedRow : {}), children: [screenReader && index === selectedIndex ? 'Selected: ' : '+ ', entry.path] }, entry.path));
|
|
857
831
|
})) }));
|
|
858
832
|
}
|
|
859
833
|
export function MentionPicker({ entries, selectedIndex, width, screenReader, }) {
|
|
834
|
+
const theme = useTuiTheme();
|
|
860
835
|
const maxVisible = 12;
|
|
861
836
|
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, entries.length - maxVisible)));
|
|
862
837
|
const visible = entries.slice(start, start + maxVisible);
|
|
@@ -864,9 +839,9 @@ export function MentionPicker({ entries, selectedIndex, width, screenReader, })
|
|
|
864
839
|
const index = start + visibleIndex;
|
|
865
840
|
const selected = index === selectedIndex;
|
|
866
841
|
if (entry.kind === 'agent') {
|
|
867
|
-
return (_jsxs(Text, {
|
|
842
|
+
return (_jsxs(Text, { ...(selected ? theme.text.selectedRow : {}), ...(screenReader ? {} : { wrap: 'truncate-end' }), children: [screenReader && selected ? 'Selected agent: ' : '* ', entry.name, screenReader ? '' : ' (agent)', entry.description ? ` – ${entry.description}` : ''] }, `agent:${entry.name}`));
|
|
868
843
|
}
|
|
869
|
-
return (_jsxs(Text, {
|
|
844
|
+
return (_jsxs(Text, { ...(selected ? theme.text.selectedRow : {}), ...(screenReader ? {} : { wrap: 'truncate-end' }), children: [screenReader && selected ? 'Selected: ' : '+ ', entry.path] }, `file:${entry.path}`));
|
|
870
845
|
})) }));
|
|
871
846
|
}
|
|
872
847
|
const SHORTCUT_ROWS = [
|
|
@@ -896,38 +871,34 @@ export function ShortcutHelp({ width }) {
|
|
|
896
871
|
return (_jsx(Box, { flexDirection: "column", width: Math.min(100, width), children: SHORTCUT_ROWS.map((row, rowIndex) => wide ? (_jsx(Box, { flexDirection: "row", children: row.map((cell, cellIndex) => (_jsx(Box, { width: cellIndex === 2 ? undefined : '33%', children: _jsx(Text, { dimColor: true, children: cell }) }, cellIndex))) }, rowIndex)) : (row.filter(Boolean).map((cell, cellIndex) => (_jsx(Text, { dimColor: true, children: cell }, `${rowIndex}-${cellIndex}`))))) }));
|
|
897
872
|
}
|
|
898
873
|
export function HelpMenu({ tabIndex, selectedIndex, builtinCommands, customCommands, width, screenReader, }) {
|
|
899
|
-
const
|
|
874
|
+
const theme = useTuiTheme();
|
|
900
875
|
const tabs = ['General', 'Commands', 'Custom commands'];
|
|
901
876
|
const commands = tabIndex === 1 ? builtinCommands : customCommands;
|
|
902
877
|
const maxVisible = 10;
|
|
903
878
|
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, commands.length - maxVisible)));
|
|
904
879
|
const visible = commands.slice(start, start + maxVisible);
|
|
905
880
|
const line = '─'.repeat(Math.max(12, Math.min(100, width)));
|
|
906
|
-
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Box, { children: [
|
|
907
|
-
? { color: palette.brand, bold: true }
|
|
908
|
-
: {}), children: [' ', tab, ' '] }, tab)))] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: tabIndex === 0 ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: "Praxis understands your codebase, makes edits with your permission, and executes commands from your terminal." }), _jsx(Text, { bold: true, children: "Shortcuts" }), _jsx(ShortcutHelp, { width: width })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, children: tabIndex === 1
|
|
881
|
+
return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Box, { children: [_jsxs(Text, { ...theme.text.navigation, bold: true, children: [' ', "Help", ' '] }), tabs.map((tab, index) => (_jsxs(Text, { ...(index === tabIndex ? theme.text.selectedTab : {}), children: [' ', tab, ' '] }, tab)))] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: tabIndex === 0 ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: "Praxis understands your codebase, makes edits with your permission, and executes commands from your terminal." }), _jsx(Text, { ...theme.text.heading, bold: true, children: "Shortcuts" }), _jsx(ShortcutHelp, { width: width })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, children: tabIndex === 1
|
|
909
882
|
? 'Browse default commands'
|
|
910
883
|
: 'Browse shared commands and skills' }), visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No commands found." })) : (visible.map((command, visibleIndex) => {
|
|
911
884
|
const index = start + visibleIndex;
|
|
912
885
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { ...(index === selectedIndex
|
|
913
|
-
?
|
|
886
|
+
? theme.text.selectedRow
|
|
914
887
|
: {}), children: [index === selectedIndex ? '↓ ' : ' ', "/", command.name] }), _jsxs(Text, { dimColor: true, children: [" ", command.description] })] }, command.name));
|
|
915
888
|
}))] })) }), _jsx(Text, { dimColor: true, children: "\u2190/\u2192 to switch \u00B7 \u2191/\u2193 to navigate \u00B7 Esc to cancel" })] }));
|
|
916
889
|
}
|
|
917
890
|
export function SelectionMenu({ title, description, options, selectedIndex, footer, width, screenReader, }) {
|
|
918
|
-
const
|
|
891
|
+
const theme = useTuiTheme();
|
|
919
892
|
const maxVisible = 7;
|
|
920
893
|
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, options.length - maxVisible)));
|
|
921
894
|
const visible = options.slice(start, start + maxVisible);
|
|
922
895
|
const current = options.find((option) => option.selected);
|
|
923
896
|
const maxLabelWidth = options.reduce((max, option, index) => Math.max(max, `${index + 1}. ${option.label}`.length), 0);
|
|
924
|
-
return (_jsxs(Box, { borderStyle: screenReader ? undefined : 'round',
|
|
897
|
+
return (_jsxs(Box, { borderStyle: screenReader ? undefined : 'round', ...theme.surface.neutralBorder, flexDirection: "column", marginTop: 1, paddingX: screenReader ? 0 : 1, width: screenReader ? undefined : Math.min(80, width), children: [_jsx(Text, { ...theme.text.heading, bold: true, children: title }), description ? _jsx(Text, { dimColor: true, children: description }) : null, screenReader && current ? _jsxs(Text, { children: ["Current: ", current.label] }) : null, visible.map((option, visibleIndex) => {
|
|
925
898
|
const index = start + visibleIndex;
|
|
926
899
|
const selected = index === selectedIndex;
|
|
927
900
|
const rowLabel = `${index + 1}. ${option.label}`;
|
|
928
|
-
return (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { ...(!screenReader && selected
|
|
929
|
-
? { color: palette.brand, bold: true }
|
|
930
|
-
: {}), children: [selectionPrefix(selected, screenReader), rowLabel, !screenReader && option.selected ? ' ✔' : '', option.description ? (_jsxs(Text, { dimColor: true, children: [' '.repeat(Math.max(2, maxLabelWidth -
|
|
901
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { ...(!screenReader && selected ? theme.text.selectedRow : {}), children: [selectionPrefix(selected, screenReader), rowLabel, !screenReader && option.selected ? ' ✔' : '', option.description ? (_jsxs(Text, { dimColor: true, children: [' '.repeat(Math.max(2, maxLabelWidth -
|
|
931
902
|
rowLabel.length -
|
|
932
903
|
(option.selected && !screenReader ? 2 : 0))), option.description] })) : null] }) }, `${index}-${option.label}`));
|
|
933
904
|
}), start > 0 || start + visible.length < options.length ? (_jsxs(Text, { dimColor: true, children: [start > 0 ? `↑ ${start} earlier` : '', start > 0 && start + visible.length < options.length ? ' · ' : '', start + visible.length < options.length
|
|
@@ -935,27 +906,26 @@ export function SelectionMenu({ title, description, options, selectedIndex, foot
|
|
|
935
906
|
: ''] })) : null, _jsx(Text, { dimColor: true, children: footer })] }));
|
|
936
907
|
}
|
|
937
908
|
export function ModelMenu({ options, effort, selectedIndex, width, screenReader, }) {
|
|
938
|
-
const
|
|
909
|
+
const theme = useTuiTheme();
|
|
939
910
|
const current = options.find((option) => option.selected);
|
|
940
911
|
const maxLabelWidth = options.reduce((max, option, index) => Math.max(max, `${index + 1}. ${option.label}`.length), 0);
|
|
941
|
-
return (_jsxs(Box, { borderStyle: screenReader ? undefined : 'round',
|
|
912
|
+
return (_jsxs(Box, { borderStyle: screenReader ? undefined : 'round', ...theme.surface.neutralBorder, flexDirection: "column", marginTop: 1, paddingX: screenReader ? 0 : 1, width: screenReader ? undefined : Math.min(80, width), children: [_jsx(Text, { ...theme.text.heading, bold: true, children: "Select model" }), _jsx(Text, { dimColor: true, children: 'Switch between models. Your pick applies to this and future Praxis Code sessions. For other model names, specify with --model.' }), screenReader && current ? _jsxs(Text, { children: ["Current: ", current.label] }) : null, options.map((option, index) => {
|
|
942
913
|
const selected = index === selectedIndex;
|
|
943
914
|
const rowLabel = `${index + 1}. ${option.label}`;
|
|
944
|
-
return (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { ...(!screenReader && selected
|
|
945
|
-
? { color: palette.brand, bold: true }
|
|
946
|
-
: {}), children: [selectionPrefix(selected, screenReader), rowLabel, !screenReader && option.selected ? ' ✔' : '', option.description ? (_jsxs(Text, { dimColor: true, children: [' '.repeat(Math.max(2, maxLabelWidth -
|
|
915
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { ...(!screenReader && selected ? theme.text.selectedRow : {}), children: [selectionPrefix(selected, screenReader), rowLabel, !screenReader && option.selected ? ' ✔' : '', option.description ? (_jsxs(Text, { dimColor: true, children: [' '.repeat(Math.max(2, maxLabelWidth -
|
|
947
916
|
rowLabel.length -
|
|
948
917
|
(option.selected && !screenReader ? 2 : 0))), option.description] })) : null] }) }, `${index}-${option.label}`));
|
|
949
|
-
}), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: [_jsx(Text, {
|
|
918
|
+
}), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: [_jsx(Text, { ...theme.text.focusMarker, children: "\u25CF " }), effort.charAt(0).toUpperCase() + effort.slice(1), " effort (default)", _jsx(Text, { dimColor: true, children: " \u2190/\u2192 to adjust" })] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to select \u00B7 Esc to cancel" }) })] }));
|
|
950
919
|
}
|
|
951
920
|
function ComposerInput({ input, cursor }) {
|
|
952
|
-
const
|
|
921
|
+
const theme = useTuiTheme();
|
|
953
922
|
const { before, current, after } = composerEditorSegments({
|
|
954
923
|
text: input,
|
|
955
924
|
cursor,
|
|
956
925
|
});
|
|
957
926
|
const cursorText = current === '\n' ? '↵' : (current ?? ' ');
|
|
958
|
-
|
|
927
|
+
const noColorCursorText = current === undefined ? ` ${'\u0332'}` : `${cursorText}\u0332`;
|
|
928
|
+
return (_jsxs(Text, { children: [before, _jsx(Text, { ...theme.text.inputCursor, children: theme.noColor ? noColorCursorText : cursorText }), after] }));
|
|
959
929
|
}
|
|
960
930
|
export function ExternalEditorWait({ screenReader, }) {
|
|
961
931
|
if (screenReader)
|
|
@@ -963,7 +933,7 @@ export function ExternalEditorWait({ screenReader, }) {
|
|
|
963
933
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }), _jsx(Text, { children: "Save and close editor to continue..." }), _jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" })] }));
|
|
964
934
|
}
|
|
965
935
|
export function Composer({ input, cursor, busy, clipboardBusy = false, status, display, usage, costUsd, width, screenReader, hasThinking = false, thinkingExpanded = false, shortcutsVisible = false, shellMode = false, footerMessage, reduceMotion = false, progressBar = true, turnDuration, editorMode = 'normal', prStatus, sessionColor, commandArgumentHint, }) {
|
|
966
|
-
const
|
|
936
|
+
const theme = useTuiTheme();
|
|
967
937
|
const [spinnerIndex, setSpinnerIndex] = useState(0);
|
|
968
938
|
useEffect(() => {
|
|
969
939
|
if (!busy || screenReader || reduceMotion)
|
|
@@ -981,7 +951,7 @@ export function Composer({ input, cursor, busy, clipboardBusy = false, status, d
|
|
|
981
951
|
: `Prompt: ${input}` }));
|
|
982
952
|
const { lineWidth, footerWidth, showEditorHint } = composerLayoutForWidth(width);
|
|
983
953
|
const line = '─'.repeat(lineWidth);
|
|
984
|
-
const separatorColor = sessionColor === undefined ? undefined :
|
|
954
|
+
const separatorColor = sessionColor === undefined ? undefined : theme.session(sessionColor);
|
|
985
955
|
const footerMode = `⏵⏵ ${permissionLabel(display.permissionMode)}`;
|
|
986
956
|
const footerCompactMode = `⏵⏵ ${compactPermissionLabel(display.permissionMode)}`;
|
|
987
957
|
const footerLeft = composerFooterLeft(footerWidth, busy, hasThinking, thinkingExpanded, footerMode, footerCompactMode);
|
|
@@ -994,14 +964,14 @@ export function Composer({ input, cursor, busy, clipboardBusy = false, status, d
|
|
|
994
964
|
? ` · ${usage.cacheReadInputTokens} cached`
|
|
995
965
|
: '', costUsd === undefined ? '' : ` · $${costUsd.toFixed(6)}`] })) : null, _jsx(Text, { ...(separatorColor === undefined
|
|
996
966
|
? { dimColor: true }
|
|
997
|
-
: { color: separatorColor }), children: line }), clipboardBusy ? (_jsx(Text, { children: "Pasting\u2026" })) : busy ? (_jsxs(Text, { children: [progressBar ? (_jsx(Text, {
|
|
967
|
+
: { color: separatorColor }), children: line }), clipboardBusy ? (_jsx(Text, { children: "Pasting\u2026" })) : busy ? (_jsxs(Text, { children: [progressBar ? (_jsx(Text, { ...theme.text.focusMarker, children: reduceMotion ? '•' : SPINNER[spinnerIndex] })) : null, ' ', _jsxs(Text, { ...theme.text.active, children: [status, "\u2026"] }), ' ', _jsx(Text, { dimColor: true, children: "\u00B7 esc to interrupt" })] })) : (_jsxs(Text, { children: [_jsx(Text, { ...(shellMode ? theme.text.shellMode : theme.text.inputMarker), children: shellMode ? '! ' : '❯ ' }), input ? (_jsxs(Text, { children: [_jsx(ComposerInput, { cursor: cursor ?? Array.from(input).length, input: input }), commandArgumentHint ? (_jsxs(Text, { dimColor: true, children: [input.endsWith(' ') ? '' : ' ', commandArgumentHint] })) : null] })) : (_jsx(Text, { dimColor: true, children: shellMode
|
|
998
968
|
? 'Enter a shell command'
|
|
999
969
|
: 'Try "review this project"' }))] })), _jsx(Text, { ...(separatorColor === undefined
|
|
1000
970
|
? { dimColor: true }
|
|
1001
|
-
: { color: separatorColor }), children: line }), shortcutsVisible ? (_jsx(ShortcutHelp, { width: width })) : (_jsx(Box, { width: footerWidth, children: _jsx(Text, { wrap: "truncate", children: shellMode ? (_jsx(Text, { dimColor: true, children: "! for bash mode" })) : footerMessage ? (_jsxs(Text, { children: [_jsxs(Text, { dimColor: true, children: [footerMessageLeft, " \u00B7 "] }), footerMessage.isError ? (_jsx(Text, {
|
|
971
|
+
: { color: separatorColor }), children: line }), shortcutsVisible ? (_jsx(ShortcutHelp, { width: width })) : (_jsx(Box, { width: footerWidth, children: _jsx(Text, { wrap: "truncate", children: shellMode ? (_jsx(Text, { dimColor: true, children: "! for bash mode" })) : footerMessage ? (_jsxs(Text, { children: [_jsxs(Text, { dimColor: true, children: [footerMessageLeft, " \u00B7 "] }), footerMessage.isError ? (_jsx(Text, { ...theme.text.error, children: footerMessage.text })) : (_jsx(Text, { dimColor: true, children: footerMessage.text }))] })) : prStatus ? (_jsxs(Text, { children: [_jsxs(Text, { dimColor: true, children: [footerLeft, " \u00B7 "] }), _jsx(Text, { dimColor: true, children: prStatus })] })) : turnDuration ? (_jsxs(Text, { children: [_jsxs(Text, { dimColor: true, children: [footerLeft, " \u00B7 "] }), _jsxs(Text, { dimColor: true, children: ["Cooked for ", turnDuration] })] })) : display.effort ? (_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: footerLeft }), _jsx(Text, { dimColor: true, children: " \u00B7 " }), _jsxs(Text, { ...theme.text.focusMarker, children: ["\u25CF ", display.effort] }), showEditorHint ? (_jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", editorMode === 'vim' ? 'vim' : '/effort'] })) : null] })) : (_jsx(Text, { dimColor: true, children: footerLeft })) }) }))] }));
|
|
1002
972
|
}
|
|
1003
973
|
export function DialogFrame({ title, children, screenReader, }) {
|
|
1004
|
-
const
|
|
1005
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: screenReader ? undefined : 'round',
|
|
974
|
+
const theme = useTuiTheme();
|
|
975
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: screenReader ? undefined : 'round', ...theme.surface.decision, paddingX: screenReader ? 0 : 1, marginTop: 1, children: [_jsx(Text, { ...theme.text.heading, ...theme.text.warning, bold: true, children: title }), children] }));
|
|
1006
976
|
}
|
|
1007
977
|
//# sourceMappingURL=claude-style.js.map
|