@ngandu/ulicode 0.0.6
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/CHANGELOG.md +1081 -0
- package/README.md +312 -0
- package/dist/agents/definitions/ask.agent.md +53 -0
- package/dist/agents/definitions/audit-tests.agent.md +138 -0
- package/dist/agents/definitions/build.agent.md +111 -0
- package/dist/agents/definitions/execute.agent.md +99 -0
- package/dist/agents/definitions/explore.agent.md +57 -0
- package/dist/agents/definitions/fast.agent.md +48 -0
- package/dist/agents/definitions/plan-mode.agent.md +102 -0
- package/dist/agents/definitions/planner.agent.md +59 -0
- package/dist/chunk-3YYDXNUH.js +854 -0
- package/dist/chunk-3YYDXNUH.js.map +1 -0
- package/dist/chunk-IEV2IT3O.cjs +873 -0
- package/dist/chunk-IEV2IT3O.cjs.map +1 -0
- package/dist/chunk-MBWGSXBT.js +11927 -0
- package/dist/chunk-MBWGSXBT.js.map +1 -0
- package/dist/chunk-MS5RYNRK.js +137 -0
- package/dist/chunk-MS5RYNRK.js.map +1 -0
- package/dist/chunk-OXFO76JC.js +2633 -0
- package/dist/chunk-OXFO76JC.js.map +1 -0
- package/dist/chunk-PKRLG6A4.js +1756 -0
- package/dist/chunk-PKRLG6A4.js.map +1 -0
- package/dist/chunk-PUVEPQQ3.cjs +1805 -0
- package/dist/chunk-PUVEPQQ3.cjs.map +1 -0
- package/dist/chunk-R6JK3DE3.cjs +148 -0
- package/dist/chunk-R6JK3DE3.cjs.map +1 -0
- package/dist/chunk-Y3HWP75B.cjs +11974 -0
- package/dist/chunk-Y3HWP75B.cjs.map +1 -0
- package/dist/chunk-Y5PO67TG.cjs +2659 -0
- package/dist/chunk-Y5PO67TG.cjs.map +1 -0
- package/dist/cli.cjs +372 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +370 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +16 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +165 -0
- package/dist/index.d.ts +165 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions-NRD36MYI.cjs +40 -0
- package/dist/permissions-NRD36MYI.cjs.map +1 -0
- package/dist/permissions-RC7CYR5H.js +3 -0
- package/dist/permissions-RC7CYR5H.js.map +1 -0
- package/dist/project-q9WpahUs.d.cts +329 -0
- package/dist/project-q9WpahUs.d.ts +329 -0
- package/dist/storage-6P53PQBL.cjs +24 -0
- package/dist/storage-6P53PQBL.cjs.map +1 -0
- package/dist/storage-QELMNBZ2.js +3 -0
- package/dist/storage-QELMNBZ2.js.map +1 -0
- package/dist/tui.cjs +76 -0
- package/dist/tui.cjs.map +1 -0
- package/dist/tui.d.cts +1013 -0
- package/dist/tui.d.ts +1013 -0
- package/dist/tui.js +3 -0
- package/dist/tui.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,873 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var child_process = require('child_process');
|
|
6
|
+
var crypto$1 = require('crypto');
|
|
7
|
+
var os = require('os');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
12
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
13
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
14
|
+
|
|
15
|
+
// src/auth/storage.ts
|
|
16
|
+
function git(args, cwd) {
|
|
17
|
+
try {
|
|
18
|
+
return child_process.execSync(`git ${args}`, {
|
|
19
|
+
cwd,
|
|
20
|
+
encoding: "utf-8",
|
|
21
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
22
|
+
}).trim();
|
|
23
|
+
} catch {
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function slugify(str) {
|
|
28
|
+
return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
29
|
+
}
|
|
30
|
+
function shortHash(str) {
|
|
31
|
+
return crypto$1.createHash("sha256").update(str).digest("hex").slice(0, 12);
|
|
32
|
+
}
|
|
33
|
+
function normalizeGitUrl(url) {
|
|
34
|
+
return url.replace(/\.git$/, "").replace(/^git@([^:]+):/, "https://$1/").replace(/^ssh:\/\/git@/, "https://").toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
function detectProject(projectPath) {
|
|
37
|
+
const absolutePath = path__default.default.resolve(projectPath);
|
|
38
|
+
const gitDir = git("rev-parse --git-dir", absolutePath);
|
|
39
|
+
const isGitRepo = gitDir !== void 0;
|
|
40
|
+
let rootPath = absolutePath;
|
|
41
|
+
let gitUrl;
|
|
42
|
+
let gitBranch;
|
|
43
|
+
let isWorktree = false;
|
|
44
|
+
let mainRepoPath;
|
|
45
|
+
if (isGitRepo) {
|
|
46
|
+
rootPath = git("rev-parse --show-toplevel", absolutePath) || absolutePath;
|
|
47
|
+
const commonDir = git("rev-parse --git-common-dir", absolutePath);
|
|
48
|
+
if (commonDir && commonDir !== ".git" && commonDir !== gitDir) {
|
|
49
|
+
isWorktree = true;
|
|
50
|
+
mainRepoPath = path__default.default.dirname(path__default.default.resolve(rootPath, commonDir));
|
|
51
|
+
}
|
|
52
|
+
gitUrl = git("remote get-url origin", absolutePath);
|
|
53
|
+
if (!gitUrl) {
|
|
54
|
+
const remotes = git("remote", absolutePath);
|
|
55
|
+
if (remotes) {
|
|
56
|
+
const firstRemote = remotes.split("\n")[0];
|
|
57
|
+
if (firstRemote) {
|
|
58
|
+
gitUrl = git(`remote get-url ${firstRemote}`, absolutePath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
gitBranch = git("rev-parse --abbrev-ref HEAD", absolutePath);
|
|
63
|
+
}
|
|
64
|
+
let resourceIdSource;
|
|
65
|
+
if (gitUrl) {
|
|
66
|
+
resourceIdSource = normalizeGitUrl(gitUrl);
|
|
67
|
+
} else if (mainRepoPath) {
|
|
68
|
+
resourceIdSource = mainRepoPath;
|
|
69
|
+
} else {
|
|
70
|
+
resourceIdSource = rootPath;
|
|
71
|
+
}
|
|
72
|
+
const baseName = gitUrl ? gitUrl.split("/").pop()?.replace(/\.git$/, "") || "project" : path__default.default.basename(rootPath);
|
|
73
|
+
const resourceId = `${slugify(baseName)}-${shortHash(resourceIdSource)}`;
|
|
74
|
+
return {
|
|
75
|
+
resourceId,
|
|
76
|
+
name: baseName,
|
|
77
|
+
rootPath,
|
|
78
|
+
gitUrl,
|
|
79
|
+
gitBranch,
|
|
80
|
+
isWorktree,
|
|
81
|
+
mainRepoPath
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function getCurrentGitBranch(cwd) {
|
|
85
|
+
return git("rev-parse --abbrev-ref HEAD", cwd);
|
|
86
|
+
}
|
|
87
|
+
function getAppDataDir() {
|
|
88
|
+
const platform = os__default.default.platform();
|
|
89
|
+
let baseDir;
|
|
90
|
+
if (platform === "darwin") {
|
|
91
|
+
baseDir = path__default.default.join(os__default.default.homedir(), "Library", "Application Support");
|
|
92
|
+
} else if (platform === "win32") {
|
|
93
|
+
baseDir = process.env.APPDATA || path__default.default.join(os__default.default.homedir(), "AppData", "Roaming");
|
|
94
|
+
} else {
|
|
95
|
+
baseDir = process.env.XDG_DATA_HOME || path__default.default.join(os__default.default.homedir(), ".local", "share");
|
|
96
|
+
}
|
|
97
|
+
const appDir = path__default.default.join(baseDir, "ulicode");
|
|
98
|
+
const legacyDirs = [path__default.default.join(baseDir, "uli-cli"), path__default.default.join(baseDir, "pulse"), path__default.default.join(baseDir, "mastracode")];
|
|
99
|
+
for (const legacyDir of legacyDirs) {
|
|
100
|
+
if (!fs__default.default.existsSync(appDir) && fs__default.default.existsSync(legacyDir)) {
|
|
101
|
+
return legacyDir;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!fs__default.default.existsSync(appDir)) {
|
|
105
|
+
fs__default.default.mkdirSync(appDir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
return appDir;
|
|
108
|
+
}
|
|
109
|
+
function getDatabasePath() {
|
|
110
|
+
if (process.env.ULICODE_DB_PATH) {
|
|
111
|
+
return process.env.ULICODE_DB_PATH;
|
|
112
|
+
}
|
|
113
|
+
if (process.env.ULI_DB_PATH) {
|
|
114
|
+
return process.env.ULI_DB_PATH;
|
|
115
|
+
}
|
|
116
|
+
if (process.env.PULSE_DB_PATH) {
|
|
117
|
+
return process.env.PULSE_DB_PATH;
|
|
118
|
+
}
|
|
119
|
+
if (process.env.MASTRA_DB_PATH) {
|
|
120
|
+
return process.env.MASTRA_DB_PATH;
|
|
121
|
+
}
|
|
122
|
+
return path__default.default.join(getAppDataDir(), "mastra.db");
|
|
123
|
+
}
|
|
124
|
+
function getStorageConfig(projectDir, storageSettings) {
|
|
125
|
+
const envBackend = process.env.MASTRA_STORAGE_BACKEND;
|
|
126
|
+
if (envBackend === "pg") {
|
|
127
|
+
return resolvePgFromEnv();
|
|
128
|
+
}
|
|
129
|
+
if (envBackend === "libsql" || process.env.MASTRA_DB_URL) {
|
|
130
|
+
return resolveLibSQLFromEnv();
|
|
131
|
+
}
|
|
132
|
+
if (storageSettings && storageSettings.backend === "pg") {
|
|
133
|
+
return resolvePgFromSettings(storageSettings);
|
|
134
|
+
}
|
|
135
|
+
if (storageSettings && storageSettings.backend === "libsql" && storageSettings.libsql.url) {
|
|
136
|
+
return {
|
|
137
|
+
backend: "libsql",
|
|
138
|
+
url: storageSettings.libsql.url,
|
|
139
|
+
authToken: storageSettings.libsql.authToken,
|
|
140
|
+
isRemote: !storageSettings.libsql.url.startsWith("file:")
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (projectDir) {
|
|
144
|
+
const projectConfig = loadDatabaseConfig(path__default.default.join(projectDir, ".mastracode", "database.json"));
|
|
145
|
+
if (projectConfig) return projectConfig;
|
|
146
|
+
}
|
|
147
|
+
const globalConfig = loadDatabaseConfig(path__default.default.join(os__default.default.homedir(), ".mastracode", "database.json"));
|
|
148
|
+
if (globalConfig) return globalConfig;
|
|
149
|
+
return {
|
|
150
|
+
backend: "libsql",
|
|
151
|
+
url: `file:${getDatabasePath()}`,
|
|
152
|
+
isRemote: false
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function resolveLibSQLFromEnv() {
|
|
156
|
+
const url = process.env.MASTRA_DB_URL;
|
|
157
|
+
return {
|
|
158
|
+
backend: "libsql",
|
|
159
|
+
url,
|
|
160
|
+
authToken: process.env.MASTRA_DB_AUTH_TOKEN,
|
|
161
|
+
isRemote: !url.startsWith("file:")
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function resolvePgFromEnv() {
|
|
165
|
+
const connectionString = process.env.MASTRA_PG_CONNECTION_STRING;
|
|
166
|
+
if (connectionString) {
|
|
167
|
+
return {
|
|
168
|
+
backend: "pg",
|
|
169
|
+
connectionString,
|
|
170
|
+
schemaName: process.env.MASTRA_PG_SCHEMA_NAME
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
backend: "pg",
|
|
175
|
+
host: process.env.MASTRA_PG_HOST,
|
|
176
|
+
port: process.env.MASTRA_PG_PORT ? parseInt(process.env.MASTRA_PG_PORT, 10) : void 0,
|
|
177
|
+
database: process.env.MASTRA_PG_DATABASE,
|
|
178
|
+
user: process.env.MASTRA_PG_USER,
|
|
179
|
+
password: process.env.MASTRA_PG_PASSWORD,
|
|
180
|
+
schemaName: process.env.MASTRA_PG_SCHEMA_NAME
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function resolvePgFromSettings(settings) {
|
|
184
|
+
const pg = settings.pg;
|
|
185
|
+
return {
|
|
186
|
+
backend: "pg",
|
|
187
|
+
connectionString: pg.connectionString,
|
|
188
|
+
host: pg.host,
|
|
189
|
+
port: pg.port,
|
|
190
|
+
database: pg.database,
|
|
191
|
+
user: pg.user,
|
|
192
|
+
password: pg.password,
|
|
193
|
+
schemaName: pg.schemaName,
|
|
194
|
+
disableInit: pg.disableInit,
|
|
195
|
+
skipDefaultIndexes: pg.skipDefaultIndexes
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function loadDatabaseConfig(filePath) {
|
|
199
|
+
try {
|
|
200
|
+
if (!fs__default.default.existsSync(filePath)) return null;
|
|
201
|
+
const raw = fs__default.default.readFileSync(filePath, "utf-8");
|
|
202
|
+
const parsed = JSON.parse(raw);
|
|
203
|
+
if (typeof parsed?.url === "string" && parsed.url) {
|
|
204
|
+
return {
|
|
205
|
+
backend: "libsql",
|
|
206
|
+
url: parsed.url,
|
|
207
|
+
authToken: typeof parsed.authToken === "string" ? parsed.authToken : void 0,
|
|
208
|
+
isRemote: !parsed.url.startsWith("file:")
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
} catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function getUserId(projectDir) {
|
|
217
|
+
if (process.env.MASTRA_USER_ID) {
|
|
218
|
+
return process.env.MASTRA_USER_ID;
|
|
219
|
+
}
|
|
220
|
+
const cwd = projectDir || process.cwd();
|
|
221
|
+
const email = git("config user.email", cwd);
|
|
222
|
+
if (email) {
|
|
223
|
+
return email;
|
|
224
|
+
}
|
|
225
|
+
return os__default.default.userInfo().username || "unknown";
|
|
226
|
+
}
|
|
227
|
+
function getOmScope(projectDir) {
|
|
228
|
+
const envScope = process.env.MASTRA_OM_SCOPE;
|
|
229
|
+
if (envScope === "thread" || envScope === "resource") {
|
|
230
|
+
return envScope;
|
|
231
|
+
}
|
|
232
|
+
if (projectDir) {
|
|
233
|
+
const scope2 = loadOmScopeFromConfig(path__default.default.join(projectDir, ".mastracode", "database.json"));
|
|
234
|
+
if (scope2) return scope2;
|
|
235
|
+
}
|
|
236
|
+
const scope = loadOmScopeFromConfig(path__default.default.join(os__default.default.homedir(), ".mastracode", "database.json"));
|
|
237
|
+
if (scope) return scope;
|
|
238
|
+
return "thread";
|
|
239
|
+
}
|
|
240
|
+
function loadOmScopeFromConfig(filePath) {
|
|
241
|
+
try {
|
|
242
|
+
if (!fs__default.default.existsSync(filePath)) return null;
|
|
243
|
+
const raw = fs__default.default.readFileSync(filePath, "utf-8");
|
|
244
|
+
const parsed = JSON.parse(raw);
|
|
245
|
+
if (parsed?.omScope === "thread" || parsed?.omScope === "resource") {
|
|
246
|
+
return parsed.omScope;
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
} catch {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function getResourceIdOverride(projectDir) {
|
|
254
|
+
if (process.env.MASTRA_RESOURCE_ID) {
|
|
255
|
+
return process.env.MASTRA_RESOURCE_ID;
|
|
256
|
+
}
|
|
257
|
+
if (projectDir) {
|
|
258
|
+
const rid2 = loadStringField(path__default.default.join(projectDir, ".mastracode", "database.json"), "resourceId");
|
|
259
|
+
if (rid2) return rid2;
|
|
260
|
+
}
|
|
261
|
+
const rid = loadStringField(path__default.default.join(os__default.default.homedir(), ".mastracode", "database.json"), "resourceId");
|
|
262
|
+
if (rid) return rid;
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
function loadStringField(filePath, field) {
|
|
266
|
+
try {
|
|
267
|
+
if (!fs__default.default.existsSync(filePath)) return null;
|
|
268
|
+
const raw = fs__default.default.readFileSync(filePath, "utf-8");
|
|
269
|
+
const parsed = JSON.parse(raw);
|
|
270
|
+
const value = parsed?.[field];
|
|
271
|
+
if (typeof value === "string" && value) {
|
|
272
|
+
return value;
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
} catch {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/auth/pkce.ts
|
|
281
|
+
function base64urlEncode(bytes) {
|
|
282
|
+
let binary = "";
|
|
283
|
+
for (const byte of bytes) {
|
|
284
|
+
binary += String.fromCharCode(byte);
|
|
285
|
+
}
|
|
286
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
287
|
+
}
|
|
288
|
+
async function generatePKCE() {
|
|
289
|
+
const verifierBytes = new Uint8Array(32);
|
|
290
|
+
crypto.getRandomValues(verifierBytes);
|
|
291
|
+
const verifier = base64urlEncode(verifierBytes);
|
|
292
|
+
const encoder = new TextEncoder();
|
|
293
|
+
const data = encoder.encode(verifier);
|
|
294
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
295
|
+
const challenge = base64urlEncode(new Uint8Array(hashBuffer));
|
|
296
|
+
return { verifier, challenge };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// src/auth/providers/anthropic.ts
|
|
300
|
+
var decode = (s) => atob(s);
|
|
301
|
+
var CLIENT_ID = decode("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
|
|
302
|
+
var AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
|
|
303
|
+
var TOKEN_URL = "https://console.anthropic.com/v1/oauth/token";
|
|
304
|
+
var REDIRECT_URI = "https://console.anthropic.com/oauth/code/callback";
|
|
305
|
+
var SCOPES = "org:create_api_key user:profile user:inference";
|
|
306
|
+
async function loginAnthropic(onAuthUrl, onPromptCode) {
|
|
307
|
+
const { verifier, challenge } = await generatePKCE();
|
|
308
|
+
const authParams = new URLSearchParams({
|
|
309
|
+
code: "true",
|
|
310
|
+
client_id: CLIENT_ID,
|
|
311
|
+
response_type: "code",
|
|
312
|
+
redirect_uri: REDIRECT_URI,
|
|
313
|
+
scope: SCOPES,
|
|
314
|
+
code_challenge: challenge,
|
|
315
|
+
code_challenge_method: "S256",
|
|
316
|
+
state: verifier
|
|
317
|
+
});
|
|
318
|
+
const authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;
|
|
319
|
+
onAuthUrl(authUrl);
|
|
320
|
+
const authCode = await onPromptCode();
|
|
321
|
+
const splits = authCode.split("#");
|
|
322
|
+
const code = splits[0];
|
|
323
|
+
const state = splits[1];
|
|
324
|
+
const tokenResponse = await fetch(TOKEN_URL, {
|
|
325
|
+
method: "POST",
|
|
326
|
+
headers: {
|
|
327
|
+
"Content-Type": "application/json"
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify({
|
|
330
|
+
grant_type: "authorization_code",
|
|
331
|
+
client_id: CLIENT_ID,
|
|
332
|
+
code,
|
|
333
|
+
state,
|
|
334
|
+
redirect_uri: REDIRECT_URI,
|
|
335
|
+
code_verifier: verifier
|
|
336
|
+
})
|
|
337
|
+
});
|
|
338
|
+
if (!tokenResponse.ok) {
|
|
339
|
+
const error = await tokenResponse.text();
|
|
340
|
+
throw new Error(`Token exchange failed: ${error}`);
|
|
341
|
+
}
|
|
342
|
+
const tokenData = await tokenResponse.json();
|
|
343
|
+
const expiresAt = Date.now() + tokenData.expires_in * 1e3 - 5 * 60 * 1e3;
|
|
344
|
+
return {
|
|
345
|
+
refresh: tokenData.refresh_token,
|
|
346
|
+
access: tokenData.access_token,
|
|
347
|
+
expires: expiresAt
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
async function refreshAnthropicToken(refreshToken) {
|
|
351
|
+
const response = await fetch(TOKEN_URL, {
|
|
352
|
+
method: "POST",
|
|
353
|
+
headers: { "Content-Type": "application/json" },
|
|
354
|
+
body: JSON.stringify({
|
|
355
|
+
grant_type: "refresh_token",
|
|
356
|
+
client_id: CLIENT_ID,
|
|
357
|
+
refresh_token: refreshToken
|
|
358
|
+
})
|
|
359
|
+
});
|
|
360
|
+
if (!response.ok) {
|
|
361
|
+
const error = await response.text();
|
|
362
|
+
throw new Error(`Anthropic token refresh failed: ${error}`);
|
|
363
|
+
}
|
|
364
|
+
const data = await response.json();
|
|
365
|
+
return {
|
|
366
|
+
refresh: data.refresh_token,
|
|
367
|
+
access: data.access_token,
|
|
368
|
+
expires: Date.now() + data.expires_in * 1e3 - 5 * 60 * 1e3
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
var anthropicOAuthProvider = {
|
|
372
|
+
id: "anthropic",
|
|
373
|
+
name: "Anthropic (Claude Pro/Max)",
|
|
374
|
+
async login(callbacks) {
|
|
375
|
+
return loginAnthropic(
|
|
376
|
+
(url) => callbacks.onAuth({ url }),
|
|
377
|
+
() => callbacks.onPrompt({ message: "Paste the authorization code:" })
|
|
378
|
+
);
|
|
379
|
+
},
|
|
380
|
+
async refreshToken(credentials) {
|
|
381
|
+
return refreshAnthropicToken(credentials.refresh);
|
|
382
|
+
},
|
|
383
|
+
getApiKey(credentials) {
|
|
384
|
+
return credentials.access;
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
// src/auth/providers/openai-codex.ts
|
|
389
|
+
var _randomBytes = null;
|
|
390
|
+
var _http = null;
|
|
391
|
+
if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
|
|
392
|
+
import('crypto').then((m) => {
|
|
393
|
+
_randomBytes = m.randomBytes;
|
|
394
|
+
});
|
|
395
|
+
import('http').then((m) => {
|
|
396
|
+
_http = m;
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
400
|
+
var AUTHORIZE_URL2 = "https://auth.openai.com/oauth/authorize";
|
|
401
|
+
var TOKEN_URL2 = "https://auth.openai.com/oauth/token";
|
|
402
|
+
var REDIRECT_URI2 = "http://localhost:1455/auth/callback";
|
|
403
|
+
var SCOPE = "openid profile email offline_access";
|
|
404
|
+
var JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
405
|
+
var SUCCESS_HTML = `<!doctype html>
|
|
406
|
+
<html lang="en">
|
|
407
|
+
<head>
|
|
408
|
+
<meta charset="utf-8" />
|
|
409
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
410
|
+
<title>Authentication successful</title>
|
|
411
|
+
</head>
|
|
412
|
+
<body>
|
|
413
|
+
<p>Authentication successful. Return to your terminal to continue.</p>
|
|
414
|
+
</body>
|
|
415
|
+
</html>`;
|
|
416
|
+
function createState() {
|
|
417
|
+
if (!_randomBytes) {
|
|
418
|
+
throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
|
|
419
|
+
}
|
|
420
|
+
return _randomBytes(16).toString("hex");
|
|
421
|
+
}
|
|
422
|
+
function parseAuthorizationInput(input) {
|
|
423
|
+
const value = input.trim();
|
|
424
|
+
if (!value) return {};
|
|
425
|
+
try {
|
|
426
|
+
const url = new URL(value);
|
|
427
|
+
return {
|
|
428
|
+
code: url.searchParams.get("code") ?? void 0,
|
|
429
|
+
state: url.searchParams.get("state") ?? void 0
|
|
430
|
+
};
|
|
431
|
+
} catch {
|
|
432
|
+
}
|
|
433
|
+
if (value.includes("#")) {
|
|
434
|
+
const [code, state] = value.split("#", 2);
|
|
435
|
+
return { code, state };
|
|
436
|
+
}
|
|
437
|
+
if (value.includes("code=")) {
|
|
438
|
+
const params = new URLSearchParams(value);
|
|
439
|
+
return {
|
|
440
|
+
code: params.get("code") ?? void 0,
|
|
441
|
+
state: params.get("state") ?? void 0
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
return { code: value };
|
|
445
|
+
}
|
|
446
|
+
function decodeJwt(token) {
|
|
447
|
+
try {
|
|
448
|
+
const parts = token.split(".");
|
|
449
|
+
if (parts.length !== 3) return null;
|
|
450
|
+
const payload = parts[1] ?? "";
|
|
451
|
+
const decoded = atob(payload);
|
|
452
|
+
return JSON.parse(decoded);
|
|
453
|
+
} catch {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
async function exchangeAuthorizationCode(code, verifier, redirectUri = REDIRECT_URI2) {
|
|
458
|
+
const response = await fetch(TOKEN_URL2, {
|
|
459
|
+
method: "POST",
|
|
460
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
461
|
+
body: new URLSearchParams({
|
|
462
|
+
grant_type: "authorization_code",
|
|
463
|
+
client_id: CLIENT_ID2,
|
|
464
|
+
code,
|
|
465
|
+
code_verifier: verifier,
|
|
466
|
+
redirect_uri: redirectUri
|
|
467
|
+
})
|
|
468
|
+
});
|
|
469
|
+
if (!response.ok) {
|
|
470
|
+
const text = await response.text().catch(() => "");
|
|
471
|
+
console.error("[openai-codex] code->token failed:", response.status, text);
|
|
472
|
+
return { type: "failed" };
|
|
473
|
+
}
|
|
474
|
+
const json = await response.json();
|
|
475
|
+
if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
|
|
476
|
+
console.error("[openai-codex] token response missing fields:", json);
|
|
477
|
+
return { type: "failed" };
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
type: "success",
|
|
481
|
+
access: json.access_token,
|
|
482
|
+
refresh: json.refresh_token,
|
|
483
|
+
expires: Date.now() + json.expires_in * 1e3
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
async function refreshAccessToken(refreshToken) {
|
|
487
|
+
try {
|
|
488
|
+
const response = await fetch(TOKEN_URL2, {
|
|
489
|
+
method: "POST",
|
|
490
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
491
|
+
body: new URLSearchParams({
|
|
492
|
+
grant_type: "refresh_token",
|
|
493
|
+
refresh_token: refreshToken,
|
|
494
|
+
client_id: CLIENT_ID2
|
|
495
|
+
})
|
|
496
|
+
});
|
|
497
|
+
if (!response.ok) {
|
|
498
|
+
const text = await response.text().catch(() => "");
|
|
499
|
+
console.error("[openai-codex] Token refresh failed:", response.status, text);
|
|
500
|
+
return { type: "failed" };
|
|
501
|
+
}
|
|
502
|
+
const json = await response.json();
|
|
503
|
+
if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
|
|
504
|
+
console.error("[openai-codex] Token refresh response missing fields:", json);
|
|
505
|
+
return { type: "failed" };
|
|
506
|
+
}
|
|
507
|
+
return {
|
|
508
|
+
type: "success",
|
|
509
|
+
access: json.access_token,
|
|
510
|
+
refresh: json.refresh_token,
|
|
511
|
+
expires: Date.now() + json.expires_in * 1e3
|
|
512
|
+
};
|
|
513
|
+
} catch (error) {
|
|
514
|
+
console.error("[openai-codex] Token refresh error:", error);
|
|
515
|
+
return { type: "failed" };
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async function createAuthorizationFlow(originator = "pi") {
|
|
519
|
+
const { verifier, challenge } = await generatePKCE();
|
|
520
|
+
const state = createState();
|
|
521
|
+
const url = new URL(AUTHORIZE_URL2);
|
|
522
|
+
url.searchParams.set("response_type", "code");
|
|
523
|
+
url.searchParams.set("client_id", CLIENT_ID2);
|
|
524
|
+
url.searchParams.set("redirect_uri", REDIRECT_URI2);
|
|
525
|
+
url.searchParams.set("scope", SCOPE);
|
|
526
|
+
url.searchParams.set("code_challenge", challenge);
|
|
527
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
528
|
+
url.searchParams.set("state", state);
|
|
529
|
+
url.searchParams.set("id_token_add_organizations", "true");
|
|
530
|
+
url.searchParams.set("codex_cli_simplified_flow", "true");
|
|
531
|
+
url.searchParams.set("originator", originator);
|
|
532
|
+
return { verifier, state, url: url.toString() };
|
|
533
|
+
}
|
|
534
|
+
function startLocalOAuthServer(state) {
|
|
535
|
+
if (!_http) {
|
|
536
|
+
throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
|
|
537
|
+
}
|
|
538
|
+
let lastCode = null;
|
|
539
|
+
let cancelled = false;
|
|
540
|
+
const server = _http.createServer((req, res) => {
|
|
541
|
+
try {
|
|
542
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
543
|
+
if (url.pathname !== "/auth/callback") {
|
|
544
|
+
res.statusCode = 404;
|
|
545
|
+
res.end("Not found");
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (url.searchParams.get("state") !== state) {
|
|
549
|
+
res.statusCode = 400;
|
|
550
|
+
res.end("State mismatch");
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
const code = url.searchParams.get("code");
|
|
554
|
+
if (!code) {
|
|
555
|
+
res.statusCode = 400;
|
|
556
|
+
res.end("Missing authorization code");
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
res.statusCode = 200;
|
|
560
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
561
|
+
res.end(SUCCESS_HTML);
|
|
562
|
+
lastCode = code;
|
|
563
|
+
} catch {
|
|
564
|
+
res.statusCode = 500;
|
|
565
|
+
res.end("Internal error");
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
return new Promise((resolve) => {
|
|
569
|
+
server.listen(1455, "127.0.0.1", () => {
|
|
570
|
+
resolve({
|
|
571
|
+
close: () => server.close(),
|
|
572
|
+
cancelWait: () => {
|
|
573
|
+
cancelled = true;
|
|
574
|
+
},
|
|
575
|
+
waitForCode: async () => {
|
|
576
|
+
const sleep = () => new Promise((r) => setTimeout(r, 100));
|
|
577
|
+
for (let i = 0; i < 600; i += 1) {
|
|
578
|
+
if (lastCode) return { code: lastCode };
|
|
579
|
+
if (cancelled) return null;
|
|
580
|
+
await sleep();
|
|
581
|
+
}
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
}).on("error", (err) => {
|
|
586
|
+
console.error(
|
|
587
|
+
"[openai-codex] Failed to bind http://127.0.0.1:1455 (",
|
|
588
|
+
err.code,
|
|
589
|
+
") Falling back to manual paste."
|
|
590
|
+
);
|
|
591
|
+
resolve({
|
|
592
|
+
close: () => {
|
|
593
|
+
try {
|
|
594
|
+
server.close();
|
|
595
|
+
} catch {
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
cancelWait: () => {
|
|
599
|
+
},
|
|
600
|
+
waitForCode: async () => null
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
function getAccountId(accessToken) {
|
|
606
|
+
const payload = decodeJwt(accessToken);
|
|
607
|
+
const auth = payload?.[JWT_CLAIM_PATH];
|
|
608
|
+
const accountId = auth?.chatgpt_account_id;
|
|
609
|
+
return typeof accountId === "string" && accountId.length > 0 ? accountId : null;
|
|
610
|
+
}
|
|
611
|
+
async function loginOpenAICodex(options) {
|
|
612
|
+
const { verifier, state, url } = await createAuthorizationFlow(options.originator);
|
|
613
|
+
const server = await startLocalOAuthServer(state);
|
|
614
|
+
options.onAuth({
|
|
615
|
+
url,
|
|
616
|
+
instructions: "A browser window should open. Complete login to finish."
|
|
617
|
+
});
|
|
618
|
+
let code;
|
|
619
|
+
try {
|
|
620
|
+
if (options.onManualCodeInput) {
|
|
621
|
+
let manualCode;
|
|
622
|
+
let manualError;
|
|
623
|
+
const manualPromise = options.onManualCodeInput().then((input) => {
|
|
624
|
+
manualCode = input;
|
|
625
|
+
server.cancelWait();
|
|
626
|
+
}).catch((err) => {
|
|
627
|
+
manualError = err instanceof Error ? err : new Error(String(err));
|
|
628
|
+
server.cancelWait();
|
|
629
|
+
});
|
|
630
|
+
const result = await server.waitForCode();
|
|
631
|
+
if (manualError) {
|
|
632
|
+
throw manualError;
|
|
633
|
+
}
|
|
634
|
+
if (result?.code) {
|
|
635
|
+
code = result.code;
|
|
636
|
+
} else if (manualCode) {
|
|
637
|
+
const parsed = parseAuthorizationInput(manualCode);
|
|
638
|
+
if (parsed.state && parsed.state !== state) {
|
|
639
|
+
throw new Error("State mismatch");
|
|
640
|
+
}
|
|
641
|
+
code = parsed.code;
|
|
642
|
+
}
|
|
643
|
+
if (!code) {
|
|
644
|
+
await manualPromise;
|
|
645
|
+
if (manualError) {
|
|
646
|
+
throw manualError;
|
|
647
|
+
}
|
|
648
|
+
if (manualCode) {
|
|
649
|
+
const parsed = parseAuthorizationInput(manualCode);
|
|
650
|
+
if (parsed.state && parsed.state !== state) {
|
|
651
|
+
throw new Error("State mismatch");
|
|
652
|
+
}
|
|
653
|
+
code = parsed.code;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
} else {
|
|
657
|
+
const result = await server.waitForCode();
|
|
658
|
+
if (result?.code) {
|
|
659
|
+
code = result.code;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (!code) {
|
|
663
|
+
const input = await options.onPrompt({
|
|
664
|
+
message: "Paste the authorization code (or full redirect URL):"
|
|
665
|
+
});
|
|
666
|
+
const parsed = parseAuthorizationInput(input);
|
|
667
|
+
if (parsed.state && parsed.state !== state) {
|
|
668
|
+
throw new Error("State mismatch");
|
|
669
|
+
}
|
|
670
|
+
code = parsed.code;
|
|
671
|
+
}
|
|
672
|
+
if (!code) {
|
|
673
|
+
throw new Error("Missing authorization code");
|
|
674
|
+
}
|
|
675
|
+
const tokenResult = await exchangeAuthorizationCode(code, verifier);
|
|
676
|
+
if (tokenResult.type !== "success") {
|
|
677
|
+
throw new Error("Token exchange failed");
|
|
678
|
+
}
|
|
679
|
+
const accountId = getAccountId(tokenResult.access);
|
|
680
|
+
if (!accountId) {
|
|
681
|
+
throw new Error("Failed to extract accountId from token");
|
|
682
|
+
}
|
|
683
|
+
return {
|
|
684
|
+
access: tokenResult.access,
|
|
685
|
+
refresh: tokenResult.refresh,
|
|
686
|
+
expires: tokenResult.expires,
|
|
687
|
+
accountId
|
|
688
|
+
};
|
|
689
|
+
} finally {
|
|
690
|
+
server.close();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
async function refreshOpenAICodexToken(refreshToken) {
|
|
694
|
+
const result = await refreshAccessToken(refreshToken);
|
|
695
|
+
if (result.type !== "success") {
|
|
696
|
+
throw new Error("Failed to refresh OpenAI Codex token");
|
|
697
|
+
}
|
|
698
|
+
const accountId = getAccountId(result.access);
|
|
699
|
+
if (!accountId) {
|
|
700
|
+
throw new Error("Failed to extract accountId from token");
|
|
701
|
+
}
|
|
702
|
+
return {
|
|
703
|
+
access: result.access,
|
|
704
|
+
refresh: result.refresh,
|
|
705
|
+
expires: result.expires,
|
|
706
|
+
accountId
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
var openaiCodexOAuthProvider = {
|
|
710
|
+
id: "openai-codex",
|
|
711
|
+
name: "ChatGPT Plus/Pro (Codex Subscription)",
|
|
712
|
+
usesCallbackServer: true,
|
|
713
|
+
async login(callbacks) {
|
|
714
|
+
return loginOpenAICodex({
|
|
715
|
+
onAuth: callbacks.onAuth,
|
|
716
|
+
onPrompt: callbacks.onPrompt,
|
|
717
|
+
onProgress: callbacks.onProgress,
|
|
718
|
+
onManualCodeInput: callbacks.onManualCodeInput
|
|
719
|
+
});
|
|
720
|
+
},
|
|
721
|
+
async refreshToken(credentials) {
|
|
722
|
+
return refreshOpenAICodexToken(credentials.refresh);
|
|
723
|
+
},
|
|
724
|
+
getApiKey(credentials) {
|
|
725
|
+
return credentials.access;
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
// src/auth/storage.ts
|
|
730
|
+
var PROVIDER_DEFAULT_MODELS = {
|
|
731
|
+
anthropic: "anthropic/claude-opus-4-6",
|
|
732
|
+
"openai-codex": "openai/gpt-5.2-codex",
|
|
733
|
+
google: "google/gemini-2.5-flash"
|
|
734
|
+
};
|
|
735
|
+
var oauthProviderRegistry = /* @__PURE__ */ new Map([
|
|
736
|
+
[anthropicOAuthProvider.id, anthropicOAuthProvider],
|
|
737
|
+
[openaiCodexOAuthProvider.id, openaiCodexOAuthProvider]
|
|
738
|
+
]);
|
|
739
|
+
function getOAuthProvider(id) {
|
|
740
|
+
return oauthProviderRegistry.get(id);
|
|
741
|
+
}
|
|
742
|
+
function getOAuthProviders() {
|
|
743
|
+
return Array.from(oauthProviderRegistry.values());
|
|
744
|
+
}
|
|
745
|
+
var AuthStorage = class {
|
|
746
|
+
constructor(authPath = path.join(getAppDataDir(), "auth.json")) {
|
|
747
|
+
this.authPath = authPath;
|
|
748
|
+
this.reload();
|
|
749
|
+
}
|
|
750
|
+
data = {};
|
|
751
|
+
/**
|
|
752
|
+
* Reload credentials from disk.
|
|
753
|
+
*/
|
|
754
|
+
reload() {
|
|
755
|
+
if (!fs.existsSync(this.authPath)) {
|
|
756
|
+
this.data = {};
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
try {
|
|
760
|
+
this.data = JSON.parse(fs.readFileSync(this.authPath, "utf-8"));
|
|
761
|
+
} catch {
|
|
762
|
+
this.data = {};
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Save credentials to disk.
|
|
767
|
+
*/
|
|
768
|
+
save() {
|
|
769
|
+
const dir = path.dirname(this.authPath);
|
|
770
|
+
if (!fs.existsSync(dir)) {
|
|
771
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
772
|
+
}
|
|
773
|
+
fs.writeFileSync(this.authPath, JSON.stringify(this.data, null, 2), "utf-8");
|
|
774
|
+
fs.chmodSync(this.authPath, 384);
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Get credential for a provider.
|
|
778
|
+
*/
|
|
779
|
+
get(provider) {
|
|
780
|
+
return this.data[provider] ?? void 0;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Set credential for a provider.
|
|
784
|
+
*/
|
|
785
|
+
set(provider, credential) {
|
|
786
|
+
this.data[provider] = credential;
|
|
787
|
+
this.save();
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Remove credential for a provider.
|
|
791
|
+
*/
|
|
792
|
+
remove(provider) {
|
|
793
|
+
delete this.data[provider];
|
|
794
|
+
this.save();
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* List all providers with credentials.
|
|
798
|
+
*/
|
|
799
|
+
list() {
|
|
800
|
+
return Object.keys(this.data);
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Check if credentials exist for a provider.
|
|
804
|
+
*/
|
|
805
|
+
has(provider) {
|
|
806
|
+
return provider in this.data;
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Check if logged in via OAuth for a provider.
|
|
810
|
+
*/
|
|
811
|
+
isLoggedIn(provider) {
|
|
812
|
+
const cred = this.data[provider];
|
|
813
|
+
return cred?.type === "oauth";
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Login to an OAuth provider.
|
|
817
|
+
*/
|
|
818
|
+
async login(providerId, callbacks) {
|
|
819
|
+
const provider = getOAuthProvider(providerId);
|
|
820
|
+
if (!provider) {
|
|
821
|
+
throw new Error(`Unknown OAuth provider: ${providerId}`);
|
|
822
|
+
}
|
|
823
|
+
const credentials = await provider.login(callbacks);
|
|
824
|
+
this.set(providerId, { type: "oauth", ...credentials });
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Logout from a provider.
|
|
828
|
+
*/
|
|
829
|
+
logout(provider) {
|
|
830
|
+
this.remove(provider);
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Get API key for a provider, auto-refreshing OAuth tokens if needed.
|
|
834
|
+
*/
|
|
835
|
+
async getApiKey(providerId) {
|
|
836
|
+
const cred = this.data[providerId];
|
|
837
|
+
if (cred?.type === "api_key") {
|
|
838
|
+
return cred.key;
|
|
839
|
+
}
|
|
840
|
+
if (cred?.type === "oauth") {
|
|
841
|
+
const provider = getOAuthProvider(providerId);
|
|
842
|
+
if (!provider) {
|
|
843
|
+
return void 0;
|
|
844
|
+
}
|
|
845
|
+
if (Date.now() >= cred.expires) {
|
|
846
|
+
try {
|
|
847
|
+
const newCreds = await provider.refreshToken(cred);
|
|
848
|
+
this.set(providerId, { type: "oauth", ...newCreds });
|
|
849
|
+
return provider.getApiKey(newCreds);
|
|
850
|
+
} catch {
|
|
851
|
+
return void 0;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return provider.getApiKey(cred);
|
|
855
|
+
}
|
|
856
|
+
return void 0;
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
exports.AuthStorage = AuthStorage;
|
|
861
|
+
exports.PROVIDER_DEFAULT_MODELS = PROVIDER_DEFAULT_MODELS;
|
|
862
|
+
exports.detectProject = detectProject;
|
|
863
|
+
exports.getAppDataDir = getAppDataDir;
|
|
864
|
+
exports.getCurrentGitBranch = getCurrentGitBranch;
|
|
865
|
+
exports.getDatabasePath = getDatabasePath;
|
|
866
|
+
exports.getOAuthProvider = getOAuthProvider;
|
|
867
|
+
exports.getOAuthProviders = getOAuthProviders;
|
|
868
|
+
exports.getOmScope = getOmScope;
|
|
869
|
+
exports.getResourceIdOverride = getResourceIdOverride;
|
|
870
|
+
exports.getStorageConfig = getStorageConfig;
|
|
871
|
+
exports.getUserId = getUserId;
|
|
872
|
+
//# sourceMappingURL=chunk-IEV2IT3O.cjs.map
|
|
873
|
+
//# sourceMappingURL=chunk-IEV2IT3O.cjs.map
|