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/tools/executor.js
CHANGED
|
@@ -1,25 +1,44 @@
|
|
|
1
1
|
import { killByCallId } from "../modules/processes/runner";
|
|
2
2
|
import { t } from "../i18n/index";
|
|
3
|
-
|
|
3
|
+
import { TOOL_EXECUTION_TIMEOUT_MS, TOOL_MEMO_TTL_MS as MEMO_TTL_MS, } from "../config/timeouts";
|
|
4
|
+
const MEMO_MAX_ENTRIES = 100;
|
|
5
|
+
/** Стабильная сериализация: сортировка ключей, порядок аргументов на ключ не влияет. */
|
|
6
|
+
function stableArgsKey(value) {
|
|
7
|
+
if (Array.isArray(value))
|
|
8
|
+
return value.map(stableArgsKey);
|
|
9
|
+
if (value && typeof value === "object") {
|
|
10
|
+
const entries = Object.keys(value)
|
|
11
|
+
.sort()
|
|
12
|
+
.map((k) => [k, stableArgsKey(value[k])]);
|
|
13
|
+
return Object.fromEntries(entries);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
/** Исполнитель: реестр, контекст, плагины, сессионное мемо. */
|
|
4
18
|
export class ToolExecutor {
|
|
5
19
|
registry;
|
|
6
20
|
ctx;
|
|
7
21
|
pluginManager;
|
|
22
|
+
/**
|
|
23
|
+
* Сессионное мемо детерминированных read-only результатов
|
|
24
|
+
* (`ToolDefinition.cacheable` + ручные записи `manualMemo`-тулов вроде bash).
|
|
25
|
+
* Ключ: `sessionId::name::stableArgs`.
|
|
26
|
+
*/
|
|
27
|
+
memo = new Map();
|
|
8
28
|
constructor(registry, ctx, pluginManager) {
|
|
9
29
|
this.registry = registry;
|
|
10
30
|
this.ctx = ctx;
|
|
11
31
|
this.pluginManager = pluginManager;
|
|
12
32
|
}
|
|
13
33
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* hooks as a normal call.
|
|
34
|
+
* Запуск тула по имени с plain-аргументами (без call id и таймаут-обвязки).
|
|
35
|
+
* Для внутреннего использования — напр. bash перенаправляет ошибочный
|
|
36
|
+
* tool-call-как-команду в настоящий тул. Идёт через те же реестр и хуки.
|
|
18
37
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
38
|
+
* Внимание по реентрантности: временно подменяет `this.ctx`. Безопасно для
|
|
39
|
+
* последовательных вызовов, но НЕ для конкурентных на одном инстансе —
|
|
40
|
+
* будет гонка на подмене. Сейчас все вызовы последовательны (bash-редирект,
|
|
41
|
+
* один subagent-тул); так и держать.
|
|
23
42
|
*/
|
|
24
43
|
async executeByName(name, args, ctx) {
|
|
25
44
|
const prevCtx = this.ctx;
|
|
@@ -36,11 +55,59 @@ export class ToolExecutor {
|
|
|
36
55
|
this.ctx = prevCtx;
|
|
37
56
|
}
|
|
38
57
|
}
|
|
39
|
-
/**
|
|
58
|
+
/** Есть ли тул с таким именем (проверка перед редиректами). */
|
|
40
59
|
hasTool(name) {
|
|
41
60
|
return this.registry.has(name);
|
|
42
61
|
}
|
|
62
|
+
memoKey(name, args) {
|
|
63
|
+
return `${this.ctx.sessionId ?? ""}::${name}::${JSON.stringify(stableArgsKey(args))}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Чтение мемо для `manualMemo`-тулов (bash). Возвращает откреплённую копию —
|
|
67
|
+
* `toolCallId` вызывающий ставит сам.
|
|
68
|
+
*/
|
|
69
|
+
memoGet(name, args) {
|
|
70
|
+
const hit = this.memo.get(this.memoKey(name, args));
|
|
71
|
+
if (!hit)
|
|
72
|
+
return undefined;
|
|
73
|
+
if (Date.now() - hit.at > MEMO_TTL_MS) {
|
|
74
|
+
this.memo.delete(this.memoKey(name, args));
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return { ...hit.result };
|
|
78
|
+
}
|
|
79
|
+
/** Запись в мемо для `manualMemo`-тулов. Хранит откреплённую копию. */
|
|
80
|
+
memoSet(name, args, result) {
|
|
81
|
+
const key = this.memoKey(name, args);
|
|
82
|
+
if (!this.memo.has(key) && this.memo.size >= MEMO_MAX_ENTRIES) {
|
|
83
|
+
const oldest = this.memo.keys().next();
|
|
84
|
+
if (!oldest.done)
|
|
85
|
+
this.memo.delete(oldest.value);
|
|
86
|
+
}
|
|
87
|
+
this.memo.set(key, { result: { ...result }, at: Date.now() });
|
|
88
|
+
}
|
|
89
|
+
/** Сброс мемо — после всего, что могло мутировать состояние. */
|
|
90
|
+
memoInvalidate() {
|
|
91
|
+
this.memo.clear();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Имена разрешённых тулов множеством, `null` — без ограничений.
|
|
95
|
+
* `undefined` — без ограничений; `[]` — запрещено всё.
|
|
96
|
+
*/
|
|
97
|
+
allowedNames() {
|
|
98
|
+
const allow = this.ctx.toolAllowlist;
|
|
99
|
+
return allow ? new Set(allow) : null;
|
|
100
|
+
}
|
|
101
|
+
/** Выполнить tool call: allowlist → плагины → хендлер → post-хуки. */
|
|
43
102
|
async execute(call, signal) {
|
|
103
|
+
const allow = this.allowedNames();
|
|
104
|
+
if (allow && !allow.has(call.name)) {
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
output: t("tool.not_allowed", { name: call.name }),
|
|
108
|
+
toolCallId: call.id,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
44
111
|
const tool = this.registry.get(call.name);
|
|
45
112
|
if (!tool) {
|
|
46
113
|
return {
|
|
@@ -72,23 +139,27 @@ export class ToolExecutor {
|
|
|
72
139
|
}
|
|
73
140
|
}
|
|
74
141
|
let result;
|
|
142
|
+
// Мемоизированный повтор детерминированного чтения (cacheable): хендлер
|
|
143
|
+
// пропускается, но общий хвост (post-плагины, логирование) идёт как обычно,
|
|
144
|
+
// чтобы мемо-хит был неотличим от свежего прогона.
|
|
145
|
+
const memoHit = tool.cacheable ? this.memoGet(call.name, call.arguments) : undefined;
|
|
75
146
|
try {
|
|
76
147
|
this.ctx.activeCallId = call.id;
|
|
77
148
|
if (tool.interactive) {
|
|
78
|
-
//
|
|
79
|
-
result = await tool.handler(this.ctx, call.arguments);
|
|
149
|
+
// Интерактивные тулы ждут ввода — без таймаута.
|
|
150
|
+
result = memoHit ?? (await tool.handler(this.ctx, call.arguments));
|
|
80
151
|
}
|
|
81
152
|
else {
|
|
82
153
|
const timeoutMs = tool.timeoutMs ?? TOOL_EXECUTION_TIMEOUT_MS;
|
|
83
154
|
const failFast = (message) => {
|
|
84
|
-
//
|
|
155
|
+
// Убить долгоживущий дочерний процесс этого вызова.
|
|
85
156
|
killByCallId(call.id);
|
|
86
|
-
//
|
|
87
|
-
//
|
|
157
|
+
// Тул-специфичный cleanup (напр. восстановление скоупа subagent) —
|
|
158
|
+
// до reject, чтобы общее состояние восстановилось и при abandonment.
|
|
88
159
|
const cleanup = this.ctx.cleanup;
|
|
89
160
|
if (cleanup) {
|
|
90
161
|
cleanup();
|
|
91
|
-
//
|
|
162
|
+
// Сбрасывать, только если более новый вызов не подменил тем временем.
|
|
92
163
|
if (this.ctx.cleanup === cleanup)
|
|
93
164
|
this.ctx.cleanup = undefined;
|
|
94
165
|
}
|
|
@@ -105,7 +176,7 @@ export class ToolExecutor {
|
|
|
105
176
|
}, timeoutMs);
|
|
106
177
|
});
|
|
107
178
|
const racePromises = [
|
|
108
|
-
tool.handler(this.ctx, call.arguments),
|
|
179
|
+
memoHit ? Promise.resolve(memoHit) : tool.handler(this.ctx, call.arguments),
|
|
109
180
|
timeoutPromise,
|
|
110
181
|
];
|
|
111
182
|
if (signal) {
|
|
@@ -124,16 +195,15 @@ export class ToolExecutor {
|
|
|
124
195
|
result = await Promise.race(racePromises);
|
|
125
196
|
}
|
|
126
197
|
finally {
|
|
127
|
-
//
|
|
128
|
-
//
|
|
198
|
+
// Остановить таймер и снять abort-слушатель, чтобы они не сработали
|
|
199
|
+
// против контекста/cleanup УЖЕ ДРУГОГО вызова.
|
|
129
200
|
if (timer !== undefined)
|
|
130
201
|
clearTimeout(timer);
|
|
131
202
|
if (onAbort && signal)
|
|
132
203
|
signal.removeEventListener("abort", onAbort);
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
// unhandled rejection.
|
|
204
|
+
// У проигравших промисов потребителя после settled race нет (их
|
|
205
|
+
// kill/cleanup-эффекты уже применены в failFast). Залогировать
|
|
206
|
+
// reject и отцепить, чтобы не всплыл как unhandled rejection.
|
|
137
207
|
for (const p of racePromises.slice(1)) {
|
|
138
208
|
p.catch((e) => {
|
|
139
209
|
this.ctx.logger.debug(`Tool ${call.name}: discarded race loser: ${e.message}`);
|
|
@@ -150,10 +220,22 @@ export class ToolExecutor {
|
|
|
150
220
|
toolCallId: call.id,
|
|
151
221
|
};
|
|
152
222
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
223
|
+
if (!memoHit) {
|
|
224
|
+
// Успешные детерминированные чтения мемоизируются; всё остальное, что
|
|
225
|
+
// реально выполнялось, могло мутировать состояние (даже упавшая команда
|
|
226
|
+
// применяется наполовину) — мемо сбрасывается. `manualMemo` (bash) ведут
|
|
227
|
+
// свои записи сами.
|
|
228
|
+
if (tool.cacheable && result.success) {
|
|
229
|
+
this.memoSet(call.name, call.arguments, result);
|
|
230
|
+
}
|
|
231
|
+
else if (!tool.cacheable && !tool.manualMemo) {
|
|
232
|
+
this.memoInvalidate();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// После аборта работа тула отбрасывается (цикл агента завершается без
|
|
236
|
+
// рендера/логирования), поэтому медленные post-плагины (LSP, lint, tsc)
|
|
237
|
+
// пропускаются целиком. Аборт посреди плагина виден ему через signal
|
|
238
|
+
// в контексте хука — плагин убьёт свои дочерние процессы.
|
|
157
239
|
if (signal?.aborted) {
|
|
158
240
|
this.ctx.logger.debug(`Tool ${call.name}: abort, skipping onAfterTool plugins`);
|
|
159
241
|
}
|
|
@@ -175,24 +257,47 @@ export class ToolExecutor {
|
|
|
175
257
|
this.ctx.logger.debug(`Tool ${call.name}: ${result.success ? "OK" : "FAIL"}`);
|
|
176
258
|
return result;
|
|
177
259
|
}
|
|
260
|
+
/** Определения тулов с учётом allowlist (для схемы LLM). */
|
|
178
261
|
getToolDefinitions(tags) {
|
|
262
|
+
const allow = this.allowedNames();
|
|
263
|
+
if (allow) {
|
|
264
|
+
return this.registry
|
|
265
|
+
.getAll()
|
|
266
|
+
.filter((t) => allow.has(t.name))
|
|
267
|
+
.map((t) => ({
|
|
268
|
+
name: t.name,
|
|
269
|
+
description: t.description,
|
|
270
|
+
parameters: t.parameters,
|
|
271
|
+
boundedOutput: t.boundedOutput,
|
|
272
|
+
}));
|
|
273
|
+
}
|
|
179
274
|
return this.registry.getAllForLLM(tags);
|
|
180
275
|
}
|
|
276
|
+
/** Доступ к реестру. */
|
|
181
277
|
getRegistry() {
|
|
182
278
|
return this.registry;
|
|
183
279
|
}
|
|
280
|
+
/** Установить скоуп shared-исполнителя. */
|
|
184
281
|
setScope(scope) {
|
|
185
282
|
this.ctx.scope = scope;
|
|
186
283
|
}
|
|
284
|
+
/** Текущий скоуп shared-исполнителя (для compare-and-restore субагентов). */
|
|
285
|
+
getScope() {
|
|
286
|
+
return this.ctx.scope;
|
|
287
|
+
}
|
|
288
|
+
/** Установить prompt-поверхность для интерактивных тулов. */
|
|
187
289
|
setPromptIO(io) {
|
|
188
290
|
this.ctx.promptIO = io;
|
|
189
291
|
}
|
|
292
|
+
/** Текущая глубина рекурсии субагентов. */
|
|
190
293
|
getRecursionDepth() {
|
|
191
294
|
return this.ctx.recursionDepth ?? 0;
|
|
192
295
|
}
|
|
296
|
+
/** Установить глубину рекурсии. */
|
|
193
297
|
setRecursionDepth(depth) {
|
|
194
298
|
this.ctx.recursionDepth = depth;
|
|
195
299
|
}
|
|
300
|
+
/** Подменить LLM-провайдер в контексте. */
|
|
196
301
|
updateProvider(provider) {
|
|
197
302
|
this.ctx.llmProvider = provider;
|
|
198
303
|
}
|
package/dist/tools/file-info.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
/** Тул метаданных файла/каталога (размер, даты; кешируемый). */
|
|
1
2
|
import { statSync, existsSync } from "fs";
|
|
2
3
|
import { t } from "../i18n/index";
|
|
3
4
|
import { isPathInScope } from "../modules/security/path-validator";
|
|
4
5
|
import { safeResolvePath } from "./path-utils";
|
|
6
|
+
/** Возвращает JSON с размером, типом, датами создания/изменения. */
|
|
5
7
|
export const fileInfoTool = {
|
|
6
8
|
name: "file_info",
|
|
7
9
|
icon: "ℹ️",
|
|
8
10
|
description: "Get metadata about a file or directory (size, creation date, modification date).",
|
|
9
11
|
tags: ["file"],
|
|
10
12
|
boundedOutput: true,
|
|
13
|
+
cacheable: true,
|
|
11
14
|
parameters: {
|
|
12
15
|
type: "object",
|
|
13
16
|
properties: {
|
|
@@ -18,7 +21,6 @@ export const fileInfoTool = {
|
|
|
18
21
|
handler: async (ctx, args) => {
|
|
19
22
|
const path = String(args.path);
|
|
20
23
|
const resolved = safeResolvePath(ctx.baseDir, path);
|
|
21
|
-
// Check path permissions
|
|
22
24
|
const scopeCheck = isPathInScope(ctx.baseDir, resolved, ctx.scope, ctx.config.security?.paths);
|
|
23
25
|
if (!scopeCheck.allowed) {
|
|
24
26
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* project_map, lsp_check, enable_tools)
|
|
2
|
+
* Фильтрует тулы по набору тегов, всегда оставляя `alwaysOn`. Для MoE-роутинга
|
|
3
|
+
* экспертов и subagent tool_tags — структурные тулы (plan/todo/verify,
|
|
4
|
+
* project_map, lsp_check, enable_tools) переживают сужение.
|
|
5
5
|
*/
|
|
6
6
|
export function filterToolsByTags(tools, toolTags) {
|
|
7
7
|
if (!toolTags || toolTags.length === 0)
|
package/dist/tools/glob-tool.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
/** Тул поиска файлов по glob-паттерну (кешируемый, jail в baseDir). */
|
|
1
2
|
import { globSync } from "fs";
|
|
2
3
|
import { t } from "../i18n/index";
|
|
3
4
|
import { MAX_PREVIEW_LINES } from "./preview";
|
|
5
|
+
/** Ищет файлы по glob; выдача обрезана MAX_PREVIEW_LINES. */
|
|
4
6
|
export const globTool = {
|
|
5
7
|
name: "glob",
|
|
6
8
|
icon: "🔎",
|
|
7
9
|
description: `Search for files matching a glob pattern. Shows up to ${MAX_PREVIEW_LINES} results by default. Uses standard glob syntax (e.g., **/*.ts, src/**/*.test.ts).`,
|
|
8
10
|
tags: ["file", "code", "research"],
|
|
11
|
+
cacheable: true,
|
|
9
12
|
parameters: {
|
|
10
13
|
type: "object",
|
|
11
14
|
properties: {
|
|
@@ -15,7 +18,7 @@ export const globTool = {
|
|
|
15
18
|
},
|
|
16
19
|
handler: async (ctx, args) => {
|
|
17
20
|
const pattern = String(args.pattern);
|
|
18
|
-
//
|
|
21
|
+
// Абсолютные паттерны (/etc/*) и ".." выводят за baseDir — запретить.
|
|
19
22
|
if (/^([a-zA-Z]:)?[\\/]/.test(pattern) || pattern.split(/[\\/]/).includes("..")) {
|
|
20
23
|
return {
|
|
21
24
|
success: false,
|
package/dist/tools/grep-tool.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/** Тул поиска по содержимому (rg с fallback на grep -r). */
|
|
2
|
+
import { spawn, } from "child_process";
|
|
2
3
|
import { resolve } from "path";
|
|
3
4
|
import { t } from "../i18n/index";
|
|
4
5
|
import { logBashCommand, logSecurityBlock } from "../modules/security/audit-log";
|
|
5
6
|
import { isPathInScope } from "../modules/security/path-validator";
|
|
6
7
|
import { DEFAULT_SECURITY_CONFIG } from "../config/security";
|
|
7
8
|
import { MAX_PREVIEW_LINES } from "./preview";
|
|
9
|
+
/** Обрезает вывод до MAX_PREVIEW_LINES строк. */
|
|
8
10
|
function truncateLines(output) {
|
|
9
11
|
const lines = output.split("\n");
|
|
10
12
|
if (lines.length <= MAX_PREVIEW_LINES)
|
|
@@ -13,8 +15,8 @@ function truncateLines(output) {
|
|
|
13
15
|
`\n... (${lines.length - MAX_PREVIEW_LINES} more lines)`);
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
+
* Поисковая команда асинхронно, с kill по таймауту. Exit code 1 (нет совпадений)
|
|
19
|
+
* резолвится в пустую строку. Возврат: stdout поиска.
|
|
18
20
|
*/
|
|
19
21
|
export function runSearch(bin, args, cwd, timeoutMs = 30000) {
|
|
20
22
|
return new Promise((resolvePromise, reject) => {
|
|
@@ -53,11 +55,13 @@ export function runSearch(bin, args, cwd, timeoutMs = 30000) {
|
|
|
53
55
|
});
|
|
54
56
|
});
|
|
55
57
|
}
|
|
58
|
+
/** Ищет по содержимому через regex (rg, иначе grep -r); кешируемый. */
|
|
56
59
|
export const grepTool = {
|
|
57
60
|
name: "grep",
|
|
58
61
|
icon: "🔍",
|
|
59
62
|
description: `Search file contents using a regular expression. Shows up to ${MAX_PREVIEW_LINES} matching lines by default. Uses ripgrep (rg) if available, otherwise falls back to grep -r.`,
|
|
60
63
|
tags: ["file", "code", "research"],
|
|
64
|
+
cacheable: true,
|
|
61
65
|
parameters: {
|
|
62
66
|
type: "object",
|
|
63
67
|
properties: {
|
|
@@ -76,8 +80,8 @@ export const grepTool = {
|
|
|
76
80
|
handler: async (ctx, args) => {
|
|
77
81
|
const pattern = String(args.pattern);
|
|
78
82
|
const searchPath = args.path ? resolve(ctx.baseDir, String(args.path)) : ctx.baseDir;
|
|
79
|
-
//
|
|
80
|
-
//
|
|
83
|
+
// Каталог поиска обязан оставаться внутри baseDir/скоупа: `path: "../../.."`
|
|
84
|
+
// не должен читать вне песочницы.
|
|
81
85
|
const scopeCheck = isPathInScope(ctx.baseDir, searchPath, ctx.scope, ctx.config?.security?.paths || DEFAULT_SECURITY_CONFIG.paths);
|
|
82
86
|
if (!scopeCheck.allowed) {
|
|
83
87
|
logSecurityBlock(ctx.sessionId || undefined, "file_read", scopeCheck.reason || "grep path not allowed", String(args.path ?? ctx.baseDir));
|
|
@@ -88,13 +92,12 @@ export const grepTool = {
|
|
|
88
92
|
}),
|
|
89
93
|
};
|
|
90
94
|
}
|
|
91
|
-
//
|
|
92
|
-
//
|
|
95
|
+
// Аргументы rg массивом, чтобы шелл не трактовал метасимволы regex
|
|
96
|
+
// (|, (, )) как операторы — это паттерны, не команды шелла.
|
|
93
97
|
const rgArgs = ["-n", "--with-filename", pattern, searchPath];
|
|
94
98
|
if (args.include) {
|
|
95
99
|
rgArgs.push("-g", String(args.include));
|
|
96
100
|
}
|
|
97
|
-
// Log the search (sanitized) for audit purposes
|
|
98
101
|
logBashCommand(ctx.sessionId, `rg ${rgArgs.join(" ")}`, false, "grep-tool");
|
|
99
102
|
try {
|
|
100
103
|
const output = await runSearch("rg", rgArgs, ctx.baseDir);
|
|
@@ -113,8 +116,8 @@ export const grepTool = {
|
|
|
113
116
|
else if (e.status === 1) {
|
|
114
117
|
return { success: true, output: t("file.no_matches") };
|
|
115
118
|
}
|
|
116
|
-
//
|
|
117
|
-
//
|
|
119
|
+
// Fallback на plain grep -r, когда rg нет или упал. Массив аргументов —
|
|
120
|
+
// защита от shell injection.
|
|
118
121
|
try {
|
|
119
122
|
const grepArgs = ["-rn", pattern, searchPath];
|
|
120
123
|
if (args.include) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
/** Блок системного промпта о скрытых tag-фильтром тулах. */
|
|
1
2
|
import { t } from "../i18n/index";
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* short purposes; capped to keep the block small.
|
|
4
|
+
* Компактный блок системного промпта со скрытыми тулами. Модель должна знать
|
|
5
|
+
* об их существовании (и пути доступа), хотя их нет в tool-схеме LLM.
|
|
6
|
+
* Группировка по тегам, размер ограничен.
|
|
7
7
|
*/
|
|
8
8
|
export function buildHiddenToolsBlock(allTools, activeTags) {
|
|
9
9
|
if (!allTools.length)
|
|
@@ -11,14 +11,14 @@ export function buildHiddenToolsBlock(allTools, activeTags) {
|
|
|
11
11
|
const activeSet = new Set(activeTags);
|
|
12
12
|
const visible = new Set();
|
|
13
13
|
for (const tool of allTools) {
|
|
14
|
-
if (tool.alwaysOn || (tool.tags
|
|
14
|
+
if (tool.alwaysOn || (tool.tags?.some((tag) => activeSet.has(tag)))) {
|
|
15
15
|
visible.add(tool.name);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
const hidden = allTools.filter((tool) => !visible.has(tool.name));
|
|
19
19
|
if (hidden.length === 0)
|
|
20
20
|
return "";
|
|
21
|
-
//
|
|
21
|
+
// Группировка по тегам, внутри тега — по имени тула.
|
|
22
22
|
const byTag = new Map();
|
|
23
23
|
for (const tool of hidden) {
|
|
24
24
|
const tags = tool.tags && tool.tags.length > 0 ? tool.tags : ["other"];
|
package/dist/tools/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Точка сборки каталога тулов: импорты, реэкспорты, регистрация. */
|
|
1
2
|
import { ToolRegistry } from "./registry";
|
|
2
3
|
import { ToolExecutor } from "./executor";
|
|
3
4
|
import { readFileTool } from "./read-file";
|
|
@@ -14,29 +15,33 @@ import { bashTool } from "./bash";
|
|
|
14
15
|
import { processListTool } from "./process-list";
|
|
15
16
|
import { processLogTool } from "./process-log";
|
|
16
17
|
import { processKillTool } from "./process-kill";
|
|
18
|
+
import { processWaitTool } from "./process-wait";
|
|
17
19
|
import { subagentTool } from "./subagent";
|
|
18
20
|
import { chunkQueryTool } from "./chunk-query";
|
|
19
21
|
import { webSearchTool } from "./web-search";
|
|
20
22
|
import { webFetchTool } from "./web-fetch";
|
|
21
23
|
import { webBrowseTool } from "./web-browse";
|
|
22
24
|
import { downloadFileTool } from "./download-file";
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
25
|
+
// question/approve — основной набор: question покрывает выбор + свободный
|
|
26
|
+
// текст (с pre-check памяти), approve — явное Yes/No (reject даёт success:false,
|
|
27
|
+
// и цикл трактует это как сигнал сбоя, а не текст ответа).
|
|
28
|
+
import { questionTool } from "./question";
|
|
29
|
+
import { approveTool } from "./approve";
|
|
27
30
|
import { createLoadSkillTool } from "./load-skill";
|
|
28
31
|
import { pipelineRunTool } from "./pipeline-run";
|
|
29
32
|
import { mcpCallTool } from "./mcp-call";
|
|
30
33
|
import { searchHistoryTool } from "./search-history";
|
|
31
34
|
import { rememberTool } from "./remember";
|
|
32
35
|
import { recallTool } from "./recall";
|
|
36
|
+
import { meetDoneTool } from "./meet-done";
|
|
33
37
|
import { createBrowserTool } from "./browser";
|
|
34
38
|
import { attachImageTool } from "./attach-image";
|
|
35
39
|
import { enableToolsTool } from "./enable-tools";
|
|
36
40
|
import { sessionInfoTool } from "./session-info";
|
|
37
41
|
export { ToolRegistry, ToolExecutor };
|
|
38
42
|
export { filterToolsByTags } from "./filter-tools";
|
|
39
|
-
export { readFileTool, writeFileTool, editFileTool, globTool, grepTool, listDirTool, createDirTool, deleteFileTool, moveFileTool, fileInfoTool, bashTool, subagentTool, chunkQueryTool, processListTool, processLogTool, processKillTool, webSearchTool, webFetchTool, webBrowseTool, downloadFileTool, createLoadSkillTool, pipelineRunTool, mcpCallTool, searchHistoryTool, rememberTool, recallTool, createBrowserTool, attachImageTool, enableToolsTool, sessionInfoTool, };
|
|
43
|
+
export { readFileTool, writeFileTool, editFileTool, globTool, grepTool, listDirTool, createDirTool, deleteFileTool, moveFileTool, fileInfoTool, bashTool, subagentTool, chunkQueryTool, processListTool, processLogTool, processKillTool, processWaitTool, webSearchTool, webFetchTool, webBrowseTool, downloadFileTool, createLoadSkillTool, pipelineRunTool, mcpCallTool, searchHistoryTool, rememberTool, recallTool, meetDoneTool, createBrowserTool, attachImageTool, enableToolsTool, sessionInfoTool, questionTool, approveTool, };
|
|
44
|
+
/** Регистрирует все тулы; опционально — on-demand тул и скиллы. */
|
|
40
45
|
export function registerAllTools(registry, skillsModule, opts) {
|
|
41
46
|
const tools = [
|
|
42
47
|
readFileTool,
|
|
@@ -55,6 +60,7 @@ export function registerAllTools(registry, skillsModule, opts) {
|
|
|
55
60
|
processListTool,
|
|
56
61
|
processLogTool,
|
|
57
62
|
processKillTool,
|
|
63
|
+
processWaitTool,
|
|
58
64
|
webSearchTool,
|
|
59
65
|
webFetchTool,
|
|
60
66
|
webBrowseTool,
|
|
@@ -64,10 +70,12 @@ export function registerAllTools(registry, skillsModule, opts) {
|
|
|
64
70
|
searchHistoryTool,
|
|
65
71
|
attachImageTool,
|
|
66
72
|
sessionInfoTool,
|
|
73
|
+
meetDoneTool,
|
|
74
|
+
questionTool,
|
|
75
|
+
approveTool,
|
|
67
76
|
];
|
|
68
|
-
// On-demand
|
|
69
|
-
//
|
|
70
|
-
// with an empty defaultTags this restores the legacy all-tools behavior.
|
|
77
|
+
// On-demand активация — дефолт. При явном enableOnDemand:false тул не
|
|
78
|
+
// регистрируется вовсе — с пустым defaultTags это legacy-режим «все тулы».
|
|
71
79
|
if (opts?.enableOnDemand !== false) {
|
|
72
80
|
tools.push(enableToolsTool);
|
|
73
81
|
}
|
package/dist/tools/list-dir.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
/** Тул листинга каталога (игнор мусора, cap вывода, кешируемый). */
|
|
1
2
|
import { readdirSync, statSync, existsSync } from "fs";
|
|
2
3
|
import { resolve } from "path";
|
|
3
4
|
import { t } from "../i18n/index";
|
|
4
5
|
import { isPathInScope } from "../modules/security/path-validator";
|
|
5
6
|
import { safeResolvePath } from "./path-utils";
|
|
6
7
|
import { MAX_PREVIEW_LINES } from "./preview";
|
|
7
|
-
/**
|
|
8
|
+
/** Каталоги вне выдачи list_dir (едино с walker'ом индексёра). */
|
|
8
9
|
const IGNORED_DIRS = new Set(["node_modules", ".git", "dist", "build", "coverage", ".mma"]);
|
|
10
|
+
/** Показывает файлы/подкаталоги (каталоги с `/`); мусор скрыт. */
|
|
9
11
|
export const listDirTool = {
|
|
10
12
|
name: "list_dir",
|
|
11
13
|
icon: "📂",
|
|
12
14
|
description: `List files and directories in a given path. Shows up to ${MAX_PREVIEW_LINES} entries by default.`,
|
|
13
15
|
tags: ["file"],
|
|
14
16
|
boundedOutput: true,
|
|
17
|
+
cacheable: true,
|
|
15
18
|
parameters: {
|
|
16
19
|
type: "object",
|
|
17
20
|
properties: {
|
|
@@ -22,7 +25,6 @@ export const listDirTool = {
|
|
|
22
25
|
handler: async (ctx, args) => {
|
|
23
26
|
const path = String(args.path);
|
|
24
27
|
const resolved = safeResolvePath(ctx.baseDir, path);
|
|
25
|
-
// Check path permissions
|
|
26
28
|
const scopeCheck = isPathInScope(ctx.baseDir, resolved, ctx.scope, ctx.config.security?.paths);
|
|
27
29
|
if (!scopeCheck.allowed) {
|
|
28
30
|
return {
|
package/dist/tools/load-skill.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
/** Фабрика тула загрузки скилла (инжект в системный промпт). */
|
|
1
2
|
import { t } from "../i18n/index";
|
|
2
3
|
import { estimateTokens } from "../llm/token-counter";
|
|
4
|
+
/**
|
|
5
|
+
* Фабрика тула load_skill. Контент скилла инжектится в системный промпт
|
|
6
|
+
* (не в историю) — переживает компакцию. Возврат: определение тула.
|
|
7
|
+
*/
|
|
3
8
|
export function createLoadSkillTool(skillsModule) {
|
|
4
9
|
return {
|
|
5
10
|
name: "load_skill",
|
|
6
11
|
icon: "🎯",
|
|
7
12
|
tags: ["core"],
|
|
13
|
+
// Роутинг скиллов — вне сужения (P5): модель использует только видимый скилл.
|
|
14
|
+
alwaysOn: true,
|
|
8
15
|
description: "Load a skill by name. Skills provide specialized instructions and workflows. When loaded, the skill content is injected into the system prompt (not conversation history) so it persists through context compaction. Only use when the task clearly requires domain-specific knowledge.",
|
|
9
16
|
parameters: {
|
|
10
17
|
type: "object",
|
package/dist/tools/mcp-call.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
/** Тул вызова тула на MCP-сервере (ленивая регистрация из конфига). */
|
|
2
|
+
import { t } from "../i18n/index";
|
|
1
3
|
import { MCPClient } from "../modules/mcp/client";
|
|
2
4
|
import { MCPRegistry } from "../modules/mcp/registry";
|
|
3
5
|
const registry = new MCPRegistry();
|
|
4
6
|
let initialized = false;
|
|
7
|
+
/** Ленивая регистрация MCP-серверов из конфига (один раз на процесс). */
|
|
5
8
|
function ensureInitialized(ctx) {
|
|
6
9
|
if (initialized)
|
|
7
10
|
return;
|
|
@@ -22,6 +25,7 @@ function ensureInitialized(ctx) {
|
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
}
|
|
28
|
+
/** Вызывает тул на MCP-сервере. Параметры: server, tool, args. */
|
|
25
29
|
export const mcpCallTool = {
|
|
26
30
|
name: "mcp_call",
|
|
27
31
|
icon: "🔗",
|
|
@@ -49,21 +53,28 @@ export const mcpCallTool = {
|
|
|
49
53
|
const available = registry.list();
|
|
50
54
|
return {
|
|
51
55
|
success: false,
|
|
52
|
-
output:
|
|
56
|
+
output: t("tool.mcp_server_not_found", {
|
|
57
|
+
server: serverName,
|
|
58
|
+
available: available.join(", ") || "(none)",
|
|
59
|
+
}),
|
|
53
60
|
};
|
|
54
61
|
}
|
|
62
|
+
const client = new MCPClient(serverConfig);
|
|
55
63
|
try {
|
|
56
|
-
const client = new MCPClient(serverConfig);
|
|
57
64
|
await client.connect();
|
|
58
65
|
const result = await client.callTool(toolName, toolArgs);
|
|
59
|
-
await client.disconnect();
|
|
60
66
|
return {
|
|
61
67
|
success: true,
|
|
62
68
|
output: `MCP call result:\n${JSON.stringify(result, null, 2)}`,
|
|
63
69
|
};
|
|
64
70
|
}
|
|
65
71
|
catch (e) {
|
|
66
|
-
return { success: false, output:
|
|
72
|
+
return { success: false, output: t("tool.mcp_call_failed", { error: e.message }) };
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
// Клиент закрывать всегда: раньше ошибка/таймаут в callTool пропускала
|
|
76
|
+
// disconnect и сиротила stdio-дочерний процесс на сессию.
|
|
77
|
+
await client.disconnect().catch(() => { });
|
|
67
78
|
}
|
|
68
79
|
},
|
|
69
80
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Сентинел завершения meet-интервью: ставит флаг, REPL выходит из режима. */
|
|
2
|
+
import { t } from "../i18n/index";
|
|
3
|
+
/** Модель зовёт по финальному саммари; вне онбординга — no-op по флагу. */
|
|
4
|
+
export const meetDoneTool = {
|
|
5
|
+
name: "meet_done",
|
|
6
|
+
description: "Signal that the get-acquainted interview is complete. Call only after the final summary.",
|
|
7
|
+
tags: ["memory"],
|
|
8
|
+
parameters: { type: "object", properties: {} },
|
|
9
|
+
handler: async (ctx) => {
|
|
10
|
+
if (ctx.onboarding)
|
|
11
|
+
ctx.onboarding.done = true;
|
|
12
|
+
return { success: true, output: t("tool.meet_done") };
|
|
13
|
+
},
|
|
14
|
+
};
|