mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-08 06:25:34 +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]);
|
}, [addMessage]);
|
||||||
|
|
||||||
const executeCommand = useCallback(
|
const executeCommand = useCallback(
|
||||||
async (command: SlashCommand, rawInput?: string) => {
|
async (command: SlashCommand, rawInput?: string, options?: { preserveInput?: boolean }) => {
|
||||||
if (!command || !selectedProject) {
|
if (!command || !selectedProject) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -368,8 +368,10 @@ export function useChatComposerState({
|
|||||||
const result = (await response.json()) as CommandExecutionResult;
|
const result = (await response.json()) as CommandExecutionResult;
|
||||||
if (result.type === 'builtin') {
|
if (result.type === 'builtin') {
|
||||||
handleBuiltInCommand(result);
|
handleBuiltInCommand(result);
|
||||||
setInput('');
|
if (!options?.preserveInput) {
|
||||||
inputValueRef.current = '';
|
setInput('');
|
||||||
|
inputValueRef.current = '';
|
||||||
|
}
|
||||||
} else if (result.type === 'custom') {
|
} else if (result.type === 'custom') {
|
||||||
await handleCustomCommand(result);
|
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 {
|
const {
|
||||||
slashCommands,
|
slashCommands,
|
||||||
slashCommandsCount,
|
slashCommandsCount,
|
||||||
@@ -1049,5 +1064,6 @@ export function useChatComposerState({
|
|||||||
isInputFocused,
|
isInputFocused,
|
||||||
commandModalPayload,
|
commandModalPayload,
|
||||||
closeCommandModal,
|
closeCommandModal,
|
||||||
|
showCostModal,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ function ChatInterface({
|
|||||||
isInputFocused: _isInputFocused,
|
isInputFocused: _isInputFocused,
|
||||||
commandModalPayload,
|
commandModalPayload,
|
||||||
closeCommandModal,
|
closeCommandModal,
|
||||||
|
showCostModal,
|
||||||
} = useChatComposerState({
|
} = useChatComposerState({
|
||||||
selectedProject,
|
selectedProject,
|
||||||
selectedSession,
|
selectedSession,
|
||||||
@@ -368,6 +369,7 @@ function ChatInterface({
|
|||||||
permissionMode={permissionMode}
|
permissionMode={permissionMode}
|
||||||
onModeSwitch={cyclePermissionMode}
|
onModeSwitch={cyclePermissionMode}
|
||||||
tokenBudget={tokenBudget}
|
tokenBudget={tokenBudget}
|
||||||
|
onShowTokenUsage={showCostModal}
|
||||||
slashCommandsCount={slashCommandsCount}
|
slashCommandsCount={slashCommandsCount}
|
||||||
onToggleCommandMenu={handleToggleCommandMenu}
|
onToggleCommandMenu={handleToggleCommandMenu}
|
||||||
hasInput={Boolean(input.trim())}
|
hasInput={Boolean(input.trim())}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ interface ChatComposerProps {
|
|||||||
permissionMode: PermissionMode | string;
|
permissionMode: PermissionMode | string;
|
||||||
onModeSwitch: () => void;
|
onModeSwitch: () => void;
|
||||||
tokenBudget: Record<string, unknown> | null;
|
tokenBudget: Record<string, unknown> | null;
|
||||||
|
onShowTokenUsage: () => void;
|
||||||
slashCommandsCount: number;
|
slashCommandsCount: number;
|
||||||
onToggleCommandMenu: () => void;
|
onToggleCommandMenu: () => void;
|
||||||
hasInput: boolean;
|
hasInput: boolean;
|
||||||
@@ -111,6 +112,7 @@ export default function ChatComposer({
|
|||||||
permissionMode,
|
permissionMode,
|
||||||
onModeSwitch,
|
onModeSwitch,
|
||||||
tokenBudget,
|
tokenBudget,
|
||||||
|
onShowTokenUsage,
|
||||||
slashCommandsCount,
|
slashCommandsCount,
|
||||||
onToggleCommandMenu,
|
onToggleCommandMenu,
|
||||||
hasInput,
|
hasInput,
|
||||||
@@ -353,7 +355,7 @@ export default function ChatComposer({
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<TokenUsageSummary usage={tokenBudget} />
|
<TokenUsageSummary usage={tokenBudget} onClick={onShowTokenUsage} />
|
||||||
|
|
||||||
<PromptInputButton
|
<PromptInputButton
|
||||||
tooltip={{ content: t('input.showAllCommands') }}
|
tooltip={{ content: t('input.showAllCommands') }}
|
||||||
|
|||||||
@@ -277,11 +277,15 @@ export default function ProviderSelectionEmptyState({
|
|||||||
>
|
>
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="truncate">{model.label}</div>
|
<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">
|
<div className="truncate text-xs text-muted-foreground">
|
||||||
{model.description}
|
{model.description}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
{isSelected && (
|
{isSelected && (
|
||||||
<Check className="ml-auto h-4 w-4 shrink-0 text-primary" />
|
<Check className="ml-auto h-4 w-4 shrink-0 text-primary" />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ActivityIcon } from 'lucide-react';
|
|||||||
|
|
||||||
type TokenUsageSummaryProps = {
|
type TokenUsageSummaryProps = {
|
||||||
usage: Record<string, unknown> | null;
|
usage: Record<string, unknown> | null;
|
||||||
|
onClick?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatTokenCount = (value: number) => {
|
const formatTokenCount = (value: number) => {
|
||||||
@@ -29,7 +30,7 @@ const readUsageNumber = (value: unknown) => {
|
|||||||
return Number.isFinite(parsed) ? parsed : 0;
|
return Number.isFinite(parsed) ? parsed : 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function TokenUsageSummary({ usage }: TokenUsageSummaryProps) {
|
export default function TokenUsageSummary({ usage, onClick }: TokenUsageSummaryProps) {
|
||||||
const breakdown =
|
const breakdown =
|
||||||
usage?.breakdown && typeof usage.breakdown === 'object'
|
usage?.breakdown && typeof usage.breakdown === 'object'
|
||||||
? usage.breakdown as Record<string, unknown>
|
? usage.breakdown as Record<string, unknown>
|
||||||
@@ -39,15 +40,18 @@ export default function TokenUsageSummary({ usage }: TokenUsageSummaryProps) {
|
|||||||
const usedTokens = readUsageNumber(usage?.used) || inputTokens + outputTokens;
|
const usedTokens = readUsageNumber(usage?.used) || inputTokens + outputTokens;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<button
|
||||||
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"
|
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`}
|
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">
|
<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" />
|
<ActivityIcon className="h-3.5 w-3.5" />
|
||||||
</span>
|
</span>
|
||||||
<span className="font-medium text-foreground">{formatTokenCount(usedTokens)}</span>
|
<span className="font-medium text-foreground">{formatTokenCount(usedTokens)}</span>
|
||||||
<span className="hidden text-muted-foreground/70 sm:inline">tokens</span>
|
<span className="hidden text-muted-foreground/70 sm:inline">tokens</span>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user