feat: add copy action to AI responses
Completed AI responses now expose a bottom copy action that copies their Markdown source without reasoning, tool logs, or citation metadata. Clipboard writes use a validated Preload/Main bridge so sandboxed Electron sessions no longer fail with a renderer clipboard permission error; full-conversation copy uses the same path. Release note: AI 回复底部现在可以直接复制 Markdown 原文,并修复了沙箱环境下回复和完整会话可能无法写入剪贴板的问题。
This commit is contained in:
@@ -254,6 +254,11 @@ const desktopApi: DesktopApi = {
|
||||
return () => ipcRenderer.removeListener(ipcChannels.settingsOpen, handler)
|
||||
}
|
||||
},
|
||||
clipboard: {
|
||||
writeText: async (text: string) => {
|
||||
await ipcRenderer.invoke(ipcChannels.clipboardWriteText, text)
|
||||
}
|
||||
},
|
||||
agent: {
|
||||
getStatus: (selection) =>
|
||||
ipcRenderer.invoke(
|
||||
|
||||
@@ -21,6 +21,20 @@ describe('sandboxed preload', () => {
|
||||
expect(source).not.toMatch(/\bfrom\s+['"]zod['"]/u)
|
||||
})
|
||||
|
||||
it('exposes only explicit clipboard text writing', () => {
|
||||
const source = readFileSync(
|
||||
join(process.cwd(), 'src', 'preload', 'index.ts'),
|
||||
'utf8'
|
||||
)
|
||||
const clipboard =
|
||||
source.match(
|
||||
/clipboard: \{(?<body>[\s\S]*?)\r?\n {2}\},\r?\n {2}agent:/u
|
||||
)?.groups?.body ?? ''
|
||||
expect(clipboard).toContain('writeText: async (text: string)')
|
||||
expect(clipboard).toContain('ipcChannels.clipboardWriteText')
|
||||
expect(clipboard).not.toMatch(/\b(?:read|image|html|rtf|bookmark)\b/iu)
|
||||
})
|
||||
|
||||
it('exposes only narrow browser-control methods', () => {
|
||||
const source = readFileSync(
|
||||
join(process.cwd(), 'src', 'preload', 'index.ts'),
|
||||
|
||||
Reference in New Issue
Block a user