@ekkos/cli 0.2.9 → 0.2.10

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 (35) hide show
  1. package/dist/cache/LocalSessionStore.d.ts +34 -21
  2. package/dist/cache/LocalSessionStore.js +169 -53
  3. package/dist/cache/capture.d.ts +19 -11
  4. package/dist/cache/capture.js +243 -76
  5. package/dist/cache/types.d.ts +14 -1
  6. package/dist/commands/doctor.d.ts +10 -0
  7. package/dist/commands/doctor.js +148 -73
  8. package/dist/commands/hooks.d.ts +109 -0
  9. package/dist/commands/hooks.js +668 -0
  10. package/dist/commands/run.d.ts +1 -0
  11. package/dist/commands/run.js +69 -21
  12. package/dist/index.js +42 -1
  13. package/dist/restore/RestoreOrchestrator.d.ts +17 -3
  14. package/dist/restore/RestoreOrchestrator.js +64 -22
  15. package/dist/utils/paths.d.ts +125 -0
  16. package/dist/utils/paths.js +283 -0
  17. package/package.json +1 -1
  18. package/templates/ekkos-manifest.json +223 -0
  19. package/templates/helpers/json-parse.cjs +101 -0
  20. package/templates/hooks/assistant-response.ps1 +256 -0
  21. package/templates/hooks/assistant-response.sh +124 -64
  22. package/templates/hooks/session-start.ps1 +107 -2
  23. package/templates/hooks/session-start.sh +201 -166
  24. package/templates/hooks/stop.ps1 +124 -3
  25. package/templates/hooks/stop.sh +470 -843
  26. package/templates/hooks/user-prompt-submit.ps1 +107 -22
  27. package/templates/hooks/user-prompt-submit.sh +403 -393
  28. package/templates/project-stubs/session-start.ps1 +63 -0
  29. package/templates/project-stubs/session-start.sh +55 -0
  30. package/templates/project-stubs/stop.ps1 +63 -0
  31. package/templates/project-stubs/stop.sh +55 -0
  32. package/templates/project-stubs/user-prompt-submit.ps1 +63 -0
  33. package/templates/project-stubs/user-prompt-submit.sh +55 -0
  34. package/templates/shared/hooks-enabled.json +22 -0
  35. package/templates/shared/session-words.json +45 -0
@@ -1,11 +1,55 @@
1
1
  # ═══════════════════════════════════════════════════════════════════════════
2
2
  # ekkOS_ Hook: UserPromptSubmit - SEAMLESS CONTEXT CONTINUITY (Windows)
3
- # ═══════════════════════════════════════════════════════════════════════════
4
- # PowerShell version for Windows users
3
+ # MANAGED BY ekkos-connect - DO NOT EDIT DIRECTLY
4
+ # EKKOS_MANAGED=1
5
+ # EKKOS_MANIFEST_SHA256=<computed-at-build>
6
+ # EKKOS_TEMPLATE_VERSION=1.0.0
7
+ #
8
+ # Per ekkOS Onboarding Spec v1.2 FINAL + ADDENDUM:
9
+ # - All persisted records MUST include: instanceId, sessionId, sessionName
10
+ # - Uses EKKOS_INSTANCE_ID env var for multi-session isolation
5
11
  # ═══════════════════════════════════════════════════════════════════════════
6
12
 
7
13
  $ErrorActionPreference = "SilentlyContinue"
8
14
 
15
+ # ═══════════════════════════════════════════════════════════════════════════
16
+ # CONFIG PATHS - No hardcoded word arrays per spec v1.2 Addendum
17
+ # ═══════════════════════════════════════════════════════════════════════════
18
+ $EkkosConfigDir = if ($env:EKKOS_CONFIG_DIR) { $env:EKKOS_CONFIG_DIR } else { "$env:USERPROFILE\.ekkos" }
19
+ $SessionWordsJson = "$EkkosConfigDir\session-words.json"
20
+ $SessionWordsDefault = "$EkkosConfigDir\.defaults\session-words.json"
21
+
22
+ # ═══════════════════════════════════════════════════════════════════════════
23
+ # INSTANCE ID - Multi-session isolation per v1.2 ADDENDUM
24
+ # ═══════════════════════════════════════════════════════════════════════════
25
+ $EkkosInstanceId = if ($env:EKKOS_INSTANCE_ID) { $env:EKKOS_INSTANCE_ID } else { "default" }
26
+
27
+ # ═══════════════════════════════════════════════════════════════════════════
28
+ # Load session words from JSON file - NO HARDCODED ARRAYS
29
+ # ═══════════════════════════════════════════════════════════════════════════
30
+ $script:SessionWords = $null
31
+
32
+ function Load-SessionWords {
33
+ $wordsFile = $SessionWordsJson
34
+
35
+ # Fallback to managed defaults if user file missing/invalid
36
+ if (-not (Test-Path $wordsFile)) {
37
+ $wordsFile = $SessionWordsDefault
38
+ }
39
+
40
+ if (-not (Test-Path $wordsFile)) {
41
+ Write-Error "No session-words.json found. Run 'ekkos hooks install --global' to fix."
42
+ exit 1
43
+ }
44
+
45
+ try {
46
+ $script:SessionWords = Get-Content $wordsFile -Raw | ConvertFrom-Json
47
+ } catch {
48
+ Write-Error "Failed to parse $wordsFile. Check JSON syntax: $_"
49
+ exit 1
50
+ }
51
+ }
52
+
9
53
  # Read input from stdin
10
54
  $inputJson = [Console]::In.ReadToEnd()
11
55
  if (-not $inputJson) { exit 0 }
@@ -43,27 +87,27 @@ $queryLower = $userQuery.ToLower()
43
87
 
44
88
  # Memory First - Debug/Error/Problem solving
45
89
  if ($queryLower -match '(how do i|debug|error|bug|fix|not working|broken|fails|issue|problem|wrong|crash)') {
46
- $skillReminders += "🔧 SKILL REQUIRED: Call Skill(skill: `"ekkOS_Memory_First`") FIRST before debugging"
90
+ $skillReminders += "SKILL REQUIRED: Call Skill(skill: `"ekkOS_Memory_First`") FIRST before debugging"
47
91
  }
48
92
 
49
93
  # Recall Triggers - Time-based memory
50
94
  if ($queryLower -match '(yesterday|last week|last month|remember when|what did we|where did we leave|before|earlier|previous|ago)') {
51
- $skillReminders += "📅 SKILL REQUIRED: Call Skill(skill: `"ekkOS_Deep_Recall`") for time-based memory"
95
+ $skillReminders += "SKILL REQUIRED: Call Skill(skill: `"ekkOS_Deep_Recall`") for time-based memory"
52
96
  }
53
97
 
54
98
  # Directive Triggers - User preferences
55
99
  if ($queryLower -match '(always |never |i prefer|i like |dont |don.t |avoid |remember that |from now on)') {
56
- $skillReminders += "⚙️ SKILL REQUIRED: Call Skill(skill: `"ekkOS_Preferences`") to capture directive"
100
+ $skillReminders += "SKILL REQUIRED: Call Skill(skill: `"ekkOS_Preferences`") to capture directive"
57
101
  }
58
102
 
59
103
  # Safety Triggers - Destructive actions
60
104
  if ($queryLower -match '(delete|drop |rm -rf|deploy|push.*main|push.*master|production|migrate|rollback)') {
61
- $skillReminders += "⚠️ SAFETY REQUIRED: Call ekkOS_Conflict before this destructive action"
105
+ $skillReminders += "SAFETY REQUIRED: Call ekkOS_Conflict before this destructive action"
62
106
  }
63
107
 
64
108
  # Schema Triggers - Database operations
65
109
  if ($queryLower -match '(sql|query|supabase|prisma|database|table|column|select |insert |update |where )') {
66
- $skillReminders += "🗄️ SCHEMA REQUIRED: Call ekkOS_GetSchema for correct field names"
110
+ $skillReminders += "SCHEMA REQUIRED: Call ekkOS_GetSchema for correct field names"
67
111
  }
68
112
 
69
113
  # ═══════════════════════════════════════════════════════════════════════════
@@ -98,9 +142,30 @@ $newState = @{
98
142
  Set-Content -Path $stateFile -Value $newState -Force
99
143
 
100
144
  # ═══════════════════════════════════════════════════════════════════════════
101
- # WORKING MEMORY: Fast capture each turn (async, non-blocking)
145
+ # LOCAL CACHE: Tier 0 capture (async, non-blocking)
146
+ # Per v1.2 ADDENDUM: Pass instanceId for namespacing
102
147
  # ═══════════════════════════════════════════════════════════════════════════
103
- $configFile = Join-Path $env:USERPROFILE ".ekkos\config.json"
148
+ $captureCmd = Get-Command "ekkos-capture" -ErrorAction SilentlyContinue
149
+ if ($captureCmd -and $rawSessionId -ne "unknown") {
150
+ try {
151
+ # NEW format: ekkos-capture user <instance_id> <session_id> <session_name> <turn_id> <query> [project_path]
152
+ $queryBase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($userQuery))
153
+ $projectRoot = if ($env:PWD) { $env:PWD } else { (Get-Location).Path }
154
+
155
+ Start-Job -ScriptBlock {
156
+ param($instanceId, $sessionId, $sessionName, $turnNum, $queryB64, $projectPath)
157
+ try {
158
+ $decoded = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($queryB64))
159
+ & ekkos-capture user $instanceId $sessionId $sessionName $turnNum $decoded $projectPath 2>&1 | Out-Null
160
+ } catch {}
161
+ } -ArgumentList $EkkosInstanceId, $rawSessionId, $sessionName, $turn, $queryBase64, $projectRoot | Out-Null
162
+ } catch {}
163
+ }
164
+
165
+ # ═══════════════════════════════════════════════════════════════════════════
166
+ # WORKING MEMORY: Fast capture to API (async, non-blocking)
167
+ # ═══════════════════════════════════════════════════════════════════════════
168
+ $configFile = Join-Path $EkkosConfigDir "config.json"
104
169
  if (Test-Path $configFile) {
105
170
  try {
106
171
  $config = Get-Content $configFile -Raw | ConvertFrom-Json
@@ -110,43 +175,63 @@ if (Test-Path $configFile) {
110
175
  if ($captureToken) {
111
176
  # Async capture using Start-Job (non-blocking)
112
177
  Start-Job -ScriptBlock {
113
- param($token, $sessionId, $turnNum, $query)
178
+ param($token, $instanceId, $sessionId, $sessionName, $turnNum, $query)
114
179
  $body = @{
115
180
  session_id = $sessionId
181
+ session_name = $sessionName
182
+ instance_id = $instanceId
116
183
  turn = $turnNum
117
184
  query = $query
118
185
  } | ConvertTo-Json
119
186
 
120
- Invoke-RestMethod -Uri "https://mcp.ekkos.dev/api/v1/working/fast-capture" `
187
+ Invoke-RestMethod -Uri "https://api.ekkos.dev/api/v1/working/fast-capture" `
121
188
  -Method POST `
122
189
  -Headers @{ Authorization = "Bearer $token" } `
123
190
  -ContentType "application/json" `
124
191
  -Body $body -ErrorAction SilentlyContinue
125
- } -ArgumentList $captureToken, $rawSessionId, $turn, $userQuery | Out-Null
192
+ } -ArgumentList $captureToken, $EkkosInstanceId, $rawSessionId, $sessionName, $turn, $userQuery | Out-Null
126
193
  }
127
194
  } catch {}
128
195
  }
129
196
 
130
197
  # ═══════════════════════════════════════════════════════════════════════════
131
- # SESSION NAME (UUID to words)
198
+ # SESSION NAME (UUID to words) - Uses external session-words.json
132
199
  # ═══════════════════════════════════════════════════════════════════════════
133
200
  function Convert-UuidToWords {
134
201
  param([string]$uuid)
135
202
 
136
- $adjectives = @("alpha","beta","gamma","delta","echo","foxtrot","golf","hotel","india","juliet","kilo","lima","mike","november","oscar","papa")
137
- $nouns = @("apple","banana","cherry","dragon","eagle","falcon","grape","hawk","iris","jasper","koala","lemon","mango","nebula","orange","panda")
138
- $animals = @("ants","bats","cats","dogs","eels","foxes","goats","hares","ibis","jays","kites","lynx","mice","newts","owls","pigs")
203
+ # Load session words if not already loaded
204
+ if (-not $script:SessionWords) {
205
+ Load-SessionWords
206
+ }
207
+
208
+ # Handle missing session words gracefully
209
+ if (-not $script:SessionWords) {
210
+ return "unknown-session"
211
+ }
212
+
213
+ $adjectives = $script:SessionWords.adjectives
214
+ $nouns = $script:SessionWords.nouns
215
+ $verbs = $script:SessionWords.verbs
216
+
217
+ if (-not $adjectives -or -not $nouns -or -not $verbs) {
218
+ return "unknown-session"
219
+ }
139
220
 
140
221
  if (-not $uuid -or $uuid -eq "unknown") { return "unknown-session" }
141
222
 
142
223
  $clean = $uuid -replace "-", ""
143
224
  if ($clean.Length -lt 6) { return "unknown-session" }
144
225
 
145
- $a = [Convert]::ToInt32($clean.Substring(0,2), 16) % $adjectives.Length
146
- $n = [Convert]::ToInt32($clean.Substring(2,2), 16) % $nouns.Length
147
- $an = [Convert]::ToInt32($clean.Substring(4,2), 16) % $animals.Length
226
+ try {
227
+ $a = [Convert]::ToInt32($clean.Substring(0,2), 16) % $adjectives.Length
228
+ $n = [Convert]::ToInt32($clean.Substring(2,2), 16) % $nouns.Length
229
+ $an = [Convert]::ToInt32($clean.Substring(4,2), 16) % $verbs.Length
148
230
 
149
- return "$($adjectives[$a])-$($nouns[$n])-$($animals[$an])"
231
+ return "$($adjectives[$a])-$($nouns[$n])-$($verbs[$an])"
232
+ } catch {
233
+ return "unknown-session"
234
+ }
150
235
  }
151
236
 
152
237
  $sessionName = Convert-UuidToWords $rawSessionId
@@ -155,7 +240,7 @@ $timestamp = (Get-Date).ToString("yyyy-MM-dd hh:mm:ss tt") + " EST"
155
240
  # ═══════════════════════════════════════════════════════════════════════════
156
241
  # OUTPUT SYSTEM REMINDER
157
242
  # ═══════════════════════════════════════════════════════════════════════════
158
- $header = "[0;36m[1m🧠 ekkOS Memory[0m [2m| Turn $turn | $contextPercent | $sessionName | $timestamp[0m"
243
+ $header = "[0;36m[1mekkOS Memory[0m [2m| Turn $turn | $sessionName | $timestamp[0m"
159
244
 
160
245
  $output = @"
161
246
  $header
@@ -168,7 +253,7 @@ if ($skillReminders.Count -gt 0) {
168
253
 
169
254
  $output += @"
170
255
 
171
- <footer-format>End responses with: Claude Code ({Model}) · 🧠 **ekkOS_™** · Turn $turn · $sessionName · 📅 $timestamp</footer-format>
256
+ <footer-format>End responses with: Claude Code ({Model}) - ekkOS - Turn $turn - $sessionName - $timestamp</footer-format>
172
257
  "@
173
258
 
174
259
  Write-Output $output