@usercase/mcp 0.2.8-next.5 → 0.2.8
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/agents/new-research.md +1 -1
- package/mcp/server.js +22 -1
- package/package.json +1 -1
package/agents/new-research.md
CHANGED
|
@@ -70,7 +70,7 @@ One research is **one flow a participant can walk in one sitting**: 1–4 tasks,
|
|
|
70
70
|
The results tell who went straight from who took a detour only when a task has an expected path: the route the site was built for. Work it out now, from the code, for every task with a page or click to reach (tasks done by staying on a page have none):
|
|
71
71
|
- **where it starts**: the first task starts on the invite page; every later task starts where the previous one ended;
|
|
72
72
|
- **the clicks a participant must make**, in order — the main route the UI offers, not a shortcut only you know;
|
|
73
|
-
- **where it ends**: the page or the click that counts as done. It must agree with the task's success condition.
|
|
73
|
+
- **where it ends**: the page or the click that counts as done. It must agree with the task's success condition. When participants could reach any item of a kind (a project, a post, a product), the task's page is the route's pattern with `:name` for that part — never the item you happened to open — and while recording, `path_pattern` turns that page into the same pattern.
|
|
74
74
|
- what the route needs: a signed-in demo account, or a write the safety guard does not send (the last click is then recorded without pressing it).
|
|
75
75
|
|
|
76
76
|
## 7. Show the user everything at once
|
package/mcp/server.js
CHANGED
|
@@ -23,7 +23,7 @@ const ws = require("./workspace.js");
|
|
|
23
23
|
const persona = require("../src/persona/persona.js");
|
|
24
24
|
const report = require("./report.js");
|
|
25
25
|
const peopleRules = require("../src/persona/people.js");
|
|
26
|
-
const { PathRecorder } = require("./path.js");
|
|
26
|
+
const { PathRecorder, patternOf } = require("./path.js");
|
|
27
27
|
|
|
28
28
|
const hub = new Hub();
|
|
29
29
|
const server = new McpServer({ name: "usercase", version: require("../package.json").version });
|
|
@@ -715,7 +715,27 @@ server.registerTool(
|
|
|
715
715
|
wrap(async (args) => {
|
|
716
716
|
// 참여자는 초대를 수락한 페이지에서 첫 과제를 시작한다(SDK 는 다른 데로 데려가지 않는다).
|
|
717
717
|
// 첫 과제 경로가 다른 페이지에서 시작하면 첫 단계를 아무도 못 지난다 — 저장 전에 막는다. :이름 은 이름과 상관없이 같은 칸
|
|
718
|
+
// 녹화는 걸은 주소 그대로(/project/zksync)다. 과제에 적은 패턴(/project/:slug)에 맞는 주소는 그 패턴으로 —
|
|
719
|
+
// 안 그러면 그 항목을 고른 사람만 성공·바로 감으로 잡힌다(10/29 bluetags). 에이전트가 path_pattern 을 빠뜨려도 여기서 맞춘다
|
|
720
|
+
const toPattern = (body, pat) => {
|
|
721
|
+
if (!pat || !pat.includes(":")) return false;
|
|
722
|
+
const re = patternOf(pat);
|
|
723
|
+
const fit = (u) => u && u !== pat && !u.includes(":") && re.test(u);
|
|
724
|
+
let hit = false;
|
|
725
|
+
for (const s of body.steps) if (fit(s.url)) (s.url = pat), (hit = true);
|
|
726
|
+
const sc = body.success;
|
|
727
|
+
if (sc && fit(sc.targetUrl)) (sc.targetUrl = pat), (hit = true);
|
|
728
|
+
if (sc && fit(sc.xpathUrl)) (sc.xpathUrl = pat), (hit = true);
|
|
729
|
+
return hit;
|
|
730
|
+
};
|
|
731
|
+
const patternNotes = [];
|
|
732
|
+
for (const [n, p] of recorder.planned) {
|
|
733
|
+
const t = (args.tasks || [])[n - 1];
|
|
734
|
+
const pat = t && (t.success_condition === "element_click" ? t.xpath_url : t.target_url);
|
|
735
|
+
if (t && toPattern(p.body, pat)) patternNotes.push(`- task ${n}: recorded pages matching ${pat} now use that pattern`);
|
|
736
|
+
}
|
|
718
737
|
const first = recorder.planned.get(1);
|
|
738
|
+
if (args.invite && first && toPattern(first.body, args.invite.page)) patternNotes.push(`- task 1: its start page now uses the invite's pattern ${args.invite.page}`);
|
|
719
739
|
if (args.invite && first) {
|
|
720
740
|
const kind = (p) => String(p || "").trim().replace(/:[A-Za-z_]\w*/g, ":x").replace(/\/+$/, "") || "/";
|
|
721
741
|
const start = first.body.steps[0].url;
|
|
@@ -749,6 +769,7 @@ server.registerTool(
|
|
|
749
769
|
`Saved as a draft${r.findings ? `, linked to ${r.findings} finding${r.findings > 1 ? "s" : ""}` : ""}.`,
|
|
750
770
|
`Open it in the Inbox to review and create it: ${report.dashboardUrl(r.inboxPath)}`,
|
|
751
771
|
...(lines.length ? ["", "Expected paths saved with it:", ...lines] : []),
|
|
772
|
+
...(patternNotes.length ? ["", "Item pages were recorded with the item you opened; they now match any item of that kind:", ...patternNotes] : []),
|
|
752
773
|
...(missing.length
|
|
753
774
|
? ["", "Tasks without an expected path:", ...missing.map((t) => `- ${t.title} (record later with path_start draft:${r.draftId}:${t.index})`)]
|
|
754
775
|
: []),
|
package/package.json
CHANGED