Skip to content

feat(session): support native derived sessions#136

Open
awsl233777 wants to merge 6 commits intomainfrom
feat/native-derived-sessions
Open

feat(session): support native derived sessions#136
awsl233777 wants to merge 6 commits intomainfrom
feat/native-derived-sessions

Conversation

@awsl233777
Copy link
Copy Markdown
Collaborator

@awsl233777 awsl233777 commented May 6, 2026

Summary

  • Treat converted/derived sessions as first-class native-resumable sessions with explicit nativeAvailable, nativePath, derivedPath, and import availability metadata.
  • Default session conversion writes to the target tool's native session directory, while outputDir=derived / --output-dir derived preserves the legacy codexmate-derived directory behavior.
  • Add an import-derived-session API and Web UI “Import to Native” flow for legacy derived sessions, including conflict confirmation, rollback-safe overwrite/import handling, and resume warning when a derived session is not natively available.
  • Localize the Import to Native button, progress label, conflict dialog, success/error toasts, backend error-code mapping, resume warning title, and related derived/native badges for both zh/en UI.
  • Increase session list item height by about 4px on desktop and compact/mobile layouts, with bundled CSS expectations updated.
  • Harden native conversion conflict handling, sidecar metadata writing, Claude fallback listing metadata, async UI state targeting, and duplicate convert button guarding.

Issues

Closes #131
Closes #132
Closes #133
Closes #134
Closes #135

Verification

  • node --check cli.js
  • node --check cli/session-convert.js
  • node --check cli/session-convert-args.js
  • node --check web-ui/modules/app.methods.session-actions.mjs
  • node --check web-ui/modules/app.methods.codex-config.mjs
  • node --check web-ui/modules/i18n.dict.mjs
  • node --check web-ui/session-helpers.mjs
  • node --check tests/e2e/test-session-convert-derived.js
  • node --check tests/unit/session-convert.test.mjs
  • node --check tests/unit/session-resume-command.test.mjs
  • node tests/unit/run.mjs — 524 tests passed
  • node tests/e2e/run.js — completed with exit code 0
  • npm run lint — lint passed for 186 files
  • git diff --check

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

This PR adds native/derived session status tracking, --output-dir control for conversions, import-derived-session CLI flow, and UI support (badges, import button, localized strings). Sessions and conversion results now include native availability, nativePath, derived metadata, and conversion origin fields.

Changes

Derived Session Status and Import-to-Native Workflow

Layer / File(s) Summary
Session Metadata & Helpers
cli.js (readDerivedSessionMeta, resolveNativeSessionFilePath, buildSessionNativeStatus, attachSessionNativeStatus)
New helpers to read derived metadata and compute/attach native vs derived status and paths.
CLI Session Listing
cli.js (listCodexSessions, Claude listing modifications)
Codex/Claude listings now wrap session summaries with attachSessionNativeStatus, include derived, nativeAvailable, nativePath, convertedFrom, convertedFromLabel, plus keywords/capabilities for Claude.
Session Conversion Flow
cli.js (convertSessionToDerived updates), cli/session-convert-args.js (--output-dir)
Conversion flow supports outputDir mode (native
Conversion Output Resolution
cli/session-convert.js
Conversion writes JSONL targets using centralized path resolution and existence checks before writing.
Import Derived→Native
cli.js (importDerivedSessionToNative), CLI dispatch
New import-derived-session handler to copy derived sessions into native directories with conflict resolution; CLI dispatch recognizes the command.
Web UI State & Methods
web-ui/app.js, web-ui/modules/app.methods.codex-config.mjs, web-ui/modules/app.methods.session-actions.mjs
New data sessionImportingNative and methods: isSessionConvertAvailable, isSessionNativeAvailable, isImportToNativeAvailable, getResumeCommandTitle, importDerivedSessionToNative to govern availability, UI titles, and import flow.
Session Detail Hydration
web-ui/session-helpers.mjs
Active session hydration now consumes nativeAvailable, nativeImportAvailable, nativePath, derivedPath, convertedFrom, convertedFromLabel from API responses.
UI Templates & Styling
web-ui/partials/index/panel-sessions.html, web-ui/styles/sessions-toolbar-trash.css
Added derived badge, convertedFrom label, native-availability badge, conditional "Import to Native" button, resume title binding; new .session-derived-badge CSS.
Translations
web-ui/modules/i18n.dict.mjs
Added zh/en i18n keys for derived/native UI and import flow (confirmations, statuses, yes/no).
Tests & Verification
tests/e2e/test-session-convert-derived.js, tests/unit/*
E2E tests updated for derived outputDir behavior, native availability assertions, import flows and conflict handling; unit tests updated for header actions, resume command localization, and API parity keys.

Sequence Diagram

sequenceDiagram
    actor User as User
    participant UI as Web UI
    participant API as CLI/API
    participant FS as File System

    User->>UI: Click "Convert Session"
    UI->>API: POST convertSession(source, target, outputDir)
    API->>FS: Determine outputDir (native or derived)
    alt native
        API->>FS: Write session to native dir (e.g., ~/.codex/sessions or ~/.claude/projects)
    else derived
        API->>FS: Write session to ~/.codexmate/sessions/derived/<target>
    end
    API->>API: Build/attach native-status metadata
    API-->>UI: Return session summary with nativeAvailable, nativePath, convertedFrom
    UI->>UI: Refresh list, show derived badge

    User->>UI: Click "Import to Native" on derived session
    UI->>API: POST importDerivedSessionToNative(sessionId)
    API->>FS: Copy derived file -> native dir
    alt exists
        API-->>UI: Prompt confirm overwrite
        User->>API: Confirm
        API->>FS: Overwrite file
    else created
        API->>FS: Create file
    end
    API-->>UI: Return updated nativeAvailable, nativePath
    UI->>UI: Update session detail, remove import action
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • SakuraByteCore/codexmate#116: Introduces derived-session conversion infrastructure that this PR extends with native/derived status, outputDir handling, and import-to-native capabilities.
  • SakuraByteCore/codexmate#88: Refactors CLI session helpers in the same area where new derived/native helpers were added.
  • SakuraByteCore/codexmate#113: Overlaps on session-actions and header-tests relevant to convert/import UI wiring.

Suggested reviewers

  • SurviveM
  • ymkiux

"🐰
I found a session, small and spry,
Tagged it 'derived', then watched it fly.
Copied home, now native and bright—
Resume commands hop into the night. ✨"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(session): support native derived sessions' directly and clearly summarizes the main change: adding native-derived session support with metadata fields, import capabilities, and UI enhancements across the codebase.
Linked Issues check ✅ Passed All coding requirements from linked issues are met: #131 resume command support via native paths/import, #132 convert button enabled with availability checks, #133 import-to-native API and UI flow, #134 default native output directory with derived flag option, #135 derived badge and native availability indicators.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the five linked issues. File modifications (cli.js, session-convert files, tests, web-ui modules, i18n, styles, helpers) implement native-derived session support without unrelated modifications.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/native-derived-sessions

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

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

⚠️ Outside diff range comments (1)
cli.js (1)

4724-4747: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wrap all Claude discovery branches the same way.

Only the indexed branch on Lines 4724-4747 goes through attachSessionNativeStatus(...). The fallback scan and derived-root scan later in listClaudeSessions() still push raw summaries, so those sessions never expose nativeAvailable, nativeImportAvailable, nativePath, or derivedPath. The UI state will depend on how the session was discovered.

🤖 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` around lines 4724 - 4747, In listClaudeSessions(), some discovery
branches push raw summary objects directly (so they miss
nativeAvailable/nativeImportAvailable/nativePath/derivedPath) while the indexed
branch wraps its session with attachSessionNativeStatus before pushing; update
the fallback scan and derived-root scan branches to wrap their session objects
with attachSessionNativeStatus the same way (i.e., replace
sessions.push(rawSummary) with sessions.push(attachSessionNativeStatus({...same
fields...})) so all pushes go through attachSessionNativeStatus and expose
nativeAvailable, nativeImportAvailable, nativePath, and derivedPath
consistently.
🤖 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`:
- Around line 7112-7126: The loop always generates a derived ID via
buildDerivedSessionId(baseSessionId) even when outputDirMode === 'native', so
change the logic in the block that assigns derivedSessionId/outputPath/metaPath
to first check if outputDirMode === 'native' and in that case set
derivedSessionId = baseSessionId and set outputPath/metaPath to the native
filenames for baseSessionId (rather than calling buildDerivedSessionId); keep
the existing 8-attempt loop only for non-native modes (where
buildDerivedSessionId is invoked), and if outputDirMode === 'native' check if
the native slot exists and return the same error object when it does to surface
the conflict/abort behavior.
- Around line 7303-7334: The import-to-native flow performs
fs.copyFileSync(resolvedSourcePath, resolvedNativePath) then proceeds to write
meta via writeJsonAtomic and update Claude index via
ensureClaudeSessionsIndex/upsertClaudeSessionIndexEntry, but on any subsequent
error the new native file remains and can overwrite a working session; to fix,
make the operation rollback-safe by either copying to a temporary path and
atomically renaming into resolvedNativePath only after all meta/index writes
succeed, or capture and preserve the original file (if exists) before copy and
on error restore it (and remove the partial new file) and avoid leaving
inconsistent index entries; ensure this change touches the code around
ensureDir, fs.copyFileSync, getDerivedSessionMetaPath, readDerivedSessionMeta,
writeJsonAtomic, ensureClaudeSessionsIndex and upsertClaudeSessionIndexEntry so
failures clean up the copied file and revert any index updates.
- Around line 6469-6490: attachSessionNativeStatus currently only adds
native/derived status and omits conversion provenance used elsewhere; update
attachSessionNativeStatus to also include convertedFrom and convertedFromLabel
derived from the session meta by reading session.meta.convertedFrom (or
session.convertedFrom if present) and calling the existing
buildConvertedFromLabel(session.meta) helper so list/browse payloads carry the
same "Converted from …" fields added in readSessionDetail.
- Around line 6449-6465: In buildSessionNativeStatus: the logic sets nativePath
to resolveNativeSessionFilePath() fallback even when the session file is
actually native; change nativePath selection to prefer currentPath when the
session is already native (inNativePath === true) or when nativeExists &&
!isDerived && currentPath is present, so that nativePath resolves to currentPath
for real native sessions; update nativeAvailable/nativeImportAvailable logic
accordingly to still reflect availability but avoid pointing nativePath at the
resolveNativeSessionFilePath fallback when currentPath is the real native file.

In `@cli/session-convert.js`:
- Around line 89-100: The conversion currently writes only the .jsonl but not
the companion derived metadata, so create and persist a derived metadata file
next to the converted session after fs.writeFileSync(outputPath, jsonl,...).
Build a metadata object (include sessionId, cwd: extracted.cwd || '', derived:
true, convertedFrom: filePath (or extracted.source if available),
nativeAvailable: true/false as appropriate) and serialize it to JSON, then write
it to a sidecar file (e.g. same basename as outputPath with a .meta.json or
.metadata.json suffix) using ensureDir as needed and fs.writeFileSync; reference
readSessionMessages, buildTargetRecords, resolveDefaultOutputPath, outputPath
and extracted to locate where to add this.
- Around line 93-99: The existsSync/writeFileSync pair in
resolveDefaultOutputPath/cli session conversion is a TOCTOU race: replace the
check-then-write with an atomic create-or-fail operation by first ensuring the
target directory exists via ensureDir(path.dirname(outputPath)) and then
opening/writing the file using an exclusive-create flag (e.g., use
fs.open/fs.write or fs.writeFile with the 'wx' flag) so the write fails if the
file already exists; catch that specific error and call process.exit(1) with the
same conflict message instead of relying on fs.existsSync.

In `@web-ui/modules/app.methods.session-actions.mjs`:
- Around line 101-104: The fallback branch is mutating this.activeSession
unconditionally which can mark the wrong session after an async API return;
capture the target session identifier before initiating the async import check
(e.g., const targetSessionId = this.activeSession?.id) and when the response
arrives update the session by locating the session with that id (or verify
this.activeSession?.id === targetSessionId) before setting nativeAvailable and
nativePath; update the code paths that set nativeAvailable and nativePath
(referencing this.activeSession, nativeAvailable, nativePath, and
res.nativePath) to only mutate the session whose id matches the captured id.

In `@web-ui/modules/i18n.dict.mjs`:
- Around line 549-553: The zh dictionary contains English values for keys like
'sessions.derivedBadge', 'sessions.convertedFrom', 'sessions.nativeAvailable',
'common.yes', and 'common.no' (and the additional entries around lines 565-566);
update the zh translations to proper Chinese equivalents (e.g., Derived -> 派生,
Converted from {source} -> 转换自 {source}, Native Available: {value} ->
本地可用:{value}, Yes -> 是, No -> 否) by replacing the English strings in the zh
section for these keys so the UI is consistently localized.

In `@web-ui/partials/index/panel-sessions.html`:
- Around line 235-239: The convert button currently only disables based on
activeSession and isSessionConvertAvailable(activeSession) but not when a
conversion is already running; update the disable logic so the button (class
btn-session-export) is disabled when
sessionConverting[getSessionExportKey(activeSession)] is true as well, or add an
early guard in convertSession to return immediately if
sessionConverting[getSessionExportKey(activeSession)] is true; reference
convertSession, activeSession, sessionConverting, and getSessionExportKey to
locate and apply the change.

---

Outside diff comments:
In `@cli.js`:
- Around line 4724-4747: In listClaudeSessions(), some discovery branches push
raw summary objects directly (so they miss
nativeAvailable/nativeImportAvailable/nativePath/derivedPath) while the indexed
branch wraps its session with attachSessionNativeStatus before pushing; update
the fallback scan and derived-root scan branches to wrap their session objects
with attachSessionNativeStatus the same way (i.e., replace
sessions.push(rawSummary) with sessions.push(attachSessionNativeStatus({...same
fields...})) so all pushes go through attachSessionNativeStatus and expose
nativeAvailable, nativeImportAvailable, nativePath, and derivedPath
consistently.
🪄 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: 257d5859-6f03-4b8e-8842-7144abbfc093

📥 Commits

Reviewing files that changed from the base of the PR and between ce08db6 and 59574e9.

📒 Files selected for processing (14)
  • cli.js
  • cli/session-convert-args.js
  • cli/session-convert.js
  • tests/e2e/test-session-convert-derived.js
  • tests/unit/session-header-actions-layout.test.mjs
  • tests/unit/session-resume-command.test.mjs
  • tests/unit/web-ui-behavior-parity.test.mjs
  • web-ui/app.js
  • web-ui/modules/app.methods.codex-config.mjs
  • web-ui/modules/app.methods.session-actions.mjs
  • web-ui/modules/i18n.dict.mjs
  • web-ui/partials/index/panel-sessions.html
  • web-ui/session-helpers.mjs
  • web-ui/styles/sessions-toolbar-trash.css
📜 Review details
🔇 Additional comments (6)
web-ui/styles/sessions-toolbar-trash.css (1)

226-238: Derived badge style is clean and consistent.

The new badge integrates well with the existing session chip/badge visual system.

cli/session-convert-args.js (1)

28-28: --output-dir parsing/validation looks solid.

Good defaulting, normalization, and explicit allowlist handling.

Also applies to: 44-45, 55-56

web-ui/session-helpers.mjs (1)

428-445: Session detail hydration extension looks good.

The added native/derived metadata propagation is coherent and fits the new UI state requirements.

web-ui/modules/app.methods.codex-config.mjs (1)

83-89: Per-session convert availability guard is well implemented.

Nice addition to prevent duplicate conversion actions and invalid source/target flows.

tests/unit/session-resume-command.test.mjs (1)

23-41: New coverage for derived/native resume behavior is valuable.

This test closes an important regression gap around warning/import logic.

web-ui/app.js (1)

200-200: sessionImportingNative state addition is appropriate.

This integrates cleanly with the new import action flow and loading guards.

Comment thread cli.js
Comment thread cli.js
Comment thread cli.js
Comment thread cli.js Outdated
Comment thread cli/session-convert.js
Comment thread cli/session-convert.js Outdated
Comment thread web-ui/modules/app.methods.session-actions.mjs Outdated
Comment thread web-ui/modules/i18n.dict.mjs Outdated
Comment thread web-ui/partials/index/panel-sessions.html
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
web-ui/modules/app.methods.session-actions.mjs (1)

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

Update the imported session, not whichever session is active later.

After the awaits above, Line 108 mutates this.activeSession unconditionally. If the user switches selection before the import resolves, the wrong session can be marked as native. This is the same race previously flagged on this method.

🔒 Safer state-targeted update
-                } else if (this.activeSession) {
-                    this.activeSession.nativeAvailable = true;
-                    this.activeSession.nativePath = res.nativePath || this.activeSession.nativePath;
+                } else if (session && typeof session === 'object') {
+                    session.nativeAvailable = true;
+                    session.nativePath = res.nativePath || session.nativePath;
+                    if (this.activeSession === session) {
+                        this.activeSession.nativeAvailable = true;
+                        this.activeSession.nativePath = res.nativePath || this.activeSession.nativePath;
+                    }
                 }
🤖 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 `@web-ui/modules/app.methods.session-actions.mjs` around lines 108 - 111,
Before awaiting the import result, capture the specific session reference or its
id (e.g., importedSession or importedSessionId) and after the await, update that
stored session instance (or locate it in this.sessions by id) instead of
mutating this.activeSession; replace the unconditional writes to
this.activeSession.nativeAvailable and this.activeSession.nativePath with
updates targeted to the captured session (and guard for it being present), so a
user switching activeSession during the async import won’t cause the wrong
session to be marked native.
🤖 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 `@web-ui/modules/app.methods.session-actions.mjs`:
- Around line 31-43: The two helpers handle missing session.nativeAvailable
inconsistently: change isSessionNativeAvailable to treat nativeAvailable as
available only when explicitly true (e.g., return session.nativeAvailable ===
true after validating session object) so its behavior aligns with
isImportToNativeAvailable (which already blocks import only when nativeAvailable
=== true); update the logic in isSessionNativeAvailable (function name)
accordingly so undefined no longer counts as "native available".
- Around line 440-448: Replace the hardcoded Chinese toast messages inside the
copy/resume flow with the i18n keys added in the PR: use the nativeOk variable
and call the translation helper (e.g., this.$t or the project's i18n.t) instead
of the literal strings in both the immediate-ok branch and the
navigator.clipboard success branch; update the two showMessage calls (the ones
using nativeOk ? '已复制' : '已复制,但该会话不在原生目录,恢复可能失败') to use something like
this.$t('session.copied') and this.$t('session.copied_not_native') (keeping the
same success/info severity) so English users receive localized text.

---

Duplicate comments:
In `@web-ui/modules/app.methods.session-actions.mjs`:
- Around line 108-111: Before awaiting the import result, capture the specific
session reference or its id (e.g., importedSession or importedSessionId) and
after the await, update that stored session instance (or locate it in
this.sessions by id) instead of mutating this.activeSession; replace the
unconditional writes to this.activeSession.nativeAvailable and
this.activeSession.nativePath with updates targeted to the captured session (and
guard for it being present), so a user switching activeSession during the async
import won’t cause the wrong session to be marked native.
🪄 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: ecb5d578-a21a-42a3-af80-35b61d250279

📥 Commits

Reviewing files that changed from the base of the PR and between 59574e9 and 092a8ca.

📒 Files selected for processing (3)
  • tests/unit/session-resume-command.test.mjs
  • web-ui/modules/app.methods.session-actions.mjs
  • web-ui/modules/i18n.dict.mjs

Comment on lines +31 to +43
isSessionNativeAvailable(session) {
if (!session || typeof session !== 'object') return false;
if (session.nativeAvailable === false) return false;
return true;
},

isImportToNativeAvailable(session) {
if (!this.isDerivedSession(session)) return false;
if (session.nativeAvailable === true) return false;
if (session.nativeImportAvailable === false) return false;
const source = String(session.source || '').trim().toLowerCase();
return source === 'codex' || source === 'claude';
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align undefined nativeAvailable handling across these helpers.

Line 33 treats a missing flag as “native available”, while Line 39 only blocks import when the flag is explicitly true. A derived session with nativeAvailable omitted can therefore show the normal resume tooltip and still offer “Import to Native” at the same time.

🔧 Suggested consistency fix
         isSessionNativeAvailable(session) {
             if (!session || typeof session !== 'object') return false;
-            if (session.nativeAvailable === false) return false;
-            return true;
+            if (this.isDerivedSession(session)) {
+                return session.nativeAvailable === true;
+            }
+            return session.nativeAvailable !== false;
         },

         isImportToNativeAvailable(session) {
             if (!this.isDerivedSession(session)) return false;
-            if (session.nativeAvailable === true) return false;
+            if (this.isSessionNativeAvailable(session)) return false;
             if (session.nativeImportAvailable === false) return false;
             const source = String(session.source || '').trim().toLowerCase();
             return source === 'codex' || source === 'claude';
         },
📝 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.

Suggested change
isSessionNativeAvailable(session) {
if (!session || typeof session !== 'object') return false;
if (session.nativeAvailable === false) return false;
return true;
},
isImportToNativeAvailable(session) {
if (!this.isDerivedSession(session)) return false;
if (session.nativeAvailable === true) return false;
if (session.nativeImportAvailable === false) return false;
const source = String(session.source || '').trim().toLowerCase();
return source === 'codex' || source === 'claude';
},
isSessionNativeAvailable(session) {
if (!session || typeof session !== 'object') return false;
if (this.isDerivedSession(session)) {
return session.nativeAvailable === true;
}
return session.nativeAvailable !== false;
},
isImportToNativeAvailable(session) {
if (!this.isDerivedSession(session)) return false;
if (this.isSessionNativeAvailable(session)) return false;
if (session.nativeImportAvailable === false) return false;
const source = String(session.source || '').trim().toLowerCase();
return source === 'codex' || source === 'claude';
},
🤖 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 `@web-ui/modules/app.methods.session-actions.mjs` around lines 31 - 43, The two
helpers handle missing session.nativeAvailable inconsistently: change
isSessionNativeAvailable to treat nativeAvailable as available only when
explicitly true (e.g., return session.nativeAvailable === true after validating
session object) so its behavior aligns with isImportToNativeAvailable (which
already blocks import only when nativeAvailable === true); update the logic in
isSessionNativeAvailable (function name) accordingly so undefined no longer
counts as "native available".

Comment on lines +440 to +448
const nativeOk = !(session && session.nativeAvailable === false);
if (ok) {
this.showMessage('已复制', 'success');
this.showMessage(nativeOk ? '已复制' : '已复制,但该会话不在原生目录,恢复可能失败', nativeOk ? 'success' : 'info');
return;
}
try {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(command);
this.showMessage('已复制', 'success');
this.showMessage(nativeOk ? '已复制' : '已复制,但该会话不在原生目录,恢复可能失败', nativeOk ? 'success' : 'info');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Localize the new resume-warning toast.

Lines 442 and 448 hardcode the new success/warning text in Chinese, so English users will get a mixed-language toast on this path even though this PR already adds i18n entries for the same feature.

🌐 Suggested localization approach
         async copyResumeCommand(session) {
+            const tr = (key, fallback, params = null) => (typeof this.t === 'function' ? this.t(key, params) : fallback);
             if (!this.isResumeCommandAvailable(session)) {
                 this.showMessage('不支持此操作', 'error');
                 return;
             }
             const command = this.buildResumeCommand(session);
             const ok = this.fallbackCopyText(command);
             const nativeOk = !(session && session.nativeAvailable === false);
+            const copiedMessage = tr('toast.copy.ok', 'Copied');
+            const nativeWarning = tr('sessions.resume.nativeUnavailableTitle', 'Session not in native directory, resume may fail');
             if (ok) {
-                this.showMessage(nativeOk ? '已复制' : '已复制,但该会话不在原生目录,恢复可能失败', nativeOk ? 'success' : 'info');
+                this.showMessage(nativeOk ? copiedMessage : `${copiedMessage} · ${nativeWarning}`, nativeOk ? 'success' : 'info');
                 return;
             }
             try {
                 if (navigator.clipboard && window.isSecureContext) {
                     await navigator.clipboard.writeText(command);
-                    this.showMessage(nativeOk ? '已复制' : '已复制,但该会话不在原生目录,恢复可能失败', nativeOk ? 'success' : 'info');
+                    this.showMessage(nativeOk ? copiedMessage : `${copiedMessage} · ${nativeWarning}`, nativeOk ? 'success' : 'info');
                     return;
                 }
             } catch (_) {}
🤖 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 `@web-ui/modules/app.methods.session-actions.mjs` around lines 440 - 448,
Replace the hardcoded Chinese toast messages inside the copy/resume flow with
the i18n keys added in the PR: use the nativeOk variable and call the
translation helper (e.g., this.$t or the project's i18n.t) instead of the
literal strings in both the immediate-ok branch and the navigator.clipboard
success branch; update the two showMessage calls (the ones using nativeOk ?
'已复制' : '已复制,但该会话不在原生目录,恢复可能失败') to use something like this.$t('session.copied')
and this.$t('session.copied_not_native') (keeping the same success/info
severity) so English users receive localized text.

@awsl233777
Copy link
Copy Markdown
Collaborator Author

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@awsl233777 Sure! I'll re-review the PR right away.

[review]

@awsl233777
Copy link
Copy Markdown
Collaborator Author

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@awsl233777 Sure! I'll kick off a fresh re-review of the PR right away.

[review]

@awsl233777
Copy link
Copy Markdown
Collaborator Author

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@awsl233777 Sure! I'll kick off another fresh review of PR #136 right away.

[review]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant