@meshagent/meshagent 0.36.3 → 0.37.1
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 +16 -0
- package/dist/browser/agent-client.d.ts +2 -10
- package/dist/browser/agent-client.js +2 -30
- package/dist/browser/agent.d.ts +22 -22
- package/dist/browser/agent.js +36 -16
- package/dist/browser/containers-client.d.ts +7 -19
- package/dist/browser/containers-client.js +27 -21
- package/dist/browser/data-types.d.ts +12 -0
- package/dist/browser/data-types.js +39 -1
- package/dist/browser/database-client.d.ts +134 -47
- package/dist/browser/database-client.js +359 -133
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.js +1 -0
- package/dist/browser/meshagent-client.js +12 -1
- package/dist/browser/participant-token.d.ts +189 -22
- package/dist/browser/participant-token.js +1001 -189
- package/dist/browser/room-client.d.ts +1 -1
- package/dist/browser/services-client.d.ts +1 -1
- package/dist/browser/version.d.ts +1 -0
- package/dist/browser/version.js +4 -0
- package/dist/esm/agent-client.d.ts +2 -10
- package/dist/esm/agent-client.js +1 -28
- package/dist/esm/agent.d.ts +22 -22
- package/dist/esm/agent.js +33 -14
- package/dist/esm/containers-client.d.ts +7 -19
- package/dist/esm/containers-client.js +27 -21
- package/dist/esm/data-types.d.ts +12 -0
- package/dist/esm/data-types.js +36 -0
- package/dist/esm/database-client.d.ts +134 -47
- package/dist/esm/database-client.js +352 -132
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/meshagent-client.js +12 -1
- package/dist/esm/participant-token.d.ts +189 -22
- package/dist/esm/participant-token.js +992 -188
- package/dist/esm/room-client.d.ts +1 -1
- package/dist/esm/services-client.d.ts +1 -1
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +1 -0
- package/dist/node/agent-client.d.ts +2 -10
- package/dist/node/agent-client.js +2 -30
- package/dist/node/agent.d.ts +22 -22
- package/dist/node/agent.js +36 -16
- package/dist/node/containers-client.d.ts +7 -19
- package/dist/node/containers-client.js +27 -21
- package/dist/node/data-types.d.ts +12 -0
- package/dist/node/data-types.js +39 -1
- package/dist/node/database-client.d.ts +134 -47
- package/dist/node/database-client.js +359 -133
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/meshagent-client.js +12 -1
- package/dist/node/participant-token.d.ts +189 -22
- package/dist/node/participant-token.js +1001 -189
- package/dist/node/room-client.d.ts +1 -1
- package/dist/node/services-client.d.ts +1 -1
- package/dist/node/version.d.ts +1 -0
- package/dist/node/version.js +4 -0
- package/package.json +1 -1
|
@@ -1,19 +1,87 @@
|
|
|
1
1
|
import { decodeJwt, jwtVerify, SignJWT } from "jose";
|
|
2
2
|
import { parseApiKey } from "./api_keys";
|
|
3
|
+
import { __version__ } from "./version";
|
|
4
|
+
function matchesGrantPattern(patterns, value, allowIfUnset) {
|
|
5
|
+
if (!patterns) {
|
|
6
|
+
return allowIfUnset;
|
|
7
|
+
}
|
|
8
|
+
return patterns.some((pattern) => value === pattern
|
|
9
|
+
|| (pattern.endsWith("*")
|
|
10
|
+
&& value.startsWith(pattern.slice(0, -1))));
|
|
11
|
+
}
|
|
3
12
|
function getEnvValue(name) {
|
|
4
13
|
if (typeof process === "undefined") {
|
|
5
14
|
return undefined;
|
|
6
15
|
}
|
|
7
16
|
return process.env?.[name];
|
|
8
17
|
}
|
|
18
|
+
function normalizeNamespace(namespace) {
|
|
19
|
+
return namespace ?? [];
|
|
20
|
+
}
|
|
21
|
+
function namespacesEqual(left, right) {
|
|
22
|
+
const normalizedLeft = normalizeNamespace(left);
|
|
23
|
+
const normalizedRight = normalizeNamespace(right);
|
|
24
|
+
if (normalizedLeft.length !== normalizedRight.length) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return normalizedLeft.every((value, index) => value === normalizedRight[index]);
|
|
28
|
+
}
|
|
29
|
+
function isRecord(value) {
|
|
30
|
+
return typeof value === "object" && value !== null;
|
|
31
|
+
}
|
|
32
|
+
function asStringList(value) {
|
|
33
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string")
|
|
34
|
+
? value
|
|
35
|
+
: undefined;
|
|
36
|
+
}
|
|
9
37
|
export class AgentsGrant {
|
|
10
|
-
constructor({ registerAgent, registerPublicToolkit, registerPrivateToolkit, call, useAgents, useTools, } = {}) {
|
|
38
|
+
constructor({ registerAgent, registerPublicToolkit, registerPrivateToolkit, call, useAgents, useTools, allowedToolkits, } = {}) {
|
|
11
39
|
this.registerAgent = registerAgent ?? true;
|
|
12
40
|
this.registerPublicToolkit = registerPublicToolkit ?? true;
|
|
13
41
|
this.registerPrivateToolkit = registerPrivateToolkit ?? true;
|
|
14
42
|
this.call = call ?? true;
|
|
15
43
|
this.useAgents = useAgents ?? true;
|
|
16
44
|
this.useTools = useTools ?? true;
|
|
45
|
+
this.allowedToolkits = allowedToolkits;
|
|
46
|
+
}
|
|
47
|
+
toJSON() {
|
|
48
|
+
const json = {};
|
|
49
|
+
if (this.registerAgent !== true) {
|
|
50
|
+
json["register_agent"] = this.registerAgent;
|
|
51
|
+
}
|
|
52
|
+
if (this.registerPublicToolkit !== true) {
|
|
53
|
+
json["register_public_toolkit"] = this.registerPublicToolkit;
|
|
54
|
+
}
|
|
55
|
+
if (this.registerPrivateToolkit !== true) {
|
|
56
|
+
json["register_private_toolkit"] = this.registerPrivateToolkit;
|
|
57
|
+
}
|
|
58
|
+
if (this.call !== true) {
|
|
59
|
+
json["call"] = this.call;
|
|
60
|
+
}
|
|
61
|
+
if (this.useAgents !== true) {
|
|
62
|
+
json["use_agents"] = this.useAgents;
|
|
63
|
+
}
|
|
64
|
+
if (this.useTools !== true) {
|
|
65
|
+
json["use_tools"] = this.useTools;
|
|
66
|
+
}
|
|
67
|
+
if (this.allowedToolkits !== undefined) {
|
|
68
|
+
json["allowed_toolkits"] = this.allowedToolkits;
|
|
69
|
+
}
|
|
70
|
+
return json;
|
|
71
|
+
}
|
|
72
|
+
static fromJSON(obj) {
|
|
73
|
+
if (!isRecord(obj)) {
|
|
74
|
+
return new AgentsGrant();
|
|
75
|
+
}
|
|
76
|
+
return new AgentsGrant({
|
|
77
|
+
registerAgent: obj.register_agent ?? obj.registerAgent,
|
|
78
|
+
registerPublicToolkit: obj.register_public_toolkit ?? obj.registerPublicToolkit,
|
|
79
|
+
registerPrivateToolkit: obj.register_private_toolkit ?? obj.registerPrivateToolkit,
|
|
80
|
+
call: obj.call,
|
|
81
|
+
useAgents: obj.use_agents ?? obj.useAgents,
|
|
82
|
+
useTools: obj.use_tools ?? obj.useTools,
|
|
83
|
+
allowedToolkits: asStringList(obj.allowed_toolkits ?? obj.allowedToolkits),
|
|
84
|
+
});
|
|
17
85
|
}
|
|
18
86
|
}
|
|
19
87
|
export class LivekitGrant {
|
|
@@ -23,61 +91,367 @@ export class LivekitGrant {
|
|
|
23
91
|
canJoinBreakoutRoom(name) {
|
|
24
92
|
return !this.breakoutRooms || this.breakoutRooms.includes(name);
|
|
25
93
|
}
|
|
94
|
+
toJSON() {
|
|
95
|
+
const json = {};
|
|
96
|
+
if (this.breakoutRooms !== undefined) {
|
|
97
|
+
json["breakout_rooms"] = this.breakoutRooms;
|
|
98
|
+
}
|
|
99
|
+
return json;
|
|
100
|
+
}
|
|
101
|
+
static fromJSON(obj) {
|
|
102
|
+
if (!isRecord(obj)) {
|
|
103
|
+
return new LivekitGrant();
|
|
104
|
+
}
|
|
105
|
+
return new LivekitGrant({
|
|
106
|
+
breakoutRooms: asStringList(obj.breakout_rooms ?? obj.breakoutRooms),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
26
109
|
}
|
|
27
110
|
export class QueuesGrant {
|
|
28
|
-
constructor({ send, receive, list } = {}) {
|
|
29
|
-
this.list = true;
|
|
111
|
+
constructor({ send, receive, list, } = {}) {
|
|
30
112
|
this.send = send;
|
|
31
113
|
this.receive = receive;
|
|
32
114
|
this.list = list ?? true;
|
|
33
115
|
}
|
|
34
|
-
canSend(
|
|
35
|
-
return !this.send || this.send.includes(
|
|
116
|
+
canSend(queue) {
|
|
117
|
+
return !this.send || this.send.includes(queue);
|
|
36
118
|
}
|
|
37
|
-
canReceive(
|
|
38
|
-
return !this.receive || this.receive.includes(
|
|
119
|
+
canReceive(queue) {
|
|
120
|
+
return !this.receive || this.receive.includes(queue);
|
|
121
|
+
}
|
|
122
|
+
toJSON() {
|
|
123
|
+
const json = {};
|
|
124
|
+
if (this.send !== undefined) {
|
|
125
|
+
json["send"] = this.send;
|
|
126
|
+
}
|
|
127
|
+
if (this.receive !== undefined) {
|
|
128
|
+
json["receive"] = this.receive;
|
|
129
|
+
}
|
|
130
|
+
if (this.list !== true) {
|
|
131
|
+
json["list"] = this.list;
|
|
132
|
+
}
|
|
133
|
+
return json;
|
|
134
|
+
}
|
|
135
|
+
static fromJSON(obj) {
|
|
136
|
+
if (!isRecord(obj)) {
|
|
137
|
+
return new QueuesGrant();
|
|
138
|
+
}
|
|
139
|
+
return new QueuesGrant({
|
|
140
|
+
send: asStringList(obj.send),
|
|
141
|
+
receive: asStringList(obj.receive),
|
|
142
|
+
list: obj.list,
|
|
143
|
+
});
|
|
39
144
|
}
|
|
40
145
|
}
|
|
41
146
|
export class MessagingGrant {
|
|
42
|
-
constructor({ broadcast, list, send } = {}) {
|
|
147
|
+
constructor({ broadcast, list, send, } = {}) {
|
|
43
148
|
this.broadcast = broadcast ?? true;
|
|
44
149
|
this.list = list ?? true;
|
|
45
150
|
this.send = send ?? true;
|
|
46
151
|
}
|
|
152
|
+
toJSON() {
|
|
153
|
+
const json = {};
|
|
154
|
+
if (this.broadcast !== true) {
|
|
155
|
+
json["broadcast"] = this.broadcast;
|
|
156
|
+
}
|
|
157
|
+
if (this.list !== true) {
|
|
158
|
+
json["list"] = this.list;
|
|
159
|
+
}
|
|
160
|
+
if (this.send !== true) {
|
|
161
|
+
json["send"] = this.send;
|
|
162
|
+
}
|
|
163
|
+
return json;
|
|
164
|
+
}
|
|
165
|
+
static fromJSON(obj) {
|
|
166
|
+
if (!isRecord(obj)) {
|
|
167
|
+
return new MessagingGrant();
|
|
168
|
+
}
|
|
169
|
+
return new MessagingGrant({
|
|
170
|
+
broadcast: obj.broadcast,
|
|
171
|
+
list: obj.list,
|
|
172
|
+
send: obj.send,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
47
175
|
}
|
|
48
176
|
export class TableGrant {
|
|
49
|
-
constructor({ name, write, read, alter }) {
|
|
50
|
-
this.write = false;
|
|
51
|
-
this.read = true;
|
|
52
|
-
this.alter = false;
|
|
177
|
+
constructor({ name, namespace, write, read, alter, }) {
|
|
53
178
|
this.name = name;
|
|
179
|
+
this.namespace = namespace;
|
|
54
180
|
this.write = write ?? false;
|
|
55
181
|
this.read = read ?? true;
|
|
56
182
|
this.alter = alter ?? false;
|
|
57
183
|
}
|
|
184
|
+
toJSON() {
|
|
185
|
+
const json = {
|
|
186
|
+
name: this.name,
|
|
187
|
+
};
|
|
188
|
+
if (this.namespace !== undefined) {
|
|
189
|
+
json["namespace"] = this.namespace;
|
|
190
|
+
}
|
|
191
|
+
if (this.write !== false) {
|
|
192
|
+
json["write"] = this.write;
|
|
193
|
+
}
|
|
194
|
+
if (this.read !== true) {
|
|
195
|
+
json["read"] = this.read;
|
|
196
|
+
}
|
|
197
|
+
if (this.alter !== false) {
|
|
198
|
+
json["alter"] = this.alter;
|
|
199
|
+
}
|
|
200
|
+
return json;
|
|
201
|
+
}
|
|
202
|
+
static fromJSON(obj) {
|
|
203
|
+
if (!isRecord(obj) || typeof obj.name !== "string") {
|
|
204
|
+
throw new Error("TableGrant requires a name");
|
|
205
|
+
}
|
|
206
|
+
return new TableGrant({
|
|
207
|
+
name: obj.name,
|
|
208
|
+
namespace: asStringList(obj.namespace),
|
|
209
|
+
write: obj.write,
|
|
210
|
+
read: obj.read,
|
|
211
|
+
alter: obj.alter,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
58
214
|
}
|
|
59
215
|
export class DatabaseGrant {
|
|
60
|
-
constructor({ tables, listTables } = {}) {
|
|
61
|
-
this.listTables = true;
|
|
216
|
+
constructor({ tables, listTables, } = {}) {
|
|
62
217
|
this.tables = tables;
|
|
63
218
|
this.listTables = listTables ?? true;
|
|
64
219
|
}
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
return
|
|
68
|
-
|
|
220
|
+
matchingTables(table, namespace) {
|
|
221
|
+
if (this.tables === undefined) {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
return this.tables.filter((tableGrant) => {
|
|
225
|
+
if (tableGrant.name !== table) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
if (tableGrant.namespace === undefined) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
return namespacesEqual(tableGrant.namespace, namespace);
|
|
232
|
+
});
|
|
69
233
|
}
|
|
70
|
-
canWrite(table) {
|
|
71
|
-
|
|
72
|
-
|
|
234
|
+
canWrite(table, namespace) {
|
|
235
|
+
if (this.tables === undefined) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
const matches = this.matchingTables(table, namespace);
|
|
239
|
+
if (matches.length === 0) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return matches.some((tableGrant) => tableGrant.write);
|
|
73
243
|
}
|
|
74
|
-
canRead(table) {
|
|
75
|
-
|
|
76
|
-
|
|
244
|
+
canRead(table, namespace) {
|
|
245
|
+
if (this.tables === undefined) {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
const matches = this.matchingTables(table, namespace);
|
|
249
|
+
if (matches.length === 0) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
return matches.some((tableGrant) => tableGrant.read);
|
|
77
253
|
}
|
|
78
|
-
canAlter(table) {
|
|
79
|
-
|
|
80
|
-
|
|
254
|
+
canAlter(table, namespace) {
|
|
255
|
+
if (this.tables === undefined) {
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
const matches = this.matchingTables(table, namespace);
|
|
259
|
+
if (matches.length === 0) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
return matches.some((tableGrant) => tableGrant.alter);
|
|
263
|
+
}
|
|
264
|
+
canAccess(table, namespace) {
|
|
265
|
+
return (this.canRead(table, namespace)
|
|
266
|
+
|| this.canWrite(table, namespace)
|
|
267
|
+
|| this.canAlter(table, namespace));
|
|
268
|
+
}
|
|
269
|
+
toJSON() {
|
|
270
|
+
const json = {};
|
|
271
|
+
if (this.tables !== undefined) {
|
|
272
|
+
json["tables"] = this.tables.map((tableGrant) => tableGrant.toJSON());
|
|
273
|
+
}
|
|
274
|
+
if (this.listTables !== true) {
|
|
275
|
+
json["list_tables"] = this.listTables;
|
|
276
|
+
}
|
|
277
|
+
return json;
|
|
278
|
+
}
|
|
279
|
+
static fromJSON(obj) {
|
|
280
|
+
if (!isRecord(obj)) {
|
|
281
|
+
return new DatabaseGrant();
|
|
282
|
+
}
|
|
283
|
+
return new DatabaseGrant({
|
|
284
|
+
tables: Array.isArray(obj.tables)
|
|
285
|
+
? obj.tables.map((tableGrant) => TableGrant.fromJSON(tableGrant))
|
|
286
|
+
: undefined,
|
|
287
|
+
listTables: obj.list_tables ?? obj.listTables,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
export class MemoryPermissions {
|
|
292
|
+
constructor({ create, drop, inspect, query, upsert, ingest, recall, optimize, } = {}) {
|
|
293
|
+
this.create = create ?? true;
|
|
294
|
+
this.drop = drop ?? true;
|
|
295
|
+
this.inspect = inspect ?? true;
|
|
296
|
+
this.query = query ?? true;
|
|
297
|
+
this.upsert = upsert ?? true;
|
|
298
|
+
this.ingest = ingest ?? true;
|
|
299
|
+
this.recall = recall ?? true;
|
|
300
|
+
this.optimize = optimize ?? true;
|
|
301
|
+
}
|
|
302
|
+
toJSON() {
|
|
303
|
+
const json = {};
|
|
304
|
+
if (this.create !== true) {
|
|
305
|
+
json["create"] = this.create;
|
|
306
|
+
}
|
|
307
|
+
if (this.drop !== true) {
|
|
308
|
+
json["drop"] = this.drop;
|
|
309
|
+
}
|
|
310
|
+
if (this.inspect !== true) {
|
|
311
|
+
json["inspect"] = this.inspect;
|
|
312
|
+
}
|
|
313
|
+
if (this.query !== true) {
|
|
314
|
+
json["query"] = this.query;
|
|
315
|
+
}
|
|
316
|
+
if (this.upsert !== true) {
|
|
317
|
+
json["upsert"] = this.upsert;
|
|
318
|
+
}
|
|
319
|
+
if (this.ingest !== true) {
|
|
320
|
+
json["ingest"] = this.ingest;
|
|
321
|
+
}
|
|
322
|
+
if (this.recall !== true) {
|
|
323
|
+
json["recall"] = this.recall;
|
|
324
|
+
}
|
|
325
|
+
if (this.optimize !== true) {
|
|
326
|
+
json["optimize"] = this.optimize;
|
|
327
|
+
}
|
|
328
|
+
return json;
|
|
329
|
+
}
|
|
330
|
+
static fromJSON(obj) {
|
|
331
|
+
if (!isRecord(obj)) {
|
|
332
|
+
return new MemoryPermissions();
|
|
333
|
+
}
|
|
334
|
+
return new MemoryPermissions({
|
|
335
|
+
create: obj.create,
|
|
336
|
+
drop: obj.drop,
|
|
337
|
+
inspect: obj.inspect,
|
|
338
|
+
query: obj.query,
|
|
339
|
+
upsert: obj.upsert,
|
|
340
|
+
ingest: obj.ingest,
|
|
341
|
+
recall: obj.recall,
|
|
342
|
+
optimize: obj.optimize,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
export class MemoryEntryGrant {
|
|
347
|
+
constructor({ name, namespace, permissions, }) {
|
|
348
|
+
this.name = name;
|
|
349
|
+
this.namespace = namespace;
|
|
350
|
+
this.permissions = permissions ?? new MemoryPermissions();
|
|
351
|
+
}
|
|
352
|
+
toJSON() {
|
|
353
|
+
const json = {
|
|
354
|
+
name: this.name,
|
|
355
|
+
};
|
|
356
|
+
if (this.namespace !== undefined) {
|
|
357
|
+
json["namespace"] = this.namespace;
|
|
358
|
+
}
|
|
359
|
+
json["permissions"] = this.permissions.toJSON();
|
|
360
|
+
return json;
|
|
361
|
+
}
|
|
362
|
+
static fromJSON(obj) {
|
|
363
|
+
if (!isRecord(obj) || typeof obj.name !== "string") {
|
|
364
|
+
throw new Error("MemoryEntryGrant requires a name");
|
|
365
|
+
}
|
|
366
|
+
return new MemoryEntryGrant({
|
|
367
|
+
name: obj.name,
|
|
368
|
+
namespace: asStringList(obj.namespace),
|
|
369
|
+
permissions: MemoryPermissions.fromJSON(obj.permissions),
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
export class MemoryGrant {
|
|
374
|
+
constructor({ list, memories, } = {}) {
|
|
375
|
+
this.list = list ?? true;
|
|
376
|
+
this.memories = memories;
|
|
377
|
+
}
|
|
378
|
+
matchingMemories(name, namespace) {
|
|
379
|
+
if (this.memories === undefined) {
|
|
380
|
+
return [];
|
|
381
|
+
}
|
|
382
|
+
return this.memories.filter((memoryGrant) => {
|
|
383
|
+
if (memoryGrant.name !== name) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
if (memoryGrant.namespace === undefined) {
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
return namespacesEqual(memoryGrant.namespace, namespace);
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
can(name, namespace, permission) {
|
|
393
|
+
if (this.memories === undefined) {
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
const matches = this.matchingMemories(name, namespace);
|
|
397
|
+
if (matches.length === 0) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
return matches.some((memoryGrant) => memoryGrant.permissions[permission]);
|
|
401
|
+
}
|
|
402
|
+
canCreate(name, namespace) {
|
|
403
|
+
return this.can(name, namespace, "create");
|
|
404
|
+
}
|
|
405
|
+
canDrop(name, namespace) {
|
|
406
|
+
return this.can(name, namespace, "drop");
|
|
407
|
+
}
|
|
408
|
+
canInspect(name, namespace) {
|
|
409
|
+
return this.can(name, namespace, "inspect");
|
|
410
|
+
}
|
|
411
|
+
canQuery(name, namespace) {
|
|
412
|
+
return this.can(name, namespace, "query");
|
|
413
|
+
}
|
|
414
|
+
canUpsert(name, namespace) {
|
|
415
|
+
return this.can(name, namespace, "upsert");
|
|
416
|
+
}
|
|
417
|
+
canIngest(name, namespace) {
|
|
418
|
+
return this.can(name, namespace, "ingest");
|
|
419
|
+
}
|
|
420
|
+
canRecall(name, namespace) {
|
|
421
|
+
return this.can(name, namespace, "recall");
|
|
422
|
+
}
|
|
423
|
+
canOptimize(name, namespace) {
|
|
424
|
+
return this.can(name, namespace, "optimize");
|
|
425
|
+
}
|
|
426
|
+
canAccessExisting(name, namespace) {
|
|
427
|
+
return (this.canDrop(name, namespace)
|
|
428
|
+
|| this.canInspect(name, namespace)
|
|
429
|
+
|| this.canQuery(name, namespace)
|
|
430
|
+
|| this.canUpsert(name, namespace)
|
|
431
|
+
|| this.canIngest(name, namespace)
|
|
432
|
+
|| this.canRecall(name, namespace)
|
|
433
|
+
|| this.canOptimize(name, namespace));
|
|
434
|
+
}
|
|
435
|
+
toJSON() {
|
|
436
|
+
const json = {};
|
|
437
|
+
if (this.list !== true) {
|
|
438
|
+
json["list"] = this.list;
|
|
439
|
+
}
|
|
440
|
+
if (this.memories !== undefined) {
|
|
441
|
+
json["memories"] = this.memories.map((memoryGrant) => memoryGrant.toJSON());
|
|
442
|
+
}
|
|
443
|
+
return json;
|
|
444
|
+
}
|
|
445
|
+
static fromJSON(obj) {
|
|
446
|
+
if (!isRecord(obj)) {
|
|
447
|
+
return new MemoryGrant();
|
|
448
|
+
}
|
|
449
|
+
return new MemoryGrant({
|
|
450
|
+
list: obj.list,
|
|
451
|
+
memories: Array.isArray(obj.memories)
|
|
452
|
+
? obj.memories.map((memoryGrant) => MemoryEntryGrant.fromJSON(memoryGrant))
|
|
453
|
+
: undefined,
|
|
454
|
+
});
|
|
81
455
|
}
|
|
82
456
|
}
|
|
83
457
|
export class SyncPathGrant {
|
|
@@ -85,26 +459,67 @@ export class SyncPathGrant {
|
|
|
85
459
|
this.path = path;
|
|
86
460
|
this.readOnly = readOnly ?? false;
|
|
87
461
|
}
|
|
462
|
+
toJSON() {
|
|
463
|
+
const json = {
|
|
464
|
+
path: this.path,
|
|
465
|
+
};
|
|
466
|
+
if (this.readOnly !== false) {
|
|
467
|
+
json["read_only"] = this.readOnly;
|
|
468
|
+
}
|
|
469
|
+
return json;
|
|
470
|
+
}
|
|
471
|
+
static fromJSON(obj) {
|
|
472
|
+
if (!isRecord(obj) || typeof obj.path !== "string") {
|
|
473
|
+
throw new Error("SyncPathGrant requires a path");
|
|
474
|
+
}
|
|
475
|
+
return new SyncPathGrant({
|
|
476
|
+
path: obj.path,
|
|
477
|
+
readOnly: obj.read_only ?? obj.readOnly,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
88
480
|
}
|
|
89
481
|
export class SyncGrant {
|
|
90
482
|
constructor({ paths } = {}) {
|
|
91
483
|
this.paths = paths;
|
|
92
484
|
}
|
|
93
|
-
matches(
|
|
94
|
-
return
|
|
485
|
+
matches(pathGrant, path) {
|
|
486
|
+
return pathGrant.path === path
|
|
487
|
+
|| (pathGrant.path.endsWith("*")
|
|
488
|
+
&& path.startsWith(pathGrant.path.slice(0, -1)));
|
|
95
489
|
}
|
|
96
490
|
canRead(path) {
|
|
97
|
-
if (this.paths) {
|
|
98
|
-
return
|
|
491
|
+
if (this.paths === undefined) {
|
|
492
|
+
return true;
|
|
99
493
|
}
|
|
100
|
-
return
|
|
494
|
+
return this.paths.some((pathGrant) => this.matches(pathGrant, path));
|
|
101
495
|
}
|
|
102
496
|
canWrite(path) {
|
|
103
|
-
if (this.paths) {
|
|
104
|
-
|
|
105
|
-
return p ? !p.readOnly : false;
|
|
497
|
+
if (this.paths === undefined) {
|
|
498
|
+
return true;
|
|
106
499
|
}
|
|
107
|
-
|
|
500
|
+
for (const pathGrant of this.paths) {
|
|
501
|
+
if (this.matches(pathGrant, path)) {
|
|
502
|
+
return !pathGrant.readOnly;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
toJSON() {
|
|
508
|
+
const json = {};
|
|
509
|
+
if (this.paths !== undefined) {
|
|
510
|
+
json["paths"] = this.paths.map((pathGrant) => pathGrant.toJSON());
|
|
511
|
+
}
|
|
512
|
+
return json;
|
|
513
|
+
}
|
|
514
|
+
static fromJSON(obj) {
|
|
515
|
+
if (!isRecord(obj)) {
|
|
516
|
+
return new SyncGrant();
|
|
517
|
+
}
|
|
518
|
+
return new SyncGrant({
|
|
519
|
+
paths: Array.isArray(obj.paths)
|
|
520
|
+
? obj.paths.map((pathGrant) => SyncPathGrant.fromJSON(pathGrant))
|
|
521
|
+
: undefined,
|
|
522
|
+
});
|
|
108
523
|
}
|
|
109
524
|
}
|
|
110
525
|
export class StoragePathGrant {
|
|
@@ -112,112 +527,516 @@ export class StoragePathGrant {
|
|
|
112
527
|
this.path = path;
|
|
113
528
|
this.readOnly = readOnly ?? false;
|
|
114
529
|
}
|
|
530
|
+
toJSON() {
|
|
531
|
+
const json = {
|
|
532
|
+
path: this.path,
|
|
533
|
+
};
|
|
534
|
+
if (this.readOnly !== false) {
|
|
535
|
+
json["read_only"] = this.readOnly;
|
|
536
|
+
}
|
|
537
|
+
return json;
|
|
538
|
+
}
|
|
539
|
+
static fromJSON(obj) {
|
|
540
|
+
if (!isRecord(obj) || typeof obj.path !== "string") {
|
|
541
|
+
throw new Error("StoragePathGrant requires a path");
|
|
542
|
+
}
|
|
543
|
+
return new StoragePathGrant({
|
|
544
|
+
path: obj.path,
|
|
545
|
+
readOnly: obj.read_only ?? obj.readOnly,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
115
548
|
}
|
|
116
549
|
export class StorageGrant {
|
|
117
550
|
constructor({ paths } = {}) {
|
|
118
551
|
this.paths = paths;
|
|
119
552
|
}
|
|
120
|
-
matches(p, path) {
|
|
121
|
-
return path.startsWith(p.path);
|
|
122
|
-
}
|
|
123
553
|
canRead(path) {
|
|
124
|
-
if (
|
|
554
|
+
if (this.paths === undefined) {
|
|
125
555
|
return true;
|
|
126
|
-
|
|
556
|
+
}
|
|
557
|
+
return this.paths.some((pathGrant) => path.startsWith(pathGrant.path));
|
|
127
558
|
}
|
|
128
559
|
canWrite(path) {
|
|
129
|
-
if (
|
|
560
|
+
if (this.paths === undefined) {
|
|
130
561
|
return true;
|
|
131
|
-
|
|
132
|
-
|
|
562
|
+
}
|
|
563
|
+
for (const pathGrant of this.paths) {
|
|
564
|
+
if (path.startsWith(pathGrant.path)) {
|
|
565
|
+
return !pathGrant.readOnly;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
toJSON() {
|
|
571
|
+
const json = {};
|
|
572
|
+
if (this.paths !== undefined) {
|
|
573
|
+
json["paths"] = this.paths.map((pathGrant) => pathGrant.toJSON());
|
|
574
|
+
}
|
|
575
|
+
return json;
|
|
576
|
+
}
|
|
577
|
+
static fromJSON(obj) {
|
|
578
|
+
if (!isRecord(obj)) {
|
|
579
|
+
return new StorageGrant();
|
|
580
|
+
}
|
|
581
|
+
return new StorageGrant({
|
|
582
|
+
paths: Array.isArray(obj.paths)
|
|
583
|
+
? obj.paths.map((pathGrant) => StoragePathGrant.fromJSON(pathGrant))
|
|
584
|
+
: undefined,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
export class ContainerRegistryGrant {
|
|
589
|
+
constructor({ list, pull, run, write, } = {}) {
|
|
590
|
+
this.list = list;
|
|
591
|
+
this.pull = pull;
|
|
592
|
+
this.run = run;
|
|
593
|
+
this.write = write;
|
|
594
|
+
}
|
|
595
|
+
canList(repository) {
|
|
596
|
+
if (this.list !== undefined) {
|
|
597
|
+
return matchesGrantPattern(this.list, repository, false);
|
|
598
|
+
}
|
|
599
|
+
if (this.pull === undefined && this.run === undefined && this.write === undefined) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
return [this.pull, this.run, this.write]
|
|
603
|
+
.filter((patterns) => patterns !== undefined)
|
|
604
|
+
.some((patterns) => matchesGrantPattern(patterns, repository, false));
|
|
605
|
+
}
|
|
606
|
+
canPull(repository) {
|
|
607
|
+
return matchesGrantPattern(this.pull, repository, true);
|
|
608
|
+
}
|
|
609
|
+
canRun(repository) {
|
|
610
|
+
return matchesGrantPattern(this.run, repository, true);
|
|
611
|
+
}
|
|
612
|
+
canWrite(repository) {
|
|
613
|
+
return matchesGrantPattern(this.write, repository, true);
|
|
614
|
+
}
|
|
615
|
+
toJSON() {
|
|
616
|
+
const json = {};
|
|
617
|
+
if (this.list !== undefined) {
|
|
618
|
+
json["list"] = this.list;
|
|
619
|
+
}
|
|
620
|
+
if (this.pull !== undefined) {
|
|
621
|
+
json["pull"] = this.pull;
|
|
622
|
+
}
|
|
623
|
+
if (this.run !== undefined) {
|
|
624
|
+
json["run"] = this.run;
|
|
625
|
+
}
|
|
626
|
+
if (this.write !== undefined) {
|
|
627
|
+
json["write"] = this.write;
|
|
628
|
+
}
|
|
629
|
+
return json;
|
|
630
|
+
}
|
|
631
|
+
static fromJSON(obj) {
|
|
632
|
+
if (!isRecord(obj)) {
|
|
633
|
+
return new ContainerRegistryGrant();
|
|
634
|
+
}
|
|
635
|
+
return new ContainerRegistryGrant({
|
|
636
|
+
list: asStringList(obj.list),
|
|
637
|
+
pull: asStringList(obj.pull),
|
|
638
|
+
run: asStringList(obj.run),
|
|
639
|
+
write: asStringList(obj.write),
|
|
640
|
+
});
|
|
133
641
|
}
|
|
134
642
|
}
|
|
135
643
|
export class ContainersGrant {
|
|
136
|
-
constructor({ logs, pull, run, useContainers } = {}) {
|
|
644
|
+
constructor({ logs, pull, run, registry, useContainers, } = {}) {
|
|
137
645
|
this.logs = logs ?? true;
|
|
138
646
|
this.pull = pull;
|
|
139
647
|
this.run = run;
|
|
648
|
+
this.registry = registry;
|
|
140
649
|
this.useContainers = useContainers ?? true;
|
|
141
650
|
}
|
|
142
|
-
|
|
143
|
-
|
|
651
|
+
canPull(tag) {
|
|
652
|
+
return matchesGrantPattern(this.pull, tag, true);
|
|
653
|
+
}
|
|
654
|
+
canRun(tag) {
|
|
655
|
+
return matchesGrantPattern(this.run, tag, true);
|
|
656
|
+
}
|
|
657
|
+
canRegistryList(repository) {
|
|
658
|
+
if (this.registry === undefined) {
|
|
144
659
|
return true;
|
|
145
660
|
}
|
|
146
|
-
return
|
|
661
|
+
return this.registry.canList(repository);
|
|
147
662
|
}
|
|
148
|
-
|
|
149
|
-
|
|
663
|
+
canRegistryPull(repository) {
|
|
664
|
+
if (this.registry === undefined) {
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
return this.registry.canPull(repository);
|
|
150
668
|
}
|
|
151
|
-
|
|
152
|
-
|
|
669
|
+
canRegistryRun(repository) {
|
|
670
|
+
if (this.registry === undefined) {
|
|
671
|
+
return true;
|
|
672
|
+
}
|
|
673
|
+
return this.registry.canRun(repository);
|
|
674
|
+
}
|
|
675
|
+
canRegistryWrite(repository) {
|
|
676
|
+
if (this.registry === undefined) {
|
|
677
|
+
return true;
|
|
678
|
+
}
|
|
679
|
+
return this.registry.canWrite(repository);
|
|
680
|
+
}
|
|
681
|
+
toJSON() {
|
|
682
|
+
const json = {};
|
|
683
|
+
if (this.logs !== true) {
|
|
684
|
+
json["logs"] = this.logs;
|
|
685
|
+
}
|
|
686
|
+
if (this.pull !== undefined) {
|
|
687
|
+
json["pull"] = this.pull;
|
|
688
|
+
}
|
|
689
|
+
if (this.run !== undefined) {
|
|
690
|
+
json["run"] = this.run;
|
|
691
|
+
}
|
|
692
|
+
if (this.registry !== undefined) {
|
|
693
|
+
json["registry"] = this.registry.toJSON();
|
|
694
|
+
}
|
|
695
|
+
if (this.useContainers !== true) {
|
|
696
|
+
json["use_containers"] = this.useContainers;
|
|
697
|
+
}
|
|
698
|
+
return json;
|
|
699
|
+
}
|
|
700
|
+
static fromJSON(obj) {
|
|
701
|
+
if (!isRecord(obj)) {
|
|
702
|
+
return new ContainersGrant();
|
|
703
|
+
}
|
|
704
|
+
return new ContainersGrant({
|
|
705
|
+
logs: obj.logs,
|
|
706
|
+
pull: asStringList(obj.pull),
|
|
707
|
+
run: asStringList(obj.run),
|
|
708
|
+
registry: obj.registry ? ContainerRegistryGrant.fromJSON(obj.registry) : undefined,
|
|
709
|
+
useContainers: obj.use_containers ?? obj.useContainers,
|
|
710
|
+
});
|
|
153
711
|
}
|
|
154
712
|
}
|
|
155
713
|
export class DeveloperGrant {
|
|
156
714
|
constructor({ logs } = {}) {
|
|
157
715
|
this.logs = logs ?? true;
|
|
158
716
|
}
|
|
717
|
+
toJSON() {
|
|
718
|
+
const json = {};
|
|
719
|
+
if (this.logs !== true) {
|
|
720
|
+
json["logs"] = this.logs;
|
|
721
|
+
}
|
|
722
|
+
return json;
|
|
723
|
+
}
|
|
724
|
+
static fromJSON(obj) {
|
|
725
|
+
if (!isRecord(obj)) {
|
|
726
|
+
return new DeveloperGrant();
|
|
727
|
+
}
|
|
728
|
+
return new DeveloperGrant({
|
|
729
|
+
logs: obj.logs,
|
|
730
|
+
});
|
|
731
|
+
}
|
|
159
732
|
}
|
|
160
733
|
export class AdminGrant {
|
|
734
|
+
constructor({ config } = {}) {
|
|
735
|
+
this.config = config ?? true;
|
|
736
|
+
}
|
|
737
|
+
toJSON() {
|
|
738
|
+
const json = {};
|
|
739
|
+
if (this.config !== true) {
|
|
740
|
+
json["config"] = this.config;
|
|
741
|
+
}
|
|
742
|
+
return json;
|
|
743
|
+
}
|
|
744
|
+
static fromJSON(obj) {
|
|
745
|
+
if (!isRecord(obj)) {
|
|
746
|
+
return new AdminGrant();
|
|
747
|
+
}
|
|
748
|
+
return new AdminGrant({
|
|
749
|
+
config: obj.config,
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
export class OAuthEndpoint {
|
|
754
|
+
constructor({ endpoint, clientId }) {
|
|
755
|
+
this.endpoint = endpoint;
|
|
756
|
+
this.clientId = clientId;
|
|
757
|
+
}
|
|
758
|
+
toJSON() {
|
|
759
|
+
return {
|
|
760
|
+
endpoint: this.endpoint,
|
|
761
|
+
client_id: this.clientId,
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
static fromJSON(obj) {
|
|
765
|
+
if (!isRecord(obj) || typeof obj.endpoint !== "string") {
|
|
766
|
+
throw new Error("OAuthEndpoint requires an endpoint");
|
|
767
|
+
}
|
|
768
|
+
const clientId = obj.client_id ?? obj.clientId;
|
|
769
|
+
if (typeof clientId !== "string") {
|
|
770
|
+
throw new Error("OAuthEndpoint requires a client_id");
|
|
771
|
+
}
|
|
772
|
+
return new OAuthEndpoint({
|
|
773
|
+
endpoint: obj.endpoint,
|
|
774
|
+
clientId,
|
|
775
|
+
});
|
|
776
|
+
}
|
|
161
777
|
}
|
|
162
778
|
export class SecretsGrant {
|
|
163
|
-
|
|
164
|
-
|
|
779
|
+
constructor({ requestOauthToken } = {}) {
|
|
780
|
+
this.requestOauthToken = requestOauthToken;
|
|
781
|
+
}
|
|
782
|
+
canRequestOauthToken({ connector, oauth, } = {}) {
|
|
783
|
+
void connector;
|
|
784
|
+
if (this.requestOauthToken === undefined) {
|
|
165
785
|
return true;
|
|
166
786
|
}
|
|
167
|
-
|
|
787
|
+
const authorizationEndpoint = typeof oauth?.authorization_endpoint === "string"
|
|
788
|
+
? oauth.authorization_endpoint.trim()
|
|
789
|
+
: "";
|
|
790
|
+
const clientId = typeof oauth?.client_id === "string"
|
|
791
|
+
? oauth.client_id.trim()
|
|
792
|
+
: "";
|
|
793
|
+
if (authorizationEndpoint === "" || clientId === "") {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
return this.requestOauthToken.some((endpointGrant) => ((endpointGrant.endpoint === authorizationEndpoint
|
|
797
|
+
|| (endpointGrant.endpoint.endsWith("*")
|
|
798
|
+
&& authorizationEndpoint.startsWith(endpointGrant.endpoint.slice(0, -1))))
|
|
799
|
+
&& endpointGrant.clientId === clientId));
|
|
800
|
+
}
|
|
801
|
+
toJSON() {
|
|
802
|
+
const json = {};
|
|
803
|
+
if (this.requestOauthToken !== undefined) {
|
|
804
|
+
json["request_oauth_token"] = this.requestOauthToken.map((endpointGrant) => endpointGrant.toJSON());
|
|
805
|
+
}
|
|
806
|
+
return json;
|
|
807
|
+
}
|
|
808
|
+
static fromJSON(obj) {
|
|
809
|
+
if (!isRecord(obj)) {
|
|
810
|
+
return new SecretsGrant();
|
|
811
|
+
}
|
|
812
|
+
const requestOauthToken = obj.request_oauth_token ?? obj.requestOauthToken;
|
|
813
|
+
return new SecretsGrant({
|
|
814
|
+
requestOauthToken: Array.isArray(requestOauthToken)
|
|
815
|
+
? requestOauthToken.map((endpointGrant) => OAuthEndpoint.fromJSON(endpointGrant))
|
|
816
|
+
: undefined,
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
export class TunnelsGrant {
|
|
821
|
+
constructor({ ports } = {}) {
|
|
822
|
+
this.ports = ports;
|
|
823
|
+
}
|
|
824
|
+
toJSON() {
|
|
825
|
+
const json = {};
|
|
826
|
+
if (this.ports !== undefined) {
|
|
827
|
+
json["ports"] = this.ports;
|
|
828
|
+
}
|
|
829
|
+
return json;
|
|
830
|
+
}
|
|
831
|
+
static fromJSON(obj) {
|
|
832
|
+
if (!isRecord(obj)) {
|
|
833
|
+
return new TunnelsGrant();
|
|
834
|
+
}
|
|
835
|
+
return new TunnelsGrant({
|
|
836
|
+
ports: asStringList(obj.ports),
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
export class ServicesGrant {
|
|
841
|
+
constructor({ list } = {}) {
|
|
842
|
+
this.list = list ?? true;
|
|
843
|
+
}
|
|
844
|
+
toJSON() {
|
|
845
|
+
const json = {};
|
|
846
|
+
if (this.list !== true) {
|
|
847
|
+
json["list"] = this.list;
|
|
848
|
+
}
|
|
849
|
+
return json;
|
|
850
|
+
}
|
|
851
|
+
static fromJSON(obj) {
|
|
852
|
+
if (!isRecord(obj)) {
|
|
853
|
+
return new ServicesGrant();
|
|
854
|
+
}
|
|
855
|
+
return new ServicesGrant({
|
|
856
|
+
list: obj.list,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
export class LLMGrant {
|
|
861
|
+
constructor({ models } = {}) {
|
|
862
|
+
this.models = models;
|
|
863
|
+
}
|
|
864
|
+
canUseProvider(provider) {
|
|
865
|
+
const normalizedProvider = provider.trim();
|
|
866
|
+
if (normalizedProvider === "") {
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
if (!this.models) {
|
|
870
|
+
return true;
|
|
871
|
+
}
|
|
872
|
+
const prefix = `${normalizedProvider}/`;
|
|
873
|
+
return this.models.some((pattern) => pattern.trim().startsWith(prefix));
|
|
874
|
+
}
|
|
875
|
+
canUseModel(provider, model) {
|
|
876
|
+
const normalizedProvider = provider.trim();
|
|
877
|
+
const normalizedModel = model.trim();
|
|
878
|
+
if (normalizedProvider === "" || normalizedModel === "") {
|
|
879
|
+
return false;
|
|
880
|
+
}
|
|
881
|
+
return matchesGrantPattern(this.models, `${normalizedProvider}/${normalizedModel}`, true);
|
|
882
|
+
}
|
|
883
|
+
toJSON() {
|
|
884
|
+
const json = {};
|
|
885
|
+
if (this.models !== undefined) {
|
|
886
|
+
json["models"] = this.models;
|
|
887
|
+
}
|
|
888
|
+
return json;
|
|
889
|
+
}
|
|
890
|
+
static fromJSON(obj) {
|
|
891
|
+
if (!isRecord(obj)) {
|
|
892
|
+
return new LLMGrant();
|
|
893
|
+
}
|
|
894
|
+
return new LLMGrant({
|
|
895
|
+
models: asStringList(obj.models),
|
|
896
|
+
});
|
|
168
897
|
}
|
|
169
898
|
}
|
|
170
899
|
export class ApiScope {
|
|
171
|
-
constructor({ livekit, queues, messaging, database, sync, storage, containers, developer, agents, admin, secrets, } = {}) {
|
|
900
|
+
constructor({ livekit, queues, messaging, database, memory, sync, storage, containers, developer, agents, llm, admin, secrets, tunnels, services, } = {}) {
|
|
172
901
|
this.livekit = livekit;
|
|
173
902
|
this.queues = queues;
|
|
174
903
|
this.messaging = messaging;
|
|
175
904
|
this.database = database;
|
|
905
|
+
this.memory = memory;
|
|
176
906
|
this.sync = sync;
|
|
177
907
|
this.storage = storage;
|
|
178
908
|
this.containers = containers;
|
|
179
909
|
this.developer = developer;
|
|
180
910
|
this.agents = agents;
|
|
911
|
+
this.llm = llm;
|
|
181
912
|
this.admin = admin;
|
|
182
913
|
this.secrets = secrets;
|
|
914
|
+
this.tunnels = tunnels;
|
|
915
|
+
this.services = services;
|
|
183
916
|
}
|
|
184
|
-
static agentDefault() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
917
|
+
static agentDefault({ tunnels = false } = {}) {
|
|
918
|
+
return new ApiScope({
|
|
919
|
+
livekit: new LivekitGrant(),
|
|
920
|
+
queues: new QueuesGrant(),
|
|
921
|
+
messaging: new MessagingGrant(),
|
|
922
|
+
database: new DatabaseGrant(),
|
|
923
|
+
memory: new MemoryGrant(),
|
|
924
|
+
sync: new SyncGrant(),
|
|
925
|
+
storage: new StorageGrant(),
|
|
926
|
+
containers: new ContainersGrant(),
|
|
927
|
+
developer: new DeveloperGrant(),
|
|
928
|
+
agents: new AgentsGrant(),
|
|
929
|
+
llm: new LLMGrant(),
|
|
930
|
+
secrets: new SecretsGrant(),
|
|
931
|
+
services: new ServicesGrant(),
|
|
932
|
+
tunnels: tunnels ? new TunnelsGrant() : undefined,
|
|
933
|
+
});
|
|
196
934
|
}
|
|
197
935
|
static userDefault() {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
936
|
+
return new ApiScope({
|
|
937
|
+
livekit: new LivekitGrant(),
|
|
938
|
+
queues: new QueuesGrant(),
|
|
939
|
+
messaging: new MessagingGrant(),
|
|
940
|
+
database: new DatabaseGrant(),
|
|
941
|
+
memory: new MemoryGrant(),
|
|
942
|
+
sync: new SyncGrant(),
|
|
943
|
+
storage: new StorageGrant(),
|
|
944
|
+
containers: new ContainersGrant(),
|
|
945
|
+
developer: new DeveloperGrant(),
|
|
946
|
+
agents: new AgentsGrant(),
|
|
947
|
+
secrets: new SecretsGrant(),
|
|
948
|
+
services: new ServicesGrant(),
|
|
949
|
+
});
|
|
210
950
|
}
|
|
211
951
|
static full() {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
952
|
+
return new ApiScope({
|
|
953
|
+
livekit: new LivekitGrant(),
|
|
954
|
+
queues: new QueuesGrant(),
|
|
955
|
+
messaging: new MessagingGrant(),
|
|
956
|
+
database: new DatabaseGrant(),
|
|
957
|
+
memory: new MemoryGrant(),
|
|
958
|
+
sync: new SyncGrant(),
|
|
959
|
+
storage: new StorageGrant(),
|
|
960
|
+
containers: new ContainersGrant(),
|
|
961
|
+
developer: new DeveloperGrant(),
|
|
962
|
+
agents: new AgentsGrant(),
|
|
963
|
+
llm: new LLMGrant(),
|
|
964
|
+
admin: new AdminGrant(),
|
|
965
|
+
secrets: new SecretsGrant(),
|
|
966
|
+
tunnels: new TunnelsGrant(),
|
|
967
|
+
services: new ServicesGrant(),
|
|
968
|
+
});
|
|
215
969
|
}
|
|
216
970
|
toJSON() {
|
|
217
|
-
|
|
971
|
+
const json = {};
|
|
972
|
+
if (this.livekit !== undefined) {
|
|
973
|
+
json["livekit"] = this.livekit.toJSON();
|
|
974
|
+
}
|
|
975
|
+
if (this.queues !== undefined) {
|
|
976
|
+
json["queues"] = this.queues.toJSON();
|
|
977
|
+
}
|
|
978
|
+
if (this.messaging !== undefined) {
|
|
979
|
+
json["messaging"] = this.messaging.toJSON();
|
|
980
|
+
}
|
|
981
|
+
if (this.database !== undefined) {
|
|
982
|
+
json["database"] = this.database.toJSON();
|
|
983
|
+
}
|
|
984
|
+
if (this.memory !== undefined) {
|
|
985
|
+
json["memory"] = this.memory.toJSON();
|
|
986
|
+
}
|
|
987
|
+
if (this.sync !== undefined) {
|
|
988
|
+
json["sync"] = this.sync.toJSON();
|
|
989
|
+
}
|
|
990
|
+
if (this.storage !== undefined) {
|
|
991
|
+
json["storage"] = this.storage.toJSON();
|
|
992
|
+
}
|
|
993
|
+
if (this.containers !== undefined) {
|
|
994
|
+
json["containers"] = this.containers.toJSON();
|
|
995
|
+
}
|
|
996
|
+
if (this.developer !== undefined) {
|
|
997
|
+
json["developer"] = this.developer.toJSON();
|
|
998
|
+
}
|
|
999
|
+
if (this.agents !== undefined) {
|
|
1000
|
+
json["agents"] = this.agents.toJSON();
|
|
1001
|
+
}
|
|
1002
|
+
if (this.llm !== undefined) {
|
|
1003
|
+
json["llm"] = this.llm.toJSON();
|
|
1004
|
+
}
|
|
1005
|
+
if (this.admin !== undefined) {
|
|
1006
|
+
json["admin"] = this.admin.toJSON();
|
|
1007
|
+
}
|
|
1008
|
+
if (this.secrets !== undefined) {
|
|
1009
|
+
json["secrets"] = this.secrets.toJSON();
|
|
1010
|
+
}
|
|
1011
|
+
if (this.tunnels !== undefined) {
|
|
1012
|
+
json["tunnels"] = this.tunnels.toJSON();
|
|
1013
|
+
}
|
|
1014
|
+
if (this.services !== undefined) {
|
|
1015
|
+
json["services"] = this.services.toJSON();
|
|
1016
|
+
}
|
|
1017
|
+
return json;
|
|
218
1018
|
}
|
|
219
1019
|
static fromJSON(obj) {
|
|
220
|
-
|
|
1020
|
+
if (!isRecord(obj)) {
|
|
1021
|
+
return new ApiScope();
|
|
1022
|
+
}
|
|
1023
|
+
return new ApiScope({
|
|
1024
|
+
livekit: obj.livekit ? LivekitGrant.fromJSON(obj.livekit) : undefined,
|
|
1025
|
+
queues: obj.queues ? QueuesGrant.fromJSON(obj.queues) : undefined,
|
|
1026
|
+
messaging: obj.messaging ? MessagingGrant.fromJSON(obj.messaging) : undefined,
|
|
1027
|
+
database: obj.database ? DatabaseGrant.fromJSON(obj.database) : undefined,
|
|
1028
|
+
memory: obj.memory ? MemoryGrant.fromJSON(obj.memory) : undefined,
|
|
1029
|
+
sync: obj.sync ? SyncGrant.fromJSON(obj.sync) : undefined,
|
|
1030
|
+
storage: obj.storage ? StorageGrant.fromJSON(obj.storage) : undefined,
|
|
1031
|
+
containers: obj.containers ? ContainersGrant.fromJSON(obj.containers) : undefined,
|
|
1032
|
+
developer: obj.developer ? DeveloperGrant.fromJSON(obj.developer) : undefined,
|
|
1033
|
+
agents: obj.agents ? AgentsGrant.fromJSON(obj.agents) : undefined,
|
|
1034
|
+
llm: obj.llm ? LLMGrant.fromJSON(obj.llm) : undefined,
|
|
1035
|
+
admin: obj.admin ? AdminGrant.fromJSON(obj.admin) : undefined,
|
|
1036
|
+
secrets: obj.secrets ? SecretsGrant.fromJSON(obj.secrets) : undefined,
|
|
1037
|
+
tunnels: obj.tunnels ? TunnelsGrant.fromJSON(obj.tunnels) : undefined,
|
|
1038
|
+
services: obj.services ? ServicesGrant.fromJSON(obj.services) : undefined,
|
|
1039
|
+
});
|
|
221
1040
|
}
|
|
222
1041
|
}
|
|
223
1042
|
export class ParticipantGrant {
|
|
@@ -250,12 +1069,14 @@ export class ParticipantGrant {
|
|
|
250
1069
|
}
|
|
251
1070
|
}
|
|
252
1071
|
function compareSemver(a, b) {
|
|
253
|
-
const pa = a.split(".").map(
|
|
254
|
-
const pb = b.split(".").map(
|
|
255
|
-
for (let
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
1072
|
+
const pa = a.split(".").map((value) => parseInt(value, 10));
|
|
1073
|
+
const pb = b.split(".").map((value) => parseInt(value, 10));
|
|
1074
|
+
for (let index = 0; index < Math.max(pa.length, pb.length); index += 1) {
|
|
1075
|
+
const left = pa[index] || 0;
|
|
1076
|
+
const right = pb[index] || 0;
|
|
1077
|
+
if (left !== right) {
|
|
1078
|
+
return left - right;
|
|
1079
|
+
}
|
|
259
1080
|
}
|
|
260
1081
|
return 0;
|
|
261
1082
|
}
|
|
@@ -264,14 +1085,14 @@ export class ParticipantToken {
|
|
|
264
1085
|
this.name = name;
|
|
265
1086
|
this.projectId = projectId;
|
|
266
1087
|
this.apiKeyId = apiKeyId;
|
|
267
|
-
this.version = version;
|
|
1088
|
+
this.version = version ?? __version__;
|
|
268
1089
|
this.extra = extra ?? {};
|
|
269
1090
|
this.grants = grants ?? [];
|
|
270
1091
|
}
|
|
271
1092
|
get role() {
|
|
272
|
-
for (const
|
|
273
|
-
if (
|
|
274
|
-
return String(
|
|
1093
|
+
for (const grant of this.grants) {
|
|
1094
|
+
if (grant.name === "role" && grant.scope !== "user") {
|
|
1095
|
+
return String(grant.scope);
|
|
275
1096
|
}
|
|
276
1097
|
}
|
|
277
1098
|
return "user";
|
|
@@ -293,8 +1114,10 @@ export class ParticipantToken {
|
|
|
293
1114
|
return true;
|
|
294
1115
|
}
|
|
295
1116
|
addTunnelGrant(ports) {
|
|
296
|
-
|
|
297
|
-
|
|
1117
|
+
this.grants.push(new ParticipantGrant({
|
|
1118
|
+
name: "tunnel_ports",
|
|
1119
|
+
scope: ports.join(","),
|
|
1120
|
+
}));
|
|
298
1121
|
}
|
|
299
1122
|
addRoleGrant(role) {
|
|
300
1123
|
this.grants.push(new ParticipantGrant({ name: "role", scope: role }));
|
|
@@ -303,132 +1126,113 @@ export class ParticipantToken {
|
|
|
303
1126
|
this.grants.push(new ParticipantGrant({ name: "room", scope: roomName }));
|
|
304
1127
|
}
|
|
305
1128
|
addApiGrant(grant) {
|
|
1129
|
+
for (const existingGrant of this.grants) {
|
|
1130
|
+
if (existingGrant.name === "api") {
|
|
1131
|
+
throw new Error("can only have a single api grant");
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
306
1134
|
this.grants.push(new ParticipantGrant({ name: "api", scope: grant }));
|
|
307
1135
|
}
|
|
308
1136
|
grantScope(name) {
|
|
309
|
-
return this.grants.find(
|
|
1137
|
+
return this.grants.find((grant) => grant.name === name)?.scope;
|
|
310
1138
|
}
|
|
311
1139
|
getApiGrant() {
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
314
|
-
return
|
|
315
|
-
}
|
|
316
|
-
if (this.version && compareSemver(this.version, "0.6.0") < 0 && !api) {
|
|
317
|
-
return new ApiScope({
|
|
318
|
-
livekit: new LivekitGrant(),
|
|
319
|
-
queues: new QueuesGrant(),
|
|
320
|
-
messaging: new MessagingGrant(),
|
|
321
|
-
database: new DatabaseGrant(),
|
|
322
|
-
sync: new SyncGrant(),
|
|
323
|
-
storage: new StorageGrant(),
|
|
324
|
-
agents: new AgentsGrant(),
|
|
325
|
-
developer: new DeveloperGrant(),
|
|
326
|
-
});
|
|
1140
|
+
const apiGrant = this.grantScope("api");
|
|
1141
|
+
if (apiGrant && typeof apiGrant !== "string") {
|
|
1142
|
+
return apiGrant;
|
|
327
1143
|
}
|
|
328
|
-
return
|
|
1144
|
+
return undefined;
|
|
329
1145
|
}
|
|
330
1146
|
toJson() {
|
|
331
|
-
const
|
|
1147
|
+
const json = {
|
|
1148
|
+
...(this.extra ?? {}),
|
|
332
1149
|
name: this.name,
|
|
333
|
-
grants: this.grants.map(
|
|
1150
|
+
grants: this.grants.map((grant) => grant.toJson()),
|
|
334
1151
|
};
|
|
335
|
-
if (this.projectId) {
|
|
336
|
-
|
|
1152
|
+
if (this.projectId !== undefined) {
|
|
1153
|
+
json["sub"] = this.projectId;
|
|
337
1154
|
}
|
|
338
|
-
if (this.apiKeyId) {
|
|
339
|
-
|
|
1155
|
+
if (this.apiKeyId !== undefined) {
|
|
1156
|
+
json["kid"] = this.apiKeyId;
|
|
340
1157
|
}
|
|
341
|
-
if (this.version) {
|
|
342
|
-
|
|
1158
|
+
if (this.version !== undefined) {
|
|
1159
|
+
json["version"] = this.version;
|
|
343
1160
|
}
|
|
344
|
-
return
|
|
1161
|
+
return json;
|
|
345
1162
|
}
|
|
346
|
-
async toJwt({ token, expiration, apiKey } = {}) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
apiGrant = g;
|
|
351
|
-
break;
|
|
352
|
-
}
|
|
1163
|
+
async toJwt({ token, expiration, apiKey, } = {}) {
|
|
1164
|
+
const apiGrant = this.grants.find((grant) => grant.name === "api");
|
|
1165
|
+
if (!apiGrant && compareSemver(this.version, "0.3.5") > 0) {
|
|
1166
|
+
console.warn("there is no ApiScope in the participant token, this participant will not be able to make calls to the the room API. Use addApiGrant to add an ApiScope to this token.");
|
|
353
1167
|
}
|
|
354
|
-
if (!apiGrant && this.version && compareSemver(this.version, "0.5.3") >= 0) {
|
|
355
|
-
console.error("ParticipantToken.toJwt: No API grant found, but version is >= 0.5.3. " +
|
|
356
|
-
"This may cause issues with older clients that expect an API grant.");
|
|
357
|
-
}
|
|
358
|
-
let resolvedSecret = token;
|
|
359
|
-
let resolvedKid = this.apiKeyId;
|
|
360
|
-
let resolvedSub = this.projectId;
|
|
361
|
-
const apiKeyValue = apiKey ?? getEnvValue("MESHAGENT_API_KEY");
|
|
362
|
-
if (apiKeyValue) {
|
|
363
|
-
const parsed = parseApiKey(apiKeyValue);
|
|
364
|
-
resolvedSecret ?? (resolvedSecret = parsed.secret);
|
|
365
|
-
resolvedKid = parsed.id;
|
|
366
|
-
resolvedSub = parsed.projectId;
|
|
367
|
-
}
|
|
368
|
-
let usingDefaultSecret = false;
|
|
369
|
-
if (!resolvedSecret) {
|
|
370
|
-
const envSecret = getEnvValue("MESHAGENT_SECRET");
|
|
371
|
-
if (!envSecret) {
|
|
372
|
-
throw new Error("ParticipantToken.toJwt: No secret provided. Pass `token`, `apiKey`, or set MESHAGENT_SECRET / MESHAGENT_API_KEY.");
|
|
373
|
-
}
|
|
374
|
-
resolvedSecret = envSecret;
|
|
375
|
-
usingDefaultSecret = true;
|
|
376
|
-
}
|
|
377
|
-
const secretKey = new TextEncoder().encode(resolvedSecret);
|
|
378
1168
|
const payload = this.toJson();
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
1169
|
+
const resolvedApiKey = apiKey ?? getEnvValue("MESHAGENT_API_KEY");
|
|
1170
|
+
let resolvedSecret = token;
|
|
1171
|
+
if (resolvedApiKey !== undefined) {
|
|
1172
|
+
const parsed = parseApiKey(resolvedApiKey);
|
|
1173
|
+
resolvedSecret = parsed.secret;
|
|
1174
|
+
payload["kid"] = parsed.id;
|
|
1175
|
+
payload["sub"] = parsed.projectId;
|
|
384
1176
|
}
|
|
385
|
-
if (
|
|
1177
|
+
else if (resolvedSecret === undefined) {
|
|
386
1178
|
delete payload["kid"];
|
|
387
1179
|
}
|
|
388
|
-
|
|
389
|
-
|
|
1180
|
+
if (resolvedSecret === undefined) {
|
|
1181
|
+
resolvedSecret = getEnvValue("MESHAGENT_SECRET");
|
|
390
1182
|
}
|
|
391
|
-
|
|
392
|
-
|
|
1183
|
+
if (resolvedSecret === undefined) {
|
|
1184
|
+
throw new Error("ParticipantToken.toJwt: No secret provided. Pass `token`, `apiKey`, or set MESHAGENT_SECRET / MESHAGENT_API_KEY.");
|
|
393
1185
|
}
|
|
394
|
-
if (expiration) {
|
|
1186
|
+
if (expiration !== undefined) {
|
|
395
1187
|
payload.exp = Math.floor(expiration.getTime() / 1000);
|
|
396
1188
|
}
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
1189
|
+
const secretKey = new TextEncoder().encode(resolvedSecret);
|
|
1190
|
+
return await new SignJWT(payload)
|
|
1191
|
+
.setProtectedHeader({ alg: "HS256", typ: "JWT" })
|
|
1192
|
+
.sign(secretKey);
|
|
401
1193
|
}
|
|
402
1194
|
static fromJson(json) {
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
1195
|
+
const data = { ...json };
|
|
1196
|
+
if (typeof data.name !== "string") {
|
|
1197
|
+
throw new Error(`Participant token does not have a name ${JSON.stringify(json)}`);
|
|
1198
|
+
}
|
|
1199
|
+
const name = data.name;
|
|
1200
|
+
delete data.name;
|
|
1201
|
+
const grantsRaw = Array.isArray(data.grants) ? data.grants : [];
|
|
1202
|
+
delete data.grants;
|
|
1203
|
+
const projectId = typeof data.sub === "string" ? data.sub : undefined;
|
|
1204
|
+
delete data.sub;
|
|
1205
|
+
const apiKeyId = typeof data.kid === "string" ? data.kid : undefined;
|
|
1206
|
+
delete data.kid;
|
|
1207
|
+
const version = typeof data.version === "string" ? data.version : __version__;
|
|
1208
|
+
delete data.version;
|
|
406
1209
|
return new ParticipantToken({
|
|
407
|
-
name
|
|
408
|
-
projectId
|
|
409
|
-
apiKeyId
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
1210
|
+
name,
|
|
1211
|
+
projectId,
|
|
1212
|
+
apiKeyId,
|
|
1213
|
+
grants: grantsRaw.map((grant) => ParticipantGrant.fromJson(grant)),
|
|
1214
|
+
extra: data,
|
|
1215
|
+
version,
|
|
413
1216
|
});
|
|
414
1217
|
}
|
|
415
1218
|
static async fromJwt(jwtStr, options = {}) {
|
|
416
|
-
const { token, verify = true } = options
|
|
1219
|
+
const { token, verify = true } = options;
|
|
417
1220
|
if (verify) {
|
|
418
|
-
const
|
|
1221
|
+
const verificationToken = token ?? getEnvValue("MESHAGENT_SECRET");
|
|
1222
|
+
if (verificationToken === undefined) {
|
|
1223
|
+
throw new Error("Failed to verify JWT: no token provided");
|
|
1224
|
+
}
|
|
1225
|
+
const secretKey = new TextEncoder().encode(verificationToken);
|
|
419
1226
|
const { payload } = await jwtVerify(jwtStr, secretKey, {
|
|
420
1227
|
algorithms: ["HS256"],
|
|
421
1228
|
});
|
|
422
1229
|
return ParticipantToken.fromJson(payload);
|
|
423
1230
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
catch (err) {
|
|
430
|
-
throw new Error("Failed to decode JWT");
|
|
431
|
-
}
|
|
1231
|
+
try {
|
|
1232
|
+
return ParticipantToken.fromJson(decodeJwt(jwtStr));
|
|
1233
|
+
}
|
|
1234
|
+
catch {
|
|
1235
|
+
throw new Error("Failed to decode JWT");
|
|
432
1236
|
}
|
|
433
1237
|
}
|
|
434
1238
|
}
|