@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,658 @@
|
|
|
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.setup = setup;
|
|
7
|
+
const os_1 = require("os");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
12
|
+
const ora_1 = __importDefault(require("ora"));
|
|
13
|
+
const EKKOS_API_URL = 'https://mcp.ekkos.dev';
|
|
14
|
+
const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.ekkos');
|
|
15
|
+
const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, 'config.json');
|
|
16
|
+
/**
|
|
17
|
+
* Auto-detect which IDE the user is running in
|
|
18
|
+
*/
|
|
19
|
+
function detectIDE() {
|
|
20
|
+
// Check TERM_PROGRAM environment variable (set by many terminals/IDEs)
|
|
21
|
+
const termProgram = process.env.TERM_PROGRAM?.toLowerCase() || '';
|
|
22
|
+
const termEmulator = process.env.TERMINAL_EMULATOR?.toLowerCase() || '';
|
|
23
|
+
const colorterm = process.env.COLORTERM?.toLowerCase() || '';
|
|
24
|
+
// Cursor sets TERM_PROGRAM
|
|
25
|
+
if (termProgram.includes('cursor')) {
|
|
26
|
+
return 'cursor';
|
|
27
|
+
}
|
|
28
|
+
// VSCode sets TERM_PROGRAM to "vscode"
|
|
29
|
+
if (termProgram.includes('vscode') || termEmulator.includes('vscode')) {
|
|
30
|
+
return 'vscode';
|
|
31
|
+
}
|
|
32
|
+
// Windsurf/Codeium detection
|
|
33
|
+
if (termProgram.includes('windsurf') || termProgram.includes('codeium')) {
|
|
34
|
+
return 'windsurf';
|
|
35
|
+
}
|
|
36
|
+
// Check for Windsurf by config directory existence (if recently used)
|
|
37
|
+
const windsurfConfig = (0, path_1.join)((0, os_1.homedir)(), '.codeium', 'windsurf');
|
|
38
|
+
if ((0, fs_1.existsSync)(windsurfConfig)) {
|
|
39
|
+
// Also check if there's activity (mcp_config.json exists or was modified recently)
|
|
40
|
+
const mcpConfig = (0, path_1.join)(windsurfConfig, 'mcp_config.json');
|
|
41
|
+
if ((0, fs_1.existsSync)(mcpConfig)) {
|
|
42
|
+
// Windsurf is installed and configured - suggest it
|
|
43
|
+
// But don't return it as definitive without env var
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Check for Claude Code by looking at parent process or specific env vars
|
|
47
|
+
// Claude Code typically runs in a terminal context
|
|
48
|
+
if (process.env.CLAUDE_CODE || process.env.ANTHROPIC_API_KEY) {
|
|
49
|
+
return 'claude-code';
|
|
50
|
+
}
|
|
51
|
+
// Check ~/.claude directory for Claude Code usage
|
|
52
|
+
const claudeDir = (0, path_1.join)((0, os_1.homedir)(), '.claude');
|
|
53
|
+
if ((0, fs_1.existsSync)(claudeDir)) {
|
|
54
|
+
const hooksDir = (0, path_1.join)(claudeDir, 'hooks');
|
|
55
|
+
if ((0, fs_1.existsSync)(hooksDir)) {
|
|
56
|
+
// Claude Code has been set up before
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check for cursor config directory
|
|
60
|
+
const cursorDir = (0, path_1.join)((0, os_1.homedir)(), '.cursor');
|
|
61
|
+
if ((0, fs_1.existsSync)(cursorDir)) {
|
|
62
|
+
// Cursor is installed
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
async function setup(options) {
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log(chalk_1.default.cyan.bold('🧠 ekkOS Setup'));
|
|
69
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
70
|
+
console.log('');
|
|
71
|
+
// Get API key
|
|
72
|
+
let apiKey = options.key || process.env.EKKOS_API_KEY;
|
|
73
|
+
if (!apiKey) {
|
|
74
|
+
console.log(chalk_1.default.yellow('Get your API key from: https://ekkos.dev/dashboard/keys'));
|
|
75
|
+
console.log('');
|
|
76
|
+
const answers = await inquirer_1.default.prompt([
|
|
77
|
+
{
|
|
78
|
+
type: 'password',
|
|
79
|
+
name: 'apiKey',
|
|
80
|
+
message: 'Enter your ekkOS API key:',
|
|
81
|
+
mask: '*',
|
|
82
|
+
validate: (input) => {
|
|
83
|
+
if (!input || input.length < 10) {
|
|
84
|
+
return 'Please enter a valid API key';
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
]);
|
|
90
|
+
apiKey = answers.apiKey;
|
|
91
|
+
}
|
|
92
|
+
// Verify API key
|
|
93
|
+
const spinner = (0, ora_1.default)('Verifying API key...').start();
|
|
94
|
+
try {
|
|
95
|
+
const response = await fetch(`${EKKOS_API_URL}/api/v1/patterns/query`, {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: {
|
|
98
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
99
|
+
'Content-Type': 'application/json'
|
|
100
|
+
},
|
|
101
|
+
body: JSON.stringify({ query: 'test', k: 1 })
|
|
102
|
+
});
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
spinner.fail('Invalid API key');
|
|
105
|
+
console.log(chalk_1.default.red('Please check your API key and try again.'));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
spinner.succeed('API key verified');
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
spinner.fail('Could not connect to ekkOS');
|
|
112
|
+
console.log(chalk_1.default.red('Check your internet connection and try again.'));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
// Save config
|
|
116
|
+
if (!(0, fs_1.existsSync)(CONFIG_DIR)) {
|
|
117
|
+
(0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
const config = {
|
|
120
|
+
apiKey: apiKey,
|
|
121
|
+
installedIDEs: [],
|
|
122
|
+
installedAt: new Date().toISOString()
|
|
123
|
+
};
|
|
124
|
+
// Determine which IDE to setup
|
|
125
|
+
let ideToSetup;
|
|
126
|
+
if (options.ide === 'all') {
|
|
127
|
+
// Try to auto-detect the IDE
|
|
128
|
+
const detectedIDE = detectIDE();
|
|
129
|
+
if (detectedIDE) {
|
|
130
|
+
console.log(chalk_1.default.green(`✓ Detected IDE: ${detectedIDE}`));
|
|
131
|
+
console.log('');
|
|
132
|
+
}
|
|
133
|
+
const ideAnswers = await inquirer_1.default.prompt([
|
|
134
|
+
{
|
|
135
|
+
type: 'list',
|
|
136
|
+
name: 'ide',
|
|
137
|
+
message: 'Which IDE are you setting up?',
|
|
138
|
+
choices: [
|
|
139
|
+
{ name: 'Claude Code (CLI)', value: 'claude-code' },
|
|
140
|
+
{ name: 'Cursor', value: 'cursor' },
|
|
141
|
+
{ name: 'Windsurf (Cascade)', value: 'windsurf' },
|
|
142
|
+
{ name: 'VSCode (Copilot)', value: 'vscode' }
|
|
143
|
+
],
|
|
144
|
+
default: detectedIDE || 'cursor'
|
|
145
|
+
}
|
|
146
|
+
]);
|
|
147
|
+
ideToSetup = ideAnswers.ide;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
ideToSetup = options.ide;
|
|
151
|
+
}
|
|
152
|
+
console.log('');
|
|
153
|
+
// Setup the selected IDE
|
|
154
|
+
await setupIDE(ideToSetup, apiKey, config);
|
|
155
|
+
// Save final config
|
|
156
|
+
(0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
157
|
+
// Summary
|
|
158
|
+
console.log('');
|
|
159
|
+
console.log(chalk_1.default.green.bold('✅ Setup complete!'));
|
|
160
|
+
console.log('');
|
|
161
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
162
|
+
console.log('');
|
|
163
|
+
console.log('Configured IDEs:');
|
|
164
|
+
for (const ide of config.installedIDEs) {
|
|
165
|
+
console.log(chalk_1.default.cyan(` • ${ide}`));
|
|
166
|
+
}
|
|
167
|
+
console.log('');
|
|
168
|
+
console.log('Next steps:');
|
|
169
|
+
console.log(chalk_1.default.gray(' 1. Open your IDE'));
|
|
170
|
+
console.log(chalk_1.default.gray(' 2. Start coding - memory is now active'));
|
|
171
|
+
console.log(chalk_1.default.gray(' 3. Watch patterns form as you work'));
|
|
172
|
+
console.log('');
|
|
173
|
+
console.log(chalk_1.default.cyan('View your memory at: https://ekkos.dev/dashboard'));
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
async function setupIDE(ide, apiKey, config) {
|
|
177
|
+
const spinner = (0, ora_1.default)(`Setting up ${ide}...`).start();
|
|
178
|
+
try {
|
|
179
|
+
switch (ide) {
|
|
180
|
+
case 'claude-code':
|
|
181
|
+
await setupClaudeCode(apiKey);
|
|
182
|
+
break;
|
|
183
|
+
case 'cursor':
|
|
184
|
+
await setupCursor(apiKey);
|
|
185
|
+
break;
|
|
186
|
+
case 'windsurf':
|
|
187
|
+
await setupWindsurf(apiKey);
|
|
188
|
+
break;
|
|
189
|
+
case 'vscode':
|
|
190
|
+
await setupVSCode(apiKey);
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
spinner.warn(`Unknown IDE: ${ide}`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
config.installedIDEs.push(ide);
|
|
197
|
+
spinner.succeed(`${ide} configured`);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
spinner.fail(`Failed to setup ${ide}: ${error}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function setupClaudeCode(apiKey) {
|
|
204
|
+
const claudeDir = (0, path_1.join)((0, os_1.homedir)(), '.claude');
|
|
205
|
+
const hooksDir = (0, path_1.join)(claudeDir, 'hooks');
|
|
206
|
+
if (!(0, fs_1.existsSync)(hooksDir)) {
|
|
207
|
+
(0, fs_1.mkdirSync)(hooksDir, { recursive: true });
|
|
208
|
+
}
|
|
209
|
+
const isWindows = (0, os_1.platform)() === 'win32';
|
|
210
|
+
if (isWindows) {
|
|
211
|
+
// Windows: PowerShell hooks
|
|
212
|
+
const promptSubmitHook = generatePromptSubmitHookPS(apiKey);
|
|
213
|
+
const promptSubmitPath = (0, path_1.join)(hooksDir, 'user-prompt-submit.ps1');
|
|
214
|
+
(0, fs_1.writeFileSync)(promptSubmitPath, promptSubmitHook);
|
|
215
|
+
const stopHook = generateStopHookPS(apiKey);
|
|
216
|
+
const stopPath = (0, path_1.join)(hooksDir, 'stop.ps1');
|
|
217
|
+
(0, fs_1.writeFileSync)(stopPath, stopHook);
|
|
218
|
+
// Create wrapper batch files for Windows
|
|
219
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(hooksDir, 'user-prompt-submit.cmd'), `@echo off\npowershell -ExecutionPolicy Bypass -File "%~dp0user-prompt-submit.ps1"`);
|
|
220
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(hooksDir, 'stop.cmd'), `@echo off\npowershell -ExecutionPolicy Bypass -File "%~dp0stop.ps1"`);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
// Unix: Bash hooks
|
|
224
|
+
const promptSubmitHook = generatePromptSubmitHook(apiKey);
|
|
225
|
+
const promptSubmitPath = (0, path_1.join)(hooksDir, 'user-prompt-submit.sh');
|
|
226
|
+
(0, fs_1.writeFileSync)(promptSubmitPath, promptSubmitHook);
|
|
227
|
+
(0, fs_1.chmodSync)(promptSubmitPath, '755');
|
|
228
|
+
const stopHook = generateStopHook(apiKey);
|
|
229
|
+
const stopPath = (0, path_1.join)(hooksDir, 'stop.sh');
|
|
230
|
+
(0, fs_1.writeFileSync)(stopPath, stopHook);
|
|
231
|
+
(0, fs_1.chmodSync)(stopPath, '755');
|
|
232
|
+
}
|
|
233
|
+
// Create state directory
|
|
234
|
+
const stateDir = (0, path_1.join)(claudeDir, 'state');
|
|
235
|
+
if (!(0, fs_1.existsSync)(stateDir)) {
|
|
236
|
+
(0, fs_1.mkdirSync)(stateDir, { recursive: true });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function setupCursor(apiKey) {
|
|
240
|
+
// Cursor uses .cursorrules for system prompt
|
|
241
|
+
// and MCP servers for tools
|
|
242
|
+
const cursorDir = (0, path_1.join)((0, os_1.homedir)(), '.cursor');
|
|
243
|
+
if (!(0, fs_1.existsSync)(cursorDir)) {
|
|
244
|
+
(0, fs_1.mkdirSync)(cursorDir, { recursive: true });
|
|
245
|
+
}
|
|
246
|
+
// Create/update MCP settings
|
|
247
|
+
const mcpConfigPath = (0, path_1.join)(cursorDir, 'mcp.json');
|
|
248
|
+
let mcpConfig = {};
|
|
249
|
+
if ((0, fs_1.existsSync)(mcpConfigPath)) {
|
|
250
|
+
try {
|
|
251
|
+
mcpConfig = JSON.parse((0, fs_1.readFileSync)(mcpConfigPath, 'utf-8'));
|
|
252
|
+
}
|
|
253
|
+
catch { }
|
|
254
|
+
}
|
|
255
|
+
mcpConfig.mcpServers = mcpConfig.mcpServers || {};
|
|
256
|
+
mcpConfig.mcpServers['ekkos-memory'] = {
|
|
257
|
+
command: 'npx',
|
|
258
|
+
args: ['@ekkos/mcp-server'],
|
|
259
|
+
env: {
|
|
260
|
+
EKKOS_API_KEY: apiKey
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
(0, fs_1.writeFileSync)(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
|
|
264
|
+
// Create .cursorrules template in current directory
|
|
265
|
+
const cursorRules = generateCursorRules();
|
|
266
|
+
const cursorRulesPath = (0, path_1.join)(process.cwd(), '.cursorrules');
|
|
267
|
+
if (!(0, fs_1.existsSync)(cursorRulesPath)) {
|
|
268
|
+
(0, fs_1.writeFileSync)(cursorRulesPath, cursorRules);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async function setupWindsurf(apiKey) {
|
|
272
|
+
// Windsurf (Codeium) supports MCP servers like Cursor
|
|
273
|
+
// Config location: ~/.codeium/windsurf/mcp_config.json
|
|
274
|
+
const codeiumDir = (0, path_1.join)((0, os_1.homedir)(), '.codeium', 'windsurf');
|
|
275
|
+
if (!(0, fs_1.existsSync)(codeiumDir)) {
|
|
276
|
+
(0, fs_1.mkdirSync)(codeiumDir, { recursive: true });
|
|
277
|
+
}
|
|
278
|
+
// Create/update MCP config for Windsurf
|
|
279
|
+
const mcpConfigPath = (0, path_1.join)(codeiumDir, 'mcp_config.json');
|
|
280
|
+
let mcpConfig = { mcpServers: {} };
|
|
281
|
+
if ((0, fs_1.existsSync)(mcpConfigPath)) {
|
|
282
|
+
try {
|
|
283
|
+
mcpConfig = JSON.parse((0, fs_1.readFileSync)(mcpConfigPath, 'utf-8'));
|
|
284
|
+
mcpConfig.mcpServers = mcpConfig.mcpServers || {};
|
|
285
|
+
}
|
|
286
|
+
catch { }
|
|
287
|
+
}
|
|
288
|
+
// Add ekkOS cloud MCP server (HTTP transport)
|
|
289
|
+
mcpConfig.mcpServers['ekkos-memory'] = {
|
|
290
|
+
serverUrl: 'https://mcp.ekkos.dev',
|
|
291
|
+
disabled: false,
|
|
292
|
+
alwaysAllow: [],
|
|
293
|
+
headers: {
|
|
294
|
+
'Authorization': `Bearer ${apiKey}`
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
(0, fs_1.writeFileSync)(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
|
|
298
|
+
// Also save to legacy location for backwards compat
|
|
299
|
+
const windsurfDir = (0, path_1.join)((0, os_1.homedir)(), '.windsurf');
|
|
300
|
+
if (!(0, fs_1.existsSync)(windsurfDir)) {
|
|
301
|
+
(0, fs_1.mkdirSync)(windsurfDir, { recursive: true });
|
|
302
|
+
}
|
|
303
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(windsurfDir, 'ekkos.json'), JSON.stringify({ apiKey }, null, 2));
|
|
304
|
+
// Create project rules template
|
|
305
|
+
const cascadeRules = generateCascadeRules();
|
|
306
|
+
const cascadeRulesPath = (0, path_1.join)(process.cwd(), '.windsurfrules');
|
|
307
|
+
if (!(0, fs_1.existsSync)(cascadeRulesPath)) {
|
|
308
|
+
(0, fs_1.writeFileSync)(cascadeRulesPath, cascadeRules);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async function setupVSCode(apiKey) {
|
|
312
|
+
// VSCode - create settings for Copilot/Continue
|
|
313
|
+
const vscodeDir = (0, path_1.join)((0, os_1.homedir)(), '.vscode');
|
|
314
|
+
if (!(0, fs_1.existsSync)(vscodeDir)) {
|
|
315
|
+
(0, fs_1.mkdirSync)(vscodeDir, { recursive: true });
|
|
316
|
+
}
|
|
317
|
+
// Save config
|
|
318
|
+
const configPath = (0, path_1.join)(vscodeDir, 'ekkos.json');
|
|
319
|
+
(0, fs_1.writeFileSync)(configPath, JSON.stringify({ apiKey }, null, 2));
|
|
320
|
+
// Note: Full VSCode integration requires extension
|
|
321
|
+
console.log(chalk_1.default.yellow(' Note: VSCode requires the ekkOS extension for full integration'));
|
|
322
|
+
}
|
|
323
|
+
function generatePromptSubmitHook(apiKey) {
|
|
324
|
+
return `#!/bin/bash
|
|
325
|
+
# ekkOS Hook: UserPromptSubmit
|
|
326
|
+
# Golden Loop: RETRIEVE → INJECT
|
|
327
|
+
|
|
328
|
+
set -e
|
|
329
|
+
|
|
330
|
+
EKKOS_API_KEY="${apiKey}"
|
|
331
|
+
MEMORY_API_URL="https://mcp.ekkos.dev"
|
|
332
|
+
STATE_DIR="$HOME/.claude/state"
|
|
333
|
+
mkdir -p "$STATE_DIR"
|
|
334
|
+
|
|
335
|
+
INPUT=$(cat)
|
|
336
|
+
USER_QUERY=$(echo "$INPUT" | jq -r '.query // .message // .prompt // ""')
|
|
337
|
+
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
|
|
338
|
+
MODEL_INFO=$(echo "$INPUT" | jq -r '.model // "claude-sonnet-4-5"')
|
|
339
|
+
|
|
340
|
+
if [ -z "$USER_QUERY" ] || [ "$USER_QUERY" = "null" ]; then
|
|
341
|
+
exit 0
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
TASK_ID="task-\${SESSION_ID}-$(date +%s)"
|
|
345
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
346
|
+
|
|
347
|
+
echo ""
|
|
348
|
+
echo "[ekkOS_RETRIEVE] Searching memory..."
|
|
349
|
+
|
|
350
|
+
JSON_PAYLOAD=$(cat << EOF
|
|
351
|
+
{
|
|
352
|
+
"query": $(echo "$USER_QUERY" | jq -R -s .),
|
|
353
|
+
"k": 5,
|
|
354
|
+
"model_used": "$MODEL_INFO"
|
|
355
|
+
}
|
|
356
|
+
EOF
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
API_RESPONSE=$(curl -s -X POST "$MEMORY_API_URL/api/v1/patterns/query" \\
|
|
360
|
+
-H "Authorization: Bearer $EKKOS_API_KEY" \\
|
|
361
|
+
-H "Content-Type: application/json" \\
|
|
362
|
+
-d "$JSON_PAYLOAD" \\
|
|
363
|
+
--connect-timeout 3 \\
|
|
364
|
+
--max-time 5 2>/dev/null || echo '{"patterns":[]}')
|
|
365
|
+
|
|
366
|
+
PATTERNS=$(echo "$API_RESPONSE" | jq '.patterns // []' 2>/dev/null || echo "[]")
|
|
367
|
+
PATTERN_COUNT=$(echo "$PATTERNS" | jq 'length' 2>/dev/null || echo "0")
|
|
368
|
+
|
|
369
|
+
if [ "$PATTERN_COUNT" -gt 0 ]; then
|
|
370
|
+
echo "[ekkOS_RETRIEVE] Found $PATTERN_COUNT patterns"
|
|
371
|
+
else
|
|
372
|
+
echo "[ekkOS_RETRIEVE] No patterns found (building memory)"
|
|
373
|
+
fi
|
|
374
|
+
|
|
375
|
+
# Store state
|
|
376
|
+
PATTERN_DATA=$(cat << EOF
|
|
377
|
+
{
|
|
378
|
+
"patterns": $PATTERNS,
|
|
379
|
+
"model_used": "$MODEL_INFO",
|
|
380
|
+
"task_id": "$TASK_ID",
|
|
381
|
+
"retrieved_at": "$TIMESTAMP",
|
|
382
|
+
"query": $(echo "$USER_QUERY" | jq -R -s .)
|
|
383
|
+
}
|
|
384
|
+
EOF
|
|
385
|
+
)
|
|
386
|
+
echo "$PATTERN_DATA" > "$STATE_DIR/patterns-\${SESSION_ID}.json"
|
|
387
|
+
|
|
388
|
+
# Display patterns
|
|
389
|
+
if [ "$PATTERN_COUNT" -gt 0 ]; then
|
|
390
|
+
AVG_SUCCESS=$(echo "$PATTERNS" | jq '[.[].success_rate // 0.9] | add / length * 100 | round' 2>/dev/null || echo "90")
|
|
391
|
+
echo "[ekkOS_INJECT] Loading $PATTERN_COUNT patterns (\${AVG_SUCCESS}% avg success)"
|
|
392
|
+
echo ""
|
|
393
|
+
|
|
394
|
+
echo "$PATTERNS" | jq -c '.[:5] | .[]' 2>/dev/null | while read -r pattern; do
|
|
395
|
+
TITLE=$(echo "$pattern" | jq -r '.title // "Untitled"')
|
|
396
|
+
SUCCESS_RATE=$(echo "$pattern" | jq -r 'if .success_rate then (.success_rate * 100 | round | tostring) + "%" else "~80%" end')
|
|
397
|
+
APPLIED_COUNT=$(echo "$pattern" | jq -r '.applied_count // 0')
|
|
398
|
+
GUIDANCE=$(echo "$pattern" | jq -r '.guidance // .content // "No guidance"')
|
|
399
|
+
|
|
400
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
401
|
+
echo "🧠 PATTERN: \\"$TITLE\\""
|
|
402
|
+
echo " Applied \${APPLIED_COUNT}x | \${SUCCESS_RATE} success"
|
|
403
|
+
echo ""
|
|
404
|
+
echo " $GUIDANCE" | head -c 500
|
|
405
|
+
echo ""
|
|
406
|
+
done
|
|
407
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
408
|
+
fi
|
|
409
|
+
|
|
410
|
+
echo ""
|
|
411
|
+
echo "[ekkOS_LEARN] 🔥 FORGE new patterns when you solve something!"
|
|
412
|
+
echo ""
|
|
413
|
+
|
|
414
|
+
exit 0
|
|
415
|
+
`;
|
|
416
|
+
}
|
|
417
|
+
function generateStopHook(apiKey) {
|
|
418
|
+
return `#!/bin/bash
|
|
419
|
+
# ekkOS Hook: Stop
|
|
420
|
+
# Golden Loop: CAPTURE → MEASURE
|
|
421
|
+
|
|
422
|
+
set -e
|
|
423
|
+
|
|
424
|
+
EKKOS_API_KEY="${apiKey}"
|
|
425
|
+
MEMORY_API_URL="https://mcp.ekkos.dev"
|
|
426
|
+
STATE_DIR="$HOME/.claude/state"
|
|
427
|
+
|
|
428
|
+
INPUT=$(cat)
|
|
429
|
+
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
|
|
430
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
431
|
+
|
|
432
|
+
PATTERNS_FILE="$STATE_DIR/patterns-\${SESSION_ID}.json"
|
|
433
|
+
PATTERN_COUNT=0
|
|
434
|
+
|
|
435
|
+
if [ -f "$PATTERNS_FILE" ]; then
|
|
436
|
+
STORED_DATA=$(cat "$PATTERNS_FILE" 2>/dev/null || echo "{}")
|
|
437
|
+
PATTERNS=$(echo "$STORED_DATA" | jq '.patterns // []' 2>/dev/null || echo "[]")
|
|
438
|
+
PATTERN_COUNT=$(echo "$PATTERNS" | jq 'length' 2>/dev/null || echo "0")
|
|
439
|
+
fi
|
|
440
|
+
|
|
441
|
+
echo ""
|
|
442
|
+
echo "[ekkOS_CAPTURE] ✓ Session saved"
|
|
443
|
+
|
|
444
|
+
if [ "$PATTERN_COUNT" -gt 0 ]; then
|
|
445
|
+
echo "[ekkOS_MEASURE] ✓ Tracked $PATTERN_COUNT patterns"
|
|
446
|
+
fi
|
|
447
|
+
|
|
448
|
+
rm -f "$PATTERNS_FILE" 2>/dev/null
|
|
449
|
+
|
|
450
|
+
echo ""
|
|
451
|
+
echo "┌─────────────────────────────────────────────┐"
|
|
452
|
+
echo "│ ekkOS_ GOLDEN LOOP COMPLETE │"
|
|
453
|
+
echo "│ The system learns from every interaction. │"
|
|
454
|
+
echo "└─────────────────────────────────────────────┘"
|
|
455
|
+
echo ""
|
|
456
|
+
|
|
457
|
+
exit 0
|
|
458
|
+
`;
|
|
459
|
+
}
|
|
460
|
+
function generateCursorRules() {
|
|
461
|
+
return `# ekkOS Golden Loop Integration
|
|
462
|
+
|
|
463
|
+
## Memory System Active
|
|
464
|
+
|
|
465
|
+
Before responding, check ekkOS memory for relevant patterns using the MCP tools:
|
|
466
|
+
- \`ekkOS_Search\` - Find patterns that match the current problem
|
|
467
|
+
- \`ekkOS_Forge\` - Save new patterns when you solve something
|
|
468
|
+
|
|
469
|
+
## When to FORGE New Patterns
|
|
470
|
+
|
|
471
|
+
Use \`ekkOS_Forge\` when you:
|
|
472
|
+
- Fixed a non-obvious bug
|
|
473
|
+
- Found a better approach
|
|
474
|
+
- Discovered a pitfall
|
|
475
|
+
- User corrected you
|
|
476
|
+
|
|
477
|
+
## Pattern Application
|
|
478
|
+
|
|
479
|
+
When you use a pattern from memory:
|
|
480
|
+
\`\`\`
|
|
481
|
+
[ekkOS_APPLY] Using: "Pattern Name"
|
|
482
|
+
\`\`\`
|
|
483
|
+
|
|
484
|
+
This is how ekkOS learns and improves over time.
|
|
485
|
+
`;
|
|
486
|
+
}
|
|
487
|
+
function generateCascadeRules() {
|
|
488
|
+
return `# ekkOS Memory Integration for Windsurf
|
|
489
|
+
|
|
490
|
+
## Active Learning
|
|
491
|
+
|
|
492
|
+
This project uses ekkOS for persistent AI memory.
|
|
493
|
+
|
|
494
|
+
When solving problems:
|
|
495
|
+
1. Check if similar patterns exist in memory
|
|
496
|
+
2. Apply proven solutions when they match
|
|
497
|
+
3. Create new patterns when you solve something novel
|
|
498
|
+
|
|
499
|
+
## Creating Patterns
|
|
500
|
+
|
|
501
|
+
When you solve a problem that others might encounter:
|
|
502
|
+
- Document the problem clearly
|
|
503
|
+
- Explain the solution
|
|
504
|
+
- Note any anti-patterns to avoid
|
|
505
|
+
|
|
506
|
+
The system learns from every interaction.
|
|
507
|
+
`;
|
|
508
|
+
}
|
|
509
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
510
|
+
// WINDOWS POWERSHELL HOOKS
|
|
511
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
512
|
+
function generatePromptSubmitHookPS(apiKey) {
|
|
513
|
+
return `# ekkOS Hook: UserPromptSubmit (Windows PowerShell)
|
|
514
|
+
# Golden Loop: RETRIEVE → INJECT
|
|
515
|
+
|
|
516
|
+
$ErrorActionPreference = "Stop"
|
|
517
|
+
|
|
518
|
+
$EKKOS_API_KEY = "${apiKey}"
|
|
519
|
+
$MEMORY_API_URL = "https://mcp.ekkos.dev"
|
|
520
|
+
$STATE_DIR = "$env:USERPROFILE\\.claude\\state"
|
|
521
|
+
|
|
522
|
+
if (!(Test-Path $STATE_DIR)) {
|
|
523
|
+
New-Item -ItemType Directory -Path $STATE_DIR -Force | Out-Null
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
$INPUT = $input | Out-String
|
|
527
|
+
$jsonInput = $INPUT | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
528
|
+
|
|
529
|
+
$USER_QUERY = if ($jsonInput.query) { $jsonInput.query } elseif ($jsonInput.message) { $jsonInput.message } elseif ($jsonInput.prompt) { $jsonInput.prompt } else { "" }
|
|
530
|
+
$SESSION_ID = if ($jsonInput.session_id) { $jsonInput.session_id } else { "unknown" }
|
|
531
|
+
$MODEL_INFO = if ($jsonInput.model) { $jsonInput.model } else { "claude-sonnet-4-5" }
|
|
532
|
+
|
|
533
|
+
if ([string]::IsNullOrEmpty($USER_QUERY)) {
|
|
534
|
+
exit 0
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
$TASK_ID = "claude-code-task-$SESSION_ID-$([DateTimeOffset]::Now.ToUnixTimeSeconds())"
|
|
538
|
+
$TIMESTAMP = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
539
|
+
|
|
540
|
+
Write-Host ""
|
|
541
|
+
Write-Host "[ekkOS_RETRIEVE] Searching memory..."
|
|
542
|
+
|
|
543
|
+
$body = @{
|
|
544
|
+
query = $USER_QUERY
|
|
545
|
+
k = 5
|
|
546
|
+
model_used = $MODEL_INFO
|
|
547
|
+
} | ConvertTo-Json
|
|
548
|
+
|
|
549
|
+
try {
|
|
550
|
+
$response = Invoke-RestMethod -Uri "$MEMORY_API_URL/api/v1/patterns/query" \`
|
|
551
|
+
-Method Post \`
|
|
552
|
+
-Headers @{ "Authorization" = "Bearer $EKKOS_API_KEY"; "Content-Type" = "application/json" } \`
|
|
553
|
+
-Body $body \`
|
|
554
|
+
-TimeoutSec 5
|
|
555
|
+
|
|
556
|
+
$PATTERNS = $response.patterns
|
|
557
|
+
$PATTERN_COUNT = if ($PATTERNS) { $PATTERNS.Count } else { 0 }
|
|
558
|
+
} catch {
|
|
559
|
+
$PATTERNS = @()
|
|
560
|
+
$PATTERN_COUNT = 0
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if ($PATTERN_COUNT -gt 0) {
|
|
564
|
+
Write-Host "[ekkOS_RETRIEVE] Found $PATTERN_COUNT patterns"
|
|
565
|
+
} else {
|
|
566
|
+
Write-Host "[ekkOS_RETRIEVE] No patterns found (new territory)"
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
# Store for stop hook
|
|
570
|
+
$PATTERN_DATA = @{
|
|
571
|
+
patterns = $PATTERNS
|
|
572
|
+
model_used = $MODEL_INFO
|
|
573
|
+
task_id = $TASK_ID
|
|
574
|
+
retrieved_at = $TIMESTAMP
|
|
575
|
+
query = $USER_QUERY.Substring(0, [Math]::Min($USER_QUERY.Length, 1000))
|
|
576
|
+
} | ConvertTo-Json -Depth 10
|
|
577
|
+
|
|
578
|
+
$PATTERN_DATA | Out-File -FilePath "$STATE_DIR\\patterns-$SESSION_ID.json" -Encoding UTF8
|
|
579
|
+
|
|
580
|
+
# Display patterns
|
|
581
|
+
if ($PATTERN_COUNT -gt 0) {
|
|
582
|
+
$rates = $PATTERNS | ForEach-Object { if ($_.success_rate) { $_.success_rate } else { 0.9 } }
|
|
583
|
+
$AVG_SUCCESS = [math]::Round(($rates | Measure-Object -Average).Average * 100)
|
|
584
|
+
|
|
585
|
+
Write-Host "[ekkOS_INJECT] Loading $PATTERN_COUNT patterns ($AVG_SUCCESS% avg success)"
|
|
586
|
+
Write-Host ""
|
|
587
|
+
|
|
588
|
+
$idx = 0
|
|
589
|
+
foreach ($pattern in $PATTERNS | Select-Object -First 5) {
|
|
590
|
+
$idx++
|
|
591
|
+
$TITLE = if ($pattern.title) { $pattern.title } else { "Untitled" }
|
|
592
|
+
$SUCCESS_RATE = if ($pattern.success_rate) { "$([math]::Round($pattern.success_rate * 100))%" } else { "~80%" }
|
|
593
|
+
$APPLIED_COUNT = if ($pattern.applied_count) { $pattern.applied_count } else { 0 }
|
|
594
|
+
|
|
595
|
+
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
596
|
+
Write-Host "🧠 LEARNED PATTERN #$idx: \`"$TITLE\`""
|
|
597
|
+
Write-Host " Applied $APPLIED_COUNT time(s) with $SUCCESS_RATE success rate"
|
|
598
|
+
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
599
|
+
Write-Host ""
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
Write-Host "[ekkOS_LEARN] 🔥 FORGE new patterns when you solve something!"
|
|
604
|
+
Write-Host ""
|
|
605
|
+
|
|
606
|
+
exit 0
|
|
607
|
+
`;
|
|
608
|
+
}
|
|
609
|
+
function generateStopHookPS(apiKey) {
|
|
610
|
+
return `# ekkOS Hook: Stop (Windows PowerShell)
|
|
611
|
+
# Golden Loop: CAPTURE → MEASURE
|
|
612
|
+
|
|
613
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
614
|
+
|
|
615
|
+
$EKKOS_API_KEY = "${apiKey}"
|
|
616
|
+
$MEMORY_API_URL = "https://mcp.ekkos.dev"
|
|
617
|
+
$STATE_DIR = "$env:USERPROFILE\\.claude\\state"
|
|
618
|
+
|
|
619
|
+
$INPUT = $input | Out-String
|
|
620
|
+
$jsonInput = $INPUT | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
621
|
+
|
|
622
|
+
$SESSION_ID = if ($jsonInput.session_id) { $jsonInput.session_id } else { "unknown" }
|
|
623
|
+
$TIMESTAMP = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
624
|
+
|
|
625
|
+
# Load patterns from RETRIEVE step
|
|
626
|
+
$PATTERNS_FILE = "$STATE_DIR\\patterns-$SESSION_ID.json"
|
|
627
|
+
$PATTERN_COUNT = 0
|
|
628
|
+
$PATTERNS = @()
|
|
629
|
+
|
|
630
|
+
if (Test-Path $PATTERNS_FILE) {
|
|
631
|
+
try {
|
|
632
|
+
$STORED_DATA = Get-Content $PATTERNS_FILE -Raw | ConvertFrom-Json
|
|
633
|
+
$PATTERNS = $STORED_DATA.patterns
|
|
634
|
+
$PATTERN_COUNT = if ($PATTERNS) { $PATTERNS.Count } else { 0 }
|
|
635
|
+
} catch {}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
Write-Host ""
|
|
639
|
+
Write-Host "[ekkOS_CAPTURE] ✓ Session saved"
|
|
640
|
+
|
|
641
|
+
if ($PATTERN_COUNT -gt 0) {
|
|
642
|
+
Write-Host "[ekkOS_MEASURE] ✓ Tracked $PATTERN_COUNT patterns"
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
# Cleanup
|
|
646
|
+
Remove-Item $PATTERNS_FILE -Force -ErrorAction SilentlyContinue
|
|
647
|
+
|
|
648
|
+
Write-Host ""
|
|
649
|
+
Write-Host "┌─────────────────────────────────────────────────────────────────┐"
|
|
650
|
+
Write-Host "│ ekkOS_ GOLDEN LOOP COMPLETE │"
|
|
651
|
+
Write-Host "├─────────────────────────────────────────────────────────────────┤"
|
|
652
|
+
Write-Host "│ The system learns from every interaction. │"
|
|
653
|
+
Write-Host "└─────────────────────────────────────────────────────────────────┘"
|
|
654
|
+
Write-Host ""
|
|
655
|
+
|
|
656
|
+
exit 0
|
|
657
|
+
`;
|
|
658
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function status(): Promise<void>;
|