praxis-agent 0.35.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 +5 -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 -4
- package/dist/application/session-service.js +528 -434
- package/dist/application/subagent-service.js +358 -177
- 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 +2 -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 +264 -204
- package/dist/cli/tui/claude-style.js +154 -130
- 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/tui-interaction-router.d.ts +78 -0
- package/dist/cli/tui/tui-interaction-router.js +127 -0
- package/dist/cli-runtime.d.ts +2 -2
- package/dist/core/agent-orchestration.d.ts +31 -0
- package/dist/core/agent-orchestration.js +235 -0
- package/dist/core/runtime.d.ts +5 -0
- package/dist/core/runtime.js +15 -1
- package/dist/persistence/claude-job-store.d.ts +58 -0
- package/dist/persistence/claude-job-store.js +483 -1
- 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/package.json +1 -1
|
@@ -47,10 +47,19 @@ export function projectBackgroundBashTask(snapshot) {
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
export function projectBackgroundAgentTask(snapshot) {
|
|
50
|
+
const status = snapshot.status === 'cancelled'
|
|
51
|
+
? 'stopped'
|
|
52
|
+
: snapshot.status === 'orphaned'
|
|
53
|
+
? 'interrupted'
|
|
54
|
+
: snapshot.status === 'queued' ||
|
|
55
|
+
snapshot.status === 'waiting' ||
|
|
56
|
+
snapshot.status === 'cancelling'
|
|
57
|
+
? 'running'
|
|
58
|
+
: snapshot.status;
|
|
50
59
|
return {
|
|
51
60
|
id: snapshot.agentId,
|
|
52
61
|
kind: 'agent',
|
|
53
|
-
status
|
|
62
|
+
status,
|
|
54
63
|
label: snapshot.name ?? snapshot.description,
|
|
55
64
|
output: snapshot.result?.text ?? snapshot.error ?? '',
|
|
56
65
|
startedAtMs: snapshot.startedAt,
|
package/dist/cli/tui/theme.d.ts
CHANGED
|
@@ -36,20 +36,63 @@ export interface TuiPalette {
|
|
|
36
36
|
syntaxTheme: 'Monokai Extended' | 'GitHub' | 'ansi';
|
|
37
37
|
syntax: TuiSyntaxPalette;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
/** Ink-compatible text attributes owned by the Praxis semantic theme. */
|
|
40
|
+
export interface TuiTextStyle {
|
|
41
|
+
readonly color?: string;
|
|
42
|
+
readonly backgroundColor?: string;
|
|
43
|
+
readonly bold?: boolean;
|
|
44
|
+
readonly dimColor?: boolean;
|
|
45
|
+
readonly italic?: boolean;
|
|
46
|
+
readonly underline?: boolean;
|
|
47
|
+
readonly inverse?: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** Ink-compatible surface attributes owned by the Praxis semantic theme. */
|
|
50
|
+
export interface TuiSurfaceStyle {
|
|
51
|
+
readonly borderColor?: string;
|
|
52
|
+
readonly backgroundColor?: string;
|
|
53
|
+
}
|
|
54
|
+
export declare const TUI_TEXT_ROLES: readonly ["body", "productIdentity", "heading", "navigation", "selectedRow", "selectedTab", "focusMarker", "inputMarker", "inputCursor", "muted", "link", "active", "info", "success", "warning", "permission", "error", "diffAdded", "diffRemoved", "shellMode"];
|
|
55
|
+
export type TuiTextRole = (typeof TUI_TEXT_ROLES)[number];
|
|
56
|
+
export declare const TUI_SURFACE_ROLES: readonly ["neutralBorder", "separator", "selectedRow", "selectedTab", "input", "decision", "error"];
|
|
57
|
+
export type TuiSurfaceRole = (typeof TUI_SURFACE_ROLES)[number];
|
|
58
|
+
export interface TuiSemanticTheme {
|
|
59
|
+
readonly profile: TuiTheme;
|
|
60
|
+
readonly dark: boolean;
|
|
61
|
+
readonly ansiOnly: boolean;
|
|
62
|
+
readonly terminalColorCapability: TerminalColorCapability;
|
|
63
|
+
readonly syntaxHighlightingDisabled: boolean;
|
|
64
|
+
readonly screenReader: boolean;
|
|
65
|
+
readonly noColor: boolean;
|
|
66
|
+
readonly syntaxTheme: TuiPalette['syntaxTheme'];
|
|
67
|
+
readonly text: Readonly<Record<TuiTextRole, TuiTextStyle>>;
|
|
68
|
+
readonly surface: Readonly<Record<TuiSurfaceRole, TuiSurfaceStyle>>;
|
|
69
|
+
syntax(token: TuiSyntaxToken, change?: 'added' | 'removed'): Readonly<{
|
|
70
|
+
color?: string;
|
|
71
|
+
backgroundColor?: string;
|
|
72
|
+
}>;
|
|
73
|
+
session(agentColor: AgentColorName): string | undefined;
|
|
74
|
+
}
|
|
75
|
+
export interface TuiThemePresentationOptions {
|
|
76
|
+
environment?: TerminalEnvironment;
|
|
77
|
+
screenReader?: boolean;
|
|
78
|
+
}
|
|
79
|
+
export type TuiSyntaxToken = 'text' | 'keyword' | 'identifier' | 'string' | 'addedHighlight';
|
|
40
80
|
export type TerminalColorCapability = 'ansi16' | 'ansi256' | 'truecolor';
|
|
41
81
|
type TerminalEnvironment = Readonly<Record<string, string | undefined>>;
|
|
42
|
-
export declare function tuiSyntaxStyle(palette: TuiPalette, token: TuiSyntaxToken, change?: 'added' | 'removed'): {
|
|
82
|
+
export declare function tuiSyntaxStyle(palette: TuiPalette | TuiSemanticTheme, token: TuiSyntaxToken, change?: 'added' | 'removed'): {
|
|
43
83
|
color?: string;
|
|
44
84
|
backgroundColor?: string;
|
|
45
85
|
};
|
|
46
86
|
export declare const DEFAULT_TUI_THEME_SETTINGS: TuiThemeSettings;
|
|
47
87
|
export declare function terminalColorCapability(environment?: TerminalEnvironment): TerminalColorCapability;
|
|
48
88
|
export declare function tuiPalette(profile: TuiTheme, syntaxHighlightingDisabled?: boolean, environment?: TerminalEnvironment, customTheme?: TuiCustomTheme): TuiPalette;
|
|
49
|
-
export declare function
|
|
89
|
+
export declare function resolveTuiTheme(settings: TuiThemeSettings, options?: TuiThemePresentationOptions): TuiSemanticTheme;
|
|
90
|
+
export declare function TuiThemeProvider({ settings, screenReader, children, }: {
|
|
50
91
|
settings: TuiThemeSettings;
|
|
92
|
+
screenReader?: boolean;
|
|
51
93
|
children: ReactNode;
|
|
52
94
|
}): import("react").JSX.Element;
|
|
53
95
|
export declare function useTuiPalette(): TuiPalette;
|
|
96
|
+
export declare function useTuiTheme(): TuiSemanticTheme;
|
|
54
97
|
export {};
|
|
55
98
|
//# sourceMappingURL=theme.d.ts.map
|
package/dist/cli/tui/theme.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext } from 'react';
|
|
2
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
3
3
|
export const TUI_THEMES = [
|
|
4
4
|
'auto',
|
|
5
5
|
'dark',
|
|
@@ -9,16 +9,55 @@ export const TUI_THEMES = [
|
|
|
9
9
|
'dark-ansi',
|
|
10
10
|
'light-ansi',
|
|
11
11
|
];
|
|
12
|
+
export const TUI_TEXT_ROLES = [
|
|
13
|
+
'body',
|
|
14
|
+
'productIdentity',
|
|
15
|
+
'heading',
|
|
16
|
+
'navigation',
|
|
17
|
+
'selectedRow',
|
|
18
|
+
'selectedTab',
|
|
19
|
+
'focusMarker',
|
|
20
|
+
'inputMarker',
|
|
21
|
+
'inputCursor',
|
|
22
|
+
'muted',
|
|
23
|
+
'link',
|
|
24
|
+
'active',
|
|
25
|
+
'info',
|
|
26
|
+
'success',
|
|
27
|
+
'warning',
|
|
28
|
+
'permission',
|
|
29
|
+
'error',
|
|
30
|
+
'diffAdded',
|
|
31
|
+
'diffRemoved',
|
|
32
|
+
'shellMode',
|
|
33
|
+
];
|
|
34
|
+
export const TUI_SURFACE_ROLES = [
|
|
35
|
+
'neutralBorder',
|
|
36
|
+
'separator',
|
|
37
|
+
'selectedRow',
|
|
38
|
+
'selectedTab',
|
|
39
|
+
'input',
|
|
40
|
+
'decision',
|
|
41
|
+
'error',
|
|
42
|
+
];
|
|
12
43
|
export function tuiSyntaxStyle(palette, token, change) {
|
|
44
|
+
if (typeof palette.syntax === 'function')
|
|
45
|
+
return palette.syntax(token, change);
|
|
13
46
|
if (palette.syntaxHighlightingDisabled)
|
|
14
47
|
return {};
|
|
48
|
+
const syntax = palette.syntax;
|
|
49
|
+
if (token === 'addedHighlight') {
|
|
50
|
+
return syntax.addedHighlight === undefined
|
|
51
|
+
? {}
|
|
52
|
+
: { backgroundColor: syntax.addedHighlight };
|
|
53
|
+
}
|
|
15
54
|
const backgroundColor = change === 'added'
|
|
16
|
-
?
|
|
55
|
+
? syntax.addedBackground
|
|
17
56
|
: change === 'removed'
|
|
18
|
-
?
|
|
57
|
+
? syntax.removedBackground
|
|
19
58
|
: undefined;
|
|
20
59
|
return {
|
|
21
|
-
color:
|
|
60
|
+
color: syntax[token],
|
|
22
61
|
...(backgroundColor === undefined ? {} : { backgroundColor }),
|
|
23
62
|
};
|
|
24
63
|
}
|
|
@@ -114,6 +153,42 @@ export function terminalColorCapability(environment = process.env) {
|
|
|
114
153
|
return /256color/iu.test(environment.TERM ?? '') ? 'ansi256' : 'ansi16';
|
|
115
154
|
}
|
|
116
155
|
const ANSI_256_LEVELS = [0, 95, 135, 175, 215, 255];
|
|
156
|
+
const ANSI_16_RGB = [
|
|
157
|
+
[0, 0, 0],
|
|
158
|
+
[128, 0, 0],
|
|
159
|
+
[0, 128, 0],
|
|
160
|
+
[128, 128, 0],
|
|
161
|
+
[0, 0, 128],
|
|
162
|
+
[128, 0, 128],
|
|
163
|
+
[0, 128, 128],
|
|
164
|
+
[192, 192, 192],
|
|
165
|
+
[128, 128, 128],
|
|
166
|
+
[255, 0, 0],
|
|
167
|
+
[0, 255, 0],
|
|
168
|
+
[255, 255, 0],
|
|
169
|
+
[0, 0, 255],
|
|
170
|
+
[255, 0, 255],
|
|
171
|
+
[0, 255, 255],
|
|
172
|
+
[255, 255, 255],
|
|
173
|
+
];
|
|
174
|
+
const ANSI_16_NAMES = [
|
|
175
|
+
'black',
|
|
176
|
+
'red',
|
|
177
|
+
'green',
|
|
178
|
+
'yellow',
|
|
179
|
+
'blue',
|
|
180
|
+
'magenta',
|
|
181
|
+
'cyan',
|
|
182
|
+
'white',
|
|
183
|
+
'blackBright',
|
|
184
|
+
'redBright',
|
|
185
|
+
'greenBright',
|
|
186
|
+
'yellowBright',
|
|
187
|
+
'blueBright',
|
|
188
|
+
'magentaBright',
|
|
189
|
+
'cyanBright',
|
|
190
|
+
'whiteBright',
|
|
191
|
+
];
|
|
117
192
|
const ansi256ColorCache = new Map();
|
|
118
193
|
const ANSI_16_COLORS = {
|
|
119
194
|
'#ffffff': 'whiteBright',
|
|
@@ -123,6 +198,7 @@ const ANSI_16_COLORS = {
|
|
|
123
198
|
'#5f0000': 'black',
|
|
124
199
|
'#005f00': 'black',
|
|
125
200
|
'#008700': 'green',
|
|
201
|
+
'#16a34a': 'green',
|
|
126
202
|
'#d97757': 'redBright',
|
|
127
203
|
'#b8a1ff': 'whiteBright',
|
|
128
204
|
'#5fafff': 'cyanBright',
|
|
@@ -142,8 +218,115 @@ const ANSI_16_COLORS = {
|
|
|
142
218
|
'#875f00': 'red',
|
|
143
219
|
'#585858': 'black',
|
|
144
220
|
};
|
|
145
|
-
function ansi16Color(
|
|
146
|
-
|
|
221
|
+
function ansi16Color(value) {
|
|
222
|
+
const normalized = normalizeAnsiName(value);
|
|
223
|
+
const directAnsi = /^ansi256\((\d+)\)$/iu.exec(normalized);
|
|
224
|
+
if (directAnsi) {
|
|
225
|
+
const index = Number(directAnsi[1]);
|
|
226
|
+
if (index >= 0 && index < ANSI_16_NAMES.length)
|
|
227
|
+
return ANSI_16_NAMES[index] ?? 'black';
|
|
228
|
+
}
|
|
229
|
+
const known = ANSI_16_COLORS[normalized.toLowerCase()];
|
|
230
|
+
if (known)
|
|
231
|
+
return known;
|
|
232
|
+
const hex = hexFromRgb(normalized) ?? ansi256ToHex(normalized);
|
|
233
|
+
const match = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/iu.exec(hex ?? normalized);
|
|
234
|
+
if (!match)
|
|
235
|
+
return normalized;
|
|
236
|
+
const rgb = [
|
|
237
|
+
Number.parseInt(match[1] ?? '0', 16),
|
|
238
|
+
Number.parseInt(match[2] ?? '0', 16),
|
|
239
|
+
Number.parseInt(match[3] ?? '0', 16),
|
|
240
|
+
];
|
|
241
|
+
let bestIndex = 0;
|
|
242
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
243
|
+
for (const [index, candidate] of ANSI_16_RGB.entries()) {
|
|
244
|
+
const distance = candidate.reduce((total, component, componentIndex) => total + ((rgb[componentIndex] ?? 0) - component) ** 2, 0);
|
|
245
|
+
if (distance < bestDistance) {
|
|
246
|
+
bestDistance = distance;
|
|
247
|
+
bestIndex = index;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return ANSI_16_NAMES[bestIndex] ?? 'black';
|
|
251
|
+
}
|
|
252
|
+
function hexFromRgb(value) {
|
|
253
|
+
const match = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/iu.exec(value);
|
|
254
|
+
if (!match)
|
|
255
|
+
return undefined;
|
|
256
|
+
return `#${[match[1], match[2], match[3]]
|
|
257
|
+
.map((component) => Number(component).toString(16).padStart(2, '0'))
|
|
258
|
+
.join('')}`;
|
|
259
|
+
}
|
|
260
|
+
function ansi256ToHex(value) {
|
|
261
|
+
const match = /^ansi256\((\d+)\)$/iu.exec(value);
|
|
262
|
+
if (!match)
|
|
263
|
+
return undefined;
|
|
264
|
+
const index = Number(match[1]);
|
|
265
|
+
if (index < 0 || index > 255)
|
|
266
|
+
return undefined;
|
|
267
|
+
if (index < 16) {
|
|
268
|
+
const [red, green, blue] = ANSI_16_RGB[index] ?? [];
|
|
269
|
+
if (red === undefined || green === undefined || blue === undefined)
|
|
270
|
+
return undefined;
|
|
271
|
+
return `#${[red, green, blue]
|
|
272
|
+
.map((component) => component.toString(16).padStart(2, '0'))
|
|
273
|
+
.join('')}`;
|
|
274
|
+
}
|
|
275
|
+
if (index >= 232) {
|
|
276
|
+
const level = 8 + (index - 232) * 10;
|
|
277
|
+
return `#${[level, level, level]
|
|
278
|
+
.map((component) => component.toString(16).padStart(2, '0'))
|
|
279
|
+
.join('')}`;
|
|
280
|
+
}
|
|
281
|
+
const offset = index - 16;
|
|
282
|
+
const red = Math.floor(offset / 36);
|
|
283
|
+
const green = Math.floor((offset % 36) / 6);
|
|
284
|
+
const blue = offset % 6;
|
|
285
|
+
const levels = [0, 95, 135, 175, 215, 255];
|
|
286
|
+
return `#${[levels[red], levels[green], levels[blue]]
|
|
287
|
+
.map((component) => (component ?? 0).toString(16).padStart(2, '0'))
|
|
288
|
+
.join('')}`;
|
|
289
|
+
}
|
|
290
|
+
function normalizeAnsiName(value) {
|
|
291
|
+
return value.startsWith('ansi:') ? value.slice('ansi:'.length) : value;
|
|
292
|
+
}
|
|
293
|
+
function adaptEffectiveColor(value, capability) {
|
|
294
|
+
const normalized = normalizeAnsiName(value);
|
|
295
|
+
if (capability === 'truecolor')
|
|
296
|
+
return normalized;
|
|
297
|
+
if (capability === 'ansi256' &&
|
|
298
|
+
/^ansi256\((?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\)$/u.test(normalized))
|
|
299
|
+
return normalized;
|
|
300
|
+
const rgb = hexFromRgb(normalized);
|
|
301
|
+
const hex = rgb ?? ansi256ToHex(normalized) ?? normalized;
|
|
302
|
+
if (capability === 'ansi16') {
|
|
303
|
+
if (!hex.startsWith('#'))
|
|
304
|
+
return hex;
|
|
305
|
+
return ansi16Color(hex);
|
|
306
|
+
}
|
|
307
|
+
if (hex.startsWith('#'))
|
|
308
|
+
return ansi256Color(hex);
|
|
309
|
+
return hex;
|
|
310
|
+
}
|
|
311
|
+
function projectPalette(palette, capability) {
|
|
312
|
+
const adapt = (value) => adaptEffectiveColor(value, capability);
|
|
313
|
+
return {
|
|
314
|
+
...palette,
|
|
315
|
+
brand: adapt(palette.brand),
|
|
316
|
+
accent: adapt(palette.accent),
|
|
317
|
+
info: adapt(palette.info),
|
|
318
|
+
link: adapt(palette.link),
|
|
319
|
+
error: adapt(palette.error),
|
|
320
|
+
success: adapt(palette.success),
|
|
321
|
+
warning: adapt(palette.warning),
|
|
322
|
+
muted: adapt(palette.muted),
|
|
323
|
+
selectionText: adapt(palette.selectionText),
|
|
324
|
+
sessionColors: Object.fromEntries(Object.entries(palette.sessionColors).map(([name, value]) => [
|
|
325
|
+
name,
|
|
326
|
+
adapt(value),
|
|
327
|
+
])),
|
|
328
|
+
syntax: adaptSyntaxColors(palette.syntax, adapt),
|
|
329
|
+
};
|
|
147
330
|
}
|
|
148
331
|
function ansi256Color(hex) {
|
|
149
332
|
const cached = ansi256ColorCache.get(hex);
|
|
@@ -201,7 +384,7 @@ function adaptSyntaxColors(syntax, adapt) {
|
|
|
201
384
|
: { addedHighlight: adapt(syntax.addedHighlight) }),
|
|
202
385
|
};
|
|
203
386
|
}
|
|
204
|
-
|
|
387
|
+
function resolveRawPalette(profile, syntaxHighlightingDisabled = false, environment = process.env, customTheme) {
|
|
205
388
|
const dark = profile === 'auto'
|
|
206
389
|
? automaticDark(environment)
|
|
207
390
|
: profile === 'dark' ||
|
|
@@ -235,16 +418,6 @@ export function tuiPalette(profile, syntaxHighlightingDisabled = false, environm
|
|
|
235
418
|
}
|
|
236
419
|
: {}),
|
|
237
420
|
};
|
|
238
|
-
const terminalCapability = terminalColorCapability(environment);
|
|
239
|
-
const adaptAutoColor = terminalCapability === 'ansi16'
|
|
240
|
-
? ansi16Color
|
|
241
|
-
: terminalCapability === 'ansi256'
|
|
242
|
-
? ansi256Color
|
|
243
|
-
: (color) => color;
|
|
244
|
-
const syntax = profile === 'auto'
|
|
245
|
-
? adaptSyntaxColors(syntaxBase, adaptAutoColor)
|
|
246
|
-
: syntaxBase;
|
|
247
|
-
const autoColor = (color) => profile === 'auto' ? adaptAutoColor(color) : color;
|
|
248
421
|
const sessionColors = ansiOnly
|
|
249
422
|
? dark
|
|
250
423
|
? DARK_ANSI_SESSION_COLORS
|
|
@@ -254,14 +427,14 @@ export function tuiPalette(profile, syntaxHighlightingDisabled = false, environm
|
|
|
254
427
|
? DARK_DALTONIZED_SESSION_COLORS
|
|
255
428
|
: LIGHT_DALTONIZED_SESSION_COLORS
|
|
256
429
|
: {
|
|
257
|
-
red:
|
|
258
|
-
blue:
|
|
259
|
-
green:
|
|
260
|
-
yellow:
|
|
261
|
-
purple:
|
|
262
|
-
orange:
|
|
263
|
-
pink:
|
|
264
|
-
cyan:
|
|
430
|
+
red: NORMAL_SESSION_COLORS.red,
|
|
431
|
+
blue: NORMAL_SESSION_COLORS.blue,
|
|
432
|
+
green: NORMAL_SESSION_COLORS.green,
|
|
433
|
+
yellow: NORMAL_SESSION_COLORS.yellow,
|
|
434
|
+
purple: NORMAL_SESSION_COLORS.purple,
|
|
435
|
+
orange: NORMAL_SESSION_COLORS.orange,
|
|
436
|
+
pink: NORMAL_SESSION_COLORS.pink,
|
|
437
|
+
cyan: NORMAL_SESSION_COLORS.cyan,
|
|
265
438
|
};
|
|
266
439
|
const palette = {
|
|
267
440
|
profile,
|
|
@@ -269,31 +442,17 @@ export function tuiPalette(profile, syntaxHighlightingDisabled = false, environm
|
|
|
269
442
|
ansiOnly,
|
|
270
443
|
syntaxHighlightingDisabled,
|
|
271
444
|
sessionColors,
|
|
272
|
-
brand: ansiOnly ? 'redBright' :
|
|
273
|
-
accent: ansiOnly
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
? autoColor('#B8A1FF')
|
|
281
|
-
: autoColor('#875faf'),
|
|
282
|
-
info: ansiOnly ? 'cyanBright' : autoColor(dark ? '#5fd7ff' : '#005f87'),
|
|
283
|
-
link: ansiOnly ? 'blueBright' : autoColor(dark ? '#5fafff' : '#005faf'),
|
|
284
|
-
error: ansiOnly ? 'redBright' : autoColor(dark ? '#ff5f5f' : '#af0000'),
|
|
285
|
-
success: ansiOnly ? 'greenBright' : autoColor(dark ? '#5fd75f' : '#008700'),
|
|
286
|
-
warning: ansiOnly
|
|
287
|
-
? 'yellowBright'
|
|
288
|
-
: autoColor(dark ? '#ffd75f' : '#875f00'),
|
|
289
|
-
muted: ansiOnly
|
|
290
|
-
? dark
|
|
291
|
-
? 'white'
|
|
292
|
-
: 'black'
|
|
293
|
-
: autoColor(dark ? '#a8a8a8' : '#585858'),
|
|
445
|
+
brand: ansiOnly ? 'redBright' : '#D97757',
|
|
446
|
+
accent: ansiOnly ? 'redBright' : '#D97757',
|
|
447
|
+
info: ansiOnly ? 'cyanBright' : dark ? '#5fd7ff' : '#005f87',
|
|
448
|
+
link: ansiOnly ? 'blueBright' : dark ? '#5fafff' : '#005faf',
|
|
449
|
+
error: ansiOnly ? 'redBright' : dark ? '#ff5f5f' : '#af0000',
|
|
450
|
+
success: ansiOnly ? 'greenBright' : dark ? '#5fd75f' : '#008700',
|
|
451
|
+
warning: ansiOnly ? 'yellowBright' : dark ? '#ffd75f' : '#875f00',
|
|
452
|
+
muted: ansiOnly ? (dark ? 'white' : 'black') : dark ? '#a8a8a8' : '#585858',
|
|
294
453
|
selectionText: dark ? 'black' : 'white',
|
|
295
454
|
syntaxTheme: ansiOnly ? 'ansi' : dark ? 'Monokai Extended' : 'GitHub',
|
|
296
|
-
syntax,
|
|
455
|
+
syntax: syntaxBase,
|
|
297
456
|
};
|
|
298
457
|
if (customTheme) {
|
|
299
458
|
const overrides = customTheme.overrides;
|
|
@@ -313,22 +472,221 @@ export function tuiPalette(profile, syntaxHighlightingDisabled = false, environm
|
|
|
313
472
|
keyword: override('claudeBlue_FOR_SYSTEM_SPINNER', palette.syntax.keyword),
|
|
314
473
|
identifier: override('suggestion', palette.syntax.identifier),
|
|
315
474
|
string: override('success', palette.syntax.string),
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
475
|
+
...(palette.syntax.removedBackground !== undefined ||
|
|
476
|
+
overrides.diffRemoved !== undefined
|
|
477
|
+
? {
|
|
478
|
+
removedBackground: override('diffRemoved', palette.syntax.removedBackground ?? ''),
|
|
479
|
+
}
|
|
480
|
+
: {}),
|
|
481
|
+
...(palette.syntax.addedBackground !== undefined ||
|
|
482
|
+
overrides.diffAdded !== undefined
|
|
483
|
+
? {
|
|
484
|
+
addedBackground: override('diffAdded', palette.syntax.addedBackground ?? ''),
|
|
485
|
+
}
|
|
486
|
+
: {}),
|
|
487
|
+
...(palette.syntax.addedHighlight !== undefined ||
|
|
488
|
+
overrides.diffAddedWord !== undefined
|
|
489
|
+
? {
|
|
490
|
+
addedHighlight: override('diffAddedWord', palette.syntax.addedHighlight ?? ''),
|
|
491
|
+
}
|
|
492
|
+
: {}),
|
|
319
493
|
};
|
|
320
494
|
palette.profile = customTheme.base;
|
|
321
495
|
}
|
|
322
496
|
return palette;
|
|
323
497
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
498
|
+
export function tuiPalette(profile, syntaxHighlightingDisabled = false, environment = process.env, customTheme) {
|
|
499
|
+
return resolvedThemeBundle({
|
|
500
|
+
theme: profile,
|
|
501
|
+
syntaxHighlightingDisabled,
|
|
502
|
+
...(customTheme === undefined ? {} : { customTheme }),
|
|
503
|
+
}, { environment }).palette;
|
|
504
|
+
}
|
|
505
|
+
function frozen(value) {
|
|
506
|
+
return Object.freeze(value);
|
|
507
|
+
}
|
|
508
|
+
function semanticText(color, options, attributes = {}) {
|
|
509
|
+
const withoutBackground = { ...attributes };
|
|
510
|
+
delete withoutBackground.backgroundColor;
|
|
511
|
+
if (color === undefined ||
|
|
512
|
+
options.screenReader ||
|
|
513
|
+
options.environment?.NO_COLOR !== undefined)
|
|
514
|
+
return frozen(withoutBackground);
|
|
515
|
+
return frozen({ color, ...attributes });
|
|
516
|
+
}
|
|
517
|
+
function semanticSurface(colors, options) {
|
|
518
|
+
if (options.screenReader || options.environment?.NO_COLOR !== undefined)
|
|
519
|
+
return frozen({});
|
|
520
|
+
return frozen(colors);
|
|
521
|
+
}
|
|
522
|
+
const EMPTY_STYLE = Object.freeze({});
|
|
523
|
+
function buildSemanticTheme(settings, palette, options = {}, capability = palette.ansiOnly
|
|
524
|
+
? 'ansi16'
|
|
525
|
+
: terminalColorCapability(options.environment ?? process.env), diffColors = {
|
|
526
|
+
added: palette.success,
|
|
527
|
+
removed: palette.error,
|
|
528
|
+
}) {
|
|
529
|
+
const environment = options.environment ?? process.env;
|
|
530
|
+
const noColor = environment.NO_COLOR !== undefined;
|
|
531
|
+
const screenReader = options.screenReader === true;
|
|
532
|
+
const suppressColor = noColor || screenReader;
|
|
533
|
+
const productColor = palette.brand;
|
|
534
|
+
const focusColor = palette.accent;
|
|
535
|
+
const infoColor = palette.info;
|
|
536
|
+
const linkColor = palette.link;
|
|
537
|
+
const errorColor = palette.error;
|
|
538
|
+
const successColor = palette.success;
|
|
539
|
+
const warningColor = palette.warning;
|
|
540
|
+
const mutedColor = palette.muted;
|
|
541
|
+
const selectionTextColor = palette.selectionText;
|
|
542
|
+
const syntaxPalette = palette.syntax;
|
|
543
|
+
const sessionColors = palette.sessionColors;
|
|
544
|
+
const color = (value) => suppressColor ? undefined : value;
|
|
545
|
+
const diffAdded = diffColors.added;
|
|
546
|
+
const diffRemoved = diffColors.removed;
|
|
547
|
+
const text = {
|
|
548
|
+
body: semanticText(undefined, options),
|
|
549
|
+
productIdentity: semanticText(color(productColor), options, {
|
|
550
|
+
bold: true,
|
|
551
|
+
}),
|
|
552
|
+
heading: semanticText(undefined, options, { bold: true }),
|
|
553
|
+
navigation: semanticText(color(focusColor), options, { bold: true }),
|
|
554
|
+
selectedRow: semanticText(color(selectionTextColor), options, {
|
|
555
|
+
...(suppressColor ? {} : { backgroundColor: focusColor }),
|
|
556
|
+
bold: true,
|
|
557
|
+
}),
|
|
558
|
+
selectedTab: semanticText(color(selectionTextColor), options, {
|
|
559
|
+
...(suppressColor ? {} : { backgroundColor: focusColor }),
|
|
560
|
+
bold: true,
|
|
561
|
+
}),
|
|
562
|
+
focusMarker: semanticText(color(focusColor), options, { bold: true }),
|
|
563
|
+
inputMarker: semanticText(color(focusColor), options),
|
|
564
|
+
inputCursor: frozen(suppressColor ? {} : { inverse: true }),
|
|
565
|
+
muted: semanticText(color(mutedColor), options, { dimColor: true }),
|
|
566
|
+
link: semanticText(color(linkColor), options, { underline: true }),
|
|
567
|
+
active: semanticText(color(infoColor), options, { bold: true }),
|
|
568
|
+
info: semanticText(color(infoColor), options),
|
|
569
|
+
success: semanticText(color(successColor), options),
|
|
570
|
+
warning: semanticText(color(warningColor), options),
|
|
571
|
+
permission: semanticText(color(warningColor), options, { bold: true }),
|
|
572
|
+
error: semanticText(color(errorColor), options, { bold: true }),
|
|
573
|
+
diffAdded: semanticText(color(diffAdded), options),
|
|
574
|
+
diffRemoved: semanticText(color(diffRemoved), options),
|
|
575
|
+
shellMode: semanticText(color(infoColor), options, { bold: true }),
|
|
576
|
+
};
|
|
577
|
+
const border = (value) => {
|
|
578
|
+
const resolved = color(value);
|
|
579
|
+
return resolved === undefined ? {} : { borderColor: resolved };
|
|
580
|
+
};
|
|
581
|
+
const background = (value) => {
|
|
582
|
+
const resolved = color(value);
|
|
583
|
+
return resolved === undefined ? {} : { backgroundColor: resolved };
|
|
584
|
+
};
|
|
585
|
+
const surface = {
|
|
586
|
+
neutralBorder: semanticSurface(border(mutedColor), options),
|
|
587
|
+
separator: semanticSurface(border(mutedColor), options),
|
|
588
|
+
selectedRow: semanticSurface(background(focusColor), options),
|
|
589
|
+
selectedTab: semanticSurface(background(focusColor), options),
|
|
590
|
+
input: semanticSurface(border(focusColor), options),
|
|
591
|
+
decision: semanticSurface(border(warningColor), options),
|
|
592
|
+
error: semanticSurface(border(errorColor), options),
|
|
593
|
+
};
|
|
594
|
+
const syntaxStyle = (token, change) => {
|
|
595
|
+
if (settings.syntaxHighlightingDisabled || suppressColor)
|
|
596
|
+
return EMPTY_STYLE;
|
|
597
|
+
const backgroundColor = change === 'added'
|
|
598
|
+
? syntaxPalette.addedBackground
|
|
599
|
+
: change === 'removed'
|
|
600
|
+
? syntaxPalette.removedBackground
|
|
601
|
+
: token === 'addedHighlight'
|
|
602
|
+
? syntaxPalette.addedHighlight
|
|
603
|
+
: undefined;
|
|
604
|
+
if (token === 'addedHighlight')
|
|
605
|
+
return backgroundColor === undefined
|
|
606
|
+
? frozen({})
|
|
607
|
+
: frozen({ backgroundColor });
|
|
608
|
+
return frozen({
|
|
609
|
+
color: syntaxPalette[token],
|
|
610
|
+
...(backgroundColor === undefined ? {} : { backgroundColor }),
|
|
611
|
+
});
|
|
612
|
+
};
|
|
613
|
+
const syntaxStyles = new Map();
|
|
614
|
+
for (const token of [
|
|
615
|
+
'text',
|
|
616
|
+
'keyword',
|
|
617
|
+
'identifier',
|
|
618
|
+
'string',
|
|
619
|
+
'addedHighlight',
|
|
620
|
+
]) {
|
|
621
|
+
for (const change of [undefined, 'added', 'removed']) {
|
|
622
|
+
syntaxStyles.set(change === undefined ? token : `${token}:${change}`, syntaxStyle(token, change));
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
profile: palette.profile,
|
|
627
|
+
dark: palette.dark,
|
|
628
|
+
ansiOnly: palette.ansiOnly,
|
|
629
|
+
terminalColorCapability: capability,
|
|
630
|
+
syntaxHighlightingDisabled: settings.syntaxHighlightingDisabled,
|
|
631
|
+
screenReader,
|
|
632
|
+
noColor,
|
|
633
|
+
syntaxTheme: palette.syntaxTheme,
|
|
634
|
+
text: frozen(text),
|
|
635
|
+
surface: frozen(surface),
|
|
636
|
+
syntax: (token, change) => syntaxStyles.get(change === undefined ? token : `${token}:${change}`) ??
|
|
637
|
+
EMPTY_STYLE,
|
|
638
|
+
session: (agentColor) => suppressColor ? undefined : sessionColors[agentColor],
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
function resolvedThemeBundle(settings, options = {}) {
|
|
642
|
+
const profile = TUI_THEMES.includes(settings.theme)
|
|
327
643
|
? settings.theme
|
|
328
|
-
: 'dark';
|
|
329
|
-
|
|
644
|
+
: (settings.customTheme?.base ?? 'dark');
|
|
645
|
+
const environment = options.environment ?? process.env;
|
|
646
|
+
const capability = profile.endsWith('-ansi')
|
|
647
|
+
? 'ansi16'
|
|
648
|
+
: terminalColorCapability(environment);
|
|
649
|
+
const rawPalette = resolveRawPalette(profile, settings.syntaxHighlightingDisabled, environment, settings.customTheme);
|
|
650
|
+
const palette = projectPalette(rawPalette, capability);
|
|
651
|
+
const adapt = (value) => adaptEffectiveColor(value, capability);
|
|
652
|
+
return {
|
|
653
|
+
palette,
|
|
654
|
+
theme: buildSemanticTheme(settings, palette, options, capability, {
|
|
655
|
+
added: adapt(settings.customTheme?.overrides.diffAdded ?? rawPalette.success),
|
|
656
|
+
removed: adapt(settings.customTheme?.overrides.diffRemoved ?? rawPalette.error),
|
|
657
|
+
}),
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
export function resolveTuiTheme(settings, options = {}) {
|
|
661
|
+
return resolvedThemeBundle(settings, options).theme;
|
|
662
|
+
}
|
|
663
|
+
const TuiPaletteContext = createContext(tuiPalette('auto'));
|
|
664
|
+
const TuiThemeContext = createContext(resolveTuiTheme(DEFAULT_TUI_THEME_SETTINGS));
|
|
665
|
+
export function TuiThemeProvider({ settings, screenReader = false, children, }) {
|
|
666
|
+
const environment = process.env;
|
|
667
|
+
const environmentKey = [
|
|
668
|
+
environment.COLORFGBG,
|
|
669
|
+
environment.FORCE_COLOR,
|
|
670
|
+
environment.COLORTERM,
|
|
671
|
+
environment.TERM,
|
|
672
|
+
environment.TERM_PROGRAM,
|
|
673
|
+
environment.NO_COLOR,
|
|
674
|
+
]
|
|
675
|
+
.map((value) => value ?? '')
|
|
676
|
+
.join('\u0000');
|
|
677
|
+
const bundle = useMemo(() => resolvedThemeBundle(settings, { environment, screenReader }), [
|
|
678
|
+
settings.theme,
|
|
679
|
+
settings.syntaxHighlightingDisabled,
|
|
680
|
+
settings.customTheme,
|
|
681
|
+
screenReader,
|
|
682
|
+
environmentKey,
|
|
683
|
+
]);
|
|
684
|
+
return (_jsx(TuiThemeContext.Provider, { value: bundle.theme, children: _jsx(TuiPaletteContext.Provider, { value: bundle.palette, children: children }) }));
|
|
330
685
|
}
|
|
331
686
|
export function useTuiPalette() {
|
|
332
687
|
return useContext(TuiPaletteContext);
|
|
333
688
|
}
|
|
689
|
+
export function useTuiTheme() {
|
|
690
|
+
return useContext(TuiThemeContext);
|
|
691
|
+
}
|
|
334
692
|
//# sourceMappingURL=theme.js.map
|
|
@@ -8,7 +8,7 @@ import { extractPermissionRules, permissionRuleValueToString, shellPermissionSug
|
|
|
8
8
|
import { redactSensitiveText } from '../../platform/sensitive-data.js';
|
|
9
9
|
import { resolveDataPlaneRoot, } from '../../persistence/data-plane.js';
|
|
10
10
|
import { composerEditorSegments, } from './composer-editor.js';
|
|
11
|
-
import {
|
|
11
|
+
import { useTuiTheme } from './theme.js';
|
|
12
12
|
function stringInput(call, name) {
|
|
13
13
|
const value = call.input[name];
|
|
14
14
|
return typeof value === 'string' ? value : undefined;
|
|
@@ -370,10 +370,12 @@ export function projectTuiToolPermission(call, cwd, sensitiveValues, decision, d
|
|
|
370
370
|
});
|
|
371
371
|
}
|
|
372
372
|
export function ToolPermissionDialog({ model, selection, feedbackMode, feedback, ruleEditor, screenReader, }) {
|
|
373
|
-
const
|
|
374
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: screenReader ? undefined : 'round',
|
|
373
|
+
const theme = useTuiTheme();
|
|
374
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: screenReader ? undefined : 'round', ...theme.surface.decision, paddingX: screenReader ? 0 : 1, marginTop: 1, children: [_jsx(Text, { ...theme.text.permission, children: model.title }), model.subtitle ? _jsx(Text, { dimColor: true, children: model.subtitle }) : null, _jsxs(Box, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [model.detail.map((line, index) => {
|
|
375
375
|
const content = `${line.prefix ? `${line.prefix} ` : ''}${line.text}`;
|
|
376
|
-
return line.prefix ? (_jsx(Text, {
|
|
376
|
+
return line.prefix ? (_jsx(Text, { ...(line.prefix === '+'
|
|
377
|
+
? theme.text.diffAdded
|
|
378
|
+
: theme.text.diffRemoved), children: content }, `${index}-${line.prefix}`)) : (_jsx(Text, { children: content }, `${index}-`));
|
|
377
379
|
}), model.description ? _jsx(Text, { dimColor: true, children: model.description }) : null] }), model.explanation ? _jsx(Text, { dimColor: true, children: model.explanation }) : null, _jsx(Text, { children: model.question }), model.options.map((option, index) => {
|
|
378
380
|
const selected = selection === index;
|
|
379
381
|
const editor = option.editableRule
|
|
@@ -383,7 +385,9 @@ export function ToolPermissionDialog({ model, selection, feedbackMode, feedback,
|
|
|
383
385
|
})
|
|
384
386
|
: null;
|
|
385
387
|
const segments = editor ? composerEditorSegments(editor) : null;
|
|
386
|
-
return (_jsxs(Text, { bold: selected, ...(selected ?
|
|
388
|
+
return (_jsxs(Text, { bold: selected, ...(selected ? theme.text.selectedRow : {}), children: [selected ? (screenReader ? 'Selected: ' : '❯ ') : ' ', index + 1, ". ", option.label, segments ? (screenReader || !selected ? (`: ${editor?.text ?? ''}`) : (_jsxs(Text, { children: [": ", segments.before, _jsx(Text, { ...theme.text.inputCursor, children: theme.noColor
|
|
389
|
+
? `${segments.current ?? ' '}\u0332`
|
|
390
|
+
: (segments.current ?? ' ') }), segments.after] }))) : null] }, `${option.action}-${index}`));
|
|
387
391
|
}), feedbackMode ? (_jsxs(Text, { children: ["\u203A", ' ', feedback ||
|
|
388
392
|
(model.options[selection]?.action === 'deny'
|
|
389
393
|
? 'tell Praxis what to do differently'
|