Files
devclaw-gitea/lib/onboarding.ts
Lauren ten Hoor a359ffed34 feat(migration): implement workspace layout migration and testing
- Added `migrate-layout.ts` to handle migration from old workspace layouts to the new `devclaw/` structure.
- Introduced `migrate-layout.test.ts` for comprehensive tests covering various migration scenarios.
- Updated `workspace.ts` to ensure default files are created post-migration, including `workflow.yaml` and role-specific prompts.
- Refactored role instruction handling to accommodate new directory structure.
- Enhanced project registration to scaffold prompt files in the new `devclaw/projects/<project>/prompts/` directory.
- Adjusted setup tool descriptions and logic to reflect changes in file structure.
- Updated templates to align with the new workflow configuration and role instructions.
2026-02-15 20:19:09 +08:00

184 lines
7.0 KiB
TypeScript

/**
* onboarding.ts — Conversational onboarding context templates.
*
* Provides context templates for the onboard tool.
*/
import fs from "node:fs/promises";
import path from "node:path";
import { getAllDefaultModels } from "./roles/index.js";
// ---------------------------------------------------------------------------
// Detection
// ---------------------------------------------------------------------------
export function isPluginConfigured(
pluginConfig?: Record<string, unknown>,
): boolean {
// Models moved to workflow.yaml — check for any devclaw plugin config (heartbeat, notifications, etc.)
return !!pluginConfig && Object.keys(pluginConfig).length > 0;
}
export async function hasWorkspaceFiles(
workspaceDir?: string,
): Promise<boolean> {
if (!workspaceDir) return false;
try {
const content = await fs.readFile(
path.join(workspaceDir, "AGENTS.md"),
"utf-8",
);
return content.includes("DevClaw") && content.includes("work_start");
} catch {
return false;
}
}
// ---------------------------------------------------------------------------
// Context templates
// ---------------------------------------------------------------------------
function buildModelTable(): string {
const lines: string[] = [];
for (const [role, levels] of Object.entries(getAllDefaultModels())) {
for (const [level, model] of Object.entries(levels)) {
lines.push(` - **${role} ${level}**: ${model}`);
}
}
return lines.join("\n");
}
export function buildReconfigContext(): string {
const modelTable = buildModelTable();
return `# DevClaw Reconfiguration
The user wants to reconfigure DevClaw. Default model configuration:
${modelTable}
Models are configured in \`devclaw/workflow.yaml\`. Edit that file directly or call \`setup\` with a \`models\` object to update.
## What can be changed
1. **Model levels** — call \`setup\` with a \`models\` object containing only the levels to change
2. **Workspace files** — \`setup\` re-writes AGENTS.md, HEARTBEAT.md (backs up existing files)
3. **Register new projects** — use \`project_register\`
Ask what they want to change, then call the appropriate tool.
\`setup\` is safe to re-run — it backs up existing files before overwriting.
`;
}
export function buildOnboardToolContext(): string {
// Build the model table dynamically from getAllDefaultModels()
const rows: string[] = [];
const purposes: Record<string, string> = {
junior: "Simple tasks, single-file fixes",
medior: "Features, bug fixes, code review",
senior: "Architecture, refactoring, complex tasks",
};
for (const [role, levels] of Object.entries(getAllDefaultModels())) {
for (const [level, model] of Object.entries(levels)) {
rows.push(`| ${role} | ${level} | ${model} | ${purposes[level] ?? ""} |`);
}
}
const modelTable = rows.join("\n");
return `# DevClaw Onboarding
## What is DevClaw?
DevClaw turns each Telegram group into an autonomous development team:
- An **orchestrator** that manages backlogs and delegates work
- **Developer workers** (junior/medior/senior levels) that write code in isolated sessions
- **Tester workers** that review code and run tests
- Atomic tools for label transitions, session dispatch, state management, and audit logging
## Setup Steps
**Step 1: Agent Selection**
Ask: "Do you want to configure DevClaw for the current agent, or create a new dedicated agent?"
- Current agent → no \`newAgentName\` needed
- New agent → ask for:
1. Agent name
2. **Channel binding**: "Which channel should this agent listen to? (telegram/whatsapp/none)"
- If telegram/whatsapp selected:
a) Check openclaw.json for existing channel bindings
b) If channel not configured/enabled → warn and recommend skipping binding for now
c) If channel-wide binding exists on another agent → ask: "Migrate binding from {agentName}?"
d) Collect migration decision
- If none selected, user can add bindings manually later via openclaw.json
**Step 2: Model Configuration**
1. **Call \`autoconfigure_models\`** to automatically discover and assign models:
- Discovers all authenticated models in OpenClaw
- Uses AI to intelligently assign them to DevClaw roles
- Returns a ready-to-use model configuration
2. **Handle the result**:
- If \`success: false\` and \`modelCount: 0\`:
- **BLOCK setup** - show the authentication instructions from the message
- **DO NOT proceed** - exit onboarding until user configures API keys
- If \`success: true\`:
- Present the model assignment table to the user
- Store the \`models\` object for Step 3
3. **Optional: Prefer specific provider**
- If user wants only models from one provider (e.g., "only use Anthropic"):
- Call \`autoconfigure_models({ preferProvider: "anthropic" })\`
4. **Confirm with user**
- Ask: "Does this look good, or would you like to customize any roles?"
- If approved → proceed to Step 3 with the \`models\` configuration
- If they want changes → ask which specific roles to modify
- If they want different provider → go back to step 3
**Step 3: Run Setup**
Call \`setup\` with the collected answers:
- Current agent: \`setup({})\` or \`setup({ models: { developer: { ... }, tester: { ... } } })\`
- New agent: \`setup({ newAgentName: "<name>", channelBinding: "telegram"|"whatsapp"|null, migrateFrom: "<agentId>"|null, models: { ... } })\`
- \`migrateFrom\`: Include if user wants to migrate an existing channel-wide binding
**Step 4: Telegram Group Setup (IMPORTANT)**
After setup completes, explain project isolation best practices:
📱 **Telegram Group Guidance:**
DevClaw uses **one Telegram group per project** for isolation and clean backlogs.
**Recommended Setup:**
1. **Create a new Telegram group** for each project
2. **Add your bot** to the group
3. **Use mentions** to interact: "@botname status", "@botname pick up #42"
4. Each group gets its own queue, workers, and audit log
**Why separate groups?**
- Clean issue backlogs per project
- Isolated worker state (no cross-project confusion)
- Clear audit trails
- Team-specific access control
**Single-project mode:**
If you REALLY want all projects in one group (not recommended):
- You can register multiple projects to the same group ID
- ⚠️ WARNING: Shared queues, workers will see all issues
- Only use this for personal/solo projects
Ask: "Do you understand the group-per-project model, or do you want single-project mode?"
- Most users should proceed with the recommended approach
- Only force single-project if they insist
**Step 5: Project Registration**
Ask: "Would you like to register a project now?"
If yes, collect: project name, repo path, Telegram group ID, group name, base branch.
Then call \`project_register\`.
💡 **Tip**: For the Telegram group ID:
- Add the bot to your group
- Send any message with the bot mentioned
- Bot can tell you the group ID
## Guidelines
- Be conversational and friendly. Ask one question at a time.
- Show defaults so the user can accept them quickly.
- After setup, summarize what was configured (including channel binding if applicable).
`;
}