feat(context): 添加上下文压缩 API 和 UI 组件

Server API:
- 扩展 Agent Adapter 接口添加压缩相关方法
- 新增 context.ts 路由 (GET /sessions/:id/context, POST /sessions/:id/compress)
- 扩展 config.ts 添加摘要模型配置接口 (GET/PUT /config/summary)

UI 组件:
- 新增 ContextUsage 组件显示上下文使用情况
- 扩展 ConfigPanel 添加摘要模型配置区域
- 添加 API 客户端方法和类型定义

Web 集成:
- 在 Chat 页面头部集成 ContextUsage 紧凑模式显示
This commit is contained in:
2025-12-14 20:33:51 +08:00
parent f54f24b079
commit 70a9a154a4
13 changed files with 934 additions and 10 deletions
+64
View File
@@ -45,6 +45,11 @@ import type {
CustomProviderDefinition,
ProviderConfig,
ConnectionTestResult,
// Context & Summary types
ContextUsageInfo,
CompressionResult,
SummaryConfigInfo,
SummaryConfigInput,
} from './types.js';
// Re-export types
@@ -113,6 +118,14 @@ export type {
CustomProviderDefinition,
ProviderConfig,
ConnectionTestResult,
// Context compression types
TokenUsage,
ContextUsageInfo,
CompressionStatus,
CompressionType,
CompressionResult,
SummaryConfigInfo,
SummaryConfigInput,
} from './types.js';
// API Configuration
@@ -936,3 +949,54 @@ export async function deleteProviderModel(
}> {
return request('DELETE', `/providers/${encodeURIComponent(providerId)}/models/${encodeURIComponent(modelId)}`);
}
// ============ Context Compression API ============
/**
* 获取会话上下文使用情况
*/
export async function getContextUsage(sessionId: string): Promise<{
success: boolean;
data?: ContextUsageInfo;
error?: string;
}> {
return request('GET', `/sessions/${encodeURIComponent(sessionId)}/context`);
}
/**
* 触发上下文压缩
*/
export async function compressContext(
sessionId: string,
options?: { force?: boolean }
): Promise<{
success: boolean;
data?: CompressionResult;
error?: string;
}> {
return request('POST', `/sessions/${encodeURIComponent(sessionId)}/compress`, options || {});
}
/**
* 获取摘要模型配置
*/
export async function getSummaryConfig(): Promise<{
success: boolean;
data?: SummaryConfigInfo;
error?: string;
}> {
return request('GET', '/config/summary');
}
/**
* 更新摘要模型配置
*/
export async function updateSummaryConfig(
config: SummaryConfigInput
): Promise<{
success: boolean;
data?: SummaryConfigInfo;
error?: string;
}> {
return request('PUT', '/config/summary', config);
}
+73
View File
@@ -711,3 +711,76 @@ export interface ConnectionTestResult {
/** 错误信息 */
error?: string;
}
// ============ 上下文压缩相关 ============
/** Token 使用情况 */
export interface TokenUsage {
/** 当前输入 tokens */
input: number;
/** 上下文限制 */
contextLimit: number;
/** 可用空间 */
available: number;
/** 使用百分比 (0-100) */
usagePercent: number;
}
/** 上下文使用信息(包含格式化字符串) */
export interface ContextUsageInfo extends TokenUsage {
/** 格式化字符串,如 "12.5K/100K (12%)" */
formatted: string;
/** 是否建议压缩 */
shouldCompress: boolean;
}
/** 压缩状态 */
export type CompressionStatus =
| 'success'
| 'noop'
| 'failed_empty_summary'
| 'failed_token_inflated'
| 'failed_error';
/** 压缩类型 */
export type CompressionType = 'prune' | 'compaction' | 'both' | 'none';
/** 压缩结果 */
export interface CompressionResult {
/** 压缩类型 */
type: CompressionType;
/** 压缩状态 */
status: CompressionStatus;
/** 释放的 tokens */
freedTokens: number;
/** 错误信息 */
error?: string;
/** 原始 tokens(压缩前) */
originalTokens?: number;
/** 摘要 tokens(压缩后) */
summaryTokens?: number;
}
/** 摘要模型配置信息(不含 API Key 明文) */
export interface SummaryConfigInfo {
/** 提供商类型 */
provider?: string;
/** 模型名称 */
model?: string;
/** 是否已配置 API Key */
hasApiKey: boolean;
/** 服务地址 */
baseUrl?: string;
}
/** 摘要模型配置输入 */
export interface SummaryConfigInput {
/** 提供商类型 */
provider?: string;
/** 模型名称 */
model?: string;
/** API Key */
apiKey?: string;
/** 服务地址 */
baseUrl?: string;
}