@wlfi-agent/cli 1.4.15 → 1.4.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/Cargo.lock +1 -0
  2. package/Cargo.toml +1 -1
  3. package/README.md +10 -2
  4. package/crates/vault-cli-admin/src/main.rs +21 -2
  5. package/crates/vault-cli-admin/src/tui.rs +634 -129
  6. package/crates/vault-cli-daemon/Cargo.toml +1 -0
  7. package/crates/vault-cli-daemon/src/bin/wlfi-agent-system-keychain.rs +122 -8
  8. package/crates/vault-cli-daemon/src/main.rs +24 -4
  9. package/crates/vault-cli-daemon/src/relay_sync.rs +155 -35
  10. package/crates/vault-cli-daemon/tests/system_keychain_helper_acl.rs +23 -18
  11. package/crates/vault-daemon/src/daemon_parts/api_impl_and_utils.rs +6 -0
  12. package/crates/vault-daemon/src/daemon_parts/types_api_rpc.rs +6 -0
  13. package/crates/vault-daemon/src/tests.rs +2 -2
  14. package/crates/vault-daemon/src/tests_parts/part4.rs +110 -0
  15. package/crates/vault-transport-unix/src/lib.rs +22 -3
  16. package/crates/vault-transport-xpc/src/lib.rs +20 -2
  17. package/dist/cli.cjs +20842 -25552
  18. package/dist/cli.cjs.map +1 -1
  19. package/package.json +5 -3
  20. package/packages/cache/.turbo/turbo-build.log +20 -20
  21. package/packages/cache/coverage/base.css +224 -0
  22. package/packages/cache/coverage/block-navigation.js +87 -0
  23. package/packages/cache/coverage/clover.xml +585 -0
  24. package/packages/cache/coverage/coverage-final.json +5 -0
  25. package/packages/cache/coverage/favicon.png +0 -0
  26. package/packages/cache/coverage/index.html +161 -0
  27. package/packages/cache/coverage/prettify.css +1 -0
  28. package/packages/cache/coverage/prettify.js +2 -0
  29. package/packages/cache/coverage/sort-arrow-sprite.png +0 -0
  30. package/packages/cache/coverage/sorter.js +210 -0
  31. package/packages/cache/coverage/src/client/index.html +116 -0
  32. package/packages/cache/coverage/src/client/index.ts.html +253 -0
  33. package/packages/cache/coverage/src/errors/index.html +116 -0
  34. package/packages/cache/coverage/src/errors/index.ts.html +244 -0
  35. package/packages/cache/coverage/src/index.html +116 -0
  36. package/packages/cache/coverage/src/index.ts.html +94 -0
  37. package/packages/cache/coverage/src/service/index.html +116 -0
  38. package/packages/cache/coverage/src/service/index.ts.html +2212 -0
  39. package/packages/cache/dist/{chunk-ALQ6H7KG.cjs → chunk-QF4XKEIA.cjs} +189 -45
  40. package/packages/cache/dist/chunk-QF4XKEIA.cjs.map +1 -0
  41. package/packages/cache/dist/{chunk-FGJEEF5N.js → chunk-QNK6GOTI.js} +182 -38
  42. package/packages/cache/dist/chunk-QNK6GOTI.js.map +1 -0
  43. package/packages/cache/dist/index.cjs +2 -2
  44. package/packages/cache/dist/index.js +1 -1
  45. package/packages/cache/dist/service/index.cjs +2 -2
  46. package/packages/cache/dist/service/index.d.cts +2 -0
  47. package/packages/cache/dist/service/index.d.ts +2 -0
  48. package/packages/cache/dist/service/index.js +1 -1
  49. package/packages/cache/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  50. package/packages/cache/src/service/index.test.ts +575 -0
  51. package/packages/cache/src/service/index.ts +234 -51
  52. package/packages/config/.turbo/turbo-build.log +17 -18
  53. package/packages/config/node_modules/.bin/tsc +2 -2
  54. package/packages/config/node_modules/.bin/tsserver +2 -2
  55. package/packages/config/node_modules/.bin/tsup +2 -2
  56. package/packages/config/node_modules/.bin/tsup-node +2 -2
  57. package/packages/rpc/.turbo/turbo-build.log +31 -32
  58. package/packages/rpc/node_modules/.bin/tsc +2 -2
  59. package/packages/rpc/node_modules/.bin/tsserver +2 -2
  60. package/packages/rpc/node_modules/.bin/tsup +2 -2
  61. package/packages/rpc/node_modules/.bin/tsup-node +2 -2
  62. package/packages/ui/.turbo/turbo-build.log +43 -44
  63. package/scripts/install-rust-binaries.mjs +164 -58
  64. package/src/cli.ts +51 -39
  65. package/src/lib/admin-passthrough.js +1 -0
  66. package/src/lib/admin-reset.js +1 -0
  67. package/src/lib/admin-reset.ts +26 -16
  68. package/src/lib/admin-setup.js +1 -0
  69. package/src/lib/admin-setup.ts +32 -20
  70. package/src/lib/agent-auth-revoke.js +1 -0
  71. package/src/lib/agent-auth-rotate.js +1 -0
  72. package/src/lib/agent-auth.js +1 -0
  73. package/src/lib/config-mutation.js +1 -0
  74. package/src/lib/launchd-assets.js +1 -0
  75. package/src/lib/launchd-assets.ts +29 -0
  76. package/src/lib/local-admin-access.js +1 -0
  77. package/src/lib/rust.ts +1 -1
  78. package/src/lib/status-repair-cli.js +1 -0
  79. package/packages/cache/dist/chunk-ALQ6H7KG.cjs.map +0 -1
  80. package/packages/cache/dist/chunk-FGJEEF5N.js.map +0 -1
@@ -1,44 +1,43 @@
1
-
2
- 
3
- > @wlfi-agent/ui@0.0.0 build /Users/hanzhi/Documents/WLFI/wlfi-agent-sdk/packages/ui
4
- > tsup
5
-
6
- CLI Building entry: src/tailwind.ts, src/components/badge.tsx, src/components/button.tsx, src/components/card.tsx, src/components/input.tsx, src/components/label.tsx, src/components/separator.tsx, src/components/textarea.tsx, src/utils/cn.ts
7
- CLI Using tsconfig: tsconfig.json
8
- CLI tsup v8.5.1
9
- CLI Using tsup config: /Users/hanzhi/Documents/WLFI/wlfi-agent-sdk/packages/ui/tsup.config.ts
10
- CLI Target: es2022
11
- CLI Cleaning output folder
12
- ESM Build start
13
- ESM dist/chunk-MOAFBKSA.js 209.00 B
14
- ESM dist/tailwind.js 1.59 KB
15
- ESM dist/components/card.js 1.22 KB
16
- ESM dist/components/separator.js 349.00 B
17
- ESM dist/components/label.js 327.00 B
18
- ESM dist/components/textarea.js 785.00 B
19
- ESM dist/utils/cn.js 92.00 B
20
- ESM dist/components/badge.js 971.00 B
21
- ESM dist/components/button.js 1.43 KB
22
- ESM dist/components/input.js 840.00 B
23
- ESM dist/chunk-MOAFBKSA.js.map 368.00 B
24
- ESM dist/tailwind.js.map 2.39 KB
25
- ESM dist/components/card.js.map 2.10 KB
26
- ESM dist/components/textarea.js.map 1.05 KB
27
- ESM dist/components/badge.js.map 1.50 KB
28
- ESM dist/utils/cn.js.map 71.00 B
29
- ESM dist/components/input.js.map 1.12 KB
30
- ESM dist/components/separator.js.map 519.00 B
31
- ESM dist/components/button.js.map 2.14 KB
32
- ESM dist/components/label.js.map 502.00 B
33
- ESM ⚡️ Build success in 19ms
34
- DTS Build start
35
- DTS ⚡️ Build success in 955ms
36
- DTS dist/tailwind.d.ts 1.49 KB
37
- DTS dist/components/badge.d.ts 612.00 B
38
- DTS dist/components/button.d.ts 715.00 B
39
- DTS dist/components/card.d.ts 791.00 B
40
- DTS dist/components/input.d.ts 191.00 B
41
- DTS dist/components/label.d.ts 165.00 B
42
- DTS dist/components/separator.d.ts 166.00 B
43
- DTS dist/components/textarea.d.ts 206.00 B
44
- DTS dist/utils/cn.d.ts 106.00 B
1
+
2
+ > @wlfi-agent/ui@0.0.0 build /Users/hanzhi/Documents/WLFI/wlfi-agent-sdk/packages/ui
3
+ > tsup
4
+
5
+ CLI Building entry: src/tailwind.ts, src/components/badge.tsx, src/components/button.tsx, src/components/card.tsx, src/components/input.tsx, src/components/label.tsx, src/components/separator.tsx, src/components/textarea.tsx, src/utils/cn.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.5.1
8
+ CLI Using tsup config: /Users/hanzhi/Documents/WLFI/wlfi-agent-sdk/packages/ui/tsup.config.ts
9
+ CLI Target: es2022
10
+ CLI Cleaning output folder
11
+ ESM Build start
12
+ ESM dist/tailwind.js 1.59 KB
13
+ ESM dist/utils/cn.js 92.00 B
14
+ ESM dist/components/label.js 327.00 B
15
+ ESM dist/components/card.js 1.22 KB
16
+ ESM dist/components/button.js 1.43 KB
17
+ ESM dist/components/input.js 840.00 B
18
+ ESM dist/components/badge.js 971.00 B
19
+ ESM dist/components/textarea.js 785.00 B
20
+ ESM dist/components/separator.js 349.00 B
21
+ ESM dist/chunk-MOAFBKSA.js 209.00 B
22
+ ESM dist/utils/cn.js.map 71.00 B
23
+ ESM dist/tailwind.js.map 2.39 KB
24
+ ESM dist/components/label.js.map 502.00 B
25
+ ESM dist/components/card.js.map 2.10 KB
26
+ ESM dist/components/input.js.map 1.12 KB
27
+ ESM dist/components/button.js.map 2.14 KB
28
+ ESM dist/components/textarea.js.map 1.05 KB
29
+ ESM dist/components/badge.js.map 1.50 KB
30
+ ESM dist/chunk-MOAFBKSA.js.map 368.00 B
31
+ ESM dist/components/separator.js.map 519.00 B
32
+ ESM ⚡️ Build success in 31ms
33
+ DTS Build start
34
+ DTS ⚡️ Build success in 688ms
35
+ DTS dist/tailwind.d.ts 1.49 KB
36
+ DTS dist/components/badge.d.ts 612.00 B
37
+ DTS dist/components/button.d.ts 715.00 B
38
+ DTS dist/components/card.d.ts 791.00 B
39
+ DTS dist/components/input.d.ts 191.00 B
40
+ DTS dist/components/label.d.ts 165.00 B
41
+ DTS dist/components/separator.d.ts 166.00 B
42
+ DTS dist/components/textarea.d.ts 206.00 B
43
+ DTS dist/utils/cn.d.ts 106.00 B
@@ -2,83 +2,189 @@ import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { spawnSync } from 'node:child_process';
5
-
6
- if (process.env.WLFI_SKIP_RUST_INSTALL === '1') {
7
- process.exit(0);
8
- }
5
+ import { pathToFileURL } from 'node:url';
9
6
 
10
7
  const repoRoot = new URL('..', import.meta.url).pathname;
11
- const wlfiHome = process.env.WLFI_HOME?.trim() || path.join(os.homedir(), '.wlfi_agent');
12
- const binDir = path.join(wlfiHome, 'bin');
13
8
  const extension = process.platform === 'win32' ? '.exe' : '';
14
9
  const rustBins = [
15
10
  'wlfi-agent-daemon',
16
11
  'wlfi-agent-admin',
17
12
  'wlfi-agent-agent',
18
- 'wlfi-agent-system-keychain'
13
+ 'wlfi-agent-system-keychain',
19
14
  ];
20
- const helperScripts = [
21
- {
22
- source: path.join(repoRoot, 'scripts', 'launchd', 'run-wlfi-agent-daemon.sh'),
23
- destination: path.join(binDir, 'run-wlfi-agent-daemon.sh')
15
+ const RERUN_INSTRUCTIONS =
16
+ 'After installing prerequisites, rerun `npm install -g @wlfi-agent/cli`.';
17
+
18
+ function decodeOutput(value) {
19
+ if (!value) {
20
+ return '';
24
21
  }
25
- ];
22
+ return value.toString().trim();
23
+ }
26
24
 
27
- fs.mkdirSync(binDir, { recursive: true, mode: 0o700 });
28
- const cargo = spawnSync('cargo', ['--version'], { cwd: repoRoot, stdio: 'pipe' });
29
- if (cargo.status !== 0) {
30
- console.warn('[wlfi-agent] cargo was not found; skipping Rust binary installation');
31
- console.warn('[wlfi-agent] install Rust from https://rustup.rs and rerun `npm run install:rust-binaries`.');
32
- process.exit(0);
25
+ function runCheck(spawnSyncImpl, command, args, options = {}) {
26
+ return spawnSyncImpl(command, args, {
27
+ cwd: repoRoot,
28
+ stdio: 'pipe',
29
+ ...options,
30
+ });
33
31
  }
34
32
 
35
- const build = spawnSync(
36
- 'cargo',
37
- [
38
- 'build',
39
- '--release',
40
- '-p',
41
- 'wlfi-agent-daemon',
42
- '-p',
43
- 'wlfi-agent-admin',
44
- '-p',
45
- 'wlfi-agent-agent'
46
- ],
47
- { cwd: repoRoot, stdio: 'inherit' }
48
- );
49
- if (build.status !== 0) {
50
- process.exit(build.status ?? 1);
33
+ function resolveWlfiPaths(env) {
34
+ const wlfiHome = env.WLFI_HOME?.trim() || path.join(os.homedir(), '.wlfi_agent');
35
+ return {
36
+ wlfiHome,
37
+ binDir: path.join(wlfiHome, 'bin'),
38
+ };
51
39
  }
52
40
 
53
- for (const binary of rustBins) {
54
- const source = path.join(repoRoot, 'target', 'release', binary + extension);
55
- const destination = path.join(binDir, binary + extension);
56
- fs.copyFileSync(source, destination);
57
- if (process.platform !== 'win32') {
58
- fs.chmodSync(destination, 0o755);
41
+ function resolveHelperScripts(binDir) {
42
+ return [
43
+ {
44
+ source: path.join(repoRoot, 'scripts', 'launchd', 'run-wlfi-agent-daemon.sh'),
45
+ destination: path.join(binDir, 'run-wlfi-agent-daemon.sh'),
46
+ },
47
+ {
48
+ source: path.join(repoRoot, 'scripts', 'launchd', 'install-user-daemon.sh'),
49
+ destination: path.join(binDir, 'install-user-daemon.sh'),
50
+ },
51
+ {
52
+ source: path.join(repoRoot, 'scripts', 'launchd', 'uninstall-user-daemon.sh'),
53
+ destination: path.join(binDir, 'uninstall-user-daemon.sh'),
54
+ },
55
+ ];
56
+ }
57
+
58
+ function checkCargoAvailable(spawnSyncImpl) {
59
+ const result = runCheck(spawnSyncImpl, 'cargo', ['--version']);
60
+ if (result.status === 0) {
61
+ return;
62
+ }
63
+
64
+ const detail = decodeOutput(result.stderr) || decodeOutput(result.stdout);
65
+ const lines = [
66
+ '[wlfi-agent] Rust toolchain was not found on PATH.',
67
+ '[wlfi-agent] Install Rust from https://rustup.rs.',
68
+ ];
69
+ if (detail) {
70
+ lines.push(`[wlfi-agent] cargo check output: ${detail}`);
59
71
  }
72
+ lines.push(`[wlfi-agent] ${RERUN_INSTRUCTIONS}`);
73
+ throw new Error(lines.join('\n'));
60
74
  }
61
75
 
62
- for (const script of helperScripts) {
63
- fs.copyFileSync(script.source, script.destination);
64
- if (process.platform !== 'win32') {
65
- fs.chmodSync(script.destination, 0o755);
76
+ function checkMacOsToolchainAvailable(spawnSyncImpl, platform) {
77
+ if (platform !== 'darwin') {
78
+ return;
66
79
  }
80
+
81
+ const result = runCheck(spawnSyncImpl, 'xcrun', ['--sdk', 'macosx', '--find', 'clang']);
82
+ if (result.status === 0) {
83
+ return;
84
+ }
85
+
86
+ const detail = decodeOutput(result.stderr) || decodeOutput(result.stdout);
87
+ const lines = [
88
+ '[wlfi-agent] macOS Command Line Tools were not found or are not configured.',
89
+ '[wlfi-agent] Install them with `xcode-select --install`.',
90
+ ];
91
+ if (detail) {
92
+ lines.push(`[wlfi-agent] xcrun check output: ${detail}`);
93
+ }
94
+ lines.push(`[wlfi-agent] ${RERUN_INSTRUCTIONS}`);
95
+ throw new Error(lines.join('\n'));
67
96
  }
68
97
 
69
- const configPath = path.join(wlfiHome, 'config.json');
70
- if (!fs.existsSync(configPath)) {
71
- fs.writeFileSync(
72
- configPath,
73
- JSON.stringify(
74
- {
75
- daemonSocket: path.join(wlfiHome, 'daemon.sock'),
76
- stateFile: path.join(wlfiHome, 'daemon-state.enc'),
77
- rustBinDir: binDir
78
- },
79
- null,
80
- 2
81
- ) + '\n',
82
- { mode: 0o600 }
98
+ export function verifyRustInstallPrerequisites({
99
+ spawnSyncImpl = spawnSync,
100
+ platform = process.platform,
101
+ } = {}) {
102
+ checkCargoAvailable(spawnSyncImpl);
103
+ checkMacOsToolchainAvailable(spawnSyncImpl, platform);
104
+ }
105
+
106
+ export function installRustBinaries({
107
+ spawnSyncImpl = spawnSync,
108
+ env = process.env,
109
+ platform = process.platform,
110
+ } = {}) {
111
+ if (env.WLFI_SKIP_RUST_INSTALL === '1') {
112
+ return 0;
113
+ }
114
+
115
+ verifyRustInstallPrerequisites({ spawnSyncImpl, platform });
116
+
117
+ const { wlfiHome, binDir } = resolveWlfiPaths(env);
118
+ const helperScripts = resolveHelperScripts(binDir);
119
+
120
+ fs.mkdirSync(binDir, { recursive: true, mode: 0o700 });
121
+ const build = spawnSyncImpl(
122
+ 'cargo',
123
+ [
124
+ 'build',
125
+ '--release',
126
+ '-p',
127
+ 'wlfi-agent-daemon',
128
+ '-p',
129
+ 'wlfi-agent-admin',
130
+ '-p',
131
+ 'wlfi-agent-agent',
132
+ ],
133
+ { cwd: repoRoot, stdio: 'inherit' },
134
+ );
135
+ if (build.status !== 0) {
136
+ return build.status ?? 1;
137
+ }
138
+
139
+ for (const binary of rustBins) {
140
+ const source = path.join(repoRoot, 'target', 'release', binary + extension);
141
+ const destination = path.join(binDir, binary + extension);
142
+ fs.copyFileSync(source, destination);
143
+ if (platform !== 'win32') {
144
+ fs.chmodSync(destination, 0o755);
145
+ }
146
+ }
147
+
148
+ for (const script of helperScripts) {
149
+ fs.copyFileSync(script.source, script.destination);
150
+ if (platform !== 'win32') {
151
+ fs.chmodSync(script.destination, 0o755);
152
+ }
153
+ }
154
+
155
+ const configPath = path.join(wlfiHome, 'config.json');
156
+ if (!fs.existsSync(configPath)) {
157
+ fs.writeFileSync(
158
+ configPath,
159
+ JSON.stringify(
160
+ {
161
+ daemonSocket: path.join(wlfiHome, 'daemon.sock'),
162
+ stateFile: path.join(wlfiHome, 'daemon-state.enc'),
163
+ rustBinDir: binDir,
164
+ },
165
+ null,
166
+ 2,
167
+ ) + '\n',
168
+ { mode: 0o600 },
169
+ );
170
+ }
171
+
172
+ return 0;
173
+ }
174
+
175
+ function isDirectExecution() {
176
+ return (
177
+ Boolean(process.argv[1]) &&
178
+ import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href
83
179
  );
84
180
  }
181
+
182
+ if (isDirectExecution()) {
183
+ try {
184
+ process.exitCode = installRustBinaries();
185
+ } catch (error) {
186
+ const message = error instanceof Error ? error.message : String(error);
187
+ process.stderr.write(`${message}\n`);
188
+ process.exitCode = 1;
189
+ }
190
+ }
package/src/cli.ts CHANGED
@@ -1,41 +1,6 @@
1
- import {
2
- type ChainProfile,
3
- defaultDaemonSocketPath,
4
- deleteConfigKey,
5
- ensureWlfiHome,
6
- listBuiltinChains,
7
- listBuiltinTokens,
8
- listConfiguredChains,
9
- listConfiguredTokens,
10
- readConfig,
11
- redactConfig,
12
- removeChainProfile,
13
- removeTokenChainProfile,
14
- removeTokenProfile,
15
- resolveChainProfile,
16
- resolveConfigPath,
17
- resolveTokenProfile,
18
- saveChainProfile,
19
- saveTokenChainProfile,
20
- switchActiveChain,
21
- type TokenChainProfile,
22
- type WlfiConfig,
23
- writeConfig,
24
- } from '@wlfi-agent/config';
25
- import {
26
- broadcastRawTransaction,
27
- estimateFees,
28
- estimateGas,
29
- getAccountSnapshot,
30
- getChainInfo,
31
- getCodeAtAddress,
32
- getLatestBlockNumber,
33
- getNativeBalance,
34
- getNonce,
35
- getTokenBalance,
36
- getTransactionByHash,
37
- getTransactionReceiptByHash,
38
- } from '@wlfi-agent/rpc';
1
+ import * as configPackage from '../packages/config/src/index.js';
2
+ import * as rpcPackage from '../packages/rpc/src/index.ts';
3
+ import type { ChainProfile, TokenChainProfile, WlfiConfig } from '../packages/config/src/index.js';
39
4
  import { Command, Option } from 'commander';
40
5
  import { type Address, type Hex, isAddress, isHex } from 'viem';
41
6
  import { assertSafeRpcUrl } from '../packages/config/src/index.js';
@@ -118,6 +83,49 @@ import {
118
83
  walletProfileFromBootstrapSummary,
119
84
  } from './lib/wallet-profile.js';
120
85
 
86
+ const configExports = (
87
+ 'default' in configPackage ? configPackage.default : configPackage
88
+ ) as typeof import('../packages/config/src/index.js');
89
+ const {
90
+ defaultDaemonSocketPath,
91
+ deleteConfigKey,
92
+ ensureWlfiHome,
93
+ listBuiltinChains,
94
+ listBuiltinTokens,
95
+ listConfiguredChains,
96
+ listConfiguredTokens,
97
+ readConfig,
98
+ redactConfig,
99
+ removeChainProfile,
100
+ removeTokenChainProfile,
101
+ removeTokenProfile,
102
+ resolveChainProfile,
103
+ resolveConfigPath,
104
+ resolveTokenProfile,
105
+ saveChainProfile,
106
+ saveTokenChainProfile,
107
+ switchActiveChain,
108
+ writeConfig,
109
+ } = configExports;
110
+
111
+ const rpcExports = ('default' in rpcPackage ? rpcPackage.default : rpcPackage) as typeof import(
112
+ '../packages/rpc/src/index.ts'
113
+ );
114
+ const {
115
+ broadcastRawTransaction,
116
+ estimateFees,
117
+ estimateGas,
118
+ getAccountSnapshot,
119
+ getChainInfo,
120
+ getCodeAtAddress,
121
+ getLatestBlockNumber,
122
+ getNativeBalance,
123
+ getNonce,
124
+ getTokenBalance,
125
+ getTransactionByHash,
126
+ getTransactionReceiptByHash,
127
+ } = rpcExports;
128
+
121
129
  interface RustBroadcastOutput {
122
130
  command: string;
123
131
  network: string;
@@ -302,7 +310,11 @@ async function readTrimmedStdin(label: string): Promise<string> {
302
310
  }
303
311
 
304
312
  function formatJson(payload: unknown) {
305
- return JSON.stringify(payload, null, 2);
313
+ return JSON.stringify(
314
+ payload,
315
+ (_key, value) => (typeof value === 'bigint' ? value.toString() : value),
316
+ 2,
317
+ );
306
318
  }
307
319
 
308
320
  function stringifyOptionalValue(value: { toString(): string } | null | undefined): string | null {
@@ -0,0 +1 @@
1
+ export * from './admin-passthrough.ts';
@@ -0,0 +1 @@
1
+ export * from './admin-reset.ts';
@@ -20,6 +20,10 @@ import {
20
20
  DAEMON_PASSWORD_KEYCHAIN_SERVICE,
21
21
  deleteAgentAuthTokenFromKeychain,
22
22
  } from './keychain.js';
23
+ import {
24
+ LAUNCHD_UNINSTALL_SCRIPT_NAME,
25
+ resolveLaunchDaemonHelperScriptPath,
26
+ } from './launchd-assets.js';
23
27
  import { createSudoSession } from './sudo.js';
24
28
 
25
29
  const DEFAULT_LAUNCH_DAEMON_LABEL = 'com.wlfi.agent.daemon';
@@ -29,6 +33,7 @@ const DEFAULT_LAUNCH_DAEMON_PLIST = `/Library/LaunchDaemons/${DEFAULT_LAUNCH_DAE
29
33
  const DEFAULT_MANAGED_ROOT_DIR = '/Library/WLFI';
30
34
  const DEFAULT_MANAGED_STATE_DIR = '/var/db/wlfi-agent';
31
35
  const DEFAULT_MANAGED_LOG_DIR = '/var/log/wlfi-agent';
36
+ const DEFAULT_MANAGED_RELAY_DAEMON_TOKEN_FILE = `${DEFAULT_MANAGED_STATE_DIR}/relay-daemon-token`;
32
37
  const MAX_SECRET_STDIN_BYTES = 16 * 1024;
33
38
  const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
34
39
 
@@ -247,6 +252,7 @@ function printResetSummary(result: {
247
252
  daemon: {
248
253
  label: string;
249
254
  daemonSocket: string;
255
+ relayDaemonTokenFile: string;
250
256
  stateFile: string;
251
257
  };
252
258
  local: CleanupLocalAdminResetStateResult;
@@ -256,6 +262,7 @@ function printResetSummary(result: {
256
262
  `managed daemon removed: ${result.daemon.label}`,
257
263
  `managed state deleted: ${result.daemon.stateFile}`,
258
264
  `managed socket removed: ${result.daemon.daemonSocket}`,
265
+ `managed relay token removed: ${result.daemon.relayDaemonTokenFile}`,
259
266
  ];
260
267
 
261
268
  if (result.local.agentKeyId) {
@@ -284,20 +291,20 @@ function printResetSummary(result: {
284
291
  console.log(lines.join('\n'));
285
292
  }
286
293
 
287
- function resolveLaunchDaemonUninstallScriptPath(): string {
288
- const candidates = [
289
- path.resolve(__dirname, '../scripts/launchd/uninstall-user-daemon.sh'),
290
- path.resolve(__dirname, '../../scripts/launchd/uninstall-user-daemon.sh'),
291
- path.resolve(process.cwd(), 'scripts/launchd/uninstall-user-daemon.sh'),
292
- ];
294
+ function resolveLaunchDaemonUninstallScriptPath(config?: WlfiConfig): string {
295
+ return resolveLaunchDaemonHelperScriptPath(LAUNCHD_UNINSTALL_SCRIPT_NAME, config);
296
+ }
293
297
 
294
- for (const candidate of candidates) {
295
- if (fs.existsSync(candidate)) {
296
- return candidate;
297
- }
298
- }
298
+ function readConfigIfPresent(): WlfiConfig | undefined {
299
+ return fs.existsSync(resolveConfigPath()) ? readConfig() : undefined;
300
+ }
299
301
 
300
- return candidates[0];
302
+ export function managedDaemonResetArtifactPaths(): string[] {
303
+ return [
304
+ DEFAULT_MANAGED_STATE_FILE,
305
+ DEFAULT_MANAGED_DAEMON_SOCKET,
306
+ DEFAULT_MANAGED_RELAY_DAEMON_TOKEN_FILE,
307
+ ];
301
308
  }
302
309
 
303
310
  export function cleanupLocalAdminResetState(
@@ -480,12 +487,13 @@ async function runAdminReset(options: AdminResetOptions): Promise<void> {
480
487
  );
481
488
  }
482
489
  await sudoSession.prime();
490
+ const currentConfig = readConfigIfPresent();
483
491
 
484
492
  const uninstallProgress = createProgress('Uninstalling managed daemon', showProgress);
485
493
  let uninstallResult;
486
494
  try {
487
495
  uninstallResult = await sudoSession.run([
488
- resolveLaunchDaemonUninstallScriptPath(),
496
+ resolveLaunchDaemonUninstallScriptPath(currentConfig),
489
497
  '--label',
490
498
  DEFAULT_LAUNCH_DAEMON_LABEL,
491
499
  '--keychain-service',
@@ -514,8 +522,7 @@ async function runAdminReset(options: AdminResetOptions): Promise<void> {
514
522
  deleteRootArtifactsResult = await sudoSession.run([
515
523
  '/bin/rm',
516
524
  '-f',
517
- DEFAULT_MANAGED_STATE_FILE,
518
- DEFAULT_MANAGED_DAEMON_SOCKET,
525
+ ...managedDaemonResetArtifactPaths(),
519
526
  ]);
520
527
  } catch (error) {
521
528
  stateProgress.fail();
@@ -543,6 +550,7 @@ async function runAdminReset(options: AdminResetOptions): Promise<void> {
543
550
  launchdDomain: 'system',
544
551
  plist: DEFAULT_LAUNCH_DAEMON_PLIST,
545
552
  daemonSocket: DEFAULT_MANAGED_DAEMON_SOCKET,
553
+ relayDaemonTokenFile: DEFAULT_MANAGED_RELAY_DAEMON_TOKEN_FILE,
546
554
  stateFile: DEFAULT_MANAGED_STATE_FILE,
547
555
  systemKeychainPasswordService: DAEMON_PASSWORD_KEYCHAIN_SERVICE,
548
556
  systemKeychainPasswordAccount: keychainAccount,
@@ -560,6 +568,7 @@ async function runAdminReset(options: AdminResetOptions): Promise<void> {
560
568
  daemon: {
561
569
  label: result.daemon.label,
562
570
  daemonSocket: result.daemon.daemonSocket,
571
+ relayDaemonTokenFile: result.daemon.relayDaemonTokenFile,
563
572
  stateFile: result.daemon.stateFile,
564
573
  },
565
574
  local,
@@ -625,12 +634,13 @@ async function runAdminUninstall(options: AdminUninstallOptions): Promise<void>
625
634
  );
626
635
  }
627
636
  await sudoSession.prime();
637
+ const currentConfig = readConfigIfPresent();
628
638
 
629
639
  const uninstallProgress = createProgress('Uninstalling managed daemon', showProgress);
630
640
  let uninstallResult;
631
641
  try {
632
642
  uninstallResult = await sudoSession.run([
633
- resolveLaunchDaemonUninstallScriptPath(),
643
+ resolveLaunchDaemonUninstallScriptPath(currentConfig),
634
644
  '--label',
635
645
  DEFAULT_LAUNCH_DAEMON_LABEL,
636
646
  '--keychain-service',
@@ -0,0 +1 @@
1
+ export * from './admin-setup.ts';