unity-open-mcp 1.4.0 → 1.6.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/dist/capabilities/cost-hints.js +73 -0
- package/dist/capabilities/cost-hints.js.map +1 -1
- package/dist/capabilities/intent-groups.js +76 -4
- package/dist/capabilities/intent-groups.js.map +1 -1
- package/dist/capabilities/lifecycle.js +9 -0
- package/dist/capabilities/lifecycle.js.map +1 -1
- package/dist/capabilities/tool-groups.js +75 -17
- package/dist/capabilities/tool-groups.js.map +1 -1
- package/dist/compressible-router.d.ts +4 -1
- package/dist/compressible-router.js +27 -11
- package/dist/compressible-router.js.map +1 -1
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +2 -2
- package/dist/event-stream.d.ts +10 -0
- package/dist/event-stream.js +29 -0
- package/dist/event-stream.js.map +1 -1
- package/dist/game-view-settle.d.ts +18 -0
- package/dist/game-view-settle.js +81 -0
- package/dist/game-view-settle.js.map +1 -0
- package/dist/jobs/adapters.d.ts +59 -0
- package/dist/jobs/adapters.js +226 -0
- package/dist/jobs/adapters.js.map +1 -1
- package/dist/live-client.d.ts +17 -60
- package/dist/live-client.js +52 -87
- package/dist/live-client.js.map +1 -1
- package/dist/local-tools.js +3 -0
- package/dist/local-tools.js.map +1 -1
- package/dist/offline/api.d.ts +2 -0
- package/dist/offline/api.js +4 -2
- package/dist/offline/api.js.map +1 -1
- package/dist/offline/model.js +1 -1
- package/dist/offline/model.js.map +1 -1
- package/dist/offline/parse.d.ts +1 -1
- package/dist/offline/parse.js +20 -8
- package/dist/offline/parse.js.map +1 -1
- package/dist/playmode-routes.d.ts +17 -0
- package/dist/playmode-routes.js +50 -0
- package/dist/playmode-routes.js.map +1 -0
- package/dist/playtest/png.d.ts +27 -0
- package/dist/playtest/png.js +248 -0
- package/dist/playtest/png.js.map +1 -0
- package/dist/playtest/recorder.d.ts +203 -0
- package/dist/playtest/recorder.js +945 -0
- package/dist/playtest/recorder.js.map +1 -0
- package/dist/playtest/redact.d.ts +16 -0
- package/dist/playtest/redact.js +124 -0
- package/dist/playtest/redact.js.map +1 -0
- package/dist/playtest/report.d.ts +73 -0
- package/dist/playtest/report.js +477 -0
- package/dist/playtest/report.js.map +1 -0
- package/dist/playtest/session-store.d.ts +78 -0
- package/dist/playtest/session-store.js +224 -0
- package/dist/playtest/session-store.js.map +1 -0
- package/dist/skill/SKILL.md +22 -3
- package/dist/skill/references/senses-and-tests.md +3 -0
- package/dist/skill/references/yaml-and-offline-work.md +1 -1
- package/dist/tool-router.d.ts +44 -0
- package/dist/tool-router.js +249 -7
- package/dist/tool-router.js.map +1 -1
- package/dist/tools/batch-execute.js +5 -1
- package/dist/tools/batch-execute.js.map +1 -1
- package/dist/tools/capture-inline.js +30 -12
- package/dist/tools/capture-inline.js.map +1 -1
- package/dist/tools/capture-series.d.ts +46 -0
- package/dist/tools/capture-series.js +116 -0
- package/dist/tools/capture-series.js.map +1 -0
- package/dist/tools/game-view.d.ts +44 -0
- package/dist/tools/game-view.js +103 -0
- package/dist/tools/game-view.js.map +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +34 -7
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inputsim-gesture.d.ts +46 -0
- package/dist/tools/inputsim-gesture.js +123 -0
- package/dist/tools/inputsim-gesture.js.map +1 -0
- package/dist/tools/inputsim-pointer.js +35 -2
- package/dist/tools/inputsim-pointer.js.map +1 -1
- package/dist/tools/inputsim-touch.js +42 -22
- package/dist/tools/inputsim-touch.js.map +1 -1
- package/dist/tools/jobs.js +1 -1
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/player-state.d.ts +42 -0
- package/dist/tools/player-state.js +142 -0
- package/dist/tools/player-state.js.map +1 -0
- package/dist/tools/playtest-conditions.d.ts +334 -0
- package/dist/tools/playtest-conditions.js +99 -0
- package/dist/tools/playtest-conditions.js.map +1 -0
- package/dist/tools/playtest-session.d.ts +45 -0
- package/dist/tools/playtest-session.js +105 -0
- package/dist/tools/playtest-session.js.map +1 -0
- package/dist/tools/playtest-wait.d.ts +46 -0
- package/dist/tools/playtest-wait.js +86 -0
- package/dist/tools/playtest-wait.js.map +1 -0
- package/dist/tools/screenshot.js +31 -8
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/text-target.d.ts +22 -0
- package/dist/tools/text-target.js +39 -0
- package/dist/tools/text-target.js.map +1 -0
- package/dist/tools/ui-snapshot.d.ts +41 -0
- package/dist/tools/ui-snapshot.js +87 -0
- package/dist/tools/ui-snapshot.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
// Playtest session report — `end` turns the session log into a self-contained
|
|
2
|
+
// folder a human can open: report.md + the full frames (already linked into
|
|
3
|
+
// report/frames/ during the session) + downscaled thumbnails in report/thumbs/.
|
|
4
|
+
// Steps are the calls between two `mark`s, each with its verdict and note;
|
|
5
|
+
// every console error / exception is listed once with its first occurrence
|
|
6
|
+
// (step, call, during / after it) and stack; the player-state diff from the
|
|
7
|
+
// session's snapshot and the editor events (play mode, domain reloads) close
|
|
8
|
+
// it. Calls that were in flight when an earlier MCP server process stopped are
|
|
9
|
+
// reported as lost; calls of the ending process that had not returned yet, as
|
|
10
|
+
// still running at end.
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { thumbnail } from "./png.js";
|
|
14
|
+
import { REPORT_DIR, REPORT_FILE, THUMBS_DIR } from "./session-store.js";
|
|
15
|
+
const cell = (value) => value.replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
16
|
+
const code = (value) => "`" + value.replace(/`/g, "'") + "`";
|
|
17
|
+
// A code span inside a table cell: a `|` splits the row even there, so it is escaped too.
|
|
18
|
+
const cellCode = (value) => cell(code(value));
|
|
19
|
+
const clip = (value, max) => (value.length > max ? `${value.slice(0, max)}…` : value);
|
|
20
|
+
const firstLine = (value) => value.split("\n")[0].trim();
|
|
21
|
+
const shortTool = (tool) => tool.replace(/^unity_open_mcp_/, "").replace(/^unity_senses_/, "senses_");
|
|
22
|
+
const time = (isoText) => (isoText ? isoText.replace(/^.*T/, "").replace("Z", "") : "");
|
|
23
|
+
// One row per message: the event stream says Exception / Assert where a response's logs[] says error.
|
|
24
|
+
const errorKey = (e) => firstLine(String(e.message ?? "")).slice(0, 200);
|
|
25
|
+
const SPECIFIC_TYPES = new Set(["exception", "assert"]);
|
|
26
|
+
const sameMessage = (a, b) => firstLine(String(a.message ?? "")).slice(0, 200) === firstLine(String(b.message ?? "")).slice(0, 200);
|
|
27
|
+
function duration(ms) {
|
|
28
|
+
if (ms < 1000)
|
|
29
|
+
return `${Math.round(ms)} ms`;
|
|
30
|
+
if (ms < 60_000)
|
|
31
|
+
return `${(ms / 1000).toFixed(1)} s`;
|
|
32
|
+
const m = Math.floor(ms / 60_000), s = Math.round((ms % 60_000) / 1000);
|
|
33
|
+
return `${m} min ${s} s`;
|
|
34
|
+
}
|
|
35
|
+
/** Merge an attributed stream error into a call, replacing a stack-less response copy of the same message. */
|
|
36
|
+
function mergeError(list, item) {
|
|
37
|
+
const index = list.findIndex(e => sameMessage(e, item));
|
|
38
|
+
if (index < 0) {
|
|
39
|
+
list.push(item);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!list[index].stack && item.stack)
|
|
43
|
+
list[index] = { ...list[index], ...item };
|
|
44
|
+
}
|
|
45
|
+
export function writeReport(input) {
|
|
46
|
+
const { dir, meta, entries, redactor } = input;
|
|
47
|
+
const reportDir = join(dir, REPORT_DIR);
|
|
48
|
+
mkdirSync(join(reportDir, THUMBS_DIR), { recursive: true });
|
|
49
|
+
// ---- model -------------------------------------------------------------
|
|
50
|
+
const calls = new Map();
|
|
51
|
+
const started = new Map();
|
|
52
|
+
const orderedEvents = [];
|
|
53
|
+
const editorEvents = [];
|
|
54
|
+
const notes = [];
|
|
55
|
+
const looseErrors = [];
|
|
56
|
+
let endNote;
|
|
57
|
+
let running = new Set();
|
|
58
|
+
let errorRepeats = [];
|
|
59
|
+
let errorsOverLimit = 0, streamGaps = 0, firstGap;
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
switch (entry.k) {
|
|
62
|
+
case "call_started":
|
|
63
|
+
started.set(entry.seq, entry);
|
|
64
|
+
orderedEvents.push({ kind: "start", entry });
|
|
65
|
+
break;
|
|
66
|
+
case "call":
|
|
67
|
+
calls.set(entry.seq, {
|
|
68
|
+
seq: entry.seq, tool: entry.tool, kind: entry.kind, at: entry.at, duration_ms: entry.duration_ms ?? 0,
|
|
69
|
+
status: entry.status, args: entry.args ?? started.get(entry.seq)?.args, error: entry.error, summary: entry.summary,
|
|
70
|
+
captures: Array.isArray(entry.captures) ? entry.captures : [], errors: Array.isArray(entry.errors) ? [...entry.errors] : [],
|
|
71
|
+
errorsAfter: [], job_id: entry.job_id, of: entry.of, streamDown: entry.stream === false,
|
|
72
|
+
});
|
|
73
|
+
if (!started.has(entry.seq))
|
|
74
|
+
orderedEvents.push({ kind: "call", entry });
|
|
75
|
+
break;
|
|
76
|
+
case "mark":
|
|
77
|
+
orderedEvents.push({ kind: "mark", entry });
|
|
78
|
+
break;
|
|
79
|
+
case "errors":
|
|
80
|
+
for (const item of Array.isArray(entry.items) ? entry.items : []) {
|
|
81
|
+
const target = typeof item.seq === "number" ? calls.get(item.seq) : undefined;
|
|
82
|
+
if (target && item.relation === "during")
|
|
83
|
+
mergeError(target.errors, item);
|
|
84
|
+
else if (target)
|
|
85
|
+
target.errorsAfter.push(item);
|
|
86
|
+
else
|
|
87
|
+
looseErrors.push(item);
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
case "editor":
|
|
91
|
+
editorEvents.push(entry);
|
|
92
|
+
break;
|
|
93
|
+
case "stream_gap":
|
|
94
|
+
if (streamGaps++ === 0)
|
|
95
|
+
firstGap = `${entry.at} (${entry.detail})`;
|
|
96
|
+
break;
|
|
97
|
+
case "limit":
|
|
98
|
+
notes.push(String(entry.message));
|
|
99
|
+
break;
|
|
100
|
+
case "adopted":
|
|
101
|
+
notes.push(`At ${entry.at} a new MCP server process took the session over from pid ${entry.from_pid}.`);
|
|
102
|
+
break;
|
|
103
|
+
case "end_note":
|
|
104
|
+
endNote = entry.note;
|
|
105
|
+
break;
|
|
106
|
+
case "session_ended":
|
|
107
|
+
if (entry.dropped_calls)
|
|
108
|
+
notes.push(`${entry.dropped_calls} call(s) over the recording limit were not logged.`);
|
|
109
|
+
if (entry.frames_skipped)
|
|
110
|
+
notes.push(`${entry.frames_skipped} frame(s) over the frame limit were referenced, not copied.`);
|
|
111
|
+
running = new Set(Array.isArray(entry.running) ? entry.running : []);
|
|
112
|
+
errorRepeats = Array.isArray(entry.error_repeats) ? entry.error_repeats : [];
|
|
113
|
+
errorsOverLimit = typeof entry.errors_over_limit === "number" ? entry.errors_over_limit : 0;
|
|
114
|
+
if (entry.errors_dropped)
|
|
115
|
+
notes.push(`${entry.errors_dropped} console error(s) arrived while the backlog of one call was full and were dropped (not counted).`);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (streamGaps)
|
|
120
|
+
notes.push(`The bridge event stream reported missed events ${streamGaps} time(s), first at ${firstGap}; errors from those moments may be missing.`);
|
|
121
|
+
// Steps: the calls before each mark belong to it; a call still "started" without
|
|
122
|
+
// a result was lost (an earlier process stopped) or still running at end.
|
|
123
|
+
const steps = [];
|
|
124
|
+
let current = [];
|
|
125
|
+
const lost = [];
|
|
126
|
+
const runningAtEnd = [];
|
|
127
|
+
for (const { kind, entry } of orderedEvents) {
|
|
128
|
+
if (kind === "mark") {
|
|
129
|
+
steps.push({ number: entry.step, label: entry.label, verdict: entry.verdict, note: entry.note, at: entry.at, calls: current });
|
|
130
|
+
current = [];
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const row = calls.get(entry.seq);
|
|
134
|
+
if (row) {
|
|
135
|
+
current.push(row);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (kind === "start") {
|
|
139
|
+
const still = running.has(entry.seq);
|
|
140
|
+
(still ? runningAtEnd : lost).push({ seq: entry.seq, tool: entry.tool, at: entry.at });
|
|
141
|
+
current.push({ seq: entry.seq, tool: entry.tool, kind: entry.kind, at: entry.at, duration_ms: 0, status: still ? "running" : "lost", args: entry.args,
|
|
142
|
+
captures: [], errors: [], errorsAfter: [], ...(still ? { running: true } : { lost: true }) });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (current.length)
|
|
146
|
+
steps.push({ number: null, label: "After the last mark", verdict: null, calls: current });
|
|
147
|
+
const catalog = new Map();
|
|
148
|
+
let totalErrors = 0;
|
|
149
|
+
const record = (e, step, call, relation) => {
|
|
150
|
+
totalErrors++;
|
|
151
|
+
const key = errorKey(e);
|
|
152
|
+
const row = catalog.get(key);
|
|
153
|
+
if (row) {
|
|
154
|
+
row.count++;
|
|
155
|
+
if (!row.stack && e.stack)
|
|
156
|
+
row.stack = e.stack;
|
|
157
|
+
if (SPECIFIC_TYPES.has(String(e.type).toLowerCase()) && !SPECIFIC_TYPES.has(row.type.toLowerCase()))
|
|
158
|
+
row.type = String(e.type);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
catalog.set(key, {
|
|
162
|
+
id: catalog.size + 1, type: String(e.type ?? "error"), message: String(e.message ?? ""), stack: e.stack,
|
|
163
|
+
first_step: step?.number ?? null, first_call: call?.seq ?? null, first_tool: call?.tool, relation, at: e.at, count: 1,
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
const stepOfCall = new Map();
|
|
167
|
+
for (const step of steps)
|
|
168
|
+
for (const call of step.calls)
|
|
169
|
+
stepOfCall.set(call.seq, step);
|
|
170
|
+
for (const e of looseErrors)
|
|
171
|
+
record(e, null, null, "before the first call");
|
|
172
|
+
// Walk in time order so "first occurrence" is chronological.
|
|
173
|
+
const timeline = [];
|
|
174
|
+
for (const step of steps)
|
|
175
|
+
for (const call of step.calls) {
|
|
176
|
+
// The same message from the response and the stream inside one call is one occurrence.
|
|
177
|
+
call.errors = call.errors.filter((e, i) => call.errors.findIndex(other => sameMessage(other, e)) === i);
|
|
178
|
+
for (const e of call.errors)
|
|
179
|
+
timeline.push({ e, step, call, relation: "during", at: Date.parse(e.at ?? call.at) || 0 });
|
|
180
|
+
for (const e of call.errorsAfter)
|
|
181
|
+
timeline.push({ e, step, call, relation: "after", at: Date.parse(e.at ?? call.at) || 0 });
|
|
182
|
+
}
|
|
183
|
+
timeline.sort((a, b) => a.at - b.at);
|
|
184
|
+
for (const t of timeline)
|
|
185
|
+
record(t.e, t.step, t.call, t.relation);
|
|
186
|
+
// Occurrences the recorder counted but did not log (a message past its repeat cap, errors past the session cap).
|
|
187
|
+
let suppressed = 0;
|
|
188
|
+
for (const repeat of errorRepeats) {
|
|
189
|
+
const count = typeof repeat.count === "number" ? repeat.count : 0;
|
|
190
|
+
const row = catalog.get(errorKey(repeat));
|
|
191
|
+
if (row)
|
|
192
|
+
row.count += count;
|
|
193
|
+
suppressed += count;
|
|
194
|
+
}
|
|
195
|
+
totalErrors += suppressed + errorsOverLimit;
|
|
196
|
+
if (suppressed)
|
|
197
|
+
notes.push(`${suppressed} repeat(s) of ${errorRepeats.length} message(s) over the per-message log cap were counted, not logged (they are in the ×counts).`);
|
|
198
|
+
if (errorsOverLimit)
|
|
199
|
+
notes.push(`${errorsOverLimit} console error(s) over the per-call / per-session error limit were counted, not logged.`);
|
|
200
|
+
const errorRows = [...catalog.values()].sort((a, b) => a.id - b.id);
|
|
201
|
+
// ---- thumbnails --------------------------------------------------------
|
|
202
|
+
const budgetEnd = input.now() + (input.thumbnailBudgetMs ?? 20_000);
|
|
203
|
+
let thumbs = 0, captureCount = 0, thumbSkipped = 0;
|
|
204
|
+
const thumbFor = (capture) => {
|
|
205
|
+
if (!capture.file)
|
|
206
|
+
return null;
|
|
207
|
+
if (thumbs >= input.maxThumbnails || input.now() > budgetEnd) {
|
|
208
|
+
thumbSkipped++;
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
const source = join(reportDir, capture.file);
|
|
212
|
+
const name = capture.file.replace(/^frames\//, "").replace(/\.png$/i, "") + ".thumb.png";
|
|
213
|
+
const target = join(reportDir, THUMBS_DIR, name);
|
|
214
|
+
try {
|
|
215
|
+
if (!existsSync(target)) {
|
|
216
|
+
const contact = capture.label === "contact sheet";
|
|
217
|
+
const thumb = thumbnail(readFileSync(source), contact ? 960 : 320, contact ? 480 : 320);
|
|
218
|
+
if (!thumb)
|
|
219
|
+
return null;
|
|
220
|
+
writeFileSync(target, thumb.png);
|
|
221
|
+
}
|
|
222
|
+
thumbs++;
|
|
223
|
+
return `${THUMBS_DIR}/${name}`;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
// ---- markdown ----------------------------------------------------------
|
|
230
|
+
const verdicts = { ok: 0, bug: 0, suspicious: 0 };
|
|
231
|
+
for (const step of steps)
|
|
232
|
+
if (step.verdict && step.verdict in verdicts)
|
|
233
|
+
verdicts[step.verdict]++;
|
|
234
|
+
const allCalls = [...calls.values()];
|
|
235
|
+
const failedCalls = allCalls.filter(c => c.status === "error").length;
|
|
236
|
+
for (const c of allCalls)
|
|
237
|
+
captureCount += c.captures.filter(x => x.file).length;
|
|
238
|
+
const startedMs = Date.parse(meta.started_at), endedMs = Date.parse(meta.ended_at ?? new Date(input.now()).toISOString());
|
|
239
|
+
const device = meta.device ?? {};
|
|
240
|
+
const view = (device.view ?? {});
|
|
241
|
+
const deviceText = [
|
|
242
|
+
device.summary ? String(device.summary) : null,
|
|
243
|
+
view.mode ? `${view.mode === "simulator" ? `Device Simulator ${view.device ?? ""}`.trim() : `Game view ${view.size ?? ""}`.trim()}` : null,
|
|
244
|
+
Array.isArray(view.screen) ? `${view.screen[0]}×${view.screen[1]}${view.orientation ? ` ${view.orientation}` : ""}` : null,
|
|
245
|
+
].filter(Boolean).join(" · ") || "not recorded";
|
|
246
|
+
// A hook ran: an invoke that succeeded, or a job (`jobs start` row) whose observed result did not fail.
|
|
247
|
+
const hooks = {};
|
|
248
|
+
const failedJobs = new Set(allCalls.filter(c => c.of !== undefined && c.status === "error").map(c => c.of));
|
|
249
|
+
for (const c of allCalls) {
|
|
250
|
+
const args = c.args;
|
|
251
|
+
const id = typeof args?.command_id === "string" ? args.command_id
|
|
252
|
+
: typeof args?.tool_or_command === "string" ? args.tool_or_command : "";
|
|
253
|
+
const ran = c.status === "ok" || (c.status === "job_started" && !failedJobs.has(c.seq));
|
|
254
|
+
if (/(^|\.)playtest\.begin$/.test(id) && ran)
|
|
255
|
+
hooks.begin = id;
|
|
256
|
+
if (/(^|\.)playtest\.end$/.test(id) && ran)
|
|
257
|
+
hooks.end = id;
|
|
258
|
+
}
|
|
259
|
+
const md = [];
|
|
260
|
+
md.push(`# Playtest report: ${cell(meta.name)}`, "");
|
|
261
|
+
md.push("| | |", "|---|---|");
|
|
262
|
+
md.push(`| Session | ${cellCode(meta.id)} |`);
|
|
263
|
+
md.push(`| Project | ${cell(meta.company)} / ${cell(meta.product)} (${cellCode(meta.project)}) |`);
|
|
264
|
+
md.push(`| Started | ${meta.started_at} |`);
|
|
265
|
+
md.push(`| Ended | ${meta.ended_at ?? "—"} (${Number.isFinite(endedMs - startedMs) ? duration(endedMs - startedMs) : "?"}) |`);
|
|
266
|
+
md.push(`| Device | ${cell(deviceText)} |`);
|
|
267
|
+
md.push(`| Player-state snapshot | ${meta.snapshot ? `${cellCode(meta.snapshot.name)} (${meta.snapshot.taken ? "taken at start" : "existing"})` : "none"} |`);
|
|
268
|
+
if (hooks.begin || hooks.end)
|
|
269
|
+
md.push(`| Project isolation hook | ${[hooks.begin, hooks.end].filter(Boolean).map(h => cellCode(h)).join(" → ")}${hooks.begin && !hooks.end ? " (end hook not recorded)" : ""} |`);
|
|
270
|
+
md.push(`| Recorded | ${allCalls.length} call(s) in ${steps.length} step(s), ${failedCalls} failed, ${captureCount} frame(s), ${errorRows.length} distinct error(s) (${totalErrors} total) |`);
|
|
271
|
+
md.push(`| Verdicts | ok ${verdicts.ok} · bug ${verdicts.bug} · suspicious ${verdicts.suspicious} |`);
|
|
272
|
+
md.push("");
|
|
273
|
+
md.push("## Findings", "");
|
|
274
|
+
const findings = steps.filter(s => s.verdict === "bug" || s.verdict === "suspicious");
|
|
275
|
+
if (!findings.length && !errorRows.length && !lost.length && !runningAtEnd.length && !failedCalls)
|
|
276
|
+
md.push("No bug or suspicious verdicts, no console errors, no failed calls.");
|
|
277
|
+
for (const step of findings)
|
|
278
|
+
md.push(`- **${step.verdict}** — step ${step.number}: ${cell(step.label)}${step.note ? ` — ${cell(step.note)}` : ""}`);
|
|
279
|
+
for (const row of errorRows)
|
|
280
|
+
md.push(`- **${row.type}** ${code(clip(firstLine(row.message), 160))} — first in ${row.first_step !== null ? `step ${row.first_step}` : row.first_call !== null ? "the unmarked calls" : "the session before any call"}${row.first_call !== null ? `, call #${row.first_call} ${code(shortTool(row.first_tool ?? ""))} (${row.relation} it)` : ""}${row.count > 1 ? `, ×${row.count}` : ""} → [E${row.id}](#e${row.id})`);
|
|
281
|
+
if (failedCalls)
|
|
282
|
+
md.push(`- ${failedCalls} recorded call(s) failed (status \`error\` in the steps below).`);
|
|
283
|
+
for (const l of lost)
|
|
284
|
+
md.push(`- **Lost in flight:** call #${l.seq} ${code(shortTool(l.tool))} started at ${l.at} and never finished — the MCP server process stopped during it.`);
|
|
285
|
+
for (const l of runningAtEnd)
|
|
286
|
+
md.push(`- **Still running at end:** call #${l.seq} ${code(shortTool(l.tool))} started at ${l.at} and had not returned when the session ended.`);
|
|
287
|
+
if (endNote)
|
|
288
|
+
md.push("", `> ${cell(endNote)}`);
|
|
289
|
+
md.push("");
|
|
290
|
+
md.push("## Steps", "");
|
|
291
|
+
if (!steps.length)
|
|
292
|
+
md.push("No calls were recorded.", "");
|
|
293
|
+
for (const step of steps) {
|
|
294
|
+
md.push(step.number !== null ? `### Step ${step.number}: ${cell(step.label)} — ${step.verdict}` : `### ${step.label}`, "");
|
|
295
|
+
if (step.note)
|
|
296
|
+
md.push(`> ${cell(step.note)}`, "");
|
|
297
|
+
if (!step.calls.length) {
|
|
298
|
+
md.push("_No recorded calls in this step._", "");
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
md.push("| # | Time | Tool | Arguments | Result | Duration |", "|---|---|---|---|---|---|");
|
|
302
|
+
for (const call of step.calls) {
|
|
303
|
+
const result = call.lost ? "**lost** (server stopped)"
|
|
304
|
+
: call.running ? "**still running at end**"
|
|
305
|
+
: call.status === "error" ? `**error** ${cellCode(call.error?.code ?? "")}${call.error?.message ? ` ${cell(clip(call.error.message, 120))}` : ""}`
|
|
306
|
+
: call.status === "job_started" ? `job ${cellCode(call.job_id ?? "")}`
|
|
307
|
+
: resultText(call);
|
|
308
|
+
md.push(`| ${call.seq}${call.of ? ` (of #${call.of})` : ""} | ${time(call.at)} | ${cellCode(shortTool(call.tool))} | ${call.args !== undefined ? cellCode(clip(JSON.stringify(call.args), 160)) : ""} | ${result} | ${call.lost || call.running ? "—" : duration(call.duration_ms)} |`);
|
|
309
|
+
}
|
|
310
|
+
md.push("");
|
|
311
|
+
const stepErrors = step.calls.flatMap(c => [
|
|
312
|
+
...c.errors.map(e => ({ e, c, relation: "during" })), ...c.errorsAfter.map(e => ({ e, c, relation: "after" })),
|
|
313
|
+
]);
|
|
314
|
+
if (stepErrors.length) {
|
|
315
|
+
md.push("Console errors in this step:", "");
|
|
316
|
+
for (const { e, c, relation } of stepErrors.slice(0, 20)) {
|
|
317
|
+
const row = catalog.get(errorKey(e));
|
|
318
|
+
md.push(`- ${e.type} ${code(clip(firstLine(String(e.message ?? "")), 200))} — ${relation} call #${c.seq}${row ? ` → [E${row.id}](#e${row.id})` : ""}`);
|
|
319
|
+
}
|
|
320
|
+
if (stepErrors.length > 20)
|
|
321
|
+
md.push(`- … ${stepErrors.length - 20} more`);
|
|
322
|
+
md.push("");
|
|
323
|
+
}
|
|
324
|
+
const shots = [];
|
|
325
|
+
for (const call of step.calls) {
|
|
326
|
+
const files = call.captures.filter(c => c.file);
|
|
327
|
+
// A series: its contact sheet, else the first and the last frame.
|
|
328
|
+
const sheet = files.find(c => c.label === "contact sheet");
|
|
329
|
+
const chosen = sheet ? [sheet] : files.length > 3 ? [files[0], files[Math.floor(files.length / 2)], files[files.length - 1]] : files;
|
|
330
|
+
for (const capture of chosen) {
|
|
331
|
+
const thumb = thumbFor(capture);
|
|
332
|
+
const caption = `#${call.seq}${capture.label ? ` ${capture.label}` : ""}${capture.frame !== undefined ? ` F${capture.frame}` : ""}`;
|
|
333
|
+
shots.push(thumb ? `[](${capture.file})` : `[${caption}](${capture.file})`);
|
|
334
|
+
}
|
|
335
|
+
const rest = files.filter(f => !chosen.includes(f));
|
|
336
|
+
if (rest.length)
|
|
337
|
+
shots.push(`#${call.seq}: ${rest.length} more frame(s): ${rest.slice(0, 12).map((f, i) => `[${f.frame !== undefined ? `F${f.frame}` : i + 1}](${f.file})`).join(" ")}${rest.length > 12 ? " …" : ""}`);
|
|
338
|
+
const skipped = call.captures.filter(c => !c.file && c.source);
|
|
339
|
+
if (skipped.length)
|
|
340
|
+
shots.push(`#${call.seq}: ${skipped.length} frame(s) not copied (${skipped[0].skipped ?? skipped[0].missing ?? "unavailable"}): ${code(skipped[0].source)}${skipped.length > 1 ? " …" : ""}`);
|
|
341
|
+
}
|
|
342
|
+
if (shots.length)
|
|
343
|
+
md.push("Frames:", "", shots.join(" "), "");
|
|
344
|
+
}
|
|
345
|
+
md.push("## Errors", "");
|
|
346
|
+
if (!errorRows.length)
|
|
347
|
+
md.push("No console errors or exceptions were logged while recording.", "");
|
|
348
|
+
for (const row of errorRows) {
|
|
349
|
+
md.push(`### E${row.id}`, "");
|
|
350
|
+
md.push(`**${row.type}** ${code(clip(firstLine(row.message), 300))}`, "");
|
|
351
|
+
md.push(`First occurrence: ${row.first_step !== null ? `step ${row.first_step}` : "outside a marked step"}${row.first_call !== null ? `, ${row.relation} call #${row.first_call} ${code(shortTool(row.first_tool ?? ""))}` : ` (${row.relation})`}${row.at ? ` at ${row.at}` : ""}; seen ${row.count} time(s).`, "");
|
|
352
|
+
const body = [row.message.includes("\n") ? row.message : null, row.stack ? row.stack.trim() : null].filter(Boolean).join("\n");
|
|
353
|
+
if (body)
|
|
354
|
+
md.push("```text", clip(body, 4_000).replace(/```/g, "'''"), "```", "");
|
|
355
|
+
else
|
|
356
|
+
md.push("_No stack trace (reported by the tool response; the event stream was not connected)._", "");
|
|
357
|
+
}
|
|
358
|
+
md.push("## State diff", "");
|
|
359
|
+
let stateDiff = null;
|
|
360
|
+
if (!meta.snapshot)
|
|
361
|
+
md.push("No player-state snapshot was taken for this session.", "");
|
|
362
|
+
else if (!input.stateDiff)
|
|
363
|
+
md.push(`Not computed (\`diff: false\`). Snapshot: ${code(meta.snapshot.name)}.`, "");
|
|
364
|
+
else if (!input.stateDiff.ok) {
|
|
365
|
+
stateDiff = { error: input.stateDiff.error };
|
|
366
|
+
md.push(`The diff against ${code(meta.snapshot.name)} failed: ${code(JSON.stringify(input.stateDiff.error).slice(0, 300))}.`, "");
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
const diff = input.stateDiff.output;
|
|
370
|
+
writeFileSync(join(reportDir, "state-diff.json"), JSON.stringify(diff, null, 2));
|
|
371
|
+
stateDiff = { identical: diff.identical, prefs: diff.prefs?.counts, files: diff.files?.counts, editor_prefs: diff.editor_prefs?.counts ?? null };
|
|
372
|
+
md.push(`Snapshot ${code(meta.snapshot.name)} → the state at the end of the session${diff.to?.mode ? ` (${diff.to.mode} mode)` : ""}. Full diff: [state-diff.json](state-diff.json).`, "");
|
|
373
|
+
if (diff.identical)
|
|
374
|
+
md.push("No PlayerPrefs, EditorPrefs or persistentDataPath change.", "");
|
|
375
|
+
for (const [title, part] of [["PlayerPrefs", diff.prefs], ["EditorPrefs", diff.editor_prefs]]) {
|
|
376
|
+
if (!part)
|
|
377
|
+
continue;
|
|
378
|
+
const rows = [
|
|
379
|
+
...(part.added ?? []).map((e) => ["added", e.key, "", show(e.to ?? e)]),
|
|
380
|
+
...(part.removed ?? []).map((e) => ["removed", e.key, show(e.from ?? e), ""]),
|
|
381
|
+
...(part.changed ?? []).map((e) => ["changed", e.key, show(e.from), show(e.to)]),
|
|
382
|
+
];
|
|
383
|
+
if (!rows.length)
|
|
384
|
+
continue;
|
|
385
|
+
md.push(`${title}: ${JSON.stringify(part.counts ?? {})}`, "", "| Change | Key | From | To |", "|---|---|---|---|");
|
|
386
|
+
for (const [change, key, from, to] of rows)
|
|
387
|
+
md.push(`| ${change} | ${cellCode(String(key))} | ${cell(from)} | ${cell(to)} |`);
|
|
388
|
+
if (part.truncated)
|
|
389
|
+
md.push(`| … | ${part.truncated} more | | |`);
|
|
390
|
+
md.push("");
|
|
391
|
+
}
|
|
392
|
+
const files = diff.files;
|
|
393
|
+
if (files && ((files.added?.length ?? 0) + (files.removed?.length ?? 0) + (files.changed?.length ?? 0)) > 0) {
|
|
394
|
+
md.push(`persistentDataPath files: ${JSON.stringify(files.counts ?? {})}`, "", "| Change | Path | Size |", "|---|---|---|");
|
|
395
|
+
for (const e of files.added ?? [])
|
|
396
|
+
md.push(`| added | ${cellCode(String(e.path))} | ${e.size ?? ""} |`);
|
|
397
|
+
for (const e of files.removed ?? [])
|
|
398
|
+
md.push(`| removed | ${cellCode(String(e.path))} | ${e.size ?? ""} |`);
|
|
399
|
+
for (const e of files.changed ?? [])
|
|
400
|
+
md.push(`| changed | ${cellCode(String(e.path))} | ${e.from?.size ?? ""} → ${e.to?.size ?? ""} |`);
|
|
401
|
+
md.push("");
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (editorEvents.length) {
|
|
405
|
+
md.push("## Editor events", "", "| Time | State |", "|---|---|");
|
|
406
|
+
for (const e of editorEvents)
|
|
407
|
+
md.push(`| ${time(e.at)} | ${cellCode(String(e.state))}${EDITOR_STATE_NOTES[String(e.state)] ?? ""} |`);
|
|
408
|
+
md.push("");
|
|
409
|
+
}
|
|
410
|
+
const streamDown = allCalls.filter(c => c.streamDown).length;
|
|
411
|
+
if (streamDown)
|
|
412
|
+
notes.push(`${streamDown} call(s) ran while the bridge event stream was disconnected (a domain reload or restart in progress): their errors come from the tool responses only, without stacks.`);
|
|
413
|
+
if (thumbSkipped)
|
|
414
|
+
notes.push(`${thumbSkipped} frame(s) are linked without a thumbnail (thumbnail limit ${input.maxThumbnails} or time budget).`);
|
|
415
|
+
md.push("## Notes", "");
|
|
416
|
+
md.push("- Frames are full-size PNGs in [frames/](frames/); thumbnails in [thumbs/](thumbs/). The raw log is `../log.jsonl` (one JSON line per event).");
|
|
417
|
+
md.push("- Errors are matched to calls by time: \"during\" = logged while the call ran, \"after\" = logged between this call and the next recorded one.");
|
|
418
|
+
md.push("- Secrets in arguments, notes, console text and the state diff are replaced with `[redacted]`.");
|
|
419
|
+
for (const note of notes)
|
|
420
|
+
md.push(`- ${cell(note)}`);
|
|
421
|
+
md.push("");
|
|
422
|
+
const reportPath = join(reportDir, REPORT_FILE);
|
|
423
|
+
writeFileSync(reportPath, redactor.text(md.join("\n")));
|
|
424
|
+
return {
|
|
425
|
+
report: reportPath, steps: steps.length, calls: allCalls.length, failed_calls: failedCalls, captures: captureCount, thumbnails: thumbs,
|
|
426
|
+
duration_ms: Number.isFinite(endedMs - startedMs) ? endedMs - startedMs : 0, verdicts,
|
|
427
|
+
errors: { unique: errorRows.length, total: totalErrors },
|
|
428
|
+
findings: findings.slice(0, 10).map(s => ({ step: s.number ?? 0, label: s.label, verdict: s.verdict, ...(s.note ? { note: clip(s.note, 300) } : {}) })),
|
|
429
|
+
top_errors: errorRows.slice(0, 5).map(r => ({ type: r.type, message: clip(firstLine(r.message), 200), first_step: r.first_step, first_call: r.first_call, relation: r.relation, count: r.count })),
|
|
430
|
+
lost_in_flight: lost, running_at_end: runningAtEnd, state_diff: stateDiff, hooks, notes,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
const EDITOR_STATE_NOTES = {
|
|
434
|
+
reloading: " (domain reload)",
|
|
435
|
+
stream_reconnected: " (the bridge was away and came back: a domain reload or an Editor restart)",
|
|
436
|
+
entering_playmode: " (entering play mode)",
|
|
437
|
+
exiting_playmode: " (leaving play mode)",
|
|
438
|
+
};
|
|
439
|
+
function show(value) {
|
|
440
|
+
if (value === undefined || value === null)
|
|
441
|
+
return "";
|
|
442
|
+
if (typeof value === "object") {
|
|
443
|
+
if ("value" in value)
|
|
444
|
+
return `${value.type ? `${value.type} ` : ""}${clip(JSON.stringify(value.value), 80)}`;
|
|
445
|
+
if ("length" in value)
|
|
446
|
+
return `${value.type ?? "string"} (${value.length} chars)`;
|
|
447
|
+
return clip(JSON.stringify(value), 80);
|
|
448
|
+
}
|
|
449
|
+
return clip(String(value), 80);
|
|
450
|
+
}
|
|
451
|
+
function resultText(call) {
|
|
452
|
+
const s = call.summary ?? {};
|
|
453
|
+
const parts = [];
|
|
454
|
+
if (typeof s.outcome === "string")
|
|
455
|
+
parts.push(s.outcome);
|
|
456
|
+
const fired = s.fired;
|
|
457
|
+
if (fired && typeof fired === "object" && fired.type)
|
|
458
|
+
parts.push(`fired ${fired.type}${fired.frame !== undefined ? ` @F${fired.frame}` : ""}`);
|
|
459
|
+
const captured = s.capturedAt;
|
|
460
|
+
if (captured && typeof captured === "object")
|
|
461
|
+
parts.push([captured.mode, captured.device ?? captured.size, Array.isArray(captured.screen) ? captured.screen.join("×") : null].filter(Boolean).join(" "));
|
|
462
|
+
const series = s.series;
|
|
463
|
+
if (series && typeof series === "object" && series.captured !== undefined)
|
|
464
|
+
parts.push(`${series.captured} frame(s)`);
|
|
465
|
+
if (Array.isArray(s.backend))
|
|
466
|
+
parts.push(s.backend.join("+"));
|
|
467
|
+
if (s.result !== undefined)
|
|
468
|
+
parts.push(code(clip(JSON.stringify(s.result), 100)));
|
|
469
|
+
if (typeof s.action === "string" && call.kind === "control")
|
|
470
|
+
parts.push(`${s.action} requested`);
|
|
471
|
+
else if (typeof s.isPlaying === "boolean")
|
|
472
|
+
parts.push(s.isPlaying ? "playing" : "edit mode");
|
|
473
|
+
if (call.captures.length && !series)
|
|
474
|
+
parts.push(`${call.captures.length} frame(s)`);
|
|
475
|
+
return ["ok", ...parts].map(p => cell(p)).join(" · ");
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/playtest/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export declare const SESSION_FORMAT = 1;
|
|
2
|
+
export declare const SESSION_FILE = "session.json";
|
|
3
|
+
export declare const LOG_FILE = "log.jsonl";
|
|
4
|
+
export declare const REPORT_DIR = "report";
|
|
5
|
+
export declare const FRAMES_DIR = "frames";
|
|
6
|
+
export declare const THUMBS_DIR = "thumbs";
|
|
7
|
+
export declare const REPORT_FILE = "report.md";
|
|
8
|
+
export interface SessionOwner {
|
|
9
|
+
project: string;
|
|
10
|
+
agent: string;
|
|
11
|
+
port?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface SessionMeta {
|
|
14
|
+
format: number;
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
project: string;
|
|
18
|
+
company: string;
|
|
19
|
+
product: string;
|
|
20
|
+
owner: SessionOwner;
|
|
21
|
+
/** MCP server process that owns the session; a dead pid makes it adoptable. */
|
|
22
|
+
server_pid: number;
|
|
23
|
+
started_at: string;
|
|
24
|
+
state: "open" | "ended";
|
|
25
|
+
ended_at?: string;
|
|
26
|
+
device: Record<string, unknown> | null;
|
|
27
|
+
snapshot: {
|
|
28
|
+
name: string;
|
|
29
|
+
taken: boolean;
|
|
30
|
+
} | null;
|
|
31
|
+
report?: string;
|
|
32
|
+
adoptions?: Array<{
|
|
33
|
+
at: string;
|
|
34
|
+
from: SessionOwner;
|
|
35
|
+
from_pid: number;
|
|
36
|
+
}>;
|
|
37
|
+
limits: Record<string, number>;
|
|
38
|
+
}
|
|
39
|
+
/** The platform app-data folder (same rule as the bridge's player-state store). */
|
|
40
|
+
export declare function appDataRoot(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv, home?: string): string;
|
|
41
|
+
export declare function sessionsRoot(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv, home?: string): string;
|
|
42
|
+
/** A company / product name as one path segment (the bridge's SafeSegment rule). */
|
|
43
|
+
export declare function safeSegment(value: string | null | undefined): string;
|
|
44
|
+
/** A session id: UTC stamp + a slug of the name + 4 hex, safe as a folder name. */
|
|
45
|
+
export declare function sessionId(name: string, now: Date, random: string): string;
|
|
46
|
+
export declare const SESSION_ID_PATTERN: RegExp;
|
|
47
|
+
/**
|
|
48
|
+
* Company / product from ProjectSettings/ProjectSettings.asset — the fallback
|
|
49
|
+
* when the Editor cannot be asked (a restart with the Editor closed). Plain
|
|
50
|
+
* and quoted YAML scalars only; anything else falls back to Unity's defaults.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readProjectIdentity(projectPath: string): {
|
|
53
|
+
company: string;
|
|
54
|
+
product: string;
|
|
55
|
+
} | null;
|
|
56
|
+
export declare class SessionStore {
|
|
57
|
+
readonly root: string;
|
|
58
|
+
constructor(root: string);
|
|
59
|
+
productDir(company: string, product: string): string;
|
|
60
|
+
dir(meta: Pick<SessionMeta, "company" | "product" | "id">): string;
|
|
61
|
+
create(meta: SessionMeta): string;
|
|
62
|
+
writeMeta(meta: SessionMeta): void;
|
|
63
|
+
readMeta(dir: string): SessionMeta | null;
|
|
64
|
+
append(meta: Pick<SessionMeta, "company" | "product" | "id">, entry: Record<string, unknown>): void;
|
|
65
|
+
/**
|
|
66
|
+
* Every parseable line of a session log; a torn line (a crash mid-write) is
|
|
67
|
+
* skipped. Read in chunks, so a log larger than the longest JS string still
|
|
68
|
+
* yields its entries.
|
|
69
|
+
*/
|
|
70
|
+
readLog(dir: string): Array<Record<string, any>>;
|
|
71
|
+
/** End a torn last line, so the next appended entry starts a line of its own. */
|
|
72
|
+
terminateLog(dir: string): void;
|
|
73
|
+
/** Sessions of one product, newest first. */
|
|
74
|
+
list(company: string, product: string): Array<{
|
|
75
|
+
dir: string;
|
|
76
|
+
meta: SessionMeta;
|
|
77
|
+
}>;
|
|
78
|
+
}
|