loudmouth-ai 0.1.0 → 0.2.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 (593) hide show
  1. package/README.md +148 -77
  2. package/dist/build-info.json +3 -3
  3. package/extensions/package.json +6 -0
  4. package/package.json +1 -1
  5. package/skills/autopilot/SKILL.md +179 -0
  6. package/skills/goals/SKILL.md +189 -0
  7. package/skills/wordpress/SKILL.md +232 -0
  8. package/extensions/bluebubbles/clawdbot.plugin.json +0 -11
  9. package/extensions/bluebubbles/index.ts +0 -20
  10. package/extensions/bluebubbles/package.json +0 -33
  11. package/extensions/bluebubbles/src/accounts.ts +0 -80
  12. package/extensions/bluebubbles/src/actions.test.ts +0 -651
  13. package/extensions/bluebubbles/src/actions.ts +0 -403
  14. package/extensions/bluebubbles/src/attachments.test.ts +0 -346
  15. package/extensions/bluebubbles/src/attachments.ts +0 -282
  16. package/extensions/bluebubbles/src/channel.ts +0 -399
  17. package/extensions/bluebubbles/src/chat.test.ts +0 -462
  18. package/extensions/bluebubbles/src/chat.ts +0 -354
  19. package/extensions/bluebubbles/src/config-schema.ts +0 -51
  20. package/extensions/bluebubbles/src/media-send.ts +0 -168
  21. package/extensions/bluebubbles/src/monitor.test.ts +0 -2140
  22. package/extensions/bluebubbles/src/monitor.ts +0 -2101
  23. package/extensions/bluebubbles/src/onboarding.ts +0 -340
  24. package/extensions/bluebubbles/src/probe.ts +0 -127
  25. package/extensions/bluebubbles/src/reactions.test.ts +0 -393
  26. package/extensions/bluebubbles/src/reactions.ts +0 -183
  27. package/extensions/bluebubbles/src/runtime.ts +0 -14
  28. package/extensions/bluebubbles/src/send.test.ts +0 -809
  29. package/extensions/bluebubbles/src/send.ts +0 -418
  30. package/extensions/bluebubbles/src/targets.test.ts +0 -184
  31. package/extensions/bluebubbles/src/targets.ts +0 -323
  32. package/extensions/bluebubbles/src/types.ts +0 -127
  33. package/extensions/copilot-proxy/README.md +0 -24
  34. package/extensions/copilot-proxy/clawdbot.plugin.json +0 -11
  35. package/extensions/copilot-proxy/index.ts +0 -142
  36. package/extensions/copilot-proxy/package.json +0 -11
  37. package/extensions/google-antigravity-auth/README.md +0 -24
  38. package/extensions/google-antigravity-auth/clawdbot.plugin.json +0 -11
  39. package/extensions/google-antigravity-auth/index.ts +0 -437
  40. package/extensions/google-antigravity-auth/package.json +0 -11
  41. package/extensions/google-gemini-cli-auth/README.md +0 -35
  42. package/extensions/google-gemini-cli-auth/clawdbot.plugin.json +0 -11
  43. package/extensions/google-gemini-cli-auth/index.ts +0 -91
  44. package/extensions/google-gemini-cli-auth/oauth.test.ts +0 -228
  45. package/extensions/google-gemini-cli-auth/oauth.ts +0 -580
  46. package/extensions/google-gemini-cli-auth/package.json +0 -11
  47. package/extensions/googlechat/clawdbot.plugin.json +0 -11
  48. package/extensions/googlechat/index.ts +0 -20
  49. package/extensions/googlechat/package.json +0 -39
  50. package/extensions/googlechat/src/accounts.ts +0 -133
  51. package/extensions/googlechat/src/actions.ts +0 -162
  52. package/extensions/googlechat/src/api.test.ts +0 -62
  53. package/extensions/googlechat/src/api.ts +0 -259
  54. package/extensions/googlechat/src/auth.ts +0 -113
  55. package/extensions/googlechat/src/channel.ts +0 -580
  56. package/extensions/googlechat/src/monitor.test.ts +0 -27
  57. package/extensions/googlechat/src/monitor.ts +0 -900
  58. package/extensions/googlechat/src/onboarding.ts +0 -278
  59. package/extensions/googlechat/src/runtime.ts +0 -14
  60. package/extensions/googlechat/src/targets.test.ts +0 -35
  61. package/extensions/googlechat/src/targets.ts +0 -55
  62. package/extensions/googlechat/src/types.config.ts +0 -3
  63. package/extensions/googlechat/src/types.ts +0 -73
  64. package/extensions/imessage/clawdbot.plugin.json +0 -11
  65. package/extensions/imessage/index.ts +0 -18
  66. package/extensions/imessage/package.json +0 -11
  67. package/extensions/imessage/src/channel.ts +0 -294
  68. package/extensions/imessage/src/runtime.ts +0 -14
  69. package/extensions/line/clawdbot.plugin.json +0 -11
  70. package/extensions/line/index.ts +0 -20
  71. package/extensions/line/package.json +0 -29
  72. package/extensions/line/src/card-command.ts +0 -338
  73. package/extensions/line/src/channel.logout.test.ts +0 -96
  74. package/extensions/line/src/channel.sendPayload.test.ts +0 -308
  75. package/extensions/line/src/channel.ts +0 -773
  76. package/extensions/line/src/runtime.ts +0 -14
  77. package/extensions/matrix/CHANGELOG.md +0 -54
  78. package/extensions/matrix/clawdbot.plugin.json +0 -11
  79. package/extensions/matrix/index.ts +0 -18
  80. package/extensions/matrix/package.json +0 -36
  81. package/extensions/matrix/src/actions.ts +0 -185
  82. package/extensions/matrix/src/channel.directory.test.ts +0 -56
  83. package/extensions/matrix/src/channel.ts +0 -417
  84. package/extensions/matrix/src/config-schema.ts +0 -62
  85. package/extensions/matrix/src/directory-live.ts +0 -175
  86. package/extensions/matrix/src/group-mentions.ts +0 -61
  87. package/extensions/matrix/src/matrix/accounts.test.ts +0 -83
  88. package/extensions/matrix/src/matrix/accounts.ts +0 -63
  89. package/extensions/matrix/src/matrix/actions/client.ts +0 -53
  90. package/extensions/matrix/src/matrix/actions/messages.ts +0 -120
  91. package/extensions/matrix/src/matrix/actions/pins.ts +0 -70
  92. package/extensions/matrix/src/matrix/actions/reactions.ts +0 -84
  93. package/extensions/matrix/src/matrix/actions/room.ts +0 -88
  94. package/extensions/matrix/src/matrix/actions/summary.ts +0 -77
  95. package/extensions/matrix/src/matrix/actions/types.ts +0 -84
  96. package/extensions/matrix/src/matrix/actions.ts +0 -15
  97. package/extensions/matrix/src/matrix/active-client.ts +0 -11
  98. package/extensions/matrix/src/matrix/client/config.ts +0 -165
  99. package/extensions/matrix/src/matrix/client/create-client.ts +0 -127
  100. package/extensions/matrix/src/matrix/client/logging.ts +0 -35
  101. package/extensions/matrix/src/matrix/client/runtime.ts +0 -4
  102. package/extensions/matrix/src/matrix/client/shared.ts +0 -169
  103. package/extensions/matrix/src/matrix/client/storage.ts +0 -131
  104. package/extensions/matrix/src/matrix/client/types.ts +0 -34
  105. package/extensions/matrix/src/matrix/client.test.ts +0 -57
  106. package/extensions/matrix/src/matrix/client.ts +0 -9
  107. package/extensions/matrix/src/matrix/credentials.ts +0 -103
  108. package/extensions/matrix/src/matrix/deps.ts +0 -57
  109. package/extensions/matrix/src/matrix/format.test.ts +0 -34
  110. package/extensions/matrix/src/matrix/format.ts +0 -22
  111. package/extensions/matrix/src/matrix/index.ts +0 -11
  112. package/extensions/matrix/src/matrix/monitor/allowlist.ts +0 -58
  113. package/extensions/matrix/src/matrix/monitor/auto-join.ts +0 -68
  114. package/extensions/matrix/src/matrix/monitor/direct.ts +0 -105
  115. package/extensions/matrix/src/matrix/monitor/events.ts +0 -103
  116. package/extensions/matrix/src/matrix/monitor/handler.ts +0 -645
  117. package/extensions/matrix/src/matrix/monitor/index.ts +0 -279
  118. package/extensions/matrix/src/matrix/monitor/location.ts +0 -83
  119. package/extensions/matrix/src/matrix/monitor/media.test.ts +0 -103
  120. package/extensions/matrix/src/matrix/monitor/media.ts +0 -113
  121. package/extensions/matrix/src/matrix/monitor/mentions.ts +0 -31
  122. package/extensions/matrix/src/matrix/monitor/replies.ts +0 -96
  123. package/extensions/matrix/src/matrix/monitor/room-info.ts +0 -58
  124. package/extensions/matrix/src/matrix/monitor/rooms.ts +0 -43
  125. package/extensions/matrix/src/matrix/monitor/threads.ts +0 -64
  126. package/extensions/matrix/src/matrix/monitor/types.ts +0 -39
  127. package/extensions/matrix/src/matrix/poll-types.test.ts +0 -22
  128. package/extensions/matrix/src/matrix/poll-types.ts +0 -157
  129. package/extensions/matrix/src/matrix/probe.ts +0 -70
  130. package/extensions/matrix/src/matrix/send/client.ts +0 -63
  131. package/extensions/matrix/src/matrix/send/formatting.ts +0 -92
  132. package/extensions/matrix/src/matrix/send/media.ts +0 -220
  133. package/extensions/matrix/src/matrix/send/targets.test.ts +0 -102
  134. package/extensions/matrix/src/matrix/send/targets.ts +0 -144
  135. package/extensions/matrix/src/matrix/send/types.ts +0 -109
  136. package/extensions/matrix/src/matrix/send.test.ts +0 -172
  137. package/extensions/matrix/src/matrix/send.ts +0 -255
  138. package/extensions/matrix/src/onboarding.ts +0 -432
  139. package/extensions/matrix/src/outbound.ts +0 -53
  140. package/extensions/matrix/src/resolve-targets.ts +0 -89
  141. package/extensions/matrix/src/runtime.ts +0 -14
  142. package/extensions/matrix/src/tool-actions.ts +0 -160
  143. package/extensions/matrix/src/types.ts +0 -95
  144. package/extensions/mattermost/clawdbot.plugin.json +0 -11
  145. package/extensions/mattermost/index.ts +0 -18
  146. package/extensions/mattermost/package.json +0 -25
  147. package/extensions/mattermost/src/channel.test.ts +0 -43
  148. package/extensions/mattermost/src/channel.ts +0 -339
  149. package/extensions/mattermost/src/config-schema.ts +0 -56
  150. package/extensions/mattermost/src/group-mentions.ts +0 -14
  151. package/extensions/mattermost/src/mattermost/accounts.ts +0 -115
  152. package/extensions/mattermost/src/mattermost/client.ts +0 -208
  153. package/extensions/mattermost/src/mattermost/index.ts +0 -9
  154. package/extensions/mattermost/src/mattermost/monitor-helpers.ts +0 -150
  155. package/extensions/mattermost/src/mattermost/monitor.ts +0 -921
  156. package/extensions/mattermost/src/mattermost/probe.ts +0 -70
  157. package/extensions/mattermost/src/mattermost/send.ts +0 -217
  158. package/extensions/mattermost/src/normalize.ts +0 -38
  159. package/extensions/mattermost/src/onboarding-helpers.ts +0 -42
  160. package/extensions/mattermost/src/onboarding.ts +0 -187
  161. package/extensions/mattermost/src/runtime.ts +0 -14
  162. package/extensions/mattermost/src/types.ts +0 -50
  163. package/extensions/msteams/CHANGELOG.md +0 -51
  164. package/extensions/msteams/clawdbot.plugin.json +0 -11
  165. package/extensions/msteams/index.ts +0 -18
  166. package/extensions/msteams/package.json +0 -36
  167. package/extensions/msteams/src/attachments/download.ts +0 -206
  168. package/extensions/msteams/src/attachments/graph.ts +0 -319
  169. package/extensions/msteams/src/attachments/html.ts +0 -76
  170. package/extensions/msteams/src/attachments/payload.ts +0 -22
  171. package/extensions/msteams/src/attachments/shared.ts +0 -235
  172. package/extensions/msteams/src/attachments/types.ts +0 -37
  173. package/extensions/msteams/src/attachments.test.ts +0 -424
  174. package/extensions/msteams/src/attachments.ts +0 -18
  175. package/extensions/msteams/src/channel.directory.test.ts +0 -46
  176. package/extensions/msteams/src/channel.ts +0 -436
  177. package/extensions/msteams/src/conversation-store-fs.test.ts +0 -88
  178. package/extensions/msteams/src/conversation-store-fs.ts +0 -155
  179. package/extensions/msteams/src/conversation-store-memory.ts +0 -45
  180. package/extensions/msteams/src/conversation-store.ts +0 -41
  181. package/extensions/msteams/src/directory-live.ts +0 -179
  182. package/extensions/msteams/src/errors.test.ts +0 -46
  183. package/extensions/msteams/src/errors.ts +0 -158
  184. package/extensions/msteams/src/file-consent-helpers.test.ts +0 -234
  185. package/extensions/msteams/src/file-consent-helpers.ts +0 -73
  186. package/extensions/msteams/src/file-consent.ts +0 -122
  187. package/extensions/msteams/src/graph-chat.ts +0 -52
  188. package/extensions/msteams/src/graph-upload.ts +0 -445
  189. package/extensions/msteams/src/inbound.test.ts +0 -67
  190. package/extensions/msteams/src/inbound.ts +0 -38
  191. package/extensions/msteams/src/index.ts +0 -4
  192. package/extensions/msteams/src/media-helpers.test.ts +0 -186
  193. package/extensions/msteams/src/media-helpers.ts +0 -77
  194. package/extensions/msteams/src/messenger.test.ts +0 -245
  195. package/extensions/msteams/src/messenger.ts +0 -460
  196. package/extensions/msteams/src/monitor-handler/inbound-media.ts +0 -123
  197. package/extensions/msteams/src/monitor-handler/message-handler.ts +0 -629
  198. package/extensions/msteams/src/monitor-handler.ts +0 -166
  199. package/extensions/msteams/src/monitor-types.ts +0 -5
  200. package/extensions/msteams/src/monitor.ts +0 -290
  201. package/extensions/msteams/src/onboarding.ts +0 -432
  202. package/extensions/msteams/src/outbound.ts +0 -47
  203. package/extensions/msteams/src/pending-uploads.ts +0 -87
  204. package/extensions/msteams/src/policy.test.ts +0 -210
  205. package/extensions/msteams/src/policy.ts +0 -202
  206. package/extensions/msteams/src/polls-store-memory.ts +0 -30
  207. package/extensions/msteams/src/polls-store.test.ts +0 -40
  208. package/extensions/msteams/src/polls.test.ts +0 -72
  209. package/extensions/msteams/src/polls.ts +0 -299
  210. package/extensions/msteams/src/probe.test.ts +0 -57
  211. package/extensions/msteams/src/probe.ts +0 -99
  212. package/extensions/msteams/src/reply-dispatcher.ts +0 -128
  213. package/extensions/msteams/src/resolve-allowlist.ts +0 -277
  214. package/extensions/msteams/src/runtime.ts +0 -14
  215. package/extensions/msteams/src/sdk-types.ts +0 -19
  216. package/extensions/msteams/src/sdk.ts +0 -33
  217. package/extensions/msteams/src/send-context.ts +0 -156
  218. package/extensions/msteams/src/send.ts +0 -489
  219. package/extensions/msteams/src/sent-message-cache.test.ts +0 -16
  220. package/extensions/msteams/src/sent-message-cache.ts +0 -41
  221. package/extensions/msteams/src/storage.ts +0 -22
  222. package/extensions/msteams/src/store-fs.ts +0 -80
  223. package/extensions/msteams/src/token.ts +0 -19
  224. package/extensions/nextcloud-talk/clawdbot.plugin.json +0 -11
  225. package/extensions/nextcloud-talk/index.ts +0 -18
  226. package/extensions/nextcloud-talk/package.json +0 -30
  227. package/extensions/nextcloud-talk/src/accounts.ts +0 -154
  228. package/extensions/nextcloud-talk/src/channel.ts +0 -404
  229. package/extensions/nextcloud-talk/src/config-schema.ts +0 -78
  230. package/extensions/nextcloud-talk/src/format.ts +0 -79
  231. package/extensions/nextcloud-talk/src/inbound.ts +0 -336
  232. package/extensions/nextcloud-talk/src/monitor.ts +0 -246
  233. package/extensions/nextcloud-talk/src/normalize.ts +0 -31
  234. package/extensions/nextcloud-talk/src/onboarding.ts +0 -341
  235. package/extensions/nextcloud-talk/src/policy.ts +0 -175
  236. package/extensions/nextcloud-talk/src/room-info.ts +0 -111
  237. package/extensions/nextcloud-talk/src/runtime.ts +0 -14
  238. package/extensions/nextcloud-talk/src/send.ts +0 -206
  239. package/extensions/nextcloud-talk/src/signature.ts +0 -67
  240. package/extensions/nextcloud-talk/src/types.ts +0 -179
  241. package/extensions/nostr/CHANGELOG.md +0 -46
  242. package/extensions/nostr/README.md +0 -136
  243. package/extensions/nostr/clawdbot.plugin.json +0 -11
  244. package/extensions/nostr/index.ts +0 -69
  245. package/extensions/nostr/package.json +0 -31
  246. package/extensions/nostr/src/channel.test.ts +0 -141
  247. package/extensions/nostr/src/channel.ts +0 -342
  248. package/extensions/nostr/src/config-schema.ts +0 -90
  249. package/extensions/nostr/src/metrics.ts +0 -464
  250. package/extensions/nostr/src/nostr-bus.fuzz.test.ts +0 -544
  251. package/extensions/nostr/src/nostr-bus.integration.test.ts +0 -452
  252. package/extensions/nostr/src/nostr-bus.test.ts +0 -199
  253. package/extensions/nostr/src/nostr-bus.ts +0 -741
  254. package/extensions/nostr/src/nostr-profile-http.test.ts +0 -378
  255. package/extensions/nostr/src/nostr-profile-http.ts +0 -500
  256. package/extensions/nostr/src/nostr-profile-import.test.ts +0 -120
  257. package/extensions/nostr/src/nostr-profile-import.ts +0 -259
  258. package/extensions/nostr/src/nostr-profile.fuzz.test.ts +0 -479
  259. package/extensions/nostr/src/nostr-profile.test.ts +0 -410
  260. package/extensions/nostr/src/nostr-profile.ts +0 -242
  261. package/extensions/nostr/src/nostr-state-store.test.ts +0 -128
  262. package/extensions/nostr/src/nostr-state-store.ts +0 -226
  263. package/extensions/nostr/src/runtime.ts +0 -14
  264. package/extensions/nostr/src/seen-tracker.ts +0 -271
  265. package/extensions/nostr/src/types.test.ts +0 -161
  266. package/extensions/nostr/src/types.ts +0 -99
  267. package/extensions/nostr/test/setup.ts +0 -5
  268. package/extensions/open-prose/README.md +0 -25
  269. package/extensions/open-prose/clawdbot.plugin.json +0 -11
  270. package/extensions/open-prose/index.ts +0 -5
  271. package/extensions/open-prose/package.json +0 -11
  272. package/extensions/open-prose/skills/prose/LICENSE +0 -21
  273. package/extensions/open-prose/skills/prose/SKILL.md +0 -318
  274. package/extensions/open-prose/skills/prose/alt-borges.md +0 -141
  275. package/extensions/open-prose/skills/prose/alts/arabian-nights.md +0 -358
  276. package/extensions/open-prose/skills/prose/alts/borges.md +0 -360
  277. package/extensions/open-prose/skills/prose/alts/folk.md +0 -322
  278. package/extensions/open-prose/skills/prose/alts/homer.md +0 -346
  279. package/extensions/open-prose/skills/prose/alts/kafka.md +0 -373
  280. package/extensions/open-prose/skills/prose/compiler.md +0 -2967
  281. package/extensions/open-prose/skills/prose/examples/01-hello-world.prose +0 -4
  282. package/extensions/open-prose/skills/prose/examples/02-research-and-summarize.prose +0 -6
  283. package/extensions/open-prose/skills/prose/examples/03-code-review.prose +0 -17
  284. package/extensions/open-prose/skills/prose/examples/04-write-and-refine.prose +0 -14
  285. package/extensions/open-prose/skills/prose/examples/05-debug-issue.prose +0 -20
  286. package/extensions/open-prose/skills/prose/examples/06-explain-codebase.prose +0 -17
  287. package/extensions/open-prose/skills/prose/examples/07-refactor.prose +0 -20
  288. package/extensions/open-prose/skills/prose/examples/08-blog-post.prose +0 -20
  289. package/extensions/open-prose/skills/prose/examples/09-research-with-agents.prose +0 -25
  290. package/extensions/open-prose/skills/prose/examples/10-code-review-agents.prose +0 -32
  291. package/extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose +0 -27
  292. package/extensions/open-prose/skills/prose/examples/12-secure-agent-permissions.prose +0 -43
  293. package/extensions/open-prose/skills/prose/examples/13-variables-and-context.prose +0 -51
  294. package/extensions/open-prose/skills/prose/examples/14-composition-blocks.prose +0 -48
  295. package/extensions/open-prose/skills/prose/examples/15-inline-sequences.prose +0 -23
  296. package/extensions/open-prose/skills/prose/examples/16-parallel-reviews.prose +0 -19
  297. package/extensions/open-prose/skills/prose/examples/17-parallel-research.prose +0 -19
  298. package/extensions/open-prose/skills/prose/examples/18-mixed-parallel-sequential.prose +0 -36
  299. package/extensions/open-prose/skills/prose/examples/19-advanced-parallel.prose +0 -71
  300. package/extensions/open-prose/skills/prose/examples/20-fixed-loops.prose +0 -20
  301. package/extensions/open-prose/skills/prose/examples/21-pipeline-operations.prose +0 -35
  302. package/extensions/open-prose/skills/prose/examples/22-error-handling.prose +0 -51
  303. package/extensions/open-prose/skills/prose/examples/23-retry-with-backoff.prose +0 -63
  304. package/extensions/open-prose/skills/prose/examples/24-choice-blocks.prose +0 -86
  305. package/extensions/open-prose/skills/prose/examples/25-conditionals.prose +0 -114
  306. package/extensions/open-prose/skills/prose/examples/26-parameterized-blocks.prose +0 -100
  307. package/extensions/open-prose/skills/prose/examples/27-string-interpolation.prose +0 -105
  308. package/extensions/open-prose/skills/prose/examples/28-automated-pr-review.prose +0 -37
  309. package/extensions/open-prose/skills/prose/examples/28-gas-town.prose +0 -1572
  310. package/extensions/open-prose/skills/prose/examples/29-captains-chair.prose +0 -218
  311. package/extensions/open-prose/skills/prose/examples/30-captains-chair-simple.prose +0 -42
  312. package/extensions/open-prose/skills/prose/examples/31-captains-chair-with-memory.prose +0 -145
  313. package/extensions/open-prose/skills/prose/examples/33-pr-review-autofix.prose +0 -168
  314. package/extensions/open-prose/skills/prose/examples/34-content-pipeline.prose +0 -204
  315. package/extensions/open-prose/skills/prose/examples/35-feature-factory.prose +0 -296
  316. package/extensions/open-prose/skills/prose/examples/36-bug-hunter.prose +0 -237
  317. package/extensions/open-prose/skills/prose/examples/37-the-forge.prose +0 -1474
  318. package/extensions/open-prose/skills/prose/examples/38-skill-scan.prose +0 -455
  319. package/extensions/open-prose/skills/prose/examples/39-architect-by-simulation.prose +0 -277
  320. package/extensions/open-prose/skills/prose/examples/40-rlm-self-refine.prose +0 -32
  321. package/extensions/open-prose/skills/prose/examples/41-rlm-divide-conquer.prose +0 -38
  322. package/extensions/open-prose/skills/prose/examples/42-rlm-filter-recurse.prose +0 -46
  323. package/extensions/open-prose/skills/prose/examples/43-rlm-pairwise.prose +0 -50
  324. package/extensions/open-prose/skills/prose/examples/44-run-endpoint-ux-test.prose +0 -261
  325. package/extensions/open-prose/skills/prose/examples/45-plugin-release.prose +0 -159
  326. package/extensions/open-prose/skills/prose/examples/45-run-endpoint-ux-test-with-remediation.prose +0 -637
  327. package/extensions/open-prose/skills/prose/examples/46-run-endpoint-ux-test-fast.prose +0 -148
  328. package/extensions/open-prose/skills/prose/examples/46-workflow-crystallizer.prose +0 -225
  329. package/extensions/open-prose/skills/prose/examples/47-language-self-improvement.prose +0 -356
  330. package/extensions/open-prose/skills/prose/examples/48-habit-miner.prose +0 -445
  331. package/extensions/open-prose/skills/prose/examples/49-prose-run-retrospective.prose +0 -210
  332. package/extensions/open-prose/skills/prose/examples/README.md +0 -391
  333. package/extensions/open-prose/skills/prose/examples/roadmap/README.md +0 -22
  334. package/extensions/open-prose/skills/prose/examples/roadmap/iterative-refinement.prose +0 -20
  335. package/extensions/open-prose/skills/prose/examples/roadmap/parallel-review.prose +0 -18
  336. package/extensions/open-prose/skills/prose/examples/roadmap/simple-pipeline.prose +0 -17
  337. package/extensions/open-prose/skills/prose/examples/roadmap/syntax/open-prose-syntax.prose +0 -223
  338. package/extensions/open-prose/skills/prose/guidance/antipatterns.md +0 -951
  339. package/extensions/open-prose/skills/prose/guidance/patterns.md +0 -700
  340. package/extensions/open-prose/skills/prose/guidance/system-prompt.md +0 -180
  341. package/extensions/open-prose/skills/prose/help.md +0 -143
  342. package/extensions/open-prose/skills/prose/lib/README.md +0 -105
  343. package/extensions/open-prose/skills/prose/lib/calibrator.prose +0 -215
  344. package/extensions/open-prose/skills/prose/lib/cost-analyzer.prose +0 -174
  345. package/extensions/open-prose/skills/prose/lib/error-forensics.prose +0 -250
  346. package/extensions/open-prose/skills/prose/lib/inspector.prose +0 -196
  347. package/extensions/open-prose/skills/prose/lib/profiler.prose +0 -460
  348. package/extensions/open-prose/skills/prose/lib/program-improver.prose +0 -275
  349. package/extensions/open-prose/skills/prose/lib/project-memory.prose +0 -118
  350. package/extensions/open-prose/skills/prose/lib/user-memory.prose +0 -93
  351. package/extensions/open-prose/skills/prose/lib/vm-improver.prose +0 -243
  352. package/extensions/open-prose/skills/prose/primitives/session.md +0 -587
  353. package/extensions/open-prose/skills/prose/prose.md +0 -1235
  354. package/extensions/open-prose/skills/prose/state/filesystem.md +0 -478
  355. package/extensions/open-prose/skills/prose/state/in-context.md +0 -380
  356. package/extensions/open-prose/skills/prose/state/postgres.md +0 -875
  357. package/extensions/open-prose/skills/prose/state/sqlite.md +0 -572
  358. package/extensions/qwen-portal-auth/README.md +0 -24
  359. package/extensions/qwen-portal-auth/clawdbot.plugin.json +0 -11
  360. package/extensions/qwen-portal-auth/index.ts +0 -127
  361. package/extensions/qwen-portal-auth/oauth.ts +0 -190
  362. package/extensions/signal/clawdbot.plugin.json +0 -11
  363. package/extensions/signal/index.ts +0 -18
  364. package/extensions/signal/package.json +0 -11
  365. package/extensions/signal/src/channel.ts +0 -312
  366. package/extensions/signal/src/runtime.ts +0 -14
  367. package/extensions/telegram/clawdbot.plugin.json +0 -11
  368. package/extensions/telegram/index.ts +0 -18
  369. package/extensions/telegram/package.json +0 -11
  370. package/extensions/telegram/src/channel.ts +0 -478
  371. package/extensions/telegram/src/runtime.ts +0 -14
  372. package/extensions/tlon/README.md +0 -5
  373. package/extensions/tlon/clawdbot.plugin.json +0 -11
  374. package/extensions/tlon/index.ts +0 -18
  375. package/extensions/tlon/package.json +0 -30
  376. package/extensions/tlon/src/channel.ts +0 -379
  377. package/extensions/tlon/src/config-schema.test.ts +0 -32
  378. package/extensions/tlon/src/config-schema.ts +0 -43
  379. package/extensions/tlon/src/monitor/discovery.ts +0 -71
  380. package/extensions/tlon/src/monitor/history.ts +0 -87
  381. package/extensions/tlon/src/monitor/index.ts +0 -501
  382. package/extensions/tlon/src/monitor/processed-messages.test.ts +0 -24
  383. package/extensions/tlon/src/monitor/processed-messages.ts +0 -38
  384. package/extensions/tlon/src/monitor/utils.ts +0 -83
  385. package/extensions/tlon/src/onboarding.ts +0 -213
  386. package/extensions/tlon/src/runtime.ts +0 -14
  387. package/extensions/tlon/src/targets.ts +0 -79
  388. package/extensions/tlon/src/types.ts +0 -85
  389. package/extensions/tlon/src/urbit/auth.ts +0 -18
  390. package/extensions/tlon/src/urbit/http-api.ts +0 -36
  391. package/extensions/tlon/src/urbit/send.test.ts +0 -38
  392. package/extensions/tlon/src/urbit/send.ts +0 -127
  393. package/extensions/tlon/src/urbit/sse-client.test.ts +0 -41
  394. package/extensions/tlon/src/urbit/sse-client.ts +0 -367
  395. package/extensions/twitch/CHANGELOG.md +0 -21
  396. package/extensions/twitch/README.md +0 -89
  397. package/extensions/twitch/clawdbot.plugin.json +0 -9
  398. package/extensions/twitch/index.ts +0 -20
  399. package/extensions/twitch/package.json +0 -20
  400. package/extensions/twitch/src/access-control.test.ts +0 -489
  401. package/extensions/twitch/src/access-control.ts +0 -154
  402. package/extensions/twitch/src/actions.ts +0 -173
  403. package/extensions/twitch/src/client-manager-registry.ts +0 -115
  404. package/extensions/twitch/src/config-schema.ts +0 -82
  405. package/extensions/twitch/src/config.test.ts +0 -88
  406. package/extensions/twitch/src/config.ts +0 -116
  407. package/extensions/twitch/src/monitor.ts +0 -257
  408. package/extensions/twitch/src/onboarding.test.ts +0 -311
  409. package/extensions/twitch/src/onboarding.ts +0 -411
  410. package/extensions/twitch/src/outbound.test.ts +0 -373
  411. package/extensions/twitch/src/outbound.ts +0 -186
  412. package/extensions/twitch/src/plugin.test.ts +0 -39
  413. package/extensions/twitch/src/plugin.ts +0 -274
  414. package/extensions/twitch/src/probe.test.ts +0 -198
  415. package/extensions/twitch/src/probe.ts +0 -118
  416. package/extensions/twitch/src/resolver.ts +0 -137
  417. package/extensions/twitch/src/runtime.ts +0 -14
  418. package/extensions/twitch/src/send.test.ts +0 -289
  419. package/extensions/twitch/src/send.ts +0 -136
  420. package/extensions/twitch/src/status.test.ts +0 -270
  421. package/extensions/twitch/src/status.ts +0 -176
  422. package/extensions/twitch/src/token.test.ts +0 -171
  423. package/extensions/twitch/src/token.ts +0 -87
  424. package/extensions/twitch/src/twitch-client.test.ts +0 -574
  425. package/extensions/twitch/src/twitch-client.ts +0 -277
  426. package/extensions/twitch/src/types.ts +0 -141
  427. package/extensions/twitch/src/utils/markdown.ts +0 -92
  428. package/extensions/twitch/src/utils/twitch.ts +0 -78
  429. package/extensions/twitch/test/setup.ts +0 -7
  430. package/extensions/voice-call/CHANGELOG.md +0 -72
  431. package/extensions/voice-call/README.md +0 -134
  432. package/extensions/voice-call/clawdbot.plugin.json +0 -601
  433. package/extensions/voice-call/index.ts +0 -497
  434. package/extensions/voice-call/package.json +0 -16
  435. package/extensions/voice-call/src/cli.ts +0 -300
  436. package/extensions/voice-call/src/config.test.ts +0 -204
  437. package/extensions/voice-call/src/config.ts +0 -493
  438. package/extensions/voice-call/src/core-bridge.ts +0 -196
  439. package/extensions/voice-call/src/manager/context.ts +0 -21
  440. package/extensions/voice-call/src/manager/events.ts +0 -177
  441. package/extensions/voice-call/src/manager/lookup.ts +0 -33
  442. package/extensions/voice-call/src/manager/outbound.ts +0 -248
  443. package/extensions/voice-call/src/manager/state.ts +0 -50
  444. package/extensions/voice-call/src/manager/store.ts +0 -88
  445. package/extensions/voice-call/src/manager/timers.ts +0 -86
  446. package/extensions/voice-call/src/manager/twiml.ts +0 -9
  447. package/extensions/voice-call/src/manager.test.ts +0 -108
  448. package/extensions/voice-call/src/manager.ts +0 -876
  449. package/extensions/voice-call/src/media-stream.test.ts +0 -97
  450. package/extensions/voice-call/src/media-stream.ts +0 -393
  451. package/extensions/voice-call/src/providers/base.ts +0 -67
  452. package/extensions/voice-call/src/providers/index.ts +0 -10
  453. package/extensions/voice-call/src/providers/mock.ts +0 -168
  454. package/extensions/voice-call/src/providers/plivo.test.ts +0 -28
  455. package/extensions/voice-call/src/providers/plivo.ts +0 -504
  456. package/extensions/voice-call/src/providers/stt-openai-realtime.ts +0 -311
  457. package/extensions/voice-call/src/providers/telnyx.ts +0 -364
  458. package/extensions/voice-call/src/providers/tts-openai.ts +0 -264
  459. package/extensions/voice-call/src/providers/twilio/api.ts +0 -45
  460. package/extensions/voice-call/src/providers/twilio/webhook.ts +0 -29
  461. package/extensions/voice-call/src/providers/twilio.test.ts +0 -64
  462. package/extensions/voice-call/src/providers/twilio.ts +0 -595
  463. package/extensions/voice-call/src/response-generator.ts +0 -171
  464. package/extensions/voice-call/src/runtime.ts +0 -205
  465. package/extensions/voice-call/src/telephony-audio.ts +0 -88
  466. package/extensions/voice-call/src/telephony-tts.ts +0 -95
  467. package/extensions/voice-call/src/tunnel.ts +0 -331
  468. package/extensions/voice-call/src/types.ts +0 -272
  469. package/extensions/voice-call/src/utils.ts +0 -12
  470. package/extensions/voice-call/src/voice-mapping.ts +0 -65
  471. package/extensions/voice-call/src/webhook-security.test.ts +0 -233
  472. package/extensions/voice-call/src/webhook-security.ts +0 -446
  473. package/extensions/voice-call/src/webhook.ts +0 -490
  474. package/extensions/whatsapp/clawdbot.plugin.json +0 -11
  475. package/extensions/whatsapp/index.ts +0 -18
  476. package/extensions/whatsapp/package.json +0 -11
  477. package/extensions/whatsapp/src/channel.ts +0 -500
  478. package/extensions/whatsapp/src/runtime.ts +0 -14
  479. package/extensions/zalo/CHANGELOG.md +0 -55
  480. package/extensions/zalo/README.md +0 -50
  481. package/extensions/zalo/clawdbot.plugin.json +0 -11
  482. package/extensions/zalo/index.ts +0 -20
  483. package/extensions/zalo/package.json +0 -33
  484. package/extensions/zalo/src/accounts.ts +0 -71
  485. package/extensions/zalo/src/actions.ts +0 -62
  486. package/extensions/zalo/src/api.ts +0 -206
  487. package/extensions/zalo/src/channel.directory.test.ts +0 -35
  488. package/extensions/zalo/src/channel.ts +0 -394
  489. package/extensions/zalo/src/config-schema.ts +0 -24
  490. package/extensions/zalo/src/monitor.ts +0 -760
  491. package/extensions/zalo/src/monitor.webhook.test.ts +0 -70
  492. package/extensions/zalo/src/onboarding.ts +0 -405
  493. package/extensions/zalo/src/probe.ts +0 -46
  494. package/extensions/zalo/src/proxy.ts +0 -18
  495. package/extensions/zalo/src/runtime.ts +0 -14
  496. package/extensions/zalo/src/send.ts +0 -117
  497. package/extensions/zalo/src/status-issues.ts +0 -50
  498. package/extensions/zalo/src/token.ts +0 -55
  499. package/extensions/zalo/src/types.ts +0 -42
  500. package/extensions/zalouser/CHANGELOG.md +0 -33
  501. package/extensions/zalouser/README.md +0 -221
  502. package/extensions/zalouser/clawdbot.plugin.json +0 -11
  503. package/extensions/zalouser/index.ts +0 -32
  504. package/extensions/zalouser/package.json +0 -33
  505. package/extensions/zalouser/src/accounts.ts +0 -117
  506. package/extensions/zalouser/src/channel.test.ts +0 -17
  507. package/extensions/zalouser/src/channel.ts +0 -641
  508. package/extensions/zalouser/src/config-schema.ts +0 -27
  509. package/extensions/zalouser/src/monitor.ts +0 -574
  510. package/extensions/zalouser/src/onboarding.ts +0 -488
  511. package/extensions/zalouser/src/probe.ts +0 -28
  512. package/extensions/zalouser/src/runtime.ts +0 -14
  513. package/extensions/zalouser/src/send.ts +0 -150
  514. package/extensions/zalouser/src/status-issues.test.ts +0 -58
  515. package/extensions/zalouser/src/status-issues.ts +0 -81
  516. package/extensions/zalouser/src/tool.ts +0 -156
  517. package/extensions/zalouser/src/types.ts +0 -102
  518. package/extensions/zalouser/src/zca.ts +0 -208
  519. package/skills/1password/SKILL.md +0 -53
  520. package/skills/1password/references/cli-examples.md +0 -29
  521. package/skills/1password/references/get-started.md +0 -17
  522. package/skills/apple-notes/SKILL.md +0 -50
  523. package/skills/apple-reminders/SKILL.md +0 -67
  524. package/skills/bear-notes/SKILL.md +0 -79
  525. package/skills/bird/SKILL.md +0 -197
  526. package/skills/blogwatcher/SKILL.md +0 -46
  527. package/skills/blucli/SKILL.md +0 -27
  528. package/skills/bluebubbles/SKILL.md +0 -39
  529. package/skills/camsnap/SKILL.md +0 -25
  530. package/skills/canvas/SKILL.md +0 -189
  531. package/skills/clawdhub/SKILL.md +0 -53
  532. package/skills/coding-agent/SKILL.md +0 -278
  533. package/skills/discord/SKILL.md +0 -475
  534. package/skills/eightctl/SKILL.md +0 -29
  535. package/skills/food-order/SKILL.md +0 -41
  536. package/skills/gemini/SKILL.md +0 -23
  537. package/skills/gifgrep/SKILL.md +0 -47
  538. package/skills/github/SKILL.md +0 -48
  539. package/skills/gog/SKILL.md +0 -92
  540. package/skills/goplaces/SKILL.md +0 -30
  541. package/skills/himalaya/SKILL.md +0 -217
  542. package/skills/himalaya/references/configuration.md +0 -174
  543. package/skills/himalaya/references/message-composition.md +0 -182
  544. package/skills/imsg/SKILL.md +0 -25
  545. package/skills/local-places/SERVER_README.md +0 -101
  546. package/skills/local-places/SKILL.md +0 -91
  547. package/skills/local-places/pyproject.toml +0 -27
  548. package/skills/local-places/src/local_places/__init__.py +0 -2
  549. package/skills/local-places/src/local_places/google_places.py +0 -314
  550. package/skills/local-places/src/local_places/main.py +0 -65
  551. package/skills/local-places/src/local_places/schemas.py +0 -107
  552. package/skills/mcporter/SKILL.md +0 -38
  553. package/skills/model-usage/SKILL.md +0 -45
  554. package/skills/model-usage/references/codexbar-cli.md +0 -28
  555. package/skills/model-usage/scripts/model_usage.py +0 -310
  556. package/skills/nano-banana-pro/SKILL.md +0 -30
  557. package/skills/nano-banana-pro/scripts/generate_image.py +0 -169
  558. package/skills/nano-pdf/SKILL.md +0 -20
  559. package/skills/notion/SKILL.md +0 -156
  560. package/skills/obsidian/SKILL.md +0 -55
  561. package/skills/openai-image-gen/SKILL.md +0 -71
  562. package/skills/openai-image-gen/scripts/gen.py +0 -240
  563. package/skills/openai-whisper/SKILL.md +0 -19
  564. package/skills/openai-whisper-api/SKILL.md +0 -43
  565. package/skills/openai-whisper-api/scripts/transcribe.sh +0 -85
  566. package/skills/openhue/SKILL.md +0 -30
  567. package/skills/oracle/SKILL.md +0 -105
  568. package/skills/ordercli/SKILL.md +0 -47
  569. package/skills/peekaboo/SKILL.md +0 -153
  570. package/skills/sag/SKILL.md +0 -62
  571. package/skills/session-logs/SKILL.md +0 -105
  572. package/skills/sherpa-onnx-tts/SKILL.md +0 -49
  573. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -178
  574. package/skills/skill-creator/SKILL.md +0 -371
  575. package/skills/skill-creator/license.txt +0 -202
  576. package/skills/skill-creator/scripts/init_skill.py +0 -378
  577. package/skills/skill-creator/scripts/package_skill.py +0 -111
  578. package/skills/skill-creator/scripts/quick_validate.py +0 -101
  579. package/skills/slack/SKILL.md +0 -144
  580. package/skills/songsee/SKILL.md +0 -29
  581. package/skills/sonoscli/SKILL.md +0 -26
  582. package/skills/spotify-player/SKILL.md +0 -34
  583. package/skills/summarize/SKILL.md +0 -67
  584. package/skills/things-mac/SKILL.md +0 -61
  585. package/skills/tmux/SKILL.md +0 -121
  586. package/skills/tmux/scripts/find-sessions.sh +0 -112
  587. package/skills/tmux/scripts/wait-for-text.sh +0 -83
  588. package/skills/trello/SKILL.md +0 -84
  589. package/skills/video-frames/SKILL.md +0 -29
  590. package/skills/video-frames/scripts/frame.sh +0 -81
  591. package/skills/voice-call/SKILL.md +0 -35
  592. package/skills/wacli/SKILL.md +0 -42
  593. package/skills/weather/SKILL.md +0 -49
@@ -1,410 +0,0 @@
1
- import { describe, expect, it, vi, beforeEach } from "vitest";
2
- import { verifyEvent, getPublicKey } from "nostr-tools";
3
- import {
4
- createProfileEvent,
5
- profileToContent,
6
- contentToProfile,
7
- validateProfile,
8
- sanitizeProfileForDisplay,
9
- type ProfileContent,
10
- } from "./nostr-profile.js";
11
- import type { NostrProfile } from "./config-schema.js";
12
-
13
- // Test private key (DO NOT use in production - this is a known test key)
14
- const TEST_HEX_KEY = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
15
- const TEST_SK = new Uint8Array(
16
- TEST_HEX_KEY.match(/.{2}/g)!.map((byte) => parseInt(byte, 16))
17
- );
18
- const TEST_PUBKEY = getPublicKey(TEST_SK);
19
-
20
- // ============================================================================
21
- // Profile Content Conversion Tests
22
- // ============================================================================
23
-
24
- describe("profileToContent", () => {
25
- it("converts full profile to NIP-01 content format", () => {
26
- const profile: NostrProfile = {
27
- name: "testuser",
28
- displayName: "Test User",
29
- about: "A test user for unit testing",
30
- picture: "https://example.com/avatar.png",
31
- banner: "https://example.com/banner.png",
32
- website: "https://example.com",
33
- nip05: "testuser@example.com",
34
- lud16: "testuser@walletofsatoshi.com",
35
- };
36
-
37
- const content = profileToContent(profile);
38
-
39
- expect(content.name).toBe("testuser");
40
- expect(content.display_name).toBe("Test User");
41
- expect(content.about).toBe("A test user for unit testing");
42
- expect(content.picture).toBe("https://example.com/avatar.png");
43
- expect(content.banner).toBe("https://example.com/banner.png");
44
- expect(content.website).toBe("https://example.com");
45
- expect(content.nip05).toBe("testuser@example.com");
46
- expect(content.lud16).toBe("testuser@walletofsatoshi.com");
47
- });
48
-
49
- it("omits undefined fields from content", () => {
50
- const profile: NostrProfile = {
51
- name: "minimaluser",
52
- };
53
-
54
- const content = profileToContent(profile);
55
-
56
- expect(content.name).toBe("minimaluser");
57
- expect("display_name" in content).toBe(false);
58
- expect("about" in content).toBe(false);
59
- expect("picture" in content).toBe(false);
60
- });
61
-
62
- it("handles empty profile", () => {
63
- const profile: NostrProfile = {};
64
- const content = profileToContent(profile);
65
- expect(Object.keys(content)).toHaveLength(0);
66
- });
67
- });
68
-
69
- describe("contentToProfile", () => {
70
- it("converts NIP-01 content to profile format", () => {
71
- const content: ProfileContent = {
72
- name: "testuser",
73
- display_name: "Test User",
74
- about: "A test user",
75
- picture: "https://example.com/avatar.png",
76
- nip05: "test@example.com",
77
- };
78
-
79
- const profile = contentToProfile(content);
80
-
81
- expect(profile.name).toBe("testuser");
82
- expect(profile.displayName).toBe("Test User");
83
- expect(profile.about).toBe("A test user");
84
- expect(profile.picture).toBe("https://example.com/avatar.png");
85
- expect(profile.nip05).toBe("test@example.com");
86
- });
87
-
88
- it("handles empty content", () => {
89
- const content: ProfileContent = {};
90
- const profile = contentToProfile(content);
91
- expect(Object.keys(profile).filter((k) => profile[k as keyof NostrProfile] !== undefined)).toHaveLength(0);
92
- });
93
-
94
- it("round-trips profile data", () => {
95
- const original: NostrProfile = {
96
- name: "roundtrip",
97
- displayName: "Round Trip Test",
98
- about: "Testing round-trip conversion",
99
- };
100
-
101
- const content = profileToContent(original);
102
- const restored = contentToProfile(content);
103
-
104
- expect(restored.name).toBe(original.name);
105
- expect(restored.displayName).toBe(original.displayName);
106
- expect(restored.about).toBe(original.about);
107
- });
108
- });
109
-
110
- // ============================================================================
111
- // Event Creation Tests
112
- // ============================================================================
113
-
114
- describe("createProfileEvent", () => {
115
- beforeEach(() => {
116
- vi.useFakeTimers();
117
- vi.setSystemTime(new Date("2024-01-15T12:00:00Z"));
118
- });
119
-
120
- it("creates a valid kind:0 event", () => {
121
- const profile: NostrProfile = {
122
- name: "testbot",
123
- about: "A test bot",
124
- };
125
-
126
- const event = createProfileEvent(TEST_SK, profile);
127
-
128
- expect(event.kind).toBe(0);
129
- expect(event.pubkey).toBe(TEST_PUBKEY);
130
- expect(event.tags).toEqual([]);
131
- expect(event.id).toMatch(/^[0-9a-f]{64}$/);
132
- expect(event.sig).toMatch(/^[0-9a-f]{128}$/);
133
- });
134
-
135
- it("includes profile content as JSON in event content", () => {
136
- const profile: NostrProfile = {
137
- name: "jsontest",
138
- displayName: "JSON Test User",
139
- about: "Testing JSON serialization",
140
- };
141
-
142
- const event = createProfileEvent(TEST_SK, profile);
143
- const parsedContent = JSON.parse(event.content) as ProfileContent;
144
-
145
- expect(parsedContent.name).toBe("jsontest");
146
- expect(parsedContent.display_name).toBe("JSON Test User");
147
- expect(parsedContent.about).toBe("Testing JSON serialization");
148
- });
149
-
150
- it("produces a verifiable signature", () => {
151
- const profile: NostrProfile = { name: "signaturetest" };
152
- const event = createProfileEvent(TEST_SK, profile);
153
-
154
- expect(verifyEvent(event)).toBe(true);
155
- });
156
-
157
- it("uses current timestamp when no lastPublishedAt provided", () => {
158
- const profile: NostrProfile = { name: "timestamptest" };
159
- const event = createProfileEvent(TEST_SK, profile);
160
-
161
- const expectedTimestamp = Math.floor(Date.now() / 1000);
162
- expect(event.created_at).toBe(expectedTimestamp);
163
- });
164
-
165
- it("ensures monotonic timestamp when lastPublishedAt is in the future", () => {
166
- // Current time is 2024-01-15T12:00:00Z = 1705320000
167
- const futureTimestamp = 1705320000 + 3600; // 1 hour in the future
168
- const profile: NostrProfile = { name: "monotonictest" };
169
-
170
- const event = createProfileEvent(TEST_SK, profile, futureTimestamp);
171
-
172
- expect(event.created_at).toBe(futureTimestamp + 1);
173
- });
174
-
175
- it("uses current time when lastPublishedAt is in the past", () => {
176
- const pastTimestamp = 1705320000 - 3600; // 1 hour in the past
177
- const profile: NostrProfile = { name: "pasttest" };
178
-
179
- const event = createProfileEvent(TEST_SK, profile, pastTimestamp);
180
-
181
- const expectedTimestamp = Math.floor(Date.now() / 1000);
182
- expect(event.created_at).toBe(expectedTimestamp);
183
- });
184
-
185
- vi.useRealTimers();
186
- });
187
-
188
- // ============================================================================
189
- // Profile Validation Tests
190
- // ============================================================================
191
-
192
- describe("validateProfile", () => {
193
- it("validates a correct profile", () => {
194
- const profile = {
195
- name: "validuser",
196
- about: "A valid user",
197
- picture: "https://example.com/pic.png",
198
- };
199
-
200
- const result = validateProfile(profile);
201
-
202
- expect(result.valid).toBe(true);
203
- expect(result.profile).toBeDefined();
204
- expect(result.errors).toBeUndefined();
205
- });
206
-
207
- it("rejects profile with invalid URL", () => {
208
- const profile = {
209
- name: "invalidurl",
210
- picture: "http://insecure.example.com/pic.png", // HTTP not HTTPS
211
- };
212
-
213
- const result = validateProfile(profile);
214
-
215
- expect(result.valid).toBe(false);
216
- expect(result.errors).toBeDefined();
217
- expect(result.errors!.some((e) => e.includes("https://"))).toBe(true);
218
- });
219
-
220
- it("rejects profile with javascript: URL", () => {
221
- const profile = {
222
- name: "xssattempt",
223
- picture: "javascript:alert('xss')",
224
- };
225
-
226
- const result = validateProfile(profile);
227
-
228
- expect(result.valid).toBe(false);
229
- });
230
-
231
- it("rejects profile with data: URL", () => {
232
- const profile = {
233
- name: "dataurl",
234
- picture: "data:image/png;base64,abc123",
235
- };
236
-
237
- const result = validateProfile(profile);
238
-
239
- expect(result.valid).toBe(false);
240
- });
241
-
242
- it("rejects name exceeding 256 characters", () => {
243
- const profile = {
244
- name: "a".repeat(257),
245
- };
246
-
247
- const result = validateProfile(profile);
248
-
249
- expect(result.valid).toBe(false);
250
- expect(result.errors!.some((e) => e.includes("256"))).toBe(true);
251
- });
252
-
253
- it("rejects about exceeding 2000 characters", () => {
254
- const profile = {
255
- about: "a".repeat(2001),
256
- };
257
-
258
- const result = validateProfile(profile);
259
-
260
- expect(result.valid).toBe(false);
261
- expect(result.errors!.some((e) => e.includes("2000"))).toBe(true);
262
- });
263
-
264
- it("accepts empty profile", () => {
265
- const result = validateProfile({});
266
- expect(result.valid).toBe(true);
267
- });
268
-
269
- it("rejects null input", () => {
270
- const result = validateProfile(null);
271
- expect(result.valid).toBe(false);
272
- });
273
-
274
- it("rejects non-object input", () => {
275
- const result = validateProfile("not an object");
276
- expect(result.valid).toBe(false);
277
- });
278
- });
279
-
280
- // ============================================================================
281
- // Sanitization Tests
282
- // ============================================================================
283
-
284
- describe("sanitizeProfileForDisplay", () => {
285
- it("escapes HTML in name field", () => {
286
- const profile: NostrProfile = {
287
- name: "<script>alert('xss')</script>",
288
- };
289
-
290
- const sanitized = sanitizeProfileForDisplay(profile);
291
-
292
- expect(sanitized.name).toBe("&lt;script&gt;alert(&#039;xss&#039;)&lt;/script&gt;");
293
- });
294
-
295
- it("escapes HTML in about field", () => {
296
- const profile: NostrProfile = {
297
- about: 'Check out <img src="x" onerror="alert(1)">',
298
- };
299
-
300
- const sanitized = sanitizeProfileForDisplay(profile);
301
-
302
- expect(sanitized.about).toBe(
303
- 'Check out &lt;img src=&quot;x&quot; onerror=&quot;alert(1)&quot;&gt;'
304
- );
305
- });
306
-
307
- it("preserves URLs without modification", () => {
308
- const profile: NostrProfile = {
309
- picture: "https://example.com/pic.png",
310
- website: "https://example.com",
311
- };
312
-
313
- const sanitized = sanitizeProfileForDisplay(profile);
314
-
315
- expect(sanitized.picture).toBe("https://example.com/pic.png");
316
- expect(sanitized.website).toBe("https://example.com");
317
- });
318
-
319
- it("handles undefined fields", () => {
320
- const profile: NostrProfile = {
321
- name: "test",
322
- };
323
-
324
- const sanitized = sanitizeProfileForDisplay(profile);
325
-
326
- expect(sanitized.name).toBe("test");
327
- expect(sanitized.about).toBeUndefined();
328
- expect(sanitized.picture).toBeUndefined();
329
- });
330
-
331
- it("escapes ampersands", () => {
332
- const profile: NostrProfile = {
333
- name: "Tom & Jerry",
334
- };
335
-
336
- const sanitized = sanitizeProfileForDisplay(profile);
337
-
338
- expect(sanitized.name).toBe("Tom &amp; Jerry");
339
- });
340
-
341
- it("escapes quotes", () => {
342
- const profile: NostrProfile = {
343
- about: 'Say "hello" to everyone',
344
- };
345
-
346
- const sanitized = sanitizeProfileForDisplay(profile);
347
-
348
- expect(sanitized.about).toBe("Say &quot;hello&quot; to everyone");
349
- });
350
- });
351
-
352
- // ============================================================================
353
- // Edge Cases
354
- // ============================================================================
355
-
356
- describe("edge cases", () => {
357
- it("handles emoji in profile fields", () => {
358
- const profile: NostrProfile = {
359
- name: "🤖 Bot",
360
- about: "I am a 🤖 robot! 🎉",
361
- };
362
-
363
- const content = profileToContent(profile);
364
- expect(content.name).toBe("🤖 Bot");
365
- expect(content.about).toBe("I am a 🤖 robot! 🎉");
366
-
367
- const event = createProfileEvent(TEST_SK, profile);
368
- const parsed = JSON.parse(event.content) as ProfileContent;
369
- expect(parsed.name).toBe("🤖 Bot");
370
- });
371
-
372
- it("handles unicode in profile fields", () => {
373
- const profile: NostrProfile = {
374
- name: "日本語ユーザー",
375
- about: "Привет мир! 你好世界!",
376
- };
377
-
378
- const content = profileToContent(profile);
379
- expect(content.name).toBe("日本語ユーザー");
380
-
381
- const event = createProfileEvent(TEST_SK, profile);
382
- expect(verifyEvent(event)).toBe(true);
383
- });
384
-
385
- it("handles newlines in about field", () => {
386
- const profile: NostrProfile = {
387
- about: "Line 1\nLine 2\nLine 3",
388
- };
389
-
390
- const content = profileToContent(profile);
391
- expect(content.about).toBe("Line 1\nLine 2\nLine 3");
392
-
393
- const event = createProfileEvent(TEST_SK, profile);
394
- const parsed = JSON.parse(event.content) as ProfileContent;
395
- expect(parsed.about).toBe("Line 1\nLine 2\nLine 3");
396
- });
397
-
398
- it("handles maximum length fields", () => {
399
- const profile: NostrProfile = {
400
- name: "a".repeat(256),
401
- about: "b".repeat(2000),
402
- };
403
-
404
- const result = validateProfile(profile);
405
- expect(result.valid).toBe(true);
406
-
407
- const event = createProfileEvent(TEST_SK, profile);
408
- expect(verifyEvent(event)).toBe(true);
409
- });
410
- });
@@ -1,242 +0,0 @@
1
- /**
2
- * Nostr Profile Management (NIP-01 kind:0)
3
- *
4
- * Profile events are "replaceable" - the latest created_at wins.
5
- * This module handles profile event creation and publishing.
6
- */
7
-
8
- import { finalizeEvent, SimplePool, type Event } from "nostr-tools";
9
- import { type NostrProfile, NostrProfileSchema } from "./config-schema.js";
10
-
11
- // ============================================================================
12
- // Types
13
- // ============================================================================
14
-
15
- /** Result of a profile publish attempt */
16
- export interface ProfilePublishResult {
17
- /** Event ID of the published profile */
18
- eventId: string;
19
- /** Relays that successfully received the event */
20
- successes: string[];
21
- /** Relays that failed with their error messages */
22
- failures: Array<{ relay: string; error: string }>;
23
- /** Unix timestamp when the event was created */
24
- createdAt: number;
25
- }
26
-
27
- /** NIP-01 profile content (JSON inside kind:0 event) */
28
- export interface ProfileContent {
29
- name?: string;
30
- display_name?: string;
31
- about?: string;
32
- picture?: string;
33
- banner?: string;
34
- website?: string;
35
- nip05?: string;
36
- lud16?: string;
37
- }
38
-
39
- // ============================================================================
40
- // Profile Content Conversion
41
- // ============================================================================
42
-
43
- /**
44
- * Convert our config profile schema to NIP-01 content format.
45
- * Strips undefined fields and validates URLs.
46
- */
47
- export function profileToContent(profile: NostrProfile): ProfileContent {
48
- const validated = NostrProfileSchema.parse(profile);
49
-
50
- const content: ProfileContent = {};
51
-
52
- if (validated.name !== undefined) content.name = validated.name;
53
- if (validated.displayName !== undefined) content.display_name = validated.displayName;
54
- if (validated.about !== undefined) content.about = validated.about;
55
- if (validated.picture !== undefined) content.picture = validated.picture;
56
- if (validated.banner !== undefined) content.banner = validated.banner;
57
- if (validated.website !== undefined) content.website = validated.website;
58
- if (validated.nip05 !== undefined) content.nip05 = validated.nip05;
59
- if (validated.lud16 !== undefined) content.lud16 = validated.lud16;
60
-
61
- return content;
62
- }
63
-
64
- /**
65
- * Convert NIP-01 content format back to our config profile schema.
66
- * Useful for importing existing profiles from relays.
67
- */
68
- export function contentToProfile(content: ProfileContent): NostrProfile {
69
- const profile: NostrProfile = {};
70
-
71
- if (content.name !== undefined) profile.name = content.name;
72
- if (content.display_name !== undefined) profile.displayName = content.display_name;
73
- if (content.about !== undefined) profile.about = content.about;
74
- if (content.picture !== undefined) profile.picture = content.picture;
75
- if (content.banner !== undefined) profile.banner = content.banner;
76
- if (content.website !== undefined) profile.website = content.website;
77
- if (content.nip05 !== undefined) profile.nip05 = content.nip05;
78
- if (content.lud16 !== undefined) profile.lud16 = content.lud16;
79
-
80
- return profile;
81
- }
82
-
83
- // ============================================================================
84
- // Event Creation
85
- // ============================================================================
86
-
87
- /**
88
- * Create a signed kind:0 profile event.
89
- *
90
- * @param sk - Private key as Uint8Array (32 bytes)
91
- * @param profile - Profile data to include
92
- * @param lastPublishedAt - Previous profile timestamp (for monotonic guarantee)
93
- * @returns Signed Nostr event
94
- */
95
- export function createProfileEvent(
96
- sk: Uint8Array,
97
- profile: NostrProfile,
98
- lastPublishedAt?: number
99
- ): Event {
100
- const content = profileToContent(profile);
101
- const contentJson = JSON.stringify(content);
102
-
103
- // Ensure monotonic timestamp (new event > previous)
104
- const now = Math.floor(Date.now() / 1000);
105
- const createdAt = lastPublishedAt !== undefined ? Math.max(now, lastPublishedAt + 1) : now;
106
-
107
- const event = finalizeEvent(
108
- {
109
- kind: 0,
110
- content: contentJson,
111
- tags: [],
112
- created_at: createdAt,
113
- },
114
- sk
115
- );
116
-
117
- return event;
118
- }
119
-
120
- // ============================================================================
121
- // Profile Publishing
122
- // ============================================================================
123
-
124
- /** Per-relay publish timeout (ms) */
125
- const RELAY_PUBLISH_TIMEOUT_MS = 5000;
126
-
127
- /**
128
- * Publish a profile event to multiple relays.
129
- *
130
- * Best-effort: publishes to all relays in parallel, reports per-relay results.
131
- * Does NOT retry automatically - caller should handle retries if needed.
132
- *
133
- * @param pool - SimplePool instance for relay connections
134
- * @param relays - Array of relay WebSocket URLs
135
- * @param event - Signed profile event (kind:0)
136
- * @returns Publish results with successes and failures
137
- */
138
- export async function publishProfileEvent(
139
- pool: SimplePool,
140
- relays: string[],
141
- event: Event
142
- ): Promise<ProfilePublishResult> {
143
- const successes: string[] = [];
144
- const failures: Array<{ relay: string; error: string }> = [];
145
-
146
- // Publish to each relay in parallel with timeout
147
- const publishPromises = relays.map(async (relay) => {
148
- try {
149
- const timeoutPromise = new Promise<never>((_, reject) => {
150
- setTimeout(() => reject(new Error("timeout")), RELAY_PUBLISH_TIMEOUT_MS);
151
- });
152
-
153
- await Promise.race([pool.publish([relay], event), timeoutPromise]);
154
-
155
- successes.push(relay);
156
- } catch (err) {
157
- const errorMessage = err instanceof Error ? err.message : String(err);
158
- failures.push({ relay, error: errorMessage });
159
- }
160
- });
161
-
162
- await Promise.all(publishPromises);
163
-
164
- return {
165
- eventId: event.id,
166
- successes,
167
- failures,
168
- createdAt: event.created_at,
169
- };
170
- }
171
-
172
- /**
173
- * Create and publish a profile event in one call.
174
- *
175
- * @param pool - SimplePool instance
176
- * @param sk - Private key as Uint8Array
177
- * @param relays - Array of relay URLs
178
- * @param profile - Profile data
179
- * @param lastPublishedAt - Previous timestamp for monotonic ordering
180
- * @returns Publish results
181
- */
182
- export async function publishProfile(
183
- pool: SimplePool,
184
- sk: Uint8Array,
185
- relays: string[],
186
- profile: NostrProfile,
187
- lastPublishedAt?: number
188
- ): Promise<ProfilePublishResult> {
189
- const event = createProfileEvent(sk, profile, lastPublishedAt);
190
- return publishProfileEvent(pool, relays, event);
191
- }
192
-
193
- // ============================================================================
194
- // Profile Validation Helpers
195
- // ============================================================================
196
-
197
- /**
198
- * Validate a profile without throwing (returns result object).
199
- */
200
- export function validateProfile(profile: unknown): {
201
- valid: boolean;
202
- profile?: NostrProfile;
203
- errors?: string[];
204
- } {
205
- const result = NostrProfileSchema.safeParse(profile);
206
-
207
- if (result.success) {
208
- return { valid: true, profile: result.data };
209
- }
210
-
211
- return {
212
- valid: false,
213
- errors: result.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`),
214
- };
215
- }
216
-
217
- /**
218
- * Sanitize profile text fields to prevent XSS when displaying in UI.
219
- * Escapes HTML special characters.
220
- */
221
- export function sanitizeProfileForDisplay(profile: NostrProfile): NostrProfile {
222
- const escapeHtml = (str: string | undefined): string | undefined => {
223
- if (str === undefined) return undefined;
224
- return str
225
- .replace(/&/g, "&amp;")
226
- .replace(/</g, "&lt;")
227
- .replace(/>/g, "&gt;")
228
- .replace(/"/g, "&quot;")
229
- .replace(/'/g, "&#039;");
230
- };
231
-
232
- return {
233
- name: escapeHtml(profile.name),
234
- displayName: escapeHtml(profile.displayName),
235
- about: escapeHtml(profile.about),
236
- picture: profile.picture, // URLs already validated by schema
237
- banner: profile.banner,
238
- website: profile.website,
239
- nip05: escapeHtml(profile.nip05),
240
- lud16: escapeHtml(profile.lud16),
241
- };
242
- }