@baton-dx/cli 0.4.2 → 0.4.3
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/dist/{create-W7AYGROv.mjs → create-C1zm03eE.mjs} +2 -2
- package/dist/{create-W7AYGROv.mjs.map → create-C1zm03eE.mjs.map} +1 -1
- package/dist/index.mjs +90 -8
- package/dist/index.mjs.map +1 -1
- package/dist/{list-D5O_m1e5.mjs → list-BHFeSiTO.mjs} +2 -2
- package/dist/{list-D5O_m1e5.mjs.map → list-BHFeSiTO.mjs.map} +1 -1
- package/dist/{src-BPYdPWlV.mjs → src-YrWWPWNR.mjs} +114 -24
- package/dist/src-YrWWPWNR.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/src-BPYdPWlV.mjs.map +0 -1
- package/dist/templates/profile/minimal/ai/memory/CLAUDE.md +0 -3
- package/dist/templates/profile/team/ai/memory/CLAUDE.md +0 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { c as Ve, h as defineCommand, i as Le, l as We, n as isInSourceRepo } from "./context-detection-DdbrKid3.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { N as discoverProfilesInSourceRepo } from "./src-YrWWPWNR.mjs";
|
|
4
4
|
import "./ai-tool-detection-CMsBNa9e.mjs";
|
|
5
5
|
import "./esm-BagM-kVd.mjs";
|
|
6
6
|
|
|
@@ -53,4 +53,4 @@ Note: Must be run from a source repository (directory with baton.source.yaml)`
|
|
|
53
53
|
|
|
54
54
|
//#endregion
|
|
55
55
|
export { profileListCommand };
|
|
56
|
-
//# sourceMappingURL=list-
|
|
56
|
+
//# sourceMappingURL=list-BHFeSiTO.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-
|
|
1
|
+
{"version":3,"file":"list-BHFeSiTO.mjs","names":[],"sources":["../src/commands/profile/list.ts"],"sourcesContent":["import { discoverProfilesInSourceRepo } from \"@baton-dx/core\";\nimport * as p from \"@clack/prompts\";\nimport { defineCommand } from \"citty\";\nimport { isInSourceRepo } from \"../../utils/context-detection.js\";\n\nexport const profileListCommand = defineCommand({\n meta: {\n name: \"profile list\",\n description: `List all profiles in the current source repository\n\nShows a table of all profiles with:\n - Profile name (root profile marked with \"(root)\")\n - Version from baton.profile.yaml\n - Description from profile manifest\n\nExamples:\n baton profile list\n\nNote: Must be run from a source repository (directory with baton.source.yaml)`,\n },\n run: async () => {\n p.intro(\"List Profiles\");\n\n // Check if we're in a source repo\n const inSourceRepo = await isInSourceRepo();\n if (!inSourceRepo) {\n p.outro(\n \"Error: Not in a source repository. Run this command from a directory containing baton.source.yaml\",\n );\n process.exit(1);\n }\n\n const cwd = process.cwd();\n\n // Discover all profiles in the profiles/ directory\n const profiles = await discoverProfilesInSourceRepo(cwd);\n\n if (profiles.length === 0) {\n p.outro(\"No profiles found.\");\n process.exit(0);\n }\n\n // Build table output\n const lines: string[] = [];\n lines.push(\"┌─────────────────────┬─────────┬────────────────────────────────────┐\");\n lines.push(\"│ Name │ Version │ Description │\");\n lines.push(\"├─────────────────────┼─────────┼────────────────────────────────────┤\");\n\n for (const profile of profiles) {\n const name = profile.name;\n const version = profile.version || \"-\";\n const description = profile.description || \"-\";\n\n // Pad columns to fixed width\n const namePadded = name.padEnd(19);\n const versionPadded = version.padEnd(7);\n const descPadded = description.padEnd(34);\n\n lines.push(`│ ${namePadded} │ ${versionPadded} │ ${descPadded} │`);\n }\n\n lines.push(\"└─────────────────────┴─────────┴────────────────────────────────────┘\");\n\n p.note(lines.join(\"\\n\"), \"Profiles\");\n p.outro(`Found ${profiles.length} profile${profiles.length === 1 ? \"\" : \"s\"}`);\n process.exit(0);\n },\n});\n"],"mappings":";;;;;;;AAKA,MAAa,qBAAqB,cAAc;CAC9C,MAAM;EACJ,MAAM;EACN,aAAa;;;;;;;;;;;EAWd;CACD,KAAK,YAAY;AACf,KAAQ,gBAAgB;AAIxB,MAAI,CADiB,MAAM,gBAAgB,EACxB;AACjB,MACE,oGACD;AACD,WAAQ,KAAK,EAAE;;EAMjB,MAAM,WAAW,MAAM,6BAHX,QAAQ,KAAK,CAG+B;AAExD,MAAI,SAAS,WAAW,GAAG;AACzB,MAAQ,qBAAqB;AAC7B,WAAQ,KAAK,EAAE;;EAIjB,MAAM,QAAkB,EAAE;AAC1B,QAAM,KAAK,yEAAyE;AACpF,QAAM,KAAK,yEAAyE;AACpF,QAAM,KAAK,yEAAyE;AAEpF,OAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,OAAO,QAAQ;GACrB,MAAM,UAAU,QAAQ,WAAW;GACnC,MAAM,cAAc,QAAQ,eAAe;GAG3C,MAAM,aAAa,KAAK,OAAO,GAAG;GAClC,MAAM,gBAAgB,QAAQ,OAAO,EAAE;GACvC,MAAM,aAAa,YAAY,OAAO,GAAG;AAEzC,SAAM,KAAK,KAAK,WAAW,KAAK,cAAc,KAAK,WAAW,IAAI;;AAGpE,QAAM,KAAK,yEAAyE;AAEpF,KAAO,MAAM,KAAK,KAAK,EAAE,WAAW;AACpC,KAAQ,SAAS,SAAS,OAAO,UAAU,SAAS,WAAW,IAAI,KAAK,MAAM;AAC9E,UAAQ,KAAK,EAAE;;CAElB,CAAC"}
|
|
@@ -4815,22 +4815,55 @@ async function isCacheValid(cachePath) {
|
|
|
4815
4815
|
}
|
|
4816
4816
|
}
|
|
4817
4817
|
/**
|
|
4818
|
+
* Checks if a cached repository is stale based on FETCH_HEAD or HEAD mtime.
|
|
4819
|
+
* Falls back to .git/HEAD if FETCH_HEAD does not exist.
|
|
4820
|
+
*/
|
|
4821
|
+
async function isCacheStale(cachePath, maxAgeMs) {
|
|
4822
|
+
try {
|
|
4823
|
+
const fetchHeadStat = await stat(join(cachePath, ".git", "FETCH_HEAD"));
|
|
4824
|
+
return Date.now() - fetchHeadStat.mtimeMs > maxAgeMs;
|
|
4825
|
+
} catch {
|
|
4826
|
+
try {
|
|
4827
|
+
const headStat = await stat(join(cachePath, ".git", "HEAD"));
|
|
4828
|
+
return Date.now() - headStat.mtimeMs > maxAgeMs;
|
|
4829
|
+
} catch {
|
|
4830
|
+
return true;
|
|
4831
|
+
}
|
|
4832
|
+
}
|
|
4833
|
+
}
|
|
4834
|
+
/**
|
|
4818
4835
|
* Clones a Git repository with shallow clone and optional sparse checkout
|
|
4819
4836
|
*/
|
|
4820
4837
|
async function cloneGitSource(options) {
|
|
4821
|
-
const { url, ref, subpath, useCache = true } = options;
|
|
4838
|
+
const { url, ref, subpath, useCache = true, maxCacheAgeMs } = options;
|
|
4822
4839
|
const cachePath = getCachePath(url, ref);
|
|
4823
4840
|
if (useCache && await isCacheValid(cachePath)) {
|
|
4824
4841
|
const git = esm_default(cachePath);
|
|
4825
4842
|
try {
|
|
4826
|
-
try {
|
|
4843
|
+
if (maxCacheAgeMs !== void 0 && await isCacheStale(cachePath, maxCacheAgeMs)) try {
|
|
4844
|
+
await git.fetch(["--depth=1", "origin"]);
|
|
4845
|
+
await git.raw([
|
|
4846
|
+
"reset",
|
|
4847
|
+
"--hard",
|
|
4848
|
+
`origin/${ref || "HEAD"}`
|
|
4849
|
+
]);
|
|
4850
|
+
} catch {
|
|
4851
|
+
try {
|
|
4852
|
+
await git.pull(["--depth=1"]);
|
|
4853
|
+
} catch {
|
|
4854
|
+
console.warn(`[baton] Network unavailable, using stale cache for ${url}`);
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4857
|
+
else try {
|
|
4827
4858
|
await git.pull(["--depth=1"]);
|
|
4828
4859
|
} catch {}
|
|
4829
4860
|
const sha = await git.revparse(["HEAD"]);
|
|
4830
4861
|
return {
|
|
4831
4862
|
localPath: subpath ? join(cachePath, subpath) : cachePath,
|
|
4832
4863
|
fromCache: true,
|
|
4833
|
-
sha: sha.trim()
|
|
4864
|
+
sha: sha.trim(),
|
|
4865
|
+
cachePath,
|
|
4866
|
+
sparseCheckout: !!subpath
|
|
4834
4867
|
};
|
|
4835
4868
|
} catch (error) {
|
|
4836
4869
|
throw new GitSourceError(`Failed to read cached repository: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
@@ -4873,12 +4906,25 @@ async function cloneGitSource(options) {
|
|
|
4873
4906
|
return {
|
|
4874
4907
|
localPath: subpath ? join(cachePath, subpath) : cachePath,
|
|
4875
4908
|
fromCache: false,
|
|
4876
|
-
sha: sha.trim()
|
|
4909
|
+
sha: sha.trim(),
|
|
4910
|
+
cachePath,
|
|
4911
|
+
sparseCheckout: !!subpath
|
|
4877
4912
|
};
|
|
4878
4913
|
} catch (error) {
|
|
4879
4914
|
throw new GitSourceError(`Failed to clone Git repository from ${url}: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
4880
4915
|
}
|
|
4881
4916
|
}
|
|
4917
|
+
/**
|
|
4918
|
+
* Expands sparse-checkout in a cached repository to include additional paths.
|
|
4919
|
+
* Uses 'git sparse-checkout add' to preserve existing checkout paths.
|
|
4920
|
+
*/
|
|
4921
|
+
async function expandSparseCheckout(cachePath, additionalPaths) {
|
|
4922
|
+
await esm_default(cachePath).raw([
|
|
4923
|
+
"sparse-checkout",
|
|
4924
|
+
"add",
|
|
4925
|
+
...additionalPaths
|
|
4926
|
+
]);
|
|
4927
|
+
}
|
|
4882
4928
|
|
|
4883
4929
|
//#endregion
|
|
4884
4930
|
//#region ../core/src/sources/npm-resolver.ts
|
|
@@ -6487,22 +6533,31 @@ async function removePlacedFiles(filePaths, projectRoot) {
|
|
|
6487
6533
|
//#region ../core/src/sources/load-profile-safe.ts
|
|
6488
6534
|
/**
|
|
6489
6535
|
* Loads and parses a profile manifest from a given path within a source repository.
|
|
6490
|
-
* Returns null if the file doesn't exist
|
|
6536
|
+
* Returns null if the file doesn't exist (ENOENT). Logs a warning for schema
|
|
6537
|
+
* validation errors and other failures so they are visible to the user.
|
|
6491
6538
|
*
|
|
6492
6539
|
* @param sourceRoot - Absolute path to the source repository root
|
|
6493
6540
|
* @param profilePath - Relative path to the profile (e.g., "profiles/frontend")
|
|
6494
6541
|
* @returns Parsed manifest summary or null
|
|
6495
6542
|
*/
|
|
6496
6543
|
async function loadProfileManifestSafe(sourceRoot, profilePath) {
|
|
6544
|
+
const manifestPath = join(sourceRoot, profilePath, "baton.profile.yaml");
|
|
6497
6545
|
try {
|
|
6498
|
-
const parsed = (0, import_dist.parse)(await readFile(
|
|
6546
|
+
const parsed = (0, import_dist.parse)(await readFile(manifestPath, "utf-8"));
|
|
6499
6547
|
const manifest = profileManifestSchema.parse(parsed);
|
|
6500
6548
|
return {
|
|
6501
6549
|
name: manifest.name,
|
|
6502
6550
|
version: manifest.version,
|
|
6503
6551
|
description: manifest.description
|
|
6504
6552
|
};
|
|
6505
|
-
} catch {
|
|
6553
|
+
} catch (error) {
|
|
6554
|
+
if (error.code === "ENOENT" || error instanceof Error && error.message.includes("ENOENT")) return null;
|
|
6555
|
+
if (error instanceof ZodError) {
|
|
6556
|
+
const issues = error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
6557
|
+
console.warn(`Warning: Invalid profile manifest at ${manifestPath}:\n${issues}`);
|
|
6558
|
+
return null;
|
|
6559
|
+
}
|
|
6560
|
+
console.warn(`Warning: Could not load profile manifest at ${manifestPath}: ${error instanceof Error ? error.message : error}`);
|
|
6506
6561
|
return null;
|
|
6507
6562
|
}
|
|
6508
6563
|
}
|
|
@@ -6706,11 +6761,12 @@ const MAX_CHAIN_DEPTH = 10;
|
|
|
6706
6761
|
* @param manifest - Root profile manifest
|
|
6707
6762
|
* @param source - Source URL or path of root profile
|
|
6708
6763
|
* @param baseDir - Base directory for resolving relative paths
|
|
6764
|
+
* @param cloneContext - Optional clone context for sparse-checkout expansion
|
|
6709
6765
|
* @returns Array of resolved profiles in merge order (base first, overrides last)
|
|
6710
6766
|
*/
|
|
6711
|
-
async function resolveProfileChain(manifest, source, baseDir) {
|
|
6767
|
+
async function resolveProfileChain(manifest, source, baseDir, cloneContext) {
|
|
6712
6768
|
const chain = [];
|
|
6713
|
-
await resolveChainRecursive(manifest, source, baseDir, chain, /* @__PURE__ */ new Set(), []);
|
|
6769
|
+
await resolveChainRecursive(manifest, source, baseDir, chain, /* @__PURE__ */ new Set(), [], void 0, cloneContext);
|
|
6714
6770
|
return chain;
|
|
6715
6771
|
}
|
|
6716
6772
|
/**
|
|
@@ -6723,19 +6779,22 @@ async function resolveProfileChain(manifest, source, baseDir) {
|
|
|
6723
6779
|
* @param visited - Set of visited sources (for circular detection)
|
|
6724
6780
|
* @param path - Current path (for error messages)
|
|
6725
6781
|
* @param localPath - Resolved local directory path for this profile
|
|
6782
|
+
* @param cloneContext - Optional clone context for sparse-checkout expansion
|
|
6726
6783
|
*/
|
|
6727
|
-
async function resolveChainRecursive(manifest, source, baseDir, chain, visited, path, localPath) {
|
|
6784
|
+
async function resolveChainRecursive(manifest, source, baseDir, chain, visited, path, localPath, cloneContext) {
|
|
6728
6785
|
if (path.length >= MAX_CHAIN_DEPTH) throw new Error(`Profile inheritance chain exceeds maximum depth of ${MAX_CHAIN_DEPTH}. Chain: ${path.join(" -> ")} -> ${manifest.name}`);
|
|
6729
6786
|
if (visited.has(source)) throw new CircularInheritanceError(`Circular profile inheritance detected: ${[...path, manifest.name].join(" -> ")}`);
|
|
6730
6787
|
const currentVisited = new Set(visited);
|
|
6731
6788
|
currentVisited.add(source);
|
|
6732
6789
|
path.push(manifest.name);
|
|
6733
6790
|
if (manifest.extends && manifest.extends.length > 0) for (const extendSource of manifest.extends) try {
|
|
6734
|
-
const { manifest: parentManifest, localPath: parentLocalPath } = await loadProfileFromSource(extendSource, baseDir);
|
|
6735
|
-
await resolveChainRecursive(parentManifest, extendSource, baseDir, chain, currentVisited, [...path], parentLocalPath);
|
|
6791
|
+
const { manifest: parentManifest, localPath: parentLocalPath } = await loadProfileFromSource(extendSource, baseDir, cloneContext);
|
|
6792
|
+
await resolveChainRecursive(parentManifest, extendSource, baseDir, chain, currentVisited, [...path], parentLocalPath, cloneContext);
|
|
6736
6793
|
} catch (error) {
|
|
6737
6794
|
if (error instanceof CircularInheritanceError) throw error;
|
|
6738
6795
|
if (error instanceof Error && error.message.includes("exceeds maximum depth")) throw error;
|
|
6796
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
6797
|
+
throw new Error(`Failed to resolve extends '${extendSource}' from profile '${manifest.name}': ${cause}`);
|
|
6739
6798
|
}
|
|
6740
6799
|
chain.push({
|
|
6741
6800
|
manifest,
|
|
@@ -6748,25 +6807,55 @@ async function resolveChainRecursive(manifest, source, baseDir, chain, visited,
|
|
|
6748
6807
|
/**
|
|
6749
6808
|
* Load a profile from a source (Git URL or local path)
|
|
6750
6809
|
*
|
|
6810
|
+
* When operating inside a sparse-checkout repo and the profile is not found,
|
|
6811
|
+
* expands the sparse-checkout to include the profile path and retries.
|
|
6812
|
+
*
|
|
6751
6813
|
* @param source - Source URL or path
|
|
6752
6814
|
* @param baseDir - Base directory for resolving relative paths
|
|
6815
|
+
* @param cloneContext - Optional clone context for sparse-checkout expansion
|
|
6753
6816
|
* @returns Loaded profile manifest and resolved local directory path
|
|
6754
6817
|
*/
|
|
6755
|
-
async function loadProfileFromSource(source, baseDir) {
|
|
6818
|
+
async function loadProfileFromSource(source, baseDir, cloneContext) {
|
|
6756
6819
|
const parsed = parseSource(source);
|
|
6757
6820
|
if (parsed.provider === "local") {
|
|
6758
6821
|
const absolutePath = resolve(baseDir, parsed.path);
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6822
|
+
const manifestPath = resolve(absolutePath, "baton.profile.yaml");
|
|
6823
|
+
try {
|
|
6824
|
+
return {
|
|
6825
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6826
|
+
localPath: absolutePath
|
|
6827
|
+
};
|
|
6828
|
+
} catch (error) {
|
|
6829
|
+
if (error instanceof FileNotFoundError && cloneContext?.sparseCheckout) {
|
|
6830
|
+
const relativePath = relative(cloneContext.cachePath, absolutePath);
|
|
6831
|
+
await expandSparseCheckout(cloneContext.cachePath, [relativePath]);
|
|
6832
|
+
return {
|
|
6833
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6834
|
+
localPath: absolutePath
|
|
6835
|
+
};
|
|
6836
|
+
}
|
|
6837
|
+
throw error;
|
|
6838
|
+
}
|
|
6763
6839
|
}
|
|
6764
6840
|
if (parsed.provider === "file") {
|
|
6765
6841
|
const absolutePath = parsed.path.startsWith("/") ? parsed.path : resolve(baseDir, parsed.path);
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6842
|
+
const manifestPath = resolve(absolutePath, "baton.profile.yaml");
|
|
6843
|
+
try {
|
|
6844
|
+
return {
|
|
6845
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6846
|
+
localPath: absolutePath
|
|
6847
|
+
};
|
|
6848
|
+
} catch (error) {
|
|
6849
|
+
if (error instanceof FileNotFoundError && cloneContext?.sparseCheckout) {
|
|
6850
|
+
const relativePath = relative(cloneContext.cachePath, absolutePath);
|
|
6851
|
+
await expandSparseCheckout(cloneContext.cachePath, [relativePath]);
|
|
6852
|
+
return {
|
|
6853
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6854
|
+
localPath: absolutePath
|
|
6855
|
+
};
|
|
6856
|
+
}
|
|
6857
|
+
throw error;
|
|
6858
|
+
}
|
|
6770
6859
|
}
|
|
6771
6860
|
if (parsed.provider === "npm") throw new Error("NPM sources are not yet implemented in inheritance chain");
|
|
6772
6861
|
const subpath = parsed.provider !== "git" ? parsed.subpath : void 0;
|
|
@@ -14411,7 +14500,8 @@ const globalConfigSchema = objectType({
|
|
|
14411
14500
|
]).default("deep")
|
|
14412
14501
|
}).optional(),
|
|
14413
14502
|
ai: objectType({ tools: arrayType(stringType()).optional().default([]) }).optional(),
|
|
14414
|
-
ide: objectType({ platforms: arrayType(stringType()).optional().default([]) }).optional()
|
|
14503
|
+
ide: objectType({ platforms: arrayType(stringType()).optional().default([]) }).optional(),
|
|
14504
|
+
sync: objectType({ cacheTtlHours: numberType().default(24) }).optional()
|
|
14415
14505
|
});
|
|
14416
14506
|
|
|
14417
14507
|
//#endregion
|
|
@@ -14788,5 +14878,5 @@ async function resolvePreferences(projectRoot) {
|
|
|
14788
14878
|
}
|
|
14789
14879
|
|
|
14790
14880
|
//#endregion
|
|
14791
|
-
export {
|
|
14792
|
-
//# sourceMappingURL=src-
|
|
14881
|
+
export { loadLockfile as $, resolveProfileChain as A, cloneGitSource as B, mergeSkills as C, sortProfilesByWeight as D, isLockedProfile as E, removePlacedFiles as F, getIdePlatformTargetDir as G, ensureBatonDirGitignored as H, generateLock as I, isKnownIdePlatform as J, getRegisteredIdePlatforms as K, readLock as L, placeFile as M, discoverProfilesInSourceRepo as N, mergeContentParts as O, findSourceManifest as P, parseSource as Q, writeLock as R, mergeRulesWithWarnings as S, getProfileWeight as T, removeGitignoreManagedSection as U, collectComprehensivePatterns as V, updateGitignore as W, getAllAIToolAdapters as X, getAIToolAdaptersForKeys as Y, parseFrontmatter as Z, require_lib as _, clearIdeCache as a, getAIToolConfig as at, mergeAgentsWithWarnings as b, getDefaultGlobalSource as c, getGlobalSources as d, loadProfileManifest as et, loadGlobalConfig as f, setGlobalIdePlatforms as g, setGlobalAiTools as h, computeIntersection as i, SourceParseError as it, detectLegacyPaths as j, resolveProfileSupport as k, getGlobalAiTools as l, saveGlobalConfig as m, readProjectPreferences as n, KEBAB_CASE_REGEX as nt, detectInstalledIdes as o, getAIToolPath as ot, removeGlobalSource as p, idePlatformRegistry as q, writeProjectPreferences as r, FileNotFoundError as rt, addGlobalSource as s, getAllAIToolKeys as st, resolvePreferences as t, loadProjectManifest as tt, getGlobalIdePlatforms as u, mergeMemory as v, mergeSkillsWithWarnings as w, mergeRules as x, mergeMemoryWithWarnings as y, resolveVersion as z };
|
|
14882
|
+
//# sourceMappingURL=src-YrWWPWNR.mjs.map
|