Skip to content

Commit e6ca3b3

Browse files
authored
feat(knowledge): add connector tools and expand document metadata (#3452)
* feat(knowledge): add connector tools and expand document metadata * fix(knowledge): address PR review feedback on new tools * fix(knowledge): remove unused params from get_document transform
1 parent b93c87c commit e6ca3b3

File tree

10 files changed

+586
-2
lines changed

10 files changed

+586
-2
lines changed

apps/sim/app/api/knowledge/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ export interface DocumentData {
5858
boolean3?: boolean | null
5959
// Connector fields
6060
connectorId?: string | null
61+
sourceUrl?: string | null
62+
externalId?: string | null
6163
}
6264

6365
export interface EmbeddingData {
@@ -287,6 +289,8 @@ export async function checkDocumentWriteAccess(
287289
boolean3: document.boolean3,
288290
// Connector fields
289291
connectorId: document.connectorId,
292+
sourceUrl: document.sourceUrl,
293+
externalId: document.externalId,
290294
})
291295
.from(document)
292296
.where(and(eq(document.id, documentId), isNull(document.deletedAt)))

apps/sim/blocks/blocks/knowledge.ts

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ export const KnowledgeBlock: BlockConfig = {
1010
bestPractices: `
1111
- Clarify which tags are available for the knowledge base to understand whether to use tag filters on a search.
1212
- Use List Documents to enumerate documents before operating on them.
13+
- Use Get Document to retrieve full details including tags, connector metadata, and processing status.
1314
- Use List Chunks to inspect a document's contents before updating or deleting chunks.
15+
- Use List Connectors to see which external sources are syncing documents into the knowledge base.
16+
- Use Get Connector to check sync health and review recent sync logs.
1417
`,
1518
bgColor: '#00B0B0',
1619
icon: PackageSearchIcon,
@@ -24,13 +27,17 @@ export const KnowledgeBlock: BlockConfig = {
2427
options: [
2528
{ label: 'Search', id: 'search' },
2629
{ label: 'List Documents', id: 'list_documents' },
30+
{ label: 'Get Document', id: 'get_document' },
2731
{ label: 'Create Document', id: 'create_document' },
2832
{ label: 'Delete Document', id: 'delete_document' },
2933
{ label: 'List Chunks', id: 'list_chunks' },
3034
{ label: 'Upload Chunk', id: 'upload_chunk' },
3135
{ label: 'Update Chunk', id: 'update_chunk' },
3236
{ label: 'Delete Chunk', id: 'delete_chunk' },
3337
{ label: 'List Tags', id: 'list_tags' },
38+
{ label: 'List Connectors', id: 'list_connectors' },
39+
{ label: 'Get Connector', id: 'get_connector' },
40+
{ label: 'Trigger Sync', id: 'trigger_sync' },
3441
],
3542
value: () => 'search',
3643
},
@@ -125,7 +132,14 @@ export const KnowledgeBlock: BlockConfig = {
125132
mode: 'basic',
126133
condition: {
127134
field: 'operation',
128-
value: ['upload_chunk', 'delete_document', 'list_chunks', 'update_chunk', 'delete_chunk'],
135+
value: [
136+
'get_document',
137+
'upload_chunk',
138+
'delete_document',
139+
'list_chunks',
140+
'update_chunk',
141+
'delete_chunk',
142+
],
129143
},
130144
},
131145
// Document selector — advanced mode (manual ID input)
@@ -139,7 +153,14 @@ export const KnowledgeBlock: BlockConfig = {
139153
mode: 'advanced',
140154
condition: {
141155
field: 'operation',
142-
value: ['upload_chunk', 'delete_document', 'list_chunks', 'update_chunk', 'delete_chunk'],
156+
value: [
157+
'get_document',
158+
'upload_chunk',
159+
'delete_document',
160+
'list_chunks',
161+
'update_chunk',
162+
'delete_chunk',
163+
],
143164
},
144165
},
145166

@@ -208,6 +229,16 @@ export const KnowledgeBlock: BlockConfig = {
208229
condition: { field: 'operation', value: 'update_chunk' },
209230
},
210231

232+
// --- Connector operations ---
233+
{
234+
id: 'connectorId',
235+
title: 'Connector ID',
236+
type: 'short-input',
237+
placeholder: 'Enter connector ID',
238+
required: true,
239+
condition: { field: 'operation', value: ['get_connector', 'trigger_sync'] },
240+
},
241+
211242
// --- List Chunks ---
212243
{
213244
id: 'chunkSearch',
@@ -235,10 +266,14 @@ export const KnowledgeBlock: BlockConfig = {
235266
'knowledge_create_document',
236267
'knowledge_list_tags',
237268
'knowledge_list_documents',
269+
'knowledge_get_document',
238270
'knowledge_delete_document',
239271
'knowledge_list_chunks',
240272
'knowledge_update_chunk',
241273
'knowledge_delete_chunk',
274+
'knowledge_list_connectors',
275+
'knowledge_get_connector',
276+
'knowledge_trigger_sync',
242277
],
243278
config: {
244279
tool: (params) => {
@@ -253,6 +288,8 @@ export const KnowledgeBlock: BlockConfig = {
253288
return 'knowledge_list_tags'
254289
case 'list_documents':
255290
return 'knowledge_list_documents'
291+
case 'get_document':
292+
return 'knowledge_get_document'
256293
case 'delete_document':
257294
return 'knowledge_delete_document'
258295
case 'list_chunks':
@@ -261,6 +298,12 @@ export const KnowledgeBlock: BlockConfig = {
261298
return 'knowledge_update_chunk'
262299
case 'delete_chunk':
263300
return 'knowledge_delete_chunk'
301+
case 'list_connectors':
302+
return 'knowledge_list_connectors'
303+
case 'get_connector':
304+
return 'knowledge_get_connector'
305+
case 'trigger_sync':
306+
return 'knowledge_trigger_sync'
264307
default:
265308
return 'knowledge_search'
266309
}
@@ -273,6 +316,7 @@ export const KnowledgeBlock: BlockConfig = {
273316
params.knowledgeBaseId = knowledgeBaseId
274317

275318
const docOps = [
319+
'get_document',
276320
'upload_chunk',
277321
'delete_document',
278322
'list_chunks',
@@ -296,6 +340,15 @@ export const KnowledgeBlock: BlockConfig = {
296340
params.chunkId = chunkId
297341
}
298342

343+
const connectorOps = ['get_connector', 'trigger_sync']
344+
if (connectorOps.includes(params.operation)) {
345+
const connectorId = params.connectorId ? String(params.connectorId).trim() : ''
346+
if (!connectorId) {
347+
throw new Error(`Connector ID is required for ${params.operation} operation`)
348+
}
349+
params.connectorId = connectorId
350+
}
351+
299352
// Map list_chunks sub-block fields to tool params
300353
if (params.operation === 'list_chunks') {
301354
if (params.chunkSearch) params.search = params.chunkSearch
@@ -329,6 +382,7 @@ export const KnowledgeBlock: BlockConfig = {
329382
documentTags: { type: 'string', description: 'Document tags' },
330383
chunkSearch: { type: 'string', description: 'Search filter for chunks' },
331384
chunkEnabledFilter: { type: 'string', description: 'Filter chunks by enabled status' },
385+
connectorId: { type: 'string', description: 'Connector identifier' },
332386
},
333387
outputs: {
334388
results: { type: 'json', description: 'Search results' },
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import type { KnowledgeGetConnectorResponse } from '@/tools/knowledge/types'
2+
import type { ToolConfig } from '@/tools/types'
3+
4+
export const knowledgeGetConnectorTool: ToolConfig<any, KnowledgeGetConnectorResponse> = {
5+
id: 'knowledge_get_connector',
6+
name: 'Knowledge Get Connector',
7+
description:
8+
'Get detailed connector information including recent sync logs for monitoring sync health',
9+
version: '1.0.0',
10+
11+
params: {
12+
knowledgeBaseId: {
13+
type: 'string',
14+
required: true,
15+
visibility: 'user-or-llm',
16+
description: 'ID of the knowledge base the connector belongs to',
17+
},
18+
connectorId: {
19+
type: 'string',
20+
required: true,
21+
visibility: 'user-or-llm',
22+
description: 'ID of the connector to retrieve',
23+
},
24+
},
25+
26+
request: {
27+
url: (params) =>
28+
`/api/knowledge/${params.knowledgeBaseId}/connectors/${params.connectorId}`,
29+
method: 'GET',
30+
headers: () => ({
31+
'Content-Type': 'application/json',
32+
}),
33+
},
34+
35+
transformResponse: async (response): Promise<KnowledgeGetConnectorResponse> => {
36+
const result = await response.json()
37+
const data = result.data || {}
38+
39+
return {
40+
success: result.success ?? true,
41+
output: {
42+
connector: {
43+
id: data.id,
44+
connectorType: data.connectorType,
45+
status: data.status,
46+
syncIntervalMinutes: data.syncIntervalMinutes,
47+
lastSyncAt: data.lastSyncAt ?? null,
48+
lastSyncError: data.lastSyncError ?? null,
49+
lastSyncDocCount: data.lastSyncDocCount ?? null,
50+
nextSyncAt: data.nextSyncAt ?? null,
51+
consecutiveFailures: data.consecutiveFailures ?? 0,
52+
createdAt: data.createdAt ?? null,
53+
updatedAt: data.updatedAt ?? null,
54+
},
55+
syncLogs: (data.syncLogs || []).map(
56+
(log: {
57+
id: string
58+
status: string
59+
startedAt: string | null
60+
completedAt: string | null
61+
docsAdded: number | null
62+
docsUpdated: number | null
63+
docsDeleted: number | null
64+
docsUnchanged: number | null
65+
errorMessage: string | null
66+
}) => ({
67+
id: log.id,
68+
status: log.status,
69+
startedAt: log.startedAt ?? null,
70+
completedAt: log.completedAt ?? null,
71+
docsAdded: log.docsAdded ?? null,
72+
docsUpdated: log.docsUpdated ?? null,
73+
docsDeleted: log.docsDeleted ?? null,
74+
docsUnchanged: log.docsUnchanged ?? null,
75+
errorMessage: log.errorMessage ?? null,
76+
})
77+
),
78+
},
79+
}
80+
},
81+
82+
outputs: {
83+
connector: {
84+
type: 'object',
85+
description: 'Connector details',
86+
properties: {
87+
id: { type: 'string', description: 'Connector ID' },
88+
connectorType: { type: 'string', description: 'Type of connector' },
89+
status: { type: 'string', description: 'Connector status (active, paused, syncing)' },
90+
syncIntervalMinutes: { type: 'number', description: 'Sync interval in minutes' },
91+
lastSyncAt: { type: 'string', description: 'Timestamp of last sync' },
92+
lastSyncError: { type: 'string', description: 'Error from last sync if failed' },
93+
lastSyncDocCount: { type: 'number', description: 'Docs synced in last sync' },
94+
nextSyncAt: { type: 'string', description: 'Next scheduled sync timestamp' },
95+
consecutiveFailures: { type: 'number', description: 'Consecutive sync failures' },
96+
createdAt: { type: 'string', description: 'Creation timestamp' },
97+
updatedAt: { type: 'string', description: 'Last update timestamp' },
98+
},
99+
},
100+
syncLogs: {
101+
type: 'array',
102+
description: 'Recent sync log entries',
103+
items: {
104+
type: 'object',
105+
properties: {
106+
id: { type: 'string', description: 'Sync log ID' },
107+
status: { type: 'string', description: 'Sync status' },
108+
startedAt: { type: 'string', description: 'Sync start time' },
109+
completedAt: { type: 'string', description: 'Sync completion time' },
110+
docsAdded: { type: 'number', description: 'Documents added' },
111+
docsUpdated: { type: 'number', description: 'Documents updated' },
112+
docsDeleted: { type: 'number', description: 'Documents deleted' },
113+
docsUnchanged: { type: 'number', description: 'Documents unchanged' },
114+
errorMessage: { type: 'string', description: 'Error message if sync failed' },
115+
},
116+
},
117+
},
118+
},
119+
}

0 commit comments

Comments
 (0)