min-agent 0.2.0 → 0.3.0

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.
Files changed (81) hide show
  1. package/README.md +146 -18
  2. package/dist/agent.js +293 -408
  3. package/dist/assistant-stream.js +11 -7
  4. package/dist/cli.js +403 -140
  5. package/dist/clipboard.js +59 -23
  6. package/dist/code-mode.js +3 -3
  7. package/dist/compaction.js +182 -81
  8. package/dist/config.js +186 -35
  9. package/dist/confirm.js +55 -6
  10. package/dist/context-window.js +67 -54
  11. package/dist/doom-loop.js +19 -12
  12. package/dist/http.js +119 -0
  13. package/dist/instructions.js +51 -33
  14. package/dist/logger.js +66 -0
  15. package/dist/markdown.js +3 -44
  16. package/dist/mcp.js +547 -100
  17. package/dist/memory.js +48 -6
  18. package/dist/output.js +36 -27
  19. package/dist/paste-handler.js +3 -3
  20. package/dist/plugins.js +33 -6
  21. package/dist/pricing.js +119 -0
  22. package/dist/provider.js +17 -15
  23. package/dist/serve.js +658 -369
  24. package/dist/sessions.js +151 -13
  25. package/dist/skills.js +466 -76
  26. package/dist/synthetic.js +7 -0
  27. package/dist/title-gen.js +2 -1
  28. package/dist/tool-display.js +173 -0
  29. package/dist/tool-output.js +54 -45
  30. package/dist/tools/apply_patch.js +191 -0
  31. package/dist/tools/backend.js +61 -0
  32. package/dist/tools/bash.js +147 -70
  33. package/dist/tools/code_search.js +6 -5
  34. package/dist/tools/edit.js +23 -7
  35. package/dist/tools/explore.js +80 -12
  36. package/dist/tools/glob.js +3 -3
  37. package/dist/tools/grep.js +146 -14
  38. package/dist/tools/index.js +7 -7
  39. package/dist/tools/question.js +4 -22
  40. package/dist/tools/read.js +71 -11
  41. package/dist/tools/task.js +33 -20
  42. package/dist/tools/todo.js +83 -73
  43. package/dist/tools/web_fetch.js +150 -46
  44. package/dist/tools/web_search.js +706 -28
  45. package/dist/tools/write.js +13 -7
  46. package/dist/tui/App.js +40 -6
  47. package/dist/tui/ConfirmBar.js +24 -3
  48. package/dist/tui/InputBar.js +390 -45
  49. package/dist/tui/MessageList.js +533 -20
  50. package/dist/tui/ModelPicker.js +108 -0
  51. package/dist/tui/QuestionBar.js +104 -0
  52. package/dist/tui/StatusBar.js +19 -11
  53. package/dist/tui/agent-runner.js +103 -0
  54. package/dist/tui/caret-pos.js +134 -0
  55. package/dist/tui/caret.js +69 -0
  56. package/dist/tui/diff-view.js +61 -0
  57. package/dist/tui/drag-state.js +44 -0
  58. package/dist/tui/index.js +153 -24
  59. package/dist/tui/input-history.js +44 -0
  60. package/dist/tui/layout.js +17 -0
  61. package/dist/tui/mouse.js +46 -0
  62. package/dist/tui/selection.js +134 -0
  63. package/dist/tui/slash-commands.js +90 -0
  64. package/dist/tui/slash-handler.js +370 -0
  65. package/dist/tui/text-width.js +91 -0
  66. package/dist/tui/theme.js +12 -0
  67. package/dist/tui/undo-stack.js +14 -0
  68. package/dist/tui/use-sgr-mouse.js +27 -0
  69. package/dist/tui-chat.js +111 -331
  70. package/dist/updater.js +57 -0
  71. package/docs/API.md +160 -14
  72. package/docs/superpowers/plans/2026-08-16-batch1-tui-improvements.md +1510 -0
  73. package/docs/superpowers/plans/2026-08-16-batch2-cli-tools-api.md +2105 -0
  74. package/docs/superpowers/plans/2026-08-16-batch3-config-engineering.md +1595 -0
  75. package/docs/superpowers/plans/2026-08-16-input-caret.md +782 -0
  76. package/docs/superpowers/specs/2026-08-16-batch1-tui-improvements-design.md +183 -0
  77. package/docs/superpowers/specs/2026-08-16-batch2-cli-tools-api-design.md +220 -0
  78. package/docs/superpowers/specs/2026-08-16-batch3-config-engineering-design.md +196 -0
  79. package/docs/superpowers/specs/2026-08-16-input-caret-design.md +63 -0
  80. package/docs/superpowers/specs/2026-08-17-mouse-selection-design.md +116 -0
  81. package/package.json +7 -8
@@ -0,0 +1,116 @@
1
+ # 消息区鼠标拖拽选择与自动复制设计
2
+
3
+ 日期:2026-08-17
4
+ 状态:已批准(用户确认方案 A:应用内拖拽选择 + 自动复制)
5
+
6
+ ## 问题
7
+
8
+ min-agent TUI 启用了 SGR 鼠标跟踪(1000 模式),终端原生拖拽选择被鼠标协议接管,
9
+ 消息区(内容区)文本无法用鼠标选取、复制。参考 opencode / claude code 的交互:
10
+ 在消息区按住左键拖拽高亮文本,松开自动复制到系统剪贴板。
11
+
12
+ ## 目标
13
+
14
+ 1. 消息区按住左键拖拽 → 选区实时高亮(反显)
15
+ 2. 松开 → 自动复制到系统剪贴板(不占用 Ctrl+C,它仍用于退出)
16
+ 3. 选区保持高亮直到下次点击/按键,状态栏短暂提示"已复制"
17
+ 4. 原有功能不回归:单击展开工具行、滚轮滚动、输入框点击定位光标、Ctrl+C 退出
18
+
19
+ ## 设计
20
+
21
+ ### 1. 鼠标协议升级(`src/tui/mouse.ts`)
22
+
23
+ - `MOUSE_ENABLE` = `\x1b[?1000h\x1b[?1002h\x1b[?1006h`(1002 = 按住按钮时报告拖拽移动)
24
+ - `MOUSE_DISABLE` 同步加 `?1002l`
25
+ - 新增 `MOTION = 32` 常量:SGR 移动事件按钮码 = 基础按钮 + 32;修饰键(Shift=4 等)
26
+ 与基础按钮同在一个字段,`button & 15 === 0` 判断为无修饰键的纯左键
27
+
28
+ ### 2. 剪贴板写入(`src/clipboard.ts`)
29
+
30
+ 新增 `writeClipboard(text: string): boolean`,平台分发与现有读剪贴板一致:
31
+ - macOS:`pbcopy`(execSync input 管道,避免 shell 引号问题)
32
+ - Linux:`xclip -selection clipboard`,失败回退 `xsel --clipboard --input`
33
+ - Windows:PowerShell `Set-Clipboard -Value ([Console]::In.ReadToEnd())`
34
+
35
+ 失败静默返回 false,不弹错。
36
+
37
+ ### 3. 选区纯函数模块(`src/tui/selection.ts`,新)
38
+
39
+ 全部按 `charWidth` 处理 CJK 宽度,输入为 ANSI 行与 0-based 显示列:
40
+
41
+ - `stripAnsi(line)`:去掉 `\x1b[...m` 颜色码
42
+ - `applySelection(line, start, end)`:在选区边界注入 `\x1b[7m` / `\x1b[27m`(反显),
43
+ 保留原有样式;选区内遇到 `\x1b[0m`(RESET)时在其后重注入 `\x1b[7m`,保证跨样式
44
+ 重置时高亮不断裂。与选区有交叠的字符(含全角)整字符高亮,不动字符边界
45
+ - `extractText(line, start, end)`:按显示列切出选区纯文本(剥 ANSI)
46
+ - `selectionRanges(rows, anchor, current)`:把拖拽锚点/当前点(0-based 坐标:
47
+ 行 = `areaRows` 索引,列 = 行内显示列,由 MessageList 从终端坐标换算)归一为
48
+ 与 `rows` 对齐的逐行选区,流式语义:
49
+ - 同行:`[min(col), max(col))`
50
+ - 跨行(向下拖):首行 `[anchor.col, 行尾)`,中间行整行,末行 `[0, current.col)`
51
+ - 跨行(向上拖):对称反转
52
+ - `rows` 中 null(指示行/空白行)跳过;坐标夹在消息区范围内
53
+ - 返回 `(start,end | null)[]`,与 `rows` 对齐
54
+
55
+ ### 4. MessageList 集成(`src/tui/MessageList.tsx`)
56
+
57
+ **状态**:`selection: { anchor: Cell; cur: Cell } | null`(终端 1-based 坐标);
58
+ `pendingPress` ref 记录按下点,用于区分单击与拖拽——按下只记录,出现移动事件才
59
+ 激活选区,松开未移动才算点击(工具行展开,逻辑从"按下即触发"改为"松开且未移动")。
60
+
61
+ **行映射**:渲染时用与 MessageRow 相同的逻辑(`sliceLines`)构建 `areaRows:
62
+ (string | null)[]`,与终端行一一对应(1 行 = 1 项,指示行/用户消息空行 = null)。
63
+ 点击与选区换算共用该映射,选区随每次渲染实时重算(流式输出时选区跟随内容)。
64
+
65
+ **坐标换算**:行号(1-based)→ `areaRows` 索引(减 1);列 = 终端列 - 2(全部行有
66
+ `paddingLeft={1}`,第一字符在终端列 2),夹到行宽内。
67
+
68
+ **高亮渲染**:每个消息 part 把选区范围换算为"shown 行空间",以新 prop
69
+ `selection?: (CellRange | null)[]` 传入 `MessageRow`,按角色逐行注入反显
70
+ (用户消息首行的 "> "、工具行首行的 "⚡ name ▸ " 前缀单独处理,选区可跨前缀)。
71
+ memo 比较追加 `prev.selection === next.selection`;无选区时传 `undefined`,
72
+ 身份稳定,不影响流式渲染性能。
73
+
74
+ **松手复制**:提取各选中行文本(剥 ANSI、按列切片)以 `\n` 拼接 →
75
+ `writeClipboard` → 选区保持高亮,直到下次点击(按下即清)、按键或滚轮滚动时清除;
76
+ 复制成功且文本非空时调用 `onCopyNotice` 回调。
77
+
78
+ **事件过滤**:仅处理无修饰键(`button & 15 === 0`)且落在消息区(`row ≤ areaRows.length`)
79
+ 的事件;带修饰键(Shift)的拖拽不接管,留给支持原生 Shift 选择的终端。
80
+
81
+ ### 5. 复制反馈
82
+
83
+ - `TuiState` 增 `copyNotice?: string`;`TuiRenderer.showCopyNotice(text)` 设置并在
84
+ 2.5s 后自动清除
85
+ - App 增 `onCopyNotice` 回调 prop 传给 MessageList(实现为 TuiRenderer.showCopyNotice)
86
+ - StatusBar:把提示渲染在分隔线行的右端(占用分隔线自身宽度,不增加行数,布局不跳动)
87
+
88
+ ### 6. 文件改动
89
+
90
+ | 文件 | 改动 |
91
+ |---|---|
92
+ | `src/tui/mouse.ts` | 启用/禁用序列加 1002、`MOTION` 常量 |
93
+ | `src/tui/selection.ts`(新) | 选区纯函数:stripAnsi/applySelection/extractText/selectionRanges |
94
+ | `src/clipboard.ts` | `writeClipboard()` |
95
+ | `src/tui/MessageList.tsx` | selection state、press/drag/release 事件流、areaRows 映射、MessageRow 高亮渲染、onCopyNotice |
96
+ | `src/tui/types.ts` | `TuiState.copyNotice` |
97
+ | `src/tui/index.tsx` | `TuiRenderer.showCopyNotice()`、App 增 onCopyNotice prop |
98
+ | `src/tui/App.tsx` | 传 onCopyNotice 给 MessageList |
99
+ | `src/tui/StatusBar.tsx` | 分隔线行右端渲染"✓ 已复制"提示 |
100
+ | `src/tui-chat.ts` | `/help` 快捷键区加"鼠标拖拽 选择文本并自动复制" |
101
+
102
+ ### 7. 测试
103
+
104
+ - `tests/selection.test.ts`(新):stripAnsi / extractText(含 CJK 边界)/
105
+ applySelection(注入、RESET 重注入、空选区不变)/ selectionRanges(同行、
106
+ 向下、向上、null 行跳过、越界夹取)
107
+ - `tests/mouse.test.ts`:补拖拽移动事件解析(button 32)、启用序列含 `?1002h`
108
+ - 运行 `bun run typecheck`(仓库根)与 `bun test`(packages/min-agent)
109
+
110
+ ## 不做(YAGNI)
111
+
112
+ - 双击选词、三击选段
113
+ - 键盘选择模式(tmux 风格)
114
+ - 跨行选区自动去除 "> " / "⚡ name ▸ " 前缀(复制所见即所得)
115
+ - 复制保留 Markdown 格式/富文本
116
+ - 选区随流式输出"追字"(选区锚定终端坐标,内容变化时重算)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "min-agent",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Minimal AI coding agent with tool use, MCP, and skills support",
6
6
  "license": "MIT",
@@ -46,15 +46,14 @@
46
46
  "http-api"
47
47
  ],
48
48
  "dependencies": {
49
- "@ai-sdk/openai": "3.0.53",
50
- "@ai-sdk/provider": "3.0.8",
51
- "@modelcontextprotocol/sdk": "1.27.1",
52
- "ai": "6.0.168",
53
- "glob": "13.0.5",
49
+ "@ai-sdk/openai": "~3.0.53",
50
+ "@ai-sdk/provider": "~3.0.8",
51
+ "@modelcontextprotocol/sdk": "~1.27.1",
52
+ "ai": "~6.0.168",
53
+ "glob": "~13.0.5",
54
54
  "ink": "5",
55
55
  "ink-spinner": "5",
56
- "react": "18",
57
- "zod": "^3.25.76"
56
+ "react": "18"
58
57
  },
59
58
  "devDependencies": {
60
59
  "@types/node": "22.13.9",