Skip to content

fix(chat): preserve path:line refs through file open - #810

Open
ZxlDragonDoctor wants to merge 1 commit into
vastsa:mainfrom
ZxlDragonDoctor:fix/chat-file-ref-line
Open

ZxlDragonDoctor wants to merge 1 commit into
vastsa:mainfrom
ZxlDragonDoctor:fix/chat-file-ref-line

Conversation

@ZxlDragonDoctor

Copy link
Copy Markdown
Contributor

Problem

Chat tokens such as src/a.ts:42 open the file but lose the line. On current main, parseFileRef recognizes :line[:column] then stripLineRef drops the position before any opener runs; useOpenChatFileRef only forwards a path into file-manager / work panel.

Confirmed on the issue: reporter symptom matches code path; maintainer review on #681 notes the stripLineRef gap is real and no mergeable PR existed.

Solution

  • Keep line/column on the parse result and on ChatPreviewTarget.
  • Thread the position through useOpenChatFileRef / work-panel open path.
  • Encode plugin locations as path#L{n} via fileLocationWithPosition.
  • Host FilesTab scrolls to the line when the bundled plugin view is absent.

Addresses maintainer confirmation on #681 (stripLineRef gap; no competing mergeable PR).

Testing

  • Command: node --test apps/desktop/test/chat-links.test.mjs
  • Result: 22 passed (rechecked on this branch)
  • Cases covering this issue include:
    • parseFileRefPosition keeps the line the transcript named (#681)
    • fileLocationWithPosition encodes #L for plugin open locations (#681)
    • existing parse/linkify/workspace path behavior unchanged

Agent dimension

tool-retrieval (chat path:line refs ? file open + line scroll)

Core value

[path:line] chips in chat keep the line through open instead of only landing on the file.

Issue alignment

Fixes #681

Chat tokens like src/a.ts:42 previously lost the line in parseFileRef
before any opener ran. Keep the position on ChatPreviewTarget, thread it
through useOpenChatFileRef, encode plugin locations as path#L{line}, and
scroll the host file viewer when the bundled file-manager view is absent.
@vastsa

vastsa commented Sep 21, 2026

Copy link
Copy Markdown
Owner

Thanks — keeping the parse position is the right direction, but I checked this branch against current origin/main and it can't land as-is. The reported path from #681 is still not fixed, and the branch is red.

CI on the head is failing (landing blocker)

  • apps/desktop/src/components/workpanel/FilesTab.tsx(247,42): error TS2339: Property 'line' does not exist on type '{ path: string; seq: number; mimeType?: string | undefined; }'. workPanelFileRequest in apps/desktop/src/stores/app-state.ts:354 was not extended, so fileRequest.line does not typecheck (Head contains latest base also fails: merge-base aad46adbc, 157 commits behind origin/main).
  • apps/desktop/test/transcript-file-chips.test.mjs:47-52 still asserts fileManagerPluginTab\(target\), openFile\(target, mimeType\) and openFile\(match\.absolutePath, mimeType\). The hook now emits fileManagerPluginTab(fileLocationWithPosition(target, …)) and openFile(target, mimeType, { line, column }), so that source-contract test fails too.

The #681 path itself is not threaded

  • The transcript chip is FileRefChip in apps/desktop/src/features/chat/transcript/shared.tsx: it is given path={segment.target.path} (already stripped of :42) and calls onOpen(path), and the new 4th position argument of useOpenChatFileRef is never passed on that path — so a src/a.ts:42 chip in chat still opens the file without the line. useOpenChatFileRef's internal parseFileRefPosition(path) fallback cannot help, because the position was stripped upstream.
  • The host FilesTab path cannot work even after adding the type: all tab→request constructions (stores/slices/work-panel-slice.ts:180-184 and the sibling sites) copy only tab.resource / seq / mimeType, never the tab's line, so the scroll added in FilesTab.tsx:250-266 would be dead code.
  • Markdown #L42 links are still unhandled: toWorkspaceRel keeps #L42 and stripLineRef only strips :digits.

Possible regression on the bundled file-view path — please confirm
fileLocationWithPosition now sends path#L{n} as the plugin-view location. By design the transport preserves it: plugin-view-location.ts percent-encodes the value into the piViewOpen query parameter (and later the view:open event) so # survives. The bundled pi.file-manager 0.5.2 view uses that value as a plain path and has no #/#L parsing in resources/plugins/pi.file-manager/views/assets/index.js. With fileViewAvailable true the plugin therefore receives a literal src/a.ts#L10, where main opened the file. Either update the bundled plugin view in the same change, or keep plugin locations free of the suffix.

What would make this landable: rebase onto origin/main; extend workPanelFileRequest plus every tab→request construction; pass the position through FileRefChip; keep plugin locations plain or ship the plugin update with it; update the contract test and add the spec/E2E entries for the new #L encoding. I'll re-run the integration check (typecheck + desktop tests + targeted open path) as soon as the branch is updated.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 文件管理器插件,以 [文件名:行号] 跳转仅能定位到文件,不能跳转到行

2 participants