@ekkos/cli 1.2.18 → 1.3.1
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/capture.js +0 -0
- package/dist/commands/dashboard.js +121 -66
- package/dist/commands/hooks.d.ts +25 -36
- package/dist/commands/hooks.js +43 -615
- package/dist/commands/init.js +7 -23
- package/dist/commands/run.js +90 -3
- package/dist/commands/setup.js +10 -352
- package/dist/deploy/hooks.d.ts +8 -5
- package/dist/deploy/hooks.js +12 -105
- package/dist/deploy/settings.d.ts +8 -2
- package/dist/deploy/settings.js +22 -51
- package/dist/index.js +17 -39
- package/dist/utils/state.js +7 -2
- package/package.json +1 -1
- package/templates/CLAUDE.md +82 -292
- package/templates/cursor-rules/ekkos-memory.md +48 -108
- package/templates/windsurf-rules/ekkos-memory.md +62 -64
- package/templates/cursor-hooks/after-agent-response.sh +0 -117
- package/templates/cursor-hooks/before-submit-prompt.sh +0 -419
- package/templates/cursor-hooks/hooks.json +0 -20
- package/templates/cursor-hooks/lib/contract.sh +0 -320
- package/templates/cursor-hooks/stop.sh +0 -75
- package/templates/hooks/assistant-response.ps1 +0 -256
- package/templates/hooks/assistant-response.sh +0 -160
- package/templates/hooks/hooks.json +0 -40
- package/templates/hooks/lib/contract.sh +0 -332
- package/templates/hooks/lib/count-tokens.cjs +0 -86
- package/templates/hooks/lib/ekkos-reminders.sh +0 -98
- package/templates/hooks/lib/state.sh +0 -210
- package/templates/hooks/session-start.ps1 +0 -146
- package/templates/hooks/session-start.sh +0 -353
- package/templates/hooks/stop.ps1 +0 -349
- package/templates/hooks/stop.sh +0 -382
- package/templates/hooks/user-prompt-submit.ps1 +0 -419
- package/templates/hooks/user-prompt-submit.sh +0 -516
- package/templates/project-stubs/session-start.ps1 +0 -63
- package/templates/project-stubs/session-start.sh +0 -55
- package/templates/project-stubs/stop.ps1 +0 -63
- package/templates/project-stubs/stop.sh +0 -55
- package/templates/project-stubs/user-prompt-submit.ps1 +0 -63
- package/templates/project-stubs/user-prompt-submit.sh +0 -55
- package/templates/windsurf-hooks/README.md +0 -212
- package/templates/windsurf-hooks/hooks.json +0 -17
- package/templates/windsurf-hooks/install.sh +0 -148
- package/templates/windsurf-hooks/lib/contract.sh +0 -322
- package/templates/windsurf-hooks/post-cascade-response.sh +0 -251
- package/templates/windsurf-hooks/pre-user-prompt.sh +0 -435
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
3
|
-
# ekkOS_ Hook: SessionStart - MINIMAL + AUTO-RESTORE + TIME MACHINE CONTINUE
|
|
4
|
-
# MANAGED BY ekkos-connect - DO NOT EDIT DIRECTLY
|
|
5
|
-
# EKKOS_MANAGED=1
|
|
6
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
7
|
-
# This hook does THREE things:
|
|
8
|
-
# 1. Check for pending Time Machine "Continue from here" requests
|
|
9
|
-
# 2. Initialize session tracking
|
|
10
|
-
# 3. Auto-restore from L2 if recent turns exist (FAST TRIM support)
|
|
11
|
-
#
|
|
12
|
-
# TIME MACHINE FLOW:
|
|
13
|
-
# User clicks "Continue from here" on web → API queues request →
|
|
14
|
-
# User runs `claude` → This hook detects pending request →
|
|
15
|
-
# Restores THAT session's context → Seamless time travel!
|
|
16
|
-
#
|
|
17
|
-
# FAST TRIM FLOW:
|
|
18
|
-
# User runs /clear → session-start detects fresh session →
|
|
19
|
-
# Checks L2 for recent turns → Auto-injects last 15 turns → Seamless continuity
|
|
20
|
-
#
|
|
21
|
-
# Per spec v1.2 Addendum: NO jq dependency
|
|
22
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
23
|
-
|
|
24
|
-
set +e
|
|
25
|
-
|
|
26
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
27
|
-
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
28
|
-
|
|
29
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
30
|
-
# CONFIG PATHS - Per spec v1.2 Addendum
|
|
31
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
32
|
-
EKKOS_CONFIG_DIR="${EKKOS_CONFIG_DIR:-$HOME/.ekkos}"
|
|
33
|
-
JSON_PARSE_HELPER="$EKKOS_CONFIG_DIR/.helpers/json-parse.cjs"
|
|
34
|
-
|
|
35
|
-
INPUT=$(cat)
|
|
36
|
-
|
|
37
|
-
# Parse input using Node (no jq)
|
|
38
|
-
parse_json_value() {
|
|
39
|
-
local json="$1"
|
|
40
|
-
local path="$2"
|
|
41
|
-
echo "$json" | node -e "
|
|
42
|
-
const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
43
|
-
const path = '$path'.replace(/^\./,'').split('.').filter(Boolean);
|
|
44
|
-
let result = data;
|
|
45
|
-
for (const p of path) {
|
|
46
|
-
if (result === undefined || result === null) { result = undefined; break; }
|
|
47
|
-
result = result[p];
|
|
48
|
-
}
|
|
49
|
-
if (result !== undefined && result !== null) console.log(result);
|
|
50
|
-
" 2>/dev/null || echo ""
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
SESSION_ID=$(parse_json_value "$INPUT" '.session_id')
|
|
54
|
-
[ -z "$SESSION_ID" ] && SESSION_ID="unknown"
|
|
55
|
-
|
|
56
|
-
TRANSCRIPT_PATH=$(parse_json_value "$INPUT" '.transcript_path')
|
|
57
|
-
SOURCE=$(parse_json_value "$INPUT" '.source')
|
|
58
|
-
[ -z "$SOURCE" ] && SOURCE="unknown"
|
|
59
|
-
|
|
60
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
61
|
-
# Load auth
|
|
62
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
63
|
-
EKKOS_CONFIG="$HOME/.ekkos/config.json"
|
|
64
|
-
AUTH_TOKEN=""
|
|
65
|
-
USER_ID=""
|
|
66
|
-
|
|
67
|
-
if [ -f "$EKKOS_CONFIG" ] && [ -f "$JSON_PARSE_HELPER" ]; then
|
|
68
|
-
AUTH_TOKEN=$(node "$JSON_PARSE_HELPER" "$EKKOS_CONFIG" '.hookApiKey' 2>/dev/null || echo "")
|
|
69
|
-
if [ -z "$AUTH_TOKEN" ]; then
|
|
70
|
-
AUTH_TOKEN=$(node "$JSON_PARSE_HELPER" "$EKKOS_CONFIG" '.apiKey' 2>/dev/null || echo "")
|
|
71
|
-
fi
|
|
72
|
-
USER_ID=$(node "$JSON_PARSE_HELPER" "$EKKOS_CONFIG" '.userId' 2>/dev/null || echo "")
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
if [ -z "$AUTH_TOKEN" ] && [ -f "$PROJECT_ROOT/.env.local" ]; then
|
|
76
|
-
AUTH_TOKEN=$(grep -E "^SUPABASE_SECRET_KEY=" "$PROJECT_ROOT/.env.local" | cut -d'=' -f2- | tr -d '"' | tr -d "'" | tr -d '\r')
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
|
-
[ -z "$AUTH_TOKEN" ] && exit 0
|
|
80
|
-
|
|
81
|
-
MEMORY_API_URL="https://mcp.ekkos.dev"
|
|
82
|
-
|
|
83
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
84
|
-
# TIME MACHINE: Check for pending "Continue from here" requests
|
|
85
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
86
|
-
RESTORE_REQUEST_ID="${EKKOS_RESTORE:-}"
|
|
87
|
-
TIME_MACHINE_SESSION=""
|
|
88
|
-
TIME_MACHINE_FROM_TURN=""
|
|
89
|
-
TIME_MACHINE_TO_TURN=""
|
|
90
|
-
|
|
91
|
-
# Check via env var first, then API
|
|
92
|
-
if [ -n "$RESTORE_REQUEST_ID" ]; then
|
|
93
|
-
echo -e "\033[0;35m Time Machine request detected: $RESTORE_REQUEST_ID\033[0m" >&2
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
# Check API for pending requests (if we have user_id)
|
|
97
|
-
if [ -z "$TIME_MACHINE_SESSION" ] && [ -n "$USER_ID" ]; then
|
|
98
|
-
PENDING_RESPONSE=$(curl -s -X GET "$MEMORY_API_URL/api/v1/context/restore-request/pending?user_id=$USER_ID" \
|
|
99
|
-
-H "Authorization: Bearer $AUTH_TOKEN" \
|
|
100
|
-
--connect-timeout 2 \
|
|
101
|
-
--max-time 3 2>/dev/null || echo '{}')
|
|
102
|
-
|
|
103
|
-
# Parse using Node (no jq)
|
|
104
|
-
IS_PENDING=$(echo "$PENDING_RESPONSE" | node -e "
|
|
105
|
-
const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
106
|
-
console.log(data.pending || false);
|
|
107
|
-
" 2>/dev/null || echo "false")
|
|
108
|
-
|
|
109
|
-
if [ "$IS_PENDING" = "true" ]; then
|
|
110
|
-
TIME_MACHINE_SESSION=$(echo "$PENDING_RESPONSE" | node -e "
|
|
111
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
112
|
-
console.log(d.request?.session_id || '');
|
|
113
|
-
" 2>/dev/null || echo "")
|
|
114
|
-
TIME_MACHINE_FROM_TURN=$(echo "$PENDING_RESPONSE" | node -e "
|
|
115
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
116
|
-
console.log(d.request?.from_turn || '');
|
|
117
|
-
" 2>/dev/null || echo "")
|
|
118
|
-
TIME_MACHINE_TO_TURN=$(echo "$PENDING_RESPONSE" | node -e "
|
|
119
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
120
|
-
console.log(d.request?.to_turn || '');
|
|
121
|
-
" 2>/dev/null || echo "")
|
|
122
|
-
RESTORE_REQUEST_ID=$(echo "$PENDING_RESPONSE" | node -e "
|
|
123
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
124
|
-
console.log(d.request?.request_id || '');
|
|
125
|
-
" 2>/dev/null || echo "")
|
|
126
|
-
|
|
127
|
-
if [ -n "$TIME_MACHINE_SESSION" ]; then
|
|
128
|
-
echo "" >&2
|
|
129
|
-
echo -e "\033[0;35m------------------------------------------------------------------------\033[0m" >&2
|
|
130
|
-
echo -e "\033[0;35m\033[1m TIME MACHINE\033[0m \033[2m| Restoring session from web request...\033[0m" >&2
|
|
131
|
-
echo -e "\033[0;35m------------------------------------------------------------------------\033[0m" >&2
|
|
132
|
-
|
|
133
|
-
# Mark request as consumed
|
|
134
|
-
curl -s -X POST "$MEMORY_API_URL/api/v1/context/restore-request/consume" \
|
|
135
|
-
-H "Authorization: Bearer $AUTH_TOKEN" \
|
|
136
|
-
-H "Content-Type: application/json" \
|
|
137
|
-
-d "{\"request_id\": \"$RESTORE_REQUEST_ID\"}" \
|
|
138
|
-
--connect-timeout 2 \
|
|
139
|
-
--max-time 3 >/dev/null 2>&1 || true
|
|
140
|
-
fi
|
|
141
|
-
fi
|
|
142
|
-
fi
|
|
143
|
-
|
|
144
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
145
|
-
# Session ID persistence - PROJECT-LOCAL for isolation
|
|
146
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
147
|
-
STATE_DIR="$PROJECT_ROOT/.claude/state"
|
|
148
|
-
mkdir -p "$STATE_DIR" 2>/dev/null || true
|
|
149
|
-
SESSION_FILE="$STATE_DIR/current-session.json"
|
|
150
|
-
|
|
151
|
-
# Project-local session storage (isolated per project)
|
|
152
|
-
PROJECT_SESSION_DIR="$STATE_DIR/sessions"
|
|
153
|
-
mkdir -p "$PROJECT_SESSION_DIR" 2>/dev/null || true
|
|
154
|
-
|
|
155
|
-
# Use Claude's RAW_SESSION_ID directly (from session_id field)
|
|
156
|
-
CURRENT_SESSION_ID="$SESSION_ID"
|
|
157
|
-
|
|
158
|
-
# Find most recent session in THIS PROJECT for auto-restore
|
|
159
|
-
MOST_RECENT_SESSION=""
|
|
160
|
-
SAVED_TURN_COUNT=0
|
|
161
|
-
|
|
162
|
-
if [ -n "$CURRENT_SESSION_ID" ] && [ "$CURRENT_SESSION_ID" != "unknown" ]; then
|
|
163
|
-
# Check if THIS session has saved turns (for /clear continuity)
|
|
164
|
-
TURN_COUNTER_FILE="$PROJECT_SESSION_DIR/${CURRENT_SESSION_ID}.turn"
|
|
165
|
-
if [ -f "$TURN_COUNTER_FILE" ]; then
|
|
166
|
-
SAVED_TURN_COUNT=$(cat "$TURN_COUNTER_FILE" 2>/dev/null || echo "0")
|
|
167
|
-
MOST_RECENT_SESSION="$CURRENT_SESSION_ID"
|
|
168
|
-
else
|
|
169
|
-
# Fresh start: find most recent session in project
|
|
170
|
-
MOST_RECENT_FILE=$(ls -t "$PROJECT_SESSION_DIR"/*.turn 2>/dev/null | head -1)
|
|
171
|
-
if [ -n "$MOST_RECENT_FILE" ]; then
|
|
172
|
-
MOST_RECENT_SESSION=$(basename "$MOST_RECENT_FILE" .turn)
|
|
173
|
-
SAVED_TURN_COUNT=$(cat "$MOST_RECENT_FILE" 2>/dev/null || echo "0")
|
|
174
|
-
fi
|
|
175
|
-
fi
|
|
176
|
-
fi
|
|
177
|
-
|
|
178
|
-
# Save current session info
|
|
179
|
-
if [ -n "$CURRENT_SESSION_ID" ]; then
|
|
180
|
-
cat > "$SESSION_FILE" << EOF
|
|
181
|
-
{
|
|
182
|
-
"session_id": "$CURRENT_SESSION_ID",
|
|
183
|
-
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
184
|
-
"project_root": "$PROJECT_ROOT"
|
|
185
|
-
}
|
|
186
|
-
EOF
|
|
187
|
-
fi
|
|
188
|
-
|
|
189
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
190
|
-
# GOLDEN LOOP: Initialize session tracking file
|
|
191
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
192
|
-
GOLDEN_LOOP_FILE="$PROJECT_ROOT/.ekkos/golden-loop-current.json"
|
|
193
|
-
mkdir -p "$PROJECT_ROOT/.ekkos" 2>/dev/null || true
|
|
194
|
-
|
|
195
|
-
# Initialize with session start state using Node (no jq)
|
|
196
|
-
node -e "
|
|
197
|
-
const fs = require('fs');
|
|
198
|
-
const data = {
|
|
199
|
-
phase: 'idle',
|
|
200
|
-
turn: 0,
|
|
201
|
-
session: '$CURRENT_SESSION_ID',
|
|
202
|
-
timestamp: new Date().toISOString(),
|
|
203
|
-
stats: { retrieved: 0, applied: 0, forged: 0 }
|
|
204
|
-
};
|
|
205
|
-
fs.writeFileSync('$GOLDEN_LOOP_FILE', JSON.stringify(data, null, 2));
|
|
206
|
-
" 2>/dev/null || true
|
|
207
|
-
|
|
208
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
209
|
-
# COLORS
|
|
210
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
211
|
-
CYAN='\033[0;36m'
|
|
212
|
-
GREEN='\033[0;32m'
|
|
213
|
-
YELLOW='\033[1;33m'
|
|
214
|
-
MAGENTA='\033[0;35m'
|
|
215
|
-
DIM='\033[2m'
|
|
216
|
-
BOLD='\033[1m'
|
|
217
|
-
RESET='\033[0m'
|
|
218
|
-
|
|
219
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
220
|
-
# AUTO-RESTORE REMOVED: Manual /continue only (saves 79% token burn!)
|
|
221
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
222
|
-
# WHY REMOVED:
|
|
223
|
-
# - Auto-restore burned 5,000 tokens per turn on session start
|
|
224
|
-
# - Manual /continue: one-time cost + clean slate (79% token savings!)
|
|
225
|
-
# - Manual /continue is 10x more powerful (Bash + multi-source + narrative)
|
|
226
|
-
#
|
|
227
|
-
# KEPT: Time Machine feature (explicit user request)
|
|
228
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
229
|
-
|
|
230
|
-
# Handle Time Machine requests (explicit user action)
|
|
231
|
-
if [ -n "$TIME_MACHINE_SESSION" ]; then
|
|
232
|
-
echo "" >&2
|
|
233
|
-
echo -e "${MAGENTA}${BOLD} TIME MACHINE${RESET} ${DIM}| Restoring past session: ${TIME_MACHINE_SESSION:0:12}...${RESET}" >&2
|
|
234
|
-
|
|
235
|
-
# Build recall request with turn range
|
|
236
|
-
RECALL_BODY="{\"session_id\": \"${TIME_MACHINE_SESSION}\", \"last_n\": 15, \"format\": \"summary\"}"
|
|
237
|
-
|
|
238
|
-
if [ -n "$TIME_MACHINE_FROM_TURN" ] && [ -n "$TIME_MACHINE_TO_TURN" ]; then
|
|
239
|
-
RECALL_BODY="{\"session_id\": \"${TIME_MACHINE_SESSION}\", \"from_turn\": ${TIME_MACHINE_FROM_TURN}, \"to_turn\": ${TIME_MACHINE_TO_TURN}, \"format\": \"summary\"}"
|
|
240
|
-
elif [ -n "$TIME_MACHINE_FROM_TURN" ]; then
|
|
241
|
-
RECALL_BODY="{\"session_id\": \"${TIME_MACHINE_SESSION}\", \"from_turn\": ${TIME_MACHINE_FROM_TURN}, \"format\": \"summary\"}"
|
|
242
|
-
fi
|
|
243
|
-
|
|
244
|
-
# Fetch turns from L2
|
|
245
|
-
RESTORE_RESPONSE=$(curl -s -X POST "$MEMORY_API_URL/api/v1/turns/recall" \
|
|
246
|
-
-H "Authorization: Bearer $AUTH_TOKEN" \
|
|
247
|
-
-H "Content-Type: application/json" \
|
|
248
|
-
-d "$RECALL_BODY" \
|
|
249
|
-
--connect-timeout 3 \
|
|
250
|
-
--max-time 5 2>/dev/null || echo '{"error":"timeout"}')
|
|
251
|
-
|
|
252
|
-
# Check if we got turns back using Node (no jq)
|
|
253
|
-
RESTORED_COUNT=$(echo "$RESTORE_RESPONSE" | node -e "
|
|
254
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
255
|
-
console.log((d.turns || []).length);
|
|
256
|
-
" 2>/dev/null || echo "0")
|
|
257
|
-
|
|
258
|
-
if [ "$RESTORED_COUNT" -gt 0 ]; then
|
|
259
|
-
echo -e "${MAGENTA} ✓${RESET} Restored ${RESTORED_COUNT} turns from past session" >&2
|
|
260
|
-
echo "" >&2
|
|
261
|
-
echo -e "${MAGENTA}${BOLD}## Time Machine Context${RESET}" >&2
|
|
262
|
-
echo "" >&2
|
|
263
|
-
|
|
264
|
-
# Output the turns as context using Node (no jq)
|
|
265
|
-
TURNS_OUTPUT=$(echo "$RESTORE_RESPONSE" | node -e "
|
|
266
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
267
|
-
(d.turns || []).forEach(t => {
|
|
268
|
-
const q = (t.user_query || '').substring(0, 100);
|
|
269
|
-
const r = (t.assistant_response || '').substring(0, 200);
|
|
270
|
-
console.log('**Turn ' + (t.turn_number || '?') + '**: ' + q + '...');
|
|
271
|
-
console.log('> ' + r + '...');
|
|
272
|
-
console.log('');
|
|
273
|
-
});
|
|
274
|
-
" 2>/dev/null || echo "")
|
|
275
|
-
echo "$TURNS_OUTPUT" >&2
|
|
276
|
-
echo "$TURNS_OUTPUT"
|
|
277
|
-
|
|
278
|
-
echo "" >&2
|
|
279
|
-
echo -e "${DIM}You've traveled to a past session. Continue from here!${RESET}" >&2
|
|
280
|
-
echo "" >&2
|
|
281
|
-
fi
|
|
282
|
-
fi
|
|
283
|
-
|
|
284
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
285
|
-
# DIRECTIVE RETRIEVAL: Fetch user's MUST/NEVER/PREFER/AVOID rules
|
|
286
|
-
# ═══════════════════════════════════════════════════════════════════════════
|
|
287
|
-
DIRECTIVES_INJECTED=false
|
|
288
|
-
DIRECTIVE_COUNT=0
|
|
289
|
-
|
|
290
|
-
# Only fetch if we have auth
|
|
291
|
-
if [ -n "$AUTH_TOKEN" ]; then
|
|
292
|
-
# Fetch directives (top 20 by priority to avoid token bloat)
|
|
293
|
-
DIRECTIVES_RESPONSE=$(curl -s -X GET "$MEMORY_API_URL/api/v1/memory/directives?limit=20" \
|
|
294
|
-
-H "Authorization: Bearer $AUTH_TOKEN" \
|
|
295
|
-
--connect-timeout 2 \
|
|
296
|
-
--max-time 3 2>/dev/null || echo '{}')
|
|
297
|
-
|
|
298
|
-
# Parse response using Node (no jq)
|
|
299
|
-
DIRECTIVE_COUNT=$(echo "$DIRECTIVES_RESPONSE" | node -e "
|
|
300
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
301
|
-
console.log(d.count || 0);
|
|
302
|
-
" 2>/dev/null || echo "0")
|
|
303
|
-
|
|
304
|
-
if [ "$DIRECTIVE_COUNT" -gt 0 ]; then
|
|
305
|
-
DIRECTIVES_INJECTED=true
|
|
306
|
-
|
|
307
|
-
# Extract MUST/NEVER/PREFER/AVOID arrays using Node
|
|
308
|
-
echo "<system-reminder>"
|
|
309
|
-
echo "USER DIRECTIVES (FOLLOW THESE):"
|
|
310
|
-
echo ""
|
|
311
|
-
|
|
312
|
-
echo "$DIRECTIVES_RESPONSE" | node -e "
|
|
313
|
-
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8') || '{}');
|
|
314
|
-
const types = ['MUST', 'NEVER', 'PREFER', 'AVOID'];
|
|
315
|
-
types.forEach(type => {
|
|
316
|
-
const rules = (d[type] || []).slice(0, 5);
|
|
317
|
-
if (rules.length > 0) {
|
|
318
|
-
console.log(type + ':');
|
|
319
|
-
rules.forEach(r => console.log(' - ' + (r.rule || '')));
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
" 2>/dev/null || true
|
|
323
|
-
|
|
324
|
-
echo "</system-reminder>"
|
|
325
|
-
echo -e "${GREEN} ${DIRECTIVE_COUNT} directives loaded${RESET}" >&2
|
|
326
|
-
fi
|
|
327
|
-
fi
|
|
328
|
-
|
|
329
|
-
# Simple status display (no auto-restore)
|
|
330
|
-
if [ "$SAVED_TURN_COUNT" -gt 0 ]; then
|
|
331
|
-
echo "" >&2
|
|
332
|
-
if [ "$SAVED_TURN_COUNT" -gt 0 ]; then
|
|
333
|
-
echo -e "${CYAN}${BOLD} ekkOS${RESET} ${DIM}|${RESET} Session: ${CURRENT_SESSION_ID:-$SESSION_ID} ${DIM}|${RESET} ${GREEN}${SAVED_TURN_COUNT} turns${RESET}" >&2
|
|
334
|
-
else
|
|
335
|
-
echo -e "${CYAN}${BOLD} ekkOS${RESET} ${DIM}|${RESET} Session: ${CURRENT_SESSION_ID:-$SESSION_ID} ${DIM}| New session${RESET}" >&2
|
|
336
|
-
fi
|
|
337
|
-
fi
|
|
338
|
-
|
|
339
|
-
# Final confirmation that's always visible
|
|
340
|
-
if [ -n "$TIME_MACHINE_SESSION" ]; then
|
|
341
|
-
echo -e "${MAGENTA}------------------------------------------------------------------------${RESET}" >&2
|
|
342
|
-
echo -e "${MAGENTA} ${RESET} Time Machine active - Restored from session ${TIME_MACHINE_SESSION:0:12}..." >&2
|
|
343
|
-
echo -e "${MAGENTA}------------------------------------------------------------------------${RESET}" >&2
|
|
344
|
-
elif [ "$SAVED_TURN_COUNT" -gt 0 ]; then
|
|
345
|
-
echo -e "${GREEN}------------------------------------------------------------------------${RESET}" >&2
|
|
346
|
-
echo -e "${GREEN}✓${RESET} Session continued - ${SAVED_TURN_COUNT} turns preserved - Ready to resume" >&2
|
|
347
|
-
echo -e "${GREEN}------------------------------------------------------------------------${RESET}" >&2
|
|
348
|
-
else
|
|
349
|
-
echo -e "${CYAN}✓${RESET} New session started" >&2
|
|
350
|
-
fi
|
|
351
|
-
echo "" >&2
|
|
352
|
-
|
|
353
|
-
exit 0
|