@geminilight/mindos 0.6.22 → 0.6.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -46
- package/README_zh.md +58 -46
- package/app/app/.well-known/agent-card.json/route.ts +34 -0
- package/app/app/api/a2a/route.ts +100 -0
- package/app/app/api/file/import/route.ts +0 -2
- package/app/app/api/setup/route.ts +2 -0
- package/app/components/Backlinks.tsx +2 -2
- package/app/components/Breadcrumb.tsx +1 -1
- package/app/components/CsvView.tsx +41 -19
- package/app/components/DirView.tsx +2 -2
- package/app/components/FileTree.tsx +14 -1
- package/app/components/GuideCard.tsx +6 -2
- package/app/components/HomeContent.tsx +2 -2
- package/app/components/RightAskPanel.tsx +17 -10
- package/app/components/SearchModal.tsx +3 -3
- package/app/components/SidebarLayout.tsx +4 -2
- package/app/components/SyncStatusBar.tsx +2 -2
- package/app/components/ask/AskContent.tsx +6 -6
- package/app/components/ask/FileChip.tsx +1 -1
- package/app/components/ask/MentionPopover.tsx +2 -2
- package/app/components/ask/MessageList.tsx +1 -1
- package/app/components/ask/SlashCommandPopover.tsx +1 -1
- package/app/components/explore/UseCaseCard.tsx +2 -2
- package/app/components/help/HelpContent.tsx +6 -1
- package/app/components/panels/AgentsPanelAgentDetail.tsx +2 -2
- package/app/components/panels/DiscoverPanel.tsx +3 -3
- package/app/components/panels/PanelNavRow.tsx +2 -2
- package/app/components/panels/PluginsPanel.tsx +1 -1
- package/app/components/panels/SearchPanel.tsx +3 -3
- package/app/components/renderers/summary/SummaryRenderer.tsx +1 -1
- package/app/components/settings/AiTab.tsx +4 -4
- package/app/components/settings/KnowledgeTab.tsx +1 -1
- package/app/components/settings/McpTab.tsx +22 -4
- package/app/components/settings/UpdateTab.tsx +1 -1
- package/app/components/setup/index.tsx +9 -3
- package/app/components/walkthrough/WalkthroughProvider.tsx +2 -2
- package/app/hooks/useAskPanel.ts +7 -3
- package/app/hooks/useFileImport.ts +1 -1
- package/app/lib/a2a/agent-card.ts +107 -0
- package/app/lib/a2a/index.ts +23 -0
- package/app/lib/a2a/task-handler.ts +228 -0
- package/app/lib/a2a/types.ts +158 -0
- package/app/lib/agent/tools.ts +1 -1
- package/app/lib/core/fs-ops.ts +3 -2
- package/app/lib/fs.ts +28 -11
- package/app/lib/i18n-en.ts +2 -0
- package/app/lib/i18n-zh.ts +2 -0
- package/app/lib/settings.ts +1 -1
- package/bin/cli.js +48 -20
- package/bin/commands/agent.js +18 -0
- package/bin/commands/api.js +58 -0
- package/bin/commands/ask.js +101 -0
- package/bin/commands/file.js +286 -0
- package/bin/commands/search.js +51 -0
- package/bin/commands/space.js +167 -0
- package/bin/commands/status.js +69 -0
- package/bin/lib/command.js +156 -0
- package/mcp/dist/index.cjs +1 -1
- package/mcp/src/index.ts +1 -1
- package/package.json +1 -1
- package/skills/mindos/SKILL.md +2 -2
- package/skills/mindos-zh/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
<p align="center">
|
|
16
16
|
<a href="https://tianfuwang.tech/MindOS"><img src="https://img.shields.io/badge/Website-MindOS-0ea5e9.svg?style=for-the-badge" alt="Website"></a>
|
|
17
17
|
<a href="https://www.npmjs.com/package/@geminilight/mindos"><img src="https://img.shields.io/npm/v/@geminilight/mindos.svg?style=for-the-badge&color=f59e0b" alt="npm version"></a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/@geminilight/mindos"><img src="https://img.shields.io/npm/dw/@geminilight/mindos.svg?style=for-the-badge&color=10b981" alt="npm downloads"></a>
|
|
19
18
|
<a href="#wechat"><img src="https://img.shields.io/badge/WeChat-Group-07C160.svg?style=for-the-badge&logo=wechat&logoColor=white" alt="WeChat"></a>
|
|
20
19
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-6366f1.svg?style=for-the-badge" alt="MIT License"></a>
|
|
21
20
|
</p>
|
|
@@ -32,6 +31,25 @@ MindOS is where you think, and where your AI agents act — a local-first knowle
|
|
|
32
31
|
</picture>
|
|
33
32
|
</p>
|
|
34
33
|
|
|
34
|
+
<table>
|
|
35
|
+
<tr>
|
|
36
|
+
<td width="50%"><img src="assets/images/mindos-home.png" alt="MindOS Home" /></td>
|
|
37
|
+
<td width="50%"><img src="assets/images/mindos-chat.png" alt="MindOS AI Chat" /></td>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr>
|
|
40
|
+
<td align="center"><em>Home — Knowledge base overview</em></td>
|
|
41
|
+
<td align="center"><em>AI Chat — Converse with your knowledge in context</em></td>
|
|
42
|
+
</tr>
|
|
43
|
+
<tr>
|
|
44
|
+
<td width="50%"><img src="assets/images/mindos-dashboard.png" alt="MindOS Agents Dashboard" /></td>
|
|
45
|
+
<td width="50%"><img src="assets/images/mindos-echo.png" alt="MindOS Echo" /></td>
|
|
46
|
+
</tr>
|
|
47
|
+
<tr>
|
|
48
|
+
<td align="center"><em>Agents — Manage all connected AI agents</em></td>
|
|
49
|
+
<td align="center"><em>Echo — Reflect and distill cognitive growth</em></td>
|
|
50
|
+
</tr>
|
|
51
|
+
</table>
|
|
52
|
+
|
|
35
53
|
> [!IMPORTANT]
|
|
36
54
|
> **⭐ One-click install:** Send this to your Agent (Claude Code, Cursor, etc.) to set up everything automatically:
|
|
37
55
|
> ```
|
|
@@ -67,37 +85,6 @@ You express preferences but the next chat starts from zero, leaving your thinkin
|
|
|
67
85
|
|
|
68
86
|
> **Foundation:** Local-first by default — all data stays in local plain text for privacy, ownership, and speed.
|
|
69
87
|
|
|
70
|
-
## ✨ Features
|
|
71
|
-
|
|
72
|
-
**For Humans**
|
|
73
|
-
|
|
74
|
-
- **GUI Workbench**: browse, edit, search notes with unified search + AI entry (`⌘K` / `⌘/`), designed for human-AI co-creation.
|
|
75
|
-
- **Built-in Agent Assistant**: converse with the knowledge base in context; edits seamlessly capture human-curated knowledge.
|
|
76
|
-
- **Plugin Extensions**: multiple built-in renderer plugins — TODO Board, CSV Views, Wiki Graph, Timeline, Agent Inspector, and more.
|
|
77
|
-
|
|
78
|
-
**For Agents**
|
|
79
|
-
|
|
80
|
-
- **MCP Server + Skills**: stdio + HTTP dual transport, full-lineup Agent compatible (OpenClaw, Claude Code, Cursor, etc.). Zero-config access.
|
|
81
|
-
- **Structured Templates**: pre-set directory structures for Profiles, Workflows, Configurations, etc., to jumpstart personal context.
|
|
82
|
-
- **Agent-Ready Docs**: everyday notes naturally double as high-quality executable Agent commands — no format conversion needed, write and dispatch.
|
|
83
|
-
|
|
84
|
-
**Infrastructure**
|
|
85
|
-
|
|
86
|
-
- **Security**: Bearer Token auth, path sandboxing, INSTRUCTION.md write-protection, atomic writes.
|
|
87
|
-
- **Knowledge Graph**: dynamically parses and visualizes inter-file references and dependencies.
|
|
88
|
-
- **Backlinks View**: displays all files that reference the current file, helping you understand how a note fits into the knowledge network.
|
|
89
|
-
- **Git Time Machine**: Git auto-sync (commit/push/pull), records every edit by both humans and Agents. One-click rollback, cross-device sync.
|
|
90
|
-
- **Desktop App**: native macOS/Windows/Linux app with system tray, auto-start, and local process management.
|
|
91
|
-
|
|
92
|
-
<details>
|
|
93
|
-
<summary><strong>Coming Soon</strong></summary>
|
|
94
|
-
|
|
95
|
-
- [ ] ACP (Agent Communication Protocol): connect external Agents (e.g., Claude Code, Cursor) and turn the knowledge base into a multi-Agent collaboration hub
|
|
96
|
-
- [ ] Deep RAG integration: retrieval-augmented generation grounded in your knowledge base for more accurate, context-aware AI responses
|
|
97
|
-
- [ ] Agent Inspector: render Agent operation logs as a filterable timeline to audit every tool call in detail
|
|
98
|
-
|
|
99
|
-
</details>
|
|
100
|
-
|
|
101
88
|
---
|
|
102
89
|
|
|
103
90
|
## 🚀 Getting Started
|
|
@@ -150,9 +137,6 @@ mindos open
|
|
|
150
137
|
2. Upload your resume or any personal/project material.
|
|
151
138
|
3. Send this prompt: `Help me sync this information into my MindOS knowledge base.`
|
|
152
139
|
|
|
153
|
-
<p align="center">
|
|
154
|
-
<img src="assets/images/gui-sync-cv.png" alt="Sync CV Example" width="800" />
|
|
155
|
-
</p>
|
|
156
140
|
|
|
157
141
|
### 4. Make Any Agent Ready (MCP + Skills)
|
|
158
142
|
|
|
@@ -172,6 +156,37 @@ npx skills add https://github.com/GeminiLight/MindOS --skill mindos-zh -g -y #
|
|
|
172
156
|
|
|
173
157
|
> For remote access, manual JSON config, and common pitfalls, see **[docs/en/supported-agents.md](docs/en/supported-agents.md)**.
|
|
174
158
|
|
|
159
|
+
## ✨ Features
|
|
160
|
+
|
|
161
|
+
**For Humans**
|
|
162
|
+
|
|
163
|
+
- **GUI Workbench**: browse, edit, search notes with unified search + AI entry (`⌘K` / `⌘/`), designed for human-AI co-creation.
|
|
164
|
+
- **Built-in Agent Assistant**: converse with the knowledge base in context; edits seamlessly capture human-curated knowledge.
|
|
165
|
+
- **Plugin Extensions**: multiple built-in renderer plugins — TODO Board, CSV Views, Wiki Graph, Timeline, Agent Inspector, and more.
|
|
166
|
+
|
|
167
|
+
**For Agents**
|
|
168
|
+
|
|
169
|
+
- **MCP Server + Skills**: stdio + HTTP dual transport, full-lineup Agent compatible (OpenClaw, Claude Code, Cursor, etc.). Zero-config access.
|
|
170
|
+
- **Structured Templates**: pre-set directory structures for Profiles, Workflows, Configurations, etc., to jumpstart personal context.
|
|
171
|
+
- **Agent-Ready Docs**: everyday notes naturally double as high-quality executable Agent commands — no format conversion needed, write and dispatch.
|
|
172
|
+
|
|
173
|
+
**Infrastructure**
|
|
174
|
+
|
|
175
|
+
- **Security**: Bearer Token auth, path sandboxing, INSTRUCTION.md write-protection, atomic writes.
|
|
176
|
+
- **Knowledge Graph**: dynamically parses and visualizes inter-file references and dependencies.
|
|
177
|
+
- **Backlinks View**: displays all files that reference the current file, helping you understand how a note fits into the knowledge network.
|
|
178
|
+
- **Git Time Machine**: Git auto-sync (commit/push/pull), records every edit by both humans and Agents. One-click rollback, cross-device sync.
|
|
179
|
+
- **Desktop App**: native macOS/Windows/Linux app with system tray, auto-start, and local process management.
|
|
180
|
+
|
|
181
|
+
<details>
|
|
182
|
+
<summary><strong>Coming Soon</strong></summary>
|
|
183
|
+
|
|
184
|
+
- [ ] ACP (Agent Communication Protocol): connect external Agents (e.g., Claude Code, Cursor) and turn the knowledge base into a multi-Agent collaboration hub
|
|
185
|
+
- [ ] Deep RAG integration: retrieval-augmented generation grounded in your knowledge base for more accurate, context-aware AI responses
|
|
186
|
+
- [ ] Agent Inspector: render Agent operation logs as a filterable timeline to audit every tool call in detail
|
|
187
|
+
|
|
188
|
+
</details>
|
|
189
|
+
|
|
175
190
|
## ⚙️ How It Works
|
|
176
191
|
|
|
177
192
|
```mermaid
|
|
@@ -203,22 +218,21 @@ graph LR
|
|
|
203
218
|
|
|
204
219
|
| Agent | MCP | Skills |
|
|
205
220
|
|:------|:---:|:------:|
|
|
206
|
-
| MindOS Agent | ✅ | ✅ |
|
|
207
221
|
| OpenClaw | ✅ | ✅ |
|
|
208
|
-
| Claude
|
|
209
|
-
| CodeBuddy | ✅ | ✅ |
|
|
222
|
+
| Claude Code | ✅ | ✅ |
|
|
210
223
|
| Cursor | ✅ | ✅ |
|
|
211
|
-
|
|
|
212
|
-
| Cline | ✅ | ✅ |
|
|
213
|
-
| Trae | ✅ | ✅ |
|
|
224
|
+
| Codex | ✅ | ✅ |
|
|
214
225
|
| Gemini CLI | ✅ | ✅ |
|
|
215
226
|
| GitHub Copilot | ✅ | ✅ |
|
|
216
|
-
|
|
|
227
|
+
| Trae | ✅ | ✅ |
|
|
228
|
+
| CodeBuddy | ✅ | ✅ |
|
|
229
|
+
| Qoder | ✅ | ✅ |
|
|
230
|
+
| Cline | ✅ | ✅ |
|
|
231
|
+
| Windsurf | ✅ | ✅ |
|
|
217
232
|
|
|
218
233
|
---
|
|
219
234
|
|
|
220
|
-
|
|
221
|
-
<summary><strong>📁 Project Structure</strong></summary>
|
|
235
|
+
## 📁 Project Structure
|
|
222
236
|
|
|
223
237
|
```bash
|
|
224
238
|
MindOS/
|
|
@@ -236,8 +250,6 @@ MindOS/
|
|
|
236
250
|
└── mind/ # Your private knowledge base (default: ~/MindOS/mind, customizable on onboard)
|
|
237
251
|
```
|
|
238
252
|
|
|
239
|
-
</details>
|
|
240
|
-
|
|
241
253
|
## ⌨️ CLI Commands
|
|
242
254
|
|
|
243
255
|
> Full command reference: **[docs/en/cli-commands.md](docs/en/cli-commands.md)**
|
package/README_zh.md
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
<p align="center">
|
|
16
16
|
<a href="https://tianfuwang.tech/MindOS"><img src="https://img.shields.io/badge/Website-MindOS-0ea5e9.svg?style=for-the-badge" alt="Website"></a>
|
|
17
17
|
<a href="https://www.npmjs.com/package/@geminilight/mindos"><img src="https://img.shields.io/npm/v/@geminilight/mindos.svg?style=for-the-badge&color=f59e0b" alt="npm version"></a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/@geminilight/mindos"><img src="https://img.shields.io/npm/dw/@geminilight/mindos.svg?style=for-the-badge&color=10b981" alt="npm downloads"></a>
|
|
19
18
|
<a href="#wechat"><img src="https://img.shields.io/badge/WeChat-群聊-07C160.svg?style=for-the-badge&logo=wechat&logoColor=white" alt="WeChat"></a>
|
|
20
19
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-6366f1.svg?style=for-the-badge" alt="MIT License"></a>
|
|
21
20
|
</p>
|
|
@@ -32,6 +31,25 @@ MindOS 是你思考的地方,也是 AI Agent 行动的起点——一个你和
|
|
|
32
31
|
</picture>
|
|
33
32
|
</p>
|
|
34
33
|
|
|
34
|
+
<table>
|
|
35
|
+
<tr>
|
|
36
|
+
<td width="50%"><img src="assets/images/mindos-home.png" alt="MindOS 首页" /></td>
|
|
37
|
+
<td width="50%"><img src="assets/images/mindos-chat.png" alt="MindOS AI 对话" /></td>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr>
|
|
40
|
+
<td align="center"><em>首页 — 知识库概览</em></td>
|
|
41
|
+
<td align="center"><em>AI 对话 — 在上下文中与知识库对话</em></td>
|
|
42
|
+
</tr>
|
|
43
|
+
<tr>
|
|
44
|
+
<td width="50%"><img src="assets/images/mindos-dashboard.png" alt="MindOS Agent 工作台" /></td>
|
|
45
|
+
<td width="50%"><img src="assets/images/mindos-echo.png" alt="MindOS Echo" /></td>
|
|
46
|
+
</tr>
|
|
47
|
+
<tr>
|
|
48
|
+
<td align="center"><em>Agent 工作台 — 管理所有已连接的 AI Agent</em></td>
|
|
49
|
+
<td align="center"><em>Echo — 复盘与认知沉淀</em></td>
|
|
50
|
+
</tr>
|
|
51
|
+
</table>
|
|
52
|
+
|
|
35
53
|
> [!IMPORTANT]
|
|
36
54
|
> **⭐ 一键安装:** 把这句话发给你的 Agent(Claude Code、Cursor 等),自动完成全部安装:
|
|
37
55
|
> ```
|
|
@@ -67,37 +85,6 @@ Agent 记忆锁在黑箱中,推理无法审查,错误极难纠正且幻觉
|
|
|
67
85
|
|
|
68
86
|
> **底层原则:** 默认本地优先,全部数据以本地纯文本保存,兼顾隐私、主权与性能。
|
|
69
87
|
|
|
70
|
-
## ✨ 功能特性
|
|
71
|
-
|
|
72
|
-
**人类侧**
|
|
73
|
-
|
|
74
|
-
- **GUI 工作台**:浏览、编辑、搜索笔记,统一搜索 + AI 入口(`⌘K` / `⌘/`),专为人机共创设计。
|
|
75
|
-
- **内置 Agent 助手**:在上下文中与知识库对话,编辑无缝沉淀为可管理知识。
|
|
76
|
-
- **插件扩展**:多种内置渲染器插件——TODO Board、CSV Views、Wiki Graph、Timeline、Agent Inspector 等。
|
|
77
|
-
|
|
78
|
-
**Agent 侧**
|
|
79
|
-
|
|
80
|
-
- **MCP Server + Skills**:stdio + HTTP 双传输,全阵容 Agent 兼容(OpenClaw, Claude Code, Cursor 等),零配置接入。
|
|
81
|
-
- **结构化模板**:预置 Profile、Workflows、Configurations 等目录骨架,快速冷启动个人 Context。
|
|
82
|
-
- **笔记即指令**:日常笔记天然就是 Agent 可直接执行的高质量指令——无需额外格式转换,写下即可调度。
|
|
83
|
-
|
|
84
|
-
**基础设施**
|
|
85
|
-
|
|
86
|
-
- **安全防线**:Bearer Token 认证、路径沙箱、INSTRUCTION.md 写保护、原子写入。
|
|
87
|
-
- **知识图谱**:动态解析并可视化文件间的引用与依赖关系。
|
|
88
|
-
- **反向链接视图**:展示所有引用当前文件的反向链接,理解笔记在知识网络中的位置。
|
|
89
|
-
- **Git 时光机**:Git 自动同步(commit/push/pull),记录人类与 Agent 的每次编辑历史,一键回滚,跨设备同步。
|
|
90
|
-
- **桌面客户端**:原生 macOS/Windows/Linux 应用,系统托盘、开机自启、本地进程管理。
|
|
91
|
-
|
|
92
|
-
<details>
|
|
93
|
-
<summary><strong>即将到来</strong></summary>
|
|
94
|
-
|
|
95
|
-
- [ ] ACP(Agent Communication Protocol):连接外部 Agent(如 Claude Code、Cursor),让知识库成为多 Agent 协作的中枢
|
|
96
|
-
- [ ] RAG 深度集成:基于知识库内容的检索增强生成,让 AI 回答更精准、更有上下文
|
|
97
|
-
- [ ] Agent 审计面板(Agent Inspector):将 Agent 操作日志渲染为可筛选的时间线,审查每次工具调用的详情
|
|
98
|
-
|
|
99
|
-
</details>
|
|
100
|
-
|
|
101
88
|
---
|
|
102
89
|
|
|
103
90
|
## 🚀 快速开始
|
|
@@ -150,9 +137,6 @@ mindos open
|
|
|
150
137
|
2. 上传你的简历或任意个人/项目资料。
|
|
151
138
|
3. 发送指令:`帮我把这些信息同步到我的 MindOS 知识库。`
|
|
152
139
|
|
|
153
|
-
<p align="center">
|
|
154
|
-
<img src="assets/images/gui-sync-cv.png" alt="同步简历示例" width="800" />
|
|
155
|
-
</p>
|
|
156
140
|
|
|
157
141
|
### 4. 让任意 Agent 可用(MCP + Skills)
|
|
158
142
|
|
|
@@ -172,6 +156,37 @@ npx skills add https://github.com/GeminiLight/MindOS --skill mindos-zh -g -y #
|
|
|
172
156
|
|
|
173
157
|
> 远程配置、手动 JSON 片段、常见误区等详见 **[docs/zh/supported-agents.md](docs/zh/supported-agents.md)**。
|
|
174
158
|
|
|
159
|
+
## ✨ 功能特性
|
|
160
|
+
|
|
161
|
+
**人类侧**
|
|
162
|
+
|
|
163
|
+
- **GUI 工作台**:浏览、编辑、搜索笔记,统一搜索 + AI 入口(`⌘K` / `⌘/`),专为人机共创设计。
|
|
164
|
+
- **内置 Agent 助手**:在上下文中与知识库对话,编辑无缝沉淀为可管理知识。
|
|
165
|
+
- **插件扩展**:多种内置渲染器插件——TODO Board、CSV Views、Wiki Graph、Timeline、Agent Inspector 等。
|
|
166
|
+
|
|
167
|
+
**Agent 侧**
|
|
168
|
+
|
|
169
|
+
- **MCP Server + Skills**:stdio + HTTP 双传输,全阵容 Agent 兼容(OpenClaw, Claude Code, Cursor 等),零配置接入。
|
|
170
|
+
- **结构化模板**:预置 Profile、Workflows、Configurations 等目录骨架,快速冷启动个人 Context。
|
|
171
|
+
- **笔记即指令**:日常笔记天然就是 Agent 可直接执行的高质量指令——无需额外格式转换,写下即可调度。
|
|
172
|
+
|
|
173
|
+
**基础设施**
|
|
174
|
+
|
|
175
|
+
- **安全防线**:Bearer Token 认证、路径沙箱、INSTRUCTION.md 写保护、原子写入。
|
|
176
|
+
- **知识图谱**:动态解析并可视化文件间的引用与依赖关系。
|
|
177
|
+
- **反向链接视图**:展示所有引用当前文件的反向链接,理解笔记在知识网络中的位置。
|
|
178
|
+
- **Git 时光机**:Git 自动同步(commit/push/pull),记录人类与 Agent 的每次编辑历史,一键回滚,跨设备同步。
|
|
179
|
+
- **桌面客户端**:原生 macOS/Windows/Linux 应用,系统托盘、开机自启、本地进程管理。
|
|
180
|
+
|
|
181
|
+
<details>
|
|
182
|
+
<summary><strong>即将到来</strong></summary>
|
|
183
|
+
|
|
184
|
+
- [ ] ACP(Agent Communication Protocol):连接外部 Agent(如 Claude Code、Cursor),让知识库成为多 Agent 协作的中枢
|
|
185
|
+
- [ ] RAG 深度集成:基于知识库内容的检索增强生成,让 AI 回答更精准、更有上下文
|
|
186
|
+
- [ ] Agent 审计面板(Agent Inspector):将 Agent 操作日志渲染为可筛选的时间线,审查每次工具调用的详情
|
|
187
|
+
|
|
188
|
+
</details>
|
|
189
|
+
|
|
175
190
|
## ⚙️ 运作机制
|
|
176
191
|
|
|
177
192
|
```mermaid
|
|
@@ -203,22 +218,21 @@ graph LR
|
|
|
203
218
|
|
|
204
219
|
| Agent | MCP | Skills |
|
|
205
220
|
|:------|:---:|:------:|
|
|
206
|
-
| MindOS Agent | ✅ | ✅ |
|
|
207
221
|
| OpenClaw | ✅ | ✅ |
|
|
208
|
-
| Claude
|
|
209
|
-
| CodeBuddy | ✅ | ✅ |
|
|
222
|
+
| Claude Code | ✅ | ✅ |
|
|
210
223
|
| Cursor | ✅ | ✅ |
|
|
211
|
-
|
|
|
212
|
-
| Cline | ✅ | ✅ |
|
|
213
|
-
| Trae | ✅ | ✅ |
|
|
224
|
+
| Codex | ✅ | ✅ |
|
|
214
225
|
| Gemini CLI | ✅ | ✅ |
|
|
215
226
|
| GitHub Copilot | ✅ | ✅ |
|
|
216
|
-
|
|
|
227
|
+
| Trae | ✅ | ✅ |
|
|
228
|
+
| CodeBuddy | ✅ | ✅ |
|
|
229
|
+
| Qoder | ✅ | ✅ |
|
|
230
|
+
| Cline | ✅ | ✅ |
|
|
231
|
+
| Windsurf | ✅ | ✅ |
|
|
217
232
|
|
|
218
233
|
---
|
|
219
234
|
|
|
220
|
-
|
|
221
|
-
<summary><strong>📁 项目架构</strong></summary>
|
|
235
|
+
## 📁 项目架构
|
|
222
236
|
|
|
223
237
|
```bash
|
|
224
238
|
MindOS/
|
|
@@ -236,8 +250,6 @@ MindOS/
|
|
|
236
250
|
└── my-mind/ # 你的私有知识库(默认路径,onboard 时可自定义)
|
|
237
251
|
```
|
|
238
252
|
|
|
239
|
-
</details>
|
|
240
|
-
|
|
241
253
|
## ⌨️ CLI 命令
|
|
242
254
|
|
|
243
255
|
> 完整命令参考:**[docs/zh/cli-commands.md](docs/zh/cli-commands.md)**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const dynamic = 'force-dynamic';
|
|
2
|
+
|
|
3
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
+
import { buildAgentCard } from '@/lib/a2a/agent-card';
|
|
5
|
+
|
|
6
|
+
const CORS_HEADERS: Record<string, string> = {
|
|
7
|
+
'Access-Control-Allow-Origin': '*',
|
|
8
|
+
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
|
9
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
10
|
+
'Cache-Control': 'public, max-age=300',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function GET(req: NextRequest) {
|
|
14
|
+
// Prefer explicit config; fall back to request headers
|
|
15
|
+
const configuredUrl = process.env.MINDOS_BASE_URL;
|
|
16
|
+
let baseUrl: string;
|
|
17
|
+
if (configuredUrl) {
|
|
18
|
+
baseUrl = configuredUrl.replace(/\/+$/, '');
|
|
19
|
+
} else {
|
|
20
|
+
const proto = req.headers.get('x-forwarded-proto') ?? 'http';
|
|
21
|
+
const host = req.headers.get('host') ?? `localhost:${process.env.PORT || 3456}`;
|
|
22
|
+
baseUrl = `${proto}://${host}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const card = buildAgentCard(baseUrl);
|
|
26
|
+
|
|
27
|
+
const res = NextResponse.json(card);
|
|
28
|
+
for (const [k, v] of Object.entries(CORS_HEADERS)) res.headers.set(k, v);
|
|
29
|
+
return res;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function OPTIONS() {
|
|
33
|
+
return new Response(null, { status: 204, headers: CORS_HEADERS });
|
|
34
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const dynamic = 'force-dynamic';
|
|
2
|
+
|
|
3
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
+
import type { JsonRpcRequest, JsonRpcResponse, SendMessageParams, GetTaskParams, CancelTaskParams } from '@/lib/a2a/types';
|
|
5
|
+
import { A2A_ERRORS } from '@/lib/a2a/types';
|
|
6
|
+
import { handleSendMessage, handleGetTask, handleCancelTask } from '@/lib/a2a/task-handler';
|
|
7
|
+
|
|
8
|
+
const CORS_HEADERS: Record<string, string> = {
|
|
9
|
+
'Access-Control-Allow-Origin': '*',
|
|
10
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
11
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization, A2A-Version',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function jsonRpcOk(id: string | number | null, result: unknown): JsonRpcResponse {
|
|
15
|
+
return { jsonrpc: '2.0', id, result };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function jsonRpcError(id: string | number | null, error: { code: number; message: string; data?: unknown }): JsonRpcResponse {
|
|
19
|
+
return { jsonrpc: '2.0', id, error };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function respond(body: JsonRpcResponse, status = 200) {
|
|
23
|
+
const res = NextResponse.json(body, { status });
|
|
24
|
+
for (const [k, v] of Object.entries(CORS_HEADERS)) res.headers.set(k, v);
|
|
25
|
+
return res;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const MAX_REQUEST_BYTES = 100_000; // 100KB max request body
|
|
29
|
+
|
|
30
|
+
export async function POST(req: NextRequest) {
|
|
31
|
+
// Check content length to prevent OOM from oversized payloads
|
|
32
|
+
const contentLength = Number(req.headers.get('content-length') || 0);
|
|
33
|
+
if (contentLength > MAX_REQUEST_BYTES) {
|
|
34
|
+
return respond(jsonRpcError(null, { code: -32600, message: `Request too large (max ${MAX_REQUEST_BYTES} bytes)` }), 413);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Parse JSON-RPC request
|
|
38
|
+
let rpc: JsonRpcRequest;
|
|
39
|
+
try {
|
|
40
|
+
rpc = await req.json();
|
|
41
|
+
} catch {
|
|
42
|
+
return respond(jsonRpcError(null, A2A_ERRORS.PARSE_ERROR), 400);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (rpc.jsonrpc !== '2.0' || typeof rpc.method !== 'string') {
|
|
46
|
+
return respond(jsonRpcError(rpc.id ?? null, A2A_ERRORS.INVALID_REQUEST), 400);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
switch (rpc.method) {
|
|
51
|
+
case 'SendMessage': {
|
|
52
|
+
const params = rpc.params as unknown as SendMessageParams;
|
|
53
|
+
if (!params?.message?.parts?.length) {
|
|
54
|
+
return respond(jsonRpcError(rpc.id, A2A_ERRORS.INVALID_PARAMS));
|
|
55
|
+
}
|
|
56
|
+
const task = await handleSendMessage(params);
|
|
57
|
+
return respond(jsonRpcOk(rpc.id, task));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
case 'GetTask': {
|
|
61
|
+
const params = rpc.params as unknown as GetTaskParams;
|
|
62
|
+
if (!params?.id) {
|
|
63
|
+
return respond(jsonRpcError(rpc.id, A2A_ERRORS.INVALID_PARAMS));
|
|
64
|
+
}
|
|
65
|
+
const task = handleGetTask(params);
|
|
66
|
+
if (!task) {
|
|
67
|
+
return respond(jsonRpcError(rpc.id, A2A_ERRORS.TASK_NOT_FOUND));
|
|
68
|
+
}
|
|
69
|
+
return respond(jsonRpcOk(rpc.id, task));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
case 'CancelTask': {
|
|
73
|
+
const params = rpc.params as unknown as CancelTaskParams;
|
|
74
|
+
if (!params?.id) {
|
|
75
|
+
return respond(jsonRpcError(rpc.id, A2A_ERRORS.INVALID_PARAMS));
|
|
76
|
+
}
|
|
77
|
+
const task = handleCancelTask(params);
|
|
78
|
+
if (!task) {
|
|
79
|
+
return respond(jsonRpcError(rpc.id, {
|
|
80
|
+
...A2A_ERRORS.TASK_NOT_FOUND,
|
|
81
|
+
message: 'Task not found or not cancelable',
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
return respond(jsonRpcOk(rpc.id, task));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
default:
|
|
88
|
+
return respond(jsonRpcError(rpc.id, A2A_ERRORS.METHOD_NOT_FOUND));
|
|
89
|
+
}
|
|
90
|
+
} catch (err) {
|
|
91
|
+
return respond(jsonRpcError(rpc.id, {
|
|
92
|
+
...A2A_ERRORS.INTERNAL_ERROR,
|
|
93
|
+
data: (err as Error).message,
|
|
94
|
+
}), 500);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function OPTIONS() {
|
|
99
|
+
return new Response(null, { status: 204, headers: CORS_HEADERS });
|
|
100
|
+
}
|
|
@@ -7,7 +7,6 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
7
7
|
import { revalidatePath } from 'next/cache';
|
|
8
8
|
import { sanitizeFileName, convertToMarkdown } from '@/lib/core/file-convert';
|
|
9
9
|
import { resolveSafe } from '@/lib/core/security';
|
|
10
|
-
import { scaffoldIfNewSpace } from '@/lib/core/space-scaffold';
|
|
11
10
|
import { organizeAfterImport } from '@/lib/core/organize';
|
|
12
11
|
import { invalidateSearchIndex } from '@/lib/core/search';
|
|
13
12
|
import { effectiveSopRoot } from '@/lib/settings';
|
|
@@ -157,7 +156,6 @@ export async function POST(req: NextRequest) {
|
|
|
157
156
|
|
|
158
157
|
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
159
158
|
fs.writeFileSync(resolved, convertResult.content, 'utf-8');
|
|
160
|
-
scaffoldIfNewSpace(mindRoot, finalRel);
|
|
161
159
|
|
|
162
160
|
created.push({ original: entry.name, path: finalRel });
|
|
163
161
|
createdPaths.push(finalRel);
|
|
@@ -172,6 +172,8 @@ export async function PATCH(req: NextRequest) {
|
|
|
172
172
|
if (typeof patch.askedAI === 'boolean') updated.askedAI = patch.askedAI;
|
|
173
173
|
if (typeof patch.nextStepIndex === 'number' && patch.nextStepIndex >= 0) updated.nextStepIndex = patch.nextStepIndex;
|
|
174
174
|
if (typeof patch.active === 'boolean') updated.active = patch.active;
|
|
175
|
+
if (typeof patch.walkthroughStep === 'number' && patch.walkthroughStep >= 0) updated.walkthroughStep = patch.walkthroughStep;
|
|
176
|
+
if (typeof patch.walkthroughDismissed === 'boolean') updated.walkthroughDismissed = patch.walkthroughDismissed;
|
|
175
177
|
|
|
176
178
|
writeSettings({ ...current, guideState: updated });
|
|
177
179
|
return NextResponse.json({ ok: true, guideState: updated });
|
|
@@ -58,10 +58,10 @@ export default function Backlinks({ filePath }: { filePath: string }) {
|
|
|
58
58
|
<FileText size={14} className="text-muted-foreground group-hover:text-[var(--amber)]" />
|
|
59
59
|
</div>
|
|
60
60
|
<div className="min-w-0 flex-1">
|
|
61
|
-
<div className="font-medium text-sm text-foreground group-hover:text-[var(--amber)] transition-colors truncate mb-1">
|
|
61
|
+
<div className="font-medium text-sm text-foreground group-hover:text-[var(--amber)] transition-colors truncate mb-1" title={link.filePath}>
|
|
62
62
|
{link.filePath}
|
|
63
63
|
</div>
|
|
64
|
-
<div className="text-xs text-muted-foreground line-clamp-2 leading-relaxed italic opacity-80 group-hover:opacity-100 transition-opacity">
|
|
64
|
+
<div className="text-xs text-muted-foreground line-clamp-2 leading-relaxed italic opacity-80 group-hover:opacity-100 transition-opacity" title={link.snippets[0] || ''}>
|
|
65
65
|
{link.snippets[0] || ''}
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
@@ -29,7 +29,7 @@ export default function Breadcrumb({ filePath }: { filePath: string }) {
|
|
|
29
29
|
<span suppressHydrationWarning>{part}</span>
|
|
30
30
|
</span>
|
|
31
31
|
) : (
|
|
32
|
-
<Link href={href} className="hover:
|
|
32
|
+
<Link href={href} className="px-2 py-0.5 rounded-md hover:bg-muted/50 transition-colors truncate max-w-[200px]" title={part}>
|
|
33
33
|
<span suppressHydrationWarning>{part}</span>
|
|
34
34
|
</Link>
|
|
35
35
|
)}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useMemo, useState, useRef, useCallback, useEffect } from 'react';
|
|
4
4
|
import Papa from 'papaparse';
|
|
5
|
-
import { ChevronUp, ChevronDown, ChevronsUpDown, Plus, Trash2 } from 'lucide-react';
|
|
5
|
+
import { ChevronUp, ChevronDown, ChevronsUpDown, Plus, Trash2, Loader2 } from 'lucide-react';
|
|
6
6
|
|
|
7
7
|
interface CsvViewProps {
|
|
8
8
|
content: string;
|
|
@@ -135,6 +135,7 @@ export default function CsvView({ content: initialContent, appendAction, saveAct
|
|
|
135
135
|
const [sortCol, setSortCol] = useState<number | null>(null);
|
|
136
136
|
const [sortDir, setSortDir] = useState<SortDir>(null);
|
|
137
137
|
const [showAdd, setShowAdd] = useState(false);
|
|
138
|
+
const [saving, setSaving] = useState(false);
|
|
138
139
|
|
|
139
140
|
const parsed = useMemo(() => {
|
|
140
141
|
const result = Papa.parse<string[]>(content, { skipEmptyLines: true });
|
|
@@ -163,38 +164,57 @@ export default function CsvView({ content: initialContent, appendAction, saveAct
|
|
|
163
164
|
// Update a single cell and persist
|
|
164
165
|
const handleCellCommit = useCallback(async (rowIdx: number, colIdx: number, newVal: string) => {
|
|
165
166
|
if (!saveAction) return;
|
|
166
|
-
|
|
167
|
-
const updatedRows = rows.map((r, i) => {
|
|
168
|
-
// find which original row matches this sorted row
|
|
167
|
+
const updatedRows = rows.map((r) => {
|
|
169
168
|
const sorted = sortedRows[rowIdx];
|
|
170
169
|
if (r === sorted) return r.map((cell, ci) => ci === colIdx ? newVal : cell);
|
|
171
170
|
return r;
|
|
172
171
|
});
|
|
173
172
|
const newContent = serializeRows(headers, updatedRows);
|
|
174
173
|
setContent(newContent);
|
|
175
|
-
|
|
174
|
+
setSaving(true);
|
|
175
|
+
try {
|
|
176
|
+
await saveAction(newContent);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
console.error('[CsvView] Cell save failed:', err);
|
|
179
|
+
} finally {
|
|
180
|
+
setSaving(false);
|
|
181
|
+
}
|
|
176
182
|
}, [saveAction, rows, sortedRows, headers]);
|
|
177
183
|
|
|
178
184
|
// Delete a row and persist
|
|
179
185
|
const handleDeleteRow = useCallback(async (rowIdx: number) => {
|
|
180
|
-
if (!saveAction) return;
|
|
186
|
+
if (!saveAction || saving) return;
|
|
181
187
|
const sorted = sortedRows[rowIdx];
|
|
182
188
|
const updatedRows = rows.filter(r => r !== sorted);
|
|
183
189
|
const newContent = serializeRows(headers, updatedRows);
|
|
184
190
|
setContent(newContent);
|
|
185
|
-
|
|
186
|
-
|
|
191
|
+
setSaving(true);
|
|
192
|
+
try {
|
|
193
|
+
await saveAction(newContent);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
console.error('[CsvView] Row delete failed:', err);
|
|
196
|
+
} finally {
|
|
197
|
+
setSaving(false);
|
|
198
|
+
}
|
|
199
|
+
}, [saveAction, rows, sortedRows, headers, saving]);
|
|
187
200
|
|
|
188
201
|
// Append a new row
|
|
189
202
|
const handleAddRow = useCallback(async (newRow: string[]) => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
203
|
+
setSaving(true);
|
|
204
|
+
try {
|
|
205
|
+
if (appendAction) {
|
|
206
|
+
const result = await appendAction(newRow);
|
|
207
|
+
setContent(result.newContent);
|
|
208
|
+
} else if (saveAction) {
|
|
209
|
+
const newContent = serializeRows(headers, [...rows, newRow]);
|
|
210
|
+
setContent(newContent);
|
|
211
|
+
await saveAction(newContent);
|
|
212
|
+
}
|
|
213
|
+
setShowAdd(false);
|
|
214
|
+
} catch (err) {
|
|
215
|
+
console.error('[CsvView] Add row failed:', err);
|
|
216
|
+
} finally {
|
|
217
|
+
setSaving(false);
|
|
198
218
|
}
|
|
199
219
|
}, [appendAction, saveAction, headers, rows]);
|
|
200
220
|
|
|
@@ -266,9 +286,10 @@ export default function CsvView({ content: initialContent, appendAction, saveAct
|
|
|
266
286
|
{saveAction && (
|
|
267
287
|
<button
|
|
268
288
|
onClick={() => handleDeleteRow(rowIdx)}
|
|
269
|
-
|
|
289
|
+
disabled={saving}
|
|
290
|
+
className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-destructive/10 disabled:opacity-30"
|
|
270
291
|
style={{ color: 'var(--muted-foreground)' }}
|
|
271
|
-
title=
|
|
292
|
+
title={saving ? 'Saving...' : 'Delete row'}
|
|
272
293
|
>
|
|
273
294
|
<Trash2 size={12} />
|
|
274
295
|
</button>
|
|
@@ -295,8 +316,9 @@ export default function CsvView({ content: initialContent, appendAction, saveAct
|
|
|
295
316
|
className="px-4 py-2 flex items-center justify-between"
|
|
296
317
|
style={{ background: 'var(--muted)', borderTop: '1px solid var(--border)' }}
|
|
297
318
|
>
|
|
298
|
-
<span className="text-xs font-display" style={{ color: 'var(--muted-foreground)' }}>
|
|
319
|
+
<span className="text-xs font-display flex items-center gap-1.5" style={{ color: 'var(--muted-foreground)' }}>
|
|
299
320
|
{rows.length} rows · {headers.length} cols
|
|
321
|
+
{saving && <Loader2 size={10} className="animate-spin" style={{ color: 'var(--amber)' }} />}
|
|
300
322
|
</span>
|
|
301
323
|
|
|
302
324
|
{canEdit && !showAdd && (
|
|
@@ -207,7 +207,7 @@ export default function DirView({ dirPath, entries, spacePreview }: DirViewProps
|
|
|
207
207
|
{entry.type === 'directory'
|
|
208
208
|
? <FolderOpen size={22} className="text-yellow-400" />
|
|
209
209
|
: <FileIconLarge node={entry} />}
|
|
210
|
-
<span className="text-xs text-foreground leading-snug line-clamp-2 w-full" suppressHydrationWarning>
|
|
210
|
+
<span className="text-xs text-foreground leading-snug line-clamp-2 w-full" title={entry.name} suppressHydrationWarning>
|
|
211
211
|
{entry.name}
|
|
212
212
|
</span>
|
|
213
213
|
{entry.type === 'directory' && (
|
|
@@ -230,7 +230,7 @@ export default function DirView({ dirPath, entries, spacePreview }: DirViewProps
|
|
|
230
230
|
className="flex items-center gap-3 px-4 py-3 bg-card hover:bg-accent transition-colors duration-100"
|
|
231
231
|
>
|
|
232
232
|
<FileIcon node={entry} />
|
|
233
|
-
<span className="flex-1 text-sm text-foreground truncate" suppressHydrationWarning>
|
|
233
|
+
<span className="flex-1 text-sm text-foreground truncate" title={entry.name} suppressHydrationWarning>
|
|
234
234
|
{entry.name}
|
|
235
235
|
</span>
|
|
236
236
|
{entry.type === 'directory' ? (
|