teamix-evo 0.14.1 → 0.14.3
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 +57 -27
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +79 -37
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
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,13 +2393,19 @@ 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
|
};
|
|
2377
2400
|
if (idx >= 0) installed.installed[idx] = entry;
|
|
2378
2401
|
else installed.installed.push(entry);
|
|
2379
2402
|
await writeInstalledManifest(projectRoot, installed);
|
|
2403
|
+
config.packages[packageName] = {
|
|
2404
|
+
...config.packages[packageName] ?? {},
|
|
2405
|
+
variant,
|
|
2406
|
+
version: packageVersion
|
|
2407
|
+
};
|
|
2408
|
+
await writeProjectConfig(projectRoot, config);
|
|
2380
2409
|
return {
|
|
2381
2410
|
packageName: fullPackageName,
|
|
2382
2411
|
variant,
|
|
@@ -2446,7 +2475,7 @@ async function listBizUiEntries(variant, packageRoot) {
|
|
|
2446
2475
|
|
|
2447
2476
|
// src/core/lint-init.ts
|
|
2448
2477
|
import * as path13 from "path";
|
|
2449
|
-
import * as
|
|
2478
|
+
import * as fs12 from "fs";
|
|
2450
2479
|
import { execa } from "execa";
|
|
2451
2480
|
var ESLINT_CONFIG_CONTENT = `/**
|
|
2452
2481
|
* teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
|
|
@@ -2538,7 +2567,7 @@ async function runLintInit(options) {
|
|
|
2538
2567
|
let stylelintIgnoreFilesWarning = false;
|
|
2539
2568
|
if (!stylelintNeedsWrite && stylelintTemplateExists) {
|
|
2540
2569
|
try {
|
|
2541
|
-
const existingContent =
|
|
2570
|
+
const existingContent = fs12.readFileSync(stylelintConfigPath, "utf-8");
|
|
2542
2571
|
const usesTeamixPreset = existingContent.includes("@teamix-evo/stylelint-config/presets/") || existingContent.includes("@teamix-evo/stylelint-config/preset/");
|
|
2543
2572
|
const hasTokenIgnore = existingContent.includes("tokens.theme.css") && existingContent.includes("tokens.overrides.css");
|
|
2544
2573
|
if (!usesTeamixPreset && !hasTokenIgnore) {
|
|
@@ -2575,8 +2604,8 @@ async function runLintInit(options) {
|
|
|
2575
2604
|
};
|
|
2576
2605
|
}
|
|
2577
2606
|
function detectPm(projectRoot) {
|
|
2578
|
-
if (
|
|
2579
|
-
if (
|
|
2607
|
+
if (fs12.existsSync(path13.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
2608
|
+
if (fs12.existsSync(path13.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
2580
2609
|
return "npm";
|
|
2581
2610
|
}
|
|
2582
2611
|
async function patchPackageJsonScripts(projectRoot) {
|
|
@@ -2609,7 +2638,7 @@ async function patchPackageJsonScripts(projectRoot) {
|
|
|
2609
2638
|
}
|
|
2610
2639
|
|
|
2611
2640
|
// src/core/init-detect.ts
|
|
2612
|
-
import * as
|
|
2641
|
+
import * as fs13 from "fs/promises";
|
|
2613
2642
|
import * as path14 from "path";
|
|
2614
2643
|
var IGNORED_TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
2615
2644
|
".git",
|
|
@@ -2644,7 +2673,7 @@ async function detectProjectState(cwd) {
|
|
|
2644
2673
|
}
|
|
2645
2674
|
let entries;
|
|
2646
2675
|
try {
|
|
2647
|
-
entries = await
|
|
2676
|
+
entries = await fs13.readdir(absCwd);
|
|
2648
2677
|
} catch (err) {
|
|
2649
2678
|
if (err.code === "ENOENT") {
|
|
2650
2679
|
return {
|
|
@@ -2678,7 +2707,7 @@ async function detectProjectState(cwd) {
|
|
|
2678
2707
|
}
|
|
2679
2708
|
|
|
2680
2709
|
// src/core/project-state.ts
|
|
2681
|
-
import * as
|
|
2710
|
+
import * as fs14 from "fs/promises";
|
|
2682
2711
|
import * as path15 from "path";
|
|
2683
2712
|
var IGNORED_TOP_LEVEL2 = /* @__PURE__ */ new Set([
|
|
2684
2713
|
".git",
|
|
@@ -2738,7 +2767,7 @@ async function detectProjectState2(cwd) {
|
|
|
2738
2767
|
}
|
|
2739
2768
|
let entries;
|
|
2740
2769
|
try {
|
|
2741
|
-
entries = await
|
|
2770
|
+
entries = await fs14.readdir(absCwd);
|
|
2742
2771
|
} catch (err) {
|
|
2743
2772
|
if (err.code === "ENOENT") {
|
|
2744
2773
|
return {
|
|
@@ -2821,7 +2850,7 @@ function assertCommandPrecondition(command, state) {
|
|
|
2821
2850
|
|
|
2822
2851
|
// src/core/init-conflicts.ts
|
|
2823
2852
|
import * as crypto from "crypto";
|
|
2824
|
-
import * as
|
|
2853
|
+
import * as fs15 from "fs/promises";
|
|
2825
2854
|
import * as path16 from "path";
|
|
2826
2855
|
var TAILWIND_CONFIG_CANDIDATES = [
|
|
2827
2856
|
"tailwind.config.ts",
|
|
@@ -2866,7 +2895,7 @@ var STYLELINT_CONFIG_CANDIDATES = [
|
|
|
2866
2895
|
];
|
|
2867
2896
|
async function isDir(target) {
|
|
2868
2897
|
try {
|
|
2869
|
-
const stat3 = await
|
|
2898
|
+
const stat3 = await fs15.stat(target);
|
|
2870
2899
|
return stat3.isDirectory();
|
|
2871
2900
|
} catch {
|
|
2872
2901
|
return false;
|
|
@@ -2874,7 +2903,7 @@ async function isDir(target) {
|
|
|
2874
2903
|
}
|
|
2875
2904
|
async function dirHasContent(target) {
|
|
2876
2905
|
try {
|
|
2877
|
-
const entries = await
|
|
2906
|
+
const entries = await fs15.readdir(target);
|
|
2878
2907
|
return entries.length > 0;
|
|
2879
2908
|
} catch {
|
|
2880
2909
|
return false;
|
|
@@ -3015,7 +3044,7 @@ async function detectShadcnSource(cwd) {
|
|
|
3015
3044
|
try {
|
|
3016
3045
|
const uiDir = path16.join(cwd, "src/components/ui");
|
|
3017
3046
|
if (await isDir(uiDir)) {
|
|
3018
|
-
const entries = await
|
|
3047
|
+
const entries = await fs15.readdir(uiDir);
|
|
3019
3048
|
componentCount = entries.filter(
|
|
3020
3049
|
(e) => e.endsWith(".tsx") || e.endsWith(".ts")
|
|
3021
3050
|
).length;
|
|
@@ -3093,7 +3122,7 @@ async function detectStylelintConfig(cwd) {
|
|
|
3093
3122
|
|
|
3094
3123
|
// src/core/meta-installer.ts
|
|
3095
3124
|
import * as path17 from "path";
|
|
3096
|
-
import * as
|
|
3125
|
+
import * as fs16 from "fs/promises";
|
|
3097
3126
|
import { createRequire as createRequire5 } from "module";
|
|
3098
3127
|
import {
|
|
3099
3128
|
loadUiPackageManifest as loadUiPackageManifest3,
|
|
@@ -3137,7 +3166,7 @@ async function landManifestMeta(opts) {
|
|
|
3137
3166
|
await ensureDir(metaDir);
|
|
3138
3167
|
const manifestDest = path17.join(metaDir, "manifest.json");
|
|
3139
3168
|
const manifestSrc = path17.join(packageRoot, "manifest.json");
|
|
3140
|
-
await
|
|
3169
|
+
await fs16.copyFile(manifestSrc, manifestDest);
|
|
3141
3170
|
logger.debug(`meta: copied manifest.json \u2192 ${manifestDest}`);
|
|
3142
3171
|
let written = 0;
|
|
3143
3172
|
let total = 0;
|
|
@@ -3147,7 +3176,7 @@ async function landManifestMeta(opts) {
|
|
|
3147
3176
|
const srcPath = path17.join(packageRoot, entry.meta);
|
|
3148
3177
|
const destPath = path17.join(metaDir, `${entry.id}.md`);
|
|
3149
3178
|
try {
|
|
3150
|
-
await
|
|
3179
|
+
await fs16.copyFile(srcPath, destPath);
|
|
3151
3180
|
written++;
|
|
3152
3181
|
logger.debug(`meta: ${entry.id} \u2192 ${destPath}`);
|
|
3153
3182
|
} catch (err) {
|
|
@@ -3170,7 +3199,7 @@ async function landManifestMeta(opts) {
|
|
|
3170
3199
|
}
|
|
3171
3200
|
|
|
3172
3201
|
// src/core/deps-install.ts
|
|
3173
|
-
import * as
|
|
3202
|
+
import * as fs17 from "fs/promises";
|
|
3174
3203
|
import * as path18 from "path";
|
|
3175
3204
|
import { exec } from "child_process";
|
|
3176
3205
|
import { promisify } from "util";
|
|
@@ -3227,7 +3256,7 @@ async function installProjectDeps(options) {
|
|
|
3227
3256
|
pkg.dependencies = Object.fromEntries(
|
|
3228
3257
|
Object.entries(pkg.dependencies).sort(([a], [b]) => a.localeCompare(b))
|
|
3229
3258
|
);
|
|
3230
|
-
await
|
|
3259
|
+
await fs17.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3231
3260
|
logger.info(
|
|
3232
3261
|
` patched package.json: +${Object.keys(added).length} dependencies`
|
|
3233
3262
|
);
|
|
@@ -3289,7 +3318,7 @@ ${stepLines}
|
|
|
3289
3318
|
}
|
|
3290
3319
|
|
|
3291
3320
|
// src/core/file-changes.ts
|
|
3292
|
-
import * as
|
|
3321
|
+
import * as fs18 from "fs/promises";
|
|
3293
3322
|
import * as path19 from "path";
|
|
3294
3323
|
function toRelativePosix(p, projectRoot) {
|
|
3295
3324
|
let rel2 = p;
|
|
@@ -3418,6 +3447,7 @@ async function runProjectInit(options) {
|
|
|
3418
3447
|
`teamix-evo-design-${variant}`,
|
|
3419
3448
|
`teamix-evo-code-${variant}`
|
|
3420
3449
|
],
|
|
3450
|
+
globalSkillIds: ["teamix-evo-manage"],
|
|
3421
3451
|
mode: "merge-managed"
|
|
3422
3452
|
});
|
|
3423
3453
|
record({
|
|
@@ -3748,7 +3778,7 @@ function deriveLintChanges(result) {
|
|
|
3748
3778
|
|
|
3749
3779
|
// src/core/installer.ts
|
|
3750
3780
|
import * as path21 from "path";
|
|
3751
|
-
import * as
|
|
3781
|
+
import * as fs19 from "fs/promises";
|
|
3752
3782
|
async function installResources(options) {
|
|
3753
3783
|
const { projectRoot, manifest, data, variantDir, packageRoot } = options;
|
|
3754
3784
|
const installedResources = [];
|
|
@@ -3791,7 +3821,7 @@ async function installSingleResource(resource, projectRoot, data, variantDir, pa
|
|
|
3791
3821
|
const templateContent = await loadTemplateFile(sourcePath);
|
|
3792
3822
|
content = renderTemplate(templateContent, data);
|
|
3793
3823
|
} else {
|
|
3794
|
-
content = await
|
|
3824
|
+
content = await fs19.readFile(sourcePath, "utf-8");
|
|
3795
3825
|
}
|
|
3796
3826
|
await writeFileSafe(targetPath, content);
|
|
3797
3827
|
const hash = computeHash(content);
|
|
@@ -3824,7 +3854,7 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3824
3854
|
const templateContent = await loadTemplateFile(entry);
|
|
3825
3855
|
content = renderTemplate(templateContent, data);
|
|
3826
3856
|
} else {
|
|
3827
|
-
content = await
|
|
3857
|
+
content = await fs19.readFile(entry, "utf-8");
|
|
3828
3858
|
}
|
|
3829
3859
|
await writeFileSafe(targetFile, content);
|
|
3830
3860
|
const hash = computeHash(content);
|
|
@@ -3842,7 +3872,7 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3842
3872
|
|
|
3843
3873
|
// src/core/registry-client.ts
|
|
3844
3874
|
import * as path22 from "path";
|
|
3845
|
-
import * as
|
|
3875
|
+
import * as fs20 from "fs/promises";
|
|
3846
3876
|
import { createRequire as createRequire6 } from "module";
|
|
3847
3877
|
import { loadVariantManifest } from "@teamix-evo/registry";
|
|
3848
3878
|
var require7 = createRequire6(import.meta.url);
|
|
@@ -3859,7 +3889,7 @@ async function loadVariantData(packageName, variant) {
|
|
|
3859
3889
|
let data = {};
|
|
3860
3890
|
const dataPath = path22.join(variantDir, "_data.json");
|
|
3861
3891
|
try {
|
|
3862
|
-
const raw = await
|
|
3892
|
+
const raw = await fs20.readFile(dataPath, "utf-8");
|
|
3863
3893
|
data = JSON.parse(raw);
|
|
3864
3894
|
} catch (err) {
|
|
3865
3895
|
if (err.code !== "ENOENT") {
|