@meshagent/meshagent 0.41.9 → 0.42.2
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 +17 -0
- package/dist/browser/containers-client.d.ts +24 -1
- package/dist/browser/containers-client.js +66 -4
- package/dist/browser/meshagent-client.d.ts +7 -0
- package/dist/browser/meshagent-client.js +5 -0
- package/dist/browser/toolkit-config.js +1 -1
- package/dist/esm/containers-client.d.ts +24 -1
- package/dist/esm/containers-client.js +66 -4
- package/dist/esm/meshagent-client.d.ts +7 -0
- package/dist/esm/meshagent-client.js +5 -0
- package/dist/esm/toolkit-config.js +1 -1
- package/dist/node/containers-client.d.ts +24 -1
- package/dist/node/containers-client.js +66 -4
- package/dist/node/meshagent-client.d.ts +7 -0
- package/dist/node/meshagent-client.js +5 -0
- package/dist/node/toolkit-config.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## [0.42.2]
|
|
2
|
+
- Added `ContainerExitStatus`, `RoomContainerStats`, and published build image metadata to the TypeScript container client models.
|
|
3
|
+
- Added `waitForExitStatus` while keeping `waitForExit` as the exit-code convenience wrapper.
|
|
4
|
+
- Container list parsing now preserves image IDs, runtime stats, and exit-status metadata from API responses.
|
|
5
|
+
|
|
6
|
+
## [0.42.1]
|
|
7
|
+
- Stability
|
|
8
|
+
|
|
9
|
+
## [0.42.0]
|
|
10
|
+
- Added project lookup by key.
|
|
11
|
+
- Container and room APIs now return structured `containerPort`/`hostPort` entries instead of integer port lists, which is a breaking response-shape change.
|
|
12
|
+
- `ContainerSpec`, `PortSpec`, and `RoutePathSpec` now support `template`, `host_port`, and `stripPrefix`, and room service URL resolution uses `host_port` when available.
|
|
13
|
+
- `createRoom` now serializes typed permissions, and container creation now accepts a `template` option.
|
|
14
|
+
|
|
15
|
+
## [0.41.10]
|
|
16
|
+
- Stability
|
|
17
|
+
|
|
1
18
|
## [0.41.9]
|
|
2
19
|
- Stability
|
|
3
20
|
|
|
@@ -52,15 +52,34 @@ export interface ContainerParticipantInfo {
|
|
|
52
52
|
id: string;
|
|
53
53
|
name: string;
|
|
54
54
|
}
|
|
55
|
+
export interface RoomContainerPort {
|
|
56
|
+
containerPort: number;
|
|
57
|
+
hostPort: number;
|
|
58
|
+
}
|
|
59
|
+
export interface RoomContainerStats {
|
|
60
|
+
cpuUsageNanoCores?: number;
|
|
61
|
+
memoryUsageBytes?: number;
|
|
62
|
+
memoryWorkingSetBytes?: number;
|
|
63
|
+
timestampNs?: number;
|
|
64
|
+
}
|
|
55
65
|
export interface RoomContainer {
|
|
56
66
|
id: string;
|
|
57
67
|
image: string;
|
|
68
|
+
imageId?: string;
|
|
58
69
|
name?: string;
|
|
59
|
-
ports:
|
|
70
|
+
ports: RoomContainerPort[];
|
|
60
71
|
startedBy: ContainerParticipantInfo;
|
|
61
72
|
state: string;
|
|
62
73
|
private: boolean;
|
|
63
74
|
serviceId?: string;
|
|
75
|
+
stats?: RoomContainerStats;
|
|
76
|
+
exitStatus?: ContainerExitStatus;
|
|
77
|
+
}
|
|
78
|
+
export interface ContainerExitStatus {
|
|
79
|
+
exitCode: number;
|
|
80
|
+
reason?: string;
|
|
81
|
+
message?: string;
|
|
82
|
+
oomKilled?: boolean;
|
|
64
83
|
}
|
|
65
84
|
export interface LogProgress {
|
|
66
85
|
layer?: string | null;
|
|
@@ -170,6 +189,7 @@ export declare class ContainersClient {
|
|
|
170
189
|
credentials?: DockerSecret[];
|
|
171
190
|
name?: string;
|
|
172
191
|
mounts?: ContainerMountSpec;
|
|
192
|
+
template?: "agent" | "none";
|
|
173
193
|
writableRootFs?: boolean;
|
|
174
194
|
private?: boolean;
|
|
175
195
|
}): Promise<string>;
|
|
@@ -206,6 +226,9 @@ export declare class ContainersClient {
|
|
|
206
226
|
containerId: string;
|
|
207
227
|
force?: boolean;
|
|
208
228
|
}): Promise<void>;
|
|
229
|
+
waitForExitStatus(params: {
|
|
230
|
+
containerId: string;
|
|
231
|
+
}): Promise<ContainerExitStatus>;
|
|
209
232
|
waitForExit(params: {
|
|
210
233
|
containerId: string;
|
|
211
234
|
}): Promise<number>;
|
|
@@ -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
|
});
|
|
@@ -617,14 +618,27 @@ class ContainersClient {
|
|
|
617
618
|
force: params.force ?? false,
|
|
618
619
|
});
|
|
619
620
|
}
|
|
620
|
-
async
|
|
621
|
+
async waitForExitStatus(params) {
|
|
621
622
|
const output = await this.invoke("wait_for_exit", {
|
|
622
623
|
container_id: params.containerId,
|
|
623
624
|
});
|
|
624
625
|
if (!(output instanceof response_1.JsonContent) || !isRecord(output.json)) {
|
|
625
626
|
throw this.unexpectedResponseError("wait_for_exit");
|
|
626
627
|
}
|
|
627
|
-
|
|
628
|
+
const exitCode = readIntegerField(output.json, "exit_code", "wait_for_exit");
|
|
629
|
+
const reason = output.json["reason"];
|
|
630
|
+
const message = output.json["message"];
|
|
631
|
+
const oomKilled = output.json["oom_killed"];
|
|
632
|
+
return {
|
|
633
|
+
exitCode,
|
|
634
|
+
reason: typeof reason === "string" ? reason : undefined,
|
|
635
|
+
message: typeof message === "string" ? message : undefined,
|
|
636
|
+
oomKilled: typeof oomKilled === "boolean" ? oomKilled : undefined,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
async waitForExit(params) {
|
|
640
|
+
const status = await this.waitForExitStatus(params);
|
|
641
|
+
return status.exitCode;
|
|
628
642
|
}
|
|
629
643
|
async deleteContainer(params) {
|
|
630
644
|
await this.invoke("delete_container", {
|
|
@@ -887,16 +901,62 @@ class ContainersClient {
|
|
|
887
901
|
throw this.unexpectedResponseError("list");
|
|
888
902
|
}
|
|
889
903
|
const nameRaw = entry["name"];
|
|
904
|
+
const imageIdRaw = entry["image_id"];
|
|
890
905
|
const portsRaw = entry["ports"];
|
|
891
906
|
const serviceIdRaw = entry["service_id"];
|
|
892
|
-
|
|
907
|
+
const statsRaw = entry["stats"];
|
|
908
|
+
const exitStatusRaw = entry["exit_status"];
|
|
909
|
+
if (!Array.isArray(portsRaw) ||
|
|
910
|
+
!portsRaw.every((port) => {
|
|
911
|
+
if (!isRecord(port)) {
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
return (typeof port["container_port"] === "number" &&
|
|
915
|
+
Number.isInteger(port["container_port"]) &&
|
|
916
|
+
typeof port["host_port"] === "number" &&
|
|
917
|
+
Number.isInteger(port["host_port"]));
|
|
918
|
+
})) {
|
|
893
919
|
throw this.unexpectedResponseError("list");
|
|
894
920
|
}
|
|
921
|
+
const ports = portsRaw.map((port) => ({
|
|
922
|
+
containerPort: port["container_port"],
|
|
923
|
+
hostPort: port["host_port"],
|
|
924
|
+
}));
|
|
925
|
+
let stats;
|
|
926
|
+
if (isRecord(statsRaw)) {
|
|
927
|
+
const cpuUsageNanoCores = statsRaw["cpu_usage_nano_cores"];
|
|
928
|
+
const memoryUsageBytes = statsRaw["memory_usage_bytes"];
|
|
929
|
+
const memoryWorkingSetBytes = statsRaw["memory_working_set_bytes"];
|
|
930
|
+
const timestampNs = statsRaw["timestamp_ns"];
|
|
931
|
+
stats = {
|
|
932
|
+
cpuUsageNanoCores: typeof cpuUsageNanoCores === "number" ? cpuUsageNanoCores : undefined,
|
|
933
|
+
memoryUsageBytes: typeof memoryUsageBytes === "number" ? memoryUsageBytes : undefined,
|
|
934
|
+
memoryWorkingSetBytes: typeof memoryWorkingSetBytes === "number" ? memoryWorkingSetBytes : undefined,
|
|
935
|
+
timestampNs: typeof timestampNs === "number" ? timestampNs : undefined,
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
let exitStatus;
|
|
939
|
+
if (isRecord(exitStatusRaw)) {
|
|
940
|
+
const exitCode = exitStatusRaw["exit_code"];
|
|
941
|
+
if (typeof exitCode === "number" &&
|
|
942
|
+
Number.isInteger(exitCode)) {
|
|
943
|
+
const reason = exitStatusRaw["reason"];
|
|
944
|
+
const message = exitStatusRaw["message"];
|
|
945
|
+
const oomKilled = exitStatusRaw["oom_killed"];
|
|
946
|
+
exitStatus = {
|
|
947
|
+
exitCode,
|
|
948
|
+
reason: typeof reason === "string" ? reason : undefined,
|
|
949
|
+
message: typeof message === "string" ? message : undefined,
|
|
950
|
+
oomKilled: typeof oomKilled === "boolean" ? oomKilled : undefined,
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
}
|
|
895
954
|
items.push({
|
|
896
955
|
id,
|
|
897
956
|
image,
|
|
957
|
+
imageId: typeof imageIdRaw === "string" ? imageIdRaw : undefined,
|
|
898
958
|
name: typeof nameRaw === "string" ? nameRaw : undefined,
|
|
899
|
-
ports
|
|
959
|
+
ports,
|
|
900
960
|
startedBy: {
|
|
901
961
|
id: startedById,
|
|
902
962
|
name: startedByName,
|
|
@@ -904,6 +964,8 @@ class ContainersClient {
|
|
|
904
964
|
state,
|
|
905
965
|
private: privateFlag,
|
|
906
966
|
serviceId: typeof serviceIdRaw === "string" ? serviceIdRaw : undefined,
|
|
967
|
+
stats,
|
|
968
|
+
exitStatus,
|
|
907
969
|
});
|
|
908
970
|
}
|
|
909
971
|
return items;
|
|
@@ -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,15 +52,34 @@ export interface ContainerParticipantInfo {
|
|
|
52
52
|
id: string;
|
|
53
53
|
name: string;
|
|
54
54
|
}
|
|
55
|
+
export interface RoomContainerPort {
|
|
56
|
+
containerPort: number;
|
|
57
|
+
hostPort: number;
|
|
58
|
+
}
|
|
59
|
+
export interface RoomContainerStats {
|
|
60
|
+
cpuUsageNanoCores?: number;
|
|
61
|
+
memoryUsageBytes?: number;
|
|
62
|
+
memoryWorkingSetBytes?: number;
|
|
63
|
+
timestampNs?: number;
|
|
64
|
+
}
|
|
55
65
|
export interface RoomContainer {
|
|
56
66
|
id: string;
|
|
57
67
|
image: string;
|
|
68
|
+
imageId?: string;
|
|
58
69
|
name?: string;
|
|
59
|
-
ports:
|
|
70
|
+
ports: RoomContainerPort[];
|
|
60
71
|
startedBy: ContainerParticipantInfo;
|
|
61
72
|
state: string;
|
|
62
73
|
private: boolean;
|
|
63
74
|
serviceId?: string;
|
|
75
|
+
stats?: RoomContainerStats;
|
|
76
|
+
exitStatus?: ContainerExitStatus;
|
|
77
|
+
}
|
|
78
|
+
export interface ContainerExitStatus {
|
|
79
|
+
exitCode: number;
|
|
80
|
+
reason?: string;
|
|
81
|
+
message?: string;
|
|
82
|
+
oomKilled?: boolean;
|
|
64
83
|
}
|
|
65
84
|
export interface LogProgress {
|
|
66
85
|
layer?: string | null;
|
|
@@ -170,6 +189,7 @@ export declare class ContainersClient {
|
|
|
170
189
|
credentials?: DockerSecret[];
|
|
171
190
|
name?: string;
|
|
172
191
|
mounts?: ContainerMountSpec;
|
|
192
|
+
template?: "agent" | "none";
|
|
173
193
|
writableRootFs?: boolean;
|
|
174
194
|
private?: boolean;
|
|
175
195
|
}): Promise<string>;
|
|
@@ -206,6 +226,9 @@ export declare class ContainersClient {
|
|
|
206
226
|
containerId: string;
|
|
207
227
|
force?: boolean;
|
|
208
228
|
}): Promise<void>;
|
|
229
|
+
waitForExitStatus(params: {
|
|
230
|
+
containerId: string;
|
|
231
|
+
}): Promise<ContainerExitStatus>;
|
|
209
232
|
waitForExit(params: {
|
|
210
233
|
containerId: string;
|
|
211
234
|
}): Promise<number>;
|
|
@@ -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
|
});
|
|
@@ -617,14 +618,27 @@ class ContainersClient {
|
|
|
617
618
|
force: params.force ?? false,
|
|
618
619
|
});
|
|
619
620
|
}
|
|
620
|
-
async
|
|
621
|
+
async waitForExitStatus(params) {
|
|
621
622
|
const output = await this.invoke("wait_for_exit", {
|
|
622
623
|
container_id: params.containerId,
|
|
623
624
|
});
|
|
624
625
|
if (!(output instanceof response_1.JsonContent) || !isRecord(output.json)) {
|
|
625
626
|
throw this.unexpectedResponseError("wait_for_exit");
|
|
626
627
|
}
|
|
627
|
-
|
|
628
|
+
const exitCode = readIntegerField(output.json, "exit_code", "wait_for_exit");
|
|
629
|
+
const reason = output.json["reason"];
|
|
630
|
+
const message = output.json["message"];
|
|
631
|
+
const oomKilled = output.json["oom_killed"];
|
|
632
|
+
return {
|
|
633
|
+
exitCode,
|
|
634
|
+
reason: typeof reason === "string" ? reason : undefined,
|
|
635
|
+
message: typeof message === "string" ? message : undefined,
|
|
636
|
+
oomKilled: typeof oomKilled === "boolean" ? oomKilled : undefined,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
async waitForExit(params) {
|
|
640
|
+
const status = await this.waitForExitStatus(params);
|
|
641
|
+
return status.exitCode;
|
|
628
642
|
}
|
|
629
643
|
async deleteContainer(params) {
|
|
630
644
|
await this.invoke("delete_container", {
|
|
@@ -887,16 +901,62 @@ class ContainersClient {
|
|
|
887
901
|
throw this.unexpectedResponseError("list");
|
|
888
902
|
}
|
|
889
903
|
const nameRaw = entry["name"];
|
|
904
|
+
const imageIdRaw = entry["image_id"];
|
|
890
905
|
const portsRaw = entry["ports"];
|
|
891
906
|
const serviceIdRaw = entry["service_id"];
|
|
892
|
-
|
|
907
|
+
const statsRaw = entry["stats"];
|
|
908
|
+
const exitStatusRaw = entry["exit_status"];
|
|
909
|
+
if (!Array.isArray(portsRaw) ||
|
|
910
|
+
!portsRaw.every((port) => {
|
|
911
|
+
if (!isRecord(port)) {
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
return (typeof port["container_port"] === "number" &&
|
|
915
|
+
Number.isInteger(port["container_port"]) &&
|
|
916
|
+
typeof port["host_port"] === "number" &&
|
|
917
|
+
Number.isInteger(port["host_port"]));
|
|
918
|
+
})) {
|
|
893
919
|
throw this.unexpectedResponseError("list");
|
|
894
920
|
}
|
|
921
|
+
const ports = portsRaw.map((port) => ({
|
|
922
|
+
containerPort: port["container_port"],
|
|
923
|
+
hostPort: port["host_port"],
|
|
924
|
+
}));
|
|
925
|
+
let stats;
|
|
926
|
+
if (isRecord(statsRaw)) {
|
|
927
|
+
const cpuUsageNanoCores = statsRaw["cpu_usage_nano_cores"];
|
|
928
|
+
const memoryUsageBytes = statsRaw["memory_usage_bytes"];
|
|
929
|
+
const memoryWorkingSetBytes = statsRaw["memory_working_set_bytes"];
|
|
930
|
+
const timestampNs = statsRaw["timestamp_ns"];
|
|
931
|
+
stats = {
|
|
932
|
+
cpuUsageNanoCores: typeof cpuUsageNanoCores === "number" ? cpuUsageNanoCores : undefined,
|
|
933
|
+
memoryUsageBytes: typeof memoryUsageBytes === "number" ? memoryUsageBytes : undefined,
|
|
934
|
+
memoryWorkingSetBytes: typeof memoryWorkingSetBytes === "number" ? memoryWorkingSetBytes : undefined,
|
|
935
|
+
timestampNs: typeof timestampNs === "number" ? timestampNs : undefined,
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
let exitStatus;
|
|
939
|
+
if (isRecord(exitStatusRaw)) {
|
|
940
|
+
const exitCode = exitStatusRaw["exit_code"];
|
|
941
|
+
if (typeof exitCode === "number" &&
|
|
942
|
+
Number.isInteger(exitCode)) {
|
|
943
|
+
const reason = exitStatusRaw["reason"];
|
|
944
|
+
const message = exitStatusRaw["message"];
|
|
945
|
+
const oomKilled = exitStatusRaw["oom_killed"];
|
|
946
|
+
exitStatus = {
|
|
947
|
+
exitCode,
|
|
948
|
+
reason: typeof reason === "string" ? reason : undefined,
|
|
949
|
+
message: typeof message === "string" ? message : undefined,
|
|
950
|
+
oomKilled: typeof oomKilled === "boolean" ? oomKilled : undefined,
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
}
|
|
895
954
|
items.push({
|
|
896
955
|
id,
|
|
897
956
|
image,
|
|
957
|
+
imageId: typeof imageIdRaw === "string" ? imageIdRaw : undefined,
|
|
898
958
|
name: typeof nameRaw === "string" ? nameRaw : undefined,
|
|
899
|
-
ports
|
|
959
|
+
ports,
|
|
900
960
|
startedBy: {
|
|
901
961
|
id: startedById,
|
|
902
962
|
name: startedByName,
|
|
@@ -904,6 +964,8 @@ class ContainersClient {
|
|
|
904
964
|
state,
|
|
905
965
|
private: privateFlag,
|
|
906
966
|
serviceId: typeof serviceIdRaw === "string" ? serviceIdRaw : undefined,
|
|
967
|
+
stats,
|
|
968
|
+
exitStatus,
|
|
907
969
|
});
|
|
908
970
|
}
|
|
909
971
|
return items;
|
|
@@ -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,15 +52,34 @@ export interface ContainerParticipantInfo {
|
|
|
52
52
|
id: string;
|
|
53
53
|
name: string;
|
|
54
54
|
}
|
|
55
|
+
export interface RoomContainerPort {
|
|
56
|
+
containerPort: number;
|
|
57
|
+
hostPort: number;
|
|
58
|
+
}
|
|
59
|
+
export interface RoomContainerStats {
|
|
60
|
+
cpuUsageNanoCores?: number;
|
|
61
|
+
memoryUsageBytes?: number;
|
|
62
|
+
memoryWorkingSetBytes?: number;
|
|
63
|
+
timestampNs?: number;
|
|
64
|
+
}
|
|
55
65
|
export interface RoomContainer {
|
|
56
66
|
id: string;
|
|
57
67
|
image: string;
|
|
68
|
+
imageId?: string;
|
|
58
69
|
name?: string;
|
|
59
|
-
ports:
|
|
70
|
+
ports: RoomContainerPort[];
|
|
60
71
|
startedBy: ContainerParticipantInfo;
|
|
61
72
|
state: string;
|
|
62
73
|
private: boolean;
|
|
63
74
|
serviceId?: string;
|
|
75
|
+
stats?: RoomContainerStats;
|
|
76
|
+
exitStatus?: ContainerExitStatus;
|
|
77
|
+
}
|
|
78
|
+
export interface ContainerExitStatus {
|
|
79
|
+
exitCode: number;
|
|
80
|
+
reason?: string;
|
|
81
|
+
message?: string;
|
|
82
|
+
oomKilled?: boolean;
|
|
64
83
|
}
|
|
65
84
|
export interface LogProgress {
|
|
66
85
|
layer?: string | null;
|
|
@@ -170,6 +189,7 @@ export declare class ContainersClient {
|
|
|
170
189
|
credentials?: DockerSecret[];
|
|
171
190
|
name?: string;
|
|
172
191
|
mounts?: ContainerMountSpec;
|
|
192
|
+
template?: "agent" | "none";
|
|
173
193
|
writableRootFs?: boolean;
|
|
174
194
|
private?: boolean;
|
|
175
195
|
}): Promise<string>;
|
|
@@ -206,6 +226,9 @@ export declare class ContainersClient {
|
|
|
206
226
|
containerId: string;
|
|
207
227
|
force?: boolean;
|
|
208
228
|
}): Promise<void>;
|
|
229
|
+
waitForExitStatus(params: {
|
|
230
|
+
containerId: string;
|
|
231
|
+
}): Promise<ContainerExitStatus>;
|
|
209
232
|
waitForExit(params: {
|
|
210
233
|
containerId: string;
|
|
211
234
|
}): Promise<number>;
|
|
@@ -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
|
});
|
|
@@ -617,14 +618,27 @@ class ContainersClient {
|
|
|
617
618
|
force: params.force ?? false,
|
|
618
619
|
});
|
|
619
620
|
}
|
|
620
|
-
async
|
|
621
|
+
async waitForExitStatus(params) {
|
|
621
622
|
const output = await this.invoke("wait_for_exit", {
|
|
622
623
|
container_id: params.containerId,
|
|
623
624
|
});
|
|
624
625
|
if (!(output instanceof response_1.JsonContent) || !isRecord(output.json)) {
|
|
625
626
|
throw this.unexpectedResponseError("wait_for_exit");
|
|
626
627
|
}
|
|
627
|
-
|
|
628
|
+
const exitCode = readIntegerField(output.json, "exit_code", "wait_for_exit");
|
|
629
|
+
const reason = output.json["reason"];
|
|
630
|
+
const message = output.json["message"];
|
|
631
|
+
const oomKilled = output.json["oom_killed"];
|
|
632
|
+
return {
|
|
633
|
+
exitCode,
|
|
634
|
+
reason: typeof reason === "string" ? reason : undefined,
|
|
635
|
+
message: typeof message === "string" ? message : undefined,
|
|
636
|
+
oomKilled: typeof oomKilled === "boolean" ? oomKilled : undefined,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
async waitForExit(params) {
|
|
640
|
+
const status = await this.waitForExitStatus(params);
|
|
641
|
+
return status.exitCode;
|
|
628
642
|
}
|
|
629
643
|
async deleteContainer(params) {
|
|
630
644
|
await this.invoke("delete_container", {
|
|
@@ -887,16 +901,62 @@ class ContainersClient {
|
|
|
887
901
|
throw this.unexpectedResponseError("list");
|
|
888
902
|
}
|
|
889
903
|
const nameRaw = entry["name"];
|
|
904
|
+
const imageIdRaw = entry["image_id"];
|
|
890
905
|
const portsRaw = entry["ports"];
|
|
891
906
|
const serviceIdRaw = entry["service_id"];
|
|
892
|
-
|
|
907
|
+
const statsRaw = entry["stats"];
|
|
908
|
+
const exitStatusRaw = entry["exit_status"];
|
|
909
|
+
if (!Array.isArray(portsRaw) ||
|
|
910
|
+
!portsRaw.every((port) => {
|
|
911
|
+
if (!isRecord(port)) {
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
return (typeof port["container_port"] === "number" &&
|
|
915
|
+
Number.isInteger(port["container_port"]) &&
|
|
916
|
+
typeof port["host_port"] === "number" &&
|
|
917
|
+
Number.isInteger(port["host_port"]));
|
|
918
|
+
})) {
|
|
893
919
|
throw this.unexpectedResponseError("list");
|
|
894
920
|
}
|
|
921
|
+
const ports = portsRaw.map((port) => ({
|
|
922
|
+
containerPort: port["container_port"],
|
|
923
|
+
hostPort: port["host_port"],
|
|
924
|
+
}));
|
|
925
|
+
let stats;
|
|
926
|
+
if (isRecord(statsRaw)) {
|
|
927
|
+
const cpuUsageNanoCores = statsRaw["cpu_usage_nano_cores"];
|
|
928
|
+
const memoryUsageBytes = statsRaw["memory_usage_bytes"];
|
|
929
|
+
const memoryWorkingSetBytes = statsRaw["memory_working_set_bytes"];
|
|
930
|
+
const timestampNs = statsRaw["timestamp_ns"];
|
|
931
|
+
stats = {
|
|
932
|
+
cpuUsageNanoCores: typeof cpuUsageNanoCores === "number" ? cpuUsageNanoCores : undefined,
|
|
933
|
+
memoryUsageBytes: typeof memoryUsageBytes === "number" ? memoryUsageBytes : undefined,
|
|
934
|
+
memoryWorkingSetBytes: typeof memoryWorkingSetBytes === "number" ? memoryWorkingSetBytes : undefined,
|
|
935
|
+
timestampNs: typeof timestampNs === "number" ? timestampNs : undefined,
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
let exitStatus;
|
|
939
|
+
if (isRecord(exitStatusRaw)) {
|
|
940
|
+
const exitCode = exitStatusRaw["exit_code"];
|
|
941
|
+
if (typeof exitCode === "number" &&
|
|
942
|
+
Number.isInteger(exitCode)) {
|
|
943
|
+
const reason = exitStatusRaw["reason"];
|
|
944
|
+
const message = exitStatusRaw["message"];
|
|
945
|
+
const oomKilled = exitStatusRaw["oom_killed"];
|
|
946
|
+
exitStatus = {
|
|
947
|
+
exitCode,
|
|
948
|
+
reason: typeof reason === "string" ? reason : undefined,
|
|
949
|
+
message: typeof message === "string" ? message : undefined,
|
|
950
|
+
oomKilled: typeof oomKilled === "boolean" ? oomKilled : undefined,
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
}
|
|
895
954
|
items.push({
|
|
896
955
|
id,
|
|
897
956
|
image,
|
|
957
|
+
imageId: typeof imageIdRaw === "string" ? imageIdRaw : undefined,
|
|
898
958
|
name: typeof nameRaw === "string" ? nameRaw : undefined,
|
|
899
|
-
ports
|
|
959
|
+
ports,
|
|
900
960
|
startedBy: {
|
|
901
961
|
id: startedById,
|
|
902
962
|
name: startedByName,
|
|
@@ -904,6 +964,8 @@ class ContainersClient {
|
|
|
904
964
|
state,
|
|
905
965
|
private: privateFlag,
|
|
906
966
|
serviceId: typeof serviceIdRaw === "string" ? serviceIdRaw : undefined,
|
|
967
|
+
stats,
|
|
968
|
+
exitStatus,
|
|
907
969
|
});
|
|
908
970
|
}
|
|
909
971
|
return items;
|
|
@@ -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}`;
|