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