micro-models-agent 2.10.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 +33 -0
- package/dist/assets/app.js +22 -4
- package/dist/assets/index.html +29 -0
- package/dist/assets/js/dom.js +2 -1
- package/dist/assets/js/feed.js +38 -26
- package/dist/assets/js/format.js +1 -1
- package/dist/assets/js/rail.js +114 -0
- package/dist/assets/js/settings-controls.js +2 -2
- package/dist/assets/js/settings.js +246 -51
- package/dist/assets/js/store.js +3 -0
- package/dist/assets/js/tabs.js +104 -2
- package/dist/assets/styles.css +215 -66
- 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 +106 -21
- package/dist/i18n/index.js +37 -3
- package/dist/i18n/ru.json +109 -21
- 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 +24285 -22447
- 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/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,39 @@ All notable changes to Micro Models Agent (MMA) will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.12.0] - 2026-09-29
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Session-bound plans** (`src/modules/execution/plan-store.ts`, `module.ts`, `src/core/bootstrap/modules-phase.ts`, `src/cli/repl-commands.ts`, `src/modules/webui/sessions-api.ts`, `state.ts`, `module.ts`, `assets/js/tabs.js`): the active plan is now stored per session (`.mma/plans/sessions/<sessionId>/active.json`) instead of a single project-global `active.json`. Switching sessions (`/resume`, `/new`, `POST /api/sessions/activate` / `POST /api/sessions`) moves the `ExecutionModule` tracker to that session's plan (new sessions start plan-less, `/resume` prints a `◇ <plan>` status line); deleting a session drops its plan slot. Plan tools writing past `setPlan` (`abort`/`switch`/`delete`/`purge`) and internal saves mirror the slot, so an aborted plan never resurrects on return. Drafts/archive stay a shared library; the legacy global plan is adopted by the active session on first start after upgrade. Web sidebar refreshes immediately after tab switch instead of waiting for the 2s poll. Spec: `docs/specs/2026-09-29-session-plan-binding-design.md`.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **Provider identity sync on swap** (`src/modules/providers/manager.ts`, `src/config/registry.ts`, `src/core/agent.ts`): switching `provider.active` now mirrors the legacy flat fields (`baseUrl`/`apiKey`/`type`) from the active entry, closing the desync where banner and probes used a stale flat endpoint (e.g. `localhost:1234` while `opencode-go` was active); `reasoning_effort` is normalized and the reasoning strategy refreshed on provider swap; assistant `tool_calls` are kept paired with their tool results.
|
|
16
|
+
|
|
17
|
+
## [2.11.0] - 2026-09-28
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Plan contracts for small models: `plan_step` tool + per-step `checks`** (`src/modules/execution/plan-tool.ts`, `plan-actions.ts`, `plan-checks.ts`, `planner.ts`, `plan-steps.ts`, `module.ts`): `plan create`/`re-plan` now require `checks` 1:1 with steps (`file-exists:<path>` hard-verified on done via `StepVerifier`, `command:<cmd>`/`manual:<text>` self-certified with an explicit note; delete-kind inverts the file check). New alwaysOn tool `plan_step step=N status=done|failed|skipped` replaces `plan update step=` for status changes (no `action` parameter to confuse; old form keeps working as an alias) and is wired everywhere `plan`/`todo` are (alignment exemption, stuck-detector read-only set, bookkeeping key, terminal checklist refresh, web plan snapshot, meta-color sets). `plan` coverage validation is now a hard block (`plan.coverage_blocked`, validated before any state mutation so a rejected create leaks no active plan). `kinds` removed from the model-facing schema — create/delete intent is fully auto-detected (`switchStepKind` both directions: verified deletions flip to delete, never-deleted-missing files flip back to create). `todo done` accepts `ids=[...]` (list/add print `[id]`); text matching stays as fallback. Step checks render as `↳ check:` in the prompt block; system prompt and all model-facing `plan update` directives now teach `plan_step`; i18n en+ru (`plan.checks_*`, `plan.check_failed`, `plan.check_self_certified`, `plan.coverage_blocked`, `plan.step_required`, `todo.subtask_id_not_found`).
|
|
22
|
+
|
|
23
|
+
- **Memory-aware `question` tool in the core set** (`src/tools/question.ts`, `src/tools/index.ts`, `src/core/system-prompt.ts`, `src/i18n/en.json`, `src/i18n/ru.json`): single/multi-choice and free-text prompts now registered in `registerAllTools()` (visible in REPL and web UI; `approve` registered alongside for explicit Yes/No — reject returns `success:false` so the loop treats it as a failure signal). The handler pre-checks agent memory itself (`splitByMemory` over `MemoryStore.search`, fail-open) — questions memory already answers are reported, not asked; answers live only in the session (persist via `remember` only when asked to); at most `MAX_QUESTIONS_PER_CALL = 3` unknown questions per call with a re-call note. System prompt carries a one-line `ASK RULE`; REPL rendering already matched `STYLE.md`, web rendering reuses `feed.js onQuestion`.
|
|
24
|
+
|
|
25
|
+
- **Activity rail above the composer** (`src/modules/webui/assets/js/rail.js`, `index.html`, `styles.css`, `app.js`, `tabs.js`, `settings.js`): an indicator that lives for the whole turn — indeterminate scanner with phase/elapsed/tool & event counters when no plan exists, honest `done/total` progress with step ticks when an MoE plan is active, and a short flash on every real SSE event (`tool_start`/`tool_end`/`text`/`plan`). Layouts `off|line|meta|full` via the new config key `ui.activityRail` (default `line`), editable in `/config` and web Settings → Chat output and applied live; en/ru localized, `prefers-reduced-motion` respected, phase announced politely (`role="status"`, timer/counters `aria-hidden`). Spec: `docs/specs/2026-09-27-activity-rail-design.md`.
|
|
26
|
+
|
|
27
|
+
- **Web chat font size** (`src/config/types.ts`, `defaults.ts`, `registry-extra.ts`, `src/modules/webui/assets/styles.css`, `assets/js/settings.js`, `app.js`, `src/i18n/en.json`, `ru.json`): new `ui.fontSize` key (`compact` = 13px / `comfortable` = 15px / `large` = 17px, default `comfortable`), editable via `/config`, `mma config set` and web Settings → Chat output; applied live through `body[data-font]` without a reload (unknown values fall back to the default). Web-only — the terminal is unaffected.
|
|
28
|
+
|
|
29
|
+
- **Composer selector switches with loaders + 4th reasoning selector** (`src/modules/webui/reasoning-view.ts`, `config-api.ts`, `assets/js/settings.js`, `store.js`, `index.html`, `styles.css`, `src/i18n/en.json`, `ru.json`): switching provider/model/context/reasoning now paints a pending mark (`⋯` + `aria-busy`, all selector menus inert) from click until config + model list are re-read (provider/model re-reads run in parallel; context/reasoning skip the model round-trip), with single-flight (double-click answers `web.selectors.switch_busy`) and a stale-guard so a slow A→B→A never repaints over the fresh state; boot shows the same mark instead of bare `—`. `GET /api/models` additively carries `reasoning: {strategy, supported, mode}` (strategy from the active provider preset via entries, `supported` from the probe cache, `null` until probed), rendered as a 4th row showing only supported levels (`openai-effort` → full set, `prompt-tag`/`template-kwarg` → coarse set without `medium`/`max`); `strategy: "none"` hides the row, a failed probe shows an honest `off` mark with a shortcut to Settings → Reasoning. Spec: `docs/specs/2026-09-28-web-selector-loaders-reasoning-design.md`.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **Internal loop diagnostics are verbose-only** (`src/logger/app-logger.ts`, `src/output/channel.ts`, `src/cli/main.ts`, `src/cli/repl-commands.ts`): new `Logger.diagnostic(level, msg, meta)` marks loop internals (hallucination retries, audit/compaction notes, repeated-tool nudges, MoE/critic internals, `LLM warning`) with `data.diagnostic` on the output bus. `OutputChannel.setShowDiagnostics()` drops them unless `ui.verbosity === "verbose"`, so chat shows user-facing notices only; file logging (`.log`, `app.jsonl`) is unchanged and diagnostics stay diagnosable. `/config ui.verbosity` now also hides `info` logs outside verbose, matching the startup rule.
|
|
34
|
+
- **Critic verdict no longer renders in chat** (`src/core/agent/critic-gate.ts`, `src/ui/renderer.ts`, `src/modules/webui/forward.ts`, `assets/app.js`, `assets/js/feed.js`): `Renderer.criticVerdict`, the SSE `critic` event, the `onCritic` UI callback and the `ui.critic_*`/`web.critic_*` i18n keys are removed. The verdict remains in `session.jsonl` (`critic_check`/`critic_verdict`/`critic_escalation`) and as a verbose diagnostic line; model-facing repair/advice still goes through `<system-summary>` only.
|
|
35
|
+
- **Hallucination uncertainty line follows the same rule** (`src/core/agent/hallucination-gate.ts`): the `[⚠️ Uncertainty]` meta line is rendered only in verbose mode; the model still receives the retry context.
|
|
36
|
+
- **Web quiet hides model-facing tool bodies** (`src/core/types.ts`, `src/core/agent/tool-batch.ts`, `src/modules/webui/forward.ts`, `run-agent.ts`, `assets/app.js`, `assets/js/feed.js`, `src/tools/question.ts`): `onMeta` carries an optional `MetaKind` (`tool` for display/output/diff/failure-gist from `ToolBatch`, `status` otherwise); the SSE `meta` event tags tool bodies with `kind: "tool"` (status events stay wire-identical) and `feed.js onMeta` drops them in `quiet`, mirroring the terminal renderer. `question` returns `display: ""` so its model directives (memory/session/batch rules) never echo — the model still gets the full `output` in `role:"tool"`. Plan/file/question cards and the single `↳` failure cause are unaffected. Spec: `docs/specs/2026-09-28-web-quiet-tool-meta-design.md`.
|
|
37
|
+
- **System prompt routes questions through tools, not plain text** (`src/core/system-prompt.ts`, `src/tools/question.ts`): observed in `ses_mukw2cxn` — the model asked a choice question as a chat dash-list instead of calling `question`, so no interactive buttons appeared. `SCOPE`/`STOP AND ASK` now mandate the `question` tool (options when variants are known), `PROTECTED PATHS` mandates `approve`; plain text remains only as a headless fallback. The `question` description itself now forbids plain-text choice lists.
|
|
38
|
+
- **Web default font size 13px → 15px** (`src/modules/webui/assets/styles.css`): the `body` base size moves to the new `comfortable` step; `compact` restores the old 13px via `body[data-font]`.
|
|
39
|
+
|
|
7
40
|
## [2.10.0] - 2026-09-27
|
|
8
41
|
|
|
9
42
|
### Added
|
package/dist/assets/app.js
CHANGED
|
@@ -4,7 +4,7 @@ import { I18N, t, loadI18n } from "./js/i18n.js";
|
|
|
4
4
|
import { S, hooks } from "./js/store.js";
|
|
5
5
|
import {
|
|
6
6
|
onText, onReasoning, onMeta, onPhase, onToolStart, onToolEnd,
|
|
7
|
-
onTurnEnd, onErrorEvent, onCommandOutput, onLog,
|
|
7
|
+
onTurnEnd, onErrorEvent, onCommandOutput, onLog, onPlan, onQuestion,
|
|
8
8
|
showEmptyFeed, renderPlan, renderUsage, renderEnvironment, renderWorkspace,
|
|
9
9
|
feedHasContent, loadHistory,
|
|
10
10
|
} from "./js/feed.js";
|
|
@@ -14,8 +14,11 @@ loadCommands,
|
|
|
14
14
|
} from "./js/tabs.js";
|
|
15
15
|
import {
|
|
16
16
|
renderSelectors, renderSettings, loadConfig, loadModels, loadProviders,
|
|
17
|
-
loadMemory, loadSkills, loadPlugins, applyTheme, currentTheme, setConnStatus,
|
|
17
|
+
loadMemory, loadSkills, loadPlugins, applyTheme, currentTheme, applyFontSize, setConnStatus,
|
|
18
18
|
} from "./js/settings.js";
|
|
19
|
+
import {
|
|
20
|
+
initRail, setPlan as railPlan, railEvent, applyRailI18n,
|
|
21
|
+
} from "./js/rail.js";
|
|
19
22
|
|
|
20
23
|
document.querySelectorAll("[data-collapse]").forEach((head) => {
|
|
21
24
|
const initArrow = head.querySelector(".arrow");
|
|
@@ -64,6 +67,7 @@ function renderState(snapshot, busy) {
|
|
|
64
67
|
if (sessionId) updateTabName(sessionId, S.state.host.sessionName);
|
|
65
68
|
if (!S.tabs.length) showEmptyFeed();
|
|
66
69
|
renderPlan(S.state.host.plan);
|
|
70
|
+
railPlan(busy && snapshot ? snapshot.plan : null);
|
|
67
71
|
renderUsage(S.state.host);
|
|
68
72
|
// Late provider auto-detect may change the effective window after boot —
|
|
69
73
|
// the snapshot carries it so the topbar follows without a config re-fetch.
|
|
@@ -120,13 +124,12 @@ function connectSSE() {
|
|
|
120
124
|
// checks and stay bespoke below; everything else is `parse → null-guard → call`.
|
|
121
125
|
const handlers = [
|
|
122
126
|
["text", (d) => onText(d.chunk || "", d.sessionId)],
|
|
123
|
-
["meta", (d) => onMeta(d.chunk || "", d.sessionId)],
|
|
127
|
+
["meta", (d) => onMeta(d.chunk || "", d.sessionId, d.kind)],
|
|
124
128
|
["reasoning", (d) => onReasoning(d.chunk || "", d.sessionId)],
|
|
125
129
|
["phase", (d) => onPhase(d.phase, d.sessionId)],
|
|
126
130
|
["tool_start", onToolStart],
|
|
127
131
|
["tool_end", onToolEnd],
|
|
128
132
|
["plan", onPlan],
|
|
129
|
-
["critic", onCritic],
|
|
130
133
|
["question", onQuestion],
|
|
131
134
|
["turn_end", onTurnEnd],
|
|
132
135
|
["log", onLog],
|
|
@@ -137,6 +140,15 @@ for (const [event, fn] of handlers) {
|
|
|
137
140
|
if (d) fn(d);
|
|
138
141
|
});
|
|
139
142
|
}
|
|
143
|
+
// Activity rail: its own listeners — feed handlers stay untouched.
|
|
144
|
+
for (const ev of ["tool_start", "tool_end", "text", "plan"]) {
|
|
145
|
+
es.addEventListener(ev, (e) => {
|
|
146
|
+
const d = parse(e);
|
|
147
|
+
if (!d) return;
|
|
148
|
+
if (ev === "plan") railPlan(d);
|
|
149
|
+
else railEvent(ev, d.name);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
140
152
|
es.addEventListener("command", (e) => {
|
|
141
153
|
const d = parse(e);
|
|
142
154
|
if (d && typeof d.text === "string") onCommandOutput(d.text, d.sessionId);
|
|
@@ -188,6 +200,9 @@ function applyStaticI18n() {
|
|
|
188
200
|
closeSettings: ["x", t("web.topbar.close")],
|
|
189
201
|
sessNew: ["plus", t("web.sessions.new")],
|
|
190
202
|
sessRefresh: ["refresh", t("web.sessions.refresh")],
|
|
203
|
+
sessPrev: ["chevron-left", t("web.sessbar.prev")],
|
|
204
|
+
sessNext: ["chevron-right", t("web.sessbar.next")],
|
|
205
|
+
sessClose: ["x", t("web.topbar.close")],
|
|
191
206
|
};
|
|
192
207
|
Object.keys(controls).forEach((id) => {
|
|
193
208
|
const node = document.getElementById(id);
|
|
@@ -223,6 +238,7 @@ function applyStaticI18n() {
|
|
|
223
238
|
|
|
224
239
|
renderSelectors();
|
|
225
240
|
renderSessionsDropdown();
|
|
241
|
+
applyRailI18n();
|
|
226
242
|
if (msgs.querySelector(".empty")) showEmptyFeed();
|
|
227
243
|
if (connStatus && !connStatus.hidden) setConnStatus(true);
|
|
228
244
|
}
|
|
@@ -242,11 +258,13 @@ async function boot() {
|
|
|
242
258
|
await loadI18n();
|
|
243
259
|
await loadCommands();
|
|
244
260
|
applyTheme(currentTheme());
|
|
261
|
+
applyFontSize();
|
|
245
262
|
applyStaticI18n();
|
|
246
263
|
showEmptyFeed();
|
|
247
264
|
renderSelectors();
|
|
248
265
|
renderSettings();
|
|
249
266
|
await loadConfig();
|
|
267
|
+
initRail(S.state.config && S.state.config.ui ? S.state.config.ui.activityRail : undefined);
|
|
250
268
|
await loadModels();
|
|
251
269
|
await loadProviders();
|
|
252
270
|
await loadSessions();
|
package/dist/assets/index.html
CHANGED
|
@@ -31,12 +31,37 @@
|
|
|
31
31
|
<span class="conn" id="connStatus" role="status" aria-live="polite" hidden></span>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
|
+
<div class="bar-sub" id="sessBar">
|
|
35
|
+
<button class="icon-btn" id="sessPrev" type="button">‹</button>
|
|
36
|
+
<button class="sess-name" id="sessNameBtn" type="button"><span id="sessName">—</span></button>
|
|
37
|
+
<button class="icon-btn" id="sessNext" type="button">›</button>
|
|
38
|
+
<button class="icon-btn" id="sessClose" type="button">✕</button>
|
|
39
|
+
<span class="sess-tools" id="sessTools"></span>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
34
42
|
<div class="layout">
|
|
35
43
|
<div class="chat">
|
|
36
44
|
<div class="msgs" id="msgs" role="log" aria-label="conversation"></div>
|
|
37
45
|
<div class="visually-hidden" id="live" role="status" aria-live="polite" aria-atomic="true"></div>
|
|
38
46
|
|
|
39
47
|
<div class="input-area">
|
|
48
|
+
<div class="rail-wrap l-line" id="railWrap" role="status" aria-live="polite" hidden>
|
|
49
|
+
<div class="rail-l1">
|
|
50
|
+
<span class="lab" id="railPhase">✦ thinking</span>
|
|
51
|
+
<span class="s" aria-hidden="true">·</span><span class="time" id="railTime" aria-hidden="true">0.0s</span>
|
|
52
|
+
<span class="s" aria-hidden="true">·</span><span class="st" id="railSteps" aria-hidden="true">no plan</span>
|
|
53
|
+
<span class="right" id="railEsc" aria-hidden="true">Esc — stop</span>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="rl-track" id="railTrack" data-mode="scan">
|
|
56
|
+
<div class="rl-fill" id="railFill"></div>
|
|
57
|
+
<div class="rl-scan"></div>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="rail-l2" aria-hidden="true">
|
|
60
|
+
<span class="tools" id="railTools">0 tools</span>
|
|
61
|
+
<span class="s">·</span><span class="events" id="railEvents">0 events</span>
|
|
62
|
+
<span class="s">·</span><span class="last" id="railLast">—</span>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
40
65
|
<div class="selectors">
|
|
41
66
|
<div class="sel" data-sel="provider">
|
|
42
67
|
<button id="selProviderBtn">provider: <b>—</b> ▾</button>
|
|
@@ -50,6 +75,10 @@
|
|
|
50
75
|
<button id="selContextBtn">context: <b>—</b> ▾</button>
|
|
51
76
|
<div class="menu" id="selContextMenu"></div>
|
|
52
77
|
</div>
|
|
78
|
+
<div class="sel" data-sel="reasoning">
|
|
79
|
+
<button id="selReasoningBtn">reasoning: <b>—</b> ▾</button>
|
|
80
|
+
<div class="menu" id="selReasoningMenu"></div>
|
|
81
|
+
</div>
|
|
53
82
|
</div>
|
|
54
83
|
<input type="file" id="imgPicker" accept="image/*" multiple hidden>
|
|
55
84
|
<div class="attach-strip" id="attachStrip" hidden></div>
|
package/dist/assets/js/dom.js
CHANGED
|
@@ -67,7 +67,8 @@ refresh: [
|
|
|
67
67
|
["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }],
|
|
68
68
|
["path", { d: "M8 21H3v-5" }],
|
|
69
69
|
],
|
|
70
|
-
"chevron-down": [["path", { d: "m6 9 6 6 6-6" }]],
|
|
70
|
+
"chevron-down": [["path", { d: "m6 9 6 6 6-6" }]],
|
|
71
|
+
"chevron-left": [["path", { d: "m15 18-6-6 6-6" }]],
|
|
71
72
|
"chevron-right": [["path", { d: "m9 18 6-6-6-6" }]],
|
|
72
73
|
search: [
|
|
73
74
|
["circle", { cx: 11, cy: 11, r: 8 }],
|
package/dist/assets/js/feed.js
CHANGED
|
@@ -247,8 +247,12 @@ export function onReasoning(chunk, sid) {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
// Generic agent status (context stats, compaction, MoE status, warnings):
|
|
250
|
-
// always visible, one dim line per chunk, never collapsed.
|
|
251
|
-
|
|
250
|
+
// always visible, one dim line per chunk, never collapsed. Tool bodies
|
|
251
|
+
// (`kind: "tool"` — display/output/diff/failure-gist from ToolBatch) are
|
|
252
|
+
// model-facing and hidden in quiet mode, mirroring the terminal renderer
|
|
253
|
+
// (`writeInlineBody`); failures still surface once via `tool_end` ↳ cause.
|
|
254
|
+
export function onMeta(chunk, sid, kind) {
|
|
255
|
+
if (kind === "tool" && verbosity() === "quiet") return;
|
|
252
256
|
const feed = feedForEvent(sid);
|
|
253
257
|
clearBusy(feed);
|
|
254
258
|
const text = (chunk || "").trim();
|
|
@@ -343,14 +347,39 @@ function cardFor(name, args, sid) {
|
|
|
343
347
|
card.appendChild(top);
|
|
344
348
|
const bottom = el("div", "fc-bottom");
|
|
345
349
|
bottom.appendChild(el("span", "lab", labelOf(name)));
|
|
350
|
+
const actions = el("span", "fc-actions");
|
|
351
|
+
const baseName = String(path.split(/[\\/]/).pop() || path);
|
|
346
352
|
if (OPENABLE_TOOLS.indexOf(name) !== -1) {
|
|
347
353
|
const openLink = el("a", "fc-open", t("web.card.open"));
|
|
348
354
|
openLink.href = "/api/file?path=" + encodeURIComponent(path);
|
|
349
355
|
openLink.target = "_blank";
|
|
350
356
|
openLink.rel = "noopener noreferrer";
|
|
351
|
-
|
|
357
|
+
openLink.title = t("web.card.open_title");
|
|
358
|
+
actions.appendChild(openLink);
|
|
359
|
+
const dlLink = el("a", "fc-open", t("web.card.download"));
|
|
360
|
+
dlLink.href = "/api/file?path=" + encodeURIComponent(path) + "&download=1";
|
|
361
|
+
dlLink.title = t("web.card.download_title");
|
|
362
|
+
dlLink.setAttribute("download", baseName);
|
|
363
|
+
actions.appendChild(dlLink);
|
|
352
364
|
}
|
|
365
|
+
const copyBtn = el("button", "fc-open", t("web.card.copy_path"));
|
|
366
|
+
copyBtn.type = "button";
|
|
367
|
+
copyBtn.title = t("web.card.copy_title");
|
|
368
|
+
copyBtn.addEventListener("click", () => {
|
|
369
|
+
copyText(path).then((ok) => {
|
|
370
|
+
copyBtn.textContent = ok ? "✓ " + t("web.code.copied") : "⚠ " + t("web.code.copy_failed");
|
|
371
|
+
window.setTimeout(() => {
|
|
372
|
+
copyBtn.textContent = t("web.card.copy_path");
|
|
373
|
+
}, 1400);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
actions.appendChild(copyBtn);
|
|
377
|
+
bottom.appendChild(actions);
|
|
353
378
|
card.appendChild(bottom);
|
|
379
|
+
if (/\.drawio(\.xml)?$/i.test(path)) {
|
|
380
|
+
const hint = el("div", "fc-hint", t("web.card.drawio_hint"));
|
|
381
|
+
card.appendChild(hint);
|
|
382
|
+
}
|
|
354
383
|
appendTo(feed, card);
|
|
355
384
|
return card;
|
|
356
385
|
}
|
|
@@ -507,6 +536,9 @@ export function onCommandOutput(text, sid) {
|
|
|
507
536
|
// `textContent` so nothing untrusted is parsed as HTML.
|
|
508
537
|
export function onLog(data) {
|
|
509
538
|
if (!data || typeof data.text !== "string" || !data.text) return;
|
|
539
|
+
// Internal loop diagnostics (retry counters, audit/compaction internals) are
|
|
540
|
+
// session-log material — the chat shows them only in verbose mode.
|
|
541
|
+
if (data.diagnostic && verbosity() !== "verbose") return;
|
|
510
542
|
const feed = feedForEvent(data.sessionId) || activeFeed();
|
|
511
543
|
if (!feed) return;
|
|
512
544
|
const level = data.level;
|
|
@@ -518,29 +550,9 @@ export function onLog(data) {
|
|
|
518
550
|
if (level === "error" || level === "warn") announce(data.text);
|
|
519
551
|
}
|
|
520
552
|
|
|
521
|
-
// In-loop critic
|
|
522
|
-
//
|
|
523
|
-
//
|
|
524
|
-
export function onCritic(data) {
|
|
525
|
-
if (!data || (data.status !== "concern" && data.status !== "critical")) return;
|
|
526
|
-
const level = verbosity();
|
|
527
|
-
if (level === "quiet") return;
|
|
528
|
-
const feed = feedForEvent(data.sessionId) || activeFeed();
|
|
529
|
-
if (!feed) return;
|
|
530
|
-
const critical = data.status === "critical" || data.repair === true;
|
|
531
|
-
const label = critical
|
|
532
|
-
? t("web.critic_repair")
|
|
533
|
-
: pluralCount("web.critic_concern", Number(data.issueCount) || 0);
|
|
534
|
-
const line = el("div", critical ? "warnline" : "detail");
|
|
535
|
-
line.textContent = (critical ? "⚠ " : "⟡ ") + label;
|
|
536
|
-
appendTo(feed, line);
|
|
537
|
-
if (level === "verbose" && typeof data.summary === "string" && data.summary) {
|
|
538
|
-
const detail = el("div", "detail");
|
|
539
|
-
detail.textContent = "↳ " + data.summary;
|
|
540
|
-
appendTo(feed, detail);
|
|
541
|
-
}
|
|
542
|
-
if (critical) announce(label);
|
|
543
|
-
}
|
|
553
|
+
// In-loop critic verdicts are session-log only (`critic_verdict` in
|
|
554
|
+
// `session.jsonl`): the chat keeps user-facing notices and verbose-mode
|
|
555
|
+
// diagnostics, not verifier verdicts.
|
|
544
556
|
|
|
545
557
|
function renderAssistantText(feed, text) {
|
|
546
558
|
const raw = String(text == null ? "" : text);
|
package/dist/assets/js/format.js
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Activity rail — the indicator above the composer for the whole `busy` period.
|
|
2
|
+
//
|
|
3
|
+
// The in-feed `.busy` line clears on the first `text` event; the rail lives
|
|
4
|
+
// until the turn ends and shows only what we actually know: phase, elapsed,
|
|
5
|
+
// plan progress when a plan exists (MoE), tool/event counters. Without a plan
|
|
6
|
+
// the rail is an indeterminate scanner — no invented percentages.
|
|
7
|
+
// Layouts: off | line (default) | meta | full — see docs/specs/2026-09-27-activity-rail-design.md.
|
|
8
|
+
|
|
9
|
+
import { t, pluralCount } from "./i18n.js";
|
|
10
|
+
import { labelOf } from "./format.js";
|
|
11
|
+
|
|
12
|
+
const LAYOUTS = ["off", "line", "meta", "full"];
|
|
13
|
+
|
|
14
|
+
let root = null, trackEl = null, fillEl = null;
|
|
15
|
+
let labEl = null, timeEl = null, stepsEl = null, escEl = null;
|
|
16
|
+
let toolsEl = null, eventsEl = null, lastEl = null;
|
|
17
|
+
let layout = "line";
|
|
18
|
+
let busy = false, startedAt = 0;
|
|
19
|
+
let tools = 0, events = 0, lastTool = "";
|
|
20
|
+
let sawText = false, pendingTool = false;
|
|
21
|
+
let plan = null;
|
|
22
|
+
let timer = null;
|
|
23
|
+
|
|
24
|
+
function render() {
|
|
25
|
+
if (!root) return;
|
|
26
|
+
root.hidden = layout === "off" || !busy;
|
|
27
|
+
if (root.hidden) return;
|
|
28
|
+
const phase = pendingTool ? "tool" : sawText ? "composing" : "thinking";
|
|
29
|
+
root.classList.toggle("phase-tool", phase === "tool");
|
|
30
|
+
root.classList.toggle("phase-compose", phase === "composing");
|
|
31
|
+
labEl.textContent = "✦ " + (phase === "tool" ? t("web.rail.working")
|
|
32
|
+
: phase === "composing" ? t("web.rail.composing") : t("web.action.thinking"));
|
|
33
|
+
timeEl.textContent = ((Date.now() - startedAt) / 1000).toFixed(1) + "s";
|
|
34
|
+
const steps = plan && Array.isArray(plan.steps) ? plan.steps : [];
|
|
35
|
+
if (steps.length > 0) {
|
|
36
|
+
const done = steps.filter((s) => s && s.status === "done").length;
|
|
37
|
+
trackEl.dataset.mode = "plan";
|
|
38
|
+
fillEl.style.setProperty("--prog", String((done / steps.length) * 100));
|
|
39
|
+
stepsEl.textContent = t("web.rail.step_of", { cur: Math.min(done + 1, steps.length), total: steps.length });
|
|
40
|
+
} else {
|
|
41
|
+
trackEl.dataset.mode = "scan";
|
|
42
|
+
stepsEl.textContent = t("web.rail.no_plan");
|
|
43
|
+
}
|
|
44
|
+
toolsEl.textContent = pluralCount("web.rail.tools", tools);
|
|
45
|
+
eventsEl.textContent = pluralCount("web.rail.events", events);
|
|
46
|
+
lastEl.textContent = lastTool ? t("web.rail.last") + " " + lastTool : t("web.rail.none");
|
|
47
|
+
escEl.textContent = t("web.input.esc");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function flash() {
|
|
51
|
+
if (!trackEl || !busy) return;
|
|
52
|
+
trackEl.classList.remove("flash");
|
|
53
|
+
void trackEl.offsetWidth;
|
|
54
|
+
trackEl.classList.add("flash");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function initRail(cfgLayout) {
|
|
58
|
+
root = document.getElementById("railWrap");
|
|
59
|
+
if (!root) return;
|
|
60
|
+
trackEl = root.querySelector(".rl-track");
|
|
61
|
+
fillEl = root.querySelector(".rl-fill");
|
|
62
|
+
labEl = root.querySelector(".lab");
|
|
63
|
+
timeEl = root.querySelector(".time");
|
|
64
|
+
stepsEl = root.querySelector(".st");
|
|
65
|
+
escEl = root.querySelector(".right");
|
|
66
|
+
toolsEl = root.querySelector(".tools");
|
|
67
|
+
eventsEl = root.querySelector(".events");
|
|
68
|
+
lastEl = root.querySelector(".last");
|
|
69
|
+
setLayout(cfgLayout);
|
|
70
|
+
if (!timer) timer = setInterval(render, 250);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function setLayout(next) {
|
|
74
|
+
layout = LAYOUTS.includes(next) ? next : "line";
|
|
75
|
+
if (!root) return;
|
|
76
|
+
root.classList.remove("l-line", "l-meta", "l-full");
|
|
77
|
+
root.classList.add("l-" + layout);
|
|
78
|
+
const inpMeta = document.querySelector(".inp-meta");
|
|
79
|
+
const inputArea = document.querySelector(".input-area");
|
|
80
|
+
if (layout === "meta" && inpMeta && root.parentElement !== inpMeta) {
|
|
81
|
+
inpMeta.prepend(root);
|
|
82
|
+
} else if (layout !== "meta" && inputArea && root.parentElement !== inputArea) {
|
|
83
|
+
const selectors = inputArea.querySelector(".selectors");
|
|
84
|
+
inputArea.insertBefore(root, selectors || inputArea.firstChild);
|
|
85
|
+
}
|
|
86
|
+
render();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function setBusy(on) {
|
|
90
|
+
const next = !!on;
|
|
91
|
+
if (next && !busy) {
|
|
92
|
+
startedAt = Date.now();
|
|
93
|
+
tools = 0; events = 0; lastTool = "";
|
|
94
|
+
sawText = false; pendingTool = false; plan = null;
|
|
95
|
+
}
|
|
96
|
+
busy = next;
|
|
97
|
+
render();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function setPlan(p) {
|
|
101
|
+
plan = p && Array.isArray(p.steps) && p.steps.length > 0 ? p : null;
|
|
102
|
+
render();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function railEvent(kind, name) {
|
|
106
|
+
events += 1;
|
|
107
|
+
if (kind === "tool_start") { pendingTool = true; lastTool = labelOf(name); }
|
|
108
|
+
else if (kind === "tool_end") { pendingTool = false; tools += 1; lastTool = labelOf(name); }
|
|
109
|
+
else if (kind === "text") sawText = true;
|
|
110
|
+
flash();
|
|
111
|
+
render();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function applyRailI18n() { render(); }
|
|
@@ -402,7 +402,7 @@ export const PANEL_SECTIONS = {
|
|
|
402
402
|
],
|
|
403
403
|
agent: [
|
|
404
404
|
{ id: "agent.moe", titleKey: "web.settings.sec.agent.moe", descKey: "web.settings.sec.agent.moe.desc", keys: ["moe.enabled", "moe.maxReplanCycles", "experts"] },
|
|
405
|
-
{ id: "agent.critic", titleKey: "web.settings.sec.agent.critic", descKey: "web.settings.sec.agent.critic.desc", keys: ["critic.enabled", "critic.maxCalls", "critic.maxRepairCycles", "critic.timeoutMs"] },
|
|
405
|
+
{ id: "agent.critic", titleKey: "web.settings.sec.agent.critic", descKey: "web.settings.sec.agent.critic.desc", keys: ["critic.enabled", "critic.model", "critic.provider", "critic.tools", "critic.maxCalls", "critic.maxRepairCycles", "critic.timeoutMs"] },
|
|
406
406
|
{ id: "agent.tools", titleKey: "web.settings.sec.agent.tools", descKey: "web.settings.sec.agent.tools.desc", keys: ["tools.enableOnDemand", "tools.defaultTags", "skills.budget"] },
|
|
407
407
|
{ id: "agent.subagent", titleKey: "web.settings.sec.agent.subagent", descKey: "web.settings.sec.agent.subagent.desc", keys: ["subagent.resultMode", "subagent.maxSummaryChars", "subagent.maxParallelChunkQueries", "subagent.stableSystemPrompt"] },
|
|
408
408
|
{ id: "agent.hallucination", titleKey: "web.settings.sec.agent.hallucination", descKey: "web.settings.sec.agent.hallucination.desc", keys: ["hallucination.judge.enabled"] },
|
|
@@ -421,7 +421,7 @@ export const PANEL_SECTIONS = {
|
|
|
421
421
|
{ id: "sessions.isolation", titleKey: "web.settings.sec.sessions.isolation", descKey: "web.settings.sec.sessions.isolation.desc", keys: ["sessionIsolation.enabled", "sessionIsolation.isolatePlugins", "sessionIsolation.isolateTempFiles"] },
|
|
422
422
|
],
|
|
423
423
|
ui: [
|
|
424
|
-
{ id: "ui.chat", titleKey: "web.settings.sec.ui.chat", descKey: "web.settings.sec.ui.chat.desc", keys: ["ui.spinner", "ui.showContextStats", "ui.showCompaction"] },
|
|
424
|
+
{ id: "ui.chat", titleKey: "web.settings.sec.ui.chat", descKey: "web.settings.sec.ui.chat.desc", keys: ["ui.fontSize", "ui.activityRail", "ui.spinner", "ui.showContextStats", "ui.showCompaction"] },
|
|
425
425
|
],
|
|
426
426
|
security: [
|
|
427
427
|
{ id: "security.switches", titleKey: "web.settings.sec.security.switches", descKey: "web.settings.sec.security.switches.desc", keys: ["security.enabled", "security.bash.enabled", "security.bash.blockDangerousFlags", "security.paths.enabled", "security.contentScan.enabled", "security.network.enabled", "security.sessionEncryption.enabled"] },
|