@teamix-evo/mcp 0.3.0 → 0.4.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 -1
- package/dist/cli.js +161 -162
- package/dist/cli.js.map +1 -1
- package/dist/data/adr/0001-three-layer-alignment.md +54 -0
- package/dist/data/adr/0002-package-naming.md +50 -0
- package/dist/data/adr/0003-update-strategy-tri-state.md +62 -0
- package/dist/data/adr/0004-cli-command-structure.md +61 -0
- package/dist/data/adr/0005-ui-no-variant.md +67 -0
- package/dist/data/adr/0006-ui-upgrade-no-baseline.md +67 -0
- package/dist/data/adr/0007-governance-docs-at-root.md +62 -0
- package/dist/data/adr/0008-eslint-visual-rules-warn-baseline.md +110 -0
- package/dist/data/adr/0009-registry-mcp-protocol-layer.md +87 -0
- package/dist/data/adr/0010-design-default-and-variants.md +319 -0
- package/dist/data/adr/0011-mcp-single-package-multi-group.md +169 -0
- package/dist/data/adr/0012-lint-shared-core.md +215 -0
- package/dist/data/adr/0013-skills-source-mirror.md +154 -0
- package/dist/data/adr/0014-ui-biz-ui-templates-tier.md +274 -0
- package/dist/data/adr/0015-skill-description-trigger-contract.md +122 -0
- package/dist/data/adr/0016-design-md-brand-charter.md +93 -0
- package/dist/data/adr/0017-mcp-design-group.md +107 -0
- package/dist/data/adr/0018-ai-context-routing.md +112 -0
- package/dist/data/adr/0019-project-upgrade-flow.md +156 -0
- package/dist/data/adr/0020-design-to-tokens-skill-fusion.md +139 -0
- package/dist/data/adr/README.md +70 -0
- package/dist/data/adr/_template.md +36 -0
- package/dist/index.d.ts +64 -59
- package/dist/index.js +168 -170
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
| Group | Status | Tools | Naming |
|
|
19
19
|
| --- | --- | --- | --- |
|
|
20
20
|
| **registry** | ✅ shipping | `list_components` / `get_component_meta` / `find_components` | unprefixed (historical exception, see ADR 0011 §5) |
|
|
21
|
-
| **
|
|
21
|
+
| **tokens** | ✅ shipping | `tokens_get` / `tokens_list` / `tokens_search` | `<group>_<verb>_<noun>` |
|
|
22
22
|
| **skills** | ✅ shipping | `skills_list` / `skills_get` / `skills_find` | `<group>_<verb>_<noun>` |
|
|
23
23
|
| **adr** | ✅ shipping | `adr_list` / `adr_get` / `adr_find` | `<group>_<verb>_<noun>` |
|
|
24
24
|
| **scenario** | ⏸ v0.8 | `scenario_list` / `scenario_get_pack` | `<group>_<verb>_<noun>` |
|
package/dist/cli.js
CHANGED
|
@@ -40,10 +40,15 @@ function resolveManifestPath(startDir = process.cwd()) {
|
|
|
40
40
|
}
|
|
41
41
|
throw new Error(
|
|
42
42
|
[
|
|
43
|
-
"Could not locate @teamix-evo/ui/manifest.json.",
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
43
|
+
"Could not locate @teamix-evo/ui/manifest.json \u2014 the UI registry is not installed in this project.",
|
|
44
|
+
"",
|
|
45
|
+
"Fix one of:",
|
|
46
|
+
` 1. Install the package: pnpm add @teamix-evo/ui (or npm/yarn equivalent)`,
|
|
47
|
+
` 2. Point env at an existing manifest: export TEAMIX_EVO_UI_MANIFEST=/abs/path/to/manifest.json`,
|
|
48
|
+
"",
|
|
49
|
+
`Searched: $TEAMIX_EVO_UI_MANIFEST, then walked up from ${startDir} looking for node_modules/@teamix-evo/ui/manifest.json (16 levels).`,
|
|
50
|
+
"Note: MCP currently has no online fallback \u2014 it does not fetch from the npm registry / unpkg."
|
|
51
|
+
].join("\n")
|
|
47
52
|
);
|
|
48
53
|
}
|
|
49
54
|
function loadManifest(path) {
|
|
@@ -238,11 +243,18 @@ import { z as z2 } from "zod";
|
|
|
238
243
|
// src/adr-loader.ts
|
|
239
244
|
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync } from "fs";
|
|
240
245
|
import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
246
|
+
import { fileURLToPath } from "url";
|
|
241
247
|
function resolveAdrRoot(startDir = process.cwd()) {
|
|
242
248
|
const envPath = process.env.TEAMIX_EVO_ADR_ROOT;
|
|
243
249
|
if (envPath && existsSync2(envPath)) {
|
|
244
250
|
return envPath;
|
|
245
251
|
}
|
|
252
|
+
try {
|
|
253
|
+
const here = dirname2(fileURLToPath(import.meta.url));
|
|
254
|
+
const bundled = join2(here, "data", "adr");
|
|
255
|
+
if (existsSync2(bundled)) return bundled;
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
246
258
|
let dir = resolve2(startDir);
|
|
247
259
|
for (let i = 0; i < 16; i++) {
|
|
248
260
|
const candidates = [
|
|
@@ -259,8 +271,8 @@ function resolveAdrRoot(startDir = process.cwd()) {
|
|
|
259
271
|
throw new Error(
|
|
260
272
|
[
|
|
261
273
|
"Could not locate ADR directory.",
|
|
262
|
-
`Tried env TEAMIX_EVO_ADR_ROOT
|
|
263
|
-
"Either
|
|
274
|
+
`Tried env TEAMIX_EVO_ADR_ROOT, mcp-bundled snapshot, and walked up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,
|
|
275
|
+
"Either install @teamix-evo/mcp (carries ADR snapshot) or set TEAMIX_EVO_ADR_ROOT to an absolute path."
|
|
264
276
|
].join(" ")
|
|
265
277
|
);
|
|
266
278
|
}
|
|
@@ -544,8 +556,8 @@ function resolveSkillsRoot(startDir = process.cwd()) {
|
|
|
544
556
|
throw new Error(
|
|
545
557
|
[
|
|
546
558
|
"Could not locate @teamix-evo/skills root.",
|
|
547
|
-
`Tried env TEAMIX_EVO_SKILLS_ROOT
|
|
548
|
-
"
|
|
559
|
+
`Tried env TEAMIX_EVO_SKILLS_ROOT and walked up from ${startDir} for packages/skills/ or node_modules/@teamix-evo/skills/.`,
|
|
560
|
+
"Install @teamix-evo/skills as a devDependency in your project (the scaffold adds it automatically)."
|
|
549
561
|
].join(" ")
|
|
550
562
|
);
|
|
551
563
|
}
|
|
@@ -795,20 +807,20 @@ function createSkillsGroup(opts = {}) {
|
|
|
795
807
|
};
|
|
796
808
|
}
|
|
797
809
|
|
|
798
|
-
// src/groups/
|
|
810
|
+
// src/groups/tokens.ts
|
|
799
811
|
import { z as z4 } from "zod";
|
|
800
812
|
|
|
801
|
-
// src/
|
|
802
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4
|
|
813
|
+
// src/tokens-loader.ts
|
|
814
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
803
815
|
import { dirname as dirname4, join as join4, resolve as resolve4 } from "path";
|
|
804
|
-
function
|
|
805
|
-
const envPath = process.env.
|
|
816
|
+
function resolveTokensRoot(startDir = process.cwd()) {
|
|
817
|
+
const envPath = process.env.TEAMIX_EVO_TOKENS_ROOT;
|
|
806
818
|
if (envPath && existsSync4(envPath)) {
|
|
807
819
|
return envPath;
|
|
808
820
|
}
|
|
809
821
|
let dir = resolve4(startDir);
|
|
810
822
|
for (let i = 0; i < 16; i++) {
|
|
811
|
-
const candidate = join4(dir, ".teamix-evo"
|
|
823
|
+
const candidate = join4(dir, ".teamix-evo");
|
|
812
824
|
if (existsSync4(candidate)) return candidate;
|
|
813
825
|
const parent = dirname4(dir);
|
|
814
826
|
if (parent === dir) break;
|
|
@@ -816,11 +828,11 @@ function resolveDesignRoot(startDir = process.cwd()) {
|
|
|
816
828
|
}
|
|
817
829
|
return null;
|
|
818
830
|
}
|
|
819
|
-
function
|
|
820
|
-
const root = rootDir ??
|
|
831
|
+
function loadTokens(rootDir) {
|
|
832
|
+
const root = rootDir ?? resolveTokensRoot();
|
|
821
833
|
if (!root) return null;
|
|
822
834
|
let variant = null;
|
|
823
|
-
const lockPath = join4(root, "
|
|
835
|
+
const lockPath = join4(root, "tokens-lock.json");
|
|
824
836
|
if (existsSync4(lockPath)) {
|
|
825
837
|
try {
|
|
826
838
|
const raw = JSON.parse(readFileSync4(lockPath, "utf-8"));
|
|
@@ -831,47 +843,17 @@ function loadDesign(rootDir) {
|
|
|
831
843
|
}
|
|
832
844
|
return { rootDir: root, variant };
|
|
833
845
|
}
|
|
834
|
-
var PRINCIPLE_HEADING_RE = /^#{2,3}\s+(P\d+)\s*[·:]\s*(.+?)\s*$/;
|
|
835
|
-
function readPrinciples(loaded) {
|
|
836
|
-
const filePath = join4(loaded.rootDir, "philosophy", "principles.md");
|
|
837
|
-
if (!existsSync4(filePath)) {
|
|
838
|
-
return {
|
|
839
|
-
principles: [],
|
|
840
|
-
sourcePath: null,
|
|
841
|
-
note: "philosophy/principles.md not found in this project. Run `teamix-evo design init <variant>` to install it."
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
const text = readFileSync4(filePath, "utf-8");
|
|
845
|
-
const lines = text.split(/\r?\n/);
|
|
846
|
-
const out = [];
|
|
847
|
-
for (let i = 0; i < lines.length; i++) {
|
|
848
|
-
const m = lines[i].match(PRINCIPLE_HEADING_RE);
|
|
849
|
-
if (!m) continue;
|
|
850
|
-
let def = "";
|
|
851
|
-
for (let j = i + 1; j < lines.length && j < i + 8; j++) {
|
|
852
|
-
const candidate = lines[j].trim();
|
|
853
|
-
if (!candidate) continue;
|
|
854
|
-
if (/^#{1,6}\s/.test(candidate)) break;
|
|
855
|
-
def = candidate.replace(/^[*_>\s-]+/, "").trim();
|
|
856
|
-
break;
|
|
857
|
-
}
|
|
858
|
-
out.push({ id: m[1], name: m[2].trim(), oneLineDef: def });
|
|
859
|
-
}
|
|
860
|
-
return { principles: out, sourcePath: filePath };
|
|
861
|
-
}
|
|
862
846
|
function resolveTokensDir(loaded) {
|
|
863
847
|
const projectRoot = dirname4(loaded.rootDir);
|
|
864
|
-
const
|
|
865
|
-
if (existsSync4(
|
|
866
|
-
const legacy = join4(loaded.rootDir, "foundations", "tokens");
|
|
867
|
-
if (existsSync4(legacy)) return legacy;
|
|
848
|
+
const rootTokens = join4(projectRoot, "tokens");
|
|
849
|
+
if (existsSync4(rootTokens)) return rootTokens;
|
|
868
850
|
return null;
|
|
869
851
|
}
|
|
870
852
|
function readTokens(loaded) {
|
|
871
853
|
const tokensDir = resolveTokensDir(loaded);
|
|
872
854
|
const out = { sources: [] };
|
|
873
855
|
if (!tokensDir) {
|
|
874
|
-
out.note = "
|
|
856
|
+
out.note = "tokens/ not found at project root.";
|
|
875
857
|
return out;
|
|
876
858
|
}
|
|
877
859
|
const tryJson = (rel) => {
|
|
@@ -891,169 +873,186 @@ function readTokens(loaded) {
|
|
|
891
873
|
return readFileSync4(fp, "utf-8");
|
|
892
874
|
};
|
|
893
875
|
out.base = tryJson("base.tokens.json");
|
|
894
|
-
out.semantic = tryJson("semantic.tokens.json");
|
|
895
876
|
out.themeCss = tryText("tokens.theme.css");
|
|
896
877
|
out.overridesCss = tryText("tokens.overrides.css");
|
|
897
878
|
return out;
|
|
898
879
|
}
|
|
899
|
-
var
|
|
900
|
-
function
|
|
901
|
-
|
|
902
|
-
|
|
880
|
+
var W3C_KEYS = /* @__PURE__ */ new Set(["$value", "$type", "$description", "$extensions"]);
|
|
881
|
+
function isPlainObject(v) {
|
|
882
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
883
|
+
}
|
|
884
|
+
function flattenTokens(base) {
|
|
885
|
+
if (!isPlainObject(base)) return [];
|
|
903
886
|
const out = [];
|
|
904
|
-
for (const
|
|
905
|
-
if (
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
if (
|
|
909
|
-
|
|
910
|
-
|
|
887
|
+
for (const [category, group] of Object.entries(base)) {
|
|
888
|
+
if (category.startsWith("$")) continue;
|
|
889
|
+
if (!isPlainObject(group)) continue;
|
|
890
|
+
for (const [name, leaf] of Object.entries(group)) {
|
|
891
|
+
if (name.startsWith("$")) continue;
|
|
892
|
+
if (!isPlainObject(leaf)) continue;
|
|
893
|
+
const type = typeof leaf.$type === "string" ? leaf.$type : void 0;
|
|
894
|
+
const values = {};
|
|
895
|
+
let description = typeof leaf.$description === "string" ? leaf.$description : void 0;
|
|
896
|
+
if (typeof leaf.$value === "string") {
|
|
897
|
+
values.default = leaf.$value;
|
|
898
|
+
}
|
|
899
|
+
for (const [modeKey, modeVal] of Object.entries(leaf)) {
|
|
900
|
+
if (W3C_KEYS.has(modeKey)) continue;
|
|
901
|
+
if (!isPlainObject(modeVal)) continue;
|
|
902
|
+
if (typeof modeVal.$value === "string") {
|
|
903
|
+
values[modeKey] = modeVal.$value;
|
|
904
|
+
}
|
|
905
|
+
if (!description && typeof modeVal.$description === "string") {
|
|
906
|
+
description = modeVal.$description;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (Object.keys(values).length === 0) continue;
|
|
910
|
+
out.push({
|
|
911
|
+
category,
|
|
912
|
+
name,
|
|
913
|
+
...type ? { type } : {},
|
|
914
|
+
values,
|
|
915
|
+
...description ? { description } : {}
|
|
916
|
+
});
|
|
911
917
|
}
|
|
912
|
-
const stem = name.replace(/\.md$/, "");
|
|
913
|
-
const text = readFileSync4(fp, "utf-8");
|
|
914
|
-
const titleMatch = text.match(/^#\s+(.+?)\s*$/m);
|
|
915
|
-
out.push({
|
|
916
|
-
id: stem,
|
|
917
|
-
title: titleMatch ? titleMatch[1] : stem,
|
|
918
|
-
sourcePath: fp,
|
|
919
|
-
variantSpecific: VARIANT_PREFIX_RE.test(stem)
|
|
920
|
-
});
|
|
921
918
|
}
|
|
922
|
-
return out
|
|
919
|
+
return out;
|
|
923
920
|
}
|
|
924
|
-
function
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
|
|
921
|
+
function listTokens(loaded) {
|
|
922
|
+
const snapshot = readTokens(loaded);
|
|
923
|
+
if (!snapshot.base) {
|
|
924
|
+
return {
|
|
925
|
+
variant: loaded.variant,
|
|
926
|
+
tokens: [],
|
|
927
|
+
sources: snapshot.sources,
|
|
928
|
+
note: snapshot.note ?? "base.tokens.json not found."
|
|
929
|
+
};
|
|
930
|
+
}
|
|
928
931
|
return {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
+
variant: loaded.variant,
|
|
933
|
+
tokens: flattenTokens(snapshot.base),
|
|
934
|
+
sources: snapshot.sources
|
|
932
935
|
};
|
|
933
936
|
}
|
|
934
|
-
function
|
|
935
|
-
const
|
|
936
|
-
const
|
|
937
|
-
if (!
|
|
938
|
-
|
|
939
|
-
|
|
937
|
+
function searchTokens(loaded, query, limit = 20) {
|
|
938
|
+
const list = listTokens(loaded);
|
|
939
|
+
const q = query.trim().toLowerCase();
|
|
940
|
+
if (!q) {
|
|
941
|
+
return {
|
|
942
|
+
variant: list.variant,
|
|
943
|
+
query,
|
|
944
|
+
matches: [],
|
|
945
|
+
sources: list.sources,
|
|
946
|
+
note: "query is empty."
|
|
947
|
+
};
|
|
940
948
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
949
|
+
if (list.note && list.tokens.length === 0) {
|
|
950
|
+
return {
|
|
951
|
+
variant: list.variant,
|
|
952
|
+
query,
|
|
953
|
+
matches: [],
|
|
954
|
+
sources: list.sources,
|
|
955
|
+
note: list.note
|
|
956
|
+
};
|
|
946
957
|
}
|
|
947
|
-
|
|
958
|
+
const hits = list.tokens.filter((t) => {
|
|
959
|
+
if (t.category.toLowerCase().includes(q)) return true;
|
|
960
|
+
if (t.name.toLowerCase().includes(q)) return true;
|
|
961
|
+
if (t.description?.toLowerCase().includes(q)) return true;
|
|
962
|
+
return Object.values(t.values).some((v) => v.toLowerCase().includes(q));
|
|
963
|
+
});
|
|
964
|
+
hits.sort((a, b) => {
|
|
965
|
+
const c = a.category.localeCompare(b.category);
|
|
966
|
+
return c !== 0 ? c : a.name.localeCompare(b.name);
|
|
967
|
+
});
|
|
968
|
+
return {
|
|
969
|
+
variant: list.variant,
|
|
970
|
+
query,
|
|
971
|
+
matches: hits.slice(0, limit),
|
|
972
|
+
sources: list.sources
|
|
973
|
+
};
|
|
948
974
|
}
|
|
949
975
|
|
|
950
|
-
// src/groups/
|
|
976
|
+
// src/groups/tokens.ts
|
|
951
977
|
var EmptyInput = z4.object({});
|
|
952
|
-
var
|
|
953
|
-
|
|
978
|
+
var SearchInput = z4.object({
|
|
979
|
+
query: z4.string().min(1),
|
|
980
|
+
limit: z4.number().int().min(1).max(100).optional()
|
|
954
981
|
});
|
|
955
982
|
var TOOLS4 = [
|
|
956
983
|
{
|
|
957
|
-
name: "
|
|
958
|
-
description:
|
|
959
|
-
inputSchema: { type: "object", properties: {} }
|
|
960
|
-
},
|
|
961
|
-
{
|
|
962
|
-
name: "design_get_tokens",
|
|
963
|
-
description: "Fetch the consumer project's design tokens \u2014 parsed JSON from `.teamix-evo/tokens/base.tokens.json` and `semantic.tokens.json`, plus raw text of `tokens.theme.css` (variant theme) and `tokens.overrides.css` (user-owned overrides) when present. Use when AI needs to know what semantic colors / spacing / radii are available before writing component styles. JSON is for introspection; CSS is for copy-paste. Each tool result lists `sources` so you can cite paths.",
|
|
984
|
+
name: "tokens_get",
|
|
985
|
+
description: "Fetch the consumer project's design tokens \u2014 parsed JSON from `tokens/base.tokens.json`, plus raw text of `tokens.theme.css` (variant theme) and `tokens.overrides.css` (user-owned overrides) when present. Use when AI needs to know what semantic colors / spacing / radii are available before writing component styles. JSON is for introspection; CSS is for copy-paste. Each result lists `sources` so you can cite paths.",
|
|
964
986
|
inputSchema: { type: "object", properties: {} }
|
|
965
987
|
},
|
|
966
988
|
{
|
|
967
|
-
name: "
|
|
968
|
-
description: "
|
|
989
|
+
name: "tokens_list",
|
|
990
|
+
description: "List ALL design tokens as a flat array of entries `{ category, name, type, values, description }`. Categories come from top-level keys of base.tokens.json (e.g. `color`, `radius`, `spacing`). Each entry exposes resolved values keyed by mode (e.g. `light` / `dark` / `default`). Use this BEFORE writing styles to discover what semantic names are available \u2014 much cheaper than parsing the whole CSS file. Use `tokens_search` instead when you have a keyword.",
|
|
969
991
|
inputSchema: { type: "object", properties: {} }
|
|
970
992
|
},
|
|
971
993
|
{
|
|
972
|
-
name: "
|
|
973
|
-
description:
|
|
994
|
+
name: "tokens_search",
|
|
995
|
+
description: 'Substring match across token category / name / description / values (case-insensitive). Use when you remember a phrase ("primary" / "destructive" / "card-gap") but not the exact path. Returns up to `limit` matches (default 20). Combine with `tokens_get` if you need raw CSS text after locating an entry.',
|
|
974
996
|
inputSchema: {
|
|
975
997
|
type: "object",
|
|
976
998
|
properties: {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
999
|
+
query: { type: "string", description: "Free-text query." },
|
|
1000
|
+
limit: {
|
|
1001
|
+
type: "integer",
|
|
1002
|
+
minimum: 1,
|
|
1003
|
+
maximum: 100,
|
|
1004
|
+
description: "Max matches to return (default 20)."
|
|
980
1005
|
}
|
|
981
1006
|
},
|
|
982
|
-
required: ["
|
|
1007
|
+
required: ["query"]
|
|
983
1008
|
}
|
|
984
|
-
},
|
|
985
|
-
{
|
|
986
|
-
name: "design_get_brand",
|
|
987
|
-
description: "Fetch the consumer project's variant-specific brand voice \u2014 `brand/tone.md`, `brand/voice.md`, `brand/examples.md`. Each is optional; the response contains only the files that exist. Some variants (like `_template` or `default`) ship no brand content \u2014 that's not an error, the response simply lists no entries. Use this when generating or reviewing user-facing copy, error messages, empty states, or onboarding text where brand voice matters.",
|
|
988
|
-
inputSchema: { type: "object", properties: {} }
|
|
989
1009
|
}
|
|
990
1010
|
];
|
|
991
1011
|
var TOOL_NAMES4 = new Set(TOOLS4.map((t) => t.name));
|
|
992
|
-
var
|
|
993
|
-
function
|
|
1012
|
+
var NO_TOKENS_NOTE = "tokens/ directory not found in this project. Run `npx teamix-evo tokens init <variant>` to install design tokens.";
|
|
1013
|
+
function createTokensGroup(opts = {}) {
|
|
994
1014
|
let cache = opts.loaded === void 0 ? void 0 : opts.loaded;
|
|
995
|
-
function
|
|
996
|
-
if (cache === void 0) cache =
|
|
1015
|
+
function getLoaded() {
|
|
1016
|
+
if (cache === void 0) cache = loadTokens(opts.rootDir);
|
|
997
1017
|
return cache;
|
|
998
1018
|
}
|
|
999
1019
|
return {
|
|
1000
|
-
name: "
|
|
1020
|
+
name: "tokens",
|
|
1001
1021
|
tools: TOOLS4,
|
|
1002
1022
|
async handle(name, args) {
|
|
1003
1023
|
if (!TOOL_NAMES4.has(name)) return void 0;
|
|
1004
|
-
const loaded =
|
|
1005
|
-
if (name === "
|
|
1006
|
-
EmptyInput.parse(args ?? {});
|
|
1007
|
-
if (!loaded) {
|
|
1008
|
-
return jsonResult({ principles: [], sourcePath: null, note: NO_DESIGN_NOTE });
|
|
1009
|
-
}
|
|
1010
|
-
return jsonResult(readPrinciples(loaded));
|
|
1011
|
-
}
|
|
1012
|
-
if (name === "design_get_tokens") {
|
|
1024
|
+
const loaded = getLoaded();
|
|
1025
|
+
if (name === "tokens_get") {
|
|
1013
1026
|
EmptyInput.parse(args ?? {});
|
|
1014
1027
|
if (!loaded) {
|
|
1015
|
-
return jsonResult({ sources: [], note:
|
|
1028
|
+
return jsonResult({ sources: [], note: NO_TOKENS_NOTE });
|
|
1016
1029
|
}
|
|
1017
1030
|
return jsonResult(readTokens(loaded));
|
|
1018
1031
|
}
|
|
1019
|
-
if (name === "
|
|
1032
|
+
if (name === "tokens_list") {
|
|
1020
1033
|
EmptyInput.parse(args ?? {});
|
|
1021
1034
|
if (!loaded) {
|
|
1022
|
-
return jsonResult({
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
}
|
|
1029
|
-
if (name === "design_get_pattern") {
|
|
1030
|
-
const input = GetPatternInput.parse(args);
|
|
1031
|
-
if (!loaded) {
|
|
1032
|
-
return {
|
|
1033
|
-
content: [{ type: "text", text: NO_DESIGN_NOTE }],
|
|
1034
|
-
isError: true
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
const result = readPatternContent(loaded, input.id);
|
|
1038
|
-
if (!result) {
|
|
1039
|
-
return {
|
|
1040
|
-
content: [
|
|
1041
|
-
{
|
|
1042
|
-
type: "text",
|
|
1043
|
-
text: `Pattern not found: ${input.id}. Use design_list_patterns to discover available ids.`
|
|
1044
|
-
}
|
|
1045
|
-
],
|
|
1046
|
-
isError: true
|
|
1047
|
-
};
|
|
1035
|
+
return jsonResult({
|
|
1036
|
+
variant: null,
|
|
1037
|
+
tokens: [],
|
|
1038
|
+
sources: [],
|
|
1039
|
+
note: NO_TOKENS_NOTE
|
|
1040
|
+
});
|
|
1048
1041
|
}
|
|
1049
|
-
return jsonResult(
|
|
1042
|
+
return jsonResult(listTokens(loaded));
|
|
1050
1043
|
}
|
|
1051
|
-
if (name === "
|
|
1052
|
-
|
|
1044
|
+
if (name === "tokens_search") {
|
|
1045
|
+
const parsed = SearchInput.parse(args ?? {});
|
|
1053
1046
|
if (!loaded) {
|
|
1054
|
-
return jsonResult({
|
|
1047
|
+
return jsonResult({
|
|
1048
|
+
variant: null,
|
|
1049
|
+
query: parsed.query,
|
|
1050
|
+
matches: [],
|
|
1051
|
+
sources: [],
|
|
1052
|
+
note: NO_TOKENS_NOTE
|
|
1053
|
+
});
|
|
1055
1054
|
}
|
|
1056
|
-
return jsonResult(
|
|
1055
|
+
return jsonResult(searchTokens(loaded, parsed.query, parsed.limit));
|
|
1057
1056
|
}
|
|
1058
1057
|
return void 0;
|
|
1059
1058
|
}
|
|
@@ -1071,7 +1070,7 @@ function createServer(opts = {}) {
|
|
|
1071
1070
|
createRegistryGroup(opts.registry),
|
|
1072
1071
|
createAdrGroup(opts.adr),
|
|
1073
1072
|
createSkillsGroup(opts.skills),
|
|
1074
|
-
|
|
1073
|
+
createTokensGroup(opts.tokens)
|
|
1075
1074
|
// Future: createScenarioGroup(opts.scenario), // ADR 0011, v0.8
|
|
1076
1075
|
];
|
|
1077
1076
|
const seen = /* @__PURE__ */ new Set();
|