From 319b4d02a0abcdf479607892791bec52a2ed6ae5 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 22 Jan 2026 06:39:19 +0000 Subject: [PATCH] fix: load workspace templates from docs --- src/agents/workspace.ts | 162 +++------------------------------------- 1 file changed, 12 insertions(+), 150 deletions(-) diff --git a/src/agents/workspace.ts b/src/agents/workspace.ts index bba81d4c7..cf1de7daf 100644 --- a/src/agents/workspace.ts +++ b/src/agents/workspace.ts @@ -4,7 +4,6 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; import { isSubagentSessionKey } from "../routing/session-key.js"; -import { formatCliCommand } from "../cli/command-format.js"; import { resolveUserPath } from "../utils.js"; export function resolveDefaultAgentWorkspaceDir( @@ -27,142 +26,9 @@ export const DEFAULT_USER_FILENAME = "USER.md"; export const DEFAULT_HEARTBEAT_FILENAME = "HEARTBEAT.md"; export const DEFAULT_BOOTSTRAP_FILENAME = "BOOTSTRAP.md"; -const DEFAULT_AGENTS_TEMPLATE = `# AGENTS.md - Clawdbot Workspace - -This folder is the assistant's working directory. - -## First run (one-time) -- If BOOTSTRAP.md exists, follow its ritual and delete it once complete. -- Your agent identity lives in IDENTITY.md. -- Your profile lives in USER.md. - -## Backup tip (recommended) -If you treat this workspace as the agent's "memory", make it a git repo (ideally private) so identity -and notes are backed up. - -\`\`\`bash -git init -git add AGENTS.md -git commit -m "Add agent workspace" -\`\`\` - -## Safety defaults -- Don't exfiltrate secrets or private data. -- Don't run destructive commands unless explicitly asked. -- Be concise in chat; write longer output to files in this workspace. - -## Daily memory (recommended) -- Keep a short daily log at memory/YYYY-MM-DD.md (create memory/ if needed). -- On session start, read today + yesterday if present. -- Capture durable facts, preferences, and decisions; avoid secrets. - -## Heartbeats (optional) -- HEARTBEAT.md can hold a tiny checklist for heartbeat runs; keep it small. - -## Customize -- Add your preferred style, rules, and "memory" here. -`; - -const DEFAULT_SOUL_TEMPLATE = `# SOUL.md - Persona & Boundaries - -Describe who the assistant is, tone, and boundaries. - -- Keep replies concise and direct. -- Ask clarifying questions when needed. -- Never send streaming/partial replies to external messaging surfaces. -`; - -const DEFAULT_TOOLS_TEMPLATE = `# TOOLS.md - User Tool Notes (editable) - -This file is for *your* notes about external tools and conventions. -It does not define which tools exist; Clawdbot provides built-in tools internally. - -## Examples - -### imsg -- Send an iMessage/SMS: describe who/what, confirm before sending. -- Prefer short messages; avoid sending secrets. - -### sag -- Text-to-speech: specify voice, target speaker/room, and whether to stream. - -Add whatever else you want the assistant to know about your local toolchain. -`; - -const DEFAULT_HEARTBEAT_TEMPLATE = `# HEARTBEAT.md - -Optional: keep a tiny checklist for heartbeat runs. - -Guidance (to avoid nagging): -- Only report items that are truly new or changed. -- Do not invent tasks from old chat context. -- If nothing needs attention, reply HEARTBEAT_OK. -`; - -const DEFAULT_BOOTSTRAP_TEMPLATE = `# BOOTSTRAP.md - First Run Ritual (delete after) - -Hello. I was just born. - -## Your mission -Start a short, playful conversation and learn: -- Who am I? -- What am I? -- Who are you? -- How should I call you? - -## How to ask (cute + helpful) -Say: -"Hello! I was just born. Who am I? What am I? Who are you? How should I call you?" - -Then offer suggestions: -- 3-5 name ideas. -- 3-5 creature/vibe combos. -- 5 emoji ideas. - -## Write these files -After the user chooses, update: - -1) IDENTITY.md -- Name -- Creature -- Vibe -- Emoji - -2) USER.md -- Name -- Preferred address -- Pronouns (optional) -- Timezone (optional) -- Notes - -3) ~/.clawdbot/clawdbot.json -Run: ${formatCliCommand('clawdbot agents set-identity --workspace "" --from-identity')} -If multiple agents share a host, add --agent . - -## Cleanup -Delete BOOTSTRAP.md once this is complete. -`; - -const DEFAULT_IDENTITY_TEMPLATE = `# IDENTITY.md - Agent Identity - -- Name: -- Creature: -- Vibe: -- Emoji: -`; - -const DEFAULT_USER_TEMPLATE = `# USER.md - User Profile - -- Name: -- Preferred address: -- Pronouns (optional): -- Timezone (optional): -- Notes: -`; - const TEMPLATE_DIR = path.resolve( path.dirname(fileURLToPath(import.meta.url)), - "../../docs/templates", + "../../docs/reference/templates", ); function stripFrontMatter(content: string): string { @@ -175,13 +41,15 @@ function stripFrontMatter(content: string): string { return trimmed; } -async function loadTemplate(name: string, fallback: string): Promise { +async function loadTemplate(name: string): Promise { const templatePath = path.join(TEMPLATE_DIR, name); try { const content = await fs.readFile(templatePath, "utf-8"); return stripFrontMatter(content); } catch { - return fallback; + throw new Error( + `Missing workspace template: ${name} (${templatePath}). Ensure docs/reference/templates are packaged.`, + ); } } @@ -255,19 +123,13 @@ export async function ensureAgentWorkspace(params?: { return existing.every((v) => !v); })(); - const agentsTemplate = await loadTemplate(DEFAULT_AGENTS_FILENAME, DEFAULT_AGENTS_TEMPLATE); - const soulTemplate = await loadTemplate(DEFAULT_SOUL_FILENAME, DEFAULT_SOUL_TEMPLATE); - const toolsTemplate = await loadTemplate(DEFAULT_TOOLS_FILENAME, DEFAULT_TOOLS_TEMPLATE); - const identityTemplate = await loadTemplate(DEFAULT_IDENTITY_FILENAME, DEFAULT_IDENTITY_TEMPLATE); - const userTemplate = await loadTemplate(DEFAULT_USER_FILENAME, DEFAULT_USER_TEMPLATE); - const heartbeatTemplate = await loadTemplate( - DEFAULT_HEARTBEAT_FILENAME, - DEFAULT_HEARTBEAT_TEMPLATE, - ); - const bootstrapTemplate = await loadTemplate( - DEFAULT_BOOTSTRAP_FILENAME, - DEFAULT_BOOTSTRAP_TEMPLATE, - ); + const agentsTemplate = await loadTemplate(DEFAULT_AGENTS_FILENAME); + const soulTemplate = await loadTemplate(DEFAULT_SOUL_FILENAME); + const toolsTemplate = await loadTemplate(DEFAULT_TOOLS_FILENAME); + const identityTemplate = await loadTemplate(DEFAULT_IDENTITY_FILENAME); + const userTemplate = await loadTemplate(DEFAULT_USER_FILENAME); + const heartbeatTemplate = await loadTemplate(DEFAULT_HEARTBEAT_FILENAME); + const bootstrapTemplate = await loadTemplate(DEFAULT_BOOTSTRAP_FILENAME); await writeFileIfMissing(agentsPath, agentsTemplate); await writeFileIfMissing(soulPath, soulTemplate);