omnibiofex 4.1.0 → 4.2.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/package.json +1 -1
- package/src/commands/diagram.js +91 -126
package/package.json
CHANGED
package/src/commands/diagram.js
CHANGED
|
@@ -13,54 +13,34 @@ if (!fs.existsSync(DIAGRAMS_DIR)) {
|
|
|
13
13
|
fs.mkdirSync(DIAGRAMS_DIR, { recursive: true });
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
// Diagram styles
|
|
16
|
+
// Diagram styles with costs
|
|
17
17
|
const STYLES = {
|
|
18
|
-
minimal: {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
detailed: {
|
|
24
|
-
name: 'Detailed',
|
|
25
|
-
cost: 80,
|
|
26
|
-
description: 'Comprehensive ecosystem with all components'
|
|
27
|
-
},
|
|
28
|
-
flowchart: {
|
|
29
|
-
name: 'Flowchart',
|
|
30
|
-
cost: 60,
|
|
31
|
-
description: 'Step-by-step process flow'
|
|
32
|
-
},
|
|
33
|
-
network: {
|
|
34
|
-
name: 'Network',
|
|
35
|
-
cost: 70,
|
|
36
|
-
description: 'Interconnected nodes and relationships'
|
|
37
|
-
}
|
|
18
|
+
minimal: { name: 'Minimal', cost: 50, description: 'Clean, simple flowchart' },
|
|
19
|
+
detailed: { name: 'Detailed', cost: 80, description: 'Comprehensive ecosystem' },
|
|
20
|
+
flowchart: { name: 'Flowchart', cost: 60, description: 'Step-by-step process' },
|
|
21
|
+
network: { name: 'Network', cost: 70, description: 'Interconnected nodes' }
|
|
38
22
|
};
|
|
39
23
|
|
|
40
|
-
// Generate ASCII box
|
|
41
|
-
function box(text, width = 60) {
|
|
42
|
-
const padding = Math.max(0, width - text.length - 2);
|
|
43
|
-
const leftPad = Math.floor(padding / 2);
|
|
44
|
-
const rightPad = padding - leftPad;
|
|
45
|
-
return `║ ${' '.repeat(leftPad)}${text}${' '.repeat(rightPad)} ║`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
24
|
// Generate ASCII banner
|
|
49
25
|
function banner(title, width = 80) {
|
|
50
26
|
const top = `╔${'═'.repeat(width)}╗`;
|
|
51
27
|
const bottom = `╚${'═'.repeat(width)}╝`;
|
|
52
|
-
const
|
|
28
|
+
const padding = Math.max(0, width - title.length - 2);
|
|
29
|
+
const leftPad = Math.floor(padding / 2);
|
|
30
|
+
const rightPad = padding - leftPad;
|
|
31
|
+
const content = `║ ${' '.repeat(leftPad)}${title}${' '.repeat(rightPad)} ║`;
|
|
53
32
|
return `${top}\n${content}\n${bottom}`;
|
|
54
33
|
}
|
|
55
34
|
|
|
56
35
|
// Generate node box
|
|
57
36
|
function node(text, width = 20) {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const padding = Math.max(0, width - text.length - 2);
|
|
37
|
+
const safeText = text.substring(0, width - 2);
|
|
38
|
+
const padding = Math.max(0, width - safeText.length - 2);
|
|
61
39
|
const leftPad = Math.floor(padding / 2);
|
|
62
40
|
const rightPad = padding - leftPad;
|
|
63
|
-
const
|
|
41
|
+
const top = `┌${'─'.repeat(width)}┐`;
|
|
42
|
+
const bottom = `└${'─'.repeat(width)}┘`;
|
|
43
|
+
const content = `│ ${' '.repeat(leftPad)}${safeText}${' '.repeat(rightPad)} │`;
|
|
64
44
|
return `${top}\n${content}\n${bottom}`;
|
|
65
45
|
}
|
|
66
46
|
|
|
@@ -75,27 +55,8 @@ function arrow(direction = 'down') {
|
|
|
75
55
|
}
|
|
76
56
|
}
|
|
77
57
|
|
|
78
|
-
// Generate minimal diagram
|
|
79
|
-
function generateMinimalDiagram(topic, components) {
|
|
80
|
-
const width = 60;
|
|
81
|
-
let diagram = banner(topic.toUpperCase(), width) + '\n\n';
|
|
82
|
-
|
|
83
|
-
// Problem box
|
|
84
|
-
diagram += `${' '.repeat(20)}${node('Problem', 20)}\n`;
|
|
85
|
-
diagram += `${' '.repeat(29)}${arrow('down')}\n`;
|
|
86
|
-
|
|
87
|
-
// Three branches
|
|
88
|
-
diagram += `${' '.repeat(10)}${node('Research', 20)}\n`;
|
|
89
|
-
diagram += `${' '.repeat(19)}${arrow('down')}\n`;
|
|
90
|
-
diagram += `${' '.repeat(10)}${node('Analysis', 20)}\n`;
|
|
91
|
-
diagram += `${' '.repeat(19)}${arrow('down')}\n`;
|
|
92
|
-
diagram += `${' '.repeat(10)}${node('Solution', 20)}\n`;
|
|
93
|
-
|
|
94
|
-
return diagram;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
58
|
// Generate detailed diagram
|
|
98
|
-
function generateDetailedDiagram(topic,
|
|
59
|
+
function generateDetailedDiagram(topic, data) {
|
|
99
60
|
const width = 80;
|
|
100
61
|
let diagram = banner(`${topic.toUpperCase()} RESEARCH ECOSYSTEM`, width) + '\n\n';
|
|
101
62
|
|
|
@@ -104,7 +65,8 @@ function generateDetailedDiagram(topic, components) {
|
|
|
104
65
|
diagram += `${' '.repeat(37)}${arrow('down')}\n\n`;
|
|
105
66
|
|
|
106
67
|
// Three input sources
|
|
107
|
-
|
|
68
|
+
const sources = data.components?.slice(0, 3) || ['Literature', 'Data', 'Theory'];
|
|
69
|
+
diagram += `${' '.repeat(5)}${node(sources[0] || 'Literature', 18)} ${node(sources[1] || 'Data', 18)} ${node(sources[2] || 'Theory', 18)}\n`;
|
|
108
70
|
diagram += `${' '.repeat(14)}\\ | /\n`;
|
|
109
71
|
diagram += `${' '.repeat(15)}\\ | /\n`;
|
|
110
72
|
diagram += `${' '.repeat(16)}\\ | /\n`;
|
|
@@ -117,7 +79,8 @@ function generateDetailedDiagram(topic, components) {
|
|
|
117
79
|
diagram += `${' '.repeat(32)}${arrow('down')}\n\n`;
|
|
118
80
|
|
|
119
81
|
// Four analysis types
|
|
120
|
-
|
|
82
|
+
const methods = data.methods?.slice(0, 4) || ['Statistical', 'Qualitative', 'Comparative', 'Predictive'];
|
|
83
|
+
diagram += `${node(methods[0], 14)} ${node(methods[1], 14)} ${node(methods[2], 14)} ${node(methods[3], 14)}\n`;
|
|
121
84
|
diagram += `${' '.repeat(7)}\\ | | /\n`;
|
|
122
85
|
diagram += `${' '.repeat(8)}\\ | | /\n`;
|
|
123
86
|
diagram += `${' '.repeat(9)}\\ | | /\n`;
|
|
@@ -130,45 +93,58 @@ function generateDetailedDiagram(topic, components) {
|
|
|
130
93
|
diagram += `${' '.repeat(32)}${arrow('down')}\n\n`;
|
|
131
94
|
|
|
132
95
|
// Three outputs
|
|
133
|
-
|
|
96
|
+
const outputs = data.outputs?.slice(0, 3) || ['Publication', 'Implementation', 'Future Work'];
|
|
97
|
+
diagram += `${node(outputs[0], 18)} ${node(outputs[1], 18)} ${node(outputs[2], 18)}\n`;
|
|
98
|
+
|
|
99
|
+
return diagram;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Generate minimal diagram
|
|
103
|
+
function generateMinimalDiagram(topic, data) {
|
|
104
|
+
const width = 60;
|
|
105
|
+
let diagram = banner(topic.toUpperCase(), width) + '\n\n';
|
|
106
|
+
|
|
107
|
+
diagram += `${' '.repeat(20)}${node('Problem', 20)}\n`;
|
|
108
|
+
diagram += `${' '.repeat(29)}${arrow('down')}\n`;
|
|
109
|
+
diagram += `${' '.repeat(10)}${node('Research', 20)}\n`;
|
|
110
|
+
diagram += `${' '.repeat(19)}${arrow('down')}\n`;
|
|
111
|
+
diagram += `${' '.repeat(10)}${node('Analysis', 20)}\n`;
|
|
112
|
+
diagram += `${' '.repeat(19)}${arrow('down')}\n`;
|
|
113
|
+
diagram += `${' '.repeat(10)}${node('Solution', 20)}\n`;
|
|
134
114
|
|
|
135
115
|
return diagram;
|
|
136
116
|
}
|
|
137
117
|
|
|
138
118
|
// Generate flowchart diagram
|
|
139
|
-
function generateFlowchartDiagram(topic,
|
|
119
|
+
function generateFlowchartDiagram(topic, data) {
|
|
140
120
|
const width = 60;
|
|
121
|
+
const steps = data.steps?.length > 0 ? data.steps : ['Research', 'Analysis', 'Implementation'];
|
|
141
122
|
let diagram = banner(`${topic.toUpperCase()} WORKFLOW`, width) + '\n\n';
|
|
142
123
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const stepText = `Step ${currentStep}: ${step}`;
|
|
124
|
+
steps.forEach((step, i) => {
|
|
125
|
+
const stepText = `Step ${i + 1}: ${step}`;
|
|
146
126
|
diagram += `${' '.repeat(15)}${node(stepText, 45)}\n`;
|
|
147
|
-
if (
|
|
127
|
+
if (i < steps.length - 1) {
|
|
148
128
|
diagram += `${' '.repeat(37)}${arrow('down')}\n`;
|
|
149
129
|
}
|
|
150
|
-
|
|
151
|
-
}
|
|
130
|
+
});
|
|
152
131
|
|
|
153
132
|
diagram += `\n${' '.repeat(25)}${node('✓ Complete', 20)}\n`;
|
|
154
|
-
|
|
155
133
|
return diagram;
|
|
156
134
|
}
|
|
157
135
|
|
|
158
136
|
// Generate network diagram
|
|
159
|
-
function generateNetworkDiagram(topic,
|
|
137
|
+
function generateNetworkDiagram(topic, data) {
|
|
160
138
|
const width = 70;
|
|
139
|
+
const nodes = data.nodes?.slice(0, 3) || ['Component A', 'Component B', 'Component C'];
|
|
161
140
|
let diagram = banner(`${topic.toUpperCase()} NETWORK`, width) + '\n\n';
|
|
162
141
|
|
|
163
|
-
// Central node
|
|
164
142
|
diagram += `${' '.repeat(25)}${node(topic, 25)}\n`;
|
|
165
143
|
diagram += `${' '.repeat(37)}|\n`;
|
|
166
144
|
diagram += `${' '.repeat(20)}┌────────┼────────┐\n`;
|
|
167
145
|
diagram += `${' '.repeat(20)}│ │ │\n`;
|
|
168
146
|
diagram += `${' '.repeat(20)}▼ ▼ ▼\n`;
|
|
169
|
-
|
|
170
|
-
// Three connected nodes
|
|
171
|
-
diagram += `${node(nodes[0] || 'Node A', 18)} ${node(nodes[1] || 'Node B', 18)} ${node(nodes[2] || 'Node C', 18)}\n`;
|
|
147
|
+
diagram += `${node(nodes[0], 18)} ${node(nodes[1], 18)} ${node(nodes[2], 18)}\n`;
|
|
172
148
|
diagram += `${' '.repeat(9)}│ │ │\n`;
|
|
173
149
|
diagram += `${' '.repeat(9)}└────────┼────────┘\n`;
|
|
174
150
|
diagram += `${' '.repeat(18)}▼\n`;
|
|
@@ -177,24 +153,6 @@ function generateNetworkDiagram(topic, nodes) {
|
|
|
177
153
|
return diagram;
|
|
178
154
|
}
|
|
179
155
|
|
|
180
|
-
// Generate Mermaid diagram for markdown
|
|
181
|
-
function generateMermaidDiagram(topic, components, style) {
|
|
182
|
-
let mermaid = '```mermaid\n';
|
|
183
|
-
mermaid += 'graph TD\n';
|
|
184
|
-
mermaid += ` A[${topic}] --> B[Research Phase]\n`;
|
|
185
|
-
mermaid += ` B --> C[Analysis Phase]\n`;
|
|
186
|
-
mermaid += ` C --> D[Output Phase]\n`;
|
|
187
|
-
|
|
188
|
-
if (components && components.length > 0) {
|
|
189
|
-
components.forEach((comp, i) => {
|
|
190
|
-
mermaid += ` B --> E${i}[${comp}]\n`;
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
mermaid += '```';
|
|
195
|
-
return mermaid;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
156
|
// Main diagram command
|
|
199
157
|
async function diagram(topic, options = {}) {
|
|
200
158
|
if (!isAuthenticated()) {
|
|
@@ -205,14 +163,13 @@ async function diagram(topic, options = {}) {
|
|
|
205
163
|
|
|
206
164
|
if (!topic) {
|
|
207
165
|
console.error(chalk.red('✗ Please provide a topic'));
|
|
208
|
-
console.log(chalk.gray('Usage: obx diagram "topic" [--style minimal|detailed|flowchart|network] [--save]
|
|
166
|
+
console.log(chalk.gray('Usage: obx diagram "topic" [--style minimal|detailed|flowchart|network] [--save]'));
|
|
209
167
|
process.exit(1);
|
|
210
168
|
return;
|
|
211
169
|
}
|
|
212
170
|
|
|
213
171
|
const style = options.style || 'detailed';
|
|
214
172
|
const save = options.save || false;
|
|
215
|
-
const publish = options.publish || false;
|
|
216
173
|
const cost = STYLES[style]?.cost || 80;
|
|
217
174
|
|
|
218
175
|
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
|
|
@@ -229,10 +186,10 @@ async function diagram(topic, options = {}) {
|
|
|
229
186
|
try {
|
|
230
187
|
const token = await getAuthToken();
|
|
231
188
|
|
|
232
|
-
// Call AI backend to get components/structure
|
|
233
189
|
spinner.update('Analyzing topic with AI');
|
|
234
190
|
await sleep(500);
|
|
235
191
|
|
|
192
|
+
// ✅ FIX: Use DEEP_RESEARCH task type (already supported by backend)
|
|
236
193
|
const response = await fetch(BACKEND_URL, {
|
|
237
194
|
method: 'POST',
|
|
238
195
|
headers: {
|
|
@@ -240,22 +197,27 @@ async function diagram(topic, options = {}) {
|
|
|
240
197
|
'Authorization': `Bearer ${token}`
|
|
241
198
|
},
|
|
242
199
|
body: JSON.stringify({
|
|
243
|
-
taskType: '
|
|
244
|
-
message: `Generate a structured breakdown of "${topic}" for an ASCII diagram.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
200
|
+
taskType: 'DEEP_RESEARCH', // ← Use existing task type
|
|
201
|
+
message: `Generate a structured breakdown of "${topic}" for an ASCII diagram.
|
|
202
|
+
|
|
203
|
+
Return ONLY a valid JSON object with this exact structure (no other text):
|
|
204
|
+
{
|
|
205
|
+
"components": ["component1", "component2", "component3", "component4"],
|
|
206
|
+
"methods": ["method1", "method2", "method3", "method4"],
|
|
207
|
+
"steps": ["step1", "step2", "step3", "step4", "step5"],
|
|
208
|
+
"nodes": ["node1", "node2", "node3"],
|
|
209
|
+
"outputs": ["output1", "output2", "output3"]
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
Make the components, methods, steps, nodes, and outputs specific to "${topic}".
|
|
213
|
+
Return ONLY the JSON object, nothing else.`,
|
|
253
214
|
model: 'deep'
|
|
254
215
|
})
|
|
255
216
|
});
|
|
256
217
|
|
|
257
218
|
if (!response.ok) {
|
|
258
|
-
|
|
219
|
+
const errorText = await response.text();
|
|
220
|
+
throw new Error(`Backend returned ${response.status}: ${errorText.substring(0, 100)}`);
|
|
259
221
|
}
|
|
260
222
|
|
|
261
223
|
spinner.update('Rendering ASCII art');
|
|
@@ -263,11 +225,20 @@ async function diagram(topic, options = {}) {
|
|
|
263
225
|
|
|
264
226
|
const data = await response.json();
|
|
265
227
|
|
|
266
|
-
// Parse AI response
|
|
267
|
-
let aiData = {
|
|
228
|
+
// Parse AI response - extract JSON from the response
|
|
229
|
+
let aiData = {
|
|
230
|
+
components: [],
|
|
231
|
+
methods: [],
|
|
232
|
+
steps: [],
|
|
233
|
+
nodes: [],
|
|
234
|
+
outputs: []
|
|
235
|
+
};
|
|
236
|
+
|
|
268
237
|
try {
|
|
269
|
-
// Try to
|
|
270
|
-
const
|
|
238
|
+
// Try to find JSON in the response
|
|
239
|
+
const responseText = data.response || '';
|
|
240
|
+
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
|
|
241
|
+
|
|
271
242
|
if (jsonMatch) {
|
|
272
243
|
aiData = JSON.parse(jsonMatch[0]);
|
|
273
244
|
}
|
|
@@ -279,30 +250,27 @@ async function diagram(topic, options = {}) {
|
|
|
279
250
|
let asciiDiagram;
|
|
280
251
|
switch (style) {
|
|
281
252
|
case 'minimal':
|
|
282
|
-
asciiDiagram = generateMinimalDiagram(topic, aiData
|
|
253
|
+
asciiDiagram = generateMinimalDiagram(topic, aiData);
|
|
283
254
|
break;
|
|
284
255
|
case 'flowchart':
|
|
285
|
-
asciiDiagram = generateFlowchartDiagram(topic, aiData
|
|
256
|
+
asciiDiagram = generateFlowchartDiagram(topic, aiData);
|
|
286
257
|
break;
|
|
287
258
|
case 'network':
|
|
288
|
-
asciiDiagram = generateNetworkDiagram(topic, aiData
|
|
259
|
+
asciiDiagram = generateNetworkDiagram(topic, aiData);
|
|
289
260
|
break;
|
|
290
261
|
case 'detailed':
|
|
291
262
|
default:
|
|
292
|
-
asciiDiagram = generateDetailedDiagram(topic, aiData
|
|
263
|
+
asciiDiagram = generateDetailedDiagram(topic, aiData);
|
|
293
264
|
break;
|
|
294
265
|
}
|
|
295
266
|
|
|
296
|
-
// Generate Mermaid version
|
|
297
|
-
const mermaidDiagram = generateMermaidDiagram(topic, aiData.components, style);
|
|
298
|
-
|
|
299
267
|
spinner.succeed('✓ Diagram generated');
|
|
300
268
|
|
|
301
269
|
// Display diagram
|
|
302
270
|
console.log('\n' + chalk.cyan(asciiDiagram) + '\n');
|
|
303
271
|
|
|
304
272
|
// Save if requested
|
|
305
|
-
if (save
|
|
273
|
+
if (save) {
|
|
306
274
|
const timestamp = Date.now();
|
|
307
275
|
const safeTopic = topic.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 50);
|
|
308
276
|
|
|
@@ -310,22 +278,14 @@ async function diagram(topic, options = {}) {
|
|
|
310
278
|
const txtFilename = `${safeTopic}-${timestamp}.txt`;
|
|
311
279
|
const txtPath = path.join(DIAGRAMS_DIR, txtFilename);
|
|
312
280
|
fs.writeFileSync(txtPath, asciiDiagram, 'utf8');
|
|
313
|
-
console.log(chalk.green(` 💾 Saved
|
|
281
|
+
console.log(chalk.green(` 💾 Saved: ${txtPath}`));
|
|
314
282
|
|
|
315
|
-
// Save Markdown version
|
|
283
|
+
// Save Markdown version
|
|
316
284
|
const mdFilename = `${safeTopic}-${timestamp}.md`;
|
|
317
285
|
const mdPath = path.join(DIAGRAMS_DIR, mdFilename);
|
|
318
|
-
const mdContent = `# ${topic} Research Diagram\n\n**Style:** ${STYLES[style].name}\n**Generated:** ${new Date().toLocaleString()}\n\n
|
|
286
|
+
const mdContent = `# ${topic} Research Diagram\n\n**Style:** ${STYLES[style].name}\n**Generated:** ${new Date().toLocaleString()}\n\n\`\`\`\n${asciiDiagram}\n\`\`\`\n`;
|
|
319
287
|
fs.writeFileSync(mdPath, mdContent, 'utf8');
|
|
320
|
-
console.log(chalk.green(` 💾 Saved
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Publish if requested
|
|
324
|
-
if (publish) {
|
|
325
|
-
console.log(chalk.yellow('\n 📤 To publish this diagram as research:'));
|
|
326
|
-
console.log(chalk.gray(' 1. Review the saved markdown file'));
|
|
327
|
-
console.log(chalk.gray(' 2. Run: obx publish'));
|
|
328
|
-
console.log(chalk.gray(' 3. Select the diagram from your missions'));
|
|
288
|
+
console.log(chalk.green(` 💾 Saved: ${mdPath}`));
|
|
329
289
|
}
|
|
330
290
|
|
|
331
291
|
console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
|
|
@@ -333,6 +293,11 @@ async function diagram(topic, options = {}) {
|
|
|
333
293
|
} catch (error) {
|
|
334
294
|
spinner.fail('Failed to generate diagram');
|
|
335
295
|
console.error(chalk.red(error.message));
|
|
296
|
+
|
|
297
|
+
if (error.message.includes('402') || error.message.includes('Insufficient')) {
|
|
298
|
+
console.log(chalk.yellow('\n 💡 You need more RCC credits. Run: obx buy'));
|
|
299
|
+
}
|
|
300
|
+
|
|
336
301
|
process.exit(1);
|
|
337
302
|
}
|
|
338
303
|
}
|