@ekkos/cli 1.3.7 → 1.3.9
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/commands/dashboard.js +67 -11
- package/dist/commands/gemini.js +45 -18
- package/dist/commands/init.js +92 -21
- package/dist/commands/living-docs.d.ts +8 -0
- package/dist/commands/living-docs.js +66 -0
- package/dist/commands/run.d.ts +5 -0
- package/dist/commands/run.js +473 -15
- package/dist/commands/scan.d.ts +68 -0
- package/dist/commands/scan.js +318 -22
- package/dist/commands/setup.js +2 -6
- package/dist/deploy/index.d.ts +1 -0
- package/dist/deploy/index.js +1 -0
- package/dist/deploy/instructions.d.ts +10 -3
- package/dist/deploy/instructions.js +34 -7
- package/dist/index.js +170 -87
- package/dist/lib/usage-parser.js +18 -2
- package/dist/local/index.d.ts +4 -0
- package/dist/local/index.js +14 -1
- package/dist/local/language-config.d.ts +55 -0
- package/dist/local/language-config.js +729 -0
- package/dist/local/living-docs-manager.d.ts +59 -0
- package/dist/local/living-docs-manager.js +1084 -0
- package/dist/local/stack-detection.d.ts +21 -0
- package/dist/local/stack-detection.js +406 -0
- package/dist/utils/proxy-url.d.ts +6 -1
- package/dist/utils/proxy-url.js +16 -2
- package/package.json +31 -17
- package/templates/CLAUDE.md +89 -99
- package/templates/agents/prune.md +83 -0
- package/templates/agents/rewind.md +84 -0
- package/templates/agents/scout.md +102 -0
- package/templates/agents/trace.md +99 -0
- package/templates/commands/continue.md +47 -0
- package/LICENSE +0 -21
package/dist/index.js
CHANGED
|
@@ -38,24 +38,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
const commander_1 = require("commander");
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// The `run` command is the default (bare `ekkos`), so it stays eager.
|
|
42
|
+
// `dashboardCommand` is eager because `run --dashboard` spawns `ekkos dashboard` in tmux.
|
|
43
|
+
// All other command modules are loaded lazily inside .action() callbacks.
|
|
44
44
|
const run_1 = require("./commands/run");
|
|
45
|
-
const gemini_1 = require("./commands/gemini");
|
|
46
|
-
const test_claude_1 = require("./commands/test-claude");
|
|
47
|
-
const doctor_1 = require("./commands/doctor");
|
|
48
|
-
const stream_1 = require("./commands/stream");
|
|
49
|
-
const claw_1 = require("./commands/claw");
|
|
50
|
-
// DEPRECATED: Hooks removed in hookless architecture migration
|
|
51
|
-
// hooksInstall, hooksVerify, hooksStatus no longer called — `hooks` command prints a deprecation notice.
|
|
52
|
-
const state_1 = require("./utils/state");
|
|
53
|
-
const index_1 = require("./commands/usage/index");
|
|
54
45
|
const dashboard_1 = require("./commands/dashboard");
|
|
55
|
-
const swarm_1 = require("./commands/swarm");
|
|
56
|
-
const swarm_dashboard_1 = require("./commands/swarm-dashboard");
|
|
57
|
-
const swarm_setup_1 = require("./commands/swarm-setup");
|
|
58
|
-
const scan_1 = require("./commands/scan");
|
|
59
46
|
const chalk_1 = __importDefault(require("chalk"));
|
|
60
47
|
const fs = __importStar(require("fs"));
|
|
61
48
|
const path = __importStar(require("path"));
|
|
@@ -76,12 +63,16 @@ commander_1.program
|
|
|
76
63
|
.addHelpText('after', [
|
|
77
64
|
'',
|
|
78
65
|
chalk_1.default.cyan.bold('Examples:'),
|
|
79
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos')} ${chalk_1.default.gray('
|
|
80
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
81
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
82
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
83
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
84
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
66
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos')} ${chalk_1.default.gray('Launch Claude Code with ekkOS memory (default)')}`,
|
|
67
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos pulse')} ${chalk_1.default.gray('Launch ekkOS Pulse preset: bypass + selector + live dashboard')}`,
|
|
68
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos --model')} ${chalk_1.default.gray('Open Claude launch selector (model + context + resume)')}`,
|
|
69
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos gemini')} ${chalk_1.default.gray('Launch Gemini CLI with ekkOS memory')}`,
|
|
70
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos run --dashboard')} ${chalk_1.default.gray('Claude Code with live usage dashboard')}`,
|
|
71
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos init')} ${chalk_1.default.gray('First-time setup — authenticate + configure IDEs')}`,
|
|
72
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos docs watch')} ${chalk_1.default.gray('Keep ekkOS_CONTEXT.md files updated on disk')}`,
|
|
73
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos connect gemini')} ${chalk_1.default.gray('Store your Gemini API key in the cloud')}`,
|
|
74
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos swarm launch -t "task"')} ${chalk_1.default.gray('Parallel workers on a decomposed task')}`,
|
|
75
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos agent create --path ./repo')} ${chalk_1.default.gray('Spawn a headless remote agent')}`,
|
|
85
76
|
'',
|
|
86
77
|
chalk_1.default.gray(' Run ') + chalk_1.default.white('ekkos <command> --help') + chalk_1.default.gray(' for detailed options on any command.'),
|
|
87
78
|
'',
|
|
@@ -146,51 +137,53 @@ commander_1.program
|
|
|
146
137
|
}
|
|
147
138
|
const groups = [
|
|
148
139
|
{
|
|
149
|
-
title: '
|
|
150
|
-
icon: '
|
|
140
|
+
title: 'Launch',
|
|
141
|
+
icon: '🚀',
|
|
151
142
|
commands: [
|
|
152
|
-
{ name: '
|
|
153
|
-
{ name: '
|
|
154
|
-
{ name: '
|
|
155
|
-
{ name: '
|
|
143
|
+
{ name: 'run', desc: 'Claude Code with memory, proxy, and mobile sync', note: 'default' },
|
|
144
|
+
{ name: 'pulse', desc: 'Pulse preset: bypass + guided selector + live dashboard' },
|
|
145
|
+
{ name: 'gemini', desc: 'Gemini CLI with memory and proxy' },
|
|
146
|
+
{ name: 'codex', desc: 'Codex (OpenAI) with mobile sync' },
|
|
147
|
+
{ name: 'acp', desc: 'Any ACP-compatible agent' },
|
|
156
148
|
],
|
|
157
149
|
},
|
|
158
150
|
{
|
|
159
|
-
title: '
|
|
160
|
-
icon: '
|
|
151
|
+
title: 'Setup',
|
|
152
|
+
icon: '⚙️',
|
|
161
153
|
commands: [
|
|
162
|
-
{ name: '
|
|
163
|
-
{ name: '
|
|
164
|
-
{ name: '
|
|
165
|
-
{ name: '
|
|
154
|
+
{ name: 'init', desc: 'Authenticate and configure IDEs' },
|
|
155
|
+
{ name: 'scan', desc: 'Discover repo structure and seed system registry' },
|
|
156
|
+
{ name: 'docs', desc: 'Watch and regenerate ekkOS_CONTEXT.md files' },
|
|
157
|
+
{ name: 'connect', desc: 'Store AI vendor API keys in the cloud' },
|
|
166
158
|
],
|
|
167
159
|
},
|
|
168
160
|
{
|
|
169
|
-
title: '
|
|
170
|
-
icon: '
|
|
161
|
+
title: 'Agents & Swarm',
|
|
162
|
+
icon: '🐝',
|
|
171
163
|
commands: [
|
|
172
|
-
{ name: '
|
|
173
|
-
{ name: '
|
|
174
|
-
{ name: 'sandbox', desc: '
|
|
175
|
-
{ name: 'notify', desc: 'Send push notifications to your Synk mobile app' },
|
|
164
|
+
{ name: 'agent', desc: 'Manage headless agents (create, list, stop)' },
|
|
165
|
+
{ name: 'swarm', desc: 'Parallel workers with Q-learning routing' },
|
|
166
|
+
{ name: 'sandbox', desc: 'OS-level sandboxing for agent execution' },
|
|
176
167
|
],
|
|
177
168
|
},
|
|
178
169
|
{
|
|
179
|
-
title: '
|
|
180
|
-
icon: '
|
|
170
|
+
title: 'Monitor',
|
|
171
|
+
icon: '📊',
|
|
181
172
|
commands: [
|
|
182
|
-
{ name: '
|
|
183
|
-
{ name: '
|
|
173
|
+
{ name: 'status', desc: 'System status (Memory, Sync, Auth)' },
|
|
174
|
+
{ name: 'dashboard', desc: 'Live TUI dashboard for session monitoring' },
|
|
175
|
+
{ name: 'usage', desc: 'Token usage and cost tracking' },
|
|
176
|
+
{ name: 'sessions', desc: 'List active local CLI sessions' },
|
|
184
177
|
],
|
|
185
178
|
},
|
|
186
179
|
{
|
|
187
|
-
title: '
|
|
188
|
-
icon: '
|
|
180
|
+
title: 'Utilities',
|
|
181
|
+
icon: '🔧',
|
|
189
182
|
commands: [
|
|
190
|
-
{ name: 'auth', desc: 'Manage authentication
|
|
191
|
-
{ name: '
|
|
192
|
-
{ name: '
|
|
193
|
-
{ name: '
|
|
183
|
+
{ name: 'auth', desc: 'Manage authentication tokens' },
|
|
184
|
+
{ name: 'daemon', desc: 'Background mobile sync service (start, stop)' },
|
|
185
|
+
{ name: 'notify', desc: 'Push notifications to Synk mobile app' },
|
|
186
|
+
{ name: 'doctor', desc: 'Check prerequisites and fix issues' },
|
|
194
187
|
],
|
|
195
188
|
},
|
|
196
189
|
];
|
|
@@ -232,7 +225,7 @@ commander_1.program
|
|
|
232
225
|
.option('-q, --quick', 'Quick setup: auto-detect IDE, use defaults, only prompt for API key if missing')
|
|
233
226
|
.option('--skip-hooks', '[DEPRECATED] Hooks are no longer deployed; this flag is a no-op')
|
|
234
227
|
.option('--skip-skills', 'Skip skills deployment')
|
|
235
|
-
.action(
|
|
228
|
+
.action(async (options) => { const { init } = await Promise.resolve().then(() => __importStar(require('./commands/init'))); await init(options); });
|
|
236
229
|
// Scan command — discover repo systems and seed registry
|
|
237
230
|
commander_1.program
|
|
238
231
|
.command('scan')
|
|
@@ -240,21 +233,45 @@ commander_1.program
|
|
|
240
233
|
.option('-c, --compile', 'Trigger a compile pass after seeding')
|
|
241
234
|
.option('-n, --dry-run', 'Show discovered systems without seeding')
|
|
242
235
|
.option('-p, --path <path>', 'Path to scan (default: current directory)')
|
|
243
|
-
.action((options) => {
|
|
244
|
-
(
|
|
236
|
+
.action(async (options) => {
|
|
237
|
+
const { scan } = await Promise.resolve().then(() => __importStar(require('./commands/scan')));
|
|
238
|
+
scan({
|
|
245
239
|
compile: options.compile,
|
|
246
240
|
dryRun: options.dryRun,
|
|
247
241
|
path: options.path,
|
|
248
242
|
});
|
|
249
243
|
});
|
|
244
|
+
// Local living docs command
|
|
245
|
+
const docsCmd = commander_1.program
|
|
246
|
+
.command('docs')
|
|
247
|
+
.description('Manage local ekkOS_CONTEXT.md living docs');
|
|
248
|
+
docsCmd
|
|
249
|
+
.command('watch')
|
|
250
|
+
.description('Watch the local workspace and keep ekkOS_CONTEXT.md files current on disk')
|
|
251
|
+
.option('-p, --path <path>', 'Path to watch (default: current directory)')
|
|
252
|
+
.option('--timezone <iana-tz>', 'IANA timezone for timestamps (default: local machine timezone)')
|
|
253
|
+
.option('--poll-interval-ms <ms>', 'Polling interval fallback in milliseconds', (value) => parseInt(value, 10))
|
|
254
|
+
.option('--debounce-ms <ms>', 'Debounce window before recompiling in milliseconds', (value) => parseInt(value, 10))
|
|
255
|
+
.option('--no-seed', 'Do not seed the platform registry while watching')
|
|
256
|
+
.action(async (options) => {
|
|
257
|
+
const { watchLivingDocs } = await Promise.resolve().then(() => __importStar(require('./commands/living-docs')));
|
|
258
|
+
watchLivingDocs({
|
|
259
|
+
path: options.path,
|
|
260
|
+
timeZone: options.timezone,
|
|
261
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
262
|
+
debounceMs: options.debounceMs,
|
|
263
|
+
noSeed: options.seed === false,
|
|
264
|
+
});
|
|
265
|
+
});
|
|
250
266
|
// Status command
|
|
251
267
|
commander_1.program
|
|
252
268
|
.command('status')
|
|
253
269
|
.description('Show live session metrics and memory status')
|
|
254
270
|
.option('-w, --watch', 'Watch mode — refresh session panel every 2s')
|
|
255
271
|
.option('--json', 'Output raw metrics JSON (no memory API call)')
|
|
256
|
-
.action((options) => {
|
|
257
|
-
|
|
272
|
+
.action(async (options) => {
|
|
273
|
+
const { status } = await Promise.resolve().then(() => __importStar(require('./commands/status')));
|
|
274
|
+
status({ watch: options.watch, json: options.json });
|
|
258
275
|
});
|
|
259
276
|
// OpenClaw integration commands
|
|
260
277
|
const clawCmd = commander_1.program
|
|
@@ -267,8 +284,9 @@ clawCmd
|
|
|
267
284
|
.option('--proxy-url <url>', 'Expected ekkOS proxy URL (default: https://proxy.ekkos.dev)')
|
|
268
285
|
.option('--model <model>', 'Expected primary OpenClaw model (default: ekkos-proxy/claude-sonnet-4-6)')
|
|
269
286
|
.option('--workspace <path>', 'Expected OpenClaw workspace path')
|
|
270
|
-
.action((options) => {
|
|
271
|
-
|
|
287
|
+
.action(async (options) => {
|
|
288
|
+
const { clawStatus } = await Promise.resolve().then(() => __importStar(require('./commands/claw')));
|
|
289
|
+
clawStatus({
|
|
272
290
|
json: options.json,
|
|
273
291
|
proxyUrl: options.proxyUrl,
|
|
274
292
|
model: options.model,
|
|
@@ -284,8 +302,9 @@ clawCmd
|
|
|
284
302
|
.option('--proxy-url <url>', 'Target ekkOS proxy URL')
|
|
285
303
|
.option('--model <model>', 'Target primary OpenClaw model')
|
|
286
304
|
.option('--workspace <path>', 'Expected OpenClaw workspace path for status verification')
|
|
287
|
-
.action((options) => {
|
|
288
|
-
|
|
305
|
+
.action(async (options) => {
|
|
306
|
+
const { clawUpgrade } = await Promise.resolve().then(() => __importStar(require('./commands/claw')));
|
|
307
|
+
clawUpgrade({
|
|
289
308
|
apply: options.apply,
|
|
290
309
|
force: options.force,
|
|
291
310
|
json: options.json,
|
|
@@ -298,7 +317,7 @@ clawCmd
|
|
|
298
317
|
commander_1.program
|
|
299
318
|
.command('test')
|
|
300
319
|
.description('Test connection to ekkOS memory')
|
|
301
|
-
.action(
|
|
320
|
+
.action(async () => { const { test } = await Promise.resolve().then(() => __importStar(require('./commands/test'))); await test(); });
|
|
302
321
|
// Run command - launches Claude Code with ekkOS proxy
|
|
303
322
|
commander_1.program
|
|
304
323
|
.command('run')
|
|
@@ -312,6 +331,10 @@ commander_1.program
|
|
|
312
331
|
.option('--skip-proxy', 'Skip API proxy (use direct Anthropic API, disables seamless context eviction)')
|
|
313
332
|
.option('--dashboard', 'Launch with live usage dashboard in an isolated 60/40 tmux split (requires tmux)')
|
|
314
333
|
.option('--add-dir <dirs...>', 'Additional directories Claude Code can access (outside working directory)')
|
|
334
|
+
.option('--model [model]', 'Claude launch model. Pass without a value to open the launch selector')
|
|
335
|
+
.option('--context-window <mode>', 'Context window mode: auto, 200k, or 1m')
|
|
336
|
+
.option('--continue-last', 'Continue the most recent Claude conversation')
|
|
337
|
+
.option('--resume-session <id>', 'Resume a Claude conversation by session ID')
|
|
315
338
|
.action((options) => {
|
|
316
339
|
(0, run_1.run)({
|
|
317
340
|
session: options.session,
|
|
@@ -323,6 +346,43 @@ commander_1.program
|
|
|
323
346
|
noProxy: options.skipProxy,
|
|
324
347
|
dashboard: options.dashboard,
|
|
325
348
|
addDirs: options.addDir,
|
|
349
|
+
model: options.model,
|
|
350
|
+
contextWindow: options.contextWindow,
|
|
351
|
+
continueLast: options.continueLast,
|
|
352
|
+
resumeSession: options.resumeSession,
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
commander_1.program
|
|
356
|
+
.command('pulse')
|
|
357
|
+
.description('Launch ekkOS Pulse: bypass + selector + live Claude dashboard')
|
|
358
|
+
.option('-s, --session <name>', 'Session name to restore on clear')
|
|
359
|
+
.option('--no-bypass', 'Disable bypass permissions mode')
|
|
360
|
+
.option('-v, --verbose', 'Show debug output')
|
|
361
|
+
.option('-d, --doctor', 'Run diagnostics before starting')
|
|
362
|
+
.option('-r, --research', 'Auto-run research agent on startup (scans arXiv for new AI papers)')
|
|
363
|
+
.option('--skip-inject', 'Monitor-only mode (detect context wall but print instructions instead of auto-inject)')
|
|
364
|
+
.option('--skip-proxy', 'Skip API proxy (use direct Anthropic API, disables seamless context eviction)')
|
|
365
|
+
.option('--add-dir <dirs...>', 'Additional directories Claude Code can access (outside working directory)')
|
|
366
|
+
.option('--model [model]', 'Claude launch model. Omit the value to open the launch selector (default for pulse)')
|
|
367
|
+
.option('--context-window <mode>', 'Context window mode: auto, 200k, or 1m')
|
|
368
|
+
.option('--continue-last', 'Continue the most recent Claude conversation')
|
|
369
|
+
.option('--resume-session <id>', 'Resume a Claude conversation by session ID')
|
|
370
|
+
.action((options) => {
|
|
371
|
+
(0, run_1.run)({
|
|
372
|
+
session: options.session,
|
|
373
|
+
bypass: options.bypass !== false,
|
|
374
|
+
pulse: true,
|
|
375
|
+
verbose: options.verbose,
|
|
376
|
+
doctor: options.doctor,
|
|
377
|
+
noInject: options.skipInject,
|
|
378
|
+
research: options.research,
|
|
379
|
+
noProxy: options.skipProxy,
|
|
380
|
+
dashboard: true,
|
|
381
|
+
addDirs: options.addDir,
|
|
382
|
+
model: options.model ?? true,
|
|
383
|
+
contextWindow: options.contextWindow,
|
|
384
|
+
continueLast: options.continueLast,
|
|
385
|
+
resumeSession: options.resumeSession,
|
|
326
386
|
});
|
|
327
387
|
});
|
|
328
388
|
// Gemini CLI — launch Gemini with ekkOS proxy
|
|
@@ -332,8 +392,9 @@ commander_1.program
|
|
|
332
392
|
.option('-s, --session <name>', 'Session name')
|
|
333
393
|
.option('-v, --verbose', 'Show debug output')
|
|
334
394
|
.option('--skip-proxy', 'Skip API proxy (use direct Gemini API)')
|
|
335
|
-
.action((options) => {
|
|
336
|
-
(
|
|
395
|
+
.action(async (options) => {
|
|
396
|
+
const { gemini } = await Promise.resolve().then(() => __importStar(require('./commands/gemini')));
|
|
397
|
+
gemini({
|
|
337
398
|
session: options.session,
|
|
338
399
|
verbose: options.verbose,
|
|
339
400
|
noProxy: options.skipProxy,
|
|
@@ -346,8 +407,9 @@ commander_1.program
|
|
|
346
407
|
.option('--no-proxy', 'Skip proxy too (completely vanilla Claude)')
|
|
347
408
|
.option('--no-hooks', 'Temporarily disable all hooks during test')
|
|
348
409
|
.option('-v, --verbose', 'Show debug output')
|
|
349
|
-
.action((options) => {
|
|
350
|
-
|
|
410
|
+
.action(async (options) => {
|
|
411
|
+
const { testClaude } = await Promise.resolve().then(() => __importStar(require('./commands/test-claude')));
|
|
412
|
+
testClaude({
|
|
351
413
|
noProxy: options.proxy === false,
|
|
352
414
|
noHooks: options.hooks === false,
|
|
353
415
|
verbose: options.verbose,
|
|
@@ -359,8 +421,9 @@ commander_1.program
|
|
|
359
421
|
.description('Check system prerequisites for ekkOS (Node, PTY, Claude, MCP)')
|
|
360
422
|
.option('-f, --fix', 'Attempt safe auto-fixes and show commands for manual fixes')
|
|
361
423
|
.option('-j, --json', 'Output machine-readable JSON report')
|
|
362
|
-
.action((options) => {
|
|
363
|
-
|
|
424
|
+
.action(async (options) => {
|
|
425
|
+
const { doctor } = await Promise.resolve().then(() => __importStar(require('./commands/doctor')));
|
|
426
|
+
doctor({ fix: options.fix, json: options.json });
|
|
364
427
|
});
|
|
365
428
|
// Stream command - stream capture status and management
|
|
366
429
|
const streamCmd = commander_1.program
|
|
@@ -372,8 +435,9 @@ streamCmd
|
|
|
372
435
|
.option('-s, --session <id>', 'Session ID to check')
|
|
373
436
|
.option('-w, --watch', 'Watch mode - refresh every second')
|
|
374
437
|
.option('-j, --json', 'Output machine-readable JSON')
|
|
375
|
-
.action((options) => {
|
|
376
|
-
|
|
438
|
+
.action(async (options) => {
|
|
439
|
+
const { streamStatus } = await Promise.resolve().then(() => __importStar(require('./commands/stream')));
|
|
440
|
+
streamStatus({
|
|
377
441
|
session: options.session,
|
|
378
442
|
watch: options.watch,
|
|
379
443
|
json: options.json
|
|
@@ -382,8 +446,9 @@ streamCmd
|
|
|
382
446
|
streamCmd
|
|
383
447
|
.command('list')
|
|
384
448
|
.description('List all sessions with stream data')
|
|
385
|
-
.action(() => {
|
|
386
|
-
|
|
449
|
+
.action(async () => {
|
|
450
|
+
const { streamList } = await Promise.resolve().then(() => __importStar(require('./commands/stream')));
|
|
451
|
+
streamList();
|
|
387
452
|
});
|
|
388
453
|
// DEPRECATED: Hooks removed in hookless architecture migration
|
|
389
454
|
// The `hooks` command prints a deprecation notice directing users to `ekkos run`.
|
|
@@ -400,17 +465,28 @@ commander_1.program
|
|
|
400
465
|
console.log(chalk_1.default.gray(' the ekkOS proxy — no shell hooks required.'));
|
|
401
466
|
console.log('');
|
|
402
467
|
});
|
|
403
|
-
// Usage command
|
|
404
|
-
|
|
405
|
-
|
|
468
|
+
// Usage command — lightweight stub, heavy handler loaded lazily
|
|
469
|
+
commander_1.program
|
|
470
|
+
.command('usage')
|
|
471
|
+
.description('Token usage and cost tracking (daily, weekly, monthly, session)')
|
|
472
|
+
.allowUnknownOption()
|
|
473
|
+
.action(async () => {
|
|
474
|
+
const { registerUsageCommand } = await Promise.resolve().then(() => __importStar(require('./commands/usage/index')));
|
|
475
|
+
const { Command } = await Promise.resolve().then(() => __importStar(require('commander')));
|
|
476
|
+
const usageProgram = new Command('ekkos');
|
|
477
|
+
registerUsageCommand(usageProgram);
|
|
478
|
+
usageProgram.parse(['node', 'ekkos', 'usage', ...process.argv.slice(3)]);
|
|
479
|
+
});
|
|
480
|
+
// Dashboard command — eager because `run --dashboard` spawns `ekkos dashboard` in tmux
|
|
406
481
|
commander_1.program.addCommand(dashboard_1.dashboardCommand);
|
|
407
482
|
// Sessions command - list active Claude Code sessions (swarm support)
|
|
408
483
|
commander_1.program
|
|
409
484
|
.command('sessions')
|
|
410
485
|
.description('List active Claude Code sessions (for swarm/multi-session support)')
|
|
411
486
|
.option('-j, --json', 'Output machine-readable JSON')
|
|
412
|
-
.action((options) => {
|
|
413
|
-
const
|
|
487
|
+
.action(async (options) => {
|
|
488
|
+
const { getActiveSessions } = await Promise.resolve().then(() => __importStar(require('./utils/state')));
|
|
489
|
+
const sessions = getActiveSessions();
|
|
414
490
|
if (options.json) {
|
|
415
491
|
console.log(JSON.stringify(sessions, null, 2));
|
|
416
492
|
return;
|
|
@@ -450,7 +526,8 @@ commander_1.program
|
|
|
450
526
|
console.log(chalk_1.default.gray('Running init with your options...'));
|
|
451
527
|
console.log('');
|
|
452
528
|
// Forward to init
|
|
453
|
-
await (
|
|
529
|
+
const { init } = await Promise.resolve().then(() => __importStar(require('./commands/init')));
|
|
530
|
+
await init({
|
|
454
531
|
ide: options.ide,
|
|
455
532
|
key: options.key
|
|
456
533
|
});
|
|
@@ -462,19 +539,19 @@ const swarmCmd = commander_1.program
|
|
|
462
539
|
swarmCmd
|
|
463
540
|
.command('status')
|
|
464
541
|
.description('Show Q-table stats (states, visits, epsilon, top actions)')
|
|
465
|
-
.action(
|
|
542
|
+
.action(async () => { const { swarmStatus } = await Promise.resolve().then(() => __importStar(require('./commands/swarm'))); swarmStatus(); });
|
|
466
543
|
swarmCmd
|
|
467
544
|
.command('reset')
|
|
468
545
|
.description('Clear Q-table from Redis (routing reverts to static rules)')
|
|
469
|
-
.action(
|
|
546
|
+
.action(async () => { const { swarmReset } = await Promise.resolve().then(() => __importStar(require('./commands/swarm'))); swarmReset(); });
|
|
470
547
|
swarmCmd
|
|
471
548
|
.command('export')
|
|
472
549
|
.description('Export Q-table to .swarm/q-learning-model.json')
|
|
473
|
-
.action(
|
|
550
|
+
.action(async () => { const { swarmExport } = await Promise.resolve().then(() => __importStar(require('./commands/swarm'))); swarmExport(); });
|
|
474
551
|
swarmCmd
|
|
475
552
|
.command('import')
|
|
476
553
|
.description('Import Q-table from .swarm/q-learning-model.json into Redis')
|
|
477
|
-
.action(
|
|
554
|
+
.action(async () => { const { swarmImport } = await Promise.resolve().then(() => __importStar(require('./commands/swarm'))); swarmImport(); });
|
|
478
555
|
swarmCmd
|
|
479
556
|
.command('launch')
|
|
480
557
|
.description('Launch parallel workers on a decomposed task (opens wizard if --task is omitted)')
|
|
@@ -485,13 +562,14 @@ swarmCmd
|
|
|
485
562
|
.option('--no-queen', 'Skip launching the Python Queen coordinator')
|
|
486
563
|
.option('--queen-strategy <strategy>', 'Queen strategy (adaptive-default, hierarchical-cascade, mesh-consensus)')
|
|
487
564
|
.option('-v, --verbose', 'Show debug output')
|
|
488
|
-
.action((options) => {
|
|
489
|
-
// Auto-open wizard when --task is missing
|
|
565
|
+
.action(async (options) => {
|
|
490
566
|
if (!options.task) {
|
|
491
|
-
|
|
567
|
+
const { swarmSetup } = await Promise.resolve().then(() => __importStar(require('./commands/swarm-setup')));
|
|
568
|
+
swarmSetup();
|
|
492
569
|
return;
|
|
493
570
|
}
|
|
494
|
-
|
|
571
|
+
const { swarmLaunch } = await Promise.resolve().then(() => __importStar(require('./commands/swarm')));
|
|
572
|
+
swarmLaunch({
|
|
495
573
|
workers: options.workers || 4,
|
|
496
574
|
task: options.task,
|
|
497
575
|
bypass: options.bypass !== false,
|
|
@@ -504,10 +582,15 @@ swarmCmd
|
|
|
504
582
|
swarmCmd
|
|
505
583
|
.command('setup')
|
|
506
584
|
.description('Interactive TUI wizard for configuring and launching a swarm')
|
|
507
|
-
.action(() => {
|
|
508
|
-
|
|
585
|
+
.action(async () => { const { swarmSetup } = await Promise.resolve().then(() => __importStar(require('./commands/swarm-setup'))); swarmSetup(); });
|
|
586
|
+
swarmCmd
|
|
587
|
+
.command('swarm-dashboard')
|
|
588
|
+
.description('Live swarm dashboard')
|
|
589
|
+
.allowUnknownOption()
|
|
590
|
+
.action(async () => {
|
|
591
|
+
const { swarmDashboardCommand } = await Promise.resolve().then(() => __importStar(require('./commands/swarm-dashboard')));
|
|
592
|
+
swarmDashboardCommand.parse(process.argv.slice(3));
|
|
509
593
|
});
|
|
510
|
-
swarmCmd.addCommand(swarm_dashboard_1.swarmDashboardCommand);
|
|
511
594
|
// --- Remote & Agent Wrapper Helpers ---
|
|
512
595
|
function runRemoteCommand(command, ...args) {
|
|
513
596
|
const isAgent = command === 'agent';
|
package/dist/lib/usage-parser.js
CHANGED
|
@@ -91,8 +91,24 @@ function resolveSessionName(name) {
|
|
|
91
91
|
if (fs.existsSync(activeSessionsPath)) {
|
|
92
92
|
try {
|
|
93
93
|
const sessions = JSON.parse(fs.readFileSync(activeSessionsPath, 'utf-8'));
|
|
94
|
-
// Find first entry with a valid UUID sessionId (skip "unknown" or empty)
|
|
95
|
-
|
|
94
|
+
// Find first entry with a valid UUID sessionId (skip "unknown" or empty).
|
|
95
|
+
// Also skip entries whose PID is dead (stale from prior runs / restarts).
|
|
96
|
+
const match = sessions.find(s => {
|
|
97
|
+
if (s.sessionName !== name)
|
|
98
|
+
return false;
|
|
99
|
+
if (!s.sessionId || s.sessionId === 'unknown' || s.sessionId.length <= 8)
|
|
100
|
+
return false;
|
|
101
|
+
// Prune dead PIDs — prevents stale cross-binding after restart
|
|
102
|
+
if (s.pid > 1) {
|
|
103
|
+
try {
|
|
104
|
+
process.kill(s.pid, 0);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
});
|
|
96
112
|
if (match) {
|
|
97
113
|
return {
|
|
98
114
|
uuid: match.sessionId,
|
package/dist/local/index.d.ts
CHANGED
|
@@ -12,3 +12,7 @@ export { SyncEngine, createSyncEngine, } from './sync-engine';
|
|
|
12
12
|
export type { SyncResult, } from './sync-engine';
|
|
13
13
|
export { generateLocalEmbedding, cosineSimilarity, searchByEmbedding, isEmbeddingAvailable, } from './local-embeddings';
|
|
14
14
|
export type { SimilarityResult, } from './local-embeddings';
|
|
15
|
+
export { detectStack, } from './stack-detection';
|
|
16
|
+
export type { StackInfo, } from './stack-detection';
|
|
17
|
+
export { LANGUAGE_CONFIGS, BASE_KEY_FILES, BASE_EXCLUDED_DIRS, getKeyFilesForStack, getExcludedDirsForStack, getPromptHintsForStack, getSourceExtensionsForStack, getSystemBoundaryMarkersForStack, } from './language-config';
|
|
18
|
+
export type { LanguageConfig, } from './language-config';
|
package/dist/local/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Provides offline-capable memory, fallback logic, sync, and local embeddings.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.isEmbeddingAvailable = exports.searchByEmbedding = exports.cosineSimilarity = exports.generateLocalEmbedding = exports.createSyncEngine = exports.SyncEngine = exports.OFFLINE_CAPABLE_TOOLS = exports.isOfflineFallbackReady = exports.callWithFallback = exports.localStore = exports.LocalMemoryStore = void 0;
|
|
9
|
+
exports.getSystemBoundaryMarkersForStack = exports.getSourceExtensionsForStack = exports.getPromptHintsForStack = exports.getExcludedDirsForStack = exports.getKeyFilesForStack = exports.BASE_EXCLUDED_DIRS = exports.BASE_KEY_FILES = exports.LANGUAGE_CONFIGS = exports.detectStack = exports.isEmbeddingAvailable = exports.searchByEmbedding = exports.cosineSimilarity = exports.generateLocalEmbedding = exports.createSyncEngine = exports.SyncEngine = exports.OFFLINE_CAPABLE_TOOLS = exports.isOfflineFallbackReady = exports.callWithFallback = exports.localStore = exports.LocalMemoryStore = void 0;
|
|
10
10
|
// SQLite memory store (Phase 6A)
|
|
11
11
|
var sqlite_store_1 = require("./sqlite-store");
|
|
12
12
|
Object.defineProperty(exports, "LocalMemoryStore", { enumerable: true, get: function () { return sqlite_store_1.LocalMemoryStore; } });
|
|
@@ -26,3 +26,16 @@ Object.defineProperty(exports, "generateLocalEmbedding", { enumerable: true, get
|
|
|
26
26
|
Object.defineProperty(exports, "cosineSimilarity", { enumerable: true, get: function () { return local_embeddings_1.cosineSimilarity; } });
|
|
27
27
|
Object.defineProperty(exports, "searchByEmbedding", { enumerable: true, get: function () { return local_embeddings_1.searchByEmbedding; } });
|
|
28
28
|
Object.defineProperty(exports, "isEmbeddingAvailable", { enumerable: true, get: function () { return local_embeddings_1.isEmbeddingAvailable; } });
|
|
29
|
+
// Stack detection (Living Docs V4 — Phase 4)
|
|
30
|
+
var stack_detection_1 = require("./stack-detection");
|
|
31
|
+
Object.defineProperty(exports, "detectStack", { enumerable: true, get: function () { return stack_detection_1.detectStack; } });
|
|
32
|
+
// Language configuration (Living Docs V4 — Phase 4)
|
|
33
|
+
var language_config_1 = require("./language-config");
|
|
34
|
+
Object.defineProperty(exports, "LANGUAGE_CONFIGS", { enumerable: true, get: function () { return language_config_1.LANGUAGE_CONFIGS; } });
|
|
35
|
+
Object.defineProperty(exports, "BASE_KEY_FILES", { enumerable: true, get: function () { return language_config_1.BASE_KEY_FILES; } });
|
|
36
|
+
Object.defineProperty(exports, "BASE_EXCLUDED_DIRS", { enumerable: true, get: function () { return language_config_1.BASE_EXCLUDED_DIRS; } });
|
|
37
|
+
Object.defineProperty(exports, "getKeyFilesForStack", { enumerable: true, get: function () { return language_config_1.getKeyFilesForStack; } });
|
|
38
|
+
Object.defineProperty(exports, "getExcludedDirsForStack", { enumerable: true, get: function () { return language_config_1.getExcludedDirsForStack; } });
|
|
39
|
+
Object.defineProperty(exports, "getPromptHintsForStack", { enumerable: true, get: function () { return language_config_1.getPromptHintsForStack; } });
|
|
40
|
+
Object.defineProperty(exports, "getSourceExtensionsForStack", { enumerable: true, get: function () { return language_config_1.getSourceExtensionsForStack; } });
|
|
41
|
+
Object.defineProperty(exports, "getSystemBoundaryMarkersForStack", { enumerable: true, get: function () { return language_config_1.getSystemBoundaryMarkersForStack; } });
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Configuration — data-driven config for each language ecosystem
|
|
3
|
+
*
|
|
4
|
+
* Pure functions with zero dependencies. Provides key files, excluded dirs,
|
|
5
|
+
* source extensions, system boundary markers, and Gemini prompt hints
|
|
6
|
+
* for each supported language.
|
|
7
|
+
*
|
|
8
|
+
* Living Docs V4 — Phase 4: Language-Adapted Discovery
|
|
9
|
+
*/
|
|
10
|
+
import type { StackInfo } from './stack-detection.js';
|
|
11
|
+
export interface LanguageConfig {
|
|
12
|
+
/** Key file names to prioritize reading (for both CLI and server compiler) */
|
|
13
|
+
keyFiles: string[];
|
|
14
|
+
/** Directories to exclude from scanning */
|
|
15
|
+
excludedDirs: string[];
|
|
16
|
+
/** File extensions that count as source files */
|
|
17
|
+
sourceExtensions: string[];
|
|
18
|
+
/** Files that mark a system boundary */
|
|
19
|
+
systemBoundaryMarkers: string[];
|
|
20
|
+
/** Prompt hints for Gemini (what to ask about) */
|
|
21
|
+
promptHints: {
|
|
22
|
+
architecture: string[];
|
|
23
|
+
buildSystem: string[];
|
|
24
|
+
deployTarget: string[];
|
|
25
|
+
testFramework: string[];
|
|
26
|
+
conventions: string[];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare const BASE_KEY_FILES: string[];
|
|
30
|
+
export declare const BASE_EXCLUDED_DIRS: string[];
|
|
31
|
+
export declare const LANGUAGE_CONFIGS: Record<string, LanguageConfig>;
|
|
32
|
+
/**
|
|
33
|
+
* Get the merged key files list for a detected stack.
|
|
34
|
+
* Returns BASE_KEY_FILES + language-specific files (deduplicated).
|
|
35
|
+
*/
|
|
36
|
+
export declare function getKeyFilesForStack(stack: StackInfo): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Get the merged excluded dirs for a detected stack.
|
|
39
|
+
* Returns BASE_EXCLUDED_DIRS + language-specific dirs.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getExcludedDirsForStack(stack: StackInfo): Set<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Get prompt hints for the Gemini compiler.
|
|
44
|
+
* Falls back to TypeScript hints for unknown languages.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getPromptHintsForStack(stack: StackInfo): LanguageConfig['promptHints'];
|
|
47
|
+
/**
|
|
48
|
+
* Get the source extensions for a detected stack.
|
|
49
|
+
*/
|
|
50
|
+
export declare function getSourceExtensionsForStack(stack: StackInfo): Set<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Get system boundary markers for a detected stack.
|
|
53
|
+
* These are files that indicate a "system root" directory.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getSystemBoundaryMarkersForStack(stack: StackInfo): string[];
|