micro-models-agent 2.11.0 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/assets/app.js +22 -2
- package/dist/assets/index.html +39 -9
- package/dist/assets/js/dom.js +15 -0
- package/dist/assets/js/feed.js +129 -10
- package/dist/assets/js/sidebar.js +512 -0
- package/dist/assets/js/tabs.js +30 -5
- package/dist/assets/setup.js +267 -8
- package/dist/assets/styles.css +168 -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/en.json +89 -3
- package/dist/i18n/index.js +37 -3
- package/dist/i18n/ru.json +89 -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 +888 -139
- 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
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { setAuditSessionDir } from "../modules/security/audit-log";
|
|
2
2
|
import { sanitizeLogMessage } from "../modules/security/data-sanitizer";
|
|
3
|
-
import {
|
|
4
|
-
import { readFileSync, existsSync } from "fs";
|
|
3
|
+
import { redactContextSecrets } from "./agent/context-log";
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
* `if (sessionManager)` + `new Date().toISOString()`
|
|
8
|
-
* from the agent loop.
|
|
5
|
+
* Тонкая обёртка над SessionManager: убирает повторяющиеся
|
|
6
|
+
* `if (sessionManager)` + `new Date().toISOString()` из цикла агента.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* При создании привязывает логгер приложения и аудит-лог к каталогу сессии
|
|
9
|
+
* (вместо глобального ~/.mma/logs/).
|
|
12
10
|
*/
|
|
13
11
|
export class SessionLogger {
|
|
14
12
|
session;
|
|
@@ -21,26 +19,36 @@ export class SessionLogger {
|
|
|
21
19
|
this.bindSessionDir();
|
|
22
20
|
}
|
|
23
21
|
bindSessionDir() {
|
|
24
|
-
const
|
|
25
|
-
|
|
22
|
+
const session = this.session;
|
|
23
|
+
const meta = session?.getActiveMeta();
|
|
24
|
+
if (!session || !meta)
|
|
26
25
|
return;
|
|
27
|
-
const dir =
|
|
26
|
+
const dir = session.getSessionDirectory(meta.id);
|
|
28
27
|
if (this.logger) {
|
|
29
28
|
this.logger.setSessionDir(dir);
|
|
30
29
|
this.logger.initSessionLog(meta.id);
|
|
31
30
|
}
|
|
32
31
|
setAuditSessionDir(dir);
|
|
33
32
|
}
|
|
33
|
+
/** Есть ли активная сессия. */
|
|
34
34
|
get active() {
|
|
35
35
|
return !!this.session?.getActive();
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Пишет системное сообщение в лог сессии.
|
|
39
|
+
* @param content текст системного сообщения.
|
|
40
|
+
*/
|
|
37
41
|
logSystem(content) {
|
|
38
42
|
this.session?.appendLog({
|
|
39
43
|
ts: new Date().toISOString(),
|
|
40
44
|
type: "system",
|
|
41
|
-
content,
|
|
45
|
+
content: redactContextSecrets(content),
|
|
42
46
|
});
|
|
43
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Пишет сообщение пользователя (санитизированное).
|
|
50
|
+
* @param content текст пользователя.
|
|
51
|
+
*/
|
|
44
52
|
logUser(content) {
|
|
45
53
|
const sanitized = sanitizeLogMessage(content);
|
|
46
54
|
this.session?.appendMessage({
|
|
@@ -54,13 +62,18 @@ export class SessionLogger {
|
|
|
54
62
|
content: sanitized,
|
|
55
63
|
});
|
|
56
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Пишет ответ ассистента (+ reasoning и tool_calls при наличии).
|
|
67
|
+
* @param content текст ответа; @param reasoning reasoning-контент;
|
|
68
|
+
* @param toolCalls вызовы тулов; @param iteration номер итерации.
|
|
69
|
+
*/
|
|
57
70
|
logAssistant(content, reasoning, toolCalls, iteration) {
|
|
58
71
|
const caller = this.getCaller?.();
|
|
59
72
|
if (reasoning) {
|
|
60
73
|
this.session?.appendLog({
|
|
61
74
|
ts: new Date().toISOString(),
|
|
62
75
|
type: "reasoning",
|
|
63
|
-
content: reasoning,
|
|
76
|
+
content: redactContextSecrets(reasoning),
|
|
64
77
|
iteration,
|
|
65
78
|
provider: caller?.provider,
|
|
66
79
|
model: caller?.model,
|
|
@@ -69,7 +82,7 @@ export class SessionLogger {
|
|
|
69
82
|
this.session?.appendLog({
|
|
70
83
|
ts: new Date().toISOString(),
|
|
71
84
|
type: "assistant",
|
|
72
|
-
content,
|
|
85
|
+
content: redactContextSecrets(content),
|
|
73
86
|
...(toolCalls
|
|
74
87
|
? {
|
|
75
88
|
tool_calls: toolCalls.map((tc) => ({
|
|
@@ -84,16 +97,24 @@ export class SessionLogger {
|
|
|
84
97
|
model: caller?.model,
|
|
85
98
|
});
|
|
86
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Сохраняет сообщение ассистента в историю сессии (для resume).
|
|
102
|
+
* @param content текст сообщения.
|
|
103
|
+
*/
|
|
87
104
|
saveAssistantMessage(content) {
|
|
88
105
|
const caller = this.getCaller?.();
|
|
89
106
|
this.session?.appendMessage({
|
|
90
107
|
role: "assistant",
|
|
91
|
-
content,
|
|
108
|
+
content: redactContextSecrets(content),
|
|
92
109
|
timestamp: new Date().toISOString(),
|
|
93
110
|
provider: caller?.provider,
|
|
94
111
|
model: caller?.model,
|
|
95
112
|
});
|
|
96
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Пишет набор определений тулов итерации (состав для пост-анализа).
|
|
116
|
+
* @param toolCount число тулов; @param toolNames имена; @param iteration итерация.
|
|
117
|
+
*/
|
|
97
118
|
logToolDefs(toolCount, toolNames, iteration) {
|
|
98
119
|
this.session?.appendLog({
|
|
99
120
|
ts: new Date().toISOString(),
|
|
@@ -103,16 +124,46 @@ export class SessionLogger {
|
|
|
103
124
|
iteration,
|
|
104
125
|
});
|
|
105
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Пишет вызов тула (имя, id, санитизированные аргументы).
|
|
129
|
+
* @param call вызов тула; @param iteration номер итерации.
|
|
130
|
+
*/
|
|
106
131
|
logToolCall(call, iteration) {
|
|
107
132
|
this.session?.appendLog({
|
|
108
133
|
ts: new Date().toISOString(),
|
|
109
134
|
type: "tool_call",
|
|
110
135
|
tool: call.name,
|
|
111
136
|
tool_call_id: call.id,
|
|
112
|
-
args:
|
|
137
|
+
args: this.sanitizeArgs(call.arguments),
|
|
113
138
|
iteration,
|
|
114
139
|
});
|
|
115
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Сериализует аргументы тула для лога. Санитайзер может испортить JSON
|
|
143
|
+
* (например, режет закрывающую кавычку в `password=secret"`), поэтому при
|
|
144
|
+
* ошибке парсинга пишем сырую санитизированную строку и предупреждаем —
|
|
145
|
+
* запись tool_call не должна теряться.
|
|
146
|
+
*/
|
|
147
|
+
sanitizeArgs(args) {
|
|
148
|
+
const raw = JSON.stringify(args ?? {});
|
|
149
|
+
const sanitized = sanitizeLogMessage(raw);
|
|
150
|
+
try {
|
|
151
|
+
const parsed = JSON.parse(sanitized);
|
|
152
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
153
|
+
return parsed;
|
|
154
|
+
}
|
|
155
|
+
return { raw: sanitized };
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
this.logger?.warn(`tool_call args sanitization broke JSON; storing raw string (${raw.length} chars)`);
|
|
159
|
+
return { raw: sanitized };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Пишет результат тула (успех, вывод, diff, длительность).
|
|
164
|
+
* @param call вызов; @param result результат; @param duration длительность, мс;
|
|
165
|
+
* @param iteration номер итерации.
|
|
166
|
+
*/
|
|
116
167
|
logToolResult(call, result, duration, iteration) {
|
|
117
168
|
const caller = this.getCaller?.();
|
|
118
169
|
this.session?.appendMessage({
|
|
@@ -137,6 +188,10 @@ export class SessionLogger {
|
|
|
137
188
|
model: caller?.model,
|
|
138
189
|
});
|
|
139
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Пишет событие компакции (причина, токены/качество до и после).
|
|
193
|
+
* @param info параметры компакции.
|
|
194
|
+
*/
|
|
140
195
|
logCompaction(info) {
|
|
141
196
|
this.session?.appendLog({
|
|
142
197
|
ts: new Date().toISOString(),
|
|
@@ -155,6 +210,10 @@ export class SessionLogger {
|
|
|
155
210
|
summary: info.summary,
|
|
156
211
|
});
|
|
157
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Пишет снапшот контекста (бюджеты, токены, качество, состав блоков).
|
|
215
|
+
* @param info параметры снапшота.
|
|
216
|
+
*/
|
|
158
217
|
logContext(info) {
|
|
159
218
|
this.session?.appendLog({
|
|
160
219
|
ts: new Date().toISOString(),
|
|
@@ -179,6 +238,10 @@ export class SessionLogger {
|
|
|
179
238
|
blocks: info.blocks,
|
|
180
239
|
});
|
|
181
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Пишет usage LLM-вызова (токены, источник, кеш, стабильность префикса).
|
|
243
|
+
* @param iteration номер итерации; @param usage токены и мета.
|
|
244
|
+
*/
|
|
182
245
|
logLlmUsage(iteration, usage) {
|
|
183
246
|
this.session?.appendLog({
|
|
184
247
|
ts: new Date().toISOString(),
|
|
@@ -198,13 +261,21 @@ export class SessionLogger {
|
|
|
198
261
|
cacheSource: usage.cache?.source,
|
|
199
262
|
});
|
|
200
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Пишет ошибку в лог сессии.
|
|
266
|
+
* @param message текст ошибки.
|
|
267
|
+
*/
|
|
201
268
|
logError(message) {
|
|
202
269
|
this.session?.appendLog({
|
|
203
270
|
ts: new Date().toISOString(),
|
|
204
271
|
type: "error",
|
|
205
|
-
content: message,
|
|
272
|
+
content: redactContextSecrets(message),
|
|
206
273
|
});
|
|
207
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Пишет вердикт финального аудита.
|
|
277
|
+
* @param summary сводка аудита; @param iteration номер итерации.
|
|
278
|
+
*/
|
|
208
279
|
logAudit(summary, iteration) {
|
|
209
280
|
this.session?.appendLog({
|
|
210
281
|
ts: new Date().toISOString(),
|
|
@@ -213,6 +284,10 @@ export class SessionLogger {
|
|
|
213
284
|
iteration,
|
|
214
285
|
});
|
|
215
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Пишет событие плана MoE/обычного (создание, шаги, re-plan).
|
|
289
|
+
* @param event имя события; @param detail детали; @param iteration итерация.
|
|
290
|
+
*/
|
|
216
291
|
logPlan(event, detail, iteration) {
|
|
217
292
|
this.session?.appendLog({
|
|
218
293
|
ts: new Date().toISOString(),
|
|
@@ -223,24 +298,23 @@ export class SessionLogger {
|
|
|
223
298
|
});
|
|
224
299
|
}
|
|
225
300
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
301
|
+
* Пишет стартовую диагностику сессии: окружение, LSP-проба, плагины, скиллы.
|
|
302
|
+
* Должна быть ПЕРВОЙ записью в session.jsonl (файл самоописываем).
|
|
303
|
+
* Пропускает, если session_start уже есть (напр., записан REPL).
|
|
229
304
|
*/
|
|
230
305
|
logSessionStart(data) {
|
|
231
|
-
//
|
|
306
|
+
// Пропуск при уже записанном session_start (REPL мог записать с LSP-пробой).
|
|
307
|
+
// Чтение через decrypt-aware store: при шифровании сессии строки на диске —
|
|
308
|
+
// шифртекст, поэтому проверка подстрокой никогда не срабатывала и дубль дописывался.
|
|
232
309
|
const meta = this.session?.getActiveMeta();
|
|
233
310
|
if (meta) {
|
|
234
|
-
const logPath = join(this.session.getSessionDirectory(meta.id), "session.jsonl");
|
|
235
311
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
312
|
+
const entries = this.session.loadSessionLog(meta.id);
|
|
313
|
+
if (entries.some((e) => e.type === "session_start"))
|
|
314
|
+
return;
|
|
241
315
|
}
|
|
242
316
|
catch {
|
|
243
|
-
//
|
|
317
|
+
// Ошибка чтения — всё равно пишем
|
|
244
318
|
}
|
|
245
319
|
}
|
|
246
320
|
this.session?.appendLog({
|
|
@@ -254,7 +328,7 @@ export class SessionLogger {
|
|
|
254
328
|
});
|
|
255
329
|
}
|
|
256
330
|
/**
|
|
257
|
-
*
|
|
331
|
+
* Пишет событие управления reasoning (уровень, оценка политики).
|
|
258
332
|
*/
|
|
259
333
|
logReasoningControl(data) {
|
|
260
334
|
this.session?.appendLog({
|
|
@@ -269,8 +343,8 @@ export class SessionLogger {
|
|
|
269
343
|
});
|
|
270
344
|
}
|
|
271
345
|
/**
|
|
272
|
-
*
|
|
273
|
-
* moe_verify).
|
|
346
|
+
* Пишет событие наблюдаемости MoE (moe_plan / moe_subtask / moe_replan /
|
|
347
|
+
* moe_verify). Эмитят runWithMoE и MoEExecutor (Plan 4.2).
|
|
274
348
|
*/
|
|
275
349
|
logMoE(event, data) {
|
|
276
350
|
this.session?.appendLog({
|
|
@@ -280,4 +354,22 @@ export class SessionLogger {
|
|
|
280
354
|
...data,
|
|
281
355
|
});
|
|
282
356
|
}
|
|
357
|
+
/** Пишет событие онбординга (meet/init) для пост-анализа. */
|
|
358
|
+
logOnboarding(event, data = {}) {
|
|
359
|
+
this.session?.appendLog({
|
|
360
|
+
ts: new Date().toISOString(),
|
|
361
|
+
type: `onboarding_${event}`,
|
|
362
|
+
content: event,
|
|
363
|
+
...data,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
/** Пишет событие критика (контр-агент). */
|
|
367
|
+
logCritic(event, data = {}) {
|
|
368
|
+
this.session?.appendLog({
|
|
369
|
+
ts: new Date().toISOString(),
|
|
370
|
+
type: event,
|
|
371
|
+
content: data.summary ?? event,
|
|
372
|
+
...data,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
283
375
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Рендерит системный промпт (чистая функция).
|
|
3
|
+
* @param config конфиг приложения; @param baseDir workspace;
|
|
4
|
+
* @param profileCompressed сжатый профиль окружения.
|
|
5
|
+
* @returns текст системного сообщения для модели.
|
|
6
|
+
*/
|
|
7
|
+
export function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
8
|
+
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
9
|
+
const isWin = profileCompressed.toLowerCase().includes("win32");
|
|
10
|
+
const lines = [
|
|
11
|
+
`You are MMA v2, an AI agent for small models (${config.model}). Date: ${now}.`,
|
|
12
|
+
`Workspace: ${baseDir}. ${profileCompressed}.`,
|
|
13
|
+
`Reply in the user's language. Explain briefly if not obvious.`,
|
|
14
|
+
``,
|
|
15
|
+
`TOOLS: file ops (read/write/edit/delete), search (glob/grep), shell (bash), web, subagents, browser, MCP.`,
|
|
16
|
+
`On tool failure: analyze, fix the call, retry up to 2x with different approaches, then ask the user.`,
|
|
17
|
+
``,
|
|
18
|
+
`SCOPE — do ONLY what the user explicitly asked: no extra features, files, refactors, or fixes beyond the request.`,
|
|
19
|
+
`Read-only requests ("расскажи", "покажи", "объясни", "check") mean READ-ONLY: inspect and answer, never modify anything.`,
|
|
20
|
+
`Ambiguous task (unclear what/where/which) or target not found — STOP and ask via the "question" tool, do not guess.`,
|
|
21
|
+
`A "not found" tool result means the PATH was wrong, not that the project is missing: list_dir the workspace first,`,
|
|
22
|
+
`then the parent of a user-named path. NEVER scaffold a new project for questions about an existing one.`,
|
|
23
|
+
``,
|
|
24
|
+
`ARTIFACTS: CREATE a file ONLY when the user explicitly asks for a file — "write/save to file", "create a file/document",`,
|
|
25
|
+
`or a filename/path with an extension.`,
|
|
26
|
+
`Bare "recommendation", "summary", "report", "result" mean ANSWER IN CHAT, never files.`,
|
|
27
|
+
`Use the requested format and stack; never add unagreed libraries.`,
|
|
28
|
+
`If a needed choice is unspecified, ask or search first.`,
|
|
29
|
+
``,
|
|
30
|
+
`MEMORY: the current user message outranks stored memory/preferences.`,
|
|
31
|
+
`Never "correct" an explicit value from stored facts.`,
|
|
32
|
+
`Never ask what memory already answers (the "question" tool checks memory itself); "remember" only on explicit request.`,
|
|
33
|
+
`MEMORY PRIVACY: never copy stored personal facts (birthday, height, name, contacts) into workspace files unless asked.`,
|
|
34
|
+
``,
|
|
35
|
+
`PROTECTED PATHS: never touch VCS internals (.git/, .hg/, .svn/) or secrets (.env*, *.key, *.pem, *.p12, *.pfx, *.crt,`,
|
|
36
|
+
`*.secret, *.token, .npmrc, .netrc, .git-credentials, .gitconfig) without explicit confirmation via the "approve" tool.`,
|
|
37
|
+
`Do not retry around a refusal or work around it with bash.`,
|
|
38
|
+
``,
|
|
39
|
+
`WORK RULES: 1) install deps BEFORE source (verify lockfile; no uninstalled imports); 2) framework init BEFORE app code;`,
|
|
40
|
+
`3) plan sequentially, verify each step's deliverables exist with real content; 4) verify on disk + command output;`,
|
|
41
|
+
`5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, change approach, ask.`,
|
|
42
|
+
``,
|
|
43
|
+
`SESSION START (first turn with a workspace task): 1) inspect — list_dir the workspace, note package.json/tests/config;`,
|
|
44
|
+
`2) baseline for CODE tasks only — run project checks (bun test / tsc --noEmit),`,
|
|
45
|
+
`report pass/fail BEFORE changing code;`,
|
|
46
|
+
`3) trivial chat/questions skip the baseline. Then proceed with the user's task.`,
|
|
47
|
+
``,
|
|
48
|
+
`FORBIDDEN:`,
|
|
49
|
+
`- Marking done without proof (no clean check output) — see VERIFY.`,
|
|
50
|
+
`- Creating files the user didn't ask for — see ARTIFACTS.`,
|
|
51
|
+
`- Retrying the same failing command a 3rd time — change approach or ask.`,
|
|
52
|
+
`- Claiming "fixed" from a fresh port/server while the user's endpoint still fails.`,
|
|
53
|
+
``,
|
|
54
|
+
`DONE CONDITIONS — finished only when ALL hold: all plan steps are marked done;`,
|
|
55
|
+
`requested files/artifacts exist with real content; each runnable verification reports clean.`,
|
|
56
|
+
`Then reply with a short summary of what changed (files created/edited).`,
|
|
57
|
+
`STOP AND ASK THE USER WHEN: the task is ambiguous (multiple approaches, unclear what/where);`,
|
|
58
|
+
`you could not find what the user asked about after listing the parent directory;`,
|
|
59
|
+
`finishing would delete/overwrite important files;`,
|
|
60
|
+
`or you are stuck after 2+ different approaches.`,
|
|
61
|
+
`Ask via the "question" tool (one short question, options when known) and wait.`,
|
|
62
|
+
`Plain text only when interactive tools are unavailable.`,
|
|
63
|
+
];
|
|
64
|
+
if (isWin) {
|
|
65
|
+
lines.push(`Windows (PowerShell): use list_dir/read_file/delete_file/create_dir tools instead of dir/type/del/mkdir.`, `No PowerShell cmdlets (Get-Content, Select-Object, Write-Output), no head/tail/grep/cat.`, `Forward slashes in paths. CWD: ${baseDir}`);
|
|
66
|
+
}
|
|
67
|
+
// MMA — Bun-only проект (скрипты package.json, Bun API в коде): модель
|
|
68
|
+
// должна предпочитать bun, а не node/tsx/ts-node, для запуска TypeScript
|
|
69
|
+
// (наблюдалось: модель жгла 10+ итераций на установку tsx вместо `bun file.ts`).
|
|
70
|
+
lines.push(`Runtime: Bun is available — run TypeScript directly with "bun <file.ts>", tests with "bun test" (no tsx/ts-node needed).`, `Bash: pass "workdir", never "cd dir && cmd". One command per call.`, `Long-running: "background: true", else auto-backgrounded — check with process_log.`, ``, `VERIFY EVERY WRITE: after write_file/edit_file with NO [LSP errors], [LSP warnings], [Syntax check failed],`, `or [Project typecheck failed] in the result — call "lsp_check" on that file BEFORE marking the step done.`, `Never assume, prove.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact paths, packages, commands).`, `No vague steps. 5-8 steps, init → verify.`, `Each step needs a 1:1 verification contract in "checks":`, `"file-exists:<path>", "command:<exact command>", or "manual:<what>".`, `For "check/fix errors" tasks each verification step names the exact proving command`, `("bun run build", "bun test", "lsp_check").`, `A step is done only after its check reports clean — then "plan_step step=N status=done".`);
|
|
71
|
+
if (config.autoPlan) {
|
|
72
|
+
lines.push(`PLAN (MANDATORY): file creation, package installs, or multi-action tasks MUST create a "plan" BEFORE starting.`);
|
|
73
|
+
}
|
|
74
|
+
// Баг в терминах runtime-поведения (что происходит при запуске) доказывается
|
|
75
|
+
// только ВОСПРОИЗВЕДЕНИЕМ — запуском app/build/browser и сверкой с реальным
|
|
76
|
+
// выводом. Модель решает сама, когда это применимо (без классификации по
|
|
77
|
+
// ключевым словам). Протухшие dev-серверы держат СТАРЫЙ пайплайн в памяти и
|
|
78
|
+
// продолжают кидать исходную ошибку (наблюдалось: старый vite на 5173–5176
|
|
79
|
+
// сыпал postcss после фикса на диске, а свежий на 5177 был чист) — фикс
|
|
80
|
+
// реален, только когда чист сервер ПОЛЬЗОВАТЕЛЯ.
|
|
81
|
+
lines.push(`Runtime verification: when a bug is described in terms of runtime behavior`, `(what happens when the app runs), reproduce it —`, `run the app / build / browser tool — confirm the fix against actual runtime output`, `before calling "plan_step step=N status=done".`, `Check existing servers first (process_list/process_log): a stale dev server`, `runs the old pipeline and keeps failing after the fix.`, `Restart/kill it (process_kill) and verify the exact endpoint/port reported —`, `a fresh port does NOT prove the user's error is gone.`);
|
|
82
|
+
// Правила безопасности: при включённой защите модель должна знать ограничения
|
|
83
|
+
// заранее — заблокированный вызов стоит итерацию, а этот блок ~100 токенов
|
|
84
|
+
// один раз. Компактно и с cap, чтобы длинный blacklist не рвал бюджет.
|
|
85
|
+
const sec = config.security;
|
|
86
|
+
if (sec?.enabled) {
|
|
87
|
+
const secLines = [
|
|
88
|
+
`SECURITY RESTRICTIONS (enforced — blocked calls return "[SECURITY BLOCKED]", do not retry them):`,
|
|
89
|
+
];
|
|
90
|
+
if (sec.bash?.enabled && sec.bash.blacklist.length > 0) {
|
|
91
|
+
const cmds = sec.bash.blacklist.slice(0, 15).join(", ");
|
|
92
|
+
secLines.push(`Forbidden bash commands: ${cmds}${sec.bash.blacklist.length > 15 ? ", …" : ""}.`);
|
|
93
|
+
if (sec.bash.whitelist.length > 0) {
|
|
94
|
+
secLines.push(`Only whitelisted bash commands are allowed: ${sec.bash.whitelist.slice(0, 15).join(", ")}.`);
|
|
95
|
+
}
|
|
96
|
+
if (sec.bash.blockDangerousFlags) {
|
|
97
|
+
secLines.push(`Pipes/redirects/chaining (| > >> ; &&) in bash are blocked — one plain command per call.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (sec.paths?.enabled && sec.paths.denied.length > 0) {
|
|
101
|
+
const paths = sec.paths.denied.slice(0, 10).join(", ");
|
|
102
|
+
secLines.push(`Denied paths (read/write): ${paths}${sec.paths.denied.length > 10 ? ", …" : ""}.`);
|
|
103
|
+
}
|
|
104
|
+
if (sec.network?.enabled && sec.network.deniedDomains.length > 0) {
|
|
105
|
+
const domains = sec.network.deniedDomains.slice(0, 10).join(", ");
|
|
106
|
+
secLines.push(`Denied network domains: ${domains}${sec.network.deniedDomains.length > 10 ? ", …" : ""}.`);
|
|
107
|
+
}
|
|
108
|
+
if (secLines.length > 1) {
|
|
109
|
+
lines.push(...secLines);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const hasMCP = config.mcpServers && Object.values(config.mcpServers).some((s) => s.enabled !== false);
|
|
113
|
+
if (hasMCP) {
|
|
114
|
+
lines.push(`MCP servers are available — use the named MCP tools (prefixed mcp__) to query external services.`);
|
|
115
|
+
}
|
|
116
|
+
return lines.join("\n");
|
|
117
|
+
}
|
package/dist/core/version.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
/** Версия MMA: читается из package.json в рантайме. */
|
|
1
2
|
import { existsSync, readFileSync } from "fs";
|
|
2
3
|
import { join, dirname } from "path";
|
|
3
4
|
import { fileURLToPath } from "url";
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Читает версию MMA из package.json в рантайме (не статическим импортом —
|
|
7
|
+
* бандлеры инлайнят устаревшее значение на этапе сборки, см. правило №12).
|
|
8
|
+
* @returns версия из package.json либо "0.0.0", если файл не найден/бит.
|
|
7
9
|
*/
|
|
8
10
|
export function readMmaVersion() {
|
|
9
11
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
@@ -16,11 +18,11 @@ export function readMmaVersion() {
|
|
|
16
18
|
return raw.version;
|
|
17
19
|
}
|
|
18
20
|
catch {
|
|
19
|
-
//
|
|
21
|
+
// Битый package.json — пробуем следующий кандидат
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
return "0.0.0";
|
|
24
26
|
}
|
|
25
|
-
/**
|
|
27
|
+
/** Устаревший алиас — используй readMmaVersion(). */
|
|
26
28
|
export const readVersion = readMmaVersion;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defaultOutputBus } from "../output/bus";
|
|
2
|
+
/** Реализация хоста для `mma web` — без TTY, без LineEditor. */
|
|
3
|
+
export class WebHost {
|
|
4
|
+
deps;
|
|
5
|
+
constructor(deps) {
|
|
6
|
+
this.deps = deps;
|
|
7
|
+
}
|
|
8
|
+
isBusy() {
|
|
9
|
+
return this.deps.isBusy();
|
|
10
|
+
}
|
|
11
|
+
async submit(text, o) {
|
|
12
|
+
if (this.deps.isBusy())
|
|
13
|
+
throw new Error("agent is busy");
|
|
14
|
+
for (const url of o?.images ?? [])
|
|
15
|
+
this.deps.addPendingImage?.(url);
|
|
16
|
+
return this.deps.runAgent(text);
|
|
17
|
+
}
|
|
18
|
+
interrupt() {
|
|
19
|
+
if (this.deps.isBusy())
|
|
20
|
+
this.deps.interrupt();
|
|
21
|
+
}
|
|
22
|
+
subscribeOutput(fn) {
|
|
23
|
+
return defaultOutputBus.subscribe(fn);
|
|
24
|
+
}
|
|
25
|
+
async executeCommand(line) {
|
|
26
|
+
const trimmed = line.trim();
|
|
27
|
+
if (!trimmed.startsWith("/"))
|
|
28
|
+
return;
|
|
29
|
+
await this.deps.executeCommand(trimmed);
|
|
30
|
+
}
|
|
31
|
+
getState() {
|
|
32
|
+
return this.deps.getState();
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/core/workspace.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
/** Резолвинг путей workspace: поиск корня проекта по манифестам. */
|
|
1
2
|
import { existsSync, readdirSync } from "fs";
|
|
2
3
|
import { resolve, isAbsolute, join } from "path";
|
|
3
|
-
/**
|
|
4
|
+
/** Файлы/каталоги — маркеры корня проекта. */
|
|
4
5
|
const PROJECT_MANIFESTS = [
|
|
5
6
|
"package.json",
|
|
6
7
|
"bun.lockb",
|
|
@@ -14,7 +15,7 @@ const PROJECT_MANIFESTS = [
|
|
|
14
15
|
"Gemfile",
|
|
15
16
|
"composer.json",
|
|
16
17
|
];
|
|
17
|
-
/**
|
|
18
|
+
/** Подкаталоги, никогда не кандидаты в корень проекта. */
|
|
18
19
|
const SKIP_DIRS = new Set(["node_modules", "dist", ".git", ".hg", ".svn"]);
|
|
19
20
|
const subdirCache = new Map();
|
|
20
21
|
function scanSubdirs(baseDir) {
|
|
@@ -35,27 +36,30 @@ function scanSubdirs(baseDir) {
|
|
|
35
36
|
subdirCache.set(baseDir, dirs);
|
|
36
37
|
return dirs;
|
|
37
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Есть ли в каталоге манифест проекта.
|
|
41
|
+
* @param dir каталог для проверки.
|
|
42
|
+
* @returns true, если найден известный манифест.
|
|
43
|
+
*/
|
|
38
44
|
export function hasProjectManifest(dir) {
|
|
39
45
|
return PROJECT_MANIFESTS.some((m) => existsSync(join(dir, m)));
|
|
40
46
|
}
|
|
41
47
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* Returns baseDir/<p> as a fallback when nothing exists, so callers that
|
|
51
|
-
* check existsSync() still correctly report the path as missing.
|
|
48
|
+
* Резолвит путь внутри workspace. Терпит запуск из родителя, когда проект
|
|
49
|
+
* лежит в одном подкаталоге (baseDir=<repo>, проект=<repo>/app). Порядок:
|
|
50
|
+
* 1. абсолютный путь как есть;
|
|
51
|
+
* 2. baseDir/<p> — проект прямо в baseDir;
|
|
52
|
+
* 3. <subdir>/<p> по подкаталогам (приоритет — с манифестом).
|
|
53
|
+
* Фолбэк — baseDir/<p>, чтобы вызывающий через existsSync() корректно
|
|
54
|
+
* определил отсутствие пути.
|
|
55
|
+
* @param baseDir корень workspace; @param p относительный/абсолютный путь.
|
|
52
56
|
*/
|
|
53
57
|
export function resolveProjectPath(baseDir, p) {
|
|
54
58
|
const abs = isAbsolute(p) ? p : resolve(baseDir, p);
|
|
55
59
|
if (existsSync(abs))
|
|
56
60
|
return abs;
|
|
57
|
-
// baseDir
|
|
58
|
-
//
|
|
61
|
+
// Сам baseDir — корень проекта: подкаталоги не сканируем, иначе
|
|
62
|
+
// зацепим файлы посторонних вложенных пакетов.
|
|
59
63
|
if (hasProjectManifest(baseDir))
|
|
60
64
|
return abs;
|
|
61
65
|
let fallback = abs;
|
|
@@ -70,7 +74,7 @@ export function resolveProjectPath(baseDir, p) {
|
|
|
70
74
|
}
|
|
71
75
|
return fallback;
|
|
72
76
|
}
|
|
73
|
-
/**
|
|
77
|
+
/** Сбрасывает кэш подкаталогов (нужен тестам). */
|
|
74
78
|
export function clearWorkspaceCache() {
|
|
75
79
|
subdirCache.clear();
|
|
76
80
|
}
|