feat(templates): centralize workspace templates
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
|
||||
@@ -9,21 +10,35 @@ export const DEFAULT_AGENTS_FILENAME = "AGENTS.md";
|
||||
export const DEFAULT_SOUL_FILENAME = "SOUL.md";
|
||||
export const DEFAULT_TOOLS_FILENAME = "TOOLS.md";
|
||||
|
||||
const DEFAULT_AGENTS_TEMPLATE = `# AGENTS.md — Clawdis Workspace
|
||||
const DEFAULT_AGENTS_TEMPLATE = `# AGENTS.md - Clawdis Workspace
|
||||
|
||||
This folder is the assistant’s working directory.
|
||||
This folder is the assistant's working directory.
|
||||
|
||||
## 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.
|
||||
- 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.
|
||||
|
||||
## How to use this
|
||||
- Put project notes, scratch files, and “memory” here.
|
||||
- Customize this file with additional instructions for your assistant.
|
||||
## 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.
|
||||
|
||||
## Customize
|
||||
- Add your preferred style, rules, and "memory" here.
|
||||
`;
|
||||
|
||||
const DEFAULT_SOUL_TEMPLATE = `# SOUL.md — Persona & Boundaries
|
||||
const DEFAULT_SOUL_TEMPLATE = `# SOUL.md - Persona & Boundaries
|
||||
|
||||
Describe who the assistant is, tone, and boundaries.
|
||||
|
||||
@@ -32,7 +47,7 @@ Describe who the assistant is, tone, and boundaries.
|
||||
- Never send streaming/partial replies to external messaging surfaces.
|
||||
`;
|
||||
|
||||
const DEFAULT_TOOLS_TEMPLATE = `# TOOLS.md — User Tool Notes (editable)
|
||||
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; Clawdis provides built-in tools internally.
|
||||
@@ -49,6 +64,34 @@ It does not define which tools exist; Clawdis provides built-in tools internally
|
||||
Add whatever else you want the assistant to know about your local toolchain.
|
||||
`;
|
||||
|
||||
const TEMPLATE_DIR = path.resolve(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"../../docs/templates",
|
||||
);
|
||||
|
||||
function stripFrontMatter(content: string): string {
|
||||
if (!content.startsWith("---")) return content;
|
||||
const endIndex = content.indexOf("\n---", 3);
|
||||
if (endIndex === -1) return content;
|
||||
const start = endIndex + "\n---".length;
|
||||
let trimmed = content.slice(start);
|
||||
trimmed = trimmed.replace(/^\s+/, "");
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
async function loadTemplate(
|
||||
name: string,
|
||||
fallback: string,
|
||||
): Promise<string> {
|
||||
const templatePath = path.join(TEMPLATE_DIR, name);
|
||||
try {
|
||||
const content = await fs.readFile(templatePath, "utf-8");
|
||||
return stripFrontMatter(content);
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
export type WorkspaceBootstrapFileName =
|
||||
| typeof DEFAULT_AGENTS_FILENAME
|
||||
| typeof DEFAULT_SOUL_FILENAME
|
||||
@@ -94,9 +137,22 @@ export async function ensureAgentWorkspace(params?: {
|
||||
const soulPath = path.join(dir, DEFAULT_SOUL_FILENAME);
|
||||
const toolsPath = path.join(dir, DEFAULT_TOOLS_FILENAME);
|
||||
|
||||
await writeFileIfMissing(agentsPath, DEFAULT_AGENTS_TEMPLATE);
|
||||
await writeFileIfMissing(soulPath, DEFAULT_SOUL_TEMPLATE);
|
||||
await writeFileIfMissing(toolsPath, DEFAULT_TOOLS_TEMPLATE);
|
||||
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,
|
||||
);
|
||||
|
||||
await writeFileIfMissing(agentsPath, agentsTemplate);
|
||||
await writeFileIfMissing(soulPath, soulTemplate);
|
||||
await writeFileIfMissing(toolsPath, toolsTemplate);
|
||||
|
||||
return { dir, agentsPath, soulPath, toolsPath };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user