@byok-sdk/client 0.9.0 → 0.10.0
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/README.md +59 -0
- package/dist/agent-memory/index.d.ts +96 -0
- package/dist/agent-memory/index.js +762 -0
- package/dist/agent-memory/index.js.map +1 -0
- package/dist/bin/byok-agent.js +134 -29
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/daemon/auth-manager.d.ts +8 -0
- package/dist/daemon/create-daemon.d.ts +8 -0
- package/dist/daemon/machine-id.d.ts +25 -0
- package/dist/index.js +133 -28
- package/dist/index.js.map +1 -1
- package/package.json +9 -5
|
@@ -15,6 +15,14 @@ export interface AuthManagerOptions {
|
|
|
15
15
|
/** Internal-only credential custody seam. Product construction uses store.credentials. */
|
|
16
16
|
credentials?: DeviceCredentialStore | InMemoryDeviceCredentialStore;
|
|
17
17
|
deviceName?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Optional resolver for the client-hashed physical machine identity sent
|
|
20
|
+
* with `POST /byok/pair` (protocol §6.1). Resolved once per pair attempt; a
|
|
21
|
+
* resolver that yields `undefined` omits the field entirely rather than
|
|
22
|
+
* sending a placeholder, because the server treats its presence as
|
|
23
|
+
* permission to supersede this machine's prior active device rows.
|
|
24
|
+
*/
|
|
25
|
+
machineId?: () => Promise<string | undefined>;
|
|
18
26
|
/** Called once revocation is detected, so a caller (ConnectionManager) can stop retrying and surface the state instead of looping. */
|
|
19
27
|
onRevoked?: () => void;
|
|
20
28
|
}
|
|
@@ -91,6 +91,14 @@ export interface DaemonConfig {
|
|
|
91
91
|
productId: string;
|
|
92
92
|
serverUrl: string;
|
|
93
93
|
deviceName?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Optional override for the client-hashed physical machine identity sent
|
|
96
|
+
* with `POST /byok/pair` (protocol §6.1). Defaults to `resolveMachineId`
|
|
97
|
+
* over this product id, which probes one OS identifier and hashes it; a
|
|
98
|
+
* host that has its own machine authority can supply it here, and one that
|
|
99
|
+
* wants no supersession at all supplies `async () => undefined`.
|
|
100
|
+
*/
|
|
101
|
+
machineId?: () => Promise<string | undefined>;
|
|
94
102
|
workspaceRoot: string;
|
|
95
103
|
/**
|
|
96
104
|
* Strict Agent execution boundary. The host selects one absolute branded
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DeviceCommandRunner } from './device-credential-store';
|
|
2
|
+
export interface ResolveMachineIdOptions {
|
|
3
|
+
/** Domain separator for the digest — the same machine yields a different value per product. */
|
|
4
|
+
readonly productId: string;
|
|
5
|
+
readonly platform?: NodeJS.Platform;
|
|
6
|
+
/** Injectable process runner, same shape as the credential store's. Tests substitute a double; production gets `runDeviceCommand`. */
|
|
7
|
+
readonly run?: DeviceCommandRunner;
|
|
8
|
+
/** Injectable file read for the Linux probe, for the same reason `run` is injectable. */
|
|
9
|
+
readonly readFile?: (path: string) => Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Upper bound on the whole probe, in milliseconds (default 2000). A probe
|
|
12
|
+
* that never settles — a wedged `ioreg`, a hung registry read, an NFS-backed
|
|
13
|
+
* `/etc/machine-id` — must not stall pairing, because `AuthManager` awaits
|
|
14
|
+
* this value inline before `POST /byok/pair`. On expiry the resolution is
|
|
15
|
+
* `undefined`, the same as every other failure shape.
|
|
16
|
+
*/
|
|
17
|
+
readonly timeoutMs?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The lowercase-hex digest for this machine, or `undefined` when no OS
|
|
21
|
+
* identifier is available. Never throws: every probe failure, every
|
|
22
|
+
* unsupported platform, every empty read, and a probe that exceeds
|
|
23
|
+
* `timeoutMs` all collapse to the same `undefined`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveMachineId(options: ResolveMachineIdOptions): Promise<string | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -6275,13 +6275,15 @@ var AuthManager = class {
|
|
|
6275
6275
|
}
|
|
6276
6276
|
const keyPair = existing ? { privateKey: importPrivateKeyPem(existing.devicePrivateKeyPem), publicKeyBase64Url: existing.devicePublicKey } : generateDeviceKeyPair();
|
|
6277
6277
|
const url = new URL(BYOK_PAIR_PATH, toHttpBase(this.opts.serverUrl));
|
|
6278
|
+
const machineId = await this.opts.machineId?.();
|
|
6278
6279
|
const res = await fetch(url, {
|
|
6279
6280
|
method: "POST",
|
|
6280
6281
|
headers: { "content-type": "application/json" },
|
|
6281
6282
|
body: JSON.stringify({
|
|
6282
6283
|
pairingCode,
|
|
6283
6284
|
deviceName: this.opts.deviceName ?? os4__default.hostname(),
|
|
6284
|
-
devicePublicKey: keyPair.publicKeyBase64Url
|
|
6285
|
+
devicePublicKey: keyPair.publicKeyBase64Url,
|
|
6286
|
+
...machineId === void 0 ? {} : { machineId }
|
|
6285
6287
|
})
|
|
6286
6288
|
});
|
|
6287
6289
|
if (!res.ok) {
|
|
@@ -6590,6 +6592,67 @@ var BlobClient = class {
|
|
|
6590
6592
|
throw lastFailure;
|
|
6591
6593
|
}
|
|
6592
6594
|
};
|
|
6595
|
+
var DEFAULT_TIMEOUT_MS2 = 2e3;
|
|
6596
|
+
var DARWIN_UUID_RE = /"IOPlatformUUID"\s*=\s*"([^"]+)"/u;
|
|
6597
|
+
var WIN32_GUID_RE = /MachineGuid\s+REG_SZ\s+(\S+)/u;
|
|
6598
|
+
var LINUX_MACHINE_ID_PATHS = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
|
|
6599
|
+
async function probeDarwin(run) {
|
|
6600
|
+
const result = await run("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"]);
|
|
6601
|
+
if (result.exitCode !== 0) return void 0;
|
|
6602
|
+
return DARWIN_UUID_RE.exec(result.stdout)?.[1];
|
|
6603
|
+
}
|
|
6604
|
+
async function probeLinux(readFile3) {
|
|
6605
|
+
for (const path38 of LINUX_MACHINE_ID_PATHS) {
|
|
6606
|
+
try {
|
|
6607
|
+
const contents = (await readFile3(path38)).trim();
|
|
6608
|
+
if (contents.length > 0) return contents;
|
|
6609
|
+
} catch {
|
|
6610
|
+
}
|
|
6611
|
+
}
|
|
6612
|
+
return void 0;
|
|
6613
|
+
}
|
|
6614
|
+
async function probeWin32(run) {
|
|
6615
|
+
const result = await run("reg", [
|
|
6616
|
+
"query",
|
|
6617
|
+
"HKLM\\SOFTWARE\\Microsoft\\Cryptography",
|
|
6618
|
+
"/v",
|
|
6619
|
+
"MachineGuid"
|
|
6620
|
+
]);
|
|
6621
|
+
if (result.exitCode !== 0) return void 0;
|
|
6622
|
+
return WIN32_GUID_RE.exec(result.stdout)?.[1];
|
|
6623
|
+
}
|
|
6624
|
+
async function withTimeout(probe, timeoutMs) {
|
|
6625
|
+
let timer;
|
|
6626
|
+
const expiry = new Promise((resolve) => {
|
|
6627
|
+
timer = setTimeout(() => resolve(void 0), timeoutMs);
|
|
6628
|
+
timer.unref?.();
|
|
6629
|
+
});
|
|
6630
|
+
try {
|
|
6631
|
+
return await Promise.race([probe, expiry]);
|
|
6632
|
+
} finally {
|
|
6633
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
async function resolveMachineId(options) {
|
|
6637
|
+
const platform = options.platform ?? process.platform;
|
|
6638
|
+
const run = options.run ?? runDeviceCommand;
|
|
6639
|
+
const readFile3 = options.readFile ?? ((path38) => fs13.readFile(path38, "utf8"));
|
|
6640
|
+
let probe;
|
|
6641
|
+
if (platform === "darwin") probe = probeDarwin(run);
|
|
6642
|
+
else if (platform === "linux") probe = probeLinux(readFile3);
|
|
6643
|
+
else if (platform === "win32") probe = probeWin32(run);
|
|
6644
|
+
if (probe === void 0) return void 0;
|
|
6645
|
+
let raw;
|
|
6646
|
+
try {
|
|
6647
|
+
raw = await withTimeout(probe, options.timeoutMs ?? DEFAULT_TIMEOUT_MS2);
|
|
6648
|
+
} catch {
|
|
6649
|
+
return void 0;
|
|
6650
|
+
}
|
|
6651
|
+
const trimmed = raw?.trim();
|
|
6652
|
+
if (trimmed === void 0 || trimmed.length === 0) return void 0;
|
|
6653
|
+
return createHash("sha256").update(`${options.productId}
|
|
6654
|
+
${trimmed}`, "utf8").digest("hex");
|
|
6655
|
+
}
|
|
6593
6656
|
var PRESENCE_HINTS_CAPABILITY = "presence.hints";
|
|
6594
6657
|
var CapabilityDiscoveryError = class extends Error {
|
|
6595
6658
|
constructor(message, options) {
|
|
@@ -11189,7 +11252,7 @@ async function readPinnedFile(directory, fileName, maxBytes = AGENT_MEMORY_MAX_F
|
|
|
11189
11252
|
});
|
|
11190
11253
|
}
|
|
11191
11254
|
}
|
|
11192
|
-
async function
|
|
11255
|
+
async function readFile2(context, relativePath, maxBytes = AGENT_MEMORY_MAX_FILE_BYTES) {
|
|
11193
11256
|
if (context.filesystem !== void 0) return context.filesystem.read(relativePath, maxBytes);
|
|
11194
11257
|
return withMemoryParent(context, relativePath, (directory, fileName) => readPinnedFile(directory, fileName, maxBytes));
|
|
11195
11258
|
}
|
|
@@ -11357,7 +11420,7 @@ var AgentMemoryService = class {
|
|
|
11357
11420
|
const context = taskContext(this.input);
|
|
11358
11421
|
const relativePath = validateAgentMemoryPath(input.path);
|
|
11359
11422
|
if (input.ifRevision !== void 0 && !revision(input.ifRevision)) throw new AgentMemoryError("ifRevision must be a sha256 content revision");
|
|
11360
|
-
const current = await
|
|
11423
|
+
const current = await readFile2(context, relativePath);
|
|
11361
11424
|
if (!current.exists) throw new AgentMemoryError("memory file does not exist");
|
|
11362
11425
|
if (input.ifRevision !== void 0 && current.revision !== input.ifRevision) throw new AgentMemoryRevisionConflictError(input.ifRevision, current.revision);
|
|
11363
11426
|
const auditWarning = await exclusiveAgentMemoryHome(context.canonicalHome, () => recordAuditWarning(context, "recall", {
|
|
@@ -11444,7 +11507,7 @@ async function captureAgentMemorySnapshot(input) {
|
|
|
11444
11507
|
const files = [];
|
|
11445
11508
|
let totalBytes = 0;
|
|
11446
11509
|
for (const relativePath of paths) {
|
|
11447
|
-
const current = await
|
|
11510
|
+
const current = await readFile2(context, relativePath);
|
|
11448
11511
|
if (!current.exists) {
|
|
11449
11512
|
if (relativePath === "MEMORY.md") throw new AgentMemoryError("MEMORY.md disappeared before snapshot");
|
|
11450
11513
|
continue;
|
|
@@ -13292,8 +13355,49 @@ var TaskRunner = class {
|
|
|
13292
13355
|
if (this.tasks.get(active.taskId) !== active || active.beingTornDown) return;
|
|
13293
13356
|
if (active.messageRequirement !== void 0 && active.messageAccepted !== true) {
|
|
13294
13357
|
active.pendingMessageCompletion = { finalOutput, ...outcome.document === void 0 ? {} : { document: outcome.document } };
|
|
13295
|
-
const
|
|
13296
|
-
|
|
13358
|
+
const outbox = active.messageOutbox;
|
|
13359
|
+
const record = outbox?.get(active.taskId);
|
|
13360
|
+
if (record !== void 0) {
|
|
13361
|
+
this.sendAgentMessageRecord(outbox, record);
|
|
13362
|
+
return;
|
|
13363
|
+
}
|
|
13364
|
+
const body = finalOutput.trim();
|
|
13365
|
+
if (outbox === void 0 || active.agentRef === void 0) {
|
|
13366
|
+
active.pendingMessageCompletion = void 0;
|
|
13367
|
+
await this.fail(active.taskId, "required Agent message lane is unavailable for this task", false);
|
|
13368
|
+
return;
|
|
13369
|
+
}
|
|
13370
|
+
if (body === "") {
|
|
13371
|
+
active.pendingMessageCompletion = void 0;
|
|
13372
|
+
await this.fail(active.taskId, "runtime produced no reply text for the required Agent message", false);
|
|
13373
|
+
return;
|
|
13374
|
+
}
|
|
13375
|
+
try {
|
|
13376
|
+
await outbox.appendDraft({
|
|
13377
|
+
taskId: active.taskId,
|
|
13378
|
+
tenantId: this.deps.tenantId,
|
|
13379
|
+
agentRef: active.agentRef,
|
|
13380
|
+
requirement: active.messageRequirement,
|
|
13381
|
+
contentType: active.messageRequirement.contentType,
|
|
13382
|
+
body,
|
|
13383
|
+
maxPendingEvents: 64,
|
|
13384
|
+
maxPendingBytes: 4 * 1024 * 1024
|
|
13385
|
+
});
|
|
13386
|
+
if (this.tasks.get(active.taskId) !== active || active.beingTornDown) return;
|
|
13387
|
+
const activated = await outbox.activate(active.taskId, active.session.sessionRef);
|
|
13388
|
+
if (this.tasks.get(active.taskId) !== active || active.beingTornDown) return;
|
|
13389
|
+
if (activated === void 0) throw new Error("Agent message draft disappeared before activation");
|
|
13390
|
+
this.sendAgentMessageRecord(outbox, activated);
|
|
13391
|
+
} catch (err) {
|
|
13392
|
+
if (this.tasks.get(active.taskId) !== active || active.beingTornDown) return;
|
|
13393
|
+
const raced = outbox.get(active.taskId);
|
|
13394
|
+
if (raced !== void 0 && raced.sessionRef !== void 0) {
|
|
13395
|
+
this.sendAgentMessageRecord(outbox, raced);
|
|
13396
|
+
return;
|
|
13397
|
+
}
|
|
13398
|
+
active.pendingMessageCompletion = void 0;
|
|
13399
|
+
await this.fail(active.taskId, `failed to deliver the required Agent message: ${errorMessage4(err)}`, false);
|
|
13400
|
+
}
|
|
13297
13401
|
return;
|
|
13298
13402
|
}
|
|
13299
13403
|
await this.publishSuccessfulCompletion(active, finalOutput, outcome.document);
|
|
@@ -16385,6 +16489,7 @@ function buildDaemonWithAdapters(config, adapters, overrides = {}, assertionProb
|
|
|
16385
16489
|
serverUrl: config.serverUrl,
|
|
16386
16490
|
store,
|
|
16387
16491
|
deviceName: config.deviceName,
|
|
16492
|
+
machineId: config.machineId ?? (() => resolveMachineId({ productId: config.productId })),
|
|
16388
16493
|
onRevoked: () => {
|
|
16389
16494
|
connectionState = "revoked";
|
|
16390
16495
|
}
|
|
@@ -17683,7 +17788,7 @@ function connectAndHandshake(endpoint, token, opts) {
|
|
|
17683
17788
|
});
|
|
17684
17789
|
});
|
|
17685
17790
|
}
|
|
17686
|
-
function
|
|
17791
|
+
function withTimeout2(promise, ms, message) {
|
|
17687
17792
|
return new Promise((resolve, reject) => {
|
|
17688
17793
|
const timer = setTimeout(() => reject(new Error(message)), ms);
|
|
17689
17794
|
timer.unref?.();
|
|
@@ -17762,7 +17867,7 @@ function createControlClient(socket, reader, opts) {
|
|
|
17762
17867
|
async request(method, params) {
|
|
17763
17868
|
if (closed) throw new Error("control connection is closed");
|
|
17764
17869
|
const { promise } = send(method, params);
|
|
17765
|
-
const result = await
|
|
17870
|
+
const result = await withTimeout2(promise, opts.requestTimeoutMs ?? 1e4, `control request "${method}" timed out`);
|
|
17766
17871
|
return result;
|
|
17767
17872
|
},
|
|
17768
17873
|
subscribe(method, params, onEvent) {
|
|
@@ -18699,7 +18804,7 @@ ${args.map((a) => ` ${plistString(a)}`).join("\n")}
|
|
|
18699
18804
|
}
|
|
18700
18805
|
function createLaunchdLifecycle(def, deps = {}) {
|
|
18701
18806
|
const run = deps.run ?? defaultRunner;
|
|
18702
|
-
const
|
|
18807
|
+
const fs30 = deps.fs ?? promises;
|
|
18703
18808
|
const homedir = deps.homedir ?? (() => os4__default.homedir());
|
|
18704
18809
|
const getuid = deps.getuid ?? (() => {
|
|
18705
18810
|
if (typeof process.getuid !== "function") {
|
|
@@ -18713,7 +18818,7 @@ function createLaunchdLifecycle(def, deps = {}) {
|
|
|
18713
18818
|
const serviceTarget = () => `${domainTarget()}/${label}`;
|
|
18714
18819
|
async function fileExists(p) {
|
|
18715
18820
|
try {
|
|
18716
|
-
await
|
|
18821
|
+
await fs30.stat(p);
|
|
18717
18822
|
return true;
|
|
18718
18823
|
} catch {
|
|
18719
18824
|
return false;
|
|
@@ -18721,9 +18826,9 @@ function createLaunchdLifecycle(def, deps = {}) {
|
|
|
18721
18826
|
}
|
|
18722
18827
|
async function writePlist(program) {
|
|
18723
18828
|
const xml = generateLaunchdPlist({ label, program, logDir: def.logDir });
|
|
18724
|
-
await
|
|
18725
|
-
await
|
|
18726
|
-
await
|
|
18829
|
+
await fs30.mkdir(path3__default.dirname(plistPath()), { recursive: true });
|
|
18830
|
+
await fs30.mkdir(def.logDir, { recursive: true });
|
|
18831
|
+
await fs30.writeFile(plistPath(), xml, "utf8");
|
|
18727
18832
|
}
|
|
18728
18833
|
async function install(opts = {}) {
|
|
18729
18834
|
await writePlist(opts.program ?? def.program);
|
|
@@ -18734,7 +18839,7 @@ function createLaunchdLifecycle(def, deps = {}) {
|
|
|
18734
18839
|
}
|
|
18735
18840
|
async function uninstall() {
|
|
18736
18841
|
await runIdempotent(run, "launchctl", ["bootout", serviceTarget()], "launchctl bootout", LAUNCHD_NOT_LOADED);
|
|
18737
|
-
await
|
|
18842
|
+
await fs30.rm(plistPath(), { force: true });
|
|
18738
18843
|
}
|
|
18739
18844
|
async function start() {
|
|
18740
18845
|
if (!await fileExists(plistPath())) {
|
|
@@ -18818,14 +18923,14 @@ WantedBy=default.target
|
|
|
18818
18923
|
}
|
|
18819
18924
|
function createSystemdLifecycle(def, deps = {}) {
|
|
18820
18925
|
const run = deps.run ?? defaultRunner;
|
|
18821
|
-
const
|
|
18926
|
+
const fs30 = deps.fs ?? promises;
|
|
18822
18927
|
const homedir = deps.homedir ?? (() => os4__default.homedir());
|
|
18823
18928
|
const name = sanitizeServiceName(def.name);
|
|
18824
18929
|
const unitName = `${name}.service`;
|
|
18825
18930
|
const unitPath = () => path3__default.join(homedir(), ".config", "systemd", "user", unitName);
|
|
18826
18931
|
async function fileExists(p) {
|
|
18827
18932
|
try {
|
|
18828
|
-
await
|
|
18933
|
+
await fs30.stat(p);
|
|
18829
18934
|
return true;
|
|
18830
18935
|
} catch {
|
|
18831
18936
|
return false;
|
|
@@ -18833,9 +18938,9 @@ function createSystemdLifecycle(def, deps = {}) {
|
|
|
18833
18938
|
}
|
|
18834
18939
|
async function writeUnit(program) {
|
|
18835
18940
|
const unit = generateSystemdUnit({ name, displayName: def.displayName ?? def.name, program, logDir: def.logDir });
|
|
18836
|
-
await
|
|
18837
|
-
await
|
|
18838
|
-
await
|
|
18941
|
+
await fs30.mkdir(path3__default.dirname(unitPath()), { recursive: true });
|
|
18942
|
+
await fs30.mkdir(def.logDir, { recursive: true });
|
|
18943
|
+
await fs30.writeFile(unitPath(), unit, "utf8");
|
|
18839
18944
|
}
|
|
18840
18945
|
async function install(opts = {}) {
|
|
18841
18946
|
await writeUnit(opts.program ?? def.program);
|
|
@@ -18844,7 +18949,7 @@ function createSystemdLifecycle(def, deps = {}) {
|
|
|
18844
18949
|
}
|
|
18845
18950
|
async function uninstall() {
|
|
18846
18951
|
await runIdempotent(run, "systemctl", ["--user", "disable", "--now", unitName], "systemctl disable --now", SYSTEMD_NOT_LOADED);
|
|
18847
|
-
await
|
|
18952
|
+
await fs30.rm(unitPath(), { force: true });
|
|
18848
18953
|
await run("systemctl", ["--user", "daemon-reload"]);
|
|
18849
18954
|
}
|
|
18850
18955
|
async function start() {
|
|
@@ -18907,7 +19012,7 @@ ${argXml}${cwdXml}
|
|
|
18907
19012
|
}
|
|
18908
19013
|
function createWinswLifecycle(def, deps = {}) {
|
|
18909
19014
|
const run = deps.run ?? defaultRunner;
|
|
18910
|
-
const
|
|
19015
|
+
const fs30 = deps.fs ?? promises;
|
|
18911
19016
|
const windows = def.windows;
|
|
18912
19017
|
if (!windows) {
|
|
18913
19018
|
throw new Error("WinSW service lifecycle requires `ServiceDefinition.windows.winswBin` (the product-bundled WinSW executable path)");
|
|
@@ -18919,7 +19024,7 @@ function createWinswLifecycle(def, deps = {}) {
|
|
|
18919
19024
|
const xmlPath = path3__default.join(installDir, `${id}.xml`);
|
|
18920
19025
|
async function fileExists(p) {
|
|
18921
19026
|
try {
|
|
18922
|
-
await
|
|
19027
|
+
await fs30.stat(p);
|
|
18923
19028
|
return true;
|
|
18924
19029
|
} catch {
|
|
18925
19030
|
return false;
|
|
@@ -18927,10 +19032,10 @@ function createWinswLifecycle(def, deps = {}) {
|
|
|
18927
19032
|
}
|
|
18928
19033
|
async function writeFiles(program) {
|
|
18929
19034
|
const xml = generateWinswXml({ id, displayName: def.displayName ?? def.name, program, logDir: def.logDir });
|
|
18930
|
-
await
|
|
18931
|
-
await
|
|
18932
|
-
await
|
|
18933
|
-
await
|
|
19035
|
+
await fs30.mkdir(installDir, { recursive: true });
|
|
19036
|
+
await fs30.mkdir(def.logDir, { recursive: true });
|
|
19037
|
+
await fs30.copyFile(winswBin, exePath);
|
|
19038
|
+
await fs30.writeFile(xmlPath, xml, "utf8");
|
|
18934
19039
|
}
|
|
18935
19040
|
async function install(opts = {}) {
|
|
18936
19041
|
await writeFiles(opts.program ?? def.program);
|
|
@@ -18940,8 +19045,8 @@ function createWinswLifecycle(def, deps = {}) {
|
|
|
18940
19045
|
async function uninstall() {
|
|
18941
19046
|
await runIdempotent(run, exePath, ["stop"], "winsw stop", WINSW_NOT_INSTALLED);
|
|
18942
19047
|
await runIdempotent(run, exePath, ["uninstall"], "winsw uninstall", WINSW_NOT_INSTALLED);
|
|
18943
|
-
await
|
|
18944
|
-
await
|
|
19048
|
+
await fs30.rm(exePath, { force: true });
|
|
19049
|
+
await fs30.rm(xmlPath, { force: true });
|
|
18945
19050
|
}
|
|
18946
19051
|
async function start() {
|
|
18947
19052
|
if (!await fileExists(xmlPath)) {
|