@flame0510/project-aether 1.1.9

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 (290) hide show
  1. package/README.md +150 -0
  2. package/agent-templates/README.md +37 -0
  3. package/agent-templates/argus/AGENTS.md +52 -0
  4. package/agent-templates/argus/IDENTITY.md +7 -0
  5. package/agent-templates/argus/MEMORY.md +9 -0
  6. package/agent-templates/argus/SOUL.md +24 -0
  7. package/agent-templates/argus/TOOLS.md +8 -0
  8. package/agent-templates/atlas/AGENTS.md +47 -0
  9. package/agent-templates/atlas/HEARTBEAT.md +10 -0
  10. package/agent-templates/atlas/IDENTITY.md +6 -0
  11. package/agent-templates/atlas/MEMORY.md +9 -0
  12. package/agent-templates/atlas/SOUL.md +21 -0
  13. package/agent-templates/atlas/TOOLS.md +4 -0
  14. package/agent-templates/base-image/.trigger +0 -0
  15. package/agent-templates/base-image/Dockerfile +90 -0
  16. package/agent-templates/base-image/entrypoint.sh +37 -0
  17. package/agent-templates/custom/AGENTS.md +29 -0
  18. package/agent-templates/custom/BOOTSTRAP.md +56 -0
  19. package/agent-templates/custom/MEMORY.md +8 -0
  20. package/agent-templates/prometheus/AGENTS.md +37 -0
  21. package/agent-templates/prometheus/IDENTITY.md +6 -0
  22. package/agent-templates/prometheus/MEMORY.md +9 -0
  23. package/agent-templates/prometheus/SOUL.md +21 -0
  24. package/agent-templates/prometheus/TOOLS.md +4 -0
  25. package/app/agents/ChannelManager.tsx +465 -0
  26. package/app/agents/ImageDownloadBanner.tsx +159 -0
  27. package/app/agents/PageClient.tsx +1285 -0
  28. package/app/agents/create/PageClient.tsx +437 -0
  29. package/app/agents/create/page.tsx +126 -0
  30. package/app/agents/loading.tsx +14 -0
  31. package/app/agents/page.tsx +5 -0
  32. package/app/api/agents/[id]/backup/route.ts +169 -0
  33. package/app/api/agents/[id]/channels/pairing/route.ts +69 -0
  34. package/app/api/agents/[id]/channels/route.ts +14 -0
  35. package/app/api/agents/[id]/channels/telegram/route.ts +50 -0
  36. package/app/api/agents/[id]/lifecycle/route.ts +94 -0
  37. package/app/api/agents/[id]/recreate/route.ts +199 -0
  38. package/app/api/agents/[id]/restart/route.ts +33 -0
  39. package/app/api/agents/[id]/restore/route.ts +81 -0
  40. package/app/api/agents/[id]/route.ts +280 -0
  41. package/app/api/agents/channels-summary/route.ts +39 -0
  42. package/app/api/agents/config-json/route.ts +58 -0
  43. package/app/api/agents/create/route.ts +488 -0
  44. package/app/api/agents/download-image/route.ts +32 -0
  45. package/app/api/agents/image-status/route.ts +126 -0
  46. package/app/api/agents/route.ts +213 -0
  47. package/app/api/agents/token/route.ts +94 -0
  48. package/app/api/agents-active/route.ts +190 -0
  49. package/app/api/agents-config/route.ts +629 -0
  50. package/app/api/alerts/smoke/route.ts +26 -0
  51. package/app/api/aliases/add/route.ts +28 -0
  52. package/app/api/aliases/remove/route.ts +27 -0
  53. package/app/api/assistant/route.ts +204 -0
  54. package/app/api/auth/check/route.ts +38 -0
  55. package/app/api/auth/login/route.ts +85 -0
  56. package/app/api/auth/logout/route.ts +7 -0
  57. package/app/api/auth/status/route.ts +33 -0
  58. package/app/api/config/env/route.ts +132 -0
  59. package/app/api/config/restart/route.ts +26 -0
  60. package/app/api/containers/route.ts +75 -0
  61. package/app/api/cost-override/route.ts +46 -0
  62. package/app/api/costs/route.ts +84 -0
  63. package/app/api/credentials/[id]/reveal/route.ts +21 -0
  64. package/app/api/credentials/[id]/route.ts +52 -0
  65. package/app/api/credentials/[id]/sync/route.ts +58 -0
  66. package/app/api/credentials/detect/route.ts +246 -0
  67. package/app/api/credentials/route.ts +33 -0
  68. package/app/api/crons/[id]/route.ts +69 -0
  69. package/app/api/crons/route.ts +12 -0
  70. package/app/api/crons/runs/route.ts +31 -0
  71. package/app/api/debug/route.ts +11 -0
  72. package/app/api/envcheck/route.ts +18 -0
  73. package/app/api/events/route.ts +24 -0
  74. package/app/api/gateway/agent/route.ts +154 -0
  75. package/app/api/gateway/provider/balance/route.ts +38 -0
  76. package/app/api/gateway/provider/keys.ts +38 -0
  77. package/app/api/gateway/provider/oauth/route.ts +304 -0
  78. package/app/api/gateway/provider/route.ts +209 -0
  79. package/app/api/gateway/route.ts +223 -0
  80. package/app/api/gateway/sync.ts +189 -0
  81. package/app/api/lineage/route.ts +54 -0
  82. package/app/api/memory-context/route.ts +15 -0
  83. package/app/api/metrics/route.ts +35 -0
  84. package/app/api/models/route.ts +77 -0
  85. package/app/api/plugins/route.js +37 -0
  86. package/app/api/provider/upstream.ts +142 -0
  87. package/app/api/provider/v1/chat/completions/route.ts +146 -0
  88. package/app/api/provider/v1/models/route.ts +167 -0
  89. package/app/api/provider-usage/route.ts +629 -0
  90. package/app/api/session/route.ts +39 -0
  91. package/app/api/sessions/[id]/route.ts +38 -0
  92. package/app/api/sessions/route.ts +23 -0
  93. package/app/api/setup/agent-image/route.ts +102 -0
  94. package/app/api/setup/password/route.ts +111 -0
  95. package/app/api/setup/restart/route.ts +76 -0
  96. package/app/api/skills/delete/route.js +105 -0
  97. package/app/api/skills/promote/route.js +129 -0
  98. package/app/api/skills/route.js +203 -0
  99. package/app/api/skills/save/route.js +142 -0
  100. package/app/api/stats/route.ts +34 -0
  101. package/app/api/stats-since/route.ts +20 -0
  102. package/app/api/stream/route.ts +70 -0
  103. package/app/api/system-health/route.ts +233 -0
  104. package/app/api/tool-calls/route.ts +24 -0
  105. package/app/api/tools-config/route.ts +163 -0
  106. package/app/api/update-check/route.ts +127 -0
  107. package/app/api/version/route.ts +25 -0
  108. package/app/api/wizard/complete/route.ts +32 -0
  109. package/app/api/wizard/reset/route.ts +28 -0
  110. package/app/api/wizard/status/route.ts +28 -0
  111. package/app/api/workspace/route.ts +392 -0
  112. package/app/api/workspace/stream/route.ts +136 -0
  113. package/app/components/AppShell.tsx +33 -0
  114. package/app/components/AuthGuard.tsx +91 -0
  115. package/app/components/CostBreakdown.tsx +37 -0
  116. package/app/components/DashboardHeader.tsx +73 -0
  117. package/app/components/DashboardLayout.tsx +76 -0
  118. package/app/components/DashboardToolbar.tsx +61 -0
  119. package/app/components/FloatingActions.tsx +33 -0
  120. package/app/components/Icons.tsx +78 -0
  121. package/app/components/LineageGraphPage.tsx +142 -0
  122. package/app/components/LiveFeed.tsx +48 -0
  123. package/app/components/MobileBottomNav.tsx +84 -0
  124. package/app/components/ModelPickerModal.tsx +94 -0
  125. package/app/components/PasswordInput.tsx +86 -0
  126. package/app/components/PulseChat.tsx +362 -0
  127. package/app/components/Rev4aLoader.tsx +48 -0
  128. package/app/components/SessionDrawer.tsx +263 -0
  129. package/app/components/SessionTopology.tsx +289 -0
  130. package/app/components/Sidebar.tsx +294 -0
  131. package/app/components/Skeleton.tsx +133 -0
  132. package/app/components/SystemCockpit.tsx +169 -0
  133. package/app/components/VersionBanner.tsx +105 -0
  134. package/app/components/WizardButton.tsx +30 -0
  135. package/app/components/ui/Badge.tsx +30 -0
  136. package/app/components/ui/Button.tsx +59 -0
  137. package/app/components/ui/ConfirmModal.tsx +46 -0
  138. package/app/components/ui/FilterBar.tsx +33 -0
  139. package/app/components/ui/Input.tsx +25 -0
  140. package/app/components/ui/ItemList.tsx +83 -0
  141. package/app/components/ui/LoadingSpinner.tsx +30 -0
  142. package/app/components/ui/Metric.tsx +22 -0
  143. package/app/components/ui/Modal.tsx +42 -0
  144. package/app/components/ui/Page.tsx +18 -0
  145. package/app/components/ui/Pill.tsx +6 -0
  146. package/app/components/ui/PropertyList.tsx +24 -0
  147. package/app/components/ui/Select.tsx +26 -0
  148. package/app/components/ui/StatusCard.tsx +32 -0
  149. package/app/components/ui/Surface.tsx +14 -0
  150. package/app/components/ui/Tabs.tsx +55 -0
  151. package/app/components/ui/TemplateOption.tsx +59 -0
  152. package/app/components/ui/Toast.tsx +44 -0
  153. package/app/components/ui/index.ts +19 -0
  154. package/app/components/ui/tokens.ts +18 -0
  155. package/app/config/PageClient.tsx +293 -0
  156. package/app/config/loading.tsx +10 -0
  157. package/app/config/page.tsx +7 -0
  158. package/app/containers/ContainersClient.tsx +129 -0
  159. package/app/containers/loading.tsx +21 -0
  160. package/app/containers/page.tsx +5 -0
  161. package/app/containers/terminal/[id]/TerminalClient.tsx +313 -0
  162. package/app/containers/terminal/[id]/page.tsx +6 -0
  163. package/app/credentials/PageClient.tsx +598 -0
  164. package/app/credentials/loading.tsx +10 -0
  165. package/app/credentials/page.tsx +7 -0
  166. package/app/crons/PageClient.tsx +538 -0
  167. package/app/crons/loading.tsx +10 -0
  168. package/app/crons/page.tsx +5 -0
  169. package/app/design-system.ts +57 -0
  170. package/app/gateway/PageClient.tsx +1048 -0
  171. package/app/gateway/loading.tsx +24 -0
  172. package/app/gateway/page.tsx +5 -0
  173. package/app/globals.css +1474 -0
  174. package/app/layout.tsx +45 -0
  175. package/app/lib/models-context.tsx +41 -0
  176. package/app/lineage/loading.tsx +10 -0
  177. package/app/lineage/page.tsx +13 -0
  178. package/app/loading.tsx +16 -0
  179. package/app/login/page.tsx +160 -0
  180. package/app/memory/MemoryContextPageClient.tsx +196 -0
  181. package/app/memory/loading.tsx +10 -0
  182. package/app/memory/page.tsx +8 -0
  183. package/app/page.tsx +31 -0
  184. package/app/plugins/PageClient.tsx +296 -0
  185. package/app/plugins/loading.tsx +10 -0
  186. package/app/plugins/page.tsx +5 -0
  187. package/app/setup/PageClient.tsx +227 -0
  188. package/app/setup/loading.tsx +21 -0
  189. package/app/setup/page.tsx +7 -0
  190. package/app/skills/PageClient.tsx +499 -0
  191. package/app/skills/loading.tsx +10 -0
  192. package/app/skills/page.tsx +5 -0
  193. package/app/tools/ToolsPageClient.tsx +308 -0
  194. package/app/tools/loading.tsx +10 -0
  195. package/app/tools/page.tsx +62 -0
  196. package/app/tools/tools-catalog.ts +141 -0
  197. package/app/wizard/PageClient.tsx +485 -0
  198. package/app/wizard/icons.tsx +89 -0
  199. package/app/wizard/loading.tsx +24 -0
  200. package/app/wizard/page.tsx +7 -0
  201. package/app/wizard/storage.ts +33 -0
  202. package/app/wizard/useWizard.ts +101 -0
  203. package/app/workspace/WorkspaceClient.tsx +633 -0
  204. package/app/workspace/loading.tsx +36 -0
  205. package/app/workspace/page.tsx +8 -0
  206. package/bin/docker-entrypoint.sh +21 -0
  207. package/bin/postinstall.js +20 -0
  208. package/bin/rev4a.js +696 -0
  209. package/daemon.js +783 -0
  210. package/docs/ARCHITECTURE.md +557 -0
  211. package/docs/CONTAINER-TERMINAL.md +280 -0
  212. package/docs/DESIGN-SYSTEM.md +99 -0
  213. package/docs/FRONTEND-ARCHITECTURE.md +119 -0
  214. package/docs/REV4A.md +504 -0
  215. package/docs/dev/API-REFERENCE.md +1835 -0
  216. package/docs/dev/DATABASE.md +224 -0
  217. package/docs/dev/GATEWAY.md +300 -0
  218. package/docs/dev/PROVIDERS.md +229 -0
  219. package/docs/dev/SESSION-MAINTENANCE-PLAN.md +607 -0
  220. package/docs/dev/WORKSPACE.md +199 -0
  221. package/docs/rag/DATA-FRESHNESS.md +109 -0
  222. package/docs/rag/GLOSSARY.md +125 -0
  223. package/docs/rag/REV4A-OVERVIEW.md +135 -0
  224. package/docs/rag/WHAT-I-CAN-ANSWER.md +124 -0
  225. package/lib/agent-setup.ts +130 -0
  226. package/lib/alerts.ts +115 -0
  227. package/lib/apiFetch.ts +7 -0
  228. package/lib/auth.ts +28 -0
  229. package/lib/billing.ts +100 -0
  230. package/lib/buildAgentImage.ts +346 -0
  231. package/lib/channelManager.ts +386 -0
  232. package/lib/container.ts +60 -0
  233. package/lib/credentials/db.ts +86 -0
  234. package/lib/credentials/delivery.ts +448 -0
  235. package/lib/credentials/detect.ts +149 -0
  236. package/lib/credentials/hash.ts +9 -0
  237. package/lib/credentials/providers.ts +110 -0
  238. package/lib/credentials/vault.ts +195 -0
  239. package/lib/db-bootstrap.d.ts +3 -0
  240. package/lib/db-bootstrap.mjs +144 -0
  241. package/lib/db.ts +25 -0
  242. package/lib/docker-utils.ts +60 -0
  243. package/lib/hooks/useDashboard.ts +264 -0
  244. package/lib/hooks/useRev4aTimezone.ts +28 -0
  245. package/lib/hooks/useScreenshot.ts +30 -0
  246. package/lib/memory-context.ts +385 -0
  247. package/lib/model-catalogue.ts +131 -0
  248. package/lib/model-pricing.ts +63 -0
  249. package/lib/openclaw-cron.ts +350 -0
  250. package/lib/patterns/ApiAdapter.ts +73 -0
  251. package/lib/patterns/ApiClient.ts +65 -0
  252. package/lib/patterns/EventBus.ts +113 -0
  253. package/lib/patterns/FilterStrategy.ts +79 -0
  254. package/lib/patterns/SessionFactory.ts +117 -0
  255. package/lib/patterns/sessionPresentation.ts +117 -0
  256. package/lib/provider-balance.ts +163 -0
  257. package/lib/requireAuth.tsx +38 -0
  258. package/lib/rev4a-auth.d.ts +3 -0
  259. package/lib/rev4a-auth.js +36 -0
  260. package/lib/rev4a-paths.ts +145 -0
  261. package/lib/timezone.ts +46 -0
  262. package/lib/types/index.ts +96 -0
  263. package/lib/utils/format.ts +82 -0
  264. package/lineage.js +56 -0
  265. package/model-pricing.json +482 -0
  266. package/models.config.json +844 -0
  267. package/next-env.d.ts +6 -0
  268. package/next.config.mjs +7 -0
  269. package/package.json +82 -0
  270. package/public/apple-touch-icon.png +0 -0
  271. package/public/favicon-64.png +0 -0
  272. package/public/favicon.svg +58 -0
  273. package/public/icon-192-maskable.png +0 -0
  274. package/public/icon-192.png +0 -0
  275. package/public/icon-512-maskable.png +0 -0
  276. package/public/icon-512.png +0 -0
  277. package/public/manifest.json +38 -0
  278. package/public/rev4a-logo.png +0 -0
  279. package/public/rev4a-logo.svg +58 -0
  280. package/rev4a-rules/AGENTS.md +37 -0
  281. package/scripts/add-auth.cjs +185 -0
  282. package/scripts/backup.sh +66 -0
  283. package/scripts/check-providers.mjs +143 -0
  284. package/scripts/docker/traefik/docker-compose.yml +32 -0
  285. package/scripts/docker/traefik/dynamic/.gitkeep +18 -0
  286. package/scripts/docker/traefik/traefik.yml +37 -0
  287. package/scripts/remove-auth-profile.js +56 -0
  288. package/scripts/restore.sh +82 -0
  289. package/terminal-ws-server.js +139 -0
  290. package/tsconfig.json +42 -0
@@ -0,0 +1,224 @@
1
+ # Rev4a — Database Reference
2
+
3
+ > **Last updated:** 2026-06-30
4
+
5
+ Rev4a uses a single SQLite file (`events.db`) in WAL mode.
6
+
7
+ ## Location
8
+
9
+ | Environment | Path |
10
+ |---|---|
11
+ | VPS (default) | `/path/to/rev4a/data/events.db` |
12
+ | Custom | Set `REV4A_DB` env var |
13
+
14
+ ## WAL Mode
15
+
16
+ ```sql
17
+ PRAGMA journal_mode = WAL;
18
+ PRAGMA synchronous = NORMAL;
19
+ ```
20
+
21
+ - The daemon writes; the Next.js API routes open read-only connections
22
+ - `PRAGMA wal_checkpoint(PASSIVE)` runs after each daemon poll cycle
23
+ - WAL files: `events.db-shm`, `events.db-wal` — do not delete while daemon is running
24
+
25
+ ## Tables
26
+
27
+ ### `sessions` — primary session tracking
28
+
29
+ ```sql
30
+ CREATE TABLE sessions (
31
+ session_id TEXT PRIMARY KEY,
32
+ parent_id TEXT,
33
+ label TEXT,
34
+ model TEXT,
35
+ tokens_in INTEGER DEFAULT 0,
36
+ tokens_out INTEGER DEFAULT 0,
37
+ cost_usd REAL DEFAULT 0,
38
+ status TEXT DEFAULT 'idle',
39
+ task_preview TEXT,
40
+ started_at INTEGER, -- Unix seconds
41
+ ended_at INTEGER, -- Unix seconds, null if active
42
+ updated_at INTEGER, -- Unix ms, updated only on real changes
43
+ trello_card_url TEXT
44
+ );
45
+
46
+ CREATE INDEX idx_sessions_updated ON sessions(updated_at);
47
+ ```
48
+
49
+ **Status values:** `idle` / `working` / `completed` / `error`
50
+
51
+ ### `events` — lifecycle events
52
+
53
+ ```sql
54
+ CREATE TABLE events (
55
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
56
+ ts INTEGER NOT NULL, -- Unix ms
57
+ session_id TEXT NOT NULL,
58
+ type TEXT NOT NULL, -- spawn | complete | error | tool_call
59
+ data TEXT -- JSON payload
60
+ );
61
+
62
+ CREATE INDEX idx_events_session ON events(session_id, ts);
63
+ ```
64
+
65
+ ### `lineage` — explicit parent→child declarations
66
+
67
+ ```sql
68
+ CREATE TABLE lineage (
69
+ child_id TEXT PRIMARY KEY,
70
+ parent_id TEXT,
71
+ agent_name TEXT,
72
+ declared_at INTEGER -- Unix ms
73
+ );
74
+ ```
75
+
76
+ Populated by agents calling `lineage.js` at spawn time or via `POST /api/lineage`.
77
+
78
+ ### `cost_override` — manual monthly billing corrections
79
+
80
+ ```sql
81
+ CREATE TABLE cost_override (
82
+ month TEXT PRIMARY KEY, -- YYYY-MM
83
+ amount REAL,
84
+ note TEXT,
85
+ updated_at INTEGER -- Unix ms
86
+ );
87
+ ```
88
+
89
+ When a `cost_override` row exists for the current month, the UI displays the override value instead of the computed sum.
90
+
91
+ ### `system_metrics` — infrastructure metrics
92
+
93
+ ```sql
94
+ CREATE TABLE system_metrics (
95
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
96
+ ts INTEGER NOT NULL,
97
+ cpu_percent REAL,
98
+ ram_used_mb INTEGER,
99
+ ram_total_mb INTEGER,
100
+ disk_used_gb REAL,
101
+ disk_total_gb REAL,
102
+ load_avg_1m REAL
103
+ );
104
+
105
+ CREATE INDEX idx_metrics_ts ON system_metrics(ts);
106
+ ```
107
+
108
+ Rows older than 24 h are pruned automatically by the daemon.
109
+
110
+ ## Useful Queries
111
+
112
+ ```sql
113
+ -- Total cost this month
114
+ SELECT SUM(cost_usd) FROM sessions
115
+ WHERE started_at >= strftime('%s', date('now', 'start of month'));
116
+
117
+ -- Active sessions right now
118
+ SELECT session_id, label, model, status, cost_usd
119
+ FROM sessions WHERE status = 'working';
120
+
121
+ -- Cost by model (all time)
122
+ SELECT model, SUM(cost_usd) AS total, COUNT(*) AS sessions
123
+ FROM sessions GROUP BY model ORDER BY total DESC;
124
+
125
+ -- Last poll time (freshness check)
126
+ SELECT datetime(MAX(ts)/1000, 'unixepoch', 'localtime') AS last_event
127
+ FROM events;
128
+
129
+ -- Lineage tree for a session
130
+ WITH RECURSIVE tree(child_id, parent_id, agent_name, depth) AS (
131
+ SELECT child_id, parent_id, agent_name, 0 FROM lineage WHERE child_id = 'agent:ops:main'
132
+ UNION ALL
133
+ SELECT l.child_id, l.parent_id, l.agent_name, t.depth + 1
134
+ FROM lineage l JOIN tree t ON l.parent_id = t.child_id
135
+ )
136
+ SELECT * FROM tree;
137
+ ```
138
+
139
+ ## Backup
140
+
141
+ ```bash
142
+ # Manual snapshot
143
+ sqlite3 events.db ".backup events.db.bak-$(date +%s)"
144
+
145
+ # Automated (via backup.sh in repo root)
146
+ bash /data/.openclaw/workspace-ops/rev4a-next-ts/backup.sh
147
+ ```
148
+
149
+ Backups are stored in `backups/` inside the repo directory.
150
+
151
+ ## Credentials Database (`credentials.db`)
152
+
153
+ The credential hub uses a **separate SQLite file** (`credentials.db`) alongside
154
+ events.db in the same data directory. It stores credentials that can be synced
155
+ to agent containers via CLI auth or env files.
156
+
157
+ **Location:** `data/credentials.db` (same directory as `events.db`)
158
+ **Custom path:** Set `REV4A_CREDENTIALS_DB` env var to override.
159
+ **WAL mode:** Enabled.
160
+
161
+ ### `credential_profiles` — credential hub metadata
162
+
163
+ ```sql
164
+ CREATE TABLE credential_profiles (
165
+ id TEXT PRIMARY KEY,
166
+ provider_id TEXT NOT NULL,
167
+ label TEXT NOT NULL,
168
+ status TEXT NOT NULL DEFAULT 'active',
169
+ secret_masked TEXT,
170
+ created_at INTEGER NOT NULL,
171
+ updated_at INTEGER NOT NULL,
172
+ last_synced_at INTEGER
173
+ );
174
+ ```
175
+
176
+ ### `credential_secrets` — stored secret payloads
177
+
178
+ ```sql
179
+ CREATE TABLE credential_secrets (
180
+ profile_id TEXT PRIMARY KEY,
181
+ payload TEXT NOT NULL
182
+ );
183
+ ```
184
+
185
+ Payloads are stored as JSON strings. In a future release they will be AES-256-GCM encrypted.
186
+
187
+ ### `credential_audit_log` — append-only audit trail
188
+
189
+ ```sql
190
+ CREATE TABLE credential_audit_log (
191
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
192
+ ts INTEGER NOT NULL,
193
+ actor TEXT NOT NULL,
194
+ action TEXT NOT NULL,
195
+ profile_id TEXT,
196
+ result TEXT
197
+ );
198
+ ```
199
+
200
+ Actions: `create`, `update`, `delete`, `sync`, `reveal`.
201
+
202
+ ---
203
+
204
+ ## Migrations
205
+
206
+ The daemon applies these migrations safely at startup:
207
+
208
+ ```sql
209
+ ALTER TABLE sessions ADD COLUMN trello_card_url TEXT; -- idempotent
210
+ ALTER TABLE sessions ADD COLUMN ended_at INTEGER; -- idempotent
211
+ ```
212
+
213
+ For future schema changes, add a `try/catch` ALTER TABLE block in `daemon.js` following the same pattern.
214
+
215
+ ## Integrity Check
216
+
217
+ ```bash
218
+ sqlite3 events.db "PRAGMA quick_check"
219
+ # Expected output: ok
220
+ ```
221
+
222
+ **Current location on VPS:** `/path/to/rev4a/data/events.db`
223
+
224
+ The `REV4A_DB` env var is set in the systemd override file at `/etc/systemd/system/rev4a.service.d/env.conf`.
@@ -0,0 +1,300 @@
1
+ # Gateway Page
2
+
3
+ > **Last updated:** 2026-07-31
4
+
5
+ The Gateway page (`/gateway`) is the central control panel for managing provider
6
+ configurations and agent model assignments across all Docker containers.
7
+
8
+ The Gateway aggregates multiple upstream AI providers (DeepSeek, OpenAI, Anthropic,
9
+ Kimi, GLM, Qwen, and others) behind a single Rev4a provider. Agent containers see
10
+ only `rev4a` as their provider and route all LLM traffic through the Rev4a proxy
11
+ at `/api/provider/v1/`.
12
+
13
+ ---
14
+
15
+ ## Overview
16
+
17
+ ```
18
+ Gateway Page
19
+ ├── Provider Tab → Manage provider API keys, enable/disable models, push sync
20
+ └── Agents Tab → Change primary model per agent container
21
+ ```
22
+
23
+ The Gateway talks to each agent container directly via `docker exec`, reading and
24
+ writing to `/root/.openclaw/openclaw.json` inside the container.
25
+
26
+ ---
27
+
28
+ ## Provider Tab
29
+
30
+ Lists all AI providers from `models.config.json` in the project root. Each provider
31
+ row shows:
32
+
33
+ - Provider name and label
34
+ - Configured API key (masked)
35
+ - Enable/disable toggles per model
36
+ - ADD / CHANGE / REMOVE KEY buttons
37
+
38
+ ### Provider Key Storage
39
+
40
+ Provider API keys are stored in `data/provider-keys.json`:
41
+
42
+ ```json
43
+ {
44
+ "deepseek": "sk-...",
45
+ "openrouter": "sk-...",
46
+ "rev4a": "ciao"
47
+ }
48
+ ```
49
+
50
+ The `rev4a` entry is the master gateway token. Agent containers authenticate
51
+ against the Rev4a provider proxy using this token. See [`PROVIDERS.md`](PROVIDERS.md).
52
+
53
+ ### Sync Flow
54
+
55
+ When a provider key is saved or a model toggle is changed, the Gateway:
56
+
57
+ 1. **Reads** `models.config.json` to get the full model catalogue
58
+ 2. **Filters** enabled models for providers that have a configured API key
59
+ 3. **Builds** a `models.providers.rev4a` config block (without `rev4a/` prefix
60
+ on model IDs)
61
+ 4. **Writes** the block into `/root/.openclaw/openclaw.json` on every agent container
62
+ (containers with `AGENT_ID` Docker label)
63
+ 5. **Cleans up** stale `models.json` and `auth-profiles.json` files inside each
64
+ container
65
+ 6. **Writes** the block into `/root/.openclaw/openclaw.json` on every agent container
66
+ — **does NOT touch** `agents.defaults.model` or `agents.list[].model`
67
+ 7. **Does NOT restart** the gateway — writes are live via file write
68
+
69
+ ### Model ID Convention
70
+
71
+ Inside `models.providers.rev4a.models`, model IDs are stored **without** the
72
+ `rev4a/` prefix:
73
+
74
+ ```json
75
+ {
76
+ "models": {
77
+ "providers": {
78
+ "rev4a": {
79
+ "baseUrl": "http://host.docker.internal:3740/api/provider/v1",
80
+ "api": "openai-completions",
81
+ "apiKey": "***",
82
+ "models": [
83
+ { "id": "deepseek/deepseek-v4-flash", "name": "DeepSeek V4 Flash" },
84
+ { "id": "deepseek/deepseek-v4-pro", "name": "DeepSeek V4 Pro" }
85
+ ]
86
+ }
87
+ }
88
+ }
89
+ }
90
+ ```
91
+
92
+ OpenClaw automatically prefixes model IDs with the provider name at runtime,
93
+ producing `rev4a/deepseek/deepseek-v4-flash`. The `mode` field is **not** set —
94
+ OpenClaw defaults to merging config models with auto-discovered models.
95
+
96
+ ### Model Catalogue
97
+
98
+ The model catalogue lives in [`models.config.json`](../models.config.json) at the project root.
99
+ This file is **tracked in the repository** and serves as the default model configuration
100
+ for anyone cloning the project. It defines all known models across all providers:
101
+
102
+ ```json
103
+ {
104
+ "models": [
105
+ { "id": "openai/gpt-5.6-sol", "name": "GPT-5.6 Sol", "provider": "openai", "enabled": true },
106
+ { "id": "openai/gpt-5.6-terra", "name": "GPT-5.6 Terra", "provider": "openai", "enabled": true },
107
+ { "id": "openai/gpt-5.6-luna", "name": "GPT-5.6 Luna", "provider": "openai", "enabled": true },
108
+ { "id": "openai/gpt-5.5", "name": "GPT-5.5", "provider": "openai", "enabled": true },
109
+ { "id": "openai/gpt-5.4", "name": "GPT-5.4", "provider": "openai", "enabled": true },
110
+ { "id": "openai/gpt-5.4-mini", "name": "GPT-5.4 Mini", "provider": "openai", "enabled": true },
111
+ { "id": "anthropic/claude-fable-5", "name": "Claude Fable 5", "provider": "anthropic", "enabled": false },
112
+ { "id": "anthropic/claude-opus-5", "name": "Claude Opus 5", "provider": "anthropic", "enabled": false },
113
+ { "id": "anthropic/claude-sonnet-5", "name": "Claude Sonnet 5", "provider": "anthropic", "enabled": false },
114
+ { "id": "groq/llama-3.3-70b-versatile", "name": "Llama 3.3 70B (Groq)", "provider": "groq", "enabled": false },
115
+ { "id": "kimi/kimi-k3", "name": "Kimi K3", "provider": "kimi", "enabled": true },
116
+ { "id": "glm/glm-5.2", "name": "GLM-5.2", "provider": "glm", "enabled": false },
117
+ { "id": "qwen/qwen3.7-plus", "name": "Qwen 3.7 Plus", "provider": "qwen", "enabled": true }
118
+ ]
119
+ }
120
+ ```
121
+
122
+ Only enabled models for providers with a configured API key are synced to agent
123
+ containers.
124
+
125
+ ---
126
+
127
+ ## Agents Tab
128
+
129
+ Lists all agent containers discovered from Docker (containers with `AGENT_ID`
130
+ label). Each agent row shows:
131
+
132
+ - Agent name and container name
133
+ - Current primary model
134
+ - "Change Model" button
135
+
136
+ ### Change Model Flow
137
+
138
+ Clicking "Change Model" opens an inline form with:
139
+
140
+ 1. **Primary model select** — dropdown of all enabled models (filtered to
141
+ configured providers only)
142
+
143
+ On save:
144
+
145
+ 1. **PUT /api/gateway/agent** writes the model config to the container's
146
+ `openclaw.json`:
147
+ - `agents.defaults.model.primary` and `agents.list[0].model.primary` written
148
+ with format `rev4a/<provider>/<model>`
149
+ - No fallbacks are set unless explicitly provided
150
+ 2. **No restart** — writes are live via `docker exec node -e`
151
+
152
+ ### Model Select Filtering
153
+
154
+ The model select in the Agents tab only shows models whose provider has a
155
+ configured API key in `data/provider-keys.json`. This ensures users can only
156
+ select models that are actually available.
157
+
158
+ ---
159
+
160
+ ## API Endpoints
161
+
162
+ ### `GET /api/gateway`
163
+
164
+ Returns live Gateway status from all agent containers. Reads agent model configs
165
+ via `openclaw models status --json` inside each container.
166
+
167
+ **Response:**
168
+ ```json
169
+ {
170
+ "agents": {
171
+ "total": 1,
172
+ "list": [
173
+ {
174
+ "containerName": "openclaw-atlas",
175
+ "agentId": "atlas",
176
+ "agentName": "Atlas",
177
+ "defaultModel": "rev4a/deepseek/deepseek-v4-flash",
178
+ "configured": true
179
+ }
180
+ ]
181
+ }
182
+ }
183
+ ```
184
+
185
+ ### `PUT /api/gateway/provider`
186
+
187
+ Triggers a full provider model sync to all agent containers. Only writes
188
+ `models.providers.rev4a` — does NOT touch model references.
189
+
190
+ **Body:** none (reads current provider state from `models.config.json` and
191
+ `data/provider-keys.json`)
192
+
193
+ **Response:**
194
+ ```json
195
+ {
196
+ "status": "ok",
197
+ "activeModels": 2,
198
+ "results": ["Active models: 2 across 1 agent(s)"]
199
+ }
200
+ ```
201
+
202
+ ### `PUT /api/gateway/agent`
203
+
204
+ Updates model config for a single agent container (primary model only).
205
+
206
+ **Body:**
207
+ ```json
208
+ {
209
+ "containerName": "openclaw-atlas",
210
+ "model": "deepseek/deepseek-v4-flash"
211
+ }
212
+ ```
213
+
214
+ **Response:**
215
+ ```json
216
+ {
217
+ "status": "ok",
218
+ "agent": "openclaw-atlas",
219
+ "model": {
220
+ "primary": "rev4a/deepseek/deepseek-v4-flash"
221
+ },
222
+ "verify": { "ok": true, "bytes": 2058 }
223
+ }
224
+ ```
225
+
226
+ ### `GET /api/gateway/provider`
227
+
228
+ Returns current provider configuration state.
229
+
230
+ **Response:**
231
+ ```json
232
+ {
233
+ "providers": [
234
+ {
235
+ "provider": "deepseek",
236
+ "label": "DeepSeek",
237
+ "configured": true,
238
+ "baseUrl": "https://api.deepseek.com",
239
+ "models": [
240
+ { "id": "deepseek/deepseek-v4-flash", "name": "DeepSeek V4 Flash", "enabled": true }
241
+ ]
242
+ }
243
+ ]
244
+ }
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Config Page (`/config`)
250
+
251
+ A companion page at `/config` that allows editing environment variables and
252
+ triggering a server restart.
253
+
254
+ ### `PUT /api/config/env`
255
+
256
+ Update environment variables on the VPS host.
257
+
258
+ **Body:** `{ "REV4A_PASSWORD": "newpass", ... }`
259
+
260
+ **Response:** `{ "ok": true }`
261
+
262
+ ### `POST /api/config/restart`
263
+
264
+ Restart the Rev4a server (via systemd).
265
+
266
+ **Response:** `{ "ok": true }`
267
+
268
+ ---
269
+
270
+ ## Key Design Decisions
271
+
272
+ 1. **No `mode: 'replace'`** — The `mode` field is not written to the provider
273
+ config. OpenClaw uses its default merge behavior, combining config models with
274
+ auto-discovered models from the provider API.
275
+
276
+ 2. **Model IDs without `rev4a/` prefix in config** — Inside
277
+ `models.providers.rev4a.models`, model IDs do NOT include the `rev4a/`
278
+ prefix. OpenClaw adds it automatically at runtime.
279
+
280
+ 3. **Provider keys in `data/provider-keys.json`** — Not in env vars or
281
+ committed code. This file is gitignored and managed exclusively through the
282
+ Gateway UI.
283
+
284
+ 4. **No gateway restart after model sync** — The sync module writes `models.providers`
285
+ to the file directly without restarting the gateway.
286
+
287
+ 5. **Entrypoint does not generate openclaw.json** — The entrypoint resolves the
288
+ auth token and starts the gateway with `--allow-unconfigured`; OpenClaw
289
+ generates its own default config on first boot. All post-creation config
290
+ (controlUi, model refs, providers) is written by the create route
291
+ (`POST /api/agents/create`) after the gateway is fully ready.
292
+ The entrypoint also runs `openclaw doctor --non-interactive` **before** the
293
+ gateway, but only when the OpenClaw version changed since last boot
294
+ (tracked in `/root/.openclaw/.last-version`) — safe migrations only, no restart.
295
+
296
+ 6. **Model ref written after gateway readiness** — When the wizard creates an agent,
297
+ the create route waits for gateway health check, then writes
298
+ `agents.defaults.model.primary` + fallbacks and `gateway.controlUi.allowedOrigins`,
299
+ then calls `syncAgent(name)`. The Gateway sync (`PUT /api/gateway/provider`)
300
+ never touches model references — only `models.providers` is synced.