regen migrations, ack PR comments

This commit is contained in:
waleed
2026-02-16 23:51:33 -08:00
parent b0d9f4e8b5
commit f5640b2919
9 changed files with 71 additions and 47 deletions

View File

@@ -117,11 +117,12 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
}
let finalSourceConfig: Record<string, unknown> = sourceConfig
const tagSlotMapping: Record<string, string> = {}
if (connectorConfig.tagDefinitions?.length) {
const disabledIds = new Set((sourceConfig.disabledTagIds as string[] | undefined) ?? [])
const enabledDefs = connectorConfig.tagDefinitions.filter((td) => !disabledIds.has(td.id))
const tagSlotMapping: Record<string, string> = {}
const skippedTags: string[] = []
for (const td of enabledDefs) {
const slot = await getNextAvailableSlot(knowledgeBaseId, td.fieldType)
@@ -130,15 +131,6 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
logger.warn(`[${requestId}] No available ${td.fieldType} slots for "${td.displayName}"`)
continue
}
await createTagDefinition(
{
knowledgeBaseId,
tagSlot: slot,
displayName: td.displayName,
fieldType: td.fieldType,
},
requestId
)
tagSlotMapping[td.id] = slot
}
@@ -157,17 +149,33 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
const nextSyncAt =
syncIntervalMinutes > 0 ? new Date(now.getTime() + syncIntervalMinutes * 60 * 1000) : null
await db.insert(knowledgeConnector).values({
id: connectorId,
knowledgeBaseId,
connectorType,
credentialId,
sourceConfig: finalSourceConfig,
syncIntervalMinutes,
status: 'active',
nextSyncAt,
createdAt: now,
updatedAt: now,
await db.transaction(async (tx) => {
for (const [semanticId, slot] of Object.entries(tagSlotMapping)) {
const td = connectorConfig.tagDefinitions!.find((d) => d.id === semanticId)!
await createTagDefinition(
{
knowledgeBaseId,
tagSlot: slot,
displayName: td.displayName,
fieldType: td.fieldType,
},
requestId,
tx
)
}
await tx.insert(knowledgeConnector).values({
id: connectorId,
knowledgeBaseId,
connectorType,
credentialId,
sourceConfig: finalSourceConfig,
syncIntervalMinutes,
status: 'active',
nextSyncAt,
createdAt: now,
updatedAt: now,
})
})
logger.info(`[${requestId}] Created connector ${connectorId} for KB ${knowledgeBaseId}`)

View File

@@ -745,6 +745,7 @@ export function Document({
setEnabledFilter('all')
setIsFilterPopoverOpen(false)
setSelectedChunks(new Set())
goToPage(1)
}}
>
All
@@ -755,6 +756,7 @@ export function Document({
setEnabledFilter('enabled')
setIsFilterPopoverOpen(false)
setSelectedChunks(new Set())
goToPage(1)
}}
>
Enabled
@@ -765,6 +767,7 @@ export function Document({
setEnabledFilter('disabled')
setIsFilterPopoverOpen(false)
setSelectedChunks(new Set())
goToPage(1)
}}
>
Disabled

View File

@@ -8,13 +8,6 @@ const logger = createLogger('JiraConnector')
const PAGE_SIZE = 50
/**
* Escapes a value for use inside JQL double-quoted strings.
*/
function escapeJql(value: string): string {
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')
}
/**
* Computes a SHA-256 hash of the given content.
*/
@@ -147,9 +140,9 @@ export const jiraConnector: ConnectorConfig = {
const cloudId = await getJiraCloudId(domain, accessToken)
let jql = `project = "${escapeJql(projectKey)}" ORDER BY updated DESC`
let jql = `project = ${projectKey} ORDER BY updated DESC`
if (jqlFilter.trim()) {
jql = `project = "${escapeJql(projectKey)}" AND (${jqlFilter.trim()}) ORDER BY updated DESC`
jql = `project = ${projectKey} AND (${jqlFilter.trim()}) ORDER BY updated DESC`
}
const startAt = cursor ? Number(cursor) : 0
@@ -251,19 +244,13 @@ export const jiraConnector: ConnectorConfig = {
return { valid: false, error: 'Max issues must be a positive number' }
}
const jql = sourceConfig.jql as string | undefined
if (jql?.trim()) {
if (/\b(delete|drop|truncate|insert|update|alter|create|grant|revoke)\b/i.test(jql)) {
return { valid: false, error: 'Invalid JQL filter' }
}
}
const jqlFilter = (sourceConfig.jql as string | undefined)?.trim() || ''
try {
const cloudId = await getJiraCloudId(domain, accessToken)
// Verify the project exists by running a minimal search
const params = new URLSearchParams()
params.append('jql', `project = "${escapeJql(projectKey)}"`)
params.append('jql', `project = ${projectKey}`)
params.append('maxResults', '0')
const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/search?${params.toString()}`
@@ -287,6 +274,29 @@ export const jiraConnector: ConnectorConfig = {
return { valid: false, error: `Failed to validate: ${response.status} - ${errorText}` }
}
if (jqlFilter) {
const filterParams = new URLSearchParams()
filterParams.append('jql', `project = ${projectKey} AND (${jqlFilter})`)
filterParams.append('maxResults', '0')
const filterUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/search?${filterParams.toString()}`
const filterResponse = await fetchWithRetry(
filterUrl,
{
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${accessToken}`,
},
},
VALIDATE_RETRY_OPTIONS
)
if (!filterResponse.ok) {
return { valid: false, error: 'Invalid JQL filter. Check syntax and field names.' }
}
}
return { valid: true }
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to validate configuration'

View File

@@ -275,7 +275,7 @@ export async function executeSync(
}
}
if (options?.fullSync || connector.syncMode === 'incremental') {
if (options?.fullSync || connector.syncMode === 'full') {
for (const existing of existingDocs) {
if (existing.externalId && !seenExternalIds.has(existing.externalId)) {
await db

View File

@@ -3,6 +3,7 @@ import { db } from '@sim/db'
import { document, embedding, knowledgeBaseTagDefinitions } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { and, eq, isNotNull, isNull, sql } from 'drizzle-orm'
import type { DbOrTx } from '@/lib/db/types'
import { getSlotsForFieldType, SUPPORTED_FIELD_TYPES } from '@/lib/knowledge/constants'
import type { BulkTagDefinitionsData, DocumentTagDefinition } from '@/lib/knowledge/tags/types'
import type {
@@ -485,8 +486,10 @@ export async function deleteTagDefinition(
*/
export async function createTagDefinition(
data: CreateTagDefinitionData,
requestId: string
requestId: string,
txDb?: DbOrTx
): Promise<TagDefinition> {
const dbInstance = txDb ?? db
const tagDefinitionId = randomUUID()
const now = new Date()
@@ -500,7 +503,7 @@ export async function createTagDefinition(
updatedAt: now,
}
await db.insert(knowledgeBaseTagDefinitions).values(newDefinition)
await dbInstance.insert(knowledgeBaseTagDefinitions).values(newDefinition)
logger.info(
`[${requestId}] Created tag definition: ${data.displayName} -> ${data.tagSlot} in KB ${data.knowledgeBaseId}`