feat(recorder): aggiunti tool di registrazione e analisi attivita BiDi (JSONL)
This commit is contained in:
@@ -720,6 +720,159 @@ export default function (pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Registrazione e analisi attività di navigazione (Activity Recorder JSONL)
|
||||
// -------------------------------------------------------------------------
|
||||
pi.registerTool({
|
||||
name: "browser_record_start",
|
||||
label: "Browser Record Start",
|
||||
description:
|
||||
"Avvia o riconfigura la registrazione continua degli eventi e delle attività di navigazione " +
|
||||
"(URL, domini, navigazioni, caricamento DOM, errori e log di console) su un file JSONL.",
|
||||
parameters: Type.Object({
|
||||
path: Type.Optional(
|
||||
Type.String({
|
||||
description:
|
||||
"Percorso assoluto del file JSONL (default: ~/.local/state/pi-firefox-bidi/activity.jsonl)",
|
||||
}),
|
||||
),
|
||||
events: Type.Optional(
|
||||
Type.Array(Type.String(), {
|
||||
description: "Lista di eventi BiDi da registrare (opzionale)",
|
||||
}),
|
||||
),
|
||||
}),
|
||||
async execute(_id, params) {
|
||||
await ensureBridge();
|
||||
const r = await bridge("/recorder/start", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Registrazione attività attiva su file: ${r.file}`,
|
||||
},
|
||||
],
|
||||
details: r,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerTool({
|
||||
name: "browser_record_stop",
|
||||
label: "Browser Record Stop",
|
||||
description: "Sospende la registrazione delle attività di navigazione su file.",
|
||||
parameters: Type.Object({}),
|
||||
async execute() {
|
||||
await ensureBridge();
|
||||
const r = await bridge("/recorder/stop", { method: "POST" });
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Registrazione attività sospesa. Eventi totali registrati: ${r.totalEvents} (${r.file})`,
|
||||
},
|
||||
],
|
||||
details: r,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerTool({
|
||||
name: "browser_record_status",
|
||||
label: "Browser Record Status",
|
||||
description: "Mostra lo stato del registratore attività, il percorso del file JSONL e il numero di eventi.",
|
||||
parameters: Type.Object({}),
|
||||
async execute() {
|
||||
await ensureBridge();
|
||||
const r = await bridge("/recorder/status");
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(r, null, 2) }],
|
||||
details: r,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerTool({
|
||||
name: "browser_record_get",
|
||||
label: "Browser Record Get",
|
||||
description:
|
||||
"Recupera le attività di navigazione registrate dal file JSONL per analisi (formato compatto o JSON grezzo).",
|
||||
parameters: Type.Object({
|
||||
limit: Type.Optional(
|
||||
Type.Number({ description: "Numero massimo di eventi recenti da recuperare (default 30)", default: 30 }),
|
||||
),
|
||||
format: Type.Optional(
|
||||
Type.Enum(
|
||||
{ summary: "summary", json: "json" },
|
||||
{ description: "Formato: 'summary' (timeline compatta) o 'json' (oggetti completi)", default: "summary" },
|
||||
),
|
||||
),
|
||||
}),
|
||||
async execute(_id, params) {
|
||||
await ensureBridge();
|
||||
const r = await bridge("/recorder/get", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ limit: params.limit ?? 30 }),
|
||||
});
|
||||
const records: any[] = r.records ?? [];
|
||||
if (params.format === "json") {
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(r, null, 2) }],
|
||||
details: r,
|
||||
};
|
||||
}
|
||||
|
||||
if (records.length === 0) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Nessuna attività registrata nel log (${r.file}).` }],
|
||||
details: r,
|
||||
};
|
||||
}
|
||||
|
||||
const lines = records.map((rec) => {
|
||||
const timeStr = rec.timestamp ? rec.timestamp.split("T")[1]?.slice(0, 8) : "--:--:--";
|
||||
if (rec.event === "navigation_started") {
|
||||
return `[${timeStr}] 🌐 Navigazione: ${rec.url} (dominio: ${rec.domain ?? "-"})`;
|
||||
} else if (rec.event === "page_loaded") {
|
||||
return `[${timeStr}] ⏱ Caricato: ${rec.url ?? ""} in ${rec.durationMs ?? "?"}ms`;
|
||||
} else if (rec.event === "dom_ready") {
|
||||
return `[${timeStr}] 📄 DOM Ready: ${rec.url ?? ""}`;
|
||||
} else if (rec.event === "console_log") {
|
||||
return `[${timeStr}] 💬 [Console ${rec.level ?? "log"}]: ${rec.text ?? ""}`;
|
||||
}
|
||||
return `[${timeStr}] ⚡ ${rec.event}: ${rec.url ?? JSON.stringify(rec)}`;
|
||||
});
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Ultime ${records.length} attività registrate (${r.file}):\n\n` + lines.join("\n"),
|
||||
},
|
||||
],
|
||||
details: r,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerTool({
|
||||
name: "browser_record_clear",
|
||||
label: "Browser Record Clear",
|
||||
description: "Svuota il file di log delle attività e azzera il contatore.",
|
||||
parameters: Type.Object({}),
|
||||
async execute() {
|
||||
await ensureBridge();
|
||||
const r = await bridge("/recorder/clear", { method: "POST" });
|
||||
return {
|
||||
content: [{ type: "text", text: "Log attività svuotato con successo." }],
|
||||
details: r,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Notifica asincrona (agy/bridge → pi): webhook locale
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user