micro-models-agent 2.11.0 → 2.12.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 +10 -0
- package/dist/assets/js/tabs.js +22 -3
- package/dist/cli/cache-line.js +1 -0
- package/dist/cli/command-suggest.js +5 -4
- package/dist/cli/commands.js +231 -122
- package/dist/cli/completer.js +132 -31
- package/dist/cli/index.js +1 -0
- package/dist/cli/json-payload.js +4 -4
- package/dist/cli/main.js +166 -61
- package/dist/cli/onboarding-commands.js +126 -0
- package/dist/cli/plugin-commands.js +2 -1
- package/dist/cli/relaunch.js +16 -13
- package/dist/cli/repl-commands-lsp.js +75 -0
- package/dist/cli/repl-commands-skills.js +105 -0
- package/dist/cli/repl-commands.js +589 -266
- package/dist/cli/repl.js +436 -177
- package/dist/cli/run-result.js +5 -6
- package/dist/cli/security-commands.js +37 -28
- package/dist/cli/setup-order.js +4 -55
- package/dist/cli/setup-prompt.js +3 -2
- package/dist/cli/setup.js +27 -107
- package/dist/cli/web-command.js +98 -0
- package/dist/config/budget.js +5 -5
- package/dist/config/config.js +103 -96
- package/dist/config/defaults.js +38 -8
- package/dist/config/domains.js +24 -27
- package/dist/config/env.js +46 -0
- package/dist/config/experts.js +2 -0
- package/dist/config/index.js +1 -0
- package/dist/config/paths.js +56 -0
- package/dist/config/redact.js +44 -0
- package/dist/config/registry-extra.js +334 -0
- package/dist/config/registry.js +584 -0
- package/dist/config/security.js +35 -36
- package/dist/config/timeouts.js +74 -0
- package/dist/config/utils.js +16 -15
- package/dist/core/agent/artifact-progress.js +59 -0
- package/dist/core/agent/artifact-resolve.js +79 -0
- package/dist/core/agent/audit-gate.js +7 -3
- package/dist/core/agent/compaction.js +2 -2
- package/dist/core/agent/constants.js +33 -4
- package/dist/core/agent/context-log.js +454 -0
- package/dist/core/agent/context-renderer.js +5 -0
- package/dist/core/agent/critic-gate.js +132 -0
- package/dist/core/agent/hallucination-gate.js +148 -38
- package/dist/core/agent/loop-state.js +15 -0
- package/dist/core/agent/prefix-monitor.js +1 -1
- package/dist/core/agent/reasoning-resolver.js +10 -1
- package/dist/core/agent/token-tracker.js +7 -4
- package/dist/core/agent/tool-batch.js +93 -18
- package/dist/core/agent/tool-images.js +18 -0
- package/dist/core/agent/tool-output.js +65 -11
- package/dist/core/agent/tool-pairing.js +60 -0
- package/dist/core/agent-moe.js +25 -24
- package/dist/core/agent.js +429 -108
- package/dist/core/bootstrap/agent-phase.js +66 -0
- package/dist/core/bootstrap/config-phase.js +86 -0
- package/dist/core/bootstrap/modules-phase.js +269 -0
- package/dist/core/bootstrap/provider-phase.js +183 -0
- package/dist/core/bootstrap/session-phase.js +204 -0
- package/dist/core/bootstrap/state.js +94 -0
- package/dist/core/bootstrap/workspace-phase.js +115 -0
- package/dist/core/bootstrap.js +92 -660
- package/dist/core/crash-handler.js +17 -7
- package/dist/core/environment.js +37 -12
- package/dist/core/host-plan.js +43 -0
- package/dist/core/host.js +23 -0
- package/dist/core/index.js +1 -0
- package/dist/core/prompt-builder.js +17 -1
- package/dist/core/prompt-overflow.js +42 -43
- package/dist/core/session-logger.js +122 -30
- package/dist/core/system-prompt.js +117 -0
- package/dist/core/version.js +6 -4
- package/dist/core/web-host.js +34 -0
- package/dist/core/workspace.js +19 -15
- package/dist/i18n/index.js +37 -3
- package/dist/index.js +7 -3
- package/dist/llm/image-utils.js +55 -64
- package/dist/llm/llm-errors.js +9 -0
- package/dist/llm/model-loader.js +10 -32
- package/dist/llm/models-dev.js +121 -0
- package/dist/llm/openai-compat.js +146 -73
- package/dist/llm/orchestrator.js +33 -11
- package/dist/llm/provider-budget.js +2 -2
- package/dist/llm/provider-context.js +233 -0
- package/dist/llm/provider.js +1 -1
- package/dist/llm/response.js +5 -0
- package/dist/llm/token-counter.js +27 -11
- package/dist/logger/app-logger.js +48 -22
- package/dist/logger/file-log.js +28 -19
- package/dist/logger/index.js +1 -0
- package/dist/main.js +273 -47
- package/dist/migration/backup.js +14 -3
- package/dist/migration/detect.js +12 -3
- package/dist/migration/index.js +1 -0
- package/dist/modules/artifacts/store.js +9 -8
- package/dist/modules/browser/actions.js +6 -0
- package/dist/modules/browser/bridge-client.js +14 -12
- package/dist/modules/browser/bridge-path.js +4 -4
- package/dist/modules/browser/console-buffer.js +37 -0
- package/dist/modules/browser/cookie-store.js +5 -0
- package/dist/modules/browser/driver-types.js +1 -0
- package/dist/modules/browser/driver.js +19 -11
- package/dist/modules/browser/index.js +3 -1
- package/dist/modules/browser/module.js +2 -1
- package/dist/modules/browser/session.js +10 -30
- package/dist/modules/browser/snapshot.js +19 -13
- package/dist/modules/browser/types.js +1 -0
- package/dist/modules/certification/cli.js +28 -20
- package/dist/modules/certification/fact-checker.js +9 -1
- package/dist/modules/certification/loader.js +9 -2
- package/dist/modules/certification/manifest.js +83 -21
- package/dist/modules/certification/runner.js +23 -13
- package/dist/modules/certification/scenarios.js +20 -20
- package/dist/modules/certification/syntax-scenarios.js +1 -2
- package/dist/modules/context/chunk-query.js +11 -9
- package/dist/modules/context/fact-extractor.js +37 -39
- package/dist/modules/context/index.js +1 -0
- package/dist/modules/context/manager.js +106 -80
- package/dist/modules/critic/client.js +176 -0
- package/dist/modules/critic/evidence.js +81 -0
- package/dist/modules/critic/provider.js +45 -0
- package/dist/modules/critic/tools.js +78 -0
- package/dist/modules/critic/types.js +1 -0
- package/dist/modules/execution/audit-runners.js +28 -34
- package/dist/modules/execution/auditor.js +53 -49
- package/dist/modules/execution/execution-plugin.js +142 -102
- package/dist/modules/execution/index.js +1 -1
- package/dist/modules/execution/input-from.js +37 -13
- package/dist/modules/execution/module.js +368 -191
- package/dist/modules/execution/moe-executor.js +53 -26
- package/dist/modules/execution/plan-actions.js +320 -202
- package/dist/modules/execution/plan-checks.js +35 -0
- package/dist/modules/execution/plan-coverage.js +36 -33
- package/dist/modules/execution/plan-steps.js +11 -3
- package/dist/modules/execution/plan-store.js +83 -17
- package/dist/modules/execution/plan-tool.js +89 -35
- package/dist/modules/execution/plan-validator.js +30 -10
- package/dist/modules/execution/planner.js +22 -13
- package/dist/modules/execution/stuck-detector.js +196 -93
- package/dist/modules/execution/tracker.js +22 -8
- package/dist/modules/execution/verifier.js +69 -48
- package/dist/modules/execution/windows-commands.js +12 -12
- package/dist/modules/hallucination/artifact-claim.js +93 -0
- package/dist/modules/hallucination/confidence.js +13 -11
- package/dist/modules/hallucination/consistency.js +10 -2
- package/dist/modules/hallucination/detector.js +10 -5
- package/dist/modules/hallucination/factual.js +43 -26
- package/dist/modules/hallucination/index.js +1 -0
- package/dist/modules/hallucination/js-identifiers.js +44 -45
- package/dist/modules/hallucination/llm-judge.js +17 -12
- package/dist/modules/hallucination/success-claim.js +59 -0
- package/dist/modules/indexer/cache.js +52 -4
- package/dist/modules/indexer/index.js +1 -0
- package/dist/modules/indexer/map-command.js +2 -4
- package/dist/modules/indexer/map-select.js +16 -16
- package/dist/modules/indexer/module.js +47 -12
- package/dist/modules/indexer/project-profile.js +8 -7
- package/dist/modules/indexer/symbols.js +15 -15
- package/dist/modules/indexer/walker.js +159 -29
- package/dist/modules/lsp/check-tool.js +7 -5
- package/dist/modules/lsp/client.js +39 -39
- package/dist/modules/lsp/command.js +17 -24
- package/dist/modules/lsp/config.js +12 -11
- package/dist/modules/lsp/index.js +1 -0
- package/dist/modules/lsp/module.js +48 -46
- package/dist/modules/lsp/probe.js +13 -14
- package/dist/modules/lsp/project-root.js +14 -17
- package/dist/modules/lsp/startup-check.js +18 -16
- package/dist/modules/mcp/client.js +59 -62
- package/dist/modules/mcp/index.js +1 -0
- package/dist/modules/mcp/module.js +66 -37
- package/dist/modules/mcp/registry.js +5 -0
- package/dist/modules/memory/index.js +1 -0
- package/dist/modules/memory/module.js +12 -8
- package/dist/modules/memory/search.js +4 -1
- package/dist/modules/memory/store.js +40 -2
- package/dist/modules/onboarding/init.js +47 -0
- package/dist/modules/onboarding/meet.js +30 -0
- package/dist/modules/onboarding/mode.js +30 -0
- package/dist/modules/onboarding/prompts.js +43 -0
- package/dist/modules/pipelines/engine.js +10 -0
- package/dist/modules/pipelines/index.js +1 -0
- package/dist/modules/pipelines/parser.js +4 -1
- package/dist/modules/pipelines/template.js +4 -0
- package/dist/modules/plugins/builtin/lint-on-write.js +80 -67
- package/dist/modules/plugins/builtin/notify.js +2 -0
- package/dist/modules/plugins/index.js +1 -0
- package/dist/modules/plugins/loader.js +18 -3
- package/dist/modules/plugins/manager.js +37 -17
- package/dist/modules/pricing/index.js +10 -11
- package/dist/modules/pricing/prices.js +12 -12
- package/dist/modules/processes/index.js +1 -0
- package/dist/modules/processes/kill-tree.js +27 -31
- package/dist/modules/processes/registry.js +44 -25
- package/dist/modules/processes/runner.js +4 -4
- package/dist/modules/providers/capabilities.js +28 -0
- package/dist/modules/providers/create.js +3 -4
- package/dist/modules/providers/factory.js +7 -7
- package/dist/modules/providers/fallback.js +12 -12
- package/dist/modules/providers/health.js +4 -4
- package/dist/modules/providers/manager.js +50 -19
- package/dist/modules/providers/naming.js +15 -0
- package/dist/modules/providers/preflight.js +71 -0
- package/dist/modules/providers/presets.js +39 -8
- package/dist/modules/providers/registry.js +7 -2
- package/dist/modules/reasoning/policy.js +8 -6
- package/dist/modules/reasoning/probe.js +30 -25
- package/dist/modules/security/audit-log.js +19 -36
- package/dist/modules/security/audit-notifier.js +35 -75
- package/dist/modules/security/command-validator.js +99 -51
- package/dist/modules/security/content-scanner.js +8 -8
- package/dist/modules/security/data-sanitizer.js +9 -16
- package/dist/modules/security/encryption.js +32 -52
- package/dist/modules/security/index.js +2 -1
- package/dist/modules/security/network-validator.js +120 -43
- package/dist/modules/security/path-validator.js +61 -46
- package/dist/modules/security/protected-paths.js +73 -0
- package/dist/modules/security/rate-limiter.js +17 -49
- package/dist/modules/security/security-policies.js +25 -57
- package/dist/modules/security/session-encryption.js +32 -71
- package/dist/modules/security/session-isolation.js +15 -28
- package/dist/modules/session/auto-name.js +63 -0
- package/dist/modules/session/export.js +98 -0
- package/dist/modules/session/index.js +1 -0
- package/dist/modules/session/manager.js +79 -28
- package/dist/modules/session/module.js +4 -3
- package/dist/modules/session/store.js +57 -20
- package/dist/modules/setup/answers.js +35 -0
- package/dist/modules/setup/apply.js +79 -0
- package/dist/modules/setup/discovery.js +72 -0
- package/dist/modules/skills/index.js +1 -0
- package/dist/modules/skills/loader.js +9 -1
- package/dist/modules/skills/module.js +11 -0
- package/dist/modules/updater/changelog-reader.js +15 -16
- package/dist/modules/updater/checker.js +9 -4
- package/dist/modules/updater/dev-detect.js +7 -6
- package/dist/modules/updater/index.js +1 -0
- package/dist/modules/updater/module.js +17 -15
- package/dist/modules/user-profile/compressor.js +2 -0
- package/dist/modules/user-profile/index.js +1 -0
- package/dist/modules/user-profile/profile.js +10 -1
- package/dist/modules/webui/answer-api.js +29 -0
- package/dist/modules/webui/assets.js +50 -0
- package/dist/modules/webui/body.js +21 -0
- package/dist/modules/webui/commands-settings.js +209 -0
- package/dist/modules/webui/commands-shared.js +60 -0
- package/dist/modules/webui/commands.js +174 -0
- package/dist/modules/webui/config-api.js +134 -0
- package/dist/modules/webui/file-api.js +202 -0
- package/dist/modules/webui/forward.js +159 -0
- package/dist/modules/webui/history-api.js +112 -0
- package/dist/modules/webui/host-state.js +60 -0
- package/dist/modules/webui/i18n-api.js +9 -0
- package/dist/modules/webui/limits.js +6 -0
- package/dist/modules/webui/log-forward.js +20 -0
- package/dist/modules/webui/memory-commands.js +64 -0
- package/dist/modules/webui/model-cache.js +18 -0
- package/dist/modules/webui/module.js +148 -0
- package/dist/modules/webui/persist.js +24 -0
- package/dist/modules/webui/prompt-io.js +97 -0
- package/dist/modules/webui/providers-api.js +337 -0
- package/dist/modules/webui/providers-view.js +56 -0
- package/dist/modules/webui/reasoning-view.js +15 -0
- package/dist/modules/webui/run-agent.js +81 -0
- package/dist/modules/webui/server.js +284 -0
- package/dist/modules/webui/sessions-api.js +178 -0
- package/dist/modules/webui/settings-api.js +561 -0
- package/dist/modules/webui/setup-api.js +201 -0
- package/dist/modules/webui/state.js +74 -0
- package/dist/modules/webui/util.js +261 -0
- package/dist/output/bus.js +7 -2
- package/dist/output/channel.js +80 -28
- package/dist/output/format.js +2 -1
- package/dist/output/index.js +1 -0
- package/dist/output/json-sink.js +5 -3
- package/dist/output/machine.js +4 -3
- package/dist/output/session-sink.js +4 -4
- package/dist/tools/approve.js +4 -0
- package/dist/tools/attach-image.js +5 -4
- package/dist/tools/auto-fixer.js +26 -44
- package/dist/tools/auto-tags.js +83 -0
- package/dist/tools/bash.js +193 -116
- package/dist/tools/browser.js +76 -31
- package/dist/tools/chunk-query.js +14 -6
- package/dist/tools/create-dir.js +9 -5
- package/dist/tools/delete-file.js +9 -5
- package/dist/tools/download-file.js +32 -7
- package/dist/tools/edit-file.js +52 -14
- package/dist/tools/enable-tools.js +6 -6
- package/dist/tools/executor.js +132 -27
- package/dist/tools/file-info.js +3 -1
- package/dist/tools/filter-tools.js +3 -3
- package/dist/tools/glob-tool.js +4 -1
- package/dist/tools/grep-tool.js +13 -10
- package/dist/tools/hidden-tools-block.js +6 -6
- package/dist/tools/index.js +16 -8
- package/dist/tools/list-dir.js +4 -2
- package/dist/tools/load-skill.js +7 -0
- package/dist/tools/mcp-call.js +15 -4
- package/dist/tools/meet-done.js +14 -0
- package/dist/tools/move-file.js +14 -7
- package/dist/tools/path-utils.js +29 -29
- package/dist/tools/pipeline-run.js +29 -7
- package/dist/tools/preview.js +1 -1
- package/dist/tools/process-ids.js +31 -0
- package/dist/tools/process-kill.js +9 -16
- package/dist/tools/process-list.js +1 -0
- package/dist/tools/process-log.js +11 -16
- package/dist/tools/process-wait.js +63 -0
- package/dist/tools/prompt-io.js +4 -3
- package/dist/tools/question.js +172 -25
- package/dist/tools/read-file.js +55 -34
- package/dist/tools/recall.js +14 -8
- package/dist/tools/registry.js +6 -5
- package/dist/tools/remember.js +8 -4
- package/dist/tools/scope-request.js +11 -6
- package/dist/tools/search-history.js +5 -2
- package/dist/tools/session-info.js +2 -0
- package/dist/tools/set-thinking.js +8 -4
- package/dist/tools/subagent.js +59 -39
- package/dist/tools/syntax-validator.js +292 -90
- package/dist/tools/user-input.js +22 -18
- package/dist/tools/web-browse.js +9 -3
- package/dist/tools/web-fetch.js +12 -23
- package/dist/tools/web-search.js +7 -5
- package/dist/tools/write-file.js +45 -15
- package/dist/ui/action-log.js +13 -0
- package/dist/ui/box.js +4 -3
- package/dist/ui/colors.js +2 -0
- package/dist/ui/diff.js +6 -5
- package/dist/ui/index.js +1 -0
- package/dist/ui/line-editor.js +230 -122
- package/dist/ui/line-math.js +10 -2
- package/dist/ui/md-formatter.js +57 -37
- package/dist/ui/output.js +8 -3
- package/dist/ui/plan-view.js +21 -10
- package/dist/ui/renderer.js +393 -67
- package/dist/ui/spinner.js +16 -5
- package/dist/ui/table.js +15 -17
- package/dist/ui/theme.js +143 -0
- package/dist/utils/child-run.js +20 -0
- package/dist/utils/error.js +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/retry.js +2 -2
- package/dist/utils/truncate.js +1 -1
- package/package.json +1 -1
package/dist/llm/image-utils.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Картинки: MIME, буфер обмена, загрузка файла/URL в data URL. */
|
|
1
2
|
import { readFileSync } from "fs";
|
|
2
3
|
import { extname } from "path";
|
|
3
4
|
const MIME_MAP = {
|
|
@@ -9,31 +10,54 @@ const MIME_MAP = {
|
|
|
9
10
|
".bmp": "image/bmp",
|
|
10
11
|
".svg": "image/svg+xml",
|
|
11
12
|
};
|
|
12
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Определяет MIME-тип по расширению файла.
|
|
15
|
+
* @param filePath путь к файлу; @returns MIME-тип (дефолт image/png).
|
|
16
|
+
*/
|
|
13
17
|
export function detectMime(filePath) {
|
|
14
18
|
const ext = extname(filePath).toLowerCase();
|
|
15
19
|
return MIME_MAP[ext] ?? "image/png";
|
|
16
20
|
}
|
|
21
|
+
/** Конструктор Bun.Image под Bun, иначе undefined. */
|
|
22
|
+
function getBunImage() {
|
|
23
|
+
return globalThis.Bun?.Image;
|
|
24
|
+
}
|
|
25
|
+
/** Ужимает буфер в JPEG data URL через Bun.Image; null, если недоступно/упало. */
|
|
26
|
+
async function resizeToJpegDataUrl(buf) {
|
|
27
|
+
const Image = getBunImage();
|
|
28
|
+
if (!Image)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
const img = new Image(buf);
|
|
32
|
+
const { width } = await img.metadata();
|
|
33
|
+
const targetWidth = Math.min(800, width || 800);
|
|
34
|
+
return await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
17
40
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
41
|
+
* Читает картинку из буфера обмена через Bun.Image (macOS/Windows).
|
|
42
|
+
* На Linux — платформенные команды. Null, если картинки нет.
|
|
43
|
+
* @returns буфер PNG/JPEG либо null.
|
|
21
44
|
*/
|
|
22
45
|
export async function readClipboardImage() {
|
|
23
|
-
// Bun.Image.fromClipboard()
|
|
24
|
-
|
|
46
|
+
// Bun.Image.fromClipboard() работает на macOS и Windows
|
|
47
|
+
const Image = getBunImage();
|
|
48
|
+
if (Image) {
|
|
25
49
|
try {
|
|
26
|
-
const img =
|
|
50
|
+
const img = Image.fromClipboard();
|
|
27
51
|
if (img) {
|
|
28
52
|
const buf = await img.resize(800, 800, { fit: "inside" }).jpeg({ quality: 60 }).buffer();
|
|
29
53
|
return Buffer.from(buf);
|
|
30
54
|
}
|
|
31
55
|
}
|
|
32
56
|
catch {
|
|
33
|
-
// Bun.Image.fromClipboard()
|
|
57
|
+
// Bun.Image.fromClipboard() упал — идём в платформенный фолбэк
|
|
34
58
|
}
|
|
35
59
|
}
|
|
36
|
-
// Linux
|
|
60
|
+
// Linux-фолбэк: xclip/wl-paste → временный файл → чтение
|
|
37
61
|
return readClipboardFallback();
|
|
38
62
|
}
|
|
39
63
|
async function readClipboardFallback() {
|
|
@@ -44,7 +68,7 @@ async function readClipboardFallback() {
|
|
|
44
68
|
if (platform() !== "linux")
|
|
45
69
|
return null; // macOS/Windows use Bun.Image
|
|
46
70
|
const tmpPath = join(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
47
|
-
//
|
|
71
|
+
// Сначала Wayland (wl-paste), затем X11 (xclip)
|
|
48
72
|
const commands = [
|
|
49
73
|
`wl-paste --type image/png > "${tmpPath}" 2>/dev/null`,
|
|
50
74
|
`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`,
|
|
@@ -58,45 +82,36 @@ async function readClipboardFallback() {
|
|
|
58
82
|
return buf;
|
|
59
83
|
}
|
|
60
84
|
catch {
|
|
61
|
-
//
|
|
85
|
+
// пробуем следующую команду
|
|
62
86
|
}
|
|
63
87
|
}
|
|
64
88
|
try {
|
|
65
89
|
unlinkSync(tmpPath);
|
|
66
90
|
}
|
|
67
|
-
catch {
|
|
91
|
+
catch {
|
|
92
|
+
// Best-effort чистка времянки — зависший файл не должен маскировать null.
|
|
93
|
+
}
|
|
68
94
|
return null;
|
|
69
95
|
}
|
|
70
96
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
97
|
+
* Грузит картинку из файла, ужимает через Bun.Image, отдаёт JPEG data URL.
|
|
98
|
+
* Цель: ~800px по ширине, JPEG 60 — обычно 5–15KB (~2–4K токенов).
|
|
73
99
|
*/
|
|
74
100
|
export async function loadFileAsDataUrl(filePath) {
|
|
75
101
|
const buf = readFileSync(filePath);
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const targetWidth = Math.min(800, width || 800);
|
|
82
|
-
const dataUrl = await img
|
|
83
|
-
.resize(targetWidth, 800, { fit: "inside" })
|
|
84
|
-
.jpeg({ quality: 60 })
|
|
85
|
-
.dataurl();
|
|
86
|
-
return { dataUrl };
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
// Bun.Image failed — fall through to raw base64
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// Fallback: raw base64 (no resize)
|
|
102
|
+
// Bun.Image, если есть — ресайз + конвертация в JPEG
|
|
103
|
+
const resized = await resizeToJpegDataUrl(buf);
|
|
104
|
+
if (resized)
|
|
105
|
+
return { dataUrl: resized };
|
|
106
|
+
// Фолбэк: сырой base64 (без ресайза)
|
|
93
107
|
const b64 = buf.toString("base64");
|
|
94
108
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
95
109
|
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "webp" ? "image/webp" : "image/png";
|
|
96
110
|
return { dataUrl: `data:${mime};base64,${b64}` };
|
|
97
111
|
}
|
|
98
112
|
/**
|
|
99
|
-
*
|
|
113
|
+
* Грузит картинку по URL, ужимает, отдаёт JPEG data URL.
|
|
114
|
+
* @param url URL картинки; @returns data URL.
|
|
100
115
|
*/
|
|
101
116
|
export async function loadUrlAsDataUrl(url) {
|
|
102
117
|
const resp = await fetch(url);
|
|
@@ -104,44 +119,20 @@ export async function loadUrlAsDataUrl(url) {
|
|
|
104
119
|
throw new Error(`Failed to fetch image: ${resp.status} ${resp.statusText}`);
|
|
105
120
|
}
|
|
106
121
|
const buf = Buffer.from(await resp.arrayBuffer());
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const { width } = await img.metadata();
|
|
111
|
-
const targetWidth = Math.min(800, width || 800);
|
|
112
|
-
const dataUrl = await img
|
|
113
|
-
.resize(targetWidth, 800, { fit: "inside" })
|
|
114
|
-
.jpeg({ quality: 60 })
|
|
115
|
-
.dataurl();
|
|
116
|
-
return { dataUrl };
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
// fall through
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
+
const resized = await resizeToJpegDataUrl(buf);
|
|
123
|
+
if (resized)
|
|
124
|
+
return { dataUrl: resized };
|
|
122
125
|
const b64 = buf.toString("base64");
|
|
123
126
|
return { dataUrl: `data:image/png;base64,${b64}` };
|
|
124
127
|
}
|
|
125
128
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
129
|
+
* Превращает буфер обмена (уже ужатый readClipboardImage) в data URL.
|
|
130
|
+
* Нужен обработчику Ctrl+V.
|
|
128
131
|
*/
|
|
129
132
|
export async function bufferToDataUrl(buf) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const { width } = await img.metadata();
|
|
134
|
-
const targetWidth = Math.min(800, width || 800);
|
|
135
|
-
const dataUrl = await img
|
|
136
|
-
.resize(targetWidth, 800, { fit: "inside" })
|
|
137
|
-
.jpeg({ quality: 60 })
|
|
138
|
-
.dataurl();
|
|
139
|
-
return { dataUrl };
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
// fall through
|
|
143
|
-
}
|
|
144
|
-
}
|
|
133
|
+
const resized = await resizeToJpegDataUrl(buf);
|
|
134
|
+
if (resized)
|
|
135
|
+
return { dataUrl: resized };
|
|
145
136
|
const b64 = buf.toString("base64");
|
|
146
137
|
return { dataUrl: `data:image/png;base64,${b64}` };
|
|
147
138
|
}
|
package/dist/llm/llm-errors.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Типизированные ошибки LLM-транспорта (terminal/recoverable/status). */
|
|
1
2
|
/**
|
|
2
3
|
* Типизированные ошибки LLM-транспорта.
|
|
3
4
|
*
|
|
@@ -30,10 +31,18 @@ export class LlmError extends Error {
|
|
|
30
31
|
this.recoverable = options.recoverable ?? false;
|
|
31
32
|
this.llmStatus = options.llmStatus;
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Помечает ошибку терминальной (стрим не ретраится).
|
|
36
|
+
* @returns this для чейнинга.
|
|
37
|
+
*/
|
|
33
38
|
markTerminal() {
|
|
34
39
|
this.terminal = true;
|
|
35
40
|
return this;
|
|
36
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Помечает ошибку восстановимой (причину вернуть модели через цикл).
|
|
44
|
+
* @returns this для чейнинга.
|
|
45
|
+
*/
|
|
37
46
|
markRecoverable() {
|
|
38
47
|
this.recoverable = true;
|
|
39
48
|
return this;
|
package/dist/llm/model-loader.js
CHANGED
|
@@ -1,33 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* null when the endpoint is unavailable (not LM Studio), the model is not
|
|
6
|
-
* found/loaded, or the request fails — the caller must degrade silently.
|
|
7
|
-
*/
|
|
8
|
-
export async function getLoadedContextLength(baseUrl, model, timeoutMs = 3000) {
|
|
9
|
-
const base = baseUrl.replace(/\/$/, "").replace(/\/v1\/?$/, "");
|
|
10
|
-
try {
|
|
11
|
-
const response = await fetch(`${base}/api/v1/models`, {
|
|
12
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
13
|
-
});
|
|
14
|
-
if (!response.ok)
|
|
15
|
-
return null;
|
|
16
|
-
const data = (await response.json());
|
|
17
|
-
const models = data.models || [];
|
|
18
|
-
const found = models.find((m) => m.key === model || m.name === model || model.includes(m.key));
|
|
19
|
-
if (!found)
|
|
20
|
-
return null;
|
|
21
|
-
const loadedInstance = (found.loaded_instances ?? [])[0];
|
|
22
|
-
const actual = loadedInstance?.config?.context_length ?? found.max_context_length;
|
|
23
|
-
if (typeof actual !== "number" || actual <= 0)
|
|
24
|
-
return null;
|
|
25
|
-
return { model: found.key ?? found.name ?? model, actual };
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
// Хелперы живой context-probe — в ./provider-context.ts и ./models-dev.ts;
|
|
2
|
+
// реэкспорт отсюда, чтобы существующие импорты не ломать.
|
|
3
|
+
export { probeModel, getLoadedContextLength, probeProviderContext, } from "./provider-context";
|
|
4
|
+
/** Загрузчик модели LM Studio: ensure + load через native API. */
|
|
31
5
|
export class ModelLoader {
|
|
32
6
|
baseUrl;
|
|
33
7
|
logger;
|
|
@@ -36,6 +10,10 @@ export class ModelLoader {
|
|
|
36
10
|
this.baseUrl = url.replace(/\/v1\/?$/, "");
|
|
37
11
|
this.logger = logger;
|
|
38
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Гарантирует загруженную модель с нужным контекстом (иначе грузит).
|
|
15
|
+
* @param config конфиг загрузки; @returns итог (уже была/загружена/ошибка).
|
|
16
|
+
*/
|
|
39
17
|
async ensureModelLoaded(config) {
|
|
40
18
|
if (config.autoLoad === false) {
|
|
41
19
|
return { success: true, alreadyLoaded: true };
|
|
@@ -61,11 +39,11 @@ export class ModelLoader {
|
|
|
61
39
|
if (!response.ok)
|
|
62
40
|
return false;
|
|
63
41
|
const data = (await response.json());
|
|
64
|
-
const models = data.models
|
|
42
|
+
const models = data.models ?? [];
|
|
65
43
|
const found = models.find((m) => m.key === model || m.name === model);
|
|
66
44
|
if (!found)
|
|
67
45
|
return false;
|
|
68
|
-
const loadedInstances = found.loaded_instances
|
|
46
|
+
const loadedInstances = found.loaded_instances ?? [];
|
|
69
47
|
return loadedInstances.some((inst) => inst.config?.context_length === contextLength);
|
|
70
48
|
}
|
|
71
49
|
catch {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* models.dev-фолбэк для хостед-шлюзов (OpenCode Zen/Go), чей собственный
|
|
3
|
+
* `/models` отдаёт голые id без метаданных контекста (проверено вживую:
|
|
4
|
+
* только `{id, object, created, owned_by}`).
|
|
5
|
+
*
|
|
6
|
+
* models.dev — открытая база моделей (MIT, sst/models.dev), её же использует
|
|
7
|
+
* сам opencode. Каталог `api.json`: `Record<providerId, { models:
|
|
8
|
+
* Record<modelId, { limit: { context } }> }>`, провайдер `opencode` держит
|
|
9
|
+
* модели под теми же bare id, что отдаёт Zen (`deepseek-v4.1-flash` →
|
|
10
|
+
* `limit.context`).
|
|
11
|
+
*
|
|
12
|
+
* На диске только slim-проекция (`opencode` → id → контекст):
|
|
13
|
+
* `~/.mma/models-dev-cache.json` (override `MMA_MODELS_DEV_CACHE`), TTL 24h
|
|
14
|
+
* как у reasoning-пробника. Любой сбой — null, вызывающий хранит настроенный
|
|
15
|
+
* `contextWindow` (fail-open).
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
18
|
+
import { join, dirname } from "path";
|
|
19
|
+
import { globalMmaDir } from "../config/paths";
|
|
20
|
+
import { readEnv } from "../config/env";
|
|
21
|
+
import { MODELS_DEV_CATALOG_TTL_MS, MODELS_DEV_FETCH_TIMEOUT_MS, } from "../config/timeouts";
|
|
22
|
+
const MODELS_DEV_URL = "https://models.dev/api.json";
|
|
23
|
+
function cachePath() {
|
|
24
|
+
return readEnv("MODELS_DEV_CACHE") ?? join(globalMmaDir(), "models-dev-cache.json");
|
|
25
|
+
}
|
|
26
|
+
/** In-memory L1: свежая проекция на время жизни процесса. */
|
|
27
|
+
let memCache = null;
|
|
28
|
+
function readDiskCache() {
|
|
29
|
+
try {
|
|
30
|
+
const path = cachePath();
|
|
31
|
+
if (!existsSync(path))
|
|
32
|
+
return null;
|
|
33
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
34
|
+
if (typeof parsed.ts !== "string" || !parsed.models || typeof parsed.models !== "object") {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return { ts: parsed.ts, models: parsed.models };
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Битый кэш — перечитываем ниже.
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function writeDiskCache(models) {
|
|
45
|
+
try {
|
|
46
|
+
const path = cachePath();
|
|
47
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
48
|
+
const entry = { ts: new Date().toISOString(), models };
|
|
49
|
+
writeFileSync(path, JSON.stringify(entry), "utf-8");
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Best-effort — падение записи не должно ронять агента.
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** `limit.context` одной записи модели, если это годное число. */
|
|
56
|
+
function modelContextOf(meta) {
|
|
57
|
+
const context = meta?.limit?.context;
|
|
58
|
+
if (typeof context !== "number" || !Number.isFinite(context) || context <= 0)
|
|
59
|
+
return null;
|
|
60
|
+
return Math.floor(context);
|
|
61
|
+
}
|
|
62
|
+
function extractOpencodeModels(catalog) {
|
|
63
|
+
if (!catalog || typeof catalog !== "object")
|
|
64
|
+
return null;
|
|
65
|
+
const provider = catalog.opencode;
|
|
66
|
+
if (!provider || typeof provider !== "object")
|
|
67
|
+
return null;
|
|
68
|
+
const models = provider.models;
|
|
69
|
+
if (!models || typeof models !== "object")
|
|
70
|
+
return null;
|
|
71
|
+
const out = {};
|
|
72
|
+
for (const [id, meta] of Object.entries(models)) {
|
|
73
|
+
const context = modelContextOf(meta);
|
|
74
|
+
if (context !== null)
|
|
75
|
+
out[id] = context;
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
async function fetchCatalog(timeoutMs) {
|
|
80
|
+
try {
|
|
81
|
+
const response = await fetch(MODELS_DEV_URL, { signal: AbortSignal.timeout(timeoutMs) });
|
|
82
|
+
if (!response.ok)
|
|
83
|
+
return null;
|
|
84
|
+
return extractOpencodeModels((await response.json()));
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Ищет `model` в секции провайдера `opencode` каталога models.dev.
|
|
92
|
+
* Только точное совпадение id (Zen отдаёт bare id, каталог ключует так же).
|
|
93
|
+
* Возвращает каталожный `limit.context`, на любом промахе — null.
|
|
94
|
+
*/
|
|
95
|
+
export async function lookupModelsDevContext(model, opts = {}) {
|
|
96
|
+
const timeoutMs = opts.timeoutMs ?? MODELS_DEV_FETCH_TIMEOUT_MS;
|
|
97
|
+
if (memCache && Date.now() - memCache.ts < MODELS_DEV_CATALOG_TTL_MS) {
|
|
98
|
+
return memCache.models[model] ?? null;
|
|
99
|
+
}
|
|
100
|
+
const disk = readDiskCache();
|
|
101
|
+
if (disk && Date.now() - new Date(disk.ts).getTime() < MODELS_DEV_CATALOG_TTL_MS) {
|
|
102
|
+
memCache = { models: disk.models, ts: Date.now() };
|
|
103
|
+
return disk.models[model] ?? null;
|
|
104
|
+
}
|
|
105
|
+
const fresh = await fetchCatalog(timeoutMs);
|
|
106
|
+
if (!fresh) {
|
|
107
|
+
// Офлайн с протухшим кэшем: протухшее окно лучше никакого.
|
|
108
|
+
if (disk) {
|
|
109
|
+
memCache = { models: disk.models, ts: Date.now() };
|
|
110
|
+
return disk.models[model] ?? null;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
memCache = { models: fresh, ts: Date.now() };
|
|
115
|
+
writeDiskCache(fresh);
|
|
116
|
+
return fresh[model] ?? null;
|
|
117
|
+
}
|
|
118
|
+
/** Тестовый шов: сбросить in-memory проекцию (диск изолирован через env). */
|
|
119
|
+
export function resetModelsDevCache() {
|
|
120
|
+
memCache = null;
|
|
121
|
+
}
|