@@ -16,6 +16,11 @@ import {
1616} from '@/lib/knowledge/application/workspace-search'
1717import { sourceAuthor } from '@/lib/knowledge/search/author'
1818import { createKnowledgeDocumentCitation } from '@/lib/knowledge/search/citation'
19+ import {
20+ measureSearchStage ,
21+ recordSearchStageDuration ,
22+ withSearchDiagnostics ,
23+ } from '@/lib/knowledge/search/diagnostics'
1924import { intersectWorkspaceSearchFilters } from '@/lib/knowledge/search/filters'
2025import { connectorDisplayName } from '@/lib/sim-search/connectors'
2126import { projectResolvedSecretModelContent } from '@/executor/utils/resolved-secret-content-projection'
@@ -37,77 +42,91 @@ const CITATION_INSTRUCTION =
3742export const searchWorkspaceServerTool : BaseServerTool = {
3843 name : 'search_workspace' ,
3944 async execute ( raw , context ?: ServerToolContext ) {
40- try {
41- const scope = requireCopilotKnowledgeScope ( context )
42- const { query, topK, ...requestedFilters } = searchInputSchema . parse ( raw )
43- const registry = context ?. resolvedSecretTraceRegistry
44- if ( ! registry ) throw new Error ( 'Knowledge result provenance is unavailable' )
45- const projected = projectResolvedSecretModelContent ( query , registry )
46- if ( ! projected . safe || typeof projected . value !== 'string' ) {
47- return {
48- success : false ,
49- message : 'Search query contains protected content. Rephrase the query.' ,
50- }
51- }
52- const input = {
53- query : projected . value ,
54- topK,
55- filters : intersectWorkspaceSearchFilters ( requestedFilters , context ?. assistantSearch ) ,
45+ return withSearchDiagnostics (
46+ {
5647 surface : context ?. searchSurface ?? 'copilot' ,
57- resultSecretRegistry : registry ,
58- signal : context ?. abortSignal ,
59- } as const
60- const result =
61- scope . kind === 'organization'
62- ? await executeCopilotOrganizationKnowledgeUseCase ( context , searchOrganizationKnowledge , {
63- ...input ,
64- organizationId : scope . organizationId ,
65- } )
66- : await executeCopilotKnowledgeUseCase ( context , searchWorkspaceKnowledge , {
67- ...input ,
68- workspaceId : scope . workspaceId ,
69- } )
70- const names = new Map ( result . knowledgeBases . map ( ( base ) => [ base . id , base . name ] ) )
71- return {
72- success : true ,
73- message : `Found ${ result . results . length } passages. ${ CITATION_INSTRUCTION } ` ,
74- data : {
75- query,
76- results : result . results . map ( ( item ) => ( {
77- documentId : item . documentId ,
78- knowledgeBaseId : item . knowledgeBaseId ,
79- knowledgeBaseName : names . get ( item . knowledgeBaseId ) ?? '' ,
80- siteName : item . connectorType
81- ? connectorDisplayName ( item . connectorType )
82- : names . get ( item . knowledgeBaseId ) ,
83- documentName : item . documentName ,
84- sourceUrl : item . sourceUrl ,
85- connectorType : item . connectorType ,
86- sourceModifiedAt : item . sourceModifiedAt ?. toISOString ( ) ?? null ,
87- author : sourceAuthor ( item . metadata ) ,
88- content : item . content ,
89- chunkIndex : item . chunkIndex ,
90- similarity : item . similarity ,
91- ...createKnowledgeDocumentCitation ( {
92- scope,
93- knowledgeBaseId : item . knowledgeBaseId ,
94- documentId : item . documentId ,
95- sourceUrl : item . sourceUrl ,
96- baseUrl : getBaseUrl ( ) ,
97- } ) ,
98- } ) ) ,
99- } ,
100- }
101- } catch ( error ) {
102- logger . error ( 'Workspace search failed' , { error } )
103- return {
104- success : false ,
105- message :
106- error instanceof z . ZodError
107- ? 'Invalid search arguments'
108- : messageForCopilotKnowledgeError ( error ) ,
48+ toolCallId : context ?. toolCallId ,
49+ executionId : context ?. executionId ,
50+ } ,
51+ async ( ) => {
52+ try {
53+ const inputStarted = performance . now ( )
54+ const scope = requireCopilotKnowledgeScope ( context )
55+ const { query, topK, ...requestedFilters } = searchInputSchema . parse ( raw )
56+ const registry = context ?. resolvedSecretTraceRegistry
57+ if ( ! registry ) throw new Error ( 'Knowledge result provenance is unavailable' )
58+ const projected = projectResolvedSecretModelContent ( query , registry )
59+ if ( ! projected . safe || typeof projected . value !== 'string' ) {
60+ return {
61+ success : false ,
62+ message : 'Search query contains protected content. Rephrase the query.' ,
63+ }
64+ }
65+ const input = {
66+ query : projected . value ,
67+ topK,
68+ filters : intersectWorkspaceSearchFilters ( requestedFilters , context ?. assistantSearch ) ,
69+ surface : context ?. searchSurface ?? 'copilot' ,
70+ resultSecretRegistry : registry ,
71+ signal : context ?. abortSignal ,
72+ } as const
73+ recordSearchStageDuration ( 'tool_input' , performance . now ( ) - inputStarted )
74+ const result = await measureSearchStage ( 'tool_application' , ( ) =>
75+ scope . kind === 'organization'
76+ ? executeCopilotOrganizationKnowledgeUseCase ( context , searchOrganizationKnowledge , {
77+ ...input ,
78+ organizationId : scope . organizationId ,
79+ } )
80+ : executeCopilotKnowledgeUseCase ( context , searchWorkspaceKnowledge , {
81+ ...input ,
82+ workspaceId : scope . workspaceId ,
83+ } )
84+ )
85+ return await measureSearchStage ( 'tool_presentation' , ( ) => {
86+ const names = new Map ( result . knowledgeBases . map ( ( base ) => [ base . id , base . name ] ) )
87+ return {
88+ success : true ,
89+ message : `Found ${ result . results . length } passages. ${ CITATION_INSTRUCTION } ` ,
90+ data : {
91+ query,
92+ results : result . results . map ( ( item ) => ( {
93+ documentId : item . documentId ,
94+ knowledgeBaseId : item . knowledgeBaseId ,
95+ knowledgeBaseName : names . get ( item . knowledgeBaseId ) ?? '' ,
96+ siteName : item . connectorType
97+ ? connectorDisplayName ( item . connectorType )
98+ : names . get ( item . knowledgeBaseId ) ,
99+ documentName : item . documentName ,
100+ sourceUrl : item . sourceUrl ,
101+ connectorType : item . connectorType ,
102+ sourceModifiedAt : item . sourceModifiedAt ?. toISOString ( ) ?? null ,
103+ author : sourceAuthor ( item . metadata ) ,
104+ content : item . content ,
105+ chunkIndex : item . chunkIndex ,
106+ similarity : item . similarity ,
107+ ...createKnowledgeDocumentCitation ( {
108+ scope,
109+ knowledgeBaseId : item . knowledgeBaseId ,
110+ documentId : item . documentId ,
111+ sourceUrl : item . sourceUrl ,
112+ baseUrl : getBaseUrl ( ) ,
113+ } ) ,
114+ } ) ) ,
115+ } ,
116+ }
117+ } )
118+ } catch ( error ) {
119+ logger . error ( 'Workspace search failed' , { error } )
120+ return {
121+ success : false ,
122+ message :
123+ error instanceof z . ZodError
124+ ? 'Invalid search arguments'
125+ : messageForCopilotKnowledgeError ( error ) ,
126+ }
127+ }
109128 }
110- }
129+ )
111130 } ,
112131}
113132
0 commit comments