feat: 原生系统提示词只读展示、会话末尾 fork、深浅色主题

This commit is contained in:
Rick Ye
2026-09-09 03:16:13 +08:00
parent b9bb72ada9
commit bb0aedd27c
15 changed files with 376 additions and 219 deletions
+45 -15
View File
@@ -1,4 +1,5 @@
import { app, dialog, shell } from 'electron'
import { nativeTheme } from 'electron'
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import {
@@ -39,6 +40,7 @@ import type {
SessionStatsInfo,
SkillDetail,
ThinkingLevel,
ThemeMode,
WorkspaceFile,
WorkspaceMeta
} from '@shared/types'
@@ -63,7 +65,7 @@ export class AgentService {
private flushTimer: NodeJS.Timeout | null = null
private attached: AgentSession | null = null
private unsubscribeAttached: (() => void) | null = null
private settings: AppSettings = { systemPrompt: '' }
private settings: AppSettings = {}
/** 当前工作区目录(agent cwd),会话按目录隔离 */
private workspaceDir = ''
private approvalsRegistered = false
@@ -73,6 +75,13 @@ export class AgentService {
private skillsEstimate: { cwd: string; value: number } | null = null
readonly approvals = new ApprovalService()
constructor() {
// 设置同步读入 + 应用持久化的深浅色偏好(nativeTheme 会影响渲染层
// prefers-color-scheme 与原生控件配色;窗口创建前生效可避免首帧闪错色)
this.loadSettings()
nativeTheme.themeSource = this.settings.themeMode ?? 'system'
}
/** 工作区根目录:文档/Inkreach,每个子目录 = 一个工作区 */
get workspacesRoot(): string {
return join(app.getPath('documents'), 'Inkreach')
@@ -94,7 +103,6 @@ export class AgentService {
try {
const raw = JSON.parse(readFileSync(this.settingsFile, 'utf8')) as Partial<AppSettings>
this.settings = {
systemPrompt: typeof raw.systemPrompt === 'string' ? raw.systemPrompt : '',
workspace: typeof raw.workspace === 'string' ? raw.workspace : undefined,
customWorkspaces: Array.isArray(raw.customWorkspaces)
? raw.customWorkspaces.filter((p): p is string => typeof p === 'string')
@@ -102,10 +110,11 @@ export class AgentService {
// 历史版本存过 autoEdit/plan,统一收敛回 confirm
permissionMode:
raw.permissionMode === 'full' ? 'full' : 'confirm',
themeColor: typeof raw.themeColor === 'string' ? raw.themeColor : undefined
themeColor: typeof raw.themeColor === 'string' ? raw.themeColor : undefined,
themeMode: raw.themeMode === 'light' || raw.themeMode === 'dark' ? raw.themeMode : 'system'
}
} catch {
this.settings = { systemPrompt: '', permissionMode: this.permissionMode }
this.settings = { permissionMode: this.permissionMode, themeMode: 'system' }
}
this.permissionMode = this.settings.permissionMode ?? 'confirm'
this.initWorkspaces()
@@ -258,7 +267,6 @@ export class AgentService {
cwd: targetCwd,
agentDir: targetAgentDir,
resourceLoaderOptions: {
...(this.settings.systemPrompt.trim() ? { systemPrompt: this.settings.systemPrompt } : {}),
extensionFactories: [
createApprovalExtension(this.approvals, TOOLS_REQUIRING_APPROVAL, () => this.permissionMode)
]
@@ -1054,17 +1062,45 @@ export class AgentService {
this.emitSwitched(session)
}
/** 在会话末尾分叉出新会话(pi fork:复制到新会话文件,原会话保留不动)。
* fork 后 runtime 重挂新会话,rebind 回调负责发 session_switched。 */
async forkSession(): Promise<void> {
const runtime = await this.getRuntime()
const session = runtime.session
if (session.isStreaming) {
await session.abort()
}
const leafId = session.sessionManager.getLeafId()
if (!leafId) {
throw new Error('会话还没有可分叉的内容')
}
const result = await runtime.fork(leafId, { position: 'at' })
if (result.cancelled) return
}
// ---- 应用设置 ----
getSettings(): AppSettings {
return { ...this.settings }
}
/** 更新系统提示词后重建运行时(continueRecent 重新挂载当前最近会话,历史保留) */
async setSystemPrompt(text: string): Promise<void> {
this.settings = { ...this.settings, systemPrompt: text }
/** 当前生效的系统提示词(pi 原生提示词 + 技能注入,只读展示用) */
async getSystemPrompt(): Promise<string> {
const runtime = await this.getRuntime()
return runtime.session.systemPrompt
}
/** 深浅色模式:写入 Electron nativeTheme(渲染层 prefers-color-scheme 随之变化)并持久化 */
setThemeMode(mode: ThemeMode): void {
this.settings = { ...this.settings, themeMode: mode }
this.saveSettings()
nativeTheme.themeSource = mode
}
/** 主题色偏好(纯外观,仅持久化;渲染层负责应用) */
setThemeColor(id: string): void {
this.settings = { ...this.settings, themeColor: id }
this.saveSettings()
await this.rebuildRuntime()
}
/** 切换权限模式:即时生效(审批扩展每笔工具调用实时读取),并广播给渲染层 */
@@ -1078,12 +1114,6 @@ export class AgentService {
}
}
/** 主题色偏好(纯外观,仅持久化;渲染层负责应用) */
setThemeColor(id: string): void {
this.settings = { ...this.settings, themeColor: id }
this.saveSettings()
}
private async rebuildRuntime(): Promise<void> {
const old = this.runtime
this.runtime = null