@baton-dx/cli 0.4.2 → 0.4.4
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/{context-detection-DdbrKid3.mjs → context-detection-Ddu0mj_K.mjs} +17 -17
- package/dist/context-detection-Ddu0mj_K.mjs.map +1 -0
- package/dist/{create-W7AYGROv.mjs → create-DEZA3dPb.mjs} +3 -3
- package/dist/{create-W7AYGROv.mjs.map → create-DEZA3dPb.mjs.map} +1 -1
- package/dist/index.mjs +92 -10
- package/dist/index.mjs.map +1 -1
- package/dist/{list-D5O_m1e5.mjs → list-BT2zFAVc.mjs} +3 -3
- package/dist/{list-D5O_m1e5.mjs.map → list-BT2zFAVc.mjs.map} +1 -1
- package/dist/{prompt-B0zuVo8N.mjs → prompt-DtgNNhRW.mjs} +8 -8
- package/dist/{prompt-B0zuVo8N.mjs.map → prompt-DtgNNhRW.mjs.map} +1 -1
- package/dist/{remove-iaf_gkie.mjs → remove-BBFBYUPy.mjs} +2 -2
- package/dist/{remove-iaf_gkie.mjs.map → remove-BBFBYUPy.mjs.map} +1 -1
- package/dist/{src-BPYdPWlV.mjs → src-dY02psbw.mjs} +129 -30
- package/dist/src-dY02psbw.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/context-detection-DdbrKid3.mjs.map +0 -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 { n as __require, r as __toESM, t as __commonJSMin } from "./chunk-BbwQpWto.mjs";
|
|
3
|
-
import { m as require_dist } from "./context-detection-
|
|
3
|
+
import { m as require_dist } from "./context-detection-Ddu0mj_K.mjs";
|
|
4
4
|
import { i as AI_TOOL_PATHS, r as evaluateDetection } from "./ai-tool-detection-CMsBNa9e.mjs";
|
|
5
5
|
import { d as esm_default, m as simpleGit } from "./esm-BagM-kVd.mjs";
|
|
6
6
|
import { access, mkdir, readFile, readdir, rm, rmdir, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
@@ -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);
|
|
@@ -4852,11 +4885,20 @@ async function cloneGitSource(options) {
|
|
|
4852
4885
|
const git = esm_default();
|
|
4853
4886
|
try {
|
|
4854
4887
|
const cloneOptions = ["--depth=1"];
|
|
4855
|
-
|
|
4888
|
+
const isSha = ref && /^[0-9a-f]{7,40}$/i.test(ref);
|
|
4889
|
+
if (ref && !isSha && ref !== "main" && ref !== "master") cloneOptions.push("--branch", ref);
|
|
4856
4890
|
if (subpath) cloneOptions.push("--no-checkout");
|
|
4857
4891
|
await git.clone(url, cachePath, cloneOptions);
|
|
4892
|
+
const repoGit = esm_default(cachePath);
|
|
4893
|
+
if (isSha) {
|
|
4894
|
+
await repoGit.fetch([
|
|
4895
|
+
"--depth=1",
|
|
4896
|
+
"origin",
|
|
4897
|
+
ref
|
|
4898
|
+
]);
|
|
4899
|
+
await repoGit.checkout("FETCH_HEAD");
|
|
4900
|
+
}
|
|
4858
4901
|
if (subpath) {
|
|
4859
|
-
const repoGit = esm_default(cachePath);
|
|
4860
4902
|
await repoGit.raw([
|
|
4861
4903
|
"sparse-checkout",
|
|
4862
4904
|
"init",
|
|
@@ -4867,18 +4909,31 @@ async function cloneGitSource(options) {
|
|
|
4867
4909
|
"set",
|
|
4868
4910
|
subpath
|
|
4869
4911
|
]);
|
|
4870
|
-
await repoGit.checkout(ref || "HEAD");
|
|
4871
|
-
} else if (ref && ref !== "main" && ref !== "master") await
|
|
4872
|
-
const sha = await
|
|
4912
|
+
if (!isSha) await repoGit.checkout(ref || "HEAD");
|
|
4913
|
+
} else if (ref && !isSha && ref !== "main" && ref !== "master") await repoGit.checkout(ref);
|
|
4914
|
+
const sha = await repoGit.revparse(["HEAD"]);
|
|
4873
4915
|
return {
|
|
4874
4916
|
localPath: subpath ? join(cachePath, subpath) : cachePath,
|
|
4875
4917
|
fromCache: false,
|
|
4876
|
-
sha: sha.trim()
|
|
4918
|
+
sha: sha.trim(),
|
|
4919
|
+
cachePath,
|
|
4920
|
+
sparseCheckout: !!subpath
|
|
4877
4921
|
};
|
|
4878
4922
|
} catch (error) {
|
|
4879
4923
|
throw new GitSourceError(`Failed to clone Git repository from ${url}: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
4880
4924
|
}
|
|
4881
4925
|
}
|
|
4926
|
+
/**
|
|
4927
|
+
* Expands sparse-checkout in a cached repository to include additional paths.
|
|
4928
|
+
* Uses 'git sparse-checkout add' to preserve existing checkout paths.
|
|
4929
|
+
*/
|
|
4930
|
+
async function expandSparseCheckout(cachePath, additionalPaths) {
|
|
4931
|
+
await esm_default(cachePath).raw([
|
|
4932
|
+
"sparse-checkout",
|
|
4933
|
+
"add",
|
|
4934
|
+
...additionalPaths
|
|
4935
|
+
]);
|
|
4936
|
+
}
|
|
4882
4937
|
|
|
4883
4938
|
//#endregion
|
|
4884
4939
|
//#region ../core/src/sources/npm-resolver.ts
|
|
@@ -6487,22 +6542,31 @@ async function removePlacedFiles(filePaths, projectRoot) {
|
|
|
6487
6542
|
//#region ../core/src/sources/load-profile-safe.ts
|
|
6488
6543
|
/**
|
|
6489
6544
|
* Loads and parses a profile manifest from a given path within a source repository.
|
|
6490
|
-
* Returns null if the file doesn't exist
|
|
6545
|
+
* Returns null if the file doesn't exist (ENOENT). Logs a warning for schema
|
|
6546
|
+
* validation errors and other failures so they are visible to the user.
|
|
6491
6547
|
*
|
|
6492
6548
|
* @param sourceRoot - Absolute path to the source repository root
|
|
6493
6549
|
* @param profilePath - Relative path to the profile (e.g., "profiles/frontend")
|
|
6494
6550
|
* @returns Parsed manifest summary or null
|
|
6495
6551
|
*/
|
|
6496
6552
|
async function loadProfileManifestSafe(sourceRoot, profilePath) {
|
|
6553
|
+
const manifestPath = join(sourceRoot, profilePath, "baton.profile.yaml");
|
|
6497
6554
|
try {
|
|
6498
|
-
const parsed = (0, import_dist.parse)(await readFile(
|
|
6555
|
+
const parsed = (0, import_dist.parse)(await readFile(manifestPath, "utf-8"));
|
|
6499
6556
|
const manifest = profileManifestSchema.parse(parsed);
|
|
6500
6557
|
return {
|
|
6501
6558
|
name: manifest.name,
|
|
6502
6559
|
version: manifest.version,
|
|
6503
6560
|
description: manifest.description
|
|
6504
6561
|
};
|
|
6505
|
-
} catch {
|
|
6562
|
+
} catch (error) {
|
|
6563
|
+
if (error.code === "ENOENT" || error instanceof Error && error.message.includes("ENOENT")) return null;
|
|
6564
|
+
if (error instanceof ZodError) {
|
|
6565
|
+
const issues = error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
6566
|
+
console.warn(`Warning: Invalid profile manifest at ${manifestPath}:\n${issues}`);
|
|
6567
|
+
return null;
|
|
6568
|
+
}
|
|
6569
|
+
console.warn(`Warning: Could not load profile manifest at ${manifestPath}: ${error instanceof Error ? error.message : error}`);
|
|
6506
6570
|
return null;
|
|
6507
6571
|
}
|
|
6508
6572
|
}
|
|
@@ -6706,11 +6770,12 @@ const MAX_CHAIN_DEPTH = 10;
|
|
|
6706
6770
|
* @param manifest - Root profile manifest
|
|
6707
6771
|
* @param source - Source URL or path of root profile
|
|
6708
6772
|
* @param baseDir - Base directory for resolving relative paths
|
|
6773
|
+
* @param cloneContext - Optional clone context for sparse-checkout expansion
|
|
6709
6774
|
* @returns Array of resolved profiles in merge order (base first, overrides last)
|
|
6710
6775
|
*/
|
|
6711
|
-
async function resolveProfileChain(manifest, source, baseDir) {
|
|
6776
|
+
async function resolveProfileChain(manifest, source, baseDir, cloneContext) {
|
|
6712
6777
|
const chain = [];
|
|
6713
|
-
await resolveChainRecursive(manifest, source, baseDir, chain, /* @__PURE__ */ new Set(), []);
|
|
6778
|
+
await resolveChainRecursive(manifest, source, baseDir, chain, /* @__PURE__ */ new Set(), [], void 0, cloneContext);
|
|
6714
6779
|
return chain;
|
|
6715
6780
|
}
|
|
6716
6781
|
/**
|
|
@@ -6723,19 +6788,22 @@ async function resolveProfileChain(manifest, source, baseDir) {
|
|
|
6723
6788
|
* @param visited - Set of visited sources (for circular detection)
|
|
6724
6789
|
* @param path - Current path (for error messages)
|
|
6725
6790
|
* @param localPath - Resolved local directory path for this profile
|
|
6791
|
+
* @param cloneContext - Optional clone context for sparse-checkout expansion
|
|
6726
6792
|
*/
|
|
6727
|
-
async function resolveChainRecursive(manifest, source, baseDir, chain, visited, path, localPath) {
|
|
6793
|
+
async function resolveChainRecursive(manifest, source, baseDir, chain, visited, path, localPath, cloneContext) {
|
|
6728
6794
|
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
6795
|
if (visited.has(source)) throw new CircularInheritanceError(`Circular profile inheritance detected: ${[...path, manifest.name].join(" -> ")}`);
|
|
6730
6796
|
const currentVisited = new Set(visited);
|
|
6731
6797
|
currentVisited.add(source);
|
|
6732
6798
|
path.push(manifest.name);
|
|
6733
6799
|
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);
|
|
6800
|
+
const { manifest: parentManifest, localPath: parentLocalPath } = await loadProfileFromSource(extendSource, baseDir, cloneContext);
|
|
6801
|
+
await resolveChainRecursive(parentManifest, extendSource, baseDir, chain, currentVisited, [...path], parentLocalPath, cloneContext);
|
|
6736
6802
|
} catch (error) {
|
|
6737
6803
|
if (error instanceof CircularInheritanceError) throw error;
|
|
6738
6804
|
if (error instanceof Error && error.message.includes("exceeds maximum depth")) throw error;
|
|
6805
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
6806
|
+
throw new Error(`Failed to resolve extends '${extendSource}' from profile '${manifest.name}': ${cause}`);
|
|
6739
6807
|
}
|
|
6740
6808
|
chain.push({
|
|
6741
6809
|
manifest,
|
|
@@ -6748,25 +6816,55 @@ async function resolveChainRecursive(manifest, source, baseDir, chain, visited,
|
|
|
6748
6816
|
/**
|
|
6749
6817
|
* Load a profile from a source (Git URL or local path)
|
|
6750
6818
|
*
|
|
6819
|
+
* When operating inside a sparse-checkout repo and the profile is not found,
|
|
6820
|
+
* expands the sparse-checkout to include the profile path and retries.
|
|
6821
|
+
*
|
|
6751
6822
|
* @param source - Source URL or path
|
|
6752
6823
|
* @param baseDir - Base directory for resolving relative paths
|
|
6824
|
+
* @param cloneContext - Optional clone context for sparse-checkout expansion
|
|
6753
6825
|
* @returns Loaded profile manifest and resolved local directory path
|
|
6754
6826
|
*/
|
|
6755
|
-
async function loadProfileFromSource(source, baseDir) {
|
|
6827
|
+
async function loadProfileFromSource(source, baseDir, cloneContext) {
|
|
6756
6828
|
const parsed = parseSource(source);
|
|
6757
6829
|
if (parsed.provider === "local") {
|
|
6758
6830
|
const absolutePath = resolve(baseDir, parsed.path);
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6831
|
+
const manifestPath = resolve(absolutePath, "baton.profile.yaml");
|
|
6832
|
+
try {
|
|
6833
|
+
return {
|
|
6834
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6835
|
+
localPath: absolutePath
|
|
6836
|
+
};
|
|
6837
|
+
} catch (error) {
|
|
6838
|
+
if (error instanceof FileNotFoundError && cloneContext?.sparseCheckout) {
|
|
6839
|
+
const relativePath = relative(cloneContext.cachePath, absolutePath);
|
|
6840
|
+
await expandSparseCheckout(cloneContext.cachePath, [relativePath]);
|
|
6841
|
+
return {
|
|
6842
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6843
|
+
localPath: absolutePath
|
|
6844
|
+
};
|
|
6845
|
+
}
|
|
6846
|
+
throw error;
|
|
6847
|
+
}
|
|
6763
6848
|
}
|
|
6764
6849
|
if (parsed.provider === "file") {
|
|
6765
6850
|
const absolutePath = parsed.path.startsWith("/") ? parsed.path : resolve(baseDir, parsed.path);
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6851
|
+
const manifestPath = resolve(absolutePath, "baton.profile.yaml");
|
|
6852
|
+
try {
|
|
6853
|
+
return {
|
|
6854
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6855
|
+
localPath: absolutePath
|
|
6856
|
+
};
|
|
6857
|
+
} catch (error) {
|
|
6858
|
+
if (error instanceof FileNotFoundError && cloneContext?.sparseCheckout) {
|
|
6859
|
+
const relativePath = relative(cloneContext.cachePath, absolutePath);
|
|
6860
|
+
await expandSparseCheckout(cloneContext.cachePath, [relativePath]);
|
|
6861
|
+
return {
|
|
6862
|
+
manifest: await loadProfileManifest(manifestPath),
|
|
6863
|
+
localPath: absolutePath
|
|
6864
|
+
};
|
|
6865
|
+
}
|
|
6866
|
+
throw error;
|
|
6867
|
+
}
|
|
6770
6868
|
}
|
|
6771
6869
|
if (parsed.provider === "npm") throw new Error("NPM sources are not yet implemented in inheritance chain");
|
|
6772
6870
|
const subpath = parsed.provider !== "git" ? parsed.subpath : void 0;
|
|
@@ -14411,7 +14509,8 @@ const globalConfigSchema = objectType({
|
|
|
14411
14509
|
]).default("deep")
|
|
14412
14510
|
}).optional(),
|
|
14413
14511
|
ai: objectType({ tools: arrayType(stringType()).optional().default([]) }).optional(),
|
|
14414
|
-
ide: objectType({ platforms: arrayType(stringType()).optional().default([]) }).optional()
|
|
14512
|
+
ide: objectType({ platforms: arrayType(stringType()).optional().default([]) }).optional(),
|
|
14513
|
+
sync: objectType({ cacheTtlHours: numberType().default(24) }).optional()
|
|
14415
14514
|
});
|
|
14416
14515
|
|
|
14417
14516
|
//#endregion
|
|
@@ -14788,5 +14887,5 @@ async function resolvePreferences(projectRoot) {
|
|
|
14788
14887
|
}
|
|
14789
14888
|
|
|
14790
14889
|
//#endregion
|
|
14791
|
-
export {
|
|
14792
|
-
//# sourceMappingURL=src-
|
|
14890
|
+
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 };
|
|
14891
|
+
//# sourceMappingURL=src-dY02psbw.mjs.map
|