@agent-vm/gateway-interface 0.0.71 → 0.0.72
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/dist/index.d.ts +111 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +104 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -145,7 +145,7 @@ interface GatewayAuthConfig {
|
|
|
145
145
|
}) => string;
|
|
146
146
|
}
|
|
147
147
|
interface GatewayAuthProfilesRef {
|
|
148
|
-
readonly source: '1password' | 'environment';
|
|
148
|
+
readonly source: '1password' | 'config' | 'environment';
|
|
149
149
|
}
|
|
150
150
|
interface OnePasswordGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
|
|
151
151
|
readonly source: '1password';
|
|
@@ -155,10 +155,17 @@ interface EnvironmentGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
|
|
|
155
155
|
readonly source: 'environment';
|
|
156
156
|
readonly envVar: string;
|
|
157
157
|
}
|
|
158
|
+
interface ConfigGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
|
|
159
|
+
readonly source: 'config';
|
|
160
|
+
readonly value: string;
|
|
161
|
+
}
|
|
158
162
|
type GatewaySshSecretEnvMode = 'always' | 'explicit' | 'never';
|
|
159
163
|
interface GatewaySshConfig {
|
|
160
164
|
readonly secretEnv: GatewaySshSecretEnvMode;
|
|
161
165
|
}
|
|
166
|
+
interface GatewayControllerAuthConfig {
|
|
167
|
+
readonly secret: string;
|
|
168
|
+
}
|
|
162
169
|
interface GatewayZoneBaseGatewayConfig {
|
|
163
170
|
readonly type: GatewayType;
|
|
164
171
|
readonly memory: string;
|
|
@@ -167,12 +174,13 @@ interface GatewayZoneBaseGatewayConfig {
|
|
|
167
174
|
readonly config: string;
|
|
168
175
|
readonly stateDir: string;
|
|
169
176
|
readonly ssh: GatewaySshConfig;
|
|
170
|
-
readonly authProfilesRef?: OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef | undefined;
|
|
177
|
+
readonly authProfilesRef?: ConfigGatewayAuthProfilesRef | OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef | undefined;
|
|
171
178
|
}
|
|
172
179
|
interface OpenClawGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {
|
|
173
180
|
readonly type: 'openclaw';
|
|
174
181
|
readonly zoneFilesDir: string;
|
|
175
|
-
readonly
|
|
182
|
+
readonly controllerAuth: GatewayControllerAuthConfig;
|
|
183
|
+
readonly authProfilesByAgent?: Readonly<Record<string, ConfigGatewayAuthProfilesRef | OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef>>;
|
|
176
184
|
readonly rawEnvSecrets?: readonly string[];
|
|
177
185
|
}
|
|
178
186
|
interface WorkerGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {
|
|
@@ -187,7 +195,11 @@ interface EnvironmentSecretSourceConfig {
|
|
|
187
195
|
readonly source: 'environment';
|
|
188
196
|
readonly envVar: string;
|
|
189
197
|
}
|
|
190
|
-
|
|
198
|
+
interface ConfigSecretSourceConfig {
|
|
199
|
+
readonly source: 'config';
|
|
200
|
+
readonly value: string;
|
|
201
|
+
}
|
|
202
|
+
type SecretSourceConfig = OnePasswordSecretSourceConfig | EnvironmentSecretSourceConfig | ConfigSecretSourceConfig;
|
|
191
203
|
type EnvInjectedGatewaySecretConfig = SecretSourceConfig & {
|
|
192
204
|
readonly audience: 'gateway';
|
|
193
205
|
readonly injection: 'env';
|
|
@@ -283,5 +295,99 @@ type SplitResolvedGatewaySecretsResult = SplitResolvedSecretsResult;
|
|
|
283
295
|
declare function splitResolvedGatewaySecrets(zone: GatewayZoneConfig, resolvedSecrets: Record<string, string>): SplitResolvedGatewaySecretsResult;
|
|
284
296
|
declare function mergeRuntimeGatewaySecrets(baseSecrets: SplitResolvedSecretsResult, options?: MergeRuntimeGatewaySecretsOptions): SplitResolvedSecretsResult;
|
|
285
297
|
//#endregion
|
|
286
|
-
|
|
298
|
+
//#region src/tool-vm-active-use.d.ts
|
|
299
|
+
type ToolVmActiveUseOutcome = 'abandoned' | 'cancelled' | 'completed' | 'failed' | 'timed-out';
|
|
300
|
+
interface ToolVmActiveUseCorrelation {
|
|
301
|
+
readonly agentId?: string;
|
|
302
|
+
readonly sessionId?: string;
|
|
303
|
+
readonly sessionKey?: string;
|
|
304
|
+
readonly toolCallId?: string;
|
|
305
|
+
readonly toolName?: string;
|
|
306
|
+
}
|
|
307
|
+
interface StartToolVmActiveUseRequest {
|
|
308
|
+
readonly correlation?: ToolVmActiveUseCorrelation;
|
|
309
|
+
readonly useId: string;
|
|
310
|
+
}
|
|
311
|
+
interface StartToolVmActiveUseResponse {
|
|
312
|
+
readonly expiresAt: number;
|
|
313
|
+
readonly heartbeatAfterMs: number;
|
|
314
|
+
readonly useId: string;
|
|
315
|
+
}
|
|
316
|
+
interface HeartbeatToolVmActiveUseResponse {
|
|
317
|
+
readonly expiresAt: number;
|
|
318
|
+
readonly heartbeatAfterMs: number;
|
|
319
|
+
}
|
|
320
|
+
interface EndToolVmActiveUseRequest {
|
|
321
|
+
readonly outcome: ToolVmActiveUseOutcome;
|
|
322
|
+
}
|
|
323
|
+
interface ToolVmActiveUseHandle {
|
|
324
|
+
readonly useId: string;
|
|
325
|
+
dispose(outcome?: ToolVmActiveUseOutcome): Promise<void>;
|
|
326
|
+
end(outcome?: ToolVmActiveUseOutcome): Promise<void>;
|
|
327
|
+
}
|
|
328
|
+
interface CreateToolVmActiveUseHandleOptions {
|
|
329
|
+
readonly correlation?: ToolVmActiveUseCorrelation;
|
|
330
|
+
readonly endActiveUse: (useId: string, request: EndToolVmActiveUseRequest) => Promise<void>;
|
|
331
|
+
readonly heartbeatActiveUse: (useId: string) => Promise<HeartbeatToolVmActiveUseResponse>;
|
|
332
|
+
readonly isEndErrorTolerable?: (error: unknown) => boolean;
|
|
333
|
+
readonly logEndFailure?: (error: unknown) => void;
|
|
334
|
+
readonly logHeartbeatFailure?: (error: unknown) => void;
|
|
335
|
+
readonly maxHeartbeatDurationMs?: number;
|
|
336
|
+
readonly nowImpl?: () => number;
|
|
337
|
+
readonly startActiveUse: (request: StartToolVmActiveUseRequest) => Promise<StartToolVmActiveUseResponse>;
|
|
338
|
+
readonly setTimeoutImpl?: typeof setTimeout;
|
|
339
|
+
readonly clearTimeoutImpl?: typeof clearTimeout;
|
|
340
|
+
}
|
|
341
|
+
declare function createToolVmActiveUseId(): string;
|
|
342
|
+
declare function isToolVmActiveUseId(value: string): boolean;
|
|
343
|
+
declare function createToolVmActiveUseHandle(options: CreateToolVmActiveUseHandleOptions): Promise<ToolVmActiveUseHandle>;
|
|
344
|
+
//#endregion
|
|
345
|
+
//#region src/vm-capability-lease.d.ts
|
|
346
|
+
/**
|
|
347
|
+
* Small host-issued capability envelope shared by VM-backed transports. The
|
|
348
|
+
* transport tag keeps SSH Tool VM leases distinct from future host-side
|
|
349
|
+
* Gondolin RPC or bridge capabilities without inventing a transport object.
|
|
350
|
+
*/
|
|
351
|
+
interface VmCapabilityLease<TTransport extends string> {
|
|
352
|
+
readonly leaseId: string;
|
|
353
|
+
readonly transport: TTransport;
|
|
354
|
+
}
|
|
355
|
+
interface VmSshEndpoint {
|
|
356
|
+
readonly host: string;
|
|
357
|
+
readonly identityPem: string;
|
|
358
|
+
readonly knownHostsLine: string;
|
|
359
|
+
readonly port: number;
|
|
360
|
+
readonly user: string;
|
|
361
|
+
}
|
|
362
|
+
interface VmSshPublicEndpoint {
|
|
363
|
+
readonly host: string;
|
|
364
|
+
readonly port: number;
|
|
365
|
+
readonly user: string;
|
|
366
|
+
}
|
|
367
|
+
interface VmSshLease<TTransport extends string> extends VmCapabilityLease<TTransport> {
|
|
368
|
+
readonly ssh: VmSshEndpoint;
|
|
369
|
+
}
|
|
370
|
+
declare function isVmCapabilityLease<TTransport extends string>(value: unknown, transport: TTransport): value is VmCapabilityLease<TTransport>;
|
|
371
|
+
declare function isVmSshEndpoint(value: unknown): value is VmSshEndpoint;
|
|
372
|
+
declare function isVmSshPublicEndpoint(value: unknown): value is VmSshPublicEndpoint;
|
|
373
|
+
//#endregion
|
|
374
|
+
//#region src/tool-vm-lease.d.ts
|
|
375
|
+
interface ToolVmSshLease extends VmSshLease<'ssh-sandbox'> {
|
|
376
|
+
readonly tcpSlot: number;
|
|
377
|
+
readonly workdir: string;
|
|
378
|
+
}
|
|
379
|
+
interface ToolVmLeasePeek extends VmCapabilityLease<'ssh-sandbox'> {
|
|
380
|
+
readonly createdAt: number;
|
|
381
|
+
readonly lastUsedAt: number;
|
|
382
|
+
readonly profileId: string;
|
|
383
|
+
readonly scopeKey: string;
|
|
384
|
+
readonly ssh: VmSshPublicEndpoint;
|
|
385
|
+
readonly tcpSlot: number;
|
|
386
|
+
readonly workdir: string;
|
|
387
|
+
readonly zoneId: string;
|
|
388
|
+
}
|
|
389
|
+
declare function isToolVmSshLease(value: unknown): value is ToolVmSshLease;
|
|
390
|
+
declare function isToolVmLeasePeek(value: unknown): value is ToolVmLeasePeek;
|
|
391
|
+
//#endregion
|
|
392
|
+
export { type BuildGatewayVmSpecOptions, type CreateToolVmActiveUseHandleOptions, type EgressHostConfig, type EndToolVmActiveUseRequest, type EnvInjectedGatewaySecretConfig, FORCE_IPV4_EGRESS_NODE_OPTIONS, type GatewayAuthConfig, type GatewayHealthCheck, type GatewayLifecycle, type GatewayProcessSpec, type GatewaySecretConfig, type GatewayType, type GatewayVmSpec, type GatewayZoneAgentConfig, type GatewayZoneConfig, type GatewayZoneMcpPortalConfig, type HeartbeatToolVmActiveUseResponse, type HttpMediatedGatewaySecretConfig, type RuntimeVmAudience, type SecretInjectionConfig, type SplitResolvedGatewaySecretsResult, type SplitResolvedSecretsResult, type StartToolVmActiveUseRequest, type StartToolVmActiveUseResponse, type ToolVmActiveUseCorrelation, type ToolVmActiveUseHandle, type ToolVmActiveUseOutcome, type ToolVmLeasePeek, type ToolVmSshLease, type VmAudience, type VmCapabilityLease, type VmSshEndpoint, type VmSshLease, type VmSshPublicEndpoint, buildGatewaySessionLabel, buildToolSessionLabel, composeNodeOptions, controllerVmHost, createToolVmActiveUseHandle, createToolVmActiveUseId, egressHostsForAudience, gatewayTypeValues, gatewayVmAllowedHosts, isToolVmActiveUseId, isToolVmLeasePeek, isToolVmSshLease, isVmCapabilityLease, isVmSshEndpoint, isVmSshPublicEndpoint, mergeRuntimeGatewaySecrets, splitResolvedGatewaySecrets, splitResolvedSecretsByInjection, targetsAudience, vmAudienceValues };
|
|
287
393
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/gateway-runtime-contract.ts","../src/audience.ts","../src/force-ipv4-egress.ts","../src/gateway-process-spec.ts","../src/gateway-vm-spec.ts","../src/gateway-lifecycle.ts","../src/split-resolved-gateway-secrets.ts"],"mappings":";;;;cAAa,iBAAA;AAAA,KAED,WAAA,WAAsB,iBAAA;AAAA,iBAElB,wBAAA,CAAyB,gBAAA,UAA0B,MAAA;AAAA,iBAInD,qBAAA,CACf,gBAAA,UACA,MAAA,UACA,OAAA;;;cCXY,gBAAA;AAAA,KAED,UAAA,WAAqB,gBAAA;AAAA,KACrB,iBAAA,GAAoB,OAAA,CAAQ,UAAA;AAAA,UAEvB,gBAAA;EAAA,SACP,IAAA;EAAA,SACA,QAAA,EAAU,UAAA;AAAA;AAAA,cAGP,gBAAA;AAAA,iBAEG,eAAA,CACf,cAAA,EAAgB,UAAA,EAChB,eAAA,EAAiB,iBAAA;AAAA,iBAKF,sBAAA,CACf,WAAA,WAAsB,gBAAA,IACtB,eAAA,EAAiB,iBAAA;AAAA,iBAOF,qBAAA,CAAsB,WAAA,WAAsB,gBAAA;;;;;;;AD5B5D;;;;;AAEA;;;;;AAEA;;;;;AAIA;;;;;;;;;;;;ACRA;;;;cCmCa,8BAAA;ADjCb;;;;;AACA;;;;;AAEA;;;;;;;;;AAKA;;;;;AAEA;;;;AAVA,iBCgEgB,kBAAA,CAAmB,SAAA;;;KClEvB,kBAAA;EAAA,SACE,IAAA;EAAA,SAAuB,IAAA;EAAA,SAAuB,IAAA;AAAA;EAAA,SAC9C,IAAA;EAAA,SAA0B,OAAA;AAAA;;AHAxC;;;UGMiB,kBAAA;EAAA,SACP,gBAAA;EAAA,SACA,YAAA;EAAA,SACA,WAAA,EAAa,kBAAA;EAAA,SACb,eAAA;EAAA,SACA,OAAA;AAAA;;;;;AHbV;;UIOiB,aAAA;EAAA,SACP,WAAA,EAAa,MAAA;EAAA,SACb,SAAA,EAAW,MAAA,SAAe,YAAA;EAAA,SAC1B,eAAA,EAAiB,MAAA,SAAe,kBAAA;EAAA,SAChC,QAAA,EAAU,MAAA;EAAA,SACV,YAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA;AAAA;;;;;;;UCHO,iBAAA;ELTM;;;;EAAA,SKcb,oBAAA;ELZ8B;;;;EAAA,SKkB9B,iBAAA,GACR,QAAA,UACA,OAAA;IAAA,SACU,UAAA;IAAA,SACA,OAAA;IAAA,SACA,UAAA;EAAA;AAAA;AAAA,UAKF,sBAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGA,iCAAA,SAA0C,sBAAA;EAAA,SAC1C,MAAA;EAAA,SACA,GAAA;AAAA;AAAA,UAGA,iCAAA,SAA0C,sBAAA;EAAA,SAC1C,MAAA;EAAA,SACA,MAAA;AAAA;AAAA,KAGE,uBAAA;AAAA,UAEK,gBAAA;EAAA,SACP,SAAA,EAAW,uBAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/gateway-runtime-contract.ts","../src/audience.ts","../src/force-ipv4-egress.ts","../src/gateway-process-spec.ts","../src/gateway-vm-spec.ts","../src/gateway-lifecycle.ts","../src/split-resolved-gateway-secrets.ts","../src/tool-vm-active-use.ts","../src/vm-capability-lease.ts","../src/tool-vm-lease.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { v7, validate, version } from "uuid";
|
|
1
2
|
//#region src/gateway-runtime-contract.ts
|
|
2
3
|
const gatewayTypeValues = ["openclaw", "worker"];
|
|
3
4
|
function buildGatewaySessionLabel(projectNamespace, zoneId) {
|
|
@@ -150,6 +151,108 @@ function mergeRuntimeGatewaySecrets(baseSecrets, options = {}) {
|
|
|
150
151
|
};
|
|
151
152
|
}
|
|
152
153
|
//#endregion
|
|
153
|
-
|
|
154
|
+
//#region src/tool-vm-active-use.ts
|
|
155
|
+
const defaultMaxHeartbeatDurationMs = 720 * 60 * 1e3;
|
|
156
|
+
function createToolVmActiveUseId() {
|
|
157
|
+
return v7();
|
|
158
|
+
}
|
|
159
|
+
function isToolVmActiveUseId(value) {
|
|
160
|
+
return validate(value) && version(value) === 7;
|
|
161
|
+
}
|
|
162
|
+
async function createToolVmActiveUseHandle(options) {
|
|
163
|
+
const useId = createToolVmActiveUseId();
|
|
164
|
+
const startedUse = await options.startActiveUse({
|
|
165
|
+
...options.correlation ? { correlation: options.correlation } : {},
|
|
166
|
+
useId
|
|
167
|
+
});
|
|
168
|
+
const setTimeoutImpl = options.setTimeoutImpl ?? setTimeout;
|
|
169
|
+
const clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout;
|
|
170
|
+
const now = options.nowImpl ?? Date.now;
|
|
171
|
+
const startedAt = now();
|
|
172
|
+
const maxHeartbeatDurationMs = options.maxHeartbeatDurationMs ?? defaultMaxHeartbeatDurationMs;
|
|
173
|
+
let ended = false;
|
|
174
|
+
let heartbeatTimer;
|
|
175
|
+
const clearHeartbeatTimer = () => {
|
|
176
|
+
if (heartbeatTimer) {
|
|
177
|
+
clearTimeoutImpl(heartbeatTimer);
|
|
178
|
+
heartbeatTimer = void 0;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const scheduleHeartbeat = (delayMs) => {
|
|
182
|
+
if (now() - startedAt >= maxHeartbeatDurationMs) return;
|
|
183
|
+
clearHeartbeatTimer();
|
|
184
|
+
heartbeatTimer = setTimeoutImpl(() => {
|
|
185
|
+
if (now() - startedAt >= maxHeartbeatDurationMs) return;
|
|
186
|
+
options.heartbeatActiveUse(startedUse.useId).then((heartbeat) => {
|
|
187
|
+
if (!ended) scheduleHeartbeat(heartbeat.heartbeatAfterMs);
|
|
188
|
+
}).catch((error) => {
|
|
189
|
+
options.logHeartbeatFailure?.(error);
|
|
190
|
+
if (!ended) scheduleHeartbeat(startedUse.heartbeatAfterMs);
|
|
191
|
+
});
|
|
192
|
+
}, delayMs);
|
|
193
|
+
};
|
|
194
|
+
scheduleHeartbeat(startedUse.heartbeatAfterMs);
|
|
195
|
+
const end = async (outcome = "completed") => {
|
|
196
|
+
if (ended) return;
|
|
197
|
+
ended = true;
|
|
198
|
+
clearHeartbeatTimer();
|
|
199
|
+
try {
|
|
200
|
+
await options.endActiveUse(startedUse.useId, { outcome });
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (options.isEndErrorTolerable?.(error) === true) {
|
|
203
|
+
options.logEndFailure?.(error);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
useId: startedUse.useId,
|
|
211
|
+
dispose: end,
|
|
212
|
+
end
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/vm-capability-lease.ts
|
|
217
|
+
const VM_SSH_PUBLIC_ENDPOINT_KEYS = new Set([
|
|
218
|
+
"host",
|
|
219
|
+
"port",
|
|
220
|
+
"user"
|
|
221
|
+
]);
|
|
222
|
+
function objectValue$1(value) {
|
|
223
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
224
|
+
}
|
|
225
|
+
function isNonEmptyString(value) {
|
|
226
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
227
|
+
}
|
|
228
|
+
function isVmCapabilityLease(value, transport) {
|
|
229
|
+
const record = objectValue$1(value);
|
|
230
|
+
return record !== void 0 && typeof Reflect.get(record, "leaseId") === "string" && Reflect.get(record, "transport") === transport;
|
|
231
|
+
}
|
|
232
|
+
function isVmSshEndpoint(value) {
|
|
233
|
+
const record = objectValue$1(value);
|
|
234
|
+
return record !== void 0 && typeof Reflect.get(record, "host") === "string" && isNonEmptyString(Reflect.get(record, "identityPem")) && typeof Reflect.get(record, "knownHostsLine") === "string" && typeof Reflect.get(record, "port") === "number" && typeof Reflect.get(record, "user") === "string";
|
|
235
|
+
}
|
|
236
|
+
function isVmSshPublicEndpoint(value) {
|
|
237
|
+
const record = objectValue$1(value);
|
|
238
|
+
if (record === void 0) return false;
|
|
239
|
+
for (const key of Object.keys(record)) if (!VM_SSH_PUBLIC_ENDPOINT_KEYS.has(key)) return false;
|
|
240
|
+
return typeof Reflect.get(record, "host") === "string" && typeof Reflect.get(record, "port") === "number" && typeof Reflect.get(record, "user") === "string";
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/tool-vm-lease.ts
|
|
244
|
+
function objectValue(value) {
|
|
245
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
246
|
+
}
|
|
247
|
+
function isToolVmSshLease(value) {
|
|
248
|
+
const record = objectValue(value);
|
|
249
|
+
return isVmCapabilityLease(record, "ssh-sandbox") && isVmSshEndpoint(Reflect.get(record, "ssh")) && typeof Reflect.get(record, "tcpSlot") === "number" && typeof Reflect.get(record, "workdir") === "string";
|
|
250
|
+
}
|
|
251
|
+
function isToolVmLeasePeek(value) {
|
|
252
|
+
const record = objectValue(value);
|
|
253
|
+
return isVmCapabilityLease(record, "ssh-sandbox") && typeof Reflect.get(record, "createdAt") === "number" && typeof Reflect.get(record, "lastUsedAt") === "number" && typeof Reflect.get(record, "profileId") === "string" && typeof Reflect.get(record, "scopeKey") === "string" && isVmSshPublicEndpoint(Reflect.get(record, "ssh")) && typeof Reflect.get(record, "tcpSlot") === "number" && typeof Reflect.get(record, "workdir") === "string" && typeof Reflect.get(record, "zoneId") === "string";
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
256
|
+
export { FORCE_IPV4_EGRESS_NODE_OPTIONS, buildGatewaySessionLabel, buildToolSessionLabel, composeNodeOptions, controllerVmHost, createToolVmActiveUseHandle, createToolVmActiveUseId, egressHostsForAudience, gatewayTypeValues, gatewayVmAllowedHosts, isToolVmActiveUseId, isToolVmLeasePeek, isToolVmSshLease, isVmCapabilityLease, isVmSshEndpoint, isVmSshPublicEndpoint, mergeRuntimeGatewaySecrets, splitResolvedGatewaySecrets, splitResolvedSecretsByInjection, targetsAudience, vmAudienceValues };
|
|
154
257
|
|
|
155
258
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/gateway-runtime-contract.ts","../src/audience.ts","../src/force-ipv4-egress.ts","../src/split-resolved-gateway-secrets.ts"],"sourcesContent":["export const gatewayTypeValues = ['openclaw', 'worker'] as const;\n\nexport type GatewayType = (typeof gatewayTypeValues)[number];\n\nexport function buildGatewaySessionLabel(projectNamespace: string, zoneId: string): string {\n\treturn `${projectNamespace}:${zoneId}:gateway`;\n}\n\nexport function buildToolSessionLabel(\n\tprojectNamespace: string,\n\tzoneId: string,\n\ttcpSlot: number,\n): string {\n\treturn `${projectNamespace}:${zoneId}:tool:${tcpSlot}`;\n}\n","export const vmAudienceValues = ['gateway', 'tool-vm', 'both'] as const;\n\nexport type VmAudience = (typeof vmAudienceValues)[number];\nexport type RuntimeVmAudience = Exclude<VmAudience, 'both'>;\n\nexport interface EgressHostConfig {\n\treadonly host: string;\n\treadonly audience: VmAudience;\n}\n\nexport const controllerVmHost = 'controller.vm.host';\n\nexport function targetsAudience(\n\tconfigAudience: VmAudience,\n\truntimeAudience: RuntimeVmAudience,\n): boolean {\n\treturn configAudience === runtimeAudience || configAudience === 'both';\n}\n\nexport function egressHostsForAudience(\n\tegressHosts: readonly EgressHostConfig[],\n\truntimeAudience: RuntimeVmAudience,\n): readonly string[] {\n\treturn egressHosts\n\t\t.filter((egressHost) => targetsAudience(egressHost.audience, runtimeAudience))\n\t\t.map((egressHost) => egressHost.host);\n}\n\nexport function gatewayVmAllowedHosts(egressHosts: readonly EgressHostConfig[]): readonly string[] {\n\treturn Array.from(new Set([controllerVmHost, ...egressHostsForAudience(egressHosts, 'gateway')]));\n}\n","/**\n * Canonical NODE_OPTIONS value for forcing IPv4-preference egress\n * in agent-vm VMs.\n *\n * Background: Gondolin's synthetic DNS (when tcpHosts is enabled)\n * returns a per-host IPv4 (reverse-lookable) and a single shared\n * IPv4-mapped IPv6 (::ffff:198.18.0.1, NOT reverse-lookable). Node\n * 20+'s fetch (via undici, autoSelectFamily: true) races both\n * families; when the IPv6 race wins (~5-20% under sequential load),\n * gondolin cannot route it and the request fails with a non-JSON\n * 400 (HTTP) or 403 (TLS). The two flags below stop the race:\n *\n * --dns-result-order=ipv4first changes dns.lookup() so\n * IPv4 addresses are listed\n * before IPv6.\n *\n * --no-network-family-autoselection disables Node's Happy\n * Eyeballs entirely. This is\n * the load-bearing flag —\n * --dns-result-order alone\n * doesn't prevent Node from\n * racing both families if\n * IPv4 is slow.\n *\n * Composition: NODE_OPTIONS is whitespace-separated. To add more\n * flags downstream, append rather than replace. Example:\n *\n * NODE_OPTIONS: `${FORCE_IPV4_EGRESS_NODE_OPTIONS} --inspect`\n *\n * Reference: see `shravan-claw@0ddf5f2:docs/wip/debugging/\n * 2026-05-21-lease-keepalive-400-and-discord-403-ipv6-race.md`\n * for the full root-cause analysis. Node-side flag references:\n * https://github.com/nodejs/node/issues/54359 (autoSelectFamily\n * revert recommendation by the Node core team).\n */\nexport const FORCE_IPV4_EGRESS_NODE_OPTIONS =\n\t'--dns-result-order=ipv4first --no-network-family-autoselection';\n\n/**\n * Compose the forced IPv4-preference flags with a user-provided\n * NODE_OPTIONS value (if any).\n *\n * Use this at every site where NODE_OPTIONS is set into a VM env\n * block AFTER a spread of user-controlled secrets, to guarantee\n * the forced flags are always present in the final value even if\n * a zone secret happens to provide its own NODE_OPTIONS.\n *\n * Forced flags come FIRST so they are unambiguously applied.\n * User-provided flags are appended verbatim. Node treats NODE_OPTIONS\n * as a whitespace-separated list and all flags apply.\n *\n * Returns just the forced flags if the user value is undefined,\n * empty, or whitespace-only.\n *\n * Examples:\n *\n * composeNodeOptions(undefined)\n * ──► '--dns-result-order=ipv4first --no-network-family-autoselection'\n *\n * composeNodeOptions('')\n * ──► '--dns-result-order=ipv4first --no-network-family-autoselection'\n *\n * composeNodeOptions('--inspect=0.0.0.0:9229')\n * ──► '--dns-result-order=ipv4first --no-network-family-autoselection\n * --inspect=0.0.0.0:9229'\n */\nexport function composeNodeOptions(userValue: string | undefined): string {\n\tconst trimmed = userValue?.trim() ?? '';\n\tif (trimmed === '') {\n\t\treturn FORCE_IPV4_EGRESS_NODE_OPTIONS;\n\t}\n\treturn `${FORCE_IPV4_EGRESS_NODE_OPTIONS} ${trimmed}`;\n}\n","import type { MediatedSecretSpec } from '@agent-vm/secret-management';\n\nimport { targetsAudience, type RuntimeVmAudience } from './audience.js';\nimport type { GatewaySecretConfig, GatewayZoneConfig } from './gateway-lifecycle.js';\n\nexport interface SplitResolvedSecretsResult {\n\treadonly environmentSecrets: Record<string, string>;\n\treadonly mediatedSecrets: Record<string, MediatedSecretSpec>;\n}\n\nexport interface MergeRuntimeGatewaySecretsOptions {\n\treadonly logPrefix?: string;\n\treadonly runtimeEnvironment?: Readonly<Record<string, string>> | undefined;\n\treadonly runtimeMediatedSecrets?: Readonly<Record<string, MediatedSecretSpec>> | undefined;\n}\n\nexport type SecretInjectionConfig = GatewaySecretConfig;\n\nexport interface SplitResolvedSecretsOptions {\n\treadonly audience: RuntimeVmAudience;\n\treadonly logPrefix?: string;\n}\n\nexport function splitResolvedSecretsByInjection(\n\tsecretConfigs: Readonly<Record<string, SecretInjectionConfig>>,\n\tresolvedSecrets: Record<string, string>,\n\toptions: SplitResolvedSecretsOptions,\n): SplitResolvedSecretsResult {\n\tconst environmentSecrets: Record<string, string> = {};\n\tconst mediatedSecrets: Record<string, MediatedSecretSpec> = {};\n\tconst logPrefix = options.logPrefix ?? 'split-resolved-secrets';\n\n\tfor (const [secretName, secretValue] of Object.entries(resolvedSecrets)) {\n\t\tconst secretConfig = secretConfigs[secretName];\n\t\tif (!secretConfig) {\n\t\t\tthrow new Error(\n\t\t\t\t`[${logPrefix}] Secret '${secretName}' was resolved but has no matching secret config.`,\n\t\t\t);\n\t\t}\n\t\tif (!targetsAudience(secretConfig.audience, options.audience)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (secretConfig.injection === 'http-mediation') {\n\t\t\tif (secretConfig.hosts.length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`[${logPrefix}] Secret '${secretName}' uses http-mediation but declares no hosts.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tmediatedSecrets[secretName] = {\n\t\t\t\thosts: [...secretConfig.hosts],\n\t\t\t\tvalue: secretValue,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst envSecretAudience = (secretConfig as { readonly audience: string }).audience;\n\t\tif (envSecretAudience !== 'gateway') {\n\t\t\tthrow new Error(\n\t\t\t\t`[${logPrefix}] Secret '${secretName}' uses env injection with non-gateway audience '${envSecretAudience}'.`,\n\t\t\t);\n\t\t}\n\t\tif (options.audience === 'gateway') {\n\t\t\tenvironmentSecrets[secretName] = secretValue;\n\t\t}\n\t}\n\n\treturn { environmentSecrets, mediatedSecrets };\n}\n\nexport type SplitResolvedGatewaySecretsResult = SplitResolvedSecretsResult;\n\nexport function splitResolvedGatewaySecrets(\n\tzone: GatewayZoneConfig,\n\tresolvedSecrets: Record<string, string>,\n): SplitResolvedGatewaySecretsResult {\n\treturn splitResolvedSecretsByInjection(zone.secrets, resolvedSecrets, {\n\t\taudience: 'gateway',\n\t\tlogPrefix: 'split-resolved-gateway-secrets',\n\t});\n}\n\nfunction assertNoRuntimeSecretCollision(\n\tsecretName: string,\n\ttarget: 'environment' | 'http-mediation',\n\tbaseSecrets: SplitResolvedSecretsResult,\n\truntimeSeen: Set<string>,\n\tlogPrefix: string,\n): void {\n\tif (runtimeSeen.has(secretName)) {\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] Runtime gateway secret '${secretName}' is declared for both environment and http-mediation injection.`,\n\t\t);\n\t}\n\tif (secretName in baseSecrets.environmentSecrets) {\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] Runtime gateway ${target} secret '${secretName}' would overwrite an authored environment secret.`,\n\t\t);\n\t}\n\tif (secretName in baseSecrets.mediatedSecrets) {\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] Runtime gateway ${target} secret '${secretName}' would overwrite an authored http-mediation secret.`,\n\t\t);\n\t}\n\truntimeSeen.add(secretName);\n}\n\nexport function mergeRuntimeGatewaySecrets(\n\tbaseSecrets: SplitResolvedSecretsResult,\n\toptions: MergeRuntimeGatewaySecretsOptions = {},\n): SplitResolvedSecretsResult {\n\tconst logPrefix = options.logPrefix ?? 'merge-runtime-gateway-secrets';\n\tconst runtimeSeen = new Set<string>();\n\tfor (const secretName of Object.keys(options.runtimeEnvironment ?? {})) {\n\t\tassertNoRuntimeSecretCollision(secretName, 'environment', baseSecrets, runtimeSeen, logPrefix);\n\t}\n\tfor (const secretName of Object.keys(options.runtimeMediatedSecrets ?? {})) {\n\t\tassertNoRuntimeSecretCollision(\n\t\t\tsecretName,\n\t\t\t'http-mediation',\n\t\t\tbaseSecrets,\n\t\t\truntimeSeen,\n\t\t\tlogPrefix,\n\t\t);\n\t}\n\n\treturn {\n\t\tenvironmentSecrets: {\n\t\t\t...baseSecrets.environmentSecrets,\n\t\t\t...options.runtimeEnvironment,\n\t\t},\n\t\tmediatedSecrets: {\n\t\t\t...baseSecrets.mediatedSecrets,\n\t\t\t...options.runtimeMediatedSecrets,\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["uuidv7","validateUuid","uuidVersion","objectValue"],"sources":["../src/gateway-runtime-contract.ts","../src/audience.ts","../src/force-ipv4-egress.ts","../src/split-resolved-gateway-secrets.ts","../src/tool-vm-active-use.ts","../src/vm-capability-lease.ts","../src/tool-vm-lease.ts"],"sourcesContent":["export const gatewayTypeValues = ['openclaw', 'worker'] as const;\n\nexport type GatewayType = (typeof gatewayTypeValues)[number];\n\nexport function buildGatewaySessionLabel(projectNamespace: string, zoneId: string): string {\n\treturn `${projectNamespace}:${zoneId}:gateway`;\n}\n\nexport function buildToolSessionLabel(\n\tprojectNamespace: string,\n\tzoneId: string,\n\ttcpSlot: number,\n): string {\n\treturn `${projectNamespace}:${zoneId}:tool:${tcpSlot}`;\n}\n","export const vmAudienceValues = ['gateway', 'tool-vm', 'both'] as const;\n\nexport type VmAudience = (typeof vmAudienceValues)[number];\nexport type RuntimeVmAudience = Exclude<VmAudience, 'both'>;\n\nexport interface EgressHostConfig {\n\treadonly host: string;\n\treadonly audience: VmAudience;\n}\n\nexport const controllerVmHost = 'controller.vm.host';\n\nexport function targetsAudience(\n\tconfigAudience: VmAudience,\n\truntimeAudience: RuntimeVmAudience,\n): boolean {\n\treturn configAudience === runtimeAudience || configAudience === 'both';\n}\n\nexport function egressHostsForAudience(\n\tegressHosts: readonly EgressHostConfig[],\n\truntimeAudience: RuntimeVmAudience,\n): readonly string[] {\n\treturn egressHosts\n\t\t.filter((egressHost) => targetsAudience(egressHost.audience, runtimeAudience))\n\t\t.map((egressHost) => egressHost.host);\n}\n\nexport function gatewayVmAllowedHosts(egressHosts: readonly EgressHostConfig[]): readonly string[] {\n\treturn Array.from(new Set([controllerVmHost, ...egressHostsForAudience(egressHosts, 'gateway')]));\n}\n","/**\n * Canonical NODE_OPTIONS value for forcing IPv4-preference egress\n * in agent-vm VMs.\n *\n * Background: Gondolin's synthetic DNS (when tcpHosts is enabled)\n * returns a per-host IPv4 (reverse-lookable) and a single shared\n * IPv4-mapped IPv6 (::ffff:198.18.0.1, NOT reverse-lookable). Node\n * 20+'s fetch (via undici, autoSelectFamily: true) races both\n * families; when the IPv6 race wins (~5-20% under sequential load),\n * gondolin cannot route it and the request fails with a non-JSON\n * 400 (HTTP) or 403 (TLS). The two flags below stop the race:\n *\n * --dns-result-order=ipv4first changes dns.lookup() so\n * IPv4 addresses are listed\n * before IPv6.\n *\n * --no-network-family-autoselection disables Node's Happy\n * Eyeballs entirely. This is\n * the load-bearing flag —\n * --dns-result-order alone\n * doesn't prevent Node from\n * racing both families if\n * IPv4 is slow.\n *\n * Composition: NODE_OPTIONS is whitespace-separated. To add more\n * flags downstream, append rather than replace. Example:\n *\n * NODE_OPTIONS: `${FORCE_IPV4_EGRESS_NODE_OPTIONS} --inspect`\n *\n * Reference: see `shravan-claw@0ddf5f2:docs/wip/debugging/\n * 2026-05-21-lease-keepalive-400-and-discord-403-ipv6-race.md`\n * for the full root-cause analysis. Node-side flag references:\n * https://github.com/nodejs/node/issues/54359 (autoSelectFamily\n * revert recommendation by the Node core team).\n */\nexport const FORCE_IPV4_EGRESS_NODE_OPTIONS =\n\t'--dns-result-order=ipv4first --no-network-family-autoselection';\n\n/**\n * Compose the forced IPv4-preference flags with a user-provided\n * NODE_OPTIONS value (if any).\n *\n * Use this at every site where NODE_OPTIONS is set into a VM env\n * block AFTER a spread of user-controlled secrets, to guarantee\n * the forced flags are always present in the final value even if\n * a zone secret happens to provide its own NODE_OPTIONS.\n *\n * Forced flags come FIRST so they are unambiguously applied.\n * User-provided flags are appended verbatim. Node treats NODE_OPTIONS\n * as a whitespace-separated list and all flags apply.\n *\n * Returns just the forced flags if the user value is undefined,\n * empty, or whitespace-only.\n *\n * Examples:\n *\n * composeNodeOptions(undefined)\n * ──► '--dns-result-order=ipv4first --no-network-family-autoselection'\n *\n * composeNodeOptions('')\n * ──► '--dns-result-order=ipv4first --no-network-family-autoselection'\n *\n * composeNodeOptions('--inspect=0.0.0.0:9229')\n * ──► '--dns-result-order=ipv4first --no-network-family-autoselection\n * --inspect=0.0.0.0:9229'\n */\nexport function composeNodeOptions(userValue: string | undefined): string {\n\tconst trimmed = userValue?.trim() ?? '';\n\tif (trimmed === '') {\n\t\treturn FORCE_IPV4_EGRESS_NODE_OPTIONS;\n\t}\n\treturn `${FORCE_IPV4_EGRESS_NODE_OPTIONS} ${trimmed}`;\n}\n","import type { MediatedSecretSpec } from '@agent-vm/secret-management';\n\nimport { targetsAudience, type RuntimeVmAudience } from './audience.js';\nimport type { GatewaySecretConfig, GatewayZoneConfig } from './gateway-lifecycle.js';\n\nexport interface SplitResolvedSecretsResult {\n\treadonly environmentSecrets: Record<string, string>;\n\treadonly mediatedSecrets: Record<string, MediatedSecretSpec>;\n}\n\nexport interface MergeRuntimeGatewaySecretsOptions {\n\treadonly logPrefix?: string;\n\treadonly runtimeEnvironment?: Readonly<Record<string, string>> | undefined;\n\treadonly runtimeMediatedSecrets?: Readonly<Record<string, MediatedSecretSpec>> | undefined;\n}\n\nexport type SecretInjectionConfig = GatewaySecretConfig;\n\nexport interface SplitResolvedSecretsOptions {\n\treadonly audience: RuntimeVmAudience;\n\treadonly logPrefix?: string;\n}\n\nexport function splitResolvedSecretsByInjection(\n\tsecretConfigs: Readonly<Record<string, SecretInjectionConfig>>,\n\tresolvedSecrets: Record<string, string>,\n\toptions: SplitResolvedSecretsOptions,\n): SplitResolvedSecretsResult {\n\tconst environmentSecrets: Record<string, string> = {};\n\tconst mediatedSecrets: Record<string, MediatedSecretSpec> = {};\n\tconst logPrefix = options.logPrefix ?? 'split-resolved-secrets';\n\n\tfor (const [secretName, secretValue] of Object.entries(resolvedSecrets)) {\n\t\tconst secretConfig = secretConfigs[secretName];\n\t\tif (!secretConfig) {\n\t\t\tthrow new Error(\n\t\t\t\t`[${logPrefix}] Secret '${secretName}' was resolved but has no matching secret config.`,\n\t\t\t);\n\t\t}\n\t\tif (!targetsAudience(secretConfig.audience, options.audience)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (secretConfig.injection === 'http-mediation') {\n\t\t\tif (secretConfig.hosts.length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`[${logPrefix}] Secret '${secretName}' uses http-mediation but declares no hosts.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tmediatedSecrets[secretName] = {\n\t\t\t\thosts: [...secretConfig.hosts],\n\t\t\t\tvalue: secretValue,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst envSecretAudience = (secretConfig as { readonly audience: string }).audience;\n\t\tif (envSecretAudience !== 'gateway') {\n\t\t\tthrow new Error(\n\t\t\t\t`[${logPrefix}] Secret '${secretName}' uses env injection with non-gateway audience '${envSecretAudience}'.`,\n\t\t\t);\n\t\t}\n\t\tif (options.audience === 'gateway') {\n\t\t\tenvironmentSecrets[secretName] = secretValue;\n\t\t}\n\t}\n\n\treturn { environmentSecrets, mediatedSecrets };\n}\n\nexport type SplitResolvedGatewaySecretsResult = SplitResolvedSecretsResult;\n\nexport function splitResolvedGatewaySecrets(\n\tzone: GatewayZoneConfig,\n\tresolvedSecrets: Record<string, string>,\n): SplitResolvedGatewaySecretsResult {\n\treturn splitResolvedSecretsByInjection(zone.secrets, resolvedSecrets, {\n\t\taudience: 'gateway',\n\t\tlogPrefix: 'split-resolved-gateway-secrets',\n\t});\n}\n\nfunction assertNoRuntimeSecretCollision(\n\tsecretName: string,\n\ttarget: 'environment' | 'http-mediation',\n\tbaseSecrets: SplitResolvedSecretsResult,\n\truntimeSeen: Set<string>,\n\tlogPrefix: string,\n): void {\n\tif (runtimeSeen.has(secretName)) {\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] Runtime gateway secret '${secretName}' is declared for both environment and http-mediation injection.`,\n\t\t);\n\t}\n\tif (secretName in baseSecrets.environmentSecrets) {\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] Runtime gateway ${target} secret '${secretName}' would overwrite an authored environment secret.`,\n\t\t);\n\t}\n\tif (secretName in baseSecrets.mediatedSecrets) {\n\t\tthrow new Error(\n\t\t\t`[${logPrefix}] Runtime gateway ${target} secret '${secretName}' would overwrite an authored http-mediation secret.`,\n\t\t);\n\t}\n\truntimeSeen.add(secretName);\n}\n\nexport function mergeRuntimeGatewaySecrets(\n\tbaseSecrets: SplitResolvedSecretsResult,\n\toptions: MergeRuntimeGatewaySecretsOptions = {},\n): SplitResolvedSecretsResult {\n\tconst logPrefix = options.logPrefix ?? 'merge-runtime-gateway-secrets';\n\tconst runtimeSeen = new Set<string>();\n\tfor (const secretName of Object.keys(options.runtimeEnvironment ?? {})) {\n\t\tassertNoRuntimeSecretCollision(secretName, 'environment', baseSecrets, runtimeSeen, logPrefix);\n\t}\n\tfor (const secretName of Object.keys(options.runtimeMediatedSecrets ?? {})) {\n\t\tassertNoRuntimeSecretCollision(\n\t\t\tsecretName,\n\t\t\t'http-mediation',\n\t\t\tbaseSecrets,\n\t\t\truntimeSeen,\n\t\t\tlogPrefix,\n\t\t);\n\t}\n\n\treturn {\n\t\tenvironmentSecrets: {\n\t\t\t...baseSecrets.environmentSecrets,\n\t\t\t...options.runtimeEnvironment,\n\t\t},\n\t\tmediatedSecrets: {\n\t\t\t...baseSecrets.mediatedSecrets,\n\t\t\t...options.runtimeMediatedSecrets,\n\t\t},\n\t};\n}\n","import { v7 as uuidv7, validate as validateUuid, version as uuidVersion } from 'uuid';\n\nexport type ToolVmActiveUseOutcome =\n\t| 'abandoned'\n\t| 'cancelled'\n\t| 'completed'\n\t| 'failed'\n\t| 'timed-out';\n\nexport interface ToolVmActiveUseCorrelation {\n\treadonly agentId?: string;\n\treadonly sessionId?: string;\n\treadonly sessionKey?: string;\n\treadonly toolCallId?: string;\n\treadonly toolName?: string;\n}\n\nexport interface StartToolVmActiveUseRequest {\n\treadonly correlation?: ToolVmActiveUseCorrelation;\n\treadonly useId: string;\n}\n\nexport interface StartToolVmActiveUseResponse {\n\treadonly expiresAt: number;\n\treadonly heartbeatAfterMs: number;\n\treadonly useId: string;\n}\n\nexport interface HeartbeatToolVmActiveUseResponse {\n\treadonly expiresAt: number;\n\treadonly heartbeatAfterMs: number;\n}\n\nexport interface EndToolVmActiveUseRequest {\n\treadonly outcome: ToolVmActiveUseOutcome;\n}\n\nexport interface ToolVmActiveUseHandle {\n\treadonly useId: string;\n\tdispose(outcome?: ToolVmActiveUseOutcome): Promise<void>;\n\tend(outcome?: ToolVmActiveUseOutcome): Promise<void>;\n}\n\nexport interface CreateToolVmActiveUseHandleOptions {\n\treadonly correlation?: ToolVmActiveUseCorrelation;\n\treadonly endActiveUse: (useId: string, request: EndToolVmActiveUseRequest) => Promise<void>;\n\treadonly heartbeatActiveUse: (useId: string) => Promise<HeartbeatToolVmActiveUseResponse>;\n\treadonly isEndErrorTolerable?: (error: unknown) => boolean;\n\treadonly logEndFailure?: (error: unknown) => void;\n\treadonly logHeartbeatFailure?: (error: unknown) => void;\n\treadonly maxHeartbeatDurationMs?: number;\n\treadonly nowImpl?: () => number;\n\treadonly startActiveUse: (\n\t\trequest: StartToolVmActiveUseRequest,\n\t) => Promise<StartToolVmActiveUseResponse>;\n\treadonly setTimeoutImpl?: typeof setTimeout;\n\treadonly clearTimeoutImpl?: typeof clearTimeout;\n}\n\ntype HeartbeatTimer = ReturnType<typeof setTimeout>;\n\nconst defaultMaxHeartbeatDurationMs = 12 * 60 * 60 * 1000;\n\nexport function createToolVmActiveUseId(): string {\n\treturn uuidv7();\n}\n\nexport function isToolVmActiveUseId(value: string): boolean {\n\treturn validateUuid(value) && uuidVersion(value) === 7;\n}\n\nexport async function createToolVmActiveUseHandle(\n\toptions: CreateToolVmActiveUseHandleOptions,\n): Promise<ToolVmActiveUseHandle> {\n\tconst useId = createToolVmActiveUseId();\n\tconst startedUse = await options.startActiveUse({\n\t\t...(options.correlation ? { correlation: options.correlation } : {}),\n\t\tuseId,\n\t});\n\tconst setTimeoutImpl = options.setTimeoutImpl ?? setTimeout;\n\tconst clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout;\n\tconst now = options.nowImpl ?? Date.now;\n\tconst startedAt = now();\n\tconst maxHeartbeatDurationMs = options.maxHeartbeatDurationMs ?? defaultMaxHeartbeatDurationMs;\n\tlet ended = false;\n\tlet heartbeatTimer: HeartbeatTimer | undefined;\n\n\tconst clearHeartbeatTimer = (): void => {\n\t\tif (heartbeatTimer) {\n\t\t\tclearTimeoutImpl(heartbeatTimer);\n\t\t\theartbeatTimer = undefined;\n\t\t}\n\t};\n\n\tconst scheduleHeartbeat = (delayMs: number): void => {\n\t\tif (now() - startedAt >= maxHeartbeatDurationMs) {\n\t\t\treturn;\n\t\t}\n\t\tclearHeartbeatTimer();\n\t\theartbeatTimer = setTimeoutImpl(() => {\n\t\t\tif (now() - startedAt >= maxHeartbeatDurationMs) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvoid options\n\t\t\t\t.heartbeatActiveUse(startedUse.useId)\n\t\t\t\t.then((heartbeat) => {\n\t\t\t\t\tif (!ended) {\n\t\t\t\t\t\tscheduleHeartbeat(heartbeat.heartbeatAfterMs);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\toptions.logHeartbeatFailure?.(error);\n\t\t\t\t\tif (!ended) {\n\t\t\t\t\t\tscheduleHeartbeat(startedUse.heartbeatAfterMs);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, delayMs);\n\t};\n\n\tscheduleHeartbeat(startedUse.heartbeatAfterMs);\n\n\tconst end = async (outcome: ToolVmActiveUseOutcome = 'completed'): Promise<void> => {\n\t\tif (ended) {\n\t\t\treturn;\n\t\t}\n\t\tended = true;\n\t\tclearHeartbeatTimer();\n\t\ttry {\n\t\t\tawait options.endActiveUse(startedUse.useId, { outcome });\n\t\t} catch (error) {\n\t\t\tif (options.isEndErrorTolerable?.(error) === true) {\n\t\t\t\toptions.logEndFailure?.(error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\treturn {\n\t\tuseId: startedUse.useId,\n\t\tdispose: end,\n\t\tend,\n\t};\n}\n","const VM_SSH_PUBLIC_ENDPOINT_KEYS = new Set(['host', 'port', 'user']);\n\n/**\n * Small host-issued capability envelope shared by VM-backed transports. The\n * transport tag keeps SSH Tool VM leases distinct from future host-side\n * Gondolin RPC or bridge capabilities without inventing a transport object.\n */\nexport interface VmCapabilityLease<TTransport extends string> {\n\treadonly leaseId: string;\n\treadonly transport: TTransport;\n}\n\nexport interface VmSshEndpoint {\n\treadonly host: string;\n\treadonly identityPem: string;\n\treadonly knownHostsLine: string;\n\treadonly port: number;\n\treadonly user: string;\n}\n\nexport interface VmSshPublicEndpoint {\n\treadonly host: string;\n\treadonly port: number;\n\treadonly user: string;\n}\n\nexport interface VmSshLease<TTransport extends string> extends VmCapabilityLease<TTransport> {\n\treadonly ssh: VmSshEndpoint;\n}\n\nfunction objectValue(value: unknown): object | undefined {\n\treturn typeof value === 'object' && value !== null ? value : undefined;\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n\treturn typeof value === 'string' && value.trim().length > 0;\n}\n\nexport function isVmCapabilityLease<TTransport extends string>(\n\tvalue: unknown,\n\ttransport: TTransport,\n): value is VmCapabilityLease<TTransport> {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'leaseId') === 'string' &&\n\t\tReflect.get(record, 'transport') === transport\n\t);\n}\n\nexport function isVmSshEndpoint(value: unknown): value is VmSshEndpoint {\n\tconst record = objectValue(value);\n\treturn (\n\t\trecord !== undefined &&\n\t\ttypeof Reflect.get(record, 'host') === 'string' &&\n\t\tisNonEmptyString(Reflect.get(record, 'identityPem')) &&\n\t\ttypeof Reflect.get(record, 'knownHostsLine') === 'string' &&\n\t\ttypeof Reflect.get(record, 'port') === 'number' &&\n\t\ttypeof Reflect.get(record, 'user') === 'string'\n\t);\n}\n\nexport function isVmSshPublicEndpoint(value: unknown): value is VmSshPublicEndpoint {\n\tconst record = objectValue(value);\n\tif (record === undefined) {\n\t\treturn false;\n\t}\n\tfor (const key of Object.keys(record)) {\n\t\tif (!VM_SSH_PUBLIC_ENDPOINT_KEYS.has(key)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn (\n\t\ttypeof Reflect.get(record, 'host') === 'string' &&\n\t\ttypeof Reflect.get(record, 'port') === 'number' &&\n\t\ttypeof Reflect.get(record, 'user') === 'string'\n\t);\n}\n","import {\n\tisVmCapabilityLease,\n\tisVmSshEndpoint,\n\tisVmSshPublicEndpoint,\n\ttype VmCapabilityLease,\n\ttype VmSshLease,\n\ttype VmSshPublicEndpoint,\n} from './vm-capability-lease.js';\n\nexport interface ToolVmSshLease extends VmSshLease<'ssh-sandbox'> {\n\treadonly tcpSlot: number;\n\treadonly workdir: string;\n}\n\nexport interface ToolVmLeasePeek extends VmCapabilityLease<'ssh-sandbox'> {\n\treadonly createdAt: number;\n\treadonly lastUsedAt: number;\n\treadonly profileId: string;\n\treadonly scopeKey: string;\n\treadonly ssh: VmSshPublicEndpoint;\n\treadonly tcpSlot: number;\n\treadonly workdir: string;\n\treadonly zoneId: string;\n}\n\nfunction objectValue(value: unknown): object | undefined {\n\treturn typeof value === 'object' && value !== null ? value : undefined;\n}\n\nexport function isToolVmSshLease(value: unknown): value is ToolVmSshLease {\n\tconst record = objectValue(value);\n\treturn (\n\t\tisVmCapabilityLease(record, 'ssh-sandbox') &&\n\t\tisVmSshEndpoint(Reflect.get(record, 'ssh')) &&\n\t\ttypeof Reflect.get(record, 'tcpSlot') === 'number' &&\n\t\ttypeof Reflect.get(record, 'workdir') === 'string'\n\t);\n}\n\nexport function isToolVmLeasePeek(value: unknown): value is ToolVmLeasePeek {\n\tconst record = objectValue(value);\n\treturn (\n\t\tisVmCapabilityLease(record, 'ssh-sandbox') &&\n\t\ttypeof Reflect.get(record, 'createdAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'lastUsedAt') === 'number' &&\n\t\ttypeof Reflect.get(record, 'profileId') === 'string' &&\n\t\ttypeof Reflect.get(record, 'scopeKey') === 'string' &&\n\t\tisVmSshPublicEndpoint(Reflect.get(record, 'ssh')) &&\n\t\ttypeof Reflect.get(record, 'tcpSlot') === 'number' &&\n\t\ttypeof Reflect.get(record, 'workdir') === 'string' &&\n\t\ttypeof Reflect.get(record, 'zoneId') === 'string'\n\t);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-vm/gateway-interface",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.72",
|
|
4
4
|
"description": "Shared TypeScript interfaces for VM gateway lifecycles, VmSpec, and ProcessSpec.",
|
|
5
5
|
"homepage": "https://github.com/ShravanSunder/agent-vm#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"
|
|
33
|
-
"@agent-vm/
|
|
32
|
+
"uuid": "^11.1.1",
|
|
33
|
+
"@agent-vm/secret-management": "0.0.72",
|
|
34
|
+
"@agent-vm/gondolin-adapter": "0.0.72"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "tsdown",
|