codeloop-mcp-server 0.1.91 → 0.1.96
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/README.md +30 -0
- package/dist/evidence/binary_freshness.d.ts +27 -0
- package/dist/evidence/binary_freshness.d.ts.map +1 -1
- package/dist/evidence/binary_freshness.js +100 -22
- package/dist/evidence/binary_freshness.js.map +1 -1
- package/dist/evidence/change_coverage.d.ts +41 -0
- package/dist/evidence/change_coverage.d.ts.map +1 -1
- package/dist/evidence/change_coverage.js +69 -2
- package/dist/evidence/change_coverage.js.map +1 -1
- package/dist/evidence/interaction_evidence.d.ts +38 -0
- package/dist/evidence/interaction_evidence.d.ts.map +1 -1
- package/dist/evidence/interaction_evidence.js +60 -0
- package/dist/evidence/interaction_evidence.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -5
- package/dist/index.js.map +1 -1
- package/dist/runners/android_sdk.d.ts +50 -0
- package/dist/runners/android_sdk.d.ts.map +1 -0
- package/dist/runners/android_sdk.js +123 -0
- package/dist/runners/android_sdk.js.map +1 -0
- package/dist/runners/app_launcher.d.ts +22 -0
- package/dist/runners/app_launcher.d.ts.map +1 -1
- package/dist/runners/app_launcher.js +70 -18
- package/dist/runners/app_launcher.js.map +1 -1
- package/dist/runners/device_probe.d.ts.map +1 -1
- package/dist/runners/device_probe.js +5 -2
- package/dist/runners/device_probe.js.map +1 -1
- package/dist/runners/interaction_engine.js +7 -0
- package/dist/runners/interaction_engine.js.map +1 -1
- package/dist/runners/journey_to_maestro.d.ts +27 -0
- package/dist/runners/journey_to_maestro.d.ts.map +1 -1
- package/dist/runners/journey_to_maestro.js +54 -0
- package/dist/runners/journey_to_maestro.js.map +1 -1
- package/dist/runners/logging_readiness.d.ts.map +1 -1
- package/dist/runners/logging_readiness.js +38 -7
- package/dist/runners/logging_readiness.js.map +1 -1
- package/dist/runners/modal_detector.d.ts +13 -0
- package/dist/runners/modal_detector.d.ts.map +1 -1
- package/dist/runners/modal_detector.js +101 -2
- package/dist/runners/modal_detector.js.map +1 -1
- package/dist/runners/screenshot.d.ts.map +1 -1
- package/dist/runners/screenshot.js +10 -1
- package/dist/runners/screenshot.js.map +1 -1
- package/dist/runners/semantics_audit.d.ts +32 -0
- package/dist/runners/semantics_audit.d.ts.map +1 -0
- package/dist/runners/semantics_audit.js +140 -0
- package/dist/runners/semantics_audit.js.map +1 -0
- package/dist/runners/uia_resolver.d.ts.map +1 -1
- package/dist/runners/uia_resolver.js +32 -0
- package/dist/runners/uia_resolver.js.map +1 -1
- package/dist/runners/video_recorder.d.ts.map +1 -1
- package/dist/runners/video_recorder.js +25 -6
- package/dist/runners/video_recorder.js.map +1 -1
- package/dist/runners/wayland.d.ts +32 -0
- package/dist/runners/wayland.d.ts.map +1 -0
- package/dist/runners/wayland.js +49 -0
- package/dist/runners/wayland.js.map +1 -0
- package/dist/runners/window_manager.d.ts +23 -0
- package/dist/runners/window_manager.d.ts.map +1 -1
- package/dist/runners/window_manager.js +66 -3
- package/dist/runners/window_manager.js.map +1 -1
- package/dist/tools/discover_interactions.d.ts.map +1 -1
- package/dist/tools/discover_interactions.js +5 -1
- package/dist/tools/discover_interactions.js.map +1 -1
- package/dist/tools/gate_check.d.ts.map +1 -1
- package/dist/tools/gate_check.js +16 -2
- package/dist/tools/gate_check.js.map +1 -1
- package/dist/tools/plan_change_journey.d.ts.map +1 -1
- package/dist/tools/plan_change_journey.js +15 -2
- package/dist/tools/plan_change_journey.js.map +1 -1
- package/dist/tools/plan_user_journey.d.ts.map +1 -1
- package/dist/tools/plan_user_journey.js +5 -2
- package/dist/tools/plan_user_journey.js.map +1 -1
- package/dist/tools/run_journey.d.ts +64 -0
- package/dist/tools/run_journey.d.ts.map +1 -1
- package/dist/tools/run_journey.js +135 -6
- package/dist/tools/run_journey.js.map +1 -1
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +55 -11
- package/dist/tools/verify.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,6 +17,46 @@
|
|
|
17
17
|
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from "fs";
|
|
18
18
|
import { join } from "path";
|
|
19
19
|
const FILE = "interaction_evidence.json";
|
|
20
|
+
/**
|
|
21
|
+
* P5.4 — per-platform confidence breakdown from a multi-platform journey's
|
|
22
|
+
* evidence. Scoring (drive-completeness only — build/tests/lint gates are
|
|
23
|
+
* platform-agnostic and stay in the monolithic score):
|
|
24
|
+
* launch_failed → 0, device_required → 10;
|
|
25
|
+
* completed → 60 base + up to 20 for flow pass-rate (full marks when no
|
|
26
|
+
* label flows ran but steps drove) + 20 for screenshots.
|
|
27
|
+
*/
|
|
28
|
+
export function computePlatformBreakdown(per) {
|
|
29
|
+
return per.map((p) => {
|
|
30
|
+
if (p.status !== "completed") {
|
|
31
|
+
const isLaunch = p.status === "launch_failed";
|
|
32
|
+
return {
|
|
33
|
+
target: p.target,
|
|
34
|
+
status: p.status,
|
|
35
|
+
score: isLaunch ? 0 : 10,
|
|
36
|
+
driven_steps: p.driven_steps,
|
|
37
|
+
screenshots: p.screenshots,
|
|
38
|
+
fix_hint: isLaunch
|
|
39
|
+
? `${p.target}: the app did not launch — fix the build/launch blocker for this platform (see the journey's launch notes), then re-run codeloop_verify.`
|
|
40
|
+
: `${p.target}: no device was available — boot one (or configure e2e.android_avd / e2e.ios_device), then re-run codeloop_verify.`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const flowsTotal = p.mobile_flows_total ?? 0;
|
|
44
|
+
const flowRatio = flowsTotal > 0 ? (p.mobile_flows_passed ?? 0) / flowsTotal : p.driven_steps > 0 ? 1 : 0;
|
|
45
|
+
const score = Math.round(60 + 20 * flowRatio + (p.screenshots > 0 ? 20 : 0));
|
|
46
|
+
const weak = score < 100;
|
|
47
|
+
return {
|
|
48
|
+
target: p.target,
|
|
49
|
+
status: p.status,
|
|
50
|
+
score,
|
|
51
|
+
driven_steps: p.driven_steps,
|
|
52
|
+
screenshots: p.screenshots,
|
|
53
|
+
flows: flowsTotal > 0 ? `${p.mobile_flows_passed ?? 0}/${flowsTotal}` : undefined,
|
|
54
|
+
fix_hint: weak
|
|
55
|
+
? `${p.target}: drove but incompletely (${flowsTotal > 0 ? `flows ${p.mobile_flows_passed ?? 0}/${flowsTotal}` : `${p.driven_steps} step(s)`}, ${p.screenshots} screenshot(s)) — check the failed flow labels / missing screenshots for this platform.`
|
|
56
|
+
: undefined,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
20
60
|
/** Persist a run_journey interaction-evidence record into its run dir. */
|
|
21
61
|
export function writeInteractionEvidence(runDir, ev) {
|
|
22
62
|
try {
|
|
@@ -64,6 +104,26 @@ export function evaluateInteractionEvidenceGate(input) {
|
|
|
64
104
|
const { journeyEvidence, journeyStale, hasManualInteractionLogs } = input;
|
|
65
105
|
if (journeyEvidence && !journeyStale) {
|
|
66
106
|
const e = journeyEvidence.evidence;
|
|
107
|
+
// P5.3 — multi-platform record: every configured platform must have
|
|
108
|
+
// completed with driven evidence. A launch_failed iOS leg must fail the
|
|
109
|
+
// gate even when the Android leg drove fine.
|
|
110
|
+
if (e.per_platform && e.per_platform.length > 0) {
|
|
111
|
+
const summary = e.per_platform
|
|
112
|
+
.map((p) => p.status === "completed"
|
|
113
|
+
? `${p.target}: ${p.driven_steps} step(s), ${p.screenshots} screenshot(s)${p.mobile_engine ? ` via ${p.mobile_engine}` : ""}`
|
|
114
|
+
: `${p.target}: ${p.status.toUpperCase()}`)
|
|
115
|
+
.join("; ");
|
|
116
|
+
const failing = e.per_platform.filter((p) => p.status !== "completed" || (p.driven_steps === 0 && p.screenshots === 0));
|
|
117
|
+
if (failing.length === 0) {
|
|
118
|
+
return { passed: true, reason: `codeloop_run_journey drove ALL configured platforms — ${summary}.` };
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
passed: false,
|
|
122
|
+
reason: `Multi-platform run (e2e.platforms) is INCOMPLETE — ${summary}. ` +
|
|
123
|
+
`Every configured platform must produce driven evidence: fix ${failing.map((p) => p.target).join(", ")} ` +
|
|
124
|
+
`(or remove it from e2e.platforms), then re-run codeloop_verify.`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
67
127
|
const mobile = e.mobile_engine
|
|
68
128
|
? ` (mobile engine: ${e.mobile_engine}${e.mobile_flows_total != null ? `, ${e.mobile_flows_passed ?? 0}/${e.mobile_flows_total} flow(s)` : ""})`
|
|
69
129
|
: "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interaction_evidence.js","sourceRoot":"","sources":["../../src/evidence/interaction_evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"interaction_evidence.js","sourceRoot":"","sources":["../../src/evidence/interaction_evidence.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4QA,QAAA,MAAM,oBAAoB,yDAA6B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AA6VhC,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEjD"}
|
package/dist/index.js
CHANGED
|
@@ -216,6 +216,14 @@ function autoCloseStuckModalsEnabled() {
|
|
|
216
216
|
}
|
|
217
217
|
/** Consecutive same-dialog detections that mark a file dialog as genuinely stuck. */
|
|
218
218
|
const MODAL_AUTOCLOSE_THRESHOLD = 3;
|
|
219
|
+
// P2.1 — Android Studio installs the SDK without putting platform-tools on
|
|
220
|
+
// the shell PATH. Resolve ANDROID_HOME / ANDROID_SDK_ROOT / the default
|
|
221
|
+
// install location ONCE at startup and append the tool dirs to PATH so every
|
|
222
|
+
// adb/emulator call (ours and Maestro's) just works. Resolution details are
|
|
223
|
+
// surfaced by `codeloop doctor` and Android launch errors.
|
|
224
|
+
import { ensureAndroidToolsOnPath } from "./runners/android_sdk.js";
|
|
225
|
+
const androidSdkResolution = ensureAndroidToolsOnPath();
|
|
226
|
+
export { androidSdkResolution };
|
|
219
227
|
const server = new McpServer({
|
|
220
228
|
name: "codeloop",
|
|
221
229
|
version: "0.1.14",
|
|
@@ -1857,20 +1865,72 @@ screens_captured[], screenshots[], unsupported_count, manual_followups[], direct
|
|
|
1857
1865
|
target_type: targetTypeSchema.optional().describe("Override the auto-detected interaction target. Accepts synonyms (web→browser, android→android_emulator, ios→ios_simulator, *_desktop→desktop)."),
|
|
1858
1866
|
web_url: z.string().optional().describe("URL to open for browser targets (e.g. http://localhost:3000). Defaults to e2e.web_url from config. Start your dev server first."),
|
|
1859
1867
|
max_duration_seconds: z.number().int().min(10).max(600).optional().describe("Max video recording length. Default 180s."),
|
|
1860
|
-
}, async (params) => {
|
|
1868
|
+
}, async (params, extra) => {
|
|
1869
|
+
// P5.5 (0.1.92) — stream journey progress (boot, build heartbeat lines,
|
|
1870
|
+
// drive, capture) the same way verify streams phases, so a cold first
|
|
1871
|
+
// build doesn't look like a hang. Same safety gate as verify: only when
|
|
1872
|
+
// the client passed a progressToken AND is safe to stream to.
|
|
1873
|
+
const progressToken = extra?._meta?.progressToken;
|
|
1874
|
+
let journeyClientName;
|
|
1875
|
+
try {
|
|
1876
|
+
journeyClientName = server.server.getClientVersion?.()?.name;
|
|
1877
|
+
}
|
|
1878
|
+
catch {
|
|
1879
|
+
journeyClientName = undefined;
|
|
1880
|
+
}
|
|
1861
1881
|
const result = await withAuth(async () => {
|
|
1862
1882
|
const cwd = resolveCwd(params);
|
|
1863
1883
|
const { loadConfig } = await import("./config.js");
|
|
1864
1884
|
const cfg = loadConfig(cwd);
|
|
1865
|
-
const {
|
|
1866
|
-
|
|
1885
|
+
const { runJourneyForPlatforms } = await import("./tools/run_journey.js");
|
|
1886
|
+
const { progressClientDecision } = await import("./tools/verify.js");
|
|
1887
|
+
const progressSafe = progressClientDecision(journeyClientName, process.env.CODELOOP_PROGRESS);
|
|
1888
|
+
let progressCount = 0;
|
|
1889
|
+
const onProgress = !progressSafe || progressToken === undefined
|
|
1890
|
+
? undefined
|
|
1891
|
+
: (u) => {
|
|
1892
|
+
progressCount += 1;
|
|
1893
|
+
void extra
|
|
1894
|
+
.sendNotification({
|
|
1895
|
+
method: "notifications/progress",
|
|
1896
|
+
params: {
|
|
1897
|
+
progressToken,
|
|
1898
|
+
progress: progressCount,
|
|
1899
|
+
message: `${u.phase}${u.detail ? ` — ${u.detail.slice(0, 120)}` : ""} (${Math.round(u.elapsedMs / 1000)}s)`,
|
|
1900
|
+
},
|
|
1901
|
+
})
|
|
1902
|
+
.catch(() => { });
|
|
1903
|
+
};
|
|
1904
|
+
// P5.3 — e2e.platforms drives every listed platform sequentially; an
|
|
1905
|
+
// explicit target_type argument still forces a single-platform run.
|
|
1906
|
+
return runJourneyForPlatforms({
|
|
1867
1907
|
cwd,
|
|
1868
1908
|
e2e: { ...cfg.e2e, web_url: params.web_url ?? cfg.e2e?.web_url },
|
|
1869
1909
|
targetApp: cfg.evidence?.target_app,
|
|
1870
1910
|
targetType: params.target_type,
|
|
1871
1911
|
maxDurationSeconds: params.max_duration_seconds,
|
|
1912
|
+
onProgress,
|
|
1872
1913
|
});
|
|
1873
1914
|
}, { tool: "codeloop_run_journey", cwd: resolveCwd(params), input: params });
|
|
1915
|
+
// Single-platform runs keep the legacy flat result shape; multi-platform
|
|
1916
|
+
// runs return the per-platform outcome list plus a combined directive.
|
|
1917
|
+
const isWrapped = result && typeof result === "object" && "outcomes" in result;
|
|
1918
|
+
const wrapped = isWrapped ? result : null;
|
|
1919
|
+
if (wrapped && !wrapped.multi) {
|
|
1920
|
+
const single = wrapped.outcomes[0].result;
|
|
1921
|
+
const directive = `\n\n${single.directive}`;
|
|
1922
|
+
return {
|
|
1923
|
+
content: withInitHint([{ type: "text", text: JSON.stringify(single, null, 2) + directive }]),
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1926
|
+
if (wrapped) {
|
|
1927
|
+
const directives = wrapped.outcomes
|
|
1928
|
+
.map((o) => `── ${o.platform} ──\n${o.result.directive}`)
|
|
1929
|
+
.join("\n\n");
|
|
1930
|
+
return {
|
|
1931
|
+
content: withInitHint([{ type: "text", text: JSON.stringify(result, null, 2) + `\n\n${directives}` }]),
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1874
1934
|
const directive = result && typeof result === "object" && "directive" in result ? `\n\n${result.directive}` : "";
|
|
1875
1935
|
return {
|
|
1876
1936
|
content: withInitHint([{ type: "text", text: JSON.stringify(result, null, 2) + directive }]),
|
|
@@ -2110,8 +2170,11 @@ App logs (stdout, logcat, simctl log) are automatically captured alongside the v
|
|
|
2110
2170
|
let binaryFreshnessDetails;
|
|
2111
2171
|
if (targetType === "desktop" && appName) {
|
|
2112
2172
|
try {
|
|
2113
|
-
|
|
2114
|
-
|
|
2173
|
+
// 0.1.96 — prefer the actually-running process binary (E2E #14: the
|
|
2174
|
+
// configured path pointed at a stale publish/ copy while the running
|
|
2175
|
+
// app was a fresh subproject Debug build → false BINARY MISMATCH).
|
|
2176
|
+
const { checkBinaryFreshnessAsync } = await import("./evidence/binary_freshness.js");
|
|
2177
|
+
binaryFreshnessDetails = await checkBinaryFreshnessAsync({ app_name: appName, cwd });
|
|
2115
2178
|
if (binaryFreshnessDetails.stale) {
|
|
2116
2179
|
binaryFreshnessWarning = binaryFreshnessDetails.reason;
|
|
2117
2180
|
const { recordCycleIssue } = await import("./evidence/cycle_issues.js");
|
|
@@ -3063,6 +3126,18 @@ Wait 1-2 seconds between interactions so video frames capture state changes.`, {
|
|
|
3063
3126
|
let windowOriginOffset = null;
|
|
3064
3127
|
let screenshotDims = null;
|
|
3065
3128
|
if (tt === "desktop") {
|
|
3129
|
+
// P2.2 — Wayland-only Linux sessions can't be driven by xdotool.
|
|
3130
|
+
// Fail fast with the remediation directive instead of letting every
|
|
3131
|
+
// individual action return an unexplained success: false.
|
|
3132
|
+
const { waylandDirective } = await import("./runners/wayland.js");
|
|
3133
|
+
const waylandBlock = waylandDirective();
|
|
3134
|
+
if (waylandBlock && action !== "wait") {
|
|
3135
|
+
return {
|
|
3136
|
+
content: [
|
|
3137
|
+
{ type: "text", text: JSON.stringify({ success: false, action, error: waylandBlock }, null, 2) },
|
|
3138
|
+
],
|
|
3139
|
+
};
|
|
3140
|
+
}
|
|
3066
3141
|
const appName = params.app_name || vr.getActiveRecordingAppName();
|
|
3067
3142
|
if (appName && action !== "wait") {
|
|
3068
3143
|
await wm.bringAppToFront(appName);
|