create-yonderclaw 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/LICENSE +44 -0
  2. package/README.md +288 -0
  3. package/bin/create-yonderclaw.mjs +43 -0
  4. package/docs/assets/favicon.png +0 -0
  5. package/docs/assets/metaclaw-banner.svg +86 -0
  6. package/docs/assets/qis-logo.png +0 -0
  7. package/docs/assets/yz-favicon.png +0 -0
  8. package/docs/assets/yz-logo.png +0 -0
  9. package/docs/index.html +1155 -0
  10. package/installer/assets/favicon.png +0 -0
  11. package/installer/auto-start.ts +330 -0
  12. package/installer/brand.ts +115 -0
  13. package/installer/core-scaffold.ts +448 -0
  14. package/installer/dashboard-generator.ts +657 -0
  15. package/installer/detect.ts +129 -0
  16. package/installer/index.ts +355 -0
  17. package/installer/module-loader.ts +412 -0
  18. package/installer/modules/boardroom/boardroom/client.ts.txt +201 -0
  19. package/installer/modules/boardroom/boardroom/db.ts.txt +322 -0
  20. package/installer/modules/boardroom/boardroom/meeting-agent.ts.txt +129 -0
  21. package/installer/modules/boardroom/boardroom/meeting-scheduler.ts.txt +194 -0
  22. package/installer/modules/boardroom/boardroom/server.ts.txt +473 -0
  23. package/installer/modules/boardroom/boardroom/start-boardroom.bat.txt +26 -0
  24. package/installer/modules/boardroom/boardroom/summons.ts.txt +76 -0
  25. package/installer/modules/boardroom/boardroom/turn-v2.ts.txt +172 -0
  26. package/installer/modules/boardroom/boardroom/turn.ts.txt +208 -0
  27. package/installer/modules/boardroom/boardroom/types.ts.txt +100 -0
  28. package/installer/modules/boardroom/metaclaw-module.json +35 -0
  29. package/installer/modules/boardroom/scripts/meeting-check.bat.txt +38 -0
  30. package/installer/modules/core/metaclaw-module.json +51 -0
  31. package/installer/modules/core/src/db.ts.txt +277 -0
  32. package/installer/modules/core/src/health-check.ts.txt +128 -0
  33. package/installer/modules/core/src/observability.ts.txt +20 -0
  34. package/installer/modules/core/src/safety.ts.txt +26 -0
  35. package/installer/modules/core/src/scan-capabilities.ts.txt +196 -0
  36. package/installer/modules/core/src/self-improve.ts.txt +48 -0
  37. package/installer/modules/core/src/self-update.ts.txt +345 -0
  38. package/installer/modules/core/src/sync-context.ts.txt +133 -0
  39. package/installer/modules/core/src/tasks.ts.txt +159 -0
  40. package/installer/modules/custom/metaclaw-module.json +15 -0
  41. package/installer/modules/custom/src/agent-custom.ts.txt +100 -0
  42. package/installer/modules/dashboard/metaclaw-module.json +23 -0
  43. package/installer/modules/dashboard/scripts/build-dashboard.cjs.txt +51 -0
  44. package/installer/modules/dashboard/src/update-dashboard.ts.txt +126 -0
  45. package/installer/modules/outreach/metaclaw-module.json +29 -0
  46. package/installer/modules/outreach/src/agent-outreach.ts.txt +193 -0
  47. package/installer/modules/outreach/src/inbox-agent.ts.txt +283 -0
  48. package/installer/modules/outreach/src/morning-report.ts.txt +124 -0
  49. package/installer/modules/research/metaclaw-module.json +15 -0
  50. package/installer/modules/research/src/agent-research.ts.txt +127 -0
  51. package/installer/modules/scheduler/metaclaw-module.json +27 -0
  52. package/installer/modules/scheduler/scripts/agent-cycle.bat.txt +85 -0
  53. package/installer/modules/scheduler/scripts/detect-session.bat.txt +41 -0
  54. package/installer/modules/scheduler/scripts/launch.bat.txt +120 -0
  55. package/installer/modules/scheduler/src/cron-manager.ts.txt +273 -0
  56. package/installer/modules/social/metaclaw-module.json +15 -0
  57. package/installer/modules/social/src/agent-social.ts.txt +110 -0
  58. package/installer/modules/support/metaclaw-module.json +15 -0
  59. package/installer/modules/support/src/agent-support.ts.txt +60 -0
  60. package/installer/modules/swarm/metaclaw-module.json +25 -0
  61. package/installer/modules/swarm/swarm/dht-client.ts.txt +376 -0
  62. package/installer/modules/swarm/swarm/relay-server.ts.txt +348 -0
  63. package/installer/modules/swarm/swarm/swarm-client.ts.txt +303 -0
  64. package/installer/modules/swarm/swarm/types.ts.txt +51 -0
  65. package/installer/modules/voice/metaclaw-module.json +16 -0
  66. package/installer/questionnaire.ts +277 -0
  67. package/installer/research.ts +258 -0
  68. package/installer/scaffold-from-config.ts +270 -0
  69. package/installer/task-generator.ts +324 -0
  70. package/installer/templates/agent-custom.ts.txt +100 -0
  71. package/installer/templates/agent-cycle.bat.txt +19 -0
  72. package/installer/templates/agent-outreach.ts.txt +193 -0
  73. package/installer/templates/agent-research.ts.txt +127 -0
  74. package/installer/templates/agent-social.ts.txt +110 -0
  75. package/installer/templates/agent-support.ts.txt +60 -0
  76. package/installer/templates/build-dashboard.cjs.txt +51 -0
  77. package/installer/templates/cron-manager.ts.txt +273 -0
  78. package/installer/templates/dashboard.html.txt +450 -0
  79. package/installer/templates/db.ts.txt +277 -0
  80. package/installer/templates/detect-session.bat.txt +41 -0
  81. package/installer/templates/health-check.ts.txt +128 -0
  82. package/installer/templates/inbox-agent.ts.txt +283 -0
  83. package/installer/templates/launch.bat.txt +120 -0
  84. package/installer/templates/morning-report.ts.txt +124 -0
  85. package/installer/templates/observability.ts.txt +20 -0
  86. package/installer/templates/safety.ts.txt +26 -0
  87. package/installer/templates/self-improve.ts.txt +48 -0
  88. package/installer/templates/self-update.ts.txt +345 -0
  89. package/installer/templates/state.json.txt +33 -0
  90. package/installer/templates/system-context.json.txt +33 -0
  91. package/installer/templates/update-dashboard.ts.txt +126 -0
  92. package/package.json +31 -0
  93. package/setup.bat +178 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * MetaClaw Swarm — Shared Types
3
+ * QIS-inspired bucket system for intelligence sharing
4
+ */
5
+
6
+ export interface OutcomePacket {
7
+ v: 1;
8
+ bucket: string; // canonical problem path e.g. "outreach.email.cold.response_rate_low"
9
+ bucket_id: string; // SHA-256 hash of bucket path (first 16 hex chars)
10
+ ts: number; // Unix timestamp
11
+ agent_id: string; // anonymized, e.g. "mc_anon_7f3a"
12
+ outcome: {
13
+ signal: "positive" | "negative" | "neutral";
14
+ confidence: number; // 0-1
15
+ insight: string; // the actual knowledge
16
+ context: Record<string, any>; // structured metadata for filtering
17
+ metrics?: {
18
+ sample_size?: number;
19
+ effect_size?: number;
20
+ stat_sig?: boolean;
21
+ };
22
+ };
23
+ sig?: string; // Ed25519 signature (future)
24
+ }
25
+
26
+ export interface BucketMeta {
27
+ bucket_id: string;
28
+ path: string; // canonical problem path
29
+ domain: string; // first segment e.g. "outreach"
30
+ title: string; // human-readable
31
+ description: string;
32
+ conditions: string[]; // when this bucket applies
33
+ exclusions: string[]; // when it does NOT apply
34
+ packet_count: number;
35
+ last_updated: string;
36
+ confidence_avg: number;
37
+ }
38
+
39
+ export interface BucketIndex {
40
+ version: number;
41
+ updated_at: string;
42
+ buckets: BucketMeta[];
43
+ }
44
+
45
+ export interface SwarmConfig {
46
+ relay_url: string;
47
+ agent_id: string;
48
+ enabled: boolean;
49
+ publish: boolean; // contribute insights to meta swarm
50
+ subscribe: boolean; // pull insights from meta swarm
51
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "voice",
3
+ "displayName": "Voice — Push-to-Talk & TTS",
4
+ "version": "1.0.0",
5
+ "description": "Browser-based voice I/O: push-to-talk, always-on listening, Microsoft Jenny neural TTS",
6
+ "category": "ui",
7
+ "alwaysInstall": true,
8
+ "engines": { "metaclaw": ">=3.3.0" },
9
+ "requires": { "modules": ["dashboard"] },
10
+ "contributes": {
11
+ "dashboard": {
12
+ "inject": "voice"
13
+ },
14
+ "claudeMd": ["voice"]
15
+ }
16
+ }
@@ -0,0 +1,277 @@
1
+ /**
2
+ * MetaClaw Questionnaire — Claude-powered needs assessment
3
+ *
4
+ * Asks the user what they need, then uses Claude to research
5
+ * best practices and generate an optimal agent configuration.
6
+ */
7
+
8
+ import * as clack from "@clack/prompts";
9
+ import chalk from "chalk";
10
+ import { brand, purple, muted, accent, sectionHeader } from "./brand.js";
11
+ import type { SystemInfo } from "./detect.js";
12
+
13
+ export type ClawTemplate = {
14
+ id: string;
15
+ name: string;
16
+ description: string;
17
+ hint: string;
18
+ icon: string;
19
+ requiredTools: string[];
20
+ optionalTools: string[];
21
+ questions: Array<{
22
+ key: string;
23
+ message: string;
24
+ type: "text" | "select" | "confirm";
25
+ options?: Array<{ value: string; label: string; hint?: string }>;
26
+ placeholder?: string;
27
+ default?: string;
28
+ }>;
29
+ };
30
+
31
+ // --- Claw Templates ---
32
+ export const CLAW_TEMPLATES: ClawTemplate[] = [
33
+ {
34
+ id: "outreach",
35
+ name: "Outreach Claw",
36
+ description: "Email prospecting, follow-ups, auto-reply, AI detection gate",
37
+ hint: "sales, partnerships, networking",
38
+ icon: "📧",
39
+ requiredTools: ["gmail_smtp", "gmail_imap"],
40
+ optionalTools: ["linkedin", "slack", "gptzero"],
41
+ questions: [
42
+ { key: "senderName", message: "Your name (appears in From field)", type: "text", placeholder: "Jane Doe" },
43
+ { key: "senderEmail", message: "Email address to send FROM (create a separate one for outreach — never your personal email. Gmail, Outlook, any provider)", type: "text", placeholder: "yourname.outreach@gmail.com" },
44
+ { key: "targetAudience", message: "Who are you reaching out to?", type: "text", placeholder: "CTOs at Series A startups" },
45
+ { key: "purpose", message: "What's the goal of your outreach?", type: "text", placeholder: "Introduce QIS Protocol for fleet intelligence" },
46
+ { key: "tone", message: "Email tone", type: "select", options: [
47
+ { value: "casual", label: "Casual", hint: "peer-to-peer, like texting a colleague" },
48
+ { value: "professional", label: "Professional", hint: "respectful but direct" },
49
+ { value: "technical", label: "Technical", hint: "engineer-to-engineer, show depth" },
50
+ ]},
51
+ { key: "dailyLimit", message: "Max emails per day", type: "text", default: "50", placeholder: "50" },
52
+ ],
53
+ },
54
+ {
55
+ id: "research",
56
+ name: "Research Claw",
57
+ description: "Deep web research, competitive analysis, synthesized reports",
58
+ hint: "market research, due diligence, monitoring",
59
+ icon: "🔍",
60
+ requiredTools: ["web_search", "web_fetch"],
61
+ optionalTools: ["pdf_reader", "notion", "google_docs"],
62
+ questions: [
63
+ { key: "researchDomain", message: "What domain are you researching?", type: "text", placeholder: "AI agent frameworks, competitor analysis" },
64
+ { key: "outputFormat", message: "How do you want results?", type: "select", options: [
65
+ { value: "markdown", label: "Markdown reports", hint: "saved to files" },
66
+ { value: "email", label: "Email digest", hint: "daily/weekly summary to your inbox" },
67
+ { value: "notion", label: "Notion pages", hint: "auto-create in your workspace" },
68
+ ]},
69
+ { key: "frequency", message: "How often should it run?", type: "select", options: [
70
+ { value: "once", label: "One-time deep dive" },
71
+ { value: "daily", label: "Daily monitoring" },
72
+ { value: "weekly", label: "Weekly roundup" },
73
+ ]},
74
+ ],
75
+ },
76
+ {
77
+ id: "support",
78
+ name: "Support Claw",
79
+ description: "Inbox monitoring, auto-triage, draft responses, escalation",
80
+ hint: "customer support, helpdesk, email management",
81
+ icon: "🎧",
82
+ requiredTools: ["gmail_smtp", "gmail_imap"],
83
+ optionalTools: ["slack", "zendesk", "intercom"],
84
+ questions: [
85
+ { key: "supportEmail", message: "Support inbox email", type: "text", placeholder: "support@yourdomain.com" },
86
+ { key: "escalationEmail", message: "Escalation email (urgent issues)", type: "text", placeholder: "you@yourdomain.com" },
87
+ { key: "autoReply", message: "Auto-reply to common questions?", type: "confirm" },
88
+ { key: "categories", message: "What types of requests do you get?", type: "text", placeholder: "billing, technical, feature requests, bugs" },
89
+ ],
90
+ },
91
+ {
92
+ id: "social",
93
+ name: "Social Claw",
94
+ description: "Content creation, scheduling, engagement monitoring",
95
+ hint: "twitter/X, LinkedIn, content marketing",
96
+ icon: "📱",
97
+ requiredTools: ["web_search"],
98
+ optionalTools: ["twitter_api", "linkedin_api", "buffer"],
99
+ questions: [
100
+ { key: "platforms", message: "Which platforms?", type: "text", placeholder: "Twitter/X, LinkedIn" },
101
+ { key: "contentType", message: "What kind of content?", type: "select", options: [
102
+ { value: "thought_leadership", label: "Thought leadership", hint: "original insights, opinions" },
103
+ { value: "engagement", label: "Engagement", hint: "reply to others, build community" },
104
+ { value: "promotion", label: "Promotion", hint: "share product updates, launches" },
105
+ { value: "curation", label: "Curation", hint: "share relevant industry content" },
106
+ ]},
107
+ { key: "postsPerDay", message: "Target posts per day", type: "text", default: "3", placeholder: "3" },
108
+ ],
109
+ },
110
+ {
111
+ id: "custom",
112
+ name: "Custom Claw",
113
+ description: "Describe what you need — Claude configures it from scratch",
114
+ hint: "anything else, blank slate",
115
+ icon: "⚡",
116
+ requiredTools: [],
117
+ optionalTools: [],
118
+ questions: [
119
+ { key: "description", message: "Describe what you want the agent to do (be specific)", type: "text", placeholder: "Monitor Hacker News for QIS-related posts and draft thoughtful replies..." },
120
+ { key: "schedule", message: "How often should it run?", type: "select", options: [
121
+ { value: "continuous", label: "Continuously", hint: "always running" },
122
+ { value: "hourly", label: "Every hour" },
123
+ { value: "daily", label: "Once a day" },
124
+ { value: "weekly", label: "Once a week" },
125
+ { value: "manual", label: "Only when triggered" },
126
+ ]},
127
+ { key: "outputMethod", message: "How should it deliver results?", type: "select", options: [
128
+ { value: "email", label: "Email" },
129
+ { value: "file", label: "Save to files" },
130
+ { value: "slack", label: "Slack message" },
131
+ { value: "console", label: "Terminal output" },
132
+ ]},
133
+ ],
134
+ },
135
+ ];
136
+
137
+ export type QuestionnaireResult = {
138
+ template: ClawTemplate;
139
+ answers: Record<string, string | boolean>;
140
+ projectName: string;
141
+ };
142
+
143
+ /**
144
+ * Run the interactive questionnaire.
145
+ */
146
+ export async function runQuestionnaire(systemInfo: SystemInfo): Promise<QuestionnaireResult | null> {
147
+ console.log(sectionHeader("What do you want to build?"));
148
+ console.log("");
149
+
150
+ // Step 1: Choose template
151
+ const templateId = await clack.select({
152
+ message: "Select an agent type",
153
+ options: CLAW_TEMPLATES.map((t) => ({
154
+ value: t.id,
155
+ label: `${t.icon} ${t.name}`,
156
+ hint: t.hint,
157
+ })),
158
+ });
159
+
160
+ if (clack.isCancel(templateId)) return null;
161
+
162
+ const template = CLAW_TEMPLATES.find((t) => t.id === templateId)!;
163
+
164
+ console.log("");
165
+ console.log(
166
+ muted(` ${template.icon} ${template.name}: ${template.description}`)
167
+ );
168
+ console.log("");
169
+
170
+ // Step 2: Project name
171
+ const projectName = await clack.text({
172
+ message: "Project name",
173
+ placeholder: `my-${template.id}-agent`,
174
+ defaultValue: `my-${template.id}-agent`,
175
+ });
176
+
177
+ if (clack.isCancel(projectName)) return null;
178
+
179
+ // Step 3: Template-specific questions
180
+ const answers: Record<string, string | boolean> = {};
181
+
182
+ for (const q of template.questions) {
183
+ let answer: string | boolean | symbol;
184
+
185
+ if (q.type === "text") {
186
+ answer = await clack.text({
187
+ message: q.message,
188
+ placeholder: q.placeholder,
189
+ defaultValue: q.default,
190
+ });
191
+ } else if (q.type === "select" && q.options) {
192
+ answer = await clack.select({
193
+ message: q.message,
194
+ options: q.options,
195
+ });
196
+ } else if (q.type === "confirm") {
197
+ answer = await clack.confirm({ message: q.message });
198
+ } else {
199
+ continue;
200
+ }
201
+
202
+ if (clack.isCancel(answer)) return null;
203
+ answers[q.key] = answer as string | boolean;
204
+ }
205
+
206
+ // Step 4: Universal deep-dive (every Claw gets these)
207
+ console.log("");
208
+ console.log(muted(" Now let's go deeper so the board can build your perfect agent."));
209
+ console.log("");
210
+
211
+ const taskDescription = await clack.text({
212
+ message: "Describe in detail what you want this agent to do day-to-day",
213
+ placeholder: "Find potential partners, research them, send personalized emails, follow up, track responses...",
214
+ });
215
+ if (clack.isCancel(taskDescription)) return null;
216
+ answers.taskDescription = taskDescription as string;
217
+
218
+ const toolsUsed = await clack.text({
219
+ message: "What tools/platforms do you currently use? (email, CRM, Slack, etc.)",
220
+ placeholder: "Gmail, Slack, HubSpot, LinkedIn, Google Sheets...",
221
+ });
222
+ if (clack.isCancel(toolsUsed)) return null;
223
+ answers.toolsUsed = toolsUsed as string;
224
+
225
+ const autonomyLevel = await clack.select({
226
+ message: "How autonomous should the agent be?",
227
+ options: [
228
+ { value: "supervised", label: "Suggest & wait for approval", hint: "safest — you review everything" },
229
+ { value: "semi", label: "Act on routine tasks, ask on important ones", hint: "recommended" },
230
+ { value: "full", label: "Fully autonomous", hint: "agent handles everything, alerts on issues only" },
231
+ ],
232
+ });
233
+ if (clack.isCancel(autonomyLevel)) return null;
234
+ answers.autonomyLevel = autonomyLevel as string;
235
+
236
+ const volume = await clack.text({
237
+ message: "Expected daily volume? (emails, tasks, posts, etc.)",
238
+ placeholder: "20-50 emails per day",
239
+ });
240
+ if (clack.isCancel(volume)) return null;
241
+ answers.volume = volume as string;
242
+
243
+ const specialInstructions = await clack.text({
244
+ message: "Anything else the agent should know? (special rules, tone, avoid certain things, etc.)",
245
+ placeholder: "Never contact competitors. Always be casual. Include a link to our site...",
246
+ defaultValue: "",
247
+ });
248
+ if (clack.isCancel(specialInstructions)) return null;
249
+ if (specialInstructions) answers.specialInstructions = specialInstructions as string;
250
+
251
+ // Step 5: Shortcut preferences
252
+ const addDesktopShortcut = await clack.confirm({
253
+ message: "Add a shortcut to your Desktop?",
254
+ initialValue: true,
255
+ });
256
+ if (clack.isCancel(addDesktopShortcut)) return null;
257
+ answers.addDesktopShortcut = addDesktopShortcut as boolean;
258
+
259
+ // Step 6: Self-update interval
260
+ const updateInterval = await clack.select({
261
+ message: "How often should the agent self-optimize?",
262
+ options: [
263
+ { value: "1", label: "Every hour", hint: "aggressive learning" },
264
+ { value: "6", label: "Every 6 hours", hint: "recommended" },
265
+ { value: "24", label: "Once a day", hint: "conservative" },
266
+ { value: "168", label: "Once a week", hint: "minimal" },
267
+ ],
268
+ });
269
+ if (clack.isCancel(updateInterval)) return null;
270
+ answers.selfUpdateIntervalHours = updateInterval as string;
271
+
272
+ return {
273
+ template,
274
+ answers,
275
+ projectName: projectName as string,
276
+ };
277
+ }
@@ -0,0 +1,258 @@
1
+ /**
2
+ * MetaClaw Research Phase — Claude-powered best practices research
3
+ *
4
+ * Uses the Agent SDK to:
5
+ * 1. Research best practices for the user's specific agent type
6
+ * 2. Generate optimal configuration
7
+ * 3. Validate the configuration
8
+ *
9
+ * Auth: reads ~/.claude/.credentials.json (from Claude login)
10
+ * No CLI needs to be open — the SDK uses the stored OAuth token.
11
+ */
12
+
13
+ import { query } from "@anthropic-ai/claude-agent-sdk";
14
+ import type { SDKResultMessage, SDKResultSuccess, SDKAssistantMessage, Options } from "@anthropic-ai/claude-agent-sdk";
15
+ import ora from "ora";
16
+ import { brand, muted, success, sectionHeader, status } from "./brand.js";
17
+ import type { SystemInfo } from "./detect.js";
18
+ import type { QuestionnaireResult } from "./questionnaire.js";
19
+
20
+ export type ClawConfig = {
21
+ name: string;
22
+ template: string;
23
+ systemPrompt: string;
24
+ tools: string[];
25
+ safety: Record<string, unknown>;
26
+ schedule: { cron: string; description: string };
27
+ selfImprovement: {
28
+ enabled: boolean;
29
+ reflectionFrequency: string;
30
+ metricsToTrack: string[];
31
+ };
32
+ rawResearch: string;
33
+ };
34
+
35
+ /**
36
+ * Build the meta-prompt that instructs Claude to research and configure.
37
+ */
38
+ function buildMetaPrompt(result: QuestionnaireResult, systemInfo: SystemInfo): string {
39
+ const { template, answers } = result;
40
+
41
+ return `You are MetaClaw, an autonomous AI agent configuration engine by Yonder Zenith LLC.
42
+
43
+ ## YOUR MISSION
44
+ Research and generate the OPTIMAL agent configuration for this user's needs. Be opinionated — choose the best approach, don't offer multiple options.
45
+
46
+ ## SYSTEM CONTEXT
47
+ - OS: ${systemInfo.os.platform} ${systemInfo.os.release} (${systemInfo.os.arch})
48
+ - Hardware: ${systemInfo.hardware.cpus} CPUs, ${systemInfo.hardware.ram} RAM, GPU: ${systemInfo.hardware.gpu}
49
+ - User: ${systemInfo.user.username}
50
+ - Workspace: ${systemInfo.paths.workspace}
51
+ - Available: Node.js ${systemInfo.node.version}${systemInfo.docker.installed ? ", Docker " + systemInfo.docker.version : ""}${systemInfo.python.installed ? ", Python " + systemInfo.python.version : ""}
52
+
53
+ ## AGENT REQUEST
54
+ - Template: ${template.name} (${template.id})
55
+ - Description: ${template.description}
56
+ - Project: ${result.projectName}
57
+
58
+ ## USER'S DETAILED REQUIREMENTS
59
+ - Day-to-day tasks: ${answers.taskDescription || "Not specified"}
60
+ - Tools/platforms they use: ${answers.toolsUsed || "Not specified"}
61
+ - Autonomy level: ${answers.autonomyLevel || "semi"}
62
+ - Expected daily volume: ${answers.volume || "Not specified"}
63
+ - Special instructions: ${answers.specialInstructions || "None"}
64
+
65
+ ## TEMPLATE-SPECIFIC CONFIG
66
+ ${Object.entries(answers).filter(([k]) => !["taskDescription", "toolsUsed", "autonomyLevel", "volume", "specialInstructions", "selfUpdateIntervalHours"].includes(k)).map(([k, v]) => `- ${k}: ${v}`).join("\n")}
67
+
68
+ ## PROTOCOL (follow this exactly)
69
+
70
+ ### STEP 1: RESEARCH (use WebSearch)
71
+ Search for and synthesize:
72
+ - What are the absolute best practices for a ${template.name} in 2026?
73
+ - What tools/MCP servers are proven for this use case?
74
+ - What are common failure modes and how to prevent them?
75
+ - What compliance/safety requirements exist?
76
+ - What makes world-class agents of this type vs mediocre ones?
77
+ Do at least 3 web searches. Be thorough.
78
+
79
+ ### STEP 2: DESIGN
80
+ Based on research, design the agent:
81
+ - System prompt (comprehensive, with anti-AI-detection rules if sending emails)
82
+ - Tool list (specific MCP servers and built-in tools)
83
+ - Safety rules (rate limits, circuit breakers, compliance)
84
+ - Self-improvement strategy
85
+ - Schedule
86
+
87
+ ### STEP 3: OUTPUT
88
+ Output a JSON block with this exact structure:
89
+ \`\`\`json
90
+ {
91
+ "name": "${result.projectName}",
92
+ "template": "${template.id}",
93
+ "systemPrompt": "the full system prompt",
94
+ "tools": ["tool1", "tool2"],
95
+ "safety": {
96
+ "maxActionsPerDay": 50,
97
+ "maxActionsPerHour": 10,
98
+ "circuitBreakerThreshold": 0.05
99
+ },
100
+ "schedule": {
101
+ "cron": "*/30 * * * *",
102
+ "description": "every 30 minutes"
103
+ },
104
+ "selfImprovement": {
105
+ "enabled": true,
106
+ "reflectionFrequency": "daily",
107
+ "metricsToTrack": ["success_rate", "response_quality"]
108
+ }
109
+ }
110
+ \`\`\`
111
+
112
+ ### STEP 4: VALIDATE
113
+ Before outputting, check:
114
+ - Is every field populated? (no empty strings or missing keys)
115
+ - Is the system prompt specific to this use case? (not generic)
116
+ - Are safety limits reasonable? (not too loose, not too restrictive)
117
+ - Will this actually work on ${systemInfo.os.platform} with the available tools?
118
+ If anything scores below 8/10, revise it.`;
119
+ }
120
+
121
+ /**
122
+ * Run the AI research phase — calls Claude Agent SDK to research and configure.
123
+ */
124
+ export async function runResearch(
125
+ result: QuestionnaireResult,
126
+ systemInfo: SystemInfo
127
+ ): Promise<ClawConfig | null> {
128
+ console.log(sectionHeader("MetaClaw Board Convening"));
129
+ console.log("");
130
+ console.log(brand(" Board members are researching for your ultimate custom setup."));
131
+ console.log(muted(" Analyzing your requirements, researching best practices,"));
132
+ console.log(muted(" and designing the optimal configuration for " + result.template.name + "..."));
133
+ console.log("");
134
+
135
+ const spinner = ora({
136
+ text: "Board convening — analyzing requirements...",
137
+ color: "magenta",
138
+ spinner: "dots12",
139
+ }).start();
140
+
141
+ const metaPrompt = buildMetaPrompt(result, systemInfo);
142
+
143
+ try {
144
+ let fullResponse = "";
145
+ let currentPhase = "Researching...";
146
+
147
+ const options: Options = {
148
+ systemPrompt: "You are MetaClaw, an expert AI agent configuration engine. You research best practices using web search, then generate optimal agent configurations. Always output valid JSON in your final response.",
149
+ allowedTools: ["WebSearch", "WebFetch"],
150
+ maxTurns: 20,
151
+ model: "claude-sonnet-4-6",
152
+ };
153
+
154
+ const stream = query({ prompt: metaPrompt, options });
155
+
156
+ for await (const message of stream) {
157
+ if (message.type === "assistant") {
158
+ const msg = message as SDKAssistantMessage;
159
+ if (msg.message?.content) {
160
+ for (const block of msg.message.content) {
161
+ if (block.type === "text" && "text" in block) {
162
+ const text = (block as { type: "text"; text: string }).text;
163
+ fullResponse += text;
164
+
165
+ // Update spinner with board-style messaging
166
+ if (text.includes("search") || text.includes("Search")) {
167
+ spinner.text = "Board researching industry best practices...";
168
+ } else if (text.includes("design") || text.includes("Design")) {
169
+ spinner.text = "Board designing your agent architecture...";
170
+ } else if (text.includes("json") || text.includes("JSON")) {
171
+ spinner.text = "Board generating your custom configuration...";
172
+ } else if (text.includes("validat") || text.includes("Validat")) {
173
+ spinner.text = "Board reviewing and stress-testing...";
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ if (message.type === "result") {
181
+ const res = message as SDKResultMessage;
182
+ if (res.subtype === "success") {
183
+ const s = res as SDKResultSuccess;
184
+ spinner.succeed(`Board consensus reached — configuration finalized ($${s.total_cost_usd.toFixed(2)})`);
185
+ } else {
186
+ spinner.fail("Research failed: " + res.subtype);
187
+ return null;
188
+ }
189
+ }
190
+ }
191
+
192
+ // Extract JSON from response
193
+ const config = extractConfig(fullResponse, result);
194
+ if (config) {
195
+ console.log("");
196
+ console.log(status.ok("Agent configuration generated"));
197
+ console.log(status.ok(`System prompt: ${config.systemPrompt.length} characters`));
198
+ console.log(status.ok(`Tools: ${config.tools.join(", ")}`));
199
+ console.log(status.ok(`Schedule: ${config.schedule.description}`));
200
+ console.log(status.ok(`Self-improvement: ${config.selfImprovement.enabled ? "enabled" : "disabled"}`));
201
+ }
202
+
203
+ return config;
204
+ } catch (err) {
205
+ const msg = err instanceof Error ? err.message : String(err);
206
+ spinner.fail(`Research failed: ${msg}`);
207
+ return null;
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Extract JSON config from Claude's response.
213
+ */
214
+ function extractConfig(response: string, result: QuestionnaireResult): ClawConfig | null {
215
+ // Try to find JSON block in response
216
+ const jsonMatch = response.match(/```json\s*([\s\S]*?)```/);
217
+ if (jsonMatch) {
218
+ try {
219
+ const parsed = JSON.parse(jsonMatch[1]);
220
+ return {
221
+ ...parsed,
222
+ rawResearch: response,
223
+ };
224
+ } catch {
225
+ // JSON parse failed
226
+ }
227
+ }
228
+
229
+ // Try to find raw JSON object
230
+ const braceMatch = response.match(/\{[\s\S]*"name"[\s\S]*"systemPrompt"[\s\S]*\}/);
231
+ if (braceMatch) {
232
+ try {
233
+ const parsed = JSON.parse(braceMatch[0]);
234
+ return {
235
+ ...parsed,
236
+ rawResearch: response,
237
+ };
238
+ } catch {
239
+ // JSON parse failed
240
+ }
241
+ }
242
+
243
+ // Fallback — return minimal config
244
+ return {
245
+ name: result.projectName,
246
+ template: result.template.id,
247
+ systemPrompt: `You are a ${result.template.name}. ${result.template.description}`,
248
+ tools: result.template.requiredTools,
249
+ safety: { maxActionsPerDay: 50, maxActionsPerHour: 10 },
250
+ schedule: { cron: "*/30 * * * *", description: "every 30 minutes" },
251
+ selfImprovement: {
252
+ enabled: true,
253
+ reflectionFrequency: "daily",
254
+ metricsToTrack: ["success_rate"],
255
+ },
256
+ rawResearch: response,
257
+ };
258
+ }