teamix-evo 0.16.0 → 0.18.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 +36 -35
- 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 +627 -61
- 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);
|
|
@@ -2395,11 +2395,11 @@ var uninstallCommand = new Command5("uninstall").description(
|
|
|
2395
2395
|
`Will remove ${removable.length} file(s); keep ${kept} managed file(s).`
|
|
2396
2396
|
);
|
|
2397
2397
|
if (!opts.yes) {
|
|
2398
|
-
const
|
|
2398
|
+
const confirm8 = await prompts.confirm({
|
|
2399
2399
|
message: "\u786E\u8BA4\u5378\u8F7D tokens \u53D8\u4F53\uFF1F",
|
|
2400
2400
|
initialValue: false
|
|
2401
2401
|
});
|
|
2402
|
-
if (prompts.isCancel(
|
|
2402
|
+
if (prompts.isCancel(confirm8) || !confirm8) {
|
|
2403
2403
|
logger.info("Cancelled.");
|
|
2404
2404
|
return;
|
|
2405
2405
|
}
|
|
@@ -4583,11 +4583,11 @@ async function runFullUninstall(args) {
|
|
|
4583
4583
|
`Will remove ${resources.length} skill file(s) installed by ${SKILLS_PACKAGE3}.`
|
|
4584
4584
|
);
|
|
4585
4585
|
if (!opts.yes) {
|
|
4586
|
-
const
|
|
4586
|
+
const confirm8 = await prompts4.confirm({
|
|
4587
4587
|
message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
|
|
4588
4588
|
initialValue: false
|
|
4589
4589
|
});
|
|
4590
|
-
if (prompts4.isCancel(
|
|
4590
|
+
if (prompts4.isCancel(confirm8) || !confirm8) {
|
|
4591
4591
|
logger.info("Cancelled.");
|
|
4592
4592
|
return;
|
|
4593
4593
|
}
|
|
@@ -4640,11 +4640,11 @@ async function runPartialUninstall(args) {
|
|
|
4640
4640
|
`Will remove ${matched.length} skill(s): ${matched.join(", ")} (${toRemove.length} file(s)).`
|
|
4641
4641
|
);
|
|
4642
4642
|
if (!opts.yes) {
|
|
4643
|
-
const
|
|
4643
|
+
const confirm8 = await prompts4.confirm({
|
|
4644
4644
|
message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
|
|
4645
4645
|
initialValue: false
|
|
4646
4646
|
});
|
|
4647
|
-
if (prompts4.isCancel(
|
|
4647
|
+
if (prompts4.isCancel(confirm8) || !confirm8) {
|
|
4648
4648
|
logger.info("Cancelled.");
|
|
4649
4649
|
return;
|
|
4650
4650
|
}
|
|
@@ -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,11 +9685,16 @@ 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 path45 from "path";
|
|
9691
|
+
import * as fs32 from "fs/promises";
|
|
9665
9692
|
import * as prompts7 from "@clack/prompts";
|
|
9666
9693
|
|
|
9694
|
+
// src/core/graft-init.ts
|
|
9695
|
+
import { hasManagedRegion as hasManagedRegion5, replaceManagedRegion as replaceManagedRegion4 } from "@teamix-evo/registry";
|
|
9696
|
+
init_state();
|
|
9697
|
+
|
|
9667
9698
|
// src/core/snapshot.ts
|
|
9668
9699
|
init_logger();
|
|
9669
9700
|
import * as fs31 from "fs/promises";
|
|
@@ -9672,6 +9703,7 @@ var TEAMIX_DIR6 = ".teamix-evo";
|
|
|
9672
9703
|
var SNAPSHOTS_DIR = ".snapshots";
|
|
9673
9704
|
var META_FILE = "_meta.json";
|
|
9674
9705
|
var DEFAULT_KEEP = 5;
|
|
9706
|
+
var SNAPSHOT_REASONS = ["init", "update", "switch", "restore", "graft", "manual"];
|
|
9675
9707
|
function isoToFsSafe3(iso) {
|
|
9676
9708
|
return iso.replace(/[:.]/g, "-");
|
|
9677
9709
|
}
|
|
@@ -9684,8 +9716,8 @@ function fsSafeToIso(safe) {
|
|
|
9684
9716
|
async function createSnapshot(projectRoot, opts = {}) {
|
|
9685
9717
|
const teamixDir = path43.join(projectRoot, TEAMIX_DIR6);
|
|
9686
9718
|
try {
|
|
9687
|
-
const
|
|
9688
|
-
if (!
|
|
9719
|
+
const stat6 = await fs31.stat(teamixDir);
|
|
9720
|
+
if (!stat6.isDirectory()) return null;
|
|
9689
9721
|
} catch (err) {
|
|
9690
9722
|
if (err.code === "ENOENT") return null;
|
|
9691
9723
|
throw err;
|
|
@@ -9737,7 +9769,7 @@ async function listSnapshots(projectRoot) {
|
|
|
9737
9769
|
const raw = await fs31.readFile(path43.join(dir, META_FILE), "utf-8");
|
|
9738
9770
|
const parsed = JSON.parse(raw);
|
|
9739
9771
|
if (typeof parsed.ts === "string") isoTs = parsed.ts;
|
|
9740
|
-
if (typeof parsed.reason === "string" &&
|
|
9772
|
+
if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
|
|
9741
9773
|
parsed.reason
|
|
9742
9774
|
)) {
|
|
9743
9775
|
reason = parsed.reason;
|
|
@@ -9769,8 +9801,8 @@ async function restoreSnapshot(projectRoot, ts) {
|
|
|
9769
9801
|
const snapshotRoot = path43.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
|
|
9770
9802
|
const target = path43.join(snapshotRoot, ts);
|
|
9771
9803
|
try {
|
|
9772
|
-
const
|
|
9773
|
-
if (!
|
|
9804
|
+
const stat6 = await fs31.stat(target);
|
|
9805
|
+
if (!stat6.isDirectory()) {
|
|
9774
9806
|
throw new Error(`Snapshot path is not a directory: ${target}`);
|
|
9775
9807
|
}
|
|
9776
9808
|
} catch (err) {
|
|
@@ -9801,14 +9833,547 @@ async function restoreSnapshot(projectRoot, ts) {
|
|
|
9801
9833
|
logger.debug(`Restored .teamix-evo/ from snapshot ${ts}`);
|
|
9802
9834
|
}
|
|
9803
9835
|
|
|
9836
|
+
// src/core/graft-init.ts
|
|
9837
|
+
init_error();
|
|
9838
|
+
init_logger();
|
|
9839
|
+
init_fs();
|
|
9840
|
+
import * as fsNode2 from "fs/promises";
|
|
9841
|
+
import * as path44 from "path";
|
|
9842
|
+
var CRITICAL_STEPS2 = /* @__PURE__ */ new Set([
|
|
9843
|
+
"ensure-teamix-dir",
|
|
9844
|
+
"tokens",
|
|
9845
|
+
"ui-init",
|
|
9846
|
+
"skills"
|
|
9847
|
+
]);
|
|
9848
|
+
var AGENTS_MD_GRAFT_MANAGED_ID = "teamix-evo-graft";
|
|
9849
|
+
var GITIGNORE_MARKER_START2 = "# >>> teamix-evo:managed >>>";
|
|
9850
|
+
var GITIGNORE_MARKER_END2 = "# <<< teamix-evo:managed <<<";
|
|
9851
|
+
var GITIGNORE_RULES2 = [
|
|
9852
|
+
"# Runtime artifacts (regenerable / archives)",
|
|
9853
|
+
".teamix-evo/.snapshots/",
|
|
9854
|
+
".teamix-evo/.backups/",
|
|
9855
|
+
".teamix-evo/.upgrade-staging/",
|
|
9856
|
+
".teamix-evo/.upgrade-hints/"
|
|
9857
|
+
];
|
|
9858
|
+
var LEGACY_LIB_META = {
|
|
9859
|
+
fusion: {
|
|
9860
|
+
displayName: "Fusion Design",
|
|
9861
|
+
imports: ["teamix/ui", "@alifd/next", "@ali/teamix-material"]
|
|
9862
|
+
},
|
|
9863
|
+
antd: {
|
|
9864
|
+
displayName: "Ant Design",
|
|
9865
|
+
imports: ["antd", "@ant-design/*"]
|
|
9866
|
+
},
|
|
9867
|
+
element: {
|
|
9868
|
+
displayName: "Element UI",
|
|
9869
|
+
imports: ["element-ui", "element-plus"]
|
|
9870
|
+
}
|
|
9871
|
+
};
|
|
9872
|
+
async function runGraftInit(options) {
|
|
9873
|
+
const {
|
|
9874
|
+
projectRoot,
|
|
9875
|
+
variant,
|
|
9876
|
+
legacyLib,
|
|
9877
|
+
onStep
|
|
9878
|
+
} = options;
|
|
9879
|
+
const ide = options.ide ?? "qoder";
|
|
9880
|
+
const ides = options.ides ?? ["qoder", "claude"];
|
|
9881
|
+
const scope = options.scope ?? "project";
|
|
9882
|
+
const steps = [];
|
|
9883
|
+
let aborted = false;
|
|
9884
|
+
function record(step) {
|
|
9885
|
+
steps.push(step);
|
|
9886
|
+
onStep?.(step);
|
|
9887
|
+
}
|
|
9888
|
+
function recordFailure(name, err) {
|
|
9889
|
+
const message = getErrorMessage(err);
|
|
9890
|
+
record({ name, status: "fail", detail: message });
|
|
9891
|
+
if (CRITICAL_STEPS2.has(name)) aborted = true;
|
|
9892
|
+
}
|
|
9893
|
+
try {
|
|
9894
|
+
await ensureTeamixDir(projectRoot);
|
|
9895
|
+
record({ name: "ensure-teamix-dir", status: "ok" });
|
|
9896
|
+
} catch (err) {
|
|
9897
|
+
recordFailure("ensure-teamix-dir", err);
|
|
9898
|
+
}
|
|
9899
|
+
if (!aborted) {
|
|
9900
|
+
try {
|
|
9901
|
+
const snap = await createSnapshot(projectRoot, { reason: "graft" });
|
|
9902
|
+
record({
|
|
9903
|
+
name: "snapshot",
|
|
9904
|
+
status: "ok",
|
|
9905
|
+
detail: snap ? `snapshot ${snap.ts}` : "empty .teamix-evo/ \u2014 nothing to snapshot"
|
|
9906
|
+
});
|
|
9907
|
+
} catch (err) {
|
|
9908
|
+
recordFailure("snapshot", err);
|
|
9909
|
+
}
|
|
9910
|
+
} else {
|
|
9911
|
+
record({ name: "snapshot", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
9912
|
+
}
|
|
9913
|
+
if (!aborted) {
|
|
9914
|
+
try {
|
|
9915
|
+
const result = await runTokensInit({ projectRoot, variant, ide });
|
|
9916
|
+
const detail = result.status === "installed" ? `${result.packageName}@${result.version} (${result.count} files)` : result.status;
|
|
9917
|
+
record({ name: "tokens", status: "ok", detail });
|
|
9918
|
+
} catch (err) {
|
|
9919
|
+
recordFailure("tokens", err);
|
|
9920
|
+
}
|
|
9921
|
+
} else {
|
|
9922
|
+
record({ name: "tokens", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
9923
|
+
}
|
|
9924
|
+
if (!aborted) {
|
|
9925
|
+
try {
|
|
9926
|
+
const initResult = await runUiInit({ projectRoot, ide });
|
|
9927
|
+
record({
|
|
9928
|
+
name: "ui-init",
|
|
9929
|
+
status: "ok",
|
|
9930
|
+
detail: initResult.status === "installed" ? "config.json packages.ui written" : initResult.status
|
|
9931
|
+
});
|
|
9932
|
+
} catch (err) {
|
|
9933
|
+
recordFailure("ui-init", err);
|
|
9934
|
+
}
|
|
9935
|
+
} else {
|
|
9936
|
+
record({ name: "ui-init", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
9937
|
+
}
|
|
9938
|
+
const collectedNpmDeps = {};
|
|
9939
|
+
if (!aborted) {
|
|
9940
|
+
try {
|
|
9941
|
+
const { manifest } = await loadUiData("@teamix-evo/ui");
|
|
9942
|
+
const allIds = manifest.entries.map((e) => e.id);
|
|
9943
|
+
const addResult = await runUiAdd({
|
|
9944
|
+
projectRoot,
|
|
9945
|
+
ids: allIds,
|
|
9946
|
+
overwrite: true
|
|
9947
|
+
});
|
|
9948
|
+
record({
|
|
9949
|
+
name: "ui-add",
|
|
9950
|
+
status: "ok",
|
|
9951
|
+
detail: `${addResult.orderedIds.length} entries (${addResult.written} written, ${addResult.skipped} skipped)`
|
|
9952
|
+
});
|
|
9953
|
+
Object.assign(collectedNpmDeps, addResult.npmDependencies);
|
|
9954
|
+
} catch (err) {
|
|
9955
|
+
recordFailure("ui-add", err);
|
|
9956
|
+
}
|
|
9957
|
+
} else {
|
|
9958
|
+
record({ name: "ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
9959
|
+
}
|
|
9960
|
+
if (!aborted) {
|
|
9961
|
+
try {
|
|
9962
|
+
const listing = await listBizUiEntries(variant);
|
|
9963
|
+
if (listing.entries.length === 0) {
|
|
9964
|
+
record({
|
|
9965
|
+
name: "biz-ui-add",
|
|
9966
|
+
status: "skip",
|
|
9967
|
+
detail: `no biz-ui entries for variant "${variant}"`
|
|
9968
|
+
});
|
|
9969
|
+
} else {
|
|
9970
|
+
const allIds = listing.entries.map((e) => e.id);
|
|
9971
|
+
const result = await runBizUiAdd({
|
|
9972
|
+
projectRoot,
|
|
9973
|
+
variant,
|
|
9974
|
+
ids: allIds,
|
|
9975
|
+
overwrite: true
|
|
9976
|
+
});
|
|
9977
|
+
record({
|
|
9978
|
+
name: "biz-ui-add",
|
|
9979
|
+
status: "ok",
|
|
9980
|
+
detail: `${result.orderedIds.length} entries (${result.written} written, ${result.skipped} skipped)`
|
|
9981
|
+
});
|
|
9982
|
+
if (result.npmDependencies) {
|
|
9983
|
+
Object.assign(collectedNpmDeps, result.npmDependencies);
|
|
9984
|
+
}
|
|
9985
|
+
}
|
|
9986
|
+
} catch (err) {
|
|
9987
|
+
recordFailure("biz-ui-add", err);
|
|
9988
|
+
}
|
|
9989
|
+
} else {
|
|
9990
|
+
record({ name: "biz-ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
9991
|
+
}
|
|
9992
|
+
if (!aborted && Object.keys(collectedNpmDeps).length > 0) {
|
|
9993
|
+
try {
|
|
9994
|
+
await installProjectDeps({
|
|
9995
|
+
projectRoot,
|
|
9996
|
+
npmDependencies: collectedNpmDeps,
|
|
9997
|
+
skipInstall: options.skipInstall ?? false
|
|
9998
|
+
});
|
|
9999
|
+
} catch (err) {
|
|
10000
|
+
logger.warn(
|
|
10001
|
+
`\u5B89\u88C5 ui/biz-ui \u4F20\u9012\u4F9D\u8D56\u5931\u8D25\uFF1A${getErrorMessage(err)}\uFF08\u53EF\u624B\u52A8\u8FD0\u884C \`npm install\` \u91CD\u8BD5\uFF09`
|
|
10002
|
+
);
|
|
10003
|
+
}
|
|
10004
|
+
}
|
|
10005
|
+
if (!aborted) {
|
|
10006
|
+
try {
|
|
10007
|
+
const result = await runSkillsInit({ projectRoot, ides, scope, ide });
|
|
10008
|
+
if (result.status === "already-initialized") {
|
|
10009
|
+
record({ name: "skills", status: "ok", detail: "already-initialized" });
|
|
10010
|
+
} else {
|
|
10011
|
+
record({
|
|
10012
|
+
name: "skills",
|
|
10013
|
+
status: "ok",
|
|
10014
|
+
detail: `${result.skillCount} skills, ${result.fileCount} files`
|
|
10015
|
+
});
|
|
10016
|
+
}
|
|
10017
|
+
} catch (err) {
|
|
10018
|
+
recordFailure("skills", err);
|
|
10019
|
+
}
|
|
10020
|
+
} else {
|
|
10021
|
+
record({ name: "skills", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
10022
|
+
}
|
|
10023
|
+
if (!aborted) {
|
|
10024
|
+
try {
|
|
10025
|
+
const result = await runGenerateAgentsMd({
|
|
10026
|
+
projectRoot,
|
|
10027
|
+
variant,
|
|
10028
|
+
skillIds: [
|
|
10029
|
+
`teamix-evo-design-${variant}`,
|
|
10030
|
+
`teamix-evo-code-${variant}`
|
|
10031
|
+
],
|
|
10032
|
+
globalSkillIds: ["teamix-evo-manage"],
|
|
10033
|
+
mode: "merge-managed"
|
|
10034
|
+
});
|
|
10035
|
+
record({
|
|
10036
|
+
name: "agents-md",
|
|
10037
|
+
status: "ok",
|
|
10038
|
+
detail: `${result.skillCount} skill index (${result.merge})`
|
|
10039
|
+
});
|
|
10040
|
+
} catch (err) {
|
|
10041
|
+
recordFailure("agents-md", err);
|
|
10042
|
+
}
|
|
10043
|
+
} else {
|
|
10044
|
+
record({ name: "agents-md", status: "skip", detail: "aborted" });
|
|
10045
|
+
}
|
|
10046
|
+
if (!aborted) {
|
|
10047
|
+
try {
|
|
10048
|
+
const agentsMdPath = path44.join(projectRoot, "AGENTS.md");
|
|
10049
|
+
const existing = await readFileOrNull(agentsMdPath) ?? "";
|
|
10050
|
+
const meta = LEGACY_LIB_META[legacyLib] ?? {
|
|
10051
|
+
displayName: legacyLib,
|
|
10052
|
+
imports: [legacyLib]
|
|
10053
|
+
};
|
|
10054
|
+
const importsStr = meta.imports.map((i) => `\`${i}\``).join("\u3001");
|
|
10055
|
+
const graftBody = renderGraftManagedBody(meta.displayName, importsStr);
|
|
10056
|
+
let output;
|
|
10057
|
+
if (hasManagedRegion5(existing, AGENTS_MD_GRAFT_MANAGED_ID)) {
|
|
10058
|
+
output = replaceManagedRegion4(
|
|
10059
|
+
existing,
|
|
10060
|
+
AGENTS_MD_GRAFT_MANAGED_ID,
|
|
10061
|
+
graftBody
|
|
10062
|
+
);
|
|
10063
|
+
} else {
|
|
10064
|
+
const wrapped = wrapGraftManagedBlock(graftBody);
|
|
10065
|
+
output = existing.trimEnd() + "\n\n" + wrapped + "\n";
|
|
10066
|
+
}
|
|
10067
|
+
await fsNode2.writeFile(agentsMdPath, output, "utf-8");
|
|
10068
|
+
record({ name: "agents-md-graft", status: "ok", detail: `dual-stack rules for ${legacyLib}` });
|
|
10069
|
+
} catch (err) {
|
|
10070
|
+
recordFailure("agents-md-graft", err);
|
|
10071
|
+
}
|
|
10072
|
+
} else {
|
|
10073
|
+
record({ name: "agents-md-graft", status: "skip", detail: "aborted" });
|
|
10074
|
+
}
|
|
10075
|
+
if (!aborted) {
|
|
10076
|
+
try {
|
|
10077
|
+
const uiResult = await landUiMeta(projectRoot);
|
|
10078
|
+
const bizResult = await landBizUiMeta(projectRoot, variant);
|
|
10079
|
+
record({
|
|
10080
|
+
name: "meta-landing",
|
|
10081
|
+
status: "ok",
|
|
10082
|
+
detail: `ui: ${uiResult.metaFilesWritten}/${uiResult.metaFilesTotal}, biz-ui: ${bizResult.metaFilesWritten}/${bizResult.metaFilesTotal}`
|
|
10083
|
+
});
|
|
10084
|
+
} catch (err) {
|
|
10085
|
+
recordFailure("meta-landing", err);
|
|
10086
|
+
}
|
|
10087
|
+
} else {
|
|
10088
|
+
record({ name: "meta-landing", status: "skip", detail: "aborted" });
|
|
10089
|
+
}
|
|
10090
|
+
if (!aborted) {
|
|
10091
|
+
try {
|
|
10092
|
+
const config = await readProjectConfig(projectRoot);
|
|
10093
|
+
if (config) {
|
|
10094
|
+
config.mode = "graft";
|
|
10095
|
+
config.legacyLib = legacyLib;
|
|
10096
|
+
await writeProjectConfig(projectRoot, config);
|
|
10097
|
+
record({ name: "config-mode", status: "ok", detail: `mode=graft, legacyLib=${legacyLib}` });
|
|
10098
|
+
} else {
|
|
10099
|
+
record({ name: "config-mode", status: "skip", detail: "no config.json found to patch" });
|
|
10100
|
+
}
|
|
10101
|
+
} catch (err) {
|
|
10102
|
+
recordFailure("config-mode", err);
|
|
10103
|
+
}
|
|
10104
|
+
} else {
|
|
10105
|
+
record({ name: "config-mode", status: "skip", detail: "aborted" });
|
|
10106
|
+
}
|
|
10107
|
+
if (!aborted) {
|
|
10108
|
+
try {
|
|
10109
|
+
const giPath = path44.join(projectRoot, ".gitignore");
|
|
10110
|
+
let giContent = "";
|
|
10111
|
+
try {
|
|
10112
|
+
giContent = await fsNode2.readFile(giPath, "utf-8");
|
|
10113
|
+
} catch {
|
|
10114
|
+
}
|
|
10115
|
+
if (giContent.includes(GITIGNORE_MARKER_START2)) {
|
|
10116
|
+
record({ name: "gitignore", status: "skip", detail: "teamix-evo markers already present" });
|
|
10117
|
+
} else {
|
|
10118
|
+
const block = [
|
|
10119
|
+
"",
|
|
10120
|
+
GITIGNORE_MARKER_START2,
|
|
10121
|
+
...GITIGNORE_RULES2,
|
|
10122
|
+
GITIGNORE_MARKER_END2,
|
|
10123
|
+
""
|
|
10124
|
+
].join("\n");
|
|
10125
|
+
const separator = giContent.length > 0 && !giContent.endsWith("\n") ? "\n" : "";
|
|
10126
|
+
await fsNode2.writeFile(giPath, giContent + separator + block, "utf-8");
|
|
10127
|
+
record({
|
|
10128
|
+
name: "gitignore",
|
|
10129
|
+
status: "ok",
|
|
10130
|
+
detail: `${GITIGNORE_RULES2.filter((r) => r && !r.startsWith("#")).length} rules appended`
|
|
10131
|
+
});
|
|
10132
|
+
}
|
|
10133
|
+
} catch (err) {
|
|
10134
|
+
recordFailure("gitignore", err);
|
|
10135
|
+
}
|
|
10136
|
+
} else {
|
|
10137
|
+
record({ name: "gitignore", status: "skip", detail: "aborted" });
|
|
10138
|
+
}
|
|
10139
|
+
const status = steps.some((s) => s.status === "fail") ? "partial" : "success";
|
|
10140
|
+
return { status, steps };
|
|
10141
|
+
}
|
|
10142
|
+
function renderGraftManagedBody(legacyLibName, legacyImports) {
|
|
10143
|
+
return `## \u53CC\u6808\u7814\u53D1\u89C4\u5219
|
|
10144
|
+
|
|
10145
|
+
\u672C\u9879\u76EE\u540C\u65F6\u5B58\u5728 ${legacyLibName}\uFF08\u65E7\u6808\uFF09\u548C teamix-evo\uFF08\u65B0\u6808\uFF09\u4E24\u5957\u6280\u672F\u6808\u3002
|
|
10146
|
+
|
|
10147
|
+
### \u5224\u65AD\u89C4\u5219\u2014\u2014\u901A\u8FC7 import \u8BED\u53E5\u8BC6\u522B
|
|
10148
|
+
- \u6587\u4EF6\u4E2D import \u4E86 ${legacyImports} \u2192 **\u65E7\u6808**\uFF0C\u6309 ${legacyLibName} \u89C4\u8303\u7814\u53D1\uFF0C**\u8DF3\u8FC7** teamix-evo \u7684 design / code skill
|
|
10149
|
+
- \u6587\u4EF6\u4E2D import \u4E86 \`@/components/ui\`\u3001\u4F7F\u7528 Tailwind class \u2192 **\u65B0\u6808**\uFF0C\u6B63\u5E38\u89E6\u53D1 teamix-evo design / code skill
|
|
10150
|
+
- \u65B0\u5EFA\u9875\u9762 \u2192 \u9ED8\u8BA4\u4F7F\u7528\u65B0\u6808\uFF08teamix-evo\uFF09
|
|
10151
|
+
|
|
10152
|
+
### \u7981\u6B62\u4E8B\u9879
|
|
10153
|
+
- \u7981\u6B62\u5728\u65E7\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 \`@/components/ui\` \u6216 Tailwind class
|
|
10154
|
+
- \u7981\u6B62\u5728\u65B0\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 ${legacyImports}
|
|
10155
|
+
- \u7981\u6B62\u5728\u540C\u4E00\u6587\u4EF6\u4E2D\u6DF7\u7528\u4E24\u5957\u7EC4\u4EF6\u5E93`;
|
|
10156
|
+
}
|
|
10157
|
+
function wrapGraftManagedBlock(body) {
|
|
10158
|
+
return `<!-- teamix-evo:managed:start id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->
|
|
10159
|
+
${body}
|
|
10160
|
+
<!-- teamix-evo:managed:end id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->`;
|
|
10161
|
+
}
|
|
10162
|
+
|
|
10163
|
+
// src/commands/graft/index.ts
|
|
10164
|
+
init_logger();
|
|
10165
|
+
init_error();
|
|
10166
|
+
init_fs();
|
|
10167
|
+
var APP_ENTRY_CANDIDATES = [
|
|
10168
|
+
"src/app.tsx",
|
|
10169
|
+
"src/app.ts",
|
|
10170
|
+
"src/app.jsx",
|
|
10171
|
+
"src/app.js",
|
|
10172
|
+
"src/index.tsx",
|
|
10173
|
+
"src/index.ts",
|
|
10174
|
+
"src/index.jsx",
|
|
10175
|
+
"src/index.js"
|
|
10176
|
+
];
|
|
10177
|
+
var POSTCSS_CONFIG_CANDIDATES = [
|
|
10178
|
+
"postcss.config.js",
|
|
10179
|
+
"postcss.config.cjs",
|
|
10180
|
+
"postcss.config.mjs",
|
|
10181
|
+
"postcss.config.ts",
|
|
10182
|
+
".postcssrc",
|
|
10183
|
+
".postcssrc.json",
|
|
10184
|
+
".postcssrc.yml",
|
|
10185
|
+
".postcssrc.yaml",
|
|
10186
|
+
".postcssrc.js"
|
|
10187
|
+
];
|
|
10188
|
+
var CONFLICT_PATHS = [
|
|
10189
|
+
{ path: ".teamix-evo", type: "directory" },
|
|
10190
|
+
{ path: "src/components/ui", type: "directory" },
|
|
10191
|
+
{ path: "src/components/business", type: "directory" },
|
|
10192
|
+
{ path: "tokens", type: "directory" }
|
|
10193
|
+
];
|
|
10194
|
+
async function findFirst(cwd, candidates) {
|
|
10195
|
+
for (const c of candidates) {
|
|
10196
|
+
if (await fileExists(path45.join(cwd, c))) return c;
|
|
10197
|
+
}
|
|
10198
|
+
return null;
|
|
10199
|
+
}
|
|
10200
|
+
async function getLegacyLibVersion(cwd, legacyLib) {
|
|
10201
|
+
const pkgRaw = await readFileOrNull(path45.join(cwd, "package.json"));
|
|
10202
|
+
if (!pkgRaw) return "unknown";
|
|
10203
|
+
try {
|
|
10204
|
+
const pkg = JSON.parse(pkgRaw);
|
|
10205
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
10206
|
+
const libKeyMap = {
|
|
10207
|
+
fusion: ["@alifd/next", "@ali/teamix-material"],
|
|
10208
|
+
antd: ["antd"],
|
|
10209
|
+
element: ["element-ui", "element-plus"]
|
|
10210
|
+
};
|
|
10211
|
+
const keys = libKeyMap[legacyLib] ?? [];
|
|
10212
|
+
for (const key of keys) {
|
|
10213
|
+
if (allDeps[key]) return allDeps[key];
|
|
10214
|
+
}
|
|
10215
|
+
} catch {
|
|
10216
|
+
}
|
|
10217
|
+
return "unknown";
|
|
10218
|
+
}
|
|
10219
|
+
async function detectConflicts(cwd) {
|
|
10220
|
+
const conflicts = [];
|
|
10221
|
+
for (const entry of CONFLICT_PATHS) {
|
|
10222
|
+
const full = path45.join(cwd, entry.path);
|
|
10223
|
+
try {
|
|
10224
|
+
const stat6 = await fs32.stat(full);
|
|
10225
|
+
if (entry.type === "directory" && stat6.isDirectory() || entry.type === "file" && stat6.isFile()) {
|
|
10226
|
+
conflicts.push(entry);
|
|
10227
|
+
}
|
|
10228
|
+
} catch {
|
|
10229
|
+
}
|
|
10230
|
+
}
|
|
10231
|
+
return conflicts;
|
|
10232
|
+
}
|
|
10233
|
+
async function analyzeProject(cwd) {
|
|
10234
|
+
const state = await detectProjectState(cwd);
|
|
10235
|
+
if (state.state !== "other") {
|
|
10236
|
+
assertCommandPrecondition("graft", state.state);
|
|
10237
|
+
throw new Error("unreachable");
|
|
10238
|
+
}
|
|
10239
|
+
const legacyLib = state.legacyLib ?? "unknown";
|
|
10240
|
+
const buildTool = state.buildTool ?? "unknown";
|
|
10241
|
+
const legacyVersion = await getLegacyLibVersion(cwd, legacyLib);
|
|
10242
|
+
const BUILD_TOOL_CONFIG_CANDIDATES = {
|
|
10243
|
+
ice: ["build.json"],
|
|
10244
|
+
vite: ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"],
|
|
10245
|
+
webpack: ["webpack.config.js", "webpack.config.ts", "webpack.config.cjs"]
|
|
10246
|
+
};
|
|
10247
|
+
const buildToolConfig = await findFirst(
|
|
10248
|
+
cwd,
|
|
10249
|
+
BUILD_TOOL_CONFIG_CANDIDATES[buildTool] ?? []
|
|
10250
|
+
);
|
|
10251
|
+
const postcssPath = await findFirst(cwd, POSTCSS_CONFIG_CANDIDATES);
|
|
10252
|
+
const appEntry = await findFirst(cwd, APP_ENTRY_CANDIDATES);
|
|
10253
|
+
const conflicts = await detectConflicts(cwd);
|
|
10254
|
+
return {
|
|
10255
|
+
report: {
|
|
10256
|
+
projectRoot: cwd,
|
|
10257
|
+
legacyLib: { name: legacyLib, version: legacyVersion },
|
|
10258
|
+
buildTool: { type: buildTool, configFile: buildToolConfig },
|
|
10259
|
+
postcssConfig: { exists: postcssPath !== null, path: postcssPath },
|
|
10260
|
+
appEntry,
|
|
10261
|
+
conflicts
|
|
10262
|
+
},
|
|
10263
|
+
legacyLib
|
|
10264
|
+
};
|
|
10265
|
+
}
|
|
10266
|
+
function printReport(report) {
|
|
10267
|
+
logger.info("Teamix Evo Graft \u2014 \u53CC\u6808\u5171\u5B58\u524D\u7F6E\u68C0\u67E5");
|
|
10268
|
+
logger.info("");
|
|
10269
|
+
logger.info(` \u9879\u76EE\u76EE\u5F55\uFF1A${report.projectRoot}`);
|
|
10270
|
+
logger.info(
|
|
10271
|
+
` \u65E7\u7EC4\u4EF6\u5E93\uFF1A${report.legacyLib.name} (${report.legacyLib.version})`
|
|
10272
|
+
);
|
|
10273
|
+
logger.info(` \u6784\u5EFA\u5DE5\u5177\uFF1A${report.buildTool.type}`);
|
|
10274
|
+
logger.info(
|
|
10275
|
+
` PostCSS \u914D\u7F6E\uFF1A${report.postcssConfig.path ?? "\u672A\u68C0\u6D4B\u5230"}`
|
|
10276
|
+
);
|
|
10277
|
+
logger.info(` App \u5165\u53E3\uFF1A${report.appEntry ?? "\u672A\u68C0\u6D4B\u5230"}`);
|
|
10278
|
+
if (report.conflicts.length > 0) {
|
|
10279
|
+
logger.info("");
|
|
10280
|
+
logger.warn(" \u5DF2\u5B58\u5728\u7684\u8DEF\u5F84\uFF08\u53EF\u80FD\u51B2\u7A81\uFF09\uFF1A");
|
|
10281
|
+
for (const c of report.conflicts) {
|
|
10282
|
+
logger.warn(` ${c.path} (${c.type})`);
|
|
10283
|
+
}
|
|
10284
|
+
}
|
|
10285
|
+
}
|
|
10286
|
+
var graftCommand = new Command39("graft").description(
|
|
10287
|
+
"\u53E0\u52A0 Teamix Evo AICoding \u80FD\u529B\u5230\u73B0\u6709\u9879\u76EE\uFF08\u53CC\u6808\u5171\u5B58\uFF0CADR 0047\uFF09"
|
|
10288
|
+
).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").option("--apply", "\u6267\u884C graft pipeline\uFF08\u9ED8\u8BA4\u4EC5\u524D\u7F6E\u68C0\u67E5\uFF09").option("-y, --yes", "\u8DF3\u8FC7 --apply \u4E8C\u6B21\u786E\u8BA4").action(async (opts) => {
|
|
10289
|
+
const cwd = path45.resolve(opts.cwd ?? process.cwd());
|
|
10290
|
+
const apply = opts.apply ?? false;
|
|
10291
|
+
try {
|
|
10292
|
+
const { report, legacyLib } = await analyzeProject(cwd);
|
|
10293
|
+
if (opts.json) {
|
|
10294
|
+
console.log(JSON.stringify(report, null, 2));
|
|
10295
|
+
} else {
|
|
10296
|
+
printReport(report);
|
|
10297
|
+
}
|
|
10298
|
+
if (!apply) {
|
|
10299
|
+
if (!opts.json) {
|
|
10300
|
+
logger.info("");
|
|
10301
|
+
logger.info(
|
|
10302
|
+
"\u524D\u7F6E\u68C0\u67E5\u5B8C\u6210\u3002\u52A0 --apply --variant <v> \u6267\u884C graft pipeline\u3002"
|
|
10303
|
+
);
|
|
10304
|
+
}
|
|
10305
|
+
return;
|
|
10306
|
+
}
|
|
10307
|
+
if (!opts.variant) {
|
|
10308
|
+
logger.error("--apply \u9700\u8981\u6307\u5B9A --variant\uFF08\u5982 --variant opentrek\uFF09");
|
|
10309
|
+
process.exitCode = 1;
|
|
10310
|
+
return;
|
|
10311
|
+
}
|
|
10312
|
+
if (legacyLib === "unknown") {
|
|
10313
|
+
logger.error(
|
|
10314
|
+
"\u672A\u8BC6\u522B\u65E7\u7EC4\u4EF6\u5E93\u3002\u8BF7\u786E\u8BA4 package.json \u4E2D\u5305\u542B @alifd/next / antd / element-ui \u7B49\u4F9D\u8D56\u3002"
|
|
10315
|
+
);
|
|
10316
|
+
process.exitCode = 1;
|
|
10317
|
+
return;
|
|
10318
|
+
}
|
|
10319
|
+
const isInteractive = Boolean(process.stdin.isTTY);
|
|
10320
|
+
if (!opts.yes && isInteractive) {
|
|
10321
|
+
logger.info("");
|
|
10322
|
+
logger.info(
|
|
10323
|
+
`graft --apply \u5C06\u5B89\u88C5 teamix-evo \u5168\u6808\uFF08tokens + UI + biz-ui + skills + AGENTS.md\uFF09\uFF0Cvariant = "${opts.variant}"\u3002`
|
|
10324
|
+
);
|
|
10325
|
+
const confirmed = await prompts7.confirm({
|
|
10326
|
+
message: "\u7EE7\u7EED\u6267\u884C\uFF1F"
|
|
10327
|
+
});
|
|
10328
|
+
if (prompts7.isCancel(confirmed) || !confirmed) {
|
|
10329
|
+
logger.info("\u5DF2\u53D6\u6D88\u3002");
|
|
10330
|
+
return;
|
|
10331
|
+
}
|
|
10332
|
+
}
|
|
10333
|
+
logger.info("");
|
|
10334
|
+
logger.info("\u6267\u884C graft pipeline\u2026");
|
|
10335
|
+
logger.info("");
|
|
10336
|
+
const result = await runGraftInit({
|
|
10337
|
+
projectRoot: cwd,
|
|
10338
|
+
variant: opts.variant,
|
|
10339
|
+
legacyLib,
|
|
10340
|
+
onStep: (step) => {
|
|
10341
|
+
const icon = STEP_ICON[step.status];
|
|
10342
|
+
const detail = step.detail ? ` \u2014 ${step.detail}` : "";
|
|
10343
|
+
logger.info(` ${icon} ${step.name}${detail}`);
|
|
10344
|
+
}
|
|
10345
|
+
});
|
|
10346
|
+
logger.info("");
|
|
10347
|
+
if (result.status === "success") {
|
|
10348
|
+
logger.success(
|
|
10349
|
+
`graft \u5B8C\u6210\uFF08${result.steps.filter((s) => s.status === "ok").length}/${result.steps.length} \u6B65\u6210\u529F\uFF09`
|
|
10350
|
+
);
|
|
10351
|
+
} else {
|
|
10352
|
+
logger.warn("graft \u90E8\u5206\u5B8C\u6210\uFF08\u542B\u5931\u8D25\u6B65\u9AA4\uFF09\uFF0C\u8BE6\u89C1\u4E0A\u65B9\u660E\u7EC6\u3002");
|
|
10353
|
+
const failed = result.steps.filter((s) => s.status === "fail");
|
|
10354
|
+
for (const s of failed) {
|
|
10355
|
+
logger.error(` \u2716 ${s.name}: ${s.detail ?? "unknown error"}`);
|
|
10356
|
+
}
|
|
10357
|
+
process.exitCode = 1;
|
|
10358
|
+
}
|
|
10359
|
+
} catch (err) {
|
|
10360
|
+
logger.error(`graft \u5931\u8D25\uFF1A${getErrorMessage(err)}`);
|
|
10361
|
+
logger.debug(err.stack ?? "");
|
|
10362
|
+
process.exitCode = 1;
|
|
10363
|
+
}
|
|
10364
|
+
});
|
|
10365
|
+
|
|
9804
10366
|
// src/commands/restore/index.ts
|
|
10367
|
+
import { Command as Command40 } from "commander";
|
|
10368
|
+
import * as path46 from "path";
|
|
10369
|
+
import * as prompts8 from "@clack/prompts";
|
|
9805
10370
|
init_logger();
|
|
9806
10371
|
init_error();
|
|
9807
10372
|
function createRestoreCommand() {
|
|
9808
|
-
return new
|
|
10373
|
+
return new Command40("restore").description(
|
|
9809
10374
|
"\u56DE\u6EDA .teamix-evo/ \u5230\u6307\u5B9A snapshot\uFF08init/update \u5931\u8D25\u65F6\u4F7F\u7528 \u2014 ADR 0019 \xA72\uFF09"
|
|
9810
10375
|
).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 =
|
|
10376
|
+
const cwd = path46.resolve(opts.cwd ?? process.cwd());
|
|
9812
10377
|
try {
|
|
9813
10378
|
const snapshots = await listSnapshots(cwd);
|
|
9814
10379
|
if (opts.list) {
|
|
@@ -9856,10 +10421,10 @@ function createRestoreCommand() {
|
|
|
9856
10421
|
logger.info(
|
|
9857
10422
|
'\u56DE\u6EDA\u524D\u4F1A\u81EA\u52A8\u518D\u505A\u4E00\u6B21 reason="restore" \u7684\u5B89\u5168 snapshot\uFF0C\u53EF\u4E8C\u6B21\u56DE\u6EDA\u3002'
|
|
9858
10423
|
);
|
|
9859
|
-
const confirmed = await
|
|
10424
|
+
const confirmed = await prompts8.confirm({
|
|
9860
10425
|
message: "\u7EE7\u7EED\u56DE\u6EDA\uFF1F"
|
|
9861
10426
|
});
|
|
9862
|
-
if (
|
|
10427
|
+
if (prompts8.isCancel(confirmed) || !confirmed) {
|
|
9863
10428
|
logger.info("\u5DF2\u53D6\u6D88\u3002");
|
|
9864
10429
|
return;
|
|
9865
10430
|
}
|
|
@@ -9904,14 +10469,14 @@ function printSnapshotTable(snapshots) {
|
|
|
9904
10469
|
}
|
|
9905
10470
|
|
|
9906
10471
|
// src/commands/switch/index.ts
|
|
9907
|
-
import { Command as
|
|
9908
|
-
import * as
|
|
9909
|
-
import * as
|
|
10472
|
+
import { Command as Command41 } from "commander";
|
|
10473
|
+
import * as path48 from "path";
|
|
10474
|
+
import * as prompts9 from "@clack/prompts";
|
|
9910
10475
|
|
|
9911
10476
|
// src/core/variant-switch.ts
|
|
9912
10477
|
init_fs();
|
|
9913
|
-
import * as
|
|
9914
|
-
import * as
|
|
10478
|
+
import * as path47 from "path";
|
|
10479
|
+
import * as fs33 from "fs/promises";
|
|
9915
10480
|
import {
|
|
9916
10481
|
loadTokensPackageManifest as loadTokensPackageManifest3,
|
|
9917
10482
|
getVariantEntry as getVariantEntry3
|
|
@@ -9948,8 +10513,8 @@ async function runVariantSwitch(options) {
|
|
|
9948
10513
|
const upstreamByBasename = /* @__PURE__ */ new Map();
|
|
9949
10514
|
for (const fileRel of variantEntry.files) {
|
|
9950
10515
|
upstreamByBasename.set(
|
|
9951
|
-
|
|
9952
|
-
|
|
10516
|
+
path47.basename(fileRel),
|
|
10517
|
+
path47.join(packageRoot, fileRel)
|
|
9953
10518
|
);
|
|
9954
10519
|
}
|
|
9955
10520
|
const prior = await readInstalledManifest(projectRoot) ?? {
|
|
@@ -9963,7 +10528,7 @@ async function runVariantSwitch(options) {
|
|
|
9963
10528
|
const priorVersion = installedIdx >= 0 ? prior.installed[installedIdx].version : "0.0.0";
|
|
9964
10529
|
const changes = [];
|
|
9965
10530
|
for (const resource of priorResources) {
|
|
9966
|
-
const consumerBasename =
|
|
10531
|
+
const consumerBasename = path47.basename(resource.target);
|
|
9967
10532
|
const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
|
|
9968
10533
|
const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
|
|
9969
10534
|
if (resource.strategy === "frozen") {
|
|
@@ -9984,7 +10549,7 @@ async function runVariantSwitch(options) {
|
|
|
9984
10549
|
});
|
|
9985
10550
|
continue;
|
|
9986
10551
|
}
|
|
9987
|
-
const upstreamContent = await
|
|
10552
|
+
const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
|
|
9988
10553
|
if (resource.strategy === "regenerable") {
|
|
9989
10554
|
const newHash = computeHash(upstreamContent);
|
|
9990
10555
|
if (newHash === resource.hash) {
|
|
@@ -10037,12 +10602,12 @@ async function runVariantSwitch(options) {
|
|
|
10037
10602
|
}
|
|
10038
10603
|
const refreshedResources = [];
|
|
10039
10604
|
for (const resource of priorResources) {
|
|
10040
|
-
const consumerAbs =
|
|
10041
|
-
const consumerBasename =
|
|
10605
|
+
const consumerAbs = path47.isAbsolute(resource.target) ? resource.target : path47.join(projectRoot, resource.target);
|
|
10606
|
+
const consumerBasename = path47.basename(resource.target);
|
|
10042
10607
|
const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
|
|
10043
10608
|
const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
|
|
10044
10609
|
if (resource.strategy === "regenerable" && upstreamAbs) {
|
|
10045
|
-
const upstreamContent = await
|
|
10610
|
+
const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
|
|
10046
10611
|
await writeFileSafe(consumerAbs, upstreamContent);
|
|
10047
10612
|
logger.debug(`[variant-switch] rewrite regenerable: ${resource.target}`);
|
|
10048
10613
|
refreshedResources.push({
|
|
@@ -10052,8 +10617,8 @@ async function runVariantSwitch(options) {
|
|
|
10052
10617
|
continue;
|
|
10053
10618
|
}
|
|
10054
10619
|
if (resource.strategy === "managed" && upstreamAbs && await fileExists(consumerAbs)) {
|
|
10055
|
-
const upstreamContent = await
|
|
10056
|
-
const consumerContent = await
|
|
10620
|
+
const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
|
|
10621
|
+
const consumerContent = await fs33.readFile(consumerAbs, "utf-8");
|
|
10057
10622
|
const merged = mergeManagedRegions(upstreamContent, consumerContent);
|
|
10058
10623
|
if (merged !== consumerContent) {
|
|
10059
10624
|
await writeFileSafe(consumerAbs, merged);
|
|
@@ -10084,7 +10649,7 @@ async function runVariantSwitch(options) {
|
|
|
10084
10649
|
installedAt: now
|
|
10085
10650
|
};
|
|
10086
10651
|
await writeFileSafe(
|
|
10087
|
-
|
|
10652
|
+
path47.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
|
|
10088
10653
|
JSON.stringify(lock, null, 2) + "\n"
|
|
10089
10654
|
);
|
|
10090
10655
|
logger.debug(
|
|
@@ -10201,10 +10766,10 @@ var KIND_LABEL = {
|
|
|
10201
10766
|
unchanged: "unchanged"
|
|
10202
10767
|
};
|
|
10203
10768
|
function createSwitchCommand() {
|
|
10204
|
-
return new
|
|
10769
|
+
return new Command41("switch").description(
|
|
10205
10770
|
"variant \u5207\u6362\uFF1A\u5148\u5C55\u793A file-level diff\uFF0C--apply \u624D\u771F\u5199\uFF08ADR 0019 \xA7D3\uFF09"
|
|
10206
10771
|
).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 =
|
|
10772
|
+
const cwd = path48.resolve(opts.cwd ?? process.cwd());
|
|
10208
10773
|
const apply = opts.apply ?? false;
|
|
10209
10774
|
try {
|
|
10210
10775
|
const plan = await runVariantSwitch({
|
|
@@ -10250,10 +10815,10 @@ function createSwitchCommand() {
|
|
|
10250
10815
|
logger.info(
|
|
10251
10816
|
'\u6267\u884C\u524D\u4F1A\u81EA\u52A8\u6355\u83B7 reason="switch" snapshot\uFF0C\u53EF\u901A\u8FC7 `teamix-evo restore <ts>` \u56DE\u6EDA\u3002'
|
|
10252
10817
|
);
|
|
10253
|
-
const confirmed = await
|
|
10818
|
+
const confirmed = await prompts9.confirm({
|
|
10254
10819
|
message: `\u7EE7\u7EED\u5207\u6362\u81F3 "${newVariant}"\uFF1F`
|
|
10255
10820
|
});
|
|
10256
|
-
if (
|
|
10821
|
+
if (prompts9.isCancel(confirmed) || !confirmed) {
|
|
10257
10822
|
logger.info("\u5DF2\u53D6\u6D88\u3002");
|
|
10258
10823
|
return;
|
|
10259
10824
|
}
|
|
@@ -10320,7 +10885,7 @@ function printChangePlan(from, to, toVersion, changes) {
|
|
|
10320
10885
|
// src/index.ts
|
|
10321
10886
|
var require9 = createRequire9(import.meta.url);
|
|
10322
10887
|
var { version } = require9("../package.json");
|
|
10323
|
-
var program = new
|
|
10888
|
+
var program = new Command42();
|
|
10324
10889
|
program.name("teamix-evo").description("Where ideas evolve. \u2014 AI Coding \u5957\u4EF6").version(version);
|
|
10325
10890
|
program.addCommand(tokensCommand);
|
|
10326
10891
|
program.addCommand(skillsCommand);
|
|
@@ -10331,6 +10896,7 @@ program.addCommand(lintCommand);
|
|
|
10331
10896
|
program.addCommand(initCommand5);
|
|
10332
10897
|
program.addCommand(updateCommand5);
|
|
10333
10898
|
program.addCommand(migrateCommand);
|
|
10899
|
+
program.addCommand(graftCommand);
|
|
10334
10900
|
program.addCommand(restoreCommand);
|
|
10335
10901
|
program.addCommand(switchCommand);
|
|
10336
10902
|
function enableHelpAfterError(cmd) {
|