@mcptoolshop/claude-synergy 1.1.1 → 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.
@@ -1,6 +1,10 @@
1
+ import {
2
+ loadProductsConfig
3
+ } from "./chunk-MZLFGICO.js";
4
+
1
5
  // src/ingest.ts
2
- import { readdirSync, readFileSync as readFileSync2, statSync, existsSync as existsSync2 } from "fs";
3
- import { join as join2, relative, basename } from "path";
6
+ import { readdirSync, readFileSync, statSync, existsSync } from "fs";
7
+ import { join, relative, basename } from "path";
4
8
  import { createHash } from "crypto";
5
9
  import matter from "gray-matter";
6
10
  import TurndownService from "turndown";
@@ -71,136 +75,6 @@ function extractEntities(text) {
71
75
  return found;
72
76
  }
73
77
 
74
- // src/products-config.ts
75
- import { readFileSync, existsSync } from "fs";
76
- import { dirname, join } from "path";
77
- import { fileURLToPath } from "url";
78
- import { parse as parseYaml } from "yaml";
79
- var __dirname2 = dirname(fileURLToPath(import.meta.url));
80
- var PRODUCT_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
81
- var GH_REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
82
- var warnedAboutMissingYaml = false;
83
- function loadProductsConfig(yamlPath) {
84
- const resolved = yamlPath ?? resolveYamlPath();
85
- if (!resolved || !existsSync(resolved)) {
86
- if (!warnedAboutMissingYaml) {
87
- console.error(`[claude-synergy] products.yaml not found at ${resolved}; using hardcoded defaults`);
88
- warnedAboutMissingYaml = true;
89
- }
90
- return null;
91
- }
92
- let raw;
93
- try {
94
- raw = readFileSync(resolved, "utf-8");
95
- } catch (e) {
96
- console.error(`[claude-synergy] could not read ${resolved}: ${e.message}; using hardcoded defaults`);
97
- return null;
98
- }
99
- if (raw.charCodeAt(0) === 65279) raw = raw.slice(1);
100
- let parsed;
101
- try {
102
- parsed = parseYaml(raw);
103
- } catch (e) {
104
- throw new Error(`[claude-synergy] products.yaml parse error: ${e.message}`);
105
- }
106
- if (!parsed || !Array.isArray(parsed.products)) {
107
- throw new Error(`[claude-synergy] products.yaml missing required 'products' array`);
108
- }
109
- const productMeta = {};
110
- const fetchTargets = [];
111
- for (const p of parsed.products) {
112
- if (!p.name || !p.display_name) {
113
- throw new Error(`[claude-synergy] products.yaml entry missing name/display_name: ${JSON.stringify(p)}`);
114
- }
115
- if (!PRODUCT_NAME_RE.test(p.name)) {
116
- throw new Error(
117
- `[claude-synergy] products.yaml: invalid product name '${p.name}' \u2014 must match /^[a-z0-9][a-z0-9-]*$/ (lowercase alphanumeric + hyphens, no leading hyphen)`
118
- );
119
- }
120
- productMeta[p.name] = {
121
- name: p.name,
122
- display_name: p.display_name,
123
- source_tier: p.tier ?? 1,
124
- source_url: p.source_url ?? "",
125
- fetch_strategy: p.fetch_strategy ?? "gh-releases",
126
- notes: p.notes ?? null
127
- };
128
- if (p.fetch) {
129
- const target = buildFetchTarget(p.name, p.fetch);
130
- if (target) {
131
- if (target.strategy === "gh-releases" && target.repo && !GH_REPO_RE.test(target.repo)) {
132
- throw new Error(
133
- `[claude-synergy] products.yaml: ${p.name}: invalid repo '${target.repo}' \u2014 must match 'owner/repo' (alphanumeric + dot/underscore/hyphen)`
134
- );
135
- }
136
- fetchTargets.push(target);
137
- }
138
- }
139
- }
140
- return { productMeta, fetchTargets };
141
- }
142
- function buildFetchTarget(name, fetch) {
143
- if (!fetch) return null;
144
- const target = { product: name, strategy: fetch.type };
145
- switch (fetch.type) {
146
- case "gh-releases":
147
- if (!fetch.repo) throw new Error(`[claude-synergy] ${name}: gh-releases requires 'repo'`);
148
- target.repo = fetch.repo;
149
- if (fetch.multi_package) target.multiPackage = true;
150
- break;
151
- case "rss":
152
- if (!fetch.url) throw new Error(`[claude-synergy] ${name}: rss requires 'url'`);
153
- target.rssUrl = fetch.url;
154
- if (fetch.title_filter) {
155
- try {
156
- target.rssTitleFilter = new RegExp(fetch.title_filter, "i");
157
- } catch (e) {
158
- throw new Error(`[claude-synergy] ${name}: invalid rss title_filter regex: ${e.message}`);
159
- }
160
- }
161
- break;
162
- case "raw-changelog":
163
- if (!fetch.url) throw new Error(`[claude-synergy] ${name}: raw-changelog requires 'url'`);
164
- if (!fetch.parser) throw new Error(`[claude-synergy] ${name}: raw-changelog requires 'parser'`);
165
- if (fetch.parser !== "aider-history" && fetch.parser !== "keep-a-changelog") {
166
- throw new Error(
167
- `[claude-synergy] ${name}: raw-changelog 'parser' must be one of: aider-history, keep-a-changelog (got '${fetch.parser}')`
168
- );
169
- }
170
- target.rawChangelogUrl = fetch.url;
171
- target.rawChangelogParser = fetch.parser;
172
- break;
173
- case "html-scrape":
174
- if (!fetch.parser) throw new Error(`[claude-synergy] ${name}: html-scrape requires 'parser'`);
175
- target.htmlParser = fetch.parser;
176
- break;
177
- case "catalog":
178
- if (!fetch.catalog_type) throw new Error(`[claude-synergy] ${name}: catalog requires 'catalog_type'`);
179
- target.catalogType = fetch.catalog_type;
180
- if (fetch.max_entries) target.catalogMaxEntries = fetch.max_entries;
181
- break;
182
- case "playwright":
183
- break;
184
- default:
185
- throw new Error(`[claude-synergy] ${name}: unknown fetch type ${fetch.type}`);
186
- }
187
- return target;
188
- }
189
- function resolveYamlPath() {
190
- const candidates = [
191
- join(__dirname2, "..", "products.yaml"),
192
- join(process.cwd(), "products.yaml")
193
- ];
194
- for (const p of candidates) {
195
- try {
196
- readFileSync(p);
197
- return p;
198
- } catch {
199
- }
200
- }
201
- return candidates[0];
202
- }
203
-
204
78
  // src/ingest.ts
205
79
  var turndown = new TurndownService({
206
80
  headingStyle: "atx",
@@ -316,14 +190,20 @@ function ingestAll(db, productsRoot) {
316
190
  };
317
191
  const productDirs = readdirSync(productsRoot).filter((name) => {
318
192
  try {
319
- return statSync(join2(productsRoot, name)).isDirectory();
193
+ return statSync(join(productsRoot, name)).isDirectory();
320
194
  } catch {
321
195
  return false;
322
196
  }
323
197
  });
324
198
  const insertProduct = db.prepare(`
325
- INSERT OR REPLACE INTO products (name, display_name, source_tier, source_url, fetch_strategy, notes)
199
+ INSERT INTO products (name, display_name, source_tier, source_url, fetch_strategy, notes)
326
200
  VALUES (@name, @display_name, @source_tier, @source_url, @fetch_strategy, @notes)
201
+ ON CONFLICT(name) DO UPDATE SET
202
+ display_name = excluded.display_name,
203
+ source_tier = excluded.source_tier,
204
+ source_url = excluded.source_url,
205
+ fetch_strategy = excluded.fetch_strategy,
206
+ notes = excluded.notes
327
207
  `);
328
208
  const insertRelease = db.prepare(`
329
209
  INSERT OR REPLACE INTO releases (product, version, released_at, notes_path, fetched_at, source_url, bundle_size_kb, notes_hash)
@@ -342,8 +222,8 @@ function ingestAll(db, productsRoot) {
342
222
  VALUES (?, ?, ?)
343
223
  `);
344
224
  for (const product of productDirs) {
345
- const releasesDir = join2(productsRoot, product, "releases");
346
- if (!existsSync2(releasesDir)) {
225
+ const releasesDir = join(productsRoot, product, "releases");
226
+ if (!existsSync(releasesDir)) {
347
227
  continue;
348
228
  }
349
229
  let releaseFiles;
@@ -374,8 +254,8 @@ function ingestAll(db, productsRoot) {
374
254
  for (const file of releaseFiles) {
375
255
  try {
376
256
  stats.total++;
377
- const path = join2(releasesDir, file);
378
- const raw = readFileSync2(path, "utf-8");
257
+ const path = join(releasesDir, file);
258
+ const raw = readFileSync(path, "utf-8");
379
259
  const { data: fm, content } = matter(raw);
380
260
  const fmTyped = fm;
381
261
  const baseVersion = fmTyped.version ?? basename(file, ".md");
@@ -548,7 +428,7 @@ function ingestSynergies(db, synergyDir) {
548
428
  changeRefsAdded: 0,
549
429
  errors: []
550
430
  };
551
- if (!existsSync2(synergyDir)) {
431
+ if (!existsSync(synergyDir)) {
552
432
  return stats;
553
433
  }
554
434
  let files;
@@ -611,8 +491,8 @@ function ingestSynergies(db, synergyDir) {
611
491
  const tx = db.transaction(() => {
612
492
  for (const file of files) {
613
493
  try {
614
- const path = join2(synergyDir, file);
615
- const raw = readFileSync2(path, "utf-8");
494
+ const path = join(synergyDir, file);
495
+ const raw = readFileSync(path, "utf-8");
616
496
  const parsed = matter(raw);
617
497
  const fm = parsed.data;
618
498
  const body = parsed.content;
@@ -743,7 +623,6 @@ function ingestSynergies(db, synergyDir) {
743
623
  }
744
624
 
745
625
  export {
746
- loadProductsConfig,
747
626
  ingestAll,
748
627
  ingestSynergies
749
628
  };