@agent-vm/gateway-interface 0.0.71 → 0.0.73
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 +114 -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
|
@@ -120,6 +120,7 @@ interface GatewayVmSpec {
|
|
|
120
120
|
readonly tcpHosts: Record<string, string>;
|
|
121
121
|
readonly allowedHosts: readonly string[];
|
|
122
122
|
readonly rootfsMode: 'readonly' | 'memory' | 'cow';
|
|
123
|
+
readonly runtimeRootfsSize?: string;
|
|
123
124
|
readonly sessionLabel: string;
|
|
124
125
|
}
|
|
125
126
|
//#endregion
|
|
@@ -145,7 +146,7 @@ interface GatewayAuthConfig {
|
|
|
145
146
|
}) => string;
|
|
146
147
|
}
|
|
147
148
|
interface GatewayAuthProfilesRef {
|
|
148
|
-
readonly source: '1password' | 'environment';
|
|
149
|
+
readonly source: '1password' | 'config' | 'environment';
|
|
149
150
|
}
|
|
150
151
|
interface OnePasswordGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
|
|
151
152
|
readonly source: '1password';
|
|
@@ -155,24 +156,34 @@ interface EnvironmentGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
|
|
|
155
156
|
readonly source: 'environment';
|
|
156
157
|
readonly envVar: string;
|
|
157
158
|
}
|
|
159
|
+
interface ConfigGatewayAuthProfilesRef extends GatewayAuthProfilesRef {
|
|
160
|
+
readonly source: 'config';
|
|
161
|
+
readonly value: string;
|
|
162
|
+
}
|
|
158
163
|
type GatewaySshSecretEnvMode = 'always' | 'explicit' | 'never';
|
|
159
164
|
interface GatewaySshConfig {
|
|
160
165
|
readonly secretEnv: GatewaySshSecretEnvMode;
|
|
161
166
|
}
|
|
167
|
+
interface GatewayIngressConfig {
|
|
168
|
+
readonly upstreamHeaderTimeoutMs?: number;
|
|
169
|
+
readonly upstreamResponseTimeoutMs?: number;
|
|
170
|
+
}
|
|
162
171
|
interface GatewayZoneBaseGatewayConfig {
|
|
163
172
|
readonly type: GatewayType;
|
|
164
173
|
readonly memory: string;
|
|
165
174
|
readonly cpus: number;
|
|
166
175
|
readonly port: number;
|
|
176
|
+
readonly ingress?: GatewayIngressConfig;
|
|
167
177
|
readonly config: string;
|
|
168
178
|
readonly stateDir: string;
|
|
179
|
+
readonly runtimeRootfsSize?: string;
|
|
169
180
|
readonly ssh: GatewaySshConfig;
|
|
170
|
-
readonly authProfilesRef?: OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef | undefined;
|
|
181
|
+
readonly authProfilesRef?: ConfigGatewayAuthProfilesRef | OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef | undefined;
|
|
171
182
|
}
|
|
172
183
|
interface OpenClawGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {
|
|
173
184
|
readonly type: 'openclaw';
|
|
174
185
|
readonly zoneFilesDir: string;
|
|
175
|
-
readonly authProfilesByAgent?: Readonly<Record<string, OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef>>;
|
|
186
|
+
readonly authProfilesByAgent?: Readonly<Record<string, ConfigGatewayAuthProfilesRef | OnePasswordGatewayAuthProfilesRef | EnvironmentGatewayAuthProfilesRef>>;
|
|
176
187
|
readonly rawEnvSecrets?: readonly string[];
|
|
177
188
|
}
|
|
178
189
|
interface WorkerGatewayZoneGatewayConfig extends GatewayZoneBaseGatewayConfig {
|
|
@@ -187,7 +198,11 @@ interface EnvironmentSecretSourceConfig {
|
|
|
187
198
|
readonly source: 'environment';
|
|
188
199
|
readonly envVar: string;
|
|
189
200
|
}
|
|
190
|
-
|
|
201
|
+
interface ConfigSecretSourceConfig {
|
|
202
|
+
readonly source: 'config';
|
|
203
|
+
readonly value: string;
|
|
204
|
+
}
|
|
205
|
+
type SecretSourceConfig = OnePasswordSecretSourceConfig | EnvironmentSecretSourceConfig | ConfigSecretSourceConfig;
|
|
191
206
|
type EnvInjectedGatewaySecretConfig = SecretSourceConfig & {
|
|
192
207
|
readonly audience: 'gateway';
|
|
193
208
|
readonly injection: 'env';
|
|
@@ -283,5 +298,99 @@ type SplitResolvedGatewaySecretsResult = SplitResolvedSecretsResult;
|
|
|
283
298
|
declare function splitResolvedGatewaySecrets(zone: GatewayZoneConfig, resolvedSecrets: Record<string, string>): SplitResolvedGatewaySecretsResult;
|
|
284
299
|
declare function mergeRuntimeGatewaySecrets(baseSecrets: SplitResolvedSecretsResult, options?: MergeRuntimeGatewaySecretsOptions): SplitResolvedSecretsResult;
|
|
285
300
|
//#endregion
|
|
286
|
-
|
|
301
|
+
//#region src/tool-vm-active-use.d.ts
|
|
302
|
+
type ToolVmActiveUseOutcome = 'abandoned' | 'cancelled' | 'completed' | 'failed' | 'timed-out';
|
|
303
|
+
interface ToolVmActiveUseCorrelation {
|
|
304
|
+
readonly agentId?: string;
|
|
305
|
+
readonly sessionId?: string;
|
|
306
|
+
readonly sessionKey?: string;
|
|
307
|
+
readonly toolCallId?: string;
|
|
308
|
+
readonly toolName?: string;
|
|
309
|
+
}
|
|
310
|
+
interface StartToolVmActiveUseRequest {
|
|
311
|
+
readonly correlation?: ToolVmActiveUseCorrelation;
|
|
312
|
+
readonly useId: string;
|
|
313
|
+
}
|
|
314
|
+
interface StartToolVmActiveUseResponse {
|
|
315
|
+
readonly expiresAt: number;
|
|
316
|
+
readonly heartbeatAfterMs: number;
|
|
317
|
+
readonly useId: string;
|
|
318
|
+
}
|
|
319
|
+
interface HeartbeatToolVmActiveUseResponse {
|
|
320
|
+
readonly expiresAt: number;
|
|
321
|
+
readonly heartbeatAfterMs: number;
|
|
322
|
+
}
|
|
323
|
+
interface EndToolVmActiveUseRequest {
|
|
324
|
+
readonly outcome: ToolVmActiveUseOutcome;
|
|
325
|
+
}
|
|
326
|
+
interface ToolVmActiveUseHandle {
|
|
327
|
+
readonly useId: string;
|
|
328
|
+
dispose(outcome?: ToolVmActiveUseOutcome): Promise<void>;
|
|
329
|
+
end(outcome?: ToolVmActiveUseOutcome): Promise<void>;
|
|
330
|
+
}
|
|
331
|
+
interface CreateToolVmActiveUseHandleOptions {
|
|
332
|
+
readonly correlation?: ToolVmActiveUseCorrelation;
|
|
333
|
+
readonly endActiveUse: (useId: string, request: EndToolVmActiveUseRequest) => Promise<void>;
|
|
334
|
+
readonly heartbeatActiveUse: (useId: string) => Promise<HeartbeatToolVmActiveUseResponse>;
|
|
335
|
+
readonly isEndErrorTolerable?: (error: unknown) => boolean;
|
|
336
|
+
readonly logEndFailure?: (error: unknown) => void;
|
|
337
|
+
readonly logHeartbeatFailure?: (error: unknown) => void;
|
|
338
|
+
readonly maxHeartbeatDurationMs?: number;
|
|
339
|
+
readonly nowImpl?: () => number;
|
|
340
|
+
readonly startActiveUse: (request: StartToolVmActiveUseRequest) => Promise<StartToolVmActiveUseResponse>;
|
|
341
|
+
readonly setTimeoutImpl?: typeof setTimeout;
|
|
342
|
+
readonly clearTimeoutImpl?: typeof clearTimeout;
|
|
343
|
+
}
|
|
344
|
+
declare function createToolVmActiveUseId(): string;
|
|
345
|
+
declare function isToolVmActiveUseId(value: string): boolean;
|
|
346
|
+
declare function createToolVmActiveUseHandle(options: CreateToolVmActiveUseHandleOptions): Promise<ToolVmActiveUseHandle>;
|
|
347
|
+
//#endregion
|
|
348
|
+
//#region src/vm-capability-lease.d.ts
|
|
349
|
+
/**
|
|
350
|
+
* Small host-issued capability envelope shared by VM-backed transports. The
|
|
351
|
+
* transport tag keeps SSH Tool VM leases distinct from future host-side
|
|
352
|
+
* Gondolin RPC or bridge capabilities without inventing a transport object.
|
|
353
|
+
*/
|
|
354
|
+
interface VmCapabilityLease<TTransport extends string> {
|
|
355
|
+
readonly leaseId: string;
|
|
356
|
+
readonly transport: TTransport;
|
|
357
|
+
}
|
|
358
|
+
interface VmSshEndpoint {
|
|
359
|
+
readonly host: string;
|
|
360
|
+
readonly identityPem: string;
|
|
361
|
+
readonly knownHostsLine: string;
|
|
362
|
+
readonly port: number;
|
|
363
|
+
readonly user: string;
|
|
364
|
+
}
|
|
365
|
+
interface VmSshPublicEndpoint {
|
|
366
|
+
readonly host: string;
|
|
367
|
+
readonly port: number;
|
|
368
|
+
readonly user: string;
|
|
369
|
+
}
|
|
370
|
+
interface VmSshLease<TTransport extends string> extends VmCapabilityLease<TTransport> {
|
|
371
|
+
readonly ssh: VmSshEndpoint;
|
|
372
|
+
}
|
|
373
|
+
declare function isVmCapabilityLease<TTransport extends string>(value: unknown, transport: TTransport): value is VmCapabilityLease<TTransport>;
|
|
374
|
+
declare function isVmSshEndpoint(value: unknown): value is VmSshEndpoint;
|
|
375
|
+
declare function isVmSshPublicEndpoint(value: unknown): value is VmSshPublicEndpoint;
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/tool-vm-lease.d.ts
|
|
378
|
+
interface ToolVmSshLease extends VmSshLease<'ssh-sandbox'> {
|
|
379
|
+
readonly tcpSlot: number;
|
|
380
|
+
readonly workdir: string;
|
|
381
|
+
}
|
|
382
|
+
interface ToolVmLeasePeek extends VmCapabilityLease<'ssh-sandbox'> {
|
|
383
|
+
readonly createdAt: number;
|
|
384
|
+
readonly lastUsedAt: number;
|
|
385
|
+
readonly profileId: string;
|
|
386
|
+
readonly scopeKey: string;
|
|
387
|
+
readonly ssh: VmSshPublicEndpoint;
|
|
388
|
+
readonly tcpSlot: number;
|
|
389
|
+
readonly workdir: string;
|
|
390
|
+
readonly zoneId: string;
|
|
391
|
+
}
|
|
392
|
+
declare function isToolVmSshLease(value: unknown): value is ToolVmSshLease;
|
|
393
|
+
declare function isToolVmLeasePeek(value: unknown): value is ToolVmLeasePeek;
|
|
394
|
+
//#endregion
|
|
395
|
+
export { type BuildGatewayVmSpecOptions, type CreateToolVmActiveUseHandleOptions, type EgressHostConfig, type EndToolVmActiveUseRequest, type EnvInjectedGatewaySecretConfig, FORCE_IPV4_EGRESS_NODE_OPTIONS, type GatewayAuthConfig, type GatewayHealthCheck, type GatewayIngressConfig, 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
396
|
//# 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;;;;;;;
|
|
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.73",
|
|
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/gondolin-adapter": "0.0.
|
|
32
|
+
"uuid": "^11.1.1",
|
|
33
|
+
"@agent-vm/gondolin-adapter": "0.0.73",
|
|
34
|
+
"@agent-vm/secret-management": "0.0.73"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "tsdown",
|