@@ -14,7 +14,14 @@ import type {
1414 ToolResultPart ,
1515} from 'ai' ;
1616import { newContextItem } from './AISidebarContext' ;
17- import { type AIChatDisplayMessage , isMessageWithContext } from './types' ;
17+ import {
18+ type AIAtomicResourceMessageContext ,
19+ type AIChatDisplayMessage ,
20+ type AIMCPResourceMessageContext ,
21+ type AIMessageContext ,
22+ isAtomicResource ,
23+ isMessageWithContext ,
24+ } from './types' ;
1825
1926// Not exported from 'ai' for some reason, for now we need to define it ourselves.
2027type ReasoningPart = {
@@ -40,17 +47,14 @@ export const displayMessageToResource = async (
4047 message : AIChatDisplayMessage ,
4148 parent : Resource < Ai . AiChat > ,
4249 store : Store ,
43- context ?: string [ ] ,
50+ context ?: AIMessageContext [ ] ,
4451) : Promise < Resource < Ai . AiMessage > > => {
4552 if ( isMessageWithContext ( message ) ) {
46- // TODO: Add context to the resource
47- const contextSubjects = message . context . map ( c => c . subject ) ;
48-
4953 return displayMessageToResource (
5054 message . message ,
5155 parent ,
5256 store ,
53- contextSubjects ,
57+ message . context ,
5458 ) ;
5559 }
5660
@@ -63,7 +67,11 @@ export const displayMessageToResource = async (
6367 } ) ;
6468
6569 if ( context && context . length > 0 ) {
66- messageResource . props . providedContext = context ;
70+ const subjects = await Promise . all (
71+ context . map ( c => contextToResource ( c , messageResource , store ) ) ,
72+ ) ;
73+
74+ messageResource . props . providedContext = subjects ;
6775 }
6876
6977 if ( typeof message . content === 'string' ) {
@@ -110,6 +118,33 @@ export const displayMessageToResource = async (
110118 return messageResource ;
111119} ;
112120
121+ const contextToResource = async (
122+ context : AIMessageContext ,
123+ message : Resource < Ai . AiMessage > ,
124+ store : Store ,
125+ ) : Promise < string > => {
126+ if ( isAtomicResource ( context ) ) {
127+ return context . subject ;
128+ }
129+
130+ const contextResource = await store . newResource < Ai . AiMessage > ( {
131+ isA : ai . classes . mcpResource ,
132+ parent : message . subject ,
133+ propVals : {
134+ [ core . properties . name ] : context . name ,
135+ [ ai . properties . mcpUri ] : context . uri ,
136+ [ ai . properties . mcpServerId ] : context . serverId ,
137+ ...( context . mimetype
138+ ? { [ server . properties . mimetype ] : context . mimetype }
139+ : { } ) ,
140+ } ,
141+ } ) ;
142+
143+ contextResource . save ( ) ;
144+
145+ return contextResource . subject ;
146+ } ;
147+
113148export const messageResourcesToDisplayMessages = async (
114149 subjects : string [ ] ,
115150 store : Store ,
@@ -126,6 +161,7 @@ export const messageResourcesToDisplayMessages = async (
126161 }
127162
128163 const role = tagToRole ( resource . props . role ) ;
164+
129165 const contentResources = await Promise . all (
130166 resource . props . content . map ( s => store . getResource ( s ) ) ,
131167 ) ;
@@ -151,15 +187,20 @@ export const messageResourcesToDisplayMessages = async (
151187 } ;
152188
153189 if ( resource . props . providedContext ) {
190+ const context = (
191+ await Promise . allSettled (
192+ resource . props . providedContext . map ( c =>
193+ resourceToAIMessageContext ( c , store ) ,
194+ ) ,
195+ )
196+ )
197+ . filter ( c => c . status === 'fulfilled' )
198+ . map ( c => c . value ) ;
199+
154200 message = {
155201 role : 'annotated-message' ,
156202 message,
157- context : resource . props . providedContext . map ( c =>
158- newContextItem ( {
159- subject : c ,
160- type : 'resource' ,
161- } ) ,
162- ) ,
203+ context,
163204 } ;
164205 }
165206 }
@@ -240,6 +281,32 @@ export const messageResourcesToDisplayMessages = async (
240281 return messages ;
241282} ;
242283
284+ const resourceToAIMessageContext = async (
285+ subject : string ,
286+ store : Store ,
287+ ) : Promise < AIMessageContext > => {
288+ const resource = await store . getResource ( subject ) ;
289+
290+ if ( resource . error ) {
291+ throw resource . error ;
292+ }
293+
294+ if ( resource . hasClasses ( ai . classes . mcpResource ) ) {
295+ return newContextItem < AIMCPResourceMessageContext > ( {
296+ type : 'mcp-resource' ,
297+ name : resource . props . name ,
298+ uri : resource . props . mcpUri ,
299+ serverId : resource . props . mcpServerId ,
300+ mimetype : resource . props . mimetype ,
301+ } ) ;
302+ }
303+
304+ return newContextItem < AIAtomicResourceMessageContext > ( {
305+ type : 'atomic-resource' ,
306+ subject : resource . subject ,
307+ } ) ;
308+ } ;
309+
243310const tagToRole = ( subject : string ) => {
244311 const tag = TAG_TO_ROLE_MAPPING [ subject as keyof typeof TAG_TO_ROLE_MAPPING ] ;
245312
0 commit comments