@agentdocumentformat/cli 0.7.8 → 0.8.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.
Files changed (100) hide show
  1. package/README.md +1 -1
  2. package/dist/adf.mjs +59 -8
  3. package/dist/chunks/{APEv2Parser-2CNNHMXV.mjs → APEv2Parser-WIXRJLHB.mjs} +2 -2
  4. package/dist/chunks/{AiffParser-7BR4RL6G.mjs → AiffParser-ZC4QFOVJ.mjs} +5 -5
  5. package/dist/chunks/{App-7RIIOHJJ.mjs → App-A5GUFCFJ.mjs} +279 -293
  6. package/dist/chunks/{DsdiffParser-CMD4AX7A.mjs → DsdiffParser-UAPAJHFX.mjs} +5 -5
  7. package/dist/chunks/{DsfParser-UOGZDS2M.mjs → DsfParser-NNYZK2QX.mjs} +6 -6
  8. package/dist/chunks/{FlacParser-HB3T3CD4.mjs → FlacParser-MW2W4LO3.mjs} +6 -6
  9. package/dist/chunks/{MP4Parser-66HBRUSX.mjs → MP4Parser-Z57SYOOQ.mjs} +4 -4
  10. package/dist/chunks/{MpegParser-YW6LIUEW.mjs → MpegParser-XIIPAZVM.mjs} +7 -7
  11. package/dist/chunks/{MusepackParser-PAUSXP7D.mjs → MusepackParser-QWNDEYHJ.mjs} +6 -6
  12. package/dist/chunks/{OggParser-NUBV3GWC.mjs → OggParser-WRX53F77.mjs} +9 -9
  13. package/dist/chunks/{WavPackParser-WQAGT7TC.mjs → WavPackParser-MJ7WCSJ5.mjs} +2 -2
  14. package/dist/chunks/{WaveParser-EWLQVDX4.mjs → WaveParser-RAVLHZ5S.mjs} +7 -7
  15. package/dist/chunks/{adf-schema-US4NFHMR.mjs → adf-schema-YJSGLMA4.mjs} +2 -2
  16. package/dist/chunks/auth-manager-AJ32FZWS.mjs +19 -0
  17. package/dist/chunks/auth-manager-C5OBEQK2.mjs +18 -0
  18. package/dist/chunks/auth-manager-TBNKCJ45.mjs +17 -0
  19. package/dist/chunks/{chatgpt-subscription-E4MXTIAT.mjs → chatgpt-subscription-MMGNW5KJ.mjs} +5 -2
  20. package/dist/chunks/chunk-3UGZFWIF.mjs +26 -0
  21. package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-4OGZFUKA.mjs} +126 -67
  22. package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-6XQZGYMK.mjs} +246 -67
  23. package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
  24. package/dist/chunks/chunk-AZYOXXVL.mjs +865 -0
  25. package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
  26. package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
  27. package/dist/chunks/chunk-C4GA5SI4.mjs +12799 -0
  28. package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
  29. package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
  30. package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-G6NBFYG5.mjs} +152 -824
  31. package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
  32. package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
  33. package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
  34. package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
  35. package/dist/chunks/chunk-JVPZIMXW.mjs +976 -0
  36. package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
  37. package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
  38. package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
  39. package/dist/chunks/{chunk-G6PH7RPW.mjs → chunk-LCMANRYY.mjs} +3 -3
  40. package/dist/chunks/{chunk-ZESQMP66.mjs → chunk-LGL6ML37.mjs} +3 -3
  41. package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
  42. package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
  43. package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
  44. package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
  45. package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
  46. package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
  47. package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-NZO5O4VN.mjs} +1 -1
  48. package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
  49. package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
  50. package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
  51. package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
  52. package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-PRPTKMQW.mjs} +67 -26
  53. package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
  54. package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
  55. package/dist/chunks/chunk-V2T6NZX2.mjs +517 -0
  56. package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
  57. package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
  58. package/dist/chunks/chunk-WVTPPOKK.mjs +290 -0
  59. package/dist/chunks/{chunk-J74STFKE.mjs → chunk-WX6QCUWI.mjs} +272 -51
  60. package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
  61. package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-XT2BJUFC.mjs} +15 -6
  62. package/dist/chunks/{chunk-HSBV6YFU.mjs → chunk-YRMKSHW3.mjs} +614 -92
  63. package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
  64. package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
  65. package/dist/chunks/claude-subscription-33BMZB6I.mjs +29 -0
  66. package/dist/chunks/{cli-NMFIAR7Z.mjs → cli-I47IFDHJ.mjs} +797 -56
  67. package/dist/chunks/{commands-KPJWFRUE.mjs → commands-E4EQUHE5.mjs} +4 -3
  68. package/dist/chunks/{daemon-YDIK3AAM.mjs → daemon-FQ5BV3AP.mjs} +82058 -63958
  69. package/dist/chunks/daemon-control-L3CLG63P.mjs +59 -0
  70. package/dist/chunks/{daemon-token-WRSULP7G.mjs → daemon-token-L5QKTHU5.mjs} +3 -1
  71. package/dist/chunks/{discord-DSP4HUWI.mjs → discord-IR62565M.mjs} +3 -52
  72. package/dist/chunks/{email-BRG7KUO2.mjs → email-KHHTJBDW.mjs} +4 -2
  73. package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
  74. package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
  75. package/dist/chunks/{open-VAU7PXT6.mjs → open-TLGS2Z3Q.mjs} +4 -4
  76. package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
  77. package/dist/chunks/{pipeline-executor-O77NTGLP.mjs → pipeline-executor-FD4FBWQA.mjs} +6 -5
  78. package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
  79. package/dist/chunks/remote-access-cli-XXAPQWH6.mjs +268 -0
  80. package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
  81. package/dist/chunks/sdk-5FD2ZP7N.mjs +28422 -0
  82. package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
  83. package/dist/chunks/{store-HUVDJPYN.mjs → store-ZRN2WCFB.mjs} +6 -3
  84. package/dist/chunks/tailscale-WLJATFMB.mjs +25 -0
  85. package/dist/chunks/{theme-SFE3JMA2.mjs → theme-HLBDTF6F.mjs} +1 -1
  86. package/dist/chunks/{themes-YLXLOIJF.mjs → themes-BQ72P446.mjs} +2 -2
  87. package/dist/chunks/{token-6G3HCMNX.mjs → token-6D22WECM.mjs} +20 -16
  88. package/dist/chunks/{token-util-UXYSDQIW.mjs → token-util-YF3ZWBZ4.mjs} +1 -2
  89. package/dist/chunks/{tui-UQJLK7XI.mjs → tui-SPSPDADM.mjs} +17 -14
  90. package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
  91. package/dist/chunks/{whatsapp-AJMRQBT7.mjs → whatsapp-YJFFVN4Q.mjs} +9 -9
  92. package/package.json +1 -1
  93. package/dist/chunks/chunk-GKKCMXIZ.mjs +0 -94
  94. package/dist/chunks/chunk-IHDDCZBS.mjs +0 -112
  95. package/dist/chunks/chunk-KWFOS5WC.mjs +0 -41
  96. package/dist/chunks/chunk-UEZR2CNS.mjs +0 -65
  97. package/dist/chunks/chunk-VMHTYDH4.mjs +0 -172
  98. package/dist/chunks/chunk-Y2QA53AN.mjs +0 -259
  99. package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
  100. package/dist/chunks/{telegram-2EFGKIVK.mjs → telegram-JYY2VDTI.mjs} +5 -5
@@ -338,7 +338,7 @@ var Parser = class _Parser {
338
338
  for (; this.peek().type === "semi"; ) this.advance();
339
339
  if (this.peek().type === "eof") return left;
340
340
  let right = this.parseChain();
341
- left = { kind: "chain", left, operator, right };
341
+ return { kind: "chain", left, operator, right };
342
342
  }
343
343
  return left;
344
344
  }
@@ -0,0 +1,517 @@
1
+ import { createRequire as __adfCreateRequire } from 'node:module';
2
+ import { fileURLToPath as __adfFileURLToPath } from 'node:url';
3
+ import { dirname as __adfDirname } from 'node:path';
4
+ const require = __adfCreateRequire(import.meta.url);
5
+ const __filename = __adfFileURLToPath(import.meta.url);
6
+ const __dirname = __adfDirname(__filename);
7
+ import {
8
+ isLocalOnlyRoute,
9
+ openKeychainBackend,
10
+ readLocalProof,
11
+ testSeamsAllowed
12
+ } from "./chunk-WVTPPOKK.mjs";
13
+ import {
14
+ daemonSettingsDir,
15
+ readDaemonToken
16
+ } from "./chunk-WJGPNHGX.mjs";
17
+ import {
18
+ writeSecretFileAtomic
19
+ } from "./chunk-ZPB3HYM7.mjs";
20
+ import {
21
+ __export
22
+ } from "./chunk-M2RX3S2T.mjs";
23
+
24
+ // src/main/cli/remotes.ts
25
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
26
+ import { link, open, readFile, rename, stat, unlink } from "node:fs/promises";
27
+ import { randomBytes } from "node:crypto";
28
+ import { join } from "node:path";
29
+
30
+ // src/main/backend/daemon-secrets.ts
31
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
32
+ import { dirname } from "node:path";
33
+ var TEST_KEYCHAIN_FILE_ENV = "ADF_TEST_KEYCHAIN_FILE", JsonFileKeychain = class {
34
+ constructor(filePath) {
35
+ this.filePath = filePath;
36
+ }
37
+ filePath;
38
+ kind = "keychain";
39
+ read() {
40
+ if (!existsSync(this.filePath)) return {};
41
+ let parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
42
+ return parsed && typeof parsed == "object" && !Array.isArray(parsed) ? parsed : {};
43
+ }
44
+ write(values) {
45
+ mkdirSync(dirname(this.filePath), { recursive: !0 });
46
+ let tmp = `${this.filePath}.studio.tmp`;
47
+ writeFileSync(tmp, JSON.stringify(values, null, 2) + `
48
+ `, { mode: 384 }), renameSync(tmp, this.filePath);
49
+ }
50
+ isUnlocked() {
51
+ return !0;
52
+ }
53
+ get(account2) {
54
+ return this.read()[account2] ?? null;
55
+ }
56
+ set(account2, value) {
57
+ this.write({ ...this.read(), [account2]: value });
58
+ }
59
+ delete(account2) {
60
+ let values = this.read();
61
+ account2 in values && (delete values[account2], this.write(values));
62
+ }
63
+ };
64
+ function openDaemonSecrets(env = process.env, opts = {}) {
65
+ if (env.ADF_SECRET_STORE === "file")
66
+ return { backend: null, unavailable: "the daemon keeps its secrets in its passphrase file (ADF_SECRET_STORE=file), which Studio cannot write" };
67
+ if (env.ADF_KEYCHAIN === "0" || env.ADF_KEYCHAIN === "off")
68
+ return { backend: null, unavailable: "the OS keychain is turned off (ADF_KEYCHAIN=0)" };
69
+ let fake = env[TEST_KEYCHAIN_FILE_ENV];
70
+ if (fake)
71
+ return !opts.packaged && testSeamsAllowed({ env }) ? { backend: new JsonFileKeychain(fake) } : { backend: null, unavailable: `${TEST_KEYCHAIN_FILE_ENV} is set without the test seams` };
72
+ let keychain = openKeychainBackend();
73
+ return keychain ? { backend: keychain } : { backend: null, unavailable: "no OS keychain is usable on this machine" };
74
+ }
75
+
76
+ // src/main/cli/remotes.ts
77
+ var REMOTES_FILENAME = "cli-remotes.json", REMOTE_TOKENS_FILENAME = "cli-remote-tokens.json", REMOTE_ENV = "ADF_REMOTE";
78
+ function remotesPath(env) {
79
+ return join(daemonSettingsDir(env), REMOTES_FILENAME);
80
+ }
81
+ function tokensPath(env) {
82
+ return join(daemonSettingsDir(env), REMOTE_TOKENS_FILENAME);
83
+ }
84
+ function isRecord(value) {
85
+ return !!value && typeof value == "object" && !Array.isArray(value);
86
+ }
87
+ var RemotesUnreadableError = class extends Error {
88
+ constructor(path, why) {
89
+ super(`${why}. Fix or remove it; nothing was changed.`);
90
+ this.path = path;
91
+ this.why = why;
92
+ this.name = "RemotesUnreadableError";
93
+ }
94
+ path;
95
+ why;
96
+ };
97
+ function emptyRemotes() {
98
+ return { v: 1, default: null, remotes: {} };
99
+ }
100
+ function stripBom(text) {
101
+ return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
102
+ }
103
+ function errorText(err) {
104
+ return err instanceof Error ? err.message : String(err);
105
+ }
106
+ var rawOfRead = /* @__PURE__ */ new WeakMap();
107
+ function readOf(path, text, readError) {
108
+ let none = (unreadable) => ({ file: emptyRemotes(), names: /* @__PURE__ */ new Set(), unreadable, malformed: [], malformedDefault: null });
109
+ if (text === null)
110
+ return readError?.code === "ENOENT" ? none(null) : none(`${path} cannot be read (${errorText(readError)})`);
111
+ let raw;
112
+ try {
113
+ raw = JSON.parse(stripBom(text));
114
+ } catch (err) {
115
+ return none(`${path} is not valid JSON (${errorText(err)})`);
116
+ }
117
+ if (!isRecord(raw) || raw.v !== 1 || !isRecord(raw.remotes)) return none(`${path} is not a saved-connections file (v 1)`);
118
+ let file = parseRemotes(text), order = Object.keys(raw.remotes), malformed = Object.fromEntries(Object.entries(raw.remotes).filter(([name]) => !file.remotes[name])), malformedDefault = typeof raw.default == "string" && raw.default in malformed ? raw.default : null, read = { file, names: new Set(order), unreadable: null, malformed: Object.keys(malformed), malformedDefault };
119
+ return rawOfRead.set(read, { malformed, order, default: raw.default ?? null }), read;
120
+ }
121
+ function rawOf(file, raw, malformed, parsedDefault) {
122
+ let remotes = {};
123
+ for (let name of raw.order)
124
+ file.remotes[name] ? remotes[name] = file.remotes[name] : name in malformed && (remotes[name] = malformed[name]);
125
+ for (let [name, remote] of Object.entries(file.remotes)) name in remotes || (remotes[name] = remote);
126
+ let keepRawDefault = file.default === parsedDefault && typeof raw.default == "string" && raw.default in malformed && raw.default in remotes;
127
+ return { ...file, default: keepRawDefault ? raw.default : file.default, remotes };
128
+ }
129
+ function readRemotes(env = process.env) {
130
+ let path = remotesPath(env);
131
+ try {
132
+ return readOf(path, readFileSync2(path, "utf-8"));
133
+ } catch (err) {
134
+ return readOf(path, null, err);
135
+ }
136
+ }
137
+ async function readRemotesAsync(env = process.env) {
138
+ let path = remotesPath(env), text;
139
+ try {
140
+ text = await readFile(path, "utf-8");
141
+ } catch (err) {
142
+ return readOf(path, null, err);
143
+ }
144
+ return readOf(path, text);
145
+ }
146
+ function loadRemotes(env = process.env) {
147
+ return readRemotes(env).file;
148
+ }
149
+ function parseRemotes(text) {
150
+ let empty = emptyRemotes();
151
+ try {
152
+ let raw = JSON.parse(stripBom(text));
153
+ if (!isRecord(raw) || raw.v !== 1 || !isRecord(raw.remotes)) return empty;
154
+ let remotes = {};
155
+ for (let [name, r] of Object.entries(raw.remotes))
156
+ isRecord(r) && typeof r.url == "string" && typeof r.fingerprint == "string" && typeof r.deviceId == "string" && (remotes[name] = {
157
+ url: r.url,
158
+ fingerprint: r.fingerprint,
159
+ deviceId: r.deviceId,
160
+ label: typeof r.label == "string" ? r.label : "",
161
+ pairedAt: typeof r.pairedAt == "string" ? r.pairedAt : "",
162
+ ...typeof r.hostName == "string" ? { hostName: r.hostName } : {}
163
+ });
164
+ return { v: 1, default: typeof raw.default == "string" && remotes[raw.default] ? raw.default : null, remotes };
165
+ } catch {
166
+ return empty;
167
+ }
168
+ }
169
+ function writeJson(path, value) {
170
+ writeSecretFileAtomic(path, `${JSON.stringify(value, null, 2)}
171
+ `);
172
+ }
173
+ var REMOTES_LOCK_STALE_MS = 1e4, REMOTES_LOCK_WAIT_MS = 5e3, RemotesLockedError = class extends Error {
174
+ constructor(path) {
175
+ super(`${path} is locked by another program; try again.`);
176
+ this.path = path;
177
+ this.name = "RemotesLockedError";
178
+ }
179
+ path;
180
+ };
181
+ function remotesFilePath(env = process.env) {
182
+ return remotesPath(env);
183
+ }
184
+ async function updateRemotes(env, mutate, opts = {}) {
185
+ let path = remotesPath(env), lock = `${path}.lock`, staleMs = opts.staleMs ?? REMOTES_LOCK_STALE_MS, deadline = Date.now() + (opts.waitMs ?? REMOTES_LOCK_WAIT_MS), openLock = opts.openLock ?? open, busy = (err) => {
186
+ let code = err?.code;
187
+ return code === "EEXIST" || (opts.platform ?? process.platform) === "win32" && code === "EPERM";
188
+ }, mine = `${process.pid} ${randomBytes(8).toString("hex")}`, ageOf = (file) => stat(file).then((s) => Date.now() - s.mtimeMs, () => null), takeOver = async () => {
189
+ let claim = `${lock}.claim`;
190
+ try {
191
+ await (await openLock(claim, "wx")).close();
192
+ } catch (err) {
193
+ if (!busy(err)) throw err;
194
+ let age = await ageOf(claim);
195
+ age !== null && age > staleMs && await unlink(claim).catch(() => {
196
+ });
197
+ return;
198
+ }
199
+ try {
200
+ let age = await ageOf(lock);
201
+ if (age === null || age <= staleMs) return;
202
+ let tomb = `${lock}.${process.pid}.${randomBytes(4).toString("hex")}.stale`;
203
+ try {
204
+ await rename(lock, tomb);
205
+ } catch {
206
+ return;
207
+ }
208
+ let tombAge = await ageOf(tomb);
209
+ tombAge !== null && tombAge <= staleMs && await link(tomb, lock).catch(() => {
210
+ }), await unlink(tomb).catch(() => {
211
+ });
212
+ } finally {
213
+ await unlink(claim).catch(() => {
214
+ });
215
+ }
216
+ };
217
+ for (await import("node:fs/promises").then((fs) => fs.mkdir(daemonSettingsDir(env), { recursive: !0 })); ; )
218
+ try {
219
+ let handle = await openLock(lock, "wx");
220
+ await handle.writeFile(`${mine}
221
+ `), await handle.close();
222
+ break;
223
+ } catch (err) {
224
+ if (!busy(err)) throw err;
225
+ if (err.code === "EPERM") {
226
+ if (Date.now() > deadline) throw new RemotesLockedError(path);
227
+ await new Promise((r) => setTimeout(r, 25));
228
+ continue;
229
+ }
230
+ let age = await ageOf(lock);
231
+ if (age !== null && age > staleMs) {
232
+ await opts.onStaleSeen?.(), await takeOver();
233
+ continue;
234
+ }
235
+ if (Date.now() > deadline) throw new RemotesLockedError(path);
236
+ await new Promise((r) => setTimeout(r, 25));
237
+ }
238
+ try {
239
+ let read = await readRemotesAsync(env);
240
+ if (read.unreadable) throw new RemotesUnreadableError(path, read.unreadable);
241
+ let file = read.file;
242
+ read.malformedDefault && (file.default = read.malformedDefault);
243
+ let raw = rawOfRead.get(read) ?? { malformed: {}, order: [], default: null }, malformed = { ...raw.malformed }, parsedDefault = file.default, before = JSON.stringify([file, malformed]), result = await mutate(file, malformed);
244
+ if (JSON.stringify([file, malformed]) !== before) {
245
+ let out = rawOf(file, raw, malformed, parsedDefault);
246
+ for (; ; )
247
+ try {
248
+ writeJson(path, out);
249
+ break;
250
+ } catch (err) {
251
+ let code = err?.code;
252
+ if ((opts.platform ?? process.platform) !== "win32" || code !== "EPERM" && code !== "EBUSY" || Date.now() > deadline) throw err;
253
+ await new Promise((r) => setTimeout(r, 25));
254
+ }
255
+ }
256
+ return result;
257
+ } finally {
258
+ (await readFile(lock, "utf8").catch(() => null))?.trim() === mine && await unlink(lock).catch(() => {
259
+ });
260
+ }
261
+ }
262
+ var account = (fingerprint) => `remote-token:${fingerprint}`;
263
+ function readTokenFile(env) {
264
+ try {
265
+ let raw = JSON.parse(readFileSync2(tokensPath(env), "utf-8"));
266
+ return isRecord(raw) ? Object.fromEntries(Object.entries(raw).filter((e) => typeof e[1] == "string")) : {};
267
+ } catch {
268
+ return {};
269
+ }
270
+ }
271
+ var KEYCHAIN_FILE_COPY = {
272
+ title: "Keychain unavailable",
273
+ message: "The token can be saved in a file only you can read.",
274
+ ok: "Save to file",
275
+ cancel: "Cancel",
276
+ prompt: "Save to file? [y/N] "
277
+ }, TokenNotStoredError = class extends Error {
278
+ constructor(why) {
279
+ super(`The token was not saved (${why}).`);
280
+ this.why = why;
281
+ this.name = "TokenNotStoredError";
282
+ }
283
+ why;
284
+ };
285
+ async function storeRemoteToken(fingerprint, token, env, confirmFile) {
286
+ let secrets = openDaemonSecrets(env), why = secrets.unavailable ?? "no OS keychain";
287
+ if (secrets.backend)
288
+ try {
289
+ return secrets.backend.set(account(fingerprint), token), { where: "keychain", why: null, path: null };
290
+ } catch (err) {
291
+ why = `the OS keychain refused it: ${err instanceof Error ? err.message : String(err)}`;
292
+ }
293
+ if (!confirmFile || !await confirmFile(why).catch(() => !1)) throw new TokenNotStoredError(why);
294
+ return storeInFile(fingerprint, token, env, why);
295
+ }
296
+ function storeInFile(fingerprint, token, env, why) {
297
+ let path = tokensPath(env);
298
+ return writeJson(path, { ...readTokenFile(env), [account(fingerprint)]: token }), { where: "file", why, path };
299
+ }
300
+ function readRemoteToken(fingerprint, env = process.env) {
301
+ let secrets = openDaemonSecrets(env);
302
+ if (secrets.backend)
303
+ try {
304
+ let value = secrets.backend.get(account(fingerprint));
305
+ if (value) return value;
306
+ } catch {
307
+ }
308
+ return readTokenFile(env)[account(fingerprint)] ?? null;
309
+ }
310
+ function deleteRemoteToken(fingerprint, env = process.env) {
311
+ let secrets = openDaemonSecrets(env);
312
+ try {
313
+ secrets.backend?.delete(account(fingerprint));
314
+ } catch {
315
+ }
316
+ let tokens = readTokenFile(env);
317
+ account(fingerprint) in tokens && (delete tokens[account(fingerprint)], writeJson(tokensPath(env), tokens));
318
+ }
319
+ function malformedRemoteSentence(path, name) {
320
+ return `"${name}" in ${path} is malformed and is not used; fix it, or remove it with: adf remotes forget ${name}`;
321
+ }
322
+ var RemoteMalformedError = class extends Error {
323
+ constructor(path, remoteName) {
324
+ super(malformedRemoteSentence(path, remoteName));
325
+ this.path = path;
326
+ this.remoteName = remoteName;
327
+ this.name = "RemoteMalformedError";
328
+ }
329
+ path;
330
+ remoteName;
331
+ };
332
+ async function forgetRemote(env, name) {
333
+ let removed = await updateRemotes(env, (file, malformed) => {
334
+ let remote = file.remotes[name];
335
+ if (!remote)
336
+ return name in malformed ? (delete malformed[name], file.default === name && (file.default = null), { remote: null, sharedWith: null }) : null;
337
+ delete file.remotes[name], file.default === name && (file.default = null);
338
+ let sharedWith = Object.entries(file.remotes).find(([, r]) => r.fingerprint === remote.fingerprint)?.[0] ?? Object.entries(malformed).find(([, r]) => isRecord(r) && r.fingerprint === remote.fingerprint)?.[0] ?? null;
339
+ return { remote, sharedWith };
340
+ });
341
+ if (!removed) return null;
342
+ let tokenError = null;
343
+ if (removed.remote && !removed.sharedWith)
344
+ try {
345
+ deleteRemoteToken(removed.remote.fingerprint, env);
346
+ } catch (err) {
347
+ tokenError = errorText(err);
348
+ }
349
+ return { ...removed, tokenError };
350
+ }
351
+ function selectedRemote(env = process.env) {
352
+ let chosen = env[REMOTE_ENV]?.trim();
353
+ if (chosen === "local" || !chosen && !existsSync2(remotesPath(env))) return null;
354
+ let read = readRemotes(env);
355
+ if (read.unreadable) throw new RemotesUnreadableError(remotesPath(env), read.unreadable);
356
+ let file = read.file;
357
+ if (chosen) {
358
+ let remote = file.remotes[chosen];
359
+ if (!remote && read.malformed.includes(chosen)) throw new RemoteMalformedError(remotesPath(env), chosen);
360
+ if (!remote) throw new Error(`No saved remote named "${chosen}". List them with: adf remotes`);
361
+ return { name: chosen, remote };
362
+ }
363
+ if (read.malformedDefault) throw new RemoteMalformedError(remotesPath(env), read.malformedDefault);
364
+ return file.default ? { name: file.default, remote: file.remotes[file.default] } : null;
365
+ }
366
+ function sameOrigin(a, b) {
367
+ try {
368
+ return new URL(a).origin === new URL(b).origin;
369
+ } catch {
370
+ return !1;
371
+ }
372
+ }
373
+ function savedRemoteToken(url, env = process.env) {
374
+ if (!existsSync2(remotesPath(env))) return;
375
+ let file = loadRemotes(env);
376
+ for (let remote of Object.values(file.remotes))
377
+ if (sameOrigin(remote.url, url)) return readRemoteToken(remote.fingerprint, env) ?? void 0;
378
+ }
379
+ function savedRemoteFor(url, env = process.env) {
380
+ if (!existsSync2(remotesPath(env))) return null;
381
+ for (let [name, remote] of Object.entries(loadRemotes(env).remotes))
382
+ if (sameOrigin(remote.url, url)) return { name, remote };
383
+ return null;
384
+ }
385
+ async function pinnedRemoteRefusal(url, env, fetchImpl, wait = {}) {
386
+ let saved = savedRemoteFor(url, env);
387
+ if (!saved) return null;
388
+ let token = readRemoteToken(saved.remote.fingerprint, env), { fetchHello, helloRefusal, rateLimitedSentence, verifyHello } = await import("./remote-hello-UFWUBDQI.mjs"), host = `"${saved.name}" (${saved.remote.hostName ?? saved.remote.url})`, ask = () => token ? verifyHello(url, token, { fetch: fetchImpl }) : fetchHello(url, fetchImpl).then((hello) => hello ? { kind: "verified", hello } : { kind: "none" }), check = await ask();
389
+ for (let attempt = 0; check.kind === "rate_limited"; attempt++) {
390
+ if (attempt >= (wait.retries ?? 0))
391
+ return wait.retries ? `${host} is rate-limiting connections; try again in ${Math.ceil(check.retryAfterMs / 1e3)} s.` : rateLimitedSentence(host);
392
+ wait.onWait?.(rateLimitedSentence(host)), await (wait.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))))(check.retryAfterMs), check = await ask();
393
+ }
394
+ return check.kind === "none" ? `${url} did not answer as ${host}: it is down, its remote access is off, or another program answers there. The saved token was not sent.` : check.kind !== "not_device_token" && check.hello.fingerprint !== saved.remote.fingerprint ? `The ADF daemon at ${url} is not ${host}: it shows fingerprint ${check.hello.fingerprint}, and ${saved.remote.fingerprint} was saved when you paired. The saved token was not sent. If that computer was set up again, pair it again: adf remotes forget ${saved.name}, then adf pair ${url}.` : helloRefusal(check, host, url);
395
+ }
396
+ function remoteNameFor(hostName, taken) {
397
+ let base = hostName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32) || "remote", name = base;
398
+ for (let i = 2; taken[name]; i++) name = `${base}-${i}`;
399
+ return name;
400
+ }
401
+
402
+ // src/main/cli/daemon-url.ts
403
+ var daemon_url_exports = {};
404
+ __export(daemon_url_exports, {
405
+ DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT,
406
+ DEFAULT_DAEMON_URL: () => DEFAULT_DAEMON_URL,
407
+ daemonCredentials: () => daemonCredentials,
408
+ isLocalDaemonUrl: () => isLocalDaemonUrl,
409
+ isLocalOnlyRoute: () => isLocalOnlyRoute,
410
+ localDaemonToken: () => localDaemonToken,
411
+ localProofHeaders: () => localProofHeaders,
412
+ loopbackPort: () => loopbackPort,
413
+ resolveDaemonToken: () => resolveDaemonToken,
414
+ resolveDaemonUrl: () => resolveDaemonUrl,
415
+ tunnelTokenHint: () => tunnelTokenHint
416
+ });
417
+ import { readFileSync as readFileSync3 } from "node:fs";
418
+ import { join as join2 } from "node:path";
419
+ var DEFAULT_DAEMON_PORT = 7385, DEFAULT_DAEMON_URL = `http://127.0.0.1:${DEFAULT_DAEMON_PORT}`;
420
+ function resolveDaemonUrl(explicit, env = process.env) {
421
+ return (explicit ?? env.ADF_DAEMON_URL ?? selectedRemote(env)?.remote.url ?? DEFAULT_DAEMON_URL).replace(/\/+$/, "");
422
+ }
423
+ function loopbackPort(url) {
424
+ try {
425
+ let parsed = new URL(url), host = parsed.hostname.replace(/^\[|\]$/g, "").toLowerCase();
426
+ return host === "localhost" || host === "::1" || /^127\./.test(host) ? parsed.port ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80 : null;
427
+ } catch {
428
+ return null;
429
+ }
430
+ }
431
+ function pidFileAlive(file) {
432
+ try {
433
+ let raw = readFileSync3(file, "utf-8").trim(), pid = raw.startsWith("{") ? JSON.parse(raw).pid : Number.parseInt(raw, 10);
434
+ if (typeof pid != "number" || !Number.isFinite(pid) || pid <= 0) return !1;
435
+ try {
436
+ return process.kill(pid, 0), !0;
437
+ } catch (err) {
438
+ return err?.code === "EPERM";
439
+ }
440
+ } catch {
441
+ return !1;
442
+ }
443
+ }
444
+ function isLocalDaemonUrl(url, env = process.env) {
445
+ let port = loopbackPort(url);
446
+ return port === null ? !1 : port === DEFAULT_DAEMON_PORT || port === Number(env.ADF_DAEMON_PORT) ? !0 : pidFileAlive(join2(daemonSettingsDir(env), `adf-daemon-${port}.pid`));
447
+ }
448
+ function localDaemonToken(url, env = process.env) {
449
+ if (isLocalDaemonUrl(url, env))
450
+ return readDaemonToken(daemonSettingsDir(env)) ?? void 0;
451
+ }
452
+ function tunnelTokenHint(url, explicit, env = process.env) {
453
+ return explicit || env.ADF_DAEMON_TOKEN || loopbackPort(url) === null || isLocalDaemonUrl(url, env) ? null : `${url} is not this machine's daemon port (${Number(env.ADF_DAEMON_PORT) || DEFAULT_DAEMON_PORT}; e.g. an SSH tunnel), so the local token is not sent there. Pass --token or set ADF_DAEMON_TOKEN to the remote daemon's token (print it on that host with: adf daemon token).`;
454
+ }
455
+ function resolveDaemonToken(explicit, env = process.env, url) {
456
+ let token = explicit ?? env.ADF_DAEMON_TOKEN;
457
+ if (token) return token;
458
+ if (url)
459
+ return savedRemoteToken(url, env) ?? localDaemonToken(url, env);
460
+ }
461
+ function localProofHeaders(url, path, env = process.env) {
462
+ if (!isLocalOnlyRoute(path) || !isLocalDaemonUrl(url, env)) return {};
463
+ let proof = readLocalProof(daemonSettingsDir(env), loopbackPort(url) ?? DEFAULT_DAEMON_PORT);
464
+ return proof ? { "X-ADF-Local-Proof": proof } : {};
465
+ }
466
+ function daemonCredentials(url, options = {}) {
467
+ let env = options.env ?? process.env, token = resolveDaemonToken(options.token, env, options.localToken ? url : void 0), pinned = !!options.localToken && !options.token && !env.ADF_DAEMON_TOKEN && savedRemoteFor(url, env) !== null, fetchImpl = options.fetch ?? fetch, proved = null;
468
+ return {
469
+ token: () => token,
470
+ ...pinned ? { ready: () => {
471
+ proved ??= pinnedRemoteRefusal(url, env, fetchImpl).then((refusal) => {
472
+ if (refusal) throw new Error(refusal);
473
+ });
474
+ let check = proved;
475
+ return check.catch((err) => {
476
+ throw proved === check && (proved = null), err;
477
+ });
478
+ }, dropped: () => {
479
+ proved = null;
480
+ } } : {},
481
+ // The daemon answered 401: pick up a token file that appeared or changed
482
+ // since (daemon first start). localDaemonToken is null for any URL that is
483
+ // not this machine's daemon, so a remote URL never gets the local token.
484
+ refresh: () => {
485
+ if (!options.localToken || options.token || env.ADF_DAEMON_TOKEN) return !1;
486
+ let fresh = localDaemonToken(url, env);
487
+ return !fresh || fresh === token ? !1 : (token = fresh, !0);
488
+ },
489
+ localProof: (path) => options.localToken ? localProofHeaders(url, path, env) : {}
490
+ };
491
+ }
492
+
493
+ export {
494
+ RemotesUnreadableError,
495
+ readRemotes,
496
+ remotesFilePath,
497
+ updateRemotes,
498
+ KEYCHAIN_FILE_COPY,
499
+ storeRemoteToken,
500
+ readRemoteToken,
501
+ deleteRemoteToken,
502
+ malformedRemoteSentence,
503
+ RemoteMalformedError,
504
+ forgetRemote,
505
+ pinnedRemoteRefusal,
506
+ remoteNameFor,
507
+ DEFAULT_DAEMON_PORT,
508
+ DEFAULT_DAEMON_URL,
509
+ resolveDaemonUrl,
510
+ loopbackPort,
511
+ isLocalDaemonUrl,
512
+ localDaemonToken,
513
+ tunnelTokenHint,
514
+ resolveDaemonToken,
515
+ localProofHeaders,
516
+ daemon_url_exports
517
+ };