Give Gemini Code a face lift.
- This utilizes `ink-gradient` to render GEMINI CODE in amazing colors. - Added a shared color configuration for UX (should this be in config?). It's very possible that we shouldn't be talking about the specific colors and instead be mentioning "foreground"/"background"/inlineCode etc. type colors. - Updated existing color usages to utilize `Colors.*` Fixes https://b.corp.google.com/issues/411385593
This commit is contained in:
parent
3fce6cea27
commit
f7edf71190
|
@ -1062,6 +1062,15 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/gradient-string": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/gradient-string/-/gradient-string-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-LkaYxluY4G5wR1M4AKQUal2q61Di1yVVCw42ImFTuaIoQVgmV0WP1xUaLB8zwb47mp82vWTpePI9JmrjEnJ7nQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tinycolor2": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
|
@ -1096,6 +1105,12 @@
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/tinycolor2": {
|
||||||
|
"version": "1.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.6.tgz",
|
||||||
|
"integrity": "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/yargs": {
|
"node_modules/@types/yargs": {
|
||||||
"version": "17.0.33",
|
"version": "17.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
||||||
|
@ -1777,9 +1792,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/bignumber.js": {
|
"node_modules/bignumber.js": {
|
||||||
"version": "9.2.1",
|
"version": "9.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz",
|
||||||
"integrity": "sha512-+NzaKgOUvInq9TIUZ1+DRspzf/HApkCwD4btfuasFTdrfnOxqx853TgDpMolp+uv4RpRp7bPcEU2zKr9+fRmyw==",
|
"integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
|
@ -1905,7 +1920,6 @@
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^4.1.0",
|
"ansi-styles": "^4.1.0",
|
||||||
|
@ -3364,6 +3378,19 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/gradient-string": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/gradient-string/-/gradient-string-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"tinygradient": "^1.1.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/graphemer": {
|
"node_modules/graphemer": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||||
|
@ -3401,7 +3428,6 @@
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
|
@ -3588,6 +3614,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ink-gradient": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ink-gradient/-/ink-gradient-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-OVyPBovBxE1tFcBhSamb+P1puqDP6pG3xFe2W9NiLgwUZd9RbcjBeR7twLbliUT9navrUstEf1ZcPKKvx71BsQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/gradient-string": "^1.1.2",
|
||||||
|
"gradient-string": "^2.0.2",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
|
"strip-ansi": "^7.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"ink": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ink-select-input": {
|
"node_modules/ink-select-input": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ink-select-input/-/ink-select-input-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ink-select-input/-/ink-select-input-6.1.0.tgz",
|
||||||
|
@ -4442,7 +4489,6 @@
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
|
@ -4798,7 +4844,6 @@
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
|
@ -4852,7 +4897,6 @@
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-reconciler": {
|
"node_modules/react-reconciler": {
|
||||||
|
@ -5544,7 +5588,6 @@
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-flag": "^4.0.0"
|
"has-flag": "^4.0.0"
|
||||||
|
@ -5573,6 +5616,12 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/tinycolor2": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tinyexec": {
|
"node_modules/tinyexec": {
|
||||||
"version": "0.3.2",
|
"version": "0.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
|
||||||
|
@ -5581,13 +5630,13 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.12",
|
"version": "0.2.13",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
|
||||||
"integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
|
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fdir": "^6.4.3",
|
"fdir": "^6.4.4",
|
||||||
"picomatch": "^4.0.2"
|
"picomatch": "^4.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -5625,6 +5674,16 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tinygradient": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinygradient/-/tinygradient-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tinycolor2": "^1.4.0",
|
||||||
|
"tinycolor2": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinypool": {
|
"node_modules/tinypool": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz",
|
||||||
|
@ -6424,6 +6483,7 @@
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"ink": "^5.2.0",
|
"ink": "^5.2.0",
|
||||||
|
"ink-gradient": "^3.0.0",
|
||||||
"ink-select-input": "^6.0.0",
|
"ink-select-input": "^6.0.0",
|
||||||
"ink-spinner": "^5.0.0",
|
"ink-spinner": "^5.0.0",
|
||||||
"ink-text-input": "^6.0.0",
|
"ink-text-input": "^6.0.0",
|
||||||
|
@ -6446,7 +6506,15 @@
|
||||||
"packages/server": {
|
"packages/server": {
|
||||||
"name": "@gemini-code/server",
|
"name": "@gemini-code/server",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@google/genai": "^0.8.0",
|
||||||
|
"diff": "^7.0.0",
|
||||||
|
"dotenv": "^16.4.7",
|
||||||
|
"fast-glob": "^3.3.3"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/diff": "^7.0.2",
|
||||||
|
"@types/dotenv": "^6.1.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vitest": "^3.1.1"
|
"vitest": "^3.1.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"ink": "^5.2.0",
|
"ink": "^5.2.0",
|
||||||
|
"ink-gradient": "^3.0.0",
|
||||||
"ink-select-input": "^6.0.0",
|
"ink-select-input": "^6.0.0",
|
||||||
"ink-spinner": "^5.0.0",
|
"ink-spinner": "^5.0.0",
|
||||||
"ink-text-input": "^6.0.0",
|
"ink-text-input": "^6.0.0",
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { useGeminiStream } from './hooks/useGeminiStream.js';
|
||||||
import { useLoadingIndicator } from './hooks/useLoadingIndicator.js';
|
import { useLoadingIndicator } from './hooks/useLoadingIndicator.js';
|
||||||
import { useInputHistory } from './hooks/useInputHistory.js';
|
import { useInputHistory } from './hooks/useInputHistory.js';
|
||||||
import { Header } from './components/Header.js';
|
import { Header } from './components/Header.js';
|
||||||
import { Tips } from './components/Tips.js';
|
|
||||||
import { HistoryDisplay } from './components/HistoryDisplay.js';
|
import { HistoryDisplay } from './components/HistoryDisplay.js';
|
||||||
import { LoadingIndicator } from './components/LoadingIndicator.js';
|
import { LoadingIndicator } from './components/LoadingIndicator.js';
|
||||||
import { InputPrompt } from './components/InputPrompt.js';
|
import { InputPrompt } from './components/InputPrompt.js';
|
||||||
|
@ -22,7 +21,8 @@ import {
|
||||||
useStartupWarnings,
|
useStartupWarnings,
|
||||||
useInitializationErrorEffect,
|
useInitializationErrorEffect,
|
||||||
} from './hooks/useAppEffects.js';
|
} from './hooks/useAppEffects.js';
|
||||||
import type { Config } from '@gemini-code/server';
|
import { shortenPath, type Config } from '@gemini-code/server';
|
||||||
|
import { Colors } from './colors.js';
|
||||||
|
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
config: Config;
|
config: Config;
|
||||||
|
@ -73,39 +73,37 @@ export const App = ({ config }: AppProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" padding={1} marginBottom={1} width="100%">
|
<Box flexDirection="column" padding={1} marginBottom={1} width="100%">
|
||||||
<Header cwd={config.getTargetDir()} />
|
<Header />
|
||||||
|
|
||||||
{startupWarnings.length > 0 && (
|
{startupWarnings.length > 0 && (
|
||||||
<Box
|
<Box
|
||||||
borderStyle="round"
|
borderStyle="round"
|
||||||
borderColor="yellow"
|
borderColor={Colors.AccentYellow}
|
||||||
paddingX={1}
|
paddingX={1}
|
||||||
marginY={1}
|
marginY={1}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
>
|
>
|
||||||
{startupWarnings.map((warning, index) => (
|
{startupWarnings.map((warning, index) => (
|
||||||
<Text key={index} color="yellow">
|
<Text key={index} color={Colors.AccentYellow}>
|
||||||
{warning}
|
{warning}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Tips />
|
|
||||||
|
|
||||||
{initError &&
|
{initError &&
|
||||||
streamingState !== StreamingState.Responding &&
|
streamingState !== StreamingState.Responding &&
|
||||||
!isWaitingForToolConfirmation && (
|
!isWaitingForToolConfirmation && (
|
||||||
<Box
|
<Box
|
||||||
borderStyle="round"
|
borderStyle="round"
|
||||||
borderColor="red"
|
borderColor={Colors.AccentRed}
|
||||||
paddingX={1}
|
paddingX={1}
|
||||||
marginBottom={1}
|
marginBottom={1}
|
||||||
>
|
>
|
||||||
{history.find(
|
{history.find(
|
||||||
(item) => item.type === 'error' && item.text?.includes(initError),
|
(item) => item.type === 'error' && item.text?.includes(initError),
|
||||||
)?.text ? (
|
)?.text ? (
|
||||||
<Text color="red">
|
<Text color={Colors.AccentRed}>
|
||||||
{
|
{
|
||||||
history.find(
|
history.find(
|
||||||
(item) =>
|
(item) =>
|
||||||
|
@ -115,8 +113,10 @@ export const App = ({ config }: AppProps) => {
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Text color="red">Initialization Error: {initError}</Text>
|
<Text color={Colors.AccentRed}>
|
||||||
<Text color="red">
|
Initialization Error: {initError}
|
||||||
|
</Text>
|
||||||
|
<Text color={Colors.AccentRed}>
|
||||||
{' '}
|
{' '}
|
||||||
Please check API key and configuration.
|
Please check API key and configuration.
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -134,7 +134,18 @@ export const App = ({ config }: AppProps) => {
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{isInputActive && <InputPrompt onSubmit={handleHistorySubmit} />}
|
{isInputActive && (
|
||||||
|
<>
|
||||||
|
<Box>
|
||||||
|
<Text color={Colors.SubtleComment}>cwd: </Text>
|
||||||
|
<Text color={Colors.LightBlue}>
|
||||||
|
{shortenPath(config.getTargetDir(), /*maxLength*/ 70)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<InputPrompt onSubmit={handleHistorySubmit} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Footer queryLength={query.length} />
|
<Footer queryLength={query.length} />
|
||||||
<ITermDetectionWarning />
|
<ITermDetectionWarning />
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
export const Colors = {
|
||||||
|
Background: '#1E1E2E',
|
||||||
|
Foreground: 'white',
|
||||||
|
LightBlue: '#CDD6F4',
|
||||||
|
AccentBlue: '#89B4FA',
|
||||||
|
AccentPurple: '#CBA6F7',
|
||||||
|
AccentCyan: '#89DCEB',
|
||||||
|
AccentGreen: '#A6E3A1',
|
||||||
|
AccentYellow: '#F9E2AF',
|
||||||
|
AccentRed: '#F38BA8',
|
||||||
|
SubtleComment: '#6C7086',
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text } from 'ink';
|
import { Box, Text } from 'ink';
|
||||||
|
import { Colors } from '../colors.js';
|
||||||
|
|
||||||
interface FooterProps {
|
interface FooterProps {
|
||||||
queryLength: number;
|
queryLength: number;
|
||||||
|
@ -14,8 +15,10 @@ interface FooterProps {
|
||||||
export const Footer: React.FC<FooterProps> = ({ queryLength }) => (
|
export const Footer: React.FC<FooterProps> = ({ queryLength }) => (
|
||||||
<Box marginTop={1} justifyContent="space-between">
|
<Box marginTop={1} justifyContent="space-between">
|
||||||
<Box minWidth={15}>
|
<Box minWidth={15}>
|
||||||
<Text color="gray">{queryLength === 0 ? '? for shortcuts' : ''}</Text>
|
<Text color={Colors.SubtleComment}>
|
||||||
|
{queryLength === 0 ? '? for shortcuts' : ''}
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Text color="blue">Gemini</Text>
|
<Text color={Colors.AccentBlue}>Gemini</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,37 +6,32 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text } from 'ink';
|
import { Box, Text } from 'ink';
|
||||||
import { UI_WIDTH, BOX_PADDING_X } from '../constants.js';
|
import Gradient from 'ink-gradient';
|
||||||
import { shortenPath } from '@gemini-code/server';
|
import { Tips } from './Tips.js';
|
||||||
|
|
||||||
interface HeaderProps {
|
const gradientColors = ['#4796E4', '#847ACE', '#C3677F'];
|
||||||
cwd: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Header: React.FC<HeaderProps> = ({ cwd }) => (
|
export const Header: React.FC = () => (
|
||||||
<>
|
<>
|
||||||
{/* Static Header Art */}
|
<Box marginBottom={1} alignItems="flex-start">
|
||||||
<Box marginBottom={1}>
|
<Gradient colors={gradientColors}>
|
||||||
<Text color="blue">{`
|
<Text>{`
|
||||||
______ ________ ____ ____ _____ ____ _____ _____
|
██████╗ ███████╗███╗ ███╗██╗███╗ ██╗██╗
|
||||||
.' ___ ||_ __ ||_ \\ / _||_ _||_ \\|_ _||_ _|
|
██╔════╝ ██╔════╝████╗ ████║██║████╗ ██║██║
|
||||||
/ .' \\_| | |_ \\_| | \\/ | | | | \\ | | | |
|
██║ ███╗█████╗ ██╔████╔██║██║██╔██╗ ██║██║
|
||||||
| | ____ | _| _ | |\\ /| | | | | |\\ \\| | | |
|
██║ ██║██╔══╝ ██║╚██╔╝██║██║██║╚██╗██║██║
|
||||||
\\ \`.___] |_| |__/ | _| |_\\/_| |_ _| |_ _| |_\\ |_ _| |_
|
╚██████╔╝███████╗██║ ╚═╝ ██║██║██║ ╚████║██║
|
||||||
\`._____.'|________||_____||_____||_____||_____|\\____||_____|`}</Text>
|
╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝
|
||||||
</Box>
|
|
||||||
{/* CWD Display */}
|
██████╗ ██████╗ ██████╗ ███████╗
|
||||||
<Box
|
██╔════╝██╔═══██╗██╔══██╗██╔════╝
|
||||||
borderStyle="round"
|
██║ ██║ ██║██║ ██║█████╗
|
||||||
borderColor="blue"
|
██║ ██║ ██║██║ ██║██╔══╝
|
||||||
paddingX={BOX_PADDING_X}
|
╚██████╗╚██████╔╝██████╔╝███████╗
|
||||||
flexDirection="column"
|
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
||||||
marginBottom={1}
|
`}</Text>
|
||||||
width={UI_WIDTH}
|
</Gradient>
|
||||||
>
|
|
||||||
<Box paddingLeft={2}>
|
|
||||||
<Text color="gray">cwd: {shortenPath(cwd, /*maxLength*/ 70)}</Text>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
<Tips />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, useInput, useFocus } from 'ink';
|
import { Text, Box, useInput, useFocus } from 'ink';
|
||||||
import TextInput from 'ink-text-input';
|
import TextInput from 'ink-text-input';
|
||||||
|
import { Colors } from '../colors.js';
|
||||||
|
|
||||||
interface InputPromptProps {
|
interface InputPromptProps {
|
||||||
onSubmit: (value: string) => void;
|
onSubmit: (value: string) => void;
|
||||||
|
@ -29,19 +30,18 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ onSubmit }) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box borderStyle="round" borderColor={Colors.AccentBlue} paddingX={1}>
|
||||||
borderStyle="round"
|
<Text color={Colors.AccentPurple}>> </Text>
|
||||||
borderColor={isFocused ? 'blue' : 'gray'}
|
<Box flexGrow={1}>
|
||||||
paddingX={1}
|
<TextInput
|
||||||
>
|
value={value}
|
||||||
<TextInput
|
onChange={setValue}
|
||||||
value={value}
|
placeholder="Enter your message or use tools..."
|
||||||
onChange={setValue}
|
onSubmit={() => {
|
||||||
placeholder="Enter your message or use tools..."
|
/* Empty to prevent double submission */
|
||||||
onSubmit={() => {
|
}}
|
||||||
/* Empty to prevent double submission */
|
/>
|
||||||
}}
|
</Box>
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text } from 'ink';
|
import { Box, Text } from 'ink';
|
||||||
import Spinner from 'ink-spinner';
|
import Spinner from 'ink-spinner';
|
||||||
|
import { Colors } from '../colors.js';
|
||||||
|
|
||||||
interface LoadingIndicatorProps {
|
interface LoadingIndicatorProps {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
@ -28,11 +29,11 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
||||||
<Box marginRight={1}>
|
<Box marginRight={1}>
|
||||||
<Spinner type="dots" />
|
<Spinner type="dots" />
|
||||||
</Box>
|
</Box>
|
||||||
<Text color="cyan">
|
<Text color={Colors.AccentPurple}>
|
||||||
{currentLoadingPhrase} ({elapsedTime}s)
|
{currentLoadingPhrase} ({elapsedTime}s)
|
||||||
</Text>
|
</Text>
|
||||||
<Box flexGrow={1}>{/* Spacer */}</Box>
|
<Box flexGrow={1}>{/* Spacer */}</Box>
|
||||||
<Text color="gray">(ESC to cancel)</Text>
|
<Text color={Colors.SubtleComment}>(ESC to cancel)</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,19 +6,28 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text } from 'ink';
|
import { Box, Text } from 'ink';
|
||||||
import { UI_WIDTH } from '../constants.js';
|
import { Colors } from '../colors.js';
|
||||||
|
|
||||||
export const Tips: React.FC = () => (
|
export const Tips: React.FC = () => (
|
||||||
<Box flexDirection="column" marginBottom={1} width={UI_WIDTH}>
|
<Box flexDirection="column" marginBottom={1}>
|
||||||
<Text>Tips for getting started:</Text>
|
<Text color={Colors.Foreground}>Tips for getting started:</Text>
|
||||||
<Text>
|
<Text color={Colors.Foreground}>
|
||||||
1. <Text bold>/help</Text> for more information.
|
1.{' '}
|
||||||
|
<Text bold color={Colors.AccentPurple}>
|
||||||
|
/help
|
||||||
|
</Text>{' '}
|
||||||
|
for more information.
|
||||||
</Text>
|
</Text>
|
||||||
<Text>
|
<Text color={Colors.Foreground}>
|
||||||
2. <Text bold>/init</Text> to create a GEMINI.md for instructions &
|
2.{' '}
|
||||||
context.
|
<Text bold color={Colors.AccentPurple}>
|
||||||
|
/init
|
||||||
|
</Text>{' '}
|
||||||
|
to create a GEMINI.md for instructions & context.
|
||||||
</Text>
|
</Text>
|
||||||
<Text>3. Ask coding questions, edit code or run commands.</Text>
|
<Text color={Colors.Foreground}>
|
||||||
<Text>4. Be specific for the best results.</Text>
|
3. Ask coding questions, edit code or run commands.
|
||||||
|
</Text>
|
||||||
|
<Text color={Colors.Foreground}>4. Be specific for the best results.</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text } from 'ink';
|
import { Box, Text } from 'ink';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
interface DiffLine {
|
interface DiffLine {
|
||||||
type: 'add' | 'del' | 'context' | 'hunk' | 'other';
|
type: 'add' | 'del' | 'context' | 'hunk' | 'other';
|
||||||
|
@ -96,7 +97,7 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
||||||
tabWidth = DEFAULT_TAB_WIDTH,
|
tabWidth = DEFAULT_TAB_WIDTH,
|
||||||
}) => {
|
}) => {
|
||||||
if (!diffContent || typeof diffContent !== 'string') {
|
if (!diffContent || typeof diffContent !== 'string') {
|
||||||
return <Text color="yellow">No diff content.</Text>;
|
return <Text color={Colors.AccentYellow}>No diff content.</Text>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedLines = parseDiffWithLineNumbers(diffContent);
|
const parsedLines = parseDiffWithLineNumbers(diffContent);
|
||||||
|
@ -114,7 +115,7 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
||||||
|
|
||||||
if (displayableLines.length === 0) {
|
if (displayableLines.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Box borderStyle="round" borderColor="gray" padding={1}>
|
<Box borderStyle="round" borderColor={Colors.SubtleComment} padding={1}>
|
||||||
<Text dimColor>No changes detected.</Text>
|
<Text dimColor>No changes detected.</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -137,7 +138,11 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
||||||
// --- End Modification ---
|
// --- End Modification ---
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box borderStyle="round" borderColor="gray" flexDirection="column">
|
<Box
|
||||||
|
borderStyle="round"
|
||||||
|
borderColor={Colors.SubtleComment}
|
||||||
|
flexDirection="column"
|
||||||
|
>
|
||||||
{/* Iterate over the lines that should be displayed (already normalized) */}
|
{/* Iterate over the lines that should be displayed (already normalized) */}
|
||||||
{displayableLines.map((line, index) => {
|
{displayableLines.map((line, index) => {
|
||||||
const key = `diff-line-${index}`;
|
const key = `diff-line-${index}`;
|
||||||
|
@ -165,7 +170,6 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown line type: ${line.type}`);
|
throw new Error(`Unknown line type: ${line.type}`);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the line content *after* stripping the calculated *minimum* baseIndentation.
|
// Render the line content *after* stripping the calculated *minimum* baseIndentation.
|
||||||
|
@ -175,7 +179,7 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
||||||
return (
|
return (
|
||||||
// Using your original rendering structure
|
// Using your original rendering structure
|
||||||
<Box key={key} flexDirection="row">
|
<Box key={key} flexDirection="row">
|
||||||
<Text color="gray">{gutterNumStr} </Text>
|
<Text color={Colors.SubtleComment}>{gutterNumStr} </Text>
|
||||||
<Text color={color} dimColor={dim}>
|
<Text color={color} dimColor={dim}>
|
||||||
{prefixSymbol}{' '}
|
{prefixSymbol}{' '}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, Box } from 'ink';
|
import { Text, Box } from 'ink';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
interface ErrorMessageProps {
|
interface ErrorMessageProps {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -18,10 +19,10 @@ export const ErrorMessage: React.FC<ErrorMessageProps> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="row">
|
<Box flexDirection="row">
|
||||||
<Box width={prefixWidth}>
|
<Box width={prefixWidth}>
|
||||||
<Text color="red">{prefix}</Text>
|
<Text color={Colors.AccentRed}>{prefix}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flexGrow={1}>
|
<Box flexGrow={1}>
|
||||||
<Text wrap="wrap" color="red">
|
<Text wrap="wrap" color={Colors.AccentRed}>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, Box } from 'ink';
|
import { Text, Box } from 'ink';
|
||||||
import { MarkdownRenderer } from '../../utils/MarkdownRenderer.js';
|
import { MarkdownRenderer } from '../../utils/MarkdownRenderer.js';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
interface GeminiMessageProps {
|
interface GeminiMessageProps {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -28,7 +29,7 @@ export const GeminiMessage: React.FC<GeminiMessageProps> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="row">
|
<Box flexDirection="row">
|
||||||
<Box width={prefixWidth}>
|
<Box width={prefixWidth}>
|
||||||
<Text color="blue">{prefix}</Text>
|
<Text color={Colors.AccentPurple}>{prefix}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flexGrow={1}></Box>
|
<Box flexGrow={1}></Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -38,7 +39,7 @@ export const GeminiMessage: React.FC<GeminiMessageProps> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="row">
|
<Box flexDirection="row">
|
||||||
<Box width={prefixWidth}>
|
<Box width={prefixWidth}>
|
||||||
<Text color="blue">{prefix}</Text>
|
<Text color={Colors.AccentPurple}>{prefix}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flexGrow={1} flexDirection="column">
|
<Box flexGrow={1} flexDirection="column">
|
||||||
{renderedBlocks}
|
{renderedBlocks}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, Box } from 'ink';
|
import { Text, Box } from 'ink';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
interface InfoMessageProps {
|
interface InfoMessageProps {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -18,10 +19,10 @@ export const InfoMessage: React.FC<InfoMessageProps> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="row">
|
<Box flexDirection="row">
|
||||||
<Box width={prefixWidth}>
|
<Box width={prefixWidth}>
|
||||||
<Text color="yellow">{prefix}</Text>
|
<Text color={Colors.AccentYellow}>{prefix}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flexGrow={1}>
|
<Box flexGrow={1}>
|
||||||
<Text wrap="wrap" color="yellow">
|
<Text wrap="wrap" color={Colors.AccentYellow}>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import { PartListUnion } from '@google/genai';
|
import { PartListUnion } from '@google/genai';
|
||||||
import { DiffRenderer } from './DiffRenderer.js';
|
import { DiffRenderer } from './DiffRenderer.js';
|
||||||
import { UI_WIDTH } from '../../constants.js';
|
import { UI_WIDTH } from '../../constants.js';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
export interface ToolConfirmationMessageProps {
|
export interface ToolConfirmationMessageProps {
|
||||||
confirmationDetails: ToolCallConfirmationDetails;
|
confirmationDetails: ToolCallConfirmationDetails;
|
||||||
|
@ -74,7 +75,9 @@ export const ToolConfirmationMessage: React.FC<
|
||||||
confirmationDetails as ToolExecuteConfirmationDetails;
|
confirmationDetails as ToolExecuteConfirmationDetails;
|
||||||
|
|
||||||
// For execution, we still need context display and description
|
// For execution, we still need context display and description
|
||||||
const commandDisplay = <Text color="cyan">{executionProps.command}</Text>;
|
const commandDisplay = (
|
||||||
|
<Text color={Colors.AccentCyan}>{executionProps.command}</Text>
|
||||||
|
);
|
||||||
|
|
||||||
// Combine command and description into bodyContent for layout consistency
|
// Combine command and description into bodyContent for layout consistency
|
||||||
bodyContent = (
|
bodyContent = (
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { IndividualToolCallDisplay, ToolCallStatus } from '../../types.js';
|
||||||
import { ToolMessage } from './ToolMessage.js';
|
import { ToolMessage } from './ToolMessage.js';
|
||||||
import { PartListUnion } from '@google/genai';
|
import { PartListUnion } from '@google/genai';
|
||||||
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
|
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
interface ToolGroupMessageProps {
|
interface ToolGroupMessageProps {
|
||||||
toolCalls: IndividualToolCallDisplay[];
|
toolCalls: IndividualToolCallDisplay[];
|
||||||
|
@ -22,7 +23,7 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}) => {
|
}) => {
|
||||||
const hasPending = toolCalls.some((t) => t.status === ToolCallStatus.Pending);
|
const hasPending = toolCalls.some((t) => t.status === ToolCallStatus.Pending);
|
||||||
const borderColor = hasPending ? 'yellow' : 'blue';
|
const borderColor = hasPending ? Colors.AccentYellow : Colors.AccentBlue;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" borderStyle="round" borderColor={borderColor}>
|
<Box flexDirection="column" borderStyle="round" borderColor={borderColor}>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
} from '../../types.js';
|
} from '../../types.js';
|
||||||
import { DiffRenderer } from './DiffRenderer.js';
|
import { DiffRenderer } from './DiffRenderer.js';
|
||||||
import { FileDiff, ToolResultDisplay } from '../../../tools/tools.js';
|
import { FileDiff, ToolResultDisplay } from '../../../tools/tools.js';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
|
export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
|
||||||
callId,
|
callId,
|
||||||
|
@ -31,7 +32,7 @@ export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
|
||||||
| undefined;
|
| undefined;
|
||||||
const typedResultDisplay = resultDisplay as ToolResultDisplay | undefined;
|
const typedResultDisplay = resultDisplay as ToolResultDisplay | undefined;
|
||||||
|
|
||||||
let color = 'gray';
|
let color = Colors.SubtleComment;
|
||||||
let prefix = '';
|
let prefix = '';
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ToolCallStatus.Pending:
|
case ToolCallStatus.Pending:
|
||||||
|
@ -41,15 +42,15 @@ export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
|
||||||
prefix = 'Executing:';
|
prefix = 'Executing:';
|
||||||
break;
|
break;
|
||||||
case ToolCallStatus.Confirming:
|
case ToolCallStatus.Confirming:
|
||||||
color = 'yellow';
|
color = Colors.AccentYellow;
|
||||||
prefix = 'Confirm:';
|
prefix = 'Confirm:';
|
||||||
break;
|
break;
|
||||||
case ToolCallStatus.Success:
|
case ToolCallStatus.Success:
|
||||||
color = 'green';
|
color = Colors.AccentGreen;
|
||||||
prefix = 'Success:';
|
prefix = 'Success:';
|
||||||
break;
|
break;
|
||||||
case ToolCallStatus.Error:
|
case ToolCallStatus.Error:
|
||||||
color = 'red';
|
color = Colors.AccentRed;
|
||||||
prefix = 'Error:';
|
prefix = 'Error:';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -60,11 +61,11 @@ export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
|
||||||
const title = `${prefix} ${name}`;
|
const title = `${prefix} ${name}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box key={callId} borderStyle="round" paddingX={1} flexDirection="column">
|
<Box key={callId} flexDirection="column" paddingX={1}>
|
||||||
<Box>
|
<Box>
|
||||||
{status === ToolCallStatus.Invoked && (
|
{status === ToolCallStatus.Invoked && (
|
||||||
<Box marginRight={1}>
|
<Box marginRight={1}>
|
||||||
<Text color="blue">
|
<Text color={Colors.AccentBlue}>
|
||||||
<Spinner type="dots" />
|
<Spinner type="dots" />
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -91,7 +92,7 @@ export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
|
||||||
)}
|
)}
|
||||||
{/* Display command for execute */}
|
{/* Display command for execute */}
|
||||||
{'command' in typedConfirmationDetails && (
|
{'command' in typedConfirmationDetails && (
|
||||||
<Text color="yellow">
|
<Text color={Colors.AccentYellow}>
|
||||||
Command:{' '}
|
Command:{' '}
|
||||||
{
|
{
|
||||||
(typedConfirmationDetails as ToolExecuteConfirmationDetails)
|
(typedConfirmationDetails as ToolExecuteConfirmationDetails)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, Box } from 'ink';
|
import { Text, Box } from 'ink';
|
||||||
|
import { Colors } from '../../colors.js';
|
||||||
|
|
||||||
interface UserMessageProps {
|
interface UserMessageProps {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -18,7 +19,7 @@ export const UserMessage: React.FC<UserMessageProps> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="row">
|
<Box flexDirection="row">
|
||||||
<Box width={prefixWidth}>
|
<Box width={prefixWidth}>
|
||||||
<Text color="gray">{prefix}</Text>
|
<Text color={Colors.SubtleComment}>{prefix}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flexGrow={1}>
|
<Box flexGrow={1}>
|
||||||
<Text wrap="wrap">{text}</Text>
|
<Text wrap="wrap">{text}</Text>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, Box } from 'ink';
|
import { Text, Box } from 'ink';
|
||||||
|
import { Colors } from '../colors.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class to render a subset of Markdown into Ink components.
|
* A utility class to render a subset of Markdown into Ink components.
|
||||||
|
@ -83,14 +84,14 @@ export class MarkdownRenderer {
|
||||||
const codeMatch = fullMatch.match(/^(`+)(.+?)\1$/s);
|
const codeMatch = fullMatch.match(/^(`+)(.+?)\1$/s);
|
||||||
if (codeMatch && codeMatch[2]) {
|
if (codeMatch && codeMatch[2]) {
|
||||||
renderedNode = (
|
renderedNode = (
|
||||||
<Text key={key} color="yellow">
|
<Text key={key} color={Colors.AccentPurple}>
|
||||||
{codeMatch[2]}
|
{codeMatch[2]}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Fallback for simple or non-matching cases
|
// Fallback for simple or non-matching cases
|
||||||
renderedNode = (
|
renderedNode = (
|
||||||
<Text key={key} color="yellow">
|
<Text key={key} color={Colors.AccentPurple}>
|
||||||
{fullMatch.slice(1, -1)}
|
{fullMatch.slice(1, -1)}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
@ -109,7 +110,7 @@ export class MarkdownRenderer {
|
||||||
renderedNode = (
|
renderedNode = (
|
||||||
<Text key={key}>
|
<Text key={key}>
|
||||||
{linkText}
|
{linkText}
|
||||||
<Text color="blue"> ({url})</Text>
|
<Text color={Colors.AccentBlue}> ({url})</Text>
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -160,7 +161,7 @@ export class MarkdownRenderer {
|
||||||
key={key}
|
key={key}
|
||||||
borderStyle="round"
|
borderStyle="round"
|
||||||
paddingX={1}
|
paddingX={1}
|
||||||
borderColor="gray"
|
borderColor={Colors.SubtleComment}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
>
|
>
|
||||||
{lang && <Text dimColor> {lang}</Text>}
|
{lang && <Text dimColor> {lang}</Text>}
|
||||||
|
@ -281,14 +282,14 @@ export class MarkdownRenderer {
|
||||||
switch (level /* ... (header styling as before) ... */) {
|
switch (level /* ... (header styling as before) ... */) {
|
||||||
case 1:
|
case 1:
|
||||||
headerNode = (
|
headerNode = (
|
||||||
<Text bold color="cyan">
|
<Text bold color={Colors.AccentCyan}>
|
||||||
{renderedHeaderText}
|
{renderedHeaderText}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
headerNode = (
|
headerNode = (
|
||||||
<Text bold color="blue">
|
<Text bold color={Colors.AccentBlue}>
|
||||||
{renderedHeaderText}
|
{renderedHeaderText}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
@ -298,7 +299,7 @@ export class MarkdownRenderer {
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
headerNode = (
|
headerNode = (
|
||||||
<Text italic color="gray">
|
<Text italic color={Colors.SubtleComment}>
|
||||||
{renderedHeaderText}
|
{renderedHeaderText}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue