50c 3.3.0 ā 3.7.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.
- package/bin/50c.js +207 -2
- package/lib/invent-ui.js +717 -0
- package/lib/mcp-tv.js +1015 -0
- package/lib/team.js +47 -5
- package/package.json +1 -1
package/lib/invent-ui.js
ADDED
|
@@ -0,0 +1,717 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 50c Invent UI - Real-time Swarm Visualization
|
|
4
|
+
* Opens a dark-mode browser window showing pipeline progress
|
|
5
|
+
* "MCP TV" - watch your invention happen live!
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const http = require('http');
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
let clients = [];
|
|
13
|
+
let inventionState = {
|
|
14
|
+
problem: '',
|
|
15
|
+
domain: 'code',
|
|
16
|
+
rigor: 'deep',
|
|
17
|
+
status: 'initializing',
|
|
18
|
+
stages: [],
|
|
19
|
+
currentStage: null,
|
|
20
|
+
result: null,
|
|
21
|
+
startTime: Date.now(),
|
|
22
|
+
angles: [],
|
|
23
|
+
priorArt: [],
|
|
24
|
+
proofs: []
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const HTML_PAGE = `<!DOCTYPE html>
|
|
28
|
+
<html lang="en">
|
|
29
|
+
<head>
|
|
30
|
+
<meta charset="UTF-8">
|
|
31
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
32
|
+
<title>50c Auto-Invent | MCP TV</title>
|
|
33
|
+
<style>
|
|
34
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
35
|
+
|
|
36
|
+
body {
|
|
37
|
+
background: linear-gradient(135deg, #0a0a0f 0%, #1a1a2e 50%, #0f0f1a 100%);
|
|
38
|
+
color: #e0e0e0;
|
|
39
|
+
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
|
|
40
|
+
min-height: 100vh;
|
|
41
|
+
overflow-x: hidden;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.container {
|
|
45
|
+
max-width: 1400px;
|
|
46
|
+
margin: 0 auto;
|
|
47
|
+
padding: 20px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Header */
|
|
51
|
+
.header {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
padding: 20px 0;
|
|
56
|
+
border-bottom: 1px solid rgba(0, 255, 136, 0.2);
|
|
57
|
+
margin-bottom: 30px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.logo {
|
|
61
|
+
font-size: 28px;
|
|
62
|
+
font-weight: bold;
|
|
63
|
+
background: linear-gradient(90deg, #00ff88, #00d4ff);
|
|
64
|
+
-webkit-background-clip: text;
|
|
65
|
+
-webkit-text-fill-color: transparent;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.status-badge {
|
|
69
|
+
padding: 8px 16px;
|
|
70
|
+
border-radius: 20px;
|
|
71
|
+
font-size: 12px;
|
|
72
|
+
text-transform: uppercase;
|
|
73
|
+
letter-spacing: 1px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.status-running { background: rgba(255, 200, 0, 0.2); color: #ffc800; border: 1px solid #ffc800; }
|
|
77
|
+
.status-complete { background: rgba(0, 255, 136, 0.2); color: #00ff88; border: 1px solid #00ff88; }
|
|
78
|
+
.status-error { background: rgba(255, 68, 68, 0.2); color: #ff4444; border: 1px solid #ff4444; }
|
|
79
|
+
|
|
80
|
+
/* Problem Display */
|
|
81
|
+
.problem-card {
|
|
82
|
+
background: rgba(255, 255, 255, 0.03);
|
|
83
|
+
border: 1px solid rgba(0, 255, 136, 0.1);
|
|
84
|
+
border-radius: 12px;
|
|
85
|
+
padding: 24px;
|
|
86
|
+
margin-bottom: 30px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.problem-label {
|
|
90
|
+
font-size: 11px;
|
|
91
|
+
color: #888;
|
|
92
|
+
text-transform: uppercase;
|
|
93
|
+
letter-spacing: 2px;
|
|
94
|
+
margin-bottom: 8px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.problem-text {
|
|
98
|
+
font-size: 20px;
|
|
99
|
+
color: #fff;
|
|
100
|
+
line-height: 1.4;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.meta-row {
|
|
104
|
+
display: flex;
|
|
105
|
+
gap: 20px;
|
|
106
|
+
margin-top: 16px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.meta-item {
|
|
110
|
+
background: rgba(0, 212, 255, 0.1);
|
|
111
|
+
padding: 6px 12px;
|
|
112
|
+
border-radius: 6px;
|
|
113
|
+
font-size: 12px;
|
|
114
|
+
color: #00d4ff;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Pipeline Visualization */
|
|
118
|
+
.pipeline {
|
|
119
|
+
display: flex;
|
|
120
|
+
gap: 8px;
|
|
121
|
+
flex-wrap: wrap;
|
|
122
|
+
margin-bottom: 30px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.stage {
|
|
126
|
+
flex: 1;
|
|
127
|
+
min-width: 120px;
|
|
128
|
+
background: rgba(255, 255, 255, 0.02);
|
|
129
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
130
|
+
border-radius: 8px;
|
|
131
|
+
padding: 16px;
|
|
132
|
+
transition: all 0.3s ease;
|
|
133
|
+
position: relative;
|
|
134
|
+
overflow: hidden;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.stage::before {
|
|
138
|
+
content: '';
|
|
139
|
+
position: absolute;
|
|
140
|
+
top: 0;
|
|
141
|
+
left: 0;
|
|
142
|
+
width: 100%;
|
|
143
|
+
height: 3px;
|
|
144
|
+
background: rgba(255, 255, 255, 0.1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.stage.pending::before { background: rgba(255, 255, 255, 0.1); }
|
|
148
|
+
.stage.running::before {
|
|
149
|
+
background: linear-gradient(90deg, #ffc800, #ff8800);
|
|
150
|
+
animation: pulse 1s infinite;
|
|
151
|
+
}
|
|
152
|
+
.stage.complete::before { background: #00ff88; }
|
|
153
|
+
.stage.error::before { background: #ff4444; }
|
|
154
|
+
|
|
155
|
+
.stage.running {
|
|
156
|
+
border-color: #ffc800;
|
|
157
|
+
box-shadow: 0 0 20px rgba(255, 200, 0, 0.2);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.stage.complete {
|
|
161
|
+
border-color: rgba(0, 255, 136, 0.3);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@keyframes pulse {
|
|
165
|
+
0%, 100% { opacity: 1; }
|
|
166
|
+
50% { opacity: 0.5; }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.stage-icon {
|
|
170
|
+
font-size: 24px;
|
|
171
|
+
margin-bottom: 8px;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.stage-name {
|
|
175
|
+
font-size: 11px;
|
|
176
|
+
color: #888;
|
|
177
|
+
text-transform: uppercase;
|
|
178
|
+
letter-spacing: 1px;
|
|
179
|
+
margin-bottom: 4px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.stage-status {
|
|
183
|
+
font-size: 12px;
|
|
184
|
+
color: #aaa;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.stage-time {
|
|
188
|
+
font-size: 10px;
|
|
189
|
+
color: #666;
|
|
190
|
+
margin-top: 8px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* Results Section */
|
|
194
|
+
.results {
|
|
195
|
+
display: none;
|
|
196
|
+
animation: fadeIn 0.5s ease;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.results.visible { display: block; }
|
|
200
|
+
|
|
201
|
+
@keyframes fadeIn {
|
|
202
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
203
|
+
to { opacity: 1; transform: translateY(0); }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.result-section {
|
|
207
|
+
background: rgba(255, 255, 255, 0.02);
|
|
208
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
209
|
+
border-radius: 12px;
|
|
210
|
+
padding: 24px;
|
|
211
|
+
margin-bottom: 20px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.result-section h3 {
|
|
215
|
+
font-size: 14px;
|
|
216
|
+
color: #00ff88;
|
|
217
|
+
text-transform: uppercase;
|
|
218
|
+
letter-spacing: 2px;
|
|
219
|
+
margin-bottom: 16px;
|
|
220
|
+
display: flex;
|
|
221
|
+
align-items: center;
|
|
222
|
+
gap: 8px;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.angles-grid {
|
|
226
|
+
display: grid;
|
|
227
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
228
|
+
gap: 12px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.angle-card {
|
|
232
|
+
background: rgba(0, 212, 255, 0.05);
|
|
233
|
+
border: 1px solid rgba(0, 212, 255, 0.2);
|
|
234
|
+
border-radius: 8px;
|
|
235
|
+
padding: 16px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.angle-card:hover {
|
|
239
|
+
border-color: #00d4ff;
|
|
240
|
+
background: rgba(0, 212, 255, 0.1);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.solution-content {
|
|
244
|
+
background: #0a0a0f;
|
|
245
|
+
border-radius: 8px;
|
|
246
|
+
padding: 20px;
|
|
247
|
+
font-size: 14px;
|
|
248
|
+
line-height: 1.8;
|
|
249
|
+
max-height: 600px;
|
|
250
|
+
overflow-y: auto;
|
|
251
|
+
white-space: pre-wrap;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.solution-content::-webkit-scrollbar {
|
|
255
|
+
width: 8px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.solution-content::-webkit-scrollbar-track {
|
|
259
|
+
background: rgba(255, 255, 255, 0.05);
|
|
260
|
+
border-radius: 4px;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.solution-content::-webkit-scrollbar-thumb {
|
|
264
|
+
background: rgba(0, 255, 136, 0.3);
|
|
265
|
+
border-radius: 4px;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Stats Footer */
|
|
269
|
+
.stats-footer {
|
|
270
|
+
display: flex;
|
|
271
|
+
justify-content: space-between;
|
|
272
|
+
padding: 20px;
|
|
273
|
+
background: rgba(0, 0, 0, 0.3);
|
|
274
|
+
border-radius: 12px;
|
|
275
|
+
margin-top: 30px;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.stat {
|
|
279
|
+
text-align: center;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.stat-value {
|
|
283
|
+
font-size: 24px;
|
|
284
|
+
font-weight: bold;
|
|
285
|
+
color: #00ff88;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.stat-label {
|
|
289
|
+
font-size: 11px;
|
|
290
|
+
color: #666;
|
|
291
|
+
text-transform: uppercase;
|
|
292
|
+
letter-spacing: 1px;
|
|
293
|
+
margin-top: 4px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Loading Animation */
|
|
297
|
+
.loader {
|
|
298
|
+
display: inline-block;
|
|
299
|
+
width: 20px;
|
|
300
|
+
height: 20px;
|
|
301
|
+
border: 2px solid rgba(255, 200, 0, 0.3);
|
|
302
|
+
border-top-color: #ffc800;
|
|
303
|
+
border-radius: 50%;
|
|
304
|
+
animation: spin 1s linear infinite;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
@keyframes spin {
|
|
308
|
+
to { transform: rotate(360deg); }
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* Markdown-like styling */
|
|
312
|
+
.solution-content h1, .solution-content h2, .solution-content h3 {
|
|
313
|
+
color: #00ff88;
|
|
314
|
+
margin: 20px 0 10px 0;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.solution-content code {
|
|
318
|
+
background: rgba(0, 212, 255, 0.1);
|
|
319
|
+
padding: 2px 6px;
|
|
320
|
+
border-radius: 4px;
|
|
321
|
+
color: #00d4ff;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.solution-content pre {
|
|
325
|
+
background: rgba(0, 0, 0, 0.5);
|
|
326
|
+
padding: 16px;
|
|
327
|
+
border-radius: 8px;
|
|
328
|
+
overflow-x: auto;
|
|
329
|
+
margin: 12px 0;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.solution-content table {
|
|
333
|
+
width: 100%;
|
|
334
|
+
border-collapse: collapse;
|
|
335
|
+
margin: 16px 0;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.solution-content th, .solution-content td {
|
|
339
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
340
|
+
padding: 8px 12px;
|
|
341
|
+
text-align: left;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.solution-content th {
|
|
345
|
+
background: rgba(0, 255, 136, 0.1);
|
|
346
|
+
color: #00ff88;
|
|
347
|
+
}
|
|
348
|
+
</style>
|
|
349
|
+
</head>
|
|
350
|
+
<body>
|
|
351
|
+
<div class="container">
|
|
352
|
+
<header class="header">
|
|
353
|
+
<div class="logo">š¬ 50c Auto-Invent</div>
|
|
354
|
+
<div id="status" class="status-badge status-running">Initializing</div>
|
|
355
|
+
</header>
|
|
356
|
+
|
|
357
|
+
<div class="problem-card">
|
|
358
|
+
<div class="problem-label">Problem Statement</div>
|
|
359
|
+
<div id="problem" class="problem-text">Loading...</div>
|
|
360
|
+
<div class="meta-row">
|
|
361
|
+
<span id="domain" class="meta-item">Domain: code</span>
|
|
362
|
+
<span id="rigor" class="meta-item">Rigor: deep</span>
|
|
363
|
+
<span id="cost" class="meta-item">Cost: $2.00</span>
|
|
364
|
+
</div>
|
|
365
|
+
</div>
|
|
366
|
+
|
|
367
|
+
<div id="pipeline" class="pipeline"></div>
|
|
368
|
+
|
|
369
|
+
<div id="results" class="results">
|
|
370
|
+
<div id="angles-section" class="result-section" style="display:none;">
|
|
371
|
+
<h3>š Creative Angles</h3>
|
|
372
|
+
<div id="angles" class="angles-grid"></div>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
<div class="result-section">
|
|
376
|
+
<h3>š” Solution</h3>
|
|
377
|
+
<div id="solution" class="solution-content">Generating...</div>
|
|
378
|
+
</div>
|
|
379
|
+
|
|
380
|
+
<div id="proofs-section" class="result-section" style="display:none;">
|
|
381
|
+
<h3>ā Verification Proofs</h3>
|
|
382
|
+
<div id="proofs"></div>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
|
|
386
|
+
<div class="stats-footer">
|
|
387
|
+
<div class="stat">
|
|
388
|
+
<div id="duration" class="stat-value">0.0s</div>
|
|
389
|
+
<div class="stat-label">Duration</div>
|
|
390
|
+
</div>
|
|
391
|
+
<div class="stat">
|
|
392
|
+
<div id="stages-complete" class="stat-value">0/0</div>
|
|
393
|
+
<div class="stat-label">Stages</div>
|
|
394
|
+
</div>
|
|
395
|
+
<div class="stat">
|
|
396
|
+
<div id="verified" class="stat-value">ā</div>
|
|
397
|
+
<div class="stat-label">Verified</div>
|
|
398
|
+
</div>
|
|
399
|
+
<div class="stat">
|
|
400
|
+
<div id="confidence" class="stat-value">--</div>
|
|
401
|
+
<div class="stat-label">Confidence</div>
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
405
|
+
|
|
406
|
+
<script>
|
|
407
|
+
const eventSource = new EventSource('/events');
|
|
408
|
+
let startTime = Date.now();
|
|
409
|
+
|
|
410
|
+
const STAGE_ICONS = {
|
|
411
|
+
'mind_opener': 'š§ ',
|
|
412
|
+
'idea_fold': 'š¬',
|
|
413
|
+
'bcalc': 'š',
|
|
414
|
+
'web_search': 'š',
|
|
415
|
+
'genius_plus': 'š”',
|
|
416
|
+
'cvi_verify': 'ā',
|
|
417
|
+
'roast': 'š„',
|
|
418
|
+
'compute': 'ā”'
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
eventSource.onmessage = (event) => {
|
|
422
|
+
const data = JSON.parse(event.data);
|
|
423
|
+
updateUI(data);
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
function updateUI(state) {
|
|
427
|
+
// Update problem
|
|
428
|
+
document.getElementById('problem').textContent = state.problem || 'Loading...';
|
|
429
|
+
document.getElementById('domain').textContent = 'Domain: ' + (state.domain || 'code');
|
|
430
|
+
document.getElementById('rigor').textContent = 'Rigor: ' + (state.rigor || 'deep');
|
|
431
|
+
|
|
432
|
+
// Update status badge
|
|
433
|
+
const statusEl = document.getElementById('status');
|
|
434
|
+
statusEl.className = 'status-badge status-' + (state.status === 'complete' ? 'complete' : state.status === 'error' ? 'error' : 'running');
|
|
435
|
+
statusEl.textContent = state.status === 'complete' ? 'Complete' : state.status === 'error' ? 'Error' : 'Running';
|
|
436
|
+
|
|
437
|
+
// Update pipeline stages
|
|
438
|
+
const pipelineEl = document.getElementById('pipeline');
|
|
439
|
+
if (state.stages && state.stages.length > 0) {
|
|
440
|
+
pipelineEl.innerHTML = state.stages.map(stage => {
|
|
441
|
+
const icon = STAGE_ICONS[stage.name] || 'āļø';
|
|
442
|
+
const statusClass = stage.status || 'pending';
|
|
443
|
+
const time = stage.duration_ms ? (stage.duration_ms / 1000).toFixed(1) + 's' : '';
|
|
444
|
+
return \`
|
|
445
|
+
<div class="stage \${statusClass}">
|
|
446
|
+
<div class="stage-icon">\${icon}</div>
|
|
447
|
+
<div class="stage-name">\${stage.name.replace('_', ' ')}</div>
|
|
448
|
+
<div class="stage-status">\${statusClass === 'running' ? '<span class="loader"></span>' : statusClass}</div>
|
|
449
|
+
\${time ? '<div class="stage-time">' + time + '</div>' : ''}
|
|
450
|
+
</div>
|
|
451
|
+
\`;
|
|
452
|
+
}).join('');
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Update duration
|
|
456
|
+
const duration = state.duration_ms || (Date.now() - startTime);
|
|
457
|
+
document.getElementById('duration').textContent = (duration / 1000).toFixed(1) + 's';
|
|
458
|
+
|
|
459
|
+
// Update stages count
|
|
460
|
+
const complete = state.stages ? state.stages.filter(s => s.status === 'complete').length : 0;
|
|
461
|
+
const total = state.stages ? state.stages.length : 0;
|
|
462
|
+
document.getElementById('stages-complete').textContent = complete + '/' + total;
|
|
463
|
+
|
|
464
|
+
// Show results when complete
|
|
465
|
+
if (state.status === 'complete' && state.result) {
|
|
466
|
+
document.getElementById('results').classList.add('visible');
|
|
467
|
+
|
|
468
|
+
// Angles
|
|
469
|
+
if (state.angles && state.angles.length > 0) {
|
|
470
|
+
document.getElementById('angles-section').style.display = 'block';
|
|
471
|
+
document.getElementById('angles').innerHTML = state.angles.slice(0, 6).map((angle, i) => \`
|
|
472
|
+
<div class="angle-card">\${i + 1}. \${angle.slice(0, 200)}...</div>
|
|
473
|
+
\`).join('');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Solution
|
|
477
|
+
if (state.result.invention && state.result.invention.solution) {
|
|
478
|
+
document.getElementById('solution').innerHTML = formatMarkdown(state.result.invention.solution);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Verification
|
|
482
|
+
document.getElementById('verified').textContent = state.result.verified ? 'ā' : 'ā';
|
|
483
|
+
|
|
484
|
+
// Confidence
|
|
485
|
+
if (state.result.invention && state.result.invention.confidence) {
|
|
486
|
+
document.getElementById('confidence').textContent = (state.result.invention.confidence * 100).toFixed(0) + '%';
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Proofs
|
|
490
|
+
if (state.proofs && state.proofs.length > 0) {
|
|
491
|
+
document.getElementById('proofs-section').style.display = 'block';
|
|
492
|
+
document.getElementById('proofs').innerHTML = state.proofs.map(p => \`<div class="angle-card">\${p.type}: \${p.summary || 'Verified'}</div>\`).join('');
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function formatMarkdown(text) {
|
|
498
|
+
return text
|
|
499
|
+
.replace(/### \*\*(.*?)\*\*/g, '<h3>$1</h3>')
|
|
500
|
+
.replace(/## \*\*(.*?)\*\*/g, '<h2>$1</h2>')
|
|
501
|
+
.replace(/# \*\*(.*?)\*\*/g, '<h1>$1</h1>')
|
|
502
|
+
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
|
503
|
+
.replace(/\`\`\`(\w+)?\n([\s\S]*?)\`\`\`/g, '<pre><code>$2</code></pre>')
|
|
504
|
+
.replace(/\`([^\`]+)\`/g, '<code>$1</code>')
|
|
505
|
+
.replace(/\n/g, '<br>');
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Keep updating duration while running
|
|
509
|
+
setInterval(() => {
|
|
510
|
+
if (!document.querySelector('.status-complete')) {
|
|
511
|
+
const el = document.getElementById('duration');
|
|
512
|
+
const current = parseFloat(el.textContent);
|
|
513
|
+
el.textContent = (current + 0.1).toFixed(1) + 's';
|
|
514
|
+
}
|
|
515
|
+
}, 100);
|
|
516
|
+
</script>
|
|
517
|
+
</body>
|
|
518
|
+
</html>`;
|
|
519
|
+
|
|
520
|
+
function createServer(port = 50888) {
|
|
521
|
+
const server = http.createServer((req, res) => {
|
|
522
|
+
if (req.url === '/events') {
|
|
523
|
+
res.writeHead(200, {
|
|
524
|
+
'Content-Type': 'text/event-stream',
|
|
525
|
+
'Cache-Control': 'no-cache',
|
|
526
|
+
'Connection': 'keep-alive',
|
|
527
|
+
'Access-Control-Allow-Origin': '*'
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
clients.push(res);
|
|
531
|
+
|
|
532
|
+
// Send initial state
|
|
533
|
+
res.write(`data: ${JSON.stringify(inventionState)}\n\n`);
|
|
534
|
+
|
|
535
|
+
req.on('close', () => {
|
|
536
|
+
clients = clients.filter(c => c !== res);
|
|
537
|
+
});
|
|
538
|
+
} else {
|
|
539
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
540
|
+
res.end(HTML_PAGE);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
server.listen(port, () => {
|
|
545
|
+
console.log(`š„ļø 50c Invent UI running at http://localhost:${port}`);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
return server;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function broadcast(state) {
|
|
552
|
+
inventionState = { ...inventionState, ...state };
|
|
553
|
+
const data = `data: ${JSON.stringify(inventionState)}\n\n`;
|
|
554
|
+
clients.forEach(client => client.write(data));
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function openBrowser(url) {
|
|
558
|
+
const platform = process.platform;
|
|
559
|
+
let cmd;
|
|
560
|
+
|
|
561
|
+
if (platform === 'win32') {
|
|
562
|
+
cmd = spawn('cmd', ['/c', 'start', url], { detached: true, stdio: 'ignore' });
|
|
563
|
+
} else if (platform === 'darwin') {
|
|
564
|
+
cmd = spawn('open', [url], { detached: true, stdio: 'ignore' });
|
|
565
|
+
} else {
|
|
566
|
+
cmd = spawn('xdg-open', [url], { detached: true, stdio: 'ignore' });
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
cmd.unref();
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
async function runInventWithUI(problem, options = {}) {
|
|
573
|
+
const { domain = 'code', rigor = 'deep', constraints = [] } = options;
|
|
574
|
+
const port = 50888 + Math.floor(Math.random() * 100);
|
|
575
|
+
|
|
576
|
+
// Start server
|
|
577
|
+
const server = createServer(port);
|
|
578
|
+
|
|
579
|
+
// Initialize state
|
|
580
|
+
broadcast({
|
|
581
|
+
problem,
|
|
582
|
+
domain,
|
|
583
|
+
rigor,
|
|
584
|
+
status: 'running',
|
|
585
|
+
startTime: Date.now(),
|
|
586
|
+
stages: getStagesForRigor(rigor)
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// Open browser
|
|
590
|
+
setTimeout(() => openBrowser(`http://localhost:${port}`), 500);
|
|
591
|
+
|
|
592
|
+
// Run the invention
|
|
593
|
+
try {
|
|
594
|
+
const { autoInvent } = require('../bin/50c.js');
|
|
595
|
+
|
|
596
|
+
// Hook into the stages to broadcast progress
|
|
597
|
+
const originalConsoleLog = console.log;
|
|
598
|
+
console.log = (...args) => {
|
|
599
|
+
const msg = args.join(' ');
|
|
600
|
+
|
|
601
|
+
// Detect stage changes
|
|
602
|
+
if (msg.includes('mind_opener')) updateStage('mind_opener', 'running');
|
|
603
|
+
if (msg.includes('idea_fold')) updateStage('idea_fold', 'running');
|
|
604
|
+
if (msg.includes('bcalc')) updateStage('bcalc', 'running');
|
|
605
|
+
if (msg.includes('web_search')) updateStage('web_search', 'running');
|
|
606
|
+
if (msg.includes('genius_plus')) updateStage('genius_plus', 'running');
|
|
607
|
+
if (msg.includes('cvi_verify')) updateStage('cvi_verify', 'running');
|
|
608
|
+
if (msg.includes('roast')) updateStage('roast', 'running');
|
|
609
|
+
if (msg.includes('compute')) updateStage('compute', 'running');
|
|
610
|
+
|
|
611
|
+
originalConsoleLog.apply(console, args);
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
const result = await autoInvent({ problem, domain, rigor, constraints });
|
|
615
|
+
|
|
616
|
+
console.log = originalConsoleLog;
|
|
617
|
+
|
|
618
|
+
// Mark all stages complete
|
|
619
|
+
inventionState.stages.forEach(s => s.status = 'complete');
|
|
620
|
+
|
|
621
|
+
// Broadcast final result
|
|
622
|
+
broadcast({
|
|
623
|
+
status: 'complete',
|
|
624
|
+
result,
|
|
625
|
+
angles: result.angles || [],
|
|
626
|
+
proofs: result.proofs || [],
|
|
627
|
+
duration_ms: Date.now() - inventionState.startTime
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// Keep server alive for viewing
|
|
631
|
+
console.log(`\n⨠Invention complete! View at http://localhost:${port}`);
|
|
632
|
+
console.log('Press Ctrl+C to close.\n');
|
|
633
|
+
|
|
634
|
+
} catch (err) {
|
|
635
|
+
broadcast({
|
|
636
|
+
status: 'error',
|
|
637
|
+
error: err.message
|
|
638
|
+
});
|
|
639
|
+
console.error('Invention failed:', err.message);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function getStagesForRigor(rigor) {
|
|
644
|
+
const stages = [
|
|
645
|
+
{ name: 'mind_opener', status: 'pending' },
|
|
646
|
+
{ name: 'idea_fold', status: 'pending' },
|
|
647
|
+
{ name: 'bcalc', status: 'pending' },
|
|
648
|
+
];
|
|
649
|
+
|
|
650
|
+
if (rigor === 'standard' || rigor === 'deep' || rigor === 'exhaustive') {
|
|
651
|
+
stages.push({ name: 'web_search', status: 'pending' });
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
stages.push({ name: 'genius_plus', status: 'pending' });
|
|
655
|
+
|
|
656
|
+
if (rigor === 'deep' || rigor === 'exhaustive') {
|
|
657
|
+
stages.push({ name: 'cvi_verify', status: 'pending' });
|
|
658
|
+
stages.push({ name: 'roast', status: 'pending' });
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (rigor === 'exhaustive') {
|
|
662
|
+
stages.push({ name: 'compute', status: 'pending' });
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return stages;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
function updateStage(name, status) {
|
|
669
|
+
const stage = inventionState.stages.find(s => s.name === name);
|
|
670
|
+
if (stage) {
|
|
671
|
+
// Complete previous running stages
|
|
672
|
+
inventionState.stages.forEach(s => {
|
|
673
|
+
if (s.status === 'running' && s.name !== name) {
|
|
674
|
+
s.status = 'complete';
|
|
675
|
+
s.duration_ms = (Date.now() - inventionState.startTime) / inventionState.stages.length;
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
stage.status = status;
|
|
680
|
+
broadcast({});
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
module.exports = { runInventWithUI, createServer, broadcast };
|
|
685
|
+
|
|
686
|
+
// CLI entry point
|
|
687
|
+
if (require.main === module) {
|
|
688
|
+
const args = process.argv.slice(2);
|
|
689
|
+
|
|
690
|
+
if (args.length === 0) {
|
|
691
|
+
console.log(`
|
|
692
|
+
š¬ 50c Invent UI - MCP TV for Inventions
|
|
693
|
+
|
|
694
|
+
Usage: node invent-ui.js "problem" [options]
|
|
695
|
+
|
|
696
|
+
Options:
|
|
697
|
+
--rigor=fast|standard|deep|exhaustive (default: deep)
|
|
698
|
+
--domain=math|physics|code|business (default: code)
|
|
699
|
+
|
|
700
|
+
Example:
|
|
701
|
+
node invent-ui.js "faster sorting algorithm" --rigor=deep --domain=code
|
|
702
|
+
`);
|
|
703
|
+
process.exit(0);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
let problem = '';
|
|
707
|
+
let rigor = 'deep';
|
|
708
|
+
let domain = 'code';
|
|
709
|
+
|
|
710
|
+
for (const arg of args) {
|
|
711
|
+
if (arg.startsWith('--rigor=')) rigor = arg.split('=')[1];
|
|
712
|
+
else if (arg.startsWith('--domain=')) domain = arg.split('=')[1];
|
|
713
|
+
else if (!arg.startsWith('--')) problem += (problem ? ' ' : '') + arg;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
runInventWithUI(problem, { domain, rigor });
|
|
717
|
+
}
|