feat: globalize Magic Notes and improve runtime tools
This commit is contained in:
@@ -1,9 +1,20 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const magicNoteCommentModeSchema = z.enum([
|
||||
'immediate',
|
||||
'after-save-auto',
|
||||
'after-save-manual'
|
||||
])
|
||||
|
||||
export type MagicNoteCommentMode = z.infer<
|
||||
typeof magicNoteCommentModeSchema
|
||||
>
|
||||
|
||||
export const applicationSettingsSchema = z
|
||||
.object({
|
||||
checkUpdatesOnStartup: z.boolean(),
|
||||
magicNotesEnabled: z.boolean()
|
||||
magicNotesEnabled: z.boolean(),
|
||||
magicNoteCommentMode: magicNoteCommentModeSchema
|
||||
})
|
||||
.strict()
|
||||
|
||||
|
||||
@@ -4,7 +4,11 @@ export type BuiltinMcpServerSummary = {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
tools: readonly string[]
|
||||
tools: readonly {
|
||||
name: string
|
||||
description: string
|
||||
access: 'read'
|
||||
}[]
|
||||
assignments: readonly RuntimeTarget[]
|
||||
access: 'read'
|
||||
authorization: 'conversation-scoped'
|
||||
@@ -16,7 +20,29 @@ export const builtinMcpServers = [
|
||||
name: '知识库 MCP',
|
||||
description:
|
||||
'搜索当前对话明确选择的知识库,并返回可核验的来源与证据引用。',
|
||||
tools: ['knowledge_search'],
|
||||
tools: [
|
||||
{
|
||||
name: 'knowledge_search',
|
||||
description: '搜索当前对话已授权的知识库并返回来源引用。',
|
||||
access: 'read'
|
||||
}
|
||||
],
|
||||
assignments: ['model', 'opencode', 'continue'],
|
||||
access: 'read',
|
||||
authorization: 'conversation-scoped'
|
||||
},
|
||||
{
|
||||
id: 'magic-notes',
|
||||
name: '笔记 MCP',
|
||||
description:
|
||||
'搜索全局魔法笔记,返回匹配的笔记、记录正文与更新时间。',
|
||||
tools: [
|
||||
{
|
||||
name: 'note_search',
|
||||
description: '搜索全局魔法笔记中的标题和记录正文。',
|
||||
access: 'read'
|
||||
}
|
||||
],
|
||||
assignments: ['model', 'opencode', 'continue'],
|
||||
access: 'read',
|
||||
authorization: 'conversation-scoped'
|
||||
|
||||
@@ -3,6 +3,7 @@ export type BuiltinModelToolSummary = {
|
||||
displayName: string
|
||||
description: string
|
||||
access: 'read' | 'write'
|
||||
group: 'filesystem' | 'browser'
|
||||
}
|
||||
|
||||
export const builtinModelTools = [
|
||||
@@ -10,61 +11,88 @@ export const builtinModelTools = [
|
||||
name: 'workspace_read_text',
|
||||
displayName: '读取工作区文本',
|
||||
description: '读取当前工作区内不超过 256KB 的 UTF-8 文本文件。',
|
||||
access: 'read'
|
||||
access: 'read',
|
||||
group: 'filesystem'
|
||||
},
|
||||
{
|
||||
name: 'workspace_list_directory',
|
||||
displayName: '列出工作区目录',
|
||||
description: '列出当前工作区内目录的直属内容,最多返回 200 项。',
|
||||
access: 'read'
|
||||
access: 'read',
|
||||
group: 'filesystem'
|
||||
},
|
||||
{
|
||||
name: 'workspace_write_text',
|
||||
displayName: '写入工作区文本',
|
||||
description:
|
||||
'在当前工作区内新建或覆盖不超过 512KB 的 UTF-8 文本文件,父目录必须已存在。',
|
||||
access: 'write'
|
||||
access: 'write',
|
||||
group: 'filesystem'
|
||||
},
|
||||
{
|
||||
name: 'browser_navigate',
|
||||
displayName: '浏览器导航',
|
||||
description: '在隔离浏览器中打开当前设备可连接的 HTTP 或 HTTPS 页面。',
|
||||
access: 'write'
|
||||
access: 'write',
|
||||
group: 'browser'
|
||||
},
|
||||
{
|
||||
name: 'browser_snapshot',
|
||||
displayName: '读取浏览器快照',
|
||||
description: '读取当前页面的有界可访问性快照;可编辑值会被隐藏。',
|
||||
access: 'read'
|
||||
access: 'read',
|
||||
group: 'browser'
|
||||
},
|
||||
{
|
||||
name: 'browser_click',
|
||||
displayName: '点击浏览器元素',
|
||||
description: '点击最近一次浏览器快照中的可见元素。',
|
||||
access: 'write'
|
||||
access: 'write',
|
||||
group: 'browser'
|
||||
},
|
||||
{
|
||||
name: 'browser_type',
|
||||
displayName: '输入浏览器文本',
|
||||
description: '向可编辑页面元素(包括密码框)输入文本;不支持上传文件。',
|
||||
access: 'write'
|
||||
access: 'write',
|
||||
group: 'browser'
|
||||
},
|
||||
{
|
||||
name: 'browser_select',
|
||||
displayName: '选择浏览器选项',
|
||||
description: '在最近一次快照标识的原生选择控件中选择值。',
|
||||
access: 'write'
|
||||
access: 'write',
|
||||
group: 'browser'
|
||||
},
|
||||
{
|
||||
name: 'browser_back',
|
||||
displayName: '浏览器返回',
|
||||
description: '在隔离浏览器的历史记录中返回上一页。',
|
||||
access: 'write'
|
||||
access: 'write',
|
||||
group: 'browser'
|
||||
},
|
||||
{
|
||||
name: 'browser_screenshot',
|
||||
displayName: '截取浏览器页面',
|
||||
description: '截取当前可见页面区域、约 200KB 的有界 JPEG 图片。',
|
||||
access: 'read'
|
||||
access: 'read',
|
||||
group: 'browser'
|
||||
}
|
||||
] as const satisfies readonly BuiltinModelToolSummary[]
|
||||
|
||||
export const builtinModelToolGroups = [
|
||||
{
|
||||
id: 'filesystem',
|
||||
name: '文件系统操作',
|
||||
description:
|
||||
'在 Execute 模式下读取、列出或写入当前工作区范围内的文件。',
|
||||
tools: builtinModelTools.filter((tool) => tool.group === 'filesystem')
|
||||
},
|
||||
{
|
||||
id: 'browser',
|
||||
name: '浏览器操作',
|
||||
description:
|
||||
'启用“浏览器控制”后,在 Execute 模式下操作 GoodBuddy 隔离浏览器。',
|
||||
tools: builtinModelTools.filter((tool) => tool.group === 'browser')
|
||||
}
|
||||
] as const
|
||||
|
||||
@@ -37,16 +37,16 @@ import {
|
||||
type ExpertUpdateInput
|
||||
} from './assistant-contracts'
|
||||
import type {
|
||||
MagicNoteDraftAnalysis,
|
||||
MagicNoteDetail,
|
||||
MagicNoteCreateInput,
|
||||
MagicNoteEntryCreateInput,
|
||||
MagicNoteEntryUpdateInput,
|
||||
MagicNoteRichContent,
|
||||
MagicNotesSnapshot,
|
||||
MagicNoteUpdateInput,
|
||||
MagicTodoCreateInput,
|
||||
MagicTodoItem,
|
||||
MagicTodosSnapshot,
|
||||
MagicTodoUpdateInput
|
||||
MagicTodosSnapshot
|
||||
} from './magic-notes-contracts'
|
||||
import type {
|
||||
ChannelConnectionTestResult,
|
||||
@@ -1158,7 +1158,7 @@ export type DesktopApi = {
|
||||
remove: (contextId: string) => Promise<void>
|
||||
}
|
||||
magicNotes: {
|
||||
list: (projectId?: string) => Promise<MagicNotesSnapshot>
|
||||
list: () => Promise<MagicNotesSnapshot>
|
||||
get: (noteId: string) => Promise<MagicNoteDetail>
|
||||
create: (input: MagicNoteCreateInput) => Promise<MagicNoteDetail>
|
||||
update: (input: MagicNoteUpdateInput) => Promise<MagicNoteDetail>
|
||||
@@ -1171,10 +1171,10 @@ export type DesktopApi = {
|
||||
) => Promise<MagicNoteDetail>
|
||||
removeEntry: (entryId: string) => Promise<MagicNoteDetail>
|
||||
analyze: (entryId: string) => Promise<MagicNoteDetail>
|
||||
listTodos: (projectId?: string) => Promise<MagicTodosSnapshot>
|
||||
createTodo: (input: MagicTodoCreateInput) => Promise<MagicTodoItem>
|
||||
updateTodo: (input: MagicTodoUpdateInput) => Promise<MagicTodoItem>
|
||||
removeTodo: (todoId: string) => Promise<void>
|
||||
analyzeDraft: (
|
||||
content: MagicNoteRichContent
|
||||
) => Promise<MagicNoteDraftAnalysis>
|
||||
listTodos: () => Promise<MagicTodosSnapshot>
|
||||
analyzeTodo: (todoId: string) => Promise<MagicTodoItem>
|
||||
}
|
||||
knowledge: {
|
||||
|
||||
@@ -126,10 +126,8 @@ export const ipcChannels = {
|
||||
magicNotesUpdateEntry: 'magic-notes:update-entry',
|
||||
magicNotesDeleteEntry: 'magic-notes:delete-entry',
|
||||
magicNotesAnalyze: 'magic-notes:analyze',
|
||||
magicNotesAnalyzeDraft: 'magic-notes:analyze-draft',
|
||||
magicTodosList: 'magic-todos:list',
|
||||
magicTodosCreate: 'magic-todos:create',
|
||||
magicTodosUpdate: 'magic-todos:update',
|
||||
magicTodosDelete: 'magic-todos:delete',
|
||||
magicTodosAnalyze: 'magic-todos:analyze',
|
||||
knowledgeSnapshot: 'knowledge:snapshot',
|
||||
knowledgeCreateLibrary: 'knowledge:library:create',
|
||||
|
||||
@@ -100,15 +100,8 @@ export type MagicNoteRichContent = z.infer<
|
||||
typeof magicNoteRichContentSchema
|
||||
>
|
||||
|
||||
export const magicNoteScopeSchema = z
|
||||
.object({
|
||||
projectId: magicNoteIdSchema.optional()
|
||||
})
|
||||
.strict()
|
||||
|
||||
export const magicNoteCreateSchema = z
|
||||
.object({
|
||||
projectId: magicNoteIdSchema.optional(),
|
||||
title: z.string().trim().min(1).max(100)
|
||||
})
|
||||
.strict()
|
||||
@@ -166,32 +159,11 @@ export const magicNoteAnalyzeSchema = z
|
||||
})
|
||||
.strict()
|
||||
|
||||
export const magicTodoCreateSchema = z
|
||||
export const magicNoteDraftAnalyzeSchema = z
|
||||
.object({
|
||||
projectId: magicNoteIdSchema.optional(),
|
||||
title: z.string().trim().min(1).max(120),
|
||||
instructions: z.string().trim().max(20_000)
|
||||
content: magicNoteRichContentSchema
|
||||
})
|
||||
.strict()
|
||||
export type MagicTodoCreateInput = z.infer<typeof magicTodoCreateSchema>
|
||||
|
||||
export const magicTodoUpdateSchema = z
|
||||
.object({
|
||||
todoId: magicNoteIdSchema,
|
||||
title: z.string().trim().min(1).max(120).optional(),
|
||||
instructions: z.string().trim().max(20_000).optional(),
|
||||
completed: z.boolean().optional(),
|
||||
expectedRevision: z.number().int().nonnegative()
|
||||
})
|
||||
.strict()
|
||||
.refine(
|
||||
(input) =>
|
||||
input.title !== undefined ||
|
||||
input.instructions !== undefined ||
|
||||
input.completed !== undefined,
|
||||
{ message: '没有可更新的待办字段' }
|
||||
)
|
||||
export type MagicTodoUpdateInput = z.infer<typeof magicTodoUpdateSchema>
|
||||
|
||||
export const magicTodoIdSchema = z
|
||||
.object({
|
||||
@@ -221,7 +193,6 @@ export type MagicNoteEntry = {
|
||||
|
||||
export type MagicNoteSummary = {
|
||||
id: string
|
||||
projectId?: string
|
||||
title: string
|
||||
preview: string
|
||||
entryCount: number
|
||||
@@ -241,12 +212,11 @@ export type MagicNotesSnapshot = {
|
||||
|
||||
export type MagicTodoItem = {
|
||||
id: string
|
||||
projectId?: string
|
||||
noteId?: string
|
||||
entryId?: string
|
||||
noteTitle?: string
|
||||
sourceIndex?: number
|
||||
source: 'note' | 'manual'
|
||||
noteId: string
|
||||
entryId: string
|
||||
noteTitle: string
|
||||
sourceIndex: number
|
||||
source: 'note'
|
||||
title: string
|
||||
instructions: string
|
||||
completed: boolean
|
||||
@@ -260,3 +230,17 @@ export type MagicTodoItem = {
|
||||
export type MagicTodosSnapshot = {
|
||||
todos: MagicTodoItem[]
|
||||
}
|
||||
|
||||
export type MagicNoteDraftAnalysis = {
|
||||
id: string
|
||||
comments: MagicNoteComment[]
|
||||
analyzedAt: string
|
||||
}
|
||||
|
||||
export type MagicNoteSearchResult = {
|
||||
noteId: string
|
||||
noteTitle: string
|
||||
entryId: string
|
||||
content: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user