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.
- package/README.md +148 -77
- package/dist/build-info.json +3 -3
- package/extensions/package.json +6 -0
- package/package.json +1 -1
- package/skills/autopilot/SKILL.md +179 -0
- package/skills/goals/SKILL.md +189 -0
- package/skills/wordpress/SKILL.md +232 -0
- package/extensions/bluebubbles/clawdbot.plugin.json +0 -11
- package/extensions/bluebubbles/index.ts +0 -20
- package/extensions/bluebubbles/package.json +0 -33
- package/extensions/bluebubbles/src/accounts.ts +0 -80
- package/extensions/bluebubbles/src/actions.test.ts +0 -651
- package/extensions/bluebubbles/src/actions.ts +0 -403
- package/extensions/bluebubbles/src/attachments.test.ts +0 -346
- package/extensions/bluebubbles/src/attachments.ts +0 -282
- package/extensions/bluebubbles/src/channel.ts +0 -399
- package/extensions/bluebubbles/src/chat.test.ts +0 -462
- package/extensions/bluebubbles/src/chat.ts +0 -354
- package/extensions/bluebubbles/src/config-schema.ts +0 -51
- package/extensions/bluebubbles/src/media-send.ts +0 -168
- package/extensions/bluebubbles/src/monitor.test.ts +0 -2140
- package/extensions/bluebubbles/src/monitor.ts +0 -2101
- package/extensions/bluebubbles/src/onboarding.ts +0 -340
- package/extensions/bluebubbles/src/probe.ts +0 -127
- package/extensions/bluebubbles/src/reactions.test.ts +0 -393
- package/extensions/bluebubbles/src/reactions.ts +0 -183
- package/extensions/bluebubbles/src/runtime.ts +0 -14
- package/extensions/bluebubbles/src/send.test.ts +0 -809
- package/extensions/bluebubbles/src/send.ts +0 -418
- package/extensions/bluebubbles/src/targets.test.ts +0 -184
- package/extensions/bluebubbles/src/targets.ts +0 -323
- package/extensions/bluebubbles/src/types.ts +0 -127
- package/extensions/copilot-proxy/README.md +0 -24
- package/extensions/copilot-proxy/clawdbot.plugin.json +0 -11
- package/extensions/copilot-proxy/index.ts +0 -142
- package/extensions/copilot-proxy/package.json +0 -11
- package/extensions/google-antigravity-auth/README.md +0 -24
- package/extensions/google-antigravity-auth/clawdbot.plugin.json +0 -11
- package/extensions/google-antigravity-auth/index.ts +0 -437
- package/extensions/google-antigravity-auth/package.json +0 -11
- package/extensions/google-gemini-cli-auth/README.md +0 -35
- package/extensions/google-gemini-cli-auth/clawdbot.plugin.json +0 -11
- package/extensions/google-gemini-cli-auth/index.ts +0 -91
- package/extensions/google-gemini-cli-auth/oauth.test.ts +0 -228
- package/extensions/google-gemini-cli-auth/oauth.ts +0 -580
- package/extensions/google-gemini-cli-auth/package.json +0 -11
- package/extensions/googlechat/clawdbot.plugin.json +0 -11
- package/extensions/googlechat/index.ts +0 -20
- package/extensions/googlechat/package.json +0 -39
- package/extensions/googlechat/src/accounts.ts +0 -133
- package/extensions/googlechat/src/actions.ts +0 -162
- package/extensions/googlechat/src/api.test.ts +0 -62
- package/extensions/googlechat/src/api.ts +0 -259
- package/extensions/googlechat/src/auth.ts +0 -113
- package/extensions/googlechat/src/channel.ts +0 -580
- package/extensions/googlechat/src/monitor.test.ts +0 -27
- package/extensions/googlechat/src/monitor.ts +0 -900
- package/extensions/googlechat/src/onboarding.ts +0 -278
- package/extensions/googlechat/src/runtime.ts +0 -14
- package/extensions/googlechat/src/targets.test.ts +0 -35
- package/extensions/googlechat/src/targets.ts +0 -55
- package/extensions/googlechat/src/types.config.ts +0 -3
- package/extensions/googlechat/src/types.ts +0 -73
- package/extensions/imessage/clawdbot.plugin.json +0 -11
- package/extensions/imessage/index.ts +0 -18
- package/extensions/imessage/package.json +0 -11
- package/extensions/imessage/src/channel.ts +0 -294
- package/extensions/imessage/src/runtime.ts +0 -14
- package/extensions/line/clawdbot.plugin.json +0 -11
- package/extensions/line/index.ts +0 -20
- package/extensions/line/package.json +0 -29
- package/extensions/line/src/card-command.ts +0 -338
- package/extensions/line/src/channel.logout.test.ts +0 -96
- package/extensions/line/src/channel.sendPayload.test.ts +0 -308
- package/extensions/line/src/channel.ts +0 -773
- package/extensions/line/src/runtime.ts +0 -14
- package/extensions/matrix/CHANGELOG.md +0 -54
- package/extensions/matrix/clawdbot.plugin.json +0 -11
- package/extensions/matrix/index.ts +0 -18
- package/extensions/matrix/package.json +0 -36
- package/extensions/matrix/src/actions.ts +0 -185
- package/extensions/matrix/src/channel.directory.test.ts +0 -56
- package/extensions/matrix/src/channel.ts +0 -417
- package/extensions/matrix/src/config-schema.ts +0 -62
- package/extensions/matrix/src/directory-live.ts +0 -175
- package/extensions/matrix/src/group-mentions.ts +0 -61
- package/extensions/matrix/src/matrix/accounts.test.ts +0 -83
- package/extensions/matrix/src/matrix/accounts.ts +0 -63
- package/extensions/matrix/src/matrix/actions/client.ts +0 -53
- package/extensions/matrix/src/matrix/actions/messages.ts +0 -120
- package/extensions/matrix/src/matrix/actions/pins.ts +0 -70
- package/extensions/matrix/src/matrix/actions/reactions.ts +0 -84
- package/extensions/matrix/src/matrix/actions/room.ts +0 -88
- package/extensions/matrix/src/matrix/actions/summary.ts +0 -77
- package/extensions/matrix/src/matrix/actions/types.ts +0 -84
- package/extensions/matrix/src/matrix/actions.ts +0 -15
- package/extensions/matrix/src/matrix/active-client.ts +0 -11
- package/extensions/matrix/src/matrix/client/config.ts +0 -165
- package/extensions/matrix/src/matrix/client/create-client.ts +0 -127
- package/extensions/matrix/src/matrix/client/logging.ts +0 -35
- package/extensions/matrix/src/matrix/client/runtime.ts +0 -4
- package/extensions/matrix/src/matrix/client/shared.ts +0 -169
- package/extensions/matrix/src/matrix/client/storage.ts +0 -131
- package/extensions/matrix/src/matrix/client/types.ts +0 -34
- package/extensions/matrix/src/matrix/client.test.ts +0 -57
- package/extensions/matrix/src/matrix/client.ts +0 -9
- package/extensions/matrix/src/matrix/credentials.ts +0 -103
- package/extensions/matrix/src/matrix/deps.ts +0 -57
- package/extensions/matrix/src/matrix/format.test.ts +0 -34
- package/extensions/matrix/src/matrix/format.ts +0 -22
- package/extensions/matrix/src/matrix/index.ts +0 -11
- package/extensions/matrix/src/matrix/monitor/allowlist.ts +0 -58
- package/extensions/matrix/src/matrix/monitor/auto-join.ts +0 -68
- package/extensions/matrix/src/matrix/monitor/direct.ts +0 -105
- package/extensions/matrix/src/matrix/monitor/events.ts +0 -103
- package/extensions/matrix/src/matrix/monitor/handler.ts +0 -645
- package/extensions/matrix/src/matrix/monitor/index.ts +0 -279
- package/extensions/matrix/src/matrix/monitor/location.ts +0 -83
- package/extensions/matrix/src/matrix/monitor/media.test.ts +0 -103
- package/extensions/matrix/src/matrix/monitor/media.ts +0 -113
- package/extensions/matrix/src/matrix/monitor/mentions.ts +0 -31
- package/extensions/matrix/src/matrix/monitor/replies.ts +0 -96
- package/extensions/matrix/src/matrix/monitor/room-info.ts +0 -58
- package/extensions/matrix/src/matrix/monitor/rooms.ts +0 -43
- package/extensions/matrix/src/matrix/monitor/threads.ts +0 -64
- package/extensions/matrix/src/matrix/monitor/types.ts +0 -39
- package/extensions/matrix/src/matrix/poll-types.test.ts +0 -22
- package/extensions/matrix/src/matrix/poll-types.ts +0 -157
- package/extensions/matrix/src/matrix/probe.ts +0 -70
- package/extensions/matrix/src/matrix/send/client.ts +0 -63
- package/extensions/matrix/src/matrix/send/formatting.ts +0 -92
- package/extensions/matrix/src/matrix/send/media.ts +0 -220
- package/extensions/matrix/src/matrix/send/targets.test.ts +0 -102
- package/extensions/matrix/src/matrix/send/targets.ts +0 -144
- package/extensions/matrix/src/matrix/send/types.ts +0 -109
- package/extensions/matrix/src/matrix/send.test.ts +0 -172
- package/extensions/matrix/src/matrix/send.ts +0 -255
- package/extensions/matrix/src/onboarding.ts +0 -432
- package/extensions/matrix/src/outbound.ts +0 -53
- package/extensions/matrix/src/resolve-targets.ts +0 -89
- package/extensions/matrix/src/runtime.ts +0 -14
- package/extensions/matrix/src/tool-actions.ts +0 -160
- package/extensions/matrix/src/types.ts +0 -95
- package/extensions/mattermost/clawdbot.plugin.json +0 -11
- package/extensions/mattermost/index.ts +0 -18
- package/extensions/mattermost/package.json +0 -25
- package/extensions/mattermost/src/channel.test.ts +0 -43
- package/extensions/mattermost/src/channel.ts +0 -339
- package/extensions/mattermost/src/config-schema.ts +0 -56
- package/extensions/mattermost/src/group-mentions.ts +0 -14
- package/extensions/mattermost/src/mattermost/accounts.ts +0 -115
- package/extensions/mattermost/src/mattermost/client.ts +0 -208
- package/extensions/mattermost/src/mattermost/index.ts +0 -9
- package/extensions/mattermost/src/mattermost/monitor-helpers.ts +0 -150
- package/extensions/mattermost/src/mattermost/monitor.ts +0 -921
- package/extensions/mattermost/src/mattermost/probe.ts +0 -70
- package/extensions/mattermost/src/mattermost/send.ts +0 -217
- package/extensions/mattermost/src/normalize.ts +0 -38
- package/extensions/mattermost/src/onboarding-helpers.ts +0 -42
- package/extensions/mattermost/src/onboarding.ts +0 -187
- package/extensions/mattermost/src/runtime.ts +0 -14
- package/extensions/mattermost/src/types.ts +0 -50
- package/extensions/msteams/CHANGELOG.md +0 -51
- package/extensions/msteams/clawdbot.plugin.json +0 -11
- package/extensions/msteams/index.ts +0 -18
- package/extensions/msteams/package.json +0 -36
- package/extensions/msteams/src/attachments/download.ts +0 -206
- package/extensions/msteams/src/attachments/graph.ts +0 -319
- package/extensions/msteams/src/attachments/html.ts +0 -76
- package/extensions/msteams/src/attachments/payload.ts +0 -22
- package/extensions/msteams/src/attachments/shared.ts +0 -235
- package/extensions/msteams/src/attachments/types.ts +0 -37
- package/extensions/msteams/src/attachments.test.ts +0 -424
- package/extensions/msteams/src/attachments.ts +0 -18
- package/extensions/msteams/src/channel.directory.test.ts +0 -46
- package/extensions/msteams/src/channel.ts +0 -436
- package/extensions/msteams/src/conversation-store-fs.test.ts +0 -88
- package/extensions/msteams/src/conversation-store-fs.ts +0 -155
- package/extensions/msteams/src/conversation-store-memory.ts +0 -45
- package/extensions/msteams/src/conversation-store.ts +0 -41
- package/extensions/msteams/src/directory-live.ts +0 -179
- package/extensions/msteams/src/errors.test.ts +0 -46
- package/extensions/msteams/src/errors.ts +0 -158
- package/extensions/msteams/src/file-consent-helpers.test.ts +0 -234
- package/extensions/msteams/src/file-consent-helpers.ts +0 -73
- package/extensions/msteams/src/file-consent.ts +0 -122
- package/extensions/msteams/src/graph-chat.ts +0 -52
- package/extensions/msteams/src/graph-upload.ts +0 -445
- package/extensions/msteams/src/inbound.test.ts +0 -67
- package/extensions/msteams/src/inbound.ts +0 -38
- package/extensions/msteams/src/index.ts +0 -4
- package/extensions/msteams/src/media-helpers.test.ts +0 -186
- package/extensions/msteams/src/media-helpers.ts +0 -77
- package/extensions/msteams/src/messenger.test.ts +0 -245
- package/extensions/msteams/src/messenger.ts +0 -460
- package/extensions/msteams/src/monitor-handler/inbound-media.ts +0 -123
- package/extensions/msteams/src/monitor-handler/message-handler.ts +0 -629
- package/extensions/msteams/src/monitor-handler.ts +0 -166
- package/extensions/msteams/src/monitor-types.ts +0 -5
- package/extensions/msteams/src/monitor.ts +0 -290
- package/extensions/msteams/src/onboarding.ts +0 -432
- package/extensions/msteams/src/outbound.ts +0 -47
- package/extensions/msteams/src/pending-uploads.ts +0 -87
- package/extensions/msteams/src/policy.test.ts +0 -210
- package/extensions/msteams/src/policy.ts +0 -202
- package/extensions/msteams/src/polls-store-memory.ts +0 -30
- package/extensions/msteams/src/polls-store.test.ts +0 -40
- package/extensions/msteams/src/polls.test.ts +0 -72
- package/extensions/msteams/src/polls.ts +0 -299
- package/extensions/msteams/src/probe.test.ts +0 -57
- package/extensions/msteams/src/probe.ts +0 -99
- package/extensions/msteams/src/reply-dispatcher.ts +0 -128
- package/extensions/msteams/src/resolve-allowlist.ts +0 -277
- package/extensions/msteams/src/runtime.ts +0 -14
- package/extensions/msteams/src/sdk-types.ts +0 -19
- package/extensions/msteams/src/sdk.ts +0 -33
- package/extensions/msteams/src/send-context.ts +0 -156
- package/extensions/msteams/src/send.ts +0 -489
- package/extensions/msteams/src/sent-message-cache.test.ts +0 -16
- package/extensions/msteams/src/sent-message-cache.ts +0 -41
- package/extensions/msteams/src/storage.ts +0 -22
- package/extensions/msteams/src/store-fs.ts +0 -80
- package/extensions/msteams/src/token.ts +0 -19
- package/extensions/nextcloud-talk/clawdbot.plugin.json +0 -11
- package/extensions/nextcloud-talk/index.ts +0 -18
- package/extensions/nextcloud-talk/package.json +0 -30
- package/extensions/nextcloud-talk/src/accounts.ts +0 -154
- package/extensions/nextcloud-talk/src/channel.ts +0 -404
- package/extensions/nextcloud-talk/src/config-schema.ts +0 -78
- package/extensions/nextcloud-talk/src/format.ts +0 -79
- package/extensions/nextcloud-talk/src/inbound.ts +0 -336
- package/extensions/nextcloud-talk/src/monitor.ts +0 -246
- package/extensions/nextcloud-talk/src/normalize.ts +0 -31
- package/extensions/nextcloud-talk/src/onboarding.ts +0 -341
- package/extensions/nextcloud-talk/src/policy.ts +0 -175
- package/extensions/nextcloud-talk/src/room-info.ts +0 -111
- package/extensions/nextcloud-talk/src/runtime.ts +0 -14
- package/extensions/nextcloud-talk/src/send.ts +0 -206
- package/extensions/nextcloud-talk/src/signature.ts +0 -67
- package/extensions/nextcloud-talk/src/types.ts +0 -179
- package/extensions/nostr/CHANGELOG.md +0 -46
- package/extensions/nostr/README.md +0 -136
- package/extensions/nostr/clawdbot.plugin.json +0 -11
- package/extensions/nostr/index.ts +0 -69
- package/extensions/nostr/package.json +0 -31
- package/extensions/nostr/src/channel.test.ts +0 -141
- package/extensions/nostr/src/channel.ts +0 -342
- package/extensions/nostr/src/config-schema.ts +0 -90
- package/extensions/nostr/src/metrics.ts +0 -464
- package/extensions/nostr/src/nostr-bus.fuzz.test.ts +0 -544
- package/extensions/nostr/src/nostr-bus.integration.test.ts +0 -452
- package/extensions/nostr/src/nostr-bus.test.ts +0 -199
- package/extensions/nostr/src/nostr-bus.ts +0 -741
- package/extensions/nostr/src/nostr-profile-http.test.ts +0 -378
- package/extensions/nostr/src/nostr-profile-http.ts +0 -500
- package/extensions/nostr/src/nostr-profile-import.test.ts +0 -120
- package/extensions/nostr/src/nostr-profile-import.ts +0 -259
- package/extensions/nostr/src/nostr-profile.fuzz.test.ts +0 -479
- package/extensions/nostr/src/nostr-profile.test.ts +0 -410
- package/extensions/nostr/src/nostr-profile.ts +0 -242
- package/extensions/nostr/src/nostr-state-store.test.ts +0 -128
- package/extensions/nostr/src/nostr-state-store.ts +0 -226
- package/extensions/nostr/src/runtime.ts +0 -14
- package/extensions/nostr/src/seen-tracker.ts +0 -271
- package/extensions/nostr/src/types.test.ts +0 -161
- package/extensions/nostr/src/types.ts +0 -99
- package/extensions/nostr/test/setup.ts +0 -5
- package/extensions/open-prose/README.md +0 -25
- package/extensions/open-prose/clawdbot.plugin.json +0 -11
- package/extensions/open-prose/index.ts +0 -5
- package/extensions/open-prose/package.json +0 -11
- package/extensions/open-prose/skills/prose/LICENSE +0 -21
- package/extensions/open-prose/skills/prose/SKILL.md +0 -318
- package/extensions/open-prose/skills/prose/alt-borges.md +0 -141
- package/extensions/open-prose/skills/prose/alts/arabian-nights.md +0 -358
- package/extensions/open-prose/skills/prose/alts/borges.md +0 -360
- package/extensions/open-prose/skills/prose/alts/folk.md +0 -322
- package/extensions/open-prose/skills/prose/alts/homer.md +0 -346
- package/extensions/open-prose/skills/prose/alts/kafka.md +0 -373
- package/extensions/open-prose/skills/prose/compiler.md +0 -2967
- package/extensions/open-prose/skills/prose/examples/01-hello-world.prose +0 -4
- package/extensions/open-prose/skills/prose/examples/02-research-and-summarize.prose +0 -6
- package/extensions/open-prose/skills/prose/examples/03-code-review.prose +0 -17
- package/extensions/open-prose/skills/prose/examples/04-write-and-refine.prose +0 -14
- package/extensions/open-prose/skills/prose/examples/05-debug-issue.prose +0 -20
- package/extensions/open-prose/skills/prose/examples/06-explain-codebase.prose +0 -17
- package/extensions/open-prose/skills/prose/examples/07-refactor.prose +0 -20
- package/extensions/open-prose/skills/prose/examples/08-blog-post.prose +0 -20
- package/extensions/open-prose/skills/prose/examples/09-research-with-agents.prose +0 -25
- package/extensions/open-prose/skills/prose/examples/10-code-review-agents.prose +0 -32
- package/extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose +0 -27
- package/extensions/open-prose/skills/prose/examples/12-secure-agent-permissions.prose +0 -43
- package/extensions/open-prose/skills/prose/examples/13-variables-and-context.prose +0 -51
- package/extensions/open-prose/skills/prose/examples/14-composition-blocks.prose +0 -48
- package/extensions/open-prose/skills/prose/examples/15-inline-sequences.prose +0 -23
- package/extensions/open-prose/skills/prose/examples/16-parallel-reviews.prose +0 -19
- package/extensions/open-prose/skills/prose/examples/17-parallel-research.prose +0 -19
- package/extensions/open-prose/skills/prose/examples/18-mixed-parallel-sequential.prose +0 -36
- package/extensions/open-prose/skills/prose/examples/19-advanced-parallel.prose +0 -71
- package/extensions/open-prose/skills/prose/examples/20-fixed-loops.prose +0 -20
- package/extensions/open-prose/skills/prose/examples/21-pipeline-operations.prose +0 -35
- package/extensions/open-prose/skills/prose/examples/22-error-handling.prose +0 -51
- package/extensions/open-prose/skills/prose/examples/23-retry-with-backoff.prose +0 -63
- package/extensions/open-prose/skills/prose/examples/24-choice-blocks.prose +0 -86
- package/extensions/open-prose/skills/prose/examples/25-conditionals.prose +0 -114
- package/extensions/open-prose/skills/prose/examples/26-parameterized-blocks.prose +0 -100
- package/extensions/open-prose/skills/prose/examples/27-string-interpolation.prose +0 -105
- package/extensions/open-prose/skills/prose/examples/28-automated-pr-review.prose +0 -37
- package/extensions/open-prose/skills/prose/examples/28-gas-town.prose +0 -1572
- package/extensions/open-prose/skills/prose/examples/29-captains-chair.prose +0 -218
- package/extensions/open-prose/skills/prose/examples/30-captains-chair-simple.prose +0 -42
- package/extensions/open-prose/skills/prose/examples/31-captains-chair-with-memory.prose +0 -145
- package/extensions/open-prose/skills/prose/examples/33-pr-review-autofix.prose +0 -168
- package/extensions/open-prose/skills/prose/examples/34-content-pipeline.prose +0 -204
- package/extensions/open-prose/skills/prose/examples/35-feature-factory.prose +0 -296
- package/extensions/open-prose/skills/prose/examples/36-bug-hunter.prose +0 -237
- package/extensions/open-prose/skills/prose/examples/37-the-forge.prose +0 -1474
- package/extensions/open-prose/skills/prose/examples/38-skill-scan.prose +0 -455
- package/extensions/open-prose/skills/prose/examples/39-architect-by-simulation.prose +0 -277
- package/extensions/open-prose/skills/prose/examples/40-rlm-self-refine.prose +0 -32
- package/extensions/open-prose/skills/prose/examples/41-rlm-divide-conquer.prose +0 -38
- package/extensions/open-prose/skills/prose/examples/42-rlm-filter-recurse.prose +0 -46
- package/extensions/open-prose/skills/prose/examples/43-rlm-pairwise.prose +0 -50
- package/extensions/open-prose/skills/prose/examples/44-run-endpoint-ux-test.prose +0 -261
- package/extensions/open-prose/skills/prose/examples/45-plugin-release.prose +0 -159
- package/extensions/open-prose/skills/prose/examples/45-run-endpoint-ux-test-with-remediation.prose +0 -637
- package/extensions/open-prose/skills/prose/examples/46-run-endpoint-ux-test-fast.prose +0 -148
- package/extensions/open-prose/skills/prose/examples/46-workflow-crystallizer.prose +0 -225
- package/extensions/open-prose/skills/prose/examples/47-language-self-improvement.prose +0 -356
- package/extensions/open-prose/skills/prose/examples/48-habit-miner.prose +0 -445
- package/extensions/open-prose/skills/prose/examples/49-prose-run-retrospective.prose +0 -210
- package/extensions/open-prose/skills/prose/examples/README.md +0 -391
- package/extensions/open-prose/skills/prose/examples/roadmap/README.md +0 -22
- package/extensions/open-prose/skills/prose/examples/roadmap/iterative-refinement.prose +0 -20
- package/extensions/open-prose/skills/prose/examples/roadmap/parallel-review.prose +0 -18
- package/extensions/open-prose/skills/prose/examples/roadmap/simple-pipeline.prose +0 -17
- package/extensions/open-prose/skills/prose/examples/roadmap/syntax/open-prose-syntax.prose +0 -223
- package/extensions/open-prose/skills/prose/guidance/antipatterns.md +0 -951
- package/extensions/open-prose/skills/prose/guidance/patterns.md +0 -700
- package/extensions/open-prose/skills/prose/guidance/system-prompt.md +0 -180
- package/extensions/open-prose/skills/prose/help.md +0 -143
- package/extensions/open-prose/skills/prose/lib/README.md +0 -105
- package/extensions/open-prose/skills/prose/lib/calibrator.prose +0 -215
- package/extensions/open-prose/skills/prose/lib/cost-analyzer.prose +0 -174
- package/extensions/open-prose/skills/prose/lib/error-forensics.prose +0 -250
- package/extensions/open-prose/skills/prose/lib/inspector.prose +0 -196
- package/extensions/open-prose/skills/prose/lib/profiler.prose +0 -460
- package/extensions/open-prose/skills/prose/lib/program-improver.prose +0 -275
- package/extensions/open-prose/skills/prose/lib/project-memory.prose +0 -118
- package/extensions/open-prose/skills/prose/lib/user-memory.prose +0 -93
- package/extensions/open-prose/skills/prose/lib/vm-improver.prose +0 -243
- package/extensions/open-prose/skills/prose/primitives/session.md +0 -587
- package/extensions/open-prose/skills/prose/prose.md +0 -1235
- package/extensions/open-prose/skills/prose/state/filesystem.md +0 -478
- package/extensions/open-prose/skills/prose/state/in-context.md +0 -380
- package/extensions/open-prose/skills/prose/state/postgres.md +0 -875
- package/extensions/open-prose/skills/prose/state/sqlite.md +0 -572
- package/extensions/qwen-portal-auth/README.md +0 -24
- package/extensions/qwen-portal-auth/clawdbot.plugin.json +0 -11
- package/extensions/qwen-portal-auth/index.ts +0 -127
- package/extensions/qwen-portal-auth/oauth.ts +0 -190
- package/extensions/signal/clawdbot.plugin.json +0 -11
- package/extensions/signal/index.ts +0 -18
- package/extensions/signal/package.json +0 -11
- package/extensions/signal/src/channel.ts +0 -312
- package/extensions/signal/src/runtime.ts +0 -14
- package/extensions/telegram/clawdbot.plugin.json +0 -11
- package/extensions/telegram/index.ts +0 -18
- package/extensions/telegram/package.json +0 -11
- package/extensions/telegram/src/channel.ts +0 -478
- package/extensions/telegram/src/runtime.ts +0 -14
- package/extensions/tlon/README.md +0 -5
- package/extensions/tlon/clawdbot.plugin.json +0 -11
- package/extensions/tlon/index.ts +0 -18
- package/extensions/tlon/package.json +0 -30
- package/extensions/tlon/src/channel.ts +0 -379
- package/extensions/tlon/src/config-schema.test.ts +0 -32
- package/extensions/tlon/src/config-schema.ts +0 -43
- package/extensions/tlon/src/monitor/discovery.ts +0 -71
- package/extensions/tlon/src/monitor/history.ts +0 -87
- package/extensions/tlon/src/monitor/index.ts +0 -501
- package/extensions/tlon/src/monitor/processed-messages.test.ts +0 -24
- package/extensions/tlon/src/monitor/processed-messages.ts +0 -38
- package/extensions/tlon/src/monitor/utils.ts +0 -83
- package/extensions/tlon/src/onboarding.ts +0 -213
- package/extensions/tlon/src/runtime.ts +0 -14
- package/extensions/tlon/src/targets.ts +0 -79
- package/extensions/tlon/src/types.ts +0 -85
- package/extensions/tlon/src/urbit/auth.ts +0 -18
- package/extensions/tlon/src/urbit/http-api.ts +0 -36
- package/extensions/tlon/src/urbit/send.test.ts +0 -38
- package/extensions/tlon/src/urbit/send.ts +0 -127
- package/extensions/tlon/src/urbit/sse-client.test.ts +0 -41
- package/extensions/tlon/src/urbit/sse-client.ts +0 -367
- package/extensions/twitch/CHANGELOG.md +0 -21
- package/extensions/twitch/README.md +0 -89
- package/extensions/twitch/clawdbot.plugin.json +0 -9
- package/extensions/twitch/index.ts +0 -20
- package/extensions/twitch/package.json +0 -20
- package/extensions/twitch/src/access-control.test.ts +0 -489
- package/extensions/twitch/src/access-control.ts +0 -154
- package/extensions/twitch/src/actions.ts +0 -173
- package/extensions/twitch/src/client-manager-registry.ts +0 -115
- package/extensions/twitch/src/config-schema.ts +0 -82
- package/extensions/twitch/src/config.test.ts +0 -88
- package/extensions/twitch/src/config.ts +0 -116
- package/extensions/twitch/src/monitor.ts +0 -257
- package/extensions/twitch/src/onboarding.test.ts +0 -311
- package/extensions/twitch/src/onboarding.ts +0 -411
- package/extensions/twitch/src/outbound.test.ts +0 -373
- package/extensions/twitch/src/outbound.ts +0 -186
- package/extensions/twitch/src/plugin.test.ts +0 -39
- package/extensions/twitch/src/plugin.ts +0 -274
- package/extensions/twitch/src/probe.test.ts +0 -198
- package/extensions/twitch/src/probe.ts +0 -118
- package/extensions/twitch/src/resolver.ts +0 -137
- package/extensions/twitch/src/runtime.ts +0 -14
- package/extensions/twitch/src/send.test.ts +0 -289
- package/extensions/twitch/src/send.ts +0 -136
- package/extensions/twitch/src/status.test.ts +0 -270
- package/extensions/twitch/src/status.ts +0 -176
- package/extensions/twitch/src/token.test.ts +0 -171
- package/extensions/twitch/src/token.ts +0 -87
- package/extensions/twitch/src/twitch-client.test.ts +0 -574
- package/extensions/twitch/src/twitch-client.ts +0 -277
- package/extensions/twitch/src/types.ts +0 -141
- package/extensions/twitch/src/utils/markdown.ts +0 -92
- package/extensions/twitch/src/utils/twitch.ts +0 -78
- package/extensions/twitch/test/setup.ts +0 -7
- package/extensions/voice-call/CHANGELOG.md +0 -72
- package/extensions/voice-call/README.md +0 -134
- package/extensions/voice-call/clawdbot.plugin.json +0 -601
- package/extensions/voice-call/index.ts +0 -497
- package/extensions/voice-call/package.json +0 -16
- package/extensions/voice-call/src/cli.ts +0 -300
- package/extensions/voice-call/src/config.test.ts +0 -204
- package/extensions/voice-call/src/config.ts +0 -493
- package/extensions/voice-call/src/core-bridge.ts +0 -196
- package/extensions/voice-call/src/manager/context.ts +0 -21
- package/extensions/voice-call/src/manager/events.ts +0 -177
- package/extensions/voice-call/src/manager/lookup.ts +0 -33
- package/extensions/voice-call/src/manager/outbound.ts +0 -248
- package/extensions/voice-call/src/manager/state.ts +0 -50
- package/extensions/voice-call/src/manager/store.ts +0 -88
- package/extensions/voice-call/src/manager/timers.ts +0 -86
- package/extensions/voice-call/src/manager/twiml.ts +0 -9
- package/extensions/voice-call/src/manager.test.ts +0 -108
- package/extensions/voice-call/src/manager.ts +0 -876
- package/extensions/voice-call/src/media-stream.test.ts +0 -97
- package/extensions/voice-call/src/media-stream.ts +0 -393
- package/extensions/voice-call/src/providers/base.ts +0 -67
- package/extensions/voice-call/src/providers/index.ts +0 -10
- package/extensions/voice-call/src/providers/mock.ts +0 -168
- package/extensions/voice-call/src/providers/plivo.test.ts +0 -28
- package/extensions/voice-call/src/providers/plivo.ts +0 -504
- package/extensions/voice-call/src/providers/stt-openai-realtime.ts +0 -311
- package/extensions/voice-call/src/providers/telnyx.ts +0 -364
- package/extensions/voice-call/src/providers/tts-openai.ts +0 -264
- package/extensions/voice-call/src/providers/twilio/api.ts +0 -45
- package/extensions/voice-call/src/providers/twilio/webhook.ts +0 -29
- package/extensions/voice-call/src/providers/twilio.test.ts +0 -64
- package/extensions/voice-call/src/providers/twilio.ts +0 -595
- package/extensions/voice-call/src/response-generator.ts +0 -171
- package/extensions/voice-call/src/runtime.ts +0 -205
- package/extensions/voice-call/src/telephony-audio.ts +0 -88
- package/extensions/voice-call/src/telephony-tts.ts +0 -95
- package/extensions/voice-call/src/tunnel.ts +0 -331
- package/extensions/voice-call/src/types.ts +0 -272
- package/extensions/voice-call/src/utils.ts +0 -12
- package/extensions/voice-call/src/voice-mapping.ts +0 -65
- package/extensions/voice-call/src/webhook-security.test.ts +0 -233
- package/extensions/voice-call/src/webhook-security.ts +0 -446
- package/extensions/voice-call/src/webhook.ts +0 -490
- package/extensions/whatsapp/clawdbot.plugin.json +0 -11
- package/extensions/whatsapp/index.ts +0 -18
- package/extensions/whatsapp/package.json +0 -11
- package/extensions/whatsapp/src/channel.ts +0 -500
- package/extensions/whatsapp/src/runtime.ts +0 -14
- package/extensions/zalo/CHANGELOG.md +0 -55
- package/extensions/zalo/README.md +0 -50
- package/extensions/zalo/clawdbot.plugin.json +0 -11
- package/extensions/zalo/index.ts +0 -20
- package/extensions/zalo/package.json +0 -33
- package/extensions/zalo/src/accounts.ts +0 -71
- package/extensions/zalo/src/actions.ts +0 -62
- package/extensions/zalo/src/api.ts +0 -206
- package/extensions/zalo/src/channel.directory.test.ts +0 -35
- package/extensions/zalo/src/channel.ts +0 -394
- package/extensions/zalo/src/config-schema.ts +0 -24
- package/extensions/zalo/src/monitor.ts +0 -760
- package/extensions/zalo/src/monitor.webhook.test.ts +0 -70
- package/extensions/zalo/src/onboarding.ts +0 -405
- package/extensions/zalo/src/probe.ts +0 -46
- package/extensions/zalo/src/proxy.ts +0 -18
- package/extensions/zalo/src/runtime.ts +0 -14
- package/extensions/zalo/src/send.ts +0 -117
- package/extensions/zalo/src/status-issues.ts +0 -50
- package/extensions/zalo/src/token.ts +0 -55
- package/extensions/zalo/src/types.ts +0 -42
- package/extensions/zalouser/CHANGELOG.md +0 -33
- package/extensions/zalouser/README.md +0 -221
- package/extensions/zalouser/clawdbot.plugin.json +0 -11
- package/extensions/zalouser/index.ts +0 -32
- package/extensions/zalouser/package.json +0 -33
- package/extensions/zalouser/src/accounts.ts +0 -117
- package/extensions/zalouser/src/channel.test.ts +0 -17
- package/extensions/zalouser/src/channel.ts +0 -641
- package/extensions/zalouser/src/config-schema.ts +0 -27
- package/extensions/zalouser/src/monitor.ts +0 -574
- package/extensions/zalouser/src/onboarding.ts +0 -488
- package/extensions/zalouser/src/probe.ts +0 -28
- package/extensions/zalouser/src/runtime.ts +0 -14
- package/extensions/zalouser/src/send.ts +0 -150
- package/extensions/zalouser/src/status-issues.test.ts +0 -58
- package/extensions/zalouser/src/status-issues.ts +0 -81
- package/extensions/zalouser/src/tool.ts +0 -156
- package/extensions/zalouser/src/types.ts +0 -102
- package/extensions/zalouser/src/zca.ts +0 -208
- package/skills/1password/SKILL.md +0 -53
- package/skills/1password/references/cli-examples.md +0 -29
- package/skills/1password/references/get-started.md +0 -17
- package/skills/apple-notes/SKILL.md +0 -50
- package/skills/apple-reminders/SKILL.md +0 -67
- package/skills/bear-notes/SKILL.md +0 -79
- package/skills/bird/SKILL.md +0 -197
- package/skills/blogwatcher/SKILL.md +0 -46
- package/skills/blucli/SKILL.md +0 -27
- package/skills/bluebubbles/SKILL.md +0 -39
- package/skills/camsnap/SKILL.md +0 -25
- package/skills/canvas/SKILL.md +0 -189
- package/skills/clawdhub/SKILL.md +0 -53
- package/skills/coding-agent/SKILL.md +0 -278
- package/skills/discord/SKILL.md +0 -475
- package/skills/eightctl/SKILL.md +0 -29
- package/skills/food-order/SKILL.md +0 -41
- package/skills/gemini/SKILL.md +0 -23
- package/skills/gifgrep/SKILL.md +0 -47
- package/skills/github/SKILL.md +0 -48
- package/skills/gog/SKILL.md +0 -92
- package/skills/goplaces/SKILL.md +0 -30
- package/skills/himalaya/SKILL.md +0 -217
- package/skills/himalaya/references/configuration.md +0 -174
- package/skills/himalaya/references/message-composition.md +0 -182
- package/skills/imsg/SKILL.md +0 -25
- package/skills/local-places/SERVER_README.md +0 -101
- package/skills/local-places/SKILL.md +0 -91
- package/skills/local-places/pyproject.toml +0 -27
- package/skills/local-places/src/local_places/__init__.py +0 -2
- package/skills/local-places/src/local_places/google_places.py +0 -314
- package/skills/local-places/src/local_places/main.py +0 -65
- package/skills/local-places/src/local_places/schemas.py +0 -107
- package/skills/mcporter/SKILL.md +0 -38
- package/skills/model-usage/SKILL.md +0 -45
- package/skills/model-usage/references/codexbar-cli.md +0 -28
- package/skills/model-usage/scripts/model_usage.py +0 -310
- package/skills/nano-banana-pro/SKILL.md +0 -30
- package/skills/nano-banana-pro/scripts/generate_image.py +0 -169
- package/skills/nano-pdf/SKILL.md +0 -20
- package/skills/notion/SKILL.md +0 -156
- package/skills/obsidian/SKILL.md +0 -55
- package/skills/openai-image-gen/SKILL.md +0 -71
- package/skills/openai-image-gen/scripts/gen.py +0 -240
- package/skills/openai-whisper/SKILL.md +0 -19
- package/skills/openai-whisper-api/SKILL.md +0 -43
- package/skills/openai-whisper-api/scripts/transcribe.sh +0 -85
- package/skills/openhue/SKILL.md +0 -30
- package/skills/oracle/SKILL.md +0 -105
- package/skills/ordercli/SKILL.md +0 -47
- package/skills/peekaboo/SKILL.md +0 -153
- package/skills/sag/SKILL.md +0 -62
- package/skills/session-logs/SKILL.md +0 -105
- package/skills/sherpa-onnx-tts/SKILL.md +0 -49
- package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -178
- package/skills/skill-creator/SKILL.md +0 -371
- package/skills/skill-creator/license.txt +0 -202
- package/skills/skill-creator/scripts/init_skill.py +0 -378
- package/skills/skill-creator/scripts/package_skill.py +0 -111
- package/skills/skill-creator/scripts/quick_validate.py +0 -101
- package/skills/slack/SKILL.md +0 -144
- package/skills/songsee/SKILL.md +0 -29
- package/skills/sonoscli/SKILL.md +0 -26
- package/skills/spotify-player/SKILL.md +0 -34
- package/skills/summarize/SKILL.md +0 -67
- package/skills/things-mac/SKILL.md +0 -61
- package/skills/tmux/SKILL.md +0 -121
- package/skills/tmux/scripts/find-sessions.sh +0 -112
- package/skills/tmux/scripts/wait-for-text.sh +0 -83
- package/skills/trello/SKILL.md +0 -84
- package/skills/video-frames/SKILL.md +0 -29
- package/skills/video-frames/scripts/frame.sh +0 -81
- package/skills/voice-call/SKILL.md +0 -35
- package/skills/wacli/SKILL.md +0 -42
- package/skills/weather/SKILL.md +0 -49
|
@@ -1,595 +0,0 @@
|
|
|
1
|
-
import crypto from "node:crypto";
|
|
2
|
-
|
|
3
|
-
import type { TwilioConfig } from "../config.js";
|
|
4
|
-
import type { MediaStreamHandler } from "../media-stream.js";
|
|
5
|
-
import type {
|
|
6
|
-
HangupCallInput,
|
|
7
|
-
InitiateCallInput,
|
|
8
|
-
InitiateCallResult,
|
|
9
|
-
NormalizedEvent,
|
|
10
|
-
PlayTtsInput,
|
|
11
|
-
ProviderWebhookParseResult,
|
|
12
|
-
StartListeningInput,
|
|
13
|
-
StopListeningInput,
|
|
14
|
-
WebhookContext,
|
|
15
|
-
WebhookVerificationResult,
|
|
16
|
-
} from "../types.js";
|
|
17
|
-
import { escapeXml, mapVoiceToPolly } from "../voice-mapping.js";
|
|
18
|
-
import { chunkAudio } from "../telephony-audio.js";
|
|
19
|
-
import type { TelephonyTtsProvider } from "../telephony-tts.js";
|
|
20
|
-
import type { VoiceCallProvider } from "./base.js";
|
|
21
|
-
import { twilioApiRequest } from "./twilio/api.js";
|
|
22
|
-
import { verifyTwilioProviderWebhook } from "./twilio/webhook.js";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Twilio Voice API provider implementation.
|
|
26
|
-
*
|
|
27
|
-
* Uses Twilio Programmable Voice API with Media Streams for real-time
|
|
28
|
-
* bidirectional audio streaming.
|
|
29
|
-
*
|
|
30
|
-
* @see https://www.twilio.com/docs/voice
|
|
31
|
-
* @see https://www.twilio.com/docs/voice/media-streams
|
|
32
|
-
*/
|
|
33
|
-
export interface TwilioProviderOptions {
|
|
34
|
-
/** Allow ngrok free tier compatibility mode (less secure) */
|
|
35
|
-
allowNgrokFreeTier?: boolean;
|
|
36
|
-
/** Override public URL for signature verification */
|
|
37
|
-
publicUrl?: string;
|
|
38
|
-
/** Path for media stream WebSocket (e.g., /voice/stream) */
|
|
39
|
-
streamPath?: string;
|
|
40
|
-
/** Skip webhook signature verification (development only) */
|
|
41
|
-
skipVerification?: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export class TwilioProvider implements VoiceCallProvider {
|
|
45
|
-
readonly name = "twilio" as const;
|
|
46
|
-
|
|
47
|
-
private readonly accountSid: string;
|
|
48
|
-
private readonly authToken: string;
|
|
49
|
-
private readonly baseUrl: string;
|
|
50
|
-
private readonly callWebhookUrls = new Map<string, string>();
|
|
51
|
-
private readonly options: TwilioProviderOptions;
|
|
52
|
-
|
|
53
|
-
/** Current public webhook URL (set when tunnel starts or from config) */
|
|
54
|
-
private currentPublicUrl: string | null = null;
|
|
55
|
-
|
|
56
|
-
/** Optional telephony TTS provider for streaming TTS */
|
|
57
|
-
private ttsProvider: TelephonyTtsProvider | null = null;
|
|
58
|
-
|
|
59
|
-
/** Optional media stream handler for sending audio */
|
|
60
|
-
private mediaStreamHandler: MediaStreamHandler | null = null;
|
|
61
|
-
|
|
62
|
-
/** Map of call SID to stream SID for media streams */
|
|
63
|
-
private callStreamMap = new Map<string, string>();
|
|
64
|
-
|
|
65
|
-
/** Storage for TwiML content (for notify mode with URL-based TwiML) */
|
|
66
|
-
private readonly twimlStorage = new Map<string, string>();
|
|
67
|
-
/** Track notify-mode calls to avoid streaming on follow-up callbacks */
|
|
68
|
-
private readonly notifyCalls = new Set<string>();
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Delete stored TwiML for a given `callId`.
|
|
72
|
-
*
|
|
73
|
-
* We keep TwiML in-memory only long enough to satisfy the initial Twilio
|
|
74
|
-
* webhook request (notify mode). Subsequent webhooks should not reuse it.
|
|
75
|
-
*/
|
|
76
|
-
private deleteStoredTwiml(callId: string): void {
|
|
77
|
-
this.twimlStorage.delete(callId);
|
|
78
|
-
this.notifyCalls.delete(callId);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Delete stored TwiML for a call, addressed by Twilio's provider call SID.
|
|
83
|
-
*
|
|
84
|
-
* This is used when we only have `providerCallId` (e.g. hangup).
|
|
85
|
-
*/
|
|
86
|
-
private deleteStoredTwimlForProviderCall(providerCallId: string): void {
|
|
87
|
-
const webhookUrl = this.callWebhookUrls.get(providerCallId);
|
|
88
|
-
if (!webhookUrl) return;
|
|
89
|
-
|
|
90
|
-
const callIdMatch = webhookUrl.match(/callId=([^&]+)/);
|
|
91
|
-
if (!callIdMatch) return;
|
|
92
|
-
|
|
93
|
-
this.deleteStoredTwiml(callIdMatch[1]);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
constructor(config: TwilioConfig, options: TwilioProviderOptions = {}) {
|
|
97
|
-
if (!config.accountSid) {
|
|
98
|
-
throw new Error("Twilio Account SID is required");
|
|
99
|
-
}
|
|
100
|
-
if (!config.authToken) {
|
|
101
|
-
throw new Error("Twilio Auth Token is required");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.accountSid = config.accountSid;
|
|
105
|
-
this.authToken = config.authToken;
|
|
106
|
-
this.baseUrl = `https://api.twilio.com/2010-04-01/Accounts/${this.accountSid}`;
|
|
107
|
-
this.options = options;
|
|
108
|
-
|
|
109
|
-
if (options.publicUrl) {
|
|
110
|
-
this.currentPublicUrl = options.publicUrl;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
setPublicUrl(url: string): void {
|
|
115
|
-
this.currentPublicUrl = url;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
getPublicUrl(): string | null {
|
|
119
|
-
return this.currentPublicUrl;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
setTTSProvider(provider: TelephonyTtsProvider): void {
|
|
123
|
-
this.ttsProvider = provider;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
setMediaStreamHandler(handler: MediaStreamHandler): void {
|
|
127
|
-
this.mediaStreamHandler = handler;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
registerCallStream(callSid: string, streamSid: string): void {
|
|
131
|
-
this.callStreamMap.set(callSid, streamSid);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
unregisterCallStream(callSid: string): void {
|
|
135
|
-
this.callStreamMap.delete(callSid);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Clear TTS queue for a call (barge-in).
|
|
140
|
-
* Used when user starts speaking to interrupt current TTS playback.
|
|
141
|
-
*/
|
|
142
|
-
clearTtsQueue(callSid: string): void {
|
|
143
|
-
const streamSid = this.callStreamMap.get(callSid);
|
|
144
|
-
if (streamSid && this.mediaStreamHandler) {
|
|
145
|
-
this.mediaStreamHandler.clearTtsQueue(streamSid);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Make an authenticated request to the Twilio API.
|
|
151
|
-
*/
|
|
152
|
-
private async apiRequest<T = unknown>(
|
|
153
|
-
endpoint: string,
|
|
154
|
-
params: Record<string, string | string[]>,
|
|
155
|
-
options?: { allowNotFound?: boolean },
|
|
156
|
-
): Promise<T> {
|
|
157
|
-
return await twilioApiRequest<T>({
|
|
158
|
-
baseUrl: this.baseUrl,
|
|
159
|
-
accountSid: this.accountSid,
|
|
160
|
-
authToken: this.authToken,
|
|
161
|
-
endpoint,
|
|
162
|
-
body: params,
|
|
163
|
-
allowNotFound: options?.allowNotFound,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Verify Twilio webhook signature using HMAC-SHA1.
|
|
169
|
-
*
|
|
170
|
-
* Handles reverse proxy scenarios (Tailscale, nginx, ngrok) by reconstructing
|
|
171
|
-
* the public URL from forwarding headers.
|
|
172
|
-
*
|
|
173
|
-
* @see https://www.twilio.com/docs/usage/webhooks/webhooks-security
|
|
174
|
-
*/
|
|
175
|
-
verifyWebhook(ctx: WebhookContext): WebhookVerificationResult {
|
|
176
|
-
return verifyTwilioProviderWebhook({
|
|
177
|
-
ctx,
|
|
178
|
-
authToken: this.authToken,
|
|
179
|
-
currentPublicUrl: this.currentPublicUrl,
|
|
180
|
-
options: this.options,
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Parse Twilio webhook event into normalized format.
|
|
186
|
-
*/
|
|
187
|
-
parseWebhookEvent(ctx: WebhookContext): ProviderWebhookParseResult {
|
|
188
|
-
try {
|
|
189
|
-
const params = new URLSearchParams(ctx.rawBody);
|
|
190
|
-
const callIdFromQuery =
|
|
191
|
-
typeof ctx.query?.callId === "string" && ctx.query.callId.trim()
|
|
192
|
-
? ctx.query.callId.trim()
|
|
193
|
-
: undefined;
|
|
194
|
-
const event = this.normalizeEvent(params, callIdFromQuery);
|
|
195
|
-
|
|
196
|
-
// For Twilio, we must return TwiML. Most actions are driven by Calls API updates,
|
|
197
|
-
// so the webhook response is typically a pause to keep the call alive.
|
|
198
|
-
const twiml = this.generateTwimlResponse(ctx);
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
events: event ? [event] : [],
|
|
202
|
-
providerResponseBody: twiml,
|
|
203
|
-
providerResponseHeaders: { "Content-Type": "application/xml" },
|
|
204
|
-
statusCode: 200,
|
|
205
|
-
};
|
|
206
|
-
} catch {
|
|
207
|
-
return { events: [], statusCode: 400 };
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Parse Twilio direction to normalized format.
|
|
213
|
-
*/
|
|
214
|
-
private static parseDirection(
|
|
215
|
-
direction: string | null,
|
|
216
|
-
): "inbound" | "outbound" | undefined {
|
|
217
|
-
if (direction === "inbound") return "inbound";
|
|
218
|
-
if (direction === "outbound-api" || direction === "outbound-dial")
|
|
219
|
-
return "outbound";
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Convert Twilio webhook params to normalized event format.
|
|
225
|
-
*/
|
|
226
|
-
private normalizeEvent(
|
|
227
|
-
params: URLSearchParams,
|
|
228
|
-
callIdOverride?: string,
|
|
229
|
-
): NormalizedEvent | null {
|
|
230
|
-
const callSid = params.get("CallSid") || "";
|
|
231
|
-
|
|
232
|
-
const baseEvent = {
|
|
233
|
-
id: crypto.randomUUID(),
|
|
234
|
-
callId: callIdOverride || callSid,
|
|
235
|
-
providerCallId: callSid,
|
|
236
|
-
timestamp: Date.now(),
|
|
237
|
-
direction: TwilioProvider.parseDirection(params.get("Direction")),
|
|
238
|
-
from: params.get("From") || undefined,
|
|
239
|
-
to: params.get("To") || undefined,
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
// Handle speech result (from <Gather>)
|
|
243
|
-
const speechResult = params.get("SpeechResult");
|
|
244
|
-
if (speechResult) {
|
|
245
|
-
return {
|
|
246
|
-
...baseEvent,
|
|
247
|
-
type: "call.speech",
|
|
248
|
-
transcript: speechResult,
|
|
249
|
-
isFinal: true,
|
|
250
|
-
confidence: parseFloat(params.get("Confidence") || "0.9"),
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Handle DTMF
|
|
255
|
-
const digits = params.get("Digits");
|
|
256
|
-
if (digits) {
|
|
257
|
-
return { ...baseEvent, type: "call.dtmf", digits };
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Handle call status changes
|
|
261
|
-
const callStatus = params.get("CallStatus");
|
|
262
|
-
switch (callStatus) {
|
|
263
|
-
case "initiated":
|
|
264
|
-
return { ...baseEvent, type: "call.initiated" };
|
|
265
|
-
case "ringing":
|
|
266
|
-
return { ...baseEvent, type: "call.ringing" };
|
|
267
|
-
case "in-progress":
|
|
268
|
-
return { ...baseEvent, type: "call.answered" };
|
|
269
|
-
case "completed":
|
|
270
|
-
case "busy":
|
|
271
|
-
case "no-answer":
|
|
272
|
-
case "failed":
|
|
273
|
-
if (callIdOverride) {
|
|
274
|
-
this.deleteStoredTwiml(callIdOverride);
|
|
275
|
-
}
|
|
276
|
-
return { ...baseEvent, type: "call.ended", reason: callStatus };
|
|
277
|
-
case "canceled":
|
|
278
|
-
if (callIdOverride) {
|
|
279
|
-
this.deleteStoredTwiml(callIdOverride);
|
|
280
|
-
}
|
|
281
|
-
return { ...baseEvent, type: "call.ended", reason: "hangup-bot" };
|
|
282
|
-
default:
|
|
283
|
-
return null;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private static readonly EMPTY_TWIML =
|
|
288
|
-
'<?xml version="1.0" encoding="UTF-8"?><Response></Response>';
|
|
289
|
-
|
|
290
|
-
private static readonly PAUSE_TWIML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
291
|
-
<Response>
|
|
292
|
-
<Pause length="30"/>
|
|
293
|
-
</Response>`;
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Generate TwiML response for webhook.
|
|
297
|
-
* When a call is answered, connects to media stream for bidirectional audio.
|
|
298
|
-
*/
|
|
299
|
-
private generateTwimlResponse(ctx?: WebhookContext): string {
|
|
300
|
-
if (!ctx) return TwilioProvider.EMPTY_TWIML;
|
|
301
|
-
|
|
302
|
-
const params = new URLSearchParams(ctx.rawBody);
|
|
303
|
-
const type =
|
|
304
|
-
typeof ctx.query?.type === "string" ? ctx.query.type.trim() : undefined;
|
|
305
|
-
const isStatusCallback = type === "status";
|
|
306
|
-
const callStatus = params.get("CallStatus");
|
|
307
|
-
const direction = params.get("Direction");
|
|
308
|
-
const isOutbound = direction?.startsWith("outbound") ?? false;
|
|
309
|
-
const callIdFromQuery =
|
|
310
|
-
typeof ctx.query?.callId === "string" && ctx.query.callId.trim()
|
|
311
|
-
? ctx.query.callId.trim()
|
|
312
|
-
: undefined;
|
|
313
|
-
|
|
314
|
-
// Avoid logging webhook params/TwiML (may contain PII).
|
|
315
|
-
|
|
316
|
-
// Handle initial TwiML request (when Twilio first initiates the call)
|
|
317
|
-
// Check if we have stored TwiML for this call (notify mode)
|
|
318
|
-
if (callIdFromQuery && !isStatusCallback) {
|
|
319
|
-
const storedTwiml = this.twimlStorage.get(callIdFromQuery);
|
|
320
|
-
if (storedTwiml) {
|
|
321
|
-
// Clean up after serving (one-time use)
|
|
322
|
-
this.deleteStoredTwiml(callIdFromQuery);
|
|
323
|
-
return storedTwiml;
|
|
324
|
-
}
|
|
325
|
-
if (this.notifyCalls.has(callIdFromQuery)) {
|
|
326
|
-
return TwilioProvider.EMPTY_TWIML;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Conversation mode: return streaming TwiML immediately for outbound calls.
|
|
330
|
-
if (isOutbound) {
|
|
331
|
-
const streamUrl = this.getStreamUrl();
|
|
332
|
-
return streamUrl
|
|
333
|
-
? this.getStreamConnectXml(streamUrl)
|
|
334
|
-
: TwilioProvider.PAUSE_TWIML;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Status callbacks should not receive TwiML.
|
|
339
|
-
if (isStatusCallback) {
|
|
340
|
-
return TwilioProvider.EMPTY_TWIML;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Handle subsequent webhook requests (status callbacks, etc.)
|
|
344
|
-
// For inbound calls, answer immediately with stream
|
|
345
|
-
if (direction === "inbound") {
|
|
346
|
-
const streamUrl = this.getStreamUrl();
|
|
347
|
-
return streamUrl
|
|
348
|
-
? this.getStreamConnectXml(streamUrl)
|
|
349
|
-
: TwilioProvider.PAUSE_TWIML;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// For outbound calls, only connect to stream when call is in-progress
|
|
353
|
-
if (callStatus !== "in-progress") {
|
|
354
|
-
return TwilioProvider.EMPTY_TWIML;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const streamUrl = this.getStreamUrl();
|
|
358
|
-
return streamUrl
|
|
359
|
-
? this.getStreamConnectXml(streamUrl)
|
|
360
|
-
: TwilioProvider.PAUSE_TWIML;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Get the WebSocket URL for media streaming.
|
|
365
|
-
* Derives from the public URL origin + stream path.
|
|
366
|
-
*/
|
|
367
|
-
private getStreamUrl(): string | null {
|
|
368
|
-
if (!this.currentPublicUrl || !this.options.streamPath) {
|
|
369
|
-
return null;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Extract just the origin (host) from the public URL, ignoring any path
|
|
373
|
-
const url = new URL(this.currentPublicUrl);
|
|
374
|
-
const origin = url.origin;
|
|
375
|
-
|
|
376
|
-
// Convert https:// to wss:// for WebSocket
|
|
377
|
-
const wsOrigin = origin
|
|
378
|
-
.replace(/^https:\/\//, "wss://")
|
|
379
|
-
.replace(/^http:\/\//, "ws://");
|
|
380
|
-
|
|
381
|
-
// Append the stream path
|
|
382
|
-
const path = this.options.streamPath.startsWith("/")
|
|
383
|
-
? this.options.streamPath
|
|
384
|
-
: `/${this.options.streamPath}`;
|
|
385
|
-
|
|
386
|
-
return `${wsOrigin}${path}`;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Generate TwiML to connect a call to a WebSocket media stream.
|
|
391
|
-
* This enables bidirectional audio streaming for real-time STT/TTS.
|
|
392
|
-
*
|
|
393
|
-
* @param streamUrl - WebSocket URL (wss://...) for the media stream
|
|
394
|
-
*/
|
|
395
|
-
getStreamConnectXml(streamUrl: string): string {
|
|
396
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
397
|
-
<Response>
|
|
398
|
-
<Connect>
|
|
399
|
-
<Stream url="${escapeXml(streamUrl)}" />
|
|
400
|
-
</Connect>
|
|
401
|
-
</Response>`;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Initiate an outbound call via Twilio API.
|
|
406
|
-
* If inlineTwiml is provided, uses that directly (for notify mode).
|
|
407
|
-
* Otherwise, uses webhook URL for dynamic TwiML.
|
|
408
|
-
*/
|
|
409
|
-
async initiateCall(input: InitiateCallInput): Promise<InitiateCallResult> {
|
|
410
|
-
const url = new URL(input.webhookUrl);
|
|
411
|
-
url.searchParams.set("callId", input.callId);
|
|
412
|
-
|
|
413
|
-
// Create separate URL for status callbacks (required by Twilio)
|
|
414
|
-
const statusUrl = new URL(input.webhookUrl);
|
|
415
|
-
statusUrl.searchParams.set("callId", input.callId);
|
|
416
|
-
statusUrl.searchParams.set("type", "status"); // Differentiate from TwiML requests
|
|
417
|
-
|
|
418
|
-
// Store TwiML content if provided (for notify mode)
|
|
419
|
-
// We now serve it from the webhook endpoint instead of sending inline
|
|
420
|
-
if (input.inlineTwiml) {
|
|
421
|
-
this.twimlStorage.set(input.callId, input.inlineTwiml);
|
|
422
|
-
this.notifyCalls.add(input.callId);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Build request params - always use URL-based TwiML.
|
|
426
|
-
// Twilio silently ignores `StatusCallback` when using the inline `Twiml` parameter.
|
|
427
|
-
const params: Record<string, string | string[]> = {
|
|
428
|
-
To: input.to,
|
|
429
|
-
From: input.from,
|
|
430
|
-
Url: url.toString(), // TwiML serving endpoint
|
|
431
|
-
StatusCallback: statusUrl.toString(), // Separate status callback endpoint
|
|
432
|
-
StatusCallbackEvent: ["initiated", "ringing", "answered", "completed"],
|
|
433
|
-
Timeout: "30",
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
const result = await this.apiRequest<TwilioCallResponse>(
|
|
437
|
-
"/Calls.json",
|
|
438
|
-
params,
|
|
439
|
-
);
|
|
440
|
-
|
|
441
|
-
this.callWebhookUrls.set(result.sid, url.toString());
|
|
442
|
-
|
|
443
|
-
return {
|
|
444
|
-
providerCallId: result.sid,
|
|
445
|
-
status: result.status === "queued" ? "queued" : "initiated",
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Hang up a call via Twilio API.
|
|
451
|
-
*/
|
|
452
|
-
async hangupCall(input: HangupCallInput): Promise<void> {
|
|
453
|
-
this.deleteStoredTwimlForProviderCall(input.providerCallId);
|
|
454
|
-
|
|
455
|
-
this.callWebhookUrls.delete(input.providerCallId);
|
|
456
|
-
|
|
457
|
-
await this.apiRequest(
|
|
458
|
-
`/Calls/${input.providerCallId}.json`,
|
|
459
|
-
{ Status: "completed" },
|
|
460
|
-
{ allowNotFound: true },
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Play TTS audio via Twilio.
|
|
466
|
-
*
|
|
467
|
-
* Two modes:
|
|
468
|
-
* 1. Core TTS + Media Streams: If TTS provider and media stream are available,
|
|
469
|
-
* generates audio via core TTS and streams it through WebSocket (preferred).
|
|
470
|
-
* 2. TwiML <Say>: Falls back to Twilio's native TTS with Polly voices.
|
|
471
|
-
* Note: This may not work on all Twilio accounts.
|
|
472
|
-
*/
|
|
473
|
-
async playTts(input: PlayTtsInput): Promise<void> {
|
|
474
|
-
// Try telephony TTS via media stream first (if configured)
|
|
475
|
-
const streamSid = this.callStreamMap.get(input.providerCallId);
|
|
476
|
-
if (this.ttsProvider && this.mediaStreamHandler && streamSid) {
|
|
477
|
-
try {
|
|
478
|
-
await this.playTtsViaStream(input.text, streamSid);
|
|
479
|
-
return;
|
|
480
|
-
} catch (err) {
|
|
481
|
-
console.warn(
|
|
482
|
-
`[voice-call] Telephony TTS failed, falling back to Twilio <Say>:`,
|
|
483
|
-
err instanceof Error ? err.message : err,
|
|
484
|
-
);
|
|
485
|
-
// Fall through to TwiML <Say> fallback
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// Fall back to TwiML <Say> (may not work on all accounts)
|
|
490
|
-
const webhookUrl = this.callWebhookUrls.get(input.providerCallId);
|
|
491
|
-
if (!webhookUrl) {
|
|
492
|
-
throw new Error(
|
|
493
|
-
"Missing webhook URL for this call (provider state not initialized)",
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
console.warn(
|
|
498
|
-
"[voice-call] Using TwiML <Say> fallback - telephony TTS not configured or media stream not active",
|
|
499
|
-
);
|
|
500
|
-
|
|
501
|
-
const pollyVoice = mapVoiceToPolly(input.voice);
|
|
502
|
-
const twiml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
503
|
-
<Response>
|
|
504
|
-
<Say voice="${pollyVoice}" language="${input.locale || "en-US"}">${escapeXml(input.text)}</Say>
|
|
505
|
-
<Gather input="speech" speechTimeout="auto" action="${escapeXml(webhookUrl)}" method="POST">
|
|
506
|
-
<Say>.</Say>
|
|
507
|
-
</Gather>
|
|
508
|
-
</Response>`;
|
|
509
|
-
|
|
510
|
-
await this.apiRequest(`/Calls/${input.providerCallId}.json`, {
|
|
511
|
-
Twiml: twiml,
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* Play TTS via core TTS and Twilio Media Streams.
|
|
517
|
-
* Generates audio with core TTS, converts to mu-law, and streams via WebSocket.
|
|
518
|
-
* Uses a queue to serialize playback and prevent overlapping audio.
|
|
519
|
-
*/
|
|
520
|
-
private async playTtsViaStream(
|
|
521
|
-
text: string,
|
|
522
|
-
streamSid: string,
|
|
523
|
-
): Promise<void> {
|
|
524
|
-
if (!this.ttsProvider || !this.mediaStreamHandler) {
|
|
525
|
-
throw new Error("TTS provider and media stream handler required");
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// Stream audio in 20ms chunks (160 bytes at 8kHz mu-law)
|
|
529
|
-
const CHUNK_SIZE = 160;
|
|
530
|
-
const CHUNK_DELAY_MS = 20;
|
|
531
|
-
|
|
532
|
-
const handler = this.mediaStreamHandler;
|
|
533
|
-
const ttsProvider = this.ttsProvider;
|
|
534
|
-
await handler.queueTts(streamSid, async (signal) => {
|
|
535
|
-
// Generate audio with core TTS (returns mu-law at 8kHz)
|
|
536
|
-
const muLawAudio = await ttsProvider.synthesizeForTelephony(text);
|
|
537
|
-
for (const chunk of chunkAudio(muLawAudio, CHUNK_SIZE)) {
|
|
538
|
-
if (signal.aborted) break;
|
|
539
|
-
handler.sendAudio(streamSid, chunk);
|
|
540
|
-
|
|
541
|
-
// Pace the audio to match real-time playback
|
|
542
|
-
await new Promise((resolve) => setTimeout(resolve, CHUNK_DELAY_MS));
|
|
543
|
-
if (signal.aborted) break;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
if (!signal.aborted) {
|
|
547
|
-
// Send a mark to track when audio finishes
|
|
548
|
-
handler.sendMark(streamSid, `tts-${Date.now()}`);
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Start listening for speech via Twilio <Gather>.
|
|
555
|
-
*/
|
|
556
|
-
async startListening(input: StartListeningInput): Promise<void> {
|
|
557
|
-
const webhookUrl = this.callWebhookUrls.get(input.providerCallId);
|
|
558
|
-
if (!webhookUrl) {
|
|
559
|
-
throw new Error(
|
|
560
|
-
"Missing webhook URL for this call (provider state not initialized)",
|
|
561
|
-
);
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
const twiml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
565
|
-
<Response>
|
|
566
|
-
<Gather input="speech" speechTimeout="auto" language="${input.language || "en-US"}" action="${escapeXml(webhookUrl)}" method="POST">
|
|
567
|
-
</Gather>
|
|
568
|
-
</Response>`;
|
|
569
|
-
|
|
570
|
-
await this.apiRequest(`/Calls/${input.providerCallId}.json`, {
|
|
571
|
-
Twiml: twiml,
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* Stop listening - for Twilio this is a no-op as <Gather> auto-ends.
|
|
577
|
-
*/
|
|
578
|
-
async stopListening(_input: StopListeningInput): Promise<void> {
|
|
579
|
-
// Twilio's <Gather> automatically stops on speech end
|
|
580
|
-
// No explicit action needed
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
// -----------------------------------------------------------------------------
|
|
585
|
-
// Twilio-specific types
|
|
586
|
-
// -----------------------------------------------------------------------------
|
|
587
|
-
|
|
588
|
-
interface TwilioCallResponse {
|
|
589
|
-
sid: string;
|
|
590
|
-
status: string;
|
|
591
|
-
direction: string;
|
|
592
|
-
from: string;
|
|
593
|
-
to: string;
|
|
594
|
-
uri: string;
|
|
595
|
-
}
|