@meshagent/meshagent 0.47.0 → 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.
@@ -530,10 +530,10 @@ class _RemoteToolkitWrapper {
530
530
  return false;
531
531
  }
532
532
  }
533
- async _sendToolCallResponseChunk(messageId, toolCallId, chunk) {
533
+ _sendToolCallResponseChunk(messageId, toolCallId, chunk) {
534
534
  const [header, payload] = (0, utils_js_1.unpackMessage)(chunk.pack());
535
535
  try {
536
- await this.client.protocol.send("room.tool_call_response_chunk", (0, utils_js_1.packMessage)({ tool_call_id: toolCallId, chunk: header }, payload.length > 0 ? payload : undefined), { id: messageId });
536
+ this.client.protocol.sendNowait("room.tool_call_response_chunk", (0, utils_js_1.packMessage)({ tool_call_id: toolCallId, chunk: header }, payload.length > 0 ? payload : undefined), { id: messageId });
537
537
  return true;
538
538
  }
539
539
  catch (error) {
@@ -634,10 +634,10 @@ class _RemoteToolkitWrapper {
634
634
  return;
635
635
  for await (const chunk of output.stream) {
636
636
  this.toolkit.validateOutputContent(tool, chunk);
637
- if (!await this._sendToolCallResponseChunk(messageId, toolCallId, chunk))
637
+ if (!this._sendToolCallResponseChunk(messageId, toolCallId, chunk))
638
638
  return;
639
639
  }
640
- await this._sendToolCallResponseChunk(messageId, toolCallId, new response_js_1.ControlContent({ method: "close" }));
640
+ this._sendToolCallResponseChunk(messageId, toolCallId, new response_js_1.ControlContent({ method: "close" }));
641
641
  return;
642
642
  }
643
643
  throw new Error(`tool ${toolName} returned unsupported output`);
@@ -648,9 +648,9 @@ class _RemoteToolkitWrapper {
648
648
  return;
649
649
  }
650
650
  if (!(error instanceof InvalidToolDataException)) {
651
- await this._sendToolCallResponseChunk(messageId, toolCallId, new response_js_1.ErrorContent({ text: String(error) }));
651
+ this._sendToolCallResponseChunk(messageId, toolCallId, new response_js_1.ErrorContent({ text: String(error) }));
652
652
  }
653
- await this._sendToolCallResponseChunk(messageId, toolCallId, new response_js_1.ControlContent({
653
+ this._sendToolCallResponseChunk(messageId, toolCallId, new response_js_1.ControlContent({
654
654
  method: "close",
655
655
  statusCode: error instanceof InvalidToolDataException ? response_js_1.ControlCloseStatus.INVALID_DATA : undefined,
656
656
  message: error instanceof InvalidToolDataException ? error.message : undefined,
@@ -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 | ResourceRole | FeedRole | SecretRole | "list";
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 {
@@ -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();
@@ -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") {
@@ -190,6 +190,7 @@ export declare class RoomClient {
190
190
  _sendLocalAttributesNowait(attributes: Record<string, unknown>): void;
191
191
  _resendLocalAttributesNowait(): void;
192
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;
@@ -249,7 +250,7 @@ export declare class RoomClient {
249
250
  participantId?: string;
250
251
  onBehalfOfId?: string;
251
252
  }): Promise<AsyncIterable<Content>>;
252
- private _sendToolCallRequestChunk;
253
+ private _dispatchToolCallRequestChunk;
253
254
  private _streamInvokeToolRequestChunks;
254
255
  private _decodeToolCallContent;
255
256
  private _handleToolCallResponseChunk;
@@ -1147,6 +1147,11 @@ class RoomClient {
1147
1147
  this._sendLocalAttributesNowait(attributes);
1148
1148
  }
1149
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,9 +1160,8 @@ class RoomClient {
1155
1160
  const completer = new completer_js_1.Completer();
1156
1161
  this._pendingRequests.set(requestId, completer);
1157
1162
  try {
1158
- await this._protocolInstance.send(type, (0, utils_js_1.packMessage)(request, data), requestId);
1159
- afterSend?.();
1160
- return await completer.fut;
1163
+ this._protocolInstance.sendNowait(type, (0, utils_js_1.packMessage)(request, data), { id: requestId });
1164
+ return completer.fut;
1161
1165
  }
1162
1166
  catch (error) {
1163
1167
  this._pendingRequests.delete(requestId);
@@ -1263,7 +1267,6 @@ class RoomClient {
1263
1267
  let requestTask;
1264
1268
  if (params.streamInput === true) {
1265
1269
  request["arguments"] = { type: "control", method: "open" };
1266
- requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
1267
1270
  }
1268
1271
  else {
1269
1272
  const input = params.input;
@@ -1280,9 +1283,14 @@ class RoomClient {
1280
1283
  if (params.onBehalfOfId != null) {
1281
1284
  request["on_behalf_of_id"] = params.onBehalfOfId;
1282
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
+ }
1283
1291
  try {
1284
1292
  const response = await Promise.race([
1285
- this.sendRequest("room.invoke_tool", request, requestData, params.afterSend),
1293
+ responseRequest,
1286
1294
  preOpenError.fut,
1287
1295
  ]);
1288
1296
  this._toolCallPreOpenErrors.delete(toolCallId);
@@ -1337,9 +1345,10 @@ class RoomClient {
1337
1345
  if (params.onBehalfOfId != null) {
1338
1346
  request["on_behalf_of_id"] = params.onBehalfOfId;
1339
1347
  }
1348
+ const responseRequest = this._dispatchRequest("room.invoke_tool", request);
1340
1349
  const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
1341
1350
  try {
1342
- const response = await this.sendRequest("room.invoke_tool", request);
1351
+ const response = await responseRequest;
1343
1352
  await requestTask;
1344
1353
  if (response instanceof response_js_1.ControlContent && response.method === "open") {
1345
1354
  throw new room_server_client_js_1.RoomServerException(`unexpected return type from ${params.toolkit}.${params.tool}`);
@@ -1370,6 +1379,7 @@ class RoomClient {
1370
1379
  if (params.onBehalfOfId != null) {
1371
1380
  request["on_behalf_of_id"] = params.onBehalfOfId;
1372
1381
  }
1382
+ const responseRequest = this._dispatchRequest("room.invoke_tool", request);
1373
1383
  const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
1374
1384
  void requestTask.catch((error) => {
1375
1385
  const stream = this._toolCallStreams.get(toolCallId);
@@ -1383,7 +1393,7 @@ class RoomClient {
1383
1393
  let response;
1384
1394
  try {
1385
1395
  response = await Promise.race([
1386
- this.sendRequest("room.invoke_tool", request),
1396
+ responseRequest,
1387
1397
  preOpenError.fut,
1388
1398
  ]);
1389
1399
  }
@@ -1405,24 +1415,27 @@ class RoomClient {
1405
1415
  },
1406
1416
  };
1407
1417
  }
1408
- async _sendToolCallRequestChunk(toolCallId, chunk) {
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
+ }
1409
1423
  const packed = chunk.pack();
1410
1424
  const request = {
1411
1425
  tool_call_id: toolCallId,
1412
1426
  chunk: JSON.parse((0, utils_js_1.splitMessageHeader)(packed)),
1413
1427
  };
1414
1428
  const payload = (0, utils_js_1.splitMessagePayload)(packed);
1415
- await this.sendRequest("room.tool_call_request_chunk", request, payload.length > 0 ? payload : undefined);
1429
+ this._protocolInstance.sendNowait("room.tool_call_request_chunk", (0, utils_js_1.packMessage)(request, payload.length > 0 ? payload : undefined));
1416
1430
  }
1417
1431
  async _streamInvokeToolRequestChunks(toolCallId, input) {
1418
- await Promise.resolve();
1419
1432
  try {
1420
1433
  for await (const item of input) {
1421
- await this._sendToolCallRequestChunk(toolCallId, item);
1434
+ this._dispatchToolCallRequestChunk(toolCallId, item);
1422
1435
  }
1423
1436
  }
1424
1437
  finally {
1425
- await this._sendToolCallRequestChunk(toolCallId, new response_js_1.ControlContent({ method: "close" }));
1438
+ this._dispatchToolCallRequestChunk(toolCallId, new response_js_1.ControlContent({ method: "close" }));
1426
1439
  }
1427
1440
  }
1428
1441
  _decodeToolCallContent(params) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshagent/meshagent",
3
- "version": "0.47.0",
3
+ "version": "0.47.1",
4
4
  "description": "Meshagent Client",
5
5
  "homepage": "https://github.com/meshagent/meshagent-ts",
6
6
  "scripts": {