@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.
Files changed (131) hide show
  1. package/dist/capture/jsonl-rewriter.d.ts +1 -1
  2. package/dist/capture/jsonl-rewriter.js +3 -3
  3. package/dist/capture/transcript-repair.d.ts +2 -2
  4. package/dist/capture/transcript-repair.js +2 -2
  5. package/dist/commands/claw.d.ts +13 -0
  6. package/dist/commands/claw.js +253 -0
  7. package/dist/commands/dashboard.js +742 -118
  8. package/dist/commands/doctor.d.ts +3 -3
  9. package/dist/commands/doctor.js +6 -79
  10. package/dist/commands/gemini.d.ts +19 -0
  11. package/dist/commands/gemini.js +193 -0
  12. package/dist/commands/init.d.ts +1 -0
  13. package/dist/commands/init.js +56 -41
  14. package/dist/commands/run.d.ts +0 -1
  15. package/dist/commands/run.js +288 -263
  16. package/dist/commands/scan.d.ts +21 -0
  17. package/dist/commands/scan.js +386 -0
  18. package/dist/commands/status.d.ts +4 -1
  19. package/dist/commands/status.js +165 -27
  20. package/dist/commands/swarm-dashboard.js +156 -28
  21. package/dist/commands/swarm.d.ts +1 -1
  22. package/dist/commands/swarm.js +1 -1
  23. package/dist/commands/test-claude.d.ts +2 -2
  24. package/dist/commands/test-claude.js +3 -3
  25. package/dist/deploy/index.d.ts +0 -2
  26. package/dist/deploy/index.js +0 -2
  27. package/dist/deploy/settings.d.ts +6 -5
  28. package/dist/deploy/settings.js +64 -16
  29. package/dist/deploy/skills.js +1 -2
  30. package/dist/index.js +86 -96
  31. package/dist/lib/usage-parser.d.ts +1 -1
  32. package/dist/lib/usage-parser.js +9 -6
  33. package/dist/local/index.d.ts +14 -0
  34. package/dist/local/index.js +28 -0
  35. package/dist/local/local-embeddings.d.ts +49 -0
  36. package/dist/local/local-embeddings.js +232 -0
  37. package/dist/local/offline-fallback.d.ts +44 -0
  38. package/dist/local/offline-fallback.js +159 -0
  39. package/dist/local/sqlite-store.d.ts +126 -0
  40. package/dist/local/sqlite-store.js +393 -0
  41. package/dist/local/sync-engine.d.ts +42 -0
  42. package/dist/local/sync-engine.js +223 -0
  43. package/dist/utils/platform.d.ts +5 -1
  44. package/dist/utils/platform.js +24 -4
  45. package/dist/utils/proxy-url.d.ts +21 -0
  46. package/dist/utils/proxy-url.js +34 -0
  47. package/dist/utils/state.d.ts +1 -1
  48. package/dist/utils/state.js +11 -3
  49. package/dist/utils/templates.js +1 -1
  50. package/package.json +11 -4
  51. package/templates/CLAUDE.md +49 -107
  52. package/dist/agent/daemon.d.ts +0 -130
  53. package/dist/agent/daemon.js +0 -606
  54. package/dist/agent/health-check.d.ts +0 -35
  55. package/dist/agent/health-check.js +0 -243
  56. package/dist/agent/pty-runner.d.ts +0 -53
  57. package/dist/agent/pty-runner.js +0 -190
  58. package/dist/commands/agent.d.ts +0 -50
  59. package/dist/commands/agent.js +0 -544
  60. package/dist/commands/setup-remote.d.ts +0 -20
  61. package/dist/commands/setup-remote.js +0 -582
  62. package/dist/utils/verify-remote-terminal.d.ts +0 -10
  63. package/dist/utils/verify-remote-terminal.js +0 -415
  64. package/templates/README.md +0 -378
  65. package/templates/claude-plugins/PHASE2_COMPLETION.md +0 -346
  66. package/templates/claude-plugins/PLUGIN_PROPOSALS.md +0 -1776
  67. package/templates/claude-plugins/README.md +0 -587
  68. package/templates/claude-plugins/agents/code-reviewer.json +0 -14
  69. package/templates/claude-plugins/agents/debug-detective.json +0 -15
  70. package/templates/claude-plugins/agents/git-companion.json +0 -14
  71. package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +0 -8
  72. package/templates/claude-plugins/blog-manager/commands/blog.md +0 -691
  73. package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +0 -8
  74. package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +0 -434
  75. package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +0 -8
  76. package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +0 -282
  77. package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +0 -8
  78. package/templates/claude-plugins/memory-lens/commands/memory-search.md +0 -181
  79. package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +0 -8
  80. package/templates/claude-plugins/pattern-coach/commands/forge.md +0 -365
  81. package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +0 -8
  82. package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +0 -582
  83. package/templates/claude-plugins-admin/AGENT_TEAM_PROPOSALS.md +0 -819
  84. package/templates/claude-plugins-admin/README.md +0 -446
  85. package/templates/claude-plugins-admin/autonomous-admin-agent/.claude-plugin/plugin.json +0 -8
  86. package/templates/claude-plugins-admin/autonomous-admin-agent/commands/agent.md +0 -595
  87. package/templates/claude-plugins-admin/backend-agent/.claude-plugin/plugin.json +0 -8
  88. package/templates/claude-plugins-admin/backend-agent/commands/backend.md +0 -798
  89. package/templates/claude-plugins-admin/deploy-guardian/.claude-plugin/plugin.json +0 -8
  90. package/templates/claude-plugins-admin/deploy-guardian/commands/deploy.md +0 -554
  91. package/templates/claude-plugins-admin/frontend-agent/.claude-plugin/plugin.json +0 -8
  92. package/templates/claude-plugins-admin/frontend-agent/commands/frontend.md +0 -881
  93. package/templates/claude-plugins-admin/mcp-server-manager/.claude-plugin/plugin.json +0 -8
  94. package/templates/claude-plugins-admin/mcp-server-manager/commands/mcp.md +0 -85
  95. package/templates/claude-plugins-admin/memory-system-monitor/.claude-plugin/plugin.json +0 -8
  96. package/templates/claude-plugins-admin/memory-system-monitor/commands/memory-health.md +0 -569
  97. package/templates/claude-plugins-admin/qa-agent/.claude-plugin/plugin.json +0 -8
  98. package/templates/claude-plugins-admin/qa-agent/commands/qa.md +0 -863
  99. package/templates/claude-plugins-admin/tech-lead-agent/.claude-plugin/plugin.json +0 -8
  100. package/templates/claude-plugins-admin/tech-lead-agent/commands/lead.md +0 -732
  101. package/templates/commands/continue.md +0 -47
  102. package/templates/cursor-rules/ekkos-memory.md +0 -127
  103. package/templates/ekkos-manifest.json +0 -223
  104. package/templates/helpers/json-parse.cjs +0 -101
  105. package/templates/hooks-node/lib/state.js +0 -187
  106. package/templates/hooks-node/stop.js +0 -416
  107. package/templates/hooks-node/user-prompt-submit.js +0 -337
  108. package/templates/plan-template.md +0 -306
  109. package/templates/rules/00-hooks-contract.mdc +0 -89
  110. package/templates/rules/30-ekkos-core.mdc +0 -188
  111. package/templates/rules/31-ekkos-messages.mdc +0 -78
  112. package/templates/shared/hooks-enabled.json +0 -22
  113. package/templates/shared/session-words.json +0 -45
  114. package/templates/skills/ekkOS_Deep_Recall/Skill.md +0 -282
  115. package/templates/skills/ekkOS_Learn/Skill.md +0 -265
  116. package/templates/skills/ekkOS_Memory_First/Skill.md +0 -206
  117. package/templates/skills/ekkOS_Plan_Assist/Skill.md +0 -302
  118. package/templates/skills/ekkOS_Preferences/Skill.md +0 -247
  119. package/templates/skills/ekkOS_Reflect/Skill.md +0 -257
  120. package/templates/skills/ekkOS_Safety/Skill.md +0 -265
  121. package/templates/skills/ekkOS_Schema/Skill.md +0 -251
  122. package/templates/skills/ekkOS_Summary/Skill.md +0 -257
  123. package/templates/spec-template.md +0 -159
  124. package/templates/windsurf-rules/ekkos-memory.md +0 -127
  125. package/templates/windsurf-skills/README.md +0 -58
  126. package/templates/windsurf-skills/ekkos-continue/SKILL.md +0 -81
  127. package/templates/windsurf-skills/ekkos-golden-loop/SKILL.md +0 -225
  128. package/templates/windsurf-skills/ekkos-insights/SKILL.md +0 -138
  129. package/templates/windsurf-skills/ekkos-recall/SKILL.md +0 -96
  130. package/templates/windsurf-skills/ekkos-safety/SKILL.md +0 -89
  131. package/templates/windsurf-skills/ekkos-vault/SKILL.md +0 -86
@@ -1,544 +0,0 @@
1
- "use strict";
2
- /**
3
- * ekkos agent - Agent management commands for remote terminal
4
- *
5
- * Subcommands:
6
- * - daemon: Run the agent daemon (used by service)
7
- * - start: Start the agent service
8
- * - stop: Stop the agent service
9
- * - restart: Restart the agent service
10
- * - status: Check agent status
11
- * - uninstall: Remove agent service
12
- */
13
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- var desc = Object.getOwnPropertyDescriptor(m, k);
16
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
- desc = { enumerable: true, get: function() { return m[k]; } };
18
- }
19
- Object.defineProperty(o, k2, desc);
20
- }) : (function(o, m, k, k2) {
21
- if (k2 === undefined) k2 = k;
22
- o[k2] = m[k];
23
- }));
24
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
- Object.defineProperty(o, "default", { enumerable: true, value: v });
26
- }) : function(o, v) {
27
- o["default"] = v;
28
- });
29
- var __importStar = (this && this.__importStar) || (function () {
30
- var ownKeys = function(o) {
31
- ownKeys = Object.getOwnPropertyNames || function (o) {
32
- var ar = [];
33
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
- return ar;
35
- };
36
- return ownKeys(o);
37
- };
38
- return function (mod) {
39
- if (mod && mod.__esModule) return mod;
40
- var result = {};
41
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
- __setModuleDefault(result, mod);
43
- return result;
44
- };
45
- })();
46
- var __importDefault = (this && this.__importDefault) || function (mod) {
47
- return (mod && mod.__esModule) ? mod : { "default": mod };
48
- };
49
- Object.defineProperty(exports, "__esModule", { value: true });
50
- exports.agentDaemon = agentDaemon;
51
- exports.agentStart = agentStart;
52
- exports.agentStop = agentStop;
53
- exports.agentRestart = agentRestart;
54
- exports.agentStatus = agentStatus;
55
- exports.agentUninstall = agentUninstall;
56
- exports.agentLogs = agentLogs;
57
- exports.agentHealth = agentHealth;
58
- const chalk_1 = __importDefault(require("chalk"));
59
- const os = __importStar(require("os"));
60
- const fs = __importStar(require("fs"));
61
- const path = __importStar(require("path"));
62
- const child_process_1 = require("child_process");
63
- const state_1 = require("../utils/state");
64
- const daemon_1 = require("../agent/daemon");
65
- /**
66
- * Run the agent daemon (foreground)
67
- */
68
- async function agentDaemon(options = {}) {
69
- const verbose = options.verbose || false;
70
- // Load device info
71
- const deviceFilePath = path.join(state_1.EKKOS_DIR, 'device.json');
72
- if (!fs.existsSync(deviceFilePath)) {
73
- console.error(chalk_1.default.red('Device not configured. Run `ekkos setup-remote` first.'));
74
- process.exit(1);
75
- }
76
- const deviceData = JSON.parse(fs.readFileSync(deviceFilePath, 'utf-8'));
77
- if (!deviceData.deviceToken) {
78
- console.error(chalk_1.default.red('Device not paired. Run `ekkos setup-remote` first.'));
79
- process.exit(1);
80
- }
81
- if (verbose) {
82
- console.log(chalk_1.default.cyan(`Starting ekkOS agent daemon...`));
83
- console.log(chalk_1.default.gray(` Device: ${deviceData.deviceName}`));
84
- console.log(chalk_1.default.gray(` Platform: ${deviceData.platform}/${deviceData.arch}`));
85
- }
86
- // Start the daemon
87
- const daemon = new daemon_1.AgentDaemon({
88
- deviceToken: deviceData.deviceToken,
89
- deviceId: deviceData.deviceId,
90
- deviceName: deviceData.deviceName,
91
- verbose,
92
- });
93
- await daemon.start();
94
- // Handle shutdown signals
95
- const shutdown = async () => {
96
- console.log(chalk_1.default.gray('\nShutting down agent...'));
97
- await daemon.stop();
98
- process.exit(0);
99
- };
100
- process.on('SIGINT', shutdown);
101
- process.on('SIGTERM', shutdown);
102
- }
103
- /**
104
- * Start the agent service
105
- */
106
- async function agentStart(options = {}) {
107
- const platform = os.platform();
108
- try {
109
- if (platform === 'darwin') {
110
- const plistPath = path.join(os.homedir(), 'Library', 'LaunchAgents', 'dev.ekkos.agent.plist');
111
- if (!fs.existsSync(plistPath)) {
112
- console.log(chalk_1.default.yellow('Agent not installed. Run `ekkos setup-remote` first.'));
113
- return;
114
- }
115
- (0, child_process_1.execSync)(`launchctl load "${plistPath}" 2>/dev/null || true`, { encoding: 'utf-8' });
116
- console.log(chalk_1.default.green('Agent started.'));
117
- }
118
- else if (platform === 'win32') {
119
- (0, child_process_1.execSync)('schtasks /run /tn "ekkOS Agent"', { encoding: 'utf-8' });
120
- console.log(chalk_1.default.green('Agent started.'));
121
- }
122
- else if (platform === 'linux') {
123
- (0, child_process_1.execSync)('systemctl --user start ekkos-agent', { encoding: 'utf-8' });
124
- console.log(chalk_1.default.green('Agent started.'));
125
- }
126
- }
127
- catch (err) {
128
- console.error(chalk_1.default.red(`Failed to start agent: ${err.message}`));
129
- process.exit(1);
130
- }
131
- }
132
- /**
133
- * Stop the agent service
134
- */
135
- async function agentStop(options = {}) {
136
- const platform = os.platform();
137
- try {
138
- if (platform === 'darwin') {
139
- const plistPath = path.join(os.homedir(), 'Library', 'LaunchAgents', 'dev.ekkos.agent.plist');
140
- (0, child_process_1.execSync)(`launchctl unload "${plistPath}" 2>/dev/null || true`, { encoding: 'utf-8' });
141
- console.log(chalk_1.default.green('Agent stopped.'));
142
- }
143
- else if (platform === 'win32') {
144
- (0, child_process_1.execSync)('taskkill /im "node.exe" /fi "windowtitle eq ekkOS*" /f 2>nul', { encoding: 'utf-8' });
145
- console.log(chalk_1.default.green('Agent stopped.'));
146
- }
147
- else if (platform === 'linux') {
148
- (0, child_process_1.execSync)('systemctl --user stop ekkos-agent', { encoding: 'utf-8' });
149
- console.log(chalk_1.default.green('Agent stopped.'));
150
- }
151
- }
152
- catch (err) {
153
- // May not be running
154
- console.log(chalk_1.default.gray('Agent was not running.'));
155
- }
156
- }
157
- /**
158
- * Restart the agent service
159
- */
160
- async function agentRestart(options = {}) {
161
- await agentStop(options);
162
- await agentStart(options);
163
- }
164
- /**
165
- * Check agent status
166
- */
167
- async function agentStatus(options = {}) {
168
- const platform = os.platform();
169
- let running = false;
170
- let statusOutput = '';
171
- try {
172
- if (platform === 'darwin') {
173
- statusOutput = (0, child_process_1.execSync)('launchctl list | grep dev.ekkos.agent || true', { encoding: 'utf-8' });
174
- running = statusOutput.includes('dev.ekkos.agent');
175
- }
176
- else if (platform === 'win32') {
177
- statusOutput = (0, child_process_1.execSync)('schtasks /query /tn "ekkOS Agent" 2>nul || true', { encoding: 'utf-8' });
178
- running = statusOutput.includes('Running');
179
- }
180
- else if (platform === 'linux') {
181
- statusOutput = (0, child_process_1.execSync)('systemctl --user is-active ekkos-agent 2>/dev/null || true', { encoding: 'utf-8' });
182
- running = statusOutput.trim() === 'active';
183
- }
184
- }
185
- catch {
186
- running = false;
187
- }
188
- console.log('');
189
- console.log(chalk_1.default.cyan.bold(' ekkOS Agent Status'));
190
- console.log('');
191
- // Check device info
192
- const deviceFilePath = path.join(state_1.EKKOS_DIR, 'device.json');
193
- if (!fs.existsSync(deviceFilePath)) {
194
- console.log(chalk_1.default.yellow(' Not configured. Run `ekkos setup-remote` first.'));
195
- return;
196
- }
197
- const deviceData = JSON.parse(fs.readFileSync(deviceFilePath, 'utf-8'));
198
- console.log(` Device: ${chalk_1.default.white(deviceData.deviceName)}`);
199
- console.log(` ID: ${chalk_1.default.gray(deviceData.deviceId.slice(0, 8))}...`);
200
- console.log(` Paired: ${deviceData.deviceToken ? chalk_1.default.green('Yes') : chalk_1.default.red('No')}`);
201
- console.log(` Service: ${running ? chalk_1.default.green('Running') : chalk_1.default.red('Stopped')}`);
202
- console.log('');
203
- // Check cloud connection
204
- if (deviceData.deviceToken) {
205
- console.log(chalk_1.default.gray(' Checking cloud connection...'));
206
- try {
207
- const authToken = (0, state_1.getAuthToken)();
208
- const state = (0, state_1.getState)();
209
- if (authToken && state?.userId) {
210
- const MEMORY_API_URL = process.env.MEMORY_API_URL || 'https://mcp.ekkos.dev';
211
- const response = await fetch(`${MEMORY_API_URL}/api/v1/relay/devices/${state.userId}`, {
212
- headers: { 'Authorization': `Bearer ${authToken}` },
213
- });
214
- if (response.ok) {
215
- const data = await response.json();
216
- const device = data.devices?.find((d) => d.deviceId === deviceData.deviceId);
217
- if (device?.online) {
218
- console.log(` Cloud: ${chalk_1.default.green('Connected')}`);
219
- }
220
- else {
221
- console.log(` Cloud: ${chalk_1.default.yellow('Offline')}`);
222
- }
223
- }
224
- }
225
- }
226
- catch {
227
- console.log(` Cloud: ${chalk_1.default.gray('Unable to check')}`);
228
- }
229
- }
230
- console.log('');
231
- // Show log location
232
- console.log(chalk_1.default.gray(` Logs: ${path.join(state_1.EKKOS_DIR, 'agent.out.log')}`));
233
- console.log('');
234
- }
235
- /**
236
- * Uninstall the agent service
237
- */
238
- async function agentUninstall(options = {}) {
239
- const platform = os.platform();
240
- console.log(chalk_1.default.cyan('Uninstalling ekkOS agent...'));
241
- try {
242
- if (platform === 'darwin') {
243
- const plistPath = path.join(os.homedir(), 'Library', 'LaunchAgents', 'dev.ekkos.agent.plist');
244
- (0, child_process_1.execSync)(`launchctl unload "${plistPath}" 2>/dev/null || true`, { encoding: 'utf-8' });
245
- if (fs.existsSync(plistPath)) {
246
- fs.unlinkSync(plistPath);
247
- }
248
- console.log(chalk_1.default.green(' ✓ Service removed'));
249
- }
250
- else if (platform === 'win32') {
251
- (0, child_process_1.execSync)('schtasks /delete /tn "ekkOS Agent" /f 2>nul || true', { encoding: 'utf-8' });
252
- console.log(chalk_1.default.green(' ✓ Scheduled task removed'));
253
- }
254
- else if (platform === 'linux') {
255
- (0, child_process_1.execSync)('systemctl --user disable ekkos-agent 2>/dev/null || true', { encoding: 'utf-8' });
256
- (0, child_process_1.execSync)('systemctl --user stop ekkos-agent 2>/dev/null || true', { encoding: 'utf-8' });
257
- const servicePath = path.join(os.homedir(), '.config', 'systemd', 'user', 'ekkos-agent.service');
258
- if (fs.existsSync(servicePath)) {
259
- fs.unlinkSync(servicePath);
260
- }
261
- console.log(chalk_1.default.green(' ✓ Service removed'));
262
- }
263
- // Remove device token (but keep device ID for potential re-pairing)
264
- const deviceFilePath = path.join(state_1.EKKOS_DIR, 'device.json');
265
- if (fs.existsSync(deviceFilePath)) {
266
- const deviceData = JSON.parse(fs.readFileSync(deviceFilePath, 'utf-8'));
267
- delete deviceData.deviceToken;
268
- delete deviceData.pairedAt;
269
- fs.writeFileSync(deviceFilePath, JSON.stringify(deviceData, null, 2));
270
- console.log(chalk_1.default.green(' ✓ Device token removed'));
271
- }
272
- console.log('');
273
- console.log(chalk_1.default.green('Agent uninstalled. Run `ekkos setup-remote` to set up again.'));
274
- console.log('');
275
- }
276
- catch (err) {
277
- console.error(chalk_1.default.red(`Failed to uninstall: ${err.message}`));
278
- process.exit(1);
279
- }
280
- }
281
- /**
282
- * Show agent logs
283
- */
284
- async function agentLogs(options = {}) {
285
- const logPath = path.join(state_1.EKKOS_DIR, 'agent.out.log');
286
- if (!fs.existsSync(logPath)) {
287
- console.log(chalk_1.default.gray('No logs found.'));
288
- return;
289
- }
290
- if (options.follow) {
291
- // Use tail -f
292
- const tail = (0, child_process_1.spawn)('tail', ['-f', logPath], { stdio: 'inherit' });
293
- tail.on('close', () => process.exit(0));
294
- }
295
- else {
296
- // Show last 50 lines
297
- const content = fs.readFileSync(logPath, 'utf-8');
298
- const lines = content.split('\n').slice(-50);
299
- console.log(lines.join('\n'));
300
- }
301
- }
302
- /**
303
- * Check agent daemon health and diagnose connection issues
304
- */
305
- async function agentHealth(options = {}) {
306
- const platform = os.platform();
307
- const deviceFilePath = path.join(state_1.EKKOS_DIR, 'device.json');
308
- const logPath = path.join(state_1.EKKOS_DIR, 'agent.out.log');
309
- const pidFilePath = path.join(state_1.EKKOS_DIR, 'agent.pid');
310
- const health = {
311
- timestamp: new Date().toISOString(),
312
- status: 'unknown',
313
- checks: {
314
- configured: false,
315
- paired: false,
316
- serviceRunning: false,
317
- processRunning: false,
318
- logsWriting: false,
319
- cloudConnected: false,
320
- networkHealthy: false,
321
- },
322
- issues: [],
323
- suggestions: [],
324
- };
325
- // Check 1: Device configured
326
- if (fs.existsSync(deviceFilePath)) {
327
- const deviceData = JSON.parse(fs.readFileSync(deviceFilePath, 'utf-8'));
328
- health.checks.configured = true;
329
- health.device = {
330
- name: deviceData.deviceName,
331
- id: deviceData.deviceId.slice(0, 8) + '...',
332
- platform: deviceData.platform,
333
- arch: deviceData.arch,
334
- };
335
- // Check 2: Device paired
336
- if (deviceData.deviceToken) {
337
- health.checks.paired = true;
338
- health.pairedAt = deviceData.pairedAt;
339
- }
340
- else {
341
- health.checks.paired = false;
342
- health.issues.push('Device not paired');
343
- health.suggestions.push('Run `ekkos setup-remote` to pair device');
344
- }
345
- // Check 3: Service running
346
- try {
347
- if (platform === 'darwin') {
348
- const output = (0, child_process_1.execSync)('launchctl list | grep dev.ekkos.agent || true', { encoding: 'utf-8' });
349
- health.checks.serviceRunning = output.includes('dev.ekkos.agent');
350
- }
351
- else if (platform === 'win32') {
352
- const output = (0, child_process_1.execSync)('schtasks /query /tn "ekkOS Agent" 2>nul || true', { encoding: 'utf-8' });
353
- health.checks.serviceRunning = output.includes('Running');
354
- }
355
- else if (platform === 'linux') {
356
- const output = (0, child_process_1.execSync)('systemctl --user is-active ekkos-agent 2>/dev/null || true', { encoding: 'utf-8' });
357
- health.checks.serviceRunning = output.trim() === 'active';
358
- }
359
- }
360
- catch {
361
- health.checks.serviceRunning = false;
362
- }
363
- if (!health.checks.serviceRunning) {
364
- health.issues.push('Service not running');
365
- health.suggestions.push('Run `ekkos agent start` to start the service');
366
- }
367
- // Check 4: Process running
368
- if (fs.existsSync(pidFilePath)) {
369
- const pid = parseInt(fs.readFileSync(pidFilePath, 'utf-8').trim());
370
- try {
371
- // Check if process exists
372
- (0, child_process_1.execSync)(`kill -0 ${pid} 2>/dev/null`, { stdio: 'pipe' });
373
- health.checks.processRunning = true;
374
- }
375
- catch {
376
- health.checks.processRunning = false;
377
- health.issues.push(`Agent process (PID ${pid}) not running`);
378
- health.suggestions.push('Run `ekkos agent restart` to restart');
379
- }
380
- }
381
- else {
382
- health.checks.processRunning = false;
383
- health.issues.push('No PID file found');
384
- }
385
- // Check 5: Logs writing
386
- if (fs.existsSync(logPath)) {
387
- const stats = fs.statSync(logPath);
388
- const lastModified = Date.now() - stats.mtime.getTime();
389
- const fifteenMinutes = 15 * 60 * 1000;
390
- health.checks.logsWriting = lastModified < fifteenMinutes;
391
- health.lastLogWrite = {
392
- timestamp: stats.mtime.toISOString(),
393
- minutesAgo: Math.round(lastModified / 1000 / 60),
394
- };
395
- if (!health.checks.logsWriting) {
396
- health.issues.push(`No logs written for ${Math.round(lastModified / 1000 / 60)} minutes`);
397
- health.suggestions.push('Check if daemon crashed - run `ekkos agent logs -f` to monitor');
398
- }
399
- // Parse recent errors from logs
400
- const content = fs.readFileSync(logPath, 'utf-8');
401
- const lines = content.split('\n').slice(-100);
402
- const errors = lines.filter(l => l.includes('ERROR') || l.includes('error') || l.includes('Connection failed'));
403
- if (errors.length > 0) {
404
- health.recentErrors = errors.slice(-5);
405
- }
406
- }
407
- else {
408
- health.checks.logsWriting = false;
409
- health.issues.push('Log file not found');
410
- }
411
- // Check 6: Cloud connectivity
412
- if (health.checks.paired) {
413
- try {
414
- const authToken = (0, state_1.getAuthToken)();
415
- const state = (0, state_1.getState)();
416
- if (authToken && state?.userId) {
417
- const MEMORY_API_URL = process.env.MEMORY_API_URL || 'https://api.ekkos.dev';
418
- const controller = new AbortController();
419
- const timeout = setTimeout(() => controller.abort(), 5000);
420
- try {
421
- const response = await fetch(`${MEMORY_API_URL}/api/v1/relay/devices/${state.userId}`, {
422
- headers: { 'Authorization': `Bearer ${authToken}` },
423
- signal: controller.signal,
424
- });
425
- clearTimeout(timeout);
426
- if (response.ok) {
427
- const data = await response.json();
428
- const device = data.devices?.find((d) => d.deviceId === deviceData.deviceId);
429
- health.checks.cloudConnected = device?.online === true;
430
- if (!health.checks.cloudConnected) {
431
- health.issues.push('Device shows offline in cloud');
432
- health.suggestions.push('Check network connection and agent logs');
433
- }
434
- }
435
- else {
436
- health.checks.cloudConnected = false;
437
- health.issues.push(`Cloud API returned ${response.status}`);
438
- }
439
- }
440
- catch (err) {
441
- clearTimeout(timeout);
442
- health.checks.cloudConnected = false;
443
- if (err.name === 'AbortError') {
444
- health.issues.push('Cloud connection timeout (>5s)');
445
- }
446
- else {
447
- health.issues.push(`Cloud connection error: ${err.message}`);
448
- }
449
- health.suggestions.push('Check internet connection');
450
- }
451
- }
452
- else {
453
- health.issues.push('Not logged in to ekkOS');
454
- health.suggestions.push('Run `ekkos init` to set up authentication');
455
- }
456
- }
457
- catch {
458
- health.checks.cloudConnected = false;
459
- health.issues.push('Unable to check cloud connectivity');
460
- }
461
- }
462
- // Check 7: Network health
463
- if (health.checks.logsWriting && health.checks.cloudConnected) {
464
- health.checks.networkHealthy = true;
465
- }
466
- }
467
- else {
468
- health.checks.configured = false;
469
- health.issues.push('Device not configured');
470
- health.suggestions.push('Run `ekkos setup-remote` to configure device');
471
- }
472
- // Determine overall status
473
- if (health.issues.length === 0) {
474
- health.status = 'healthy';
475
- }
476
- else if (health.checks.serviceRunning &&
477
- health.checks.processRunning &&
478
- health.checks.logsWriting) {
479
- health.status = 'degraded';
480
- }
481
- else {
482
- health.status = 'unhealthy';
483
- }
484
- if (options.json) {
485
- console.log(JSON.stringify(health, null, 2));
486
- }
487
- else {
488
- // Pretty print
489
- console.log('');
490
- console.log(chalk_1.default.cyan.bold(' ekkOS Agent Health Check'));
491
- console.log('');
492
- const statusColor = health.status === 'healthy' ? chalk_1.default.green :
493
- health.status === 'degraded' ? chalk_1.default.yellow :
494
- chalk_1.default.red;
495
- console.log(` Status: ${statusColor.bold(health.status.toUpperCase())}`);
496
- console.log('');
497
- // Device info
498
- if (health.device) {
499
- console.log(chalk_1.default.gray(' Device:'));
500
- console.log(` ${chalk_1.default.gray('Name:')} ${health.device.name}`);
501
- console.log(` ${chalk_1.default.gray('ID:')} ${health.device.id}`);
502
- console.log(` ${chalk_1.default.gray('Platform:')} ${health.device.platform}/${health.device.arch}`);
503
- console.log('');
504
- }
505
- // Checks
506
- console.log(chalk_1.default.gray(' Checks:'));
507
- for (const [key, value] of Object.entries(health.checks)) {
508
- const icon = value ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
509
- const label = key.replace(/([A-Z])/g, ' $1').trim();
510
- console.log(` ${icon} ${label}`);
511
- }
512
- console.log('');
513
- // Issues
514
- if (health.issues.length > 0) {
515
- console.log(chalk_1.default.yellow(' Issues:'));
516
- for (const issue of health.issues) {
517
- console.log(` ${chalk_1.default.yellow('⚠')} ${issue}`);
518
- }
519
- console.log('');
520
- }
521
- // Suggestions
522
- if (health.suggestions.length > 0) {
523
- console.log(chalk_1.default.cyan(' Suggestions:'));
524
- for (const suggestion of health.suggestions) {
525
- console.log(` ${chalk_1.default.cyan('→')} ${suggestion}`);
526
- }
527
- console.log('');
528
- }
529
- // Recent errors
530
- if (health.recentErrors && health.recentErrors.length > 0) {
531
- console.log(chalk_1.default.red(' Recent Errors:'));
532
- for (const err of health.recentErrors.slice(0, 3)) {
533
- const preview = err.substring(0, 100) + (err.length > 100 ? '...' : '');
534
- console.log(` ${chalk_1.default.red('!')} ${preview}`);
535
- }
536
- console.log('');
537
- }
538
- // Logs info
539
- if (health.lastLogWrite) {
540
- console.log(chalk_1.default.gray(` Last activity: ${health.lastLogWrite.minutesAgo} minutes ago`));
541
- console.log('');
542
- }
543
- }
544
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * ekkos setup-remote - One-command setup for remote terminal access
3
- *
4
- * This command does everything automatically:
5
- * 1. Checks if user is logged in (prompts login if not)
6
- * 2. Generates unique device ID and fingerprint
7
- * 3. Opens browser for device pairing approval
8
- * 4. Installs background agent as system service
9
- * 5. Starts agent immediately
10
- * 6. Verifies connection to cloud relay
11
- */
12
- export interface SetupRemoteOptions {
13
- force?: boolean;
14
- skipService?: boolean;
15
- verbose?: boolean;
16
- }
17
- /**
18
- * Main setup command
19
- */
20
- export declare function setupRemote(options?: SetupRemoteOptions): Promise<void>;