@iamoberlin/chorus 1.2.2 → 1.2.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/index.ts +110 -30
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  import * as prayers from "./src/prayers/prayers.js";
39
39
  import * as prayerStore from "./src/prayers/store.js";
40
40
 
41
- const VERSION = "1.2.2"; // Fix vision command CLI args
41
+ const VERSION = "1.2.4"; // Vision runs REAL choirs by default, --dry-run for narration
42
42
 
43
43
  const plugin = {
44
44
  id: "chorus",
@@ -264,8 +264,8 @@ const plugin = {
264
264
  // NOTE: This is CLI-only, runs via spawned openclaw agent calls
265
265
  program
266
266
  .command("vision [days]")
267
- .description("Simulate multiple days of choir cycles (prophetic vision)")
268
- .option("--dry-run", "Show what would run without executing")
267
+ .description("Run multiple days of choir cycles with real state changes (prophetic vision)")
268
+ .option("--dry-run", "Narration mode: describe what would happen without executing")
269
269
  .action((daysArg?: string, options?: { dryRun?: boolean }) => {
270
270
  // Synchronous wrapper to avoid async issues in commander
271
271
  const days = parseInt(daysArg || "1", 10);
@@ -286,9 +286,13 @@ const plugin = {
286
286
  console.log("");
287
287
  console.log("👁️ VISION MODE");
288
288
  console.log("═".repeat(55));
289
- console.log(` Simulating ${days} day${days > 1 ? 's' : ''} of cognitive cycles`);
290
- console.log(` Total choir runs: ${days * 9}`);
291
- console.log(` Mode: ${options?.dryRun ? 'DRY RUN' : 'LIVE'}`);
289
+ console.log(` Days: ${days}`);
290
+ console.log(` Choir runs: ${days * 9}`);
291
+ if (options?.dryRun) {
292
+ console.log(` Mode: DRY RUN (narration only, no state changes)`);
293
+ } else {
294
+ console.log(` Mode: LIVE (real execution, real state changes)`);
295
+ }
292
296
  console.log("");
293
297
 
294
298
  const startTime = Date.now();
@@ -307,41 +311,58 @@ const plugin = {
307
311
  totalRuns++;
308
312
 
309
313
  if (options?.dryRun) {
310
- console.log(` ${choir.emoji} ${choir.name} (would run)`);
311
- contextStore.set(choirId, `[Simulated ${choir.name} output for day ${day}]`);
314
+ // Dry run: narration mode - describe what would happen without doing it
315
+ process.stdout.write(` ${choir.emoji} ${choir.name}...`);
316
+ try {
317
+ const dryPrompt = `You are ${choir.name} in VISION MODE (day ${day}/${days}). Role: ${choir.function}. Output: ${choir.output}. Briefly describe what you would do. Keep response under 300 words.`;
318
+ const result = spawnSync('openclaw', [
319
+ 'agent',
320
+ '--session-id', `chorus:vision:dry:${choirId}:d${day}`,
321
+ '--message', dryPrompt,
322
+ '--json',
323
+ ], {
324
+ encoding: 'utf-8',
325
+ timeout: 60000,
326
+ maxBuffer: 1024 * 1024,
327
+ });
328
+ if (result.status === 0 && result.stdout) {
329
+ try {
330
+ const json = JSON.parse(result.stdout);
331
+ const text = json.result?.payloads?.[0]?.text || '';
332
+ contextStore.set(`${choirId}:d${day}`, text.slice(0, 500));
333
+ console.log(` ✓ (dry)`);
334
+ } catch {
335
+ contextStore.set(`${choirId}:d${day}`, `[${choir.name} would run]`);
336
+ console.log(` ✓ (dry)`);
337
+ }
338
+ } else {
339
+ console.log(` ✗ (dry)`);
340
+ }
341
+ } catch {
342
+ console.log(` ✗ (dry)`);
343
+ }
312
344
  continue;
313
345
  }
314
346
 
315
347
  process.stdout.write(` ${choir.emoji} ${choir.name}...`);
316
348
 
317
349
  try {
318
- // Build a simplified prompt for vision mode (short enough for CLI args)
319
- const visionPrompt = `You are ${choir.name} in VISION MODE (day ${day}/${days}). Role: ${choir.function}. Output: ${choir.output}. Provide a brief summary of what you would do. Keep response under 300 words.`;
320
-
321
- // Vision prompts are short - safe to use --message
350
+ // Run the REAL choir with full tool access
351
+ // This performs actual web searches, file updates, state changes
322
352
  const result = spawnSync('openclaw', [
323
- 'agent',
324
- '--session-id', `chorus:vision:${choirId}:d${day}`,
325
- '--message', visionPrompt,
326
- '--json',
353
+ 'chorus', 'run', choirId,
327
354
  ], {
328
355
  encoding: 'utf-8',
329
- timeout: 120000, // 2 min timeout per choir
330
- maxBuffer: 1024 * 1024, // 1MB buffer
356
+ timeout: 300000, // 5 min timeout per choir (real work takes longer)
357
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer for full output
331
358
  });
332
359
 
333
- if (result.status === 0 && result.stdout) {
334
- try {
335
- const json = JSON.parse(result.stdout);
336
- const text = json.result?.payloads?.[0]?.text || '';
337
- contextStore.set(choirId, text.slice(0, 500));
338
- successfulRuns++;
339
- console.log(` ✓`);
340
- } catch {
341
- contextStore.set(choirId, `[${choir.name} completed]`);
342
- successfulRuns++;
343
- console.log(` ✓`);
344
- }
360
+ if (result.status === 0) {
361
+ // Capture the choir's output for summary
362
+ const output = result.stdout || '';
363
+ contextStore.set(`${choirId}:d${day}`, output.slice(-2000)); // Last 2KB
364
+ successfulRuns++;
365
+ console.log(` ✓`);
345
366
  } else {
346
367
  const errMsg = (result.stderr || result.error?.message || 'unknown error').slice(0, 100);
347
368
  console.log(` ✗ (${errMsg})`);
@@ -364,6 +385,65 @@ const plugin = {
364
385
  console.log(` Choir runs: ${successfulRuns}/${totalRuns}`);
365
386
  console.log(` Duration: ${elapsed}s`);
366
387
  console.log("");
388
+
389
+ // Output collected insights
390
+ if (contextStore.size > 0 && !options?.dryRun) {
391
+ console.log("📜 COLLECTED INSIGHTS");
392
+ console.log("═".repeat(55));
393
+
394
+ // Group by choir across days
395
+ const choirInsights: Map<string, string[]> = new Map();
396
+ for (const [key, value] of contextStore) {
397
+ const [choirId] = key.split(':');
398
+ if (!choirInsights.has(choirId)) {
399
+ choirInsights.set(choirId, []);
400
+ }
401
+ choirInsights.get(choirId)!.push(value);
402
+ }
403
+
404
+ // Output key choirs with full text
405
+ const keyChoirs = ['virtues', 'powers', 'seraphim'];
406
+ for (const choirId of keyChoirs) {
407
+ const choir = CHOIRS[choirId];
408
+ if (!choir) continue;
409
+
410
+ const insights = [];
411
+ for (const [key, value] of contextStore) {
412
+ if (key.startsWith(choirId) || key.includes(`:${choirId}:`)) {
413
+ insights.push(value);
414
+ }
415
+ }
416
+
417
+ if (insights.length > 0) {
418
+ console.log("");
419
+ console.log(`${choir.emoji} ${choir.name.toUpperCase()}`);
420
+ console.log("─".repeat(40));
421
+ insights.forEach((insight, i) => {
422
+ if (days > 1) console.log(`Day ${i + 1}:`);
423
+ console.log(insight);
424
+ console.log("");
425
+ });
426
+ }
427
+ }
428
+
429
+ // RSI Summary (from Virtues)
430
+ const virtuesInsights = [];
431
+ for (const [key, value] of contextStore) {
432
+ if (key.includes('virtues')) {
433
+ virtuesInsights.push(value);
434
+ }
435
+ }
436
+
437
+ if (virtuesInsights.length > 0) {
438
+ console.log("");
439
+ console.log("🔄 RSI SUMMARY (Self-Improvement)");
440
+ console.log("═".repeat(55));
441
+ virtuesInsights.forEach((v, i) => {
442
+ console.log(`Day ${i + 1}: ${v.slice(0, 200)}${v.length > 200 ? '...' : ''}`);
443
+ });
444
+ console.log("");
445
+ }
446
+ }
367
447
  });
368
448
 
369
449
  // Metrics command
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamoberlin/chorus",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "CHORUS: Hierarchy Of Recursive Unified Self-improvement — with Prayer Requests social network",
5
5
  "author": "Oberlin <iam@oberlin.ai>",
6
6
  "license": "MIT",