zefiro 0.9.0 → 0.10.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/README.md +5 -14
- package/dist/cli-5w708rbb.js +167 -0
- package/dist/cli-7hvj61ht.js +150 -0
- package/dist/cli-ewbvvxm8.js +145 -0
- package/dist/cli-kjyet1n8.js +384 -0
- package/dist/cli-m1ghts25.js +133 -0
- package/dist/cli-mm7ct90g.js +110 -0
- package/dist/cli.js +180 -102
- package/dist/explorer-ckk9bkff.js +11 -0
- package/dist/explorer-svj2p317.js +10 -0
- package/dist/graph-builder-ca71yjkc.js +10 -0
- package/dist/index.js +1 -1
- package/dist/mcp.js +241 -46
- package/dist/report-wh0mnnxb.js +12 -0
- package/package.json +2 -6
package/dist/mcp.js
CHANGED
|
@@ -36,18 +36,20 @@ import {
|
|
|
36
36
|
AgentBrowser,
|
|
37
37
|
authenticate
|
|
38
38
|
} from "./cli-b26q1e27.js";
|
|
39
|
+
import {
|
|
40
|
+
generateIndexHtml,
|
|
41
|
+
generateReadme,
|
|
42
|
+
generateSectionMarkdown
|
|
43
|
+
} from "./cli-kjyet1n8.js";
|
|
39
44
|
import {
|
|
40
45
|
ensureDir,
|
|
41
46
|
writeFile
|
|
42
47
|
} from "./cli-zvk8gwe4.js";
|
|
43
48
|
import {
|
|
44
49
|
buildTopology,
|
|
45
|
-
generateIndexHtml,
|
|
46
|
-
generateReadme,
|
|
47
|
-
generateSectionMarkdown,
|
|
48
50
|
normalizeUrl,
|
|
49
51
|
urlToSlug
|
|
50
|
-
} from "./cli-
|
|
52
|
+
} from "./cli-5w708rbb.js";
|
|
51
53
|
import {
|
|
52
54
|
__commonJS,
|
|
53
55
|
__require,
|
|
@@ -17936,18 +17938,72 @@ function broadcastState() {
|
|
|
17936
17938
|
function startCompanionServer(mode, port = 0) {
|
|
17937
17939
|
state = createCompanionState(mode);
|
|
17938
17940
|
return new Promise((resolvePromise, reject) => {
|
|
17941
|
+
const startTime = Date.now();
|
|
17939
17942
|
const httpServer = createServer((req, res) => {
|
|
17940
|
-
|
|
17943
|
+
const url = req.url?.split("?")[0];
|
|
17944
|
+
const cors = { "Access-Control-Allow-Origin": "*" };
|
|
17945
|
+
if (url === "/" || url === "/companion") {
|
|
17941
17946
|
const htmlPath = resolve(uiDir, "companion.html");
|
|
17942
17947
|
if (existsSync2(htmlPath)) {
|
|
17943
|
-
res.writeHead(200, { "Content-Type": "text/html
|
|
17948
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", ...cors });
|
|
17944
17949
|
res.end(readFileSync2(htmlPath));
|
|
17945
17950
|
} else {
|
|
17946
|
-
res.writeHead(200, { "Content-Type": "text/html",
|
|
17951
|
+
res.writeHead(200, { "Content-Type": "text/html", ...cors });
|
|
17947
17952
|
res.end("<html><body><h1>Companion UI not found</h1></body></html>");
|
|
17948
17953
|
}
|
|
17949
17954
|
return;
|
|
17950
17955
|
}
|
|
17956
|
+
if (url === "/logo.svg") {
|
|
17957
|
+
const svgPath = resolve(uiDir, "logo.svg");
|
|
17958
|
+
if (existsSync2(svgPath)) {
|
|
17959
|
+
res.writeHead(200, { "Content-Type": "image/svg+xml", ...cors });
|
|
17960
|
+
res.end(readFileSync2(svgPath));
|
|
17961
|
+
} else {
|
|
17962
|
+
res.writeHead(404);
|
|
17963
|
+
res.end("Not found");
|
|
17964
|
+
}
|
|
17965
|
+
return;
|
|
17966
|
+
}
|
|
17967
|
+
if (url === "/health") {
|
|
17968
|
+
res.writeHead(200, { "Content-Type": "application/json", ...cors });
|
|
17969
|
+
res.end(JSON.stringify({ status: "ok", uptime: Math.floor((Date.now() - startTime) / 1000) }));
|
|
17970
|
+
return;
|
|
17971
|
+
}
|
|
17972
|
+
if (url === "/track" && req.method === "POST") {
|
|
17973
|
+
let body = "";
|
|
17974
|
+
req.on("data", (chunk) => {
|
|
17975
|
+
body += chunk.toString();
|
|
17976
|
+
});
|
|
17977
|
+
req.on("end", () => {
|
|
17978
|
+
try {
|
|
17979
|
+
const data = JSON.parse(body);
|
|
17980
|
+
const entry = {
|
|
17981
|
+
action: data.action ?? "unknown",
|
|
17982
|
+
timestamp: new Date().toISOString(),
|
|
17983
|
+
result: data.result,
|
|
17984
|
+
source: data.source ?? "agent"
|
|
17985
|
+
};
|
|
17986
|
+
state.actionLog.push(entry);
|
|
17987
|
+
if (state.actionLog.length > 100)
|
|
17988
|
+
state.actionLog = state.actionLog.slice(-100);
|
|
17989
|
+
if (data.url) {
|
|
17990
|
+
state.currentPage = { url: data.url, title: data.title ?? data.url };
|
|
17991
|
+
}
|
|
17992
|
+
broadcastState();
|
|
17993
|
+
res.writeHead(200, { "Content-Type": "application/json", ...cors });
|
|
17994
|
+
res.end(JSON.stringify({ success: true, tracked_at: entry.timestamp }));
|
|
17995
|
+
} catch {
|
|
17996
|
+
res.writeHead(400, { "Content-Type": "application/json", ...cors });
|
|
17997
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
17998
|
+
}
|
|
17999
|
+
});
|
|
18000
|
+
return;
|
|
18001
|
+
}
|
|
18002
|
+
if (url === "/track" && req.method === "OPTIONS") {
|
|
18003
|
+
res.writeHead(204, { ...cors, "Access-Control-Allow-Methods": "POST", "Access-Control-Allow-Headers": "Content-Type" });
|
|
18004
|
+
res.end();
|
|
18005
|
+
return;
|
|
18006
|
+
}
|
|
17951
18007
|
res.writeHead(404);
|
|
17952
18008
|
res.end("Not found");
|
|
17953
18009
|
});
|
|
@@ -18075,24 +18131,19 @@ import { homedir } from "node:os";
|
|
|
18075
18131
|
import { spawn } from "node:child_process";
|
|
18076
18132
|
|
|
18077
18133
|
// src/copilot/overlay-download.ts
|
|
18078
|
-
import { createWriteStream, mkdirSync, existsSync as existsSync3, chmodSync } from "node:fs";
|
|
18079
|
-
import { join as join3 } from "node:path";
|
|
18080
|
-
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
18081
18134
|
import { createHash } from "node:crypto";
|
|
18135
|
+
import { chmodSync, createWriteStream, existsSync as existsSync3, mkdirSync } from "node:fs";
|
|
18082
18136
|
import { readFile, unlink } from "node:fs/promises";
|
|
18137
|
+
import { join as join3 } from "node:path";
|
|
18083
18138
|
import { createInterface } from "node:readline";
|
|
18084
18139
|
import { Readable } from "node:stream";
|
|
18140
|
+
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
18085
18141
|
var OVERLAY_VERSION = "0.1.0";
|
|
18086
|
-
var GITHUB_REPO = "
|
|
18142
|
+
var GITHUB_REPO = "davide97g/qaligent";
|
|
18087
18143
|
function resolveArch() {
|
|
18088
|
-
|
|
18089
|
-
|
|
18090
|
-
|
|
18091
|
-
case "x64":
|
|
18092
|
-
return "x86_64";
|
|
18093
|
-
default:
|
|
18094
|
-
return null;
|
|
18095
|
-
}
|
|
18144
|
+
if (process.arch === "arm64")
|
|
18145
|
+
return "aarch64";
|
|
18146
|
+
return null;
|
|
18096
18147
|
}
|
|
18097
18148
|
async function confirm(message) {
|
|
18098
18149
|
if (!process.stdin.isTTY)
|
|
@@ -18152,7 +18203,7 @@ async function downloadOverlay(binDir, options) {
|
|
|
18152
18203
|
const arch = resolveArch();
|
|
18153
18204
|
if (!arch) {
|
|
18154
18205
|
if (!options?.silent) {
|
|
18155
|
-
console.log(
|
|
18206
|
+
console.log(" Native overlay is only available on Apple Silicon Macs (M1/M2/M3/M4).");
|
|
18156
18207
|
}
|
|
18157
18208
|
return false;
|
|
18158
18209
|
}
|
|
@@ -18259,27 +18310,31 @@ async function handleCopilotStart(params) {
|
|
|
18259
18310
|
const cwd = process.cwd();
|
|
18260
18311
|
const outputDir = params.outputDir ? join5(cwd, params.outputDir) : join5(cwd, "copilot-report");
|
|
18261
18312
|
const session = createSession(params.baseUrl, mode, outputDir);
|
|
18262
|
-
|
|
18263
|
-
|
|
18264
|
-
|
|
18265
|
-
|
|
18266
|
-
|
|
18267
|
-
|
|
18268
|
-
|
|
18269
|
-
|
|
18270
|
-
|
|
18271
|
-
|
|
18272
|
-
|
|
18273
|
-
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
18280
|
-
|
|
18313
|
+
if (params.browser !== "chrome") {
|
|
18314
|
+
const browser = new AgentBrowser({
|
|
18315
|
+
session: `copilot-${session.id}`,
|
|
18316
|
+
headed: params.headed ?? true
|
|
18317
|
+
});
|
|
18318
|
+
browsers.set(session.id, browser);
|
|
18319
|
+
if (params.authState) {
|
|
18320
|
+
const config = {
|
|
18321
|
+
baseUrl: params.baseUrl,
|
|
18322
|
+
outputDir,
|
|
18323
|
+
maxPages: params.maxPages ?? 100,
|
|
18324
|
+
excludePatterns: [],
|
|
18325
|
+
headed: params.headed ?? true,
|
|
18326
|
+
waitStrategy: "networkidle",
|
|
18327
|
+
waitDelay: 1500,
|
|
18328
|
+
pageTimeout: 30000,
|
|
18329
|
+
auth: { method: "state-file", stateFile: params.authState },
|
|
18330
|
+
sessionName: `copilot-${session.id}`
|
|
18331
|
+
};
|
|
18332
|
+
await authenticate(browser, config);
|
|
18333
|
+
}
|
|
18334
|
+
await browser.setViewport(1440, 900);
|
|
18335
|
+
await browser.open(params.baseUrl);
|
|
18336
|
+
await browser.waitForLoad("networkidle", 1500);
|
|
18281
18337
|
}
|
|
18282
|
-
await browser.setViewport(1440, 900);
|
|
18283
18338
|
const companion = await startCompanionServer(mode, 0);
|
|
18284
18339
|
session.companionPort = companion.port;
|
|
18285
18340
|
const overlayBin = await resolveOverlayBinary({ silent: true });
|
|
@@ -18288,8 +18343,6 @@ async function handleCopilotStart(params) {
|
|
|
18288
18343
|
if (child?.pid)
|
|
18289
18344
|
session.overlayPid = child.pid;
|
|
18290
18345
|
}
|
|
18291
|
-
await browser.open(params.baseUrl);
|
|
18292
|
-
await browser.waitForLoad("networkidle", 1500);
|
|
18293
18346
|
logAction(session, `copilot_start: ${params.baseUrl} (mode: ${mode})`);
|
|
18294
18347
|
syncAction(`copilot_start: ${params.baseUrl} (mode: ${mode})`);
|
|
18295
18348
|
return {
|
|
@@ -18297,7 +18350,8 @@ async function handleCopilotStart(params) {
|
|
|
18297
18350
|
mode: session.mode,
|
|
18298
18351
|
base_url: params.baseUrl,
|
|
18299
18352
|
output_dir: outputDir,
|
|
18300
|
-
companion_url: `http://localhost:${companion.port}
|
|
18353
|
+
companion_url: `http://localhost:${companion.port}`,
|
|
18354
|
+
browser: params.browser ?? "playwright"
|
|
18301
18355
|
};
|
|
18302
18356
|
}
|
|
18303
18357
|
async function handleCopilotStop(params) {
|
|
@@ -18432,6 +18486,7 @@ async function handleCopilotRecordPage(params) {
|
|
|
18432
18486
|
path: new URL(normalizedUrl).pathname,
|
|
18433
18487
|
title,
|
|
18434
18488
|
slug: params.slug,
|
|
18489
|
+
stableId: `page:${params.slug}`,
|
|
18435
18490
|
depth: new URL(normalizedUrl).pathname.split("/").filter(Boolean).length,
|
|
18436
18491
|
screenshot: `screenshots/${params.slug}/default.png`,
|
|
18437
18492
|
elements: [],
|
|
@@ -18499,6 +18554,21 @@ async function handleCopilotProposeAction(params) {
|
|
|
18499
18554
|
message: "Proposal sent to companion UI. Call copilot_check_input to get the result."
|
|
18500
18555
|
};
|
|
18501
18556
|
}
|
|
18557
|
+
async function handleCopilotTrack(params) {
|
|
18558
|
+
const session = getSession(params.session_id);
|
|
18559
|
+
if (!session)
|
|
18560
|
+
throw new Error(`Session not found: ${params.session_id}`);
|
|
18561
|
+
logAction(session, params.action, params.result);
|
|
18562
|
+
syncAction(params.action, params.result);
|
|
18563
|
+
if (params.url) {
|
|
18564
|
+
updateCurrentPage(params.url, params.title ?? params.url);
|
|
18565
|
+
}
|
|
18566
|
+
return {
|
|
18567
|
+
success: true,
|
|
18568
|
+
action: params.action,
|
|
18569
|
+
tracked_at: new Date().toISOString()
|
|
18570
|
+
};
|
|
18571
|
+
}
|
|
18502
18572
|
|
|
18503
18573
|
// src/mcp.ts
|
|
18504
18574
|
var SERVER_INSTRUCTIONS = `
|
|
@@ -18515,6 +18585,7 @@ It produces markdown documentation organized as a knowledge network, with an int
|
|
|
18515
18585
|
|
|
18516
18586
|
1. **Explore.** \`zefiro_explore({ baseUrl: "http://localhost:3000" })\` — BFS exploration of the application
|
|
18517
18587
|
2. **Read.** \`zefiro_read_docs()\` — read the generated documentation (README or specific sections)
|
|
18588
|
+
3. **Push.** \`zefiro_push({ apiKey: "..." })\` — push report to QA Intelligence (builds graph automatically)
|
|
18518
18589
|
|
|
18519
18590
|
## Output Structure
|
|
18520
18591
|
|
|
@@ -18530,6 +18601,7 @@ app-report/
|
|
|
18530
18601
|
|
|
18531
18602
|
- \`zefiro_explore\` — explore a web application via BFS, generating documentation and screenshots
|
|
18532
18603
|
- \`zefiro_read_docs\` — read generated documentation (README or specific section files)
|
|
18604
|
+
- \`zefiro_push\` — push exploration report to QA Intelligence (auto-builds graph with stable IDs)
|
|
18533
18605
|
- \`zefiro_scan_codebase\` — scan project for test files, configs, and path aliases (static analysis helper)
|
|
18534
18606
|
|
|
18535
18607
|
## Copilot — Interactive Browser Co-Pilot
|
|
@@ -18556,8 +18628,16 @@ Use these tools when the user asks to explore, map, or document a running web ap
|
|
|
18556
18628
|
- \`zefiro_copilot_get_session\` — Get session state (explored pages, stats)
|
|
18557
18629
|
- \`zefiro_copilot_check_input\` — Read pending human input (voice/text)
|
|
18558
18630
|
- \`zefiro_copilot_propose_action\` — ASSIST mode: propose action for approval
|
|
18631
|
+
- \`zefiro_copilot_track\` — Chrome Bridge: sync an external browser action to the session log
|
|
18632
|
+
|
|
18633
|
+
### Chrome Bridge Mode
|
|
18634
|
+
Use \`browser: "chrome"\` with \`copilot_start\` to track actions from an external browser (e.g., Claude-in-Chrome).
|
|
18635
|
+
1. \`zefiro_copilot_start({ baseUrl, mode: "assist", browser: "chrome" })\` — starts companion only
|
|
18636
|
+
2. Open the \`companion_url\` in your browser
|
|
18637
|
+
3. Use Claude-in-Chrome tools to browse; call \`zefiro_copilot_track\` after each action
|
|
18638
|
+
4. \`zefiro_copilot_stop\` — generates report
|
|
18559
18639
|
`.trim();
|
|
18560
|
-
var server = new McpServer({ name: "zefiro", version: "0.
|
|
18640
|
+
var server = new McpServer({ name: "zefiro", version: "0.10.0" }, { instructions: SERVER_INSTRUCTIONS });
|
|
18561
18641
|
server.registerTool("zefiro_explore", {
|
|
18562
18642
|
title: "Explore Application",
|
|
18563
18643
|
description: "Explore a web application using browser automation (BFS). " + "Visits pages, takes screenshots, and generates markdown documentation. " + "Requires agent-browser to be installed globally.",
|
|
@@ -18569,8 +18649,8 @@ server.registerTool("zefiro_explore", {
|
|
|
18569
18649
|
})
|
|
18570
18650
|
}, async ({ baseUrl, maxPages, outputDir, headed }) => {
|
|
18571
18651
|
try {
|
|
18572
|
-
const { runExploration } = await import("./explorer-
|
|
18573
|
-
const { generateReadme: generateReadme2, generateIndexHtml: generateIndexHtml2 } = await import("./report-
|
|
18652
|
+
const { runExploration } = await import("./explorer-ckk9bkff.js");
|
|
18653
|
+
const { generateReadme: generateReadme2, generateIndexHtml: generateIndexHtml2 } = await import("./report-wh0mnnxb.js");
|
|
18574
18654
|
const { writeFile: writeFile2, ensureDir: ensureDir2 } = await import("./fs-9dhtxzmg.js");
|
|
18575
18655
|
const cwd = process.cwd();
|
|
18576
18656
|
const outDir = outputDir ? join6(cwd, outputDir) : join6(cwd, "app-report");
|
|
@@ -18588,6 +18668,8 @@ server.registerTool("zefiro_explore", {
|
|
|
18588
18668
|
sessionName: "zefiro"
|
|
18589
18669
|
};
|
|
18590
18670
|
const state2 = await runExploration(config);
|
|
18671
|
+
const serializableState = { ...state2, pages: Object.fromEntries(state2.pages) };
|
|
18672
|
+
writeFile2(join6(outDir, ".exploration-state.json"), JSON.stringify(serializableState, null, 2));
|
|
18591
18673
|
const readme = generateReadme2(state2);
|
|
18592
18674
|
writeFile2(join6(outDir, "README.md"), readme);
|
|
18593
18675
|
const html = generateIndexHtml2(state2);
|
|
@@ -18674,12 +18756,107 @@ server.registerTool("zefiro_scan_codebase", {
|
|
|
18674
18756
|
return { content: [{ type: "text", text: `Error scanning codebase: ${err.message}` }], isError: true };
|
|
18675
18757
|
}
|
|
18676
18758
|
});
|
|
18759
|
+
server.registerTool("zefiro_push", {
|
|
18760
|
+
title: "Push Report",
|
|
18761
|
+
description: "Push the exploration report to QA Intelligence. " + "Builds a graph from the exploration state, encodes screenshots, and pushes to the API. " + "Requires a prior zefiro_explore run and an API key.",
|
|
18762
|
+
inputSchema: exports_external.object({
|
|
18763
|
+
apiKey: exports_external.string().describe("App API key for QA Intelligence"),
|
|
18764
|
+
apiUrl: exports_external.string().optional().describe("API base URL (default: https://qaligent.space)"),
|
|
18765
|
+
outputDir: exports_external.string().optional().describe("Exploration output directory (default: app-report)"),
|
|
18766
|
+
commitSha: exports_external.string().optional().describe("Git commit SHA to associate")
|
|
18767
|
+
})
|
|
18768
|
+
}, async ({ apiKey, apiUrl, outputDir, commitSha }) => {
|
|
18769
|
+
try {
|
|
18770
|
+
const { buildReportGraph, buildReportSections } = await import("./graph-builder-ca71yjkc.js");
|
|
18771
|
+
const cwd = process.cwd();
|
|
18772
|
+
const outDir = outputDir ? join6(cwd, outputDir) : join6(cwd, "app-report");
|
|
18773
|
+
const url = apiUrl ?? "https://qaligent.space";
|
|
18774
|
+
const statePath = join6(outDir, ".exploration-state.json");
|
|
18775
|
+
if (!existsSync5(statePath)) {
|
|
18776
|
+
return {
|
|
18777
|
+
content: [{ type: "text", text: "No exploration state found. Run zefiro_explore first." }],
|
|
18778
|
+
isError: true
|
|
18779
|
+
};
|
|
18780
|
+
}
|
|
18781
|
+
const raw = JSON.parse(readFileSync3(statePath, "utf-8"));
|
|
18782
|
+
const pages = new Map(Object.entries(raw.pages));
|
|
18783
|
+
const state2 = { ...raw, pages };
|
|
18784
|
+
const visitedPages = Array.from(pages.values()).filter((p) => p.status === "visited");
|
|
18785
|
+
const graph = buildReportGraph(state2);
|
|
18786
|
+
const sectionsDir = join6(outDir, "sections");
|
|
18787
|
+
const markdowns = new Map;
|
|
18788
|
+
if (existsSync5(sectionsDir)) {
|
|
18789
|
+
for (const file of readdirSync2(sectionsDir)) {
|
|
18790
|
+
if (file.endsWith(".md")) {
|
|
18791
|
+
markdowns.set(file.replace(/\.md$/, ""), readFileSync3(join6(sectionsDir, file), "utf-8"));
|
|
18792
|
+
}
|
|
18793
|
+
}
|
|
18794
|
+
}
|
|
18795
|
+
const sections = buildReportSections(visitedPages, markdowns);
|
|
18796
|
+
const screenshotsDir = join6(outDir, "screenshots");
|
|
18797
|
+
const screenshots = [];
|
|
18798
|
+
if (existsSync5(screenshotsDir)) {
|
|
18799
|
+
for (const slugDir of readdirSync2(screenshotsDir)) {
|
|
18800
|
+
const fullDir = join6(screenshotsDir, slugDir);
|
|
18801
|
+
try {
|
|
18802
|
+
const files = readdirSync2(fullDir);
|
|
18803
|
+
for (let i = 0;i < files.length; i++) {
|
|
18804
|
+
const file = files[i];
|
|
18805
|
+
if (!file.endsWith(".png") && !file.endsWith(".jpg"))
|
|
18806
|
+
continue;
|
|
18807
|
+
screenshots.push({
|
|
18808
|
+
sectionSlug: slugDir,
|
|
18809
|
+
filename: file,
|
|
18810
|
+
label: file.replace(/^\d+-/, "").replace(/\.\w+$/, ""),
|
|
18811
|
+
sortOrder: i,
|
|
18812
|
+
data: readFileSync3(join6(fullDir, file)).toString("base64")
|
|
18813
|
+
});
|
|
18814
|
+
}
|
|
18815
|
+
} catch {}
|
|
18816
|
+
}
|
|
18817
|
+
}
|
|
18818
|
+
const readmePath = join6(outDir, "README.md");
|
|
18819
|
+
const readme = existsSync5(readmePath) ? readFileSync3(readmePath, "utf-8") : `# Application Map
|
|
18820
|
+
|
|
18821
|
+
${visitedPages.length} pages explored.`;
|
|
18822
|
+
const payload = {
|
|
18823
|
+
title: `Zefiro Scan — ${new Date().toISOString().split("T")[0]}`,
|
|
18824
|
+
readme,
|
|
18825
|
+
sections,
|
|
18826
|
+
graph,
|
|
18827
|
+
screenshots,
|
|
18828
|
+
commitSha: commitSha || undefined
|
|
18829
|
+
};
|
|
18830
|
+
const res = await fetch(`${url}/api/v2/push-report`, {
|
|
18831
|
+
method: "POST",
|
|
18832
|
+
headers: {
|
|
18833
|
+
"Content-Type": "application/json",
|
|
18834
|
+
Authorization: `Bearer ${apiKey}`
|
|
18835
|
+
},
|
|
18836
|
+
body: JSON.stringify(payload)
|
|
18837
|
+
});
|
|
18838
|
+
if (!res.ok) {
|
|
18839
|
+
const body = await res.text();
|
|
18840
|
+
return { content: [{ type: "text", text: `Push failed (${res.status}): ${body}` }], isError: true };
|
|
18841
|
+
}
|
|
18842
|
+
const result = await res.json();
|
|
18843
|
+
return {
|
|
18844
|
+
content: [{
|
|
18845
|
+
type: "text",
|
|
18846
|
+
text: JSON.stringify(result, null, 2)
|
|
18847
|
+
}]
|
|
18848
|
+
};
|
|
18849
|
+
} catch (err) {
|
|
18850
|
+
return { content: [{ type: "text", text: `Error pushing report: ${err.message}` }], isError: true };
|
|
18851
|
+
}
|
|
18852
|
+
});
|
|
18677
18853
|
server.registerTool("zefiro_copilot_start", {
|
|
18678
18854
|
title: "Start Copilot Session",
|
|
18679
18855
|
description: "Start an interactive copilot session. Launches a browser and creates a session. " + "Returns a session_id to use with all other copilot tools.",
|
|
18680
18856
|
inputSchema: exports_external.object({
|
|
18681
18857
|
baseUrl: exports_external.string().describe("Base URL of the application (e.g., http://localhost:3000)"),
|
|
18682
18858
|
mode: exports_external.enum(["auto", "assist", "manual"]).optional().describe("Copilot mode: auto (AI drives), assist (AI proposes, human approves), manual (human drives)"),
|
|
18859
|
+
browser: exports_external.enum(["playwright", "chrome"]).optional().describe('Browser engine: "playwright" (default, launches new browser) or "chrome" (companion-only, use with Claude-in-Chrome)'),
|
|
18683
18860
|
headed: exports_external.boolean().optional().describe("Show browser window (default: true)"),
|
|
18684
18861
|
authState: exports_external.string().optional().describe("Path to Playwright auth state JSON file"),
|
|
18685
18862
|
outputDir: exports_external.string().optional().describe("Output directory for report (default: copilot-report)")
|
|
@@ -18877,6 +19054,24 @@ server.registerTool("zefiro_copilot_propose_action", {
|
|
|
18877
19054
|
return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
|
|
18878
19055
|
}
|
|
18879
19056
|
});
|
|
19057
|
+
server.registerTool("zefiro_copilot_track", {
|
|
19058
|
+
title: "Track Chrome Action",
|
|
19059
|
+
description: "Track a browser action performed via external browser (e.g., Claude-in-Chrome). " + "Syncs the action to the companion UI and session log. Use after each chrome tool call.",
|
|
19060
|
+
inputSchema: exports_external.object({
|
|
19061
|
+
session_id: exports_external.string().describe("Session ID"),
|
|
19062
|
+
action: exports_external.string().describe('Description of the action (e.g., "navigate: https://example.com", "click: Submit button")'),
|
|
19063
|
+
url: exports_external.string().optional().describe("Current page URL after the action (updates companion page display)"),
|
|
19064
|
+
title: exports_external.string().optional().describe("Current page title"),
|
|
19065
|
+
result: exports_external.string().optional().describe("Action result or details")
|
|
19066
|
+
})
|
|
19067
|
+
}, async (params) => {
|
|
19068
|
+
try {
|
|
19069
|
+
const result = await handleCopilotTrack(params);
|
|
19070
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
19071
|
+
} catch (err) {
|
|
19072
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
|
|
19073
|
+
}
|
|
19074
|
+
});
|
|
18880
19075
|
async function main() {
|
|
18881
19076
|
const transport = new StdioServerTransport;
|
|
18882
19077
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zefiro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"zefiro": "./dist/cli.js",
|
|
@@ -29,20 +29,16 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@inquirer/prompts": "^8.3.0",
|
|
31
31
|
"@qai/cli-auth": "workspace:*",
|
|
32
|
+
"@types/ws": "^8.18.1",
|
|
32
33
|
"@types/node": "^24.0.14",
|
|
33
|
-
"@types/react": "^18",
|
|
34
34
|
"bun-types": "^1.3.11",
|
|
35
35
|
"commander": "^13.1.0",
|
|
36
|
-
"ink": "^5",
|
|
37
|
-
"ink-text-input": "^6",
|
|
38
36
|
"picocolors": "^1.1.1",
|
|
39
|
-
"react": "^18",
|
|
40
37
|
"typescript": "^5.8.3",
|
|
41
38
|
"zod": "^4.0.5"
|
|
42
39
|
},
|
|
43
40
|
"dependencies": {
|
|
44
41
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
45
|
-
"@types/ws": "^8.18.1",
|
|
46
42
|
"ws": "^8.20.0"
|
|
47
43
|
}
|
|
48
44
|
}
|