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,177 @@
1
+ export class ChatBubbleSystem {
2
+ constructor() {
3
+ this.bubbles = [];
4
+ this.maxBubbles = 5;
5
+ this.bubbleDuration = 6000;
6
+ }
7
+
8
+ addBubble(agentId, text, type = 'normal') {
9
+ const bubble = {
10
+ id: Date.now() + Math.random(),
11
+ agentId,
12
+ text: text.substring(0, 120),
13
+ type,
14
+ createdAt: Date.now(),
15
+ opacity: 0,
16
+ fadeIn: true,
17
+ };
18
+ this.bubbles.push(bubble);
19
+ if (this.bubbles.length > this.maxBubbles) {
20
+ this.bubbles.shift();
21
+ }
22
+ return bubble;
23
+ }
24
+
25
+ update(deltaTime) {
26
+ const now = Date.now();
27
+ this.bubbles = this.bubbles.filter((b) => {
28
+ const age = now - b.createdAt;
29
+ if (age > this.bubbleDuration) return false;
30
+ if (b.fadeIn && b.opacity < 1) {
31
+ b.opacity = Math.min(1, b.opacity + deltaTime * 0.005);
32
+ if (b.opacity >= 1) b.fadeIn = false;
33
+ }
34
+ if (age > this.bubbleDuration - 1000) {
35
+ b.opacity = Math.max(0, (this.bubbleDuration - age) / 1000);
36
+ }
37
+ return true;
38
+ });
39
+ }
40
+
41
+ render(ctx, agents) {
42
+ for (const bubble of this.bubbles) {
43
+ const agent = agents[bubble.agentId] || agents[Object.keys(agents)[0]];
44
+ if (!agent) continue;
45
+
46
+ const x = agent.x;
47
+ const y = agent.y - 60;
48
+ const maxWidth = 200;
49
+ const padding = 8;
50
+
51
+ ctx.save();
52
+ ctx.globalAlpha = bubble.opacity;
53
+
54
+ ctx.font = '12px system-ui, sans-serif';
55
+ const lines = this._wrapText(ctx, bubble.text, maxWidth - padding * 2);
56
+ const lineHeight = 16;
57
+ const boxWidth = Math.min(
58
+ maxWidth,
59
+ Math.max(...lines.map((l) => ctx.measureText(l).width)) + padding * 2
60
+ );
61
+ const boxHeight = lines.length * lineHeight + padding * 2;
62
+
63
+ const colors = {
64
+ normal: '#ffffff',
65
+ thinking: '#fff3cd',
66
+ error: '#f8d7da',
67
+ success: '#d4edda',
68
+ };
69
+ ctx.fillStyle = colors[bubble.type] || colors.normal;
70
+ this._roundRect(ctx, x - boxWidth / 2, y - boxHeight, boxWidth, boxHeight, 8);
71
+ ctx.fill();
72
+ ctx.strokeStyle = '#ccc';
73
+ ctx.lineWidth = 1;
74
+ ctx.stroke();
75
+
76
+ // Triangle pointer
77
+ ctx.beginPath();
78
+ ctx.moveTo(x - 6, y);
79
+ ctx.lineTo(x, y + 8);
80
+ ctx.lineTo(x + 6, y);
81
+ ctx.fillStyle = colors[bubble.type] || colors.normal;
82
+ ctx.fill();
83
+
84
+ // Text
85
+ ctx.fillStyle = bubble.type === 'error' ? '#721c24' : '#333';
86
+ lines.forEach((line, i) => {
87
+ ctx.fillText(
88
+ line,
89
+ x - boxWidth / 2 + padding,
90
+ y - boxHeight + padding + lineHeight * (i + 1)
91
+ );
92
+ });
93
+
94
+ ctx.restore();
95
+ }
96
+ }
97
+
98
+ _wrapText(ctx, text, maxWidth) {
99
+ const words = text.split(' ');
100
+ const lines = [];
101
+ let currentLine = '';
102
+ for (const word of words) {
103
+ const test = currentLine ? currentLine + ' ' + word : word;
104
+ if (ctx.measureText(test).width > maxWidth && currentLine) {
105
+ lines.push(currentLine);
106
+ currentLine = word;
107
+ } else {
108
+ currentLine = test;
109
+ }
110
+ }
111
+ if (currentLine) lines.push(currentLine);
112
+ return lines.length ? lines : [''];
113
+ }
114
+
115
+ _roundRect(ctx, x, y, w, h, r) {
116
+ ctx.beginPath();
117
+ ctx.moveTo(x + r, y);
118
+ ctx.lineTo(x + w - r, y);
119
+ ctx.quadraticCurveTo(x + w, y, x + w, y + r);
120
+ ctx.lineTo(x + w, y + h - r);
121
+ ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
122
+ ctx.lineTo(x + r, y + h);
123
+ ctx.quadraticCurveTo(x, y + h, x, y + h - r);
124
+ ctx.lineTo(x, y + r);
125
+ ctx.quadraticCurveTo(x, y, x + r, y);
126
+ ctx.closePath();
127
+ }
128
+
129
+ generateMessage(agentRole, state) {
130
+ const messages = {
131
+ pm: {
132
+ working: [
133
+ 'Analyzing requirements...',
134
+ 'Writing user stories...',
135
+ 'Prioritizing backlog...',
136
+ 'Reviewing scope...',
137
+ ],
138
+ idle: ['Checking the roadmap', 'Coffee break ☕', 'Reviewing metrics'],
139
+ error: ['Hmm, that needs rework', 'Let me re-evaluate...'],
140
+ },
141
+ architect: {
142
+ working: [
143
+ 'Designing architecture...',
144
+ 'Drawing diagrams...',
145
+ 'Evaluating trade-offs...',
146
+ 'Planning components...',
147
+ ],
148
+ idle: ['Sketching ideas', 'Reading RFCs', 'Contemplating patterns'],
149
+ error: ['This design needs revision', 'Back to the whiteboard...'],
150
+ },
151
+ coder: {
152
+ working: [
153
+ 'Writing code...',
154
+ 'Implementing feature...',
155
+ 'Fixing bugs...',
156
+ 'Refactoring...',
157
+ 'npm install...',
158
+ ],
159
+ idle: ['Browsing Stack Overflow', 'vim or emacs? 🤔', 'git status'],
160
+ error: ['Segfault! 💥', 'Undefined is not a function', 'Works on my machine...'],
161
+ },
162
+ reviewer: {
163
+ working: [
164
+ 'Reviewing code...',
165
+ 'Checking for bugs...',
166
+ 'Running tests...',
167
+ 'Analyzing coverage...',
168
+ ],
169
+ idle: ['Sharpening red pen', 'Reading best practices', 'LGTM 👍'],
170
+ error: ['Found issues...', 'This needs more tests', 'Requesting changes...'],
171
+ },
172
+ };
173
+ const role = messages[agentRole] || messages.coder;
174
+ const stateMessages = role[state] || role.idle;
175
+ return stateMessages[Math.floor(Math.random() * stateMessages.length)];
176
+ }
177
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Cost Overlay — real-time token/cost panel for the office visualizer.
3
+ * Shows budget usage, tokens by stage, and cost by provider.
4
+ */
5
+
6
+ export class CostOverlay {
7
+ constructor(container) {
8
+ this.container = container;
9
+ this.visible = false;
10
+ this.panel = null;
11
+ this.costData = null;
12
+ this._createPanel();
13
+ }
14
+
15
+ _createPanel() {
16
+ this.panel = document.createElement('div');
17
+ this.panel.className = 'cost-overlay-panel';
18
+ this.panel.style.cssText = `
19
+ position: absolute; top: 10px; right: 10px; width: 280px;
20
+ background: rgba(15, 23, 42, 0.95); border: 1px solid #334155;
21
+ border-radius: 12px; padding: 16px; color: #e2e8f0;
22
+ font-family: system-ui, sans-serif; font-size: 12px;
23
+ display: none; z-index: 100; backdrop-filter: blur(8px);
24
+ `;
25
+ this.container.appendChild(this.panel);
26
+ }
27
+
28
+ toggle() {
29
+ this.visible = !this.visible;
30
+ this.panel.style.display = this.visible ? 'block' : 'none';
31
+ if (this.visible) this.fetchAndRender();
32
+ }
33
+
34
+ async fetchAndRender() {
35
+ try {
36
+ const res = await fetch('/api/costs');
37
+ this.costData = await res.json();
38
+ this.render();
39
+ } catch (e) {
40
+ this.panel.innerHTML = '<div style="color:#f87171">Failed to load cost data</div>';
41
+ }
42
+ }
43
+
44
+ render() {
45
+ if (!this.costData) return;
46
+ const data = this.costData;
47
+ const budget = data.budget || 2.00;
48
+ const totalCost = data.totalCost || 0;
49
+ const budgetPct = Math.min(100, (totalCost / budget) * 100);
50
+ const budgetColor = budgetPct > 80 ? '#ef4444' : budgetPct > 50 ? '#f59e0b' : '#22c55e';
51
+
52
+ const byStage = data.byStage || {};
53
+ const maxTokens = Math.max(1, ...Object.values(byStage).map(s => (s.inputTokens || 0) + (s.outputTokens || 0)));
54
+
55
+ const byProvider = data.byProvider || {};
56
+ const providerColors = { gemini: '#4285F4', claude: '#7C3AED', copilot: '#22C55E', ollama: '#F59E0B' };
57
+
58
+ this.panel.innerHTML = `
59
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
60
+ <span style="font-weight:600;font-size:14px">💰 Cost Overview</span>
61
+ <span class="cost-overlay-close" style="cursor:pointer;font-size:18px">×</span>
62
+ </div>
63
+
64
+ <div style="margin-bottom:12px">
65
+ <div style="display:flex;justify-content:space-between;margin-bottom:4px">
66
+ <span>Budget</span>
67
+ <span>$${totalCost.toFixed(4)} / $${budget.toFixed(2)}</span>
68
+ </div>
69
+ <div style="background:#1e293b;border-radius:4px;height:8px;overflow:hidden">
70
+ <div style="background:${budgetColor};height:100%;width:${budgetPct}%;border-radius:4px;transition:width 0.3s"></div>
71
+ </div>
72
+ </div>
73
+
74
+ <div style="margin-bottom:12px">
75
+ <div style="font-weight:500;margin-bottom:6px">Tokens by Stage</div>
76
+ ${['spec', 'architect', 'implement', 'review'].map(stage => {
77
+ const s = byStage[stage] || { inputTokens: 0, outputTokens: 0 };
78
+ const total = (s.inputTokens || 0) + (s.outputTokens || 0);
79
+ const pct = (total / maxTokens) * 100;
80
+ const colors = { spec: '#4285F4', architect: '#7C3AED', implement: '#22C55E', review: '#F59E0B' };
81
+ return `
82
+ <div style="margin-bottom:4px">
83
+ <div style="display:flex;justify-content:space-between;font-size:11px;margin-bottom:2px">
84
+ <span>${stage}</span>
85
+ <span>${total.toLocaleString()} tokens</span>
86
+ </div>
87
+ <div style="background:#1e293b;border-radius:3px;height:6px;overflow:hidden">
88
+ <div style="background:${colors[stage] || '#666'};height:100%;width:${pct}%;border-radius:3px"></div>
89
+ </div>
90
+ </div>
91
+ `;
92
+ }).join('')}
93
+ </div>
94
+
95
+ <div>
96
+ <div style="font-weight:500;margin-bottom:6px">By Provider</div>
97
+ <div style="display:flex;flex-wrap:wrap;gap:8px">
98
+ ${Object.entries(byProvider).map(([provider, stats]) => `
99
+ <div style="display:flex;align-items:center;gap:4px">
100
+ <div style="width:8px;height:8px;border-radius:50%;background:${providerColors[provider] || '#666'}"></div>
101
+ <span>${provider}: $${(stats.cost || 0).toFixed(4)}</span>
102
+ </div>
103
+ `).join('')}
104
+ </div>
105
+ </div>
106
+ `;
107
+
108
+ // Wire close button
109
+ const closeBtn = this.panel.querySelector('.cost-overlay-close');
110
+ if (closeBtn) {
111
+ closeBtn.addEventListener('click', () => {
112
+ this.visible = false;
113
+ this.panel.style.display = 'none';
114
+ });
115
+ }
116
+ }
117
+
118
+ handleEvent(event) {
119
+ if (event.type === 'cost-update' || event.type === 'stage-complete') {
120
+ if (this.visible) this.fetchAndRender();
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,68 @@
1
+ export class DayNightCycle {
2
+ constructor(canvas) {
3
+ this.canvas = canvas;
4
+ this.time = 'day';
5
+ this.autoMode = true;
6
+ this.transitionProgress = 1;
7
+ }
8
+
9
+ getCurrentPhase() {
10
+ if (!this.autoMode) return this.time;
11
+ const hour = new Date().getHours();
12
+ if (hour >= 6 && hour < 10) return 'morning';
13
+ if (hour >= 10 && hour < 17) return 'day';
14
+ if (hour >= 17 && hour < 20) return 'evening';
15
+ return 'night';
16
+ }
17
+
18
+ getColors() {
19
+ const phases = {
20
+ morning: { sky: '#FFE4B5', ambient: 'rgba(255,200,100,0.1)', shadow: 0.2 },
21
+ day: { sky: '#87CEEB', ambient: 'rgba(255,255,255,0)', shadow: 0.3 },
22
+ evening: { sky: '#FF6B6B', ambient: 'rgba(255,100,50,0.15)', shadow: 0.4 },
23
+ night: { sky: '#1a1a2e', ambient: 'rgba(0,0,50,0.3)', shadow: 0.6 },
24
+ };
25
+ return phases[this.getCurrentPhase()];
26
+ }
27
+
28
+ setTime(phase) {
29
+ this.autoMode = false;
30
+ this.time = phase;
31
+ this.transitionProgress = 0;
32
+ }
33
+
34
+ setAutoMode() {
35
+ this.autoMode = true;
36
+ }
37
+
38
+ update(deltaTime) {
39
+ if (this.transitionProgress < 1) {
40
+ this.transitionProgress = Math.min(1, this.transitionProgress + deltaTime * 0.001);
41
+ }
42
+ }
43
+
44
+ applyLighting(ctx, width, height) {
45
+ const colors = this.getColors();
46
+
47
+ ctx.fillStyle = colors.ambient;
48
+ ctx.fillRect(0, 0, width, height);
49
+
50
+ if (this.getCurrentPhase() === 'night') {
51
+ ctx.save();
52
+ ctx.globalAlpha = 0.15;
53
+ ctx.fillStyle = '#ffdd57';
54
+ const windowSize = 12;
55
+ const spacing = 80;
56
+ for (let x = spacing; x < width; x += spacing) {
57
+ for (let y = spacing; y < height * 0.6; y += spacing) {
58
+ if (Math.sin(x * 0.1 + y * 0.07) > 0) {
59
+ ctx.beginPath();
60
+ ctx.arc(x, y, windowSize, 0, Math.PI * 2);
61
+ ctx.fill();
62
+ }
63
+ }
64
+ }
65
+ ctx.restore();
66
+ }
67
+ }
68
+ }