Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ src/

### 2.1 `.mtm` 文件模型与 Serializer(`notebook/serializer.ts`)

`.mtm` 是 JSON:`{ metadata: AgentMetadata, context: AgentMessage[] }`。VS Code 通过 `NotebookSerializer` 把它与 Notebook 文档互相转换。
`.mtm` 是 JSON:`{ formatVersion: 1, metadata: AgentMetadata, context: PersistedAgentMessage[], notes?: NotebookNote[] }`。VS Code 通过 `NotebookSerializer` 把它与 Notebook 文档互相转换。

核心算法是 **messages ↔ generic cells 双向映射**(`messagesToGenericCells` / `genericCellsToMessages`),并被 HeadlessAdapter 复用,因此协议是"与 UI 无关"的:

- User 消息 → Code cell(kind 2)
- Assistant 消息 → Markup cell(kind 1)
- Markup cell(kind 1)→ 用户注释,按 `notes.beforeUserIndex` 独立持久化,不进入 Agent 历史
- **紧随 user 的 assistant/tool 消息组不单独建 cell**,而是存入该 user cell 的 `mutsumi_interaction` metadata,渲染为该 cell 的输出区(这是最反直觉的点)
- System 消息 → 带 `**System**: ` 前缀的 Markup cell,反序列化时剥前缀
- 孤儿 assistant/tool 消息(无前置 user)→ 直接拍平成 markdown 存 cell value,**不写** `mutsumi_interaction`
- `mutsumi_interaction` **只存在于 user cell**,永不写在 assistant cell 上
- Assistant/tool 消息必须附着于前置 user;磁盘中不支持孤儿 assistant/tool 或 system 消息
- `mutsumi_interaction` **只存在于 user cell**,永不写在 Markup cell 上
- 连续 user 是合法 pending turns;只在 provider 边界临时合并,磁盘 Cell 边界保持不变
- cell value 中保存的幽灵块 markdown 在反序列化时剥离(`stripGhostBlockFromCell`),结构化版本在 metadata 中

序列化时 `sub_agents_list` 与 `AgentOrchestrator` 内存注册表**双向同步**(打开时注入 childIds,保存时回写)。
Expand Down
20 changes: 8 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,21 +275,17 @@ code --install-extension mutsumi-[version].vsix

### Configuration

Mutsumi defaults to the `kimi-for-coding` model. To get started, simply add your API key in VS Code: settings.
Mutsumi defaults to the `kimi-for-coding` model on the built-in `kimi-coding` provider.

Open your `settings.json` and add:
1. Open the Command Palette and run **Mutsumi: Manage Model Providers**.
2. Select Kimi Coding (or another built-in provider) and enter its API key.
3. Run **Mutsumi: Select Model** to choose from providers that are authenticated by VS Code SecretStorage or a supported environment credential.

```json
"mutsumi.providers": [
{
"name": "kimi-for-coding",
"baseurl": "https://api.kimi.com/coding/v1",
"api_key": "sk-kimi-XXXXXXXXXXXXXXXXXXXXXX"
}
]
```
Keys are entered through a password input and stored in VS Code SecretStorage. They are never written to settings, `.mtm` files, model caches, or logs. The provider manager also supports non-secret custom OpenAI-compatible routes and `/models` discovery.

Mutsumi only accepts the current versioned `.mtm` format and current provider settings. Convert older files with the standalone migration project, then enter credentials again through **Mutsumi: Manage Model Providers**.

If you want to use a different model or provider, configure `mutsumi.providers` and `mutsumi.models` accordingly. See the setting descriptions in VS Code: for examples.
The built-in **+ Markdown** button adds a user-only annotation. Its Markdown source and position are saved in the `.mtm` file, but the annotation is never sent to the model or included in conversation compression and title generation.

> **Note:** This Agent framework is specifically designed and optimized around the Kimi base model family. Using `kimi-for-coding` is highly recommended.

Expand Down
20 changes: 8 additions & 12 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,21 +275,17 @@ code --install-extension mutsumi-【版本号】.vsix

### 配置

Mutsumi 默认使用 `kimi-for-coding` 模型。你只需在 VS Code 设置中填入 API Key 即可开始使用
Mutsumi 默认使用内置 `kimi-coding` 提供商的 `kimi-for-coding` 模型。

打开 `settings.json`,添加:
1. 打开命令面板,运行 **Mutsumi: 管理模型提供商**。
2. 选择 Kimi Coding(或其他内置提供商)并输入 API Key。
3. 运行 **Mutsumi: 选择模型**,从已由 VS Code SecretStorage 或受支持环境凭据完成鉴权的提供商中选择模型。

```json
"mutsumi.providers": [
{
"name": "kimi-for-coding",
"baseurl": "https://api.kimi.com/coding/v1",
"api_key": "sk-kimi-XXXXXXXXXXXXXXXXXXXXXX"
}
]
```
密钥通过密码输入框录入并存入 VS Code SecretStorage,绝不会写入设置、`.mtm` 文件、模型缓存或日志。提供商管理器还支持不含秘密的自定义 OpenAI-compatible 路由及 `/models` 自动发现。

Mutsumi 仅接受当前带版本标识的 `.mtm` 格式和当前提供商设置。旧文件请通过独立迁移项目转换,然后在 **Mutsumi: 管理模型提供商** 中重新录入凭据。

如需使用其他模型或服务商,可相应配置 `mutsumi.providers` 和 `mutsumi.models`,具体示例请参见 VS Code 设置中的说明
VS Code 内置的 **+ Markdown** 按钮会添加仅供用户查看的注释。Markdown 源文本及其位置会保存到 `.mtm` 文件,但不会发送给模型,也不会进入会话压缩或标题生成

> **注意:** 本 Agent 框架针对 Kimi 基模家族调性优化设计,强烈建议使用 `kimi-for-coding`。

Expand Down
8 changes: 4 additions & 4 deletions docs/AGENT_TYPES_DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,31 @@ If the file does not exist, Mutsumi loads built-in defaults from `src/config/typ
"agentTypes": {
"chat": {
"toolSets": ["read"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/chat.md"],
"defaultSkills": [],
"allowedChildTypes": [],
"isEntry": true
},
"implementer": {
"toolSets": ["read", "deliver", "dispatch"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/implementer.md"],
"defaultSkills": [],
"allowedChildTypes": ["implementer", "reviewer"],
"isEntry": true
},
"orchestrator": {
"toolSets": ["read", "deliver", "dispatch"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/orchestrator.md"],
"defaultSkills": [],
"allowedChildTypes": ["implementer", "reviewer"],
"isEntry": true
},
"reviewer": {
"toolSets": ["read"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/reviewer.md"],
"defaultSkills": [],
"allowedChildTypes": [],
Expand Down
8 changes: 4 additions & 4 deletions docs/AGENT_TYPES_DESIGN_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,31 @@ Agent Type 不实现通用继承。
"agentTypes": {
"chat": {
"toolSets": ["read"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/chat.md"],
"defaultSkills": [],
"allowedChildTypes": [],
"isEntry": true
},
"implementer": {
"toolSets": ["read", "deliver", "dispatch"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/implementer.md"],
"defaultSkills": [],
"allowedChildTypes": ["implementer", "reviewer"],
"isEntry": true
},
"orchestrator": {
"toolSets": ["read", "deliver", "dispatch"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/orchestrator.md"],
"defaultSkills": [],
"allowedChildTypes": ["implementer", "reviewer"],
"isEntry": true
},
"reviewer": {
"toolSets": ["read"],
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" },
"defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" },
"defaultRules": ["default/reviewer.md"],
"defaultSkills": [],
"allowedChildTypes": [],
Expand Down
2 changes: 1 addition & 1 deletion docs/HTTP_SERVER_SECURITY_DESIGN_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ HTTP Server 默认关闭;用户显式开启后,所有端点必须携带正
| 决策点 | 结论 |
|---|---|
| 认证头 | 标准 `Authorization: Bearer <password>`(scheme 匹配按 RFC 7235 大小写不敏感) |
| 密码存储 | 明文存于 VS Code 设置(与现有 `mutsumi.providers[].api_key` 明文策略一致),设置描述中注明 |
| 密码存储 | HTTP Server 密码仍按本设计存于 VS Code 设置;LLM API Key 已独立迁移到 VS Code SecretStorage,不再以此作为类比 |
| 密码比较 | 常量时间比较(`crypto.timingSafeEqual` 或等效手段),避免时序侧信道 |
| 空密码行为 | `enabled=true` 但密码为空 → **拒绝启动**,弹警告通知,提供"打开设置"与"生成随机密码"入口 |
| 浏览器/CSRF 防护 | 不实现。Bearer 头本身即非简单请求头,天然阻断浏览器预检外请求;无浏览器使用场景 |
Expand Down
10 changes: 6 additions & 4 deletions docs/custom-renderer-target-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export interface RenderData {
- L1 跨轮锁定: `commitRoundUI()` → 所有 active 内容移入 committed
- L2 轮内子段锁定:
- reasoning → locked 当 content 开始到达
- content → locked 当 tool_calls 开始到达
- content → locked 当原生 `toolCall` 内容块开始到达
- L3 工具级锁定: 每个工具执行完毕后 appendBlock 到 committed,前一个工具自然锁定

**公开接口:**
Expand Down Expand Up @@ -173,8 +173,8 @@ const rendererCtx = await esbuild.context({
## LiteAdapter 分析结论

LiteAdapter **不需要额外处理**。原因:
- `generateTitle()` 和 `compressConversation` `runner.run()` 返回的 `newMessages` 提取结果
- `newMessages` 中的 `content` 直接来自 LLM 流式累积 (`roundContent`),与 `replaceOutput`/`outputBuffer` 完全无关
- `generateTitle()` 和 `compressConversation` 只在 `runner.run()` 返回 `completed` 时从原生 `messages` 提取结果
- `messages` 中的 assistant 是 pi-ai 终态消息,与 `replaceOutput`/`outputBuffer` 完全无关
- `getCurrentOutput()` 仅被 `httpServer/chat.ts` 调用 (HeadlessAdapter),LiteAdapter 的 `outputBuffer` 无人外部读取

## SSE 改进 (Phase 2 方向,Phase 1 仅签名适配)
Expand All @@ -184,7 +184,9 @@ LiteAdapter **不需要额外处理**。原因:
```
{ event: 'block', data: RenderBlock JSON }
{ event: 'active', data: RenderData.active JSON }
{ event: 'done', data: { messageCount: N } }
{ type: 'done', messageCount: N }
{ type: 'error', code: '...', error: '...', messageCount: N }
{ type: 'cancelled', messageCount: N }
```
Phase 1 仅适配 `replaceOutput` 签名,SSE delta 逻辑暂不动。

Expand Down
28 changes: 28 additions & 0 deletions docs/mtm-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# `.mtm` format version 1

Mutsumi accepts one on-disk format. Every file has this top-level shape:

```json
{
"formatVersion": 1,
"metadata": {},
"context": [],
"notes": [{ "beforeUserIndex": 0, "markdown": "# Private note" }]
}
```

`context` contains messages with a strict semantic core:

- `user` requires a role and valid text/multimodal `content`;
- `assistant` requires a role, valid native content blocks, and `api`/`provider`/`model` identity;
- `toolResult` requires its tool-call ID/name, valid content blocks, and `isError`.

Provider envelope fields such as `usage`, cost, timestamps, stop reason, response metadata, errors, diagnostics, and signatures are preserved as opaque JSON. Missing or differently shaped envelope fields do not make the file invalid. Immediately before a provider request, Mutsumi creates a temporary pi-ai-compatible copy: invalid/missing usage becomes an all-zero value, timestamp becomes `0`, and stop reason is inferred as `toolUse` or `stop`. These defaults are never written back to disk.

`notes` is optional. Each entry stores the Markdown source of a user annotation. `beforeUserIndex` is the number of user cells before that note; array order preserves multiple notes in the same gap. Markup notes are restored in the Notebook but never enter Agent history, title generation, compression, ghost-block indexing, or a provider prompt.

System instructions are assembled dynamically and passed through `Context.systemPrompt`; they are never stored as messages. A user message may contain a `mutsumi.ghostBlock` extension. Assistant and tool-result messages may not contain Mutsumi extensions.

Consecutive user messages are valid pending turns and remain separate on disk and as Code cells. At the provider boundary only, adjacent users are merged with a blank-line separator; multimodal block order is preserved, and the last user's timestamp wins. Merging never crosses an assistant or tool result. A user message is still invalid while a preceding tool call is waiting for its result.

Files without `formatVersion: 1`, old OpenAI-shaped messages, malformed core message fields, and invalid tool-result ordering are rejected without being rewritten. Conversion belongs to the standalone migration project. If an open Notebook buffer contains malformed `mutsumi_interaction` metadata, Mutsumi ignores that entire interaction group and retains its Code cell as a pending user turn.
Loading