cbrowser 18.75.1 → 18.75.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/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +87 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/values-tools.js +3 -2
- package/dist/mcp-tools/base/values-tools.js.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.js +49 -0
- package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
- package/dist/persona-questionnaire.d.ts +14 -1
- package/dist/persona-questionnaire.d.ts.map +1 -1
- package/dist/persona-questionnaire.js +74 -0
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/visual/cross-browser.d.ts.map +1 -1
- package/dist/visual/cross-browser.js +9 -1
- package/dist/visual/cross-browser.js.map +1 -1
- package/dist/visual/distance-metrics.d.ts +23 -0
- package/dist/visual/distance-metrics.d.ts.map +1 -1
- package/dist/visual/distance-metrics.js +16 -0
- package/dist/visual/distance-metrics.js.map +1 -1
- package/package.json +1 -1
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAo0IpE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAE1D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAWvE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAWpD"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* Or: npx cbrowser mcp-server
|
|
13
13
|
*/
|
|
14
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
import { PERSONA_CATEGORIES } from "./persona-questionnaire.js";
|
|
15
16
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
16
17
|
import { z } from "zod";
|
|
17
18
|
import { CBrowser } from "./browser.js";
|
|
@@ -230,6 +231,33 @@ const VALUES_QUESTIONS = [
|
|
|
230
231
|
},
|
|
231
232
|
];
|
|
232
233
|
const questionnaireSessionsMap = new Map();
|
|
234
|
+
/**
|
|
235
|
+
* Group a flat Schwartz/SDT value record into the nested schema every other
|
|
236
|
+
* values-returning path uses (schwartz / higherOrder / sdt / maslowLevel).
|
|
237
|
+
*
|
|
238
|
+
* persona_questionnaire_build emitted `values` FLAT, with Schwartz and SDT
|
|
239
|
+
* merged and no higherOrder grouping — so the C4b nested-schema fix never
|
|
240
|
+
* reached the creation path, and a persona built through the questionnaire had
|
|
241
|
+
* a different value shape from the same persona loaded back. Three sites
|
|
242
|
+
* already hand-write this grouping; this is the shared one. (2026-07-29)
|
|
243
|
+
*/
|
|
244
|
+
function nestPersonaValues(values) {
|
|
245
|
+
if (!values)
|
|
246
|
+
return undefined;
|
|
247
|
+
const pick = (...keys) => {
|
|
248
|
+
const out = {};
|
|
249
|
+
for (const k of keys)
|
|
250
|
+
if (values[k] !== undefined)
|
|
251
|
+
out[k] = values[k];
|
|
252
|
+
return out;
|
|
253
|
+
};
|
|
254
|
+
return {
|
|
255
|
+
schwartz: pick("selfDirection", "stimulation", "hedonism", "achievement", "power", "security", "conformity", "tradition", "benevolence", "universalism"),
|
|
256
|
+
higherOrder: pick("openness", "selfEnhancement", "conservation", "selfTranscendence"),
|
|
257
|
+
sdt: pick("autonomyNeed", "competenceNeed", "relatednessNeed"),
|
|
258
|
+
maslowLevel: values.maslowLevel,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
233
261
|
function getQuestionnaireSession(sessionId) {
|
|
234
262
|
return questionnaireSessionsMap.get(sessionId);
|
|
235
263
|
}
|
|
@@ -942,6 +970,37 @@ async function registerCBrowserTools() {
|
|
|
942
970
|
url: result.url,
|
|
943
971
|
overallStatus: result.overallStatus,
|
|
944
972
|
summary: result.summary,
|
|
973
|
+
// The evidence used to be collapsed to two integers —
|
|
974
|
+
// screenshotCount / comparisonCount — while `result` carried every
|
|
975
|
+
// screenshot path, every pairwise similarity score, and
|
|
976
|
+
// problematicBrowsers. So the caller received an absolute verdict
|
|
977
|
+
// ("renders consistently across all tested browsers") with every
|
|
978
|
+
// number that could falsify it removed, and no way to open the
|
|
979
|
+
// screenshots it said it had taken.
|
|
980
|
+
//
|
|
981
|
+
// It also explains the contradiction with cross_browser_diff: this
|
|
982
|
+
// tool compares ABOVE-THE-FOLD PIXELS at a forced 1920x1080, while
|
|
983
|
+
// the diff compares FULL-PAGE TEXT at 1280x720. Two different
|
|
984
|
+
// measurements reported in language that claims to settle the same
|
|
985
|
+
// question. `scope` now says which one you are reading.
|
|
986
|
+
// (2026-07-29)
|
|
987
|
+
scope: "above-the-fold pixels at 1920x1080; page TEXT is not compared — use cross_browser_diff for content",
|
|
988
|
+
screenshots: result.screenshots.map((s) => ({
|
|
989
|
+
browser: s.browser,
|
|
990
|
+
path: s.screenshotPath,
|
|
991
|
+
viewport: s.viewport,
|
|
992
|
+
})),
|
|
993
|
+
comparisons: result.comparisons.map((c) => ({
|
|
994
|
+
browserA: c.browserA,
|
|
995
|
+
browserB: c.browserB,
|
|
996
|
+
status: c.analysis?.overallStatus,
|
|
997
|
+
similarity: c.analysis?.similarityScore,
|
|
998
|
+
changes: (c.analysis?.changes ?? []).map((ch) => ({
|
|
999
|
+
severity: ch.severity,
|
|
1000
|
+
description: ch.description,
|
|
1001
|
+
})),
|
|
1002
|
+
})),
|
|
1003
|
+
...(result.problematicBrowsers?.length ? { problematicBrowsers: result.problematicBrowsers } : {}),
|
|
945
1004
|
screenshotCount: result.screenshots.length,
|
|
946
1005
|
comparisonCount: result.comparisons.length,
|
|
947
1006
|
...(result.missingBrowsers?.length ? { missingBrowsers: result.missingBrowsers } : {}),
|
|
@@ -987,6 +1046,24 @@ async function registerCBrowserTools() {
|
|
|
987
1046
|
url: result.url,
|
|
988
1047
|
overallStatus: result.overallStatus,
|
|
989
1048
|
summary: result.summary,
|
|
1049
|
+
// `result.issues` and `problematicViewports` were both computed and
|
|
1050
|
+
// then dropped here, so the caller got "13 issues: 7 overflow, 2
|
|
1051
|
+
// unreadable text..." with no way to learn WHICH viewport or WHICH
|
|
1052
|
+
// element — a count they could not act on. Same computed-then-
|
|
1053
|
+
// discarded shape as the cross-browser handler above. (2026-07-29)
|
|
1054
|
+
issues: (result.issues ?? []).map((i) => ({
|
|
1055
|
+
type: i.type,
|
|
1056
|
+
severity: i.severity,
|
|
1057
|
+
description: i.description,
|
|
1058
|
+
affectedViewports: i.affectedViewports,
|
|
1059
|
+
...(i.breakpointRange ? { breakpointRange: i.breakpointRange } : {}),
|
|
1060
|
+
})),
|
|
1061
|
+
...(result.problematicViewports?.length ? { problematicViewports: result.problematicViewports } : {}),
|
|
1062
|
+
viewports: result.screenshots.map((s) => ({
|
|
1063
|
+
name: s.viewport
|
|
1064
|
+
?? s.name,
|
|
1065
|
+
path: s.screenshotPath,
|
|
1066
|
+
})),
|
|
990
1067
|
viewportsCount: result.screenshots.length,
|
|
991
1068
|
}, null, 2),
|
|
992
1069
|
},
|
|
@@ -1953,7 +2030,7 @@ This ensures personas are grounded in research, not stereotypes.
|
|
|
1953
2030
|
};
|
|
1954
2031
|
});
|
|
1955
2032
|
server.tool("persona_category_guidance", "Get research-based guidance for a specific persona category. Explains what values are appropriate and why, with citations. Use before building a persona to understand category constraints.", {
|
|
1956
|
-
category: z.enum(
|
|
2033
|
+
category: z.enum(PERSONA_CATEGORIES).describe("Persona category to get guidance for"),
|
|
1957
2034
|
}, async ({ category }) => {
|
|
1958
2035
|
const { getCategoryValuePreset, COGNITIVE_SUBTYPES, } = await import("./persona-questionnaire.js");
|
|
1959
2036
|
const preset = getCategoryValuePreset(category);
|
|
@@ -1983,6 +2060,11 @@ This ensures personas are grounded in research, not stereotypes.
|
|
|
1983
2060
|
sensory: "Use neutral (0.5) values. Sensory perception ≠ motivational psychology. Color-blindness doesn't make someone more/less achievement-oriented.",
|
|
1984
2061
|
emotional: "Apply trait-based values from personality psychology (e.g., anxiety = high security-seeking).",
|
|
1985
2062
|
general: "Use population baselines. Specific characteristics come from cognitive traits, not disability-based value shifts.",
|
|
2063
|
+
// Added 2026-07-29: this table covered five of the six
|
|
2064
|
+
// categories, and TypeScript flagged it the moment the enum
|
|
2065
|
+
// stopped silently excluding "agent". An unlisted key would have
|
|
2066
|
+
// yielded `undefined` guidance beside a populated preset.
|
|
2067
|
+
agent: "Agent personas are not human — motivational values do not apply. Use trait-based capability values (parsing, retrieval, tool use) and do NOT project human needs like security or belonging onto them.",
|
|
1986
2068
|
}[category],
|
|
1987
2069
|
}, null, 2),
|
|
1988
2070
|
},
|
|
@@ -1993,7 +2075,7 @@ This ensures personas are grounded in research, not stereotypes.
|
|
|
1993
2075
|
name: z.string().describe("Name for the new persona"),
|
|
1994
2076
|
description: z.string().describe("Description of the persona"),
|
|
1995
2077
|
answers: z.record(z.string(), z.number()).describe("Map of trait names to values (0-1), e.g. {patience: 0.25, riskTolerance: 0.75}"),
|
|
1996
|
-
category: z.enum(
|
|
2078
|
+
category: z.enum(PERSONA_CATEGORIES).optional().describe("Persona category for value safeguards. Auto-detected from name/description if not provided."),
|
|
1997
2079
|
valueOverrides: z.record(z.string(), z.number()).optional().describe("Override specific Schwartz values (0-1), e.g. {security: 0.8, stimulation: 0.3}"),
|
|
1998
2080
|
save: z.boolean().optional().default(true).describe("Save the persona to disk for future use"),
|
|
1999
2081
|
}, async ({ name, description, answers, category, valueOverrides, save }) => {
|
|
@@ -2047,7 +2129,10 @@ This ensures personas are grounded in research, not stereotypes.
|
|
|
2047
2129
|
strategy: categoryResult.valueStrategy,
|
|
2048
2130
|
guidance: categoryResult.guidance,
|
|
2049
2131
|
},
|
|
2132
|
+
// Flat shape retained for callers that already read it; the nested
|
|
2133
|
+
// grouping is what every other values-returning path emits.
|
|
2050
2134
|
values: categoryResult.values,
|
|
2135
|
+
valuesNested: nestPersonaValues(categoryResult.values),
|
|
2051
2136
|
researchBasis: subtypeValues
|
|
2052
2137
|
? [...categoryResult.researchBasis, subtypeValues.researchBasis]
|
|
2053
2138
|
: categoryResult.researchBasis,
|