@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.
- 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-A5GUFCFJ.mjs} +279 -293
- 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-YJSGLMA4.mjs} +2 -2
- 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-3UGZFWIF.mjs +26 -0
- package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-4OGZFUKA.mjs} +126 -67
- package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-6XQZGYMK.mjs} +246 -67
- package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
- package/dist/chunks/chunk-AZYOXXVL.mjs +865 -0
- package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
- package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
- package/dist/chunks/chunk-C4GA5SI4.mjs +12799 -0
- package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
- package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
- package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-G6NBFYG5.mjs} +152 -824
- 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-JVPZIMXW.mjs +976 -0
- package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
- package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
- package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
- package/dist/chunks/{chunk-G6PH7RPW.mjs → chunk-LCMANRYY.mjs} +3 -3
- package/dist/chunks/{chunk-ZESQMP66.mjs → chunk-LGL6ML37.mjs} +3 -3
- package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
- package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
- 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-CD3ATSXE.mjs → chunk-NZO5O4VN.mjs} +1 -1
- 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-PRPTKMQW.mjs} +67 -26
- 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-V2T6NZX2.mjs +517 -0
- package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
- package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
- package/dist/chunks/chunk-WVTPPOKK.mjs +290 -0
- package/dist/chunks/{chunk-J74STFKE.mjs → chunk-WX6QCUWI.mjs} +272 -51
- package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
- package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-XT2BJUFC.mjs} +15 -6
- package/dist/chunks/{chunk-HSBV6YFU.mjs → chunk-YRMKSHW3.mjs} +614 -92
- package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
- package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
- package/dist/chunks/claude-subscription-33BMZB6I.mjs +29 -0
- package/dist/chunks/{cli-NMFIAR7Z.mjs → cli-I47IFDHJ.mjs} +797 -56
- package/dist/chunks/{commands-KPJWFRUE.mjs → commands-E4EQUHE5.mjs} +4 -3
- package/dist/chunks/{daemon-YDIK3AAM.mjs → daemon-FQ5BV3AP.mjs} +82058 -63958
- package/dist/chunks/daemon-control-L3CLG63P.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/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
- package/dist/chunks/{open-VAU7PXT6.mjs → open-TLGS2Z3Q.mjs} +4 -4
- package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
- package/dist/chunks/{pipeline-executor-O77NTGLP.mjs → pipeline-executor-FD4FBWQA.mjs} +6 -5
- package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
- package/dist/chunks/remote-access-cli-XXAPQWH6.mjs +268 -0
- package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
- package/dist/chunks/sdk-5FD2ZP7N.mjs +28422 -0
- package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
- package/dist/chunks/{store-HUVDJPYN.mjs → store-ZRN2WCFB.mjs} +6 -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-SPSPDADM.mjs} +17 -14
- 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/{telegram-2EFGKIVK.mjs → telegram-JYY2VDTI.mjs} +5 -5
|
@@ -0,0 +1,278 @@
|
|
|
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
|
+
|
|
8
|
+
// src/main/providers/claude-subscription/auth-manager.ts
|
|
9
|
+
import { execFile as execFile2, spawn } from "node:child_process";
|
|
10
|
+
|
|
11
|
+
// src/main/providers/claude-subscription/claude-code.ts
|
|
12
|
+
import { execFile } from "node:child_process";
|
|
13
|
+
import { access, readFile } from "node:fs/promises";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { delimiter, dirname, join } from "node:path";
|
|
16
|
+
var MIN_CLAUDE_CODE_VERSION = "2.1.248", CLAUDE_CODE_INSTALL_URL = "https://code.claude.com/docs/en/setup", isWindows = process.platform === "win32", exeName = isWindows ? "claude.exe" : "claude";
|
|
17
|
+
async function exists(path) {
|
|
18
|
+
try {
|
|
19
|
+
return await access(path), !0;
|
|
20
|
+
} catch {
|
|
21
|
+
return !1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function candidatePaths() {
|
|
25
|
+
let out = [], override = process.env.ADF_CLAUDE_CODE_PATH;
|
|
26
|
+
override && out.push(override);
|
|
27
|
+
let home = homedir();
|
|
28
|
+
out.push(join(home, ".local", "bin", exeName)), out.push(join(home, ".claude", "local", exeName)), isWindows || out.push("/opt/homebrew/bin/claude", "/usr/local/bin/claude");
|
|
29
|
+
for (let dir of (process.env.PATH ?? "").split(delimiter))
|
|
30
|
+
if (dir)
|
|
31
|
+
if (isWindows) {
|
|
32
|
+
out.push(join(dir, "claude.exe"));
|
|
33
|
+
let target = await resolveNpmShim(join(dir, "claude.cmd"));
|
|
34
|
+
target && out.push(target);
|
|
35
|
+
} else
|
|
36
|
+
out.push(join(dir, "claude"));
|
|
37
|
+
let appData = process.env.APPDATA;
|
|
38
|
+
isWindows && appData && out.push(join(appData, "npm", "node_modules", "@anthropic-ai", "claude-code", "bin", "claude.exe"));
|
|
39
|
+
let unique = [...new Set(out)], present = await Promise.all(unique.map(exists));
|
|
40
|
+
return unique.filter((_, i) => present[i]);
|
|
41
|
+
}
|
|
42
|
+
async function resolveNpmShim(shimPath) {
|
|
43
|
+
try {
|
|
44
|
+
let match = (await readFile(shimPath, "utf8")).match(/"%dp0%\\([^"]+?\.exe)"/i);
|
|
45
|
+
if (!match) return null;
|
|
46
|
+
let target = join(dirname(shimPath), match[1]);
|
|
47
|
+
return await exists(target) ? target : null;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function runVersion(path) {
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
execFile(path, ["--version"], { timeout: 15e3, windowsHide: !0 }, (err, stdout) => {
|
|
55
|
+
if (err) return resolve(null);
|
|
56
|
+
let match = String(stdout).match(/(\d+\.\d+\.\d+)/);
|
|
57
|
+
resolve(match ? match[1] : null);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function compareVersions(a, b) {
|
|
62
|
+
let pa = a.split(".").map(Number), pb = b.split(".").map(Number);
|
|
63
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
64
|
+
let d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
65
|
+
if (d !== 0) return d < 0 ? -1 : 1;
|
|
66
|
+
}
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
var cached = null, inflight = null, CACHE_MS = 6e4;
|
|
70
|
+
async function runProbe() {
|
|
71
|
+
let paths = await candidatePaths(), versions = await Promise.all(paths.map(runVersion)), install = null;
|
|
72
|
+
for (let i = 0; i < paths.length; i++) {
|
|
73
|
+
let version = versions[i];
|
|
74
|
+
version && (!install || compareVersions(version, install.version) > 0) && (install = { path: paths[i], version });
|
|
75
|
+
}
|
|
76
|
+
return install ? { found: !0, install, supported: compareVersions(install.version, MIN_CLAUDE_CODE_VERSION) >= 0 } : { found: !1 };
|
|
77
|
+
}
|
|
78
|
+
function probeClaudeCode(force = !1) {
|
|
79
|
+
if (!force && cached && Date.now() - cached.at < CACHE_MS) return Promise.resolve(cached.probe);
|
|
80
|
+
if (!force && inflight) return inflight;
|
|
81
|
+
let run = runProbe().then((probe) => (cached = { probe, at: Date.now() }, probe)).finally(() => {
|
|
82
|
+
inflight === run && (inflight = null);
|
|
83
|
+
});
|
|
84
|
+
return inflight = run, run;
|
|
85
|
+
}
|
|
86
|
+
async function requireClaudeCode() {
|
|
87
|
+
let probe = await probeClaudeCode();
|
|
88
|
+
if (!probe.found)
|
|
89
|
+
throw new Error(`Claude Code is not installed. Install it (${CLAUDE_CODE_INSTALL_URL}), then sign in with Claude.`);
|
|
90
|
+
if (!probe.supported)
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Claude Code ${probe.install.version} is installed; ADF needs ${MIN_CLAUDE_CODE_VERSION} or newer. Run \`claude update\`.`
|
|
93
|
+
);
|
|
94
|
+
return probe.install;
|
|
95
|
+
}
|
|
96
|
+
var CLAUDE_ENV_DENY = /^(CLAUDE_CODE_|ANTHROPIC_|CLAUDECODE$)/i;
|
|
97
|
+
function claudeCodeEnv(extra) {
|
|
98
|
+
let env = {};
|
|
99
|
+
for (let [k, v] of Object.entries(process.env))
|
|
100
|
+
v === void 0 || CLAUDE_ENV_DENY.test(k) || k.toUpperCase() === "ELECTRON_RUN_AS_NODE" || (env[k] = v);
|
|
101
|
+
return { ...env, ...extra };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/main/providers/claude-subscription/auth-manager.ts
|
|
105
|
+
var LOGIN_TIMEOUT_MS = 10 * 6e4, STATUS_CACHE_MS = 3e4;
|
|
106
|
+
function stripAnsi(s) {
|
|
107
|
+
return s.replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, "").replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "");
|
|
108
|
+
}
|
|
109
|
+
function extractLoginUrl(output) {
|
|
110
|
+
return output.match(/https:\/\/[^\s\u0007\u001b"']+\/oauth\/authorize\?[^\s\u0007\u001b"']+/)?.[0];
|
|
111
|
+
}
|
|
112
|
+
function runCli(path, args, timeoutMs = 2e4) {
|
|
113
|
+
return new Promise((resolve) => {
|
|
114
|
+
execFile2(path, args, { timeout: timeoutMs, windowsHide: !0, env: claudeCodeEnv() }, (err, stdout, stderr) => {
|
|
115
|
+
let code = err ? typeof err.code == "number" ? err.code : 1 : 0;
|
|
116
|
+
resolve({ stdout: String(stdout), stderr: String(stderr), code });
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
var ClaudeAuthManager = class {
|
|
121
|
+
active = null;
|
|
122
|
+
starting = null;
|
|
123
|
+
startGen = 0;
|
|
124
|
+
lastFlowError;
|
|
125
|
+
statusCache = null;
|
|
126
|
+
statusInflight = null;
|
|
127
|
+
statusGen = 0;
|
|
128
|
+
/**
|
|
129
|
+
* Claude Code's sign-in state. `claude auth status` is a process spawn and
|
|
130
|
+
* this is polled by every status view and agent preflight, so results are
|
|
131
|
+
* cached briefly and concurrent callers share one read. While a sign-in is
|
|
132
|
+
* pending nothing is cached. `fresh` re-detects Claude Code and re-reads.
|
|
133
|
+
*/
|
|
134
|
+
getAuthStatus(opts) {
|
|
135
|
+
let fresh = opts?.fresh === !0;
|
|
136
|
+
if (!fresh && !this.active && this.statusCache && Date.now() - this.statusCache.at < STATUS_CACHE_MS)
|
|
137
|
+
return Promise.resolve(this.statusCache.status);
|
|
138
|
+
if (!fresh && this.statusInflight) return this.statusInflight;
|
|
139
|
+
let gen = this.statusGen, run = this.readAuthStatus(fresh).then((status) => (gen === this.statusGen && !this.active && !("flowPending" in status && status.flowPending) && (this.statusCache = { status, at: Date.now() }), status)).finally(() => {
|
|
140
|
+
this.statusInflight === run && (this.statusInflight = null);
|
|
141
|
+
});
|
|
142
|
+
return this.statusInflight = run, run;
|
|
143
|
+
}
|
|
144
|
+
invalidateStatus() {
|
|
145
|
+
this.statusGen++, this.statusCache = null, this.statusInflight = null;
|
|
146
|
+
}
|
|
147
|
+
async readAuthStatus(fresh) {
|
|
148
|
+
let probe = await probeClaudeCode(fresh);
|
|
149
|
+
if (!probe.found)
|
|
150
|
+
return { authenticated: !1, installed: !1, installUrl: CLAUDE_CODE_INSTALL_URL };
|
|
151
|
+
let { version: installed, path } = probe.install, version = { version: installed, minVersion: MIN_CLAUDE_CODE_VERSION };
|
|
152
|
+
if (!probe.supported)
|
|
153
|
+
return {
|
|
154
|
+
authenticated: !1,
|
|
155
|
+
installed: !0,
|
|
156
|
+
...version,
|
|
157
|
+
updateRequired: !0,
|
|
158
|
+
flowError: `Claude Code ${installed} is installed; ADF needs ${MIN_CLAUDE_CODE_VERSION} or newer. Run \`claude update\`.`
|
|
159
|
+
};
|
|
160
|
+
let { stdout } = await runCli(path, ["auth", "status", "--json"]), pending = this.active ? { flowPending: !0, ...this.active.url ? { flowUrl: this.active.url } : {} } : {}, cli = {};
|
|
161
|
+
try {
|
|
162
|
+
cli = JSON.parse(stdout);
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
return cli.loggedIn ? cli.authMethod !== "claude.ai" ? {
|
|
166
|
+
authenticated: !1,
|
|
167
|
+
installed: !0,
|
|
168
|
+
...version,
|
|
169
|
+
...pending,
|
|
170
|
+
flowError: "Claude Code is signed in with an Anthropic Console account, not a Claude plan. Sign in with Claude to use your subscription."
|
|
171
|
+
} : {
|
|
172
|
+
authenticated: !0,
|
|
173
|
+
installed: !0,
|
|
174
|
+
...version,
|
|
175
|
+
...pending,
|
|
176
|
+
// A failed re-sign-in (e.g. switching accounts) leaves the old account
|
|
177
|
+
// signed in; report the failure so callers don't mistake it for success.
|
|
178
|
+
...this.lastFlowError ? { flowError: this.lastFlowError } : {},
|
|
179
|
+
...cli.email ? { email: cli.email } : {},
|
|
180
|
+
...cli.subscriptionType ? { plan: cli.subscriptionType } : {}
|
|
181
|
+
} : { authenticated: !1, installed: !0, ...version, ...pending, ...this.lastFlowError ? { flowError: this.lastFlowError } : {} };
|
|
182
|
+
}
|
|
183
|
+
async isAuthenticated() {
|
|
184
|
+
return (await this.getAuthStatus()).authenticated;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Start `claude auth login`. Claude Code opens the browser itself; the
|
|
188
|
+
* returned URL is the fallback for when it cannot (remote daemon, headless
|
|
189
|
+
* box). If the browser page shows a code instead of finishing on its own,
|
|
190
|
+
* the user pastes it and it is handed to Claude Code via `submitCode`.
|
|
191
|
+
*/
|
|
192
|
+
startAuthFlowDetached() {
|
|
193
|
+
if (this.active) return this.active.ready;
|
|
194
|
+
if (!this.starting) {
|
|
195
|
+
let starting = this.spawnFlow().finally(() => {
|
|
196
|
+
this.starting === starting && (this.starting = null);
|
|
197
|
+
});
|
|
198
|
+
this.starting = starting;
|
|
199
|
+
}
|
|
200
|
+
return this.starting;
|
|
201
|
+
}
|
|
202
|
+
async spawnFlow() {
|
|
203
|
+
let gen = this.startGen, { path } = await requireClaudeCode();
|
|
204
|
+
if (gen !== this.startGen) throw new Error("Claude sign-in was cancelled.");
|
|
205
|
+
this.lastFlowError = void 0;
|
|
206
|
+
let child = spawn(path, ["auth", "login", "--claudeai"], {
|
|
207
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
208
|
+
windowsHide: !0,
|
|
209
|
+
env: claudeCodeEnv()
|
|
210
|
+
}), resolveUrl, urlReady = new Promise((r) => {
|
|
211
|
+
resolveUrl = r;
|
|
212
|
+
}), state = { child, output: "", cancelled: !1, ready: void 0 }, onData = (d) => {
|
|
213
|
+
state.output += d.toString();
|
|
214
|
+
let url = extractLoginUrl(state.output);
|
|
215
|
+
url && (state.url ??= url, resolveUrl(url));
|
|
216
|
+
};
|
|
217
|
+
child.stdout.on("data", onData), child.stderr.on("data", onData);
|
|
218
|
+
let completion = new Promise((resolve, reject) => {
|
|
219
|
+
let timer = setTimeout(() => {
|
|
220
|
+
child.kill(), reject(new Error("Claude sign-in timed out. Try again."));
|
|
221
|
+
}, LOGIN_TIMEOUT_MS);
|
|
222
|
+
child.on("error", (err) => {
|
|
223
|
+
clearTimeout(timer), resolveUrl(void 0), reject(err);
|
|
224
|
+
}), child.on("exit", (code) => {
|
|
225
|
+
if (clearTimeout(timer), resolveUrl(void 0), code === 0) return resolve();
|
|
226
|
+
if (state.cancelled) return reject(new Error("Claude sign-in was cancelled."));
|
|
227
|
+
let tail = stripAnsi(state.output).trim().split(`
|
|
228
|
+
`).filter(Boolean).pop();
|
|
229
|
+
reject(new Error(tail && !/paste code/i.test(tail) ? `Claude sign-in failed: ${tail}` : "Claude sign-in was cancelled."));
|
|
230
|
+
});
|
|
231
|
+
}).then(
|
|
232
|
+
() => {
|
|
233
|
+
this.active === state && (this.active = null), this.invalidateStatus();
|
|
234
|
+
},
|
|
235
|
+
(err) => {
|
|
236
|
+
throw this.active === state && (this.active = null, state.cancelled || (this.lastFlowError = err instanceof Error ? err.message : String(err))), this.invalidateStatus(), err;
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
return completion.catch(() => {
|
|
240
|
+
}), state.ready = Promise.race([urlReady, new Promise((r) => setTimeout(() => r(void 0), 15e3))]).then((url) => ({ url, completion })), this.active = state, this.invalidateStatus(), state.ready;
|
|
241
|
+
}
|
|
242
|
+
async startAuthFlow() {
|
|
243
|
+
await (await this.startAuthFlowDetached()).completion;
|
|
244
|
+
}
|
|
245
|
+
/** Hand the code shown on Claude's sign-in page to the waiting Claude Code. */
|
|
246
|
+
submitCode(code) {
|
|
247
|
+
let trimmed = code.trim();
|
|
248
|
+
if (!this.active) throw new Error("No Claude sign-in is in progress.");
|
|
249
|
+
if (!trimmed) throw new Error("Paste the code shown on the Claude sign-in page.");
|
|
250
|
+
this.active.child.stdin.write(`${trimmed}
|
|
251
|
+
`);
|
|
252
|
+
}
|
|
253
|
+
cancelAuthFlow() {
|
|
254
|
+
this.startGen++, this.starting = null, this.active && (this.active.cancelled = !0, this.active.child.kill(), this.active = null), this.invalidateStatus();
|
|
255
|
+
}
|
|
256
|
+
/** Signs Claude Code out on this machine (shared with the user's own Claude Code use). */
|
|
257
|
+
async logout() {
|
|
258
|
+
this.cancelAuthFlow(), this.lastFlowError = void 0;
|
|
259
|
+
try {
|
|
260
|
+
let { path } = await requireClaudeCode(), { code, stderr } = await runCli(path, ["auth", "logout"]);
|
|
261
|
+
if (code !== 0) throw new Error(`Claude sign-out failed: ${stripAnsi(stderr).trim() || `exit ${code}`}`);
|
|
262
|
+
} finally {
|
|
263
|
+
this.invalidateStatus();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}, instance = null;
|
|
267
|
+
function getClaudeAuthManager() {
|
|
268
|
+
return instance || (instance = new ClaudeAuthManager()), instance;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export {
|
|
272
|
+
MIN_CLAUDE_CODE_VERSION,
|
|
273
|
+
requireClaudeCode,
|
|
274
|
+
claudeCodeEnv,
|
|
275
|
+
stripAnsi,
|
|
276
|
+
extractLoginUrl,
|
|
277
|
+
getClaudeAuthManager
|
|
278
|
+
};
|
|
@@ -71,6 +71,7 @@ var import_react = __toESM(require_react(), 1), ADF_COLORS = {
|
|
|
71
71
|
mark: "\u258C",
|
|
72
72
|
hbar: "\u2500",
|
|
73
73
|
ellipsis: "\u2026",
|
|
74
|
+
approx: "\u2248",
|
|
74
75
|
collapsed: "\u25B8",
|
|
75
76
|
expanded: "\u25BE",
|
|
76
77
|
spinner: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]
|
|
@@ -90,6 +91,7 @@ var import_react = __toESM(require_react(), 1), ADF_COLORS = {
|
|
|
90
91
|
mark: ">",
|
|
91
92
|
hbar: "-",
|
|
92
93
|
ellipsis: "...",
|
|
94
|
+
approx: "~",
|
|
93
95
|
collapsed: "+",
|
|
94
96
|
expanded: "-",
|
|
95
97
|
spinner: ["|", "/", "-", "\\"]
|
|
@@ -141,7 +141,6 @@ var AGENT_DEFAULTS = {
|
|
|
141
141
|
provider: "",
|
|
142
142
|
model_id: "",
|
|
143
143
|
temperature: 0.7,
|
|
144
|
-
max_tokens: 4096,
|
|
145
144
|
vision: !1
|
|
146
145
|
},
|
|
147
146
|
context: {
|
|
@@ -292,6 +291,7 @@ export {
|
|
|
292
291
|
META_PROTECTION_LEVELS,
|
|
293
292
|
FILE_PROTECTION_LEVELS,
|
|
294
293
|
DEFAULT_TOOLS,
|
|
294
|
+
AUDIT_DEFAULTS,
|
|
295
295
|
AGENT_DEFAULTS,
|
|
296
296
|
getDefaultDocumentContent,
|
|
297
297
|
DEFAULT_MIND_CONTENT,
|
|
@@ -32,7 +32,7 @@ function enabledAdapters(config) {
|
|
|
32
32
|
return Object.entries(config?.adapters ?? {}).filter(([, c]) => c?.enabled !== !1).map(([type]) => type);
|
|
33
33
|
}
|
|
34
34
|
function welcomeFacts(state, extras = EMPTY_EXTRAS) {
|
|
35
|
-
let auth = state.auth, signedIn =
|
|
35
|
+
let auth = state.auth, signedIn = ["chatgpt", "grok", "claude"].some((p) => !!auth?.[p]?.authenticated), keyed = (auth?.providers ?? []).some((p) => p.hasApiKey === !0), ids = state.agentOrder.filter((id) => state.agents[id]), messaging = ids.some((id) => enabledAdapters(state.agents[id]?.config).length > 0 || (extras.adapters[id]?.length ?? 0) > 0), tasks = ids.some((id) => {
|
|
36
36
|
let loops = state.agents[id]?.loops ?? [];
|
|
37
37
|
return loops.some((l) => l.info.name !== "main") || loops.some((l) => l.info.name === "main" && (l.info.entryCount ?? 0) > 0) ? !0 : (extras.timers[id] ?? 0) > 0;
|
|
38
38
|
});
|
|
@@ -0,0 +1,244 @@
|
|
|
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
|
+
createSubscriptionTokenStore
|
|
9
|
+
} from "./chunk-C2S64Y6F.mjs";
|
|
10
|
+
import {
|
|
11
|
+
__require
|
|
12
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
13
|
+
|
|
14
|
+
// src/main/providers/grok-subscription/token-store.ts
|
|
15
|
+
var store = createSubscriptionTokenStore("grok-subscription");
|
|
16
|
+
function readTokens() {
|
|
17
|
+
return store.readTokens();
|
|
18
|
+
}
|
|
19
|
+
function writeTokens(tokens) {
|
|
20
|
+
store.writeTokens(tokens);
|
|
21
|
+
}
|
|
22
|
+
function clearTokens() {
|
|
23
|
+
store.clearTokens();
|
|
24
|
+
}
|
|
25
|
+
function noteSignIn(accountId) {
|
|
26
|
+
store.signedIn(accountId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/main/providers/grok-subscription/auth-manager.ts
|
|
30
|
+
var CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828", DEVICE_AUTHORIZATION_URL = "https://auth.x.ai/oauth2/device/code", TOKEN_URL = "https://auth.x.ai/oauth2/token", DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code", SCOPE = "openid profile email offline_access grok-cli:access api:access", REFRESH_BUFFER_MS = 300 * 1e3, POLL_DEFAULT_INTERVAL_MS = 5e3, POLL_MIN_INTERVAL_MS = 1e3, POLL_SLOW_DOWN_INCREMENT_MS = 5e3, POLL_DEFAULT_EXPIRES_MS = 900 * 1e3;
|
|
31
|
+
function decodeJwtPayload(token) {
|
|
32
|
+
let parts = token.split(".");
|
|
33
|
+
if (parts.length < 2) return {};
|
|
34
|
+
try {
|
|
35
|
+
let payload = Buffer.from(parts[1], "base64url").toString("utf-8");
|
|
36
|
+
return JSON.parse(payload);
|
|
37
|
+
} catch {
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function openExternal(url) {
|
|
42
|
+
try {
|
|
43
|
+
let electron = __require("electron");
|
|
44
|
+
if (electron.shell?.openExternal) {
|
|
45
|
+
await electron.shell.openExternal(url);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
console.log(`[Grok Auth] Open this URL to sign in: ${url}`);
|
|
51
|
+
}
|
|
52
|
+
function positiveSecondsToMs(value, defaultMs) {
|
|
53
|
+
let seconds = Number(value);
|
|
54
|
+
return Number.isFinite(seconds) && seconds > 0 ? seconds * 1e3 : defaultMs;
|
|
55
|
+
}
|
|
56
|
+
async function pollDeviceCodeToken(device, deps = {}) {
|
|
57
|
+
let fetchFn = deps.fetchFn ?? globalThis.fetch, sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))), now = deps.now ?? (() => Date.now()), deadline = now() + positiveSecondsToMs(device.expires_in, POLL_DEFAULT_EXPIRES_MS), intervalMs = Math.max(
|
|
58
|
+
positiveSecondsToMs(device.interval, POLL_DEFAULT_INTERVAL_MS),
|
|
59
|
+
POLL_MIN_INTERVAL_MS
|
|
60
|
+
);
|
|
61
|
+
for (; now() < deadline; ) {
|
|
62
|
+
let response = await fetchFn(TOKEN_URL, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
65
|
+
body: new URLSearchParams({
|
|
66
|
+
grant_type: DEVICE_CODE_GRANT_TYPE,
|
|
67
|
+
client_id: CLIENT_ID,
|
|
68
|
+
device_code: device.device_code
|
|
69
|
+
}).toString()
|
|
70
|
+
});
|
|
71
|
+
if (response.ok) return await response.json();
|
|
72
|
+
let body = await response.json().catch(() => ({}));
|
|
73
|
+
if (body.error === "authorization_pending") {
|
|
74
|
+
await sleep(Math.min(intervalMs, Math.max(0, deadline - now())));
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (body.error === "slow_down") {
|
|
78
|
+
intervalMs += POLL_SLOW_DOWN_INCREMENT_MS, await sleep(Math.min(intervalMs, Math.max(0, deadline - now())));
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (body.error === "access_denied" || body.error === "authorization_denied")
|
|
82
|
+
throw new Error("Sign-in was denied");
|
|
83
|
+
if (body.error === "expired_token")
|
|
84
|
+
throw new Error("Device code expired \u2014 please sign in again");
|
|
85
|
+
let detail = body.error_description ?? body.error ?? "";
|
|
86
|
+
throw new Error(`Grok token exchange failed (${response.status})${detail ? `: ${detail}` : ""}`);
|
|
87
|
+
}
|
|
88
|
+
throw new Error("Sign-in timed out \u2014 please try again");
|
|
89
|
+
}
|
|
90
|
+
var GrokAuthManager = class {
|
|
91
|
+
refreshPromise = null;
|
|
92
|
+
cachedTokens = null;
|
|
93
|
+
email;
|
|
94
|
+
activeAuthFlow = null;
|
|
95
|
+
lastFlowError;
|
|
96
|
+
constructor() {
|
|
97
|
+
this.syncFromDisk();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Re-read the token file, picking up writes from the other process. Studio
|
|
101
|
+
* and the daemon share one file. See the ChatGPT manager for the full
|
|
102
|
+
* rationale on why this never trusts a cache.
|
|
103
|
+
*/
|
|
104
|
+
syncFromDisk() {
|
|
105
|
+
let tokens = readTokens();
|
|
106
|
+
return tokens?.access_token !== this.cachedTokens?.access_token && (this.email = void 0), this.cachedTokens = tokens, tokens;
|
|
107
|
+
}
|
|
108
|
+
persist(tokens) {
|
|
109
|
+
writeTokens(tokens), this.cachedTokens = tokens;
|
|
110
|
+
}
|
|
111
|
+
async startAuthFlow() {
|
|
112
|
+
await (await this.startAuthFlowDetached()).completion;
|
|
113
|
+
}
|
|
114
|
+
async startAuthFlowDetached() {
|
|
115
|
+
if (this.activeAuthFlow) return this.activeAuthFlow;
|
|
116
|
+
this.lastFlowError = void 0;
|
|
117
|
+
let response = await fetch(DEVICE_AUTHORIZATION_URL, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
120
|
+
body: new URLSearchParams({
|
|
121
|
+
client_id: CLIENT_ID,
|
|
122
|
+
scope: SCOPE,
|
|
123
|
+
referrer: "adf-studio"
|
|
124
|
+
}).toString()
|
|
125
|
+
});
|
|
126
|
+
if (!response.ok) {
|
|
127
|
+
let body = await response.text().catch(() => "");
|
|
128
|
+
throw new Error(`Grok device code request failed (${response.status})${body ? `: ${body}` : ""}`);
|
|
129
|
+
}
|
|
130
|
+
let device = await response.json();
|
|
131
|
+
if (!device.device_code || !device.user_code || !device.verification_uri)
|
|
132
|
+
throw new Error("Grok device code response is missing device_code / user_code / verification_uri");
|
|
133
|
+
let openUrl = device.verification_uri_complete ?? device.verification_uri;
|
|
134
|
+
await openExternal(openUrl);
|
|
135
|
+
let completion = (async () => {
|
|
136
|
+
try {
|
|
137
|
+
let tokenData = await pollDeviceCodeToken(device), accountId = "";
|
|
138
|
+
if (tokenData.id_token) {
|
|
139
|
+
let claims = decodeJwtPayload(tokenData.id_token);
|
|
140
|
+
this.email = claims.email, accountId = claims.sub ?? "";
|
|
141
|
+
}
|
|
142
|
+
if (accountId || (accountId = decodeJwtPayload(tokenData.access_token).sub ?? ""), !tokenData.refresh_token)
|
|
143
|
+
throw new Error("Grok sign-in did not return a refresh token \u2014 is offline_access granted?");
|
|
144
|
+
this.persist({
|
|
145
|
+
access_token: tokenData.access_token,
|
|
146
|
+
refresh_token: tokenData.refresh_token,
|
|
147
|
+
expires_at: Date.now() + positiveSecondsToMs(tokenData.expires_in, 3600 * 1e3),
|
|
148
|
+
account_id: accountId
|
|
149
|
+
}), noteSignIn(accountId);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
throw this.lastFlowError = err instanceof Error ? err.message : String(err), err;
|
|
152
|
+
} finally {
|
|
153
|
+
this.activeAuthFlow = null;
|
|
154
|
+
}
|
|
155
|
+
})();
|
|
156
|
+
return completion.catch(() => {
|
|
157
|
+
}), this.activeAuthFlow = {
|
|
158
|
+
userCode: device.user_code,
|
|
159
|
+
verificationUri: device.verification_uri,
|
|
160
|
+
verificationUriComplete: device.verification_uri_complete,
|
|
161
|
+
expiresIn: positiveSecondsToMs(device.expires_in, POLL_DEFAULT_EXPIRES_MS) / 1e3,
|
|
162
|
+
completion
|
|
163
|
+
}, this.activeAuthFlow;
|
|
164
|
+
}
|
|
165
|
+
async getValidAccessToken() {
|
|
166
|
+
let tokens = this.syncFromDisk();
|
|
167
|
+
if (!tokens)
|
|
168
|
+
throw new Error("Not authenticated \u2014 sign in first");
|
|
169
|
+
return Date.now() + REFRESH_BUFFER_MS < tokens.expires_at ? tokens.access_token : this.refreshPromise ? this.refreshPromise : (this.refreshPromise = this.refreshIfStillNeeded(tokens).finally(() => {
|
|
170
|
+
this.refreshPromise = null;
|
|
171
|
+
}), this.refreshPromise);
|
|
172
|
+
}
|
|
173
|
+
getAccountId() {
|
|
174
|
+
return this.syncFromDisk()?.account_id;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Re-check the file after winning the in-process refresh lock — Studio may
|
|
178
|
+
* have refreshed while this call queued, and xAI may rotate the refresh
|
|
179
|
+
* token, which would leave our copy dead.
|
|
180
|
+
*/
|
|
181
|
+
async refreshIfStillNeeded(tokens) {
|
|
182
|
+
let fresh = this.syncFromDisk();
|
|
183
|
+
return fresh && Date.now() + REFRESH_BUFFER_MS < fresh.expires_at ? fresh.access_token : this.refreshTokens(fresh ?? tokens);
|
|
184
|
+
}
|
|
185
|
+
async refreshTokens(tokens) {
|
|
186
|
+
let data, rejected = !1;
|
|
187
|
+
try {
|
|
188
|
+
let response = await fetch(TOKEN_URL, {
|
|
189
|
+
method: "POST",
|
|
190
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
191
|
+
body: new URLSearchParams({
|
|
192
|
+
grant_type: "refresh_token",
|
|
193
|
+
client_id: CLIENT_ID,
|
|
194
|
+
refresh_token: tokens.refresh_token
|
|
195
|
+
}).toString()
|
|
196
|
+
});
|
|
197
|
+
if (!response.ok)
|
|
198
|
+
throw rejected = response.status === 400 || response.status === 401, new Error(`Token refresh failed (${response.status})`);
|
|
199
|
+
data = await response.json();
|
|
200
|
+
} catch (err) {
|
|
201
|
+
let fresh = this.syncFromDisk();
|
|
202
|
+
if (fresh && fresh.refresh_token !== tokens.refresh_token && Date.now() + REFRESH_BUFFER_MS < fresh.expires_at)
|
|
203
|
+
return fresh.access_token;
|
|
204
|
+
throw rejected ? (clearTokens(), this.cachedTokens = null, this.email = void 0, new Error("Session expired \u2014 please sign in again")) : new Error(`Could not refresh the session (${err instanceof Error ? err.message : String(err)}) \u2014 still signed in, try again`);
|
|
205
|
+
}
|
|
206
|
+
if (data.id_token) {
|
|
207
|
+
let claims = decodeJwtPayload(data.id_token);
|
|
208
|
+
this.email = claims.email;
|
|
209
|
+
}
|
|
210
|
+
return this.persist({
|
|
211
|
+
access_token: data.access_token,
|
|
212
|
+
refresh_token: data.refresh_token || tokens.refresh_token,
|
|
213
|
+
expires_at: Date.now() + positiveSecondsToMs(data.expires_in, 3600 * 1e3),
|
|
214
|
+
account_id: tokens.account_id
|
|
215
|
+
}), data.access_token;
|
|
216
|
+
}
|
|
217
|
+
getAuthStatus() {
|
|
218
|
+
let tokens = this.syncFromDisk();
|
|
219
|
+
return tokens ? {
|
|
220
|
+
authenticated: !0,
|
|
221
|
+
email: this.email,
|
|
222
|
+
expiresAt: tokens.expires_at
|
|
223
|
+
} : {
|
|
224
|
+
authenticated: !1,
|
|
225
|
+
flowPending: this.activeAuthFlow !== null,
|
|
226
|
+
flowError: this.lastFlowError
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
isAuthenticated() {
|
|
230
|
+
return this.syncFromDisk() !== null;
|
|
231
|
+
}
|
|
232
|
+
logout() {
|
|
233
|
+
clearTokens(), this.cachedTokens = null, this.email = void 0, this.refreshPromise = null, this.lastFlowError = void 0;
|
|
234
|
+
}
|
|
235
|
+
}, instance = null;
|
|
236
|
+
function getGrokAuthManager() {
|
|
237
|
+
return instance || (instance = new GrokAuthManager()), instance;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export {
|
|
241
|
+
readTokens,
|
|
242
|
+
pollDeviceCodeToken,
|
|
243
|
+
getGrokAuthManager
|
|
244
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
__require
|
|
9
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
10
|
+
|
|
11
|
+
// src/main/utils/user-data-path.ts
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { tmpdir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
16
|
+
var PRODUCT_NAME = "ADF Studio", PACKAGE_NAME = "adf-studio", SETTINGS_FILE = "adf-settings.json";
|
|
17
|
+
function getUserDataPath() {
|
|
18
|
+
if (process.env.ADF_USER_DATA_DIR) return process.env.ADF_USER_DATA_DIR;
|
|
19
|
+
let electronApp = getElectronApp();
|
|
20
|
+
return electronApp?.getPath ? electronApp.getPath("userData") : defaultUserDataPath();
|
|
21
|
+
}
|
|
22
|
+
function getTempPath() {
|
|
23
|
+
if (process.env.ADF_TEMP_DIR) return process.env.ADF_TEMP_DIR;
|
|
24
|
+
let electronApp = getElectronApp();
|
|
25
|
+
return electronApp?.getPath ? electronApp.getPath("temp") : tmpdir();
|
|
26
|
+
}
|
|
27
|
+
function platformConfigBase() {
|
|
28
|
+
return process.platform === "darwin" ? join(homedir(), "Library", "Application Support") : process.platform === "win32" ? process.env.APPDATA ?? join(homedir(), "AppData", "Roaming") : process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
|
|
29
|
+
}
|
|
30
|
+
var loggedDefaultPath = null;
|
|
31
|
+
function defaultUserDataPath(options = {}) {
|
|
32
|
+
if (process.env.ADF_USER_DATA_DIR) return process.env.ADF_USER_DATA_DIR;
|
|
33
|
+
let base = platformConfigBase(), productDir = join(base, PRODUCT_NAME), packageDir = join(base, PACKAGE_NAME), chosen = existsSync(join(productDir, SETTINGS_FILE)) ? productDir : packageDir;
|
|
34
|
+
return !options.quiet && loggedDefaultPath !== chosen && (loggedDefaultPath = chosen, console.log(`[UserDataPath] Using user data directory: ${chosen}`)), chosen;
|
|
35
|
+
}
|
|
36
|
+
function getElectronApp() {
|
|
37
|
+
try {
|
|
38
|
+
return __require("electron").app ?? null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
getUserDataPath,
|
|
46
|
+
getTempPath,
|
|
47
|
+
defaultUserDataPath
|
|
48
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
|
|
8
|
+
// src/main/cli/prompt.ts
|
|
9
|
+
import { createInterface } from "node:readline";
|
|
10
|
+
function stdinPrompt(input = process.stdin, output = process.stderr) {
|
|
11
|
+
let rl = null, ended = !1, lines = [], waiting = [], open = () => {
|
|
12
|
+
rl || ended || (rl = createInterface({ input, terminal: !1 }), rl.on("line", (line) => {
|
|
13
|
+
let next = waiting.shift();
|
|
14
|
+
next ? next(line) : lines.push(line);
|
|
15
|
+
}), rl.on("close", () => {
|
|
16
|
+
ended = !0;
|
|
17
|
+
for (let w of waiting.splice(0)) w(null);
|
|
18
|
+
}));
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
ask(question) {
|
|
22
|
+
output.write(question), open();
|
|
23
|
+
let buffered = lines.shift();
|
|
24
|
+
return buffered !== void 0 ? Promise.resolve(buffered) : ended ? Promise.resolve(null) : new Promise((resolve) => waiting.push(resolve));
|
|
25
|
+
},
|
|
26
|
+
close() {
|
|
27
|
+
rl?.close(), rl = null;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
stdinPrompt
|
|
34
|
+
};
|