teamix-evo 0.14.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.d.ts +12 -4
- package/dist/core/index.js +51 -27
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +73 -37
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/core/index.d.ts
CHANGED
|
@@ -509,9 +509,14 @@ declare function runLintInit(options: RunLintInitOptions): Promise<RunLintInitRe
|
|
|
509
509
|
* skill activation conditions even when the user prompt does not directly
|
|
510
510
|
* hit the description-based trigger.
|
|
511
511
|
*
|
|
512
|
+
* Includes both project-scope content skills AND global-scope lifecycle skills
|
|
513
|
+
* (e.g. `teamix-evo-manage`): manage triggers are rendered into the project
|
|
514
|
+
* AGENTS.md so team members who clone the repo see the lifecycle entry points
|
|
515
|
+
* even before installing the global skill themselves. A "全局技能" note guides
|
|
516
|
+
* the AI to check availability and prompt installation when needed (ADR 0033).
|
|
517
|
+
*
|
|
512
518
|
* Out of scope (per ADR 0038):
|
|
513
519
|
* - Does NOT copy skill body / rules / patterns — those stay in the skill.
|
|
514
|
-
* - Does NOT include `teamix-evo-manage` (entry skill, global scope, ADR 0033).
|
|
515
520
|
*
|
|
516
521
|
* Lifted from `create-teamix-evo` (v0.5) into `teamix-evo/core` so both
|
|
517
522
|
* `npm create teamix-evo` (scaffold path) and `teamix-evo init` (existing-
|
|
@@ -524,11 +529,14 @@ interface RunGenerateAgentsMdOptions {
|
|
|
524
529
|
projectRoot: string;
|
|
525
530
|
/** Tokens / skills variant (e.g. "opentrek"). Used for header context. */
|
|
526
531
|
variant: string;
|
|
532
|
+
/** Project-scope skill ids to index. */
|
|
533
|
+
skillIds: string[];
|
|
527
534
|
/**
|
|
528
|
-
*
|
|
529
|
-
*
|
|
535
|
+
* Global-scope skill ids to include alongside project skills. Rendered with
|
|
536
|
+
* a "全局技能" installation note. TRIGGER / SKIP text is read from the
|
|
537
|
+
* global IDE mirror path at generation time.
|
|
530
538
|
*/
|
|
531
|
-
|
|
539
|
+
globalSkillIds?: string[];
|
|
532
540
|
/**
|
|
533
541
|
* Reconciliation mode (Phase 2.B):
|
|
534
542
|
* - `'overwrite'` (default): always rewrite the full file. Pre-existing
|
package/dist/core/index.js
CHANGED
|
@@ -1463,18 +1463,24 @@ import { hasManagedRegion as hasManagedRegion2, replaceManagedRegion as replaceM
|
|
|
1463
1463
|
var AGENTS_MD_MANAGED_ID = "teamix-evo-skills";
|
|
1464
1464
|
async function runGenerateAgentsMd(options) {
|
|
1465
1465
|
const { projectRoot, variant, skillIds } = options;
|
|
1466
|
+
const globalSkillIds = options.globalSkillIds ?? [];
|
|
1466
1467
|
const mode = options.mode ?? "overwrite";
|
|
1467
1468
|
const config = await readProjectConfig(projectRoot);
|
|
1468
1469
|
const lock = await readSkillsLock(projectRoot);
|
|
1469
1470
|
const ides = config?.packages?.skills?.ides ?? ["qoder", "claude"];
|
|
1470
1471
|
const scope = config?.packages?.skills?.scope ?? lock?.skills[skillIds[0] ?? ""]?.scope ?? "project";
|
|
1471
|
-
const
|
|
1472
|
+
const skillScopeMap = /* @__PURE__ */ new Map();
|
|
1473
|
+
for (const id of skillIds) skillScopeMap.set(id, scope);
|
|
1474
|
+
for (const id of globalSkillIds) skillScopeMap.set(id, "global");
|
|
1475
|
+
const allSkillIds = [...skillIds, ...globalSkillIds];
|
|
1476
|
+
const ordered = allSkillIds.sort(
|
|
1472
1477
|
(a, b) => bucketRank(a) - bucketRank(b) || a.localeCompare(b)
|
|
1473
1478
|
);
|
|
1474
1479
|
const sections = [];
|
|
1475
1480
|
const missingSkillIds = [];
|
|
1476
1481
|
for (const id of ordered) {
|
|
1477
|
-
const
|
|
1482
|
+
const skillScope = skillScopeMap.get(id) ?? scope;
|
|
1483
|
+
const { section, missing } = await renderSkillSection(projectRoot, id, ides, skillScope);
|
|
1478
1484
|
sections.push(section);
|
|
1479
1485
|
if (missing) missingSkillIds.push(id);
|
|
1480
1486
|
}
|
|
@@ -1558,6 +1564,12 @@ async function renderSkillSection(projectRoot, skillId, ides, scope) {
|
|
|
1558
1564
|
if (parts?.coordinates) {
|
|
1559
1565
|
lines.push(`- **Coordinates with**: ${parts.coordinates}`);
|
|
1560
1566
|
}
|
|
1567
|
+
if (scope === "global") {
|
|
1568
|
+
lines.push("");
|
|
1569
|
+
lines.push(
|
|
1570
|
+
"> **\u5168\u5C40\u6280\u80FD** \u2014 \u5B89\u88C5\u5728\u5168\u5C40\u800C\u975E\u9879\u76EE\u5185\uFF0C\u4E0D\u968F\u4EE3\u7801\u4ED3\u5E93\u5206\u53D1\u3002AI \u89E6\u53D1\u65F6\u5E94\u5148\u786E\u8BA4\u672C\u6280\u80FD\u53EF\u7528\uFF1B\u82E5\u4E0D\u53EF\u7528\uFF0C\u5F15\u5BFC\u7528\u6237\u6267\u884C\u5168\u5C40\u5B89\u88C5\u3002"
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1561
1573
|
return { section: lines.join("\n"), missing };
|
|
1562
1574
|
}
|
|
1563
1575
|
function renderAgentsMd(args) {
|
|
@@ -1873,10 +1885,12 @@ async function runSkillsUpdate(options) {
|
|
|
1873
1885
|
const variant = await readTokensVariant(projectRoot);
|
|
1874
1886
|
if (variant) {
|
|
1875
1887
|
const projectSkillIds = Object.entries(lock.skills).filter(([, v]) => v.scope === "project").map(([id]) => id);
|
|
1888
|
+
const globalSkillIds = Object.entries(lock.skills).filter(([, v]) => v.scope === "global").map(([id]) => id);
|
|
1876
1889
|
await runGenerateAgentsMd({
|
|
1877
1890
|
projectRoot,
|
|
1878
1891
|
variant,
|
|
1879
1892
|
skillIds: projectSkillIds,
|
|
1893
|
+
globalSkillIds,
|
|
1880
1894
|
mode: "merge-managed"
|
|
1881
1895
|
});
|
|
1882
1896
|
}
|
|
@@ -1966,6 +1980,10 @@ async function loadUiData(packageName) {
|
|
|
1966
1980
|
const packageRoot = resolvePackageRoot2(packageName);
|
|
1967
1981
|
logger.debug(`Resolved ui package root: ${packageRoot}`);
|
|
1968
1982
|
const manifest = await loadUiPackageManifest(packageRoot);
|
|
1983
|
+
const pkgJson = JSON.parse(
|
|
1984
|
+
await fs9.readFile(path10.join(packageRoot, "package.json"), "utf-8")
|
|
1985
|
+
);
|
|
1986
|
+
manifest.version = pkgJson.version;
|
|
1969
1987
|
let data = {};
|
|
1970
1988
|
const dataPath = path10.join(packageRoot, "_data.json");
|
|
1971
1989
|
try {
|
|
@@ -2285,6 +2303,7 @@ async function runUiList(options) {
|
|
|
2285
2303
|
|
|
2286
2304
|
// src/core/variant-ui-add.ts
|
|
2287
2305
|
import * as path12 from "path";
|
|
2306
|
+
import * as fs11 from "fs/promises";
|
|
2288
2307
|
import { createRequire as createRequire4 } from "module";
|
|
2289
2308
|
import {
|
|
2290
2309
|
loadUiPackageManifest as loadUiPackageManifest2,
|
|
@@ -2319,6 +2338,10 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
2319
2338
|
}
|
|
2320
2339
|
const variantDir = path12.join(packageRoot, "variants", variant);
|
|
2321
2340
|
const variantManifest = await loadVariantUiPackageManifest(variantDir);
|
|
2341
|
+
const pkgJson = JSON.parse(
|
|
2342
|
+
await fs11.readFile(path12.join(packageRoot, "package.json"), "utf-8")
|
|
2343
|
+
);
|
|
2344
|
+
const packageVersion = pkgJson.version;
|
|
2322
2345
|
const knownIds = new Set(variantManifest.entries.map((e) => e.id));
|
|
2323
2346
|
const unknown = ids.filter((id) => !knownIds.has(id));
|
|
2324
2347
|
if (unknown.length > 0) {
|
|
@@ -2342,7 +2365,7 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
2342
2365
|
const adaptedManifest = {
|
|
2343
2366
|
schemaVersion: 1,
|
|
2344
2367
|
package: "ui",
|
|
2345
|
-
version:
|
|
2368
|
+
version: packageVersion,
|
|
2346
2369
|
engines: variantManifest.engines,
|
|
2347
2370
|
entries: mergedEntries
|
|
2348
2371
|
};
|
|
@@ -2370,7 +2393,7 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
2370
2393
|
const entry = {
|
|
2371
2394
|
package: fullPackageName,
|
|
2372
2395
|
variant,
|
|
2373
|
-
version:
|
|
2396
|
+
version: packageVersion,
|
|
2374
2397
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2375
2398
|
resources: mergedResources
|
|
2376
2399
|
};
|
|
@@ -2446,7 +2469,7 @@ async function listBizUiEntries(variant, packageRoot) {
|
|
|
2446
2469
|
|
|
2447
2470
|
// src/core/lint-init.ts
|
|
2448
2471
|
import * as path13 from "path";
|
|
2449
|
-
import * as
|
|
2472
|
+
import * as fs12 from "fs";
|
|
2450
2473
|
import { execa } from "execa";
|
|
2451
2474
|
var ESLINT_CONFIG_CONTENT = `/**
|
|
2452
2475
|
* teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
|
|
@@ -2538,7 +2561,7 @@ async function runLintInit(options) {
|
|
|
2538
2561
|
let stylelintIgnoreFilesWarning = false;
|
|
2539
2562
|
if (!stylelintNeedsWrite && stylelintTemplateExists) {
|
|
2540
2563
|
try {
|
|
2541
|
-
const existingContent =
|
|
2564
|
+
const existingContent = fs12.readFileSync(stylelintConfigPath, "utf-8");
|
|
2542
2565
|
const usesTeamixPreset = existingContent.includes("@teamix-evo/stylelint-config/presets/") || existingContent.includes("@teamix-evo/stylelint-config/preset/");
|
|
2543
2566
|
const hasTokenIgnore = existingContent.includes("tokens.theme.css") && existingContent.includes("tokens.overrides.css");
|
|
2544
2567
|
if (!usesTeamixPreset && !hasTokenIgnore) {
|
|
@@ -2575,8 +2598,8 @@ async function runLintInit(options) {
|
|
|
2575
2598
|
};
|
|
2576
2599
|
}
|
|
2577
2600
|
function detectPm(projectRoot) {
|
|
2578
|
-
if (
|
|
2579
|
-
if (
|
|
2601
|
+
if (fs12.existsSync(path13.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
2602
|
+
if (fs12.existsSync(path13.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
2580
2603
|
return "npm";
|
|
2581
2604
|
}
|
|
2582
2605
|
async function patchPackageJsonScripts(projectRoot) {
|
|
@@ -2609,7 +2632,7 @@ async function patchPackageJsonScripts(projectRoot) {
|
|
|
2609
2632
|
}
|
|
2610
2633
|
|
|
2611
2634
|
// src/core/init-detect.ts
|
|
2612
|
-
import * as
|
|
2635
|
+
import * as fs13 from "fs/promises";
|
|
2613
2636
|
import * as path14 from "path";
|
|
2614
2637
|
var IGNORED_TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
2615
2638
|
".git",
|
|
@@ -2644,7 +2667,7 @@ async function detectProjectState(cwd) {
|
|
|
2644
2667
|
}
|
|
2645
2668
|
let entries;
|
|
2646
2669
|
try {
|
|
2647
|
-
entries = await
|
|
2670
|
+
entries = await fs13.readdir(absCwd);
|
|
2648
2671
|
} catch (err) {
|
|
2649
2672
|
if (err.code === "ENOENT") {
|
|
2650
2673
|
return {
|
|
@@ -2678,7 +2701,7 @@ async function detectProjectState(cwd) {
|
|
|
2678
2701
|
}
|
|
2679
2702
|
|
|
2680
2703
|
// src/core/project-state.ts
|
|
2681
|
-
import * as
|
|
2704
|
+
import * as fs14 from "fs/promises";
|
|
2682
2705
|
import * as path15 from "path";
|
|
2683
2706
|
var IGNORED_TOP_LEVEL2 = /* @__PURE__ */ new Set([
|
|
2684
2707
|
".git",
|
|
@@ -2738,7 +2761,7 @@ async function detectProjectState2(cwd) {
|
|
|
2738
2761
|
}
|
|
2739
2762
|
let entries;
|
|
2740
2763
|
try {
|
|
2741
|
-
entries = await
|
|
2764
|
+
entries = await fs14.readdir(absCwd);
|
|
2742
2765
|
} catch (err) {
|
|
2743
2766
|
if (err.code === "ENOENT") {
|
|
2744
2767
|
return {
|
|
@@ -2821,7 +2844,7 @@ function assertCommandPrecondition(command, state) {
|
|
|
2821
2844
|
|
|
2822
2845
|
// src/core/init-conflicts.ts
|
|
2823
2846
|
import * as crypto from "crypto";
|
|
2824
|
-
import * as
|
|
2847
|
+
import * as fs15 from "fs/promises";
|
|
2825
2848
|
import * as path16 from "path";
|
|
2826
2849
|
var TAILWIND_CONFIG_CANDIDATES = [
|
|
2827
2850
|
"tailwind.config.ts",
|
|
@@ -2866,7 +2889,7 @@ var STYLELINT_CONFIG_CANDIDATES = [
|
|
|
2866
2889
|
];
|
|
2867
2890
|
async function isDir(target) {
|
|
2868
2891
|
try {
|
|
2869
|
-
const stat3 = await
|
|
2892
|
+
const stat3 = await fs15.stat(target);
|
|
2870
2893
|
return stat3.isDirectory();
|
|
2871
2894
|
} catch {
|
|
2872
2895
|
return false;
|
|
@@ -2874,7 +2897,7 @@ async function isDir(target) {
|
|
|
2874
2897
|
}
|
|
2875
2898
|
async function dirHasContent(target) {
|
|
2876
2899
|
try {
|
|
2877
|
-
const entries = await
|
|
2900
|
+
const entries = await fs15.readdir(target);
|
|
2878
2901
|
return entries.length > 0;
|
|
2879
2902
|
} catch {
|
|
2880
2903
|
return false;
|
|
@@ -3015,7 +3038,7 @@ async function detectShadcnSource(cwd) {
|
|
|
3015
3038
|
try {
|
|
3016
3039
|
const uiDir = path16.join(cwd, "src/components/ui");
|
|
3017
3040
|
if (await isDir(uiDir)) {
|
|
3018
|
-
const entries = await
|
|
3041
|
+
const entries = await fs15.readdir(uiDir);
|
|
3019
3042
|
componentCount = entries.filter(
|
|
3020
3043
|
(e) => e.endsWith(".tsx") || e.endsWith(".ts")
|
|
3021
3044
|
).length;
|
|
@@ -3093,7 +3116,7 @@ async function detectStylelintConfig(cwd) {
|
|
|
3093
3116
|
|
|
3094
3117
|
// src/core/meta-installer.ts
|
|
3095
3118
|
import * as path17 from "path";
|
|
3096
|
-
import * as
|
|
3119
|
+
import * as fs16 from "fs/promises";
|
|
3097
3120
|
import { createRequire as createRequire5 } from "module";
|
|
3098
3121
|
import {
|
|
3099
3122
|
loadUiPackageManifest as loadUiPackageManifest3,
|
|
@@ -3137,7 +3160,7 @@ async function landManifestMeta(opts) {
|
|
|
3137
3160
|
await ensureDir(metaDir);
|
|
3138
3161
|
const manifestDest = path17.join(metaDir, "manifest.json");
|
|
3139
3162
|
const manifestSrc = path17.join(packageRoot, "manifest.json");
|
|
3140
|
-
await
|
|
3163
|
+
await fs16.copyFile(manifestSrc, manifestDest);
|
|
3141
3164
|
logger.debug(`meta: copied manifest.json \u2192 ${manifestDest}`);
|
|
3142
3165
|
let written = 0;
|
|
3143
3166
|
let total = 0;
|
|
@@ -3147,7 +3170,7 @@ async function landManifestMeta(opts) {
|
|
|
3147
3170
|
const srcPath = path17.join(packageRoot, entry.meta);
|
|
3148
3171
|
const destPath = path17.join(metaDir, `${entry.id}.md`);
|
|
3149
3172
|
try {
|
|
3150
|
-
await
|
|
3173
|
+
await fs16.copyFile(srcPath, destPath);
|
|
3151
3174
|
written++;
|
|
3152
3175
|
logger.debug(`meta: ${entry.id} \u2192 ${destPath}`);
|
|
3153
3176
|
} catch (err) {
|
|
@@ -3170,7 +3193,7 @@ async function landManifestMeta(opts) {
|
|
|
3170
3193
|
}
|
|
3171
3194
|
|
|
3172
3195
|
// src/core/deps-install.ts
|
|
3173
|
-
import * as
|
|
3196
|
+
import * as fs17 from "fs/promises";
|
|
3174
3197
|
import * as path18 from "path";
|
|
3175
3198
|
import { exec } from "child_process";
|
|
3176
3199
|
import { promisify } from "util";
|
|
@@ -3227,7 +3250,7 @@ async function installProjectDeps(options) {
|
|
|
3227
3250
|
pkg.dependencies = Object.fromEntries(
|
|
3228
3251
|
Object.entries(pkg.dependencies).sort(([a], [b]) => a.localeCompare(b))
|
|
3229
3252
|
);
|
|
3230
|
-
await
|
|
3253
|
+
await fs17.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3231
3254
|
logger.info(
|
|
3232
3255
|
` patched package.json: +${Object.keys(added).length} dependencies`
|
|
3233
3256
|
);
|
|
@@ -3289,7 +3312,7 @@ ${stepLines}
|
|
|
3289
3312
|
}
|
|
3290
3313
|
|
|
3291
3314
|
// src/core/file-changes.ts
|
|
3292
|
-
import * as
|
|
3315
|
+
import * as fs18 from "fs/promises";
|
|
3293
3316
|
import * as path19 from "path";
|
|
3294
3317
|
function toRelativePosix(p, projectRoot) {
|
|
3295
3318
|
let rel2 = p;
|
|
@@ -3418,6 +3441,7 @@ async function runProjectInit(options) {
|
|
|
3418
3441
|
`teamix-evo-design-${variant}`,
|
|
3419
3442
|
`teamix-evo-code-${variant}`
|
|
3420
3443
|
],
|
|
3444
|
+
globalSkillIds: ["teamix-evo-manage"],
|
|
3421
3445
|
mode: "merge-managed"
|
|
3422
3446
|
});
|
|
3423
3447
|
record({
|
|
@@ -3748,7 +3772,7 @@ function deriveLintChanges(result) {
|
|
|
3748
3772
|
|
|
3749
3773
|
// src/core/installer.ts
|
|
3750
3774
|
import * as path21 from "path";
|
|
3751
|
-
import * as
|
|
3775
|
+
import * as fs19 from "fs/promises";
|
|
3752
3776
|
async function installResources(options) {
|
|
3753
3777
|
const { projectRoot, manifest, data, variantDir, packageRoot } = options;
|
|
3754
3778
|
const installedResources = [];
|
|
@@ -3791,7 +3815,7 @@ async function installSingleResource(resource, projectRoot, data, variantDir, pa
|
|
|
3791
3815
|
const templateContent = await loadTemplateFile(sourcePath);
|
|
3792
3816
|
content = renderTemplate(templateContent, data);
|
|
3793
3817
|
} else {
|
|
3794
|
-
content = await
|
|
3818
|
+
content = await fs19.readFile(sourcePath, "utf-8");
|
|
3795
3819
|
}
|
|
3796
3820
|
await writeFileSafe(targetPath, content);
|
|
3797
3821
|
const hash = computeHash(content);
|
|
@@ -3824,7 +3848,7 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3824
3848
|
const templateContent = await loadTemplateFile(entry);
|
|
3825
3849
|
content = renderTemplate(templateContent, data);
|
|
3826
3850
|
} else {
|
|
3827
|
-
content = await
|
|
3851
|
+
content = await fs19.readFile(entry, "utf-8");
|
|
3828
3852
|
}
|
|
3829
3853
|
await writeFileSafe(targetFile, content);
|
|
3830
3854
|
const hash = computeHash(content);
|
|
@@ -3842,7 +3866,7 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3842
3866
|
|
|
3843
3867
|
// src/core/registry-client.ts
|
|
3844
3868
|
import * as path22 from "path";
|
|
3845
|
-
import * as
|
|
3869
|
+
import * as fs20 from "fs/promises";
|
|
3846
3870
|
import { createRequire as createRequire6 } from "module";
|
|
3847
3871
|
import { loadVariantManifest } from "@teamix-evo/registry";
|
|
3848
3872
|
var require7 = createRequire6(import.meta.url);
|
|
@@ -3859,7 +3883,7 @@ async function loadVariantData(packageName, variant) {
|
|
|
3859
3883
|
let data = {};
|
|
3860
3884
|
const dataPath = path22.join(variantDir, "_data.json");
|
|
3861
3885
|
try {
|
|
3862
|
-
const raw = await
|
|
3886
|
+
const raw = await fs20.readFile(dataPath, "utf-8");
|
|
3863
3887
|
data = JSON.parse(raw);
|
|
3864
3888
|
} catch (err) {
|
|
3865
3889
|
if (err.code !== "ENOENT") {
|