ape-claw 0.1.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 (114) hide show
  1. package/.cursor/skills/ape-claw/SKILL.md +322 -0
  2. package/LICENSE +21 -0
  3. package/README.md +826 -0
  4. package/allowlists/opensea-slug-overrides.json +13 -0
  5. package/allowlists/recommended.apechain.json +322 -0
  6. package/config/clawbots.example.json +3 -0
  7. package/config/policy.example.json +27 -0
  8. package/data/starter-pack-bundle.json +1 -0
  9. package/data/starter-pack.json +495 -0
  10. package/docs/ACP_BOUNTIES.md +108 -0
  11. package/docs/APECLAW_V2_ALPHA.md +206 -0
  12. package/docs/AUTONOMY_AND_SUBSTRATE.md +69 -0
  13. package/docs/CLAWBOTS_AND_INVITES.md +102 -0
  14. package/docs/CLI_GUIDE.md +124 -0
  15. package/docs/CONTRIBUTING.md +130 -0
  16. package/docs/DASHBOARD_GUIDE.md +108 -0
  17. package/docs/GLOBAL_BACKEND.md +145 -0
  18. package/docs/ONCHAIN_V2_GUIDE.md +140 -0
  19. package/docs/PRODUCT_OVERVIEW.md +127 -0
  20. package/docs/README.md +40 -0
  21. package/docs/SKILLCARDS_AND_IMPORTER.md +147 -0
  22. package/docs/STARTER_PACK.md +297 -0
  23. package/docs/SUPPORTED_NETWORKS.md +58 -0
  24. package/docs/TELEMETRY_AND_EVENTS.md +103 -0
  25. package/docs/THE_POD_RUNNER.md +198 -0
  26. package/docs/V1_WORKFLOWS.md +108 -0
  27. package/docs/V2_ONCHAIN_SKILLS.md +157 -0
  28. package/docs/WEB4_PLAN_STATUS.md +95 -0
  29. package/docs/WEB4_SWARM_MODEL.md +104 -0
  30. package/docs/archive/AUTONOMY_AND_SUBSTRATE.md +66 -0
  31. package/docs/archive/WEB4_PLAN_STATUS.md +93 -0
  32. package/docs/archive/WEB4_SWARM_MODEL.md +98 -0
  33. package/docs/developer/01-architecture.md +345 -0
  34. package/docs/developer/02-contracts.md +1034 -0
  35. package/docs/developer/03-writing-modules.md +513 -0
  36. package/docs/developer/04-skillcard-spec.md +336 -0
  37. package/docs/developer/05-backend-api.md +1079 -0
  38. package/docs/developer/06-telemetry.md +798 -0
  39. package/docs/developer/07-testing.md +546 -0
  40. package/docs/developer/08-contributing.md +211 -0
  41. package/docs/operator/01-quickstart.md +49 -0
  42. package/docs/operator/02-dashboard.md +174 -0
  43. package/docs/operator/03-cli-reference.md +818 -0
  44. package/docs/operator/04-skills-library.md +169 -0
  45. package/docs/operator/05-pod-operations.md +314 -0
  46. package/docs/operator/06-deployment.md +299 -0
  47. package/docs/operator/07-safety-and-policy.md +311 -0
  48. package/docs/operator/08-troubleshooting.md +457 -0
  49. package/docs/operator/09-env-reference.md +238 -0
  50. package/docs/social/STARTER_PACK_THREAD.md +209 -0
  51. package/package.json +77 -0
  52. package/skillcards/import-sources.json +93 -0
  53. package/skillcards/seed/acp-bounty-poll.v1.json +38 -0
  54. package/skillcards/seed/acp-bounty-post.v1.json +55 -0
  55. package/skillcards/seed/acp-browse.v1.json +41 -0
  56. package/skillcards/seed/acp-fulfill-and-route.v1.json +56 -0
  57. package/skillcards/seed/apeclaw-bridge-relay.v1.json +46 -0
  58. package/skillcards/seed/apeclaw-nft-autobuy.v1.json +60 -0
  59. package/skillcards/seed/apeclaw-receipt-recorder.v1.json +64 -0
  60. package/skillcards/seed/humanizer.v1.json +74 -0
  61. package/skillcards/seed/otherside-navigator.v1.json +116 -0
  62. package/skillcards/seed/stonkbrokers-launcher.v1.json +280 -0
  63. package/skillcards/seed/walkie-p2p.v1.json +66 -0
  64. package/src/cli/index.mjs +8 -0
  65. package/src/cli.mjs +1929 -0
  66. package/src/lib/bridge-relay.mjs +294 -0
  67. package/src/lib/clawbots.mjs +94 -0
  68. package/src/lib/io.mjs +36 -0
  69. package/src/lib/market.mjs +233 -0
  70. package/src/lib/nft-opensea.mjs +159 -0
  71. package/src/lib/paths.mjs +17 -0
  72. package/src/lib/pod-init.mjs +40 -0
  73. package/src/lib/policy.mjs +112 -0
  74. package/src/lib/rpc.mjs +49 -0
  75. package/src/lib/telemetry.mjs +92 -0
  76. package/src/lib/v2-onchain-abi.mjs +294 -0
  77. package/src/lib/v2-skillcard.mjs +27 -0
  78. package/src/server/index.mjs +169 -0
  79. package/src/server/logger.mjs +21 -0
  80. package/src/server/middleware/auth.mjs +90 -0
  81. package/src/server/middleware/body-limit.mjs +35 -0
  82. package/src/server/middleware/cors.mjs +33 -0
  83. package/src/server/middleware/rate-limit.mjs +44 -0
  84. package/src/server/routes/chat.mjs +178 -0
  85. package/src/server/routes/clawbots.mjs +182 -0
  86. package/src/server/routes/events.mjs +95 -0
  87. package/src/server/routes/health.mjs +72 -0
  88. package/src/server/routes/pod.mjs +64 -0
  89. package/src/server/routes/quotes.mjs +161 -0
  90. package/src/server/routes/skills.mjs +239 -0
  91. package/src/server/routes/static.mjs +161 -0
  92. package/src/server/routes/v2.mjs +48 -0
  93. package/src/server/sse.mjs +73 -0
  94. package/src/server/storage/file-backend.mjs +295 -0
  95. package/src/server/storage/index.mjs +37 -0
  96. package/src/server/storage/sqlite-backend.mjs +380 -0
  97. package/src/telemetry-server.mjs +1604 -0
  98. package/ui/css/dashboard.css +792 -0
  99. package/ui/css/skills.css +689 -0
  100. package/ui/docs.html +840 -0
  101. package/ui/favicon-180.png +0 -0
  102. package/ui/favicon-192.png +0 -0
  103. package/ui/favicon-32.png +0 -0
  104. package/ui/favicon-lobster.png +0 -0
  105. package/ui/favicon.svg +10 -0
  106. package/ui/index.html +2957 -0
  107. package/ui/js/dashboard.js +1766 -0
  108. package/ui/js/skills.js +1621 -0
  109. package/ui/pod.html +909 -0
  110. package/ui/shared/motion.css +286 -0
  111. package/ui/shared/motion.js +170 -0
  112. package/ui/shared/sidebar-nav.css +379 -0
  113. package/ui/shared/sidebar-nav.js +137 -0
  114. package/ui/skills.html +2879 -0
@@ -0,0 +1,798 @@
1
+ # Telemetry System
2
+
3
+ ## Overview
4
+
5
+ The ApeClaw telemetry system provides event tracking and real-time monitoring for agent actions, skill executions, and system events. Events are logged locally and can be streamed to a remote telemetry server via Server-Sent Events (SSE).
6
+
7
+ ## Event Envelope Schema
8
+
9
+ All telemetry events follow a consistent envelope structure:
10
+
11
+ ```typescript
12
+ interface TelemetryEvent {
13
+ v: number; // Schema version (currently 1)
14
+ ts: string; // ISO 8601 timestamp
15
+ eventType: string; // Event type identifier
16
+ agentId: string; // Agent identifier
17
+ sessionId: string; // Session identifier
18
+ traceId: string; // Trace identifier for request tracking
19
+ command: string; // CLI command that triggered the event
20
+ dryRun: boolean; // Whether this was a dry run
21
+ chainId: number; // Chain ID (default: 33139 for ApeChain)
22
+ payload: Record<string, any>; // Event-specific input data
23
+ result: Record<string, any>; // Event-specific result data
24
+ ok: boolean; // Whether the operation succeeded
25
+ error: string | null; // Error message if ok=false
26
+ source?: string; // Optional source identifier (e.g., "cli")
27
+ }
28
+ ```
29
+
30
+ ### Field Descriptions
31
+
32
+ #### `v` (required)
33
+ - **Type**: `number`
34
+ - **Description**: Schema version for the event envelope
35
+ - **Current Value**: `1`
36
+
37
+ #### `ts` (required)
38
+ - **Type**: `string`
39
+ - **Description**: ISO 8601 timestamp of when the event occurred
40
+ - **Format**: `"2026-02-18T12:00:00.000Z"`
41
+ - **Generated**: Automatically set to current time if not provided
42
+
43
+ #### `eventType` (required)
44
+ - **Type**: `string`
45
+ - **Description**: Event type identifier (see Event Types section)
46
+ - **Examples**: `"nft.buy.confirmed"`, `"bridge.execute.confirmed"`, `"v2.skill.minted"`
47
+
48
+ #### `agentId` (required)
49
+ - **Type**: `string`
50
+ - **Description**: Identifier of the agent that generated the event
51
+ - **Default**: `"local-cli"` (if not provided)
52
+ - **Examples**: `"agent-123"`, `"local-cli"`
53
+
54
+ #### `sessionId` (required)
55
+ - **Type**: `string`
56
+ - **Description**: Session identifier for grouping related events
57
+ - **Default**: `"local-session"` (if not provided)
58
+ - **Examples**: `"session-123"`, `"local-session"`
59
+
60
+ #### `traceId` (required)
61
+ - **Type**: `string`
62
+ - **Description**: Unique trace identifier for tracking a request across multiple events
63
+ - **Generated**: Random ID if not provided (format: `trace_${timestamp}_${random}`)
64
+ - **Examples**: `"trace_1234567890"`, `"trace_1234567890_abc123"`
65
+
66
+ #### `command` (required)
67
+ - **Type**: `string`
68
+ - **Description**: CLI command that triggered the event
69
+ - **Examples**: `"ape-claw nft buy"`, `"ape-claw bridge execute"`
70
+
71
+ #### `dryRun` (required)
72
+ - **Type**: `boolean`
73
+ - **Description**: Whether this was a dry run (no actual execution)
74
+ - **Default**: `true`
75
+
76
+ #### `chainId` (required)
77
+ - **Type**: `number`
78
+ - **Description**: Blockchain chain ID
79
+ - **Default**: `33139` (ApeChain)
80
+
81
+ #### `payload` (required)
82
+ - **Type**: `object`
83
+ - **Description**: Event-specific input/context data
84
+ - **Default**: `{}`
85
+ - **Structure**: Varies by event type
86
+
87
+ #### `result` (required)
88
+ - **Type**: `object`
89
+ - **Description**: Event-specific result/output data
90
+ - **Default**: `{}`
91
+ - **Structure**: Varies by event type
92
+
93
+ #### `ok` (required)
94
+ - **Type**: `boolean`
95
+ - **Description**: Whether the operation succeeded
96
+ - **Default**: `true`
97
+
98
+ #### `error` (optional)
99
+ - **Type**: `string | null`
100
+ - **Description**: Error message if the operation failed
101
+ - **Default**: `null`
102
+
103
+ #### `source` (optional)
104
+ - **Type**: `string`
105
+ - **Description**: Source identifier (e.g., `"cli"`, `"backend"`)
106
+ - **Default**: Not set
107
+
108
+ ## SSE Wire Format
109
+
110
+ Events are streamed via Server-Sent Events (SSE) using the following format:
111
+
112
+ ```
113
+ data: <JSON_STRING>
114
+
115
+ data: <JSON_STRING>
116
+
117
+ ```
118
+
119
+ Each event is sent as a single line starting with `data: ` followed by the JSON-serialized event object, followed by two newlines (`\n\n`).
120
+
121
+ **Example:**
122
+ ```
123
+ data: {"v":1,"ts":"2026-02-18T12:00:00.000Z","eventType":"nft.buy.confirmed","agentId":"agent-123","sessionId":"session-123","traceId":"trace-123","command":"ape-claw nft buy","dryRun":false,"chainId":33139,"payload":{"quoteId":"quote-123"},"result":{"txHash":"0x..."},"ok":true,"error":null}
124
+
125
+ data: {"v":1,"ts":"2026-02-18T12:00:01.000Z","eventType":"bridge.execute.confirmed","agentId":"agent-123","sessionId":"session-123","traceId":"trace-456","command":"ape-claw bridge execute","dryRun":false,"chainId":33139,"payload":{"requestId":"req-123"},"result":{"txHash":"0x..."},"ok":true,"error":null}
126
+
127
+ ```
128
+
129
+ ## Event Types
130
+
131
+ ### Policy Events
132
+
133
+ #### `policy.blocked`
134
+ Operation was blocked by policy enforcement.
135
+
136
+ **Payload:**
137
+ ```json
138
+ {
139
+ "command": "ape-claw nft buy",
140
+ "reason": "Collection not on allowlist"
141
+ }
142
+ ```
143
+
144
+ **Result:**
145
+ ```json
146
+ {
147
+ "blocked": true,
148
+ "reason": "Collection not on allowlist"
149
+ }
150
+ ```
151
+
152
+ ---
153
+
154
+ ### Skill Management
155
+
156
+ #### `skill.install.ran`
157
+ Skill installation command executed.
158
+
159
+ **Result:**
160
+ ```json
161
+ {
162
+ "slug": "my-skill",
163
+ "installed": true
164
+ }
165
+ ```
166
+
167
+ ---
168
+
169
+ ### Clawbot Management
170
+
171
+ #### `clawbot.registered`
172
+ A new clawbot was registered.
173
+
174
+ **Result:**
175
+ ```json
176
+ {
177
+ "agentId": "agent-123",
178
+ "name": "My Agent",
179
+ "remote": false
180
+ }
181
+ ```
182
+
183
+ #### `clawbot.list.read`
184
+ Clawbot list was read.
185
+
186
+ **Result:**
187
+ ```json
188
+ {
189
+ "count": 5
190
+ }
191
+ ```
192
+
193
+ ---
194
+
195
+ ### Authentication
196
+
197
+ #### `auth.saved`
198
+ Authentication credentials were saved.
199
+
200
+ **Result:**
201
+ ```json
202
+ {
203
+ "path": "/path/to/.ape-claw/auth.json"
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ### System Commands
210
+
211
+ #### `doctor.ran`
212
+ System diagnostic command executed.
213
+
214
+ **Result:**
215
+ ```json
216
+ {
217
+ "checks": { /* diagnostic results */ }
218
+ }
219
+ ```
220
+
221
+ #### `quickstart.ran`
222
+ Quickstart command executed.
223
+
224
+ **Result:**
225
+ ```json
226
+ {
227
+ "completed": true
228
+ }
229
+ ```
230
+
231
+ ---
232
+
233
+ ### Chain Information
234
+
235
+ #### `chain.info.read`
236
+ Chain information was read.
237
+
238
+ **Result:**
239
+ ```json
240
+ {
241
+ "chainId": 33139,
242
+ "blockNumber": 12345
243
+ }
244
+ ```
245
+
246
+ ---
247
+
248
+ ### Market Data
249
+
250
+ #### `market.collections.read`
251
+ NFT collections were read from market data.
252
+
253
+ **Payload:**
254
+ ```json
255
+ {
256
+ "query": "bored ape"
257
+ }
258
+ ```
259
+
260
+ **Result:**
261
+ ```json
262
+ {
263
+ "collections": [ /* ... */ ]
264
+ }
265
+ ```
266
+
267
+ #### `market.listings.read`
268
+ NFT listings were read.
269
+
270
+ **Payload:**
271
+ ```json
272
+ {
273
+ "collection": "bored-ape-yacht-club",
274
+ "limit": 50
275
+ }
276
+ ```
277
+
278
+ **Result:**
279
+ ```json
280
+ {
281
+ "listings": [ /* ... */ ]
282
+ }
283
+ ```
284
+
285
+ #### `market.listings.failed`
286
+ Failed to read NFT listings.
287
+
288
+ **Result:**
289
+ ```json
290
+ {
291
+ "error": "API error"
292
+ }
293
+ ```
294
+
295
+ ---
296
+
297
+ ### NFT Operations
298
+
299
+ #### `nft.quote.created`
300
+ NFT quote was created.
301
+
302
+ **Payload:**
303
+ ```json
304
+ {
305
+ "collection": "bored-ape-yacht-club",
306
+ "tokenId": "1234"
307
+ }
308
+ ```
309
+
310
+ **Result:**
311
+ ```json
312
+ {
313
+ "quoteId": "quote-123",
314
+ "priceApe": 10.5
315
+ }
316
+ ```
317
+
318
+ #### `nft.simulation.passed`
319
+ NFT buy simulation passed.
320
+
321
+ **Payload:**
322
+ ```json
323
+ {
324
+ "quoteId": "quote-123"
325
+ }
326
+ ```
327
+
328
+ **Result:**
329
+ ```json
330
+ {
331
+ "simulated": true
332
+ }
333
+ ```
334
+
335
+ #### `nft.simulation.failed`
336
+ NFT buy simulation failed.
337
+
338
+ **Payload:**
339
+ ```json
340
+ {
341
+ "quoteId": "quote-123"
342
+ }
343
+ ```
344
+
345
+ **Result:**
346
+ ```json
347
+ {
348
+ "simulated": false,
349
+ "reason": "Insufficient balance"
350
+ }
351
+ ```
352
+
353
+ #### `nft.buy.dry_run`
354
+ NFT buy dry run executed.
355
+
356
+ **Payload:**
357
+ ```json
358
+ {
359
+ "quoteId": "quote-123"
360
+ }
361
+ ```
362
+
363
+ **Result:**
364
+ ```json
365
+ {
366
+ "wouldBuy": true
367
+ }
368
+ ```
369
+
370
+ #### `nft.buy.retry`
371
+ NFT buy retry attempted.
372
+
373
+ **Payload:**
374
+ ```json
375
+ {
376
+ "quoteId": "quote-123",
377
+ "attempt": 2
378
+ }
379
+ ```
380
+
381
+ **Result:**
382
+ ```json
383
+ {
384
+ "retried": true
385
+ }
386
+ ```
387
+
388
+ #### `nft.buy.confirmed`
389
+ NFT buy transaction confirmed.
390
+
391
+ **Payload:**
392
+ ```json
393
+ {
394
+ "quoteId": "quote-123"
395
+ }
396
+ ```
397
+
398
+ **Result:**
399
+ ```json
400
+ {
401
+ "txHash": "0x...",
402
+ "blockNumber": 12345
403
+ }
404
+ ```
405
+
406
+ #### `nft.autobuy.planned`
407
+ NFT autobuy plan created.
408
+
409
+ **Payload:**
410
+ ```json
411
+ {
412
+ "count": 5,
413
+ "minPrice": 1,
414
+ "maxPrice": 10
415
+ }
416
+ ```
417
+
418
+ **Result:**
419
+ ```json
420
+ {
421
+ "planned": [ /* quotes */ ],
422
+ "selectedCount": 5
423
+ }
424
+ ```
425
+
426
+ #### `nft.autobuy.executed`
427
+ NFT autobuy executed successfully.
428
+
429
+ **Payload:**
430
+ ```json
431
+ {
432
+ "count": 5
433
+ }
434
+ ```
435
+
436
+ **Result:**
437
+ ```json
438
+ {
439
+ "executed": 5,
440
+ "txHashes": [ "0x...", "0x..." ]
441
+ }
442
+ ```
443
+
444
+ #### `nft.autobuy.partial`
445
+ NFT autobuy partially executed (some failures).
446
+
447
+ **Payload:**
448
+ ```json
449
+ {
450
+ "count": 5
451
+ }
452
+ ```
453
+
454
+ **Result:**
455
+ ```json
456
+ {
457
+ "executed": 3,
458
+ "failed": 2,
459
+ "txHashes": [ "0x...", "0x..." ],
460
+ "errors": [ /* ... */ ]
461
+ }
462
+ ```
463
+
464
+ ---
465
+
466
+ ### Bridge Operations
467
+
468
+ #### `bridge.quote.created`
469
+ Bridge quote was created.
470
+
471
+ **Payload:**
472
+ ```json
473
+ {
474
+ "amount": "1000000000000000000",
475
+ "fromChain": 1,
476
+ "toChain": 33139
477
+ }
478
+ ```
479
+
480
+ **Result:**
481
+ ```json
482
+ {
483
+ "requestId": "req-123",
484
+ "quote": { /* ... */ }
485
+ }
486
+ ```
487
+
488
+ #### `bridge.execute.dry_run`
489
+ Bridge execution dry run.
490
+
491
+ **Payload:**
492
+ ```json
493
+ {
494
+ "requestId": "req-123"
495
+ }
496
+ ```
497
+
498
+ **Result:**
499
+ ```json
500
+ {
501
+ "wouldExecute": true
502
+ }
503
+ ```
504
+
505
+ #### `bridge.execute.confirmed`
506
+ Bridge execution transaction confirmed.
507
+
508
+ **Payload:**
509
+ ```json
510
+ {
511
+ "requestId": "req-123"
512
+ }
513
+ ```
514
+
515
+ **Result:**
516
+ ```json
517
+ {
518
+ "txHash": "0x...",
519
+ "requestId": "req-123"
520
+ }
521
+ ```
522
+
523
+ #### `bridge.status.read`
524
+ Bridge status was read.
525
+
526
+ **Payload:**
527
+ ```json
528
+ {
529
+ "requestId": "req-123"
530
+ }
531
+ ```
532
+
533
+ **Result:**
534
+ ```json
535
+ {
536
+ "status": "completed",
537
+ "requestId": "req-123"
538
+ }
539
+ ```
540
+
541
+ ---
542
+
543
+ ### Allowlist
544
+
545
+ #### `allowlist.audit.ran`
546
+ Allowlist audit command executed.
547
+
548
+ **Result:**
549
+ ```json
550
+ {
551
+ "audited": true,
552
+ "issues": [ /* ... */ ]
553
+ }
554
+ ```
555
+
556
+ ---
557
+
558
+ ### V2 On-Chain Operations
559
+
560
+ #### `v2.skill.minted`
561
+ V2 skill was minted on-chain.
562
+
563
+ **Result:**
564
+ ```json
565
+ {
566
+ "skillId": 42,
567
+ "txHash": "0x...",
568
+ "contentHash": "0x..."
569
+ }
570
+ ```
571
+
572
+ #### `v2.skill.version.published`
573
+ V2 skill version was published on-chain.
574
+
575
+ **Result:**
576
+ ```json
577
+ {
578
+ "skillId": 42,
579
+ "versionHash": "0x...",
580
+ "txHash": "0x..."
581
+ }
582
+ ```
583
+
584
+ #### `v2.intent.created`
585
+ V2 intent was created on-chain.
586
+
587
+ **Result:**
588
+ ```json
589
+ {
590
+ "intentId": 123,
591
+ "txHash": "0x...",
592
+ "traceId": "trace-123"
593
+ }
594
+ ```
595
+
596
+ #### `v2.intent.cancelled`
597
+ V2 intent was cancelled on-chain.
598
+
599
+ **Result:**
600
+ ```json
601
+ {
602
+ "intentId": 123,
603
+ "txHash": "0x..."
604
+ }
605
+ ```
606
+
607
+ #### `v2.receipt.recorded`
608
+ V2 receipt was recorded on-chain.
609
+
610
+ **Result:**
611
+ ```json
612
+ {
613
+ "traceId": "trace-123",
614
+ "traceIdHash": "0x...",
615
+ "txHash": "0x..."
616
+ }
617
+ ```
618
+
619
+ #### `v2.receipt.read`
620
+ V2 receipt was read from on-chain registry.
621
+
622
+ **Result:**
623
+ ```json
624
+ {
625
+ "traceId": "trace-123",
626
+ "traceIdHash": "0x...",
627
+ "isRecorded": true
628
+ }
629
+ ```
630
+
631
+ #### `v2.vault.release`
632
+ V2 vault release executed.
633
+
634
+ **Result:**
635
+ ```json
636
+ {
637
+ "tx": "0x...",
638
+ "member": "0x..."
639
+ }
640
+ ```
641
+
642
+ #### `v2.agent.execute`
643
+ V2 agent execution on-chain.
644
+
645
+ **Result:**
646
+ ```json
647
+ {
648
+ "tx": "0x...",
649
+ "module": "0x...",
650
+ "traceId": "trace-123"
651
+ }
652
+ ```
653
+
654
+ ---
655
+
656
+ ### Pod Workspace
657
+
658
+ #### `pod.init.completed`
659
+ Pod workspace initialization completed.
660
+
661
+ **Result:**
662
+ ```json
663
+ {
664
+ "workspacePath": "/path/to/pod-workspace",
665
+ "initialized": true
666
+ }
667
+ ```
668
+
669
+ ---
670
+
671
+ ## Subscribing to Events
672
+
673
+ ### Local SSE Stream
674
+
675
+ Connect to the local telemetry server SSE stream:
676
+
677
+ ```javascript
678
+ const eventSource = new EventSource('http://localhost:8787/events');
679
+
680
+ eventSource.onmessage = (event) => {
681
+ const data = JSON.parse(event.data);
682
+ console.log('Event:', data.eventType, data);
683
+ };
684
+
685
+ eventSource.onerror = (error) => {
686
+ console.error('SSE error:', error);
687
+ };
688
+ ```
689
+
690
+ ### Remote Telemetry Server
691
+
692
+ If `APE_CLAW_TELEMETRY_URL` is set, events are automatically sent to the remote server:
693
+
694
+ ```bash
695
+ export APE_CLAW_TELEMETRY_URL="https://apeclaw.ai"
696
+ export APE_CLAW_AGENT_ID="agent-123"
697
+ export APE_CLAW_AGENT_TOKEN="token_..."
698
+ ```
699
+
700
+ Events are sent via POST to `/api/events` with authentication headers.
701
+
702
+ ### Backlog API
703
+
704
+ Get the last 300 events from the backlog:
705
+
706
+ ```bash
707
+ curl http://localhost:8787/events/backlog
708
+ ```
709
+
710
+ Response:
711
+ ```json
712
+ {
713
+ "events": [
714
+ { /* event 1 */ },
715
+ { /* event 2 */ },
716
+ ...
717
+ ]
718
+ }
719
+ ```
720
+
721
+ ## Emitting Events
722
+
723
+ ### From CLI
724
+
725
+ Use the `emitEvent` function from `src/lib/telemetry.mjs`:
726
+
727
+ ```javascript
728
+ import { emitEvent } from './lib/telemetry.mjs';
729
+
730
+ emitEvent({
731
+ eventType: 'nft.buy.confirmed',
732
+ agentId: 'agent-123',
733
+ sessionId: 'session-123',
734
+ traceId: 'trace-123',
735
+ command: 'ape-claw nft buy',
736
+ dryRun: false,
737
+ chainId: 33139,
738
+ payload: { quoteId: 'quote-123' },
739
+ result: { txHash: '0x...' },
740
+ ok: true,
741
+ error: null
742
+ });
743
+ ```
744
+
745
+ ### From Backend
746
+
747
+ Events can be submitted via POST to `/api/events`:
748
+
749
+ ```bash
750
+ curl -X POST http://localhost:8787/api/events \
751
+ -H "Content-Type: application/json" \
752
+ -H "x-agent-id: agent-123" \
753
+ -H "x-agent-token: token_..." \
754
+ -d '{
755
+ "eventType": "nft.buy.confirmed",
756
+ "sessionId": "session-123",
757
+ "traceId": "trace-123",
758
+ "command": "ape-claw nft buy",
759
+ "dryRun": false,
760
+ "chainId": 33139,
761
+ "payload": { "quoteId": "quote-123" },
762
+ "result": { "txHash": "0x..." },
763
+ "ok": true
764
+ }'
765
+ ```
766
+
767
+ ### Environment Variables
768
+
769
+ - `APE_CLAW_TELEMETRY_URL`: Remote telemetry server URL (optional)
770
+ - `APE_CLAW_TELEMETRY_REMOTE_ONLY`: If set to `1`, only send to remote (skip local file)
771
+ - `APE_CLAW_AGENT_ID`: Agent ID for remote telemetry
772
+ - `APE_CLAW_AGENT_TOKEN`: Agent token for remote telemetry
773
+
774
+ ## Event Storage
775
+
776
+ ### Local Storage
777
+
778
+ Events are stored in a JSONL (JSON Lines) file at `state/events.jsonl`:
779
+
780
+ ```
781
+ {"v":1,"ts":"2026-02-18T12:00:00.000Z","eventType":"nft.buy.confirmed",...}
782
+ {"v":1,"ts":"2026-02-18T12:00:01.000Z","eventType":"bridge.execute.confirmed",...}
783
+ ```
784
+
785
+ Each line is a complete JSON event object.
786
+
787
+ ### File Watching
788
+
789
+ The telemetry server watches `state/events.jsonl` for new lines and broadcasts them to all connected SSE clients in real-time.
790
+
791
+ ## Best Practices
792
+
793
+ 1. **Always set `traceId`**: Use consistent trace IDs to track related events across a request lifecycle
794
+ 2. **Include context in `payload`**: Add relevant input data for debugging
795
+ 3. **Set `ok` correctly**: Use `ok: false` and `error` message for failures
796
+ 4. **Use descriptive `eventType`**: Follow the dot-separated naming convention (`category.action.status`)
797
+ 5. **Include `command`**: Always include the CLI command that triggered the event
798
+ 6. **Set `dryRun` accurately**: Distinguish between dry runs and actual executions