86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
/**
|
|
* LLM-based slug generator for session memory filenames
|
|
*/
|
|
|
|
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import {
|
|
resolveDefaultAgentId,
|
|
resolveAgentWorkspaceDir,
|
|
resolveAgentDir,
|
|
} from "../agents/agent-scope.js";
|
|
import { runEmbeddedPiAgent } from "../agents/pi-embedded.js";
|
|
import type { OpenClawConfig } from "../config/config.js";
|
|
|
|
/**
|
|
* Generate a short 1-2 word filename slug from session content using LLM
|
|
*/
|
|
export async function generateSlugViaLLM(params: {
|
|
sessionContent: string;
|
|
cfg: OpenClawConfig;
|
|
}): Promise<string | null> {
|
|
let tempSessionFile: string | null = null;
|
|
|
|
try {
|
|
const agentId = resolveDefaultAgentId(params.cfg);
|
|
const workspaceDir = resolveAgentWorkspaceDir(params.cfg, agentId);
|
|
const agentDir = resolveAgentDir(params.cfg, agentId);
|
|
|
|
// Create a temporary session file for this one-off LLM call
|
|
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-slug-"));
|
|
tempSessionFile = path.join(tempDir, "session.jsonl");
|
|
|
|
const prompt = `Based on this conversation, generate a short 1-2 word filename slug (lowercase, hyphen-separated, no file extension).
|
|
|
|
Conversation summary:
|
|
${params.sessionContent.slice(0, 2000)}
|
|
|
|
Reply with ONLY the slug, nothing else. Examples: "vendor-pitch", "api-design", "bug-fix"`;
|
|
|
|
const result = await runEmbeddedPiAgent({
|
|
sessionId: `slug-generator-${Date.now()}`,
|
|
sessionKey: "temp:slug-generator",
|
|
agentId,
|
|
sessionFile: tempSessionFile,
|
|
workspaceDir,
|
|
agentDir,
|
|
config: params.cfg,
|
|
prompt,
|
|
timeoutMs: 15_000, // 15 second timeout
|
|
runId: `slug-gen-${Date.now()}`,
|
|
});
|
|
|
|
// Extract text from payloads
|
|
if (result.payloads && result.payloads.length > 0) {
|
|
const text = result.payloads[0]?.text;
|
|
if (text) {
|
|
// Clean up the response - extract just the slug
|
|
const slug = text
|
|
.trim()
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9-]/g, "-")
|
|
.replace(/-+/g, "-")
|
|
.replace(/^-|-$/g, "")
|
|
.slice(0, 30); // Max 30 chars
|
|
|
|
return slug || null;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
} catch (err) {
|
|
console.error("[llm-slug-generator] Failed to generate slug:", err);
|
|
return null;
|
|
} finally {
|
|
// Clean up temporary session file
|
|
if (tempSessionFile) {
|
|
try {
|
|
await fs.rm(path.dirname(tempSessionFile), { recursive: true, force: true });
|
|
} catch {
|
|
// Ignore cleanup errors
|
|
}
|
|
}
|
|
}
|
|
}
|