@tloncorp/openclaw 0.1.0 → 0.4.0

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 (88) hide show
  1. package/README.md +232 -23
  2. package/dist/index.js +292 -43
  3. package/dist/index.js.map +1 -1
  4. package/dist/setup-api.js +3 -0
  5. package/dist/setup-api.js.map +1 -0
  6. package/dist/setup-entry.js +4 -0
  7. package/dist/setup-entry.js.map +1 -0
  8. package/dist/src/actions.js +30 -8
  9. package/dist/src/actions.js.map +1 -1
  10. package/dist/src/channel.js +156 -373
  11. package/dist/src/channel.js.map +1 -1
  12. package/dist/src/channel.runtime.js +142 -0
  13. package/dist/src/channel.runtime.js.map +1 -0
  14. package/dist/src/config-schema.js +41 -1
  15. package/dist/src/config-schema.js.map +1 -1
  16. package/dist/src/effective-owner.js +22 -0
  17. package/dist/src/effective-owner.js.map +1 -0
  18. package/dist/src/gateway-status.js +72 -0
  19. package/dist/src/gateway-status.js.map +1 -0
  20. package/dist/src/monitor/approval.js +194 -96
  21. package/dist/src/monitor/approval.js.map +1 -1
  22. package/dist/src/monitor/command-auth.js +62 -0
  23. package/dist/src/monitor/command-auth.js.map +1 -0
  24. package/dist/src/monitor/command-bridge.js +27 -0
  25. package/dist/src/monitor/command-bridge.js.map +1 -0
  26. package/dist/src/monitor/computing-presence.js +221 -0
  27. package/dist/src/monitor/computing-presence.js.map +1 -0
  28. package/dist/src/monitor/discovery.js +17 -9
  29. package/dist/src/monitor/discovery.js.map +1 -1
  30. package/dist/src/monitor/index.js +960 -251
  31. package/dist/src/monitor/index.js.map +1 -1
  32. package/dist/src/monitor/media.js +195 -30
  33. package/dist/src/monitor/media.js.map +1 -1
  34. package/dist/src/monitor/nudge-runner.js +232 -0
  35. package/dist/src/monitor/nudge-runner.js.map +1 -0
  36. package/dist/src/monitor/nudge-state.js +58 -0
  37. package/dist/src/monitor/nudge-state.js.map +1 -0
  38. package/dist/src/monitor/owner-reply-persistence.js +92 -0
  39. package/dist/src/monitor/owner-reply-persistence.js.map +1 -0
  40. package/dist/src/monitor/pending-nudge-persistence.js +15 -0
  41. package/dist/src/monitor/pending-nudge-persistence.js.map +1 -0
  42. package/dist/src/monitor/settings-sync.js +28 -0
  43. package/dist/src/monitor/settings-sync.js.map +1 -0
  44. package/dist/src/monitor/utils.js +21 -4
  45. package/dist/src/monitor/utils.js.map +1 -1
  46. package/dist/src/nudge-decision.js +309 -0
  47. package/dist/src/nudge-decision.js.map +1 -0
  48. package/dist/src/nudge-messages.js +25 -0
  49. package/dist/src/nudge-messages.js.map +1 -0
  50. package/dist/src/nudge-scheduler.js +91 -0
  51. package/dist/src/nudge-scheduler.js.map +1 -0
  52. package/dist/src/pending-nudge.js +57 -0
  53. package/dist/src/pending-nudge.js.map +1 -0
  54. package/dist/src/session-roles.js +39 -0
  55. package/dist/src/session-roles.js.map +1 -0
  56. package/dist/src/settings.js +82 -6
  57. package/dist/src/settings.js.map +1 -1
  58. package/dist/src/setup-core.js +164 -0
  59. package/dist/src/setup-core.js.map +1 -0
  60. package/dist/src/setup-surface.js +85 -0
  61. package/dist/src/setup-surface.js.map +1 -0
  62. package/dist/src/telemetry.js +252 -0
  63. package/dist/src/telemetry.js.map +1 -0
  64. package/dist/src/tlon-binary.js +46 -0
  65. package/dist/src/tlon-binary.js.map +1 -0
  66. package/dist/src/tlon-tool-guard.js +44 -0
  67. package/dist/src/tlon-tool-guard.js.map +1 -0
  68. package/dist/src/tool-trace.js +100 -0
  69. package/dist/src/tool-trace.js.map +1 -0
  70. package/dist/src/types.js +35 -0
  71. package/dist/src/types.js.map +1 -1
  72. package/dist/src/urbit/api-client.js +4 -3
  73. package/dist/src/urbit/api-client.js.map +1 -1
  74. package/dist/src/urbit/base-url.js +2 -2
  75. package/dist/src/urbit/base-url.js.map +1 -1
  76. package/dist/src/urbit/fetch.js +1 -1
  77. package/dist/src/urbit/fetch.js.map +1 -1
  78. package/dist/src/urbit/send.js +6 -2
  79. package/dist/src/urbit/send.js.map +1 -1
  80. package/dist/src/urbit/sse-client.js +13 -2
  81. package/dist/src/urbit/sse-client.js.map +1 -1
  82. package/dist/src/urbit/upload.js +25 -20
  83. package/dist/src/urbit/upload.js.map +1 -1
  84. package/dist/src/version.generated.js +3 -0
  85. package/dist/src/version.generated.js.map +1 -0
  86. package/package.json +32 -25
  87. package/dist/src/onboarding.js +0 -178
  88. package/dist/src/onboarding.js.map +0 -1
package/README.md CHANGED
@@ -14,6 +14,7 @@ Tlon/Urbit channel plugin for [OpenClaw](https://github.com/openclaw/openclaw).
14
14
  - **Settings Store**: Hot-reload config via Urbit settings-store (no restart needed)
15
15
  - **Auto-Discovery**: Automatically monitors all channels in joined groups
16
16
  - **Cite Resolution**: Parse and fetch quoted message content
17
+ - **Optional Telemetry**: Explicit PostHog opt-in for hosted analytics
17
18
 
18
19
  ## Installation
19
20
 
@@ -37,42 +38,59 @@ channels:
37
38
  ship: "~your-ship"
38
39
  url: "https://your-ship.tlon.network"
39
40
  code: "your-access-code"
40
-
41
+
41
42
  # Owner receives approval requests and can manage the bot
42
43
  ownerShip: "~your-main-ship"
43
-
44
+
44
45
  # Ships allowed to DM the bot directly
45
46
  dmAllowlist:
46
47
  - "~trusted-friend"
47
48
  - "~another-ship"
48
-
49
+
49
50
  # Auto-accept settings
50
- autoAcceptDmInvites: true # Accept DMs from ships in dmAllowlist
51
- autoAcceptGroupInvites: false # Require approval for group invites
52
-
51
+ autoAcceptDmInvites: true # Accept DMs from ships in dmAllowlist
52
+ autoAcceptGroupInvites: false # Require approval for group invites
53
+
53
54
  # Channel discovery
54
- autoDiscoverChannels: true # Monitor all channels in joined groups
55
- groupChannels: # Additional channels to monitor explicitly
55
+ autoDiscoverChannels: true # Monitor all channels in joined groups
56
+ groupChannels: # Additional channels to monitor explicitly
56
57
  - "chat/~host-ship/channel-name"
57
-
58
+
58
59
  # Per-channel authorization
59
60
  authorization:
60
61
  channelRules:
61
62
  "chat/~host/public-channel":
62
- mode: "open" # Anyone can interact
63
+ mode: "open" # Anyone can interact
63
64
  "chat/~host/private-channel":
64
65
  mode: "restricted"
65
66
  allowedShips:
66
67
  - "~specific-ship"
67
-
68
+
68
69
  # Ships authorized by default for restricted channels
69
70
  defaultAuthorizedShips:
70
71
  - "~always-allowed"
71
-
72
+
72
73
  # Show model info in responses
73
74
  showModelSignature: false
75
+
76
+ # Optional PostHog telemetry. Disabled unless explicitly enabled.
77
+ telemetry:
78
+ enabled: true
79
+ apiKey: "phc_your_project_api_key"
80
+ host: "https://us.i.posthog.com"
74
81
  ```
75
82
 
83
+ ## Telemetry
84
+
85
+ Telemetry is disabled by default. The plugin only sends tlemetry events when `channels.tlon.telemetry.enabled`
86
+ is set to `true` and an API key is configured.
87
+
88
+ When enabled, the plugin captures a single `TlonBot Reply Handled` event each time it enters the OpenClaw reply
89
+ flow. The event summarizes OpenClaw usage (tools used, character count, etc.), but does not log message content.
90
+
91
+ The plugin does not enable telemetry automatically just because an API key is present. `enabled: true` is
92
+ required so open-source installs do not phone home by default.
93
+
76
94
  ## Approval System
77
95
 
78
96
  The approval system lets you control who can interact with your bot. When `ownerShip` is configured, you'll receive DM notifications for:
@@ -100,11 +118,11 @@ Reply "approve", "deny", or "block" (ID: dm-1234567890-abc)
100
118
 
101
119
  The owner can send these commands via DM:
102
120
 
103
- | Command | Description |
104
- |---------|-------------|
105
- | `blocked` | List all blocked ships |
106
- | `pending` | List pending approval requests |
107
- | `unblock ~ship` | Unblock a ship |
121
+ | Command | Description |
122
+ | --------------- | ------------------------------ |
123
+ | `blocked` | List all blocked ships |
124
+ | `pending` | List pending approval requests |
125
+ | `unblock ~ship` | Unblock a ship |
108
126
 
109
127
  ## Bundled Skill
110
128
 
@@ -138,7 +156,7 @@ Full documentation: https://docs.openclaw.ai/channels/tlon
138
156
  gh repo clone tloncorp/openclaw-tlon
139
157
  cd openclaw-tlon
140
158
 
141
- # 2. Run setup (clones api-beta, creates .env)
159
+ # 2. Run setup (clones tlonbot + tlon-apps, creates .env)
142
160
  ./dev/setup.sh
143
161
 
144
162
  # 3. Edit .env with your credentials
@@ -157,17 +175,208 @@ docker compose --env-file .env -f dev/docker-compose.yml up --build
157
175
 
158
176
  ```
159
177
  parent/
160
- ├── api-beta/ # @tloncorp/api - shared API library (cloned by setup)
178
+ ├── tlonbot/ # Bot prompts + image-search extension (optional)
179
+ ├── tlon-apps/ # Source repo for dev-only local @tloncorp/api overrides
180
+ │ # (or another checkout such as "homestead")
161
181
  └── openclaw-tlon/ # This repo
162
182
  ```
163
183
 
164
- The tlon-skill is installed via npm and doesn't need to be cloned separately.
184
+ `@tloncorp/api` and `@tloncorp/tlon-skill` are installed via npm for normal installs. During Docker dev, the entrypoint will also link a local `@tloncorp/api` override from `${TLON_APPS_DIR:-../tlon-apps}/packages/api` when that checkout has been built.
185
+
186
+ The dev override uses the real `tlon-apps/packages/api` package, similar to the old `api-beta` workflow. You still rebuild `tlon-apps` separately so its `dist/` stays current, and the container startup will link that local package instead of using the published npm copy.
187
+
188
+ If your local checkout is named `homestead` instead of `tlon-apps`, set:
189
+
190
+ ```bash
191
+ export TLON_APPS_DIR=/absolute/path/to/homestead
192
+ ```
193
+
194
+ `pnpm dev`, `pnpm dev:api:link`, and the Docker dev override will all use that path.
195
+
196
+ If you want to modify `@tloncorp/api` locally while working in this repo, first link the local package into `openclaw-tlon` so your editor and local TypeScript resolve against `${TLON_APPS_DIR:-../tlon-apps}/packages/api`:
197
+
198
+ ```bash
199
+ pnpm dev:api:link
200
+ ```
201
+
202
+ That makes `openclaw-tlon` resolve `@tloncorp/api` to `${TLON_APPS_DIR:-../tlon-apps}/packages/api` on your machine. After changing the API surface, rebuild it there:
203
+
204
+ ```bash
205
+ pnpm --dir "${TLON_APPS_DIR:-../tlon-apps}" --filter @tloncorp/api build
206
+ ```
207
+
208
+ To switch back to the published npm package on your host:
209
+
210
+ ```bash
211
+ pnpm dev:api:unlink
212
+ ```
165
213
 
166
214
  ### Making Changes
167
215
 
168
- 1. Edit code in either repo
169
- 2. Restart container: `docker compose --env-file .env -f dev/docker-compose.yml up --build`
170
- 3. For faster iteration, run OpenClaw directly on host with npm link
216
+ 1. Edit code in this repo or `${TLON_APPS_DIR:-../tlon-apps}/packages/api`
217
+ 2. If you changed the API package, rebuild it first:
218
+ `pnpm --dir "${TLON_APPS_DIR:-../tlon-apps}" --filter @tloncorp/api build`
219
+ 3. Restart container: `docker compose --env-file .env -f dev/docker-compose.yml up --build`
220
+ 4. For faster iteration, run OpenClaw directly on host with npm link
221
+
222
+ ## Testing
223
+
224
+ ### Unit Tests
225
+
226
+ ```bash
227
+ pnpm test # Run unit tests
228
+ pnpm test:watch # Watch mode
229
+ pnpm test:security # Security tests only
230
+ ```
231
+
232
+ ### Integration Tests
233
+
234
+ Integration tests spin up ephemeral fakezod ships (~zod, ~ten, ~mug) in Docker, boot an OpenClaw gateway with the plugin, and run end-to-end scenarios.
235
+
236
+ #### Minimal Setup (`test:integration`)
237
+
238
+ Runs everything in Docker — ships + gateway + tests. Only needs an LLM API key.
239
+
240
+ **1. Create `.env`** with at minimum:
241
+
242
+ ```bash
243
+ # Required: at least one LLM provider key
244
+ OPENROUTER_API_KEY=sk-or-...
245
+
246
+ # Optional: override the default model (default: openrouter/minimax/minimax-m2.5)
247
+ # MODEL=anthropic/claude-sonnet-4-5
248
+ ```
249
+
250
+ That's it. The test harness handles ship credentials, config, and cleanup automatically.
251
+
252
+ **2. Run:**
253
+
254
+ ```bash
255
+ pnpm test:integration
256
+ ```
257
+
258
+ This will:
259
+
260
+ - Start 3 fakezod ships (~zod as bot, ~ten as test user, ~mug as third party)
261
+ - Build and start an OpenClaw container with the plugin
262
+ - Wait for ships, gateway, and SSE subscriptions
263
+ - Run all test cases in `test/cases/`
264
+ - Tear everything down on exit
265
+
266
+ **Run a specific test:**
267
+
268
+ ```bash
269
+ pnpm test:integration -- test/cases/dm.test.ts
270
+ ```
271
+
272
+ #### Extended Setup (`test:integration:dev`)
273
+
274
+ For iterative development — you manage the ships and gateway yourself, tests run directly against them.
275
+
276
+ **1. Run setup** (clones sibling repos, creates `.env` from template):
277
+
278
+ ```bash
279
+ ./dev/setup.sh
280
+ ```
281
+
282
+ This clones `tlonbot` and `tlon-apps` as sibling directories and creates `.env` from `.env.example` if it doesn't exist. `@tloncorp/api` still installs from npm by default, but the dev container will link a local override from `tlon-apps/packages/api` so you can test API changes without publishing first.
283
+
284
+ **2. Edit `.env`:**
285
+
286
+ ```bash
287
+ # Required: LLM provider key
288
+ OPENROUTER_API_KEY=sk-or-...
289
+
290
+ # Bot ship (the ship running the plugin)
291
+ TLON_URL=http://host.docker.internal:8080
292
+ TLON_SHIP=~zod
293
+ TLON_CODE=lidlut-tabwed-pillex-ridrup
294
+
295
+ # Test user ship (sends DMs to the bot)
296
+ TEST_USER_URL=http://host.docker.internal:8081
297
+ TEST_USER_SHIP=~ten
298
+ TEST_USER_CODE=lapseg-nolmel-riswen-hopryc
299
+
300
+ # DM allowlist and owner
301
+ TLON_DM_ALLOWLIST=~ten
302
+ TLON_OWNER_SHIP=~ten
303
+
304
+ # Gateway port (match your running gateway)
305
+ OPENCLAW_GATEWAY_PORT=18789
306
+
307
+ # Optional: Brave Search API key (enables web_search + image_search tools)
308
+ # BRAVE_API_KEY=BSA...
309
+
310
+ # Optional: telemetry (explicit opt-in only)
311
+ # TLON_TELEMETRY_ENABLED=true
312
+ # TLON_TELEMETRY_API_KEY=phc_...
313
+ # TLON_TELEMETRY_HOST=https://us.i.posthog.com
314
+
315
+ # Optional: tlonbot GitHub token (if not using local clone)
316
+ # TLONBOT_TOKEN=ghp_...
317
+ ```
318
+
319
+ **3. Start your dev environment:**
320
+
321
+ ```bash
322
+ pnpm dev # or docker compose --env-file .env -f dev/docker-compose.yml up --build
323
+ ```
324
+
325
+ **4. Run tests against it:**
326
+
327
+ ```bash
328
+ pnpm test:integration:dev # All tests
329
+ pnpm test:integration:dev test/cases/dm.test.ts # Specific test
330
+ pnpm test:integration:dev --watch # Watch mode
331
+ ```
332
+
333
+ #### Manual Testing (`test:manual`)
334
+
335
+ Starts the full Docker environment (ships + gateway) without running vitest, so you can interact with the bot manually — send DMs from ~ten's Landscape, poke around, etc.
336
+
337
+ ```bash
338
+ pnpm test:manual
339
+ ```
340
+
341
+ This will:
342
+
343
+ - Start 3 fakezod ships and the OpenClaw gateway in Docker
344
+ - Wait for everything to be ready
345
+ - Print ship URLs, access codes, and gateway address
346
+ - Tail gateway logs (Ctrl+C to stop and tear down)
347
+
348
+ Ships are accessible via browser:
349
+
350
+ - **~zod** (bot): http://localhost:8080 — code: `lidlut-tabwed-pillex-ridrup`
351
+ - **~ten** (user): http://localhost:8081 — code: `lapseg-nolmel-riswen-hopryc`
352
+ - **~mug** (3rd party): http://localhost:8082 — code: `ravsut-bolryd-hapsum-pastul`
353
+
354
+ To tear down without attaching to logs:
355
+
356
+ ```bash
357
+ pnpm test:manual -- --stop
358
+ ```
359
+
360
+ **Verbose mode:** To see full debug output from the OpenClaw entrypoint (config dumps, prompt files, env vars):
361
+
362
+ ```bash
363
+ VERBOSE=1 pnpm test:manual
364
+ ```
365
+
366
+ #### Optional: Image Search & Brave API
367
+
368
+ To test the `image_search` tool and Brave-powered `web_search`:
369
+
370
+ 1. Get a [Brave Search API key](https://brave.com/search/api/)
371
+ 2. Add to `.env`: `BRAVE_API_KEY=BSA...`
372
+ 3. Clone [tlonbot](https://github.com/tloncorp/tlonbot) as a sibling directory:
373
+ ```bash
374
+ cd .. && gh repo clone tloncorp/tlonbot
375
+ ```
376
+
377
+ When `../tlonbot` exists, `docker-compose.local.yml` mounts it automatically, making the `image-search` plugin available. The entrypoint patches the config to load it if present.
378
+
379
+ Without these, `web_search` falls back to whatever provider is available, and `image_search` returns a "no API key" error — tests that don't depend on image search still pass.
171
380
 
172
381
  ## License
173
382