Skip to content

Commit 3790098

Browse files
fix(kb): workspace id required for creation (#3001)
* fix(kb): workspace id required for creation * fix tests
1 parent 3cc9b1a commit 3790098

File tree

6 files changed

+35
-11
lines changed

6 files changed

+35
-11
lines changed

apps/sim/app/api/knowledge/route.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ mockKnowledgeSchemas()
1616
mockDrizzleOrm()
1717
mockConsoleLogger()
1818

19+
vi.mock('@/lib/workspaces/permissions/utils', () => ({
20+
getUserEntityPermissions: vi.fn().mockResolvedValue({ role: 'owner' }),
21+
}))
22+
1923
describe('Knowledge Base API Route', () => {
2024
const mockAuth$ = mockAuth()
2125

@@ -86,6 +90,7 @@ describe('Knowledge Base API Route', () => {
8690
const validKnowledgeBaseData = {
8791
name: 'Test Knowledge Base',
8892
description: 'Test description',
93+
workspaceId: 'test-workspace-id',
8994
chunkingConfig: {
9095
maxSize: 1024,
9196
minSize: 100,
@@ -133,11 +138,25 @@ describe('Knowledge Base API Route', () => {
133138
expect(data.details).toBeDefined()
134139
})
135140

141+
it('should require workspaceId', async () => {
142+
mockAuth$.mockAuthenticatedUser()
143+
144+
const req = createMockRequest('POST', { name: 'Test KB' })
145+
const { POST } = await import('@/app/api/knowledge/route')
146+
const response = await POST(req)
147+
const data = await response.json()
148+
149+
expect(response.status).toBe(400)
150+
expect(data.error).toBe('Invalid request data')
151+
expect(data.details).toBeDefined()
152+
})
153+
136154
it('should validate chunking config constraints', async () => {
137155
mockAuth$.mockAuthenticatedUser()
138156

139157
const invalidData = {
140158
name: 'Test KB',
159+
workspaceId: 'test-workspace-id',
141160
chunkingConfig: {
142161
maxSize: 100, // 100 tokens = 400 characters
143162
minSize: 500, // Invalid: minSize (500 chars) > maxSize (400 chars)
@@ -157,7 +176,7 @@ describe('Knowledge Base API Route', () => {
157176
it('should use default values for optional fields', async () => {
158177
mockAuth$.mockAuthenticatedUser()
159178

160-
const minimalData = { name: 'Test KB' }
179+
const minimalData = { name: 'Test KB', workspaceId: 'test-workspace-id' }
161180
const req = createMockRequest('POST', minimalData)
162181
const { POST } = await import('@/app/api/knowledge/route')
163182
const response = await POST(req)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const logger = createLogger('KnowledgeBaseAPI')
1919
const CreateKnowledgeBaseSchema = z.object({
2020
name: z.string().min(1, 'Name is required'),
2121
description: z.string().optional(),
22-
workspaceId: z.string().optional(),
22+
workspaceId: z.string().min(1, 'Workspace ID is required'),
2323
embeddingModel: z.literal('text-embedding-3-small').default('text-embedding-3-small'),
2424
embeddingDimension: z.literal(1536).default(1536),
2525
chunkingConfig: z

apps/sim/lib/copilot/tools/server/knowledge/knowledge-base.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ export const knowledgeBaseServerTool: BaseServerTool<KnowledgeBaseArgs, Knowledg
3737
}
3838
}
3939

40+
if (!args.workspaceId) {
41+
return {
42+
success: false,
43+
message: 'Workspace ID is required for creating a knowledge base',
44+
}
45+
}
46+
4047
const requestId = crypto.randomUUID().slice(0, 8)
4148
const newKnowledgeBase = await createKnowledgeBase(
4249
{

apps/sim/lib/copilot/tools/shared/schemas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const KnowledgeBaseArgsSchema = z.object({
7979
name: z.string().optional(),
8080
/** Description of the knowledge base (optional for create) */
8181
description: z.string().optional(),
82-
/** Workspace ID to associate with (optional for create/list) */
82+
/** Workspace ID to associate with (required for create, optional for list) */
8383
workspaceId: z.string().optional(),
8484
/** Knowledge base ID (required for get, query) */
8585
knowledgeBaseId: z.string().optional(),

apps/sim/lib/knowledge/service.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,16 @@ export async function createKnowledgeBase(
8686
const kbId = randomUUID()
8787
const now = new Date()
8888

89-
if (data.workspaceId) {
90-
const hasPermission = await getUserEntityPermissions(data.userId, 'workspace', data.workspaceId)
91-
if (hasPermission === null) {
92-
throw new Error('User does not have permission to create knowledge bases in this workspace')
93-
}
89+
const hasPermission = await getUserEntityPermissions(data.userId, 'workspace', data.workspaceId)
90+
if (hasPermission === null) {
91+
throw new Error('User does not have permission to create knowledge bases in this workspace')
9492
}
9593

9694
const newKnowledgeBase = {
9795
id: kbId,
9896
name: data.name,
9997
description: data.description ?? null,
100-
workspaceId: data.workspaceId ?? null,
98+
workspaceId: data.workspaceId,
10199
userId: data.userId,
102100
tokenCount: 0,
103101
embeddingModel: data.embeddingModel,
@@ -122,7 +120,7 @@ export async function createKnowledgeBase(
122120
chunkingConfig: data.chunkingConfig,
123121
createdAt: now,
124122
updatedAt: now,
125-
workspaceId: data.workspaceId ?? null,
123+
workspaceId: data.workspaceId,
126124
docCount: 0,
127125
}
128126
}

apps/sim/lib/knowledge/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export interface KnowledgeBaseWithCounts {
3232
export interface CreateKnowledgeBaseData {
3333
name: string
3434
description?: string
35-
workspaceId?: string
35+
workspaceId: string
3636
embeddingModel: 'text-embedding-3-small'
3737
embeddingDimension: 1536
3838
chunkingConfig: ChunkingConfig

0 commit comments

Comments
 (0)