Skip to content

Stabilize provider routing and quality checks#110

Merged
F0RLE merged 54 commits into
nightlyfrom
F0RLE/code-quality-stabilization
May 29, 2026
Merged

Stabilize provider routing and quality checks#110
F0RLE merged 54 commits into
nightlyfrom
F0RLE/code-quality-stabilization

Conversation

@F0RLE

@F0RLE F0RLE commented May 21, 2026

Copy link
Copy Markdown
Owner

Summary

Summary by CodeRabbit

  • New Features

    • Trusted local Agent Control (profiles, one‑time tokens, approvals, audit logs), Agent console view, repair action, integration draft creation, and a backend catalog snapshot API.
  • Localization

    • Added EN/RU/ZH strings for debug logs, console controls, Agent tab, OpenRouter/key management, custom model cards, and Agent Control UI.
  • Improvements

    • Console: agent view, localized empty states, safer folder handling. AI: provider resolution, streaming, local-context budgeting, timeout/local-endpoint handling. Settings/catalog: provider policy, secure-key/service flows.
  • Tests

    • Expanded coverage across AI, console, catalog snapshot, Agent Control, integration API, and settings.
  • Chores

    • CI workflows pinned; added cross‑platform CI job.

Review Change Stack

@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 1 package(s) with unknown licenses.
See the Details below.

License Issues

src-tauri/Cargo.toml

PackageVersionLicenseIssue Type
libc>= 0.2.178, < 0.3.0NullUnknown License

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/checkout de0fac2e4500dabe0009e67214ff5f5447ce83dd 🟢 5.7
Details
CheckScoreReason
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Code-Review🟢 10all changesets reviewed
Maintained⚠️ 01 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Packaging⚠️ -1packaging workflow not detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
SAST🟢 8SAST tool detected but not run on all commits
actions/actions/setup-node 48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e 🟢 5.6
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained🟢 56 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Binary-Artifacts🟢 9binaries present in source code
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
License🟢 10license file detected
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 1branch protection is not maximal on development and all release branches
SAST🟢 9SAST tool is not run on all commits -- score normalized to 9
cargo/libc >= 0.2.178, < 0.3.0 UnknownUnknown
npm/brace-expansion 5.0.6 🟢 7.2
Details
CheckScoreReason
Code-Review🟢 3Found 9/23 approved changesets -- score normalized to 3
Maintained🟢 1017 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
Binary-Artifacts🟢 10no binaries found in the repo
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Security-Policy🟢 10security policy file detected
Pinned-Dependencies🟢 10all dependencies are pinned
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 9license file detected
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Signed-Releases⚠️ -1no releases found
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0

Scanned Files

  • .github/workflows/security-audit.yml
  • src-tauri/Cargo.toml
  • src/package-lock.json

@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@F0RLE, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 22 minutes and 18 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2fabd6ea-5317-4320-ad13-986e6fd09c93

📥 Commits

Reviewing files that changed from the base of the PR and between bd89c47 and 1d14551.

⛔ Files ignored due to path filters (3)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
  • src/assets/fonts/Cubic_11.zh-subset.woff2 is excluded by !**/*.woff2
  • src/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (133)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/dependency-review.yml
  • .github/workflows/release.yml
  • .github/workflows/security-audit.yml
  • SECURITY.md
  • docs/examples/sdk/javascript/axelate-client.mjs
  • docs/examples/sdk/python/axelate_sdk.py
  • docs/localization/en/AGENT_CONTROL.md
  • docs/localization/en/ARCHITECTURE.md
  • docs/localization/en/CURRENT_STATE.md
  • docs/localization/en/DEVELOPMENT_WORKFLOW.md
  • docs/localization/en/INTEGRATION_API.md
  • docs/localization/en/INTEGRATION_DEVELOPMENT.md
  • docs/localization/en/README.md
  • docs/localization/en/ROADMAP.md
  • docs/localization/en/TRUST_MODEL.md
  • docs/localization/en/VISION.md
  • docs/localization/ru/INTEGRATION_DEVELOPMENT.md
  • docs/localization/ru/README.md
  • docs/localization/zh/INTEGRATION_DEVELOPMENT.md
  • docs/localization/zh/README.md
  • src-tauri/Cargo.toml
  • src-tauri/resources/locales/en.json
  • src-tauri/resources/locales/ru.json
  • src-tauri/resources/locales/zh.json
  • src-tauri/src/api/agent_control.rs
  • src-tauri/src/api/ai/mod.rs
  • src-tauri/src/api/mod.rs
  • src-tauri/src/api/modules/mod.rs
  • src-tauri/src/api/system/config.rs
  • src-tauri/src/api/system/console_overview.rs
  • src-tauri/src/api/system/log_targets.rs
  • src-tauri/src/api/system/logs.rs
  • src-tauri/src/api/system/mod.rs
  • src-tauri/src/app/window.rs
  • src-tauri/src/domain/agent_control.rs
  • src-tauri/src/domain/ai/ai_dispatch.rs
  • src-tauri/src/domain/ai/ai_provider_resolution.rs
  • src-tauri/src/domain/ai/ai_service.rs
  • src-tauri/src/domain/ai/ai_validation.rs
  • src-tauri/src/domain/ai/mod.rs
  • src-tauri/src/domain/ai/provider_payload.rs
  • src-tauri/src/domain/ai/session.rs
  • src-tauri/src/domain/ai/session_context.rs
  • src-tauri/src/domain/ai/streaming.rs
  • src-tauri/src/domain/ai/streaming_chunks.rs
  • src-tauri/src/domain/engine/engine_ids.rs
  • src-tauri/src/domain/engine/manager.rs
  • src-tauri/src/domain/engine/mod.rs
  • src-tauri/src/domain/integration_api/auth.rs
  • src-tauri/src/domain/integration_api/mod.rs
  • src-tauri/src/domain/integration_api/routing.rs
  • src-tauri/src/domain/integration_api/tests.rs
  • src-tauri/src/domain/integration_api/types.rs
  • src-tauri/src/domain/mod.rs
  • src-tauri/src/domain/modules/controller/lifecycle.rs
  • src-tauri/src/domain/modules/controller/mod.rs
  • src-tauri/src/domain/modules/controller/process.rs
  • src-tauri/src/domain/modules/controller/script_runtime.rs
  • src-tauri/src/domain/modules/github_release_targets.rs
  • src-tauri/src/domain/modules/github_releases.rs
  • src-tauri/src/domain/modules/mod.rs
  • src-tauri/src/domain/system/hardware_probe.rs
  • src-tauri/src/infrastructure/logging/logger.rs
  • src-tauri/src/infrastructure/system/startup.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/models/config.rs
  • src-tauri/src/models/modules.rs
  • src-tauri/src/utils/memory.rs
  • src-tauri/src/utils/paths.rs
  • src/app/CoreLifecycleController.test.ts
  • src/app/CoreLifecycleController.ts
  • src/app/CoreServiceFactory.ts
  • src/app/CoreStateRestore.test.ts
  • src/app/CoreStateRestore.ts
  • src/features/ai/services/AIBridge.test.ts
  • src/features/ai/services/AIBridge.ts
  • src/features/ai/services/AIBridgeConfig.ts
  • src/features/ai/services/AIBridgeMessageController.test.ts
  • src/features/ai/services/AIBridgeMessageController.ts
  • src/features/ai/services/AIBridgeProviderPolicy.test.ts
  • src/features/ai/services/AIBridgeProviderPolicy.ts
  • src/features/ai/services/AIChatTransport.test.ts
  • src/features/ai/services/AIChatTransport.ts
  • src/features/ai/services/AIProviderManager.test.ts
  • src/features/ai/services/AIProviderManager.ts
  • src/features/ai/services/EngineStatusService.test.ts
  • src/features/ai/services/EngineStatusService.ts
  • src/features/ai/types/aiTypes.ts
  • src/features/ai/ui/AISettingsContentRenderer.ts
  • src/features/ai/ui/AISettingsKeyController.test.ts
  • src/features/ai/ui/AISettingsKeyController.ts
  • src/features/ai/ui/AISettingsRenderer.test.ts
  • src/features/ai/ui/AISettingsRenderer.ts
  • src/features/ai/ui/AISettingsSelectionController.ts
  • src/features/ai/ui/AISettingsViewPolicy.test.ts
  • src/features/ai/ui/AISettingsViewPolicy.ts
  • src/features/console/services/ConsoleLogNormalizer.ts
  • src/features/console/services/ConsoleLogService.test.ts
  • src/features/console/services/ConsoleLogService.ts
  • src/features/console/ui/ConsoleFilterControlHelper.ts
  • src/features/console/ui/ConsoleLogPresentationHelper.ts
  • src/features/console/ui/ConsoleUI.test.ts
  • src/features/console/ui/ConsoleUI.ts
  • src/features/console/ui/ConsoleViewHelper.ts
  • src/features/settings/index.ts
  • src/features/settings/services/SettingsService.test.ts
  • src/features/settings/services/SettingsService.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.test.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.ts
  • src/features/settings/ui/SettingsPageUI.test.ts
  • src/features/settings/ui/SettingsUI.ts
  • src/public/templates/pages/console.html
  • src/public/templates/pages/settings.html
  • src/shared/services/CatalogLoadSnapshot.ts
  • src/shared/services/CatalogService.test.ts
  • src/shared/services/CatalogService.ts
  • src/shared/shell/AppUI.test.ts
  • src/shared/shell/AppUI.ts
  • src/shared/shell/ui/AppUiDashboardSupport.ts
  • src/shared/shell/ui/card/ModuleCardRenderer.test.ts
  • src/shared/shell/ui/card/ModuleCardRenderer.ts
  • src/shared/types/bindings.ts
  • src/shared/types/coreTypes.ts
  • src/shared/utils/customProviderSupport.test.ts
  • src/shared/utils/customProviderSupport.ts
  • src/shared/utils/providerSupport.test.ts
  • src/shared/utils/providerSupport.ts
  • src/styles/features/console-page.css
  • src/styles/features/settings-page.css
  • src/test/helpers/catalogTestUtils.ts
  • src/test/integration/CatalogService.integration.test.ts
📝 Walkthrough

Walkthrough

Adds a trusted local Agent Control domain (service, Tauri commands, UI renderer, settings, tests), refactors console log targeting/clearing and console overview, centralizes AI streaming/provider resolution/validation and local-context logic, switches catalog loading to a backend snapshot, adds release-target helpers, implements module repair, updates many frontend behaviors/tests, and pins CI actions (plus a cross-platform check job).

Changes

Full PR

Layer / File(s) Summary
Agent Control, logs, AI, catalog, CI (single checkpoint)
src-tauri/..., src/features/..., src/shared/..., src/public/..., src/styles/..., .github/workflows/*, docs/..., src/app/..., src/test/*
Adds Agent Control domain, API and UI (agent_control), console-overview and log-target helpers, streaming-chunk parsing, AI provider resolution/validation, session local-context builder, catalog snapshot API + frontend mapping, module repair flow and script-runtime changes, release-target helpers, broad test updates, and pins GitHub Actions including a cross-platform CI job.
  • Estimated code review effort: 🎯 5 (Critical) | ⏱️ ~120 minutes

  • Possibly related PRs:

    • F0RLE/Axelate#79: overlaps prior console-log refactor touching console log functions and canonicalization.
  • Suggested labels: frontend, backend, security, ci, dependencies

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch F0RLE/code-quality-stabilization

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 164: Replace the unpinned action reference "uses: actions/setup-node@v6"
with a pinned commit SHA for the setup-node action everywhere it appears (CI,
release and security-audit workflows); update each occurrence to "uses:
actions/setup-node@<full-commit-sha>" using the canonical commit SHA from the
actions/setup-node repository, ensure you update all files that currently use
the `@v6` tag (the same string "uses: actions/setup-node@v6") so no workflow
remains unpinned.
- Line 150: In the check-cross-platform job update the actions usage: replace
actions/checkout@v6 with a pinned commit SHA and add with: persist-credentials:
false to the checkout step (the checkout step symbol is actions/checkout), and
replace actions/setup-node@v6 with a pinned commit SHA for actions/setup-node;
ensure you update the checkout step block where persist-credentials is set and
the setup-node step reference so both actions use specific commit SHAs instead
of `@v6`.

In `@src-tauri/src/api/system/log_targets.rs`:
- Around line 46-67: The clear_console_log_target function currently follows
symlinks and may truncate files outside the intended log dir; update
clear_console_log_target (and the similar helpers around the clear_logs area
that call clear_log_file) to first reject symlinked roots/entries by using
symlink_metadata or DirEntry::file_type() (instead of
path.exists()/is_dir()/read_dir following symlinks), ensure the target itself is
not a symlink before iterating, skip any DirEntry where
file_type().is_symlink(), and only call clear_log_file for entries whose
file_type().is_file() and have a .log extension; keep clear_log_file unchanged
but ensure callers only pass canonical non-symlink File paths.
- Around line 6-18: The function resolve_console_log_target currently treats any
unrecognized view_id as the shared LOG_DIR; change it to explicitly allow only
"general" for that shared-root case and return an AppError::Validation for any
other unknown view_id. Update resolve_console_log_target to: keep the existing
engine: and module: branches, then if view_id == "general" return LOG_DIR, else
return Err(AppError::Validation("invalid console view id".into())) (use the
project’s AppError::Validation constructor/pattern). This ensures invalid IPC
payloads like "foo" fail validation instead of clearing platform logs.

In `@src/features/console/ui/ConsoleUI.test.ts`:
- Line 744: The test currently asserts a hardcoded English string via
expect(pane.textContent).toBe('No logs match selected levels'); — replace this
with a stable, i18n-safe assertion: retrieve the localized string via the app's
i18n lookup (the same key used by the Console UI) or assert a stable DOM marker
for the empty-state (e.g., a data-testid or CSS class used by ConsoleUI for the
no-logs state) instead; update ConsoleUI.test.ts to reference the i18n key or
empty-state selector rather than the literal text so tests remain
locale-agnostic (locate the assertion around the pane variable in the test).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5fccdd04-1143-47d5-8d41-aa3017f96ccf

📥 Commits

Reviewing files that changed from the base of the PR and between bd89c47 and 41c4a40.

⛔ Files ignored due to path filters (1)
  • src/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • .github/workflows/ci.yml
  • src-tauri/src/api/system/log_targets.rs
  • src-tauri/src/api/system/logs.rs
  • src-tauri/src/api/system/mod.rs
  • src/features/ai/services/AIBridgeMessageController.test.ts
  • src/features/ai/ui/AISettingsRenderer.test.ts
  • src/features/console/ui/ConsoleUI.test.ts
  • src/shared/utils/providerSupport.test.ts

Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/ci.yml Outdated
Comment thread src-tauri/src/api/system/log_targets.rs Outdated
Comment thread src-tauri/src/api/system/log_targets.rs
Comment thread src/features/console/ui/ConsoleUI.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src-tauri/src/api/system/logs.rs (1)

127-132: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Canonicalize view_id like the sibling commands do.

get_console_logs and clear_console_logs both pass view_id through canonical_console_view_id before resolving, but open_console_log_target skips that step. As a result, inputs that the other two accept (e.g. " general ", "module:foo ", or "engine:llama.cpp" when only the engine branch is canonicalized inside resolve_*) will hit the new "invalid console view id" path here and the folder-open IPC will fail for cases the rest of the API treats as valid.

Proposed fix
 pub fn open_console_log_target(view_id: String) -> Result<(), AppError> {
-    let target = resolve_console_log_target(&view_id)?;
+    let canonical_view_id = canonical_console_view_id(&view_id);
+    let target = resolve_console_log_target(&canonical_view_id)?;
     fs::create_dir_all(&target)?;
     open_folder(&target)?;
     Ok(())
 }

As per coding guidelines, "Review as a Windows-first Tauri backend. Prioritize IPC boundary validation..."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/api/system/logs.rs` around lines 127 - 132,
open_console_log_target currently calls resolve_console_log_target(&view_id)
directly and thus rejects inputs that other commands accept; update
open_console_log_target to first canonicalize the incoming view_id by calling
canonical_console_view_id(&view_id)? and use that canonical value when calling
resolve_console_log_target, preserving existing error propagation and behavior
of fs::create_dir_all and open_folder; reference functions
open_console_log_target, canonical_console_view_id, and
resolve_console_log_target when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/domain/ai/session_context.rs`:
- Around line 260-279: The code currently assigns session.summary =
merge_summary(...) and then advances session.summary_message_count
unconditionally, which can clear the existing summary when merge_summary returns
None and permanently drop those turns; change the flow so you call
merge_summary(...) and inspect its result first: if it returns Some(non_empty)
set session.summary = that value and then set session.summary_message_count =
u32::try_from(self.recent_start_index).unwrap_or(u32::MAX); if it returns None
leave session.summary and session.summary_message_count unchanged (and return
false), ensuring you only advance recent_start_index when a new summary was
actually produced; reference merge_summary, session.summary,
session.summary_message_count, recent_start_index, build_summary_lines and
summary_lines to locate the change.
- Around line 338-351: The loop over recent_turn_ranges currently uses continue
when a turn's tokens would exceed available_budget, which can produce
non-contiguous history; change the logic in that loop so that when used_tokens +
turn_tokens > available_budget you break out of the loop instead of continuing,
preserving contiguity of kept_recent; ensure this update is applied in the
function that iterates recent_turn_ranges and references session.history,
estimate_messages_tokens, kept_recent, used_tokens, and available_budget so
older turns are only appended while the budget allows and the kept window
remains contiguous.

In `@src-tauri/src/domain/ai/streaming_chunks.rs`:
- Around line 202-224: The fallback chain in streaming_chunks.rs duplicates the
json.get("message").and_then(|message|
message.get("content")).and_then(provider_response::extract_stream_text) call,
making the second instance dead code; update the or_else chain in the block that
builds the stream text to either remove the duplicate or (preferably) replace
the second occurrence with the provider variant intended for delta-style
responses, e.g. use json.get("delta").and_then(|delta|
delta.get("content")).and_then(provider_response::extract_stream_text) so the
chain checks message.content, response, delta.content, token.text as distinct
fallbacks around provider_response::extract_stream_text.

---

Outside diff comments:
In `@src-tauri/src/api/system/logs.rs`:
- Around line 127-132: open_console_log_target currently calls
resolve_console_log_target(&view_id) directly and thus rejects inputs that other
commands accept; update open_console_log_target to first canonicalize the
incoming view_id by calling canonical_console_view_id(&view_id)? and use that
canonical value when calling resolve_console_log_target, preserving existing
error propagation and behavior of fs::create_dir_all and open_folder; reference
functions open_console_log_target, canonical_console_view_id, and
resolve_console_log_target when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3d6a9cca-812b-48a4-b714-f7465ab7f060

📥 Commits

Reviewing files that changed from the base of the PR and between 41c4a40 and cc8e3f7.

⛔ Files ignored due to path filters (1)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (28)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/dependency-review.yml
  • .github/workflows/release.yml
  • .github/workflows/security-audit.yml
  • src-tauri/Cargo.toml
  • src-tauri/resources/locales/en.json
  • src-tauri/resources/locales/ru.json
  • src-tauri/resources/locales/zh.json
  • src-tauri/src/api/ai/mod.rs
  • src-tauri/src/api/system/log_targets.rs
  • src-tauri/src/api/system/logs.rs
  • src-tauri/src/app/window.rs
  • src-tauri/src/domain/ai/mod.rs
  • src-tauri/src/domain/ai/session.rs
  • src-tauri/src/domain/ai/session_context.rs
  • src-tauri/src/domain/ai/streaming.rs
  • src-tauri/src/domain/ai/streaming_chunks.rs
  • src-tauri/src/domain/modules/controller/lifecycle.rs
  • src-tauri/src/domain/modules/controller/process.rs
  • src-tauri/src/domain/modules/github_release_targets.rs
  • src-tauri/src/domain/modules/github_releases.rs
  • src-tauri/src/domain/modules/mod.rs
  • src-tauri/src/domain/system/hardware_probe.rs
  • src-tauri/src/infrastructure/system/startup.rs
  • src-tauri/src/utils/memory.rs
  • src/features/console/ui/ConsoleUI.test.ts
  • src/features/console/ui/ConsoleUI.ts
💤 Files with no reviewable changes (1)
  • src-tauri/src/infrastructure/system/startup.rs
✅ Files skipped from review due to trivial changes (6)
  • src-tauri/src/domain/ai/mod.rs
  • src-tauri/src/domain/modules/mod.rs
  • src/features/console/ui/ConsoleUI.ts
  • src-tauri/src/api/ai/mod.rs
  • src-tauri/resources/locales/ru.json
  • src-tauri/src/domain/modules/controller/process.rs

Comment thread src-tauri/src/domain/ai/session_context.rs
Comment thread src-tauri/src/domain/ai/session_context.rs
Comment thread src-tauri/src/domain/ai/streaming_chunks.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/api/system/console_overview.rs`:
- Around line 346-350: The grouping key currently uses
normalize_view_label(&slot.engine.name) which collapses different engines that
share a display name; change the grouping to use
canonical_engine_id(&slot.engine.id) as the dedupe key (i.e., set label_key to
canonical_engine_id(&slot.engine.id) or introduce engine_key =
canonical_engine_id(&slot.engine.id) and use that for label_to_id.entry(...)),
while still using normalize_view_label(&slot.engine.name) only to derive the
human-visible label when first inserting into the map; apply the same change to
the other occurrence handling lines 353-366 so engines are deduplicated by
canonical ID, not by display name.

In `@src-tauri/src/domain/ai/ai_validation.rs`:
- Around line 15-21: The code that builds models_url from the caller-provided
base_url (the base_url variable and models_url construction) accepts arbitrary
strings, enabling SSRF; change validation to parse and enforce a safe whitelist
or strict rules: accept only empty/None or URLs with scheme https and host
matching an allowlist of trusted hosts (e.g., openrouter.ai and any additional
approved domains), reject or return an error for localhost, 127.0.0.0/8, private
IP ranges, and non-HTTPS schemes; apply the same validation logic to the other
similar spot referenced (lines ~70-77) so both usages validate parsed URL host
and scheme before formatting models_url or any other request URL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 436209eb-ca79-4403-be9e-65f2745eae09

📥 Commits

Reviewing files that changed from the base of the PR and between cc8e3f7 and 2a47b44.

📒 Files selected for processing (11)
  • src-tauri/src/api/system/console_overview.rs
  • src-tauri/src/api/system/logs.rs
  • src-tauri/src/api/system/mod.rs
  • src-tauri/src/domain/ai/ai_dispatch.rs
  • src-tauri/src/domain/ai/ai_provider_resolution.rs
  • src-tauri/src/domain/ai/ai_service.rs
  • src-tauri/src/domain/ai/ai_validation.rs
  • src-tauri/src/domain/ai/mod.rs
  • src-tauri/src/domain/engine/engine_ids.rs
  • src-tauri/src/domain/engine/manager.rs
  • src-tauri/src/domain/engine/mod.rs
✅ Files skipped from review due to trivial changes (1)
  • src-tauri/src/domain/engine/mod.rs

Comment thread src-tauri/src/api/system/console_overview.rs Outdated
Comment thread src-tauri/src/domain/ai/ai_validation.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/console/services/ConsoleLogService.ts (1)

124-126: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reset known view state in fallback paths to avoid stale general-log filtering.

_knownViewIds is refreshed only on successful overview fetch. If getAvailableViews() falls back, old runtime IDs can remain and hide logs from general unexpectedly.

Suggested fix
     public async getAvailableViews(): Promise<IConsoleLogView[]> {
         if (!this.bridge.isTauri()) {
-            return [{ id: 'general', label: 'Platform' }];
+            const fallback = [{ id: 'general', label: 'Platform' }];
+            this._rememberKnownViews(fallback);
+            return fallback;
         }
@@
-        return [{ id: 'general', label: 'Platform' }];
+        const fallback = [{ id: 'general', label: 'Platform' }];
+        this._rememberKnownViews(fallback);
+        return fallback;
     }

As per coding guidelines, src/**/*.ts: “Prioritize state consistency…”.

Also applies to: 141-142

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/console/services/ConsoleLogService.ts` around lines 124 - 126,
When getAvailableViews() takes the fallback path (e.g., when
this.bridge.isTauri() is false or in the other fallback at the later branch),
reset the service's _knownViewIds to include the default 'general' view so stale
runtime IDs can't hide general logs; update the fallback branches inside
ConsoleLogService.getAvailableViews() to assign _knownViewIds = new
Set(['general']) (or equivalent) before returning the fallback view list so
state is consistent after failed overview fetches.
🧹 Nitpick comments (2)
src-tauri/src/domain/ai/ai_validation.rs (1)

254-274: ⚡ Quick win

Add test case for IPv4-mapped IPv6 bypass.

Consider adding a test for https://[::ffff:127.0.0.1]/v1 to ensure IPv4-mapped IPv6 addresses are also rejected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/domain/ai/ai_validation.rs` around lines 254 - 274, The test
build_validation_request_rejects_unsafe_base_urls is missing a case for
IPv4-mapped IPv6 addresses, which can bypass IPv4 checks; update the test (in
the function build_validation_request_rejects_unsafe_base_urls) to include
"https://[::ffff:127.0.0.1]/v1" in the array of base_url values so that
build_validation_request is asserted to reject IPv4-mapped IPv6 loopback
addresses as well.
src-tauri/src/api/system/config.rs (1)

38-49: 💤 Low value

Run npm --prefix src run bindings:sync after merging.

New Tauri command get_catalog_snapshot was added with Specta annotations. As per coding guidelines, ensure frontend bindings are regenerated.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/api/system/config.rs` around lines 38 - 49, The new Tauri
command get_catalog_snapshot() was added with #[specta::specta] annotations so
frontend bindings must be regenerated; after merging this change run the binding
sync command (npm --prefix src run bindings:sync) to update Specta/TypeScript
bindings for the new get_catalog_snapshot API so the frontend knows about the
new command and types.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/domain/ai/ai_validation.rs`:
- Around line 40-92: The SSRF check misses IPv4-mapped IPv6 addresses (e.g.
::ffff:127.0.0.1) — update is_restricted_ip so when it receives IpAddr::V6 it
first checks if the Ipv6Addr is an IPv4-mapped address, and if so converts it to
an Ipv4Addr and calls is_restricted_ipv4; otherwise continue to call
is_restricted_ipv6. Change the implementation referenced by is_restricted_ip
(and adjust callers like validate_openai_compatible_base_url if needed) to
normalize mapped IPv6 -> IPv4 before applying the IPv4-restriction checks.

In `@src-tauri/src/infrastructure/logging/logger.rs`:
- Around line 558-560: In parse_log_timestamp replace the u32 narrowing that
uses u32::try_from(timestamp.timestamp()).ok()? which drops negative or very
large seconds; instead convert the signed seconds (timestamp.timestamp() -> i64)
directly to f64 and add the fractional milliseconds
(timestamp.timestamp_subsec_millis() / 1000.0) so the function returns Some(f64)
for pre-epoch and far-future dates; update the code paths around the local
variable named seconds and the final Some(...) expression to use the i64-to-f64
conversion rather than u32 conversion.

In `@src/features/ai/services/AIBridgeProviderPolicy.ts`:
- Line 25: The current expression in AIBridgeProviderPolicy (return
this._catalogProvider(providerId)?.providerPolicy?.isCloudProvider ?? false)
defaults unknown providers to non-cloud; change it to avoid silent default by
explicitly handling missing catalog entries or missing providerPolicy: fetch the
catalog entry via _catalogProvider(providerId) and if it's null/undefined,
return an explicit "unknown" result or throw/propagate an error instead of
returning false, or use a deterministic fallback based on providerId (e.g.,
lookupAllowedFallback(providerId)) so that providerPolicy.isCloudProvider is
only used when present; update any callers of the method to handle the new
"unknown" outcome (or the thrown error) accordingly.

In `@src/features/ai/services/AIProviderManager.ts`:
- Around line 197-204: The _isLocalProvider method currently treats missing
catalog policy as local which can bypass cloud checks; change it to fail closed
by treating unknown providers as non-local: when
this._getCatalogProvider(providerId) returns null/undefined or providerPolicy is
missing, return false (or throw an explicit error) instead of true so
startProvider() will enforce cloud key checks; update _isLocalProvider (and add
a brief log or error message referencing providerId) to make the decision
explicit.

In `@src/features/ai/ui/AISettingsContentRenderer.ts`:
- Around line 144-146: Replace the hardcoded title on the API anchor element
with a localized string from the i18n resources: locate the anchor with id
`${appId}-api-link` in AISettingsContentRenderer and replace title="Manage your
OpenRouter API Keys" with a call that retrieves the text from
src-tauri/resources/locales (e.g. title={t('ai.manageOpenRouterApiKeys')} or
equivalent project i18n helper), add the new key "ai.manageOpenRouterApiKeys" to
the locale files, and ensure the same localized label is used consistently for
the link tooltip.

---

Outside diff comments:
In `@src/features/console/services/ConsoleLogService.ts`:
- Around line 124-126: When getAvailableViews() takes the fallback path (e.g.,
when this.bridge.isTauri() is false or in the other fallback at the later
branch), reset the service's _knownViewIds to include the default 'general' view
so stale runtime IDs can't hide general logs; update the fallback branches
inside ConsoleLogService.getAvailableViews() to assign _knownViewIds = new
Set(['general']) (or equivalent) before returning the fallback view list so
state is consistent after failed overview fetches.

---

Nitpick comments:
In `@src-tauri/src/api/system/config.rs`:
- Around line 38-49: The new Tauri command get_catalog_snapshot() was added with
#[specta::specta] annotations so frontend bindings must be regenerated; after
merging this change run the binding sync command (npm --prefix src run
bindings:sync) to update Specta/TypeScript bindings for the new
get_catalog_snapshot API so the frontend knows about the new command and types.

In `@src-tauri/src/domain/ai/ai_validation.rs`:
- Around line 254-274: The test
build_validation_request_rejects_unsafe_base_urls is missing a case for
IPv4-mapped IPv6 addresses, which can bypass IPv4 checks; update the test (in
the function build_validation_request_rejects_unsafe_base_urls) to include
"https://[::ffff:127.0.0.1]/v1" in the array of base_url values so that
build_validation_request is asserted to reject IPv4-mapped IPv6 loopback
addresses as well.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 688d2c81-448d-44ae-93f8-be50912c4283

📥 Commits

Reviewing files that changed from the base of the PR and between 2a47b44 and a98169f.

📒 Files selected for processing (65)
  • docs/localization/en/CURRENT_STATE.md
  • docs/localization/en/INTEGRATION_API.md
  • docs/localization/en/README.md
  • docs/localization/en/ROADMAP.md
  • docs/localization/en/TRUST_MODEL.md
  • docs/localization/en/VISION.md
  • docs/localization/ru/INTEGRATION_DEVELOPMENT.md
  • docs/localization/ru/README.md
  • docs/localization/zh/INTEGRATION_DEVELOPMENT.md
  • docs/localization/zh/README.md
  • src-tauri/src/api/system/config.rs
  • src-tauri/src/api/system/console_overview.rs
  • src-tauri/src/api/system/logs.rs
  • src-tauri/src/domain/ai/ai_service.rs
  • src-tauri/src/domain/ai/ai_validation.rs
  • src-tauri/src/domain/ai/provider_payload.rs
  • src-tauri/src/domain/ai/session.rs
  • src-tauri/src/domain/ai/session_context.rs
  • src-tauri/src/domain/ai/streaming_chunks.rs
  • src-tauri/src/domain/modules/controller/script_runtime.rs
  • src-tauri/src/infrastructure/logging/logger.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/models/config.rs
  • src-tauri/src/utils/paths.rs
  • src/app/CoreStateRestore.test.ts
  • src/app/CoreStateRestore.ts
  • src/features/ai/services/AIBridge.test.ts
  • src/features/ai/services/AIBridge.ts
  • src/features/ai/services/AIBridgeConfig.ts
  • src/features/ai/services/AIBridgeMessageController.test.ts
  • src/features/ai/services/AIBridgeMessageController.ts
  • src/features/ai/services/AIBridgeProviderPolicy.test.ts
  • src/features/ai/services/AIBridgeProviderPolicy.ts
  • src/features/ai/services/AIChatTransport.test.ts
  • src/features/ai/services/AIChatTransport.ts
  • src/features/ai/services/AIProviderManager.test.ts
  • src/features/ai/services/AIProviderManager.ts
  • src/features/ai/services/EngineStatusService.test.ts
  • src/features/ai/services/EngineStatusService.ts
  • src/features/ai/types/aiTypes.ts
  • src/features/ai/ui/AISettingsContentRenderer.ts
  • src/features/ai/ui/AISettingsKeyController.test.ts
  • src/features/ai/ui/AISettingsKeyController.ts
  • src/features/ai/ui/AISettingsRenderer.test.ts
  • src/features/ai/ui/AISettingsRenderer.ts
  • src/features/ai/ui/AISettingsSelectionController.ts
  • src/features/ai/ui/AISettingsViewPolicy.test.ts
  • src/features/ai/ui/AISettingsViewPolicy.ts
  • src/features/console/services/ConsoleLogService.test.ts
  • src/features/console/services/ConsoleLogService.ts
  • src/features/settings/services/SettingsService.test.ts
  • src/features/settings/services/SettingsService.ts
  • src/shared/services/CatalogLoadSnapshot.ts
  • src/shared/services/CatalogService.test.ts
  • src/shared/services/CatalogService.ts
  • src/shared/shell/AppUI.test.ts
  • src/shared/shell/AppUI.ts
  • src/shared/types/bindings.ts
  • src/shared/types/coreTypes.ts
  • src/shared/utils/customProviderSupport.test.ts
  • src/shared/utils/customProviderSupport.ts
  • src/shared/utils/providerSupport.test.ts
  • src/shared/utils/providerSupport.ts
  • src/test/helpers/catalogTestUtils.ts
  • src/test/integration/CatalogService.integration.test.ts
💤 Files with no reviewable changes (6)
  • src/shared/utils/providerSupport.ts
  • src/shared/utils/customProviderSupport.test.ts
  • src/shared/utils/customProviderSupport.ts
  • src/features/ai/services/EngineStatusService.ts
  • src/shared/utils/providerSupport.test.ts
  • src/shared/services/CatalogLoadSnapshot.ts
✅ Files skipped from review due to trivial changes (9)
  • docs/localization/en/README.md
  • docs/localization/zh/INTEGRATION_DEVELOPMENT.md
  • docs/localization/en/TRUST_MODEL.md
  • docs/localization/en/INTEGRATION_API.md
  • docs/localization/ru/README.md
  • src/shared/types/bindings.ts
  • docs/localization/ru/INTEGRATION_DEVELOPMENT.md
  • docs/localization/en/CURRENT_STATE.md
  • docs/localization/en/VISION.md

Comment thread src-tauri/src/domain/ai/ai_validation.rs
Comment thread src-tauri/src/infrastructure/logging/logger.rs Outdated
Comment thread src/features/ai/services/AIBridgeProviderPolicy.ts Outdated
Comment thread src/features/ai/services/AIChatTransport.ts Outdated
Comment thread src/features/ai/services/AIProviderManager.ts
Comment thread src/features/ai/ui/AISettingsContentRenderer.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/features/console/services/ConsoleLogService.test.ts (1)

196-225: ⚡ Quick win

Add clearAllLogs() coverage for agent audit logs.

This PR also changed clearAllLogs() to advance the local agent cursor, but the suite only exercises clearLogs('agent'). A targeted test here would catch regressions where old audit entries reappear after a full clear.

As per coding guidelines src/**/*.ts: Review as vanilla TypeScript frontend code. Prioritize state consistency, async cancellation, event listener cleanup, DOM injection risks, user-visible regressions, and test coverage for changed flows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/console/services/ConsoleLogService.test.ts` around lines 196 -
225, Add a test that covers clearAllLogs() for the agent audit logs: after
mocking invokeModule.invokeSafe and calling service.fetchLogs('agent'), call
service.clearAllLogs() (in addition to or instead of service.clearLogs('agent'))
and assert it returns true, that bridge.invoke was not called with
'clear_console_logs', and that service.getLogsForView('agent') is empty and any
local audit cursor/state that prevents old audit entries from reappearing has
been advanced/updated; use existing helpers setupTauri, service.fetchLogs,
service.clearLogs/service.clearAllLogs, and service.getLogsForView to locate the
code under test.
src/features/console/services/ConsoleLogService.ts (1)

51-67: ⚡ Quick win

Make localization injection mandatory.

_translate = (key) => key fails open: any missed constructor wiring renders raw IDs like ui.launcher.web.logs_agent in the UI. Since this service now emits user-facing labels and fallback text, require a translator here so missing integration fails at compile time instead of shipping untranslated keys.

♻️ Proposed fix
 type ConsoleLogTranslate = (key: string, fallback?: string) => string;
 ...
     constructor(
         private readonly bridge: IBridge,
         private readonly _tracer: ConsoleLogServiceLogger,
-        private readonly _translate: ConsoleLogTranslate = (key) => key,
+        private readonly _translate: ConsoleLogTranslate,
     ) {}

As per coding guidelines src/**/*.{ts,tsx,html}: Keep UI text in I18n resources under src-tauri/resources/locales/ and do not hardcode Russian or English user-facing strings in TS/HTML.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/console/services/ConsoleLogService.ts` around lines 51 - 67, The
constructor currently provides a default _translate = (key) => key which allows
missing i18n wiring; remove the default so the ConsoleLogService constructor
requires a ConsoleLogTranslate parameter (i.e. change the constructor signature
to accept _translate: ConsoleLogTranslate without a default) and update all call
sites that construct ConsoleLogService to pass a translator instance; ensure
references to _translate in methods (and any tests/mocks) use the injected
translator so missing wiring fails at compile time instead of showing raw keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/domain/agent_control.rs`:
- Around line 313-327: pending_token() and discard_pending_token() separate read
and removal, allowing the one-time token to be observed multiple times; replace
them with a single atomic backend-only reveal that returns the token and
invalidates it under the same lock. Implement a method (e.g.,
reveal_and_consume_pending_token or take_pending_token) that locks
self.pending_tokens.lock().await, attempts to remove(id) and returns the token
if present or an AppError::Validation if absent; update any callers of
pending_token/discard_pending_token to use the new atomic method so the token is
copied out and removed in one protected step.

---

Nitpick comments:
In `@src/features/console/services/ConsoleLogService.test.ts`:
- Around line 196-225: Add a test that covers clearAllLogs() for the agent audit
logs: after mocking invokeModule.invokeSafe and calling
service.fetchLogs('agent'), call service.clearAllLogs() (in addition to or
instead of service.clearLogs('agent')) and assert it returns true, that
bridge.invoke was not called with 'clear_console_logs', and that
service.getLogsForView('agent') is empty and any local audit cursor/state that
prevents old audit entries from reappearing has been advanced/updated; use
existing helpers setupTauri, service.fetchLogs,
service.clearLogs/service.clearAllLogs, and service.getLogsForView to locate the
code under test.

In `@src/features/console/services/ConsoleLogService.ts`:
- Around line 51-67: The constructor currently provides a default _translate =
(key) => key which allows missing i18n wiring; remove the default so the
ConsoleLogService constructor requires a ConsoleLogTranslate parameter (i.e.
change the constructor signature to accept _translate: ConsoleLogTranslate
without a default) and update all call sites that construct ConsoleLogService to
pass a translator instance; ensure references to _translate in methods (and any
tests/mocks) use the injected translator so missing wiring fails at compile time
instead of showing raw keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4e385ee-e9aa-4b75-9d1a-51ea10365e69

📥 Commits

Reviewing files that changed from the base of the PR and between a9c56ef and ee7c14a.

📒 Files selected for processing (15)
  • src-tauri/resources/locales/en.json
  • src-tauri/resources/locales/ru.json
  • src-tauri/resources/locales/zh.json
  • src-tauri/src/api/agent_control.rs
  • src-tauri/src/domain/agent_control.rs
  • src-tauri/src/domain/modules/controller/mod.rs
  • src/app/CoreServiceFactory.ts
  • src/features/console/services/ConsoleLogService.test.ts
  • src/features/console/services/ConsoleLogService.ts
  • src/features/console/ui/ConsoleLogPresentationHelper.ts
  • src/features/console/ui/ConsoleUI.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.ts
  • src/public/templates/pages/console.html
  • src/styles/features/console-page.css
  • src/styles/features/settings-page.css
✅ Files skipped from review due to trivial changes (3)
  • src/styles/features/console-page.css
  • src-tauri/resources/locales/zh.json
  • src-tauri/resources/locales/en.json

Comment thread src-tauri/src/domain/agent_control.rs Outdated
@F0RLE F0RLE force-pushed the F0RLE/code-quality-stabilization branch 2 times, most recently from 3c54c60 to 61b47f0 Compare May 22, 2026 14:47
@F0RLE F0RLE force-pushed the F0RLE/code-quality-stabilization branch from 61b47f0 to e0103e0 Compare May 22, 2026 14:55
@F0RLE

F0RLE commented May 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src-tauri/src/domain/integration_api/routing.rs (1)

429-445: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject Windows drive-relative prefixed paths (Component::Prefix without RootDir) in validate_relative_draft_path.

The current checks block is_absolute() and .., but a Windows path like C:temp\file is not considered absolute; components() includes Component::Prefix(_) while omitting Component::RootDir, so it can pass. If this value is later used with PathBuf::join(draft_dir, input), Windows join semantics can ignore the base and return the prefixed path, defeating path confinement. Extend the component validation to reject Prefix(_) (and RootDir for completeness).

Suggested fix
 pub(super) fn validate_relative_draft_path(path: &str) -> Result<(), AppError> {
     if path.trim().is_empty() {
         return Err(AppError::Validation(
             "Draft entry path cannot be empty".to_string(),
         ));
     }
     let path = Path::new(path);
     if path.is_absolute()
         || path
             .components()
-            .any(|component| matches!(component, std::path::Component::ParentDir))
+            .any(|component| {
+                matches!(
+                    component,
+                    std::path::Component::ParentDir
+                        | std::path::Component::RootDir
+                        | std::path::Component::Prefix(_)
+                )
+            })
     {
         return Err(AppError::Validation(
             "Draft entry path must stay inside the draft directory".to_string(),
         ));
     }
     Ok(())
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/domain/integration_api/routing.rs` around lines 429 - 445, The
validate_relative_draft_path function currently checks is_absolute and ParentDir
but allows Windows drive-relative prefixes; update its component validation in
validate_relative_draft_path to also reject components matching
std::path::Component::Prefix(_) and std::path::Component::RootDir so any path
containing Prefix or RootDir returns Err(AppError::Validation("Draft entry path
must stay inside the draft directory".to_string())). Locate the check that
iterates path.components() and add matches for Prefix(_) and RootDir alongside
ParentDir to ensure Windows drive-relative inputs like "C:temp\\file" are
refused.
♻️ Duplicate comments (5)
src-tauri/src/api/agent_control.rs (1)

62-68: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t consume the one-time token before clipboard write succeeds.

take_pending_token is called before write_text. On clipboard failure, the token is lost.

Suggested fix
-    let token = service.take_pending_token(&id).await?;
+    let token = service.pending_token(&id).await?;
     app.clipboard()
         .write_text(token)
         .map_err(|error| AppError::External {
             message: format!("Failed to copy Agent Control token: {error}"),
             request_id: None,
         })?;
+    service.take_pending_token(&id).await?;
     Ok(())

If a non-consuming read API is unavailable, restore the token on write failure before returning the error.

As per coding guidelines src-tauri/**/*.rs: Implement secure state management with backend ownership of sensitive data.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/api/agent_control.rs` around lines 62 - 68, The code currently
calls service.take_pending_token(&id).await? (consuming the one-time token)
before calling app.clipboard().write_text(token), which loses the token on
clipboard failure; change the flow so the token is not consumed until clipboard
write succeeds: either use a non-consuming read API on service (e.g.,
peek_pending_token or similar) and only call take_pending_token(&id) after
write_text succeeds, or if no non-consuming API exists, attempt to write_text
first and on error call a restore method on service (e.g.,
restore_pending_token(&id, token)) before returning an AppError::External;
update references to take_pending_token, app.clipboard().write_text, service,
id, token, and AppError::External accordingly.
src/features/settings/ui/SettingsUI.ts (1)

136-136: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid hardcoded English fallback in user-facing TS label.

The default value 'Switch settings section' is user-facing English in frontend code.

Suggested fix
-        const label = this._i18n.t('ui.launcher.settings.section_jump', 'Switch settings section');
+        const label = this._i18n.t('ui.launcher.settings.section_jump', '');

As per coding guidelines src/**/*.{ts,tsx,html}: Keep UI text in I18n resources under src-tauri/resources/locales/ and do not hardcode Russian or English user-facing strings in TS/HTML.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/settings/ui/SettingsUI.ts` at line 136, The code currently
hardcodes an English fallback string in the i18n call for the label (const label
= this._i18n.t('ui.launcher.settings.section_jump', 'Switch settings section')),
which violates the rule to keep UI text in locale files; add the key
ui.launcher.settings.section_jump to the src-tauri/resources/locales/* locale
JSON/YAML files with appropriate translations (including English), then remove
the hardcoded fallback from the call and call
this._i18n.t('ui.launcher.settings.section_jump') (or ensure the t function uses
locale files by default) so the label is sourced from the localization resources
instead of inline text.
src/public/templates/pages/settings.html (1)

39-40: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove hardcoded English tooltip/label fallback from the HTML button.

title and aria-label are hardcoded in English even though this control already uses i18n attributes.

Suggested fix
-        title="Switch settings section"
-        aria-label="Switch settings section"

As per coding guidelines src/**/*.{ts,tsx,html}: Keep UI text in I18n resources under src-tauri/resources/locales/ and do not hardcode Russian or English user-facing strings in TS/HTML.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/public/templates/pages/settings.html` around lines 39 - 40, Remove the
hardcoded English title and aria-label attributes from the button (the element
in settings.html that currently has title="Switch settings section" and
aria-label="Switch settings section") and replace them with the appropriate i18n
attributes/keys so the tooltip/accessible label comes from the locale resources
under src-tauri/resources/locales/ (use the same i18n key pattern already used
by this control so translations are loaded instead of hardcoding English).
src-tauri/src/domain/integration_api/routing.rs (2)

251-258: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep successful module control responses independent from UI sync failures.

Line 257 uses ? on sync_launcher_selected_module(...); if sync/save/emit fails, a successful module action is returned as an error.

Suggested fix
             if response.success
                 && matches!(
                     action,
                     ModuleAction::Start | ModuleAction::Restart | ModuleAction::Repair
                 )
             {
-                sync_launcher_selected_module(&context, client, module_id).await?;
+                if let Err(error) = sync_launcher_selected_module(&context, client, module_id).await
+                {
+                    tracing::warn!(
+                        module_id = %module_id,
+                        action = %module_action_name(action),
+                        "Module control succeeded but selected-module sync failed: {error}"
+                    );
+                }
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/domain/integration_api/routing.rs` around lines 251 - 258, The
code currently uses `?` on `sync_launcher_selected_module(&context, client,
module_id).await` inside the block that handles a successful module control
response, which turns any UI sync/save/emit failure into an overall error;
instead, call and await `sync_launcher_selected_module` and handle its Result
locally (e.g., `if let Err(e) = sync_launcher_selected_module(...).await { ...
}`) so the successful response from the module action (ModuleAction::Start |
Restart | Repair) is preserved; log or trace the error (using the existing
logger/context) and continue without propagating the error to the caller.

114-117: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restrict approval list visibility to avoid cross-agent data leakage.

Line 115 still allows AuthorizedClient::Agent(_), and Line 708 returns state.approvals unfiltered. Any observe-scoped agent can read other agents’ pending approval details.

Suggested fix
-        ("GET", ["v1", "agent", "approvals"]) => {
-            ensure_launcher_client(client)?;
-            ensure_agent_scope(client, AgentScope::Observe)?;
-            handle_agent_approvals_request(&context).await
-        }
+        ("GET", ["v1", "agent", "approvals"]) => {
+            ensure_strict_launcher_client(client)?;
+            handle_agent_approvals_request(&context).await
+        }
+fn ensure_strict_launcher_client(client: &AuthorizedClient) -> Result<(), AppError> {
+    match client {
+        AuthorizedClient::Launcher => Ok(()),
+        AuthorizedClient::Agent(_) | AuthorizedClient::Module(_) => Err(AppError::PermissionDenied(
+            "Only launcher tokens can access global approvals".to_string(),
+        )),
+    }
+}
As per coding guidelines `src-tauri/src/**/*.rs`: “Prioritize IPC boundary validation … and keep user data scoped to app directories.”

Also applies to: 699-709

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/domain/integration_api/routing.rs` around lines 114 - 117, The
approvals endpoint currently permits AuthorizedClient::Agent(_) with Observe
scope and returns state.approvals unfiltered, allowing cross-agent leakage;
update handle_agent_approvals_request to accept the caller's agent identity (or
the AuthorizedClient) and filter state.approvals to only include approvals
scoped to that agent (e.g., match approval.target_agent_id or approval.agent_id
against the caller's agent id) and ensure the routing/authorization
(ensure_agent_scope / AuthorizedClient::Agent) passes the caller identity
through to the handler so only the caller's approvals are returned.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/styles/features/settings-page.css`:
- Around line 83-87: The CSS uses the keyword "currentColor" in the box-shadow
(the block with offsets "-8px -4px 0 currentColor, 8px -4px 0 currentColor, -4px
0 0 currentColor, 4px 0 0 currentColor, 0 4px 0 currentColor;") which triggers
Stylelint's value-keyword-case rule; update each occurrence of "currentColor" to
the lowercase "currentcolor" so the keyword casing matches the linter
expectation and CI will pass.

---

Outside diff comments:
In `@src-tauri/src/domain/integration_api/routing.rs`:
- Around line 429-445: The validate_relative_draft_path function currently
checks is_absolute and ParentDir but allows Windows drive-relative prefixes;
update its component validation in validate_relative_draft_path to also reject
components matching std::path::Component::Prefix(_) and
std::path::Component::RootDir so any path containing Prefix or RootDir returns
Err(AppError::Validation("Draft entry path must stay inside the draft
directory".to_string())). Locate the check that iterates path.components() and
add matches for Prefix(_) and RootDir alongside ParentDir to ensure Windows
drive-relative inputs like "C:temp\\file" are refused.

---

Duplicate comments:
In `@src-tauri/src/api/agent_control.rs`:
- Around line 62-68: The code currently calls
service.take_pending_token(&id).await? (consuming the one-time token) before
calling app.clipboard().write_text(token), which loses the token on clipboard
failure; change the flow so the token is not consumed until clipboard write
succeeds: either use a non-consuming read API on service (e.g.,
peek_pending_token or similar) and only call take_pending_token(&id) after
write_text succeeds, or if no non-consuming API exists, attempt to write_text
first and on error call a restore method on service (e.g.,
restore_pending_token(&id, token)) before returning an AppError::External;
update references to take_pending_token, app.clipboard().write_text, service,
id, token, and AppError::External accordingly.

In `@src-tauri/src/domain/integration_api/routing.rs`:
- Around line 251-258: The code currently uses `?` on
`sync_launcher_selected_module(&context, client, module_id).await` inside the
block that handles a successful module control response, which turns any UI
sync/save/emit failure into an overall error; instead, call and await
`sync_launcher_selected_module` and handle its Result locally (e.g., `if let
Err(e) = sync_launcher_selected_module(...).await { ... }`) so the successful
response from the module action (ModuleAction::Start | Restart | Repair) is
preserved; log or trace the error (using the existing logger/context) and
continue without propagating the error to the caller.
- Around line 114-117: The approvals endpoint currently permits
AuthorizedClient::Agent(_) with Observe scope and returns state.approvals
unfiltered, allowing cross-agent leakage; update handle_agent_approvals_request
to accept the caller's agent identity (or the AuthorizedClient) and filter
state.approvals to only include approvals scoped to that agent (e.g., match
approval.target_agent_id or approval.agent_id against the caller's agent id) and
ensure the routing/authorization (ensure_agent_scope / AuthorizedClient::Agent)
passes the caller identity through to the handler so only the caller's approvals
are returned.

In `@src/features/settings/ui/SettingsUI.ts`:
- Line 136: The code currently hardcodes an English fallback string in the i18n
call for the label (const label =
this._i18n.t('ui.launcher.settings.section_jump', 'Switch settings section')),
which violates the rule to keep UI text in locale files; add the key
ui.launcher.settings.section_jump to the src-tauri/resources/locales/* locale
JSON/YAML files with appropriate translations (including English), then remove
the hardcoded fallback from the call and call
this._i18n.t('ui.launcher.settings.section_jump') (or ensure the t function uses
locale files by default) so the label is sourced from the localization resources
instead of inline text.

In `@src/public/templates/pages/settings.html`:
- Around line 39-40: Remove the hardcoded English title and aria-label
attributes from the button (the element in settings.html that currently has
title="Switch settings section" and aria-label="Switch settings section") and
replace them with the appropriate i18n attributes/keys so the tooltip/accessible
label comes from the locale resources under src-tauri/resources/locales/ (use
the same i18n key pattern already used by this control so translations are
loaded instead of hardcoding English).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 01e7f732-9e37-4dec-a432-c0e7fefb51e0

📥 Commits

Reviewing files that changed from the base of the PR and between ee7c14a and 18c4b22.

⛔ Files ignored due to path filters (1)
  • src/assets/fonts/Cubic_11.zh-subset.woff2 is excluded by !**/*.woff2
📒 Files selected for processing (25)
  • SECURITY.md
  • docs/examples/sdk/javascript/axelate-client.mjs
  • docs/examples/sdk/python/axelate_sdk.py
  • docs/localization/en/AGENT_CONTROL.md
  • docs/localization/en/INTEGRATION_API.md
  • docs/localization/en/ROADMAP.md
  • docs/localization/en/TRUST_MODEL.md
  • src-tauri/resources/locales/en.json
  • src-tauri/resources/locales/ru.json
  • src-tauri/resources/locales/zh.json
  • src-tauri/src/api/agent_control.rs
  • src-tauri/src/domain/agent_control.rs
  • src-tauri/src/domain/integration_api/routing.rs
  • src-tauri/src/domain/integration_api/tests.rs
  • src-tauri/src/lib.rs
  • src/features/settings/services/SettingsService.test.ts
  • src/features/settings/services/SettingsService.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.test.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.ts
  • src/features/settings/ui/SettingsPageUI.test.ts
  • src/features/settings/ui/SettingsUI.ts
  • src/public/templates/pages/settings.html
  • src/shared/types/bindings.ts
  • src/styles/features/console-page.css
  • src/styles/features/settings-page.css
💤 Files with no reviewable changes (3)
  • src-tauri/src/lib.rs
  • src/features/settings/services/SettingsService.ts
  • src/shared/types/bindings.ts
✅ Files skipped from review due to trivial changes (3)
  • SECURITY.md
  • docs/localization/en/AGENT_CONTROL.md
  • docs/localization/en/ROADMAP.md

Comment thread src/styles/features/settings-page.css Outdated
@F0RLE

F0RLE commented May 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@F0RLE

F0RLE commented May 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@F0RLE

F0RLE commented May 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@F0RLE

F0RLE commented May 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
src/app/CoreStateRestore.ts (1)

76-89: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore path now drops any non-catalog selected module IDs.

After this change, unresolved IDs always return null, so persisted selections outside the current catalog snapshot won’t restore and are silently downgraded to warnings. That’s a user-visible state regression for previously valid saved selections.

Suggested direction
 function resolveRestoredApp(
     catalog: CatalogService,
-    _category: string,
+    category: string,
     selectedModule: Partial<IApp>,
 ): IApp | null {
@@
     const catalogApp = catalog.getAppById(selectedModule.id);
     if (catalogApp !== undefined) {
         return catalogApp;
     }
+
+    // Preserve restore for persisted AI selections not present in the static catalog snapshot.
+    if ((category === 'ai_text' || category === 'ai_image') && selectedModule.name) {
+        return selectedModule as IApp;
+    }

     return null;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/CoreStateRestore.ts` around lines 76 - 89, The restore currently
returns null for any selectedModule.id not found in catalog (via getAppById),
which drops persisted selections; instead, when typeof selectedModule.id ===
'string' but catalog.getAppById(selectedModule.id) returns undefined, construct
and return a fallback IApp that preserves the persisted id and any available
fields from selectedModule (e.g., name, version) and sets sensible defaults for
required IApp properties plus a flag/marker (e.g., missingFromCatalog or source:
'restored') so callers can detect a non-catalog app; update the function
handling around selectedModule, catalogApp and IApp construction to
cast/populate fields from Partial<IApp> and avoid returning null for unresolved
IDs.
src-tauri/src/domain/integration_api/mod.rs (1)

289-305: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Restore bearer-token authorization in HTTP preflight.

After loopback validation, all non-health requests are accepted without checking AXELATE_HTTP_API_TOKEN. That allows any local process to call integration endpoints and bypasses module-scoped token gating.

Suggested fix
 fn preflight_http_request(
     request: &types::HttpRequest,
     peer_addr: Option<std::net::SocketAddr>,
 ) -> Option<types::HttpResponse> {
     if !is_loopback_peer(peer_addr) {
         return Some(json_error(
             403,
             "Launcher API only accepts loopback clients",
         ));
     }

     let path = http::request_path(request);
     if request.method == "GET" && path == "/v1/health" {
         return None;
     }

+    if !auth::is_authorized(&request.headers) {
+        return Some(json_error(401, "Unauthorized"));
+    }
+
     None
 }
As per coding guidelines, "src-tauri/src/**/*.rs: Review as a Windows-first Tauri backend. Prioritize IPC boundary validation..."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/domain/integration_api/mod.rs` around lines 289 - 305,
preflight_http_request currently skips token checks for non-health requests;
restore bearer-token auth by reading the configured token (e.g.,
AXELATE_HTTP_API_TOKEN) and rejecting requests without a matching Authorization:
Bearer <token> header. Modify preflight_http_request (taking types::HttpRequest
and returning Option<types::HttpResponse>) so after the loopback check and after
allowing GET /v1/health, read the incoming Authorization header (use your
existing http helpers or request.headers) and if a token is configured but the
header is missing or doesn’t match, return Some(json_error(401,
"Unauthorized")); otherwise continue to accept the request (return None).
src-tauri/src/domain/ai/session.rs (1)

103-137: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Retry path waits longer than advertised.

After the failure branches sleep retry_delay, the re-notified loop still hits the unconditional debounce at Line 103. Failed saves therefore retry after retry_delay + SAVE_DEBOUNCE_DELAY, while the log message and save_retry_delay() tests describe only the backoff delay. Retry inline or bypass the debounce for failure requeues.

src-tauri/src/api/system/logs.rs (1)

78-80: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Canonicalize console view ID before resolving log target.

open_console_log_target skips canonicalization, unlike get_console_logs and clear_console_logs. This can cause folder-open to fail for equivalent IDs with spacing/alias formatting.

Suggested fix
 pub fn open_console_log_target(view_id: String) -> Result<(), AppError> {
-    let target = resolve_console_log_target(&view_id)?;
+    let canonical_view_id = canonical_console_view_id(&view_id);
+    let target = resolve_console_log_target(&canonical_view_id)?;
     fs::create_dir_all(&target)?;
     open_folder(&target)?;
     Ok(())
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/api/system/logs.rs` around lines 78 - 80,
open_console_log_target currently uses the raw view_id while get_console_logs
and clear_console_logs canonicalize IDs first; modify open_console_log_target to
first call the same canonicalization helper (e.g., canonicalize_console_view_id
or the existing canonicalize function used by
get_console_logs/clear_console_logs) on the incoming view_id, then pass the
canonicalized ID to resolve_console_log_target and to fs::create_dir_all so
equivalent IDs with spacing/aliases resolve to the same folder.
src-tauri/src/domain/modules/controller/script_runtime.rs (1)

638-648: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Include package manager in JS dependency stamp invalidation.

Changing runtime.package_manager (e.g., npm→bun) with unchanged dependency file currently skips reinstall due to stamp cache hit, which can leave an incompatible env.

Suggested fix
-    let dependencies_hash = compute_sha256(&dependencies_path)?;
+    let dependencies_hash = compute_sha256(&dependencies_path)?;
+    let manager = resolve_js_package_manager(manifest, default_package_manager)?;
+    let install_fingerprint = format!("{manager}:{dependencies_hash}");
     let stamp_path = js_dependencies_stamp_path(env_dir);
     if stamp_path.exists()
         && fs::read_to_string(&stamp_path)
             .map(|value| value.trim().to_string())
             .ok()
-            .is_some_and(|value| value == dependencies_hash)
+            .is_some_and(|value| value == install_fingerprint)
     {
         return Ok(());
     }
@@
-    let manager = resolve_js_package_manager(manifest, default_package_manager)?;
     let package_manager = find_program(manager).await?;
@@
-    fs::write(&stamp_path, format!("{dependencies_hash}\n")).map_err(|e| {
+    fs::write(&stamp_path, format!("{install_fingerprint}\n")).map_err(|e| {

Also applies to: 668-694

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/domain/modules/controller/script_runtime.rs` around lines 638 -
648, The dependency-stamp logic (using js_dependencies_stamp_path,
compute_sha256, dependencies_hash, and stamp_path) only considers the dependency
file hash and thus ignores changes to runtime.package_manager; update the stamp
generation and comparison to include the package manager (e.g., concatenate or
hash runtime.package_manager with the dependencies file contents to produce
dependencies_hash) so that a package_manager change invalidates the stamp and
forces reinstall; apply the same fix to the other identical block referenced
around the 668-694 region so both checks use the combined hash.
♻️ Duplicate comments (1)
src/features/console/ui/ConsoleFilterControlHelper.ts (1)

162-167: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove hardcoded English fallback strings from user-visible TS labels.

These _t(key, '...') calls still embed user-facing English in frontend code (Confirm clear..., Right-click again..., Clear Console). Move the visible fallback text responsibility to locale resources/central i18n resolution and keep this file key-only.

As per coding guidelines: "Keep UI text in I18n resources under src-tauri/resources/locales/ and do not hardcode Russian or English user-facing strings in TS/HTML".

Also applies to: 182-189, 209-214

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/console/ui/ConsoleFilterControlHelper.ts` around lines 162 -
167, Replace hardcoded English fallback strings in all this._t(...) calls inside
ConsoleFilterControlHelper (e.g., the calls used to set aria-label, button.title
and other UI labels) by passing only the i18n key (for example use
this._t('ui.debug.logs_clear_confirm') instead of
this._t('ui.debug.logs_clear_confirm', 'Confirm clear console logs')); move the
visible fallback texts into your locale resources under the app’s i18n files
(add the corresponding entries for keys like ui.debug.logs_clear_confirm,
ui.debug.logs_clear_confirm_title, and the keys referenced around the other
callsites) and then remove the second-argument fallback from each this._t
invocation so the component is key-only.
🧹 Nitpick comments (5)
src-tauri/src/api/ai/mod.rs (1)

760-761: ⚡ Quick win

Refactor to avoid computing unused path on macOS.

On macOS, path is computed (line 759) but never used—the command block at line 777 uses file instead. The let _ = &path; suppresses the compiler warning, but it's cleaner to conditionally compute path only on platforms that use it, or refactor the macOS flow to use path consistently.

♻️ Option 1: Conditionally compute path
+#[cfg(not(target_os = "macos"))]
 let path = image_open_directory(&file, open_folder_only)?;
-#[cfg(target_os = "macos")]
-let _ = &path;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/api/ai/mod.rs` around lines 760 - 761, The code computes `path`
on all platforms but only uses `file` in the macOS command block, so remove the
unused `path` allocation on macOS by either 1) making its declaration
conditional (e.g., #[cfg(not(target_os = "macos"))] let path = ...) so `path` is
only computed where used, or 2) make the macOS branch use `path` consistently
instead of `file` (update the macOS command block to reference `path`), ensuring
you remove the temporary `let _ = &path;` suppression and keep only the needed
variable depending on the branch.
src/features/console/services/ConsoleLogNormalizer.ts (1)

15-25: ⚖️ Poor tradeoff

Consider documenting the fallback normalization contract.

The normalizer now preserves pre-populated fields (display_time, normalized_level, scope, etc.) and only computes values when they are missing. This assumes upstream callers apply the same normalization rules. If normalization logic evolves, pre-populated fields won't be re-normalized, potentially causing inconsistencies.

Consider adding a comment or type annotation clarifying which callers are expected to pre-normalize, or enforce a single normalization path to ensure consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/console/services/ConsoleLogNormalizer.ts` around lines 15 - 25,
The current ConsoleLogNormalizer implementation conditionally preserves
pre-populated fields (display_time, normalized_level, scope, summary_message,
source_label, source_class, page, action, expected) instead of always applying
normalization, which can lead to inconsistent logs if upstream callers mutate
normalization rules; update ConsoleLogNormalizer (the normalization object
creation and the methods _formatSourceLabel, _extractPage, _extractAction,
_extractExpected) to enforce a single normalization path by either (a)
documenting the contract clearly near the class that callers must pass
already-normalized fields, or preferably (b) always running the normalizer logic
and overriding incoming values so normalization rules are applied centrally; add
a concise comment above ConsoleLogNormalizer explaining the chosen approach and
ensure source_class logic (module: check) and source_label formatting remain
applied when overriding to preserve existing behavior.
src/app/CoreStateRestore.test.ts (1)

67-69: ⚡ Quick win

Tighten this test to match catalog contract and avoid permissive pass

Use null for missing getAppById results and assert exact call count/order; toHaveBeenCalledWith alone can pass even with extra unexpected calls.

Suggested diff
             catalog: {
                 getAppById: (appId: string) =>
-                    appId === CUSTOM_TEXT_PROVIDER_ID ? customTextApp : undefined,
+                    appId === CUSTOM_TEXT_PROVIDER_ID ? customTextApp : null,
             } as never,
@@
-        expect(updateModuleCard).toHaveBeenCalledWith('ai_text', customTextApp);
+        expect(updateModuleCard).toHaveBeenCalledTimes(1);
+        expect(updateModuleCard).toHaveBeenNthCalledWith(1, 'ai_text', customTextApp);

Also applies to: 75-75

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/CoreStateRestore.test.ts` around lines 67 - 69, The test currently
returns undefined for missing apps and only checks toHaveBeenCalledWith which
can hide extra calls; update the mock getAppById to return null instead of
undefined for non-matching appIds (keep the CUSTOM_TEXT_PROVIDER_ID =>
customTextApp mapping) and add explicit call count/order assertions (e.g., use
toHaveBeenCalledTimes and toHaveBeenNthCalledWith or equivalent) to validate
exact invocation sequence of getAppById in CoreStateRestore.test.ts.
src/features/settings/ui/SettingsPageUI.test.ts (1)

57-58: 💤 Low value

Redundant mock cleanup.

vi.restoreAllMocks() already includes clearing spies. The preceding vi.clearAllMocks() is redundant.

     vi.clearAllMocks();
-    vi.restoreAllMocks();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/settings/ui/SettingsPageUI.test.ts` around lines 57 - 58, The
test cleanup calls both vi.clearAllMocks() and vi.restoreAllMocks(); remove the
redundant vi.clearAllMocks() call and keep only vi.restoreAllMocks() in the
afterEach/teardown so mocks/spies are both cleared and restored (update the code
around vi.clearAllMocks() / vi.restoreAllMocks() in SettingsPageUI.test.ts).
src/features/ai/ui/AISettingsViewPolicy.ts (1)

4-10: ⚡ Quick win

Tighten isCleanApp input contract to avoid silent false negatives.

string inputs always return false in the current implementation. Either remove string from the signature or implement explicit string-id lookup so valid callers don’t get misleading results.

Suggested fix (type-tightening)
-    public isCleanApp(app: IApp | string): boolean {
-        const policy = typeof app === 'string' ? null : app.providerPolicy;
-        if (policy?.isCleanApp !== undefined) {
-            return policy.isCleanApp;
-        }
-
-        return false;
-    }
+    public isCleanApp(app: IApp): boolean {
+        return app.providerPolicy?.isCleanApp ?? false;
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/ai/ui/AISettingsViewPolicy.ts` around lines 4 - 10, The
isCleanApp method currently accepts IApp | string but treats string IDs as null
and returns false, causing silent false negatives; either tighten the signature
to accept only IApp (remove string from isCleanApp(…) and update all callers to
resolve IDs before calling) or implement an explicit ID lookup path inside
isCleanApp by resolving the string to an IApp (e.g., via your app
registry/lookup API) then reading providerPolicy.isCleanApp; update references
to the method accordingly and ensure providerPolicy and isCleanApp checks remain
the same once the app object is resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 148-150: The job-level "continue-on-error: true" makes the entire
cross-platform job non-blocking; remove that key from the job definition and
keep "strategy: fail-fast: false" only so the job fails CI on regressions while
still running all matrix entries, or if you truly need non-blocking behavior
make the failure explicit by applying "continue-on-error" to specific steps or
using an allowed_failures matrix entry instead; update the CI YAML to delete the
"continue-on-error: true" line and ensure any intentional non-blocking behavior
is limited to named steps or matrix configuration.

In `@docs/localization/en/CURRENT_STATE.md`:
- Around line 308-311: Remove the four bullets that are already implemented so
the “not yet” list matches reality: delete the lines containing "agent scopes
and approval prompts", "sanitized console log APIs meant for external agents",
"integration draft generation through the launcher", and "an Axelate MCP server
backed by documented launcher capabilities" from the CURRENT_STATE not-yet list
so they no longer contradict the new sections that document these features as
current behavior.

In `@docs/localization/en/TRUST_MODEL.md`:
- Around line 106-108: Update the TRUST_MODEL.md wording so it matches the
actual implementation: remove the claim "The full token is shown once" and
instead state the token is available via the copy-only flow (or reference the
exact non-frontend reveal API if one exists); mention the profile types "Trusted
Local" and "Full Access" and the exposed function/endpoint name
copyAgentProfileToken so readers know where token retrieval occurs, and note
that tokens can be rotated or deleted by the user via the existing local tool or
API.

In `@docs/localization/zh/README.md`:
- Line 28: Remove the future-feature clause "MCP、SDK 和完整的包权限模型" from the README
index line that currently reads "第一版本地 Agent Control 已在 `AGENT_CONTROL.md`
中说明;MCP、SDK 和完整的包权限模型仍是后续阶段.", and instead add that roadmap detail as a short
entry in your planning doc (create or append to VISION.md or ROADMAP.md) so
README stays focused on current-state docs; keep the README line limited to
referencing AGENT_CONTROL.md and move the exact phrase "MCP、SDK 和完整的包权限模型仍是后续阶段"
into the new or existing VISION.md/ROADMAP.md with a brief roadmap note.

In `@src-tauri/resources/locales/en.json`:
- Line 269: The JSON key "ui.launcher.settings.agent_control_trusted_local" is
mapped to the incorrect string "Selected Permissions"; update its value to a
semantically correct label for the "trusted_local" concept (for example "Trusted
Local Agents" or "Trusted Local Devices" depending on UI context) so the UI
displays the intended meaning; locate the key "agent_control_trusted_local" in
the locales file and replace the string value with the appropriate label used
elsewhere for trusted-local semantics.

In `@src-tauri/src/api/system/config.rs`:
- Line 193: The snapshot builder currently sets config_schema only from
installed_module (installed_module.and_then(|module|
module.config_schema.clone())), which causes catalog-only items to lose their
ModuleItem.config_schema; change the assignment to fall back to the catalog
item's module schema when installed_module is None (e.g.
installed_module.and_then(|m| m.config_schema.clone()).or_else(||
catalog_item.module.as_ref().and_then(|m| m.config_schema.clone()))),
referencing config_schema, installed_module, and ModuleItem.config_schema to
locate the fields to update.

In `@src-tauri/src/domain/integration_api/routing.rs`:
- Around line 123-167: The routes handling "/v1/launcher/open-page",
"/v1/launcher/select-module", and "/v1/integration-drafts" currently rely only
on ensure_agent_scope (e.g., ensure_agent_scope(client, AgentScope::Operate) and
AgentScope::DraftCreate) which permits AuthorizedClient::Module(_); add an
explicit guard to reject module-scoped tokens before performing the action:
after the ensure_agent_scope call in the blocks for handle_open_page_request,
handle_select_module_request, and handle_create_integration_draft_request, check
the client identity and return an authorization error if the client is a Module
(AuthorizedClient::Module(_)); keep the existing audit calls
(record_agent_audit) and responses unchanged but ensure the Module case is
denied to prevent launcher-wide mutation from module-scoped tokens.

In `@src/app/CoreLifecycleController.ts`:
- Around line 297-301: The event callback currently calls void
this._applyAgentOpenPageRequest(payload) which ignores rejections and can cause
unhandled promise rejections if showPage(...) inside fails; update the
tauriProvider.listen callbacks (the one using this._applyAgentOpenPageRequest at
the 'agent-control:open-page' listener and the other occurrence at lines
~319-320) to handle the returned promise by either awaiting it in an async
callback or appending .catch(...) to log/report errors (e.g., call
this._applyAgentOpenPageRequest(payload).catch(err => /* log or handle err */))
so all rejections are caught and handled.

In `@src/features/ai/ui/AISettingsRenderer.ts`:
- Around line 399-402: The fallback string "Manual OpenAI-compatible model ID"
is hardcoded in AISettingsRenderer (the desc: translate(...) call); remove the
inline English string and add the text to your i18n locale files under the key
"ui.settings.custom_model_desc" (and translations for other locales), then call
translate('ui.settings.custom_model_desc') (or supply a non-user-facing
fallback) from the desc property so no user-facing text remains in TS.
- Around line 567-569: _getKeyProviderUrl currently returns a fallback '#' which
can be passed to shell-open; instead validate the resolved URL's protocol and
only return it if it's http or https (or return null) to prevent unsafe
shell-open calls. Locate _getKeyProviderUrl and its use of
_getActiveProviderPolicy, change the function to parse/validate the URL scheme
(allow only "http:" or "https:") and return null when invalid; update callers
that call openUrl (e.g., places invoking openUrl with _getKeyProviderUrl) to
no-op when the function returns null so openUrl is only called with safe public
protocols. Ensure similar validation is applied to the other occurrences noted
(lines referenced 256-258) that feed external URLs to shell-open.

In `@src/public/templates/pages/settings.html`:
- Around line 5-10: Remove the hardcoded English fallback text inside the
elements that already use data-i18n: clear the inner text of the <div
class="module-title" data-i18n="ui.launcher.settings.taskbar_title"> and the
<div class="module-desc" data-i18n="ui.launcher.settings.taskbar_desc"> so they
contain no hardcoded strings; instead ensure the keys
ui.launcher.settings.taskbar_title and ui.launcher.settings.taskbar_desc exist
in the src-tauri/resources/locales/ i18n resource files for all supported
languages (also remove/clear similar inline text in the other affected cards
around the same block, noted in the comment for lines ~15-20).

---

Outside diff comments:
In `@src-tauri/src/api/system/logs.rs`:
- Around line 78-80: open_console_log_target currently uses the raw view_id
while get_console_logs and clear_console_logs canonicalize IDs first; modify
open_console_log_target to first call the same canonicalization helper (e.g.,
canonicalize_console_view_id or the existing canonicalize function used by
get_console_logs/clear_console_logs) on the incoming view_id, then pass the
canonicalized ID to resolve_console_log_target and to fs::create_dir_all so
equivalent IDs with spacing/aliases resolve to the same folder.

In `@src-tauri/src/domain/integration_api/mod.rs`:
- Around line 289-305: preflight_http_request currently skips token checks for
non-health requests; restore bearer-token auth by reading the configured token
(e.g., AXELATE_HTTP_API_TOKEN) and rejecting requests without a matching
Authorization: Bearer <token> header. Modify preflight_http_request (taking
types::HttpRequest and returning Option<types::HttpResponse>) so after the
loopback check and after allowing GET /v1/health, read the incoming
Authorization header (use your existing http helpers or request.headers) and if
a token is configured but the header is missing or doesn’t match, return
Some(json_error(401, "Unauthorized")); otherwise continue to accept the request
(return None).

In `@src-tauri/src/domain/modules/controller/script_runtime.rs`:
- Around line 638-648: The dependency-stamp logic (using
js_dependencies_stamp_path, compute_sha256, dependencies_hash, and stamp_path)
only considers the dependency file hash and thus ignores changes to
runtime.package_manager; update the stamp generation and comparison to include
the package manager (e.g., concatenate or hash runtime.package_manager with the
dependencies file contents to produce dependencies_hash) so that a
package_manager change invalidates the stamp and forces reinstall; apply the
same fix to the other identical block referenced around the 668-694 region so
both checks use the combined hash.

In `@src/app/CoreStateRestore.ts`:
- Around line 76-89: The restore currently returns null for any
selectedModule.id not found in catalog (via getAppById), which drops persisted
selections; instead, when typeof selectedModule.id === 'string' but
catalog.getAppById(selectedModule.id) returns undefined, construct and return a
fallback IApp that preserves the persisted id and any available fields from
selectedModule (e.g., name, version) and sets sensible defaults for required
IApp properties plus a flag/marker (e.g., missingFromCatalog or source:
'restored') so callers can detect a non-catalog app; update the function
handling around selectedModule, catalogApp and IApp construction to
cast/populate fields from Partial<IApp> and avoid returning null for unresolved
IDs.

---

Duplicate comments:
In `@src/features/console/ui/ConsoleFilterControlHelper.ts`:
- Around line 162-167: Replace hardcoded English fallback strings in all
this._t(...) calls inside ConsoleFilterControlHelper (e.g., the calls used to
set aria-label, button.title and other UI labels) by passing only the i18n key
(for example use this._t('ui.debug.logs_clear_confirm') instead of
this._t('ui.debug.logs_clear_confirm', 'Confirm clear console logs')); move the
visible fallback texts into your locale resources under the app’s i18n files
(add the corresponding entries for keys like ui.debug.logs_clear_confirm,
ui.debug.logs_clear_confirm_title, and the keys referenced around the other
callsites) and then remove the second-argument fallback from each this._t
invocation so the component is key-only.

---

Nitpick comments:
In `@src-tauri/src/api/ai/mod.rs`:
- Around line 760-761: The code computes `path` on all platforms but only uses
`file` in the macOS command block, so remove the unused `path` allocation on
macOS by either 1) making its declaration conditional (e.g., #[cfg(not(target_os
= "macos"))] let path = ...) so `path` is only computed where used, or 2) make
the macOS branch use `path` consistently instead of `file` (update the macOS
command block to reference `path`), ensuring you remove the temporary `let _ =
&path;` suppression and keep only the needed variable depending on the branch.

In `@src/app/CoreStateRestore.test.ts`:
- Around line 67-69: The test currently returns undefined for missing apps and
only checks toHaveBeenCalledWith which can hide extra calls; update the mock
getAppById to return null instead of undefined for non-matching appIds (keep the
CUSTOM_TEXT_PROVIDER_ID => customTextApp mapping) and add explicit call
count/order assertions (e.g., use toHaveBeenCalledTimes and
toHaveBeenNthCalledWith or equivalent) to validate exact invocation sequence of
getAppById in CoreStateRestore.test.ts.

In `@src/features/ai/ui/AISettingsViewPolicy.ts`:
- Around line 4-10: The isCleanApp method currently accepts IApp | string but
treats string IDs as null and returns false, causing silent false negatives;
either tighten the signature to accept only IApp (remove string from
isCleanApp(…) and update all callers to resolve IDs before calling) or implement
an explicit ID lookup path inside isCleanApp by resolving the string to an IApp
(e.g., via your app registry/lookup API) then reading providerPolicy.isCleanApp;
update references to the method accordingly and ensure providerPolicy and
isCleanApp checks remain the same once the app object is resolved.

In `@src/features/console/services/ConsoleLogNormalizer.ts`:
- Around line 15-25: The current ConsoleLogNormalizer implementation
conditionally preserves pre-populated fields (display_time, normalized_level,
scope, summary_message, source_label, source_class, page, action, expected)
instead of always applying normalization, which can lead to inconsistent logs if
upstream callers mutate normalization rules; update ConsoleLogNormalizer (the
normalization object creation and the methods _formatSourceLabel, _extractPage,
_extractAction, _extractExpected) to enforce a single normalization path by
either (a) documenting the contract clearly near the class that callers must
pass already-normalized fields, or preferably (b) always running the normalizer
logic and overriding incoming values so normalization rules are applied
centrally; add a concise comment above ConsoleLogNormalizer explaining the
chosen approach and ensure source_class logic (module: check) and source_label
formatting remain applied when overriding to preserve existing behavior.

In `@src/features/settings/ui/SettingsPageUI.test.ts`:
- Around line 57-58: The test cleanup calls both vi.clearAllMocks() and
vi.restoreAllMocks(); remove the redundant vi.clearAllMocks() call and keep only
vi.restoreAllMocks() in the afterEach/teardown so mocks/spies are both cleared
and restored (update the code around vi.clearAllMocks() / vi.restoreAllMocks()
in SettingsPageUI.test.ts).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c6111a9f-82d3-44b1-ba2d-e4f62f42859e

📥 Commits

Reviewing files that changed from the base of the PR and between bd89c47 and 735bb90.

⛔ Files ignored due to path filters (3)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
  • src/assets/fonts/Cubic_11.zh-subset.woff2 is excluded by !**/*.woff2
  • src/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (133)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/dependency-review.yml
  • .github/workflows/release.yml
  • .github/workflows/security-audit.yml
  • SECURITY.md
  • docs/examples/sdk/javascript/axelate-client.mjs
  • docs/examples/sdk/python/axelate_sdk.py
  • docs/localization/en/AGENT_CONTROL.md
  • docs/localization/en/ARCHITECTURE.md
  • docs/localization/en/CURRENT_STATE.md
  • docs/localization/en/DEVELOPMENT_WORKFLOW.md
  • docs/localization/en/INTEGRATION_API.md
  • docs/localization/en/INTEGRATION_DEVELOPMENT.md
  • docs/localization/en/README.md
  • docs/localization/en/ROADMAP.md
  • docs/localization/en/TRUST_MODEL.md
  • docs/localization/en/VISION.md
  • docs/localization/ru/INTEGRATION_DEVELOPMENT.md
  • docs/localization/ru/README.md
  • docs/localization/zh/INTEGRATION_DEVELOPMENT.md
  • docs/localization/zh/README.md
  • src-tauri/Cargo.toml
  • src-tauri/resources/locales/en.json
  • src-tauri/resources/locales/ru.json
  • src-tauri/resources/locales/zh.json
  • src-tauri/src/api/agent_control.rs
  • src-tauri/src/api/ai/mod.rs
  • src-tauri/src/api/mod.rs
  • src-tauri/src/api/modules/mod.rs
  • src-tauri/src/api/system/config.rs
  • src-tauri/src/api/system/console_overview.rs
  • src-tauri/src/api/system/log_targets.rs
  • src-tauri/src/api/system/logs.rs
  • src-tauri/src/api/system/mod.rs
  • src-tauri/src/app/window.rs
  • src-tauri/src/domain/agent_control.rs
  • src-tauri/src/domain/ai/ai_dispatch.rs
  • src-tauri/src/domain/ai/ai_provider_resolution.rs
  • src-tauri/src/domain/ai/ai_service.rs
  • src-tauri/src/domain/ai/ai_validation.rs
  • src-tauri/src/domain/ai/mod.rs
  • src-tauri/src/domain/ai/provider_payload.rs
  • src-tauri/src/domain/ai/session.rs
  • src-tauri/src/domain/ai/session_context.rs
  • src-tauri/src/domain/ai/streaming.rs
  • src-tauri/src/domain/ai/streaming_chunks.rs
  • src-tauri/src/domain/engine/engine_ids.rs
  • src-tauri/src/domain/engine/manager.rs
  • src-tauri/src/domain/engine/mod.rs
  • src-tauri/src/domain/integration_api/auth.rs
  • src-tauri/src/domain/integration_api/mod.rs
  • src-tauri/src/domain/integration_api/routing.rs
  • src-tauri/src/domain/integration_api/tests.rs
  • src-tauri/src/domain/integration_api/types.rs
  • src-tauri/src/domain/mod.rs
  • src-tauri/src/domain/modules/controller/lifecycle.rs
  • src-tauri/src/domain/modules/controller/mod.rs
  • src-tauri/src/domain/modules/controller/process.rs
  • src-tauri/src/domain/modules/controller/script_runtime.rs
  • src-tauri/src/domain/modules/github_release_targets.rs
  • src-tauri/src/domain/modules/github_releases.rs
  • src-tauri/src/domain/modules/mod.rs
  • src-tauri/src/domain/system/hardware_probe.rs
  • src-tauri/src/infrastructure/logging/logger.rs
  • src-tauri/src/infrastructure/system/startup.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/models/config.rs
  • src-tauri/src/models/modules.rs
  • src-tauri/src/utils/memory.rs
  • src-tauri/src/utils/paths.rs
  • src/app/CoreLifecycleController.test.ts
  • src/app/CoreLifecycleController.ts
  • src/app/CoreServiceFactory.ts
  • src/app/CoreStateRestore.test.ts
  • src/app/CoreStateRestore.ts
  • src/features/ai/services/AIBridge.test.ts
  • src/features/ai/services/AIBridge.ts
  • src/features/ai/services/AIBridgeConfig.ts
  • src/features/ai/services/AIBridgeMessageController.test.ts
  • src/features/ai/services/AIBridgeMessageController.ts
  • src/features/ai/services/AIBridgeProviderPolicy.test.ts
  • src/features/ai/services/AIBridgeProviderPolicy.ts
  • src/features/ai/services/AIChatTransport.test.ts
  • src/features/ai/services/AIChatTransport.ts
  • src/features/ai/services/AIProviderManager.test.ts
  • src/features/ai/services/AIProviderManager.ts
  • src/features/ai/services/EngineStatusService.test.ts
  • src/features/ai/services/EngineStatusService.ts
  • src/features/ai/types/aiTypes.ts
  • src/features/ai/ui/AISettingsContentRenderer.ts
  • src/features/ai/ui/AISettingsKeyController.test.ts
  • src/features/ai/ui/AISettingsKeyController.ts
  • src/features/ai/ui/AISettingsRenderer.test.ts
  • src/features/ai/ui/AISettingsRenderer.ts
  • src/features/ai/ui/AISettingsSelectionController.ts
  • src/features/ai/ui/AISettingsViewPolicy.test.ts
  • src/features/ai/ui/AISettingsViewPolicy.ts
  • src/features/console/services/ConsoleLogNormalizer.ts
  • src/features/console/services/ConsoleLogService.test.ts
  • src/features/console/services/ConsoleLogService.ts
  • src/features/console/ui/ConsoleFilterControlHelper.ts
  • src/features/console/ui/ConsoleLogPresentationHelper.ts
  • src/features/console/ui/ConsoleUI.test.ts
  • src/features/console/ui/ConsoleUI.ts
  • src/features/console/ui/ConsoleViewHelper.ts
  • src/features/settings/index.ts
  • src/features/settings/services/SettingsService.test.ts
  • src/features/settings/services/SettingsService.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.test.ts
  • src/features/settings/ui/AgentControlSettingsRenderer.ts
  • src/features/settings/ui/SettingsPageUI.test.ts
  • src/features/settings/ui/SettingsUI.ts
  • src/public/templates/pages/console.html
  • src/public/templates/pages/settings.html
  • src/shared/services/CatalogLoadSnapshot.ts
  • src/shared/services/CatalogService.test.ts
  • src/shared/services/CatalogService.ts
  • src/shared/shell/AppUI.test.ts
  • src/shared/shell/AppUI.ts
  • src/shared/shell/ui/AppUiDashboardSupport.ts
  • src/shared/shell/ui/card/ModuleCardRenderer.test.ts
  • src/shared/shell/ui/card/ModuleCardRenderer.ts
  • src/shared/types/bindings.ts
  • src/shared/types/coreTypes.ts
  • src/shared/utils/customProviderSupport.test.ts
  • src/shared/utils/customProviderSupport.ts
  • src/shared/utils/providerSupport.test.ts
  • src/shared/utils/providerSupport.ts
  • src/styles/features/console-page.css
  • src/styles/features/settings-page.css
  • src/test/helpers/catalogTestUtils.ts
  • src/test/integration/CatalogService.integration.test.ts
💤 Files with no reviewable changes (7)
  • src/features/ai/services/EngineStatusService.ts
  • src/shared/utils/providerSupport.ts
  • src-tauri/src/infrastructure/system/startup.rs
  • src/shared/utils/providerSupport.test.ts
  • src/shared/services/CatalogLoadSnapshot.ts
  • src/shared/utils/customProviderSupport.ts
  • src/shared/utils/customProviderSupport.test.ts

Comment thread .github/workflows/ci.yml Outdated
Comment thread docs/localization/en/CURRENT_STATE.md Outdated
Comment thread docs/localization/en/TRUST_MODEL.md Outdated
Comment thread docs/localization/zh/README.md Outdated
Comment thread src-tauri/resources/locales/en.json Outdated
Comment thread src-tauri/src/domain/modules/github_release_targets.rs Outdated
Comment thread src/app/CoreLifecycleController.ts
Comment thread src/features/ai/ui/AISettingsRenderer.ts Outdated
Comment thread src/features/ai/ui/AISettingsRenderer.ts Outdated
Comment thread src/public/templates/pages/settings.html Outdated
@F0RLE

F0RLE commented May 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@F0RLE F0RLE merged commit 9b97fa0 into nightly May 29, 2026
6 checks passed
@F0RLE F0RLE deleted the F0RLE/code-quality-stabilization branch May 29, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant