@ekkos/cli 1.3.2 → 1.3.6

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 (123) 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 +617 -83
  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.js +2 -25
  13. package/dist/commands/run.d.ts +0 -1
  14. package/dist/commands/run.js +147 -241
  15. package/dist/commands/scan.d.ts +21 -0
  16. package/dist/commands/scan.js +386 -0
  17. package/dist/commands/swarm-dashboard.js +156 -28
  18. package/dist/commands/swarm.d.ts +1 -1
  19. package/dist/commands/swarm.js +1 -1
  20. package/dist/commands/test-claude.d.ts +2 -2
  21. package/dist/commands/test-claude.js +3 -3
  22. package/dist/deploy/index.d.ts +0 -2
  23. package/dist/deploy/index.js +0 -2
  24. package/dist/deploy/settings.d.ts +2 -2
  25. package/dist/deploy/settings.js +42 -4
  26. package/dist/deploy/skills.js +1 -2
  27. package/dist/index.js +79 -19
  28. package/dist/lib/usage-parser.js +5 -4
  29. package/dist/utils/proxy-url.d.ts +12 -1
  30. package/dist/utils/proxy-url.js +16 -1
  31. package/dist/utils/templates.js +1 -1
  32. package/package.json +4 -6
  33. package/templates/CLAUDE.md +49 -107
  34. package/dist/agent/daemon.d.ts +0 -130
  35. package/dist/agent/daemon.js +0 -606
  36. package/dist/agent/health-check.d.ts +0 -35
  37. package/dist/agent/health-check.js +0 -243
  38. package/dist/agent/pty-runner.d.ts +0 -53
  39. package/dist/agent/pty-runner.js +0 -190
  40. package/dist/commands/agent.d.ts +0 -50
  41. package/dist/commands/agent.js +0 -544
  42. package/dist/commands/setup-remote.d.ts +0 -20
  43. package/dist/commands/setup-remote.js +0 -582
  44. package/dist/commands/synk.d.ts +0 -7
  45. package/dist/commands/synk.js +0 -339
  46. package/dist/cron/index.d.ts +0 -7
  47. package/dist/cron/index.js +0 -13
  48. package/dist/cron/promoter.d.ts +0 -70
  49. package/dist/cron/promoter.js +0 -403
  50. package/dist/synk/api.d.ts +0 -22
  51. package/dist/synk/api.js +0 -133
  52. package/dist/synk/auth.d.ts +0 -7
  53. package/dist/synk/auth.js +0 -30
  54. package/dist/synk/config.d.ts +0 -18
  55. package/dist/synk/config.js +0 -37
  56. package/dist/synk/daemon/control-client.d.ts +0 -11
  57. package/dist/synk/daemon/control-client.js +0 -101
  58. package/dist/synk/daemon/control-server.d.ts +0 -24
  59. package/dist/synk/daemon/control-server.js +0 -91
  60. package/dist/synk/daemon/run.d.ts +0 -14
  61. package/dist/synk/daemon/run.js +0 -338
  62. package/dist/synk/encryption.d.ts +0 -17
  63. package/dist/synk/encryption.js +0 -133
  64. package/dist/synk/index.d.ts +0 -13
  65. package/dist/synk/index.js +0 -36
  66. package/dist/synk/machine-client.d.ts +0 -42
  67. package/dist/synk/machine-client.js +0 -218
  68. package/dist/synk/persistence.d.ts +0 -51
  69. package/dist/synk/persistence.js +0 -211
  70. package/dist/synk/qr.d.ts +0 -5
  71. package/dist/synk/qr.js +0 -33
  72. package/dist/synk/session-bridge.d.ts +0 -58
  73. package/dist/synk/session-bridge.js +0 -171
  74. package/dist/synk/session-client.d.ts +0 -46
  75. package/dist/synk/session-client.js +0 -240
  76. package/dist/synk/types.d.ts +0 -574
  77. package/dist/synk/types.js +0 -74
  78. package/dist/utils/verify-remote-terminal.d.ts +0 -10
  79. package/dist/utils/verify-remote-terminal.js +0 -415
  80. package/templates/README.md +0 -378
  81. package/templates/claude-plugins/PHASE2_COMPLETION.md +0 -346
  82. package/templates/claude-plugins/PLUGIN_PROPOSALS.md +0 -1776
  83. package/templates/claude-plugins/README.md +0 -587
  84. package/templates/claude-plugins/agents/code-reviewer.json +0 -14
  85. package/templates/claude-plugins/agents/debug-detective.json +0 -15
  86. package/templates/claude-plugins/agents/git-companion.json +0 -14
  87. package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +0 -8
  88. package/templates/claude-plugins/blog-manager/commands/blog.md +0 -691
  89. package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +0 -8
  90. package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +0 -434
  91. package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +0 -8
  92. package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +0 -282
  93. package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +0 -8
  94. package/templates/claude-plugins/memory-lens/commands/memory-search.md +0 -181
  95. package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +0 -8
  96. package/templates/claude-plugins/pattern-coach/commands/forge.md +0 -365
  97. package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +0 -8
  98. package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +0 -582
  99. package/templates/commands/continue.md +0 -47
  100. package/templates/cursor-rules/ekkos-memory.md +0 -127
  101. package/templates/ekkos-manifest.json +0 -223
  102. package/templates/helpers/json-parse.cjs +0 -101
  103. package/templates/plan-template.md +0 -306
  104. package/templates/shared/hooks-enabled.json +0 -22
  105. package/templates/shared/session-words.json +0 -45
  106. package/templates/skills/ekkOS_Deep_Recall/Skill.md +0 -282
  107. package/templates/skills/ekkOS_Learn/Skill.md +0 -265
  108. package/templates/skills/ekkOS_Memory_First/Skill.md +0 -206
  109. package/templates/skills/ekkOS_Plan_Assist/Skill.md +0 -302
  110. package/templates/skills/ekkOS_Preferences/Skill.md +0 -247
  111. package/templates/skills/ekkOS_Reflect/Skill.md +0 -257
  112. package/templates/skills/ekkOS_Safety/Skill.md +0 -265
  113. package/templates/skills/ekkOS_Schema/Skill.md +0 -251
  114. package/templates/skills/ekkOS_Summary/Skill.md +0 -257
  115. package/templates/spec-template.md +0 -159
  116. package/templates/windsurf-rules/ekkos-memory.md +0 -127
  117. package/templates/windsurf-skills/README.md +0 -58
  118. package/templates/windsurf-skills/ekkos-continue/SKILL.md +0 -81
  119. package/templates/windsurf-skills/ekkos-golden-loop/SKILL.md +0 -225
  120. package/templates/windsurf-skills/ekkos-insights/SKILL.md +0 -138
  121. package/templates/windsurf-skills/ekkos-recall/SKILL.md +0 -96
  122. package/templates/windsurf-skills/ekkos-safety/SKILL.md +0 -89
  123. package/templates/windsurf-skills/ekkos-vault/SKILL.md +0 -86
@@ -1,403 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- /**
4
- * ekkOS PROMETHEUS Pattern Promoter
5
- * ==================================
6
- *
7
- * Daily cron job that evaluates patterns for promotion to constitutional memory.
8
- *
9
- * Constitutional patterns are injected into the system prompt via @ekkos/patch,
10
- * making them "instincts" that don't require retrieval.
11
- *
12
- * Promotion Criteria (default):
13
- * - Success rate ≥ 85%
14
- * - Applications ≥ 5
15
- * - Skip rate ≤ 10%
16
- * - Confidence ≥ 70%
17
- * - Used within last 30 days
18
- * - Used in ≥ 2 unique sessions
19
- *
20
- * Usage:
21
- * npx ekkos-promote # Run promotion evaluation
22
- * npx ekkos-promote --dry-run # Preview without applying changes
23
- * npx ekkos-promote --user <uuid> # Promote for specific user
24
- *
25
- * Schedule via launchd (macOS) or cron:
26
- * 0 6 * * * /path/to/node /path/to/ekkos-promote
27
- */
28
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
29
- if (k2 === undefined) k2 = k;
30
- var desc = Object.getOwnPropertyDescriptor(m, k);
31
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
32
- desc = { enumerable: true, get: function() { return m[k]; } };
33
- }
34
- Object.defineProperty(o, k2, desc);
35
- }) : (function(o, m, k, k2) {
36
- if (k2 === undefined) k2 = k;
37
- o[k2] = m[k];
38
- }));
39
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
40
- Object.defineProperty(o, "default", { enumerable: true, value: v });
41
- }) : function(o, v) {
42
- o["default"] = v;
43
- });
44
- var __importStar = (this && this.__importStar) || (function () {
45
- var ownKeys = function(o) {
46
- ownKeys = Object.getOwnPropertyNames || function (o) {
47
- var ar = [];
48
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
49
- return ar;
50
- };
51
- return ownKeys(o);
52
- };
53
- return function (mod) {
54
- if (mod && mod.__esModule) return mod;
55
- var result = {};
56
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
57
- __setModuleDefault(result, mod);
58
- return result;
59
- };
60
- })();
61
- Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.evaluatePromotions = evaluatePromotions;
63
- exports.queryPatternStats = queryPatternStats;
64
- exports.writePatchConfig = writePatchConfig;
65
- const supabase_js_1 = require("@supabase/supabase-js");
66
- const prometheus_1 = require("@ekkos/prometheus");
67
- const fs = __importStar(require("fs"));
68
- const path = __importStar(require("path"));
69
- const os = __importStar(require("os"));
70
- // ═══════════════════════════════════════════════════════════════════════════
71
- // Pattern Stats Query
72
- // ═══════════════════════════════════════════════════════════════════════════
73
- async function queryPatternStats(supabase, userId) {
74
- // Query patterns with their application stats
75
- let query = supabase
76
- .from('patterns')
77
- .select(`
78
- pattern_id,
79
- title,
80
- content,
81
- success_rate,
82
- applied_count,
83
- confidence_score,
84
- created_at,
85
- updated_at,
86
- tags,
87
- user_id
88
- `)
89
- .eq('quarantined', false)
90
- .gte('applied_count', 1); // Only consider applied patterns
91
- if (userId) {
92
- query = query.eq('user_id', userId);
93
- }
94
- const { data: patterns, error } = await query;
95
- if (error) {
96
- throw new Error(`Failed to query patterns: ${error.message}`);
97
- }
98
- if (!patterns || patterns.length === 0) {
99
- return [];
100
- }
101
- // Get application details for skip rate and session count
102
- const patternIds = patterns.map(p => p.pattern_id);
103
- const { data: applications } = await supabase
104
- .from('pattern_applications')
105
- .select('pattern_id, outcome_success, created_at, user_id')
106
- .in('pattern_id', patternIds);
107
- const { data: skips } = await supabase
108
- .from('pattern_skips')
109
- .select('pattern_id')
110
- .in('pattern_id', patternIds);
111
- // Aggregate stats per pattern
112
- const appsByPattern = new Map();
113
- const skipsByPattern = new Map();
114
- for (const app of applications || []) {
115
- if (!appsByPattern.has(app.pattern_id)) {
116
- appsByPattern.set(app.pattern_id, []);
117
- }
118
- appsByPattern.get(app.pattern_id).push(app);
119
- }
120
- for (const skip of skips || []) {
121
- const count = skipsByPattern.get(skip.pattern_id) || 0;
122
- skipsByPattern.set(skip.pattern_id, count + 1);
123
- }
124
- // Build PatternStats for each pattern
125
- return patterns.map(p => {
126
- const apps = appsByPattern.get(p.pattern_id) || [];
127
- const skipCount = skipsByPattern.get(p.pattern_id) || 0;
128
- const successCount = apps.filter(a => a.outcome_success === true).length;
129
- const failureCount = apps.filter(a => a.outcome_success === false).length;
130
- const totalApplications = successCount + failureCount;
131
- // Count unique sessions (using created_at date as proxy)
132
- const uniqueDates = new Set(apps.map(a => new Date(a.created_at).toISOString().split('T')[0]));
133
- const stats = {
134
- patternId: p.pattern_id,
135
- title: p.title || 'Untitled',
136
- successCount,
137
- failureCount,
138
- skipCount,
139
- totalApplications: totalApplications || p.applied_count || 0,
140
- uniqueSessions: uniqueDates.size,
141
- firstApplied: new Date(p.created_at),
142
- lastApplied: new Date(p.updated_at || p.created_at),
143
- currentConfidence: p.confidence_score || p.success_rate || 0.5,
144
- tags: p.tags,
145
- };
146
- return stats;
147
- });
148
- }
149
- // ═══════════════════════════════════════════════════════════════════════════
150
- // Promotion Logic
151
- // ═══════════════════════════════════════════════════════════════════════════
152
- async function evaluatePromotions(supabase, config) {
153
- const result = {
154
- evaluated: 0,
155
- promoted: 0,
156
- demoted: 0,
157
- patterns: [],
158
- };
159
- // Get pattern stats
160
- const patternStats = await queryPatternStats(supabase, config.userId);
161
- result.evaluated = patternStats.length;
162
- if (config.verbose) {
163
- console.log(`[PROMOTER] Evaluating ${patternStats.length} patterns...`);
164
- }
165
- // Get currently promoted patterns (from promoted_patterns table or metadata)
166
- const { data: currentlyPromoted } = await supabase
167
- .from('patterns')
168
- .select('pattern_id')
169
- .eq('evolution_stage', 'constitutional');
170
- const promotedSet = new Set((currentlyPromoted || []).map(p => p.pattern_id));
171
- const promotedPatterns = [];
172
- // Evaluate each pattern
173
- for (const stats of patternStats) {
174
- const evaluation = prometheus_1.promotionEvaluator.evaluate(stats);
175
- const wasPromoted = promotedSet.has(stats.patternId);
176
- if (evaluation.eligible && !wasPromoted) {
177
- // PROMOTE: Pattern meets criteria and wasn't promoted before
178
- result.promoted++;
179
- result.patterns.push({
180
- patternId: stats.patternId,
181
- title: stats.title,
182
- action: 'promoted',
183
- score: evaluation.score,
184
- });
185
- if (!config.dryRun) {
186
- // Update pattern to constitutional
187
- await supabase
188
- .from('patterns')
189
- .update({
190
- evolution_stage: 'constitutional',
191
- promoted_at: new Date().toISOString(),
192
- })
193
- .eq('pattern_id', stats.patternId);
194
- // Emit PATTERN_PROMOTED event
195
- prometheus_1.learningEvents.emitPatternPromoted({
196
- id: stats.patternId,
197
- title: stats.title,
198
- confidenceBefore: stats.currentConfidence,
199
- confidenceAfter: 1.0,
200
- tier: 'constitutional',
201
- successRate: stats.successCount / Math.max(stats.totalApplications, 1),
202
- appliedCount: stats.totalApplications,
203
- }, {
204
- daysInEpisodic: Math.floor((Date.now() - stats.firstApplied.getTime()) / (1000 * 60 * 60 * 24)),
205
- totalApplications: stats.totalApplications,
206
- finalSuccessRate: stats.successCount / Math.max(stats.totalApplications, 1),
207
- });
208
- }
209
- // Fetch full pattern for patch config
210
- const { data: fullPattern } = await supabase
211
- .from('patterns')
212
- .select('content, tags')
213
- .eq('pattern_id', stats.patternId)
214
- .single();
215
- if (fullPattern) {
216
- // Parse problem/solution from content
217
- const content = fullPattern.content || '';
218
- const problemMatch = content.match(/## Problem\n([\s\S]*?)(?=\n## Solution|$)/);
219
- const solutionMatch = content.match(/## Solution\n([\s\S]*?)$/);
220
- promotedPatterns.push({
221
- id: stats.patternId,
222
- title: stats.title,
223
- problem: problemMatch?.[1]?.trim() || 'N/A',
224
- solution: solutionMatch?.[1]?.trim() || content,
225
- promotedAt: new Date().toISOString(),
226
- successRate: stats.successCount / Math.max(stats.totalApplications, 1),
227
- appliedCount: stats.totalApplications,
228
- tags: fullPattern.tags,
229
- });
230
- }
231
- if (config.verbose) {
232
- console.log(` ✓ PROMOTE: "${stats.title}" (score: ${evaluation.score.toFixed(2)})`);
233
- }
234
- }
235
- else if (!evaluation.eligible && wasPromoted) {
236
- // DEMOTE: Pattern no longer meets criteria
237
- result.demoted++;
238
- // Find the main blocker for demotion reason
239
- const reason = evaluation.blockers[0]?.includes('success')
240
- ? 'low_success_rate'
241
- : evaluation.blockers[0]?.includes('skip')
242
- ? 'high_skip_rate'
243
- : 'outdated';
244
- result.patterns.push({
245
- patternId: stats.patternId,
246
- title: stats.title,
247
- action: 'demoted',
248
- score: evaluation.score,
249
- reason,
250
- });
251
- if (!config.dryRun) {
252
- // Update pattern back to episodic
253
- await supabase
254
- .from('patterns')
255
- .update({
256
- evolution_stage: 'episodic',
257
- demoted_at: new Date().toISOString(),
258
- })
259
- .eq('pattern_id', stats.patternId);
260
- // Emit PATTERN_DEMOTED event
261
- prometheus_1.learningEvents.emitPatternDemoted({
262
- id: stats.patternId,
263
- title: stats.title,
264
- confidenceBefore: 1.0,
265
- confidenceAfter: stats.currentConfidence,
266
- tier: 'episodic',
267
- successRate: stats.successCount / Math.max(stats.totalApplications, 1),
268
- appliedCount: stats.totalApplications,
269
- }, reason);
270
- }
271
- if (config.verbose) {
272
- console.log(` ✗ DEMOTE: "${stats.title}" (${reason})`);
273
- }
274
- }
275
- else {
276
- result.patterns.push({
277
- patternId: stats.patternId,
278
- title: stats.title,
279
- action: 'unchanged',
280
- score: evaluation.score,
281
- });
282
- }
283
- }
284
- // Also include patterns that are already promoted and still eligible
285
- for (const stats of patternStats) {
286
- const evaluation = prometheus_1.promotionEvaluator.evaluate(stats);
287
- if (evaluation.eligible && promotedSet.has(stats.patternId)) {
288
- // Fetch and include in patch config
289
- const { data: fullPattern } = await supabase
290
- .from('patterns')
291
- .select('content, tags')
292
- .eq('pattern_id', stats.patternId)
293
- .single();
294
- if (fullPattern) {
295
- const content = fullPattern.content || '';
296
- const problemMatch = content.match(/## Problem\n([\s\S]*?)(?=\n## Solution|$)/);
297
- const solutionMatch = content.match(/## Solution\n([\s\S]*?)$/);
298
- promotedPatterns.push({
299
- id: stats.patternId,
300
- title: stats.title,
301
- problem: problemMatch?.[1]?.trim() || 'N/A',
302
- solution: solutionMatch?.[1]?.trim() || content,
303
- promotedAt: new Date().toISOString(),
304
- successRate: stats.successCount / Math.max(stats.totalApplications, 1),
305
- appliedCount: stats.totalApplications,
306
- tags: fullPattern.tags,
307
- });
308
- }
309
- }
310
- }
311
- // Generate patch config
312
- result.patchConfig = {
313
- version: '1.0.0',
314
- generatedAt: new Date().toISOString(),
315
- promotedPatterns,
316
- totalPatterns: promotedPatterns.length,
317
- };
318
- return result;
319
- }
320
- // ═══════════════════════════════════════════════════════════════════════════
321
- // Patch Config Generation
322
- // ═══════════════════════════════════════════════════════════════════════════
323
- function writePatchConfig(config, outputPath) {
324
- const dir = path.dirname(outputPath);
325
- if (!fs.existsSync(dir)) {
326
- fs.mkdirSync(dir, { recursive: true });
327
- }
328
- fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));
329
- console.log(`[PROMOTER] Wrote patch config to: ${outputPath}`);
330
- }
331
- // ═══════════════════════════════════════════════════════════════════════════
332
- // CLI Entry Point
333
- // ═══════════════════════════════════════════════════════════════════════════
334
- async function main() {
335
- const args = process.argv.slice(2);
336
- const config = {
337
- supabaseUrl: process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL || '',
338
- supabaseKey: process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_SERVICE_ROLE_KEY || '',
339
- dryRun: args.includes('--dry-run'),
340
- userId: args.includes('--user') ? args[args.indexOf('--user') + 1] : undefined,
341
- patchConfigPath: path.join(os.homedir(), '.ekkos', 'promoted-patterns.json'),
342
- verbose: args.includes('--verbose') || args.includes('-v'),
343
- };
344
- // Allow custom output path
345
- if (args.includes('--output')) {
346
- config.patchConfigPath = args[args.indexOf('--output') + 1];
347
- }
348
- console.log('═══════════════════════════════════════════════════════════════');
349
- console.log(' ekkOS PROMETHEUS Pattern Promoter');
350
- console.log('═══════════════════════════════════════════════════════════════');
351
- console.log(` Mode: ${config.dryRun ? 'DRY RUN (no changes)' : 'LIVE'}`);
352
- console.log(` User: ${config.userId || 'All users'}`);
353
- console.log(` Output: ${config.patchConfigPath}`);
354
- console.log('═══════════════════════════════════════════════════════════════');
355
- console.log('');
356
- if (!config.supabaseUrl || !config.supabaseKey) {
357
- console.error('[ERROR] Missing SUPABASE_URL or SUPABASE_SECRET_KEY environment variables');
358
- process.exit(1);
359
- }
360
- const supabase = (0, supabase_js_1.createClient)(config.supabaseUrl, config.supabaseKey);
361
- try {
362
- const result = await evaluatePromotions(supabase, config);
363
- console.log('');
364
- console.log('═══════════════════════════════════════════════════════════════');
365
- console.log(' Results');
366
- console.log('═══════════════════════════════════════════════════════════════');
367
- console.log(` Patterns evaluated: ${result.evaluated}`);
368
- console.log(` Promoted: ${result.promoted}`);
369
- console.log(` Demoted: ${result.demoted}`);
370
- console.log(` Constitutional total: ${result.patchConfig?.totalPatterns || 0}`);
371
- console.log('═══════════════════════════════════════════════════════════════');
372
- // Write patch config
373
- if (!config.dryRun && result.patchConfig) {
374
- writePatchConfig(result.patchConfig, config.patchConfigPath);
375
- }
376
- else if (config.dryRun && result.patchConfig) {
377
- console.log('\n[DRY RUN] Would write patch config with:');
378
- console.log(` - ${result.patchConfig.totalPatterns} promoted patterns`);
379
- }
380
- // Summary of changes
381
- if (result.patterns.filter(p => p.action !== 'unchanged').length > 0) {
382
- console.log('\nChanges:');
383
- for (const p of result.patterns) {
384
- if (p.action === 'promoted') {
385
- console.log(` 🎓 PROMOTED: "${p.title}" (score: ${p.score.toFixed(2)})`);
386
- }
387
- else if (p.action === 'demoted') {
388
- console.log(` ⬇️ DEMOTED: "${p.title}" (${p.reason})`);
389
- }
390
- }
391
- }
392
- else {
393
- console.log('\nNo promotion changes needed.');
394
- }
395
- console.log('\n✓ Promotion evaluation complete');
396
- }
397
- catch (error) {
398
- console.error('[ERROR]', error);
399
- process.exit(1);
400
- }
401
- }
402
- // Run if executed directly
403
- main().catch(console.error);
@@ -1,22 +0,0 @@
1
- /**
2
- * API client for ekkOS_synk server
3
- */
4
- import type { AgentState, Metadata, Session, Machine, MachineMetadata, DaemonState } from './types';
5
- import type { Credentials } from './persistence';
6
- export declare class ApiClient {
7
- private readonly credential;
8
- static create(credential: Credentials): Promise<ApiClient>;
9
- private constructor();
10
- /** Create a new session or load existing one with the given tag */
11
- getOrCreateSession(opts: {
12
- tag: string;
13
- metadata: Metadata;
14
- state: AgentState | null;
15
- }): Promise<Session | null>;
16
- /** Register or update machine with the server */
17
- getOrCreateMachine(opts: {
18
- machineId: string;
19
- metadata: MachineMetadata;
20
- daemonState?: DaemonState;
21
- }): Promise<Machine>;
22
- }
package/dist/synk/api.js DELETED
@@ -1,133 +0,0 @@
1
- "use strict";
2
- /**
3
- * API client for ekkOS_synk server
4
- */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.ApiClient = void 0;
10
- const axios_1 = __importDefault(require("axios"));
11
- const encryption_1 = require("./encryption");
12
- const config_1 = require("./config");
13
- class ApiClient {
14
- static async create(credential) {
15
- return new ApiClient(credential);
16
- }
17
- constructor(credential) {
18
- this.credential = credential;
19
- }
20
- /** Create a new session or load existing one with the given tag */
21
- async getOrCreateSession(opts) {
22
- let dataEncryptionKey = null;
23
- let encryptionKey;
24
- let encryptionVariant;
25
- if (this.credential.encryption.type === 'dataKey') {
26
- encryptionKey = (0, encryption_1.getRandomBytes)(32);
27
- encryptionVariant = 'dataKey';
28
- const encryptedDataKey = (0, encryption_1.libsodiumEncryptForPublicKey)(encryptionKey, this.credential.encryption.publicKey);
29
- dataEncryptionKey = new Uint8Array(encryptedDataKey.length + 1);
30
- dataEncryptionKey.set([0], 0);
31
- dataEncryptionKey.set(encryptedDataKey, 1);
32
- }
33
- else {
34
- encryptionKey = this.credential.encryption.secret;
35
- encryptionVariant = 'legacy';
36
- }
37
- try {
38
- const response = await axios_1.default.post(`${config_1.synkConfig.serverUrl}/v1/sessions`, {
39
- tag: opts.tag,
40
- metadata: (0, encryption_1.encodeBase64)((0, encryption_1.encrypt)(encryptionKey, encryptionVariant, opts.metadata)),
41
- agentState: opts.state ? (0, encryption_1.encodeBase64)((0, encryption_1.encrypt)(encryptionKey, encryptionVariant, opts.state)) : null,
42
- dataEncryptionKey: dataEncryptionKey ? (0, encryption_1.encodeBase64)(dataEncryptionKey) : null,
43
- }, {
44
- headers: {
45
- 'Authorization': `Bearer ${this.credential.token}`,
46
- 'Content-Type': 'application/json',
47
- },
48
- timeout: 60000,
49
- });
50
- const raw = response.data.session;
51
- return {
52
- id: raw.id,
53
- seq: raw.seq,
54
- metadata: (0, encryption_1.decrypt)(encryptionKey, encryptionVariant, (0, encryption_1.decodeBase64)(raw.metadata)),
55
- metadataVersion: raw.metadataVersion,
56
- agentState: raw.agentState ? (0, encryption_1.decrypt)(encryptionKey, encryptionVariant, (0, encryption_1.decodeBase64)(raw.agentState)) : null,
57
- agentStateVersion: raw.agentStateVersion,
58
- encryptionKey,
59
- encryptionVariant,
60
- };
61
- }
62
- catch (error) {
63
- if (axios_1.default.isAxiosError(error)) {
64
- const status = error.response?.status;
65
- if (status === 404 || (status && status >= 500) || error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') {
66
- return null;
67
- }
68
- }
69
- throw new Error(`Failed to create session: ${error instanceof Error ? error.message : 'Unknown error'}`);
70
- }
71
- }
72
- /** Register or update machine with the server */
73
- async getOrCreateMachine(opts) {
74
- let dataEncryptionKey = null;
75
- let encryptionKey;
76
- let encryptionVariant;
77
- if (this.credential.encryption.type === 'dataKey') {
78
- encryptionVariant = 'dataKey';
79
- encryptionKey = this.credential.encryption.machineKey;
80
- const encryptedDataKey = (0, encryption_1.libsodiumEncryptForPublicKey)(this.credential.encryption.machineKey, this.credential.encryption.publicKey);
81
- dataEncryptionKey = new Uint8Array(encryptedDataKey.length + 1);
82
- dataEncryptionKey.set([0], 0);
83
- dataEncryptionKey.set(encryptedDataKey, 1);
84
- }
85
- else {
86
- encryptionKey = this.credential.encryption.secret;
87
- encryptionVariant = 'legacy';
88
- }
89
- const createMinimalMachine = () => ({
90
- id: opts.machineId,
91
- encryptionKey,
92
- encryptionVariant,
93
- metadata: opts.metadata,
94
- metadataVersion: 0,
95
- daemonState: opts.daemonState || null,
96
- daemonStateVersion: 0,
97
- });
98
- try {
99
- const response = await axios_1.default.post(`${config_1.synkConfig.serverUrl}/v1/machines`, {
100
- id: opts.machineId,
101
- metadata: (0, encryption_1.encodeBase64)((0, encryption_1.encrypt)(encryptionKey, encryptionVariant, opts.metadata)),
102
- daemonState: opts.daemonState ? (0, encryption_1.encodeBase64)((0, encryption_1.encrypt)(encryptionKey, encryptionVariant, opts.daemonState)) : undefined,
103
- dataEncryptionKey: dataEncryptionKey ? (0, encryption_1.encodeBase64)(dataEncryptionKey) : undefined,
104
- }, {
105
- headers: {
106
- 'Authorization': `Bearer ${this.credential.token}`,
107
- 'Content-Type': 'application/json',
108
- },
109
- timeout: 60000,
110
- });
111
- const raw = response.data.machine;
112
- return {
113
- id: raw.id,
114
- encryptionKey,
115
- encryptionVariant,
116
- metadata: raw.metadata ? (0, encryption_1.decrypt)(encryptionKey, encryptionVariant, (0, encryption_1.decodeBase64)(raw.metadata)) : opts.metadata,
117
- metadataVersion: raw.metadataVersion || 0,
118
- daemonState: raw.daemonState ? (0, encryption_1.decrypt)(encryptionKey, encryptionVariant, (0, encryption_1.decodeBase64)(raw.daemonState)) : null,
119
- daemonStateVersion: raw.daemonStateVersion || 0,
120
- };
121
- }
122
- catch (error) {
123
- if (axios_1.default.isAxiosError(error)) {
124
- const status = error.response?.status;
125
- if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND' || status === 404 || (status && status >= 500)) {
126
- return createMinimalMachine();
127
- }
128
- }
129
- return createMinimalMachine();
130
- }
131
- }
132
- }
133
- exports.ApiClient = ApiClient;
@@ -1,7 +0,0 @@
1
- /**
2
- * Authentication for ekkOS_synk server
3
- */
4
- /** Authenticate with synk-server and obtain a bearer token */
5
- export declare function authGetToken(secret: Uint8Array): Promise<string>;
6
- /** Generate a deep link URL for mobile app pairing */
7
- export declare function generateAppUrl(secret: Uint8Array): string;
package/dist/synk/auth.js DELETED
@@ -1,30 +0,0 @@
1
- "use strict";
2
- /**
3
- * Authentication for ekkOS_synk server
4
- */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.authGetToken = authGetToken;
10
- exports.generateAppUrl = generateAppUrl;
11
- const axios_1 = __importDefault(require("axios"));
12
- const encryption_1 = require("./encryption");
13
- const config_1 = require("./config");
14
- /** Authenticate with synk-server and obtain a bearer token */
15
- async function authGetToken(secret) {
16
- const { challenge, publicKey, signature } = (0, encryption_1.authChallenge)(secret);
17
- const response = await axios_1.default.post(`${config_1.synkConfig.serverUrl}/v1/auth`, {
18
- challenge: (0, encryption_1.encodeBase64)(challenge),
19
- publicKey: (0, encryption_1.encodeBase64)(publicKey),
20
- signature: (0, encryption_1.encodeBase64)(signature),
21
- });
22
- if (!response.data.success || !response.data.token) {
23
- throw new Error('Authentication failed');
24
- }
25
- return response.data.token;
26
- }
27
- /** Generate a deep link URL for mobile app pairing */
28
- function generateAppUrl(secret) {
29
- return `ekkos-synk://${(0, encryption_1.encodeBase64Url)(secret)}`;
30
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * Configuration for ekkOS_synk — remote session sync
3
- */
4
- declare class SynkConfig {
5
- readonly serverUrl: string;
6
- readonly synkHomeDir: string;
7
- readonly logsDir: string;
8
- readonly settingsFile: string;
9
- readonly credentialsFile: string;
10
- readonly daemonStateFile: string;
11
- readonly daemonLockFile: string;
12
- readonly isDaemonProcess: boolean;
13
- readonly disableCaffeinate: boolean;
14
- constructor();
15
- ensureDirectories(): void;
16
- }
17
- export declare const synkConfig: SynkConfig;
18
- export {};
@@ -1,37 +0,0 @@
1
- "use strict";
2
- /**
3
- * Configuration for ekkOS_synk — remote session sync
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.synkConfig = void 0;
7
- const node_fs_1 = require("node:fs");
8
- const node_os_1 = require("node:os");
9
- const node_path_1 = require("node:path");
10
- class SynkConfig {
11
- constructor() {
12
- this.serverUrl = process.env.SYNK_SERVER_URL || 'https://synk.ekkos.dev';
13
- const args = process.argv.slice(2);
14
- this.isDaemonProcess = args.length >= 3 && args[0] === 'synk' && args[1] === 'daemon' && args[2] === 'start-sync';
15
- if (process.env.SYNK_HOME_DIR) {
16
- this.synkHomeDir = process.env.SYNK_HOME_DIR.replace(/^~/, (0, node_os_1.homedir)());
17
- }
18
- else {
19
- this.synkHomeDir = (0, node_path_1.join)((0, node_os_1.homedir)(), '.ekkos', 'synk');
20
- }
21
- this.logsDir = (0, node_path_1.join)(this.synkHomeDir, 'logs');
22
- this.settingsFile = (0, node_path_1.join)(this.synkHomeDir, 'settings.json');
23
- this.credentialsFile = (0, node_path_1.join)(this.synkHomeDir, 'credentials.json');
24
- this.daemonStateFile = (0, node_path_1.join)(this.synkHomeDir, 'daemon.state.json');
25
- this.daemonLockFile = (0, node_path_1.join)(this.synkHomeDir, 'daemon.state.json.lock');
26
- this.disableCaffeinate = ['true', '1', 'yes'].includes(process.env.SYNK_DISABLE_CAFFEINATE?.toLowerCase() || '');
27
- }
28
- ensureDirectories() {
29
- if (!(0, node_fs_1.existsSync)(this.synkHomeDir)) {
30
- (0, node_fs_1.mkdirSync)(this.synkHomeDir, { recursive: true });
31
- }
32
- if (!(0, node_fs_1.existsSync)(this.logsDir)) {
33
- (0, node_fs_1.mkdirSync)(this.logsDir, { recursive: true });
34
- }
35
- }
36
- }
37
- exports.synkConfig = new SynkConfig();
@@ -1,11 +0,0 @@
1
- /**
2
- * HTTP client for communicating with a running synk daemon
3
- */
4
- import type { Metadata } from '../types';
5
- export declare function notifyDaemonSessionStarted(sessionId: string, metadata: Metadata): Promise<any>;
6
- export declare function listDaemonSessions(): Promise<any[]>;
7
- export declare function stopDaemonSession(sessionId: string): Promise<boolean>;
8
- export declare function spawnDaemonSession(directory: string, sessionId?: string): Promise<any>;
9
- export declare function stopDaemonHttp(): Promise<void>;
10
- export declare function checkIfDaemonRunning(): Promise<boolean>;
11
- export declare function stopDaemon(): Promise<void>;