teamix-evo 0.16.0 → 0.17.0
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 -0
- package/dist/core/index.d.ts +42 -2
- package/dist/core/index.js +489 -33
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +247 -77
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -582,7 +582,7 @@ var init_registry = __esm({
|
|
|
582
582
|
});
|
|
583
583
|
|
|
584
584
|
// src/index.ts
|
|
585
|
-
import { Command as
|
|
585
|
+
import { Command as Command42 } from "commander";
|
|
586
586
|
import { createRequire as createRequire9 } from "module";
|
|
587
587
|
|
|
588
588
|
// src/commands/tokens/index.ts
|
|
@@ -807,9 +807,9 @@ async function installSkills(options) {
|
|
|
807
807
|
async function renderSkillFiles(skill, options) {
|
|
808
808
|
const { data, packageRoot } = options;
|
|
809
809
|
const sourceAbs = path7.resolve(packageRoot, skill.source);
|
|
810
|
-
const
|
|
810
|
+
const stat6 = await fs6.stat(sourceAbs);
|
|
811
811
|
const rendered = /* @__PURE__ */ new Map();
|
|
812
|
-
if (
|
|
812
|
+
if (stat6.isFile()) {
|
|
813
813
|
const content = await renderSkillContent(sourceAbs, skill, data);
|
|
814
814
|
rendered.set("SKILL.md", content);
|
|
815
815
|
return rendered;
|
|
@@ -1072,13 +1072,13 @@ async function pruneEmptyIdeSkillDirs(args) {
|
|
|
1072
1072
|
}
|
|
1073
1073
|
for (const name of entries) {
|
|
1074
1074
|
const dir = path7.join(skillsRoot, name);
|
|
1075
|
-
let
|
|
1075
|
+
let stat6;
|
|
1076
1076
|
try {
|
|
1077
|
-
|
|
1077
|
+
stat6 = await fs6.stat(dir);
|
|
1078
1078
|
} catch {
|
|
1079
1079
|
continue;
|
|
1080
1080
|
}
|
|
1081
|
-
if (!
|
|
1081
|
+
if (!stat6.isDirectory()) continue;
|
|
1082
1082
|
let children;
|
|
1083
1083
|
try {
|
|
1084
1084
|
children = await fs6.readdir(dir);
|
|
@@ -5016,8 +5016,8 @@ async function runSkillsDoctor(options) {
|
|
|
5016
5016
|
}
|
|
5017
5017
|
async function dirExists(p2) {
|
|
5018
5018
|
try {
|
|
5019
|
-
const
|
|
5020
|
-
return
|
|
5019
|
+
const stat6 = await fs17.stat(p2);
|
|
5020
|
+
return stat6.isDirectory();
|
|
5021
5021
|
} catch {
|
|
5022
5022
|
return false;
|
|
5023
5023
|
}
|
|
@@ -6125,8 +6125,8 @@ function extractIds(pkg) {
|
|
|
6125
6125
|
}
|
|
6126
6126
|
async function directoryExists(p2) {
|
|
6127
6127
|
try {
|
|
6128
|
-
const
|
|
6129
|
-
return
|
|
6128
|
+
const stat6 = await fs22.stat(p2);
|
|
6129
|
+
return stat6.isDirectory();
|
|
6130
6130
|
} catch {
|
|
6131
6131
|
return false;
|
|
6132
6132
|
}
|
|
@@ -8548,13 +8548,44 @@ async function detectProjectState(cwd) {
|
|
|
8548
8548
|
significantEntries: []
|
|
8549
8549
|
};
|
|
8550
8550
|
}
|
|
8551
|
+
let legacyLib = "unknown";
|
|
8552
|
+
let buildTool = "unknown";
|
|
8553
|
+
let allDeps = {};
|
|
8554
|
+
if (hasPackageJson2) {
|
|
8555
|
+
const pkgRaw = await readFileOrNull(path36.join(absCwd, "package.json"));
|
|
8556
|
+
if (pkgRaw) {
|
|
8557
|
+
try {
|
|
8558
|
+
const pkg = JSON.parse(pkgRaw);
|
|
8559
|
+
allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
8560
|
+
} catch {
|
|
8561
|
+
}
|
|
8562
|
+
}
|
|
8563
|
+
}
|
|
8564
|
+
if ("@alifd/next" in allDeps || "@ali/teamix-material" in allDeps) {
|
|
8565
|
+
legacyLib = "fusion";
|
|
8566
|
+
} else if ("antd" in allDeps) {
|
|
8567
|
+
legacyLib = "antd";
|
|
8568
|
+
} else if ("element-ui" in allDeps || "element-plus" in allDeps) {
|
|
8569
|
+
legacyLib = "element";
|
|
8570
|
+
}
|
|
8571
|
+
if (await fileExists(path36.join(absCwd, "build.json"))) {
|
|
8572
|
+
buildTool = "ice";
|
|
8573
|
+
} else if (await fileExists(path36.join(absCwd, "vite.config.ts")) || await fileExists(path36.join(absCwd, "vite.config.js")) || await fileExists(path36.join(absCwd, "vite.config.mts"))) {
|
|
8574
|
+
buildTool = "vite";
|
|
8575
|
+
} else if (await fileExists(path36.join(absCwd, "webpack.config.js")) || await fileExists(path36.join(absCwd, "webpack.config.ts"))) {
|
|
8576
|
+
buildTool = "webpack";
|
|
8577
|
+
} else if ("umi" in allDeps || "@umijs/max" in allDeps) {
|
|
8578
|
+
buildTool = "umi";
|
|
8579
|
+
}
|
|
8551
8580
|
return {
|
|
8552
8581
|
state: "other",
|
|
8553
8582
|
cwd: absCwd,
|
|
8554
8583
|
hasTeamixDir: false,
|
|
8555
8584
|
hasPackageJson: hasPackageJson2,
|
|
8556
8585
|
hasComponentsJson,
|
|
8557
|
-
significantEntries: significant.slice(0, 20).sort()
|
|
8586
|
+
significantEntries: significant.slice(0, 20).sort(),
|
|
8587
|
+
legacyLib,
|
|
8588
|
+
buildTool
|
|
8558
8589
|
};
|
|
8559
8590
|
}
|
|
8560
8591
|
|
|
@@ -8563,7 +8594,8 @@ init_logger();
|
|
|
8563
8594
|
var COMMAND_LABELS = {
|
|
8564
8595
|
init: "\u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6",
|
|
8565
8596
|
migrate: "shadcn \u9879\u76EE\u8FC1\u79FB\u4E3A Teamix Evo \u5957\u4EF6",
|
|
8566
|
-
update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0"
|
|
8597
|
+
update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0",
|
|
8598
|
+
graft: "\u53E0\u52A0 Teamix Evo \u80FD\u529B"
|
|
8567
8599
|
};
|
|
8568
8600
|
var STATE_LABELS = {
|
|
8569
8601
|
empty: "\u7A7A\u76EE\u5F55",
|
|
@@ -8574,13 +8606,14 @@ var STATE_LABELS = {
|
|
|
8574
8606
|
var VALID_STATES = {
|
|
8575
8607
|
init: "empty",
|
|
8576
8608
|
migrate: "shadcn",
|
|
8577
|
-
update: "teamix-evo"
|
|
8609
|
+
update: "teamix-evo",
|
|
8610
|
+
graft: "other"
|
|
8578
8611
|
};
|
|
8579
8612
|
var STATE_TO_COMMAND = {
|
|
8580
8613
|
empty: "init",
|
|
8581
8614
|
shadcn: "migrate",
|
|
8582
8615
|
"teamix-evo": "update",
|
|
8583
|
-
other:
|
|
8616
|
+
other: "graft"
|
|
8584
8617
|
};
|
|
8585
8618
|
function assertCommandPrecondition(command, state) {
|
|
8586
8619
|
const expected = VALID_STATES[command];
|
|
@@ -8594,13 +8627,6 @@ function assertCommandPrecondition(command, state) {
|
|
|
8594
8627
|
if (suggestion) {
|
|
8595
8628
|
const suggestionLabel = COMMAND_LABELS[suggestion];
|
|
8596
8629
|
logger.info(`\u5EFA\u8BAE\u4F7F\u7528\uFF1Ateamix-evo ${suggestion}\uFF08${suggestionLabel}\uFF09`);
|
|
8597
|
-
} else {
|
|
8598
|
-
logger.info(
|
|
8599
|
-
"\u5F53\u524D\u9879\u76EE\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u76F4\u63A5\u63A5\u5165\u3002"
|
|
8600
|
-
);
|
|
8601
|
-
logger.info(
|
|
8602
|
-
"\u5EFA\u8BAE\uFF1A\u5148\u7528 teamix-evo init \u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6\uFF08\u7A7A\u76EE\u5F55\uFF09\uFF0C\u7136\u540E\u5BF9\u65E7\u9879\u76EE\u8FDB\u884C\u91CD\u6784\u3002"
|
|
8603
|
-
);
|
|
8604
8630
|
}
|
|
8605
8631
|
process.exitCode = 1;
|
|
8606
8632
|
}
|
|
@@ -9482,7 +9508,7 @@ async function detectLintVersions(projectRoot) {
|
|
|
9482
9508
|
const pkgJson = pkgJsonRaw ? JSON.parse(pkgJsonRaw) : null;
|
|
9483
9509
|
const devDeps = pkgJson?.devDependencies ?? {};
|
|
9484
9510
|
const deps = pkgJson?.dependencies ?? {};
|
|
9485
|
-
const
|
|
9511
|
+
const resolve13 = async (pkg) => {
|
|
9486
9512
|
const declared = devDeps[pkg] ?? deps[pkg] ?? null;
|
|
9487
9513
|
if (!declared) return null;
|
|
9488
9514
|
const installedPkgJson = await readFileOrNull(
|
|
@@ -9492,8 +9518,8 @@ async function detectLintVersions(projectRoot) {
|
|
|
9492
9518
|
return { declared, installed };
|
|
9493
9519
|
};
|
|
9494
9520
|
const [eslintConfig, stylelintConfig] = await Promise.all([
|
|
9495
|
-
|
|
9496
|
-
|
|
9521
|
+
resolve13(LINT_PACKAGES[0]),
|
|
9522
|
+
resolve13(LINT_PACKAGES[1])
|
|
9497
9523
|
]);
|
|
9498
9524
|
return { eslintConfig, stylelintConfig };
|
|
9499
9525
|
}
|
|
@@ -9659,19 +9685,162 @@ var migrateCommand = new Command38("migrate").description(
|
|
|
9659
9685
|
}
|
|
9660
9686
|
});
|
|
9661
9687
|
|
|
9662
|
-
// src/commands/
|
|
9688
|
+
// src/commands/graft/index.ts
|
|
9663
9689
|
import { Command as Command39 } from "commander";
|
|
9664
|
-
import * as
|
|
9690
|
+
import * as path43 from "path";
|
|
9691
|
+
import * as fs31 from "fs/promises";
|
|
9692
|
+
init_logger();
|
|
9693
|
+
init_error();
|
|
9694
|
+
init_fs();
|
|
9695
|
+
var APP_ENTRY_CANDIDATES = [
|
|
9696
|
+
"src/app.tsx",
|
|
9697
|
+
"src/app.ts",
|
|
9698
|
+
"src/app.jsx",
|
|
9699
|
+
"src/app.js",
|
|
9700
|
+
"src/index.tsx",
|
|
9701
|
+
"src/index.ts",
|
|
9702
|
+
"src/index.jsx",
|
|
9703
|
+
"src/index.js"
|
|
9704
|
+
];
|
|
9705
|
+
var POSTCSS_CONFIG_CANDIDATES = [
|
|
9706
|
+
"postcss.config.js",
|
|
9707
|
+
"postcss.config.cjs",
|
|
9708
|
+
"postcss.config.mjs",
|
|
9709
|
+
"postcss.config.ts",
|
|
9710
|
+
".postcssrc",
|
|
9711
|
+
".postcssrc.json",
|
|
9712
|
+
".postcssrc.yml",
|
|
9713
|
+
".postcssrc.yaml",
|
|
9714
|
+
".postcssrc.js"
|
|
9715
|
+
];
|
|
9716
|
+
var CONFLICT_PATHS = [
|
|
9717
|
+
{ path: ".teamix-evo", type: "directory" },
|
|
9718
|
+
{ path: "src/components/ui", type: "directory" },
|
|
9719
|
+
{ path: "src/components/business", type: "directory" },
|
|
9720
|
+
{ path: "tokens", type: "directory" }
|
|
9721
|
+
];
|
|
9722
|
+
async function findFirst(cwd, candidates) {
|
|
9723
|
+
for (const c of candidates) {
|
|
9724
|
+
if (await fileExists(path43.join(cwd, c))) return c;
|
|
9725
|
+
}
|
|
9726
|
+
return null;
|
|
9727
|
+
}
|
|
9728
|
+
async function getLegacyLibVersion(cwd, legacyLib) {
|
|
9729
|
+
const pkgRaw = await readFileOrNull(path43.join(cwd, "package.json"));
|
|
9730
|
+
if (!pkgRaw) return "unknown";
|
|
9731
|
+
try {
|
|
9732
|
+
const pkg = JSON.parse(pkgRaw);
|
|
9733
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
9734
|
+
const libKeyMap = {
|
|
9735
|
+
fusion: ["@alifd/next", "@ali/teamix-material"],
|
|
9736
|
+
antd: ["antd"],
|
|
9737
|
+
element: ["element-ui", "element-plus"]
|
|
9738
|
+
};
|
|
9739
|
+
const keys = libKeyMap[legacyLib] ?? [];
|
|
9740
|
+
for (const key of keys) {
|
|
9741
|
+
if (allDeps[key]) return allDeps[key];
|
|
9742
|
+
}
|
|
9743
|
+
} catch {
|
|
9744
|
+
}
|
|
9745
|
+
return "unknown";
|
|
9746
|
+
}
|
|
9747
|
+
async function detectConflicts(cwd) {
|
|
9748
|
+
const conflicts = [];
|
|
9749
|
+
for (const entry of CONFLICT_PATHS) {
|
|
9750
|
+
const full = path43.join(cwd, entry.path);
|
|
9751
|
+
try {
|
|
9752
|
+
const stat6 = await fs31.stat(full);
|
|
9753
|
+
if (entry.type === "directory" && stat6.isDirectory() || entry.type === "file" && stat6.isFile()) {
|
|
9754
|
+
conflicts.push(entry);
|
|
9755
|
+
}
|
|
9756
|
+
} catch {
|
|
9757
|
+
}
|
|
9758
|
+
}
|
|
9759
|
+
return conflicts;
|
|
9760
|
+
}
|
|
9761
|
+
var graftCommand = new Command39("graft").description(
|
|
9762
|
+
"\u53E0\u52A0 Teamix Evo AICoding \u80FD\u529B\u5230\u73B0\u6709\u9879\u76EE\uFF08\u53CC\u6808\u5171\u5B58\uFF0CADR 0047\uFF09"
|
|
9763
|
+
).option("--variant <name>", "\u6307\u5B9A tokens variant\uFF08\u5982 opentrek\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("--json", "\u8F93\u51FA JSON \u683C\u5F0F\u7684\u5206\u6790\u62A5\u544A\uFF08\u4F9B AI skill \u6D88\u8D39\uFF09").action(async (opts) => {
|
|
9764
|
+
const cwd = path43.resolve(opts.cwd ?? process.cwd());
|
|
9765
|
+
try {
|
|
9766
|
+
const state = await detectProjectState(cwd);
|
|
9767
|
+
if (state.state !== "other") {
|
|
9768
|
+
assertCommandPrecondition("graft", state.state);
|
|
9769
|
+
return;
|
|
9770
|
+
}
|
|
9771
|
+
const legacyLib = state.legacyLib ?? "unknown";
|
|
9772
|
+
const buildTool = state.buildTool ?? "unknown";
|
|
9773
|
+
const legacyVersion = await getLegacyLibVersion(cwd, legacyLib);
|
|
9774
|
+
const BUILD_TOOL_CONFIG_CANDIDATES = {
|
|
9775
|
+
ice: ["build.json"],
|
|
9776
|
+
vite: ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"],
|
|
9777
|
+
webpack: ["webpack.config.js", "webpack.config.ts", "webpack.config.cjs"]
|
|
9778
|
+
};
|
|
9779
|
+
const buildToolConfig = await findFirst(
|
|
9780
|
+
cwd,
|
|
9781
|
+
BUILD_TOOL_CONFIG_CANDIDATES[buildTool] ?? []
|
|
9782
|
+
);
|
|
9783
|
+
const postcssPath = await findFirst(cwd, POSTCSS_CONFIG_CANDIDATES);
|
|
9784
|
+
const appEntry = await findFirst(cwd, APP_ENTRY_CANDIDATES);
|
|
9785
|
+
const conflicts = await detectConflicts(cwd);
|
|
9786
|
+
const report = {
|
|
9787
|
+
projectRoot: cwd,
|
|
9788
|
+
legacyLib: { name: legacyLib, version: legacyVersion },
|
|
9789
|
+
buildTool: { type: buildTool, configFile: buildToolConfig },
|
|
9790
|
+
postcssConfig: { exists: postcssPath !== null, path: postcssPath },
|
|
9791
|
+
appEntry,
|
|
9792
|
+
conflicts
|
|
9793
|
+
};
|
|
9794
|
+
if (opts.json) {
|
|
9795
|
+
console.log(JSON.stringify(report, null, 2));
|
|
9796
|
+
} else {
|
|
9797
|
+
logger.info("Teamix Evo Graft \u2014 \u53CC\u6808\u5171\u5B58\u524D\u7F6E\u68C0\u67E5");
|
|
9798
|
+
logger.info("");
|
|
9799
|
+
logger.info(` \u9879\u76EE\u76EE\u5F55\uFF1A${cwd}`);
|
|
9800
|
+
logger.info(
|
|
9801
|
+
` \u65E7\u7EC4\u4EF6\u5E93\uFF1A${legacyLib} (${legacyVersion})`
|
|
9802
|
+
);
|
|
9803
|
+
logger.info(` \u6784\u5EFA\u5DE5\u5177\uFF1A${buildTool}`);
|
|
9804
|
+
logger.info(
|
|
9805
|
+
` PostCSS \u914D\u7F6E\uFF1A${postcssPath ?? "\u672A\u68C0\u6D4B\u5230"}`
|
|
9806
|
+
);
|
|
9807
|
+
logger.info(` App \u5165\u53E3\uFF1A${appEntry ?? "\u672A\u68C0\u6D4B\u5230"}`);
|
|
9808
|
+
if (conflicts.length > 0) {
|
|
9809
|
+
logger.info("");
|
|
9810
|
+
logger.warn(" \u5DF2\u5B58\u5728\u7684\u8DEF\u5F84\uFF08\u53EF\u80FD\u51B2\u7A81\uFF09\uFF1A");
|
|
9811
|
+
for (const c of conflicts) {
|
|
9812
|
+
logger.warn(` ${c.path} (${c.type})`);
|
|
9813
|
+
}
|
|
9814
|
+
}
|
|
9815
|
+
logger.info("");
|
|
9816
|
+
logger.info(
|
|
9817
|
+
"\u524D\u7F6E\u68C0\u67E5\u901A\u8FC7\u3002\u8BF7\u5728 AI IDE \u4E2D\u89E6\u53D1 teamix-evo-manage skill \u4EE5\u5F15\u5BFC graft \u6D41\u7A0B\u3002"
|
|
9818
|
+
);
|
|
9819
|
+
logger.info(
|
|
9820
|
+
"CLI \u4EC5\u505A\u524D\u7F6E\u68C0\u67E5\uFF0C\u5B9E\u9645 graft \u7531 AI skill \u9A71\u52A8\u3002"
|
|
9821
|
+
);
|
|
9822
|
+
}
|
|
9823
|
+
} catch (err) {
|
|
9824
|
+
logger.error(`graft \u524D\u7F6E\u68C0\u67E5\u5931\u8D25\uFF1A${getErrorMessage(err)}`);
|
|
9825
|
+
logger.debug(err.stack ?? "");
|
|
9826
|
+
process.exitCode = 1;
|
|
9827
|
+
}
|
|
9828
|
+
});
|
|
9829
|
+
|
|
9830
|
+
// src/commands/restore/index.ts
|
|
9831
|
+
import { Command as Command40 } from "commander";
|
|
9832
|
+
import * as path45 from "path";
|
|
9665
9833
|
import * as prompts7 from "@clack/prompts";
|
|
9666
9834
|
|
|
9667
9835
|
// src/core/snapshot.ts
|
|
9668
9836
|
init_logger();
|
|
9669
|
-
import * as
|
|
9670
|
-
import * as
|
|
9837
|
+
import * as fs32 from "fs/promises";
|
|
9838
|
+
import * as path44 from "path";
|
|
9671
9839
|
var TEAMIX_DIR6 = ".teamix-evo";
|
|
9672
9840
|
var SNAPSHOTS_DIR = ".snapshots";
|
|
9673
9841
|
var META_FILE = "_meta.json";
|
|
9674
9842
|
var DEFAULT_KEEP = 5;
|
|
9843
|
+
var SNAPSHOT_REASONS = ["init", "update", "switch", "restore", "graft", "manual"];
|
|
9675
9844
|
function isoToFsSafe3(iso) {
|
|
9676
9845
|
return iso.replace(/[:.]/g, "-");
|
|
9677
9846
|
}
|
|
@@ -9682,47 +9851,47 @@ function fsSafeToIso(safe) {
|
|
|
9682
9851
|
);
|
|
9683
9852
|
}
|
|
9684
9853
|
async function createSnapshot(projectRoot, opts = {}) {
|
|
9685
|
-
const teamixDir =
|
|
9854
|
+
const teamixDir = path44.join(projectRoot, TEAMIX_DIR6);
|
|
9686
9855
|
try {
|
|
9687
|
-
const
|
|
9688
|
-
if (!
|
|
9856
|
+
const stat6 = await fs32.stat(teamixDir);
|
|
9857
|
+
if (!stat6.isDirectory()) return null;
|
|
9689
9858
|
} catch (err) {
|
|
9690
9859
|
if (err.code === "ENOENT") return null;
|
|
9691
9860
|
throw err;
|
|
9692
9861
|
}
|
|
9693
9862
|
const isoTs = (/* @__PURE__ */ new Date()).toISOString();
|
|
9694
9863
|
const ts = isoToFsSafe3(isoTs);
|
|
9695
|
-
const snapshotRoot =
|
|
9696
|
-
const target =
|
|
9697
|
-
await
|
|
9698
|
-
const entries = await
|
|
9864
|
+
const snapshotRoot = path44.join(teamixDir, SNAPSHOTS_DIR);
|
|
9865
|
+
const target = path44.join(snapshotRoot, ts);
|
|
9866
|
+
await fs32.mkdir(target, { recursive: true });
|
|
9867
|
+
const entries = await fs32.readdir(teamixDir, { withFileTypes: true });
|
|
9699
9868
|
for (const entry of entries) {
|
|
9700
9869
|
if (entry.name === SNAPSHOTS_DIR) continue;
|
|
9701
|
-
const src =
|
|
9702
|
-
const dst =
|
|
9703
|
-
await
|
|
9870
|
+
const src = path44.join(teamixDir, entry.name);
|
|
9871
|
+
const dst = path44.join(target, entry.name);
|
|
9872
|
+
await fs32.cp(src, dst, { recursive: true });
|
|
9704
9873
|
}
|
|
9705
9874
|
const meta = {
|
|
9706
9875
|
ts: isoTs,
|
|
9707
9876
|
reason: opts.reason ?? "manual"
|
|
9708
9877
|
};
|
|
9709
|
-
await
|
|
9710
|
-
|
|
9878
|
+
await fs32.writeFile(
|
|
9879
|
+
path44.join(target, META_FILE),
|
|
9711
9880
|
JSON.stringify(meta, null, 2) + "\n",
|
|
9712
9881
|
"utf-8"
|
|
9713
9882
|
);
|
|
9714
9883
|
logger.debug(
|
|
9715
|
-
`Snapshot created \u2192 ${
|
|
9884
|
+
`Snapshot created \u2192 ${path44.relative(projectRoot, target)} (${meta.reason})`
|
|
9716
9885
|
);
|
|
9717
9886
|
const keep = opts.keep ?? DEFAULT_KEEP;
|
|
9718
9887
|
await pruneSnapshots(projectRoot, keep, { protectedTs: opts.protectedTs });
|
|
9719
9888
|
return { ts, path: target };
|
|
9720
9889
|
}
|
|
9721
9890
|
async function listSnapshots(projectRoot) {
|
|
9722
|
-
const snapshotRoot =
|
|
9891
|
+
const snapshotRoot = path44.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
|
|
9723
9892
|
let entries;
|
|
9724
9893
|
try {
|
|
9725
|
-
entries = await
|
|
9894
|
+
entries = await fs32.readdir(snapshotRoot, { withFileTypes: true });
|
|
9726
9895
|
} catch (err) {
|
|
9727
9896
|
if (err.code === "ENOENT") return [];
|
|
9728
9897
|
throw err;
|
|
@@ -9730,14 +9899,14 @@ async function listSnapshots(projectRoot) {
|
|
|
9730
9899
|
const result = [];
|
|
9731
9900
|
for (const entry of entries) {
|
|
9732
9901
|
if (!entry.isDirectory()) continue;
|
|
9733
|
-
const dir =
|
|
9902
|
+
const dir = path44.join(snapshotRoot, entry.name);
|
|
9734
9903
|
let isoTs = null;
|
|
9735
9904
|
let reason = null;
|
|
9736
9905
|
try {
|
|
9737
|
-
const raw = await
|
|
9906
|
+
const raw = await fs32.readFile(path44.join(dir, META_FILE), "utf-8");
|
|
9738
9907
|
const parsed = JSON.parse(raw);
|
|
9739
9908
|
if (typeof parsed.ts === "string") isoTs = parsed.ts;
|
|
9740
|
-
if (typeof parsed.reason === "string" &&
|
|
9909
|
+
if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
|
|
9741
9910
|
parsed.reason
|
|
9742
9911
|
)) {
|
|
9743
9912
|
reason = parsed.reason;
|
|
@@ -9759,18 +9928,18 @@ async function pruneSnapshots(projectRoot, keep = DEFAULT_KEEP, opts = {}) {
|
|
|
9759
9928
|
const toRemove = opts.protectedTs ? tail.filter((s) => s.ts !== opts.protectedTs) : tail;
|
|
9760
9929
|
const removed = [];
|
|
9761
9930
|
for (const snap of toRemove) {
|
|
9762
|
-
await
|
|
9931
|
+
await fs32.rm(snap.path, { recursive: true, force: true });
|
|
9763
9932
|
removed.push(snap.ts);
|
|
9764
9933
|
logger.debug(`Pruned snapshot ${snap.ts}`);
|
|
9765
9934
|
}
|
|
9766
9935
|
return removed.reverse();
|
|
9767
9936
|
}
|
|
9768
9937
|
async function restoreSnapshot(projectRoot, ts) {
|
|
9769
|
-
const snapshotRoot =
|
|
9770
|
-
const target =
|
|
9938
|
+
const snapshotRoot = path44.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
|
|
9939
|
+
const target = path44.join(snapshotRoot, ts);
|
|
9771
9940
|
try {
|
|
9772
|
-
const
|
|
9773
|
-
if (!
|
|
9941
|
+
const stat6 = await fs32.stat(target);
|
|
9942
|
+
if (!stat6.isDirectory()) {
|
|
9774
9943
|
throw new Error(`Snapshot path is not a directory: ${target}`);
|
|
9775
9944
|
}
|
|
9776
9945
|
} catch (err) {
|
|
@@ -9782,21 +9951,21 @@ async function restoreSnapshot(projectRoot, ts) {
|
|
|
9782
9951
|
throw err;
|
|
9783
9952
|
}
|
|
9784
9953
|
await createSnapshot(projectRoot, { reason: "restore", protectedTs: ts });
|
|
9785
|
-
const teamixDir =
|
|
9786
|
-
const live = await
|
|
9954
|
+
const teamixDir = path44.join(projectRoot, TEAMIX_DIR6);
|
|
9955
|
+
const live = await fs32.readdir(teamixDir, { withFileTypes: true });
|
|
9787
9956
|
for (const entry of live) {
|
|
9788
9957
|
if (entry.name === SNAPSHOTS_DIR) continue;
|
|
9789
|
-
await
|
|
9958
|
+
await fs32.rm(path44.join(teamixDir, entry.name), {
|
|
9790
9959
|
recursive: true,
|
|
9791
9960
|
force: true
|
|
9792
9961
|
});
|
|
9793
9962
|
}
|
|
9794
|
-
const snapshotEntries = await
|
|
9963
|
+
const snapshotEntries = await fs32.readdir(target, { withFileTypes: true });
|
|
9795
9964
|
for (const entry of snapshotEntries) {
|
|
9796
9965
|
if (entry.name === META_FILE) continue;
|
|
9797
|
-
const src =
|
|
9798
|
-
const dst =
|
|
9799
|
-
await
|
|
9966
|
+
const src = path44.join(target, entry.name);
|
|
9967
|
+
const dst = path44.join(teamixDir, entry.name);
|
|
9968
|
+
await fs32.cp(src, dst, { recursive: true });
|
|
9800
9969
|
}
|
|
9801
9970
|
logger.debug(`Restored .teamix-evo/ from snapshot ${ts}`);
|
|
9802
9971
|
}
|
|
@@ -9805,10 +9974,10 @@ async function restoreSnapshot(projectRoot, ts) {
|
|
|
9805
9974
|
init_logger();
|
|
9806
9975
|
init_error();
|
|
9807
9976
|
function createRestoreCommand() {
|
|
9808
|
-
return new
|
|
9977
|
+
return new Command40("restore").description(
|
|
9809
9978
|
"\u56DE\u6EDA .teamix-evo/ \u5230\u6307\u5B9A snapshot\uFF08init/update \u5931\u8D25\u65F6\u4F7F\u7528 \u2014 ADR 0019 \xA72\uFF09"
|
|
9810
9979
|
).argument("[ts]", "\u76EE\u6807 snapshot \u65F6\u95F4\u6233\uFF08\u5982 2026-06-11T20-59-03-000Z\uFF09").option("--list", "\u5217\u51FA\u53EF\u7528 snapshot\uFF08\u4E0D\u505A\u5B9E\u9645\u56DE\u6EDA\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("-y, --yes", "\u8DF3\u8FC7\u4E8C\u6B21\u786E\u8BA4\uFF08destructive\uFF0C\u8BF7\u786E\u8BA4\u65E0\u8BEF\uFF09").action(async (ts, opts) => {
|
|
9811
|
-
const cwd =
|
|
9980
|
+
const cwd = path45.resolve(opts.cwd ?? process.cwd());
|
|
9812
9981
|
try {
|
|
9813
9982
|
const snapshots = await listSnapshots(cwd);
|
|
9814
9983
|
if (opts.list) {
|
|
@@ -9904,14 +10073,14 @@ function printSnapshotTable(snapshots) {
|
|
|
9904
10073
|
}
|
|
9905
10074
|
|
|
9906
10075
|
// src/commands/switch/index.ts
|
|
9907
|
-
import { Command as
|
|
9908
|
-
import * as
|
|
10076
|
+
import { Command as Command41 } from "commander";
|
|
10077
|
+
import * as path47 from "path";
|
|
9909
10078
|
import * as prompts8 from "@clack/prompts";
|
|
9910
10079
|
|
|
9911
10080
|
// src/core/variant-switch.ts
|
|
9912
10081
|
init_fs();
|
|
9913
|
-
import * as
|
|
9914
|
-
import * as
|
|
10082
|
+
import * as path46 from "path";
|
|
10083
|
+
import * as fs33 from "fs/promises";
|
|
9915
10084
|
import {
|
|
9916
10085
|
loadTokensPackageManifest as loadTokensPackageManifest3,
|
|
9917
10086
|
getVariantEntry as getVariantEntry3
|
|
@@ -9948,8 +10117,8 @@ async function runVariantSwitch(options) {
|
|
|
9948
10117
|
const upstreamByBasename = /* @__PURE__ */ new Map();
|
|
9949
10118
|
for (const fileRel of variantEntry.files) {
|
|
9950
10119
|
upstreamByBasename.set(
|
|
9951
|
-
|
|
9952
|
-
|
|
10120
|
+
path46.basename(fileRel),
|
|
10121
|
+
path46.join(packageRoot, fileRel)
|
|
9953
10122
|
);
|
|
9954
10123
|
}
|
|
9955
10124
|
const prior = await readInstalledManifest(projectRoot) ?? {
|
|
@@ -9963,7 +10132,7 @@ async function runVariantSwitch(options) {
|
|
|
9963
10132
|
const priorVersion = installedIdx >= 0 ? prior.installed[installedIdx].version : "0.0.0";
|
|
9964
10133
|
const changes = [];
|
|
9965
10134
|
for (const resource of priorResources) {
|
|
9966
|
-
const consumerBasename =
|
|
10135
|
+
const consumerBasename = path46.basename(resource.target);
|
|
9967
10136
|
const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
|
|
9968
10137
|
const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
|
|
9969
10138
|
if (resource.strategy === "frozen") {
|
|
@@ -9984,7 +10153,7 @@ async function runVariantSwitch(options) {
|
|
|
9984
10153
|
});
|
|
9985
10154
|
continue;
|
|
9986
10155
|
}
|
|
9987
|
-
const upstreamContent = await
|
|
10156
|
+
const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
|
|
9988
10157
|
if (resource.strategy === "regenerable") {
|
|
9989
10158
|
const newHash = computeHash(upstreamContent);
|
|
9990
10159
|
if (newHash === resource.hash) {
|
|
@@ -10037,12 +10206,12 @@ async function runVariantSwitch(options) {
|
|
|
10037
10206
|
}
|
|
10038
10207
|
const refreshedResources = [];
|
|
10039
10208
|
for (const resource of priorResources) {
|
|
10040
|
-
const consumerAbs =
|
|
10041
|
-
const consumerBasename =
|
|
10209
|
+
const consumerAbs = path46.isAbsolute(resource.target) ? resource.target : path46.join(projectRoot, resource.target);
|
|
10210
|
+
const consumerBasename = path46.basename(resource.target);
|
|
10042
10211
|
const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
|
|
10043
10212
|
const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
|
|
10044
10213
|
if (resource.strategy === "regenerable" && upstreamAbs) {
|
|
10045
|
-
const upstreamContent = await
|
|
10214
|
+
const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
|
|
10046
10215
|
await writeFileSafe(consumerAbs, upstreamContent);
|
|
10047
10216
|
logger.debug(`[variant-switch] rewrite regenerable: ${resource.target}`);
|
|
10048
10217
|
refreshedResources.push({
|
|
@@ -10052,8 +10221,8 @@ async function runVariantSwitch(options) {
|
|
|
10052
10221
|
continue;
|
|
10053
10222
|
}
|
|
10054
10223
|
if (resource.strategy === "managed" && upstreamAbs && await fileExists(consumerAbs)) {
|
|
10055
|
-
const upstreamContent = await
|
|
10056
|
-
const consumerContent = await
|
|
10224
|
+
const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
|
|
10225
|
+
const consumerContent = await fs33.readFile(consumerAbs, "utf-8");
|
|
10057
10226
|
const merged = mergeManagedRegions(upstreamContent, consumerContent);
|
|
10058
10227
|
if (merged !== consumerContent) {
|
|
10059
10228
|
await writeFileSafe(consumerAbs, merged);
|
|
@@ -10084,7 +10253,7 @@ async function runVariantSwitch(options) {
|
|
|
10084
10253
|
installedAt: now
|
|
10085
10254
|
};
|
|
10086
10255
|
await writeFileSafe(
|
|
10087
|
-
|
|
10256
|
+
path46.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
|
|
10088
10257
|
JSON.stringify(lock, null, 2) + "\n"
|
|
10089
10258
|
);
|
|
10090
10259
|
logger.debug(
|
|
@@ -10201,10 +10370,10 @@ var KIND_LABEL = {
|
|
|
10201
10370
|
unchanged: "unchanged"
|
|
10202
10371
|
};
|
|
10203
10372
|
function createSwitchCommand() {
|
|
10204
|
-
return new
|
|
10373
|
+
return new Command41("switch").description(
|
|
10205
10374
|
"variant \u5207\u6362\uFF1A\u5148\u5C55\u793A file-level diff\uFF0C--apply \u624D\u771F\u5199\uFF08ADR 0019 \xA7D3\uFF09"
|
|
10206
10375
|
).argument("<new-variant>", "\u76EE\u6807 variant id\uFF08\u5982 opentrek / uni-manager\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("--apply", "\u771F\u6B63\u6267\u884C\u5207\u6362\uFF08\u9ED8\u8BA4 dry-run\uFF0C\u4EC5\u5C55\u793A\u8BA1\u5212\uFF09").option("-y, --yes", "\u8DF3\u8FC7 --apply \u4E8C\u6B21\u786E\u8BA4\uFF08destructive\uFF0C\u8BF7\u786E\u8BA4\u65E0\u8BEF\uFF09").action(async (newVariant, opts) => {
|
|
10207
|
-
const cwd =
|
|
10376
|
+
const cwd = path47.resolve(opts.cwd ?? process.cwd());
|
|
10208
10377
|
const apply = opts.apply ?? false;
|
|
10209
10378
|
try {
|
|
10210
10379
|
const plan = await runVariantSwitch({
|
|
@@ -10320,7 +10489,7 @@ function printChangePlan(from, to, toVersion, changes) {
|
|
|
10320
10489
|
// src/index.ts
|
|
10321
10490
|
var require9 = createRequire9(import.meta.url);
|
|
10322
10491
|
var { version } = require9("../package.json");
|
|
10323
|
-
var program = new
|
|
10492
|
+
var program = new Command42();
|
|
10324
10493
|
program.name("teamix-evo").description("Where ideas evolve. \u2014 AI Coding \u5957\u4EF6").version(version);
|
|
10325
10494
|
program.addCommand(tokensCommand);
|
|
10326
10495
|
program.addCommand(skillsCommand);
|
|
@@ -10331,6 +10500,7 @@ program.addCommand(lintCommand);
|
|
|
10331
10500
|
program.addCommand(initCommand5);
|
|
10332
10501
|
program.addCommand(updateCommand5);
|
|
10333
10502
|
program.addCommand(migrateCommand);
|
|
10503
|
+
program.addCommand(graftCommand);
|
|
10334
10504
|
program.addCommand(restoreCommand);
|
|
10335
10505
|
program.addCommand(switchCommand);
|
|
10336
10506
|
function enableHelpAfterError(cmd) {
|