Fixture/flick#1280
Conversation
主屏幕模式下 frame 持续溢出 viewport 时,cursor-restore LF 把内容滚入 scrollback 导致相对光标追踪漂移,可见区 diff 落到错误行产生重影(重复 banner / 错位)。 扩展 log-update overflow 分支为无条件 fullReset(含 \x1b[3J 清 scrollback), 并将主屏 self-healing 清屏从 ERASE_SCREEN (CSI 2 J) 换成 ERASE_DOWN (CSI J), 避免 xterm.js / VSCode 集成终端的 scrollback 边界副作用。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- scripts/verify-autofix-pr.ts: 一次性 autofix-pr 验证脚本,全仓零引用 - scripts/smoke-test-commands.ts: 开发期冒烟测试脚本,无任何 import - scripts/probe-subscription-endpoints.ts: 手动 endpoint 探针,无引用 均不在 package.json scripts、build.ts、vite.config.ts、CI workflows 中。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 src/self-hosted-runner/main.ts(自动生成的 Promise.resolve() stub)
- 同步移除 src/entrypoints/cli.tsx 中 feature('SELF_HOSTED_RUNNER') 守卫的 fast-path 分支
- 该 flag 不在 build.ts DEFAULT_BUILD_FEATURES 也不在 dev 默认列表,所有默认配置下整段为构建期死代码
删除 stub 单独会留下未解析的动态 import,必须协同拆除。
Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
移除 watchScheduledTasks、buildMissedTaskNotification、connectRemoteControl 三个 stub 函数(函数体仅 throw new Error('not implemented')),以及仅被这些 stub 引用的孤儿类型(ScheduledTasksHandle、ConnectRemoteControlOptions、RemoteControlHandle、InboundPrompt 等)。
全仓零外部引用。buildMissedTaskNotification 在 src/utils/cronScheduler.ts 有真实可用实现,未受影响。
Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 getKillRingItem、getKillRingSize、clearKillRing、canYankPop(全仓零引用的独立 export) - 移除 VIM_WORD_CHAR_REGEX 的 export 关键字(仍由 isVimWordChar 内部使用,保留常量本体) kill ring 特性本身仍活跃(getLastKill/pushToKillRing/yankPop 在 useSearchInput/useTextInput 使用),仅这几个孤儿 helper 未接入。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 deduplicateSessionBranches(全仓零调用,含 JSDoc) - 删除 buildExportData(全仓零调用,原 S3 上传路径实际用 HTML 而非 JSON) - InsightsExport 仅移除 export 关键字(保留类型本体,仍作为内部返回类型) Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 AUTONOMY_CLI(CLI 子命令描述对象,零引用;handler 仅用 AUTONOMY_USAGE) - 删除 AUTONOMY_COMMAND_DESCRIPTION(值已在 main.tsx:5181 内联) - ParsedAutonomyCommand 仅移除 export 关键字(保留类型作为 parseAutonomyArgs 返回类型) Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- binaryCheck.ts: 删除 clearBinaryCache(零调用,binaryCache 仍由 isBinaryInstalled 使用) - claudeAiLimits.ts: 删除 RATE_LIMIT_DISPLAY_NAMES 常量 + getRateLimitDisplayName(互为唯一消费者) - codeIndexing.ts: 删除 detectCodeIndexingFromMcpTool(同胞 detectCodeIndexingFromCommand/McpServerName 仍活跃) Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
下列符号均仅在本文件内被引用,export 关键字冗余;保留符号本体不动: - internalLogging.ts: getContainerId(line 88 内部调用) - api/errors.ts: isMediaSizeError(line 151 内部调用) - api/withRetry.ts: parseMaxTokensContextOverflowError(line 389/724 内部调用) - statsCache.ts: STATS_CACHE_VERSION(7 处内部使用) - startupProfiler.ts: logStartupPerf(line 128 内部调用) - bashCommandHelpers.ts: CommandIdentityCheckers(3 处内部参数类型) Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
注释代码(已死的、引用不存在符号的注释块): - Onboarding.tsx: 注释化的 preflight if-block(引用不存在的 preflightStep) - ultraplan.tsx: 两处引用不存在符号的注释(ULTRAPLAN_INSTRUCTIONS、getUltraplanModel) - types/hooks.ts: 禁用的 type-fest IsEqual 类型断言块 - types/global.d.ts: 已被真实模块取代的 Ultraplan ambient declares - types/textInputTypes.ts: 注释化的 onMessage interface 成员 legacy shim: - cli/bg.ts: 删除 handleBgFlag 别名 export(同胞 handleBgStart 已被所有调用点使用) Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 src/utils/ccshareResume.ts(parseCcshareId 恒返回 null、loadCcshare 恒抛错的 stub)
- 同步移除 src/main.tsx 中 USER_TYPE === 'ant' 守卫下的 if (ccshareId) {...} else {...} 双分支
- 提升 else 块(文件路径 resume 处理)为直接进入 if (options.resume) 块内
ccshare 是 Anthropic 内部特性(go/ccshare URL),stub 未实现导致 ccshareId 恒为 null,整个 ccshare 分支永不进入;保留的文件路径 resume 路径不变。
Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
与 self-hosted-runner 相同模式的 sibling(工作流 1 verifier 建议同步处理):
- 删除 src/environment-runner/main.ts(自动生成的 Promise.resolve() stub)
- 同步移除 src/entrypoints/cli.tsx 中 feature('BYOC_ENVIRONMENT_RUNNER') 守卫的 fast-path 分支
- 清理两个空目录(src/self-hosted-runner/、src/environment-runner/)
BYOC_ENVIRONMENT_RUNNER flag 不在 build.ts DEFAULT_BUILD_FEATURES 也不在 dev 默认列表,所有默认配置下整段为构建期死代码。
Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
#!/usr/bin/env bun shebang 的手动诊断脚本,全仓零引用,不在 package.json/build.ts/vite.config.ts/CI workflows 中。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 src/services/api/ultrareviewPreflight.ts(自动生成的 stub) - 删除 src/commands/review/UltrareviewPreflightDialog.tsx(依赖前者的 UI stub) - 删除 src/services/api/__tests__/ultrareviewPreflight.test.ts(测试已删代码) - 同步移除 ultrareviewCommand.test.tsx 中对 UltrareviewPreflightDialog 的 mock Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 src/services/compact/cachedMCConfig.ts(自动生成的 stub)
- 同步移除 src/constants/prompts.ts 中依赖该 stub 的代码:
- getCachedMCConfigForFRC 变量(feature('CACHED_MICROCOMPACT') 守卫的 require)
- getFunctionResultClearingSection 函数(约 18 行)
- systemPrompt 数组中的 frc section 调用与注册
CACHED_MICROCOMPACT 不在 build.ts DEFAULT_BUILD_FEATURES 也不在 dev 默认列表,所有默认配置下整段为构建期死代码。
Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- 删除 src/services/goal/goalAudit.ts(导出 COMPLETION_AUDIT_RULES/BLOCKED_AUDIT_RULES/isGoalTerminal 等未引用的 stub) - 同步移除 tests/integration/goal-lifecycle.test.ts 中对 goalAudit 的 import 和一个测试用例(budget_limited is terminal) Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
移除运行时函数体仅为 throw new Error 或 placeholder 的 stub: - createSdkMcpToolDefinition、createSdkMcpServer - query 函数重载与实现 - unstable_v2_* 系列函数 - session 操作 stub(getSessionMessages/listSessions/getSessionInfo/renameSession/tagSession/forkSession) - AbortError 类 保留所有 export type 重导出和类型别名(仍是公共类型面)。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
删除 "// Re-export progress types for backwards compatibility" 注释块及其重导出语句。所有消费方已直接从 src/types/tools.js 导入,无需重导出转发。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
- clearRegisteredHooks(STATE.registeredHooks 仍由其他函数管理) - getInvokedSkills(getInvokedSkillsForAgent 是活跃入口) - getSessionSource(setSessionSource 仍活跃,sessionSource state 字段保留) - markScrollActivity(scrollDraining/getIsScrollDraining/waitForScrollDrain 仍活跃) 仅删除孤儿访问器,不动模块级 state 副作用。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
涉及 18 个文件,每处均为独立的 unreferenced export 删除或 export 关键字冗余移除: - bridge/bridgeStatusUtil.ts、components/TrustDialog/utils.ts、context/stats.tsx - keybindings/loadUserBindings.ts、memdir/paths.ts、remote/sdkMessageAdapter.ts - services/acp/utils.ts(删除 nodeToWebReadable,全仓零引用) - services/api/metricsOptOut.ts、services/lsp/LSPDiagnosticRegistry.ts、services/lsp/manager.ts - services/mcp/utils.ts、services/skillLearning/projectContext.ts - services/teamMemorySync/secretScanner.ts、services/teamMemorySync/watcher.ts - skills/loadSkillsDir.ts、utils/attachments.ts、utils/filePersistence/filePersistence.ts - utils/messageQueueManager.ts Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
涉及 11 个 workspace 包文件,每处均为独立的 unreferenced export 删除或 export 关键字冗余移除: - @ant/ink/core/termio/csi.ts(eraseLine) - acp-link/manager/types.ts、acp-link/ws-message.ts - builtin-tools/AgentTool/agentMemory.ts、BashTool/bashSecurity.ts、BashTool/sedEditParser.ts - builtin-tools/ConfigTool/supportedSettings.ts、FileEditTool/utils.ts - remote-control-server/store.ts、transport/event-bus.ts、types/messages.ts Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
This reverts commit 3d18e1d.
回退 f69c705 中引入的 ink.tsx self-healing 机制(lastMainScreenHealTime 字段 + 每 5 秒触发全量重绘 + needsEraseBeforePaint 主屏幕分支)。该机制在 workflow 面板持续刷新场景下表现为可见的"重复刷新",且修复效果不稳定。 alt-screen 的 needsEraseBeforePaint 路径和 prevFrameContaminated 字段保留, 它们仍服务于 handleResize / layout shift / selection 高亮。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
之前几次渲染层修复都失败,因为没动 tab 列表的数据源:打开 /workflows 会 自动 hydrate 最多 20 个历史 done/killed run,全部塞进一行 TabsBar,超出 终端宽度后 Ink 把字符画到屏外造成重影乱码。 - selectors.ts 加 filterActiveRuns(只留 status === 'running')和 capTabsForDisplay(超额 fold 成 +N)两个 pure function - WorkflowsPanel 接线 activeRuns:focus clamp、focused、nextTab/prevTab、 TabsBar 全部基于过滤后的 activeRuns - TabsBar 复用 truncateLabel 限制每个 tab 名 18 字符 + 最多 6 个 tab, 多余显示 +N,从结构上钉死单行总宽度 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
ultracode canonical pipeline 脚本常在 agent() 直接传 opts.phase 而不调 phase() hook,导致 phase_started 从未发出;同时 phase_done 只在下次 phase() 触发,上一 个 phase 在 run.phases 里一直停在 running。mergePhases 之前把 actual 当权威, 于是出现 "Map 8/8 全 done 还显示 running、Find 1/4 running 反而显示 pending"。 改为派生层修复:mergePhases 新增 derivePhaseStatus——actual.status==='done' 权威;否则有 agents 就按 agents 状态推(全 done→done,否则 running);否则看 actual 是否 running。再补一层遍历,让只在 agents 上出现的 phase 也进 sidebar。 不改 store 状态语义,已有 state.json 无需迁移。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
entry.ts 在 ACP 握手期调用的 applySafeConfigEnvironmentVariables 触发了 loadSettingsFromDisk,此时 getOriginalCwd() 还是进程启动 cwd(非项目目录), 导致 localSettings/projectSettings 按错误路径解析为空并被 session cache 锁住, 后续 createSession 里 setOriginalCwd 也无法纠正。在 setOriginalCwd 与 chdir 之后清缓存并重新应用,让 settings.local.json 和项目级 env 对 readSettingsPermissionMode 及下游可见。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
📝 WalkthroughWalkthroughThis PR makes two main functional changes — improving the workflow panel to filter/cap run tabs and fix phase-status derivation, and refactoring the ANT session resume flow from ccshare URLs to file-based transcripts — alongside a broad cleanup that removes the ultrareview preflight flow, daemon/SDK primitive exports, runner stubs, and dozens of no-longer-needed exported helpers and test utilities across the codebase. ChangesWorkflow Panel: Active-Run Filtering and Tab Capping
Session Resume, ACP Fix, SDK Pruning, and API Surface Cleanup
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/workflow/__tests__/selectors.test.ts (1)
66-208: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winGroup these new test cases under
describe()blocks.The added cases are top-level
test()calls; this file should followdescribe()+test()grouping for module-level clarity and
consistency.As per coding guidelines,
**/*.test.ts: “usedescribe()+test()pattern with English descriptions.”🤖 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/workflow/__tests__/selectors.test.ts` around lines 66 - 208, The test cases added to the file are currently top-level test() calls, but the coding guidelines require using describe() + test() grouping pattern for module-level clarity. Organize the tests by grouping related tests under describe() blocks based on the function they test: wrap the two mergePhases tests in describe('mergePhases'), the filterAgentsByPhase test in describe('filterAgentsByPhase'), the tabLabel test in describe('tabLabel'), the four filterActiveRuns tests in describe('filterActiveRuns'), and the four capTabsForDisplay tests in describe('capTabsForDisplay'). Move each test() call inside its corresponding describe() block to maintain consistency with the file's existing patterns.Source: Coding guidelines
🤖 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/main.tsx`:
- Around line 4241-4251: The code at resolvedPath attempts to load every
non-UUID resume value as a transcript file, but if a same-named local file
exists and fails to parse as a transcript, it throws an error at line 4278
instead of falling back to picker/search-term behavior. To fix this, broaden the
error handling in the catch block after loadTranscriptFromFile to catch all
errors, not just ENOENT, so that any parse or validation errors also fall
through to the session-ID handling path instead of propagating up as a hard
failure. This allows non-file-like resume values (like search terms) and
malformed files to gracefully fall back to alternative resolution methods.
In `@src/services/acp/agent/createSessionMethod.ts`:
- Around line 94-103: The applySafeConfigEnvironmentVariables() function call
can throw an error, but it is currently positioned before the try block that
contains the finally clause responsible for restoring process.cwd(). If
applySafeConfigEnvironmentVariables() throws, the finally block will never
execute, leaving the process-global CWD in a mutated state. Move both the
resetSettingsCache() and applySafeConfigEnvironmentVariables() calls inside the
try block so that the finally block is guaranteed to execute and properly
restore the original CWD regardless of whether an exception is thrown.
In `@src/workflow/panel/WorkflowsPanel.tsx`:
- Around line 130-139: The findIndex call in both nextTab and prevTab functions
can return -1 when activeRunId is not found in activeRuns (e.g., due to
transient null/invalid values), which causes incorrect index calculations when
performing the modulo math. In both the nextTab and prevTab functions,
immediately after the findIndex call that assigns to idx, add a guard condition
to normalize idx to 0 if it equals -1, ensuring the modulo arithmetic produces
the correct tab index for cycling regardless of whether the activeRunId is
temporarily invalid.
---
Nitpick comments:
In `@src/workflow/__tests__/selectors.test.ts`:
- Around line 66-208: The test cases added to the file are currently top-level
test() calls, but the coding guidelines require using describe() + test()
grouping pattern for module-level clarity. Organize the tests by grouping
related tests under describe() blocks based on the function they test: wrap the
two mergePhases tests in describe('mergePhases'), the filterAgentsByPhase test
in describe('filterAgentsByPhase'), the tabLabel test in describe('tabLabel'),
the four filterActiveRuns tests in describe('filterActiveRuns'), and the four
capTabsForDisplay tests in describe('capTabsForDisplay'). Move each test() call
inside its corresponding describe() block to maintain consistency with the
file's existing patterns.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 57dce4d9-b7cb-42d2-bc82-f37a425940a6
📒 Files selected for processing (73)
README.mdpackages/@ant/ink/src/core/ink.tsxpackages/@ant/ink/src/core/termio/csi.tspackages/acp-link/src/manager/types.tspackages/builtin-tools/src/tools/AgentTool/agentMemory.tspackages/builtin-tools/src/tools/BashTool/bashCommandHelpers.tspackages/builtin-tools/src/tools/BashTool/bashSecurity.tspackages/builtin-tools/src/tools/BashTool/sedEditParser.tspackages/builtin-tools/src/tools/ConfigTool/supportedSettings.tspackages/builtin-tools/src/tools/FileEditTool/utils.tspackages/remote-control-server/src/store.tspackages/remote-control-server/src/transport/event-bus.tspackages/remote-control-server/src/types/messages.tsscripts/probe-local-wiring.tsscripts/probe-subscription-endpoints.tsscripts/smoke-test-commands.tsscripts/verify-autofix-pr.tssrc/Tool.tssrc/bootstrap/state.tssrc/bridge/bridgeStatusUtil.tssrc/cli/bg.tssrc/commands/insights.tssrc/commands/review/UltrareviewPreflightDialog.tsxsrc/commands/review/__tests__/ultrareviewCommand.test.tsxsrc/commands/ultraplan.tsxsrc/components/Onboarding.tsxsrc/components/TrustDialog/utils.tssrc/constants/prompts.tssrc/context/stats.tsxsrc/entrypoints/agentSdkTypes.tssrc/entrypoints/cli.tsxsrc/environment-runner/main.tssrc/keybindings/loadUserBindings.tssrc/main.tsxsrc/memdir/paths.tssrc/remote/sdkMessageAdapter.tssrc/self-hosted-runner/main.tssrc/services/acp/agent/createSessionMethod.tssrc/services/acp/utils.tssrc/services/api/__tests__/ultrareviewPreflight.test.tssrc/services/api/errors.tssrc/services/api/metricsOptOut.tssrc/services/api/ultrareviewPreflight.tssrc/services/api/withRetry.tssrc/services/claudeAiLimits.tssrc/services/compact/cachedMCConfig.tssrc/services/goal/goalAudit.tssrc/services/internalLogging.tssrc/services/lsp/LSPDiagnosticRegistry.tssrc/services/lsp/manager.tssrc/services/mcp/utils.tssrc/services/skillLearning/projectContext.tssrc/services/teamMemorySync/secretScanner.tssrc/services/teamMemorySync/watcher.tssrc/skills/loadSkillsDir.tssrc/types/global.d.tssrc/types/hooks.tssrc/types/textInputTypes.tssrc/utils/Cursor.tssrc/utils/attachments.tssrc/utils/autonomyCommandSpec.tssrc/utils/binaryCheck.tssrc/utils/ccshareResume.tssrc/utils/codeIndexing.tssrc/utils/filePersistence/filePersistence.tssrc/utils/messageQueueManager.tssrc/utils/startupProfiler.tssrc/utils/statsCache.tssrc/workflow/__tests__/selectors.test.tssrc/workflow/panel/TabsBar.tsxsrc/workflow/panel/WorkflowsPanel.tsxsrc/workflow/panel/selectors.tstests/integration/goal-lifecycle.test.ts
💤 Files with no reviewable changes (53)
- src/self-hosted-runner/main.ts
- src/environment-runner/main.ts
- src/types/textInputTypes.ts
- scripts/verify-autofix-pr.ts
- src/services/goal/goalAudit.ts
- scripts/probe-local-wiring.ts
- src/utils/binaryCheck.ts
- packages/remote-control-server/src/transport/event-bus.ts
- src/types/global.d.ts
- src/services/lsp/manager.ts
- scripts/smoke-test-commands.ts
- packages/remote-control-server/src/types/messages.ts
- src/components/Onboarding.tsx
- src/skills/loadSkillsDir.ts
- src/services/api/ultrareviewPreflight.ts
- src/services/compact/cachedMCConfig.ts
- src/types/hooks.ts
- src/utils/ccshareResume.ts
- src/services/api/tests/ultrareviewPreflight.test.ts
- src/services/mcp/utils.ts
- src/services/teamMemorySync/secretScanner.ts
- scripts/probe-subscription-endpoints.ts
- src/commands/ultraplan.tsx
- packages/builtin-tools/src/tools/ConfigTool/supportedSettings.ts
- src/services/api/metricsOptOut.ts
- src/context/stats.tsx
- src/remote/sdkMessageAdapter.ts
- src/keybindings/loadUserBindings.ts
- packages/builtin-tools/src/tools/FileEditTool/utils.ts
- tests/integration/goal-lifecycle.test.ts
- packages/builtin-tools/src/tools/AgentTool/agentMemory.ts
- src/commands/review/UltrareviewPreflightDialog.tsx
- packages/acp-link/src/manager/types.ts
- src/services/claudeAiLimits.ts
- packages/@ant/ink/src/core/termio/csi.ts
- packages/builtin-tools/src/tools/BashTool/sedEditParser.ts
- src/services/lsp/LSPDiagnosticRegistry.ts
- src/constants/prompts.ts
- src/cli/bg.ts
- src/Tool.ts
- src/utils/messageQueueManager.ts
- src/memdir/paths.ts
- src/utils/codeIndexing.ts
- packages/builtin-tools/src/tools/BashTool/bashSecurity.ts
- src/bridge/bridgeStatusUtil.ts
- src/components/TrustDialog/utils.ts
- src/bootstrap/state.ts
- src/services/skillLearning/projectContext.ts
- packages/remote-control-server/src/store.ts
- src/entrypoints/agentSdkTypes.ts
- packages/@ant/ink/src/core/ink.tsx
- src/services/teamMemorySync/watcher.ts
- src/entrypoints/cli.tsx
| const resolvedPath = resolve(options.resume); | ||
| try { | ||
| const resumeStart = performance.now(); | ||
| let logOption; | ||
| try { | ||
| const resumeStart = performance.now(); | ||
| const logOption = await loadCcshare(ccshareId); | ||
| const result = await loadConversationForResume(logOption, undefined); | ||
| // Attempt to load as a transcript file; ENOENT falls through to session-ID handling | ||
| logOption = await loadTranscriptFromFile(resolvedPath); | ||
| } catch (error) { | ||
| if (!isENOENT(error)) throw error; | ||
| // ENOENT: not a file path — fall through to session-ID handling | ||
| } |
There was a problem hiding this comment.
Avoid forcing every non-UUID --resume value through transcript-file parsing.
At Line 4241, any non-UUID resume value is treated as a file path first. If a same-named local file exists but is not a transcript, parse errors at Line 4278 cause a hard failure at Line 4284 instead of falling back to picker/search-term behavior.
💡 Suggested fix
- if (options.resume && typeof options.resume === 'string' && !maybeSessionId) {
- const resolvedPath = resolve(options.resume);
+ if (options.resume && typeof options.resume === 'string' && !maybeSessionId) {
+ const resumeArg = options.resume.trim();
+ const looksLikeTranscriptPath =
+ /[\\/]/.test(resumeArg) || resumeArg.endsWith('.json') || resumeArg.endsWith('.jsonl');
+ const resolvedPath = resolve(resumeArg);
try {
const resumeStart = performance.now();
let logOption;
- try {
+ if (looksLikeTranscriptPath) {
+ try {
// Attempt to load as a transcript file; ENOENT falls through to session-ID handling
logOption = await loadTranscriptFromFile(resolvedPath);
- } catch (error) {
- if (!isENOENT(error)) throw error;
- // ENOENT: not a file path — fall through to session-ID handling
+ } catch (error) {
+ if (!isENOENT(error)) throw error;
+ // ENOENT: not a file path — fall through to session-ID handling
+ }
}
if (logOption) {Also applies to: 4278-4286
🤖 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/main.tsx` around lines 4241 - 4251, The code at resolvedPath attempts to
load every non-UUID resume value as a transcript file, but if a same-named local
file exists and fails to parse as a transcript, it throws an error at line 4278
instead of falling back to picker/search-term behavior. To fix this, broaden the
error handling in the catch block after loadTranscriptFromFile to catch all
errors, not just ENOENT, so that any parse or validation errors also fall
through to the session-ID handling path instead of propagating up as a hard
failure. This allows non-file-like resume values (like search terms) and
malformed files to gracefully fall back to alternative resolution methods.
| // entry.ts calls applySafeConfigEnvironmentVariables() during handshake so the | ||
| // API client can authenticate before createSession arrives. At that point | ||
| // getOriginalCwd() is still the spawn cwd (not the project dir), so | ||
| // loadSettingsFromDisk() resolves localSettings/projectSettings against the | ||
| // wrong root and caches the empty result. Now that we've set the real project | ||
| // cwd, drop the cache and re-apply so settings.local.json and project env | ||
| // become visible to readSettingsPermissionMode() and downstream consumers. | ||
| resetSettingsCache() | ||
| applySafeConfigEnvironmentVariables() | ||
|
|
There was a problem hiding this comment.
Move cache/env re-apply inside the try that guarantees CWD restoration.
applySafeConfigEnvironmentVariables() at Line 102 can throw. Because it runs before the Line 104 try, the finally that restores process.cwd() never executes, leaving process-global CWD mutated.
💡 Suggested fix
- resetSettingsCache()
- applySafeConfigEnvironmentVariables()
-
- try {
+ try {
+ resetSettingsCache()
+ applySafeConfigEnvironmentVariables()
// Build tools with a permissive permission context.
const permissionContext = getEmptyToolPermissionContext()📝 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.
| // entry.ts calls applySafeConfigEnvironmentVariables() during handshake so the | |
| // API client can authenticate before createSession arrives. At that point | |
| // getOriginalCwd() is still the spawn cwd (not the project dir), so | |
| // loadSettingsFromDisk() resolves localSettings/projectSettings against the | |
| // wrong root and caches the empty result. Now that we've set the real project | |
| // cwd, drop the cache and re-apply so settings.local.json and project env | |
| // become visible to readSettingsPermissionMode() and downstream consumers. | |
| resetSettingsCache() | |
| applySafeConfigEnvironmentVariables() | |
| // entry.ts calls applySafeConfigEnvironmentVariables() during handshake so the | |
| // API client can authenticate before createSession arrives. At that point | |
| // getOriginalCwd() is still the spawn cwd (not the project dir), so | |
| // loadSettingsFromDisk() resolves localSettings/projectSettings against the | |
| // wrong root and caches the empty result. Now that we've set the real project | |
| // cwd, drop the cache and re-apply so settings.local.json and project env | |
| // become visible to readSettingsPermissionMode() and downstream consumers. | |
| try { | |
| resetSettingsCache() | |
| applySafeConfigEnvironmentVariables() | |
| // Build tools with a permissive permission context. | |
| const permissionContext = getEmptyToolPermissionContext() |
🤖 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/services/acp/agent/createSessionMethod.ts` around lines 94 - 103, The
applySafeConfigEnvironmentVariables() function call can throw an error, but it
is currently positioned before the try block that contains the finally clause
responsible for restoring process.cwd(). If
applySafeConfigEnvironmentVariables() throws, the finally block will never
execute, leaving the process-global CWD in a mutated state. Move both the
resetSettingsCache() and applySafeConfigEnvironmentVariables() calls inside the
try block so that the finally block is guaranteed to execute and properly
restore the original CWD regardless of whether an exception is thrown.
| if (activeRuns.length === 0) return; | ||
| const idx = activeRuns.findIndex(r => r.runId === activeRunId); | ||
| const next = activeRuns[(idx + 1) % activeRuns.length]!; | ||
| switchTab(next.runId); | ||
| }; | ||
| const prevTab = (): void => { | ||
| if (runs.length === 0) return; | ||
| const idx = runs.findIndex(r => r.runId === activeRunId); | ||
| const next = runs[(idx - 1 + runs.length) % runs.length]!; | ||
| if (activeRuns.length === 0) return; | ||
| const idx = activeRuns.findIndex(r => r.runId === activeRunId); | ||
| const next = activeRuns[(idx - 1 + activeRuns.length) % activeRuns.length]!; | ||
| switchTab(next.runId); |
There was a problem hiding this comment.
Handle invalid active-run index before tab cycling.
When findIndex returns -1 (e.g., transient null/invalid activeRunId), prevTab picks an unexpected entry. Normalize the
index before modulo math.
Suggested patch
const nextTab = (): void => {
if (activeRuns.length === 0) return;
- const idx = activeRuns.findIndex(r => r.runId === activeRunId);
- const next = activeRuns[(idx + 1) % activeRuns.length]!;
+ const idx = activeRuns.findIndex(r => r.runId === activeRunId);
+ const safeIdx = idx >= 0 ? idx : 0;
+ const next = activeRuns[(safeIdx + 1) % activeRuns.length]!;
switchTab(next.runId);
};
const prevTab = (): void => {
if (activeRuns.length === 0) return;
- const idx = activeRuns.findIndex(r => r.runId === activeRunId);
- const next = activeRuns[(idx - 1 + activeRuns.length) % activeRuns.length]!;
+ const idx = activeRuns.findIndex(r => r.runId === activeRunId);
+ const safeIdx = idx >= 0 ? idx : 0;
+ const next = activeRuns[(safeIdx - 1 + activeRuns.length) % activeRuns.length]!;
switchTab(next.runId);
};📝 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.
| if (activeRuns.length === 0) return; | |
| const idx = activeRuns.findIndex(r => r.runId === activeRunId); | |
| const next = activeRuns[(idx + 1) % activeRuns.length]!; | |
| switchTab(next.runId); | |
| }; | |
| const prevTab = (): void => { | |
| if (runs.length === 0) return; | |
| const idx = runs.findIndex(r => r.runId === activeRunId); | |
| const next = runs[(idx - 1 + runs.length) % runs.length]!; | |
| if (activeRuns.length === 0) return; | |
| const idx = activeRuns.findIndex(r => r.runId === activeRunId); | |
| const next = activeRuns[(idx - 1 + activeRuns.length) % activeRuns.length]!; | |
| switchTab(next.runId); | |
| const nextTab = (): void => { | |
| if (activeRuns.length === 0) return; | |
| const idx = activeRuns.findIndex(r => r.runId === activeRunId); | |
| const safeIdx = idx >= 0 ? idx : 0; | |
| const next = activeRuns[(safeIdx + 1) % activeRuns.length]!; | |
| switchTab(next.runId); | |
| }; | |
| const prevTab = (): void => { | |
| if (activeRuns.length === 0) return; | |
| const idx = activeRuns.findIndex(r => r.runId === activeRunId); | |
| const safeIdx = idx >= 0 ? idx : 0; | |
| const next = activeRuns[(safeIdx - 1 + activeRuns.length) % activeRuns.length]!; | |
| switchTab(next.runId); | |
| }; |
🤖 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/workflow/panel/WorkflowsPanel.tsx` around lines 130 - 139, The findIndex
call in both nextTab and prevTab functions can return -1 when activeRunId is not
found in activeRuns (e.g., due to transient null/invalid values), which causes
incorrect index calculations when performing the modulo math. In both the
nextTab and prevTab functions, immediately after the findIndex call that assigns
to idx, add a guard condition to normalize idx to 0 if it equals -1, ensuring
the modulo arithmetic produces the correct tab index for cycling regardless of
whether the activeRunId is temporarily invalid.
Summary by CodeRabbit
New Features
Improvements