@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
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* ekkOS CLI: doctor command
|
|
3
3
|
* Checks system prerequisites for ekkOS
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Gates:
|
|
6
6
|
* - Node gate: Node >= 18 required (FAIL if missing)
|
|
7
|
+
* - Claude gate: Claude CLI installed
|
|
7
8
|
* - PTY gate: WARN on Windows if missing (monitor-only mode available)
|
|
8
|
-
* -
|
|
9
|
-
* - NO jq checks (jq dependency eliminated)
|
|
9
|
+
* - MCP gate: ekkOS MCP server configured
|
|
10
10
|
*/
|
|
11
11
|
type GateStatus = 'PASS' | 'FAIL' | 'WARN';
|
|
12
12
|
interface Check {
|
package/dist/commands/doctor.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* ekkOS CLI: doctor command
|
|
4
4
|
* Checks system prerequisites for ekkOS
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Gates:
|
|
7
7
|
* - Node gate: Node >= 18 required (FAIL if missing)
|
|
8
|
+
* - Claude gate: Claude CLI installed
|
|
8
9
|
* - PTY gate: WARN on Windows if missing (monitor-only mode available)
|
|
9
|
-
* -
|
|
10
|
-
* - NO jq checks (jq dependency eliminated)
|
|
10
|
+
* - MCP gate: ekkOS MCP server configured
|
|
11
11
|
*/
|
|
12
12
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -20,7 +20,6 @@ const path_1 = require("path");
|
|
|
20
20
|
const fs_1 = require("fs");
|
|
21
21
|
const child_process_1 = require("child_process");
|
|
22
22
|
const chalk_1 = __importDefault(require("chalk"));
|
|
23
|
-
const hooks_1 = require("./hooks");
|
|
24
23
|
// ekkOS-managed Claude installation path (same as run.ts)
|
|
25
24
|
const EKKOS_CLAUDE_BIN = (0, path_1.join)((0, os_1.homedir)(), '.ekkos', 'claude-code', 'node_modules', '.bin', 'claude');
|
|
26
25
|
/**
|
|
@@ -139,44 +138,6 @@ function parseMcpOutput(output) {
|
|
|
139
138
|
output.toLowerCase().includes('memory');
|
|
140
139
|
return { configured: hasEkkos, servers };
|
|
141
140
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Check hooks installation status
|
|
144
|
-
*/
|
|
145
|
-
function checkHooksInstallation() {
|
|
146
|
-
const isWindows = (0, os_1.platform)() === 'win32';
|
|
147
|
-
const manifestData = (0, hooks_1.loadManifest)();
|
|
148
|
-
if (!manifestData) {
|
|
149
|
-
return { installed: false, details: 'Source manifest not found' };
|
|
150
|
-
}
|
|
151
|
-
const platformConfig = manifestData.manifest.platforms[(0, os_1.platform)()];
|
|
152
|
-
const globalHooksDir = (0, hooks_1.expandPath)(platformConfig.globalHooksDir);
|
|
153
|
-
const configDir = (0, hooks_1.expandPath)(platformConfig.configDir);
|
|
154
|
-
// Check installed manifest
|
|
155
|
-
const installedManifestPath = (0, path_1.join)(globalHooksDir, '.ekkos-manifest.json');
|
|
156
|
-
if (!(0, fs_1.existsSync)(installedManifestPath)) {
|
|
157
|
-
return { installed: false, details: 'No installed manifest found' };
|
|
158
|
-
}
|
|
159
|
-
// Check helper
|
|
160
|
-
const helperPath = (0, path_1.join)(configDir, '.helpers', 'json-parse.cjs');
|
|
161
|
-
if (!(0, fs_1.existsSync)(helperPath)) {
|
|
162
|
-
return { installed: false, details: 'json-parse.cjs helper missing' };
|
|
163
|
-
}
|
|
164
|
-
// Check defaults
|
|
165
|
-
const defaultsPath = (0, path_1.join)(configDir, '.defaults', 'session-words.json');
|
|
166
|
-
if (!(0, fs_1.existsSync)(defaultsPath)) {
|
|
167
|
-
return { installed: false, details: 'Default session words missing' };
|
|
168
|
-
}
|
|
169
|
-
// Check required hooks
|
|
170
|
-
const hookExt = isWindows ? '.ps1' : '.sh';
|
|
171
|
-
const requiredHooks = ['user-prompt-submit', 'stop', 'session-start'];
|
|
172
|
-
for (const hookName of requiredHooks) {
|
|
173
|
-
const hookPath = (0, path_1.join)(globalHooksDir, `${hookName}${hookExt}`);
|
|
174
|
-
if (!(0, fs_1.existsSync)(hookPath)) {
|
|
175
|
-
return { installed: false, details: `${hookName}${hookExt} missing` };
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return { installed: true, details: 'All hooks and helpers installed' };
|
|
179
|
-
}
|
|
180
141
|
/**
|
|
181
142
|
* Run diagnostic checks and return report
|
|
182
143
|
*/
|
|
@@ -266,7 +227,7 @@ function runDiagnostics() {
|
|
|
266
227
|
ptyChecks.push({
|
|
267
228
|
name: 'Monitor-only mode',
|
|
268
229
|
passed: true,
|
|
269
|
-
detail: '
|
|
230
|
+
detail: 'PTY not available on Windows; using spawn pass-through'
|
|
270
231
|
});
|
|
271
232
|
}
|
|
272
233
|
else {
|
|
@@ -285,32 +246,11 @@ function runDiagnostics() {
|
|
|
285
246
|
status: ptyGateStatus,
|
|
286
247
|
checks: ptyChecks,
|
|
287
248
|
fix: ptyGateStatus === 'WARN'
|
|
288
|
-
? 'npm install node-pty-prebuilt-multiarch (optional for
|
|
249
|
+
? 'npm install node-pty-prebuilt-multiarch (optional for terminal monitoring)'
|
|
289
250
|
: undefined
|
|
290
251
|
});
|
|
291
252
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
292
|
-
// GATE 4:
|
|
293
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
294
|
-
const hooksChecks = [];
|
|
295
|
-
let hooksGateStatus = 'PASS';
|
|
296
|
-
const hooksResult = checkHooksInstallation();
|
|
297
|
-
hooksChecks.push({
|
|
298
|
-
name: 'ekkOS hooks installed',
|
|
299
|
-
passed: hooksResult.installed,
|
|
300
|
-
detail: hooksResult.details
|
|
301
|
-
});
|
|
302
|
-
if (!hooksResult.installed) {
|
|
303
|
-
hooksGateStatus = 'WARN';
|
|
304
|
-
}
|
|
305
|
-
gates.push({
|
|
306
|
-
id: 'hooks',
|
|
307
|
-
title: 'ekkOS Hooks',
|
|
308
|
-
status: hooksGateStatus,
|
|
309
|
-
checks: hooksChecks,
|
|
310
|
-
fix: hooksGateStatus === 'WARN' ? 'ekkos hooks install --global' : undefined
|
|
311
|
-
});
|
|
312
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
313
|
-
// GATE 5: MCP Works
|
|
253
|
+
// GATE 4: MCP Works
|
|
314
254
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
315
255
|
const mcpChecks = [];
|
|
316
256
|
let mcpGatePass = true;
|
|
@@ -449,19 +389,6 @@ async function attemptAutoFixes(report) {
|
|
|
449
389
|
manual.push('If that fails: Install VS Build Tools, then: npm rebuild node-pty');
|
|
450
390
|
}
|
|
451
391
|
break;
|
|
452
|
-
case 'hooks':
|
|
453
|
-
// Try to install hooks
|
|
454
|
-
console.log(chalk_1.default.yellow('\nAttempting to install hooks...'));
|
|
455
|
-
try {
|
|
456
|
-
// Import and call directly
|
|
457
|
-
const { hooksInstall } = require('./hooks');
|
|
458
|
-
await hooksInstall({ global: true, verbose: false });
|
|
459
|
-
fixed.push('Hooks installed');
|
|
460
|
-
}
|
|
461
|
-
catch {
|
|
462
|
-
manual.push('ekkos hooks install --global');
|
|
463
|
-
}
|
|
464
|
-
break;
|
|
465
392
|
case 'mcp':
|
|
466
393
|
// Try to configure MCP (safe)
|
|
467
394
|
console.log(chalk_1.default.yellow('\nAttempting to configure MCP...'));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ekkOS Gemini CLI Launcher
|
|
3
|
+
*
|
|
4
|
+
* Spawns Gemini CLI with GOOGLE_GEMINI_BASE_URL pointing at the ekkOS proxy.
|
|
5
|
+
* The @google/genai SDK appends /v1beta/models/{model}:generateContent to the
|
|
6
|
+
* base URL, which the proxy routes through IPC compression + pattern injection.
|
|
7
|
+
*
|
|
8
|
+
* Minimal wrapper — Gemini CLI handles its own terminal UX.
|
|
9
|
+
* Gemini CLI handles its own terminal UX.
|
|
10
|
+
*/
|
|
11
|
+
export interface GeminiOptions {
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
noProxy?: boolean;
|
|
14
|
+
session?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Launch Gemini CLI with ekkOS proxy integration.
|
|
18
|
+
*/
|
|
19
|
+
export declare function gemini(options?: GeminiOptions): Promise<void>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ekkOS Gemini CLI Launcher
|
|
4
|
+
*
|
|
5
|
+
* Spawns Gemini CLI with GOOGLE_GEMINI_BASE_URL pointing at the ekkOS proxy.
|
|
6
|
+
* The @google/genai SDK appends /v1beta/models/{model}:generateContent to the
|
|
7
|
+
* base URL, which the proxy routes through IPC compression + pattern injection.
|
|
8
|
+
*
|
|
9
|
+
* Minimal wrapper — Gemini CLI handles its own terminal UX.
|
|
10
|
+
* Gemini CLI handles its own terminal UX.
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.gemini = gemini;
|
|
50
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
51
|
+
const crypto = __importStar(require("crypto"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const os = __importStar(require("os"));
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const child_process_1 = require("child_process");
|
|
56
|
+
const state_1 = require("../utils/state");
|
|
57
|
+
const proxy_url_1 = require("../utils/proxy-url");
|
|
58
|
+
// Session state — set once at startup
|
|
59
|
+
let cliSessionName = null;
|
|
60
|
+
let cliSessionId = null;
|
|
61
|
+
const isWindows = process.platform === 'win32';
|
|
62
|
+
/**
|
|
63
|
+
* Resolve Gemini CLI binary path.
|
|
64
|
+
* Checks common locations then falls back to PATH lookup.
|
|
65
|
+
*/
|
|
66
|
+
function resolveGeminiPath() {
|
|
67
|
+
if (!isWindows) {
|
|
68
|
+
const pathsToCheck = [
|
|
69
|
+
'/opt/homebrew/bin/gemini',
|
|
70
|
+
'/usr/local/bin/gemini',
|
|
71
|
+
path.join(os.homedir(), '.local', 'bin', 'gemini'),
|
|
72
|
+
path.join(os.homedir(), '.npm-global', 'bin', 'gemini'),
|
|
73
|
+
];
|
|
74
|
+
for (const p of pathsToCheck) {
|
|
75
|
+
if (fs.existsSync(p))
|
|
76
|
+
return p;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// PATH lookup
|
|
80
|
+
const whichCmd = isWindows ? 'where gemini' : 'which gemini';
|
|
81
|
+
try {
|
|
82
|
+
const result = (0, child_process_1.execSync)(whichCmd, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
83
|
+
if (result)
|
|
84
|
+
return result.split('\n')[0];
|
|
85
|
+
}
|
|
86
|
+
catch { /* not found */ }
|
|
87
|
+
// Fallback — let spawn resolve it (will error with helpful message)
|
|
88
|
+
return 'gemini';
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Build environment for Gemini CLI with proxy routing.
|
|
92
|
+
*/
|
|
93
|
+
function buildGeminiEnv(options) {
|
|
94
|
+
const env = { ...process.env };
|
|
95
|
+
if (options.noProxy) {
|
|
96
|
+
return env;
|
|
97
|
+
}
|
|
98
|
+
// Generate session identity (same pattern as run.ts getEkkosEnv)
|
|
99
|
+
if (!cliSessionName) {
|
|
100
|
+
cliSessionId = crypto.randomUUID();
|
|
101
|
+
cliSessionName = options.session || (0, state_1.uuidToWords)(cliSessionId);
|
|
102
|
+
console.log(chalk_1.default.gray(` 📂 Session: ${cliSessionName}`));
|
|
103
|
+
}
|
|
104
|
+
// Resolve userId from config or auth token
|
|
105
|
+
const ekkosConfig = (0, state_1.getConfig)();
|
|
106
|
+
let userId = ekkosConfig?.userId || 'anonymous';
|
|
107
|
+
if (userId === 'anonymous') {
|
|
108
|
+
const authToken = (0, state_1.getAuthToken)();
|
|
109
|
+
if (authToken?.startsWith('ekk_')) {
|
|
110
|
+
const parts = authToken.split('_');
|
|
111
|
+
if (parts.length >= 2 && parts[1])
|
|
112
|
+
userId = parts[1];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Build proxy URL — no query params (SDK concatenates baseUrl + path as strings).
|
|
116
|
+
// Format: /gproxy/{userId}/{session}/{sid}/{project64}
|
|
117
|
+
// Proxy extracts params from path, then routes /v1beta or /v1beta1 to googleRouter.
|
|
118
|
+
const proxyUrl = (0, proxy_url_1.buildGeminiProxyUrl)(userId, cliSessionName, process.cwd(), cliSessionId);
|
|
119
|
+
env.GOOGLE_GEMINI_BASE_URL = proxyUrl;
|
|
120
|
+
env.GOOGLE_VERTEX_BASE_URL = proxyUrl;
|
|
121
|
+
// User must bring their own Gemini API key — ekkOS just proxies the traffic
|
|
122
|
+
// for IPC compression and pattern injection (same model as Claude).
|
|
123
|
+
if (!env.GEMINI_API_KEY && !env.GOOGLE_API_KEY) {
|
|
124
|
+
console.warn(chalk_1.default.yellow(' ⚠ GEMINI_API_KEY not set.'));
|
|
125
|
+
console.warn(chalk_1.default.gray(' Get one at: https://aistudio.google.com/apikey'));
|
|
126
|
+
console.warn(chalk_1.default.gray(' Then: export GEMINI_API_KEY=your_key'));
|
|
127
|
+
}
|
|
128
|
+
if (options.verbose) {
|
|
129
|
+
// Redact userId from log
|
|
130
|
+
const safeUrl = proxyUrl.replace(/\/proxy\/[^/]+\//, '/proxy/[user]/');
|
|
131
|
+
console.log(chalk_1.default.gray(` 🔗 Proxy: ${safeUrl}`));
|
|
132
|
+
}
|
|
133
|
+
return env;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Launch Gemini CLI with ekkOS proxy integration.
|
|
137
|
+
*/
|
|
138
|
+
async function gemini(options = {}) {
|
|
139
|
+
(0, state_1.ensureEkkosDir)();
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log(chalk_1.default.cyan(' 🧠 ekkOS_') + chalk_1.default.gray(' + ') + chalk_1.default.blue('Gemini CLI'));
|
|
142
|
+
// Resolve binary
|
|
143
|
+
const geminiPath = resolveGeminiPath();
|
|
144
|
+
if (options.verbose) {
|
|
145
|
+
console.log(chalk_1.default.gray(` 📦 Binary: ${geminiPath}`));
|
|
146
|
+
}
|
|
147
|
+
// Build env with proxy routing
|
|
148
|
+
const env = buildGeminiEnv(options);
|
|
149
|
+
// Register session for multi-session awareness
|
|
150
|
+
const sessionId = cliSessionId || crypto.randomUUID();
|
|
151
|
+
const sessionName = cliSessionName || 'gemini-session';
|
|
152
|
+
(0, state_1.registerActiveSession)(sessionId, sessionName, process.cwd());
|
|
153
|
+
if (!options.noProxy) {
|
|
154
|
+
console.log(chalk_1.default.cyan(' 🧠 ekkOS_Continuum Loaded!'));
|
|
155
|
+
}
|
|
156
|
+
console.log('');
|
|
157
|
+
// Spawn Gemini CLI — stdio: inherit for full terminal passthrough
|
|
158
|
+
const child = (0, child_process_1.spawn)(geminiPath, [], {
|
|
159
|
+
stdio: 'inherit',
|
|
160
|
+
env,
|
|
161
|
+
cwd: process.cwd(),
|
|
162
|
+
shell: isWindows,
|
|
163
|
+
});
|
|
164
|
+
const cleanup = () => {
|
|
165
|
+
(0, state_1.unregisterActiveSession)();
|
|
166
|
+
};
|
|
167
|
+
child.on('exit', (code) => {
|
|
168
|
+
cleanup();
|
|
169
|
+
if (code !== null && code !== 0) {
|
|
170
|
+
process.exit(code);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
child.on('error', (err) => {
|
|
174
|
+
cleanup();
|
|
175
|
+
if (err.code === 'ENOENT') {
|
|
176
|
+
console.error('');
|
|
177
|
+
console.error(chalk_1.default.red(' ✘ Gemini CLI not found'));
|
|
178
|
+
console.error('');
|
|
179
|
+
console.error(chalk_1.default.white(' Install:'));
|
|
180
|
+
console.error(chalk_1.default.cyan(' npm install -g @google/gemini-cli'));
|
|
181
|
+
console.error('');
|
|
182
|
+
console.error(chalk_1.default.white(' Docs: ') + chalk_1.default.cyan('https://github.com/google-gemini/gemini-cli'));
|
|
183
|
+
console.error('');
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
console.error(chalk_1.default.red(`\n ✘ Failed to launch Gemini CLI: ${err.message}\n`));
|
|
187
|
+
}
|
|
188
|
+
process.exit(1);
|
|
189
|
+
});
|
|
190
|
+
// Forward signals for clean shutdown
|
|
191
|
+
process.on('SIGINT', () => { child.kill('SIGINT'); });
|
|
192
|
+
process.on('SIGTERM', () => { child.kill('SIGTERM'); });
|
|
193
|
+
}
|
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -11,12 +11,10 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
11
11
|
const open_1 = __importDefault(require("open"));
|
|
12
12
|
const platform_1 = require("../utils/platform");
|
|
13
13
|
const mcp_1 = require("../deploy/mcp");
|
|
14
|
+
const settings_1 = require("../deploy/settings");
|
|
14
15
|
// DEPRECATED: Hooks removed in hookless architecture migration
|
|
15
|
-
// import { deployClaudeSettings } from '../deploy/settings';
|
|
16
16
|
// import { deployHooks } from '../deploy/hooks';
|
|
17
17
|
const skills_1 = require("../deploy/skills");
|
|
18
|
-
const agents_1 = require("../deploy/agents");
|
|
19
|
-
const plugins_1 = require("../deploy/plugins");
|
|
20
18
|
const instructions_1 = require("../deploy/instructions");
|
|
21
19
|
const templates_1 = require("../utils/templates");
|
|
22
20
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -200,23 +198,37 @@ async function manualKeyAuth(providedKey) {
|
|
|
200
198
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
201
199
|
// IDE SETUP
|
|
202
200
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
203
|
-
async function selectIDEs() {
|
|
201
|
+
async function selectIDEs(autoSelect = false) {
|
|
204
202
|
console.log(chalk_1.default.cyan('Step 2/3: IDE Setup'));
|
|
205
203
|
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
206
204
|
console.log('');
|
|
207
205
|
const detected = (0, platform_1.detectInstalledIDEs)();
|
|
208
206
|
const current = (0, platform_1.detectCurrentIDE)();
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
// Build the unique ordered list: current IDE first, then any others detected
|
|
208
|
+
const detectedSet = new Set(detected);
|
|
209
|
+
if (current && (current === 'claude' || current === 'cursor' || current === 'windsurf')) {
|
|
210
|
+
detectedSet.add(current);
|
|
211
|
+
}
|
|
212
|
+
const detectedList = Array.from(detectedSet);
|
|
213
|
+
if (detectedList.length > 0) {
|
|
214
|
+
console.log(chalk_1.default.gray(`Detected: ${detectedList.join(', ')}`));
|
|
211
215
|
if (current) {
|
|
212
216
|
console.log(chalk_1.default.gray(`Current: ${current}`));
|
|
213
217
|
}
|
|
214
218
|
console.log('');
|
|
215
219
|
}
|
|
220
|
+
// Auto-select when exactly one IDE is detected or autoSelect flag is set
|
|
221
|
+
if (autoSelect || detectedList.length === 1) {
|
|
222
|
+
const autoIDE = detectedList.length === 1 ? detectedList[0] : (current ?? detectedList[0] ?? 'claude');
|
|
223
|
+
const ideName = autoIDE === 'claude' ? 'Claude Code' : autoIDE === 'cursor' ? 'Cursor' : 'Windsurf';
|
|
224
|
+
console.log(chalk_1.default.green(`✓ Auto-detected: ${chalk_1.default.bold(ideName)}`));
|
|
225
|
+
console.log('');
|
|
226
|
+
return [autoIDE];
|
|
227
|
+
}
|
|
216
228
|
const ideChoices = [
|
|
217
|
-
{ name: 'Claude Code', value: 'claude', checked:
|
|
218
|
-
{ name: 'Cursor', value: 'cursor', checked:
|
|
219
|
-
{ name: 'Windsurf (Cascade)', value: 'windsurf', checked:
|
|
229
|
+
{ name: 'Claude Code', value: 'claude', checked: detectedList.includes('claude') || current === 'claude' },
|
|
230
|
+
{ name: 'Cursor', value: 'cursor', checked: detectedList.includes('cursor') || current === 'cursor' },
|
|
231
|
+
{ name: 'Windsurf (Cascade)', value: 'windsurf', checked: detectedList.includes('windsurf') || current === 'windsurf' }
|
|
220
232
|
];
|
|
221
233
|
// If nothing was auto-detected, default to Claude Code
|
|
222
234
|
if (!ideChoices.some(c => c.checked)) {
|
|
@@ -236,10 +248,7 @@ async function deployForClaude(apiKey, userId, options) {
|
|
|
236
248
|
const result = {
|
|
237
249
|
mcp: false,
|
|
238
250
|
settings: false,
|
|
239
|
-
hooks: { count: 0, files: [] },
|
|
240
251
|
skills: { count: 0, skills: [] },
|
|
241
|
-
agents: { count: 0, agents: [] },
|
|
242
|
-
plugins: { count: 0, plugins: [] },
|
|
243
252
|
instructions: false
|
|
244
253
|
};
|
|
245
254
|
// MCP configuration
|
|
@@ -252,11 +261,18 @@ async function deployForClaude(apiKey, userId, options) {
|
|
|
252
261
|
catch (error) {
|
|
253
262
|
spinner.fail('MCP server configuration failed');
|
|
254
263
|
}
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
264
|
+
// Claude Code settings (disable auto-memory, clean up legacy hooks)
|
|
265
|
+
spinner = (0, ora_1.default)('Configuring Claude Code settings...').start();
|
|
266
|
+
try {
|
|
267
|
+
(0, settings_1.deployClaudeSettings)();
|
|
268
|
+
result.settings = true;
|
|
269
|
+
spinner.succeed('Claude Code settings (auto-memory disabled)');
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
spinner.fail('Claude Code settings failed');
|
|
273
|
+
result.settings = true; // Non-critical — don't block init
|
|
274
|
+
}
|
|
275
|
+
// Skills (only continue, ekkOS_Vault, permissions — rest handled by proxy injection)
|
|
260
276
|
if (!options.skipSkills) {
|
|
261
277
|
spinner = (0, ora_1.default)('Deploying skills...').start();
|
|
262
278
|
try {
|
|
@@ -267,24 +283,6 @@ async function deployForClaude(apiKey, userId, options) {
|
|
|
267
283
|
spinner.fail('Skills deployment failed');
|
|
268
284
|
}
|
|
269
285
|
}
|
|
270
|
-
// Agents
|
|
271
|
-
spinner = (0, ora_1.default)('Deploying agents...').start();
|
|
272
|
-
try {
|
|
273
|
-
result.agents = (0, agents_1.deployAgents)();
|
|
274
|
-
spinner.succeed(`Agents (${result.agents.count} files)`);
|
|
275
|
-
}
|
|
276
|
-
catch (error) {
|
|
277
|
-
spinner.fail('Agents deployment failed');
|
|
278
|
-
}
|
|
279
|
-
// Plugins
|
|
280
|
-
spinner = (0, ora_1.default)('Deploying plugins...').start();
|
|
281
|
-
try {
|
|
282
|
-
result.plugins = (0, plugins_1.deployPlugins)();
|
|
283
|
-
spinner.succeed(`Plugins (${result.plugins.count} folders)`);
|
|
284
|
-
}
|
|
285
|
-
catch (error) {
|
|
286
|
-
spinner.fail('Plugins deployment failed');
|
|
287
|
-
}
|
|
288
286
|
// CLAUDE.md
|
|
289
287
|
spinner = (0, ora_1.default)('Deploying global instructions...').start();
|
|
290
288
|
try {
|
|
@@ -325,9 +323,15 @@ async function deployForWindsurf(apiKey, userId) {
|
|
|
325
323
|
// MAIN INIT COMMAND
|
|
326
324
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
327
325
|
async function init(options) {
|
|
326
|
+
const isQuick = options.quick ?? false;
|
|
328
327
|
console.log('');
|
|
329
328
|
console.log(chalk_1.default.cyan.bold('╔═══════════════════════════════════════╗'));
|
|
330
|
-
|
|
329
|
+
if (isQuick) {
|
|
330
|
+
console.log(chalk_1.default.cyan.bold('║ ⚡ ekkOS Quick Setup ║'));
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
console.log(chalk_1.default.cyan.bold('║ 🧠 ekkOS Memory System Setup ║'));
|
|
334
|
+
}
|
|
331
335
|
console.log(chalk_1.default.cyan.bold('╚═══════════════════════════════════════╝'));
|
|
332
336
|
console.log('');
|
|
333
337
|
// Check templates exist
|
|
@@ -347,11 +351,11 @@ async function init(options) {
|
|
|
347
351
|
// STEP 1: Authentication
|
|
348
352
|
let auth;
|
|
349
353
|
if (options.key) {
|
|
350
|
-
// Manual API key provided
|
|
354
|
+
// Manual API key provided — always use it (respects --quick)
|
|
351
355
|
auth = await manualKeyAuth(options.key);
|
|
352
356
|
}
|
|
353
357
|
else if (existingConfig?.apiKey && !options.force) {
|
|
354
|
-
// Already authenticated
|
|
358
|
+
// Already authenticated — skip auth step entirely (works great with --quick)
|
|
355
359
|
console.log(chalk_1.default.cyan('Step 1/3: Authentication'));
|
|
356
360
|
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
357
361
|
console.log('');
|
|
@@ -365,6 +369,10 @@ async function init(options) {
|
|
|
365
369
|
tier: existingConfig.tier || 'unknown'
|
|
366
370
|
};
|
|
367
371
|
}
|
|
372
|
+
else if (isQuick) {
|
|
373
|
+
// --quick with no stored key: fall back to manual key prompt (one question only)
|
|
374
|
+
auth = await manualKeyAuth();
|
|
375
|
+
}
|
|
368
376
|
else {
|
|
369
377
|
// Device auth flow
|
|
370
378
|
try {
|
|
@@ -395,7 +403,8 @@ async function init(options) {
|
|
|
395
403
|
console.log('');
|
|
396
404
|
}
|
|
397
405
|
else {
|
|
398
|
-
|
|
406
|
+
// Pass autoSelect=true when --quick is set so we skip the checkbox prompt
|
|
407
|
+
selectedIDEs = await selectIDEs(isQuick);
|
|
399
408
|
}
|
|
400
409
|
// STEP 3: Deployment
|
|
401
410
|
console.log(chalk_1.default.cyan('Step 3/3: Deploying'));
|
|
@@ -405,7 +414,7 @@ async function init(options) {
|
|
|
405
414
|
for (const ide of selectedIDEs) {
|
|
406
415
|
if (ide === 'claude') {
|
|
407
416
|
const result = await deployForClaude(auth.apiKey, auth.userId, options);
|
|
408
|
-
if (result.mcp
|
|
417
|
+
if (result.mcp) {
|
|
409
418
|
installedIDEs.push('claude');
|
|
410
419
|
}
|
|
411
420
|
}
|
|
@@ -461,7 +470,13 @@ async function init(options) {
|
|
|
461
470
|
};
|
|
462
471
|
console.log('');
|
|
463
472
|
console.log(chalk_1.default.green.bold('╔═══════════════════════════════════════╗'));
|
|
464
|
-
|
|
473
|
+
if (isQuick) {
|
|
474
|
+
const quickIdeName = ideNames.join(' / ') || 'Claude Code';
|
|
475
|
+
console.log(chalk_1.default.green.bold(`║ ⚡ Quick setup complete for ${quickIdeName.padEnd(11)}║`));
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
console.log(chalk_1.default.green.bold('║ ✓ Setup complete! ║'));
|
|
479
|
+
}
|
|
465
480
|
console.log(chalk_1.default.green.bold('╚═══════════════════════════════════════╝'));
|
|
466
481
|
console.log('');
|
|
467
482
|
console.log(chalk_1.default.white.bold(' MCP configured:'));
|