@ekkos/cli 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/LocalSessionStore.d.ts +129 -0
- package/dist/cache/LocalSessionStore.js +688 -0
- package/dist/cache/capture.d.ts +26 -0
- package/dist/cache/capture.js +461 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.js +23 -0
- package/dist/cache/types.d.ts +147 -0
- package/dist/cache/types.js +40 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +478 -0
- package/dist/commands/run.d.ts +12 -0
- package/dist/commands/run.js +829 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.js +658 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +109 -0
- package/dist/commands/test.d.ts +1 -0
- package/dist/commands/test.js +157 -0
- package/dist/deploy/agents.d.ts +15 -0
- package/dist/deploy/agents.js +72 -0
- package/dist/deploy/hooks.d.ts +16 -0
- package/dist/deploy/hooks.js +121 -0
- package/dist/deploy/index.d.ts +7 -0
- package/dist/deploy/index.js +24 -0
- package/dist/deploy/instructions.d.ts +12 -0
- package/dist/deploy/instructions.js +36 -0
- package/dist/deploy/mcp.d.ts +19 -0
- package/dist/deploy/mcp.js +109 -0
- package/dist/deploy/plugins.d.ts +19 -0
- package/dist/deploy/plugins.js +62 -0
- package/dist/deploy/settings.d.ts +8 -0
- package/dist/deploy/settings.js +84 -0
- package/dist/deploy/skills.d.ts +19 -0
- package/dist/deploy/skills.js +60 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +71 -0
- package/dist/restore/RestoreOrchestrator.d.ts +48 -0
- package/dist/restore/RestoreOrchestrator.js +481 -0
- package/dist/restore/index.d.ts +4 -0
- package/dist/restore/index.js +20 -0
- package/dist/utils/platform.d.ts +29 -0
- package/dist/utils/platform.js +65 -0
- package/dist/utils/session-words.json +119 -0
- package/dist/utils/state.d.ts +57 -0
- package/dist/utils/state.js +186 -0
- package/dist/utils/templates.d.ts +24 -0
- package/dist/utils/templates.js +118 -0
- package/package.json +48 -0
- package/templates/CLAUDE.md +287 -0
- package/templates/README.md +378 -0
- package/templates/agents/README.md +182 -0
- package/templates/agents/code-reviewer.md +166 -0
- package/templates/agents/debug-detective.md +169 -0
- package/templates/agents/ekkOS_Vercel.md +99 -0
- package/templates/agents/extension-manager.md +229 -0
- package/templates/agents/git-companion.md +185 -0
- package/templates/agents/github-test-agent.md +321 -0
- package/templates/agents/railway-manager.md +179 -0
- package/templates/claude-plugins/PHASE2_COMPLETION.md +346 -0
- package/templates/claude-plugins/PLUGIN_PROPOSALS.md +1776 -0
- package/templates/claude-plugins/README.md +587 -0
- package/templates/claude-plugins/agents/code-reviewer.json +14 -0
- package/templates/claude-plugins/agents/debug-detective.json +15 -0
- package/templates/claude-plugins/agents/git-companion.json +14 -0
- package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins/blog-manager/commands/blog.md +691 -0
- package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +434 -0
- package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +282 -0
- package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins/memory-lens/commands/memory-search.md +181 -0
- package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins/pattern-coach/commands/forge.md +365 -0
- package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +582 -0
- package/templates/claude-plugins-admin/AGENT_TEAM_PROPOSALS.md +819 -0
- package/templates/claude-plugins-admin/README.md +446 -0
- package/templates/claude-plugins-admin/autonomous-admin-agent/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/autonomous-admin-agent/commands/agent.md +595 -0
- package/templates/claude-plugins-admin/backend-agent/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/backend-agent/commands/backend.md +798 -0
- package/templates/claude-plugins-admin/deploy-guardian/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/deploy-guardian/commands/deploy.md +554 -0
- package/templates/claude-plugins-admin/frontend-agent/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/frontend-agent/commands/frontend.md +881 -0
- package/templates/claude-plugins-admin/mcp-server-manager/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/mcp-server-manager/commands/mcp.md +85 -0
- package/templates/claude-plugins-admin/memory-system-monitor/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/memory-system-monitor/commands/memory-health.md +569 -0
- package/templates/claude-plugins-admin/qa-agent/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/qa-agent/commands/qa.md +863 -0
- package/templates/claude-plugins-admin/tech-lead-agent/.claude-plugin/plugin.json +8 -0
- package/templates/claude-plugins-admin/tech-lead-agent/commands/lead.md +732 -0
- package/templates/commands/continue.md +47 -0
- package/templates/cursor-hooks/after-agent-response.sh +117 -0
- package/templates/cursor-hooks/before-submit-prompt.sh +419 -0
- package/templates/cursor-hooks/hooks.json +20 -0
- package/templates/cursor-hooks/lib/contract.sh +320 -0
- package/templates/cursor-hooks/stop.sh +75 -0
- package/templates/cursor-rules/ekkos-memory.md +187 -0
- package/templates/hooks/assistant-response.sh +96 -0
- package/templates/hooks/hooks.json +28 -0
- package/templates/hooks/lib/contract.sh +320 -0
- package/templates/hooks/lib/state.sh +158 -0
- package/templates/hooks/session-start.ps1 +41 -0
- package/templates/hooks/session-start.sh +318 -0
- package/templates/hooks/stop.ps1 +16 -0
- package/templates/hooks/stop.sh +989 -0
- package/templates/hooks/user-prompt-submit.ps1 +174 -0
- package/templates/hooks/user-prompt-submit.sh +587 -0
- package/templates/hooks-node/lib/state.js +187 -0
- package/templates/hooks-node/stop.js +416 -0
- package/templates/hooks-node/user-prompt-submit.js +337 -0
- package/templates/plan-template.md +306 -0
- package/templates/rules/00-hooks-contract.mdc +89 -0
- package/templates/rules/30-ekkos-core.mdc +188 -0
- package/templates/rules/31-ekkos-messages.mdc +78 -0
- package/templates/skills/continue/SKILL.md +169 -0
- package/templates/skills/ekkOS_Deep_Recall/Skill.md +282 -0
- package/templates/skills/ekkOS_Learn/Skill.md +265 -0
- package/templates/skills/ekkOS_Memory_First/Skill.md +206 -0
- package/templates/skills/ekkOS_Plan_Assist/Skill.md +302 -0
- package/templates/skills/ekkOS_Preferences/Skill.md +247 -0
- package/templates/skills/ekkOS_Reflect/Skill.md +257 -0
- package/templates/skills/ekkOS_Safety/Skill.md +265 -0
- package/templates/skills/ekkOS_Schema/Skill.md +251 -0
- package/templates/skills/ekkOS_Summary/Skill.md +257 -0
- package/templates/skills/ekkOS_Vault/Skill.md +287 -0
- package/templates/skills/permissions/Skill.md +322 -0
- package/templates/spec-template.md +159 -0
- package/templates/windsurf-hooks/before-submit-prompt.sh +238 -0
- package/templates/windsurf-hooks/hooks.json +10 -0
- package/templates/windsurf-hooks/lib/contract.sh +320 -0
- package/templates/windsurf-rules/ekkos-memory.md +129 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ekkOS Fast /continue - Local Cache Types
|
|
4
|
+
*
|
|
5
|
+
* Defines the data structures for the 3-tier restore chain:
|
|
6
|
+
* Tier 0: Local JSONL cache (~20ms)
|
|
7
|
+
* Tier 1: Redis hot cache (~150ms)
|
|
8
|
+
* Tier 2: Supabase cold store (~500ms)
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.INVALID_RESPONSE_PATTERNS = void 0;
|
|
12
|
+
exports.isValidAssistantResponse = isValidAssistantResponse;
|
|
13
|
+
/**
|
|
14
|
+
* Known placeholder strings that indicate incomplete/invalid responses
|
|
15
|
+
* These should NOT be treated as valid assistant_response content
|
|
16
|
+
*/
|
|
17
|
+
exports.INVALID_RESPONSE_PATTERNS = [
|
|
18
|
+
'[object Object]',
|
|
19
|
+
'null',
|
|
20
|
+
'undefined',
|
|
21
|
+
'...',
|
|
22
|
+
'Loading...',
|
|
23
|
+
'Thinking...',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Check if an assistant_response is valid (complete, not a placeholder)
|
|
27
|
+
*/
|
|
28
|
+
function isValidAssistantResponse(response) {
|
|
29
|
+
if (!response)
|
|
30
|
+
return false;
|
|
31
|
+
const trimmed = response.trim();
|
|
32
|
+
if (trimmed.length === 0)
|
|
33
|
+
return false;
|
|
34
|
+
if (exports.INVALID_RESPONSE_PATTERNS.includes(trimmed))
|
|
35
|
+
return false;
|
|
36
|
+
// Also reject very short responses that look like placeholders
|
|
37
|
+
if (trimmed.length < 5 && !/\w{3,}/.test(trimmed))
|
|
38
|
+
return false;
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.init = init;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const open_1 = __importDefault(require("open"));
|
|
12
|
+
const platform_1 = require("../utils/platform");
|
|
13
|
+
const mcp_1 = require("../deploy/mcp");
|
|
14
|
+
const settings_1 = require("../deploy/settings");
|
|
15
|
+
const hooks_1 = require("../deploy/hooks");
|
|
16
|
+
const skills_1 = require("../deploy/skills");
|
|
17
|
+
const agents_1 = require("../deploy/agents");
|
|
18
|
+
const plugins_1 = require("../deploy/plugins");
|
|
19
|
+
const instructions_1 = require("../deploy/instructions");
|
|
20
|
+
const templates_1 = require("../utils/templates");
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
+
// DEVICE AUTHENTICATION
|
|
23
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
24
|
+
async function requestDeviceCode() {
|
|
25
|
+
const response = await fetch(`${platform_1.PLATFORM_URL}/api/device-auth/codes`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
headers: { 'Content-Type': 'application/json' }
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(`Failed to request device code: ${response.status}`);
|
|
31
|
+
}
|
|
32
|
+
return response.json();
|
|
33
|
+
}
|
|
34
|
+
async function pollForApproval(code, expiresIn) {
|
|
35
|
+
const pollInterval = 3000; // 3 seconds
|
|
36
|
+
const maxAttempts = Math.floor((expiresIn * 1000) / pollInterval);
|
|
37
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
38
|
+
const response = await fetch(`${platform_1.PLATFORM_URL}/api/device-auth/codes/${code}/status`, { method: 'GET' });
|
|
39
|
+
if (response.status === 410) {
|
|
40
|
+
return { status: 'expired' };
|
|
41
|
+
}
|
|
42
|
+
if (response.ok) {
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
if (data.status !== 'pending') {
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Wait before next poll
|
|
49
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
50
|
+
}
|
|
51
|
+
return { status: 'expired' };
|
|
52
|
+
}
|
|
53
|
+
async function generateApiKey(userId, email) {
|
|
54
|
+
const response = await fetch(`${platform_1.PLATFORM_URL}/api/auth/extension/generate`, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: { 'Content-Type': 'application/json' },
|
|
57
|
+
body: JSON.stringify({ userId, email })
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
throw new Error(`Failed to generate API key: ${response.status}`);
|
|
61
|
+
}
|
|
62
|
+
return response.json();
|
|
63
|
+
}
|
|
64
|
+
async function deviceAuth() {
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log(chalk_1.default.cyan('Step 1/3: Authentication'));
|
|
67
|
+
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
68
|
+
console.log('');
|
|
69
|
+
// Request device code
|
|
70
|
+
const spinner = (0, ora_1.default)('Requesting device code...').start();
|
|
71
|
+
let deviceCode;
|
|
72
|
+
try {
|
|
73
|
+
deviceCode = await requestDeviceCode();
|
|
74
|
+
spinner.succeed('Device code received');
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
spinner.fail('Failed to get device code');
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log(chalk_1.default.white.bold(`Your code: ${chalk_1.default.cyan.bold(deviceCode.code)}`));
|
|
82
|
+
console.log('');
|
|
83
|
+
// Open browser
|
|
84
|
+
const verificationUrl = deviceCode.verificationUrl || `${platform_1.PLATFORM_URL}/activate`;
|
|
85
|
+
console.log(chalk_1.default.gray(`Opening browser to: ${verificationUrl}`));
|
|
86
|
+
try {
|
|
87
|
+
await (0, open_1.default)(verificationUrl);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
console.log(chalk_1.default.yellow('Could not open browser automatically.'));
|
|
91
|
+
console.log(chalk_1.default.gray(`Please visit: ${verificationUrl}`));
|
|
92
|
+
}
|
|
93
|
+
console.log('');
|
|
94
|
+
// Poll for approval
|
|
95
|
+
const expiresMinutes = Math.floor(deviceCode.expiresIn / 60);
|
|
96
|
+
const pollSpinner = (0, ora_1.default)(`Waiting for approval... (expires in ${expiresMinutes} min)`).start();
|
|
97
|
+
let pollResult;
|
|
98
|
+
try {
|
|
99
|
+
pollResult = await pollForApproval(deviceCode.code, deviceCode.expiresIn);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
pollSpinner.fail('Authentication failed');
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
if (pollResult.status === 'denied') {
|
|
106
|
+
pollSpinner.fail('Authentication denied');
|
|
107
|
+
throw new Error('User denied authentication request');
|
|
108
|
+
}
|
|
109
|
+
if (pollResult.status === 'expired') {
|
|
110
|
+
pollSpinner.fail('Authentication expired');
|
|
111
|
+
throw new Error('Device code expired. Please try again.');
|
|
112
|
+
}
|
|
113
|
+
if (pollResult.status !== 'approved' || !pollResult.user_id || !pollResult.user_email) {
|
|
114
|
+
pollSpinner.fail('Authentication failed');
|
|
115
|
+
throw new Error('Invalid approval response');
|
|
116
|
+
}
|
|
117
|
+
pollSpinner.succeed('Approved');
|
|
118
|
+
// Generate API key
|
|
119
|
+
const keySpinner = (0, ora_1.default)('Generating API key...').start();
|
|
120
|
+
let keyData;
|
|
121
|
+
try {
|
|
122
|
+
keyData = await generateApiKey(pollResult.user_id, pollResult.user_email);
|
|
123
|
+
keySpinner.succeed('API key generated');
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
keySpinner.fail('Failed to generate API key');
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
console.log('');
|
|
130
|
+
console.log(chalk_1.default.green(`✓ Authenticated as ${chalk_1.default.bold(keyData.email)} (${keyData.tier} tier)`));
|
|
131
|
+
console.log('');
|
|
132
|
+
return {
|
|
133
|
+
apiKey: keyData.apiKey,
|
|
134
|
+
userId: pollResult.user_id,
|
|
135
|
+
email: keyData.email,
|
|
136
|
+
tier: keyData.tier
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
140
|
+
// MANUAL API KEY FLOW
|
|
141
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
142
|
+
async function manualKeyAuth(providedKey) {
|
|
143
|
+
console.log('');
|
|
144
|
+
console.log(chalk_1.default.cyan('Step 1/3: Authentication'));
|
|
145
|
+
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
146
|
+
console.log('');
|
|
147
|
+
let apiKey = providedKey;
|
|
148
|
+
if (!apiKey) {
|
|
149
|
+
console.log(chalk_1.default.yellow('Get your API key from: https://platform.ekkos.dev/dashboard/keys'));
|
|
150
|
+
console.log('');
|
|
151
|
+
const answers = await inquirer_1.default.prompt([
|
|
152
|
+
{
|
|
153
|
+
type: 'password',
|
|
154
|
+
name: 'apiKey',
|
|
155
|
+
message: 'Enter your ekkOS API key:',
|
|
156
|
+
mask: '*',
|
|
157
|
+
validate: (input) => {
|
|
158
|
+
if (!input || input.length < 10) {
|
|
159
|
+
return 'Please enter a valid API key';
|
|
160
|
+
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
]);
|
|
165
|
+
apiKey = answers.apiKey;
|
|
166
|
+
}
|
|
167
|
+
// Verify API key
|
|
168
|
+
const spinner = (0, ora_1.default)('Verifying API key...').start();
|
|
169
|
+
try {
|
|
170
|
+
const response = await fetch(`${platform_1.MCP_API_URL}/api/v1/patterns/query`, {
|
|
171
|
+
method: 'POST',
|
|
172
|
+
headers: {
|
|
173
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
174
|
+
'Content-Type': 'application/json'
|
|
175
|
+
},
|
|
176
|
+
body: JSON.stringify({ query: 'test', k: 1 })
|
|
177
|
+
});
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
spinner.fail('Invalid API key');
|
|
180
|
+
throw new Error('API key verification failed');
|
|
181
|
+
}
|
|
182
|
+
spinner.succeed('API key verified');
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
spinner.fail('Could not verify API key');
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
console.log('');
|
|
189
|
+
console.log(chalk_1.default.green('✓ Authenticated with API key'));
|
|
190
|
+
console.log('');
|
|
191
|
+
// For manual keys, we don't have user info
|
|
192
|
+
return {
|
|
193
|
+
apiKey: apiKey,
|
|
194
|
+
userId: 'manual',
|
|
195
|
+
email: 'manual@ekkos.dev',
|
|
196
|
+
tier: 'unknown'
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
200
|
+
// IDE SETUP
|
|
201
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
202
|
+
async function selectIDEs() {
|
|
203
|
+
console.log(chalk_1.default.cyan('Step 2/3: IDE Setup'));
|
|
204
|
+
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
205
|
+
console.log('');
|
|
206
|
+
const detected = (0, platform_1.detectInstalledIDEs)();
|
|
207
|
+
const current = (0, platform_1.detectCurrentIDE)();
|
|
208
|
+
if (detected.length > 0) {
|
|
209
|
+
console.log(chalk_1.default.gray(`Detected: ${detected.join(', ')}`));
|
|
210
|
+
if (current) {
|
|
211
|
+
console.log(chalk_1.default.gray(`Current: ${current}`));
|
|
212
|
+
}
|
|
213
|
+
console.log('');
|
|
214
|
+
}
|
|
215
|
+
const ideOptions = [
|
|
216
|
+
{ name: 'Claude Code', value: 'claude', default: detected.includes('claude') || current === 'claude' },
|
|
217
|
+
{ name: 'Cursor', value: 'cursor', default: detected.includes('cursor') || current === 'cursor' },
|
|
218
|
+
{ name: 'Windsurf (Cascade)', value: 'windsurf', default: detected.includes('windsurf') || current === 'windsurf' }
|
|
219
|
+
];
|
|
220
|
+
const selectedIDEs = [];
|
|
221
|
+
// Ask for each IDE individually
|
|
222
|
+
for (const ide of ideOptions) {
|
|
223
|
+
const answer = await inquirer_1.default.prompt({
|
|
224
|
+
type: 'confirm',
|
|
225
|
+
name: 'selected',
|
|
226
|
+
message: `Configure ${ide.name}?`,
|
|
227
|
+
default: ide.default
|
|
228
|
+
});
|
|
229
|
+
if (answer.selected) {
|
|
230
|
+
selectedIDEs.push(ide.value);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (selectedIDEs.length === 0) {
|
|
234
|
+
console.log(chalk_1.default.yellow('No IDEs selected. Defaulting to Claude Code.'));
|
|
235
|
+
selectedIDEs.push('claude');
|
|
236
|
+
}
|
|
237
|
+
console.log('');
|
|
238
|
+
return selectedIDEs;
|
|
239
|
+
}
|
|
240
|
+
async function deployForClaude(apiKey, userId, options) {
|
|
241
|
+
const result = {
|
|
242
|
+
mcp: false,
|
|
243
|
+
settings: false,
|
|
244
|
+
hooks: { count: 0, files: [] },
|
|
245
|
+
skills: { count: 0, skills: [] },
|
|
246
|
+
agents: { count: 0, agents: [] },
|
|
247
|
+
plugins: { count: 0, plugins: [] },
|
|
248
|
+
instructions: false
|
|
249
|
+
};
|
|
250
|
+
// MCP configuration
|
|
251
|
+
let spinner = (0, ora_1.default)('Deploying MCP server configuration...').start();
|
|
252
|
+
try {
|
|
253
|
+
(0, mcp_1.deployClaudeMcp)(apiKey, userId);
|
|
254
|
+
result.mcp = true;
|
|
255
|
+
spinner.succeed('MCP server configuration');
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
spinner.fail('MCP server configuration failed');
|
|
259
|
+
}
|
|
260
|
+
// Settings.json (hook registration)
|
|
261
|
+
spinner = (0, ora_1.default)('Deploying hooks configuration...').start();
|
|
262
|
+
try {
|
|
263
|
+
(0, settings_1.deployClaudeSettings)();
|
|
264
|
+
result.settings = true;
|
|
265
|
+
spinner.succeed('Hooks configuration');
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
spinner.fail('Hooks configuration failed');
|
|
269
|
+
}
|
|
270
|
+
// Hook scripts
|
|
271
|
+
if (!options.skipHooks) {
|
|
272
|
+
spinner = (0, ora_1.default)('Deploying hook scripts...').start();
|
|
273
|
+
try {
|
|
274
|
+
result.hooks = (0, hooks_1.deployHooks)(apiKey);
|
|
275
|
+
spinner.succeed(`Hook scripts (${result.hooks.count} files)`);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
spinner.fail('Hook scripts failed');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// Skills
|
|
282
|
+
if (!options.skipSkills) {
|
|
283
|
+
spinner = (0, ora_1.default)('Deploying skills...').start();
|
|
284
|
+
try {
|
|
285
|
+
result.skills = (0, skills_1.deploySkills)();
|
|
286
|
+
spinner.succeed(`Skills (${result.skills.count} folders)`);
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
spinner.fail('Skills deployment failed');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Agents
|
|
293
|
+
spinner = (0, ora_1.default)('Deploying agents...').start();
|
|
294
|
+
try {
|
|
295
|
+
result.agents = (0, agents_1.deployAgents)();
|
|
296
|
+
spinner.succeed(`Agents (${result.agents.count} files)`);
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
spinner.fail('Agents deployment failed');
|
|
300
|
+
}
|
|
301
|
+
// Plugins
|
|
302
|
+
spinner = (0, ora_1.default)('Deploying plugins...').start();
|
|
303
|
+
try {
|
|
304
|
+
result.plugins = (0, plugins_1.deployPlugins)();
|
|
305
|
+
spinner.succeed(`Plugins (${result.plugins.count} folders)`);
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
spinner.fail('Plugins deployment failed');
|
|
309
|
+
}
|
|
310
|
+
// CLAUDE.md
|
|
311
|
+
spinner = (0, ora_1.default)('Deploying global instructions...').start();
|
|
312
|
+
try {
|
|
313
|
+
(0, instructions_1.deployInstructions)();
|
|
314
|
+
result.instructions = true;
|
|
315
|
+
spinner.succeed('Global instructions (CLAUDE.md)');
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
spinner.fail('Global instructions failed');
|
|
319
|
+
}
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
async function deployForCursor(apiKey, userId) {
|
|
323
|
+
const spinner = (0, ora_1.default)('Deploying Cursor MCP configuration...').start();
|
|
324
|
+
try {
|
|
325
|
+
(0, mcp_1.deployCursorMcp)(apiKey, userId);
|
|
326
|
+
spinner.succeed('Cursor MCP configuration');
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
spinner.fail('Cursor MCP configuration failed');
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async function deployForWindsurf(apiKey, userId) {
|
|
335
|
+
const spinner = (0, ora_1.default)('Deploying Windsurf MCP configuration...').start();
|
|
336
|
+
try {
|
|
337
|
+
(0, mcp_1.deployWindsurfMcp)(apiKey, userId);
|
|
338
|
+
spinner.succeed('Windsurf MCP configuration');
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
spinner.fail('Windsurf MCP configuration failed');
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
347
|
+
// MAIN INIT COMMAND
|
|
348
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
349
|
+
async function init(options) {
|
|
350
|
+
console.log('');
|
|
351
|
+
console.log(chalk_1.default.cyan.bold('╔═══════════════════════════════════════╗'));
|
|
352
|
+
console.log(chalk_1.default.cyan.bold('║ 🧠 ekkOS Memory System Setup ║'));
|
|
353
|
+
console.log(chalk_1.default.cyan.bold('╚═══════════════════════════════════════╝'));
|
|
354
|
+
console.log('');
|
|
355
|
+
// Check templates exist
|
|
356
|
+
if (!(0, templates_1.templatesExist)()) {
|
|
357
|
+
console.log(chalk_1.default.red('Error: Templates not found.'));
|
|
358
|
+
console.log(chalk_1.default.gray('Please ensure the ekkOS CLI is installed correctly.'));
|
|
359
|
+
process.exit(1);
|
|
360
|
+
}
|
|
361
|
+
// Check for existing config
|
|
362
|
+
let existingConfig = null;
|
|
363
|
+
if ((0, fs_1.existsSync)(platform_1.EKKOS_CONFIG)) {
|
|
364
|
+
try {
|
|
365
|
+
existingConfig = JSON.parse((0, fs_1.readFileSync)(platform_1.EKKOS_CONFIG, 'utf-8'));
|
|
366
|
+
}
|
|
367
|
+
catch { }
|
|
368
|
+
}
|
|
369
|
+
// STEP 1: Authentication
|
|
370
|
+
let auth;
|
|
371
|
+
if (options.key) {
|
|
372
|
+
// Manual API key provided
|
|
373
|
+
auth = await manualKeyAuth(options.key);
|
|
374
|
+
}
|
|
375
|
+
else if (existingConfig?.apiKey && !options.force) {
|
|
376
|
+
// Already authenticated
|
|
377
|
+
console.log(chalk_1.default.cyan('Step 1/3: Authentication'));
|
|
378
|
+
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
379
|
+
console.log('');
|
|
380
|
+
console.log(chalk_1.default.green(`✓ Already authenticated as ${chalk_1.default.bold(existingConfig.email || 'unknown')}`));
|
|
381
|
+
console.log(chalk_1.default.gray(' (use --force to re-authenticate)'));
|
|
382
|
+
console.log('');
|
|
383
|
+
auth = {
|
|
384
|
+
apiKey: existingConfig.apiKey,
|
|
385
|
+
userId: existingConfig.userId || 'unknown',
|
|
386
|
+
email: existingConfig.email || 'unknown',
|
|
387
|
+
tier: existingConfig.tier || 'unknown'
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// Device auth flow
|
|
392
|
+
try {
|
|
393
|
+
auth = await deviceAuth();
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
console.log(chalk_1.default.red(`\nAuthentication failed: ${error}`));
|
|
397
|
+
console.log(chalk_1.default.gray('\nTry again or use --key to provide an API key manually.'));
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
// STEP 2: IDE Selection
|
|
402
|
+
let selectedIDEs;
|
|
403
|
+
if (options.ide) {
|
|
404
|
+
if (options.ide === 'all') {
|
|
405
|
+
selectedIDEs = (0, platform_1.detectInstalledIDEs)();
|
|
406
|
+
if (selectedIDEs.length === 0) {
|
|
407
|
+
selectedIDEs = ['claude']; // Default to Claude Code
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
selectedIDEs = [options.ide];
|
|
412
|
+
}
|
|
413
|
+
console.log(chalk_1.default.cyan('Step 2/3: IDE Setup'));
|
|
414
|
+
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
415
|
+
console.log('');
|
|
416
|
+
console.log(chalk_1.default.gray(`Configuring: ${selectedIDEs.join(', ')}`));
|
|
417
|
+
console.log('');
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
selectedIDEs = await selectIDEs();
|
|
421
|
+
}
|
|
422
|
+
// STEP 3: Deployment
|
|
423
|
+
console.log(chalk_1.default.cyan('Step 3/3: Deploying'));
|
|
424
|
+
console.log(chalk_1.default.gray('─'.repeat(40)));
|
|
425
|
+
console.log('');
|
|
426
|
+
const installedIDEs = [];
|
|
427
|
+
for (const ide of selectedIDEs) {
|
|
428
|
+
if (ide === 'claude') {
|
|
429
|
+
const result = await deployForClaude(auth.apiKey, auth.userId, options);
|
|
430
|
+
if (result.mcp || result.hooks.count > 0) {
|
|
431
|
+
installedIDEs.push('claude');
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
else if (ide === 'cursor') {
|
|
435
|
+
if (await deployForCursor(auth.apiKey, auth.userId)) {
|
|
436
|
+
installedIDEs.push('cursor');
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
else if (ide === 'windsurf') {
|
|
440
|
+
if (await deployForWindsurf(auth.apiKey, auth.userId)) {
|
|
441
|
+
installedIDEs.push('windsurf');
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// Save config
|
|
446
|
+
if (!(0, fs_1.existsSync)(platform_1.EKKOS_DIR)) {
|
|
447
|
+
(0, fs_1.mkdirSync)(platform_1.EKKOS_DIR, { recursive: true });
|
|
448
|
+
}
|
|
449
|
+
const config = {
|
|
450
|
+
apiKey: auth.apiKey,
|
|
451
|
+
userId: auth.userId,
|
|
452
|
+
email: auth.email,
|
|
453
|
+
tier: auth.tier,
|
|
454
|
+
createdAt: new Date().toISOString(),
|
|
455
|
+
installedIDEs
|
|
456
|
+
};
|
|
457
|
+
(0, fs_1.writeFileSync)(platform_1.EKKOS_CONFIG, JSON.stringify(config, null, 2));
|
|
458
|
+
(0, fs_1.chmodSync)(platform_1.EKKOS_CONFIG, '600'); // Secure permissions
|
|
459
|
+
// Summary
|
|
460
|
+
console.log('');
|
|
461
|
+
console.log(chalk_1.default.gray('═'.repeat(40)));
|
|
462
|
+
console.log(chalk_1.default.green.bold('✓ Setup complete!'));
|
|
463
|
+
console.log(chalk_1.default.gray('═'.repeat(40)));
|
|
464
|
+
console.log('');
|
|
465
|
+
if (installedIDEs.includes('claude')) {
|
|
466
|
+
console.log(chalk_1.default.yellow('→ Restart Claude Code to activate ekkOS'));
|
|
467
|
+
}
|
|
468
|
+
if (installedIDEs.includes('cursor')) {
|
|
469
|
+
console.log(chalk_1.default.yellow('→ Restart Cursor to activate ekkOS'));
|
|
470
|
+
}
|
|
471
|
+
if (installedIDEs.includes('windsurf')) {
|
|
472
|
+
console.log(chalk_1.default.yellow('→ Restart Windsurf to activate ekkOS'));
|
|
473
|
+
}
|
|
474
|
+
console.log('');
|
|
475
|
+
console.log(chalk_1.default.gray(`Run ${chalk_1.default.white('ekkos status')} to verify installation`));
|
|
476
|
+
console.log(chalk_1.default.gray(`View dashboard: ${chalk_1.default.white('https://platform.ekkos.dev/dashboard')}`));
|
|
477
|
+
console.log('');
|
|
478
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface RunOptions {
|
|
2
|
+
session?: string;
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
bypass?: boolean;
|
|
5
|
+
slashOpenDelayMs?: number;
|
|
6
|
+
charDelayMs?: number;
|
|
7
|
+
postEnterDelayMs?: number;
|
|
8
|
+
clearWaitMs?: number;
|
|
9
|
+
debugLogPath?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function run(options: RunOptions): Promise<void>;
|
|
12
|
+
export {};
|