@mcptoolshop/claude-synergy 1.1.0 → 1.2.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/CHANGELOG.md +5 -0
- package/README.es.md +25 -22
- package/README.fr.md +7 -4
- package/README.hi.md +7 -4
- package/README.it.md +27 -24
- package/README.ja.md +7 -4
- package/README.md +11 -8
- package/README.pt-BR.md +7 -4
- package/README.zh.md +29 -26
- package/dist/{chunk-H3466JDH.js → chunk-CEIOLMDT.js} +197 -885
- package/dist/{chunk-HZEQG3WT.js → chunk-KFAQPOGV.js} +21 -142
- package/dist/chunk-MTW6UZBF.js +743 -0
- package/dist/chunk-MZLFGICO.js +133 -0
- package/dist/chunk-X25ZTSCJ.js +1150 -0
- package/dist/cli.js +22 -1156
- package/dist/embed-OCOZWLXF.js +10 -0
- package/dist/fetch-XS3IETWW.js +11 -0
- package/dist/{ingest-Z45YH7OX.js → ingest-D23NTE25.js} +2 -1
- package/dist/mcp-server.js +174 -2
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/products-config.ts
|
|
2
|
+
import { readFileSync, existsSync } from "fs";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { parse as parseYaml } from "yaml";
|
|
6
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
var PRODUCT_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
8
|
+
var GH_REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
9
|
+
var warnedAboutMissingYaml = false;
|
|
10
|
+
function loadProductsConfig(yamlPath) {
|
|
11
|
+
const resolved = yamlPath ?? resolveYamlPath();
|
|
12
|
+
if (!resolved || !existsSync(resolved)) {
|
|
13
|
+
if (!warnedAboutMissingYaml) {
|
|
14
|
+
console.error(`[claude-synergy] products.yaml not found at ${resolved}; using hardcoded defaults`);
|
|
15
|
+
warnedAboutMissingYaml = true;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
let raw;
|
|
20
|
+
try {
|
|
21
|
+
raw = readFileSync(resolved, "utf-8");
|
|
22
|
+
} catch (e) {
|
|
23
|
+
console.error(`[claude-synergy] could not read ${resolved}: ${e.message}; using hardcoded defaults`);
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (raw.charCodeAt(0) === 65279) raw = raw.slice(1);
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
parsed = parseYaml(raw);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
throw new Error(`[claude-synergy] products.yaml parse error: ${e.message}`);
|
|
32
|
+
}
|
|
33
|
+
if (!parsed || !Array.isArray(parsed.products)) {
|
|
34
|
+
throw new Error(`[claude-synergy] products.yaml missing required 'products' array`);
|
|
35
|
+
}
|
|
36
|
+
const productMeta = {};
|
|
37
|
+
const fetchTargets = [];
|
|
38
|
+
for (const p of parsed.products) {
|
|
39
|
+
if (!p.name || !p.display_name) {
|
|
40
|
+
throw new Error(`[claude-synergy] products.yaml entry missing name/display_name: ${JSON.stringify(p)}`);
|
|
41
|
+
}
|
|
42
|
+
if (!PRODUCT_NAME_RE.test(p.name)) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`[claude-synergy] products.yaml: invalid product name '${p.name}' \u2014 must match /^[a-z0-9][a-z0-9-]*$/ (lowercase alphanumeric + hyphens, no leading hyphen)`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
productMeta[p.name] = {
|
|
48
|
+
name: p.name,
|
|
49
|
+
display_name: p.display_name,
|
|
50
|
+
source_tier: p.tier ?? 1,
|
|
51
|
+
source_url: p.source_url ?? "",
|
|
52
|
+
fetch_strategy: p.fetch_strategy ?? "gh-releases",
|
|
53
|
+
notes: p.notes ?? null
|
|
54
|
+
};
|
|
55
|
+
if (p.fetch) {
|
|
56
|
+
const target = buildFetchTarget(p.name, p.fetch);
|
|
57
|
+
if (target) {
|
|
58
|
+
if (target.strategy === "gh-releases" && target.repo && !GH_REPO_RE.test(target.repo)) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`[claude-synergy] products.yaml: ${p.name}: invalid repo '${target.repo}' \u2014 must match 'owner/repo' (alphanumeric + dot/underscore/hyphen)`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
fetchTargets.push(target);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { productMeta, fetchTargets };
|
|
68
|
+
}
|
|
69
|
+
function buildFetchTarget(name, fetch) {
|
|
70
|
+
if (!fetch) return null;
|
|
71
|
+
const target = { product: name, strategy: fetch.type };
|
|
72
|
+
switch (fetch.type) {
|
|
73
|
+
case "gh-releases":
|
|
74
|
+
if (!fetch.repo) throw new Error(`[claude-synergy] ${name}: gh-releases requires 'repo'`);
|
|
75
|
+
target.repo = fetch.repo;
|
|
76
|
+
if (fetch.multi_package) target.multiPackage = true;
|
|
77
|
+
break;
|
|
78
|
+
case "rss":
|
|
79
|
+
if (!fetch.url) throw new Error(`[claude-synergy] ${name}: rss requires 'url'`);
|
|
80
|
+
target.rssUrl = fetch.url;
|
|
81
|
+
if (fetch.title_filter) {
|
|
82
|
+
try {
|
|
83
|
+
target.rssTitleFilter = new RegExp(fetch.title_filter, "i");
|
|
84
|
+
} catch (e) {
|
|
85
|
+
throw new Error(`[claude-synergy] ${name}: invalid rss title_filter regex: ${e.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
case "raw-changelog":
|
|
90
|
+
if (!fetch.url) throw new Error(`[claude-synergy] ${name}: raw-changelog requires 'url'`);
|
|
91
|
+
if (!fetch.parser) throw new Error(`[claude-synergy] ${name}: raw-changelog requires 'parser'`);
|
|
92
|
+
if (fetch.parser !== "aider-history" && fetch.parser !== "keep-a-changelog") {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`[claude-synergy] ${name}: raw-changelog 'parser' must be one of: aider-history, keep-a-changelog (got '${fetch.parser}')`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
target.rawChangelogUrl = fetch.url;
|
|
98
|
+
target.rawChangelogParser = fetch.parser;
|
|
99
|
+
break;
|
|
100
|
+
case "html-scrape":
|
|
101
|
+
if (!fetch.parser) throw new Error(`[claude-synergy] ${name}: html-scrape requires 'parser'`);
|
|
102
|
+
target.htmlParser = fetch.parser;
|
|
103
|
+
break;
|
|
104
|
+
case "catalog":
|
|
105
|
+
if (!fetch.catalog_type) throw new Error(`[claude-synergy] ${name}: catalog requires 'catalog_type'`);
|
|
106
|
+
target.catalogType = fetch.catalog_type;
|
|
107
|
+
if (fetch.max_entries) target.catalogMaxEntries = fetch.max_entries;
|
|
108
|
+
break;
|
|
109
|
+
case "playwright":
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
throw new Error(`[claude-synergy] ${name}: unknown fetch type ${fetch.type}`);
|
|
113
|
+
}
|
|
114
|
+
return target;
|
|
115
|
+
}
|
|
116
|
+
function resolveYamlPath() {
|
|
117
|
+
const candidates = [
|
|
118
|
+
join(__dirname, "..", "products.yaml"),
|
|
119
|
+
join(process.cwd(), "products.yaml")
|
|
120
|
+
];
|
|
121
|
+
for (const p of candidates) {
|
|
122
|
+
try {
|
|
123
|
+
readFileSync(p);
|
|
124
|
+
return p;
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return candidates[0];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export {
|
|
132
|
+
loadProductsConfig
|
|
133
|
+
};
|