@dharma-ai-labs/agent-fabric 0.2.209 → 0.2.211
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/bin.js +2 -2
- package/dist/bin.js.map +1 -1
- package/dist/bootstrapHostScope.test.js +1 -1
- package/dist/bootstrapHostScope.test.js.map +1 -1
- package/dist/bootstrapProcessCaller.test.js +1 -0
- package/dist/bootstrapProcessCaller.test.js.map +1 -1
- package/dist/bootstrapVaultScope.test.js +25 -1
- package/dist/bootstrapVaultScope.test.js.map +1 -1
- package/dist/codexBoundSession.d.ts +59 -0
- package/dist/codexBoundSession.d.ts.map +1 -1
- package/dist/codexBoundSession.js +140 -1
- package/dist/codexBoundSession.js.map +1 -1
- package/dist/codexInboxSession.d.ts +1 -1
- package/dist/codexInboxSession.d.ts.map +1 -1
- package/dist/codexRecoveryController.test.d.ts +2 -0
- package/dist/codexRecoveryController.test.d.ts.map +1 -0
- package/dist/codexRecoveryController.test.js +295 -0
- package/dist/codexRecoveryController.test.js.map +1 -0
- package/dist/codexScopedDispatch.test.js +2 -1
- package/dist/codexScopedDispatch.test.js.map +1 -1
- package/dist/codexSetupChildProvider.test.js +20 -0
- package/dist/codexSetupChildProvider.test.js.map +1 -1
- package/dist/codexSetupNativeHost.test.js +2 -1
- package/dist/codexSetupNativeHost.test.js.map +1 -1
- package/dist/codexSetupSessionCaller.test.js +1 -0
- package/dist/codexSetupSessionCaller.test.js.map +1 -1
- package/dist/codexSigningRecoveryNativeHost.d.ts +50 -0
- package/dist/codexSigningRecoveryNativeHost.d.ts.map +1 -0
- package/dist/codexSigningRecoveryNativeHost.js +186 -0
- package/dist/codexSigningRecoveryNativeHost.js.map +1 -0
- package/dist/codexSigningRecoveryNativeHost.test.d.ts +2 -0
- package/dist/codexSigningRecoveryNativeHost.test.d.ts.map +1 -0
- package/dist/codexSigningRecoveryNativeHost.test.js +475 -0
- package/dist/codexSigningRecoveryNativeHost.test.js.map +1 -0
- package/dist/codexSigningRecoveryTool.d.ts +25 -0
- package/dist/codexSigningRecoveryTool.d.ts.map +1 -0
- package/dist/codexSigningRecoveryTool.js +24 -0
- package/dist/codexSigningRecoveryTool.js.map +1 -0
- package/dist/containerRelayLifecycle.d.ts +2 -1
- package/dist/containerRelayLifecycle.d.ts.map +1 -1
- package/dist/containerRelayLifecycle.js +12 -0
- package/dist/containerRelayLifecycle.js.map +1 -1
- package/dist/containerRelayLifecycle.test.js +38 -6
- package/dist/containerRelayLifecycle.test.js.map +1 -1
- package/dist/containerRelayRuntimeTrust.test.js +10 -0
- package/dist/containerRelayRuntimeTrust.test.js.map +1 -1
- package/dist/cooperativeInboxSession.d.ts +1 -1
- package/dist/demoPackage.d.ts +1 -1
- package/dist/demoWatchControl.d.ts +6 -6
- package/dist/deviceSigningMaintenanceController.d.ts +35 -0
- package/dist/deviceSigningMaintenanceController.d.ts.map +1 -0
- package/dist/deviceSigningMaintenanceController.js +197 -0
- package/dist/deviceSigningMaintenanceController.js.map +1 -0
- package/dist/deviceSigningMaintenanceController.test.d.ts +2 -0
- package/dist/deviceSigningMaintenanceController.test.d.ts.map +1 -0
- package/dist/deviceSigningMaintenanceController.test.js +67 -0
- package/dist/deviceSigningMaintenanceController.test.js.map +1 -0
- package/dist/deviceSigningMaintenanceFlow.test.d.ts +2 -0
- package/dist/deviceSigningMaintenanceFlow.test.d.ts.map +1 -0
- package/dist/deviceSigningMaintenanceFlow.test.js +196 -0
- package/dist/deviceSigningMaintenanceFlow.test.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +723 -470
- package/dist/index.js.map +1 -1
- package/dist/legacySigningMaintenanceBoundary.d.ts +14 -0
- package/dist/legacySigningMaintenanceBoundary.d.ts.map +1 -0
- package/dist/legacySigningMaintenanceBoundary.js +128 -0
- package/dist/legacySigningMaintenanceBoundary.js.map +1 -0
- package/dist/legacySigningMaintenanceBoundary.test.d.ts +2 -0
- package/dist/legacySigningMaintenanceBoundary.test.d.ts.map +1 -0
- package/dist/legacySigningMaintenanceBoundary.test.js +109 -0
- package/dist/legacySigningMaintenanceBoundary.test.js.map +1 -0
- package/dist/maintenanceControlCaller.test.d.ts +2 -0
- package/dist/maintenanceControlCaller.test.d.ts.map +1 -0
- package/dist/maintenanceControlCaller.test.js +119 -0
- package/dist/maintenanceControlCaller.test.js.map +1 -0
- package/dist/namedCodexThread.d.ts.map +1 -1
- package/dist/namedCodexThread.js +3 -1
- package/dist/namedCodexThread.js.map +1 -1
- package/dist/namedCodexThread.test.js +17 -1
- package/dist/namedCodexThread.test.js.map +1 -1
- package/dist/namedSessionMaintenance.d.ts +1 -1
- package/dist/namedSessionStartupFence.test.d.ts +2 -0
- package/dist/namedSessionStartupFence.test.d.ts.map +1 -0
- package/dist/namedSessionStartupFence.test.js +81 -0
- package/dist/namedSessionStartupFence.test.js.map +1 -0
- package/dist/namedSessionStoppedLock.d.ts +34 -0
- package/dist/namedSessionStoppedLock.d.ts.map +1 -0
- package/dist/namedSessionStoppedLock.js +108 -0
- package/dist/namedSessionStoppedLock.js.map +1 -0
- package/dist/namedSessionStoppedLock.test.d.ts +2 -0
- package/dist/namedSessionStoppedLock.test.d.ts.map +1 -0
- package/dist/namedSessionStoppedLock.test.js +104 -0
- package/dist/namedSessionStoppedLock.test.js.map +1 -0
- package/dist/providerSessionReplyRecovery.d.ts +1 -1
- package/dist/relayAutostart.d.ts +3 -0
- package/dist/relayAutostart.d.ts.map +1 -1
- package/dist/relayAutostart.js +45 -6
- package/dist/relayAutostart.js.map +1 -1
- package/dist/relayAutostart.test.js +49 -1
- package/dist/relayAutostart.test.js.map +1 -1
- package/dist/relayRuntimeUpgrade.d.ts +2 -1
- package/dist/relayRuntimeUpgrade.d.ts.map +1 -1
- package/dist/relayRuntimeUpgrade.js +3 -3
- package/dist/relayRuntimeUpgrade.js.map +1 -1
- package/dist/relayRuntimeUpgradeCaller.test.js +76 -0
- package/dist/relayRuntimeUpgradeCaller.test.js.map +1 -1
- package/dist/relaySigningMaintenanceUpgrade.d.ts +44 -0
- package/dist/relaySigningMaintenanceUpgrade.d.ts.map +1 -0
- package/dist/relaySigningMaintenanceUpgrade.js +249 -0
- package/dist/relaySigningMaintenanceUpgrade.js.map +1 -0
- package/dist/relaySigningMaintenanceUpgrade.test.d.ts +2 -0
- package/dist/relaySigningMaintenanceUpgrade.test.d.ts.map +1 -0
- package/dist/relaySigningMaintenanceUpgrade.test.js +230 -0
- package/dist/relaySigningMaintenanceUpgrade.test.js.map +1 -0
- package/dist/schemas/codex-signing-recovery-native-progress.schema.json +16 -0
- package/dist/schemas/device-enrollment-recovery-journal.schema.json +20 -0
- package/dist/schemas/device-signing-maintenance-challenge.schema.json +185 -0
- package/dist/schemas/device-signing-maintenance-completion.schema.json +98 -0
- package/dist/schemas/device-signing-maintenance-context-request.schema.json +68 -0
- package/dist/schemas/device-signing-maintenance-context.schema.json +137 -0
- package/dist/schemas/device-signing-maintenance-control.schema.json +12 -0
- package/dist/schemas/device-signing-maintenance-controller-progress.schema.json +26 -0
- package/dist/schemas/device-signing-maintenance-delivery-request.schema.json +45 -0
- package/dist/schemas/device-signing-maintenance-host-progress.schema.json +121 -0
- package/dist/schemas/device-signing-maintenance-plan.schema.json +136 -0
- package/dist/schemas/device-signing-maintenance-preparation.schema.json +56 -0
- package/dist/schemas/device-signing-recovery-candidate.schema.json +28 -0
- package/dist/schemas/device-signing-recovery-challenge.schema.json +52 -0
- package/dist/schemas/device-signing-recovery-completion.schema.json +23 -0
- package/dist/schemas/device-signing-recovery-delivery-request.schema.json +16 -0
- package/dist/schemas/device-signing-recovery-delivery.schema.json +22 -0
- package/dist/schemas/device-signing-recovery-host-progress.schema.json +28 -0
- package/dist/schemas/device-signing-recovery-offer-progress.schema.json +32 -0
- package/dist/schemas/device-signing-recovery-offer-read-request.schema.json +16 -0
- package/dist/schemas/device-signing-recovery-offer-registration-receipt.schema.json +16 -0
- package/dist/schemas/device-signing-recovery-offer-registration-request.schema.json +18 -0
- package/dist/schemas/device-signing-recovery-offer-response.schema.json +43 -0
- package/dist/schemas/device-signing-recovery-plan.schema.json +40 -0
- package/dist/schemas/device-signing-recovery-preparation.schema.json +23 -0
- package/dist/schemas/local-signing-maintenance-upgrade-journal.schema.json +34 -0
- package/dist/schemas/local-signing-maintenance-upgrade.schema.json +33 -0
- package/dist/schemas/provider-session-recovery-declaration.schema.json +21 -0
- package/dist/signingMaintenanceCohort.test.d.ts +2 -0
- package/dist/signingMaintenanceCohort.test.d.ts.map +1 -0
- package/dist/signingMaintenanceCohort.test.js +55 -0
- package/dist/signingMaintenanceCohort.test.js.map +1 -0
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +4 -2
- package/dist/usage.js.map +1 -1
- package/dist/wslRelayHost.d.ts +2 -0
- package/dist/wslRelayHost.d.ts.map +1 -1
- package/dist/wslRelayHost.js +35 -0
- package/dist/wslRelayHost.js.map +1 -1
- package/dist/wslRelayHost.test.js +81 -4
- package/dist/wslRelayHost.test.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { compileFunction } from 'node:vm';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import ts from 'typescript';
|
|
7
|
+
async function caller(overrides = {}) {
|
|
8
|
+
const source = await readFile(new URL('../src/index.ts', import.meta.url), 'utf8');
|
|
9
|
+
const ast = ts.createSourceFile('index.ts', source, ts.ScriptTarget.Latest, true);
|
|
10
|
+
const node = ast.statements.find(value => ts.isFunctionDeclaration(value) && value.name?.text === 'namedSessionCommand');
|
|
11
|
+
const compiled = ts.transpileModule(node.getText(ast), { compilerOptions: { target: ts.ScriptTarget.ES2023, module: ts.ModuleKind.CommonJS } });
|
|
12
|
+
const calls = [], identity = { organizationId: 'org_fixture', deviceId: 'device', workspaceId: 'workspace', repositoryBindingId: 'binding', endpointId: 'endpoint' };
|
|
13
|
+
let held = false, enabled = false;
|
|
14
|
+
const deps = { process: { platform: 'linux', execPath: '/fixture/node', env: {}, once: () => { }, removeListener: () => { } },
|
|
15
|
+
namedSessionReadinessDiagnosticRequested: () => false, currentBootstrapHostScope: () => undefined,
|
|
16
|
+
currentAcceptedSetupSessionScope: () => undefined, currentNamedSessionChildOwner: () => undefined,
|
|
17
|
+
dharmaHome: () => '/fixture/home', required: (flags, name) => flags.get(name), resolve,
|
|
18
|
+
configPath: () => '/fixture/home/device.json',
|
|
19
|
+
namedSessionPaths: () => ({ root: '/fixture/home/sessions/new-name' }),
|
|
20
|
+
acquireNamedSessionStartupAdmission: async () => { held = true; calls.push('acquire'); return async () => { assert.equal(held, true); held = false; calls.push('release'); }; },
|
|
21
|
+
registry: async () => [{ path: '/fixture/repo', ...identity }], readDeviceConfig: async () => identity,
|
|
22
|
+
assertBootstrapHostSource: async () => { }, repositoryRoleScope: () => identity,
|
|
23
|
+
readNamedSession: async () => ({ identity, enabled: false }), verifyNamedSessionVisibleSkill: () => { },
|
|
24
|
+
verifyAgentFabricSkillInstallation: async () => ({}), repositorySharedReady: async () => ({}),
|
|
25
|
+
namedSessionRequest: async () => { throw Error('stopped'); },
|
|
26
|
+
saveNamedSession: async () => { assert.equal(held, true); enabled = true; calls.push('enable'); },
|
|
27
|
+
fileURLToPath: () => '/fixture/index.js',
|
|
28
|
+
spawn: () => { assert.equal(held, false, 'parent must release before child can acquire'); calls.push('spawn'); return { on: () => { }, unref: () => { } }; },
|
|
29
|
+
observeNamedSessionStartupChild: () => ({ readFailure: () => null, dispose: () => calls.push('dispose') }),
|
|
30
|
+
waitForNamedSessionStartup: async () => { assert.equal(held, false); calls.push('wait'); return { ok: true }; },
|
|
31
|
+
mkdir: async () => { assert.equal(held, true); calls.push('mkdir'); },
|
|
32
|
+
openBootstrapVault: async () => { assert.equal(held, true); calls.push('vault'); throw Error('FIXTURE_VAULT_STOP'); },
|
|
33
|
+
namedSessionStartupPhaseError: (_phase, error) => error, ...overrides };
|
|
34
|
+
const run = compileFunction(compiled.outputText.replaceAll('import.meta.url', '"file:///fixture/index.js"') + '\nreturn namedSessionCommand;', ['exports', ...Object.keys(deps)])({}, ...Object.values(deps));
|
|
35
|
+
return { calls, run, enabled: () => enabled, held: () => held, flags: new Map([['name', 'new-name'], ['workspace-id', 'workspace'], ['apply', true]]) };
|
|
36
|
+
}
|
|
37
|
+
test('actual start and direct serve refuse maintenance contention before registration, spawn or vault', async () => {
|
|
38
|
+
for (const action of ['start', 'serve']) {
|
|
39
|
+
const f = await caller({ acquireNamedSessionStartupAdmission: async () => { throw Error('STARTUP_FENCED'); },
|
|
40
|
+
registry: async () => { throw Error('REGISTRY_REACHED_BEFORE_FENCE'); } });
|
|
41
|
+
await assert.rejects(f.run(action, f.flags), /STARTUP_FENCED/);
|
|
42
|
+
assert.deepEqual(f.calls, []);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
test('actual start serializes disabled enablement and releases admission before child fork and wait', async () => {
|
|
46
|
+
const f = await caller();
|
|
47
|
+
assert.deepEqual(await f.run('start', f.flags), { ok: true });
|
|
48
|
+
assert.equal(f.enabled(), true);
|
|
49
|
+
assert.equal(f.held(), false);
|
|
50
|
+
assert.deepEqual(f.calls, ['acquire', 'enable', 'release', 'spawn', 'wait', 'dispose']);
|
|
51
|
+
});
|
|
52
|
+
test('direct serve holds startup admission before private vault access and releases on failure', async () => {
|
|
53
|
+
const f = await caller();
|
|
54
|
+
await assert.rejects(f.run('serve', f.flags), /FIXTURE_VAULT_STOP/);
|
|
55
|
+
assert.deepEqual(f.calls, ['acquire', 'mkdir', 'vault', 'release']);
|
|
56
|
+
assert.equal(f.held(), false);
|
|
57
|
+
});
|
|
58
|
+
test('early scope failure releases startup admission without starting or touching the vault', async () => {
|
|
59
|
+
const f = await caller({ registry: async () => [] });
|
|
60
|
+
await assert.rejects(f.run('start', f.flags), /named_session_scope_mismatch/);
|
|
61
|
+
assert.deepEqual(f.calls, ['acquire', 'release']);
|
|
62
|
+
assert.equal(f.held(), false);
|
|
63
|
+
});
|
|
64
|
+
test('actual direct serve hands home-wide admission to its service lock before provider startup', async () => {
|
|
65
|
+
const effects = [];
|
|
66
|
+
const f = await caller({ openBootstrapVault: async () => ({ close: async () => { effects.push('vault-close'); } }),
|
|
67
|
+
acquirePidLock: async () => { effects.push('service-lock'); return async () => { effects.push('service-release'); }; },
|
|
68
|
+
assertNamedSessionStartupRegistration: () => { effects.push('registration-recheck'); },
|
|
69
|
+
AgentFabricClient: { open: async () => { assert.equal(f.held(), false); effects.push('provider-boundary'); throw Error('FIXTURE_PROVIDER_STOP'); } },
|
|
70
|
+
namedSessionStartupPhaseError: (_phase, error) => error });
|
|
71
|
+
await assert.rejects(f.run('serve', f.flags), /FIXTURE_PROVIDER_STOP/);
|
|
72
|
+
assert.deepEqual(f.calls, ['acquire', 'mkdir', 'release']);
|
|
73
|
+
assert.deepEqual(effects, ['service-lock', 'registration-recheck', 'provider-boundary', 'vault-close', 'service-release']);
|
|
74
|
+
});
|
|
75
|
+
test('a new-name start releases admission before spawn and direct child admission owns the next phase', async () => {
|
|
76
|
+
const f = await caller({ readNamedSession: async () => null });
|
|
77
|
+
assert.deepEqual(await f.run('start', f.flags), { ok: true });
|
|
78
|
+
assert.equal(f.enabled(), false);
|
|
79
|
+
assert.deepEqual(f.calls, ['acquire', 'release', 'spawn', 'wait', 'dispose']);
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=namedSessionStartupFence.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedSessionStartupFence.test.js","sourceRoot":"","sources":["../src/namedSessionStartupFence.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { NamedSessionRegistration } from './namedSessionService.js';
|
|
2
|
+
interface Input {
|
|
3
|
+
home: string;
|
|
4
|
+
name: string;
|
|
5
|
+
registration: NamedSessionRegistration;
|
|
6
|
+
registrationSha256: string;
|
|
7
|
+
lockSha256: string;
|
|
8
|
+
apply: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface Dependencies {
|
|
11
|
+
assertTopology(): Promise<void>;
|
|
12
|
+
processState(pid: number): Promise<'stopped' | 'running' | 'unknown'>;
|
|
13
|
+
}
|
|
14
|
+
/** Called only under the owning CLI's home-wide startup mutation admission. */
|
|
15
|
+
export declare function reconcileStoppedNamedSessionLock(input: Input, deps: Dependencies): Promise<{
|
|
16
|
+
state: string;
|
|
17
|
+
ok: boolean;
|
|
18
|
+
planned: boolean;
|
|
19
|
+
name: string;
|
|
20
|
+
workspaceId: string;
|
|
21
|
+
bindingId: string;
|
|
22
|
+
registrationSha256: string;
|
|
23
|
+
lockSha256: string;
|
|
24
|
+
archive: string;
|
|
25
|
+
previousPid: number;
|
|
26
|
+
registrationChanged: boolean;
|
|
27
|
+
budgetChanged: boolean;
|
|
28
|
+
providerStarted: boolean;
|
|
29
|
+
protectedStoreRead: boolean;
|
|
30
|
+
ready: boolean;
|
|
31
|
+
nativeContinuationAuthorized: boolean;
|
|
32
|
+
}>;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=namedSessionStoppedLock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedSessionStoppedLock.d.ts","sourceRoot":"","sources":["../src/namedSessionStoppedLock.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAC;AAIvE,UAAU,KAAK;IACb,IAAI,EAAC,MAAM,CAAC;IAAC,IAAI,EAAC,MAAM,CAAC;IAAC,YAAY,EAAC,wBAAwB,CAAC;IAChE,kBAAkB,EAAC,MAAM,CAAC;IAAC,UAAU,EAAC,MAAM,CAAC;IAAC,KAAK,EAAC,OAAO,CAAC;CAC7D;AACD,UAAU,YAAY;IACpB,cAAc,IAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,YAAY,CAAC,GAAG,EAAC,MAAM,GAAE,OAAO,CAAC,SAAS,GAAC,SAAS,GAAC,SAAS,CAAC,CAAC;CACjE;AAYD,+EAA+E;AAC/E,wBAAsB,gCAAgC,CAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,YAAY;;;;;;;;;;;;;;;;;GA+CnF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { link, lstat, open, realpath, unlink } from 'node:fs/promises';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
const digest = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
6
|
+
const unavailable = () => new Error('named_session_stopped_lock_unconfirmed');
|
|
7
|
+
async function privateFile(path, uid, limit) {
|
|
8
|
+
const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
9
|
+
try {
|
|
10
|
+
const stat = await file.stat({ bigint: true });
|
|
11
|
+
if (!stat.isFile() || Number(stat.uid) !== uid || (Number(stat.mode) & 0o077) !== 0 || stat.size > BigInt(limit))
|
|
12
|
+
throw unavailable();
|
|
13
|
+
const bytes = await file.readFile();
|
|
14
|
+
if (bytes.length > limit)
|
|
15
|
+
throw unavailable();
|
|
16
|
+
return { bytes, dev: stat.dev, ino: stat.ino };
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
await file.close();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Called only under the owning CLI's home-wide startup mutation admission. */
|
|
23
|
+
export async function reconcileStoppedNamedSessionLock(input, deps) {
|
|
24
|
+
const uid = process.getuid?.() ?? -1;
|
|
25
|
+
if (process.platform !== 'linux' || uid <= 0 || resolve(input.home) !== input.home
|
|
26
|
+
|| !/^[a-z][a-z0-9-]{0,47}$/.test(input.name) || input.registration.name !== input.name
|
|
27
|
+
|| input.registration.enabled || input.registration.maintenanceFence
|
|
28
|
+
|| ![input.registrationSha256, input.lockSha256].every(v => /^[a-f0-9]{64}$/.test(v)))
|
|
29
|
+
throw unavailable();
|
|
30
|
+
const root = join(input.home, 'sessions', input.name), registrationPath = join(root, 'registration.json'), lockPath = join(root, 'service.lock');
|
|
31
|
+
for (const path of [input.home, join(input.home, 'sessions'), root]) {
|
|
32
|
+
const stat = await lstat(path);
|
|
33
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || stat.uid !== uid || (stat.mode & 0o077) !== 0 || await realpath(path) !== path)
|
|
34
|
+
throw unavailable();
|
|
35
|
+
}
|
|
36
|
+
const verify = async () => {
|
|
37
|
+
await deps.assertTopology();
|
|
38
|
+
const registration = await privateFile(registrationPath, uid, 4096);
|
|
39
|
+
if (digest(registration.bytes) !== input.registrationSha256
|
|
40
|
+
|| JSON.stringify(JSON.parse(registration.bytes.toString('utf8'))) !== JSON.stringify(input.registration))
|
|
41
|
+
throw unavailable();
|
|
42
|
+
const lock = await privateFile(lockPath, uid, 64), text = lock.bytes.toString('utf8');
|
|
43
|
+
if (digest(lock.bytes) !== input.lockSha256 || !/^([1-9][0-9]*)\n?$/.test(text))
|
|
44
|
+
throw unavailable();
|
|
45
|
+
const pid = Number(text.trim());
|
|
46
|
+
if (!Number.isSafeInteger(pid) || pid <= 1 || await deps.processState(pid) !== 'stopped')
|
|
47
|
+
throw unavailable();
|
|
48
|
+
return { ...lock, pid };
|
|
49
|
+
};
|
|
50
|
+
const before = await verify(), archiveName = 'service.lock.stopped.' + input.lockSha256;
|
|
51
|
+
const receipt = { ok: true, planned: !input.apply, name: input.name, workspaceId: input.registration.identity.workspaceId,
|
|
52
|
+
bindingId: input.registration.bindingId, registrationSha256: input.registrationSha256, lockSha256: input.lockSha256,
|
|
53
|
+
archive: archiveName, previousPid: before.pid, registrationChanged: false, budgetChanged: false, providerStarted: false, protectedStoreRead: false,
|
|
54
|
+
ready: false, nativeContinuationAuthorized: false };
|
|
55
|
+
if (!input.apply)
|
|
56
|
+
return { ...receipt, state: 'stopped_lock_reconciliation_planned' };
|
|
57
|
+
const current = await verify();
|
|
58
|
+
if (current.dev !== before.dev || current.ino !== before.ino)
|
|
59
|
+
throw unavailable();
|
|
60
|
+
const archive = join(root, archiveName);
|
|
61
|
+
try {
|
|
62
|
+
await link(lockPath, archive);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error.code !== 'EEXIST')
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
const retained = await privateFile(archive, uid, 64);
|
|
69
|
+
if (retained.dev !== before.dev || retained.ino !== before.ino || digest(retained.bytes) !== input.lockSha256)
|
|
70
|
+
throw unavailable();
|
|
71
|
+
const archiveFile = await open(archive, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
72
|
+
try {
|
|
73
|
+
await archiveFile.sync();
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await archiveFile.close();
|
|
77
|
+
}
|
|
78
|
+
const directory = await open(root, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
79
|
+
try {
|
|
80
|
+
await directory.sync();
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
await directory.close();
|
|
84
|
+
}
|
|
85
|
+
const final = await verify();
|
|
86
|
+
if (final.dev !== before.dev || final.ino !== before.ino)
|
|
87
|
+
throw unavailable();
|
|
88
|
+
await unlink(lockPath);
|
|
89
|
+
const completedDirectory = await open(root, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
90
|
+
try {
|
|
91
|
+
await completedDirectory.sync();
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
await completedDirectory.close();
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
await lstat(lockPath);
|
|
98
|
+
throw unavailable();
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error.code !== 'ENOENT')
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
if (digest((await privateFile(registrationPath, uid, 4096)).bytes) !== input.registrationSha256)
|
|
105
|
+
throw unavailable();
|
|
106
|
+
return { ...receipt, state: 'stopped_lock_reconciled', planned: false };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=namedSessionStoppedLock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedSessionStoppedLock.js","sourceRoot":"","sources":["../src/namedSessionStoppedLock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedSessionStoppedLock.test.d.ts","sourceRoot":"","sources":["../src/namedSessionStoppedLock.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { chmod, lstat, mkdir, mkdtemp, readFile, realpath, rename, symlink, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import test from 'node:test';
|
|
7
|
+
import { reconcileStoppedNamedSessionLock } from './namedSessionStoppedLock.js';
|
|
8
|
+
const linux = { skip: process.platform !== 'linux' }, sha = (v) => createHash('sha256').update(v).digest('hex');
|
|
9
|
+
async function fixture() {
|
|
10
|
+
const home = await realpath(await mkdtemp(join(tmpdir(), 'dharma-stopped-lock-')));
|
|
11
|
+
await chmod(home, 0o700);
|
|
12
|
+
const name = 'codex-fixture', root = join(home, 'sessions', name);
|
|
13
|
+
await mkdir(root, { recursive: true, mode: 0o700 });
|
|
14
|
+
await chmod(join(home, 'sessions'), 0o700);
|
|
15
|
+
const registration = { schema: 'dharma.named-session/v1', name, bindingId: '11111111-1111-4111-8111-111111111111', enabled: false,
|
|
16
|
+
maximumCostCents: 1000, maximumTurnCostCents: 25, identity: { organizationId: 'org_fixture', provider: 'codex',
|
|
17
|
+
repositoryBindingId: '22222222-2222-4222-8222-222222222222', workspaceId: '33333333-3333-4333-8333-333333333333',
|
|
18
|
+
endpointId: '44444444-4444-4444-8444-444444444444', membershipId: '55555555-5555-4555-8555-555555555555', deviceId: '66666666-6666-4666-8666-666666666666' } };
|
|
19
|
+
await writeFile(join(root, 'registration.json'), JSON.stringify(registration) + '\n', { mode: 0o600 });
|
|
20
|
+
const lock = join(root, 'service.lock');
|
|
21
|
+
await writeFile(lock, '987654\n', { mode: 0o600 });
|
|
22
|
+
const input = { home, name, registration, registrationSha256: sha(await readFile(join(root, 'registration.json'))), lockSha256: sha(await readFile(lock)), apply: false };
|
|
23
|
+
const deps = { assertTopology: async () => { }, processState: async () => 'stopped' };
|
|
24
|
+
return { home, root, lock, input, deps };
|
|
25
|
+
}
|
|
26
|
+
test('stopped-lock plan is inert and apply retains the exact original lock inode and registration', linux, async () => {
|
|
27
|
+
const f = await fixture(), before = await lstat(f.lock);
|
|
28
|
+
const plan = await reconcileStoppedNamedSessionLock(f.input, f.deps);
|
|
29
|
+
assert.equal(plan.state, 'stopped_lock_reconciliation_planned');
|
|
30
|
+
assert.equal((await lstat(f.lock)).ino, before.ino);
|
|
31
|
+
await assert.rejects(lstat(join(f.root, plan.archive)), { code: 'ENOENT' });
|
|
32
|
+
const result = await reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps);
|
|
33
|
+
assert.equal(result.state, 'stopped_lock_reconciled');
|
|
34
|
+
assert.equal((await lstat(join(f.root, result.archive))).ino, before.ino);
|
|
35
|
+
assert.equal(result.registrationChanged, false);
|
|
36
|
+
assert.equal(result.budgetChanged, false);
|
|
37
|
+
assert.equal(result.protectedStoreRead, false);
|
|
38
|
+
await assert.rejects(lstat(f.lock), { code: 'ENOENT' });
|
|
39
|
+
});
|
|
40
|
+
for (const cause of ['enabled', 'wrong-registration', 'wrong-lock', 'running', 'unknown', 'unsafe-parent', 'foreign-topology', 'symlink', 'malformed']) {
|
|
41
|
+
test('stopped-lock reconciliation refuses ' + cause + ' without removing the lock', linux, async () => {
|
|
42
|
+
const f = await fixture();
|
|
43
|
+
if (cause === 'enabled')
|
|
44
|
+
f.input.registration.enabled = true;
|
|
45
|
+
if (cause === 'wrong-registration')
|
|
46
|
+
f.input.registrationSha256 = '0'.repeat(64);
|
|
47
|
+
if (cause === 'wrong-lock')
|
|
48
|
+
f.input.lockSha256 = '0'.repeat(64);
|
|
49
|
+
if (cause === 'running' || cause === 'unknown')
|
|
50
|
+
f.deps.processState = async () => cause;
|
|
51
|
+
if (cause === 'unsafe-parent')
|
|
52
|
+
await chmod(f.root, 0o755);
|
|
53
|
+
if (cause === 'foreign-topology')
|
|
54
|
+
f.deps.assertTopology = async () => { throw Error('foreign controller'); };
|
|
55
|
+
if (cause === 'symlink') {
|
|
56
|
+
await writeFile(join(f.root, 'foreign'), '987654\n', { mode: 0o600 });
|
|
57
|
+
f.input.name = 'linked';
|
|
58
|
+
f.input.registration = { ...f.input.registration, name: 'linked' };
|
|
59
|
+
await symlink(f.root, join(f.home, 'sessions', 'linked'));
|
|
60
|
+
}
|
|
61
|
+
if (cause === 'malformed') {
|
|
62
|
+
await writeFile(f.lock, 'not-a-pid\n');
|
|
63
|
+
f.input.lockSha256 = sha(await readFile(f.lock));
|
|
64
|
+
}
|
|
65
|
+
await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
|
|
66
|
+
assert.equal((await lstat(f.lock)).isFile(), true);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
test('a topology change after archive creation leaves the active lock intact', linux, async () => {
|
|
70
|
+
const f = await fixture();
|
|
71
|
+
let checks = 0;
|
|
72
|
+
f.deps.assertTopology = async () => { if (++checks === 3)
|
|
73
|
+
throw Error('topology changed'); };
|
|
74
|
+
await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
|
|
75
|
+
assert.equal((await lstat(f.lock)).isFile(), true);
|
|
76
|
+
assert.equal(sha(await readFile(join(f.root, 'service.lock.stopped.' + f.input.lockSha256))), f.input.lockSha256);
|
|
77
|
+
});
|
|
78
|
+
test('a symbolic service lock and an existing foreign archive never admit reconciliation', linux, async () => {
|
|
79
|
+
for (const cause of ['symlink', 'archive']) {
|
|
80
|
+
const f = await fixture();
|
|
81
|
+
if (cause === 'symlink') {
|
|
82
|
+
await rename(f.lock, join(f.root, 'original'));
|
|
83
|
+
await symlink(join(f.root, 'original'), f.lock);
|
|
84
|
+
}
|
|
85
|
+
else
|
|
86
|
+
await writeFile(join(f.root, 'service.lock.stopped.' + f.input.lockSha256), 'foreign\n', { mode: 0o600 });
|
|
87
|
+
await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
|
|
88
|
+
assert.equal(Boolean(await lstat(f.lock)), true);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
test('registration replacement or a newly live PID after planning cannot remove the active lock', linux, async () => {
|
|
92
|
+
for (const cause of ['registration', 'pid']) {
|
|
93
|
+
const f = await fixture();
|
|
94
|
+
let n = 0;
|
|
95
|
+
f.deps.assertTopology = async () => { if (++n === 2 && cause === 'registration')
|
|
96
|
+
await writeFile(join(f.root, 'registration.json'), '{}\n'); };
|
|
97
|
+
let pidChecks = 0;
|
|
98
|
+
if (cause === 'pid')
|
|
99
|
+
f.deps.processState = async () => ++pidChecks === 1 ? 'stopped' : 'running';
|
|
100
|
+
await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
|
|
101
|
+
assert.equal((await lstat(f.lock)).isFile(), true);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=namedSessionStoppedLock.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedSessionStoppedLock.test.js","sourceRoot":"","sources":["../src/namedSessionStoppedLock.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ export declare function reconcileProviderSessionReply(input: {
|
|
|
11
11
|
questionId: string;
|
|
12
12
|
taskId: string;
|
|
13
13
|
completionHash: string;
|
|
14
|
-
reasonCode: "
|
|
14
|
+
reasonCode: "delivery_unconfirmed" | "content_or_contract_blocked" | "receipt_invalid";
|
|
15
15
|
dispositionHash?: undefined;
|
|
16
16
|
delivered?: undefined;
|
|
17
17
|
replyReceiptHash?: undefined;
|
package/dist/relayAutostart.d.ts
CHANGED
|
@@ -62,6 +62,8 @@ export declare function enableRelayAutostart(options: RelayAutostartOptions & {
|
|
|
62
62
|
policy: string | null;
|
|
63
63
|
version: string;
|
|
64
64
|
preserveStandardAnchor?: boolean;
|
|
65
|
+
/** Existing Linux registration only; keep its controller paused during a signing-maintenance upgrade. */
|
|
66
|
+
pauseForSigningMaintenance?: boolean;
|
|
65
67
|
}): Promise<RelayAutostartState>;
|
|
66
68
|
export declare function disableRelayAutostart(options: RelayAutostartOptions): Promise<RelayAutostartState>;
|
|
67
69
|
export declare function startRelayAutostart(options: RelayAutostartOptions): Promise<{
|
|
@@ -72,6 +74,7 @@ export declare function startRelayAutostart(options: RelayAutostartOptions): Pro
|
|
|
72
74
|
export declare function inspectOwnedRelayAutostart(options: RelayAutostartOptions, inspection?: {
|
|
73
75
|
allowLegacy?: boolean;
|
|
74
76
|
}): Promise<RelayAutostartRegistration>;
|
|
77
|
+
export declare function assertRelayAutostartPaused(options: RelayAutostartOptions): Promise<void>;
|
|
75
78
|
export declare function stopRelayAutostart(options: RelayAutostartOptions): Promise<{
|
|
76
79
|
state: "stop_requested";
|
|
77
80
|
backend: "container-entrypoint" | "systemd-user" | "windows-task" | "launchd-user";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relayAutostart.d.ts","sourceRoot":"","sources":["../src/relayAutostart.ts"],"names":[],"mappings":"AAMA,OAAO,
|
|
1
|
+
{"version":3,"file":"relayAutostart.d.ts","sourceRoot":"","sources":["../src/relayAutostart.ts"],"names":[],"mappings":"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"}
|
package/dist/relayAutostart.js
CHANGED
|
@@ -4,9 +4,9 @@ import { lstat, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { dirname, isAbsolute, join, posix } from 'node:path';
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
|
-
import { assertContainerStartupOwnership, containerEntrypointAvailable, containerStartupControl, containerStartupState, ownsContainerStartup, writeContainerRegistration, readContainerRegistration } from './containerRelayLifecycle.js';
|
|
7
|
+
import { assertContainerStartupOwnership, containerEntrypointAvailable, containerStartupControl, containerStartupState, ownsContainerStartup, containerStartupPaused, writeContainerRegistration, readContainerRegistration } from './containerRelayLifecycle.js';
|
|
8
8
|
import { currentBootstrapHostScope } from './bootstrapHostScope.js';
|
|
9
|
-
import { assertWslHostPreflight, disableWslRelayHost, enableWslRelayHost, startWslRelayHost, wslRelayHostStatus } from './wslRelayHost.js';
|
|
9
|
+
import { assertWslHostPreflight, assertWslRelayHostPaused, pauseWslRelayHost, disableWslRelayHost, enableWslRelayHost, startWslRelayHost, wslRelayHostStatus } from './wslRelayHost.js';
|
|
10
10
|
const execFileAsync = promisify(execFile);
|
|
11
11
|
const UNIT_NAME = 'dharma-agent-fabric.service';
|
|
12
12
|
const MAC_LABEL = 'io.dharma.agent-fabric.relay';
|
|
@@ -341,6 +341,9 @@ export async function relayAutostartStatus(options) {
|
|
|
341
341
|
}
|
|
342
342
|
export async function enableRelayAutostart(options) {
|
|
343
343
|
const platform = options.platform || process.platform;
|
|
344
|
+
if (options.pauseForSigningMaintenance && (platform !== 'linux' || options.preserveStandardAnchor)) {
|
|
345
|
+
throw new Error('relay_signing_maintenance_startup_scope_invalid');
|
|
346
|
+
}
|
|
344
347
|
if (platform !== 'linux' && platform !== 'win32' && platform !== 'darwin') {
|
|
345
348
|
throw new Error(`Relay autostart is unsupported on ${platform}.`);
|
|
346
349
|
}
|
|
@@ -349,6 +352,8 @@ export async function enableRelayAutostart(options) {
|
|
|
349
352
|
const userHome = options.userHome || homedir();
|
|
350
353
|
const run = options.run || defaultRunner;
|
|
351
354
|
const previous = await readRegistration(options);
|
|
355
|
+
if (options.pauseForSigningMaintenance && !previous)
|
|
356
|
+
throw new Error('relay_signing_maintenance_startup_scope_invalid');
|
|
352
357
|
const backend = platform === 'linux'
|
|
353
358
|
? await containerEntrypointAvailable(options) ? 'container-entrypoint' : 'systemd-user'
|
|
354
359
|
: platform === 'darwin' ? 'launchd-user' : 'windows-task';
|
|
@@ -393,7 +398,7 @@ export async function enableRelayAutostart(options) {
|
|
|
393
398
|
if (previous && !await ownsStartupFile(options, previous))
|
|
394
399
|
throw new Error('autostart_conflict: container startup is not owned.');
|
|
395
400
|
await writeContainerRegistration(options, registration);
|
|
396
|
-
await containerStartupControl(options, registration,
|
|
401
|
+
await containerStartupControl(options, registration, !options.pauseForSigningMaintenance);
|
|
397
402
|
return containerStartupState(options, registration);
|
|
398
403
|
}
|
|
399
404
|
if (platform === 'win32' && !previous) {
|
|
@@ -451,8 +456,11 @@ export async function enableRelayAutostart(options) {
|
|
|
451
456
|
await writeFile(registrationPath(options.home), `${JSON.stringify(registration, null, 2)}\n`, { mode: 0o600 });
|
|
452
457
|
if (platform === 'linux') {
|
|
453
458
|
await run('systemctl', ['--user', 'daemon-reload']);
|
|
454
|
-
await run('systemctl', ['--user', 'enable', UNIT_NAME]);
|
|
455
|
-
|
|
459
|
+
await run('systemctl', ['--user', options.pauseForSigningMaintenance ? 'disable' : 'enable', UNIT_NAME]);
|
|
460
|
+
if (options.pauseForSigningMaintenance)
|
|
461
|
+
await pauseWslRelayHost(options);
|
|
462
|
+
else
|
|
463
|
+
await enableWslRelayHost(options);
|
|
456
464
|
}
|
|
457
465
|
else if (platform === 'darwin') {
|
|
458
466
|
await run('/usr/bin/plutil', ['-lint', destination]);
|
|
@@ -474,7 +482,7 @@ export async function enableRelayAutostart(options) {
|
|
|
474
482
|
await run('powershell.exe', encodedPowerShell(command));
|
|
475
483
|
}
|
|
476
484
|
const status = await relayAutostartStatus(options);
|
|
477
|
-
if (status.state !== 'enabled')
|
|
485
|
+
if (status.state !== (options.pauseForSigningMaintenance ? 'disabled' : 'enabled'))
|
|
478
486
|
throw new Error(`Relay autostart registration was not verified (${status.state}).`);
|
|
479
487
|
return status;
|
|
480
488
|
}
|
|
@@ -561,6 +569,37 @@ export async function inspectOwnedRelayAutostart(options, inspection = {}) {
|
|
|
561
569
|
await macLoaded(options, registration);
|
|
562
570
|
return registration;
|
|
563
571
|
}
|
|
572
|
+
export async function assertRelayAutostartPaused(options) {
|
|
573
|
+
const registration = await inspectOwnedRelayAutostart(options);
|
|
574
|
+
if (registration.backend === 'container-entrypoint') {
|
|
575
|
+
// Only a valid paused control awaiting its new matching heartbeat is polled.
|
|
576
|
+
// Identity, permission, malformed metadata and other failures stop immediately.
|
|
577
|
+
for (let attempt = 0; attempt < 50; attempt++) {
|
|
578
|
+
if (await containerStartupPaused(options, registration))
|
|
579
|
+
return;
|
|
580
|
+
if (attempt < 49)
|
|
581
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
582
|
+
}
|
|
583
|
+
throw Error('relay_startup_pause_unconfirmed');
|
|
584
|
+
}
|
|
585
|
+
if (registration.backend !== 'systemd-user' || (await relayAutostartStatus(options)).state !== 'disabled') {
|
|
586
|
+
throw Error('relay_startup_pause_unconfirmed');
|
|
587
|
+
}
|
|
588
|
+
const run = options.run || defaultRunner;
|
|
589
|
+
let active;
|
|
590
|
+
try {
|
|
591
|
+
active = (await run('systemctl', ['--user', 'is-active', UNIT_NAME])).stdout.trim();
|
|
592
|
+
}
|
|
593
|
+
catch (error) {
|
|
594
|
+
const e = error;
|
|
595
|
+
if (e.code !== 3 || typeof e.stdout !== 'string' || e.stdout.trim() !== 'inactive')
|
|
596
|
+
throw error;
|
|
597
|
+
active = 'inactive';
|
|
598
|
+
}
|
|
599
|
+
if (active !== 'inactive')
|
|
600
|
+
throw Error('relay_startup_pause_unconfirmed');
|
|
601
|
+
await assertWslRelayHostPaused(options);
|
|
602
|
+
}
|
|
564
603
|
export async function stopRelayAutostart(options) {
|
|
565
604
|
const registration = await inspectOwnedRelayAutostart(options);
|
|
566
605
|
const run = options.run || defaultRunner;
|