@enderfga/claw-orchestrator 4.0.0 → 4.0.3

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.
@@ -0,0 +1,153 @@
1
+ # Dashboard
2
+
3
+ The dashboard is a single-page HTML app served by the orchestrator's embedded
4
+ HTTP server. It lets you **launch and observe** Council sessions, Autoloop
5
+ runs, and Forge (Ultraapp) builds from a browser — no CLI, no webchat, no
6
+ plugin tool calls needed.
7
+
8
+ URL: `http://127.0.0.1:18796/dash` (local) or whatever public hostname you
9
+ front the embedded server with (the recommended setup uses a path-based
10
+ reverse proxy, e.g. `https://<your-host>/dash`).
11
+
12
+ ## Tabs
13
+
14
+ | Tab | Backed by | Launch endpoint |
15
+ |---|---|---|
16
+ | Autoloop | `SessionManager.autoloopStart()` | `POST /autoloop/new` |
17
+ | Council | `SessionManager.councilStart()` | `POST /council/new` |
18
+ | Forge | `UltraappManager.createRun()` | `POST /ultraapp/new` |
19
+
20
+ Each tab has a `+ New` button in the sidebar. Council and Autoloop open a
21
+ modal form (because they need workspace/task input); Forge POSTs an empty
22
+ body and drops you into an interview (the spec is built conversationally).
23
+
24
+ ## Standalone deployment
25
+
26
+ The recommended way to run the dashboard 24/7 is a separate `clawo serve`
27
+ process under launchd — completely decoupled from the OpenClaw gateway. The
28
+ gateway's plugin-side embedded server still works (lazy init on first tool
29
+ call); when both processes try to bind the default port, the loser gracefully
30
+ skips, so the two coexist without conflict.
31
+
32
+ Example `~/Library/LaunchAgents/com.clawo.serve.plist`:
33
+
34
+ ```xml
35
+ <?xml version="1.0" encoding="UTF-8"?>
36
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
37
+ <plist version="1.0">
38
+ <dict>
39
+ <key>Label</key><string>com.clawo.serve</string>
40
+ <key>RunAtLoad</key><true/>
41
+ <key>KeepAlive</key><true/>
42
+ <key>ThrottleInterval</key><integer>5</integer>
43
+ <key>ProgramArguments</key>
44
+ <array>
45
+ <string>/opt/homebrew/bin/node</string>
46
+ <string>/opt/homebrew/bin/clawo</string>
47
+ <string>serve</string>
48
+ <string>--port</string><string>18796</string>
49
+ <string>--host</string><string>127.0.0.1</string>
50
+ </array>
51
+ <key>StandardOutPath</key>
52
+ <string>/Users/USER/.openclaw/logs/clawo-serve.log</string>
53
+ <key>StandardErrorPath</key>
54
+ <string>/Users/USER/.openclaw/logs/clawo-serve.log</string>
55
+ </dict>
56
+ </plist>
57
+ ```
58
+
59
+ Bootstrap:
60
+
61
+ ```sh
62
+ launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.clawo.serve.plist
63
+ launchctl print "gui/$(id -u)/com.clawo.serve" | grep state
64
+ ```
65
+
66
+ ## Auth
67
+
68
+ The embedded server self-generates a 32-byte token at startup and writes it
69
+ to `~/.openclaw/server-token` (mode 0600). Same-user processes on the box
70
+ read it and present it as `Authorization: Bearer <token>` (or
71
+ `?token=<v>` query / `clawo_auth` cookie).
72
+
73
+ ### Local access
74
+
75
+ ```
76
+ http://127.0.0.1:18796/dash?token=$(cat ~/.openclaw/server-token)
77
+ ```
78
+
79
+ The server sets a `clawo_auth` cookie on the first query-token request, so
80
+ the bookmark `/dash` works on subsequent visits.
81
+
82
+ ### Hosted access via reverse proxy (recommended)
83
+
84
+ Don't expose the token to the public internet. Instead, gate the public
85
+ hostname with whatever auth layer you already trust (CF Access passkey,
86
+ Tailscale, mTLS, etc.) and have the reverse proxy **inject the Bearer
87
+ token on behalf of the user** when forwarding to port 18796. The browser
88
+ authenticates only against your edge auth; the dashboard's own token stays
89
+ inside the box.
90
+
91
+ Example sasha-doctor pattern (matches the user-side setup):
92
+ ```js
93
+ // after the edge auth check passes:
94
+ if (!req.headers.authorization) {
95
+ req.headers.authorization =
96
+ "Bearer " + fs.readFileSync("~/.openclaw/server-token", "utf-8").trim();
97
+ }
98
+ proxyHTTP(req, res, 18796);
99
+ ```
100
+
101
+ The `/login?token=...&redirect=/dash` endpoint exists as a fallback for
102
+ quick one-shot setups (works locally and through proxies that DON'T inject
103
+ the Bearer for you), but the proxy-injects-Bearer pattern is preferred
104
+ because users never see or paste the token.
105
+
106
+ Token-file write is deferred to the `listen()`-success callback so a second
107
+ process that loses the EADDRINUSE race does NOT clobber the winner's token.
108
+
109
+ ## Cross-process visibility
110
+
111
+ When the dashboard runs in a different process from where you spawn runs
112
+ (e.g. you started a council via the OpenClaw plugin tool from webchat, but
113
+ the dashboard is in `clawo serve`), the run state is invisible across
114
+ in-memory boundaries. The dashboard fixes this by unioning in-memory state
115
+ with on-disk records on every list call:
116
+
117
+ - **Councils**: `~/.openclaw/council-logs/council-*.md` — parsed for
118
+ `- **ID**:`, `- **Time**:`, `- **Task**:`, `- **Status**:` headers.
119
+ Legacy transcripts (pre-v4.0) fall back to a filename-derived id.
120
+ - **Autoloops**: `~/.claw-orchestrator/autoloop-registry.jsonl` — an
121
+ append-only JSONL index written by `autoloopStart()`. Stale entries
122
+ whose ledger directory no longer exists are filtered out at read time.
123
+ - **Forge**: `UltraappStore.listRuns()` already reads from disk
124
+ (`~/.claw-orchestrator/ultraapps/`).
125
+
126
+ Result: any run you've ever started — from any process — shows up in the
127
+ sidebar, sorted newest-first, until the underlying files are deleted.
128
+
129
+ ## Reverse-proxy integration
130
+
131
+ If you front the embedded server with sasha-doctor (or another reverse
132
+ proxy), route these paths to `127.0.0.1:18796`:
133
+
134
+ - `/dashboard`, `/dash`, `/login`
135
+ - `/autoloop/*`, `/council/*`, `/ultraapp/*`
136
+
137
+ The dashboard's relative `fetch()` calls expect the proxy to preserve the
138
+ path verbatim — no prefix stripping. `/v1/openclaw/*` should keep routing
139
+ to the OpenClaw gateway, not the embedded server.
140
+
141
+ ## Reset
142
+
143
+ To wipe dashboard state without touching real run data:
144
+
145
+ ```sh
146
+ # Forget all known autoloops (council/forge unchanged).
147
+ rm ~/.claw-orchestrator/autoloop-registry.jsonl
148
+
149
+ # Force the standalone server to mint a fresh auth token.
150
+ launchctl kickstart -k "gui/$(id -u)/com.clawo.serve"
151
+ # Then visit /login?token=$(cat ~/.openclaw/server-token)&redirect=/dash once
152
+ # to refresh the cookie.
153
+ ```
@@ -164,8 +164,8 @@ src/__tests__/fixtures/ultraapp-traces/
164
164
  ```
165
165
 
166
166
  ```bash
167
- tsx test-ultraapp-integration.ts --trace=image-batch-resize
168
- tsx test-ultraapp-integration.ts --trace=all
167
+ tsx scripts/test-ultraapp-integration.ts --trace=image-batch-resize
168
+ tsx scripts/test-ultraapp-integration.ts --trace=all
169
169
  ```
170
170
 
171
171
  The `spec-extraction-quality.test.ts` test replays each trace through