@lobehub/chat 1.92.1 → 1.92.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/src/database/migrations/0024_add_rbac_tables.sql +49 -0
- package/src/database/migrations/meta/0024_snapshot.json +6192 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/schemas/index.ts +1 -0
- package/src/database/schemas/rbac.ts +82 -0
- package/src/libs/model-runtime/azureOpenai/index.ts +47 -23
@@ -168,6 +168,13 @@
|
|
168
168
|
"when": 1748925630721,
|
169
169
|
"tag": "0023_remove_param_and_doubao",
|
170
170
|
"breakpoints": true
|
171
|
+
},
|
172
|
+
{
|
173
|
+
"idx": 24,
|
174
|
+
"version": "7",
|
175
|
+
"when": 1749301573666,
|
176
|
+
"tag": "0024_add_rbac_tables",
|
177
|
+
"breakpoints": true
|
171
178
|
}
|
172
179
|
],
|
173
180
|
"version": "6"
|
@@ -0,0 +1,82 @@
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
2
|
+
import { boolean, index, integer, pgTable, primaryKey, text, timestamp } from 'drizzle-orm/pg-core';
|
3
|
+
|
4
|
+
import { timestamps } from './_helpers';
|
5
|
+
import { users } from './user';
|
6
|
+
|
7
|
+
// Roles table
|
8
|
+
export const roles = pgTable('rbac_roles', {
|
9
|
+
id: integer('id').primaryKey().generatedByDefaultAsIdentity(),
|
10
|
+
name: text('name').notNull().unique(), // Role name, e.g.: admin, user, guest
|
11
|
+
displayName: text('display_name').notNull(), // Display name
|
12
|
+
description: text('description'), // Role description
|
13
|
+
isSystem: boolean('is_system').default(false).notNull(), // Whether it's a system role
|
14
|
+
isActive: boolean('is_active').default(true).notNull(), // Whether it's active
|
15
|
+
|
16
|
+
...timestamps,
|
17
|
+
});
|
18
|
+
|
19
|
+
export type NewRole = typeof roles.$inferInsert;
|
20
|
+
export type RoleItem = typeof roles.$inferSelect;
|
21
|
+
|
22
|
+
// Permissions table
|
23
|
+
export const permissions = pgTable('rbac_permissions', {
|
24
|
+
id: integer('id').primaryKey().generatedByDefaultAsIdentity(),
|
25
|
+
code: text('code').notNull().unique(), // Permission code, e.g.: chat:create, file:upload
|
26
|
+
name: text('name').notNull(), // Permission name
|
27
|
+
description: text('description'), // Permission description
|
28
|
+
category: text('category').notNull(), // Category it belongs to, e.g.: message, knowledge_base, agent
|
29
|
+
isActive: boolean('is_active').default(true).notNull(), // Whether it's active
|
30
|
+
|
31
|
+
...timestamps,
|
32
|
+
});
|
33
|
+
|
34
|
+
export type NewPermission = typeof permissions.$inferInsert;
|
35
|
+
export type PermissionItem = typeof permissions.$inferSelect;
|
36
|
+
|
37
|
+
// Role-permission association table
|
38
|
+
export const rolePermissions = pgTable(
|
39
|
+
'rbac_role_permissions',
|
40
|
+
{
|
41
|
+
roleId: integer('role_id')
|
42
|
+
.references(() => roles.id, { onDelete: 'cascade' })
|
43
|
+
.notNull(),
|
44
|
+
permissionId: integer('permission_id')
|
45
|
+
.references(() => permissions.id, { onDelete: 'cascade' })
|
46
|
+
.notNull(),
|
47
|
+
|
48
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
49
|
+
},
|
50
|
+
(self) => [
|
51
|
+
primaryKey({ columns: [self.roleId, self.permissionId] }),
|
52
|
+
index('rbac_role_permissions_role_id_idx').on(self.roleId),
|
53
|
+
index('rbac_role_permissions_permission_id_idx').on(self.permissionId),
|
54
|
+
],
|
55
|
+
);
|
56
|
+
|
57
|
+
export type NewRolePermission = typeof rolePermissions.$inferInsert;
|
58
|
+
export type RolePermissionItem = typeof rolePermissions.$inferSelect;
|
59
|
+
|
60
|
+
// User-role association table
|
61
|
+
export const userRoles = pgTable(
|
62
|
+
'rbac_user_roles',
|
63
|
+
{
|
64
|
+
userId: text('user_id')
|
65
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
66
|
+
.notNull(),
|
67
|
+
roleId: integer('role_id')
|
68
|
+
.references(() => roles.id, { onDelete: 'cascade' })
|
69
|
+
.notNull(),
|
70
|
+
|
71
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
72
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }), // Support for temporary roles
|
73
|
+
},
|
74
|
+
(self) => [
|
75
|
+
primaryKey({ columns: [self.userId, self.roleId] }),
|
76
|
+
index('rbac_user_roles_user_id_idx').on(self.userId),
|
77
|
+
index('rbac_user_roles_role_id_idx').on(self.roleId),
|
78
|
+
],
|
79
|
+
);
|
80
|
+
|
81
|
+
export type NewUserRole = typeof userRoles.$inferInsert;
|
82
|
+
export type UserRoleItem = typeof userRoles.$inferSelect;
|
@@ -5,7 +5,14 @@ import { systemToUserModels } from '@/const/models';
|
|
5
5
|
|
6
6
|
import { LobeRuntimeAI } from '../BaseAI';
|
7
7
|
import { AgentRuntimeErrorType } from '../error';
|
8
|
-
import {
|
8
|
+
import {
|
9
|
+
ChatMethodOptions,
|
10
|
+
ChatStreamPayload,
|
11
|
+
Embeddings,
|
12
|
+
EmbeddingsOptions,
|
13
|
+
EmbeddingsPayload,
|
14
|
+
ModelProvider,
|
15
|
+
} from '../types';
|
9
16
|
import { AgentRuntimeError } from '../utils/createError';
|
10
17
|
import { debugStream } from '../utils/debugStream';
|
11
18
|
import { transformResponseToStream } from '../utils/openaiCompatibleFactory';
|
@@ -75,33 +82,50 @@ export class LobeAzureOpenAI implements LobeRuntimeAI {
|
|
75
82
|
});
|
76
83
|
}
|
77
84
|
} catch (e) {
|
78
|
-
|
85
|
+
return this.handleError(e, model);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
async embeddings(payload: EmbeddingsPayload, options?: EmbeddingsOptions): Promise<Embeddings[]> {
|
90
|
+
try {
|
91
|
+
const res = await this.client.embeddings.create(
|
92
|
+
{ ...payload, encoding_format: 'float', user: options?.user },
|
93
|
+
{ headers: options?.headers, signal: options?.signal },
|
94
|
+
);
|
95
|
+
|
96
|
+
return res.data.map((item) => item.embedding);
|
97
|
+
} catch (error) {
|
98
|
+
return this.handleError(error, payload.model);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
protected handleError(e: any, model?: string): never {
|
103
|
+
let error = e as { [key: string]: any; code: string; message: string };
|
79
104
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
105
|
+
if (error.code) {
|
106
|
+
switch (error.code) {
|
107
|
+
case 'DeploymentNotFound': {
|
108
|
+
error = { ...error, deployId: model };
|
85
109
|
}
|
86
|
-
} else {
|
87
|
-
error = {
|
88
|
-
cause: error.cause,
|
89
|
-
message: error.message,
|
90
|
-
name: error.name,
|
91
|
-
} as any;
|
92
110
|
}
|
111
|
+
} else {
|
112
|
+
error = {
|
113
|
+
cause: error.cause,
|
114
|
+
message: error.message,
|
115
|
+
name: error.name,
|
116
|
+
} as any;
|
117
|
+
}
|
93
118
|
|
94
|
-
|
95
|
-
|
96
|
-
|
119
|
+
const errorType = error.code
|
120
|
+
? AgentRuntimeErrorType.ProviderBizError
|
121
|
+
: AgentRuntimeErrorType.AgentRuntimeError;
|
97
122
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
}
|
123
|
+
throw AgentRuntimeError.chat({
|
124
|
+
endpoint: this.maskSensitiveUrl(this.baseURL),
|
125
|
+
error,
|
126
|
+
errorType,
|
127
|
+
provider: ModelProvider.Azure,
|
128
|
+
});
|
105
129
|
}
|
106
130
|
|
107
131
|
// Convert object keys to camel case, copy from `@azure/openai` in `node_modules/@azure/openai/dist/index.cjs`
|