71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
import type MemoryClient from "mem0ai";
|
|
import type { Mem0Config, ScopeContext } from "../types.ts";
|
|
import { DEFAULT_CUSTOM_CATEGORIES } from "../types.ts";
|
|
import { resolveAddParams } from "../memory/scoping.ts";
|
|
import { captureEvent } from "../telemetry.ts";
|
|
|
|
interface MessageLike {
|
|
role: string;
|
|
content?: unknown;
|
|
}
|
|
|
|
function extractText(content: unknown): string | null {
|
|
if (typeof content === "string") return content;
|
|
if (Array.isArray(content)) {
|
|
const texts = content
|
|
.filter((b: any) => b.type === "text" && typeof b.text === "string")
|
|
.map((b: any) => b.text);
|
|
return texts.length > 0 ? texts.join("\n") : null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function extractConversation(
|
|
messages: MessageLike[],
|
|
): Array<{ role: "user" | "assistant"; content: string }> {
|
|
const result: Array<{ role: "user" | "assistant"; content: string }> = [];
|
|
|
|
for (const msg of messages) {
|
|
if (msg.role !== "user" && msg.role !== "assistant") continue;
|
|
const text = extractText(msg.content);
|
|
if (!text) continue;
|
|
result.push({ role: msg.role as "user" | "assistant", content: text });
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function setupAutoCapture(
|
|
pi: ExtensionAPI,
|
|
mem0: MemoryClient,
|
|
config: Mem0Config,
|
|
getScopeCtx: () => ScopeContext,
|
|
telemetryCtx?: { apiKey?: string },
|
|
): void {
|
|
if (!config.autoCapture) return;
|
|
|
|
pi.on("agent_end", async (event) => {
|
|
const messages = event.messages ?? [];
|
|
const conversation = extractConversation(messages);
|
|
if (conversation.length === 0) return;
|
|
|
|
const scopeCtx = getScopeCtx();
|
|
const addParams = resolveAddParams("project", scopeCtx);
|
|
|
|
try {
|
|
await mem0.add(conversation, {
|
|
...addParams,
|
|
customCategories: DEFAULT_CUSTOM_CATEGORIES,
|
|
});
|
|
captureEvent("pi.capture.auto", { success: true, message_count: conversation.length }, telemetryCtx);
|
|
} catch (err: unknown) {
|
|
captureEvent("pi.capture.auto", {
|
|
success: false,
|
|
error_type: err instanceof Error ? err.name : "unknown",
|
|
}, telemetryCtx);
|
|
console.error("[mem0] auto-capture failed:", err);
|
|
}
|
|
});
|
|
}
|