min-agent 0.4.1 → 0.5.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.
- package/README.md +32 -2
- package/dist/agent.js +36 -22
- package/dist/cli/commands/chat.js +3 -0
- package/dist/cli/commands/exec.js +3 -0
- package/dist/cli/commands/index.js +22 -5
- package/dist/cli/commands/memory.js +33 -15
- package/dist/cli/commands/think.js +12 -0
- package/dist/cli/commands/write-config.js +22 -0
- package/dist/cli/option-helpers.js +13 -1
- package/dist/cli/program.js +50 -13
- package/dist/code-mode.js +1 -1
- package/dist/config.js +41 -0
- package/dist/context-window.js +8 -28
- package/dist/memory-cli.js +33 -0
- package/dist/memory.js +127 -46
- package/dist/model-catalog.js +285 -0
- package/dist/permission-cli.js +1 -4
- package/dist/provider.js +4 -1
- package/dist/reasoning-stream.js +158 -0
- package/dist/sandbox-cli.js +1 -4
- package/dist/scope.js +23 -0
- package/dist/serve/common.js +22 -1
- package/dist/serve/routes-chat.js +21 -1
- package/dist/serve/routes-memory.js +31 -2
- package/dist/serve/routes-meta.js +34 -6
- package/dist/think-cli.js +36 -0
- package/dist/thinking-wire.js +228 -0
- package/dist/thinking.js +142 -0
- package/dist/token-display.js +10 -7
- package/dist/tools/todo.js +22 -8
- package/dist/tui/App.js +36 -8
- package/dist/tui/InputBar.js +109 -36
- package/dist/tui/MessageList.js +53 -22
- package/dist/tui/StatusBar.js +7 -3
- package/dist/tui/ThinkPicker.js +77 -0
- package/dist/tui/bracketed-paste.js +37 -0
- package/dist/tui/caret-pos.js +10 -8
- package/dist/tui/index.js +7 -1
- package/dist/tui/layout.js +17 -0
- package/dist/tui/overlay-input.js +12 -0
- package/dist/tui/paste-draft.js +173 -0
- package/dist/tui/selection.js +8 -2
- package/dist/tui/slash-commands.js +18 -1
- package/dist/tui/slash-handler.js +61 -17
- package/dist/tui/text-width.js +6 -6
- package/dist/tui-chat.js +63 -7
- package/docs/API.md +50 -4
- package/docs/superpowers/plans/2026-08-23-input-paste-attachments.md +475 -0
- package/docs/superpowers/plans/2026-08-23-thinking-wire-profile.md +450 -0
- package/docs/superpowers/specs/2026-08-23-input-paste-attachments-design.md +174 -0
- package/docs/superpowers/specs/2026-08-23-thinking-wire-profile-design.md +140 -0
- package/package.json +1 -1
- package/skills/self-config/SKILL.md +5 -4
- package/skills/self-config/reference.md +10 -5
package/dist/tui-chat.js
CHANGED
|
@@ -9,7 +9,7 @@ import { loadImageParts } from "./agent.js";
|
|
|
9
9
|
import { createUndoStack, clearStack } from "./tui/undo-stack.js";
|
|
10
10
|
import { killActiveProcesses } from "./tools/bash.js";
|
|
11
11
|
import { setTuiConfirm, setTuiQuestion } from "./confirm.js";
|
|
12
|
-
import { loadConfig, getActiveProvider } from "./config.js";
|
|
12
|
+
import { loadConfig, getActiveProvider, getEffectiveConfig } from "./config.js";
|
|
13
13
|
import { scanProject, buildCodeSystemPrompt } from "./code-mode.js";
|
|
14
14
|
import { handleSlashCommand, sysMsg } from "./tui/slash-handler.js";
|
|
15
15
|
import { createAgentRunner } from "./tui/agent-runner.js";
|
|
@@ -17,6 +17,8 @@ import { listSessions, loadSession, saveSession } from "./sessions.js";
|
|
|
17
17
|
import { hydrateMessages, lastUserText } from "./tui/hydrate.js";
|
|
18
18
|
import { createPromptQueue } from "./tui/prompt-queue.js";
|
|
19
19
|
import { prepareSwitch, switchFailMessage, prepareNew, newFailMessage } from "./tui/session-switch.js";
|
|
20
|
+
import { getModelCatalog } from "./model-catalog.js";
|
|
21
|
+
import { setThinkingEffort, setThinkingOverride, thinkingChoicesForModel, thinkingEffortLabel } from "./thinking.js";
|
|
20
22
|
let confirmResolver = null;
|
|
21
23
|
let questionResolver = null;
|
|
22
24
|
/** Only one confirm/question overlay can be shown at a time; parallel tool calls queue up. */
|
|
@@ -26,6 +28,41 @@ function registerSessionCompletion() {
|
|
|
26
28
|
setSlashArgProvider("sessions", provider);
|
|
27
29
|
setSlashArgProvider("resume", provider);
|
|
28
30
|
}
|
|
31
|
+
function registerThinkCompletion() {
|
|
32
|
+
const provider = (tokens) => {
|
|
33
|
+
const flags = [
|
|
34
|
+
{ value: "--project", description: "写入当前项目" },
|
|
35
|
+
{ value: "--global", description: "写入全局配置" },
|
|
36
|
+
];
|
|
37
|
+
const used = new Set(tokens);
|
|
38
|
+
const remainingFlags = flags.filter((f) => !used.has(f.value));
|
|
39
|
+
if (tokens.length === 0) {
|
|
40
|
+
const model = getActiveProvider(getEffectiveConfig())?.defaultModel;
|
|
41
|
+
return [...thinkingChoicesForModel(model).map((value) => ({ value })), ...remainingFlags];
|
|
42
|
+
}
|
|
43
|
+
return remainingFlags;
|
|
44
|
+
};
|
|
45
|
+
setSlashArgProvider("think", provider);
|
|
46
|
+
setSlashArgProvider("thinking", provider);
|
|
47
|
+
}
|
|
48
|
+
function registerMemoryCompletion() {
|
|
49
|
+
setSlashArgProvider("memory", (tokens) => {
|
|
50
|
+
const flags = [
|
|
51
|
+
{ value: "--project", description: "写入当前项目" },
|
|
52
|
+
{ value: "--global", description: "写入全局配置" },
|
|
53
|
+
];
|
|
54
|
+
const used = new Set(tokens);
|
|
55
|
+
const remainingFlags = flags.filter((f) => !used.has(f.value));
|
|
56
|
+
if (tokens.length === 0) {
|
|
57
|
+
return [
|
|
58
|
+
{ value: "on", description: "开启记忆(跨会话保留)" },
|
|
59
|
+
{ value: "off", description: "关闭记忆(默认)" },
|
|
60
|
+
...remainingFlags,
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
return remainingFlags;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
29
66
|
function registerPermissionCompletion() {
|
|
30
67
|
setSlashArgProvider("permission", (tokens) => {
|
|
31
68
|
const flags = [
|
|
@@ -106,6 +143,8 @@ export async function runTui(opts) {
|
|
|
106
143
|
discoverSkills();
|
|
107
144
|
registerSkillCompletion();
|
|
108
145
|
registerPermissionCompletion();
|
|
146
|
+
registerThinkCompletion();
|
|
147
|
+
registerMemoryCompletion();
|
|
109
148
|
registerSandboxCompletion();
|
|
110
149
|
registerSessionCompletion();
|
|
111
150
|
const instructions = await loadInstructions();
|
|
@@ -116,6 +155,8 @@ export async function runTui(opts) {
|
|
|
116
155
|
let sessionId = resumeSessionId;
|
|
117
156
|
let currentModel = modelId ?? getActiveProvider(config)?.defaultModel;
|
|
118
157
|
const currentProvider = providerName;
|
|
158
|
+
if (currentModel)
|
|
159
|
+
void getModelCatalog(currentModel, getActiveProvider(config)?.baseURL);
|
|
119
160
|
const tracker = new TokenTracker();
|
|
120
161
|
const taskState = emptyTaskState();
|
|
121
162
|
let undoStack = createUndoStack();
|
|
@@ -131,11 +172,13 @@ export async function runTui(opts) {
|
|
|
131
172
|
}
|
|
132
173
|
let runner = null;
|
|
133
174
|
const tui = new TuiRenderer({
|
|
134
|
-
onSubmit: async (
|
|
135
|
-
|
|
175
|
+
onSubmit: async (prompt) => {
|
|
176
|
+
const text = prompt.display;
|
|
177
|
+
if (text.trim().startsWith("/")) {
|
|
136
178
|
const result = await handleSlashCommand(text, tui, messages, currentModel, tracker, (model) => {
|
|
137
179
|
currentModel = model;
|
|
138
180
|
tui.setModel(model);
|
|
181
|
+
void refreshTokenBar();
|
|
139
182
|
}, requestExit, {
|
|
140
183
|
undoStack,
|
|
141
184
|
setUndoStack: (s) => {
|
|
@@ -171,12 +214,15 @@ export async function runTui(opts) {
|
|
|
171
214
|
}
|
|
172
215
|
lastUserMessage = text;
|
|
173
216
|
tui.addMessage({ id: `user-${Date.now()}`, role: "user", content: text, timestamp: Date.now() });
|
|
174
|
-
messages.push({ role: "user", content:
|
|
217
|
+
messages.push({ role: "user", content: prompt.content });
|
|
175
218
|
if (runner) {
|
|
176
219
|
await runner.run();
|
|
177
220
|
persistSession();
|
|
178
221
|
}
|
|
179
222
|
},
|
|
223
|
+
onNotice: (notice) => {
|
|
224
|
+
sysMsg(tui, notice);
|
|
225
|
+
},
|
|
180
226
|
onConfirm: (accepted) => {
|
|
181
227
|
tui.hideConfirm();
|
|
182
228
|
if (confirmResolver) {
|
|
@@ -201,11 +247,21 @@ export async function runTui(opts) {
|
|
|
201
247
|
}
|
|
202
248
|
currentModel = model;
|
|
203
249
|
tui.setModel(model);
|
|
250
|
+
void refreshTokenBar();
|
|
204
251
|
sysMsg(tui, `✓ 默认模型已设为: ${model}`);
|
|
205
252
|
},
|
|
206
253
|
onModelCancel: () => {
|
|
207
254
|
tui.hideModelPicker();
|
|
208
255
|
},
|
|
256
|
+
onThinkPick: (effort, scope) => {
|
|
257
|
+
setThinkingEffort(effort, scope);
|
|
258
|
+
setThinkingOverride(effort);
|
|
259
|
+
tui.hideThinkPicker();
|
|
260
|
+
sysMsg(tui, `✓ 思考强度已设为 ${thinkingEffortLabel(effort)}(${scope === "project" ? "项目" : "全局"})`);
|
|
261
|
+
},
|
|
262
|
+
onThinkCancel: () => {
|
|
263
|
+
tui.hideThinkPicker();
|
|
264
|
+
},
|
|
209
265
|
onSessionPick: (id) => {
|
|
210
266
|
tui.hideSessionPicker();
|
|
211
267
|
applySession(id);
|
|
@@ -299,7 +355,8 @@ export async function runTui(opts) {
|
|
|
299
355
|
tracker.reset();
|
|
300
356
|
lastUserMessage = null;
|
|
301
357
|
tui.setSessionId(undefined);
|
|
302
|
-
tui.update({ messages: []
|
|
358
|
+
tui.update({ messages: [] });
|
|
359
|
+
void refreshTokenBar();
|
|
303
360
|
sysMsg(tui, "✓ 已新建会话");
|
|
304
361
|
}
|
|
305
362
|
function openSessionPicker() {
|
|
@@ -347,8 +404,7 @@ export async function runTui(opts) {
|
|
|
347
404
|
tui.start();
|
|
348
405
|
if (messages.length > 0)
|
|
349
406
|
tui.update({ messages: hydrateMessages(messages) });
|
|
350
|
-
|
|
351
|
-
await refreshTokenBar();
|
|
407
|
+
await refreshTokenBar();
|
|
352
408
|
const prompt = initialPrompt?.trim() ?? "";
|
|
353
409
|
const notify = (kind, imgPath) => {
|
|
354
410
|
if (kind === "not_found")
|
package/docs/API.md
CHANGED
|
@@ -42,14 +42,18 @@ min-agent serve --host 0.0.0.0 --port 3000
|
|
|
42
42
|
| POST | `/v1/chat/redo` | 重发会话最后一条用户消息 |
|
|
43
43
|
| GET | `/v1/sessions` | 列出会话 |
|
|
44
44
|
| DELETE | `/v1/sessions/:id` | 删除会话 |
|
|
45
|
-
| GET | `/v1/memory` |
|
|
45
|
+
| GET | `/v1/memory` | 列出记忆(含开关状态与 `project_memories`) |
|
|
46
46
|
| POST | `/v1/memory` | 添加记忆 |
|
|
47
47
|
| GET | `/v1/memory/search?q=xxx` | 搜索记忆 |
|
|
48
48
|
| DELETE | `/v1/memory/:index` | 删除记忆 |
|
|
49
|
+
| GET | `/v1/memory/mode` | 当前记忆开关 |
|
|
50
|
+
| POST | `/v1/memory/mode` | 设置记忆开关 |
|
|
49
51
|
| GET | `/v1/budget` | 当前预算上限 |
|
|
50
52
|
| POST | `/v1/budget` | 设置预算上限 |
|
|
51
53
|
| GET | `/v1/permission` | 当前确认模式 |
|
|
52
54
|
| POST | `/v1/permission` | 设置确认模式 |
|
|
55
|
+
| GET | `/v1/thinking` | 当前思考强度 |
|
|
56
|
+
| POST | `/v1/thinking` | 设置思考强度 |
|
|
53
57
|
| GET | `/v1/sandbox` | 当前隔离策略 |
|
|
54
58
|
| POST | `/v1/sandbox` | 设置隔离策略 |
|
|
55
59
|
| GET | `/v1/diff` | 工作区未提交变更 |
|
|
@@ -86,7 +90,7 @@ min-agent serve --host 0.0.0.0 --port 3000
|
|
|
86
90
|
## `GET /v1/meta`
|
|
87
91
|
|
|
88
92
|
```json
|
|
89
|
-
{ "version": "0.1.0", "cwd": "/path/to/project", "instructions_chars": 1234, "sandbox": { "mode": "off", "network": "allow", "extraWriteRoots": [], "extraReadRoots": [], "source": null, "label": "未隔离,允许联网" }, "permission": { "permission": "ask", "source": null, "label": "询问确认" } }
|
|
93
|
+
{ "version": "0.1.0", "cwd": "/path/to/project", "instructions_chars": 1234, "sandbox": { "mode": "off", "network": "allow", "extraWriteRoots": [], "extraReadRoots": [], "source": null, "label": "未隔离,允许联网" }, "permission": { "permission": "ask", "source": null, "label": "询问确认" }, "thinking": { "thinking": "medium", "source": null, "label": "medium" }, "memory": { "memory": "off", "source": null, "label": "off" } }
|
|
90
94
|
```
|
|
91
95
|
|
|
92
96
|
## `GET /v1/update`
|
|
@@ -157,10 +161,12 @@ CLI 升级请使用 `min-agent update`(执行 `npm install -g min-agent`)。
|
|
|
157
161
|
| `auto_approve` | boolean | 默认 `true`。设为 `false` 时必须 `stream: true`,并通过 `POST /v1/approvals` / `POST /v1/answers` 回调 |
|
|
158
162
|
| `sandbox` | string | 本轮隔离:`off` / `workspace` / `strict`。只能比服务当前策略更严,不能放宽 |
|
|
159
163
|
| `network` | string | 本轮联网:`allow` / `deny`。`deny` 只能收紧 |
|
|
164
|
+
| `thinking` | string | 本轮思考强度:`off` / `low` / `medium` / `high` / `max`。不传则用配置,未配置时为 `medium` |
|
|
165
|
+
| `memory` | string | 本轮是否使用记忆:`on` / `off`。不传则用配置,未配置时为 `off` |
|
|
160
166
|
|
|
161
167
|
`auto_approve: false` 且未开流式时返回 `400 auto_approve_requires_stream`。确认/提问最多等待 5 分钟,超时视为拒绝或跳过。客户端断开连接时未完成的确认视为拒绝。
|
|
162
168
|
|
|
163
|
-
`max_steps_reached` 为 `true` 表示本轮已用尽自动续跑次数(上下文压缩/空回复等),或显式设置了 `agent.maxSteps` 且已到达该上限。默认不按固定步数切断一轮生成。`incomplete` 为 `true` 表示模型在调用工具后没有给出完整回复,或连续多次空回复。`stopped` 为 `true` 表示因同一操作反复执行而主动结束本轮。`empty_response` 为 `true` 表示 provider 连续返回空流(HTTP 200 但没有任何内容,多为上游超时/限流),`empty_attempts` 为已尝试次数;这类空回复会以原请求重发重试(首次立即,之后指数退避),可用 `agent.maxEmptyAttempts`(默认 4)与 `agent.emptyRetryDelayMs`(默认 1000)调整。发送下一条消息即可继续。`continues` 为本轮实际自动续跑次数。`task_state`
|
|
169
|
+
`max_steps_reached` 为 `true` 表示本轮已用尽自动续跑次数(上下文压缩/空回复等),或显式设置了 `agent.maxSteps` 且已到达该上限。默认不按固定步数切断一轮生成。`incomplete` 为 `true` 表示模型在调用工具后没有给出完整回复,或连续多次空回复。`stopped` 为 `true` 表示因同一操作反复执行而主动结束本轮。`empty_response` 为 `true` 表示 provider 连续返回空流(HTTP 200 但没有任何内容,多为上游超时/限流),`empty_attempts` 为已尝试次数;这类空回复会以原请求重发重试(首次立即,之后指数退避),可用 `agent.maxEmptyAttempts`(默认 4)与 `agent.emptyRetryDelayMs`(默认 1000)调整。发送下一条消息即可继续。`continues` 为本轮实际自动续跑次数。`task_state` 为当前任务目标与待办列表,会写入会话并在压缩后保留;纯问候不会记为任务目标。网页检索连续过久、或检索后尚未写出用户要求的结果时,代理会改为基于已有资料产出结果;本轮内再调用搜索/抓取会收到停止检索并直接产出的提示,而不是新的检索结果(即使 `autoContinue` 为 `false`)。
|
|
164
170
|
|
|
165
171
|
### 非流式响应
|
|
166
172
|
|
|
@@ -331,6 +337,25 @@ CLI 升级请使用 `min-agent update`(执行 `npm install -g min-agent`)。
|
|
|
331
337
|
|
|
332
338
|
`scope` 省略时写入全局。`permission` 必须为 `ask` / `accept-edits` / `allow-all`。
|
|
333
339
|
|
|
340
|
+
## `GET /v1/thinking`
|
|
341
|
+
|
|
342
|
+
```json
|
|
343
|
+
{ "thinking": "max", "source": "global", "label": "max" }
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
`thinking` 为 `off` / `low` / `medium` / `high` / `max`。未配置时为 `medium`,`source` 为 `null`。已配置时 `source` 为 `cli`、`project` 或 `global`。
|
|
347
|
+
|
|
348
|
+
## `POST /v1/thinking`
|
|
349
|
+
|
|
350
|
+
```json
|
|
351
|
+
{ "thinking": "max", "scope": "project" }
|
|
352
|
+
```
|
|
353
|
+
```json
|
|
354
|
+
{ "ok": true, "scope": "project", "thinking": "max", "source": "project", "label": "max" }
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
`scope` 省略时写入全局,并清除项目配置里的 `thinking` 覆盖,避免旧的项目值(例如 `off`)在重启后继续生效。`thinking` 必须为 `off` / `low` / `medium` / `high` / `max`(`none` → `off`,`xhigh` / `extra-high` → `max`)。
|
|
358
|
+
|
|
334
359
|
## `GET /v1/sandbox`
|
|
335
360
|
|
|
336
361
|
```json
|
|
@@ -488,12 +513,33 @@ CLI 升级请使用 `min-agent update`(执行 `npm install -g min-agent`)。
|
|
|
488
513
|
|
|
489
514
|
```json
|
|
490
515
|
{
|
|
516
|
+
"memory": "off",
|
|
517
|
+
"source": null,
|
|
518
|
+
"label": "off",
|
|
491
519
|
"memories": [{ "content": "...", "tags": [...], "created": "..." }],
|
|
492
520
|
"project_memories": [{ "content": "...", "tags": [...], "created": "..." }]
|
|
493
521
|
}
|
|
494
522
|
```
|
|
495
523
|
|
|
496
|
-
`memories` 始终为全局;`project_memories` 为当前目录 `.min-agent/memory.json
|
|
524
|
+
`memories` 始终为全局;`project_memories` 为当前目录 `.min-agent/memory.json`。`memory` 为 `on` / `off`。未配置时为 `off`,`source` 为 `null`。已配置时 `source` 为 `cli`、`project` 或 `global`。关闭时仍可读写条目,但对话不会注入记忆,也不会暴露 memory 工具。
|
|
525
|
+
|
|
526
|
+
## `GET /v1/memory/mode`
|
|
527
|
+
|
|
528
|
+
```json
|
|
529
|
+
{ "memory": "off", "source": null, "label": "off" }
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
## `POST /v1/memory/mode`
|
|
533
|
+
|
|
534
|
+
```json
|
|
535
|
+
{ "memory": "on", "scope": "project" }
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
```json
|
|
539
|
+
{ "ok": true, "scope": "project", "memory": "on", "source": "project", "label": "on" }
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
`scope` 省略时写入全局,并清除项目配置里的 `memory` 覆盖。`memory` 必须为 `on` / `off`(`true` / `enable` → `on`,`false` / `disable` → `off`)。
|
|
497
543
|
|
|
498
544
|
## `POST /v1/memory`
|
|
499
545
|
|