collavre 0.22.0 → 0.24.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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/assets/images/collavre/landing/interface-en-dark.png +0 -0
  4. data/app/assets/images/collavre/landing/interface-en.png +0 -0
  5. data/app/assets/images/collavre/landing/interface-ko-dark.png +0 -0
  6. data/app/assets/images/collavre/landing/interface-ko.png +0 -0
  7. data/app/assets/stylesheets/collavre/actiontext.css +251 -90
  8. data/app/assets/stylesheets/collavre/code_highlight.css +7 -201
  9. data/app/assets/stylesheets/collavre/comments_popup.css +158 -61
  10. data/app/assets/stylesheets/collavre/creatives.css +11 -2
  11. data/app/assets/stylesheets/collavre/landing.css +92 -0
  12. data/app/assets/stylesheets/collavre/modal_dialog.css +32 -0
  13. data/app/assets/stylesheets/collavre/popup.css +4 -2
  14. data/app/assets/stylesheets/collavre/tables.css +91 -0
  15. data/app/channels/collavre/inbox_badge_channel.rb +30 -0
  16. data/app/controllers/collavre/admin/settings_controller.rb +52 -67
  17. data/app/controllers/collavre/api/v1/agents_controller.rb +17 -188
  18. data/app/controllers/collavre/api/v1/base_controller.rb +9 -27
  19. data/app/controllers/collavre/api/v1/mobile/agent_events_controller.rb +224 -0
  20. data/app/controllers/collavre/api/v1/mobile/base_controller.rb +95 -0
  21. data/app/controllers/collavre/api/v1/mobile/devices_controller.rb +31 -0
  22. data/app/controllers/collavre/api/v1/mobile/voice_commands_controller.rb +25 -0
  23. data/app/controllers/collavre/attachments_controller.rb +13 -3
  24. data/app/controllers/collavre/concerns/slide_viewable.rb +8 -32
  25. data/app/controllers/collavre/creatives_controller.rb +47 -103
  26. data/app/controllers/collavre/inbox_items_controller.rb +10 -4
  27. data/app/controllers/collavre/landing_controller.rb +5 -2
  28. data/app/controllers/collavre/tasks_controller.rb +13 -4
  29. data/app/controllers/collavre/topics_controller.rb +54 -1
  30. data/app/controllers/collavre/typo_corrections_controller.rb +39 -0
  31. data/app/controllers/concerns/collavre/api/authenticatable.rb +40 -0
  32. data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +16 -1
  33. data/app/controllers/concerns/collavre/users_controller/registration.rb +41 -1
  34. data/app/errors/collavre/api_error.rb +20 -0
  35. data/app/helpers/collavre/application_helper.rb +1 -0
  36. data/app/helpers/collavre/creatives_helper.rb +30 -8
  37. data/app/javascript/collavre.js +2 -0
  38. data/app/javascript/components/ImageResizer.jsx +9 -3
  39. data/app/javascript/components/InlineLexicalEditor.jsx +157 -72
  40. data/app/javascript/components/__tests__/creative_tree_row_parent_id.test.js +87 -0
  41. data/app/javascript/components/creative_tree_row.js +28 -5
  42. data/app/javascript/components/plugins/list_tab_indent_plugin.jsx +16 -0
  43. data/app/javascript/components/plugins/markdown_shortcuts_plugin.jsx +15 -4
  44. data/app/javascript/components/plugins/table_hover_actions_plugin.jsx +405 -0
  45. data/app/javascript/controllers/__tests__/inbox_badge_controller.test.js +73 -0
  46. data/app/javascript/controllers/__tests__/search_popup_controller.test.js +104 -0
  47. data/app/javascript/controllers/__tests__/topic_list_controller.test.js +82 -0
  48. data/app/javascript/controllers/comment_controller.js +5 -4
  49. data/app/javascript/controllers/comment_version_controller.js +2 -1
  50. data/app/javascript/controllers/comments/__tests__/form_controller_double_submit.test.js +159 -0
  51. data/app/javascript/controllers/comments/__tests__/presence_controller.test.js +3 -2
  52. data/app/javascript/controllers/comments/__tests__/topics_controller_delete.test.js +94 -0
  53. data/app/javascript/controllers/comments/__tests__/topics_controller_topic_list.test.js +61 -0
  54. data/app/javascript/controllers/comments/form_controller.js +21 -5
  55. data/app/javascript/controllers/comments/list_controller.js +18 -17
  56. data/app/javascript/controllers/comments/presence_controller.js +2 -1
  57. data/app/javascript/controllers/comments/topics_controller.js +61 -8
  58. data/app/javascript/controllers/common_popup_controller.js +2 -2
  59. data/app/javascript/controllers/creatives/__tests__/tree_controller.test.js +150 -0
  60. data/app/javascript/controllers/creatives/import_controller.js +2 -1
  61. data/app/javascript/controllers/creatives/select_mode_controller.js +2 -1
  62. data/app/javascript/controllers/creatives/tree_controller.js +142 -1
  63. data/app/javascript/controllers/image_lightbox_controller.js +2 -1
  64. data/app/javascript/controllers/inbox_badge_controller.js +33 -0
  65. data/app/javascript/controllers/index.js +7 -1
  66. data/app/javascript/controllers/search_popup_controller.js +17 -1
  67. data/app/javascript/controllers/share_modal_controller.js +4 -3
  68. data/app/javascript/controllers/topic_list_controller.js +78 -0
  69. data/app/javascript/controllers/topic_search_controller.js +2 -1
  70. data/app/javascript/creatives/drag_drop/event_handlers.js +14 -5
  71. data/app/javascript/creatives/topic_move_members_popup.js +156 -0
  72. data/app/javascript/creatives/tree_renderer.js +11 -0
  73. data/app/javascript/lib/__tests__/common_popup_bounds.test.js +58 -0
  74. data/app/javascript/lib/__tests__/turbo_confirm.test.js +81 -0
  75. data/app/javascript/lib/__tests__/typo_correction.test.js +192 -0
  76. data/app/javascript/lib/api/__tests__/api_error.test.js +96 -0
  77. data/app/javascript/lib/api/__tests__/queue_manager.test.js +88 -1
  78. data/app/javascript/lib/api/api_error.js +108 -0
  79. data/app/javascript/lib/api/queue_manager.js +38 -4
  80. data/app/javascript/lib/common_popup.js +42 -10
  81. data/app/javascript/lib/editor/__tests__/code_edit_view_token_parity.test.js +121 -0
  82. data/app/javascript/lib/editor/__tests__/code_language_roundtrip.test.js +152 -0
  83. data/app/javascript/lib/editor/__tests__/code_languages.test.js +93 -0
  84. data/app/javascript/lib/editor/code_languages.js +173 -0
  85. data/app/javascript/lib/editor/code_token_theme.js +41 -0
  86. data/app/javascript/lib/lexical/__tests__/code_block_toggle.test.js +326 -0
  87. data/app/javascript/lib/lexical/__tests__/code_fence_shortcut.test.js +179 -0
  88. data/app/javascript/lib/lexical/__tests__/image_focus.test.js +139 -0
  89. data/app/javascript/lib/lexical/__tests__/list_tab_indent.test.js +633 -0
  90. data/app/javascript/lib/lexical/__tests__/markdown_serialize.test.js +627 -0
  91. data/app/javascript/lib/lexical/__tests__/minimize_html.test.js +20 -1
  92. data/app/javascript/lib/lexical/__tests__/selection_boundary.test.js +88 -0
  93. data/app/javascript/lib/lexical/__tests__/table_transformer.test.js +163 -0
  94. data/app/javascript/lib/lexical/__tests__/trailing_paragraph.test.js +104 -0
  95. data/app/javascript/lib/lexical/code_block_toggle.js +130 -0
  96. data/app/javascript/lib/lexical/code_fence_shortcut.js +60 -0
  97. data/app/javascript/lib/lexical/list_tab_indent.js +210 -0
  98. data/app/javascript/lib/lexical/markdown_serialize.js +320 -0
  99. data/app/javascript/lib/lexical/selection_boundary.js +58 -0
  100. data/app/javascript/lib/lexical/table_transformer.js +182 -0
  101. data/app/javascript/lib/lexical/trailing_paragraph.js +29 -0
  102. data/app/javascript/lib/turbo_confirm.js +46 -0
  103. data/app/javascript/lib/typo_correction.js +146 -0
  104. data/app/javascript/lib/utils/__tests__/confirm_dialog.test.js +88 -0
  105. data/app/javascript/lib/utils/__tests__/dialog.test.js +92 -0
  106. data/app/javascript/lib/utils/__tests__/markdown.test.js +153 -0
  107. data/app/javascript/lib/utils/__tests__/sanitize_description.test.js +68 -0
  108. data/app/javascript/lib/utils/__tests__/table_download.test.js +93 -0
  109. data/app/javascript/lib/utils/confirm_dialog.js +10 -0
  110. data/app/javascript/lib/utils/dialog.js +300 -0
  111. data/app/javascript/lib/utils/markdown.js +154 -67
  112. data/app/javascript/lib/utils/sanitize_description.js +31 -0
  113. data/app/javascript/lib/utils/table_download.js +15 -0
  114. data/app/javascript/modules/__tests__/creative_inline_payload.test.js +231 -0
  115. data/app/javascript/modules/__tests__/creative_save_queue.test.js +228 -0
  116. data/app/javascript/modules/__tests__/creative_tree_dom.test.js +425 -0
  117. data/app/javascript/modules/__tests__/typo_corrector.test.js +365 -0
  118. data/app/javascript/modules/creative_inline_payload.js +86 -0
  119. data/app/javascript/modules/creative_row_editor.js +231 -471
  120. data/app/javascript/modules/creative_row_editor_helpers.js +76 -0
  121. data/app/javascript/modules/creative_save_queue.js +95 -0
  122. data/app/javascript/modules/creative_tree_dom.js +260 -0
  123. data/app/javascript/modules/export_to_markdown.js +2 -1
  124. data/app/javascript/modules/lexical_inline_editor.jsx +2 -1
  125. data/app/javascript/modules/slide_view.js +11 -2
  126. data/app/javascript/modules/typo_corrector.js +534 -0
  127. data/app/jobs/collavre/ai_agent_job.rb +7 -4
  128. data/app/jobs/collavre/compress_job.rb +6 -2
  129. data/app/jobs/collavre/permission_cache_job.rb +20 -2
  130. data/app/jobs/collavre/trigger_loop_check_job.rb +20 -3
  131. data/app/jobs/collavre/update_mcp_tools_job.rb +17 -0
  132. data/app/models/collavre/channel.rb +16 -0
  133. data/app/models/collavre/comment/approvable.rb +16 -0
  134. data/app/models/collavre/comment/broadcastable.rb +46 -7
  135. data/app/models/collavre/comment/notifiable.rb +15 -5
  136. data/app/models/collavre/comment.rb +87 -32
  137. data/app/models/collavre/comment_version.rb +1 -1
  138. data/app/models/collavre/creative/describable.rb +104 -19
  139. data/app/models/collavre/creative/linkable.rb +9 -0
  140. data/app/models/collavre/creative/permissible.rb +97 -49
  141. data/app/models/collavre/creative.rb +73 -5
  142. data/app/models/collavre/creative_share.rb +78 -26
  143. data/app/models/collavre/inbox_item.rb +2 -2
  144. data/app/models/collavre/task.rb +27 -0
  145. data/app/models/collavre/user.rb +90 -10
  146. data/app/models/concerns/collavre/indexed_json_columns.rb +58 -0
  147. data/app/services/collavre/agent_type_classifier.rb +23 -0
  148. data/app/services/collavre/ai_agent/a2a_dispatcher.rb +4 -0
  149. data/app/services/collavre/ai_agent/message_builder.rb +1 -1
  150. data/app/services/collavre/ai_agent/session_provisioner.rb +126 -0
  151. data/app/services/collavre/ai_agent/task_claim_service.rb +96 -0
  152. data/app/services/collavre/ai_client.rb +81 -12
  153. data/app/services/collavre/auto_theme_generator.rb +15 -11
  154. data/app/services/collavre/creatives/children_index.rb +86 -0
  155. data/app/services/collavre/creatives/comment_badge_index.rb +73 -0
  156. data/app/services/collavre/creatives/creative_tree_serializer.rb +122 -0
  157. data/app/services/collavre/creatives/effective_creative_resolution.rb +37 -0
  158. data/app/services/collavre/creatives/index_query.rb +85 -16
  159. data/app/services/collavre/creatives/permission_checker.rb +1 -1
  160. data/app/services/collavre/creatives/permission_filter.rb +144 -17
  161. data/app/services/collavre/creatives/tree_builder.rb +107 -78
  162. data/app/services/collavre/gemini_parent_recommender.rb +1 -1
  163. data/app/services/collavre/http_client.rb +119 -0
  164. data/app/services/collavre/inbox_reply_service.rb +5 -0
  165. data/app/services/collavre/link_preview_fetcher.rb +129 -38
  166. data/app/services/collavre/markdown_converter.rb +13 -3
  167. data/app/services/collavre/markdown_importer.rb +30 -6
  168. data/app/services/collavre/mobile/event_summarizer.rb +40 -0
  169. data/app/services/collavre/orchestration/agent_context_builder.rb +1 -15
  170. data/app/services/collavre/orchestration/agent_orchestrator.rb +34 -8
  171. data/app/services/collavre/orchestration/arbiter.rb +16 -0
  172. data/app/services/collavre/orchestration/matcher.rb +79 -4
  173. data/app/services/collavre/orchestration/policy_resolver.rb +4 -3
  174. data/app/services/collavre/orchestration/stuck_detector.rb +141 -34
  175. data/app/services/collavre/system_events/context_builder.rb +1 -14
  176. data/app/services/collavre/tools/creative_batch_service.rb +3 -2
  177. data/app/services/collavre/tools/creative_create_service.rb +8 -8
  178. data/app/services/collavre/tools/creative_update_service.rb +23 -8
  179. data/app/services/collavre/tools/preview_attach_service.rb +5 -7
  180. data/app/services/collavre/typo_corrector.rb +188 -0
  181. data/app/views/collavre/comments/_comment.html.erb +9 -4
  182. data/app/views/collavre/comments/_comments_popup.html.erb +25 -4
  183. data/app/views/collavre/creatives/_inline_edit_form.html.erb +10 -0
  184. data/app/views/collavre/creatives/_topic_move_members_modal.html.erb +42 -0
  185. data/app/views/collavre/creatives/index.html.erb +14 -1
  186. data/app/views/collavre/creatives/slide_view.html.erb +1 -1
  187. data/app/views/collavre/landing/show.html.erb +52 -10
  188. data/app/views/collavre/users/show.html.erb +3 -0
  189. data/app/views/collavre/users/typo_correction.html.erb +50 -0
  190. data/app/views/layouts/collavre/slide.html.erb +1 -0
  191. data/config/locales/comments.en.yml +16 -0
  192. data/config/locales/comments.ko.yml +16 -0
  193. data/config/locales/creatives.en.yml +6 -0
  194. data/config/locales/creatives.ko.yml +5 -0
  195. data/config/locales/integrations.en.yml +1 -1
  196. data/config/locales/integrations.ko.yml +1 -1
  197. data/config/locales/landing.en.yml +22 -10
  198. data/config/locales/landing.ko.yml +22 -10
  199. data/config/locales/mobile.en.yml +16 -0
  200. data/config/locales/mobile.ko.yml +16 -0
  201. data/config/locales/orchestration.en.yml +1 -0
  202. data/config/locales/orchestration.ko.yml +1 -0
  203. data/config/locales/users.en.yml +15 -0
  204. data/config/locales/users.ko.yml +15 -0
  205. data/config/routes.rb +13 -0
  206. data/db/migrate/20260120045354_encrypt_oauth_tokens.rb +13 -4
  207. data/db/migrate/20260612000000_add_topic_concurrency_defer_to_comments.rb +38 -0
  208. data/db/migrate/20260617090000_add_typo_correction_settings_to_users.rb +18 -0
  209. data/db/migrate/20260702000001_enforce_system_settings_key_not_null.rb +9 -0
  210. data/db/migrate/20260702000002_add_creative_index_and_fk_to_tags.rb +11 -0
  211. data/db/migrate/20260702000003_add_creative_type_index_to_labels.rb +10 -0
  212. data/db/migrate/20260702000004_add_creative_created_at_index_to_comments.rb +10 -0
  213. data/db/migrate/20260702000005_promote_channel_config_index_columns.rb +76 -0
  214. data/db/migrate/20260713000001_add_comments_count_to_creatives.rb +20 -0
  215. data/db/migrate/20260713000002_add_comment_versions_count_to_comments.rb +20 -0
  216. data/db/migrate/20260715000000_change_creatives_description_to_plain_text.rb +16 -0
  217. data/db/seeds.rb +51 -0
  218. data/lib/collavre/version.rb +1 -1
  219. data/lib/generators/collavre/install/install_generator.rb +1 -0
  220. metadata +96 -2
  221. data/app/services/collavre/tools/description_normalizable.rb +0 -16
@@ -0,0 +1,76 @@
1
+ class PromoteChannelConfigIndexColumns < ActiveRecord::Migration[8.1]
2
+ # The channels uniqueness guarantees were enforced by UNIQUE indexes over
3
+ # JSON expressions: `json_extract(config, '$.repo_full_name')` on SQLite and
4
+ # `config->>'repo_full_name'` on PostgreSQL. Those expressions serialize
5
+ # differently per adapter, so schema.rb (dumped from the SQLite dev DB)
6
+ # carries json_extract, which is not a PostgreSQL function -- `db:schema:load`
7
+ # on PostgreSQL crashes. Promote the extracted keys to real columns kept in
8
+ # sync from `config` (see Collavre::Channel#sync_indexed_config_columns) and
9
+ # replace the expression indexes with plain-column indexes that dump
10
+ # identically on both adapters.
11
+ def up
12
+ postgres = connection.adapter_name == "PostgreSQL"
13
+
14
+ add_column :channels, :repo_full_name, :string
15
+ add_column :channels, :pr_number, :integer
16
+ add_column :channels, :worktree_id, :string
17
+
18
+ if postgres
19
+ execute <<~SQL.squish
20
+ UPDATE channels SET
21
+ repo_full_name = config->>'repo_full_name',
22
+ pr_number = NULLIF(config->>'pr_number', '')::integer,
23
+ worktree_id = config->>'worktree_id'
24
+ SQL
25
+ else
26
+ execute <<~SQL.squish
27
+ UPDATE channels SET
28
+ repo_full_name = json_extract(config, '$.repo_full_name'),
29
+ pr_number = json_extract(config, '$.pr_number'),
30
+ worktree_id = json_extract(config, '$.worktree_id')
31
+ SQL
32
+ end
33
+
34
+ remove_index :channels, name: "index_channels_on_type_topic_repo_pr"
35
+ remove_index :channels, name: "index_channels_on_topic_preview_worktree"
36
+
37
+ add_index :channels, [ :type, :topic_id, :repo_full_name, :pr_number ],
38
+ unique: true, name: "index_channels_on_type_topic_repo_pr"
39
+ add_index :channels, [ :topic_id, :worktree_id ],
40
+ unique: true, name: "index_channels_on_topic_preview_worktree",
41
+ where: "type = 'Collavre::PreviewChannel'"
42
+ end
43
+
44
+ def down
45
+ postgres = connection.adapter_name == "PostgreSQL"
46
+
47
+ remove_index :channels, name: "index_channels_on_type_topic_repo_pr"
48
+ remove_index :channels, name: "index_channels_on_topic_preview_worktree"
49
+
50
+ remove_column :channels, :repo_full_name
51
+ remove_column :channels, :pr_number
52
+ remove_column :channels, :worktree_id
53
+
54
+ if postgres
55
+ execute <<~SQL
56
+ CREATE UNIQUE INDEX index_channels_on_type_topic_repo_pr
57
+ ON channels (type, topic_id, (config->>'repo_full_name'), (config->>'pr_number'))
58
+ SQL
59
+ execute <<~SQL
60
+ CREATE UNIQUE INDEX index_channels_on_topic_preview_worktree
61
+ ON channels (topic_id, (config->>'worktree_id'))
62
+ WHERE type = 'Collavre::PreviewChannel'
63
+ SQL
64
+ else
65
+ execute <<~SQL
66
+ CREATE UNIQUE INDEX index_channels_on_type_topic_repo_pr
67
+ ON channels (type, topic_id, json_extract(config, '$.repo_full_name'), json_extract(config, '$.pr_number'))
68
+ SQL
69
+ execute <<~SQL
70
+ CREATE UNIQUE INDEX index_channels_on_topic_preview_worktree
71
+ ON channels (topic_id, json_extract(config, '$.worktree_id'))
72
+ WHERE type = 'Collavre::PreviewChannel'
73
+ SQL
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,20 @@
1
+ class AddCommentsCountToCreatives < ActiveRecord::Migration[8.1]
2
+ def up
3
+ unless column_exists?(:creatives, :comments_count)
4
+ add_column :creatives, :comments_count, :integer, default: 0, null: false
5
+ end
6
+
7
+ # Backfill: straight COUNT (no soft-delete on comments). Matches house
8
+ # raw-SQL backfill convention.
9
+ execute <<~SQL.squish
10
+ UPDATE creatives
11
+ SET comments_count = (
12
+ SELECT COUNT(*) FROM comments WHERE comments.creative_id = creatives.id
13
+ )
14
+ SQL
15
+ end
16
+
17
+ def down
18
+ remove_column :creatives, :comments_count if column_exists?(:creatives, :comments_count)
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ class AddCommentVersionsCountToComments < ActiveRecord::Migration[8.1]
2
+ def up
3
+ unless column_exists?(:comments, :comment_versions_count)
4
+ add_column :comments, :comment_versions_count, :integer, default: 0, null: false
5
+ end
6
+
7
+ # Backfill counts only the owning :comment association (comment_id),
8
+ # NOT review_comment_id (review_versions).
9
+ execute <<~SQL.squish
10
+ UPDATE comments
11
+ SET comment_versions_count = (
12
+ SELECT COUNT(*) FROM comment_versions WHERE comment_versions.comment_id = comments.id
13
+ )
14
+ SQL
15
+ end
16
+
17
+ def down
18
+ remove_column :comments, :comment_versions_count if column_exists?(:comments, :comment_versions_count)
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ class ChangeCreativesDescriptionToPlainText < ActiveRecord::Migration[8.1]
2
+ # The original AddDescriptionToCreatives migration created the column as
3
+ # `:text, limit: 4294967295` (a MySQL LONGTEXT-style byte cap). SQLite ignores
4
+ # the limit, but it gets recorded in db/schema.rb, and `db:schema:load` then
5
+ # crashes on PostgreSQL (production) with:
6
+ # ArgumentError: No text type has byte size 4294967295.
7
+ # Postgres `text` is already unbounded, so drop the limit to keep the schema
8
+ # loadable on every adapter.
9
+ def up
10
+ change_column :creatives, :description, :text, limit: nil
11
+ end
12
+
13
+ def down
14
+ change_column :creatives, :description, :text, limit: 4294967295
15
+ end
16
+ end
data/db/seeds.rb CHANGED
@@ -17,3 +17,54 @@ module Collavre
17
17
  end
18
18
 
19
19
  Collavre::ChannelBotSeed.call
20
+
21
+ module Collavre
22
+ # Seeds the "Typo Corrector" agent. Unlike event-routed agents (e.g. the GitHub
23
+ # PR Analyzer) this agent has no routing_expression — it is never dispatched by
24
+ # comment events. It exists purely as a user-configurable holder for the LLM
25
+ # vendor/model/system_prompt that Collavre::TypoCorrector invokes directly.
26
+ module TypoCorrectorSeed
27
+ AGENT_EMAIL = "typo-corrector@collavre.local"
28
+
29
+ SYSTEM_PROMPT = <<~PROMPT
30
+ You are a typo correction engine. You receive a short piece of text the user
31
+ is currently typing and return ONLY spelling/typo fixes as a structured edit list.
32
+
33
+ Rules:
34
+ - Fix only spelling mistakes and obvious typos (transposed/missing/extra letters,
35
+ wrong jamo, mis-spaced words). Works for any language (ko, en, ja, zh, mixed).
36
+ - Do NOT rewrite style, grammar, word choice, tone, or punctuation.
37
+ - Do NOT change meaning. Do NOT translate.
38
+ - Never touch code spans, URLs, @mentions, emojis, or HTML/markdown markup.
39
+ - `original` MUST be an exact substring copied verbatim from the input text.
40
+ - Keep each edit minimal: a single word or short phrase, not a whole sentence.
41
+
42
+ Return ONLY valid JSON, no markdown, in exactly this shape:
43
+ {"edits":[{"original":"<verbatim>","suggestion":"<fixed>","reason":"spelling","confidence":0.0}]}
44
+
45
+ `confidence` is a float 0.0-1.0 for how sure you are it is a real typo.
46
+ If there are no typos, return {"edits":[]}.
47
+ PROMPT
48
+
49
+ def self.call
50
+ user = User.find_or_initialize_by(email: AGENT_EMAIL)
51
+ return user unless user.new_record?
52
+
53
+ user.assign_attributes(
54
+ name: "Typo Corrector",
55
+ password: SecureRandom.hex(32),
56
+ email_verified_at: Time.current,
57
+ searchable: false,
58
+ llm_vendor: ENV.fetch("COLLAVRE_DEFAULT_LLM_VENDOR", "gemini"),
59
+ llm_model: ENV.fetch("COLLAVRE_DEFAULT_LLM_MODEL", "gemini-3.1-flash-lite"),
60
+ system_prompt: SYSTEM_PROMPT,
61
+ tools: []
62
+ )
63
+ user.save!
64
+ Rails.logger.info "[Collavre] Typo Corrector agent ensured: #{AGENT_EMAIL}"
65
+ user
66
+ end
67
+ end
68
+ end
69
+
70
+ Collavre::TypoCorrectorSeed.call
@@ -1,3 +1,3 @@
1
1
  module Collavre
2
- VERSION = "0.22.0"
2
+ VERSION = "0.24.0"
3
3
  end
@@ -31,6 +31,7 @@ module Collavre
31
31
  say "Add to your application.css if needed:"
32
32
  say " @import 'collavre/creatives';"
33
33
  say " @import 'collavre/comments_popup';"
34
+ say " @import 'collavre/tables';"
34
35
  say " @import 'collavre/dark_mode';"
35
36
  say ""
36
37
  say "Run 'npm run build' to build assets."
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collavre
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Collavre
@@ -173,6 +173,10 @@ extra_rdoc_files: []
173
173
  files:
174
174
  - README.md
175
175
  - Rakefile
176
+ - app/assets/images/collavre/landing/interface-en-dark.png
177
+ - app/assets/images/collavre/landing/interface-en.png
178
+ - app/assets/images/collavre/landing/interface-ko-dark.png
179
+ - app/assets/images/collavre/landing/interface-ko.png
176
180
  - app/assets/stylesheets/collavre/actiontext.css
177
181
  - app/assets/stylesheets/collavre/activity_logs.css
178
182
  - app/assets/stylesheets/collavre/code_highlight.css
@@ -192,11 +196,13 @@ files:
192
196
  - app/assets/stylesheets/collavre/print.css
193
197
  - app/assets/stylesheets/collavre/search_popup.css
194
198
  - app/assets/stylesheets/collavre/slide_view.css
199
+ - app/assets/stylesheets/collavre/tables.css
195
200
  - app/assets/stylesheets/collavre/trigger_status.css
196
201
  - app/assets/stylesheets/collavre/user_menu.css
197
202
  - app/channels/collavre/agent_channel.rb
198
203
  - app/channels/collavre/comments_presence_channel.rb
199
204
  - app/channels/collavre/creatives_channel.rb
205
+ - app/channels/collavre/inbox_badge_channel.rb
200
206
  - app/channels/collavre/slide_view_channel.rb
201
207
  - app/channels/collavre/topics_channel.rb
202
208
  - app/components/collavre/autocomplete_popup_component.html.erb
@@ -216,6 +222,10 @@ files:
216
222
  - app/controllers/collavre/admin/settings_controller.rb
217
223
  - app/controllers/collavre/api/v1/agents_controller.rb
218
224
  - app/controllers/collavre/api/v1/base_controller.rb
225
+ - app/controllers/collavre/api/v1/mobile/agent_events_controller.rb
226
+ - app/controllers/collavre/api/v1/mobile/base_controller.rb
227
+ - app/controllers/collavre/api/v1/mobile/devices_controller.rb
228
+ - app/controllers/collavre/api/v1/mobile/voice_commands_controller.rb
219
229
  - app/controllers/collavre/application_controller.rb
220
230
  - app/controllers/collavre/attachments_controller.rb
221
231
  - app/controllers/collavre/calendar_events_controller.rb
@@ -248,9 +258,11 @@ files:
248
258
  - app/controllers/collavre/sessions_controller.rb
249
259
  - app/controllers/collavre/tasks_controller.rb
250
260
  - app/controllers/collavre/topics_controller.rb
261
+ - app/controllers/collavre/typo_corrections_controller.rb
251
262
  - app/controllers/collavre/user_creative_preferences_controller.rb
252
263
  - app/controllers/collavre/user_themes_controller.rb
253
264
  - app/controllers/collavre/users_controller.rb
265
+ - app/controllers/concerns/collavre/api/authenticatable.rb
254
266
  - app/controllers/concerns/collavre/comments/approval_actions.rb
255
267
  - app/controllers/concerns/collavre/comments/batch_operations.rb
256
268
  - app/controllers/concerns/collavre/comments/comment_scoping.rb
@@ -263,6 +275,7 @@ files:
263
275
  - app/controllers/concerns/collavre/users_controller/contact_management.rb
264
276
  - app/controllers/concerns/collavre/users_controller/profile_and_settings.rb
265
277
  - app/controllers/concerns/collavre/users_controller/registration.rb
278
+ - app/errors/collavre/api_error.rb
266
279
  - app/errors/collavre/approval_pending_error.rb
267
280
  - app/errors/collavre/cancelled_error.rb
268
281
  - app/helpers/collavre/application_helper.rb
@@ -274,23 +287,32 @@ files:
274
287
  - app/javascript/components/ImageResizer.jsx
275
288
  - app/javascript/components/InlineLexicalEditor.jsx
276
289
  - app/javascript/components/LinkPopup.jsx
290
+ - app/javascript/components/__tests__/creative_tree_row_parent_id.test.js
277
291
  - app/javascript/components/creative_tree_row.js
278
292
  - app/javascript/components/plugins/attachment_cleanup_plugin.jsx
279
293
  - app/javascript/components/plugins/image_upload_plugin.jsx
294
+ - app/javascript/components/plugins/list_tab_indent_plugin.jsx
280
295
  - app/javascript/components/plugins/markdown_shortcuts_plugin.jsx
296
+ - app/javascript/components/plugins/table_hover_actions_plugin.jsx
297
+ - app/javascript/controllers/__tests__/inbox_badge_controller.test.js
281
298
  - app/javascript/controllers/__tests__/link_creative_controller.test.js
282
299
  - app/javascript/controllers/__tests__/popup_menu_controller.test.js
300
+ - app/javascript/controllers/__tests__/search_popup_controller.test.js
301
+ - app/javascript/controllers/__tests__/topic_list_controller.test.js
283
302
  - app/javascript/controllers/agent_trigger_controller.js
284
303
  - app/javascript/controllers/click_target_controller.js
285
304
  - app/javascript/controllers/comment_badge_controller.js
286
305
  - app/javascript/controllers/comment_controller.js
287
306
  - app/javascript/controllers/comment_version_controller.js
307
+ - app/javascript/controllers/comments/__tests__/form_controller_double_submit.test.js
288
308
  - app/javascript/controllers/comments/__tests__/form_controller_review.test.js
289
309
  - app/javascript/controllers/comments/__tests__/list_controller_selection.test.js
290
310
  - app/javascript/controllers/comments/__tests__/popup_controller.test.js
291
311
  - app/javascript/controllers/comments/__tests__/presence_controller.test.js
292
312
  - app/javascript/controllers/comments/__tests__/review_quotes_store.test.js
313
+ - app/javascript/controllers/comments/__tests__/topics_controller_delete.test.js
293
314
  - app/javascript/controllers/comments/__tests__/topics_controller_override.test.js
315
+ - app/javascript/controllers/comments/__tests__/topics_controller_topic_list.test.js
294
316
  - app/javascript/controllers/comments/contexts_controller.js
295
317
  - app/javascript/controllers/comments/drop_trigger_controller.js
296
318
  - app/javascript/controllers/comments/form_controller.js
@@ -311,6 +333,7 @@ files:
311
333
  - app/javascript/controllers/creatives/sync_controller.js
312
334
  - app/javascript/controllers/creatives/tree_controller.js
313
335
  - app/javascript/controllers/image_lightbox_controller.js
336
+ - app/javascript/controllers/inbox_badge_controller.js
314
337
  - app/javascript/controllers/index.js
315
338
  - app/javascript/controllers/landing_video_controller.js
316
339
  - app/javascript/controllers/link_creative_controller.js
@@ -323,16 +346,23 @@ files:
323
346
  - app/javascript/controllers/share_modal_controller.js
324
347
  - app/javascript/controllers/share_user_search_controller.js
325
348
  - app/javascript/controllers/tabs_controller.js
349
+ - app/javascript/controllers/topic_list_controller.js
326
350
  - app/javascript/controllers/topic_search_controller.js
327
351
  - app/javascript/creatives/drag_drop/dom.js
328
352
  - app/javascript/creatives/drag_drop/event_handlers.js
329
353
  - app/javascript/creatives/drag_drop/indicator.js
330
354
  - app/javascript/creatives/drag_drop/operations.js
331
355
  - app/javascript/creatives/drag_drop/state.js
356
+ - app/javascript/creatives/topic_move_members_popup.js
332
357
  - app/javascript/creatives/tree_renderer.js
333
358
  - app/javascript/lib/__tests__/chat_history.test.js
359
+ - app/javascript/lib/__tests__/common_popup_bounds.test.js
334
360
  - app/javascript/lib/__tests__/html_code_block_wrapper.test.js
361
+ - app/javascript/lib/__tests__/turbo_confirm.test.js
362
+ - app/javascript/lib/__tests__/typo_correction.test.js
363
+ - app/javascript/lib/api/__tests__/api_error.test.js
335
364
  - app/javascript/lib/api/__tests__/queue_manager.test.js
365
+ - app/javascript/lib/api/api_error.js
336
366
  - app/javascript/lib/api/creatives.js
337
367
  - app/javascript/lib/api/csrf_fetch.js
338
368
  - app/javascript/lib/api/drag_drop.js
@@ -341,33 +371,71 @@ files:
341
371
  - app/javascript/lib/apply_lexical_styles.js
342
372
  - app/javascript/lib/chat_history.js
343
373
  - app/javascript/lib/common_popup.js
374
+ - app/javascript/lib/editor/__tests__/code_edit_view_token_parity.test.js
375
+ - app/javascript/lib/editor/__tests__/code_language_roundtrip.test.js
376
+ - app/javascript/lib/editor/__tests__/code_languages.test.js
377
+ - app/javascript/lib/editor/code_languages.js
378
+ - app/javascript/lib/editor/code_token_theme.js
344
379
  - app/javascript/lib/gnb_popup_manager.js
345
380
  - app/javascript/lib/html_code_block_wrapper.js
346
381
  - app/javascript/lib/lexical/__tests__/attachment_payload.test.js
382
+ - app/javascript/lib/lexical/__tests__/code_block_toggle.test.js
383
+ - app/javascript/lib/lexical/__tests__/code_fence_shortcut.test.js
347
384
  - app/javascript/lib/lexical/__tests__/color_import.test.js
385
+ - app/javascript/lib/lexical/__tests__/image_focus.test.js
386
+ - app/javascript/lib/lexical/__tests__/list_tab_indent.test.js
387
+ - app/javascript/lib/lexical/__tests__/markdown_serialize.test.js
348
388
  - app/javascript/lib/lexical/__tests__/minimize_html.test.js
389
+ - app/javascript/lib/lexical/__tests__/selection_boundary.test.js
390
+ - app/javascript/lib/lexical/__tests__/table_transformer.test.js
391
+ - app/javascript/lib/lexical/__tests__/trailing_paragraph.test.js
349
392
  - app/javascript/lib/lexical/attachment_node.jsx
350
393
  - app/javascript/lib/lexical/attachment_payload.js
394
+ - app/javascript/lib/lexical/code_block_toggle.js
395
+ - app/javascript/lib/lexical/code_fence_shortcut.js
351
396
  - app/javascript/lib/lexical/color_import.js
352
397
  - app/javascript/lib/lexical/image_node.jsx
398
+ - app/javascript/lib/lexical/list_tab_indent.js
399
+ - app/javascript/lib/lexical/markdown_serialize.js
353
400
  - app/javascript/lib/lexical/minimize_html.js
401
+ - app/javascript/lib/lexical/selection_boundary.js
354
402
  - app/javascript/lib/lexical/style_attributes.js
403
+ - app/javascript/lib/lexical/table_transformer.js
404
+ - app/javascript/lib/lexical/trailing_paragraph.js
355
405
  - app/javascript/lib/lexical/video_node.jsx
356
406
  - app/javascript/lib/responsive_images.js
357
407
  - app/javascript/lib/touch_drag.js
408
+ - app/javascript/lib/turbo_confirm.js
358
409
  - app/javascript/lib/turbo_stream_actions.js
410
+ - app/javascript/lib/typo_correction.js
411
+ - app/javascript/lib/utils/__tests__/confirm_dialog.test.js
412
+ - app/javascript/lib/utils/__tests__/dialog.test.js
413
+ - app/javascript/lib/utils/__tests__/markdown.test.js
414
+ - app/javascript/lib/utils/__tests__/sanitize_description.test.js
415
+ - app/javascript/lib/utils/__tests__/table_download.test.js
416
+ - app/javascript/lib/utils/confirm_dialog.js
417
+ - app/javascript/lib/utils/dialog.js
359
418
  - app/javascript/lib/utils/markdown.js
419
+ - app/javascript/lib/utils/sanitize_description.js
360
420
  - app/javascript/lib/utils/table_download.js
361
421
  - app/javascript/modules/__tests__/command_args_form.test.js
422
+ - app/javascript/modules/__tests__/creative_inline_payload.test.js
362
423
  - app/javascript/modules/__tests__/creative_progress.test.js
424
+ - app/javascript/modules/__tests__/creative_save_queue.test.js
425
+ - app/javascript/modules/__tests__/creative_tree_dom.test.js
363
426
  - app/javascript/modules/__tests__/html_content_empty.test.js
364
427
  - app/javascript/modules/__tests__/markdown_source_reconcile.test.js
428
+ - app/javascript/modules/__tests__/typo_corrector.test.js
365
429
  - app/javascript/modules/command_args_form.js
366
430
  - app/javascript/modules/command_menu.js
367
431
  - app/javascript/modules/creative_guide.js
432
+ - app/javascript/modules/creative_inline_payload.js
368
433
  - app/javascript/modules/creative_progress.js
369
434
  - app/javascript/modules/creative_row_editor.js
435
+ - app/javascript/modules/creative_row_editor_helpers.js
370
436
  - app/javascript/modules/creative_row_swipe.js
437
+ - app/javascript/modules/creative_save_queue.js
438
+ - app/javascript/modules/creative_tree_dom.js
371
439
  - app/javascript/modules/creatives.js
372
440
  - app/javascript/modules/export_to_markdown.js
373
441
  - app/javascript/modules/html_content_empty.js
@@ -378,6 +446,7 @@ files:
378
446
  - app/javascript/modules/mention_menu.js
379
447
  - app/javascript/modules/modal_dialog.js
380
448
  - app/javascript/modules/slide_view.js
449
+ - app/javascript/modules/typo_corrector.js
381
450
  - app/javascript/services/cable.js
382
451
  - app/javascript/services/creatives_channel.js
383
452
  - app/javascript/slide_view.js
@@ -400,6 +469,7 @@ files:
400
469
  - app/jobs/collavre/stuck_detector_job.rb
401
470
  - app/jobs/collavre/trigger_loop_check_job.rb
402
471
  - app/jobs/collavre/trigger_loop_verify_job.rb
472
+ - app/jobs/collavre/update_mcp_tools_job.rb
403
473
  - app/jobs/concerns/collavre/comment_serializable.rb
404
474
  - app/jobs/concerns/collavre/trigger_loop_helpers.rb
405
475
  - app/mailers/collavre/application_mailer.rb
@@ -455,7 +525,9 @@ files:
455
525
  - app/models/collavre/webauthn_credential.rb
456
526
  - app/models/concerns/collavre/ai_agent_resolvable.rb
457
527
  - app/models/concerns/collavre/has_inbox_creative.rb
528
+ - app/models/concerns/collavre/indexed_json_columns.rb
458
529
  - app/services/collavre/agent_session_abort.rb
530
+ - app/services/collavre/agent_type_classifier.rb
459
531
  - app/services/collavre/ai_agent/a2a_dispatcher.rb
460
532
  - app/services/collavre/ai_agent/agent_lifecycle_manager.rb
461
533
  - app/services/collavre/ai_agent/approval_handler.rb
@@ -465,6 +537,8 @@ files:
465
537
  - app/services/collavre/ai_agent/response_streamer.rb
466
538
  - app/services/collavre/ai_agent/review_handler.rb
467
539
  - app/services/collavre/ai_agent/session_context_resolver.rb
540
+ - app/services/collavre/ai_agent/session_provisioner.rb
541
+ - app/services/collavre/ai_agent/task_claim_service.rb
468
542
  - app/services/collavre/ai_agent_service.rb
469
543
  - app/services/collavre/ai_client.rb
470
544
  - app/services/collavre/ai_system_prompt_renderer.rb
@@ -487,8 +561,12 @@ files:
487
561
  - app/services/collavre/comments/work_command.rb
488
562
  - app/services/collavre/comments/workflow_executor.rb
489
563
  - app/services/collavre/creatives/breadcrumb_resolver.rb
564
+ - app/services/collavre/creatives/children_index.rb
565
+ - app/services/collavre/creatives/comment_badge_index.rb
490
566
  - app/services/collavre/creatives/create_service.rb
567
+ - app/services/collavre/creatives/creative_tree_serializer.rb
491
568
  - app/services/collavre/creatives/destroy_service.rb
569
+ - app/services/collavre/creatives/effective_creative_resolution.rb
492
570
  - app/services/collavre/creatives/filter_pipeline.rb
493
571
  - app/services/collavre/creatives/filters/assignee_filter.rb
494
572
  - app/services/collavre/creatives/filters/base_filter.rb
@@ -510,12 +588,14 @@ files:
510
588
  - app/services/collavre/crons/recurring_task_arguments.rb
511
589
  - app/services/collavre/gemini_parent_recommender.rb
512
590
  - app/services/collavre/google_calendar_service.rb
591
+ - app/services/collavre/http_client.rb
513
592
  - app/services/collavre/inbox_reply_service.rb
514
593
  - app/services/collavre/link_preview_fetcher.rb
515
594
  - app/services/collavre/markdown_converter.rb
516
595
  - app/services/collavre/markdown_importer.rb
517
596
  - app/services/collavre/mcp_service.rb
518
597
  - app/services/collavre/mention_parser.rb
598
+ - app/services/collavre/mobile/event_summarizer.rb
519
599
  - app/services/collavre/orchestration/agent_context_builder.rb
520
600
  - app/services/collavre/orchestration/agent_orchestrator.rb
521
601
  - app/services/collavre/orchestration/arbiter.rb
@@ -541,13 +621,13 @@ files:
541
621
  - app/services/collavre/tools/cron_create_service.rb
542
622
  - app/services/collavre/tools/cron_list_service.rb
543
623
  - app/services/collavre/tools/cron_update_service.rb
544
- - app/services/collavre/tools/description_normalizable.rb
545
624
  - app/services/collavre/tools/permission_denied_error.rb
546
625
  - app/services/collavre/tools/preview_attach_service.rb
547
626
  - app/services/collavre/tools/preview_detach_service.rb
548
627
  - app/services/collavre/tools/topic_authorizer.rb
549
628
  - app/services/collavre/topic_branch_service.rb
550
629
  - app/services/collavre/topics/orphaned_cron_notifier.rb
630
+ - app/services/collavre/typo_corrector.rb
551
631
  - app/views/admin/shared/_tabs.html.erb
552
632
  - app/views/collavre/admin/integrations/_category.html.erb
553
633
  - app/views/collavre/admin/integrations/_setting_row.html.erb
@@ -571,6 +651,7 @@ files:
571
651
  - app/views/collavre/creatives/_integration_triggers.html.erb
572
652
  - app/views/collavre/creatives/_integrations_menu.html.erb
573
653
  - app/views/collavre/creatives/_share_modal.html.erb
654
+ - app/views/collavre/creatives/_topic_move_members_modal.html.erb
574
655
  - app/views/collavre/creatives/edit.html.erb
575
656
  - app/views/collavre/creatives/index.html.erb
576
657
  - app/views/collavre/creatives/new.html.erb
@@ -619,6 +700,7 @@ files:
619
700
  - app/views/collavre/users/new_ai.html.erb
620
701
  - app/views/collavre/users/passkeys.html.erb
621
702
  - app/views/collavre/users/show.html.erb
703
+ - app/views/collavre/users/typo_correction.html.erb
622
704
  - app/views/inbox/badge_component/_count.html.erb
623
705
  - app/views/layouts/collavre/landing.html.erb
624
706
  - app/views/layouts/collavre/slide.html.erb
@@ -646,6 +728,8 @@ files:
646
728
  - config/locales/invites.ko.yml
647
729
  - config/locales/landing.en.yml
648
730
  - config/locales/landing.ko.yml
731
+ - config/locales/mobile.en.yml
732
+ - config/locales/mobile.ko.yml
649
733
  - config/locales/notifications.en.yml
650
734
  - config/locales/notifications.ko.yml
651
735
  - config/locales/orchestration.en.yml
@@ -782,6 +866,16 @@ files:
782
866
  - db/migrate/20260609020000_add_last_seen_at_to_agent_subscriptions.rb
783
867
  - db/migrate/20260609030000_add_session_id_to_agent_subscriptions.rb
784
868
  - db/migrate/20260609190659_backfill_creative_files_into_description.rb
869
+ - db/migrate/20260612000000_add_topic_concurrency_defer_to_comments.rb
870
+ - db/migrate/20260617090000_add_typo_correction_settings_to_users.rb
871
+ - db/migrate/20260702000001_enforce_system_settings_key_not_null.rb
872
+ - db/migrate/20260702000002_add_creative_index_and_fk_to_tags.rb
873
+ - db/migrate/20260702000003_add_creative_type_index_to_labels.rb
874
+ - db/migrate/20260702000004_add_creative_created_at_index_to_comments.rb
875
+ - db/migrate/20260702000005_promote_channel_config_index_columns.rb
876
+ - db/migrate/20260713000001_add_comments_count_to_creatives.rb
877
+ - db/migrate/20260713000002_add_comment_versions_count_to_comments.rb
878
+ - db/migrate/20260715000000_change_creatives_description_to_plain_text.rb
785
879
  - db/seeds.rb
786
880
  - lib/collavre.rb
787
881
  - lib/collavre/aws_credentials.rb
@@ -1,16 +0,0 @@
1
- module Collavre
2
- module Tools
3
- module DescriptionNormalizable
4
- private
5
-
6
- def normalize_description(desc)
7
- return desc if desc.blank?
8
- stripped = desc.strip
9
- # If it already looks like HTML, return as-is
10
- return stripped if stripped.start_with?("<")
11
- # Otherwise wrap in <p> tags
12
- "<p>#{ERB::Util.html_escape(stripped)}</p>"
13
- end
14
- end
15
- end
16
- end