arcanea 3.3.0 → 3.4.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/dist/cli/index.js CHANGED
@@ -2199,7 +2199,7 @@ var {
2199
2199
  } = import__.default;
2200
2200
 
2201
2201
  // src/cli/index.ts
2202
- var import_picocolors2 = __toESM(require_picocolors(), 1);
2202
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
2203
2203
 
2204
2204
  // src/install.ts
2205
2205
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -2323,6 +2323,8 @@ async function installForPlatform(targetDir, packageRoot, platform, force) {
2323
2323
  async function installClaudeCodeSettings(platformPath, force) {
2324
2324
  const settingsPath = join(platformPath, "settings.json");
2325
2325
  if (!existsSync(settingsPath) || force) {
2326
+ const eventsDir = join(process.env.HOME || process.env.USERPROFILE || "~", ".arcanea").replace(/\\/g, "/");
2327
+ const logScript = `mkdir -p "${eventsDir}" && echo '{"type":"agent-spawn","agent":"'$(echo "$TOOL_INPUT" 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync(0,'utf8'));process.stdout.write((d.subagent_type||'unknown')+'","description":"'+(d.description||'').replace(/"/g,'')+'","team":"'+(d.subagent_type||''))}catch{process.stdout.write('unknown","description":"","team":"')}" 2>/dev/null)","timestamp":'$(date +%s000)'}' >> "${eventsDir}/swarm-events.jsonl"`;
2326
2328
  const settings = {
2327
2329
  hooks: {
2328
2330
  UserPromptSubmit: [
@@ -2361,6 +2363,15 @@ async function installClaudeCodeSettings(platformPath, force) {
2361
2363
  command: "echo '[ARCANEA_MODE=ultrawork] Maximum parallel execution. Spawn all relevant agents simultaneously using Task tool with run_in_background=true.'"
2362
2364
  }]
2363
2365
  }
2366
+ ],
2367
+ PreToolUse: [
2368
+ {
2369
+ matcher: "Task",
2370
+ hooks: [{
2371
+ type: "command",
2372
+ command: logScript
2373
+ }]
2374
+ }
2364
2375
  ]
2365
2376
  }
2366
2377
  };
@@ -2519,7 +2530,7 @@ function printSuccessMessage(platforms) {
2519
2530
  }
2520
2531
 
2521
2532
  // src/index.ts
2522
- var VERSION = "3.3.0";
2533
+ var VERSION = "3.4.0";
2523
2534
  var NAME = "arcanea";
2524
2535
  var ORCHESTRATOR = "Arcanea";
2525
2536
  var defaultConfig = {
@@ -2645,15 +2656,379 @@ var AGENT_TEAMS = {
2645
2656
  }
2646
2657
  };
2647
2658
 
2648
- // src/cli/index.ts
2649
- import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
2659
+ // src/viz/index.ts
2660
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
2661
+ import { createServer } from "http";
2662
+ import { existsSync as existsSync2, readFileSync as readFileSync2, appendFileSync, mkdirSync as mkdirSync2, statSync } from "fs";
2650
2663
  import { join as join2 } from "path";
2664
+ import { execFile } from "child_process";
2665
+ var ARCANEA_DIR = join2(process.env.HOME || process.env.USERPROFILE || "~", ".arcanea");
2666
+ var EVENTS_FILE = join2(ARCANEA_DIR, "swarm-events.jsonl");
2667
+ function logEvent(event) {
2668
+ mkdirSync2(ARCANEA_DIR, { recursive: true });
2669
+ appendFileSync(EVENTS_FILE, JSON.stringify(event) + `
2670
+ `);
2671
+ }
2672
+ function readEvents() {
2673
+ if (!existsSync2(EVENTS_FILE))
2674
+ return [];
2675
+ const content = readFileSync2(EVENTS_FILE, "utf-8").trim();
2676
+ if (!content)
2677
+ return [];
2678
+ return content.split(`
2679
+ `).map((line) => {
2680
+ try {
2681
+ return JSON.parse(line);
2682
+ } catch {
2683
+ return null;
2684
+ }
2685
+ }).filter(Boolean);
2686
+ }
2687
+ var clients = new Set;
2688
+ function broadcast(event) {
2689
+ const data = `data: ${JSON.stringify(event)}
2690
+
2691
+ `;
2692
+ for (const client of clients) {
2693
+ try {
2694
+ client.write(data);
2695
+ } catch {
2696
+ clients.delete(client);
2697
+ }
2698
+ }
2699
+ }
2700
+ function handleSSE(req, res) {
2701
+ res.writeHead(200, {
2702
+ "Content-Type": "text/event-stream",
2703
+ "Cache-Control": "no-cache",
2704
+ Connection: "keep-alive",
2705
+ "Access-Control-Allow-Origin": "*"
2706
+ });
2707
+ clients.add(res);
2708
+ req.on("close", () => clients.delete(res));
2709
+ const events = readEvents();
2710
+ res.write(`data: ${JSON.stringify({ type: "initial", events })}
2711
+
2712
+ `);
2713
+ }
2714
+ function handleAPI(_req, res) {
2715
+ const events = readEvents();
2716
+ res.writeHead(200, { "Content-Type": "application/json" });
2717
+ res.end(JSON.stringify({ events }));
2718
+ }
2719
+ function openBrowser(url) {
2720
+ if (process.platform === "darwin") {
2721
+ execFile("open", [url], () => {});
2722
+ } else if (process.platform === "win32") {
2723
+ execFile("cmd", ["/c", "start", url], () => {});
2724
+ } else {
2725
+ execFile("xdg-open", [url], () => {});
2726
+ }
2727
+ }
2728
+ function getDashboardHTML() {
2729
+ return `<!DOCTYPE html>
2730
+ <html lang="en">
2731
+ <head>
2732
+ <meta charset="utf-8">
2733
+ <meta name="viewport" content="width=device-width, initial-scale=1">
2734
+ <title>Arcanea Swarm Viz</title>
2735
+ <style>
2736
+ *{margin:0;padding:0;box-sizing:border-box}
2737
+ :root{--bg:#0a0a1a;--surface:#111128;--border:#1e1e3a;--teal:#7fffd4;--gold:#ffd700;--blue:#78a6ff;
2738
+ --red:#ff4757;--text:#e0e0e0;--dim:#666;--green:#2ed573;--purple:#a855f7}
2739
+ body{background:var(--bg);color:var(--text);font-family:'Segoe UI',system-ui,sans-serif;min-height:100vh}
2740
+ .header{background:linear-gradient(135deg,#0d0d2b,#1a1a3e);border-bottom:1px solid var(--border);padding:16px 24px;display:flex;align-items:center;gap:16px}
2741
+ .header h1{font-size:20px;color:var(--teal);font-weight:600}
2742
+ .header .version{color:var(--dim);font-size:12px}
2743
+ .header .status{margin-left:auto;display:flex;align-items:center;gap:8px}
2744
+ .dot{width:8px;height:8px;border-radius:50%;background:var(--green);animation:pulse 2s infinite}
2745
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}
2746
+ .stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;padding:16px 24px}
2747
+ .stat{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:16px;text-align:center}
2748
+ .stat .label{font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:1px;margin-bottom:4px}
2749
+ .stat .value{font-size:28px;font-weight:700;color:var(--teal)}
2750
+ .stat .value.gold{color:var(--gold)}
2751
+ .stat .value.blue{color:var(--blue)}
2752
+ .main{display:grid;grid-template-columns:1fr 300px;gap:16px;padding:0 24px 24px;height:calc(100vh - 200px)}
2753
+ .events{background:var(--surface);border:1px solid var(--border);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
2754
+ .events .title{padding:12px 16px;border-bottom:1px solid var(--border);font-size:13px;font-weight:600;display:flex;align-items:center;gap:8px}
2755
+ .events .title .count{color:var(--dim);font-weight:400}
2756
+ .event-list{flex:1;overflow-y:auto;padding:8px}
2757
+ .event{padding:8px 12px;border-radius:6px;margin-bottom:4px;font-size:13px;display:flex;align-items:flex-start;gap:8px;animation:fadeIn 0.3s ease}
2758
+ @keyframes fadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
2759
+ .event .time{color:var(--dim);font-size:11px;min-width:60px;font-family:monospace}
2760
+ .event .badge{padding:2px 6px;border-radius:4px;font-size:10px;font-weight:600;text-transform:uppercase}
2761
+ .badge-spawn{background:#7fffd420;color:var(--teal)}
2762
+ .badge-complete{background:#2ed57320;color:var(--green)}
2763
+ .badge-error{background:#ff475720;color:var(--red)}
2764
+ .badge-magic{background:#ffd70020;color:var(--gold)}
2765
+ .event .desc{flex:1;word-break:break-word}
2766
+ .event .agent-name{color:var(--blue);font-weight:500}
2767
+ .event .dur{color:var(--dim);font-size:11px;font-family:monospace}
2768
+ .sidebar{display:flex;flex-direction:column;gap:12px}
2769
+ .panel{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px}
2770
+ .panel .title{font-size:13px;font-weight:600;margin-bottom:12px}
2771
+ .bar-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12px}
2772
+ .bar-label{min-width:80px;color:var(--dim)}
2773
+ .bar-track{flex:1;height:8px;background:var(--bg);border-radius:4px;overflow:hidden}
2774
+ .bar-fill{height:100%;border-radius:4px;transition:width 0.5s ease}
2775
+ .fill-creative{background:var(--teal)}.fill-coding{background:var(--blue)}.fill-writing{background:var(--green)}
2776
+ .fill-research{background:var(--gold)}.fill-production{background:var(--purple)}.fill-development{background:var(--blue)}
2777
+ .fill-teacher{background:#ff6b81}.fill-visionary{background:var(--gold)}.fill-default{background:var(--teal)}
2778
+ .bar-value{min-width:30px;text-align:right;font-family:monospace;color:var(--dim)}
2779
+ .timing{font-family:monospace;font-size:13px}
2780
+ .timing .row{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--border)}
2781
+ .timing .row:last-child{border:none}
2782
+ .timing .label{color:var(--dim)}
2783
+ .timing .val{color:var(--teal)}
2784
+ .empty{text-align:center;padding:60px 20px;color:var(--dim)}
2785
+ .empty h3{color:var(--teal);margin-bottom:12px;font-size:16px}
2786
+ .empty p{font-size:13px;max-width:400px;margin:0 auto;line-height:1.6}
2787
+ .empty code{background:var(--bg);padding:2px 6px;border-radius:4px;font-size:12px;color:var(--gold)}
2788
+ </style>
2789
+ </head>
2790
+ <body>
2791
+ <div class="header">
2792
+ <h1>Arcanea Swarm Viz</h1>
2793
+ <span class="version">v${VERSION}</span>
2794
+ <div class="status">
2795
+ <span class="dot" id="statusDot"></span>
2796
+ <span id="statusText" style="font-size:12px;color:var(--dim)">Connecting...</span>
2797
+ </div>
2798
+ </div>
2799
+ <div class="stats">
2800
+ <div class="stat"><div class="label">Total Spawns</div><div class="value" id="statTotal">0</div></div>
2801
+ <div class="stat"><div class="label">Active Now</div><div class="value gold" id="statActive">0</div></div>
2802
+ <div class="stat"><div class="label">Success Rate</div><div class="value blue" id="statSuccess">-</div></div>
2803
+ <div class="stat"><div class="label">Avg Duration</div><div class="value" id="statAvg">-</div></div>
2804
+ </div>
2805
+ <div class="main">
2806
+ <div class="events">
2807
+ <div class="title">Live Event Feed <span class="count" id="eventCount">(0 events)</span></div>
2808
+ <div class="event-list" id="eventList"></div>
2809
+ </div>
2810
+ <div class="sidebar">
2811
+ <div class="panel"><div class="title">Team Utilization</div><div id="teamBars"></div></div>
2812
+ <div class="panel">
2813
+ <div class="title">Timing (ms)</div>
2814
+ <div class="timing">
2815
+ <div class="row"><span class="label">Avg</span><span class="val" id="timAvg">-</span></div>
2816
+ <div class="row"><span class="label">P50</span><span class="val" id="timP50">-</span></div>
2817
+ <div class="row"><span class="label">P95</span><span class="val" id="timP95">-</span></div>
2818
+ </div>
2819
+ </div>
2820
+ <div class="panel"><div class="title">Top Agents</div><div id="agentList" style="font-size:12px"></div></div>
2821
+ </div>
2822
+ </div>
2823
+ <script>
2824
+ // Uses safe DOM methods (createElement, textContent) — no innerHTML with untrusted data
2825
+ let allEvents = [];
2826
+ const fillClasses = {creative:'fill-creative',coding:'fill-coding',writing:'fill-writing',research:'fill-research',production:'fill-production',development:'fill-development',teacher:'fill-teacher',visionary:'fill-visionary'};
2827
+
2828
+ function fmtTime(ts) {
2829
+ return new Date(ts).toLocaleTimeString('en-US',{hour12:false,hour:'2-digit',minute:'2-digit',second:'2-digit'});
2830
+ }
2831
+ function fmtDur(ms) {
2832
+ if (!ms) return '';
2833
+ return ms < 1000 ? ms+'ms' : (ms/1000).toFixed(1)+'s';
2834
+ }
2835
+
2836
+ function mkEl(tag, cls, text) {
2837
+ const el = document.createElement(tag);
2838
+ if (cls) el.className = cls;
2839
+ if (text) el.textContent = text;
2840
+ return el;
2841
+ }
2842
+
2843
+ function showEmpty() {
2844
+ const list = document.getElementById('eventList');
2845
+ list.textContent = '';
2846
+ const d = mkEl('div','empty');
2847
+ const h = mkEl('h3',null,'Waiting for agent activity...');
2848
+ const p = mkEl('p',null,'Events appear here as agents spawn and complete. Use ultraworld or ultracode in Claude Code.');
2849
+ d.appendChild(h); d.appendChild(p);
2850
+ list.appendChild(d);
2851
+ }
2852
+
2853
+ function addEvent(event) {
2854
+ const list = document.getElementById('eventList');
2855
+ const empty = list.querySelector('.empty');
2856
+ if (empty) empty.remove();
2857
+
2858
+ const el = mkEl('div','event');
2859
+ el.appendChild(mkEl('span','time',fmtTime(event.timestamp)));
2860
+
2861
+ const badgeCls = event.type==='agent-spawn'?'badge badge-spawn':
2862
+ event.type==='agent-complete'?'badge badge-complete':
2863
+ event.type==='agent-error'?'badge badge-error':'badge badge-magic';
2864
+ const badgeTxt = event.type==='agent-spawn'?'SPAWN':
2865
+ event.type==='agent-complete'?'DONE':
2866
+ event.type==='agent-error'?'ERR':'MAGIC';
2867
+ el.appendChild(mkEl('span',badgeCls,badgeTxt));
2868
+ if (event.agent) el.appendChild(mkEl('span','agent-name',event.agent));
2869
+ if (event.description) el.appendChild(mkEl('span','desc',event.description));
2870
+ if (event.durationMs) el.appendChild(mkEl('span','dur',fmtDur(event.durationMs)));
2871
+
2872
+ list.appendChild(el);
2873
+ list.scrollTop = list.scrollHeight;
2874
+ }
2875
+
2876
+ function updateStats() {
2877
+ const spawns = allEvents.filter(e=>e.type==='agent-spawn');
2878
+ const completes = allEvents.filter(e=>e.type==='agent-complete');
2879
+ const errors = allEvents.filter(e=>e.type==='agent-error');
2880
+ const durs = completes.filter(e=>e.durationMs).map(e=>e.durationMs).sort((a,b)=>a-b);
2881
+
2882
+ document.getElementById('statTotal').textContent = spawns.length;
2883
+ document.getElementById('statActive').textContent = Math.max(0,spawns.length-completes.length-errors.length);
2884
+ document.getElementById('statSuccess').textContent = spawns.length>0?((completes.length/spawns.length)*100).toFixed(0)+'%':'-';
2885
+ document.getElementById('statAvg').textContent = durs.length>0?fmtDur(Math.round(durs.reduce((a,b)=>a+b,0)/durs.length)):'-';
2886
+ document.getElementById('timAvg').textContent = durs.length>0?Math.round(durs.reduce((a,b)=>a+b,0)/durs.length):'-';
2887
+ document.getElementById('timP50').textContent = durs.length>0?durs[Math.floor(durs.length*0.5)]:'-';
2888
+ document.getElementById('timP95').textContent = durs.length>0?durs[Math.floor(durs.length*0.95)]:'-';
2889
+ document.getElementById('eventCount').textContent = '('+allEvents.length+' events)';
2890
+
2891
+ // Team bars — built with safe DOM methods
2892
+ const teams = {};
2893
+ const total = (spawns.length+completes.length)||1;
2894
+ for (const e of [...spawns,...completes]) if(e.team) teams[e.team]=(teams[e.team]||0)+1;
2895
+ const barsEl = document.getElementById('teamBars');
2896
+ barsEl.textContent = '';
2897
+ for (const [team,count] of Object.entries(teams).sort((a,b)=>b[1]-a[1])) {
2898
+ const pct = ((count/total)*100).toFixed(0);
2899
+ const row = mkEl('div','bar-row');
2900
+ row.appendChild(mkEl('span','bar-label',team));
2901
+ const track = mkEl('div','bar-track');
2902
+ const fill = mkEl('div','bar-fill '+(fillClasses[team]||'fill-default'));
2903
+ fill.style.width = pct+'%';
2904
+ track.appendChild(fill);
2905
+ row.appendChild(track);
2906
+ row.appendChild(mkEl('span','bar-value',String(count)));
2907
+ barsEl.appendChild(row);
2908
+ }
2909
+
2910
+ // Agent list
2911
+ const agents = {};
2912
+ for (const e of [...spawns,...completes]) if(e.agent) agents[e.agent]=(agents[e.agent]||0)+1;
2913
+ const agentEl = document.getElementById('agentList');
2914
+ agentEl.textContent = '';
2915
+ for (const [agent,count] of Object.entries(agents).sort((a,b)=>b[1]-a[1]).slice(0,8)) {
2916
+ const row = mkEl('div','bar-row');
2917
+ row.appendChild(mkEl('span','bar-label',agent));
2918
+ const val = mkEl('span','bar-value',String(count));
2919
+ val.style.color = 'var(--teal)';
2920
+ row.appendChild(val);
2921
+ agentEl.appendChild(row);
2922
+ }
2923
+ }
2924
+
2925
+ function connect() {
2926
+ const es = new EventSource('/stream');
2927
+ es.onmessage = function(e) {
2928
+ const data = JSON.parse(e.data);
2929
+ if (data.type==='initial') {
2930
+ allEvents = data.events||[];
2931
+ document.getElementById('eventList').textContent = '';
2932
+ if (allEvents.length===0) showEmpty();
2933
+ else for (const ev of allEvents.slice(-100)) addEvent(ev);
2934
+ updateStats();
2935
+ } else {
2936
+ allEvents.push(data);
2937
+ addEvent(data);
2938
+ updateStats();
2939
+ }
2940
+ };
2941
+ es.onopen = function() {
2942
+ document.getElementById('statusDot').style.background='var(--green)';
2943
+ document.getElementById('statusText').textContent='Connected';
2944
+ };
2945
+ es.onerror = function() {
2946
+ document.getElementById('statusDot').style.background='var(--red)';
2947
+ document.getElementById('statusText').textContent='Reconnecting...';
2948
+ es.close();
2949
+ setTimeout(connect,3000);
2950
+ };
2951
+ }
2952
+ connect();
2953
+ </script>
2954
+ </body>
2955
+ </html>`;
2956
+ }
2957
+ function startVizServer(port = 3737) {
2958
+ mkdirSync2(ARCANEA_DIR, { recursive: true });
2959
+ let lastSize = 0;
2960
+ try {
2961
+ lastSize = existsSync2(EVENTS_FILE) ? statSync(EVENTS_FILE).size : 0;
2962
+ } catch {}
2963
+ const server = createServer((req, res) => {
2964
+ if (req.url === "/stream") {
2965
+ handleSSE(req, res);
2966
+ } else if (req.url === "/api/events") {
2967
+ handleAPI(req, res);
2968
+ } else if (req.url === "/api/test-event" && req.method === "POST") {
2969
+ let body = "";
2970
+ req.on("data", (chunk) => {
2971
+ body += chunk.toString();
2972
+ });
2973
+ req.on("end", () => {
2974
+ try {
2975
+ const event = JSON.parse(body);
2976
+ event.timestamp = event.timestamp || Date.now();
2977
+ logEvent(event);
2978
+ res.writeHead(200, { "Content-Type": "application/json" });
2979
+ res.end(JSON.stringify({ ok: true }));
2980
+ } catch {
2981
+ res.writeHead(400);
2982
+ res.end("Invalid JSON");
2983
+ }
2984
+ });
2985
+ } else {
2986
+ res.writeHead(200, { "Content-Type": "text/html" });
2987
+ res.end(getDashboardHTML());
2988
+ }
2989
+ });
2990
+ const pollInterval = setInterval(() => {
2991
+ try {
2992
+ if (!existsSync2(EVENTS_FILE))
2993
+ return;
2994
+ const currentSize = statSync(EVENTS_FILE).size;
2995
+ if (currentSize > lastSize) {
2996
+ const content = readFileSync2(EVENTS_FILE, "utf-8");
2997
+ const newContent = content.slice(lastSize);
2998
+ lastSize = currentSize;
2999
+ for (const line of newContent.trim().split(`
3000
+ `)) {
3001
+ if (!line)
3002
+ continue;
3003
+ try {
3004
+ broadcast(JSON.parse(line));
3005
+ } catch {}
3006
+ }
3007
+ }
3008
+ } catch {}
3009
+ }, 500);
3010
+ server.on("close", () => clearInterval(pollInterval));
3011
+ server.listen(port, () => {
3012
+ console.log(import_picocolors2.default.cyan(`
3013
+ Arcanea Swarm Viz v${VERSION}`));
3014
+ console.log(import_picocolors2.default.green(`Dashboard: http://localhost:${port}`));
3015
+ console.log(import_picocolors2.default.dim(`Events log: ${EVENTS_FILE}`));
3016
+ console.log(import_picocolors2.default.dim(`SSE stream: http://localhost:${port}/stream`));
3017
+ console.log(import_picocolors2.default.dim(`Press Ctrl+C to stop
3018
+ `));
3019
+ openBrowser(`http://localhost:${port}`);
3020
+ });
3021
+ }
3022
+
3023
+ // src/cli/index.ts
3024
+ import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
3025
+ import { join as join3 } from "path";
2651
3026
  function countMdFiles(dir) {
2652
3027
  let count = 0;
2653
3028
  for (const entry of readdirSync(dir)) {
2654
- const full = join2(dir, entry);
3029
+ const full = join3(dir, entry);
2655
3030
  try {
2656
- if (statSync(full).isDirectory()) {
3031
+ if (statSync2(full).isDirectory()) {
2657
3032
  count += countMdFiles(full);
2658
3033
  } else if (entry.endsWith(".md")) {
2659
3034
  count++;
@@ -2686,90 +3061,90 @@ program2.command("install").description("Initialize Arcanea in current project")
2686
3061
  });
2687
3062
  });
2688
3063
  program2.command("detect").description("Detect available AI coding platforms").action(() => {
2689
- console.log(import_picocolors2.default.cyan(`
3064
+ console.log(import_picocolors3.default.cyan(`
2690
3065
  ${ORCHESTRATOR} Platform Detection
2691
3066
  `));
2692
3067
  const platforms = detectPlatforms();
2693
3068
  if (platforms.length === 0) {
2694
- console.log(import_picocolors2.default.yellow("No platforms detected. Will install for Claude Code and OpenCode by default."));
3069
+ console.log(import_picocolors3.default.yellow("No platforms detected. Will install for Claude Code and OpenCode by default."));
2695
3070
  } else {
2696
- console.log(import_picocolors2.default.bold("Detected platforms:"));
3071
+ console.log(import_picocolors3.default.bold("Detected platforms:"));
2697
3072
  for (const platform of platforms) {
2698
- console.log(import_picocolors2.default.green(` ✓ ${platform}`));
3073
+ console.log(import_picocolors3.default.green(` ✓ ${platform}`));
2699
3074
  }
2700
3075
  }
2701
3076
  console.log();
2702
3077
  });
2703
3078
  program2.command("agents").description("List available agent teams").option("-t, --team <team>", "Show specific team details").action((options) => {
2704
- console.log(import_picocolors2.default.cyan(`
3079
+ console.log(import_picocolors3.default.cyan(`
2705
3080
  ${ORCHESTRATOR}'s Agent Teams
2706
3081
  `));
2707
3082
  if (options.team) {
2708
3083
  const team = AGENT_TEAMS[options.team];
2709
3084
  if (team) {
2710
- console.log(import_picocolors2.default.bold(team.name));
2711
- console.log(import_picocolors2.default.dim(team.description));
3085
+ console.log(import_picocolors3.default.bold(team.name));
3086
+ console.log(import_picocolors3.default.dim(team.description));
2712
3087
  console.log();
2713
3088
  console.log(" Agents:", team.agents.join(", "));
2714
3089
  } else {
2715
- console.log(import_picocolors2.default.red(`Unknown team: ${options.team}`));
3090
+ console.log(import_picocolors3.default.red(`Unknown team: ${options.team}`));
2716
3091
  console.log("Available teams:", Object.keys(AGENT_TEAMS).join(", "));
2717
3092
  }
2718
3093
  return;
2719
3094
  }
2720
3095
  for (const [key, team] of Object.entries(AGENT_TEAMS)) {
2721
3096
  const colors = {
2722
- creative: import_picocolors2.default.blue,
2723
- writing: import_picocolors2.default.green,
2724
- production: import_picocolors2.default.magenta,
2725
- research: import_picocolors2.default.yellow,
2726
- development: import_picocolors2.default.cyan,
2727
- teacher: import_picocolors2.default.dim,
2728
- visionary: import_picocolors2.default.dim
3097
+ creative: import_picocolors3.default.blue,
3098
+ writing: import_picocolors3.default.green,
3099
+ production: import_picocolors3.default.magenta,
3100
+ research: import_picocolors3.default.yellow,
3101
+ development: import_picocolors3.default.cyan,
3102
+ teacher: import_picocolors3.default.dim,
3103
+ visionary: import_picocolors3.default.dim
2729
3104
  };
2730
- const colorFn = colors[key] || import_picocolors2.default.white;
2731
- console.log(colorFn(import_picocolors2.default.bold(team.name + ":")));
3105
+ const colorFn = colors[key] || import_picocolors3.default.white;
3106
+ console.log(colorFn(import_picocolors3.default.bold(team.name + ":")));
2732
3107
  console.log(` ${team.agents.join(", ")}`);
2733
3108
  console.log();
2734
3109
  }
2735
3110
  });
2736
3111
  program2.command("luminors").description("Show the Seven Luminors").action(() => {
2737
- console.log(import_picocolors2.default.cyan(`
3112
+ console.log(import_picocolors3.default.cyan(`
2738
3113
  The Seven Luminors
2739
3114
  `));
2740
- console.log(import_picocolors2.default.dim(`Aspects of creative consciousness itself
3115
+ console.log(import_picocolors3.default.dim(`Aspects of creative consciousness itself
2741
3116
  `));
2742
3117
  for (const [_, luminor] of Object.entries(LUMINORS)) {
2743
- console.log(import_picocolors2.default.bold(import_picocolors2.default.yellow(`${luminor.name}`)) + ` - ${luminor.domain}`);
2744
- console.log(import_picocolors2.default.dim(` When: ${luminor.when}`));
3118
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.yellow(`${luminor.name}`)) + ` - ${luminor.domain}`);
3119
+ console.log(import_picocolors3.default.dim(` When: ${luminor.when}`));
2745
3120
  console.log();
2746
3121
  }
2747
- console.log(import_picocolors2.default.dim("Channel a Luminor: /luminor [name] [challenge]"));
3122
+ console.log(import_picocolors3.default.dim("Channel a Luminor: /luminor [name] [challenge]"));
2748
3123
  console.log();
2749
3124
  });
2750
3125
  program2.command("magic").description("Show magic words and their effects").action(() => {
2751
- console.log(import_picocolors2.default.cyan(`
3126
+ console.log(import_picocolors3.default.cyan(`
2752
3127
  Magic Words
2753
3128
  `));
2754
- console.log(import_picocolors2.default.bold("Creative Magic:"));
2755
- console.log(import_picocolors2.default.bold(import_picocolors2.default.cyan(" ultraworld")) + " (or ulw) — Fire ALL world-building agents in parallel");
2756
- console.log(import_picocolors2.default.bold(import_picocolors2.default.green(" ultrawrite")) + " (or ulwr) — Fire ALL writing/editing agents in parallel");
2757
- console.log(import_picocolors2.default.bold(import_picocolors2.default.magenta(" ultrabook")) + " (or ulb) — Complete book pipeline end-to-end");
3129
+ console.log(import_picocolors3.default.bold("Creative Magic:"));
3130
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.cyan(" ultraworld")) + " (or ulw) — Fire ALL world-building agents in parallel");
3131
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.green(" ultrawrite")) + " (or ulwr) — Fire ALL writing/editing agents in parallel");
3132
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.magenta(" ultrabook")) + " (or ulb) — Complete book pipeline end-to-end");
2758
3133
  console.log();
2759
- console.log(import_picocolors2.default.bold("Technical Magic:"));
2760
- console.log(import_picocolors2.default.bold(import_picocolors2.default.yellow(" ultracode")) + " (or ulc) — Fire ALL coding agents (architect + coder + reviewer)");
2761
- console.log(import_picocolors2.default.bold(import_picocolors2.default.cyan(" ultrawork")) + " (or ulwk) — Maximum parallel execution for ANY task");
3134
+ console.log(import_picocolors3.default.bold("Technical Magic:"));
3135
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.yellow(" ultracode")) + " (or ulc) — Fire ALL coding agents (architect + coder + reviewer)");
3136
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.cyan(" ultrawork")) + " (or ulwk) — Maximum parallel execution for ANY task");
2762
3137
  console.log();
2763
- console.log(import_picocolors2.default.bold("Prefix Triggers:"));
2764
- console.log(import_picocolors2.default.dim(" arcanea: [task]") + " — Invoke Arcanea's highest intelligence mode");
2765
- console.log(import_picocolors2.default.dim(" luminor: [task]") + " — Apply Luminor wisdom to the task");
3138
+ console.log(import_picocolors3.default.bold("Prefix Triggers:"));
3139
+ console.log(import_picocolors3.default.dim(" arcanea: [task]") + " — Invoke Arcanea's highest intelligence mode");
3140
+ console.log(import_picocolors3.default.dim(" luminor: [task]") + " — Apply Luminor wisdom to the task");
2766
3141
  console.log();
2767
- console.log(import_picocolors2.default.dim("Include any magic word in your prompt to activate!"));
3142
+ console.log(import_picocolors3.default.dim("Include any magic word in your prompt to activate!"));
2768
3143
  console.log();
2769
3144
  });
2770
3145
  program2.command("status").description("Check Arcanea installation status").action(() => {
2771
3146
  const cwd = process.cwd();
2772
- console.log(import_picocolors2.default.cyan(`
3147
+ console.log(import_picocolors3.default.cyan(`
2773
3148
  ${ORCHESTRATOR} Status
2774
3149
  `));
2775
3150
  const platformChecks = [
@@ -2779,32 +3154,32 @@ ${ORCHESTRATOR} Status
2779
3154
  { path: ".codex", name: "Codex" },
2780
3155
  { path: ".gemini", name: "Gemini CLI" }
2781
3156
  ];
2782
- console.log(import_picocolors2.default.bold("Platform installations:"));
3157
+ console.log(import_picocolors3.default.bold("Platform installations:"));
2783
3158
  for (const check of platformChecks) {
2784
- const agentsPath = join2(cwd, check.path, "agents");
2785
- const exists = existsSync2(agentsPath);
2786
- const status = exists ? import_picocolors2.default.green("✓") : import_picocolors2.default.dim("○");
3159
+ const agentsPath = join3(cwd, check.path, "agents");
3160
+ const exists = existsSync3(agentsPath);
3161
+ const status = exists ? import_picocolors3.default.green("✓") : import_picocolors3.default.dim("○");
2787
3162
  console.log(` ${status} ${check.name}`);
2788
3163
  }
2789
3164
  console.log();
2790
- console.log(import_picocolors2.default.bold("Configuration:"));
3165
+ console.log(import_picocolors3.default.bold("Configuration:"));
2791
3166
  const configChecks = [
2792
3167
  { path: "arcanea.json", name: "Arcanea config" },
2793
3168
  { path: ".mcp.json", name: "MCP config" }
2794
3169
  ];
2795
3170
  let allGood = true;
2796
3171
  for (const check of configChecks) {
2797
- const exists = existsSync2(join2(cwd, check.path));
2798
- const status = exists ? import_picocolors2.default.green("✓") : import_picocolors2.default.red("✗");
3172
+ const exists = existsSync3(join3(cwd, check.path));
3173
+ const status = exists ? import_picocolors3.default.green("✓") : import_picocolors3.default.red("✗");
2799
3174
  console.log(` ${status} ${check.name}`);
2800
3175
  if (!exists)
2801
3176
  allGood = false;
2802
3177
  }
2803
3178
  console.log();
2804
3179
  if (allGood) {
2805
- console.log(import_picocolors2.default.green("Arcanea is ready!"));
3180
+ console.log(import_picocolors3.default.green("Arcanea is ready!"));
2806
3181
  } else {
2807
- console.log(import_picocolors2.default.yellow("Run 'arcanea install' to complete setup."));
3182
+ console.log(import_picocolors3.default.yellow("Run 'arcanea install' to complete setup."));
2808
3183
  }
2809
3184
  console.log();
2810
3185
  });
@@ -2812,74 +3187,74 @@ program2.command("doctor").description("Diagnose Arcanea installation health").a
2812
3187
  const cwd = process.cwd();
2813
3188
  let issues = 0;
2814
3189
  let ok = 0;
2815
- console.log(import_picocolors2.default.cyan(`
3190
+ console.log(import_picocolors3.default.cyan(`
2816
3191
  ${ORCHESTRATOR} Doctor (v${VERSION})
2817
3192
  `));
2818
- console.log(import_picocolors2.default.bold(`Checking installation health...
3193
+ console.log(import_picocolors3.default.bold(`Checking installation health...
2819
3194
  `));
2820
3195
  const claudePaths = [
2821
- join2(cwd, ".claude", "CLAUDE.md"),
2822
- join2(cwd, ".opencode", "CLAUDE.md"),
2823
- join2(cwd, "CLAUDE.md")
3196
+ join3(cwd, ".claude", "CLAUDE.md"),
3197
+ join3(cwd, ".opencode", "CLAUDE.md"),
3198
+ join3(cwd, "CLAUDE.md")
2824
3199
  ];
2825
- const hasClaudeMd = claudePaths.some((p) => existsSync2(p));
3200
+ const hasClaudeMd = claudePaths.some((p) => existsSync3(p));
2826
3201
  if (hasClaudeMd) {
2827
- console.log(import_picocolors2.default.green(" ✓ CLAUDE.md found (Arcanea identity active)"));
3202
+ console.log(import_picocolors3.default.green(" ✓ CLAUDE.md found (Arcanea identity active)"));
2828
3203
  ok++;
2829
3204
  } else {
2830
- console.log(import_picocolors2.default.red(" ✗ No CLAUDE.md found — run 'arcanea install' to fix"));
3205
+ console.log(import_picocolors3.default.red(" ✗ No CLAUDE.md found — run 'arcanea install' to fix"));
2831
3206
  issues++;
2832
3207
  }
2833
3208
  const agentPaths = [".claude/agents", ".opencode/agents"];
2834
3209
  const hasAgents = agentPaths.some((p) => {
2835
- const full = join2(cwd, p);
2836
- return existsSync2(full) && readdirSync(full).length > 0;
3210
+ const full = join3(cwd, p);
3211
+ return existsSync3(full) && readdirSync(full).length > 0;
2837
3212
  });
2838
3213
  if (hasAgents) {
2839
- const agentDir = agentPaths.find((p) => existsSync2(join2(cwd, p)));
2840
- const count = countMdFiles(join2(cwd, agentDir));
2841
- console.log(import_picocolors2.default.green(` ✓ ${count} agent definitions installed`));
3214
+ const agentDir = agentPaths.find((p) => existsSync3(join3(cwd, p)));
3215
+ const count = countMdFiles(join3(cwd, agentDir));
3216
+ console.log(import_picocolors3.default.green(` ✓ ${count} agent definitions installed`));
2842
3217
  ok++;
2843
3218
  } else {
2844
- console.log(import_picocolors2.default.red(" ✗ No agents installed — run 'arcanea install --force'"));
3219
+ console.log(import_picocolors3.default.red(" ✗ No agents installed — run 'arcanea install --force'"));
2845
3220
  issues++;
2846
3221
  }
2847
3222
  const skillPaths = [".claude/skills", ".opencode/skills"];
2848
3223
  const hasSkills = skillPaths.some((p) => {
2849
- const full = join2(cwd, p);
2850
- return existsSync2(full) && readdirSync(full).length > 0;
3224
+ const full = join3(cwd, p);
3225
+ return existsSync3(full) && readdirSync(full).length > 0;
2851
3226
  });
2852
3227
  if (hasSkills) {
2853
- console.log(import_picocolors2.default.green(" ✓ Skills installed"));
3228
+ console.log(import_picocolors3.default.green(" ✓ Skills installed"));
2854
3229
  ok++;
2855
3230
  } else {
2856
- console.log(import_picocolors2.default.red(" ✗ No skills installed — run 'arcanea install --force'"));
3231
+ console.log(import_picocolors3.default.red(" ✗ No skills installed — run 'arcanea install --force'"));
2857
3232
  issues++;
2858
3233
  }
2859
- const mcpPath = join2(cwd, ".mcp.json");
2860
- if (existsSync2(mcpPath)) {
3234
+ const mcpPath = join3(cwd, ".mcp.json");
3235
+ if (existsSync3(mcpPath)) {
2861
3236
  try {
2862
- const mcp = JSON.parse(readFileSync2(mcpPath, "utf-8"));
3237
+ const mcp = JSON.parse(readFileSync3(mcpPath, "utf-8"));
2863
3238
  const servers = Object.keys(mcp.mcpServers || {});
2864
3239
  const hasArcanea = servers.includes("arcanea");
2865
- console.log(import_picocolors2.default.green(` ✓ MCP config: ${servers.length} servers configured`));
3240
+ console.log(import_picocolors3.default.green(` ✓ MCP config: ${servers.length} servers configured`));
2866
3241
  if (!hasArcanea) {
2867
- console.log(import_picocolors2.default.yellow(" ⚠ Arcanea MCP server not configured — run 'arcanea install --force'"));
3242
+ console.log(import_picocolors3.default.yellow(" ⚠ Arcanea MCP server not configured — run 'arcanea install --force'"));
2868
3243
  }
2869
3244
  ok++;
2870
3245
  } catch {
2871
- console.log(import_picocolors2.default.red(" ✗ .mcp.json is invalid JSON"));
3246
+ console.log(import_picocolors3.default.red(" ✗ .mcp.json is invalid JSON"));
2872
3247
  issues++;
2873
3248
  }
2874
3249
  } else {
2875
- console.log(import_picocolors2.default.red(" ✗ No .mcp.json — run 'arcanea install'"));
3250
+ console.log(import_picocolors3.default.red(" ✗ No .mcp.json — run 'arcanea install'"));
2876
3251
  issues++;
2877
3252
  }
2878
- if (existsSync2(join2(cwd, "arcanea.json"))) {
2879
- console.log(import_picocolors2.default.green(" ✓ arcanea.json config exists"));
3253
+ if (existsSync3(join3(cwd, "arcanea.json"))) {
3254
+ console.log(import_picocolors3.default.green(" ✓ arcanea.json config exists"));
2880
3255
  ok++;
2881
3256
  } else {
2882
- console.log(import_picocolors2.default.yellow(" ○ No arcanea.json (optional)"));
3257
+ console.log(import_picocolors3.default.yellow(" ○ No arcanea.json (optional)"));
2883
3258
  }
2884
3259
  const platformFiles = [
2885
3260
  { path: ".cursorrules", name: "Cursor (.cursorrules)" },
@@ -2887,19 +3262,22 @@ ${ORCHESTRATOR} Doctor (v${VERSION})
2887
3262
  { path: "GEMINI.md", name: "Gemini CLI (GEMINI.md)" }
2888
3263
  ];
2889
3264
  for (const pf of platformFiles) {
2890
- if (existsSync2(join2(cwd, pf.path))) {
2891
- console.log(import_picocolors2.default.green(` ✓ ${pf.name} configured`));
3265
+ if (existsSync3(join3(cwd, pf.path))) {
3266
+ console.log(import_picocolors3.default.green(` ✓ ${pf.name} configured`));
2892
3267
  ok++;
2893
3268
  }
2894
3269
  }
2895
3270
  console.log();
2896
3271
  if (issues === 0) {
2897
- console.log(import_picocolors2.default.green(import_picocolors2.default.bold(`Health: ${ok} checks passed, 0 issues`)));
2898
- console.log(import_picocolors2.default.green("Arcanea is fully operational!"));
3272
+ console.log(import_picocolors3.default.green(import_picocolors3.default.bold(`Health: ${ok} checks passed, 0 issues`)));
3273
+ console.log(import_picocolors3.default.green("Arcanea is fully operational!"));
2899
3274
  } else {
2900
- console.log(import_picocolors2.default.yellow(import_picocolors2.default.bold(`Health: ${ok} passed, ${issues} issues found`)));
2901
- console.log(import_picocolors2.default.dim("Run 'arcanea install --force' to fix issues."));
3275
+ console.log(import_picocolors3.default.yellow(import_picocolors3.default.bold(`Health: ${ok} passed, ${issues} issues found`)));
3276
+ console.log(import_picocolors3.default.dim("Run 'arcanea install --force' to fix issues."));
2902
3277
  }
2903
3278
  console.log();
2904
3279
  });
3280
+ program2.command("viz").description("Launch real-time swarm visualization dashboard").option("-p, --port <port>", "Server port", "3737").option("--no-open", "Don't auto-open browser").action((options) => {
3281
+ startVizServer(parseInt(options.port, 10));
3282
+ });
2905
3283
  program2.parse();
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "3.3.0";
1
+ export declare const VERSION = "3.4.0";
2
2
  export declare const NAME = "arcanea";
3
3
  export declare const ORCHESTRATOR = "Arcanea";
4
4
  export type Platform = "claude-code" | "opencode" | "codex" | "gemini" | "cursor" | "unknown";
package/dist/index.js CHANGED
@@ -208,6 +208,8 @@ async function installForPlatform(targetDir, packageRoot, platform, force) {
208
208
  async function installClaudeCodeSettings(platformPath, force) {
209
209
  const settingsPath = join(platformPath, "settings.json");
210
210
  if (!existsSync(settingsPath) || force) {
211
+ const eventsDir = join(process.env.HOME || process.env.USERPROFILE || "~", ".arcanea").replace(/\\/g, "/");
212
+ const logScript = `mkdir -p "${eventsDir}" && echo '{"type":"agent-spawn","agent":"'$(echo "$TOOL_INPUT" 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync(0,'utf8'));process.stdout.write((d.subagent_type||'unknown')+'","description":"'+(d.description||'').replace(/"/g,'')+'","team":"'+(d.subagent_type||''))}catch{process.stdout.write('unknown","description":"","team":"')}" 2>/dev/null)","timestamp":'$(date +%s000)'}' >> "${eventsDir}/swarm-events.jsonl"`;
211
213
  const settings = {
212
214
  hooks: {
213
215
  UserPromptSubmit: [
@@ -246,6 +248,15 @@ async function installClaudeCodeSettings(platformPath, force) {
246
248
  command: "echo '[ARCANEA_MODE=ultrawork] Maximum parallel execution. Spawn all relevant agents simultaneously using Task tool with run_in_background=true.'"
247
249
  }]
248
250
  }
251
+ ],
252
+ PreToolUse: [
253
+ {
254
+ matcher: "Task",
255
+ hooks: [{
256
+ type: "command",
257
+ command: logScript
258
+ }]
259
+ }
249
260
  ]
250
261
  }
251
262
  };
@@ -404,7 +415,7 @@ function printSuccessMessage(platforms) {
404
415
  }
405
416
 
406
417
  // src/index.ts
407
- var VERSION = "3.3.0";
418
+ var VERSION = "3.4.0";
408
419
  var NAME = "arcanea";
409
420
  var ORCHESTRATOR = "Arcanea";
410
421
  var defaultConfig = {
@@ -0,0 +1,13 @@
1
+ export interface SwarmEvent {
2
+ type: "agent-spawn" | "agent-complete" | "agent-error" | "magic-word" | "session-start";
3
+ agent?: string;
4
+ team?: string;
5
+ description?: string;
6
+ status?: "running" | "complete" | "error";
7
+ durationMs?: number;
8
+ timestamp: number;
9
+ meta?: Record<string, unknown>;
10
+ }
11
+ export declare function logEvent(event: SwarmEvent): void;
12
+ export declare function startVizServer(port?: number): void;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/viz/index.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,aAAa,GAAG,YAAY,GAAG,eAAe,CAAC;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAGhD;AA2RD,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAa,GAAG,IAAI,CA2DxD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcanea",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "Arcanea - The Creative Intelligence Platform. Skills, agents, and tools for AI-human co-creation.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",