55// knowledge base and the chat's attachments.
66
77import { describeTurnStatus } from '@offgrid/rag/documents'
8- import type { ToolContext , ToolExtension } from '../tools '
8+ import type { SearchResult } from '../../shared/search-contract '
99import { documentStore , documentTurns } from '.'
10- import { foundPassageSource } from './chat-turn'
10+ import { foundPassageSource , type DocumentsActivity } from './chat-turn'
11+
12+ /**
13+ * What these tools read from the tool loop's context (fields of tools.ts's ToolContext). Declared
14+ * here, not imported: the tool loop imports this module, so importing it back would be a cycle.
15+ */
16+ export interface DocumentToolContext {
17+ conversationId ?: string
18+ projectId ?: string
19+ citeDocumentPassage ?: ( source : SearchResult ) => number
20+ onActivity ?: ( activity : DocumentsActivity ) => void
21+ }
1122
1223const SEARCH = 'search_documents'
1324const READ = 'read_pages'
@@ -57,7 +68,7 @@ function where(label: string | undefined, page: number): string {
5768}
5869
5970/** The documents this tool call may see. */
60- function scopeOf ( context : ToolContext | undefined ) : { conversationId ?: string ; projectId ?: string } {
71+ function scopeOf ( context : DocumentToolContext | undefined ) : { conversationId ?: string ; projectId ?: string } {
6172 return {
6273 ...( context ?. conversationId ? { conversationId : context . conversationId } : { } ) ,
6374 ...( context ?. projectId ? { projectId : context . projectId } : { } )
@@ -69,7 +80,7 @@ function scopeOf(context: ToolContext | undefined): { conversationId?: string; p
6980 * this turn's sources (also used by search_knowledge_base).
7081 */
7182export async function searchDocumentsForTool (
72- context : ToolContext | undefined ,
83+ context : DocumentToolContext | undefined ,
7384 query : string ,
7485 documentName ?: string
7586) : Promise < string > {
@@ -87,14 +98,18 @@ export async function searchDocumentsForTool(
8798 return result . text . slice ( 0 , MAX_CHARS )
8899}
89100
90- export const documentToolExtension : ToolExtension = {
101+ export const documentToolExtension = {
91102 id : 'attached-documents' ,
92- category : 'tool' ,
103+ category : 'tool' as const ,
93104 // Added per turn by toolChat when the conversation has documents, never from the shared list.
94- schemas : ( ) => [ ] ,
95- canHandle : ( name ) => name === SEARCH || name === READ ,
96- isReadOnlyTool : ( ) => true ,
97- async execute ( name , args , context ) {
105+ schemas : ( ) : unknown [ ] => [ ] ,
106+ canHandle : ( name : string ) : boolean => name === SEARCH || name === READ ,
107+ isReadOnlyTool : ( ) : boolean => true ,
108+ async execute (
109+ name : string ,
110+ args : Record < string , unknown > ,
111+ context ?: DocumentToolContext
112+ ) : Promise < string > {
98113 if ( name === SEARCH ) {
99114 const query = typeof args . query === 'string' ? args . query . trim ( ) : ''
100115 if ( ! query ) return 'Give a query to search for.'
@@ -122,6 +137,6 @@ export const documentToolExtension: ToolExtension = {
122137 . join ( '\n\n' )
123138 . slice ( 0 , MAX_CHARS )
124139 } ,
125- systemHint : ( ) =>
140+ systemHint : ( ) : string =>
126141 'search_documents and read_pages look further into this chat\'s documents when the passages given are not enough.'
127142}
0 commit comments