@meshagent/meshagent 0.47.0 → 0.48.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 +12 -0
- package/dist/browser/agent.js +6 -6
- package/dist/browser/containers-client.d.ts +1 -0
- package/dist/browser/containers-client.js +34 -0
- package/dist/browser/entrypoint.d.ts +1 -0
- package/dist/browser/entrypoint.js +3 -3
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.js +1 -0
- package/dist/browser/meshagent-client.d.ts +9 -1
- package/dist/browser/meshagent-client.js +1 -0
- package/dist/browser/messaging-client.d.ts +72 -1
- package/dist/browser/messaging-client.js +302 -1
- package/dist/browser/mounts-client.d.ts +21 -0
- package/dist/browser/mounts-client.js +82 -0
- package/dist/browser/participant-token.d.ts +1 -0
- package/dist/browser/participant-token.js +3 -0
- package/dist/browser/room-client.d.ts +4 -1
- package/dist/browser/room-client.js +27 -12
- package/dist/esm/agent.js +6 -6
- package/dist/esm/containers-client.d.ts +1 -0
- package/dist/esm/containers-client.js +34 -0
- package/dist/esm/entrypoint.d.ts +1 -0
- package/dist/esm/entrypoint.js +3 -3
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/meshagent-client.d.ts +9 -1
- package/dist/esm/meshagent-client.js +1 -0
- package/dist/esm/messaging-client.d.ts +72 -1
- package/dist/esm/messaging-client.js +301 -1
- package/dist/esm/mounts-client.d.ts +21 -0
- package/dist/esm/mounts-client.js +78 -0
- package/dist/esm/participant-token.d.ts +1 -0
- package/dist/esm/participant-token.js +3 -0
- package/dist/esm/room-client.d.ts +4 -1
- package/dist/esm/room-client.js +27 -12
- package/dist/node/agent.js +6 -6
- package/dist/node/containers-client.d.ts +1 -0
- package/dist/node/containers-client.js +34 -0
- package/dist/node/entrypoint.d.ts +1 -0
- package/dist/node/entrypoint.js +3 -3
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/meshagent-client.d.ts +9 -1
- package/dist/node/meshagent-client.js +1 -0
- package/dist/node/messaging-client.d.ts +72 -1
- package/dist/node/messaging-client.js +302 -1
- package/dist/node/mounts-client.d.ts +21 -0
- package/dist/node/mounts-client.js +82 -0
- package/dist/node/participant-token.d.ts +1 -0
- package/dist/node/participant-token.js +3 -0
- package/dist/node/room-client.d.ts +4 -1
- package/dist/node/room-client.js +27 -12
- package/package.json +1 -1
|
@@ -9,6 +9,38 @@ const stream_controller_js_1 = require("./stream-controller.js");
|
|
|
9
9
|
function isRecord(value) {
|
|
10
10
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
11
|
}
|
|
12
|
+
function parseContainerMountSpec(value) {
|
|
13
|
+
if (value === undefined || value === null) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
if (!isRecord(value)) {
|
|
17
|
+
throw new room_server_client_js_1.RoomServerException("unexpected return type from containers.list");
|
|
18
|
+
}
|
|
19
|
+
const readMounts = (field, validate) => {
|
|
20
|
+
const raw = value[field];
|
|
21
|
+
if (raw === undefined || raw === null) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
if (!Array.isArray(raw) || !raw.every((mount) => isRecord(mount) && validate(mount))) {
|
|
25
|
+
throw new room_server_client_js_1.RoomServerException("unexpected return type from containers.list");
|
|
26
|
+
}
|
|
27
|
+
return raw;
|
|
28
|
+
};
|
|
29
|
+
const optionalMountFieldsAreValid = (mount) => (mount["subpath"] === undefined || mount["subpath"] === null || typeof mount["subpath"] === "string")
|
|
30
|
+
&& (mount["read_only"] === undefined || typeof mount["read_only"] === "boolean");
|
|
31
|
+
return {
|
|
32
|
+
room: readMounts("room", (mount) => typeof mount["path"] === "string" && optionalMountFieldsAreValid(mount)),
|
|
33
|
+
volumes: readMounts("volumes", (mount) => typeof mount["name"] === "string"
|
|
34
|
+
&& typeof mount["path"] === "string"
|
|
35
|
+
&& optionalMountFieldsAreValid(mount)),
|
|
36
|
+
empty_dirs: readMounts("empty_dirs", (mount) => typeof mount["path"] === "string"
|
|
37
|
+
&& (mount["read_only"] === undefined || typeof mount["read_only"] === "boolean")),
|
|
38
|
+
configs: readMounts("configs", (mount) => mount["path"] === undefined || mount["path"] === null || typeof mount["path"] === "string"),
|
|
39
|
+
files: readMounts("files", (mount) => typeof mount["path"] === "string"
|
|
40
|
+
&& (mount["read_only"] === undefined || typeof mount["read_only"] === "boolean")
|
|
41
|
+
&& (mount["text"] === undefined || mount["text"] === null || typeof mount["text"] === "string")),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
12
44
|
function toStringMapList(values) {
|
|
13
45
|
return Object.entries(values).map(([key, value]) => ({ key, value }));
|
|
14
46
|
}
|
|
@@ -904,6 +936,7 @@ class ContainersClient {
|
|
|
904
936
|
const imageIdRaw = entry["image_id"];
|
|
905
937
|
const portsRaw = entry["ports"];
|
|
906
938
|
const serviceIdRaw = entry["service_id"];
|
|
939
|
+
const mountsRaw = entry["mounts"];
|
|
907
940
|
const statsRaw = entry["stats"];
|
|
908
941
|
const exitStatusRaw = entry["exit_status"];
|
|
909
942
|
if (!Array.isArray(portsRaw) ||
|
|
@@ -964,6 +997,7 @@ class ContainersClient {
|
|
|
964
997
|
state,
|
|
965
998
|
private: privateFlag,
|
|
966
999
|
serviceId: typeof serviceIdRaw === "string" ? serviceIdRaw : undefined,
|
|
1000
|
+
mounts: parseContainerMountSpec(mountsRaw),
|
|
967
1001
|
stats,
|
|
968
1002
|
exitStatus,
|
|
969
1003
|
});
|
|
@@ -16,6 +16,7 @@ export var ServerXmlDocument: {
|
|
|
16
16
|
ignoreRemoteMapChanges: UndoManagerOptions;
|
|
17
17
|
captureTimeout: UndoManagerOptions;
|
|
18
18
|
afterTransactionHandler: (transaction: any) => void;
|
|
19
|
+
destroy(): void;
|
|
19
20
|
addToScope(ytypes: Array<any | {
|
|
20
21
|
gc: DocOpts;
|
|
21
22
|
gcFilter: DocOpts;
|
package/dist/node/entrypoint.js
CHANGED
|
@@ -3038,10 +3038,9 @@ var UndoManager = class extends ObservableV2 {
|
|
|
3038
3038
|
this.emit("stack-item-updated", changeEvent);
|
|
3039
3039
|
}
|
|
3040
3040
|
};
|
|
3041
|
+
this.destroy = this.destroy.bind(this);
|
|
3041
3042
|
this.doc.on("afterTransaction", this.afterTransactionHandler);
|
|
3042
|
-
this.doc.on("destroy",
|
|
3043
|
-
this.destroy();
|
|
3044
|
-
});
|
|
3043
|
+
this.doc.on("destroy", this.destroy);
|
|
3045
3044
|
}
|
|
3046
3045
|
addToScope(ytypes) {
|
|
3047
3046
|
const tmpSet = new Set(this.scope);
|
|
@@ -3110,6 +3109,7 @@ var UndoManager = class extends ObservableV2 {
|
|
|
3110
3109
|
destroy() {
|
|
3111
3110
|
this.trackedOrigins.delete(this);
|
|
3112
3111
|
this.doc.off("afterTransaction", this.afterTransactionHandler);
|
|
3112
|
+
this.doc.off("destroy", this.destroy);
|
|
3113
3113
|
super.destroy();
|
|
3114
3114
|
}
|
|
3115
3115
|
};
|
package/dist/node/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './document.js';
|
|
|
10
10
|
export * from './meshagent-client.js';
|
|
11
11
|
export * from './messaging-client.js';
|
|
12
12
|
export * from './memory-client.js';
|
|
13
|
+
export * from './mounts-client.js';
|
|
13
14
|
export * from './oauth-scopes.js';
|
|
14
15
|
export * from './participant-token.js';
|
|
15
16
|
export * from './participant.js';
|
package/dist/node/index.js
CHANGED
|
@@ -26,6 +26,7 @@ __exportStar(require("./document.js"), exports);
|
|
|
26
26
|
__exportStar(require("./meshagent-client.js"), exports);
|
|
27
27
|
__exportStar(require("./messaging-client.js"), exports);
|
|
28
28
|
__exportStar(require("./memory-client.js"), exports);
|
|
29
|
+
__exportStar(require("./mounts-client.js"), exports);
|
|
29
30
|
__exportStar(require("./oauth-scopes.js"), exports);
|
|
30
31
|
__exportStar(require("./participant-token.js"), exports);
|
|
31
32
|
__exportStar(require("./participant.js"), exports);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ApiScope } from "./participant-token.js";
|
|
2
2
|
export type ProjectRole = "member" | "admin" | "developer" | "room_creator" | "room_inventory" | "room_manager" | "session_inventory" | "agent_creator" | "agent_inventory" | "agent_manager" | "repository_creator" | "repository_inventory" | "repository_manager" | "feed_creator" | "feed_inventory" | "feed_manager" | "oauth_client_creator" | "oauth_client_inventory" | "oauth_client_manager" | "api_key_creator" | "api_key_inventory" | "api_key_manager" | "service_creator" | "service_inventory" | "service_manager" | "service_account_creator" | "service_account_inventory" | "service_account_manager" | "participant_token_creator" | "mailbox_creator" | "mailbox_inventory" | "mailbox_manager" | "route_creator" | "route_inventory" | "route_manager" | "scheduled_task_creator" | "scheduled_task_inventory" | "scheduled_task_manager" | "feed_subscription_creator" | "feed_subscription_inventory" | "feed_subscription_manager" | "llm_logger_creator" | "llm_logger_inventory" | "llm_logger_manager" | "llm_proxy_user" | "usage_reporter" | "billing_manager" | "group_manager";
|
|
3
3
|
export type ResourceRole = "viewer" | "operator" | "developer" | "admin";
|
|
4
|
+
export type RoomRole = "site_user" | ResourceRole;
|
|
4
5
|
export type FeedRole = "reader" | "subscriber" | "publisher" | "manager";
|
|
5
6
|
export type SecretRole = "use_proxy";
|
|
6
|
-
export type AccessRole = ProjectRole |
|
|
7
|
+
export type AccessRole = ProjectRole | RoomRole | FeedRole | SecretRole | "list";
|
|
7
8
|
export type AccessSubjectType = "user" | "group" | "agent" | "service_account" | "userset";
|
|
8
9
|
export type AccessResourceType = "project" | "room" | "agent" | "group" | "repository" | "feed" | "secret";
|
|
9
10
|
export interface AccessSubject {
|
|
@@ -234,6 +235,12 @@ export interface RoomStorageMountSpec {
|
|
|
234
235
|
subpath?: string | null;
|
|
235
236
|
read_only?: boolean;
|
|
236
237
|
}
|
|
238
|
+
export interface VolumeStorageMountSpec {
|
|
239
|
+
name: string;
|
|
240
|
+
path: string;
|
|
241
|
+
subpath?: string | null;
|
|
242
|
+
read_only?: boolean;
|
|
243
|
+
}
|
|
237
244
|
export interface EmptyDirMountSpec {
|
|
238
245
|
path: string;
|
|
239
246
|
read_only?: boolean;
|
|
@@ -248,6 +255,7 @@ export interface FileMountSpec {
|
|
|
248
255
|
}
|
|
249
256
|
export interface ContainerMountSpec {
|
|
250
257
|
room?: RoomStorageMountSpec[];
|
|
258
|
+
volumes?: VolumeStorageMountSpec[];
|
|
251
259
|
empty_dirs?: EmptyDirMountSpec[];
|
|
252
260
|
configs?: ConfigMountSpec[];
|
|
253
261
|
files?: FileMountSpec[];
|
|
@@ -659,6 +659,7 @@ class Meshagent {
|
|
|
659
659
|
const parsedSubject = this.parseAccessSubject(data.subject);
|
|
660
660
|
const parsedDirectRoles = Array.isArray(data.direct_roles)
|
|
661
661
|
? data.direct_roles.filter((item) => item === "member" ||
|
|
662
|
+
item === "site_user" ||
|
|
662
663
|
item === "viewer" ||
|
|
663
664
|
item === "operator" ||
|
|
664
665
|
item === "developer" ||
|
|
@@ -1,8 +1,72 @@
|
|
|
1
1
|
import { EventEmitter } from "./event-emitter.js";
|
|
2
2
|
import { Participant, RemoteParticipant } from "./participant.js";
|
|
3
|
+
import { Content } from "./response.js";
|
|
3
4
|
import { RoomClient } from "./room-client.js";
|
|
4
|
-
import { RoomMessageEvent } from "./room-event.js";
|
|
5
|
+
import { RoomMessage, RoomMessageEvent } from "./room-event.js";
|
|
5
6
|
type MessagePayload = Record<string, unknown>;
|
|
7
|
+
export type MessagingStreamEvent = {
|
|
8
|
+
kind: "message";
|
|
9
|
+
message: RoomMessage;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "client_disconnected";
|
|
12
|
+
streamId: string;
|
|
13
|
+
participantId: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "closed";
|
|
16
|
+
streamId: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
message?: string;
|
|
19
|
+
};
|
|
20
|
+
declare class MessagingStreamInput {
|
|
21
|
+
private readonly items;
|
|
22
|
+
private signal;
|
|
23
|
+
private active;
|
|
24
|
+
private closed;
|
|
25
|
+
private error;
|
|
26
|
+
enqueue(content: Content, { wait }?: {
|
|
27
|
+
wait?: boolean;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
close(error?: unknown): void;
|
|
30
|
+
fail(error: unknown): void;
|
|
31
|
+
stream(): AsyncIterable<Content>;
|
|
32
|
+
}
|
|
33
|
+
export declare class MessagingStream implements AsyncIterable<MessagingStreamEvent> {
|
|
34
|
+
readonly streamId: string;
|
|
35
|
+
readonly remoteParticipantId: string;
|
|
36
|
+
private readonly input;
|
|
37
|
+
private readonly output;
|
|
38
|
+
private readonly inputDone;
|
|
39
|
+
private readonly onClosed;
|
|
40
|
+
private readonly events;
|
|
41
|
+
private eventSignal;
|
|
42
|
+
private state;
|
|
43
|
+
constructor({ streamId, remoteParticipantId, input, output, inputClosed, onClosed, }: {
|
|
44
|
+
streamId: string;
|
|
45
|
+
remoteParticipantId: string;
|
|
46
|
+
input: MessagingStreamInput;
|
|
47
|
+
output: AsyncIterator<Content>;
|
|
48
|
+
inputClosed?: Promise<void>;
|
|
49
|
+
onClosed: () => void;
|
|
50
|
+
});
|
|
51
|
+
get closed(): boolean;
|
|
52
|
+
private push;
|
|
53
|
+
private finish;
|
|
54
|
+
private consumeOutput;
|
|
55
|
+
private content;
|
|
56
|
+
sendMessageNowait(params: {
|
|
57
|
+
type: string;
|
|
58
|
+
message: MessagePayload;
|
|
59
|
+
attachment?: Uint8Array;
|
|
60
|
+
}): void;
|
|
61
|
+
sendMessage(params: {
|
|
62
|
+
type: string;
|
|
63
|
+
message: MessagePayload;
|
|
64
|
+
attachment?: Uint8Array;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
close(): Promise<void>;
|
|
67
|
+
clientDisconnected(participantId: string): void;
|
|
68
|
+
[Symbol.asyncIterator](): AsyncIterator<MessagingStreamEvent>;
|
|
69
|
+
}
|
|
6
70
|
export declare class MessagingClient extends EventEmitter<RoomMessageEvent> {
|
|
7
71
|
private readonly client;
|
|
8
72
|
private readonly _messageHandler;
|
|
@@ -11,6 +75,7 @@ export declare class MessagingClient extends EventEmitter<RoomMessageEvent> {
|
|
|
11
75
|
private _messageQueued;
|
|
12
76
|
private _sendTask;
|
|
13
77
|
private readonly _sendOperations;
|
|
78
|
+
private readonly _streams;
|
|
14
79
|
private _messageQueueClosed;
|
|
15
80
|
private _desiredEnabled;
|
|
16
81
|
private _online;
|
|
@@ -64,6 +129,12 @@ export declare class MessagingClient extends EventEmitter<RoomMessageEvent> {
|
|
|
64
129
|
message: MessagePayload;
|
|
65
130
|
attachment?: Uint8Array;
|
|
66
131
|
}): Promise<void>;
|
|
132
|
+
stream({ to, type, message, attachment, }: {
|
|
133
|
+
to: Participant;
|
|
134
|
+
type: string;
|
|
135
|
+
message: MessagePayload;
|
|
136
|
+
attachment?: Uint8Array;
|
|
137
|
+
}): Promise<MessagingStream>;
|
|
67
138
|
getParticipants(): RemoteParticipant[];
|
|
68
139
|
getParticipant(id: string): RemoteParticipant | null;
|
|
69
140
|
getParticipantByName(name: string): RemoteParticipant | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MessagingClient = void 0;
|
|
3
|
+
exports.MessagingClient = exports.MessagingStream = void 0;
|
|
4
4
|
const completer_js_1 = require("./completer.js");
|
|
5
5
|
const event_emitter_js_1 = require("./event-emitter.js");
|
|
6
6
|
const participant_js_1 = require("./participant.js");
|
|
@@ -22,6 +22,256 @@ function bytesToBase64(bytes) {
|
|
|
22
22
|
}
|
|
23
23
|
return globalScope.btoa(binary);
|
|
24
24
|
}
|
|
25
|
+
function base64ToBytes(value) {
|
|
26
|
+
if (globalScope.Buffer != null) {
|
|
27
|
+
return new Uint8Array(globalScope.Buffer.from(value, "base64"));
|
|
28
|
+
}
|
|
29
|
+
const atob = globalThis.atob;
|
|
30
|
+
if (atob == null) {
|
|
31
|
+
throw new Error("base64 decoding is not available in this runtime");
|
|
32
|
+
}
|
|
33
|
+
const binary = atob(value);
|
|
34
|
+
return Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
35
|
+
}
|
|
36
|
+
class MessagingStreamInput {
|
|
37
|
+
constructor() {
|
|
38
|
+
this.items = [];
|
|
39
|
+
this.signal = null;
|
|
40
|
+
this.active = null;
|
|
41
|
+
this.closed = false;
|
|
42
|
+
this.error = null;
|
|
43
|
+
}
|
|
44
|
+
enqueue(content, { wait = false } = {}) {
|
|
45
|
+
if (this.closed) {
|
|
46
|
+
return Promise.reject(this.error ?? new room_server_client_js_1.RoomServerException("the messaging stream is closed"));
|
|
47
|
+
}
|
|
48
|
+
const sent = wait ? new completer_js_1.Completer() : undefined;
|
|
49
|
+
this.items.push({ content, sent });
|
|
50
|
+
this.signal?.resolve();
|
|
51
|
+
this.signal = null;
|
|
52
|
+
return sent?.fut ?? Promise.resolve();
|
|
53
|
+
}
|
|
54
|
+
close(error = new room_server_client_js_1.RoomServerException("the messaging stream is closed")) {
|
|
55
|
+
if (this.closed) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.closed = true;
|
|
59
|
+
this.error = error;
|
|
60
|
+
this.active?.sent?.reject(error);
|
|
61
|
+
this.active = null;
|
|
62
|
+
for (const item of this.items.splice(0)) {
|
|
63
|
+
item.sent?.reject(error);
|
|
64
|
+
}
|
|
65
|
+
this.signal?.resolve();
|
|
66
|
+
this.signal = null;
|
|
67
|
+
}
|
|
68
|
+
fail(error) {
|
|
69
|
+
this.close(error);
|
|
70
|
+
}
|
|
71
|
+
async *stream() {
|
|
72
|
+
try {
|
|
73
|
+
while (true) {
|
|
74
|
+
while (this.items.length === 0 && !this.closed) {
|
|
75
|
+
this.signal ?? (this.signal = new completer_js_1.Completer());
|
|
76
|
+
await this.signal.fut;
|
|
77
|
+
}
|
|
78
|
+
const item = this.items.shift();
|
|
79
|
+
if (item == null) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.active = item;
|
|
83
|
+
yield item.content;
|
|
84
|
+
item.sent?.resolve();
|
|
85
|
+
this.active = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
if (this.active != null && this.closed) {
|
|
90
|
+
this.active.sent?.reject(this.error ?? new room_server_client_js_1.RoomServerException("the messaging stream is closed"));
|
|
91
|
+
this.active = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
class MessagingStream {
|
|
97
|
+
constructor({ streamId, remoteParticipantId, input, output, inputClosed, onClosed, }) {
|
|
98
|
+
this.events = [];
|
|
99
|
+
this.eventSignal = null;
|
|
100
|
+
this.state = "accepted";
|
|
101
|
+
this.streamId = streamId;
|
|
102
|
+
this.remoteParticipantId = remoteParticipantId;
|
|
103
|
+
this.input = input;
|
|
104
|
+
this.output = output;
|
|
105
|
+
this.inputDone = Promise.resolve(inputClosed).catch((error) => {
|
|
106
|
+
this.input.fail(error);
|
|
107
|
+
this.push({
|
|
108
|
+
kind: "closed",
|
|
109
|
+
streamId: this.streamId,
|
|
110
|
+
reason: "error",
|
|
111
|
+
message: error instanceof Error ? error.message : String(error),
|
|
112
|
+
});
|
|
113
|
+
void this.output.return?.();
|
|
114
|
+
this.finish();
|
|
115
|
+
});
|
|
116
|
+
this.onClosed = onClosed;
|
|
117
|
+
void this.consumeOutput();
|
|
118
|
+
}
|
|
119
|
+
get closed() {
|
|
120
|
+
return this.state === "terminal";
|
|
121
|
+
}
|
|
122
|
+
push(event) {
|
|
123
|
+
if (this.state !== "accepted") {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.events.push(event);
|
|
127
|
+
this.eventSignal?.resolve();
|
|
128
|
+
this.eventSignal = null;
|
|
129
|
+
}
|
|
130
|
+
finish() {
|
|
131
|
+
if (this.state === "terminal") {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.state = "terminal";
|
|
135
|
+
this.input.close();
|
|
136
|
+
this.eventSignal?.resolve();
|
|
137
|
+
this.eventSignal = null;
|
|
138
|
+
void this.inputDone.finally(this.onClosed);
|
|
139
|
+
}
|
|
140
|
+
async consumeOutput() {
|
|
141
|
+
try {
|
|
142
|
+
while (true) {
|
|
143
|
+
const next = await this.output.next();
|
|
144
|
+
if (next.done) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (next.value instanceof response_js_1.ControlContent && next.value.method === "close") {
|
|
148
|
+
this.push({
|
|
149
|
+
kind: "client_disconnected",
|
|
150
|
+
streamId: this.streamId,
|
|
151
|
+
participantId: this.remoteParticipantId,
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!(next.value instanceof response_js_1.JsonContent)) {
|
|
156
|
+
throw new room_server_client_js_1.RoomServerException("unexpected chunk from messaging.stream");
|
|
157
|
+
}
|
|
158
|
+
const value = next.value.json;
|
|
159
|
+
const kind = value["kind"];
|
|
160
|
+
if (kind === "message") {
|
|
161
|
+
const type = value["type"];
|
|
162
|
+
const message = value["message"];
|
|
163
|
+
if (typeof type !== "string" || typeof message !== "object" || message == null || Array.isArray(message)) {
|
|
164
|
+
throw new room_server_client_js_1.RoomServerException("invalid message chunk from messaging.stream");
|
|
165
|
+
}
|
|
166
|
+
const encodedAttachment = value["attachment_base64"];
|
|
167
|
+
this.push({
|
|
168
|
+
kind: "message",
|
|
169
|
+
message: new room_event_js_1.RoomMessage({
|
|
170
|
+
fromParticipantId: this.remoteParticipantId,
|
|
171
|
+
type,
|
|
172
|
+
message: message,
|
|
173
|
+
attachment: typeof encodedAttachment === "string" && encodedAttachment !== ""
|
|
174
|
+
? base64ToBytes(encodedAttachment)
|
|
175
|
+
: undefined,
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
else if (kind === "client_disconnected" && typeof value["participant_id"] === "string") {
|
|
180
|
+
this.push({
|
|
181
|
+
kind,
|
|
182
|
+
streamId: this.streamId,
|
|
183
|
+
participantId: value["participant_id"],
|
|
184
|
+
});
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
else if (kind === "closed") {
|
|
188
|
+
this.push({
|
|
189
|
+
kind,
|
|
190
|
+
streamId: this.streamId,
|
|
191
|
+
reason: typeof value["reason"] === "string" ? value["reason"] : "closed",
|
|
192
|
+
message: typeof value["message"] === "string" ? value["message"] : undefined,
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
throw new room_server_client_js_1.RoomServerException("unexpected chunk from messaging.stream");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
this.input.fail(error);
|
|
203
|
+
this.push({
|
|
204
|
+
kind: "closed",
|
|
205
|
+
streamId: this.streamId,
|
|
206
|
+
reason: "error",
|
|
207
|
+
message: error instanceof Error ? error.message : String(error),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
this.finish();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
content({ type, message, attachment, }) {
|
|
215
|
+
return new response_js_1.JsonContent({
|
|
216
|
+
json: {
|
|
217
|
+
type,
|
|
218
|
+
message_json: JSON.stringify(message),
|
|
219
|
+
...(attachment == null ? {} : { attachment_base64: bytesToBase64(attachment) }),
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
sendMessageNowait(params) {
|
|
224
|
+
if (this.state !== "accepted") {
|
|
225
|
+
throw new room_server_client_js_1.RoomServerException("the messaging stream is closed");
|
|
226
|
+
}
|
|
227
|
+
void this.input.enqueue(this.content(params));
|
|
228
|
+
}
|
|
229
|
+
async sendMessage(params) {
|
|
230
|
+
if (this.state !== "accepted") {
|
|
231
|
+
throw new room_server_client_js_1.RoomServerException("the messaging stream is closed");
|
|
232
|
+
}
|
|
233
|
+
await this.input.enqueue(this.content(params), { wait: true });
|
|
234
|
+
}
|
|
235
|
+
async close() {
|
|
236
|
+
if (this.state === "terminal") {
|
|
237
|
+
await this.inputDone;
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
this.input.close();
|
|
241
|
+
try {
|
|
242
|
+
await this.inputDone;
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
await this.output.return?.();
|
|
246
|
+
this.finish();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
clientDisconnected(participantId) {
|
|
250
|
+
if (this.state === "terminal") {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
this.push({
|
|
254
|
+
kind: "client_disconnected",
|
|
255
|
+
streamId: this.streamId,
|
|
256
|
+
participantId,
|
|
257
|
+
});
|
|
258
|
+
this.finish();
|
|
259
|
+
}
|
|
260
|
+
async *[Symbol.asyncIterator]() {
|
|
261
|
+
while (true) {
|
|
262
|
+
while (this.events.length === 0 && this.state !== "terminal") {
|
|
263
|
+
this.eventSignal ?? (this.eventSignal = new completer_js_1.Completer());
|
|
264
|
+
await this.eventSignal.fut;
|
|
265
|
+
}
|
|
266
|
+
const event = this.events.shift();
|
|
267
|
+
if (event == null) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
yield event;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
exports.MessagingStream = MessagingStream;
|
|
25
275
|
class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
26
276
|
constructor({ room }) {
|
|
27
277
|
super();
|
|
@@ -31,6 +281,7 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
31
281
|
this._messageQueued = null;
|
|
32
282
|
this._sendTask = null;
|
|
33
283
|
this._sendOperations = new Set();
|
|
284
|
+
this._streams = new Set();
|
|
34
285
|
this._messageQueueClosed = false;
|
|
35
286
|
this._desiredEnabled = false;
|
|
36
287
|
this._online = false;
|
|
@@ -96,6 +347,7 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
96
347
|
await sendTask;
|
|
97
348
|
}
|
|
98
349
|
await Promise.all(this._sendOperations);
|
|
350
|
+
await Promise.all([...this._streams].map(async (stream) => stream.close()));
|
|
99
351
|
this._desiredEnabled = false;
|
|
100
352
|
this._clearCurrentConnectionState();
|
|
101
353
|
}
|
|
@@ -159,6 +411,9 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
159
411
|
}
|
|
160
412
|
}
|
|
161
413
|
_onRoomDisconnect({ reason: _reason }) {
|
|
414
|
+
for (const stream of [...this._streams]) {
|
|
415
|
+
stream.clientDisconnected(this.client.localParticipant?.id ?? stream.remoteParticipantId);
|
|
416
|
+
}
|
|
162
417
|
this._clearCurrentConnectionState();
|
|
163
418
|
}
|
|
164
419
|
_onRoomReconnect() {
|
|
@@ -351,6 +606,49 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
351
606
|
throw error;
|
|
352
607
|
}
|
|
353
608
|
}
|
|
609
|
+
async stream({ to, type, message, attachment, }) {
|
|
610
|
+
const input = new MessagingStreamInput();
|
|
611
|
+
void input.enqueue(new response_js_1.JsonContent({
|
|
612
|
+
json: {
|
|
613
|
+
to_participant_id: to.id,
|
|
614
|
+
type,
|
|
615
|
+
message_json: JSON.stringify(message),
|
|
616
|
+
...(attachment == null ? {} : { attachment_base64: bytesToBase64(attachment) }),
|
|
617
|
+
},
|
|
618
|
+
}));
|
|
619
|
+
const outputResult = await this.client.invokeToolCall({
|
|
620
|
+
toolkit: "messaging",
|
|
621
|
+
tool: "stream",
|
|
622
|
+
input: input.stream(),
|
|
623
|
+
streamInput: true,
|
|
624
|
+
});
|
|
625
|
+
if (outputResult.kind !== "stream") {
|
|
626
|
+
input.close();
|
|
627
|
+
throw new room_server_client_js_1.RoomServerException("unexpected return type from messaging.stream");
|
|
628
|
+
}
|
|
629
|
+
const outputIterable = outputResult.stream;
|
|
630
|
+
const output = outputIterable[Symbol.asyncIterator]();
|
|
631
|
+
const accepted = await output.next();
|
|
632
|
+
if (accepted.done
|
|
633
|
+
|| !(accepted.value instanceof response_js_1.JsonContent)
|
|
634
|
+
|| accepted.value.json["kind"] !== "accepted"
|
|
635
|
+
|| typeof accepted.value.json["stream_id"] !== "string") {
|
|
636
|
+
input.close();
|
|
637
|
+
await output.return?.();
|
|
638
|
+
throw new room_server_client_js_1.RoomServerException("messaging.stream did not acknowledge acceptance");
|
|
639
|
+
}
|
|
640
|
+
let stream;
|
|
641
|
+
stream = new MessagingStream({
|
|
642
|
+
streamId: accepted.value.json["stream_id"],
|
|
643
|
+
remoteParticipantId: to.id,
|
|
644
|
+
input,
|
|
645
|
+
output,
|
|
646
|
+
inputClosed: outputResult.inputClosed,
|
|
647
|
+
onClosed: () => this._streams.delete(stream),
|
|
648
|
+
});
|
|
649
|
+
this._streams.add(stream);
|
|
650
|
+
return stream;
|
|
651
|
+
}
|
|
354
652
|
getParticipants() {
|
|
355
653
|
return this.remoteParticipants;
|
|
356
654
|
}
|
|
@@ -444,6 +742,9 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
444
742
|
this._wakeMessageQueue();
|
|
445
743
|
this._drainQueuedMessages({ error });
|
|
446
744
|
this._desiredEnabled = false;
|
|
745
|
+
for (const stream of [...this._streams]) {
|
|
746
|
+
stream.clientDisconnected(this.client.localParticipant?.id ?? stream.remoteParticipantId);
|
|
747
|
+
}
|
|
447
748
|
this._clearCurrentConnectionState();
|
|
448
749
|
this.client.protocol.removeHandler("messaging.send", this._messageHandler);
|
|
449
750
|
super.dispose();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RoomClient } from "./room-client.js";
|
|
2
|
+
export interface MountedVolumeConsumer {
|
|
3
|
+
kind: "room" | "container";
|
|
4
|
+
containerId?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface MountedVolume {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
required: boolean;
|
|
10
|
+
description: string;
|
|
11
|
+
metadata: Record<string, unknown>;
|
|
12
|
+
annotations: Record<string, string>;
|
|
13
|
+
storageClass: "standard" | "juice" | "zerofs";
|
|
14
|
+
maxSizeMb?: number;
|
|
15
|
+
consumers: MountedVolumeConsumer[];
|
|
16
|
+
}
|
|
17
|
+
export declare class MountsClient {
|
|
18
|
+
private readonly room;
|
|
19
|
+
constructor(room: RoomClient);
|
|
20
|
+
list(): Promise<MountedVolume[]>;
|
|
21
|
+
}
|