mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-06 13:15:38 +08:00
Compare commits
2 Commits
v1.33.1
...
fix/do-not
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d638a8982c | ||
|
|
f238050b85 |
@@ -311,7 +311,7 @@ export function useChatComposerState({
|
||||
}, [addMessage]);
|
||||
|
||||
const executeCommand = useCallback(
|
||||
async (command: SlashCommand, rawInput?: string) => {
|
||||
async (command: SlashCommand, rawInput?: string, options?: { preserveInput?: boolean }) => {
|
||||
if (!command || !selectedProject) {
|
||||
return;
|
||||
}
|
||||
@@ -368,8 +368,10 @@ export function useChatComposerState({
|
||||
const result = (await response.json()) as CommandExecutionResult;
|
||||
if (result.type === 'builtin') {
|
||||
handleBuiltInCommand(result);
|
||||
setInput('');
|
||||
inputValueRef.current = '';
|
||||
if (!options?.preserveInput) {
|
||||
setInput('');
|
||||
inputValueRef.current = '';
|
||||
}
|
||||
} else if (result.type === 'custom') {
|
||||
await handleCustomCommand(result);
|
||||
}
|
||||
@@ -400,6 +402,19 @@ export function useChatComposerState({
|
||||
],
|
||||
);
|
||||
|
||||
const showCostModal = useCallback(() => {
|
||||
executeCommand(
|
||||
{
|
||||
name: '/cost',
|
||||
description: 'Display token usage information',
|
||||
namespace: 'builtin',
|
||||
metadata: { type: 'builtin' },
|
||||
} as SlashCommand,
|
||||
'/cost',
|
||||
{ preserveInput: true },
|
||||
);
|
||||
}, [executeCommand]);
|
||||
|
||||
const {
|
||||
slashCommands,
|
||||
slashCommandsCount,
|
||||
@@ -1049,5 +1064,6 @@ export function useChatComposerState({
|
||||
isInputFocused,
|
||||
commandModalPayload,
|
||||
closeCommandModal,
|
||||
showCostModal,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -178,6 +178,7 @@ function ChatInterface({
|
||||
isInputFocused: _isInputFocused,
|
||||
commandModalPayload,
|
||||
closeCommandModal,
|
||||
showCostModal,
|
||||
} = useChatComposerState({
|
||||
selectedProject,
|
||||
selectedSession,
|
||||
@@ -368,6 +369,7 @@ function ChatInterface({
|
||||
permissionMode={permissionMode}
|
||||
onModeSwitch={cyclePermissionMode}
|
||||
tokenBudget={tokenBudget}
|
||||
onShowTokenUsage={showCostModal}
|
||||
slashCommandsCount={slashCommandsCount}
|
||||
onToggleCommandMenu={handleToggleCommandMenu}
|
||||
hasInput={Boolean(input.trim())}
|
||||
|
||||
@@ -58,6 +58,7 @@ interface ChatComposerProps {
|
||||
permissionMode: PermissionMode | string;
|
||||
onModeSwitch: () => void;
|
||||
tokenBudget: Record<string, unknown> | null;
|
||||
onShowTokenUsage: () => void;
|
||||
slashCommandsCount: number;
|
||||
onToggleCommandMenu: () => void;
|
||||
hasInput: boolean;
|
||||
@@ -111,6 +112,7 @@ export default function ChatComposer({
|
||||
permissionMode,
|
||||
onModeSwitch,
|
||||
tokenBudget,
|
||||
onShowTokenUsage,
|
||||
slashCommandsCount,
|
||||
onToggleCommandMenu,
|
||||
hasInput,
|
||||
@@ -353,7 +355,7 @@ export default function ChatComposer({
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<TokenUsageSummary usage={tokenBudget} />
|
||||
<TokenUsageSummary usage={tokenBudget} onClick={onShowTokenUsage} />
|
||||
|
||||
<PromptInputButton
|
||||
tooltip={{ content: t('input.showAllCommands') }}
|
||||
|
||||
@@ -277,11 +277,15 @@ export default function ProviderSelectionEmptyState({
|
||||
>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate">{model.label}</div>
|
||||
{model.description && (
|
||||
{/*
|
||||
// * Temporarly commented out because the description of models from claude
|
||||
// * was a bit inconsistent. Will return it back when it becomes more consistent.
|
||||
*/}
|
||||
{/* {model.description && (
|
||||
<div className="truncate text-xs text-muted-foreground">
|
||||
{model.description}
|
||||
</div>
|
||||
)}
|
||||
)} */}
|
||||
</div>
|
||||
{isSelected && (
|
||||
<Check className="ml-auto h-4 w-4 shrink-0 text-primary" />
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ActivityIcon } from 'lucide-react';
|
||||
|
||||
type TokenUsageSummaryProps = {
|
||||
usage: Record<string, unknown> | null;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
const formatTokenCount = (value: number) => {
|
||||
@@ -29,7 +30,7 @@ const readUsageNumber = (value: unknown) => {
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
};
|
||||
|
||||
export default function TokenUsageSummary({ usage }: TokenUsageSummaryProps) {
|
||||
export default function TokenUsageSummary({ usage, onClick }: TokenUsageSummaryProps) {
|
||||
const breakdown =
|
||||
usage?.breakdown && typeof usage.breakdown === 'object'
|
||||
? usage.breakdown as Record<string, unknown>
|
||||
@@ -39,15 +40,18 @@ export default function TokenUsageSummary({ usage }: TokenUsageSummaryProps) {
|
||||
const usedTokens = readUsageNumber(usage?.used) || inputTokens + outputTokens;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="inline-flex h-9 items-center gap-1.5 rounded-lg border border-border/70 bg-background/70 px-2 text-xs text-muted-foreground shadow-sm transition-colors hover:border-primary/25 hover:text-foreground sm:gap-2 sm:px-2.5"
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className="inline-flex h-9 items-center gap-1.5 rounded-lg border border-border/70 bg-background/70 px-2 text-xs text-muted-foreground shadow-sm transition-colors hover:border-primary/25 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 sm:gap-2 sm:px-2.5"
|
||||
title={`${usedTokens.toLocaleString()} tokens used`}
|
||||
aria-label="Show token usage"
|
||||
>
|
||||
<span className="grid h-5 w-5 place-items-center rounded-md bg-primary/10 text-primary">
|
||||
<ActivityIcon className="h-3.5 w-3.5" />
|
||||
</span>
|
||||
<span className="font-medium text-foreground">{formatTokenCount(usedTokens)}</span>
|
||||
<span className="hidden text-muted-foreground/70 sm:inline">tokens</span>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user