@meshagent/meshagent 0.29.4 → 0.30.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/browser/agent-client.js +3 -28
  3. package/dist/browser/agent.js +6 -6
  4. package/dist/browser/containers-client.d.ts +125 -0
  5. package/dist/browser/containers-client.js +458 -0
  6. package/dist/browser/database-client.d.ts +42 -6
  7. package/dist/browser/database-client.js +610 -77
  8. package/dist/browser/developer-client.d.ts +2 -2
  9. package/dist/browser/developer-client.js +60 -15
  10. package/dist/browser/helpers.js +4 -3
  11. package/dist/browser/index.d.ts +1 -0
  12. package/dist/browser/index.js +1 -0
  13. package/dist/browser/lk-client.js +12 -3
  14. package/dist/browser/meshagent-client.d.ts +5 -0
  15. package/dist/browser/messaging-client.d.ts +1 -0
  16. package/dist/browser/messaging-client.js +52 -8
  17. package/dist/browser/queues-client.d.ts +2 -0
  18. package/dist/browser/queues-client.js +34 -7
  19. package/dist/browser/response.d.ts +28 -0
  20. package/dist/browser/response.js +76 -1
  21. package/dist/browser/room-client.d.ts +43 -1
  22. package/dist/browser/room-client.js +204 -0
  23. package/dist/browser/secrets-client.d.ts +1 -0
  24. package/dist/browser/secrets-client.js +32 -27
  25. package/dist/browser/storage-client.d.ts +22 -7
  26. package/dist/browser/storage-client.js +353 -15
  27. package/dist/browser/sync-client.d.ts +12 -13
  28. package/dist/browser/sync-client.js +263 -65
  29. package/dist/esm/agent-client.js +3 -28
  30. package/dist/esm/agent.js +6 -6
  31. package/dist/esm/containers-client.d.ts +125 -0
  32. package/dist/esm/containers-client.js +453 -0
  33. package/dist/esm/database-client.d.ts +42 -6
  34. package/dist/esm/database-client.js +611 -78
  35. package/dist/esm/developer-client.d.ts +2 -2
  36. package/dist/esm/developer-client.js +61 -16
  37. package/dist/esm/helpers.js +4 -3
  38. package/dist/esm/index.d.ts +1 -0
  39. package/dist/esm/index.js +1 -0
  40. package/dist/esm/lk-client.js +12 -3
  41. package/dist/esm/meshagent-client.d.ts +5 -0
  42. package/dist/esm/messaging-client.d.ts +1 -0
  43. package/dist/esm/messaging-client.js +52 -8
  44. package/dist/esm/queues-client.d.ts +2 -0
  45. package/dist/esm/queues-client.js +35 -8
  46. package/dist/esm/response.d.ts +28 -0
  47. package/dist/esm/response.js +73 -0
  48. package/dist/esm/room-client.d.ts +43 -1
  49. package/dist/esm/room-client.js +207 -3
  50. package/dist/esm/secrets-client.d.ts +1 -0
  51. package/dist/esm/secrets-client.js +33 -28
  52. package/dist/esm/storage-client.d.ts +22 -7
  53. package/dist/esm/storage-client.js +353 -15
  54. package/dist/esm/sync-client.d.ts +12 -13
  55. package/dist/esm/sync-client.js +263 -64
  56. package/dist/node/agent-client.js +3 -28
  57. package/dist/node/agent.js +6 -6
  58. package/dist/node/containers-client.d.ts +125 -0
  59. package/dist/node/containers-client.js +458 -0
  60. package/dist/node/database-client.d.ts +42 -6
  61. package/dist/node/database-client.js +610 -77
  62. package/dist/node/developer-client.d.ts +2 -2
  63. package/dist/node/developer-client.js +60 -15
  64. package/dist/node/helpers.js +4 -3
  65. package/dist/node/index.d.ts +1 -0
  66. package/dist/node/index.js +1 -0
  67. package/dist/node/lk-client.js +12 -3
  68. package/dist/node/meshagent-client.d.ts +5 -0
  69. package/dist/node/messaging-client.d.ts +1 -0
  70. package/dist/node/messaging-client.js +52 -8
  71. package/dist/node/queues-client.d.ts +2 -0
  72. package/dist/node/queues-client.js +34 -7
  73. package/dist/node/response.d.ts +28 -0
  74. package/dist/node/response.js +76 -1
  75. package/dist/node/room-client.d.ts +43 -1
  76. package/dist/node/room-client.js +204 -0
  77. package/dist/node/secrets-client.d.ts +1 -0
  78. package/dist/node/secrets-client.js +32 -27
  79. package/dist/node/storage-client.d.ts +22 -7
  80. package/dist/node/storage-client.js +353 -15
  81. package/dist/node/sync-client.d.ts +12 -13
  82. package/dist/node/sync-client.js +263 -65
  83. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Completer } from "./completer";
2
- import { packMessage, unpackMessage } from "./utils";
2
+ import { packMessage, splitMessageHeader, splitMessagePayload, unpackMessage } from "./utils";
3
3
  import { LocalParticipant } from "./participant";
4
4
  import { StreamController } from "./stream-controller";
5
5
  import { SyncClient } from "./sync-client";
@@ -8,20 +8,23 @@ import { StorageClient } from "./storage-client";
8
8
  import { MessagingClient } from "./messaging-client";
9
9
  import { QueuesClient } from "./queues-client";
10
10
  import { DatabaseClient } from "./database-client";
11
- import { AgentsClient } from "./agent-client";
11
+ import { AgentsClient, ToolkitDescription } from "./agent-client";
12
12
  import { SecretsClient } from "./secrets-client";
13
+ import { ContainersClient } from "./containers-client";
13
14
  import { RoomServerException } from "./room-server-client";
14
- import { ErrorContent, unpackContent } from "./response";
15
+ import { BinaryContent, ControlContent, EmptyContent, ErrorContent, FileContent, JsonContent, LinkContent, TextContent, unpackContent } from "./response";
15
16
  export class RoomClient {
16
17
  constructor({ protocol }) {
17
18
  this._pendingRequests = new Map();
18
19
  this._ready = new Completer();
19
20
  this._localParticipant = null;
20
21
  this._eventsController = new StreamController();
22
+ this._toolCallStreams = new Map();
21
23
  this.protocol = protocol;
22
24
  protocol.addHandler("room_ready", this._handleRoomReady.bind(this));
23
25
  protocol.addHandler("connected", this._handleParticipant.bind(this));
24
26
  protocol.addHandler("__response__", this._handleResponse.bind(this));
27
+ protocol.addHandler("room.tool_call_response_chunk", this._handleToolCallResponseChunk.bind(this));
25
28
  this.sync = new SyncClient({ room: this });
26
29
  this.storage = new StorageClient({ room: this });
27
30
  this.developer = new DeveloperClient({ room: this });
@@ -30,6 +33,7 @@ export class RoomClient {
30
33
  this.database = new DatabaseClient({ room: this });
31
34
  this.agents = new AgentsClient({ room: this });
32
35
  this.secrets = new SecretsClient({ room: this });
36
+ this.containers = new ContainersClient({ room: this });
33
37
  }
34
38
  get localParticipant() {
35
39
  return this._localParticipant;
@@ -48,6 +52,10 @@ export class RoomClient {
48
52
  this._pendingRequests.delete(prKey);
49
53
  }
50
54
  this.sync.dispose();
55
+ for (const stream of this._toolCallStreams.values()) {
56
+ stream.close();
57
+ }
58
+ this._toolCallStreams.clear();
51
59
  this.protocol.dispose();
52
60
  this._localParticipant = null;
53
61
  }
@@ -59,6 +67,202 @@ export class RoomClient {
59
67
  await this.protocol.send(type, message, requestId);
60
68
  return await pr.fut;
61
69
  }
70
+ async call(params) {
71
+ await this.sendRequest("room.call", params);
72
+ }
73
+ async listToolkits(params) {
74
+ const request = {};
75
+ if (params?.participantId != null) {
76
+ request["participant_id"] = params.participantId;
77
+ }
78
+ if (params?.participantName != null) {
79
+ request["participant_name"] = params.participantName;
80
+ }
81
+ if (params?.timeout !== undefined) {
82
+ request["timeout"] = params.timeout;
83
+ }
84
+ const result = await this.sendRequest("room.list_toolkits", request);
85
+ if (!(result instanceof JsonContent)) {
86
+ throw new RoomServerException("unexpected return type from room.list_toolkits");
87
+ }
88
+ const tools = result.json["tools"];
89
+ if (typeof tools !== "object" || tools === null || Array.isArray(tools)) {
90
+ throw new RoomServerException("unexpected return type from room.list_toolkits");
91
+ }
92
+ const toolkits = [];
93
+ for (const [name, data] of Object.entries(tools)) {
94
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
95
+ throw new RoomServerException("unexpected toolkit description from room.list_toolkits");
96
+ }
97
+ toolkits.push(ToolkitDescription.fromJson(data, { name }));
98
+ }
99
+ return toolkits;
100
+ }
101
+ async invoke(params) {
102
+ const input = params.input ?? params.arguments ?? new EmptyContent();
103
+ const request = {
104
+ toolkit: params.toolkit,
105
+ tool: params.tool,
106
+ };
107
+ let requestData;
108
+ if (input instanceof BinaryContent ||
109
+ input instanceof EmptyContent ||
110
+ input instanceof ErrorContent ||
111
+ input instanceof FileContent ||
112
+ input instanceof JsonContent ||
113
+ input instanceof LinkContent ||
114
+ input instanceof TextContent) {
115
+ const packed = input.pack();
116
+ request["arguments"] = JSON.parse(splitMessageHeader(packed));
117
+ const payload = splitMessagePayload(packed);
118
+ if (payload.length > 0) {
119
+ requestData = payload;
120
+ }
121
+ }
122
+ else if (typeof input === "object" && input !== null && !Array.isArray(input)) {
123
+ request["arguments"] = {
124
+ type: "json",
125
+ json: input,
126
+ };
127
+ }
128
+ else {
129
+ throw new RoomServerException("invoke input must be a content value or JSON object");
130
+ }
131
+ if (params.participantId != null) {
132
+ request["participant_id"] = params.participantId;
133
+ }
134
+ if (params.onBehalfOfId != null) {
135
+ request["on_behalf_of_id"] = params.onBehalfOfId;
136
+ }
137
+ if (params.callerContext != null) {
138
+ request["caller_context"] = params.callerContext;
139
+ }
140
+ return await this.sendRequest("room.invoke_tool", request, requestData);
141
+ }
142
+ async invokeWithStreamInput(params) {
143
+ const toolCallId = `${Date.now()}-${this.protocol.getNextMessageId()}-${Math.random().toString(16).slice(2)}`;
144
+ const request = {
145
+ toolkit: params.toolkit,
146
+ tool: params.tool,
147
+ tool_call_id: toolCallId,
148
+ arguments: { type: "control", method: "open" },
149
+ };
150
+ if (params.participantId != null) {
151
+ request["participant_id"] = params.participantId;
152
+ }
153
+ if (params.onBehalfOfId != null) {
154
+ request["on_behalf_of_id"] = params.onBehalfOfId;
155
+ }
156
+ if (params.callerContext != null) {
157
+ request["caller_context"] = params.callerContext;
158
+ }
159
+ const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
160
+ try {
161
+ const response = await this.sendRequest("room.invoke_tool", request);
162
+ await requestTask;
163
+ if (response instanceof ControlContent && response.method === "open") {
164
+ throw new RoomServerException(`unexpected return type from ${params.toolkit}.${params.tool}`);
165
+ }
166
+ return response;
167
+ }
168
+ catch (error) {
169
+ await Promise.resolve(requestTask).catch(() => undefined);
170
+ throw error;
171
+ }
172
+ }
173
+ async invokeStream(params) {
174
+ const toolCallId = `${Date.now()}-${this.protocol.getNextMessageId()}-${Math.random().toString(16).slice(2)}`;
175
+ const controller = new StreamController();
176
+ const responseIterator = controller.stream[Symbol.asyncIterator]();
177
+ this._toolCallStreams.set(toolCallId, controller);
178
+ const request = {
179
+ toolkit: params.toolkit,
180
+ tool: params.tool,
181
+ tool_call_id: toolCallId,
182
+ arguments: { type: "control", method: "open" },
183
+ };
184
+ if (params.participantId != null) {
185
+ request["participant_id"] = params.participantId;
186
+ }
187
+ if (params.onBehalfOfId != null) {
188
+ request["on_behalf_of_id"] = params.onBehalfOfId;
189
+ }
190
+ if (params.callerContext != null) {
191
+ request["caller_context"] = params.callerContext;
192
+ }
193
+ const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
194
+ void requestTask.catch((error) => {
195
+ const stream = this._toolCallStreams.get(toolCallId);
196
+ if (!stream) {
197
+ return;
198
+ }
199
+ stream.add(new ErrorContent({ text: `request stream failed: ${String(error)}` }));
200
+ stream.close();
201
+ this._toolCallStreams.delete(toolCallId);
202
+ });
203
+ const response = await this.sendRequest("room.invoke_tool", request);
204
+ if (!(response instanceof ControlContent) || response.method !== "open") {
205
+ this._toolCallStreams.delete(toolCallId);
206
+ controller.close();
207
+ throw new RoomServerException(`unexpected return type from ${params.toolkit}.${params.tool}`);
208
+ }
209
+ return {
210
+ [Symbol.asyncIterator]() {
211
+ return responseIterator;
212
+ },
213
+ };
214
+ }
215
+ async _sendToolCallRequestChunk(toolCallId, chunk) {
216
+ const packed = chunk.pack();
217
+ const request = {
218
+ tool_call_id: toolCallId,
219
+ chunk: JSON.parse(splitMessageHeader(packed)),
220
+ };
221
+ const payload = splitMessagePayload(packed);
222
+ await this.sendRequest("room.tool_call_request_chunk", request, payload.length > 0 ? payload : undefined);
223
+ }
224
+ async _streamInvokeToolRequestChunks(toolCallId, input) {
225
+ await Promise.resolve();
226
+ try {
227
+ for await (const item of input) {
228
+ await this._sendToolCallRequestChunk(toolCallId, item);
229
+ }
230
+ }
231
+ finally {
232
+ await this._sendToolCallRequestChunk(toolCallId, new ControlContent({ method: "close" }));
233
+ }
234
+ }
235
+ _decodeToolCallContent(params) {
236
+ const chunk = params.header["chunk"];
237
+ if (typeof chunk === "object" && chunk !== null && !Array.isArray(chunk)) {
238
+ const chunkMap = chunk;
239
+ if (typeof chunkMap["type"] === "string") {
240
+ return unpackContent(packMessage(chunkMap, params.payload.length > 0 ? params.payload : undefined));
241
+ }
242
+ return new JsonContent({ json: chunkMap });
243
+ }
244
+ return new JsonContent({ json: { chunk } });
245
+ }
246
+ async _handleToolCallResponseChunk(protocol, messageId, type, data) {
247
+ if (!data) {
248
+ return;
249
+ }
250
+ const [header, payload] = unpackMessage(data);
251
+ const toolCallId = header["tool_call_id"];
252
+ if (typeof toolCallId !== "string" || toolCallId.length === 0) {
253
+ return;
254
+ }
255
+ const stream = this._toolCallStreams.get(toolCallId);
256
+ if (!stream) {
257
+ return;
258
+ }
259
+ const content = this._decodeToolCallContent({ header, payload });
260
+ stream.add(content);
261
+ if (content instanceof ControlContent && content.method === "close") {
262
+ stream.close();
263
+ this._toolCallStreams.delete(toolCallId);
264
+ }
265
+ }
62
266
  async _handleResponse(protocol, messageId, type, data) {
63
267
  if (!data) {
64
268
  console.error("No data in response");
@@ -11,6 +11,7 @@ export declare class SecretsClient {
11
11
  constructor({ room }: {
12
12
  room: RoomClient;
13
13
  });
14
+ private unexpectedResponse;
14
15
  setSecret({ secretId, data, mimeType, name, delegatedTo, forIdentity, }: {
15
16
  secretId: string;
16
17
  data: Uint8Array;
@@ -1,45 +1,52 @@
1
- import { EmptyContent, FileContent, JsonContent } from "./response";
1
+ import { BinaryContent, EmptyContent, FileContent, JsonContent } from "./response";
2
2
  export class SecretsClient {
3
3
  constructor({ room }) {
4
4
  this.client = room;
5
5
  }
6
+ unexpectedResponse(operation) {
7
+ return new Error(`unexpected return type from secrets.${operation}`);
8
+ }
6
9
  async setSecret({ secretId, data, mimeType, name, delegatedTo, forIdentity, }) {
7
- const req = {
8
- secret_id: secretId,
9
- };
10
- if (mimeType)
11
- req.type = mimeType;
12
- if (name)
13
- req.name = name;
14
- if (delegatedTo)
15
- req.delegated_to = delegatedTo;
16
- if (forIdentity)
17
- req.for_identity = forIdentity;
18
- const response = await this.client.sendRequest("secrets.set_secret", req, data);
10
+ const response = await this.client.invoke({
11
+ toolkit: "secrets",
12
+ tool: "set_secret",
13
+ input: new BinaryContent({
14
+ data,
15
+ headers: {
16
+ secret_id: secretId,
17
+ type: mimeType ?? null,
18
+ name: name ?? null,
19
+ delegated_to: delegatedTo ?? null,
20
+ for_identity: forIdentity ?? null,
21
+ has_data: true,
22
+ },
23
+ }),
24
+ });
19
25
  if (response instanceof EmptyContent || response instanceof JsonContent) {
20
26
  return;
21
27
  }
22
- throw new Error("Invalid response received, expected EmptyContent or JsonContent");
28
+ throw this.unexpectedResponse("set_secret");
23
29
  }
24
30
  async getSecret({ secretId, delegatedTo, }) {
25
31
  const req = {
26
32
  secret_id: secretId,
33
+ type: null,
34
+ name: null,
35
+ delegated_to: delegatedTo ?? null,
27
36
  };
28
- if (delegatedTo)
29
- req.delegated_to = delegatedTo;
30
- const response = await this.client.sendRequest("secrets.get_secret", req);
37
+ const response = await this.client.invoke({ toolkit: "secrets", tool: "get_secret", input: req });
31
38
  if (response instanceof EmptyContent) {
32
39
  return null;
33
40
  }
34
41
  if (response instanceof FileContent) {
35
42
  return response;
36
43
  }
37
- throw new Error("Invalid response received, expected FileContent or EmptyContent");
44
+ throw this.unexpectedResponse("get_secret");
38
45
  }
39
46
  async listSecrets() {
40
- const response = await this.client.sendRequest("secrets.list_secrets", {});
47
+ const response = await this.client.invoke({ toolkit: "secrets", tool: "list_secrets", input: {} });
41
48
  if (!(response instanceof JsonContent)) {
42
- throw new Error("Invalid response received, expected JsonContent");
49
+ throw this.unexpectedResponse("list_secrets");
43
50
  }
44
51
  const secrets = Array.isArray(response.json?.secrets) ? response.json.secrets : [];
45
52
  return secrets.map((item) => ({
@@ -52,26 +59,24 @@ export class SecretsClient {
52
59
  async deleteSecret({ secretId, delegatedTo, }) {
53
60
  const req = {
54
61
  id: secretId,
62
+ delegated_to: delegatedTo ?? null,
55
63
  };
56
- if (delegatedTo)
57
- req.delegated_to = delegatedTo;
58
- const response = await this.client.sendRequest("secrets.delete_secret", req);
64
+ const response = await this.client.invoke({ toolkit: "secrets", tool: "delete_secret", input: req });
59
65
  if (response instanceof EmptyContent || response instanceof JsonContent) {
60
66
  return;
61
67
  }
62
- throw new Error("Invalid response received, expected EmptyContent or JsonContent");
68
+ throw this.unexpectedResponse("delete_secret");
63
69
  }
64
70
  async deleteRequestedSecret({ url, type, delegatedTo, }) {
65
71
  const req = {
66
72
  url,
67
73
  type,
74
+ delegated_to: delegatedTo ?? null,
68
75
  };
69
- if (delegatedTo)
70
- req.delegated_to = delegatedTo;
71
- const response = await this.client.sendRequest("secrets.delete_requested_secret", req);
76
+ const response = await this.client.invoke({ toolkit: "secrets", tool: "delete_requested_secret", input: req });
72
77
  if (response instanceof EmptyContent || response instanceof JsonContent) {
73
78
  return;
74
79
  }
75
- throw new Error("Invalid response received, expected EmptyContent or JsonContent");
80
+ throw this.unexpectedResponse("delete_requested_secret");
76
81
  }
77
82
  }
@@ -1,6 +1,6 @@
1
1
  import { RoomClient } from "./room-client";
2
2
  import { RoomEvent } from "./room-event";
3
- import { FileContent } from "./response";
3
+ import { BinaryContent, FileContent } from "./response";
4
4
  import { EventEmitter } from "./event-emitter";
5
5
  export declare class FileHandle {
6
6
  id: number;
@@ -11,9 +11,11 @@ export declare class FileHandle {
11
11
  declare class StorageEntry {
12
12
  name: string;
13
13
  isFolder: boolean;
14
- constructor({ name, isFolder }: {
14
+ size: number | null;
15
+ constructor({ name, isFolder, size }: {
15
16
  name: string;
16
17
  isFolder: boolean;
18
+ size?: number | null;
17
19
  });
18
20
  nameWithoutExtension(): string;
19
21
  }
@@ -24,15 +26,28 @@ export declare class StorageClient extends EventEmitter<RoomEvent> {
24
26
  });
25
27
  private _handleFileUpdated;
26
28
  private _handleFileDeleted;
29
+ private _unexpectedResponseError;
30
+ private _invoke;
27
31
  list(path: string): Promise<StorageEntry[]>;
28
32
  delete(path: string): Promise<void>;
29
- open(path: string, { overwrite }: {
30
- overwrite: boolean;
31
- }): Promise<FileHandle>;
32
33
  exists(path: string): Promise<boolean>;
33
- write(handle: FileHandle, bytes: Uint8Array): Promise<void>;
34
- close(handle: FileHandle): Promise<void>;
34
+ private _defaultUploadName;
35
+ upload(path: string, bytes: Uint8Array, { overwrite, name, mimeType, }?: {
36
+ overwrite?: boolean;
37
+ name?: string | null;
38
+ mimeType?: string | null;
39
+ }): Promise<void>;
40
+ uploadStream(path: string, chunks: AsyncIterable<Uint8Array>, { overwrite, chunkSize, size, name, mimeType, }?: {
41
+ overwrite?: boolean;
42
+ chunkSize?: number;
43
+ size?: number | null;
44
+ name?: string | null;
45
+ mimeType?: string | null;
46
+ }): Promise<void>;
35
47
  download(path: string): Promise<FileContent>;
48
+ downloadStream(path: string, { chunkSize, }?: {
49
+ chunkSize?: number;
50
+ }): Promise<AsyncIterable<BinaryContent>>;
36
51
  downloadUrl(path: string): Promise<string>;
37
52
  }
38
53
  export {};