feat: enhance workspace scaffolding with new identity and soul templates, and support for default user file
This commit is contained in:
@@ -66,7 +66,8 @@ export async function runSetup(opts: SetupOpts): Promise<SetupResult> {
|
||||
|
||||
await writePluginConfig(opts.api, agentId, opts.projectExecution);
|
||||
|
||||
const filesWritten = await scaffoldWorkspace(workspacePath);
|
||||
const defaultWorkspacePath = getDefaultWorkspacePath(opts.api);
|
||||
const filesWritten = await scaffoldWorkspace(workspacePath, defaultWorkspacePath);
|
||||
|
||||
const models = buildModelConfig(opts.models);
|
||||
await writeModelsToWorkflow(workspacePath, models);
|
||||
@@ -140,6 +141,15 @@ function buildModelConfig(overrides?: SetupOpts["models"]): ModelConfig {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDefaultWorkspacePath(api: OpenClawPluginApi): string | undefined {
|
||||
try {
|
||||
const config = api.runtime.config.loadConfig();
|
||||
return (config as any).agents?.defaults?.workspace ?? undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write model configuration to workflow.yaml (single source of truth).
|
||||
* Reads the existing workflow.yaml, merges model overrides into the roles section, and writes back.
|
||||
|
||||
@@ -8,6 +8,8 @@ import path from "node:path";
|
||||
import {
|
||||
AGENTS_MD_TEMPLATE,
|
||||
HEARTBEAT_MD_TEMPLATE,
|
||||
IDENTITY_MD_TEMPLATE,
|
||||
SOUL_MD_TEMPLATE,
|
||||
WORKFLOW_YAML_TEMPLATE,
|
||||
DEFAULT_ROLE_INSTRUCTIONS,
|
||||
} from "../templates.js";
|
||||
@@ -57,21 +59,51 @@ export async function ensureDefaultFiles(workspacePath: string): Promise<void> {
|
||||
/**
|
||||
* Write all workspace files for a DevClaw agent.
|
||||
* Returns the list of files that were written (skips files that already exist).
|
||||
*
|
||||
* @param defaultWorkspacePath — If provided, USER.md is copied from here (only if not already present).
|
||||
*/
|
||||
export async function scaffoldWorkspace(workspacePath: string): Promise<string[]> {
|
||||
export async function scaffoldWorkspace(workspacePath: string, defaultWorkspacePath?: string): Promise<string[]> {
|
||||
// Migrate old layout if detected
|
||||
await migrateWorkspaceLayout(workspacePath);
|
||||
|
||||
const written: string[] = [];
|
||||
|
||||
// AGENTS.md (backup existing — stays at workspace root)
|
||||
await backupAndWrite(path.join(workspacePath, "AGENTS.md"), AGENTS_MD_TEMPLATE);
|
||||
written.push("AGENTS.md");
|
||||
|
||||
// HEARTBEAT.md (stays at workspace root)
|
||||
await backupAndWrite(path.join(workspacePath, "HEARTBEAT.md"), HEARTBEAT_MD_TEMPLATE);
|
||||
written.push("HEARTBEAT.md");
|
||||
|
||||
// IDENTITY.md (create-only — never overwrite user customizations)
|
||||
const identityPath = path.join(workspacePath, "IDENTITY.md");
|
||||
if (!await fileExists(identityPath)) {
|
||||
await fs.writeFile(identityPath, IDENTITY_MD_TEMPLATE, "utf-8");
|
||||
written.push("IDENTITY.md");
|
||||
}
|
||||
|
||||
// SOUL.md (create-only — never overwrite user customizations)
|
||||
const soulPath = path.join(workspacePath, "SOUL.md");
|
||||
if (!await fileExists(soulPath)) {
|
||||
await fs.writeFile(soulPath, SOUL_MD_TEMPLATE, "utf-8");
|
||||
written.push("SOUL.md");
|
||||
}
|
||||
|
||||
// USER.md — copy from default workspace if available (create-only)
|
||||
const userPath = path.join(workspacePath, "USER.md");
|
||||
if (!await fileExists(userPath) && defaultWorkspacePath) {
|
||||
const sourceUser = path.join(defaultWorkspacePath, "USER.md");
|
||||
if (await fileExists(sourceUser)) {
|
||||
await fs.copyFile(sourceUser, userPath);
|
||||
written.push("USER.md");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all data-dir defaults (workflow.yaml, prompts, etc.)
|
||||
await ensureDefaultFiles(workspacePath);
|
||||
|
||||
return ["AGENTS.md", "HEARTBEAT.md"];
|
||||
return written;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -226,6 +226,10 @@ All orchestration goes through these tools. You do NOT manually manage sessions,
|
||||
| \`work_finish\` | End-to-end: label transition, state update, issue close/reopen |
|
||||
| \`design_task\` | Spawn an architect for design investigation. Creates To Design issue and dispatches architect |
|
||||
|
||||
### First Thing on Session Start
|
||||
|
||||
**Always call \`status\` first** when you start a new session. This tells you which projects you manage, what's in the queue, and which workers are active. Don't guess — check.
|
||||
|
||||
### Pipeline Flow
|
||||
|
||||
\`\`\`
|
||||
@@ -295,6 +299,56 @@ export const HEARTBEAT_MD_TEMPLATE = `# HEARTBEAT.md
|
||||
Do nothing. An internal token-free heartbeat service handles health checks and queue dispatch automatically.
|
||||
`;
|
||||
|
||||
export const IDENTITY_MD_TEMPLATE = `# IDENTITY.md - Who Am I?
|
||||
|
||||
- **Name:** DevClaw
|
||||
- **Creature:** Development orchestrator — plans, dispatches, never codes
|
||||
- **Vibe:** Direct, decisive, transparent. No fluff.
|
||||
- **Emoji:** 🦞
|
||||
`;
|
||||
|
||||
export const SOUL_MD_TEMPLATE = `# SOUL.md - DevClaw Orchestrator Identity
|
||||
|
||||
You are a **development orchestrator** — you plan, prioritize, and dispatch. You never write code yourself.
|
||||
|
||||
## Core Principles
|
||||
|
||||
**Be direct.** Skip pleasantries, get to the point. Say what you're doing and why.
|
||||
|
||||
**Be decisive.** Evaluate task complexity, pick the right level, dispatch. Don't deliberate when the answer is obvious.
|
||||
|
||||
**Be transparent.** Always include issue URLs. Always explain what happened and what's next. No black boxes.
|
||||
|
||||
**Be resourceful.** Check status before asking. Read the issue before dispatching. Understand the codebase before planning. Come back with answers, not questions.
|
||||
|
||||
## How You Work
|
||||
|
||||
- You receive requests via chat (Telegram, WhatsApp, or web)
|
||||
- You break work into issues, assign complexity levels, and dispatch workers
|
||||
- Workers (developer, tester, architect) do the actual work in isolated sessions
|
||||
- You track progress, handle failures, and keep the human informed
|
||||
- The heartbeat runs automatically — you don't manage it
|
||||
|
||||
## Communication Style
|
||||
|
||||
- Concise status updates with issue links
|
||||
- Use the announcement format from tool responses
|
||||
- Flag blockers and failures immediately
|
||||
- Don't over-explain routine operations
|
||||
|
||||
## Boundaries
|
||||
|
||||
- **Never write code** — dispatch a developer worker
|
||||
- **Never skip testing** — every code change goes through QA
|
||||
- **Never close issues** without a tester pass
|
||||
- **Ask before** architectural decisions affecting multiple projects
|
||||
|
||||
## Continuity
|
||||
|
||||
Each session starts fresh. AGENTS.md defines your operational procedures. This file defines who you are. USER.md tells you about the humans you work with. Update these files as you learn.
|
||||
`;
|
||||
|
||||
|
||||
/**
|
||||
* Generate WORKFLOW_YAML_TEMPLATE from the runtime objects (single source of truth).
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user