micro-models-agent 0.40.0 → 0.41.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/dist/main.js +322 -62
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2072,11 +2072,14 @@ var init_security = __esm(() => {
|
|
|
2072
2072
|
});
|
|
2073
2073
|
|
|
2074
2074
|
// src/modules/lsp/config.ts
|
|
2075
|
-
function
|
|
2075
|
+
function getLanguageForFile(filePath) {
|
|
2076
2076
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
2077
2077
|
if (!ext)
|
|
2078
2078
|
return null;
|
|
2079
|
-
|
|
2079
|
+
return LANGUAGE_MAP[ext] ?? null;
|
|
2080
|
+
}
|
|
2081
|
+
function getServerForFile(filePath, config) {
|
|
2082
|
+
const lang = getLanguageForFile(filePath);
|
|
2080
2083
|
if (!lang)
|
|
2081
2084
|
return null;
|
|
2082
2085
|
return config.servers[lang] ?? null;
|
|
@@ -2122,22 +2125,40 @@ var init_config = __esm(() => {
|
|
|
2122
2125
|
},
|
|
2123
2126
|
json: {
|
|
2124
2127
|
command: "npx",
|
|
2125
|
-
args: [
|
|
2126
|
-
|
|
2128
|
+
args: [
|
|
2129
|
+
"--yes",
|
|
2130
|
+
"--package",
|
|
2131
|
+
"vscode-langservers-extracted",
|
|
2132
|
+
"vscode-json-language-server",
|
|
2133
|
+
"--stdio"
|
|
2134
|
+
],
|
|
2135
|
+
timeout: 30000,
|
|
2127
2136
|
autoInstall: true,
|
|
2128
2137
|
workspaceMarkers: ["package.json"]
|
|
2129
2138
|
},
|
|
2130
2139
|
html: {
|
|
2131
2140
|
command: "npx",
|
|
2132
|
-
args: [
|
|
2133
|
-
|
|
2141
|
+
args: [
|
|
2142
|
+
"--yes",
|
|
2143
|
+
"--package",
|
|
2144
|
+
"vscode-langservers-extracted",
|
|
2145
|
+
"vscode-html-language-server",
|
|
2146
|
+
"--stdio"
|
|
2147
|
+
],
|
|
2148
|
+
timeout: 60000,
|
|
2134
2149
|
autoInstall: true,
|
|
2135
2150
|
workspaceMarkers: ["package.json"]
|
|
2136
2151
|
},
|
|
2137
2152
|
css: {
|
|
2138
2153
|
command: "npx",
|
|
2139
|
-
args: [
|
|
2140
|
-
|
|
2154
|
+
args: [
|
|
2155
|
+
"--yes",
|
|
2156
|
+
"--package",
|
|
2157
|
+
"vscode-langservers-extracted",
|
|
2158
|
+
"vscode-css-language-server",
|
|
2159
|
+
"--stdio"
|
|
2160
|
+
],
|
|
2161
|
+
timeout: 60000,
|
|
2141
2162
|
autoInstall: true,
|
|
2142
2163
|
workspaceMarkers: ["package.json"]
|
|
2143
2164
|
}
|
|
@@ -2449,6 +2470,8 @@ Summary:
|
|
|
2449
2470
|
Command: {command}`,
|
|
2450
2471
|
"proc.promoted_hint": "Command still running after {ms} ms — moved to the background",
|
|
2451
2472
|
"proc.manage_hint": "Check output: process_log id={id}. Stop it: process_kill id={id}. List all: process_list.",
|
|
2473
|
+
"proc.output_preview": `First output:
|
|
2474
|
+
{lines}`,
|
|
2452
2475
|
"proc.none": "No background processes running.",
|
|
2453
2476
|
"proc.not_found": "Process not found: {id}",
|
|
2454
2477
|
"proc.killed": "Process {id} (PID {pid}) killed.",
|
|
@@ -2697,6 +2720,10 @@ Available commands:`,
|
|
|
2697
2720
|
"repl.skills_label": "Skills:",
|
|
2698
2721
|
"repl.plugins_label": "Plugins:",
|
|
2699
2722
|
"repl.mcp_label": "MCP:",
|
|
2723
|
+
"repl.lsp_label": "LSP:",
|
|
2724
|
+
"repl.lsp_timeout": "timeout",
|
|
2725
|
+
"repl.lsp_failed": "did not start",
|
|
2726
|
+
"repl.lsp_unknown": "unknown",
|
|
2700
2727
|
"repl.work_dir": "Dir:",
|
|
2701
2728
|
"repl.agents_label": "Instructions:",
|
|
2702
2729
|
"repl.not_found": "not found",
|
|
@@ -2860,6 +2887,7 @@ Use this knowledge to answer the user's question.`,
|
|
|
2860
2887
|
"ui.success_prefix": "✓ ",
|
|
2861
2888
|
"ui.warning_prefix": "⚠ ",
|
|
2862
2889
|
"ui.thinking": "Thinking…",
|
|
2890
|
+
"ui.step_context": "step {id}: {desc}",
|
|
2863
2891
|
"indexer.map_header": "Project map",
|
|
2864
2892
|
"indexer.top_directories": "Top directories",
|
|
2865
2893
|
"indexer.files": "Files",
|
|
@@ -3075,6 +3103,8 @@ var init_ru = __esm(() => {
|
|
|
3075
3103
|
Команда: {command}`,
|
|
3076
3104
|
"proc.promoted_hint": "Команда всё ещё выполняется через {ms} мс — переведена в фоновый режим",
|
|
3077
3105
|
"proc.manage_hint": "Проверить вывод: process_log id={id}. Остановить: process_kill id={id}. Список всех: process_list.",
|
|
3106
|
+
"proc.output_preview": `Первые строки вывода:
|
|
3107
|
+
{lines}`,
|
|
3078
3108
|
"proc.none": "Фоновых процессов нет.",
|
|
3079
3109
|
"proc.not_found": "Процесс не найден: {id}",
|
|
3080
3110
|
"proc.killed": "Процесс {id} (PID {pid}) остановлен.",
|
|
@@ -3319,6 +3349,10 @@ var init_ru = __esm(() => {
|
|
|
3319
3349
|
"repl.skills_label": "Скиллы:",
|
|
3320
3350
|
"repl.plugins_label": "Плагины:",
|
|
3321
3351
|
"repl.mcp_label": "MCP:",
|
|
3352
|
+
"repl.lsp_label": "LSP:",
|
|
3353
|
+
"repl.lsp_timeout": "таймаут",
|
|
3354
|
+
"repl.lsp_failed": "не стартовал",
|
|
3355
|
+
"repl.lsp_unknown": "неизвестно",
|
|
3322
3356
|
"repl.work_dir": "Директория:",
|
|
3323
3357
|
"repl.agents_label": "Инструкции:",
|
|
3324
3358
|
"repl.not_found": "не найден",
|
|
@@ -3486,6 +3520,7 @@ var init_ru = __esm(() => {
|
|
|
3486
3520
|
"ui.success_prefix": "✓ ",
|
|
3487
3521
|
"ui.warning_prefix": "⚠ ",
|
|
3488
3522
|
"ui.thinking": "Думаю…",
|
|
3523
|
+
"ui.step_context": "шаг {id}: {desc}",
|
|
3489
3524
|
"indexer.map_header": "Карта проекта",
|
|
3490
3525
|
"indexer.top_directories": "Основные директории",
|
|
3491
3526
|
"indexer.files": "Файлы",
|
|
@@ -7628,7 +7663,7 @@ Hint: ${t("exec.npm_exec_hint")}`;
|
|
|
7628
7663
|
}
|
|
7629
7664
|
return output;
|
|
7630
7665
|
}
|
|
7631
|
-
var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, NPM_EXEC_RE, bashTool;
|
|
7666
|
+
var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, BG_OUTPUT_PREVIEW_LINES = 15, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, NPM_EXEC_RE, bashTool;
|
|
7632
7667
|
var init_bash = __esm(() => {
|
|
7633
7668
|
init_command_validator();
|
|
7634
7669
|
init_audit_log();
|
|
@@ -7829,15 +7864,21 @@ Hint: "${originalFirstWord}" may not work on Windows. ${UNIX_TO_WIN_HINTS[origin
|
|
|
7829
7864
|
return { success: code === 0, output: output2 };
|
|
7830
7865
|
}
|
|
7831
7866
|
const explicit = args.background === true;
|
|
7832
|
-
const
|
|
7867
|
+
const preview = entry.log.filter((l) => l.trim() !== "").slice(0, BG_OUTPUT_PREVIEW_LINES).join(`
|
|
7868
|
+
`);
|
|
7869
|
+
let output = `${t("proc.started", {
|
|
7833
7870
|
id: entry.id,
|
|
7834
7871
|
pid: entry.pid,
|
|
7835
7872
|
command
|
|
7836
7873
|
})}${explicit ? "" : `
|
|
7837
|
-
${t("proc.promoted_hint", { ms: settleMs })}`}
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7874
|
+
${t("proc.promoted_hint", { ms: settleMs })}`}`;
|
|
7875
|
+
if (preview) {
|
|
7876
|
+
output += `
|
|
7877
|
+
|
|
7878
|
+
${t("proc.output_preview", { lines: preview })}`;
|
|
7879
|
+
}
|
|
7880
|
+
output += `
|
|
7881
|
+
${t("proc.manage_hint", { id: entry.id })}`;
|
|
7841
7882
|
if (securityConfig?.logCommands) {
|
|
7842
7883
|
logBashCommand(ctx.sessionId, sanitizeCommandForLog(command), true, `Started in background: ${entry.id} (PID ${entry.pid})`);
|
|
7843
7884
|
}
|
|
@@ -18946,24 +18987,7 @@ class LspClient {
|
|
|
18946
18987
|
async checkFile(filePath, baseDir, config, projectRoot = baseDir) {
|
|
18947
18988
|
const timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
18948
18989
|
try {
|
|
18949
|
-
await this.
|
|
18950
|
-
const rootUri = this.pathToUri(projectRoot);
|
|
18951
|
-
const initParams = {
|
|
18952
|
-
processId: process.pid,
|
|
18953
|
-
rootUri,
|
|
18954
|
-
workspaceFolders: [{ uri: rootUri, name: "workspace" }],
|
|
18955
|
-
capabilities: { textDocument: { publishDiagnostics: {} } }
|
|
18956
|
-
};
|
|
18957
|
-
try {
|
|
18958
|
-
await this.sendRequest("initialize", initParams, timeout);
|
|
18959
|
-
} catch (e) {
|
|
18960
|
-
if (!(e instanceof Error) || !e.message.includes("initialize"))
|
|
18961
|
-
throw e;
|
|
18962
|
-
await this.shutdown();
|
|
18963
|
-
await this.startServer(config, projectRoot);
|
|
18964
|
-
await this.sendRequest("initialize", initParams, timeout);
|
|
18965
|
-
}
|
|
18966
|
-
this.initialized = true;
|
|
18990
|
+
await this.initialize(config, projectRoot, timeout);
|
|
18967
18991
|
this.sendNotification("initialized", {});
|
|
18968
18992
|
const uri = this.pathToUri(resolve20(filePath));
|
|
18969
18993
|
const fs2 = await import("fs");
|
|
@@ -18991,6 +19015,33 @@ class LspClient {
|
|
|
18991
19015
|
await this.shutdown();
|
|
18992
19016
|
}
|
|
18993
19017
|
}
|
|
19018
|
+
async probe(config, projectRoot, timeout) {
|
|
19019
|
+
try {
|
|
19020
|
+
await this.initialize(config, projectRoot, timeout);
|
|
19021
|
+
} finally {
|
|
19022
|
+
await this.shutdown();
|
|
19023
|
+
}
|
|
19024
|
+
}
|
|
19025
|
+
async initialize(config, projectRoot, timeout) {
|
|
19026
|
+
await this.startServer(config, projectRoot);
|
|
19027
|
+
const rootUri = this.pathToUri(projectRoot);
|
|
19028
|
+
const initParams = {
|
|
19029
|
+
processId: process.pid,
|
|
19030
|
+
rootUri,
|
|
19031
|
+
workspaceFolders: [{ uri: rootUri, name: "workspace" }],
|
|
19032
|
+
capabilities: { textDocument: { publishDiagnostics: {} } }
|
|
19033
|
+
};
|
|
19034
|
+
try {
|
|
19035
|
+
await this.sendRequest("initialize", initParams, timeout);
|
|
19036
|
+
} catch (e) {
|
|
19037
|
+
if (!(e instanceof Error) || !e.message.includes("initialize"))
|
|
19038
|
+
throw e;
|
|
19039
|
+
await this.shutdown();
|
|
19040
|
+
await this.startServer(config, projectRoot);
|
|
19041
|
+
await this.sendRequest("initialize", initParams, timeout);
|
|
19042
|
+
}
|
|
19043
|
+
this.initialized = true;
|
|
19044
|
+
}
|
|
18994
19045
|
async startServer(config, projectRoot) {
|
|
18995
19046
|
if (config.autoInstall === false) {
|
|
18996
19047
|
try {
|
|
@@ -31516,8 +31567,8 @@ class LineEditor {
|
|
|
31516
31567
|
}
|
|
31517
31568
|
|
|
31518
31569
|
// src/cli/repl.ts
|
|
31519
|
-
import { existsSync as
|
|
31520
|
-
import { join as
|
|
31570
|
+
import { existsSync as existsSync53, readFileSync as readFileSync34, writeFileSync as writeFileSync17 } from "fs";
|
|
31571
|
+
import { join as join47, dirname as dirname18 } from "path";
|
|
31521
31572
|
import { homedir as homedir17 } from "os";
|
|
31522
31573
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
31523
31574
|
|
|
@@ -31926,13 +31977,14 @@ class Renderer {
|
|
|
31926
31977
|
thinkingEnd() {
|
|
31927
31978
|
this.spinner.stop();
|
|
31928
31979
|
}
|
|
31929
|
-
toolStart(tool, args) {
|
|
31980
|
+
toolStart(tool, args, stepContext) {
|
|
31930
31981
|
this.endCard();
|
|
31931
31982
|
this.spinner.stop();
|
|
31932
31983
|
const summary = summarizeArgs2(args);
|
|
31984
|
+
const step = stepContext ? ` ${pc2.cyan(`← ${stepContext}`)}` : "";
|
|
31933
31985
|
if (!this.rich) {
|
|
31934
31986
|
this.out.write(`
|
|
31935
|
-
${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
|
|
31987
|
+
${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}
|
|
31936
31988
|
`);
|
|
31937
31989
|
return;
|
|
31938
31990
|
}
|
|
@@ -31940,11 +31992,19 @@ ${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
|
|
|
31940
31992
|
if (this.toolStyle === "inline") {
|
|
31941
31993
|
const marker = toolMarker(tool);
|
|
31942
31994
|
this.out.write(`
|
|
31943
|
-
${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
|
|
31995
|
+
${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}
|
|
31944
31996
|
`);
|
|
31945
31997
|
return;
|
|
31946
31998
|
}
|
|
31947
|
-
this.spinner.start(`${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}`);
|
|
31999
|
+
this.spinner.start(`${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}`);
|
|
32000
|
+
}
|
|
32001
|
+
planBlock(lines) {
|
|
32002
|
+
this.endCard();
|
|
32003
|
+
this.spinner.stop();
|
|
32004
|
+
for (const line of lines) {
|
|
32005
|
+
this.out.write(`${line}
|
|
32006
|
+
`);
|
|
32007
|
+
}
|
|
31948
32008
|
}
|
|
31949
32009
|
toolEnd(_tool, duration, error, ctxDelta) {
|
|
31950
32010
|
this.spinner.stop();
|
|
@@ -32020,13 +32080,170 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
|
|
|
32020
32080
|
init_box();
|
|
32021
32081
|
init_i18n();
|
|
32022
32082
|
init_repl_commands();
|
|
32083
|
+
|
|
32084
|
+
// src/modules/lsp/probe.ts
|
|
32085
|
+
init_client2();
|
|
32086
|
+
init_config();
|
|
32087
|
+
init_check_tool();
|
|
32088
|
+
init_project_root();
|
|
32089
|
+
var DEFAULT_PROBE_TIMEOUT_MS = 20000;
|
|
32090
|
+
async function probeLspServers(config, baseDir, deps = {}) {
|
|
32091
|
+
if (!config.enabled)
|
|
32092
|
+
return { ok: [], failed: [], noneApplicable: true };
|
|
32093
|
+
const client = deps.client ?? new LspClient;
|
|
32094
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
|
|
32095
|
+
const collect = deps.collectFiles ?? collectCheckFiles;
|
|
32096
|
+
const files = await collect(baseDir, config);
|
|
32097
|
+
const seen = new Set;
|
|
32098
|
+
const servers = [];
|
|
32099
|
+
for (const file of files) {
|
|
32100
|
+
const language = getLanguageForFile(file);
|
|
32101
|
+
if (!language)
|
|
32102
|
+
continue;
|
|
32103
|
+
const server = config.servers[language];
|
|
32104
|
+
if (!server || seen.has(language))
|
|
32105
|
+
continue;
|
|
32106
|
+
seen.add(language);
|
|
32107
|
+
servers.push({ language, config: server });
|
|
32108
|
+
}
|
|
32109
|
+
if (servers.length === 0)
|
|
32110
|
+
return { ok: [], failed: [], noneApplicable: true };
|
|
32111
|
+
const results = await Promise.all(servers.map(async ({ language, config: server }) => {
|
|
32112
|
+
const projectRoot = findProjectRoot(baseDir, baseDir, server.workspaceMarkers ?? []);
|
|
32113
|
+
const started = Date.now();
|
|
32114
|
+
try {
|
|
32115
|
+
await client.probe(server, projectRoot, timeoutMs);
|
|
32116
|
+
return { language, ok: true, durationMs: Date.now() - started };
|
|
32117
|
+
} catch (e) {
|
|
32118
|
+
return {
|
|
32119
|
+
language,
|
|
32120
|
+
ok: false,
|
|
32121
|
+
error: e instanceof Error ? e.message : String(e),
|
|
32122
|
+
durationMs: Date.now() - started
|
|
32123
|
+
};
|
|
32124
|
+
}
|
|
32125
|
+
}));
|
|
32126
|
+
return {
|
|
32127
|
+
ok: results.filter((r) => r.ok),
|
|
32128
|
+
failed: results.filter((r) => !r.ok),
|
|
32129
|
+
noneApplicable: false
|
|
32130
|
+
};
|
|
32131
|
+
}
|
|
32132
|
+
|
|
32133
|
+
// src/cli/repl.ts
|
|
32134
|
+
init_config();
|
|
32135
|
+
|
|
32136
|
+
// src/ui/plan-view.ts
|
|
32137
|
+
init_colors();
|
|
32138
|
+
init_js_identifiers();
|
|
32139
|
+
init_i18n();
|
|
32140
|
+
import { existsSync as existsSync52, readFileSync as readFileSync33 } from "fs";
|
|
32141
|
+
import { join as join46 } from "path";
|
|
32142
|
+
function readActivePlan(baseDir) {
|
|
32143
|
+
const p = join46(baseDir, ".mma", "plans", "active.json");
|
|
32144
|
+
if (!existsSync52(p))
|
|
32145
|
+
return null;
|
|
32146
|
+
try {
|
|
32147
|
+
const raw = readFileSync33(p, "utf-8");
|
|
32148
|
+
if (!raw.trim())
|
|
32149
|
+
return null;
|
|
32150
|
+
const parsed = JSON.parse(raw);
|
|
32151
|
+
if (!parsed || !Array.isArray(parsed.steps))
|
|
32152
|
+
return null;
|
|
32153
|
+
return {
|
|
32154
|
+
id: parsed.id || "plan",
|
|
32155
|
+
title: parsed.title || "Plan",
|
|
32156
|
+
steps: parsed.steps,
|
|
32157
|
+
createdAt: parsed.createdAt || new Date().toISOString(),
|
|
32158
|
+
baseDir: parsed.baseDir || baseDir,
|
|
32159
|
+
name: parsed.name
|
|
32160
|
+
};
|
|
32161
|
+
} catch {
|
|
32162
|
+
return null;
|
|
32163
|
+
}
|
|
32164
|
+
}
|
|
32165
|
+
function currentStepIndex(plan) {
|
|
32166
|
+
const idx = plan.steps.findIndex((s) => s.status !== "done" && s.status !== "skipped");
|
|
32167
|
+
return idx === -1 ? 0 : idx;
|
|
32168
|
+
}
|
|
32169
|
+
function stepMark(step) {
|
|
32170
|
+
switch (step.status) {
|
|
32171
|
+
case "done":
|
|
32172
|
+
return pc2.green("[x]");
|
|
32173
|
+
case "in_progress":
|
|
32174
|
+
return pc2.yellow("[*]");
|
|
32175
|
+
case "failed":
|
|
32176
|
+
return pc2.red("[!]");
|
|
32177
|
+
case "skipped":
|
|
32178
|
+
return pc2.dim("[-]");
|
|
32179
|
+
default:
|
|
32180
|
+
return pc2.dim("[ ]");
|
|
32181
|
+
}
|
|
32182
|
+
}
|
|
32183
|
+
function formatPlanChecklist(plan) {
|
|
32184
|
+
const done = plan.steps.filter((s) => s.status === "done" || s.status === "skipped").length;
|
|
32185
|
+
const total = plan.steps.length;
|
|
32186
|
+
const pct = total === 0 ? 0 : Math.round(done / total * 100);
|
|
32187
|
+
const cur = currentStepIndex(plan);
|
|
32188
|
+
const barLen = 15;
|
|
32189
|
+
const filled = Math.round(pct / 100 * barLen);
|
|
32190
|
+
const bar = pc2.green("█".repeat(filled)) + pc2.dim("░".repeat(barLen - filled));
|
|
32191
|
+
const title = plan.title.replace(/^\[\d+[^]]*\]\s*/, "");
|
|
32192
|
+
const lines = [
|
|
32193
|
+
`${pc2.cyan(`[${plan.id}]`)} ${pc2.bold(title)} ${bar} ${pc2.dim(`${done}/${total} ${pct}%`)}`
|
|
32194
|
+
];
|
|
32195
|
+
for (let i = 0;i < plan.steps.length; i++) {
|
|
32196
|
+
const step = plan.steps[i];
|
|
32197
|
+
const active = i === cur;
|
|
32198
|
+
const desc = active ? pc2.yellow(step.description) : pc2.dim(step.description);
|
|
32199
|
+
lines.push(` ${stepMark(step)} ${step.id}. ${desc}`);
|
|
32200
|
+
for (const sub of step.subtasks ?? []) {
|
|
32201
|
+
lines.push(` ${sub.done ? pc2.green("[x]") : pc2.dim("[ ]")} ${sub.text}`);
|
|
32202
|
+
}
|
|
32203
|
+
}
|
|
32204
|
+
return lines;
|
|
32205
|
+
}
|
|
32206
|
+
var STRUCTURAL_TOOLS = new Set([
|
|
32207
|
+
"plan",
|
|
32208
|
+
"todo",
|
|
32209
|
+
"verify",
|
|
32210
|
+
"project_map",
|
|
32211
|
+
"lsp_check",
|
|
32212
|
+
"enable_tools"
|
|
32213
|
+
]);
|
|
32214
|
+
function truncate3(s, max = 48) {
|
|
32215
|
+
return s.length > max ? `${s.slice(0, max - 1)}…` : s;
|
|
32216
|
+
}
|
|
32217
|
+
function stepContextForTool(plan, tool, args) {
|
|
32218
|
+
if (!plan || STRUCTURAL_TOOLS.has(tool))
|
|
32219
|
+
return null;
|
|
32220
|
+
const argStr = JSON.stringify(args);
|
|
32221
|
+
const callPaths = extractFileLikeTokens(stripUrls(argStr)).map((p) => p.toLowerCase());
|
|
32222
|
+
if (callPaths.length > 0) {
|
|
32223
|
+
for (const step2 of plan.steps) {
|
|
32224
|
+
if (step2.status === "done" || step2.status === "skipped")
|
|
32225
|
+
continue;
|
|
32226
|
+
const stepPaths = extractFileLikeTokens(stripUrls(step2.description)).map((p) => p.toLowerCase());
|
|
32227
|
+
if (stepPaths.length > 0 && stepPaths.some((s) => callPaths.some((c) => c.includes(s) || s.includes(c)))) {
|
|
32228
|
+
return t("ui.step_context", { id: step2.id, desc: truncate3(step2.description) });
|
|
32229
|
+
}
|
|
32230
|
+
}
|
|
32231
|
+
}
|
|
32232
|
+
const cur = currentStepIndex(plan);
|
|
32233
|
+
const step = plan.steps[cur];
|
|
32234
|
+
if (!step)
|
|
32235
|
+
return null;
|
|
32236
|
+
return t("ui.step_context", { id: step.id, desc: truncate3(step.description) });
|
|
32237
|
+
}
|
|
32238
|
+
|
|
32239
|
+
// src/cli/repl.ts
|
|
32023
32240
|
function readVersion4() {
|
|
32024
32241
|
const here = dirname18(fileURLToPath6(import.meta.url));
|
|
32025
|
-
const candidates = [
|
|
32242
|
+
const candidates = [join47(here, "..", "..", "package.json"), join47(here, "..", "package.json")];
|
|
32026
32243
|
for (const p of candidates) {
|
|
32027
|
-
if (
|
|
32244
|
+
if (existsSync53(p)) {
|
|
32028
32245
|
try {
|
|
32029
|
-
const raw = JSON.parse(
|
|
32246
|
+
const raw = JSON.parse(readFileSync34(p, "utf8"));
|
|
32030
32247
|
if (raw.version)
|
|
32031
32248
|
return raw.version;
|
|
32032
32249
|
} catch {}
|
|
@@ -32067,6 +32284,8 @@ class Repl {
|
|
|
32067
32284
|
noAgentsMd;
|
|
32068
32285
|
pendingClipboardImage = null;
|
|
32069
32286
|
exitOnClose = false;
|
|
32287
|
+
activePlan = null;
|
|
32288
|
+
lastPlanSig = "";
|
|
32070
32289
|
rl;
|
|
32071
32290
|
agent;
|
|
32072
32291
|
config;
|
|
@@ -32082,10 +32301,10 @@ class Repl {
|
|
|
32082
32301
|
this.skillsModule = skillsModule;
|
|
32083
32302
|
this.pluginManager = pluginManager;
|
|
32084
32303
|
this.logger = logger;
|
|
32085
|
-
this.configDir = configDir ||
|
|
32304
|
+
this.configDir = configDir || join47(homedir17(), ".mma");
|
|
32086
32305
|
this.baseDir = baseDir || process.cwd();
|
|
32087
32306
|
this.noAgentsMd = noAgentsMd === true;
|
|
32088
|
-
this.historyPath =
|
|
32307
|
+
this.historyPath = join47(homedir17(), ".mma", "repl-history");
|
|
32089
32308
|
this.loadHistory();
|
|
32090
32309
|
this.rl = process.stdin.isTTY ? new LineEditor({
|
|
32091
32310
|
input: process.stdin,
|
|
@@ -32118,9 +32337,9 @@ class Repl {
|
|
|
32118
32337
|
this.setupListeners();
|
|
32119
32338
|
}
|
|
32120
32339
|
loadHistory() {
|
|
32121
|
-
if (
|
|
32340
|
+
if (existsSync53(this.historyPath)) {
|
|
32122
32341
|
try {
|
|
32123
|
-
const raw =
|
|
32342
|
+
const raw = readFileSync34(this.historyPath, "utf-8");
|
|
32124
32343
|
this.history = raw.split(`
|
|
32125
32344
|
`).filter(Boolean).slice(-this.maxHistory);
|
|
32126
32345
|
} catch {
|
|
@@ -32319,11 +32538,15 @@ ${t("image.clipboard_empty")}`));
|
|
|
32319
32538
|
spinner: this.config.ui?.spinner ?? true,
|
|
32320
32539
|
toolStyle: this.config.ui?.toolStyle ?? "inline"
|
|
32321
32540
|
});
|
|
32541
|
+
this.refreshActivePlan(renderer);
|
|
32322
32542
|
const result = await this.agent.run(input, (c) => renderer.text(c), (m) => renderer.meta(m), (ev) => {
|
|
32323
32543
|
if (ev.type === "start") {
|
|
32324
|
-
renderer.toolStart(ev.tool, ev.args);
|
|
32544
|
+
renderer.toolStart(ev.tool, ev.args, stepContextForTool(this.activePlan, ev.tool, ev.args));
|
|
32325
32545
|
} else {
|
|
32326
32546
|
renderer.toolEnd(ev.tool, ev.duration ?? 0, ev.error, ev.ctxDelta);
|
|
32547
|
+
if (ev.tool === "plan" || ev.tool === "todo") {
|
|
32548
|
+
this.refreshActivePlan(renderer);
|
|
32549
|
+
}
|
|
32327
32550
|
}
|
|
32328
32551
|
}, (phase) => {
|
|
32329
32552
|
if (phase === "thinking") {
|
|
@@ -32347,6 +32570,20 @@ ${t("image.clipboard_empty")}`));
|
|
|
32347
32570
|
this.agentRunning = false;
|
|
32348
32571
|
}
|
|
32349
32572
|
}
|
|
32573
|
+
refreshActivePlan(renderer) {
|
|
32574
|
+
const plan = readActivePlan(this.baseDir);
|
|
32575
|
+
const sig = plan ? JSON.stringify(plan.steps.map((s) => `${s.id}:${s.status}`)) : "";
|
|
32576
|
+
if (!plan) {
|
|
32577
|
+
this.activePlan = null;
|
|
32578
|
+
this.lastPlanSig = "";
|
|
32579
|
+
return;
|
|
32580
|
+
}
|
|
32581
|
+
this.activePlan = plan;
|
|
32582
|
+
if (sig !== this.lastPlanSig) {
|
|
32583
|
+
this.lastPlanSig = sig;
|
|
32584
|
+
renderer.planBlock(formatPlanChecklist(plan));
|
|
32585
|
+
}
|
|
32586
|
+
}
|
|
32350
32587
|
commands = new Map;
|
|
32351
32588
|
registerCommand(cmd) {
|
|
32352
32589
|
this.commands.set(cmd.name, cmd);
|
|
@@ -32433,7 +32670,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
32433
32670
|
}
|
|
32434
32671
|
}
|
|
32435
32672
|
}
|
|
32436
|
-
start() {
|
|
32673
|
+
async start() {
|
|
32437
32674
|
this.running = true;
|
|
32438
32675
|
const info = [];
|
|
32439
32676
|
const row = (label, value) => {
|
|
@@ -32469,17 +32706,21 @@ ${t("image.clipboard_empty")}`));
|
|
|
32469
32706
|
const names = enabledServers.map(([name]) => name).join(", ");
|
|
32470
32707
|
row(t("repl.mcp_label"), `${pc2.white(String(enabledServers.length))} ${pc2.dim(`(${names})`)}`);
|
|
32471
32708
|
}
|
|
32709
|
+
const lspSummary = await this.probeLspBanner();
|
|
32710
|
+
if (lspSummary) {
|
|
32711
|
+
row(t("repl.lsp_label"), lspSummary);
|
|
32712
|
+
}
|
|
32472
32713
|
const cwd = process.cwd();
|
|
32473
32714
|
row(t("repl.work_dir"), pc2.dim(cwd));
|
|
32474
32715
|
if (this.noAgentsMd) {
|
|
32475
32716
|
row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
|
|
32476
32717
|
} else {
|
|
32477
32718
|
const agentsMdCandidates = [
|
|
32478
|
-
|
|
32479
|
-
|
|
32480
|
-
|
|
32719
|
+
join47(this.baseDir, "AGENTS.md"),
|
|
32720
|
+
join47(this.baseDir, ".mma", "AGENTS.md"),
|
|
32721
|
+
join47(this.configDir, "AGENTS.md")
|
|
32481
32722
|
];
|
|
32482
|
-
const foundAgents = agentsMdCandidates.filter((p) =>
|
|
32723
|
+
const foundAgents = agentsMdCandidates.filter((p) => existsSync53(p));
|
|
32483
32724
|
if (foundAgents.length > 0) {
|
|
32484
32725
|
for (const p of foundAgents) {
|
|
32485
32726
|
row(t("repl.agents_label"), pc2.dim(p));
|
|
@@ -32490,7 +32731,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
32490
32731
|
}
|
|
32491
32732
|
const meta = this.sessionManager?.getActiveMeta();
|
|
32492
32733
|
if (meta) {
|
|
32493
|
-
const sessionPath =
|
|
32734
|
+
const sessionPath = join47(this.configDir, "sessions", meta.id);
|
|
32494
32735
|
row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
|
|
32495
32736
|
}
|
|
32496
32737
|
const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
|
|
@@ -32503,6 +32744,25 @@ ${t("image.clipboard_empty")}`));
|
|
|
32503
32744
|
console.log();
|
|
32504
32745
|
this.rl.prompt();
|
|
32505
32746
|
}
|
|
32747
|
+
async probeLspBanner() {
|
|
32748
|
+
const config = this.config.lsp ?? DEFAULT_LSP_CONFIG;
|
|
32749
|
+
try {
|
|
32750
|
+
const summary = await probeLspServers(config, this.baseDir);
|
|
32751
|
+
if (summary.noneApplicable)
|
|
32752
|
+
return null;
|
|
32753
|
+
const parts = [];
|
|
32754
|
+
for (const r of summary.ok) {
|
|
32755
|
+
parts.push(pc2.green(`✓ ${r.language}${pc2.dim(` (${(r.durationMs / 1000).toFixed(1)}s)`)}`));
|
|
32756
|
+
}
|
|
32757
|
+
for (const r of summary.failed) {
|
|
32758
|
+
const reason = r.error?.includes("timeout") ? t("repl.lsp_timeout") : t("repl.lsp_failed");
|
|
32759
|
+
parts.push(pc2.red(`✗ ${r.language}${pc2.dim(` — ${reason}`)}`));
|
|
32760
|
+
}
|
|
32761
|
+
return parts.join(" ");
|
|
32762
|
+
} catch {
|
|
32763
|
+
return pc2.yellow(t("repl.lsp_unknown"));
|
|
32764
|
+
}
|
|
32765
|
+
}
|
|
32506
32766
|
stop() {
|
|
32507
32767
|
this.running = false;
|
|
32508
32768
|
this.saveHistory();
|
|
@@ -32531,8 +32791,8 @@ init_setup();
|
|
|
32531
32791
|
init_config2();
|
|
32532
32792
|
init_i18n();
|
|
32533
32793
|
init_colors();
|
|
32534
|
-
import { existsSync as
|
|
32535
|
-
import { join as
|
|
32794
|
+
import { existsSync as existsSync54, readFileSync as readFileSync35 } from "fs";
|
|
32795
|
+
import { join as join48, dirname as dirname19 } from "path";
|
|
32536
32796
|
import { homedir as homedir18 } from "os";
|
|
32537
32797
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
32538
32798
|
|
|
@@ -32636,11 +32896,11 @@ class UpdaterModule {
|
|
|
32636
32896
|
// src/cli/main.ts
|
|
32637
32897
|
function readVersion5() {
|
|
32638
32898
|
const here = dirname19(fileURLToPath7(import.meta.url));
|
|
32639
|
-
const candidates = [
|
|
32899
|
+
const candidates = [join48(here, "..", "..", "package.json"), join48(here, "..", "package.json")];
|
|
32640
32900
|
for (const p of candidates) {
|
|
32641
|
-
if (
|
|
32901
|
+
if (existsSync54(p)) {
|
|
32642
32902
|
try {
|
|
32643
|
-
const raw = JSON.parse(
|
|
32903
|
+
const raw = JSON.parse(readFileSync35(p, "utf8"));
|
|
32644
32904
|
if (raw.version)
|
|
32645
32905
|
return raw.version;
|
|
32646
32906
|
} catch {}
|
|
@@ -32723,15 +32983,15 @@ async function main() {
|
|
|
32723
32983
|
await updater?.waitForIdle();
|
|
32724
32984
|
process.exit(exitCode);
|
|
32725
32985
|
} else {
|
|
32726
|
-
const configPath =
|
|
32727
|
-
if (!
|
|
32986
|
+
const configPath = join48(homedir18(), ".mma", "config.json");
|
|
32987
|
+
if (!existsSync54(configPath)) {
|
|
32728
32988
|
console.log(pc2.yellow(`
|
|
32729
32989
|
` + t("cli.first_run") + `
|
|
32730
32990
|
`));
|
|
32731
32991
|
const answers = await runSetup();
|
|
32732
32992
|
const config2 = loadConfig({
|
|
32733
|
-
configDir:
|
|
32734
|
-
projectConfigPath: projectDir ?
|
|
32993
|
+
configDir: join48(homedir18(), ".mma"),
|
|
32994
|
+
projectConfigPath: projectDir ? join48(projectDir, ".mmrc") : join48(process.cwd(), ".mmrc")
|
|
32735
32995
|
});
|
|
32736
32996
|
config2.provider.type = answers.provider;
|
|
32737
32997
|
config2.provider.baseUrl = answers.apiBase;
|
|
@@ -32785,7 +33045,7 @@ async function main() {
|
|
|
32785
33045
|
} = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
|
|
32786
33046
|
startAutoUpdate(config);
|
|
32787
33047
|
const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger, true);
|
|
32788
|
-
repl.start();
|
|
33048
|
+
await repl.start();
|
|
32789
33049
|
}
|
|
32790
33050
|
}
|
|
32791
33051
|
main();
|