diff --git a/src/auto-reply/reply/commands-context-report.ts b/src/auto-reply/reply/commands-context-report.ts index 4e3a6cf1788..b9a1130e521 100644 --- a/src/auto-reply/reply/commands-context-report.ts +++ b/src/auto-reply/reply/commands-context-report.ts @@ -1,23 +1,12 @@ import type { SessionSystemPromptReport } from "../../config/sessions/types.js"; import type { ReplyPayload } from "../types.js"; import type { HandleCommandsParams } from "./commands-types.js"; -import { resolveSessionAgentIds } from "../../agents/agent-scope.js"; -import { resolveBootstrapContextForRun } from "../../agents/bootstrap-files.js"; -import { resolveDefaultModelForAgent } from "../../agents/model-selection.js"; import { resolveBootstrapMaxChars, resolveBootstrapTotalMaxChars, } from "../../agents/pi-embedded-helpers.js"; -import { createOpenClawCodingTools } from "../../agents/pi-tools.js"; -import { resolveSandboxRuntimeStatus } from "../../agents/sandbox.js"; -import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js"; -import { getSkillsSnapshotVersion } from "../../agents/skills/refresh.js"; -import { buildSystemPromptParams } from "../../agents/system-prompt-params.js"; import { buildSystemPromptReport } from "../../agents/system-prompt-report.js"; -import { buildAgentSystemPrompt } from "../../agents/system-prompt.js"; -import { buildToolSummaryMap } from "../../agents/tool-summaries.js"; -import { getRemoteSkillEligibility } from "../../infra/skills-remote.js"; -import { buildTtsSystemPromptHint } from "../../tts/tts.js"; +import { resolveCommandsSystemPromptBundle } from "./commands-system-prompt.js"; function estimateTokensFromChars(chars: number): number { return Math.ceil(Math.max(0, chars) / 4); @@ -60,109 +49,10 @@ async function resolveContextReport( return existing; } - const workspaceDir = params.workspaceDir; const bootstrapMaxChars = resolveBootstrapMaxChars(params.cfg); const bootstrapTotalMaxChars = resolveBootstrapTotalMaxChars(params.cfg); - const { bootstrapFiles, contextFiles: injectedFiles } = await resolveBootstrapContextForRun({ - workspaceDir, - config: params.cfg, - sessionKey: params.sessionKey, - sessionId: params.sessionEntry?.sessionId, - }); - const skillsSnapshot = (() => { - try { - return buildWorkspaceSkillSnapshot(workspaceDir, { - config: params.cfg, - eligibility: { remote: getRemoteSkillEligibility() }, - snapshotVersion: getSkillsSnapshotVersion(workspaceDir), - }); - } catch { - return { prompt: "", skills: [], resolvedSkills: [] }; - } - })(); - const skillsPrompt = skillsSnapshot.prompt ?? ""; - const sandboxRuntime = resolveSandboxRuntimeStatus({ - cfg: params.cfg, - sessionKey: params.ctx.SessionKey ?? params.sessionKey, - }); - const tools = (() => { - try { - return createOpenClawCodingTools({ - config: params.cfg, - workspaceDir, - sessionKey: params.sessionKey, - messageProvider: params.command.channel, - groupId: params.sessionEntry?.groupId ?? undefined, - groupChannel: params.sessionEntry?.groupChannel ?? undefined, - groupSpace: params.sessionEntry?.space ?? undefined, - spawnedBy: params.sessionEntry?.spawnedBy ?? undefined, - senderIsOwner: params.command.senderIsOwner, - modelProvider: params.provider, - modelId: params.model, - }); - } catch { - return []; - } - })(); - const toolSummaries = buildToolSummaryMap(tools); - const toolNames = tools.map((t) => t.name); - const { sessionAgentId } = resolveSessionAgentIds({ - sessionKey: params.sessionKey, - config: params.cfg, - }); - const defaultModelRef = resolveDefaultModelForAgent({ - cfg: params.cfg, - agentId: sessionAgentId, - }); - const defaultModelLabel = `${defaultModelRef.provider}/${defaultModelRef.model}`; - const { runtimeInfo, userTimezone, userTime, userTimeFormat } = buildSystemPromptParams({ - config: params.cfg, - agentId: sessionAgentId, - workspaceDir, - cwd: process.cwd(), - runtime: { - host: "unknown", - os: "unknown", - arch: "unknown", - node: process.version, - model: `${params.provider}/${params.model}`, - defaultModel: defaultModelLabel, - }, - }); - const sandboxInfo = sandboxRuntime.sandboxed - ? { - enabled: true, - workspaceDir, - workspaceAccess: "rw" as const, - elevated: { - allowed: params.elevated.allowed, - defaultLevel: (params.resolvedElevatedLevel ?? "off") as "on" | "off" | "ask" | "full", - }, - } - : { enabled: false }; - const ttsHint = params.cfg ? buildTtsSystemPromptHint(params.cfg) : undefined; - - const systemPrompt = buildAgentSystemPrompt({ - workspaceDir, - defaultThinkLevel: params.resolvedThinkLevel, - reasoningLevel: params.resolvedReasoningLevel, - extraSystemPrompt: undefined, - ownerNumbers: undefined, - reasoningTagHint: false, - toolNames, - toolSummaries, - modelAliasLines: [], - userTimezone, - userTime, - userTimeFormat, - contextFiles: injectedFiles, - skillsPrompt, - heartbeatPrompt: undefined, - ttsHint, - runtimeInfo, - sandboxInfo, - memoryCitationsMode: params.cfg?.memory?.citations, - }); + const { systemPrompt, tools, skillsPrompt, bootstrapFiles, injectedFiles, sandboxRuntime } = + await resolveCommandsSystemPromptBundle(params); return buildSystemPromptReport({ source: "estimate", @@ -171,7 +61,7 @@ async function resolveContextReport( sessionKey: params.sessionKey, provider: params.provider, model: params.model, - workspaceDir, + workspaceDir: params.workspaceDir, bootstrapMaxChars, bootstrapTotalMaxChars, sandbox: { mode: sandboxRuntime.mode, sandboxed: sandboxRuntime.sandboxed }, diff --git a/src/auto-reply/reply/commands-export-session.ts b/src/auto-reply/reply/commands-export-session.ts index 16e2bbc4ca3..a87368985db 100644 --- a/src/auto-reply/reply/commands-export-session.ts +++ b/src/auto-reply/reply/commands-export-session.ts @@ -1,4 +1,3 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; import type { SessionEntry as PiSessionEntry, SessionHeader } from "@mariozechner/pi-coding-agent"; import { SessionManager } from "@mariozechner/pi-coding-agent"; import fs from "node:fs"; @@ -7,24 +6,13 @@ import { fileURLToPath } from "node:url"; import type { SessionEntry } from "../../config/sessions/types.js"; import type { ReplyPayload } from "../types.js"; import type { HandleCommandsParams } from "./commands-types.js"; -import { resolveSessionAgentIds } from "../../agents/agent-scope.js"; -import { resolveBootstrapContextForRun } from "../../agents/bootstrap-files.js"; -import { resolveDefaultModelForAgent } from "../../agents/model-selection.js"; -import { createOpenClawCodingTools } from "../../agents/pi-tools.js"; -import { resolveSandboxRuntimeStatus } from "../../agents/sandbox.js"; -import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js"; -import { getSkillsSnapshotVersion } from "../../agents/skills/refresh.js"; -import { buildSystemPromptParams } from "../../agents/system-prompt-params.js"; -import { buildAgentSystemPrompt } from "../../agents/system-prompt.js"; -import { buildToolSummaryMap } from "../../agents/tool-summaries.js"; import { resolveDefaultSessionStorePath, resolveSessionFilePath, } from "../../config/sessions/paths.js"; import { loadSessionStore } from "../../config/sessions/store.js"; -import { getRemoteSkillEligibility } from "../../infra/skills-remote.js"; -import { buildTtsSystemPromptHint } from "../../tts/tts.js"; import { resolveUserPath } from "../../utils.js"; +import { resolveCommandsSystemPromptBundle } from "./commands-system-prompt.js"; // Export HTML templates are bundled with this module const EXPORT_HTML_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), "export-html"); @@ -110,115 +98,6 @@ function generateHtml(sessionData: SessionData): string { .replace("{{HIGHLIGHT_JS}}", hljsJs); } -async function resolveFullSystemPrompt(params: HandleCommandsParams): Promise<{ - systemPrompt: string; - tools: AgentTool[]; -}> { - const workspaceDir = params.workspaceDir; - const { contextFiles: injectedFiles } = await resolveBootstrapContextForRun({ - workspaceDir, - config: params.cfg, - sessionKey: params.sessionKey, - sessionId: params.sessionEntry?.sessionId, - }); - const skillsSnapshot = (() => { - try { - return buildWorkspaceSkillSnapshot(workspaceDir, { - config: params.cfg, - eligibility: { remote: getRemoteSkillEligibility() }, - snapshotVersion: getSkillsSnapshotVersion(workspaceDir), - }); - } catch { - return { prompt: "", skills: [], resolvedSkills: [] }; - } - })(); - const skillsPrompt = skillsSnapshot.prompt ?? ""; - const sandboxRuntime = resolveSandboxRuntimeStatus({ - cfg: params.cfg, - sessionKey: params.ctx.SessionKey ?? params.sessionKey, - }); - const tools = (() => { - try { - return createOpenClawCodingTools({ - config: params.cfg, - workspaceDir, - sessionKey: params.sessionKey, - messageProvider: params.command.channel, - groupId: params.sessionEntry?.groupId ?? undefined, - groupChannel: params.sessionEntry?.groupChannel ?? undefined, - groupSpace: params.sessionEntry?.space ?? undefined, - spawnedBy: params.sessionEntry?.spawnedBy ?? undefined, - senderIsOwner: params.command.senderIsOwner, - modelProvider: params.provider, - modelId: params.model, - }); - } catch { - return []; - } - })(); - const toolSummaries = buildToolSummaryMap(tools); - const toolNames = tools.map((t) => t.name); - const { sessionAgentId } = resolveSessionAgentIds({ - sessionKey: params.sessionKey, - config: params.cfg, - }); - const defaultModelRef = resolveDefaultModelForAgent({ - cfg: params.cfg, - agentId: sessionAgentId, - }); - const defaultModelLabel = `${defaultModelRef.provider}/${defaultModelRef.model}`; - const { runtimeInfo, userTimezone, userTime, userTimeFormat } = buildSystemPromptParams({ - config: params.cfg, - agentId: sessionAgentId, - workspaceDir, - cwd: process.cwd(), - runtime: { - host: "unknown", - os: "unknown", - arch: "unknown", - node: process.version, - model: `${params.provider}/${params.model}`, - defaultModel: defaultModelLabel, - }, - }); - const sandboxInfo = sandboxRuntime.sandboxed - ? { - enabled: true, - workspaceDir, - workspaceAccess: "rw" as const, - elevated: { - allowed: params.elevated.allowed, - defaultLevel: (params.resolvedElevatedLevel ?? "off") as "on" | "off" | "ask" | "full", - }, - } - : { enabled: false }; - const ttsHint = params.cfg ? buildTtsSystemPromptHint(params.cfg) : undefined; - - const systemPrompt = buildAgentSystemPrompt({ - workspaceDir, - defaultThinkLevel: params.resolvedThinkLevel, - reasoningLevel: params.resolvedReasoningLevel, - extraSystemPrompt: undefined, - ownerNumbers: undefined, - reasoningTagHint: false, - toolNames, - toolSummaries, - modelAliasLines: [], - userTimezone, - userTime, - userTimeFormat, - contextFiles: injectedFiles, - skillsPrompt, - heartbeatPrompt: undefined, - ttsHint, - runtimeInfo, - sandboxInfo, - memoryCitationsMode: params.cfg?.memory?.citations, - }); - - return { systemPrompt, tools }; -} - function parseExportArgs(commandBodyNormalized: string): { outputPath?: string } { const normalized = commandBodyNormalized.trim(); if (normalized === "/export-session" || normalized === "/export") { @@ -269,7 +148,7 @@ export async function buildExportSessionReply(params: HandleCommandsParams): Pro const leafId = sessionManager.getLeafId(); // 3. Build full system prompt - const { systemPrompt, tools } = await resolveFullSystemPrompt(params); + const { systemPrompt, tools } = await resolveCommandsSystemPromptBundle(params); // 4. Prepare session data const sessionData: SessionData = { diff --git a/src/auto-reply/reply/commands-system-prompt.ts b/src/auto-reply/reply/commands-system-prompt.ts new file mode 100644 index 00000000000..19e98acaa4f --- /dev/null +++ b/src/auto-reply/reply/commands-system-prompt.ts @@ -0,0 +1,133 @@ +import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { EmbeddedContextFile } from "../../agents/pi-embedded-helpers.js"; +import type { WorkspaceBootstrapFile } from "../../agents/workspace.js"; +import type { HandleCommandsParams } from "./commands-types.js"; +import { resolveSessionAgentIds } from "../../agents/agent-scope.js"; +import { resolveBootstrapContextForRun } from "../../agents/bootstrap-files.js"; +import { resolveDefaultModelForAgent } from "../../agents/model-selection.js"; +import { createOpenClawCodingTools } from "../../agents/pi-tools.js"; +import { resolveSandboxRuntimeStatus } from "../../agents/sandbox.js"; +import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js"; +import { getSkillsSnapshotVersion } from "../../agents/skills/refresh.js"; +import { buildSystemPromptParams } from "../../agents/system-prompt-params.js"; +import { buildAgentSystemPrompt } from "../../agents/system-prompt.js"; +import { buildToolSummaryMap } from "../../agents/tool-summaries.js"; +import { getRemoteSkillEligibility } from "../../infra/skills-remote.js"; +import { buildTtsSystemPromptHint } from "../../tts/tts.js"; + +export type CommandsSystemPromptBundle = { + systemPrompt: string; + tools: AgentTool[]; + skillsPrompt: string; + bootstrapFiles: WorkspaceBootstrapFile[]; + injectedFiles: EmbeddedContextFile[]; + sandboxRuntime: ReturnType; +}; + +export async function resolveCommandsSystemPromptBundle( + params: HandleCommandsParams, +): Promise { + const workspaceDir = params.workspaceDir; + const { bootstrapFiles, contextFiles: injectedFiles } = await resolveBootstrapContextForRun({ + workspaceDir, + config: params.cfg, + sessionKey: params.sessionKey, + sessionId: params.sessionEntry?.sessionId, + }); + const skillsSnapshot = (() => { + try { + return buildWorkspaceSkillSnapshot(workspaceDir, { + config: params.cfg, + eligibility: { remote: getRemoteSkillEligibility() }, + snapshotVersion: getSkillsSnapshotVersion(workspaceDir), + }); + } catch { + return { prompt: "", skills: [], resolvedSkills: [] }; + } + })(); + const skillsPrompt = skillsSnapshot.prompt ?? ""; + const sandboxRuntime = resolveSandboxRuntimeStatus({ + cfg: params.cfg, + sessionKey: params.ctx.SessionKey ?? params.sessionKey, + }); + const tools = (() => { + try { + return createOpenClawCodingTools({ + config: params.cfg, + workspaceDir, + sessionKey: params.sessionKey, + messageProvider: params.command.channel, + groupId: params.sessionEntry?.groupId ?? undefined, + groupChannel: params.sessionEntry?.groupChannel ?? undefined, + groupSpace: params.sessionEntry?.space ?? undefined, + spawnedBy: params.sessionEntry?.spawnedBy ?? undefined, + senderIsOwner: params.command.senderIsOwner, + modelProvider: params.provider, + modelId: params.model, + }); + } catch { + return []; + } + })(); + const toolSummaries = buildToolSummaryMap(tools); + const toolNames = tools.map((t) => t.name); + const { sessionAgentId } = resolveSessionAgentIds({ + sessionKey: params.sessionKey, + config: params.cfg, + }); + const defaultModelRef = resolveDefaultModelForAgent({ + cfg: params.cfg, + agentId: sessionAgentId, + }); + const defaultModelLabel = `${defaultModelRef.provider}/${defaultModelRef.model}`; + const { runtimeInfo, userTimezone, userTime, userTimeFormat } = buildSystemPromptParams({ + config: params.cfg, + agentId: sessionAgentId, + workspaceDir, + cwd: process.cwd(), + runtime: { + host: "unknown", + os: "unknown", + arch: "unknown", + node: process.version, + model: `${params.provider}/${params.model}`, + defaultModel: defaultModelLabel, + }, + }); + const sandboxInfo = sandboxRuntime.sandboxed + ? { + enabled: true, + workspaceDir, + workspaceAccess: "rw" as const, + elevated: { + allowed: params.elevated.allowed, + defaultLevel: (params.resolvedElevatedLevel ?? "off") as "on" | "off" | "ask" | "full", + }, + } + : { enabled: false }; + const ttsHint = params.cfg ? buildTtsSystemPromptHint(params.cfg) : undefined; + + const systemPrompt = buildAgentSystemPrompt({ + workspaceDir, + defaultThinkLevel: params.resolvedThinkLevel, + reasoningLevel: params.resolvedReasoningLevel, + extraSystemPrompt: undefined, + ownerNumbers: undefined, + reasoningTagHint: false, + toolNames, + toolSummaries, + modelAliasLines: [], + userTimezone, + userTime, + userTimeFormat, + contextFiles: injectedFiles, + skillsPrompt, + heartbeatPrompt: undefined, + ttsHint, + runtimeInfo, + sandboxInfo, + memoryCitationsMode: params.cfg?.memory?.citations, + }); + + return { systemPrompt, tools, skillsPrompt, bootstrapFiles, injectedFiles, sandboxRuntime }; +}