@calltelemetry/ct-lab-mcp 0.8.124 → 0.8.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/bin/ct-lab-executor.js +3 -1
  2. package/dist/src/generated-version.d.ts +1 -1
  3. package/dist/src/generated-version.js +1 -1
  4. package/dist/src/lab-exec/claim-resolve.d.ts +214 -0
  5. package/dist/src/lab-exec/claim-resolve.d.ts.map +1 -0
  6. package/dist/src/lab-exec/claim-resolve.js +64 -0
  7. package/dist/src/lab-exec/claim-resolve.js.map +1 -0
  8. package/dist/src/lab-exec/contract.d.ts +14 -6
  9. package/dist/src/lab-exec/contract.d.ts.map +1 -1
  10. package/dist/src/lab-exec/contract.js +11 -2
  11. package/dist/src/lab-exec/contract.js.map +1 -1
  12. package/dist/src/lab-exec/executor.d.ts +6 -0
  13. package/dist/src/lab-exec/executor.d.ts.map +1 -1
  14. package/dist/src/lab-exec/executor.js +9 -0
  15. package/dist/src/lab-exec/executor.js.map +1 -1
  16. package/dist/src/lab-exec/remote.d.ts +7 -0
  17. package/dist/src/lab-exec/remote.d.ts.map +1 -1
  18. package/dist/src/lab-exec/remote.js +30 -0
  19. package/dist/src/lab-exec/remote.js.map +1 -1
  20. package/dist/src/lab-exec/result.d.ts +1 -1
  21. package/dist/src/lab-exec/result.d.ts.map +1 -1
  22. package/dist/src/lab-exec/result.js +1 -1
  23. package/dist/src/lab-exec/result.js.map +1 -1
  24. package/dist/src/lab-exec/server.d.ts.map +1 -1
  25. package/dist/src/lab-exec/server.js +47 -2
  26. package/dist/src/lab-exec/server.js.map +1 -1
  27. package/dist/src/tools/appliance-claim-tools.d.ts +2 -2
  28. package/dist/src/tools/appliance-claim-tools.d.ts.map +1 -1
  29. package/dist/src/tools/appliance-claim-tools.js +29 -2
  30. package/dist/src/tools/appliance-claim-tools.js.map +1 -1
  31. package/dist/src/tools/index.js +1 -1
  32. package/dist/src/tools/index.js.map +1 -1
  33. package/dist/src/tools/lab-ssh.d.ts.map +1 -1
  34. package/dist/src/tools/lab-ssh.js +5 -3
  35. package/dist/src/tools/lab-ssh.js.map +1 -1
  36. package/package.json +1 -1
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  /** ct-lab-executor: the in-lab half of lab_ssh (ADR 0934). */
3
3
  import { CanonicalLabBridge } from "../src/canonical/bridge.js";
4
+ import { ClaimResolvingExecutor } from "../src/lab-exec/claim-resolve.js";
5
+ import { defaultOperatorClaimClient } from "../src/tools/renewal-claim.js";
4
6
  import { LocalLabExecutor } from "../src/lab-exec/executor.js";
5
7
  import { createLabExecServer } from "../src/lab-exec/server.js";
6
8
  const bridge = new CanonicalLabBridge({ required: true });
@@ -10,7 +12,7 @@ if (!bridge.isConfigured) {
10
12
  }
11
13
  const port = Number(process.env.CT_LAB_EXECUTOR_PORT || 8090);
12
14
  createLabExecServer({
13
- executor: new LocalLabExecutor(bridge),
15
+ executor: new ClaimResolvingExecutor(new LocalLabExecutor(bridge), defaultOperatorClaimClient()),
14
16
  access: {
15
17
  ENVIRONMENT: process.env.ENVIRONMENT,
16
18
  ACCESS_TEAM_DOMAIN: process.env.ACCESS_TEAM_DOMAIN,
@@ -2,5 +2,5 @@
2
2
  * Auto-synced package version fallback for non-filesystem runtimes (Cloudflare Workers).
3
3
  * Updated automatically during release publication in .github/workflows/publish.yml.
4
4
  */
5
- export declare const PACKAGE_VERSION = "0.8.124";
5
+ export declare const PACKAGE_VERSION = "0.8.126";
6
6
  //# sourceMappingURL=generated-version.d.ts.map
@@ -2,5 +2,5 @@
2
2
  * Auto-synced package version fallback for non-filesystem runtimes (Cloudflare Workers).
3
3
  * Updated automatically during release publication in .github/workflows/publish.yml.
4
4
  */
5
- export const PACKAGE_VERSION = "0.8.124";
5
+ export const PACKAGE_VERSION = "0.8.126";
6
6
  //# sourceMappingURL=generated-version.js.map
@@ -0,0 +1,214 @@
1
+ /**
2
+ * claimId -> assetId resolution for lab_ssh (REL-1961, ADR 0934). Runs wherever the
3
+ * Kubernetes API is reachable (the lab executor), never in the Worker. Reads one
4
+ * ApplianceClaim by name (RBAC: get on applianceclaims) and uses spec.vmName, the
5
+ * canonical asset ID. An unresolvable claim yields a structured ct-lab-vm-ssh-result/v1
6
+ * envelope and no ssh attempt.
7
+ */
8
+ import type { LabSshInput } from "./contract.js";
9
+ import type { LabExecCaller, LabExecOutcome, LabExecutor } from "./executor.js";
10
+ export interface ClaimReader {
11
+ getClaim(name: string): Promise<any>;
12
+ }
13
+ export declare class ClaimResolvingExecutor implements LabExecutor {
14
+ private readonly inner;
15
+ private readonly claims;
16
+ constructor(inner: LabExecutor, claims: ClaimReader);
17
+ get location(): "local" | "remote";
18
+ claimsList(input: unknown, caller?: LabExecCaller): Promise<{
19
+ [x: string]: unknown;
20
+ content: ({
21
+ type: "text";
22
+ text: string;
23
+ annotations?: {
24
+ audience?: ("user" | "assistant")[] | undefined;
25
+ priority?: number | undefined;
26
+ lastModified?: string | undefined;
27
+ } | undefined;
28
+ _meta?: {
29
+ [x: string]: unknown;
30
+ } | undefined;
31
+ } | {
32
+ type: "image";
33
+ data: string;
34
+ mimeType: string;
35
+ annotations?: {
36
+ audience?: ("user" | "assistant")[] | undefined;
37
+ priority?: number | undefined;
38
+ lastModified?: string | undefined;
39
+ } | undefined;
40
+ _meta?: {
41
+ [x: string]: unknown;
42
+ } | undefined;
43
+ } | {
44
+ type: "audio";
45
+ data: string;
46
+ mimeType: string;
47
+ annotations?: {
48
+ audience?: ("user" | "assistant")[] | undefined;
49
+ priority?: number | undefined;
50
+ lastModified?: string | undefined;
51
+ } | undefined;
52
+ _meta?: {
53
+ [x: string]: unknown;
54
+ } | undefined;
55
+ } | {
56
+ uri: string;
57
+ name: string;
58
+ type: "resource_link";
59
+ description?: string | undefined;
60
+ mimeType?: string | undefined;
61
+ size?: number | undefined;
62
+ annotations?: {
63
+ audience?: ("user" | "assistant")[] | undefined;
64
+ priority?: number | undefined;
65
+ lastModified?: string | undefined;
66
+ } | undefined;
67
+ _meta?: {
68
+ [x: string]: unknown;
69
+ } | undefined;
70
+ icons?: {
71
+ src: string;
72
+ mimeType?: string | undefined;
73
+ sizes?: string[] | undefined;
74
+ theme?: "light" | "dark" | undefined;
75
+ }[] | undefined;
76
+ title?: string | undefined;
77
+ } | {
78
+ type: "resource";
79
+ resource: {
80
+ uri: string;
81
+ text: string;
82
+ mimeType?: string | undefined;
83
+ _meta?: {
84
+ [x: string]: unknown;
85
+ } | undefined;
86
+ } | {
87
+ uri: string;
88
+ blob: string;
89
+ mimeType?: string | undefined;
90
+ _meta?: {
91
+ [x: string]: unknown;
92
+ } | undefined;
93
+ };
94
+ annotations?: {
95
+ audience?: ("user" | "assistant")[] | undefined;
96
+ priority?: number | undefined;
97
+ lastModified?: string | undefined;
98
+ } | undefined;
99
+ _meta?: {
100
+ [x: string]: unknown;
101
+ } | undefined;
102
+ })[];
103
+ _meta?: {
104
+ [x: string]: unknown;
105
+ progressToken?: string | number | undefined;
106
+ "io.modelcontextprotocol/related-task"?: {
107
+ taskId: string;
108
+ } | undefined;
109
+ } | undefined;
110
+ structuredContent?: {
111
+ [x: string]: unknown;
112
+ } | undefined;
113
+ isError?: boolean | undefined;
114
+ }>;
115
+ claimsGet(input: unknown, caller?: LabExecCaller): Promise<{
116
+ [x: string]: unknown;
117
+ content: ({
118
+ type: "text";
119
+ text: string;
120
+ annotations?: {
121
+ audience?: ("user" | "assistant")[] | undefined;
122
+ priority?: number | undefined;
123
+ lastModified?: string | undefined;
124
+ } | undefined;
125
+ _meta?: {
126
+ [x: string]: unknown;
127
+ } | undefined;
128
+ } | {
129
+ type: "image";
130
+ data: string;
131
+ mimeType: string;
132
+ annotations?: {
133
+ audience?: ("user" | "assistant")[] | undefined;
134
+ priority?: number | undefined;
135
+ lastModified?: string | undefined;
136
+ } | undefined;
137
+ _meta?: {
138
+ [x: string]: unknown;
139
+ } | undefined;
140
+ } | {
141
+ type: "audio";
142
+ data: string;
143
+ mimeType: string;
144
+ annotations?: {
145
+ audience?: ("user" | "assistant")[] | undefined;
146
+ priority?: number | undefined;
147
+ lastModified?: string | undefined;
148
+ } | undefined;
149
+ _meta?: {
150
+ [x: string]: unknown;
151
+ } | undefined;
152
+ } | {
153
+ uri: string;
154
+ name: string;
155
+ type: "resource_link";
156
+ description?: string | undefined;
157
+ mimeType?: string | undefined;
158
+ size?: number | undefined;
159
+ annotations?: {
160
+ audience?: ("user" | "assistant")[] | undefined;
161
+ priority?: number | undefined;
162
+ lastModified?: string | undefined;
163
+ } | undefined;
164
+ _meta?: {
165
+ [x: string]: unknown;
166
+ } | undefined;
167
+ icons?: {
168
+ src: string;
169
+ mimeType?: string | undefined;
170
+ sizes?: string[] | undefined;
171
+ theme?: "light" | "dark" | undefined;
172
+ }[] | undefined;
173
+ title?: string | undefined;
174
+ } | {
175
+ type: "resource";
176
+ resource: {
177
+ uri: string;
178
+ text: string;
179
+ mimeType?: string | undefined;
180
+ _meta?: {
181
+ [x: string]: unknown;
182
+ } | undefined;
183
+ } | {
184
+ uri: string;
185
+ blob: string;
186
+ mimeType?: string | undefined;
187
+ _meta?: {
188
+ [x: string]: unknown;
189
+ } | undefined;
190
+ };
191
+ annotations?: {
192
+ audience?: ("user" | "assistant")[] | undefined;
193
+ priority?: number | undefined;
194
+ lastModified?: string | undefined;
195
+ } | undefined;
196
+ _meta?: {
197
+ [x: string]: unknown;
198
+ } | undefined;
199
+ })[];
200
+ _meta?: {
201
+ [x: string]: unknown;
202
+ progressToken?: string | number | undefined;
203
+ "io.modelcontextprotocol/related-task"?: {
204
+ taskId: string;
205
+ } | undefined;
206
+ } | undefined;
207
+ structuredContent?: {
208
+ [x: string]: unknown;
209
+ } | undefined;
210
+ isError?: boolean | undefined;
211
+ }>;
212
+ ssh(input: LabSshInput, caller?: LabExecCaller): Promise<LabExecOutcome>;
213
+ }
214
+ //# sourceMappingURL=claim-resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-resolve.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/claim-resolve.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGhF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACtC;AAyBD,qBAAa,sBAAuB,YAAW,WAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAe,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAA3C,KAAK,EAAE,WAAW,EAAmB,MAAM,EAAE,WAAW;IAErF,IAAI,QAAQ,uBAAkC;IAE9C,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKjD,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAK1C,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAkB/E"}
@@ -0,0 +1,64 @@
1
+ import { labSshCommandSha256, LAB_SSH_ASSET_ID } from "./contract.js";
2
+ import { VM_SSH_RESULT_SCHEMA } from "./result.js";
3
+ function notFound(error) {
4
+ const e = error;
5
+ return e?.status === 404 || String(e?.message ?? "").includes("(404)");
6
+ }
7
+ function refusal(input, classification, message) {
8
+ const envelope = {
9
+ schema: VM_SSH_RESULT_SCHEMA,
10
+ asset_id: input.claimId ?? "",
11
+ claim_id: input.claimId ?? "",
12
+ target_mode: input.targetMode,
13
+ exit_code: 1,
14
+ classification,
15
+ stdout: "",
16
+ stderr: message,
17
+ stdout_truncated: false,
18
+ stderr_truncated: false,
19
+ duration_ms: 0,
20
+ command_sha256: labSshCommandSha256(input.command),
21
+ };
22
+ return { exitCode: 0, stdout: JSON.stringify(envelope), stderr: "" };
23
+ }
24
+ export class ClaimResolvingExecutor {
25
+ inner;
26
+ claims;
27
+ constructor(inner, claims) {
28
+ this.inner = inner;
29
+ this.claims = claims;
30
+ }
31
+ get location() { return this.inner.location; }
32
+ claimsList(input, caller) {
33
+ if (!this.inner.claimsList)
34
+ throw new Error("inner executor has no claim plane");
35
+ return this.inner.claimsList(input, caller);
36
+ }
37
+ claimsGet(input, caller) {
38
+ if (!this.inner.claimsGet)
39
+ throw new Error("inner executor has no claim plane");
40
+ return this.inner.claimsGet(input, caller);
41
+ }
42
+ async ssh(input, caller) {
43
+ if (!input.claimId)
44
+ return this.inner.ssh(input, caller);
45
+ let claim;
46
+ try {
47
+ claim = await this.claims.getClaim(input.claimId);
48
+ }
49
+ catch (error) {
50
+ if (!notFound(error))
51
+ throw error;
52
+ }
53
+ if (!claim || claim.__notFound || claim.metadata?.deletionTimestamp || claim.metadata?.name !== input.claimId) {
54
+ return refusal(input, "claim_not_found", `no live ApplianceClaim named '${input.claimId}'`);
55
+ }
56
+ const assetId = claim.spec?.vmName;
57
+ if (typeof assetId !== "string" || !LAB_SSH_ASSET_ID.test(assetId)) {
58
+ return refusal(input, "claim_has_no_asset", `ApplianceClaim '${input.claimId}' does not name a guest (spec.vmName); use assetId from list_inventory`);
59
+ }
60
+ const { claimId: _claimId, ...rest } = input;
61
+ return this.inner.ssh({ ...rest, assetId }, caller);
62
+ }
63
+ }
64
+ //# sourceMappingURL=claim-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-resolve.js","sourceRoot":"","sources":["../../../src/lab-exec/claim-resolve.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import { z } from "zod";
2
2
  export declare const LAB_SSH_ASSET_ID: RegExp;
3
+ /** Kubernetes DNS-1123 subdomain: the ApplianceClaim metadata.name (for example claim-uat-1815-302). */
4
+ export declare const LAB_SSH_CLAIM_ID: RegExp;
3
5
  export declare const LAB_SSH_HOST_KEY: RegExp;
4
6
  export declare const LAB_SSH_IPV4: RegExp;
5
7
  export declare const LAB_SSH_MAX_COMMAND_BYTES = 65536;
@@ -14,7 +16,8 @@ export declare const LabSshTargetSchema: z.ZodObject<{
14
16
  hostKeySha256?: string | undefined;
15
17
  }>;
16
18
  export declare const LabSshInputShape: {
17
- assetId: z.ZodString;
19
+ assetId: z.ZodOptional<z.ZodString>;
20
+ claimId: z.ZodOptional<z.ZodString>;
18
21
  command: z.ZodString;
19
22
  timeoutSeconds: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
23
  targetMode: z.ZodDefault<z.ZodOptional<z.ZodEnum<["resolve", "assert", "override"]>>>;
@@ -30,7 +33,8 @@ export declare const LabSshInputShape: {
30
33
  }>>;
31
34
  };
32
35
  export declare const LabSshInputSchema: z.ZodEffects<z.ZodObject<{
33
- assetId: z.ZodString;
36
+ assetId: z.ZodOptional<z.ZodString>;
37
+ claimId: z.ZodOptional<z.ZodString>;
34
38
  command: z.ZodString;
35
39
  timeoutSeconds: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
36
40
  targetMode: z.ZodDefault<z.ZodOptional<z.ZodEnum<["resolve", "assert", "override"]>>>;
@@ -47,38 +51,42 @@ export declare const LabSshInputSchema: z.ZodEffects<z.ZodObject<{
47
51
  }, "strict", z.ZodTypeAny, {
48
52
  command: string;
49
53
  timeoutSeconds: number;
50
- assetId: string;
51
54
  targetMode: "resolve" | "assert" | "override";
55
+ claimId?: string | undefined;
52
56
  target?: {
53
57
  host?: string | undefined;
54
58
  hostKeySha256?: string | undefined;
55
59
  } | undefined;
60
+ assetId?: string | undefined;
56
61
  }, {
57
62
  command: string;
58
- assetId: string;
63
+ claimId?: string | undefined;
59
64
  target?: {
60
65
  host?: string | undefined;
61
66
  hostKeySha256?: string | undefined;
62
67
  } | undefined;
63
68
  timeoutSeconds?: number | undefined;
69
+ assetId?: string | undefined;
64
70
  targetMode?: "resolve" | "assert" | "override" | undefined;
65
71
  }>, {
66
72
  command: string;
67
73
  timeoutSeconds: number;
68
- assetId: string;
69
74
  targetMode: "resolve" | "assert" | "override";
75
+ claimId?: string | undefined;
70
76
  target?: {
71
77
  host?: string | undefined;
72
78
  hostKeySha256?: string | undefined;
73
79
  } | undefined;
80
+ assetId?: string | undefined;
74
81
  }, {
75
82
  command: string;
76
- assetId: string;
83
+ claimId?: string | undefined;
77
84
  target?: {
78
85
  host?: string | undefined;
79
86
  hostKeySha256?: string | undefined;
80
87
  } | undefined;
81
88
  timeoutSeconds?: number | undefined;
89
+ assetId?: string | undefined;
82
90
  targetMode?: "resolve" | "assert" | "override" | undefined;
83
91
  }>;
84
92
  export type LabSshInput = z.output<typeof LabSshInputSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/contract.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,gBAAgB,QAAiC,CAAC;AAC/D,eAAO,MAAM,gBAAgB,QAA+B,CAAC;AAC7D,eAAO,MAAM,YAAY,QAAwE,CAAC;AAClG,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;;;;;;EAKpB,CAAC;AAEZ,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;CAU5B,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAa1B,CAAC;AAEL,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE7D,0GAA0G;AAC1G,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,CAOvD"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/contract.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,gBAAgB,QAAiC,CAAC;AAC/D,wGAAwG;AACxG,eAAO,MAAM,gBAAgB,QAA6C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAA+B,CAAC;AAC7D,eAAO,MAAM,YAAY,QAAwE,CAAC;AAClG,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;;;;;;EAKpB,CAAC;AAEZ,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAY5B,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB1B,CAAC;AAEL,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE7D,0GAA0G;AAC1G,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,CAQvD"}
@@ -5,6 +5,8 @@
5
5
  import { createHash } from "node:crypto";
6
6
  import { z } from "zod";
7
7
  export const LAB_SSH_ASSET_ID = /^[a-z0-9][a-z0-9._-]{0,127}$/;
8
+ /** Kubernetes DNS-1123 subdomain: the ApplianceClaim metadata.name (for example claim-uat-1815-302). */
9
+ export const LAB_SSH_CLAIM_ID = /^[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?$/;
8
10
  export const LAB_SSH_HOST_KEY = /^SHA256:[A-Za-z0-9+/]{43}$/;
9
11
  export const LAB_SSH_IPV4 = /^(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)$/;
10
12
  export const LAB_SSH_MAX_COMMAND_BYTES = 65_536;
@@ -15,8 +17,10 @@ export const LabSshTargetSchema = z
15
17
  })
16
18
  .strict();
17
19
  export const LabSshInputShape = {
18
- assetId: z.string().regex(LAB_SSH_ASSET_ID)
19
- .describe("Exact lab asset ID of the guest (from list_appliance_claims or list_inventory). The MCP resolves address, host key and credentials."),
20
+ assetId: z.string().regex(LAB_SSH_ASSET_ID).optional()
21
+ .describe("Exact lab asset ID of the guest (from list_appliance_claims or list_inventory). Provide exactly one of assetId or claimId. The MCP resolves address, host key and credentials."),
22
+ claimId: z.string().regex(LAB_SSH_CLAIM_ID).optional()
23
+ .describe("ApplianceClaim name (for example claim-uat-1815-302) as shown by list_appliance_claims. Alternative to assetId: the MCP resolves the claim's guest asset ID itself. Provide exactly one of assetId or claimId."),
20
24
  command: z.string().min(1).max(LAB_SSH_MAX_COMMAND_BYTES)
21
25
  .describe("Shell command run on the guest as `bash -c <command>`. Use `sudo -n` for root, and `sudo -n docker exec calltelemetry-db-1 psql -U calltelemetry -d calltelemetry_prod -t -A -c '<sql>'` for database queries."),
22
26
  timeoutSeconds: z.number().int().min(1).max(600).optional().default(60)
@@ -29,6 +33,9 @@ export const LabSshInputSchema = z
29
33
  .object(LabSshInputShape)
30
34
  .strict()
31
35
  .superRefine((value, ctx) => {
36
+ if ((value.assetId === undefined) === (value.claimId === undefined)) {
37
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["assetId"], message: "provide exactly one of assetId or claimId" });
38
+ }
32
39
  if (Buffer.byteLength(value.command, "utf8") > LAB_SSH_MAX_COMMAND_BYTES) {
33
40
  ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["command"], message: "command exceeds 64 KiB" });
34
41
  }
@@ -47,6 +54,8 @@ export function labSshCommandSha256(command) {
47
54
  return createHash("sha256").update(labSshRemoteTokens(command).join("\0")).digest("hex");
48
55
  }
49
56
  export function labSshArgv(input) {
57
+ if (!input.assetId)
58
+ throw new Error("labSshArgv requires a resolved assetId");
50
59
  const argv = ["vm", "ssh", "--asset-id", input.assetId, "--json", "--timeout-seconds", String(input.timeoutSeconds)];
51
60
  const flag = input.targetMode === "assert" ? "--expect" : input.targetMode === "override" ? "--override" : undefined;
52
61
  if (flag && input.target?.host)
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/lab-exec/contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/lab-exec/contract.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { CanonicalCommandResult } from "../canonical/types.js";
2
+ import type { CallToolResult } from "../types/mcp.js";
2
3
  import { type LabSshInput } from "./contract.js";
3
4
  /** Portal identity, used only for audit; authorization already happened at the portal. */
4
5
  export interface LabExecCaller {
@@ -14,6 +15,9 @@ export interface LabExecOutcome {
14
15
  export interface LabExecutor {
15
16
  readonly location: "local" | "remote";
16
17
  ssh(input: LabSshInput, caller?: LabExecCaller): Promise<LabExecOutcome>;
18
+ /** Read-only claim discovery (REL-1961). Returns the exact tool result the local handler produces. */
19
+ claimsList?(input: unknown, caller?: LabExecCaller): Promise<CallToolResult>;
20
+ claimsGet?(input: unknown, caller?: LabExecCaller): Promise<CallToolResult>;
17
21
  }
18
22
  export declare class LocalLabExecutor implements LabExecutor {
19
23
  private readonly bridge;
@@ -21,6 +25,8 @@ export declare class LocalLabExecutor implements LabExecutor {
21
25
  constructor(bridge: {
22
26
  run(args: string[], timeoutMs?: number): Promise<CanonicalCommandResult>;
23
27
  });
28
+ claimsList(input: unknown): Promise<CallToolResult>;
29
+ claimsGet(input: unknown): Promise<CallToolResult>;
24
30
  ssh(input: LabSshInput): Promise<LabExecOutcome>;
25
31
  }
26
32
  //# sourceMappingURL=executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC;IACtC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1E;AAKD,qBAAa,gBAAiB,YAAW,WAAW;IAGtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;gBAER,MAAM,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;KAAE;IAE3G,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;CASvD"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC;IACtC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACzE,sGAAsG;IACtG,UAAU,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7E,SAAS,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7E;AAKD,qBAAa,gBAAiB,YAAW,WAAW;IAGtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;gBAER,MAAM,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;KAAE;IAEjH,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAInD,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAI5C,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;CAUvD"}
@@ -1,3 +1,4 @@
1
+ import { handleGetApplianceClaim, handleListApplianceClaims } from "../tools/appliance-claim-tools.js";
1
2
  import { labSshArgv } from "./contract.js";
2
3
  /** Bridge headroom beyond the CLI's own --timeout-seconds for resolution and cleanup. */
3
4
  const RESOLUTION_GRACE_MS = 30_000;
@@ -7,7 +8,15 @@ export class LocalLabExecutor {
7
8
  constructor(bridge) {
8
9
  this.bridge = bridge;
9
10
  }
11
+ claimsList(input) {
12
+ return handleListApplianceClaims(input);
13
+ }
14
+ claimsGet(input) {
15
+ return handleGetApplianceClaim(input);
16
+ }
10
17
  async ssh(input) {
18
+ if (!input.assetId)
19
+ throw new Error("LocalLabExecutor requires a resolved assetId; wrap it in ClaimResolvingExecutor to accept claimId");
11
20
  const result = await this.bridge.run(labSshArgv(input), input.timeoutSeconds * 1000 + RESOLUTION_GRACE_MS);
12
21
  return {
13
22
  exitCode: result.exitCode,
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/lab-exec/executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAoB,MAAM,eAAe,CAAC;AAoB7D,yFAAyF;AACzF,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEnC,MAAM,OAAO,gBAAgB;IAGE;IAFpB,QAAQ,GAAG,OAAgB,CAAC;IAErC,YAA6B,MAAoF;QAApF,WAAM,GAAN,MAAM,CAA8E;IAAG,CAAC;IAErH,KAAK,CAAC,GAAG,CAAC,KAAkB;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,GAAG,mBAAmB,CAAC,CAAC;QAC3G,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/C,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/lab-exec/executor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AACvG,OAAO,EAAE,UAAU,EAAoB,MAAM,eAAe,CAAC;AAuB7D,yFAAyF;AACzF,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEnC,MAAM,OAAO,gBAAgB;IAGE;IAFpB,QAAQ,GAAG,OAAgB,CAAC;IAErC,YAA6B,MAAoF;QAApF,WAAM,GAAN,MAAM,CAA8E;IAAG,CAAC;IAErH,UAAU,CAAC,KAAc;QACvB,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,SAAS,CAAC,KAAc;QACtB,OAAO,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAkB;QAC1B,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;QACzI,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,GAAG,mBAAmB,CAAC,CAAC;QAC3G,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/C,CAAC;IACJ,CAAC;CACF"}
@@ -1,7 +1,11 @@
1
1
  /** Worker-side client for the lab executor behind Cloudflare Tunnel + Access (ADR 0934). */
2
+ import type { CallToolResult } from "../types/mcp.js";
2
3
  import type { LabSshInput } from "./contract.js";
3
4
  import type { LabExecCaller, LabExecOutcome, LabExecutor } from "./executor.js";
4
5
  export declare const LAB_EXEC_PATH = "/v1/lab-exec/ssh";
6
+ /** Read-only claim discovery routes (REL-1961). The zone WAF skip rule allows exactly these paths. */
7
+ export declare const LAB_EXEC_CLAIMS_LIST_PATH = "/v1/lab-exec/claims/list";
8
+ export declare const LAB_EXEC_CLAIMS_GET_PATH = "/v1/lab-exec/claims/get";
5
9
  /** Audit-only; the executor trusts it because only the Worker's service token can reach it. */
6
10
  export declare const LAB_EXEC_CALLER_HEADER = "X-CT-Lab-Caller";
7
11
  export interface RemoteLabExecutorOptions {
@@ -15,5 +19,8 @@ export declare class RemoteLabExecutor implements LabExecutor {
15
19
  readonly location: "remote";
16
20
  constructor(options: RemoteLabExecutorOptions);
17
21
  ssh(input: LabSshInput, caller?: LabExecCaller): Promise<LabExecOutcome>;
22
+ claimsList(input: unknown, caller?: LabExecCaller): Promise<CallToolResult>;
23
+ claimsGet(input: unknown, caller?: LabExecCaller): Promise<CallToolResult>;
24
+ private claims;
18
25
  }
19
26
  //# sourceMappingURL=remote.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/remote.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhF,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAChD,+FAA+F;AAC/F,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAGxD,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,qBAAa,iBAAkB,YAAW,WAAW;IAGvC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;gBAET,OAAO,EAAE,wBAAwB;IAIxD,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAwB/E"}
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/remote.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhF,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAChD,sGAAsG;AACtG,eAAO,MAAM,yBAAyB,6BAA6B,CAAC;AACpE,eAAO,MAAM,wBAAwB,4BAA4B,CAAC;AAElE,+FAA+F;AAC/F,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAGxD,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,qBAAa,iBAAkB,YAAW,WAAW;IAGvC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;gBAET,OAAO,EAAE,wBAAwB;IAIxD,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAyB9E,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAI3E,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;YAI5D,MAAM;CAmBrB"}
@@ -1,4 +1,8 @@
1
1
  export const LAB_EXEC_PATH = "/v1/lab-exec/ssh";
2
+ /** Read-only claim discovery routes (REL-1961). The zone WAF skip rule allows exactly these paths. */
3
+ export const LAB_EXEC_CLAIMS_LIST_PATH = "/v1/lab-exec/claims/list";
4
+ export const LAB_EXEC_CLAIMS_GET_PATH = "/v1/lab-exec/claims/get";
5
+ const CLAIMS_TIMEOUT_MS = 30_000;
2
6
  /** Audit-only; the executor trusts it because only the Worker's service token can reach it. */
3
7
  export const LAB_EXEC_CALLER_HEADER = "X-CT-Lab-Caller";
4
8
  const TRANSPORT_GRACE_MS = 45_000;
@@ -35,5 +39,31 @@ export class RemoteLabExecutor {
35
39
  ...(body.timedOut ? { timedOut: true } : {}),
36
40
  };
37
41
  }
42
+ claimsList(input, caller) {
43
+ return this.claims(LAB_EXEC_CLAIMS_LIST_PATH, input, caller);
44
+ }
45
+ claimsGet(input, caller) {
46
+ return this.claims(LAB_EXEC_CLAIMS_GET_PATH, input, caller);
47
+ }
48
+ async claims(path, input, caller) {
49
+ const headers = {
50
+ "content-type": "application/json",
51
+ "CF-Access-Client-Id": this.options.clientId,
52
+ "CF-Access-Client-Secret": this.options.clientSecret,
53
+ };
54
+ if (caller?.identity)
55
+ headers[LAB_EXEC_CALLER_HEADER] = caller.identity;
56
+ const response = await (this.options.fetchImpl ?? fetch)(new URL(path, this.options.url), {
57
+ method: "POST",
58
+ headers,
59
+ body: JSON.stringify(input ?? {}),
60
+ signal: AbortSignal.timeout(CLAIMS_TIMEOUT_MS),
61
+ });
62
+ const body = (await response.json().catch(() => undefined));
63
+ if (!response.ok || !body || !Array.isArray(body.content)) {
64
+ throw new Error(`lab executor HTTP ${response.status}`);
65
+ }
66
+ return body;
67
+ }
38
68
  }
39
69
  //# sourceMappingURL=remote.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../src/lab-exec/remote.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAC;AAChD,+FAA+F;AAC/F,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;AACxD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AASlC,MAAM,OAAO,iBAAiB;IAGC;IAFpB,QAAQ,GAAG,QAAiB,CAAC;IAEtC,YAA6B,OAAiC;QAAjC,YAAO,GAAP,OAAO,CAA0B;QAC5D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACpG,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAkB,EAAE,MAAsB;QAClD,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,qBAAqB,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC5C,yBAAyB,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY;SACrD,CAAC;QACF,IAAI,MAAM,EAAE,QAAQ;YAAE,OAAO,CAAC,sBAAsB,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;QACxE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACjG,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC3B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,GAAG,kBAAkB,CAAC;SAC9E,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAwC,CAAC;QACnG,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;YACjC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7C,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../src/lab-exec/remote.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { CallToolResult } from "../types/mcp.js";
2
2
  import type { LabExecOutcome } from "./executor.js";
3
3
  export declare const VM_SSH_RESULT_SCHEMA = "ct-lab-vm-ssh-result/v1";
4
- export declare function labSshToolResult(outcome: LabExecOutcome, assetId: string): CallToolResult;
4
+ export declare function labSshToolResult(outcome: LabExecOutcome, assetId: string | undefined): CallToolResult;
5
5
  //# sourceMappingURL=result.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAyB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAyB9D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CA+BzF"}
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../../src/lab-exec/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAyB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAyB9D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CA+BrG"}
@@ -13,7 +13,7 @@ export function labSshToolResult(outcome, assetId) {
13
13
  const envelope = outcome.exitCode === 0 && !outcome.timedOut ? parseVmSshResult(outcome.stdout) : undefined;
14
14
  if (!envelope) {
15
15
  return createToolErrorResult("LAB_SSH_UNAVAILABLE", outcome.stderr
16
- || (outcome.timedOut ? "lab_ssh timed out before the canonical lab CLI answered" : "canonical lab CLI returned no vm ssh result"), { operation: "lab_ssh", assetId, exitCode: outcome.exitCode, ...(outcome.timedOut ? { timedOut: true } : {}) });
16
+ || (outcome.timedOut ? "lab_ssh timed out before the canonical lab CLI answered" : "canonical lab CLI returned no vm ssh result"), { operation: "lab_ssh", ...(assetId ? { assetId } : {}), exitCode: outcome.exitCode, ...(outcome.timedOut ? { timedOut: true } : {}) });
17
17
  }
18
18
  const structuredContent = {
19
19
  assetId: envelope.asset_id,