flow_chat 0.9.0 → 0.10.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/pages.yml +43 -0
  3. data/CHANGELOG.md +26 -0
  4. data/README.md +166 -295
  5. data/Rakefile +12 -1
  6. data/SECURITY.md +1 -1
  7. data/docs/architecture.md +52 -479
  8. data/docs/async-background-processing.md +31 -265
  9. data/docs/configuration.md +106 -613
  10. data/docs/factory-pattern.md +27 -324
  11. data/docs/gateway-context-variables.md +140 -143
  12. data/docs/gateway-development.md +86 -650
  13. data/docs/getting-started.md +40 -379
  14. data/docs/instrumentation.md +88 -279
  15. data/docs/platforms/instagram.md +278 -0
  16. data/docs/platforms/messenger.md +205 -0
  17. data/docs/platforms/telegram.md +47 -951
  18. data/docs/platforms/ussd.md +38 -653
  19. data/docs/platforms/whatsapp.md +73 -1321
  20. data/docs/superpowers/plans/2026-07-09-inbound-media-support.md +732 -0
  21. data/docs/superpowers/plans/2026-07-09-inbound-media-support.md.tasks.json +58 -0
  22. data/docs/superpowers/plans/2026-08-10-messenger-instagram.md +4064 -0
  23. data/docs/superpowers/plans/2026-08-10-messenger-instagram.md.tasks.json +226 -0
  24. data/docs/superpowers/plans/2026-08-16-unified-choice-resolution.md +972 -0
  25. data/docs/superpowers/plans/2026-08-16-unified-choice-resolution.md.tasks.json +88 -0
  26. data/docs/superpowers/specs/2026-07-09-inbound-media-support-design.md +195 -0
  27. data/docs/superpowers/specs/2026-08-10-messenger-instagram-design.md +391 -0
  28. data/docs/testing.md +26 -297
  29. data/examples/http_controller.rb +12 -10
  30. data/examples/intercom_configuration_example.rb +19 -24
  31. data/examples/intercom_controller.rb +8 -20
  32. data/examples/multi_tenant_whatsapp_controller.rb +61 -166
  33. data/examples/simulator_controller.rb +0 -1
  34. data/examples/ussd_controller.rb +86 -158
  35. data/examples/whatsapp_controller.rb +16 -15
  36. data/examples/whatsapp_media_examples.rb +27 -79
  37. data/lib/flow_chat/app.rb +129 -11
  38. data/lib/flow_chat/choice_titles.rb +95 -0
  39. data/lib/flow_chat/config.rb +124 -1
  40. data/lib/flow_chat/delivery_error.rb +9 -0
  41. data/lib/flow_chat/http/configuration_error.rb +9 -0
  42. data/lib/flow_chat/http/gateway/simple.rb +24 -4
  43. data/lib/flow_chat/http/middleware/choice_mapper.rb +94 -0
  44. data/lib/flow_chat/input.rb +86 -0
  45. data/lib/flow_chat/instagram/client.rb +32 -0
  46. data/lib/flow_chat/instagram/configuration.rb +147 -0
  47. data/lib/flow_chat/instagram/configuration_error.rb +7 -0
  48. data/lib/flow_chat/instagram/gateway/send_api.rb +63 -0
  49. data/lib/flow_chat/instagram/middleware/choice_mapper.rb +22 -0
  50. data/lib/flow_chat/instagram/renderer.rb +23 -0
  51. data/lib/flow_chat/instrumentation/metrics_collector.rb +6 -1
  52. data/lib/flow_chat/instrumentation.rb +160 -1
  53. data/lib/flow_chat/intercom/client.rb +34 -28
  54. data/lib/flow_chat/intercom/configuration.rb +2 -49
  55. data/lib/flow_chat/intercom/configuration_error.rb +9 -0
  56. data/lib/flow_chat/intercom/gateway/intercom_api.rb +81 -57
  57. data/lib/flow_chat/intercom/middleware/choice_mapper.rb +101 -0
  58. data/lib/flow_chat/intercom/renderer.rb +57 -5
  59. data/lib/flow_chat/media.rb +121 -0
  60. data/lib/flow_chat/messenger/client.rb +264 -0
  61. data/lib/flow_chat/messenger/configuration.rb +103 -0
  62. data/lib/flow_chat/messenger/configuration_error.rb +9 -0
  63. data/lib/flow_chat/messenger/gateway/send_api.rb +42 -0
  64. data/lib/flow_chat/messenger/middleware/choice_mapper.rb +185 -0
  65. data/lib/flow_chat/messenger/renderer.rb +150 -0
  66. data/lib/flow_chat/meta/challenge.rb +24 -0
  67. data/lib/flow_chat/meta/choice_ladder.rb +37 -0
  68. data/lib/flow_chat/meta/configuration_error.rb +7 -0
  69. data/lib/flow_chat/meta/gateway_identity.rb +38 -0
  70. data/lib/flow_chat/meta/messaging_gateway.rb +468 -0
  71. data/lib/flow_chat/meta/signature.rb +30 -0
  72. data/lib/flow_chat/meta/signature_validation.rb +66 -0
  73. data/lib/flow_chat/meta/webhook_verification.rb +43 -0
  74. data/lib/flow_chat/named_configuration.rb +65 -0
  75. data/lib/flow_chat/prompt.rb +13 -16
  76. data/lib/flow_chat/renderers/markdown_support.rb +109 -0
  77. data/lib/flow_chat/security.rb +76 -0
  78. data/lib/flow_chat/session/middleware.rb +11 -2
  79. data/lib/flow_chat/simulator/controller.rb +31 -15
  80. data/lib/flow_chat/simulator/views/simulator.html.erb +184 -20
  81. data/lib/flow_chat/telegram/client.rb +47 -4
  82. data/lib/flow_chat/telegram/configuration.rb +2 -42
  83. data/lib/flow_chat/telegram/configuration_error.rb +9 -0
  84. data/lib/flow_chat/telegram/gateway/bot_api.rb +46 -28
  85. data/lib/flow_chat/telegram/middleware/choice_mapper.rb +77 -16
  86. data/lib/flow_chat/telegram/renderer.rb +10 -2
  87. data/lib/flow_chat/text_truncator.rb +75 -0
  88. data/lib/flow_chat/ussd/middleware/choice_mapper.rb +10 -0
  89. data/lib/flow_chat/version.rb +1 -1
  90. data/lib/flow_chat/whatsapp/client.rb +14 -7
  91. data/lib/flow_chat/whatsapp/configuration.rb +12 -51
  92. data/lib/flow_chat/whatsapp/configuration_error.rb +9 -0
  93. data/lib/flow_chat/whatsapp/gateway/cloud_api.rb +254 -203
  94. data/lib/flow_chat/whatsapp/middleware/choice_mapper.rb +144 -57
  95. data/lib/flow_chat/whatsapp/renderer.rb +121 -60
  96. data/lib/flow_chat.rb +0 -10
  97. data/site/.nojekyll +0 -0
  98. data/site/.og-card.html +89 -0
  99. data/site/favicon.svg +6 -0
  100. data/site/index.html +209 -0
  101. data/site/og.png +0 -0
  102. metadata +51 -3
  103. data/lib/flow_chat/whatsapp/id_generator.rb +0 -124
@@ -0,0 +1,58 @@
1
+ {
2
+ "planPath": "docs/superpowers/plans/2026-07-09-inbound-media-support.md",
3
+ "tasks": [
4
+ {
5
+ "id": 1,
6
+ "subject": "Task 1: FlowChat::Media value object",
7
+ "status": "completed",
8
+ "description": "**Goal:** Value object wrapping one inbound media item with metadata + per-platform url/download.\n\n```json:metadata\n{\"files\": [\"lib/flow_chat/media.rb\", \"test/unit/media_test.rb\"], \"verifyCommand\": \"ruby -Itest test/unit/media_test.rb -v\", \"acceptanceCriteria\": [\"metadata readers\", \"url/download dispatch per platform\", \"autoloads via Zeitwerk\"], \"requiresUserVerification\": false}\n```"
9
+ },
10
+ {
11
+ "id": 2,
12
+ "subject": "Task 2: Telegram client media download",
13
+ "status": "completed",
14
+ "description": "**Goal:** Add get_file, file_url, download_file to Telegram client for inbound media.\n\n```json:metadata\n{\"files\": [\"lib/flow_chat/telegram/client.rb\", \"test/unit/telegram/client_test.rb\"], \"verifyCommand\": \"ruby -Itest test/unit/telegram/client_test.rb -v\", \"acceptanceCriteria\": [\"get_file\", \"file_url\", \"download_file\"], \"requiresUserVerification\": false}\n```"
15
+ },
16
+ {
17
+ "id": 3,
18
+ "subject": "Task 3: Wire App to expose inbound media/location/contact",
19
+ "status": "completed",
20
+ "blockedBy": [1, 2],
21
+ "description": "**Goal:** Replace nil stubs; normalize single/array media into media_items, media as first-item convenience.\n\n```json:metadata\n{\"files\": [\"lib/flow_chat/app.rb\", \"test/integration/media_support_test.rb\"], \"verifyCommand\": \"ruby -Itest test/integration/media_support_test.rb -v\", \"acceptanceCriteria\": [\"media_items normalizes single/array/none\", \"media is first item\", \"location/contact/contact_name exposed\", \"correct platform client\"], \"requiresUserVerification\": false}\n```"
22
+ },
23
+ {
24
+ "id": 4,
25
+ "subject": "Task 4: Intercom gateway inbound media parsing",
26
+ "status": "completed",
27
+ "blockedBy": [3],
28
+ "description": "**Goal:** Parse Intercom attachments (array) into request.media, supporting multiple per message.\n\n```json:metadata\n{\"files\": [\"lib/flow_chat/intercom/gateway/intercom_api.rb\", \"test/unit/intercom/gateway/intercom_api_test.rb\"], \"verifyCommand\": \"ruby -Itest test/unit/intercom/gateway/intercom_api_test.rb -v\", \"acceptanceCriteria\": [\"attachments array parsed\", \"content_type mapping\", \"media sentinel input set\", \"text unaffected\"], \"requiresUserVerification\": false}\n```"
29
+ },
30
+ {
31
+ "id": 5,
32
+ "subject": "Task 5: HTTP gateway inbound media parsing",
33
+ "status": "completed",
34
+ "blockedBy": [3],
35
+ "description": "**Goal:** Accept inbound media via HTTP params (media_url/media_type/mime_type).\n\n```json:metadata\n{\"files\": [\"lib/flow_chat/http/gateway/simple.rb\", \"test/unit/http/gateway/simple_test.rb\"], \"verifyCommand\": \"ruby -Itest test/unit/http/gateway/simple_test.rb -v\", \"acceptanceCriteria\": [\"media_url sets request.media\", \"media sentinel when no text\", \"text precedence preserved\"], \"requiresUserVerification\": false}\n```"
36
+ },
37
+ {
38
+ "id": 6,
39
+ "subject": "Task 6: Full suite regression + docs",
40
+ "status": "completed",
41
+ "blockedBy": [4, 5],
42
+ "description": "**Goal:** Confirm full suite green; document inbound media API.\n\n```json:metadata\n{\"files\": [\"README.md\"], \"verifyCommand\": \"bundle exec rake test\", \"acceptanceCriteria\": [\"full suite green\", \"docs updated\"], \"requiresUserVerification\": false}\n```"
43
+ },
44
+ {
45
+ "id": 7,
46
+ "subject": "Task 7: Normalize FlowChat::Media#type across platforms",
47
+ "status": "completed",
48
+ "description": "**Goal:** Follow-up from final review. media.type returns canonical type; raw_type returns native. Committed 51ae2f8."
49
+ },
50
+ {
51
+ "id": 8,
52
+ "subject": "Task 8: Capture inbound captions (Telegram + Intercom)",
53
+ "status": "completed",
54
+ "description": "**Goal:** Follow-up from final review. Telegram message caption + Intercom body captured as media caption. Committed d58a0f5."
55
+ }
56
+ ],
57
+ "lastUpdated": "2026-07-09"
58
+ }