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/core/index.js
CHANGED
|
@@ -461,9 +461,9 @@ async function installSkills(options) {
|
|
|
461
461
|
async function renderSkillFiles(skill, options) {
|
|
462
462
|
const { data, packageRoot } = options;
|
|
463
463
|
const sourceAbs = path7.resolve(packageRoot, skill.source);
|
|
464
|
-
const
|
|
464
|
+
const stat4 = await fs6.stat(sourceAbs);
|
|
465
465
|
const rendered = /* @__PURE__ */ new Map();
|
|
466
|
-
if (
|
|
466
|
+
if (stat4.isFile()) {
|
|
467
467
|
const content = await renderSkillContent(sourceAbs, skill, data);
|
|
468
468
|
rendered.set("SKILL.md", content);
|
|
469
469
|
return rendered;
|
|
@@ -726,13 +726,13 @@ async function pruneEmptyIdeSkillDirs(args) {
|
|
|
726
726
|
}
|
|
727
727
|
for (const name of entries) {
|
|
728
728
|
const dir = path7.join(skillsRoot, name);
|
|
729
|
-
let
|
|
729
|
+
let stat4;
|
|
730
730
|
try {
|
|
731
|
-
|
|
731
|
+
stat4 = await fs6.stat(dir);
|
|
732
732
|
} catch {
|
|
733
733
|
continue;
|
|
734
734
|
}
|
|
735
|
-
if (!
|
|
735
|
+
if (!stat4.isDirectory()) continue;
|
|
736
736
|
let children;
|
|
737
737
|
try {
|
|
738
738
|
children = await fs6.readdir(dir);
|
|
@@ -2789,13 +2789,44 @@ async function detectProjectState2(cwd) {
|
|
|
2789
2789
|
significantEntries: []
|
|
2790
2790
|
};
|
|
2791
2791
|
}
|
|
2792
|
+
let legacyLib = "unknown";
|
|
2793
|
+
let buildTool = "unknown";
|
|
2794
|
+
let allDeps = {};
|
|
2795
|
+
if (hasPackageJson) {
|
|
2796
|
+
const pkgRaw = await readFileOrNull(path15.join(absCwd, "package.json"));
|
|
2797
|
+
if (pkgRaw) {
|
|
2798
|
+
try {
|
|
2799
|
+
const pkg = JSON.parse(pkgRaw);
|
|
2800
|
+
allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2801
|
+
} catch {
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
if ("@alifd/next" in allDeps || "@ali/teamix-material" in allDeps) {
|
|
2806
|
+
legacyLib = "fusion";
|
|
2807
|
+
} else if ("antd" in allDeps) {
|
|
2808
|
+
legacyLib = "antd";
|
|
2809
|
+
} else if ("element-ui" in allDeps || "element-plus" in allDeps) {
|
|
2810
|
+
legacyLib = "element";
|
|
2811
|
+
}
|
|
2812
|
+
if (await fileExists(path15.join(absCwd, "build.json"))) {
|
|
2813
|
+
buildTool = "ice";
|
|
2814
|
+
} else if (await fileExists(path15.join(absCwd, "vite.config.ts")) || await fileExists(path15.join(absCwd, "vite.config.js")) || await fileExists(path15.join(absCwd, "vite.config.mts"))) {
|
|
2815
|
+
buildTool = "vite";
|
|
2816
|
+
} else if (await fileExists(path15.join(absCwd, "webpack.config.js")) || await fileExists(path15.join(absCwd, "webpack.config.ts"))) {
|
|
2817
|
+
buildTool = "webpack";
|
|
2818
|
+
} else if ("umi" in allDeps || "@umijs/max" in allDeps) {
|
|
2819
|
+
buildTool = "umi";
|
|
2820
|
+
}
|
|
2792
2821
|
return {
|
|
2793
2822
|
state: "other",
|
|
2794
2823
|
cwd: absCwd,
|
|
2795
2824
|
hasTeamixDir: false,
|
|
2796
2825
|
hasPackageJson,
|
|
2797
2826
|
hasComponentsJson,
|
|
2798
|
-
significantEntries: significant.slice(0, 20).sort()
|
|
2827
|
+
significantEntries: significant.slice(0, 20).sort(),
|
|
2828
|
+
legacyLib,
|
|
2829
|
+
buildTool
|
|
2799
2830
|
};
|
|
2800
2831
|
}
|
|
2801
2832
|
|
|
@@ -2803,7 +2834,8 @@ async function detectProjectState2(cwd) {
|
|
|
2803
2834
|
var COMMAND_LABELS = {
|
|
2804
2835
|
init: "\u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6",
|
|
2805
2836
|
migrate: "shadcn \u9879\u76EE\u8FC1\u79FB\u4E3A Teamix Evo \u5957\u4EF6",
|
|
2806
|
-
update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0"
|
|
2837
|
+
update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0",
|
|
2838
|
+
graft: "\u53E0\u52A0 Teamix Evo \u80FD\u529B"
|
|
2807
2839
|
};
|
|
2808
2840
|
var STATE_LABELS = {
|
|
2809
2841
|
empty: "\u7A7A\u76EE\u5F55",
|
|
@@ -2814,13 +2846,14 @@ var STATE_LABELS = {
|
|
|
2814
2846
|
var VALID_STATES = {
|
|
2815
2847
|
init: "empty",
|
|
2816
2848
|
migrate: "shadcn",
|
|
2817
|
-
update: "teamix-evo"
|
|
2849
|
+
update: "teamix-evo",
|
|
2850
|
+
graft: "other"
|
|
2818
2851
|
};
|
|
2819
2852
|
var STATE_TO_COMMAND = {
|
|
2820
2853
|
empty: "init",
|
|
2821
2854
|
shadcn: "migrate",
|
|
2822
2855
|
"teamix-evo": "update",
|
|
2823
|
-
other:
|
|
2856
|
+
other: "graft"
|
|
2824
2857
|
};
|
|
2825
2858
|
function assertCommandPrecondition(command, state) {
|
|
2826
2859
|
const expected = VALID_STATES[command];
|
|
@@ -2834,13 +2867,6 @@ function assertCommandPrecondition(command, state) {
|
|
|
2834
2867
|
if (suggestion) {
|
|
2835
2868
|
const suggestionLabel = COMMAND_LABELS[suggestion];
|
|
2836
2869
|
logger.info(`\u5EFA\u8BAE\u4F7F\u7528\uFF1Ateamix-evo ${suggestion}\uFF08${suggestionLabel}\uFF09`);
|
|
2837
|
-
} else {
|
|
2838
|
-
logger.info(
|
|
2839
|
-
"\u5F53\u524D\u9879\u76EE\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u76F4\u63A5\u63A5\u5165\u3002"
|
|
2840
|
-
);
|
|
2841
|
-
logger.info(
|
|
2842
|
-
"\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"
|
|
2843
|
-
);
|
|
2844
2870
|
}
|
|
2845
2871
|
process.exitCode = 1;
|
|
2846
2872
|
}
|
|
@@ -2892,8 +2918,8 @@ var STYLELINT_CONFIG_CANDIDATES = [
|
|
|
2892
2918
|
];
|
|
2893
2919
|
async function isDir(target) {
|
|
2894
2920
|
try {
|
|
2895
|
-
const
|
|
2896
|
-
return
|
|
2921
|
+
const stat4 = await fs15.stat(target);
|
|
2922
|
+
return stat4.isDirectory();
|
|
2897
2923
|
} catch {
|
|
2898
2924
|
return false;
|
|
2899
2925
|
}
|
|
@@ -3827,9 +3853,438 @@ function deriveLintChanges(result) {
|
|
|
3827
3853
|
return out;
|
|
3828
3854
|
}
|
|
3829
3855
|
|
|
3830
|
-
// src/core/
|
|
3831
|
-
import
|
|
3856
|
+
// src/core/graft-init.ts
|
|
3857
|
+
import { hasManagedRegion as hasManagedRegion3, replaceManagedRegion as replaceManagedRegion3 } from "@teamix-evo/registry";
|
|
3858
|
+
|
|
3859
|
+
// src/core/snapshot.ts
|
|
3832
3860
|
import * as fs19 from "fs/promises";
|
|
3861
|
+
import * as path22 from "path";
|
|
3862
|
+
var TEAMIX_DIR2 = ".teamix-evo";
|
|
3863
|
+
var SNAPSHOTS_DIR = ".snapshots";
|
|
3864
|
+
var META_FILE = "_meta.json";
|
|
3865
|
+
var DEFAULT_KEEP = 5;
|
|
3866
|
+
var SNAPSHOT_REASONS = ["init", "update", "switch", "restore", "graft", "manual"];
|
|
3867
|
+
function isoToFsSafe(iso) {
|
|
3868
|
+
return iso.replace(/[:.]/g, "-");
|
|
3869
|
+
}
|
|
3870
|
+
function fsSafeToIso(safe) {
|
|
3871
|
+
return safe.replace(
|
|
3872
|
+
/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})(Z)$/,
|
|
3873
|
+
"$1T$2:$3:$4.$5$6"
|
|
3874
|
+
);
|
|
3875
|
+
}
|
|
3876
|
+
async function createSnapshot(projectRoot, opts = {}) {
|
|
3877
|
+
const teamixDir = path22.join(projectRoot, TEAMIX_DIR2);
|
|
3878
|
+
try {
|
|
3879
|
+
const stat4 = await fs19.stat(teamixDir);
|
|
3880
|
+
if (!stat4.isDirectory()) return null;
|
|
3881
|
+
} catch (err) {
|
|
3882
|
+
if (err.code === "ENOENT") return null;
|
|
3883
|
+
throw err;
|
|
3884
|
+
}
|
|
3885
|
+
const isoTs = (/* @__PURE__ */ new Date()).toISOString();
|
|
3886
|
+
const ts = isoToFsSafe(isoTs);
|
|
3887
|
+
const snapshotRoot = path22.join(teamixDir, SNAPSHOTS_DIR);
|
|
3888
|
+
const target = path22.join(snapshotRoot, ts);
|
|
3889
|
+
await fs19.mkdir(target, { recursive: true });
|
|
3890
|
+
const entries = await fs19.readdir(teamixDir, { withFileTypes: true });
|
|
3891
|
+
for (const entry of entries) {
|
|
3892
|
+
if (entry.name === SNAPSHOTS_DIR) continue;
|
|
3893
|
+
const src = path22.join(teamixDir, entry.name);
|
|
3894
|
+
const dst = path22.join(target, entry.name);
|
|
3895
|
+
await fs19.cp(src, dst, { recursive: true });
|
|
3896
|
+
}
|
|
3897
|
+
const meta = {
|
|
3898
|
+
ts: isoTs,
|
|
3899
|
+
reason: opts.reason ?? "manual"
|
|
3900
|
+
};
|
|
3901
|
+
await fs19.writeFile(
|
|
3902
|
+
path22.join(target, META_FILE),
|
|
3903
|
+
JSON.stringify(meta, null, 2) + "\n",
|
|
3904
|
+
"utf-8"
|
|
3905
|
+
);
|
|
3906
|
+
logger.debug(
|
|
3907
|
+
`Snapshot created \u2192 ${path22.relative(projectRoot, target)} (${meta.reason})`
|
|
3908
|
+
);
|
|
3909
|
+
const keep = opts.keep ?? DEFAULT_KEEP;
|
|
3910
|
+
await pruneSnapshots(projectRoot, keep, { protectedTs: opts.protectedTs });
|
|
3911
|
+
return { ts, path: target };
|
|
3912
|
+
}
|
|
3913
|
+
async function listSnapshots(projectRoot) {
|
|
3914
|
+
const snapshotRoot = path22.join(projectRoot, TEAMIX_DIR2, SNAPSHOTS_DIR);
|
|
3915
|
+
let entries;
|
|
3916
|
+
try {
|
|
3917
|
+
entries = await fs19.readdir(snapshotRoot, { withFileTypes: true });
|
|
3918
|
+
} catch (err) {
|
|
3919
|
+
if (err.code === "ENOENT") return [];
|
|
3920
|
+
throw err;
|
|
3921
|
+
}
|
|
3922
|
+
const result = [];
|
|
3923
|
+
for (const entry of entries) {
|
|
3924
|
+
if (!entry.isDirectory()) continue;
|
|
3925
|
+
const dir = path22.join(snapshotRoot, entry.name);
|
|
3926
|
+
let isoTs = null;
|
|
3927
|
+
let reason = null;
|
|
3928
|
+
try {
|
|
3929
|
+
const raw = await fs19.readFile(path22.join(dir, META_FILE), "utf-8");
|
|
3930
|
+
const parsed = JSON.parse(raw);
|
|
3931
|
+
if (typeof parsed.ts === "string") isoTs = parsed.ts;
|
|
3932
|
+
if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
|
|
3933
|
+
parsed.reason
|
|
3934
|
+
)) {
|
|
3935
|
+
reason = parsed.reason;
|
|
3936
|
+
}
|
|
3937
|
+
} catch {
|
|
3938
|
+
isoTs = fsSafeToIso(entry.name);
|
|
3939
|
+
}
|
|
3940
|
+
result.push({ ts: entry.name, isoTs, reason, path: dir });
|
|
3941
|
+
}
|
|
3942
|
+
result.sort((a, b) => a.ts < b.ts ? 1 : a.ts > b.ts ? -1 : 0);
|
|
3943
|
+
return result;
|
|
3944
|
+
}
|
|
3945
|
+
async function pruneSnapshots(projectRoot, keep = DEFAULT_KEEP, opts = {}) {
|
|
3946
|
+
if (keep < 0)
|
|
3947
|
+
throw new Error(`pruneSnapshots: keep must be >= 0, got ${keep}`);
|
|
3948
|
+
const snapshots = await listSnapshots(projectRoot);
|
|
3949
|
+
if (snapshots.length <= keep) return [];
|
|
3950
|
+
const tail = snapshots.slice(keep);
|
|
3951
|
+
const toRemove = opts.protectedTs ? tail.filter((s) => s.ts !== opts.protectedTs) : tail;
|
|
3952
|
+
const removed = [];
|
|
3953
|
+
for (const snap of toRemove) {
|
|
3954
|
+
await fs19.rm(snap.path, { recursive: true, force: true });
|
|
3955
|
+
removed.push(snap.ts);
|
|
3956
|
+
logger.debug(`Pruned snapshot ${snap.ts}`);
|
|
3957
|
+
}
|
|
3958
|
+
return removed.reverse();
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
// src/core/graft-init.ts
|
|
3962
|
+
import * as fsNode2 from "fs/promises";
|
|
3963
|
+
import * as path23 from "path";
|
|
3964
|
+
var CRITICAL_STEPS2 = /* @__PURE__ */ new Set([
|
|
3965
|
+
"ensure-teamix-dir",
|
|
3966
|
+
"tokens",
|
|
3967
|
+
"ui-init",
|
|
3968
|
+
"skills"
|
|
3969
|
+
]);
|
|
3970
|
+
var AGENTS_MD_GRAFT_MANAGED_ID = "teamix-evo-graft";
|
|
3971
|
+
var GITIGNORE_MARKER_START2 = "# >>> teamix-evo:managed >>>";
|
|
3972
|
+
var GITIGNORE_MARKER_END2 = "# <<< teamix-evo:managed <<<";
|
|
3973
|
+
var GITIGNORE_RULES2 = [
|
|
3974
|
+
"# Runtime artifacts (regenerable / archives)",
|
|
3975
|
+
".teamix-evo/.snapshots/",
|
|
3976
|
+
".teamix-evo/.backups/",
|
|
3977
|
+
".teamix-evo/.upgrade-staging/",
|
|
3978
|
+
".teamix-evo/.upgrade-hints/"
|
|
3979
|
+
];
|
|
3980
|
+
var LEGACY_LIB_META = {
|
|
3981
|
+
fusion: {
|
|
3982
|
+
displayName: "Fusion Design",
|
|
3983
|
+
imports: ["teamix/ui", "@alifd/next", "@ali/teamix-material"]
|
|
3984
|
+
},
|
|
3985
|
+
antd: {
|
|
3986
|
+
displayName: "Ant Design",
|
|
3987
|
+
imports: ["antd", "@ant-design/*"]
|
|
3988
|
+
},
|
|
3989
|
+
element: {
|
|
3990
|
+
displayName: "Element UI",
|
|
3991
|
+
imports: ["element-ui", "element-plus"]
|
|
3992
|
+
}
|
|
3993
|
+
};
|
|
3994
|
+
async function runGraftInit(options) {
|
|
3995
|
+
const {
|
|
3996
|
+
projectRoot,
|
|
3997
|
+
variant,
|
|
3998
|
+
legacyLib,
|
|
3999
|
+
onStep
|
|
4000
|
+
} = options;
|
|
4001
|
+
const ide = options.ide ?? "qoder";
|
|
4002
|
+
const ides = options.ides ?? ["qoder", "claude"];
|
|
4003
|
+
const scope = options.scope ?? "project";
|
|
4004
|
+
const steps = [];
|
|
4005
|
+
let aborted = false;
|
|
4006
|
+
function record(step) {
|
|
4007
|
+
steps.push(step);
|
|
4008
|
+
onStep?.(step);
|
|
4009
|
+
}
|
|
4010
|
+
function recordFailure(name, err) {
|
|
4011
|
+
const message = getErrorMessage(err);
|
|
4012
|
+
record({ name, status: "fail", detail: message });
|
|
4013
|
+
if (CRITICAL_STEPS2.has(name)) aborted = true;
|
|
4014
|
+
}
|
|
4015
|
+
try {
|
|
4016
|
+
await ensureTeamixDir(projectRoot);
|
|
4017
|
+
record({ name: "ensure-teamix-dir", status: "ok" });
|
|
4018
|
+
} catch (err) {
|
|
4019
|
+
recordFailure("ensure-teamix-dir", err);
|
|
4020
|
+
}
|
|
4021
|
+
if (!aborted) {
|
|
4022
|
+
try {
|
|
4023
|
+
const snap = await createSnapshot(projectRoot, { reason: "graft" });
|
|
4024
|
+
record({
|
|
4025
|
+
name: "snapshot",
|
|
4026
|
+
status: "ok",
|
|
4027
|
+
detail: snap ? `snapshot ${snap.ts}` : "empty .teamix-evo/ \u2014 nothing to snapshot"
|
|
4028
|
+
});
|
|
4029
|
+
} catch (err) {
|
|
4030
|
+
recordFailure("snapshot", err);
|
|
4031
|
+
}
|
|
4032
|
+
} else {
|
|
4033
|
+
record({ name: "snapshot", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4034
|
+
}
|
|
4035
|
+
if (!aborted) {
|
|
4036
|
+
try {
|
|
4037
|
+
const result = await runTokensInit({ projectRoot, variant, ide });
|
|
4038
|
+
const detail = result.status === "installed" ? `${result.packageName}@${result.version} (${result.count} files)` : result.status;
|
|
4039
|
+
record({ name: "tokens", status: "ok", detail });
|
|
4040
|
+
} catch (err) {
|
|
4041
|
+
recordFailure("tokens", err);
|
|
4042
|
+
}
|
|
4043
|
+
} else {
|
|
4044
|
+
record({ name: "tokens", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4045
|
+
}
|
|
4046
|
+
if (!aborted) {
|
|
4047
|
+
try {
|
|
4048
|
+
const initResult = await runUiInit({ projectRoot, ide });
|
|
4049
|
+
record({
|
|
4050
|
+
name: "ui-init",
|
|
4051
|
+
status: "ok",
|
|
4052
|
+
detail: initResult.status === "installed" ? "config.json packages.ui written" : initResult.status
|
|
4053
|
+
});
|
|
4054
|
+
} catch (err) {
|
|
4055
|
+
recordFailure("ui-init", err);
|
|
4056
|
+
}
|
|
4057
|
+
} else {
|
|
4058
|
+
record({ name: "ui-init", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4059
|
+
}
|
|
4060
|
+
const collectedNpmDeps = {};
|
|
4061
|
+
if (!aborted) {
|
|
4062
|
+
try {
|
|
4063
|
+
const { manifest } = await loadUiData("@teamix-evo/ui");
|
|
4064
|
+
const allIds = manifest.entries.map((e) => e.id);
|
|
4065
|
+
const addResult = await runUiAdd({
|
|
4066
|
+
projectRoot,
|
|
4067
|
+
ids: allIds,
|
|
4068
|
+
overwrite: true
|
|
4069
|
+
});
|
|
4070
|
+
record({
|
|
4071
|
+
name: "ui-add",
|
|
4072
|
+
status: "ok",
|
|
4073
|
+
detail: `${addResult.orderedIds.length} entries (${addResult.written} written, ${addResult.skipped} skipped)`
|
|
4074
|
+
});
|
|
4075
|
+
Object.assign(collectedNpmDeps, addResult.npmDependencies);
|
|
4076
|
+
} catch (err) {
|
|
4077
|
+
recordFailure("ui-add", err);
|
|
4078
|
+
}
|
|
4079
|
+
} else {
|
|
4080
|
+
record({ name: "ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4081
|
+
}
|
|
4082
|
+
if (!aborted) {
|
|
4083
|
+
try {
|
|
4084
|
+
const listing = await listBizUiEntries(variant);
|
|
4085
|
+
if (listing.entries.length === 0) {
|
|
4086
|
+
record({
|
|
4087
|
+
name: "biz-ui-add",
|
|
4088
|
+
status: "skip",
|
|
4089
|
+
detail: `no biz-ui entries for variant "${variant}"`
|
|
4090
|
+
});
|
|
4091
|
+
} else {
|
|
4092
|
+
const allIds = listing.entries.map((e) => e.id);
|
|
4093
|
+
const result = await runBizUiAdd({
|
|
4094
|
+
projectRoot,
|
|
4095
|
+
variant,
|
|
4096
|
+
ids: allIds,
|
|
4097
|
+
overwrite: true
|
|
4098
|
+
});
|
|
4099
|
+
record({
|
|
4100
|
+
name: "biz-ui-add",
|
|
4101
|
+
status: "ok",
|
|
4102
|
+
detail: `${result.orderedIds.length} entries (${result.written} written, ${result.skipped} skipped)`
|
|
4103
|
+
});
|
|
4104
|
+
if (result.npmDependencies) {
|
|
4105
|
+
Object.assign(collectedNpmDeps, result.npmDependencies);
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
} catch (err) {
|
|
4109
|
+
recordFailure("biz-ui-add", err);
|
|
4110
|
+
}
|
|
4111
|
+
} else {
|
|
4112
|
+
record({ name: "biz-ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4113
|
+
}
|
|
4114
|
+
if (!aborted && Object.keys(collectedNpmDeps).length > 0) {
|
|
4115
|
+
try {
|
|
4116
|
+
await installProjectDeps({
|
|
4117
|
+
projectRoot,
|
|
4118
|
+
npmDependencies: collectedNpmDeps,
|
|
4119
|
+
skipInstall: options.skipInstall ?? false
|
|
4120
|
+
});
|
|
4121
|
+
} catch (err) {
|
|
4122
|
+
logger.warn(
|
|
4123
|
+
`\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`
|
|
4124
|
+
);
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
if (!aborted) {
|
|
4128
|
+
try {
|
|
4129
|
+
const result = await runSkillsInit({ projectRoot, ides, scope, ide });
|
|
4130
|
+
if (result.status === "already-initialized") {
|
|
4131
|
+
record({ name: "skills", status: "ok", detail: "already-initialized" });
|
|
4132
|
+
} else {
|
|
4133
|
+
record({
|
|
4134
|
+
name: "skills",
|
|
4135
|
+
status: "ok",
|
|
4136
|
+
detail: `${result.skillCount} skills, ${result.fileCount} files`
|
|
4137
|
+
});
|
|
4138
|
+
}
|
|
4139
|
+
} catch (err) {
|
|
4140
|
+
recordFailure("skills", err);
|
|
4141
|
+
}
|
|
4142
|
+
} else {
|
|
4143
|
+
record({ name: "skills", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4144
|
+
}
|
|
4145
|
+
if (!aborted) {
|
|
4146
|
+
try {
|
|
4147
|
+
const result = await runGenerateAgentsMd({
|
|
4148
|
+
projectRoot,
|
|
4149
|
+
variant,
|
|
4150
|
+
skillIds: [
|
|
4151
|
+
`teamix-evo-design-${variant}`,
|
|
4152
|
+
`teamix-evo-code-${variant}`
|
|
4153
|
+
],
|
|
4154
|
+
globalSkillIds: ["teamix-evo-manage"],
|
|
4155
|
+
mode: "merge-managed"
|
|
4156
|
+
});
|
|
4157
|
+
record({
|
|
4158
|
+
name: "agents-md",
|
|
4159
|
+
status: "ok",
|
|
4160
|
+
detail: `${result.skillCount} skill index (${result.merge})`
|
|
4161
|
+
});
|
|
4162
|
+
} catch (err) {
|
|
4163
|
+
recordFailure("agents-md", err);
|
|
4164
|
+
}
|
|
4165
|
+
} else {
|
|
4166
|
+
record({ name: "agents-md", status: "skip", detail: "aborted" });
|
|
4167
|
+
}
|
|
4168
|
+
if (!aborted) {
|
|
4169
|
+
try {
|
|
4170
|
+
const agentsMdPath = path23.join(projectRoot, "AGENTS.md");
|
|
4171
|
+
const existing = await readFileOrNull(agentsMdPath) ?? "";
|
|
4172
|
+
const meta = LEGACY_LIB_META[legacyLib] ?? {
|
|
4173
|
+
displayName: legacyLib,
|
|
4174
|
+
imports: [legacyLib]
|
|
4175
|
+
};
|
|
4176
|
+
const importsStr = meta.imports.map((i) => `\`${i}\``).join("\u3001");
|
|
4177
|
+
const graftBody = renderGraftManagedBody(meta.displayName, importsStr);
|
|
4178
|
+
let output;
|
|
4179
|
+
if (hasManagedRegion3(existing, AGENTS_MD_GRAFT_MANAGED_ID)) {
|
|
4180
|
+
output = replaceManagedRegion3(
|
|
4181
|
+
existing,
|
|
4182
|
+
AGENTS_MD_GRAFT_MANAGED_ID,
|
|
4183
|
+
graftBody
|
|
4184
|
+
);
|
|
4185
|
+
} else {
|
|
4186
|
+
const wrapped = wrapGraftManagedBlock(graftBody);
|
|
4187
|
+
output = existing.trimEnd() + "\n\n" + wrapped + "\n";
|
|
4188
|
+
}
|
|
4189
|
+
await fsNode2.writeFile(agentsMdPath, output, "utf-8");
|
|
4190
|
+
record({ name: "agents-md-graft", status: "ok", detail: `dual-stack rules for ${legacyLib}` });
|
|
4191
|
+
} catch (err) {
|
|
4192
|
+
recordFailure("agents-md-graft", err);
|
|
4193
|
+
}
|
|
4194
|
+
} else {
|
|
4195
|
+
record({ name: "agents-md-graft", status: "skip", detail: "aborted" });
|
|
4196
|
+
}
|
|
4197
|
+
if (!aborted) {
|
|
4198
|
+
try {
|
|
4199
|
+
const uiResult = await landUiMeta(projectRoot);
|
|
4200
|
+
const bizResult = await landBizUiMeta(projectRoot, variant);
|
|
4201
|
+
record({
|
|
4202
|
+
name: "meta-landing",
|
|
4203
|
+
status: "ok",
|
|
4204
|
+
detail: `ui: ${uiResult.metaFilesWritten}/${uiResult.metaFilesTotal}, biz-ui: ${bizResult.metaFilesWritten}/${bizResult.metaFilesTotal}`
|
|
4205
|
+
});
|
|
4206
|
+
} catch (err) {
|
|
4207
|
+
recordFailure("meta-landing", err);
|
|
4208
|
+
}
|
|
4209
|
+
} else {
|
|
4210
|
+
record({ name: "meta-landing", status: "skip", detail: "aborted" });
|
|
4211
|
+
}
|
|
4212
|
+
if (!aborted) {
|
|
4213
|
+
try {
|
|
4214
|
+
const config = await readProjectConfig(projectRoot);
|
|
4215
|
+
if (config) {
|
|
4216
|
+
config.mode = "graft";
|
|
4217
|
+
config.legacyLib = legacyLib;
|
|
4218
|
+
await writeProjectConfig(projectRoot, config);
|
|
4219
|
+
record({ name: "config-mode", status: "ok", detail: `mode=graft, legacyLib=${legacyLib}` });
|
|
4220
|
+
} else {
|
|
4221
|
+
record({ name: "config-mode", status: "skip", detail: "no config.json found to patch" });
|
|
4222
|
+
}
|
|
4223
|
+
} catch (err) {
|
|
4224
|
+
recordFailure("config-mode", err);
|
|
4225
|
+
}
|
|
4226
|
+
} else {
|
|
4227
|
+
record({ name: "config-mode", status: "skip", detail: "aborted" });
|
|
4228
|
+
}
|
|
4229
|
+
if (!aborted) {
|
|
4230
|
+
try {
|
|
4231
|
+
const giPath = path23.join(projectRoot, ".gitignore");
|
|
4232
|
+
let giContent = "";
|
|
4233
|
+
try {
|
|
4234
|
+
giContent = await fsNode2.readFile(giPath, "utf-8");
|
|
4235
|
+
} catch {
|
|
4236
|
+
}
|
|
4237
|
+
if (giContent.includes(GITIGNORE_MARKER_START2)) {
|
|
4238
|
+
record({ name: "gitignore", status: "skip", detail: "teamix-evo markers already present" });
|
|
4239
|
+
} else {
|
|
4240
|
+
const block = [
|
|
4241
|
+
"",
|
|
4242
|
+
GITIGNORE_MARKER_START2,
|
|
4243
|
+
...GITIGNORE_RULES2,
|
|
4244
|
+
GITIGNORE_MARKER_END2,
|
|
4245
|
+
""
|
|
4246
|
+
].join("\n");
|
|
4247
|
+
const separator = giContent.length > 0 && !giContent.endsWith("\n") ? "\n" : "";
|
|
4248
|
+
await fsNode2.writeFile(giPath, giContent + separator + block, "utf-8");
|
|
4249
|
+
record({
|
|
4250
|
+
name: "gitignore",
|
|
4251
|
+
status: "ok",
|
|
4252
|
+
detail: `${GITIGNORE_RULES2.filter((r) => r && !r.startsWith("#")).length} rules appended`
|
|
4253
|
+
});
|
|
4254
|
+
}
|
|
4255
|
+
} catch (err) {
|
|
4256
|
+
recordFailure("gitignore", err);
|
|
4257
|
+
}
|
|
4258
|
+
} else {
|
|
4259
|
+
record({ name: "gitignore", status: "skip", detail: "aborted" });
|
|
4260
|
+
}
|
|
4261
|
+
const status = steps.some((s) => s.status === "fail") ? "partial" : "success";
|
|
4262
|
+
return { status, steps };
|
|
4263
|
+
}
|
|
4264
|
+
function renderGraftManagedBody(legacyLibName, legacyImports) {
|
|
4265
|
+
return `## \u53CC\u6808\u7814\u53D1\u89C4\u5219
|
|
4266
|
+
|
|
4267
|
+
\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
|
|
4268
|
+
|
|
4269
|
+
### \u5224\u65AD\u89C4\u5219\u2014\u2014\u901A\u8FC7 import \u8BED\u53E5\u8BC6\u522B
|
|
4270
|
+
- \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
|
|
4271
|
+
- \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
|
|
4272
|
+
- \u65B0\u5EFA\u9875\u9762 \u2192 \u9ED8\u8BA4\u4F7F\u7528\u65B0\u6808\uFF08teamix-evo\uFF09
|
|
4273
|
+
|
|
4274
|
+
### \u7981\u6B62\u4E8B\u9879
|
|
4275
|
+
- \u7981\u6B62\u5728\u65E7\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 \`@/components/ui\` \u6216 Tailwind class
|
|
4276
|
+
- \u7981\u6B62\u5728\u65B0\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 ${legacyImports}
|
|
4277
|
+
- \u7981\u6B62\u5728\u540C\u4E00\u6587\u4EF6\u4E2D\u6DF7\u7528\u4E24\u5957\u7EC4\u4EF6\u5E93`;
|
|
4278
|
+
}
|
|
4279
|
+
function wrapGraftManagedBlock(body) {
|
|
4280
|
+
return `<!-- teamix-evo:managed:start id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->
|
|
4281
|
+
${body}
|
|
4282
|
+
<!-- teamix-evo:managed:end id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->`;
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
// src/core/installer.ts
|
|
4286
|
+
import * as path24 from "path";
|
|
4287
|
+
import * as fs20 from "fs/promises";
|
|
3833
4288
|
async function installResources(options) {
|
|
3834
4289
|
const { projectRoot, manifest, data, variantDir, packageRoot } = options;
|
|
3835
4290
|
const installedResources = [];
|
|
@@ -3866,13 +4321,13 @@ async function installSingleResource(resource, projectRoot, data, variantDir, pa
|
|
|
3866
4321
|
variantDir,
|
|
3867
4322
|
packageRoot
|
|
3868
4323
|
);
|
|
3869
|
-
const targetPath =
|
|
4324
|
+
const targetPath = path24.join(projectRoot, resource.target);
|
|
3870
4325
|
let content;
|
|
3871
4326
|
if (resource.template) {
|
|
3872
4327
|
const templateContent = await loadTemplateFile(sourcePath);
|
|
3873
4328
|
content = renderTemplate(templateContent, data);
|
|
3874
4329
|
} else {
|
|
3875
|
-
content = await
|
|
4330
|
+
content = await fs20.readFile(sourcePath, "utf-8");
|
|
3876
4331
|
}
|
|
3877
4332
|
await writeFileSafe(targetPath, content);
|
|
3878
4333
|
const hash = computeHash(content);
|
|
@@ -3890,13 +4345,13 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3890
4345
|
variantDir,
|
|
3891
4346
|
packageRoot
|
|
3892
4347
|
);
|
|
3893
|
-
const targetDir =
|
|
4348
|
+
const targetDir = path24.join(projectRoot, resource.target);
|
|
3894
4349
|
const results = [];
|
|
3895
4350
|
await ensureDir(targetDir);
|
|
3896
4351
|
const entries = await walkDir(sourcePath);
|
|
3897
4352
|
for (const entry of entries) {
|
|
3898
|
-
const relPath =
|
|
3899
|
-
let targetFile =
|
|
4353
|
+
const relPath = path24.relative(sourcePath, entry);
|
|
4354
|
+
let targetFile = path24.join(targetDir, relPath);
|
|
3900
4355
|
if (resource.template && targetFile.endsWith(".hbs")) {
|
|
3901
4356
|
targetFile = targetFile.slice(0, -4);
|
|
3902
4357
|
}
|
|
@@ -3905,11 +4360,11 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3905
4360
|
const templateContent = await loadTemplateFile(entry);
|
|
3906
4361
|
content = renderTemplate(templateContent, data);
|
|
3907
4362
|
} else {
|
|
3908
|
-
content = await
|
|
4363
|
+
content = await fs20.readFile(entry, "utf-8");
|
|
3909
4364
|
}
|
|
3910
4365
|
await writeFileSafe(targetFile, content);
|
|
3911
4366
|
const hash = computeHash(content);
|
|
3912
|
-
const targetRel =
|
|
4367
|
+
const targetRel = path24.relative(projectRoot, targetFile);
|
|
3913
4368
|
results.push({
|
|
3914
4369
|
id: `${resource.id}:${relPath}`,
|
|
3915
4370
|
target: targetRel,
|
|
@@ -3922,25 +4377,25 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3922
4377
|
}
|
|
3923
4378
|
|
|
3924
4379
|
// src/core/registry-client.ts
|
|
3925
|
-
import * as
|
|
3926
|
-
import * as
|
|
4380
|
+
import * as path25 from "path";
|
|
4381
|
+
import * as fs21 from "fs/promises";
|
|
3927
4382
|
import { createRequire as createRequire6 } from "module";
|
|
3928
4383
|
import { loadVariantManifest } from "@teamix-evo/registry";
|
|
3929
4384
|
var require7 = createRequire6(import.meta.url);
|
|
3930
4385
|
function resolvePackageRoot5(packageName) {
|
|
3931
4386
|
const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
|
|
3932
|
-
return
|
|
4387
|
+
return path25.dirname(pkgJsonPath);
|
|
3933
4388
|
}
|
|
3934
4389
|
async function loadVariantData(packageName, variant) {
|
|
3935
4390
|
const packageRoot = resolvePackageRoot5(packageName);
|
|
3936
|
-
const variantDir =
|
|
4391
|
+
const variantDir = path25.join(packageRoot, "library", variant);
|
|
3937
4392
|
logger.debug(`Resolved variant dir: ${variantDir}`);
|
|
3938
4393
|
logger.debug(`Package root: ${packageRoot}`);
|
|
3939
4394
|
const manifest = await loadVariantManifest(variantDir);
|
|
3940
4395
|
let data = {};
|
|
3941
|
-
const dataPath =
|
|
4396
|
+
const dataPath = path25.join(variantDir, "_data.json");
|
|
3942
4397
|
try {
|
|
3943
|
-
const raw = await
|
|
4398
|
+
const raw = await fs21.readFile(dataPath, "utf-8");
|
|
3944
4399
|
data = JSON.parse(raw);
|
|
3945
4400
|
} catch (err) {
|
|
3946
4401
|
if (err.code !== "ENOENT") {
|
|
@@ -3976,6 +4431,7 @@ export {
|
|
|
3976
4431
|
removeUiFiles,
|
|
3977
4432
|
runBizUiAdd,
|
|
3978
4433
|
runGenerateAgentsMd,
|
|
4434
|
+
runGraftInit,
|
|
3979
4435
|
runLintInit,
|
|
3980
4436
|
runProjectInit,
|
|
3981
4437
|
runSkillsAdd,
|