micro-models-agent 0.57.2 → 0.58.1
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/CHANGELOG.md +33 -0
- package/dist/main.js +657 -246
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2290,22 +2290,26 @@ var init_defaults = __esm(() => {
|
|
|
2290
2290
|
code: {
|
|
2291
2291
|
model: DEFAULT_MODEL,
|
|
2292
2292
|
tool_tags: ["file", "code", "shell"],
|
|
2293
|
-
max_attempts: 3
|
|
2293
|
+
max_attempts: 3,
|
|
2294
|
+
description: "file operations, code editing, shell commands"
|
|
2294
2295
|
},
|
|
2295
2296
|
research: {
|
|
2296
2297
|
model: DEFAULT_MODEL,
|
|
2297
2298
|
tool_tags: ["research"],
|
|
2298
|
-
max_attempts: 3
|
|
2299
|
+
max_attempts: 3,
|
|
2300
|
+
description: "web search, web fetch, web browse, history search"
|
|
2299
2301
|
},
|
|
2300
2302
|
browser: {
|
|
2301
2303
|
model: DEFAULT_MODEL,
|
|
2302
2304
|
tool_tags: ["browser", "vision"],
|
|
2303
|
-
max_attempts: 3
|
|
2305
|
+
max_attempts: 3,
|
|
2306
|
+
description: "browser automation, screenshots"
|
|
2304
2307
|
},
|
|
2305
2308
|
vision: {
|
|
2306
2309
|
model: DEFAULT_MODEL,
|
|
2307
2310
|
tool_tags: ["browser", "vision", "file"],
|
|
2308
|
-
max_attempts: 2
|
|
2311
|
+
max_attempts: 2,
|
|
2312
|
+
description: "browser + file reading for visual tasks"
|
|
2309
2313
|
}
|
|
2310
2314
|
},
|
|
2311
2315
|
contextWindow: 32768,
|
|
@@ -3010,7 +3014,7 @@ Use this knowledge to answer the user's question.`,
|
|
|
3010
3014
|
"exec.audit_leftovers": "[✗] Task incomplete: {done}/{total} steps done, {files} files from delete-steps still exist",
|
|
3011
3015
|
"exec.audit_fail_tests": "[✗] Task incomplete: {done}/{total} steps done, tests FAILING: {failed} failed / {passed} passed — {detail}",
|
|
3012
3016
|
"exec.audit_fail_typecheck": "[✗] Task incomplete: {done}/{total} steps done, {missing} files missing, typecheck error: {typeError}",
|
|
3013
|
-
"exec.audit_incomplete": "
|
|
3017
|
+
"exec.audit_incomplete": "❗ Final audit incomplete: {summary}. Task is NOT finished. Remaining steps: {steps}. Resolve them - pick ONE path: (a) if the step's deliverable already exists on disk, mark it done (plan update step=N status=done); (b) if the step is no longer needed, mark it skipped; (c) if the plan drifted from reality (wrong file names, changed approach), re-plan to align it. Do NOT retry plan update repeatedly without changing anything.",
|
|
3014
3018
|
"exec.mass_edit_warning": "⚠️ Plan affects {count} files — review the full list before proceeding.",
|
|
3015
3019
|
"exec.escalation": `
|
|
3016
3020
|
|
|
@@ -3777,7 +3781,7 @@ var init_ru = __esm(() => {
|
|
|
3777
3781
|
"exec.audit_leftovers": "[✗] Задача не выполнена: {done}/{total} шагов, {files} файлов из delete-шагов всё ещё существуют",
|
|
3778
3782
|
"exec.audit_fail_tests": "[✗] Задача не выполнена: {done}/{total} шагов, тесты ПАДАЮТ: {failed} failed / {passed} passed — {detail}",
|
|
3779
3783
|
"exec.audit_fail_typecheck": "[✗] Задача не выполнена: {done}/{total} шагов, {missing} файлов отсутствует, ошибка typecheck: {typeError}",
|
|
3780
|
-
"exec.audit_incomplete": "
|
|
3784
|
+
"exec.audit_incomplete": "❗ Финальная проверка не пройдена: {summary}. Задача НЕ завершена. Незакрытые шаги: {steps}. Устрани одним путём: (a) если результат шага уже существует на диске — закрой шаг (plan update step=N status=done); (b) если шаг больше не нужен — status=skipped; (c) если план разошёлся с реальностью (другие имена файлов, сменился подход) — сделай re-plan. Не повторяй plan update без изменений.",
|
|
3781
3785
|
"exec.mass_edit_warning": "⚠️ План затрагивает {count} файлов — проверьте полный список перед продолжением.",
|
|
3782
3786
|
"exec.escalation": `
|
|
3783
3787
|
|
|
@@ -9539,12 +9543,24 @@ var init_bash = __esm(() => {
|
|
|
9539
9543
|
mv: "Use the move_file tool instead.",
|
|
9540
9544
|
rm: "Use the delete_file tool instead.",
|
|
9541
9545
|
grep: "Use the grep tool instead.",
|
|
9546
|
+
sed: "Use the edit_file tool instead.",
|
|
9547
|
+
awk: "Not available in cmd.exe. Use a Node.js one-liner or the grep tool instead.",
|
|
9542
9548
|
chmod: "Use the chmod tool instead.",
|
|
9543
9549
|
touch: "Use the write_file tool instead.",
|
|
9544
9550
|
find: "Use the glob tool instead.",
|
|
9545
9551
|
head: "Use the read_file tool with offset/limit instead.",
|
|
9546
9552
|
tail: "Use the read_file tool instead.",
|
|
9547
9553
|
wc: "Use the read_file tool instead.",
|
|
9554
|
+
uniq: "Not available in cmd.exe. Use a Node.js one-liner instead.",
|
|
9555
|
+
xargs: "Not available in cmd.exe. Use a Node.js one-liner instead.",
|
|
9556
|
+
cut: "Not available in cmd.exe. Use a Node.js one-liner instead.",
|
|
9557
|
+
tr: "Not available in cmd.exe. Use a Node.js one-liner instead.",
|
|
9558
|
+
basename: "Not available in cmd.exe. Use a Node.js one-liner instead.",
|
|
9559
|
+
dirname: "Not available in cmd.exe. Use a Node.js one-liner instead.",
|
|
9560
|
+
export: 'cmd.exe has no export - use "set VAR=value" (no spaces around =).',
|
|
9561
|
+
source: 'cmd.exe has no source - use "call script.bat".',
|
|
9562
|
+
sleep: 'Use "timeout /t N" instead.',
|
|
9563
|
+
env: "cmd.exe has no env - use set to list/set variables.",
|
|
9548
9564
|
diff: "Use the diff tool instead.",
|
|
9549
9565
|
which: 'Use "where" instead.',
|
|
9550
9566
|
echo: "echo works on Windows, but avoid pipes (|).",
|
|
@@ -10179,6 +10195,14 @@ class SessionLogger {
|
|
|
10179
10195
|
source: data.source
|
|
10180
10196
|
});
|
|
10181
10197
|
}
|
|
10198
|
+
logMoE(event, data) {
|
|
10199
|
+
this.session?.appendLog({
|
|
10200
|
+
ts: new Date().toISOString(),
|
|
10201
|
+
type: event,
|
|
10202
|
+
content: data.detail ?? data.explanation ?? event,
|
|
10203
|
+
...data
|
|
10204
|
+
});
|
|
10205
|
+
}
|
|
10182
10206
|
}
|
|
10183
10207
|
var init_session_logger = __esm(() => {
|
|
10184
10208
|
init_audit_log();
|
|
@@ -10993,23 +11017,58 @@ function parseChunks(chunks) {
|
|
|
10993
11017
|
}
|
|
10994
11018
|
|
|
10995
11019
|
// src/llm/orchestrator.ts
|
|
11020
|
+
function buildPlanSystemPrompt(experts) {
|
|
11021
|
+
if (!experts || Object.keys(experts).length === 0) {
|
|
11022
|
+
return PLAN_SYSTEM_PROMPT;
|
|
11023
|
+
}
|
|
11024
|
+
const lines = Object.entries(experts).map(([tag, cfg]) => {
|
|
11025
|
+
const desc = cfg.description || (cfg.tool_tags?.length ? `tools: ${cfg.tool_tags.join(", ")}` : "general purpose");
|
|
11026
|
+
return `- ${tag}: ${desc}`;
|
|
11027
|
+
});
|
|
11028
|
+
return `You are a planning assistant for an agent system with multiple expert sub-agents.
|
|
11029
|
+
Break down the user's task into subtasks that can be executed by different expert agents.
|
|
11030
|
+
|
|
11031
|
+
Available experts and their tool tags:
|
|
11032
|
+
${lines.join(`
|
|
11033
|
+
`)}
|
|
11034
|
+
|
|
11035
|
+
${PLAN_SYSTEM_PROMPT_RULES}`;
|
|
11036
|
+
}
|
|
11037
|
+
|
|
10996
11038
|
class OrchestratorClient {
|
|
10997
11039
|
config;
|
|
10998
11040
|
provider = null;
|
|
10999
11041
|
constructor(config, defaultProvider) {
|
|
11000
11042
|
this.config = config;
|
|
11001
|
-
if (config.model)
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
|
|
11043
|
+
if (!config.model)
|
|
11044
|
+
return;
|
|
11045
|
+
if (config.provider) {
|
|
11046
|
+
this.provider = this.buildManagedProvider(config);
|
|
11047
|
+
} else if (defaultProvider) {
|
|
11048
|
+
this.provider = defaultProvider;
|
|
11049
|
+
} else {
|
|
11050
|
+
this.provider = this.buildManagedProvider({
|
|
11051
|
+
...config,
|
|
11052
|
+
provider: { type: "openai-compat", baseUrl: DEFAULT_BASE_URL }
|
|
11053
|
+
});
|
|
11009
11054
|
}
|
|
11010
11055
|
}
|
|
11011
|
-
|
|
11012
|
-
|
|
11056
|
+
buildManagedProvider(config) {
|
|
11057
|
+
const providerCfg = config.provider;
|
|
11058
|
+
const manager = new ProviderManager({ ...providerCfg, baseUrl: providerCfg.baseUrl || DEFAULT_BASE_URL }, {
|
|
11059
|
+
contextWindow: config.contextWindow ?? DEFAULT_ORCH_CONTEXT_WINDOW,
|
|
11060
|
+
retry: config.retry,
|
|
11061
|
+
rateLimits: config.rateLimits,
|
|
11062
|
+
logger: config.logger
|
|
11063
|
+
});
|
|
11064
|
+
manager.setModel(config.model);
|
|
11065
|
+
let provider = manager.active;
|
|
11066
|
+
if (providerCfg.fallback && manager.listNames().length > 1) {
|
|
11067
|
+
provider = new FallbackProvider(manager, (from, to, error) => {
|
|
11068
|
+
config.logger?.warn(`orchestrator provider failover: ${from} -> ${to} (${error.message.slice(0, 120)})`);
|
|
11069
|
+
});
|
|
11070
|
+
}
|
|
11071
|
+
return provider;
|
|
11013
11072
|
}
|
|
11014
11073
|
isEnabled() {
|
|
11015
11074
|
return this.provider !== null;
|
|
@@ -11047,7 +11106,7 @@ class OrchestratorClient {
|
|
|
11047
11106
|
if (!this.provider)
|
|
11048
11107
|
return { error: "Orchestrator not enabled — no orchestrator model configured" };
|
|
11049
11108
|
const messages = [
|
|
11050
|
-
{ role: "system", content:
|
|
11109
|
+
{ role: "system", content: buildPlanSystemPrompt(this.config.experts) },
|
|
11051
11110
|
{ role: "user", content: userPrompt }
|
|
11052
11111
|
];
|
|
11053
11112
|
const text = await this.chat(messages, signal);
|
|
@@ -11137,16 +11196,7 @@ class OrchestratorClient {
|
|
|
11137
11196
|
return parsed.type === "text" ? parsed.content : "";
|
|
11138
11197
|
}
|
|
11139
11198
|
}
|
|
11140
|
-
var
|
|
11141
|
-
Break down the user's task into subtasks that can be executed by different expert agents.
|
|
11142
|
-
|
|
11143
|
-
Available experts and their tool tags:
|
|
11144
|
-
- code: file operations, code editing, shell commands
|
|
11145
|
-
- research: web search, web fetch, web browse, history search
|
|
11146
|
-
- browser: browser automation, screenshots
|
|
11147
|
-
- vision: browser + file reading for visual tasks
|
|
11148
|
-
|
|
11149
|
-
Rules:
|
|
11199
|
+
var PLAN_SYSTEM_PROMPT_RULES = `Rules:
|
|
11150
11200
|
1. Each subtask must have an expert_tag from the available experts.
|
|
11151
11201
|
2. Use depends_on for ordering when subtask B reads what subtask A writes.
|
|
11152
11202
|
3. Independent subtasks should NOT depend on each other (they run in parallel).
|
|
@@ -11175,7 +11225,7 @@ Respond with a JSON object only (no markdown fences):
|
|
|
11175
11225
|
"rules": ["rule 1"],
|
|
11176
11226
|
"refs": []
|
|
11177
11227
|
}
|
|
11178
|
-
}`, VERIFY_SYSTEM_PROMPT = `You are a verification and merge assistant for an agent system with multiple expert sub-agents.
|
|
11228
|
+
}`, PLAN_SYSTEM_PROMPT, VERIFY_SYSTEM_PROMPT = `You are a verification and merge assistant for an agent system with multiple expert sub-agents.
|
|
11179
11229
|
You receive the original plan, the results from each subtask, and any verification errors.
|
|
11180
11230
|
Your job is to determine if the overall task was completed successfully or if re-planning is needed.
|
|
11181
11231
|
|
|
@@ -11191,10 +11241,21 @@ Decide what to do with its scope request:
|
|
|
11191
11241
|
Respond with JSON only (no markdown fences):
|
|
11192
11242
|
{"action": "approve", "write": ["file1"], "read": ["file2"]}
|
|
11193
11243
|
or
|
|
11194
|
-
{"action": "reject", "explanation": "why"}`, DEFAULT_BASE_URL = "http://localhost:1234/v1";
|
|
11244
|
+
{"action": "reject", "explanation": "why"}`, DEFAULT_BASE_URL = "http://localhost:1234/v1", DEFAULT_ORCH_CONTEXT_WINDOW = 32768;
|
|
11195
11245
|
var init_orchestrator = __esm(() => {
|
|
11196
|
-
|
|
11246
|
+
init_manager();
|
|
11247
|
+
init_fallback();
|
|
11197
11248
|
init_esm();
|
|
11249
|
+
PLAN_SYSTEM_PROMPT = `You are a planning assistant for an agent system with multiple expert sub-agents.
|
|
11250
|
+
Break down the user's task into subtasks that can be executed by different expert agents.
|
|
11251
|
+
|
|
11252
|
+
Available experts and their tool tags:
|
|
11253
|
+
- code: file operations, code editing, shell commands
|
|
11254
|
+
- research: web search, web fetch, web browse, history search
|
|
11255
|
+
- browser: browser automation, screenshots
|
|
11256
|
+
- vision: browser + file reading for visual tasks
|
|
11257
|
+
|
|
11258
|
+
${PLAN_SYSTEM_PROMPT_RULES}`;
|
|
11198
11259
|
});
|
|
11199
11260
|
|
|
11200
11261
|
// src/modules/execution/input-from.ts
|
|
@@ -12208,7 +12269,7 @@ function topologicalSort(subtasks) {
|
|
|
12208
12269
|
}
|
|
12209
12270
|
return sorted;
|
|
12210
12271
|
}
|
|
12211
|
-
async function executeSubtask(subtask, deps, depResults, sharedContext) {
|
|
12272
|
+
async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage) {
|
|
12212
12273
|
const startTime = Date.now();
|
|
12213
12274
|
const expertConfig = getExpertConfig(deps.config, subtask.expert_tag);
|
|
12214
12275
|
if (!expertConfig) {
|
|
@@ -12290,8 +12351,11 @@ ${(subtask.success_criteria || []).map((c) => `- ${c}`).join(`
|
|
|
12290
12351
|
logger: deps.logger,
|
|
12291
12352
|
llmProvider: deps.llmProvider,
|
|
12292
12353
|
toolExecutor: deps.toolExecutor,
|
|
12293
|
-
sessionId: "moe"
|
|
12354
|
+
sessionId: deps.sessionId || "moe"
|
|
12294
12355
|
}, subagentArgs);
|
|
12356
|
+
if (result.usage) {
|
|
12357
|
+
onUsage?.(subtask.expert_tag, result.usage);
|
|
12358
|
+
}
|
|
12295
12359
|
deps.onTool?.({
|
|
12296
12360
|
type: "end",
|
|
12297
12361
|
tool: "subagent",
|
|
@@ -12305,7 +12369,7 @@ ${(subtask.success_criteria || []).map((c) => `- ${c}`).join(`
|
|
|
12305
12369
|
if (abs) {
|
|
12306
12370
|
const store = new ArtifactStore({
|
|
12307
12371
|
baseDir: deps.baseDir,
|
|
12308
|
-
sessionId: "moe"
|
|
12372
|
+
sessionId: deps.sessionId || "moe"
|
|
12309
12373
|
});
|
|
12310
12374
|
const full = store.read(abs.split(/[\\/]/).pop() || "");
|
|
12311
12375
|
deps.logger.debug(`MoE subtask "${subtask.id}" attached artifact ${abs} (${full?.length ?? 0} chars) to Router`);
|
|
@@ -12395,14 +12459,34 @@ ${stuckReason}`;
|
|
|
12395
12459
|
|
|
12396
12460
|
class MoEExecutor {
|
|
12397
12461
|
deps;
|
|
12462
|
+
usageByTag = new Map;
|
|
12398
12463
|
constructor(deps) {
|
|
12399
12464
|
this.deps = deps;
|
|
12400
12465
|
}
|
|
12401
|
-
|
|
12402
|
-
|
|
12466
|
+
getUsageByTag() {
|
|
12467
|
+
return Object.fromEntries(this.usageByTag);
|
|
12468
|
+
}
|
|
12469
|
+
recordUsage(expertTag, usage) {
|
|
12470
|
+
const entry = this.usageByTag.get(expertTag) ?? {
|
|
12471
|
+
promptTokens: 0,
|
|
12472
|
+
completionTokens: 0,
|
|
12473
|
+
totalTokens: 0,
|
|
12474
|
+
subtasks: 0
|
|
12475
|
+
};
|
|
12476
|
+
entry.promptTokens += usage.promptTokens;
|
|
12477
|
+
entry.completionTokens += usage.completionTokens;
|
|
12478
|
+
entry.totalTokens += usage.totalTokens;
|
|
12479
|
+
entry.subtasks += 1;
|
|
12480
|
+
this.usageByTag.set(expertTag, entry);
|
|
12481
|
+
}
|
|
12482
|
+
async executePlan(plan, opts) {
|
|
12483
|
+
const skipIds = opts?.skipIds;
|
|
12484
|
+
const carried = opts?.carriedResults ?? [];
|
|
12485
|
+
const results = carried.map((r) => ({ ...r }));
|
|
12403
12486
|
const errors = [];
|
|
12404
12487
|
const warnings = [];
|
|
12405
|
-
const
|
|
12488
|
+
const subtasks = skipIds && skipIds.size > 0 ? plan.subtasks.filter((s) => !skipIds.has(s.id)) : plan.subtasks;
|
|
12489
|
+
const waves = topologicalSort(subtasks);
|
|
12406
12490
|
if (waves.length === 0) {
|
|
12407
12491
|
return {
|
|
12408
12492
|
success: false,
|
|
@@ -12412,8 +12496,8 @@ class MoEExecutor {
|
|
|
12412
12496
|
};
|
|
12413
12497
|
}
|
|
12414
12498
|
const sortedCount = waves.flat().length;
|
|
12415
|
-
if (sortedCount <
|
|
12416
|
-
const missing =
|
|
12499
|
+
if (sortedCount < subtasks.length) {
|
|
12500
|
+
const missing = subtasks.filter((s) => !waves.flat().some((w) => w.id === s.id)).map((s) => s.id);
|
|
12417
12501
|
return {
|
|
12418
12502
|
success: false,
|
|
12419
12503
|
results: [],
|
|
@@ -12442,9 +12526,13 @@ class MoEExecutor {
|
|
|
12442
12526
|
release();
|
|
12443
12527
|
throw newAbortError();
|
|
12444
12528
|
}
|
|
12529
|
+
this.deps.onEvent?.({
|
|
12530
|
+
type: "moe_subtask",
|
|
12531
|
+
data: { subtaskId: subtask.id, expertTag: subtask.expert_tag, status: "start" }
|
|
12532
|
+
});
|
|
12445
12533
|
let result;
|
|
12446
12534
|
try {
|
|
12447
|
-
result = await executeSubtask(subtask, this.deps, depResults, plan.shared_context);
|
|
12535
|
+
result = await executeSubtask(subtask, this.deps, depResults, plan.shared_context, (tag, usage) => this.recordUsage(tag, usage));
|
|
12448
12536
|
if (!result.success && this.deps.onScopeRequest) {
|
|
12449
12537
|
result = await this.resolveScopeAndRetry(subtask, result, depResults, plan.shared_context);
|
|
12450
12538
|
}
|
|
@@ -12462,6 +12550,16 @@ class MoEExecutor {
|
|
|
12462
12550
|
} finally {
|
|
12463
12551
|
release();
|
|
12464
12552
|
}
|
|
12553
|
+
this.deps.onEvent?.({
|
|
12554
|
+
type: "moe_subtask",
|
|
12555
|
+
data: {
|
|
12556
|
+
subtaskId: subtask.id,
|
|
12557
|
+
expertTag: subtask.expert_tag,
|
|
12558
|
+
status: result.success ? "done" : "failed",
|
|
12559
|
+
durationMs: result.durationMs,
|
|
12560
|
+
summary: result.summary
|
|
12561
|
+
}
|
|
12562
|
+
});
|
|
12465
12563
|
results.push(result);
|
|
12466
12564
|
return result;
|
|
12467
12565
|
});
|
|
@@ -12473,7 +12571,13 @@ class MoEExecutor {
|
|
|
12473
12571
|
if (failed.length > 0) {
|
|
12474
12572
|
errors.push(...failed.map((f) => `[${f.subtaskId}] ${f.error || f.summary}`));
|
|
12475
12573
|
}
|
|
12476
|
-
return {
|
|
12574
|
+
return {
|
|
12575
|
+
success: failed.length === 0,
|
|
12576
|
+
results,
|
|
12577
|
+
errors,
|
|
12578
|
+
warnings,
|
|
12579
|
+
...carried.length > 0 ? { carriedSubtaskIds: carried.map((r) => r.subtaskId) } : {}
|
|
12580
|
+
};
|
|
12477
12581
|
}
|
|
12478
12582
|
async resolveScopeAndRetry(subtask, failed, depResults, sharedContext) {
|
|
12479
12583
|
let current = failed;
|
|
@@ -12493,7 +12597,7 @@ Router rejected scope request for files: ${req.files.join(", ")}`
|
|
|
12493
12597
|
subtask.allowed_files = uniq([...subtask.allowed_files || [], ...decision.write]);
|
|
12494
12598
|
subtask.read_only_files = uniq([...subtask.read_only_files || [], ...decision.read]);
|
|
12495
12599
|
this.deps.logger.info?.(`MoE: approved scope expansion for "${subtask.id}": +write [${decision.write.join(", ")}] +read [${decision.read.join(", ")}]`);
|
|
12496
|
-
const retry = await executeSubtask(subtask, this.deps, depResults, sharedContext);
|
|
12600
|
+
const retry = await executeSubtask(subtask, this.deps, depResults, sharedContext, (tag, usage) => this.recordUsage(tag, usage));
|
|
12497
12601
|
if (retry.success || !retry.scopeRequest)
|
|
12498
12602
|
return retry;
|
|
12499
12603
|
current = retry;
|
|
@@ -13084,7 +13188,7 @@ var init_auditor = __esm(() => {
|
|
|
13084
13188
|
});
|
|
13085
13189
|
|
|
13086
13190
|
// src/modules/execution/verifier.ts
|
|
13087
|
-
import { existsSync as existsSync26 } from "fs";
|
|
13191
|
+
import { existsSync as existsSync26, readFileSync as readFileSync13 } from "fs";
|
|
13088
13192
|
import { resolve as resolve13, extname as extname3, join as join16 } from "path";
|
|
13089
13193
|
import { spawn as spawn4 } from "child_process";
|
|
13090
13194
|
|
|
@@ -13155,6 +13259,65 @@ class StepVerifier {
|
|
|
13155
13259
|
async verifyArtifactFiles(files) {
|
|
13156
13260
|
return Promise.all(files.map((f) => this.checkFileExists(f)));
|
|
13157
13261
|
}
|
|
13262
|
+
async verifySubtaskCriteria(subtask) {
|
|
13263
|
+
const errors = [];
|
|
13264
|
+
const warnings = [];
|
|
13265
|
+
const details = [];
|
|
13266
|
+
for (const criterion of subtask.success_criteria || []) {
|
|
13267
|
+
const sep2 = criterion.indexOf(":");
|
|
13268
|
+
if (sep2 <= 0) {
|
|
13269
|
+
warnings.push(`Subtask "${subtask.id}": non-machine criterion "${criterion}" (LLM-only)`);
|
|
13270
|
+
continue;
|
|
13271
|
+
}
|
|
13272
|
+
const kind = criterion.slice(0, sep2);
|
|
13273
|
+
const rest = criterion.slice(sep2 + 1);
|
|
13274
|
+
if (kind === "file-exists") {
|
|
13275
|
+
const check = await this.checkFileExists(rest);
|
|
13276
|
+
details.push(check);
|
|
13277
|
+
if (!check.passed)
|
|
13278
|
+
errors.push(`[${subtask.id}] ${check.message}`);
|
|
13279
|
+
continue;
|
|
13280
|
+
}
|
|
13281
|
+
if (kind === "substring-in-file") {
|
|
13282
|
+
const colon = rest.indexOf(":");
|
|
13283
|
+
if (colon <= 0) {
|
|
13284
|
+
warnings.push(`Subtask "${subtask.id}": malformed substring-in-file criterion "${criterion}"`);
|
|
13285
|
+
continue;
|
|
13286
|
+
}
|
|
13287
|
+
const path = rest.slice(0, colon);
|
|
13288
|
+
const needle = rest.slice(colon + 1);
|
|
13289
|
+
const resolved = resolve13(this.baseDir, path);
|
|
13290
|
+
if (!existsSync26(resolved)) {
|
|
13291
|
+
const item = { passed: false, message: t("verify.file_not_found", { path }) };
|
|
13292
|
+
details.push(item);
|
|
13293
|
+
errors.push(`[${subtask.id}] ${item.message}`);
|
|
13294
|
+
continue;
|
|
13295
|
+
}
|
|
13296
|
+
const content = readFileSync13(resolved, "utf-8");
|
|
13297
|
+
const passed = content.includes(needle);
|
|
13298
|
+
details.push({ passed, message: `substring "${needle}" in ${path}: ${passed}` });
|
|
13299
|
+
if (!passed)
|
|
13300
|
+
errors.push(`[${subtask.id}] "${needle}" not found in ${path}`);
|
|
13301
|
+
continue;
|
|
13302
|
+
}
|
|
13303
|
+
if (kind === "command-exit-0") {
|
|
13304
|
+
try {
|
|
13305
|
+
await this.runAsync(rest, this.baseDir, 30000);
|
|
13306
|
+
details.push({ passed: true, message: `command ok: ${rest}` });
|
|
13307
|
+
} catch (e) {
|
|
13308
|
+
const item = {
|
|
13309
|
+
passed: false,
|
|
13310
|
+
message: `command failed: ${rest} (${String(e.message).slice(0, 200)})`
|
|
13311
|
+
};
|
|
13312
|
+
details.push(item);
|
|
13313
|
+
errors.push(`[${subtask.id}] ${item.message}`);
|
|
13314
|
+
}
|
|
13315
|
+
continue;
|
|
13316
|
+
}
|
|
13317
|
+
warnings.push(`Subtask "${subtask.id}": unknown criterion kind "${kind}" (LLM-only)`);
|
|
13318
|
+
}
|
|
13319
|
+
return { errors, warnings, details };
|
|
13320
|
+
}
|
|
13158
13321
|
async verifyMoEManifest(plan, config, allToolTags) {
|
|
13159
13322
|
const errors = [];
|
|
13160
13323
|
const warnings = [];
|
|
@@ -13177,6 +13340,10 @@ class StepVerifier {
|
|
|
13177
13340
|
errors.push(check.message);
|
|
13178
13341
|
}
|
|
13179
13342
|
}
|
|
13343
|
+
const criteria = await this.verifySubtaskCriteria(sub);
|
|
13344
|
+
errors.push(...criteria.errors);
|
|
13345
|
+
warnings.push(...criteria.warnings);
|
|
13346
|
+
details.push(...criteria.details);
|
|
13180
13347
|
}
|
|
13181
13348
|
return {
|
|
13182
13349
|
success: errors.length === 0,
|
|
@@ -13295,7 +13462,8 @@ var init_verifier = __esm(() => {
|
|
|
13295
13462
|
// src/core/agent-moe.ts
|
|
13296
13463
|
async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
13297
13464
|
const { config, llmProvider, logger, toolExecutor, baseDir } = deps;
|
|
13298
|
-
const { onMeta, onPhase, onTool, signal } = opts;
|
|
13465
|
+
const { onMeta, onPhase, onTool, signal, onEvent, sessionId } = opts;
|
|
13466
|
+
const emit = (type, data) => onEvent?.({ type, data });
|
|
13299
13467
|
const ensureNotAborted = () => {
|
|
13300
13468
|
if (signal?.aborted)
|
|
13301
13469
|
throw newAbortError();
|
|
@@ -13305,11 +13473,16 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13305
13473
|
if (!orchestrator) {
|
|
13306
13474
|
orchestrator = new OrchestratorClient({
|
|
13307
13475
|
model: config.orchestrator.model,
|
|
13308
|
-
provider: config.orchestrator.provider
|
|
13476
|
+
provider: config.orchestrator.provider,
|
|
13477
|
+
contextWindow: config.orchestrator.contextWindow,
|
|
13478
|
+
retry: config.retry,
|
|
13479
|
+
rateLimits: config.security?.rateLimits,
|
|
13480
|
+
logger,
|
|
13481
|
+
experts: config.experts
|
|
13309
13482
|
}, llmProvider);
|
|
13310
13483
|
}
|
|
13311
13484
|
if (!orchestrator.isEnabled()) {
|
|
13312
|
-
logger.
|
|
13485
|
+
logger.warn("MoE enabled but no orchestrator model configured — falling back to single-agent. Set orchestrator.model to activate MoE.");
|
|
13313
13486
|
return fallback();
|
|
13314
13487
|
}
|
|
13315
13488
|
onMeta?.(`\uD83E\uDD16 Planning with MoE mode...
|
|
@@ -13319,16 +13492,28 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13319
13492
|
onPhase?.("done");
|
|
13320
13493
|
if ("error" in planResult) {
|
|
13321
13494
|
logger.warn(`MoE plan failed: ${planResult.error} — falling back to single-agent`);
|
|
13495
|
+
emit("moe_plan", { status: "error", error: planResult.error });
|
|
13322
13496
|
return fallback();
|
|
13323
13497
|
}
|
|
13498
|
+
emit("moe_plan", {
|
|
13499
|
+
status: "ok",
|
|
13500
|
+
title: planResult.plan.title,
|
|
13501
|
+
subtaskIds: planResult.plan.subtasks.map((s) => s.id)
|
|
13502
|
+
});
|
|
13324
13503
|
const maxCycles = Math.max(1, config.moe?.maxReplanCycles ?? DEFAULT_MOE_MAX_REPLAN_CYCLES);
|
|
13325
13504
|
const mergedResults = new Map;
|
|
13326
13505
|
let currentPlan = planResult.plan;
|
|
13506
|
+
const usageByTag = {};
|
|
13327
13507
|
for (let cycle = 1;cycle <= maxCycles; cycle++) {
|
|
13328
13508
|
ensureNotAborted();
|
|
13329
13509
|
if (cycle > 1) {
|
|
13330
13510
|
onMeta?.(t("moe.replan_started", { cycle, max: maxCycles }) + `
|
|
13331
13511
|
`);
|
|
13512
|
+
emit("moe_replan", {
|
|
13513
|
+
cycle,
|
|
13514
|
+
title: currentPlan.title,
|
|
13515
|
+
subtaskIds: currentPlan.subtasks.map((s) => s.id)
|
|
13516
|
+
});
|
|
13332
13517
|
}
|
|
13333
13518
|
const validation = validatePlan(currentPlan, config);
|
|
13334
13519
|
if (!validation.valid) {
|
|
@@ -13357,6 +13542,8 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13357
13542
|
logger,
|
|
13358
13543
|
baseDir,
|
|
13359
13544
|
onTool,
|
|
13545
|
+
sessionId,
|
|
13546
|
+
onEvent: (e) => emit(e.type, e.data),
|
|
13360
13547
|
onScopeRequest: async (subtaskId, req) => {
|
|
13361
13548
|
const decision = await orchestrator.resolveScopeRequest(subtaskId, req, signal);
|
|
13362
13549
|
if (decision.action === "approve") {
|
|
@@ -13374,8 +13561,36 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13374
13561
|
});
|
|
13375
13562
|
onMeta?.(t("moe.executing", { count: String(currentPlan.subtasks.length), cycle: String(cycle) }) + `
|
|
13376
13563
|
`);
|
|
13377
|
-
const
|
|
13564
|
+
const skipIds = new Set;
|
|
13565
|
+
const carriedResults = [];
|
|
13566
|
+
for (const s of currentPlan.subtasks) {
|
|
13567
|
+
const prev = mergedResults.get(s.id);
|
|
13568
|
+
if (prev?.success) {
|
|
13569
|
+
skipIds.add(s.id);
|
|
13570
|
+
carriedResults.push(prev);
|
|
13571
|
+
}
|
|
13572
|
+
}
|
|
13573
|
+
for (const id of skipIds) {
|
|
13574
|
+
emit("moe_subtask", { subtaskId: id, status: "carried", cycle });
|
|
13575
|
+
}
|
|
13576
|
+
const planResults = await executor.executePlan(currentPlan, { skipIds, carriedResults });
|
|
13378
13577
|
ensureNotAborted();
|
|
13578
|
+
const cycleUsage = executor.getUsageByTag?.();
|
|
13579
|
+
if (cycleUsage) {
|
|
13580
|
+
for (const [tag, usage] of Object.entries(cycleUsage)) {
|
|
13581
|
+
const agg = usageByTag[tag] ?? {
|
|
13582
|
+
promptTokens: 0,
|
|
13583
|
+
completionTokens: 0,
|
|
13584
|
+
totalTokens: 0,
|
|
13585
|
+
subtasks: 0
|
|
13586
|
+
};
|
|
13587
|
+
agg.promptTokens += usage.promptTokens;
|
|
13588
|
+
agg.completionTokens += usage.completionTokens;
|
|
13589
|
+
agg.totalTokens += usage.totalTokens;
|
|
13590
|
+
agg.subtasks += usage.subtasks;
|
|
13591
|
+
usageByTag[tag] = agg;
|
|
13592
|
+
}
|
|
13593
|
+
}
|
|
13379
13594
|
for (const r of planResults.results) {
|
|
13380
13595
|
mergedResults.set(r.subtaskId, r);
|
|
13381
13596
|
}
|
|
@@ -13405,6 +13620,7 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13405
13620
|
onPhase?.("done");
|
|
13406
13621
|
if (err?.name === "AbortError")
|
|
13407
13622
|
throw err;
|
|
13623
|
+
emit("moe_verify", { status: "error", error: err.message });
|
|
13408
13624
|
return {
|
|
13409
13625
|
success: false,
|
|
13410
13626
|
text: `MoE verifyAndMerge crashed: ${err.message}`,
|
|
@@ -13413,6 +13629,11 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13413
13629
|
};
|
|
13414
13630
|
}
|
|
13415
13631
|
onPhase?.("done");
|
|
13632
|
+
emit("moe_verify", {
|
|
13633
|
+
decision: verifyResult.type,
|
|
13634
|
+
explanation: verifyResult.explanation,
|
|
13635
|
+
usageByTag: Object.keys(usageByTag).length > 0 ? usageByTag : undefined
|
|
13636
|
+
});
|
|
13416
13637
|
if (verifyResult.type === "final") {
|
|
13417
13638
|
return buildFinalResult(mergedResults, verification.success, verifyResult);
|
|
13418
13639
|
}
|
|
@@ -13674,7 +13895,7 @@ function evaluateReasoningPolicy(input, state) {
|
|
|
13674
13895
|
var DECAY_THRESHOLD = 5;
|
|
13675
13896
|
|
|
13676
13897
|
// src/core/agent/constants.ts
|
|
13677
|
-
var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000, QUALITY_TRIGGER_THRESHOLD = 40, TOOL_ARGS_SUMMARY_MAX_CHARS = 240, FORCED_COMPACTION_COOLDOWN = 3, MAX_LLM_ERROR_RETRIES = 2, MAX_HALLUCINATION_RETRIES = 3, MAX_CONSECUTIVE_TOOL_FAILURES = 5, MIN_REPEATED_TOOL_FAILURES = 3, MAX_AUDIT_RETRIES = 3, MAX_EMPTY_RESPONSE_RETRIES = 2, MAX_REPEATED_TOOL_CALLS = 2;
|
|
13898
|
+
var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000, QUALITY_TRIGGER_THRESHOLD = 40, TOOL_ARGS_SUMMARY_MAX_CHARS = 240, FORCED_COMPACTION_COOLDOWN = 3, MAX_LLM_ERROR_RETRIES = 2, MAX_HALLUCINATION_RETRIES = 3, MAX_CONSECUTIVE_TOOL_FAILURES = 5, MIN_REPEATED_TOOL_FAILURES = 3, MAX_AUDIT_RETRIES = 3, MAX_EMPTY_RESPONSE_RETRIES = 2, MAX_REPEATED_TOOL_CALLS = 2, MUTATION_CYCLE_NUDGE_THRESHOLD = 5;
|
|
13678
13899
|
|
|
13679
13900
|
// src/core/agent/loop-state.ts
|
|
13680
13901
|
function createLoopState() {
|
|
@@ -13690,6 +13911,8 @@ function createLoopState() {
|
|
|
13690
13911
|
repeatedToolCount: 0,
|
|
13691
13912
|
toolFailureCounts: new Map,
|
|
13692
13913
|
memoryRuleRecorded: new Set,
|
|
13914
|
+
toolTargetCounts: new Map,
|
|
13915
|
+
cycleNudgedKeys: new Set,
|
|
13693
13916
|
apiPromptTokens: 0,
|
|
13694
13917
|
apiCompletionTokens: 0,
|
|
13695
13918
|
apiCompletionChars: 0,
|
|
@@ -13866,7 +14089,7 @@ class ReasoningEffortResolver {
|
|
|
13866
14089
|
planCreated: state.iterPlanCreated,
|
|
13867
14090
|
consecutiveSuccesses: state.consecutiveToolSuccesses,
|
|
13868
14091
|
isRepetitive: state.iterRepetitive,
|
|
13869
|
-
baseline: "medium"
|
|
14092
|
+
baseline: reasoningConfig?.baseline ?? "medium"
|
|
13870
14093
|
}, deps.policyState);
|
|
13871
14094
|
level = policyResult.level;
|
|
13872
14095
|
source = "policy";
|
|
@@ -14256,6 +14479,32 @@ var init_audit_gate = __esm(() => {
|
|
|
14256
14479
|
});
|
|
14257
14480
|
|
|
14258
14481
|
// src/core/agent.ts
|
|
14482
|
+
function mutationTargetKey(name, rawArgs) {
|
|
14483
|
+
let a = null;
|
|
14484
|
+
if (typeof rawArgs === "string") {
|
|
14485
|
+
try {
|
|
14486
|
+
a = JSON.parse(rawArgs);
|
|
14487
|
+
} catch {
|
|
14488
|
+
return null;
|
|
14489
|
+
}
|
|
14490
|
+
} else if (rawArgs && typeof rawArgs === "object") {
|
|
14491
|
+
a = rawArgs;
|
|
14492
|
+
}
|
|
14493
|
+
if (!a)
|
|
14494
|
+
return null;
|
|
14495
|
+
if ((name === "edit_file" || name === "write_file") && typeof a.path === "string") {
|
|
14496
|
+
return `write:${a.path.replace(/\\/g, "/").toLowerCase()}`;
|
|
14497
|
+
}
|
|
14498
|
+
if (name === "bash" && typeof a.command === "string") {
|
|
14499
|
+
const cmd = a.command.replace(/\s+/g, " ").trim().slice(0, 80).toLowerCase();
|
|
14500
|
+
return cmd ? `bash:${cmd}` : null;
|
|
14501
|
+
}
|
|
14502
|
+
if ((name === "plan" || name === "todo") && typeof a.action === "string") {
|
|
14503
|
+
return `book:${name}:${a.action.toLowerCase()}`;
|
|
14504
|
+
}
|
|
14505
|
+
return null;
|
|
14506
|
+
}
|
|
14507
|
+
|
|
14259
14508
|
class Agent {
|
|
14260
14509
|
deps;
|
|
14261
14510
|
systemPromptAdded = false;
|
|
@@ -14450,7 +14699,8 @@ class Agent {
|
|
|
14450
14699
|
};
|
|
14451
14700
|
try {
|
|
14452
14701
|
const moeEnabled = config.moe?.enabled === true;
|
|
14453
|
-
const
|
|
14702
|
+
const moeRunner = this.deps.runWithMoEOverride ?? runWithMoE;
|
|
14703
|
+
const result = moeEnabled ? await moeRunner({
|
|
14454
14704
|
config,
|
|
14455
14705
|
llmProvider,
|
|
14456
14706
|
toolExecutor,
|
|
@@ -14460,7 +14710,9 @@ class Agent {
|
|
|
14460
14710
|
onMeta,
|
|
14461
14711
|
onTool: countTool,
|
|
14462
14712
|
onPhase,
|
|
14463
|
-
signal: this.abortController.signal
|
|
14713
|
+
signal: this.abortController.signal,
|
|
14714
|
+
onEvent: (event) => slog.logMoE(event.type, event.data),
|
|
14715
|
+
sessionId: this.deps.sessionManager?.getActiveMeta()?.id
|
|
14464
14716
|
}) : await this.executeSingleAgentLoop(input, slog, onChunk, onMeta, countTool, onPhase);
|
|
14465
14717
|
if (moeEnabled && result.moeHandled) {
|
|
14466
14718
|
if (result.text) {
|
|
@@ -14674,27 +14926,49 @@ class Agent {
|
|
|
14674
14926
|
const signature = toolCalls.map((tc) => `${tc.name}:${JSON.stringify(tc.arguments)}`).join("|");
|
|
14675
14927
|
if (signature && signature === state.lastToolSignature) {
|
|
14676
14928
|
state.iterRepetitive = true;
|
|
14929
|
+
logger.info(`Repeated identical tool call detected (iteration ${state.iteration}) — nudging model to finish or change approach`);
|
|
14930
|
+
contextManager.addMessage({
|
|
14931
|
+
role: "user",
|
|
14932
|
+
content: `<system-summary>You just called the same tool with identical arguments. If the task is done, answer with a final text response NOW. If the command failed, try a different approach.</system-summary>`
|
|
14933
|
+
});
|
|
14677
14934
|
if (this.deps.exitOnComplete) {
|
|
14678
14935
|
state.repeatedToolCount++;
|
|
14679
14936
|
if (state.repeatedToolCount >= MAX_REPEATED_TOOL_CALLS) {
|
|
14680
14937
|
logger.debug("Exit-on-complete: repeated identical tool call, stopping");
|
|
14681
14938
|
break;
|
|
14682
14939
|
}
|
|
14683
|
-
contextManager.addMessage({
|
|
14684
|
-
role: "user",
|
|
14685
|
-
content: `<system-summary>You just called the same tool with identical arguments. If the task is done, answer with a final text response NOW. If the command failed, try a different approach.</system-summary>`
|
|
14686
|
-
});
|
|
14687
14940
|
}
|
|
14688
14941
|
} else {
|
|
14689
14942
|
state.repeatedToolCount = 0;
|
|
14690
14943
|
}
|
|
14691
14944
|
state.lastToolSignature = signature;
|
|
14692
14945
|
}
|
|
14946
|
+
const cycleNudges = [];
|
|
14947
|
+
if (sawToolCall) {
|
|
14948
|
+
for (const tc of toolCalls) {
|
|
14949
|
+
const target = mutationTargetKey(tc.name, tc.arguments);
|
|
14950
|
+
if (!target)
|
|
14951
|
+
continue;
|
|
14952
|
+
const count = (state.toolTargetCounts.get(target) ?? 0) + 1;
|
|
14953
|
+
state.toolTargetCounts.set(target, count);
|
|
14954
|
+
if (count >= MUTATION_CYCLE_NUDGE_THRESHOLD && !state.cycleNudgedKeys.has(target)) {
|
|
14955
|
+
state.cycleNudgedKeys.add(target);
|
|
14956
|
+
cycleNudges.push(target);
|
|
14957
|
+
}
|
|
14958
|
+
}
|
|
14959
|
+
}
|
|
14693
14960
|
if (sawToolCall) {
|
|
14694
14961
|
const batch = await toolBatch.execute(state, toolCalls, boundedToolNames, textContent, reasoningContent, input, onTool, onMeta, slog);
|
|
14695
14962
|
if (batch.interrupted) {
|
|
14696
14963
|
break;
|
|
14697
14964
|
}
|
|
14965
|
+
if (cycleNudges.length > 0) {
|
|
14966
|
+
logger.info(`Perfectionism cycle detected (${cycleNudges.length} target(s) at ${MUTATION_CYCLE_NUDGE_THRESHOLD}+ mutations) — nudging model to finalize`);
|
|
14967
|
+
contextManager.addMessage({
|
|
14968
|
+
role: "user",
|
|
14969
|
+
content: `<system-summary>You have already modified or re-run the same target many times (e.g. ${cycleNudges[0]}). If the latest output is correct, STOP polishing and answer with a final text response. More identical edits will not change the result.</system-summary>`
|
|
14970
|
+
});
|
|
14971
|
+
}
|
|
14698
14972
|
this.contextRenderer.render(this.deps.config.ui, contextManager, onMeta);
|
|
14699
14973
|
state.suppressRepetitionRetry = false;
|
|
14700
14974
|
continue;
|
|
@@ -16253,8 +16527,9 @@ var init_subagent = __esm(() => {
|
|
|
16253
16527
|
essential: true,
|
|
16254
16528
|
estimatedTokens: 150
|
|
16255
16529
|
};
|
|
16530
|
+
const subConfig = { ...ctx.config, moe: { ...ctx.config.moe, enabled: false } };
|
|
16256
16531
|
const subDeps = {
|
|
16257
|
-
config:
|
|
16532
|
+
config: subConfig,
|
|
16258
16533
|
llmProvider: ctx.llmProvider,
|
|
16259
16534
|
toolExecutor: ctx.toolExecutor,
|
|
16260
16535
|
pluginManager: subPluginManager,
|
|
@@ -16266,12 +16541,17 @@ var init_subagent = __esm(() => {
|
|
|
16266
16541
|
toolTags,
|
|
16267
16542
|
promptBlocks: [systemPrompt]
|
|
16268
16543
|
};
|
|
16269
|
-
const subAgent = new Agent(subDeps);
|
|
16544
|
+
const subAgent = (ctx.agentFactory ?? ((d) => new Agent(d)))(subDeps);
|
|
16270
16545
|
const fullTask = context ? `${task}
|
|
16271
16546
|
|
|
16272
16547
|
Context: ${context}` : task;
|
|
16273
16548
|
try {
|
|
16274
16549
|
const result = await subAgent.run(fullTask);
|
|
16550
|
+
const pickUsage = () => result.promptTokens !== undefined || result.totalTokens !== undefined ? {
|
|
16551
|
+
promptTokens: result.promptTokens ?? 0,
|
|
16552
|
+
completionTokens: result.completionTokens ?? 0,
|
|
16553
|
+
totalTokens: result.totalTokens ?? 0
|
|
16554
|
+
} : undefined;
|
|
16275
16555
|
if (!result.success) {
|
|
16276
16556
|
let output = `Sub-agent failed: ${result.error}
|
|
16277
16557
|
Partial output: ${result.text}`;
|
|
@@ -16298,7 +16578,8 @@ ${formatScopeRequest(scopeReq)}`;
|
|
|
16298
16578
|
iterations: String(result.iterationCount),
|
|
16299
16579
|
summary
|
|
16300
16580
|
}),
|
|
16301
|
-
artifactPath: abs
|
|
16581
|
+
artifactPath: abs,
|
|
16582
|
+
usage: pickUsage()
|
|
16302
16583
|
};
|
|
16303
16584
|
}
|
|
16304
16585
|
return {
|
|
@@ -16306,7 +16587,8 @@ ${formatScopeRequest(scopeReq)}`;
|
|
|
16306
16587
|
output: `Sub-agent completed:
|
|
16307
16588
|
${result.text}
|
|
16308
16589
|
|
|
16309
|
-
Iterations: ${result.iterationCount}
|
|
16590
|
+
Iterations: ${result.iterationCount}`,
|
|
16591
|
+
usage: pickUsage()
|
|
16310
16592
|
};
|
|
16311
16593
|
} finally {
|
|
16312
16594
|
ctx.toolExecutor.setScope(parentScope);
|
|
@@ -16442,7 +16724,7 @@ var init_chunk_query = __esm(() => {
|
|
|
16442
16724
|
});
|
|
16443
16725
|
|
|
16444
16726
|
// src/tools/chunk-query.ts
|
|
16445
|
-
import { readFileSync as
|
|
16727
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
16446
16728
|
import { resolve as resolve15 } from "node:path";
|
|
16447
16729
|
var chunkQueryTool;
|
|
16448
16730
|
var init_chunk_query2 = __esm(() => {
|
|
@@ -16454,7 +16736,7 @@ var init_chunk_query2 = __esm(() => {
|
|
|
16454
16736
|
name: "chunk_query",
|
|
16455
16737
|
icon: "\uD83E\uDDE9",
|
|
16456
16738
|
description: "Answer a query over a large text (file or inline) by splitting it into chunks and querying the model per chunk in parallel, then optionally synthesizing a final answer. Use when the input is too large for the context window.",
|
|
16457
|
-
tags: ["research"
|
|
16739
|
+
tags: ["research"],
|
|
16458
16740
|
timeoutMs: 300000,
|
|
16459
16741
|
parameters: {
|
|
16460
16742
|
type: "object",
|
|
@@ -16515,7 +16797,7 @@ var init_chunk_query2 = __esm(() => {
|
|
|
16515
16797
|
return { success: false, output: `[SCOPE] ${check.reason || "Path not allowed"}` };
|
|
16516
16798
|
}
|
|
16517
16799
|
try {
|
|
16518
|
-
content =
|
|
16800
|
+
content = readFileSync14(resolvedInput, "utf8");
|
|
16519
16801
|
} catch (e) {
|
|
16520
16802
|
return { success: false, output: `Cannot read ${inputPath}: ${e.message}` };
|
|
16521
16803
|
}
|
|
@@ -16983,7 +17265,7 @@ var init_download_file = __esm(() => {
|
|
|
16983
17265
|
name: "download_file",
|
|
16984
17266
|
icon: "⬇️",
|
|
16985
17267
|
description: "Download a file (image, archive, binary, font, etc.) from a URL and save it to disk. Returns only the path, size and content type — read the saved file with read_file/attach_image afterwards. Use this for binary files; web_fetch/web_browse return text only and cannot save bytes.",
|
|
16986
|
-
tags: ["
|
|
17268
|
+
tags: ["research"],
|
|
16987
17269
|
parameters: {
|
|
16988
17270
|
type: "object",
|
|
16989
17271
|
properties: {
|
|
@@ -17320,7 +17602,7 @@ var init_pipeline_run = __esm(() => {
|
|
|
17320
17602
|
name: "pipeline_run",
|
|
17321
17603
|
icon: "▶️",
|
|
17322
17604
|
description: "Run a named pipeline with YAML definition. Creates a DAG of sub-agents that execute in dependency order.",
|
|
17323
|
-
tags: ["shell"
|
|
17605
|
+
tags: ["shell"],
|
|
17324
17606
|
parameters: {
|
|
17325
17607
|
type: "object",
|
|
17326
17608
|
properties: {
|
|
@@ -17878,7 +18160,7 @@ var init_mcp_call = __esm(() => {
|
|
|
17878
18160
|
name: "mcp_call",
|
|
17879
18161
|
icon: "\uD83D\uDD17",
|
|
17880
18162
|
description: "Call a tool on an MCP (Model Context Protocol) server. MCP servers provide external capabilities like databases, APIs, or specialized tools.",
|
|
17881
|
-
tags: ["
|
|
18163
|
+
tags: ["research"],
|
|
17882
18164
|
parameters: {
|
|
17883
18165
|
type: "object",
|
|
17884
18166
|
properties: {
|
|
@@ -18010,7 +18292,7 @@ var init_search_history = __esm(() => {
|
|
|
18010
18292
|
});
|
|
18011
18293
|
|
|
18012
18294
|
// src/modules/memory/search.ts
|
|
18013
|
-
import { readFileSync as
|
|
18295
|
+
import { readFileSync as readFileSync16, existsSync as existsSync30 } from "fs";
|
|
18014
18296
|
import { join as join20 } from "path";
|
|
18015
18297
|
|
|
18016
18298
|
class MemorySearch {
|
|
@@ -18025,7 +18307,7 @@ class MemorySearch {
|
|
|
18025
18307
|
const path = join20(this.memoryDir, `${name}.md`);
|
|
18026
18308
|
if (!existsSync30(path))
|
|
18027
18309
|
continue;
|
|
18028
|
-
const content =
|
|
18310
|
+
const content = readFileSync16(path, "utf-8");
|
|
18029
18311
|
const lines = content.split(`
|
|
18030
18312
|
`);
|
|
18031
18313
|
for (const line of lines) {
|
|
@@ -18037,7 +18319,7 @@ class MemorySearch {
|
|
|
18037
18319
|
const prefsPath = join20(this.memoryDir, "preferences.json");
|
|
18038
18320
|
if (existsSync30(prefsPath)) {
|
|
18039
18321
|
try {
|
|
18040
|
-
const prefs = JSON.parse(
|
|
18322
|
+
const prefs = JSON.parse(readFileSync16(prefsPath, "utf-8"));
|
|
18041
18323
|
for (const [key, value] of Object.entries(prefs)) {
|
|
18042
18324
|
const searchStr = `${key}=${value}`;
|
|
18043
18325
|
if (searchStr.toLowerCase().includes(lowerQuery)) {
|
|
@@ -18055,7 +18337,7 @@ var init_search = __esm(() => {
|
|
|
18055
18337
|
});
|
|
18056
18338
|
|
|
18057
18339
|
// src/modules/memory/store.ts
|
|
18058
|
-
import { readFileSync as
|
|
18340
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync11, appendFileSync as appendFileSync5, existsSync as existsSync31, mkdirSync as mkdirSync14 } from "fs";
|
|
18059
18341
|
import { join as join21 } from "path";
|
|
18060
18342
|
|
|
18061
18343
|
class MemoryStore {
|
|
@@ -18081,7 +18363,7 @@ class MemoryStore {
|
|
|
18081
18363
|
const path = join21(this.memoryDir, `${name}.md`);
|
|
18082
18364
|
if (!existsSync31(path))
|
|
18083
18365
|
return "";
|
|
18084
|
-
return
|
|
18366
|
+
return readFileSync17(path, "utf-8");
|
|
18085
18367
|
}
|
|
18086
18368
|
append(name, entry) {
|
|
18087
18369
|
const path = join21(this.memoryDir, `${name}.md`);
|
|
@@ -18102,7 +18384,7 @@ class MemoryStore {
|
|
|
18102
18384
|
if (!existsSync31(path))
|
|
18103
18385
|
return {};
|
|
18104
18386
|
try {
|
|
18105
|
-
return JSON.parse(
|
|
18387
|
+
return JSON.parse(readFileSync17(path, "utf-8"));
|
|
18106
18388
|
} catch {
|
|
18107
18389
|
return {};
|
|
18108
18390
|
}
|
|
@@ -19397,7 +19679,7 @@ __export(exports_image_utils, {
|
|
|
19397
19679
|
detectMime: () => detectMime,
|
|
19398
19680
|
bufferToDataUrl: () => bufferToDataUrl
|
|
19399
19681
|
});
|
|
19400
|
-
import { readFileSync as
|
|
19682
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
19401
19683
|
import { extname as extname4 } from "path";
|
|
19402
19684
|
function detectMime(filePath) {
|
|
19403
19685
|
const ext = extname4(filePath).toLowerCase();
|
|
@@ -19418,7 +19700,7 @@ async function readClipboardImage() {
|
|
|
19418
19700
|
async function readClipboardFallback() {
|
|
19419
19701
|
const { platform: platform6 } = await import("os");
|
|
19420
19702
|
const { execSync } = await import("child_process");
|
|
19421
|
-
const { readFileSync:
|
|
19703
|
+
const { readFileSync: readFileSync19, unlinkSync: unlinkSync5 } = await import("fs");
|
|
19422
19704
|
const { join: join27 } = await import("path");
|
|
19423
19705
|
if (platform6() !== "linux")
|
|
19424
19706
|
return null;
|
|
@@ -19430,7 +19712,7 @@ async function readClipboardFallback() {
|
|
|
19430
19712
|
for (const cmd of commands) {
|
|
19431
19713
|
try {
|
|
19432
19714
|
execSync(cmd, { timeout: 5000 });
|
|
19433
|
-
const buf =
|
|
19715
|
+
const buf = readFileSync19(tmpPath);
|
|
19434
19716
|
unlinkSync5(tmpPath);
|
|
19435
19717
|
if (buf.length > 0)
|
|
19436
19718
|
return buf;
|
|
@@ -19442,7 +19724,7 @@ async function readClipboardFallback() {
|
|
|
19442
19724
|
return null;
|
|
19443
19725
|
}
|
|
19444
19726
|
async function loadFileAsDataUrl(filePath) {
|
|
19445
|
-
const buf =
|
|
19727
|
+
const buf = readFileSync18(filePath);
|
|
19446
19728
|
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
19447
19729
|
try {
|
|
19448
19730
|
const img = new Bun.Image(buf);
|
|
@@ -20042,7 +20324,7 @@ var init_auto_fixer = __esm(() => {
|
|
|
20042
20324
|
|
|
20043
20325
|
// src/modules/plugins/builtin/lint-on-write.ts
|
|
20044
20326
|
import { spawn as spawn7, execSync } from "child_process";
|
|
20045
|
-
import { existsSync as existsSync35, readFileSync as
|
|
20327
|
+
import { existsSync as existsSync35, readFileSync as readFileSync19, writeFileSync as writeFileSync12 } from "fs";
|
|
20046
20328
|
import { resolve as resolve17, extname as extname6, join as join28 } from "path";
|
|
20047
20329
|
import { platform as platform6 } from "os";
|
|
20048
20330
|
function lintCacheKey(baseDir, lintScript) {
|
|
@@ -20143,7 +20425,7 @@ class LintOnWritePlugin {
|
|
|
20143
20425
|
if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
|
|
20144
20426
|
let content = "";
|
|
20145
20427
|
try {
|
|
20146
|
-
content =
|
|
20428
|
+
content = readFileSync19(filePath, "utf-8");
|
|
20147
20429
|
} catch {
|
|
20148
20430
|
return null;
|
|
20149
20431
|
}
|
|
@@ -20189,7 +20471,7 @@ class LintOnWritePlugin {
|
|
|
20189
20471
|
if (!existsSync35(packageJsonPath)) {
|
|
20190
20472
|
return;
|
|
20191
20473
|
}
|
|
20192
|
-
const packageJson = JSON.parse(
|
|
20474
|
+
const packageJson = JSON.parse(readFileSync19(packageJsonPath, "utf-8"));
|
|
20193
20475
|
lintScript = packageJson.scripts?.lint;
|
|
20194
20476
|
if (!lintScript) {
|
|
20195
20477
|
return;
|
|
@@ -20244,7 +20526,7 @@ ${stdout}`;
|
|
|
20244
20526
|
const output = stderr || stdout;
|
|
20245
20527
|
const errors = parseTscOutput(output);
|
|
20246
20528
|
if (errors.length > 0) {
|
|
20247
|
-
const fixResult = autoFixErrors(filePath,
|
|
20529
|
+
const fixResult = autoFixErrors(filePath, readFileSync19(filePath, "utf-8"), errors);
|
|
20248
20530
|
if (fixResult.fixed) {
|
|
20249
20531
|
writeFileSync12(filePath, fixResult.newContent, "utf-8");
|
|
20250
20532
|
result.output += `
|
|
@@ -20509,11 +20791,11 @@ class PlanTracker {
|
|
|
20509
20791
|
var init_tracker = () => {};
|
|
20510
20792
|
|
|
20511
20793
|
// src/modules/execution/plan-store.ts
|
|
20512
|
-
import { readFileSync as
|
|
20794
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, renameSync as renameSync3, mkdirSync as mkdirSync15, existsSync as existsSync36, readdirSync as readdirSync11, rmSync } from "fs";
|
|
20513
20795
|
import { join as join29 } from "path";
|
|
20514
20796
|
function readPlanFile(path, fallbackBaseDir) {
|
|
20515
20797
|
try {
|
|
20516
|
-
const raw =
|
|
20798
|
+
const raw = readFileSync20(path, "utf-8");
|
|
20517
20799
|
if (!raw.trim())
|
|
20518
20800
|
return null;
|
|
20519
20801
|
const parsed = JSON.parse(raw);
|
|
@@ -20725,6 +21007,17 @@ var init_windows_commands = __esm(() => {
|
|
|
20725
21007
|
FORBIDDEN_COMMANDS = new Set([
|
|
20726
21008
|
"grep",
|
|
20727
21009
|
"sed",
|
|
21010
|
+
"awk",
|
|
21011
|
+
"uniq",
|
|
21012
|
+
"xargs",
|
|
21013
|
+
"cut",
|
|
21014
|
+
"tr",
|
|
21015
|
+
"basename",
|
|
21016
|
+
"dirname",
|
|
21017
|
+
"export",
|
|
21018
|
+
"source",
|
|
21019
|
+
"sleep",
|
|
21020
|
+
"env",
|
|
20728
21021
|
"ls",
|
|
20729
21022
|
"find",
|
|
20730
21023
|
"rm",
|
|
@@ -21784,7 +22077,7 @@ var init_plan_tool = __esm(() => {
|
|
|
21784
22077
|
});
|
|
21785
22078
|
|
|
21786
22079
|
// src/modules/execution/module.ts
|
|
21787
|
-
import { existsSync as existsSync37, readFileSync as
|
|
22080
|
+
import { existsSync as existsSync37, readFileSync as readFileSync21 } from "fs";
|
|
21788
22081
|
import { resolve as resolve18 } from "path";
|
|
21789
22082
|
|
|
21790
22083
|
class ExecutionModule {
|
|
@@ -21934,14 +22227,35 @@ class ExecutionModule {
|
|
|
21934
22227
|
});
|
|
21935
22228
|
}).catch((e) => ctx.logger?.warn(`error web search: ${e.message}`));
|
|
21936
22229
|
}
|
|
22230
|
+
autoCloseEvidenceSteps(plan) {
|
|
22231
|
+
let closed = 0;
|
|
22232
|
+
for (const step of plan.steps) {
|
|
22233
|
+
if (step.status === "done" || step.status === "skipped")
|
|
22234
|
+
continue;
|
|
22235
|
+
const tokens = extractFileLikeTokens(stripUrls(step.description));
|
|
22236
|
+
if (tokens.length === 0)
|
|
22237
|
+
continue;
|
|
22238
|
+
const allExist = tokens.every((f) => findExistingFile(this.baseDir, f) !== null);
|
|
22239
|
+
if (!allExist)
|
|
22240
|
+
continue;
|
|
22241
|
+
step.status = "done";
|
|
22242
|
+
step.note = `auto-closed by final audit: all named files exist (${tokens.join(", ")})`;
|
|
22243
|
+
closed++;
|
|
22244
|
+
}
|
|
22245
|
+
return closed;
|
|
22246
|
+
}
|
|
21937
22247
|
async runFinalAudit() {
|
|
21938
22248
|
if (!this.tracker) {
|
|
21939
22249
|
if (!this.completedPlan)
|
|
21940
22250
|
return null;
|
|
21941
22251
|
const plan2 = this.completedPlan;
|
|
22252
|
+
const autoClosed2 = this.autoCloseEvidenceSteps(plan2);
|
|
21942
22253
|
const audit2 = await this.auditor.audit(plan2);
|
|
21943
22254
|
const pendingSteps2 = plan2.steps.flatMap((s) => s.status !== "done" && s.status !== "skipped" ? [`${s.id}. ${s.description}`] : []);
|
|
21944
22255
|
const done2 = plan2.steps.filter((s) => s.status === "done").length;
|
|
22256
|
+
if (autoClosed2 > 0) {
|
|
22257
|
+
this.store.saveActive(plan2);
|
|
22258
|
+
}
|
|
21945
22259
|
return {
|
|
21946
22260
|
passed: audit2.passed && pendingSteps2.length === 0,
|
|
21947
22261
|
done: done2,
|
|
@@ -21956,6 +22270,10 @@ class ExecutionModule {
|
|
|
21956
22270
|
return null;
|
|
21957
22271
|
}
|
|
21958
22272
|
const plan = this.tracker.getPlan();
|
|
22273
|
+
const autoClosed = this.autoCloseEvidenceSteps(plan);
|
|
22274
|
+
if (autoClosed > 0) {
|
|
22275
|
+
this.store.saveActive(plan);
|
|
22276
|
+
}
|
|
21959
22277
|
const audit = await this.auditor.audit(plan);
|
|
21960
22278
|
const pendingSteps = plan.steps.flatMap((s) => s.status !== "done" && s.status !== "skipped" ? [`${s.id}. ${s.description}`] : []);
|
|
21961
22279
|
const done = plan.steps.filter((s) => s.status === "done").length;
|
|
@@ -22150,7 +22468,7 @@ class ExecutionModule {
|
|
|
22150
22468
|
if (!r)
|
|
22151
22469
|
continue;
|
|
22152
22470
|
try {
|
|
22153
|
-
const content =
|
|
22471
|
+
const content = readFileSync21(r, "utf-8");
|
|
22154
22472
|
if (content.trim().length < 10) {
|
|
22155
22473
|
emptyFiles.push(r);
|
|
22156
22474
|
}
|
|
@@ -22258,7 +22576,7 @@ var init_module = __esm(() => {
|
|
|
22258
22576
|
});
|
|
22259
22577
|
|
|
22260
22578
|
// src/modules/security/session-encryption.ts
|
|
22261
|
-
import { readFileSync as
|
|
22579
|
+
import { readFileSync as readFileSync22, writeFileSync as writeFileSync14, existsSync as existsSync38, readdirSync as readdirSync12, unlinkSync as unlinkSync5 } from "fs";
|
|
22262
22580
|
import { join as join30 } from "path";
|
|
22263
22581
|
import { homedir as homedir9 } from "os";
|
|
22264
22582
|
|
|
@@ -22320,7 +22638,7 @@ class SessionFileEncryptor {
|
|
|
22320
22638
|
});
|
|
22321
22639
|
}
|
|
22322
22640
|
readSessionFile(filePath) {
|
|
22323
|
-
const content =
|
|
22641
|
+
const content = readFileSync22(filePath, "utf8");
|
|
22324
22642
|
return this.decryptFileContent(content);
|
|
22325
22643
|
}
|
|
22326
22644
|
writeSessionFile(filePath, content) {
|
|
@@ -22328,7 +22646,7 @@ class SessionFileEncryptor {
|
|
|
22328
22646
|
writeFileSync14(filePath, encrypted, "utf8");
|
|
22329
22647
|
}
|
|
22330
22648
|
readSessionJSON(filePath) {
|
|
22331
|
-
const content =
|
|
22649
|
+
const content = readFileSync22(filePath, "utf8");
|
|
22332
22650
|
return this.decryptJSON(content);
|
|
22333
22651
|
}
|
|
22334
22652
|
writeSessionJSON(filePath, obj) {
|
|
@@ -22336,7 +22654,7 @@ class SessionFileEncryptor {
|
|
|
22336
22654
|
writeFileSync14(filePath, content, "utf8");
|
|
22337
22655
|
}
|
|
22338
22656
|
readSessionJSONL(filePath) {
|
|
22339
|
-
const content =
|
|
22657
|
+
const content = readFileSync22(filePath, "utf8");
|
|
22340
22658
|
const lines = content.split(`
|
|
22341
22659
|
`).filter((line) => line.trim());
|
|
22342
22660
|
const decryptedLines = this.decryptJSONL(lines);
|
|
@@ -22364,7 +22682,7 @@ class SessionFileEncryptor {
|
|
|
22364
22682
|
const filePath = join30(sessionDir, file);
|
|
22365
22683
|
if (existsSync38(filePath) && !file.endsWith(".enc")) {
|
|
22366
22684
|
try {
|
|
22367
|
-
const content =
|
|
22685
|
+
const content = readFileSync22(filePath, "utf8");
|
|
22368
22686
|
const encrypted = this.encryptFileContent(content);
|
|
22369
22687
|
writeFileSync14(filePath + ".enc", encrypted, "utf8");
|
|
22370
22688
|
unlinkSync5(filePath);
|
|
@@ -22381,7 +22699,7 @@ class SessionFileEncryptor {
|
|
|
22381
22699
|
const encFilePath = join30(sessionDir, file);
|
|
22382
22700
|
const decFilePath = encFilePath.slice(0, -4);
|
|
22383
22701
|
try {
|
|
22384
|
-
const content =
|
|
22702
|
+
const content = readFileSync22(encFilePath, "utf8");
|
|
22385
22703
|
const decrypted = this.decryptFileContent(content);
|
|
22386
22704
|
writeFileSync14(decFilePath, decrypted, "utf8");
|
|
22387
22705
|
unlinkSync5(encFilePath);
|
|
@@ -22406,7 +22724,7 @@ import {
|
|
|
22406
22724
|
existsSync as existsSync39,
|
|
22407
22725
|
mkdirSync as mkdirSync16,
|
|
22408
22726
|
readdirSync as readdirSync13,
|
|
22409
|
-
readFileSync as
|
|
22727
|
+
readFileSync as readFileSync23,
|
|
22410
22728
|
rmSync as rmSync2,
|
|
22411
22729
|
writeFileSync as writeFileSync15,
|
|
22412
22730
|
appendFileSync as appendFileSync6
|
|
@@ -22474,7 +22792,7 @@ class SessionStore {
|
|
|
22474
22792
|
if (!existsSync39(path))
|
|
22475
22793
|
return null;
|
|
22476
22794
|
try {
|
|
22477
|
-
const raw =
|
|
22795
|
+
const raw = readFileSync23(path, "utf-8");
|
|
22478
22796
|
const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
|
|
22479
22797
|
const meta = JSON.parse(content);
|
|
22480
22798
|
this._metaCache.set(id, meta);
|
|
@@ -22488,7 +22806,7 @@ class SessionStore {
|
|
|
22488
22806
|
if (!existsSync39(path))
|
|
22489
22807
|
return null;
|
|
22490
22808
|
try {
|
|
22491
|
-
const raw =
|
|
22809
|
+
const raw = readFileSync23(path, "utf-8");
|
|
22492
22810
|
const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
|
|
22493
22811
|
return JSON.parse(content);
|
|
22494
22812
|
} catch {
|
|
@@ -22518,7 +22836,7 @@ class SessionStore {
|
|
|
22518
22836
|
if (!existsSync39(path))
|
|
22519
22837
|
return [];
|
|
22520
22838
|
try {
|
|
22521
|
-
const raw =
|
|
22839
|
+
const raw = readFileSync23(path, "utf-8");
|
|
22522
22840
|
const lines = raw.split(`
|
|
22523
22841
|
`).filter(Boolean);
|
|
22524
22842
|
const parseLine = (line) => {
|
|
@@ -22559,7 +22877,7 @@ class SessionStore {
|
|
|
22559
22877
|
if (!existsSync39(path))
|
|
22560
22878
|
return [];
|
|
22561
22879
|
try {
|
|
22562
|
-
const raw =
|
|
22880
|
+
const raw = readFileSync23(path, "utf-8");
|
|
22563
22881
|
const lines = raw.split(`
|
|
22564
22882
|
`).filter(Boolean);
|
|
22565
22883
|
const parseLine = (line) => {
|
|
@@ -22614,7 +22932,7 @@ class SessionStore {
|
|
|
22614
22932
|
if (updatedAt < thirtyDaysAgo) {
|
|
22615
22933
|
const historyPath = this.historyPath(session2.id);
|
|
22616
22934
|
if (existsSync39(historyPath)) {
|
|
22617
|
-
const content =
|
|
22935
|
+
const content = readFileSync23(historyPath, "utf-8");
|
|
22618
22936
|
const compressed = gzipSync(content);
|
|
22619
22937
|
const gzPath = join31(this.baseDir, `${session2.id}.jsonl.gz`);
|
|
22620
22938
|
writeFileSync15(gzPath, compressed);
|
|
@@ -22723,6 +23041,13 @@ class SessionManager {
|
|
|
22723
23041
|
return;
|
|
22724
23042
|
this.store.appendSessionLog(this.activeId, entry);
|
|
22725
23043
|
}
|
|
23044
|
+
loadSessionLog(id) {
|
|
23045
|
+
try {
|
|
23046
|
+
return this.store.loadSessionLog(id);
|
|
23047
|
+
} catch {
|
|
23048
|
+
return [];
|
|
23049
|
+
}
|
|
23050
|
+
}
|
|
22726
23051
|
loadHistory() {
|
|
22727
23052
|
if (!this.activeId)
|
|
22728
23053
|
return [];
|
|
@@ -22834,7 +23159,7 @@ class ProfileCompressor {
|
|
|
22834
23159
|
}
|
|
22835
23160
|
|
|
22836
23161
|
// src/modules/user-profile/profile.ts
|
|
22837
|
-
import { readFileSync as
|
|
23162
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync16, existsSync as existsSync40, mkdirSync as mkdirSync17 } from "fs";
|
|
22838
23163
|
import { join as join32 } from "path";
|
|
22839
23164
|
import { homedir as homedir10, hostname, platform as platform8, type } from "os";
|
|
22840
23165
|
import { env } from "process";
|
|
@@ -22869,7 +23194,7 @@ class UserProfile {
|
|
|
22869
23194
|
if (!existsSync40(path))
|
|
22870
23195
|
return null;
|
|
22871
23196
|
try {
|
|
22872
|
-
const data = JSON.parse(
|
|
23197
|
+
const data = JSON.parse(readFileSync24(path, "utf-8"));
|
|
22873
23198
|
this.info = {
|
|
22874
23199
|
platform: data.platform,
|
|
22875
23200
|
os: data.os,
|
|
@@ -22904,7 +23229,7 @@ class UserProfile {
|
|
|
22904
23229
|
var init_profile = () => {};
|
|
22905
23230
|
|
|
22906
23231
|
// src/modules/skills/loader.ts
|
|
22907
|
-
import { readdirSync as readdirSync14, readFileSync as
|
|
23232
|
+
import { readdirSync as readdirSync14, readFileSync as readFileSync25, existsSync as existsSync41, statSync as statSync7 } from "fs";
|
|
22908
23233
|
import { join as join33 } from "path";
|
|
22909
23234
|
|
|
22910
23235
|
class SkillsLoader {
|
|
@@ -22931,7 +23256,7 @@ class SkillsLoader {
|
|
|
22931
23256
|
}
|
|
22932
23257
|
if (!entry.endsWith(".md") && !entry.endsWith(".skill.md"))
|
|
22933
23258
|
continue;
|
|
22934
|
-
const content =
|
|
23259
|
+
const content = readFileSync25(fullPath, "utf-8");
|
|
22935
23260
|
const parsed = this.parseSkillFile(content, fullPath);
|
|
22936
23261
|
if (parsed)
|
|
22937
23262
|
skills.push(parsed);
|
|
@@ -23580,6 +23905,10 @@ var init_check_tool = __esm(() => {
|
|
|
23580
23905
|
// src/modules/lsp/module.ts
|
|
23581
23906
|
import { existsSync as existsSync42 } from "fs";
|
|
23582
23907
|
import { relative as relative5, resolve as resolve21 } from "path";
|
|
23908
|
+
import { join as join34 } from "path";
|
|
23909
|
+
function hasTypeEnvironment(projectRoot) {
|
|
23910
|
+
return existsSync42(join34(projectRoot, "tsconfig.json")) || existsSync42(join34(projectRoot, "jsconfig.json")) || existsSync42(join34(projectRoot, "node_modules"));
|
|
23911
|
+
}
|
|
23583
23912
|
|
|
23584
23913
|
class LspModule {
|
|
23585
23914
|
name = "lsp";
|
|
@@ -23734,6 +24063,7 @@ ${items}`;
|
|
|
23734
24063
|
const notes = [];
|
|
23735
24064
|
const checkedFiles = [];
|
|
23736
24065
|
let checked = 0;
|
|
24066
|
+
let suppressedTypeEnvDiags = 0;
|
|
23737
24067
|
for (const file of files) {
|
|
23738
24068
|
const serverConfig = getServerForFile(file, this.config);
|
|
23739
24069
|
if (!serverConfig)
|
|
@@ -23743,10 +24073,20 @@ ${items}`;
|
|
|
23743
24073
|
continue;
|
|
23744
24074
|
const projectRoot = findProjectRoot(file, ctx.baseDir, serverConfig.workspaceMarkers ?? []);
|
|
23745
24075
|
try {
|
|
23746
|
-
|
|
24076
|
+
let diags = await this.client.checkFile(file, ctx.baseDir, serverConfig, projectRoot);
|
|
23747
24077
|
this.failuresByServer.set(key, 0);
|
|
23748
24078
|
checked++;
|
|
23749
24079
|
checkedFiles.push(toForwardSlash(relative5(ctx.baseDir, file)));
|
|
24080
|
+
if (!hasTypeEnvironment(projectRoot)) {
|
|
24081
|
+
const kept = diags.filter((d) => {
|
|
24082
|
+
if (TYPE_ENV_DIAG_PATTERN.test(d.message)) {
|
|
24083
|
+
suppressedTypeEnvDiags++;
|
|
24084
|
+
return false;
|
|
24085
|
+
}
|
|
24086
|
+
return true;
|
|
24087
|
+
});
|
|
24088
|
+
diags = kept;
|
|
24089
|
+
}
|
|
23750
24090
|
for (const d of diags) {
|
|
23751
24091
|
if (d.severity === 1)
|
|
23752
24092
|
errors.push({ file, diag: d });
|
|
@@ -23784,6 +24124,9 @@ ${items}`;
|
|
|
23784
24124
|
if (checked > 0 && errors.length === 0 && warnings.length === 0) {
|
|
23785
24125
|
lines.push(t("lsp.check_clean", { count: String(checked) }));
|
|
23786
24126
|
}
|
|
24127
|
+
if (suppressedTypeEnvDiags > 0) {
|
|
24128
|
+
lines.push(`[lsp_check inconclusive: no tsconfig.json / node_modules near project root — ${suppressedTypeEnvDiags} module-resolution diagnostic(s) suppressed. Initialize the project (package.json + types) for accurate TypeScript checks.]`);
|
|
24129
|
+
}
|
|
23787
24130
|
lines.push(...notes);
|
|
23788
24131
|
if (lines.length === 0) {
|
|
23789
24132
|
return {
|
|
@@ -23805,7 +24148,7 @@ function formatDiagnostics(diagnostics, filePath) {
|
|
|
23805
24148
|
}).join(`
|
|
23806
24149
|
`);
|
|
23807
24150
|
}
|
|
23808
|
-
var MAX_CONSECUTIVE_LSP_FAILURES = 3;
|
|
24151
|
+
var MAX_CONSECUTIVE_LSP_FAILURES = 3, TYPE_ENV_DIAG_PATTERN;
|
|
23809
24152
|
var init_module5 = __esm(() => {
|
|
23810
24153
|
init_client2();
|
|
23811
24154
|
init_config();
|
|
@@ -23817,6 +24160,7 @@ var init_module5 = __esm(() => {
|
|
|
23817
24160
|
init_i18n();
|
|
23818
24161
|
init_check_tool();
|
|
23819
24162
|
init_utils();
|
|
24163
|
+
TYPE_ENV_DIAG_PATTERN = /Cannot find module ['"][^'"]+['"] or its corresponding type declarations|Cannot find name '(__dirname|__filename|require|process|Buffer|console)'|Do you need to install type definitions/;
|
|
23820
24164
|
});
|
|
23821
24165
|
|
|
23822
24166
|
// src/modules/lsp/index.ts
|
|
@@ -23828,7 +24172,7 @@ var init_lsp = __esm(() => {
|
|
|
23828
24172
|
|
|
23829
24173
|
// src/modules/lsp/startup-check.ts
|
|
23830
24174
|
import { existsSync as existsSync43 } from "fs";
|
|
23831
|
-
import { join as
|
|
24175
|
+
import { join as join35 } from "path";
|
|
23832
24176
|
import { spawn as spawn9 } from "child_process";
|
|
23833
24177
|
async function runStartupHealthCheck(config, baseDir, deps = {}) {
|
|
23834
24178
|
if (!config.enabled)
|
|
@@ -23855,7 +24199,7 @@ ${result.lines.join(`
|
|
|
23855
24199
|
}
|
|
23856
24200
|
async function runCheck(config, baseDir, deps) {
|
|
23857
24201
|
const projectRoot = findProjectRoot(baseDir, baseDir, ["tsconfig.json", "package.json"]);
|
|
23858
|
-
if (existsSync43(
|
|
24202
|
+
if (existsSync43(join35(projectRoot, "tsconfig.json"))) {
|
|
23859
24203
|
const runTsc = deps.runTsc ?? runTscDefault;
|
|
23860
24204
|
const errors = await runTsc(projectRoot, STARTUP_CHECK_TIMEOUT_MS);
|
|
23861
24205
|
if (errors.length === 0)
|
|
@@ -23957,8 +24301,8 @@ var init_startup_check = __esm(() => {
|
|
|
23957
24301
|
});
|
|
23958
24302
|
|
|
23959
24303
|
// src/modules/indexer/walker.ts
|
|
23960
|
-
import { readdirSync as readdirSync15, readFileSync as
|
|
23961
|
-
import { join as
|
|
24304
|
+
import { readdirSync as readdirSync15, readFileSync as readFileSync26, statSync as statSync8, lstatSync, existsSync as existsSync44, watch } from "fs";
|
|
24305
|
+
import { join as join36, relative as relative6, extname as extname7 } from "path";
|
|
23962
24306
|
|
|
23963
24307
|
class Indexer {
|
|
23964
24308
|
baseDir;
|
|
@@ -23996,7 +24340,7 @@ class Indexer {
|
|
|
23996
24340
|
for (const entry of entries) {
|
|
23997
24341
|
if (count >= this.MAX_FILES)
|
|
23998
24342
|
return;
|
|
23999
|
-
const fullPath =
|
|
24343
|
+
const fullPath = join36(dir, entry);
|
|
24000
24344
|
const relPath = relative6(this.baseDir, fullPath);
|
|
24001
24345
|
try {
|
|
24002
24346
|
const lst = lstatSync(fullPath, { throwIfNoEntry: false });
|
|
@@ -24011,7 +24355,7 @@ class Indexer {
|
|
|
24011
24355
|
const ext = extname7(entry).toLowerCase();
|
|
24012
24356
|
const language = LANGUAGES[ext];
|
|
24013
24357
|
if (language) {
|
|
24014
|
-
const content =
|
|
24358
|
+
const content = readFileSync26(fullPath, "utf-8");
|
|
24015
24359
|
const exports = this.extractExports(content, language);
|
|
24016
24360
|
files.push({ path: relPath, language, exports, size: stat2.size });
|
|
24017
24361
|
totalSize += stat2.size;
|
|
@@ -24069,14 +24413,14 @@ var init_walker = __esm(() => {
|
|
|
24069
24413
|
});
|
|
24070
24414
|
|
|
24071
24415
|
// src/modules/indexer/cache.ts
|
|
24072
|
-
import { readFileSync as
|
|
24073
|
-
import { join as
|
|
24416
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync17, existsSync as existsSync45, mkdirSync as mkdirSync18, rmSync as rmSync3 } from "fs";
|
|
24417
|
+
import { join as join37 } from "path";
|
|
24074
24418
|
|
|
24075
24419
|
class IndexCache {
|
|
24076
24420
|
cachePath;
|
|
24077
24421
|
cache = null;
|
|
24078
24422
|
constructor(cacheDir) {
|
|
24079
|
-
this.cachePath =
|
|
24423
|
+
this.cachePath = join37(cacheDir, "index-cache.json");
|
|
24080
24424
|
}
|
|
24081
24425
|
load() {
|
|
24082
24426
|
if (this.cache)
|
|
@@ -24084,7 +24428,7 @@ class IndexCache {
|
|
|
24084
24428
|
if (!existsSync45(this.cachePath))
|
|
24085
24429
|
return null;
|
|
24086
24430
|
try {
|
|
24087
|
-
this.cache = JSON.parse(
|
|
24431
|
+
this.cache = JSON.parse(readFileSync27(this.cachePath, "utf-8"));
|
|
24088
24432
|
return this.cache;
|
|
24089
24433
|
} catch {
|
|
24090
24434
|
return null;
|
|
@@ -24092,7 +24436,7 @@ class IndexCache {
|
|
|
24092
24436
|
}
|
|
24093
24437
|
save(result) {
|
|
24094
24438
|
this.cache = result;
|
|
24095
|
-
const dir =
|
|
24439
|
+
const dir = join37(this.cachePath, "..");
|
|
24096
24440
|
if (!existsSync45(dir))
|
|
24097
24441
|
mkdirSync18(dir, { recursive: true });
|
|
24098
24442
|
writeFileSync17(this.cachePath, JSON.stringify(result), "utf-8");
|
|
@@ -24109,11 +24453,11 @@ class IndexCache {
|
|
|
24109
24453
|
var init_cache = () => {};
|
|
24110
24454
|
|
|
24111
24455
|
// src/modules/indexer/project-profile.ts
|
|
24112
|
-
import { readFileSync as
|
|
24113
|
-
import { join as
|
|
24456
|
+
import { readFileSync as readFileSync28, existsSync as existsSync46 } from "fs";
|
|
24457
|
+
import { join as join38 } from "path";
|
|
24114
24458
|
function detectManifest(baseDir) {
|
|
24115
24459
|
for (const manifest of MANIFEST_ORDER) {
|
|
24116
|
-
if (existsSync46(
|
|
24460
|
+
if (existsSync46(join38(baseDir, manifest)))
|
|
24117
24461
|
return manifest;
|
|
24118
24462
|
}
|
|
24119
24463
|
return null;
|
|
@@ -24130,7 +24474,7 @@ function cleanDependency(entry) {
|
|
|
24130
24474
|
}
|
|
24131
24475
|
function readPackageJson(baseDir) {
|
|
24132
24476
|
try {
|
|
24133
|
-
const raw = JSON.parse(
|
|
24477
|
+
const raw = JSON.parse(readFileSync28(join38(baseDir, "package.json"), "utf-8"));
|
|
24134
24478
|
if (!raw || typeof raw !== "object")
|
|
24135
24479
|
return null;
|
|
24136
24480
|
const profile = {
|
|
@@ -24154,7 +24498,7 @@ function readPackageJson(baseDir) {
|
|
|
24154
24498
|
}
|
|
24155
24499
|
function readPyproject(baseDir) {
|
|
24156
24500
|
try {
|
|
24157
|
-
const content =
|
|
24501
|
+
const content = readFileSync28(join38(baseDir, "pyproject.toml"), "utf-8");
|
|
24158
24502
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
24159
24503
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
24160
24504
|
if (nameMatch)
|
|
@@ -24170,7 +24514,7 @@ function readPyproject(baseDir) {
|
|
|
24170
24514
|
}
|
|
24171
24515
|
function readCargo(baseDir) {
|
|
24172
24516
|
try {
|
|
24173
|
-
const content =
|
|
24517
|
+
const content = readFileSync28(join38(baseDir, "Cargo.toml"), "utf-8");
|
|
24174
24518
|
const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
|
|
24175
24519
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
24176
24520
|
if (nameMatch)
|
|
@@ -24194,7 +24538,7 @@ function readCargo(baseDir) {
|
|
|
24194
24538
|
}
|
|
24195
24539
|
function readGoMod(baseDir) {
|
|
24196
24540
|
try {
|
|
24197
|
-
const content =
|
|
24541
|
+
const content = readFileSync28(join38(baseDir, "go.mod"), "utf-8");
|
|
24198
24542
|
const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
|
|
24199
24543
|
const moduleMatch = content.match(/^module\s+(\S+)/m);
|
|
24200
24544
|
if (moduleMatch)
|
|
@@ -24212,7 +24556,7 @@ function readGoMod(baseDir) {
|
|
|
24212
24556
|
}
|
|
24213
24557
|
function readRequirements(baseDir) {
|
|
24214
24558
|
try {
|
|
24215
|
-
const content =
|
|
24559
|
+
const content = readFileSync28(join38(baseDir, "requirements.txt"), "utf-8");
|
|
24216
24560
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
24217
24561
|
for (const line of content.split(`
|
|
24218
24562
|
`)) {
|
|
@@ -24761,7 +25105,7 @@ var init_mcp = __esm(() => {
|
|
|
24761
25105
|
|
|
24762
25106
|
// src/modules/memory/module.ts
|
|
24763
25107
|
import { homedir as homedir11 } from "os";
|
|
24764
|
-
import { join as
|
|
25108
|
+
import { join as join39 } from "path";
|
|
24765
25109
|
|
|
24766
25110
|
class MemoryModule {
|
|
24767
25111
|
name = "memory";
|
|
@@ -24770,7 +25114,7 @@ class MemoryModule {
|
|
|
24770
25114
|
if (storeOrDir instanceof MemoryStore) {
|
|
24771
25115
|
this.store = storeOrDir;
|
|
24772
25116
|
} else {
|
|
24773
|
-
const dir = storeOrDir ||
|
|
25117
|
+
const dir = storeOrDir || join39(homedir11(), ".mma", "memory");
|
|
24774
25118
|
this.store = new MemoryStore(dir);
|
|
24775
25119
|
}
|
|
24776
25120
|
}
|
|
@@ -24857,16 +25201,16 @@ var init_module8 = __esm(() => {
|
|
|
24857
25201
|
});
|
|
24858
25202
|
|
|
24859
25203
|
// src/core/version.ts
|
|
24860
|
-
import { existsSync as existsSync47, readFileSync as
|
|
24861
|
-
import { join as
|
|
25204
|
+
import { existsSync as existsSync47, readFileSync as readFileSync29 } from "fs";
|
|
25205
|
+
import { join as join40, dirname as dirname15 } from "path";
|
|
24862
25206
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
24863
25207
|
function readMmaVersion() {
|
|
24864
25208
|
const here = dirname15(fileURLToPath2(import.meta.url));
|
|
24865
|
-
const candidates = [
|
|
25209
|
+
const candidates = [join40(here, "..", "..", "package.json"), join40(here, "..", "package.json")];
|
|
24866
25210
|
for (const p of candidates) {
|
|
24867
25211
|
if (existsSync47(p)) {
|
|
24868
25212
|
try {
|
|
24869
|
-
const raw = JSON.parse(
|
|
25213
|
+
const raw = JSON.parse(readFileSync29(p, "utf8"));
|
|
24870
25214
|
if (raw.version)
|
|
24871
25215
|
return raw.version;
|
|
24872
25216
|
} catch {}
|
|
@@ -24877,21 +25221,21 @@ function readMmaVersion() {
|
|
|
24877
25221
|
var init_version = () => {};
|
|
24878
25222
|
|
|
24879
25223
|
// src/core/environment.ts
|
|
24880
|
-
import { existsSync as existsSync48, readFileSync as
|
|
25224
|
+
import { existsSync as existsSync48, readFileSync as readFileSync30, readdirSync as readdirSync16 } from "fs";
|
|
24881
25225
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
24882
25226
|
import { createRequire as createRequire2 } from "module";
|
|
24883
|
-
import { join as
|
|
25227
|
+
import { join as join41, dirname as dirname16 } from "path";
|
|
24884
25228
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
24885
25229
|
import { arch, homedir as homedir12, hostname as hostname2, platform as platform10, release } from "os";
|
|
24886
25230
|
import { env as env2 } from "process";
|
|
24887
25231
|
function readEngineRequirement() {
|
|
24888
25232
|
const here = dirname16(fileURLToPath3(import.meta.url));
|
|
24889
|
-
const candidates = [
|
|
25233
|
+
const candidates = [join41(here, "..", "..", "package.json"), join41(here, "..", "package.json")];
|
|
24890
25234
|
for (const p of candidates) {
|
|
24891
25235
|
if (!existsSync48(p))
|
|
24892
25236
|
continue;
|
|
24893
25237
|
try {
|
|
24894
|
-
const raw = JSON.parse(
|
|
25238
|
+
const raw = JSON.parse(readFileSync30(p, "utf8"));
|
|
24895
25239
|
if (raw.engines?.node)
|
|
24896
25240
|
return String(raw.engines.node);
|
|
24897
25241
|
} catch {}
|
|
@@ -24954,7 +25298,7 @@ function toolVersion(cmd) {
|
|
|
24954
25298
|
function playwrightBrowsersDir() {
|
|
24955
25299
|
if (process.env.PLAYWRIGHT_BROWSERS_PATH)
|
|
24956
25300
|
return process.env.PLAYWRIGHT_BROWSERS_PATH;
|
|
24957
|
-
return process.platform === "win32" ?
|
|
25301
|
+
return process.platform === "win32" ? join41(homedir12(), "AppData", "Local", "ms-playwright") : join41(homedir12(), ".cache", "ms-playwright");
|
|
24958
25302
|
}
|
|
24959
25303
|
function playwrightInfo() {
|
|
24960
25304
|
let installed = false;
|
|
@@ -24964,7 +25308,7 @@ function playwrightInfo() {
|
|
|
24964
25308
|
const require2 = createRequire2(import.meta.url);
|
|
24965
25309
|
const pkgPath = require2.resolve("playwright/package.json");
|
|
24966
25310
|
installed = existsSync48(pkgPath);
|
|
24967
|
-
version = JSON.parse(
|
|
25311
|
+
version = JSON.parse(readFileSync30(pkgPath, "utf8")).version || "";
|
|
24968
25312
|
} catch {
|
|
24969
25313
|
installed = false;
|
|
24970
25314
|
}
|
|
@@ -25077,24 +25421,24 @@ __export(exports_manifest, {
|
|
|
25077
25421
|
getCertMark: () => getCertMark,
|
|
25078
25422
|
bundledManifestPath: () => bundledManifestPath
|
|
25079
25423
|
});
|
|
25080
|
-
import { existsSync as existsSync49, readFileSync as
|
|
25081
|
-
import { dirname as dirname17, join as
|
|
25424
|
+
import { existsSync as existsSync49, readFileSync as readFileSync31, mkdirSync as mkdirSync19, writeFileSync as writeFileSync18 } from "fs";
|
|
25425
|
+
import { dirname as dirname17, join as join42 } from "path";
|
|
25082
25426
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
25083
25427
|
import { homedir as homedir13 } from "os";
|
|
25084
25428
|
function manifestPath(projectDir) {
|
|
25085
|
-
return
|
|
25429
|
+
return join42(projectDir, "certification", "certifications.json");
|
|
25086
25430
|
}
|
|
25087
25431
|
function globalManifestDir(override) {
|
|
25088
|
-
return override || process.env.MMA_CERT_HOME ||
|
|
25432
|
+
return override || process.env.MMA_CERT_HOME || join42(homedir13(), ".mma");
|
|
25089
25433
|
}
|
|
25090
25434
|
function globalManifestPath(override) {
|
|
25091
|
-
return
|
|
25435
|
+
return join42(globalManifestDir(override), "certifications.json");
|
|
25092
25436
|
}
|
|
25093
25437
|
function readManifest(projectDir) {
|
|
25094
25438
|
const path = manifestPath(projectDir);
|
|
25095
25439
|
try {
|
|
25096
25440
|
if (existsSync49(path)) {
|
|
25097
|
-
const raw = JSON.parse(
|
|
25441
|
+
const raw = JSON.parse(readFileSync31(path, "utf-8"));
|
|
25098
25442
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
25099
25443
|
}
|
|
25100
25444
|
} catch {}
|
|
@@ -25102,14 +25446,14 @@ function readManifest(projectDir) {
|
|
|
25102
25446
|
}
|
|
25103
25447
|
function saveManifest(m, projectDir) {
|
|
25104
25448
|
const path = manifestPath(projectDir);
|
|
25105
|
-
mkdirSync19(
|
|
25449
|
+
mkdirSync19(join42(projectDir, "certification"), { recursive: true });
|
|
25106
25450
|
writeFileSync18(path, JSON.stringify(m, null, 2), "utf-8");
|
|
25107
25451
|
}
|
|
25108
25452
|
function readGlobalManifest(override) {
|
|
25109
25453
|
const path = globalManifestPath(override);
|
|
25110
25454
|
try {
|
|
25111
25455
|
if (existsSync49(path)) {
|
|
25112
|
-
const raw = JSON.parse(
|
|
25456
|
+
const raw = JSON.parse(readFileSync31(path, "utf-8"));
|
|
25113
25457
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
25114
25458
|
}
|
|
25115
25459
|
} catch {}
|
|
@@ -25175,14 +25519,14 @@ function getCertMark(model, providerUrl, currentVersion, projectDir, globalOverr
|
|
|
25175
25519
|
return isFullyPassed(entry) ? "certified" : "none";
|
|
25176
25520
|
}
|
|
25177
25521
|
function syncSnapshotPath(override) {
|
|
25178
|
-
return
|
|
25522
|
+
return join42(globalManifestDir(override), "certifications.synced.json");
|
|
25179
25523
|
}
|
|
25180
25524
|
function bundledManifestPath() {
|
|
25181
25525
|
const here = dirname17(fileURLToPath4(import.meta.url));
|
|
25182
25526
|
const candidates = [
|
|
25183
|
-
|
|
25184
|
-
|
|
25185
|
-
|
|
25527
|
+
join42(here, "certification", "certifications.json"),
|
|
25528
|
+
join42(here, "..", "certification", "certifications.json"),
|
|
25529
|
+
join42(here, "..", "..", "..", "certification", "certifications.json")
|
|
25186
25530
|
];
|
|
25187
25531
|
for (const p of candidates) {
|
|
25188
25532
|
if (existsSync49(p))
|
|
@@ -25195,9 +25539,9 @@ function syncGlobalManifest(override, bundledPathOverride) {
|
|
|
25195
25539
|
const bundledPath = bundledPathOverride ?? bundledManifestPath();
|
|
25196
25540
|
if (!bundledPath || !existsSync49(bundledPath))
|
|
25197
25541
|
return { synced: false, reason: "no-bundled" };
|
|
25198
|
-
const raw =
|
|
25542
|
+
const raw = readFileSync31(bundledPath, "utf-8");
|
|
25199
25543
|
const snapshotPath = syncSnapshotPath(override);
|
|
25200
|
-
if (existsSync49(snapshotPath) &&
|
|
25544
|
+
if (existsSync49(snapshotPath) && readFileSync31(snapshotPath, "utf-8") === raw) {
|
|
25201
25545
|
return { synced: false, reason: "unchanged" };
|
|
25202
25546
|
}
|
|
25203
25547
|
const bundled = JSON.parse(raw);
|
|
@@ -25227,11 +25571,11 @@ __export(exports_probe, {
|
|
|
25227
25571
|
getCachedProbeResult: () => getCachedProbeResult,
|
|
25228
25572
|
cacheKey: () => cacheKey
|
|
25229
25573
|
});
|
|
25230
|
-
import { existsSync as existsSync50, readFileSync as
|
|
25231
|
-
import { join as
|
|
25574
|
+
import { existsSync as existsSync50, readFileSync as readFileSync32, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
|
|
25575
|
+
import { join as join43, dirname as dirname18 } from "path";
|
|
25232
25576
|
import { homedir as homedir14 } from "os";
|
|
25233
25577
|
function cachePath() {
|
|
25234
|
-
return
|
|
25578
|
+
return join43(homedir14(), ".mma", "reasoning-cache.json");
|
|
25235
25579
|
}
|
|
25236
25580
|
async function probeReasoningSupport(provider, strategy, signal) {
|
|
25237
25581
|
if (strategy === "none")
|
|
@@ -25288,7 +25632,7 @@ function readDiskCache() {
|
|
|
25288
25632
|
try {
|
|
25289
25633
|
const path = cachePath();
|
|
25290
25634
|
if (existsSync50(path)) {
|
|
25291
|
-
return JSON.parse(
|
|
25635
|
+
return JSON.parse(readFileSync32(path, "utf-8"));
|
|
25292
25636
|
}
|
|
25293
25637
|
} catch {}
|
|
25294
25638
|
return {};
|
|
@@ -25389,8 +25733,8 @@ __export(exports_bootstrap, {
|
|
|
25389
25733
|
bootstrap: () => bootstrap
|
|
25390
25734
|
});
|
|
25391
25735
|
import { homedir as homedir15 } from "os";
|
|
25392
|
-
import { join as
|
|
25393
|
-
import { existsSync as existsSync51, readFileSync as
|
|
25736
|
+
import { join as join44, resolve as resolve22 } from "path";
|
|
25737
|
+
import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
|
|
25394
25738
|
function applyReasoningCliOverride(config, reasoningLevel) {
|
|
25395
25739
|
if (!reasoningLevel || reasoningLevel === "auto")
|
|
25396
25740
|
return;
|
|
@@ -25416,13 +25760,13 @@ function loadAgentsMdBlocks(baseDir, dir, skip) {
|
|
|
25416
25760
|
return [];
|
|
25417
25761
|
const blocks = [];
|
|
25418
25762
|
const candidates = [
|
|
25419
|
-
|
|
25420
|
-
|
|
25421
|
-
|
|
25763
|
+
join44(baseDir, "AGENTS.md"),
|
|
25764
|
+
join44(baseDir, ".mma", "AGENTS.md"),
|
|
25765
|
+
join44(dir, "AGENTS.md")
|
|
25422
25766
|
];
|
|
25423
25767
|
for (const p of candidates) {
|
|
25424
25768
|
if (existsSync51(p)) {
|
|
25425
|
-
const content =
|
|
25769
|
+
const content = readFileSync33(p, "utf-8").trim();
|
|
25426
25770
|
if (content) {
|
|
25427
25771
|
blocks.push({
|
|
25428
25772
|
content,
|
|
@@ -25499,8 +25843,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
25499
25843
|
`);
|
|
25500
25844
|
}
|
|
25501
25845
|
async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reasoningLevel) {
|
|
25502
|
-
const dir = configDir || process.env.MMA_CONFIG_DIR ||
|
|
25503
|
-
const projectConfigPath = projectDir ?
|
|
25846
|
+
const dir = configDir || process.env.MMA_CONFIG_DIR || join44(homedir15(), ".mma");
|
|
25847
|
+
const projectConfigPath = projectDir ? join44(projectDir, ".mmrc") : join44(process.cwd(), ".mmrc");
|
|
25504
25848
|
const { config, legacyDetected } = loadConfig({ configDir: dir, projectConfigPath });
|
|
25505
25849
|
setLocale(config.locale);
|
|
25506
25850
|
applyReasoningCliOverride(config, reasoningLevel);
|
|
@@ -25511,7 +25855,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25511
25855
|
}
|
|
25512
25856
|
} catch {}
|
|
25513
25857
|
const logger4 = new Logger(config.logLevel);
|
|
25514
|
-
logger4.setLogDir(
|
|
25858
|
+
logger4.setLogDir(join44(dir, "logs"));
|
|
25515
25859
|
logger4.debug("MMA bootstrap", {
|
|
25516
25860
|
version: config.version,
|
|
25517
25861
|
model: config.model
|
|
@@ -25540,7 +25884,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25540
25884
|
logger4.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
|
|
25541
25885
|
}
|
|
25542
25886
|
}
|
|
25543
|
-
const profile = new UserProfile(
|
|
25887
|
+
const profile = new UserProfile(join44(dir));
|
|
25544
25888
|
profile.load() || profile.collect();
|
|
25545
25889
|
profile.save();
|
|
25546
25890
|
const llmProvider = buildActiveProvider(config, logger4).provider;
|
|
@@ -25574,7 +25918,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25574
25918
|
for (const warning of envReport.warnings) {
|
|
25575
25919
|
logger4.warn(warning);
|
|
25576
25920
|
}
|
|
25577
|
-
const projectMapCacheDir =
|
|
25921
|
+
const projectMapCacheDir = join44(baseDir, ".mma");
|
|
25578
25922
|
const indexerModule = new IndexerModule({
|
|
25579
25923
|
baseDir,
|
|
25580
25924
|
cacheDir: projectMapCacheDir
|
|
@@ -25585,9 +25929,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25585
25929
|
logger4.warn(`Project indexing failed: ${err.message}`);
|
|
25586
25930
|
}
|
|
25587
25931
|
const skillsLoader = new SkillsLoader;
|
|
25588
|
-
const builtinDir =
|
|
25589
|
-
const globalDir =
|
|
25590
|
-
const projectSkillsDir =
|
|
25932
|
+
const builtinDir = join44(import.meta.dirname, "skills", "builtin");
|
|
25933
|
+
const globalDir = join44(homedir15(), ".agents", "skills");
|
|
25934
|
+
const projectSkillsDir = join44(baseDir, ".mma", "skills");
|
|
25591
25935
|
const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
|
|
25592
25936
|
const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
|
|
25593
25937
|
const skillsModule = new SkillsModule(availableSkills, skillsBudget);
|
|
@@ -25603,7 +25947,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25603
25947
|
essential: true,
|
|
25604
25948
|
estimatedTokens: estimateTokens(systemInfoContent)
|
|
25605
25949
|
};
|
|
25606
|
-
const sessionDir =
|
|
25950
|
+
const sessionDir = join44(dir, "sessions");
|
|
25607
25951
|
const sessionStore = new SessionStore(sessionDir);
|
|
25608
25952
|
sessionStore.init();
|
|
25609
25953
|
const sessionManager = new SessionManager(sessionStore, {
|
|
@@ -25687,7 +26031,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25687
26031
|
logger4.warn(`MCP init failed or timed out (${err instanceof Error ? err.message.slice(0, 120) : String(err)}) — continuing without MCP tools.`);
|
|
25688
26032
|
}
|
|
25689
26033
|
moduleRegistry.register(mcpModule);
|
|
25690
|
-
const memoryStore = new MemoryStore(
|
|
26034
|
+
const memoryStore = new MemoryStore(join44(dir, "memory"));
|
|
25691
26035
|
const memoryModule = new MemoryModule(memoryStore);
|
|
25692
26036
|
moduleRegistry.register(memoryModule);
|
|
25693
26037
|
if (config.browser.enabled) {
|
|
@@ -25714,8 +26058,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
25714
26058
|
pluginManager.register(plugin);
|
|
25715
26059
|
pluginManager.register(plugin2);
|
|
25716
26060
|
const pluginLoader = new PluginLoader;
|
|
25717
|
-
const globalPluginsDir =
|
|
25718
|
-
const projectPluginsDir =
|
|
26061
|
+
const globalPluginsDir = join44(homedir15(), ".mma", "plugins");
|
|
26062
|
+
const projectPluginsDir = join44(baseDir, ".mma", "plugins");
|
|
25719
26063
|
const mmaVersion = readMmaVersion();
|
|
25720
26064
|
pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger4, {
|
|
25721
26065
|
source: "global",
|
|
@@ -34087,6 +34431,50 @@ var init_scenarios = __esm(() => {
|
|
|
34087
34431
|
{ type: "fileContent", path: "file-b.txt", contains: "beta" }
|
|
34088
34432
|
]
|
|
34089
34433
|
},
|
|
34434
|
+
{
|
|
34435
|
+
id: "5.2-moe-parallel-waves",
|
|
34436
|
+
title: "MoE parallel waves with distinct deliverables",
|
|
34437
|
+
tags: ["moe"],
|
|
34438
|
+
mode: "run",
|
|
34439
|
+
timeoutMs: 600000,
|
|
34440
|
+
prompt: "Create three files. These are independent tasks that must run in parallel: wave-one.txt containing 'w1-done', wave-two.txt containing 'w2-done', and wave-three.txt containing 'w3-done'. After all three exist, report completion.",
|
|
34441
|
+
config: {
|
|
34442
|
+
moe: { enabled: true },
|
|
34443
|
+
orchestrator: { model: "" },
|
|
34444
|
+
experts: {
|
|
34445
|
+
code: { model: "", tool_tags: ["file", "code"], max_attempts: 3 }
|
|
34446
|
+
}
|
|
34447
|
+
},
|
|
34448
|
+
checks: [
|
|
34449
|
+
{ type: "fileExists", path: "wave-one.txt" },
|
|
34450
|
+
{ type: "fileExists", path: "wave-two.txt" },
|
|
34451
|
+
{ type: "fileExists", path: "wave-three.txt" },
|
|
34452
|
+
{ type: "fileContent", path: "wave-one.txt", contains: "w1-done" },
|
|
34453
|
+
{ type: "fileContent", path: "wave-two.txt", contains: "w2-done" },
|
|
34454
|
+
{ type: "fileContent", path: "wave-three.txt", contains: "w3-done" }
|
|
34455
|
+
]
|
|
34456
|
+
},
|
|
34457
|
+
{
|
|
34458
|
+
id: "5.3-moe-read-after-write",
|
|
34459
|
+
title: "MoE read-after-write via input_from dependency",
|
|
34460
|
+
tags: ["moe"],
|
|
34461
|
+
mode: "run",
|
|
34462
|
+
timeoutMs: 600000,
|
|
34463
|
+
prompt: "Two sequential steps. Step 1: create data.txt containing the exact token DATA_TOKEN_XYZ. Step 2 (depends on step 1 — it reads data.txt): create summary.txt that contains the exact token DATA_TOKEN_XYZ copied from data.txt. Step 2 must only run after data.txt exists.",
|
|
34464
|
+
config: {
|
|
34465
|
+
moe: { enabled: true },
|
|
34466
|
+
orchestrator: { model: "" },
|
|
34467
|
+
experts: {
|
|
34468
|
+
code: { model: "", tool_tags: ["file", "code"], max_attempts: 3 }
|
|
34469
|
+
}
|
|
34470
|
+
},
|
|
34471
|
+
checks: [
|
|
34472
|
+
{ type: "fileExists", path: "data.txt" },
|
|
34473
|
+
{ type: "fileExists", path: "summary.txt" },
|
|
34474
|
+
{ type: "fileContent", path: "data.txt", contains: "DATA_TOKEN_XYZ" },
|
|
34475
|
+
{ type: "fileContent", path: "summary.txt", contains: "DATA_TOKEN_XYZ" }
|
|
34476
|
+
]
|
|
34477
|
+
},
|
|
34090
34478
|
{
|
|
34091
34479
|
id: "6.2-project-map",
|
|
34092
34480
|
title: "Project map summary",
|
|
@@ -34117,8 +34505,8 @@ var init_scenarios = __esm(() => {
|
|
|
34117
34505
|
});
|
|
34118
34506
|
|
|
34119
34507
|
// src/modules/certification/loader.ts
|
|
34120
|
-
import { existsSync as existsSync53, readdirSync as readdirSync17, readFileSync as
|
|
34121
|
-
import { join as
|
|
34508
|
+
import { existsSync as existsSync53, readdirSync as readdirSync17, readFileSync as readFileSync35 } from "fs";
|
|
34509
|
+
import { join as join47 } from "path";
|
|
34122
34510
|
function validateScenario(s) {
|
|
34123
34511
|
const errors2 = [];
|
|
34124
34512
|
const isSkip = s.mode === "skip";
|
|
@@ -34175,7 +34563,7 @@ function loadScenarios(userDir) {
|
|
|
34175
34563
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
34176
34564
|
continue;
|
|
34177
34565
|
try {
|
|
34178
|
-
const raw =
|
|
34566
|
+
const raw = readFileSync35(join47(userDir, file), "utf-8");
|
|
34179
34567
|
const data = $parse(raw);
|
|
34180
34568
|
const parsed = normalizeScenario(data, file);
|
|
34181
34569
|
const errs = validateScenario(parsed);
|
|
@@ -34238,8 +34626,8 @@ var init_loader3 = __esm(() => {
|
|
|
34238
34626
|
});
|
|
34239
34627
|
|
|
34240
34628
|
// src/modules/certification/fact-checker.ts
|
|
34241
|
-
import { existsSync as existsSync54, readFileSync as
|
|
34242
|
-
import { join as
|
|
34629
|
+
import { existsSync as existsSync54, readFileSync as readFileSync36, statSync as statSync9 } from "fs";
|
|
34630
|
+
import { join as join48 } from "path";
|
|
34243
34631
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
34244
34632
|
const failures = [];
|
|
34245
34633
|
for (const check of checks) {
|
|
@@ -34256,16 +34644,16 @@ function runCheck2(sandboxDir, check, exitCode, output) {
|
|
|
34256
34644
|
case "outputContains":
|
|
34257
34645
|
return output.includes(check.text);
|
|
34258
34646
|
case "fileExists":
|
|
34259
|
-
return isFile(
|
|
34647
|
+
return isFile(join48(sandboxDir, check.path));
|
|
34260
34648
|
case "fileNotExists":
|
|
34261
|
-
return !existsSync54(
|
|
34649
|
+
return !existsSync54(join48(sandboxDir, check.path));
|
|
34262
34650
|
case "dirExists":
|
|
34263
|
-
return isDir(
|
|
34651
|
+
return isDir(join48(sandboxDir, check.path));
|
|
34264
34652
|
case "fileContent": {
|
|
34265
|
-
const abs =
|
|
34653
|
+
const abs = join48(sandboxDir, check.path);
|
|
34266
34654
|
if (!isFile(abs))
|
|
34267
34655
|
return false;
|
|
34268
|
-
const content =
|
|
34656
|
+
const content = readFileSync36(abs, "utf-8");
|
|
34269
34657
|
if (check.contains !== undefined)
|
|
34270
34658
|
return content.includes(check.contains);
|
|
34271
34659
|
if (check.equals !== undefined)
|
|
@@ -34273,10 +34661,10 @@ function runCheck2(sandboxDir, check, exitCode, output) {
|
|
|
34273
34661
|
return false;
|
|
34274
34662
|
}
|
|
34275
34663
|
case "fileRegex": {
|
|
34276
|
-
const abs =
|
|
34664
|
+
const abs = join48(sandboxDir, check.path);
|
|
34277
34665
|
if (!isFile(abs))
|
|
34278
34666
|
return false;
|
|
34279
|
-
return new RegExp(check.pattern).test(
|
|
34667
|
+
return new RegExp(check.pattern).test(readFileSync36(abs, "utf-8"));
|
|
34280
34668
|
}
|
|
34281
34669
|
default:
|
|
34282
34670
|
return false;
|
|
@@ -34322,8 +34710,8 @@ var init_fact_checker = () => {};
|
|
|
34322
34710
|
|
|
34323
34711
|
// src/modules/certification/runner.ts
|
|
34324
34712
|
import { spawn as spawn10 } from "child_process";
|
|
34325
|
-
import { existsSync as existsSync55, mkdirSync as mkdirSync21, rmSync as rmSync4, cpSync as cpSync2, writeFileSync as writeFileSync21, readdirSync as readdirSync18, readFileSync as
|
|
34326
|
-
import { join as
|
|
34713
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync21, rmSync as rmSync4, cpSync as cpSync2, writeFileSync as writeFileSync21, readdirSync as readdirSync18, readFileSync as readFileSync37 } from "fs";
|
|
34714
|
+
import { join as join49, resolve as resolve23, dirname as dirname21, relative as relative7 } from "path";
|
|
34327
34715
|
async function runScenario(scenario, opts) {
|
|
34328
34716
|
if (scenario.mode === "skip") {
|
|
34329
34717
|
return {
|
|
@@ -34343,7 +34731,7 @@ async function runScenario(scenario, opts) {
|
|
|
34343
34731
|
let firstError;
|
|
34344
34732
|
let lastFailedSandbox;
|
|
34345
34733
|
for (let i = 1;i <= reps; i++) {
|
|
34346
|
-
const sandbox =
|
|
34734
|
+
const sandbox = join49(opts.sandboxBase, `run-${scenario.id}-${i}`);
|
|
34347
34735
|
let failures = [];
|
|
34348
34736
|
let exitCode = -1;
|
|
34349
34737
|
let output = "";
|
|
@@ -34367,9 +34755,9 @@ async function runScenario(scenario, opts) {
|
|
|
34367
34755
|
env3.MMA_PROVIDER_APIKEY = opts.providerKey;
|
|
34368
34756
|
if (scenario.config && opts.baseConfig) {
|
|
34369
34757
|
const merged = deepMergeAny(opts.baseConfig, scenario.config);
|
|
34370
|
-
const certConfigDir =
|
|
34758
|
+
const certConfigDir = join49(sandbox, ".mma");
|
|
34371
34759
|
mkdirSync21(certConfigDir, { recursive: true });
|
|
34372
|
-
writeFileSync21(
|
|
34760
|
+
writeFileSync21(join49(certConfigDir, "config.json"), JSON.stringify(merged, null, 2), "utf-8");
|
|
34373
34761
|
env3.MMA_CONFIG_DIR = certConfigDir;
|
|
34374
34762
|
}
|
|
34375
34763
|
const res = await runner(env3, opts.mmaRoot, args, timeoutMs);
|
|
@@ -34416,11 +34804,11 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
34416
34804
|
rmSync4(sandbox, { recursive: true, force: true });
|
|
34417
34805
|
mkdirSync21(sandbox, { recursive: true });
|
|
34418
34806
|
for (const f of scenario.fixtures ?? []) {
|
|
34419
|
-
const src =
|
|
34807
|
+
const src = join49(mmaRoot, f.source);
|
|
34420
34808
|
if (!existsSync55(src)) {
|
|
34421
34809
|
throw new Error(`fixture missing: ${f.source}`);
|
|
34422
34810
|
}
|
|
34423
|
-
const dest =
|
|
34811
|
+
const dest = join49(sandbox, f.dest);
|
|
34424
34812
|
mkdirSync21(dirname21(dest), { recursive: true });
|
|
34425
34813
|
cpSync2(src, dest);
|
|
34426
34814
|
}
|
|
@@ -34433,10 +34821,10 @@ function collectDiagnostics(sandbox) {
|
|
|
34433
34821
|
} else {
|
|
34434
34822
|
lines.push(" Files created: (none)");
|
|
34435
34823
|
}
|
|
34436
|
-
const planPath =
|
|
34824
|
+
const planPath = join49(sandbox, ".mma", "plans", "active.json");
|
|
34437
34825
|
if (existsSync55(planPath)) {
|
|
34438
34826
|
try {
|
|
34439
|
-
const plan = JSON.parse(
|
|
34827
|
+
const plan = JSON.parse(readFileSync37(planPath, "utf-8"));
|
|
34440
34828
|
const steps = plan.steps ?? [];
|
|
34441
34829
|
const done = steps.filter((s) => s.status === "done").length;
|
|
34442
34830
|
const pending = steps.filter((s) => s.status === "pending" || s.status === "in_progress");
|
|
@@ -34455,7 +34843,7 @@ function listFiles(dir, root) {
|
|
|
34455
34843
|
for (const entry of readdirSync18(dir, { withFileTypes: true })) {
|
|
34456
34844
|
if (entry.name === ".mma")
|
|
34457
34845
|
continue;
|
|
34458
|
-
const abs =
|
|
34846
|
+
const abs = join49(dir, entry.name);
|
|
34459
34847
|
const rel = toForwardSlash(relative7(root, abs));
|
|
34460
34848
|
if (entry.isDirectory()) {
|
|
34461
34849
|
result.push(...listFiles(abs, root));
|
|
@@ -34467,15 +34855,15 @@ function listFiles(dir, root) {
|
|
|
34467
34855
|
return result;
|
|
34468
34856
|
}
|
|
34469
34857
|
function resolveMmaEntry(mmaRoot) {
|
|
34470
|
-
const dev =
|
|
34858
|
+
const dev = join49(mmaRoot, "src", "cli", "main.ts");
|
|
34471
34859
|
if (existsSync55(dev))
|
|
34472
34860
|
return dev;
|
|
34473
|
-
return
|
|
34861
|
+
return join49(mmaRoot, "dist", "main.js");
|
|
34474
34862
|
}
|
|
34475
34863
|
function findMmaRoot(fromDir) {
|
|
34476
34864
|
const candidates = [resolve23(fromDir, "..", "..", ".."), resolve23(fromDir, "..")];
|
|
34477
34865
|
for (const c of candidates) {
|
|
34478
|
-
if (existsSync55(
|
|
34866
|
+
if (existsSync55(join49(c, "package.json")))
|
|
34479
34867
|
return c;
|
|
34480
34868
|
}
|
|
34481
34869
|
return process.cwd();
|
|
@@ -34543,15 +34931,15 @@ __export(exports_cli, {
|
|
|
34543
34931
|
certList: () => certList
|
|
34544
34932
|
});
|
|
34545
34933
|
import { rmSync as rmSync5, writeFileSync as writeFileSync22 } from "fs";
|
|
34546
|
-
import { join as
|
|
34934
|
+
import { join as join50, dirname as dirname22 } from "path";
|
|
34547
34935
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
34548
|
-
import { existsSync as existsSync56, readFileSync as
|
|
34936
|
+
import { existsSync as existsSync56, readFileSync as readFileSync38 } from "fs";
|
|
34549
34937
|
function readVersion() {
|
|
34550
|
-
const candidates = [
|
|
34938
|
+
const candidates = [join50(MMA_ROOT, "package.json")];
|
|
34551
34939
|
for (const p of candidates) {
|
|
34552
34940
|
if (existsSync56(p)) {
|
|
34553
34941
|
try {
|
|
34554
|
-
const raw = JSON.parse(
|
|
34942
|
+
const raw = JSON.parse(readFileSync38(p, "utf-8"));
|
|
34555
34943
|
if (raw.version)
|
|
34556
34944
|
return raw.version;
|
|
34557
34945
|
} catch {}
|
|
@@ -34564,7 +34952,7 @@ function parseTags(s) {
|
|
|
34564
34952
|
}
|
|
34565
34953
|
async function certify(opts) {
|
|
34566
34954
|
const providerUrl = opts.providerUrl || opts.config.provider.baseUrl;
|
|
34567
|
-
const { scenarios, errors: errors2 } = loadScenarios(
|
|
34955
|
+
const { scenarios, errors: errors2 } = loadScenarios(join50(opts.projectDir, ".mma", "certification", "scenarios"));
|
|
34568
34956
|
for (const e of errors2)
|
|
34569
34957
|
console.error(pc2.yellow(` ${e}`));
|
|
34570
34958
|
let selected = filterByTags(scenarios, opts.tags);
|
|
@@ -34595,7 +34983,7 @@ async function certify(opts) {
|
|
|
34595
34983
|
return;
|
|
34596
34984
|
}
|
|
34597
34985
|
console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
|
|
34598
|
-
const sandboxBase =
|
|
34986
|
+
const sandboxBase = join50(process.cwd(), ".mma", "certification");
|
|
34599
34987
|
const results = [];
|
|
34600
34988
|
const total = selected.length;
|
|
34601
34989
|
let idx = 0;
|
|
@@ -34728,10 +35116,10 @@ function printResults(results) {
|
|
|
34728
35116
|
}
|
|
34729
35117
|
}
|
|
34730
35118
|
function writeReport(entry, projectDir) {
|
|
34731
|
-
const reportDir =
|
|
35119
|
+
const reportDir = join50(projectDir, "certification");
|
|
34732
35120
|
const ts = entry.certifiedAt.replace(/[:.]/g, "-").slice(0, 19);
|
|
34733
35121
|
const filename = `report-${entry.model.replace(/[/\\:]/g, "_")}-${ts}.json`;
|
|
34734
|
-
const reportPath =
|
|
35122
|
+
const reportPath = join50(reportDir, filename);
|
|
34735
35123
|
const report = {
|
|
34736
35124
|
model: entry.model,
|
|
34737
35125
|
providerUrl: entry.providerUrl,
|
|
@@ -34774,7 +35162,7 @@ __export(exports_repl_commands, {
|
|
|
34774
35162
|
registerAllCommands: () => registerAllCommands,
|
|
34775
35163
|
COMMAND_GROUPS: () => COMMAND_GROUPS
|
|
34776
35164
|
});
|
|
34777
|
-
import { join as
|
|
35165
|
+
import { join as join52, dirname as dirname24 } from "path";
|
|
34778
35166
|
import { existsSync as existsSync58 } from "fs";
|
|
34779
35167
|
function registerAllCommands(ctx) {
|
|
34780
35168
|
registerBuiltinCommands(ctx);
|
|
@@ -34957,7 +35345,7 @@ function registerConfigCommands(ctx) {
|
|
|
34957
35345
|
console.log(pc2.yellow(t("repl.wizard_running")));
|
|
34958
35346
|
await ctx.withExclusiveInput(async () => {
|
|
34959
35347
|
const answers = await runSetup(ctx.rl);
|
|
34960
|
-
const configPath =
|
|
35348
|
+
const configPath = join52(ctx.configDir, "config.json");
|
|
34961
35349
|
ctx.config.provider.type = answers.provider;
|
|
34962
35350
|
ctx.config.provider.baseUrl = answers.apiBase;
|
|
34963
35351
|
ctx.config.provider.apiKey = answers.apiKey;
|
|
@@ -35081,7 +35469,7 @@ function registerProviderCommands(ctx) {
|
|
|
35081
35469
|
return;
|
|
35082
35470
|
}
|
|
35083
35471
|
ctx.config.model = name;
|
|
35084
|
-
const configPath =
|
|
35472
|
+
const configPath = join52(ctx.configDir, "config.json");
|
|
35085
35473
|
saveConfig(ctx.config, configPath, dirname24(configPath));
|
|
35086
35474
|
await ctx.agent.reconfigure(ctx.config);
|
|
35087
35475
|
console.log(pc2.green(t("repl.model_set", { name })));
|
|
@@ -35106,7 +35494,7 @@ function registerProviderCommands(ctx) {
|
|
|
35106
35494
|
return;
|
|
35107
35495
|
}
|
|
35108
35496
|
ctx.config.contextWindow = size;
|
|
35109
|
-
const configPath =
|
|
35497
|
+
const configPath = join52(ctx.configDir, "config.json");
|
|
35110
35498
|
saveConfig(ctx.config, configPath, dirname24(configPath));
|
|
35111
35499
|
await ctx.agent.reconfigure(ctx.config);
|
|
35112
35500
|
console.log(pc2.green(t("cli.context_set", { size })));
|
|
@@ -35470,7 +35858,7 @@ async function runConfigMigrate(ctx) {
|
|
|
35470
35858
|
const { hasDomainFiles: hasDomainFiles3 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
35471
35859
|
const { loadConfig: loadCfg } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
35472
35860
|
const configDir = ctx.configDir;
|
|
35473
|
-
const configPath =
|
|
35861
|
+
const configPath = join52(configDir, "config.json");
|
|
35474
35862
|
if (hasDomainFiles3(configDir)) {
|
|
35475
35863
|
console.log(pc2.yellow(t("config.migrate_no_legacy")));
|
|
35476
35864
|
return;
|
|
@@ -35480,11 +35868,11 @@ async function runConfigMigrate(ctx) {
|
|
|
35480
35868
|
return;
|
|
35481
35869
|
}
|
|
35482
35870
|
console.log(t("config.migrate_start"));
|
|
35483
|
-
const { config } = loadCfg({ configDir, projectConfigPath:
|
|
35871
|
+
const { config } = loadCfg({ configDir, projectConfigPath: join52(configDir, ".mmrc") });
|
|
35484
35872
|
saveConfig(config, configPath, configDir);
|
|
35485
35873
|
const { renameSync: renameSync4, readdirSync: readdirSync19 } = await import("fs");
|
|
35486
35874
|
renameSync4(configPath, configPath + ".bak");
|
|
35487
|
-
const domainFiles = readdirSync19(
|
|
35875
|
+
const domainFiles = readdirSync19(join52(configDir, "config")).filter((f) => f.endsWith(".json"));
|
|
35488
35876
|
console.log(pc2.green(t("config.migrate_done", { count: String(domainFiles.length) })));
|
|
35489
35877
|
}
|
|
35490
35878
|
var version2, COMMAND_GROUPS;
|
|
@@ -35546,14 +35934,14 @@ init_config2();
|
|
|
35546
35934
|
init_setup();
|
|
35547
35935
|
init_i18n();
|
|
35548
35936
|
init_colors();
|
|
35549
|
-
import { join as
|
|
35937
|
+
import { join as join51, dirname as dirname23 } from "path";
|
|
35550
35938
|
import { homedir as homedir17 } from "os";
|
|
35551
35939
|
import { existsSync as existsSync57 } from "fs";
|
|
35552
35940
|
|
|
35553
35941
|
// src/cli/security-commands.ts
|
|
35554
35942
|
init_bootstrap();
|
|
35555
35943
|
init_config2();
|
|
35556
|
-
import { join as
|
|
35944
|
+
import { join as join45, dirname as dirname19 } from "path";
|
|
35557
35945
|
import { homedir as homedir16 } from "os";
|
|
35558
35946
|
|
|
35559
35947
|
// src/modules/security/security-policies.ts
|
|
@@ -36079,7 +36467,7 @@ function createSecurityCommand(program2) {
|
|
|
36079
36467
|
}
|
|
36080
36468
|
});
|
|
36081
36469
|
securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
|
|
36082
|
-
const configPath =
|
|
36470
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
36083
36471
|
const { config: appConfig } = await bootstrap();
|
|
36084
36472
|
const validPresets = ["strict", "balanced", "permissive"];
|
|
36085
36473
|
if (!validPresets.includes(preset)) {
|
|
@@ -36094,7 +36482,7 @@ function createSecurityCommand(program2) {
|
|
|
36094
36482
|
console.log(t("cli.security.policy_description", { description: policy.description }));
|
|
36095
36483
|
});
|
|
36096
36484
|
securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
|
|
36097
|
-
const configPath =
|
|
36485
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
36098
36486
|
const { config: appConfig } = await bootstrap();
|
|
36099
36487
|
const security = appConfig.security = appConfig.security || {};
|
|
36100
36488
|
toggleSessionEncryption(security, true);
|
|
@@ -36102,7 +36490,7 @@ function createSecurityCommand(program2) {
|
|
|
36102
36490
|
console.log(t("cli.security.encryption_enabled"));
|
|
36103
36491
|
});
|
|
36104
36492
|
securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
|
|
36105
|
-
const configPath =
|
|
36493
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
36106
36494
|
const { config: appConfig } = await bootstrap();
|
|
36107
36495
|
const security = appConfig.security = appConfig.security || {};
|
|
36108
36496
|
toggleSessionEncryption(security, false);
|
|
@@ -36110,7 +36498,7 @@ function createSecurityCommand(program2) {
|
|
|
36110
36498
|
console.log(t("cli.security.encryption_disabled"));
|
|
36111
36499
|
});
|
|
36112
36500
|
securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
|
|
36113
|
-
const configPath =
|
|
36501
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
36114
36502
|
const { config: appConfig } = await bootstrap();
|
|
36115
36503
|
const security = appConfig.security = appConfig.security || {};
|
|
36116
36504
|
toggleAuditNotifier(security, true);
|
|
@@ -36118,7 +36506,7 @@ function createSecurityCommand(program2) {
|
|
|
36118
36506
|
console.log(t("cli.security.audit_enabled"));
|
|
36119
36507
|
});
|
|
36120
36508
|
securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
|
|
36121
|
-
const configPath =
|
|
36509
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
36122
36510
|
const { config: appConfig } = await bootstrap();
|
|
36123
36511
|
const security = appConfig.security = appConfig.security || {};
|
|
36124
36512
|
toggleAuditNotifier(security, false);
|
|
@@ -36225,8 +36613,8 @@ function targetsFromProviders(entries) {
|
|
|
36225
36613
|
init_version();
|
|
36226
36614
|
|
|
36227
36615
|
// src/modules/updater/changelog-reader.ts
|
|
36228
|
-
import { readFileSync as
|
|
36229
|
-
import { dirname as dirname20, join as
|
|
36616
|
+
import { readFileSync as readFileSync34, existsSync as existsSync52 } from "fs";
|
|
36617
|
+
import { dirname as dirname20, join as join46 } from "path";
|
|
36230
36618
|
function readChangelog(packageName) {
|
|
36231
36619
|
try {
|
|
36232
36620
|
let dir = dirname20(import.meta.url);
|
|
@@ -36234,13 +36622,13 @@ function readChangelog(packageName) {
|
|
|
36234
36622
|
dir = decodeURIComponent(dir.slice(7));
|
|
36235
36623
|
}
|
|
36236
36624
|
for (let i = 0;i < 10; i++) {
|
|
36237
|
-
const pkgPath =
|
|
36625
|
+
const pkgPath = join46(dir, "package.json");
|
|
36238
36626
|
if (existsSync52(pkgPath)) {
|
|
36239
|
-
const pkg = JSON.parse(
|
|
36627
|
+
const pkg = JSON.parse(readFileSync34(pkgPath, "utf-8"));
|
|
36240
36628
|
if (pkg.name === packageName) {
|
|
36241
|
-
const changelogPath =
|
|
36629
|
+
const changelogPath = join46(dir, "CHANGELOG.md");
|
|
36242
36630
|
if (existsSync52(changelogPath)) {
|
|
36243
|
-
return
|
|
36631
|
+
return readFileSync34(changelogPath, "utf-8");
|
|
36244
36632
|
}
|
|
36245
36633
|
return null;
|
|
36246
36634
|
}
|
|
@@ -36307,7 +36695,7 @@ var version = readMmaVersion();
|
|
|
36307
36695
|
function buildInitCommand(program2) {
|
|
36308
36696
|
program2.command("init").description(t("cli.init")).action(async () => {
|
|
36309
36697
|
const answers = await runSetup();
|
|
36310
|
-
const configPath =
|
|
36698
|
+
const configPath = join51(homedir17(), ".mma", "config.json");
|
|
36311
36699
|
const { config } = await bootstrap();
|
|
36312
36700
|
config.provider.type = answers.provider;
|
|
36313
36701
|
config.provider.baseUrl = answers.apiBase;
|
|
@@ -36354,7 +36742,7 @@ function buildInitCommand(program2) {
|
|
|
36354
36742
|
function buildConfigCommands(program2) {
|
|
36355
36743
|
const configCmd = program2.command("config").description(t("cli.manage_config"));
|
|
36356
36744
|
configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
|
|
36357
|
-
const configPath =
|
|
36745
|
+
const configPath = join51(homedir17(), ".mma", "config.json");
|
|
36358
36746
|
const { config } = await bootstrap();
|
|
36359
36747
|
const keys = key.split(".");
|
|
36360
36748
|
let obj = config;
|
|
@@ -36384,8 +36772,8 @@ function buildConfigCommands(program2) {
|
|
|
36384
36772
|
configCmd.command("migrate").description(t("cli.migrate_config")).action(async () => {
|
|
36385
36773
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
36386
36774
|
const { hasDomainFiles: hasDomainFiles3 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
36387
|
-
const configDir =
|
|
36388
|
-
const configPath =
|
|
36775
|
+
const configDir = join51(homedir17(), ".mma");
|
|
36776
|
+
const configPath = join51(configDir, "config.json");
|
|
36389
36777
|
if (hasDomainFiles3(configDir)) {
|
|
36390
36778
|
console.log(pc2.yellow(t("config.migrate_no_legacy")));
|
|
36391
36779
|
return;
|
|
@@ -36395,13 +36783,13 @@ function buildConfigCommands(program2) {
|
|
|
36395
36783
|
return;
|
|
36396
36784
|
}
|
|
36397
36785
|
console.log(t("config.migrate_start"));
|
|
36398
|
-
const { config } = loadConfig2({ configDir, projectConfigPath:
|
|
36786
|
+
const { config } = loadConfig2({ configDir, projectConfigPath: join51(configDir, ".mmrc") });
|
|
36399
36787
|
saveConfig(config, configPath, configDir);
|
|
36400
36788
|
const bakPath = configPath + ".bak";
|
|
36401
36789
|
const { renameSync: renameSync4 } = await import("fs");
|
|
36402
36790
|
renameSync4(configPath, bakPath);
|
|
36403
36791
|
const { readdirSync: readdirSync19 } = await import("fs");
|
|
36404
|
-
const domainFiles = readdirSync19(
|
|
36792
|
+
const domainFiles = readdirSync19(join51(configDir, "config")).filter((f) => f.endsWith(".json"));
|
|
36405
36793
|
console.log(pc2.green(t("config.migrate_done", { count: String(domainFiles.length) })));
|
|
36406
36794
|
});
|
|
36407
36795
|
}
|
|
@@ -36443,7 +36831,7 @@ function buildModelCommands(program2) {
|
|
|
36443
36831
|
console.log(t("cli.model_hint"));
|
|
36444
36832
|
});
|
|
36445
36833
|
model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
|
|
36446
|
-
const configPath =
|
|
36834
|
+
const configPath = join51(homedir17(), ".mma", "config.json");
|
|
36447
36835
|
const { config } = await bootstrap();
|
|
36448
36836
|
config.model = name;
|
|
36449
36837
|
saveConfig(config, configPath, dirname23(configPath));
|
|
@@ -36484,7 +36872,7 @@ function buildModelCommands(program2) {
|
|
|
36484
36872
|
}
|
|
36485
36873
|
function buildContextCommand(program2) {
|
|
36486
36874
|
program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
|
|
36487
|
-
const configPath =
|
|
36875
|
+
const configPath = join51(homedir17(), ".mma", "config.json");
|
|
36488
36876
|
const { config } = await bootstrap();
|
|
36489
36877
|
const contextWindow = parseInt(size, 10);
|
|
36490
36878
|
if (isNaN(contextWindow) || contextWindow < 1024) {
|
|
@@ -36532,7 +36920,7 @@ function buildProviderCommands(program2) {
|
|
|
36532
36920
|
console.log(t("cli.base_url"), config.provider.baseUrl);
|
|
36533
36921
|
});
|
|
36534
36922
|
provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
|
|
36535
|
-
const configPath =
|
|
36923
|
+
const configPath = join51(homedir17(), ".mma", "config.json");
|
|
36536
36924
|
const { config, agent } = await bootstrap();
|
|
36537
36925
|
if (config.provider.entries && config.provider.entries.length > 0) {
|
|
36538
36926
|
try {
|
|
@@ -36555,7 +36943,7 @@ function buildProviderCommands(program2) {
|
|
|
36555
36943
|
}
|
|
36556
36944
|
});
|
|
36557
36945
|
provider.command("add").argument("<name>", "Provider type or label").option("--url <url>", "Base URL").option("--key <key>", "API key").option("--priority <n>", "Fallback priority (lower = tried first)").option("--context-window <n>", "Context window override for this entry").option("--rpm <n>", "Max requests per minute for this entry").option("--parallel <n>", "Max parallel tasks for this entry").description(t("cli.add_provider")).action(async (name, opts) => {
|
|
36558
|
-
const configPath =
|
|
36946
|
+
const configPath = join51(homedir17(), ".mma", "config.json");
|
|
36559
36947
|
const { config } = await bootstrap();
|
|
36560
36948
|
const entries = Array.isArray(config.provider.entries) ? config.provider.entries : [];
|
|
36561
36949
|
if (entries.length === 0) {
|
|
@@ -36622,6 +37010,24 @@ function buildSessionCommands(program2) {
|
|
|
36622
37010
|
console.log(`Model: ${meta.model}`);
|
|
36623
37011
|
console.log(`Context: ${meta.contextWindow}`);
|
|
36624
37012
|
console.log(`Project: ${meta.projectDir}`);
|
|
37013
|
+
const moeEvents = sessionManager.loadSessionLog(id).filter((e) => e.type.startsWith("moe_"));
|
|
37014
|
+
if (moeEvents.length > 0) {
|
|
37015
|
+
console.log("");
|
|
37016
|
+
console.log(pc2.cyan("MoE events:"));
|
|
37017
|
+
for (const e of moeEvents) {
|
|
37018
|
+
const ts = e.ts.slice(11, 19);
|
|
37019
|
+
if (e.type === "moe_subtask") {
|
|
37020
|
+
console.log(` ${pc2.dim(ts)} [subtask] ${e.subtaskId} (${e.expertTag}) ${e.status ?? ""}${e.durationMs !== undefined ? ` ${e.durationMs}ms` : ""}`);
|
|
37021
|
+
} else if (e.type === "moe_plan") {
|
|
37022
|
+
console.log(` ${pc2.dim(ts)} [plan] ${e.status === "ok" ? e.subtaskIds?.join(", ") : e.status}`);
|
|
37023
|
+
} else if (e.type === "moe_replan") {
|
|
37024
|
+
console.log(` ${pc2.dim(ts)} [replan] cycle ${e.cycle}: ${e.subtaskIds?.join(", ")}`);
|
|
37025
|
+
} else {
|
|
37026
|
+
const usage = e.usageByTag ? " | usage: " + Object.entries(e.usageByTag).map(([tag, u]) => `${tag}=${u.totalTokens}t`).join(", ") : "";
|
|
37027
|
+
console.log(` ${pc2.dim(ts)} [verify] ${e.decision ?? e.status ?? "?"}${e.explanation ? ` — ${e.explanation}` : ""}${usage}`);
|
|
37028
|
+
}
|
|
37029
|
+
}
|
|
37030
|
+
}
|
|
36625
37031
|
});
|
|
36626
37032
|
session2.command("delete").argument("<id>", "Session id").description(t("cli.delete_session")).action(async (id) => {
|
|
36627
37033
|
const { sessionManager } = await bootstrap();
|
|
@@ -36667,6 +37073,11 @@ function createProgram() {
|
|
|
36667
37073
|
createPluginCommand(program2);
|
|
36668
37074
|
buildChangelogCommand(program2);
|
|
36669
37075
|
program2.argument("[prompt...]", "Prompt to execute").description("Run a single prompt").action((prompt) => {});
|
|
37076
|
+
for (const cmd of program2.commands) {
|
|
37077
|
+
cmd.hook("postAction", () => {
|
|
37078
|
+
process.exit(0);
|
|
37079
|
+
});
|
|
37080
|
+
}
|
|
36670
37081
|
return program2;
|
|
36671
37082
|
}
|
|
36672
37083
|
|
|
@@ -37543,8 +37954,8 @@ class LineEditor {
|
|
|
37543
37954
|
}
|
|
37544
37955
|
|
|
37545
37956
|
// src/cli/repl.ts
|
|
37546
|
-
import { existsSync as existsSync59, readFileSync as
|
|
37547
|
-
import { join as
|
|
37957
|
+
import { existsSync as existsSync59, readFileSync as readFileSync40, writeFileSync as writeFileSync23 } from "fs";
|
|
37958
|
+
import { join as join53 } from "path";
|
|
37548
37959
|
import { homedir as homedir18 } from "os";
|
|
37549
37960
|
|
|
37550
37961
|
// src/cli/completer.ts
|
|
@@ -38376,10 +38787,10 @@ class Repl {
|
|
|
38376
38787
|
this.envReport = envReport;
|
|
38377
38788
|
this.execModule = execModule;
|
|
38378
38789
|
this.slog = new SessionLogger(sessionManager, logger4);
|
|
38379
|
-
this.configDir = configDir ||
|
|
38790
|
+
this.configDir = configDir || join53(homedir18(), ".mma");
|
|
38380
38791
|
this.baseDir = baseDir || process.cwd();
|
|
38381
38792
|
this.noAgentsMd = noAgentsMd === true;
|
|
38382
|
-
this.historyPath = historyPath ??
|
|
38793
|
+
this.historyPath = historyPath ?? join53(homedir18(), ".mma", "repl-history");
|
|
38383
38794
|
this.loadHistory();
|
|
38384
38795
|
this.rl = process.stdin.isTTY ? new LineEditor({
|
|
38385
38796
|
input: process.stdin,
|
|
@@ -38434,7 +38845,7 @@ class Repl {
|
|
|
38434
38845
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
38435
38846
|
const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
|
|
38436
38847
|
this.agent.shutdown();
|
|
38437
|
-
const projectConfigPath =
|
|
38848
|
+
const projectConfigPath = join53(this.baseDir, ".mmrc");
|
|
38438
38849
|
const { config: freshConfig } = loadConfig2({
|
|
38439
38850
|
configDir: this.configDir,
|
|
38440
38851
|
projectConfigPath
|
|
@@ -38452,7 +38863,7 @@ class Repl {
|
|
|
38452
38863
|
loadHistory() {
|
|
38453
38864
|
if (existsSync59(this.historyPath)) {
|
|
38454
38865
|
try {
|
|
38455
|
-
const raw =
|
|
38866
|
+
const raw = readFileSync40(this.historyPath, "utf-8");
|
|
38456
38867
|
this.history = raw.split(`
|
|
38457
38868
|
`).filter(Boolean).slice(-this.maxHistory);
|
|
38458
38869
|
} catch {
|
|
@@ -38853,9 +39264,9 @@ ${t("image.clipboard_empty")}`));
|
|
|
38853
39264
|
row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
|
|
38854
39265
|
} else {
|
|
38855
39266
|
const agentsMdCandidates = [
|
|
38856
|
-
|
|
38857
|
-
|
|
38858
|
-
|
|
39267
|
+
join53(this.baseDir, "AGENTS.md"),
|
|
39268
|
+
join53(this.baseDir, ".mma", "AGENTS.md"),
|
|
39269
|
+
join53(this.configDir, "AGENTS.md")
|
|
38859
39270
|
];
|
|
38860
39271
|
const foundAgents = agentsMdCandidates.filter((p) => existsSync59(p));
|
|
38861
39272
|
if (foundAgents.length > 0) {
|
|
@@ -38868,7 +39279,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
38868
39279
|
}
|
|
38869
39280
|
const meta = this.sessionManager?.getActiveMeta();
|
|
38870
39281
|
if (meta) {
|
|
38871
|
-
const sessionPath =
|
|
39282
|
+
const sessionPath = join53(this.configDir, "sessions", meta.id);
|
|
38872
39283
|
row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
|
|
38873
39284
|
}
|
|
38874
39285
|
const isTty2 = process.stdout.isTTY === true;
|
|
@@ -38984,7 +39395,7 @@ init_config2();
|
|
|
38984
39395
|
init_i18n();
|
|
38985
39396
|
init_colors();
|
|
38986
39397
|
import { existsSync as existsSync60 } from "fs";
|
|
38987
|
-
import { join as
|
|
39398
|
+
import { join as join55, dirname as dirname25 } from "path";
|
|
38988
39399
|
import { homedir as homedir20 } from "os";
|
|
38989
39400
|
|
|
38990
39401
|
// src/modules/updater/index.ts
|
|
@@ -39099,9 +39510,9 @@ init_data_sanitizer();
|
|
|
39099
39510
|
init_i18n();
|
|
39100
39511
|
init_utils();
|
|
39101
39512
|
import { appendFileSync as appendFileSync7, mkdirSync as mkdirSync22 } from "fs";
|
|
39102
|
-
import { join as
|
|
39513
|
+
import { join as join54 } from "path";
|
|
39103
39514
|
import { homedir as homedir19 } from "os";
|
|
39104
|
-
var CRASH_LOG_DIR =
|
|
39515
|
+
var CRASH_LOG_DIR = join54(homedir19(), ".mma", "logs");
|
|
39105
39516
|
var CRASH_LOG_FILE = "crash.jsonl";
|
|
39106
39517
|
function formatCrashEntry(type2, err) {
|
|
39107
39518
|
const message = errMsg(err);
|
|
@@ -39117,7 +39528,7 @@ function formatCrashEntry(type2, err) {
|
|
|
39117
39528
|
function writeCrashEntry(dir, entry) {
|
|
39118
39529
|
try {
|
|
39119
39530
|
mkdirSync22(dir, { recursive: true });
|
|
39120
|
-
appendFileSync7(
|
|
39531
|
+
appendFileSync7(join54(dir, CRASH_LOG_FILE), JSON.stringify(entry) + `
|
|
39121
39532
|
`, "utf-8");
|
|
39122
39533
|
} catch {}
|
|
39123
39534
|
}
|
|
@@ -39294,8 +39705,8 @@ async function main() {
|
|
|
39294
39705
|
await updater?.waitForIdle();
|
|
39295
39706
|
process.exit(exitCode);
|
|
39296
39707
|
} else {
|
|
39297
|
-
const mmaDir = process.env.MMA_CONFIG_DIR ||
|
|
39298
|
-
const legacyConfigPath =
|
|
39708
|
+
const mmaDir = process.env.MMA_CONFIG_DIR || join55(homedir20(), ".mma");
|
|
39709
|
+
const legacyConfigPath = join55(mmaDir, "config.json");
|
|
39299
39710
|
let hasAnyConfig = existsSync60(legacyConfigPath);
|
|
39300
39711
|
if (!hasAnyConfig) {
|
|
39301
39712
|
try {
|