@meshagent/meshagent 0.5.18 → 0.6.0
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 +6 -0
- package/dist/browser/agent-client.d.ts +15 -7
- package/dist/browser/agent-client.js +52 -14
- package/dist/browser/api_keys.d.ts +13 -0
- package/dist/browser/api_keys.js +185 -0
- package/dist/browser/data-types.d.ts +6 -0
- package/dist/browser/data-types.js +20 -1
- package/dist/browser/entrypoint.d.ts +1423 -1464
- package/dist/browser/helpers.d.ts +9 -7
- package/dist/browser/helpers.js +18 -5
- package/dist/browser/index.d.ts +3 -0
- package/dist/browser/index.js +3 -0
- package/dist/browser/lk-client.d.ts +18 -0
- package/dist/browser/lk-client.js +24 -0
- package/dist/browser/lk-protocol.d.ts +22 -0
- package/dist/browser/lk-protocol.js +37 -0
- package/dist/browser/meshagent-client.d.ts +392 -0
- package/dist/browser/meshagent-client.js +1051 -0
- package/dist/browser/participant-token.d.ts +179 -7
- package/dist/browser/participant-token.js +373 -21
- package/dist/browser/stream-controller.js +3 -14
- package/dist/esm/agent-client.d.ts +15 -7
- package/dist/esm/agent-client.js +52 -14
- package/dist/esm/api_keys.d.ts +13 -0
- package/dist/esm/api_keys.js +175 -0
- package/dist/esm/data-types.d.ts +6 -0
- package/dist/esm/data-types.js +18 -0
- package/dist/esm/entrypoint.d.ts +1423 -1464
- package/dist/esm/helpers.d.ts +9 -7
- package/dist/esm/helpers.js +19 -6
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/lk-client.d.ts +18 -0
- package/dist/esm/lk-client.js +19 -0
- package/dist/esm/lk-protocol.d.ts +22 -0
- package/dist/esm/lk-protocol.js +33 -0
- package/dist/esm/meshagent-client.d.ts +392 -0
- package/dist/esm/meshagent-client.js +1047 -0
- package/dist/esm/participant-token.d.ts +179 -7
- package/dist/esm/participant-token.js +357 -20
- package/dist/esm/stream-controller.js +3 -14
- package/dist/node/agent-client.d.ts +15 -7
- package/dist/node/agent-client.js +52 -14
- package/dist/node/api_keys.d.ts +13 -0
- package/dist/node/api_keys.js +185 -0
- package/dist/node/data-types.d.ts +6 -0
- package/dist/node/data-types.js +20 -1
- package/dist/node/entrypoint.d.ts +1423 -1464
- package/dist/node/helpers.d.ts +9 -7
- package/dist/node/helpers.js +18 -5
- package/dist/node/index.d.ts +3 -0
- package/dist/node/index.js +3 -0
- package/dist/node/lk-client.d.ts +18 -0
- package/dist/node/lk-client.js +24 -0
- package/dist/node/lk-protocol.d.ts +22 -0
- package/dist/node/lk-protocol.js +37 -0
- package/dist/node/meshagent-client.d.ts +392 -0
- package/dist/node/meshagent-client.js +1051 -0
- package/dist/node/participant-token.d.ts +179 -7
- package/dist/node/participant-token.js +373 -21
- package/dist/node/stream-controller.js +3 -14
- package/package.json +6 -3
|
@@ -1,9 +1,171 @@
|
|
|
1
|
+
export type StringList = string[];
|
|
2
|
+
export declare class AgentsGrant {
|
|
3
|
+
registerAgent: boolean;
|
|
4
|
+
registerPublicToolkit: boolean;
|
|
5
|
+
registerPrivateToolkit: boolean;
|
|
6
|
+
call: boolean;
|
|
7
|
+
useAgents: boolean;
|
|
8
|
+
useTools: boolean;
|
|
9
|
+
constructor({ registerAgent, registerPublicToolkit, registerPrivateToolkit, call, useAgents, useTools, }?: {
|
|
10
|
+
registerAgent?: boolean;
|
|
11
|
+
registerPublicToolkit?: boolean;
|
|
12
|
+
registerPrivateToolkit?: boolean;
|
|
13
|
+
call?: boolean;
|
|
14
|
+
useAgents?: boolean;
|
|
15
|
+
useTools?: boolean;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export declare class LivekitGrant {
|
|
19
|
+
breakoutRooms?: StringList;
|
|
20
|
+
constructor({ breakoutRooms }?: {
|
|
21
|
+
breakoutRooms?: StringList;
|
|
22
|
+
});
|
|
23
|
+
canJoinBreakoutRoom(name: string): boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare class QueuesGrant {
|
|
26
|
+
send?: StringList;
|
|
27
|
+
receive?: StringList;
|
|
28
|
+
list: boolean;
|
|
29
|
+
constructor({ send, receive, list }?: {
|
|
30
|
+
send?: StringList;
|
|
31
|
+
receive?: StringList;
|
|
32
|
+
list?: boolean;
|
|
33
|
+
});
|
|
34
|
+
canSend(q: string): boolean;
|
|
35
|
+
canReceive(q: string): boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare class MessagingGrant {
|
|
38
|
+
broadcast: boolean;
|
|
39
|
+
list: boolean;
|
|
40
|
+
send: boolean;
|
|
41
|
+
constructor({ broadcast, list, send }?: {
|
|
42
|
+
broadcast?: boolean;
|
|
43
|
+
list?: boolean;
|
|
44
|
+
send?: boolean;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export declare class TableGrant {
|
|
48
|
+
name: string;
|
|
49
|
+
write: boolean;
|
|
50
|
+
read: boolean;
|
|
51
|
+
alter: boolean;
|
|
52
|
+
constructor({ name, write, read, alter }: {
|
|
53
|
+
name: string;
|
|
54
|
+
write?: boolean;
|
|
55
|
+
read?: boolean;
|
|
56
|
+
alter?: boolean;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
export declare class DatabaseGrant {
|
|
60
|
+
tables?: TableGrant[];
|
|
61
|
+
listTables: boolean;
|
|
62
|
+
constructor({ tables, listTables }?: {
|
|
63
|
+
tables?: TableGrant[];
|
|
64
|
+
listTables?: boolean;
|
|
65
|
+
});
|
|
66
|
+
private _match;
|
|
67
|
+
canWrite(table: string): boolean;
|
|
68
|
+
canRead(table: string): boolean;
|
|
69
|
+
canAlter(table: string): boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare class SyncPathGrant {
|
|
72
|
+
path: string;
|
|
73
|
+
readOnly: boolean;
|
|
74
|
+
constructor({ path, readOnly }: {
|
|
75
|
+
path: string;
|
|
76
|
+
readOnly?: boolean;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export declare class SyncGrant {
|
|
80
|
+
paths?: SyncPathGrant[];
|
|
81
|
+
constructor({ paths }?: {
|
|
82
|
+
paths?: SyncPathGrant[];
|
|
83
|
+
});
|
|
84
|
+
private matches;
|
|
85
|
+
canRead(path: string): boolean;
|
|
86
|
+
canWrite(path: string): boolean;
|
|
87
|
+
}
|
|
88
|
+
export declare class StoragePathGrant {
|
|
89
|
+
path: string;
|
|
90
|
+
readOnly: boolean;
|
|
91
|
+
constructor({ path, readOnly }: {
|
|
92
|
+
path: string;
|
|
93
|
+
readOnly?: boolean;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export declare class StorageGrant {
|
|
97
|
+
paths?: StoragePathGrant[];
|
|
98
|
+
constructor({ paths }?: {
|
|
99
|
+
paths?: StoragePathGrant[];
|
|
100
|
+
});
|
|
101
|
+
private matches;
|
|
102
|
+
canRead(path: string): boolean;
|
|
103
|
+
canWrite(path: string): boolean;
|
|
104
|
+
}
|
|
105
|
+
export declare class ContainersGrant {
|
|
106
|
+
logs: boolean;
|
|
107
|
+
pull?: StringList;
|
|
108
|
+
run?: StringList;
|
|
109
|
+
useContainers: boolean;
|
|
110
|
+
constructor({ logs, pull, run, useContainers }?: {
|
|
111
|
+
logs?: boolean;
|
|
112
|
+
pull?: StringList;
|
|
113
|
+
run?: StringList;
|
|
114
|
+
useContainers?: boolean;
|
|
115
|
+
});
|
|
116
|
+
private match;
|
|
117
|
+
canPull(tag: string): boolean;
|
|
118
|
+
canRun(tag: string): boolean;
|
|
119
|
+
}
|
|
120
|
+
export declare class DeveloperGrant {
|
|
121
|
+
logs: boolean;
|
|
122
|
+
constructor({ logs }?: {
|
|
123
|
+
logs?: boolean;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
export declare class AdminGrant {
|
|
127
|
+
}
|
|
128
|
+
export declare class SecretsGrant {
|
|
129
|
+
requestOauthToken?: StringList;
|
|
130
|
+
canRequestOauthToken(authorizationEndpoint: string): boolean;
|
|
131
|
+
}
|
|
132
|
+
export declare class ApiScope {
|
|
133
|
+
livekit?: LivekitGrant;
|
|
134
|
+
queues?: QueuesGrant;
|
|
135
|
+
messaging?: MessagingGrant;
|
|
136
|
+
database?: DatabaseGrant;
|
|
137
|
+
sync?: SyncGrant;
|
|
138
|
+
storage?: StorageGrant;
|
|
139
|
+
containers?: ContainersGrant;
|
|
140
|
+
developer?: DeveloperGrant;
|
|
141
|
+
agents?: AgentsGrant;
|
|
142
|
+
admin?: AdminGrant;
|
|
143
|
+
secrets?: SecretsGrant;
|
|
144
|
+
constructor({ livekit, queues, messaging, database, sync, storage, containers, developer, agents, admin, secrets, }?: {
|
|
145
|
+
livekit?: LivekitGrant;
|
|
146
|
+
queues?: QueuesGrant;
|
|
147
|
+
messaging?: MessagingGrant;
|
|
148
|
+
database?: DatabaseGrant;
|
|
149
|
+
sync?: SyncGrant;
|
|
150
|
+
storage?: StorageGrant;
|
|
151
|
+
containers?: ContainersGrant;
|
|
152
|
+
developer?: DeveloperGrant;
|
|
153
|
+
agents?: AgentsGrant;
|
|
154
|
+
admin?: AdminGrant;
|
|
155
|
+
secrets?: SecretsGrant;
|
|
156
|
+
});
|
|
157
|
+
static agentDefault(): ApiScope;
|
|
158
|
+
static userDefault(): ApiScope;
|
|
159
|
+
static full(): ApiScope;
|
|
160
|
+
toJSON(): Record<string, any>;
|
|
161
|
+
static fromJSON(obj: any): ApiScope;
|
|
162
|
+
}
|
|
1
163
|
export declare class ParticipantGrant {
|
|
2
164
|
name: string;
|
|
3
|
-
scope?: string;
|
|
165
|
+
scope?: string | ApiScope;
|
|
4
166
|
constructor({ name, scope }: {
|
|
5
167
|
name: string;
|
|
6
|
-
scope?: string;
|
|
168
|
+
scope?: string | ApiScope;
|
|
7
169
|
});
|
|
8
170
|
toJson(): Record<string, any>;
|
|
9
171
|
static fromJson(json: Record<string, any>): ParticipantGrant;
|
|
@@ -12,25 +174,35 @@ export declare class ParticipantToken {
|
|
|
12
174
|
name: string;
|
|
13
175
|
projectId?: string;
|
|
14
176
|
apiKeyId?: string;
|
|
177
|
+
version?: string;
|
|
15
178
|
grants: ParticipantGrant[];
|
|
16
179
|
extra?: Record<string, any>;
|
|
17
|
-
constructor({ name, projectId, apiKeyId, extra, grants, }: {
|
|
180
|
+
constructor({ name, projectId, apiKeyId, version, extra, grants, }: {
|
|
18
181
|
name: string;
|
|
19
182
|
projectId?: string;
|
|
20
183
|
apiKeyId?: string;
|
|
184
|
+
version?: string;
|
|
21
185
|
extra?: Record<string, any>;
|
|
22
186
|
grants?: ParticipantGrant[];
|
|
23
187
|
});
|
|
188
|
+
get role(): string;
|
|
24
189
|
get isAgent(): boolean;
|
|
190
|
+
get isUser(): boolean;
|
|
191
|
+
addTunnelGrant(ports: number[]): void;
|
|
25
192
|
addRoleGrant(role: string): void;
|
|
26
193
|
addRoomGrant(roomName: string): void;
|
|
194
|
+
addApiGrant(grant: ApiScope): void;
|
|
195
|
+
grantScope(name: string): string | ApiScope | undefined;
|
|
196
|
+
getApiGrant(): string | ApiScope | undefined;
|
|
27
197
|
toJson(): Record<string, any>;
|
|
28
|
-
toJwt({ token }
|
|
29
|
-
token
|
|
198
|
+
toJwt({ token, expiration, apiKey }?: {
|
|
199
|
+
token?: string;
|
|
200
|
+
expiration?: Date;
|
|
201
|
+
apiKey?: string;
|
|
30
202
|
}): Promise<string>;
|
|
31
203
|
static fromJson(json: Record<string, any>): ParticipantToken;
|
|
32
|
-
static fromJwt(jwtStr: string, options
|
|
33
|
-
token
|
|
204
|
+
static fromJwt(jwtStr: string, options?: {
|
|
205
|
+
token?: string;
|
|
34
206
|
verify?: boolean;
|
|
35
207
|
}): Promise<ParticipantToken>;
|
|
36
208
|
}
|
|
@@ -1,30 +1,275 @@
|
|
|
1
1
|
import { decodeJwt, jwtVerify, SignJWT } from "jose";
|
|
2
|
+
import { parseApiKey } from "./api_keys";
|
|
3
|
+
export class AgentsGrant {
|
|
4
|
+
constructor({ registerAgent, registerPublicToolkit, registerPrivateToolkit, call, useAgents, useTools, } = {}) {
|
|
5
|
+
this.registerAgent = registerAgent ?? true;
|
|
6
|
+
this.registerPublicToolkit = registerPublicToolkit ?? true;
|
|
7
|
+
this.registerPrivateToolkit = registerPrivateToolkit ?? true;
|
|
8
|
+
this.call = call ?? true;
|
|
9
|
+
this.useAgents = useAgents ?? true;
|
|
10
|
+
this.useTools = useTools ?? true;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class LivekitGrant {
|
|
14
|
+
constructor({ breakoutRooms } = {}) {
|
|
15
|
+
this.breakoutRooms = breakoutRooms;
|
|
16
|
+
}
|
|
17
|
+
canJoinBreakoutRoom(name) {
|
|
18
|
+
return !this.breakoutRooms || this.breakoutRooms.includes(name);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class QueuesGrant {
|
|
22
|
+
constructor({ send, receive, list } = {}) {
|
|
23
|
+
this.list = true;
|
|
24
|
+
this.send = send;
|
|
25
|
+
this.receive = receive;
|
|
26
|
+
this.list = list ?? true;
|
|
27
|
+
}
|
|
28
|
+
canSend(q) {
|
|
29
|
+
return !this.send || this.send.includes(q);
|
|
30
|
+
}
|
|
31
|
+
canReceive(q) {
|
|
32
|
+
return !this.receive || this.receive.includes(q);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class MessagingGrant {
|
|
36
|
+
constructor({ broadcast, list, send } = {}) {
|
|
37
|
+
this.broadcast = broadcast ?? true;
|
|
38
|
+
this.list = list ?? true;
|
|
39
|
+
this.send = send ?? true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export class TableGrant {
|
|
43
|
+
constructor({ name, write, read, alter }) {
|
|
44
|
+
this.write = false;
|
|
45
|
+
this.read = true;
|
|
46
|
+
this.alter = false;
|
|
47
|
+
this.name = name;
|
|
48
|
+
this.write = write ?? false;
|
|
49
|
+
this.read = read ?? true;
|
|
50
|
+
this.alter = alter ?? false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class DatabaseGrant {
|
|
54
|
+
constructor({ tables, listTables } = {}) {
|
|
55
|
+
this.listTables = true;
|
|
56
|
+
this.tables = tables;
|
|
57
|
+
this.listTables = listTables ?? true;
|
|
58
|
+
}
|
|
59
|
+
_match(table) {
|
|
60
|
+
if (!this.tables)
|
|
61
|
+
return undefined;
|
|
62
|
+
return this.tables.find(t => t.name === table);
|
|
63
|
+
}
|
|
64
|
+
canWrite(table) {
|
|
65
|
+
const t = this._match(table);
|
|
66
|
+
return t ? t.write : this.tables === undefined;
|
|
67
|
+
}
|
|
68
|
+
canRead(table) {
|
|
69
|
+
const t = this._match(table);
|
|
70
|
+
return t ? t.read : this.tables === undefined;
|
|
71
|
+
}
|
|
72
|
+
canAlter(table) {
|
|
73
|
+
const t = this._match(table);
|
|
74
|
+
return t ? t.alter : this.tables === undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export class SyncPathGrant {
|
|
78
|
+
constructor({ path, readOnly }) {
|
|
79
|
+
this.path = path;
|
|
80
|
+
this.readOnly = readOnly ?? false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export class SyncGrant {
|
|
84
|
+
constructor({ paths } = {}) {
|
|
85
|
+
this.paths = paths;
|
|
86
|
+
}
|
|
87
|
+
matches(p, path) {
|
|
88
|
+
return p.path === path || (p.path.endsWith("*") && path.startsWith(p.path.slice(0, -1)));
|
|
89
|
+
}
|
|
90
|
+
canRead(path) {
|
|
91
|
+
if (this.paths) {
|
|
92
|
+
return this.paths.some(p => this.matches(p, path));
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
canWrite(path) {
|
|
97
|
+
if (this.paths) {
|
|
98
|
+
const p = this.paths.find(pp => this.matches(pp, path));
|
|
99
|
+
return p ? !p.readOnly : false;
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export class StoragePathGrant {
|
|
105
|
+
constructor({ path, readOnly }) {
|
|
106
|
+
this.path = path;
|
|
107
|
+
this.readOnly = readOnly ?? false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export class StorageGrant {
|
|
111
|
+
constructor({ paths } = {}) {
|
|
112
|
+
this.paths = paths;
|
|
113
|
+
}
|
|
114
|
+
matches(p, path) {
|
|
115
|
+
return path.startsWith(p.path);
|
|
116
|
+
}
|
|
117
|
+
canRead(path) {
|
|
118
|
+
if (!this.paths)
|
|
119
|
+
return true;
|
|
120
|
+
return this.paths.some(p => this.matches(p, path));
|
|
121
|
+
}
|
|
122
|
+
canWrite(path) {
|
|
123
|
+
if (!this.paths)
|
|
124
|
+
return true;
|
|
125
|
+
const p = this.paths.find(pp => this.matches(pp, path));
|
|
126
|
+
return p ? !p.readOnly : false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export class ContainersGrant {
|
|
130
|
+
constructor({ logs, pull, run, useContainers } = {}) {
|
|
131
|
+
this.logs = logs ?? true;
|
|
132
|
+
this.pull = pull;
|
|
133
|
+
this.run = run;
|
|
134
|
+
this.useContainers = useContainers ?? true;
|
|
135
|
+
}
|
|
136
|
+
match(list, tag) {
|
|
137
|
+
if (!list) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return list.some(t => tag === t || tag.startsWith(t.endsWith("*") ? t.slice(0, -1) : t));
|
|
141
|
+
}
|
|
142
|
+
canPull(tag) {
|
|
143
|
+
return this.match(this.pull, tag);
|
|
144
|
+
}
|
|
145
|
+
canRun(tag) {
|
|
146
|
+
return this.match(this.run, tag);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export class DeveloperGrant {
|
|
150
|
+
constructor({ logs } = {}) {
|
|
151
|
+
this.logs = logs ?? true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export class AdminGrant {
|
|
155
|
+
}
|
|
156
|
+
export class SecretsGrant {
|
|
157
|
+
canRequestOauthToken(authorizationEndpoint) {
|
|
158
|
+
if (!this.requestOauthToken) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
return this.requestOauthToken.some(t => t === authorizationEndpoint || ((t.endsWith("*") && authorizationEndpoint.startsWith(t.slice(0, -1)))));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export class ApiScope {
|
|
165
|
+
constructor({ livekit, queues, messaging, database, sync, storage, containers, developer, agents, admin, secrets, } = {}) {
|
|
166
|
+
this.livekit = livekit;
|
|
167
|
+
this.queues = queues;
|
|
168
|
+
this.messaging = messaging;
|
|
169
|
+
this.database = database;
|
|
170
|
+
this.sync = sync;
|
|
171
|
+
this.storage = storage;
|
|
172
|
+
this.containers = containers;
|
|
173
|
+
this.developer = developer;
|
|
174
|
+
this.agents = agents;
|
|
175
|
+
this.admin = admin;
|
|
176
|
+
this.secrets = secrets;
|
|
177
|
+
}
|
|
178
|
+
static agentDefault() {
|
|
179
|
+
const s = new ApiScope();
|
|
180
|
+
s.livekit = new LivekitGrant();
|
|
181
|
+
s.queues = new QueuesGrant();
|
|
182
|
+
s.messaging = new MessagingGrant();
|
|
183
|
+
s.database = new DatabaseGrant();
|
|
184
|
+
s.sync = new SyncGrant();
|
|
185
|
+
s.storage = new StorageGrant();
|
|
186
|
+
s.containers = new ContainersGrant();
|
|
187
|
+
s.developer = new DeveloperGrant();
|
|
188
|
+
s.agents = new AgentsGrant();
|
|
189
|
+
return s;
|
|
190
|
+
}
|
|
191
|
+
static userDefault() {
|
|
192
|
+
const s = new ApiScope();
|
|
193
|
+
s.livekit = new LivekitGrant();
|
|
194
|
+
s.queues = new QueuesGrant();
|
|
195
|
+
s.messaging = new MessagingGrant();
|
|
196
|
+
s.database = new DatabaseGrant();
|
|
197
|
+
s.sync = new SyncGrant();
|
|
198
|
+
s.storage = new StorageGrant();
|
|
199
|
+
s.containers = new ContainersGrant();
|
|
200
|
+
s.developer = new DeveloperGrant();
|
|
201
|
+
s.agents = new AgentsGrant();
|
|
202
|
+
s.secrets = new SecretsGrant();
|
|
203
|
+
return s;
|
|
204
|
+
}
|
|
205
|
+
static full() {
|
|
206
|
+
const s = ApiScope.agentDefault();
|
|
207
|
+
s.admin = new AdminGrant();
|
|
208
|
+
return s;
|
|
209
|
+
}
|
|
210
|
+
toJSON() {
|
|
211
|
+
return { ...this };
|
|
212
|
+
}
|
|
213
|
+
static fromJSON(obj) {
|
|
214
|
+
return Object.assign(new ApiScope(), obj);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
2
217
|
export class ParticipantGrant {
|
|
3
218
|
constructor({ name, scope }) {
|
|
4
219
|
this.name = name;
|
|
5
220
|
this.scope = scope;
|
|
6
221
|
}
|
|
7
222
|
toJson() {
|
|
223
|
+
if (this.name === "api" && this.scope && typeof this.scope !== "string") {
|
|
224
|
+
return {
|
|
225
|
+
name: this.name,
|
|
226
|
+
scope: this.scope.toJSON(),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
8
229
|
return {
|
|
9
230
|
name: this.name,
|
|
10
231
|
scope: this.scope,
|
|
11
232
|
};
|
|
12
233
|
}
|
|
13
234
|
static fromJson(json) {
|
|
235
|
+
const name = json["name"];
|
|
236
|
+
let scope = json["scope"];
|
|
237
|
+
if (name === "api" && scope && typeof scope === "object") {
|
|
238
|
+
scope = ApiScope.fromJSON(scope);
|
|
239
|
+
}
|
|
14
240
|
return new ParticipantGrant({
|
|
15
|
-
name
|
|
16
|
-
scope
|
|
241
|
+
name,
|
|
242
|
+
scope,
|
|
17
243
|
});
|
|
18
244
|
}
|
|
19
245
|
}
|
|
246
|
+
function compareSemver(a, b) {
|
|
247
|
+
const pa = a.split(".").map(n => parseInt(n, 10));
|
|
248
|
+
const pb = b.split(".").map(n => parseInt(n, 10));
|
|
249
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
250
|
+
const x = pa[i] || 0, y = pb[i] || 0;
|
|
251
|
+
if (x !== y)
|
|
252
|
+
return x - y;
|
|
253
|
+
}
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
20
256
|
export class ParticipantToken {
|
|
21
|
-
constructor({ name, projectId, apiKeyId, extra, grants, }) {
|
|
257
|
+
constructor({ name, projectId, apiKeyId, version, extra, grants, }) {
|
|
22
258
|
this.name = name;
|
|
23
259
|
this.projectId = projectId;
|
|
24
260
|
this.apiKeyId = apiKeyId;
|
|
261
|
+
this.version = version;
|
|
25
262
|
this.extra = extra ?? {};
|
|
26
263
|
this.grants = grants ?? [];
|
|
27
264
|
}
|
|
265
|
+
get role() {
|
|
266
|
+
for (const g of this.grants) {
|
|
267
|
+
if (g.name === "role" && g.scope !== "user") {
|
|
268
|
+
return String(g.scope);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return "user";
|
|
272
|
+
}
|
|
28
273
|
get isAgent() {
|
|
29
274
|
for (const grant of this.grants) {
|
|
30
275
|
if (grant.name === "role" && grant.scope === "agent") {
|
|
@@ -33,44 +278,136 @@ export class ParticipantToken {
|
|
|
33
278
|
}
|
|
34
279
|
return false;
|
|
35
280
|
}
|
|
281
|
+
get isUser() {
|
|
282
|
+
for (const grant of this.grants) {
|
|
283
|
+
if (grant.name === "role" && grant.scope !== "user") {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
addTunnelGrant(ports) {
|
|
290
|
+
const portsStr = ports.join(",");
|
|
291
|
+
this.grants.push(new ParticipantGrant({ name: "tunnel_ports", scope: portsStr }));
|
|
292
|
+
}
|
|
36
293
|
addRoleGrant(role) {
|
|
37
294
|
this.grants.push(new ParticipantGrant({ name: "role", scope: role }));
|
|
38
295
|
}
|
|
39
296
|
addRoomGrant(roomName) {
|
|
40
297
|
this.grants.push(new ParticipantGrant({ name: "room", scope: roomName }));
|
|
41
298
|
}
|
|
299
|
+
addApiGrant(grant) {
|
|
300
|
+
this.grants.push(new ParticipantGrant({ name: "api", scope: grant }));
|
|
301
|
+
}
|
|
302
|
+
grantScope(name) {
|
|
303
|
+
return this.grants.find(g => g.name === name)?.scope;
|
|
304
|
+
}
|
|
305
|
+
getApiGrant() {
|
|
306
|
+
const api = this.grantScope("api");
|
|
307
|
+
if (api && typeof api !== "string") {
|
|
308
|
+
return api;
|
|
309
|
+
}
|
|
310
|
+
if (this.version && compareSemver(this.version, "0.6.0") < 0 && !api) {
|
|
311
|
+
return new ApiScope({
|
|
312
|
+
livekit: new LivekitGrant(),
|
|
313
|
+
queues: new QueuesGrant(),
|
|
314
|
+
messaging: new MessagingGrant(),
|
|
315
|
+
database: new DatabaseGrant(),
|
|
316
|
+
sync: new SyncGrant(),
|
|
317
|
+
storage: new StorageGrant(),
|
|
318
|
+
agents: new AgentsGrant(),
|
|
319
|
+
developer: new DeveloperGrant(),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
return api;
|
|
323
|
+
}
|
|
42
324
|
toJson() {
|
|
43
|
-
|
|
325
|
+
const base = {
|
|
44
326
|
name: this.name,
|
|
45
|
-
|
|
46
|
-
...(this.apiKeyId ? { kid: this.apiKeyId } : {}),
|
|
47
|
-
grants: this.grants.map((g) => g.toJson()),
|
|
327
|
+
grants: this.grants.map(g => g.toJson()),
|
|
48
328
|
};
|
|
329
|
+
if (this.projectId) {
|
|
330
|
+
base["sub"] = this.projectId;
|
|
331
|
+
}
|
|
332
|
+
if (this.apiKeyId) {
|
|
333
|
+
base["kid"] = this.apiKeyId;
|
|
334
|
+
}
|
|
335
|
+
if (this.version) {
|
|
336
|
+
base["version"] = this.version;
|
|
337
|
+
}
|
|
338
|
+
return base;
|
|
49
339
|
}
|
|
50
|
-
async toJwt({ token }) {
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
340
|
+
async toJwt({ token, expiration, apiKey } = {}) {
|
|
341
|
+
let apiGrant = null;
|
|
342
|
+
for (const g of this.grants) {
|
|
343
|
+
if (g.name === "api") {
|
|
344
|
+
apiGrant = g;
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (!apiGrant && this.version && compareSemver(this.version, "0.5.3") >= 0) {
|
|
349
|
+
console.error("ParticipantToken.toJwt: No API grant found, but version is >= 0.5.3. " +
|
|
350
|
+
"This may cause issues with older clients that expect an API grant.");
|
|
351
|
+
}
|
|
352
|
+
let resolvedSecret = token;
|
|
353
|
+
let resolvedKid = this.apiKeyId;
|
|
354
|
+
let resolvedSub = this.projectId;
|
|
355
|
+
const apiKeyValue = apiKey ?? process.env.MESHAGENT_API_KEY;
|
|
356
|
+
if (apiKeyValue) {
|
|
357
|
+
const parsed = parseApiKey(apiKeyValue);
|
|
358
|
+
resolvedSecret ?? (resolvedSecret = parsed.secret);
|
|
359
|
+
resolvedKid = parsed.id;
|
|
360
|
+
resolvedSub = parsed.projectId;
|
|
361
|
+
}
|
|
362
|
+
let usingDefaultSecret = false;
|
|
363
|
+
if (!resolvedSecret) {
|
|
364
|
+
const envSecret = process.env.MESHAGENT_SECRET;
|
|
365
|
+
if (!envSecret) {
|
|
366
|
+
throw new Error("ParticipantToken.toJwt: No secret provided. Pass `token`, `apiKey`, or set MESHAGENT_SECRET / MESHAGENT_API_KEY.");
|
|
367
|
+
}
|
|
368
|
+
resolvedSecret = envSecret;
|
|
369
|
+
usingDefaultSecret = true;
|
|
370
|
+
}
|
|
371
|
+
const secretKey = new TextEncoder().encode(resolvedSecret);
|
|
372
|
+
const payload = this.toJson();
|
|
373
|
+
if (resolvedSub) {
|
|
374
|
+
payload["sub"] = resolvedSub;
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
delete payload["sub"];
|
|
378
|
+
}
|
|
379
|
+
if (usingDefaultSecret) {
|
|
380
|
+
delete payload["kid"];
|
|
381
|
+
}
|
|
382
|
+
else if (resolvedKid) {
|
|
383
|
+
payload["kid"] = resolvedKid;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
delete payload["kid"];
|
|
387
|
+
}
|
|
388
|
+
if (expiration) {
|
|
389
|
+
payload.exp = Math.floor(expiration.getTime() / 1000);
|
|
390
|
+
}
|
|
391
|
+
const jwt = new SignJWT(payload)
|
|
392
|
+
.setProtectedHeader({ alg: "HS256", typ: "JWT" });
|
|
393
|
+
const jwtToken = await jwt.sign(secretKey);
|
|
394
|
+
return jwtToken;
|
|
60
395
|
}
|
|
61
396
|
static fromJson(json) {
|
|
62
|
-
const { name, sub, grants, kid, ...rest } = json;
|
|
397
|
+
const { name, sub, grants, kid, version, ...rest } = json;
|
|
63
398
|
const extra = { ...rest };
|
|
399
|
+
const v = version ? version : "0.5.3";
|
|
64
400
|
return new ParticipantToken({
|
|
65
401
|
name: name,
|
|
66
402
|
projectId: sub,
|
|
67
403
|
apiKeyId: kid,
|
|
404
|
+
version: v,
|
|
68
405
|
grants: grants?.map((g) => ParticipantGrant.fromJson(g)),
|
|
69
406
|
extra,
|
|
70
407
|
});
|
|
71
408
|
}
|
|
72
|
-
static async fromJwt(jwtStr, options) {
|
|
73
|
-
const { token, verify = true } = options;
|
|
409
|
+
static async fromJwt(jwtStr, options = {}) {
|
|
410
|
+
const { token, verify = true } = options ?? {};
|
|
74
411
|
if (verify) {
|
|
75
412
|
const secretKey = new TextEncoder().encode(token);
|
|
76
413
|
const { payload } = await jwtVerify(jwtStr, secretKey, {
|
|
@@ -35,10 +35,7 @@ export class StreamController {
|
|
|
35
35
|
},
|
|
36
36
|
async return() {
|
|
37
37
|
cleanup();
|
|
38
|
-
return {
|
|
39
|
-
done: true,
|
|
40
|
-
value: undefined
|
|
41
|
-
};
|
|
38
|
+
return { done: true, value: undefined };
|
|
42
39
|
},
|
|
43
40
|
async throw(e) {
|
|
44
41
|
cleanup();
|
|
@@ -55,10 +52,7 @@ export class StreamController {
|
|
|
55
52
|
if (sub.waiter) {
|
|
56
53
|
const w = sub.waiter;
|
|
57
54
|
sub.waiter = null;
|
|
58
|
-
|
|
59
|
-
w({ done: false, value });
|
|
60
|
-
}
|
|
61
|
-
catch { }
|
|
55
|
+
w({ done: false, value });
|
|
62
56
|
}
|
|
63
57
|
else {
|
|
64
58
|
sub.queue.push(value);
|
|
@@ -73,12 +67,7 @@ export class StreamController {
|
|
|
73
67
|
if (sub.waiter) {
|
|
74
68
|
const w = sub.waiter;
|
|
75
69
|
sub.waiter = null;
|
|
76
|
-
|
|
77
|
-
w({ done: true, value: undefined });
|
|
78
|
-
}
|
|
79
|
-
catch { }
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
70
|
+
w({ done: true, value: undefined });
|
|
82
71
|
}
|
|
83
72
|
}
|
|
84
73
|
}
|