@meshagent/meshagent 0.41.7 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [0.42.0]
2
+ - Added project lookup by key.
3
+ - Container and room APIs now return structured `containerPort`/`hostPort` entries instead of integer port lists, which is a breaking response-shape change.
4
+ - `ContainerSpec`, `PortSpec`, and `RoutePathSpec` now support `template`, `host_port`, and `stripPrefix`, and room service URL resolution uses `host_port` when available.
5
+ - `createRoom` now serializes typed permissions, and container creation now accepts a `template` option.
6
+
7
+ ## [0.41.10]
8
+ - Stability
9
+
10
+ ## [0.41.9]
11
+ - Stability
12
+
13
+ ## [0.41.8]
14
+ - Stability
15
+
1
16
  ## [0.41.7]
2
17
  - Stability
3
18
 
@@ -52,11 +52,15 @@ export interface ContainerParticipantInfo {
52
52
  id: string;
53
53
  name: string;
54
54
  }
55
+ export interface RoomContainerPort {
56
+ containerPort: number;
57
+ hostPort: number;
58
+ }
55
59
  export interface RoomContainer {
56
60
  id: string;
57
61
  image: string;
58
62
  name?: string;
59
- ports: number[];
63
+ ports: RoomContainerPort[];
60
64
  startedBy: ContainerParticipantInfo;
61
65
  state: string;
62
66
  private: boolean;
@@ -170,6 +174,7 @@ export declare class ContainersClient {
170
174
  credentials?: DockerSecret[];
171
175
  name?: string;
172
176
  mounts?: ContainerMountSpec;
177
+ template?: "agent" | "none";
173
178
  writableRootFs?: boolean;
174
179
  private?: boolean;
175
180
  }): Promise<string>;
@@ -504,6 +504,7 @@ class ContainersClient {
504
504
  credentials: toCredentials(params.credentials ?? []),
505
505
  name: params.name,
506
506
  mounts: params.mounts,
507
+ template: params.template,
507
508
  writable_root_fs: params.writableRootFs,
508
509
  private: params.private,
509
510
  });
@@ -889,14 +890,27 @@ class ContainersClient {
889
890
  const nameRaw = entry["name"];
890
891
  const portsRaw = entry["ports"];
891
892
  const serviceIdRaw = entry["service_id"];
892
- if (!Array.isArray(portsRaw) || !portsRaw.every((port) => typeof port === "number" && Number.isInteger(port))) {
893
+ if (!Array.isArray(portsRaw) ||
894
+ !portsRaw.every((port) => {
895
+ if (!isRecord(port)) {
896
+ return false;
897
+ }
898
+ return (typeof port["container_port"] === "number" &&
899
+ Number.isInteger(port["container_port"]) &&
900
+ typeof port["host_port"] === "number" &&
901
+ Number.isInteger(port["host_port"]));
902
+ })) {
893
903
  throw this.unexpectedResponseError("list");
894
904
  }
905
+ const ports = portsRaw.map((port) => ({
906
+ containerPort: port["container_port"],
907
+ hostPort: port["host_port"],
908
+ }));
895
909
  items.push({
896
910
  id,
897
911
  image,
898
912
  name: typeof nameRaw === "string" ? nameRaw : undefined,
899
- ports: portsRaw,
913
+ ports,
900
914
  startedBy: {
901
915
  id: startedById,
902
916
  name: startedByName,
@@ -148,6 +148,7 @@ export interface ServiceMetadata {
148
148
  }
149
149
  export interface ContainerSpec {
150
150
  private?: boolean | null;
151
+ template?: "agent" | "none" | null;
151
152
  command?: string | null;
152
153
  working_dir?: string | null;
153
154
  image: string;
@@ -193,9 +194,13 @@ export interface EndpointSpec {
193
194
  }
194
195
  export interface PortSpec {
195
196
  num: "*" | number;
197
+ host_port?: number | null;
196
198
  type?: "http" | "tcp" | null;
199
+ published?: boolean | null;
200
+ public?: boolean | null;
197
201
  endpoints?: EndpointSpec[];
198
202
  liveness?: string | null;
203
+ annotations?: Record<string, string>;
199
204
  }
200
205
  export interface ServiceSpec {
201
206
  version: "v1";
@@ -221,6 +226,7 @@ export interface RouteBackend {
221
226
  export interface RoutePathSpec {
222
227
  path?: string;
223
228
  pathType?: "prefix" | "exact";
229
+ stripPrefix?: boolean;
224
230
  targetPort: string | number;
225
231
  }
226
232
  export interface RouteSpec {
@@ -432,6 +438,7 @@ export declare class Meshagent {
432
438
  updateUserProfile(userId: string, firstName: string, lastName: string): Promise<Record<string, unknown>>;
433
439
  listProjects(): Promise<Record<string, unknown>>;
434
440
  getProject(projectId: string): Promise<Record<string, unknown>>;
441
+ getProjectByKey(projectKey: string): Promise<Record<string, unknown>>;
435
442
  createApiKey(projectId: string, name: string, description: string): Promise<Record<string, unknown>>;
436
443
  deleteApiKey(projectId: string, id: string): Promise<void>;
437
444
  listApiKeys(projectId: string): Promise<Record<string, unknown>>;
@@ -842,6 +842,11 @@ class Meshagent {
842
842
  action: "get project",
843
843
  });
844
844
  }
845
+ async getProjectByKey(projectKey) {
846
+ return await this.request(`/accounts/projects/by-key/${encodeURIComponent(projectKey)}`, {
847
+ action: "get project by key",
848
+ });
849
+ }
845
850
  async createApiKey(projectId, name, description) {
846
851
  return await this.request(`/accounts/projects/${projectId}/api-keys`, {
847
852
  method: "POST",
@@ -221,7 +221,7 @@ function bracketIpv6Host(host) {
221
221
  }
222
222
  function roomServiceMcpServerUrl({ service, port, endpoint, }) {
223
223
  const endpointPath = normalizeEndpointPath(endpoint.path);
224
- const portValue = typeof port.num === "number" ? port.num : null;
224
+ const portValue = port.host_port ?? (typeof port.num === "number" ? port.num : null);
225
225
  if (service.external == null) {
226
226
  if (portValue == null) {
227
227
  return `http://localhost${endpointPath}`;
@@ -52,11 +52,15 @@ export interface ContainerParticipantInfo {
52
52
  id: string;
53
53
  name: string;
54
54
  }
55
+ export interface RoomContainerPort {
56
+ containerPort: number;
57
+ hostPort: number;
58
+ }
55
59
  export interface RoomContainer {
56
60
  id: string;
57
61
  image: string;
58
62
  name?: string;
59
- ports: number[];
63
+ ports: RoomContainerPort[];
60
64
  startedBy: ContainerParticipantInfo;
61
65
  state: string;
62
66
  private: boolean;
@@ -170,6 +174,7 @@ export declare class ContainersClient {
170
174
  credentials?: DockerSecret[];
171
175
  name?: string;
172
176
  mounts?: ContainerMountSpec;
177
+ template?: "agent" | "none";
173
178
  writableRootFs?: boolean;
174
179
  private?: boolean;
175
180
  }): Promise<string>;
@@ -504,6 +504,7 @@ class ContainersClient {
504
504
  credentials: toCredentials(params.credentials ?? []),
505
505
  name: params.name,
506
506
  mounts: params.mounts,
507
+ template: params.template,
507
508
  writable_root_fs: params.writableRootFs,
508
509
  private: params.private,
509
510
  });
@@ -889,14 +890,27 @@ class ContainersClient {
889
890
  const nameRaw = entry["name"];
890
891
  const portsRaw = entry["ports"];
891
892
  const serviceIdRaw = entry["service_id"];
892
- if (!Array.isArray(portsRaw) || !portsRaw.every((port) => typeof port === "number" && Number.isInteger(port))) {
893
+ if (!Array.isArray(portsRaw) ||
894
+ !portsRaw.every((port) => {
895
+ if (!isRecord(port)) {
896
+ return false;
897
+ }
898
+ return (typeof port["container_port"] === "number" &&
899
+ Number.isInteger(port["container_port"]) &&
900
+ typeof port["host_port"] === "number" &&
901
+ Number.isInteger(port["host_port"]));
902
+ })) {
893
903
  throw this.unexpectedResponseError("list");
894
904
  }
905
+ const ports = portsRaw.map((port) => ({
906
+ containerPort: port["container_port"],
907
+ hostPort: port["host_port"],
908
+ }));
895
909
  items.push({
896
910
  id,
897
911
  image,
898
912
  name: typeof nameRaw === "string" ? nameRaw : undefined,
899
- ports: portsRaw,
913
+ ports,
900
914
  startedBy: {
901
915
  id: startedById,
902
916
  name: startedByName,
@@ -148,6 +148,7 @@ export interface ServiceMetadata {
148
148
  }
149
149
  export interface ContainerSpec {
150
150
  private?: boolean | null;
151
+ template?: "agent" | "none" | null;
151
152
  command?: string | null;
152
153
  working_dir?: string | null;
153
154
  image: string;
@@ -193,9 +194,13 @@ export interface EndpointSpec {
193
194
  }
194
195
  export interface PortSpec {
195
196
  num: "*" | number;
197
+ host_port?: number | null;
196
198
  type?: "http" | "tcp" | null;
199
+ published?: boolean | null;
200
+ public?: boolean | null;
197
201
  endpoints?: EndpointSpec[];
198
202
  liveness?: string | null;
203
+ annotations?: Record<string, string>;
199
204
  }
200
205
  export interface ServiceSpec {
201
206
  version: "v1";
@@ -221,6 +226,7 @@ export interface RouteBackend {
221
226
  export interface RoutePathSpec {
222
227
  path?: string;
223
228
  pathType?: "prefix" | "exact";
229
+ stripPrefix?: boolean;
224
230
  targetPort: string | number;
225
231
  }
226
232
  export interface RouteSpec {
@@ -432,6 +438,7 @@ export declare class Meshagent {
432
438
  updateUserProfile(userId: string, firstName: string, lastName: string): Promise<Record<string, unknown>>;
433
439
  listProjects(): Promise<Record<string, unknown>>;
434
440
  getProject(projectId: string): Promise<Record<string, unknown>>;
441
+ getProjectByKey(projectKey: string): Promise<Record<string, unknown>>;
435
442
  createApiKey(projectId: string, name: string, description: string): Promise<Record<string, unknown>>;
436
443
  deleteApiKey(projectId: string, id: string): Promise<void>;
437
444
  listApiKeys(projectId: string): Promise<Record<string, unknown>>;
@@ -842,6 +842,11 @@ class Meshagent {
842
842
  action: "get project",
843
843
  });
844
844
  }
845
+ async getProjectByKey(projectKey) {
846
+ return await this.request(`/accounts/projects/by-key/${encodeURIComponent(projectKey)}`, {
847
+ action: "get project by key",
848
+ });
849
+ }
845
850
  async createApiKey(projectId, name, description) {
846
851
  return await this.request(`/accounts/projects/${projectId}/api-keys`, {
847
852
  method: "POST",
@@ -221,7 +221,7 @@ function bracketIpv6Host(host) {
221
221
  }
222
222
  function roomServiceMcpServerUrl({ service, port, endpoint, }) {
223
223
  const endpointPath = normalizeEndpointPath(endpoint.path);
224
- const portValue = typeof port.num === "number" ? port.num : null;
224
+ const portValue = port.host_port ?? (typeof port.num === "number" ? port.num : null);
225
225
  if (service.external == null) {
226
226
  if (portValue == null) {
227
227
  return `http://localhost${endpointPath}`;
@@ -52,11 +52,15 @@ export interface ContainerParticipantInfo {
52
52
  id: string;
53
53
  name: string;
54
54
  }
55
+ export interface RoomContainerPort {
56
+ containerPort: number;
57
+ hostPort: number;
58
+ }
55
59
  export interface RoomContainer {
56
60
  id: string;
57
61
  image: string;
58
62
  name?: string;
59
- ports: number[];
63
+ ports: RoomContainerPort[];
60
64
  startedBy: ContainerParticipantInfo;
61
65
  state: string;
62
66
  private: boolean;
@@ -170,6 +174,7 @@ export declare class ContainersClient {
170
174
  credentials?: DockerSecret[];
171
175
  name?: string;
172
176
  mounts?: ContainerMountSpec;
177
+ template?: "agent" | "none";
173
178
  writableRootFs?: boolean;
174
179
  private?: boolean;
175
180
  }): Promise<string>;
@@ -504,6 +504,7 @@ class ContainersClient {
504
504
  credentials: toCredentials(params.credentials ?? []),
505
505
  name: params.name,
506
506
  mounts: params.mounts,
507
+ template: params.template,
507
508
  writable_root_fs: params.writableRootFs,
508
509
  private: params.private,
509
510
  });
@@ -889,14 +890,27 @@ class ContainersClient {
889
890
  const nameRaw = entry["name"];
890
891
  const portsRaw = entry["ports"];
891
892
  const serviceIdRaw = entry["service_id"];
892
- if (!Array.isArray(portsRaw) || !portsRaw.every((port) => typeof port === "number" && Number.isInteger(port))) {
893
+ if (!Array.isArray(portsRaw) ||
894
+ !portsRaw.every((port) => {
895
+ if (!isRecord(port)) {
896
+ return false;
897
+ }
898
+ return (typeof port["container_port"] === "number" &&
899
+ Number.isInteger(port["container_port"]) &&
900
+ typeof port["host_port"] === "number" &&
901
+ Number.isInteger(port["host_port"]));
902
+ })) {
893
903
  throw this.unexpectedResponseError("list");
894
904
  }
905
+ const ports = portsRaw.map((port) => ({
906
+ containerPort: port["container_port"],
907
+ hostPort: port["host_port"],
908
+ }));
895
909
  items.push({
896
910
  id,
897
911
  image,
898
912
  name: typeof nameRaw === "string" ? nameRaw : undefined,
899
- ports: portsRaw,
913
+ ports,
900
914
  startedBy: {
901
915
  id: startedById,
902
916
  name: startedByName,
@@ -148,6 +148,7 @@ export interface ServiceMetadata {
148
148
  }
149
149
  export interface ContainerSpec {
150
150
  private?: boolean | null;
151
+ template?: "agent" | "none" | null;
151
152
  command?: string | null;
152
153
  working_dir?: string | null;
153
154
  image: string;
@@ -193,9 +194,13 @@ export interface EndpointSpec {
193
194
  }
194
195
  export interface PortSpec {
195
196
  num: "*" | number;
197
+ host_port?: number | null;
196
198
  type?: "http" | "tcp" | null;
199
+ published?: boolean | null;
200
+ public?: boolean | null;
197
201
  endpoints?: EndpointSpec[];
198
202
  liveness?: string | null;
203
+ annotations?: Record<string, string>;
199
204
  }
200
205
  export interface ServiceSpec {
201
206
  version: "v1";
@@ -221,6 +226,7 @@ export interface RouteBackend {
221
226
  export interface RoutePathSpec {
222
227
  path?: string;
223
228
  pathType?: "prefix" | "exact";
229
+ stripPrefix?: boolean;
224
230
  targetPort: string | number;
225
231
  }
226
232
  export interface RouteSpec {
@@ -432,6 +438,7 @@ export declare class Meshagent {
432
438
  updateUserProfile(userId: string, firstName: string, lastName: string): Promise<Record<string, unknown>>;
433
439
  listProjects(): Promise<Record<string, unknown>>;
434
440
  getProject(projectId: string): Promise<Record<string, unknown>>;
441
+ getProjectByKey(projectKey: string): Promise<Record<string, unknown>>;
435
442
  createApiKey(projectId: string, name: string, description: string): Promise<Record<string, unknown>>;
436
443
  deleteApiKey(projectId: string, id: string): Promise<void>;
437
444
  listApiKeys(projectId: string): Promise<Record<string, unknown>>;
@@ -842,6 +842,11 @@ class Meshagent {
842
842
  action: "get project",
843
843
  });
844
844
  }
845
+ async getProjectByKey(projectKey) {
846
+ return await this.request(`/accounts/projects/by-key/${encodeURIComponent(projectKey)}`, {
847
+ action: "get project by key",
848
+ });
849
+ }
845
850
  async createApiKey(projectId, name, description) {
846
851
  return await this.request(`/accounts/projects/${projectId}/api-keys`, {
847
852
  method: "POST",
@@ -221,7 +221,7 @@ function bracketIpv6Host(host) {
221
221
  }
222
222
  function roomServiceMcpServerUrl({ service, port, endpoint, }) {
223
223
  const endpointPath = normalizeEndpointPath(endpoint.path);
224
- const portValue = typeof port.num === "number" ? port.num : null;
224
+ const portValue = port.host_port ?? (typeof port.num === "number" ? port.num : null);
225
225
  if (service.external == null) {
226
226
  if (portValue == null) {
227
227
  return `http://localhost${endpointPath}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshagent/meshagent",
3
- "version": "0.41.7",
3
+ "version": "0.42.0",
4
4
  "description": "Meshagent Client",
5
5
  "homepage": "https://github.com/meshagent/meshagent-ts",
6
6
  "scripts": {