Repository navigation
fix(ai): open Cloud resource links in Assistant answers even when the model drops the leading slash - #1262
Merged
Conversation
… model drops the leading slash A model sometimes writes a Cloud resource link as app/notebooks/... or open/... without its leading slash. The browser resolved that against /app/assistant and opened /app/app/notebooks/..., a broken address. AssistantMarkdownBlock renders every Assistant answer and work text, so it now roots scheme-less app/ and open/ hrefs in the sanitized HTML before the first render. Server and client output stay identical, the pill keeps its type and accessible name, and the result stays same-origin under /app/ or /open/. Every other link stays as written.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Outcome
In Assistant chat answers, a Cloud resource link the model wrote without its leading slash, such as
[Meeting notes](app/notebooks/abc/notes/def)or[Draft](open/mail.draft/~x), now opens the resource. Before, the browser resolved it against/app/assistant?conversation=...and opened the broken/app/app/notebooks/....Root cause
Tools return correct root-relative hrefs and the system prompt asks the model to copy them, but models sometimes drop the leading
/. The shared links extension renders any scheme-less href as an internal reference pill and keeps it unchanged, andAssistantMarkdownBlockonly rewrote chat-file links (on the client).Fix
AssistantMarkdownBlock(packages/cloud/src/ai/chat/primitives.tsx) renders every Assistant answer and work text. It now passes the sanitized HTML throughrootResourceLinks(answer-links.ts) before rendering:<a>hrefthat starts exactly withapp/oropen/becomes/app/...or/open/.... The result is always root-relative under/app/or/open/, so it stays same-origin./app/...,#heading,?x,./app/...,report.md,docs/app/x,App/x,note://,attach://, other attributes, text,<img src>./app/...link. The test checks that the anchor is byte-identical.resolveFileLink) runs as before. It now sees the rooted href.Design note: I did not use the refs that tool results returned. That would need new plumbing from the timeline into the renderer, so this uses the narrow prefix rule. The rule builds no new URLs. It only adds the missing slash to the two Cloud route roots that refs use. The system prompt is unchanged.
Docs
docs-site/docs/en/ai/chat-interface.md: one sentence after the paragraph on answer resource links. No Help change, because Help does not describe answer links. Nocloud-devskill change, because no stable workflow or cross-cutting platform invariant changed.How do we prevent this next time?
The render test reproduces the bug: it fails on
mainwith/app/app/notebooks/...and/app/open/.... With the unit and behavior tests, it pins the rule and the unchanged cases. No existing lessons-learned error class fits (model output that drifts from a copied href), and no repository check could catch it. The tests are the guard.Verification
origin/maincode (2 hrefs resolved to/app/app/...//app/open/...) and passes with the fix.bun test answer-links.test.ts primitives.render.test.tsx: 7 pass.bun run --cwd packages/cloud typecheck: pass.bun run test --filter packages/assistant: all pass.bun run test --filter packages/cloud: all pass exceptscripts/cli-pack.test.ts> "packs the shared bundle contract..." The run hit the 5 s default timeout under machine load. The test is unrelated to this change and passed on its own (6/6, 4.15 s for the file).git diff --check, biome on the changed files: clean.