@ekkos/cli 1.3.1 → 1.3.5
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/capture/jsonl-rewriter.d.ts +1 -1
- package/dist/capture/jsonl-rewriter.js +3 -3
- package/dist/capture/transcript-repair.d.ts +2 -2
- package/dist/capture/transcript-repair.js +2 -2
- package/dist/commands/claw.d.ts +13 -0
- package/dist/commands/claw.js +253 -0
- package/dist/commands/dashboard.js +742 -118
- package/dist/commands/doctor.d.ts +3 -3
- package/dist/commands/doctor.js +6 -79
- package/dist/commands/gemini.d.ts +19 -0
- package/dist/commands/gemini.js +193 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +56 -41
- package/dist/commands/run.d.ts +0 -1
- package/dist/commands/run.js +288 -263
- package/dist/commands/scan.d.ts +21 -0
- package/dist/commands/scan.js +386 -0
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.js +165 -27
- package/dist/commands/swarm-dashboard.js +156 -28
- package/dist/commands/swarm.d.ts +1 -1
- package/dist/commands/swarm.js +1 -1
- package/dist/commands/test-claude.d.ts +2 -2
- package/dist/commands/test-claude.js +3 -3
- package/dist/deploy/index.d.ts +0 -2
- package/dist/deploy/index.js +0 -2
- package/dist/deploy/settings.d.ts +6 -5
- package/dist/deploy/settings.js +64 -16
- package/dist/deploy/skills.js +1 -2
- package/dist/index.js +86 -96
- package/dist/lib/usage-parser.d.ts +1 -1
- package/dist/lib/usage-parser.js +9 -6
- package/dist/local/index.d.ts +14 -0
- package/dist/local/index.js +28 -0
- package/dist/local/local-embeddings.d.ts +49 -0
- package/dist/local/local-embeddings.js +232 -0
- package/dist/local/offline-fallback.d.ts +44 -0
- package/dist/local/offline-fallback.js +159 -0
- package/dist/local/sqlite-store.d.ts +126 -0
- package/dist/local/sqlite-store.js +393 -0
- package/dist/local/sync-engine.d.ts +42 -0
- package/dist/local/sync-engine.js +223 -0
- package/dist/utils/platform.d.ts +5 -1
- package/dist/utils/platform.js +24 -4
- package/dist/utils/proxy-url.d.ts +21 -0
- package/dist/utils/proxy-url.js +34 -0
- package/dist/utils/state.d.ts +1 -1
- package/dist/utils/state.js +11 -3
- package/dist/utils/templates.js +1 -1
- package/package.json +11 -4
- package/templates/CLAUDE.md +49 -107
- package/dist/agent/daemon.d.ts +0 -130
- package/dist/agent/daemon.js +0 -606
- package/dist/agent/health-check.d.ts +0 -35
- package/dist/agent/health-check.js +0 -243
- package/dist/agent/pty-runner.d.ts +0 -53
- package/dist/agent/pty-runner.js +0 -190
- package/dist/commands/agent.d.ts +0 -50
- package/dist/commands/agent.js +0 -544
- package/dist/commands/setup-remote.d.ts +0 -20
- package/dist/commands/setup-remote.js +0 -582
- package/dist/utils/verify-remote-terminal.d.ts +0 -10
- package/dist/utils/verify-remote-terminal.js +0 -415
- package/templates/README.md +0 -378
- package/templates/claude-plugins/PHASE2_COMPLETION.md +0 -346
- package/templates/claude-plugins/PLUGIN_PROPOSALS.md +0 -1776
- package/templates/claude-plugins/README.md +0 -587
- package/templates/claude-plugins/agents/code-reviewer.json +0 -14
- package/templates/claude-plugins/agents/debug-detective.json +0 -15
- package/templates/claude-plugins/agents/git-companion.json +0 -14
- package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/blog-manager/commands/blog.md +0 -691
- package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +0 -434
- package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +0 -282
- package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/memory-lens/commands/memory-search.md +0 -181
- package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/pattern-coach/commands/forge.md +0 -365
- package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +0 -582
- package/templates/claude-plugins-admin/AGENT_TEAM_PROPOSALS.md +0 -819
- package/templates/claude-plugins-admin/README.md +0 -446
- package/templates/claude-plugins-admin/autonomous-admin-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/autonomous-admin-agent/commands/agent.md +0 -595
- package/templates/claude-plugins-admin/backend-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/backend-agent/commands/backend.md +0 -798
- package/templates/claude-plugins-admin/deploy-guardian/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/deploy-guardian/commands/deploy.md +0 -554
- package/templates/claude-plugins-admin/frontend-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/frontend-agent/commands/frontend.md +0 -881
- package/templates/claude-plugins-admin/mcp-server-manager/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/mcp-server-manager/commands/mcp.md +0 -85
- package/templates/claude-plugins-admin/memory-system-monitor/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/memory-system-monitor/commands/memory-health.md +0 -569
- package/templates/claude-plugins-admin/qa-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/qa-agent/commands/qa.md +0 -863
- package/templates/claude-plugins-admin/tech-lead-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/tech-lead-agent/commands/lead.md +0 -732
- package/templates/commands/continue.md +0 -47
- package/templates/cursor-rules/ekkos-memory.md +0 -127
- package/templates/ekkos-manifest.json +0 -223
- package/templates/helpers/json-parse.cjs +0 -101
- package/templates/hooks-node/lib/state.js +0 -187
- package/templates/hooks-node/stop.js +0 -416
- package/templates/hooks-node/user-prompt-submit.js +0 -337
- package/templates/plan-template.md +0 -306
- package/templates/rules/00-hooks-contract.mdc +0 -89
- package/templates/rules/30-ekkos-core.mdc +0 -188
- package/templates/rules/31-ekkos-messages.mdc +0 -78
- package/templates/shared/hooks-enabled.json +0 -22
- package/templates/shared/session-words.json +0 -45
- package/templates/skills/ekkOS_Deep_Recall/Skill.md +0 -282
- package/templates/skills/ekkOS_Learn/Skill.md +0 -265
- package/templates/skills/ekkOS_Memory_First/Skill.md +0 -206
- package/templates/skills/ekkOS_Plan_Assist/Skill.md +0 -302
- package/templates/skills/ekkOS_Preferences/Skill.md +0 -247
- package/templates/skills/ekkOS_Reflect/Skill.md +0 -257
- package/templates/skills/ekkOS_Safety/Skill.md +0 -265
- package/templates/skills/ekkOS_Schema/Skill.md +0 -251
- package/templates/skills/ekkOS_Summary/Skill.md +0 -257
- package/templates/spec-template.md +0 -159
- package/templates/windsurf-rules/ekkos-memory.md +0 -127
- package/templates/windsurf-skills/README.md +0 -58
- package/templates/windsurf-skills/ekkos-continue/SKILL.md +0 -81
- package/templates/windsurf-skills/ekkos-golden-loop/SKILL.md +0 -225
- package/templates/windsurf-skills/ekkos-insights/SKILL.md +0 -138
- package/templates/windsurf-skills/ekkos-recall/SKILL.md +0 -96
- package/templates/windsurf-skills/ekkos-safety/SKILL.md +0 -89
- package/templates/windsurf-skills/ekkos-vault/SKILL.md +0 -86
|
@@ -63,11 +63,12 @@ const commander_1 = require("commander");
|
|
|
63
63
|
const state_js_1 = require("../utils/state.js");
|
|
64
64
|
// ── Pricing (per MTok) ──
|
|
65
65
|
const MODEL_PRICING = {
|
|
66
|
-
'claude-opus-4-6': { input:
|
|
67
|
-
'claude-opus-4-5-20250620': { input:
|
|
66
|
+
'claude-opus-4-6': { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.50 },
|
|
67
|
+
'claude-opus-4-5-20250620': { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.50 },
|
|
68
|
+
'claude-sonnet-4-6': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
68
69
|
'claude-sonnet-4-5-20250929': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
69
70
|
'claude-sonnet-4-5-20250514': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
70
|
-
'claude-haiku-4-5-20251001': { input:
|
|
71
|
+
'claude-haiku-4-5-20251001': { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.10 },
|
|
71
72
|
};
|
|
72
73
|
function getModelPricing(modelId) {
|
|
73
74
|
if (MODEL_PRICING[modelId])
|
|
@@ -332,11 +333,20 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
332
333
|
const USAGE_H = 4;
|
|
333
334
|
const FOOTER_H = 3;
|
|
334
335
|
const FIXED_H = HEADER_H + WORKERS_H + USAGE_H + FOOTER_H;
|
|
336
|
+
function resolveChartRatio(height) {
|
|
337
|
+
if (height >= 62)
|
|
338
|
+
return 0.22;
|
|
339
|
+
if (height >= 48)
|
|
340
|
+
return 0.25;
|
|
341
|
+
if (height >= 36)
|
|
342
|
+
return 0.28;
|
|
343
|
+
return 0.32;
|
|
344
|
+
}
|
|
335
345
|
function calcLayout() {
|
|
336
|
-
const H = Math.max(30, screen.height);
|
|
346
|
+
const H = Math.max(30, screen.height || 30);
|
|
337
347
|
const remaining = Math.max(10, H - FIXED_H);
|
|
338
|
-
const chartH = Math.max(CHART_H_MIN, Math.floor(remaining *
|
|
339
|
-
const tableH = Math.max(
|
|
348
|
+
const chartH = Math.max(CHART_H_MIN, Math.floor(remaining * resolveChartRatio(H)));
|
|
349
|
+
const tableH = Math.max(5, remaining - chartH);
|
|
340
350
|
return {
|
|
341
351
|
header: { top: 0, height: HEADER_H },
|
|
342
352
|
workers: { top: HEADER_H, height: WORKERS_H },
|
|
@@ -368,15 +378,20 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
368
378
|
border: { type: 'line' },
|
|
369
379
|
label: ' Workers ',
|
|
370
380
|
});
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
381
|
+
function createTokenChart(top, left, width, height) {
|
|
382
|
+
return contrib.line({
|
|
383
|
+
top, left, width, height,
|
|
384
|
+
label: ' Tokens/Turn (K) ',
|
|
385
|
+
showLegend: true,
|
|
386
|
+
legend: { width: 12 },
|
|
387
|
+
style: { line: 'green', text: 'white', baseline: 'white', border: { fg: 'yellow' } },
|
|
388
|
+
border: { type: 'line', fg: 'yellow' },
|
|
389
|
+
xLabelPadding: 0, xPadding: 1, wholeNumbersOnly: false,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
let tokenChart = createTokenChart(layout.chart.top, 0, W, layout.chart.height);
|
|
393
|
+
let chartLayoutW = 0;
|
|
394
|
+
let chartLayoutH = 0;
|
|
380
395
|
const turnBox = blessed.box({
|
|
381
396
|
top: layout.table.top, left: 0, width: W, height: layout.table.height,
|
|
382
397
|
content: '',
|
|
@@ -413,22 +428,77 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
413
428
|
screen.append(footerBox);
|
|
414
429
|
function applyLayout() {
|
|
415
430
|
layout = calcLayout();
|
|
431
|
+
const fullWidth = Math.max(24, screen.width || 80);
|
|
432
|
+
const H_PAD = 1;
|
|
433
|
+
const contentWidth = Math.max(20, fullWidth - (H_PAD * 2));
|
|
416
434
|
headerBox.top = layout.header.top;
|
|
435
|
+
headerBox.left = H_PAD;
|
|
436
|
+
headerBox.width = contentWidth;
|
|
417
437
|
headerBox.height = layout.header.height;
|
|
418
438
|
workersBox.top = layout.workers.top;
|
|
439
|
+
workersBox.left = H_PAD;
|
|
440
|
+
workersBox.width = contentWidth;
|
|
419
441
|
workersBox.height = layout.workers.height;
|
|
420
|
-
|
|
421
|
-
|
|
442
|
+
if (chartLayoutW !== contentWidth || chartLayoutH !== layout.chart.height) {
|
|
443
|
+
try {
|
|
444
|
+
screen.remove(tokenChart);
|
|
445
|
+
}
|
|
446
|
+
catch { }
|
|
447
|
+
try {
|
|
448
|
+
tokenChart.destroy?.();
|
|
449
|
+
}
|
|
450
|
+
catch { }
|
|
451
|
+
tokenChart = createTokenChart(layout.chart.top, H_PAD, contentWidth, layout.chart.height);
|
|
452
|
+
chartLayoutW = contentWidth;
|
|
453
|
+
chartLayoutH = layout.chart.height;
|
|
454
|
+
screen.append(tokenChart);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
tokenChart.top = layout.chart.top;
|
|
458
|
+
tokenChart.left = H_PAD;
|
|
459
|
+
tokenChart.width = contentWidth;
|
|
460
|
+
tokenChart.height = layout.chart.height;
|
|
461
|
+
}
|
|
422
462
|
turnBox.top = layout.table.top;
|
|
463
|
+
turnBox.left = H_PAD;
|
|
464
|
+
turnBox.width = contentWidth;
|
|
423
465
|
turnBox.height = layout.table.height;
|
|
424
466
|
windowBox.top = layout.usage.top;
|
|
467
|
+
windowBox.left = H_PAD;
|
|
468
|
+
windowBox.width = contentWidth;
|
|
425
469
|
windowBox.height = layout.usage.height;
|
|
426
470
|
footerBox.top = layout.footer.top;
|
|
471
|
+
footerBox.left = H_PAD;
|
|
472
|
+
footerBox.width = contentWidth;
|
|
427
473
|
footerBox.height = layout.footer.height;
|
|
474
|
+
if (lastChartSeries) {
|
|
475
|
+
try {
|
|
476
|
+
tokenChart.setData(lastChartSeries);
|
|
477
|
+
}
|
|
478
|
+
catch { }
|
|
479
|
+
}
|
|
428
480
|
}
|
|
429
481
|
// ── State ──
|
|
430
482
|
let lastWorkers = [];
|
|
483
|
+
let lastChartSeries = null;
|
|
431
484
|
let sparkleTimer;
|
|
485
|
+
let lastLayoutW = screen.width || 0;
|
|
486
|
+
let lastLayoutH = screen.height || 0;
|
|
487
|
+
function ensureLayoutSynced() {
|
|
488
|
+
const w = screen.width || 0;
|
|
489
|
+
const h = screen.height || 0;
|
|
490
|
+
if (w === lastLayoutW && h === lastLayoutH)
|
|
491
|
+
return;
|
|
492
|
+
lastLayoutW = w;
|
|
493
|
+
lastLayoutH = h;
|
|
494
|
+
try {
|
|
495
|
+
screen.realloc?.();
|
|
496
|
+
}
|
|
497
|
+
catch { }
|
|
498
|
+
applyLayout();
|
|
499
|
+
}
|
|
500
|
+
// Apply once so initial render uses the final, padded geometry.
|
|
501
|
+
applyLayout();
|
|
432
502
|
// ── Logo animation ──
|
|
433
503
|
function renderLogoWave() {
|
|
434
504
|
try {
|
|
@@ -446,11 +516,11 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
446
516
|
const rawLogoLen = 14; // " ekkOS_ Swarm " roughly
|
|
447
517
|
const infoStr = ` ${lastWorkers.length}W ${totalTurns}t $${totalCost.toFixed(2)} ${durStr} `;
|
|
448
518
|
const rawInfoLen = infoStr.length + 1;
|
|
449
|
-
const boxW =
|
|
519
|
+
const boxW = Math.max(10, headerBox.width - 2);
|
|
450
520
|
const pad = Math.max(1, boxW - rawLogoLen - rawInfoLen);
|
|
451
521
|
headerBox.setLabel(logoStr + '\u2500'.repeat(pad) + infoStr);
|
|
452
522
|
// Header content: task description
|
|
453
|
-
const maxW =
|
|
523
|
+
const maxW = Math.max(8, headerBox.width - 6);
|
|
454
524
|
const truncTask = taskStr.length > maxW ? taskStr.slice(0, maxW - 3) + '...' : taskStr;
|
|
455
525
|
headerBox.setContent(` {gray-fg}Task:{/gray-fg} ${truncTask}`);
|
|
456
526
|
waveOffset = (waveOffset + 1) % WAVE_COLORS.length;
|
|
@@ -471,7 +541,7 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
471
541
|
workersBox.setContent(' {gray-fg}No workers detected yet...{/gray-fg}');
|
|
472
542
|
return;
|
|
473
543
|
}
|
|
474
|
-
const boxW = Math.max(20,
|
|
544
|
+
const boxW = Math.max(20, workersBox.width - 2);
|
|
475
545
|
const WORKER_COLORS = ['magenta', 'blue', 'green', 'yellow', 'cyan', 'red', 'white', 'gray'];
|
|
476
546
|
const lines = [];
|
|
477
547
|
// Row 1: Worker names + context bars
|
|
@@ -510,8 +580,9 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
510
580
|
// ── Combined turn table ──
|
|
511
581
|
function renderTurnTable(workers) {
|
|
512
582
|
const WORKER_COLORS = ['magenta', 'blue', 'green', 'yellow', 'cyan', 'red', 'white', 'gray'];
|
|
513
|
-
const w = Math.max(
|
|
583
|
+
const w = Math.max(18, turnBox.width - 4);
|
|
514
584
|
const div = '{gray-fg}|{/gray-fg}';
|
|
585
|
+
const lastScrollPerc = turnBox.getScrollPerc();
|
|
515
586
|
// Columns: W(2) Turn(4) Model(7) Context(7) CacheRd(flex) CacheWr(flex) Out(flex) Cost(7)
|
|
516
587
|
const colW = 2;
|
|
517
588
|
const colNum = 4;
|
|
@@ -540,8 +611,7 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
540
611
|
}
|
|
541
612
|
// Sort by timestamp descending (newest first)
|
|
542
613
|
allTurns.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
543
|
-
const
|
|
544
|
-
const rows = allTurns.slice(0, visibleRows).map(t => {
|
|
614
|
+
const rows = allTurns.map(t => {
|
|
545
615
|
const wColor = WORKER_COLORS[(t.workerIndex - 1) % WORKER_COLORS.length];
|
|
546
616
|
const mTag = modelTag(t.routedModel);
|
|
547
617
|
const mColor = t.routedModel.includes('haiku') ? 'green' : t.routedModel.includes('sonnet') ? 'blue' : 'magenta';
|
|
@@ -557,6 +627,9 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
557
627
|
costFlag + rpad(`$${t.cost.toFixed(2)}`, colCost) + costEnd);
|
|
558
628
|
});
|
|
559
629
|
turnBox.setContent([header, separator, ...rows].join('\n'));
|
|
630
|
+
if (lastScrollPerc > 0) {
|
|
631
|
+
turnBox.setScrollPerc(lastScrollPerc);
|
|
632
|
+
}
|
|
560
633
|
}
|
|
561
634
|
// ── Combined chart ──
|
|
562
635
|
function renderChart(workers) {
|
|
@@ -576,16 +649,68 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
576
649
|
});
|
|
577
650
|
}
|
|
578
651
|
if (series.length > 0) {
|
|
652
|
+
lastChartSeries = series;
|
|
579
653
|
tokenChart.setData(series);
|
|
580
654
|
}
|
|
581
655
|
}
|
|
582
656
|
// ── Usage window (Anthropic OAuth) ──
|
|
657
|
+
function extractClaudeOauthAccessToken(rawBlob) {
|
|
658
|
+
const raw = (rawBlob || '').trim();
|
|
659
|
+
if (!raw)
|
|
660
|
+
return null;
|
|
661
|
+
const candidates = new Set([raw]);
|
|
662
|
+
if (/^[0-9a-fA-F]+$/.test(raw) && raw.length % 2 === 0) {
|
|
663
|
+
const decoded = Buffer.from(raw, 'hex').toString('utf8');
|
|
664
|
+
candidates.add(decoded);
|
|
665
|
+
candidates.add(decoded.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '').trim());
|
|
666
|
+
}
|
|
667
|
+
for (const candidate of candidates) {
|
|
668
|
+
if (!candidate)
|
|
669
|
+
continue;
|
|
670
|
+
try {
|
|
671
|
+
const parsed = JSON.parse(candidate);
|
|
672
|
+
const token = parsed?.claudeAiOauth?.accessToken;
|
|
673
|
+
if (typeof token === 'string' && token.length > 0)
|
|
674
|
+
return token;
|
|
675
|
+
}
|
|
676
|
+
catch { }
|
|
677
|
+
try {
|
|
678
|
+
const parsed = JSON.parse(`{${candidate}}`);
|
|
679
|
+
const token = parsed?.claudeAiOauth?.accessToken;
|
|
680
|
+
if (typeof token === 'string' && token.length > 0)
|
|
681
|
+
return token;
|
|
682
|
+
}
|
|
683
|
+
catch { }
|
|
684
|
+
const oauthMatch = candidate.match(/"claudeAiOauth"\s*:\s*(\{[\s\S]*?\})/);
|
|
685
|
+
if (oauthMatch) {
|
|
686
|
+
try {
|
|
687
|
+
const oauth = JSON.parse(oauthMatch[1]);
|
|
688
|
+
const token = oauth?.accessToken;
|
|
689
|
+
if (typeof token === 'string' && token.length > 0)
|
|
690
|
+
return token;
|
|
691
|
+
}
|
|
692
|
+
catch { }
|
|
693
|
+
const tokenMatch = oauthMatch[1].match(/"accessToken"\s*:\s*"([^"]+)"/);
|
|
694
|
+
if (tokenMatch?.[1])
|
|
695
|
+
return tokenMatch[1];
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
return null;
|
|
699
|
+
}
|
|
583
700
|
async function fetchAnthropicUsage() {
|
|
584
701
|
try {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
702
|
+
let token = null;
|
|
703
|
+
if (process.platform === 'darwin') {
|
|
704
|
+
const { execSync } = require('child_process');
|
|
705
|
+
const credsBlob = execSync('security find-generic-password -s "Claude Code-credentials" -w', { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
706
|
+
token = extractClaudeOauthAccessToken(credsBlob);
|
|
707
|
+
}
|
|
708
|
+
if (!token) {
|
|
709
|
+
const credsPath = path.join(os.homedir(), '.claude', '.credentials.json');
|
|
710
|
+
if (fs.existsSync(credsPath)) {
|
|
711
|
+
token = extractClaudeOauthAccessToken(fs.readFileSync(credsPath, 'utf-8'));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
589
714
|
if (!token)
|
|
590
715
|
return null;
|
|
591
716
|
const resp = await fetch('https://api.anthropic.com/api/oauth/usage', {
|
|
@@ -664,6 +789,7 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
664
789
|
// ── Main update loop ──
|
|
665
790
|
function updateDashboard() {
|
|
666
791
|
try {
|
|
792
|
+
ensureLayoutSynced();
|
|
667
793
|
const workers = discoverWorkers(launchTs);
|
|
668
794
|
lastWorkers = workers;
|
|
669
795
|
renderWorkerCards(workers);
|
|
@@ -691,7 +817,9 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
|
|
|
691
817
|
screen.on('resize', () => {
|
|
692
818
|
try {
|
|
693
819
|
screen.realloc?.();
|
|
694
|
-
|
|
820
|
+
lastLayoutW = 0;
|
|
821
|
+
lastLayoutH = 0;
|
|
822
|
+
ensureLayoutSynced();
|
|
695
823
|
updateDashboard();
|
|
696
824
|
}
|
|
697
825
|
catch { }
|
package/dist/commands/swarm.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface SwarmLaunchOptions {
|
|
|
32
32
|
* - Uses tmux WINDOWS (not panes) — compatible with Python Queen discovery
|
|
33
33
|
* - Window 0: Swarm Dashboard (blessed TUI showing all workers)
|
|
34
34
|
* - Windows 1-N: Workers running `ekkos run -b` (proxy + infinite context)
|
|
35
|
-
* - Each worker gets full ekkOS stack: proxy, hooks,
|
|
35
|
+
* - Each worker gets full ekkOS stack: proxy, hooks, context eviction
|
|
36
36
|
*
|
|
37
37
|
* Flow:
|
|
38
38
|
* 1. Decompose task via Gemini Flash (free, fast)
|
package/dist/commands/swarm.js
CHANGED
|
@@ -194,7 +194,7 @@ function findPythonPath(swarmDir) {
|
|
|
194
194
|
* - Uses tmux WINDOWS (not panes) — compatible with Python Queen discovery
|
|
195
195
|
* - Window 0: Swarm Dashboard (blessed TUI showing all workers)
|
|
196
196
|
* - Windows 1-N: Workers running `ekkos run -b` (proxy + infinite context)
|
|
197
|
-
* - Each worker gets full ekkOS stack: proxy, hooks,
|
|
197
|
+
* - Each worker gets full ekkOS stack: proxy, hooks, context eviction
|
|
198
198
|
*
|
|
199
199
|
* Flow:
|
|
200
200
|
* 1. Decompose task via Gemini Flash (free, fast)
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* ekkos test-claude — Bare proxy test (no CLI wrapper)
|
|
3
3
|
*
|
|
4
4
|
* Launches vanilla Claude Code with ONLY the proxy URL set.
|
|
5
|
-
* No
|
|
5
|
+
* No PTY wrapper, no injection, no context management.
|
|
6
6
|
*
|
|
7
7
|
* Purpose: Isolate whether fast context growth is caused by:
|
|
8
8
|
* A) The proxy (IPC, injections, tool compression)
|
|
9
|
-
* B) The ekkos CLI wrapper (
|
|
9
|
+
* B) The ekkos CLI wrapper (PTY, run.ts logic)
|
|
10
10
|
*/
|
|
11
11
|
export interface TestClaudeOptions {
|
|
12
12
|
noProxy?: boolean;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* ekkos test-claude — Bare proxy test (no CLI wrapper)
|
|
4
4
|
*
|
|
5
5
|
* Launches vanilla Claude Code with ONLY the proxy URL set.
|
|
6
|
-
* No
|
|
6
|
+
* No PTY wrapper, no injection, no context management.
|
|
7
7
|
*
|
|
8
8
|
* Purpose: Isolate whether fast context growth is caused by:
|
|
9
9
|
* A) The proxy (IPC, injections, tool compression)
|
|
10
|
-
* B) The ekkos CLI wrapper (
|
|
10
|
+
* B) The ekkos CLI wrapper (PTY, run.ts logic)
|
|
11
11
|
*/
|
|
12
12
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
13
|
if (k2 === undefined) k2 = k;
|
|
@@ -59,7 +59,7 @@ async function testClaude(options) {
|
|
|
59
59
|
console.log(chalk_1.default.cyan('\n ekkOS test-claude — Bare Proxy Test'));
|
|
60
60
|
console.log(chalk_1.default.gray(' ══════════════════════════════════'));
|
|
61
61
|
console.log(chalk_1.default.green(' Proxy: ') + (options.noProxy ? chalk_1.default.yellow('NO') : chalk_1.default.green('YES')));
|
|
62
|
-
console.log(chalk_1.default.green(' CLI: ') + chalk_1.default.yellow('NO (no
|
|
62
|
+
console.log(chalk_1.default.green(' CLI: ') + chalk_1.default.yellow('NO (no PTY, no inject)'));
|
|
63
63
|
console.log(chalk_1.default.green(' Hooks: ') + (options.noHooks ? chalk_1.default.yellow('NO (disabled)') : chalk_1.default.gray('YES (same .claude/hooks/)')));
|
|
64
64
|
console.log('');
|
|
65
65
|
// Resolve Claude path
|
package/dist/deploy/index.d.ts
CHANGED
package/dist/deploy/index.js
CHANGED
|
@@ -19,6 +19,4 @@ __exportStar(require("./mcp"), exports);
|
|
|
19
19
|
__exportStar(require("./settings"), exports);
|
|
20
20
|
__exportStar(require("./hooks"), exports);
|
|
21
21
|
__exportStar(require("./skills"), exports);
|
|
22
|
-
__exportStar(require("./agents"), exports);
|
|
23
|
-
__exportStar(require("./plugins"), exports);
|
|
24
22
|
__exportStar(require("./instructions"), exports);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Claude Code settings.json management for ekkOS.
|
|
3
|
+
* - Disables Claude's built-in auto-memory (ekkOS replaces it with 11-layer memory)
|
|
4
|
+
* - Registers ekkOS hooks in correct Claude Code format (PascalCase events, { type, command } objects)
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
* Deploy Claude Code settings.json —
|
|
8
|
-
*
|
|
7
|
+
* Deploy Claude Code settings.json — disables auto-memory and configures hooks.
|
|
8
|
+
* ekkOS provides its own memory system via MCP, so Claude's built-in auto-memory
|
|
9
|
+
* is redundant and wastes ~1K tokens/turn on duplicate context.
|
|
9
10
|
*/
|
|
10
11
|
export declare function deployClaudeSettings(): void;
|
|
11
12
|
/**
|
package/dist/deploy/settings.js
CHANGED
|
@@ -1,37 +1,85 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Claude Code settings.json management for ekkOS.
|
|
4
|
+
* - Disables Claude's built-in auto-memory (ekkOS replaces it with 11-layer memory)
|
|
5
|
+
* - Registers ekkOS hooks in correct Claude Code format (PascalCase events, { type, command } objects)
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.deployClaudeSettings = deployClaudeSettings;
|
|
9
9
|
exports.areHooksConfigured = areHooksConfigured;
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const os_1 = require("os");
|
|
11
13
|
const platform_1 = require("../utils/platform");
|
|
12
14
|
/**
|
|
13
|
-
* Deploy Claude Code settings.json —
|
|
14
|
-
*
|
|
15
|
+
* Deploy Claude Code settings.json — disables auto-memory and configures hooks.
|
|
16
|
+
* ekkOS provides its own memory system via MCP, so Claude's built-in auto-memory
|
|
17
|
+
* is redundant and wastes ~1K tokens/turn on duplicate context.
|
|
15
18
|
*/
|
|
16
19
|
function deployClaudeSettings() {
|
|
17
20
|
// Ensure .claude directory exists
|
|
18
21
|
if (!(0, fs_1.existsSync)(platform_1.CLAUDE_DIR)) {
|
|
19
22
|
(0, fs_1.mkdirSync)(platform_1.CLAUDE_DIR, { recursive: true });
|
|
20
23
|
}
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
+
let settings = {};
|
|
25
|
+
if ((0, fs_1.existsSync)(platform_1.CLAUDE_SETTINGS)) {
|
|
26
|
+
try {
|
|
27
|
+
settings = JSON.parse((0, fs_1.readFileSync)(platform_1.CLAUDE_SETTINGS, 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Invalid JSON — start fresh
|
|
31
|
+
settings = {};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
let changed = false;
|
|
35
|
+
// Disable Claude's built-in auto-memory — ekkOS replaces it
|
|
36
|
+
if (settings.autoMemoryEnabled !== false) {
|
|
37
|
+
settings.autoMemoryEnabled = false;
|
|
38
|
+
changed = true;
|
|
24
39
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
// Build correct hooks config pointing to ~/.claude/hooks/ scripts.
|
|
41
|
+
// Claude Code requires PascalCase event names and { type, command } objects.
|
|
42
|
+
const hooksDir = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'hooks');
|
|
43
|
+
const isWindows = process.platform === 'win32';
|
|
44
|
+
const ext = isWindows ? '.ps1' : '.sh';
|
|
45
|
+
const hookMapping = [
|
|
46
|
+
{ event: 'SessionStart', script: `session-start${ext}` },
|
|
47
|
+
{ event: 'UserPromptSubmit', script: `user-prompt-submit${ext}` },
|
|
48
|
+
{ event: 'Stop', script: `stop${ext}` },
|
|
49
|
+
];
|
|
50
|
+
// Only register hooks for scripts that actually exist on disk
|
|
51
|
+
const newHooks = {};
|
|
52
|
+
for (const { event, script } of hookMapping) {
|
|
53
|
+
const scriptPath = (0, path_1.join)(hooksDir, script);
|
|
54
|
+
if ((0, fs_1.existsSync)(scriptPath)) {
|
|
55
|
+
newHooks[event] = [
|
|
56
|
+
{
|
|
57
|
+
matcher: '',
|
|
58
|
+
hooks: [
|
|
59
|
+
{
|
|
60
|
+
type: 'command',
|
|
61
|
+
command: scriptPath,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
];
|
|
31
66
|
}
|
|
32
67
|
}
|
|
33
|
-
|
|
34
|
-
|
|
68
|
+
// Replace hooks if they differ from expected (fixes wrong format + adds missing)
|
|
69
|
+
const existingHooks = settings.hooks;
|
|
70
|
+
if (Object.keys(newHooks).length > 0) {
|
|
71
|
+
if (JSON.stringify(existingHooks) !== JSON.stringify(newHooks)) {
|
|
72
|
+
settings.hooks = newHooks;
|
|
73
|
+
changed = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (existingHooks) {
|
|
77
|
+
// No hook scripts on disk — remove stale hooks entry
|
|
78
|
+
delete settings.hooks;
|
|
79
|
+
changed = true;
|
|
80
|
+
}
|
|
81
|
+
if (changed) {
|
|
82
|
+
(0, fs_1.writeFileSync)(platform_1.CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
|
|
35
83
|
}
|
|
36
84
|
}
|
|
37
85
|
/**
|
package/dist/deploy/skills.js
CHANGED
|
@@ -39,8 +39,7 @@ function areSkillsDeployed() {
|
|
|
39
39
|
if (!(0, fs_1.existsSync)(platform_1.CLAUDE_SKILLS_DIR))
|
|
40
40
|
return false;
|
|
41
41
|
const deployed = (0, fs_1.readdirSync)(platform_1.CLAUDE_SKILLS_DIR);
|
|
42
|
-
|
|
43
|
-
return deployed.length >= 5;
|
|
42
|
+
return deployed.length >= 1;
|
|
44
43
|
}
|
|
45
44
|
/**
|
|
46
45
|
* Count deployed skills
|