chainlesschain 0.47.5 → 0.47.7

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 (109) hide show
  1. package/package.json +2 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/Analytics-BFI7jbwM.css +1 -0
  4. package/src/assets/web-panel/assets/Analytics-DQ135mAd.js +3 -0
  5. package/src/assets/web-panel/assets/AppLayout-6SPt_8Y_.js +1 -0
  6. package/src/assets/web-panel/assets/AppLayout-BFJ-Fofn.css +1 -0
  7. package/src/assets/web-panel/assets/{Backup-Ba9UybpT.js → Backup-DbVRG5vE.js} +1 -1
  8. package/src/assets/web-panel/assets/{Chat-BwXskT21.js → Chat-wVhrFK9C.js} +1 -1
  9. package/src/assets/web-panel/assets/{Cowork-UmOe7qvE.js → Cowork-lOC25IW2.js} +1 -1
  10. package/src/assets/web-panel/assets/{Cron-JHS-rc-4.js → Cron-3P0eVLTV.js} +1 -1
  11. package/src/assets/web-panel/assets/{Dashboard-B95cMCO7.js → Dashboard-Br7kCwKJ.js} +1 -1
  12. package/src/assets/web-panel/assets/{Git-CSYO0_zk.js → Git-CrDCcBig.js} +2 -2
  13. package/src/assets/web-panel/assets/{Logs-Hxw_K0km.js → Logs-BfTE8urP.js} +1 -1
  14. package/src/assets/web-panel/assets/{McpTools-DIE75TrB.js → McpTools-CsGIijNe.js} +1 -1
  15. package/src/assets/web-panel/assets/{Memory-C4KVnLlp.js → Memory-BXX_yMKJ.js} +1 -1
  16. package/src/assets/web-panel/assets/{Notes-DuzrHMAk.js → Notes-DU6Vf2cL.js} +1 -1
  17. package/src/assets/web-panel/assets/{Organization-DTq6uF82.js → Organization-Bny6yOPV.js} +4 -4
  18. package/src/assets/web-panel/assets/{P2P-C0hjlhsR.js → P2P-BxFZ1Bit.js} +2 -2
  19. package/src/assets/web-panel/assets/{Permissions-Ec0NH-xC.js → Permissions-B1j3Mtms.js} +3 -3
  20. package/src/assets/web-panel/assets/{Projects-U8D0asCS.js → Projects-D-CGscDu.js} +1 -1
  21. package/src/assets/web-panel/assets/{Providers-BngtTLvJ.js → Providers-r6NaBYMf.js} +1 -1
  22. package/src/assets/web-panel/assets/{RssFeed-B9NbwCKM.js → RssFeed-D7b68C5q.js} +1 -1
  23. package/src/assets/web-panel/assets/{Security-BL5Rkr1T.js → Security-MJfKv0EJ.js} +3 -3
  24. package/src/assets/web-panel/assets/{Services-D4MJzLld.js → Services-Yb_Q1V3d.js} +1 -1
  25. package/src/assets/web-panel/assets/{Skills-CQTOMDwF.js → Skills-DLTHcH5T.js} +1 -1
  26. package/src/assets/web-panel/assets/{Tasks-DepbJMnL.js → Tasks-CqycpPjS.js} +1 -1
  27. package/src/assets/web-panel/assets/{Templates-C24PVZPu.js → Templates-y01u2Zis.js} +1 -1
  28. package/src/assets/web-panel/assets/VideoEditing-BA1N-5kq.css +1 -0
  29. package/src/assets/web-panel/assets/VideoEditing-B_nPKw6B.js +1 -0
  30. package/src/assets/web-panel/assets/{Wallet-PQoSpN_P.js → Wallet-CsRgnjJY.js} +1 -1
  31. package/src/assets/web-panel/assets/{WebAuthn-BcuyQ4Lr.js → WebAuthn-DWoR5ADp.js} +1 -1
  32. package/src/assets/web-panel/assets/{WorkflowEditor-C-SvXbHW.js → WorkflowEditor-DBJhFPMN.js} +1 -1
  33. package/src/assets/web-panel/assets/{antd-DEjZPGMj.js → antd-Dh2t0vGq.js} +84 -84
  34. package/src/assets/web-panel/assets/index-tN-8TosE.js +2 -0
  35. package/src/assets/web-panel/assets/{markdown-CusdXFxb.js → markdown-CBnGGMzE.js} +1 -1
  36. package/src/assets/web-panel/index.html +2 -2
  37. package/src/commands/agent.js +20 -0
  38. package/src/commands/config.js +67 -0
  39. package/src/commands/mcp.js +86 -4
  40. package/src/commands/memory.js +175 -0
  41. package/src/commands/sandbox.js +80 -6
  42. package/src/commands/serve.js +10 -0
  43. package/src/commands/session.js +284 -0
  44. package/src/commands/stream.js +75 -0
  45. package/src/commands/video.js +363 -0
  46. package/src/gateways/http/envelope-http-server.js +194 -0
  47. package/src/gateways/ws/message-dispatcher.js +123 -0
  48. package/src/gateways/ws/session-core-protocol.js +427 -0
  49. package/src/gateways/ws/session-protocol.js +42 -1
  50. package/src/gateways/ws/video-protocol.js +230 -0
  51. package/src/gateways/ws/ws-server.js +72 -0
  52. package/src/gateways/ws/ws-session-gateway.js +7 -3
  53. package/src/harness/jsonl-session-store.js +17 -9
  54. package/src/index.js +8 -0
  55. package/src/lib/agent-stream.js +63 -0
  56. package/src/lib/chat-core.js +183 -6
  57. package/src/lib/cowork/ab-comparator-cli.js +44 -23
  58. package/src/lib/cowork/agent-group-runner.js +145 -0
  59. package/src/lib/cowork/debate-review-cli.js +47 -25
  60. package/src/lib/cowork/project-style-analyzer-cli.js +34 -7
  61. package/src/lib/interaction-adapter.js +59 -1
  62. package/src/lib/jsonl-session-store.js +2 -0
  63. package/src/lib/memory-injection.js +90 -0
  64. package/src/lib/provider-stream.js +120 -0
  65. package/src/lib/sandbox-v2.js +198 -3
  66. package/src/lib/session-consolidator.js +125 -0
  67. package/src/lib/session-core-singletons.js +126 -0
  68. package/src/lib/session-tail.js +128 -0
  69. package/src/lib/session-usage.js +166 -0
  70. package/src/lib/shell-approval.js +96 -0
  71. package/src/lib/ws-chat-handler.js +3 -0
  72. package/src/repl/agent-repl.js +271 -6
  73. package/src/repl/chat-repl.js +87 -100
  74. package/src/runtime/agent-core.js +98 -15
  75. package/src/runtime/agent-runtime.js +105 -3
  76. package/src/runtime/policies/agent-policy.js +10 -0
  77. package/src/session/index.js +7 -0
  78. package/src/skills/video-editing/SKILL.md +46 -0
  79. package/src/skills/video-editing/beat-snap.js +127 -0
  80. package/src/skills/video-editing/extractors/audio-extractor.js +212 -0
  81. package/src/skills/video-editing/extractors/subtitle-extractor.js +90 -0
  82. package/src/skills/video-editing/extractors/video-extractor.js +137 -0
  83. package/src/skills/video-editing/parallel-orchestrator.js +212 -0
  84. package/src/skills/video-editing/pipeline.js +480 -0
  85. package/src/skills/video-editing/prompts/aesthetic-analysis.md +21 -0
  86. package/src/skills/video-editing/prompts/audio-segment.md +15 -0
  87. package/src/skills/video-editing/prompts/character-identify.md +19 -0
  88. package/src/skills/video-editing/prompts/dense-caption.md +20 -0
  89. package/src/skills/video-editing/prompts/editor-system.md +29 -0
  90. package/src/skills/video-editing/prompts/hook-dialogue.md +17 -0
  91. package/src/skills/video-editing/prompts/protagonist-detect.md +20 -0
  92. package/src/skills/video-editing/prompts/scene-caption.md +16 -0
  93. package/src/skills/video-editing/prompts/shot-caption.md +25 -0
  94. package/src/skills/video-editing/prompts/shot-plan.md +28 -0
  95. package/src/skills/video-editing/prompts/structure-proposal.md +16 -0
  96. package/src/skills/video-editing/prompts/vlog-scene-caption.md +18 -0
  97. package/src/skills/video-editing/render/audio-mix.js +128 -0
  98. package/src/skills/video-editing/render/ffmpeg-concat.js +45 -0
  99. package/src/skills/video-editing/render/ffmpeg-extract.js +67 -0
  100. package/src/skills/video-editing/reviewer.js +161 -0
  101. package/src/skills/video-editing/tools/commit.js +108 -0
  102. package/src/skills/video-editing/tools/review-clip.js +46 -0
  103. package/src/skills/video-editing/tools/semantic-retrieval.js +56 -0
  104. package/src/skills/video-editing/tools/shot-trimming.js +73 -0
  105. package/src/assets/web-panel/assets/Analytics-B4OM8S8X.css +0 -1
  106. package/src/assets/web-panel/assets/Analytics-DgypYeUB.js +0 -3
  107. package/src/assets/web-panel/assets/AppLayout-Bzf3mSZI.js +0 -1
  108. package/src/assets/web-panel/assets/AppLayout-DQyDwGut.css +0 -1
  109. package/src/assets/web-panel/assets/index-CwvzTTw_.js +0 -2
@@ -416,6 +416,290 @@ export function registerSessionCommand(program) {
416
416
  }
417
417
  });
418
418
 
419
+ // session policy — Managed Agents parity Phase E1 approval policy
420
+ session
421
+ .command("policy")
422
+ .description("Show or set per-session approval policy")
423
+ .argument("<id>", "Session ID")
424
+ .option("--set <policy>", "strict | trusted | autopilot")
425
+ .option("--json", "Output as JSON")
426
+ .action(async (id, options) => {
427
+ try {
428
+ const { getApprovalGate } =
429
+ await import("../lib/session-core-singletons.js");
430
+ const gate = await getApprovalGate();
431
+ if (options.set) {
432
+ gate.setSessionPolicy(id, options.set);
433
+ // give persistence a tick before the CLI process exits
434
+ await new Promise((r) => setImmediate(r));
435
+ logger.success(
436
+ `Session ${chalk.gray(id.slice(0, 12))} policy → ${chalk.cyan(options.set)}`,
437
+ );
438
+ }
439
+ const current = gate.getSessionPolicy(id);
440
+ if (options.json) {
441
+ console.log(JSON.stringify({ sessionId: id, policy: current }));
442
+ } else if (!options.set) {
443
+ logger.log(
444
+ `Session ${chalk.gray(id.slice(0, 12))} policy: ${chalk.cyan(current)}`,
445
+ );
446
+ }
447
+ } catch (err) {
448
+ logger.error(`Failed: ${err.message}`);
449
+ process.exit(1);
450
+ }
451
+ });
452
+
453
+ // ---------------------------------------------------------------
454
+ // session-core SessionManager lifecycle (Phase H — CLI parity)
455
+ // Parked sessions persist to ~/.chainlesschain/parked-sessions.json
456
+ // ---------------------------------------------------------------
457
+ session
458
+ .command("lifecycle")
459
+ .description("List session-core handles (running/idle/parked)")
460
+ .option("--status <s>", "Filter by status: running | idle | parked")
461
+ .option("--agent <id>", "Filter by agent id")
462
+ .option("--json", "Output as JSON")
463
+ .action(async (options) => {
464
+ try {
465
+ const { getSessionManager } =
466
+ await import("../lib/session-core-singletons.js");
467
+ const mgr = getSessionManager();
468
+ const live = mgr.list({
469
+ agentId: options.agent,
470
+ status: options.status,
471
+ });
472
+ let parked = [];
473
+ if (mgr._parkedStore) {
474
+ const all = await mgr._parkedStore.list();
475
+ parked = all
476
+ .filter((s) => !options.agent || s.agentId === options.agent)
477
+ .filter((s) => !options.status || s.status === options.status);
478
+ }
479
+ const merged = [
480
+ ...live.map((h) => h.toJSON()),
481
+ ...parked.filter(
482
+ (p) => !live.some((h) => h.sessionId === p.sessionId),
483
+ ),
484
+ ];
485
+ if (options.json) {
486
+ console.log(JSON.stringify(merged, null, 2));
487
+ return;
488
+ }
489
+ if (merged.length === 0) {
490
+ logger.info("No session-core handles");
491
+ return;
492
+ }
493
+ for (const h of merged) {
494
+ logger.log(
495
+ `${chalk.gray(h.sessionId.slice(0, 12))} ${chalk.cyan(h.status.padEnd(7))} agent=${h.agentId || "-"}`,
496
+ );
497
+ }
498
+ } catch (err) {
499
+ logger.error(`Failed: ${err.message}`);
500
+ process.exit(1);
501
+ }
502
+ });
503
+
504
+ session
505
+ .command("park")
506
+ .description("Park a session (persist to disk, free process memory)")
507
+ .argument("<id>", "Session ID")
508
+ .action(async (id) => {
509
+ try {
510
+ const { getSessionManager } =
511
+ await import("../lib/session-core-singletons.js");
512
+ const mgr = getSessionManager();
513
+ if (!mgr.has(id)) {
514
+ logger.error(`Session ${id} is not active in this process`);
515
+ process.exit(1);
516
+ }
517
+ mgr.markIdle(id);
518
+ const ok = await mgr.park(id);
519
+ if (!ok) {
520
+ logger.error(`Failed to park ${id}`);
521
+ process.exit(1);
522
+ }
523
+ logger.success(`Session ${chalk.gray(id.slice(0, 12))} parked`);
524
+ } catch (err) {
525
+ logger.error(`Failed: ${err.message}`);
526
+ process.exit(1);
527
+ }
528
+ });
529
+
530
+ session
531
+ .command("unpark")
532
+ .description("Resume a parked session")
533
+ .argument("<id>", "Session ID")
534
+ .action(async (id) => {
535
+ try {
536
+ const { getSessionManager } =
537
+ await import("../lib/session-core-singletons.js");
538
+ const mgr = getSessionManager();
539
+ const ok = await mgr.resume(id);
540
+ if (!ok) {
541
+ logger.error(`No parked session ${id}`);
542
+ process.exit(1);
543
+ }
544
+ logger.success(`Session ${chalk.gray(id.slice(0, 12))} resumed`);
545
+ } catch (err) {
546
+ logger.error(`Failed: ${err.message}`);
547
+ process.exit(1);
548
+ }
549
+ });
550
+
551
+ session
552
+ .command("end")
553
+ .description(
554
+ "Close a session (optionally consolidate trace into MemoryStore)",
555
+ )
556
+ .argument("<id>", "Session ID")
557
+ .option(
558
+ "--consolidate",
559
+ "Consolidate JSONL trace into MemoryStore before closing",
560
+ )
561
+ .option("--scope <s>", "Memory scope for consolidation", "session")
562
+ .option("--scope-id <id>", "Scope id (defaults to session id)")
563
+ .option("--agent-id <id>", "Agent id for scope=agent")
564
+ .action(async (id, options) => {
565
+ try {
566
+ const { getSessionManager } =
567
+ await import("../lib/session-core-singletons.js");
568
+ if (options.consolidate) {
569
+ try {
570
+ const { consolidateJsonlSession } =
571
+ await import("../lib/session-consolidator.js");
572
+ const res = await consolidateJsonlSession(id, {
573
+ scope: options.scope,
574
+ scopeId: options.scopeId || null,
575
+ agentId: options.agentId || null,
576
+ });
577
+ await new Promise((r) => setImmediate(r));
578
+ logger.info(
579
+ `Consolidated ${res.writtenCount} memory entries from session trace`,
580
+ );
581
+ } catch (e) {
582
+ logger.warn(`Consolidation skipped: ${e.message}`);
583
+ }
584
+ }
585
+ const mgr = getSessionManager();
586
+ const ok = await mgr.close(id);
587
+ if (!ok && mgr._parkedStore) {
588
+ await mgr._parkedStore.remove(id);
589
+ }
590
+ logger.success(`Session ${chalk.gray(id.slice(0, 12))} closed`);
591
+ } catch (err) {
592
+ logger.error(`Failed: ${err.message}`);
593
+ process.exit(1);
594
+ }
595
+ });
596
+
597
+ // ---------------------------------------------------------------
598
+ // session tail <id> — Phase I: follow JSONL events as NDJSON
599
+ // ---------------------------------------------------------------
600
+ session
601
+ .command("tail")
602
+ .description("Follow a JSONL session's events (NDJSON on stdout)")
603
+ .argument("<id>", "Session ID")
604
+ .option("--from-start", "Start from the first event (default: EOF)")
605
+ .option("--from-offset <n>", "Start from explicit byte offset")
606
+ .option("-t, --type <types>", "Comma-separated event types to include")
607
+ .option("--since <ms>", "Only events with timestamp >= ms")
608
+ .option("--once", "Drain current tail and exit (no follow)")
609
+ .option("--poll <ms>", "Poll interval", "200")
610
+ .action(async (id, options) => {
611
+ try {
612
+ const { followSession } = await import("../lib/session-tail.js");
613
+ const controller = new AbortController();
614
+ const onSig = () => controller.abort();
615
+ process.once("SIGINT", onSig);
616
+ process.once("SIGTERM", onSig);
617
+ const types = options.type
618
+ ? options.type
619
+ .split(",")
620
+ .map((s) => s.trim())
621
+ .filter(Boolean)
622
+ : null;
623
+ const iter = followSession(id, {
624
+ signal: controller.signal,
625
+ pollMs: parseInt(options.poll, 10) || 200,
626
+ fromStart: Boolean(options.fromStart),
627
+ fromOffset:
628
+ options.fromOffset !== undefined
629
+ ? parseInt(options.fromOffset, 10)
630
+ : undefined,
631
+ types,
632
+ sinceMs: options.since ? parseInt(options.since, 10) : null,
633
+ once: Boolean(options.once),
634
+ });
635
+ for await (const { event } of iter) {
636
+ process.stdout.write(JSON.stringify(event) + "\n");
637
+ }
638
+ } catch (err) {
639
+ logger.error(`Failed: ${err.message}`);
640
+ process.exit(1);
641
+ }
642
+ });
643
+
644
+ // ---------------------------------------------------------------
645
+ // session usage [id] — Phase I: aggregate token usage
646
+ // ---------------------------------------------------------------
647
+ session
648
+ .command("usage")
649
+ .description("Aggregate token usage (per-session or global)")
650
+ .argument("[id]", "Session ID (omit for global rollup)")
651
+ .option("--json", "Output as JSON")
652
+ .option("--limit <n>", "Max sessions for global rollup", "1000")
653
+ .action(async (id, options) => {
654
+ try {
655
+ const { sessionUsage, allSessionsUsage } =
656
+ await import("../lib/session-usage.js");
657
+ const result = id
658
+ ? sessionUsage(id)
659
+ : allSessionsUsage({ limit: parseInt(options.limit, 10) || 1000 });
660
+
661
+ if (options.json) {
662
+ console.log(JSON.stringify(result, null, 2));
663
+ return;
664
+ }
665
+
666
+ if (id) {
667
+ logger.log(chalk.bold(`Session ${chalk.gray(id.slice(0, 16))}`));
668
+ const t = result.total;
669
+ logger.log(
670
+ ` total: ${chalk.cyan(t.totalTokens.toLocaleString())} tokens in=${t.inputTokens} out=${t.outputTokens} calls=${t.calls}`,
671
+ );
672
+ if (result.byModel.length === 0) {
673
+ logger.log(chalk.gray(" (no token_usage events recorded)"));
674
+ return;
675
+ }
676
+ for (const row of result.byModel) {
677
+ logger.log(
678
+ ` ${chalk.gray((row.provider || "?").padEnd(10))} ${chalk.white((row.model || "?").padEnd(24))} in=${row.inputTokens} out=${row.outputTokens} calls=${row.calls}`,
679
+ );
680
+ }
681
+ } else {
682
+ const t = result.total;
683
+ logger.log(chalk.bold("Global usage"));
684
+ logger.log(
685
+ ` total: ${chalk.cyan(t.totalTokens.toLocaleString())} tokens in=${t.inputTokens} out=${t.outputTokens} calls=${t.calls} sessions=${result.sessions.length}`,
686
+ );
687
+ if (result.byModel.length === 0) {
688
+ logger.log(chalk.gray(" (no token_usage events recorded)"));
689
+ return;
690
+ }
691
+ for (const row of result.byModel) {
692
+ logger.log(
693
+ ` ${chalk.gray((row.provider || "?").padEnd(10))} ${chalk.white((row.model || "?").padEnd(24))} in=${row.inputTokens} out=${row.outputTokens} calls=${row.calls}`,
694
+ );
695
+ }
696
+ }
697
+ } catch (err) {
698
+ logger.error(`Failed: ${err.message}`);
699
+ process.exit(1);
700
+ }
701
+ });
702
+
419
703
  // session workflow — inspect canonical coding workflow state
420
704
  // Reads .chainlesschain/sessions/<id>/{intent.md,plan.md,progress.log,mode.json}
421
705
  // written by the 4 workflow skills ($deep-interview/$ralplan/$ralph/$team).
@@ -0,0 +1,75 @@
1
+ /**
2
+ * chainlesschain stream "<prompt>" — scriptable StreamRouter demo.
3
+ *
4
+ * Mirrors Desktop's `agent:stream:start` IPC: feed a provider stream through
5
+ * session-core StreamRouter and emit StreamEvent objects as NDJSON on stdout
6
+ * so downstream scripts can consume them line-by-line.
7
+ *
8
+ * Managed Agents parity Phase H — CLI symmetric entry.
9
+ * Provider adapters live in `../lib/provider-stream.js` so the WS
10
+ * `stream.run` route can reuse them (Phase I).
11
+ */
12
+
13
+ import { logger } from "../lib/logger.js";
14
+ import { loadConfig } from "../lib/config-manager.js";
15
+ import { buildProviderSource } from "../lib/provider-stream.js";
16
+
17
+ export function registerStreamCommand(program) {
18
+ program
19
+ .command("stream")
20
+ .description(
21
+ "Stream a single prompt through session-core StreamRouter (NDJSON on stdout)",
22
+ )
23
+ .argument("<prompt>", "The prompt to stream")
24
+ .option("--model <model>", "Model name")
25
+ .option("--provider <provider>", "LLM provider", "ollama")
26
+ .option("--base-url <url>", "API base URL")
27
+ .option("--api-key <key>", "API key")
28
+ .option("--text", "Emit concatenated final text instead of NDJSON events")
29
+ .action(async (prompt, options) => {
30
+ const config = loadConfig();
31
+ const provider = options.provider || config.llm?.provider || "ollama";
32
+ const baseUrl = options.baseUrl || config.llm?.baseUrl;
33
+ const apiKey = options.apiKey || config.llm?.apiKey;
34
+ const model = options.model || config.llm?.model;
35
+
36
+ try {
37
+ const { createStreamRouter } =
38
+ await import("../lib/session-core-singletons.js");
39
+ const router = createStreamRouter();
40
+ const source = buildProviderSource(provider, {
41
+ model,
42
+ baseUrl,
43
+ apiKey,
44
+ prompt,
45
+ });
46
+
47
+ if (options.text) {
48
+ const out = await router.collect(source);
49
+ if (out.errored) {
50
+ logger.error(`Stream errored: ${out.error?.message || out.error}`);
51
+ process.exit(1);
52
+ }
53
+ process.stdout.write(out.text);
54
+ if (!out.text.endsWith("\n")) process.stdout.write("\n");
55
+ return;
56
+ }
57
+
58
+ for await (const ev of router.stream(source)) {
59
+ process.stdout.write(`${JSON.stringify(ev)}\n`);
60
+ }
61
+ } catch (err) {
62
+ const ev = {
63
+ type: "error",
64
+ error: err.message,
65
+ ts: Date.now(),
66
+ };
67
+ if (options.text) {
68
+ logger.error(`Failed: ${err.message}`);
69
+ } else {
70
+ process.stdout.write(`${JSON.stringify(ev)}\n`);
71
+ }
72
+ process.exit(1);
73
+ }
74
+ });
75
+ }