ai-control-center 1.15.2

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +584 -0
  3. package/bin/aicc.js +772 -0
  4. package/lib/actions/approve.js +71 -0
  5. package/lib/actions/assign-project.js +132 -0
  6. package/lib/actions/browser-test.js +64 -0
  7. package/lib/actions/cleanup.js +174 -0
  8. package/lib/actions/debug.js +298 -0
  9. package/lib/actions/deploy.js +1229 -0
  10. package/lib/actions/fix-bug.js +134 -0
  11. package/lib/actions/new-feature.js +255 -0
  12. package/lib/actions/reject.js +307 -0
  13. package/lib/actions/review.js +706 -0
  14. package/lib/actions/status.js +47 -0
  15. package/lib/agents/browser-qa-agent.js +611 -0
  16. package/lib/agents/payment-agent.js +116 -0
  17. package/lib/agents/suggestion-agent.js +88 -0
  18. package/lib/cli.js +303 -0
  19. package/lib/config.js +243 -0
  20. package/lib/hub/hub-server.js +440 -0
  21. package/lib/hub/project-poller.js +75 -0
  22. package/lib/hub/skill-registry.js +89 -0
  23. package/lib/hub/state-aggregator.js +204 -0
  24. package/lib/index.js +471 -0
  25. package/lib/init/doctor.js +523 -0
  26. package/lib/init/presets.js +222 -0
  27. package/lib/init/skill-fetcher.js +77 -0
  28. package/lib/init/wizard.js +973 -0
  29. package/lib/integrations/codex-runner.js +128 -0
  30. package/lib/integrations/github-actions.js +248 -0
  31. package/lib/integrations/github-reporter.js +229 -0
  32. package/lib/integrations/screenshot-store.js +102 -0
  33. package/lib/openclaw/bridge.js +650 -0
  34. package/lib/openclaw/generate-skill.js +235 -0
  35. package/lib/openclaw/openclaw.json +64 -0
  36. package/lib/orchestrator/autonomous-loop.js +429 -0
  37. package/lib/orchestrator/thread-triggers.js +63 -0
  38. package/lib/roleplay/agent-messenger.js +75 -0
  39. package/lib/roleplay/discussion-threads.js +303 -0
  40. package/lib/roleplay/health-monitor.js +121 -0
  41. package/lib/roleplay/pm-agent.js +513 -0
  42. package/lib/roleplay/roleplay-config.js +25 -0
  43. package/lib/roleplay/room.js +164 -0
  44. package/lib/shared/action-runner.js +2330 -0
  45. package/lib/shared/event-bus.js +185 -0
  46. package/lib/slack/bot.js +378 -0
  47. package/lib/telegram/bot.js +416 -0
  48. package/lib/telegram/commands.js +1267 -0
  49. package/lib/telegram/keyboards.js +113 -0
  50. package/lib/telegram/notifications.js +247 -0
  51. package/lib/twitch/bot.js +354 -0
  52. package/lib/twitch/commands.js +302 -0
  53. package/lib/twitch/notifications.js +63 -0
  54. package/lib/utils/achievements.js +191 -0
  55. package/lib/utils/activity-log.js +182 -0
  56. package/lib/utils/agent-leaderboard.js +119 -0
  57. package/lib/utils/audit-logger.js +232 -0
  58. package/lib/utils/codebase-context.js +288 -0
  59. package/lib/utils/codebase-indexer.js +381 -0
  60. package/lib/utils/config-schema.js +230 -0
  61. package/lib/utils/context-compressor.js +172 -0
  62. package/lib/utils/correlation.js +63 -0
  63. package/lib/utils/cost-tracker.js +423 -0
  64. package/lib/utils/cron-scheduler.js +53 -0
  65. package/lib/utils/db-adapter.js +293 -0
  66. package/lib/utils/display.js +272 -0
  67. package/lib/utils/errors.js +116 -0
  68. package/lib/utils/format.js +134 -0
  69. package/lib/utils/intent-engine.js +464 -0
  70. package/lib/utils/mcp-client.js +238 -0
  71. package/lib/utils/model-ab-test.js +164 -0
  72. package/lib/utils/notify.js +122 -0
  73. package/lib/utils/persona-loader.js +80 -0
  74. package/lib/utils/pipeline-lock.js +73 -0
  75. package/lib/utils/pipeline.js +214 -0
  76. package/lib/utils/plugin-runner.js +234 -0
  77. package/lib/utils/rate-limiter.js +84 -0
  78. package/lib/utils/rbac.js +74 -0
  79. package/lib/utils/runner.js +1809 -0
  80. package/lib/utils/security.js +191 -0
  81. package/lib/utils/self-healer.js +144 -0
  82. package/lib/utils/skill-loader.js +255 -0
  83. package/lib/utils/spinner.js +132 -0
  84. package/lib/utils/stage-queue.js +50 -0
  85. package/lib/utils/state-machine.js +89 -0
  86. package/lib/utils/status-bar.js +327 -0
  87. package/lib/utils/token-estimator.js +101 -0
  88. package/lib/utils/ux-analyzer.js +101 -0
  89. package/lib/utils/webhook-emitter.js +83 -0
  90. package/lib/web/public/css/styles.css +417 -0
  91. package/lib/web/public/dark-mode.js +44 -0
  92. package/lib/web/public/hub/kanban.html +206 -0
  93. package/lib/web/public/index.html +45 -0
  94. package/lib/web/public/js/app.js +71 -0
  95. package/lib/web/public/js/ask.js +110 -0
  96. package/lib/web/public/js/dashboard.js +165 -0
  97. package/lib/web/public/js/deploy.js +72 -0
  98. package/lib/web/public/js/feature.js +79 -0
  99. package/lib/web/public/js/health.js +65 -0
  100. package/lib/web/public/js/logs.js +93 -0
  101. package/lib/web/public/js/review.js +123 -0
  102. package/lib/web/public/js/ws-client.js +82 -0
  103. package/lib/web/public/office/css/office.css +678 -0
  104. package/lib/web/public/office/index.html +148 -0
  105. package/lib/web/public/office/js/achievements-ui.js +117 -0
  106. package/lib/web/public/office/js/character.js +1056 -0
  107. package/lib/web/public/office/js/chat-bubbles.js +177 -0
  108. package/lib/web/public/office/js/cost-overlay.js +123 -0
  109. package/lib/web/public/office/js/day-night.js +68 -0
  110. package/lib/web/public/office/js/effects.js +632 -0
  111. package/lib/web/public/office/js/engine.js +146 -0
  112. package/lib/web/public/office/js/feature-ticket.js +216 -0
  113. package/lib/web/public/office/js/hub-client.js +60 -0
  114. package/lib/web/public/office/js/main.js +1757 -0
  115. package/lib/web/public/office/js/office-layout.js +1524 -0
  116. package/lib/web/public/office/js/pathfinding.js +144 -0
  117. package/lib/web/public/office/js/pixel-sprites.js +1454 -0
  118. package/lib/web/public/office/js/progress-bars.js +117 -0
  119. package/lib/web/public/office/js/replay.js +191 -0
  120. package/lib/web/public/office/js/sound-effects.js +91 -0
  121. package/lib/web/public/office/js/sprite-renderer.js +211 -0
  122. package/lib/web/public/office/js/stamina-system.js +89 -0
  123. package/lib/web/public/office/js/ui.js +107 -0
  124. package/lib/web/public/onboarding/index.html +243 -0
  125. package/lib/web/public/timeline/index.html +195 -0
  126. package/lib/web/routes/api.js +499 -0
  127. package/lib/web/routes/logs.js +20 -0
  128. package/lib/web/routes/metrics.js +99 -0
  129. package/lib/web/server.js +183 -0
  130. package/lib/web/ws/handler.js +65 -0
  131. package/package.json +67 -0
  132. package/templates/agent-architect.md +69 -0
  133. package/templates/agent-gemini-pm.md +49 -0
  134. package/templates/agent-gemini-reviewer.md +52 -0
  135. package/templates/copilot-instructions.md +36 -0
  136. package/templates/pipelines/mobile.json +27 -0
  137. package/templates/pipelines/nodejs-api.json +27 -0
  138. package/templates/pipelines/python.json +27 -0
  139. package/templates/pipelines/react.json +27 -0
  140. package/templates/pipelines/salesforce.json +27 -0
  141. package/templates/role-gemini.md +97 -0
  142. package/templates/skill-architect.md +114 -0
  143. package/templates/skill-browser-qa.md +50 -0
  144. package/templates/skill-bug-from-qa.md +58 -0
  145. package/templates/skill-chatbot.md +93 -0
  146. package/templates/skill-implement.md +78 -0
  147. package/templates/skill-openclaw.md +174 -0
  148. package/templates/skill-payment.md +110 -0
  149. package/templates/skill-pm-spec.md +77 -0
  150. package/templates/skill-requirement-capture.md +97 -0
  151. package/templates/skill-review.md +108 -0
  152. package/templates/skill-reviewer-qa.md +44 -0
  153. package/templates/skill-suggestion.md +45 -0
  154. package/templates/skill-template.md +142 -0
@@ -0,0 +1,235 @@
1
+ /**
2
+ * OpenClaw skill generator.
3
+ *
4
+ * Reads the project's aicc.config.js and generates ALL skill files:
5
+ * 1. SKILL.md — PM Agent (main conversational skill)
6
+ * 2. SKILL-requirement-capture.md — Requirement analysis before pipeline
7
+ * 3. SKILL-pm-spec.md — PM spec writing (stage: spec)
8
+ * 4. SKILL-architect.md — Architecture design (stage: arch)
9
+ * 5. SKILL-implement.md — Implementation coding (stage: impl)
10
+ * 6. SKILL-review.md — Code review (stage: review)
11
+ *
12
+ * Skills are written to:
13
+ * - ~/.openclaw/skills/<project-slug>/ (for OpenClaw Gateway)
14
+ * - .ai-workflow/skills/ (for AICC skill-loader injection)
15
+ */
16
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
17
+ import { resolve, dirname } from 'path';
18
+ import { fileURLToPath } from 'url';
19
+ import { spawnSync } from 'child_process';
20
+ import { getConfig } from '../config.js';
21
+ import chalk from 'chalk';
22
+
23
+ const __dirname = dirname(fileURLToPath(import.meta.url));
24
+
25
+ // ─── Skill definitions ──────────────────────────────────────────────────────
26
+
27
+ const STAGE_SKILLS = [
28
+ { template: 'skill-openclaw.md', output: 'SKILL.md', stage: null },
29
+ { template: 'skill-requirement-capture.md', output: 'SKILL-requirement-capture.md', stage: 'capture' },
30
+ { template: 'skill-pm-spec.md', output: 'SKILL-pm-spec.md', stage: 'spec' },
31
+ { template: 'skill-architect.md', output: 'SKILL-architect.md', stage: 'arch' },
32
+ { template: 'skill-implement.md', output: 'SKILL-implement.md', stage: 'impl' },
33
+ { template: 'skill-review.md', output: 'SKILL-review.md', stage: 'review' },
34
+ ];
35
+
36
+ // ─── Template substitution ───────────────────────────────────────────────────
37
+
38
+ function buildTemplateVars(config) {
39
+ // Stages table
40
+ const stagesLines = Object.entries(config.stages)
41
+ .map(([key, meta]) => `| \`${key}\` | ${meta.label} |`)
42
+ .join('\n');
43
+ const stagesTable = `| Stage Key | Label |\n|-----------|-------|\n${stagesLines}`;
44
+
45
+ // Queries section
46
+ let queriesSection = '_No custom queries configured._';
47
+ if (config.queries && config.queries.length) {
48
+ queriesSection = config.queries
49
+ .map(q => `- **${q.name}** (\`${q.key}\`): \`${q.command}\``)
50
+ .join('\n');
51
+ }
52
+
53
+ // Extra commands
54
+ let extraCommands = '';
55
+ if (config.debug?.commands?.length) {
56
+ extraCommands = '\n### Debug Commands\n\n' +
57
+ config.debug.commands.map(c => `- **${c.name}**: \`${c.command}\``).join('\n');
58
+ }
59
+
60
+ // Pipeline info
61
+ const pipeline = config.pipeline || [];
62
+ if (pipeline.length) {
63
+ const pipelineLines = pipeline
64
+ .map(e => `- **${e.stage}**: \`${e.provider}\` → \`${e.model}\`${e.fallbacks?.length ? ` (fallbacks: ${e.fallbacks.join(', ')})` : ''}`)
65
+ .join('\n');
66
+ extraCommands += '\n### Pipeline Configuration\n\n' + pipelineLines;
67
+ }
68
+
69
+ return {
70
+ PROJECT_NAME: config.name,
71
+ DESCRIPTION: config.description || `AI Control Center for ${config.name}`,
72
+ PROJECT_ROOT: config._root,
73
+ PROJECT_DESCRIPTION: config.description || `AI Control Center for ${config.name}`,
74
+ STAGES: stagesTable,
75
+ QUERIES: queriesSection,
76
+ WORKFLOW_DIR: config._workflowDir,
77
+ EXTRA_COMMANDS: extraCommands,
78
+ };
79
+ }
80
+
81
+ function applyTemplate(content, vars) {
82
+ let result = content;
83
+ for (const [key, value] of Object.entries(vars)) {
84
+ result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
85
+ }
86
+ return result;
87
+ }
88
+
89
+ // ─── Main generator ──────────────────────────────────────────────────────────
90
+
91
+ /**
92
+ * Generate pipeline skills from templates.
93
+ * Works with or without OpenClaw CLI installed:
94
+ * - ALWAYS writes stage skills to .ai-workflow/skills/ (required for pipeline)
95
+ * - Optionally writes to ~/.openclaw/skills/<slug>/ and manages gateway
96
+ */
97
+ export async function generateSkill() {
98
+ const config = getConfig();
99
+ const slug = config.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
100
+ const vars = buildTemplateVars(config);
101
+
102
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
103
+ const templateDir = resolve(__dirname, '../../templates');
104
+
105
+ // ── Step 1: Always generate to .ai-workflow/skills/ (pipeline needs these) ──
106
+ const workflowSkillDir = resolve(config._workflowDir, 'skills');
107
+ mkdirSync(workflowSkillDir, { recursive: true });
108
+
109
+ let generated = 0;
110
+ console.log('');
111
+
112
+ for (const def of STAGE_SKILLS) {
113
+ const templatePath = resolve(templateDir, def.template);
114
+ if (!existsSync(templatePath)) {
115
+ console.log(chalk.yellow(` ~ Template not found: ${def.template} — skipping`));
116
+ continue;
117
+ }
118
+
119
+ const raw = readFileSync(templatePath, 'utf8');
120
+ const rendered = applyTemplate(raw, vars);
121
+
122
+ // Always write stage skills to .ai-workflow/skills/ for pipeline injection
123
+ if (def.stage) {
124
+ const workflowPath = resolve(workflowSkillDir, def.output);
125
+ writeFileSync(workflowPath, rendered);
126
+ }
127
+
128
+ generated++;
129
+ }
130
+
131
+ console.log(chalk.green(` ✓ Generated ${generated} pipeline skills → ${workflowSkillDir}`));
132
+
133
+ // ── Step 2: Optionally write to OpenClaw directory + manage gateway ─────────
134
+ const hasOpenClaw = spawnSync('which', ['openclaw'], { encoding: 'utf8' }).status === 0;
135
+ const openclawConfigExists = existsSync(resolve(homeDir, '.openclaw', 'openclaw.json'));
136
+
137
+ if (hasOpenClaw || openclawConfigExists) {
138
+ const openclawSkillDir = resolve(homeDir, '.openclaw', 'skills', slug);
139
+ mkdirSync(openclawSkillDir, { recursive: true });
140
+
141
+ for (const def of STAGE_SKILLS) {
142
+ const templatePath = resolve(templateDir, def.template);
143
+ if (!existsSync(templatePath)) continue;
144
+ const raw = readFileSync(templatePath, 'utf8');
145
+ const rendered = applyTemplate(raw, vars);
146
+ writeFileSync(resolve(openclawSkillDir, def.output), rendered);
147
+ }
148
+
149
+ console.log(chalk.green(` ✓ OpenClaw skills → ${openclawSkillDir}`));
150
+ registerInOpenClawConfig(slug, homeDir);
151
+
152
+ if (hasOpenClaw) {
153
+ await restartGateway(config.name);
154
+ }
155
+ } else {
156
+ console.log(chalk.dim(' · OpenClaw not installed — pipeline skills are sufficient'));
157
+ }
158
+
159
+ console.log('');
160
+ }
161
+
162
+ // ─── OpenClaw config registration ────────────────────────────────────────────
163
+
164
+ function registerInOpenClawConfig(slug, homeDir) {
165
+ const configPath = resolve(homeDir, '.openclaw', 'openclaw.json');
166
+ if (!existsSync(configPath)) return;
167
+
168
+ try {
169
+ const ocConfig = JSON.parse(readFileSync(configPath, 'utf8'));
170
+ if (!ocConfig.skills) ocConfig.skills = {};
171
+ if (!ocConfig.skills.entries) ocConfig.skills.entries = {};
172
+ const skills = ocConfig.skills.entries;
173
+
174
+ if (!skills[slug]) {
175
+ skills[slug] = { enabled: true };
176
+ writeFileSync(configPath, JSON.stringify(ocConfig, null, 2));
177
+ console.log(chalk.green(` ✓ Auto-registered skill "${slug}" in openclaw.json`));
178
+ } else if (!skills[slug].enabled) {
179
+ skills[slug].enabled = true;
180
+ writeFileSync(configPath, JSON.stringify(ocConfig, null, 2));
181
+ console.log(chalk.green(` ✓ Enabled skill "${slug}" in openclaw.json`));
182
+ } else {
183
+ console.log(chalk.green(` ✓ Skill "${slug}" already enabled in openclaw.json`));
184
+ }
185
+ } catch (err) {
186
+ console.log(chalk.yellow(` ~ Could not update openclaw.json: ${err.message}`));
187
+ console.log(chalk.white(` Add manually: "${slug}": { "enabled": true }`));
188
+ }
189
+ }
190
+
191
+ // ─── Gateway management ──────────────────────────────────────────────────────
192
+
193
+ async function restartGateway(projectName) {
194
+ const which = spawnSync('which', ['openclaw'], { encoding: 'utf8' });
195
+ if (which.status !== 0) {
196
+ console.log(chalk.yellow(' ~ openclaw CLI not found — skipping gateway restart'));
197
+ console.log(chalk.dim(' Install OpenClaw to enable automatic gateway management'));
198
+ console.log('');
199
+ return;
200
+ }
201
+
202
+ console.log(chalk.cyan(' ↻ Managing OpenClaw gateway...'));
203
+
204
+ const statusResult = spawnSync('openclaw', ['gateway', 'status'], { encoding: 'utf8' });
205
+ const statusOut = (statusResult.stdout || '') + (statusResult.stderr || '');
206
+ const isNotLoaded = statusOut.includes('not loaded') || statusOut.includes('not running');
207
+ const isRunning = statusOut.includes('running') && !isNotLoaded;
208
+
209
+ if (isRunning) {
210
+ const restart = spawnSync('openclaw', ['gateway', 'restart'], { encoding: 'utf8', stdio: 'inherit' });
211
+ if (restart.status === 0) {
212
+ console.log(chalk.green(' ✓ Gateway restarted — all skills are live'));
213
+ } else {
214
+ console.log(chalk.yellow(' ~ Gateway restart returned non-zero — check manually'));
215
+ }
216
+ } else {
217
+ console.log(chalk.dim(' Gateway not running — installing as system service...'));
218
+ const install = spawnSync('openclaw', ['gateway', 'install'], { encoding: 'utf8', stdio: 'inherit' });
219
+ if (install.status === 0) {
220
+ console.log(chalk.green(' ✓ Gateway installed and started'));
221
+ } else {
222
+ const start = spawnSync('openclaw', ['gateway'], { encoding: 'utf8', stdio: 'inherit', detached: true });
223
+ if (start.status === 0 || start.status === null) {
224
+ console.log(chalk.green(' ✓ Gateway started'));
225
+ } else {
226
+ console.log(chalk.yellow(' ~ Could not start gateway automatically'));
227
+ console.log(chalk.white(' Run manually: openclaw gateway install'));
228
+ }
229
+ }
230
+ }
231
+
232
+ console.log('');
233
+ console.log(chalk.green(` ✓ Skills are active. Test in Telegram: "${chalk.bold(`What is the status of ${projectName}?`)}"`));
234
+ console.log('');
235
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "$schema": "https://openclaw.ai/schema/config.json",
3
+
4
+ "models": {
5
+ "providers": {
6
+ "ollama": {
7
+ "baseUrl": "http://localhost:11434",
8
+ "api": "ollama",
9
+ "models": [
10
+ {
11
+ "id": "llama3.1:8b",
12
+ "name": "Llama 3.1 8B",
13
+ "reasoning": false,
14
+ "input": ["text"],
15
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
16
+ "contextWindow": 32768,
17
+ "maxTokens": 32768
18
+ }
19
+ ]
20
+ }
21
+ }
22
+ },
23
+ "agents": {
24
+ "defaults": {
25
+ "model": {
26
+ "primary": "ollama/llama3.1:8b",
27
+ "fallbacks": ["github-copilot/claude-sonnet-4.6"]
28
+ }
29
+ }
30
+ },
31
+
32
+ "channels": {
33
+ "telegram": {
34
+ "enabled": true,
35
+ "botToken": "YOUR_TELEGRAM_BOT_TOKEN",
36
+ "dmPolicy": "pairing",
37
+ "streaming": "partial",
38
+ "groups": {
39
+ "*": { "requireMention": true }
40
+ }
41
+ }
42
+ },
43
+
44
+ "tools": {
45
+ "profile": "coding",
46
+ "allow": ["bash", "read", "write", "exec"]
47
+ },
48
+
49
+ "skills": {
50
+ "entries": {
51
+ "aicc": {
52
+ "enabled": true
53
+ }
54
+ }
55
+ },
56
+
57
+ "session": {
58
+ "historyLimit": 50
59
+ },
60
+
61
+ "gateway": {
62
+ "port": 18789
63
+ }
64
+ }