| |
| |
| |
|
|
| import fs from "node:fs/promises"; |
| import os from "node:os"; |
| import path from "node:path"; |
| import { |
| resolveDefaultAgentId, |
| resolveAgentWorkspaceDir, |
| resolveAgentDir, |
| resolveAgentEffectiveModelPrimary, |
| } from "../agents/agent-scope.js"; |
| import { DEFAULT_PROVIDER, DEFAULT_MODEL } from "../agents/defaults.js"; |
| import { parseModelRef } from "../agents/model-selection.js"; |
| import { runEmbeddedPiAgent } from "../agents/pi-embedded.js"; |
| import type { OpenClawConfig } from "../config/config.js"; |
| import { createSubsystemLogger } from "../logging/subsystem.js"; |
|
|
| const log = createSubsystemLogger("llm-slug-generator"); |
|
|
| |
| |
| |
| 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); |
|
|
| |
| 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 modelRef = resolveAgentEffectiveModelPrimary(params.cfg, agentId); |
| const parsed = modelRef ? parseModelRef(modelRef, DEFAULT_PROVIDER) : null; |
| const provider = parsed?.provider ?? DEFAULT_PROVIDER; |
| const model = parsed?.model ?? DEFAULT_MODEL; |
|
|
| const result = await runEmbeddedPiAgent({ |
| sessionId: `slug-generator-${Date.now()}`, |
| sessionKey: "temp:slug-generator", |
| agentId, |
| sessionFile: tempSessionFile, |
| workspaceDir, |
| agentDir, |
| config: params.cfg, |
| prompt, |
| provider, |
| model, |
| timeoutMs: 15_000, |
| runId: `slug-gen-${Date.now()}`, |
| }); |
|
|
| |
| if (result.payloads && result.payloads.length > 0) { |
| const text = result.payloads[0]?.text; |
| if (text) { |
| |
| const slug = text |
| .trim() |
| .toLowerCase() |
| .replace(/[^a-z0-9-]/g, "-") |
| .replace(/-+/g, "-") |
| .replace(/^-|-$/g, "") |
| .slice(0, 30); |
|
|
| return slug || null; |
| } |
| } |
|
|
| return null; |
| } catch (err) { |
| const message = err instanceof Error ? (err.stack ?? err.message) : String(err); |
| log.error(`Failed to generate slug: ${message}`); |
| return null; |
| } finally { |
| |
| if (tempSessionFile) { |
| try { |
| await fs.rm(path.dirname(tempSessionFile), { recursive: true, force: true }); |
| } catch { |
| |
| } |
| } |
| } |
| } |
|
|