feat(desktop, analytics): add packaging and usage export#172
feat(desktop, analytics): add packaging and usage export#172awsl233777 wants to merge 27 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Tauri desktop packaging and staging tooling, Rust Tauri lifecycle and diagnostics to spawn the Node CLI with TCP health-checks, CI desktop build/release integration (macOS/Windows) with Windows manifest verification, NSIS installer hook, staging/asset tests and docs, plus analytics export CLI/API and unit tests. ChangesDesktop Application with Tauri
Analytics export feature
Sequence DiagramsequenceDiagram
participant AppMain as src-tauri/src/main.rs
participant AppLib as src-tauri/src/lib.rs
participant NodeBackend as dist/desktop/codexmate/cli.js
participant HealthCheck as 127.0.0.1:3737
participant CI as GitHub Actions
AppMain->>AppLib: init_desktop_diagnostics() and run()
AppLib->>NodeBackend: spawn_backend (node cli.js run --host 127.0.0.1 --no-browser)
NodeBackend->>HealthCheck: serve /api
AppLib->>HealthCheck: health_check_ready polling until 200 + {"ok":true}
CI->>AppLib: build (tauri/cargo) -> bundle outputs and verify Windows manifest
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Updated this PR after rebasing onto latest Validation run locally:
@coderabbitai review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
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/desktop-build.yml:
- Around line 34-35: Replace floating action refs with pinned commit SHAs for
every `uses:` entry (e.g., change `actions/checkout@v4` to the corresponding
full commit SHA ref) and for the checkout step(s) add `persist-credentials:
false` under the step config to disable token persistence; update all
occurrences noted (the Checkout step and the other actions referenced) so each
`uses:` is a full commit SHA and each checkout step includes
`persist-credentials: false`.
In `@src-tauri/src/lib.rs`:
- Around line 116-124: The spawned child process from command.spawn() is not
terminated if wait_for_backend(Duration::from_secs(15)) returns false; modify
the error path so that when wait_for_backend(...) is false you call child.kill()
(and optionally child.wait() to reap it), handle/ignore any kill/wait errors,
and then return the Err string instead of leaving the process running; update
the block where you create let child = command.spawn() and the subsequent
readiness check to ensure child is killed and awaited before returning Err.
- Around line 39-44: The readiness probe currently only checks for "HTTP/1.1
200" or "HTTP/1.0 200" in the raw response (using response and
stream.read_to_string), which can false-positive for other services; update the
check so after reading the response it also validates a backend-specific
identity token (for example a unique header like "X-Backend: MyAppBackend" or a
distinct body string such as "MyAppBackend ready") in the response before
returning true; modify the conditional that currently returns
response.starts_with(...) to require both the 200 status line and the presence
of that unique identifier, and keep the existing error handling for
stream.read_to_string failures.
In `@tests/unit/desktop-stage.test.mjs`:
- Around line 54-56: The test currently uses a brittle full-object equality on
tauriConfig.bundle.resources via assert.deepStrictEqual; instead assert only
that the required mapping exists by checking that tauriConfig.bundle.resources
has the key '../dist/desktop/codexmate' and its value equals 'codexmate' (e.g.,
use hasOwnProperty or in-check plus assert.strictEqual on
tauriConfig.bundle.resources['../dist/desktop/codexmate']). Update the assertion
in tests/unit/desktop-stage.test.mjs to verify the single mapping rather than
the entire resources object.
In `@tools/desktop/prepare-tauri-resources.js`:
- Around line 48-53: The use of fs.cpSync in prepare-tauri-resources.js is
incompatible with engines.node >=14; either update package.json.engines to a
Node version that includes fs.cpSync or replace the fs.cpSync call with a
Node-14-compatible recursive copy routine: implement a small utility in
prepare-tauri-resources.js (e.g., copyDirRecursive) that creates destination
dirs with fs.mkdirSync(..., { recursive: true }), iterates entries with
fs.readdirSync, skips any path containing '.git' (match the existing filter
logic), copies files with fs.copyFileSync and handles directories recursively,
and preserves the intended dereference/force semantics as best-effort; modify
the code to call this utility instead of fs.cpSync (or bump engines.node if you
prefer the simpler 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: 95d40a9b-5e65-40b6-bcd5-49df9fc4fc2a
⛔ Files ignored due to path filters (16)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/icons/128x128.pngis excluded by!**/*.pngsrc-tauri/icons/128x128@2x.pngis excluded by!**/*.pngsrc-tauri/icons/32x32.pngis excluded by!**/*.pngsrc-tauri/icons/Square107x107Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square142x142Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square150x150Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square284x284Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square30x30Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square310x310Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square44x44Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square71x71Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square89x89Logo.pngis excluded by!**/*.pngsrc-tauri/icons/StoreLogo.pngis excluded by!**/*.pngsrc-tauri/icons/icon.icois excluded by!**/*.icosrc-tauri/icons/icon.pngis excluded by!**/*.png
📒 Files selected for processing (15)
.github/workflows/desktop-build.ymldoc/desktop.mdpackage.jsonsrc-tauri/.gitignoresrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/icons/icon.icnssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsontests/unit/desktop-stage.test.mjstests/unit/npm-package-files.test.mjstests/unit/run.mjstools/desktop/prepare-tauri-resources.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Windows
- GitHub Check: macOS
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/desktop-build.yml
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 38-38: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 44-44: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 59-59: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (10)
doc/desktop.md (1)
1-62: LGTM!src-tauri/.gitignore (1)
1-4: LGTM!src-tauri/Cargo.toml (1)
1-25: LGTM!src-tauri/build.rs (1)
1-3: LGTM!src-tauri/capabilities/default.json (1)
1-11: LGTM!src-tauri/tauri.conf.json (1)
1-47: LGTM!src-tauri/src/main.rs (1)
1-6: LGTM!package.json (1)
45-49: LGTM!Also applies to: 79-80
tests/unit/npm-package-files.test.mjs (1)
20-25: LGTM!tests/unit/run.mjs (1)
57-57: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
tests/unit/desktop-stage.test.mjs (1)
54-56:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid brittle full-object equality for
bundle.resources.Assert the required mapping instead of the whole object so valid extra resources don’t break this test.
Proposed fix
- assert.deepStrictEqual(tauriConfig.bundle.resources, { - '../dist/desktop/codexmate': 'codexmate' - }); + assert.strictEqual( + tauriConfig.bundle?.resources?.['../dist/desktop/codexmate'], + 'codexmate', + 'tauri bundle.resources must map ../dist/desktop/codexmate to codexmate' + );🤖 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 `@tests/unit/desktop-stage.test.mjs` around lines 54 - 56, The test currently asserts full-object equality on tauriConfig.bundle.resources which is brittle; update the assertion in tests/unit/desktop-stage.test.mjs to check only that the required mapping exists (e.g., assert that tauriConfig.bundle.resources['../dist/desktop/codexmate'] equals 'codexmate' or that Object.prototype.hasOwnProperty.call(tauriConfig.bundle.resources, '../dist/desktop/codexmate') and its value is 'codexmate') so extra resources won’t break the test while still verifying the necessary mapping.tools/desktop/prepare-tauri-resources.js (1)
48-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAlign declared Node support with
fs.cpSyncusage.
fs.cpSynchere breaks on Node 14, but the project still declaresengines.node >=14. Please either raise the engine floor (e.g. Node >=16.7) or replace this copy path with a Node-14-compatible recursive implementation.#!/bin/bash set -euo pipefail echo "Declared Node engine in package.json:" rg -n '"engines"\s*:\s*\{|"node"\s*:' package.json -A2 -B1 echo echo "Node API usage in desktop staging script:" rg -n '\bfs\.cpSync\b' tools/desktop/prepare-tauri-resources.js -C2🤖 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 `@tools/desktop/prepare-tauri-resources.js` around lines 48 - 53, The code uses fs.cpSync in prepare-tauri-resources.js which requires a newer Node than the project's declared engines.node (>=14); either update package.json engines.node to a minimum Node version that supports fs.cpSync (e.g., ">=16.7.0") or replace the fs.cpSync call with a Node-14-compatible recursive copier: implement a copyDirSync function (using fs.readdirSync, fs.statSync/lstatSync to honor dereference, fs.mkdirSync, fs.copyFileSync and handling overwrite/force) and apply the same filter logic (skip paths containing '.git') before calling it in place of fs.cpSync; ensure the replacement preserves recursive, force/overwrite, dereference, and filter behavior used in the original fs.cpSync invocation..github/workflows/desktop-build.yml (1)
34-35:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPin all workflow actions to commit SHAs and harden checkout credentials.
This workflow still uses floating action refs and keeps default checkout credential persistence. Pin every
uses:to full commit SHAs and setpersist-credentials: falseon checkout.#!/bin/bash set -euo pipefail echo "Unpinned action refs:" rg -n '^\s*uses:\s*[^@]+@(v[0-9]+|stable|main|master)\s*$' .github/workflows/desktop-build.yml echo echo "Checkout credential persistence setting:" rg -n '^\s*- name:\s*Checkout|persist-credentials' .github/workflows/desktop-build.yml -C2Also applies to: 38-38, 44-44, 59-59
🤖 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 @.github/workflows/desktop-build.yml around lines 34 - 35, Pin every "uses:" entry to a full commit SHA instead of floating refs (e.g., replace uses: actions/checkout@v4 with the corresponding commit SHA for actions/checkout and do the same for any other uses: entries currently pinned to tags/branches), and harden the Checkout step by adding persist-credentials: false under the step that contains uses: actions/checkout@... (ensure the key is present and set to false). Locate these changes by searching for the literal "uses: actions/checkout@" and other "uses:" entries in the workflow and update each to its full commit SHA; add or update the "persist-credentials" field in the checkout step to false so credentials are not persisted.src-tauri/src/lib.rs (2)
116-124:⚠️ Potential issue | 🟠 Major | ⚡ Quick winKill the spawned backend if readiness times out.
If
wait_for_backend()times out, the function returns an error without terminating the already-spawned child process, leaving an orphaned backend running.🧹 Proposed fix to clean up on timeout
- let child = command + let mut child = command .spawn() .map_err(|err| format!("unable to start codexmate backend with Node.js: {err}"))?; if !wait_for_backend(Duration::from_secs(15)) { + let _ = child.kill(); + let _ = child.wait(); return Err("codexmate backend did not become ready on 127.0.0.1:3737".into()); } Ok(Some(child))🤖 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/lib.rs` around lines 116 - 124, After spawning the child with command.spawn() and before returning an error when wait_for_backend(Duration::from_secs(15)) returns false, ensure you terminate the spawned process: call child.kill() (handle/ignore errors if the process already exited) and then call child.wait() to reap it; only after killing/waiting return the error string. This guarantees the spawned child (variable child from command.spawn()) is cleaned up on wait_for_backend timeout.
39-44:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake the readiness probe validate backend identity, not just status code.
The current health check only verifies HTTP 200 status, which could false-positive if an unrelated service is running on
127.0.0.1:3737, causing the app to skip backend startup or connect to the wrong service.🔍 Proposed fix to validate backend identity
let mut response = String::new(); if stream.read_to_string(&mut response).is_err() { return false; } - response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200") + (response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200")) + && response.contains("\"ok\":true")This checks for a backend-specific token in the response body to confirm identity.
🤖 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/lib.rs` around lines 39 - 44, The readiness probe currently only checks the HTTP status by calling stream.read_to_string(&mut response) and response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200"); update this logic to also validate a backend-specific identity token in the response body (e.g., a known marker like "X-BACKEND-ID: my-backend" or "MY_BACKEND_READY") before returning true, so after successful read_to_string verify both the 200 status and response.contains("<IDENTITY_TOKEN>") and return false if the token is missing.
🤖 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/tauri.conf.json`:
- Around line 26-28: Replace the null Content Security Policy in tauri.conf.json
by setting the security.csp key to a restrictive CSP string that permits only
'self' and the local backend origin (http://127.0.0.1:3737) and only the minimal
additional directives your frontend needs (e.g., avoid unsafe-eval, avoid
unsafe-inline unless absolutely required); update the security.csp value (the
"security": {"csp": ...} entry) accordingly so CSP is enforced rather than
disabled.
---
Duplicate comments:
In @.github/workflows/desktop-build.yml:
- Around line 34-35: Pin every "uses:" entry to a full commit SHA instead of
floating refs (e.g., replace uses: actions/checkout@v4 with the corresponding
commit SHA for actions/checkout and do the same for any other uses: entries
currently pinned to tags/branches), and harden the Checkout step by adding
persist-credentials: false under the step that contains uses:
actions/checkout@... (ensure the key is present and set to false). Locate these
changes by searching for the literal "uses: actions/checkout@" and other "uses:"
entries in the workflow and update each to its full commit SHA; add or update
the "persist-credentials" field in the checkout step to false so credentials are
not persisted.
In `@src-tauri/src/lib.rs`:
- Around line 116-124: After spawning the child with command.spawn() and before
returning an error when wait_for_backend(Duration::from_secs(15)) returns false,
ensure you terminate the spawned process: call child.kill() (handle/ignore
errors if the process already exited) and then call child.wait() to reap it;
only after killing/waiting return the error string. This guarantees the spawned
child (variable child from command.spawn()) is cleaned up on wait_for_backend
timeout.
- Around line 39-44: The readiness probe currently only checks the HTTP status
by calling stream.read_to_string(&mut response) and
response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200");
update this logic to also validate a backend-specific identity token in the
response body (e.g., a known marker like "X-BACKEND-ID: my-backend" or
"MY_BACKEND_READY") before returning true, so after successful read_to_string
verify both the 200 status and response.contains("<IDENTITY_TOKEN>") and return
false if the token is missing.
In `@tests/unit/desktop-stage.test.mjs`:
- Around line 54-56: The test currently asserts full-object equality on
tauriConfig.bundle.resources which is brittle; update the assertion in
tests/unit/desktop-stage.test.mjs to check only that the required mapping exists
(e.g., assert that tauriConfig.bundle.resources['../dist/desktop/codexmate']
equals 'codexmate' or that
Object.prototype.hasOwnProperty.call(tauriConfig.bundle.resources,
'../dist/desktop/codexmate') and its value is 'codexmate') so extra resources
won’t break the test while still verifying the necessary mapping.
In `@tools/desktop/prepare-tauri-resources.js`:
- Around line 48-53: The code uses fs.cpSync in prepare-tauri-resources.js which
requires a newer Node than the project's declared engines.node (>=14); either
update package.json engines.node to a minimum Node version that supports
fs.cpSync (e.g., ">=16.7.0") or replace the fs.cpSync call with a
Node-14-compatible recursive copier: implement a copyDirSync function (using
fs.readdirSync, fs.statSync/lstatSync to honor dereference, fs.mkdirSync,
fs.copyFileSync and handling overwrite/force) and apply the same filter logic
(skip paths containing '.git') before calling it in place of fs.cpSync; ensure
the replacement preserves recursive, force/overwrite, dereference, and filter
behavior used in the original fs.cpSync invocation.
🪄 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: e089cd15-bd97-4c65-8b49-bc57bab0cb3b
⛔ Files ignored due to path filters (16)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/icons/128x128.pngis excluded by!**/*.pngsrc-tauri/icons/128x128@2x.pngis excluded by!**/*.pngsrc-tauri/icons/32x32.pngis excluded by!**/*.pngsrc-tauri/icons/Square107x107Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square142x142Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square150x150Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square284x284Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square30x30Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square310x310Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square44x44Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square71x71Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square89x89Logo.pngis excluded by!**/*.pngsrc-tauri/icons/StoreLogo.pngis excluded by!**/*.pngsrc-tauri/icons/icon.icois excluded by!**/*.icosrc-tauri/icons/icon.pngis excluded by!**/*.png
📒 Files selected for processing (15)
.github/workflows/desktop-build.ymldoc/desktop.mdpackage.jsonsrc-tauri/.gitignoresrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/icons/icon.icnssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsontests/unit/desktop-stage.test.mjstests/unit/npm-package-files.test.mjstests/unit/run.mjstools/desktop/prepare-tauri-resources.js
📜 Review details
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/desktop-build.yml
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 38-38: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 44-44: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 59-59: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (11)
doc/desktop.md (1)
1-61: LGTM!package.json (1)
45-49: LGTM!Also applies to: 79-80
tests/unit/npm-package-files.test.mjs (1)
20-25: LGTM!tests/unit/run.mjs (1)
57-57: LGTM!src-tauri/.gitignore (1)
1-4: LGTM!src-tauri/build.rs (1)
1-3: LGTM!src-tauri/capabilities/default.json (1)
1-11: LGTM!src-tauri/src/lib.rs (2)
146-158: LGTM!
160-164: LGTM!src-tauri/src/main.rs (1)
1-6: LGTM!src-tauri/Cargo.toml (1)
3-3: ⚡ Quick winCheck
src-tauri/Cargo.tomlfor current/secure Rust + Tauri pins
- crates.io latest:
tauri2.11.2,tauri-build2.6.2,tauri-plugin-log2.8.0.- Security advisory affects
tauriversions>= 2.0.0, <= 2.11.0(patched in2.11.1), so the pinnedtauriversion must be>= 2.11.1.- The provided snippet only shows
version = "0.0.36"; confirm the actualtauri*dependency versions and[package].rust-versioninsrc-tauri/Cargo.tomland update if they fall into vulnerable/outdated ranges (Rust stable is currently 1.95.0).
|
Updated the desktop app icons from Validation run locally:
Notes:
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
.github/workflows/desktop-build.yml (1)
34-35:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHarden workflow actions by pinning SHAs and disabling checkout credential persistence.
The workflow still uses floating action refs and keeps default checkout credential persistence. Pin each
uses:to a full commit SHA and setpersist-credentials: falsein the checkout step.#!/bin/bash set -euo pipefail echo "All action references:" rg -n '^\s*uses:\s*' .github/workflows/desktop-build.yml echo echo "Checkout credential persistence setting:" rg -n 'persist-credentials' .github/workflows/desktop-build.yml || trueAlso applies to: 38-38, 44-44, 59-59
🤖 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 @.github/workflows/desktop-build.yml around lines 34 - 35, Replace floating action refs and enable non-persistent checkout credentials: pin every "uses:" action to a full commit SHA instead of tags (e.g., replace uses: actions/checkout@v4 with a specific commit SHA) and add persist-credentials: false to the checkout step; apply these changes for the checkout occurrences and any other "uses:" lines referenced in the file so all actions are SHA-pinned and the Checkout step sets persist-credentials: false.tools/desktop/prepare-tauri-resources.js (1)
48-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAlign runtime floor with
fs.cpSyncusage.
fs.cpSyncat Line 48 is incompatible with the declarednode >=14support, sodesktop:stagecan fail on supported runtimes. Either raise the engine floor for desktop-supporting environments or replace this with a Node-14-compatible recursive copy path.#!/bin/bash set -euo pipefail echo "Declared Node engine:" rg -n '"engines"\s*:\s*\{|"node"\s*:' package.json -n -A2 -B1 echo echo "Node APIs used by desktop staging script:" rg -n '\bfs\.cpSync\b|\bfs\.rmSync\b' tools/desktop/prepare-tauri-resources.js -C2🤖 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 `@tools/desktop/prepare-tauri-resources.js` around lines 48 - 53, The script prepare-tauri-resources.js currently calls fs.cpSync (symbol: fs.cpSync) which is only available in Node >=16 and thus conflicts with the declared node >=14 engine; either raise the project's Node engine to a version that supports fs.cpSync or replace this call with a Node-14-compatible implementation (e.g., use fs-extra.copySync or implement a recursive copy helper and use fs.readdir/fs.copyFile/fs.mkdir) and preserve the existing options (recursive, force, dereference, filter logic that excludes '.git'); update any imports/require usage accordingly and ensure prepare-tauri-resources.js continues to exclude .git paths as before.src-tauri/src/lib.rs (2)
116-122:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTerminate the spawned backend when readiness times out.
Lines 116–121 return an error without killing/reaping the child process, leaving a stray backend process running.
🛠️ Suggested fix
- let child = command + let mut child = command .spawn() .map_err(|err| format!("unable to start codexmate backend with Node.js: {err}"))?; if !wait_for_backend(Duration::from_secs(15)) { + let _ = child.kill(); + let _ = child.wait(); return Err("codexmate backend did not become ready on 127.0.0.1:3737".into()); }🤖 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/lib.rs` around lines 116 - 122, The code spawns a child process into the variable child but returns early when wait_for_backend(Duration::from_secs(15)) is false without killing or reaping that child; update the timeout branch to terminate and reap the process: call child.kill() (handle/ignore any kill error) and then child.wait() (or wait_with_output/try_wait) before returning the Err so the spawned backend is not left running; keep references to the child variable and add minimal error handling/logging around kill() and wait() in the same scope where wait_for_backend is checked.
39-44:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake readiness verification backend-specific, not status-only.
Line 43 treats any local HTTP 200 as healthy, which can false-positive against an unrelated service on
127.0.0.1:3737.✅ Suggested fix
- response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200") + let status_ok = response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200"); + let identity_ok = response.contains("\"ok\":true"); + status_ok && identity_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/lib.rs` around lines 39 - 44, The current readiness check only inspects the HTTP status line using response.starts_with(...) which can false-positive against any service on 127.0.0.1:3737; update the readiness logic (the block that calls stream.read_to_string(&mut response) and currently returns based on response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200")) to validate a backend-specific signature instead: parse the HTTP response and verify both the 200 status and a unique marker (e.g., a specific response path/body JSON field or header such as an X-Backend or a known body token) that your backend exposes so only the intended service is considered healthy. Ensure you still handle read errors from stream.read_to_string and return false on failure, but replace the bare status-line check with a combined status + backend-identifier check using the response string you already populate.src-tauri/tauri.conf.json (1)
26-28:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnable a restrictive CSP instead of disabling it.
Line 27 sets CSP to
null, which removes webview-side injection protections even for localhost content.🔒 Suggested fix
"security": { - "csp": null + "csp": "default-src 'self' http://127.0.0.1:3737; connect-src 'self' http://127.0.0.1:3737; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'" }🤖 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/tauri.conf.json` around lines 26 - 28, The CSP is currently disabled by setting the "csp" key to null inside the "security" object; replace that with a restrictive Content Security Policy string (rather than null) to re-enable webview-side protections—update the "security"."csp" value to a restrictive policy that limits sources to self and local dev endpoints (for example, a policy restricting default-src to 'self' and localhost, limiting script-src/style-src/connect-src to 'self' and localhost, and allowing images from 'self' and data:); ensure the "csp" key contains that policy string so the tauri webview enforces it instead of being disabled.
🤖 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/lib.rs`:
- Around line 74-76: Remove the unsafe production fallback that adds
current_dir.join("cli.js") to candidates; instead only allow this behavior in
non-production (debug) builds. Locate the block that pushes
current_dir.join("cli.js") into the candidates vector (the current_dir / cli.js
fallback) and wrap it behind a debug-only guard (e.g., cfg!(debug_assertions))
so that in release builds the current working directory is not used as a
resource lookup candidate.
---
Duplicate comments:
In @.github/workflows/desktop-build.yml:
- Around line 34-35: Replace floating action refs and enable non-persistent
checkout credentials: pin every "uses:" action to a full commit SHA instead of
tags (e.g., replace uses: actions/checkout@v4 with a specific commit SHA) and
add persist-credentials: false to the checkout step; apply these changes for the
checkout occurrences and any other "uses:" lines referenced in the file so all
actions are SHA-pinned and the Checkout step sets persist-credentials: false.
In `@src-tauri/src/lib.rs`:
- Around line 116-122: The code spawns a child process into the variable child
but returns early when wait_for_backend(Duration::from_secs(15)) is false
without killing or reaping that child; update the timeout branch to terminate
and reap the process: call child.kill() (handle/ignore any kill error) and then
child.wait() (or wait_with_output/try_wait) before returning the Err so the
spawned backend is not left running; keep references to the child variable and
add minimal error handling/logging around kill() and wait() in the same scope
where wait_for_backend is checked.
- Around line 39-44: The current readiness check only inspects the HTTP status
line using response.starts_with(...) which can false-positive against any
service on 127.0.0.1:3737; update the readiness logic (the block that calls
stream.read_to_string(&mut response) and currently returns based on
response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200")) to
validate a backend-specific signature instead: parse the HTTP response and
verify both the 200 status and a unique marker (e.g., a specific response
path/body JSON field or header such as an X-Backend or a known body token) that
your backend exposes so only the intended service is considered healthy. Ensure
you still handle read errors from stream.read_to_string and return false on
failure, but replace the bare status-line check with a combined status +
backend-identifier check using the response string you already populate.
In `@src-tauri/tauri.conf.json`:
- Around line 26-28: The CSP is currently disabled by setting the "csp" key to
null inside the "security" object; replace that with a restrictive Content
Security Policy string (rather than null) to re-enable webview-side
protections—update the "security"."csp" value to a restrictive policy that
limits sources to self and local dev endpoints (for example, a policy
restricting default-src to 'self' and localhost, limiting
script-src/style-src/connect-src to 'self' and localhost, and allowing images
from 'self' and data:); ensure the "csp" key contains that policy string so the
tauri webview enforces it instead of being disabled.
In `@tools/desktop/prepare-tauri-resources.js`:
- Around line 48-53: The script prepare-tauri-resources.js currently calls
fs.cpSync (symbol: fs.cpSync) which is only available in Node >=16 and thus
conflicts with the declared node >=14 engine; either raise the project's Node
engine to a version that supports fs.cpSync or replace this call with a
Node-14-compatible implementation (e.g., use fs-extra.copySync or implement a
recursive copy helper and use fs.readdir/fs.copyFile/fs.mkdir) and preserve the
existing options (recursive, force, dereference, filter logic that excludes
'.git'); update any imports/require usage accordingly and ensure
prepare-tauri-resources.js continues to exclude .git paths as before.
🪄 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: 20600851-56c4-4332-9661-57ed83462160
⛔ Files ignored due to path filters (54)
package-lock.jsonis excluded by!**/package-lock.jsonsite/.vitepress/public/images/logo-v.pngis excluded by!**/*.pngsite/.vitepress/public/images/logo.pngis excluded by!**/*.pngsite/.vitepress/public/images/logo.svgis excluded by!**/*.svgsite/.vitepress/public/images/web-ui-screenshot.pngis excluded by!**/*.pngsrc-tauri/icons/128x128.pngis excluded by!**/*.pngsrc-tauri/icons/128x128@2x.pngis excluded by!**/*.pngsrc-tauri/icons/32x32.pngis excluded by!**/*.pngsrc-tauri/icons/64x64.pngis excluded by!**/*.pngsrc-tauri/icons/Square107x107Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square142x142Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square150x150Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square284x284Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square30x30Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square310x310Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square44x44Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square71x71Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square89x89Logo.pngis excluded by!**/*.pngsrc-tauri/icons/StoreLogo.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-hdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-hdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-mdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-mdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xhdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxhdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/icon.icois excluded by!**/*.icosrc-tauri/icons/icon.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@2x-1.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@2x-1.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@2x-1.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-512@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-60x60@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-60x60@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-76x76@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-76x76@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-83.5x83.5@2x.pngis excluded by!**/*.png
📒 Files selected for processing (17)
.github/workflows/desktop-build.ymldoc/desktop.mdpackage.jsonsrc-tauri/.gitignoresrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xmlsrc-tauri/icons/android/values/ic_launcher_background.xmlsrc-tauri/icons/icon.icnssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsontests/unit/desktop-stage.test.mjstests/unit/npm-package-files.test.mjstests/unit/run.mjstools/desktop/prepare-tauri-resources.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Windows
- GitHub Check: macOS
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/desktop-build.yml
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 38-38: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 44-44: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 59-59: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (13)
doc/desktop.md (1)
1-61: LGTM!tests/unit/desktop-stage.test.mjs (1)
54-56: ⚡ Quick winAssert only the required
bundle.resourcesmapping.This assertion is brittle because it enforces the entire object shape, not just the contract required by this PR.
Proposed fix
- assert.deepStrictEqual(tauriConfig.bundle.resources, { - '../dist/desktop/codexmate': 'codexmate' - }); + assert.strictEqual( + tauriConfig.bundle?.resources?.['../dist/desktop/codexmate'], + 'codexmate', + 'tauri bundle.resources must map ../dist/desktop/codexmate to codexmate' + );package.json (1)
45-49: LGTM!Also applies to: 79-80
tests/unit/npm-package-files.test.mjs (1)
20-25: LGTM!tests/unit/run.mjs (1)
57-57: LGTM!src-tauri/.gitignore (1)
1-4: LGTM!src-tauri/Cargo.toml (1)
1-25: LGTM!src-tauri/build.rs (1)
1-3: LGTM!src-tauri/capabilities/default.json (1)
1-11: LGTM!src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml (1)
1-5: LGTM!src-tauri/icons/android/values/ic_launcher_background.xml (1)
1-4: LGTM!src-tauri/src/main.rs (2)
1-2: LGTM!
4-6: ⚡ Quick winConfirm
app_libmatches the Tauri library crate andrun()is exported
src-tauri/Cargo.tomlsets[lib] name = "app_lib", matchingapp_lib::run()insrc-tauri/src/main.rs.src-tauri/src/lib.rsexportspub fn run().- While
run()returns(), it still handles failures via?in.setup(...)and.expect("error while running tauri application").
兔子审查 - 必须修复的问题🔴 Critical (安全/资源泄漏)1.
|
|
@coderabbitai re-review I addressed the findings from #172 (comment) in commit
Validation actually run: Local limitation: this environment does not have Could you please verify whether the previously listed issues are now resolved? |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== 1. .github/workflows/desktop-build.yml ==="
cat .github/workflows/desktop-build.yml
echo ""
echo "=== 2 & 3. src-tauri/src/lib.rs ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== 4. src-tauri/tauri.conf.json ==="
cat src-tauri/tauri.conf.json
echo ""
echo "=== 5. package.json (engines) ==="
python3 -c "import json; d=json.load(open('package.json')); print('engines:', d.get('engines')); print('devDeps tauri:', d.get('devDependencies',{}).get('`@tauri-apps/cli`'))"
echo ""
echo "=== 6. tests/unit/desktop-stage.test.mjs ==="
cat tests/unit/desktop-stage.test.mjsLength of output: 10697
The only remaining item (Rust ✅ Actions performedFull review triggered. |
|
@coderabbitai re-review Follow-up on the remaining desktop review item:
Latest validation actually run after this change: The prior six items from #172 (comment) remain addressed, and CI on the previous head was green before this follow-up commit. Please verify whether the remaining review concern is now resolved on the latest head. |
|
Your plan includes 2 PR reviews per hour. More reviews will be available in 19 minutes and 40 seconds. |
|
@coderabbitai re-review Follow-up release packaging change in
Validation actually run: Please verify the latest head, especially the release workflow artifact handoff and release asset globs. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== Release workflow ==="
fd -e yml -e yaml . .github/workflows/ --exec cat {}
echo ""
echo "=== Desktop build workflow ==="
cat .github/workflows/desktop-build.yml 2>/dev/null || echo "not found"
echo ""
echo "=== Unit test files (new contract test) ==="
fd 'release' tests/unit/ 2>/dev/null || fd '\.test\.mjs$' tests/unit/ | sort
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjs
echo ""
echo "=== All test mjs files listing ==="
fd '\.test\.mjs$' tests/unit/ | sortLength of output: 25332 🏁 Script executed: #!/bin/bash
# Read any new release-related test files
echo "=== release workflow contract test (if any) ==="
fd 'release' tests/unit/ 2>/dev/null
fd 'release' tests/ 2>/dev/null
echo ""
echo "=== Newer test files ==="
ls -la tests/unit/
echo ""
echo "=== package.json scripts section ==="
python3 -c "import json; d=json.load(open('package.json')); [print(k,'=',v) for k,v in d.get('scripts',{}).items()]"
echo ""
echo "=== package.json engines ==="
python3 -c "import json; d=json.load(open('package.json')); print(d.get('engines'))"Length of output: 7351 🏁 Script executed: #!/bin/bash
echo "=== release-workflow-contract.test.mjs ==="
cat tests/unit/release-workflow-contract.test.mjs
echo ""
echo "=== Checking ci.yml for unpinned actions ==="
cat .github/workflows/ci.yml
echo ""
echo "=== Release workflow: softprops action SHA verification ==="
grep -n "softprops\|download-artifact\|upload-artifact\|checkout\|setup-node\|rust-toolchain" .github/workflows/release.ymlLength of output: 3519
One minor pre-existing note (out of scope for this PR): Everything in scope for this PR looks solid. 🐇 ✨ ✅ Actions performedReview triggered.
|
|
@coderabbitai re-review Follow-up commit
Verified locally after the test addition:
Please confirm whether the previous desktop icon distribution is correct across the generated sizes and whether the icons are truly used by the Tauri desktop bundle configuration. If there is still an icon packaging/usage gap, please point to the exact missing platform, size, or config path. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
tests/unit/session-usage-backend.test.mjs (1)
254-301: ⚡ Quick winAdd failure-path tests for invalid
formatand invalid date ranges.Current coverage is success-only. Please add explicit assertions for invalid format and invalid
from/tocombinations to lock export contract behavior.🤖 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 `@tests/unit/session-usage-backend.test.mjs` around lines 254 - 301, Add tests that assert exportSessionUsageCore rejects when given an unsupported format and when given invalid date ranges; specifically, call usageCore.exportSessionUsageCore with format: 'xml' and assert.rejects the promise (or try/catch) to ensure an error is thrown, and add cases where from is after to (e.g., from: '2026-05-10', to: '2026-05-01') and where dates are malformed (e.g., from: 'invalid'), asserting rejection for each; reference the exported function usageCore.exportSessionUsageCore and mirror the existing test style (assert.rejects or async/await with try/catch) to lock the contract for format and date validation.tests/unit/analytics-export-args.test.mjs (1)
46-56: ⚡ Quick winAdd missing-value coverage for value-taking flags.
Please add cases like
['--source']and['--from', '--to', '2026-05-06']to assert parser errors. This branch is currently untested and is easy to regress.🤖 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 `@tests/unit/analytics-export-args.test.mjs` around lines 46 - 56, The test currently checks invalid tokens and choices but omits coverage for flags that require values; add additional assertions calling parseAnalyticsExportArgs with value-taking flags left without values (e.g., ['--source'] and ['--from', '--to', '2026-05-06']) and assert that parsed.error contains the appropriate "missing value" messages; update the existing test case (test name parseAnalyticsExportArgs reports unknown tokens and invalid choices) or add a new test that calls parseAnalyticsExportArgs with those argument arrays and asserts parsed.error matches patterns for missing values for --source, --from, and --to to prevent regressions in the parser logic.
🤖 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 `@cli.js`:
- Line 16025: Update the top-level analytics help string in cli.js so it
includes the --source option to match printAnalyticsUsage(); specifically edit
the console.log call that prints "codexmate analytics export ..." and add the
`--source <SOURCE>` token (or `--source` flag format used elsewhere) into the
same options list so both help surfaces stay consistent with the
printAnalyticsUsage() documentation.
In `@cli/analytics-export-args.js`:
- Around line 10-17: The readValue function is swallowing the next token even
when it's another flag; modify readValue (and the equivalent parsing block
around lines 22–39) to validate that args[index + 1] exists and does not start
with '-' before consuming it—if the next token is missing or begins with '-'
throw or return a clear parse error indicating the flag (e.g., the current
token/flag) is missing its value; keep using token.startsWith(`${flag}=`) for
inline values but otherwise do not unconditionally increment index or return
args[index+1] without this validation.
In `@cli/session-usage.js`:
- Around line 159-162: normalizeUsageExportFormat currently coerces any unknown
format to 'csv', hiding invalid input; update normalizeUsageExportFormat to
validate the normalized value and only return 'json' or 'csv' and otherwise
throw a clear error (e.g., throw new TypeError(`Invalid export format:
${value}`)) so callers receive a validation failure; apply the same validation
change to the other duplicate implementation noted in the diff (the second
normalize/format handler around the later block) so both places consistently
reject unsupported formats instead of silently returning 'csv'.
---
Nitpick comments:
In `@tests/unit/analytics-export-args.test.mjs`:
- Around line 46-56: The test currently checks invalid tokens and choices but
omits coverage for flags that require values; add additional assertions calling
parseAnalyticsExportArgs with value-taking flags left without values (e.g.,
['--source'] and ['--from', '--to', '2026-05-06']) and assert that parsed.error
contains the appropriate "missing value" messages; update the existing test case
(test name parseAnalyticsExportArgs reports unknown tokens and invalid choices)
or add a new test that calls parseAnalyticsExportArgs with those argument arrays
and asserts parsed.error matches patterns for missing values for --source,
--from, and --to to prevent regressions in the parser logic.
In `@tests/unit/session-usage-backend.test.mjs`:
- Around line 254-301: Add tests that assert exportSessionUsageCore rejects when
given an unsupported format and when given invalid date ranges; specifically,
call usageCore.exportSessionUsageCore with format: 'xml' and assert.rejects the
promise (or try/catch) to ensure an error is thrown, and add cases where from is
after to (e.g., from: '2026-05-10', to: '2026-05-01') and where dates are
malformed (e.g., from: 'invalid'), asserting rejection for each; reference the
exported function usageCore.exportSessionUsageCore and mirror the existing test
style (assert.rejects or async/await with try/catch) to lock the contract for
format and date validation.
🪄 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: 12d7b70a-3f19-4dae-a706-67d7e7bb91c5
📒 Files selected for processing (6)
cli.jscli/analytics-export-args.jscli/session-usage.jstests/unit/analytics-export-args.test.mjstests/unit/run.mjstests/unit/session-usage-backend.test.mjs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Windows
- GitHub Check: macOS
🔇 Additional comments (2)
tests/unit/run.mjs (1)
30-30: LGTM!cli.js (1)
165-166: LGTM!Also applies to: 5208-5212, 9806-9810, 9812-9845, 11128-11141, 16118-16118
| console.log(' codexmate delete-model <模型> 删除模型'); | ||
| console.log(' codexmate workflow <list|get|validate|run|runs> MCP 工作流中心'); | ||
| console.log(' codexmate task <plan|run|runs|queue|retry|cancel|logs> 本地任务编排'); | ||
| console.log(' codexmate analytics export [--format csv|json] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--model <MODEL>] [--output <PATH|->] [-o <PATH|->] 导出 Usage 数据'); |
There was a problem hiding this comment.
Add --source to the top-level analytics help line.
Line [16025] omits --source, but this option is supported and documented in printAnalyticsUsage(). Keeping both help surfaces aligned avoids CLI confusion.
Suggested patch
- console.log(' codexmate analytics export [--format csv|json] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--model <MODEL>] [--output <PATH|->] [-o <PATH|->] 导出 Usage 数据');
+ console.log(' codexmate analytics export [--format csv|json] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--model <MODEL>] [--source <codex|claude|gemini|codebuddy|all>] [--output <PATH|->] [-o <PATH|->] 导出 Usage 数据');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| console.log(' codexmate analytics export [--format csv|json] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--model <MODEL>] [--output <PATH|->] [-o <PATH|->] 导出 Usage 数据'); | |
| console.log(' codexmate analytics export [--format csv|json] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--model <MODEL>] [--source <codex|claude|gemini|codebuddy|all>] [--output <PATH|->] [-o <PATH|->] 导出 Usage 数据'); |
🤖 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 `@cli.js` at line 16025, Update the top-level analytics help string in cli.js
so it includes the --source option to match printAnalyticsUsage(); specifically
edit the console.log call that prints "codexmate analytics export ..." and add
the `--source <SOURCE>` token (or `--source` flag format used elsewhere) into
the same options list so both help surfaces stay consistent with the
printAnalyticsUsage() documentation.
| const readValue = (flag) => { | ||
| if (token.startsWith(`${flag}=`)) { | ||
| return token.slice(flag.length + 1); | ||
| } | ||
| const value = args[index + 1]; | ||
| index += 1; | ||
| return value; | ||
| }; |
There was a problem hiding this comment.
Missing-value flags are silently accepted and can swallow the next flag.
For value-taking flags, readValue (Line 10–17) consumes args[index + 1] unconditionally. Inputs like --source --format json can treat --format as the --source value instead of raising a parse error.
💡 Suggested fix
function parseAnalyticsExportArgs(args = []) {
+ const valueFlags = new Set(['--format', '--from', '--to', '--model', '--source', '--output', '-o']);
const options = {
format: 'csv',
source: 'all',
output: ''
};
@@
const token = String(args[index] || '');
+ const tokenKey = token.split('=')[0];
const readValue = (flag) => {
if (token.startsWith(`${flag}=`)) {
return token.slice(flag.length + 1);
}
const value = args[index + 1];
+ const nextKey = String(value || '').split('=')[0];
+ if (value === undefined || valueFlags.has(nextKey)) {
+ errors.push(`${flag} 需要提供值`);
+ return '';
+ }
index += 1;
return value;
};Also applies to: 22-39
🤖 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 `@cli/analytics-export-args.js` around lines 10 - 17, The readValue function is
swallowing the next token even when it's another flag; modify readValue (and the
equivalent parsing block around lines 22–39) to validate that args[index + 1]
exists and does not start with '-' before consuming it—if the next token is
missing or begins with '-' throw or return a clear parse error indicating the
flag (e.g., the current token/flag) is missing its value; keep using
token.startsWith(`${flag}=`) for inline values but otherwise do not
unconditionally increment index or return args[index+1] without this validation.
| function normalizeUsageExportFormat(value) { | ||
| const normalized = typeof value === 'string' ? value.trim().toLowerCase() : ''; | ||
| return normalized === 'json' ? 'json' : 'csv'; | ||
| } |
There was a problem hiding this comment.
Invalid export formats are silently coerced to CSV.
normalizeUsageExportFormat currently maps any unknown value to csv, so API callers can pass bad input (e.g. xml) and still get success instead of a validation error.
💡 Suggested fix
function normalizeUsageExportFormat(value) {
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
- return normalized === 'json' ? 'json' : 'csv';
+ if (!normalized) return 'csv';
+ return normalized === 'json' || normalized === 'csv' ? normalized : '';
}
@@
const format = normalizeUsageExportFormat(params.format);
+ if (!format) {
+ return { error: 'Invalid format' };
+ }Also applies to: 284-289
🤖 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 `@cli/session-usage.js` around lines 159 - 162, normalizeUsageExportFormat
currently coerces any unknown format to 'csv', hiding invalid input; update
normalizeUsageExportFormat to validate the normalized value and only return
'json' or 'csv' and otherwise throw a clear error (e.g., throw new
TypeError(`Invalid export format: ${value}`)) so callers receive a validation
failure; apply the same validation change to the other duplicate implementation
noted in the diff (the second normalize/format handler around the later block)
so both places consistently reject unsupported formats instead of silently
returning 'csv'.
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== 1. tauri.conf.json bundle.icon section ==="
python3 -c "import json; d=json.load(open('src-tauri/tauri.conf.json')); print(json.dumps(d.get('bundle',{}).get('icon','NOT FOUND'), indent=2))"
echo ""
echo "=== 2. New icon contract test file (if present) ==="
fd 'icon' tests/unit/ | sort
fd 'icon.*contract\|contract.*icon\|desktop.*icon\|icon.*test' tests/unit/ | sort
# List all test files to find new ones
ls -la tests/unit/
echo ""
echo "=== 3. run.mjs ==="
cat tests/unit/run.mjs
echo ""
echo "=== 4. Icon files present under src-tauri/icons/ ==="
find src-tauri/icons/ -type f | sort
echo ""
echo "=== 5. Read the newest test file content ==="
fd '\.test\.mjs$' tests/unit/ | sort | xargs ls -laLength of output: 20157 🏁 Script executed: #!/bin/bash
echo "=== desktop-stage.test.mjs (full) ==="
cat tests/unit/desktop-stage.test.mjs
echo ""
echo "=== Check if run.mjs has any new imports vs expected ==="
grep -c "import" tests/unit/run.mjs
echo ""
echo "=== Check icon file binary headers to verify they're real PNGs, ICO, ICNS ==="
python3 - <<'EOF'
import struct, os
icons_dir = "src-tauri/icons"
# Check key PNGs have correct PNG header
for name in ["32x32.png","128x128.png","128x128@2x.png","icon.png","64x64.png"]:
p = os.path.join(icons_dir, name)
with open(p,"rb") as f:
hdr = f.read(8)
ok = hdr == b'\x89PNG\r\n\x1a\n'
print(f"PNG {name}: {'OK' if ok else 'BAD'}")
# Check ICO header
ico_path = os.path.join(icons_dir, "icon.ico")
with open(ico_path,"rb") as f:
data = f.read()
reserved, img_type, count = struct.unpack_from("<HHH", data, 0)
print(f"\nICO reserved={reserved}, type={img_type}, count={count}")
sizes = []
for i in range(count):
off = 6 + i * 16
w, h = data[off], data[off+1]
sizes.append(w if w != 0 else 256)
print(f"ICO sizes (width): {sorted(sizes)}")
# Check ICNS header
icns_path = os.path.join(icons_dir, "icon.icns")
with open(icns_path,"rb") as f:
data = f.read()
magic = data[:4]
total_len = struct.unpack_from(">I", data, 4)[0]
print(f"\nICNS magic={magic}, declared_len={total_len}, file_len={len(data)}")
# Read all block type tags
offset = 8
tags = []
while offset < len(data) - 8:
tag = data[offset:offset+4].decode('ascii', errors='replace')
blk_len = struct.unpack_from(">I", data, offset+4)[0]
tags.append(tag)
if blk_len < 8: break
offset += blk_len
print(f"ICNS block tags: {tags}")
EOFLength of output: 8269
No icon packaging or config gap. The icon chain is complete and the binary file assertions are accurate. 🐇 ✨ ✅ Actions performedReview triggered.
|
|
@coderabbitai re-review Follow-up commit What changed:
Verified locally:
Local blocker: this machine does not have Please check whether this approach is correct for Tauri Windows release diagnostics and whether there are any remaining concerns with console attachment, backend stdio inheritance, file logging, or normal double-click UX. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/src/lib.rs ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== doc/desktop.md ==="
cat doc/desktop.md
echo ""
echo "=== tests/unit/run.mjs (confirm new test registered) ==="
cat tests/unit/run.mjs
echo ""
echo "=== src-tauri/src/main.rs ==="
cat src-tauri/src/main.rsLength of output: 19421
🟡 Minor items (non-blocking)1. command.stdout(desktop_log_stdio()).stderr(desktop_log_stdio());Both calls open the log file with let log_stdio_out = desktop_log_stdio();
let log_stdio_err = desktop_log_stdio(); // separate append handle is fine for low-volume
command.stdout(log_stdio_out).stderr(log_stdio_err);(No change actually needed — current code is fine for this use case.) 2. Raw epoch-ms timestamps are hard to read directly Log lines like Edge-case worth documenting (already implied by the docs): If a user runs Everything critical is correct. The diagnostics chain (env → console attach → CONOUT$ → file log → backend stdio → panic hook) is complete and the contract tests protect the key paths. 🐇 ✨ |
|
Updated the desktop startup behavior for occupied backend port cases. What changed:
Validation performed:
Remaining note:
|
|
Updated again based on the latest Windows install/startup feedback. Fixes in
Validation performed:
@coderabbitai re-review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/src/lib.rs ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== src-tauri/src/main.rs ==="
cat src-tauri/src/main.rs
echo ""
echo "=== src-tauri/tauri.conf.json ==="
cat src-tauri/tauri.conf.json
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjs
echo ""
echo "=== New test files ==="
fd '\.test\.mjs$' tests/unit/ | sort
echo ""
echo "=== Any new contract/diagnostics test files ==="
fd 'diagnostics\|installer\|nsis\|message\|startup' tests/unit/ | sort
echo ""
echo "=== desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs 2>/dev/null || echo "not found"Length of output: 31698
The ✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
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 `@doc/desktop.md`:
- Around line 67-71: Update the documentation text that currently states backend
stdout/stderr are appended to "%LOCALAPPDATA%\CodexMate\logs\desktop.log" so it
documents both "%LOCALAPPDATA%\CodexMate\logs\desktop.log" and
"%LOCALAPPDATA%\CodexMate\logs\startup.log" (the latter is used when console
logging is off), and change the nearby heading text "如需指定日志位置:" to "如需指定
`desktop.log` 位置:"; apply the same wording/path changes to the other occurrence
referenced (the block around lines 73-78) so both places correctly list
desktop.log and startup.log.
In `@src-tauri/src/lib.rs`:
- Around line 333-348: The cleanup currently kills any PID found on port 3737;
update the logic in the backend cleanup path (the block using
windows_command_line_for_pid, command_output and taskkill and the analogous
non-Windows path that uses lsof and kill) to first verify the PID is a Codex
Mate backend and that the socket is in LISTEN state before issuing a kill: check
the process command line (via windows_command_line_for_pid or parsing lsof
output) for a trusted identifier such as the backend binary name or a specific
CLI flag, and for non-Windows use lsof's state or netstat to ensure the socket
is LISTEN; if verification fails, do not call taskkill/kill and instead call
desktop_log to surface user guidance about the occupied port and how to manually
stop the backend. Ensure you change both the Windows block (where you currently
call taskkill via command_output) and the non-Windows block (where you call lsof
-ti tcp:3737 and kill -9) to follow this verification-before-kill flow and only
increment released when a verified kill succeeds.
🪄 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: 1bceb29f-ca6d-4396-ac7b-0689485ce344
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
doc/desktop.mdpackage.jsonsrc-tauri/Cargo.tomlsrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsonsrc-tauri/windows/installer-hooks.nshtests/unit/desktop-diagnostics-contract.test.mjstests/unit/desktop-stage.test.mjstests/unit/run.mjs
✅ Files skipped from review due to trivial changes (1)
- src-tauri/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (4)
- src-tauri/src/main.rs
- src-tauri/tauri.conf.json
- package.json
- tests/unit/desktop-stage.test.mjs
📜 Review details
🔇 Additional comments (3)
src-tauri/windows/installer-hooks.nsh (1)
1-4: LGTM!tests/unit/run.mjs (1)
60-60: LGTM!tests/unit/desktop-diagnostics-contract.test.mjs (1)
1-88: LGTM!
| 启用后,桌面壳会尝试附着父控制台,打印 Rust/Tauri 启动日志,并让内置 Node backend 的 stdout/stderr 继承到当前终端。无论是否启用控制台,桌面壳都会写入本地文件日志;未启用控制台时,backend stdout/stderr 也会追加到同一个日志文件: | ||
|
|
||
| ```text | ||
| %LOCALAPPDATA%\CodexMate\logs\desktop.log | ||
| ``` |
There was a problem hiding this comment.
Document backend log file as startup.log (not only desktop.log).
The text says backend stdout/stderr are appended to the same file shown below (desktop.log), but current implementation routes backend stdio to startup.log when console logging is off. Please update the wording and paths to avoid misdirected troubleshooting.
Suggested doc patch
-启用后,桌面壳会尝试附着父控制台,打印 Rust/Tauri 启动日志,并让内置 Node backend 的 stdout/stderr 继承到当前终端。无论是否启用控制台,桌面壳都会写入本地文件日志;未启用控制台时,backend stdout/stderr 也会追加到同一个日志文件:
+启用后,桌面壳会尝试附着父控制台,打印 Rust/Tauri 启动日志,并让内置 Node backend 的 stdout/stderr 继承到当前终端。无论是否启用控制台,桌面壳都会写入本地文件日志;未启用控制台时,backend stdout/stderr 会写入 `startup.log`:
```text
%LOCALAPPDATA%\CodexMate\logs\desktop.log
+%LOCALAPPDATA%\CodexMate\logs\startup.log-如需指定日志位置:
+如需指定 desktop.log 位置:
</details>
Also applies to: 73-78
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @doc/desktop.md around lines 67 - 71, Update the documentation text that
currently states backend stdout/stderr are appended to
"%LOCALAPPDATA%\CodexMate\logs\desktop.log" so it documents both
"%LOCALAPPDATA%\CodexMate\logs\desktop.log" and
"%LOCALAPPDATA%\CodexMate\logs\startup.log" (the latter is used when console
logging is off), and change the nearby heading text "如需指定日志位置:" to "如需指定
desktop.log 位置:"; apply the same wording/path changes to the other occurrence
referenced (the block around lines 73-78) so both places correctly list
desktop.log and startup.log.
</details>
<!-- fingerprinting:phantom:poseidon:hawk -->
<!-- This is an auto-generated comment by CodeRabbit -->
|
Update pushed: What changed:
Validation run locally:
Not run locally:
|
|
Update pushed: Adjusted per the requested packaging-level UAC strategy:
Validation run locally:
Not run locally:
|
|
Updated the desktop Windows verification path after the reported UAC behavior did not reproduce reliably from installed artifacts. Changes in this round:
Validated locally:
@coderabbitai re-review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/app.manifest ==="
cat src-tauri/app.manifest 2>/dev/null || echo "not found"
echo ""
echo "=== src-tauri/build.rs ==="
cat src-tauri/build.rs
echo ""
echo "=== .github/workflows/desktop-build.yml ==="
cat .github/workflows/desktop-build.yml
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== src-tauri/src/lib.rs (key sections: port cleanup, startup_error, manifest) ==="
# Show full lib.rs
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 34061
The ✅ Actions performedReview triggered.
|
|
Update pushed: What changed:
Validation performed:
@coderabbitai re-review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== tools/desktop/prepare-tauri-resources.js ==="
cat tools/desktop/prepare-tauri-resources.js
echo ""
echo "=== src-tauri/src/lib.rs (node launcher section) ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/desktop-stage.test.mjs ==="
cat tests/unit/desktop-stage.test.mjs
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== doc/desktop.md ==="
cat doc/desktop.md
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 48779
One inherent architectural note (not a blocker): Everything in scope is solid. 🐇 ✨ ✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
♻️ Duplicate comments (1)
doc/desktop.md (1)
69-73:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winThe past review comment about documenting both
desktop.logandstartup.logremains unresolved.The previous review flagged that backend stdout/stderr are routed to
startup.logwhen console logging is off, but the documentation still only mentionsdesktop.logat line 72. Line 69 should clarify that backend stdio goes to a different file (startup.log), and the heading at line 75 should specify it controls onlydesktop.loglocation. This mismatch could misdirect users during troubleshooting.🤖 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 `@doc/desktop.md` around lines 69 - 73, Update the documentation to clearly state two log files: explain that when the console/parent terminal is attached backend stdout/stderr are inherited by the terminal and desktop writes local file logs to desktop.log, but when console logging is disabled the backend stdout/stderr are appended to a separate startup.log (not desktop.log); also update the nearby heading that currently references desktop.log so it explicitly says it controls only the desktop.log location and does not cover startup.log, and mention both filenames (desktop.log and startup.log) where relevant.
🤖 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.
Duplicate comments:
In `@doc/desktop.md`:
- Around line 69-73: Update the documentation to clearly state two log files:
explain that when the console/parent terminal is attached backend stdout/stderr
are inherited by the terminal and desktop writes local file logs to desktop.log,
but when console logging is disabled the backend stdout/stderr are appended to a
separate startup.log (not desktop.log); also update the nearby heading that
currently references desktop.log so it explicitly says it controls only the
desktop.log location and does not cover startup.log, and mention both filenames
(desktop.log and startup.log) where relevant.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2b53d913-09e3-4606-98a8-451bc206eff6
📒 Files selected for processing (5)
doc/desktop.mdsrc-tauri/src/lib.rstests/unit/desktop-diagnostics-contract.test.mjstests/unit/desktop-stage.test.mjstools/desktop/prepare-tauri-resources.js
🚧 Files skipped from review as they are similar to previous changes (4)
- tests/unit/desktop-diagnostics-contract.test.mjs
- tests/unit/desktop-stage.test.mjs
- tools/desktop/prepare-tauri-resources.js
- src-tauri/src/lib.rs
📜 Review details
🔇 Additional comments (4)
doc/desktop.md (4)
12-12: LGTM!
29-29: LGTM!
33-33: LGTM!
52-52: LGTM!
Summary
.dmg,.msi,.exe) alongside existing npm/standalone archivescodexmate analytics exportand theexport-sessions-usageAPI actionValidation
npm run test:unit—All 535 tests passed.node --check cli.jsnode cli.js analytics export --format csv --from 2100-01-01 --to 2100-01-02 --output -node cli.js analytics export --format json --from 2100-01-01 --to 2100-01-02 --output -git diff --checkNotes
webkit2gtk-4.1,rsvg2). Windows/macOS bundle validation runs through GitHub Actions.workflow_dispatch, so the PR validates its release asset handoff by workflow contract tests and review; a real Release asset upload requires running the release workflow for a tag.Closes #169
Closes #139
Summary by CodeRabbit
New Features
Documentation
Chores
Tests