@@ -17,6 +17,7 @@ import { COPILOT_REQUEST_MODES } from '@/lib/copilot/models'
1717import { orchestrateCopilotStream } from '@/lib/copilot/orchestrator'
1818import { getStreamMeta , readStreamEvents } from '@/lib/copilot/orchestrator/stream/buffer'
1919import type { OrchestratorResult } from '@/lib/copilot/orchestrator/types'
20+ import { resolveActiveResourceContext } from '@/lib/copilot/process-contents'
2021import {
2122 authenticateCopilotRequestSessionOnly ,
2223 createBadRequestResponse ,
@@ -45,6 +46,13 @@ const FileAttachmentSchema = z.object({
4546 size : z . number ( ) ,
4647} )
4748
49+ const ResourceAttachmentSchema = z . object ( {
50+ type : z . enum ( [ 'workflow' , 'table' , 'file' , 'knowledgebase' ] ) ,
51+ id : z . string ( ) . min ( 1 ) ,
52+ title : z . string ( ) . optional ( ) ,
53+ active : z . boolean ( ) . optional ( ) ,
54+ } )
55+
4856const ChatMessageSchema = z . object ( {
4957 message : z . string ( ) . min ( 1 , 'Message is required' ) ,
5058 userMessageId : z . string ( ) . optional ( ) ,
@@ -59,6 +67,7 @@ const ChatMessageSchema = z.object({
5967 stream : z . boolean ( ) . optional ( ) . default ( true ) ,
6068 implicitFeedback : z . string ( ) . optional ( ) ,
6169 fileAttachments : z . array ( FileAttachmentSchema ) . optional ( ) ,
70+ resourceAttachments : z . array ( ResourceAttachmentSchema ) . optional ( ) ,
6271 provider : z . string ( ) . optional ( ) ,
6372 contexts : z
6473 . array (
@@ -125,6 +134,7 @@ export async function POST(req: NextRequest) {
125134 stream,
126135 implicitFeedback,
127136 fileAttachments,
137+ resourceAttachments,
128138 provider,
129139 contexts,
130140 commands,
@@ -242,6 +252,35 @@ export async function POST(req: NextRequest) {
242252 }
243253 }
244254
255+ if ( Array . isArray ( resourceAttachments ) && resourceAttachments . length > 0 && resolvedWorkspaceId ) {
256+ const results = await Promise . allSettled (
257+ resourceAttachments . map ( async ( r ) => {
258+ const ctx = await resolveActiveResourceContext (
259+ r . type ,
260+ r . id ,
261+ resolvedWorkspaceId ! ,
262+ authenticatedUserId ,
263+ actualChatId
264+ )
265+ if ( ! ctx ) return null
266+ return {
267+ ...ctx ,
268+ tag : r . active ? '@active_tab' : '@open_tab' ,
269+ }
270+ } )
271+ )
272+ for ( const result of results ) {
273+ if ( result . status === 'fulfilled' && result . value ) {
274+ agentContexts . push ( result . value )
275+ } else if ( result . status === 'rejected' ) {
276+ logger . error (
277+ `[${ tracker . requestId } ] Failed to resolve resource attachment` ,
278+ result . reason
279+ )
280+ }
281+ }
282+ }
283+
245284 const effectiveMode = mode === 'agent' ? 'build' : mode
246285
247286 const userPermission = resolvedWorkspaceId
@@ -321,7 +360,7 @@ export async function POST(req: NextRequest) {
321360 }
322361 }
323362
324- if ( actualChatId ) {
363+ if ( stream && actualChatId ) {
325364 const acquired = await acquirePendingChatStream ( actualChatId , userMessageIdToUse )
326365 if ( ! acquired ) {
327366 return NextResponse . json (
@@ -351,7 +390,7 @@ export async function POST(req: NextRequest) {
351390 titleProvider : provider ,
352391 requestId : tracker . requestId ,
353392 workspaceId : resolvedWorkspaceId ,
354- pendingChatStreamAlreadyRegistered : Boolean ( actualChatId ) ,
393+ pendingChatStreamAlreadyRegistered : Boolean ( actualChatId && stream ) ,
355394 orchestrateOptions : {
356395 userId : authenticatedUserId ,
357396 workflowId,
0 commit comments