Files
devclaw-gitea/lib/onboarding.ts
Lauren ten Hoor 93d616b0dc feat: improve onboarding with model access check and Telegram group guidance
Enhanced the DevClaw onboarding flow to address real-world usability issues
discovered during testing.

Changes:

1. Model Selection Improvements (Step 2):
   - Added explicit prompt to check user's available models first
   - Changed 'Default Model' table to 'Suggested default' to emphasize flexibility
   - Added model selection guidance with class descriptions:
     * junior/tester: Fast, cheap (Haiku-class, GPT-4-mini)
     * medior/reviewer: Balanced (Sonnet-class, GPT-4)
     * senior: Most capable (Opus-class, o1)
   - Emphasized guiding users to configure finer-grained mappings
   - Added warning that defaults are suggestions, not requirements

2. Telegram Group Setup Guidance (New Step 4):
   - Added comprehensive section on project isolation best practices
   - Explains the one-group-per-project model clearly
   - Provides rationale:
     * Clean issue backlogs per project
     * Isolated worker state
     * Clear audit trails
     * Team-specific access control
   - Documents mention requirement (@botname command)
   - Includes single-project mode option with strong warning
   - Provides tip for getting group ID from bot

3. Improved Flow:
   - Renumbered steps (Project Registration is now Step 5)
   - Added group ID discovery tip
   - Maintained conversational tone while being more explicit

Impact:
- Prevents configuration failures from using unavailable models
- Guides users toward sustainable multi-project setup
- Reduces support burden by proactively explaining best practices
- Still allows single-project mode for solo developers

Addresses issue #132
2026-02-12 12:31:50 +08:00

185 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 { DEFAULT_MODELS } from "./tiers.js";
// ---------------------------------------------------------------------------
// Detection
// ---------------------------------------------------------------------------
export function isPluginConfigured(
pluginConfig?: Record<string, unknown>,
): boolean {
const models = (pluginConfig as { models?: Record<string, string> })?.models;
return !!models && Object.keys(models).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(pluginConfig?: Record<string, unknown>): string {
const cfg = (pluginConfig as { models?: { dev?: Record<string, string>; qa?: Record<string, string> } })?.models;
const lines: string[] = [];
for (const [role, levels] of Object.entries(DEFAULT_MODELS)) {
for (const [level, defaultModel] of Object.entries(levels)) {
const model = cfg?.[role as "dev" | "qa"]?.[level] || defaultModel;
lines.push(` - **${role} ${level}**: ${model} (default: ${defaultModel})`);
}
}
return lines.join("\n");
}
export function buildReconfigContext(
pluginConfig?: Record<string, unknown>,
): string {
const modelTable = buildModelTable(pluginConfig);
return `# DevClaw Reconfiguration
The user wants to reconfigure DevClaw. Current model configuration:
${modelTable}
## 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 DEFAULT_MODELS
const rows: string[] = [];
const purposes: Record<string, string> = {
junior: "Typos, single-file fixes",
medior: "Features, bug fixes",
senior: "Architecture, refactoring",
reviewer: "Code review",
tester: "Testing",
};
for (const [role, levels] of Object.entries(DEFAULT_MODELS)) {
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
- **DEV workers** (junior/medior/senior levels) that write code in isolated sessions
- **QA 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**
⚠️ **IMPORTANT**: First check what models the user has access to! The defaults below are suggestions.
Ask: "What models do you have access to in your OpenClaw configuration?"
- Guide them to check their available models (router configuration, API keys, etc.)
- If they have the default Claude models, great!
- If not, help them map their available models to these levels:
**Suggested default level-to-model mapping:**
| Role | Level | Default Model | Purpose |
|------|-------|---------------|---------|
${modelTable}
**Model selection guidance:**
- **junior/tester**: Fastest, cheapest models (Haiku-class, GPT-4-mini, etc.)
- **medior/reviewer**: Balanced models (Sonnet-class, GPT-4, etc.)
- **senior**: Most capable models (Opus-class, o1, etc.)
Ask which levels they want to customize, and collect their actual model IDs.
💡 **Tip**: Guide users to configure finer-grained mappings rather than accepting unsuitable defaults.
**Step 3: Run Setup**
Call \`setup\` with the collected answers:
- Current agent: \`setup({})\` or \`setup({ models: { dev: { ... }, qa: { ... } } })\`
- 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).
`;
}