min-agent 0.5.1 → 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 (169) hide show
  1. package/README.md +18 -18
  2. package/dist/cli.js +538 -12
  3. package/docs/API.md +6 -6
  4. package/package.json +6 -6
  5. package/skills/self-config/SKILL.md +4 -2
  6. package/skills/self-config/reference.md +4 -1
  7. package/dist/agent.js +0 -1388
  8. package/dist/assistant-stream.js +0 -131
  9. package/dist/cli/commands/chat.js +0 -13
  10. package/dist/cli/commands/ctx.js +0 -7
  11. package/dist/cli/commands/exec.js +0 -35
  12. package/dist/cli/commands/history.js +0 -58
  13. package/dist/cli/commands/index.js +0 -249
  14. package/dist/cli/commands/init.js +0 -18
  15. package/dist/cli/commands/mcp.js +0 -173
  16. package/dist/cli/commands/memory.js +0 -87
  17. package/dist/cli/commands/models.js +0 -21
  18. package/dist/cli/commands/permission.js +0 -12
  19. package/dist/cli/commands/rules.js +0 -33
  20. package/dist/cli/commands/sandbox.js +0 -13
  21. package/dist/cli/commands/serve.js +0 -9
  22. package/dist/cli/commands/setup.js +0 -56
  23. package/dist/cli/commands/shared.js +0 -25
  24. package/dist/cli/commands/skills.js +0 -119
  25. package/dist/cli/commands/think.js +0 -12
  26. package/dist/cli/commands/update.js +0 -7
  27. package/dist/cli/commands/write-config.js +0 -52
  28. package/dist/cli/errors.js +0 -36
  29. package/dist/cli/exec-prompt.js +0 -26
  30. package/dist/cli/option-helpers.js +0 -65
  31. package/dist/cli/program.js +0 -223
  32. package/dist/cli/setup/detect.js +0 -17
  33. package/dist/cli/setup/flags.js +0 -12
  34. package/dist/cli/setup/flow.js +0 -108
  35. package/dist/cli/setup/provider-form.js +0 -102
  36. package/dist/cli/setup/ui.js +0 -534
  37. package/dist/clipboard.js +0 -142
  38. package/dist/code-mode.js +0 -184
  39. package/dist/compaction.js +0 -644
  40. package/dist/config.js +0 -363
  41. package/dist/confirm.js +0 -172
  42. package/dist/context-window.js +0 -256
  43. package/dist/ctx-cli.js +0 -30
  44. package/dist/ctx.js +0 -80
  45. package/dist/doom-loop.js +0 -278
  46. package/dist/fetch-timeout.js +0 -152
  47. package/dist/http-approvals.js +0 -60
  48. package/dist/http.js +0 -119
  49. package/dist/instructions.js +0 -196
  50. package/dist/logger.js +0 -95
  51. package/dist/markdown.js +0 -259
  52. package/dist/mcp.js +0 -1036
  53. package/dist/memory-cli.js +0 -33
  54. package/dist/memory.js +0 -295
  55. package/dist/model-catalog.js +0 -285
  56. package/dist/ollama-model.js +0 -234
  57. package/dist/ollama-openai-bridge.js +0 -383
  58. package/dist/output.js +0 -76
  59. package/dist/paste-handler.js +0 -41
  60. package/dist/permission-cli.js +0 -40
  61. package/dist/plugins.js +0 -131
  62. package/dist/pricing.js +0 -119
  63. package/dist/provider.js +0 -63
  64. package/dist/question-format.js +0 -60
  65. package/dist/reasoning-stream.js +0 -158
  66. package/dist/sandbox-cli.js +0 -79
  67. package/dist/sandbox.js +0 -403
  68. package/dist/save-throttle.js +0 -45
  69. package/dist/scope.js +0 -23
  70. package/dist/serve/common.js +0 -425
  71. package/dist/serve/routes-chat.js +0 -367
  72. package/dist/serve/routes-mcp.js +0 -212
  73. package/dist/serve/routes-memory.js +0 -95
  74. package/dist/serve/routes-meta.js +0 -268
  75. package/dist/serve/routes-sessions.js +0 -61
  76. package/dist/serve/routes-skills.js +0 -70
  77. package/dist/serve.js +0 -138
  78. package/dist/sessions.js +0 -265
  79. package/dist/skills.js +0 -599
  80. package/dist/structured-output.js +0 -29
  81. package/dist/synthetic.js +0 -7
  82. package/dist/think-cli.js +0 -36
  83. package/dist/thinking-wire.js +0 -239
  84. package/dist/thinking.js +0 -166
  85. package/dist/title-gen.js +0 -55
  86. package/dist/token-display.js +0 -39
  87. package/dist/tool-display.js +0 -178
  88. package/dist/tool-output.js +0 -126
  89. package/dist/tools/apply_patch.js +0 -265
  90. package/dist/tools/atomic-file.js +0 -35
  91. package/dist/tools/backend.js +0 -61
  92. package/dist/tools/bash.js +0 -231
  93. package/dist/tools/code_search.js +0 -98
  94. package/dist/tools/edit.js +0 -68
  95. package/dist/tools/explore.js +0 -232
  96. package/dist/tools/glob.js +0 -40
  97. package/dist/tools/grep.js +0 -174
  98. package/dist/tools/index.js +0 -34
  99. package/dist/tools/question.js +0 -54
  100. package/dist/tools/read.js +0 -109
  101. package/dist/tools/search-searxng.js +0 -223
  102. package/dist/tools/search-serper.js +0 -189
  103. package/dist/tools/task.js +0 -165
  104. package/dist/tools/todo.js +0 -213
  105. package/dist/tools/web_fetch.js +0 -195
  106. package/dist/tools/web_search.js +0 -228
  107. package/dist/tools/write.js +0 -55
  108. package/dist/tui/App.js +0 -138
  109. package/dist/tui/ConfirmBar.js +0 -66
  110. package/dist/tui/CtxPicker.js +0 -68
  111. package/dist/tui/InputBar.js +0 -618
  112. package/dist/tui/MessageList.js +0 -718
  113. package/dist/tui/ModelPicker.js +0 -113
  114. package/dist/tui/QuestionBar.js +0 -136
  115. package/dist/tui/SessionPicker.js +0 -79
  116. package/dist/tui/Spinner.js +0 -6
  117. package/dist/tui/StatusBar.js +0 -22
  118. package/dist/tui/ThinkPicker.js +0 -75
  119. package/dist/tui/agent-runner.js +0 -223
  120. package/dist/tui/bracketed-paste.js +0 -37
  121. package/dist/tui/caret-pos.js +0 -179
  122. package/dist/tui/caret.js +0 -69
  123. package/dist/tui/click-count.js +0 -13
  124. package/dist/tui/diff-view.js +0 -61
  125. package/dist/tui/drag-state.js +0 -49
  126. package/dist/tui/hydrate.js +0 -129
  127. package/dist/tui/index.js +0 -264
  128. package/dist/tui/input-history.js +0 -125
  129. package/dist/tui/layout.js +0 -105
  130. package/dist/tui/mouse.js +0 -46
  131. package/dist/tui/overlay-input.js +0 -12
  132. package/dist/tui/paste-draft.js +0 -173
  133. package/dist/tui/prompt-queue.js +0 -24
  134. package/dist/tui/selection.js +0 -232
  135. package/dist/tui/session-switch.js +0 -28
  136. package/dist/tui/slash-commands.js +0 -129
  137. package/dist/tui/slash-handler.js +0 -615
  138. package/dist/tui/text-width.js +0 -113
  139. package/dist/tui/theme.js +0 -12
  140. package/dist/tui/token-info.js +0 -7
  141. package/dist/tui/tool-children.js +0 -19
  142. package/dist/tui/types.js +0 -1
  143. package/dist/tui/undo-stack.js +0 -14
  144. package/dist/tui/use-sgr-mouse.js +0 -29
  145. package/dist/tui-chat.js +0 -478
  146. package/dist/updater.js +0 -116
  147. package/dist/xml-search.js +0 -194
  148. package/docs/superpowers/plans/2026-08-16-batch1-tui-improvements.md +0 -1510
  149. package/docs/superpowers/plans/2026-08-16-batch2-cli-tools-api.md +0 -2105
  150. package/docs/superpowers/plans/2026-08-16-batch3-config-engineering.md +0 -1595
  151. package/docs/superpowers/plans/2026-08-16-input-caret.md +0 -782
  152. package/docs/superpowers/plans/2026-08-20-tui-completeness.md +0 -873
  153. package/docs/superpowers/plans/2026-08-20-unified-tui-default.md +0 -631
  154. package/docs/superpowers/plans/2026-08-23-cli-setup.md +0 -501
  155. package/docs/superpowers/plans/2026-08-23-input-paste-attachments.md +0 -475
  156. package/docs/superpowers/plans/2026-08-23-thinking-wire-profile.md +0 -450
  157. package/docs/superpowers/specs/2026-08-16-batch1-tui-improvements-design.md +0 -183
  158. package/docs/superpowers/specs/2026-08-16-batch2-cli-tools-api-design.md +0 -220
  159. package/docs/superpowers/specs/2026-08-16-batch3-config-engineering-design.md +0 -196
  160. package/docs/superpowers/specs/2026-08-16-input-caret-design.md +0 -63
  161. package/docs/superpowers/specs/2026-08-17-mouse-selection-design.md +0 -116
  162. package/docs/superpowers/specs/2026-08-20-config-http-alignment-design.md +0 -47
  163. package/docs/superpowers/specs/2026-08-20-mcp-plugins-alignment-design.md +0 -37
  164. package/docs/superpowers/specs/2026-08-20-sandbox-permissions-design.md +0 -68
  165. package/docs/superpowers/specs/2026-08-20-tui-completeness-design.md +0 -273
  166. package/docs/superpowers/specs/2026-08-20-unified-tui-default-design.md +0 -165
  167. package/docs/superpowers/specs/2026-08-23-cli-setup-design.md +0 -282
  168. package/docs/superpowers/specs/2026-08-23-input-paste-attachments-design.md +0 -174
  169. package/docs/superpowers/specs/2026-08-23-thinking-wire-profile-design.md +0 -140
package/dist/sessions.js DELETED
@@ -1,265 +0,0 @@
1
- import { readFileSync, mkdirSync, existsSync, readdirSync, unlinkSync, openSync, readSync, closeSync, statSync, } from "fs";
2
- import path from "path";
3
- import { randomUUID } from "crypto";
4
- import { atomicWriteFileSync } from "./tools/atomic-file.js";
5
- import { getConfigDir } from "./config.js";
6
- import { generateTitle } from "./title-gen.js";
7
- import { isSyntheticMessage } from "./synthetic.js";
8
- import { parseTaskState } from "./tools/todo.js";
9
- function getSessionsDir() {
10
- return path.join(getConfigDir(), "sessions");
11
- }
12
- /**
13
- * In-process per-session mutex serializing read-modify-write cycles
14
- * (load → append → run → save) so concurrent requests on the same session
15
- * cannot lose messages. Cross-process safety is NOT provided.
16
- */
17
- const sessionLocks = new Map();
18
- export async function withSessionLock(sessionId, fn) {
19
- if (!sessionId)
20
- return fn();
21
- const prev = sessionLocks.get(sessionId) ?? Promise.resolve();
22
- let release;
23
- const ours = new Promise((r) => {
24
- release = r;
25
- });
26
- const chained = prev.then(() => ours);
27
- sessionLocks.set(sessionId, chained);
28
- await prev;
29
- try {
30
- return await fn();
31
- }
32
- finally {
33
- release();
34
- if (sessionLocks.get(sessionId) === chained)
35
- sessionLocks.delete(sessionId);
36
- }
37
- }
38
- /** Session ids are UUIDs; a strict whitelist blocks path traversal via `/v1/sessions/..%2F..%2Fconfig`. */
39
- const SESSION_ID_RE = /^[a-zA-Z0-9_-]+$/;
40
- function sessionPath(id) {
41
- if (!SESSION_ID_RE.test(id))
42
- throw new Error(`invalid session id: ${id}`);
43
- return path.join(getSessionsDir(), `${id}.json`);
44
- }
45
- /** Session meta lives at the head of the JSON file, so only the first bytes are needed. */
46
- const META_READ_LIMIT = 64 * 1024;
47
- function readHead(file, limit) {
48
- const fd = openSync(file, "r");
49
- try {
50
- const buf = Buffer.alloc(Math.min(statSync(file).size, limit));
51
- if (buf.length === 0)
52
- return "";
53
- readSync(fd, buf, 0, buf.length, 0);
54
- return buf.toString("utf-8");
55
- }
56
- finally {
57
- closeSync(fd);
58
- }
59
- }
60
- /** Find the index of the `}` that closes the object opened at `start`, or -1. */
61
- function matchBrace(text, start) {
62
- let depth = 0;
63
- let inString = false;
64
- let escaped = false;
65
- for (let i = start; i < text.length; i++) {
66
- const ch = text[i];
67
- if (inString) {
68
- if (escaped)
69
- escaped = false;
70
- else if (ch === "\\")
71
- escaped = true;
72
- else if (ch === '"')
73
- inString = false;
74
- continue;
75
- }
76
- if (ch === '"')
77
- inString = true;
78
- else if (ch === "{")
79
- depth++;
80
- else if (ch === "}") {
81
- depth--;
82
- if (depth === 0)
83
- return i;
84
- }
85
- }
86
- return -1;
87
- }
88
- /** Extract the meta object from a (possibly truncated) session JSON head. */
89
- function parseMetaFromHead(head) {
90
- const key = head.indexOf('"meta"');
91
- if (key < 0)
92
- return null;
93
- const brace = head.indexOf("{", key);
94
- if (brace < 0)
95
- return null;
96
- const end = matchBrace(head, brace);
97
- if (end < 0)
98
- return null;
99
- try {
100
- return JSON.parse(head.slice(brace, end + 1));
101
- }
102
- catch {
103
- return null;
104
- }
105
- }
106
- function generateId() {
107
- return randomUUID();
108
- }
109
- function textOfContent(content) {
110
- if (typeof content === "string")
111
- return content;
112
- return content
113
- .map((p) => (p.type === "text" ? p.text : ""))
114
- .join(" ")
115
- .trim();
116
- }
117
- function deriveTitle(messages) {
118
- const first = messages.find((m) => m.role === "user");
119
- if (!first)
120
- return "Untitled";
121
- const text = textOfContent(first.content);
122
- return text.slice(0, 60) || "Untitled";
123
- }
124
- /** Convert binary image parts to data URLs so JSON serialization stays usable. */
125
- export function sanitizeForStorage(messages) {
126
- return messages
127
- .filter((msg) => !isSyntheticMessage(msg))
128
- .map((msg) => {
129
- if (!Array.isArray(msg.content))
130
- return msg;
131
- const content = msg.content.map((part) => {
132
- if (part.type !== "image" || part.image == null || typeof part.image === "string")
133
- return part;
134
- let buf = null;
135
- if (Buffer.isBuffer(part.image) || part.image instanceof Uint8Array) {
136
- buf = Buffer.isBuffer(part.image) ? part.image : Buffer.from(part.image);
137
- }
138
- else if (typeof part.image === "object" && !(part.image instanceof URL)) {
139
- const data = part.image.data;
140
- if (Buffer.isBuffer(data) || data instanceof Uint8Array) {
141
- buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
142
- }
143
- }
144
- if (!buf)
145
- return part;
146
- const mime = part.mimeType ?? "image/png";
147
- return { ...part, image: `data:${mime};base64,${buf.toString("base64")}` };
148
- });
149
- return { ...msg, content };
150
- });
151
- }
152
- export function saveSession(messages, existingId, title, created, taskState) {
153
- const dir = getSessionsDir();
154
- mkdirSync(dir, { recursive: true });
155
- const id = existingId && SESSION_ID_RE.test(existingId) ? existingId : generateId();
156
- const now = new Date().toISOString();
157
- const existingMeta = existingId ? readMeta(id) : null;
158
- const preservedState = taskState === undefined && existingId ? loadSession(id)?.taskState : undefined;
159
- const resolvedState = taskState ?? preservedState;
160
- const data = {
161
- meta: {
162
- id,
163
- title: title ?? existingMeta?.title ?? deriveTitle(messages),
164
- created: created ?? existingMeta?.created ?? now,
165
- updated: now,
166
- messageCount: messages.length,
167
- },
168
- ...(resolvedState ? { taskState: resolvedState } : {}),
169
- messages: sanitizeForStorage(messages),
170
- };
171
- atomicWriteFileSync(sessionPath(id), JSON.stringify(data, null, 2));
172
- return id;
173
- }
174
- /** Read only the meta head to recover the original created/title. */
175
- function readMeta(id) {
176
- const file = sessionPath(id);
177
- if (!existsSync(file))
178
- return null;
179
- try {
180
- return parseMetaFromHead(readHead(file, META_READ_LIMIT));
181
- }
182
- catch {
183
- return null;
184
- }
185
- }
186
- /** Save session with auto-generated title from LLM */
187
- export async function saveSessionWithTitle(messages, model, existingId) {
188
- let title = null;
189
- try {
190
- title = await generateTitle(model, messages);
191
- }
192
- catch { }
193
- return saveSession(messages, existingId, title ?? undefined);
194
- }
195
- export function loadSession(id) {
196
- if (!SESSION_ID_RE.test(id))
197
- return null;
198
- const file = sessionPath(id);
199
- if (!existsSync(file))
200
- return null;
201
- try {
202
- const data = JSON.parse(readFileSync(file, "utf-8"));
203
- const taskState = parseTaskState(data.taskState);
204
- return taskState ? { ...data, taskState } : data;
205
- }
206
- catch {
207
- return null;
208
- }
209
- }
210
- export function loadExecHistory(resumeSessionId) {
211
- if (!resumeSessionId)
212
- return { ok: true, messages: [], sessionId: undefined };
213
- const session = loadSession(resumeSessionId);
214
- if (!session)
215
- return { ok: false, error: `会话不存在: ${resumeSessionId}` };
216
- return { ok: true, messages: [...session.messages], sessionId: resumeSessionId, taskState: session.taskState };
217
- }
218
- export function listSessions() {
219
- const dir = getSessionsDir();
220
- if (!existsSync(dir))
221
- return [];
222
- return readdirSync(dir)
223
- .filter((f) => f.endsWith(".json"))
224
- .map((f) => {
225
- try {
226
- return parseMetaFromHead(readHead(path.join(dir, f), META_READ_LIMIT));
227
- }
228
- catch {
229
- return null;
230
- }
231
- })
232
- .filter((m) => m !== null)
233
- .sort((a, b) => b.updated.localeCompare(a.updated));
234
- }
235
- export function deleteSession(id) {
236
- if (!SESSION_ID_RE.test(id))
237
- return false;
238
- const file = sessionPath(id);
239
- if (!existsSync(file))
240
- return false;
241
- try {
242
- unlinkSync(file);
243
- return true;
244
- }
245
- catch {
246
- return false;
247
- }
248
- }
249
- export function renameSession(id, title) {
250
- if (!SESSION_ID_RE.test(id))
251
- return false;
252
- const file = sessionPath(id);
253
- if (!existsSync(file))
254
- return false;
255
- try {
256
- const data = JSON.parse(readFileSync(file, "utf-8"));
257
- data.meta.title = title;
258
- data.meta.updated = new Date().toISOString();
259
- atomicWriteFileSync(file, JSON.stringify(data, null, 2));
260
- return true;
261
- }
262
- catch {
263
- return false;
264
- }
265
- }