@braid-cloud/cli 0.1.18 → 0.1.19
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 +46 -0
- package/dist/index.js +1316 -1047
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -18,10 +18,28 @@ var init_esm_shims = __esm({
|
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
// src/lib/automation-headers.ts
|
|
22
|
+
import process3 from "process";
|
|
23
|
+
var VERCEL_AUTOMATION_BYPASS_SECRET, mergeAutomationHeaders;
|
|
24
|
+
var init_automation_headers = __esm({
|
|
25
|
+
"src/lib/automation-headers.ts"() {
|
|
26
|
+
"use strict";
|
|
27
|
+
init_esm_shims();
|
|
28
|
+
VERCEL_AUTOMATION_BYPASS_SECRET = process3.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
29
|
+
mergeAutomationHeaders = (headers) => {
|
|
30
|
+
const merged = new Headers(headers);
|
|
31
|
+
if (VERCEL_AUTOMATION_BYPASS_SECRET) {
|
|
32
|
+
merged.set("x-vercel-protection-bypass", VERCEL_AUTOMATION_BYPASS_SECRET);
|
|
33
|
+
}
|
|
34
|
+
return merged.entries().next().done ? void 0 : merged;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
21
39
|
// src/lib/braid-workspace.ts
|
|
22
40
|
import { existsSync, readFileSync } from "fs";
|
|
23
41
|
import { dirname as dirname3, join as join2 } from "path";
|
|
24
|
-
import
|
|
42
|
+
import process4 from "process";
|
|
25
43
|
function readPackageName(packagePath) {
|
|
26
44
|
if (!existsSync(packagePath)) {
|
|
27
45
|
return void 0;
|
|
@@ -38,7 +56,7 @@ function readPackageName(packagePath) {
|
|
|
38
56
|
function isBraidWorkspaceRoot(directory) {
|
|
39
57
|
return readPackageName(join2(directory, "package.json")) === BRAID_WORKSPACE_NAME;
|
|
40
58
|
}
|
|
41
|
-
function findBraidWorkspaceRoot(startDir =
|
|
59
|
+
function findBraidWorkspaceRoot(startDir = process4.cwd()) {
|
|
42
60
|
let currentDir = startDir;
|
|
43
61
|
while (true) {
|
|
44
62
|
if (isBraidWorkspaceRoot(currentDir)) {
|
|
@@ -108,9 +126,9 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
|
108
126
|
import { mkdir as mkdir2, readFile, writeFile as writeFile2 } from "fs/promises";
|
|
109
127
|
import { homedir as homedir2 } from "os";
|
|
110
128
|
import { dirname as dirname4, join as join3, parse } from "path";
|
|
111
|
-
import
|
|
129
|
+
import process5 from "process";
|
|
112
130
|
import { Data as Data2, Effect as Effect3, pipe as pipe3 } from "effect";
|
|
113
|
-
var CONFIG_DIR, CONFIG_FILE, PROJECT_CONFIG_FILENAME, USER_CONFIG_FILENAME, CONVEX_CLOUD_SUFFIX_REGEX, LOCAL_CONVEX_PORT_REGEX, LOCAL_SERVER_ENV_FILES, LOOPBACK_HOSTS, NEWLINE_REGEX, TRAILING_SLASHES, ConfigReadError, ConfigWriteError, findConfigFile, findProjectConfigFile, findUserConfigFile, stripQuotes, parseDotenv, normalizeBaseUrl, resolveConvexSiteUrl, resolveLocalServerUrlFromEnv, resolveLocalServerUrlFromFiles, resolveLocalServerUrl, loadProjectConfig, loadUserConfig, resolveUserConfigWritePath, resolveProjectConfigWritePath, saveUserConfig, saveProjectConfig, isValidServerUrl, resolveServerUrlFromConfig, applyConfigSource, applyEnvOverrides, createDefaultMergedConfig, loadMergedConfig, loadConfig, saveConfig, getApiKey, setApiKey, getServerUrl, clearApiKey, getDemoContext, setDemoContext, clearDemoContext, loadConfigAsync, loadProjectConfigAsync, loadUserConfigAsync, loadMergedConfigAsync, findProjectConfigFileAsync, findUserConfigFileAsync, saveConfigAsync, saveUserConfigAsync, saveProjectConfigAsync, getApiKeyAsync, setApiKeyAsync, persistApiKeyAsync, getServerUrlAsync, clearApiKeyAsync, getDemoContextAsync, setDemoContextAsync, clearDemoContextAsync;
|
|
131
|
+
var CONFIG_DIR, CONFIG_FILE, PROJECT_CONFIG_FILENAME, USER_CONFIG_FILENAME, CONVEX_CLOUD_SUFFIX_REGEX, LOCAL_CONVEX_PORT_REGEX, LOCAL_SERVER_ENV_FILES, LOOPBACK_HOSTS, NEWLINE_REGEX, TRAILING_SLASHES, ConfigReadError, ConfigWriteError, findConfigFile, findProjectConfigFile, findUserConfigFile, stripQuotes, parseDotenv, normalizeBaseUrl, resolveConvexSiteUrl, resolveLocalServerUrlFromEnv, resolveLocalServerUrlFromFiles, resolveLocalServerUrl, loadProjectConfig, loadUserConfig, resolveUserConfigWritePath, resolveProjectConfigWritePath, saveUserConfig, saveProjectConfig, isValidServerUrl, resolveServerUrlFromConfig, applyConfigSource, applyGlobalConfigSource, applyEnvOverrides, createDefaultMergedConfig, loadMergedConfig, loadConfig, saveConfig, getApiKey, setApiKey, getServerUrl, clearApiKey, getDemoContext, setDemoContext, clearDemoContext, loadConfigAsync, loadProjectConfigAsync, loadUserConfigAsync, loadMergedConfigAsync, findProjectConfigFileAsync, findUserConfigFileAsync, saveConfigAsync, saveUserConfigAsync, saveProjectConfigAsync, getApiKeyAsync, setApiKeyAsync, persistApiKeyAsync, getServerUrlAsync, clearApiKeyAsync, getDemoContextAsync, setDemoContextAsync, clearDemoContextAsync;
|
|
114
132
|
var init_config = __esm({
|
|
115
133
|
"src/lib/config.ts"() {
|
|
116
134
|
"use strict";
|
|
@@ -133,7 +151,7 @@ var init_config = __esm({
|
|
|
133
151
|
};
|
|
134
152
|
ConfigWriteError = class extends Data2.TaggedError("ConfigWriteError") {
|
|
135
153
|
};
|
|
136
|
-
findConfigFile = (filename, startDir =
|
|
154
|
+
findConfigFile = (filename, startDir = process5.cwd()) => {
|
|
137
155
|
let currentDir = startDir;
|
|
138
156
|
while (true) {
|
|
139
157
|
const configPath = join3(currentDir, filename);
|
|
@@ -147,8 +165,8 @@ var init_config = __esm({
|
|
|
147
165
|
currentDir = parsed.dir;
|
|
148
166
|
}
|
|
149
167
|
};
|
|
150
|
-
findProjectConfigFile = (startDir =
|
|
151
|
-
findUserConfigFile = (startDir =
|
|
168
|
+
findProjectConfigFile = (startDir = process5.cwd()) => findConfigFile(PROJECT_CONFIG_FILENAME, startDir);
|
|
169
|
+
findUserConfigFile = (startDir = process5.cwd()) => findConfigFile(USER_CONFIG_FILENAME, startDir);
|
|
152
170
|
stripQuotes = (value) => {
|
|
153
171
|
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
154
172
|
return value.slice(1, -1);
|
|
@@ -207,7 +225,7 @@ var init_config = __esm({
|
|
|
207
225
|
}
|
|
208
226
|
return void 0;
|
|
209
227
|
};
|
|
210
|
-
resolveLocalServerUrlFromFiles = (startDir =
|
|
228
|
+
resolveLocalServerUrlFromFiles = (startDir = process5.cwd()) => {
|
|
211
229
|
const workspaceRoot = findBraidWorkspaceRoot(startDir);
|
|
212
230
|
if (!workspaceRoot) {
|
|
213
231
|
return void 0;
|
|
@@ -226,7 +244,7 @@ var init_config = __esm({
|
|
|
226
244
|
}
|
|
227
245
|
return void 0;
|
|
228
246
|
};
|
|
229
|
-
resolveLocalServerUrl = (startDir =
|
|
247
|
+
resolveLocalServerUrl = (startDir = process5.cwd()) => resolveLocalServerUrlFromEnv(process5.env) ?? resolveLocalServerUrlFromFiles(startDir);
|
|
230
248
|
loadProjectConfig = () => Effect3.tryPromise({
|
|
231
249
|
try: async () => {
|
|
232
250
|
const configPath = await findProjectConfigFile();
|
|
@@ -249,9 +267,9 @@ var init_config = __esm({
|
|
|
249
267
|
},
|
|
250
268
|
catch: () => void 0
|
|
251
269
|
}).pipe(Effect3.orElseSucceed(() => void 0));
|
|
252
|
-
resolveUserConfigWritePath = (startDir =
|
|
253
|
-
resolveProjectConfigWritePath = (startDir =
|
|
254
|
-
saveUserConfig = (config, startDir =
|
|
270
|
+
resolveUserConfigWritePath = (startDir = process5.cwd()) => findUserConfigFile(startDir) ?? join3(startDir, USER_CONFIG_FILENAME);
|
|
271
|
+
resolveProjectConfigWritePath = (startDir = process5.cwd()) => findProjectConfigFile(startDir) ?? join3(startDir, PROJECT_CONFIG_FILENAME);
|
|
272
|
+
saveUserConfig = (config, startDir = process5.cwd()) => {
|
|
255
273
|
const targetPath = resolveUserConfigWritePath(startDir);
|
|
256
274
|
return pipe3(
|
|
257
275
|
Effect3.tryPromise({
|
|
@@ -267,7 +285,7 @@ var init_config = __esm({
|
|
|
267
285
|
})
|
|
268
286
|
);
|
|
269
287
|
};
|
|
270
|
-
saveProjectConfig = (config, startDir =
|
|
288
|
+
saveProjectConfig = (config, startDir = process5.cwd()) => {
|
|
271
289
|
const targetPath = resolveProjectConfigWritePath(startDir);
|
|
272
290
|
return pipe3(
|
|
273
291
|
Effect3.tryPromise({
|
|
@@ -343,11 +361,17 @@ var init_config = __esm({
|
|
|
343
361
|
merged.token = config.token;
|
|
344
362
|
}
|
|
345
363
|
};
|
|
364
|
+
applyGlobalConfigSource = (merged, config) => {
|
|
365
|
+
const serverUrl = resolveServerUrlFromConfig(config);
|
|
366
|
+
if (serverUrl) {
|
|
367
|
+
merged.serverUrl = serverUrl;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
346
370
|
applyEnvOverrides = (merged) => {
|
|
347
|
-
if (
|
|
348
|
-
merged.token =
|
|
371
|
+
if (process5.env.BRAID_API_KEY) {
|
|
372
|
+
merged.token = process5.env.BRAID_API_KEY;
|
|
349
373
|
}
|
|
350
|
-
const envServerUrl =
|
|
374
|
+
const envServerUrl = process5.env.BRAID_SKILLS_SERVER_URL ?? process5.env.BRAID_SERVER_URL;
|
|
351
375
|
if (envServerUrl && isValidServerUrl(envServerUrl)) {
|
|
352
376
|
merged.serverUrl = envServerUrl;
|
|
353
377
|
}
|
|
@@ -367,6 +391,7 @@ var init_config = __esm({
|
|
|
367
391
|
}),
|
|
368
392
|
Effect3.map(({ projectConfig, userConfig, globalConfig }) => {
|
|
369
393
|
const merged = createDefaultMergedConfig();
|
|
394
|
+
applyGlobalConfigSource(merged, globalConfig);
|
|
370
395
|
applyConfigSource(merged, projectConfig);
|
|
371
396
|
applyConfigSource(merged, userConfig);
|
|
372
397
|
applyEnvOverrides(merged);
|
|
@@ -402,7 +427,7 @@ var init_config = __esm({
|
|
|
402
427
|
})
|
|
403
428
|
);
|
|
404
429
|
getApiKey = () => pipe3(
|
|
405
|
-
Effect3.succeed(
|
|
430
|
+
Effect3.succeed(process5.env.BRAID_API_KEY),
|
|
406
431
|
Effect3.flatMap(
|
|
407
432
|
(envKey) => envKey ? Effect3.succeed(envKey) : pipe3(
|
|
408
433
|
loadUserConfig(),
|
|
@@ -420,7 +445,7 @@ var init_config = __esm({
|
|
|
420
445
|
Effect3.flatMap((config) => saveConfig({ ...config, apiKey }))
|
|
421
446
|
);
|
|
422
447
|
getServerUrl = () => pipe3(
|
|
423
|
-
Effect3.succeed(
|
|
448
|
+
Effect3.succeed(process5.env.BRAID_SERVER_URL),
|
|
424
449
|
Effect3.flatMap(
|
|
425
450
|
(envUrl) => envUrl ? Effect3.succeed(envUrl) : pipe3(
|
|
426
451
|
loadUserConfig(),
|
|
@@ -498,89 +523,226 @@ var init_config = __esm({
|
|
|
498
523
|
}
|
|
499
524
|
});
|
|
500
525
|
|
|
501
|
-
// src/lib/
|
|
502
|
-
import {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
526
|
+
// src/lib/device-auth.ts
|
|
527
|
+
import { execFile } from "child_process";
|
|
528
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
529
|
+
import { hostname, platform } from "os";
|
|
530
|
+
import { join as join4 } from "path";
|
|
531
|
+
import process6 from "process";
|
|
532
|
+
function resolveAuthWebBaseUrl(serverUrl) {
|
|
533
|
+
const canonicalBaseUrl = resolveCanonicalAuthWebBaseUrl(serverUrl);
|
|
534
|
+
try {
|
|
535
|
+
const url = new URL(canonicalBaseUrl);
|
|
536
|
+
const localAuthBaseUrl = resolveLocalAuthWebBaseUrl();
|
|
537
|
+
if (localAuthBaseUrl && (DEFAULT_BRAID_AUTH_HOSTS.has(url.hostname) || isLoopbackHost(url.hostname))) {
|
|
538
|
+
return localAuthBaseUrl;
|
|
539
|
+
}
|
|
540
|
+
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
541
|
+
} catch {
|
|
542
|
+
return canonicalBaseUrl;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
function buildAuthVerificationUrlFromBaseUrl(authBaseUrl, userCode) {
|
|
546
|
+
return `${authBaseUrl.replace(TRAILING_SLASHES2, "")}/cli/authorize?user_code=${encodeURIComponent(userCode)}`;
|
|
547
|
+
}
|
|
548
|
+
async function fetchAuthConfigFromBaseUrl(authBaseUrl) {
|
|
549
|
+
const headers = mergeAutomationHeaders();
|
|
550
|
+
const authConfigUrl = `${authBaseUrl}/api/cli/auth-config`;
|
|
551
|
+
const response = headers ? await fetch(authConfigUrl, { headers }) : await fetch(authConfigUrl);
|
|
552
|
+
if (!response.ok) {
|
|
553
|
+
const body = await response.text();
|
|
554
|
+
throw new Error(
|
|
555
|
+
`Failed to fetch auth config (${response.status}): ${body}`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
...await response.json(),
|
|
560
|
+
verificationBaseUrl: authBaseUrl
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
async function fetchAuthConfig(serverUrl) {
|
|
564
|
+
const authBaseUrl = resolveAuthWebBaseUrl(serverUrl).replace(
|
|
565
|
+
TRAILING_SLASHES2,
|
|
566
|
+
""
|
|
567
|
+
);
|
|
568
|
+
const canonicalAuthBaseUrl = resolveCanonicalAuthWebBaseUrl(
|
|
569
|
+
serverUrl
|
|
570
|
+
).replace(TRAILING_SLASHES2, "");
|
|
571
|
+
try {
|
|
572
|
+
return await fetchAuthConfigFromBaseUrl(authBaseUrl);
|
|
573
|
+
} catch (error) {
|
|
574
|
+
if (authBaseUrl !== canonicalAuthBaseUrl && isHostedBraidAuthServer(serverUrl)) {
|
|
575
|
+
return fetchAuthConfigFromBaseUrl(canonicalAuthBaseUrl);
|
|
576
|
+
}
|
|
577
|
+
throw error;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
async function initiateDeviceAuth(convexSiteUrl, deviceInfo) {
|
|
581
|
+
const url = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/device/authorize`;
|
|
582
|
+
const response = await fetch(url, {
|
|
583
|
+
method: "POST",
|
|
584
|
+
headers: mergeAutomationHeaders({
|
|
585
|
+
"Content-Type": "application/json"
|
|
586
|
+
}),
|
|
587
|
+
body: JSON.stringify(deviceInfo)
|
|
588
|
+
});
|
|
589
|
+
if (!response.ok) {
|
|
590
|
+
const body = await response.text();
|
|
591
|
+
throw new Error(
|
|
592
|
+
`Failed to initiate device authorization (${response.status}): ${body}`
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
return response.json();
|
|
596
|
+
}
|
|
597
|
+
async function pollForSession(convexSiteUrl, deviceCode, interval, expiresIn, timeoutSeconds) {
|
|
598
|
+
const tokenUrl = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/device/token`;
|
|
599
|
+
const deadline = Date.now() + Math.min(expiresIn, timeoutSeconds) * 1e3;
|
|
600
|
+
let currentInterval = interval;
|
|
601
|
+
while (Date.now() < deadline) {
|
|
602
|
+
await sleep(currentInterval * 1e3);
|
|
603
|
+
const response = await fetch(tokenUrl, {
|
|
604
|
+
method: "POST",
|
|
605
|
+
headers: mergeAutomationHeaders({
|
|
606
|
+
"Content-Type": "application/json"
|
|
607
|
+
}),
|
|
608
|
+
body: JSON.stringify({ device_code: deviceCode })
|
|
609
|
+
});
|
|
610
|
+
if (response.ok) {
|
|
611
|
+
const result = await response.json();
|
|
612
|
+
return {
|
|
613
|
+
sessionToken: result.session_token,
|
|
614
|
+
expiresAt: result.expires_at,
|
|
615
|
+
user: result.user
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
let errorCode;
|
|
619
|
+
try {
|
|
620
|
+
const errorBody = await response.json();
|
|
621
|
+
errorCode = errorBody.error;
|
|
622
|
+
} catch {
|
|
623
|
+
throw new Error(`Device auth polling error: HTTP ${response.status}`);
|
|
624
|
+
}
|
|
625
|
+
if (errorCode === "authorization_pending") {
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (errorCode === "slow_down") {
|
|
629
|
+
currentInterval += 5;
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
if (errorCode === "expired_token") {
|
|
633
|
+
throw new DeviceAuthExpiredError();
|
|
634
|
+
}
|
|
635
|
+
if (errorCode === "access_denied") {
|
|
636
|
+
throw new DeviceAuthDeniedError();
|
|
637
|
+
}
|
|
638
|
+
throw new Error(
|
|
639
|
+
`Device auth polling error: ${errorCode ?? `HTTP ${response.status}`}`
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
throw new DeviceAuthTimeoutError();
|
|
643
|
+
}
|
|
644
|
+
async function fetchSessionInfo(convexSiteUrl, sessionToken) {
|
|
645
|
+
const url = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/sessions/me`;
|
|
646
|
+
const response = await fetch(url, {
|
|
647
|
+
method: "GET",
|
|
648
|
+
headers: mergeAutomationHeaders({
|
|
649
|
+
Authorization: `Bearer ${sessionToken}`
|
|
650
|
+
})
|
|
651
|
+
});
|
|
652
|
+
if (response.status === 404) {
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
if (!response.ok) {
|
|
656
|
+
const body = await response.text();
|
|
657
|
+
throw new Error(
|
|
658
|
+
`Failed to fetch session info (${response.status}): ${body}`
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
return response.json();
|
|
662
|
+
}
|
|
663
|
+
async function revokeSession(convexSiteUrl, sessionToken) {
|
|
664
|
+
const url = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/sessions/me`;
|
|
665
|
+
const response = await fetch(url, {
|
|
666
|
+
method: "DELETE",
|
|
667
|
+
headers: mergeAutomationHeaders({
|
|
668
|
+
Authorization: `Bearer ${sessionToken}`
|
|
669
|
+
})
|
|
670
|
+
});
|
|
671
|
+
if (response.status === 404) {
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
if (!response.ok) {
|
|
675
|
+
const body = await response.text();
|
|
676
|
+
throw new Error(`Failed to revoke session (${response.status}): ${body}`);
|
|
677
|
+
}
|
|
678
|
+
return true;
|
|
679
|
+
}
|
|
680
|
+
function openBrowser(url) {
|
|
681
|
+
if (process6.env.BRAID_DISABLE_BROWSER_OPEN === "1" || process6.env.BRAID_DISABLE_BROWSER_OPEN === "true") {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
const currentPlatform = platform();
|
|
685
|
+
if (currentPlatform === "darwin") {
|
|
686
|
+
execFile("open", [url], noop);
|
|
687
|
+
} else if (currentPlatform === "win32") {
|
|
688
|
+
execFile("cmd", ["/c", "start", "", url], noop);
|
|
689
|
+
} else {
|
|
690
|
+
execFile("xdg-open", [url], noop);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function getDeviceInfo() {
|
|
694
|
+
return {
|
|
695
|
+
deviceName: hostname(),
|
|
696
|
+
deviceOs: platform(),
|
|
697
|
+
deviceHostname: hostname()
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
var TRAILING_SLASHES2, LEGACY_BRAID_AUTH_HOSTS, BRAID_APP_HOST, DEFAULT_BRAID_AUTH_HOSTS, LOOPBACK_HOSTS2, LOCAL_AUTH_ENV_FILES, LOCAL_AUTH_ENV_KEYS, NEWLINE_REGEX2, DeviceAuthTimeoutError, DeviceAuthDeniedError, DeviceAuthExpiredError, sleep, normalizeBaseUrl2, normalizeLoopbackBaseUrl, isLoopbackHost, isLoopbackUrl, stripQuotes2, parseDotenv2, resolveLocalAuthWebBaseUrlFromEnv, resolveLocalAuthWebBaseUrlFromFiles, resolveLocalAuthWebBaseUrl, normalizeServerBaseUrl, resolveCanonicalAuthWebBaseUrl, isHostedBraidAuthServer, noop;
|
|
701
|
+
var init_device_auth = __esm({
|
|
702
|
+
"src/lib/device-auth.ts"() {
|
|
506
703
|
"use strict";
|
|
507
704
|
init_esm_shims();
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
705
|
+
init_automation_headers();
|
|
706
|
+
init_braid_workspace();
|
|
707
|
+
TRAILING_SLASHES2 = /\/+$/;
|
|
708
|
+
LEGACY_BRAID_AUTH_HOSTS = /* @__PURE__ */ new Set([
|
|
709
|
+
"api.braid.cloud",
|
|
710
|
+
"braid.cloud",
|
|
711
|
+
"www.braid.cloud"
|
|
712
|
+
]);
|
|
713
|
+
BRAID_APP_HOST = "app.braid.cloud";
|
|
714
|
+
DEFAULT_BRAID_AUTH_HOSTS = /* @__PURE__ */ new Set([
|
|
715
|
+
...LEGACY_BRAID_AUTH_HOSTS,
|
|
716
|
+
BRAID_APP_HOST
|
|
717
|
+
]);
|
|
718
|
+
LOOPBACK_HOSTS2 = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
|
|
719
|
+
LOCAL_AUTH_ENV_FILES = [
|
|
720
|
+
["apps", "web", ".env.local"],
|
|
721
|
+
["apps", "convex", ".env.local"]
|
|
722
|
+
];
|
|
723
|
+
LOCAL_AUTH_ENV_KEYS = ["APP_URL", "SITE_URL"];
|
|
724
|
+
NEWLINE_REGEX2 = /\r?\n/;
|
|
725
|
+
DeviceAuthTimeoutError = class extends Error {
|
|
726
|
+
constructor() {
|
|
727
|
+
super("Device authorization timed out");
|
|
728
|
+
this.name = "DeviceAuthTimeoutError";
|
|
528
729
|
}
|
|
529
730
|
};
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
NetworkError = class extends Data3.TaggedError("NetworkError") {
|
|
535
|
-
};
|
|
536
|
-
resolveApiKey = (optionsApiKey) => {
|
|
537
|
-
if (optionsApiKey) {
|
|
538
|
-
return Effect4.succeed(optionsApiKey);
|
|
731
|
+
DeviceAuthDeniedError = class extends Error {
|
|
732
|
+
constructor() {
|
|
733
|
+
super("Device authorization was denied");
|
|
734
|
+
this.name = "DeviceAuthDeniedError";
|
|
539
735
|
}
|
|
540
|
-
return pipe4(
|
|
541
|
-
Effect4.tryPromise({
|
|
542
|
-
try: () => getApiKeyAsync(),
|
|
543
|
-
catch: () => new NetworkError({ message: "Failed to read config" })
|
|
544
|
-
}),
|
|
545
|
-
Effect4.flatMap(
|
|
546
|
-
(key) => key ? Effect4.succeed(key) : Effect4.fail(
|
|
547
|
-
new AuthenticationError({
|
|
548
|
-
message: 'No API key configured. Run "braid auth" to authenticate.'
|
|
549
|
-
})
|
|
550
|
-
)
|
|
551
|
-
)
|
|
552
|
-
);
|
|
553
736
|
};
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
new NetworkError({
|
|
559
|
-
message: `Untrusted server URL '${optionsServerUrl}'. Set ${ALLOW_UNTRUSTED_SERVER_ENV}=true to override.`
|
|
560
|
-
})
|
|
561
|
-
);
|
|
562
|
-
}
|
|
563
|
-
return Effect4.succeed(optionsServerUrl);
|
|
737
|
+
DeviceAuthExpiredError = class extends Error {
|
|
738
|
+
constructor() {
|
|
739
|
+
super("Device authorization code has expired");
|
|
740
|
+
this.name = "DeviceAuthExpiredError";
|
|
564
741
|
}
|
|
565
|
-
return pipe4(
|
|
566
|
-
Effect4.tryPromise({
|
|
567
|
-
try: () => getServerUrlAsync(),
|
|
568
|
-
catch: () => new NetworkError({ message: "Failed to read config" })
|
|
569
|
-
}),
|
|
570
|
-
Effect4.flatMap((serverUrl) => {
|
|
571
|
-
if (isTruthy(process.env[ALLOW_UNTRUSTED_SERVER_ENV]) || isTrustedApiServerUrl(serverUrl)) {
|
|
572
|
-
return Effect4.succeed(serverUrl);
|
|
573
|
-
}
|
|
574
|
-
return Effect4.fail(
|
|
575
|
-
new NetworkError({
|
|
576
|
-
message: `Untrusted server URL '${serverUrl}'. Set ${ALLOW_UNTRUSTED_SERVER_ENV}=true to override.`
|
|
577
|
-
})
|
|
578
|
-
);
|
|
579
|
-
})
|
|
580
|
-
);
|
|
581
742
|
};
|
|
582
|
-
|
|
583
|
-
|
|
743
|
+
sleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
744
|
+
normalizeBaseUrl2 = (rawUrl) => {
|
|
745
|
+
const trimmed = rawUrl.replace(TRAILING_SLASHES2, "");
|
|
584
746
|
try {
|
|
585
747
|
const url = new URL(trimmed);
|
|
586
748
|
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
@@ -588,13 +750,295 @@ var init_api = __esm({
|
|
|
588
750
|
return trimmed;
|
|
589
751
|
}
|
|
590
752
|
};
|
|
753
|
+
normalizeLoopbackBaseUrl = (rawUrl) => {
|
|
754
|
+
const normalized = normalizeBaseUrl2(rawUrl);
|
|
755
|
+
try {
|
|
756
|
+
const url = new URL(normalized);
|
|
757
|
+
if (isLoopbackHost(url.hostname)) {
|
|
758
|
+
url.hostname = "localhost";
|
|
759
|
+
}
|
|
760
|
+
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
761
|
+
} catch {
|
|
762
|
+
return normalized;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
isLoopbackHost = (hostname2) => LOOPBACK_HOSTS2.has(hostname2);
|
|
766
|
+
isLoopbackUrl = (rawUrl) => {
|
|
767
|
+
try {
|
|
768
|
+
return isLoopbackHost(new URL(rawUrl).hostname);
|
|
769
|
+
} catch {
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
stripQuotes2 = (value) => {
|
|
774
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
775
|
+
return value.slice(1, -1);
|
|
776
|
+
}
|
|
777
|
+
return value;
|
|
778
|
+
};
|
|
779
|
+
parseDotenv2 = (content) => {
|
|
780
|
+
const result = {};
|
|
781
|
+
for (const rawLine of content.split(NEWLINE_REGEX2)) {
|
|
782
|
+
const line = rawLine.trim();
|
|
783
|
+
if (!line || line.startsWith("#")) {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
const separatorIndex = line.indexOf("=");
|
|
787
|
+
if (separatorIndex <= 0) {
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
791
|
+
const value = line.slice(separatorIndex + 1).trim();
|
|
792
|
+
result[key] = stripQuotes2(value);
|
|
793
|
+
}
|
|
794
|
+
return result;
|
|
795
|
+
};
|
|
796
|
+
resolveLocalAuthWebBaseUrlFromEnv = (env) => {
|
|
797
|
+
for (const key of LOCAL_AUTH_ENV_KEYS) {
|
|
798
|
+
const value = env[key];
|
|
799
|
+
if (value && isLoopbackUrl(value)) {
|
|
800
|
+
return normalizeLoopbackBaseUrl(value);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return void 0;
|
|
804
|
+
};
|
|
805
|
+
resolveLocalAuthWebBaseUrlFromFiles = () => {
|
|
806
|
+
const workspaceRoot = findBraidWorkspaceRoot();
|
|
807
|
+
if (!workspaceRoot) {
|
|
808
|
+
return void 0;
|
|
809
|
+
}
|
|
810
|
+
for (const envFile of LOCAL_AUTH_ENV_FILES) {
|
|
811
|
+
const envPath = join4(workspaceRoot, ...envFile);
|
|
812
|
+
if (!existsSync3(envPath)) {
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
const localAppUrl = resolveLocalAuthWebBaseUrlFromEnv(
|
|
816
|
+
parseDotenv2(readFileSync3(envPath, "utf8"))
|
|
817
|
+
);
|
|
818
|
+
if (localAppUrl) {
|
|
819
|
+
return localAppUrl;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
return void 0;
|
|
823
|
+
};
|
|
824
|
+
resolveLocalAuthWebBaseUrl = () => resolveLocalAuthWebBaseUrlFromEnv(process6.env) ?? resolveLocalAuthWebBaseUrlFromFiles();
|
|
825
|
+
normalizeServerBaseUrl = (serverUrl) => {
|
|
826
|
+
const trimmed = normalizeBaseUrl2(serverUrl);
|
|
827
|
+
try {
|
|
828
|
+
const url = new URL(trimmed);
|
|
829
|
+
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
830
|
+
} catch {
|
|
831
|
+
return trimmed;
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
resolveCanonicalAuthWebBaseUrl = (serverUrl) => {
|
|
835
|
+
const normalized = normalizeServerBaseUrl(serverUrl);
|
|
836
|
+
try {
|
|
837
|
+
const url = new URL(normalized);
|
|
838
|
+
if (LEGACY_BRAID_AUTH_HOSTS.has(url.hostname)) {
|
|
839
|
+
url.hostname = BRAID_APP_HOST;
|
|
840
|
+
url.pathname = "/";
|
|
841
|
+
}
|
|
842
|
+
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
843
|
+
} catch {
|
|
844
|
+
return normalized;
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
isHostedBraidAuthServer = (serverUrl) => {
|
|
848
|
+
try {
|
|
849
|
+
return DEFAULT_BRAID_AUTH_HOSTS.has(
|
|
850
|
+
new URL(normalizeServerBaseUrl(serverUrl)).hostname
|
|
851
|
+
);
|
|
852
|
+
} catch {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
noop = () => {
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
// src/lib/api.ts
|
|
862
|
+
import { Data as Data3, Effect as Effect4, pipe as pipe4 } from "effect";
|
|
863
|
+
var TRAILING_SLASH_REGEX, ALLOW_UNTRUSTED_SERVER_ENV, SESSION_TOKEN_PREFIX, isTruthy, isLocalHost, isConvexSiteHost, isTrustedApiServerUrl, isSessionApiServerUrl, REAUTH_REQUIRED_MESSAGE, RAW_AUTH_ERROR_PATTERN, normalizeAuthenticationErrorMessage, ApiError, AuthenticationError, NetworkError, resolveApiKey, resolveServerUrl, resolveApiRequestServerUrl, normalizeApiServerBaseUrl, readJsonResponseAsync, readJsonResponse, getApiErrorResponse, isAuthenticationErrorResponse, parseResponse, buildApiUrl, buildExportUrl, executeApiRequest, parseScopeOptionsResponse, fetchScopeOptions, buildLibraryOptionsUrl, fetchLibraryOptions, fetchSkills, runLifecycleCommand, DEFAULT_PUBLIC_SERVER_URL, NotFoundError, RateLimitedError, handlePublicApiResponse, fetchPublicMetadata, fetchPublicExport, fetchPublicMetadataAsync, fetchPublicExportAsync, validateApiKey, fetchSkillsAsync, validateApiKeyAsync, fetchScopeOptionsAsync, fetchLibraryOptionsAsync, runLifecycleCommandAsync;
|
|
864
|
+
var init_api = __esm({
|
|
865
|
+
"src/lib/api.ts"() {
|
|
866
|
+
"use strict";
|
|
867
|
+
init_esm_shims();
|
|
868
|
+
init_automation_headers();
|
|
869
|
+
init_config();
|
|
870
|
+
init_device_auth();
|
|
871
|
+
TRAILING_SLASH_REGEX = /\/$/;
|
|
872
|
+
ALLOW_UNTRUSTED_SERVER_ENV = "BRAID_ALLOW_UNTRUSTED_SERVER_URL";
|
|
873
|
+
SESSION_TOKEN_PREFIX = "brs_";
|
|
874
|
+
isTruthy = (value) => value === "1" || value === "true" || value === "yes";
|
|
875
|
+
isLocalHost = (hostname2) => hostname2 === "localhost" || hostname2 === "127.0.0.1" || hostname2 === "::1";
|
|
876
|
+
isConvexSiteHost = (hostname2) => hostname2.endsWith(".convex.site");
|
|
877
|
+
isTrustedApiServerUrl = (serverUrl) => {
|
|
878
|
+
try {
|
|
879
|
+
const parsed = new URL(serverUrl);
|
|
880
|
+
const hostname2 = parsed.hostname;
|
|
881
|
+
const isBraidHost = hostname2 === "braid.cloud" || hostname2.endsWith(".braid.cloud");
|
|
882
|
+
const isConvexSite = isConvexSiteHost(hostname2);
|
|
883
|
+
if (parsed.protocol === "https:" && (isBraidHost || isConvexSite)) {
|
|
884
|
+
return true;
|
|
885
|
+
}
|
|
886
|
+
if (parsed.protocol === "http:" && isLocalHost(hostname2)) {
|
|
887
|
+
return true;
|
|
888
|
+
}
|
|
889
|
+
return false;
|
|
890
|
+
} catch {
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
isSessionApiServerUrl = (serverUrl) => {
|
|
895
|
+
try {
|
|
896
|
+
const hostname2 = new URL(serverUrl).hostname;
|
|
897
|
+
return isConvexSiteHost(hostname2) || isLocalHost(hostname2);
|
|
898
|
+
} catch {
|
|
899
|
+
return false;
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
REAUTH_REQUIRED_MESSAGE = "Invalid or expired API key. Run 'braid auth' to re-authenticate.";
|
|
903
|
+
RAW_AUTH_ERROR_PATTERN = /invalid authentication token|authentication token expired|token expired|not authenticated/i;
|
|
904
|
+
normalizeAuthenticationErrorMessage = (message) => {
|
|
905
|
+
if (!message || RAW_AUTH_ERROR_PATTERN.test(message)) {
|
|
906
|
+
return REAUTH_REQUIRED_MESSAGE;
|
|
907
|
+
}
|
|
908
|
+
return message;
|
|
909
|
+
};
|
|
910
|
+
ApiError = class extends Data3.TaggedError("ApiError") {
|
|
911
|
+
};
|
|
912
|
+
AuthenticationError = class extends Data3.TaggedError("AuthenticationError") {
|
|
913
|
+
};
|
|
914
|
+
NetworkError = class extends Data3.TaggedError("NetworkError") {
|
|
915
|
+
};
|
|
916
|
+
resolveApiKey = (optionsApiKey) => {
|
|
917
|
+
if (optionsApiKey) {
|
|
918
|
+
return Effect4.succeed(optionsApiKey);
|
|
919
|
+
}
|
|
920
|
+
return pipe4(
|
|
921
|
+
Effect4.tryPromise({
|
|
922
|
+
try: () => getApiKeyAsync(),
|
|
923
|
+
catch: () => new NetworkError({ message: "Failed to read config" })
|
|
924
|
+
}),
|
|
925
|
+
Effect4.flatMap(
|
|
926
|
+
(key) => key ? Effect4.succeed(key) : Effect4.fail(
|
|
927
|
+
new AuthenticationError({
|
|
928
|
+
message: 'No API key configured. Run "braid auth" to authenticate.'
|
|
929
|
+
})
|
|
930
|
+
)
|
|
931
|
+
)
|
|
932
|
+
);
|
|
933
|
+
};
|
|
934
|
+
resolveServerUrl = (optionsServerUrl) => {
|
|
935
|
+
if (optionsServerUrl) {
|
|
936
|
+
if (!(isTruthy(process.env[ALLOW_UNTRUSTED_SERVER_ENV]) || isTrustedApiServerUrl(optionsServerUrl))) {
|
|
937
|
+
return Effect4.fail(
|
|
938
|
+
new NetworkError({
|
|
939
|
+
message: `Untrusted server URL '${optionsServerUrl}'. Set ${ALLOW_UNTRUSTED_SERVER_ENV}=true to override.`
|
|
940
|
+
})
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
return Effect4.succeed(optionsServerUrl);
|
|
944
|
+
}
|
|
945
|
+
return pipe4(
|
|
946
|
+
Effect4.tryPromise({
|
|
947
|
+
try: () => getServerUrlAsync(),
|
|
948
|
+
catch: () => new NetworkError({ message: "Failed to read config" })
|
|
949
|
+
}),
|
|
950
|
+
Effect4.flatMap((serverUrl) => {
|
|
951
|
+
if (isTruthy(process.env[ALLOW_UNTRUSTED_SERVER_ENV]) || isTrustedApiServerUrl(serverUrl)) {
|
|
952
|
+
return Effect4.succeed(serverUrl);
|
|
953
|
+
}
|
|
954
|
+
return Effect4.fail(
|
|
955
|
+
new NetworkError({
|
|
956
|
+
message: `Untrusted server URL '${serverUrl}'. Set ${ALLOW_UNTRUSTED_SERVER_ENV}=true to override.`
|
|
957
|
+
})
|
|
958
|
+
);
|
|
959
|
+
})
|
|
960
|
+
);
|
|
961
|
+
};
|
|
962
|
+
resolveApiRequestServerUrl = (serverUrl, apiKey) => {
|
|
963
|
+
if (!apiKey?.startsWith(SESSION_TOKEN_PREFIX)) {
|
|
964
|
+
return Effect4.succeed(serverUrl);
|
|
965
|
+
}
|
|
966
|
+
if (isSessionApiServerUrl(serverUrl)) {
|
|
967
|
+
return Effect4.succeed(serverUrl);
|
|
968
|
+
}
|
|
969
|
+
return pipe4(
|
|
970
|
+
Effect4.tryPromise({
|
|
971
|
+
try: async () => {
|
|
972
|
+
const authConfig = await fetchAuthConfig(serverUrl);
|
|
973
|
+
return authConfig.convexSiteUrl.replace(TRAILING_SLASH_REGEX, "");
|
|
974
|
+
},
|
|
975
|
+
catch: (cause) => new NetworkError({
|
|
976
|
+
message: `Failed to resolve session API server for ${serverUrl}`,
|
|
977
|
+
cause
|
|
978
|
+
})
|
|
979
|
+
}),
|
|
980
|
+
Effect4.flatMap((resolvedServerUrl) => {
|
|
981
|
+
if (isTruthy(process.env[ALLOW_UNTRUSTED_SERVER_ENV]) || isTrustedApiServerUrl(resolvedServerUrl)) {
|
|
982
|
+
return Effect4.succeed(resolvedServerUrl);
|
|
983
|
+
}
|
|
984
|
+
return Effect4.fail(
|
|
985
|
+
new NetworkError({
|
|
986
|
+
message: `Untrusted server URL '${resolvedServerUrl}'. Set ${ALLOW_UNTRUSTED_SERVER_ENV}=true to override.`
|
|
987
|
+
})
|
|
988
|
+
);
|
|
989
|
+
})
|
|
990
|
+
);
|
|
991
|
+
};
|
|
992
|
+
normalizeApiServerBaseUrl = (serverUrl) => {
|
|
993
|
+
const trimmed = serverUrl.replace(TRAILING_SLASH_REGEX, "");
|
|
994
|
+
try {
|
|
995
|
+
const url = new URL(trimmed);
|
|
996
|
+
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
997
|
+
} catch {
|
|
998
|
+
return trimmed;
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
readJsonResponseAsync = async (response) => {
|
|
1002
|
+
const raw = await response.text();
|
|
1003
|
+
if (raw.trim().length === 0) {
|
|
1004
|
+
if (response.ok) {
|
|
1005
|
+
throw new Error("Empty API response");
|
|
1006
|
+
}
|
|
1007
|
+
return null;
|
|
1008
|
+
}
|
|
1009
|
+
try {
|
|
1010
|
+
return JSON.parse(raw);
|
|
1011
|
+
} catch (error) {
|
|
1012
|
+
if (!response.ok) {
|
|
1013
|
+
return null;
|
|
1014
|
+
}
|
|
1015
|
+
throw error;
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
readJsonResponse = (response) => Effect4.tryPromise({
|
|
1019
|
+
try: () => readJsonResponseAsync(response),
|
|
1020
|
+
catch: () => new NetworkError({ message: "Failed to parse API response" })
|
|
1021
|
+
});
|
|
1022
|
+
getApiErrorResponse = (json) => {
|
|
1023
|
+
if (typeof json !== "object" || json === null || Array.isArray(json)) {
|
|
1024
|
+
return {};
|
|
1025
|
+
}
|
|
1026
|
+
return json;
|
|
1027
|
+
};
|
|
1028
|
+
isAuthenticationErrorResponse = (response, json) => {
|
|
1029
|
+
if (response.status === 401) {
|
|
1030
|
+
return true;
|
|
1031
|
+
}
|
|
1032
|
+
const errorResponse = getApiErrorResponse(json);
|
|
1033
|
+
return RAW_AUTH_ERROR_PATTERN.test(errorResponse.error ?? "");
|
|
1034
|
+
};
|
|
591
1035
|
parseResponse = (response, json) => {
|
|
592
1036
|
if (!response.ok) {
|
|
593
|
-
const errorResponse = json;
|
|
594
|
-
if (response
|
|
1037
|
+
const errorResponse = getApiErrorResponse(json);
|
|
1038
|
+
if (isAuthenticationErrorResponse(response, json)) {
|
|
595
1039
|
return Effect4.fail(
|
|
596
1040
|
new AuthenticationError({
|
|
597
|
-
message: errorResponse.error
|
|
1041
|
+
message: normalizeAuthenticationErrorMessage(errorResponse.error)
|
|
598
1042
|
})
|
|
599
1043
|
);
|
|
600
1044
|
}
|
|
@@ -653,10 +1097,10 @@ var init_api = __esm({
|
|
|
653
1097
|
Effect4.tryPromise({
|
|
654
1098
|
try: () => fetch(url.toString(), {
|
|
655
1099
|
method: "GET",
|
|
656
|
-
headers: {
|
|
1100
|
+
headers: mergeAutomationHeaders({
|
|
657
1101
|
"Content-Type": "application/json",
|
|
658
1102
|
...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
|
|
659
|
-
}
|
|
1103
|
+
})
|
|
660
1104
|
}),
|
|
661
1105
|
catch: (e) => new NetworkError({
|
|
662
1106
|
message: `Failed to connect to ${serverUrl}`,
|
|
@@ -666,7 +1110,7 @@ var init_api = __esm({
|
|
|
666
1110
|
Effect4.flatMap(
|
|
667
1111
|
(response) => pipe4(
|
|
668
1112
|
Effect4.tryPromise({
|
|
669
|
-
try: () => response
|
|
1113
|
+
try: () => readJsonResponseAsync(response),
|
|
670
1114
|
catch: () => new NetworkError({ message: "Failed to parse API response" })
|
|
671
1115
|
}),
|
|
672
1116
|
Effect4.flatMap((json) => parseResponse(response, json))
|
|
@@ -675,11 +1119,11 @@ var init_api = __esm({
|
|
|
675
1119
|
);
|
|
676
1120
|
parseScopeOptionsResponse = (response, json) => {
|
|
677
1121
|
if (!response.ok) {
|
|
678
|
-
const errorResponse = json;
|
|
679
|
-
if (response
|
|
1122
|
+
const errorResponse = getApiErrorResponse(json);
|
|
1123
|
+
if (isAuthenticationErrorResponse(response, json)) {
|
|
680
1124
|
return Effect4.fail(
|
|
681
1125
|
new AuthenticationError({
|
|
682
|
-
message: errorResponse.error
|
|
1126
|
+
message: normalizeAuthenticationErrorMessage(errorResponse.error)
|
|
683
1127
|
})
|
|
684
1128
|
);
|
|
685
1129
|
}
|
|
@@ -698,33 +1142,37 @@ var init_api = __esm({
|
|
|
698
1142
|
apiKey: resolveApiKey(options.apiKey),
|
|
699
1143
|
serverUrl: resolveServerUrl(options.serverUrl)
|
|
700
1144
|
}),
|
|
701
|
-
Effect4.flatMap(
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
Effect4.
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
headers: {
|
|
708
|
-
Authorization: `Bearer ${apiKey}`,
|
|
709
|
-
"Content-Type": "application/json"
|
|
710
|
-
}
|
|
711
|
-
}),
|
|
712
|
-
catch: (e) => new NetworkError({
|
|
713
|
-
message: `Failed to connect to ${serverUrl}`,
|
|
714
|
-
cause: e
|
|
715
|
-
})
|
|
716
|
-
}),
|
|
717
|
-
Effect4.flatMap(
|
|
718
|
-
(response) => pipe4(
|
|
1145
|
+
Effect4.flatMap(
|
|
1146
|
+
({ apiKey, serverUrl }) => pipe4(
|
|
1147
|
+
resolveApiRequestServerUrl(serverUrl, apiKey),
|
|
1148
|
+
Effect4.flatMap((apiServerUrl) => {
|
|
1149
|
+
const url = buildApiUrl(apiServerUrl, "/api/skills/scope-options");
|
|
1150
|
+
return pipe4(
|
|
719
1151
|
Effect4.tryPromise({
|
|
720
|
-
try: () =>
|
|
721
|
-
|
|
1152
|
+
try: () => fetch(url.toString(), {
|
|
1153
|
+
method: "GET",
|
|
1154
|
+
headers: mergeAutomationHeaders({
|
|
1155
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1156
|
+
"Content-Type": "application/json"
|
|
1157
|
+
})
|
|
1158
|
+
}),
|
|
1159
|
+
catch: (e) => new NetworkError({
|
|
1160
|
+
message: `Failed to connect to ${apiServerUrl}`,
|
|
1161
|
+
cause: e
|
|
1162
|
+
})
|
|
722
1163
|
}),
|
|
723
|
-
Effect4.flatMap(
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
1164
|
+
Effect4.flatMap(
|
|
1165
|
+
(response) => pipe4(
|
|
1166
|
+
readJsonResponse(response),
|
|
1167
|
+
Effect4.flatMap(
|
|
1168
|
+
(json) => parseScopeOptionsResponse(response, json)
|
|
1169
|
+
)
|
|
1170
|
+
)
|
|
1171
|
+
)
|
|
1172
|
+
);
|
|
1173
|
+
})
|
|
1174
|
+
)
|
|
1175
|
+
)
|
|
728
1176
|
);
|
|
729
1177
|
buildLibraryOptionsUrl = (serverUrl, options) => {
|
|
730
1178
|
const url = buildApiUrl(serverUrl, "/api/skills/library-options");
|
|
@@ -758,41 +1206,57 @@ var init_api = __esm({
|
|
|
758
1206
|
}),
|
|
759
1207
|
Effect4.flatMap(
|
|
760
1208
|
({ apiKey, serverUrl }) => pipe4(
|
|
761
|
-
|
|
762
|
-
try: () => fetch(buildLibraryOptionsUrl(serverUrl, options).toString(), {
|
|
763
|
-
method: "GET",
|
|
764
|
-
headers: {
|
|
765
|
-
Authorization: `Bearer ${apiKey}`,
|
|
766
|
-
"Content-Type": "application/json"
|
|
767
|
-
}
|
|
768
|
-
}),
|
|
769
|
-
catch: (e) => new NetworkError({
|
|
770
|
-
message: `Failed to connect to ${serverUrl}`,
|
|
771
|
-
cause: e
|
|
772
|
-
})
|
|
773
|
-
}),
|
|
1209
|
+
resolveApiRequestServerUrl(serverUrl, apiKey),
|
|
774
1210
|
Effect4.flatMap(
|
|
775
|
-
(
|
|
1211
|
+
(apiServerUrl) => pipe4(
|
|
776
1212
|
Effect4.tryPromise({
|
|
777
|
-
try: () =>
|
|
778
|
-
|
|
1213
|
+
try: () => fetch(
|
|
1214
|
+
buildLibraryOptionsUrl(apiServerUrl, options).toString(),
|
|
1215
|
+
{
|
|
1216
|
+
method: "GET",
|
|
1217
|
+
headers: mergeAutomationHeaders({
|
|
1218
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1219
|
+
"Content-Type": "application/json"
|
|
1220
|
+
})
|
|
1221
|
+
}
|
|
1222
|
+
),
|
|
1223
|
+
catch: (e) => new NetworkError({
|
|
1224
|
+
message: `Failed to connect to ${apiServerUrl}`,
|
|
1225
|
+
cause: e
|
|
1226
|
+
})
|
|
779
1227
|
}),
|
|
780
|
-
Effect4.flatMap(
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1228
|
+
Effect4.flatMap(
|
|
1229
|
+
(response) => pipe4(
|
|
1230
|
+
readJsonResponse(response),
|
|
1231
|
+
Effect4.flatMap(
|
|
1232
|
+
(json) => {
|
|
1233
|
+
if (!response.ok) {
|
|
1234
|
+
return pipe4(
|
|
1235
|
+
parseResponse(response, json),
|
|
1236
|
+
Effect4.flatMap(
|
|
1237
|
+
() => Effect4.fail(
|
|
1238
|
+
new ApiError({
|
|
1239
|
+
message: "API request failed",
|
|
1240
|
+
code: "UNKNOWN_ERROR",
|
|
1241
|
+
status: response.status
|
|
1242
|
+
})
|
|
1243
|
+
)
|
|
1244
|
+
),
|
|
1245
|
+
Effect4.catchTag(
|
|
1246
|
+
"AuthenticationError",
|
|
1247
|
+
(error) => Effect4.fail(error)
|
|
1248
|
+
),
|
|
1249
|
+
Effect4.catchTag(
|
|
1250
|
+
"ApiError",
|
|
1251
|
+
(error) => Effect4.fail(error)
|
|
1252
|
+
)
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
return Effect4.succeed(json);
|
|
1256
|
+
}
|
|
1257
|
+
)
|
|
1258
|
+
)
|
|
1259
|
+
)
|
|
796
1260
|
)
|
|
797
1261
|
)
|
|
798
1262
|
)
|
|
@@ -803,10 +1267,15 @@ var init_api = __esm({
|
|
|
803
1267
|
apiKey: options.demo ? Effect4.succeed(options.apiKey) : resolveApiKey(options.apiKey),
|
|
804
1268
|
serverUrl: resolveServerUrl(options.serverUrl)
|
|
805
1269
|
}),
|
|
806
|
-
Effect4.flatMap(
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1270
|
+
Effect4.flatMap(
|
|
1271
|
+
({ apiKey, serverUrl }) => pipe4(
|
|
1272
|
+
resolveApiRequestServerUrl(serverUrl, apiKey),
|
|
1273
|
+
Effect4.flatMap((apiServerUrl) => {
|
|
1274
|
+
const url = buildExportUrl(apiServerUrl, options);
|
|
1275
|
+
return executeApiRequest(url, apiKey, apiServerUrl);
|
|
1276
|
+
})
|
|
1277
|
+
)
|
|
1278
|
+
)
|
|
810
1279
|
);
|
|
811
1280
|
runLifecycleCommand = (request, options = {}) => pipe4(
|
|
812
1281
|
Effect4.all({
|
|
@@ -814,45 +1283,56 @@ var init_api = __esm({
|
|
|
814
1283
|
serverUrl: resolveServerUrl(options.serverUrl)
|
|
815
1284
|
}),
|
|
816
1285
|
Effect4.flatMap(
|
|
817
|
-
({ apiKey, serverUrl }) =>
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
{
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
1286
|
+
({ apiKey, serverUrl }) => pipe4(
|
|
1287
|
+
resolveApiRequestServerUrl(serverUrl, apiKey),
|
|
1288
|
+
Effect4.flatMap(
|
|
1289
|
+
(apiServerUrl) => Effect4.tryPromise({
|
|
1290
|
+
try: async () => {
|
|
1291
|
+
const response = await fetch(
|
|
1292
|
+
buildApiUrl(apiServerUrl, "/api/lifecycle").toString(),
|
|
1293
|
+
{
|
|
1294
|
+
method: "POST",
|
|
1295
|
+
headers: mergeAutomationHeaders({
|
|
1296
|
+
"Content-Type": "application/json",
|
|
1297
|
+
...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
|
|
1298
|
+
}),
|
|
1299
|
+
body: JSON.stringify({ ...request, demo: options.demo })
|
|
1300
|
+
}
|
|
1301
|
+
);
|
|
1302
|
+
const json = await readJsonResponseAsync(response).catch(() => {
|
|
1303
|
+
throw new NetworkError({
|
|
1304
|
+
message: "Failed to parse API response"
|
|
1305
|
+
});
|
|
1306
|
+
});
|
|
1307
|
+
if (!response.ok) {
|
|
1308
|
+
const errorResponse = getApiErrorResponse(json);
|
|
1309
|
+
if (isAuthenticationErrorResponse(response, json)) {
|
|
1310
|
+
throw new AuthenticationError({
|
|
1311
|
+
message: normalizeAuthenticationErrorMessage(
|
|
1312
|
+
errorResponse.error
|
|
1313
|
+
)
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
throw new ApiError({
|
|
1317
|
+
message: errorResponse.error || "API request failed",
|
|
1318
|
+
code: errorResponse.code || "UNKNOWN_ERROR",
|
|
1319
|
+
status: response.status
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
return json;
|
|
1323
|
+
},
|
|
1324
|
+
catch: (error) => {
|
|
1325
|
+
if (error instanceof ApiError || error instanceof AuthenticationError || error instanceof NetworkError) {
|
|
1326
|
+
return error;
|
|
1327
|
+
}
|
|
1328
|
+
return new NetworkError({
|
|
1329
|
+
message: `Failed to connect to ${apiServerUrl}`,
|
|
1330
|
+
cause: error
|
|
836
1331
|
});
|
|
837
1332
|
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
status: response.status
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
return json;
|
|
845
|
-
},
|
|
846
|
-
catch: (error) => {
|
|
847
|
-
if (error instanceof ApiError || error instanceof AuthenticationError || error instanceof NetworkError) {
|
|
848
|
-
return error;
|
|
849
|
-
}
|
|
850
|
-
return new NetworkError({
|
|
851
|
-
message: `Failed to connect to ${serverUrl}`,
|
|
852
|
-
cause: error
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
})
|
|
1333
|
+
})
|
|
1334
|
+
)
|
|
1335
|
+
)
|
|
856
1336
|
)
|
|
857
1337
|
);
|
|
858
1338
|
DEFAULT_PUBLIC_SERVER_URL = "https://braid.cloud";
|
|
@@ -879,7 +1359,7 @@ var init_api = __esm({
|
|
|
879
1359
|
})
|
|
880
1360
|
);
|
|
881
1361
|
}
|
|
882
|
-
const errorResponse = json;
|
|
1362
|
+
const errorResponse = getApiErrorResponse(json);
|
|
883
1363
|
return Effect4.fail(
|
|
884
1364
|
new ApiError({
|
|
885
1365
|
message: errorResponse.error || "API request failed",
|
|
@@ -899,7 +1379,10 @@ var init_api = __esm({
|
|
|
899
1379
|
}
|
|
900
1380
|
return pipe4(
|
|
901
1381
|
Effect4.tryPromise({
|
|
902
|
-
try: () => fetch(url.toString(), {
|
|
1382
|
+
try: () => fetch(url.toString(), {
|
|
1383
|
+
method: "GET",
|
|
1384
|
+
headers: mergeAutomationHeaders()
|
|
1385
|
+
}),
|
|
903
1386
|
catch: (e) => new NetworkError({
|
|
904
1387
|
message: `Failed to connect to ${baseUrl}`,
|
|
905
1388
|
cause: e
|
|
@@ -907,10 +1390,7 @@ var init_api = __esm({
|
|
|
907
1390
|
}),
|
|
908
1391
|
Effect4.flatMap(
|
|
909
1392
|
(response) => pipe4(
|
|
910
|
-
|
|
911
|
-
try: () => response.json(),
|
|
912
|
-
catch: () => new NetworkError({ message: "Failed to parse API response" })
|
|
913
|
-
}),
|
|
1393
|
+
readJsonResponse(response),
|
|
914
1394
|
Effect4.flatMap(
|
|
915
1395
|
(json) => handlePublicApiResponse(response, json)
|
|
916
1396
|
)
|
|
@@ -932,7 +1412,10 @@ var init_api = __esm({
|
|
|
932
1412
|
}
|
|
933
1413
|
return pipe4(
|
|
934
1414
|
Effect4.tryPromise({
|
|
935
|
-
try: () => fetch(url.toString(), {
|
|
1415
|
+
try: () => fetch(url.toString(), {
|
|
1416
|
+
method: "GET",
|
|
1417
|
+
headers: mergeAutomationHeaders()
|
|
1418
|
+
}),
|
|
936
1419
|
catch: (e) => new NetworkError({
|
|
937
1420
|
message: `Failed to connect to ${baseUrl}`,
|
|
938
1421
|
cause: e
|
|
@@ -940,10 +1423,7 @@ var init_api = __esm({
|
|
|
940
1423
|
}),
|
|
941
1424
|
Effect4.flatMap(
|
|
942
1425
|
(response) => pipe4(
|
|
943
|
-
|
|
944
|
-
try: () => response.json(),
|
|
945
|
-
catch: () => new NetworkError({ message: "Failed to parse API response" })
|
|
946
|
-
}),
|
|
1426
|
+
readJsonResponse(response),
|
|
947
1427
|
Effect4.flatMap(
|
|
948
1428
|
(json) => handlePublicApiResponse(response, json)
|
|
949
1429
|
)
|
|
@@ -975,10 +1455,10 @@ var init_api = __esm({
|
|
|
975
1455
|
url.searchParams.set("profile", "default");
|
|
976
1456
|
const response = await fetch(url.toString(), {
|
|
977
1457
|
method: "GET",
|
|
978
|
-
headers: {
|
|
1458
|
+
headers: mergeAutomationHeaders({
|
|
979
1459
|
Authorization: `Bearer ${apiKey}`,
|
|
980
1460
|
"Content-Type": "application/json"
|
|
981
|
-
}
|
|
1461
|
+
})
|
|
982
1462
|
});
|
|
983
1463
|
return response.status !== 401;
|
|
984
1464
|
},
|
|
@@ -998,7 +1478,7 @@ var init_api = __esm({
|
|
|
998
1478
|
});
|
|
999
1479
|
|
|
1000
1480
|
// src/lib/tui.ts
|
|
1001
|
-
import
|
|
1481
|
+
import process7 from "process";
|
|
1002
1482
|
import {
|
|
1003
1483
|
cancel as clackCancel,
|
|
1004
1484
|
confirm as clackConfirm,
|
|
@@ -1023,19 +1503,19 @@ function spinner() {
|
|
|
1023
1503
|
return {
|
|
1024
1504
|
start: (message) => {
|
|
1025
1505
|
if (message) {
|
|
1026
|
-
|
|
1506
|
+
process7.stdout.write(`${message}
|
|
1027
1507
|
`);
|
|
1028
1508
|
}
|
|
1029
1509
|
},
|
|
1030
1510
|
stop: (message) => {
|
|
1031
1511
|
if (message) {
|
|
1032
|
-
|
|
1512
|
+
process7.stdout.write(`${message}
|
|
1033
1513
|
`);
|
|
1034
1514
|
}
|
|
1035
1515
|
},
|
|
1036
1516
|
message: (message) => {
|
|
1037
1517
|
if (message) {
|
|
1038
|
-
|
|
1518
|
+
process7.stdout.write(`${message}
|
|
1039
1519
|
`);
|
|
1040
1520
|
}
|
|
1041
1521
|
}
|
|
@@ -1045,7 +1525,7 @@ function intro(message) {
|
|
|
1045
1525
|
if (isTTY) {
|
|
1046
1526
|
clackIntro(message);
|
|
1047
1527
|
} else {
|
|
1048
|
-
|
|
1528
|
+
process7.stdout.write(`
|
|
1049
1529
|
${message}
|
|
1050
1530
|
`);
|
|
1051
1531
|
}
|
|
@@ -1054,7 +1534,7 @@ function outro(message) {
|
|
|
1054
1534
|
if (isTTY) {
|
|
1055
1535
|
clackOutro(message);
|
|
1056
1536
|
} else {
|
|
1057
|
-
|
|
1537
|
+
process7.stdout.write(`${message}
|
|
1058
1538
|
|
|
1059
1539
|
`);
|
|
1060
1540
|
}
|
|
@@ -1064,7 +1544,7 @@ var init_tui = __esm({
|
|
|
1064
1544
|
"src/lib/tui.ts"() {
|
|
1065
1545
|
"use strict";
|
|
1066
1546
|
init_esm_shims();
|
|
1067
|
-
isTTY = Boolean(
|
|
1547
|
+
isTTY = Boolean(process7.stdout.isTTY);
|
|
1068
1548
|
cancel = clackCancel;
|
|
1069
1549
|
confirm = clackConfirm;
|
|
1070
1550
|
isCancel = clackIsCancel;
|
|
@@ -1174,10 +1654,10 @@ var scope_exports = {};
|
|
|
1174
1654
|
__export(scope_exports, {
|
|
1175
1655
|
scopeCommand: () => scopeCommand
|
|
1176
1656
|
});
|
|
1177
|
-
import
|
|
1657
|
+
import process9 from "process";
|
|
1178
1658
|
function exitCancelled(message) {
|
|
1179
1659
|
cancel(message);
|
|
1180
|
-
|
|
1660
|
+
process9.exit(0);
|
|
1181
1661
|
}
|
|
1182
1662
|
async function selectTargetFile(options) {
|
|
1183
1663
|
if (options.file) {
|
|
@@ -1529,7 +2009,7 @@ async function scopeCommand(options) {
|
|
|
1529
2009
|
} catch (error) {
|
|
1530
2010
|
loadSpinner.stop("Failed to load scope options");
|
|
1531
2011
|
log.error(error instanceof Error ? error.message : String(error));
|
|
1532
|
-
|
|
2012
|
+
process9.exit(1);
|
|
1533
2013
|
}
|
|
1534
2014
|
}
|
|
1535
2015
|
var init_scope = __esm({
|
|
@@ -1568,7 +2048,7 @@ __export(lockfile_exports, {
|
|
|
1568
2048
|
});
|
|
1569
2049
|
import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
1570
2050
|
import { join as join6 } from "path";
|
|
1571
|
-
import { Data as
|
|
2051
|
+
import { Data as Data5, Effect as Effect6, pipe as pipe6 } from "effect";
|
|
1572
2052
|
var LOCKFILE_FILENAME, LOCKFILE_VERSION, MARKETPLACE_KEY_REGEX, ORG_KEY_REGEX, LockfileReadError, LockfileWriteError, LockfileVersionError, LockfileCorruptError, getLockfilePath, emptyLockfile, readLockfile, writeLockfile, resolveLocked, upsertLockfileEntry, removeLockfileEntry, buildLockfileKey, parseLockfileKey, readLockfileAsync, writeLockfileAsync, upsertLockfileEntryAsync, removeLockfileEntryAsync;
|
|
1573
2053
|
var init_lockfile = __esm({
|
|
1574
2054
|
"src/lib/lockfile.ts"() {
|
|
@@ -1578,13 +2058,13 @@ var init_lockfile = __esm({
|
|
|
1578
2058
|
LOCKFILE_VERSION = 1;
|
|
1579
2059
|
MARKETPLACE_KEY_REGEX = /^@([a-z0-9-]+)\/([a-z0-9-]+)@(\d+)$/;
|
|
1580
2060
|
ORG_KEY_REGEX = /^([a-z0-9-]+)\/([a-z0-9-]+)@(\d+)$/;
|
|
1581
|
-
LockfileReadError = class extends
|
|
2061
|
+
LockfileReadError = class extends Data5.TaggedError("LockfileReadError") {
|
|
1582
2062
|
};
|
|
1583
|
-
LockfileWriteError = class extends
|
|
2063
|
+
LockfileWriteError = class extends Data5.TaggedError("LockfileWriteError") {
|
|
1584
2064
|
};
|
|
1585
|
-
LockfileVersionError = class extends
|
|
2065
|
+
LockfileVersionError = class extends Data5.TaggedError("LockfileVersionError") {
|
|
1586
2066
|
};
|
|
1587
|
-
LockfileCorruptError = class extends
|
|
2067
|
+
LockfileCorruptError = class extends Data5.TaggedError("LockfileCorruptError") {
|
|
1588
2068
|
};
|
|
1589
2069
|
getLockfilePath = (dir) => join6(dir, LOCKFILE_FILENAME);
|
|
1590
2070
|
emptyLockfile = () => ({
|
|
@@ -1593,27 +2073,27 @@ var init_lockfile = __esm({
|
|
|
1593
2073
|
});
|
|
1594
2074
|
readLockfile = (dir) => {
|
|
1595
2075
|
const lockfilePath = getLockfilePath(dir);
|
|
1596
|
-
return
|
|
1597
|
-
|
|
2076
|
+
return pipe6(
|
|
2077
|
+
Effect6.tryPromise({
|
|
1598
2078
|
try: () => readFile3(lockfilePath, "utf-8"),
|
|
1599
2079
|
catch: () => new LockfileReadError({ path: lockfilePath, cause: "not found" })
|
|
1600
2080
|
}),
|
|
1601
|
-
|
|
2081
|
+
Effect6.catchTag(
|
|
1602
2082
|
"LockfileReadError",
|
|
1603
|
-
() =>
|
|
2083
|
+
() => Effect6.succeed(null)
|
|
1604
2084
|
),
|
|
1605
|
-
|
|
2085
|
+
Effect6.flatMap((content) => {
|
|
1606
2086
|
if (content === null) {
|
|
1607
|
-
return
|
|
2087
|
+
return Effect6.succeed(null);
|
|
1608
2088
|
}
|
|
1609
|
-
return
|
|
1610
|
-
|
|
2089
|
+
return pipe6(
|
|
2090
|
+
Effect6.try({
|
|
1611
2091
|
try: () => JSON.parse(content),
|
|
1612
2092
|
catch: (cause) => new LockfileCorruptError({ path: lockfilePath, cause })
|
|
1613
2093
|
}),
|
|
1614
|
-
|
|
2094
|
+
Effect6.flatMap((parsed) => {
|
|
1615
2095
|
if (parsed.lockfileVersion !== LOCKFILE_VERSION) {
|
|
1616
|
-
return
|
|
2096
|
+
return Effect6.fail(
|
|
1617
2097
|
new LockfileVersionError({
|
|
1618
2098
|
path: lockfilePath,
|
|
1619
2099
|
expected: LOCKFILE_VERSION,
|
|
@@ -1621,7 +2101,7 @@ var init_lockfile = __esm({
|
|
|
1621
2101
|
})
|
|
1622
2102
|
);
|
|
1623
2103
|
}
|
|
1624
|
-
return
|
|
2104
|
+
return Effect6.succeed(parsed);
|
|
1625
2105
|
})
|
|
1626
2106
|
);
|
|
1627
2107
|
})
|
|
@@ -1629,7 +2109,7 @@ var init_lockfile = __esm({
|
|
|
1629
2109
|
};
|
|
1630
2110
|
writeLockfile = (dir, lockfile) => {
|
|
1631
2111
|
const lockfilePath = getLockfilePath(dir);
|
|
1632
|
-
return
|
|
2112
|
+
return Effect6.tryPromise({
|
|
1633
2113
|
try: () => writeFile4(
|
|
1634
2114
|
lockfilePath,
|
|
1635
2115
|
`${JSON.stringify(lockfile, null, 2)}
|
|
@@ -1646,26 +2126,26 @@ var init_lockfile = __esm({
|
|
|
1646
2126
|
}
|
|
1647
2127
|
return entry;
|
|
1648
2128
|
};
|
|
1649
|
-
upsertLockfileEntry = (dir, key, entry) =>
|
|
2129
|
+
upsertLockfileEntry = (dir, key, entry) => pipe6(
|
|
1650
2130
|
readLockfile(dir),
|
|
1651
|
-
|
|
1652
|
-
|
|
2131
|
+
Effect6.map((existing) => existing ?? emptyLockfile()),
|
|
2132
|
+
Effect6.map((lockfile) => ({
|
|
1653
2133
|
...lockfile,
|
|
1654
2134
|
resolved: {
|
|
1655
2135
|
...lockfile.resolved,
|
|
1656
2136
|
[key]: entry
|
|
1657
2137
|
}
|
|
1658
2138
|
})),
|
|
1659
|
-
|
|
2139
|
+
Effect6.flatMap((lockfile) => writeLockfile(dir, lockfile))
|
|
1660
2140
|
);
|
|
1661
|
-
removeLockfileEntry = (dir, key) =>
|
|
2141
|
+
removeLockfileEntry = (dir, key) => pipe6(
|
|
1662
2142
|
readLockfile(dir),
|
|
1663
|
-
|
|
1664
|
-
|
|
2143
|
+
Effect6.map((existing) => existing ?? emptyLockfile()),
|
|
2144
|
+
Effect6.map((lockfile) => {
|
|
1665
2145
|
const { [key]: _removed, ...rest } = lockfile.resolved;
|
|
1666
2146
|
return { ...lockfile, resolved: rest };
|
|
1667
2147
|
}),
|
|
1668
|
-
|
|
2148
|
+
Effect6.flatMap((lockfile) => writeLockfile(dir, lockfile))
|
|
1669
2149
|
);
|
|
1670
2150
|
buildLockfileKey = (source, handle, slug, version) => {
|
|
1671
2151
|
const prefix = source === "marketplace" ? `@${handle}` : handle;
|
|
@@ -1692,10 +2172,10 @@ var init_lockfile = __esm({
|
|
|
1692
2172
|
}
|
|
1693
2173
|
return null;
|
|
1694
2174
|
};
|
|
1695
|
-
readLockfileAsync = (dir) =>
|
|
1696
|
-
writeLockfileAsync = (dir, lockfile) =>
|
|
1697
|
-
upsertLockfileEntryAsync = (dir, key, entry) =>
|
|
1698
|
-
removeLockfileEntryAsync = (dir, key) =>
|
|
2175
|
+
readLockfileAsync = (dir) => Effect6.runPromise(readLockfile(dir));
|
|
2176
|
+
writeLockfileAsync = (dir, lockfile) => Effect6.runPromise(writeLockfile(dir, lockfile));
|
|
2177
|
+
upsertLockfileEntryAsync = (dir, key, entry) => Effect6.runPromise(upsertLockfileEntry(dir, key, entry));
|
|
2178
|
+
removeLockfileEntryAsync = (dir, key) => Effect6.runPromise(removeLockfileEntry(dir, key));
|
|
1699
2179
|
}
|
|
1700
2180
|
});
|
|
1701
2181
|
|
|
@@ -2244,42 +2724,289 @@ var resolveInstallPath = (agent, options) => {
|
|
|
2244
2724
|
if (!agent.projectPath) {
|
|
2245
2725
|
return void 0;
|
|
2246
2726
|
}
|
|
2247
|
-
const cwd = options.projectRoot ?? process2.cwd();
|
|
2248
|
-
return join(cwd, agent.projectPath);
|
|
2249
|
-
};
|
|
2250
|
-
var resolveAgentsInstallPath = (agent, options) => {
|
|
2251
|
-
if (options.global) {
|
|
2252
|
-
return agent.agentsGlobalPath;
|
|
2727
|
+
const cwd = options.projectRoot ?? process2.cwd();
|
|
2728
|
+
return join(cwd, agent.projectPath);
|
|
2729
|
+
};
|
|
2730
|
+
var resolveAgentsInstallPath = (agent, options) => {
|
|
2731
|
+
if (options.global) {
|
|
2732
|
+
return agent.agentsGlobalPath;
|
|
2733
|
+
}
|
|
2734
|
+
if (!agent.agentsProjectPath) {
|
|
2735
|
+
return void 0;
|
|
2736
|
+
}
|
|
2737
|
+
const cwd = options.projectRoot ?? process2.cwd();
|
|
2738
|
+
return join(cwd, agent.agentsProjectPath);
|
|
2739
|
+
};
|
|
2740
|
+
var resolveRulesInstallPath = (agent, options) => {
|
|
2741
|
+
if (options.global) {
|
|
2742
|
+
return agent.rulesGlobalPath;
|
|
2743
|
+
}
|
|
2744
|
+
if (!agent.rulesProjectPath) {
|
|
2745
|
+
return void 0;
|
|
2746
|
+
}
|
|
2747
|
+
const cwd = options.projectRoot ?? process2.cwd();
|
|
2748
|
+
return join(cwd, agent.rulesProjectPath);
|
|
2749
|
+
};
|
|
2750
|
+
var resolveHookConfigPath = (agent, options) => {
|
|
2751
|
+
if (options.global) {
|
|
2752
|
+
return agent.hookGlobalConfigPath;
|
|
2753
|
+
}
|
|
2754
|
+
if (!agent.hookProjectConfigPath) {
|
|
2755
|
+
return void 0;
|
|
2756
|
+
}
|
|
2757
|
+
const cwd = options.projectRoot ?? process2.cwd();
|
|
2758
|
+
return join(cwd, agent.hookProjectConfigPath);
|
|
2759
|
+
};
|
|
2760
|
+
|
|
2761
|
+
// src/commands/agents.ts
|
|
2762
|
+
init_api();
|
|
2763
|
+
|
|
2764
|
+
// src/lib/command-output.ts
|
|
2765
|
+
init_esm_shims();
|
|
2766
|
+
init_api();
|
|
2767
|
+
import process8 from "process";
|
|
2768
|
+
|
|
2769
|
+
// src/lib/marketplace-api.ts
|
|
2770
|
+
init_esm_shims();
|
|
2771
|
+
init_automation_headers();
|
|
2772
|
+
init_config();
|
|
2773
|
+
init_device_auth();
|
|
2774
|
+
import { Data as Data4, Effect as Effect5, pipe as pipe5 } from "effect";
|
|
2775
|
+
var TRAILING_SLASH_REGEX2 = /\/$/;
|
|
2776
|
+
var SESSION_TOKEN_PREFIX2 = "brs_";
|
|
2777
|
+
var MarketplaceApiError = class extends Data4.TaggedError("MarketplaceApiError") {
|
|
2778
|
+
};
|
|
2779
|
+
var isLocalHost2 = (hostname2) => hostname2 === "localhost" || hostname2 === "127.0.0.1" || hostname2 === "::1";
|
|
2780
|
+
var isConvexSiteHost2 = (hostname2) => hostname2.endsWith(".convex.site");
|
|
2781
|
+
var isSessionApiServerUrl2 = (serverUrl) => {
|
|
2782
|
+
try {
|
|
2783
|
+
const hostname2 = new URL(serverUrl).hostname;
|
|
2784
|
+
return isConvexSiteHost2(hostname2) || isLocalHost2(hostname2);
|
|
2785
|
+
} catch {
|
|
2786
|
+
return false;
|
|
2787
|
+
}
|
|
2788
|
+
};
|
|
2789
|
+
var resolveApiKey2 = (provided) => {
|
|
2790
|
+
if (provided) {
|
|
2791
|
+
return Effect5.succeed(provided);
|
|
2792
|
+
}
|
|
2793
|
+
return pipe5(
|
|
2794
|
+
Effect5.tryPromise({
|
|
2795
|
+
try: () => getApiKeyAsync(),
|
|
2796
|
+
catch: () => new MarketplaceApiError({
|
|
2797
|
+
message: "Failed to load API key",
|
|
2798
|
+
status: 500,
|
|
2799
|
+
code: "CONFIG_ERROR"
|
|
2800
|
+
})
|
|
2801
|
+
}),
|
|
2802
|
+
Effect5.flatMap(
|
|
2803
|
+
(token) => token ? Effect5.succeed(token) : Effect5.fail(
|
|
2804
|
+
new MarketplaceApiError({
|
|
2805
|
+
message: "Not signed in. Run 'braid auth'.",
|
|
2806
|
+
status: 401,
|
|
2807
|
+
code: "AUTH_REQUIRED"
|
|
2808
|
+
})
|
|
2809
|
+
)
|
|
2810
|
+
)
|
|
2811
|
+
);
|
|
2812
|
+
};
|
|
2813
|
+
var resolveServer = (provided) => {
|
|
2814
|
+
if (provided) {
|
|
2815
|
+
return Effect5.succeed(provided.replace(TRAILING_SLASH_REGEX2, ""));
|
|
2816
|
+
}
|
|
2817
|
+
return pipe5(
|
|
2818
|
+
Effect5.tryPromise({
|
|
2819
|
+
try: () => getServerUrlAsync(),
|
|
2820
|
+
catch: () => new MarketplaceApiError({
|
|
2821
|
+
message: "Failed to load server URL",
|
|
2822
|
+
status: 500,
|
|
2823
|
+
code: "CONFIG_ERROR"
|
|
2824
|
+
})
|
|
2825
|
+
}),
|
|
2826
|
+
Effect5.map((server) => server.replace(TRAILING_SLASH_REGEX2, ""))
|
|
2827
|
+
);
|
|
2828
|
+
};
|
|
2829
|
+
var resolveRequestServer = (server, apiKey) => {
|
|
2830
|
+
if (!apiKey.startsWith(SESSION_TOKEN_PREFIX2) || isSessionApiServerUrl2(server)) {
|
|
2831
|
+
return Effect5.succeed(server);
|
|
2832
|
+
}
|
|
2833
|
+
return Effect5.tryPromise({
|
|
2834
|
+
try: async () => {
|
|
2835
|
+
const authConfig = await fetchAuthConfig(server);
|
|
2836
|
+
return authConfig.convexSiteUrl.replace(TRAILING_SLASH_REGEX2, "");
|
|
2837
|
+
},
|
|
2838
|
+
catch: () => new MarketplaceApiError({
|
|
2839
|
+
message: `Failed to resolve marketplace API server for ${server}`,
|
|
2840
|
+
status: 500,
|
|
2841
|
+
code: "CONFIG_ERROR"
|
|
2842
|
+
})
|
|
2843
|
+
});
|
|
2844
|
+
};
|
|
2845
|
+
var requestJson = (url, options, requestOptions = {}) => pipe5(
|
|
2846
|
+
Effect5.tryPromise({
|
|
2847
|
+
try: () => fetch(url, options),
|
|
2848
|
+
catch: () => new MarketplaceApiError({
|
|
2849
|
+
message: "Network error",
|
|
2850
|
+
status: 503,
|
|
2851
|
+
code: "NETWORK_ERROR"
|
|
2852
|
+
})
|
|
2853
|
+
}),
|
|
2854
|
+
Effect5.flatMap(
|
|
2855
|
+
(response) => Effect5.tryPromise({
|
|
2856
|
+
try: async () => {
|
|
2857
|
+
const payload = await response.json().catch(() => null);
|
|
2858
|
+
if (!response.ok) {
|
|
2859
|
+
const normalizedMessage = requestOptions.normalizeErrorMessage?.({
|
|
2860
|
+
payload,
|
|
2861
|
+
response,
|
|
2862
|
+
url
|
|
2863
|
+
});
|
|
2864
|
+
throw new MarketplaceApiError({
|
|
2865
|
+
message: normalizedMessage ?? (response.status === 404 ? requestOptions.notFoundMessage : void 0) ?? payload?.error ?? payload?.message ?? `Request failed (HTTP ${response.status} from ${new URL(url).origin})`,
|
|
2866
|
+
status: response.status,
|
|
2867
|
+
code: payload?.code ?? "REQUEST_ERROR"
|
|
2868
|
+
});
|
|
2869
|
+
}
|
|
2870
|
+
return payload;
|
|
2871
|
+
},
|
|
2872
|
+
catch: (error) => error instanceof MarketplaceApiError ? error : new MarketplaceApiError({
|
|
2873
|
+
message: "Invalid response",
|
|
2874
|
+
status: 500,
|
|
2875
|
+
code: "PARSE_ERROR"
|
|
2876
|
+
})
|
|
2877
|
+
})
|
|
2878
|
+
)
|
|
2879
|
+
);
|
|
2880
|
+
var fetchMarketplaceLibrary = (options) => pipe5(
|
|
2881
|
+
Effect5.all({
|
|
2882
|
+
server: resolveServer(options.server),
|
|
2883
|
+
apiKey: resolveApiKey2(options.apiKey)
|
|
2884
|
+
}),
|
|
2885
|
+
Effect5.flatMap(
|
|
2886
|
+
({ server, apiKey }) => Effect5.all({
|
|
2887
|
+
apiKey: Effect5.succeed(apiKey),
|
|
2888
|
+
server: resolveRequestServer(server, apiKey)
|
|
2889
|
+
})
|
|
2890
|
+
),
|
|
2891
|
+
Effect5.flatMap(
|
|
2892
|
+
({ server, apiKey }) => requestJson(
|
|
2893
|
+
`${server}/api/marketplace/library`,
|
|
2894
|
+
{
|
|
2895
|
+
method: "GET",
|
|
2896
|
+
headers: mergeAutomationHeaders({
|
|
2897
|
+
Authorization: `Bearer ${apiKey}`
|
|
2898
|
+
})
|
|
2899
|
+
}
|
|
2900
|
+
)
|
|
2901
|
+
),
|
|
2902
|
+
Effect5.map((response) => response.items)
|
|
2903
|
+
);
|
|
2904
|
+
var fetchMarketplaceInstallManifest = (slug, options) => pipe5(
|
|
2905
|
+
Effect5.all({
|
|
2906
|
+
server: resolveServer(options.server),
|
|
2907
|
+
apiKey: resolveApiKey2(options.apiKey)
|
|
2908
|
+
}),
|
|
2909
|
+
Effect5.flatMap(
|
|
2910
|
+
({ server, apiKey }) => Effect5.all({
|
|
2911
|
+
apiKey: Effect5.succeed(apiKey),
|
|
2912
|
+
server: resolveRequestServer(server, apiKey)
|
|
2913
|
+
})
|
|
2914
|
+
),
|
|
2915
|
+
Effect5.flatMap(
|
|
2916
|
+
({ server, apiKey }) => requestJson(
|
|
2917
|
+
`${server}/api/marketplace/install-manifest/${encodeURIComponent(slug)}`,
|
|
2918
|
+
{
|
|
2919
|
+
method: "GET",
|
|
2920
|
+
headers: mergeAutomationHeaders({
|
|
2921
|
+
Authorization: `Bearer ${apiKey}`
|
|
2922
|
+
})
|
|
2923
|
+
},
|
|
2924
|
+
{
|
|
2925
|
+
normalizeErrorMessage: ({ payload }) => payload?.error === "Not entitled" ? "Pack not found or no longer available in your library." : void 0,
|
|
2926
|
+
notFoundMessage: "Pack not found or no longer available in your library."
|
|
2927
|
+
}
|
|
2928
|
+
)
|
|
2929
|
+
)
|
|
2930
|
+
);
|
|
2931
|
+
var fetchMarketplaceLibraryAsync = (options) => Effect5.runPromise(fetchMarketplaceLibrary(options));
|
|
2932
|
+
var fetchMarketplaceInstallManifestAsync = (slug, options) => Effect5.runPromise(fetchMarketplaceInstallManifest(slug, options));
|
|
2933
|
+
|
|
2934
|
+
// src/lib/command-output.ts
|
|
2935
|
+
init_tui();
|
|
2936
|
+
var CommandValidationError = class extends Error {
|
|
2937
|
+
code = "CLI_VALIDATION_ERROR";
|
|
2938
|
+
constructor(message) {
|
|
2939
|
+
super(message);
|
|
2940
|
+
this.name = "CommandValidationError";
|
|
2941
|
+
}
|
|
2942
|
+
};
|
|
2943
|
+
var writeJson = (value) => {
|
|
2944
|
+
process8.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
2945
|
+
`);
|
|
2946
|
+
};
|
|
2947
|
+
var toJsonErrorOutput = (error) => {
|
|
2948
|
+
if (error instanceof ApiError) {
|
|
2949
|
+
return {
|
|
2950
|
+
error: error.message,
|
|
2951
|
+
code: error.code,
|
|
2952
|
+
status: error.status
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
if (error instanceof AuthenticationError) {
|
|
2956
|
+
return {
|
|
2957
|
+
error: error.message,
|
|
2958
|
+
code: "AUTH_REQUIRED",
|
|
2959
|
+
status: 401
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2962
|
+
if (error instanceof NetworkError) {
|
|
2963
|
+
return {
|
|
2964
|
+
error: error.message,
|
|
2965
|
+
code: "NETWORK_ERROR",
|
|
2966
|
+
status: 503
|
|
2967
|
+
};
|
|
2253
2968
|
}
|
|
2254
|
-
if (
|
|
2255
|
-
return
|
|
2969
|
+
if (error instanceof MarketplaceApiError) {
|
|
2970
|
+
return {
|
|
2971
|
+
error: error.message,
|
|
2972
|
+
code: error.code,
|
|
2973
|
+
status: error.status
|
|
2974
|
+
};
|
|
2256
2975
|
}
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2976
|
+
if (error instanceof CommandValidationError || error instanceof SyntaxError) {
|
|
2977
|
+
return {
|
|
2978
|
+
error: error.message,
|
|
2979
|
+
code: "CLI_VALIDATION_ERROR",
|
|
2980
|
+
status: 400
|
|
2981
|
+
};
|
|
2263
2982
|
}
|
|
2264
|
-
if (
|
|
2265
|
-
return
|
|
2983
|
+
if (error instanceof Error) {
|
|
2984
|
+
return {
|
|
2985
|
+
error: error.message,
|
|
2986
|
+
code: "CLI_ERROR",
|
|
2987
|
+
status: 500
|
|
2988
|
+
};
|
|
2266
2989
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2990
|
+
return {
|
|
2991
|
+
error: String(error),
|
|
2992
|
+
code: "CLI_ERROR",
|
|
2993
|
+
status: 500
|
|
2994
|
+
};
|
|
2269
2995
|
};
|
|
2270
|
-
var
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
if (
|
|
2275
|
-
|
|
2996
|
+
var fail = (message) => {
|
|
2997
|
+
throw new CommandValidationError(message);
|
|
2998
|
+
};
|
|
2999
|
+
var exitCommandError = (error, options) => {
|
|
3000
|
+
if (options?.json) {
|
|
3001
|
+
writeJson(toJsonErrorOutput(error));
|
|
3002
|
+
process8.exit(1);
|
|
2276
3003
|
}
|
|
2277
|
-
const
|
|
2278
|
-
|
|
3004
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3005
|
+
log.error(message);
|
|
3006
|
+
process8.exit(1);
|
|
2279
3007
|
};
|
|
2280
3008
|
|
|
2281
3009
|
// src/commands/agents.ts
|
|
2282
|
-
init_api();
|
|
2283
3010
|
init_tui();
|
|
2284
3011
|
var parseCsv = (input) => {
|
|
2285
3012
|
if (!input) {
|
|
@@ -2288,18 +3015,6 @@ var parseCsv = (input) => {
|
|
|
2288
3015
|
const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
2289
3016
|
return values.length > 0 ? values : void 0;
|
|
2290
3017
|
};
|
|
2291
|
-
var writeJson = (value) => {
|
|
2292
|
-
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
2293
|
-
`);
|
|
2294
|
-
};
|
|
2295
|
-
var fail = (message) => {
|
|
2296
|
-
throw new Error(message);
|
|
2297
|
-
};
|
|
2298
|
-
var exitWithError = (error) => {
|
|
2299
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2300
|
-
log.error(message);
|
|
2301
|
-
process.exit(1);
|
|
2302
|
-
};
|
|
2303
3018
|
var run = (command, args, options) => {
|
|
2304
3019
|
const apiOptions = {
|
|
2305
3020
|
...options.server ? { serverUrl: options.server } : {},
|
|
@@ -2403,7 +3118,7 @@ async function agentsListCommand(options) {
|
|
|
2403
3118
|
log.success("sub-agents list completed");
|
|
2404
3119
|
writeJson(result);
|
|
2405
3120
|
} catch (error) {
|
|
2406
|
-
|
|
3121
|
+
exitCommandError(error, { json: options.json });
|
|
2407
3122
|
}
|
|
2408
3123
|
}
|
|
2409
3124
|
async function agentsGetCommand(options) {
|
|
@@ -2417,7 +3132,7 @@ async function agentsGetCommand(options) {
|
|
|
2417
3132
|
log.success("sub-agents get completed");
|
|
2418
3133
|
writeJson(result);
|
|
2419
3134
|
} catch (error) {
|
|
2420
|
-
|
|
3135
|
+
exitCommandError(error, { json: options.json });
|
|
2421
3136
|
}
|
|
2422
3137
|
}
|
|
2423
3138
|
async function agentsCreateCommand(options) {
|
|
@@ -2445,7 +3160,7 @@ async function agentsCreateCommand(options) {
|
|
|
2445
3160
|
}
|
|
2446
3161
|
log.success("sub-agents create completed");
|
|
2447
3162
|
} catch (error) {
|
|
2448
|
-
|
|
3163
|
+
exitCommandError(error, { json: options.json });
|
|
2449
3164
|
}
|
|
2450
3165
|
}
|
|
2451
3166
|
async function agentsUpdateCommand(options) {
|
|
@@ -2470,7 +3185,7 @@ async function agentsUpdateCommand(options) {
|
|
|
2470
3185
|
}
|
|
2471
3186
|
log.success("sub-agents update completed");
|
|
2472
3187
|
} catch (error) {
|
|
2473
|
-
|
|
3188
|
+
exitCommandError(error, { json: options.json });
|
|
2474
3189
|
}
|
|
2475
3190
|
}
|
|
2476
3191
|
async function agentsRemoveCommand(options) {
|
|
@@ -2486,7 +3201,7 @@ async function agentsRemoveCommand(options) {
|
|
|
2486
3201
|
}
|
|
2487
3202
|
log.success("sub-agents remove completed");
|
|
2488
3203
|
} catch (error) {
|
|
2489
|
-
|
|
3204
|
+
exitCommandError(error, { json: options.json });
|
|
2490
3205
|
}
|
|
2491
3206
|
}
|
|
2492
3207
|
async function agentsInstallCommand(options) {
|
|
@@ -2522,354 +3237,46 @@ async function agentsInstallCommand(options) {
|
|
|
2522
3237
|
}
|
|
2523
3238
|
if (options.json) {
|
|
2524
3239
|
writeJson(summary);
|
|
2525
|
-
return;
|
|
2526
|
-
}
|
|
2527
|
-
for (const item of summary) {
|
|
2528
|
-
log.info(
|
|
2529
|
-
`${item.platform}: ${item.written} file(s) written${item.installPath ? ` to ${item.installPath}` : ""}`
|
|
2530
|
-
);
|
|
2531
|
-
for (const warning of item.warnings) {
|
|
2532
|
-
log.warn(` warning: ${warning}`);
|
|
2533
|
-
}
|
|
2534
|
-
for (const error of item.errors) {
|
|
2535
|
-
log.error(` error (${error.agent}): ${error.error}`);
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
log.success("sub-agents install completed");
|
|
2539
|
-
} catch (error) {
|
|
2540
|
-
exitWithError(error);
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
|
|
2544
|
-
// src/commands/auth.ts
|
|
2545
|
-
init_esm_shims();
|
|
2546
|
-
init_api();
|
|
2547
|
-
init_config();
|
|
2548
|
-
import process8 from "process";
|
|
2549
|
-
|
|
2550
|
-
// src/lib/device-auth.ts
|
|
2551
|
-
init_esm_shims();
|
|
2552
|
-
init_braid_workspace();
|
|
2553
|
-
import { execFile } from "child_process";
|
|
2554
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
2555
|
-
import { hostname, platform } from "os";
|
|
2556
|
-
import { join as join4 } from "path";
|
|
2557
|
-
import process6 from "process";
|
|
2558
|
-
var TRAILING_SLASHES2 = /\/+$/;
|
|
2559
|
-
var LEGACY_BRAID_AUTH_HOSTS = /* @__PURE__ */ new Set([
|
|
2560
|
-
"api.braid.cloud",
|
|
2561
|
-
"braid.cloud",
|
|
2562
|
-
"www.braid.cloud"
|
|
2563
|
-
]);
|
|
2564
|
-
var BRAID_APP_HOST = "app.braid.cloud";
|
|
2565
|
-
var DEFAULT_BRAID_AUTH_HOSTS = /* @__PURE__ */ new Set([
|
|
2566
|
-
...LEGACY_BRAID_AUTH_HOSTS,
|
|
2567
|
-
BRAID_APP_HOST
|
|
2568
|
-
]);
|
|
2569
|
-
var LOOPBACK_HOSTS2 = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
|
|
2570
|
-
var LOCAL_AUTH_ENV_FILES = [
|
|
2571
|
-
["apps", "web", ".env.local"],
|
|
2572
|
-
["apps", "convex", ".env.local"]
|
|
2573
|
-
];
|
|
2574
|
-
var LOCAL_AUTH_ENV_KEYS = ["APP_URL", "SITE_URL"];
|
|
2575
|
-
var NEWLINE_REGEX2 = /\r?\n/;
|
|
2576
|
-
var DeviceAuthTimeoutError = class extends Error {
|
|
2577
|
-
constructor() {
|
|
2578
|
-
super("Device authorization timed out");
|
|
2579
|
-
this.name = "DeviceAuthTimeoutError";
|
|
2580
|
-
}
|
|
2581
|
-
};
|
|
2582
|
-
var DeviceAuthDeniedError = class extends Error {
|
|
2583
|
-
constructor() {
|
|
2584
|
-
super("Device authorization was denied");
|
|
2585
|
-
this.name = "DeviceAuthDeniedError";
|
|
2586
|
-
}
|
|
2587
|
-
};
|
|
2588
|
-
var DeviceAuthExpiredError = class extends Error {
|
|
2589
|
-
constructor() {
|
|
2590
|
-
super("Device authorization code has expired");
|
|
2591
|
-
this.name = "DeviceAuthExpiredError";
|
|
2592
|
-
}
|
|
2593
|
-
};
|
|
2594
|
-
var sleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
2595
|
-
var normalizeBaseUrl2 = (rawUrl) => {
|
|
2596
|
-
const trimmed = rawUrl.replace(TRAILING_SLASHES2, "");
|
|
2597
|
-
try {
|
|
2598
|
-
const url = new URL(trimmed);
|
|
2599
|
-
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
2600
|
-
} catch {
|
|
2601
|
-
return trimmed;
|
|
2602
|
-
}
|
|
2603
|
-
};
|
|
2604
|
-
var normalizeLoopbackBaseUrl = (rawUrl) => {
|
|
2605
|
-
const normalized = normalizeBaseUrl2(rawUrl);
|
|
2606
|
-
try {
|
|
2607
|
-
const url = new URL(normalized);
|
|
2608
|
-
if (isLoopbackHost(url.hostname)) {
|
|
2609
|
-
url.hostname = "localhost";
|
|
2610
|
-
}
|
|
2611
|
-
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
2612
|
-
} catch {
|
|
2613
|
-
return normalized;
|
|
2614
|
-
}
|
|
2615
|
-
};
|
|
2616
|
-
var isLoopbackHost = (hostname2) => LOOPBACK_HOSTS2.has(hostname2);
|
|
2617
|
-
var isLoopbackUrl = (rawUrl) => {
|
|
2618
|
-
try {
|
|
2619
|
-
return isLoopbackHost(new URL(rawUrl).hostname);
|
|
2620
|
-
} catch {
|
|
2621
|
-
return false;
|
|
2622
|
-
}
|
|
2623
|
-
};
|
|
2624
|
-
var stripQuotes2 = (value) => {
|
|
2625
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
2626
|
-
return value.slice(1, -1);
|
|
2627
|
-
}
|
|
2628
|
-
return value;
|
|
2629
|
-
};
|
|
2630
|
-
var parseDotenv2 = (content) => {
|
|
2631
|
-
const result = {};
|
|
2632
|
-
for (const rawLine of content.split(NEWLINE_REGEX2)) {
|
|
2633
|
-
const line = rawLine.trim();
|
|
2634
|
-
if (!line || line.startsWith("#")) {
|
|
2635
|
-
continue;
|
|
2636
|
-
}
|
|
2637
|
-
const separatorIndex = line.indexOf("=");
|
|
2638
|
-
if (separatorIndex <= 0) {
|
|
2639
|
-
continue;
|
|
2640
|
-
}
|
|
2641
|
-
const key = line.slice(0, separatorIndex).trim();
|
|
2642
|
-
const value = line.slice(separatorIndex + 1).trim();
|
|
2643
|
-
result[key] = stripQuotes2(value);
|
|
2644
|
-
}
|
|
2645
|
-
return result;
|
|
2646
|
-
};
|
|
2647
|
-
var resolveLocalAuthWebBaseUrlFromEnv = (env) => {
|
|
2648
|
-
for (const key of LOCAL_AUTH_ENV_KEYS) {
|
|
2649
|
-
const value = env[key];
|
|
2650
|
-
if (value && isLoopbackUrl(value)) {
|
|
2651
|
-
return normalizeLoopbackBaseUrl(value);
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
return void 0;
|
|
2655
|
-
};
|
|
2656
|
-
var resolveLocalAuthWebBaseUrlFromFiles = () => {
|
|
2657
|
-
const workspaceRoot = findBraidWorkspaceRoot();
|
|
2658
|
-
if (!workspaceRoot) {
|
|
2659
|
-
return void 0;
|
|
2660
|
-
}
|
|
2661
|
-
for (const envFile of LOCAL_AUTH_ENV_FILES) {
|
|
2662
|
-
const envPath = join4(workspaceRoot, ...envFile);
|
|
2663
|
-
if (!existsSync3(envPath)) {
|
|
2664
|
-
continue;
|
|
2665
|
-
}
|
|
2666
|
-
const localAppUrl = resolveLocalAuthWebBaseUrlFromEnv(
|
|
2667
|
-
parseDotenv2(readFileSync3(envPath, "utf8"))
|
|
2668
|
-
);
|
|
2669
|
-
if (localAppUrl) {
|
|
2670
|
-
return localAppUrl;
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
return void 0;
|
|
2674
|
-
};
|
|
2675
|
-
var resolveLocalAuthWebBaseUrl = () => resolveLocalAuthWebBaseUrlFromEnv(process6.env) ?? resolveLocalAuthWebBaseUrlFromFiles();
|
|
2676
|
-
var normalizeServerBaseUrl = (serverUrl) => {
|
|
2677
|
-
const trimmed = normalizeBaseUrl2(serverUrl);
|
|
2678
|
-
try {
|
|
2679
|
-
const url = new URL(trimmed);
|
|
2680
|
-
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
2681
|
-
} catch {
|
|
2682
|
-
return trimmed;
|
|
2683
|
-
}
|
|
2684
|
-
};
|
|
2685
|
-
var resolveCanonicalAuthWebBaseUrl = (serverUrl) => {
|
|
2686
|
-
const normalized = normalizeServerBaseUrl(serverUrl);
|
|
2687
|
-
try {
|
|
2688
|
-
const url = new URL(normalized);
|
|
2689
|
-
if (LEGACY_BRAID_AUTH_HOSTS.has(url.hostname)) {
|
|
2690
|
-
url.hostname = BRAID_APP_HOST;
|
|
2691
|
-
url.pathname = "/";
|
|
2692
|
-
}
|
|
2693
|
-
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
2694
|
-
} catch {
|
|
2695
|
-
return normalized;
|
|
2696
|
-
}
|
|
2697
|
-
};
|
|
2698
|
-
var isHostedBraidAuthServer = (serverUrl) => {
|
|
2699
|
-
try {
|
|
2700
|
-
return DEFAULT_BRAID_AUTH_HOSTS.has(
|
|
2701
|
-
new URL(normalizeServerBaseUrl(serverUrl)).hostname
|
|
2702
|
-
);
|
|
2703
|
-
} catch {
|
|
2704
|
-
return false;
|
|
2705
|
-
}
|
|
2706
|
-
};
|
|
2707
|
-
function resolveAuthWebBaseUrl(serverUrl) {
|
|
2708
|
-
const canonicalBaseUrl = resolveCanonicalAuthWebBaseUrl(serverUrl);
|
|
2709
|
-
try {
|
|
2710
|
-
const url = new URL(canonicalBaseUrl);
|
|
2711
|
-
const localAuthBaseUrl = resolveLocalAuthWebBaseUrl();
|
|
2712
|
-
if (localAuthBaseUrl && (DEFAULT_BRAID_AUTH_HOSTS.has(url.hostname) || isLoopbackHost(url.hostname))) {
|
|
2713
|
-
return localAuthBaseUrl;
|
|
2714
|
-
}
|
|
2715
|
-
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
|
|
2716
|
-
} catch {
|
|
2717
|
-
return canonicalBaseUrl;
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
function buildAuthVerificationUrlFromBaseUrl(authBaseUrl, userCode) {
|
|
2721
|
-
return `${authBaseUrl.replace(TRAILING_SLASHES2, "")}/cli/authorize?user_code=${encodeURIComponent(userCode)}`;
|
|
2722
|
-
}
|
|
2723
|
-
async function fetchAuthConfigFromBaseUrl(authBaseUrl) {
|
|
2724
|
-
const response = await fetch(`${authBaseUrl}/api/cli/auth-config`);
|
|
2725
|
-
if (!response.ok) {
|
|
2726
|
-
const body = await response.text();
|
|
2727
|
-
throw new Error(
|
|
2728
|
-
`Failed to fetch auth config (${response.status}): ${body}`
|
|
2729
|
-
);
|
|
2730
|
-
}
|
|
2731
|
-
return {
|
|
2732
|
-
...await response.json(),
|
|
2733
|
-
verificationBaseUrl: authBaseUrl
|
|
2734
|
-
};
|
|
2735
|
-
}
|
|
2736
|
-
async function fetchAuthConfig(serverUrl) {
|
|
2737
|
-
const authBaseUrl = resolveAuthWebBaseUrl(serverUrl).replace(
|
|
2738
|
-
TRAILING_SLASHES2,
|
|
2739
|
-
""
|
|
2740
|
-
);
|
|
2741
|
-
const canonicalAuthBaseUrl = resolveCanonicalAuthWebBaseUrl(
|
|
2742
|
-
serverUrl
|
|
2743
|
-
).replace(TRAILING_SLASHES2, "");
|
|
2744
|
-
try {
|
|
2745
|
-
return await fetchAuthConfigFromBaseUrl(authBaseUrl);
|
|
2746
|
-
} catch (error) {
|
|
2747
|
-
if (authBaseUrl !== canonicalAuthBaseUrl && isHostedBraidAuthServer(serverUrl)) {
|
|
2748
|
-
return fetchAuthConfigFromBaseUrl(canonicalAuthBaseUrl);
|
|
2749
|
-
}
|
|
2750
|
-
throw error;
|
|
2751
|
-
}
|
|
2752
|
-
}
|
|
2753
|
-
async function initiateDeviceAuth(convexSiteUrl, deviceInfo) {
|
|
2754
|
-
const url = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/device/authorize`;
|
|
2755
|
-
const response = await fetch(url, {
|
|
2756
|
-
method: "POST",
|
|
2757
|
-
headers: { "Content-Type": "application/json" },
|
|
2758
|
-
body: JSON.stringify(deviceInfo)
|
|
2759
|
-
});
|
|
2760
|
-
if (!response.ok) {
|
|
2761
|
-
const body = await response.text();
|
|
2762
|
-
throw new Error(
|
|
2763
|
-
`Failed to initiate device authorization (${response.status}): ${body}`
|
|
2764
|
-
);
|
|
2765
|
-
}
|
|
2766
|
-
return response.json();
|
|
2767
|
-
}
|
|
2768
|
-
async function pollForSession(convexSiteUrl, deviceCode, interval, expiresIn, timeoutSeconds) {
|
|
2769
|
-
const tokenUrl = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/device/token`;
|
|
2770
|
-
const deadline = Date.now() + Math.min(expiresIn, timeoutSeconds) * 1e3;
|
|
2771
|
-
let currentInterval = interval;
|
|
2772
|
-
while (Date.now() < deadline) {
|
|
2773
|
-
await sleep(currentInterval * 1e3);
|
|
2774
|
-
const response = await fetch(tokenUrl, {
|
|
2775
|
-
method: "POST",
|
|
2776
|
-
headers: { "Content-Type": "application/json" },
|
|
2777
|
-
body: JSON.stringify({ device_code: deviceCode })
|
|
2778
|
-
});
|
|
2779
|
-
if (response.ok) {
|
|
2780
|
-
const result = await response.json();
|
|
2781
|
-
return {
|
|
2782
|
-
sessionToken: result.session_token,
|
|
2783
|
-
expiresAt: result.expires_at,
|
|
2784
|
-
user: result.user
|
|
2785
|
-
};
|
|
2786
|
-
}
|
|
2787
|
-
let errorCode;
|
|
2788
|
-
try {
|
|
2789
|
-
const errorBody = await response.json();
|
|
2790
|
-
errorCode = errorBody.error;
|
|
2791
|
-
} catch {
|
|
2792
|
-
throw new Error(`Device auth polling error: HTTP ${response.status}`);
|
|
2793
|
-
}
|
|
2794
|
-
if (errorCode === "authorization_pending") {
|
|
2795
|
-
continue;
|
|
2796
|
-
}
|
|
2797
|
-
if (errorCode === "slow_down") {
|
|
2798
|
-
currentInterval += 5;
|
|
2799
|
-
continue;
|
|
2800
|
-
}
|
|
2801
|
-
if (errorCode === "expired_token") {
|
|
2802
|
-
throw new DeviceAuthExpiredError();
|
|
2803
|
-
}
|
|
2804
|
-
if (errorCode === "access_denied") {
|
|
2805
|
-
throw new DeviceAuthDeniedError();
|
|
2806
|
-
}
|
|
2807
|
-
throw new Error(
|
|
2808
|
-
`Device auth polling error: ${errorCode ?? `HTTP ${response.status}`}`
|
|
2809
|
-
);
|
|
2810
|
-
}
|
|
2811
|
-
throw new DeviceAuthTimeoutError();
|
|
2812
|
-
}
|
|
2813
|
-
async function fetchSessionInfo(convexSiteUrl, sessionToken) {
|
|
2814
|
-
const url = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/sessions/me`;
|
|
2815
|
-
const response = await fetch(url, {
|
|
2816
|
-
method: "GET",
|
|
2817
|
-
headers: {
|
|
2818
|
-
Authorization: `Bearer ${sessionToken}`
|
|
3240
|
+
return;
|
|
2819
3241
|
}
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
return response.json();
|
|
2831
|
-
}
|
|
2832
|
-
async function revokeSession(convexSiteUrl, sessionToken) {
|
|
2833
|
-
const url = `${convexSiteUrl.replace(TRAILING_SLASHES2, "")}/api/cli/sessions/me`;
|
|
2834
|
-
const response = await fetch(url, {
|
|
2835
|
-
method: "DELETE",
|
|
2836
|
-
headers: {
|
|
2837
|
-
Authorization: `Bearer ${sessionToken}`
|
|
3242
|
+
for (const item of summary) {
|
|
3243
|
+
log.info(
|
|
3244
|
+
`${item.platform}: ${item.written} file(s) written${item.installPath ? ` to ${item.installPath}` : ""}`
|
|
3245
|
+
);
|
|
3246
|
+
for (const warning of item.warnings) {
|
|
3247
|
+
log.warn(` warning: ${warning}`);
|
|
3248
|
+
}
|
|
3249
|
+
for (const error of item.errors) {
|
|
3250
|
+
log.error(` error (${error.agent}): ${error.error}`);
|
|
3251
|
+
}
|
|
2838
3252
|
}
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
}
|
|
2843
|
-
if (!response.ok) {
|
|
2844
|
-
const body = await response.text();
|
|
2845
|
-
throw new Error(`Failed to revoke session (${response.status}): ${body}`);
|
|
2846
|
-
}
|
|
2847
|
-
return true;
|
|
2848
|
-
}
|
|
2849
|
-
var noop = () => {
|
|
2850
|
-
};
|
|
2851
|
-
function openBrowser(url) {
|
|
2852
|
-
const currentPlatform = platform();
|
|
2853
|
-
if (currentPlatform === "darwin") {
|
|
2854
|
-
execFile("open", [url], noop);
|
|
2855
|
-
} else if (currentPlatform === "win32") {
|
|
2856
|
-
execFile("cmd", ["/c", "start", "", url], noop);
|
|
2857
|
-
} else {
|
|
2858
|
-
execFile("xdg-open", [url], noop);
|
|
3253
|
+
log.success("sub-agents install completed");
|
|
3254
|
+
} catch (error) {
|
|
3255
|
+
exitCommandError(error, { json: options.json });
|
|
2859
3256
|
}
|
|
2860
3257
|
}
|
|
2861
|
-
function getDeviceInfo() {
|
|
2862
|
-
return {
|
|
2863
|
-
deviceName: hostname(),
|
|
2864
|
-
deviceOs: platform(),
|
|
2865
|
-
deviceHostname: hostname()
|
|
2866
|
-
};
|
|
2867
|
-
}
|
|
2868
3258
|
|
|
2869
3259
|
// src/commands/auth.ts
|
|
3260
|
+
init_esm_shims();
|
|
3261
|
+
init_api();
|
|
3262
|
+
init_config();
|
|
3263
|
+
init_device_auth();
|
|
2870
3264
|
init_tui();
|
|
2871
|
-
|
|
3265
|
+
import process10 from "process";
|
|
3266
|
+
var SESSION_TOKEN_PREFIX3 = "brs_";
|
|
3267
|
+
var LOOPBACK_HOSTS3 = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
|
|
2872
3268
|
var DEFAULT_TIMEOUT_SECONDS = 300;
|
|
3269
|
+
var resolvePersistedCliServerUrl = (serverUrl, convexSiteUrl) => {
|
|
3270
|
+
try {
|
|
3271
|
+
const convexUrl = new URL(convexSiteUrl);
|
|
3272
|
+
if (LOOPBACK_HOSTS3.has(convexUrl.hostname)) {
|
|
3273
|
+
return convexSiteUrl;
|
|
3274
|
+
}
|
|
3275
|
+
} catch {
|
|
3276
|
+
return serverUrl;
|
|
3277
|
+
}
|
|
3278
|
+
return serverUrl;
|
|
3279
|
+
};
|
|
2873
3280
|
async function configureDefaultScopeAsync(serverUrl) {
|
|
2874
3281
|
const shouldConfigureScope = await confirm({
|
|
2875
3282
|
message: "Configure organization and scope defaults now?",
|
|
@@ -2904,9 +3311,9 @@ async function manualTokenFlow(apiKey, serverUrl, options) {
|
|
|
2904
3311
|
log.error(
|
|
2905
3312
|
"The API key could not be validated. Please check your key and try again."
|
|
2906
3313
|
);
|
|
2907
|
-
|
|
3314
|
+
process10.exit(1);
|
|
2908
3315
|
}
|
|
2909
|
-
await persistApiKeyAsync(apiKey);
|
|
3316
|
+
await persistApiKeyAsync(apiKey, serverUrl);
|
|
2910
3317
|
stopAuthSpinner("API key validated and saved");
|
|
2911
3318
|
if (options.scope !== false) {
|
|
2912
3319
|
await configureDefaultScopeAsync(serverUrl);
|
|
@@ -2919,7 +3326,7 @@ async function manualTokenFlow(apiKey, serverUrl, options) {
|
|
|
2919
3326
|
stopAuthSpinner("Validation failed");
|
|
2920
3327
|
const message = error instanceof Error ? error.message : String(error);
|
|
2921
3328
|
log.error(`Failed to validate API key: ${message}`);
|
|
2922
|
-
|
|
3329
|
+
process10.exit(1);
|
|
2923
3330
|
}
|
|
2924
3331
|
}
|
|
2925
3332
|
function handlePollingError(error) {
|
|
@@ -2933,7 +3340,7 @@ function handlePollingError(error) {
|
|
|
2933
3340
|
const message = error instanceof Error ? error.message : String(error);
|
|
2934
3341
|
log.error(`Authentication failed: ${message}`);
|
|
2935
3342
|
}
|
|
2936
|
-
|
|
3343
|
+
process10.exit(1);
|
|
2937
3344
|
}
|
|
2938
3345
|
async function deviceFlow(serverUrl, timeoutSeconds, options) {
|
|
2939
3346
|
const configSpinner = spinner();
|
|
@@ -2946,7 +3353,7 @@ async function deviceFlow(serverUrl, timeoutSeconds, options) {
|
|
|
2946
3353
|
configSpinner.stop("Failed to fetch auth configuration");
|
|
2947
3354
|
const message = error instanceof Error ? error.message : String(error);
|
|
2948
3355
|
log.error(`Could not connect to server: ${message}`);
|
|
2949
|
-
|
|
3356
|
+
process10.exit(1);
|
|
2950
3357
|
}
|
|
2951
3358
|
const deviceSpinner = spinner();
|
|
2952
3359
|
deviceSpinner.start("Initiating device authorization...");
|
|
@@ -2961,7 +3368,7 @@ async function deviceFlow(serverUrl, timeoutSeconds, options) {
|
|
|
2961
3368
|
deviceSpinner.stop("Failed to initiate device authorization");
|
|
2962
3369
|
const message = error instanceof Error ? error.message : String(error);
|
|
2963
3370
|
log.error(`Device authorization failed: ${message}`);
|
|
2964
|
-
|
|
3371
|
+
process10.exit(1);
|
|
2965
3372
|
}
|
|
2966
3373
|
const verificationUrl = buildAuthVerificationUrlFromBaseUrl(
|
|
2967
3374
|
authConfig.verificationBaseUrl,
|
|
@@ -2995,9 +3402,13 @@ async function deviceFlow(serverUrl, timeoutSeconds, options) {
|
|
|
2995
3402
|
pollSpinner.stop("Authentication failed");
|
|
2996
3403
|
handlePollingError(error);
|
|
2997
3404
|
}
|
|
2998
|
-
|
|
3405
|
+
const persistedServerUrl = resolvePersistedCliServerUrl(
|
|
3406
|
+
serverUrl,
|
|
3407
|
+
authConfig.convexSiteUrl
|
|
3408
|
+
);
|
|
3409
|
+
await persistApiKeyAsync(session.sessionToken, persistedServerUrl);
|
|
2999
3410
|
if (options.scope !== false) {
|
|
3000
|
-
await configureDefaultScopeAsync(
|
|
3411
|
+
await configureDefaultScopeAsync(persistedServerUrl);
|
|
3001
3412
|
}
|
|
3002
3413
|
log.success(`Session saved to ${CONFIG_FILE}`);
|
|
3003
3414
|
outro(
|
|
@@ -3025,12 +3436,12 @@ async function authCommand(options) {
|
|
|
3025
3436
|
const timeoutSeconds = options.timeout ? Number.parseInt(options.timeout, 10) : DEFAULT_TIMEOUT_SECONDS;
|
|
3026
3437
|
if (Number.isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
3027
3438
|
log.error("Invalid timeout value. Must be a positive number of seconds.");
|
|
3028
|
-
|
|
3439
|
+
process10.exit(1);
|
|
3029
3440
|
}
|
|
3030
3441
|
await deviceFlow(serverUrl, timeoutSeconds, options);
|
|
3031
3442
|
}
|
|
3032
3443
|
async function displayTokenSource(masked) {
|
|
3033
|
-
if (
|
|
3444
|
+
if (process10.env.BRAID_API_KEY) {
|
|
3034
3445
|
log.info(`Authenticated with key: ${masked}`);
|
|
3035
3446
|
log.info("Source: BRAID_API_KEY environment variable");
|
|
3036
3447
|
return;
|
|
@@ -3111,7 +3522,7 @@ async function authStatusCommand() {
|
|
|
3111
3522
|
);
|
|
3112
3523
|
return;
|
|
3113
3524
|
}
|
|
3114
|
-
if (config.token.startsWith(
|
|
3525
|
+
if (config.token.startsWith(SESSION_TOKEN_PREFIX3)) {
|
|
3115
3526
|
await displaySessionInfo(config.token);
|
|
3116
3527
|
await displayProjectConfig();
|
|
3117
3528
|
displayResolvedSettings(config);
|
|
@@ -3134,7 +3545,7 @@ async function revokeSessionIfActive(token) {
|
|
|
3134
3545
|
async function authLogoutCommand() {
|
|
3135
3546
|
const config = await loadMergedConfigAsync();
|
|
3136
3547
|
const { clearApiKeyAsync: clearApiKeyAsync2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
3137
|
-
if (config.token?.startsWith(
|
|
3548
|
+
if (config.token?.startsWith(SESSION_TOKEN_PREFIX3)) {
|
|
3138
3549
|
await revokeSessionIfActive(config.token);
|
|
3139
3550
|
}
|
|
3140
3551
|
await clearApiKeyAsync2();
|
|
@@ -3146,7 +3557,6 @@ init_esm_shims();
|
|
|
3146
3557
|
init_api();
|
|
3147
3558
|
init_config();
|
|
3148
3559
|
init_tui();
|
|
3149
|
-
import process9 from "process";
|
|
3150
3560
|
var parseCsv2 = (input) => {
|
|
3151
3561
|
if (!input) {
|
|
3152
3562
|
return void 0;
|
|
@@ -3154,15 +3564,6 @@ var parseCsv2 = (input) => {
|
|
|
3154
3564
|
const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
3155
3565
|
return values.length > 0 ? values : void 0;
|
|
3156
3566
|
};
|
|
3157
|
-
var writeJson2 = (value) => {
|
|
3158
|
-
process9.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
3159
|
-
`);
|
|
3160
|
-
};
|
|
3161
|
-
var exitWithError2 = (error) => {
|
|
3162
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3163
|
-
log.error(message);
|
|
3164
|
-
process9.exit(1);
|
|
3165
|
-
};
|
|
3166
3567
|
var applyCommonOptions = (base, options) => ({
|
|
3167
3568
|
...base,
|
|
3168
3569
|
...options.server ? { serverUrl: options.server } : {},
|
|
@@ -3189,7 +3590,7 @@ async function projectsListCommand(options) {
|
|
|
3189
3590
|
applyCommonOptions({}, options)
|
|
3190
3591
|
);
|
|
3191
3592
|
if (options.json) {
|
|
3192
|
-
|
|
3593
|
+
writeJson(result);
|
|
3193
3594
|
return;
|
|
3194
3595
|
}
|
|
3195
3596
|
log.info("Personal projects:");
|
|
@@ -3211,7 +3612,7 @@ Organization: ${orgProjects.orgName} (${orgProjects.orgId})`);
|
|
|
3211
3612
|
}
|
|
3212
3613
|
}
|
|
3213
3614
|
} catch (error) {
|
|
3214
|
-
|
|
3615
|
+
exitCommandError(error, { json: options.json });
|
|
3215
3616
|
}
|
|
3216
3617
|
}
|
|
3217
3618
|
var buildRulesRequest = async (options) => {
|
|
@@ -3232,7 +3633,7 @@ async function rulesListCommand(options) {
|
|
|
3232
3633
|
await buildRulesRequest(options)
|
|
3233
3634
|
);
|
|
3234
3635
|
if (options.json) {
|
|
3235
|
-
|
|
3636
|
+
writeJson(result);
|
|
3236
3637
|
return;
|
|
3237
3638
|
}
|
|
3238
3639
|
if (result.rules.length === 0) {
|
|
@@ -3243,7 +3644,7 @@ async function rulesListCommand(options) {
|
|
|
3243
3644
|
log.info(`${rule.id} ${rule.title}`);
|
|
3244
3645
|
}
|
|
3245
3646
|
} catch (error) {
|
|
3246
|
-
|
|
3647
|
+
exitCommandError(error, { json: options.json });
|
|
3247
3648
|
}
|
|
3248
3649
|
}
|
|
3249
3650
|
var buildSkillsRequest = async (options) => {
|
|
@@ -3263,7 +3664,7 @@ async function skillsListCommand(options) {
|
|
|
3263
3664
|
try {
|
|
3264
3665
|
const result = await fetchSkillsAsync(await buildSkillsRequest(options));
|
|
3265
3666
|
if (options.json) {
|
|
3266
|
-
|
|
3667
|
+
writeJson(result);
|
|
3267
3668
|
return;
|
|
3268
3669
|
}
|
|
3269
3670
|
if (result.skills.length === 0) {
|
|
@@ -3274,7 +3675,7 @@ async function skillsListCommand(options) {
|
|
|
3274
3675
|
log.info(`${skill.name}`);
|
|
3275
3676
|
}
|
|
3276
3677
|
} catch (error) {
|
|
3277
|
-
|
|
3678
|
+
exitCommandError(error, { json: options.json });
|
|
3278
3679
|
}
|
|
3279
3680
|
}
|
|
3280
3681
|
|
|
@@ -3421,11 +3822,11 @@ init_lockfile();
|
|
|
3421
3822
|
init_esm_shims();
|
|
3422
3823
|
import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
3423
3824
|
import { dirname as dirname6, join as join7 } from "path";
|
|
3424
|
-
import { Data as
|
|
3825
|
+
import { Data as Data6, Effect as Effect7, pipe as pipe7 } from "effect";
|
|
3425
3826
|
var METADATA_FILENAME2 = ".braid-metadata.json";
|
|
3426
|
-
var MetadataReadError = class extends
|
|
3827
|
+
var MetadataReadError = class extends Data6.TaggedError("MetadataReadError") {
|
|
3427
3828
|
};
|
|
3428
|
-
var MetadataWriteError = class extends
|
|
3829
|
+
var MetadataWriteError = class extends Data6.TaggedError("MetadataWriteError") {
|
|
3429
3830
|
};
|
|
3430
3831
|
var normalizeInstalledSkill = (skill) => ({
|
|
3431
3832
|
kind: skill.kind ?? "skill",
|
|
@@ -3441,18 +3842,18 @@ var normalizeMetadata = (metadata) => ({
|
|
|
3441
3842
|
var getMetadataPath = (skillsDir) => join7(dirname6(skillsDir), METADATA_FILENAME2);
|
|
3442
3843
|
var readMetadata = (skillsDir) => {
|
|
3443
3844
|
const metadataPath = getMetadataPath(skillsDir);
|
|
3444
|
-
return
|
|
3445
|
-
|
|
3845
|
+
return pipe7(
|
|
3846
|
+
Effect7.tryPromise({
|
|
3446
3847
|
try: () => readFile4(metadataPath, "utf-8"),
|
|
3447
3848
|
catch: (e) => new MetadataReadError({ path: metadataPath, cause: e })
|
|
3448
3849
|
}),
|
|
3449
|
-
|
|
3450
|
-
(content) =>
|
|
3850
|
+
Effect7.flatMap(
|
|
3851
|
+
(content) => Effect7.try({
|
|
3451
3852
|
try: () => normalizeMetadata(JSON.parse(content)),
|
|
3452
3853
|
catch: () => normalizeMetadata(void 0)
|
|
3453
3854
|
})
|
|
3454
3855
|
),
|
|
3455
|
-
|
|
3856
|
+
Effect7.orElseSucceed(() => normalizeMetadata(void 0))
|
|
3456
3857
|
);
|
|
3457
3858
|
};
|
|
3458
3859
|
var readRawJson = async (path2) => {
|
|
@@ -3469,7 +3870,7 @@ var readRawJson = async (path2) => {
|
|
|
3469
3870
|
};
|
|
3470
3871
|
var writeMetadata = (skillsDir, metadata) => {
|
|
3471
3872
|
const metadataPath = getMetadataPath(skillsDir);
|
|
3472
|
-
return
|
|
3873
|
+
return Effect7.tryPromise({
|
|
3473
3874
|
try: async () => {
|
|
3474
3875
|
const existing = await readRawJson(metadataPath);
|
|
3475
3876
|
const merged = { ...existing, skills: metadata.skills };
|
|
@@ -3478,9 +3879,9 @@ var writeMetadata = (skillsDir, metadata) => {
|
|
|
3478
3879
|
catch: (e) => new MetadataWriteError({ path: metadataPath, cause: e })
|
|
3479
3880
|
});
|
|
3480
3881
|
};
|
|
3481
|
-
var updateMetadata = (skillsDir, newSkills) =>
|
|
3882
|
+
var updateMetadata = (skillsDir, newSkills) => pipe7(
|
|
3482
3883
|
readMetadata(skillsDir),
|
|
3483
|
-
|
|
3884
|
+
Effect7.map((existing) => {
|
|
3484
3885
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3485
3886
|
const updatedSkills = [...existing.skills];
|
|
3486
3887
|
for (const skill of newSkills) {
|
|
@@ -3503,35 +3904,35 @@ var updateMetadata = (skillsDir, newSkills) => pipe6(
|
|
|
3503
3904
|
}
|
|
3504
3905
|
return { skills: updatedSkills };
|
|
3505
3906
|
}),
|
|
3506
|
-
|
|
3907
|
+
Effect7.flatMap((metadata) => writeMetadata(skillsDir, metadata))
|
|
3507
3908
|
);
|
|
3508
|
-
var removeFromMetadata = (skillsDir, skillName) =>
|
|
3909
|
+
var removeFromMetadata = (skillsDir, skillName) => pipe7(
|
|
3509
3910
|
readMetadata(skillsDir),
|
|
3510
|
-
|
|
3911
|
+
Effect7.map((metadata) => ({
|
|
3511
3912
|
skills: metadata.skills.filter((s) => s.name !== skillName)
|
|
3512
3913
|
})),
|
|
3513
|
-
|
|
3914
|
+
Effect7.flatMap((metadata) => writeMetadata(skillsDir, metadata))
|
|
3514
3915
|
);
|
|
3515
|
-
var readMetadataAsync = (skillsDir) =>
|
|
3516
|
-
var updateMetadataAsync = (skillsDir, newSkills) =>
|
|
3517
|
-
var removeFromMetadataAsync = (skillsDir, skillName) =>
|
|
3916
|
+
var readMetadataAsync = (skillsDir) => Effect7.runPromise(readMetadata(skillsDir));
|
|
3917
|
+
var updateMetadataAsync = (skillsDir, newSkills) => Effect7.runPromise(updateMetadata(skillsDir, newSkills));
|
|
3918
|
+
var removeFromMetadataAsync = (skillsDir, skillName) => Effect7.runPromise(removeFromMetadata(skillsDir, skillName));
|
|
3518
3919
|
|
|
3519
3920
|
// src/lib/rule-writer.ts
|
|
3520
3921
|
init_esm_shims();
|
|
3521
3922
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
3522
3923
|
import { dirname as dirname7, resolve as resolve3, sep as sep2 } from "path";
|
|
3523
|
-
import { Data as
|
|
3524
|
-
var RuleWriteError = class extends
|
|
3924
|
+
import { Data as Data7, Effect as Effect8, pipe as pipe8 } from "effect";
|
|
3925
|
+
var RuleWriteError = class extends Data7.TaggedError("RuleWriteError") {
|
|
3525
3926
|
};
|
|
3526
|
-
var createDirectory = (dir) =>
|
|
3927
|
+
var createDirectory = (dir) => Effect8.tryPromise({
|
|
3527
3928
|
try: () => mkdir4(dir, { recursive: true }),
|
|
3528
3929
|
catch: (e) => new RuleWriteError({ path: dir, operation: "mkdir", cause: e })
|
|
3529
3930
|
});
|
|
3530
|
-
var writeTextFile = (fullPath, content) =>
|
|
3931
|
+
var writeTextFile = (fullPath, content) => Effect8.tryPromise({
|
|
3531
3932
|
try: () => writeFile6(fullPath, content, "utf-8"),
|
|
3532
3933
|
catch: (e) => new RuleWriteError({ path: fullPath, operation: "write", cause: e })
|
|
3533
3934
|
});
|
|
3534
|
-
var readTextFile = (fullPath) =>
|
|
3935
|
+
var readTextFile = (fullPath) => Effect8.tryPromise({
|
|
3535
3936
|
try: () => readFile5(fullPath, "utf-8"),
|
|
3536
3937
|
catch: (e) => new RuleWriteError({ path: fullPath, operation: "read", cause: e })
|
|
3537
3938
|
});
|
|
@@ -3539,7 +3940,7 @@ var assertRulePathWithinBase = (basePath, ruleName) => {
|
|
|
3539
3940
|
const resolvedBase = resolve3(basePath);
|
|
3540
3941
|
const resolvedFull = resolve3(basePath, ruleName);
|
|
3541
3942
|
if (resolvedFull !== resolvedBase && !resolvedFull.startsWith(resolvedBase + sep2)) {
|
|
3542
|
-
return
|
|
3943
|
+
return Effect8.fail(
|
|
3543
3944
|
new RuleWriteError({
|
|
3544
3945
|
path: ruleName,
|
|
3545
3946
|
operation: "write",
|
|
@@ -3549,7 +3950,7 @@ var assertRulePathWithinBase = (basePath, ruleName) => {
|
|
|
3549
3950
|
})
|
|
3550
3951
|
);
|
|
3551
3952
|
}
|
|
3552
|
-
return
|
|
3953
|
+
return Effect8.succeed(resolvedFull);
|
|
3553
3954
|
};
|
|
3554
3955
|
var BRAID_SECTION_START = "<!-- braid:rules:start -->";
|
|
3555
3956
|
var BRAID_SECTION_END = "<!-- braid:rules:end -->";
|
|
@@ -3582,30 +3983,30 @@ function buildAppendContent(rules2) {
|
|
|
3582
3983
|
lines.push(BRAID_SECTION_END);
|
|
3583
3984
|
return lines.join("\n");
|
|
3584
3985
|
}
|
|
3585
|
-
var writeMdcRules = (basePath, rules2) =>
|
|
3986
|
+
var writeMdcRules = (basePath, rules2) => pipe8(
|
|
3586
3987
|
createDirectory(basePath),
|
|
3587
|
-
|
|
3588
|
-
() =>
|
|
3988
|
+
Effect8.flatMap(
|
|
3989
|
+
() => Effect8.forEach(
|
|
3589
3990
|
rules2,
|
|
3590
|
-
(rule) =>
|
|
3991
|
+
(rule) => pipe8(
|
|
3591
3992
|
assertRulePathWithinBase(basePath, `${rule.name}.mdc`),
|
|
3592
|
-
|
|
3993
|
+
Effect8.flatMap(
|
|
3593
3994
|
(filePath) => writeTextFile(filePath, buildMdcContent(rule))
|
|
3594
3995
|
)
|
|
3595
3996
|
),
|
|
3596
3997
|
{ concurrency: "unbounded" }
|
|
3597
3998
|
)
|
|
3598
3999
|
),
|
|
3599
|
-
|
|
4000
|
+
Effect8.asVoid
|
|
3600
4001
|
);
|
|
3601
|
-
var writeMarkdownDirRules = (basePath, rules2) =>
|
|
4002
|
+
var writeMarkdownDirRules = (basePath, rules2) => pipe8(
|
|
3602
4003
|
createDirectory(basePath),
|
|
3603
|
-
|
|
3604
|
-
() =>
|
|
4004
|
+
Effect8.flatMap(
|
|
4005
|
+
() => Effect8.forEach(
|
|
3605
4006
|
rules2,
|
|
3606
|
-
(rule) =>
|
|
4007
|
+
(rule) => pipe8(
|
|
3607
4008
|
assertRulePathWithinBase(basePath, `${rule.name}.md`),
|
|
3608
|
-
|
|
4009
|
+
Effect8.flatMap(
|
|
3609
4010
|
(filePath) => writeTextFile(filePath, `# ${rule.title}
|
|
3610
4011
|
|
|
3611
4012
|
${rule.content}`)
|
|
@@ -3614,17 +4015,17 @@ ${rule.content}`)
|
|
|
3614
4015
|
{ concurrency: "unbounded" }
|
|
3615
4016
|
)
|
|
3616
4017
|
),
|
|
3617
|
-
|
|
4018
|
+
Effect8.asVoid
|
|
3618
4019
|
);
|
|
3619
|
-
var writeAppendSingleRules = (filePath, rules2) =>
|
|
4020
|
+
var writeAppendSingleRules = (filePath, rules2) => pipe8(
|
|
3620
4021
|
createDirectory(dirname7(filePath)),
|
|
3621
|
-
|
|
3622
|
-
() =>
|
|
4022
|
+
Effect8.flatMap(
|
|
4023
|
+
() => pipe8(
|
|
3623
4024
|
readTextFile(filePath),
|
|
3624
|
-
|
|
4025
|
+
Effect8.orElseSucceed(() => "")
|
|
3625
4026
|
)
|
|
3626
4027
|
),
|
|
3627
|
-
|
|
4028
|
+
Effect8.flatMap((existing) => {
|
|
3628
4029
|
const braidContent = buildAppendContent(rules2);
|
|
3629
4030
|
const startIdx = existing.indexOf(BRAID_SECTION_START);
|
|
3630
4031
|
const endIdx = existing.indexOf(BRAID_SECTION_END);
|
|
@@ -3648,21 +4049,21 @@ var writeRulesForFormat = (basePath, rules2, format) => {
|
|
|
3648
4049
|
case "append-single":
|
|
3649
4050
|
return writeAppendSingleRules(basePath, rules2);
|
|
3650
4051
|
default:
|
|
3651
|
-
return
|
|
4052
|
+
return Effect8.void;
|
|
3652
4053
|
}
|
|
3653
4054
|
};
|
|
3654
4055
|
var writeRulesForAgent = (agent, rules2, rulesPath) => {
|
|
3655
4056
|
if (!agent.ruleFormat || rules2.length === 0) {
|
|
3656
|
-
return
|
|
4057
|
+
return Effect8.succeed({ written: 0, errors: [] });
|
|
3657
4058
|
}
|
|
3658
|
-
return
|
|
4059
|
+
return pipe8(
|
|
3659
4060
|
writeRulesForFormat(rulesPath, rules2, agent.ruleFormat),
|
|
3660
|
-
|
|
4061
|
+
Effect8.map(() => ({
|
|
3661
4062
|
written: rules2.length,
|
|
3662
4063
|
errors: []
|
|
3663
4064
|
})),
|
|
3664
|
-
|
|
3665
|
-
(error) =>
|
|
4065
|
+
Effect8.catch(
|
|
4066
|
+
(error) => Effect8.succeed({
|
|
3666
4067
|
written: 0,
|
|
3667
4068
|
errors: [
|
|
3668
4069
|
{
|
|
@@ -3674,29 +4075,29 @@ var writeRulesForAgent = (agent, rules2, rulesPath) => {
|
|
|
3674
4075
|
)
|
|
3675
4076
|
);
|
|
3676
4077
|
};
|
|
3677
|
-
var writeRulesForAgentAsync = (agent, rules2, rulesPath) =>
|
|
4078
|
+
var writeRulesForAgentAsync = (agent, rules2, rulesPath) => Effect8.runPromise(writeRulesForAgent(agent, rules2, rulesPath));
|
|
3678
4079
|
|
|
3679
4080
|
// src/lib/skill-writer.ts
|
|
3680
4081
|
init_esm_shims();
|
|
3681
4082
|
import { createHash as createHash2 } from "crypto";
|
|
3682
4083
|
import { chmod, mkdir as mkdir5, rm as rm2, symlink, writeFile as writeFile7 } from "fs/promises";
|
|
3683
4084
|
import { dirname as dirname8, join as join8, resolve as resolve4, sep as sep3 } from "path";
|
|
3684
|
-
import { Data as
|
|
3685
|
-
var WriteError = class extends
|
|
4085
|
+
import { Data as Data8, Effect as Effect9, pipe as pipe9 } from "effect";
|
|
4086
|
+
var WriteError = class extends Data8.TaggedError("WriteError") {
|
|
3686
4087
|
};
|
|
3687
|
-
var createDirectory2 = (dir, fullPath) =>
|
|
4088
|
+
var createDirectory2 = (dir, fullPath) => Effect9.tryPromise({
|
|
3688
4089
|
try: () => mkdir5(dir, { recursive: true }),
|
|
3689
4090
|
catch: (e) => new WriteError({ path: fullPath, operation: "mkdir", cause: e })
|
|
3690
4091
|
});
|
|
3691
|
-
var writeTextFile2 = (fullPath, content) =>
|
|
4092
|
+
var writeTextFile2 = (fullPath, content) => Effect9.tryPromise({
|
|
3692
4093
|
try: () => writeFile7(fullPath, content, "utf-8"),
|
|
3693
4094
|
catch: (e) => new WriteError({ path: fullPath, operation: "write", cause: e })
|
|
3694
4095
|
});
|
|
3695
|
-
var writeBinaryFile = (fullPath, content) =>
|
|
4096
|
+
var writeBinaryFile = (fullPath, content) => Effect9.tryPromise({
|
|
3696
4097
|
try: () => writeFile7(fullPath, content),
|
|
3697
4098
|
catch: (e) => new WriteError({ path: fullPath, operation: "write", cause: e })
|
|
3698
4099
|
});
|
|
3699
|
-
var makeExecutable = (fullPath) =>
|
|
4100
|
+
var makeExecutable = (fullPath) => Effect9.tryPromise({
|
|
3700
4101
|
try: () => chmod(fullPath, 493),
|
|
3701
4102
|
catch: (e) => new WriteError({ path: fullPath, operation: "chmod", cause: e })
|
|
3702
4103
|
});
|
|
@@ -3704,7 +4105,7 @@ var assertWithinBase2 = (basePath, untrustedPath) => {
|
|
|
3704
4105
|
const resolvedBase = resolve4(basePath);
|
|
3705
4106
|
const resolvedFull = resolve4(basePath, untrustedPath);
|
|
3706
4107
|
if (resolvedFull !== resolvedBase && !resolvedFull.startsWith(resolvedBase + sep3)) {
|
|
3707
|
-
return
|
|
4108
|
+
return Effect9.fail(
|
|
3708
4109
|
new WriteError({
|
|
3709
4110
|
path: untrustedPath,
|
|
3710
4111
|
operation: "write",
|
|
@@ -3714,7 +4115,7 @@ var assertWithinBase2 = (basePath, untrustedPath) => {
|
|
|
3714
4115
|
})
|
|
3715
4116
|
);
|
|
3716
4117
|
}
|
|
3717
|
-
return
|
|
4118
|
+
return Effect9.succeed(resolvedFull);
|
|
3718
4119
|
};
|
|
3719
4120
|
var COMPATIBILITY_REGEX = /^compatibility:\s*.+$/m;
|
|
3720
4121
|
var rewriteCompatibility = (content, agentId) => {
|
|
@@ -3757,22 +4158,22 @@ var isScriptFile = (path2) => {
|
|
|
3757
4158
|
return inScriptsDir && scriptExtensions.some((ext) => lowerPath.endsWith(ext));
|
|
3758
4159
|
};
|
|
3759
4160
|
var writeFileContent = (fullPath, file, agentId) => isBinaryFile(file.path) ? writeBinaryFile(fullPath, decodeFileContentBinary(file)) : writeTextFile2(fullPath, decodeFileContent(file, agentId));
|
|
3760
|
-
var setExecutableIfScript = (fullPath, file, agentId) => isScriptFile(file.path) && decodeFileContent(file, agentId).startsWith("#!") ? makeExecutable(fullPath) :
|
|
3761
|
-
var writeSkillFile = (basePath, file, agentId) =>
|
|
4161
|
+
var setExecutableIfScript = (fullPath, file, agentId) => isScriptFile(file.path) && decodeFileContent(file, agentId).startsWith("#!") ? makeExecutable(fullPath) : Effect9.void;
|
|
4162
|
+
var writeSkillFile = (basePath, file, agentId) => pipe9(
|
|
3762
4163
|
assertWithinBase2(basePath, file.path),
|
|
3763
|
-
|
|
4164
|
+
Effect9.flatMap((fullPath) => {
|
|
3764
4165
|
const dir = dirname8(fullPath);
|
|
3765
|
-
return
|
|
4166
|
+
return pipe9(
|
|
3766
4167
|
createDirectory2(dir, fullPath),
|
|
3767
|
-
|
|
3768
|
-
|
|
4168
|
+
Effect9.flatMap(() => writeFileContent(fullPath, file, agentId)),
|
|
4169
|
+
Effect9.flatMap(() => setExecutableIfScript(fullPath, file, agentId))
|
|
3769
4170
|
);
|
|
3770
4171
|
})
|
|
3771
4172
|
);
|
|
3772
|
-
var writeSkillAtPath = (skillPath, skill, agentId) =>
|
|
4173
|
+
var writeSkillAtPath = (skillPath, skill, agentId) => pipe9(
|
|
3773
4174
|
createDirectory2(skillPath, skillPath),
|
|
3774
|
-
|
|
3775
|
-
() =>
|
|
4175
|
+
Effect9.flatMap(
|
|
4176
|
+
() => Effect9.forEach(
|
|
3776
4177
|
skill.files,
|
|
3777
4178
|
(file) => writeSkillFile(skillPath, file, agentId),
|
|
3778
4179
|
{
|
|
@@ -3780,16 +4181,16 @@ var writeSkillAtPath = (skillPath, skill, agentId) => pipe8(
|
|
|
3780
4181
|
}
|
|
3781
4182
|
)
|
|
3782
4183
|
),
|
|
3783
|
-
|
|
4184
|
+
Effect9.map(() => void 0)
|
|
3784
4185
|
);
|
|
3785
|
-
var writeSkill = (basePath, skill, agentId) =>
|
|
4186
|
+
var writeSkill = (basePath, skill, agentId) => pipe9(
|
|
3786
4187
|
assertWithinBase2(basePath, skill.name),
|
|
3787
|
-
|
|
4188
|
+
Effect9.flatMap((skillDir) => writeSkillAtPath(skillDir, skill, agentId))
|
|
3788
4189
|
);
|
|
3789
|
-
var writeSkillSymlink = (basePath, skill, agentId, options) =>
|
|
4190
|
+
var writeSkillSymlink = (basePath, skill, agentId, options) => pipe9(
|
|
3790
4191
|
assertWithinBase2(basePath, skill.name),
|
|
3791
|
-
|
|
3792
|
-
(installPath) =>
|
|
4192
|
+
Effect9.flatMap(
|
|
4193
|
+
(installPath) => Effect9.tryPromise({
|
|
3793
4194
|
try: async () => {
|
|
3794
4195
|
if (!options.storeRoot) {
|
|
3795
4196
|
throw new Error("storeRoot is required for shared-store installs");
|
|
@@ -3799,7 +4200,7 @@ var writeSkillSymlink = (basePath, skill, agentId, options) => pipe8(
|
|
|
3799
4200
|
skill,
|
|
3800
4201
|
agentId
|
|
3801
4202
|
);
|
|
3802
|
-
await
|
|
4203
|
+
await Effect9.runPromise(
|
|
3803
4204
|
writeSkillAtPath(storedBundlePath, skill, agentId)
|
|
3804
4205
|
);
|
|
3805
4206
|
const destinationPath = await resolveManagedBundlePathAsync(
|
|
@@ -3826,14 +4227,14 @@ var writeSkillSymlink = (basePath, skill, agentId, options) => pipe8(
|
|
|
3826
4227
|
);
|
|
3827
4228
|
var hashSkill = (skill, agentId) => createHash2("sha256").update(JSON.stringify({ agentId, skill })).digest("hex").slice(0, 16);
|
|
3828
4229
|
var resolveStorePath = (storeRoot, skill, agentId) => join8(storeRoot, `${skill.name}-${hashSkill(skill, agentId)}`);
|
|
3829
|
-
var writeSkills = (basePath, skills2, agentId, options = {}) =>
|
|
3830
|
-
|
|
4230
|
+
var writeSkills = (basePath, skills2, agentId, options = {}) => pipe9(
|
|
4231
|
+
Effect9.forEach(
|
|
3831
4232
|
skills2,
|
|
3832
|
-
(skill) =>
|
|
4233
|
+
(skill) => pipe9(
|
|
3833
4234
|
options.storeRoot ? writeSkillSymlink(basePath, skill, agentId, options) : writeSkill(basePath, skill, agentId),
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
(error) =>
|
|
4235
|
+
Effect9.map(() => ({ success: true, skill: skill.name })),
|
|
4236
|
+
Effect9.catch(
|
|
4237
|
+
(error) => Effect9.succeed({
|
|
3837
4238
|
success: false,
|
|
3838
4239
|
skill: skill.name,
|
|
3839
4240
|
error: error.cause instanceof Error ? error.cause.message : String(error.cause)
|
|
@@ -3842,14 +4243,14 @@ var writeSkills = (basePath, skills2, agentId, options = {}) => pipe8(
|
|
|
3842
4243
|
),
|
|
3843
4244
|
{ concurrency: "unbounded" }
|
|
3844
4245
|
),
|
|
3845
|
-
|
|
4246
|
+
Effect9.map((results) => ({
|
|
3846
4247
|
written: results.filter((r) => r.success).map((r) => r.skill),
|
|
3847
4248
|
errors: results.filter(
|
|
3848
4249
|
(r) => !r.success
|
|
3849
4250
|
).map((r) => ({ skill: r.skill, error: r.error }))
|
|
3850
4251
|
}))
|
|
3851
4252
|
);
|
|
3852
|
-
var writeSkillsAsync = (basePath, skills2, agentId, options) =>
|
|
4253
|
+
var writeSkillsAsync = (basePath, skills2, agentId, options) => Effect9.runPromise(writeSkills(basePath, skills2, agentId, options));
|
|
3853
4254
|
|
|
3854
4255
|
// src/commands/install.ts
|
|
3855
4256
|
init_tui();
|
|
@@ -4299,6 +4700,7 @@ async function writeLockfileAfterInstall(handle, slug, version, contentHash, rul
|
|
|
4299
4700
|
}
|
|
4300
4701
|
}
|
|
4301
4702
|
async function publicInstallCommand(source, options) {
|
|
4703
|
+
const config = await loadMergedConfigAsync();
|
|
4302
4704
|
const parsed = parsePublicSource(source);
|
|
4303
4705
|
if (!parsed) {
|
|
4304
4706
|
log.error(`Invalid public source: ${source}`);
|
|
@@ -4322,6 +4724,7 @@ async function publicInstallCommand(source, options) {
|
|
|
4322
4724
|
log.info(`Using locked version: v${version}`);
|
|
4323
4725
|
}
|
|
4324
4726
|
const versionSuffix = version !== void 0 ? `@${version}` : "";
|
|
4727
|
+
const serverUrl = options.server ?? config.serverUrl;
|
|
4325
4728
|
intro(`Installing from @${handle}/${slug}${versionSuffix}`);
|
|
4326
4729
|
const installSpinner = spinner();
|
|
4327
4730
|
installSpinner.start("Fetching public content...");
|
|
@@ -4331,7 +4734,10 @@ async function publicInstallCommand(source, options) {
|
|
|
4331
4734
|
slug,
|
|
4332
4735
|
version,
|
|
4333
4736
|
lockedRuleIds,
|
|
4334
|
-
|
|
4737
|
+
{
|
|
4738
|
+
...options,
|
|
4739
|
+
server: serverUrl
|
|
4740
|
+
},
|
|
4335
4741
|
installSpinner
|
|
4336
4742
|
);
|
|
4337
4743
|
installSpinner.stop(`Downloaded ${summarizeContent(response)}`);
|
|
@@ -4339,11 +4745,13 @@ async function publicInstallCommand(source, options) {
|
|
|
4339
4745
|
log.warn("No content to install.");
|
|
4340
4746
|
process.exit(0);
|
|
4341
4747
|
}
|
|
4342
|
-
const serverUrl = options.server ?? "https://braid.cloud";
|
|
4343
4748
|
const { totalWritten, totalErrors } = await installToSelectedAgents(
|
|
4344
4749
|
response,
|
|
4345
4750
|
serverUrl,
|
|
4346
|
-
|
|
4751
|
+
{
|
|
4752
|
+
...options,
|
|
4753
|
+
server: serverUrl
|
|
4754
|
+
},
|
|
4347
4755
|
installSpinner
|
|
4348
4756
|
);
|
|
4349
4757
|
if (totalWritten > 0 && version !== void 0) {
|
|
@@ -4540,7 +4948,8 @@ async function listCommand(options) {
|
|
|
4540
4948
|
|
|
4541
4949
|
// src/commands/manage.ts
|
|
4542
4950
|
init_esm_shims();
|
|
4543
|
-
|
|
4951
|
+
init_device_auth();
|
|
4952
|
+
import process11 from "process";
|
|
4544
4953
|
|
|
4545
4954
|
// src/lib/manage-server.ts
|
|
4546
4955
|
init_esm_shims();
|
|
@@ -4550,6 +4959,7 @@ import { createServer } from "http";
|
|
|
4550
4959
|
import { isAbsolute, relative as relative2, resolve as resolve6 } from "path";
|
|
4551
4960
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4552
4961
|
init_config();
|
|
4962
|
+
init_device_auth();
|
|
4553
4963
|
|
|
4554
4964
|
// src/lib/manage-actions.ts
|
|
4555
4965
|
init_esm_shims();
|
|
@@ -4560,8 +4970,8 @@ import { basename as basename2, dirname as dirname10, join as join11, relative }
|
|
|
4560
4970
|
init_esm_shims();
|
|
4561
4971
|
import { mkdir as mkdir6, readFile as readFile6, rm as rm3, writeFile as writeFile8 } from "fs/promises";
|
|
4562
4972
|
import { dirname as dirname9, join as join9 } from "path";
|
|
4563
|
-
import { Data as
|
|
4564
|
-
var HookConfigWriteError = class extends
|
|
4973
|
+
import { Data as Data9, Effect as Effect10 } from "effect";
|
|
4974
|
+
var HookConfigWriteError = class extends Data9.TaggedError("HookConfigWriteError") {
|
|
4565
4975
|
};
|
|
4566
4976
|
var HOOK_METADATA_FILENAME = ".braid-metadata.json";
|
|
4567
4977
|
function stableStringify(value) {
|
|
@@ -4886,7 +5296,7 @@ async function ensureMarketplaceHookBundleFile(settingsPath, sourceSlug) {
|
|
|
4886
5296
|
});
|
|
4887
5297
|
return bundlePath;
|
|
4888
5298
|
}
|
|
4889
|
-
var writeMarketplaceHooks = (settingsPath, hooks, options) =>
|
|
5299
|
+
var writeMarketplaceHooks = (settingsPath, hooks, options) => Effect10.tryPromise({
|
|
4890
5300
|
try: async () => {
|
|
4891
5301
|
const activeHooks = hooks.filter(
|
|
4892
5302
|
(hook) => hook.enabled !== false && hook.runtime === "claude"
|
|
@@ -4941,131 +5351,18 @@ var writeMarketplaceHooks = (settingsPath, hooks, options) => Effect9.tryPromise
|
|
|
4941
5351
|
},
|
|
4942
5352
|
catch: (cause) => new HookConfigWriteError({ path: settingsPath, cause })
|
|
4943
5353
|
});
|
|
4944
|
-
var writeMarketplaceHooksAsync = (settingsPath, hooks, options) =>
|
|
5354
|
+
var writeMarketplaceHooksAsync = (settingsPath, hooks, options) => Effect10.runPromise(writeMarketplaceHooks(settingsPath, hooks, options));
|
|
4945
5355
|
var removeMarketplaceHooksBySourceAsync = (settingsPath, sourceSlug) => removeMarketplaceHooksBySource(settingsPath, sourceSlug);
|
|
4946
5356
|
var ensureMarketplaceHookBundleFileAsync = (settingsPath, sourceSlug) => ensureMarketplaceHookBundleFile(settingsPath, sourceSlug);
|
|
4947
5357
|
var listInstalledMarketplaceHookSourcesAsync = (settingsPath) => listInstalledMarketplaceHookSources(settingsPath);
|
|
4948
5358
|
var readMarketplaceHookBundleFileAsync = (bundlePath) => readMarketplaceHookBundleFile(bundlePath);
|
|
4949
5359
|
|
|
4950
|
-
// src/lib/marketplace-api.ts
|
|
4951
|
-
init_esm_shims();
|
|
4952
|
-
init_config();
|
|
4953
|
-
import { Data as Data9, Effect as Effect10, pipe as pipe9 } from "effect";
|
|
4954
|
-
var TRAILING_SLASH_REGEX2 = /\/$/;
|
|
4955
|
-
var MarketplaceApiError = class extends Data9.TaggedError("MarketplaceApiError") {
|
|
4956
|
-
};
|
|
4957
|
-
var resolveApiKey2 = (provided) => {
|
|
4958
|
-
if (provided) {
|
|
4959
|
-
return Effect10.succeed(provided);
|
|
4960
|
-
}
|
|
4961
|
-
return pipe9(
|
|
4962
|
-
Effect10.tryPromise({
|
|
4963
|
-
try: () => getApiKeyAsync(),
|
|
4964
|
-
catch: () => new MarketplaceApiError({
|
|
4965
|
-
message: "Failed to load API key",
|
|
4966
|
-
status: 500,
|
|
4967
|
-
code: "CONFIG_ERROR"
|
|
4968
|
-
})
|
|
4969
|
-
}),
|
|
4970
|
-
Effect10.flatMap(
|
|
4971
|
-
(token) => token ? Effect10.succeed(token) : Effect10.fail(
|
|
4972
|
-
new MarketplaceApiError({
|
|
4973
|
-
message: "Not signed in. Run 'braid auth'.",
|
|
4974
|
-
status: 401,
|
|
4975
|
-
code: "AUTH_REQUIRED"
|
|
4976
|
-
})
|
|
4977
|
-
)
|
|
4978
|
-
)
|
|
4979
|
-
);
|
|
4980
|
-
};
|
|
4981
|
-
var resolveServer = (provided) => {
|
|
4982
|
-
if (provided) {
|
|
4983
|
-
return Effect10.succeed(provided.replace(TRAILING_SLASH_REGEX2, ""));
|
|
4984
|
-
}
|
|
4985
|
-
return pipe9(
|
|
4986
|
-
Effect10.tryPromise({
|
|
4987
|
-
try: () => getServerUrlAsync(),
|
|
4988
|
-
catch: () => new MarketplaceApiError({
|
|
4989
|
-
message: "Failed to load server URL",
|
|
4990
|
-
status: 500,
|
|
4991
|
-
code: "CONFIG_ERROR"
|
|
4992
|
-
})
|
|
4993
|
-
}),
|
|
4994
|
-
Effect10.map((server) => server.replace(TRAILING_SLASH_REGEX2, ""))
|
|
4995
|
-
);
|
|
4996
|
-
};
|
|
4997
|
-
var requestJson = (url, options) => pipe9(
|
|
4998
|
-
Effect10.tryPromise({
|
|
4999
|
-
try: () => fetch(url, options),
|
|
5000
|
-
catch: () => new MarketplaceApiError({
|
|
5001
|
-
message: "Network error",
|
|
5002
|
-
status: 503,
|
|
5003
|
-
code: "NETWORK_ERROR"
|
|
5004
|
-
})
|
|
5005
|
-
}),
|
|
5006
|
-
Effect10.flatMap(
|
|
5007
|
-
(response) => Effect10.tryPromise({
|
|
5008
|
-
try: async () => {
|
|
5009
|
-
const payload = await response.json().catch(() => null);
|
|
5010
|
-
if (!response.ok) {
|
|
5011
|
-
throw new MarketplaceApiError({
|
|
5012
|
-
message: payload?.error ?? payload?.message ?? `Request failed (HTTP ${response.status} from ${new URL(url).origin})`,
|
|
5013
|
-
status: response.status,
|
|
5014
|
-
code: payload?.code ?? "REQUEST_ERROR"
|
|
5015
|
-
});
|
|
5016
|
-
}
|
|
5017
|
-
return payload;
|
|
5018
|
-
},
|
|
5019
|
-
catch: (error) => error instanceof MarketplaceApiError ? error : new MarketplaceApiError({
|
|
5020
|
-
message: "Invalid response",
|
|
5021
|
-
status: 500,
|
|
5022
|
-
code: "PARSE_ERROR"
|
|
5023
|
-
})
|
|
5024
|
-
})
|
|
5025
|
-
)
|
|
5026
|
-
);
|
|
5027
|
-
var fetchMarketplaceLibrary = (options) => pipe9(
|
|
5028
|
-
Effect10.all({
|
|
5029
|
-
server: resolveServer(options.server),
|
|
5030
|
-
apiKey: resolveApiKey2(options.apiKey)
|
|
5031
|
-
}),
|
|
5032
|
-
Effect10.flatMap(
|
|
5033
|
-
({ server, apiKey }) => requestJson(
|
|
5034
|
-
`${server}/api/marketplace/library`,
|
|
5035
|
-
{
|
|
5036
|
-
method: "GET",
|
|
5037
|
-
headers: {
|
|
5038
|
-
Authorization: `Bearer ${apiKey}`
|
|
5039
|
-
}
|
|
5040
|
-
}
|
|
5041
|
-
)
|
|
5042
|
-
),
|
|
5043
|
-
Effect10.map((response) => response.items)
|
|
5044
|
-
);
|
|
5045
|
-
var fetchMarketplaceInstallManifest = (slug, options) => pipe9(
|
|
5046
|
-
Effect10.all({
|
|
5047
|
-
server: resolveServer(options.server),
|
|
5048
|
-
apiKey: resolveApiKey2(options.apiKey)
|
|
5049
|
-
}),
|
|
5050
|
-
Effect10.flatMap(
|
|
5051
|
-
({ server, apiKey }) => requestJson(
|
|
5052
|
-
`${server}/api/marketplace/install-manifest/${encodeURIComponent(slug)}`,
|
|
5053
|
-
{
|
|
5054
|
-
method: "GET",
|
|
5055
|
-
headers: {
|
|
5056
|
-
Authorization: `Bearer ${apiKey}`
|
|
5057
|
-
}
|
|
5058
|
-
}
|
|
5059
|
-
)
|
|
5060
|
-
)
|
|
5061
|
-
);
|
|
5062
|
-
var fetchMarketplaceLibraryAsync = (options) => Effect10.runPromise(fetchMarketplaceLibrary(options));
|
|
5063
|
-
var fetchMarketplaceInstallManifestAsync = (slug, options) => Effect10.runPromise(fetchMarketplaceInstallManifest(slug, options));
|
|
5064
|
-
|
|
5065
5360
|
// src/lib/marketplace-installer.ts
|
|
5066
5361
|
init_esm_shims();
|
|
5067
5362
|
import { rm as rm4 } from "fs/promises";
|
|
5068
5363
|
import { join as join10 } from "path";
|
|
5364
|
+
init_config();
|
|
5365
|
+
var TRAILING_SLASH_REGEX3 = /\/$/;
|
|
5069
5366
|
function parseAgentIds(value) {
|
|
5070
5367
|
if (!value) {
|
|
5071
5368
|
return [];
|
|
@@ -5135,7 +5432,7 @@ async function installSkillsForAgent(args) {
|
|
|
5135
5432
|
versionId: args.manifest.versionId
|
|
5136
5433
|
},
|
|
5137
5434
|
version: args.manifest.versionId ?? args.manifest.commitSha ?? "unknown",
|
|
5138
|
-
serverUrl:
|
|
5435
|
+
serverUrl: args.serverUrl
|
|
5139
5436
|
}))
|
|
5140
5437
|
);
|
|
5141
5438
|
args.targets.push(`${args.agent.name} -> ${installPath}`);
|
|
@@ -5224,6 +5521,7 @@ async function installAllForAgent(args) {
|
|
|
5224
5521
|
agent: args.agent,
|
|
5225
5522
|
manifest: args.manifest,
|
|
5226
5523
|
slug: args.slug,
|
|
5524
|
+
serverUrl: args.serverUrl,
|
|
5227
5525
|
skills: args.skills,
|
|
5228
5526
|
global: args.global,
|
|
5229
5527
|
installedSkills: args.installedSkills,
|
|
@@ -5281,6 +5579,7 @@ async function installMarketplaceSkillSet(options) {
|
|
|
5281
5579
|
"No compatible agents found. Use --agents to specify targets."
|
|
5282
5580
|
);
|
|
5283
5581
|
}
|
|
5582
|
+
const serverUrl = (options.serverUrl ?? await getServerUrlAsync().catch(() => "https://braid.cloud")).replace(TRAILING_SLASH_REGEX3, "");
|
|
5284
5583
|
const targets = [];
|
|
5285
5584
|
const installedSkills = /* @__PURE__ */ new Set();
|
|
5286
5585
|
for (const agent of targetAgents) {
|
|
@@ -5288,6 +5587,7 @@ async function installMarketplaceSkillSet(options) {
|
|
|
5288
5587
|
agent,
|
|
5289
5588
|
manifest: options.manifest,
|
|
5290
5589
|
slug: options.slug,
|
|
5590
|
+
serverUrl,
|
|
5291
5591
|
skills: resolvedSkills,
|
|
5292
5592
|
rules: rules2,
|
|
5293
5593
|
agents: agents2,
|
|
@@ -5437,7 +5737,8 @@ async function installLibraryPackAsync(options) {
|
|
|
5437
5737
|
agents: options.agentId,
|
|
5438
5738
|
global: options.scope === "global",
|
|
5439
5739
|
manifest,
|
|
5440
|
-
slug: options.slug
|
|
5740
|
+
slug: options.slug,
|
|
5741
|
+
serverUrl: options.server
|
|
5441
5742
|
});
|
|
5442
5743
|
}
|
|
5443
5744
|
|
|
@@ -5914,7 +6215,8 @@ var MIME_TYPES = {
|
|
|
5914
6215
|
};
|
|
5915
6216
|
var TRAILING_SLASHES3 = /\/+$/;
|
|
5916
6217
|
var MANAGE_AUTH_TIMEOUT_SECONDS = 300;
|
|
5917
|
-
var
|
|
6218
|
+
var SESSION_TOKEN_PREFIX4 = "brs_";
|
|
6219
|
+
var LOOPBACK_HOSTS4 = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
|
|
5918
6220
|
function getErrorStatus(error) {
|
|
5919
6221
|
if (typeof error === "object" && error !== null && "status" in error && typeof error.status === "number") {
|
|
5920
6222
|
return error.status ?? 500;
|
|
@@ -5991,7 +6293,18 @@ function getContentType(pathname) {
|
|
|
5991
6293
|
const extension = pathname.slice(pathname.lastIndexOf("."));
|
|
5992
6294
|
return MIME_TYPES[extension] ?? "application/octet-stream";
|
|
5993
6295
|
}
|
|
5994
|
-
function
|
|
6296
|
+
function resolvePersistedCliServerUrl2(serverUrl, convexSiteUrl) {
|
|
6297
|
+
try {
|
|
6298
|
+
const convexUrl = new URL(convexSiteUrl);
|
|
6299
|
+
if (LOOPBACK_HOSTS4.has(convexUrl.hostname)) {
|
|
6300
|
+
return convexSiteUrl;
|
|
6301
|
+
}
|
|
6302
|
+
} catch {
|
|
6303
|
+
return serverUrl;
|
|
6304
|
+
}
|
|
6305
|
+
return serverUrl;
|
|
6306
|
+
}
|
|
6307
|
+
function writeJson2(response, status, body) {
|
|
5995
6308
|
response.writeHead(status, {
|
|
5996
6309
|
"content-type": "application/json; charset=utf-8",
|
|
5997
6310
|
"cache-control": "no-store"
|
|
@@ -6015,7 +6328,7 @@ async function serveStaticAsset(serverResponse, assetRoot, pathname) {
|
|
|
6015
6328
|
const assetPath = resolve6(assetRoot, relativePath);
|
|
6016
6329
|
const resolvedRoot = resolve6(assetRoot);
|
|
6017
6330
|
if (!isWithinManageAssetRoot(resolvedRoot, assetPath)) {
|
|
6018
|
-
|
|
6331
|
+
writeJson2(serverResponse, 404, { error: "Not found" });
|
|
6019
6332
|
return true;
|
|
6020
6333
|
}
|
|
6021
6334
|
try {
|
|
@@ -6109,19 +6422,19 @@ async function handleManageApiRoute(request, response, dependencies) {
|
|
|
6109
6422
|
const pathname = new URL(request.url ?? "/", "http://127.0.0.1").pathname;
|
|
6110
6423
|
switch (`${method} ${pathname}`) {
|
|
6111
6424
|
case "GET /api/inventory":
|
|
6112
|
-
|
|
6425
|
+
writeJson2(response, 200, await dependencies.getInventory());
|
|
6113
6426
|
return true;
|
|
6114
6427
|
case "GET /api/library":
|
|
6115
|
-
|
|
6428
|
+
writeJson2(response, 200, await dependencies.listLibrary());
|
|
6116
6429
|
return true;
|
|
6117
6430
|
case "GET /api/auth/session":
|
|
6118
|
-
|
|
6431
|
+
writeJson2(response, 200, {
|
|
6119
6432
|
ok: true,
|
|
6120
6433
|
result: await dependencies.getAuthSession()
|
|
6121
6434
|
});
|
|
6122
6435
|
return true;
|
|
6123
6436
|
case "POST /api/auth/start":
|
|
6124
|
-
|
|
6437
|
+
writeJson2(response, 200, {
|
|
6125
6438
|
ok: true,
|
|
6126
6439
|
result: await dependencies.startAuth()
|
|
6127
6440
|
});
|
|
@@ -6135,7 +6448,7 @@ async function handleManageApiRoute(request, response, dependencies) {
|
|
|
6135
6448
|
"AUTH_REQUEST_REQUIRED"
|
|
6136
6449
|
);
|
|
6137
6450
|
}
|
|
6138
|
-
|
|
6451
|
+
writeJson2(response, 200, {
|
|
6139
6452
|
ok: true,
|
|
6140
6453
|
result: await dependencies.completeAuth({
|
|
6141
6454
|
requestId: payload.requestId
|
|
@@ -6144,14 +6457,14 @@ async function handleManageApiRoute(request, response, dependencies) {
|
|
|
6144
6457
|
return true;
|
|
6145
6458
|
}
|
|
6146
6459
|
case "POST /api/auth/sign-out":
|
|
6147
|
-
|
|
6460
|
+
writeJson2(response, 200, {
|
|
6148
6461
|
ok: true,
|
|
6149
6462
|
result: await dependencies.signOut()
|
|
6150
6463
|
});
|
|
6151
6464
|
return true;
|
|
6152
6465
|
case "POST /api/actions/install": {
|
|
6153
6466
|
const payload = await readJsonBody(request);
|
|
6154
|
-
|
|
6467
|
+
writeJson2(response, 200, {
|
|
6155
6468
|
ok: true,
|
|
6156
6469
|
result: await dependencies.installLibraryPack(payload)
|
|
6157
6470
|
});
|
|
@@ -6159,7 +6472,7 @@ async function handleManageApiRoute(request, response, dependencies) {
|
|
|
6159
6472
|
}
|
|
6160
6473
|
case "POST /api/actions/disable": {
|
|
6161
6474
|
const payload = await readJsonBody(request);
|
|
6162
|
-
|
|
6475
|
+
writeJson2(response, 200, {
|
|
6163
6476
|
ok: true,
|
|
6164
6477
|
result: await dependencies.disableManagedBundle(payload)
|
|
6165
6478
|
});
|
|
@@ -6167,7 +6480,7 @@ async function handleManageApiRoute(request, response, dependencies) {
|
|
|
6167
6480
|
}
|
|
6168
6481
|
case "POST /api/actions/enable": {
|
|
6169
6482
|
const payload = await readJsonBody(request);
|
|
6170
|
-
|
|
6483
|
+
writeJson2(response, 200, {
|
|
6171
6484
|
ok: true,
|
|
6172
6485
|
result: await dependencies.enableManagedBundle(payload)
|
|
6173
6486
|
});
|
|
@@ -6175,7 +6488,7 @@ async function handleManageApiRoute(request, response, dependencies) {
|
|
|
6175
6488
|
}
|
|
6176
6489
|
case "POST /api/actions/remove": {
|
|
6177
6490
|
const payload = await readJsonBody(request);
|
|
6178
|
-
|
|
6491
|
+
writeJson2(response, 200, {
|
|
6179
6492
|
ok: true,
|
|
6180
6493
|
result: await dependencies.removeManagedBundle(payload)
|
|
6181
6494
|
});
|
|
@@ -6197,11 +6510,11 @@ async function handleManageRequest(request, response, assetRoot, dependencies) {
|
|
|
6197
6510
|
return;
|
|
6198
6511
|
}
|
|
6199
6512
|
}
|
|
6200
|
-
|
|
6513
|
+
writeJson2(response, 404, { error: "Not found" });
|
|
6201
6514
|
} catch (error) {
|
|
6202
6515
|
const message = error instanceof Error ? error.message : String(error);
|
|
6203
6516
|
const code = getErrorCode(error);
|
|
6204
|
-
|
|
6517
|
+
writeJson2(response, getErrorStatus(error), {
|
|
6205
6518
|
...code ? { code } : {},
|
|
6206
6519
|
error: message
|
|
6207
6520
|
});
|
|
@@ -6272,6 +6585,10 @@ async function startManageServer(options = {}) {
|
|
|
6272
6585
|
deviceAuth.user_code
|
|
6273
6586
|
);
|
|
6274
6587
|
authRequests.set(requestId, {
|
|
6588
|
+
serverUrl: resolvePersistedCliServerUrl2(
|
|
6589
|
+
serverUrl,
|
|
6590
|
+
authConfig.convexSiteUrl
|
|
6591
|
+
),
|
|
6275
6592
|
convexSiteUrl: authConfig.convexSiteUrl,
|
|
6276
6593
|
deviceCode: deviceAuth.device_code,
|
|
6277
6594
|
expiresIn: deviceAuth.expires_in,
|
|
@@ -6304,7 +6621,7 @@ async function startManageServer(options = {}) {
|
|
|
6304
6621
|
);
|
|
6305
6622
|
await persistApiKeyAsync(
|
|
6306
6623
|
session.sessionToken,
|
|
6307
|
-
pendingRequest.
|
|
6624
|
+
pendingRequest.serverUrl
|
|
6308
6625
|
);
|
|
6309
6626
|
return {
|
|
6310
6627
|
authenticated: true,
|
|
@@ -6321,7 +6638,7 @@ async function startManageServer(options = {}) {
|
|
|
6321
6638
|
if (!token) {
|
|
6322
6639
|
return { authenticated: false };
|
|
6323
6640
|
}
|
|
6324
|
-
if (!token.startsWith(
|
|
6641
|
+
if (!token.startsWith(SESSION_TOKEN_PREFIX4)) {
|
|
6325
6642
|
return { authenticated: true };
|
|
6326
6643
|
}
|
|
6327
6644
|
const serverUrl = (options.server ?? config.serverUrl).replace(
|
|
@@ -6346,7 +6663,7 @@ async function startManageServer(options = {}) {
|
|
|
6346
6663
|
const signOut = options.signOut ?? (async () => {
|
|
6347
6664
|
const config = await loadMergedConfigAsync();
|
|
6348
6665
|
const token = config.token;
|
|
6349
|
-
if (token?.startsWith(
|
|
6666
|
+
if (token?.startsWith(SESSION_TOKEN_PREFIX4)) {
|
|
6350
6667
|
try {
|
|
6351
6668
|
const serverUrl = (options.server ?? config.serverUrl).replace(
|
|
6352
6669
|
TRAILING_SLASHES3,
|
|
@@ -6378,7 +6695,7 @@ async function startManageServer(options = {}) {
|
|
|
6378
6695
|
handleManageRequest(request, response, assetRoot, dependencies).catch(
|
|
6379
6696
|
(error) => {
|
|
6380
6697
|
const message = error instanceof Error ? error.message : String(error);
|
|
6381
|
-
|
|
6698
|
+
writeJson2(response, 500, { error: message });
|
|
6382
6699
|
}
|
|
6383
6700
|
);
|
|
6384
6701
|
});
|
|
@@ -6422,7 +6739,7 @@ async function manageCommand(options) {
|
|
|
6422
6739
|
const server = await startManageServer({
|
|
6423
6740
|
apiKey: options.apiKey,
|
|
6424
6741
|
port: parsePort(options.port),
|
|
6425
|
-
projectRoot:
|
|
6742
|
+
projectRoot: process11.cwd(),
|
|
6426
6743
|
server: options.server
|
|
6427
6744
|
});
|
|
6428
6745
|
if (options.open !== false) {
|
|
@@ -6432,17 +6749,17 @@ async function manageCommand(options) {
|
|
|
6432
6749
|
log.info("Press Ctrl+C to stop.");
|
|
6433
6750
|
await new Promise((resolveClose, rejectClose) => {
|
|
6434
6751
|
const shutdown = () => {
|
|
6435
|
-
|
|
6436
|
-
|
|
6752
|
+
process11.off("SIGINT", shutdown);
|
|
6753
|
+
process11.off("SIGTERM", shutdown);
|
|
6437
6754
|
server.close().then(resolveClose).catch(rejectClose);
|
|
6438
6755
|
};
|
|
6439
|
-
|
|
6440
|
-
|
|
6756
|
+
process11.once("SIGINT", shutdown);
|
|
6757
|
+
process11.once("SIGTERM", shutdown);
|
|
6441
6758
|
});
|
|
6442
6759
|
} catch (error) {
|
|
6443
6760
|
const message = error instanceof Error ? error.message : String(error);
|
|
6444
6761
|
log.error(message);
|
|
6445
|
-
|
|
6762
|
+
process11.exit(1);
|
|
6446
6763
|
}
|
|
6447
6764
|
}
|
|
6448
6765
|
|
|
@@ -6450,7 +6767,7 @@ async function manageCommand(options) {
|
|
|
6450
6767
|
init_esm_shims();
|
|
6451
6768
|
import { rm as rm6 } from "fs/promises";
|
|
6452
6769
|
import { join as join13, resolve as resolve7 } from "path";
|
|
6453
|
-
import
|
|
6770
|
+
import process12 from "process";
|
|
6454
6771
|
init_tui();
|
|
6455
6772
|
async function selectInstallScope(options) {
|
|
6456
6773
|
if (options.global != null) {
|
|
@@ -6469,7 +6786,7 @@ async function selectInstallScope(options) {
|
|
|
6469
6786
|
});
|
|
6470
6787
|
if (isCancel(result)) {
|
|
6471
6788
|
cancel("Install cancelled.");
|
|
6472
|
-
|
|
6789
|
+
process12.exit(0);
|
|
6473
6790
|
}
|
|
6474
6791
|
return result;
|
|
6475
6792
|
}
|
|
@@ -6504,7 +6821,7 @@ async function selectInstallAgents(options, global) {
|
|
|
6504
6821
|
});
|
|
6505
6822
|
if (isCancel(selected)) {
|
|
6506
6823
|
cancel("Install cancelled.");
|
|
6507
|
-
|
|
6824
|
+
process12.exit(0);
|
|
6508
6825
|
}
|
|
6509
6826
|
return selected;
|
|
6510
6827
|
}
|
|
@@ -6521,7 +6838,7 @@ async function confirmHooksOptIn(hookCount, options) {
|
|
|
6521
6838
|
});
|
|
6522
6839
|
if (isCancel(result)) {
|
|
6523
6840
|
cancel("Install cancelled.");
|
|
6524
|
-
|
|
6841
|
+
process12.exit(0);
|
|
6525
6842
|
}
|
|
6526
6843
|
return result;
|
|
6527
6844
|
}
|
|
@@ -6546,7 +6863,7 @@ async function marketplaceLibraryCommand(options) {
|
|
|
6546
6863
|
log.error(
|
|
6547
6864
|
error instanceof Error ? error.message : "Failed to fetch library"
|
|
6548
6865
|
);
|
|
6549
|
-
|
|
6866
|
+
process12.exit(1);
|
|
6550
6867
|
}
|
|
6551
6868
|
}
|
|
6552
6869
|
async function resolveAndInstallPack(slug, options, overrides) {
|
|
@@ -6569,7 +6886,8 @@ async function resolveAndInstallPack(slug, options, overrides) {
|
|
|
6569
6886
|
manifest,
|
|
6570
6887
|
agents: agents2,
|
|
6571
6888
|
global,
|
|
6572
|
-
allowHooks: options.allowHooks
|
|
6889
|
+
allowHooks: options.allowHooks,
|
|
6890
|
+
serverUrl: options.server
|
|
6573
6891
|
});
|
|
6574
6892
|
}
|
|
6575
6893
|
async function marketplaceInstallCommand(slug, options) {
|
|
@@ -6580,7 +6898,7 @@ async function marketplaceInstallCommand(slug, options) {
|
|
|
6580
6898
|
log.error(
|
|
6581
6899
|
error instanceof Error ? error.message : "Failed to install pack"
|
|
6582
6900
|
);
|
|
6583
|
-
|
|
6901
|
+
process12.exit(1);
|
|
6584
6902
|
}
|
|
6585
6903
|
}
|
|
6586
6904
|
function addSkillToPack(packMap, slug, versionId, skillName, agent, installPath) {
|
|
@@ -6634,7 +6952,7 @@ async function marketplaceUpdateCommand(slug, options) {
|
|
|
6634
6952
|
const toUpdate = slug ? installed.filter((p) => p.slug === slug) : installed;
|
|
6635
6953
|
if (toUpdate.length === 0) {
|
|
6636
6954
|
log.error(`Pack "${slug}" is not installed.`);
|
|
6637
|
-
|
|
6955
|
+
process12.exit(1);
|
|
6638
6956
|
}
|
|
6639
6957
|
let updated = 0;
|
|
6640
6958
|
for (const pack of toUpdate) {
|
|
@@ -6654,7 +6972,7 @@ async function marketplaceUpdateCommand(slug, options) {
|
|
|
6654
6972
|
log.error(
|
|
6655
6973
|
error instanceof Error ? error.message : "Failed to update packs"
|
|
6656
6974
|
);
|
|
6657
|
-
|
|
6975
|
+
process12.exit(1);
|
|
6658
6976
|
}
|
|
6659
6977
|
}
|
|
6660
6978
|
async function selectPacksToRemove(installed, slug, options) {
|
|
@@ -6680,7 +6998,7 @@ async function selectPacksToRemove(installed, slug, options) {
|
|
|
6680
6998
|
});
|
|
6681
6999
|
if (isCancel(selected)) {
|
|
6682
7000
|
cancel("Remove cancelled.");
|
|
6683
|
-
|
|
7001
|
+
process12.exit(0);
|
|
6684
7002
|
}
|
|
6685
7003
|
return selected;
|
|
6686
7004
|
}
|
|
@@ -6718,7 +7036,7 @@ async function marketplaceRemoveCommand(slug, options) {
|
|
|
6718
7036
|
});
|
|
6719
7037
|
if (isCancel(confirmed) || !confirmed) {
|
|
6720
7038
|
cancel("Remove cancelled.");
|
|
6721
|
-
|
|
7039
|
+
process12.exit(0);
|
|
6722
7040
|
}
|
|
6723
7041
|
}
|
|
6724
7042
|
for (const pack of toRemove) {
|
|
@@ -6729,7 +7047,7 @@ async function marketplaceRemoveCommand(slug, options) {
|
|
|
6729
7047
|
log.error(
|
|
6730
7048
|
error instanceof Error ? error.message : "Failed to remove packs"
|
|
6731
7049
|
);
|
|
6732
|
-
|
|
7050
|
+
process12.exit(1);
|
|
6733
7051
|
}
|
|
6734
7052
|
}
|
|
6735
7053
|
|
|
@@ -6737,19 +7055,6 @@ async function marketplaceRemoveCommand(slug, options) {
|
|
|
6737
7055
|
init_esm_shims();
|
|
6738
7056
|
init_api();
|
|
6739
7057
|
init_tui();
|
|
6740
|
-
import process12 from "process";
|
|
6741
|
-
var writeJson4 = (value) => {
|
|
6742
|
-
process12.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
6743
|
-
`);
|
|
6744
|
-
};
|
|
6745
|
-
var exitWithError3 = (error) => {
|
|
6746
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
6747
|
-
log.error(message);
|
|
6748
|
-
process12.exit(1);
|
|
6749
|
-
};
|
|
6750
|
-
var fail2 = (message) => {
|
|
6751
|
-
throw new Error(message);
|
|
6752
|
-
};
|
|
6753
7058
|
var parseContext = (contextJson) => {
|
|
6754
7059
|
if (!contextJson) {
|
|
6755
7060
|
return void 0;
|
|
@@ -6770,7 +7075,7 @@ var run2 = async (command, args, options) => {
|
|
|
6770
7075
|
apiOptions
|
|
6771
7076
|
);
|
|
6772
7077
|
if (options.json) {
|
|
6773
|
-
|
|
7078
|
+
writeJson(result);
|
|
6774
7079
|
return;
|
|
6775
7080
|
}
|
|
6776
7081
|
log.success(`profiles ${command} completed`);
|
|
@@ -6779,34 +7084,34 @@ async function profilesListCommand(options) {
|
|
|
6779
7084
|
try {
|
|
6780
7085
|
await run2("list", {}, options);
|
|
6781
7086
|
} catch (error) {
|
|
6782
|
-
|
|
7087
|
+
exitCommandError(error, options);
|
|
6783
7088
|
}
|
|
6784
7089
|
}
|
|
6785
7090
|
async function profilesGetCommand(options) {
|
|
6786
7091
|
try {
|
|
6787
7092
|
if (!(options.id || options.name)) {
|
|
6788
|
-
|
|
7093
|
+
fail("profiles get requires --id or --name");
|
|
6789
7094
|
}
|
|
6790
7095
|
await run2("get", { id: options.id, name: options.name }, options);
|
|
6791
7096
|
} catch (error) {
|
|
6792
|
-
|
|
7097
|
+
exitCommandError(error, options);
|
|
6793
7098
|
}
|
|
6794
7099
|
}
|
|
6795
7100
|
async function profilesCreateCommand(options) {
|
|
6796
7101
|
try {
|
|
6797
|
-
const name = options.name ??
|
|
7102
|
+
const name = options.name ?? fail("profiles create requires --name");
|
|
6798
7103
|
await run2(
|
|
6799
7104
|
"create",
|
|
6800
7105
|
{ name, context: parseContext(options.contextJson) },
|
|
6801
7106
|
options
|
|
6802
7107
|
);
|
|
6803
7108
|
} catch (error) {
|
|
6804
|
-
|
|
7109
|
+
exitCommandError(error, options);
|
|
6805
7110
|
}
|
|
6806
7111
|
}
|
|
6807
7112
|
async function profilesUpdateCommand(options) {
|
|
6808
7113
|
try {
|
|
6809
|
-
const id = options.id ??
|
|
7114
|
+
const id = options.id ?? fail("profiles update requires --id");
|
|
6810
7115
|
await run2(
|
|
6811
7116
|
"update",
|
|
6812
7117
|
{
|
|
@@ -6817,26 +7122,26 @@ async function profilesUpdateCommand(options) {
|
|
|
6817
7122
|
options
|
|
6818
7123
|
);
|
|
6819
7124
|
} catch (error) {
|
|
6820
|
-
|
|
7125
|
+
exitCommandError(error, options);
|
|
6821
7126
|
}
|
|
6822
7127
|
}
|
|
6823
7128
|
async function profilesRemoveCommand(options) {
|
|
6824
7129
|
try {
|
|
6825
|
-
const id = options.id ??
|
|
7130
|
+
const id = options.id ?? fail("profiles remove requires --id");
|
|
6826
7131
|
if (!options.yes) {
|
|
6827
|
-
|
|
7132
|
+
fail("profiles remove requires --yes");
|
|
6828
7133
|
}
|
|
6829
7134
|
await run2("remove", { id, yes: true }, options);
|
|
6830
7135
|
} catch (error) {
|
|
6831
|
-
|
|
7136
|
+
exitCommandError(error, options);
|
|
6832
7137
|
}
|
|
6833
7138
|
}
|
|
6834
7139
|
async function profilesSetDefaultCommand(options) {
|
|
6835
7140
|
try {
|
|
6836
|
-
const id = options.id ??
|
|
7141
|
+
const id = options.id ?? fail("profiles set-default requires --id");
|
|
6837
7142
|
await run2("set-default", { id }, options);
|
|
6838
7143
|
} catch (error) {
|
|
6839
|
-
|
|
7144
|
+
exitCommandError(error, options);
|
|
6840
7145
|
}
|
|
6841
7146
|
}
|
|
6842
7147
|
|
|
@@ -6844,14 +7149,6 @@ async function profilesSetDefaultCommand(options) {
|
|
|
6844
7149
|
init_esm_shims();
|
|
6845
7150
|
init_api();
|
|
6846
7151
|
init_tui();
|
|
6847
|
-
import process13 from "process";
|
|
6848
|
-
var writeJson5 = (value) => {
|
|
6849
|
-
process13.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
6850
|
-
`);
|
|
6851
|
-
};
|
|
6852
|
-
var fail3 = (message) => {
|
|
6853
|
-
throw new Error(message);
|
|
6854
|
-
};
|
|
6855
7152
|
var run3 = async (command, args, options) => {
|
|
6856
7153
|
const apiOptions = {
|
|
6857
7154
|
...options.server ? { serverUrl: options.server } : {},
|
|
@@ -6866,39 +7163,34 @@ var run3 = async (command, args, options) => {
|
|
|
6866
7163
|
apiOptions
|
|
6867
7164
|
);
|
|
6868
7165
|
if (options.json) {
|
|
6869
|
-
|
|
7166
|
+
writeJson(result);
|
|
6870
7167
|
return;
|
|
6871
7168
|
}
|
|
6872
7169
|
log.success(`projects ${command} completed`);
|
|
6873
7170
|
};
|
|
6874
|
-
var exitWithError4 = (error) => {
|
|
6875
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
6876
|
-
log.error(message);
|
|
6877
|
-
process13.exit(1);
|
|
6878
|
-
};
|
|
6879
7171
|
async function projectsGetCommand(options) {
|
|
6880
7172
|
try {
|
|
6881
|
-
const id = options.id ??
|
|
7173
|
+
const id = options.id ?? fail("projects get requires --id");
|
|
6882
7174
|
await run3("get", { id }, options);
|
|
6883
7175
|
} catch (error) {
|
|
6884
|
-
|
|
7176
|
+
exitCommandError(error, options);
|
|
6885
7177
|
}
|
|
6886
7178
|
}
|
|
6887
7179
|
async function projectsCreateCommand(options) {
|
|
6888
7180
|
try {
|
|
6889
|
-
const name = options.name ??
|
|
7181
|
+
const name = options.name ?? fail("projects create requires --name");
|
|
6890
7182
|
await run3(
|
|
6891
7183
|
"create",
|
|
6892
7184
|
{ name, description: options.description, orgId: options.orgId },
|
|
6893
7185
|
options
|
|
6894
7186
|
);
|
|
6895
7187
|
} catch (error) {
|
|
6896
|
-
|
|
7188
|
+
exitCommandError(error, options);
|
|
6897
7189
|
}
|
|
6898
7190
|
}
|
|
6899
7191
|
async function projectsUpdateCommand(options) {
|
|
6900
7192
|
try {
|
|
6901
|
-
const id = options.id ??
|
|
7193
|
+
const id = options.id ?? fail("projects update requires --id");
|
|
6902
7194
|
await run3(
|
|
6903
7195
|
"update",
|
|
6904
7196
|
{
|
|
@@ -6909,18 +7201,18 @@ async function projectsUpdateCommand(options) {
|
|
|
6909
7201
|
options
|
|
6910
7202
|
);
|
|
6911
7203
|
} catch (error) {
|
|
6912
|
-
|
|
7204
|
+
exitCommandError(error, options);
|
|
6913
7205
|
}
|
|
6914
7206
|
}
|
|
6915
7207
|
async function projectsRemoveCommand(options) {
|
|
6916
7208
|
try {
|
|
6917
|
-
const id = options.id ??
|
|
7209
|
+
const id = options.id ?? fail("projects remove requires --id");
|
|
6918
7210
|
if (!options.yes) {
|
|
6919
|
-
|
|
7211
|
+
fail("projects remove requires --yes");
|
|
6920
7212
|
}
|
|
6921
7213
|
await run3("remove", { id, yes: true }, options);
|
|
6922
7214
|
} catch (error) {
|
|
6923
|
-
|
|
7215
|
+
exitCommandError(error, options);
|
|
6924
7216
|
}
|
|
6925
7217
|
}
|
|
6926
7218
|
|
|
@@ -6928,11 +7220,6 @@ async function projectsRemoveCommand(options) {
|
|
|
6928
7220
|
init_esm_shims();
|
|
6929
7221
|
init_api();
|
|
6930
7222
|
init_tui();
|
|
6931
|
-
import process14 from "process";
|
|
6932
|
-
var writeJson6 = (value) => {
|
|
6933
|
-
process14.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
6934
|
-
`);
|
|
6935
|
-
};
|
|
6936
7223
|
var parseCsv3 = (input) => {
|
|
6937
7224
|
if (!input) {
|
|
6938
7225
|
return void 0;
|
|
@@ -6940,14 +7227,6 @@ var parseCsv3 = (input) => {
|
|
|
6940
7227
|
const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
6941
7228
|
return values.length > 0 ? values : void 0;
|
|
6942
7229
|
};
|
|
6943
|
-
var exitWithError5 = (error) => {
|
|
6944
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
6945
|
-
log.error(message);
|
|
6946
|
-
process14.exit(1);
|
|
6947
|
-
};
|
|
6948
|
-
var fail4 = (message) => {
|
|
6949
|
-
throw new Error(message);
|
|
6950
|
-
};
|
|
6951
7230
|
var run4 = async (command, args, options) => {
|
|
6952
7231
|
const apiOptions = {
|
|
6953
7232
|
...options.server ? { serverUrl: options.server } : {},
|
|
@@ -6962,69 +7241,69 @@ var run4 = async (command, args, options) => {
|
|
|
6962
7241
|
apiOptions
|
|
6963
7242
|
);
|
|
6964
7243
|
if (options.json) {
|
|
6965
|
-
|
|
7244
|
+
writeJson(result);
|
|
6966
7245
|
return;
|
|
6967
7246
|
}
|
|
6968
7247
|
log.success(`references ${command} completed`);
|
|
6969
7248
|
};
|
|
6970
7249
|
async function referencesListCommand(options) {
|
|
6971
7250
|
try {
|
|
6972
|
-
const ruleId = options.ruleId ??
|
|
7251
|
+
const ruleId = options.ruleId ?? fail("references list requires --rule-id");
|
|
6973
7252
|
await run4("list", { ruleId }, options);
|
|
6974
7253
|
} catch (error) {
|
|
6975
|
-
|
|
7254
|
+
exitCommandError(error, options);
|
|
6976
7255
|
}
|
|
6977
7256
|
}
|
|
6978
7257
|
async function referencesGetCommand(options) {
|
|
6979
7258
|
try {
|
|
6980
|
-
const id = options.id ??
|
|
7259
|
+
const id = options.id ?? fail("references get requires --id");
|
|
6981
7260
|
await run4("get", { id }, options);
|
|
6982
7261
|
} catch (error) {
|
|
6983
|
-
|
|
7262
|
+
exitCommandError(error, options);
|
|
6984
7263
|
}
|
|
6985
7264
|
}
|
|
6986
7265
|
async function referencesCreateCommand(options) {
|
|
6987
7266
|
try {
|
|
6988
|
-
const ruleId = options.ruleId ??
|
|
6989
|
-
const file = options.file ??
|
|
7267
|
+
const ruleId = options.ruleId ?? fail("references create requires --rule-id");
|
|
7268
|
+
const file = options.file ?? fail("references create requires --file");
|
|
6990
7269
|
await run4("create", { ruleId, file }, options);
|
|
6991
7270
|
} catch (error) {
|
|
6992
|
-
|
|
7271
|
+
exitCommandError(error, options);
|
|
6993
7272
|
}
|
|
6994
7273
|
}
|
|
6995
7274
|
async function referencesUpdateCommand(options) {
|
|
6996
7275
|
try {
|
|
6997
|
-
const id = options.id ??
|
|
7276
|
+
const id = options.id ?? fail("references update requires --id");
|
|
6998
7277
|
await run4(
|
|
6999
7278
|
"update",
|
|
7000
7279
|
{ id, label: options.label, replaceFile: options.replaceFile },
|
|
7001
7280
|
options
|
|
7002
7281
|
);
|
|
7003
7282
|
} catch (error) {
|
|
7004
|
-
|
|
7283
|
+
exitCommandError(error, options);
|
|
7005
7284
|
}
|
|
7006
7285
|
}
|
|
7007
7286
|
async function referencesRemoveCommand(options) {
|
|
7008
7287
|
try {
|
|
7009
|
-
const id = options.id ??
|
|
7288
|
+
const id = options.id ?? fail("references remove requires --id");
|
|
7010
7289
|
if (!options.yes) {
|
|
7011
|
-
|
|
7290
|
+
fail("references remove requires --yes");
|
|
7012
7291
|
}
|
|
7013
7292
|
await run4("remove", { id, yes: true }, options);
|
|
7014
7293
|
} catch (error) {
|
|
7015
|
-
|
|
7294
|
+
exitCommandError(error, options);
|
|
7016
7295
|
}
|
|
7017
7296
|
}
|
|
7018
7297
|
async function referencesReorderCommand(options) {
|
|
7019
7298
|
try {
|
|
7020
|
-
const ruleId = options.ruleId ??
|
|
7299
|
+
const ruleId = options.ruleId ?? fail("references reorder requires --rule-id");
|
|
7021
7300
|
const orderedIds = parseCsv3(options.orderedIds);
|
|
7022
7301
|
if (!orderedIds || orderedIds.length === 0) {
|
|
7023
|
-
|
|
7302
|
+
fail("references reorder requires --ordered-ids");
|
|
7024
7303
|
}
|
|
7025
7304
|
await run4("reorder", { ruleId, orderedIds }, options);
|
|
7026
7305
|
} catch (error) {
|
|
7027
|
-
|
|
7306
|
+
exitCommandError(error, options);
|
|
7028
7307
|
}
|
|
7029
7308
|
}
|
|
7030
7309
|
|
|
@@ -7032,7 +7311,7 @@ async function referencesReorderCommand(options) {
|
|
|
7032
7311
|
init_esm_shims();
|
|
7033
7312
|
import { rm as rm7 } from "fs/promises";
|
|
7034
7313
|
import { join as join14, resolve as resolve8 } from "path";
|
|
7035
|
-
import
|
|
7314
|
+
import process13 from "process";
|
|
7036
7315
|
init_tui();
|
|
7037
7316
|
async function collectInstalledSkills(detectedAgents, options) {
|
|
7038
7317
|
const skillsToRemove = [];
|
|
@@ -7065,7 +7344,7 @@ async function selectSkillsToRemove(skillsToRemove, options) {
|
|
|
7065
7344
|
if (selected.length === 0) {
|
|
7066
7345
|
log.error(`Skill '${options.skill}' not found.`);
|
|
7067
7346
|
log.info("Run 'braid list' to see installed skills.");
|
|
7068
|
-
|
|
7347
|
+
process13.exit(1);
|
|
7069
7348
|
}
|
|
7070
7349
|
return selected;
|
|
7071
7350
|
}
|
|
@@ -7084,7 +7363,7 @@ async function selectSkillsToRemove(skillsToRemove, options) {
|
|
|
7084
7363
|
});
|
|
7085
7364
|
if (isCancel(result)) {
|
|
7086
7365
|
cancel("Remove cancelled.");
|
|
7087
|
-
|
|
7366
|
+
process13.exit(0);
|
|
7088
7367
|
}
|
|
7089
7368
|
return result;
|
|
7090
7369
|
}
|
|
@@ -7098,7 +7377,7 @@ async function confirmRemoval(selectedCount, options) {
|
|
|
7098
7377
|
});
|
|
7099
7378
|
if (isCancel(confirmed) || !confirmed) {
|
|
7100
7379
|
cancel("Remove cancelled.");
|
|
7101
|
-
|
|
7380
|
+
process13.exit(0);
|
|
7102
7381
|
}
|
|
7103
7382
|
}
|
|
7104
7383
|
async function removeSkill(skill, removeSpinner) {
|
|
@@ -7162,7 +7441,7 @@ async function removeCommand(options) {
|
|
|
7162
7441
|
removeSpinner.stop("Remove failed");
|
|
7163
7442
|
const message = error instanceof Error ? error.message : String(error);
|
|
7164
7443
|
log.error(message);
|
|
7165
|
-
|
|
7444
|
+
process13.exit(1);
|
|
7166
7445
|
}
|
|
7167
7446
|
}
|
|
7168
7447
|
|
|
@@ -7221,6 +7500,7 @@ async function retractCommand(source, _options) {
|
|
|
7221
7500
|
// src/commands/rollback.ts
|
|
7222
7501
|
init_esm_shims();
|
|
7223
7502
|
init_api();
|
|
7503
|
+
init_config();
|
|
7224
7504
|
init_lockfile();
|
|
7225
7505
|
init_tui();
|
|
7226
7506
|
var PUBLIC_SOURCE_REGEX2 = /^@([a-z0-9-]+)\/([a-z0-9-]+)$/;
|
|
@@ -7253,6 +7533,8 @@ async function findPreviousActiveVersion(args) {
|
|
|
7253
7533
|
return null;
|
|
7254
7534
|
}
|
|
7255
7535
|
async function rollbackCommand(source, options) {
|
|
7536
|
+
const config = await loadMergedConfigAsync();
|
|
7537
|
+
const serverUrl = options.server ?? config.serverUrl;
|
|
7256
7538
|
intro(`Rolling back ${source}`);
|
|
7257
7539
|
const rollbackSpinner = spinner();
|
|
7258
7540
|
rollbackSpinner.start("Reading lockfile...");
|
|
@@ -7317,7 +7599,7 @@ async function rollbackCommand(source, options) {
|
|
|
7317
7599
|
slug: publicSource.slug,
|
|
7318
7600
|
currentVersion: parsed.version,
|
|
7319
7601
|
ruleIds: currentValue.ruleIds,
|
|
7320
|
-
server:
|
|
7602
|
+
server: serverUrl
|
|
7321
7603
|
});
|
|
7322
7604
|
if (!result) {
|
|
7323
7605
|
rollbackSpinner.stop("No active version found");
|
|
@@ -7360,7 +7642,6 @@ async function rollbackCommand(source, options) {
|
|
|
7360
7642
|
init_esm_shims();
|
|
7361
7643
|
init_api();
|
|
7362
7644
|
init_tui();
|
|
7363
|
-
import process16 from "process";
|
|
7364
7645
|
var parseCsv4 = (input) => {
|
|
7365
7646
|
if (!input) {
|
|
7366
7647
|
return void 0;
|
|
@@ -7368,18 +7649,6 @@ var parseCsv4 = (input) => {
|
|
|
7368
7649
|
const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
7369
7650
|
return values.length > 0 ? values : void 0;
|
|
7370
7651
|
};
|
|
7371
|
-
var writeJson7 = (value) => {
|
|
7372
|
-
process16.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
7373
|
-
`);
|
|
7374
|
-
};
|
|
7375
|
-
var exitWithError6 = (error) => {
|
|
7376
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
7377
|
-
log.error(message);
|
|
7378
|
-
process16.exit(1);
|
|
7379
|
-
};
|
|
7380
|
-
var fail5 = (message) => {
|
|
7381
|
-
throw new Error(message);
|
|
7382
|
-
};
|
|
7383
7652
|
var run5 = async (command, args, options) => {
|
|
7384
7653
|
const apiOptions = {
|
|
7385
7654
|
...options.server ? { serverUrl: options.server } : {},
|
|
@@ -7394,23 +7663,23 @@ var run5 = async (command, args, options) => {
|
|
|
7394
7663
|
apiOptions
|
|
7395
7664
|
);
|
|
7396
7665
|
if (options.json) {
|
|
7397
|
-
|
|
7666
|
+
writeJson(result);
|
|
7398
7667
|
return;
|
|
7399
7668
|
}
|
|
7400
7669
|
log.success(`rules ${command} completed`);
|
|
7401
7670
|
};
|
|
7402
7671
|
async function rulesGetCommand(options) {
|
|
7403
7672
|
try {
|
|
7404
|
-
const id = options.id ??
|
|
7673
|
+
const id = options.id ?? fail("rules get requires --id");
|
|
7405
7674
|
await run5("get", { id }, options);
|
|
7406
7675
|
} catch (error) {
|
|
7407
|
-
|
|
7676
|
+
exitCommandError(error, options);
|
|
7408
7677
|
}
|
|
7409
7678
|
}
|
|
7410
7679
|
async function rulesCreateCommand(options) {
|
|
7411
7680
|
try {
|
|
7412
|
-
const title = options.title ??
|
|
7413
|
-
const content = options.content ??
|
|
7681
|
+
const title = options.title ?? fail("rules create requires --title");
|
|
7682
|
+
const content = options.content ?? fail("rules create requires --content");
|
|
7414
7683
|
await run5(
|
|
7415
7684
|
"create",
|
|
7416
7685
|
{
|
|
@@ -7423,12 +7692,12 @@ async function rulesCreateCommand(options) {
|
|
|
7423
7692
|
options
|
|
7424
7693
|
);
|
|
7425
7694
|
} catch (error) {
|
|
7426
|
-
|
|
7695
|
+
exitCommandError(error, options);
|
|
7427
7696
|
}
|
|
7428
7697
|
}
|
|
7429
7698
|
async function rulesUpdateCommand(options) {
|
|
7430
7699
|
try {
|
|
7431
|
-
const id = options.id ??
|
|
7700
|
+
const id = options.id ?? fail("rules update requires --id");
|
|
7432
7701
|
await run5(
|
|
7433
7702
|
"update",
|
|
7434
7703
|
{
|
|
@@ -7441,120 +7710,120 @@ async function rulesUpdateCommand(options) {
|
|
|
7441
7710
|
options
|
|
7442
7711
|
);
|
|
7443
7712
|
} catch (error) {
|
|
7444
|
-
|
|
7713
|
+
exitCommandError(error, options);
|
|
7445
7714
|
}
|
|
7446
7715
|
}
|
|
7447
7716
|
async function rulesRemoveCommand(options) {
|
|
7448
7717
|
try {
|
|
7449
|
-
const id = options.id ??
|
|
7718
|
+
const id = options.id ?? fail("rules remove requires --id");
|
|
7450
7719
|
if (!options.yes) {
|
|
7451
|
-
|
|
7720
|
+
fail("rules remove requires --yes");
|
|
7452
7721
|
}
|
|
7453
7722
|
await run5("remove", { id, yes: true }, options);
|
|
7454
7723
|
} catch (error) {
|
|
7455
|
-
|
|
7724
|
+
exitCommandError(error, options);
|
|
7456
7725
|
}
|
|
7457
7726
|
}
|
|
7458
7727
|
async function rulesEnableCommand(options) {
|
|
7459
7728
|
try {
|
|
7460
|
-
const id = options.id ??
|
|
7729
|
+
const id = options.id ?? fail("rules enable requires --id");
|
|
7461
7730
|
await run5("enable", { id }, options);
|
|
7462
7731
|
} catch (error) {
|
|
7463
|
-
|
|
7732
|
+
exitCommandError(error, options);
|
|
7464
7733
|
}
|
|
7465
7734
|
}
|
|
7466
7735
|
async function rulesDisableCommand(options) {
|
|
7467
7736
|
try {
|
|
7468
|
-
const id = options.id ??
|
|
7737
|
+
const id = options.id ?? fail("rules disable requires --id");
|
|
7469
7738
|
await run5("disable", { id }, options);
|
|
7470
7739
|
} catch (error) {
|
|
7471
|
-
|
|
7740
|
+
exitCommandError(error, options);
|
|
7472
7741
|
}
|
|
7473
7742
|
}
|
|
7474
7743
|
async function rulesMoveCommand(options) {
|
|
7475
7744
|
try {
|
|
7476
|
-
const id = options.id ??
|
|
7477
|
-
const projectId = options.projectId ??
|
|
7745
|
+
const id = options.id ?? fail("rules move requires --id");
|
|
7746
|
+
const projectId = options.projectId ?? fail("rules move requires --project-id");
|
|
7478
7747
|
await run5("move", { id, projectId }, options);
|
|
7479
7748
|
} catch (error) {
|
|
7480
|
-
|
|
7749
|
+
exitCommandError(error, options);
|
|
7481
7750
|
}
|
|
7482
7751
|
}
|
|
7483
7752
|
async function rulesDuplicateCommand(options) {
|
|
7484
7753
|
try {
|
|
7485
|
-
const id = options.id ??
|
|
7754
|
+
const id = options.id ?? fail("rules duplicate requires --id");
|
|
7486
7755
|
await run5(
|
|
7487
7756
|
"duplicate",
|
|
7488
7757
|
{ id, targetProjectId: options.targetProjectId },
|
|
7489
7758
|
options
|
|
7490
7759
|
);
|
|
7491
7760
|
} catch (error) {
|
|
7492
|
-
|
|
7761
|
+
exitCommandError(error, options);
|
|
7493
7762
|
}
|
|
7494
7763
|
}
|
|
7495
7764
|
async function rulesForkCommand(options) {
|
|
7496
7765
|
try {
|
|
7497
|
-
const id = options.id ??
|
|
7766
|
+
const id = options.id ?? fail("rules fork requires --id");
|
|
7498
7767
|
await run5(
|
|
7499
7768
|
"fork",
|
|
7500
7769
|
{ id, targetProjectId: options.targetProjectId },
|
|
7501
7770
|
options
|
|
7502
7771
|
);
|
|
7503
7772
|
} catch (error) {
|
|
7504
|
-
|
|
7773
|
+
exitCommandError(error, options);
|
|
7505
7774
|
}
|
|
7506
7775
|
}
|
|
7507
7776
|
async function rulesSyncStatusCommand(options) {
|
|
7508
7777
|
try {
|
|
7509
7778
|
await run5("sync-status", { id: options.id }, options);
|
|
7510
7779
|
} catch (error) {
|
|
7511
|
-
|
|
7780
|
+
exitCommandError(error, options);
|
|
7512
7781
|
}
|
|
7513
7782
|
}
|
|
7514
7783
|
async function rulesSyncHistoryCommand(options) {
|
|
7515
7784
|
try {
|
|
7516
|
-
const id = options.id ??
|
|
7785
|
+
const id = options.id ?? fail("rules sync-history requires --id");
|
|
7517
7786
|
await run5("sync-history", { id }, options);
|
|
7518
7787
|
} catch (error) {
|
|
7519
|
-
|
|
7788
|
+
exitCommandError(error, options);
|
|
7520
7789
|
}
|
|
7521
7790
|
}
|
|
7522
7791
|
async function rulesSyncEnableCommand(options) {
|
|
7523
7792
|
try {
|
|
7524
|
-
const id = options.id ??
|
|
7793
|
+
const id = options.id ?? fail("rules sync-enable requires --id");
|
|
7525
7794
|
await run5("sync-enable", { id }, options);
|
|
7526
7795
|
} catch (error) {
|
|
7527
|
-
|
|
7796
|
+
exitCommandError(error, options);
|
|
7528
7797
|
}
|
|
7529
7798
|
}
|
|
7530
7799
|
async function rulesSyncDisableCommand(options) {
|
|
7531
7800
|
try {
|
|
7532
|
-
const id = options.id ??
|
|
7801
|
+
const id = options.id ?? fail("rules sync-disable requires --id");
|
|
7533
7802
|
await run5("sync-disable", { id }, options);
|
|
7534
7803
|
} catch (error) {
|
|
7535
|
-
|
|
7804
|
+
exitCommandError(error, options);
|
|
7536
7805
|
}
|
|
7537
7806
|
}
|
|
7538
7807
|
async function rulesSyncCheckCommand(options) {
|
|
7539
7808
|
try {
|
|
7540
|
-
const id = options.id ??
|
|
7809
|
+
const id = options.id ?? fail("rules sync-check requires --id");
|
|
7541
7810
|
await run5("sync-check", { id }, options);
|
|
7542
7811
|
} catch (error) {
|
|
7543
|
-
|
|
7812
|
+
exitCommandError(error, options);
|
|
7544
7813
|
}
|
|
7545
7814
|
}
|
|
7546
7815
|
async function rulesSyncNowCommand(options) {
|
|
7547
7816
|
try {
|
|
7548
|
-
const id = options.id ??
|
|
7817
|
+
const id = options.id ?? fail("rules sync-now requires --id");
|
|
7549
7818
|
await run5("sync-now", { id }, options);
|
|
7550
7819
|
} catch (error) {
|
|
7551
|
-
|
|
7820
|
+
exitCommandError(error, options);
|
|
7552
7821
|
}
|
|
7553
7822
|
}
|
|
7554
7823
|
|
|
7555
7824
|
// src/commands/scaffold.ts
|
|
7556
7825
|
init_esm_shims();
|
|
7557
|
-
import
|
|
7826
|
+
import process14 from "process";
|
|
7558
7827
|
|
|
7559
7828
|
// src/lib/scaffold.ts
|
|
7560
7829
|
init_esm_shims();
|
|
@@ -8514,11 +8783,11 @@ var normalizeReferenceList = (referenceLabel, availableNamesLabel, values, avail
|
|
|
8514
8783
|
};
|
|
8515
8784
|
var exitCancelled2 = () => {
|
|
8516
8785
|
cancel("Scaffold cancelled.");
|
|
8517
|
-
|
|
8786
|
+
process14.exit(0);
|
|
8518
8787
|
};
|
|
8519
|
-
var
|
|
8788
|
+
var exitWithError = (message) => {
|
|
8520
8789
|
log.error(message);
|
|
8521
|
-
|
|
8790
|
+
process14.exit(1);
|
|
8522
8791
|
};
|
|
8523
8792
|
var requirePromptValue = (value) => {
|
|
8524
8793
|
if (isCancel(value)) {
|
|
@@ -8531,7 +8800,7 @@ var resolveType = async (options) => {
|
|
|
8531
8800
|
return options.type;
|
|
8532
8801
|
}
|
|
8533
8802
|
if (options.yes) {
|
|
8534
|
-
return
|
|
8803
|
+
return exitWithError("--type is required when using --yes");
|
|
8535
8804
|
}
|
|
8536
8805
|
const selected = requirePromptValue(
|
|
8537
8806
|
await select({
|
|
@@ -8561,7 +8830,7 @@ var resolveName = async (options) => {
|
|
|
8561
8830
|
return options.name.trim();
|
|
8562
8831
|
}
|
|
8563
8832
|
if (options.yes) {
|
|
8564
|
-
return
|
|
8833
|
+
return exitWithError("--name is required when using --yes");
|
|
8565
8834
|
}
|
|
8566
8835
|
const value = requirePromptValue(
|
|
8567
8836
|
await text({
|
|
@@ -8647,7 +8916,7 @@ var resolveOptionalReference = async (label, flagValue, options, availableNames)
|
|
|
8647
8916
|
return selected || void 0;
|
|
8648
8917
|
};
|
|
8649
8918
|
var buildScaffoldInput = async (options) => {
|
|
8650
|
-
const context = await inspectScaffoldDirectory(
|
|
8919
|
+
const context = await inspectScaffoldDirectory(process14.cwd());
|
|
8651
8920
|
const availableSkillNames = context.manifest.skills.map(
|
|
8652
8921
|
(entry) => entry.name
|
|
8653
8922
|
);
|
|
@@ -8701,7 +8970,7 @@ var buildScaffoldInput = async (options) => {
|
|
|
8701
8970
|
availableWorkflowNames
|
|
8702
8971
|
) : void 0;
|
|
8703
8972
|
return {
|
|
8704
|
-
cwd:
|
|
8973
|
+
cwd: process14.cwd(),
|
|
8705
8974
|
type,
|
|
8706
8975
|
name,
|
|
8707
8976
|
title,
|
|
@@ -8730,10 +8999,10 @@ var finishScaffoldSuccess = (type, name, createdFiles) => {
|
|
|
8730
8999
|
var isMockedProcessExitError = (error) => error instanceof Error && error.message.startsWith("process.exit:");
|
|
8731
9000
|
var handleScaffoldCommandFailure = (error) => {
|
|
8732
9001
|
if (error instanceof ScaffoldError) {
|
|
8733
|
-
|
|
9002
|
+
exitWithError(error.message);
|
|
8734
9003
|
}
|
|
8735
9004
|
if (error instanceof Error && !isMockedProcessExitError(error)) {
|
|
8736
|
-
|
|
9005
|
+
exitWithError(error.message);
|
|
8737
9006
|
}
|
|
8738
9007
|
throw error;
|
|
8739
9008
|
};
|