@agentdocumentformat/cli 0.7.8 → 0.8.1
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 +1 -1
- package/dist/adf.mjs +59 -8
- package/dist/chunks/{APEv2Parser-2CNNHMXV.mjs → APEv2Parser-WIXRJLHB.mjs} +2 -2
- package/dist/chunks/{AiffParser-7BR4RL6G.mjs → AiffParser-ZC4QFOVJ.mjs} +5 -5
- package/dist/chunks/{App-7RIIOHJJ.mjs → App-4AZZJNN2.mjs} +917 -826
- package/dist/chunks/{DsdiffParser-CMD4AX7A.mjs → DsdiffParser-UAPAJHFX.mjs} +5 -5
- package/dist/chunks/{DsfParser-UOGZDS2M.mjs → DsfParser-NNYZK2QX.mjs} +6 -6
- package/dist/chunks/{FlacParser-HB3T3CD4.mjs → FlacParser-MW2W4LO3.mjs} +6 -6
- package/dist/chunks/{MP4Parser-66HBRUSX.mjs → MP4Parser-Z57SYOOQ.mjs} +4 -4
- package/dist/chunks/{MpegParser-YW6LIUEW.mjs → MpegParser-XIIPAZVM.mjs} +7 -7
- package/dist/chunks/{MusepackParser-PAUSXP7D.mjs → MusepackParser-QWNDEYHJ.mjs} +6 -6
- package/dist/chunks/{OggParser-NUBV3GWC.mjs → OggParser-WRX53F77.mjs} +9 -9
- package/dist/chunks/{WavPackParser-WQAGT7TC.mjs → WavPackParser-MJ7WCSJ5.mjs} +2 -2
- package/dist/chunks/{WaveParser-EWLQVDX4.mjs → WaveParser-RAVLHZ5S.mjs} +7 -7
- package/dist/chunks/{adf-schema-US4NFHMR.mjs → adf-schema-AIPBQTR2.mjs} +9 -3
- package/dist/chunks/auth-manager-AJ32FZWS.mjs +19 -0
- package/dist/chunks/auth-manager-C5OBEQK2.mjs +18 -0
- package/dist/chunks/auth-manager-TBNKCJ45.mjs +17 -0
- package/dist/chunks/{chatgpt-subscription-E4MXTIAT.mjs → chatgpt-subscription-MMGNW5KJ.mjs} +5 -2
- package/dist/chunks/chunk-2Z7X3UUR.mjs +678 -0
- package/dist/chunks/chunk-3UGZFWIF.mjs +26 -0
- package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
- package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-7JZXMDDF.mjs} +158 -67
- package/dist/chunks/chunk-AEAJDCVK.mjs +517 -0
- package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
- package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-BR3AD5QZ.mjs} +8 -2
- package/dist/chunks/chunk-BS3USVEA.mjs +301 -0
- package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
- package/dist/chunks/chunk-D7A77SNL.mjs +976 -0
- package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
- package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
- package/dist/chunks/{chunk-G6PH7RPW.mjs → chunk-E7LC6SHP.mjs} +3 -3
- package/dist/chunks/{chunk-ZESQMP66.mjs → chunk-F3WSCAJD.mjs} +3 -3
- package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
- package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
- package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
- package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
- package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-IMVMSU3A.mjs} +251 -68
- package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
- package/dist/chunks/chunk-KCIRFUZH.mjs +12799 -0
- package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
- package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
- package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
- package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
- package/dist/chunks/{chunk-HSBV6YFU.mjs → chunk-LVF2DRBR.mjs} +634 -99
- package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
- package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
- package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
- package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
- package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
- package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
- package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
- package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
- package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-RHBGCOS3.mjs} +67 -26
- package/dist/chunks/{chunk-J74STFKE.mjs → chunk-RJDOVMM4.mjs} +362 -58
- package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-SOSPQPEN.mjs} +167 -650
- package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
- package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
- package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
- package/dist/chunks/chunk-VENQBMOA.mjs +62 -0
- package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
- package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
- package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-YRBFIDLB.mjs} +46 -10
- package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
- package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
- package/dist/chunks/claude-subscription-EB4LAAVV.mjs +29 -0
- package/dist/chunks/{cli-NMFIAR7Z.mjs → cli-PCVFB6B4.mjs} +797 -56
- package/dist/chunks/{commands-KPJWFRUE.mjs → commands-KOMPXJZS.mjs} +4 -3
- package/dist/chunks/{daemon-YDIK3AAM.mjs → daemon-BVDB565V.mjs} +83142 -64424
- package/dist/chunks/daemon-control-MKN7G5M3.mjs +59 -0
- package/dist/chunks/{daemon-token-WRSULP7G.mjs → daemon-token-L5QKTHU5.mjs} +3 -1
- package/dist/chunks/{discord-DSP4HUWI.mjs → discord-IR62565M.mjs} +3 -52
- package/dist/chunks/{email-BRG7KUO2.mjs → email-KHHTJBDW.mjs} +4 -2
- package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
- package/dist/chunks/{layout-EPJQNFAI.mjs → layout-ECWGJF6M.mjs} +2 -2
- package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
- package/dist/chunks/{open-VAU7PXT6.mjs → open-3OR6WT4T.mjs} +6 -6
- package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
- package/dist/chunks/{pipeline-executor-O77NTGLP.mjs → pipeline-executor-DRYEEFDR.mjs} +6 -5
- package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
- package/dist/chunks/remote-access-cli-GLEEP7DI.mjs +268 -0
- package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
- package/dist/chunks/sdk-OJOAF4DP.mjs +30014 -0
- package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
- package/dist/chunks/{store-HUVDJPYN.mjs → store-55CQSAOX.mjs} +7 -3
- package/dist/chunks/tailscale-WLJATFMB.mjs +25 -0
- package/dist/chunks/{theme-SFE3JMA2.mjs → theme-HLBDTF6F.mjs} +1 -1
- package/dist/chunks/{themes-YLXLOIJF.mjs → themes-BQ72P446.mjs} +2 -2
- package/dist/chunks/{token-6G3HCMNX.mjs → token-6D22WECM.mjs} +20 -16
- package/dist/chunks/{token-util-UXYSDQIW.mjs → token-util-YF3ZWBZ4.mjs} +1 -2
- package/dist/chunks/{tui-UQJLK7XI.mjs → tui-RAUVFOYY.mjs} +21 -18
- package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
- package/dist/chunks/{whatsapp-AJMRQBT7.mjs → whatsapp-YJFFVN4Q.mjs} +9 -9
- package/package.json +1 -1
- package/dist/chunks/chunk-GKKCMXIZ.mjs +0 -94
- package/dist/chunks/chunk-IHDDCZBS.mjs +0 -112
- package/dist/chunks/chunk-KWFOS5WC.mjs +0 -41
- package/dist/chunks/chunk-UEZR2CNS.mjs +0 -65
- package/dist/chunks/chunk-VMHTYDH4.mjs +0 -172
- package/dist/chunks/chunk-Y2QA53AN.mjs +0 -259
- package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
- package/dist/chunks/{chunk-APRU6PHC.mjs → chunk-JZ7AQNPM.mjs} +3 -3
- package/dist/chunks/{telegram-2EFGKIVK.mjs → telegram-JYY2VDTI.mjs} +5 -5
|
@@ -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-BS3USVEA.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
|
+
};
|
|
@@ -17,19 +17,23 @@ __export(auth_flow_exports, {
|
|
|
17
17
|
AUTH_POLL_INTERVAL_MS: () => AUTH_POLL_INTERVAL_MS,
|
|
18
18
|
AUTH_PROVIDERS: () => AUTH_PROVIDERS,
|
|
19
19
|
AUTH_PROVIDER_LABELS: () => AUTH_PROVIDER_LABELS,
|
|
20
|
+
CLAUDE_AUTH_TIMEOUT_MS: () => CLAUDE_AUTH_TIMEOUT_MS,
|
|
20
21
|
RELAY_CALLBACK_TIMEOUT_MS: () => RELAY_CALLBACK_TIMEOUT_MS,
|
|
21
22
|
browserLaunchCommand: () => browserLaunchCommand,
|
|
22
23
|
daemonIsLocal: () => daemonIsLocal,
|
|
23
24
|
loginChatGpt: () => loginChatGpt,
|
|
25
|
+
loginClaude: () => loginClaude,
|
|
24
26
|
loginGrok: () => loginGrok,
|
|
25
27
|
normalizeAuthProvider: () => normalizeAuthProvider,
|
|
26
28
|
openBrowser: () => openBrowser,
|
|
29
|
+
submitClaudeCode: () => submitClaudeCode,
|
|
27
30
|
waitForAuth: () => waitForAuth
|
|
28
31
|
});
|
|
29
32
|
import { spawn as nodeSpawn } from "child_process";
|
|
30
|
-
var AUTH_PROVIDERS = ["chatgpt", "grok"], AUTH_PROVIDER_LABELS = {
|
|
33
|
+
var AUTH_PROVIDERS = ["chatgpt", "grok", "claude"], AUTH_PROVIDER_LABELS = {
|
|
31
34
|
chatgpt: "ChatGPT",
|
|
32
|
-
grok: "Grok"
|
|
35
|
+
grok: "Grok",
|
|
36
|
+
claude: "Claude"
|
|
33
37
|
}, RELAY_CALLBACK_TIMEOUT_MS = 300 * 1e3, AUTH_POLL_INTERVAL_MS = 2e3, LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
|
|
34
38
|
function normalizeAuthProvider(value) {
|
|
35
39
|
switch (value?.toLowerCase()) {
|
|
@@ -40,6 +44,9 @@ function normalizeAuthProvider(value) {
|
|
|
40
44
|
case "grok":
|
|
41
45
|
case "xai":
|
|
42
46
|
return "grok";
|
|
47
|
+
case "claude":
|
|
48
|
+
case "claude-code":
|
|
49
|
+
return "claude";
|
|
43
50
|
default:
|
|
44
51
|
return null;
|
|
45
52
|
}
|
|
@@ -63,7 +70,7 @@ function openBrowser(url, deps = {}) {
|
|
|
63
70
|
} catch {
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
|
-
var CANCELLED = { ok: !1, error: "Sign-in cancelled", cancelled: !0 };
|
|
73
|
+
var CLAUDE_AUTH_TIMEOUT_MS = 660 * 1e3, CANCELLED = { ok: !1, error: "Sign-in cancelled", cancelled: !0 };
|
|
67
74
|
function isRecord(value) {
|
|
68
75
|
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
69
76
|
}
|
|
@@ -107,6 +114,35 @@ async function loginGrok(deps, opts) {
|
|
|
107
114
|
let userCode = typeof data.userCode == "string" ? data.userCode : "", verificationUri = typeof data.verificationUriComplete == "string" && data.verificationUriComplete ? data.verificationUriComplete : typeof data.verificationUri == "string" ? data.verificationUri : "", expiresInSec = typeof data.expiresIn == "number" && data.expiresIn > 0 ? data.expiresIn : 900;
|
|
108
115
|
return opts.onStart({ userCode, verificationUri, expiresInSec, raw: data }), deps.signal?.aborted ? CANCELLED : (verificationUri && (deps.openBrowser ?? openBrowser)(verificationUri), waitForAuth(deps, "grok", expiresInSec * 1e3));
|
|
109
116
|
}
|
|
117
|
+
async function loginClaude(deps, opts) {
|
|
118
|
+
let before = await deps.request("GET", "/auth/claude/status");
|
|
119
|
+
if (isRecord(before) && before.installed === !1) {
|
|
120
|
+
let installUrl = typeof before.installUrl == "string" ? before.installUrl : "";
|
|
121
|
+
return { ok: !1, error: `Claude Code is not installed on the daemon host.${installUrl ? ` Install it from ${installUrl}, then sign in again.` : ""}`, notInstalled: !0, installUrl };
|
|
122
|
+
}
|
|
123
|
+
let data = await deps.request("POST", "/auth/claude/start"), url = isRecord(data) && typeof data.url == "string" ? data.url : "";
|
|
124
|
+
if (opts.onStart({ url, raw: data }), opts.wait === !1 && !deps.signal?.aborted) return { ok: !1, error: "Sign-in started; not waiting for it", detached: !0 };
|
|
125
|
+
let outcome = deps.signal?.aborted ? CANCELLED : await waitForClaude(deps);
|
|
126
|
+
return !outcome.ok && (outcome.cancelled || outcome.timedOut) && await deps.request("POST", "/auth/claude/cancel").catch(() => {
|
|
127
|
+
}), outcome;
|
|
128
|
+
}
|
|
129
|
+
async function submitClaudeCode(deps, code) {
|
|
130
|
+
await deps.request("POST", "/auth/claude/code", { code: code.trim() });
|
|
131
|
+
}
|
|
132
|
+
async function waitForClaude(deps) {
|
|
133
|
+
let sleep = deps.sleep ?? ((ms) => abortableSleep(ms, deps.signal)), deadline = Date.now() + CLAUDE_AUTH_TIMEOUT_MS;
|
|
134
|
+
for (; Date.now() < deadline; ) {
|
|
135
|
+
if (await sleep(AUTH_POLL_INTERVAL_MS), deps.signal?.aborted) return CANCELLED;
|
|
136
|
+
let status = await deps.request("GET", "/auth/claude/status");
|
|
137
|
+
if (deps.signal?.aborted) return CANCELLED;
|
|
138
|
+
if (isRecord(status) && status.flowPending !== !0) {
|
|
139
|
+
if (typeof status.flowError == "string" && status.flowError) return { ok: !1, error: status.flowError };
|
|
140
|
+
if (status.authenticated === !0) return { ok: !0, email: typeof status.email == "string" ? status.email : void 0, raw: status };
|
|
141
|
+
if (status.installed === !1) return { ok: !1, error: "Claude Code is not installed on the daemon host." };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return { ok: !1, error: "Timed out waiting for Claude sign-in", timedOut: !0 };
|
|
145
|
+
}
|
|
110
146
|
async function waitForAuth(deps, provider, timeoutMs) {
|
|
111
147
|
let sleep = deps.sleep ?? ((ms) => abortableSleep(ms, deps.signal)), deadline = Date.now() + timeoutMs;
|
|
112
148
|
for (; Date.now() < deadline; ) {
|
|
@@ -140,5 +176,7 @@ export {
|
|
|
140
176
|
openBrowser,
|
|
141
177
|
loginChatGpt,
|
|
142
178
|
loginGrok,
|
|
179
|
+
loginClaude,
|
|
180
|
+
submitClaudeCode,
|
|
143
181
|
auth_flow_exports
|
|
144
182
|
};
|
|
@@ -37,7 +37,11 @@ var START_IN_STATES = ["active", "idle", "hibernate"];
|
|
|
37
37
|
function resolveStartInState(config) {
|
|
38
38
|
return config.start_in_state ?? "active";
|
|
39
39
|
}
|
|
40
|
-
var DEFAULT_NEW_LOOP_TOOLS = ["loop_send", "loop_list", "sys_set_state"],
|
|
40
|
+
var DEFAULT_NEW_LOOP_TOOLS = ["loop_send", "loop_list", "sys_set_state"], MAX_SIDE_LOOPS = 16;
|
|
41
|
+
function hasLoopGoal(loop) {
|
|
42
|
+
return !!loop.goal?.trim();
|
|
43
|
+
}
|
|
44
|
+
var LOOP_PROHIBITED_TOOLS = ["sys_update_config", "loop_manage", "sys_create_adf"];
|
|
41
45
|
var META_PROTECTION_LEVELS = ["none", "readonly", "increment"], FILE_PROTECTION_LEVELS = ["read_only", "no_delete", "none"];
|
|
42
46
|
var DEFAULT_TOOLS = [
|
|
43
47
|
{ name: "fs_read", enabled: !0, visible: !0 },
|
|
@@ -141,7 +145,6 @@ var AGENT_DEFAULTS = {
|
|
|
141
145
|
provider: "",
|
|
142
146
|
model_id: "",
|
|
143
147
|
temperature: 0.7,
|
|
144
|
-
max_tokens: 4096,
|
|
145
148
|
vision: !1
|
|
146
149
|
},
|
|
147
150
|
context: {
|
|
@@ -288,10 +291,13 @@ export {
|
|
|
288
291
|
START_IN_STATES,
|
|
289
292
|
resolveStartInState,
|
|
290
293
|
DEFAULT_NEW_LOOP_TOOLS,
|
|
294
|
+
MAX_SIDE_LOOPS,
|
|
295
|
+
hasLoopGoal,
|
|
291
296
|
LOOP_PROHIBITED_TOOLS,
|
|
292
297
|
META_PROTECTION_LEVELS,
|
|
293
298
|
FILE_PROTECTION_LEVELS,
|
|
294
299
|
DEFAULT_TOOLS,
|
|
300
|
+
AUDIT_DEFAULTS,
|
|
295
301
|
AGENT_DEFAULTS,
|
|
296
302
|
getDefaultDocumentContent,
|
|
297
303
|
DEFAULT_MIND_CONTENT,
|