@bridge-ds/mcp 0.11.0 → 0.11.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.
|
@@ -559,7 +559,7 @@ function productOfRepo(products, repo, designSystemRepo) {
|
|
|
559
559
|
}
|
|
560
560
|
var KEY = /^[a-z0-9][a-z0-9-]*$/;
|
|
561
561
|
var REPO = /^[\w.-]+\/[\w.-]+$/;
|
|
562
|
-
var FIELDS = ["key", "name", "repo", "path", "preview", "framework", "default"];
|
|
562
|
+
var FIELDS = ["key", "name", "repo", "path", "preview", "production", "framework", "default"];
|
|
563
563
|
function productProblems(raw) {
|
|
564
564
|
if (raw === void 0) return [];
|
|
565
565
|
if (!Array.isArray(raw)) return ['"products" must be a list of { "key", "name" } objects'];
|
|
@@ -585,6 +585,7 @@ function productProblems(raw) {
|
|
|
585
585
|
if (bad) problems.push(`${at}.path" must be a folder relative to the repository root, without a leading "/" or "..", such as "apps/admin"`);
|
|
586
586
|
}
|
|
587
587
|
if (o.preview !== void 0 && (typeof o.preview !== "string" || !/^https?:\/\//.test(o.preview))) problems.push(`${at}.preview" must be an http(s) URL template, such as "https://app-git-{branch}.vercel.app"`);
|
|
588
|
+
if (o.production !== void 0 && (typeof o.production !== "string" || !/^https?:\/\/[^{}\s]+$/.test(o.production))) problems.push(`${at}.production" must be the product's production URL, without placeholders, such as "https://shop.example.com"`);
|
|
588
589
|
if (o.framework !== void 0 && (typeof o.framework !== "string" || !o.framework.trim())) problems.push(`${at}.framework" must be a name such as "react", "vue" or "other"`);
|
|
589
590
|
if (o.default !== void 0 && typeof o.default !== "boolean") problems.push(`${at}.default" must be true or false`);
|
|
590
591
|
if (o.default === true) defaults++;
|
|
@@ -89,7 +89,7 @@ import {
|
|
|
89
89
|
validateLayered,
|
|
90
90
|
variantKeyOf,
|
|
91
91
|
whoCanShipSentence
|
|
92
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-HNGVASTJ.js";
|
|
93
93
|
|
|
94
94
|
// src/lib.ts
|
|
95
95
|
import { execFileSync } from "node:child_process";
|
|
@@ -4018,13 +4018,21 @@ var labelNames = (labels) => labels.map((l) => typeof l === "string" ? l : l.nam
|
|
|
4018
4018
|
function isExplorationPull(p) {
|
|
4019
4019
|
return isExplorationBranch(p.headRef) || labelNames(p.labels).includes(EXPLORATION_LABEL) || Boolean(parseExplorationBody(p.body));
|
|
4020
4020
|
}
|
|
4021
|
+
function isUnlabeledExploration(p) {
|
|
4022
|
+
if (p.state !== "open" || p.draft !== true) return false;
|
|
4023
|
+
const names4 = labelNames(p.labels ?? []);
|
|
4024
|
+
if (names4.includes(EXPLORATION_LABEL) || names4.includes(EXPLORATION_ARCHIVED_LABEL) || names4.includes(EXPLORATION_READY_LABEL)) return false;
|
|
4025
|
+
const block = parseExplorationBody(p.body);
|
|
4026
|
+
if (block?.doneAt) return false;
|
|
4027
|
+
return isExplorationBranch(p.headRef) || Boolean(block);
|
|
4028
|
+
}
|
|
4021
4029
|
function isHandedOff(p) {
|
|
4022
4030
|
return labelNames(p.labels).includes(EXPLORATION_READY_LABEL) || Boolean(parseExplorationBody(p.body)?.doneAt);
|
|
4023
4031
|
}
|
|
4024
4032
|
function explorationStatus(p) {
|
|
4025
4033
|
const merged = Boolean(p.merged || p.merged_at || p.state === "merged");
|
|
4026
4034
|
if (p.state !== "open" && !merged) return "closed";
|
|
4027
|
-
if (p.state === "open" && labelNames(p.labels).includes(EXPLORATION_LABEL)) return "active";
|
|
4035
|
+
if (p.state === "open" && (labelNames(p.labels).includes(EXPLORATION_LABEL) || isUnlabeledExploration(p))) return "active";
|
|
4028
4036
|
if (!isHandedOff(p)) return "promoted";
|
|
4029
4037
|
if (merged) return "shipped";
|
|
4030
4038
|
if (p.draft === false) return "building";
|
|
@@ -4038,6 +4046,7 @@ function isHeldExploration(p) {
|
|
|
4038
4046
|
if (p.state !== void 0 && p.state !== "open") return false;
|
|
4039
4047
|
const names4 = labelNames(p.labels ?? []);
|
|
4040
4048
|
if (names4.includes(EXPLORATION_LABEL) || names4.includes(EXPLORATION_ARCHIVED_LABEL)) return true;
|
|
4049
|
+
if (isUnlabeledExploration({ state: "open", draft: p.draft, labels: p.labels, headRef: p.headRef ?? p.head?.ref, body: p.body })) return true;
|
|
4041
4050
|
return names4.includes(EXPLORATION_READY_LABEL) && p.draft !== false;
|
|
4042
4051
|
}
|
|
4043
4052
|
var explorationTakeCommands = (branch) => ["git fetch origin", `git checkout ${branch}`];
|
|
@@ -4570,7 +4579,7 @@ async function startExplorationOnGitHub(gh, e, s) {
|
|
|
4570
4579
|
const ctx = { owner: gh.owner, repo: gh.name, packages: s.packages, apps: s.apps, ...s.requests?.length ? { requests: s.requests } : {}, ...s.inProduct ? { inProduct: s.inProduct } : {} };
|
|
4571
4580
|
const title = full.jira ? `${full.jira.trim().toUpperCase()} ${explorationPrTitle(full)}` : explorationPrTitle(full);
|
|
4572
4581
|
const pr = await x.createPullRequest({ title, head: branch, base: s.base, body: explorationPrBody(full, ctx), draft: true });
|
|
4573
|
-
await x
|
|
4582
|
+
const labelsMissing = await labelExploration(x, pr.number, s.labels ?? [], s.retryMs);
|
|
4574
4583
|
await x.updatePullRequest(pr.number, { body: explorationPrBody(full, { ...ctx, pr: pr.number }) }).catch(() => void 0);
|
|
4575
4584
|
return {
|
|
4576
4585
|
branch,
|
|
@@ -4579,9 +4588,21 @@ async function startExplorationOnGitHub(gh, e, s) {
|
|
|
4579
4588
|
url: pr.url,
|
|
4580
4589
|
commit: commit.sha,
|
|
4581
4590
|
tryIt: { state: "building" },
|
|
4582
|
-
previews: previewLinks(s.apps, { branch, pr: pr.number, sha: commit.sha })
|
|
4591
|
+
previews: previewLinks(s.apps, { branch, pr: pr.number, sha: commit.sha }),
|
|
4592
|
+
...labelsMissing.length ? { labelsMissing } : {}
|
|
4583
4593
|
};
|
|
4584
4594
|
}
|
|
4595
|
+
var wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
4596
|
+
async function labelExploration(gh, pr, extra, retryMs = 600) {
|
|
4597
|
+
let labeled = false;
|
|
4598
|
+
for (let i = 0; i < 3 && !labeled; i++) {
|
|
4599
|
+
if (i) await wait(retryMs * i);
|
|
4600
|
+
labeled = await gh.addLabels(pr, [EXPLORATION_LABEL]);
|
|
4601
|
+
}
|
|
4602
|
+
const more = extra.filter((l) => l !== EXPLORATION_LABEL);
|
|
4603
|
+
const moreOk = more.length ? await gh.addLabels(pr, more) : true;
|
|
4604
|
+
return [...labeled ? [] : [EXPLORATION_LABEL], ...moreOk ? [] : more];
|
|
4605
|
+
}
|
|
4585
4606
|
async function productRepoAccess(gh) {
|
|
4586
4607
|
try {
|
|
4587
4608
|
const r = await gh.getRepo();
|
|
@@ -9858,6 +9879,7 @@ async function markFigmaChangeDraftedOnGitHub(gh, n) {
|
|
|
9858
9879
|
var BUILD_REQUEST_LABEL = "bridge-build";
|
|
9859
9880
|
var SOURCE_FIGMA_LABEL = "source: figma";
|
|
9860
9881
|
var BUILD_STALE_DAYS = 7;
|
|
9882
|
+
var BUILD_DECLINED_DAYS = 7;
|
|
9861
9883
|
var names3 = (labels) => (labels ?? []).map((l) => (typeof l === "string" ? l : l.name ?? "").toLowerCase());
|
|
9862
9884
|
function isFigmaPush(p) {
|
|
9863
9885
|
const l = names3(p.labels);
|
|
@@ -10069,7 +10091,8 @@ function buildRequestStatus(x, now = Date.now(), nameOf = (l) => l) {
|
|
|
10069
10091
|
if (s === "shipped") return { status: s, ...shippedAt ? { at: shippedAt } : {} };
|
|
10070
10092
|
return { status: s };
|
|
10071
10093
|
});
|
|
10072
|
-
|
|
10094
|
+
const closedOn = x.issue ? x.issue.closedAt : own?.closedAt ?? own?.updatedAt;
|
|
10095
|
+
if (status === "not-planned") timeline.push({ status: "not-planned", ...closedOn ? { at: closedOn } : {} });
|
|
10073
10096
|
return {
|
|
10074
10097
|
status,
|
|
10075
10098
|
label: status === "requested" && stale ? `Requested ${ageDays} days ago` : BUILD_STATUS_LABEL[status],
|
|
@@ -10147,9 +10170,10 @@ var BUILD_FILTER_LABEL = {
|
|
|
10147
10170
|
"in-progress": "In progress",
|
|
10148
10171
|
"shipped-this-week": "Shipped this week"
|
|
10149
10172
|
};
|
|
10173
|
+
var declinedAt = (v) => v.status === "not-planned" ? v.timeline.find((e) => e.status === "not-planned")?.at ?? null : null;
|
|
10150
10174
|
function matchesBuildFilter(v, f, now = Date.now()) {
|
|
10151
10175
|
const nowMs = typeof now === "number" ? now : now.getTime();
|
|
10152
|
-
const recent = (iso) => Boolean(iso) && nowMs - Date.parse(iso) <=
|
|
10176
|
+
const recent = (iso, days = 7) => Boolean(iso) && nowMs - Date.parse(iso) <= days * DAY;
|
|
10153
10177
|
switch (f) {
|
|
10154
10178
|
case "waiting":
|
|
10155
10179
|
return v.status === "requested";
|
|
@@ -10158,7 +10182,7 @@ function matchesBuildFilter(v, f, now = Date.now()) {
|
|
|
10158
10182
|
case "shipped-this-week":
|
|
10159
10183
|
return v.status === "shipped" && recent(v.shippedAt);
|
|
10160
10184
|
default:
|
|
10161
|
-
return v.status === "not-planned" ? recent(v
|
|
10185
|
+
return v.status === "not-planned" ? recent(declinedAt(v), BUILD_DECLINED_DAYS) : true;
|
|
10162
10186
|
}
|
|
10163
10187
|
}
|
|
10164
10188
|
var openBuildRequests = (views) => views.filter((v) => v.status !== "shipped" && v.status !== "not-planned");
|
|
@@ -15731,7 +15755,7 @@ async function visualImpact(ctx, a, run2) {
|
|
|
15731
15755
|
if (ctx.mode !== "local" || !ctx.root) throw new Error("Visual impact needs a local checkout (start Bridge with --root): it builds Storybook and the app at both refs.");
|
|
15732
15756
|
if (!ctx.isGit) throw new Error(`${ctx.root} is not a git repository.`);
|
|
15733
15757
|
const out = a.out ? resolve3(ctx.root, a.out) : join5(ctx.root, "visual-impact");
|
|
15734
|
-
const runImpact = run2 ?? (await import("./src-
|
|
15758
|
+
const runImpact = run2 ?? (await import("./src-P42KWNHQ.js")).runImpact;
|
|
15735
15759
|
const r = await runImpact({
|
|
15736
15760
|
root: ctx.root,
|
|
15737
15761
|
base: a.base ?? "main",
|
|
@@ -17130,7 +17154,7 @@ async function proposeFigmaFixesOp(ctx, a) {
|
|
|
17130
17154
|
}
|
|
17131
17155
|
|
|
17132
17156
|
// src/server.ts
|
|
17133
|
-
var VERSION = true ? "0.11.
|
|
17157
|
+
var VERSION = true ? "0.11.2" : "dev";
|
|
17134
17158
|
var BRIDGE_SITE = "https://bridge.floriangouloubi.com";
|
|
17135
17159
|
var SERVER_INFO = {
|
|
17136
17160
|
name: "bridge",
|
package/dist/index.js
CHANGED
package/dist/lib.js
CHANGED
|
@@ -42,12 +42,12 @@ import {
|
|
|
42
42
|
studio_exports,
|
|
43
43
|
suggestions_exports,
|
|
44
44
|
tokenNote
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-P2UU6IKZ.js";
|
|
46
46
|
import {
|
|
47
47
|
CONFIG_FILE,
|
|
48
48
|
loadConfig,
|
|
49
49
|
toConfigJson
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-HNGVASTJ.js";
|
|
51
51
|
export {
|
|
52
52
|
BlockedError,
|
|
53
53
|
BridgeContext,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bridge-ds/mcp",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Bridge MCP server: lets Claude (Claude Code, Claude Desktop or any MCP client) read, check and propose changes to a DTCG design system repo through pull requests.",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"build:package": "node ../../scripts/build-packages.mjs mcp"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@bridge-ds/core": "^0.
|
|
59
|
-
"@bridge-ds/visual": "^0.3.
|
|
58
|
+
"@bridge-ds/core": "^0.23.0",
|
|
59
|
+
"@bridge-ds/visual": "^0.3.17",
|
|
60
60
|
"@modelcontextprotocol/sdk": "1.31.0",
|
|
61
61
|
"typescript": "5.9.3",
|
|
62
62
|
"zod": "3.25.76"
|