@golba98/codexa 1.0.1 → 1.0.3
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 +391 -94
- package/package.json +14 -8
- package/src/app.tsx +196 -63
- package/src/commands/handler.ts +9 -4
- package/src/config/buildInfo.ts +3 -0
- package/src/config/launchArgs.ts +10 -0
- package/src/config/layeredConfig.ts +0 -0
- package/src/config/persistence.ts +51 -0
- package/src/config/runtimeConfig.ts +4 -0
- package/src/config/settings.ts +6 -13
- package/src/config/toml-serialize.ts +0 -0
- package/src/config/trustStore.ts +0 -0
- package/src/config/updateCheckCache.ts +63 -0
- package/src/core/attachments.ts +0 -0
- package/src/core/auth/codexAuth.ts +0 -0
- package/src/core/channel.ts +23 -0
- package/src/core/cleanupFastFail.ts +0 -0
- package/src/core/clipboard.ts +0 -0
- package/src/core/codex.ts +0 -0
- package/src/core/codexExecArgs.ts +0 -0
- package/src/core/codexLaunch.ts +0 -0
- package/src/core/codexPrompt.ts +0 -0
- package/src/core/executables/claudeExecutable.ts +0 -0
- package/src/core/executables/codexExecutable.ts +1 -0
- package/src/core/executables/executableResolver.ts +61 -43
- package/src/core/executables/geminiExecutable.ts +0 -0
- package/src/core/githubDiagnostics.ts +0 -0
- package/src/core/hollowResponseFormat.ts +0 -0
- package/src/core/inputDebug.ts +0 -0
- package/src/core/launchContext.ts +33 -33
- package/src/core/models/codexCapabilities.ts +0 -0
- package/src/core/models/codexModelCapabilities.ts +0 -0
- package/src/core/models/modelSpecs.ts +0 -0
- package/src/core/perf/profiler.ts +0 -0
- package/src/core/perf/renderDebug.ts +0 -0
- package/src/core/planStorage.ts +0 -0
- package/src/core/process/CommandRunner.ts +0 -0
- package/src/core/process/processValidation.ts +9 -5
- package/src/core/projectInstructions.ts +0 -0
- package/src/core/providerLauncher/launcher.ts +59 -42
- package/src/core/providerLauncher/registry.ts +0 -0
- package/src/core/providerLauncher/types.ts +0 -0
- package/src/core/providerLauncher/workspaceConfig.ts +0 -0
- package/src/core/providerRuntime/anthropic.ts +0 -0
- package/src/core/providerRuntime/capabilityProfile.ts +0 -0
- package/src/core/providerRuntime/claudeCodeDiscovery.ts +0 -0
- package/src/core/providerRuntime/contextMetadata.ts +0 -0
- package/src/core/providerRuntime/gemini.ts +0 -0
- package/src/core/providerRuntime/lmstudio.ts +0 -0
- package/src/core/providerRuntime/local.ts +0 -0
- package/src/core/providerRuntime/models.ts +0 -0
- package/src/core/providerRuntime/reasoning.ts +0 -0
- package/src/core/providerRuntime/registry.ts +0 -0
- package/src/core/providerRuntime/types.ts +0 -0
- package/src/core/providers/codexJsonStream.ts +0 -0
- package/src/core/providers/codexSubprocess.ts +0 -0
- package/src/core/providers/codexTranscript.ts +0 -0
- package/src/core/providers/openaiNative.ts +0 -0
- package/src/core/providers/registry.ts +0 -0
- package/src/core/providers/types.ts +0 -0
- package/src/core/terminal/startupClear.ts +20 -0
- package/src/core/terminal/terminalCapabilities.ts +0 -0
- package/src/core/terminal/terminalControl.ts +0 -0
- package/src/core/terminal/terminalSanitize.ts +0 -0
- package/src/core/terminal/terminalSelection.ts +0 -0
- package/src/core/terminal/terminalTitle.ts +0 -0
- package/src/core/updateCheck.ts +188 -0
- package/src/core/workspaceActivity.ts +0 -0
- package/src/core/workspaceGuard.ts +0 -0
- package/src/core/workspaceRoot.ts +0 -0
- package/src/exec.ts +0 -0
- package/src/headless/execArgs.ts +1 -0
- package/src/headless/execRunner.ts +0 -0
- package/src/index.tsx +13 -9
- package/src/session/appSession.ts +0 -0
- package/src/session/chatLifecycle.ts +0 -0
- package/src/session/liveRenderScheduler.ts +0 -0
- package/src/session/planFlow.ts +0 -0
- package/src/session/planTranscript.ts +0 -0
- package/src/session/promptRunSchedule.ts +0 -0
- package/src/session/types.ts +2 -1
- package/src/test/runtimeTestUtils.ts +0 -0
- package/src/types/react-dom.d.ts +0 -0
- package/src/ui/ActionRequiredBlock.tsx +5 -5
- package/src/ui/ActivityBars.tsx +3 -3
- package/src/ui/ActivityIndicator.tsx +6 -6
- package/src/ui/AgentBlock.tsx +6 -6
- package/src/ui/AnimatedStatusText.tsx +1 -1
- package/src/ui/AppShell.tsx +13 -5
- package/src/ui/AttachmentImportPanel.tsx +8 -8
- package/src/ui/AuthPanel.tsx +20 -20
- package/src/ui/BackendPicker.tsx +0 -0
- package/src/ui/BottomComposer.tsx +117 -78
- package/src/ui/DashCard.tsx +3 -3
- package/src/ui/Markdown.tsx +17 -17
- package/src/ui/ModePicker.tsx +0 -0
- package/src/ui/ModelPicker.tsx +0 -0
- package/src/ui/ModelPickerScreen.tsx +10 -10
- package/src/ui/ModelReasoningPicker.tsx +14 -14
- package/src/ui/Panel.tsx +3 -3
- package/src/ui/PermissionsPanel.tsx +0 -0
- package/src/ui/PlanActionPicker.tsx +6 -6
- package/src/ui/PlanReviewPanel.tsx +8 -8
- package/src/ui/ProviderPicker.tsx +18 -18
- package/src/ui/ReasoningPicker.tsx +0 -0
- package/src/ui/RunFooter.tsx +3 -3
- package/src/ui/SelectionPanel.tsx +4 -4
- package/src/ui/SettingsPanel.tsx +8 -8
- package/src/ui/Spinner.tsx +1 -1
- package/src/ui/StaticIntroItem.tsx +0 -0
- package/src/ui/StaticTranscriptItem.tsx +0 -0
- package/src/ui/TextEntryPanel.tsx +10 -10
- package/src/ui/ThemePicker.tsx +0 -0
- package/src/ui/ThinkingBlock.tsx +8 -8
- package/src/ui/Timeline.tsx +21 -17
- package/src/ui/TopHeader.tsx +421 -257
- package/src/ui/TurnGroup.tsx +31 -31
- package/src/ui/UpdateAvailableCard.tsx +41 -0
- package/src/ui/UpdatePromptPanel.tsx +203 -0
- package/src/ui/busyStatusAnimation.ts +0 -0
- package/src/ui/commandNormalize.ts +0 -0
- package/src/ui/diffRenderer.ts +0 -0
- package/src/ui/focus.ts +3 -0
- package/src/ui/inputBuffer.ts +0 -0
- package/src/ui/layout.ts +1 -1
- package/src/ui/logoVariants.ts +107 -0
- package/src/ui/modeDisplay.ts +12 -12
- package/src/ui/outputPipeline.ts +0 -0
- package/src/ui/progressEntries.ts +0 -0
- package/src/ui/runActivityView.ts +0 -0
- package/src/ui/runtimeDisplay.ts +100 -0
- package/src/ui/slashCommands.ts +0 -0
- package/src/ui/terminalAnswerFormat.ts +0 -0
- package/src/ui/textLayout.ts +0 -0
- package/src/ui/theme.tsx +274 -395
- package/src/ui/themeFlow.ts +0 -0
- package/src/ui/timelineMeasure.ts +29 -19
- package/src/ui/useThrottledValue.ts +0 -0
- package/scripts/audit-codexa-capabilities.mjs +0 -466
- package/scripts/smoke-terminal-bench.mjs +0 -35
- package/src/appRenderStability.test.ts +0 -131
- package/src/commands/handler.test.ts +0 -643
- package/src/config/launchArgs.test.ts +0 -158
- package/src/config/layeredConfig.test.ts +0 -143
- package/src/config/persistence.test.ts +0 -110
- package/src/config/runtimeConfig.test.ts +0 -218
- package/src/config/settings.test.ts +0 -155
- package/src/config/trustStore.test.ts +0 -29
- package/src/core/attachments.test.ts +0 -155
- package/src/core/auth/codexAuth.test.ts +0 -68
- package/src/core/cleanupFastFail.test.ts +0 -76
- package/src/core/codexExecArgs.test.ts +0 -195
- package/src/core/codexLaunch.test.ts +0 -205
- package/src/core/codexPrompt.test.ts +0 -252
- package/src/core/executables/codexExecutable.test.ts +0 -212
- package/src/core/executables/executableResolver.test.ts +0 -129
- package/src/core/executables/geminiExecutable.test.ts +0 -116
- package/src/core/executables/pathSanityScan.test.ts +0 -47
- package/src/core/githubDiagnostics.test.ts +0 -92
- package/src/core/hollowResponseFormat.test.ts +0 -58
- package/src/core/launchContext.test.ts +0 -157
- package/src/core/models/codexCapabilities.test.ts +0 -45
- package/src/core/models/codexModelCapabilities.test.ts +0 -246
- package/src/core/models/modelSpecs.test.ts +0 -283
- package/src/core/perf/renderDebug.test.ts +0 -230
- package/src/core/planStorage.test.ts +0 -143
- package/src/core/process/CommandRunner.test.ts +0 -105
- package/src/core/projectInstructions.test.ts +0 -50
- package/src/core/providerLauncher/launcher.test.ts +0 -238
- package/src/core/providerLauncher/registry.test.ts +0 -324
- package/src/core/providerLauncher/workspaceConfig.test.ts +0 -638
- package/src/core/providerRuntime/anthropic.test.ts +0 -1120
- package/src/core/providerRuntime/capabilityProfile.test.ts +0 -311
- package/src/core/providerRuntime/contextMetadata.test.ts +0 -468
- package/src/core/providerRuntime/gemini.test.ts +0 -437
- package/src/core/providerRuntime/lmstudio.test.ts +0 -168
- package/src/core/providerRuntime/local.test.ts +0 -787
- package/src/core/providerRuntime/registry.test.ts +0 -233
- package/src/core/providers/codexJsonStream.test.ts +0 -148
- package/src/core/providers/codexSubprocess.test.ts +0 -68
- package/src/core/providers/codexTranscript.test.ts +0 -284
- package/src/core/terminal/terminalCapabilities.test.ts +0 -93
- package/src/core/terminal/terminalControl.test.ts +0 -75
- package/src/core/terminal/terminalSanitize.test.ts +0 -22
- package/src/core/terminal/terminalSelection.test.ts +0 -42
- package/src/core/terminal/terminalTitle.test.ts +0 -328
- package/src/core/workspaceActivity.test.ts +0 -163
- package/src/core/workspaceGuard.test.ts +0 -151
- package/src/core/workspaceRoot.test.ts +0 -23
- package/src/exec.test.ts +0 -13
- package/src/headless/execArgs.test.ts +0 -147
- package/src/headless/execRunner.test.ts +0 -434
- package/src/index.test.tsx +0 -618
- package/src/session/appSession.test.ts +0 -897
- package/src/session/chatLifecycle.test.ts +0 -64
- package/src/session/liveRenderScheduler.test.ts +0 -201
- package/src/session/planFlow.test.ts +0 -103
- package/src/session/planTranscript.test.ts +0 -65
- package/src/session/promptRunSchedule.test.ts +0 -36
- package/src/ui/ActivityIndicator.test.tsx +0 -58
- package/src/ui/AgentBlock.test.ts +0 -6
- package/src/ui/AnimatedStatusText.test.ts +0 -16
- package/src/ui/AppShell.test.tsx +0 -1739
- package/src/ui/AttachmentImportPanel.test.tsx +0 -204
- package/src/ui/BottomComposer.test.ts +0 -674
- package/src/ui/CodexLogo.tsx +0 -55
- package/src/ui/Markdown.test.ts +0 -157
- package/src/ui/ModelPickerProviderScope.test.tsx +0 -411
- package/src/ui/ModelPickerScreen.test.tsx +0 -99
- package/src/ui/ModelPickerState.test.tsx +0 -151
- package/src/ui/ModelReasoningPicker.test.tsx +0 -447
- package/src/ui/PlanReviewPanel.test.tsx +0 -267
- package/src/ui/PromptCardBorder.test.tsx +0 -161
- package/src/ui/ProviderPicker.test.tsx +0 -289
- package/src/ui/ProviderShortcut.test.tsx +0 -143
- package/src/ui/SettingsPanel.test.tsx +0 -233
- package/src/ui/Timeline.test.ts +0 -2067
- package/src/ui/TimelineNavigation.test.tsx +0 -201
- package/src/ui/TopHeader.test.tsx +0 -239
- package/src/ui/TurnGroup.test.tsx +0 -365
- package/src/ui/busyStatusAnimation.test.ts +0 -30
- package/src/ui/commandNormalize.test.ts +0 -142
- package/src/ui/diffRenderer.test.ts +0 -102
- package/src/ui/focusFlow.test.tsx +0 -1098
- package/src/ui/inputBuffer.test.ts +0 -151
- package/src/ui/layout.test.ts +0 -145
- package/src/ui/modeDisplay.test.ts +0 -42
- package/src/ui/runActivityView.test.ts +0 -89
- package/src/ui/runLifecycleView.test.tsx +0 -237
- package/src/ui/statusRenderIsolation.test.tsx +0 -654
- package/src/ui/terminalAnswerFormat.test.ts +0 -19
- package/src/ui/textLayout.test.ts +0 -18
- package/src/ui/themeFlow.test.ts +0 -53
- package/src/ui/timelineMeasureCache.test.ts +0 -986
package/src/ui/TurnGroup.tsx
CHANGED
|
@@ -69,14 +69,14 @@ function UserInputCard({
|
|
|
69
69
|
dim: boolean;
|
|
70
70
|
}) {
|
|
71
71
|
const theme = useTheme();
|
|
72
|
-
const borderColor = theme.
|
|
72
|
+
const borderColor = theme.border;
|
|
73
73
|
const contentWidth = Math.max(1, cols - 7);
|
|
74
74
|
const lines = wrapPlainText(sanitizeTerminalOutput(prompt), contentWidth);
|
|
75
75
|
|
|
76
76
|
return (
|
|
77
77
|
<DashCard cols={cols} title="PROMPT" borderColor={borderColor}>
|
|
78
78
|
{lines.map((line, i) => (
|
|
79
|
-
<Text key={i} color={dim ? theme.
|
|
79
|
+
<Text key={i} color={dim ? theme.textDim : theme.text}>
|
|
80
80
|
{i === 0 ? "❯ " : " "}{line}
|
|
81
81
|
</Text>
|
|
82
82
|
))}
|
|
@@ -122,38 +122,38 @@ function ImpactSummary({
|
|
|
122
122
|
|
|
123
123
|
const opColor = (op: string) => {
|
|
124
124
|
switch (op) {
|
|
125
|
-
case "created": return theme.
|
|
126
|
-
case "deleted": return theme.
|
|
127
|
-
default: return theme.
|
|
125
|
+
case "created": return theme.success;
|
|
126
|
+
case "deleted": return theme.error;
|
|
127
|
+
default: return theme.info;
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
return (
|
|
132
132
|
<Box flexDirection="column" width="100%" paddingX={1} marginTop={0}>
|
|
133
133
|
{hasDeletes && (
|
|
134
|
-
<Text color={theme.
|
|
134
|
+
<Text color={theme.warning}>{"⚠ Destructive changes detected:"}</Text>
|
|
135
135
|
)}
|
|
136
136
|
{hasFiles && (
|
|
137
137
|
<>
|
|
138
|
-
<Text color={theme.
|
|
138
|
+
<Text color={theme.textDim}>{" Changes:"}</Text>
|
|
139
139
|
{recentFiles.map((file: RunFileActivity, i: number) => {
|
|
140
140
|
const diffInfo = file.addedLines != null || file.removedLines != null
|
|
141
141
|
? ` (+${file.addedLines ?? 0} -${file.removedLines ?? 0})`
|
|
142
142
|
: "";
|
|
143
143
|
return (
|
|
144
144
|
<Text key={i}>
|
|
145
|
-
<Text color={theme.
|
|
145
|
+
<Text color={theme.textDim}>{" "}</Text>
|
|
146
146
|
<Text color={opColor(file.operation)}>{opLabel(file.operation)}</Text>
|
|
147
|
-
<Text color={theme.
|
|
148
|
-
<Text color={theme.
|
|
147
|
+
<Text color={theme.text}>{" "}{file.path}</Text>
|
|
148
|
+
<Text color={theme.textDim}>{diffInfo}</Text>
|
|
149
149
|
</Text>
|
|
150
150
|
);
|
|
151
151
|
})}
|
|
152
152
|
</>
|
|
153
153
|
)}
|
|
154
|
-
<Text color={theme.
|
|
154
|
+
<Text color={theme.textDim}>
|
|
155
155
|
{" "}
|
|
156
|
-
<Text color={theme.
|
|
156
|
+
<Text color={theme.success}>{"✔ "}</Text>
|
|
157
157
|
{run.touchedFileCount > 0 && `${run.touchedFileCount} file${run.touchedFileCount === 1 ? "" : "s"}`}
|
|
158
158
|
{hasTools && `${hasFiles ? " • " : ""}${run.toolActivities.length} action${run.toolActivities.length === 1 ? "" : "s"}`}
|
|
159
159
|
{run.durationMs != null && ` • ${formatDuration(run.durationMs)}`}
|
|
@@ -172,11 +172,11 @@ function FileScanCard({ run, cols }: { run: RunEvent; cols: number }) {
|
|
|
172
172
|
return (
|
|
173
173
|
<DashCard cols={cols} title="Scanning workspace ..." rightBadge={badge}>
|
|
174
174
|
{hiddenCount > 0 && (
|
|
175
|
-
<Text color={theme.
|
|
175
|
+
<Text color={theme.textDim}>{`... ${hiddenCount} more`}</Text>
|
|
176
176
|
)}
|
|
177
177
|
{visible.map((file, i) => (
|
|
178
|
-
<Text key={i} color={theme.
|
|
179
|
-
{"● "}<Text color={theme.
|
|
178
|
+
<Text key={i} color={theme.success}>
|
|
179
|
+
{"● "}<Text color={theme.text}>{file.path}</Text>
|
|
180
180
|
</Text>
|
|
181
181
|
))}
|
|
182
182
|
</DashCard>
|
|
@@ -307,9 +307,9 @@ function PlanPanel({
|
|
|
307
307
|
cols={cols}
|
|
308
308
|
title="Plan"
|
|
309
309
|
rightBadge={approved ? "approved" : undefined}
|
|
310
|
-
borderColor={theme.
|
|
311
|
-
titleColor={theme.
|
|
312
|
-
badgeColor={theme.
|
|
310
|
+
borderColor={theme.accent}
|
|
311
|
+
titleColor={theme.text}
|
|
312
|
+
badgeColor={theme.success}
|
|
313
313
|
>
|
|
314
314
|
<MemoizedRenderMessage segments={formatted} width={contentWidth} brightHeadings />
|
|
315
315
|
</DashCard>
|
|
@@ -337,12 +337,12 @@ function ActionEventCard({
|
|
|
337
337
|
const actionLabel = getFriendlyActionLabel(actionNormalized);
|
|
338
338
|
|
|
339
339
|
const statusIcon = tool.status === "failed" ? "✕" : tool.status === "completed" ? "✔" : "▸";
|
|
340
|
-
const statusColor = tool.status === "failed" ? theme.
|
|
341
|
-
const borderColor = dim ? theme.
|
|
340
|
+
const statusColor = tool.status === "failed" ? theme.error : tool.status === "completed" ? theme.success : theme.info;
|
|
341
|
+
const borderColor = dim ? theme.border : tool.status === "running" ? theme.borderFocused : theme.border;
|
|
342
342
|
const detailText = isLiveCursorTarget && tool.status === "running"
|
|
343
343
|
? "▌"
|
|
344
344
|
: tool.summary?.trim() ? tool.summary : " ";
|
|
345
|
-
const detailColor = isLiveCursorTarget && tool.status === "running" ? theme.
|
|
345
|
+
const detailColor = isLiveCursorTarget && tool.status === "running" ? theme.accent : theme.textMuted;
|
|
346
346
|
const duration = tool.completedAt != null
|
|
347
347
|
? formatDuration(tool.completedAt - tool.startedAt)
|
|
348
348
|
: null;
|
|
@@ -356,10 +356,10 @@ function ActionEventCard({
|
|
|
356
356
|
<>
|
|
357
357
|
<Box>
|
|
358
358
|
<Text color={statusColor}>{statusIcon + " "}</Text>
|
|
359
|
-
<Text color={dim ? theme.
|
|
359
|
+
<Text color={dim ? theme.textDim : theme.text}>{actionLabel}</Text>
|
|
360
360
|
</Box>
|
|
361
361
|
{commandLines.map((line, i) => (
|
|
362
|
-
<Text key={i} color={theme.
|
|
362
|
+
<Text key={i} color={theme.textMuted}>{" "}{line || " "}</Text>
|
|
363
363
|
))}
|
|
364
364
|
</>
|
|
365
365
|
) : (
|
|
@@ -367,10 +367,10 @@ function ActionEventCard({
|
|
|
367
367
|
{commandLines.map((line, i) => (
|
|
368
368
|
<Box key={i}>
|
|
369
369
|
<Text color={i === 0 ? statusColor : undefined}>{i === 0 ? statusIcon + " " : " "}</Text>
|
|
370
|
-
<Text color={dim ? theme.
|
|
370
|
+
<Text color={dim ? theme.textDim : theme.text}>{line || " "}</Text>
|
|
371
371
|
</Box>
|
|
372
372
|
))}
|
|
373
|
-
<Text color={theme.
|
|
373
|
+
<Text color={theme.textMuted}>{" "}</Text>
|
|
374
374
|
</>
|
|
375
375
|
)}
|
|
376
376
|
<Text color={detailColor}>{" "}{detailText}</Text>
|
|
@@ -405,14 +405,14 @@ function CodexThinkingBlock({
|
|
|
405
405
|
|
|
406
406
|
return (
|
|
407
407
|
<Box flexDirection="column" width="100%" paddingLeft={transcriptContentIndent} paddingRight={1}>
|
|
408
|
-
<Text color={theme.
|
|
408
|
+
<Text color={theme.textMuted} bold>Codexa</Text>
|
|
409
409
|
{formatProgressBlockBodyLines(block.text, contentWidth)
|
|
410
410
|
.slice(0, verboseMode ? undefined : COMPACT_PROCESSING_BODY_LINE_CAP)
|
|
411
411
|
.map((line, i) => (
|
|
412
|
-
<Text key={i} color={theme.
|
|
412
|
+
<Text key={i} color={theme.textDim}>{line || " "}</Text>
|
|
413
413
|
))}
|
|
414
414
|
{isLiveCursorTarget && block.status === "active" && (
|
|
415
|
-
<Text color={theme.
|
|
415
|
+
<Text color={theme.accent}>▌</Text>
|
|
416
416
|
)}
|
|
417
417
|
</Box>
|
|
418
418
|
);
|
|
@@ -453,11 +453,11 @@ function CodexResponseBlock({
|
|
|
453
453
|
|
|
454
454
|
return (
|
|
455
455
|
<Box flexDirection="column" width="100%" paddingLeft={transcriptContentIndent} paddingRight={1}>
|
|
456
|
-
<Text color={theme.
|
|
456
|
+
<Text color={theme.textMuted} bold>Codexa</Text>
|
|
457
457
|
{run.status === "failed" && !streaming && isLast && (
|
|
458
458
|
<Box flexDirection="column">
|
|
459
459
|
{wrapPlainText(sanitizeTerminalOutput(run.errorMessage ?? run.summary), contentWidth).map((row, i) => (
|
|
460
|
-
<Text key={i} color={theme.
|
|
460
|
+
<Text key={i} color={theme.error}>{i === 0 ? `✕ ${row}` : ` ${row}`}</Text>
|
|
461
461
|
))}
|
|
462
462
|
</Box>
|
|
463
463
|
)}
|
|
@@ -466,7 +466,7 @@ function CodexResponseBlock({
|
|
|
466
466
|
width={contentWidth}
|
|
467
467
|
/>
|
|
468
468
|
{isLiveCursorTarget && segmentStreaming && (
|
|
469
|
-
<Text color={theme.
|
|
469
|
+
<Text color={theme.accent}>▌</Text>
|
|
470
470
|
)}
|
|
471
471
|
</Box>
|
|
472
472
|
);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { CODEXA_UPDATE_COMMAND } from "../core/updateCheck.js";
|
|
4
|
+
import { clampVisualText } from "./layout.js";
|
|
5
|
+
import { useTheme } from "./theme.js";
|
|
6
|
+
|
|
7
|
+
export const UPDATE_CARD_CONTENT_ROWS = 4; // title + available + using + command
|
|
8
|
+
export const UPDATE_CARD_ROWS = UPDATE_CARD_CONTENT_ROWS + 2; // +2 for top/bottom border rows
|
|
9
|
+
|
|
10
|
+
export interface UpdateAvailableCardProps {
|
|
11
|
+
latestVersion: string;
|
|
12
|
+
currentVersion: string;
|
|
13
|
+
/** Total box width including borders. Long lines are truncated to fit. */
|
|
14
|
+
width?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function UpdateAvailableCard({ latestVersion, currentVersion, width }: UpdateAvailableCardProps) {
|
|
18
|
+
const theme = useTheme();
|
|
19
|
+
const command = `Run: ${CODEXA_UPDATE_COMMAND}`;
|
|
20
|
+
// Inner content width = boxWidth - 2 (left/right border cols)
|
|
21
|
+
const innerWidth = width !== undefined ? Math.max(8, width - 2) : undefined;
|
|
22
|
+
|
|
23
|
+
function clamp(text: string): string {
|
|
24
|
+
return innerWidth !== undefined ? clampVisualText(text, innerWidth) : text;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Box
|
|
29
|
+
borderStyle="round"
|
|
30
|
+
borderColor={theme.accent}
|
|
31
|
+
flexDirection="column"
|
|
32
|
+
width={width}
|
|
33
|
+
flexShrink={0}
|
|
34
|
+
>
|
|
35
|
+
<Text color={theme.text} bold>{clamp("Update available")}</Text>
|
|
36
|
+
<Text color={theme.textMuted}>{clamp(`Codexa ${latestVersion} is available`)}</Text>
|
|
37
|
+
<Text color={theme.textMuted}>{clamp(`You are using ${currentVersion}`)}</Text>
|
|
38
|
+
<Text color={theme.textDim}>{clamp(command)}</Text>
|
|
39
|
+
</Box>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { Box, Text, useFocus, useInput } from "ink";
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { useTheme } from "./theme.js";
|
|
5
|
+
import { CODEXA_NPM_PACKAGE, CODEXA_UPDATE_COMMAND } from "../core/updateCheck.js";
|
|
6
|
+
|
|
7
|
+
type Phase = "menu" | "running" | "done" | "error";
|
|
8
|
+
|
|
9
|
+
const MENU_ITEMS = [
|
|
10
|
+
{ label: "Update now" },
|
|
11
|
+
{ label: "Skip" },
|
|
12
|
+
{ label: "Skip until next version" },
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
15
|
+
interface UpdatePromptPanelProps {
|
|
16
|
+
focusId: string;
|
|
17
|
+
currentVersion: string;
|
|
18
|
+
latestVersion: string;
|
|
19
|
+
onSkip: () => void;
|
|
20
|
+
onSkipUntilNextVersion: (version: string) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function UpdatePromptPanel({
|
|
24
|
+
focusId,
|
|
25
|
+
currentVersion,
|
|
26
|
+
latestVersion,
|
|
27
|
+
onSkip,
|
|
28
|
+
onSkipUntilNextVersion,
|
|
29
|
+
}: UpdatePromptPanelProps) {
|
|
30
|
+
const theme = useTheme();
|
|
31
|
+
const { isFocused } = useFocus({ id: focusId, autoFocus: true });
|
|
32
|
+
|
|
33
|
+
const [phase, setPhase] = useState<Phase>("menu");
|
|
34
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
35
|
+
const [outputLines, setOutputLines] = useState<string[]>([]);
|
|
36
|
+
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
|
37
|
+
|
|
38
|
+
const spawnStartedRef = useRef(false);
|
|
39
|
+
|
|
40
|
+
useInput((input, key) => {
|
|
41
|
+
if (phase === "menu") {
|
|
42
|
+
if (key.upArrow || input === "k") {
|
|
43
|
+
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (key.downArrow || input === "j") {
|
|
47
|
+
setSelectedIndex((i) => Math.min(MENU_ITEMS.length - 1, i + 1));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (key.return) {
|
|
51
|
+
if (selectedIndex === 0) {
|
|
52
|
+
setPhase("running");
|
|
53
|
+
} else if (selectedIndex === 1) {
|
|
54
|
+
onSkip();
|
|
55
|
+
} else {
|
|
56
|
+
onSkipUntilNextVersion(latestVersion);
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (key.escape) {
|
|
61
|
+
onSkip();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
} else if (phase === "done" || phase === "error") {
|
|
65
|
+
if (key.return || key.escape) {
|
|
66
|
+
onSkip();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}, { isActive: isFocused });
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (phase !== "running") return;
|
|
73
|
+
if (spawnStartedRef.current) return;
|
|
74
|
+
spawnStartedRef.current = true;
|
|
75
|
+
|
|
76
|
+
const child = spawn("npm", ["install", "-g", `${CODEXA_NPM_PACKAGE}@latest`], {
|
|
77
|
+
shell: false,
|
|
78
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const appendLines = (buf: Buffer) => {
|
|
82
|
+
const lines = buf.toString("utf8").split(/\r?\n/).filter(Boolean);
|
|
83
|
+
if (lines.length > 0) {
|
|
84
|
+
setOutputLines((prev) => [...prev, ...lines]);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
child.stdout?.on("data", appendLines);
|
|
89
|
+
child.stderr?.on("data", appendLines);
|
|
90
|
+
|
|
91
|
+
child.once("error", (err: Error) => {
|
|
92
|
+
setErrorMessage(err.message);
|
|
93
|
+
setPhase("error");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
child.once("close", (code: number | null) => {
|
|
97
|
+
if (code === 0) {
|
|
98
|
+
setPhase("done");
|
|
99
|
+
} else {
|
|
100
|
+
setErrorMessage(`npm exited with code ${code ?? "unknown"}.`);
|
|
101
|
+
setPhase("error");
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return () => {
|
|
106
|
+
try { child.kill(); } catch { /* ignore */ }
|
|
107
|
+
};
|
|
108
|
+
}, [phase]);
|
|
109
|
+
|
|
110
|
+
const hintText = phase === "menu"
|
|
111
|
+
? "↑↓/jk select Enter confirm Esc skip"
|
|
112
|
+
: "Press Enter to close";
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Box flexDirection="column" width="100%" marginTop={1}>
|
|
116
|
+
<Box
|
|
117
|
+
borderStyle="round"
|
|
118
|
+
borderColor={theme.border}
|
|
119
|
+
paddingX={2}
|
|
120
|
+
paddingY={1}
|
|
121
|
+
width="100%"
|
|
122
|
+
flexDirection="column"
|
|
123
|
+
>
|
|
124
|
+
<Box>
|
|
125
|
+
<Text color={theme.accent} bold>Update available </Text>
|
|
126
|
+
<Text color={theme.textMuted}>{hintText}</Text>
|
|
127
|
+
</Box>
|
|
128
|
+
<Box marginTop={1}>
|
|
129
|
+
<Text color={theme.text}>{`✨ ${currentVersion} -> ${latestVersion}`}</Text>
|
|
130
|
+
</Box>
|
|
131
|
+
<Box>
|
|
132
|
+
<Text color={theme.textMuted}>{`Package: ${CODEXA_NPM_PACKAGE}`}</Text>
|
|
133
|
+
</Box>
|
|
134
|
+
<Box>
|
|
135
|
+
<Text color={theme.textMuted}>{`Run: ${CODEXA_UPDATE_COMMAND}`}</Text>
|
|
136
|
+
</Box>
|
|
137
|
+
</Box>
|
|
138
|
+
|
|
139
|
+
<Box
|
|
140
|
+
borderStyle="round"
|
|
141
|
+
borderColor={theme.borderFocused}
|
|
142
|
+
paddingX={2}
|
|
143
|
+
paddingY={1}
|
|
144
|
+
marginTop={1}
|
|
145
|
+
width="100%"
|
|
146
|
+
flexDirection="column"
|
|
147
|
+
>
|
|
148
|
+
{phase === "menu" && (
|
|
149
|
+
<>
|
|
150
|
+
{MENU_ITEMS.map((item, index) => (
|
|
151
|
+
<Box key={item.label}>
|
|
152
|
+
<Text color={index === selectedIndex ? theme.accent : theme.textMuted}>
|
|
153
|
+
{index === selectedIndex ? "› " : " "}
|
|
154
|
+
</Text>
|
|
155
|
+
<Text
|
|
156
|
+
color={index === selectedIndex ? theme.text : theme.textMuted}
|
|
157
|
+
bold={index === selectedIndex}
|
|
158
|
+
>
|
|
159
|
+
{`${index + 1}. ${item.label}`}
|
|
160
|
+
</Text>
|
|
161
|
+
</Box>
|
|
162
|
+
))}
|
|
163
|
+
<Box marginTop={1}>
|
|
164
|
+
<Text color={theme.textDim}>Press enter to continue</Text>
|
|
165
|
+
</Box>
|
|
166
|
+
</>
|
|
167
|
+
)}
|
|
168
|
+
|
|
169
|
+
{phase === "running" && (
|
|
170
|
+
<>
|
|
171
|
+
<Text color={theme.text}>{`Installing Codexa ${latestVersion}...`}</Text>
|
|
172
|
+
{outputLines.map((line, i) => (
|
|
173
|
+
<Text key={i} color={theme.textMuted}>{line}</Text>
|
|
174
|
+
))}
|
|
175
|
+
</>
|
|
176
|
+
)}
|
|
177
|
+
|
|
178
|
+
{phase === "done" && (
|
|
179
|
+
<>
|
|
180
|
+
<Text color={theme.success}>{"Codexa was updated successfully."}</Text>
|
|
181
|
+
<Text color={theme.textMuted}>{"Restart Codexa to use the new version."}</Text>
|
|
182
|
+
<Box marginTop={1}>
|
|
183
|
+
<Text color={theme.textDim}>Press Enter to close</Text>
|
|
184
|
+
</Box>
|
|
185
|
+
</>
|
|
186
|
+
)}
|
|
187
|
+
|
|
188
|
+
{phase === "error" && (
|
|
189
|
+
<>
|
|
190
|
+
<Text color={theme.error}>{"Update failed."}</Text>
|
|
191
|
+
{errorMessage != null && <Text color={theme.textMuted}>{errorMessage}</Text>}
|
|
192
|
+
{outputLines.slice(-5).map((line, i) => (
|
|
193
|
+
<Text key={i} color={theme.textDim}>{line}</Text>
|
|
194
|
+
))}
|
|
195
|
+
<Box marginTop={1}>
|
|
196
|
+
<Text color={theme.textDim}>Press Enter to close</Text>
|
|
197
|
+
</Box>
|
|
198
|
+
</>
|
|
199
|
+
)}
|
|
200
|
+
</Box>
|
|
201
|
+
</Box>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
File without changes
|
|
File without changes
|
package/src/ui/diffRenderer.ts
CHANGED
|
File without changes
|
package/src/ui/focus.ts
CHANGED
|
@@ -18,6 +18,7 @@ export const FOCUS_IDS = {
|
|
|
18
18
|
permissionsAddWritableRoot: "permissions-add-writable-root",
|
|
19
19
|
permissionsRemoveWritableRoot: "permissions-remove-writable-root",
|
|
20
20
|
importConfirmationPanel: "import-confirmation",
|
|
21
|
+
updatePrompt: "update-prompt",
|
|
21
22
|
} as const;
|
|
22
23
|
|
|
23
24
|
export type FocusTargetId = (typeof FOCUS_IDS)[keyof typeof FOCUS_IDS];
|
|
@@ -54,6 +55,8 @@ export function getFocusTargetForScreen(screen: Screen): FocusTargetId {
|
|
|
54
55
|
return FOCUS_IDS.permissionsRemoveWritableRoot;
|
|
55
56
|
case "import-confirmation":
|
|
56
57
|
return FOCUS_IDS.importConfirmationPanel;
|
|
58
|
+
case "update-prompt":
|
|
59
|
+
return FOCUS_IDS.updatePrompt;
|
|
57
60
|
case "main":
|
|
58
61
|
default:
|
|
59
62
|
return FOCUS_IDS.composer;
|
package/src/ui/inputBuffer.ts
CHANGED
|
File without changes
|
package/src/ui/layout.ts
CHANGED
|
@@ -20,7 +20,7 @@ export const MIN_VIEWPORT_ROWS = 10;
|
|
|
20
20
|
export const RESTORE_SETTLE_MS = 100;
|
|
21
21
|
export const STARTUP_TINY_MIN_COLS = 40;
|
|
22
22
|
export const STARTUP_TINY_MIN_ROWS = 14;
|
|
23
|
-
export const STARTUP_FULL_MIN_COLS =
|
|
23
|
+
export const STARTUP_FULL_MIN_COLS = 100; // matches LOGO_LARGE_MIN_COLS in logoVariants.ts
|
|
24
24
|
export const STARTUP_FULL_MIN_BODY_ROWS = 4;
|
|
25
25
|
export const STARTUP_FULL_SAFE_PADDING_ROWS = 1;
|
|
26
26
|
export const STARTUP_COMPACT_INTRO_ROWS = 4;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { getTextWidth } from "./textLayout.js";
|
|
2
|
+
|
|
3
|
+
// ─── Logo constants ───────────────────────────────────────────────────────────
|
|
4
|
+
// Each variant is an array of exact terminal rows.
|
|
5
|
+
//
|
|
6
|
+
// IMPORTANT: Never apply `bold` when rendering these rows. Bold rendering of
|
|
7
|
+
// Unicode full-block (█) and box-drawing (╔═╗╝) characters causes per-glyph
|
|
8
|
+
// width/stroke differences in most terminal fonts (Ptyxis, GNOME Terminal,
|
|
9
|
+
// VS Code), producing visible gaps between characters that should be flush.
|
|
10
|
+
// The companion `wrap="truncate"` rule keeps each row on exactly one terminal
|
|
11
|
+
// line regardless of the surrounding Ink flex layout.
|
|
12
|
+
|
|
13
|
+
// Canonical Codexa brand wordmark — the ██ block art is the authoritative logo.
|
|
14
|
+
// Always shown on any normal-width terminal (≥ LOGO_LARGE_MIN_COLS cols).
|
|
15
|
+
export const CODEXA_WORDMARK = [
|
|
16
|
+
" ██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗ █████╗ ",
|
|
17
|
+
"██╔════╝██╔═══██╗██╔══██╗██╔════╝╚██╗██╔╝██╔══██╗",
|
|
18
|
+
"██║ ██║ ██║██║ ██║█████╗ ╚███╔╝ ███████║",
|
|
19
|
+
"██║ ██║ ██║██║ ██║██╔══╝ ██╔██╗ ██╔══██║",
|
|
20
|
+
"╚██████╗╚██████╔╝██████╔╝███████╗██╔╝ ██╗██║ ██║",
|
|
21
|
+
" ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝",
|
|
22
|
+
].join("\n");
|
|
23
|
+
|
|
24
|
+
/** 6-row ANSI Shadow block-char logo. Requires cols ≥ LOGO_LARGE_MIN_COLS. */
|
|
25
|
+
export const LOGO_LARGE: readonly string[] = CODEXA_WORDMARK.split("\n");
|
|
26
|
+
|
|
27
|
+
/** 4-row pure-ASCII art logo. Requires cols ≥ LOGO_MEDIUM_MIN_COLS. */
|
|
28
|
+
export const LOGO_MEDIUM: readonly string[] = [
|
|
29
|
+
" ____ ___ ____ _____ _ __ _ ",
|
|
30
|
+
" / ___| / _ \\| _ \\| ____| |/ / / \\ ",
|
|
31
|
+
"| | | | | | | | | _| | ' / / _ \\ ",
|
|
32
|
+
"|_| \\___/|_| |_|_____|_|\\_\\ /_/ \\_\\ ",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/** 1-row compact logo. Requires cols ≥ LOGO_COMPACT_MIN_COLS. */
|
|
36
|
+
export const LOGO_COMPACT: readonly string[] = [
|
|
37
|
+
"✦ CODEXA",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// ─── Breakpoints ──────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
// Aligned with MEDIUM_HEADER_MIN_COLUMNS so any side-by-side-capable terminal
|
|
43
|
+
// shows the canonical block wordmark instead of the thin ASCII fallback.
|
|
44
|
+
export const LOGO_LARGE_MIN_COLS = 72;
|
|
45
|
+
export const LOGO_MEDIUM_MIN_COLS = 72;
|
|
46
|
+
export const LOGO_COMPACT_MIN_COLS = 48;
|
|
47
|
+
|
|
48
|
+
// Minimum terminal rows each variant needs to render without crowding out the
|
|
49
|
+
// metadata + composer. A wide-but-short terminal (e.g. VS Code's bottom panel)
|
|
50
|
+
// must step DOWN to a smaller logo instead of dropping straight to text-only.
|
|
51
|
+
export const LOGO_LARGE_MIN_ROWS = 24;
|
|
52
|
+
export const LOGO_MEDIUM_MIN_ROWS = 16;
|
|
53
|
+
export const LOGO_COMPACT_MIN_ROWS = 12;
|
|
54
|
+
|
|
55
|
+
// LOGO_MEDIUM is kept as an exported constant but intentionally omitted from
|
|
56
|
+
// LOGO_VARIANTS. At 72+ cols, LOGO_LARGE_MIN_COLS = LOGO_MEDIUM_MIN_COLS = 72,
|
|
57
|
+
// so LOGO_LARGE always wins. Below 72 cols the viewport is too narrow for the
|
|
58
|
+
// thin ASCII art to add value over the compact single-line fallback.
|
|
59
|
+
const LOGO_VARIANTS: readonly { logo: readonly string[]; minCols: number; minRows: number }[] = [
|
|
60
|
+
{ logo: LOGO_LARGE, minCols: LOGO_LARGE_MIN_COLS, minRows: LOGO_LARGE_MIN_ROWS },
|
|
61
|
+
{ logo: LOGO_COMPACT, minCols: LOGO_COMPACT_MIN_COLS, minRows: LOGO_COMPACT_MIN_ROWS },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
// ─── Selection ────────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns the best logo variant for the given terminal column count.
|
|
68
|
+
*
|
|
69
|
+
* Env overrides:
|
|
70
|
+
* CODEXA_NO_ASCII_LOGO=1 → always text-only (empty array)
|
|
71
|
+
* CODEXA_COMPACT_LOGO=1 → always compact single-line logo
|
|
72
|
+
*/
|
|
73
|
+
export function selectLogoVariant(cols: number): readonly string[] {
|
|
74
|
+
if (process.env["CODEXA_NO_ASCII_LOGO"] === "1") return [];
|
|
75
|
+
if (process.env["CODEXA_COMPACT_LOGO"] === "1") return LOGO_COMPACT;
|
|
76
|
+
if (cols >= LOGO_LARGE_MIN_COLS) return LOGO_LARGE;
|
|
77
|
+
if (cols >= LOGO_COMPACT_MIN_COLS) return LOGO_COMPACT;
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns the largest logo variant that fits BOTH the available columns and
|
|
83
|
+
* rows. Unlike {@link selectLogoVariant} (columns-only), this degrades a
|
|
84
|
+
* too-tall logo to a shorter one before falling back to text-only — so a
|
|
85
|
+
* wide-but-short terminal keeps a logo instead of collapsing to a flat line.
|
|
86
|
+
* Returns an empty array only when even the 1-row compact logo cannot fit.
|
|
87
|
+
*
|
|
88
|
+
* Honours the same env overrides as {@link selectLogoVariant}.
|
|
89
|
+
*/
|
|
90
|
+
export function selectLogoVariantForViewport(cols: number, rows: number): readonly string[] {
|
|
91
|
+
if (process.env["CODEXA_NO_ASCII_LOGO"] === "1") return [];
|
|
92
|
+
if (process.env["CODEXA_COMPACT_LOGO"] === "1") {
|
|
93
|
+
return rows >= LOGO_COMPACT_MIN_ROWS ? LOGO_COMPACT : [];
|
|
94
|
+
}
|
|
95
|
+
if (cols >= LOGO_LARGE_MIN_COLS) return LOGO_LARGE;
|
|
96
|
+
for (const variant of LOGO_VARIANTS) {
|
|
97
|
+
if (cols >= variant.minCols && rows >= variant.minRows) {
|
|
98
|
+
return variant.logo;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Returns the visual column width of the widest row in a logo variant. */
|
|
105
|
+
export function getLogoWidth(logo: readonly string[]): number {
|
|
106
|
+
return logo.reduce((max, line) => Math.max(max, getTextWidth(line)), 0);
|
|
107
|
+
}
|
package/src/ui/modeDisplay.ts
CHANGED
|
@@ -18,10 +18,10 @@ export function getModeDisplaySpec(mode: string, theme: Theme): ModeDisplaySpec
|
|
|
18
18
|
return {
|
|
19
19
|
label: formatModeLabel(mode),
|
|
20
20
|
ringGlyph: "◉",
|
|
21
|
-
ringColor: theme.
|
|
22
|
-
ringFill: theme.
|
|
23
|
-
iconColor: theme.
|
|
24
|
-
labelColor: theme.
|
|
21
|
+
ringColor: theme.warning,
|
|
22
|
+
ringFill: theme.border,
|
|
23
|
+
iconColor: theme.warning,
|
|
24
|
+
labelColor: theme.text,
|
|
25
25
|
labelBold: true,
|
|
26
26
|
ringBold: true,
|
|
27
27
|
};
|
|
@@ -29,10 +29,10 @@ export function getModeDisplaySpec(mode: string, theme: Theme): ModeDisplaySpec
|
|
|
29
29
|
return {
|
|
30
30
|
label: formatModeLabel(mode),
|
|
31
31
|
ringGlyph: "◎",
|
|
32
|
-
ringColor: theme.
|
|
33
|
-
ringFill: theme.
|
|
34
|
-
iconColor: theme.
|
|
35
|
-
labelColor: theme.
|
|
32
|
+
ringColor: theme.borderFocused,
|
|
33
|
+
ringFill: theme.surfaceMuted,
|
|
34
|
+
iconColor: theme.prompt,
|
|
35
|
+
labelColor: theme.text,
|
|
36
36
|
labelBold: true,
|
|
37
37
|
ringBold: false,
|
|
38
38
|
};
|
|
@@ -41,10 +41,10 @@ export function getModeDisplaySpec(mode: string, theme: Theme): ModeDisplaySpec
|
|
|
41
41
|
return {
|
|
42
42
|
label: formatModeLabel(mode),
|
|
43
43
|
ringGlyph: "○",
|
|
44
|
-
ringColor: theme.
|
|
45
|
-
ringFill: theme.
|
|
46
|
-
iconColor: theme.
|
|
47
|
-
labelColor: theme.
|
|
44
|
+
ringColor: theme.success,
|
|
45
|
+
ringFill: theme.surfaceMuted,
|
|
46
|
+
iconColor: theme.success,
|
|
47
|
+
labelColor: theme.textMuted,
|
|
48
48
|
labelBold: false,
|
|
49
49
|
ringBold: false,
|
|
50
50
|
};
|
package/src/ui/outputPipeline.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|