@meshagent/meshagent 0.38.2 → 0.38.4

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 CHANGED
@@ -1,3 +1,15 @@
1
+ ## [0.38.4]
2
+ - Stability
3
+
4
+ ## [0.38.3]
5
+ - Breaking: TypeScript container image summaries now use `references`/`preferredRef` and metadata fields (timestamps/media type), and `inspectImage` returns manifests/layers/content size; `tags`/`size` are removed.
6
+ - `getUsage` now supports filters for users, room, provider, model, and usage type.
7
+ - Room connection and errors improved: `RoomServerException` now carries `statusCode` and `retryable`, and `RoomClient` can route OAuth/secret requests via handler options.
8
+ - React hooks add robust connection retry/backoff, new authorization helpers, and optional secret/OAuth handlers; document connection now supports schema/initial JSON and improved cleanup.
9
+ - New Livekit support (client + protocol channel) and room participant hook; hosted toolkits are now shared per room to avoid duplicate starts.
10
+ - Breaking: `meshagent-react` no longer exports the legacy chat and file-upload modules.
11
+ - Tailwind chat UI is rebuilt with multi-thread support, new thread creation via agent tools, and file attachment utilities, with new exports for thread and conversation helpers.
12
+
1
13
  ## [0.38.2]
2
14
  - Stability
3
15
 
@@ -9,9 +9,33 @@ export interface DockerSecret {
9
9
  }
10
10
  export interface ContainerImage {
11
11
  id: string;
12
- tags: string[];
13
- size?: number;
12
+ preferredRef?: string | null;
13
+ references: string[];
14
14
  labels: Record<string, string>;
15
+ createdAt?: Date | null;
16
+ updatedAt?: Date | null;
17
+ targetMediaType?: string | null;
18
+ }
19
+ export interface ContainerImageDescriptor {
20
+ digest: string;
21
+ mediaType?: string | null;
22
+ size?: number;
23
+ annotations: Record<string, string>;
24
+ }
25
+ export interface ContainerImageManifest {
26
+ descriptor: ContainerImageDescriptor;
27
+ platformOs?: string | null;
28
+ platformArchitecture?: string | null;
29
+ platformVariant?: string | null;
30
+ }
31
+ export interface ContainerImageInspection {
32
+ image: ContainerImage;
33
+ target: ContainerImageDescriptor;
34
+ selectedManifest?: ContainerImageDescriptor | null;
35
+ manifests: ContainerImageManifest[];
36
+ config?: ContainerImageDescriptor | null;
37
+ layers: ContainerImageDescriptor[];
38
+ contentSize?: number;
15
39
  }
16
40
  export interface ImportedImage {
17
41
  resolvedRef: string;
@@ -96,6 +120,9 @@ export declare class ContainersClient {
96
120
  private unexpectedResponseError;
97
121
  private invoke;
98
122
  listImages(): Promise<ContainerImage[]>;
123
+ inspectImage(params: {
124
+ imageId: string;
125
+ }): Promise<ContainerImageInspection>;
99
126
  deleteImage(params: {
100
127
  image: string;
101
128
  }): Promise<void>;
@@ -52,6 +52,30 @@ function readOptionalIntegerField(data, field, operation) {
52
52
  }
53
53
  return value;
54
54
  }
55
+ function readOptionalStringField(data, field, operation) {
56
+ const value = data[field];
57
+ if (value === undefined || value === null) {
58
+ return undefined;
59
+ }
60
+ if (typeof value !== "string") {
61
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
62
+ }
63
+ return value;
64
+ }
65
+ function parseTimestampField(data, field, operation) {
66
+ const value = data[field];
67
+ if (value === undefined || value === null) {
68
+ return undefined;
69
+ }
70
+ if (typeof value !== "string") {
71
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
72
+ }
73
+ const timestamp = new Date(value);
74
+ if (Number.isNaN(timestamp.getTime())) {
75
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
76
+ }
77
+ return timestamp;
78
+ }
55
79
  function decodeUtf8(data, operation) {
56
80
  try {
57
81
  return new TextDecoder("utf-8", { fatal: true }).decode(data);
@@ -109,6 +133,98 @@ function normalizeImageLabels(labelsRaw, operation) {
109
133
  }
110
134
  throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
111
135
  }
136
+ function normalizeImageReferences(entry, operation) {
137
+ const referencesRaw = entry["references"];
138
+ if (Array.isArray(referencesRaw)) {
139
+ const references = referencesRaw.filter((item) => typeof item === "string");
140
+ if (references.length !== referencesRaw.length) {
141
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
142
+ }
143
+ return references;
144
+ }
145
+ const tagsRaw = entry["tags"];
146
+ if (Array.isArray(tagsRaw)) {
147
+ const references = tagsRaw.filter((item) => typeof item === "string");
148
+ if (references.length !== tagsRaw.length) {
149
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
150
+ }
151
+ return references;
152
+ }
153
+ if (referencesRaw === undefined || referencesRaw === null) {
154
+ return [];
155
+ }
156
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
157
+ }
158
+ function parseContainerImage(entry, operation) {
159
+ const references = normalizeImageReferences(entry, operation);
160
+ const preferredRef = readOptionalStringField(entry, "preferred_ref", operation) ?? references[0];
161
+ return {
162
+ id: readStringField(entry, "id", operation),
163
+ preferredRef,
164
+ references,
165
+ labels: normalizeImageLabels(entry["labels"], operation),
166
+ createdAt: parseTimestampField(entry, "created_at", operation),
167
+ updatedAt: parseTimestampField(entry, "updated_at", operation),
168
+ targetMediaType: readOptionalStringField(entry, "target_media_type", operation),
169
+ };
170
+ }
171
+ function parseContainerImageDescriptor(entry, operation) {
172
+ return {
173
+ digest: readStringField(entry, "digest", operation),
174
+ mediaType: readOptionalStringField(entry, "media_type", operation),
175
+ size: readOptionalIntegerField(entry, "size", operation),
176
+ annotations: normalizeImageLabels(entry["annotations"], operation),
177
+ };
178
+ }
179
+ function parseOptionalContainerImageDescriptor(value, operation) {
180
+ if (value === undefined || value === null) {
181
+ return undefined;
182
+ }
183
+ if (!isRecord(value)) {
184
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
185
+ }
186
+ return parseContainerImageDescriptor(value, operation);
187
+ }
188
+ function parseContainerImageManifest(entry, operation) {
189
+ const descriptorRaw = entry["descriptor"];
190
+ if (!isRecord(descriptorRaw)) {
191
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
192
+ }
193
+ return {
194
+ descriptor: parseContainerImageDescriptor(descriptorRaw, operation),
195
+ platformOs: readOptionalStringField(entry, "platform_os", operation),
196
+ platformArchitecture: readOptionalStringField(entry, "platform_architecture", operation),
197
+ platformVariant: readOptionalStringField(entry, "platform_variant", operation),
198
+ };
199
+ }
200
+ function parseContainerImageInspection(entry, operation) {
201
+ const imageRaw = entry["image"];
202
+ const targetRaw = entry["target"];
203
+ const manifestsRaw = entry["manifests"];
204
+ const layersRaw = entry["layers"];
205
+ if (!isRecord(imageRaw) || !isRecord(targetRaw) || !Array.isArray(manifestsRaw) || !Array.isArray(layersRaw)) {
206
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
207
+ }
208
+ return {
209
+ image: parseContainerImage(imageRaw, operation),
210
+ target: parseContainerImageDescriptor(targetRaw, operation),
211
+ selectedManifest: parseOptionalContainerImageDescriptor(entry["selected_manifest"], operation),
212
+ manifests: manifestsRaw.map((manifest) => {
213
+ if (!isRecord(manifest)) {
214
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
215
+ }
216
+ return parseContainerImageManifest(manifest, operation);
217
+ }),
218
+ config: parseOptionalContainerImageDescriptor(entry["config"], operation),
219
+ layers: layersRaw.map((layer) => {
220
+ if (!isRecord(layer)) {
221
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
222
+ }
223
+ return parseContainerImageDescriptor(layer, operation);
224
+ }),
225
+ contentSize: readOptionalIntegerField(entry, "content_size", operation),
226
+ };
227
+ }
112
228
  function parseImportedImage(data, operation) {
113
229
  const resolvedRef = data["resolved_ref"];
114
230
  const refsRaw = data["refs"];
@@ -303,23 +419,19 @@ class ContainersClient {
303
419
  if (!isRecord(entry)) {
304
420
  throw this.unexpectedResponseError("list_images");
305
421
  }
306
- const id = entry["id"];
307
- const tags = entry["tags"];
308
- const labelsRaw = entry["labels"];
309
- if (typeof id !== "string" || !Array.isArray(tags)) {
310
- throw this.unexpectedResponseError("list_images");
311
- }
312
- const normalizedTags = tags.filter((tag) => typeof tag === "string");
313
- const size = entry["size"];
314
- images.push({
315
- id,
316
- tags: normalizedTags,
317
- size: typeof size === "number" ? size : undefined,
318
- labels: normalizeImageLabels(labelsRaw, "list_images"),
319
- });
422
+ images.push(parseContainerImage(entry, "list_images"));
320
423
  }
321
424
  return images;
322
425
  }
426
+ async inspectImage(params) {
427
+ const output = await this.invoke("inspect_image", {
428
+ image_id: params.imageId,
429
+ });
430
+ if (!(output instanceof response_1.JsonContent) || !isRecord(output.json)) {
431
+ throw this.unexpectedResponseError("inspect_image");
432
+ }
433
+ return parseContainerImageInspection(output.json, "inspect_image");
434
+ }
323
435
  async deleteImage(params) {
324
436
  await this.invoke("delete_image", {
325
437
  image: params.image,
@@ -1,7 +1,7 @@
1
1
  import { MeshSchema } from './schema';
2
2
  import { RoomClient } from './room-client';
3
3
  import { ParticipantToken } from './participant-token';
4
- import { ProtocolFactory } from './protocol';
4
+ import type { ProtocolFactory } from './protocol';
5
5
  export declare function validateSchemaName(name: string): void;
6
6
  export declare function deploySchema({ room, schema, name, overwrite }: {
7
7
  room: RoomClient;
@@ -360,6 +360,11 @@ export declare class Meshagent {
360
360
  end?: Date;
361
361
  interval?: string;
362
362
  report?: string;
363
+ users?: string[];
364
+ room?: string;
365
+ provider?: string;
366
+ model?: string;
367
+ usageType?: string;
363
368
  }): Promise<Record<string, unknown>[]>;
364
369
  getSession(projectId: string, sessionId: string): Promise<Record<string, unknown>>;
365
370
  listActiveSessions(projectId: string): Promise<RoomSession[]>;
@@ -784,13 +784,18 @@ class Meshagent {
784
784
  });
785
785
  }
786
786
  async getUsage(projectId, options = {}) {
787
- const { start, end, interval, report } = options;
787
+ const { start, end, interval, report, users, room, provider, model, usageType } = options;
788
788
  const data = await this.request(`/accounts/projects/${projectId}/usage`, {
789
789
  query: {
790
790
  start: start ? start.toISOString() : undefined,
791
791
  end: end ? end.toISOString() : undefined,
792
792
  interval,
793
793
  report,
794
+ users: users && users.length > 0 ? users.join(",") : undefined,
795
+ room: room && room.trim().length > 0 ? room.trim() : undefined,
796
+ provider: provider && provider.trim().length > 0 ? provider.trim() : undefined,
797
+ model: model && model.trim().length > 0 ? model.trim() : undefined,
798
+ usage_type: usageType && usageType.trim().length > 0 ? usageType.trim() : undefined,
794
799
  },
795
800
  action: "retrieve usage",
796
801
  });
@@ -4,12 +4,12 @@ import { type EventHandler, type EventName } from "./event-emitter";
4
4
  import { MessagingClient } from "./messaging-client";
5
5
  import { MemoryClient } from "./memory-client";
6
6
  import { LocalParticipant } from "./participant";
7
- import { Protocol, ProtocolCloseKind, ProtocolFactory, type MessageHandler } from "./protocol";
7
+ import { Protocol, ProtocolCloseKind, type MessageHandler, type ProtocolFactory } from "./protocol";
8
8
  import { QueuesClient } from "./queues-client";
9
- import { Content } from "./response";
9
+ import type { Content } from "./response";
10
10
  import { RoomEvent } from "./room-event";
11
11
  import { RoomServerException } from "./room-server-client";
12
- import { SecretsClient } from "./secrets-client";
12
+ import { SecretsClient, type OAuthTokenRequestHandler, type SecretRequestHandler } from "./secrets-client";
13
13
  import { ServicesClient } from "./services-client";
14
14
  import { StorageClient } from "./storage-client";
15
15
  import { SyncClient } from "./sync-client";
@@ -91,9 +91,11 @@ export declare class RoomClient {
91
91
  private readonly _handleParticipantBound;
92
92
  private readonly _handleResponseBound;
93
93
  private readonly _handleToolCallResponseChunkBound;
94
- constructor({ protocolFactory, reconnectTimeout, }?: {
94
+ constructor({ protocolFactory, reconnectTimeout, oauthTokenRequestHandler, secretRequestHandler, }?: {
95
95
  protocolFactory?: ProtocolFactory | null;
96
96
  reconnectTimeout?: number | null;
97
+ oauthTokenRequestHandler?: OAuthTokenRequestHandler;
98
+ secretRequestHandler?: SecretRequestHandler;
97
99
  });
98
100
  get localParticipant(): LocalParticipant | null;
99
101
  get ready(): Promise<void>;
@@ -203,7 +203,7 @@ class RoomProtocolProxy {
203
203
  }
204
204
  exports.RoomProtocolProxy = RoomProtocolProxy;
205
205
  class RoomClient {
206
- constructor({ protocolFactory = null, reconnectTimeout = null, } = {}) {
206
+ constructor({ protocolFactory = null, reconnectTimeout = null, oauthTokenRequestHandler, secretRequestHandler, } = {}) {
207
207
  this._entered = false;
208
208
  this._allowDisconnectedRequests = false;
209
209
  this._eventsController = new stream_controller_1.StreamController();
@@ -250,7 +250,11 @@ class RoomClient {
250
250
  this.queues = new queues_client_1.QueuesClient({ room: this });
251
251
  this.database = new database_client_1.DatabaseClient({ room: this });
252
252
  this.agents = new agent_client_1.AgentsClient({ room: this });
253
- this.secrets = new secrets_client_1.SecretsClient({ room: this });
253
+ this.secrets = new secrets_client_1.SecretsClient({
254
+ room: this,
255
+ oauthTokenRequestHandler,
256
+ secretRequestHandler,
257
+ });
254
258
  this.containers = new containers_client_1.ContainersClient({ room: this });
255
259
  this.memory = new memory_client_1.MemoryClient({ room: this });
256
260
  this.services = new services_client_1.ServicesClient({ room: this });
@@ -2,8 +2,13 @@ import { RuntimeDocument } from "./document";
2
2
  import { MeshSchema } from "./schema";
3
3
  export type Uint8List = Uint8Array;
4
4
  export declare class RoomServerException extends Error {
5
+ readonly statusCode?: number;
5
6
  readonly code?: number;
6
- constructor(message: string, code?: number);
7
+ readonly retryable: boolean;
8
+ constructor(message: string, code?: number, { statusCode, retryable, }?: {
9
+ statusCode?: number;
10
+ retryable?: boolean;
11
+ });
7
12
  }
8
13
  export declare class MeshDocument extends RuntimeDocument {
9
14
  private _synchronized;
@@ -6,10 +6,12 @@ const document_1 = require("./document");
6
6
  const completer_1 = require("./completer");
7
7
  const runtime_1 = require("./runtime");
8
8
  class RoomServerException extends Error {
9
- constructor(message, code) {
9
+ constructor(message, code, { statusCode, retryable = false, } = {}) {
10
10
  super(message);
11
11
  this.name = "RoomServerException";
12
+ this.statusCode = statusCode;
12
13
  this.code = code;
14
+ this.retryable = retryable;
13
15
  }
14
16
  }
15
17
  exports.RoomServerException = RoomServerException;
@@ -9,9 +9,33 @@ export interface DockerSecret {
9
9
  }
10
10
  export interface ContainerImage {
11
11
  id: string;
12
- tags: string[];
13
- size?: number;
12
+ preferredRef?: string | null;
13
+ references: string[];
14
14
  labels: Record<string, string>;
15
+ createdAt?: Date | null;
16
+ updatedAt?: Date | null;
17
+ targetMediaType?: string | null;
18
+ }
19
+ export interface ContainerImageDescriptor {
20
+ digest: string;
21
+ mediaType?: string | null;
22
+ size?: number;
23
+ annotations: Record<string, string>;
24
+ }
25
+ export interface ContainerImageManifest {
26
+ descriptor: ContainerImageDescriptor;
27
+ platformOs?: string | null;
28
+ platformArchitecture?: string | null;
29
+ platformVariant?: string | null;
30
+ }
31
+ export interface ContainerImageInspection {
32
+ image: ContainerImage;
33
+ target: ContainerImageDescriptor;
34
+ selectedManifest?: ContainerImageDescriptor | null;
35
+ manifests: ContainerImageManifest[];
36
+ config?: ContainerImageDescriptor | null;
37
+ layers: ContainerImageDescriptor[];
38
+ contentSize?: number;
15
39
  }
16
40
  export interface ImportedImage {
17
41
  resolvedRef: string;
@@ -96,6 +120,9 @@ export declare class ContainersClient {
96
120
  private unexpectedResponseError;
97
121
  private invoke;
98
122
  listImages(): Promise<ContainerImage[]>;
123
+ inspectImage(params: {
124
+ imageId: string;
125
+ }): Promise<ContainerImageInspection>;
99
126
  deleteImage(params: {
100
127
  image: string;
101
128
  }): Promise<void>;
@@ -49,6 +49,30 @@ function readOptionalIntegerField(data, field, operation) {
49
49
  }
50
50
  return value;
51
51
  }
52
+ function readOptionalStringField(data, field, operation) {
53
+ const value = data[field];
54
+ if (value === undefined || value === null) {
55
+ return undefined;
56
+ }
57
+ if (typeof value !== "string") {
58
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
59
+ }
60
+ return value;
61
+ }
62
+ function parseTimestampField(data, field, operation) {
63
+ const value = data[field];
64
+ if (value === undefined || value === null) {
65
+ return undefined;
66
+ }
67
+ if (typeof value !== "string") {
68
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
69
+ }
70
+ const timestamp = new Date(value);
71
+ if (Number.isNaN(timestamp.getTime())) {
72
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
73
+ }
74
+ return timestamp;
75
+ }
52
76
  function decodeUtf8(data, operation) {
53
77
  try {
54
78
  return new TextDecoder("utf-8", { fatal: true }).decode(data);
@@ -106,6 +130,98 @@ function normalizeImageLabels(labelsRaw, operation) {
106
130
  }
107
131
  throw new RoomServerException(`unexpected return type from containers.${operation}`);
108
132
  }
133
+ function normalizeImageReferences(entry, operation) {
134
+ const referencesRaw = entry["references"];
135
+ if (Array.isArray(referencesRaw)) {
136
+ const references = referencesRaw.filter((item) => typeof item === "string");
137
+ if (references.length !== referencesRaw.length) {
138
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
139
+ }
140
+ return references;
141
+ }
142
+ const tagsRaw = entry["tags"];
143
+ if (Array.isArray(tagsRaw)) {
144
+ const references = tagsRaw.filter((item) => typeof item === "string");
145
+ if (references.length !== tagsRaw.length) {
146
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
147
+ }
148
+ return references;
149
+ }
150
+ if (referencesRaw === undefined || referencesRaw === null) {
151
+ return [];
152
+ }
153
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
154
+ }
155
+ function parseContainerImage(entry, operation) {
156
+ const references = normalizeImageReferences(entry, operation);
157
+ const preferredRef = readOptionalStringField(entry, "preferred_ref", operation) ?? references[0];
158
+ return {
159
+ id: readStringField(entry, "id", operation),
160
+ preferredRef,
161
+ references,
162
+ labels: normalizeImageLabels(entry["labels"], operation),
163
+ createdAt: parseTimestampField(entry, "created_at", operation),
164
+ updatedAt: parseTimestampField(entry, "updated_at", operation),
165
+ targetMediaType: readOptionalStringField(entry, "target_media_type", operation),
166
+ };
167
+ }
168
+ function parseContainerImageDescriptor(entry, operation) {
169
+ return {
170
+ digest: readStringField(entry, "digest", operation),
171
+ mediaType: readOptionalStringField(entry, "media_type", operation),
172
+ size: readOptionalIntegerField(entry, "size", operation),
173
+ annotations: normalizeImageLabels(entry["annotations"], operation),
174
+ };
175
+ }
176
+ function parseOptionalContainerImageDescriptor(value, operation) {
177
+ if (value === undefined || value === null) {
178
+ return undefined;
179
+ }
180
+ if (!isRecord(value)) {
181
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
182
+ }
183
+ return parseContainerImageDescriptor(value, operation);
184
+ }
185
+ function parseContainerImageManifest(entry, operation) {
186
+ const descriptorRaw = entry["descriptor"];
187
+ if (!isRecord(descriptorRaw)) {
188
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
189
+ }
190
+ return {
191
+ descriptor: parseContainerImageDescriptor(descriptorRaw, operation),
192
+ platformOs: readOptionalStringField(entry, "platform_os", operation),
193
+ platformArchitecture: readOptionalStringField(entry, "platform_architecture", operation),
194
+ platformVariant: readOptionalStringField(entry, "platform_variant", operation),
195
+ };
196
+ }
197
+ function parseContainerImageInspection(entry, operation) {
198
+ const imageRaw = entry["image"];
199
+ const targetRaw = entry["target"];
200
+ const manifestsRaw = entry["manifests"];
201
+ const layersRaw = entry["layers"];
202
+ if (!isRecord(imageRaw) || !isRecord(targetRaw) || !Array.isArray(manifestsRaw) || !Array.isArray(layersRaw)) {
203
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
204
+ }
205
+ return {
206
+ image: parseContainerImage(imageRaw, operation),
207
+ target: parseContainerImageDescriptor(targetRaw, operation),
208
+ selectedManifest: parseOptionalContainerImageDescriptor(entry["selected_manifest"], operation),
209
+ manifests: manifestsRaw.map((manifest) => {
210
+ if (!isRecord(manifest)) {
211
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
212
+ }
213
+ return parseContainerImageManifest(manifest, operation);
214
+ }),
215
+ config: parseOptionalContainerImageDescriptor(entry["config"], operation),
216
+ layers: layersRaw.map((layer) => {
217
+ if (!isRecord(layer)) {
218
+ throw new RoomServerException(`unexpected return type from containers.${operation}`);
219
+ }
220
+ return parseContainerImageDescriptor(layer, operation);
221
+ }),
222
+ contentSize: readOptionalIntegerField(entry, "content_size", operation),
223
+ };
224
+ }
109
225
  function parseImportedImage(data, operation) {
110
226
  const resolvedRef = data["resolved_ref"];
111
227
  const refsRaw = data["refs"];
@@ -299,23 +415,19 @@ export class ContainersClient {
299
415
  if (!isRecord(entry)) {
300
416
  throw this.unexpectedResponseError("list_images");
301
417
  }
302
- const id = entry["id"];
303
- const tags = entry["tags"];
304
- const labelsRaw = entry["labels"];
305
- if (typeof id !== "string" || !Array.isArray(tags)) {
306
- throw this.unexpectedResponseError("list_images");
307
- }
308
- const normalizedTags = tags.filter((tag) => typeof tag === "string");
309
- const size = entry["size"];
310
- images.push({
311
- id,
312
- tags: normalizedTags,
313
- size: typeof size === "number" ? size : undefined,
314
- labels: normalizeImageLabels(labelsRaw, "list_images"),
315
- });
418
+ images.push(parseContainerImage(entry, "list_images"));
316
419
  }
317
420
  return images;
318
421
  }
422
+ async inspectImage(params) {
423
+ const output = await this.invoke("inspect_image", {
424
+ image_id: params.imageId,
425
+ });
426
+ if (!(output instanceof JsonContent) || !isRecord(output.json)) {
427
+ throw this.unexpectedResponseError("inspect_image");
428
+ }
429
+ return parseContainerImageInspection(output.json, "inspect_image");
430
+ }
319
431
  async deleteImage(params) {
320
432
  await this.invoke("delete_image", {
321
433
  image: params.image,
@@ -1,7 +1,7 @@
1
1
  import { MeshSchema } from './schema';
2
2
  import { RoomClient } from './room-client';
3
3
  import { ParticipantToken } from './participant-token';
4
- import { ProtocolFactory } from './protocol';
4
+ import type { ProtocolFactory } from './protocol';
5
5
  export declare function validateSchemaName(name: string): void;
6
6
  export declare function deploySchema({ room, schema, name, overwrite }: {
7
7
  room: RoomClient;
@@ -360,6 +360,11 @@ export declare class Meshagent {
360
360
  end?: Date;
361
361
  interval?: string;
362
362
  report?: string;
363
+ users?: string[];
364
+ room?: string;
365
+ provider?: string;
366
+ model?: string;
367
+ usageType?: string;
363
368
  }): Promise<Record<string, unknown>[]>;
364
369
  getSession(projectId: string, sessionId: string): Promise<Record<string, unknown>>;
365
370
  listActiveSessions(projectId: string): Promise<RoomSession[]>;
@@ -781,13 +781,18 @@ export class Meshagent {
781
781
  });
782
782
  }
783
783
  async getUsage(projectId, options = {}) {
784
- const { start, end, interval, report } = options;
784
+ const { start, end, interval, report, users, room, provider, model, usageType } = options;
785
785
  const data = await this.request(`/accounts/projects/${projectId}/usage`, {
786
786
  query: {
787
787
  start: start ? start.toISOString() : undefined,
788
788
  end: end ? end.toISOString() : undefined,
789
789
  interval,
790
790
  report,
791
+ users: users && users.length > 0 ? users.join(",") : undefined,
792
+ room: room && room.trim().length > 0 ? room.trim() : undefined,
793
+ provider: provider && provider.trim().length > 0 ? provider.trim() : undefined,
794
+ model: model && model.trim().length > 0 ? model.trim() : undefined,
795
+ usage_type: usageType && usageType.trim().length > 0 ? usageType.trim() : undefined,
791
796
  },
792
797
  action: "retrieve usage",
793
798
  });
@@ -4,12 +4,12 @@ import { type EventHandler, type EventName } from "./event-emitter";
4
4
  import { MessagingClient } from "./messaging-client";
5
5
  import { MemoryClient } from "./memory-client";
6
6
  import { LocalParticipant } from "./participant";
7
- import { Protocol, ProtocolCloseKind, ProtocolFactory, type MessageHandler } from "./protocol";
7
+ import { Protocol, ProtocolCloseKind, type MessageHandler, type ProtocolFactory } from "./protocol";
8
8
  import { QueuesClient } from "./queues-client";
9
- import { Content } from "./response";
9
+ import type { Content } from "./response";
10
10
  import { RoomEvent } from "./room-event";
11
11
  import { RoomServerException } from "./room-server-client";
12
- import { SecretsClient } from "./secrets-client";
12
+ import { SecretsClient, type OAuthTokenRequestHandler, type SecretRequestHandler } from "./secrets-client";
13
13
  import { ServicesClient } from "./services-client";
14
14
  import { StorageClient } from "./storage-client";
15
15
  import { SyncClient } from "./sync-client";
@@ -91,9 +91,11 @@ export declare class RoomClient {
91
91
  private readonly _handleParticipantBound;
92
92
  private readonly _handleResponseBound;
93
93
  private readonly _handleToolCallResponseChunkBound;
94
- constructor({ protocolFactory, reconnectTimeout, }?: {
94
+ constructor({ protocolFactory, reconnectTimeout, oauthTokenRequestHandler, secretRequestHandler, }?: {
95
95
  protocolFactory?: ProtocolFactory | null;
96
96
  reconnectTimeout?: number | null;
97
+ oauthTokenRequestHandler?: OAuthTokenRequestHandler;
98
+ secretRequestHandler?: SecretRequestHandler;
97
99
  });
98
100
  get localParticipant(): LocalParticipant | null;
99
101
  get ready(): Promise<void>;
@@ -199,7 +199,7 @@ export class RoomProtocolProxy {
199
199
  }
200
200
  }
201
201
  export class RoomClient {
202
- constructor({ protocolFactory = null, reconnectTimeout = null, } = {}) {
202
+ constructor({ protocolFactory = null, reconnectTimeout = null, oauthTokenRequestHandler, secretRequestHandler, } = {}) {
203
203
  this._entered = false;
204
204
  this._allowDisconnectedRequests = false;
205
205
  this._eventsController = new StreamController();
@@ -246,7 +246,11 @@ export class RoomClient {
246
246
  this.queues = new QueuesClient({ room: this });
247
247
  this.database = new DatabaseClient({ room: this });
248
248
  this.agents = new AgentsClient({ room: this });
249
- this.secrets = new SecretsClient({ room: this });
249
+ this.secrets = new SecretsClient({
250
+ room: this,
251
+ oauthTokenRequestHandler,
252
+ secretRequestHandler,
253
+ });
250
254
  this.containers = new ContainersClient({ room: this });
251
255
  this.memory = new MemoryClient({ room: this });
252
256
  this.services = new ServicesClient({ room: this });
@@ -2,8 +2,13 @@ import { RuntimeDocument } from "./document";
2
2
  import { MeshSchema } from "./schema";
3
3
  export type Uint8List = Uint8Array;
4
4
  export declare class RoomServerException extends Error {
5
+ readonly statusCode?: number;
5
6
  readonly code?: number;
6
- constructor(message: string, code?: number);
7
+ readonly retryable: boolean;
8
+ constructor(message: string, code?: number, { statusCode, retryable, }?: {
9
+ statusCode?: number;
10
+ retryable?: boolean;
11
+ });
7
12
  }
8
13
  export declare class MeshDocument extends RuntimeDocument {
9
14
  private _synchronized;
@@ -3,10 +3,12 @@ import { RuntimeDocument } from "./document";
3
3
  import { Completer } from "./completer";
4
4
  import { registerDocument, unregisterDocument, applyChanges, getState, getStateVector, } from "./runtime";
5
5
  export class RoomServerException extends Error {
6
- constructor(message, code) {
6
+ constructor(message, code, { statusCode, retryable = false, } = {}) {
7
7
  super(message);
8
8
  this.name = "RoomServerException";
9
+ this.statusCode = statusCode;
9
10
  this.code = code;
11
+ this.retryable = retryable;
10
12
  }
11
13
  }
12
14
  export class MeshDocument extends RuntimeDocument {
@@ -9,9 +9,33 @@ export interface DockerSecret {
9
9
  }
10
10
  export interface ContainerImage {
11
11
  id: string;
12
- tags: string[];
13
- size?: number;
12
+ preferredRef?: string | null;
13
+ references: string[];
14
14
  labels: Record<string, string>;
15
+ createdAt?: Date | null;
16
+ updatedAt?: Date | null;
17
+ targetMediaType?: string | null;
18
+ }
19
+ export interface ContainerImageDescriptor {
20
+ digest: string;
21
+ mediaType?: string | null;
22
+ size?: number;
23
+ annotations: Record<string, string>;
24
+ }
25
+ export interface ContainerImageManifest {
26
+ descriptor: ContainerImageDescriptor;
27
+ platformOs?: string | null;
28
+ platformArchitecture?: string | null;
29
+ platformVariant?: string | null;
30
+ }
31
+ export interface ContainerImageInspection {
32
+ image: ContainerImage;
33
+ target: ContainerImageDescriptor;
34
+ selectedManifest?: ContainerImageDescriptor | null;
35
+ manifests: ContainerImageManifest[];
36
+ config?: ContainerImageDescriptor | null;
37
+ layers: ContainerImageDescriptor[];
38
+ contentSize?: number;
15
39
  }
16
40
  export interface ImportedImage {
17
41
  resolvedRef: string;
@@ -96,6 +120,9 @@ export declare class ContainersClient {
96
120
  private unexpectedResponseError;
97
121
  private invoke;
98
122
  listImages(): Promise<ContainerImage[]>;
123
+ inspectImage(params: {
124
+ imageId: string;
125
+ }): Promise<ContainerImageInspection>;
99
126
  deleteImage(params: {
100
127
  image: string;
101
128
  }): Promise<void>;
@@ -52,6 +52,30 @@ function readOptionalIntegerField(data, field, operation) {
52
52
  }
53
53
  return value;
54
54
  }
55
+ function readOptionalStringField(data, field, operation) {
56
+ const value = data[field];
57
+ if (value === undefined || value === null) {
58
+ return undefined;
59
+ }
60
+ if (typeof value !== "string") {
61
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
62
+ }
63
+ return value;
64
+ }
65
+ function parseTimestampField(data, field, operation) {
66
+ const value = data[field];
67
+ if (value === undefined || value === null) {
68
+ return undefined;
69
+ }
70
+ if (typeof value !== "string") {
71
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
72
+ }
73
+ const timestamp = new Date(value);
74
+ if (Number.isNaN(timestamp.getTime())) {
75
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
76
+ }
77
+ return timestamp;
78
+ }
55
79
  function decodeUtf8(data, operation) {
56
80
  try {
57
81
  return new TextDecoder("utf-8", { fatal: true }).decode(data);
@@ -109,6 +133,98 @@ function normalizeImageLabels(labelsRaw, operation) {
109
133
  }
110
134
  throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
111
135
  }
136
+ function normalizeImageReferences(entry, operation) {
137
+ const referencesRaw = entry["references"];
138
+ if (Array.isArray(referencesRaw)) {
139
+ const references = referencesRaw.filter((item) => typeof item === "string");
140
+ if (references.length !== referencesRaw.length) {
141
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
142
+ }
143
+ return references;
144
+ }
145
+ const tagsRaw = entry["tags"];
146
+ if (Array.isArray(tagsRaw)) {
147
+ const references = tagsRaw.filter((item) => typeof item === "string");
148
+ if (references.length !== tagsRaw.length) {
149
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
150
+ }
151
+ return references;
152
+ }
153
+ if (referencesRaw === undefined || referencesRaw === null) {
154
+ return [];
155
+ }
156
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
157
+ }
158
+ function parseContainerImage(entry, operation) {
159
+ const references = normalizeImageReferences(entry, operation);
160
+ const preferredRef = readOptionalStringField(entry, "preferred_ref", operation) ?? references[0];
161
+ return {
162
+ id: readStringField(entry, "id", operation),
163
+ preferredRef,
164
+ references,
165
+ labels: normalizeImageLabels(entry["labels"], operation),
166
+ createdAt: parseTimestampField(entry, "created_at", operation),
167
+ updatedAt: parseTimestampField(entry, "updated_at", operation),
168
+ targetMediaType: readOptionalStringField(entry, "target_media_type", operation),
169
+ };
170
+ }
171
+ function parseContainerImageDescriptor(entry, operation) {
172
+ return {
173
+ digest: readStringField(entry, "digest", operation),
174
+ mediaType: readOptionalStringField(entry, "media_type", operation),
175
+ size: readOptionalIntegerField(entry, "size", operation),
176
+ annotations: normalizeImageLabels(entry["annotations"], operation),
177
+ };
178
+ }
179
+ function parseOptionalContainerImageDescriptor(value, operation) {
180
+ if (value === undefined || value === null) {
181
+ return undefined;
182
+ }
183
+ if (!isRecord(value)) {
184
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
185
+ }
186
+ return parseContainerImageDescriptor(value, operation);
187
+ }
188
+ function parseContainerImageManifest(entry, operation) {
189
+ const descriptorRaw = entry["descriptor"];
190
+ if (!isRecord(descriptorRaw)) {
191
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
192
+ }
193
+ return {
194
+ descriptor: parseContainerImageDescriptor(descriptorRaw, operation),
195
+ platformOs: readOptionalStringField(entry, "platform_os", operation),
196
+ platformArchitecture: readOptionalStringField(entry, "platform_architecture", operation),
197
+ platformVariant: readOptionalStringField(entry, "platform_variant", operation),
198
+ };
199
+ }
200
+ function parseContainerImageInspection(entry, operation) {
201
+ const imageRaw = entry["image"];
202
+ const targetRaw = entry["target"];
203
+ const manifestsRaw = entry["manifests"];
204
+ const layersRaw = entry["layers"];
205
+ if (!isRecord(imageRaw) || !isRecord(targetRaw) || !Array.isArray(manifestsRaw) || !Array.isArray(layersRaw)) {
206
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
207
+ }
208
+ return {
209
+ image: parseContainerImage(imageRaw, operation),
210
+ target: parseContainerImageDescriptor(targetRaw, operation),
211
+ selectedManifest: parseOptionalContainerImageDescriptor(entry["selected_manifest"], operation),
212
+ manifests: manifestsRaw.map((manifest) => {
213
+ if (!isRecord(manifest)) {
214
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
215
+ }
216
+ return parseContainerImageManifest(manifest, operation);
217
+ }),
218
+ config: parseOptionalContainerImageDescriptor(entry["config"], operation),
219
+ layers: layersRaw.map((layer) => {
220
+ if (!isRecord(layer)) {
221
+ throw new room_server_client_1.RoomServerException(`unexpected return type from containers.${operation}`);
222
+ }
223
+ return parseContainerImageDescriptor(layer, operation);
224
+ }),
225
+ contentSize: readOptionalIntegerField(entry, "content_size", operation),
226
+ };
227
+ }
112
228
  function parseImportedImage(data, operation) {
113
229
  const resolvedRef = data["resolved_ref"];
114
230
  const refsRaw = data["refs"];
@@ -303,23 +419,19 @@ class ContainersClient {
303
419
  if (!isRecord(entry)) {
304
420
  throw this.unexpectedResponseError("list_images");
305
421
  }
306
- const id = entry["id"];
307
- const tags = entry["tags"];
308
- const labelsRaw = entry["labels"];
309
- if (typeof id !== "string" || !Array.isArray(tags)) {
310
- throw this.unexpectedResponseError("list_images");
311
- }
312
- const normalizedTags = tags.filter((tag) => typeof tag === "string");
313
- const size = entry["size"];
314
- images.push({
315
- id,
316
- tags: normalizedTags,
317
- size: typeof size === "number" ? size : undefined,
318
- labels: normalizeImageLabels(labelsRaw, "list_images"),
319
- });
422
+ images.push(parseContainerImage(entry, "list_images"));
320
423
  }
321
424
  return images;
322
425
  }
426
+ async inspectImage(params) {
427
+ const output = await this.invoke("inspect_image", {
428
+ image_id: params.imageId,
429
+ });
430
+ if (!(output instanceof response_1.JsonContent) || !isRecord(output.json)) {
431
+ throw this.unexpectedResponseError("inspect_image");
432
+ }
433
+ return parseContainerImageInspection(output.json, "inspect_image");
434
+ }
323
435
  async deleteImage(params) {
324
436
  await this.invoke("delete_image", {
325
437
  image: params.image,
@@ -1,7 +1,7 @@
1
1
  import { MeshSchema } from './schema';
2
2
  import { RoomClient } from './room-client';
3
3
  import { ParticipantToken } from './participant-token';
4
- import { ProtocolFactory } from './protocol';
4
+ import type { ProtocolFactory } from './protocol';
5
5
  export declare function validateSchemaName(name: string): void;
6
6
  export declare function deploySchema({ room, schema, name, overwrite }: {
7
7
  room: RoomClient;
@@ -360,6 +360,11 @@ export declare class Meshagent {
360
360
  end?: Date;
361
361
  interval?: string;
362
362
  report?: string;
363
+ users?: string[];
364
+ room?: string;
365
+ provider?: string;
366
+ model?: string;
367
+ usageType?: string;
363
368
  }): Promise<Record<string, unknown>[]>;
364
369
  getSession(projectId: string, sessionId: string): Promise<Record<string, unknown>>;
365
370
  listActiveSessions(projectId: string): Promise<RoomSession[]>;
@@ -784,13 +784,18 @@ class Meshagent {
784
784
  });
785
785
  }
786
786
  async getUsage(projectId, options = {}) {
787
- const { start, end, interval, report } = options;
787
+ const { start, end, interval, report, users, room, provider, model, usageType } = options;
788
788
  const data = await this.request(`/accounts/projects/${projectId}/usage`, {
789
789
  query: {
790
790
  start: start ? start.toISOString() : undefined,
791
791
  end: end ? end.toISOString() : undefined,
792
792
  interval,
793
793
  report,
794
+ users: users && users.length > 0 ? users.join(",") : undefined,
795
+ room: room && room.trim().length > 0 ? room.trim() : undefined,
796
+ provider: provider && provider.trim().length > 0 ? provider.trim() : undefined,
797
+ model: model && model.trim().length > 0 ? model.trim() : undefined,
798
+ usage_type: usageType && usageType.trim().length > 0 ? usageType.trim() : undefined,
794
799
  },
795
800
  action: "retrieve usage",
796
801
  });
@@ -4,12 +4,12 @@ import { type EventHandler, type EventName } from "./event-emitter";
4
4
  import { MessagingClient } from "./messaging-client";
5
5
  import { MemoryClient } from "./memory-client";
6
6
  import { LocalParticipant } from "./participant";
7
- import { Protocol, ProtocolCloseKind, ProtocolFactory, type MessageHandler } from "./protocol";
7
+ import { Protocol, ProtocolCloseKind, type MessageHandler, type ProtocolFactory } from "./protocol";
8
8
  import { QueuesClient } from "./queues-client";
9
- import { Content } from "./response";
9
+ import type { Content } from "./response";
10
10
  import { RoomEvent } from "./room-event";
11
11
  import { RoomServerException } from "./room-server-client";
12
- import { SecretsClient } from "./secrets-client";
12
+ import { SecretsClient, type OAuthTokenRequestHandler, type SecretRequestHandler } from "./secrets-client";
13
13
  import { ServicesClient } from "./services-client";
14
14
  import { StorageClient } from "./storage-client";
15
15
  import { SyncClient } from "./sync-client";
@@ -91,9 +91,11 @@ export declare class RoomClient {
91
91
  private readonly _handleParticipantBound;
92
92
  private readonly _handleResponseBound;
93
93
  private readonly _handleToolCallResponseChunkBound;
94
- constructor({ protocolFactory, reconnectTimeout, }?: {
94
+ constructor({ protocolFactory, reconnectTimeout, oauthTokenRequestHandler, secretRequestHandler, }?: {
95
95
  protocolFactory?: ProtocolFactory | null;
96
96
  reconnectTimeout?: number | null;
97
+ oauthTokenRequestHandler?: OAuthTokenRequestHandler;
98
+ secretRequestHandler?: SecretRequestHandler;
97
99
  });
98
100
  get localParticipant(): LocalParticipant | null;
99
101
  get ready(): Promise<void>;
@@ -203,7 +203,7 @@ class RoomProtocolProxy {
203
203
  }
204
204
  exports.RoomProtocolProxy = RoomProtocolProxy;
205
205
  class RoomClient {
206
- constructor({ protocolFactory = null, reconnectTimeout = null, } = {}) {
206
+ constructor({ protocolFactory = null, reconnectTimeout = null, oauthTokenRequestHandler, secretRequestHandler, } = {}) {
207
207
  this._entered = false;
208
208
  this._allowDisconnectedRequests = false;
209
209
  this._eventsController = new stream_controller_1.StreamController();
@@ -250,7 +250,11 @@ class RoomClient {
250
250
  this.queues = new queues_client_1.QueuesClient({ room: this });
251
251
  this.database = new database_client_1.DatabaseClient({ room: this });
252
252
  this.agents = new agent_client_1.AgentsClient({ room: this });
253
- this.secrets = new secrets_client_1.SecretsClient({ room: this });
253
+ this.secrets = new secrets_client_1.SecretsClient({
254
+ room: this,
255
+ oauthTokenRequestHandler,
256
+ secretRequestHandler,
257
+ });
254
258
  this.containers = new containers_client_1.ContainersClient({ room: this });
255
259
  this.memory = new memory_client_1.MemoryClient({ room: this });
256
260
  this.services = new services_client_1.ServicesClient({ room: this });
@@ -2,8 +2,13 @@ import { RuntimeDocument } from "./document";
2
2
  import { MeshSchema } from "./schema";
3
3
  export type Uint8List = Uint8Array;
4
4
  export declare class RoomServerException extends Error {
5
+ readonly statusCode?: number;
5
6
  readonly code?: number;
6
- constructor(message: string, code?: number);
7
+ readonly retryable: boolean;
8
+ constructor(message: string, code?: number, { statusCode, retryable, }?: {
9
+ statusCode?: number;
10
+ retryable?: boolean;
11
+ });
7
12
  }
8
13
  export declare class MeshDocument extends RuntimeDocument {
9
14
  private _synchronized;
@@ -6,10 +6,12 @@ const document_1 = require("./document");
6
6
  const completer_1 = require("./completer");
7
7
  const runtime_1 = require("./runtime");
8
8
  class RoomServerException extends Error {
9
- constructor(message, code) {
9
+ constructor(message, code, { statusCode, retryable = false, } = {}) {
10
10
  super(message);
11
11
  this.name = "RoomServerException";
12
+ this.statusCode = statusCode;
12
13
  this.code = code;
14
+ this.retryable = retryable;
13
15
  }
14
16
  }
15
17
  exports.RoomServerException = RoomServerException;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshagent/meshagent",
3
- "version": "0.38.2",
3
+ "version": "0.38.4",
4
4
  "description": "Meshagent Client",
5
5
  "homepage": "https://github.com/meshagent/meshagent-ts",
6
6
  "scripts": {