nexo-brain 5.3.26 → 5.3.27

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 (211) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/src/server.py +3 -0
  4. package/src/tools_sessions.py +6 -1
  5. package/src/dashboard/static/favicon 2.svg +0 -32
  6. package/src/dashboard/static/nexo-logo 2.png +0 -0
  7. package/src/dashboard/static/nexo-logo 2.svg +0 -40
  8. package/src/dashboard/static/style 2.css +0 -2458
  9. package/src/dashboard/templates/adaptive 2.html +0 -118
  10. package/src/dashboard/templates/artifacts 2.html +0 -133
  11. package/src/dashboard/templates/backups 2.html +0 -136
  12. package/src/dashboard/templates/base 2.html +0 -417
  13. package/src/dashboard/templates/calendar 2.html +0 -591
  14. package/src/dashboard/templates/chat 2.html +0 -356
  15. package/src/dashboard/templates/claims 2.html +0 -259
  16. package/src/dashboard/templates/cortex 2.html +0 -321
  17. package/src/dashboard/templates/credentials 2.html +0 -128
  18. package/src/dashboard/templates/crons 2.html +0 -370
  19. package/src/dashboard/templates/dashboard 2.html +0 -494
  20. package/src/dashboard/templates/dreams 2.html +0 -252
  21. package/src/dashboard/templates/email 2.html +0 -160
  22. package/src/dashboard/templates/evolution 2.html +0 -189
  23. package/src/dashboard/templates/feed 2.html +0 -249
  24. package/src/dashboard/templates/followup_health 2.html +0 -170
  25. package/src/dashboard/templates/graph 2.html +0 -201
  26. package/src/dashboard/templates/guard 2.html +0 -259
  27. package/src/dashboard/templates/inbox 2.html +0 -251
  28. package/src/dashboard/templates/memory 2.html +0 -420
  29. package/src/dashboard/templates/operations 2.html +0 -608
  30. package/src/dashboard/templates/plugins 2.html +0 -185
  31. package/src/dashboard/templates/protocol 2.html +0 -199
  32. package/src/dashboard/templates/rules 2.html +0 -246
  33. package/src/dashboard/templates/sentiment 2.html +0 -247
  34. package/src/dashboard/templates/sessions 2.html +0 -218
  35. package/src/dashboard/templates/skills 2.html +0 -329
  36. package/src/dashboard/templates/somatic 2.html +0 -73
  37. package/src/dashboard/templates/triggers 2.html +0 -133
  38. package/src/dashboard/templates/trust 2.html +0 -360
  39. package/src/db/__init__ 2.py +0 -259
  40. package/src/db/_core 2.py +0 -437
  41. package/src/db/_credentials 2.py +0 -124
  42. package/src/db/_episodic 2.py +0 -762
  43. package/src/db/_evolution 2.py +0 -54
  44. package/src/db/_fts 2.py +0 -406
  45. package/src/db/_goal_profiles 2.py +0 -376
  46. package/src/db/_hot_context 2.py +0 -660
  47. package/src/db/_outcomes 2.py +0 -800
  48. package/src/db/_personal_scripts 2.py +0 -582
  49. package/src/db/_sessions 2.py +0 -330
  50. package/src/db/_tasks 2.py +0 -91
  51. package/src/db/_watchers 2.py +0 -173
  52. package/src/doctor/formatters 2.py +0 -52
  53. package/src/doctor/models 2.py +0 -69
  54. package/src/doctor/planes 2.py +0 -87
  55. package/src/doctor/providers/__init__ 2.py +0 -1
  56. package/src/doctor/providers/deep 2.py +0 -367
  57. package/src/evolution_cycle 2.py +0 -519
  58. package/src/hooks/auto_capture 2.py +0 -208
  59. package/src/hooks/caffeinate-guard 2.sh +0 -8
  60. package/src/hooks/capture-session 2.sh +0 -21
  61. package/src/hooks/capture-tool-logs 2.sh +0 -158
  62. package/src/hooks/daily-briefing-check 2.sh +0 -33
  63. package/src/hooks/heartbeat-enforcement 2.py +0 -90
  64. package/src/hooks/heartbeat-posttool 2.sh +0 -18
  65. package/src/hooks/inbox-hook 2.sh +0 -76
  66. package/src/hooks/post-compact 2.sh +0 -152
  67. package/src/hooks/pre-compact 2.sh +0 -169
  68. package/src/hooks/protocol-guardrail 2.sh +0 -10
  69. package/src/hooks/protocol-pretool-guardrail 2.sh +0 -9
  70. package/src/hooks/session-stop 2.sh +0 -52
  71. package/src/kg_populate 2.py +0 -292
  72. package/src/maintenance 2.py +0 -53
  73. package/src/memory_backends 2.py +0 -71
  74. package/src/migrate_embeddings 2.py +0 -124
  75. package/src/nexo_sdk 2.py +0 -103
  76. package/src/observability 2.py +0 -199
  77. package/src/plugin_loader 2.py +0 -217
  78. package/src/plugins/__init__ 2.py +0 -0
  79. package/src/plugins/artifact_registry 2.py +0 -450
  80. package/src/plugins/backup 2.py +0 -127
  81. package/src/plugins/claims_tools 2.py +0 -119
  82. package/src/plugins/cognitive_memory 2.py +0 -609
  83. package/src/plugins/core_rules 2.py +0 -252
  84. package/src/plugins/cortex 2.py +0 -1155
  85. package/src/plugins/entities 2.py +0 -67
  86. package/src/plugins/episodic_memory 2.py +0 -560
  87. package/src/plugins/evolution 2.py +0 -167
  88. package/src/plugins/goal_engine 2.py +0 -142
  89. package/src/plugins/guard 2.py +0 -862
  90. package/src/plugins/impact 2.py +0 -29
  91. package/src/plugins/knowledge_graph_tools 2.py +0 -137
  92. package/src/plugins/media_memory_tools 2.py +0 -98
  93. package/src/plugins/memory_export 2.py +0 -196
  94. package/src/plugins/outcomes 2.py +0 -130
  95. package/src/plugins/personal_scripts 2.py +0 -117
  96. package/src/plugins/preferences 2.py +0 -47
  97. package/src/plugins/protocol 2.py +0 -1449
  98. package/src/plugins/simple_api 2.py +0 -106
  99. package/src/plugins/skills 2.py +0 -341
  100. package/src/plugins/state_watchers 2.py +0 -79
  101. package/src/plugins/update 2.py +0 -986
  102. package/src/plugins/user_state_tools 2.py +0 -43
  103. package/src/plugins/workflow 2.py +0 -588
  104. package/src/protocol_settings 2.py +0 -59
  105. package/src/public_contribution 2.py +0 -466
  106. package/src/public_evolution_queue 2.py +0 -241
  107. package/src/requirements 2.txt +0 -14
  108. package/src/retroactive_learnings 2.py +0 -373
  109. package/src/rules/__init__ 2.py +0 -0
  110. package/src/rules/core-rules 2.json +0 -331
  111. package/src/rules/migrate 2.py +0 -207
  112. package/src/runtime_power 2.py +0 -874
  113. package/src/script_registry 2.py +0 -1559
  114. package/src/scripts/check-context 2.py +0 -272
  115. package/src/scripts/deep-sleep/apply_findings 2.py +0 -2327
  116. package/src/scripts/deep-sleep/collect 2.py +0 -928
  117. package/src/scripts/deep-sleep/extract 2.py +0 -330
  118. package/src/scripts/deep-sleep/extract-prompt 2.md +0 -285
  119. package/src/scripts/deep-sleep/synthesize 2.py +0 -312
  120. package/src/scripts/deep-sleep/synthesize-prompt 2.md +0 -336
  121. package/src/scripts/nexo-agent-run 2.py +0 -75
  122. package/src/scripts/nexo-auto-update 2.py +0 -6
  123. package/src/scripts/nexo-backup 2.sh +0 -25
  124. package/src/scripts/nexo-brain-activation 2.sh +0 -140
  125. package/src/scripts/nexo-catchup 2.py +0 -300
  126. package/src/scripts/nexo-cognitive-decay 2.py +0 -257
  127. package/src/scripts/nexo-cortex-cycle 2.py +0 -293
  128. package/src/scripts/nexo-cron-wrapper 2.sh +0 -53
  129. package/src/scripts/nexo-daily-self-audit 2.py +0 -2161
  130. package/src/scripts/nexo-dashboard 2.sh +0 -29
  131. package/src/scripts/nexo-deep-sleep 2.sh +0 -86
  132. package/src/scripts/nexo-evolution-run 2.py +0 -1664
  133. package/src/scripts/nexo-followup-hygiene 2.py +0 -139
  134. package/src/scripts/nexo-hook-record 2.py +0 -42
  135. package/src/scripts/nexo-immune 2.py +0 -936
  136. package/src/scripts/nexo-impact-scorer 2.py +0 -117
  137. package/src/scripts/nexo-inbox-hook 2.sh +0 -74
  138. package/src/scripts/nexo-install 2.py +0 -6
  139. package/src/scripts/nexo-learning-housekeep 2.py +0 -401
  140. package/src/scripts/nexo-learning-validator 2.py +0 -266
  141. package/src/scripts/nexo-migrate 2.py +0 -260
  142. package/src/scripts/nexo-outcome-checker 2.py +0 -127
  143. package/src/scripts/nexo-postmortem-consolidator 2.py +0 -456
  144. package/src/scripts/nexo-pre-commit 2.py +0 -120
  145. package/src/scripts/nexo-prevent-sleep 2.sh +0 -35
  146. package/src/scripts/nexo-proactive-dashboard 2.py +0 -354
  147. package/src/scripts/nexo-reflection 2.py +0 -256
  148. package/src/scripts/nexo-runtime-preflight 2.py +0 -274
  149. package/src/scripts/nexo-sleep 2.py +0 -631
  150. package/src/scripts/nexo-snapshot-restore 2.sh +0 -35
  151. package/src/scripts/nexo-sync-clients 2.py +0 -16
  152. package/src/scripts/nexo-synthesis 2.py +0 -475
  153. package/src/scripts/nexo-tcc-approve 2.sh +0 -79
  154. package/src/scripts/nexo-update 2.sh +0 -306
  155. package/src/scripts/nexo-watchdog 2.sh +0 -1207
  156. package/src/scripts/nexo-watchdog-smoke 2.py +0 -119
  157. package/src/scripts/rehydrate_learnings_from_archive 2.py +0 -245
  158. package/src/server 2.py +0 -1296
  159. package/src/skills/run-nexo-audit-phase/guide 2.md +0 -43
  160. package/src/skills/run-nexo-audit-phase/skill 2.json +0 -59
  161. package/src/skills/run-nexo-core-fix-cycle/guide 2.md +0 -17
  162. package/src/skills/run-nexo-core-fix-cycle/script 2.py +0 -276
  163. package/src/skills/run-nexo-core-fix-cycle/skill 2.json +0 -58
  164. package/src/skills/run-release-final-audit/guide 2.md +0 -16
  165. package/src/skills/run-release-final-audit/script 2.py +0 -259
  166. package/src/skills/run-release-final-audit/skill 2.json +0 -77
  167. package/src/skills/run-runtime-doctor/guide 2.md +0 -12
  168. package/src/skills/run-runtime-doctor/script 2.py +0 -21
  169. package/src/skills/run-runtime-doctor/skill 2.json +0 -25
  170. package/src/skills_runtime 2.py +0 -932
  171. package/src/state_watchers_runtime 2.py +0 -475
  172. package/src/storage_router 2.py +0 -32
  173. package/src/system_catalog 2.py +0 -786
  174. package/src/tools_coordination 2.py +0 -103
  175. package/src/tools_credentials 2.py +0 -68
  176. package/src/tools_drive 2.py +0 -487
  177. package/src/tools_hot_context 2.py +0 -163
  178. package/src/tools_learnings 2.py +0 -612
  179. package/src/tools_menu 2.py +0 -229
  180. package/src/tools_reminders 2.py +0 -88
  181. package/src/tools_reminders_crud 2.py +0 -363
  182. package/src/tools_sessions 2.py +0 -1054
  183. package/src/tools_system_catalog 2.py +0 -19
  184. package/src/tools_task_history 2.py +0 -57
  185. package/src/tools_transcripts 2.py +0 -98
  186. package/src/transcript_utils 2.py +0 -412
  187. package/src/user_context 2.py +0 -46
  188. package/src/user_data_portability 2.py +0 -328
  189. package/src/user_state_model 2.py +0 -170
  190. package/templates/CLAUDE.md 2.template +0 -108
  191. package/templates/CODEX.AGENTS.md 2.template +0 -66
  192. package/templates/launchagents/README 2.md +0 -132
  193. package/templates/launchagents/com.nexo.auto-close-sessions 2.plist +0 -39
  194. package/templates/launchagents/com.nexo.catchup 2.plist +0 -39
  195. package/templates/launchagents/com.nexo.cognitive-decay 2.plist +0 -40
  196. package/templates/launchagents/com.nexo.dashboard 2.plist +0 -43
  197. package/templates/launchagents/com.nexo.deep-sleep 2.plist +0 -43
  198. package/templates/launchagents/com.nexo.evolution 2.plist +0 -44
  199. package/templates/launchagents/com.nexo.followup-hygiene 2.plist +0 -45
  200. package/templates/launchagents/com.nexo.immune 2.plist +0 -41
  201. package/templates/launchagents/com.nexo.postmortem 2.plist +0 -45
  202. package/templates/launchagents/com.nexo.self-audit 2.plist +0 -47
  203. package/templates/launchagents/com.nexo.synthesis 2.plist +0 -45
  204. package/templates/launchagents/com.nexo.watchdog 2.plist +0 -37
  205. package/templates/nexo_helper 2.py +0 -301
  206. package/templates/openclaw 2.json +0 -13
  207. package/templates/plugin-template 2.py +0 -40
  208. package/templates/script-template 2.py +0 -59
  209. package/templates/script-template 2.sh +0 -13
  210. package/templates/skill-script-template 2.py +0 -48
  211. package/templates/skill-template 2.md +0 -33
@@ -1,252 +0,0 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Dream Journal{% endblock %}
4
- {% block page_title %}Dream Journal{% endblock %}
5
-
6
- {% block head %}
7
- <style>
8
- .dream-bg {
9
- position: fixed;
10
- top: 0; left: 0; right: 0; bottom: 0;
11
- pointer-events: none;
12
- z-index: 0;
13
- overflow: hidden;
14
- }
15
- .star {
16
- position: absolute;
17
- width: 2px; height: 2px;
18
- background: white;
19
- border-radius: 50%;
20
- opacity: 0;
21
- animation: twinkle var(--duration) ease-in-out var(--delay) infinite;
22
- }
23
- @keyframes twinkle {
24
- 0%, 100% { opacity: 0; }
25
- 50% { opacity: var(--max-opacity); }
26
- }
27
- @keyframes floatUp {
28
- 0% { opacity: 0; transform: translateY(20px) scale(0.95); }
29
- 100% { opacity: 1; transform: translateY(0) scale(1); }
30
- }
31
- .dream-card {
32
- animation: floatUp 0.6s ease-out forwards;
33
- opacity: 0;
34
- transition: border-color 0.3s, box-shadow 0.3s, transform 0.3s;
35
- }
36
- .dream-card:hover {
37
- border-color: rgba(139, 92, 246, 0.4);
38
- box-shadow: 0 0 30px rgba(139, 92, 246, 0.12);
39
- transform: translateY(-2px);
40
- }
41
- .insight-glow {
42
- text-shadow: 0 0 20px rgba(139, 92, 246, 0.3);
43
- }
44
- .connection-line {
45
- background: linear-gradient(90deg, rgba(99, 102, 241, 0.3), rgba(139, 92, 246, 0.6), rgba(99, 102, 241, 0.3));
46
- height: 1px;
47
- position: relative;
48
- }
49
- .connection-line::after {
50
- content: '';
51
- position: absolute;
52
- top: -1px; left: 0; right: 0; height: 3px;
53
- background: linear-gradient(90deg, transparent, rgba(139, 92, 246, 0.4), transparent);
54
- animation: shimmer 3s ease-in-out infinite;
55
- }
56
- @keyframes shimmer {
57
- 0%, 100% { opacity: 0.3; }
58
- 50% { opacity: 1; }
59
- }
60
- .night-divider {
61
- position: relative;
62
- text-align: center;
63
- margin: 2rem 0 1.5rem;
64
- }
65
- .night-divider::before {
66
- content: '';
67
- position: absolute;
68
- left: 0; right: 0; top: 50%;
69
- height: 1px;
70
- background: linear-gradient(90deg, transparent, rgba(99, 102, 241, 0.3), transparent);
71
- }
72
- .night-divider span {
73
- position: relative;
74
- background: #030712;
75
- padding: 0 1rem;
76
- }
77
- </style>
78
- {% endblock %}
79
-
80
- {% block content %}
81
- <!-- Star background -->
82
- <div class="dream-bg" id="star-field"></div>
83
-
84
- <!-- Stats header -->
85
- <div class="relative z-10 grid grid-cols-2 sm:grid-cols-3 gap-4 mb-6">
86
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 text-center">
87
- <div class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-2">Total Dreams</div>
88
- <div class="text-3xl font-display font-bold text-indigo-300" id="stat-total">--</div>
89
- </div>
90
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 text-center">
91
- <div class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-2">Insights Generated</div>
92
- <div class="text-3xl font-display font-bold text-violet-300" id="stat-insights">--</div>
93
- </div>
94
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 text-center sm:col-span-1 col-span-2">
95
- <div class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-2">Sleep Entries</div>
96
- <div class="text-3xl font-display font-bold text-slate-300" id="stat-sleep">--</div>
97
- </div>
98
- </div>
99
-
100
- <!-- Dream Timeline -->
101
- <div class="relative z-10 mb-8" id="dream-timeline">
102
- <h2 class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-4 flex items-center gap-2">
103
- <svg class="w-4 h-4 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
104
- Dream Timeline
105
- </h2>
106
- <div id="dreams-container" class="space-y-1">
107
- <div class="text-xs text-slate-600 text-center py-12">Loading dream data...</div>
108
- </div>
109
- </div>
110
-
111
- <!-- Sleep Diary -->
112
- <div class="relative z-10" id="sleep-section">
113
- <h2 class="text-xs uppercase tracking-wider text-slate-500 font-semibold mb-4 flex items-center gap-2">
114
- <svg class="w-4 h-4 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
115
- Sleep Diary
116
- </h2>
117
- <div id="sleep-container" class="space-y-3">
118
- <div class="text-xs text-slate-600 text-center py-8">Loading sleep entries...</div>
119
- </div>
120
- </div>
121
- {% endblock %}
122
-
123
- {% block scripts %}
124
- <script>
125
- const REFRESH_MS = 60000;
126
-
127
- // Generate star field
128
- function createStars() {
129
- const field = document.getElementById('star-field');
130
- for (let i = 0; i < 80; i++) {
131
- const star = document.createElement('div');
132
- star.className = 'star';
133
- star.style.left = Math.random() * 100 + '%';
134
- star.style.top = Math.random() * 100 + '%';
135
- star.style.setProperty('--duration', (2 + Math.random() * 4) + 's');
136
- star.style.setProperty('--delay', (Math.random() * 3) + 's');
137
- star.style.setProperty('--max-opacity', (0.2 + Math.random() * 0.5).toString());
138
- const size = 1 + Math.random() * 2;
139
- star.style.width = size + 'px';
140
- star.style.height = size + 'px';
141
- field.appendChild(star);
142
- }
143
- }
144
-
145
- function groupByNight(dreams) {
146
- const groups = {};
147
- for (const d of dreams) {
148
- const date = (d.created_at || '').split(/[T ]/)[0] || 'Unknown';
149
- if (!groups[date]) groups[date] = [];
150
- groups[date].push(d);
151
- }
152
- return groups;
153
- }
154
-
155
- function renderDreamCard(d, idx) {
156
- const insight = d.insight_content || d.insight || 'No insight recorded';
157
- const memA = d.memory_a_content || `Memory #${d.memory_a_id || '?'}`;
158
- const memB = d.memory_b_content || `Memory #${d.memory_b_id || '?'}`;
159
- const created = d.created_at ? relativeTime(d.created_at) : '';
160
- const delay = idx * 0.1;
161
-
162
- return `<div class="dream-card bg-slate-900/50 border border-indigo-500/20 rounded-xl p-5 mb-3" style="animation-delay:${delay}s">
163
- <div class="flex items-center justify-between mb-3">
164
- <div class="flex items-center gap-2">
165
- <svg class="w-4 h-4 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
166
- <span class="text-xs text-indigo-400 font-medium">Dream Connection</span>
167
- </div>
168
- <span class="text-[10px] text-slate-600 font-mono">${escapeHtml(created)}</span>
169
- </div>
170
-
171
- <!-- Two memories connected -->
172
- <div class="flex items-stretch gap-0 mb-4">
173
- <div class="flex-1 bg-slate-800/50 border border-slate-700/50 rounded-lg p-3">
174
- <div class="text-[10px] uppercase tracking-wider text-slate-500 mb-1">Memory A</div>
175
- <p class="text-xs text-slate-300 leading-relaxed">${escapeHtml(typeof memA === 'string' ? (memA.length > 120 ? memA.substring(0, 120) + '...' : memA) : String(memA))}</p>
176
- </div>
177
- <div class="flex flex-col items-center justify-center px-3">
178
- <div class="w-8 connection-line"></div>
179
- <svg class="w-4 h-4 text-violet-400 my-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
180
- <div class="w-8 connection-line"></div>
181
- </div>
182
- <div class="flex-1 bg-slate-800/50 border border-slate-700/50 rounded-lg p-3">
183
- <div class="text-[10px] uppercase tracking-wider text-slate-500 mb-1">Memory B</div>
184
- <p class="text-xs text-slate-300 leading-relaxed">${escapeHtml(typeof memB === 'string' ? (memB.length > 120 ? memB.substring(0, 120) + '...' : memB) : String(memB))}</p>
185
- </div>
186
- </div>
187
-
188
- <!-- Insight -->
189
- <div class="bg-violet-500/5 border border-violet-500/20 rounded-lg p-3">
190
- <div class="text-[10px] uppercase tracking-wider text-violet-400 font-semibold mb-1">Insight</div>
191
- <p class="text-sm text-violet-200 leading-relaxed insight-glow">${escapeHtml(insight)}</p>
192
- </div>
193
- </div>`;
194
- }
195
-
196
- function renderSleepEntry(entry) {
197
- const content = entry.content || entry.summary || 'Sleep cycle completed';
198
- const created = entry.created_at ? relativeTime(entry.created_at) : '';
199
- return `<div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-4 transition-all hover:border-slate-700/50">
200
- <div class="flex items-center justify-between mb-2">
201
- <span class="text-[10px] px-1.5 py-0.5 rounded bg-slate-700 text-slate-400 font-medium">sleep</span>
202
- <span class="text-[10px] text-slate-600 font-mono">${escapeHtml(created)}</span>
203
- </div>
204
- <p class="text-sm text-slate-300 leading-relaxed">${escapeHtml(content)}</p>
205
- </div>`;
206
- }
207
-
208
- async function loadDreams() {
209
- const data = await fetchJSON('/api/dreams');
210
- if (!data) return;
211
-
212
- const dreams = data.dreams || [];
213
- const sleepEntries = data.sleep_entries || [];
214
-
215
- // Stats
216
- document.getElementById('stat-total').textContent = formatNumber(dreams.length);
217
- document.getElementById('stat-insights').textContent = formatNumber(dreams.filter(d => d.insight_content || d.insight_id).length);
218
- document.getElementById('stat-sleep').textContent = formatNumber(sleepEntries.length);
219
-
220
- // Timeline grouped by night
221
- const container = document.getElementById('dreams-container');
222
- if (dreams.length === 0) {
223
- container.innerHTML = '<div class="text-center py-12"><div class="text-2xl mb-2">&#127769;</div><div class="text-sm text-slate-500">No dreams recorded yet. Dreams are generated during deep sleep cycles.</div></div>';
224
- return;
225
- }
226
-
227
- const groups = groupByNight(dreams);
228
- let html = '';
229
- let cardIdx = 0;
230
- for (const [night, nightDreams] of Object.entries(groups).sort((a, b) => b[0].localeCompare(a[0]))) {
231
- const d = new Date(night + 'T00:00:00');
232
- const label = isNaN(d.getTime()) ? night : d.toLocaleDateString('en', { weekday: 'long', month: 'short', day: 'numeric' });
233
- html += `<div class="night-divider"><span class="text-xs text-indigo-400/60 font-mono">${escapeHtml(label)} &mdash; ${nightDreams.length} dream${nightDreams.length > 1 ? 's' : ''}</span></div>`;
234
- for (const dream of nightDreams) {
235
- html += renderDreamCard(dream, cardIdx++);
236
- }
237
- }
238
- container.innerHTML = html;
239
-
240
- // Sleep entries
241
- const sleepContainer = document.getElementById('sleep-container');
242
- sleepContainer.innerHTML = sleepEntries.length === 0
243
- ? '<div class="text-xs text-slate-600 text-center py-6">No sleep diary entries</div>'
244
- : sleepEntries.map(renderSleepEntry).join('');
245
- }
246
-
247
- // Init
248
- createStars();
249
- loadDreams();
250
- setInterval(loadDreams, REFRESH_MS);
251
- </script>
252
- {% endblock %}
@@ -1,160 +0,0 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Email Monitor{% endblock %}
4
- {% block page_title %}Email Monitor{% endblock %}
5
-
6
- {% block content %}
7
- <div class="space-y-5">
8
- <!-- Stats cards -->
9
- <div class="grid grid-cols-4 gap-4">
10
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-4 card">
11
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-2">Total Emails</div>
12
- <div class="text-xl font-mono font-semibold text-slate-200" id="email-total">--</div>
13
- </div>
14
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-4 card">
15
- <div class="text-xs uppercase tracking-wider text-emerald-400/70 font-medium mb-2">Processed</div>
16
- <div class="text-xl font-mono font-semibold text-emerald-400" id="email-processed">--</div>
17
- </div>
18
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-4 card">
19
- <div class="text-xs uppercase tracking-wider text-amber-400/70 font-medium mb-2">Pending</div>
20
- <div class="text-xl font-mono font-semibold text-amber-400" id="email-pending">--</div>
21
- </div>
22
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-4 card">
23
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-2">Processing Rate</div>
24
- <div class="text-xl font-mono font-semibold text-violet-400" id="email-rate">--%</div>
25
- </div>
26
- </div>
27
-
28
- <!-- Processing funnel -->
29
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 card">
30
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-4">Processing Funnel</div>
31
- <div class="flex items-end gap-1 justify-center" id="funnel" style="height: 80px;">
32
- <!-- JS fills -->
33
- </div>
34
- </div>
35
-
36
- <!-- Recent emails table -->
37
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 card">
38
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-4">Recent Emails</div>
39
- <div class="overflow-x-auto">
40
- <table class="w-full text-left">
41
- <thead>
42
- <tr class="border-b border-slate-800/50">
43
- <th class="text-[10px] uppercase tracking-wider text-slate-500 font-medium pb-2 pr-4">Status</th>
44
- <th class="text-[10px] uppercase tracking-wider text-slate-500 font-medium pb-2 pr-4">From</th>
45
- <th class="text-[10px] uppercase tracking-wider text-slate-500 font-medium pb-2 pr-4">Subject</th>
46
- <th class="text-[10px] uppercase tracking-wider text-slate-500 font-medium pb-2 text-right">Received</th>
47
- </tr>
48
- </thead>
49
- <tbody id="email-table" class="divide-y divide-slate-800/30">
50
- <tr><td colspan="4" class="text-xs text-slate-600 py-8 text-center">loading...</td></tr>
51
- </tbody>
52
- </table>
53
- </div>
54
- </div>
55
-
56
- <!-- Thread grouping -->
57
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 card">
58
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-4">Thread Groups</div>
59
- <div class="space-y-2" id="thread-groups">
60
- <div class="text-xs text-slate-600 py-4 text-center">loading...</div>
61
- </div>
62
- </div>
63
- </div>
64
- {% endblock %}
65
-
66
- {% block scripts %}
67
- <script>
68
- const EMAIL_STATUS = {
69
- processed: { bg: 'bg-emerald-500/10', text: 'text-emerald-400', dot: 'bg-emerald-500' },
70
- pending: { bg: 'bg-amber-500/10', text: 'text-amber-400', dot: 'bg-amber-500' },
71
- failed: { bg: 'bg-red-500/10', text: 'text-red-400', dot: 'bg-red-500' },
72
- skipped: { bg: 'bg-slate-500/10', text: 'text-slate-400', dot: 'bg-slate-600' },
73
- };
74
-
75
- function renderFunnel(stats) {
76
- const container = document.getElementById('funnel');
77
- const total = stats.total || 1;
78
- const processed = stats.processed || 0;
79
- const pending = stats.pending || 0;
80
- const failed = total - processed - pending;
81
-
82
- const stages = [
83
- { label: 'Received', value: total, color: 'bg-violet-500' },
84
- { label: 'Processed', value: processed, color: 'bg-emerald-500' },
85
- { label: 'Pending', value: pending, color: 'bg-amber-500' },
86
- ];
87
- if (failed > 0) stages.push({ label: 'Failed', value: failed, color: 'bg-red-500' });
88
-
89
- const maxVal = Math.max(...stages.map(s => s.value), 1);
90
-
91
- container.innerHTML = stages.map(s => {
92
- const pct = Math.max(8, (s.value / maxVal) * 100);
93
- return `<div class="flex-1 flex flex-col items-center gap-1">
94
- <span class="text-xs font-mono text-slate-300">${s.value}</span>
95
- <div class="w-full rounded-t-md ${s.color} transition-all duration-500" style="height:${pct}%"></div>
96
- <span class="text-[10px] text-slate-500">${s.label}</span>
97
- </div>`;
98
- }).join('');
99
- }
100
-
101
- function renderTable(emails) {
102
- const tbody = document.getElementById('email-table');
103
- if (!emails || !emails.length) {
104
- tbody.innerHTML = '<tr><td colspan="4" class="text-xs text-slate-600 py-8 text-center">No emails found</td></tr>';
105
- return;
106
- }
107
-
108
- tbody.innerHTML = emails.map(e => {
109
- const status = e.status || 'pending';
110
- const sc = EMAIL_STATUS[status] || EMAIL_STATUS.pending;
111
- return `<tr class="hover:bg-slate-800/20 transition-colors">
112
- <td class="py-2.5 pr-4"><span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-[10px] font-medium ${sc.bg} ${sc.text}"><span class="w-1.5 h-1.5 rounded-full ${sc.dot}"></span>${escapeHtml(status)}</span></td>
113
- <td class="py-2.5 pr-4 text-xs text-slate-300 truncate max-w-[200px]">${escapeHtml(e.from_addr || '--')}</td>
114
- <td class="py-2.5 pr-4 text-xs text-slate-400 truncate max-w-[300px]">${escapeHtml(e.subject || '(no subject)')}</td>
115
- <td class="py-2.5 text-xs text-slate-500 text-right whitespace-nowrap">${relativeTime(e.received_at)}</td>
116
- </tr>`;
117
- }).join('');
118
- }
119
-
120
- function renderThreads(threads) {
121
- const container = document.getElementById('thread-groups');
122
- if (!threads || !threads.length) {
123
- container.innerHTML = '<div class="text-xs text-slate-600 py-4 text-center">No thread data</div>';
124
- return;
125
- }
126
-
127
- container.innerHTML = threads.map(t => {
128
- const count = t.count || t.messages || 1;
129
- return `<div class="flex items-center gap-3 py-2 px-3 rounded-lg hover:bg-slate-800/20 transition-colors">
130
- <svg class="w-4 h-4 text-slate-500 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/></svg>
131
- <div class="flex-1 min-w-0">
132
- <div class="text-xs text-slate-300 truncate">${escapeHtml(t.subject || t.thread_id || '--')}</div>
133
- <div class="text-[10px] text-slate-500">${count} message${count !== 1 ? 's' : ''}</div>
134
- </div>
135
- <span class="text-[10px] text-slate-600">${relativeTime(t.last_at || t.updated_at)}</span>
136
- </div>`;
137
- }).join('');
138
- }
139
-
140
- async function loadEmail() {
141
- const data = await fetchJSON('/api/email');
142
- if (!data) return;
143
-
144
- const stats = data.stats || {};
145
- document.getElementById('email-total').textContent = formatNumber(stats.total || 0);
146
- document.getElementById('email-processed').textContent = formatNumber(stats.processed || 0);
147
- document.getElementById('email-pending').textContent = formatNumber(stats.pending || 0);
148
-
149
- const rate = stats.total ? Math.round((stats.processed / stats.total) * 100) : 0;
150
- document.getElementById('email-rate').textContent = rate + '%';
151
-
152
- renderFunnel(stats);
153
- renderTable(data.recent || []);
154
- renderThreads(data.threads || []);
155
- }
156
-
157
- loadEmail();
158
- setInterval(loadEmail, 60000);
159
- </script>
160
- {% endblock %}
@@ -1,189 +0,0 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Evolution Cockpit{% endblock %}
4
- {% block page_title %}Evolution Cockpit{% endblock %}
5
-
6
- {% block content %}
7
- <div class="space-y-5">
8
- <!-- Top stats -->
9
- <div class="grid grid-cols-5 gap-4" id="dim-cards">
10
- <!-- Populated by JS -->
11
- </div>
12
-
13
- <!-- Main row: Radar + History -->
14
- <div class="grid grid-cols-2 gap-5">
15
- <!-- Radar Chart -->
16
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 card">
17
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-4">Dimension Radar</div>
18
- <div class="flex items-center justify-center" style="min-height: 320px;">
19
- <svg id="radar-svg" viewBox="0 0 400 400" class="w-full max-w-sm"></svg>
20
- </div>
21
- </div>
22
-
23
- <!-- Score History -->
24
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 card">
25
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-4">Score History</div>
26
- <div class="space-y-3" id="score-history">
27
- <div class="text-xs text-slate-600 py-8 text-center">loading...</div>
28
- </div>
29
- </div>
30
- </div>
31
-
32
- <!-- Evolution Log Timeline -->
33
- <div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-5 card">
34
- <div class="text-xs uppercase tracking-wider text-slate-400 font-medium mb-4">Evolution Log</div>
35
- <div class="space-y-3" id="evo-log">
36
- <div class="text-xs text-slate-600 py-4 text-center">loading...</div>
37
- </div>
38
- </div>
39
- </div>
40
- {% endblock %}
41
-
42
- {% block scripts %}
43
- <script>
44
- const DIMS = ['autonomy', 'reasoning', 'memory', 'trust', 'creativity'];
45
- const DIM_COLORS = {
46
- autonomy: '#7C3AED', reasoning: '#3B82F6', memory: '#EC4899',
47
- trust: '#10B981', creativity: '#F59E0B'
48
- };
49
-
50
- function drawRadar(dimensions) {
51
- const svg = document.getElementById('radar-svg');
52
- const cx = 200, cy = 200, maxR = 150;
53
- const n = DIMS.length;
54
- const angleStep = (2 * Math.PI) / n;
55
-
56
- let html = '';
57
- // Grid rings
58
- for (let ring = 1; ring <= 5; ring++) {
59
- const r = (ring / 5) * maxR;
60
- let points = '';
61
- for (let i = 0; i < n; i++) {
62
- const a = -Math.PI / 2 + i * angleStep;
63
- points += `${cx + r * Math.cos(a)},${cy + r * Math.sin(a)} `;
64
- }
65
- html += `<polygon points="${points}" fill="none" stroke="rgba(51,65,85,0.4)" stroke-width="1"/>`;
66
- if (ring === 5) {
67
- html += `<text x="${cx + 4}" y="${cy - r - 4}" class="text-[10px]" fill="#64748b">100</text>`;
68
- }
69
- }
70
-
71
- // Axes
72
- for (let i = 0; i < n; i++) {
73
- const a = -Math.PI / 2 + i * angleStep;
74
- const ex = cx + maxR * Math.cos(a);
75
- const ey = cy + maxR * Math.sin(a);
76
- html += `<line x1="${cx}" y1="${cy}" x2="${ex}" y2="${ey}" stroke="rgba(51,65,85,0.3)" stroke-width="1"/>`;
77
- const lx = cx + (maxR + 20) * Math.cos(a);
78
- const ly = cy + (maxR + 20) * Math.sin(a);
79
- html += `<text x="${lx}" y="${ly}" text-anchor="middle" dominant-baseline="middle" fill="${DIM_COLORS[DIMS[i]]}" class="text-xs font-display font-semibold" style="font-size:11px">${DIMS[i]}</text>`;
80
- }
81
-
82
- // Data polygon
83
- if (dimensions) {
84
- let points = '';
85
- for (let i = 0; i < n; i++) {
86
- const score = dimensions[DIMS[i]]?.score ?? 0;
87
- const r = (score / 100) * maxR;
88
- const a = -Math.PI / 2 + i * angleStep;
89
- points += `${cx + r * Math.cos(a)},${cy + r * Math.sin(a)} `;
90
- }
91
- html += `<polygon points="${points}" fill="rgba(124,58,237,0.15)" stroke="#7C3AED" stroke-width="2"/>`;
92
-
93
- // Data points
94
- for (let i = 0; i < n; i++) {
95
- const score = dimensions[DIMS[i]]?.score ?? 0;
96
- const r = (score / 100) * maxR;
97
- const a = -Math.PI / 2 + i * angleStep;
98
- const px = cx + r * Math.cos(a);
99
- const py = cy + r * Math.sin(a);
100
- html += `<circle cx="${px}" cy="${py}" r="4" fill="${DIM_COLORS[DIMS[i]]}" stroke="#0f172a" stroke-width="2"/>`;
101
- }
102
- }
103
-
104
- svg.innerHTML = html;
105
- }
106
-
107
- function renderDimCards(dimensions) {
108
- const container = document.getElementById('dim-cards');
109
- if (!dimensions) { container.innerHTML = '<div class="col-span-5 text-xs text-slate-600 text-center py-4">No dimension data</div>'; return; }
110
-
111
- container.innerHTML = DIMS.map(dim => {
112
- const d = dimensions[dim] || {};
113
- const score = d.score ?? 0;
114
- const delta = d.delta ?? 0;
115
- const deltaSign = delta > 0 ? '+' : '';
116
- const deltaColor = delta > 0 ? 'text-emerald-400' : delta < 0 ? 'text-red-400' : 'text-slate-500';
117
- const color = DIM_COLORS[dim];
118
- return `<div class="bg-slate-900/50 border border-slate-800/50 rounded-xl p-4 card">
119
- <div class="flex items-center gap-2 mb-2">
120
- <span class="w-2 h-2 rounded-full" style="background:${color}"></span>
121
- <span class="text-xs uppercase tracking-wider text-slate-400 font-medium">${dim}</span>
122
- </div>
123
- <div class="flex items-end gap-2">
124
- <span class="text-xl font-mono font-semibold text-slate-200">${score.toFixed(1)}</span>
125
- <span class="text-xs font-mono ${deltaColor} mb-0.5">${deltaSign}${delta.toFixed(1)}</span>
126
- </div>
127
- <div class="mt-2 h-1 bg-slate-800 rounded-full overflow-hidden">
128
- <div class="h-full rounded-full transition-all duration-700" style="width:${Math.min(100, score)}%;background:${color}"></div>
129
- </div>
130
- <div class="mt-1 text-[10px] text-slate-600">${d.measured_at ? relativeTime(d.measured_at) : '--'}</div>
131
- </div>`;
132
- }).join('');
133
- }
134
-
135
- function renderHistory(metrics) {
136
- const container = document.getElementById('score-history');
137
- if (!metrics || !metrics.length) { container.innerHTML = '<div class="text-xs text-slate-600 py-8 text-center">No history data</div>'; return; }
138
-
139
- const maxEntries = 20;
140
- const items = metrics.slice(0, maxEntries);
141
- container.innerHTML = items.map(m => {
142
- const dim = m.dimension || m.name || '--';
143
- const score = m.score ?? m.value ?? 0;
144
- const color = DIM_COLORS[dim] || '#64748b';
145
- return `<div class="flex items-center gap-3">
146
- <span class="w-16 text-[10px] text-slate-500 font-mono">${relativeTime(m.measured_at || m.created_at)}</span>
147
- <span class="w-2 h-2 rounded-full flex-shrink-0" style="background:${color}"></span>
148
- <span class="text-xs text-slate-400 flex-1">${escapeHtml(dim)}</span>
149
- <span class="text-xs font-mono text-slate-300">${score.toFixed(1)}</span>
150
- </div>`;
151
- }).join('');
152
- }
153
-
154
- function renderLog(logs) {
155
- const container = document.getElementById('evo-log');
156
- if (!logs || !logs.length) { container.innerHTML = '<div class="text-xs text-slate-600 py-4 text-center">No evolution logs</div>'; return; }
157
-
158
- container.innerHTML = logs.map(log => {
159
- const status = log.status || 'proposed';
160
- const statusColors = { approved: 'bg-emerald-500/10 text-emerald-400', rejected: 'bg-red-500/10 text-red-400', proposed: 'bg-amber-500/10 text-amber-400' };
161
- const sc = statusColors[status] || statusColors.proposed;
162
- return `<div class="flex items-start gap-3 py-2 border-b border-slate-800/30 last:border-0">
163
- <div class="w-1 h-1 rounded-full bg-slate-600 mt-1.5 flex-shrink-0"></div>
164
- <div class="flex-1 min-w-0">
165
- <div class="flex items-center gap-2 flex-wrap">
166
- <span class="text-xs text-slate-300">${escapeHtml(log.proposal || log.description || log.text || '--')}</span>
167
- <span class="px-1.5 py-0.5 rounded text-[10px] font-medium ${sc}">${escapeHtml(status)}</span>
168
- </div>
169
- <div class="text-[10px] text-slate-600 mt-0.5">${escapeHtml(log.dimension || '')} ${log.created_at ? '-- ' + relativeTime(log.created_at) : ''}</div>
170
- </div>
171
- </div>`;
172
- }).join('');
173
- }
174
-
175
- async function loadEvolution() {
176
- const data = await fetchJSON('/api/evolution');
177
- if (!data) return;
178
-
179
- const dimensions = data.dimensions || {};
180
- drawRadar(dimensions);
181
- renderDimCards(dimensions);
182
- renderHistory(data.metrics || []);
183
- renderLog(data.logs || []);
184
- }
185
-
186
- loadEvolution();
187
- setInterval(loadEvolution, 60000);
188
- </script>
189
- {% endblock %}