@@ -15,6 +15,10 @@ import { Checkbox, CopyCodeButton, cn, languages, highlight as prismHighlight }
1515import { decodeVfsSegmentSafe } from '@/lib/copilot/vfs/path-utils'
1616import { extractTextContent } from '@/lib/core/utils/react-node-text'
1717import { ContextMentionIcon } from '@/app/workspace/[workspaceId]/home/components/context-mention-icon'
18+ import {
19+ appendInlineReferenceMarkdown ,
20+ workspaceResourceReferenceMarkdown ,
21+ } from '@/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/workspace-resource-markdown'
1822import {
1923 type ContentSegment ,
2024 type CredentialSubmissionPayload ,
@@ -95,47 +99,6 @@ const ANIMATION_DRAIN_MS = 300
9599 */
96100const FADE_MAX_REVEALED_CHARS = 6000
97101
98- function startsInlineWord ( value : string ) : boolean {
99- return / ^ [ A - Z a - z 0 - 9 _ ( ] / . test ( value )
100- }
101-
102- function endsInlineWord ( value : string ) : boolean {
103- return / [ A - Z a - z 0 - 9 _ ) ] $ / . test ( value )
104- }
105-
106- function nextInlineSegmentLabel ( segment ?: ContentSegment ) : string {
107- if ( ! segment ) return ''
108- // Thinking segments are never rendered, so they contribute no following text.
109- if ( segment . type === 'text' ) return segment . content
110- if ( segment . type === 'workspace_resource' ) return segment . data . title || segment . data . id || ''
111- return ''
112- }
113-
114- function appendInlineReferenceMarkdown (
115- currentMarkdown : string ,
116- referenceMarkdown : string ,
117- nextSegment ?: ContentSegment
118- ) : string {
119- let nextMarkdown = currentMarkdown
120- if ( currentMarkdown && endsInlineWord ( currentMarkdown ) && ! / \s $ / . test ( currentMarkdown ) ) {
121- nextMarkdown += ' '
122- }
123-
124- nextMarkdown += referenceMarkdown
125-
126- const followingText = nextInlineSegmentLabel ( nextSegment )
127- if (
128- followingText &&
129- startsInlineWord ( followingText ) &&
130- ! / ^ \s / . test ( followingText ) &&
131- ! / \s $ / . test ( nextMarkdown )
132- ) {
133- nextMarkdown += ' '
134- }
135-
136- return nextMarkdown
137- }
138-
139102type TdProps = ComponentPropsWithoutRef < 'td' >
140103type ThProps = ComponentPropsWithoutRef < 'th' >
141104
@@ -586,14 +549,9 @@ function ChatContentInner({
586549 const s = parsed . segments [ i ]
587550 const nextSegment = parsed . segments [ i + 1 ]
588551 if ( s . type === 'workspace_resource' ) {
589- // Files are addressed by their encoded VFS path (copied verbatim from the tag);
590- // workflows/tables/KBs by id. The angle-bracket link destination keeps the path
591- // intact through markdown parsing (tolerates parens) without re-encoding it.
592- const ref = s . data . type === 'file' ? ( s . data . path ?? s . data . id ?? '' ) : ( s . data . id ?? '' )
593- const label = s . data . title || ref
594552 pendingMarkdown = appendInlineReferenceMarkdown (
595553 pendingMarkdown ,
596- `[ ${ label } ](<#wsres- ${ s . data . type } - ${ ref } >)` ,
554+ workspaceResourceReferenceMarkdown ( s . data ) ,
597555 nextSegment
598556 )
599557 } else if ( s . type === 'thinking' ) {
0 commit comments