min-agent 0.5.0 → 0.6.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 (156) hide show
  1. package/README.md +32 -18
  2. package/dist/cli.js +538 -12
  3. package/docs/API.md +25 -8
  4. package/package.json +6 -6
  5. package/skills/self-config/SKILL.md +7 -3
  6. package/skills/self-config/reference.md +8 -4
  7. package/dist/agent.js +0 -1342
  8. package/dist/assistant-stream.js +0 -131
  9. package/dist/cli/commands/chat.js +0 -13
  10. package/dist/cli/commands/exec.js +0 -35
  11. package/dist/cli/commands/history.js +0 -58
  12. package/dist/cli/commands/index.js +0 -241
  13. package/dist/cli/commands/init.js +0 -18
  14. package/dist/cli/commands/mcp.js +0 -173
  15. package/dist/cli/commands/memory.js +0 -87
  16. package/dist/cli/commands/models.js +0 -21
  17. package/dist/cli/commands/permission.js +0 -12
  18. package/dist/cli/commands/rules.js +0 -33
  19. package/dist/cli/commands/sandbox.js +0 -13
  20. package/dist/cli/commands/serve.js +0 -9
  21. package/dist/cli/commands/setup.js +0 -4
  22. package/dist/cli/commands/shared.js +0 -16
  23. package/dist/cli/commands/skills.js +0 -119
  24. package/dist/cli/commands/think.js +0 -12
  25. package/dist/cli/commands/update.js +0 -7
  26. package/dist/cli/commands/write-config.js +0 -52
  27. package/dist/cli/errors.js +0 -36
  28. package/dist/cli/exec-prompt.js +0 -26
  29. package/dist/cli/option-helpers.js +0 -65
  30. package/dist/cli/program.js +0 -217
  31. package/dist/clipboard.js +0 -142
  32. package/dist/code-mode.js +0 -184
  33. package/dist/compaction.js +0 -644
  34. package/dist/config.js +0 -470
  35. package/dist/confirm.js +0 -172
  36. package/dist/context-window.js +0 -246
  37. package/dist/doom-loop.js +0 -278
  38. package/dist/fetch-timeout.js +0 -152
  39. package/dist/http-approvals.js +0 -60
  40. package/dist/http.js +0 -119
  41. package/dist/instructions.js +0 -196
  42. package/dist/logger.js +0 -95
  43. package/dist/markdown.js +0 -259
  44. package/dist/mcp.js +0 -1036
  45. package/dist/memory-cli.js +0 -33
  46. package/dist/memory.js +0 -295
  47. package/dist/model-catalog.js +0 -285
  48. package/dist/output.js +0 -76
  49. package/dist/paste-handler.js +0 -41
  50. package/dist/permission-cli.js +0 -40
  51. package/dist/plugins.js +0 -131
  52. package/dist/pricing.js +0 -119
  53. package/dist/provider.js +0 -63
  54. package/dist/question-format.js +0 -60
  55. package/dist/reasoning-stream.js +0 -158
  56. package/dist/sandbox-cli.js +0 -79
  57. package/dist/sandbox.js +0 -403
  58. package/dist/save-throttle.js +0 -45
  59. package/dist/scope.js +0 -23
  60. package/dist/serve/common.js +0 -425
  61. package/dist/serve/routes-chat.js +0 -367
  62. package/dist/serve/routes-mcp.js +0 -212
  63. package/dist/serve/routes-memory.js +0 -95
  64. package/dist/serve/routes-meta.js +0 -233
  65. package/dist/serve/routes-sessions.js +0 -61
  66. package/dist/serve/routes-skills.js +0 -70
  67. package/dist/serve.js +0 -138
  68. package/dist/sessions.js +0 -265
  69. package/dist/skills.js +0 -599
  70. package/dist/structured-output.js +0 -29
  71. package/dist/synthetic.js +0 -7
  72. package/dist/think-cli.js +0 -36
  73. package/dist/thinking-wire.js +0 -228
  74. package/dist/thinking.js +0 -142
  75. package/dist/title-gen.js +0 -55
  76. package/dist/token-display.js +0 -39
  77. package/dist/tool-display.js +0 -178
  78. package/dist/tool-output.js +0 -126
  79. package/dist/tools/apply_patch.js +0 -265
  80. package/dist/tools/atomic-file.js +0 -35
  81. package/dist/tools/backend.js +0 -61
  82. package/dist/tools/bash.js +0 -231
  83. package/dist/tools/code_search.js +0 -98
  84. package/dist/tools/edit.js +0 -68
  85. package/dist/tools/explore.js +0 -232
  86. package/dist/tools/glob.js +0 -40
  87. package/dist/tools/grep.js +0 -174
  88. package/dist/tools/index.js +0 -34
  89. package/dist/tools/question.js +0 -54
  90. package/dist/tools/read.js +0 -109
  91. package/dist/tools/search-searxng.js +0 -223
  92. package/dist/tools/search-serper.js +0 -189
  93. package/dist/tools/task.js +0 -165
  94. package/dist/tools/todo.js +0 -213
  95. package/dist/tools/web_fetch.js +0 -195
  96. package/dist/tools/web_search.js +0 -228
  97. package/dist/tools/write.js +0 -55
  98. package/dist/tui/App.js +0 -126
  99. package/dist/tui/ConfirmBar.js +0 -66
  100. package/dist/tui/InputBar.js +0 -616
  101. package/dist/tui/MessageList.js +0 -718
  102. package/dist/tui/ModelPicker.js +0 -113
  103. package/dist/tui/QuestionBar.js +0 -136
  104. package/dist/tui/SessionPicker.js +0 -79
  105. package/dist/tui/Spinner.js +0 -6
  106. package/dist/tui/StatusBar.js +0 -22
  107. package/dist/tui/ThinkPicker.js +0 -77
  108. package/dist/tui/agent-runner.js +0 -223
  109. package/dist/tui/bracketed-paste.js +0 -37
  110. package/dist/tui/caret-pos.js +0 -179
  111. package/dist/tui/caret.js +0 -69
  112. package/dist/tui/click-count.js +0 -13
  113. package/dist/tui/diff-view.js +0 -61
  114. package/dist/tui/drag-state.js +0 -49
  115. package/dist/tui/hydrate.js +0 -129
  116. package/dist/tui/index.js +0 -258
  117. package/dist/tui/input-history.js +0 -125
  118. package/dist/tui/layout.js +0 -105
  119. package/dist/tui/mouse.js +0 -46
  120. package/dist/tui/overlay-input.js +0 -12
  121. package/dist/tui/paste-draft.js +0 -173
  122. package/dist/tui/prompt-queue.js +0 -24
  123. package/dist/tui/selection.js +0 -232
  124. package/dist/tui/session-switch.js +0 -28
  125. package/dist/tui/slash-commands.js +0 -123
  126. package/dist/tui/slash-handler.js +0 -589
  127. package/dist/tui/text-width.js +0 -113
  128. package/dist/tui/theme.js +0 -12
  129. package/dist/tui/token-info.js +0 -7
  130. package/dist/tui/tool-children.js +0 -19
  131. package/dist/tui/types.js +0 -1
  132. package/dist/tui/undo-stack.js +0 -14
  133. package/dist/tui/use-sgr-mouse.js +0 -29
  134. package/dist/tui-chat.js +0 -456
  135. package/dist/updater.js +0 -116
  136. package/dist/xml-search.js +0 -194
  137. package/docs/superpowers/plans/2026-08-16-batch1-tui-improvements.md +0 -1510
  138. package/docs/superpowers/plans/2026-08-16-batch2-cli-tools-api.md +0 -2105
  139. package/docs/superpowers/plans/2026-08-16-batch3-config-engineering.md +0 -1595
  140. package/docs/superpowers/plans/2026-08-16-input-caret.md +0 -782
  141. package/docs/superpowers/plans/2026-08-20-tui-completeness.md +0 -873
  142. package/docs/superpowers/plans/2026-08-20-unified-tui-default.md +0 -631
  143. package/docs/superpowers/plans/2026-08-23-input-paste-attachments.md +0 -475
  144. package/docs/superpowers/plans/2026-08-23-thinking-wire-profile.md +0 -450
  145. package/docs/superpowers/specs/2026-08-16-batch1-tui-improvements-design.md +0 -183
  146. package/docs/superpowers/specs/2026-08-16-batch2-cli-tools-api-design.md +0 -220
  147. package/docs/superpowers/specs/2026-08-16-batch3-config-engineering-design.md +0 -196
  148. package/docs/superpowers/specs/2026-08-16-input-caret-design.md +0 -63
  149. package/docs/superpowers/specs/2026-08-17-mouse-selection-design.md +0 -116
  150. package/docs/superpowers/specs/2026-08-20-config-http-alignment-design.md +0 -47
  151. package/docs/superpowers/specs/2026-08-20-mcp-plugins-alignment-design.md +0 -37
  152. package/docs/superpowers/specs/2026-08-20-sandbox-permissions-design.md +0 -68
  153. package/docs/superpowers/specs/2026-08-20-tui-completeness-design.md +0 -273
  154. package/docs/superpowers/specs/2026-08-20-unified-tui-default-design.md +0 -165
  155. package/docs/superpowers/specs/2026-08-23-input-paste-attachments-design.md +0 -174
  156. package/docs/superpowers/specs/2026-08-23-thinking-wire-profile-design.md +0 -140
package/dist/updater.js DELETED
@@ -1,116 +0,0 @@
1
- import { readFileSync } from "fs";
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
- import { spawnSync } from "child_process";
5
- export const UPDATE_PACKAGE = "min-agent";
6
- export const NPM_LATEST_URL = `https://registry.npmjs.org/${UPDATE_PACKAGE}/latest`;
7
- export const UPDATE_NPM_BIN = "npm";
8
- export const UPDATE_NPM_ARGS = ["install", "-g", UPDATE_PACKAGE];
9
- const VERSION_RE = /^\d+\.\d+\.\d+/;
10
- const FETCH_TIMEOUT_MS = 10_000;
11
- export function updateInstallCommand() {
12
- return [UPDATE_NPM_BIN, ...UPDATE_NPM_ARGS].join(" ");
13
- }
14
- export function localVersion() {
15
- try {
16
- const pkgPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../package.json");
17
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
18
- return typeof pkg.version === "string" && pkg.version.length > 0 ? pkg.version : "0.0.0";
19
- }
20
- catch {
21
- return "0.0.0";
22
- }
23
- }
24
- export function compareVersions(a, b) {
25
- const pa = a.split("-")[0].split(".").map(Number);
26
- const pb = b.split("-")[0].split(".").map(Number);
27
- for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
28
- const va = pa[i] ?? 0;
29
- const vb = pb[i] ?? 0;
30
- const na = Number.isFinite(va) ? va : 0;
31
- const nb = Number.isFinite(vb) ? vb : 0;
32
- if (na !== nb)
33
- return na - nb;
34
- }
35
- return 0;
36
- }
37
- function parseVersion(value) {
38
- if (typeof value !== "string" || !VERSION_RE.test(value))
39
- return null;
40
- return value;
41
- }
42
- export async function fetchLatestVersion(fetchFn = fetch) {
43
- let response;
44
- try {
45
- response = await fetchFn(NPM_LATEST_URL, {
46
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
47
- headers: { Accept: "application/json" },
48
- });
49
- }
50
- catch {
51
- return null;
52
- }
53
- if (!response.ok)
54
- return null;
55
- let data;
56
- try {
57
- data = await response.json();
58
- }
59
- catch {
60
- return null;
61
- }
62
- if (!data || typeof data !== "object" || !("version" in data))
63
- return null;
64
- return parseVersion(data.version);
65
- }
66
- export async function checkForUpdate(opts) {
67
- const current = opts?.currentVersion ?? localVersion();
68
- const latest = await fetchLatestVersion(opts?.fetchFn);
69
- return {
70
- current,
71
- latest,
72
- updateAvailable: latest !== null && compareVersions(current, latest) < 0,
73
- };
74
- }
75
- export function installLatest() {
76
- const result = spawnSync(UPDATE_NPM_BIN, [...UPDATE_NPM_ARGS], {
77
- stdio: "inherit",
78
- shell: process.platform === "win32",
79
- env: process.env,
80
- });
81
- if (result.error) {
82
- const code = result.error.code;
83
- return { ok: false, missing: code === "ENOENT" };
84
- }
85
- return { ok: result.status === 0 };
86
- }
87
- export async function runUpdate(io = {}) {
88
- const log = io.log ?? ((msg) => console.log(msg));
89
- const error = io.error ?? ((msg) => console.error(msg));
90
- const current = io.currentVersion?.() ?? localVersion();
91
- const cmd = updateInstallCommand();
92
- log(`当前版本: ${current}`);
93
- const latest = io.fetchLatest ? await io.fetchLatest() : await fetchLatestVersion();
94
- if (!latest) {
95
- error(`无法检查新版本(网络不可用)。请稍后重试,或手动执行: ${cmd}`);
96
- return { status: "check-failed", current, latest: null };
97
- }
98
- if (compareVersions(current, latest) >= 0) {
99
- log(`已是最新版本 (${latest})`);
100
- return { status: "up-to-date", current, latest };
101
- }
102
- log(`发现新版本: ${latest}`);
103
- log(`正在执行 ${cmd} ...`);
104
- const installed = (io.install ?? installLatest)();
105
- if (!installed.ok) {
106
- if (installed.missing) {
107
- error(`未找到 npm。请先安装 Node.js,然后执行: ${cmd}`);
108
- }
109
- else {
110
- error(`自动升级失败。请手动执行: ${cmd}`);
111
- }
112
- return { status: "install-failed", current, latest };
113
- }
114
- log(`✓ 已升级到 ${latest}`);
115
- return { status: "updated", current, latest };
116
- }
@@ -1,194 +0,0 @@
1
- /**
2
- * Some OpenAI-compatible gateways (and a few models) dump built-in web search
3
- * into the assistant text as <web_search>…</web_search> instead of a tool call,
4
- * then stop. This module splits those blocks out of the stream so the agent can
5
- * turn them into search_web tool results and keep going.
6
- */
7
- const OPEN_NAME = "<web_search";
8
- const CLOSE_NAME = "</web_search";
9
- const PARTIAL_TAG_HOLD = 80;
10
- const UNCLOSED_MAX = 64 * 1024;
11
- function collapse(s) {
12
- return s.replace(/\s+/g, " ").trim();
13
- }
14
- function isNameBoundary(ch) {
15
- return ch === undefined || ch === ">" || ch === "/" || ch === " " || ch === "\t" || ch === "\n" || ch === "\r";
16
- }
17
- function findOpen(buf) {
18
- const l = buf.toLowerCase();
19
- let from = 0;
20
- while (from < l.length) {
21
- const index = l.indexOf(OPEN_NAME, from);
22
- if (index < 0)
23
- return null;
24
- if (!isNameBoundary(l[index + OPEN_NAME.length])) {
25
- from = index + 1;
26
- continue;
27
- }
28
- const gt = buf.indexOf(">", index);
29
- if (gt < 0)
30
- return null;
31
- return { index, openLen: gt - index + 1, raw: buf.slice(index, gt + 1) };
32
- }
33
- return null;
34
- }
35
- function findClose(buf, from) {
36
- const l = buf.toLowerCase();
37
- let start = from;
38
- while (start < l.length) {
39
- const index = l.indexOf(CLOSE_NAME, start);
40
- if (index < 0)
41
- return null;
42
- if (!isNameBoundary(l[index + CLOSE_NAME.length])) {
43
- start = index + 1;
44
- continue;
45
- }
46
- const gt = buf.indexOf(">", index);
47
- if (gt < 0)
48
- return null;
49
- return { innerEnd: index, tagEnd: gt + 1 };
50
- }
51
- return null;
52
- }
53
- function queryFromOpenTag(raw) {
54
- const m = /\bquery\s*=\s*"([^"]*)"/i.exec(raw) ?? /\bquery\s*=\s*'([^']*)'/i.exec(raw);
55
- return m?.[1]?.trim() ?? "";
56
- }
57
- const RESULTS_HEADER = /^Search results for\s+"([^"]*)"\s*:/im;
58
- export function classifyXmlSearchBody(inner, attrQuery = "") {
59
- const trimmed = inner.trim();
60
- if (!trimmed) {
61
- const query = attrQuery.trim();
62
- return query ? { kind: "invoke", query } : { kind: "results", query: "", body: "" };
63
- }
64
- const header = RESULTS_HEADER.exec(trimmed);
65
- if (header) {
66
- return { kind: "results", query: header[1].trim() || attrQuery, body: trimmed };
67
- }
68
- if (/^\d+\.\s+Title\s*:/m.test(trimmed) && /\bURL\s*:/m.test(trimmed)) {
69
- return { kind: "results", query: attrQuery, body: trimmed };
70
- }
71
- const query = collapse(trimmed) || attrQuery;
72
- if (query && query.length <= 500 && !/\bURL\s*:\s*https?:\/\//i.test(trimmed)) {
73
- return { kind: "invoke", query };
74
- }
75
- return { kind: "results", query: attrQuery || query, body: trimmed };
76
- }
77
- function lastPotentialPartialOpen(buf) {
78
- const start = Math.max(0, buf.length - PARTIAL_TAG_HOLD);
79
- const tail = buf.slice(start);
80
- const lt = tail.lastIndexOf("<");
81
- if (lt < 0)
82
- return -1;
83
- const globalLt = start + lt;
84
- const cand = buf.slice(globalLt).toLowerCase();
85
- if (cand.length > 72)
86
- return -1;
87
- if (OPEN_NAME.startsWith(cand) || CLOSE_NAME.startsWith(cand))
88
- return globalLt;
89
- if (cand.startsWith(OPEN_NAME) && !cand.includes(">"))
90
- return globalLt;
91
- if (cand.startsWith(CLOSE_NAME) && !cand.includes(">"))
92
- return globalLt;
93
- return -1;
94
- }
95
- export class XmlSearchSplitter {
96
- buf = "";
97
- feed(chunk) {
98
- this.buf += chunk;
99
- return this.drain(false);
100
- }
101
- flush() {
102
- return this.drain(true);
103
- }
104
- drain(isFinal) {
105
- const out = [];
106
- let hadBlock = false;
107
- const pushDisplay = (text) => {
108
- if (!text)
109
- return;
110
- const last = out[out.length - 1];
111
- if (last?.type === "display")
112
- last.text += text;
113
- else
114
- out.push({ type: "display", text });
115
- };
116
- while (this.buf.length > 0) {
117
- const open = findOpen(this.buf);
118
- if (!open) {
119
- if (isFinal) {
120
- pushDisplay(this.buf);
121
- this.buf = "";
122
- }
123
- else {
124
- const holdFrom = lastPotentialPartialOpen(this.buf);
125
- if (holdFrom >= 0) {
126
- pushDisplay(this.buf.slice(0, holdFrom));
127
- this.buf = this.buf.slice(holdFrom);
128
- }
129
- else {
130
- pushDisplay(this.buf);
131
- this.buf = "";
132
- }
133
- }
134
- break;
135
- }
136
- if (open.index > 0) {
137
- let pre = this.buf.slice(0, open.index);
138
- pre = pre.replace(/\n+$/, "");
139
- if (pre)
140
- pushDisplay(pre);
141
- this.buf = this.buf.slice(open.index);
142
- }
143
- const close = findClose(this.buf, open.openLen);
144
- if (!close) {
145
- const innerLen = this.buf.length - open.openLen;
146
- if (isFinal || innerLen > UNCLOSED_MAX) {
147
- const inner = this.buf.slice(open.openLen);
148
- out.push({ type: "search", block: classifyXmlSearchBody(inner, queryFromOpenTag(open.raw)) });
149
- hadBlock = true;
150
- this.buf = "";
151
- }
152
- break;
153
- }
154
- const inner = this.buf.slice(open.openLen, close.innerEnd);
155
- out.push({ type: "search", block: classifyXmlSearchBody(inner, queryFromOpenTag(open.raw)) });
156
- hadBlock = true;
157
- this.buf = this.buf.slice(close.tagEnd).replace(/^\n+/, "");
158
- }
159
- if (hadBlock) {
160
- const first = out[0];
161
- if (first?.type === "display")
162
- first.text = first.text.replace(/^\n+/, "");
163
- }
164
- return out.filter((sl) => sl.type === "search" || sl.text.length > 0);
165
- }
166
- }
167
- export function extractXmlSearch(text) {
168
- const splitter = new XmlSearchSplitter();
169
- const slices = [...splitter.feed(text), ...splitter.flush()];
170
- let display = "";
171
- const blocks = [];
172
- for (const sl of slices) {
173
- if (sl.type === "display")
174
- display += sl.text;
175
- else
176
- blocks.push(sl.block);
177
- }
178
- return { display, blocks, slices };
179
- }
180
- /** Drop the XML wrappers but keep the inner query/results, for sub-agent returns. */
181
- export function unwrapXmlSearchTags(text) {
182
- const { slices } = extractXmlSearch(text);
183
- if (slices.every((sl) => sl.type === "display"))
184
- return text;
185
- return slices
186
- .map((sl) => {
187
- if (sl.type === "display")
188
- return sl.text;
189
- return sl.block.kind === "results" ? sl.block.body : sl.block.query;
190
- })
191
- .join("")
192
- .replace(/^\n+/, "")
193
- .replace(/\n+$/, "");
194
- }