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.
- package/README.md +18 -18
- package/dist/cli.js +538 -12
- package/docs/API.md +6 -6
- package/package.json +6 -6
- package/skills/self-config/SKILL.md +4 -2
- package/skills/self-config/reference.md +4 -1
- package/dist/agent.js +0 -1388
- package/dist/assistant-stream.js +0 -131
- package/dist/cli/commands/chat.js +0 -13
- package/dist/cli/commands/ctx.js +0 -7
- package/dist/cli/commands/exec.js +0 -35
- package/dist/cli/commands/history.js +0 -58
- package/dist/cli/commands/index.js +0 -249
- package/dist/cli/commands/init.js +0 -18
- package/dist/cli/commands/mcp.js +0 -173
- package/dist/cli/commands/memory.js +0 -87
- package/dist/cli/commands/models.js +0 -21
- package/dist/cli/commands/permission.js +0 -12
- package/dist/cli/commands/rules.js +0 -33
- package/dist/cli/commands/sandbox.js +0 -13
- package/dist/cli/commands/serve.js +0 -9
- package/dist/cli/commands/setup.js +0 -56
- package/dist/cli/commands/shared.js +0 -25
- package/dist/cli/commands/skills.js +0 -119
- package/dist/cli/commands/think.js +0 -12
- package/dist/cli/commands/update.js +0 -7
- package/dist/cli/commands/write-config.js +0 -52
- package/dist/cli/errors.js +0 -36
- package/dist/cli/exec-prompt.js +0 -26
- package/dist/cli/option-helpers.js +0 -65
- package/dist/cli/program.js +0 -223
- package/dist/cli/setup/detect.js +0 -17
- package/dist/cli/setup/flags.js +0 -12
- package/dist/cli/setup/flow.js +0 -108
- package/dist/cli/setup/provider-form.js +0 -102
- package/dist/cli/setup/ui.js +0 -534
- package/dist/clipboard.js +0 -142
- package/dist/code-mode.js +0 -184
- package/dist/compaction.js +0 -644
- package/dist/config.js +0 -363
- package/dist/confirm.js +0 -172
- package/dist/context-window.js +0 -256
- package/dist/ctx-cli.js +0 -30
- package/dist/ctx.js +0 -80
- package/dist/doom-loop.js +0 -278
- package/dist/fetch-timeout.js +0 -152
- package/dist/http-approvals.js +0 -60
- package/dist/http.js +0 -119
- package/dist/instructions.js +0 -196
- package/dist/logger.js +0 -95
- package/dist/markdown.js +0 -259
- package/dist/mcp.js +0 -1036
- package/dist/memory-cli.js +0 -33
- package/dist/memory.js +0 -295
- package/dist/model-catalog.js +0 -285
- package/dist/ollama-model.js +0 -234
- package/dist/ollama-openai-bridge.js +0 -383
- package/dist/output.js +0 -76
- package/dist/paste-handler.js +0 -41
- package/dist/permission-cli.js +0 -40
- package/dist/plugins.js +0 -131
- package/dist/pricing.js +0 -119
- package/dist/provider.js +0 -63
- package/dist/question-format.js +0 -60
- package/dist/reasoning-stream.js +0 -158
- package/dist/sandbox-cli.js +0 -79
- package/dist/sandbox.js +0 -403
- package/dist/save-throttle.js +0 -45
- package/dist/scope.js +0 -23
- package/dist/serve/common.js +0 -425
- package/dist/serve/routes-chat.js +0 -367
- package/dist/serve/routes-mcp.js +0 -212
- package/dist/serve/routes-memory.js +0 -95
- package/dist/serve/routes-meta.js +0 -268
- package/dist/serve/routes-sessions.js +0 -61
- package/dist/serve/routes-skills.js +0 -70
- package/dist/serve.js +0 -138
- package/dist/sessions.js +0 -265
- package/dist/skills.js +0 -599
- package/dist/structured-output.js +0 -29
- package/dist/synthetic.js +0 -7
- package/dist/think-cli.js +0 -36
- package/dist/thinking-wire.js +0 -239
- package/dist/thinking.js +0 -166
- package/dist/title-gen.js +0 -55
- package/dist/token-display.js +0 -39
- package/dist/tool-display.js +0 -178
- package/dist/tool-output.js +0 -126
- package/dist/tools/apply_patch.js +0 -265
- package/dist/tools/atomic-file.js +0 -35
- package/dist/tools/backend.js +0 -61
- package/dist/tools/bash.js +0 -231
- package/dist/tools/code_search.js +0 -98
- package/dist/tools/edit.js +0 -68
- package/dist/tools/explore.js +0 -232
- package/dist/tools/glob.js +0 -40
- package/dist/tools/grep.js +0 -174
- package/dist/tools/index.js +0 -34
- package/dist/tools/question.js +0 -54
- package/dist/tools/read.js +0 -109
- package/dist/tools/search-searxng.js +0 -223
- package/dist/tools/search-serper.js +0 -189
- package/dist/tools/task.js +0 -165
- package/dist/tools/todo.js +0 -213
- package/dist/tools/web_fetch.js +0 -195
- package/dist/tools/web_search.js +0 -228
- package/dist/tools/write.js +0 -55
- package/dist/tui/App.js +0 -138
- package/dist/tui/ConfirmBar.js +0 -66
- package/dist/tui/CtxPicker.js +0 -68
- package/dist/tui/InputBar.js +0 -618
- package/dist/tui/MessageList.js +0 -718
- package/dist/tui/ModelPicker.js +0 -113
- package/dist/tui/QuestionBar.js +0 -136
- package/dist/tui/SessionPicker.js +0 -79
- package/dist/tui/Spinner.js +0 -6
- package/dist/tui/StatusBar.js +0 -22
- package/dist/tui/ThinkPicker.js +0 -75
- package/dist/tui/agent-runner.js +0 -223
- package/dist/tui/bracketed-paste.js +0 -37
- package/dist/tui/caret-pos.js +0 -179
- package/dist/tui/caret.js +0 -69
- package/dist/tui/click-count.js +0 -13
- package/dist/tui/diff-view.js +0 -61
- package/dist/tui/drag-state.js +0 -49
- package/dist/tui/hydrate.js +0 -129
- package/dist/tui/index.js +0 -264
- package/dist/tui/input-history.js +0 -125
- package/dist/tui/layout.js +0 -105
- package/dist/tui/mouse.js +0 -46
- package/dist/tui/overlay-input.js +0 -12
- package/dist/tui/paste-draft.js +0 -173
- package/dist/tui/prompt-queue.js +0 -24
- package/dist/tui/selection.js +0 -232
- package/dist/tui/session-switch.js +0 -28
- package/dist/tui/slash-commands.js +0 -129
- package/dist/tui/slash-handler.js +0 -615
- package/dist/tui/text-width.js +0 -113
- package/dist/tui/theme.js +0 -12
- package/dist/tui/token-info.js +0 -7
- package/dist/tui/tool-children.js +0 -19
- package/dist/tui/types.js +0 -1
- package/dist/tui/undo-stack.js +0 -14
- package/dist/tui/use-sgr-mouse.js +0 -29
- package/dist/tui-chat.js +0 -478
- package/dist/updater.js +0 -116
- package/dist/xml-search.js +0 -194
- package/docs/superpowers/plans/2026-08-16-batch1-tui-improvements.md +0 -1510
- package/docs/superpowers/plans/2026-08-16-batch2-cli-tools-api.md +0 -2105
- package/docs/superpowers/plans/2026-08-16-batch3-config-engineering.md +0 -1595
- package/docs/superpowers/plans/2026-08-16-input-caret.md +0 -782
- package/docs/superpowers/plans/2026-08-20-tui-completeness.md +0 -873
- package/docs/superpowers/plans/2026-08-20-unified-tui-default.md +0 -631
- package/docs/superpowers/plans/2026-08-23-cli-setup.md +0 -501
- package/docs/superpowers/plans/2026-08-23-input-paste-attachments.md +0 -475
- package/docs/superpowers/plans/2026-08-23-thinking-wire-profile.md +0 -450
- package/docs/superpowers/specs/2026-08-16-batch1-tui-improvements-design.md +0 -183
- package/docs/superpowers/specs/2026-08-16-batch2-cli-tools-api-design.md +0 -220
- package/docs/superpowers/specs/2026-08-16-batch3-config-engineering-design.md +0 -196
- package/docs/superpowers/specs/2026-08-16-input-caret-design.md +0 -63
- package/docs/superpowers/specs/2026-08-17-mouse-selection-design.md +0 -116
- package/docs/superpowers/specs/2026-08-20-config-http-alignment-design.md +0 -47
- package/docs/superpowers/specs/2026-08-20-mcp-plugins-alignment-design.md +0 -37
- package/docs/superpowers/specs/2026-08-20-sandbox-permissions-design.md +0 -68
- package/docs/superpowers/specs/2026-08-20-tui-completeness-design.md +0 -273
- package/docs/superpowers/specs/2026-08-20-unified-tui-default-design.md +0 -165
- package/docs/superpowers/specs/2026-08-23-cli-setup-design.md +0 -282
- package/docs/superpowers/specs/2026-08-23-input-paste-attachments-design.md +0 -174
- package/docs/superpowers/specs/2026-08-23-thinking-wire-profile-design.md +0 -140
package/dist/assistant-stream.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Split "thinking" fragments (inline XML-style blocks some models leak into text)
|
|
3
|
-
* from displayable assistant text. Thinking is emitted to stderr; display goes to Markdown.
|
|
4
|
-
*/
|
|
5
|
-
const BT = String.fromCharCode(96); // backtick — some models wrap thinking in `think` / `redacted_thinking`
|
|
6
|
-
const THINKING_BLOCKS = [
|
|
7
|
-
{ open: "<think>", close: "</think>" },
|
|
8
|
-
{ open: "<thinking>", close: "</thinking>" },
|
|
9
|
-
{ open: `<${BT}think${BT}>`, close: `<${BT}/think${BT}>` },
|
|
10
|
-
{ open: `<${BT}redacted_thinking${BT}>`, close: `<${BT}/redacted_thinking${BT}>` },
|
|
11
|
-
];
|
|
12
|
-
/** Max tail to keep when looking for a partial opening tag. */
|
|
13
|
-
const PARTIAL_TAG_HOLD = 72;
|
|
14
|
-
/**
|
|
15
|
-
* If an opening tag never gets closed (truncated / misbehaving model), the
|
|
16
|
-
* buffer would grow without bound. Beyond this size, treat the remainder as
|
|
17
|
-
* thinking text and move on.
|
|
18
|
-
*/
|
|
19
|
-
const UNCLOSED_THINK_MAX = 16 * 1024;
|
|
20
|
-
function lower(s) {
|
|
21
|
-
return s.toLowerCase();
|
|
22
|
-
}
|
|
23
|
-
function findFirstOpen(buf) {
|
|
24
|
-
const l = lower(buf);
|
|
25
|
-
let best = null;
|
|
26
|
-
for (const tag of THINKING_BLOCKS) {
|
|
27
|
-
const i = l.indexOf(tag.open);
|
|
28
|
-
if (i >= 0 && (!best || i < best.index))
|
|
29
|
-
best = { index: i, tag };
|
|
30
|
-
}
|
|
31
|
-
return best;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Incremental filter: feed raw model text deltas; get display text (for stdout / history)
|
|
35
|
-
* and thinking text (for stderr). Handles tags split across chunks.
|
|
36
|
-
*/
|
|
37
|
-
export class ThinkingBodySplitter {
|
|
38
|
-
buf = "";
|
|
39
|
-
feed(chunk) {
|
|
40
|
-
this.buf += chunk;
|
|
41
|
-
return this.drain(false);
|
|
42
|
-
}
|
|
43
|
-
/** End of stream: flush remainder; incomplete thinking block → stderr only. */
|
|
44
|
-
flush() {
|
|
45
|
-
return this.drain(true);
|
|
46
|
-
}
|
|
47
|
-
drain(isFinal) {
|
|
48
|
-
let display = "";
|
|
49
|
-
let thinking = "";
|
|
50
|
-
let hadThinking = false;
|
|
51
|
-
while (this.buf.length > 0) {
|
|
52
|
-
const open = findFirstOpen(this.buf);
|
|
53
|
-
if (!open) {
|
|
54
|
-
if (isFinal) {
|
|
55
|
-
display += this.buf;
|
|
56
|
-
this.buf = "";
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const holdFrom = lastPotentialPartialOpen(this.buf);
|
|
60
|
-
if (holdFrom >= 0) {
|
|
61
|
-
display += this.buf.slice(0, holdFrom);
|
|
62
|
-
this.buf = this.buf.slice(holdFrom);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
display += this.buf;
|
|
66
|
-
this.buf = "";
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
if (open.index > 0) {
|
|
72
|
-
// Strip trailing newlines before thinking block
|
|
73
|
-
let pre = this.buf.slice(0, open.index);
|
|
74
|
-
pre = pre.replace(/\n+$/, "");
|
|
75
|
-
if (pre)
|
|
76
|
-
display += pre;
|
|
77
|
-
this.buf = this.buf.slice(open.index);
|
|
78
|
-
}
|
|
79
|
-
const low = lower(this.buf);
|
|
80
|
-
const afterOpen = open.tag.open.length;
|
|
81
|
-
const closeRel = low.indexOf(open.tag.close, afterOpen);
|
|
82
|
-
if (closeRel < 0) {
|
|
83
|
-
if (isFinal) {
|
|
84
|
-
thinking += this.buf.slice(afterOpen);
|
|
85
|
-
this.buf = "";
|
|
86
|
-
}
|
|
87
|
-
else if (this.buf.length - afterOpen > UNCLOSED_THINK_MAX) {
|
|
88
|
-
thinking += this.buf.slice(afterOpen);
|
|
89
|
-
this.buf = "";
|
|
90
|
-
hadThinking = true;
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
const inner = this.buf.slice(afterOpen, closeRel);
|
|
95
|
-
thinking += inner;
|
|
96
|
-
hadThinking = true;
|
|
97
|
-
this.buf = this.buf.slice(closeRel + open.tag.close.length);
|
|
98
|
-
}
|
|
99
|
-
// Strip leading newlines from display that follow a thinking block
|
|
100
|
-
if (hadThinking) {
|
|
101
|
-
display = display.replace(/^\n+/, "");
|
|
102
|
-
}
|
|
103
|
-
return { display, thinking };
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/** If `buf` ends with `<...` that could still become a thinking open tag, return index of `<` to hold from; else -1. */
|
|
107
|
-
function lastPotentialPartialOpen(buf) {
|
|
108
|
-
const start = Math.max(0, buf.length - PARTIAL_TAG_HOLD);
|
|
109
|
-
const tail = buf.slice(start);
|
|
110
|
-
const lt = tail.lastIndexOf("<");
|
|
111
|
-
if (lt < 0)
|
|
112
|
-
return -1;
|
|
113
|
-
const globalLt = start + lt;
|
|
114
|
-
const cand = buf.slice(globalLt).toLowerCase();
|
|
115
|
-
if (cand.length > 64)
|
|
116
|
-
return -1;
|
|
117
|
-
for (const tag of THINKING_BLOCKS) {
|
|
118
|
-
if (tag.open.startsWith(cand))
|
|
119
|
-
return globalLt;
|
|
120
|
-
}
|
|
121
|
-
return -1;
|
|
122
|
-
}
|
|
123
|
-
/** Final strip for assistant message (complete tags only). */
|
|
124
|
-
export function stripThinkingFromAssistantText(text) {
|
|
125
|
-
let s = text;
|
|
126
|
-
for (const { open, close } of THINKING_BLOCKS) {
|
|
127
|
-
const re = new RegExp(open.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "[\\s\\S]*?" + close.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
128
|
-
s = s.replace(re, "");
|
|
129
|
-
}
|
|
130
|
-
return s;
|
|
131
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { startTuiSession } from "./shared.js";
|
|
2
|
-
import { applySessionOverrides, applySessionRuntimeOverrides } from "../program.js";
|
|
3
|
-
export async function runChat(promptTokens, opts) {
|
|
4
|
-
applySessionOverrides(opts);
|
|
5
|
-
await applySessionRuntimeOverrides(opts);
|
|
6
|
-
await startTuiSession({
|
|
7
|
-
model: opts.model,
|
|
8
|
-
provider: opts.provider,
|
|
9
|
-
resume: opts.resume,
|
|
10
|
-
images: opts.image,
|
|
11
|
-
positionals: promptTokens,
|
|
12
|
-
});
|
|
13
|
-
}
|
package/dist/cli/commands/ctx.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { runAgent } from "../../agent.js";
|
|
2
|
-
import { isConfigured } from "../../config.js";
|
|
3
|
-
import { resolveExecPrompt } from "../exec-prompt.js";
|
|
4
|
-
import { CliError } from "../errors.js";
|
|
5
|
-
import { applySessionOverrides, applySessionRuntimeOverrides } from "../program.js";
|
|
6
|
-
export async function runExec(messageTokens, opts) {
|
|
7
|
-
if (!isConfigured()) {
|
|
8
|
-
throw new CliError("Not configured.", { hint: "Run: min-agent setup" });
|
|
9
|
-
}
|
|
10
|
-
applySessionOverrides(opts);
|
|
11
|
-
await applySessionRuntimeOverrides(opts);
|
|
12
|
-
const stdinIsTty = Boolean(process.stdin.isTTY);
|
|
13
|
-
const joined = messageTokens.join(" ");
|
|
14
|
-
const shouldReadStdin = joined === "-" || !stdinIsTty;
|
|
15
|
-
let stdinText = "";
|
|
16
|
-
if (shouldReadStdin) {
|
|
17
|
-
try {
|
|
18
|
-
const chunks = [];
|
|
19
|
-
for await (const chunk of process.stdin) {
|
|
20
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
21
|
-
}
|
|
22
|
-
stdinText = Buffer.concat(chunks).toString("utf-8");
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
throw new CliError("Failed to read stdin");
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const resolved = resolveExecPrompt(messageTokens, stdinText, stdinIsTty);
|
|
29
|
-
if (!resolved.ok) {
|
|
30
|
-
throw new CliError(resolved.error);
|
|
31
|
-
}
|
|
32
|
-
const failed = await runAgent(resolved.prompt, opts.model, opts.image.length > 0 ? opts.image : undefined, opts.provider, opts.resume);
|
|
33
|
-
if (failed)
|
|
34
|
-
process.exitCode = 1;
|
|
35
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from "fs";
|
|
2
|
-
import { CliError } from "../errors.js";
|
|
3
|
-
export async function runHistoryList() {
|
|
4
|
-
const { listSessions } = await import("../../sessions.js");
|
|
5
|
-
const sessions = listSessions();
|
|
6
|
-
if (sessions.length === 0) {
|
|
7
|
-
console.log("No saved sessions.");
|
|
8
|
-
console.log("Sessions are auto-saved when you exit interactive chat.");
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
console.log(`Sessions (${sessions.length}):`);
|
|
12
|
-
for (const s of sessions.slice(0, 20)) {
|
|
13
|
-
const date = s.updated.split("T")[0];
|
|
14
|
-
console.log(` ${s.id} ${date} ${s.title} (${s.messageCount} msgs)`);
|
|
15
|
-
}
|
|
16
|
-
console.log("\nResume with: min-agent --resume <id>");
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
export async function runHistoryDelete(id) {
|
|
20
|
-
const { deleteSession } = await import("../../sessions.js");
|
|
21
|
-
if (deleteSession(id)) {
|
|
22
|
-
console.log(`✓ Session ${id} deleted`);
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
throw new CliError(`Session ${id} not found`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export async function runHistoryRename(id, titleTokens) {
|
|
29
|
-
const title = titleTokens.join(" ");
|
|
30
|
-
if (!title)
|
|
31
|
-
throw new CliError("Usage: min-agent history rename <id> <title>");
|
|
32
|
-
const { renameSession } = await import("../../sessions.js");
|
|
33
|
-
if (renameSession(id, title)) {
|
|
34
|
-
console.log(`✓ Session ${id} renamed to: ${title}`);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
throw new CliError(`Session ${id} not found`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
export async function runHistoryExport(id, opts) {
|
|
41
|
-
const { loadSession } = await import("../../sessions.js");
|
|
42
|
-
const session = loadSession(id);
|
|
43
|
-
if (!session)
|
|
44
|
-
throw new CliError(`Session ${id} not found`);
|
|
45
|
-
const json = JSON.stringify(session, null, 2);
|
|
46
|
-
if (opts.output) {
|
|
47
|
-
try {
|
|
48
|
-
writeFileSync(opts.output, json, "utf-8");
|
|
49
|
-
console.log(`✓ Session ${id} exported to ${opts.output}`);
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
throw new CliError(`Export failed: ${err.message}`, { exitCode: 2 });
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
console.log(json);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { Option } from "commander";
|
|
2
|
-
import { resolveScope, parsePositiveIntArg } from "../option-helpers.js";
|
|
3
|
-
import { registerSetupCommand } from "./setup.js";
|
|
4
|
-
import { runModelsCommand } from "./models.js";
|
|
5
|
-
import { runChat } from "./chat.js";
|
|
6
|
-
import { runExec } from "./exec.js";
|
|
7
|
-
import { runServeCommand } from "./serve.js";
|
|
8
|
-
import { runSandboxCommand } from "./sandbox.js";
|
|
9
|
-
import { runPermissionCommand } from "./permission.js";
|
|
10
|
-
import { runThinkCommand } from "./think.js";
|
|
11
|
-
import { runCtxCommand } from "./ctx.js";
|
|
12
|
-
import { runInitCommand } from "./init.js";
|
|
13
|
-
import { runRulesShow, runRulesEdit } from "./rules.js";
|
|
14
|
-
import { runUpdateCommand } from "./update.js";
|
|
15
|
-
import { runHistoryList, runHistoryDelete, runHistoryRename, runHistoryExport } from "./history.js";
|
|
16
|
-
import { runMemoryList, runMemoryAdd, runMemorySearch, runMemoryDelete, runMemoryMode } from "./memory.js";
|
|
17
|
-
import { runMcpAdd, runMcpRemove, runMcpList, runMcpInfo, runMcpCheck, runMcpToggle, } from "./mcp.js";
|
|
18
|
-
import { runSkillsList, runSkillsInfo, runSkillsToggle, runSkillsNew } from "./skills.js";
|
|
19
|
-
/**
|
|
20
|
-
* All `--project`/`--global`/`--model`/`--provider`/`--resume`/`--image`/`--sandbox`/
|
|
21
|
-
* `--network`/`--permission`/`--think`/`--memory` flags live on the root `program` (see addSessionOptions),
|
|
22
|
-
* so they can appear before or after a subcommand name. Subcommands read them via
|
|
23
|
-
* `program.opts<SessionOptions>()` instead of re-declaring the same options — commander
|
|
24
|
-
* resolves options against the first command in the chain that declares them, so a
|
|
25
|
-
* subcommand-local redeclaration would silently shadow the root option instead of merging.
|
|
26
|
-
*/
|
|
27
|
-
export function registerCommands(program) {
|
|
28
|
-
const rootOpts = () => program.opts();
|
|
29
|
-
// --- Session aliases -----------------------------------------------------
|
|
30
|
-
for (const alias of ["chat", "code"]) {
|
|
31
|
-
program
|
|
32
|
-
.command(alias)
|
|
33
|
-
.description("Same as interactive session (compat)")
|
|
34
|
-
.argument("[prompt...]", "Prompt to send")
|
|
35
|
-
.allowUnknownOption()
|
|
36
|
-
.action(async (prompt) => {
|
|
37
|
-
await runChat(prompt, rootOpts());
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
program
|
|
41
|
-
.command("exec")
|
|
42
|
-
.description("Run one message non-interactively")
|
|
43
|
-
.argument("[message...]", 'Message to send (use "-" to read from stdin)')
|
|
44
|
-
.allowUnknownOption()
|
|
45
|
-
.action(async (message) => {
|
|
46
|
-
await runExec(message, rootOpts());
|
|
47
|
-
});
|
|
48
|
-
// --- Setup & config ----------------------------------------------------
|
|
49
|
-
registerSetupCommand(program, rootOpts);
|
|
50
|
-
program.command("init").description("Initialize .min-agent/ in current directory").action(runInitCommand);
|
|
51
|
-
program
|
|
52
|
-
.command("models")
|
|
53
|
-
.description("List available models")
|
|
54
|
-
.action(async () => {
|
|
55
|
-
await runModelsCommand(rootOpts());
|
|
56
|
-
});
|
|
57
|
-
const rules = program.command("rules").description("Show or edit instruction rules");
|
|
58
|
-
rules.action(runRulesShow);
|
|
59
|
-
rules.command("edit").description("Edit the global rules file").action(runRulesEdit);
|
|
60
|
-
const memory = program.command("memory").description("Show or set memory, and manage saved memories");
|
|
61
|
-
memory.argument("[state]", "on or off");
|
|
62
|
-
memory.action(async (state) => {
|
|
63
|
-
const opts = rootOpts();
|
|
64
|
-
const scope = opts.project ? "project" : opts.global ? "global" : undefined;
|
|
65
|
-
if (await runMemoryMode(state, scope, opts.memory))
|
|
66
|
-
return;
|
|
67
|
-
if (state && state !== "list") {
|
|
68
|
-
const { CliError } = await import("../errors.js");
|
|
69
|
-
throw new CliError("Usage: min-agent memory [on|off|list|add|search|delete] [--project|--global]");
|
|
70
|
-
}
|
|
71
|
-
await runMemoryList(scope);
|
|
72
|
-
});
|
|
73
|
-
memory
|
|
74
|
-
.command("add")
|
|
75
|
-
.argument("<text...>")
|
|
76
|
-
.description("Add a memory")
|
|
77
|
-
.action(async (text) => {
|
|
78
|
-
const opts = rootOpts();
|
|
79
|
-
await runMemoryAdd(text, opts.project ? "project" : opts.global ? "global" : undefined);
|
|
80
|
-
});
|
|
81
|
-
memory
|
|
82
|
-
.command("search")
|
|
83
|
-
.argument("<query...>")
|
|
84
|
-
.description("Search memories")
|
|
85
|
-
.action(async (query) => {
|
|
86
|
-
const opts = rootOpts();
|
|
87
|
-
await runMemorySearch(query, opts.project ? "project" : opts.global ? "global" : undefined);
|
|
88
|
-
});
|
|
89
|
-
memory
|
|
90
|
-
.command("delete")
|
|
91
|
-
.argument("<index>")
|
|
92
|
-
.description("Delete a memory by index")
|
|
93
|
-
.action(async (index) => {
|
|
94
|
-
const opts = rootOpts();
|
|
95
|
-
await runMemoryDelete(index, opts.project ? "project" : opts.global ? "global" : undefined);
|
|
96
|
-
});
|
|
97
|
-
const sandbox = program
|
|
98
|
-
.command("sandbox")
|
|
99
|
-
.description("Show or set isolation mode (uses --project/--global)")
|
|
100
|
-
.argument("[mode]", "off, workspace, or strict");
|
|
101
|
-
sandbox.action(async (mode) => {
|
|
102
|
-
const opts = rootOpts();
|
|
103
|
-
await runSandboxCommand(mode ? [mode] : [], opts, opts);
|
|
104
|
-
});
|
|
105
|
-
sandbox
|
|
106
|
-
.command("network")
|
|
107
|
-
.description("Show or set network policy")
|
|
108
|
-
.argument("[policy]", "allow or deny")
|
|
109
|
-
.action(async (policy) => {
|
|
110
|
-
const opts = rootOpts();
|
|
111
|
-
await runSandboxCommand(["network", ...(policy ? [policy] : [])], opts, opts);
|
|
112
|
-
});
|
|
113
|
-
program
|
|
114
|
-
.command("permission")
|
|
115
|
-
.description("Show or set confirmation mode (uses --project/--global)")
|
|
116
|
-
.argument("[mode]", "ask, accept-edits, or allow-all")
|
|
117
|
-
.action(async (mode) => {
|
|
118
|
-
const opts = rootOpts();
|
|
119
|
-
await runPermissionCommand(mode ? [mode] : [], opts, opts);
|
|
120
|
-
});
|
|
121
|
-
program
|
|
122
|
-
.command("think")
|
|
123
|
-
.description("Show or set thinking intensity (uses --project/--global)")
|
|
124
|
-
.argument("[level]", "off, low, medium, high, or max")
|
|
125
|
-
.action(async (level) => {
|
|
126
|
-
const opts = rootOpts();
|
|
127
|
-
await runThinkCommand(level ? [level] : [], opts, opts);
|
|
128
|
-
});
|
|
129
|
-
program
|
|
130
|
-
.command("ctx")
|
|
131
|
-
.description("Show or set the Ollama context window level")
|
|
132
|
-
.argument("[level]", "2k, 4k, 8k, 12k, 16k, 32k, 64k, 128k, 256k, or auto")
|
|
133
|
-
.action(async (level) => {
|
|
134
|
-
await runCtxCommand(level ? [level] : []);
|
|
135
|
-
});
|
|
136
|
-
// --- Integrations --------------------------------------------------------
|
|
137
|
-
const mcp = program.command("mcp").description("Manage MCP servers");
|
|
138
|
-
mcp
|
|
139
|
-
.command("add")
|
|
140
|
-
.description("Add a new MCP server (stdio or remote)")
|
|
141
|
-
.usage("[options] <name> [command...]")
|
|
142
|
-
.argument("<name>")
|
|
143
|
-
.argument("[cmd...]", "Command to launch a stdio server (npx, node, ...)")
|
|
144
|
-
.option("--url <url>", "Remote server URL")
|
|
145
|
-
.option("--sse", "Use SSE transport for the remote server")
|
|
146
|
-
.option("--streamable-http", "Use streamable-http transport for the remote server")
|
|
147
|
-
.option("--token <token>", "Bearer token for remote servers")
|
|
148
|
-
.option("--env <KEY=VALUE>", "Extra env for stdio servers (repeatable)", (v, prev) => [...prev, v], [])
|
|
149
|
-
.addOption(new Option("--timeout <ms>", "Connection/call timeout").argParser(parsePositiveIntArg("--timeout")))
|
|
150
|
-
.option("--skip-check", "Skip validation before saving")
|
|
151
|
-
.addHelpText("after", "\nAll options above must come before <name>. Everything after <name> (including flags meant for the\n" +
|
|
152
|
-
"launched command, like `npx -y`) is passed through as-is.\n" +
|
|
153
|
-
"Scope: pass --project on `min-agent` before `mcp add` to write to .min-agent/mcp.json.")
|
|
154
|
-
.allowUnknownOption()
|
|
155
|
-
.passThroughOptions()
|
|
156
|
-
.action(async (name, cmd, opts) => {
|
|
157
|
-
await runMcpAdd(name, cmd, { ...opts, project: rootOpts().project });
|
|
158
|
-
});
|
|
159
|
-
mcp
|
|
160
|
-
.command("remove")
|
|
161
|
-
.argument("<name>")
|
|
162
|
-
.description("Remove a server")
|
|
163
|
-
.action(async (name) => {
|
|
164
|
-
await runMcpRemove(name, { project: rootOpts().project });
|
|
165
|
-
});
|
|
166
|
-
mcp.command("list").description("List configured MCP servers").action(runMcpList);
|
|
167
|
-
mcp.command("info").argument("<name>").description("Show details of a server").action(runMcpInfo);
|
|
168
|
-
mcp.command("check").description("Test connectivity of all servers").action(runMcpCheck);
|
|
169
|
-
mcp
|
|
170
|
-
.command("enable")
|
|
171
|
-
.argument("<names...>")
|
|
172
|
-
.description("Enable disabled servers (use --project to target project scope)")
|
|
173
|
-
.action(async (names) => {
|
|
174
|
-
await runMcpToggle(names, true, { project: rootOpts().project });
|
|
175
|
-
});
|
|
176
|
-
mcp
|
|
177
|
-
.command("disable")
|
|
178
|
-
.argument("<names...>")
|
|
179
|
-
.description("Disable servers (use --project to target project scope)")
|
|
180
|
-
.action(async (names) => {
|
|
181
|
-
await runMcpToggle(names, false, { project: rootOpts().project });
|
|
182
|
-
});
|
|
183
|
-
const skills = program.command("skills").description("Manage skills");
|
|
184
|
-
skills
|
|
185
|
-
.command("list")
|
|
186
|
-
.option("--json", "Machine-readable JSON output")
|
|
187
|
-
.description("List skills")
|
|
188
|
-
.action(async (opts) => {
|
|
189
|
-
await runSkillsList(Boolean(opts.json));
|
|
190
|
-
});
|
|
191
|
-
skills
|
|
192
|
-
.command("info")
|
|
193
|
-
.argument("<name>")
|
|
194
|
-
.option("--json", "Machine-readable JSON output")
|
|
195
|
-
.description("Show details of a skill")
|
|
196
|
-
.action(async (name, opts) => {
|
|
197
|
-
await runSkillsInfo(name, Boolean(opts.json));
|
|
198
|
-
});
|
|
199
|
-
skills
|
|
200
|
-
.command("new")
|
|
201
|
-
.argument("<name>")
|
|
202
|
-
.description("Create a new skill scaffold (use --global on `min-agent` for ~/.agents/skills/)")
|
|
203
|
-
.action(async (name) => {
|
|
204
|
-
await runSkillsNew(name, Boolean(rootOpts().global));
|
|
205
|
-
});
|
|
206
|
-
skills
|
|
207
|
-
.command("enable")
|
|
208
|
-
.argument("<names...>")
|
|
209
|
-
.description("Enable disabled skills (use --project to target this project only)")
|
|
210
|
-
.action(async (names) => {
|
|
211
|
-
await runSkillsToggle(names, true, resolveScope(rootOpts()));
|
|
212
|
-
});
|
|
213
|
-
skills
|
|
214
|
-
.command("disable")
|
|
215
|
-
.argument("<names...>")
|
|
216
|
-
.description("Disable skills (use --project to target this project only)")
|
|
217
|
-
.action(async (names) => {
|
|
218
|
-
await runSkillsToggle(names, false, resolveScope(rootOpts()));
|
|
219
|
-
});
|
|
220
|
-
// --- Operations -----------------------------------------------------------
|
|
221
|
-
program
|
|
222
|
-
.command("serve")
|
|
223
|
-
.description("Start the HTTP API (see docs/API.md)")
|
|
224
|
-
.option("--host <host>", "Bind host")
|
|
225
|
-
.addOption(new Option("--port <port>", "Bind port").argParser(parsePositiveIntArg("--port")))
|
|
226
|
-
.action(async (opts) => {
|
|
227
|
-
await runServeCommand(opts);
|
|
228
|
-
});
|
|
229
|
-
const history = program.command("history").description("Manage saved sessions");
|
|
230
|
-
history.action(runHistoryList);
|
|
231
|
-
history.command("delete").argument("<id>").description("Delete a saved session").action(runHistoryDelete);
|
|
232
|
-
history
|
|
233
|
-
.command("rename")
|
|
234
|
-
.argument("<id>")
|
|
235
|
-
.argument("<title...>")
|
|
236
|
-
.description("Rename a saved session")
|
|
237
|
-
.action(async (id, title) => {
|
|
238
|
-
await runHistoryRename(id, title);
|
|
239
|
-
});
|
|
240
|
-
history
|
|
241
|
-
.command("export")
|
|
242
|
-
.argument("<id>")
|
|
243
|
-
.option("-o, --output <file>", "Write to a file instead of stdout")
|
|
244
|
-
.description("Export a session as JSON")
|
|
245
|
-
.action(async (id, opts) => {
|
|
246
|
-
await runHistoryExport(id, opts);
|
|
247
|
-
});
|
|
248
|
-
program.command("update").description("Upgrade to the latest npm release").action(runUpdateCommand);
|
|
249
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { existsSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
function ensureProjectDefaults() {
|
|
4
|
-
const projectConfigDir = path.join(process.cwd(), ".min-agent");
|
|
5
|
-
const projectSkillsDir = path.join(projectConfigDir, "skills");
|
|
6
|
-
const projectMcpFile = path.join(projectConfigDir, "mcp.json");
|
|
7
|
-
if (!existsSync(projectSkillsDir)) {
|
|
8
|
-
mkdirSync(projectSkillsDir, { recursive: true });
|
|
9
|
-
}
|
|
10
|
-
if (!existsSync(projectMcpFile)) {
|
|
11
|
-
mkdirSync(projectConfigDir, { recursive: true });
|
|
12
|
-
writeFileSync(projectMcpFile, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export async function runInitCommand() {
|
|
16
|
-
ensureProjectDefaults();
|
|
17
|
-
console.log(`✓ Initialized .min-agent/ in ${process.cwd()}`);
|
|
18
|
-
}
|