@braid-cloud/cli 0.1.16 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +438 -134
- package/dist/index.js.map +1 -1
- package/dist/manage-ui/assets/index-DvWPfYXk.css +2 -0
- package/dist/manage-ui/assets/{index-BFp1kLOE.js → index-m-nUswBP.js} +1 -1
- package/dist/manage-ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/manage-ui/assets/index-De7GJyM1.css +0 -2
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ var init_esm_shims = __esm({
|
|
|
20
20
|
|
|
21
21
|
// src/lib/braid-workspace.ts
|
|
22
22
|
import { existsSync, readFileSync } from "fs";
|
|
23
|
-
import { dirname as
|
|
23
|
+
import { dirname as dirname3, join as join2 } from "path";
|
|
24
24
|
import process3 from "process";
|
|
25
25
|
function readPackageName(packagePath) {
|
|
26
26
|
if (!existsSync(packagePath)) {
|
|
@@ -44,7 +44,7 @@ function findBraidWorkspaceRoot(startDir = process3.cwd()) {
|
|
|
44
44
|
if (isBraidWorkspaceRoot(currentDir)) {
|
|
45
45
|
return currentDir;
|
|
46
46
|
}
|
|
47
|
-
const parentDir =
|
|
47
|
+
const parentDir = dirname3(currentDir);
|
|
48
48
|
if (parentDir === currentDir) {
|
|
49
49
|
return void 0;
|
|
50
50
|
}
|
|
@@ -107,7 +107,7 @@ __export(config_exports, {
|
|
|
107
107
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
108
108
|
import { mkdir as mkdir2, readFile, writeFile as writeFile2 } from "fs/promises";
|
|
109
109
|
import { homedir as homedir2 } from "os";
|
|
110
|
-
import { dirname as
|
|
110
|
+
import { dirname as dirname4, join as join3, parse } from "path";
|
|
111
111
|
import process4 from "process";
|
|
112
112
|
import { Data as Data2, Effect as Effect3, pipe as pipe3 } from "effect";
|
|
113
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;
|
|
@@ -256,7 +256,7 @@ var init_config = __esm({
|
|
|
256
256
|
return pipe3(
|
|
257
257
|
Effect3.tryPromise({
|
|
258
258
|
try: async () => {
|
|
259
|
-
await mkdir2(
|
|
259
|
+
await mkdir2(dirname4(targetPath), { recursive: true, mode: 448 });
|
|
260
260
|
await writeFile2(targetPath, JSON.stringify(config, null, 2), {
|
|
261
261
|
encoding: "utf-8",
|
|
262
262
|
mode: 384
|
|
@@ -272,7 +272,7 @@ var init_config = __esm({
|
|
|
272
272
|
return pipe3(
|
|
273
273
|
Effect3.tryPromise({
|
|
274
274
|
try: async () => {
|
|
275
|
-
await mkdir2(
|
|
275
|
+
await mkdir2(dirname4(targetPath), { recursive: true, mode: 448 });
|
|
276
276
|
await writeFile2(targetPath, JSON.stringify(config, null, 2), {
|
|
277
277
|
encoding: "utf-8",
|
|
278
278
|
mode: 384
|
|
@@ -392,7 +392,7 @@ var init_config = __esm({
|
|
|
392
392
|
saveConfig = (config) => pipe3(
|
|
393
393
|
Effect3.tryPromise({
|
|
394
394
|
try: async () => {
|
|
395
|
-
await mkdir2(
|
|
395
|
+
await mkdir2(dirname4(CONFIG_FILE), { recursive: true, mode: 448 });
|
|
396
396
|
await writeFile2(CONFIG_FILE, JSON.stringify(config, null, 2), {
|
|
397
397
|
encoding: "utf-8",
|
|
398
398
|
mode: 384
|
|
@@ -1941,7 +1941,7 @@ var writeAgentsForPlatformAsync = (platform2, specs, installPath) => Effect.runP
|
|
|
1941
1941
|
init_esm_shims();
|
|
1942
1942
|
import { access, constants } from "fs/promises";
|
|
1943
1943
|
import { homedir } from "os";
|
|
1944
|
-
import { join } from "path";
|
|
1944
|
+
import { dirname as dirname2, join } from "path";
|
|
1945
1945
|
import process2 from "process";
|
|
1946
1946
|
import { Effect as Effect2, pipe as pipe2 } from "effect";
|
|
1947
1947
|
var home = homedir();
|
|
@@ -2585,7 +2585,7 @@ var DeviceAuthExpiredError = class extends Error {
|
|
|
2585
2585
|
this.name = "DeviceAuthExpiredError";
|
|
2586
2586
|
}
|
|
2587
2587
|
};
|
|
2588
|
-
var sleep = (ms) => new Promise((
|
|
2588
|
+
var sleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
2589
2589
|
var normalizeBaseUrl2 = (rawUrl) => {
|
|
2590
2590
|
const trimmed = rawUrl.replace(TRAILING_SLASHES2, "");
|
|
2591
2591
|
try {
|
|
@@ -3288,7 +3288,7 @@ import {
|
|
|
3288
3288
|
writeFile as writeFile3
|
|
3289
3289
|
} from "fs/promises";
|
|
3290
3290
|
import { homedir as homedir3 } from "os";
|
|
3291
|
-
import { basename, dirname as
|
|
3291
|
+
import { basename, dirname as dirname5, join as join5, resolve as resolve2 } from "path";
|
|
3292
3292
|
var BRAID_CONFIG_DIR = join5(homedir3(), ".config", "braid");
|
|
3293
3293
|
var DEFAULT_STORE_ROOT = join5(BRAID_CONFIG_DIR, "store", "skills");
|
|
3294
3294
|
var DEFAULT_DISABLED_ROOT = join5(BRAID_CONFIG_DIR, ".disabled");
|
|
@@ -3397,7 +3397,7 @@ var enableBundleAsync = async (originalPath, options = {}) => {
|
|
|
3397
3397
|
if (!record) {
|
|
3398
3398
|
throw new Error(`No disabled bundle found for ${originalPath}`);
|
|
3399
3399
|
}
|
|
3400
|
-
await mkdir3(
|
|
3400
|
+
await mkdir3(dirname5(record.originalPath), { recursive: true });
|
|
3401
3401
|
await rm(record.originalPath, { recursive: true, force: true });
|
|
3402
3402
|
await rename(record.payloadPath, record.originalPath);
|
|
3403
3403
|
await rm(record.disabledPath, { recursive: true, force: true });
|
|
@@ -3414,9 +3414,9 @@ init_lockfile();
|
|
|
3414
3414
|
// src/lib/metadata.ts
|
|
3415
3415
|
init_esm_shims();
|
|
3416
3416
|
import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
3417
|
-
import { join as join7 } from "path";
|
|
3417
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
3418
3418
|
import { Data as Data5, Effect as Effect6, pipe as pipe6 } from "effect";
|
|
3419
|
-
var METADATA_FILENAME2 = ".
|
|
3419
|
+
var METADATA_FILENAME2 = ".braid-metadata.json";
|
|
3420
3420
|
var MetadataReadError = class extends Data5.TaggedError("MetadataReadError") {
|
|
3421
3421
|
};
|
|
3422
3422
|
var MetadataWriteError = class extends Data5.TaggedError("MetadataWriteError") {
|
|
@@ -3432,7 +3432,7 @@ var normalizeInstalledSkill = (skill) => ({
|
|
|
3432
3432
|
var normalizeMetadata = (metadata) => ({
|
|
3433
3433
|
skills: Array.isArray(metadata?.skills) ? metadata.skills.map(normalizeInstalledSkill) : []
|
|
3434
3434
|
});
|
|
3435
|
-
var getMetadataPath = (skillsDir) => join7(skillsDir, METADATA_FILENAME2);
|
|
3435
|
+
var getMetadataPath = (skillsDir) => join7(dirname6(skillsDir), METADATA_FILENAME2);
|
|
3436
3436
|
var readMetadata = (skillsDir) => {
|
|
3437
3437
|
const metadataPath = getMetadataPath(skillsDir);
|
|
3438
3438
|
return pipe6(
|
|
@@ -3449,10 +3449,26 @@ var readMetadata = (skillsDir) => {
|
|
|
3449
3449
|
Effect6.orElseSucceed(() => normalizeMetadata(void 0))
|
|
3450
3450
|
);
|
|
3451
3451
|
};
|
|
3452
|
+
var readRawJson = async (path2) => {
|
|
3453
|
+
try {
|
|
3454
|
+
const content = await readFile4(path2, "utf-8");
|
|
3455
|
+
const parsed = JSON.parse(content);
|
|
3456
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3457
|
+
return parsed;
|
|
3458
|
+
}
|
|
3459
|
+
} catch (_) {
|
|
3460
|
+
return {};
|
|
3461
|
+
}
|
|
3462
|
+
return {};
|
|
3463
|
+
};
|
|
3452
3464
|
var writeMetadata = (skillsDir, metadata) => {
|
|
3453
3465
|
const metadataPath = getMetadataPath(skillsDir);
|
|
3454
3466
|
return Effect6.tryPromise({
|
|
3455
|
-
try: () =>
|
|
3467
|
+
try: async () => {
|
|
3468
|
+
const existing = await readRawJson(metadataPath);
|
|
3469
|
+
const merged = { ...existing, skills: metadata.skills };
|
|
3470
|
+
await writeFile5(metadataPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
3471
|
+
},
|
|
3456
3472
|
catch: (e) => new MetadataWriteError({ path: metadataPath, cause: e })
|
|
3457
3473
|
});
|
|
3458
3474
|
};
|
|
@@ -3497,7 +3513,7 @@ var removeFromMetadataAsync = (skillsDir, skillName) => Effect6.runPromise(remov
|
|
|
3497
3513
|
// src/lib/rule-writer.ts
|
|
3498
3514
|
init_esm_shims();
|
|
3499
3515
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
3500
|
-
import { dirname as
|
|
3516
|
+
import { dirname as dirname7, resolve as resolve3, sep as sep2 } from "path";
|
|
3501
3517
|
import { Data as Data6, Effect as Effect7, pipe as pipe7 } from "effect";
|
|
3502
3518
|
var RuleWriteError = class extends Data6.TaggedError("RuleWriteError") {
|
|
3503
3519
|
};
|
|
@@ -3595,7 +3611,7 @@ ${rule.content}`)
|
|
|
3595
3611
|
Effect7.asVoid
|
|
3596
3612
|
);
|
|
3597
3613
|
var writeAppendSingleRules = (filePath, rules2) => pipe7(
|
|
3598
|
-
createDirectory(
|
|
3614
|
+
createDirectory(dirname7(filePath)),
|
|
3599
3615
|
Effect7.flatMap(
|
|
3600
3616
|
() => pipe7(
|
|
3601
3617
|
readTextFile(filePath),
|
|
@@ -3658,7 +3674,7 @@ var writeRulesForAgentAsync = (agent, rules2, rulesPath) => Effect7.runPromise(w
|
|
|
3658
3674
|
init_esm_shims();
|
|
3659
3675
|
import { createHash as createHash2 } from "crypto";
|
|
3660
3676
|
import { chmod, mkdir as mkdir5, rm as rm2, symlink, writeFile as writeFile7 } from "fs/promises";
|
|
3661
|
-
import { dirname as
|
|
3677
|
+
import { dirname as dirname8, join as join8, resolve as resolve4, sep as sep3 } from "path";
|
|
3662
3678
|
import { Data as Data7, Effect as Effect8, pipe as pipe8 } from "effect";
|
|
3663
3679
|
var WriteError = class extends Data7.TaggedError("WriteError") {
|
|
3664
3680
|
};
|
|
@@ -3739,7 +3755,7 @@ var setExecutableIfScript = (fullPath, file, agentId) => isScriptFile(file.path)
|
|
|
3739
3755
|
var writeSkillFile = (basePath, file, agentId) => pipe8(
|
|
3740
3756
|
assertWithinBase2(basePath, file.path),
|
|
3741
3757
|
Effect8.flatMap((fullPath) => {
|
|
3742
|
-
const dir =
|
|
3758
|
+
const dir = dirname8(fullPath);
|
|
3743
3759
|
return pipe8(
|
|
3744
3760
|
createDirectory2(dir, fullPath),
|
|
3745
3761
|
Effect8.flatMap(() => writeFileContent(fullPath, file, agentId)),
|
|
@@ -3786,7 +3802,7 @@ var writeSkillSymlink = (basePath, skill, agentId, options) => pipe8(
|
|
|
3786
3802
|
disabledRoot: options.disabledRoot
|
|
3787
3803
|
}
|
|
3788
3804
|
);
|
|
3789
|
-
await mkdir5(
|
|
3805
|
+
await mkdir5(dirname8(destinationPath), { recursive: true });
|
|
3790
3806
|
await rm2(destinationPath, { recursive: true, force: true });
|
|
3791
3807
|
await symlink(
|
|
3792
3808
|
storedBundlePath,
|
|
@@ -4531,17 +4547,17 @@ init_config();
|
|
|
4531
4547
|
|
|
4532
4548
|
// src/lib/manage-actions.ts
|
|
4533
4549
|
init_esm_shims();
|
|
4534
|
-
import { rm as
|
|
4535
|
-
import { basename as basename2, dirname as
|
|
4550
|
+
import { rm as rm5 } from "fs/promises";
|
|
4551
|
+
import { basename as basename2, dirname as dirname10, join as join11, relative } from "path";
|
|
4536
4552
|
|
|
4537
4553
|
// src/lib/hook-writer.ts
|
|
4538
4554
|
init_esm_shims();
|
|
4539
4555
|
import { mkdir as mkdir6, readFile as readFile6, rm as rm3, writeFile as writeFile8 } from "fs/promises";
|
|
4540
|
-
import { dirname as
|
|
4556
|
+
import { dirname as dirname9, join as join9 } from "path";
|
|
4541
4557
|
import { Data as Data8, Effect as Effect9 } from "effect";
|
|
4542
4558
|
var HookConfigWriteError = class extends Data8.TaggedError("HookConfigWriteError") {
|
|
4543
4559
|
};
|
|
4544
|
-
var HOOK_METADATA_FILENAME = ".braid-
|
|
4560
|
+
var HOOK_METADATA_FILENAME = ".braid-metadata.json";
|
|
4545
4561
|
function stableStringify(value) {
|
|
4546
4562
|
return JSON.stringify(value, (_key, currentValue) => {
|
|
4547
4563
|
if (currentValue && typeof currentValue === "object" && !Array.isArray(currentValue)) {
|
|
@@ -4582,7 +4598,7 @@ async function readJsonFile(path2) {
|
|
|
4582
4598
|
}
|
|
4583
4599
|
}
|
|
4584
4600
|
async function writeJsonFile(path2, value) {
|
|
4585
|
-
await mkdir6(
|
|
4601
|
+
await mkdir6(dirname9(path2), { recursive: true, mode: 448 });
|
|
4586
4602
|
await writeFile8(path2, `${JSON.stringify(value, null, 2)}
|
|
4587
4603
|
`, {
|
|
4588
4604
|
encoding: "utf-8",
|
|
@@ -4681,7 +4697,7 @@ function addHookHandlers(config, hook) {
|
|
|
4681
4697
|
return writeMatcherGroups(config, hook.event, groups);
|
|
4682
4698
|
}
|
|
4683
4699
|
function getHookMetadataPath(settingsPath) {
|
|
4684
|
-
return join9(
|
|
4700
|
+
return join9(dirname9(settingsPath), HOOK_METADATA_FILENAME);
|
|
4685
4701
|
}
|
|
4686
4702
|
async function readHookMetadata(settingsPath) {
|
|
4687
4703
|
const metadataPath = getHookMetadataPath(settingsPath);
|
|
@@ -4690,9 +4706,9 @@ async function readHookMetadata(settingsPath) {
|
|
|
4690
4706
|
return { hooks };
|
|
4691
4707
|
}
|
|
4692
4708
|
async function writeHookMetadata(settingsPath, metadata) {
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
});
|
|
4709
|
+
const metadataPath = getHookMetadataPath(settingsPath);
|
|
4710
|
+
const existing = await readJsonFile(metadataPath);
|
|
4711
|
+
await writeJsonFile(metadataPath, { ...existing, hooks: metadata.hooks });
|
|
4696
4712
|
}
|
|
4697
4713
|
function buildMarketplaceHookSource(sourceSlug) {
|
|
4698
4714
|
return {
|
|
@@ -4790,7 +4806,7 @@ async function listInstalledMarketplaceHookSources(settingsPath) {
|
|
|
4790
4806
|
);
|
|
4791
4807
|
}
|
|
4792
4808
|
function buildMarketplaceHookBundlePath(settingsPath, sourceSlug) {
|
|
4793
|
-
return join9(
|
|
4809
|
+
return join9(dirname9(settingsPath), ".braid-hooks", `${sourceSlug}.json`);
|
|
4794
4810
|
}
|
|
4795
4811
|
function buildMarketplaceHookBundle(hooks, options) {
|
|
4796
4812
|
return {
|
|
@@ -5042,6 +5058,8 @@ var fetchMarketplaceInstallManifestAsync = (slug, options) => Effect10.runPromis
|
|
|
5042
5058
|
|
|
5043
5059
|
// src/lib/marketplace-installer.ts
|
|
5044
5060
|
init_esm_shims();
|
|
5061
|
+
import { rm as rm4 } from "fs/promises";
|
|
5062
|
+
import { join as join10 } from "path";
|
|
5045
5063
|
function parseAgentIds(value) {
|
|
5046
5064
|
if (!value) {
|
|
5047
5065
|
return [];
|
|
@@ -5184,6 +5202,58 @@ async function installHooksForAgent(args) {
|
|
|
5184
5202
|
args.targets.push(`${args.agent.name} hooks -> ${hookConfigPath}`);
|
|
5185
5203
|
return true;
|
|
5186
5204
|
}
|
|
5205
|
+
async function pruneStaleMarketplaceSkills(installPath, slug, currentSkillNames) {
|
|
5206
|
+
const metadata = await readMetadataAsync(installPath);
|
|
5207
|
+
const stale = metadata.skills.filter(
|
|
5208
|
+
(skill) => skill.source.type === "marketplace" && skill.source.slug === slug && !currentSkillNames.has(skill.name)
|
|
5209
|
+
);
|
|
5210
|
+
for (const skill of stale) {
|
|
5211
|
+
const skillPath = join10(installPath, skill.name);
|
|
5212
|
+
await rm4(skillPath, { recursive: true, force: true });
|
|
5213
|
+
await removeFromMetadataAsync(installPath, skill.name);
|
|
5214
|
+
}
|
|
5215
|
+
}
|
|
5216
|
+
async function installAllForAgent(args) {
|
|
5217
|
+
await installSkillsForAgent({
|
|
5218
|
+
agent: args.agent,
|
|
5219
|
+
manifest: args.manifest,
|
|
5220
|
+
slug: args.slug,
|
|
5221
|
+
skills: args.skills,
|
|
5222
|
+
global: args.global,
|
|
5223
|
+
installedSkills: args.installedSkills,
|
|
5224
|
+
targets: args.targets
|
|
5225
|
+
});
|
|
5226
|
+
await installRulesForAgent({
|
|
5227
|
+
agent: args.agent,
|
|
5228
|
+
rules: args.rules,
|
|
5229
|
+
global: args.global,
|
|
5230
|
+
targets: args.targets
|
|
5231
|
+
});
|
|
5232
|
+
await installAgentsForAgent({
|
|
5233
|
+
agent: args.agent,
|
|
5234
|
+
agents: args.agents,
|
|
5235
|
+
global: args.global,
|
|
5236
|
+
targets: args.targets
|
|
5237
|
+
});
|
|
5238
|
+
if (args.installHooks) {
|
|
5239
|
+
await installHooksForAgent({
|
|
5240
|
+
agent: args.agent,
|
|
5241
|
+
hooks: args.hooks,
|
|
5242
|
+
slug: args.slug,
|
|
5243
|
+
manifest: args.manifest,
|
|
5244
|
+
global: args.global,
|
|
5245
|
+
targets: args.targets
|
|
5246
|
+
});
|
|
5247
|
+
}
|
|
5248
|
+
const installPath = resolveInstallPath(args.agent, { global: args.global });
|
|
5249
|
+
if (installPath) {
|
|
5250
|
+
await pruneStaleMarketplaceSkills(
|
|
5251
|
+
installPath,
|
|
5252
|
+
args.slug,
|
|
5253
|
+
args.installedSkills
|
|
5254
|
+
);
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5187
5257
|
async function installMarketplaceSkillSet(options) {
|
|
5188
5258
|
if (options.manifest.blocked) {
|
|
5189
5259
|
throw new Error(
|
|
@@ -5195,12 +5265,8 @@ async function installMarketplaceSkillSet(options) {
|
|
|
5195
5265
|
const hooks = options.manifest.manifest?.hooks ?? [];
|
|
5196
5266
|
const agents2 = options.manifest.manifest?.agents ?? [];
|
|
5197
5267
|
const workflows = options.manifest.manifest?.workflows ?? [];
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
"Marketplace packs with hooks require explicit opt-in. Re-run with --allow-hooks after reviewing the hook commands."
|
|
5201
|
-
);
|
|
5202
|
-
}
|
|
5203
|
-
if (resolvedSkills.length === 0 && rules2.length === 0 && hooks.length === 0 && agents2.length === 0 && workflows.length === 0) {
|
|
5268
|
+
const installHooks = hooks.length > 0 && options.allowHooks === true;
|
|
5269
|
+
if (resolvedSkills.length === 0 && rules2.length === 0 && (!installHooks || hooks.length === 0) && agents2.length === 0 && workflows.length === 0) {
|
|
5204
5270
|
throw new Error("No installable content found in manifest");
|
|
5205
5271
|
}
|
|
5206
5272
|
const targetAgents = await resolveTargetAgents(options.agents);
|
|
@@ -5212,33 +5278,17 @@ async function installMarketplaceSkillSet(options) {
|
|
|
5212
5278
|
const targets = [];
|
|
5213
5279
|
const installedSkills = /* @__PURE__ */ new Set();
|
|
5214
5280
|
for (const agent of targetAgents) {
|
|
5215
|
-
await
|
|
5281
|
+
await installAllForAgent({
|
|
5216
5282
|
agent,
|
|
5217
5283
|
manifest: options.manifest,
|
|
5218
5284
|
slug: options.slug,
|
|
5219
5285
|
skills: resolvedSkills,
|
|
5220
|
-
global: options.global,
|
|
5221
|
-
installedSkills,
|
|
5222
|
-
targets
|
|
5223
|
-
});
|
|
5224
|
-
await installRulesForAgent({
|
|
5225
|
-
agent,
|
|
5226
5286
|
rules: rules2,
|
|
5227
|
-
global: options.global,
|
|
5228
|
-
targets
|
|
5229
|
-
});
|
|
5230
|
-
await installAgentsForAgent({
|
|
5231
|
-
agent,
|
|
5232
5287
|
agents: agents2,
|
|
5233
|
-
global: options.global,
|
|
5234
|
-
targets
|
|
5235
|
-
});
|
|
5236
|
-
await installHooksForAgent({
|
|
5237
|
-
agent,
|
|
5238
5288
|
hooks,
|
|
5239
|
-
|
|
5240
|
-
manifest: options.manifest,
|
|
5289
|
+
installHooks,
|
|
5241
5290
|
global: options.global,
|
|
5291
|
+
installedSkills,
|
|
5242
5292
|
targets
|
|
5243
5293
|
});
|
|
5244
5294
|
}
|
|
@@ -5257,12 +5307,12 @@ function isMarketplaceHookBundlePath(originalPath) {
|
|
|
5257
5307
|
return getHookBundleRoot(originalPath) !== null;
|
|
5258
5308
|
}
|
|
5259
5309
|
function getHookBundleRoot(originalPath) {
|
|
5260
|
-
let currentPath =
|
|
5310
|
+
let currentPath = dirname10(originalPath);
|
|
5261
5311
|
while (true) {
|
|
5262
5312
|
if (basename2(currentPath) === ".braid-hooks") {
|
|
5263
|
-
return
|
|
5313
|
+
return dirname10(currentPath);
|
|
5264
5314
|
}
|
|
5265
|
-
const parentPath =
|
|
5315
|
+
const parentPath = dirname10(currentPath);
|
|
5266
5316
|
if (parentPath === currentPath) {
|
|
5267
5317
|
return null;
|
|
5268
5318
|
}
|
|
@@ -5274,7 +5324,7 @@ function getHookBundleRelativePath(originalPath) {
|
|
|
5274
5324
|
if (!bundleRoot) {
|
|
5275
5325
|
throw new Error(`Invalid marketplace hook bundle path: ${originalPath}`);
|
|
5276
5326
|
}
|
|
5277
|
-
return relative(
|
|
5327
|
+
return relative(join11(bundleRoot, ".braid-hooks"), originalPath);
|
|
5278
5328
|
}
|
|
5279
5329
|
function getHookSourceSlug(originalPath) {
|
|
5280
5330
|
const relativePath = getHookBundleRelativePath(originalPath);
|
|
@@ -5293,7 +5343,7 @@ function getHookSettingsPath(originalPath) {
|
|
|
5293
5343
|
if (!bundleRoot) {
|
|
5294
5344
|
throw new Error(`Invalid marketplace hook bundle path: ${originalPath}`);
|
|
5295
5345
|
}
|
|
5296
|
-
return
|
|
5346
|
+
return join11(bundleRoot, "settings.json");
|
|
5297
5347
|
}
|
|
5298
5348
|
async function disableManagedBundleAsync(options) {
|
|
5299
5349
|
if (options.surface === "hooks") {
|
|
@@ -5350,7 +5400,7 @@ async function removeManagedBundleAsync(options) {
|
|
|
5350
5400
|
}
|
|
5351
5401
|
);
|
|
5352
5402
|
await removeMarketplaceHooksBySourceAsync(
|
|
5353
|
-
|
|
5403
|
+
join11(options.installRoot, "settings.json"),
|
|
5354
5404
|
options.bundleName
|
|
5355
5405
|
);
|
|
5356
5406
|
if (disabledRecord2) {
|
|
@@ -5364,7 +5414,7 @@ async function removeManagedBundleAsync(options) {
|
|
|
5364
5414
|
disabledRoot: options.disabledRoot
|
|
5365
5415
|
}
|
|
5366
5416
|
);
|
|
5367
|
-
await
|
|
5417
|
+
await rm5(options.originalPath, { recursive: true, force: true });
|
|
5368
5418
|
if (disabledRecord) {
|
|
5369
5419
|
await removePathAsync(disabledRecord.disabledPath);
|
|
5370
5420
|
}
|
|
@@ -5388,7 +5438,7 @@ async function installLibraryPackAsync(options) {
|
|
|
5388
5438
|
// src/lib/manage-inventory.ts
|
|
5389
5439
|
init_esm_shims();
|
|
5390
5440
|
import { access as access2, constants as constants2, lstat, readdir as readdir2 } from "fs/promises";
|
|
5391
|
-
import { basename as basename3, delimiter, dirname as
|
|
5441
|
+
import { basename as basename3, delimiter, dirname as dirname11, join as join12, resolve as resolve5 } from "path";
|
|
5392
5442
|
var MANAGE_PROVIDER_COMMANDS = {
|
|
5393
5443
|
amp: ["amp"],
|
|
5394
5444
|
"claude-code": ["claude"],
|
|
@@ -5436,7 +5486,7 @@ function getCommandExtensions() {
|
|
|
5436
5486
|
function getCommandCandidates(command, pathValue) {
|
|
5437
5487
|
return pathValue.split(delimiter).flatMap(
|
|
5438
5488
|
(segment) => segment ? getCommandExtensions().map(
|
|
5439
|
-
(extension) =>
|
|
5489
|
+
(extension) => join12(segment, `${command}${extension}`)
|
|
5440
5490
|
) : []
|
|
5441
5491
|
);
|
|
5442
5492
|
}
|
|
@@ -5552,9 +5602,9 @@ async function listSurfaceEntries(rootPath, surface) {
|
|
|
5552
5602
|
}
|
|
5553
5603
|
return entry.isDirectory() || entry.isFile() || entry.isSymbolicLink();
|
|
5554
5604
|
}).map((entry) => ({
|
|
5555
|
-
currentPath:
|
|
5605
|
+
currentPath: join12(rootPath, entry.name),
|
|
5556
5606
|
name: entry.name,
|
|
5557
|
-
originalPath:
|
|
5607
|
+
originalPath: join12(rootPath, entry.name)
|
|
5558
5608
|
}));
|
|
5559
5609
|
}
|
|
5560
5610
|
function toBundleKey(path2) {
|
|
@@ -5603,7 +5653,7 @@ async function collectSkillBundles(args) {
|
|
|
5603
5653
|
});
|
|
5604
5654
|
}
|
|
5605
5655
|
for (const metadataEntry of metadata.skills) {
|
|
5606
|
-
const originalPath =
|
|
5656
|
+
const originalPath = join12(args.rootPath, metadataEntry.name);
|
|
5607
5657
|
const bundleKey = toBundleKey(originalPath);
|
|
5608
5658
|
if (bundles.has(bundleKey)) {
|
|
5609
5659
|
continue;
|
|
@@ -5684,7 +5734,7 @@ async function collectHookBundles(args) {
|
|
|
5684
5734
|
return [];
|
|
5685
5735
|
}
|
|
5686
5736
|
const settingsPath = args.settingsPath;
|
|
5687
|
-
const installRoot =
|
|
5737
|
+
const installRoot = dirname11(settingsPath);
|
|
5688
5738
|
const sources = await listInstalledMarketplaceHookSourcesAsync(settingsPath);
|
|
5689
5739
|
const disabledRecords = getDisabledRecordsForSurface({
|
|
5690
5740
|
agent: args.agent,
|
|
@@ -5788,7 +5838,7 @@ async function collectScopeInventory(args) {
|
|
|
5788
5838
|
},
|
|
5789
5839
|
hooks: {
|
|
5790
5840
|
bundles: hooks,
|
|
5791
|
-
rootPath: hookSettingsPath ?
|
|
5841
|
+
rootPath: hookSettingsPath ? dirname11(hookSettingsPath) : null,
|
|
5792
5842
|
surface: "hooks"
|
|
5793
5843
|
},
|
|
5794
5844
|
rules: {
|
|
@@ -6389,39 +6439,288 @@ async function manageCommand(options) {
|
|
|
6389
6439
|
|
|
6390
6440
|
// src/commands/marketplace.ts
|
|
6391
6441
|
init_esm_shims();
|
|
6442
|
+
import { rm as rm6 } from "fs/promises";
|
|
6443
|
+
import { join as join13, resolve as resolve7 } from "path";
|
|
6444
|
+
import process11 from "process";
|
|
6392
6445
|
init_tui();
|
|
6393
|
-
async function
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6446
|
+
async function selectInstallScope(options) {
|
|
6447
|
+
if (options.global != null) {
|
|
6448
|
+
return options.global;
|
|
6449
|
+
}
|
|
6450
|
+
if (options.yes) {
|
|
6451
|
+
return false;
|
|
6452
|
+
}
|
|
6453
|
+
const result = await select({
|
|
6454
|
+
message: "Install location:",
|
|
6455
|
+
options: [
|
|
6456
|
+
{ value: false, label: "Project", hint: "local to this directory" },
|
|
6457
|
+
{ value: true, label: "Global", hint: "available everywhere" }
|
|
6458
|
+
],
|
|
6459
|
+
initialValue: false
|
|
6397
6460
|
});
|
|
6398
|
-
if (
|
|
6399
|
-
|
|
6400
|
-
|
|
6461
|
+
if (isCancel(result)) {
|
|
6462
|
+
cancel("Install cancelled.");
|
|
6463
|
+
process11.exit(0);
|
|
6401
6464
|
}
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6465
|
+
return result;
|
|
6466
|
+
}
|
|
6467
|
+
async function selectInstallAgents(options, global) {
|
|
6468
|
+
const detected = await detectAgentsAsync();
|
|
6469
|
+
const available = detected.map((d) => getAgentById(d.id)).filter((a) => a != null);
|
|
6470
|
+
if (available.length === 0) {
|
|
6471
|
+
throw new Error(
|
|
6472
|
+
"No compatible agents found. Use --agents to specify targets."
|
|
6407
6473
|
);
|
|
6408
6474
|
}
|
|
6475
|
+
if (options.agents) {
|
|
6476
|
+
const ids = options.agents.split(",").map((s) => s.trim());
|
|
6477
|
+
const matched = ids.map((id) => getAgentById(id)).filter((a) => a != null);
|
|
6478
|
+
if (matched.length === 0) {
|
|
6479
|
+
throw new Error(`No agents matched: ${options.agents}`);
|
|
6480
|
+
}
|
|
6481
|
+
return matched;
|
|
6482
|
+
}
|
|
6483
|
+
if (options.yes || available.length === 1) {
|
|
6484
|
+
return available.length === 1 ? available : available;
|
|
6485
|
+
}
|
|
6486
|
+
const selected = await multiselect({
|
|
6487
|
+
message: "Select agents to install to:",
|
|
6488
|
+
options: available.map((agent) => ({
|
|
6489
|
+
value: agent,
|
|
6490
|
+
label: agent.name,
|
|
6491
|
+
hint: global ? agent.globalPath : agent.projectPath
|
|
6492
|
+
})),
|
|
6493
|
+
initialValues: [],
|
|
6494
|
+
required: true
|
|
6495
|
+
});
|
|
6496
|
+
if (isCancel(selected)) {
|
|
6497
|
+
cancel("Install cancelled.");
|
|
6498
|
+
process11.exit(0);
|
|
6499
|
+
}
|
|
6500
|
+
return selected;
|
|
6409
6501
|
}
|
|
6410
|
-
async function
|
|
6502
|
+
async function confirmHooksOptIn(hookCount, options) {
|
|
6503
|
+
if (options.allowHooks) {
|
|
6504
|
+
return true;
|
|
6505
|
+
}
|
|
6506
|
+
if (options.yes) {
|
|
6507
|
+
return false;
|
|
6508
|
+
}
|
|
6509
|
+
const result = await confirm({
|
|
6510
|
+
message: `This pack includes ${hookCount} hook${hookCount === 1 ? "" : "s"} that run shell commands. Allow hooks?`,
|
|
6511
|
+
initialValue: false
|
|
6512
|
+
});
|
|
6513
|
+
if (isCancel(result)) {
|
|
6514
|
+
cancel("Install cancelled.");
|
|
6515
|
+
process11.exit(0);
|
|
6516
|
+
}
|
|
6517
|
+
return result;
|
|
6518
|
+
}
|
|
6519
|
+
async function marketplaceLibraryCommand(options) {
|
|
6520
|
+
try {
|
|
6521
|
+
const items = await fetchMarketplaceLibraryAsync({
|
|
6522
|
+
server: options.server,
|
|
6523
|
+
apiKey: options.apiKey
|
|
6524
|
+
});
|
|
6525
|
+
if (items.length === 0) {
|
|
6526
|
+
log.info("No marketplace packs in your library yet.");
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
6529
|
+
for (const item of items) {
|
|
6530
|
+
const scan = item.scanVerdict ?? "clean";
|
|
6531
|
+
const commit = item.commitSha ?? "unknown";
|
|
6532
|
+
log.info(
|
|
6533
|
+
`${item.slug} | ${item.title} | scan=${scan} | commit=${commit} | install=braid marketplace install ${item.slug}`
|
|
6534
|
+
);
|
|
6535
|
+
}
|
|
6536
|
+
} catch (error) {
|
|
6537
|
+
log.error(
|
|
6538
|
+
error instanceof Error ? error.message : "Failed to fetch library"
|
|
6539
|
+
);
|
|
6540
|
+
process11.exit(1);
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
async function resolveAndInstallPack(slug, options, overrides) {
|
|
6411
6544
|
const manifest = await fetchMarketplaceInstallManifestAsync(slug, {
|
|
6412
6545
|
server: options.server,
|
|
6413
6546
|
apiKey: options.apiKey
|
|
6414
6547
|
});
|
|
6415
|
-
const
|
|
6548
|
+
const global = overrides?.global ?? await selectInstallScope(options);
|
|
6549
|
+
const hooks = manifest.manifest?.hooks ?? [];
|
|
6550
|
+
if (hooks.length > 0) {
|
|
6551
|
+
const allowed = await confirmHooksOptIn(hooks.length, options);
|
|
6552
|
+
if (!allowed) {
|
|
6553
|
+
log.warn("Hooks skipped. Re-run with --allow-hooks to include them.");
|
|
6554
|
+
}
|
|
6555
|
+
options.allowHooks = allowed;
|
|
6556
|
+
}
|
|
6557
|
+
const agents2 = overrides?.agents ?? (await selectInstallAgents(options, global)).map((a) => a.id).join(",");
|
|
6558
|
+
await installMarketplaceSkillSet({
|
|
6416
6559
|
slug,
|
|
6417
6560
|
manifest,
|
|
6418
|
-
agents:
|
|
6419
|
-
global
|
|
6561
|
+
agents: agents2,
|
|
6562
|
+
global,
|
|
6420
6563
|
allowHooks: options.allowHooks
|
|
6421
6564
|
});
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6565
|
+
}
|
|
6566
|
+
async function marketplaceInstallCommand(slug, options) {
|
|
6567
|
+
try {
|
|
6568
|
+
await resolveAndInstallPack(slug, options);
|
|
6569
|
+
log.success(`Installed marketplace pack ${slug}`);
|
|
6570
|
+
} catch (error) {
|
|
6571
|
+
log.error(
|
|
6572
|
+
error instanceof Error ? error.message : "Failed to install pack"
|
|
6573
|
+
);
|
|
6574
|
+
process11.exit(1);
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6577
|
+
function addSkillToPack(packMap, slug, versionId, skillName, agent, installPath) {
|
|
6578
|
+
let pack = packMap.get(slug);
|
|
6579
|
+
if (!pack) {
|
|
6580
|
+
pack = { slug, versionId, skills: [], agents: [] };
|
|
6581
|
+
packMap.set(slug, pack);
|
|
6582
|
+
}
|
|
6583
|
+
if (!pack.skills.includes(skillName)) {
|
|
6584
|
+
pack.skills.push(skillName);
|
|
6585
|
+
}
|
|
6586
|
+
if (!pack.agents.some((a) => a.agent.id === agent.id)) {
|
|
6587
|
+
pack.agents.push({ agent, installPath });
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
async function findInstalledMarketplacePacks(options) {
|
|
6591
|
+
const detected = await detectAgentsAsync();
|
|
6592
|
+
const agents2 = detected.map((d) => getAgentById(d.id)).filter((a) => a != null);
|
|
6593
|
+
const packMap = /* @__PURE__ */ new Map();
|
|
6594
|
+
for (const agent of agents2) {
|
|
6595
|
+
const installPath = resolveInstallPath(agent, {
|
|
6596
|
+
global: options.global ?? false
|
|
6597
|
+
});
|
|
6598
|
+
if (!installPath) {
|
|
6599
|
+
continue;
|
|
6600
|
+
}
|
|
6601
|
+
const metadata = await readMetadataAsync(installPath);
|
|
6602
|
+
for (const skill of metadata.skills) {
|
|
6603
|
+
if (skill.source.type !== "marketplace") {
|
|
6604
|
+
continue;
|
|
6605
|
+
}
|
|
6606
|
+
addSkillToPack(
|
|
6607
|
+
packMap,
|
|
6608
|
+
skill.source.slug,
|
|
6609
|
+
skill.source.versionId ?? skill.version,
|
|
6610
|
+
skill.name,
|
|
6611
|
+
agent,
|
|
6612
|
+
installPath
|
|
6613
|
+
);
|
|
6614
|
+
}
|
|
6615
|
+
}
|
|
6616
|
+
return [...packMap.values()];
|
|
6617
|
+
}
|
|
6618
|
+
async function marketplaceUpdateCommand(slug, options) {
|
|
6619
|
+
try {
|
|
6620
|
+
const installed = await findInstalledMarketplacePacks(options);
|
|
6621
|
+
if (installed.length === 0) {
|
|
6622
|
+
log.info("No marketplace packs installed.");
|
|
6623
|
+
return;
|
|
6624
|
+
}
|
|
6625
|
+
const toUpdate = slug ? installed.filter((p) => p.slug === slug) : installed;
|
|
6626
|
+
if (toUpdate.length === 0) {
|
|
6627
|
+
log.error(`Pack "${slug}" is not installed.`);
|
|
6628
|
+
process11.exit(1);
|
|
6629
|
+
}
|
|
6630
|
+
let updated = 0;
|
|
6631
|
+
for (const pack of toUpdate) {
|
|
6632
|
+
const agentIds = pack.agents.map((a) => a.agent.id).join(",");
|
|
6633
|
+
const isGlobal = options.global ?? false;
|
|
6634
|
+
await resolveAndInstallPack(pack.slug, options, {
|
|
6635
|
+
agents: agentIds,
|
|
6636
|
+
global: isGlobal
|
|
6637
|
+
});
|
|
6638
|
+
log.success(`Updated ${pack.slug}`);
|
|
6639
|
+
updated++;
|
|
6640
|
+
}
|
|
6641
|
+
if (updated === 0) {
|
|
6642
|
+
log.info("All packs are up to date.");
|
|
6643
|
+
}
|
|
6644
|
+
} catch (error) {
|
|
6645
|
+
log.error(
|
|
6646
|
+
error instanceof Error ? error.message : "Failed to update packs"
|
|
6647
|
+
);
|
|
6648
|
+
process11.exit(1);
|
|
6649
|
+
}
|
|
6650
|
+
}
|
|
6651
|
+
async function selectPacksToRemove(installed, slug, options) {
|
|
6652
|
+
if (slug) {
|
|
6653
|
+
const matched = installed.filter((p) => p.slug === slug);
|
|
6654
|
+
if (matched.length === 0) {
|
|
6655
|
+
throw new Error(`Pack "${slug}" is not installed.`);
|
|
6656
|
+
}
|
|
6657
|
+
return matched;
|
|
6658
|
+
}
|
|
6659
|
+
if (options.yes) {
|
|
6660
|
+
return installed;
|
|
6661
|
+
}
|
|
6662
|
+
const selected = await multiselect({
|
|
6663
|
+
message: "Select packs to remove:",
|
|
6664
|
+
options: installed.map((p) => ({
|
|
6665
|
+
value: p,
|
|
6666
|
+
label: p.slug,
|
|
6667
|
+
hint: `${p.skills.length} skill${p.skills.length === 1 ? "" : "s"}`
|
|
6668
|
+
})),
|
|
6669
|
+
initialValues: [],
|
|
6670
|
+
required: true
|
|
6671
|
+
});
|
|
6672
|
+
if (isCancel(selected)) {
|
|
6673
|
+
cancel("Remove cancelled.");
|
|
6674
|
+
process11.exit(0);
|
|
6675
|
+
}
|
|
6676
|
+
return selected;
|
|
6677
|
+
}
|
|
6678
|
+
async function removePackFiles(pack, options) {
|
|
6679
|
+
for (const { agent, installPath } of pack.agents) {
|
|
6680
|
+
for (const skillName of pack.skills) {
|
|
6681
|
+
const skillPath = resolve7(join13(installPath, skillName));
|
|
6682
|
+
if (!skillPath.startsWith(`${resolve7(installPath)}/`)) {
|
|
6683
|
+
continue;
|
|
6684
|
+
}
|
|
6685
|
+
await rm6(skillPath, { recursive: true, force: true });
|
|
6686
|
+
await removeFromMetadataAsync(installPath, skillName);
|
|
6687
|
+
}
|
|
6688
|
+
const hookConfigPath = resolveHookConfigPath(agent, {
|
|
6689
|
+
global: options.global ?? false
|
|
6690
|
+
});
|
|
6691
|
+
if (hookConfigPath) {
|
|
6692
|
+
await removeMarketplaceHooksBySourceAsync(hookConfigPath, pack.slug);
|
|
6693
|
+
}
|
|
6694
|
+
}
|
|
6695
|
+
}
|
|
6696
|
+
async function marketplaceRemoveCommand(slug, options) {
|
|
6697
|
+
try {
|
|
6698
|
+
const installed = await findInstalledMarketplacePacks(options);
|
|
6699
|
+
if (installed.length === 0) {
|
|
6700
|
+
log.info("No marketplace packs installed.");
|
|
6701
|
+
return;
|
|
6702
|
+
}
|
|
6703
|
+
const toRemove = await selectPacksToRemove(installed, slug, options);
|
|
6704
|
+
if (!options.yes) {
|
|
6705
|
+
const slugList = toRemove.map((p) => p.slug).join(", ");
|
|
6706
|
+
const confirmed = await confirm({
|
|
6707
|
+
message: `Remove ${toRemove.length} pack${toRemove.length === 1 ? "" : "s"} (${slugList})?`,
|
|
6708
|
+
initialValue: false
|
|
6709
|
+
});
|
|
6710
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
6711
|
+
cancel("Remove cancelled.");
|
|
6712
|
+
process11.exit(0);
|
|
6713
|
+
}
|
|
6714
|
+
}
|
|
6715
|
+
for (const pack of toRemove) {
|
|
6716
|
+
await removePackFiles(pack, options);
|
|
6717
|
+
log.success(`Removed ${pack.slug}`);
|
|
6718
|
+
}
|
|
6719
|
+
} catch (error) {
|
|
6720
|
+
log.error(
|
|
6721
|
+
error instanceof Error ? error.message : "Failed to remove packs"
|
|
6722
|
+
);
|
|
6723
|
+
process11.exit(1);
|
|
6425
6724
|
}
|
|
6426
6725
|
}
|
|
6427
6726
|
|
|
@@ -6429,15 +6728,15 @@ async function marketplaceInstallCommand(slug, options) {
|
|
|
6429
6728
|
init_esm_shims();
|
|
6430
6729
|
init_api();
|
|
6431
6730
|
init_tui();
|
|
6432
|
-
import
|
|
6731
|
+
import process12 from "process";
|
|
6433
6732
|
var writeJson4 = (value) => {
|
|
6434
|
-
|
|
6733
|
+
process12.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
6435
6734
|
`);
|
|
6436
6735
|
};
|
|
6437
6736
|
var exitWithError3 = (error) => {
|
|
6438
6737
|
const message = error instanceof Error ? error.message : String(error);
|
|
6439
6738
|
log.error(message);
|
|
6440
|
-
|
|
6739
|
+
process12.exit(1);
|
|
6441
6740
|
};
|
|
6442
6741
|
var fail2 = (message) => {
|
|
6443
6742
|
throw new Error(message);
|
|
@@ -6536,9 +6835,9 @@ async function profilesSetDefaultCommand(options) {
|
|
|
6536
6835
|
init_esm_shims();
|
|
6537
6836
|
init_api();
|
|
6538
6837
|
init_tui();
|
|
6539
|
-
import
|
|
6838
|
+
import process13 from "process";
|
|
6540
6839
|
var writeJson5 = (value) => {
|
|
6541
|
-
|
|
6840
|
+
process13.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
6542
6841
|
`);
|
|
6543
6842
|
};
|
|
6544
6843
|
var fail3 = (message) => {
|
|
@@ -6566,7 +6865,7 @@ var run3 = async (command, args, options) => {
|
|
|
6566
6865
|
var exitWithError4 = (error) => {
|
|
6567
6866
|
const message = error instanceof Error ? error.message : String(error);
|
|
6568
6867
|
log.error(message);
|
|
6569
|
-
|
|
6868
|
+
process13.exit(1);
|
|
6570
6869
|
};
|
|
6571
6870
|
async function projectsGetCommand(options) {
|
|
6572
6871
|
try {
|
|
@@ -6620,9 +6919,9 @@ async function projectsRemoveCommand(options) {
|
|
|
6620
6919
|
init_esm_shims();
|
|
6621
6920
|
init_api();
|
|
6622
6921
|
init_tui();
|
|
6623
|
-
import
|
|
6922
|
+
import process14 from "process";
|
|
6624
6923
|
var writeJson6 = (value) => {
|
|
6625
|
-
|
|
6924
|
+
process14.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
6626
6925
|
`);
|
|
6627
6926
|
};
|
|
6628
6927
|
var parseCsv3 = (input) => {
|
|
@@ -6635,7 +6934,7 @@ var parseCsv3 = (input) => {
|
|
|
6635
6934
|
var exitWithError5 = (error) => {
|
|
6636
6935
|
const message = error instanceof Error ? error.message : String(error);
|
|
6637
6936
|
log.error(message);
|
|
6638
|
-
|
|
6937
|
+
process14.exit(1);
|
|
6639
6938
|
};
|
|
6640
6939
|
var fail4 = (message) => {
|
|
6641
6940
|
throw new Error(message);
|
|
@@ -6722,9 +7021,9 @@ async function referencesReorderCommand(options) {
|
|
|
6722
7021
|
|
|
6723
7022
|
// src/commands/remove.ts
|
|
6724
7023
|
init_esm_shims();
|
|
6725
|
-
import { rm as
|
|
6726
|
-
import { join as
|
|
6727
|
-
import
|
|
7024
|
+
import { rm as rm7 } from "fs/promises";
|
|
7025
|
+
import { join as join14, resolve as resolve8 } from "path";
|
|
7026
|
+
import process15 from "process";
|
|
6728
7027
|
init_tui();
|
|
6729
7028
|
async function collectInstalledSkills(detectedAgents, options) {
|
|
6730
7029
|
const skillsToRemove = [];
|
|
@@ -6745,7 +7044,7 @@ async function collectInstalledSkills(detectedAgents, options) {
|
|
|
6745
7044
|
name: skill.name,
|
|
6746
7045
|
agentName: agent.name,
|
|
6747
7046
|
installPath,
|
|
6748
|
-
skillPath:
|
|
7047
|
+
skillPath: join14(installPath, skill.name)
|
|
6749
7048
|
});
|
|
6750
7049
|
}
|
|
6751
7050
|
}
|
|
@@ -6757,7 +7056,7 @@ async function selectSkillsToRemove(skillsToRemove, options) {
|
|
|
6757
7056
|
if (selected.length === 0) {
|
|
6758
7057
|
log.error(`Skill '${options.skill}' not found.`);
|
|
6759
7058
|
log.info("Run 'braid list' to see installed skills.");
|
|
6760
|
-
|
|
7059
|
+
process15.exit(1);
|
|
6761
7060
|
}
|
|
6762
7061
|
return selected;
|
|
6763
7062
|
}
|
|
@@ -6776,7 +7075,7 @@ async function selectSkillsToRemove(skillsToRemove, options) {
|
|
|
6776
7075
|
});
|
|
6777
7076
|
if (isCancel(result)) {
|
|
6778
7077
|
cancel("Remove cancelled.");
|
|
6779
|
-
|
|
7078
|
+
process15.exit(0);
|
|
6780
7079
|
}
|
|
6781
7080
|
return result;
|
|
6782
7081
|
}
|
|
@@ -6790,20 +7089,20 @@ async function confirmRemoval(selectedCount, options) {
|
|
|
6790
7089
|
});
|
|
6791
7090
|
if (isCancel(confirmed) || !confirmed) {
|
|
6792
7091
|
cancel("Remove cancelled.");
|
|
6793
|
-
|
|
7092
|
+
process15.exit(0);
|
|
6794
7093
|
}
|
|
6795
7094
|
}
|
|
6796
7095
|
async function removeSkill(skill, removeSpinner) {
|
|
6797
7096
|
removeSpinner.start(`Removing ${skill.name} from ${skill.agentName}...`);
|
|
6798
7097
|
try {
|
|
6799
|
-
const resolvedSkillPath =
|
|
6800
|
-
const resolvedInstallPath =
|
|
7098
|
+
const resolvedSkillPath = resolve8(skill.skillPath);
|
|
7099
|
+
const resolvedInstallPath = resolve8(skill.installPath);
|
|
6801
7100
|
if (!resolvedSkillPath.startsWith(`${resolvedInstallPath}/`)) {
|
|
6802
7101
|
removeSpinner.stop(`Unsafe path for ${skill.name}`);
|
|
6803
7102
|
log.warn(" Skill path escapes install directory, skipping.");
|
|
6804
7103
|
return false;
|
|
6805
7104
|
}
|
|
6806
|
-
await
|
|
7105
|
+
await rm7(resolvedSkillPath, { recursive: true, force: true });
|
|
6807
7106
|
await removeFromMetadataAsync(skill.installPath, skill.name);
|
|
6808
7107
|
removeSpinner.stop(`Removed ${skill.name} from ${skill.agentName}`);
|
|
6809
7108
|
return true;
|
|
@@ -6854,7 +7153,7 @@ async function removeCommand(options) {
|
|
|
6854
7153
|
removeSpinner.stop("Remove failed");
|
|
6855
7154
|
const message = error instanceof Error ? error.message : String(error);
|
|
6856
7155
|
log.error(message);
|
|
6857
|
-
|
|
7156
|
+
process15.exit(1);
|
|
6858
7157
|
}
|
|
6859
7158
|
}
|
|
6860
7159
|
|
|
@@ -7052,7 +7351,7 @@ async function rollbackCommand(source, options) {
|
|
|
7052
7351
|
init_esm_shims();
|
|
7053
7352
|
init_api();
|
|
7054
7353
|
init_tui();
|
|
7055
|
-
import
|
|
7354
|
+
import process16 from "process";
|
|
7056
7355
|
var parseCsv4 = (input) => {
|
|
7057
7356
|
if (!input) {
|
|
7058
7357
|
return void 0;
|
|
@@ -7061,13 +7360,13 @@ var parseCsv4 = (input) => {
|
|
|
7061
7360
|
return values.length > 0 ? values : void 0;
|
|
7062
7361
|
};
|
|
7063
7362
|
var writeJson7 = (value) => {
|
|
7064
|
-
|
|
7363
|
+
process16.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
7065
7364
|
`);
|
|
7066
7365
|
};
|
|
7067
7366
|
var exitWithError6 = (error) => {
|
|
7068
7367
|
const message = error instanceof Error ? error.message : String(error);
|
|
7069
7368
|
log.error(message);
|
|
7070
|
-
|
|
7369
|
+
process16.exit(1);
|
|
7071
7370
|
};
|
|
7072
7371
|
var fail5 = (message) => {
|
|
7073
7372
|
throw new Error(message);
|
|
@@ -7246,7 +7545,7 @@ async function rulesSyncNowCommand(options) {
|
|
|
7246
7545
|
|
|
7247
7546
|
// src/commands/scaffold.ts
|
|
7248
7547
|
init_esm_shims();
|
|
7249
|
-
import
|
|
7548
|
+
import process17 from "process";
|
|
7250
7549
|
|
|
7251
7550
|
// src/lib/scaffold.ts
|
|
7252
7551
|
init_esm_shims();
|
|
@@ -7256,11 +7555,11 @@ import {
|
|
|
7256
7555
|
mkdir as mkdir7,
|
|
7257
7556
|
readdir as readdir3,
|
|
7258
7557
|
readFile as readFile8,
|
|
7259
|
-
rm as
|
|
7558
|
+
rm as rm8,
|
|
7260
7559
|
stat,
|
|
7261
7560
|
writeFile as writeFile9
|
|
7262
7561
|
} from "fs/promises";
|
|
7263
|
-
import { dirname as
|
|
7562
|
+
import { dirname as dirname12, join as join15 } from "path";
|
|
7264
7563
|
var BRAID_PACK_FILENAME = "braid-pack.json";
|
|
7265
7564
|
var DEFAULT_TIMEOUT_MS = 3e5;
|
|
7266
7565
|
var MAX_DURATION_MS = 18e5;
|
|
@@ -7392,7 +7691,7 @@ var directoryContainsMatchingFile = async (absoluteDirectoryPath, matcher) => {
|
|
|
7392
7691
|
);
|
|
7393
7692
|
}
|
|
7394
7693
|
for (const entry of entries) {
|
|
7395
|
-
const absoluteEntryPath =
|
|
7694
|
+
const absoluteEntryPath = join15(absoluteDirectoryPath, entry.name);
|
|
7396
7695
|
if (entry.isDirectory()) {
|
|
7397
7696
|
if (await directoryContainsMatchingFile(absoluteEntryPath, matcher)) {
|
|
7398
7697
|
return true;
|
|
@@ -7448,19 +7747,19 @@ var directoryContainsHookArtifact = async (absoluteDirectoryPath) => directoryCo
|
|
|
7448
7747
|
}
|
|
7449
7748
|
);
|
|
7450
7749
|
var hasUnmanifestedPackContent = async (cwd) => {
|
|
7451
|
-
if (await manifestExists(
|
|
7750
|
+
if (await manifestExists(join15(cwd, "SKILL.md"))) {
|
|
7452
7751
|
return true;
|
|
7453
7752
|
}
|
|
7454
|
-
if (await directoryContainsSkillArtifact(
|
|
7753
|
+
if (await directoryContainsSkillArtifact(join15(cwd, "skills"))) {
|
|
7455
7754
|
return true;
|
|
7456
7755
|
}
|
|
7457
|
-
if (await directoryContainsAgentArtifact(
|
|
7756
|
+
if (await directoryContainsAgentArtifact(join15(cwd, "agents"))) {
|
|
7458
7757
|
return true;
|
|
7459
7758
|
}
|
|
7460
|
-
if (await directoryContainsHookArtifact(
|
|
7759
|
+
if (await directoryContainsHookArtifact(join15(cwd, "hooks"))) {
|
|
7461
7760
|
return true;
|
|
7462
7761
|
}
|
|
7463
|
-
return directoryContainsWorkflowArtifact(
|
|
7762
|
+
return directoryContainsWorkflowArtifact(join15(cwd, "workflows"));
|
|
7464
7763
|
};
|
|
7465
7764
|
var parseManifestEntries = (manifest, key, parser) => {
|
|
7466
7765
|
const value = manifest[key];
|
|
@@ -7986,7 +8285,7 @@ var writeTextFile3 = async (absolutePath, relativePath, content) => {
|
|
|
7986
8285
|
var restoreManifest = async (absoluteManifestPath, previousContent) => {
|
|
7987
8286
|
try {
|
|
7988
8287
|
if (previousContent === void 0) {
|
|
7989
|
-
await
|
|
8288
|
+
await rm8(absoluteManifestPath, { force: true });
|
|
7990
8289
|
return;
|
|
7991
8290
|
}
|
|
7992
8291
|
await writeFile9(absoluteManifestPath, previousContent, "utf-8");
|
|
@@ -8010,8 +8309,8 @@ var prepareScaffoldOperation = async (normalizedInput) => {
|
|
|
8010
8309
|
normalizedInput.type,
|
|
8011
8310
|
normalizedInput.name
|
|
8012
8311
|
);
|
|
8013
|
-
const absoluteManifestPath =
|
|
8014
|
-
const absoluteArtifactPath =
|
|
8312
|
+
const absoluteManifestPath = join15(normalizedInput.cwd, BRAID_PACK_FILENAME);
|
|
8313
|
+
const absoluteArtifactPath = join15(normalizedInput.cwd, filePath);
|
|
8015
8314
|
const manifestKey = MANIFEST_KEY_BY_TYPE[normalizedInput.type];
|
|
8016
8315
|
const previousManifestContent = context.state === "manifest-pack" ? await readManifestFile(absoluteManifestPath) : void 0;
|
|
8017
8316
|
const existingEntry = context.manifest[manifestKey].find(
|
|
@@ -8063,7 +8362,7 @@ var writeArtifactWithRollback = async ({
|
|
|
8063
8362
|
previousManifestContent
|
|
8064
8363
|
}) => {
|
|
8065
8364
|
try {
|
|
8066
|
-
await mkdir7(
|
|
8365
|
+
await mkdir7(dirname12(absoluteArtifactPath), { recursive: true });
|
|
8067
8366
|
await writeTextFile3(absoluteArtifactPath, filePath, artifactContent);
|
|
8068
8367
|
} catch (error) {
|
|
8069
8368
|
const artifactError = error instanceof ScaffoldError ? error : toIoError(filePath, error);
|
|
@@ -8090,10 +8389,10 @@ var ScaffoldError = class extends Error {
|
|
|
8090
8389
|
}
|
|
8091
8390
|
};
|
|
8092
8391
|
var inspectScaffoldDirectory = async (cwd) => {
|
|
8093
|
-
const manifestPath =
|
|
8392
|
+
const manifestPath = join15(cwd, BRAID_PACK_FILENAME);
|
|
8094
8393
|
const hasManifest = await manifestExists(manifestPath);
|
|
8095
8394
|
if (!hasManifest) {
|
|
8096
|
-
if (await manifestExists(
|
|
8395
|
+
if (await manifestExists(join15(cwd, "SKILL.md"))) {
|
|
8097
8396
|
throw new ScaffoldError(
|
|
8098
8397
|
"invalid_repo_state",
|
|
8099
8398
|
"Invalid repo state: root SKILL.md requires migration to braid-pack.json before scaffolding."
|
|
@@ -8206,11 +8505,11 @@ var normalizeReferenceList = (referenceLabel, availableNamesLabel, values, avail
|
|
|
8206
8505
|
};
|
|
8207
8506
|
var exitCancelled2 = () => {
|
|
8208
8507
|
cancel("Scaffold cancelled.");
|
|
8209
|
-
|
|
8508
|
+
process17.exit(0);
|
|
8210
8509
|
};
|
|
8211
8510
|
var exitWithError7 = (message) => {
|
|
8212
8511
|
log.error(message);
|
|
8213
|
-
|
|
8512
|
+
process17.exit(1);
|
|
8214
8513
|
};
|
|
8215
8514
|
var requirePromptValue = (value) => {
|
|
8216
8515
|
if (isCancel(value)) {
|
|
@@ -8339,7 +8638,7 @@ var resolveOptionalReference = async (label, flagValue, options, availableNames)
|
|
|
8339
8638
|
return selected || void 0;
|
|
8340
8639
|
};
|
|
8341
8640
|
var buildScaffoldInput = async (options) => {
|
|
8342
|
-
const context = await inspectScaffoldDirectory(
|
|
8641
|
+
const context = await inspectScaffoldDirectory(process17.cwd());
|
|
8343
8642
|
const availableSkillNames = context.manifest.skills.map(
|
|
8344
8643
|
(entry) => entry.name
|
|
8345
8644
|
);
|
|
@@ -8393,7 +8692,7 @@ var buildScaffoldInput = async (options) => {
|
|
|
8393
8692
|
availableWorkflowNames
|
|
8394
8693
|
) : void 0;
|
|
8395
8694
|
return {
|
|
8396
|
-
cwd:
|
|
8695
|
+
cwd: process17.cwd(),
|
|
8397
8696
|
type,
|
|
8398
8697
|
name,
|
|
8399
8698
|
title,
|
|
@@ -8485,8 +8784,8 @@ init_scope();
|
|
|
8485
8784
|
|
|
8486
8785
|
// src/commands/update.ts
|
|
8487
8786
|
init_esm_shims();
|
|
8488
|
-
import { rm as
|
|
8489
|
-
import { join as
|
|
8787
|
+
import { rm as rm9 } from "fs/promises";
|
|
8788
|
+
import { join as join16, resolve as resolve9 } from "path";
|
|
8490
8789
|
import {
|
|
8491
8790
|
cancel as cancel2,
|
|
8492
8791
|
isCancel as isCancel2,
|
|
@@ -8631,12 +8930,12 @@ var areSameSourceProjects = (left, right) => {
|
|
|
8631
8930
|
};
|
|
8632
8931
|
var isSameInstalledSource = (source, target) => source.type === target.type && source.name === target.name && areSameSourceProjects(source.orgProjects, target.orgProjects) && areSameSourceProjects(source.personalProjects, target.personalProjects);
|
|
8633
8932
|
var removeInstalledBundle = async (installPath, bundleName) => {
|
|
8634
|
-
const resolvedInstallPath =
|
|
8635
|
-
const resolvedBundlePath =
|
|
8933
|
+
const resolvedInstallPath = resolve9(installPath);
|
|
8934
|
+
const resolvedBundlePath = resolve9(join16(installPath, bundleName));
|
|
8636
8935
|
if (!resolvedBundlePath.startsWith(`${resolvedInstallPath}/`)) {
|
|
8637
8936
|
throw new Error(`Unsafe bundle path for ${bundleName}`);
|
|
8638
8937
|
}
|
|
8639
|
-
await
|
|
8938
|
+
await rm9(resolvedBundlePath, { recursive: true, force: true });
|
|
8640
8939
|
const disabledRecord = await findDisabledBundleByOriginalPathAsync(
|
|
8641
8940
|
resolvedBundlePath,
|
|
8642
8941
|
{
|
|
@@ -8954,6 +9253,11 @@ marketplace.command("install").description("Install a marketplace pack by slug")
|
|
|
8954
9253
|
"--allow-hooks",
|
|
8955
9254
|
"Allow marketplace packs to install executable Claude Code hooks"
|
|
8956
9255
|
).option("-y, --yes", "Skip confirmation prompts").action((slug, options) => marketplaceInstallCommand(slug, options));
|
|
9256
|
+
marketplace.command("update").description("Update installed marketplace packs to their latest version").argument("[slug]", "Pack slug (updates all if omitted)").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("-g, --global", "Update packs in global agent directories").option(
|
|
9257
|
+
"--allow-hooks",
|
|
9258
|
+
"Allow marketplace packs to install executable Claude Code hooks"
|
|
9259
|
+
).option("-y, --yes", "Skip confirmation prompts").action((slug, options) => marketplaceUpdateCommand(slug, options));
|
|
9260
|
+
marketplace.command("remove").description("Remove installed marketplace packs").argument("[slug]", "Pack slug (prompts for selection if omitted)").option("-g, --global", "Remove from global agent directories").option("-y, --yes", "Skip confirmation prompts").action((slug, options) => marketplaceRemoveCommand(slug, options));
|
|
8957
9261
|
var projects = program.command("projects").description("Discover available projects from braid");
|
|
8958
9262
|
projects.command("list").description("List available personal and org projects").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsListCommand);
|
|
8959
9263
|
projects.command("get").description("Get a project by id").requiredOption("--id <id>", "Project ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsGetCommand);
|