VoiceInput/Agent/doc/tools.json
JOJO 9f3ea09b06 feat(agent): Better Siri 改造 — 个人助手 + 记忆系统 + 统一弹窗 + 多项优化
=== 记忆系统 ===
- 新增 remember(记录)和 recall(搜索)工具,持久化到 ~/Library/Application Support/VoiceInput/memory/memory.json
- 新增 set_identity 工具,独立管理助手名字/用户称呼/语气
- prompt 重写为个人助手身份,注入 macOS 能力 + 记忆规则
- prompt 中积极调用记忆工具,按需搜索、自然融入回答
- 禁止相对时间,待办必须绝对日期

=== 对话持久化 ===
- 集成 conversation_store,done 前自动写入对话文件
- token 记录:prompt/completion 累加,total 覆盖为最新上下文长度
- 启动时加载最新对话继续(使用 eagent /resume 逻辑)
- 去重:末尾连续 assistant 消息自动合并
- 修复消息加载顺序 bug(旧对话覆盖用户新消息)

=== 新建对话 ===
- 手动/自动两种模式(设置窗口可切换)
- 自动模式:total > 阈值时隐藏按钮,下次输入自动新建
- 自动阈值在设置窗口可配置(默认 40000)

=== 弹窗 UI 统一 ===
- 语音输入按 Fn 即显示刘海弹窗(和打字输入统一)
- 语音识别内容自动填入并发送(可关闭自动发送)
- 工作期间(thinking/running)隐藏输入框,idle/done 时显示
- 工具显示三种模式:全部显示/最后隐藏/一直不显示

=== 设置窗口增强 ===
- 助手名字 / 用户称呼 / 语气可配置
- 工具显示模式 / 新建对话模式 / 自动阈值
- 语音输入后自动发送开关(默认开)
- 记忆管理窗口可视化编辑(Dock 可访问)
- 窗口高度 840→860

=== 菜单增强 ===
- Agent LLM 二级菜单切换语音/打字输入
- 助手设置和记忆管理入口(Dock 可访问)

=== 修复 ===
- Fn 按下时停止正在进行的朗读
- 弹窗已存在时不再覆盖 isTextInputMode
- voiceInputText 加 @Published 以触发 UI 更新
2026-04-30 18:16:58 +08:00

371 lines
13 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[
{
"type": "function",
"function": {
"name": "read_file",
"description": "读取/搜索/抽取 UTF-8 文本文件。type=read/search/extract仅单文件操作。",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "文件路径:工作区内请用相对路径,工作区外可用绝对路径。"
},
"type": {
"type": "string",
"enum": ["read", "search", "extract"],
"description": "读取模式read=按行读取search=在文件内搜索extract=按行段抽取。"
},
"max_chars": {
"type": "integer",
"description": "返回内容最大字符数,超出将截断。"
},
"start_line": {
"type": "integer",
"description": "[read] 起始行号1-based。"
},
"end_line": {
"type": "integer",
"description": "[read] 结束行号(>= start_line。"
},
"query": {
"type": "string",
"description": "[search] 搜索关键词。"
},
"max_matches": {
"type": "integer",
"description": "[search] 最多返回多少条命中窗口。"
},
"context_before": {
"type": "integer",
"description": "[search] 命中行向上追加行数。"
},
"context_after": {
"type": "integer",
"description": "[search] 命中行向下追加行数。"
},
"case_sensitive": {
"type": "boolean",
"description": "[search] 是否区分大小写。"
},
"segments": {
"type": "array",
"description": "[extract] 需要抽取的行区间数组。",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "片段标签(可选)。"
},
"start_line": {
"type": "integer",
"description": "起始行号(>=1。"
},
"end_line": {
"type": "integer",
"description": "结束行号(>= start_line。"
}
},
"required": ["start_line", "end_line"]
},
"minItems": 1
}
},
"required": ["path", "type"]
}
}
},
{
"type": "function",
"function": {
"name": "edit_file",
"description": "在文件中执行精确字符串替换;建议先用 read_file 精确复制 old_string。",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "文件路径:工作区内请用相对路径,工作区外可用绝对路径。"
},
"old_string": {
"type": "string",
"description": "要替换的旧文本(必须与文件内容精确匹配)。"
},
"new_string": {
"type": "string",
"description": "替换的新文本(必须不同于 old_string。"
}
},
"required": ["file_path", "old_string", "new_string"]
}
}
},
{
"type": "function",
"function": {
"name": "web_search",
"description": "网络搜索Tavily。用于外部资料或最新信息检索。",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词(不要包含时间范围)。"
},
"max_results": {
"type": "integer",
"description": "最大返回结果数。"
},
"topic": {
"type": "string",
"enum": ["general", "news", "finance"],
"description": "搜索主题类型。"
},
"time_range": {
"type": "string",
"enum": ["day", "week", "month", "year", "d", "w", "m", "y"],
"description": "相对时间范围(与 days / start_date+end_date 互斥)。"
},
"days": {
"type": "integer",
"description": "最近 N 天(仅 topic=news 可用)。"
},
"start_date": {
"type": "string",
"description": "开始日期 YYYY-MM-DD必须与 end_date 同时提供)。"
},
"end_date": {
"type": "string",
"description": "结束日期 YYYY-MM-DD必须与 start_date 同时提供)。"
},
"country": {
"type": "string",
"description": "国家过滤,仅 topic=general 可用(英文小写国名)。"
}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "extract_webpage",
"description": "网页内容提取Tavily。mode=read 直接返回内容mode=save 保存为文件。",
"parameters": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["read", "save"],
"description": "read=直接返回内容save=写入文件。"
},
"url": {
"type": "string",
"description": "目标网页 URL。"
},
"target_path": {
"type": "string",
"description": "[save] 保存路径:工作区内请用相对路径,工作区外可用绝对路径。必须是 .md 文件。mode=save 必填。"
}
},
"required": ["mode", "url"]
}
}
},
{
"type": "function",
"function": {
"name": "run_command",
"description": "在当前终端环境执行一次性命令(非交互式)。",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "要执行的命令。"
},
"timeout": {
"type": "number",
"description": "超时时间(秒),必填。"
},
"working_dir": {
"type": "string",
"description": "工作目录:工作区内请用相对路径,工作区外可用绝对路径。"
}
},
"required": ["command", "timeout"]
}
}
},
{
"type": "function",
"function": {
"name": "search_workspace",
"description": "在本地目录内搜索文件名或文件内容(跨文件)。仅返回摘要。",
"parameters": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["file", "content"],
"description": "file=搜索文件名content=跨文件搜索内容。"
},
"query": {
"type": "string",
"description": "搜索关键词或正则。"
},
"root": {
"type": "string",
"description": "搜索起点目录:工作区内请用相对路径,工作区外可用绝对路径。默认 '.'。"
},
"use_regex": {
"type": "boolean",
"description": "是否使用正则匹配(默认 false。"
},
"case_sensitive": {
"type": "boolean",
"description": "是否区分大小写(默认 false。"
},
"max_results": {
"type": "integer",
"description": "最大返回结果数(默认 20。"
},
"max_matches_per_file": {
"type": "integer",
"description": "[content] 每个文件最多返回多少处匹配(默认 3。"
},
"include_glob": {
"type": "array",
"description": "仅包含匹配这些 glob 的文件。",
"items": { "type": "string" }
},
"exclude_glob": {
"type": "array",
"description": "排除匹配这些 glob 的文件。",
"items": { "type": "string" }
},
"max_file_size": {
"type": "integer",
"description": "跳过超过该字节数的文件。"
}
},
"required": ["mode", "query"]
}
}
},
{
"type": "function",
"function": {
"name": "read_mediafile",
"description": "读取图片或视频文件并附加给模型。非媒体文件将拒绝。",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "媒体文件路径:工作区内请用相对路径,工作区外可用绝对路径。"
}
},
"required": ["path"]
}
}
},
{
"type": "function",
"function": {
"name": "remember",
"description": "记录用户个人记忆。当用户表达了个人偏好、习惯、待办事项、身份信息、人际关系、重要事件等值得记住的信息时调用。\n注意不要记录无意义信息例如用户的打招呼、让调低音量等一次性操作。",
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["add", "update", "delete"],
"description": "操作类型add=新增记忆update=更新已有记忆delete=删除记忆"
},
"type": {
"type": "string",
"enum": ["preference", "habit", "event", "todo", "identity", "relationship", "other"],
"description": "记忆类型。preference=偏好喜欢什么不喜欢什么habit=用户的生活习惯event=过去需要记住的重要事件todo=未来需要完成的任务identity=用户的身份信息relationship=用户和其他人的关联other=其他"
},
"content": {
"type": "string",
"description": "记忆内容。add时必须提供。update时可选不提供则保留原内容"
},
"keywords": {
"type": "array",
"items": { "type": "string" },
"description": "关键词数组,便于后续搜索匹配"
},
"id": {
"type": "string",
"description": "记忆ID。update和delete时必填"
}
},
"required": ["action"]
}
}
},
{
"type": "function",
"function": {
"name": "recall",
"description": "搜索用户个人记忆。当用户提问可能涉及个人偏好、历史或已知信息时使用。注意:简单操作如调音量、问天气不需要搜索。搜索结果自然融入回答,不要显式说'根据我的记忆'。",
"parameters": {
"type": "object",
"properties": {
"types": {
"type": "array",
"items": { "type": "string" },
"description": "限定搜索的记忆类型可选值preference, habit, event, todo, identity, relationship, other。不提供则搜索所有类型"
},
"query": {
"type": "string",
"description": "搜索关键词,在记忆内容和关键词中匹配"
},
"start_date": {
"type": "string",
"description": "起始日期ISO格式如2026-01-01可选"
},
"end_date": {
"type": "string",
"description": "结束日期ISO格式如2026-12-31可选"
},
"max_results": {
"type": "integer",
"description": "最大返回数量默认10"
}
},
"required": []
}
}
},
{
"type": "function",
"function": {
"name": "set_identity",
"description": "设置用户的身份信息和 AI 助手个性化配置。当用户表达以下意图时使用此工具,而不是 remember\n- 希望 AI 助手叫什么名字\n- 希望被怎么称呼(用户的名字/昵称)\n- 希望 AI 助手用什么语气交流\n这三个配置会立即生效影响后续所有对话。可以只更新其中一个字段。",
"parameters": {
"type": "object",
"properties": {
"assistant_name": {
"type": "string",
"description": "AI 助手的名字,如'小A'、'Jarvis'。可选。"
},
"user_name": {
"type": "string",
"description": "用户希望被称呼的名字,如'jojo'、'张总'。可选。"
},
"assistant_tone": {
"type": "string",
"description": "AI 助手的语气,可选值:友好、专业、幽默、简洁、温暖、正式。可选。"
}
},
"required": []
}
}
}
]