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/cli/exec-prompt.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the final prompt text for `min-agent exec`, combining positional
|
|
3
|
-
* arguments with piped stdin according to these rules:
|
|
4
|
-
* - `exec -` reads the entire prompt from stdin.
|
|
5
|
-
* - `exec` (no args) requires piped stdin (non-TTY); errors otherwise.
|
|
6
|
-
* - `exec <msg>` + pipe appends piped stdin after the message.
|
|
7
|
-
* - `exec <msg>` uses the message as-is.
|
|
8
|
-
*/
|
|
9
|
-
export function resolveExecPrompt(positionals, stdinText, stdinIsTty) {
|
|
10
|
-
const joined = positionals.join(" ");
|
|
11
|
-
const piped = stdinText.length > 0;
|
|
12
|
-
if (joined === "-") {
|
|
13
|
-
const prompt = stdinText;
|
|
14
|
-
if (!prompt.trim())
|
|
15
|
-
return { ok: false, error: "Usage: min-agent exec <message>" };
|
|
16
|
-
return { ok: true, prompt };
|
|
17
|
-
}
|
|
18
|
-
if (!joined) {
|
|
19
|
-
if (stdinIsTty || !piped)
|
|
20
|
-
return { ok: false, error: "Usage: min-agent exec <message>" };
|
|
21
|
-
return { ok: true, prompt: stdinText };
|
|
22
|
-
}
|
|
23
|
-
if (piped && !stdinIsTty)
|
|
24
|
-
return { ok: true, prompt: `${joined}\n\n${stdinText}` };
|
|
25
|
-
return { ok: true, prompt: joined };
|
|
26
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { Option } from "commander";
|
|
2
|
-
import { parseNetworkPolicy, parseSandboxMode } from "../sandbox.js";
|
|
3
|
-
import { parsePermissionMode, parseThinkingEffort, parseMemoryMode, } from "../config.js";
|
|
4
|
-
import { userError } from "./errors.js";
|
|
5
|
-
/** Reusable --project / --global mutually exclusive scope selector. */
|
|
6
|
-
export function scopeOptions() {
|
|
7
|
-
return [
|
|
8
|
-
new Option("--project", "Apply to this project only (.min-agent/config.json)").conflicts("global"),
|
|
9
|
-
new Option("--global", "Apply to every project (~/.min-agent/config.json)").conflicts("project"),
|
|
10
|
-
];
|
|
11
|
-
}
|
|
12
|
-
/** Resolve --project/--global into a Scope, given an optional fallback. */
|
|
13
|
-
export function resolveScope(opts, fallback = "global") {
|
|
14
|
-
if (opts.project)
|
|
15
|
-
return "project";
|
|
16
|
-
if (opts.global)
|
|
17
|
-
return "global";
|
|
18
|
-
return fallback;
|
|
19
|
-
}
|
|
20
|
-
export function parseSandboxModeArg(value) {
|
|
21
|
-
const parsed = parseSandboxMode(value);
|
|
22
|
-
if (!parsed)
|
|
23
|
-
throw userError(`Invalid --sandbox value: "${value}"`, "use one of: off, workspace, strict");
|
|
24
|
-
return parsed;
|
|
25
|
-
}
|
|
26
|
-
export function parseNetworkPolicyArg(value) {
|
|
27
|
-
const parsed = parseNetworkPolicy(value);
|
|
28
|
-
if (!parsed)
|
|
29
|
-
throw userError(`Invalid --network value: "${value}"`, "use one of: allow, deny");
|
|
30
|
-
return parsed;
|
|
31
|
-
}
|
|
32
|
-
export function parsePermissionModeArg(value) {
|
|
33
|
-
const parsed = parsePermissionMode(value);
|
|
34
|
-
if (!parsed)
|
|
35
|
-
throw userError(`Invalid --permission value: "${value}"`, "use one of: ask, accept-edits, allow-all");
|
|
36
|
-
return parsed;
|
|
37
|
-
}
|
|
38
|
-
export function parseThinkingEffortArg(value) {
|
|
39
|
-
const parsed = parseThinkingEffort(value);
|
|
40
|
-
if (!parsed)
|
|
41
|
-
throw userError(`Invalid --think value: "${value}"`, "use one of: off, low, medium, high, max");
|
|
42
|
-
return parsed;
|
|
43
|
-
}
|
|
44
|
-
export function parseMemoryModeArg(value) {
|
|
45
|
-
const parsed = parseMemoryMode(value);
|
|
46
|
-
if (!parsed)
|
|
47
|
-
throw userError(`Invalid --memory value: "${value}"`, "use one of: on, off");
|
|
48
|
-
return parsed;
|
|
49
|
-
}
|
|
50
|
-
export function parsePortArg(value) {
|
|
51
|
-
const n = Number.parseInt(value, 10);
|
|
52
|
-
if (!Number.isFinite(n) || n <= 0 || n > 65535) {
|
|
53
|
-
throw userError(`Invalid --port value: "${value}"`, "use an integer between 1 and 65535");
|
|
54
|
-
}
|
|
55
|
-
return n;
|
|
56
|
-
}
|
|
57
|
-
export function parsePositiveIntArg(flagName) {
|
|
58
|
-
return (value) => {
|
|
59
|
-
const n = Number.parseInt(value, 10);
|
|
60
|
-
if (!Number.isFinite(n) || n <= 0) {
|
|
61
|
-
throw userError(`Invalid ${flagName} value: "${value}"`, "use a positive integer");
|
|
62
|
-
}
|
|
63
|
-
return n;
|
|
64
|
-
};
|
|
65
|
-
}
|
package/dist/cli/program.js
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { Command, Option } from "commander";
|
|
2
|
-
import { setAutoApprove } from "../confirm.js";
|
|
3
|
-
import { CliError, formatCliError, exitCodeFor } from "./errors.js";
|
|
4
|
-
import { parseNetworkPolicyArg, parsePermissionModeArg, parseSandboxModeArg, parseThinkingEffortArg, parseMemoryModeArg, } from "./option-helpers.js";
|
|
5
|
-
import { localVersion } from "../updater.js";
|
|
6
|
-
function collectImage(value, previous) {
|
|
7
|
-
return [...previous, value];
|
|
8
|
-
}
|
|
9
|
-
/** Options shared across the root command and `exec` (session-affecting flags). */
|
|
10
|
-
export function addSessionOptions(cmd) {
|
|
11
|
-
return cmd
|
|
12
|
-
.option("-m, --model <model>", "Override model for this request")
|
|
13
|
-
.option("--provider <name>", "Use a specific configured provider")
|
|
14
|
-
.option("--resume <id>", "Resume a previous session by id")
|
|
15
|
-
.option("-i, --image <path>", "Attach an image (repeatable)", collectImage, [])
|
|
16
|
-
.addOption(new Option("--sandbox <mode>", "Isolation mode (off, workspace, strict)").argParser(parseSandboxModeArg))
|
|
17
|
-
.addOption(new Option("--network <policy>", "Network policy (allow, deny)").argParser(parseNetworkPolicyArg))
|
|
18
|
-
.addOption(new Option("--permission <mode>", "Confirmation mode (ask, accept-edits, allow-all)").argParser(parsePermissionModeArg))
|
|
19
|
-
.addOption(new Option("--think <level>", "Thinking intensity (off, low, medium, high, max)").argParser(parseThinkingEffortArg))
|
|
20
|
-
.addOption(new Option("--memory <mode>", "Memory across sessions (on, off; default off)").argParser(parseMemoryModeArg))
|
|
21
|
-
.option("--project", "Write --permission/--sandbox/--think/--memory to this repo's config")
|
|
22
|
-
.option("--global", "Write --permission/--sandbox/--think/--memory to the global config")
|
|
23
|
-
.option("-y, --yes", "This session only: same as --permission allow-all");
|
|
24
|
-
}
|
|
25
|
-
export function buildProgram() {
|
|
26
|
-
const program = new Command("min-agent");
|
|
27
|
-
program
|
|
28
|
-
.description("min-agent - Minimal AI coding agent")
|
|
29
|
-
.version(localVersion(), "-v, --version", "Show version number")
|
|
30
|
-
.helpOption("-h, --help", "Show help")
|
|
31
|
-
.allowUnknownOption()
|
|
32
|
-
.enablePositionalOptions()
|
|
33
|
-
.configureOutput({
|
|
34
|
-
writeErr: (str) => process.stderr.write(str),
|
|
35
|
-
outputError: (str) => process.stderr.write(str),
|
|
36
|
-
})
|
|
37
|
-
.exitOverride();
|
|
38
|
-
addSessionOptions(program);
|
|
39
|
-
program.argument("[prompt...]", "Prompt to send in an interactive session");
|
|
40
|
-
program.addHelpText("after", `
|
|
41
|
-
Session:
|
|
42
|
-
min-agent Start interactive session
|
|
43
|
-
min-agent <message> Start interactive session and send message
|
|
44
|
-
min-agent --resume <id> Resume a previous interactive session
|
|
45
|
-
min-agent chat | code Same as interactive session (compat)
|
|
46
|
-
min-agent exec <message> Run one message non-interactively
|
|
47
|
-
min-agent exec --resume <id> <msg> Continue a saved exec session
|
|
48
|
-
|
|
49
|
-
Setup & config:
|
|
50
|
-
min-agent setup [--type T] Configure providers (interactively, or with flags)
|
|
51
|
-
min-agent init Initialize .min-agent/ in current directory
|
|
52
|
-
min-agent models List available models
|
|
53
|
-
min-agent rules [edit] Show or edit instruction rules
|
|
54
|
-
min-agent memory [on|off] Show or set memory (off by default)
|
|
55
|
-
min-agent memory <add|search|delete> Manage saved memories
|
|
56
|
-
min-agent sandbox [off|workspace|strict] Show or set isolation mode
|
|
57
|
-
min-agent sandbox network <allow|deny> Show or set network policy
|
|
58
|
-
min-agent permission [ask|accept-edits|allow-all] Show or set confirmation mode
|
|
59
|
-
min-agent think [off|low|medium|high|max] Show or set thinking intensity
|
|
60
|
-
min-agent ctx [2k|4k|8k|12k|16k|32k|64k|128k|256k|auto] Show or set Ollama context window
|
|
61
|
-
|
|
62
|
-
Integrations:
|
|
63
|
-
min-agent mcp <list|add|remove|info|check|enable|disable> Manage MCP servers
|
|
64
|
-
min-agent skills <list|info|new|enable|disable> Manage skills
|
|
65
|
-
|
|
66
|
-
Operations:
|
|
67
|
-
min-agent serve [--host H] [--port P] Start the HTTP API (see docs/API.md)
|
|
68
|
-
min-agent history [delete|rename|export] Manage saved sessions
|
|
69
|
-
min-agent update Upgrade to the latest npm release
|
|
70
|
-
|
|
71
|
-
Confirmation modes (default: ask; independent of isolation):
|
|
72
|
-
ask Prompt before dangerous operations
|
|
73
|
-
accept-edits Auto-approve file writes; still prompt for dangerous commands
|
|
74
|
-
allow-all Auto-approve everything
|
|
75
|
-
|
|
76
|
-
Thinking intensity (default: medium):
|
|
77
|
-
off Disable thinking
|
|
78
|
-
low Light reasoning
|
|
79
|
-
medium Standard reasoning
|
|
80
|
-
high Strong reasoning
|
|
81
|
-
max Highest reasoning
|
|
82
|
-
|
|
83
|
-
Ollama context window:
|
|
84
|
-
2k … 256k Loaded window size
|
|
85
|
-
auto Use the model's default
|
|
86
|
-
|
|
87
|
-
Memory (default: off):
|
|
88
|
-
off Do not inject memories or expose memory tools
|
|
89
|
-
on Remember facts across sessions
|
|
90
|
-
|
|
91
|
-
Isolation modes (default: off; independent of confirmation):
|
|
92
|
-
off No sandboxing
|
|
93
|
-
workspace Restrict file writes to the project workspace
|
|
94
|
-
strict Restrict file writes and deny risky commands
|
|
95
|
-
Env: MIN_AGENT_SANDBOX, MIN_AGENT_SANDBOX_NETWORK
|
|
96
|
-
|
|
97
|
-
Rules (loaded as system instructions):
|
|
98
|
-
Global: ~/.min-agent/rules.md
|
|
99
|
-
Project: ./AGENTS.md or ./RULES.md or ./.min-agent/AGENTS.md
|
|
100
|
-
Config: "instructions" array in ~/.min-agent/config.json
|
|
101
|
-
|
|
102
|
-
Examples:
|
|
103
|
-
min-agent setup
|
|
104
|
-
min-agent setup --type ollama
|
|
105
|
-
min-agent
|
|
106
|
-
min-agent "hello"
|
|
107
|
-
min-agent exec "hello"
|
|
108
|
-
min-agent exec --resume <id> "continue"
|
|
109
|
-
min-agent --resume <id>
|
|
110
|
-
min-agent --permission ask
|
|
111
|
-
min-agent --think max
|
|
112
|
-
min-agent --memory on
|
|
113
|
-
min-agent serve --port 8787
|
|
114
|
-
min-agent update
|
|
115
|
-
min-agent rules edit
|
|
116
|
-
min-agent mcp add filesystem npx -y @modelcontextprotocol/server-filesystem /tmp
|
|
117
|
-
min-agent mcp add remote --url https://example.com/mcp --token "$TOKEN"
|
|
118
|
-
`);
|
|
119
|
-
return program;
|
|
120
|
-
}
|
|
121
|
-
/** Apply --yes/-y for this process. Sandbox/permission overrides are applied per-invocation-kind. */
|
|
122
|
-
export function applySessionOverrides(opts) {
|
|
123
|
-
if (opts.yes)
|
|
124
|
-
setAutoApprove(true);
|
|
125
|
-
}
|
|
126
|
-
export async function applySessionRuntimeOverrides(opts) {
|
|
127
|
-
if (opts.sandbox !== undefined || opts.network !== undefined) {
|
|
128
|
-
const { setSandboxOverride } = await import("../sandbox.js");
|
|
129
|
-
if (opts.sandbox !== undefined)
|
|
130
|
-
setSandboxOverride({ mode: opts.sandbox });
|
|
131
|
-
if (opts.network !== undefined)
|
|
132
|
-
setSandboxOverride({ network: opts.network });
|
|
133
|
-
}
|
|
134
|
-
if (opts.permission !== undefined) {
|
|
135
|
-
const { setPermissionOverride } = await import("../confirm.js");
|
|
136
|
-
setPermissionOverride(opts.permission);
|
|
137
|
-
}
|
|
138
|
-
if (opts.think !== undefined) {
|
|
139
|
-
const { setThinkingOverride } = await import("../thinking.js");
|
|
140
|
-
setThinkingOverride(opts.think);
|
|
141
|
-
}
|
|
142
|
-
if (opts.memory !== undefined) {
|
|
143
|
-
const { setMemoryOverride } = await import("../memory.js");
|
|
144
|
-
setMemoryOverride(opts.memory);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
export function hasSessionIntent(opts, prompt) {
|
|
148
|
-
return (prompt.length > 0 || Boolean(opts.resume) || opts.image.length > 0 || Boolean(opts.model) || Boolean(opts.provider));
|
|
149
|
-
}
|
|
150
|
-
/** Extract `--unknown` style tokens left over in positionals (from allowUnknownOption) as errors. */
|
|
151
|
-
export function extractUnknownOptionErrors(positionals) {
|
|
152
|
-
const rest = [];
|
|
153
|
-
const errors = [];
|
|
154
|
-
for (const p of positionals) {
|
|
155
|
-
if (p.startsWith("--"))
|
|
156
|
-
errors.push(`Unknown option: ${p}`);
|
|
157
|
-
else
|
|
158
|
-
rest.push(p);
|
|
159
|
-
}
|
|
160
|
-
return { rest, errors };
|
|
161
|
-
}
|
|
162
|
-
async function runRootAction(promptTokens, opts) {
|
|
163
|
-
applySessionOverrides(opts);
|
|
164
|
-
const { rest, errors } = extractUnknownOptionErrors(promptTokens);
|
|
165
|
-
const sessionIntent = hasSessionIntent(opts, rest);
|
|
166
|
-
const wantsConfigWrite = opts.sandbox !== undefined ||
|
|
167
|
-
opts.network !== undefined ||
|
|
168
|
-
opts.permission !== undefined ||
|
|
169
|
-
opts.think !== undefined ||
|
|
170
|
-
opts.memory !== undefined;
|
|
171
|
-
if (wantsConfigWrite && !sessionIntent) {
|
|
172
|
-
const { runWriteConfig } = await import("./commands/write-config.js");
|
|
173
|
-
await runWriteConfig({
|
|
174
|
-
sandbox: opts.sandbox,
|
|
175
|
-
network: opts.network,
|
|
176
|
-
permission: opts.permission,
|
|
177
|
-
think: opts.think,
|
|
178
|
-
memory: opts.memory,
|
|
179
|
-
scope: opts.project ? "project" : opts.global ? "global" : undefined,
|
|
180
|
-
});
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
await applySessionRuntimeOverrides(opts);
|
|
184
|
-
if (errors.length > 0) {
|
|
185
|
-
console.error(errors[0]);
|
|
186
|
-
process.exitCode = 1;
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
const { startTuiSession } = await import("./commands/shared.js");
|
|
190
|
-
await startTuiSession({
|
|
191
|
-
model: opts.model,
|
|
192
|
-
provider: opts.provider,
|
|
193
|
-
resume: opts.resume,
|
|
194
|
-
images: opts.image,
|
|
195
|
-
positionals: rest,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
export async function runProgram(argv, registerCommands) {
|
|
199
|
-
const program = buildProgram();
|
|
200
|
-
program.action((promptTokens, opts) => runRootAction(promptTokens, opts));
|
|
201
|
-
registerCommands(program);
|
|
202
|
-
try {
|
|
203
|
-
await program.parseAsync(argv, { from: "user" });
|
|
204
|
-
}
|
|
205
|
-
catch (err) {
|
|
206
|
-
if (err instanceof CliError) {
|
|
207
|
-
console.error(formatCliError(err));
|
|
208
|
-
process.exitCode = exitCodeFor(err);
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
// Commander throws a CommanderError for --help/--version and for its own
|
|
212
|
-
// usage errors; those already printed output and set process.exitCode.
|
|
213
|
-
if (isCommanderExit(err)) {
|
|
214
|
-
process.exitCode = err.exitCode;
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
console.error(formatCliError(err));
|
|
218
|
-
process.exitCode = 2;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
function isCommanderExit(err) {
|
|
222
|
-
return typeof err === "object" && err !== null && "exitCode" in err && "code" in err;
|
|
223
|
-
}
|
package/dist/cli/setup/detect.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { normalizeOllamaBaseURL } from "../../config.js";
|
|
2
|
-
const DEFAULT_TAGS_URL = "http://localhost:11434/api/tags";
|
|
3
|
-
const DEFAULT_TIMEOUT_MS = 800;
|
|
4
|
-
const DEFAULT_BASE = "http://localhost:11434/v1";
|
|
5
|
-
export async function detectLocalOllama(opts) {
|
|
6
|
-
const fetchImpl = opts?.fetchImpl ?? fetch;
|
|
7
|
-
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
8
|
-
try {
|
|
9
|
-
const response = await fetchImpl(DEFAULT_TAGS_URL, { signal: AbortSignal.timeout(timeoutMs) });
|
|
10
|
-
if (!response.ok)
|
|
11
|
-
return { found: false };
|
|
12
|
-
return { found: true, baseURL: normalizeOllamaBaseURL(DEFAULT_BASE) };
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
return { found: false };
|
|
16
|
-
}
|
|
17
|
-
}
|
package/dist/cli/setup/flags.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { userError } from "../errors.js";
|
|
2
|
-
export function parseProviderType(value) {
|
|
3
|
-
if (value === "openai-compatible" || value === "openai" || value === "ollama")
|
|
4
|
-
return value;
|
|
5
|
-
throw userError(`Invalid --type value: "${value}"`, "use one of: openai-compatible, openai, ollama");
|
|
6
|
-
}
|
|
7
|
-
export function isNonInteractive(flags) {
|
|
8
|
-
return Boolean(flags.type || flags.switch || flags.remove);
|
|
9
|
-
}
|
|
10
|
-
export function exclusiveActionCount(flags) {
|
|
11
|
-
return [flags.type, flags.switch, flags.remove].filter(Boolean).length;
|
|
12
|
-
}
|
package/dist/cli/setup/flow.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { getActiveProvider, normalizeOllamaBaseURL } from "../../config.js";
|
|
2
|
-
import { CliError, runtimeError } from "../errors.js";
|
|
3
|
-
import { applyAddProvider, applyRemoveProvider, applySwitchProvider, suggestName, } from "./provider-form.js";
|
|
4
|
-
import { exclusiveActionCount } from "./flags.js";
|
|
5
|
-
const OPENAI_URL = "https://api.openai.com/v1";
|
|
6
|
-
const OLLAMA_URL = "http://localhost:11434/v1";
|
|
7
|
-
const NON_INTERACTIVE_HINT = "使用 --type、--switch 或 --remove。例如: min-agent setup --type ollama";
|
|
8
|
-
export function shouldOfferSetupWizard(configured, isTty) {
|
|
9
|
-
return !configured && isTty;
|
|
10
|
-
}
|
|
11
|
-
export async function runSetup(flags, deps, wizardMode) {
|
|
12
|
-
if (exclusiveActionCount(flags) > 1) {
|
|
13
|
-
throw new CliError("一次只能执行一种操作。");
|
|
14
|
-
}
|
|
15
|
-
if (flags.remove) {
|
|
16
|
-
await runRemove(flags.remove, flags.yes === true, deps);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (flags.switch) {
|
|
20
|
-
persist(applySwitchProvider(deps.load(), flags.switch), deps);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (flags.type) {
|
|
24
|
-
await runAdd(flags, deps);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (!deps.isTty) {
|
|
28
|
-
throw new CliError("无法在非交互环境完成配置。", { hint: NON_INTERACTIVE_HINT });
|
|
29
|
-
}
|
|
30
|
-
const config = deps.load();
|
|
31
|
-
const mode = wizardMode ?? (hasUsableProvider(config) ? "hub" : "first-run");
|
|
32
|
-
await deps.runWizard(mode);
|
|
33
|
-
}
|
|
34
|
-
function hasUsableProvider(config) {
|
|
35
|
-
const provider = getActiveProvider(config);
|
|
36
|
-
return Boolean(provider?.baseURL && provider?.apiKey);
|
|
37
|
-
}
|
|
38
|
-
async function runRemove(name, yes, deps) {
|
|
39
|
-
if (!yes) {
|
|
40
|
-
throw new CliError("删除需要确认。", { hint: "加上 --yes" });
|
|
41
|
-
}
|
|
42
|
-
persist(applyRemoveProvider(deps.load(), name), deps);
|
|
43
|
-
}
|
|
44
|
-
async function runAdd(flags, deps) {
|
|
45
|
-
const type = flags.type;
|
|
46
|
-
const baseURL = resolveBaseURL(type, flags.url);
|
|
47
|
-
const apiKey = resolveApiKey(type, flags.apiKey);
|
|
48
|
-
const defaultModel = await resolveDefaultModel(type, baseURL, apiKey, flags.defaultModel, deps.fetchLive);
|
|
49
|
-
const config = deps.load();
|
|
50
|
-
const existing = (config.providers ?? []).map((p) => p.name).filter((name) => Boolean(name));
|
|
51
|
-
const name = (flags.name?.trim() || suggestName(type, baseURL, existing)).trim();
|
|
52
|
-
const draft = {
|
|
53
|
-
name,
|
|
54
|
-
type,
|
|
55
|
-
baseURL,
|
|
56
|
-
apiKey,
|
|
57
|
-
defaultModel,
|
|
58
|
-
...(flags.contextWindow != null ? { contextWindow: flags.contextWindow } : {}),
|
|
59
|
-
};
|
|
60
|
-
const overwrite = flags.yes === true;
|
|
61
|
-
const result = applyAddProvider(config, draft, { overwrite });
|
|
62
|
-
if (isApplyError(result) && result.error.startsWith("已存在同名服务商") && !overwrite) {
|
|
63
|
-
throw new CliError(result.error, { hint: "加上 --yes 以覆盖" });
|
|
64
|
-
}
|
|
65
|
-
persist(result, deps);
|
|
66
|
-
}
|
|
67
|
-
function resolveBaseURL(type, url) {
|
|
68
|
-
if (type === "openai")
|
|
69
|
-
return OPENAI_URL;
|
|
70
|
-
if (type === "ollama")
|
|
71
|
-
return normalizeOllamaBaseURL(url?.trim() || OLLAMA_URL);
|
|
72
|
-
const trimmed = url?.trim() ?? "";
|
|
73
|
-
if (!trimmed)
|
|
74
|
-
throw new CliError("API 地址不能为空。");
|
|
75
|
-
return trimmed.replace(/\/$/, "");
|
|
76
|
-
}
|
|
77
|
-
function resolveApiKey(type, apiKey) {
|
|
78
|
-
if (type === "ollama")
|
|
79
|
-
return apiKey?.trim() || "ollama";
|
|
80
|
-
const trimmed = apiKey?.trim() ?? "";
|
|
81
|
-
if (!trimmed)
|
|
82
|
-
throw new CliError("API 密钥不能为空。");
|
|
83
|
-
return trimmed;
|
|
84
|
-
}
|
|
85
|
-
async function resolveDefaultModel(type, baseURL, apiKey, explicit, fetchLive) {
|
|
86
|
-
const given = explicit?.trim() ?? "";
|
|
87
|
-
if (given)
|
|
88
|
-
return given;
|
|
89
|
-
const live = await fetchLive(baseURL, apiKey);
|
|
90
|
-
if (live.models[0])
|
|
91
|
-
return live.models[0];
|
|
92
|
-
if (type === "ollama")
|
|
93
|
-
return "llama3";
|
|
94
|
-
if (!live.ok && live.status == null) {
|
|
95
|
-
throw runtimeError("无法连接到该服务商。");
|
|
96
|
-
}
|
|
97
|
-
throw new CliError("默认模型不能为空。");
|
|
98
|
-
}
|
|
99
|
-
function persist(result, deps) {
|
|
100
|
-
if (isApplyError(result))
|
|
101
|
-
throw new CliError(result.error);
|
|
102
|
-
deps.save(result);
|
|
103
|
-
deps.log(`已保存到 ${deps.configPath()}`);
|
|
104
|
-
}
|
|
105
|
-
function isApplyError(result) {
|
|
106
|
-
return Object.keys(result).length === 1 && "error" in result;
|
|
107
|
-
}
|
|
108
|
-
export { isNonInteractive } from "./flags.js";
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
export function suggestName(type, baseURL, existing) {
|
|
2
|
-
const base = type === "openai" ? "openai" : type === "ollama" ? "ollama" : (hostSlug(baseURL) ?? "provider");
|
|
3
|
-
return uniqueName(base, existing);
|
|
4
|
-
}
|
|
5
|
-
export function validateProviderName(name) {
|
|
6
|
-
const trimmed = name.trim();
|
|
7
|
-
if (!trimmed || trimmed.includes("/") || trimmed.includes(":")) {
|
|
8
|
-
return "名称不能为空,且不能包含 / 或 :。";
|
|
9
|
-
}
|
|
10
|
-
return null;
|
|
11
|
-
}
|
|
12
|
-
export function maskApiKey(key) {
|
|
13
|
-
if (key.length < 4)
|
|
14
|
-
return "****";
|
|
15
|
-
return `…${key.slice(-4)}`;
|
|
16
|
-
}
|
|
17
|
-
export function filterChoices(query, items) {
|
|
18
|
-
const q = query.trim().toLowerCase();
|
|
19
|
-
if (!q)
|
|
20
|
-
return [...items];
|
|
21
|
-
return items.filter((item) => item.toLowerCase().includes(q));
|
|
22
|
-
}
|
|
23
|
-
export function applyAddProvider(config, draft, opts) {
|
|
24
|
-
const nameError = validateProviderName(draft.name);
|
|
25
|
-
if (nameError)
|
|
26
|
-
return { error: nameError };
|
|
27
|
-
const name = draft.name.trim();
|
|
28
|
-
const providers = [...(config.providers ?? [])];
|
|
29
|
-
const idx = providers.findIndex((p) => p.name === name);
|
|
30
|
-
if (idx >= 0 && !opts.overwrite)
|
|
31
|
-
return { error: `已存在同名服务商 "${name}"。` };
|
|
32
|
-
const entry = toProvider(draft, name);
|
|
33
|
-
if (idx >= 0)
|
|
34
|
-
providers[idx] = entry;
|
|
35
|
-
else
|
|
36
|
-
providers.push(entry);
|
|
37
|
-
return { ...config, providers, activeProvider: name };
|
|
38
|
-
}
|
|
39
|
-
export function applySwitchProvider(config, name) {
|
|
40
|
-
const target = (config.providers ?? []).find((p) => p.name === name);
|
|
41
|
-
if (!target)
|
|
42
|
-
return { error: `找不到服务商 "${name}"。` };
|
|
43
|
-
return { ...config, activeProvider: name };
|
|
44
|
-
}
|
|
45
|
-
export function applyUpdateProvider(config, oldName, draft) {
|
|
46
|
-
const nameError = validateProviderName(draft.name);
|
|
47
|
-
if (nameError)
|
|
48
|
-
return { error: nameError };
|
|
49
|
-
const name = draft.name.trim();
|
|
50
|
-
const providers = [...(config.providers ?? [])];
|
|
51
|
-
const idx = providers.findIndex((p) => p.name === oldName);
|
|
52
|
-
if (idx < 0)
|
|
53
|
-
return { error: `找不到服务商 "${oldName}"。` };
|
|
54
|
-
if (name !== oldName && providers.some((p) => p.name === name)) {
|
|
55
|
-
return { error: `已存在同名服务商 "${name}"。` };
|
|
56
|
-
}
|
|
57
|
-
providers[idx] = toProvider(draft, name);
|
|
58
|
-
const activeProvider = config.activeProvider === oldName ? name : config.activeProvider;
|
|
59
|
-
return { ...config, providers, activeProvider };
|
|
60
|
-
}
|
|
61
|
-
export function applyRemoveProvider(config, name) {
|
|
62
|
-
const providers = config.providers ?? [];
|
|
63
|
-
if (!providers.some((p) => p.name === name))
|
|
64
|
-
return { error: `找不到服务商 "${name}"。` };
|
|
65
|
-
const remaining = providers.filter((p) => p.name !== name);
|
|
66
|
-
if (remaining.length === 0) {
|
|
67
|
-
const { activeProvider: _dropped, ...rest } = config;
|
|
68
|
-
return { ...rest, providers: [] };
|
|
69
|
-
}
|
|
70
|
-
const activeProvider = config.activeProvider === name ? remaining[0]?.name : config.activeProvider;
|
|
71
|
-
return { ...config, providers: remaining, activeProvider };
|
|
72
|
-
}
|
|
73
|
-
function toProvider(draft, name) {
|
|
74
|
-
return {
|
|
75
|
-
name,
|
|
76
|
-
type: draft.type,
|
|
77
|
-
baseURL: draft.baseURL,
|
|
78
|
-
apiKey: draft.apiKey,
|
|
79
|
-
defaultModel: draft.defaultModel,
|
|
80
|
-
...(draft.contextWindow != null ? { contextWindow: draft.contextWindow } : {}),
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function hostSlug(baseURL) {
|
|
84
|
-
try {
|
|
85
|
-
const host = new URL(baseURL).hostname.toLowerCase();
|
|
86
|
-
const trimmed = host.startsWith("www.") ? host.slice(4) : host;
|
|
87
|
-
if (!trimmed)
|
|
88
|
-
return undefined;
|
|
89
|
-
return trimmed.replace(/\./g, "-");
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
function uniqueName(base, existing) {
|
|
96
|
-
if (!existing.includes(base))
|
|
97
|
-
return base;
|
|
98
|
-
let n = 2;
|
|
99
|
-
while (existing.includes(`${base}-${n}`))
|
|
100
|
-
n += 1;
|
|
101
|
-
return `${base}-${n}`;
|
|
102
|
-
}
|