343 lines
13 KiB
TypeScript
343 lines
13 KiB
TypeScript
/**
|
||
* 主进程 / 渲染进程共享的类型与 IPC 契约。
|
||
*
|
||
* 已存 API Key 不返回渲染进程;用户可在模型表单编辑地址和新密钥。
|
||
* 对话由主进程 Claude Code 内核完成;模型配置与连接测试仍在主进程。
|
||
*/
|
||
|
||
/** 会话内的一条消息(对外视图) */
|
||
import type { ArtifactContent, ChatAttachment, ChatInteraction, MessageQuote, PlanContent, TaskContent, UserContentBlock } from './conversation'
|
||
|
||
export interface ChatMessage {
|
||
id: string
|
||
role: 'user' | 'assistant'
|
||
content: string
|
||
/** 助手消息携带的工具调用记录 */
|
||
tools?: ToolCallRecord[]
|
||
/** 按事件顺序记录正文与工具位置;旧会话没有此字段时按兼容方式渲染。 */
|
||
parts?: MessagePart[]
|
||
attachments?: ChatAttachment[]
|
||
resources?: string[]
|
||
/** 发送时引用进对话的表格等内容块快照(WorkBuddy messageQuote)。 */
|
||
quotes?: MessageQuote[]
|
||
/** Ordered inline presentation, validated against content and its actual payload collections. */
|
||
userContent?: UserContentBlock[]
|
||
skills?: Array<{ id: string; name: string; uri: string }>
|
||
assistantDisplay?: import('./capabilities').ExpertBinding
|
||
/** The model selected when this assistant turn started; kept with history. */
|
||
modelId?: string
|
||
modelName?: string
|
||
/** Last actual upstream request sample, with that turn's frozen window. Never a session sum. */
|
||
contextUsage?: ContextUsageSnapshot
|
||
/** Independent local counts of one prepared provider input; never a split of billed usage. */
|
||
contextBreakdown?: ContextUsageBreakdown
|
||
interactions?: ChatInteraction[]
|
||
requestId?: string
|
||
/** Last top-level Claude chain entry for this assistant turn, used only as a fork point. */
|
||
claudeEntryId?: string
|
||
planId?: string
|
||
feedback?: 'like' | 'dislike'
|
||
interrupted?: boolean
|
||
createdAt: number
|
||
/** User-submit timestamp shared by the live timer and terminal turn duration. */
|
||
turnStartedAt?: number
|
||
/** Measured user-send to terminal-event duration, used by the source completed fold. */
|
||
turnDurationMs?: number
|
||
/** 本回合的终态 */
|
||
status?: 'streaming' | 'done' | 'error' | 'cancelled'
|
||
error?: string
|
||
/** 渲染进程专用的启动占位阶段(新任务发送后、主进程回合就绪前);不参与持久化。 */
|
||
prepareStage?: string
|
||
}
|
||
|
||
export interface ToolCallRecord {
|
||
id: string
|
||
name: string
|
||
/** Human-readable action description supplied by the tool runtime, when available. */
|
||
intent?: string
|
||
/** 已解析的参数(原始 JSON 字符串的解析结果,解析失败则保留原文) */
|
||
args: unknown
|
||
argsRaw: string
|
||
status: 'running' | 'ok' | 'error' | 'cancelled'
|
||
/** 完整的文本输出;summary 仅供折叠态摘要,不能替代原文。 */
|
||
output?: string
|
||
/** 展示用摘要(截断后的结果) */
|
||
summary?: string
|
||
durationMs?: number
|
||
/** Native structured result and renderer metadata are retained separately from text. */
|
||
result?: unknown
|
||
metadata?: Record<string, unknown>
|
||
}
|
||
|
||
export type MessagePart =
|
||
| { type: 'text'; text: string }
|
||
| { type: 'tool'; toolId: string }
|
||
| { type: 'reasoning'; id: string; text: string; finished?: boolean }
|
||
| { type: 'plan'; plan: PlanContent }
|
||
| { type: 'task'; task: TaskContent }
|
||
| { type: 'artifact'; artifact: ArtifactContent }
|
||
| { type: 'image'; id: string; url: string; alt?: string }
|
||
|
||
/** 面向模型暴露的工具描述(OpenAI function tool 格式) */
|
||
export interface ToolSpec {
|
||
type: 'function'
|
||
function: {
|
||
name: string
|
||
description: string
|
||
parameters: Record<string, unknown>
|
||
}
|
||
}
|
||
|
||
/** Main-process resolved upstream protocol and credentials. */
|
||
export interface GatewayConfig {
|
||
api?: import('./models').ModelApi
|
||
supportsReasoning?: boolean
|
||
temperatureSupported?: boolean
|
||
thinkingLevel?: import('./workspaces').ThinkingLevel
|
||
reasoningBudget?: number
|
||
reasoningOptions?: import('./models').ModelReasoningOption[]
|
||
speechBaseUrl?: string
|
||
speechModel?: string
|
||
/** 上游 baseUrl,例如 https://api.deepseek.com/v1 */
|
||
baseUrl: string
|
||
/** 模型名,例如 deepseek-chat */
|
||
model: string
|
||
/** API Key(仅存在于主进程) */
|
||
apiKey: string
|
||
/** 采样温度 */
|
||
temperature: number
|
||
/** 单回合最大工具轮次 */
|
||
maxToolRounds: number
|
||
authMode?: 'api-key' | 'none'
|
||
maxOutputTokens?: number
|
||
}
|
||
|
||
/** 渲染进程可见的配置视图(不含 apiKey) */
|
||
export interface GatewayConfigView {
|
||
speechBaseUrl?: string
|
||
speechModel?: string
|
||
baseUrl: string
|
||
model: string
|
||
temperature: number
|
||
maxToolRounds: number
|
||
/** 是否已配置 Key(不回传明文) */
|
||
hasApiKey: boolean
|
||
/** Key 来源:safeStorage 加密 / 明文降级 */
|
||
keyStorage: 'encrypted' | 'plaintext' | 'none'
|
||
}
|
||
|
||
/** 设置 → 通用:真实状态视图(未接入项不下发数据)。 */
|
||
export interface GeneralSettingsView {
|
||
/** 系统登录项的真实状态 */
|
||
autoLaunch: boolean
|
||
/** 运行任务时阻止系统休眠(偏好) */
|
||
preventSleep: boolean
|
||
/** 当前是否有 powerSaveBlocker 生效 */
|
||
preventSleepActive: boolean
|
||
/** 数据目录(存放对话记录、运行缓存与临时文件) */
|
||
dataDir: string
|
||
/** 数据目录占用字节 */
|
||
dataBytes: number
|
||
/** 扫描是否因预算被截断 */
|
||
dataUsagePartial: boolean
|
||
/** 数据目录所在磁盘容量 */
|
||
disk: { totalBytes: number; freeBytes: number }
|
||
/** 默认工作空间存储路径 */
|
||
workspaceRoot: string
|
||
}
|
||
|
||
export interface GeneralSettingsPatch {
|
||
autoLaunch?: boolean
|
||
preventSleep?: boolean
|
||
}
|
||
|
||
/** 设置 → 个性化的回复风格(REA ev_af920…:默认/专业严谨/亲和友善/直言不讳/天马行空/高效务实/毒舌吐槽/启发引导)。 */
|
||
export type PersonalizationTone = 'default' | 'professional' | 'friendly' | 'direct' | 'imaginative' | 'efficient' | 'sarcastic' | 'socratic'
|
||
|
||
/**
|
||
* 设置 → 个性化的持久化数据。
|
||
*
|
||
* 已接入运行链路:userCallName / aiName / tone / customPrompt / persona / longTermMemory 会拼进
|
||
* 每次对话的请求上下文;loadingTips 控制流式加载提示的欢迎语是否显示。
|
||
* showFileChanges 已在原版页面呈现,但 YCode 的「逐步展示文件修改过程」渲染尚未接入,UI 标记为不可用。
|
||
*/
|
||
export interface PersonalizationSettings {
|
||
/** WorkBuddy 对你的称呼(YCode 品牌化为「YCode 对你的称呼」)。 */
|
||
userCallName: string
|
||
/** WorkBuddy 的名字(YCode 品牌化为「YCode 的名字」)。 */
|
||
aiName: string
|
||
tone: PersonalizationTone
|
||
/** 欢迎语:对话加载较慢时显示的问候/提示。 */
|
||
loadingTips: boolean
|
||
/** 显示文件修改过程(尚未接入渲染链路)。 */
|
||
showFileChanges: boolean
|
||
/** 给 WorkBuddy 的指令(长期生效的附加要求)。 */
|
||
customPrompt: string
|
||
/** 人设设定。 */
|
||
persona: string
|
||
/** 长期记忆。 */
|
||
longTermMemory: string
|
||
}
|
||
|
||
export type PersonalizationPatch = Partial<PersonalizationSettings>
|
||
|
||
/**
|
||
* 设置 → 智能体(TODO 15)。
|
||
* 智能体团队管理为本地子智能体调度总开关;经济模式与浏览器操控已按用户要求移除。
|
||
*/
|
||
export interface AgentSettings {
|
||
/** 开启后复杂任务自动拆分多个智能体协作完成(原版默认开启)。 */
|
||
teamManagement: boolean
|
||
}
|
||
|
||
export type AgentSettingsPatch = Partial<AgentSettings>
|
||
|
||
/**
|
||
* 设置 → 记忆与进化(TODO 14)。
|
||
*
|
||
* 原版把“对话记忆”保存到账户侧,“本地记忆与技能”保存在本地存储
|
||
* (REA 回收 MemorySettingsPanel-BU1K5nn4.js / local-skills-memory-Bb3Kqaxi.js)。
|
||
* YCode 将两项偏好统一写入 config.json;页面展示的数据不会补造。
|
||
*/
|
||
export interface MemoryPreferences {
|
||
/** 允许已保存的长期记忆进入后续对话上下文。 */
|
||
conversationMemory: boolean
|
||
/** 本地记忆与技能偏好;自动记录执行器尚未接入。 */
|
||
localMemorySkills: boolean
|
||
}
|
||
|
||
export interface MemorySettingsView extends MemoryPreferences {
|
||
/** 当前长期记忆正文(由个性化设置的真实长期记忆字段提供)。 */
|
||
content: string
|
||
}
|
||
|
||
export type MemoryPreferencesPatch = Partial<MemoryPreferences>
|
||
|
||
/** 主进程 → 渲染进程的流式事件 */
|
||
export type ChatEvent = { sessionId?: string; turnDurationMs?: number; sequence?: number } & (
|
||
| { runId: string; type: 'started'; messageId: string }
|
||
| { runId: string; type: 'text'; delta: string }
|
||
| { runId: string; type: 'part'; part: Exclude<MessagePart, { type: 'text' } | { type: 'tool' }> }
|
||
| { runId: string; type: 'interaction'; interaction: ChatInteraction }
|
||
| { runId: string; type: 'tool_call'; call: ToolCallRecord }
|
||
| { runId: string; type: 'tool_result'; call: ToolCallRecord }
|
||
| { runId: string; type: 'usage'; usage: TokenUsage; contextWindow?: number; sampledAt?: number; modelId?: string; source?: ContextUsageSnapshot['source'] }
|
||
| { runId: string; type: 'context_breakdown'; breakdown: ContextUsageBreakdown }
|
||
| { runId: string; type: 'done'; content: string; tools: ToolCallRecord[] }
|
||
| { runId: string; type: 'cancelled' }
|
||
| { runId: string; type: 'error'; message: string }
|
||
)
|
||
|
||
/**
|
||
* 上游返回的真实 token 用量(Responses `response.completed.usage`)。
|
||
* 只做透传,不做估算:拿不到就不产生该事件。
|
||
*/
|
||
export interface TokenUsage {
|
||
inputTokens: number
|
||
outputTokens: number
|
||
totalTokens: number
|
||
cachedTokens?: number
|
||
}
|
||
|
||
export interface ContextUsageSnapshot {
|
||
usage: TokenUsage
|
||
/** Missing when the selected profile never declared a real context window. */
|
||
contextWindow?: number
|
||
source?: 'upstream'
|
||
sampledAt?: number
|
||
requestId?: string
|
||
modelId?: string
|
||
}
|
||
|
||
export type ContextUsageCategory = 'system' | 'tools' | 'conversation' | 'mcp' | 'skills' | 'other'
|
||
|
||
export interface ContextUsageBreakdown {
|
||
requestId: string
|
||
/** Monotonic within a turn, so a late older request cannot replace a newer one. */
|
||
sequence: number
|
||
sampledAt: number
|
||
modelId?: string
|
||
contextWindow?: number
|
||
method: 'model-tokenizer' | 'o200k_base' | 'utf8-estimate'
|
||
scope: 'provider-request' | 'prepared-request'
|
||
counts: Record<ContextUsageCategory, number>
|
||
inputTokens: number
|
||
/** Images or an unavailable provider layer mean these counts are partial. */
|
||
partial: boolean
|
||
}
|
||
|
||
/** A read-only query never creates or switches an agent to obtain a number. */
|
||
export interface ContextUsageInfo {
|
||
sample?: ContextUsageSnapshot
|
||
breakdown?: ContextUsageBreakdown
|
||
status: 'latest' | 'previous' | 'unavailable'
|
||
reason?: string
|
||
}
|
||
|
||
/**
|
||
* 会话工作目录的 Git 信息(用于对话框的分支标签)。
|
||
* `repo: false` 表示该目录不在 Git 仓库内;`detached: true` 时 `branch` 为空、`head` 为短 SHA。
|
||
*/
|
||
export interface GitBranchInfo {
|
||
/** 目录是否位于 Git 工作树内 */
|
||
repo: boolean
|
||
/** 分支名;detached HEAD 或尚无提交时为 null */
|
||
branch: string | null
|
||
detached: boolean
|
||
/** detached HEAD 的短 SHA;无提交时为 null */
|
||
head: string | null
|
||
/** git 可执行文件缺失或命令超时时为 true,UI 不显示分支标签 */
|
||
unavailable?: boolean
|
||
}
|
||
|
||
/** 一次会话的元信息 */
|
||
export interface SessionMeta {
|
||
projectId?: string
|
||
id: string
|
||
title: string
|
||
createdAt: number
|
||
updatedAt: number
|
||
workspaceId?: string
|
||
cwd?: string
|
||
modelId?: string
|
||
expertId?: string | null
|
||
agentMode?: import('./conversation').AgentMode
|
||
thinkingLevel?: import('./workspaces').ThinkingLevel
|
||
/** Claude Code session used for this YCode conversation. */
|
||
claudeSessionId?: string
|
||
/** Pending Claude fork point for edit/regenerate. */
|
||
claudeForkAt?: string
|
||
/** 置顶时间(毫秒)。有值即视为已置顶,用于侧栏任务排序,不改变 createdAt/updatedAt 语义。 */
|
||
pinnedAt?: number
|
||
/** 归档时间(毫秒)。归档任务从默认任务列表移出,但不删除消息与工作目录。 */
|
||
archivedAt?: number
|
||
}
|
||
|
||
/** 工作目录信息 */
|
||
export interface WorkspaceInfo {
|
||
root: string
|
||
}
|
||
|
||
/** 无边框窗口状态 */
|
||
export interface WindowState {
|
||
maximized: boolean
|
||
fullscreen: boolean
|
||
}
|
||
|
||
/** 应用信息(关于对话框用) */
|
||
export interface AppInfo {
|
||
name: string
|
||
version: string
|
||
electron: string
|
||
chrome: string
|
||
node: string
|
||
configDir: string
|
||
/** Claude Code 内核状态(未探测到时 available 为 false) */
|
||
claude: {
|
||
available: boolean
|
||
exePath: string | null
|
||
sessionDir: string
|
||
version?: string
|
||
}
|
||
}
|