micro-models-agent 0.61.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +619 -595
- package/README.md +358 -358
- package/dist/certification/certifications.json +493 -493
- package/dist/cli/commands.js +447 -0
- package/dist/cli/completer.js +167 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/main.js +153 -0
- package/dist/cli/plugin-commands.js +36 -0
- package/dist/cli/repl-commands.js +761 -0
- package/dist/cli/repl.js +702 -0
- package/dist/cli/run-result.js +33 -0
- package/dist/cli/security-commands.js +164 -0
- package/dist/cli/setup.js +237 -0
- package/dist/config/config.js +276 -0
- package/dist/config/defaults.js +141 -0
- package/dist/config/domains.js +179 -0
- package/dist/config/experts.js +15 -0
- package/dist/config/index.js +4 -0
- package/dist/config/security.js +213 -0
- package/dist/config/types.js +1 -0
- package/dist/core/agent-moe.js +102 -0
- package/dist/core/agent.js +1018 -0
- package/dist/core/bootstrap.js +481 -0
- package/dist/core/crash-handler.js +51 -0
- package/dist/core/environment.js +199 -0
- package/dist/core/index.js +2 -0
- package/dist/core/prompt-builder.js +76 -0
- package/dist/core/session-logger.js +251 -0
- package/dist/core/types.js +1 -0
- package/dist/core/version.js +26 -0
- package/dist/core/workspace.js +76 -0
- package/dist/i18n/en.json +776 -757
- package/dist/i18n/index.js +46 -0
- package/dist/i18n/ru.json +776 -757
- package/dist/index.js +22 -0
- package/dist/llm/image-utils.js +143 -0
- package/dist/llm/index.js +4 -0
- package/dist/llm/model-loader.js +78 -0
- package/dist/llm/openai-compat.js +497 -0
- package/dist/llm/orchestrator.js +200 -0
- package/dist/llm/provider.js +10 -0
- package/dist/llm/response.js +39 -0
- package/dist/llm/token-counter.js +39 -0
- package/dist/llm/types.js +1 -0
- package/dist/logger/app-logger.js +189 -0
- package/dist/logger/file-log.js +151 -0
- package/dist/logger/index.js +1 -0
- package/dist/main.js +1026 -417
- package/dist/migration/backup.js +45 -0
- package/dist/migration/detect.js +50 -0
- package/dist/migration/index.js +2 -0
- package/dist/modules/artifacts/store.js +61 -0
- package/dist/modules/browser/actions.js +76 -0
- package/dist/modules/browser/bridge-client.js +199 -0
- package/dist/modules/browser/bridge-path.js +10 -0
- package/dist/modules/browser/bridge-server.mjs +219 -219
- package/dist/modules/browser/cookie-store.js +24 -0
- package/dist/modules/browser/driver.js +136 -0
- package/dist/modules/browser/index.js +7 -0
- package/dist/modules/browser/module.js +29 -0
- package/dist/modules/browser/session.js +342 -0
- package/dist/modules/browser/snapshot.js +148 -0
- package/dist/modules/browser/types.js +12 -0
- package/dist/modules/certification/cli.js +213 -0
- package/dist/modules/certification/fact-checker.js +82 -0
- package/dist/modules/certification/loader.js +106 -0
- package/dist/modules/certification/manifest.js +58 -0
- package/dist/modules/certification/runner.js +245 -0
- package/dist/modules/certification/scenarios.js +407 -0
- package/dist/modules/certification/types.js +1 -0
- package/dist/modules/context/chunk-query.js +100 -0
- package/dist/modules/context/fact-extractor.js +168 -0
- package/dist/modules/context/history.js +15 -0
- package/dist/modules/context/index.js +1 -0
- package/dist/modules/context/manager.js +440 -0
- package/dist/modules/execution/audit-runners.js +206 -0
- package/dist/modules/execution/auditor.js +218 -0
- package/dist/modules/execution/execution-plugin.js +431 -0
- package/dist/modules/execution/index.js +8 -0
- package/dist/modules/execution/module.js +625 -0
- package/dist/modules/execution/moe-executor.js +304 -0
- package/dist/modules/execution/plan-coverage.js +68 -0
- package/dist/modules/execution/plan-persister.js +46 -0
- package/dist/modules/execution/plan-store.js +196 -0
- package/dist/modules/execution/plan-tool.js +677 -0
- package/dist/modules/execution/plan-validator.js +153 -0
- package/dist/modules/execution/planner.js +94 -0
- package/dist/modules/execution/stuck-detector.js +746 -0
- package/dist/modules/execution/tracker.js +69 -0
- package/dist/modules/execution/types.js +1 -0
- package/dist/modules/execution/verifier.js +235 -0
- package/dist/modules/execution/windows-commands.js +41 -0
- package/dist/modules/hallucination/confidence.js +66 -0
- package/dist/modules/hallucination/consistency.js +26 -0
- package/dist/modules/hallucination/detector.js +47 -0
- package/dist/modules/hallucination/factual.js +169 -0
- package/dist/modules/hallucination/index.js +5 -0
- package/dist/modules/hallucination/js-identifiers.js +262 -0
- package/dist/modules/hallucination/llm-judge.js +101 -0
- package/dist/modules/index.js +5 -0
- package/dist/modules/indexer/cache.js +40 -0
- package/dist/modules/indexer/index.js +3 -0
- package/dist/modules/indexer/module.js +246 -0
- package/dist/modules/indexer/project-profile.js +183 -0
- package/dist/modules/indexer/walker.js +101 -0
- package/dist/modules/lsp/check-tool.js +58 -0
- package/dist/modules/lsp/client.js +389 -0
- package/dist/modules/lsp/command.js +60 -0
- package/dist/modules/lsp/config.js +135 -0
- package/dist/modules/lsp/index.js +3 -0
- package/dist/modules/lsp/module.js +260 -0
- package/dist/modules/lsp/probe.js +86 -0
- package/dist/modules/lsp/project-root.js +32 -0
- package/dist/modules/lsp/startup-check.js +144 -0
- package/dist/modules/lsp/types.js +1 -0
- package/dist/modules/mcp/client.js +399 -0
- package/dist/modules/mcp/index.js +3 -0
- package/dist/modules/mcp/module.js +142 -0
- package/dist/modules/mcp/registry.js +15 -0
- package/dist/modules/memory/index.js +1 -0
- package/dist/modules/memory/module.js +96 -0
- package/dist/modules/memory/search.js +42 -0
- package/dist/modules/memory/store.js +69 -0
- package/dist/modules/pipelines/engine.js +60 -0
- package/dist/modules/pipelines/index.js +3 -0
- package/dist/modules/pipelines/parser.js +56 -0
- package/dist/modules/pipelines/template.js +14 -0
- package/dist/modules/plugins/builtin/lint-on-write.js +334 -0
- package/dist/modules/plugins/builtin/notify.js +9 -0
- package/dist/modules/plugins/index.js +1 -0
- package/dist/modules/plugins/loader.js +70 -0
- package/dist/modules/plugins/manager.js +261 -0
- package/dist/modules/plugins/types.js +1 -0
- package/dist/modules/pricing/index.js +61 -0
- package/dist/modules/pricing/prices.js +129 -0
- package/dist/modules/processes/detect.js +34 -0
- package/dist/modules/processes/index.js +2 -0
- package/dist/modules/processes/registry.js +327 -0
- package/dist/modules/processes/runner.js +23 -0
- package/dist/modules/providers/create.js +22 -0
- package/dist/modules/providers/fallback.js +79 -0
- package/dist/modules/providers/health.js +46 -0
- package/dist/modules/providers/index.js +5 -0
- package/dist/modules/providers/manager.js +161 -0
- package/dist/modules/providers/presets.js +128 -0
- package/dist/modules/providers/registry.js +22 -0
- package/dist/modules/providers/types.js +1 -0
- package/dist/modules/registry.js +48 -0
- package/dist/modules/security/audit-log.js +136 -0
- package/dist/modules/security/audit-notifier.js +292 -0
- package/dist/modules/security/command-validator.js +219 -0
- package/dist/modules/security/content-scanner.js +53 -0
- package/dist/modules/security/data-sanitizer.js +89 -0
- package/dist/modules/security/encryption.js +242 -0
- package/dist/modules/security/index.js +14 -0
- package/dist/modules/security/network-validator.js +88 -0
- package/dist/modules/security/path-validator.js +203 -0
- package/dist/modules/security/rate-limiter.js +119 -0
- package/dist/modules/security/security-policies.js +531 -0
- package/dist/modules/security/session-encryption.js +210 -0
- package/dist/modules/security/session-isolation.js +95 -0
- package/dist/modules/session/index.js +3 -0
- package/dist/modules/session/manager.js +172 -0
- package/dist/modules/session/module.js +24 -0
- package/dist/modules/session/store.js +222 -0
- package/dist/modules/session/types.js +1 -0
- package/dist/modules/skills/index.js +2 -0
- package/dist/modules/skills/loader.js +72 -0
- package/dist/modules/skills/matcher.js +27 -0
- package/dist/modules/skills/module.js +129 -0
- package/dist/modules/types.js +1 -0
- package/dist/modules/updater/checker.js +96 -0
- package/dist/modules/updater/index.js +2 -0
- package/dist/modules/updater/module.js +116 -0
- package/dist/modules/user-profile/compressor.js +16 -0
- package/dist/modules/user-profile/index.js +1 -0
- package/dist/modules/user-profile/profile.js +68 -0
- package/dist/skills/builtin/git.md +36 -36
- package/dist/skills/builtin/typescript.md +35 -35
- package/dist/tools/approve.js +33 -0
- package/dist/tools/attach-image.js +101 -0
- package/dist/tools/bash.js +519 -0
- package/dist/tools/browser.js +115 -0
- package/dist/tools/chunk-query.js +100 -0
- package/dist/tools/create-dir.js +56 -0
- package/dist/tools/delete-file.js +63 -0
- package/dist/tools/download-file.js +117 -0
- package/dist/tools/edit-file.js +80 -0
- package/dist/tools/enable-tools.js +59 -0
- package/dist/tools/executor.js +154 -0
- package/dist/tools/file-info.js +47 -0
- package/dist/tools/filter-tools.js +17 -0
- package/dist/tools/glob-tool.js +27 -0
- package/dist/tools/grep-tool.js +125 -0
- package/dist/tools/hidden-tools-block.js +37 -0
- package/dist/tools/index.js +78 -0
- package/dist/tools/list-dir.js +49 -0
- package/dist/tools/load-skill.js +43 -0
- package/dist/tools/mcp-call.js +69 -0
- package/dist/tools/move-file.js +86 -0
- package/dist/tools/path-utils.js +101 -0
- package/dist/tools/pipeline-run.js +145 -0
- package/dist/tools/preview.js +2 -0
- package/dist/tools/process-kill.js +40 -0
- package/dist/tools/process-list.js +37 -0
- package/dist/tools/process-log.js +54 -0
- package/dist/tools/question.js +141 -0
- package/dist/tools/read-file.js +179 -0
- package/dist/tools/recall.js +118 -0
- package/dist/tools/registry.js +47 -0
- package/dist/tools/remember.js +68 -0
- package/dist/tools/scope-check.js +32 -0
- package/dist/tools/search-history.js +85 -0
- package/dist/tools/subagent.js +196 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/user-input.js +123 -0
- package/dist/tools/web-browse.js +87 -0
- package/dist/tools/web-fetch.js +119 -0
- package/dist/tools/web-search.js +105 -0
- package/dist/tools/write-file.js +82 -0
- package/dist/ui/box.js +77 -0
- package/dist/ui/colors.js +4 -0
- package/dist/ui/diff.js +178 -0
- package/dist/ui/index.js +6 -0
- package/dist/ui/line-editor.js +822 -0
- package/dist/ui/line-math.js +73 -0
- package/dist/ui/md-formatter.js +212 -0
- package/dist/ui/output.js +13 -0
- package/dist/ui/plan-view.js +103 -0
- package/dist/ui/renderer.js +259 -0
- package/dist/ui/spinner.js +70 -0
- package/dist/ui/table.js +144 -0
- package/package.json +51 -51
package/dist/main.js
CHANGED
|
@@ -3188,6 +3188,25 @@ Apply a matching solution from these results. If none is relevant — do NOT rep
|
|
|
3188
3188
|
"repl.cost": "Total cost: {cost}",
|
|
3189
3189
|
"repl.cost_breakdown": "By provider: {breakdown}",
|
|
3190
3190
|
"repl.tokens": "Tokens used: {tokens}",
|
|
3191
|
+
"repl.cache": "Cache: {hit}% hit · saved {saved}",
|
|
3192
|
+
"repl.cache_nosave": "Cache: {hit}% hit",
|
|
3193
|
+
"repl.prefix": "Prefix stable: {stable}% · broke: {cause}",
|
|
3194
|
+
"cache.cause.system": "system prompt",
|
|
3195
|
+
"cache.cause.tools": "tool set",
|
|
3196
|
+
"cache.cause.history": "history",
|
|
3197
|
+
"cache.cause.volatile": "volatile content",
|
|
3198
|
+
"cache.cause.unknown": "unknown",
|
|
3199
|
+
"cli.session_usage": "API usage: {prompt} prompt + {completion} completion = {total} tokens",
|
|
3200
|
+
"cli.session_cache": "Cache: {hit}% hit ({cached} cached / {uncached} uncached)",
|
|
3201
|
+
"cli.usage": "Show provider balance/usage (OpenRouter)",
|
|
3202
|
+
"cli.usage_unsupported": 'Provider "{provider}" does not expose an API balance. Only OpenRouter does; OpenCode Zen/Go show it in the web dashboard.',
|
|
3203
|
+
"cli.usage_no_key": "No API key configured for the active provider.",
|
|
3204
|
+
"cli.usage_error": "Failed to fetch balance: {error}",
|
|
3205
|
+
"cli.usage_key_usage": "Key usage: {usage}",
|
|
3206
|
+
"cli.usage_key_limit": "Key limit: {limit} · remaining {remaining}",
|
|
3207
|
+
"cli.usage_balance": "Balance: {balance}",
|
|
3208
|
+
"cli.usage_account": "Account: {credits} purchased · {used} used",
|
|
3209
|
+
"cli.usage_empty": "No balance information returned.",
|
|
3191
3210
|
"repl.ctrl_c_interrupt": `
|
|
3192
3211
|
[Ctrl+C] Stopping agent... (press again to force)`,
|
|
3193
3212
|
"exec.stop_directive": 'STOP. Step {stepId} ("{description}") took {iterations} iterations with no progress. DO NOT continue this step. Immediately call: plan update step={stepId} status=done (if code works despite warnings) OR plan update step={stepId} status=skipped note="reason". Do NOT make any other tool calls before updating the plan.',
|
|
@@ -4005,6 +4024,25 @@ var init_ru = __esm(() => {
|
|
|
4005
4024
|
"repl.cost": "Итого потрачено: {cost}",
|
|
4006
4025
|
"repl.cost_breakdown": "По провайдерам: {breakdown}",
|
|
4007
4026
|
"repl.tokens": "Потрачено токенов: {tokens}",
|
|
4027
|
+
"repl.cache": "Кеш: {hit}% попаданий · сэкономлено {saved}",
|
|
4028
|
+
"repl.cache_nosave": "Кеш: {hit}% попаданий",
|
|
4029
|
+
"repl.prefix": "Префикс стабилен: {stable}% · сломалось: {cause}",
|
|
4030
|
+
"cache.cause.system": "системный промпт",
|
|
4031
|
+
"cache.cause.tools": "набор инструментов",
|
|
4032
|
+
"cache.cause.history": "история",
|
|
4033
|
+
"cache.cause.volatile": "волатильное содержимое",
|
|
4034
|
+
"cache.cause.unknown": "неизвестно",
|
|
4035
|
+
"cli.session_usage": "API-использование: {prompt} prompt + {completion} completion = {total} токенов",
|
|
4036
|
+
"cli.session_cache": "Кеш: {hit}% попаданий ({cached} из кеша / {uncached} новых)",
|
|
4037
|
+
"cli.usage": "Показать баланс/расход провайдера (OpenRouter)",
|
|
4038
|
+
"cli.usage_unsupported": 'Провайдер "{provider}" не отдаёт баланс по API. Это умеет только OpenRouter; OpenCode Zen/Go показывают его в веб-дашборде.',
|
|
4039
|
+
"cli.usage_no_key": "Для активного провайдера не настроен API-ключ.",
|
|
4040
|
+
"cli.usage_error": "Не удалось получить баланс: {error}",
|
|
4041
|
+
"cli.usage_key_usage": "Расход по ключу: {usage}",
|
|
4042
|
+
"cli.usage_key_limit": "Лимит ключа: {limit} · осталось {remaining}",
|
|
4043
|
+
"cli.usage_balance": "Баланс: {balance}",
|
|
4044
|
+
"cli.usage_account": "Аккаунт: куплено {credits} · израсходовано {used}",
|
|
4045
|
+
"cli.usage_empty": "Провайдер не вернул данных о балансе.",
|
|
4008
4046
|
"repl.ctrl_c_interrupt": `
|
|
4009
4047
|
[Ctrl+C] Остановка агента... (ещё раз — принудительно)`,
|
|
4010
4048
|
"exec.stop_directive": 'STOP. Step {stepId} ("{description}") took {iterations} iterations with no progress. DO NOT continue this step. Immediately call: plan update step={stepId} status=done (if code works despite warnings) OR plan update step={stepId} status=skipped note="reason". Do NOT make any other tool calls before updating the plan.',
|
|
@@ -5742,6 +5780,26 @@ var init_token_counter = __esm(() => {
|
|
|
5742
5780
|
init_dist();
|
|
5743
5781
|
});
|
|
5744
5782
|
|
|
5783
|
+
// src/core/version.ts
|
|
5784
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
|
|
5785
|
+
import { join as join9, dirname as dirname3 } from "path";
|
|
5786
|
+
import { fileURLToPath } from "url";
|
|
5787
|
+
function readMmaVersion() {
|
|
5788
|
+
const here = dirname3(fileURLToPath(import.meta.url));
|
|
5789
|
+
const candidates = [join9(here, "..", "..", "package.json"), join9(here, "..", "package.json")];
|
|
5790
|
+
for (const p of candidates) {
|
|
5791
|
+
if (existsSync9(p)) {
|
|
5792
|
+
try {
|
|
5793
|
+
const raw = JSON.parse(readFileSync5(p, "utf8"));
|
|
5794
|
+
if (raw.version)
|
|
5795
|
+
return raw.version;
|
|
5796
|
+
} catch {}
|
|
5797
|
+
}
|
|
5798
|
+
}
|
|
5799
|
+
return "0.0.0";
|
|
5800
|
+
}
|
|
5801
|
+
var init_version = () => {};
|
|
5802
|
+
|
|
5745
5803
|
// src/modules/security/rate-limiter.ts
|
|
5746
5804
|
class RateLimiter {
|
|
5747
5805
|
config;
|
|
@@ -5873,11 +5931,83 @@ class StreamState {
|
|
|
5873
5931
|
}
|
|
5874
5932
|
}
|
|
5875
5933
|
|
|
5934
|
+
// src/llm/cache-usage.ts
|
|
5935
|
+
function num(value) {
|
|
5936
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
5937
|
+
}
|
|
5938
|
+
function isRecord(value) {
|
|
5939
|
+
return typeof value === "object" && value !== null;
|
|
5940
|
+
}
|
|
5941
|
+
function parseCacheUsage(usage, format, estimatedPromptTokens) {
|
|
5942
|
+
if (!isRecord(usage))
|
|
5943
|
+
return;
|
|
5944
|
+
switch (format) {
|
|
5945
|
+
case "openai": {
|
|
5946
|
+
const details = usage.prompt_tokens_details;
|
|
5947
|
+
if (!isRecord(details))
|
|
5948
|
+
return;
|
|
5949
|
+
const cached = num(details.cached_tokens);
|
|
5950
|
+
if (cached === undefined)
|
|
5951
|
+
return;
|
|
5952
|
+
const prompt = num(usage.prompt_tokens) ?? cached;
|
|
5953
|
+
const write = num(details.cache_write_tokens) ?? 0;
|
|
5954
|
+
return {
|
|
5955
|
+
cachedTokens: cached,
|
|
5956
|
+
cacheWriteTokens: write,
|
|
5957
|
+
uncachedTokens: Math.max(0, prompt - cached),
|
|
5958
|
+
source: "api"
|
|
5959
|
+
};
|
|
5960
|
+
}
|
|
5961
|
+
case "deepseek": {
|
|
5962
|
+
const hit = num(usage.prompt_cache_hit_tokens);
|
|
5963
|
+
const miss = num(usage.prompt_cache_miss_tokens);
|
|
5964
|
+
if (hit === undefined && miss === undefined)
|
|
5965
|
+
return;
|
|
5966
|
+
return {
|
|
5967
|
+
cachedTokens: hit ?? 0,
|
|
5968
|
+
cacheWriteTokens: 0,
|
|
5969
|
+
uncachedTokens: miss ?? 0,
|
|
5970
|
+
source: "api"
|
|
5971
|
+
};
|
|
5972
|
+
}
|
|
5973
|
+
case "anthropic": {
|
|
5974
|
+
const read = num(usage.cache_read_input_tokens);
|
|
5975
|
+
const creation = num(usage.cache_creation_input_tokens);
|
|
5976
|
+
if (read === undefined && creation === undefined)
|
|
5977
|
+
return;
|
|
5978
|
+
return {
|
|
5979
|
+
cachedTokens: read ?? 0,
|
|
5980
|
+
cacheWriteTokens: creation ?? 0,
|
|
5981
|
+
uncachedTokens: num(usage.input_tokens) ?? 0,
|
|
5982
|
+
source: "api"
|
|
5983
|
+
};
|
|
5984
|
+
}
|
|
5985
|
+
case "ollama": {
|
|
5986
|
+
const evaluated = num(usage.prompt_eval_count);
|
|
5987
|
+
if (evaluated === undefined || estimatedPromptTokens === undefined)
|
|
5988
|
+
return;
|
|
5989
|
+
return {
|
|
5990
|
+
cachedTokens: Math.max(0, estimatedPromptTokens - evaluated),
|
|
5991
|
+
cacheWriteTokens: 0,
|
|
5992
|
+
uncachedTokens: evaluated,
|
|
5993
|
+
source: "derived"
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
default:
|
|
5997
|
+
return;
|
|
5998
|
+
}
|
|
5999
|
+
}
|
|
6000
|
+
|
|
5876
6001
|
// src/llm/openai-compat.ts
|
|
5877
6002
|
var exports_openai_compat = {};
|
|
5878
6003
|
__export(exports_openai_compat, {
|
|
5879
6004
|
OpenAICompatProvider: () => OpenAICompatProvider
|
|
5880
6005
|
});
|
|
6006
|
+
function defaultUserAgent() {
|
|
6007
|
+
if (cachedUserAgent === null)
|
|
6008
|
+
cachedUserAgent = `micro-models-agent/${readMmaVersion()}`;
|
|
6009
|
+
return cachedUserAgent;
|
|
6010
|
+
}
|
|
5881
6011
|
function buildRequestBody(opts) {
|
|
5882
6012
|
const body = {
|
|
5883
6013
|
model: opts.model,
|
|
@@ -5886,6 +6016,14 @@ function buildRequestBody(opts) {
|
|
|
5886
6016
|
};
|
|
5887
6017
|
if (opts.maxTokens !== undefined)
|
|
5888
6018
|
body.max_tokens = opts.maxTokens;
|
|
6019
|
+
if (opts.cachePrompt)
|
|
6020
|
+
body.cache_prompt = true;
|
|
6021
|
+
if (opts.promptCacheKey)
|
|
6022
|
+
body.prompt_cache_key = opts.promptCacheKey;
|
|
6023
|
+
if (opts.sessionId)
|
|
6024
|
+
body.session_id = opts.sessionId;
|
|
6025
|
+
if (opts.stream && opts.streamUsage)
|
|
6026
|
+
body.stream_options = { include_usage: true };
|
|
5889
6027
|
const strategy = opts.reasoningStrategy ?? "openai-effort";
|
|
5890
6028
|
const level = opts.reasoningEffort;
|
|
5891
6029
|
if (strategy === "openai-effort" && level && level !== "default") {
|
|
@@ -5917,10 +6055,16 @@ class OpenAICompatProvider {
|
|
|
5917
6055
|
retryConfig;
|
|
5918
6056
|
rateLimiter;
|
|
5919
6057
|
debug;
|
|
6058
|
+
getSessionId;
|
|
6059
|
+
userAgent;
|
|
6060
|
+
cache;
|
|
6061
|
+
cacheReport;
|
|
5920
6062
|
constructor(config) {
|
|
5921
6063
|
this.config = config;
|
|
5922
6064
|
this.model = config.model;
|
|
5923
6065
|
this.contextWindow = config.contextWindow ?? 32768;
|
|
6066
|
+
this.cache = config.cache;
|
|
6067
|
+
this.cacheReport = config.cache?.report ?? "openai";
|
|
5924
6068
|
this.tokenCounter = new TokenCounter;
|
|
5925
6069
|
this.retryConfig = config.retry ?? {
|
|
5926
6070
|
maxRetries: 3,
|
|
@@ -5930,6 +6074,8 @@ class OpenAICompatProvider {
|
|
|
5930
6074
|
noDataTimeoutMs: 180000
|
|
5931
6075
|
};
|
|
5932
6076
|
this.rateLimiter = createRateLimiter(config.rateLimits);
|
|
6077
|
+
this.getSessionId = config.getSessionId;
|
|
6078
|
+
this.userAgent = config.userAgent ?? defaultUserAgent();
|
|
5933
6079
|
this.debug = config.logger ? config.logger.debug.bind(config.logger) : null;
|
|
5934
6080
|
}
|
|
5935
6081
|
async* chat(messages, tools, signal, options) {
|
|
@@ -6021,7 +6167,8 @@ class OpenAICompatProvider {
|
|
|
6021
6167
|
stream: true,
|
|
6022
6168
|
maxTokens,
|
|
6023
6169
|
reasoningEffort: options?.reasoningEffort,
|
|
6024
|
-
reasoningStrategy: options?.reasoningStrategy
|
|
6170
|
+
reasoningStrategy: options?.reasoningStrategy,
|
|
6171
|
+
...this.cacheHints()
|
|
6025
6172
|
});
|
|
6026
6173
|
this.debug?.("LLM stream request", {
|
|
6027
6174
|
baseUrl: this.config.baseUrl,
|
|
@@ -6129,7 +6276,8 @@ class OpenAICompatProvider {
|
|
|
6129
6276
|
st.usage = {
|
|
6130
6277
|
promptTokens: parsed.usage.prompt_tokens ?? 0,
|
|
6131
6278
|
completionTokens: parsed.usage.completion_tokens ?? 0,
|
|
6132
|
-
totalTokens: parsed.usage.total_tokens ?? 0
|
|
6279
|
+
totalTokens: parsed.usage.total_tokens ?? 0,
|
|
6280
|
+
cache: parseCacheUsage(parsed.usage, this.cacheReport)
|
|
6133
6281
|
};
|
|
6134
6282
|
this.debug?.("LLM stream usage", { ...st.usage });
|
|
6135
6283
|
} else if (parsed.error) {
|
|
@@ -6217,13 +6365,27 @@ class OpenAICompatProvider {
|
|
|
6217
6365
|
}
|
|
6218
6366
|
return st.sawDone;
|
|
6219
6367
|
}
|
|
6368
|
+
cacheHints() {
|
|
6369
|
+
const sessionId = this.getSessionId?.();
|
|
6370
|
+
return {
|
|
6371
|
+
cachePrompt: this.cache?.requestCachePrompt === true,
|
|
6372
|
+
promptCacheKey: this.cache?.requestPromptCacheKey ? sessionId : undefined,
|
|
6373
|
+
sessionId: this.cache?.requestSessionId ? sessionId : undefined,
|
|
6374
|
+
streamUsage: this.cache?.requestStreamUsage === true
|
|
6375
|
+
};
|
|
6376
|
+
}
|
|
6220
6377
|
buildRequestSetup(signal) {
|
|
6221
6378
|
const headers = {
|
|
6222
|
-
"Content-Type": "application/json"
|
|
6379
|
+
"Content-Type": "application/json",
|
|
6380
|
+
"User-Agent": this.userAgent
|
|
6223
6381
|
};
|
|
6224
6382
|
if (this.config.apiKey && this.config.apiKey !== "not-needed") {
|
|
6225
6383
|
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
6226
6384
|
}
|
|
6385
|
+
const sessionId = this.getSessionId?.();
|
|
6386
|
+
const sendSessionHeader = this.cache ? this.cache.sessionHeader : true;
|
|
6387
|
+
if (sessionId && sendSessionHeader)
|
|
6388
|
+
headers["x-opencode-session"] = sessionId;
|
|
6227
6389
|
const controller = new AbortController;
|
|
6228
6390
|
let timedOut = false;
|
|
6229
6391
|
const timeoutId = setTimeout(() => {
|
|
@@ -6261,7 +6423,8 @@ class OpenAICompatProvider {
|
|
|
6261
6423
|
stream: false,
|
|
6262
6424
|
maxTokens: options?.maxTokens ?? this.config.maxCompletionTokens ?? 4096,
|
|
6263
6425
|
reasoningEffort: options?.reasoningEffort,
|
|
6264
|
-
reasoningStrategy: options?.reasoningStrategy
|
|
6426
|
+
reasoningStrategy: options?.reasoningStrategy,
|
|
6427
|
+
...this.cacheHints()
|
|
6265
6428
|
});
|
|
6266
6429
|
const { headers, abortSignal, cleanup, isTimeout } = this.buildRequestSetup(signal);
|
|
6267
6430
|
try {
|
|
@@ -6314,7 +6477,8 @@ class OpenAICompatProvider {
|
|
|
6314
6477
|
usage: {
|
|
6315
6478
|
promptTokens: data.usage.prompt_tokens ?? 0,
|
|
6316
6479
|
completionTokens: data.usage.completion_tokens ?? 0,
|
|
6317
|
-
totalTokens: data.usage.total_tokens ?? 0
|
|
6480
|
+
totalTokens: data.usage.total_tokens ?? 0,
|
|
6481
|
+
cache: parseCacheUsage(data.usage, this.cacheReport)
|
|
6318
6482
|
}
|
|
6319
6483
|
});
|
|
6320
6484
|
}
|
|
@@ -6335,7 +6499,8 @@ class OpenAICompatProvider {
|
|
|
6335
6499
|
try {
|
|
6336
6500
|
const url = `${this.config.baseUrl.replace(/\/+$/, "")}/models`;
|
|
6337
6501
|
const headers = {
|
|
6338
|
-
"Content-Type": "application/json"
|
|
6502
|
+
"Content-Type": "application/json",
|
|
6503
|
+
"User-Agent": this.userAgent
|
|
6339
6504
|
};
|
|
6340
6505
|
if (this.config.apiKey && this.config.apiKey !== "not-needed") {
|
|
6341
6506
|
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
@@ -6409,10 +6574,11 @@ class OpenAICompatProvider {
|
|
|
6409
6574
|
});
|
|
6410
6575
|
}
|
|
6411
6576
|
}
|
|
6412
|
-
var REQUEST_TIMEOUT_MS = 120000, MAX_RATE_WAIT_MS = 30000;
|
|
6577
|
+
var REQUEST_TIMEOUT_MS = 120000, MAX_RATE_WAIT_MS = 30000, cachedUserAgent = null;
|
|
6413
6578
|
var init_openai_compat = __esm(() => {
|
|
6414
6579
|
init_token_counter();
|
|
6415
6580
|
init_i18n();
|
|
6581
|
+
init_version();
|
|
6416
6582
|
init_rate_limiter();
|
|
6417
6583
|
init_llm_errors();
|
|
6418
6584
|
});
|
|
@@ -6433,6 +6599,8 @@ function openaiCompat(opts) {
|
|
|
6433
6599
|
retry,
|
|
6434
6600
|
rateLimits,
|
|
6435
6601
|
maxCompletionTokens: opts.maxCompletionTokens,
|
|
6602
|
+
getSessionId: opts.getSessionId,
|
|
6603
|
+
cache: opts.capabilities?.cache,
|
|
6436
6604
|
logger: opts.logger
|
|
6437
6605
|
});
|
|
6438
6606
|
}
|
|
@@ -6450,7 +6618,17 @@ var init_presets = __esm(() => {
|
|
|
6450
6618
|
reasoningStrategy: "prompt-tag",
|
|
6451
6619
|
listModels: true,
|
|
6452
6620
|
requiresKey: false,
|
|
6453
|
-
auth: "bearer"
|
|
6621
|
+
auth: "bearer",
|
|
6622
|
+
cache: {
|
|
6623
|
+
mechanism: "local",
|
|
6624
|
+
report: "openai",
|
|
6625
|
+
sessionHeader: false,
|
|
6626
|
+
requestCachePrompt: false,
|
|
6627
|
+
requestPromptCacheKey: false,
|
|
6628
|
+
requestSessionId: false,
|
|
6629
|
+
requestCacheControl: false,
|
|
6630
|
+
requestStreamUsage: true
|
|
6631
|
+
}
|
|
6454
6632
|
},
|
|
6455
6633
|
create: openaiCompat
|
|
6456
6634
|
};
|
|
@@ -6465,7 +6643,17 @@ var init_presets = __esm(() => {
|
|
|
6465
6643
|
reasoningStrategy: "openai-effort",
|
|
6466
6644
|
listModels: true,
|
|
6467
6645
|
requiresKey: true,
|
|
6468
|
-
auth: "bearer"
|
|
6646
|
+
auth: "bearer",
|
|
6647
|
+
cache: {
|
|
6648
|
+
mechanism: "auto",
|
|
6649
|
+
report: "openai",
|
|
6650
|
+
sessionHeader: false,
|
|
6651
|
+
requestCachePrompt: false,
|
|
6652
|
+
requestPromptCacheKey: false,
|
|
6653
|
+
requestSessionId: true,
|
|
6654
|
+
requestCacheControl: false,
|
|
6655
|
+
requestStreamUsage: true
|
|
6656
|
+
}
|
|
6469
6657
|
},
|
|
6470
6658
|
create: openaiCompat
|
|
6471
6659
|
};
|
|
@@ -6480,7 +6668,17 @@ var init_presets = __esm(() => {
|
|
|
6480
6668
|
reasoningStrategy: "openai-effort",
|
|
6481
6669
|
listModels: true,
|
|
6482
6670
|
requiresKey: true,
|
|
6483
|
-
auth: "bearer"
|
|
6671
|
+
auth: "bearer",
|
|
6672
|
+
cache: {
|
|
6673
|
+
mechanism: "auto",
|
|
6674
|
+
report: "openai",
|
|
6675
|
+
sessionHeader: false,
|
|
6676
|
+
requestCachePrompt: false,
|
|
6677
|
+
requestPromptCacheKey: true,
|
|
6678
|
+
requestSessionId: false,
|
|
6679
|
+
requestCacheControl: false,
|
|
6680
|
+
requestStreamUsage: true
|
|
6681
|
+
}
|
|
6484
6682
|
},
|
|
6485
6683
|
create: openaiCompat
|
|
6486
6684
|
};
|
|
@@ -6495,7 +6693,17 @@ var init_presets = __esm(() => {
|
|
|
6495
6693
|
reasoningStrategy: "none",
|
|
6496
6694
|
listModels: false,
|
|
6497
6695
|
requiresKey: true,
|
|
6498
|
-
auth: "header"
|
|
6696
|
+
auth: "header",
|
|
6697
|
+
cache: {
|
|
6698
|
+
mechanism: "explicit",
|
|
6699
|
+
report: "anthropic",
|
|
6700
|
+
sessionHeader: false,
|
|
6701
|
+
requestCachePrompt: false,
|
|
6702
|
+
requestPromptCacheKey: false,
|
|
6703
|
+
requestSessionId: false,
|
|
6704
|
+
requestCacheControl: true,
|
|
6705
|
+
requestStreamUsage: false
|
|
6706
|
+
}
|
|
6499
6707
|
},
|
|
6500
6708
|
create: openaiCompat
|
|
6501
6709
|
};
|
|
@@ -6510,7 +6718,17 @@ var init_presets = __esm(() => {
|
|
|
6510
6718
|
reasoningStrategy: "openai-effort",
|
|
6511
6719
|
listModels: true,
|
|
6512
6720
|
requiresKey: false,
|
|
6513
|
-
auth: "bearer"
|
|
6721
|
+
auth: "bearer",
|
|
6722
|
+
cache: {
|
|
6723
|
+
mechanism: "auto",
|
|
6724
|
+
report: "openai",
|
|
6725
|
+
sessionHeader: true,
|
|
6726
|
+
requestCachePrompt: false,
|
|
6727
|
+
requestPromptCacheKey: false,
|
|
6728
|
+
requestSessionId: false,
|
|
6729
|
+
requestCacheControl: false,
|
|
6730
|
+
requestStreamUsage: true
|
|
6731
|
+
}
|
|
6514
6732
|
},
|
|
6515
6733
|
create: openaiCompat
|
|
6516
6734
|
};
|
|
@@ -6525,7 +6743,17 @@ var init_presets = __esm(() => {
|
|
|
6525
6743
|
reasoningStrategy: "openai-effort",
|
|
6526
6744
|
listModels: true,
|
|
6527
6745
|
requiresKey: false,
|
|
6528
|
-
auth: "bearer"
|
|
6746
|
+
auth: "bearer",
|
|
6747
|
+
cache: {
|
|
6748
|
+
mechanism: "auto",
|
|
6749
|
+
report: "openai",
|
|
6750
|
+
sessionHeader: true,
|
|
6751
|
+
requestCachePrompt: false,
|
|
6752
|
+
requestPromptCacheKey: false,
|
|
6753
|
+
requestSessionId: false,
|
|
6754
|
+
requestCacheControl: false,
|
|
6755
|
+
requestStreamUsage: true
|
|
6756
|
+
}
|
|
6529
6757
|
},
|
|
6530
6758
|
create: openaiCompat
|
|
6531
6759
|
};
|
|
@@ -6588,6 +6816,25 @@ var init_create = __esm(() => {
|
|
|
6588
6816
|
init_presets();
|
|
6589
6817
|
});
|
|
6590
6818
|
|
|
6819
|
+
// src/modules/providers/cache.ts
|
|
6820
|
+
function resolveCacheCapability(spec, override) {
|
|
6821
|
+
const base = spec?.capabilities.cache ?? NO_CACHE_CAPABILITY;
|
|
6822
|
+
return { ...base, ...override ?? {} };
|
|
6823
|
+
}
|
|
6824
|
+
var NO_CACHE_CAPABILITY;
|
|
6825
|
+
var init_cache = __esm(() => {
|
|
6826
|
+
NO_CACHE_CAPABILITY = {
|
|
6827
|
+
mechanism: "none",
|
|
6828
|
+
report: "none",
|
|
6829
|
+
sessionHeader: false,
|
|
6830
|
+
requestCachePrompt: false,
|
|
6831
|
+
requestPromptCacheKey: false,
|
|
6832
|
+
requestSessionId: false,
|
|
6833
|
+
requestCacheControl: false,
|
|
6834
|
+
requestStreamUsage: false
|
|
6835
|
+
};
|
|
6836
|
+
});
|
|
6837
|
+
|
|
6591
6838
|
// src/modules/providers/manager.ts
|
|
6592
6839
|
class ProviderManager {
|
|
6593
6840
|
entries;
|
|
@@ -6710,17 +6957,26 @@ class ProviderManager {
|
|
|
6710
6957
|
retry: entry.retry ?? this.opts.retry,
|
|
6711
6958
|
rateLimits: entry.rateLimits ?? this.opts.rateLimits,
|
|
6712
6959
|
maxCompletionTokens: entry.maxCompletionTokens,
|
|
6960
|
+
getSessionId: this.opts.getSessionId,
|
|
6961
|
+
capabilities: this.resolveCapabilities(entry),
|
|
6713
6962
|
logger: this.opts.logger
|
|
6714
6963
|
}, this.registry);
|
|
6715
6964
|
this.cache.set(key, provider);
|
|
6716
6965
|
return provider;
|
|
6717
6966
|
}
|
|
6967
|
+
resolveCapabilities(entry) {
|
|
6968
|
+
const spec = this.registry.get(entry.type);
|
|
6969
|
+
if (!spec)
|
|
6970
|
+
return { cache: resolveCacheCapability(undefined, entry.cache) };
|
|
6971
|
+
return { ...spec.capabilities, cache: resolveCacheCapability(spec, entry.cache) };
|
|
6972
|
+
}
|
|
6718
6973
|
resetCache() {
|
|
6719
6974
|
this.cache.clear();
|
|
6720
6975
|
}
|
|
6721
6976
|
}
|
|
6722
6977
|
var init_manager = __esm(() => {
|
|
6723
6978
|
init_create();
|
|
6979
|
+
init_cache();
|
|
6724
6980
|
init_presets();
|
|
6725
6981
|
});
|
|
6726
6982
|
|
|
@@ -6794,11 +7050,12 @@ var init_fallback = __esm(() => {
|
|
|
6794
7050
|
});
|
|
6795
7051
|
|
|
6796
7052
|
// src/modules/providers/factory.ts
|
|
6797
|
-
function buildActiveProvider(config, logger) {
|
|
7053
|
+
function buildActiveProvider(config, logger, opts) {
|
|
6798
7054
|
const manager = new ProviderManager(config.provider, {
|
|
6799
7055
|
contextWindow: config.contextWindow,
|
|
6800
7056
|
retry: config.retry,
|
|
6801
7057
|
rateLimits: config.security?.rateLimits,
|
|
7058
|
+
getSessionId: opts?.getSessionId,
|
|
6802
7059
|
logger
|
|
6803
7060
|
});
|
|
6804
7061
|
manager.setModel(config.model);
|
|
@@ -7142,8 +7399,8 @@ var init_executor = __esm(() => {
|
|
|
7142
7399
|
});
|
|
7143
7400
|
|
|
7144
7401
|
// src/tools/path-utils.ts
|
|
7145
|
-
import { resolve, normalize, dirname as
|
|
7146
|
-
import { existsSync as
|
|
7402
|
+
import { resolve, normalize, dirname as dirname4, basename, sep, relative, isAbsolute } from "path";
|
|
7403
|
+
import { existsSync as existsSync10 } from "fs";
|
|
7147
7404
|
function toForwardSlash(p) {
|
|
7148
7405
|
return p.replace(/\\/g, "/");
|
|
7149
7406
|
}
|
|
@@ -7164,30 +7421,30 @@ function matchesScopeEntry(targetResolved, entryResolved) {
|
|
|
7164
7421
|
function safeResolvePath(baseDir, userPath) {
|
|
7165
7422
|
const asIs = resolve(normalize(userPath));
|
|
7166
7423
|
if (userPath.startsWith("/") || userPath.startsWith("\\")) {
|
|
7167
|
-
if (
|
|
7424
|
+
if (existsSync10(asIs) || existsSync10(dirname4(asIs)))
|
|
7168
7425
|
return asIs;
|
|
7169
7426
|
}
|
|
7170
7427
|
const norm = normalize(userPath);
|
|
7171
7428
|
if (isAbsolute(norm)) {
|
|
7172
|
-
if (
|
|
7429
|
+
if (existsSync10(norm) || existsSync10(dirname4(norm)))
|
|
7173
7430
|
return norm;
|
|
7174
7431
|
const stripped2 = norm.replace(/^[/\\]/, "");
|
|
7175
7432
|
const relativeCandidate = resolve(baseDir, stripped2);
|
|
7176
|
-
if (
|
|
7433
|
+
if (existsSync10(relativeCandidate) || existsSync10(dirname4(relativeCandidate))) {
|
|
7177
7434
|
return relativeCandidate;
|
|
7178
7435
|
}
|
|
7179
7436
|
return norm;
|
|
7180
7437
|
}
|
|
7181
7438
|
const stripped = norm.replace(/^[/\\]/, "");
|
|
7182
7439
|
const resolved = resolve(baseDir, stripped);
|
|
7183
|
-
if (
|
|
7440
|
+
if (existsSync10(resolved) || existsSync10(dirname4(resolved)))
|
|
7184
7441
|
return resolved;
|
|
7185
7442
|
const baseNorm = normalize(baseDir);
|
|
7186
7443
|
let cur = baseNorm;
|
|
7187
|
-
while (cur && cur !==
|
|
7444
|
+
while (cur && cur !== dirname4(cur)) {
|
|
7188
7445
|
const name = basename(cur);
|
|
7189
7446
|
if (!name) {
|
|
7190
|
-
cur =
|
|
7447
|
+
cur = dirname4(cur);
|
|
7191
7448
|
continue;
|
|
7192
7449
|
}
|
|
7193
7450
|
let idx = stripped.toLowerCase().indexOf(name.toLowerCase());
|
|
@@ -7197,17 +7454,17 @@ function safeResolvePath(baseDir, userPath) {
|
|
|
7197
7454
|
if (afterChar && afterChar !== "\\" && afterChar !== "/") {
|
|
7198
7455
|
const fixed = stripped.slice(0, afterIdx) + sep + stripped.slice(afterIdx);
|
|
7199
7456
|
const fixedResolved = resolve(baseDir, normalize(fixed));
|
|
7200
|
-
if (
|
|
7457
|
+
if (existsSync10(fixedResolved) || existsSync10(dirname4(fixedResolved))) {
|
|
7201
7458
|
return fixedResolved;
|
|
7202
7459
|
}
|
|
7203
|
-
const fromParent = resolve(
|
|
7204
|
-
if (
|
|
7460
|
+
const fromParent = resolve(dirname4(cur), normalize(fixed));
|
|
7461
|
+
if (existsSync10(fromParent) || existsSync10(dirname4(fromParent))) {
|
|
7205
7462
|
return fromParent;
|
|
7206
7463
|
}
|
|
7207
7464
|
}
|
|
7208
7465
|
idx = stripped.toLowerCase().indexOf(name.toLowerCase(), idx + 1);
|
|
7209
7466
|
}
|
|
7210
|
-
cur =
|
|
7467
|
+
cur = dirname4(cur);
|
|
7211
7468
|
}
|
|
7212
7469
|
return resolved;
|
|
7213
7470
|
}
|
|
@@ -7424,10 +7681,10 @@ __export(exports_audit_notifier, {
|
|
|
7424
7681
|
DEFAULT_AUDIT_NOTIFIER_CONFIG: () => DEFAULT_AUDIT_NOTIFIER_CONFIG,
|
|
7425
7682
|
AuditNotifier: () => AuditNotifier
|
|
7426
7683
|
});
|
|
7427
|
-
import { writeFileSync as writeFileSync5, appendFileSync as appendFileSync3, existsSync as
|
|
7428
|
-
import { join as
|
|
7684
|
+
import { writeFileSync as writeFileSync5, appendFileSync as appendFileSync3, existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
|
|
7685
|
+
import { join as join10, dirname as dirname5 } from "path";
|
|
7429
7686
|
import { homedir as homedir3 } from "os";
|
|
7430
|
-
import { readFileSync as
|
|
7687
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
7431
7688
|
|
|
7432
7689
|
class AuditNotifier {
|
|
7433
7690
|
config;
|
|
@@ -7452,7 +7709,7 @@ class AuditNotifier {
|
|
|
7452
7709
|
}
|
|
7453
7710
|
ensureLogDirectory() {
|
|
7454
7711
|
if (this.config.filePath) {
|
|
7455
|
-
const dir =
|
|
7712
|
+
const dir = dirname5(this.config.filePath);
|
|
7456
7713
|
mkdirSync6(dir, { recursive: true });
|
|
7457
7714
|
}
|
|
7458
7715
|
}
|
|
@@ -7582,11 +7839,11 @@ class AuditNotifier {
|
|
|
7582
7839
|
}
|
|
7583
7840
|
}
|
|
7584
7841
|
readNotifications(limit = 100) {
|
|
7585
|
-
if (!this.config.filePath || !
|
|
7842
|
+
if (!this.config.filePath || !existsSync11(this.config.filePath)) {
|
|
7586
7843
|
return [];
|
|
7587
7844
|
}
|
|
7588
7845
|
try {
|
|
7589
|
-
const content =
|
|
7846
|
+
const content = readFileSync6(this.config.filePath, "utf8");
|
|
7590
7847
|
const lines = content.split(`
|
|
7591
7848
|
`).filter(Boolean);
|
|
7592
7849
|
return lines.slice(-limit).map((line) => JSON.parse(line));
|
|
@@ -7640,7 +7897,7 @@ var init_audit_notifier = __esm(() => {
|
|
|
7640
7897
|
};
|
|
7641
7898
|
DEFAULT_AUDIT_NOTIFIER_CONFIG = {
|
|
7642
7899
|
enabled: false,
|
|
7643
|
-
filePath:
|
|
7900
|
+
filePath: join10(homedir3(), ".mma", "logs", "audit-notifications.jsonl"),
|
|
7644
7901
|
webhookTimeout: 5000,
|
|
7645
7902
|
minSeverity: "medium",
|
|
7646
7903
|
eventTypes: [
|
|
@@ -7657,26 +7914,26 @@ var init_audit_notifier = __esm(() => {
|
|
|
7657
7914
|
});
|
|
7658
7915
|
|
|
7659
7916
|
// src/modules/security/audit-log.ts
|
|
7660
|
-
import { existsSync as
|
|
7661
|
-
import { resolve as resolve3, join as
|
|
7917
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, appendFileSync as appendFileSync4 } from "fs";
|
|
7918
|
+
import { resolve as resolve3, join as join11 } from "path";
|
|
7662
7919
|
import { homedir as homedir4 } from "os";
|
|
7663
7920
|
function getAuditDir() {
|
|
7664
7921
|
return _sessionAuditDir ?? _globalAuditDir;
|
|
7665
7922
|
}
|
|
7666
7923
|
function setAuditSessionDir(dir) {
|
|
7667
7924
|
_sessionAuditDir = dir;
|
|
7668
|
-
if (!
|
|
7925
|
+
if (!existsSync12(dir)) {
|
|
7669
7926
|
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
7670
7927
|
}
|
|
7671
7928
|
}
|
|
7672
7929
|
function logAudit(entry) {
|
|
7673
7930
|
const dir = getAuditDir();
|
|
7674
|
-
if (!
|
|
7931
|
+
if (!existsSync12(dir)) {
|
|
7675
7932
|
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
7676
7933
|
}
|
|
7677
7934
|
try {
|
|
7678
7935
|
const logEntry = JSON.stringify(entry);
|
|
7679
|
-
appendFileSync4(
|
|
7936
|
+
appendFileSync4(join11(dir, "audit.jsonl"), logEntry + `
|
|
7680
7937
|
`, "utf8");
|
|
7681
7938
|
} catch {}
|
|
7682
7939
|
try {
|
|
@@ -7740,7 +7997,7 @@ var init_audit_log = __esm(() => {
|
|
|
7740
7997
|
});
|
|
7741
7998
|
|
|
7742
7999
|
// src/tools/read-file.ts
|
|
7743
|
-
import { readFileSync as
|
|
8000
|
+
import { readFileSync as readFileSync7, existsSync as existsSync13, statSync as statSync2, openSync, readSync, closeSync } from "fs";
|
|
7744
8001
|
import { extname } from "path";
|
|
7745
8002
|
function readLineSlice(path, offset, limit) {
|
|
7746
8003
|
const fd = openSync(path, "r");
|
|
@@ -7841,7 +8098,7 @@ var init_read_file = __esm(() => {
|
|
|
7841
8098
|
})
|
|
7842
8099
|
};
|
|
7843
8100
|
}
|
|
7844
|
-
if (!
|
|
8101
|
+
if (!existsSync13(resolved)) {
|
|
7845
8102
|
const output = resolved !== path ? t("file.notfound_resolved", {
|
|
7846
8103
|
path,
|
|
7847
8104
|
resolved
|
|
@@ -7858,7 +8115,7 @@ var init_read_file = __esm(() => {
|
|
|
7858
8115
|
total = slice.total;
|
|
7859
8116
|
selected = slice.selected;
|
|
7860
8117
|
} else {
|
|
7861
|
-
const content =
|
|
8118
|
+
const content = readFileSync7(resolved, "utf-8");
|
|
7862
8119
|
lines = content.split(`
|
|
7863
8120
|
`);
|
|
7864
8121
|
total = lines.length;
|
|
@@ -7950,14 +8207,14 @@ __export(exports_session_isolation, {
|
|
|
7950
8207
|
cleanupSessionTempDir: () => cleanupSessionTempDir,
|
|
7951
8208
|
DEFAULT_SESSION_ISOLATION: () => DEFAULT_SESSION_ISOLATION
|
|
7952
8209
|
});
|
|
7953
|
-
import { join as
|
|
8210
|
+
import { join as join12, resolve as resolve5 } from "path";
|
|
7954
8211
|
import { homedir as homedir5 } from "os";
|
|
7955
|
-
import { mkdirSync as mkdirSync8, existsSync as
|
|
8212
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync14 } from "fs";
|
|
7956
8213
|
function createSessionContext(sessionId, projectDir, isolationConfig, securityOverrides) {
|
|
7957
8214
|
const config = { ...DEFAULT_SESSION_ISOLATION, ...isolationConfig };
|
|
7958
|
-
const baseDir = config.baseDir ||
|
|
7959
|
-
const tempDir =
|
|
7960
|
-
if (config.isolateTempFiles && !
|
|
8215
|
+
const baseDir = config.baseDir || join12(homedir5(), ".mma", "sessions", sessionId);
|
|
8216
|
+
const tempDir = join12(baseDir, "temp");
|
|
8217
|
+
if (config.isolateTempFiles && !existsSync14(tempDir)) {
|
|
7961
8218
|
try {
|
|
7962
8219
|
mkdirSync8(tempDir, { recursive: true, mode: 448 });
|
|
7963
8220
|
} catch {}
|
|
@@ -8122,8 +8379,8 @@ function buildDiff(oldLines, newLines) {
|
|
|
8122
8379
|
return result;
|
|
8123
8380
|
}
|
|
8124
8381
|
function formatLine(line, maxNumWidth) {
|
|
8125
|
-
const
|
|
8126
|
-
const numStr =
|
|
8382
|
+
const num2 = line.type === "remove" ? line.oldNum : line.newNum;
|
|
8383
|
+
const numStr = num2 !== null ? String(num2).padStart(maxNumWidth) : " ".repeat(maxNumWidth);
|
|
8127
8384
|
if (line.type === "remove") {
|
|
8128
8385
|
return `${numStr} ${pc2.red("-")} ${line.content}`;
|
|
8129
8386
|
} else if (line.type === "add") {
|
|
@@ -8207,8 +8464,8 @@ var init_diff = __esm(() => {
|
|
|
8207
8464
|
});
|
|
8208
8465
|
|
|
8209
8466
|
// src/tools/syntax-validator.ts
|
|
8210
|
-
import { writeFileSync as writeFileSync6, existsSync as
|
|
8211
|
-
import { extname as extname2, dirname as
|
|
8467
|
+
import { writeFileSync as writeFileSync6, existsSync as existsSync15, unlinkSync as unlinkSync3 } from "fs";
|
|
8468
|
+
import { extname as extname2, dirname as dirname6 } from "path";
|
|
8212
8469
|
import { spawn } from "child_process";
|
|
8213
8470
|
function contentHash(content) {
|
|
8214
8471
|
let h = 5381;
|
|
@@ -8272,7 +8529,7 @@ async function preValidateSyntax(filePath, content, baseDir) {
|
|
|
8272
8529
|
const tmpFile = `${filePath}.tmp${ext}`;
|
|
8273
8530
|
try {
|
|
8274
8531
|
writeFileSync6(tmpFile, content, "utf-8");
|
|
8275
|
-
await runCommand(`bun build --no-bundle --target=bun "${tmpFile}"`,
|
|
8532
|
+
await runCommand(`bun build --no-bundle --target=bun "${tmpFile}"`, dirname6(filePath), 5000);
|
|
8276
8533
|
SYNTAX_CACHE.set(filePath, { hash, error: null });
|
|
8277
8534
|
return { valid: true };
|
|
8278
8535
|
} catch (err) {
|
|
@@ -8284,7 +8541,7 @@ async function preValidateSyntax(filePath, content, baseDir) {
|
|
|
8284
8541
|
return { valid: false, error };
|
|
8285
8542
|
} finally {
|
|
8286
8543
|
try {
|
|
8287
|
-
if (
|
|
8544
|
+
if (existsSync15(tmpFile))
|
|
8288
8545
|
unlinkSync3(tmpFile);
|
|
8289
8546
|
} catch {}
|
|
8290
8547
|
}
|
|
@@ -8298,7 +8555,7 @@ async function preValidateSyntax(filePath, content, baseDir) {
|
|
|
8298
8555
|
const tmpFile = `${filePath}.tmp${ext}`;
|
|
8299
8556
|
try {
|
|
8300
8557
|
writeFileSync6(tmpFile, content, "utf-8");
|
|
8301
|
-
await runCommand(`node --check "${tmpFile}"`,
|
|
8558
|
+
await runCommand(`node --check "${tmpFile}"`, dirname6(filePath), 5000);
|
|
8302
8559
|
SYNTAX_CACHE.set(filePath, { hash, error: null });
|
|
8303
8560
|
return { valid: true };
|
|
8304
8561
|
} catch (err) {
|
|
@@ -8310,7 +8567,7 @@ async function preValidateSyntax(filePath, content, baseDir) {
|
|
|
8310
8567
|
return { valid: false, error };
|
|
8311
8568
|
} finally {
|
|
8312
8569
|
try {
|
|
8313
|
-
if (
|
|
8570
|
+
if (existsSync15(tmpFile))
|
|
8314
8571
|
unlinkSync3(tmpFile);
|
|
8315
8572
|
} catch {}
|
|
8316
8573
|
}
|
|
@@ -8350,8 +8607,8 @@ var init_syntax_validator = __esm(() => {
|
|
|
8350
8607
|
});
|
|
8351
8608
|
|
|
8352
8609
|
// src/tools/write-file.ts
|
|
8353
|
-
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync9, existsSync as
|
|
8354
|
-
import { dirname as
|
|
8610
|
+
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync9, existsSync as existsSync16, readFileSync as readFileSync8 } from "fs";
|
|
8611
|
+
import { dirname as dirname7 } from "path";
|
|
8355
8612
|
var writeFileTool;
|
|
8356
8613
|
var init_write_file = __esm(() => {
|
|
8357
8614
|
init_i18n();
|
|
@@ -8409,8 +8666,8 @@ var init_write_file = __esm(() => {
|
|
|
8409
8666
|
};
|
|
8410
8667
|
}
|
|
8411
8668
|
}
|
|
8412
|
-
const dir =
|
|
8413
|
-
if (!
|
|
8669
|
+
const dir = dirname7(resolved);
|
|
8670
|
+
if (!existsSync16(dir)) {
|
|
8414
8671
|
mkdirSync9(dir, { recursive: true });
|
|
8415
8672
|
}
|
|
8416
8673
|
const validation = await preValidateSyntax(resolved, content, ctx.baseDir);
|
|
@@ -8421,10 +8678,10 @@ var init_write_file = __esm(() => {
|
|
|
8421
8678
|
};
|
|
8422
8679
|
}
|
|
8423
8680
|
const conflicts = detectImportConflicts(content);
|
|
8424
|
-
const fileExists =
|
|
8681
|
+
const fileExists = existsSync16(resolved);
|
|
8425
8682
|
let oldContent = "";
|
|
8426
8683
|
if (fileExists) {
|
|
8427
|
-
oldContent =
|
|
8684
|
+
oldContent = readFileSync8(resolved, "utf-8");
|
|
8428
8685
|
}
|
|
8429
8686
|
writeFileSync7(resolved, content, "utf-8");
|
|
8430
8687
|
const diff = fileExists ? generateDiff(oldContent, content) : generateNewFileDiff(content);
|
|
@@ -8441,7 +8698,7 @@ var init_write_file = __esm(() => {
|
|
|
8441
8698
|
});
|
|
8442
8699
|
|
|
8443
8700
|
// src/tools/edit-file.ts
|
|
8444
|
-
import { readFileSync as
|
|
8701
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
8445
8702
|
var editFileTool;
|
|
8446
8703
|
var init_edit_file = __esm(() => {
|
|
8447
8704
|
init_i18n();
|
|
@@ -8489,7 +8746,7 @@ var init_edit_file = __esm(() => {
|
|
|
8489
8746
|
})
|
|
8490
8747
|
};
|
|
8491
8748
|
}
|
|
8492
|
-
const content =
|
|
8749
|
+
const content = readFileSync9(resolved, "utf-8");
|
|
8493
8750
|
const oldStr = String(args.old);
|
|
8494
8751
|
const newStr = String(args.new);
|
|
8495
8752
|
if (!content.includes(oldStr)) {
|
|
@@ -8697,7 +8954,7 @@ var init_grep_tool = __esm(() => {
|
|
|
8697
8954
|
});
|
|
8698
8955
|
|
|
8699
8956
|
// src/tools/list-dir.ts
|
|
8700
|
-
import { readdirSync as readdirSync5, statSync as statSync3, existsSync as
|
|
8957
|
+
import { readdirSync as readdirSync5, statSync as statSync3, existsSync as existsSync17 } from "fs";
|
|
8701
8958
|
import { resolve as resolve8 } from "path";
|
|
8702
8959
|
var IGNORED_DIRS, listDirTool;
|
|
8703
8960
|
var init_list_dir = __esm(() => {
|
|
@@ -8730,7 +8987,7 @@ var init_list_dir = __esm(() => {
|
|
|
8730
8987
|
})
|
|
8731
8988
|
};
|
|
8732
8989
|
}
|
|
8733
|
-
if (!
|
|
8990
|
+
if (!existsSync17(resolved)) {
|
|
8734
8991
|
return { success: false, output: t("file.dir_notfound", { path }) };
|
|
8735
8992
|
}
|
|
8736
8993
|
const entries = readdirSync5(resolved).filter((e) => !IGNORED_DIRS.has(e));
|
|
@@ -8750,7 +9007,7 @@ var init_list_dir = __esm(() => {
|
|
|
8750
9007
|
});
|
|
8751
9008
|
|
|
8752
9009
|
// src/tools/create-dir.ts
|
|
8753
|
-
import { mkdirSync as mkdirSync10, existsSync as
|
|
9010
|
+
import { mkdirSync as mkdirSync10, existsSync as existsSync18 } from "fs";
|
|
8754
9011
|
var createDirTool;
|
|
8755
9012
|
var init_create_dir = __esm(() => {
|
|
8756
9013
|
init_i18n();
|
|
@@ -8793,7 +9050,7 @@ var init_create_dir = __esm(() => {
|
|
|
8793
9050
|
})
|
|
8794
9051
|
};
|
|
8795
9052
|
}
|
|
8796
|
-
if (!
|
|
9053
|
+
if (!existsSync18(resolved)) {
|
|
8797
9054
|
mkdirSync10(resolved, { recursive: true });
|
|
8798
9055
|
}
|
|
8799
9056
|
ctx.fileOperationsCount = currentCount + 1;
|
|
@@ -8804,7 +9061,7 @@ var init_create_dir = __esm(() => {
|
|
|
8804
9061
|
});
|
|
8805
9062
|
|
|
8806
9063
|
// src/tools/delete-file.ts
|
|
8807
|
-
import { unlinkSync as unlinkSync4, existsSync as
|
|
9064
|
+
import { unlinkSync as unlinkSync4, existsSync as existsSync19, statSync as statSync4, readFileSync as readFileSync10 } from "fs";
|
|
8808
9065
|
var deleteFileTool;
|
|
8809
9066
|
var init_delete_file = __esm(() => {
|
|
8810
9067
|
init_i18n();
|
|
@@ -8848,13 +9105,13 @@ var init_delete_file = __esm(() => {
|
|
|
8848
9105
|
})
|
|
8849
9106
|
};
|
|
8850
9107
|
}
|
|
8851
|
-
if (!
|
|
9108
|
+
if (!existsSync19(resolved)) {
|
|
8852
9109
|
return { success: false, output: t("file.notfound", { path }) };
|
|
8853
9110
|
}
|
|
8854
9111
|
if (statSync4(resolved).isDirectory()) {
|
|
8855
9112
|
return { success: false, output: t("file.is_directory", { path }) };
|
|
8856
9113
|
}
|
|
8857
|
-
const content =
|
|
9114
|
+
const content = readFileSync10(resolved, "utf-8");
|
|
8858
9115
|
unlinkSync4(resolved);
|
|
8859
9116
|
const diff = generateDeleteDiff(content);
|
|
8860
9117
|
ctx.fileOperationsCount = currentCount + 1;
|
|
@@ -8865,8 +9122,8 @@ var init_delete_file = __esm(() => {
|
|
|
8865
9122
|
});
|
|
8866
9123
|
|
|
8867
9124
|
// src/tools/move-file.ts
|
|
8868
|
-
import { renameSync as renameSync2, existsSync as
|
|
8869
|
-
import { resolve as resolve9, normalize as normalize3, dirname as
|
|
9125
|
+
import { renameSync as renameSync2, existsSync as existsSync20, mkdirSync as mkdirSync11 } from "fs";
|
|
9126
|
+
import { resolve as resolve9, normalize as normalize3, dirname as dirname8 } from "path";
|
|
8870
9127
|
var moveFileTool;
|
|
8871
9128
|
var init_move_file = __esm(() => {
|
|
8872
9129
|
init_i18n();
|
|
@@ -8924,14 +9181,14 @@ var init_move_file = __esm(() => {
|
|
|
8924
9181
|
})
|
|
8925
9182
|
};
|
|
8926
9183
|
}
|
|
8927
|
-
if (!
|
|
9184
|
+
if (!existsSync20(fromResolved)) {
|
|
8928
9185
|
return {
|
|
8929
9186
|
success: false,
|
|
8930
9187
|
output: t("file.not_found_short", { path: fromPath })
|
|
8931
9188
|
};
|
|
8932
9189
|
}
|
|
8933
|
-
const toDir =
|
|
8934
|
-
if (!
|
|
9190
|
+
const toDir = dirname8(toResolved);
|
|
9191
|
+
if (!existsSync20(toDir)) {
|
|
8935
9192
|
mkdirSync11(toDir, { recursive: true });
|
|
8936
9193
|
}
|
|
8937
9194
|
renameSync2(fromResolved, toResolved);
|
|
@@ -8948,7 +9205,7 @@ var init_move_file = __esm(() => {
|
|
|
8948
9205
|
});
|
|
8949
9206
|
|
|
8950
9207
|
// src/tools/file-info.ts
|
|
8951
|
-
import { statSync as statSync5, existsSync as
|
|
9208
|
+
import { statSync as statSync5, existsSync as existsSync21 } from "fs";
|
|
8952
9209
|
var fileInfoTool;
|
|
8953
9210
|
var init_file_info = __esm(() => {
|
|
8954
9211
|
init_i18n();
|
|
@@ -8979,7 +9236,7 @@ var init_file_info = __esm(() => {
|
|
|
8979
9236
|
})
|
|
8980
9237
|
};
|
|
8981
9238
|
}
|
|
8982
|
-
if (!
|
|
9239
|
+
if (!existsSync21(resolved)) {
|
|
8983
9240
|
return { success: false, output: t("file.not_found_short", { path }) };
|
|
8984
9241
|
}
|
|
8985
9242
|
const stat = statSync5(resolved);
|
|
@@ -10079,8 +10336,8 @@ var init_prompt_builder = __esm(() => {
|
|
|
10079
10336
|
});
|
|
10080
10337
|
|
|
10081
10338
|
// src/core/session-logger.ts
|
|
10082
|
-
import { join as
|
|
10083
|
-
import { readFileSync as
|
|
10339
|
+
import { join as join13 } from "path";
|
|
10340
|
+
import { readFileSync as readFileSync11, existsSync as existsSync22 } from "fs";
|
|
10084
10341
|
|
|
10085
10342
|
class SessionLogger {
|
|
10086
10343
|
session;
|
|
@@ -10258,7 +10515,12 @@ class SessionLogger {
|
|
|
10258
10515
|
completionTokens: usage.completionTokens,
|
|
10259
10516
|
totalTokens: usage.totalTokens,
|
|
10260
10517
|
source: usage.source,
|
|
10261
|
-
durationMs: usage.durationMs
|
|
10518
|
+
durationMs: usage.durationMs,
|
|
10519
|
+
cacheStable: usage.prefix ? Number(usage.prefix.stableRatio.toFixed(4)) : undefined,
|
|
10520
|
+
cacheCause: usage.prefix?.cause,
|
|
10521
|
+
cachedTokens: usage.cache?.cachedTokens,
|
|
10522
|
+
cacheWriteTokens: usage.cache?.cacheWriteTokens,
|
|
10523
|
+
cacheSource: usage.cache?.source
|
|
10262
10524
|
});
|
|
10263
10525
|
}
|
|
10264
10526
|
logError(message) {
|
|
@@ -10288,10 +10550,10 @@ class SessionLogger {
|
|
|
10288
10550
|
logSessionStart(data) {
|
|
10289
10551
|
const meta = this.session?.getActiveMeta();
|
|
10290
10552
|
if (meta) {
|
|
10291
|
-
const logPath =
|
|
10553
|
+
const logPath = join13(this.session.getSessionDirectory(meta.id), "session.jsonl");
|
|
10292
10554
|
try {
|
|
10293
|
-
if (
|
|
10294
|
-
const content =
|
|
10555
|
+
if (existsSync22(logPath)) {
|
|
10556
|
+
const content = readFileSync11(logPath, "utf-8");
|
|
10295
10557
|
if (content.includes('"type":"session_start"'))
|
|
10296
10558
|
return;
|
|
10297
10559
|
}
|
|
@@ -10908,52 +11170,52 @@ ${output}
|
|
|
10908
11170
|
}
|
|
10909
11171
|
function parseNumber() {
|
|
10910
11172
|
const start = i;
|
|
10911
|
-
let
|
|
11173
|
+
let num2 = "";
|
|
10912
11174
|
let invalid = false;
|
|
10913
11175
|
if (text[i] === "-") {
|
|
10914
|
-
|
|
11176
|
+
num2 += text[i];
|
|
10915
11177
|
i++;
|
|
10916
11178
|
if (!isDigit(text[i]) && atEndOfNumber()) {
|
|
10917
|
-
|
|
11179
|
+
num2 += "0";
|
|
10918
11180
|
}
|
|
10919
11181
|
}
|
|
10920
11182
|
if (text[i] === "0" && isDigit(text[i + 1])) {
|
|
10921
11183
|
invalid = true;
|
|
10922
11184
|
}
|
|
10923
11185
|
while (isDigit(text[i])) {
|
|
10924
|
-
|
|
11186
|
+
num2 += text[i];
|
|
10925
11187
|
i++;
|
|
10926
11188
|
}
|
|
10927
11189
|
if (text[i] === ".") {
|
|
10928
|
-
if (
|
|
10929
|
-
|
|
11190
|
+
if (num2 === "" || num2 === "-") {
|
|
11191
|
+
num2 += "0";
|
|
10930
11192
|
}
|
|
10931
|
-
|
|
11193
|
+
num2 += text[i];
|
|
10932
11194
|
i++;
|
|
10933
11195
|
if (!isDigit(text[i])) {
|
|
10934
|
-
|
|
11196
|
+
num2 += "0";
|
|
10935
11197
|
}
|
|
10936
11198
|
while (isDigit(text[i])) {
|
|
10937
|
-
|
|
11199
|
+
num2 += text[i];
|
|
10938
11200
|
i++;
|
|
10939
11201
|
}
|
|
10940
11202
|
}
|
|
10941
11203
|
if (i > start) {
|
|
10942
11204
|
if (text[i] === "e" || text[i] === "E") {
|
|
10943
|
-
if (
|
|
11205
|
+
if (num2 === "-") {
|
|
10944
11206
|
invalid = true;
|
|
10945
11207
|
}
|
|
10946
|
-
|
|
11208
|
+
num2 += text[i];
|
|
10947
11209
|
i++;
|
|
10948
11210
|
if (text[i] === "-" || text[i] === "+") {
|
|
10949
|
-
|
|
11211
|
+
num2 += text[i];
|
|
10950
11212
|
i++;
|
|
10951
11213
|
}
|
|
10952
11214
|
if (!isDigit(text[i])) {
|
|
10953
|
-
|
|
11215
|
+
num2 += "0";
|
|
10954
11216
|
}
|
|
10955
11217
|
while (isDigit(text[i])) {
|
|
10956
|
-
|
|
11218
|
+
num2 += text[i];
|
|
10957
11219
|
i++;
|
|
10958
11220
|
}
|
|
10959
11221
|
}
|
|
@@ -10961,7 +11223,7 @@ ${output}
|
|
|
10961
11223
|
i = start;
|
|
10962
11224
|
return false;
|
|
10963
11225
|
}
|
|
10964
|
-
output += invalid ? `"${text.substring(start, i)}"` :
|
|
11226
|
+
output += invalid ? `"${text.substring(start, i)}"` : num2;
|
|
10965
11227
|
return true;
|
|
10966
11228
|
}
|
|
10967
11229
|
return false;
|
|
@@ -11162,8 +11424,10 @@ ${PLAN_SYSTEM_PROMPT_RULES}`;
|
|
|
11162
11424
|
class OrchestratorClient {
|
|
11163
11425
|
config;
|
|
11164
11426
|
provider = null;
|
|
11165
|
-
|
|
11427
|
+
getSessionId;
|
|
11428
|
+
constructor(config, defaultProvider, opts) {
|
|
11166
11429
|
this.config = config;
|
|
11430
|
+
this.getSessionId = opts?.getSessionId;
|
|
11167
11431
|
if (!config.model)
|
|
11168
11432
|
return;
|
|
11169
11433
|
if (config.provider) {
|
|
@@ -11183,6 +11447,7 @@ class OrchestratorClient {
|
|
|
11183
11447
|
contextWindow: config.contextWindow ?? DEFAULT_ORCH_CONTEXT_WINDOW,
|
|
11184
11448
|
retry: config.retry,
|
|
11185
11449
|
rateLimits: config.rateLimits,
|
|
11450
|
+
getSessionId: this.getSessionId,
|
|
11186
11451
|
logger: config.logger
|
|
11187
11452
|
});
|
|
11188
11453
|
manager.setModel(config.model);
|
|
@@ -12208,7 +12473,7 @@ var init_stuck_detector = __esm(() => {
|
|
|
12208
12473
|
});
|
|
12209
12474
|
|
|
12210
12475
|
// src/modules/artifacts/store.ts
|
|
12211
|
-
import { existsSync as
|
|
12476
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
12212
12477
|
import { resolve as resolve10, relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
|
|
12213
12478
|
|
|
12214
12479
|
class ArtifactStore {
|
|
@@ -12246,9 +12511,9 @@ class ArtifactStore {
|
|
|
12246
12511
|
const abs = resolve10(this.root, path);
|
|
12247
12512
|
if (!ArtifactStore.isInside(this.root, abs))
|
|
12248
12513
|
return null;
|
|
12249
|
-
if (!
|
|
12514
|
+
if (!existsSync23(abs))
|
|
12250
12515
|
return null;
|
|
12251
|
-
return
|
|
12516
|
+
return readFileSync12(abs, "utf8");
|
|
12252
12517
|
}
|
|
12253
12518
|
summary(content, maxChars) {
|
|
12254
12519
|
if (content.length <= maxChars)
|
|
@@ -12748,23 +13013,41 @@ var init_moe_executor = __esm(() => {
|
|
|
12748
13013
|
});
|
|
12749
13014
|
|
|
12750
13015
|
// src/modules/lsp/project-root.ts
|
|
12751
|
-
import { existsSync as
|
|
12752
|
-
import { dirname as
|
|
13016
|
+
import { existsSync as existsSync24 } from "fs";
|
|
13017
|
+
import { dirname as dirname9, join as join14, relative as relative3, isAbsolute as isAbsolute3 } from "path";
|
|
13018
|
+
import { platform as platform4 } from "os";
|
|
13019
|
+
function resolveTscCommand(startDir, maxLevels = 8) {
|
|
13020
|
+
const runtime = process.execPath;
|
|
13021
|
+
let dir = startDir;
|
|
13022
|
+
for (let i = 0;i < maxLevels; i++) {
|
|
13023
|
+
const js = join14(dir, "node_modules", "typescript", "bin", "tsc");
|
|
13024
|
+
if (existsSync24(js))
|
|
13025
|
+
return `"${runtime}" "${js}"`;
|
|
13026
|
+
const stub = join14(dir, "node_modules", ".bin", platform4() === "win32" ? "tsc.cmd" : "tsc");
|
|
13027
|
+
if (existsSync24(stub))
|
|
13028
|
+
return `"${stub}"`;
|
|
13029
|
+
const parent = dirname9(dir);
|
|
13030
|
+
if (parent === dir)
|
|
13031
|
+
break;
|
|
13032
|
+
dir = parent;
|
|
13033
|
+
}
|
|
13034
|
+
return null;
|
|
13035
|
+
}
|
|
12753
13036
|
function findProjectRoot(filePath, baseDir, markers) {
|
|
12754
13037
|
if (!markers || markers.length === 0)
|
|
12755
13038
|
return baseDir;
|
|
12756
|
-
let dir =
|
|
13039
|
+
let dir = dirname9(filePath);
|
|
12757
13040
|
const root = baseDir.replace(/[\\/]+$/, "");
|
|
12758
13041
|
const rel = relative3(root, dir);
|
|
12759
13042
|
if (rel && rel.startsWith("..") || isAbsolute3(rel))
|
|
12760
13043
|
dir = root;
|
|
12761
13044
|
while (true) {
|
|
12762
|
-
if (markers.some((m) =>
|
|
13045
|
+
if (markers.some((m) => existsSync24(join14(dir, m)))) {
|
|
12763
13046
|
return dir;
|
|
12764
13047
|
}
|
|
12765
13048
|
if (dir === root)
|
|
12766
13049
|
return dir;
|
|
12767
|
-
const parent =
|
|
13050
|
+
const parent = dirname9(dir);
|
|
12768
13051
|
if (parent === dir)
|
|
12769
13052
|
return root;
|
|
12770
13053
|
dir = parent;
|
|
@@ -12982,13 +13265,13 @@ var init_js_identifiers = __esm(() => {
|
|
|
12982
13265
|
});
|
|
12983
13266
|
|
|
12984
13267
|
// src/modules/execution/audit-runners.ts
|
|
12985
|
-
import { existsSync as
|
|
12986
|
-
import { dirname as
|
|
13268
|
+
import { existsSync as existsSync25, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
|
|
13269
|
+
import { dirname as dirname10, join as join15, resolve as resolve11 } from "path";
|
|
12987
13270
|
function resolveTestCommand(dir) {
|
|
12988
|
-
const pkgPath =
|
|
12989
|
-
if (
|
|
13271
|
+
const pkgPath = join15(dir, "package.json");
|
|
13272
|
+
if (existsSync25(pkgPath)) {
|
|
12990
13273
|
try {
|
|
12991
|
-
const pkg = JSON.parse(
|
|
13274
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
12992
13275
|
const script = pkg?.scripts?.test;
|
|
12993
13276
|
if (typeof script === "string" && script.trim())
|
|
12994
13277
|
return script.trim();
|
|
@@ -13004,7 +13287,7 @@ function resolveTestCommand(dir) {
|
|
|
13004
13287
|
"jest.config.cjs",
|
|
13005
13288
|
"bunfig.toml"
|
|
13006
13289
|
]) {
|
|
13007
|
-
if (
|
|
13290
|
+
if (existsSync25(join15(dir, f))) {
|
|
13008
13291
|
if (f.startsWith("vitest"))
|
|
13009
13292
|
return "bunx vitest run";
|
|
13010
13293
|
if (f.startsWith("jest"))
|
|
@@ -13013,12 +13296,12 @@ function resolveTestCommand(dir) {
|
|
|
13013
13296
|
return "bun test";
|
|
13014
13297
|
}
|
|
13015
13298
|
}
|
|
13016
|
-
if (
|
|
13299
|
+
if (existsSync25(join15(dir, "pyproject.toml")) || existsSync25(join15(dir, "pytest.ini")) || existsSync25(join15(dir, "conftest.py"))) {
|
|
13017
13300
|
return "python -m pytest -q";
|
|
13018
13301
|
}
|
|
13019
|
-
if (
|
|
13302
|
+
if (existsSync25(join15(dir, "go.mod")))
|
|
13020
13303
|
return "go test ./...";
|
|
13021
|
-
if (
|
|
13304
|
+
if (existsSync25(join15(dir, "Cargo.toml")))
|
|
13022
13305
|
return "cargo test";
|
|
13023
13306
|
return "bun test";
|
|
13024
13307
|
}
|
|
@@ -13032,7 +13315,7 @@ function findTestFile(dir, depth = 0) {
|
|
|
13032
13315
|
return null;
|
|
13033
13316
|
}
|
|
13034
13317
|
for (const e of entries) {
|
|
13035
|
-
const full =
|
|
13318
|
+
const full = join15(dir, e.name);
|
|
13036
13319
|
if (e.isDirectory()) {
|
|
13037
13320
|
if (SKIP_DIRS.has(e.name))
|
|
13038
13321
|
continue;
|
|
@@ -13108,12 +13391,12 @@ function findTypecheckRoot(baseDir, existingFiles = []) {
|
|
|
13108
13391
|
for (const start of candidates) {
|
|
13109
13392
|
let dir = resolve11(start);
|
|
13110
13393
|
for (let depth = 0;depth <= 10; depth++) {
|
|
13111
|
-
if (
|
|
13394
|
+
if (existsSync25(join15(dir, "tsconfig.json"))) {
|
|
13112
13395
|
if (!best || depth < best.depth)
|
|
13113
13396
|
best = { depth, root: dir };
|
|
13114
13397
|
break;
|
|
13115
13398
|
}
|
|
13116
|
-
const parent =
|
|
13399
|
+
const parent = dirname10(dir);
|
|
13117
13400
|
if (parent === dir)
|
|
13118
13401
|
break;
|
|
13119
13402
|
dir = parent;
|
|
@@ -13122,7 +13405,10 @@ function findTypecheckRoot(baseDir, existingFiles = []) {
|
|
|
13122
13405
|
return best?.root ?? null;
|
|
13123
13406
|
}
|
|
13124
13407
|
async function runTypecheck(baseDir) {
|
|
13125
|
-
const
|
|
13408
|
+
const tsc = resolveTscCommand(baseDir);
|
|
13409
|
+
if (!tsc)
|
|
13410
|
+
return null;
|
|
13411
|
+
const entry = processRegistry.start(`${tsc} --noEmit --skipLibCheck`, baseDir);
|
|
13126
13412
|
const exited = await processRegistry.waitForExit(entry.id, 90000);
|
|
13127
13413
|
const output = entry.log.join(`
|
|
13128
13414
|
`);
|
|
@@ -13135,6 +13421,7 @@ var SKIP_DIRS, TEST_EXT_RE, PY_TEST_RE, TEST_STEP_RE;
|
|
|
13135
13421
|
var init_audit_runners = __esm(() => {
|
|
13136
13422
|
init_bash();
|
|
13137
13423
|
init_processes();
|
|
13424
|
+
init_project_root();
|
|
13138
13425
|
SKIP_DIRS = new Set([
|
|
13139
13426
|
"node_modules",
|
|
13140
13427
|
".git",
|
|
@@ -13152,11 +13439,11 @@ var init_audit_runners = __esm(() => {
|
|
|
13152
13439
|
});
|
|
13153
13440
|
|
|
13154
13441
|
// src/modules/execution/auditor.ts
|
|
13155
|
-
import { existsSync as
|
|
13156
|
-
import { resolve as resolve12, join as
|
|
13442
|
+
import { existsSync as existsSync26, readdirSync as readdirSync7 } from "fs";
|
|
13443
|
+
import { resolve as resolve12, join as join16, basename as basename2 } from "path";
|
|
13157
13444
|
function findExistingFile(baseDir, filePath) {
|
|
13158
13445
|
const direct = resolve12(baseDir, filePath);
|
|
13159
|
-
if (
|
|
13446
|
+
if (existsSync26(direct))
|
|
13160
13447
|
return direct;
|
|
13161
13448
|
const name = basename2(filePath).toLowerCase();
|
|
13162
13449
|
const suffix = toForwardSlash(filePath).toLowerCase();
|
|
@@ -13173,7 +13460,7 @@ function findExistingFile(baseDir, filePath) {
|
|
|
13173
13460
|
for (const e of entries) {
|
|
13174
13461
|
if (found)
|
|
13175
13462
|
return;
|
|
13176
|
-
const full =
|
|
13463
|
+
const full = join16(dir, e.name);
|
|
13177
13464
|
if (e.isDirectory()) {
|
|
13178
13465
|
if (SKIP_DIRS.has(e.name))
|
|
13179
13466
|
continue;
|
|
@@ -13312,8 +13599,8 @@ var init_auditor = __esm(() => {
|
|
|
13312
13599
|
});
|
|
13313
13600
|
|
|
13314
13601
|
// src/modules/execution/verifier.ts
|
|
13315
|
-
import { existsSync as
|
|
13316
|
-
import { resolve as resolve13, extname as extname3, join as
|
|
13602
|
+
import { existsSync as existsSync27, readFileSync as readFileSync14 } from "fs";
|
|
13603
|
+
import { resolve as resolve13, extname as extname3, dirname as dirname11, join as join17 } from "path";
|
|
13317
13604
|
import { spawn as spawn4 } from "child_process";
|
|
13318
13605
|
|
|
13319
13606
|
class StepVerifier {
|
|
@@ -13323,7 +13610,7 @@ class StepVerifier {
|
|
|
13323
13610
|
}
|
|
13324
13611
|
async checkFileExists(path) {
|
|
13325
13612
|
const resolved = resolve13(this.baseDir, path);
|
|
13326
|
-
const exists =
|
|
13613
|
+
const exists = existsSync27(resolved);
|
|
13327
13614
|
return {
|
|
13328
13615
|
passed: exists,
|
|
13329
13616
|
message: exists ? t("verify.file_exists", { path }) : t("verify.file_not_found", { path })
|
|
@@ -13342,11 +13629,14 @@ class StepVerifier {
|
|
|
13342
13629
|
}
|
|
13343
13630
|
async runTypeCheck() {
|
|
13344
13631
|
const tsconfigPath = resolve13(this.baseDir, "tsconfig.json");
|
|
13345
|
-
if (!
|
|
13632
|
+
if (!existsSync27(tsconfigPath)) {
|
|
13346
13633
|
return { passed: true, message: "No tsconfig.json found — skipping type check" };
|
|
13347
13634
|
}
|
|
13635
|
+
const tsc = resolveTscCommand(this.baseDir);
|
|
13636
|
+
if (!tsc)
|
|
13637
|
+
return { passed: true, message: "tsc not installed — skipping type check" };
|
|
13348
13638
|
try {
|
|
13349
|
-
await this.runAsync(
|
|
13639
|
+
await this.runAsync(`${tsc} --noEmit`, this.baseDir, 60000);
|
|
13350
13640
|
return { passed: true, message: "TypeScript type check passed" };
|
|
13351
13641
|
} catch (e) {
|
|
13352
13642
|
const stderr = e.stderr?.toString() || e.stdout?.toString() || e.message;
|
|
@@ -13355,12 +13645,15 @@ class StepVerifier {
|
|
|
13355
13645
|
}
|
|
13356
13646
|
async runTypeCheckForFile(filePath) {
|
|
13357
13647
|
const projectRoot = findProjectRoot(filePath, this.baseDir, ["tsconfig.json", "package.json"]);
|
|
13358
|
-
const tsconfigPath =
|
|
13359
|
-
if (!
|
|
13648
|
+
const tsconfigPath = join17(projectRoot, "tsconfig.json");
|
|
13649
|
+
if (!existsSync27(tsconfigPath)) {
|
|
13360
13650
|
return { passed: true, message: "No tsconfig.json found — skipping type check" };
|
|
13361
13651
|
}
|
|
13652
|
+
const tsc = resolveTscCommand(projectRoot);
|
|
13653
|
+
if (!tsc)
|
|
13654
|
+
return { passed: true, message: "tsc not installed — skipping type check" };
|
|
13362
13655
|
try {
|
|
13363
|
-
await this.runAsync(
|
|
13656
|
+
await this.runAsync(`${tsc} --noEmit --skipLibCheck`, projectRoot, 60000);
|
|
13364
13657
|
return { passed: true, message: "TypeScript type check passed" };
|
|
13365
13658
|
} catch (e) {
|
|
13366
13659
|
const stderr = e.stderr?.toString() || e.stdout?.toString() || e.message;
|
|
@@ -13369,7 +13662,7 @@ class StepVerifier {
|
|
|
13369
13662
|
}
|
|
13370
13663
|
async runTests() {
|
|
13371
13664
|
const pkgPath = resolve13(this.baseDir, "package.json");
|
|
13372
|
-
if (!
|
|
13665
|
+
if (!existsSync27(pkgPath)) {
|
|
13373
13666
|
return { passed: true, message: "No package.json found — skipping tests" };
|
|
13374
13667
|
}
|
|
13375
13668
|
try {
|
|
@@ -13411,13 +13704,13 @@ class StepVerifier {
|
|
|
13411
13704
|
const path = rest.slice(0, colon);
|
|
13412
13705
|
const needle = rest.slice(colon + 1);
|
|
13413
13706
|
const resolved = resolve13(this.baseDir, path);
|
|
13414
|
-
if (!
|
|
13707
|
+
if (!existsSync27(resolved)) {
|
|
13415
13708
|
const item = { passed: false, message: t("verify.file_not_found", { path }) };
|
|
13416
13709
|
details.push(item);
|
|
13417
13710
|
errors.push(`[${subtask.id}] ${item.message}`);
|
|
13418
13711
|
continue;
|
|
13419
13712
|
}
|
|
13420
|
-
const content =
|
|
13713
|
+
const content = readFileSync14(resolved, "utf-8");
|
|
13421
13714
|
const passed = content.includes(needle);
|
|
13422
13715
|
details.push({ passed, message: `substring "${needle}" in ${path}: ${passed}` });
|
|
13423
13716
|
if (!passed)
|
|
@@ -13513,8 +13806,11 @@ class StepVerifier {
|
|
|
13513
13806
|
async validateSyntax(filePath) {
|
|
13514
13807
|
const ext = extname3(filePath);
|
|
13515
13808
|
if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
|
|
13809
|
+
const tsc = resolveTscCommand(dirname11(filePath));
|
|
13810
|
+
if (!tsc)
|
|
13811
|
+
return true;
|
|
13516
13812
|
try {
|
|
13517
|
-
await this.runAsync(
|
|
13813
|
+
await this.runAsync(`${tsc} --noEmit --skipLibCheck "${filePath}"`, this.baseDir, 20000);
|
|
13518
13814
|
return true;
|
|
13519
13815
|
} catch (err) {
|
|
13520
13816
|
if (err.status === 127 || err.message.includes("not found") || err.message.includes("ENOENT")) {
|
|
@@ -13603,7 +13899,7 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
13603
13899
|
rateLimits: config.security?.rateLimits,
|
|
13604
13900
|
logger,
|
|
13605
13901
|
experts: config.experts
|
|
13606
|
-
}, llmProvider);
|
|
13902
|
+
}, llmProvider, { getSessionId: () => sessionId });
|
|
13607
13903
|
}
|
|
13608
13904
|
if (!orchestrator.isEnabled()) {
|
|
13609
13905
|
logger.warn("MoE enabled but no orchestrator model configured — falling back to single-agent. Set orchestrator.model to activate MoE.");
|
|
@@ -13844,11 +14140,18 @@ function resolvePrice(model, config) {
|
|
|
13844
14140
|
return direct;
|
|
13845
14141
|
return ZEN_PRICES[bare];
|
|
13846
14142
|
}
|
|
13847
|
-
function
|
|
14143
|
+
function calculateCostDetailed(model, promptTokens, completionTokens, config, cache) {
|
|
13848
14144
|
const price = resolvePrice(model, config);
|
|
13849
14145
|
if (!price)
|
|
13850
14146
|
return;
|
|
13851
|
-
|
|
14147
|
+
const cached = Math.max(0, cache?.cachedTokens ?? 0);
|
|
14148
|
+
const write = Math.max(0, cache?.cacheWriteTokens ?? 0);
|
|
14149
|
+
const uncached = Math.max(0, promptTokens - cached);
|
|
14150
|
+
const cachedRate = price.cachedInput ?? price.input;
|
|
14151
|
+
const writeRate = price.cacheWrite ?? 0;
|
|
14152
|
+
const cost = uncached / 1e6 * price.input + cached / 1e6 * cachedRate + write / 1e6 * writeRate + completionTokens / 1e6 * price.output;
|
|
14153
|
+
const saved = cached / 1e6 * (price.input - cachedRate);
|
|
14154
|
+
return { cost, saved };
|
|
13852
14155
|
}
|
|
13853
14156
|
function formatCost(cost) {
|
|
13854
14157
|
if (cost === 0)
|
|
@@ -13868,12 +14171,12 @@ var init_prices = __esm(() => {
|
|
|
13868
14171
|
"nemotron-3-ultra-free": { input: 0, output: 0 },
|
|
13869
14172
|
"nemotron-3.5-lightning-free": { input: 0, output: 0 },
|
|
13870
14173
|
"muse-spark-1.2-contributor-free": { input: 0, output: 0 },
|
|
13871
|
-
"minimax-m3": { input: 0.3, output: 1.2 },
|
|
13872
|
-
"minimax-m2.7": { input: 0.3, output: 1.2 },
|
|
13873
|
-
"minimax-m2.5": { input: 0.3, output: 1.2 },
|
|
13874
|
-
"glm-5.2": { input: 1.4, output: 4.4 },
|
|
13875
|
-
"glm-5.1": { input: 1.4, output: 4.4 },
|
|
13876
|
-
"glm-5": { input: 1, output: 3.2 },
|
|
14174
|
+
"minimax-m3": { input: 0.3, output: 1.2, cachedInput: 0.06 },
|
|
14175
|
+
"minimax-m2.7": { input: 0.3, output: 1.2, cachedInput: 0.06 },
|
|
14176
|
+
"minimax-m2.5": { input: 0.3, output: 1.2, cachedInput: 0.06 },
|
|
14177
|
+
"glm-5.2": { input: 1.4, output: 4.4, cachedInput: 0.26 },
|
|
14178
|
+
"glm-5.1": { input: 1.4, output: 4.4, cachedInput: 0.26 },
|
|
14179
|
+
"glm-5": { input: 1, output: 3.2, cachedInput: 0.2 },
|
|
13877
14180
|
"glm-5.3": { input: 1.4, output: 4.4 },
|
|
13878
14181
|
"kimi-k2.7-code": { input: 0.95, output: 4 },
|
|
13879
14182
|
"kimi-k3": { input: 3, output: 15 },
|
|
@@ -13935,6 +14238,7 @@ class CostTracker {
|
|
|
13935
14238
|
config;
|
|
13936
14239
|
model;
|
|
13937
14240
|
_total = 0;
|
|
14241
|
+
_saved = 0;
|
|
13938
14242
|
_known = false;
|
|
13939
14243
|
byProvider = new Map;
|
|
13940
14244
|
constructor(model, config) {
|
|
@@ -13944,24 +14248,28 @@ class CostTracker {
|
|
|
13944
14248
|
setModel(model) {
|
|
13945
14249
|
this.model = model;
|
|
13946
14250
|
}
|
|
13947
|
-
record(promptTokens, completionTokens, provider) {
|
|
14251
|
+
record(promptTokens, completionTokens, provider, cache) {
|
|
13948
14252
|
const key = provider || "unknown";
|
|
13949
|
-
const
|
|
13950
|
-
if (
|
|
14253
|
+
const result = calculateCostDetailed(this.model, promptTokens, completionTokens, this.config, cache);
|
|
14254
|
+
if (!result)
|
|
13951
14255
|
return;
|
|
13952
14256
|
this._known = true;
|
|
13953
|
-
this._total += cost;
|
|
14257
|
+
this._total += result.cost;
|
|
14258
|
+
this._saved += result.saved;
|
|
13954
14259
|
let entry = this.byProvider.get(key);
|
|
13955
14260
|
if (!entry) {
|
|
13956
14261
|
entry = { total: 0, known: false };
|
|
13957
14262
|
this.byProvider.set(key, entry);
|
|
13958
14263
|
}
|
|
13959
14264
|
entry.known = true;
|
|
13960
|
-
entry.total += cost;
|
|
14265
|
+
entry.total += result.cost;
|
|
13961
14266
|
}
|
|
13962
14267
|
get total() {
|
|
13963
14268
|
return this._known ? this._total : undefined;
|
|
13964
14269
|
}
|
|
14270
|
+
get saved() {
|
|
14271
|
+
return this._known ? this._saved : undefined;
|
|
14272
|
+
}
|
|
13965
14273
|
totalFor(provider) {
|
|
13966
14274
|
const entry = this.byProvider.get(provider);
|
|
13967
14275
|
return entry && entry.known ? entry.total : undefined;
|
|
@@ -14042,6 +14350,10 @@ function createLoopState() {
|
|
|
14042
14350
|
apiCompletionChars: 0,
|
|
14043
14351
|
estimatedPromptTokensTotal: 0,
|
|
14044
14352
|
totalLlmDuration: 0,
|
|
14353
|
+
cacheCachedTotal: 0,
|
|
14354
|
+
cacheUncachedTotal: 0,
|
|
14355
|
+
cacheWriteTotal: 0,
|
|
14356
|
+
cacheSource: "none",
|
|
14045
14357
|
auditRetries: 0,
|
|
14046
14358
|
lastAuditSummary: "",
|
|
14047
14359
|
emptyResponseRetries: 0,
|
|
@@ -14148,6 +14460,7 @@ class TokenTracker {
|
|
|
14148
14460
|
}
|
|
14149
14461
|
beginIteration(state, estimatedPromptTokens) {
|
|
14150
14462
|
state.estimatedPromptTokensTotal += estimatedPromptTokens;
|
|
14463
|
+
state.cacheUsage = undefined;
|
|
14151
14464
|
return {
|
|
14152
14465
|
promptBefore: state.apiPromptTokens,
|
|
14153
14466
|
completionBefore: state.apiCompletionTokens
|
|
@@ -14156,6 +14469,7 @@ class TokenTracker {
|
|
|
14156
14469
|
recordApiUsage(state, baseline, usage) {
|
|
14157
14470
|
state.apiPromptTokens = baseline.promptBefore + usage.promptTokens;
|
|
14158
14471
|
state.apiCompletionTokens = baseline.completionBefore + usage.completionTokens;
|
|
14472
|
+
state.cacheUsage = usage.cache;
|
|
14159
14473
|
}
|
|
14160
14474
|
addCompletionChars(state, chars) {
|
|
14161
14475
|
state.apiCompletionChars += chars;
|
|
@@ -14166,14 +14480,22 @@ class TokenTracker {
|
|
|
14166
14480
|
const source = usagePrompt > 0 || usageCompletion > 0 ? "api" : "estimate";
|
|
14167
14481
|
const prompt = source === "api" ? usagePrompt : contextTokens;
|
|
14168
14482
|
const completion = source === "api" ? usageCompletion : estimateTokens(textContent);
|
|
14483
|
+
if (state.cacheUsage) {
|
|
14484
|
+
state.cacheCachedTotal += state.cacheUsage.cachedTokens;
|
|
14485
|
+
state.cacheUncachedTotal += state.cacheUsage.uncachedTokens;
|
|
14486
|
+
state.cacheWriteTotal += state.cacheUsage.cacheWriteTokens;
|
|
14487
|
+
state.cacheSource = state.cacheUsage.source;
|
|
14488
|
+
}
|
|
14169
14489
|
slog.logLlmUsage(iteration, {
|
|
14170
14490
|
promptTokens: prompt,
|
|
14171
14491
|
completionTokens: completion,
|
|
14172
14492
|
totalTokens: prompt + completion,
|
|
14173
14493
|
source,
|
|
14174
|
-
durationMs
|
|
14494
|
+
durationMs,
|
|
14495
|
+
prefix: state.prefixDelta,
|
|
14496
|
+
cache: state.cacheUsage
|
|
14175
14497
|
});
|
|
14176
|
-
this.costTracker.record(prompt, completion, this.getProviderName());
|
|
14498
|
+
this.costTracker.record(prompt, completion, this.getProviderName(), source === "api" ? state.cacheUsage : undefined);
|
|
14177
14499
|
}
|
|
14178
14500
|
resolveFinal(state) {
|
|
14179
14501
|
if (state.apiPromptTokens > 0 || state.apiCompletionTokens > 0) {
|
|
@@ -14192,6 +14514,75 @@ var init_token_tracker = __esm(() => {
|
|
|
14192
14514
|
init_token_counter();
|
|
14193
14515
|
});
|
|
14194
14516
|
|
|
14517
|
+
// src/core/agent/prefix-monitor.ts
|
|
14518
|
+
function serializeTools(tools) {
|
|
14519
|
+
return tools.map((t2) => `${t2.name}\x01${t2.description}\x01${JSON.stringify(t2.parameters)}`).join("\x02");
|
|
14520
|
+
}
|
|
14521
|
+
function serializeMessages(messages) {
|
|
14522
|
+
return messages.map((m) => `${m.role}\x01${typeof m.content === "string" ? m.content : JSON.stringify(m.content)}`).join("\x02");
|
|
14523
|
+
}
|
|
14524
|
+
function buildPromptSnapshot(messages, tools) {
|
|
14525
|
+
const system = [];
|
|
14526
|
+
const rest = [];
|
|
14527
|
+
for (const m of messages) {
|
|
14528
|
+
if (m.role === "system")
|
|
14529
|
+
system.push(m);
|
|
14530
|
+
else
|
|
14531
|
+
rest.push(m);
|
|
14532
|
+
}
|
|
14533
|
+
return {
|
|
14534
|
+
system: serializeMessages(system),
|
|
14535
|
+
tools: serializeTools(tools),
|
|
14536
|
+
history: serializeMessages(rest)
|
|
14537
|
+
};
|
|
14538
|
+
}
|
|
14539
|
+
function frame(s) {
|
|
14540
|
+
const full = s.system + SEP + s.tools + SEP + s.history;
|
|
14541
|
+
const toolsStart = s.system.length + SEP.length;
|
|
14542
|
+
const historyStart = toolsStart + s.tools.length + SEP.length;
|
|
14543
|
+
return { full, toolsStart, historyStart };
|
|
14544
|
+
}
|
|
14545
|
+
function diffPrompt(prev, curr, countTokens) {
|
|
14546
|
+
const c = frame(curr);
|
|
14547
|
+
const currTokens = countTokens(c.full);
|
|
14548
|
+
if (!prev) {
|
|
14549
|
+
return {
|
|
14550
|
+
prevTokens: 0,
|
|
14551
|
+
currTokens,
|
|
14552
|
+
commonPrefixTokens: 0,
|
|
14553
|
+
stableRatio: 0,
|
|
14554
|
+
cause: "unknown"
|
|
14555
|
+
};
|
|
14556
|
+
}
|
|
14557
|
+
const p = frame(prev);
|
|
14558
|
+
const prevTokens = countTokens(p.full);
|
|
14559
|
+
const maxCp = Math.min(p.full.length, c.full.length);
|
|
14560
|
+
let cp = 0;
|
|
14561
|
+
while (cp < maxCp && p.full[cp] === c.full[cp])
|
|
14562
|
+
cp++;
|
|
14563
|
+
const commonPrefixTokens = countTokens(c.full.slice(0, cp));
|
|
14564
|
+
const stableRatio = currTokens === 0 ? 0 : Math.min(1, commonPrefixTokens / currTokens);
|
|
14565
|
+
if (cp === maxCp) {
|
|
14566
|
+
return { prevTokens, currTokens, commonPrefixTokens, stableRatio, cause: "none" };
|
|
14567
|
+
}
|
|
14568
|
+
let cause;
|
|
14569
|
+
if (cp >= c.historyStart)
|
|
14570
|
+
cause = "history";
|
|
14571
|
+
else if (cp >= c.toolsStart)
|
|
14572
|
+
cause = "tools";
|
|
14573
|
+
else
|
|
14574
|
+
cause = "system";
|
|
14575
|
+
const window = c.full.slice(Math.max(0, cp - 40), cp + 160) + p.full.slice(Math.max(0, cp - 40), cp + 160);
|
|
14576
|
+
if (VOLATILE_RE.test(window))
|
|
14577
|
+
cause = "volatile";
|
|
14578
|
+
return { prevTokens, currTokens, commonPrefixTokens, stableRatio, cause };
|
|
14579
|
+
}
|
|
14580
|
+
var SEP = `
|
|
14581
|
+
`, VOLATILE_RE;
|
|
14582
|
+
var init_prefix_monitor = __esm(() => {
|
|
14583
|
+
VOLATILE_RE = /(\d{4}-\d{2}-\d{2}|\d{2}:\d{2}:\d{2}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}|[A-Za-z]:\\|\\AppData\\|\\Temp\\|\/tmp\/)/;
|
|
14584
|
+
});
|
|
14585
|
+
|
|
14195
14586
|
// src/core/agent/reasoning-resolver.ts
|
|
14196
14587
|
class ReasoningEffortResolver {
|
|
14197
14588
|
resolve(deps) {
|
|
@@ -14604,8 +14995,8 @@ var init_audit_gate = __esm(() => {
|
|
|
14604
14995
|
|
|
14605
14996
|
// src/core/prompt-overflow.ts
|
|
14606
14997
|
import { createHash } from "crypto";
|
|
14607
|
-
import { existsSync as
|
|
14608
|
-
import { join as
|
|
14998
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "fs";
|
|
14999
|
+
import { join as join18 } from "path";
|
|
14609
15000
|
function dryRunOverflow(allBlocks, systemBudget) {
|
|
14610
15001
|
const builder = new PromptBuilder(systemBudget);
|
|
14611
15002
|
builder.addBlocks(allBlocks);
|
|
@@ -14619,10 +15010,10 @@ function cacheKey(kind, content, maxTokens) {
|
|
|
14619
15010
|
}
|
|
14620
15011
|
function readCache(cacheDir, key) {
|
|
14621
15012
|
try {
|
|
14622
|
-
const path =
|
|
14623
|
-
if (!
|
|
15013
|
+
const path = join18(cacheDir, `${key}.md`);
|
|
15014
|
+
if (!existsSync28(path))
|
|
14624
15015
|
return null;
|
|
14625
|
-
const raw =
|
|
15016
|
+
const raw = readFileSync15(path, "utf-8").trim();
|
|
14626
15017
|
if (!raw)
|
|
14627
15018
|
return null;
|
|
14628
15019
|
try {
|
|
@@ -14640,7 +15031,7 @@ function readCache(cacheDir, key) {
|
|
|
14640
15031
|
function writeCache(cacheDir, key, entry) {
|
|
14641
15032
|
try {
|
|
14642
15033
|
mkdirSync13(cacheDir, { recursive: true });
|
|
14643
|
-
writeFileSync10(
|
|
15034
|
+
writeFileSync10(join18(cacheDir, `${key}.md`), JSON.stringify(entry), "utf-8");
|
|
14644
15035
|
} catch {}
|
|
14645
15036
|
}
|
|
14646
15037
|
async function collectText(provider, prompt, maxTokens) {
|
|
@@ -14800,7 +15191,7 @@ function contextWindowHint(config, configDir, recommended) {
|
|
|
14800
15191
|
if (src.source === "global") {
|
|
14801
15192
|
return `run "mma context ${recommended}"`;
|
|
14802
15193
|
}
|
|
14803
|
-
return `edit "${
|
|
15194
|
+
return `edit "${join18(configDir, "config", "provider.json")}" → provider.entries[label="${src.label}"].contextWindow = ${recommended}`;
|
|
14804
15195
|
}
|
|
14805
15196
|
function recommendContextSize(neededSystemTokens) {
|
|
14806
15197
|
const sizes = [8192, 16384, 32768, 65536, 131072, 262144];
|
|
@@ -14850,7 +15241,7 @@ var init_prompt_overflow = __esm(() => {
|
|
|
14850
15241
|
});
|
|
14851
15242
|
|
|
14852
15243
|
// src/core/agent.ts
|
|
14853
|
-
import { join as
|
|
15244
|
+
import { join as join19 } from "path";
|
|
14854
15245
|
function mutationTargetKey(name, rawArgs) {
|
|
14855
15246
|
let a = null;
|
|
14856
15247
|
if (typeof rawArgs === "string") {
|
|
@@ -15005,7 +15396,7 @@ class Agent {
|
|
|
15005
15396
|
includedTokens: dry.blocks.filter((b) => b.included).reduce((s, b) => s + b.tokens, 0),
|
|
15006
15397
|
systemBudget,
|
|
15007
15398
|
provider: cfg.instructions?.summarize === false ? null : this.deps.llmProvider,
|
|
15008
|
-
cacheDir:
|
|
15399
|
+
cacheDir: join19(this.deps.baseDir, ".mma", "cache", "prompt-summaries"),
|
|
15009
15400
|
logger: this.deps.logger
|
|
15010
15401
|
});
|
|
15011
15402
|
for (const r of res.replacements) {
|
|
@@ -15220,6 +15611,12 @@ class Agent {
|
|
|
15220
15611
|
compactionService.compactIfNeeded(state);
|
|
15221
15612
|
this.refreshSystemPrompt();
|
|
15222
15613
|
const history = contextManager.getActiveHistory();
|
|
15614
|
+
const promptSnapshot = buildPromptSnapshot(history, allToolsForBudget);
|
|
15615
|
+
state.prefixDelta = diffPrompt(state.prevPrompt, promptSnapshot, estimateTokens);
|
|
15616
|
+
state.prevPrompt = promptSnapshot;
|
|
15617
|
+
if (state.prefixDelta.cause === "system" || state.prefixDelta.cause === "tools" || state.prefixDelta.cause === "history" || state.prefixDelta.cause === "volatile") {
|
|
15618
|
+
state.lastPrefixBreak = state.prefixDelta;
|
|
15619
|
+
}
|
|
15223
15620
|
slog.logToolDefs(allToolsForBudget.length, allToolsForBudget.map((t2) => t2.name), state.iteration);
|
|
15224
15621
|
if (state.iteration === 1) {
|
|
15225
15622
|
const { blocks } = this.buildSystemPrompt();
|
|
@@ -15468,6 +15865,7 @@ class Agent {
|
|
|
15468
15865
|
const tokensUsed = contextManager.getEstimatedTokens();
|
|
15469
15866
|
const budget = contextManager.getBudget();
|
|
15470
15867
|
const usageTokens = tokenTracker.resolveFinal(state);
|
|
15868
|
+
const cacheStats = this.buildCacheStats(state);
|
|
15471
15869
|
if (state.iteration >= config.maxToolIterations && !state.finalAnswerAccepted) {
|
|
15472
15870
|
return {
|
|
15473
15871
|
success: false,
|
|
@@ -15481,6 +15879,7 @@ class Agent {
|
|
|
15481
15879
|
totalTokens: usageTokens.total,
|
|
15482
15880
|
totalCost: this.costTracker.total,
|
|
15483
15881
|
costBreakdown: this.costTracker.breakdown(),
|
|
15882
|
+
cache: cacheStats,
|
|
15484
15883
|
compactionCount: contextManager.getCompactionCount(),
|
|
15485
15884
|
contextQuality: contextManager.getQuality()
|
|
15486
15885
|
};
|
|
@@ -15497,18 +15896,38 @@ class Agent {
|
|
|
15497
15896
|
totalTokens: usageTokens.total,
|
|
15498
15897
|
totalCost: this.costTracker.total,
|
|
15499
15898
|
costBreakdown: this.costTracker.breakdown(),
|
|
15899
|
+
cache: cacheStats,
|
|
15500
15900
|
compactionCount: contextManager.getCompactionCount(),
|
|
15501
15901
|
contextQuality: contextManager.getQuality(),
|
|
15502
15902
|
llmDurationMs: state.totalLlmDuration
|
|
15503
15903
|
};
|
|
15504
15904
|
}
|
|
15905
|
+
buildCacheStats(state) {
|
|
15906
|
+
const hasTokens = state.cacheCachedTotal > 0 || state.cacheUncachedTotal > 0 || state.cacheWriteTotal > 0;
|
|
15907
|
+
const prefix = state.lastPrefixBreak ?? state.prefixDelta;
|
|
15908
|
+
if (!hasTokens && prefix?.stableRatio === undefined)
|
|
15909
|
+
return;
|
|
15910
|
+
const denom = state.cacheCachedTotal + state.cacheUncachedTotal;
|
|
15911
|
+
return {
|
|
15912
|
+
cachedTokens: state.cacheCachedTotal,
|
|
15913
|
+
uncachedTokens: state.cacheUncachedTotal,
|
|
15914
|
+
cacheWriteTokens: state.cacheWriteTotal,
|
|
15915
|
+
hitRate: denom > 0 ? state.cacheCachedTotal / denom : 0,
|
|
15916
|
+
saved: this.costTracker.saved,
|
|
15917
|
+
prefixStable: prefix?.stableRatio,
|
|
15918
|
+
prefixCause: prefix?.cause,
|
|
15919
|
+
source: state.cacheSource
|
|
15920
|
+
};
|
|
15921
|
+
}
|
|
15505
15922
|
clearContext() {
|
|
15506
15923
|
this.deps.contextManager.clear();
|
|
15507
15924
|
this.systemPromptAdded = false;
|
|
15508
15925
|
}
|
|
15509
15926
|
async reconfigure(config) {
|
|
15510
15927
|
const { TokenCounter: TokenCounter2 } = await Promise.resolve().then(() => (init_token_counter(), exports_token_counter));
|
|
15511
|
-
const { provider: newProvider } = buildActiveProvider(config, this.deps.logger
|
|
15928
|
+
const { provider: newProvider } = buildActiveProvider(config, this.deps.logger, {
|
|
15929
|
+
getSessionId: () => this.deps.sessionManager?.getActiveMeta()?.id
|
|
15930
|
+
});
|
|
15512
15931
|
this.deps.llmProvider = newProvider;
|
|
15513
15932
|
this.deps.toolExecutor.updateProvider(newProvider);
|
|
15514
15933
|
const newTokenCounter = new TokenCounter2(config.model);
|
|
@@ -15519,7 +15938,9 @@ class Agent {
|
|
|
15519
15938
|
this.costTracker.setModel(config.model);
|
|
15520
15939
|
}
|
|
15521
15940
|
setProvider(name, model) {
|
|
15522
|
-
const { manager, provider } = buildActiveProvider(this.deps.config, this.deps.logger
|
|
15941
|
+
const { manager, provider } = buildActiveProvider(this.deps.config, this.deps.logger, {
|
|
15942
|
+
getSessionId: () => this.deps.sessionManager?.getActiveMeta()?.id
|
|
15943
|
+
});
|
|
15523
15944
|
manager.switch(name, model);
|
|
15524
15945
|
const providerCfg = manager.toConfig();
|
|
15525
15946
|
this.deps.config.provider = providerCfg;
|
|
@@ -15530,7 +15951,8 @@ class Agent {
|
|
|
15530
15951
|
const manager = new ProviderManager(this.deps.config.provider, {
|
|
15531
15952
|
contextWindow: this.deps.config.contextWindow,
|
|
15532
15953
|
retry: this.deps.config.retry,
|
|
15533
|
-
rateLimits: this.deps.config.security?.rateLimits
|
|
15954
|
+
rateLimits: this.deps.config.security?.rateLimits,
|
|
15955
|
+
getSessionId: () => this.deps.sessionManager?.getActiveMeta()?.id
|
|
15534
15956
|
});
|
|
15535
15957
|
const activeName = this.deps.config.provider.active;
|
|
15536
15958
|
return manager.list().map((e) => ({
|
|
@@ -15544,6 +15966,7 @@ class Agent {
|
|
|
15544
15966
|
contextWindow: this.deps.config.contextWindow,
|
|
15545
15967
|
retry: this.deps.config.retry,
|
|
15546
15968
|
rateLimits: this.deps.config.security?.rateLimits,
|
|
15969
|
+
getSessionId: () => this.deps.sessionManager?.getActiveMeta()?.id,
|
|
15547
15970
|
logger: this.deps.logger
|
|
15548
15971
|
});
|
|
15549
15972
|
manager.setModel(this.deps.config.model);
|
|
@@ -15600,6 +16023,7 @@ var init_agent = __esm(() => {
|
|
|
15600
16023
|
init_loop_state();
|
|
15601
16024
|
init_compaction();
|
|
15602
16025
|
init_token_tracker();
|
|
16026
|
+
init_prefix_monitor();
|
|
15603
16027
|
init_reasoning_resolver();
|
|
15604
16028
|
init_context_renderer();
|
|
15605
16029
|
init_tool_batch();
|
|
@@ -16183,8 +16607,8 @@ var init_confidence = __esm(() => {
|
|
|
16183
16607
|
});
|
|
16184
16608
|
|
|
16185
16609
|
// src/modules/hallucination/factual.ts
|
|
16186
|
-
import { existsSync as
|
|
16187
|
-
import { resolve as resolve14, isAbsolute as isAbsolute4, join as
|
|
16610
|
+
import { existsSync as existsSync29, readdirSync as readdirSync8 } from "fs";
|
|
16611
|
+
import { resolve as resolve14, isAbsolute as isAbsolute4, join as join20 } from "path";
|
|
16188
16612
|
|
|
16189
16613
|
class FactualCheck {
|
|
16190
16614
|
baseDir;
|
|
@@ -16227,13 +16651,13 @@ class FactualCheck {
|
|
|
16227
16651
|
}
|
|
16228
16652
|
pathExists(fp) {
|
|
16229
16653
|
if (isAbsolute4(fp))
|
|
16230
|
-
return
|
|
16654
|
+
return existsSync29(fp);
|
|
16231
16655
|
if (this.knownFiles.has(fp))
|
|
16232
16656
|
return true;
|
|
16233
16657
|
for (const cand of this.dotfileVariants(fp)) {
|
|
16234
16658
|
if (this.knownFiles.has(cand))
|
|
16235
16659
|
return true;
|
|
16236
|
-
if (
|
|
16660
|
+
if (existsSync29(resolve14(this.baseDir, cand)))
|
|
16237
16661
|
return true;
|
|
16238
16662
|
}
|
|
16239
16663
|
if (!fp.includes("/") && !fp.includes("\\")) {
|
|
@@ -16261,7 +16685,7 @@ class FactualCheck {
|
|
|
16261
16685
|
}
|
|
16262
16686
|
bareNameExists(name) {
|
|
16263
16687
|
for (const cand of this.dotfileVariants(name)) {
|
|
16264
|
-
if (
|
|
16688
|
+
if (existsSync29(resolve14(this.baseDir, cand)))
|
|
16265
16689
|
return true;
|
|
16266
16690
|
if (this.indexHas(cand))
|
|
16267
16691
|
return true;
|
|
@@ -16307,7 +16731,7 @@ class FactualCheck {
|
|
|
16307
16731
|
for (const entry of entries) {
|
|
16308
16732
|
if (count >= FactualCheck.MAX_INDEXED_FILES)
|
|
16309
16733
|
break;
|
|
16310
|
-
const full =
|
|
16734
|
+
const full = join20(dir, entry.name);
|
|
16311
16735
|
if (entry.isDirectory()) {
|
|
16312
16736
|
if (!IGNORED_DIRS2.has(entry.name)) {
|
|
16313
16737
|
count = this.scanDir(full, index, count);
|
|
@@ -16489,10 +16913,10 @@ var init_detector = __esm(() => {
|
|
|
16489
16913
|
});
|
|
16490
16914
|
|
|
16491
16915
|
// src/modules/lsp/command.ts
|
|
16492
|
-
import { delimiter, join as
|
|
16493
|
-
import { existsSync as
|
|
16494
|
-
import { platform as
|
|
16495
|
-
function resolveSpawnCommand(command, platformName =
|
|
16916
|
+
import { delimiter, join as join21 } from "path";
|
|
16917
|
+
import { existsSync as existsSync30 } from "fs";
|
|
16918
|
+
import { platform as platform5 } from "os";
|
|
16919
|
+
function resolveSpawnCommand(command, platformName = platform5(), pathEnv = process.env.PATH ?? "") {
|
|
16496
16920
|
if (platformName !== "win32")
|
|
16497
16921
|
return command;
|
|
16498
16922
|
if (command.includes("/") || command.includes("\\") || WIN_EXTS.some((ext) => command.toLowerCase().endsWith(ext))) {
|
|
@@ -16501,8 +16925,8 @@ function resolveSpawnCommand(command, platformName = platform4(), pathEnv = proc
|
|
|
16501
16925
|
const dirs = pathEnv.split(delimiter).filter(Boolean);
|
|
16502
16926
|
for (const dir of dirs) {
|
|
16503
16927
|
for (const ext of WIN_EXTS) {
|
|
16504
|
-
const candidate =
|
|
16505
|
-
if (
|
|
16928
|
+
const candidate = join21(dir, `${command}${ext}`);
|
|
16929
|
+
if (existsSync30(candidate))
|
|
16506
16930
|
return `${command}${ext}`;
|
|
16507
16931
|
}
|
|
16508
16932
|
}
|
|
@@ -16524,7 +16948,7 @@ var init_command = __esm(() => {
|
|
|
16524
16948
|
});
|
|
16525
16949
|
|
|
16526
16950
|
// src/modules/updater/checker.ts
|
|
16527
|
-
import { platform as
|
|
16951
|
+
import { platform as platform6 } from "os";
|
|
16528
16952
|
function semverGt(a, b) {
|
|
16529
16953
|
const pa = a.replace(/^v/, "").split(/[.-]/).map((p) => Number.parseInt(p, 10) || 0);
|
|
16530
16954
|
const pb = b.replace(/^v/, "").split(/[.-]/).map((p) => Number.parseInt(p, 10) || 0);
|
|
@@ -16595,7 +17019,7 @@ class Updater {
|
|
|
16595
17019
|
buildInstallCommand(latest) {
|
|
16596
17020
|
const npmArgs = ["install", "-g", `${this.packageName}@${latest}`];
|
|
16597
17021
|
const command = resolveSpawnCommand("npm");
|
|
16598
|
-
if (
|
|
17022
|
+
if (platform6() === "win32" && /\.(cmd|bat)$/i.test(command)) {
|
|
16599
17023
|
return { command: "cmd.exe", args: ["/c", command, ...npmArgs] };
|
|
16600
17024
|
}
|
|
16601
17025
|
return { command, args: npmArgs };
|
|
@@ -17146,7 +17570,7 @@ var init_chunk_query = __esm(() => {
|
|
|
17146
17570
|
});
|
|
17147
17571
|
|
|
17148
17572
|
// src/tools/chunk-query.ts
|
|
17149
|
-
import { readFileSync as
|
|
17573
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
17150
17574
|
import { resolve as resolve15 } from "node:path";
|
|
17151
17575
|
var chunkQueryTool;
|
|
17152
17576
|
var init_chunk_query2 = __esm(() => {
|
|
@@ -17219,7 +17643,7 @@ var init_chunk_query2 = __esm(() => {
|
|
|
17219
17643
|
return { success: false, output: `[SCOPE] ${check.reason || "Path not allowed"}` };
|
|
17220
17644
|
}
|
|
17221
17645
|
try {
|
|
17222
|
-
content =
|
|
17646
|
+
content = readFileSync16(resolvedInput, "utf8");
|
|
17223
17647
|
} catch (e) {
|
|
17224
17648
|
return { success: false, output: `Cannot read ${inputPath}: ${e.message}` };
|
|
17225
17649
|
}
|
|
@@ -17672,7 +18096,7 @@ var init_web_browse = __esm(() => {
|
|
|
17672
18096
|
|
|
17673
18097
|
// src/tools/download-file.ts
|
|
17674
18098
|
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync14 } from "fs";
|
|
17675
|
-
import { dirname as
|
|
18099
|
+
import { dirname as dirname12 } from "path";
|
|
17676
18100
|
var MAX_DOWNLOAD_BYTES, downloadFileTool;
|
|
17677
18101
|
var init_download_file = __esm(() => {
|
|
17678
18102
|
init_i18n();
|
|
@@ -17760,7 +18184,7 @@ var init_download_file = __esm(() => {
|
|
|
17760
18184
|
output: t("tool.download_too_large", { max: String(maxBytes) })
|
|
17761
18185
|
};
|
|
17762
18186
|
}
|
|
17763
|
-
mkdirSync14(
|
|
18187
|
+
mkdirSync14(dirname12(resolved), { recursive: true });
|
|
17764
18188
|
writeFileSync11(resolved, buffer);
|
|
17765
18189
|
const contentType = response.headers.get("content-type")?.split(";")[0]?.trim() || "unknown";
|
|
17766
18190
|
logNetworkRequest(ctx.sessionId, sanitizeUrl(url), true, `Status: ${response.status}`);
|
|
@@ -18627,7 +19051,7 @@ ${JSON.stringify(result, null, 2)}`
|
|
|
18627
19051
|
|
|
18628
19052
|
// src/tools/search-history.ts
|
|
18629
19053
|
import * as fs from "fs";
|
|
18630
|
-
import { join as
|
|
19054
|
+
import { join as join22 } from "path";
|
|
18631
19055
|
import { homedir as homedir6 } from "os";
|
|
18632
19056
|
function searchFile(filePath, query, maxResults, results) {
|
|
18633
19057
|
if (!fs.existsSync(filePath))
|
|
@@ -18672,7 +19096,7 @@ var init_search_history = __esm(() => {
|
|
|
18672
19096
|
const query = String(args.query || "").toLowerCase();
|
|
18673
19097
|
const maxResults = Number(args.maxResults) || 5;
|
|
18674
19098
|
const sessionId = args.sessionId ? String(args.sessionId) : null;
|
|
18675
|
-
const sessionDir =
|
|
19099
|
+
const sessionDir = join22(homedir6(), ".mma", "sessions");
|
|
18676
19100
|
const results = [];
|
|
18677
19101
|
try {
|
|
18678
19102
|
if (!fs.existsSync(sessionDir)) {
|
|
@@ -18687,7 +19111,7 @@ var init_search_history = __esm(() => {
|
|
|
18687
19111
|
continue;
|
|
18688
19112
|
if (sessionId && entry.name !== sessionId)
|
|
18689
19113
|
continue;
|
|
18690
|
-
const historyFile =
|
|
19114
|
+
const historyFile = join22(sessionDir, entry.name, "history.jsonl");
|
|
18691
19115
|
searchFile(historyFile, query, maxResults, results);
|
|
18692
19116
|
if (results.length >= maxResults)
|
|
18693
19117
|
break;
|
|
@@ -18714,8 +19138,8 @@ var init_search_history = __esm(() => {
|
|
|
18714
19138
|
});
|
|
18715
19139
|
|
|
18716
19140
|
// src/modules/memory/search.ts
|
|
18717
|
-
import { readFileSync as
|
|
18718
|
-
import { join as
|
|
19141
|
+
import { readFileSync as readFileSync18, existsSync as existsSync32 } from "fs";
|
|
19142
|
+
import { join as join23 } from "path";
|
|
18719
19143
|
|
|
18720
19144
|
class MemorySearch {
|
|
18721
19145
|
memoryDir;
|
|
@@ -18726,10 +19150,10 @@ class MemorySearch {
|
|
|
18726
19150
|
const results = [];
|
|
18727
19151
|
const lowerQuery = query.toLowerCase();
|
|
18728
19152
|
for (const name of MEMORY_FILES) {
|
|
18729
|
-
const path =
|
|
18730
|
-
if (!
|
|
19153
|
+
const path = join23(this.memoryDir, `${name}.md`);
|
|
19154
|
+
if (!existsSync32(path))
|
|
18731
19155
|
continue;
|
|
18732
|
-
const content =
|
|
19156
|
+
const content = readFileSync18(path, "utf-8");
|
|
18733
19157
|
const lines = content.split(`
|
|
18734
19158
|
`);
|
|
18735
19159
|
for (const line of lines) {
|
|
@@ -18738,10 +19162,10 @@ class MemorySearch {
|
|
|
18738
19162
|
}
|
|
18739
19163
|
}
|
|
18740
19164
|
}
|
|
18741
|
-
const prefsPath =
|
|
18742
|
-
if (
|
|
19165
|
+
const prefsPath = join23(this.memoryDir, "preferences.json");
|
|
19166
|
+
if (existsSync32(prefsPath)) {
|
|
18743
19167
|
try {
|
|
18744
|
-
const prefs = JSON.parse(
|
|
19168
|
+
const prefs = JSON.parse(readFileSync18(prefsPath, "utf-8"));
|
|
18745
19169
|
for (const [key, value] of Object.entries(prefs)) {
|
|
18746
19170
|
const searchStr = `${key}=${value}`;
|
|
18747
19171
|
if (searchStr.toLowerCase().includes(lowerQuery)) {
|
|
@@ -18759,8 +19183,8 @@ var init_search = __esm(() => {
|
|
|
18759
19183
|
});
|
|
18760
19184
|
|
|
18761
19185
|
// src/modules/memory/store.ts
|
|
18762
|
-
import { readFileSync as
|
|
18763
|
-
import { join as
|
|
19186
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync12, appendFileSync as appendFileSync5, existsSync as existsSync33, mkdirSync as mkdirSync15 } from "fs";
|
|
19187
|
+
import { join as join24 } from "path";
|
|
18764
19188
|
|
|
18765
19189
|
class MemoryStore {
|
|
18766
19190
|
memoryDir;
|
|
@@ -18768,8 +19192,8 @@ class MemoryStore {
|
|
|
18768
19192
|
this.memoryDir = memoryDir;
|
|
18769
19193
|
this.ensureDir();
|
|
18770
19194
|
for (const name of MEMORY_FILES2) {
|
|
18771
|
-
const path =
|
|
18772
|
-
if (!
|
|
19195
|
+
const path = join24(this.memoryDir, `${name}.md`);
|
|
19196
|
+
if (!existsSync33(path)) {
|
|
18773
19197
|
writeFileSync12(path, `# ${name.charAt(0).toUpperCase() + name.slice(1)}
|
|
18774
19198
|
|
|
18775
19199
|
`, "utf-8");
|
|
@@ -18777,18 +19201,18 @@ class MemoryStore {
|
|
|
18777
19201
|
}
|
|
18778
19202
|
}
|
|
18779
19203
|
ensureDir() {
|
|
18780
|
-
if (!
|
|
19204
|
+
if (!existsSync33(this.memoryDir)) {
|
|
18781
19205
|
mkdirSync15(this.memoryDir, { recursive: true });
|
|
18782
19206
|
}
|
|
18783
19207
|
}
|
|
18784
19208
|
read(name) {
|
|
18785
|
-
const path =
|
|
18786
|
-
if (!
|
|
19209
|
+
const path = join24(this.memoryDir, `${name}.md`);
|
|
19210
|
+
if (!existsSync33(path))
|
|
18787
19211
|
return "";
|
|
18788
|
-
return
|
|
19212
|
+
return readFileSync19(path, "utf-8");
|
|
18789
19213
|
}
|
|
18790
19214
|
append(name, entry) {
|
|
18791
|
-
const path =
|
|
19215
|
+
const path = join24(this.memoryDir, `${name}.md`);
|
|
18792
19216
|
const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
18793
19217
|
const formatted = `- **${timestamp}** — ${entry}
|
|
18794
19218
|
`;
|
|
@@ -18799,14 +19223,14 @@ class MemoryStore {
|
|
|
18799
19223
|
return searchModule.query(query);
|
|
18800
19224
|
}
|
|
18801
19225
|
prefsPath() {
|
|
18802
|
-
return
|
|
19226
|
+
return join24(this.memoryDir, "preferences.json");
|
|
18803
19227
|
}
|
|
18804
19228
|
getPreferences() {
|
|
18805
19229
|
const path = this.prefsPath();
|
|
18806
|
-
if (!
|
|
19230
|
+
if (!existsSync33(path))
|
|
18807
19231
|
return {};
|
|
18808
19232
|
try {
|
|
18809
|
-
return JSON.parse(
|
|
19233
|
+
return JSON.parse(readFileSync19(path, "utf-8"));
|
|
18810
19234
|
} catch {
|
|
18811
19235
|
return {};
|
|
18812
19236
|
}
|
|
@@ -18839,7 +19263,7 @@ var init_store2 = __esm(() => {
|
|
|
18839
19263
|
|
|
18840
19264
|
// src/tools/remember.ts
|
|
18841
19265
|
import { homedir as homedir7 } from "os";
|
|
18842
|
-
import { join as
|
|
19266
|
+
import { join as join25 } from "path";
|
|
18843
19267
|
var CATEGORIES, rememberTool;
|
|
18844
19268
|
var init_remember = __esm(() => {
|
|
18845
19269
|
init_i18n();
|
|
@@ -18878,7 +19302,7 @@ var init_remember = __esm(() => {
|
|
|
18878
19302
|
if (!CATEGORIES.includes(category)) {
|
|
18879
19303
|
return { success: false, output: t("tool.invalid_params") };
|
|
18880
19304
|
}
|
|
18881
|
-
const memoryDir =
|
|
19305
|
+
const memoryDir = join25(homedir7(), ".mma", "memory");
|
|
18882
19306
|
const store = new MemoryStore(memoryDir);
|
|
18883
19307
|
try {
|
|
18884
19308
|
if (category === "preferences") {
|
|
@@ -18911,7 +19335,7 @@ var init_remember = __esm(() => {
|
|
|
18911
19335
|
|
|
18912
19336
|
// src/tools/recall.ts
|
|
18913
19337
|
import { homedir as homedir8 } from "os";
|
|
18914
|
-
import { join as
|
|
19338
|
+
import { join as join26 } from "path";
|
|
18915
19339
|
function formatAll(store) {
|
|
18916
19340
|
const parts = [];
|
|
18917
19341
|
const prefs = store.getPreferences();
|
|
@@ -18995,7 +19419,7 @@ var init_recall = __esm(() => {
|
|
|
18995
19419
|
handler: async (_ctx, args) => {
|
|
18996
19420
|
const query = args.query ? String(args.query) : "";
|
|
18997
19421
|
const category = args.category ? String(args.category) : "";
|
|
18998
|
-
const memoryDir =
|
|
19422
|
+
const memoryDir = join26(homedir8(), ".mma", "memory");
|
|
18999
19423
|
const store = new MemoryStore(memoryDir);
|
|
19000
19424
|
try {
|
|
19001
19425
|
if (!query && !category) {
|
|
@@ -19033,9 +19457,9 @@ var init_recall = __esm(() => {
|
|
|
19033
19457
|
});
|
|
19034
19458
|
|
|
19035
19459
|
// src/modules/browser/bridge-path.ts
|
|
19036
|
-
import { existsSync as
|
|
19460
|
+
import { existsSync as existsSync34 } from "fs";
|
|
19037
19461
|
function pickExistingPath(candidates, fallback = candidates[0]) {
|
|
19038
|
-
return candidates.find((p) =>
|
|
19462
|
+
return candidates.find((p) => existsSync34(p)) ?? fallback;
|
|
19039
19463
|
}
|
|
19040
19464
|
var init_bridge_path = () => {};
|
|
19041
19465
|
|
|
@@ -19046,13 +19470,13 @@ __export(exports_bridge_client, {
|
|
|
19046
19470
|
});
|
|
19047
19471
|
import { spawn as spawn6 } from "child_process";
|
|
19048
19472
|
import { createInterface } from "readline";
|
|
19049
|
-
import { dirname as
|
|
19050
|
-
import { fileURLToPath } from "url";
|
|
19473
|
+
import { dirname as dirname13, join as join27 } from "path";
|
|
19474
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
19051
19475
|
function bridgeScriptPath() {
|
|
19052
|
-
const dir =
|
|
19476
|
+
const dir = dirname13(fileURLToPath2(import.meta.url));
|
|
19053
19477
|
const candidates = [
|
|
19054
|
-
|
|
19055
|
-
|
|
19478
|
+
join27(dir, "bridge-server.mjs"),
|
|
19479
|
+
join27(dir, "modules", "browser", "bridge-server.mjs")
|
|
19056
19480
|
];
|
|
19057
19481
|
return pickExistingPath(candidates);
|
|
19058
19482
|
}
|
|
@@ -19606,15 +20030,15 @@ function buildTextExtractionScript() {
|
|
|
19606
20030
|
|
|
19607
20031
|
// src/modules/browser/cookie-store.ts
|
|
19608
20032
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
19609
|
-
import { join as
|
|
20033
|
+
import { join as join28 } from "path";
|
|
19610
20034
|
|
|
19611
20035
|
class CookieStore {
|
|
19612
20036
|
filePath;
|
|
19613
20037
|
constructor(cookieDir) {
|
|
19614
|
-
this.filePath =
|
|
20038
|
+
this.filePath = join28(cookieDir, "cookies.json");
|
|
19615
20039
|
}
|
|
19616
20040
|
async save(cookies) {
|
|
19617
|
-
await mkdir(
|
|
20041
|
+
await mkdir(join28(this.filePath, ".."), { recursive: true });
|
|
19618
20042
|
await writeFile(this.filePath, JSON.stringify(cookies, null, 2), "utf-8");
|
|
19619
20043
|
}
|
|
19620
20044
|
async load() {
|
|
@@ -19972,10 +20396,10 @@ var init_session = __esm(() => {
|
|
|
19972
20396
|
});
|
|
19973
20397
|
|
|
19974
20398
|
// src/tools/browser.ts
|
|
19975
|
-
import { join as
|
|
20399
|
+
import { join as join29 } from "path";
|
|
19976
20400
|
function getSession(ctx) {
|
|
19977
20401
|
if (!session) {
|
|
19978
|
-
const cookieDir =
|
|
20402
|
+
const cookieDir = join29(ctx.baseDir, ".mma", "browser");
|
|
19979
20403
|
session = new BrowserSession({
|
|
19980
20404
|
...DEFAULT_BROWSER_CONFIG,
|
|
19981
20405
|
headless: ctx.config.browser?.headless ?? true,
|
|
@@ -20101,7 +20525,7 @@ __export(exports_image_utils, {
|
|
|
20101
20525
|
detectMime: () => detectMime,
|
|
20102
20526
|
bufferToDataUrl: () => bufferToDataUrl
|
|
20103
20527
|
});
|
|
20104
|
-
import { readFileSync as
|
|
20528
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
20105
20529
|
import { extname as extname4 } from "path";
|
|
20106
20530
|
function detectMime(filePath) {
|
|
20107
20531
|
const ext = extname4(filePath).toLowerCase();
|
|
@@ -20120,13 +20544,13 @@ async function readClipboardImage() {
|
|
|
20120
20544
|
return readClipboardFallback();
|
|
20121
20545
|
}
|
|
20122
20546
|
async function readClipboardFallback() {
|
|
20123
|
-
const { platform:
|
|
20547
|
+
const { platform: platform7 } = await import("os");
|
|
20124
20548
|
const { execSync } = await import("child_process");
|
|
20125
|
-
const { readFileSync:
|
|
20126
|
-
const { join:
|
|
20127
|
-
if (
|
|
20549
|
+
const { readFileSync: readFileSync21, unlinkSync: unlinkSync5 } = await import("fs");
|
|
20550
|
+
const { join: join30 } = await import("path");
|
|
20551
|
+
if (platform7() !== "linux")
|
|
20128
20552
|
return null;
|
|
20129
|
-
const tmpPath =
|
|
20553
|
+
const tmpPath = join30(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
20130
20554
|
const commands = [
|
|
20131
20555
|
`wl-paste --type image/png > "${tmpPath}" 2>/dev/null`,
|
|
20132
20556
|
`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`
|
|
@@ -20134,7 +20558,7 @@ async function readClipboardFallback() {
|
|
|
20134
20558
|
for (const cmd of commands) {
|
|
20135
20559
|
try {
|
|
20136
20560
|
execSync(cmd, { timeout: 5000 });
|
|
20137
|
-
const buf =
|
|
20561
|
+
const buf = readFileSync21(tmpPath);
|
|
20138
20562
|
unlinkSync5(tmpPath);
|
|
20139
20563
|
if (buf.length > 0)
|
|
20140
20564
|
return buf;
|
|
@@ -20146,7 +20570,7 @@ async function readClipboardFallback() {
|
|
|
20146
20570
|
return null;
|
|
20147
20571
|
}
|
|
20148
20572
|
async function loadFileAsDataUrl(filePath) {
|
|
20149
|
-
const buf =
|
|
20573
|
+
const buf = readFileSync20(filePath);
|
|
20150
20574
|
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
20151
20575
|
try {
|
|
20152
20576
|
const img = new Bun.Image(buf);
|
|
@@ -20206,7 +20630,7 @@ var init_image_utils = __esm(() => {
|
|
|
20206
20630
|
});
|
|
20207
20631
|
|
|
20208
20632
|
// src/tools/attach-image.ts
|
|
20209
|
-
import { existsSync as
|
|
20633
|
+
import { existsSync as existsSync35 } from "fs";
|
|
20210
20634
|
import { resolve as resolve16 } from "path";
|
|
20211
20635
|
var attachImageTool;
|
|
20212
20636
|
var init_attach_image = __esm(() => {
|
|
@@ -20258,7 +20682,7 @@ var init_attach_image = __esm(() => {
|
|
|
20258
20682
|
dataUrl = result.dataUrl;
|
|
20259
20683
|
} else {
|
|
20260
20684
|
const absPath = resolve16(ctx.baseDir, source);
|
|
20261
|
-
if (!
|
|
20685
|
+
if (!existsSync35(absPath)) {
|
|
20262
20686
|
return {
|
|
20263
20687
|
success: false,
|
|
20264
20688
|
output: t("image.not_found", { path: source })
|
|
@@ -20567,16 +20991,16 @@ class ModuleRegistry {
|
|
|
20567
20991
|
}
|
|
20568
20992
|
|
|
20569
20993
|
// src/modules/plugins/loader.ts
|
|
20570
|
-
import { readdirSync as readdirSync10, existsSync as
|
|
20571
|
-
import { join as
|
|
20994
|
+
import { readdirSync as readdirSync10, existsSync as existsSync36, statSync as statSync6 } from "fs";
|
|
20995
|
+
import { join as join30, basename as basename3 } from "path";
|
|
20572
20996
|
|
|
20573
20997
|
class PluginLoader {
|
|
20574
20998
|
loadFromDir(dirPath, pluginManager, logger2, options) {
|
|
20575
|
-
if (!
|
|
20999
|
+
if (!existsSync36(dirPath))
|
|
20576
21000
|
return;
|
|
20577
21001
|
const entries = readdirSync10(dirPath).sort();
|
|
20578
21002
|
for (const entry of entries) {
|
|
20579
|
-
const fullPath =
|
|
21003
|
+
const fullPath = join30(dirPath, entry);
|
|
20580
21004
|
const stat = statSync6(fullPath);
|
|
20581
21005
|
if (stat.isFile()) {
|
|
20582
21006
|
if (!entry.endsWith(".ts") && !entry.endsWith(".js"))
|
|
@@ -20592,8 +21016,8 @@ class PluginLoader {
|
|
|
20592
21016
|
}
|
|
20593
21017
|
findEntryFile(dir) {
|
|
20594
21018
|
for (const name of FOLDER_ENTRY_NAMES) {
|
|
20595
|
-
const candidate =
|
|
20596
|
-
if (
|
|
21019
|
+
const candidate = join30(dir, name);
|
|
21020
|
+
if (existsSync36(candidate))
|
|
20597
21021
|
return candidate;
|
|
20598
21022
|
}
|
|
20599
21023
|
return null;
|
|
@@ -20798,9 +21222,9 @@ var init_auto_fixer = __esm(() => {
|
|
|
20798
21222
|
|
|
20799
21223
|
// src/modules/plugins/builtin/lint-on-write.ts
|
|
20800
21224
|
import { spawn as spawn7, execSync } from "child_process";
|
|
20801
|
-
import { existsSync as
|
|
20802
|
-
import { resolve as resolve17, extname as extname6, join as
|
|
20803
|
-
import { platform as
|
|
21225
|
+
import { existsSync as existsSync37, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
|
|
21226
|
+
import { resolve as resolve17, extname as extname6, join as join31 } from "path";
|
|
21227
|
+
import { platform as platform7 } from "os";
|
|
20804
21228
|
function lintCacheKey(baseDir, lintScript) {
|
|
20805
21229
|
return `${baseDir}::${lintScript}`;
|
|
20806
21230
|
}
|
|
@@ -20821,7 +21245,7 @@ function contentHash2(content) {
|
|
|
20821
21245
|
function getWinDecoder() {
|
|
20822
21246
|
if (_winDecoder !== undefined)
|
|
20823
21247
|
return _winDecoder;
|
|
20824
|
-
if (
|
|
21248
|
+
if (platform7() !== "win32") {
|
|
20825
21249
|
_winDecoder = new TextDecoder("utf-8");
|
|
20826
21250
|
return _winDecoder;
|
|
20827
21251
|
}
|
|
@@ -20875,7 +21299,7 @@ class LintOnWritePlugin {
|
|
|
20875
21299
|
if (!path)
|
|
20876
21300
|
return;
|
|
20877
21301
|
const fullPath = resolve17(ctx.baseDir, path);
|
|
20878
|
-
if (!
|
|
21302
|
+
if (!existsSync37(fullPath))
|
|
20879
21303
|
return;
|
|
20880
21304
|
const signal = ctx.signal;
|
|
20881
21305
|
if (signal?.aborted)
|
|
@@ -20899,7 +21323,7 @@ class LintOnWritePlugin {
|
|
|
20899
21323
|
if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
|
|
20900
21324
|
let content = "";
|
|
20901
21325
|
try {
|
|
20902
|
-
content =
|
|
21326
|
+
content = readFileSync21(filePath, "utf-8");
|
|
20903
21327
|
} catch {
|
|
20904
21328
|
return null;
|
|
20905
21329
|
}
|
|
@@ -20941,11 +21365,11 @@ class LintOnWritePlugin {
|
|
|
20941
21365
|
async runProjectLint(ctx, result, signal) {
|
|
20942
21366
|
let lintScript;
|
|
20943
21367
|
try {
|
|
20944
|
-
const packageJsonPath =
|
|
20945
|
-
if (!
|
|
21368
|
+
const packageJsonPath = join31(ctx.baseDir, "package.json");
|
|
21369
|
+
if (!existsSync37(packageJsonPath)) {
|
|
20946
21370
|
return;
|
|
20947
21371
|
}
|
|
20948
|
-
const packageJson = JSON.parse(
|
|
21372
|
+
const packageJson = JSON.parse(readFileSync21(packageJsonPath, "utf-8"));
|
|
20949
21373
|
lintScript = packageJson.scripts?.lint;
|
|
20950
21374
|
if (!lintScript) {
|
|
20951
21375
|
return;
|
|
@@ -20978,8 +21402,12 @@ ${stdout}`;
|
|
|
20978
21402
|
}
|
|
20979
21403
|
async runProjectTypeCheck(filePath, baseDir, result, signal) {
|
|
20980
21404
|
const projectRoot = findProjectRoot(filePath, baseDir, ["tsconfig.json", "package.json"]);
|
|
20981
|
-
const tsconfigPath =
|
|
20982
|
-
if (!
|
|
21405
|
+
const tsconfigPath = join31(projectRoot, "tsconfig.json");
|
|
21406
|
+
if (!existsSync37(tsconfigPath)) {
|
|
21407
|
+
return;
|
|
21408
|
+
}
|
|
21409
|
+
const tsc = resolveTscCommand(projectRoot);
|
|
21410
|
+
if (!tsc) {
|
|
20983
21411
|
return;
|
|
20984
21412
|
}
|
|
20985
21413
|
const now = Date.now();
|
|
@@ -20993,14 +21421,14 @@ ${stdout}`;
|
|
|
20993
21421
|
return;
|
|
20994
21422
|
}
|
|
20995
21423
|
this._checkTimestamp = now;
|
|
20996
|
-
this._checkPromise = this.runTscCheck(projectRoot, signal);
|
|
21424
|
+
this._checkPromise = this.runTscCheck(tsc, projectRoot, signal);
|
|
20997
21425
|
const error = await this._checkPromise;
|
|
20998
21426
|
if (error) {
|
|
20999
|
-
const { stdout, stderr } = await runAsync(
|
|
21427
|
+
const { stdout, stderr } = await runAsync(`${tsc} --noEmit --skipLibCheck 2>&1`, projectRoot, 30000, signal).catch(() => ({ stdout: "", stderr: error }));
|
|
21000
21428
|
const output = stderr || stdout;
|
|
21001
21429
|
const errors = parseTscOutput(output);
|
|
21002
21430
|
if (errors.length > 0) {
|
|
21003
|
-
const fixResult = autoFixErrors(filePath,
|
|
21431
|
+
const fixResult = autoFixErrors(filePath, readFileSync21(filePath, "utf-8"), errors);
|
|
21004
21432
|
if (fixResult.fixed) {
|
|
21005
21433
|
writeFileSync13(filePath, fixResult.newContent, "utf-8");
|
|
21006
21434
|
result.output += `
|
|
@@ -21025,9 +21453,9 @@ ${stdout}`;
|
|
|
21025
21453
|
}
|
|
21026
21454
|
}
|
|
21027
21455
|
}
|
|
21028
|
-
async runTscCheck(baseDir, signal) {
|
|
21456
|
+
async runTscCheck(tsc, baseDir, signal) {
|
|
21029
21457
|
try {
|
|
21030
|
-
const { stdout, stderr } = await runAsync(
|
|
21458
|
+
const { stdout, stderr } = await runAsync(`${tsc} --noEmit --skipLibCheck`, baseDir, 30000, signal);
|
|
21031
21459
|
return null;
|
|
21032
21460
|
} catch (err) {
|
|
21033
21461
|
if (err.status === 127 || err.message.includes("not found") || err.message.includes("ENOENT")) {
|
|
@@ -21265,11 +21693,11 @@ class PlanTracker {
|
|
|
21265
21693
|
var init_tracker = () => {};
|
|
21266
21694
|
|
|
21267
21695
|
// src/modules/execution/plan-store.ts
|
|
21268
|
-
import { readFileSync as
|
|
21269
|
-
import { join as
|
|
21696
|
+
import { readFileSync as readFileSync22, writeFileSync as writeFileSync14, renameSync as renameSync3, mkdirSync as mkdirSync16, existsSync as existsSync38, readdirSync as readdirSync11, rmSync } from "fs";
|
|
21697
|
+
import { join as join32 } from "path";
|
|
21270
21698
|
function readPlanFile(path, fallbackBaseDir) {
|
|
21271
21699
|
try {
|
|
21272
|
-
const raw =
|
|
21700
|
+
const raw = readFileSync22(path, "utf-8");
|
|
21273
21701
|
if (!raw.trim())
|
|
21274
21702
|
return null;
|
|
21275
21703
|
const parsed = JSON.parse(raw);
|
|
@@ -21293,10 +21721,10 @@ function writePlanFile(path, plan) {
|
|
|
21293
21721
|
renameSync3(tmpPath, path);
|
|
21294
21722
|
}
|
|
21295
21723
|
function listDir(dir, baseDir) {
|
|
21296
|
-
if (!
|
|
21724
|
+
if (!existsSync38(dir))
|
|
21297
21725
|
return [];
|
|
21298
21726
|
const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
|
|
21299
|
-
return files.map((f) => readPlanFile(
|
|
21727
|
+
return files.map((f) => readPlanFile(join32(dir, f), baseDir)).filter((p) => p !== null);
|
|
21300
21728
|
}
|
|
21301
21729
|
function toMeta(plan, status) {
|
|
21302
21730
|
return {
|
|
@@ -21317,33 +21745,33 @@ class PlanStore {
|
|
|
21317
21745
|
archiveDir;
|
|
21318
21746
|
legacyPath;
|
|
21319
21747
|
constructor(baseDir) {
|
|
21320
|
-
const mmaDir =
|
|
21321
|
-
if (!
|
|
21748
|
+
const mmaDir = join32(baseDir, ".mma");
|
|
21749
|
+
if (!existsSync38(mmaDir))
|
|
21322
21750
|
mkdirSync16(mmaDir, { recursive: true });
|
|
21323
21751
|
this.baseDir = baseDir;
|
|
21324
|
-
this.plansDir =
|
|
21325
|
-
this.draftsDir =
|
|
21326
|
-
this.archiveDir =
|
|
21327
|
-
this.legacyPath =
|
|
21752
|
+
this.plansDir = join32(mmaDir, "plans");
|
|
21753
|
+
this.draftsDir = join32(this.plansDir, "drafts");
|
|
21754
|
+
this.archiveDir = join32(this.plansDir, "archive");
|
|
21755
|
+
this.legacyPath = join32(mmaDir, LEGACY_FILE);
|
|
21328
21756
|
for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
|
|
21329
|
-
if (!
|
|
21757
|
+
if (!existsSync38(dir))
|
|
21330
21758
|
mkdirSync16(dir, { recursive: true });
|
|
21331
21759
|
}
|
|
21332
21760
|
}
|
|
21333
21761
|
activePath() {
|
|
21334
|
-
return
|
|
21762
|
+
return join32(this.plansDir, "active.json");
|
|
21335
21763
|
}
|
|
21336
21764
|
saveActive(plan) {
|
|
21337
21765
|
writePlanFile(this.activePath(), plan);
|
|
21338
21766
|
}
|
|
21339
21767
|
loadActive() {
|
|
21340
21768
|
const activePath = this.activePath();
|
|
21341
|
-
if (
|
|
21769
|
+
if (existsSync38(activePath)) {
|
|
21342
21770
|
const plan = readPlanFile(activePath, this.baseDir);
|
|
21343
21771
|
if (plan)
|
|
21344
21772
|
return plan;
|
|
21345
21773
|
}
|
|
21346
|
-
if (
|
|
21774
|
+
if (existsSync38(this.legacyPath)) {
|
|
21347
21775
|
const legacy = readPlanFile(this.legacyPath, this.baseDir);
|
|
21348
21776
|
if (legacy) {
|
|
21349
21777
|
this.saveActive(legacy);
|
|
@@ -21362,26 +21790,26 @@ class PlanStore {
|
|
|
21362
21790
|
}
|
|
21363
21791
|
clearActive() {
|
|
21364
21792
|
const p = this.activePath();
|
|
21365
|
-
if (
|
|
21793
|
+
if (existsSync38(p))
|
|
21366
21794
|
rmSync(p, { force: true });
|
|
21367
21795
|
}
|
|
21368
21796
|
saveDraft(plan) {
|
|
21369
|
-
writePlanFile(
|
|
21797
|
+
writePlanFile(join32(this.draftsDir, `${plan.id}.json`), plan);
|
|
21370
21798
|
}
|
|
21371
21799
|
loadDraft(id) {
|
|
21372
|
-
const p =
|
|
21373
|
-
return
|
|
21800
|
+
const p = join32(this.draftsDir, `${id}.json`);
|
|
21801
|
+
return existsSync38(p) ? readPlanFile(p, this.baseDir) : null;
|
|
21374
21802
|
}
|
|
21375
21803
|
removeDraft(id) {
|
|
21376
|
-
const p =
|
|
21377
|
-
if (
|
|
21804
|
+
const p = join32(this.draftsDir, `${id}.json`);
|
|
21805
|
+
if (existsSync38(p))
|
|
21378
21806
|
rmSync(p, { force: true });
|
|
21379
21807
|
}
|
|
21380
21808
|
listDrafts() {
|
|
21381
21809
|
return listDir(this.draftsDir, this.baseDir);
|
|
21382
21810
|
}
|
|
21383
21811
|
archivePlan(plan) {
|
|
21384
|
-
writePlanFile(
|
|
21812
|
+
writePlanFile(join32(this.archiveDir, `${plan.id}.json`), plan);
|
|
21385
21813
|
this.removeDraft(plan.id);
|
|
21386
21814
|
const active = this.loadActive();
|
|
21387
21815
|
if (active && active.id === plan.id) {
|
|
@@ -21392,8 +21820,8 @@ class PlanStore {
|
|
|
21392
21820
|
return listDir(this.archiveDir, this.baseDir);
|
|
21393
21821
|
}
|
|
21394
21822
|
removeArchived(id) {
|
|
21395
|
-
const p =
|
|
21396
|
-
if (
|
|
21823
|
+
const p = join32(this.archiveDir, `${id}.json`);
|
|
21824
|
+
if (existsSync38(p))
|
|
21397
21825
|
rmSync(p, { force: true });
|
|
21398
21826
|
}
|
|
21399
21827
|
listAll() {
|
|
@@ -21425,13 +21853,13 @@ class PlanStore {
|
|
|
21425
21853
|
this.clearActive();
|
|
21426
21854
|
return "active";
|
|
21427
21855
|
}
|
|
21428
|
-
const draftPath =
|
|
21429
|
-
if (
|
|
21856
|
+
const draftPath = join32(this.draftsDir, `${id}.json`);
|
|
21857
|
+
if (existsSync38(draftPath)) {
|
|
21430
21858
|
rmSync(draftPath, { force: true });
|
|
21431
21859
|
return "draft";
|
|
21432
21860
|
}
|
|
21433
|
-
const archivedPath =
|
|
21434
|
-
if (
|
|
21861
|
+
const archivedPath = join32(this.archiveDir, `${id}.json`);
|
|
21862
|
+
if (existsSync38(archivedPath)) {
|
|
21435
21863
|
rmSync(archivedPath, { force: true });
|
|
21436
21864
|
return "archived";
|
|
21437
21865
|
}
|
|
@@ -21513,7 +21941,7 @@ function switchStepToDelete(plan, step, save) {
|
|
|
21513
21941
|
}
|
|
21514
21942
|
|
|
21515
21943
|
// src/modules/execution/execution-plugin.ts
|
|
21516
|
-
import { platform as
|
|
21944
|
+
import { platform as platform8 } from "os";
|
|
21517
21945
|
function normalizeBrokenPath(p) {
|
|
21518
21946
|
return toForwardSlash(p).replace(/^\.\//, "");
|
|
21519
21947
|
}
|
|
@@ -21746,7 +22174,7 @@ Last compile error: ${first[1]}`;
|
|
|
21746
22174
|
if (call.name === "bash") {
|
|
21747
22175
|
deps.stuckDetector.recordBashAttempt(false);
|
|
21748
22176
|
}
|
|
21749
|
-
if (call.name === "bash" &&
|
|
22177
|
+
if (call.name === "bash" && platform8() === "win32") {
|
|
21750
22178
|
const cmd = String(call.arguments?.command ?? "");
|
|
21751
22179
|
const forbidden = forbiddenWindowsCommand(cmd);
|
|
21752
22180
|
if (forbidden) {
|
|
@@ -22551,7 +22979,7 @@ var init_plan_tool = __esm(() => {
|
|
|
22551
22979
|
});
|
|
22552
22980
|
|
|
22553
22981
|
// src/modules/execution/module.ts
|
|
22554
|
-
import { existsSync as
|
|
22982
|
+
import { existsSync as existsSync39, readFileSync as readFileSync23 } from "fs";
|
|
22555
22983
|
import { resolve as resolve18 } from "path";
|
|
22556
22984
|
|
|
22557
22985
|
class ExecutionModule {
|
|
@@ -22910,7 +23338,7 @@ class ExecutionModule {
|
|
|
22910
23338
|
"poetry.lock",
|
|
22911
23339
|
"requirements.txt"
|
|
22912
23340
|
];
|
|
22913
|
-
const hasLockFile = lockFiles.some((f) =>
|
|
23341
|
+
const hasLockFile = lockFiles.some((f) => existsSync39(resolve18(this.baseDir, f)));
|
|
22914
23342
|
if (!hasLockFile) {
|
|
22915
23343
|
if (contextManager) {
|
|
22916
23344
|
const hints = this.state.depsGateHints.get(step.id) || 0;
|
|
@@ -22942,7 +23370,7 @@ class ExecutionModule {
|
|
|
22942
23370
|
if (!r)
|
|
22943
23371
|
continue;
|
|
22944
23372
|
try {
|
|
22945
|
-
const content =
|
|
23373
|
+
const content = readFileSync23(r, "utf-8");
|
|
22946
23374
|
if (content.trim().length < 10) {
|
|
22947
23375
|
emptyFiles.push(r);
|
|
22948
23376
|
}
|
|
@@ -23050,8 +23478,8 @@ var init_module = __esm(() => {
|
|
|
23050
23478
|
});
|
|
23051
23479
|
|
|
23052
23480
|
// src/modules/security/session-encryption.ts
|
|
23053
|
-
import { readFileSync as
|
|
23054
|
-
import { join as
|
|
23481
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync15, existsSync as existsSync40, readdirSync as readdirSync12, unlinkSync as unlinkSync5 } from "fs";
|
|
23482
|
+
import { join as join33 } from "path";
|
|
23055
23483
|
import { homedir as homedir9 } from "os";
|
|
23056
23484
|
|
|
23057
23485
|
class SessionFileEncryptor {
|
|
@@ -23060,7 +23488,7 @@ class SessionFileEncryptor {
|
|
|
23060
23488
|
constructor(config) {
|
|
23061
23489
|
this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
|
|
23062
23490
|
this.encryptor = new ConfigEncryptor({
|
|
23063
|
-
keyPath: config?.keyPath ||
|
|
23491
|
+
keyPath: config?.keyPath || join33(homedir9(), ".mma", ".session-encryption-key")
|
|
23064
23492
|
});
|
|
23065
23493
|
}
|
|
23066
23494
|
isEnabled() {
|
|
@@ -23112,7 +23540,7 @@ class SessionFileEncryptor {
|
|
|
23112
23540
|
});
|
|
23113
23541
|
}
|
|
23114
23542
|
readSessionFile(filePath) {
|
|
23115
|
-
const content =
|
|
23543
|
+
const content = readFileSync24(filePath, "utf8");
|
|
23116
23544
|
return this.decryptFileContent(content);
|
|
23117
23545
|
}
|
|
23118
23546
|
writeSessionFile(filePath, content) {
|
|
@@ -23120,7 +23548,7 @@ class SessionFileEncryptor {
|
|
|
23120
23548
|
writeFileSync15(filePath, encrypted, "utf8");
|
|
23121
23549
|
}
|
|
23122
23550
|
readSessionJSON(filePath) {
|
|
23123
|
-
const content =
|
|
23551
|
+
const content = readFileSync24(filePath, "utf8");
|
|
23124
23552
|
return this.decryptJSON(content);
|
|
23125
23553
|
}
|
|
23126
23554
|
writeSessionJSON(filePath, obj) {
|
|
@@ -23128,7 +23556,7 @@ class SessionFileEncryptor {
|
|
|
23128
23556
|
writeFileSync15(filePath, content, "utf8");
|
|
23129
23557
|
}
|
|
23130
23558
|
readSessionJSONL(filePath) {
|
|
23131
|
-
const content =
|
|
23559
|
+
const content = readFileSync24(filePath, "utf8");
|
|
23132
23560
|
const lines = content.split(`
|
|
23133
23561
|
`).filter((line) => line.trim());
|
|
23134
23562
|
const decryptedLines = this.decryptJSONL(lines);
|
|
@@ -23153,10 +23581,10 @@ class SessionFileEncryptor {
|
|
|
23153
23581
|
return;
|
|
23154
23582
|
const files = readdirSync12(sessionDir);
|
|
23155
23583
|
for (const file of files) {
|
|
23156
|
-
const filePath =
|
|
23157
|
-
if (
|
|
23584
|
+
const filePath = join33(sessionDir, file);
|
|
23585
|
+
if (existsSync40(filePath) && !file.endsWith(".enc")) {
|
|
23158
23586
|
try {
|
|
23159
|
-
const content =
|
|
23587
|
+
const content = readFileSync24(filePath, "utf8");
|
|
23160
23588
|
const encrypted = this.encryptFileContent(content);
|
|
23161
23589
|
writeFileSync15(filePath + ".enc", encrypted, "utf8");
|
|
23162
23590
|
unlinkSync5(filePath);
|
|
@@ -23170,10 +23598,10 @@ class SessionFileEncryptor {
|
|
|
23170
23598
|
const files = readdirSync12(sessionDir);
|
|
23171
23599
|
for (const file of files) {
|
|
23172
23600
|
if (file.endsWith(".enc")) {
|
|
23173
|
-
const encFilePath =
|
|
23601
|
+
const encFilePath = join33(sessionDir, file);
|
|
23174
23602
|
const decFilePath = encFilePath.slice(0, -4);
|
|
23175
23603
|
try {
|
|
23176
|
-
const content =
|
|
23604
|
+
const content = readFileSync24(encFilePath, "utf8");
|
|
23177
23605
|
const decrypted = this.decryptFileContent(content);
|
|
23178
23606
|
writeFileSync15(decFilePath, decrypted, "utf8");
|
|
23179
23607
|
unlinkSync5(encFilePath);
|
|
@@ -23195,15 +23623,15 @@ var init_session_encryption = __esm(() => {
|
|
|
23195
23623
|
|
|
23196
23624
|
// src/modules/session/store.ts
|
|
23197
23625
|
import {
|
|
23198
|
-
existsSync as
|
|
23626
|
+
existsSync as existsSync41,
|
|
23199
23627
|
mkdirSync as mkdirSync17,
|
|
23200
23628
|
readdirSync as readdirSync13,
|
|
23201
|
-
readFileSync as
|
|
23629
|
+
readFileSync as readFileSync25,
|
|
23202
23630
|
rmSync as rmSync2,
|
|
23203
23631
|
writeFileSync as writeFileSync16,
|
|
23204
23632
|
appendFileSync as appendFileSync6
|
|
23205
23633
|
} from "fs";
|
|
23206
|
-
import { join as
|
|
23634
|
+
import { join as join34 } from "path";
|
|
23207
23635
|
import { gzipSync } from "zlib";
|
|
23208
23636
|
|
|
23209
23637
|
class SessionStore {
|
|
@@ -23217,7 +23645,7 @@ class SessionStore {
|
|
|
23217
23645
|
}
|
|
23218
23646
|
}
|
|
23219
23647
|
getSessionDir(id) {
|
|
23220
|
-
return
|
|
23648
|
+
return join34(this.baseDir, id);
|
|
23221
23649
|
}
|
|
23222
23650
|
updateEncryption(config) {
|
|
23223
23651
|
if (config?.enabled) {
|
|
@@ -23233,19 +23661,19 @@ class SessionStore {
|
|
|
23233
23661
|
mkdirSync17(this.baseDir, { recursive: true, mode: 448 });
|
|
23234
23662
|
}
|
|
23235
23663
|
sessionDir(id) {
|
|
23236
|
-
return
|
|
23664
|
+
return join34(this.baseDir, id);
|
|
23237
23665
|
}
|
|
23238
23666
|
metaPath(id) {
|
|
23239
|
-
return
|
|
23667
|
+
return join34(this.sessionDir(id), "meta.json");
|
|
23240
23668
|
}
|
|
23241
23669
|
historyPath(id) {
|
|
23242
|
-
return
|
|
23670
|
+
return join34(this.sessionDir(id), "history.jsonl");
|
|
23243
23671
|
}
|
|
23244
23672
|
sessionLogPath(id) {
|
|
23245
|
-
return
|
|
23673
|
+
return join34(this.sessionDir(id), "session.jsonl");
|
|
23246
23674
|
}
|
|
23247
23675
|
sessionExists(id) {
|
|
23248
|
-
return
|
|
23676
|
+
return existsSync41(this.metaPath(id));
|
|
23249
23677
|
}
|
|
23250
23678
|
saveMeta(id, meta) {
|
|
23251
23679
|
this._metaCache.set(id, meta);
|
|
@@ -23263,10 +23691,10 @@ class SessionStore {
|
|
|
23263
23691
|
if (cached)
|
|
23264
23692
|
return cached;
|
|
23265
23693
|
const path = this.metaPath(id);
|
|
23266
|
-
if (!
|
|
23694
|
+
if (!existsSync41(path))
|
|
23267
23695
|
return null;
|
|
23268
23696
|
try {
|
|
23269
|
-
const raw =
|
|
23697
|
+
const raw = readFileSync25(path, "utf-8");
|
|
23270
23698
|
const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
|
|
23271
23699
|
const meta = JSON.parse(content);
|
|
23272
23700
|
this._metaCache.set(id, meta);
|
|
@@ -23277,10 +23705,10 @@ class SessionStore {
|
|
|
23277
23705
|
}
|
|
23278
23706
|
readMetaFromDisk(id) {
|
|
23279
23707
|
const path = this.metaPath(id);
|
|
23280
|
-
if (!
|
|
23708
|
+
if (!existsSync41(path))
|
|
23281
23709
|
return null;
|
|
23282
23710
|
try {
|
|
23283
|
-
const raw =
|
|
23711
|
+
const raw = readFileSync25(path, "utf-8");
|
|
23284
23712
|
const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
|
|
23285
23713
|
return JSON.parse(content);
|
|
23286
23714
|
} catch {
|
|
@@ -23307,10 +23735,10 @@ class SessionStore {
|
|
|
23307
23735
|
}
|
|
23308
23736
|
loadHistory(id) {
|
|
23309
23737
|
const path = this.historyPath(id);
|
|
23310
|
-
if (!
|
|
23738
|
+
if (!existsSync41(path))
|
|
23311
23739
|
return [];
|
|
23312
23740
|
try {
|
|
23313
|
-
const raw =
|
|
23741
|
+
const raw = readFileSync25(path, "utf-8");
|
|
23314
23742
|
const lines = raw.split(`
|
|
23315
23743
|
`).filter(Boolean);
|
|
23316
23744
|
const parseLine = (line) => {
|
|
@@ -23348,10 +23776,10 @@ class SessionStore {
|
|
|
23348
23776
|
}
|
|
23349
23777
|
loadSessionLog(id) {
|
|
23350
23778
|
const path = this.sessionLogPath(id);
|
|
23351
|
-
if (!
|
|
23779
|
+
if (!existsSync41(path))
|
|
23352
23780
|
return [];
|
|
23353
23781
|
try {
|
|
23354
|
-
const raw =
|
|
23782
|
+
const raw = readFileSync25(path, "utf-8");
|
|
23355
23783
|
const lines = raw.split(`
|
|
23356
23784
|
`).filter(Boolean);
|
|
23357
23785
|
const parseLine = (line) => {
|
|
@@ -23376,7 +23804,7 @@ class SessionStore {
|
|
|
23376
23804
|
}
|
|
23377
23805
|
}
|
|
23378
23806
|
listSessions() {
|
|
23379
|
-
if (!
|
|
23807
|
+
if (!existsSync41(this.baseDir))
|
|
23380
23808
|
return [];
|
|
23381
23809
|
const entries = readdirSync13(this.baseDir, { withFileTypes: true });
|
|
23382
23810
|
const sessions = [];
|
|
@@ -23393,7 +23821,7 @@ class SessionStore {
|
|
|
23393
23821
|
deleteSession(id) {
|
|
23394
23822
|
this._metaCache.delete(id);
|
|
23395
23823
|
const dir = this.sessionDir(id);
|
|
23396
|
-
if (
|
|
23824
|
+
if (existsSync41(dir)) {
|
|
23397
23825
|
rmSync2(dir, { recursive: true, force: true });
|
|
23398
23826
|
}
|
|
23399
23827
|
}
|
|
@@ -23405,10 +23833,10 @@ class SessionStore {
|
|
|
23405
23833
|
const updatedAt = new Date(session2.updatedAt);
|
|
23406
23834
|
if (updatedAt < thirtyDaysAgo) {
|
|
23407
23835
|
const historyPath = this.historyPath(session2.id);
|
|
23408
|
-
if (
|
|
23409
|
-
const content =
|
|
23836
|
+
if (existsSync41(historyPath)) {
|
|
23837
|
+
const content = readFileSync25(historyPath, "utf-8");
|
|
23410
23838
|
const compressed = gzipSync(content);
|
|
23411
|
-
const gzPath =
|
|
23839
|
+
const gzPath = join34(this.baseDir, `${session2.id}.jsonl.gz`);
|
|
23412
23840
|
writeFileSync16(gzPath, compressed);
|
|
23413
23841
|
rmSync2(historyPath);
|
|
23414
23842
|
const meta = this.loadMeta(session2.id);
|
|
@@ -23638,9 +24066,9 @@ class ProfileCompressor {
|
|
|
23638
24066
|
}
|
|
23639
24067
|
|
|
23640
24068
|
// src/modules/user-profile/profile.ts
|
|
23641
|
-
import { readFileSync as
|
|
23642
|
-
import { join as
|
|
23643
|
-
import { homedir as homedir10, hostname, platform as
|
|
24069
|
+
import { readFileSync as readFileSync26, writeFileSync as writeFileSync17, existsSync as existsSync42, mkdirSync as mkdirSync18 } from "fs";
|
|
24070
|
+
import { join as join35 } from "path";
|
|
24071
|
+
import { homedir as homedir10, hostname, platform as platform9, type } from "os";
|
|
23644
24072
|
import { env } from "process";
|
|
23645
24073
|
|
|
23646
24074
|
class UserProfile {
|
|
@@ -23652,7 +24080,7 @@ class UserProfile {
|
|
|
23652
24080
|
}
|
|
23653
24081
|
collect() {
|
|
23654
24082
|
this.info = {
|
|
23655
|
-
platform:
|
|
24083
|
+
platform: platform9(),
|
|
23656
24084
|
os: `${type()} ${hostname()}`,
|
|
23657
24085
|
hostname: hostname(),
|
|
23658
24086
|
shell: env.SHELL || env.ComSpec || "unknown",
|
|
@@ -23663,17 +24091,17 @@ class UserProfile {
|
|
|
23663
24091
|
return this.info;
|
|
23664
24092
|
}
|
|
23665
24093
|
save() {
|
|
23666
|
-
if (!
|
|
24094
|
+
if (!existsSync42(this.profileDir)) {
|
|
23667
24095
|
mkdirSync18(this.profileDir, { recursive: true });
|
|
23668
24096
|
}
|
|
23669
|
-
writeFileSync17(
|
|
24097
|
+
writeFileSync17(join35(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
|
|
23670
24098
|
}
|
|
23671
24099
|
load() {
|
|
23672
|
-
const path =
|
|
23673
|
-
if (!
|
|
24100
|
+
const path = join35(this.profileDir, "profile.json");
|
|
24101
|
+
if (!existsSync42(path))
|
|
23674
24102
|
return null;
|
|
23675
24103
|
try {
|
|
23676
|
-
const data = JSON.parse(
|
|
24104
|
+
const data = JSON.parse(readFileSync26(path, "utf-8"));
|
|
23677
24105
|
this.info = {
|
|
23678
24106
|
platform: data.platform,
|
|
23679
24107
|
os: data.os,
|
|
@@ -23708,12 +24136,12 @@ class UserProfile {
|
|
|
23708
24136
|
var init_profile = () => {};
|
|
23709
24137
|
|
|
23710
24138
|
// src/modules/skills/loader.ts
|
|
23711
|
-
import { readdirSync as readdirSync14, readFileSync as
|
|
23712
|
-
import { join as
|
|
24139
|
+
import { readdirSync as readdirSync14, readFileSync as readFileSync27, existsSync as existsSync43, statSync as statSync7 } from "fs";
|
|
24140
|
+
import { join as join36 } from "path";
|
|
23713
24141
|
|
|
23714
24142
|
class SkillsLoader {
|
|
23715
24143
|
loadFromDir(dirPath) {
|
|
23716
|
-
if (!
|
|
24144
|
+
if (!existsSync43(dirPath))
|
|
23717
24145
|
return [];
|
|
23718
24146
|
const skills = [];
|
|
23719
24147
|
this.scanDir(dirPath, skills);
|
|
@@ -23722,7 +24150,7 @@ class SkillsLoader {
|
|
|
23722
24150
|
scanDir(dirPath, skills) {
|
|
23723
24151
|
const entries = readdirSync14(dirPath);
|
|
23724
24152
|
for (const entry of entries) {
|
|
23725
|
-
const fullPath =
|
|
24153
|
+
const fullPath = join36(dirPath, entry);
|
|
23726
24154
|
let stat;
|
|
23727
24155
|
try {
|
|
23728
24156
|
stat = statSync7(fullPath);
|
|
@@ -23735,7 +24163,7 @@ class SkillsLoader {
|
|
|
23735
24163
|
}
|
|
23736
24164
|
if (!entry.endsWith(".md") && !entry.endsWith(".skill.md"))
|
|
23737
24165
|
continue;
|
|
23738
|
-
const content =
|
|
24166
|
+
const content = readFileSync27(fullPath, "utf-8");
|
|
23739
24167
|
const parsed = this.parseSkillFile(content, fullPath);
|
|
23740
24168
|
if (parsed)
|
|
23741
24169
|
skills.push(parsed);
|
|
@@ -23974,7 +24402,7 @@ var init_browser2 = __esm(() => {
|
|
|
23974
24402
|
// src/modules/lsp/client.ts
|
|
23975
24403
|
import { spawn as spawn8, execSync as execSync2 } from "child_process";
|
|
23976
24404
|
import { resolve as resolve19 } from "path";
|
|
23977
|
-
import { platform as
|
|
24405
|
+
import { platform as platform10 } from "os";
|
|
23978
24406
|
|
|
23979
24407
|
class FileOnlyLogger {
|
|
23980
24408
|
logger;
|
|
@@ -24094,7 +24522,7 @@ class LspClient {
|
|
|
24094
24522
|
if (config.command === "npx" && effectiveArgs.length > 0) {
|
|
24095
24523
|
const binaryName = this.extractBinaryFromNpxArgs(effectiveArgs);
|
|
24096
24524
|
if (binaryName) {
|
|
24097
|
-
const whichCmd =
|
|
24525
|
+
const whichCmd = platform10() === "win32" ? `where ${binaryName}` : `which ${binaryName}`;
|
|
24098
24526
|
try {
|
|
24099
24527
|
execSync2(whichCmd, { stdio: "pipe", timeout: 3000 });
|
|
24100
24528
|
effectiveCommand = binaryName;
|
|
@@ -24107,7 +24535,7 @@ class LspClient {
|
|
|
24107
24535
|
}
|
|
24108
24536
|
return new Promise((resolve20, reject) => {
|
|
24109
24537
|
const args = effectiveArgs;
|
|
24110
|
-
const isWin =
|
|
24538
|
+
const isWin = platform10() === "win32";
|
|
24111
24539
|
let spawnCommand = resolveSpawnCommand(effectiveCommand);
|
|
24112
24540
|
let spawnArgs = args;
|
|
24113
24541
|
const spawnOpts = {
|
|
@@ -24382,11 +24810,11 @@ var init_check_tool = __esm(() => {
|
|
|
24382
24810
|
});
|
|
24383
24811
|
|
|
24384
24812
|
// src/modules/lsp/module.ts
|
|
24385
|
-
import { existsSync as
|
|
24813
|
+
import { existsSync as existsSync44 } from "fs";
|
|
24386
24814
|
import { relative as relative5, resolve as resolve21 } from "path";
|
|
24387
|
-
import { join as
|
|
24815
|
+
import { join as join37 } from "path";
|
|
24388
24816
|
function hasTypeEnvironment(projectRoot) {
|
|
24389
|
-
return
|
|
24817
|
+
return existsSync44(join37(projectRoot, "tsconfig.json")) || existsSync44(join37(projectRoot, "jsconfig.json")) || existsSync44(join37(projectRoot, "node_modules"));
|
|
24390
24818
|
}
|
|
24391
24819
|
|
|
24392
24820
|
class LspModule {
|
|
@@ -24441,7 +24869,7 @@ class LspModule {
|
|
|
24441
24869
|
if (!filePath)
|
|
24442
24870
|
return;
|
|
24443
24871
|
const fullPath = resolve21(_ctx.baseDir, filePath);
|
|
24444
|
-
if (!
|
|
24872
|
+
if (!existsSync44(fullPath))
|
|
24445
24873
|
return;
|
|
24446
24874
|
const serverConfig = getServerForFile(fullPath, self.config);
|
|
24447
24875
|
if (!serverConfig)
|
|
@@ -24533,7 +24961,7 @@ ${items}`;
|
|
|
24533
24961
|
})
|
|
24534
24962
|
};
|
|
24535
24963
|
}
|
|
24536
|
-
if (!
|
|
24964
|
+
if (!existsSync44(resolved)) {
|
|
24537
24965
|
return { success: false, output: t("lsp.check_notfound", { path }) };
|
|
24538
24966
|
}
|
|
24539
24967
|
const files = await collectCheckFiles(resolved, this.config);
|
|
@@ -24650,8 +25078,8 @@ var init_lsp = __esm(() => {
|
|
|
24650
25078
|
});
|
|
24651
25079
|
|
|
24652
25080
|
// src/modules/lsp/startup-check.ts
|
|
24653
|
-
import { existsSync as
|
|
24654
|
-
import { join as
|
|
25081
|
+
import { existsSync as existsSync45 } from "fs";
|
|
25082
|
+
import { join as join38 } from "path";
|
|
24655
25083
|
import { spawn as spawn9 } from "child_process";
|
|
24656
25084
|
async function runStartupHealthCheck(config, baseDir, deps = {}) {
|
|
24657
25085
|
if (!config.enabled)
|
|
@@ -24678,7 +25106,7 @@ ${result.lines.join(`
|
|
|
24678
25106
|
}
|
|
24679
25107
|
async function runCheck(config, baseDir, deps) {
|
|
24680
25108
|
const projectRoot = findProjectRoot(baseDir, baseDir, ["tsconfig.json", "package.json"]);
|
|
24681
|
-
if (
|
|
25109
|
+
if (existsSync45(join38(projectRoot, "tsconfig.json"))) {
|
|
24682
25110
|
const runTsc = deps.runTsc ?? runTscDefault;
|
|
24683
25111
|
const errors = await runTsc(projectRoot, STARTUP_CHECK_TIMEOUT_MS);
|
|
24684
25112
|
if (errors.length === 0)
|
|
@@ -24713,8 +25141,11 @@ async function runCheck(config, baseDir, deps) {
|
|
|
24713
25141
|
return { lines: lines.slice(0, STARTUP_CHECK_ERROR_CAP) };
|
|
24714
25142
|
}
|
|
24715
25143
|
async function runTscDefault(projectRoot, timeoutMs) {
|
|
25144
|
+
const tsc = resolveTscCommand(projectRoot);
|
|
25145
|
+
if (!tsc)
|
|
25146
|
+
return [];
|
|
24716
25147
|
return new Promise((resolve22) => {
|
|
24717
|
-
const child = spawn9(
|
|
25148
|
+
const child = spawn9(`${tsc} --noEmit --skipLibCheck`, {
|
|
24718
25149
|
cwd: projectRoot,
|
|
24719
25150
|
shell: true,
|
|
24720
25151
|
windowsHide: true,
|
|
@@ -24951,8 +25382,8 @@ var init_symbols = __esm(() => {
|
|
|
24951
25382
|
});
|
|
24952
25383
|
|
|
24953
25384
|
// src/modules/indexer/walker.ts
|
|
24954
|
-
import { readdirSync as readdirSync15, readFileSync as
|
|
24955
|
-
import { join as
|
|
25385
|
+
import { readdirSync as readdirSync15, readFileSync as readFileSync28, statSync as statSync8, lstatSync, existsSync as existsSync46, watch } from "fs";
|
|
25386
|
+
import { join as join39, relative as relative6, extname as extname7 } from "path";
|
|
24956
25387
|
function isIgnoredDirName(name) {
|
|
24957
25388
|
return IGNORE_DIRS.has(name.toLowerCase());
|
|
24958
25389
|
}
|
|
@@ -24985,7 +25416,7 @@ class Indexer {
|
|
|
24985
25416
|
let totalSize = 0;
|
|
24986
25417
|
let count = 0;
|
|
24987
25418
|
const walkDir2 = (dir) => {
|
|
24988
|
-
if (!
|
|
25419
|
+
if (!existsSync46(dir))
|
|
24989
25420
|
return;
|
|
24990
25421
|
let entries;
|
|
24991
25422
|
try {
|
|
@@ -24996,7 +25427,7 @@ class Indexer {
|
|
|
24996
25427
|
for (const entry of entries) {
|
|
24997
25428
|
if (count >= this.MAX_FILES)
|
|
24998
25429
|
return;
|
|
24999
|
-
const fullPath =
|
|
25430
|
+
const fullPath = join39(dir, entry);
|
|
25000
25431
|
const relPath = relative6(this.baseDir, fullPath);
|
|
25001
25432
|
try {
|
|
25002
25433
|
const lst = lstatSync(fullPath, { throwIfNoEntry: false });
|
|
@@ -25011,7 +25442,7 @@ class Indexer {
|
|
|
25011
25442
|
const ext = extname7(entry).toLowerCase();
|
|
25012
25443
|
const language = languageIdForExt(ext);
|
|
25013
25444
|
if (language) {
|
|
25014
|
-
const content =
|
|
25445
|
+
const content = readFileSync28(fullPath, "utf-8");
|
|
25015
25446
|
const exports = extractSymbols(content, language);
|
|
25016
25447
|
files.push({ path: relPath, language, exports, size: stat2.size });
|
|
25017
25448
|
totalSize += stat2.size;
|
|
@@ -25081,22 +25512,22 @@ var init_walker = __esm(() => {
|
|
|
25081
25512
|
});
|
|
25082
25513
|
|
|
25083
25514
|
// src/modules/indexer/cache.ts
|
|
25084
|
-
import { readFileSync as
|
|
25085
|
-
import { join as
|
|
25515
|
+
import { readFileSync as readFileSync29, writeFileSync as writeFileSync18, existsSync as existsSync47, mkdirSync as mkdirSync19, rmSync as rmSync3 } from "fs";
|
|
25516
|
+
import { join as join40 } from "path";
|
|
25086
25517
|
|
|
25087
25518
|
class IndexCache {
|
|
25088
25519
|
cachePath;
|
|
25089
25520
|
cache = null;
|
|
25090
25521
|
constructor(cacheDir) {
|
|
25091
|
-
this.cachePath =
|
|
25522
|
+
this.cachePath = join40(cacheDir, "index-cache.json");
|
|
25092
25523
|
}
|
|
25093
25524
|
load() {
|
|
25094
25525
|
if (this.cache)
|
|
25095
25526
|
return this.cache;
|
|
25096
|
-
if (!
|
|
25527
|
+
if (!existsSync47(this.cachePath))
|
|
25097
25528
|
return null;
|
|
25098
25529
|
try {
|
|
25099
|
-
this.cache = JSON.parse(
|
|
25530
|
+
this.cache = JSON.parse(readFileSync29(this.cachePath, "utf-8"));
|
|
25100
25531
|
return this.cache;
|
|
25101
25532
|
} catch {
|
|
25102
25533
|
return null;
|
|
@@ -25104,21 +25535,21 @@ class IndexCache {
|
|
|
25104
25535
|
}
|
|
25105
25536
|
save(result) {
|
|
25106
25537
|
this.cache = result;
|
|
25107
|
-
const dir =
|
|
25108
|
-
if (!
|
|
25538
|
+
const dir = join40(this.cachePath, "..");
|
|
25539
|
+
if (!existsSync47(dir))
|
|
25109
25540
|
mkdirSync19(dir, { recursive: true });
|
|
25110
25541
|
writeFileSync18(this.cachePath, JSON.stringify(result), "utf-8");
|
|
25111
25542
|
}
|
|
25112
25543
|
invalidate() {
|
|
25113
25544
|
this.cache = null;
|
|
25114
|
-
if (
|
|
25545
|
+
if (existsSync47(this.cachePath)) {
|
|
25115
25546
|
try {
|
|
25116
25547
|
rmSync3(this.cachePath);
|
|
25117
25548
|
} catch {}
|
|
25118
25549
|
}
|
|
25119
25550
|
}
|
|
25120
25551
|
}
|
|
25121
|
-
var
|
|
25552
|
+
var init_cache2 = () => {};
|
|
25122
25553
|
|
|
25123
25554
|
// src/modules/indexer/map-select.ts
|
|
25124
25555
|
function isNoiseFile(file) {
|
|
@@ -25186,11 +25617,11 @@ var init_map_select = __esm(() => {
|
|
|
25186
25617
|
});
|
|
25187
25618
|
|
|
25188
25619
|
// src/modules/indexer/project-profile.ts
|
|
25189
|
-
import { readFileSync as
|
|
25190
|
-
import { join as
|
|
25620
|
+
import { readFileSync as readFileSync30, existsSync as existsSync48 } from "fs";
|
|
25621
|
+
import { join as join41 } from "path";
|
|
25191
25622
|
function detectManifest(baseDir) {
|
|
25192
25623
|
for (const manifest of MANIFEST_ORDER) {
|
|
25193
|
-
if (
|
|
25624
|
+
if (existsSync48(join41(baseDir, manifest)))
|
|
25194
25625
|
return manifest;
|
|
25195
25626
|
}
|
|
25196
25627
|
return null;
|
|
@@ -25207,7 +25638,7 @@ function cleanDependency(entry) {
|
|
|
25207
25638
|
}
|
|
25208
25639
|
function readPackageJson(baseDir) {
|
|
25209
25640
|
try {
|
|
25210
|
-
const raw = JSON.parse(
|
|
25641
|
+
const raw = JSON.parse(readFileSync30(join41(baseDir, "package.json"), "utf-8"));
|
|
25211
25642
|
if (!raw || typeof raw !== "object")
|
|
25212
25643
|
return null;
|
|
25213
25644
|
const profile = {
|
|
@@ -25231,7 +25662,7 @@ function readPackageJson(baseDir) {
|
|
|
25231
25662
|
}
|
|
25232
25663
|
function readPyproject(baseDir) {
|
|
25233
25664
|
try {
|
|
25234
|
-
const content =
|
|
25665
|
+
const content = readFileSync30(join41(baseDir, "pyproject.toml"), "utf-8");
|
|
25235
25666
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
25236
25667
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
25237
25668
|
if (nameMatch)
|
|
@@ -25247,7 +25678,7 @@ function readPyproject(baseDir) {
|
|
|
25247
25678
|
}
|
|
25248
25679
|
function readCargo(baseDir) {
|
|
25249
25680
|
try {
|
|
25250
|
-
const content =
|
|
25681
|
+
const content = readFileSync30(join41(baseDir, "Cargo.toml"), "utf-8");
|
|
25251
25682
|
const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
|
|
25252
25683
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
25253
25684
|
if (nameMatch)
|
|
@@ -25271,7 +25702,7 @@ function readCargo(baseDir) {
|
|
|
25271
25702
|
}
|
|
25272
25703
|
function readGoMod(baseDir) {
|
|
25273
25704
|
try {
|
|
25274
|
-
const content =
|
|
25705
|
+
const content = readFileSync30(join41(baseDir, "go.mod"), "utf-8");
|
|
25275
25706
|
const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
|
|
25276
25707
|
const moduleMatch = content.match(/^module\s+(\S+)/m);
|
|
25277
25708
|
if (moduleMatch)
|
|
@@ -25289,7 +25720,7 @@ function readGoMod(baseDir) {
|
|
|
25289
25720
|
}
|
|
25290
25721
|
function readRequirements(baseDir) {
|
|
25291
25722
|
try {
|
|
25292
|
-
const content =
|
|
25723
|
+
const content = readFileSync30(join41(baseDir, "requirements.txt"), "utf-8");
|
|
25293
25724
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
25294
25725
|
for (const line of content.split(`
|
|
25295
25726
|
`)) {
|
|
@@ -25354,7 +25785,7 @@ var init_project_profile = __esm(() => {
|
|
|
25354
25785
|
});
|
|
25355
25786
|
|
|
25356
25787
|
// src/modules/indexer/module.ts
|
|
25357
|
-
import { dirname as
|
|
25788
|
+
import { dirname as dirname15 } from "path";
|
|
25358
25789
|
|
|
25359
25790
|
class IndexerModule {
|
|
25360
25791
|
name = "indexer";
|
|
@@ -25523,7 +25954,7 @@ ${t("indexer.and_more", { count: result.files.length - listed.length })}` : "";
|
|
|
25523
25954
|
const counts = {};
|
|
25524
25955
|
for (const f of result.files) {
|
|
25525
25956
|
const normalized = toForwardSlash(f.path);
|
|
25526
|
-
const dir =
|
|
25957
|
+
const dir = dirname15(normalized);
|
|
25527
25958
|
const key = dir === "." ? "(root)" : dir;
|
|
25528
25959
|
counts[key] = (counts[key] || 0) + 1;
|
|
25529
25960
|
}
|
|
@@ -25590,7 +26021,7 @@ ${stackLine}` : summary;
|
|
|
25590
26021
|
var MAP_FILE_LIMIT = 80;
|
|
25591
26022
|
var init_module6 = __esm(() => {
|
|
25592
26023
|
init_walker();
|
|
25593
|
-
|
|
26024
|
+
init_cache2();
|
|
25594
26025
|
init_map_select();
|
|
25595
26026
|
init_project_profile();
|
|
25596
26027
|
init_i18n();
|
|
@@ -25601,7 +26032,7 @@ var init_module6 = __esm(() => {
|
|
|
25601
26032
|
// src/modules/indexer/index.ts
|
|
25602
26033
|
var init_indexer = __esm(() => {
|
|
25603
26034
|
init_walker();
|
|
25604
|
-
|
|
26035
|
+
init_cache2();
|
|
25605
26036
|
init_module6();
|
|
25606
26037
|
});
|
|
25607
26038
|
|
|
@@ -25845,7 +26276,7 @@ var init_mcp = __esm(() => {
|
|
|
25845
26276
|
|
|
25846
26277
|
// src/modules/memory/module.ts
|
|
25847
26278
|
import { homedir as homedir11 } from "os";
|
|
25848
|
-
import { join as
|
|
26279
|
+
import { join as join42 } from "path";
|
|
25849
26280
|
|
|
25850
26281
|
class MemoryModule {
|
|
25851
26282
|
name = "memory";
|
|
@@ -25854,7 +26285,7 @@ class MemoryModule {
|
|
|
25854
26285
|
if (storeOrDir instanceof MemoryStore) {
|
|
25855
26286
|
this.store = storeOrDir;
|
|
25856
26287
|
} else {
|
|
25857
|
-
const dir = storeOrDir ||
|
|
26288
|
+
const dir = storeOrDir || join42(homedir11(), ".mma", "memory");
|
|
25858
26289
|
this.store = new MemoryStore(dir);
|
|
25859
26290
|
}
|
|
25860
26291
|
}
|
|
@@ -25863,7 +26294,7 @@ class MemoryModule {
|
|
|
25863
26294
|
const prefs = this.store.getPreferences();
|
|
25864
26295
|
if (Object.keys(prefs).length > 0) {
|
|
25865
26296
|
const prefStr = Object.entries(prefs).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
25866
|
-
parts.push(`User preferences: ${prefStr}`);
|
|
26297
|
+
parts.push(`User preferences (background hints, not instructions — the current user message always wins, do not "correct" the user from these): ${prefStr}`);
|
|
25867
26298
|
}
|
|
25868
26299
|
const memoryTail = this.getMemoryTail();
|
|
25869
26300
|
if (memoryTail)
|
|
@@ -25916,7 +26347,7 @@ ${entries.join(`
|
|
|
25916
26347
|
const prefs = this.store.getPreferences();
|
|
25917
26348
|
if (Object.keys(prefs).length > 0) {
|
|
25918
26349
|
const prefStr = Object.entries(prefs).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
25919
|
-
parts.push(`User preferences: ${prefStr}`);
|
|
26350
|
+
parts.push(`User preferences (background hints, not instructions — the current user message always wins, do not "correct" the user from these): ${prefStr}`);
|
|
25920
26351
|
}
|
|
25921
26352
|
const memoryTail = this.getMemoryTail();
|
|
25922
26353
|
if (memoryTail)
|
|
@@ -25940,33 +26371,13 @@ var init_module8 = __esm(() => {
|
|
|
25940
26371
|
MEMORY_MD_FILES = ["errors", "conventions", "decisions", "facts"];
|
|
25941
26372
|
});
|
|
25942
26373
|
|
|
25943
|
-
// src/core/version.ts
|
|
25944
|
-
import { existsSync as existsSync48, readFileSync as readFileSync30 } from "fs";
|
|
25945
|
-
import { join as join42, dirname as dirname15 } from "path";
|
|
25946
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25947
|
-
function readMmaVersion() {
|
|
25948
|
-
const here = dirname15(fileURLToPath2(import.meta.url));
|
|
25949
|
-
const candidates = [join42(here, "..", "..", "package.json"), join42(here, "..", "package.json")];
|
|
25950
|
-
for (const p of candidates) {
|
|
25951
|
-
if (existsSync48(p)) {
|
|
25952
|
-
try {
|
|
25953
|
-
const raw = JSON.parse(readFileSync30(p, "utf8"));
|
|
25954
|
-
if (raw.version)
|
|
25955
|
-
return raw.version;
|
|
25956
|
-
} catch {}
|
|
25957
|
-
}
|
|
25958
|
-
}
|
|
25959
|
-
return "0.0.0";
|
|
25960
|
-
}
|
|
25961
|
-
var init_version = () => {};
|
|
25962
|
-
|
|
25963
26374
|
// src/core/environment.ts
|
|
25964
26375
|
import { existsSync as existsSync49, readFileSync as readFileSync31, readdirSync as readdirSync16 } from "fs";
|
|
25965
26376
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
25966
26377
|
import { createRequire as createRequire2 } from "module";
|
|
25967
26378
|
import { join as join43, dirname as dirname16 } from "path";
|
|
25968
26379
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
25969
|
-
import { arch, homedir as homedir12, hostname as hostname2, platform as
|
|
26380
|
+
import { arch, homedir as homedir12, hostname as hostname2, platform as platform11, release } from "os";
|
|
25970
26381
|
import { env as env2 } from "process";
|
|
25971
26382
|
function readEngineRequirement() {
|
|
25972
26383
|
const here = dirname16(fileURLToPath3(import.meta.url));
|
|
@@ -26112,7 +26523,7 @@ function collectEnvironment(opts) {
|
|
|
26112
26523
|
mmaVersion: readMmaVersion(),
|
|
26113
26524
|
runtime,
|
|
26114
26525
|
os: {
|
|
26115
|
-
platform:
|
|
26526
|
+
platform: platform11(),
|
|
26116
26527
|
arch: arch(),
|
|
26117
26528
|
release: release(),
|
|
26118
26529
|
hostname: hostname2(),
|
|
@@ -26469,6 +26880,7 @@ var init_set_thinking = __esm(() => {
|
|
|
26469
26880
|
// src/core/bootstrap.ts
|
|
26470
26881
|
var exports_bootstrap = {};
|
|
26471
26882
|
__export(exports_bootstrap, {
|
|
26883
|
+
setOneShotMode: () => setOneShotMode,
|
|
26472
26884
|
buildSystemInfo: () => buildSystemInfo,
|
|
26473
26885
|
bootstrap: () => bootstrap
|
|
26474
26886
|
});
|
|
@@ -26540,6 +26952,7 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
26540
26952
|
`Reply in the user's language. Use tools for file ops (read/write/edit/delete), search (glob/grep), shell (bash), web, subagents, browser, MCP. Explain briefly if not obvious. On tool failure: analyze, fix the call, retry up to 2x with different approaches, then ask the user.`,
|
|
26541
26953
|
`Design: YAGNI (no unneeded code), KISS (simple over clever), DRY (reuse existing utilities).`,
|
|
26542
26954
|
`SCOPE DISCIPLINE: do ONLY what the user explicitly asked — no extra features, files, refactors, "improvements", or fixes beyond the request. Read-only requests ("расскажи", "покажи", "объясни", "check") mean READ-ONLY: inspect and answer, never create/modify/delete anything. If the task is ambiguous (what to create, where, which variant) or the request implies action on something you could not find — STOP and ask the user a short clarifying question in plain text instead of guessing.`,
|
|
26955
|
+
`INPUT PRIORITY: the current user message outranks stored memory/preferences/facts. Never override, reinterpret, or "correct" an explicit value the user states now (city, path, name, language, choice) because a stored preference disagrees — follow the user's current message. If they truly conflict or look like a typo, ask the user instead of assuming.`,
|
|
26543
26956
|
`NOT FOUND ≠ MISSING PROJECT: a "not found" tool result means the PATH was wrong (typo, different location), not that the project does not exist. Before creating or scaffolding ANY project/files: first run list_dir on the working directory to see what is already there; if a user-named path is not found, list its parent directory to locate the real path. NEVER create a new project when the user asked about an existing one — inspect first, create only after confirming the workspace is empty AND the user asked for creation.`
|
|
26544
26957
|
];
|
|
26545
26958
|
if (isWin) {
|
|
@@ -26583,6 +26996,9 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
26583
26996
|
return lines.join(`
|
|
26584
26997
|
`);
|
|
26585
26998
|
}
|
|
26999
|
+
function setOneShotMode(value) {
|
|
27000
|
+
oneShotMode = value;
|
|
27001
|
+
}
|
|
26586
27002
|
async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reasoningLevel) {
|
|
26587
27003
|
const dir = configDir || process.env.MMA_CONFIG_DIR || join46(homedir15(), ".mma");
|
|
26588
27004
|
const projectConfigPath = projectDir ? join46(projectDir, ".mmrc") : join46(process.cwd(), ".mmrc");
|
|
@@ -26645,7 +27061,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
26645
27061
|
const profile = new UserProfile(join46(dir));
|
|
26646
27062
|
profile.load() || profile.collect();
|
|
26647
27063
|
profile.save();
|
|
26648
|
-
|
|
27064
|
+
let activeSessionManager;
|
|
27065
|
+
const getSessionId = () => activeSessionManager?.getActiveMeta()?.id;
|
|
27066
|
+
const llmProvider = buildActiveProvider(config, logger4, { getSessionId }).provider;
|
|
26649
27067
|
const providerSpec = BUILTIN_PROVIDERS.find((p) => p.type === config.provider.type);
|
|
26650
27068
|
const reasoningStrategy = providerSpec?.capabilities.reasoningStrategy ?? "none";
|
|
26651
27069
|
let reasoningProbePromise = Promise.resolve(false);
|
|
@@ -26724,6 +27142,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
26724
27142
|
maxSessions: config.session.maxSessions,
|
|
26725
27143
|
isolation: config.sessionIsolation
|
|
26726
27144
|
});
|
|
27145
|
+
activeSessionManager = sessionManager;
|
|
26727
27146
|
if (config.session.autoSave && !sessionManager.getActive()) {
|
|
26728
27147
|
sessionManager.create();
|
|
26729
27148
|
}
|
|
@@ -26815,7 +27234,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
26815
27234
|
moduleRegistry.register(lspModule);
|
|
26816
27235
|
registerBuiltinPlugin(pluginManager, lspModule.getPlugin());
|
|
26817
27236
|
let startupCheckBlock = null;
|
|
26818
|
-
const startupCheckPromise = !exitOnComplete ? runStartupHealthCheck(config.lsp ?? DEFAULT_LSP_CONFIG, baseDir, { logger: lspLogger }) : Promise.resolve(null);
|
|
27237
|
+
const startupCheckPromise = !oneShotMode && !exitOnComplete ? runStartupHealthCheck(config.lsp ?? DEFAULT_LSP_CONFIG, baseDir, { logger: lspLogger }) : Promise.resolve(null);
|
|
26819
27238
|
const moduleTools = moduleRegistry.collectToolDefinitions();
|
|
26820
27239
|
for (const tool of moduleTools) {
|
|
26821
27240
|
toolRegistry.register(tool);
|
|
@@ -26970,6 +27389,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
26970
27389
|
contextProbe: contextProbePromise
|
|
26971
27390
|
};
|
|
26972
27391
|
}
|
|
27392
|
+
var oneShotMode = false;
|
|
26973
27393
|
var init_bootstrap = __esm(() => {
|
|
26974
27394
|
init_config2();
|
|
26975
27395
|
init_app_logger();
|
|
@@ -27445,9 +27865,9 @@ class Spinner {
|
|
|
27445
27865
|
tick() {
|
|
27446
27866
|
if (!this.timer)
|
|
27447
27867
|
return;
|
|
27448
|
-
const
|
|
27868
|
+
const frame2 = FRAMES[this.frame % FRAMES.length];
|
|
27449
27869
|
this.frame++;
|
|
27450
|
-
this.stream.write("\r" + pc2.cyan(
|
|
27870
|
+
this.stream.write("\r" + pc2.cyan(frame2) + " " + this.message + "\x1B[K");
|
|
27451
27871
|
}
|
|
27452
27872
|
}
|
|
27453
27873
|
var FRAMES;
|
|
@@ -30043,9 +30463,9 @@ var require_stringifyNumber = __commonJS((exports) => {
|
|
|
30043
30463
|
function stringifyNumber({ format, minFractionDigits, tag, value }) {
|
|
30044
30464
|
if (typeof value === "bigint")
|
|
30045
30465
|
return String(value);
|
|
30046
|
-
const
|
|
30047
|
-
if (!isFinite(
|
|
30048
|
-
return isNaN(
|
|
30466
|
+
const num3 = typeof value === "number" ? value : Number(value);
|
|
30467
|
+
if (!isFinite(num3))
|
|
30468
|
+
return isNaN(num3) ? ".nan" : num3 < 0 ? "-.inf" : ".inf";
|
|
30049
30469
|
let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
|
|
30050
30470
|
if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n) && !n.includes("e")) {
|
|
30051
30471
|
let i = n.indexOf(".");
|
|
@@ -30082,8 +30502,8 @@ var require_float = __commonJS((exports) => {
|
|
|
30082
30502
|
test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
|
|
30083
30503
|
resolve: (str) => parseFloat(str),
|
|
30084
30504
|
stringify(node) {
|
|
30085
|
-
const
|
|
30086
|
-
return isFinite(
|
|
30505
|
+
const num3 = Number(node.value);
|
|
30506
|
+
return isFinite(num3) ? num3.toExponential() : stringifyNumber.stringifyNumber(node);
|
|
30087
30507
|
}
|
|
30088
30508
|
};
|
|
30089
30509
|
var float = {
|
|
@@ -30487,8 +30907,8 @@ var require_float2 = __commonJS((exports) => {
|
|
|
30487
30907
|
test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
|
|
30488
30908
|
resolve: (str) => parseFloat(str.replace(/_/g, "")),
|
|
30489
30909
|
stringify(node) {
|
|
30490
|
-
const
|
|
30491
|
-
return isFinite(
|
|
30910
|
+
const num3 = Number(node.value);
|
|
30911
|
+
return isFinite(num3) ? num3.toExponential() : stringifyNumber.stringifyNumber(node);
|
|
30492
30912
|
}
|
|
30493
30913
|
};
|
|
30494
30914
|
var float = {
|
|
@@ -30678,23 +31098,23 @@ var require_timestamp = __commonJS((exports) => {
|
|
|
30678
31098
|
function parseSexagesimal(str, asBigInt) {
|
|
30679
31099
|
const sign = str[0];
|
|
30680
31100
|
const parts = sign === "-" || sign === "+" ? str.substring(1) : str;
|
|
30681
|
-
const
|
|
30682
|
-
const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 *
|
|
30683
|
-
return sign === "-" ?
|
|
31101
|
+
const num3 = (n) => asBigInt ? BigInt(n) : Number(n);
|
|
31102
|
+
const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num3(60) + num3(p), num3(0));
|
|
31103
|
+
return sign === "-" ? num3(-1) * res : res;
|
|
30684
31104
|
}
|
|
30685
31105
|
function stringifySexagesimal(node) {
|
|
30686
31106
|
let { value } = node;
|
|
30687
|
-
let
|
|
31107
|
+
let num3 = (n) => n;
|
|
30688
31108
|
if (typeof value === "bigint")
|
|
30689
|
-
|
|
31109
|
+
num3 = (n) => BigInt(n);
|
|
30690
31110
|
else if (isNaN(value) || !isFinite(value))
|
|
30691
31111
|
return stringifyNumber.stringifyNumber(node);
|
|
30692
31112
|
let sign = "";
|
|
30693
31113
|
if (value < 0) {
|
|
30694
31114
|
sign = "-";
|
|
30695
|
-
value *=
|
|
31115
|
+
value *= num3(-1);
|
|
30696
31116
|
}
|
|
30697
|
-
const _60 =
|
|
31117
|
+
const _60 = num3(60);
|
|
30698
31118
|
const parts = [value % _60];
|
|
30699
31119
|
if (value < 60) {
|
|
30700
31120
|
parts.unshift(0);
|
|
@@ -37535,6 +37955,63 @@ init_version();
|
|
|
37535
37955
|
init_map_command();
|
|
37536
37956
|
init_budget();
|
|
37537
37957
|
|
|
37958
|
+
// src/llm/provider-budget.ts
|
|
37959
|
+
var DEFAULT_TIMEOUT_MS = 5000;
|
|
37960
|
+
function num2(value) {
|
|
37961
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
37962
|
+
}
|
|
37963
|
+
async function getJson(url, apiKey, timeoutMs) {
|
|
37964
|
+
const response = await fetch(url, {
|
|
37965
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
37966
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
37967
|
+
});
|
|
37968
|
+
if (!response.ok) {
|
|
37969
|
+
throw new Error(`HTTP ${response.status}`);
|
|
37970
|
+
}
|
|
37971
|
+
return response.json();
|
|
37972
|
+
}
|
|
37973
|
+
async function fetchProviderBudget(provider, baseUrl, apiKey, options) {
|
|
37974
|
+
if (provider !== "openrouter") {
|
|
37975
|
+
options.log("debug", `budget: provider "${provider}" does not expose an API balance`);
|
|
37976
|
+
return { budget: null, reason: "unsupported" };
|
|
37977
|
+
}
|
|
37978
|
+
if (!apiKey) {
|
|
37979
|
+
options.log("debug", "budget: no api key configured");
|
|
37980
|
+
return { budget: null, reason: "no-key" };
|
|
37981
|
+
}
|
|
37982
|
+
const base = baseUrl.replace(/\/$/, "");
|
|
37983
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
37984
|
+
try {
|
|
37985
|
+
const keyBody = await getJson(`${base}/key`, apiKey, timeoutMs);
|
|
37986
|
+
const data = keyBody?.data ?? {};
|
|
37987
|
+
const budget = { provider, source: "openrouter" };
|
|
37988
|
+
budget.keyLabel = typeof data.label === "string" ? data.label : undefined;
|
|
37989
|
+
budget.keyUsageUsd = num2(data.usage);
|
|
37990
|
+
budget.keyLimitUsd = num2(data.limit);
|
|
37991
|
+
budget.keyRemainingUsd = num2(data.limit_remaining);
|
|
37992
|
+
budget.isFreeTier = typeof data.is_free_tier === "boolean" ? data.is_free_tier : undefined;
|
|
37993
|
+
try {
|
|
37994
|
+
const creditsBody = await getJson(`${base}/credits`, apiKey, timeoutMs);
|
|
37995
|
+
const c = creditsBody?.data ?? {};
|
|
37996
|
+
budget.totalCreditsUsd = num2(c.total_credits);
|
|
37997
|
+
budget.totalUsageUsd = num2(c.total_usage);
|
|
37998
|
+
if (budget.totalCreditsUsd !== undefined && budget.totalUsageUsd !== undefined) {
|
|
37999
|
+
budget.balanceUsd = budget.totalCreditsUsd - budget.totalUsageUsd;
|
|
38000
|
+
}
|
|
38001
|
+
} catch (creditsErr) {
|
|
38002
|
+
options.log("debug", `budget: /credits unavailable (${creditsErr instanceof Error ? creditsErr.message : String(creditsErr)})`);
|
|
38003
|
+
}
|
|
38004
|
+
return { budget, reason: "ok" };
|
|
38005
|
+
} catch (err) {
|
|
38006
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
38007
|
+
options.log("warn", `budget: request failed (${message})`);
|
|
38008
|
+
return { budget: null, reason: "error", error: message };
|
|
38009
|
+
}
|
|
38010
|
+
}
|
|
38011
|
+
|
|
38012
|
+
// src/cli/commands.ts
|
|
38013
|
+
init_prices();
|
|
38014
|
+
|
|
37538
38015
|
// src/modules/updater/changelog-reader.ts
|
|
37539
38016
|
import { readFileSync as readFileSync35, existsSync as existsSync53 } from "fs";
|
|
37540
38017
|
import { dirname as dirname20, join as join48 } from "path";
|
|
@@ -37823,6 +38300,53 @@ function buildContextCommand(program2) {
|
|
|
37823
38300
|
console.log(t("cli.context_set", { size: contextWindow }));
|
|
37824
38301
|
});
|
|
37825
38302
|
}
|
|
38303
|
+
function buildUsageCommand(program2) {
|
|
38304
|
+
program2.command("usage").description(t("cli.usage")).action(async () => {
|
|
38305
|
+
const { config, logger: logger4 } = await bootstrap();
|
|
38306
|
+
const { type: provider, baseUrl, apiKey } = config.provider;
|
|
38307
|
+
const result = await fetchProviderBudget(provider, baseUrl, apiKey, {
|
|
38308
|
+
log: (level, message) => level === "warn" ? logger4.warn(message) : logger4.debug(message)
|
|
38309
|
+
});
|
|
38310
|
+
if (result.reason === "unsupported") {
|
|
38311
|
+
console.log(t("cli.usage_unsupported", { provider }));
|
|
38312
|
+
return;
|
|
38313
|
+
}
|
|
38314
|
+
if (result.reason === "no-key") {
|
|
38315
|
+
console.log(t("cli.usage_no_key"));
|
|
38316
|
+
return;
|
|
38317
|
+
}
|
|
38318
|
+
if (result.reason === "error" || !result.budget) {
|
|
38319
|
+
console.log(t("cli.usage_error", { error: result.error ?? "" }));
|
|
38320
|
+
return;
|
|
38321
|
+
}
|
|
38322
|
+
const b = result.budget;
|
|
38323
|
+
let printed = false;
|
|
38324
|
+
if (b.keyUsageUsd !== undefined) {
|
|
38325
|
+
console.log(t("cli.usage_key_usage", { usage: formatCost(b.keyUsageUsd) }));
|
|
38326
|
+
printed = true;
|
|
38327
|
+
}
|
|
38328
|
+
if (b.keyLimitUsd !== undefined && b.keyRemainingUsd !== undefined) {
|
|
38329
|
+
console.log(t("cli.usage_key_limit", {
|
|
38330
|
+
limit: formatCost(b.keyLimitUsd),
|
|
38331
|
+
remaining: formatCost(b.keyRemainingUsd)
|
|
38332
|
+
}));
|
|
38333
|
+
printed = true;
|
|
38334
|
+
}
|
|
38335
|
+
if (b.balanceUsd !== undefined) {
|
|
38336
|
+
console.log(t("cli.usage_balance", { balance: formatCost(b.balanceUsd) }));
|
|
38337
|
+
printed = true;
|
|
38338
|
+
}
|
|
38339
|
+
if (b.totalCreditsUsd !== undefined && b.totalUsageUsd !== undefined) {
|
|
38340
|
+
console.log(t("cli.usage_account", {
|
|
38341
|
+
credits: formatCost(b.totalCreditsUsd),
|
|
38342
|
+
used: formatCost(b.totalUsageUsd)
|
|
38343
|
+
}));
|
|
38344
|
+
printed = true;
|
|
38345
|
+
}
|
|
38346
|
+
if (!printed)
|
|
38347
|
+
console.log(t("cli.usage_empty"));
|
|
38348
|
+
});
|
|
38349
|
+
}
|
|
37826
38350
|
function buildMapCommand(program2) {
|
|
37827
38351
|
program2.command("map").description(t("cli.map.description")).argument("[action]", t("cli.map.action"), "summary").argument("[query]", t("cli.map.query")).action(async (action, query) => {
|
|
37828
38352
|
const { agent } = await bootstrap();
|
|
@@ -37979,6 +38503,31 @@ function buildSessionCommands(program2) {
|
|
|
37979
38503
|
}
|
|
37980
38504
|
}
|
|
37981
38505
|
}
|
|
38506
|
+
const usageEvents = sessionManager.loadSessionLog(id).filter((e) => e.type === "llm_usage");
|
|
38507
|
+
if (usageEvents.length > 0) {
|
|
38508
|
+
let prompt = 0;
|
|
38509
|
+
let completion = 0;
|
|
38510
|
+
let cached = 0;
|
|
38511
|
+
for (const e of usageEvents) {
|
|
38512
|
+
prompt += e.promptTokens ?? 0;
|
|
38513
|
+
completion += e.completionTokens ?? 0;
|
|
38514
|
+
cached += e.cachedTokens ?? 0;
|
|
38515
|
+
}
|
|
38516
|
+
console.log("");
|
|
38517
|
+
console.log(pc2.cyan(t("cli.session_usage", {
|
|
38518
|
+
prompt,
|
|
38519
|
+
completion,
|
|
38520
|
+
total: prompt + completion
|
|
38521
|
+
})));
|
|
38522
|
+
if (cached > 0 && prompt > 0) {
|
|
38523
|
+
const hit = Math.round(cached / prompt * 100);
|
|
38524
|
+
console.log(pc2.dim(t("cli.session_cache", {
|
|
38525
|
+
hit,
|
|
38526
|
+
cached,
|
|
38527
|
+
uncached: Math.max(0, prompt - cached)
|
|
38528
|
+
})));
|
|
38529
|
+
}
|
|
38530
|
+
}
|
|
37982
38531
|
});
|
|
37983
38532
|
session2.command("delete").argument("<id>", "Session id").description(t("cli.delete_session")).action(async (id) => {
|
|
37984
38533
|
const { sessionManager } = await bootstrap();
|
|
@@ -38018,6 +38567,7 @@ function createProgram() {
|
|
|
38018
38567
|
buildConfigCommands(program2);
|
|
38019
38568
|
buildModelCommands(program2);
|
|
38020
38569
|
buildContextCommand(program2);
|
|
38570
|
+
buildUsageCommand(program2);
|
|
38021
38571
|
buildMapCommand(program2);
|
|
38022
38572
|
buildProviderCommands(program2);
|
|
38023
38573
|
buildSessionCommands(program2);
|
|
@@ -38025,11 +38575,15 @@ function createProgram() {
|
|
|
38025
38575
|
createPluginCommand(program2);
|
|
38026
38576
|
buildChangelogCommand(program2);
|
|
38027
38577
|
program2.argument("[prompt...]", "Prompt to execute").description("Run a single prompt").action((prompt) => {});
|
|
38028
|
-
|
|
38578
|
+
const attachOneShotExit = (cmd) => {
|
|
38029
38579
|
cmd.hook("postAction", () => {
|
|
38030
38580
|
process.exit(0);
|
|
38031
38581
|
});
|
|
38032
|
-
|
|
38582
|
+
for (const sub of cmd.commands)
|
|
38583
|
+
attachOneShotExit(sub);
|
|
38584
|
+
};
|
|
38585
|
+
for (const cmd of program2.commands)
|
|
38586
|
+
attachOneShotExit(cmd);
|
|
38033
38587
|
return program2;
|
|
38034
38588
|
}
|
|
38035
38589
|
|
|
@@ -39662,6 +40216,28 @@ function stepContextForTool(plan, tool, args) {
|
|
|
39662
40216
|
// src/cli/repl.ts
|
|
39663
40217
|
init_prices();
|
|
39664
40218
|
|
|
40219
|
+
// src/cli/cache-line.ts
|
|
40220
|
+
init_i18n();
|
|
40221
|
+
init_prices();
|
|
40222
|
+
function formatCacheLine(cache) {
|
|
40223
|
+
if (!cache)
|
|
40224
|
+
return;
|
|
40225
|
+
const total = cache.cachedTokens + cache.uncachedTokens;
|
|
40226
|
+
const hit = Math.round(cache.hitRate * 100);
|
|
40227
|
+
if (total > 0) {
|
|
40228
|
+
if (cache.saved !== undefined && cache.saved > 0) {
|
|
40229
|
+
return t("repl.cache", { hit, saved: formatCost(cache.saved) });
|
|
40230
|
+
}
|
|
40231
|
+
return t("repl.cache_nosave", { hit });
|
|
40232
|
+
}
|
|
40233
|
+
const broken = cache.prefixCause !== undefined && cache.prefixCause !== "none" && cache.prefixCause !== "unknown";
|
|
40234
|
+
if (broken && cache.prefixStable !== undefined && cache.prefixStable < 0.98) {
|
|
40235
|
+
const stable = Math.round(cache.prefixStable * 100);
|
|
40236
|
+
return t("repl.prefix", { stable, cause: t(`cache.cause.${cache.prefixCause}`) });
|
|
40237
|
+
}
|
|
40238
|
+
return;
|
|
40239
|
+
}
|
|
40240
|
+
|
|
39665
40241
|
// src/ui/output.ts
|
|
39666
40242
|
function writeWarning(text) {
|
|
39667
40243
|
process.stdout.write(formatWarning(text) + `
|
|
@@ -40168,6 +40744,10 @@ ${t("image.clipboard_empty")}`));
|
|
|
40168
40744
|
if (result.totalCost !== undefined && result.totalCost > 0) {
|
|
40169
40745
|
console.log(pc2.yellow(` ${t("repl.cost", { cost: formatCost(result.totalCost) })}`));
|
|
40170
40746
|
}
|
|
40747
|
+
const cacheLine = formatCacheLine(result.cache);
|
|
40748
|
+
if (cacheLine) {
|
|
40749
|
+
console.log(pc2.dim(` ${cacheLine}`));
|
|
40750
|
+
}
|
|
40171
40751
|
} else if (ui?.showCompaction && result.compactionCount !== undefined) {
|
|
40172
40752
|
if (result.compactionCount > this.lastCompactionShown) {
|
|
40173
40753
|
this.lastCompactionShown = result.compactionCount;
|
|
@@ -40352,6 +40932,10 @@ function printRunResult(result, flush) {
|
|
|
40352
40932
|
} else if (result.totalTokens !== undefined && result.totalTokens > 0) {
|
|
40353
40933
|
console.log(pc2.dim(`${t("repl.tokens", { tokens: result.totalTokens })}`));
|
|
40354
40934
|
}
|
|
40935
|
+
const cacheLine = formatCacheLine(result.cache);
|
|
40936
|
+
if (cacheLine) {
|
|
40937
|
+
console.log(pc2.dim(` ${cacheLine}`));
|
|
40938
|
+
}
|
|
40355
40939
|
if (!result.text) {
|
|
40356
40940
|
console.log(pc2.yellow(t("cli.no_output")));
|
|
40357
40941
|
}
|
|
@@ -40369,6 +40953,7 @@ init_colors();
|
|
|
40369
40953
|
import { existsSync as existsSync61 } from "fs";
|
|
40370
40954
|
import { join as join57, dirname as dirname25 } from "path";
|
|
40371
40955
|
import { homedir as homedir20 } from "os";
|
|
40956
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
40372
40957
|
|
|
40373
40958
|
// src/modules/updater/index.ts
|
|
40374
40959
|
init_checker();
|
|
@@ -40476,6 +41061,11 @@ ${t("cli.changelog_title", { version: result.latest })}
|
|
|
40476
41061
|
await this.runOnce();
|
|
40477
41062
|
}
|
|
40478
41063
|
}
|
|
41064
|
+
// src/modules/updater/dev-detect.ts
|
|
41065
|
+
function isDevEntryPath(path) {
|
|
41066
|
+
const clean = path.split(/[?#]/)[0];
|
|
41067
|
+
return clean.endsWith(".ts") || clean.endsWith(".tsx") || clean.endsWith(".mts") || clean.endsWith(".cts");
|
|
41068
|
+
}
|
|
40479
41069
|
// src/core/crash-handler.ts
|
|
40480
41070
|
init_environment();
|
|
40481
41071
|
init_data_sanitizer();
|
|
@@ -40564,6 +41154,8 @@ function closestCommand(input, known, maxDistance = 2) {
|
|
|
40564
41154
|
// src/cli/main.ts
|
|
40565
41155
|
init_utils();
|
|
40566
41156
|
function startAutoUpdate(config) {
|
|
41157
|
+
if (isDevEntryPath(fileURLToPath6(import.meta.url)))
|
|
41158
|
+
return;
|
|
40567
41159
|
try {
|
|
40568
41160
|
const module = new UpdaterModule(config.updater, readMmaVersion(), "micro-models-agent", {
|
|
40569
41161
|
info: (m) => process.stderr.write(pc2.dim(m) + `
|
|
@@ -40582,6 +41174,22 @@ function startAutoUpdate(config) {
|
|
|
40582
41174
|
async function main() {
|
|
40583
41175
|
installCrashHandlers();
|
|
40584
41176
|
const program2 = createProgram();
|
|
41177
|
+
const valueOpts = new Set(["-d", "--dir", "--reasoning"]);
|
|
41178
|
+
const argv = process.argv.slice(2);
|
|
41179
|
+
let firstPositional;
|
|
41180
|
+
for (let i = 0;i < argv.length; i++) {
|
|
41181
|
+
const a = argv[i];
|
|
41182
|
+
if (a.startsWith("-")) {
|
|
41183
|
+
if (valueOpts.has(a))
|
|
41184
|
+
i++;
|
|
41185
|
+
continue;
|
|
41186
|
+
}
|
|
41187
|
+
firstPositional = a;
|
|
41188
|
+
break;
|
|
41189
|
+
}
|
|
41190
|
+
if (firstPositional && program2.commands.some((c) => c.name() === firstPositional)) {
|
|
41191
|
+
setOneShotMode(true);
|
|
41192
|
+
}
|
|
40585
41193
|
program2.parse(process.argv);
|
|
40586
41194
|
const cmdNames = new Set(program2.commands.map((c) => c.name()));
|
|
40587
41195
|
const opts = program2.opts();
|
|
@@ -40633,7 +41241,8 @@ async function main() {
|
|
|
40633
41241
|
completionTokens: result2.completionTokens ?? null,
|
|
40634
41242
|
totalTokens: result2.totalTokens ?? null,
|
|
40635
41243
|
totalCost: result2.totalCost ?? null,
|
|
40636
|
-
costBreakdown: result2.costBreakdown ?? []
|
|
41244
|
+
costBreakdown: result2.costBreakdown ?? [],
|
|
41245
|
+
cache: result2.cache ?? null
|
|
40637
41246
|
}, null, 2));
|
|
40638
41247
|
process.stdout.write(`
|
|
40639
41248
|
`);
|