mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 22:05:50 +00:00
更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)
* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-2): 格式化 commands (79 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-5): 格式化 components其余 + hooks + tools (232 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md - README.md: 大幅重写,更详细版本历史和配置示例 - Run.ps1: 新增 Windows 启动脚本 - TODO.md: 新增包完成清单 - V6.md: 删除(架构重构规划已不适用) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复以前的问题 * fix: 修复 login 面板的问题 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { feature } from 'bun:bundle';
|
||||
import * as React from 'react';
|
||||
import { Box, Text } from '../ink.js';
|
||||
import type { ContextData } from '../utils/analyzeContext.js';
|
||||
import { generateContextSuggestions } from '../utils/contextSuggestions.js';
|
||||
import { getDisplayPath } from '../utils/file.js';
|
||||
import { formatTokens } from '../utils/format.js';
|
||||
import { getSourceDisplayName, type SettingSource } from '../utils/settings/constants.js';
|
||||
import { plural } from '../utils/stringUtils.js';
|
||||
import { ContextSuggestions } from './ContextSuggestions.js';
|
||||
const RESERVED_CATEGORY_NAME = 'Autocompact buffer';
|
||||
import { feature } from 'bun:bundle'
|
||||
import * as React from 'react'
|
||||
import { Box, Text } from '../ink.js'
|
||||
import type { ContextData } from '../utils/analyzeContext.js'
|
||||
import { generateContextSuggestions } from '../utils/contextSuggestions.js'
|
||||
import { getDisplayPath } from '../utils/file.js'
|
||||
import { formatTokens } from '../utils/format.js'
|
||||
import {
|
||||
getSourceDisplayName,
|
||||
type SettingSource,
|
||||
} from '../utils/settings/constants.js'
|
||||
import { plural } from '../utils/stringUtils.js'
|
||||
import { ContextSuggestions } from './ContextSuggestions.js'
|
||||
|
||||
const RESERVED_CATEGORY_NAME = 'Autocompact buffer'
|
||||
|
||||
/**
|
||||
* One-liner for the legend header showing what context-collapse has done.
|
||||
@@ -18,95 +21,100 @@ const RESERVED_CATEGORY_NAME = 'Autocompact buffer';
|
||||
* their context was rewritten — the <collapsed> placeholders are isMeta
|
||||
* and don't appear in the conversation view.
|
||||
*/
|
||||
function CollapseStatus() {
|
||||
const $ = _c(2);
|
||||
if (feature("CONTEXT_COLLAPSE")) {
|
||||
let t0;
|
||||
let t1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = Symbol.for("react.early_return_sentinel");
|
||||
bb0: {
|
||||
const {
|
||||
getStats,
|
||||
isContextCollapseEnabled
|
||||
} = require("../services/contextCollapse/index.js") as typeof import('../services/contextCollapse/index.js');
|
||||
if (!isContextCollapseEnabled()) {
|
||||
t1 = null;
|
||||
break bb0;
|
||||
}
|
||||
const s = getStats();
|
||||
const {
|
||||
health: h
|
||||
} = s;
|
||||
const parts = [];
|
||||
if (s.collapsedSpans > 0) {
|
||||
parts.push(`${s.collapsedSpans} ${plural(s.collapsedSpans, "span")} summarized (${s.collapsedMessages} msgs)`);
|
||||
}
|
||||
if (s.stagedSpans > 0) {
|
||||
parts.push(`${s.stagedSpans} staged`);
|
||||
}
|
||||
const summary = parts.length > 0 ? parts.join(", ") : h.totalSpawns > 0 ? `${h.totalSpawns} ${plural(h.totalSpawns, "spawn")}, nothing staged yet` : "waiting for first trigger";
|
||||
let line2 = null;
|
||||
if (h.totalErrors > 0) {
|
||||
line2 = <Text color="warning">Collapse errors: {h.totalErrors}/{h.totalSpawns} spawns failed{h.lastError ? ` (last: ${h.lastError.slice(0, 60)})` : ""}</Text>;
|
||||
} else {
|
||||
if (h.emptySpawnWarningEmitted) {
|
||||
line2 = <Text color="warning">Collapse idle: {h.totalEmptySpawns} consecutive empty runs</Text>;
|
||||
}
|
||||
}
|
||||
t0 = <><Text dimColor={true}>Context strategy: collapse ({summary})</Text>{line2}</>;
|
||||
}
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
t1 = $[1];
|
||||
function CollapseStatus(): React.ReactNode {
|
||||
if (feature('CONTEXT_COLLAPSE')) {
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const { getStats, isContextCollapseEnabled } =
|
||||
require('../services/contextCollapse/index.js') as typeof import('../services/contextCollapse/index.js')
|
||||
/* eslint-enable @typescript-eslint/no-require-imports */
|
||||
if (!isContextCollapseEnabled()) return null
|
||||
|
||||
const s = getStats()
|
||||
const { health: h } = s
|
||||
|
||||
const parts: string[] = []
|
||||
if (s.collapsedSpans > 0) {
|
||||
parts.push(
|
||||
`${s.collapsedSpans} ${plural(s.collapsedSpans, 'span')} summarized (${s.collapsedMessages} msgs)`,
|
||||
)
|
||||
}
|
||||
if (t1 !== Symbol.for("react.early_return_sentinel")) {
|
||||
return t1;
|
||||
if (s.stagedSpans > 0) parts.push(`${s.stagedSpans} staged`)
|
||||
const summary =
|
||||
parts.length > 0
|
||||
? parts.join(', ')
|
||||
: h.totalSpawns > 0
|
||||
? `${h.totalSpawns} ${plural(h.totalSpawns, 'spawn')}, nothing staged yet`
|
||||
: 'waiting for first trigger'
|
||||
|
||||
let line2: React.ReactNode = null
|
||||
if (h.totalErrors > 0) {
|
||||
line2 = (
|
||||
<Text color="warning">
|
||||
Collapse errors: {h.totalErrors}/{h.totalSpawns} spawns failed
|
||||
{h.lastError ? ` (last: ${h.lastError.slice(0, 60)})` : ''}
|
||||
</Text>
|
||||
)
|
||||
} else if (h.emptySpawnWarningEmitted) {
|
||||
line2 = (
|
||||
<Text color="warning">
|
||||
Collapse idle: {h.totalEmptySpawns} consecutive empty runs
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
return t0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text dimColor>Context strategy: collapse ({summary})</Text>
|
||||
{line2}
|
||||
</>
|
||||
)
|
||||
}
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
// Order for displaying source groups: Project > User > Managed > Plugin > Built-in
|
||||
const SOURCE_DISPLAY_ORDER = ['Project', 'User', 'Managed', 'Plugin', 'Built-in'];
|
||||
const SOURCE_DISPLAY_ORDER = [
|
||||
'Project',
|
||||
'User',
|
||||
'Managed',
|
||||
'Plugin',
|
||||
'Built-in',
|
||||
]
|
||||
|
||||
/** Group items by source type for display, sorted by tokens descending within each group */
|
||||
function groupBySource<T extends {
|
||||
source: SettingSource | 'plugin' | 'built-in';
|
||||
tokens: number;
|
||||
}>(items: T[]): Map<string, T[]> {
|
||||
const groups = new Map<string, T[]>();
|
||||
function groupBySource<
|
||||
T extends { source: SettingSource | 'plugin' | 'built-in'; tokens: number },
|
||||
>(items: T[]): Map<string, T[]> {
|
||||
const groups = new Map<string, T[]>()
|
||||
for (const item of items) {
|
||||
const key = getSourceDisplayName(item.source);
|
||||
const existing = groups.get(key) || [];
|
||||
existing.push(item);
|
||||
groups.set(key, existing);
|
||||
const key = getSourceDisplayName(item.source)
|
||||
const existing = groups.get(key) || []
|
||||
existing.push(item)
|
||||
groups.set(key, existing)
|
||||
}
|
||||
// Sort each group by tokens descending
|
||||
for (const [key, group] of groups.entries()) {
|
||||
groups.set(key, group.sort((a, b) => b.tokens - a.tokens));
|
||||
groups.set(
|
||||
key,
|
||||
group.sort((a, b) => b.tokens - a.tokens),
|
||||
)
|
||||
}
|
||||
// Return groups in consistent order
|
||||
const orderedGroups = new Map<string, T[]>();
|
||||
const orderedGroups = new Map<string, T[]>()
|
||||
for (const source of SOURCE_DISPLAY_ORDER) {
|
||||
const group = groups.get(source);
|
||||
const group = groups.get(source)
|
||||
if (group) {
|
||||
orderedGroups.set(source, group);
|
||||
orderedGroups.set(source, group)
|
||||
}
|
||||
}
|
||||
return orderedGroups;
|
||||
return orderedGroups
|
||||
}
|
||||
|
||||
interface Props {
|
||||
data: ContextData;
|
||||
data: ContextData
|
||||
}
|
||||
export function ContextVisualization(t0) {
|
||||
const $ = _c(87);
|
||||
const {
|
||||
data
|
||||
} = t0;
|
||||
|
||||
export function ContextVisualization({ data }: Props): React.ReactNode {
|
||||
const {
|
||||
categories,
|
||||
totalTokens,
|
||||
@@ -116,373 +124,371 @@ export function ContextVisualization(t0) {
|
||||
model,
|
||||
memoryFiles,
|
||||
mcpTools,
|
||||
deferredBuiltinTools: t1,
|
||||
deferredBuiltinTools = [],
|
||||
systemTools,
|
||||
systemPromptSections,
|
||||
agents,
|
||||
skills,
|
||||
messageBreakdown
|
||||
} = data;
|
||||
let T0;
|
||||
let T1;
|
||||
let t2;
|
||||
let t3;
|
||||
let t4;
|
||||
let t5;
|
||||
let t6;
|
||||
let t7;
|
||||
let t8;
|
||||
let t9;
|
||||
if ($[0] !== categories || $[1] !== gridRows || $[2] !== mcpTools || $[3] !== model || $[4] !== percentage || $[5] !== rawMaxTokens || $[6] !== systemTools || $[7] !== t1 || $[8] !== totalTokens) {
|
||||
const deferredBuiltinTools = t1 === undefined ? [] : t1;
|
||||
const visibleCategories = categories.filter(_temp);
|
||||
let t10;
|
||||
if ($[19] !== categories) {
|
||||
t10 = categories.some(_temp2);
|
||||
$[19] = categories;
|
||||
$[20] = t10;
|
||||
} else {
|
||||
t10 = $[20];
|
||||
}
|
||||
const hasDeferredMcpTools = t10;
|
||||
const hasDeferredBuiltinTools = deferredBuiltinTools.length > 0;
|
||||
const autocompactCategory = categories.find(_temp3);
|
||||
T1 = Box;
|
||||
t6 = "column";
|
||||
t7 = 1;
|
||||
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t8 = <Text bold={true}>Context Usage</Text>;
|
||||
$[21] = t8;
|
||||
} else {
|
||||
t8 = $[21];
|
||||
}
|
||||
let t11;
|
||||
if ($[22] !== gridRows) {
|
||||
t11 = gridRows.map(_temp5);
|
||||
$[22] = gridRows;
|
||||
$[23] = t11;
|
||||
} else {
|
||||
t11 = $[23];
|
||||
}
|
||||
let t12;
|
||||
if ($[24] !== t11) {
|
||||
t12 = <Box flexDirection="column" flexShrink={0}>{t11}</Box>;
|
||||
$[24] = t11;
|
||||
$[25] = t12;
|
||||
} else {
|
||||
t12 = $[25];
|
||||
}
|
||||
let t13;
|
||||
if ($[26] !== totalTokens) {
|
||||
t13 = formatTokens(totalTokens);
|
||||
$[26] = totalTokens;
|
||||
$[27] = t13;
|
||||
} else {
|
||||
t13 = $[27];
|
||||
}
|
||||
let t14;
|
||||
if ($[28] !== rawMaxTokens) {
|
||||
t14 = formatTokens(rawMaxTokens);
|
||||
$[28] = rawMaxTokens;
|
||||
$[29] = t14;
|
||||
} else {
|
||||
t14 = $[29];
|
||||
}
|
||||
let t15;
|
||||
if ($[30] !== model || $[31] !== percentage || $[32] !== t13 || $[33] !== t14) {
|
||||
t15 = <Text dimColor={true}>{model} · {t13}/{t14}{" "}tokens ({percentage}%)</Text>;
|
||||
$[30] = model;
|
||||
$[31] = percentage;
|
||||
$[32] = t13;
|
||||
$[33] = t14;
|
||||
$[34] = t15;
|
||||
} else {
|
||||
t15 = $[34];
|
||||
}
|
||||
let t16;
|
||||
let t17;
|
||||
let t18;
|
||||
if ($[35] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t16 = <CollapseStatus />;
|
||||
t17 = <Text> </Text>;
|
||||
t18 = <Text dimColor={true} italic={true}>Estimated usage by category</Text>;
|
||||
$[35] = t16;
|
||||
$[36] = t17;
|
||||
$[37] = t18;
|
||||
} else {
|
||||
t16 = $[35];
|
||||
t17 = $[36];
|
||||
t18 = $[37];
|
||||
}
|
||||
let t19;
|
||||
if ($[38] !== rawMaxTokens) {
|
||||
t19 = (cat_2, index) => {
|
||||
const tokenDisplay = formatTokens(cat_2.tokens);
|
||||
const percentDisplay = cat_2.isDeferred ? "N/A" : `${(cat_2.tokens / rawMaxTokens * 100).toFixed(1)}%`;
|
||||
const isReserved = cat_2.name === RESERVED_CATEGORY_NAME;
|
||||
const displayName = cat_2.name;
|
||||
const symbol = cat_2.isDeferred ? " " : isReserved ? "\u26DD" : "\u26C1";
|
||||
return <Box key={index}><Text color={cat_2.color}>{symbol}</Text><Text> {displayName}: </Text><Text dimColor={true}>{tokenDisplay} tokens ({percentDisplay})</Text></Box>;
|
||||
};
|
||||
$[38] = rawMaxTokens;
|
||||
$[39] = t19;
|
||||
} else {
|
||||
t19 = $[39];
|
||||
}
|
||||
const t20 = visibleCategories.map(t19);
|
||||
let t21;
|
||||
if ($[40] !== categories || $[41] !== rawMaxTokens) {
|
||||
t21 = (categories.find(_temp6)?.tokens ?? 0) > 0 && <Box><Text dimColor={true}>⛶</Text><Text> Free space: </Text><Text dimColor={true}>{formatTokens(categories.find(_temp7)?.tokens || 0)}{" "}({((categories.find(_temp8)?.tokens || 0) / rawMaxTokens * 100).toFixed(1)}%)</Text></Box>;
|
||||
$[40] = categories;
|
||||
$[41] = rawMaxTokens;
|
||||
$[42] = t21;
|
||||
} else {
|
||||
t21 = $[42];
|
||||
}
|
||||
const t22 = autocompactCategory && autocompactCategory.tokens > 0 && <Box><Text color={autocompactCategory.color}>⛝</Text><Text dimColor={true}> {autocompactCategory.name}: </Text><Text dimColor={true}>{formatTokens(autocompactCategory.tokens)} tokens ({(autocompactCategory.tokens / rawMaxTokens * 100).toFixed(1)}%)</Text></Box>;
|
||||
let t23;
|
||||
if ($[43] !== t15 || $[44] !== t20 || $[45] !== t21 || $[46] !== t22) {
|
||||
t23 = <Box flexDirection="column" gap={0} flexShrink={0}>{t15}{t16}{t17}{t18}{t20}{t21}{t22}</Box>;
|
||||
$[43] = t15;
|
||||
$[44] = t20;
|
||||
$[45] = t21;
|
||||
$[46] = t22;
|
||||
$[47] = t23;
|
||||
} else {
|
||||
t23 = $[47];
|
||||
}
|
||||
if ($[48] !== t12 || $[49] !== t23) {
|
||||
t9 = <Box flexDirection="row" gap={2}>{t12}{t23}</Box>;
|
||||
$[48] = t12;
|
||||
$[49] = t23;
|
||||
$[50] = t9;
|
||||
} else {
|
||||
t9 = $[50];
|
||||
}
|
||||
T0 = Box;
|
||||
t2 = "column";
|
||||
t3 = -1;
|
||||
if ($[51] !== hasDeferredMcpTools || $[52] !== mcpTools) {
|
||||
t4 = mcpTools.length > 0 && <Box flexDirection="column" marginTop={1}><Box><Text bold={true}>MCP tools</Text><Text dimColor={true}>{" "}· /mcp{hasDeferredMcpTools ? " (loaded on-demand)" : ""}</Text></Box>{mcpTools.some(_temp9) && <Box flexDirection="column" marginTop={1}><Text dimColor={true}>Loaded</Text>{mcpTools.filter(_temp0).map(_temp1)}</Box>}{hasDeferredMcpTools && mcpTools.some(_temp10) && <Box flexDirection="column" marginTop={1}><Text dimColor={true}>Available</Text>{mcpTools.filter(_temp11).map(_temp12)}</Box>}{!hasDeferredMcpTools && mcpTools.map(_temp13)}</Box>;
|
||||
$[51] = hasDeferredMcpTools;
|
||||
$[52] = mcpTools;
|
||||
$[53] = t4;
|
||||
} else {
|
||||
t4 = $[53];
|
||||
}
|
||||
t5 = (systemTools && systemTools.length > 0 || hasDeferredBuiltinTools) && false && <Box flexDirection="column" marginTop={1}><Box><Text bold={true}>[ANT-ONLY] System tools</Text>{hasDeferredBuiltinTools && <Text dimColor={true}> (some loaded on-demand)</Text>}</Box><Box flexDirection="column" marginTop={1}><Text dimColor={true}>Loaded</Text>{systemTools?.map(_temp14)}{deferredBuiltinTools.filter(_temp15).map(_temp16)}</Box>{hasDeferredBuiltinTools && deferredBuiltinTools.some(_temp17) && <Box flexDirection="column" marginTop={1}><Text dimColor={true}>Available</Text>{deferredBuiltinTools.filter(_temp18).map(_temp19)}</Box>}</Box>;
|
||||
$[0] = categories;
|
||||
$[1] = gridRows;
|
||||
$[2] = mcpTools;
|
||||
$[3] = model;
|
||||
$[4] = percentage;
|
||||
$[5] = rawMaxTokens;
|
||||
$[6] = systemTools;
|
||||
$[7] = t1;
|
||||
$[8] = totalTokens;
|
||||
$[9] = T0;
|
||||
$[10] = T1;
|
||||
$[11] = t2;
|
||||
$[12] = t3;
|
||||
$[13] = t4;
|
||||
$[14] = t5;
|
||||
$[15] = t6;
|
||||
$[16] = t7;
|
||||
$[17] = t8;
|
||||
$[18] = t9;
|
||||
} else {
|
||||
T0 = $[9];
|
||||
T1 = $[10];
|
||||
t2 = $[11];
|
||||
t3 = $[12];
|
||||
t4 = $[13];
|
||||
t5 = $[14];
|
||||
t6 = $[15];
|
||||
t7 = $[16];
|
||||
t8 = $[17];
|
||||
t9 = $[18];
|
||||
}
|
||||
let t10;
|
||||
if ($[54] !== systemPromptSections) {
|
||||
t10 = systemPromptSections && systemPromptSections.length > 0 && false && <Box flexDirection="column" marginTop={1}><Text bold={true}>[ANT-ONLY] System prompt sections</Text>{systemPromptSections.map(_temp20)}</Box>;
|
||||
$[54] = systemPromptSections;
|
||||
$[55] = t10;
|
||||
} else {
|
||||
t10 = $[55];
|
||||
}
|
||||
let t11;
|
||||
if ($[56] !== agents) {
|
||||
t11 = agents.length > 0 && <Box flexDirection="column" marginTop={1}><Box><Text bold={true}>Custom agents</Text><Text dimColor={true}> · /agents</Text></Box>{Array.from(groupBySource(agents).entries()).map(_temp22)}</Box>;
|
||||
$[56] = agents;
|
||||
$[57] = t11;
|
||||
} else {
|
||||
t11 = $[57];
|
||||
}
|
||||
let t12;
|
||||
if ($[58] !== memoryFiles) {
|
||||
t12 = memoryFiles.length > 0 && <Box flexDirection="column" marginTop={1}><Box><Text bold={true}>Memory files</Text><Text dimColor={true}> · /memory</Text></Box>{memoryFiles.map(_temp23)}</Box>;
|
||||
$[58] = memoryFiles;
|
||||
$[59] = t12;
|
||||
} else {
|
||||
t12 = $[59];
|
||||
}
|
||||
let t13;
|
||||
if ($[60] !== skills) {
|
||||
t13 = skills && skills.tokens > 0 && <Box flexDirection="column" marginTop={1}><Box><Text bold={true}>Skills</Text><Text dimColor={true}> · /skills</Text></Box>{Array.from(groupBySource(skills.skillFrontmatter).entries()).map(_temp25)}</Box>;
|
||||
$[60] = skills;
|
||||
$[61] = t13;
|
||||
} else {
|
||||
t13 = $[61];
|
||||
}
|
||||
let t14;
|
||||
if ($[62] !== messageBreakdown) {
|
||||
t14 = messageBreakdown && false && <Box flexDirection="column" marginTop={1}><Text bold={true}>[ANT-ONLY] Message breakdown</Text><Box flexDirection="column" marginLeft={1}><Box><Text>Tool calls: </Text><Text dimColor={true}>{formatTokens(messageBreakdown.toolCallTokens)} tokens</Text></Box><Box><Text>Tool results: </Text><Text dimColor={true}>{formatTokens(messageBreakdown.toolResultTokens)} tokens</Text></Box><Box><Text>Attachments: </Text><Text dimColor={true}>{formatTokens(messageBreakdown.attachmentTokens)} tokens</Text></Box><Box><Text>Assistant messages (non-tool): </Text><Text dimColor={true}>{formatTokens(messageBreakdown.assistantMessageTokens)} tokens</Text></Box><Box><Text>User messages (non-tool-result): </Text><Text dimColor={true}>{formatTokens(messageBreakdown.userMessageTokens)} tokens</Text></Box></Box>{messageBreakdown.toolCallsByType.length > 0 && <Box flexDirection="column" marginTop={1}><Text bold={true}>[ANT-ONLY] Top tools</Text>{messageBreakdown.toolCallsByType.slice(0, 5).map(_temp26)}</Box>}{messageBreakdown.attachmentsByType.length > 0 && <Box flexDirection="column" marginTop={1}><Text bold={true}>[ANT-ONLY] Top attachments</Text>{messageBreakdown.attachmentsByType.slice(0, 5).map(_temp27)}</Box>}</Box>;
|
||||
$[62] = messageBreakdown;
|
||||
$[63] = t14;
|
||||
} else {
|
||||
t14 = $[63];
|
||||
}
|
||||
let t15;
|
||||
if ($[64] !== T0 || $[65] !== t10 || $[66] !== t11 || $[67] !== t12 || $[68] !== t13 || $[69] !== t14 || $[70] !== t2 || $[71] !== t3 || $[72] !== t4 || $[73] !== t5) {
|
||||
t15 = <T0 flexDirection={t2} marginLeft={t3}>{t4}{t5}{t10}{t11}{t12}{t13}{t14}</T0>;
|
||||
$[64] = T0;
|
||||
$[65] = t10;
|
||||
$[66] = t11;
|
||||
$[67] = t12;
|
||||
$[68] = t13;
|
||||
$[69] = t14;
|
||||
$[70] = t2;
|
||||
$[71] = t3;
|
||||
$[72] = t4;
|
||||
$[73] = t5;
|
||||
$[74] = t15;
|
||||
} else {
|
||||
t15 = $[74];
|
||||
}
|
||||
let t16;
|
||||
if ($[75] !== data) {
|
||||
t16 = generateContextSuggestions(data);
|
||||
$[75] = data;
|
||||
$[76] = t16;
|
||||
} else {
|
||||
t16 = $[76];
|
||||
}
|
||||
let t17;
|
||||
if ($[77] !== t16) {
|
||||
t17 = <ContextSuggestions suggestions={t16} />;
|
||||
$[77] = t16;
|
||||
$[78] = t17;
|
||||
} else {
|
||||
t17 = $[78];
|
||||
}
|
||||
let t18;
|
||||
if ($[79] !== T1 || $[80] !== t15 || $[81] !== t17 || $[82] !== t6 || $[83] !== t7 || $[84] !== t8 || $[85] !== t9) {
|
||||
t18 = <T1 flexDirection={t6} paddingLeft={t7}>{t8}{t9}{t15}{t17}</T1>;
|
||||
$[79] = T1;
|
||||
$[80] = t15;
|
||||
$[81] = t17;
|
||||
$[82] = t6;
|
||||
$[83] = t7;
|
||||
$[84] = t8;
|
||||
$[85] = t9;
|
||||
$[86] = t18;
|
||||
} else {
|
||||
t18 = $[86];
|
||||
}
|
||||
return t18;
|
||||
}
|
||||
function _temp27(attachment, i_10) {
|
||||
return <Box key={i_10} marginLeft={1}><Text>└ {attachment.name}: </Text><Text dimColor={true}>{formatTokens(attachment.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp26(tool_5, i_9) {
|
||||
return <Box key={i_9} marginLeft={1}><Text>└ {tool_5.name}: </Text><Text dimColor={true}>calls {formatTokens(tool_5.callTokens)}, results{" "}{formatTokens(tool_5.resultTokens)}</Text></Box>;
|
||||
}
|
||||
function _temp25(t0) {
|
||||
const [sourceDisplay_0, sourceSkills] = t0;
|
||||
return <Box key={sourceDisplay_0} flexDirection="column" marginTop={1}><Text dimColor={true}>{sourceDisplay_0}</Text>{sourceSkills.map(_temp24)}</Box>;
|
||||
}
|
||||
function _temp24(skill, i_8) {
|
||||
return <Box key={i_8}><Text>└ {skill.name}: </Text><Text dimColor={true}>{formatTokens(skill.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp23(file, i_7) {
|
||||
return <Box key={i_7}><Text>└ {getDisplayPath(file.path)}: </Text><Text dimColor={true}>{formatTokens(file.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp22(t0) {
|
||||
const [sourceDisplay, sourceAgents] = t0;
|
||||
return <Box key={sourceDisplay} flexDirection="column" marginTop={1}><Text dimColor={true}>{sourceDisplay}</Text>{sourceAgents.map(_temp21)}</Box>;
|
||||
}
|
||||
function _temp21(agent, i_6) {
|
||||
return <Box key={i_6}><Text>└ {agent.agentType}: </Text><Text dimColor={true}>{formatTokens(agent.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp20(section, i_5) {
|
||||
return <Box key={i_5}><Text>└ {section.name}: </Text><Text dimColor={true}>{formatTokens(section.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp19(tool_4, i_4) {
|
||||
return <Box key={i_4}><Text dimColor={true}>└ {tool_4.name}</Text></Box>;
|
||||
}
|
||||
function _temp18(t_4) {
|
||||
return !t_4.isLoaded;
|
||||
}
|
||||
function _temp17(t_5) {
|
||||
return !t_5.isLoaded;
|
||||
}
|
||||
function _temp16(tool_3, i_3) {
|
||||
return <Box key={`def-${i_3}`}><Text>└ {tool_3.name}: </Text><Text dimColor={true}>{formatTokens(tool_3.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp15(t_3) {
|
||||
return t_3.isLoaded;
|
||||
}
|
||||
function _temp14(tool_2, i_2) {
|
||||
return <Box key={`sys-${i_2}`}><Text>└ {tool_2.name}: </Text><Text dimColor={true}>{formatTokens(tool_2.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp13(tool_1, i_1) {
|
||||
return <Box key={i_1}><Text>└ {tool_1.name}: </Text><Text dimColor={true}>{formatTokens(tool_1.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp12(tool_0, i_0) {
|
||||
return <Box key={i_0}><Text dimColor={true}>└ {tool_0.name}</Text></Box>;
|
||||
}
|
||||
function _temp11(t_1) {
|
||||
return !t_1.isLoaded;
|
||||
}
|
||||
function _temp10(t_2) {
|
||||
return !t_2.isLoaded;
|
||||
}
|
||||
function _temp1(tool, i) {
|
||||
return <Box key={i}><Text>└ {tool.name}: </Text><Text dimColor={true}>{formatTokens(tool.tokens)} tokens</Text></Box>;
|
||||
}
|
||||
function _temp0(t) {
|
||||
return t.isLoaded;
|
||||
}
|
||||
function _temp9(t_0) {
|
||||
return t_0.isLoaded;
|
||||
}
|
||||
function _temp8(c_0) {
|
||||
return c_0.name === "Free space";
|
||||
}
|
||||
function _temp7(c) {
|
||||
return c.name === "Free space";
|
||||
}
|
||||
function _temp6(c_1) {
|
||||
return c_1.name === "Free space";
|
||||
}
|
||||
function _temp5(row, rowIndex) {
|
||||
return <Box key={rowIndex} flexDirection="row" marginLeft={-1}>{row.map(_temp4)}</Box>;
|
||||
}
|
||||
function _temp4(square, colIndex) {
|
||||
if (square.categoryName === "Free space") {
|
||||
return <Text key={colIndex} dimColor={true}>{"\u26F6 "}</Text>;
|
||||
}
|
||||
if (square.categoryName === RESERVED_CATEGORY_NAME) {
|
||||
return <Text key={colIndex} color={square.color}>{"\u26DD "}</Text>;
|
||||
}
|
||||
return <Text key={colIndex} color={square.color}>{square.squareFullness >= 0.7 ? "\u26C1 " : "\u26C0 "}</Text>;
|
||||
}
|
||||
function _temp3(cat_1) {
|
||||
return cat_1.name === RESERVED_CATEGORY_NAME;
|
||||
}
|
||||
function _temp2(cat_0) {
|
||||
return cat_0.isDeferred && cat_0.name.includes("MCP");
|
||||
}
|
||||
function _temp(cat) {
|
||||
return cat.tokens > 0 && cat.name !== "Free space" && cat.name !== RESERVED_CATEGORY_NAME && !cat.isDeferred;
|
||||
messageBreakdown,
|
||||
} = data
|
||||
|
||||
// Filter out categories with 0 tokens for the legend, and exclude Free space, Autocompact buffer, and deferred
|
||||
const visibleCategories = categories.filter(
|
||||
cat =>
|
||||
cat.tokens > 0 &&
|
||||
cat.name !== 'Free space' &&
|
||||
cat.name !== RESERVED_CATEGORY_NAME &&
|
||||
!cat.isDeferred,
|
||||
)
|
||||
// Check if MCP tools are deferred (loaded on-demand via tool search)
|
||||
const hasDeferredMcpTools = categories.some(
|
||||
cat => cat.isDeferred && cat.name.includes('MCP'),
|
||||
)
|
||||
// Check if builtin tools are deferred
|
||||
const hasDeferredBuiltinTools = deferredBuiltinTools.length > 0
|
||||
const autocompactCategory = categories.find(
|
||||
cat => cat.name === RESERVED_CATEGORY_NAME,
|
||||
)
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" paddingLeft={1}>
|
||||
<Text bold>Context Usage</Text>
|
||||
<Box flexDirection="row" gap={2}>
|
||||
{/* Fixed size grid */}
|
||||
<Box flexDirection="column" flexShrink={0}>
|
||||
{gridRows.map((row, rowIndex) => (
|
||||
<Box key={rowIndex} flexDirection="row" marginLeft={-1}>
|
||||
{row.map((square, colIndex) => {
|
||||
if (square.categoryName === 'Free space') {
|
||||
return (
|
||||
<Text key={colIndex} dimColor>
|
||||
{'⛶ '}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
if (square.categoryName === RESERVED_CATEGORY_NAME) {
|
||||
return (
|
||||
<Text key={colIndex} color={square.color}>
|
||||
{'⛝ '}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Text key={colIndex} color={square.color}>
|
||||
{square.squareFullness >= 0.7 ? '⛁ ' : '⛀ '}
|
||||
</Text>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
{/* Legend to the right */}
|
||||
<Box flexDirection="column" gap={0} flexShrink={0}>
|
||||
<Text dimColor>
|
||||
{model} · {formatTokens(totalTokens)}/{formatTokens(rawMaxTokens)}{' '}
|
||||
tokens ({percentage}%)
|
||||
</Text>
|
||||
<CollapseStatus />
|
||||
<Text> </Text>
|
||||
<Text dimColor italic>
|
||||
Estimated usage by category
|
||||
</Text>
|
||||
{visibleCategories.map((cat, index) => {
|
||||
const tokenDisplay = formatTokens(cat.tokens)
|
||||
// Show "N/A" for deferred categories since they don't count toward context
|
||||
const percentDisplay = cat.isDeferred
|
||||
? 'N/A'
|
||||
: `${((cat.tokens / rawMaxTokens) * 100).toFixed(1)}%`
|
||||
const isReserved = cat.name === RESERVED_CATEGORY_NAME
|
||||
const displayName = cat.name
|
||||
// Deferred categories don't appear in grid, so show blank instead of symbol
|
||||
const symbol = cat.isDeferred ? ' ' : isReserved ? '⛝' : '⛁'
|
||||
|
||||
return (
|
||||
<Box key={index}>
|
||||
<Text color={cat.color}>{symbol}</Text>
|
||||
<Text> {displayName}: </Text>
|
||||
<Text dimColor>
|
||||
{tokenDisplay} tokens ({percentDisplay})
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
{(categories.find(c => c.name === 'Free space')?.tokens ?? 0) > 0 && (
|
||||
<Box>
|
||||
<Text dimColor>⛶</Text>
|
||||
<Text> Free space: </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(
|
||||
categories.find(c => c.name === 'Free space')?.tokens || 0,
|
||||
)}{' '}
|
||||
(
|
||||
{(
|
||||
((categories.find(c => c.name === 'Free space')?.tokens ||
|
||||
0) /
|
||||
rawMaxTokens) *
|
||||
100
|
||||
).toFixed(1)}
|
||||
%)
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
{autocompactCategory && autocompactCategory.tokens > 0 && (
|
||||
<Box>
|
||||
<Text color={autocompactCategory.color}>⛝</Text>
|
||||
<Text dimColor> {autocompactCategory.name}: </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(autocompactCategory.tokens)} tokens (
|
||||
{((autocompactCategory.tokens / rawMaxTokens) * 100).toFixed(1)}
|
||||
%)
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box flexDirection="column" marginLeft={-1}>
|
||||
{mcpTools.length > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Box>
|
||||
<Text bold>MCP tools</Text>
|
||||
<Text dimColor>
|
||||
{' '}
|
||||
· /mcp{hasDeferredMcpTools ? ' (loaded on-demand)' : ''}
|
||||
</Text>
|
||||
</Box>
|
||||
{/* Show loaded tools first */}
|
||||
{mcpTools.some(t => t.isLoaded) && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text dimColor>Loaded</Text>
|
||||
{mcpTools
|
||||
.filter(t => t.isLoaded)
|
||||
.map((tool, i) => (
|
||||
<Box key={i}>
|
||||
<Text>└ {tool.name}: </Text>
|
||||
<Text dimColor>{formatTokens(tool.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{/* Show available (deferred) tools */}
|
||||
{hasDeferredMcpTools && mcpTools.some(t => !t.isLoaded) && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text dimColor>Available</Text>
|
||||
{mcpTools
|
||||
.filter(t => !t.isLoaded)
|
||||
.map((tool, i) => (
|
||||
<Box key={i}>
|
||||
<Text dimColor>└ {tool.name}</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{/* Show all tools normally when not deferred */}
|
||||
{!hasDeferredMcpTools &&
|
||||
mcpTools.map((tool, i) => (
|
||||
<Box key={i}>
|
||||
<Text>└ {tool.name}: </Text>
|
||||
<Text dimColor>{formatTokens(tool.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Show builtin tools: always-loaded + deferred (ant-only) */}
|
||||
{((systemTools && systemTools.length > 0) || hasDeferredBuiltinTools) &&
|
||||
process.env.USER_TYPE === 'ant' && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Box>
|
||||
<Text bold>[ANT-ONLY] System tools</Text>
|
||||
{hasDeferredBuiltinTools && (
|
||||
<Text dimColor> (some loaded on-demand)</Text>
|
||||
)}
|
||||
</Box>
|
||||
{/* Always-loaded + deferred-but-loaded tools */}
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text dimColor>Loaded</Text>
|
||||
{systemTools?.map((tool, i) => (
|
||||
<Box key={`sys-${i}`}>
|
||||
<Text>└ {tool.name}: </Text>
|
||||
<Text dimColor>{formatTokens(tool.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
{deferredBuiltinTools
|
||||
.filter(t => t.isLoaded)
|
||||
.map((tool, i) => (
|
||||
<Box key={`def-${i}`}>
|
||||
<Text>└ {tool.name}: </Text>
|
||||
<Text dimColor>{formatTokens(tool.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
{/* Deferred (not yet loaded) tools */}
|
||||
{hasDeferredBuiltinTools &&
|
||||
deferredBuiltinTools.some(t => !t.isLoaded) && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text dimColor>Available</Text>
|
||||
{deferredBuiltinTools
|
||||
.filter(t => !t.isLoaded)
|
||||
.map((tool, i) => (
|
||||
<Box key={i}>
|
||||
<Text dimColor>└ {tool.name}</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{systemPromptSections &&
|
||||
systemPromptSections.length > 0 &&
|
||||
process.env.USER_TYPE === 'ant' && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text bold>[ANT-ONLY] System prompt sections</Text>
|
||||
{systemPromptSections.map((section, i) => (
|
||||
<Box key={i}>
|
||||
<Text>└ {section.name}: </Text>
|
||||
<Text dimColor>{formatTokens(section.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{agents.length > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Box>
|
||||
<Text bold>Custom agents</Text>
|
||||
<Text dimColor> · /agents</Text>
|
||||
</Box>
|
||||
{Array.from(groupBySource(agents).entries()).map(
|
||||
([sourceDisplay, sourceAgents]) => (
|
||||
<Box key={sourceDisplay} flexDirection="column" marginTop={1}>
|
||||
<Text dimColor>{sourceDisplay}</Text>
|
||||
{sourceAgents.map((agent, i) => (
|
||||
<Box key={i}>
|
||||
<Text>└ {agent.agentType}: </Text>
|
||||
<Text dimColor>{formatTokens(agent.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
),
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{memoryFiles.length > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Box>
|
||||
<Text bold>Memory files</Text>
|
||||
<Text dimColor> · /memory</Text>
|
||||
</Box>
|
||||
{memoryFiles.map((file, i) => (
|
||||
<Box key={i}>
|
||||
<Text>└ {getDisplayPath(file.path)}: </Text>
|
||||
<Text dimColor>{formatTokens(file.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{skills && skills.tokens > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Box>
|
||||
<Text bold>Skills</Text>
|
||||
<Text dimColor> · /skills</Text>
|
||||
</Box>
|
||||
{Array.from(groupBySource(skills.skillFrontmatter).entries()).map(
|
||||
([sourceDisplay, sourceSkills]) => (
|
||||
<Box key={sourceDisplay} flexDirection="column" marginTop={1}>
|
||||
<Text dimColor>{sourceDisplay}</Text>
|
||||
{sourceSkills.map((skill, i) => (
|
||||
<Box key={i}>
|
||||
<Text>└ {skill.name}: </Text>
|
||||
<Text dimColor>{formatTokens(skill.tokens)} tokens</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
),
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{messageBreakdown && process.env.USER_TYPE === 'ant' && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text bold>[ANT-ONLY] Message breakdown</Text>
|
||||
|
||||
<Box flexDirection="column" marginLeft={1}>
|
||||
<Box>
|
||||
<Text>Tool calls: </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(messageBreakdown.toolCallTokens)} tokens
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text>Tool results: </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(messageBreakdown.toolResultTokens)} tokens
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text>Attachments: </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(messageBreakdown.attachmentTokens)} tokens
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text>Assistant messages (non-tool): </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(messageBreakdown.assistantMessageTokens)} tokens
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text>User messages (non-tool-result): </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(messageBreakdown.userMessageTokens)} tokens
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{messageBreakdown.toolCallsByType.length > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text bold>[ANT-ONLY] Top tools</Text>
|
||||
{messageBreakdown.toolCallsByType.slice(0, 5).map((tool, i) => (
|
||||
<Box key={i} marginLeft={1}>
|
||||
<Text>└ {tool.name}: </Text>
|
||||
<Text dimColor>
|
||||
calls {formatTokens(tool.callTokens)}, results{' '}
|
||||
{formatTokens(tool.resultTokens)}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{messageBreakdown.attachmentsByType.length > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text bold>[ANT-ONLY] Top attachments</Text>
|
||||
{messageBreakdown.attachmentsByType
|
||||
.slice(0, 5)
|
||||
.map((attachment, i) => (
|
||||
<Box key={i} marginLeft={1}>
|
||||
<Text>└ {attachment.name}: </Text>
|
||||
<Text dimColor>
|
||||
{formatTokens(attachment.tokens)} tokens
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<ContextSuggestions suggestions={generateContextSuggestions(data)} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user