micro-models-agent 0.41.2 → 0.42.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/bin/mma.mjs +41 -41
- package/dist/cli/commands.js +19 -9
- package/dist/cli/completer.js +37 -36
- package/dist/cli/index.js +2 -2
- package/dist/cli/main.js +23 -48
- package/dist/cli/repl-commands.js +12 -40
- package/dist/cli/repl.js +87 -217
- package/dist/cli/security-commands.js +7 -5
- package/dist/cli/setup.js +26 -8
- package/dist/config/config.js +5 -52
- package/dist/config/defaults.js +5 -29
- package/dist/config/experts.js +1 -1
- package/dist/config/index.js +3 -3
- package/dist/config/security.js +10 -3
- package/dist/core/agent-moe.js +10 -2
- package/dist/core/agent.js +82 -273
- package/dist/core/bootstrap.js +13 -80
- package/dist/core/index.js +2 -2
- package/dist/core/prompt-builder.js +2 -23
- package/dist/core/session-logger.js +4 -46
- package/dist/i18n/en.json +2 -75
- package/dist/i18n/ru.json +1 -74
- package/dist/index.js +1 -1
- package/dist/llm/image-utils.js +5 -4
- package/dist/llm/index.js +4 -4
- package/dist/llm/model-loader.js +6 -6
- package/dist/llm/openai-compat.js +34 -40
- package/dist/llm/orchestrator.js +29 -33
- package/dist/llm/response.js +9 -9
- package/dist/logger/app-logger.js +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/main.js +299 -55
- package/dist/migration/backup.js +13 -13
- package/dist/migration/detect.js +11 -11
- package/dist/migration/index.js +2 -2
- package/dist/modules/browser/actions.js +4 -34
- package/dist/modules/browser/bridge-server.mjs +202 -202
- package/dist/modules/browser/cookie-store.js +6 -6
- package/dist/modules/browser/index.js +5 -7
- package/dist/modules/browser/module.js +7 -8
- package/dist/modules/browser/session.js +84 -87
- package/dist/modules/browser/snapshot.js +58 -92
- package/dist/modules/browser/types.js +1 -4
- package/dist/modules/certification/cli.js +4 -2
- package/dist/modules/certification/fact-checker.js +3 -1
- package/dist/modules/certification/loader.js +9 -3
- package/dist/modules/certification/runner.js +4 -1
- package/dist/modules/context/index.js +1 -1
- package/dist/modules/context/manager.js +86 -160
- package/dist/modules/execution/auditor.js +25 -177
- package/dist/modules/execution/module.js +544 -201
- package/dist/modules/execution/moe-executor.js +0 -25
- package/dist/modules/execution/plan-store.js +3 -1
- package/dist/modules/execution/plan-validator.js +10 -10
- package/dist/modules/execution/planner.js +1 -6
- package/dist/modules/execution/stuck-detector.js +10 -173
- package/dist/modules/execution/verifier.js +42 -86
- package/dist/modules/hallucination/confidence.js +1 -8
- package/dist/modules/hallucination/detector.js +5 -2
- package/dist/modules/hallucination/factual.js +64 -3
- package/dist/modules/hallucination/index.js +1 -1
- package/dist/modules/hallucination/js-identifiers.js +0 -190
- package/dist/modules/hallucination/llm-judge.js +3 -1
- package/dist/modules/indexer/cache.js +7 -9
- package/dist/modules/indexer/index.js +3 -3
- package/dist/modules/indexer/module.js +42 -95
- package/dist/modules/indexer/walker.js +17 -17
- package/dist/modules/lsp/client.js +31 -74
- package/dist/modules/lsp/config.js +33 -87
- package/dist/modules/lsp/index.js +3 -3
- package/dist/modules/lsp/module.js +21 -185
- package/dist/modules/mcp/module.js +6 -2
- package/dist/modules/memory/index.js +1 -1
- package/dist/modules/memory/module.js +23 -71
- package/dist/modules/memory/search.js +9 -11
- package/dist/modules/memory/store.js +13 -13
- package/dist/modules/pipelines/engine.js +10 -10
- package/dist/modules/pipelines/index.js +3 -3
- package/dist/modules/pipelines/parser.js +14 -17
- package/dist/modules/pipelines/template.js +1 -1
- package/dist/modules/plugins/builtin/lint-on-write.js +16 -21
- package/dist/modules/plugins/builtin/notify.js +2 -3
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/loader.js +17 -59
- package/dist/modules/plugins/manager.js +17 -73
- package/dist/modules/processes/index.js +1 -1
- package/dist/modules/processes/registry.js +46 -135
- package/dist/modules/registry.js +2 -4
- package/dist/modules/security/audit-notifier.js +39 -39
- package/dist/modules/security/command-validator.js +8 -2
- package/dist/modules/security/data-sanitizer.js +9 -1
- package/dist/modules/security/encryption.js +56 -58
- package/dist/modules/security/network-validator.js +9 -1
- package/dist/modules/security/path-validator.js +3 -1
- package/dist/modules/security/security-policies.js +19 -3
- package/dist/modules/security/session-encryption.js +1 -1
- package/dist/modules/security/session-isolation.js +8 -8
- package/dist/modules/session/index.js +3 -3
- package/dist/modules/session/module.js +5 -5
- package/dist/modules/session/store.js +9 -3
- package/dist/modules/skills/module.js +2 -1
- package/dist/modules/updater/checker.js +6 -70
- package/dist/modules/updater/index.js +1 -2
- package/dist/modules/user-profile/compressor.js +2 -2
- package/dist/modules/user-profile/index.js +1 -1
- package/dist/modules/user-profile/profile.js +9 -9
- package/dist/tools/attach-image.js +1 -1
- package/dist/tools/bash.js +19 -178
- package/dist/tools/browser.js +29 -46
- package/dist/tools/executor.js +5 -4
- package/dist/tools/file-info.js +12 -13
- package/dist/tools/filter-tools.js +2 -9
- package/dist/tools/glob-tool.js +11 -11
- package/dist/tools/grep-tool.js +3 -1
- package/dist/tools/index.js +2 -13
- package/dist/tools/list-dir.js +17 -18
- package/dist/tools/load-skill.js +3 -1
- package/dist/tools/path-utils.js +4 -4
- package/dist/tools/pipeline-run.js +25 -25
- package/dist/tools/process-kill.js +11 -11
- package/dist/tools/process-list.js +22 -20
- package/dist/tools/process-log.js +18 -22
- package/dist/tools/question.js +3 -1
- package/dist/tools/read-file.js +2 -10
- package/dist/tools/recall.js +37 -44
- package/dist/tools/registry.js +4 -15
- package/dist/tools/remember.js +29 -29
- package/dist/tools/scope-check.js +9 -9
- package/dist/tools/subagent.js +9 -54
- package/dist/tools/user-input.js +1 -1
- package/dist/tools/web-browse.js +3 -3
- package/dist/tools/web-fetch.js +3 -3
- package/dist/tools/web-search.js +3 -3
- package/dist/tools/write-file.js +3 -1
- package/dist/ui/box.js +5 -1
- package/dist/ui/index.js +6 -6
- package/dist/ui/md-formatter.js +33 -33
- package/dist/ui/output.js +5 -5
- package/dist/ui/renderer.js +10 -15
- package/dist/ui/table.js +1 -1
- package/package.json +48 -48
- package/dist/cli/plugin-commands.js +0 -36
- package/dist/cli/run-result.js +0 -22
- package/dist/core/version.js +0 -24
- package/dist/modules/artifacts/store.js +0 -61
- package/dist/modules/browser/bridge-client.js +0 -199
- package/dist/modules/browser/bridge-path.js +0 -10
- package/dist/modules/browser/driver.js +0 -136
- package/dist/modules/context/chunk-query.js +0 -100
- package/dist/modules/context/fact-extractor.js +0 -162
- package/dist/modules/context/history.js +0 -15
- package/dist/modules/execution/audit-runners.js +0 -152
- package/dist/modules/execution/execution-plugin.js +0 -272
- package/dist/modules/execution/plan-tool.js +0 -508
- package/dist/modules/execution/windows-commands.js +0 -41
- package/dist/modules/indexer/project-profile.js +0 -183
- package/dist/modules/lsp/check-tool.js +0 -58
- package/dist/modules/lsp/command.js +0 -60
- package/dist/modules/lsp/probe.js +0 -76
- package/dist/modules/lsp/project-root.js +0 -32
- package/dist/modules/lsp/startup-check.js +0 -141
- package/dist/modules/processes/detect.js +0 -34
- package/dist/modules/skills/matcher.js +0 -27
- package/dist/modules/updater/module.js +0 -116
- package/dist/tools/chunk-query.js +0 -99
- package/dist/tools/download-file.js +0 -116
- package/dist/tools/enable-tools.js +0 -58
- package/dist/tools/hidden-tools-block.js +0 -37
- package/dist/ui/line-editor.js +0 -703
- package/dist/ui/line-math.js +0 -69
- package/dist/ui/plan-view.js +0 -103
package/bin/mma.mjs
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
|
|
6
|
-
// MMA is designed to run under Bun: clipboard image paste relies on
|
|
7
|
-
// `Bun.Image.fromClipboard()` (Node has no clipboard API), and on Windows a
|
|
8
|
-
// bare `npx.cmd` shim can only be spawned reliably through Bun's child_process
|
|
9
|
-
// (under Node it throws `spawn EINVAL`). The global npm shim (`mma` /
|
|
10
|
-
// `mma.cmd`) launches this file under Node, so re-execute ourselves under Bun
|
|
11
|
-
// when it is available. The `bun run mma` path already runs under Bun and
|
|
12
|
-
// skips the respawn.
|
|
13
|
-
const runningUnderBun =
|
|
14
|
-
typeof globalThis.Bun !== "undefined" &&
|
|
15
|
-
typeof globalThis.Bun?.version !== "undefined";
|
|
16
|
-
|
|
17
|
-
if (process.env.MMA_DEBUG_RUNTIME) {
|
|
18
|
-
console.error(
|
|
19
|
-
"[mma] runtime=" +
|
|
20
|
-
(runningUnderBun ? "bun " + globalThis.Bun.version : "node " + process.version),
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (!runningUnderBun) {
|
|
25
|
-
try {
|
|
26
|
-
const res = spawnSync("bun", [process.argv[1], ...process.argv.slice(2)], {
|
|
27
|
-
stdio: "inherit",
|
|
28
|
-
windowsHide: true,
|
|
29
|
-
});
|
|
30
|
-
if (res.error) throw res.error;
|
|
31
|
-
process.exit(res.status ?? 0);
|
|
32
|
-
} catch {
|
|
33
|
-
// `bun` is not on PATH — fall back to the Node import path (clipboard
|
|
34
|
-
// paste and LSP will degrade, but the agent still works).
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
39
|
-
const main = join(__dirname, "..", "dist", "main.js");
|
|
40
|
-
|
|
41
|
-
await import(pathToFileURL(main).href);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
// MMA is designed to run under Bun: clipboard image paste relies on
|
|
7
|
+
// `Bun.Image.fromClipboard()` (Node has no clipboard API), and on Windows a
|
|
8
|
+
// bare `npx.cmd` shim can only be spawned reliably through Bun's child_process
|
|
9
|
+
// (under Node it throws `spawn EINVAL`). The global npm shim (`mma` /
|
|
10
|
+
// `mma.cmd`) launches this file under Node, so re-execute ourselves under Bun
|
|
11
|
+
// when it is available. The `bun run mma` path already runs under Bun and
|
|
12
|
+
// skips the respawn.
|
|
13
|
+
const runningUnderBun =
|
|
14
|
+
typeof globalThis.Bun !== "undefined" &&
|
|
15
|
+
typeof globalThis.Bun?.version !== "undefined";
|
|
16
|
+
|
|
17
|
+
if (process.env.MMA_DEBUG_RUNTIME) {
|
|
18
|
+
console.error(
|
|
19
|
+
"[mma] runtime=" +
|
|
20
|
+
(runningUnderBun ? "bun " + globalThis.Bun.version : "node " + process.version),
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!runningUnderBun) {
|
|
25
|
+
try {
|
|
26
|
+
const res = spawnSync("bun", [process.argv[1], ...process.argv.slice(2)], {
|
|
27
|
+
stdio: "inherit",
|
|
28
|
+
windowsHide: true,
|
|
29
|
+
});
|
|
30
|
+
if (res.error) throw res.error;
|
|
31
|
+
process.exit(res.status ?? 0);
|
|
32
|
+
} catch {
|
|
33
|
+
// `bun` is not on PATH — fall back to the Node import path (clipboard
|
|
34
|
+
// paste and LSP will degrade, but the agent still works).
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
39
|
+
const main = join(__dirname, "..", "dist", "main.js");
|
|
40
|
+
|
|
41
|
+
await import(pathToFileURL(main).href);
|
package/dist/cli/commands.js
CHANGED
|
@@ -7,11 +7,13 @@ import { join, dirname } from "path";
|
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
import { existsSync, readFileSync } from "fs";
|
|
9
9
|
import { createSecurityCommand } from "./security-commands";
|
|
10
|
-
import { createPluginCommand } from "./plugin-commands";
|
|
11
10
|
import { fileURLToPath } from "url";
|
|
12
11
|
function readVersion() {
|
|
13
12
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
const candidates = [
|
|
13
|
+
const candidates = [
|
|
14
|
+
join(here, "..", "..", "package.json"),
|
|
15
|
+
join(here, "..", "package.json"),
|
|
16
|
+
];
|
|
15
17
|
for (const p of candidates) {
|
|
16
18
|
if (existsSync(p)) {
|
|
17
19
|
try {
|
|
@@ -53,7 +55,9 @@ export function createProgram() {
|
|
|
53
55
|
// Apply security settings from wizard
|
|
54
56
|
if (config.security) {
|
|
55
57
|
config.security.enabled =
|
|
56
|
-
answers.securityBashBlock ||
|
|
58
|
+
answers.securityBashBlock ||
|
|
59
|
+
answers.securityFlagsBlock ||
|
|
60
|
+
!answers.securityPathsDeny;
|
|
57
61
|
config.security.bash.enabled = config.security.enabled;
|
|
58
62
|
config.security.bash.blockDangerousFlags = answers.securityFlagsBlock;
|
|
59
63
|
if (answers.securityBashBlock) {
|
|
@@ -86,7 +90,9 @@ export function createProgram() {
|
|
|
86
90
|
saveConfig(config, configPath);
|
|
87
91
|
console.log(t("cli.config_saved"));
|
|
88
92
|
});
|
|
89
|
-
const configCmd = program
|
|
93
|
+
const configCmd = program
|
|
94
|
+
.command("config")
|
|
95
|
+
.description(t("cli.manage_config"));
|
|
90
96
|
configCmd
|
|
91
97
|
.command("set")
|
|
92
98
|
.argument("<key>", t("cli.config_key"))
|
|
@@ -193,7 +199,9 @@ export function createProgram() {
|
|
|
193
199
|
name,
|
|
194
200
|
providerUrl: cmdOpts.providerUrl,
|
|
195
201
|
providerKey: cmdOpts.providerKey,
|
|
196
|
-
contextWindow: cmdOpts.contextWindow
|
|
202
|
+
contextWindow: cmdOpts.contextWindow
|
|
203
|
+
? parseInt(cmdOpts.contextWindow, 10)
|
|
204
|
+
: undefined,
|
|
197
205
|
tags: parseTags(cmdOpts.tags),
|
|
198
206
|
reps: cmdOpts.reps ? parseInt(cmdOpts.reps, 10) : 3,
|
|
199
207
|
force: cmdOpts.force === true,
|
|
@@ -243,7 +251,9 @@ export function createProgram() {
|
|
|
243
251
|
saveConfig(config, configPath);
|
|
244
252
|
console.log(t("cli.context_set", { size: contextWindow }));
|
|
245
253
|
});
|
|
246
|
-
const provider = program
|
|
254
|
+
const provider = program
|
|
255
|
+
.command("provider")
|
|
256
|
+
.description(t("cli.manage_providers"));
|
|
247
257
|
provider
|
|
248
258
|
.command("list")
|
|
249
259
|
.description(t("cli.list_providers"))
|
|
@@ -263,7 +273,9 @@ export function createProgram() {
|
|
|
263
273
|
saveConfig(config, configPath);
|
|
264
274
|
console.log(t("cli.provider_set", { name }));
|
|
265
275
|
});
|
|
266
|
-
const session = program
|
|
276
|
+
const session = program
|
|
277
|
+
.command("session")
|
|
278
|
+
.description(t("cli.manage_sessions"));
|
|
267
279
|
session
|
|
268
280
|
.command("list")
|
|
269
281
|
.description(t("cli.list_sessions"))
|
|
@@ -311,8 +323,6 @@ export function createProgram() {
|
|
|
311
323
|
});
|
|
312
324
|
// Add security commands
|
|
313
325
|
createSecurityCommand(program);
|
|
314
|
-
// Add plugin commands
|
|
315
|
-
createPluginCommand(program);
|
|
316
326
|
program
|
|
317
327
|
.argument("[prompt...]", "Prompt to execute")
|
|
318
328
|
.description("Run a single prompt")
|
package/dist/cli/completer.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { readdirSync, statSync } from
|
|
2
|
-
import { join } from
|
|
1
|
+
import { readdirSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
3
|
export class SlashCommandProvider {
|
|
4
|
-
name =
|
|
4
|
+
name = 'slash-commands';
|
|
5
5
|
commands;
|
|
6
6
|
constructor(commands) {
|
|
7
7
|
this.commands = commands;
|
|
8
8
|
}
|
|
9
9
|
match(ctx) {
|
|
10
|
-
return ctx.tokenIndex === 0 && ctx.line.startsWith(
|
|
10
|
+
return ctx.tokenIndex === 0 && ctx.line.startsWith('/');
|
|
11
11
|
}
|
|
12
12
|
complete(ctx) {
|
|
13
|
-
return this.commands
|
|
13
|
+
return this.commands
|
|
14
|
+
.filter(c => c.startsWith(ctx.partial.slice(1)))
|
|
15
|
+
.map(c => `/${c}`);
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
export class SubcommandProvider {
|
|
17
|
-
name =
|
|
19
|
+
name = 'subcommands';
|
|
18
20
|
command;
|
|
19
21
|
subcommands;
|
|
20
22
|
constructor(command, subcommands) {
|
|
@@ -25,54 +27,54 @@ export class SubcommandProvider {
|
|
|
25
27
|
return ctx.tokenIndex === 1 && ctx.tokens[0] === `/${this.command}`;
|
|
26
28
|
}
|
|
27
29
|
complete(ctx) {
|
|
28
|
-
return this.subcommands.filter(
|
|
30
|
+
return this.subcommands.filter(s => s.startsWith(ctx.partial));
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
export class ModelArgProvider {
|
|
32
|
-
name =
|
|
34
|
+
name = 'model-args';
|
|
33
35
|
models;
|
|
34
36
|
constructor(models) {
|
|
35
37
|
this.models = models;
|
|
36
38
|
}
|
|
37
39
|
match(ctx) {
|
|
38
|
-
return ctx.tokenIndex === 2 && (ctx.tokens[0] ===
|
|
40
|
+
return ctx.tokenIndex === 2 && (ctx.tokens[0] === '/model' || ctx.tokens[0] === '/config');
|
|
39
41
|
}
|
|
40
42
|
complete(ctx) {
|
|
41
|
-
return this.models.filter(
|
|
43
|
+
return this.models.filter(m => m.startsWith(ctx.partial));
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
export class ConfigKeyProvider {
|
|
45
|
-
name =
|
|
47
|
+
name = 'config-keys';
|
|
46
48
|
keys;
|
|
47
49
|
constructor(keys) {
|
|
48
50
|
this.keys = keys;
|
|
49
51
|
}
|
|
50
52
|
match(ctx) {
|
|
51
|
-
return ctx.tokenIndex >= 1 && ctx.tokens[0] ===
|
|
53
|
+
return ctx.tokenIndex >= 1 && ctx.tokens[0] === '/config' && ctx.tokens[1] === 'set';
|
|
52
54
|
}
|
|
53
55
|
complete(ctx) {
|
|
54
|
-
return this.keys.filter(
|
|
56
|
+
return this.keys.filter(k => k.startsWith(ctx.partial));
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
export class FilePathProvider {
|
|
58
|
-
name =
|
|
60
|
+
name = 'file-paths';
|
|
59
61
|
match(ctx) {
|
|
60
|
-
return ctx.partial.includes(
|
|
62
|
+
return ctx.partial.includes('/') || ctx.partial.includes('\\');
|
|
61
63
|
}
|
|
62
64
|
complete(ctx) {
|
|
63
65
|
try {
|
|
64
66
|
const cwd = process.cwd();
|
|
65
67
|
const partialPath = ctx.partial;
|
|
66
|
-
const lastSlash = Math.max(partialPath.lastIndexOf(
|
|
67
|
-
const dirPath = lastSlash > 0 ? partialPath.slice(0, lastSlash) :
|
|
68
|
-
const prefix = lastSlash > 0 ? partialPath.slice(0, lastSlash + 1) :
|
|
68
|
+
const lastSlash = Math.max(partialPath.lastIndexOf('/'), partialPath.lastIndexOf('\\'));
|
|
69
|
+
const dirPath = lastSlash > 0 ? partialPath.slice(0, lastSlash) : '.';
|
|
70
|
+
const prefix = lastSlash > 0 ? partialPath.slice(0, lastSlash + 1) : '';
|
|
69
71
|
const fullPath = join(cwd, dirPath);
|
|
70
72
|
const entries = readdirSync(fullPath);
|
|
71
73
|
const matches = [];
|
|
72
74
|
for (const entry of entries) {
|
|
73
75
|
const entryPath = join(fullPath, entry);
|
|
74
76
|
const stat = statSync(entryPath);
|
|
75
|
-
const completion = prefix + entry + (stat.isDirectory() ?
|
|
77
|
+
const completion = prefix + entry + (stat.isDirectory() ? '/' : '');
|
|
76
78
|
if (completion.startsWith(ctx.partial)) {
|
|
77
79
|
matches.push(completion);
|
|
78
80
|
}
|
|
@@ -85,60 +87,59 @@ export class FilePathProvider {
|
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
export class ProviderArgProvider {
|
|
88
|
-
name =
|
|
90
|
+
name = 'provider-args';
|
|
89
91
|
providers;
|
|
90
92
|
constructor(providers) {
|
|
91
93
|
this.providers = providers;
|
|
92
94
|
}
|
|
93
95
|
match(ctx) {
|
|
94
|
-
return ctx.tokenIndex === 2 && ctx.tokens[0] ===
|
|
96
|
+
return ctx.tokenIndex === 2 && ctx.tokens[0] === '/provider' && ctx.tokens[1] === 'use';
|
|
95
97
|
}
|
|
96
98
|
complete(ctx) {
|
|
97
|
-
return this.providers.filter(
|
|
99
|
+
return this.providers.filter(p => p.startsWith(ctx.partial));
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
export class SessionNameProvider {
|
|
101
|
-
name =
|
|
103
|
+
name = 'session-names';
|
|
102
104
|
getNames;
|
|
103
105
|
constructor(getNames) {
|
|
104
106
|
this.getNames = getNames;
|
|
105
107
|
}
|
|
106
108
|
match(ctx) {
|
|
107
|
-
return ctx.tokenIndex >= 1 && ctx.tokens[0] ===
|
|
109
|
+
return ctx.tokenIndex >= 1 && ctx.tokens[0] === '/resume';
|
|
108
110
|
}
|
|
109
111
|
complete(ctx) {
|
|
110
112
|
const names = this.getNames();
|
|
111
113
|
if (!ctx.partial)
|
|
112
114
|
return names;
|
|
113
|
-
return names.filter(
|
|
115
|
+
return names.filter(n => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
export class SkillNameProvider {
|
|
117
|
-
name =
|
|
119
|
+
name = 'skill-names';
|
|
118
120
|
skillsModule;
|
|
119
121
|
constructor(skillsModule) {
|
|
120
122
|
this.skillsModule = skillsModule;
|
|
121
123
|
}
|
|
122
124
|
match(ctx) {
|
|
123
|
-
return
|
|
124
|
-
ctx.tokens[
|
|
125
|
-
(ctx.tokens[1] === "load" || ctx.tokens[1] === "unload"));
|
|
125
|
+
return ctx.tokenIndex >= 2 && ctx.tokens[0] === '/skill' &&
|
|
126
|
+
(ctx.tokens[1] === 'load' || ctx.tokens[1] === 'unload');
|
|
126
127
|
}
|
|
127
128
|
complete(ctx) {
|
|
128
129
|
const subcmd = ctx.tokens[1];
|
|
129
|
-
if (subcmd ===
|
|
130
|
+
if (subcmd === 'load') {
|
|
130
131
|
const available = this.skillsModule.getAvailable();
|
|
131
|
-
const names = available.map(
|
|
132
|
+
const names = available.map(s => s.name);
|
|
132
133
|
if (!ctx.partial)
|
|
133
134
|
return names;
|
|
134
|
-
return names.filter(
|
|
135
|
+
return names.filter(n => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
135
136
|
}
|
|
136
|
-
if (subcmd ===
|
|
137
|
+
if (subcmd === 'unload') {
|
|
137
138
|
const loaded = this.skillsModule.getLoaded();
|
|
138
|
-
const names = loaded.map(
|
|
139
|
+
const names = loaded.map(s => s.name);
|
|
139
140
|
if (!ctx.partial)
|
|
140
141
|
return names;
|
|
141
|
-
return names.filter(
|
|
142
|
+
return names.filter(n => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
142
143
|
}
|
|
143
144
|
return [];
|
|
144
145
|
}
|
|
@@ -151,7 +152,7 @@ export class Completer {
|
|
|
151
152
|
complete(line) {
|
|
152
153
|
const cursor = line.length;
|
|
153
154
|
const tokens = line.split(/\s+/);
|
|
154
|
-
const partial = tokens[tokens.length - 1] ||
|
|
155
|
+
const partial = tokens[tokens.length - 1] || '';
|
|
155
156
|
const tokenIndex = tokens.length - 1;
|
|
156
157
|
const ctx = { line, cursor, tokens, partial, tokenIndex };
|
|
157
158
|
for (const provider of this.providers) {
|
package/dist/cli/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { main } from
|
|
2
|
-
export { createProgram } from
|
|
1
|
+
export { main } from './main';
|
|
2
|
+
export { createProgram } from './commands';
|
package/dist/cli/main.js
CHANGED
|
@@ -1,50 +1,15 @@
|
|
|
1
1
|
import { createProgram } from "./commands";
|
|
2
2
|
import { bootstrap } from "../core/bootstrap";
|
|
3
3
|
import { Repl } from "./repl";
|
|
4
|
+
import { formatMarkdown } from "../ui/md-formatter";
|
|
4
5
|
import { Renderer } from "../ui/renderer";
|
|
5
|
-
import { printRunResult } from "./run-result";
|
|
6
6
|
import { runSetup } from "./setup";
|
|
7
7
|
import { saveConfig, loadConfig } from "../config/config";
|
|
8
8
|
import { t } from "../i18n/index";
|
|
9
9
|
import { pc } from "../ui/colors";
|
|
10
|
-
import { existsSync
|
|
11
|
-
import { join
|
|
10
|
+
import { existsSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
12
12
|
import { homedir } from "os";
|
|
13
|
-
import { fileURLToPath } from "url";
|
|
14
|
-
import { UpdaterModule } from "../modules/updater/index";
|
|
15
|
-
function readVersion() {
|
|
16
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
17
|
-
const candidates = [join(here, "..", "..", "package.json"), join(here, "..", "package.json")];
|
|
18
|
-
for (const p of candidates) {
|
|
19
|
-
if (existsSync(p)) {
|
|
20
|
-
try {
|
|
21
|
-
const raw = JSON.parse(readFileSync(p, "utf8"));
|
|
22
|
-
if (raw.version)
|
|
23
|
-
return raw.version;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// fall through
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return "0.0.0";
|
|
31
|
-
}
|
|
32
|
-
/** Fire-and-forget self-update in the background (never blocks startup). */
|
|
33
|
-
function startAutoUpdate(config) {
|
|
34
|
-
try {
|
|
35
|
-
const module = new UpdaterModule(config.updater, readVersion(), "micro-models-agent", {
|
|
36
|
-
info: (m) => process.stderr.write(pc.dim(m) + "\n"),
|
|
37
|
-
warn: (m) => process.stderr.write(pc.yellow(m) + "\n"),
|
|
38
|
-
error: (m) => process.stderr.write(pc.red(m) + "\n"),
|
|
39
|
-
});
|
|
40
|
-
module.start();
|
|
41
|
-
return module;
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// Auto-update is best-effort; never let it crash startup.
|
|
45
|
-
return undefined;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
13
|
async function main() {
|
|
49
14
|
const program = createProgram();
|
|
50
15
|
program.parse(process.argv);
|
|
@@ -61,7 +26,6 @@ async function main() {
|
|
|
61
26
|
if (program.args.length > 0) {
|
|
62
27
|
const prompt = program.args.join(" ");
|
|
63
28
|
const { agent, config } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
|
|
64
|
-
const updater = exitOnComplete ? undefined : startAutoUpdate(config);
|
|
65
29
|
if (jsonMode) {
|
|
66
30
|
const result = await agent.run(prompt);
|
|
67
31
|
agent.shutdown();
|
|
@@ -77,7 +41,6 @@ async function main() {
|
|
|
77
41
|
totalTokens: result.totalTokens ?? null,
|
|
78
42
|
}, null, 2));
|
|
79
43
|
process.stdout.write("\n");
|
|
80
|
-
await updater?.waitForIdle();
|
|
81
44
|
process.exit(result.success ? 0 : 1);
|
|
82
45
|
}
|
|
83
46
|
const renderer = new Renderer({
|
|
@@ -100,10 +63,19 @@ async function main() {
|
|
|
100
63
|
}
|
|
101
64
|
});
|
|
102
65
|
renderer.flush();
|
|
103
|
-
|
|
66
|
+
if (result.success) {
|
|
67
|
+
if (!result.text) {
|
|
68
|
+
console.log(pc.yellow(t("cli.no_output")));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.error(`${t("error.prefix")}${result.error}`);
|
|
73
|
+
if (result.text) {
|
|
74
|
+
console.log(formatMarkdown(result.text));
|
|
75
|
+
}
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
104
78
|
agent.shutdown();
|
|
105
|
-
await updater?.waitForIdle();
|
|
106
|
-
process.exit(exitCode);
|
|
107
79
|
}
|
|
108
80
|
else {
|
|
109
81
|
const configPath = join(homedir(), ".mma", "config.json");
|
|
@@ -112,7 +84,9 @@ async function main() {
|
|
|
112
84
|
const answers = await runSetup();
|
|
113
85
|
const config = loadConfig({
|
|
114
86
|
configDir: join(homedir(), ".mma"),
|
|
115
|
-
projectConfigPath: projectDir
|
|
87
|
+
projectConfigPath: projectDir
|
|
88
|
+
? join(projectDir, ".mmrc")
|
|
89
|
+
: join(process.cwd(), ".mmrc"),
|
|
116
90
|
});
|
|
117
91
|
config.provider.type = answers.provider;
|
|
118
92
|
config.provider.baseUrl = answers.apiBase;
|
|
@@ -123,7 +97,9 @@ async function main() {
|
|
|
123
97
|
config.locale = answers.locale;
|
|
124
98
|
if (config.security) {
|
|
125
99
|
config.security.enabled =
|
|
126
|
-
answers.securityBashBlock ||
|
|
100
|
+
answers.securityBashBlock ||
|
|
101
|
+
answers.securityFlagsBlock ||
|
|
102
|
+
!answers.securityPathsDeny;
|
|
127
103
|
config.security.bash.enabled = config.security.enabled;
|
|
128
104
|
config.security.bash.blockDangerousFlags = answers.securityFlagsBlock;
|
|
129
105
|
if (answers.securityBashBlock) {
|
|
@@ -156,9 +132,8 @@ async function main() {
|
|
|
156
132
|
saveConfig(config, configPath);
|
|
157
133
|
}
|
|
158
134
|
const { agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, logger, } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
await repl.start();
|
|
135
|
+
const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger);
|
|
136
|
+
repl.start();
|
|
162
137
|
}
|
|
163
138
|
}
|
|
164
139
|
main();
|
|
@@ -10,7 +10,10 @@ import { existsSync, readFileSync } from "fs";
|
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
11
|
function readVersion() {
|
|
12
12
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const candidates = [
|
|
13
|
+
const candidates = [
|
|
14
|
+
join(here, "..", "..", "package.json"),
|
|
15
|
+
join(here, "..", "package.json"),
|
|
16
|
+
];
|
|
14
17
|
for (const p of candidates) {
|
|
15
18
|
if (existsSync(p)) {
|
|
16
19
|
try {
|
|
@@ -47,7 +50,6 @@ export const COMMAND_GROUPS = {
|
|
|
47
50
|
rename: "session",
|
|
48
51
|
delete: "session",
|
|
49
52
|
skill: "skill",
|
|
50
|
-
plugins: "agent",
|
|
51
53
|
};
|
|
52
54
|
export function registerAllCommands(ctx) {
|
|
53
55
|
registerBuiltinCommands(ctx);
|
|
@@ -120,7 +122,8 @@ function registerMmaCommands(ctx) {
|
|
|
120
122
|
dataUrl = result.dataUrl;
|
|
121
123
|
label = "clipboard";
|
|
122
124
|
}
|
|
123
|
-
else if (source.startsWith("http://") ||
|
|
125
|
+
else if (source.startsWith("http://") ||
|
|
126
|
+
source.startsWith("https://")) {
|
|
124
127
|
const result = await loadUrlAsDataUrl(source);
|
|
125
128
|
dataUrl = result.dataUrl;
|
|
126
129
|
label = source;
|
|
@@ -181,7 +184,9 @@ function registerMmaCommands(ctx) {
|
|
|
181
184
|
usage: t("repl.reasoning_usage"),
|
|
182
185
|
action: () => {
|
|
183
186
|
ctx.config.showReasoning = !ctx.config.showReasoning;
|
|
184
|
-
const status = ctx.config.showReasoning
|
|
187
|
+
const status = ctx.config.showReasoning
|
|
188
|
+
? pc.green(t("repl.show"))
|
|
189
|
+
: pc.dim(t("repl.hide"));
|
|
185
190
|
console.log(t("repl.reasoning_status", { status }));
|
|
186
191
|
},
|
|
187
192
|
});
|
|
@@ -386,41 +391,6 @@ function registerMmaCommands(ctx) {
|
|
|
386
391
|
console.log(`${t("repl.provider")} ${ctx.config.provider.type} @ ${ctx.config.provider.baseUrl}`);
|
|
387
392
|
},
|
|
388
393
|
});
|
|
389
|
-
ctx.registerCommand({
|
|
390
|
-
name: "plugins",
|
|
391
|
-
description: t("repl.plugins"),
|
|
392
|
-
usage: t("repl.plugins_usage"),
|
|
393
|
-
action: (args) => {
|
|
394
|
-
if (!ctx.pluginManager) {
|
|
395
|
-
console.log(t("cli.plugins.none"));
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
const showAll = args.includes("--all");
|
|
399
|
-
const infos = ctx.pluginManager.getPluginInfos();
|
|
400
|
-
const filtered = showAll ? infos : infos.filter(({ plugin }) => !plugin.isBuiltin);
|
|
401
|
-
if (filtered.length === 0) {
|
|
402
|
-
console.log(t("cli.plugins.none"));
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
const mmaVersion = version;
|
|
406
|
-
console.log(t("cli.plugins.header", {
|
|
407
|
-
count: String(filtered.length),
|
|
408
|
-
mma: mmaVersion,
|
|
409
|
-
}));
|
|
410
|
-
for (const { plugin, source } of filtered) {
|
|
411
|
-
const v = plugin.version || "-";
|
|
412
|
-
const origin = source || "builtin";
|
|
413
|
-
const mark = plugin.isBuiltin ? t("cli.plugins.builtin_mark") : " ";
|
|
414
|
-
console.log(` ${mark} ${plugin.name} v${v} [${origin}]`);
|
|
415
|
-
}
|
|
416
|
-
if (!showAll) {
|
|
417
|
-
const builtinCount = infos.filter(({ plugin }) => plugin.isBuiltin).length;
|
|
418
|
-
if (builtinCount > 0) {
|
|
419
|
-
console.log(pc.dim(` (${builtinCount} builtin hidden — /plugins --all to show)`));
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
},
|
|
423
|
-
});
|
|
424
394
|
}
|
|
425
395
|
function registerSessionCommands(ctx) {
|
|
426
396
|
if (!ctx.sessionManager)
|
|
@@ -589,7 +559,9 @@ function registerSkillCommands(ctx) {
|
|
|
589
559
|
console.log(pc.bold(t("repl.available_skills")));
|
|
590
560
|
for (const skill of available) {
|
|
591
561
|
const tokens = Math.ceil(skill.content.length / 4);
|
|
592
|
-
const loaded = ctx
|
|
562
|
+
const loaded = ctx
|
|
563
|
+
.skillsModule.getLoaded()
|
|
564
|
+
.some((s) => s.name === skill.name);
|
|
593
565
|
const marker = loaded ? pc.green(" [loaded]") : "";
|
|
594
566
|
console.log(` ${pc.cyan(skill.name)}${marker} ${pc.dim(`(${tokens} tokens)`)} ${skill.description.slice(0, 60)}`);
|
|
595
567
|
}
|