Files
ycode/src/shared/ipc.ts
T

245 lines
9.3 KiB
TypeScript

/**
* IPC 契约(主进程与 preload 共享)。
* 放在 shared 下,避免主进程反向依赖 electron 类型。
*/
import type {
ChatMessage,
ChatEvent,
SessionMeta,
GatewayConfigView,
WorkspaceInfo,
WindowState,
AppInfo,
GitBranchInfo,
GeneralSettingsPatch,
GeneralSettingsView,
PersonalizationPatch,
PersonalizationSettings,
AgentSettings,
AgentSettingsPatch,
MemoryPreferencesPatch,
MemorySettingsView,
TokenUsage
} from './types'
import type { ContextUsageInfo } from './types'
import type { DownloadPayload, DownloadResult, ResourceEntry, ResourceRange, WorkspaceResource } from './resources'
import type { ChatAttachment, InteractionResponse, MessageQuote, PermissionMode } from './conversation'
import type { CustomModelInput, ModelRegistryView, ModelTestResult, ModelDiscoveryInput, ModelDiscoveryResult, ModelMetadata, ModelMetadataStatus, ModelProtocol } from './models'
import type { SessionContext, WorkspaceRegistryView } from './workspaces'
import type { BrowserHostApi } from './browser-host'
import type { TerminalHostApi } from './terminal-host'
import type { ExpertsApi, McpApi, SkillsApi } from './capabilities'
import type { ProjectInput, ProjectRecord } from './projects'
import type { AutomationApi } from './automation-api'
import type { LibraryApi } from './library'
export interface ConfigPatchLike {
speechBaseUrl?: string
speechModel?: string
baseUrl?: string
model?: string
temperature?: number
maxToolRounds?: number
apiKey?: string
}
export type EditAction = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'selectAll'
export interface RewindOptions {
rollbackArtifacts?: boolean
}
export interface EditInspection {
editable: boolean
reason?: string
}
export interface SendPayload {
skillIds?: string[]
planId?: string
resources?: string[]
sessionId: string
text: string
attachments?: ChatAttachment[]
/** 表格等内容的引用快照,随用户消息持久化。 */
quotes?: MessageQuote[]
userContent?: import('./conversation').UserContentBlock[]
permissionMode?: PermissionMode
/** Retry/edit from this message; descendants are preserved in an archived branch. */
fromMessageId?: string
action?: 'edit' | 'resend' | 'regenerate'
/** Editing can retain the current files after an explicit user choice. */
rollbackArtifacts?: boolean
}
export interface SendResult {
runId: string
assistantMessageId: string
/** Frozen identity of the model selected when this assistant turn started. */
modelId?: string
modelName?: string
assistantDisplay?: import('./capabilities').ExpertBinding
userMessage: ChatMessage
messages?: ChatMessage[]
}
export interface ActiveChatRun extends SendResult {
sessionId: string
sequence: number
messages: ChatMessage[]
usage?: TokenUsage
}
/** 统一的返回包装,便于渲染进程处理错误而不炸掉 UI */
export type Ipc<T> = Promise<T>
/** A cancelled folder picker has no attached ID, even when the registry has a selection. */
export interface WorkspaceAttachResult extends WorkspaceRegistryView {
attachedWorkspaceId?: string
}
/** preload 暴露给渲染进程的 API 形状 */
export interface YCodeApi {
automation: AutomationApi
library: LibraryApi
projects: {
list(): Ipc<ProjectRecord[]>
create(input: ProjectInput): Ipc<ProjectRecord>
update(projectId: string, patch: Partial<ProjectInput>): Ipc<ProjectRecord>
}
experts: ExpertsApi
skills: SkillsApi
mcp: McpApi
browser: BrowserHostApi
terminal: TerminalHostApi
window: {
minimize(): Ipc<void>
toggleMaximize(): Ipc<{ maximized: boolean }>
close(): Ipc<void>
getState(): Ipc<WindowState>
onState(listener: (state: WindowState) => void): () => void
onFocus(listener: (focused: boolean) => void): () => void
}
edit: {
action(action: EditAction): Ipc<void>
}
app: {
info(): Ipc<AppInfo>
openConfigDir(): Ipc<void>
openSettings(section?: string, action?: 'new'): Ipc<void>
onSettingsChanged(listener: () => void): () => void
settingsReady(): Ipc<void>
settingsRendered(requestId: number): Ipc<void>
onSettingsClosed(listener: () => void): () => void
onSettingsNavigate(listener: (section: string, action?: 'new', requestId?: number) => void): () => void
}
git: {
/** 读取某个会话工作目录的真实分支信息;目录不在仓库内或 git 不可用时返回 repo:false/unavailable。 */
branch(sessionId: string): Ipc<GitBranchInfo>
}
config: {
get(): Ipc<GatewayConfigView>
update(patch: ConfigPatchLike): Ipc<GatewayConfigView>
}
/** 设置 → 通用:真实可接入的能力。 */
general: {
get(options?: { refreshUsage?: boolean }): Ipc<GeneralSettingsView>
update(patch: GeneralSettingsPatch): Ipc<GeneralSettingsView>
/** 打开数据目录 / 默认工作空间目录 */
openFolder(kind: 'data' | 'workspace'): Ipc<void>
/** 修改默认工作空间存储路径;传入 path 时不弹系统对话框(验收用)。 */
changeWorkspaceRoot(path?: string): Ipc<GeneralSettingsView>
/** 打开系统通知设置页。 */
openSystemNotificationSettings(): Ipc<void>
}
/** 设置 → 个性化:身份、回复风格、指令、人设与长期记忆。 */
personalization: {
get(): Ipc<PersonalizationSettings>
update(patch: PersonalizationPatch): Ipc<PersonalizationSettings>
}
/** 设置 → 智能体:智能体团队管理偏好。 */
agents: {
get(): Ipc<AgentSettings>
update(patch: AgentSettingsPatch): Ipc<AgentSettings>
}
/** 设置 → 记忆与进化:偏好、长期记忆正文与导入。 */
memory: {
get(): Ipc<MemorySettingsView>
update(patch: MemoryPreferencesPatch): Ipc<MemorySettingsView>
import(input: { content: string }): Ipc<MemorySettingsView>
}
workspace: {
get(): Ipc<WorkspaceInfo>
choose(): Ipc<WorkspaceInfo & { changed: boolean }>
list(): Ipc<WorkspaceRegistryView>
generate(name: string): Ipc<WorkspaceRegistryView>
attach(path?: string): Ipc<WorkspaceAttachResult>
select(id: string | null): Ipc<WorkspaceRegistryView>
rename(id: string, name: string): Ipc<WorkspaceRegistryView>
remove(id: string): Ipc<WorkspaceRegistryView>
open(id: string): Ipc<void>
}
models: {
fetch(input: ModelDiscoveryInput): Ipc<ModelDiscoveryResult>
metadata(model: string, protocol?: ModelProtocol): Ipc<ModelMetadata | null>
metadataStatus(): Ipc<ModelMetadataStatus>
refreshMetadata(): Ipc<ModelMetadataStatus>
list(): Ipc<ModelRegistryView>
save(input: CustomModelInput, overwrite?: boolean): Ipc<ModelRegistryView>
remove(id: string): Ipc<ModelRegistryView>
select(id: string | null): Ipc<ModelRegistryView>
test(input: CustomModelInput): Ipc<ModelTestResult>
}
resources: {
list(sessionId?: string, workspaceId?: string): Ipc<ResourceEntry[]>
openExternal(url: string): Ipc<void>
read(path: string, range?: ResourceRange, sessionId?: string): Ipc<WorkspaceResource>
readText(path: string, sessionId?: string): Ipc<string>
classify(path: string, sessionId?: string): Ipc<'file' | 'directory' | 'unknown'>
resolveImage(source: string, sessionId?: string): Ipc<string | undefined>
download(payload: DownloadPayload): Ipc<DownloadResult>
downloadImage(source: string, filename?: string, sessionId?: string): Ipc<DownloadResult>
}
attachments: {
pick(): Ipc<ChatAttachment[]>
stage(payload: { name: string; mimeType: string; dataBase64: string }): Ipc<ChatAttachment>
preview(id: string): Ipc<WorkspaceResource>
remove(id: string): Ipc<void>
}
speech: {
transcribe(payload: { audioBase64: string; mimeType: string }): Ipc<{ text: string }>
}
session: {
list(): Ipc<SessionMeta[]>
listArchived(): Ipc<SessionMeta[]>
create(title?: string, context?: SessionContext): Ipc<SessionMeta>
updateContext(id: string, context: SessionContext): Ipc<SessionMeta>
messages(sessionId: string): Ipc<ChatMessage[]>
contextUsage(sessionId: string): Ipc<ContextUsageInfo>
rename(sessionId: string, title: string): Ipc<void>
remove(sessionId: string, options?: { onlyIfEmpty?: boolean }): Ipc<void>
/** 置顶/取消置顶;返回刷新后的元信息。 */
setPinned(sessionId: string, pinned: boolean): Ipc<SessionMeta>
/** 归档/取消归档;不删除消息与工作目录。 */
setArchived(sessionId: string, archived: boolean): Ipc<SessionMeta>
/** 用系统文件管理器打开任务绑定的工作目录。 */
openFolder(sessionId: string): Ipc<void>
/** 在新窗口打开该任务。 */
openWindow(sessionId: string): Ipc<void>
}
chat: {
activeRun(sessionId: string): Ipc<ActiveChatRun | null>
onStarted(listener: (run: ActiveChatRun) => void): () => void
setSessionVisible(sessionId: string | null): Ipc<{ accepted: boolean }>
inspectEdit(sessionId: string, userMessageId: string): Ipc<EditInspection>
revert(sessionId: string, userMessageId: string, options?: RewindOptions): Ipc<{ messages: ChatMessage[] }>
feedback(sessionId: string, messageId: string, value: 'like' | 'dislike'): Ipc<void>
send(payload: SendPayload): Ipc<SendResult>
cancel(runId: string): Ipc<{ cancelled: boolean }>
respond(runId: string, interactionId: string, response: InteractionResponse): Ipc<{ accepted: boolean }>
/** 返回取消订阅函数 */
onEvent(listener: (event: ChatEvent) => void): () => void
}
}