@meshagent/meshagent 0.46.4 → 0.47.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 +10 -2
- package/dist/browser/agent.js +6 -6
- package/dist/browser/meshagent-client.d.ts +10 -1
- package/dist/browser/meshagent-client.js +28 -0
- package/dist/browser/messaging-client.d.ts +74 -1
- package/dist/browser/messaging-client.js +350 -28
- package/dist/browser/participant-token.d.ts +1 -0
- package/dist/browser/participant-token.js +3 -0
- package/dist/browser/room-client.d.ts +5 -2
- package/dist/browser/room-client.js +27 -12
- package/dist/esm/agent.js +6 -6
- package/dist/esm/meshagent-client.d.ts +10 -1
- package/dist/esm/meshagent-client.js +28 -0
- package/dist/esm/messaging-client.d.ts +74 -1
- package/dist/esm/messaging-client.js +349 -28
- package/dist/esm/participant-token.d.ts +1 -0
- package/dist/esm/participant-token.js +3 -0
- package/dist/esm/room-client.d.ts +5 -2
- package/dist/esm/room-client.js +27 -12
- package/dist/node/agent.js +6 -6
- package/dist/node/meshagent-client.d.ts +10 -1
- package/dist/node/meshagent-client.js +28 -0
- package/dist/node/messaging-client.d.ts +74 -1
- package/dist/node/messaging-client.js +350 -28
- package/dist/node/participant-token.d.ts +1 -0
- package/dist/node/participant-token.js +3 -0
- package/dist/node/room-client.d.ts +5 -2
- package/dist/node/room-client.js +27 -12
- package/package.json +1 -1
|
@@ -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();
|
|
@@ -30,6 +280,8 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
30
280
|
this._messageQueue = [];
|
|
31
281
|
this._messageQueued = null;
|
|
32
282
|
this._sendTask = null;
|
|
283
|
+
this._sendOperations = new Set();
|
|
284
|
+
this._streams = new Set();
|
|
33
285
|
this._messageQueueClosed = false;
|
|
34
286
|
this._desiredEnabled = false;
|
|
35
287
|
this._online = false;
|
|
@@ -59,11 +311,12 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
59
311
|
}
|
|
60
312
|
return input;
|
|
61
313
|
}
|
|
62
|
-
async _invoke({ operation, input, }) {
|
|
314
|
+
async _invoke({ operation, input, afterSend, }) {
|
|
63
315
|
await this.client.invokeContent({
|
|
64
316
|
toolkit: "messaging",
|
|
65
317
|
tool: operation,
|
|
66
318
|
input: new response_js_1.JsonContent({ json: input }),
|
|
319
|
+
afterSend,
|
|
67
320
|
});
|
|
68
321
|
}
|
|
69
322
|
_invokeNowait({ operation, input, }) {
|
|
@@ -93,6 +346,8 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
93
346
|
if (sendTask != null) {
|
|
94
347
|
await sendTask;
|
|
95
348
|
}
|
|
349
|
+
await Promise.all(this._sendOperations);
|
|
350
|
+
await Promise.all([...this._streams].map(async (stream) => stream.close()));
|
|
96
351
|
this._desiredEnabled = false;
|
|
97
352
|
this._clearCurrentConnectionState();
|
|
98
353
|
}
|
|
@@ -156,6 +411,9 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
156
411
|
}
|
|
157
412
|
}
|
|
158
413
|
_onRoomDisconnect({ reason: _reason }) {
|
|
414
|
+
for (const stream of [...this._streams]) {
|
|
415
|
+
stream.clientDisconnected(this.client.localParticipant?.id ?? stream.remoteParticipantId);
|
|
416
|
+
}
|
|
159
417
|
this._clearCurrentConnectionState();
|
|
160
418
|
}
|
|
161
419
|
_onRoomReconnect() {
|
|
@@ -238,34 +496,52 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
238
496
|
});
|
|
239
497
|
continue;
|
|
240
498
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
499
|
+
const dispatched = new completer_js_1.Completer();
|
|
500
|
+
const operation = this._sendQueuedMessage({
|
|
501
|
+
message,
|
|
502
|
+
resolvedTo,
|
|
503
|
+
afterSend: () => dispatched.resolve(),
|
|
504
|
+
});
|
|
505
|
+
this._sendOperations.add(operation);
|
|
506
|
+
void operation.then(() => {
|
|
507
|
+
this._sendOperations.delete(operation);
|
|
508
|
+
if (!dispatched.completed)
|
|
509
|
+
dispatched.resolve();
|
|
510
|
+
}, () => {
|
|
511
|
+
this._sendOperations.delete(operation);
|
|
512
|
+
if (!dispatched.completed)
|
|
513
|
+
dispatched.resolve();
|
|
514
|
+
});
|
|
515
|
+
await dispatched.fut;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async _sendQueuedMessage({ message, resolvedTo, afterSend, }) {
|
|
519
|
+
try {
|
|
520
|
+
await this._invoke({
|
|
521
|
+
operation: "send",
|
|
522
|
+
input: this._messageInput({
|
|
523
|
+
toParticipantId: resolvedTo.id,
|
|
524
|
+
type: message.type,
|
|
525
|
+
message: message.message,
|
|
526
|
+
attachment: message.attachment,
|
|
527
|
+
}),
|
|
528
|
+
afterSend,
|
|
529
|
+
});
|
|
530
|
+
if (message.completer != null && !message.completer.completed) {
|
|
531
|
+
message.completer.complete();
|
|
254
532
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
this._dropQueuedMessage({ message, error: wrapped });
|
|
264
|
-
continue;
|
|
265
|
-
}
|
|
266
|
-
if (message.completer != null && !message.completer.completed) {
|
|
267
|
-
message.completer.completeError(error);
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
if (error instanceof room_server_client_js_1.RoomServerException) {
|
|
536
|
+
const wrapped = this.client._coerceMessageSendError(error);
|
|
537
|
+
if (wrapped.message === "the participant was not found") {
|
|
538
|
+
this._markParticipantOffline(message.to);
|
|
268
539
|
}
|
|
540
|
+
this._dropQueuedMessage({ message, error: wrapped });
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
if (message.completer != null && !message.completer.completed) {
|
|
544
|
+
message.completer.completeError(error);
|
|
269
545
|
}
|
|
270
546
|
}
|
|
271
547
|
}
|
|
@@ -330,6 +606,49 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
330
606
|
throw error;
|
|
331
607
|
}
|
|
332
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
|
+
}
|
|
333
652
|
getParticipants() {
|
|
334
653
|
return this.remoteParticipants;
|
|
335
654
|
}
|
|
@@ -423,6 +742,9 @@ class MessagingClient extends event_emitter_js_1.EventEmitter {
|
|
|
423
742
|
this._wakeMessageQueue();
|
|
424
743
|
this._drainQueuedMessages({ error });
|
|
425
744
|
this._desiredEnabled = false;
|
|
745
|
+
for (const stream of [...this._streams]) {
|
|
746
|
+
stream.clientDisconnected(this.client.localParticipant?.id ?? stream.remoteParticipantId);
|
|
747
|
+
}
|
|
426
748
|
this._clearCurrentConnectionState();
|
|
427
749
|
this.client.protocol.removeHandler("messaging.send", this._messageHandler);
|
|
428
750
|
super.dispose();
|
|
@@ -404,6 +404,7 @@ export declare class ParticipantToken {
|
|
|
404
404
|
addTunnelGrant(ports: number[]): void;
|
|
405
405
|
addRoleGrant(role: string): void;
|
|
406
406
|
addRoomGrant(roomName: string): void;
|
|
407
|
+
addSiteGrant(roomName: string): void;
|
|
407
408
|
addApiGrant(grant: ApiScope): void;
|
|
408
409
|
grantScope(name: string): string | ApiScope | undefined;
|
|
409
410
|
getApiGrant(): ApiScope | undefined;
|
|
@@ -1323,6 +1323,9 @@ class ParticipantToken {
|
|
|
1323
1323
|
addRoomGrant(roomName) {
|
|
1324
1324
|
this.grants.push(new ParticipantGrant({ name: "room", scope: roomName }));
|
|
1325
1325
|
}
|
|
1326
|
+
addSiteGrant(roomName) {
|
|
1327
|
+
this.grants.push(new ParticipantGrant({ name: "site", scope: roomName }));
|
|
1328
|
+
}
|
|
1326
1329
|
addApiGrant(grant) {
|
|
1327
1330
|
for (const existingGrant of this.grants) {
|
|
1328
1331
|
if (existingGrant.name === "api") {
|
|
@@ -189,7 +189,8 @@ export declare class RoomClient {
|
|
|
189
189
|
}): void;
|
|
190
190
|
_sendLocalAttributesNowait(attributes: Record<string, unknown>): void;
|
|
191
191
|
_resendLocalAttributesNowait(): void;
|
|
192
|
-
sendRequest(type: string, request: RequestHeader, data?: Uint8Array): Promise<Content>;
|
|
192
|
+
sendRequest(type: string, request: RequestHeader, data?: Uint8Array, afterSend?: () => void): Promise<Content>;
|
|
193
|
+
private _dispatchRequest;
|
|
193
194
|
call(params: {
|
|
194
195
|
name: string;
|
|
195
196
|
url: string;
|
|
@@ -216,6 +217,7 @@ export declare class RoomClient {
|
|
|
216
217
|
input?: InvokeInput;
|
|
217
218
|
participantId?: string;
|
|
218
219
|
onBehalfOfId?: string;
|
|
220
|
+
afterSend?: () => void;
|
|
219
221
|
}): Promise<Content>;
|
|
220
222
|
invokeToolCall(params: {
|
|
221
223
|
toolkit: string;
|
|
@@ -224,6 +226,7 @@ export declare class RoomClient {
|
|
|
224
226
|
streamInput?: boolean;
|
|
225
227
|
participantId?: string;
|
|
226
228
|
onBehalfOfId?: string;
|
|
229
|
+
afterSend?: () => void;
|
|
227
230
|
}): Promise<{
|
|
228
231
|
kind: "content";
|
|
229
232
|
content: Content;
|
|
@@ -247,7 +250,7 @@ export declare class RoomClient {
|
|
|
247
250
|
participantId?: string;
|
|
248
251
|
onBehalfOfId?: string;
|
|
249
252
|
}): Promise<AsyncIterable<Content>>;
|
|
250
|
-
private
|
|
253
|
+
private _dispatchToolCallRequestChunk;
|
|
251
254
|
private _streamInvokeToolRequestChunks;
|
|
252
255
|
private _decodeToolCallContent;
|
|
253
256
|
private _handleToolCallResponseChunk;
|
|
@@ -1146,7 +1146,12 @@ class RoomClient {
|
|
|
1146
1146
|
}
|
|
1147
1147
|
this._sendLocalAttributesNowait(attributes);
|
|
1148
1148
|
}
|
|
1149
|
-
async sendRequest(type, request, data) {
|
|
1149
|
+
async sendRequest(type, request, data, afterSend) {
|
|
1150
|
+
const response = this._dispatchRequest(type, request, data);
|
|
1151
|
+
afterSend?.();
|
|
1152
|
+
return await response;
|
|
1153
|
+
}
|
|
1154
|
+
_dispatchRequest(type, request, data) {
|
|
1150
1155
|
this._raiseIfTerminal();
|
|
1151
1156
|
if (this._entered && !this._connected && !this._allowDisconnectedRequests) {
|
|
1152
1157
|
throw this._disconnectedError({ baseMessage: "room connection is disconnected" });
|
|
@@ -1155,8 +1160,8 @@ class RoomClient {
|
|
|
1155
1160
|
const completer = new completer_js_1.Completer();
|
|
1156
1161
|
this._pendingRequests.set(requestId, completer);
|
|
1157
1162
|
try {
|
|
1158
|
-
|
|
1159
|
-
return
|
|
1163
|
+
this._protocolInstance.sendNowait(type, (0, utils_js_1.packMessage)(request, data), { id: requestId });
|
|
1164
|
+
return completer.fut;
|
|
1160
1165
|
}
|
|
1161
1166
|
catch (error) {
|
|
1162
1167
|
this._pendingRequests.delete(requestId);
|
|
@@ -1239,6 +1244,7 @@ class RoomClient {
|
|
|
1239
1244
|
input: this._normalizeInvokeInput(params.input ?? params.arguments),
|
|
1240
1245
|
participantId: params.participantId,
|
|
1241
1246
|
onBehalfOfId: params.onBehalfOfId,
|
|
1247
|
+
afterSend: params.afterSend,
|
|
1242
1248
|
});
|
|
1243
1249
|
if (output.kind !== "content") {
|
|
1244
1250
|
throw new room_server_client_js_1.RoomServerException("unexpected streamed output from " + params.toolkit + "." + params.tool);
|
|
@@ -1261,7 +1267,6 @@ class RoomClient {
|
|
|
1261
1267
|
let requestTask;
|
|
1262
1268
|
if (params.streamInput === true) {
|
|
1263
1269
|
request["arguments"] = { type: "control", method: "open" };
|
|
1264
|
-
requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
|
|
1265
1270
|
}
|
|
1266
1271
|
else {
|
|
1267
1272
|
const input = params.input;
|
|
@@ -1278,9 +1283,14 @@ class RoomClient {
|
|
|
1278
1283
|
if (params.onBehalfOfId != null) {
|
|
1279
1284
|
request["on_behalf_of_id"] = params.onBehalfOfId;
|
|
1280
1285
|
}
|
|
1286
|
+
const responseRequest = this._dispatchRequest("room.invoke_tool", request, requestData);
|
|
1287
|
+
params.afterSend?.();
|
|
1288
|
+
if (params.streamInput === true) {
|
|
1289
|
+
requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
|
|
1290
|
+
}
|
|
1281
1291
|
try {
|
|
1282
1292
|
const response = await Promise.race([
|
|
1283
|
-
|
|
1293
|
+
responseRequest,
|
|
1284
1294
|
preOpenError.fut,
|
|
1285
1295
|
]);
|
|
1286
1296
|
this._toolCallPreOpenErrors.delete(toolCallId);
|
|
@@ -1335,9 +1345,10 @@ class RoomClient {
|
|
|
1335
1345
|
if (params.onBehalfOfId != null) {
|
|
1336
1346
|
request["on_behalf_of_id"] = params.onBehalfOfId;
|
|
1337
1347
|
}
|
|
1348
|
+
const responseRequest = this._dispatchRequest("room.invoke_tool", request);
|
|
1338
1349
|
const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
|
|
1339
1350
|
try {
|
|
1340
|
-
const response = await
|
|
1351
|
+
const response = await responseRequest;
|
|
1341
1352
|
await requestTask;
|
|
1342
1353
|
if (response instanceof response_js_1.ControlContent && response.method === "open") {
|
|
1343
1354
|
throw new room_server_client_js_1.RoomServerException(`unexpected return type from ${params.toolkit}.${params.tool}`);
|
|
@@ -1368,6 +1379,7 @@ class RoomClient {
|
|
|
1368
1379
|
if (params.onBehalfOfId != null) {
|
|
1369
1380
|
request["on_behalf_of_id"] = params.onBehalfOfId;
|
|
1370
1381
|
}
|
|
1382
|
+
const responseRequest = this._dispatchRequest("room.invoke_tool", request);
|
|
1371
1383
|
const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
|
|
1372
1384
|
void requestTask.catch((error) => {
|
|
1373
1385
|
const stream = this._toolCallStreams.get(toolCallId);
|
|
@@ -1381,7 +1393,7 @@ class RoomClient {
|
|
|
1381
1393
|
let response;
|
|
1382
1394
|
try {
|
|
1383
1395
|
response = await Promise.race([
|
|
1384
|
-
|
|
1396
|
+
responseRequest,
|
|
1385
1397
|
preOpenError.fut,
|
|
1386
1398
|
]);
|
|
1387
1399
|
}
|
|
@@ -1403,24 +1415,27 @@ class RoomClient {
|
|
|
1403
1415
|
},
|
|
1404
1416
|
};
|
|
1405
1417
|
}
|
|
1406
|
-
|
|
1418
|
+
_dispatchToolCallRequestChunk(toolCallId, chunk) {
|
|
1419
|
+
this._raiseIfTerminal();
|
|
1420
|
+
if (this._entered && !this._connected && !this._allowDisconnectedRequests) {
|
|
1421
|
+
throw this._disconnectedError({ baseMessage: "room connection is disconnected" });
|
|
1422
|
+
}
|
|
1407
1423
|
const packed = chunk.pack();
|
|
1408
1424
|
const request = {
|
|
1409
1425
|
tool_call_id: toolCallId,
|
|
1410
1426
|
chunk: JSON.parse((0, utils_js_1.splitMessageHeader)(packed)),
|
|
1411
1427
|
};
|
|
1412
1428
|
const payload = (0, utils_js_1.splitMessagePayload)(packed);
|
|
1413
|
-
|
|
1429
|
+
this._protocolInstance.sendNowait("room.tool_call_request_chunk", (0, utils_js_1.packMessage)(request, payload.length > 0 ? payload : undefined));
|
|
1414
1430
|
}
|
|
1415
1431
|
async _streamInvokeToolRequestChunks(toolCallId, input) {
|
|
1416
|
-
await Promise.resolve();
|
|
1417
1432
|
try {
|
|
1418
1433
|
for await (const item of input) {
|
|
1419
|
-
|
|
1434
|
+
this._dispatchToolCallRequestChunk(toolCallId, item);
|
|
1420
1435
|
}
|
|
1421
1436
|
}
|
|
1422
1437
|
finally {
|
|
1423
|
-
|
|
1438
|
+
this._dispatchToolCallRequestChunk(toolCallId, new response_js_1.ControlContent({ method: "close" }));
|
|
1424
1439
|
}
|
|
1425
1440
|
}
|
|
1426
1441
|
_decodeToolCallContent(params) {
|
package/dist/esm/agent.js
CHANGED
|
@@ -511,10 +511,10 @@ class _RemoteToolkitWrapper {
|
|
|
511
511
|
return false;
|
|
512
512
|
}
|
|
513
513
|
}
|
|
514
|
-
|
|
514
|
+
_sendToolCallResponseChunk(messageId, toolCallId, chunk) {
|
|
515
515
|
const [header, payload] = unpackMessage(chunk.pack());
|
|
516
516
|
try {
|
|
517
|
-
|
|
517
|
+
this.client.protocol.sendNowait("room.tool_call_response_chunk", packMessage({ tool_call_id: toolCallId, chunk: header }, payload.length > 0 ? payload : undefined), { id: messageId });
|
|
518
518
|
return true;
|
|
519
519
|
}
|
|
520
520
|
catch (error) {
|
|
@@ -615,10 +615,10 @@ class _RemoteToolkitWrapper {
|
|
|
615
615
|
return;
|
|
616
616
|
for await (const chunk of output.stream) {
|
|
617
617
|
this.toolkit.validateOutputContent(tool, chunk);
|
|
618
|
-
if (!
|
|
618
|
+
if (!this._sendToolCallResponseChunk(messageId, toolCallId, chunk))
|
|
619
619
|
return;
|
|
620
620
|
}
|
|
621
|
-
|
|
621
|
+
this._sendToolCallResponseChunk(messageId, toolCallId, new ControlContent({ method: "close" }));
|
|
622
622
|
return;
|
|
623
623
|
}
|
|
624
624
|
throw new Error(`tool ${toolName} returned unsupported output`);
|
|
@@ -629,9 +629,9 @@ class _RemoteToolkitWrapper {
|
|
|
629
629
|
return;
|
|
630
630
|
}
|
|
631
631
|
if (!(error instanceof InvalidToolDataException)) {
|
|
632
|
-
|
|
632
|
+
this._sendToolCallResponseChunk(messageId, toolCallId, new ErrorContent({ text: String(error) }));
|
|
633
633
|
}
|
|
634
|
-
|
|
634
|
+
this._sendToolCallResponseChunk(messageId, toolCallId, new ControlContent({
|
|
635
635
|
method: "close",
|
|
636
636
|
statusCode: error instanceof InvalidToolDataException ? ControlCloseStatus.INVALID_DATA : undefined,
|
|
637
637
|
message: error instanceof InvalidToolDataException ? error.message : undefined,
|