societyai 0.1.3 → 0.1.4

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 (2) hide show
  1. package/bin/societyai.js +114 -43
  2. package/package.json +3 -2
package/bin/societyai.js CHANGED
@@ -160,7 +160,7 @@ async function validateCommand(filePath) {
160
160
  const ext = path.extname(fullPath);
161
161
  if (ext === '.ts') {
162
162
  console.log(colorize('dim', ' Compiling TypeScript...'));
163
- execSync(`npx tsc --noEmit "${fullPath}"`, { stdio: 'pipe' });
163
+ execSync(`npx tsc --noEmit "${fullPath}"`, { stdio: 'pipe', cwd: path.dirname(fullPath) });
164
164
  }
165
165
 
166
166
  // Try to load and validate the module
@@ -242,17 +242,21 @@ async function visualizeCommand(filePath, options) {
242
242
  const module = require(fullPath);
243
243
  const society = module.default || module.society;
244
244
 
245
- if (!society || !society.engine) {
246
- console.error(colorize('red', '❌ Error: Could not find Society engine in file'));
245
+ if (!society || typeof society.build !== 'function') {
246
+ console.error(colorize('red', '❌ Error: Could not find Society builder in file'));
247
247
  process.exit(1);
248
248
  }
249
249
 
250
+ const { SocietyExecutor } = require('../dist/agents/society-executor');
251
+ const config = society.build();
252
+ const engine = new SocietyExecutor().buildExecutionGraph(config);
253
+
250
254
  let result = '';
251
255
 
252
256
  switch (format.toLowerCase()) {
253
257
  case 'mermaid':
254
258
  const { GraphVisualizer } = require('../dist/execution/graph-visualizer');
255
- result = GraphVisualizer.toMermaid(society.engine, {
259
+ result = GraphVisualizer.toMermaid(engine, {
256
260
  direction,
257
261
  theme,
258
262
  highlightPath: highlight,
@@ -262,27 +266,27 @@ async function visualizeCommand(filePath, options) {
262
266
  case 'dot':
263
267
  case 'graphviz':
264
268
  const { GraphVisualizer: GV2 } = require('../dist/execution/graph-visualizer');
265
- result = GV2.toDOT(society.engine, { rankdir: direction });
269
+ result = GV2.toDOT(engine, { rankdir: direction });
266
270
  break;
267
271
 
268
272
  case 'json':
269
273
  const { GraphVisualizer: GV3 } = require('../dist/execution/graph-visualizer');
270
- result = JSON.stringify(GV3.toJSON(society.engine), null, 2);
274
+ result = JSON.stringify(GV3.toJSON(engine), null, 2);
271
275
  break;
272
276
 
273
277
  case 'html':
274
278
  const { GraphVisualizer: GV4 } = require('../dist/execution/graph-visualizer');
275
- result = GV4.toHTML(society.engine, { direction, theme, highlightPath: highlight });
279
+ result = GV4.toHTML(engine, { direction, theme, highlightPath: highlight });
276
280
  break;
277
281
 
278
282
  case 'ascii':
279
283
  const { GraphVisualizer: GV5 } = require('../dist/execution/graph-visualizer');
280
- result = GV5.toASCII(society.engine);
284
+ result = GV5.toASCII(engine);
281
285
  break;
282
286
 
283
287
  case 'plantuml':
284
288
  const { GraphVisualizer: GV6 } = require('../dist/execution/graph-visualizer');
285
- result = GV6.toPlantUML(society.engine, direction);
289
+ result = GV6.toPlantUML(engine, direction);
286
290
  break;
287
291
 
288
292
  default:
@@ -347,23 +351,29 @@ async function runCommand(filePath, options) {
347
351
  }
348
352
 
349
353
  // Setup observer for verbose mode
350
- const observer = verbose ? {
351
- onNodeStart: (nodeId, type, input) => {
352
- console.log(colorize('dim', ` ▶️ Node ${nodeId} (${type}) starting...`));
353
- },
354
- onNodeEnd: (nodeId, output, duration) => {
355
- console.log(colorize('dim', ` ✅ Node ${nodeId} completed in ${duration}ms`));
356
- },
357
- onAgentStart: (agentId, modelName, input) => {
358
- console.log(colorize('blue', ` 🤖 Agent ${agentId} (${modelName}) processing...`));
359
- },
360
- onAgentComplete: (agentId, modelName, output) => {
361
- console.log(colorize('green', ` ✅ Agent ${agentId} completed`));
362
- },
363
- onAgentError: (agentId, modelName, error) => {
364
- console.log(colorize('red', ` ❌ Agent ${agentId} error: ${error.message}`));
365
- },
366
- } : undefined;
354
+ if (verbose) {
355
+ society.withObserver({
356
+ onNodeStart: (nodeId, type, input) => {
357
+ console.log(colorize('dim', ` ▶️ Node ${nodeId} (${type}) starting...`));
358
+ },
359
+ onNodeEnd: (nodeId, output, duration) => {
360
+ console.log(colorize('dim', ` ✅ Node ${nodeId} completed in ${duration}ms`));
361
+ },
362
+ onAgentStart: (agentId, modelName, input) => {
363
+ console.log(colorize('blue', ` 🤖 Agent ${agentId} (${modelName}) processing...`));
364
+ },
365
+ onAgentComplete: (agentId, modelName, output) => {
366
+ console.log(colorize('green', ` ✅ Agent ${agentId} completed`));
367
+ },
368
+ onAgentError: (agentId, modelName, error) => {
369
+ console.log(colorize('red', ` ❌ Agent ${agentId} error: ${error.message}`));
370
+ },
371
+ onPhaseStart: () => {},
372
+ onPhaseComplete: () => {},
373
+ onSocietyStart: () => {},
374
+ onSocietyComplete: () => {},
375
+ });
376
+ }
367
377
 
368
378
  // Execute with timeout
369
379
  const timeoutPromise = new Promise((_, reject) => {
@@ -371,7 +381,7 @@ async function runCommand(filePath, options) {
371
381
  });
372
382
 
373
383
  const result = await Promise.race([
374
- society.execute({ input, observer }),
384
+ society.execute(input),
375
385
  timeoutPromise,
376
386
  ]);
377
387
 
@@ -430,10 +440,9 @@ async function initCommand(template, options) {
430
440
 
431
441
  const templates = {
432
442
  basic: {
433
- 'society.ts': `import { Society } from 'societyai';
434
- import { MockModel } from 'societyai/adapters';
443
+ 'society.ts': `import { Society, StandardModelBase } from 'societyai';
435
444
 
436
- const model = new MockModel();
445
+ const model = new StandardModelBase({}, async () => 'Hello from mock model!').withName('mock');
437
446
 
438
447
  export const society = Society.create()
439
448
  .withName('${projectName}')
@@ -450,11 +459,9 @@ export const society = Society.create()
450
459
  );
451
460
 
452
461
  // Execute
453
- if (require.main === module) {
454
- society.execute({ input: 'Hello World' })
455
- .then(result => console.log(result.output))
456
- .catch(console.error);
457
- }
462
+ society.execute('Hello World')
463
+ .then(result => console.log(result.output))
464
+ .catch(console.error);
458
465
  `,
459
466
  'package.json': JSON.stringify({
460
467
  name: projectName,
@@ -618,6 +625,68 @@ npm start
618
625
  }
619
626
 
620
627
  // Diff command
628
+ async function inspectCommand(filePath) {
629
+ if (!filePath) {
630
+ console.error(colorize('red', '❌ Error: No file specified'));
631
+ console.error(colorize('dim', 'Usage: societyai inspect <path-to-state.json>'));
632
+ process.exit(1);
633
+ }
634
+
635
+ const fullPath = path.resolve(filePath);
636
+ if (!fs.existsSync(fullPath)) {
637
+ console.error(colorize('red', `❌ File not found: ${fullPath}`));
638
+ process.exit(1);
639
+ }
640
+
641
+ try {
642
+ const content = fs.readFileSync(fullPath, 'utf-8');
643
+ const state = JSON.parse(content);
644
+
645
+ console.log('\n🔍 SocietyAI Execution State Inspector\n');
646
+ console.log(`🆔 Execution ID: ${colorize('cyan', state.executionId || 'N/A')}`);
647
+ console.log(`📅 Timestamp: ${state.timestamp ? new Date(state.timestamp).toLocaleString() : 'N/A'}`);
648
+ console.log(`🚦 Status: ${formatInspectStatus(state.status)}`);
649
+
650
+ if (state.executionPath && state.executionPath.length > 0) {
651
+ console.log(`🛣️ Path Length: ${state.executionPath.length} steps`);
652
+ console.log(` Start: ${state.executionPath[0] || 'N/A'}`);
653
+ console.log(` Current: ${state.executionPath[state.executionPath.length - 1] || 'N/A'}`);
654
+ }
655
+
656
+ console.log('\n📋 Queue (Next Nodes):');
657
+ if (!state.queue || state.queue.length === 0) {
658
+ console.log(' (Empty)');
659
+ } else {
660
+ state.queue.forEach((nodeId, idx) => {
661
+ console.log(` ${idx + 1}. ${nodeId}`);
662
+ });
663
+ }
664
+
665
+ if (state.status === 'paused' && state.waitingForNodeId) {
666
+ console.log(`\n⏸️ Waiting For: ${colorize('yellow', state.waitingForNodeId)} (Human Input)`);
667
+ }
668
+
669
+ if (state.deadLetterQueue && state.deadLetterQueue.length > 0) {
670
+ console.log(`\n💀 Dead Letter Queue: ${colorize('red', state.deadLetterQueue.join(', '))}`);
671
+ }
672
+
673
+ console.log(`\n🧠 Memory/Results Captured: ${state.results ? state.results.length : 0} nodes`);
674
+ } catch (error) {
675
+ console.error(colorize('red', `❌ Error reading state file: ${error.message}`));
676
+ process.exit(1);
677
+ }
678
+ }
679
+
680
+ function formatInspectStatus(status) {
681
+ switch (status) {
682
+ case 'active': return colorize('green', 'Active');
683
+ case 'completed': return colorize('cyan', 'Completed');
684
+ case 'failed': return colorize('red', 'Failed');
685
+ case 'paused': return colorize('yellow', 'Paused');
686
+ default: return status || 'Unknown';
687
+ }
688
+ }
689
+
621
690
  async function diffCommand(file1, file2) {
622
691
  console.log(colorize('cyan', '🔍 Comparing Society configurations...'));
623
692
 
@@ -654,16 +723,19 @@ async function diffCommand(file1, file2) {
654
723
  const society1 = module1.default || module1.society;
655
724
  const society2 = module2.default || module2.society;
656
725
 
657
- if (!society1 || !society2) {
658
- console.error(colorize('red', '❌ Error: Could not find Society in one or both files'));
726
+ if (!society1 || typeof society1.build !== 'function' || !society2 || typeof society2.build !== 'function') {
727
+ console.error(colorize('red', '❌ Error: Could not find Society builder in one or both files'));
659
728
  process.exit(1);
660
729
  }
661
730
 
731
+ const config1 = society1.build();
732
+ const config2 = society2.build();
733
+
662
734
  console.log(colorize('cyan', '\n📊 Comparison Results:'));
663
735
 
664
736
  // Compare agents
665
- const agents1 = society1.agents || [];
666
- const agents2 = society2.agents || [];
737
+ const agents1 = config1.agents || [];
738
+ const agents2 = config2.agents || [];
667
739
 
668
740
  console.log(colorize('blue', '\nAgents:'));
669
741
  console.log(colorize('dim', ` File 1: ${agents1.length} agents`));
@@ -688,8 +760,8 @@ async function diffCommand(file1, file2) {
688
760
  }
689
761
 
690
762
  // Compare tasks
691
- const tasks1 = society1.tasks || [];
692
- const tasks2 = society2.tasks || [];
763
+ const tasks1 = config1.tasks || [];
764
+ const tasks2 = config2.tasks || [];
693
765
 
694
766
  console.log(colorize('blue', '\nTasks:'));
695
767
  console.log(colorize('dim', ` File 1: ${tasks1.length} tasks`));
@@ -783,8 +855,7 @@ async function main() {
783
855
  break;
784
856
 
785
857
  case 'inspect':
786
- // Delegate to inspect.js
787
- require('./inspect');
858
+ await inspectCommand(args[0]);
788
859
  break;
789
860
 
790
861
  case 'diff':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "societyai",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "A powerful TypeScript library for creating collaborative multi-agent AI systems with DAG-based orchestration. Build sophisticated workflows where AI agents work together through dependency graphs, conditional routing, and pluggable execution strategies. Features thread-safe parallel execution, memory management, and circuit breaker patterns for production-grade reliability.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -108,7 +108,8 @@
108
108
  "prettier": "^3.1.1",
109
109
  "ts-jest": "^29.1.1",
110
110
  "ts-node": "^10.9.2",
111
- "typescript": "^5.7.3"
111
+ "typescript": "^5.7.3",
112
+ "vitest": "^4.1.0"
112
113
  },
113
114
  "peerDependencies": {
114
115
  "@modelcontextprotocol/sdk": "^0.5.0",