@newsails/veil-cli 1.0.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.
Files changed (199) hide show
  1. package/.veil/agents/analyst/AGENT.md +21 -0
  2. package/.veil/agents/analyst/agent.json +23 -0
  3. package/.veil/agents/assistant/AGENT.md +15 -0
  4. package/.veil/agents/assistant/agent.json +19 -0
  5. package/.veil/agents/coder/AGENT.md +18 -0
  6. package/.veil/agents/coder/agent.json +19 -0
  7. package/.veil/agents/hello/AGENT.md +5 -0
  8. package/.veil/agents/hello/agent.json +13 -0
  9. package/.veil/agents/writer/AGENT.md +12 -0
  10. package/.veil/agents/writer/agent.json +17 -0
  11. package/.veil/memory/MEMORY.md +343 -0
  12. package/.veil/memory/agents/analyst/MEMORY.md +55 -0
  13. package/.veil/memory/agents/hello/MEMORY.md +12 -0
  14. package/.veil/runtime.pid +1 -0
  15. package/.veil/settings.json +10 -0
  16. package/.veil-studio/studio.db +0 -0
  17. package/.veil-studio/studio.db-shm +0 -0
  18. package/.veil-studio/studio.db-wal +0 -0
  19. package/PLAN/01-vision.md +26 -0
  20. package/PLAN/02-tech-stack.md +94 -0
  21. package/PLAN/03-agents.md +232 -0
  22. package/PLAN/04-runtime.md +171 -0
  23. package/PLAN/05-tools.md +211 -0
  24. package/PLAN/06-communication.md +243 -0
  25. package/PLAN/07-storage.md +218 -0
  26. package/PLAN/08-api-cli.md +153 -0
  27. package/PLAN/09-permissions.md +108 -0
  28. package/PLAN/10-ably.md +105 -0
  29. package/PLAN/11-file-formats.md +442 -0
  30. package/PLAN/12-folder-structure.md +205 -0
  31. package/PLAN/13-operations.md +212 -0
  32. package/PLAN/README.md +23 -0
  33. package/README.md +128 -0
  34. package/REPORT.md +174 -0
  35. package/TODO.md +45 -0
  36. package/ai-tests/FRONTEND_PROMPT.md +220 -0
  37. package/ai-tests/Research & Planning.md +814 -0
  38. package/ai-tests/prompt-001-basic-api.md +230 -0
  39. package/ai-tests/prompt-002-basic-flows.md +230 -0
  40. package/ai-tests/prompt-003-agent-behaviors.md +220 -0
  41. package/api/middleware.js +60 -0
  42. package/api/routes/agents.js +193 -0
  43. package/api/routes/chat.js +93 -0
  44. package/api/routes/completions.js +122 -0
  45. package/api/routes/daemons.js +80 -0
  46. package/api/routes/memory.js +169 -0
  47. package/api/routes/models.js +40 -0
  48. package/api/routes/remote-methods.js +74 -0
  49. package/api/routes/sessions.js +208 -0
  50. package/api/routes/settings.js +108 -0
  51. package/api/routes/system.js +50 -0
  52. package/api/routes/tasks.js +270 -0
  53. package/api/server.js +120 -0
  54. package/cli/formatter.js +70 -0
  55. package/cli/index.js +443 -0
  56. package/cli/parser.js +113 -0
  57. package/config/config.json +10 -0
  58. package/config/models.json +6826 -0
  59. package/core/agent.js +329 -0
  60. package/core/cancel.js +38 -0
  61. package/core/compaction.js +176 -0
  62. package/core/events.js +13 -0
  63. package/core/loop.js +564 -0
  64. package/core/memory.js +51 -0
  65. package/core/prompt.js +185 -0
  66. package/core/queue.js +96 -0
  67. package/core/registry.js +291 -0
  68. package/core/remote-methods.js +124 -0
  69. package/core/router.js +386 -0
  70. package/core/running-sessions.js +18 -0
  71. package/docs/api/01-system.md +84 -0
  72. package/docs/api/02-agents.md +374 -0
  73. package/docs/api/03-chat.md +269 -0
  74. package/docs/api/04-tasks.md +470 -0
  75. package/docs/api/05-sessions.md +444 -0
  76. package/docs/api/06-daemons.md +142 -0
  77. package/docs/api/07-memory.md +186 -0
  78. package/docs/api/08-settings.md +133 -0
  79. package/docs/api/09-models.md +119 -0
  80. package/docs/api/09-websocket.md +350 -0
  81. package/docs/api/10-completions.md +134 -0
  82. package/docs/api/README.md +116 -0
  83. package/docs/guide/01-quickstart.md +220 -0
  84. package/docs/guide/02-folder-structure.md +185 -0
  85. package/docs/guide/03-configuration.md +252 -0
  86. package/docs/guide/04-agents.md +267 -0
  87. package/docs/guide/05-cli.md +290 -0
  88. package/docs/guide/06-tools.md +643 -0
  89. package/docs/guide/07-permissions.md +236 -0
  90. package/docs/guide/08-memory.md +139 -0
  91. package/docs/guide/09-multi-agent.md +271 -0
  92. package/docs/guide/10-daemons.md +226 -0
  93. package/docs/guide/README.md +53 -0
  94. package/docs/index.html +623 -0
  95. package/examples/README.md +151 -0
  96. package/examples/agents/assistant/AGENT.md +31 -0
  97. package/examples/agents/assistant/SOUL.md +9 -0
  98. package/examples/agents/assistant/agent.json +74 -0
  99. package/examples/agents/hello/AGENT.md +15 -0
  100. package/examples/agents/hello/agent.json +14 -0
  101. package/examples/agents/monitor/AGENT.md +51 -0
  102. package/examples/agents/monitor/agent.json +33 -0
  103. package/examples/agents/monitor/heartbeats/monitor.md +24 -0
  104. package/examples/agents/orchestrator/AGENT.md +70 -0
  105. package/examples/agents/orchestrator/agent.json +30 -0
  106. package/examples/agents/researcher/AGENT.md +52 -0
  107. package/examples/agents/researcher/agent.json +49 -0
  108. package/examples/agents/researcher/skills/web-research.md +28 -0
  109. package/examples/skills/code-review.md +72 -0
  110. package/examples/skills/summarise.md +59 -0
  111. package/examples/skills/web-research.md +42 -0
  112. package/examples/tools/word-count/index.js +27 -0
  113. package/examples/tools/word-count/tool.json +18 -0
  114. package/infrastructure/database.js +563 -0
  115. package/infrastructure/scheduler.js +122 -0
  116. package/llm/client.js +206 -0
  117. package/migrations/001-initial.sql +121 -0
  118. package/migrations/002-debuggability.sql +13 -0
  119. package/migrations/003-drop-orphaned-columns.sql +72 -0
  120. package/migrations/004-session-message-token-fields.sql +78 -0
  121. package/migrations/005-session-thinking.sql +5 -0
  122. package/package.json +30 -0
  123. package/schemas/agent.json +143 -0
  124. package/schemas/settings.json +111 -0
  125. package/scripts/fetch-models.js +93 -0
  126. package/session-debug-scenario.md +248 -0
  127. package/settings/fields.js +52 -0
  128. package/system-prompts/base-core.md +7 -0
  129. package/system-prompts/environment.md +13 -0
  130. package/system-prompts/reminders/anti-drift.md +6 -0
  131. package/system-prompts/reminders/stall-recovery.md +10 -0
  132. package/system-prompts/safety-rules.md +25 -0
  133. package/system-prompts/task-heuristics.md +27 -0
  134. package/test/client.js +71 -0
  135. package/test/integration/01-health.test.js +25 -0
  136. package/test/integration/02-agents.test.js +80 -0
  137. package/test/integration/03-chat-hello.test.js +48 -0
  138. package/test/integration/04-chat-multiturn.test.js +61 -0
  139. package/test/integration/05-chat-writer.test.js +48 -0
  140. package/test/integration/06-task-basic.test.js +68 -0
  141. package/test/integration/07-task-tools.test.js +74 -0
  142. package/test/integration/08-task-code-analysis.test.js +69 -0
  143. package/test/integration/09-memory-analyst.test.js +63 -0
  144. package/test/integration/10-task-advanced.test.js +85 -0
  145. package/test/integration/11-sessions-advanced.test.js +84 -0
  146. package/test/integration/12-assistant-chat-tools.test.js +75 -0
  147. package/test/integration/13-edge-cases.test.js +99 -0
  148. package/test/integration/14-cancel.test.js +62 -0
  149. package/test/integration/15-debug.test.js +106 -0
  150. package/test/integration/16-memory-api.test.js +83 -0
  151. package/test/integration/17-settings-api.test.js +41 -0
  152. package/test/integration/18-tool-search-activation.test.js +119 -0
  153. package/test/results/.gitkeep +0 -0
  154. package/test/runner.js +206 -0
  155. package/test/smoke.js +216 -0
  156. package/tools/agent_message.js +85 -0
  157. package/tools/agent_send.js +80 -0
  158. package/tools/agent_spawn.js +44 -0
  159. package/tools/bash.js +49 -0
  160. package/tools/edit_file.js +41 -0
  161. package/tools/glob.js +64 -0
  162. package/tools/grep.js +82 -0
  163. package/tools/list_dir.js +63 -0
  164. package/tools/log_write.js +31 -0
  165. package/tools/memory_read.js +38 -0
  166. package/tools/memory_search.js +65 -0
  167. package/tools/memory_write.js +42 -0
  168. package/tools/read_file.js +48 -0
  169. package/tools/sleep.js +22 -0
  170. package/tools/task_create.js +41 -0
  171. package/tools/task_respond.js +37 -0
  172. package/tools/task_spawn.js +64 -0
  173. package/tools/task_status.js +39 -0
  174. package/tools/task_subscribe.js +37 -0
  175. package/tools/todo_read.js +26 -0
  176. package/tools/todo_write.js +38 -0
  177. package/tools/tool_activate.js +24 -0
  178. package/tools/tool_search.js +24 -0
  179. package/tools/web_fetch.js +50 -0
  180. package/tools/web_search.js +52 -0
  181. package/tools/write_file.js +28 -0
  182. package/ui/api.js +190 -0
  183. package/ui/app.js +281 -0
  184. package/ui/index.html +382 -0
  185. package/ui/views/agents.js +377 -0
  186. package/ui/views/chat.js +610 -0
  187. package/ui/views/connection.js +96 -0
  188. package/ui/views/daemons.js +129 -0
  189. package/ui/views/feed.js +194 -0
  190. package/ui/views/memory.js +263 -0
  191. package/ui/views/models.js +146 -0
  192. package/ui/views/sessions.js +314 -0
  193. package/ui/views/settings.js +142 -0
  194. package/ui/views/tasks.js +415 -0
  195. package/utils/context.js +49 -0
  196. package/utils/id.js +16 -0
  197. package/utils/models.js +88 -0
  198. package/utils/paths.js +213 -0
  199. package/utils/settings.js +172 -0
@@ -0,0 +1,623 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Veil CLI Documentation</title>
7
+
8
+ <!-- Tailwind CSS -->
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+
11
+ <!-- Marked.js for Markdown parsing -->
12
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/marked-highlight/lib/index.umd.js"></script>
14
+
15
+ <!-- Highlight.js for syntax highlighting -->
16
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github-dark.min.css">
17
+ <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
18
+ <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/json.min.js"></script>
19
+ <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script>
20
+ <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/javascript.min.js"></script>
21
+
22
+ <!-- Fuse.js for fuzzy search -->
23
+ <script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0"></script>
24
+
25
+ <!-- Lucide Icons -->
26
+ <script src="https://unpkg.com/lucide@latest"></script>
27
+
28
+ <script>
29
+ tailwind.config = {
30
+ darkMode: 'class',
31
+ theme: {
32
+ extend: {
33
+ colors: {
34
+ primary: {
35
+ 50: '#f0f9ff',
36
+ 100: '#e0f2fe',
37
+ 200: '#bae6fd',
38
+ 300: '#7dd3fc',
39
+ 400: '#38bdf8',
40
+ 500: '#0ea5e9',
41
+ 600: '#0284c7',
42
+ 700: '#0369a1',
43
+ 800: '#075985',
44
+ 900: '#0c4a6e',
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ </script>
51
+
52
+ <style>
53
+ /* Custom scrollbar */
54
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
55
+ ::-webkit-scrollbar-track { background: transparent; }
56
+ ::-webkit-scrollbar-thumb { background: #475569; border-radius: 3px; }
57
+ ::-webkit-scrollbar-thumb:hover { background: #64748b; }
58
+
59
+ /* Markdown content styles */
60
+ .markdown-body {
61
+ line-height: 1.7;
62
+ }
63
+ .markdown-body h1 { font-size: 2rem; font-weight: 700; margin: 1.5rem 0 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid #334155; }
64
+ .markdown-body h2 { font-size: 1.5rem; font-weight: 600; margin: 1.5rem 0 0.75rem; color: #38bdf8; }
65
+ .markdown-body h3 { font-size: 1.25rem; font-weight: 600; margin: 1.25rem 0 0.5rem; color: #94a3b8; }
66
+ .markdown-body h4 { font-size: 1.1rem; font-weight: 600; margin: 1rem 0 0.5rem; }
67
+ .markdown-body p { margin: 0.75rem 0; }
68
+ .markdown-body ul, .markdown-body ol { margin: 0.75rem 0; padding-left: 1.5rem; }
69
+ .markdown-body li { margin: 0.25rem 0; }
70
+ .markdown-body ul { list-style-type: disc; }
71
+ .markdown-body ol { list-style-type: decimal; }
72
+ .markdown-body code:not(pre code) {
73
+ background: #1e293b;
74
+ padding: 0.2rem 0.4rem;
75
+ border-radius: 4px;
76
+ font-size: 0.875rem;
77
+ color: #f472b6;
78
+ }
79
+ .markdown-body pre {
80
+ background: #0f172a;
81
+ padding: 1rem;
82
+ border-radius: 8px;
83
+ overflow-x: auto;
84
+ margin: 1rem 0;
85
+ border: 1px solid #1e293b;
86
+ }
87
+ .markdown-body pre code {
88
+ background: transparent;
89
+ padding: 0;
90
+ color: #e2e8f0;
91
+ font-size: 0.875rem;
92
+ }
93
+ .markdown-body table {
94
+ width: 100%;
95
+ border-collapse: collapse;
96
+ margin: 1rem 0;
97
+ font-size: 0.9rem;
98
+ }
99
+ .markdown-body th, .markdown-body td {
100
+ border: 1px solid #334155;
101
+ padding: 0.5rem 0.75rem;
102
+ text-align: left;
103
+ }
104
+ .markdown-body th {
105
+ background: #1e293b;
106
+ font-weight: 600;
107
+ color: #38bdf8;
108
+ }
109
+ .markdown-body tr:hover { background: #1e293b40; }
110
+ .markdown-body blockquote {
111
+ border-left: 4px solid #0ea5e9;
112
+ padding-left: 1rem;
113
+ margin: 1rem 0;
114
+ color: #94a3b8;
115
+ background: #1e293b40;
116
+ padding: 0.5rem 1rem;
117
+ border-radius: 0 8px 8px 0;
118
+ }
119
+ .markdown-body a { color: #38bdf8; text-decoration: none; }
120
+ .markdown-body a:hover { text-decoration: underline; }
121
+ .markdown-body hr { border: none; border-top: 1px solid #334155; margin: 2rem 0; }
122
+
123
+ /* Active nav item */
124
+ .nav-item.active { background: linear-gradient(90deg, #0ea5e920 0%, transparent 100%); border-left-color: #0ea5e9; }
125
+
126
+ /* Search highlight */
127
+ .search-highlight { background: #fbbf2440; color: #fbbf24; padding: 0 2px; border-radius: 2px; }
128
+
129
+ /* Smooth transitions */
130
+ .nav-item { transition: all 0.15s ease; }
131
+
132
+ /* Loading spinner */
133
+ @keyframes spin { to { transform: rotate(360deg); } }
134
+ .spinner { animation: spin 1s linear infinite; }
135
+ </style>
136
+ </head>
137
+ <body class="bg-slate-950 text-slate-200 min-h-screen">
138
+ <div class="flex h-screen overflow-hidden">
139
+
140
+ <!-- Sidebar -->
141
+ <aside id="sidebar" class="w-72 bg-slate-900 border-r border-slate-800 flex flex-col flex-shrink-0">
142
+ <!-- Header -->
143
+ <div class="p-4 border-b border-slate-800">
144
+ <div class="flex items-center gap-3">
145
+ <div class="w-10 h-10 bg-gradient-to-br from-primary-500 to-primary-700 rounded-lg flex items-center justify-center">
146
+ <i data-lucide="bot" class="w-6 h-6 text-white"></i>
147
+ </div>
148
+ <div>
149
+ <h1 class="font-bold text-lg text-white">Veil CLI</h1>
150
+ <p class="text-xs text-slate-500">Documentation</p>
151
+ </div>
152
+ </div>
153
+ </div>
154
+
155
+ <!-- Search -->
156
+ <div class="p-3 border-b border-slate-800">
157
+ <div class="relative">
158
+ <i data-lucide="search" class="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-slate-500"></i>
159
+ <input
160
+ type="text"
161
+ id="searchInput"
162
+ placeholder="Search docs... (Ctrl+K)"
163
+ class="w-full bg-slate-800 border border-slate-700 rounded-lg py-2 pl-10 pr-4 text-sm focus:outline-none focus:border-primary-500 focus:ring-1 focus:ring-primary-500 placeholder-slate-500"
164
+ >
165
+ <kbd class="absolute right-3 top-1/2 -translate-y-1/2 text-xs text-slate-500 bg-slate-700 px-1.5 py-0.5 rounded hidden sm:inline">⌘K</kbd>
166
+ </div>
167
+ </div>
168
+
169
+ <!-- Search Results -->
170
+ <div id="searchResults" class="hidden border-b border-slate-800 max-h-64 overflow-y-auto">
171
+ <div class="p-2 text-xs text-slate-500 font-medium px-4">Search Results</div>
172
+ <div id="searchResultsList" class="pb-2"></div>
173
+ </div>
174
+
175
+ <!-- Navigation -->
176
+ <nav id="navigation" class="flex-1 overflow-y-auto p-3">
177
+ <ul id="navList" class="space-y-1">
178
+ <!-- Populated dynamically -->
179
+ </ul>
180
+ </nav>
181
+
182
+ <!-- Footer -->
183
+ <div class="p-4 border-t border-slate-800">
184
+ <div class="flex items-center justify-between text-xs text-slate-500">
185
+ <span>v1.0.0</span>
186
+ <a href="https://github.com" target="_blank" class="flex items-center gap-1 hover:text-slate-300">
187
+ <i data-lucide="github" class="w-4 h-4"></i>
188
+ GitHub
189
+ </a>
190
+ </div>
191
+ </div>
192
+ </aside>
193
+
194
+ <!-- Main Content -->
195
+ <main class="flex-1 flex flex-col overflow-hidden">
196
+ <!-- Top Bar -->
197
+ <header class="bg-slate-900/50 backdrop-blur border-b border-slate-800 px-6 py-3 flex items-center justify-between flex-shrink-0">
198
+ <div class="flex items-center gap-4">
199
+ <button id="sidebarToggle" class="lg:hidden p-2 hover:bg-slate-800 rounded-lg">
200
+ <i data-lucide="menu" class="w-5 h-5"></i>
201
+ </button>
202
+ <nav id="breadcrumb" class="flex items-center gap-2 text-sm">
203
+ <span class="text-slate-500">Docs</span>
204
+ <i data-lucide="chevron-right" class="w-4 h-4 text-slate-600"></i>
205
+ <span id="currentSection" class="text-slate-500">Guide</span>
206
+ <i data-lucide="chevron-right" class="w-4 h-4 text-slate-600"></i>
207
+ <span id="currentDoc" class="text-slate-300">README</span>
208
+ </nav>
209
+ </div>
210
+ <div class="flex items-center gap-2">
211
+ <button id="prevDoc" class="p-2 hover:bg-slate-800 rounded-lg disabled:opacity-30 disabled:cursor-not-allowed" title="Previous">
212
+ <i data-lucide="chevron-left" class="w-5 h-5"></i>
213
+ </button>
214
+ <button id="nextDoc" class="p-2 hover:bg-slate-800 rounded-lg disabled:opacity-30 disabled:cursor-not-allowed" title="Next">
215
+ <i data-lucide="chevron-right" class="w-5 h-5"></i>
216
+ </button>
217
+ <span class="w-px h-6 bg-slate-700 mx-2"></span>
218
+ <button id="scrollTop" class="p-2 hover:bg-slate-800 rounded-lg" title="Scroll to top">
219
+ <i data-lucide="arrow-up" class="w-5 h-5"></i>
220
+ </button>
221
+ </div>
222
+ </header>
223
+
224
+ <!-- Content Area -->
225
+ <div id="contentWrapper" class="flex-1 overflow-y-auto">
226
+ <!-- Loading State -->
227
+ <div id="loading" class="flex items-center justify-center h-full">
228
+ <div class="text-center">
229
+ <i data-lucide="loader-2" class="w-8 h-8 text-primary-500 spinner mx-auto mb-4"></i>
230
+ <p class="text-slate-500">Loading documentation...</p>
231
+ </div>
232
+ </div>
233
+
234
+ <!-- Document Content -->
235
+ <article id="content" class="hidden max-w-4xl mx-auto px-6 py-8 markdown-body"></article>
236
+
237
+ <!-- Table of Contents (sticky on large screens) -->
238
+ <aside id="toc" class="hidden xl:block fixed right-8 top-24 w-56">
239
+ <div class="bg-slate-900/80 backdrop-blur rounded-lg border border-slate-800 p-4">
240
+ <h4 class="text-xs font-semibold text-slate-500 uppercase tracking-wider mb-3">On this page</h4>
241
+ <ul id="tocList" class="space-y-2 text-sm max-h-[calc(100vh-12rem)] overflow-y-auto"></ul>
242
+ </div>
243
+ </aside>
244
+ </div>
245
+ </main>
246
+ </div>
247
+
248
+ <script>
249
+ // State
250
+ let docs = [];
251
+ let currentDocIndex = 0;
252
+ let fuse = null;
253
+ let searchIndex = [];
254
+
255
+ // Documentation sections
256
+ const DOC_SECTIONS = [
257
+ {
258
+ label: 'Guide',
259
+ folder: 'guide/',
260
+ files: [
261
+ 'README.md',
262
+ '01-quickstart.md',
263
+ '02-folder-structure.md',
264
+ '03-configuration.md',
265
+ '04-agents.md',
266
+ '05-cli.md',
267
+ '06-tools.md',
268
+ '07-permissions.md',
269
+ '08-memory.md',
270
+ '09-multi-agent.md',
271
+ '10-daemons.md',
272
+ ]
273
+ },
274
+ {
275
+ label: 'API Reference',
276
+ folder: 'api/',
277
+ files: [
278
+ 'README.md',
279
+ '01-system.md',
280
+ '02-agents.md',
281
+ '03-chat.md',
282
+ '04-tasks.md',
283
+ '05-sessions.md',
284
+ '06-daemons.md',
285
+ '07-memory.md',
286
+ '08-settings.md',
287
+ '09-models.md',
288
+ '09-websocket.md',
289
+ '10-completions.md',
290
+ ]
291
+ }
292
+ ];
293
+
294
+ // DOM elements
295
+ const navList = document.getElementById('navList');
296
+ const content = document.getElementById('content');
297
+ const loading = document.getElementById('loading');
298
+ const searchInput = document.getElementById('searchInput');
299
+ const searchResults = document.getElementById('searchResults');
300
+ const searchResultsList = document.getElementById('searchResultsList');
301
+ const currentDocEl = document.getElementById('currentDoc');
302
+ const tocList = document.getElementById('tocList');
303
+ const prevBtn = document.getElementById('prevDoc');
304
+ const nextBtn = document.getElementById('nextDoc');
305
+
306
+ // Initialize
307
+ async function init() {
308
+ lucide.createIcons();
309
+ await loadAllDocs();
310
+ setupSearch();
311
+ setupKeyboardShortcuts();
312
+ setupNavigation();
313
+
314
+ // Load first doc or from hash
315
+ const hash = window.location.hash.slice(1);
316
+ const docIndex = docs.findIndex(d => d.slug === hash);
317
+ loadDoc(docIndex >= 0 ? docIndex : 0);
318
+ }
319
+
320
+ // Load all markdown files
321
+ async function loadAllDocs() {
322
+ const allDocs = [];
323
+ for (const section of DOC_SECTIONS) {
324
+ const promises = section.files.map(async (file) => {
325
+ try {
326
+ const response = await fetch(section.folder + file);
327
+ if (!response.ok) return null;
328
+ const text = await response.text();
329
+ const title = extractTitle(text, file);
330
+ const prefix = section.folder.replace('/', '');
331
+ const slug = prefix + '/' + file.replace('.md', '').toLowerCase();
332
+ return { file, section: section.label, folder: section.folder, title, slug, content: text };
333
+ } catch (e) {
334
+ console.warn(`Failed to load ${section.folder + file}:`, e);
335
+ return null;
336
+ }
337
+ });
338
+ const sectionDocs = (await Promise.all(promises)).filter(Boolean);
339
+ allDocs.push(...sectionDocs);
340
+ }
341
+ docs = allDocs;
342
+ renderNavigation();
343
+ }
344
+
345
+ // Extract title from markdown content
346
+ function extractTitle(content, filename) {
347
+ const match = content.match(/^#\s+(.+)$/m);
348
+ if (match) return match[1];
349
+ // Fallback: format filename
350
+ return filename.replace('.md', '').replace(/^\d+-/, '').replace(/-/g, ' ')
351
+ .replace(/\b\w/g, c => c.toUpperCase());
352
+ }
353
+
354
+ // Render sidebar navigation
355
+ function renderNavigation() {
356
+ // Group docs by section in order
357
+ const sections = {};
358
+ const sectionOrder = [];
359
+ docs.forEach((doc, index) => {
360
+ if (!sections[doc.section]) {
361
+ sections[doc.section] = [];
362
+ sectionOrder.push(doc.section);
363
+ }
364
+ sections[doc.section].push({ doc, index });
365
+ });
366
+
367
+ navList.innerHTML = sectionOrder.map(sectionName => {
368
+ const items = sections[sectionName];
369
+ return `
370
+ <li class="mt-4 first:mt-0">
371
+ <div class="text-xs font-semibold text-slate-500 uppercase tracking-wider mb-1 px-3">${sectionName}</div>
372
+ <ul class="space-y-1">
373
+ ${items.map(({ doc, index }) => {
374
+ const icon = getDocIcon(doc.slug);
375
+ return `
376
+ <li>
377
+ <button
378
+ onclick="loadDoc(${index})"
379
+ class="nav-item w-full flex items-center gap-3 px-3 py-2 text-sm text-slate-400 hover:text-slate-200 hover:bg-slate-800/50 rounded-lg border-l-2 border-transparent"
380
+ data-index="${index}"
381
+ >
382
+ <i data-lucide="${icon}" class="w-4 h-4 flex-shrink-0"></i>
383
+ <span class="truncate">${doc.title}</span>
384
+ </button>
385
+ </li>
386
+ `;
387
+ }).join('')}
388
+ </ul>
389
+ </li>
390
+ `;
391
+ }).join('');
392
+ lucide.createIcons();
393
+ }
394
+
395
+ // Get icon for doc type
396
+ function getDocIcon(slug) {
397
+ const icons = {
398
+ // Guide
399
+ 'guide/readme': 'book-open',
400
+ 'guide/01-quickstart': 'zap',
401
+ 'guide/02-folder-structure': 'folder-tree',
402
+ 'guide/03-configuration': 'sliders',
403
+ 'guide/04-agents': 'bot',
404
+ 'guide/05-cli': 'terminal',
405
+ 'guide/06-tools': 'wrench',
406
+ 'guide/07-permissions': 'shield',
407
+ 'guide/08-memory': 'brain',
408
+ 'guide/09-multi-agent': 'network',
409
+ 'guide/10-daemons': 'clock',
410
+ // API Reference
411
+ 'api/readme': 'book-open',
412
+ 'api/01-system': 'server',
413
+ 'api/02-agents': 'bot',
414
+ 'api/03-chat': 'message-circle',
415
+ 'api/04-tasks': 'list-checks',
416
+ 'api/05-sessions': 'users',
417
+ 'api/06-daemons': 'activity',
418
+ 'api/07-memory': 'database',
419
+ 'api/08-settings': 'settings',
420
+ 'api/09-models': 'cpu',
421
+ 'api/09-websocket': 'plug',
422
+ 'api/10-completions': 'sparkles',
423
+ };
424
+ return icons[slug] || 'file-text';
425
+ }
426
+
427
+ // Load and render a document
428
+ function loadDoc(index) {
429
+ if (index < 0 || index >= docs.length) return;
430
+
431
+ currentDocIndex = index;
432
+ const doc = docs[index];
433
+
434
+ // Update URL hash
435
+ window.location.hash = doc.slug;
436
+
437
+ // Update breadcrumb
438
+ const sectionEl = document.getElementById('currentSection');
439
+ if (sectionEl) sectionEl.textContent = doc.section;
440
+ currentDocEl.textContent = doc.title;
441
+
442
+ // Configure marked with highlight extension
443
+ const markedInstance = new marked.Marked(
444
+ markedHighlight.markedHighlight({
445
+ langPrefix: 'hljs language-',
446
+ highlight(code, lang) {
447
+ const language = hljs.getLanguage(lang) ? lang : 'plaintext';
448
+ return hljs.highlight(code, { language }).value;
449
+ }
450
+ })
451
+ );
452
+ markedInstance.setOptions({ breaks: false, gfm: true });
453
+
454
+ // Render markdown
455
+ content.innerHTML = markedInstance.parse(doc.content);
456
+
457
+ // Show content
458
+ loading.classList.add('hidden');
459
+ content.classList.remove('hidden');
460
+
461
+ // Update active nav item
462
+ document.querySelectorAll('.nav-item').forEach((item, i) => {
463
+ item.classList.toggle('active', i === index);
464
+ item.classList.toggle('text-primary-400', i === index);
465
+ item.classList.toggle('text-slate-400', i !== index);
466
+ });
467
+
468
+ // Update prev/next buttons
469
+ prevBtn.disabled = index === 0;
470
+ nextBtn.disabled = index === docs.length - 1;
471
+
472
+ // Generate TOC
473
+ generateTOC();
474
+
475
+ // Scroll to top
476
+ document.getElementById('contentWrapper').scrollTop = 0;
477
+ }
478
+
479
+ // Generate table of contents
480
+ function generateTOC() {
481
+ const headings = content.querySelectorAll('h2, h3');
482
+ if (headings.length === 0) {
483
+ document.getElementById('toc').classList.add('hidden');
484
+ return;
485
+ }
486
+
487
+ document.getElementById('toc').classList.remove('hidden');
488
+ tocList.innerHTML = Array.from(headings).map(h => {
489
+ const id = h.textContent.toLowerCase().replace(/[^\w]+/g, '-');
490
+ h.id = id;
491
+ const isH3 = h.tagName === 'H3';
492
+ return `
493
+ <li>
494
+ <a href="#${id}" class="block text-slate-400 hover:text-slate-200 truncate ${isH3 ? 'pl-3 text-xs' : ''}">${h.textContent}</a>
495
+ </li>
496
+ `;
497
+ }).join('');
498
+ }
499
+
500
+ // Setup search
501
+ function setupSearch() {
502
+ // Build search index
503
+ searchIndex = docs.flatMap(doc => {
504
+ const sections = doc.content.split(/^##\s+/m).slice(1);
505
+ return [
506
+ { doc: doc.slug, title: doc.title, content: doc.content.slice(0, 500), type: 'doc' },
507
+ ...sections.map(section => {
508
+ const lines = section.split('\n');
509
+ const sectionTitle = lines[0];
510
+ const sectionContent = lines.slice(1).join('\n').slice(0, 300);
511
+ return {
512
+ doc: doc.slug,
513
+ docTitle: doc.title,
514
+ title: sectionTitle,
515
+ content: sectionContent,
516
+ type: 'section'
517
+ };
518
+ })
519
+ ];
520
+ });
521
+
522
+ fuse = new Fuse(searchIndex, {
523
+ keys: ['title', 'content'],
524
+ threshold: 0.3,
525
+ includeMatches: true,
526
+ minMatchCharLength: 2
527
+ });
528
+
529
+ // Search input handler
530
+ let debounceTimer;
531
+ searchInput.addEventListener('input', (e) => {
532
+ clearTimeout(debounceTimer);
533
+ debounceTimer = setTimeout(() => performSearch(e.target.value), 150);
534
+ });
535
+ }
536
+
537
+ // Perform search
538
+ function performSearch(query) {
539
+ if (query.length < 2) {
540
+ searchResults.classList.add('hidden');
541
+ return;
542
+ }
543
+
544
+ const results = fuse.search(query).slice(0, 10);
545
+
546
+ if (results.length === 0) {
547
+ searchResultsList.innerHTML = `
548
+ <div class="px-4 py-3 text-sm text-slate-500">No results found</div>
549
+ `;
550
+ } else {
551
+ searchResultsList.innerHTML = results.map(({ item }) => {
552
+ const docIndex = docs.findIndex(d => d.slug === item.doc);
553
+ const icon = item.type === 'doc' ? 'file-text' : 'hash';
554
+ const subtitle = item.type === 'section' ? item.docTitle : '';
555
+ return `
556
+ <button
557
+ onclick="loadDoc(${docIndex}); searchInput.value=''; searchResults.classList.add('hidden');"
558
+ class="w-full flex items-start gap-3 px-4 py-2 hover:bg-slate-800 text-left"
559
+ >
560
+ <i data-lucide="${icon}" class="w-4 h-4 text-slate-500 mt-0.5 flex-shrink-0"></i>
561
+ <div class="min-w-0">
562
+ <div class="text-sm text-slate-200 truncate">${item.title}</div>
563
+ ${subtitle ? `<div class="text-xs text-slate-500 truncate">${subtitle}</div>` : ''}
564
+ </div>
565
+ </button>
566
+ `;
567
+ }).join('');
568
+ }
569
+
570
+ searchResults.classList.remove('hidden');
571
+ lucide.createIcons();
572
+ }
573
+
574
+ // Keyboard shortcuts
575
+ function setupKeyboardShortcuts() {
576
+ document.addEventListener('keydown', (e) => {
577
+ // Ctrl/Cmd + K for search
578
+ if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
579
+ e.preventDefault();
580
+ searchInput.focus();
581
+ }
582
+
583
+ // Escape to close search
584
+ if (e.key === 'Escape') {
585
+ searchInput.blur();
586
+ searchInput.value = '';
587
+ searchResults.classList.add('hidden');
588
+ }
589
+
590
+ // Arrow keys for navigation (when not in input)
591
+ if (document.activeElement !== searchInput) {
592
+ if (e.key === 'ArrowLeft' && !prevBtn.disabled) {
593
+ loadDoc(currentDocIndex - 1);
594
+ } else if (e.key === 'ArrowRight' && !nextBtn.disabled) {
595
+ loadDoc(currentDocIndex + 1);
596
+ }
597
+ }
598
+ });
599
+ }
600
+
601
+ // Navigation buttons
602
+ function setupNavigation() {
603
+ prevBtn.addEventListener('click', () => loadDoc(currentDocIndex - 1));
604
+ nextBtn.addEventListener('click', () => loadDoc(currentDocIndex + 1));
605
+ document.getElementById('scrollTop').addEventListener('click', () => {
606
+ document.getElementById('contentWrapper').scrollTop = 0;
607
+ });
608
+
609
+ // Handle hash change
610
+ window.addEventListener('hashchange', () => {
611
+ const hash = window.location.hash.slice(1);
612
+ const docIndex = docs.findIndex(d => d.slug === hash);
613
+ if (docIndex >= 0 && docIndex !== currentDocIndex) {
614
+ loadDoc(docIndex);
615
+ }
616
+ });
617
+ }
618
+
619
+ // Start
620
+ init();
621
+ </script>
622
+ </body>
623
+ </html>