collavre 0.24.0 → 0.25.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 (440) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/app/assets/stylesheets/collavre/comments_popup.css +165 -99
  4. data/app/assets/stylesheets/collavre/creatives.css +346 -37
  5. data/app/assets/stylesheets/collavre/desktop_setup.css +246 -0
  6. data/app/assets/stylesheets/collavre/gnb.css +64 -3
  7. data/app/assets/stylesheets/collavre/landing.css +108 -3
  8. data/app/assets/stylesheets/collavre/mention_menu.css +32 -0
  9. data/app/assets/stylesheets/collavre/popup.css +14 -0
  10. data/app/assets/stylesheets/collavre/print.css +0 -1
  11. data/app/assets/stylesheets/collavre/search_popup.css +1 -1
  12. data/app/assets/stylesheets/collavre/secret_fields.css +3 -0
  13. data/app/assets/stylesheets/collavre/workspace.css +307 -0
  14. data/app/channels/collavre/agent_channel.rb +14 -21
  15. data/app/channels/collavre/comments_presence_channel.rb +181 -21
  16. data/app/channels/collavre/inbox_badge_channel.rb +7 -1
  17. data/app/components/collavre/inbox/badge_component.rb +6 -13
  18. data/app/components/collavre/progress_filter_component.html.erb +2 -2
  19. data/app/components/collavre/progress_filter_component.rb +20 -0
  20. data/app/controllers/collavre/admin/settings_controller.rb +4 -1
  21. data/app/controllers/collavre/agent_connections_controller.rb +165 -0
  22. data/app/controllers/collavre/agent_gateways_controller.rb +132 -0
  23. data/app/controllers/collavre/agent_provisioning_controller.rb +79 -0
  24. data/app/controllers/collavre/api/v1/agents_controller.rb +45 -97
  25. data/app/controllers/collavre/application_controller.rb +13 -2
  26. data/app/controllers/collavre/comment_read_pointers_controller.rb +69 -40
  27. data/app/controllers/collavre/comments_controller.rb +45 -131
  28. data/app/controllers/collavre/concerns/shareable.rb +9 -3
  29. data/app/controllers/collavre/creatives_controller.rb +144 -11
  30. data/app/controllers/collavre/desktop_gateway_registrations_controller.rb +173 -0
  31. data/app/controllers/collavre/desktop_setup_controller.rb +119 -0
  32. data/app/controllers/collavre/desktop_sidecar_health_controller.rb +35 -0
  33. data/app/controllers/collavre/features_controller.rb +57 -0
  34. data/app/controllers/collavre/invites_controller.rb +12 -1
  35. data/app/controllers/collavre/llm_models_controller.rb +8 -0
  36. data/app/controllers/collavre/notices_controller.rb +20 -0
  37. data/app/controllers/collavre/tasks_controller.rb +40 -6
  38. data/app/controllers/collavre/topics_controller.rb +130 -53
  39. data/app/controllers/collavre/user_creative_preferences_controller.rb +214 -30
  40. data/app/controllers/concerns/collavre/comments/batch_operations.rb +15 -3
  41. data/app/controllers/concerns/collavre/comments/conversion.rb +1 -1
  42. data/app/controllers/concerns/collavre/users_controller/ai_user_management.rb +118 -8
  43. data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +1 -15
  44. data/app/controllers/concerns/collavre/users_controller/registration.rb +2 -2
  45. data/app/errors/collavre/turn_deadline_error.rb +20 -0
  46. data/app/helpers/collavre/application_helper.rb +38 -0
  47. data/app/helpers/collavre/creatives_helper.rb +56 -22
  48. data/app/helpers/collavre/navigation_helper.rb +12 -0
  49. data/app/javascript/collavre.js +1 -2
  50. data/app/javascript/components/InlineLexicalEditor.jsx +30 -21
  51. data/app/javascript/components/__tests__/creative_tree_row_parent_id.test.js +32 -2
  52. data/app/javascript/components/__tests__/creative_tree_row_progress_toggle.test.js +185 -0
  53. data/app/javascript/components/creative_tree_row.js +62 -22
  54. data/app/javascript/controllers/__tests__/agent_connection_controller.test.js +195 -0
  55. data/app/javascript/controllers/__tests__/desktop_proxy_setup_controller.test.js +96 -0
  56. data/app/javascript/controllers/__tests__/index.test.js +42 -0
  57. data/app/javascript/controllers/__tests__/last_visited_creative_controller.test.js +103 -0
  58. data/app/javascript/controllers/__tests__/link_creative_controller.test.js +253 -2
  59. data/app/javascript/controllers/__tests__/progress_filter_controller.test.js +134 -0
  60. data/app/javascript/controllers/__tests__/search_popup_controller.test.js +310 -0
  61. data/app/javascript/controllers/__tests__/topic_list_controller.test.js +111 -0
  62. data/app/javascript/controllers/__tests__/workspace_tree_controller.test.js +1011 -0
  63. data/app/javascript/controllers/agent_connection_controller.js +357 -0
  64. data/app/javascript/controllers/agent_vendor_controller.js +23 -0
  65. data/app/javascript/controllers/comment_controller.js +3 -1
  66. data/app/javascript/controllers/comments/__tests__/feature_cards_controller.test.js +223 -0
  67. data/app/javascript/controllers/comments/__tests__/form_controller_default_placeholder.test.js +83 -0
  68. data/app/javascript/controllers/comments/__tests__/form_controller_draft.test.js +2069 -0
  69. data/app/javascript/controllers/comments/__tests__/form_controller_ime_send.test.js +324 -0
  70. data/app/javascript/controllers/comments/__tests__/form_controller_review.test.js +28 -2
  71. data/app/javascript/controllers/comments/__tests__/form_controller_search_submit.test.js +106 -0
  72. data/app/javascript/controllers/comments/__tests__/form_controller_stashed_draft.test.js +134 -0
  73. data/app/javascript/controllers/comments/__tests__/form_controller_stashed_draft_creative_switch.test.js +166 -0
  74. data/app/javascript/controllers/comments/__tests__/form_controller_stashed_draft_failure.test.js +183 -0
  75. data/app/javascript/controllers/comments/__tests__/list_controller_deep_link_topic.test.js +467 -0
  76. data/app/javascript/controllers/comments/__tests__/list_controller_docked.test.js +115 -0
  77. data/app/javascript/controllers/comments/__tests__/list_controller_prev_message.test.js +245 -0
  78. data/app/javascript/controllers/comments/__tests__/list_controller_read_pointer.test.js +276 -0
  79. data/app/javascript/controllers/comments/__tests__/list_controller_stream_archived.test.js +221 -0
  80. data/app/javascript/controllers/comments/__tests__/list_controller_stream_search.test.js +104 -0
  81. data/app/javascript/controllers/comments/__tests__/placeholder_controller.test.js +79 -0
  82. data/app/javascript/controllers/comments/__tests__/popup_controller.test.js +754 -1
  83. data/app/javascript/controllers/comments/__tests__/presence_controller.test.js +717 -15
  84. data/app/javascript/controllers/comments/__tests__/prev_message_navigator.test.js +129 -0
  85. data/app/javascript/controllers/comments/__tests__/topics_controller_action_errors.test.js +184 -0
  86. data/app/javascript/controllers/comments/__tests__/topics_controller_archived.test.js +879 -0
  87. data/app/javascript/controllers/comments/__tests__/topics_controller_creation_container.test.js +154 -0
  88. data/app/javascript/controllers/comments/__tests__/topics_controller_creation_scroll.test.js +92 -0
  89. data/app/javascript/controllers/comments/__tests__/topics_controller_delete.test.js +130 -0
  90. data/app/javascript/controllers/comments/__tests__/topics_controller_docked.test.js +32 -0
  91. data/app/javascript/controllers/comments/__tests__/topics_controller_last_topic_echo.test.js +1938 -0
  92. data/app/javascript/controllers/comments/__tests__/topics_controller_primary_agent.test.js +256 -0
  93. data/app/javascript/controllers/comments/__tests__/topics_controller_scroll.test.js +182 -0
  94. data/app/javascript/controllers/comments/__tests__/topics_controller_selection_race.test.js +981 -0
  95. data/app/javascript/controllers/comments/__tests__/topics_controller_topic_list.test.js +313 -0
  96. data/app/javascript/controllers/comments/feature_cards_controller.js +83 -0
  97. data/app/javascript/controllers/comments/form_controller.js +795 -14
  98. data/app/javascript/controllers/comments/list_controller.js +338 -52
  99. data/app/javascript/controllers/comments/placeholder_controller.js +30 -0
  100. data/app/javascript/controllers/comments/popup_controller.js +425 -83
  101. data/app/javascript/controllers/comments/presence_controller.js +317 -55
  102. data/app/javascript/controllers/comments/prev_message_navigator.js +94 -0
  103. data/app/javascript/controllers/comments/topics_controller.js +1772 -100
  104. data/app/javascript/controllers/common_popup_controller.js +2 -2
  105. data/app/javascript/controllers/creatives/__tests__/select_mode_controller.test.js +139 -0
  106. data/app/javascript/controllers/creatives/__tests__/tree_controller.test.js +605 -0
  107. data/app/javascript/controllers/creatives/__tests__/write_access_request_controller.test.js +125 -0
  108. data/app/javascript/controllers/creatives/select_mode_controller.js +7 -2
  109. data/app/javascript/controllers/creatives/tree_controller.js +140 -31
  110. data/app/javascript/controllers/creatives/write_access_request_controller.js +58 -0
  111. data/app/javascript/controllers/desktop_proxy_setup_controller.js +51 -0
  112. data/app/javascript/controllers/gateway_check_controller.js +36 -0
  113. data/app/javascript/controllers/index.js +25 -1
  114. data/app/javascript/controllers/last_visited_creative_controller.js +58 -0
  115. data/app/javascript/controllers/link_creative_controller.js +89 -18
  116. data/app/javascript/controllers/progress_filter_controller.js +12 -22
  117. data/app/javascript/controllers/search_popup_controller.js +64 -46
  118. data/app/javascript/controllers/share_user_search_controller.js +2 -2
  119. data/app/javascript/controllers/topic_list_controller.js +44 -7
  120. data/app/javascript/controllers/workspace_tree_controller.js +662 -0
  121. data/app/javascript/creatives/__tests__/tree_renderer.test.js +80 -0
  122. data/app/javascript/creatives/drag_drop/__tests__/drop_completion_empty_state.test.js +98 -0
  123. data/app/javascript/creatives/drag_drop/__tests__/topic_move_released_agent.test.js +125 -0
  124. data/app/javascript/creatives/drag_drop/event_handlers.js +12 -0
  125. data/app/javascript/creatives/tree_renderer.js +65 -22
  126. data/app/javascript/lib/__tests__/chat_drafts.test.js +1458 -0
  127. data/app/javascript/lib/__tests__/common_popup_bounds.test.js +8 -3
  128. data/app/javascript/lib/__tests__/common_popup_placement.test.js +374 -0
  129. data/app/javascript/lib/__tests__/common_popup_reshow.test.js +131 -0
  130. data/app/javascript/lib/__tests__/creative_link_prefetch.test.js +46 -0
  131. data/app/javascript/lib/__tests__/last_visited_creative.test.js +87 -0
  132. data/app/javascript/lib/__tests__/skill_html_entities.test.js +23 -0
  133. data/app/javascript/lib/__tests__/turbo_stream_actions.test.js +190 -0
  134. data/app/javascript/lib/api/__tests__/creatives.test.js +68 -0
  135. data/app/javascript/lib/api/__tests__/csrf_fetch.test.js +27 -0
  136. data/app/javascript/lib/api/__tests__/topics_save_last_topic.test.js +112 -0
  137. data/app/javascript/lib/api/creatives.js +32 -13
  138. data/app/javascript/lib/api/csrf_fetch.js +6 -4
  139. data/app/javascript/lib/api/topics.js +63 -5
  140. data/app/javascript/lib/chat_drafts.js +786 -0
  141. data/app/javascript/lib/common_popup.js +164 -25
  142. data/app/javascript/lib/creative_link_prefetch.js +27 -0
  143. data/app/javascript/lib/last_visited_creative.js +97 -0
  144. data/app/javascript/lib/lexical/__tests__/creative_link_node.test.js +162 -0
  145. data/app/javascript/lib/lexical/__tests__/creative_link_trigger.test.js +133 -0
  146. data/app/javascript/lib/lexical/__tests__/link_toolbar.test.js +62 -0
  147. data/app/javascript/lib/lexical/creative_link_node.js +101 -0
  148. data/app/javascript/lib/lexical/creative_link_trigger.js +98 -0
  149. data/app/javascript/lib/lexical/link_toolbar.js +23 -0
  150. data/app/javascript/lib/turbo_stream_actions.js +23 -16
  151. data/app/javascript/lib/utils/__tests__/filter_navigation.test.js +210 -0
  152. data/app/javascript/lib/utils/__tests__/markdown.test.js +44 -0
  153. data/app/javascript/lib/utils/filter_navigation.js +100 -0
  154. data/app/javascript/modules/__tests__/command_menu_creative_picker.test.js +62 -0
  155. data/app/javascript/modules/__tests__/command_menu_typeahead.test.js +267 -0
  156. data/app/javascript/modules/__tests__/creative_link_picker.test.js +85 -0
  157. data/app/javascript/modules/__tests__/creative_row_editor_archive.test.js +391 -0
  158. data/app/javascript/modules/__tests__/creative_row_editor_delegated_clicks.test.js +158 -0
  159. data/app/javascript/modules/__tests__/creative_row_editor_empty_state_recovery.test.js +519 -0
  160. data/app/javascript/modules/__tests__/creative_row_editor_empty_state_removal.test.js +346 -0
  161. data/app/javascript/modules/__tests__/creative_row_editor_session.test.js +144 -0
  162. data/app/javascript/modules/__tests__/creative_tree_dom.test.js +30 -0
  163. data/app/javascript/modules/__tests__/creative_tree_empty_state.test.js +186 -0
  164. data/app/javascript/modules/__tests__/dom_listener_registry.test.js +67 -0
  165. data/app/javascript/modules/__tests__/support/inline_editor_dom.js +159 -0
  166. data/app/javascript/modules/command_args_form.js +0 -12
  167. data/app/javascript/modules/command_menu.js +80 -38
  168. data/app/javascript/modules/creative_link_picker.js +56 -0
  169. data/app/javascript/modules/creative_row_editor.js +446 -243
  170. data/app/javascript/modules/creative_row_editor_delegated_clicks.js +87 -0
  171. data/app/javascript/modules/creative_tree_dom.js +4 -0
  172. data/app/javascript/modules/creative_tree_empty_state.js +80 -0
  173. data/app/javascript/modules/dom_listener_registry.js +23 -0
  174. data/app/javascript/modules/mention_menu.js +2 -3
  175. data/app/javascript/utils/__tests__/caret_anchor.test.js +75 -0
  176. data/app/javascript/utils/__tests__/chevron_icons.test.js +15 -0
  177. data/app/javascript/utils/caret_position.js +10 -0
  178. data/app/javascript/utils/chevron_icons.js +7 -0
  179. data/app/jobs/collavre/ai_agent_job.rb +262 -72
  180. data/app/jobs/collavre/cancel_offline_delegated_tasks_job.rb +11 -36
  181. data/app/jobs/collavre/comment_badges_broadcast_job.rb +28 -0
  182. data/app/jobs/collavre/comment_link_preview_job.rb +33 -0
  183. data/app/jobs/collavre/comment_notification_job.rb +14 -0
  184. data/app/jobs/collavre/comment_push_delivery_sweep_job.rb +17 -0
  185. data/app/jobs/collavre/compress_job.rb +33 -22
  186. data/app/jobs/collavre/creative_broadcast_job.rb +161 -48
  187. data/app/jobs/collavre/cron_action_job.rb +36 -18
  188. data/app/jobs/collavre/drop_trigger_job.rb +23 -9
  189. data/app/jobs/collavre/merge_comments_job.rb +33 -16
  190. data/app/jobs/collavre/push_notification_job.rb +62 -18
  191. data/app/jobs/collavre/restore_dropped_dispatches_job.rb +17 -0
  192. data/app/jobs/collavre/stuck_detector_job.rb +1 -1
  193. data/app/jobs/collavre/touch_creative_subtree_job.rb +14 -0
  194. data/app/models/collavre/agent_gateway.rb +200 -0
  195. data/app/models/collavre/agent_subscription.rb +4 -4
  196. data/app/models/collavre/agent_workspace.rb +210 -0
  197. data/app/models/collavre/comment/broadcastable.rb +22 -52
  198. data/app/models/collavre/comment/notifiable.rb +154 -77
  199. data/app/models/collavre/comment/topic_membership.rb +41 -0
  200. data/app/models/collavre/comment.rb +336 -31
  201. data/app/models/collavre/comment_notification_delivery.rb +61 -0
  202. data/app/models/collavre/comment_presence_store/cache_batches.rb +64 -0
  203. data/app/models/collavre/comment_presence_store.rb +272 -12
  204. data/app/models/collavre/comment_read_pointer.rb +9 -15
  205. data/app/models/collavre/creative/describable.rb +8 -2
  206. data/app/models/collavre/creative/permissible.rb +11 -0
  207. data/app/models/collavre/creative.rb +29 -4
  208. data/app/models/collavre/creative_share.rb +109 -4
  209. data/app/models/collavre/current.rb +1 -0
  210. data/app/models/collavre/llm_model.rb +62 -0
  211. data/app/models/collavre/system_setting.rb +12 -1
  212. data/app/models/collavre/task.rb +121 -2
  213. data/app/models/collavre/topic.rb +51 -0
  214. data/app/models/collavre/user.rb +101 -41
  215. data/app/models/collavre/user_creative_preference.rb +3 -1
  216. data/app/services/collavre/agent_provisioning/archive.rb +108 -0
  217. data/app/services/collavre/ai_agent/a2a_dispatcher.rb +16 -3
  218. data/app/services/collavre/ai_agent/agent_lifecycle_manager.rb +63 -6
  219. data/app/services/collavre/ai_agent/approval_handler.rb +12 -4
  220. data/app/services/collavre/ai_agent/claude_channel_adapter.rb +10 -5
  221. data/app/services/collavre/ai_agent/merged_trigger_comments.rb +164 -0
  222. data/app/services/collavre/ai_agent/message_builder.rb +103 -16
  223. data/app/services/collavre/ai_agent/session_provisioner.rb +3 -7
  224. data/app/services/collavre/ai_agent/task_claim_service.rb +29 -15
  225. data/app/services/collavre/ai_agent/task_reply_service.rb +67 -0
  226. data/app/services/collavre/ai_agent_service.rb +108 -20
  227. data/app/services/collavre/ai_client.rb +211 -21
  228. data/app/services/collavre/cli_proxy/client.rb +147 -0
  229. data/app/services/collavre/cli_proxy/endpoint_policy.rb +81 -0
  230. data/app/services/collavre/cli_proxy/identity.rb +47 -0
  231. data/app/services/collavre/cli_proxy/safe_net_http_adapter.rb +19 -0
  232. data/app/services/collavre/command_menu_service.rb +0 -10
  233. data/app/services/collavre/comment_move_service.rb +96 -7
  234. data/app/services/collavre/comment_snapshot_restore_service.rb +11 -5
  235. data/app/services/collavre/comments/action_executor.rb +48 -20
  236. data/app/services/collavre/comments/command_processor.rb +0 -1
  237. data/app/services/collavre/comments/list_response.rb +133 -0
  238. data/app/services/collavre/comments/read_pointer_writer.rb +210 -0
  239. data/app/services/collavre/comments/read_receipt_broadcaster.rb +157 -0
  240. data/app/services/collavre/comments/read_receipt_index.rb +152 -0
  241. data/app/services/collavre/comments/topic_command.rb +72 -1
  242. data/app/services/collavre/comments/topic_mutation.rb +20 -0
  243. data/app/services/collavre/creatives/breadcrumb_resolver.rb +1 -1
  244. data/app/services/collavre/creatives/comment_badge_index.rb +299 -27
  245. data/app/services/collavre/creatives/reorderer.rb +15 -3
  246. data/app/services/collavre/creatives/tree_builder.rb +1 -1
  247. data/app/services/collavre/creatives/tree_formatter.rb +5 -6
  248. data/app/services/collavre/creatives/workspace_path_resolver.rb +50 -0
  249. data/app/services/collavre/creatives/workspace_tree_builder.rb +92 -0
  250. data/app/services/collavre/crons/recurring_topic_tasks.rb +23 -0
  251. data/app/services/collavre/home_page_path.rb +55 -0
  252. data/app/services/collavre/html_text.rb +64 -0
  253. data/app/services/collavre/http_client.rb +11 -2
  254. data/app/services/collavre/inbox_reply_service.rb +1 -1
  255. data/app/services/collavre/markdown_converter.rb +13 -1
  256. data/app/services/collavre/orchestration/agent_orchestrator.rb +776 -81
  257. data/app/services/collavre/orchestration/arbiter.rb +48 -5
  258. data/app/services/collavre/orchestration/deferred_trigger_scope.rb +53 -0
  259. data/app/services/collavre/orchestration/delivery_record.rb +792 -0
  260. data/app/services/collavre/orchestration/loop_breaker.rb +10 -4
  261. data/app/services/collavre/orchestration/matcher.rb +132 -17
  262. data/app/services/collavre/orchestration/policy_resolver.rb +58 -10
  263. data/app/services/collavre/orchestration/scheduler.rb +10 -4
  264. data/app/services/collavre/orchestration/scheduling_hooks.rb +10 -0
  265. data/app/services/collavre/orchestration/selection.rb +43 -0
  266. data/app/services/collavre/orchestration/stuck_detector.rb +25 -112
  267. data/app/services/collavre/orchestration/task_coalescer.rb +355 -0
  268. data/app/services/collavre/orchestration/topic_slot.rb +73 -0
  269. data/app/services/collavre/system_events/context_builder.rb +60 -11
  270. data/app/services/collavre/system_events/dispatcher.rb +58 -12
  271. data/app/services/collavre/system_events/envelope.rb +73 -0
  272. data/app/services/collavre/system_events/vocabulary.rb +45 -0
  273. data/app/services/collavre/tools/creative_retrieval_service.rb +1 -1
  274. data/app/services/collavre/tools/cron_create_service.rb +32 -18
  275. data/app/services/collavre/tools/id_list.rb +38 -0
  276. data/app/services/collavre/tools/topic_authorizer.rb +61 -7
  277. data/app/services/collavre/tools/topic_branch_service.rb +85 -0
  278. data/app/services/collavre/tools/topic_create_service.rb +117 -0
  279. data/app/services/collavre/tools/topic_list_service.rb +101 -0
  280. data/app/services/collavre/tools/topic_message_create_service.rb +192 -0
  281. data/app/services/collavre/tools/topic_messages_service.rb +346 -0
  282. data/app/services/collavre/tools/topic_move_service.rb +108 -0
  283. data/app/services/collavre/tools/topic_selection.rb +59 -0
  284. data/app/services/collavre/tools/topic_update_service.rb +165 -0
  285. data/app/services/collavre/topic_branch_service.rb +39 -10
  286. data/app/services/collavre/topics/agent_resolver.rb +87 -0
  287. data/app/services/collavre/topics/char_budget.rb +70 -0
  288. data/app/services/collavre/topics/last_topic_preference_payload.rb +18 -0
  289. data/app/services/collavre/topics/message_page.rb +380 -0
  290. data/app/services/collavre/topics/message_page_markdown.rb +102 -0
  291. data/app/services/collavre/topics/message_scope.rb +61 -0
  292. data/app/services/collavre/topics/message_stats.rb +92 -0
  293. data/app/services/collavre/topics/move_blocker.rb +47 -0
  294. data/app/services/collavre/topics/next_name.rb +35 -0
  295. data/app/services/collavre/topics/pin_rejection.rb +25 -0
  296. data/app/services/collavre/topics/read_pointer_relocator.rb +71 -0
  297. data/app/services/collavre/topics/reserved_name.rb +18 -0
  298. data/app/services/collavre/topics/serializer.rb +92 -0
  299. data/app/services/collavre/topics/topic_destroy.rb +30 -0
  300. data/app/services/collavre/topics/topic_move.rb +80 -0
  301. data/app/services/collavre/topics/topic_move_effects.rb +35 -0
  302. data/app/services/collavre/topics/topic_mutation.rb +27 -0
  303. data/app/views/collavre/admin/integrations/_setting_row.html.erb +5 -8
  304. data/app/views/collavre/admin/settings/_system_tab.html.erb +7 -0
  305. data/app/views/collavre/agent_connections/show.html.erb +77 -0
  306. data/app/views/collavre/agent_gateways/_form.html.erb +71 -0
  307. data/app/views/collavre/agent_gateways/edit.html.erb +2 -0
  308. data/app/views/collavre/agent_gateways/index.html.erb +54 -0
  309. data/app/views/collavre/agent_gateways/new.html.erb +2 -0
  310. data/app/views/collavre/comments/_comments_popup.html.erb +32 -17
  311. data/app/views/collavre/comments/_empty_state.html.erb +33 -0
  312. data/app/views/collavre/comments/_empty_state_minimal.html.erb +7 -0
  313. data/app/views/collavre/comments/_feature_card.html.erb +35 -0
  314. data/app/views/collavre/comments/_list.html.erb +3 -2
  315. data/app/views/collavre/comments/_no_search_results.html.erb +3 -0
  316. data/app/views/collavre/creatives/_add_button.html.erb +17 -19
  317. data/app/views/collavre/creatives/_empty_state.html.erb +109 -0
  318. data/app/views/collavre/creatives/_inline_edit_form.html.erb +5 -5
  319. data/app/views/collavre/creatives/_tree_loading_placeholder.html.erb +16 -0
  320. data/app/views/collavre/creatives/_workspace_tree.html.erb +33 -0
  321. data/app/views/collavre/creatives/index.html.erb +79 -18
  322. data/app/views/collavre/desktop_setup/show.html.erb +114 -0
  323. data/app/views/collavre/features/index.html.erb +42 -0
  324. data/app/views/collavre/features/show.html.erb +52 -0
  325. data/app/views/collavre/invitation_mailer/invite.html.erb +1 -1
  326. data/app/views/collavre/invitation_mailer/invite.text.erb +1 -1
  327. data/app/views/collavre/invites/show.html.erb +14 -1
  328. data/app/views/collavre/landing/show.html.erb +5 -1
  329. data/app/views/collavre/shared/_link_creative_modal.html.erb +4 -1
  330. data/app/views/collavre/shared/navigation/_help_button.html.erb +3 -1
  331. data/app/views/collavre/shared/navigation/_panels.html.erb +1 -8
  332. data/app/views/collavre/shared/navigation/_search_form.html.erb +13 -2
  333. data/app/views/collavre/user_themes/index.html.erb +1 -1
  334. data/app/views/collavre/users/_llm_fields.html.erb +65 -0
  335. data/app/views/collavre/users/_org_chart_node.html.erb +1 -1
  336. data/app/views/collavre/users/edit_ai.html.erb +33 -31
  337. data/app/views/collavre/users/new.html.erb +4 -2
  338. data/app/views/collavre/users/new_ai.html.erb +14 -32
  339. data/app/views/collavre/users/show.html.erb +13 -1
  340. data/app/views/layouts/collavre/landing.html.erb +9 -4
  341. data/config/initializers/ruby_llm_openai_reasoning_content.rb +77 -0
  342. data/config/locales/admin.en.yml +3 -1
  343. data/config/locales/admin.ko.yml +3 -1
  344. data/config/locales/agent_gateway.en.yml +217 -0
  345. data/config/locales/agent_gateway.ko.yml +217 -0
  346. data/config/locales/ai_agent.en.yml +0 -1
  347. data/config/locales/ai_agent.ko.yml +0 -1
  348. data/config/locales/comments.en.yml +72 -30
  349. data/config/locales/comments.ko.yml +72 -30
  350. data/config/locales/creatives.en.yml +32 -1
  351. data/config/locales/creatives.ko.yml +32 -1
  352. data/config/locales/features.en.yml +140 -0
  353. data/config/locales/features.ko.yml +140 -0
  354. data/config/locales/invites.en.yml +3 -0
  355. data/config/locales/invites.ko.yml +3 -0
  356. data/config/locales/landing.en.yml +2 -1
  357. data/config/locales/landing.ko.yml +2 -1
  358. data/config/locales/tools.en.yml +20 -0
  359. data/config/locales/tools.ko.yml +20 -0
  360. data/config/locales/users.en.yml +15 -14
  361. data/config/locales/users.ko.yml +14 -14
  362. data/config/routes.rb +45 -19
  363. data/db/migrate/20250911084338_backfill_creative_in_comment_inbox_items.rb +9 -1
  364. data/db/migrate/20260724000000_add_creative_id_index_to_comments.rb +34 -0
  365. data/db/migrate/20260724000001_add_creative_private_id_index_to_comments.rb +50 -0
  366. data/db/migrate/20260724090000_add_async_comment_notification_state.rb +64 -0
  367. data/db/migrate/20260727000000_add_waiting_notice_scope_to_comments.rb +30 -0
  368. data/db/migrate/20260727010000_add_waiting_notice_scope_to_tasks.rb +26 -0
  369. data/db/migrate/20260805000000_add_creative_workspace_enabled_to_users.rb +5 -0
  370. data/db/migrate/20260807050000_add_dismissed_notices_to_users.rb +5 -0
  371. data/db/migrate/20260809000000_change_creative_workspace_enabled_default_to_true.rb +18 -0
  372. data/db/migrate/20260809000001_create_llm_models.rb +64 -0
  373. data/db/migrate/20260809000002_create_agent_gateways_and_workspaces.rb +35 -0
  374. data/db/migrate/20260809000003_hash_agent_workspace_callback_tokens.rb +44 -0
  375. data/db/migrate/20260809000004_encrypt_agent_workspace_manifest_tokens.rb +59 -0
  376. data/db/migrate/20260810000000_split_agent_workspace_identity_axes.rb +58 -0
  377. data/db/migrate/20260810000001_seed_codex_custom_proxy_llm_models.rb +28 -0
  378. data/db/migrate/20260810010000_add_last_visited_creative_to_users.rb +8 -0
  379. data/db/migrate/20260810020000_add_last_visited_creative_at_to_users.rb +5 -0
  380. data/db/migrate/20260810030000_add_last_visited_creative_navigation_order_to_users.rb +6 -0
  381. data/db/migrate/20260810060000_add_last_visited_creative_issued_sequence_to_users.rb +5 -0
  382. data/db/migrate/20260810100000_add_desktop_managed_to_agent_gateways.rb +40 -0
  383. data/db/migrate/20260810100001_add_desktop_preset_adapter_to_users.rb +38 -0
  384. data/db/migrate/20260811000000_make_agent_gateway_completion_key_nullable.rb +7 -0
  385. data/db/migrate/20260812000000_remove_workflow_columns_from_tasks.rb +101 -0
  386. data/db/migrate/20260812000001_remove_android_devices.rb +24 -0
  387. data/db/migrate/20260812010000_drop_inbox_items.rb +22 -0
  388. data/db/migrate/20260813000000_clear_claude_channel_presence_routing_expressions.rb +16 -0
  389. data/db/migrate/20260813000001_add_last_topic_revision_to_user_creative_preferences.rb +5 -0
  390. data/db/migrate/20260813000002_add_last_topic_save_order_to_user_creative_preferences.rb +6 -0
  391. data/db/migrate/20260813000003_add_last_topic_save_sequences_to_user_creative_preferences.rb +5 -0
  392. data/db/migrate/20260813000004_add_last_topic_save_fences_to_user_creative_preferences.rb +6 -0
  393. data/db/migrate/20260814000000_add_topic_to_comment_read_pointers.rb +79 -0
  394. data/db/migrate/20260814000001_add_creative_topic_private_id_index_to_comments.rb +37 -0
  395. data/db/migrate/20260816000000_add_watermark_index_to_comment_read_pointers.rb +27 -0
  396. data/db/migrate/20260816000001_add_private_recipient_topic_index_to_comments.rb +48 -0
  397. data/db/migrate/20260820000000_add_topic_assigned_at_to_comments.rb +13 -0
  398. data/db/seeds.rb +1 -51
  399. data/lib/collavre/engine.rb +108 -1
  400. data/lib/collavre/feature_card_registry.rb +168 -0
  401. data/lib/collavre/hashed_access_token_lookup.rb +22 -0
  402. data/lib/collavre/sensitive_request_silencer.rb +23 -0
  403. data/lib/collavre/user_extensions.rb +0 -2
  404. data/lib/collavre/version.rb +1 -1
  405. data/lib/collavre.rb +1 -0
  406. data/skills/collavre/SKILL.md +165 -0
  407. data/skills/collavre/package.json +8 -0
  408. data/skills/collavre/references/tool-reference.md +347 -0
  409. data/skills/collavre/scripts/collavre +634 -0
  410. data/skills/collavre/scripts/html_entities.js +24 -0
  411. metadata +228 -30
  412. data/app/controllers/collavre/api/v1/mobile/agent_events_controller.rb +0 -224
  413. data/app/controllers/collavre/api/v1/mobile/base_controller.rb +0 -95
  414. data/app/controllers/collavre/api/v1/mobile/devices_controller.rb +0 -31
  415. data/app/controllers/collavre/api/v1/mobile/voice_commands_controller.rb +0 -25
  416. data/app/controllers/collavre/inbox_items_controller.rb +0 -70
  417. data/app/controllers/collavre/typo_corrections_controller.rb +0 -39
  418. data/app/javascript/lib/__tests__/typo_correction.test.js +0 -192
  419. data/app/javascript/lib/typo_correction.js +0 -146
  420. data/app/javascript/modules/__tests__/typo_corrector.test.js +0 -365
  421. data/app/javascript/modules/creative_guide.js +0 -67
  422. data/app/javascript/modules/typo_corrector.js +0 -534
  423. data/app/jobs/collavre/inbox_summary_job.rb +0 -24
  424. data/app/mailers/collavre/inbox_mailer.rb +0 -19
  425. data/app/models/collavre/inbox_item.rb +0 -89
  426. data/app/services/collavre/comments/concerns/workflow_support.rb +0 -115
  427. data/app/services/collavre/comments/work_command.rb +0 -161
  428. data/app/services/collavre/comments/workflow_executor.rb +0 -276
  429. data/app/services/collavre/gemini_parent_recommender.rb +0 -77
  430. data/app/services/collavre/mobile/event_summarizer.rb +0 -40
  431. data/app/services/collavre/typo_corrector.rb +0 -188
  432. data/app/views/collavre/inbox_items/_item.html.erb +0 -18
  433. data/app/views/collavre/inbox_items/_items.html.erb +0 -3
  434. data/app/views/collavre/inbox_items/_list.html.erb +0 -7
  435. data/app/views/collavre/inbox_items/index.html.erb +0 -1
  436. data/app/views/collavre/inbox_mailer/daily_summary.html.erb +0 -11
  437. data/app/views/collavre/inbox_mailer/daily_summary.text.erb +0 -8
  438. data/app/views/collavre/users/typo_correction.html.erb +0 -50
  439. data/config/locales/mobile.en.yml +0 -16
  440. data/config/locales/mobile.ko.yml +0 -16
@@ -0,0 +1,347 @@
1
+ # Collavre MCP Tool Reference
2
+
3
+ ## creative_retrieval_service
4
+
5
+ Retrieve Creatives by ID, search query, or list roots.
6
+
7
+ | Param | Type | Required | Default | Description |
8
+ |-------|------|----------|---------|-------------|
9
+ | `id` | Integer | No | — | Specific Creative ID (returns subtree) |
10
+ | `query` | String | No | — | Text search in descriptions and comments |
11
+ | `level` | Integer | No | 3 | Tree depth to return |
12
+ | `tags` | String | No | — | Comma-separated tag filter |
13
+ | `progress_min` | Float | No | — | Min progress (0.0–1.0) |
14
+ | `progress_max` | Float | No | — | Max progress (0.0–1.0) |
15
+ | `updated_since` | String | No | — | ISO8601 timestamp |
16
+ | `include_comments` | Boolean | No | false | Include recent comments (up to 3 per Creative) |
17
+ | `format` | String | No | "markdown" | "markdown" or "json" |
18
+
19
+ **Markdown output format:**
20
+ ```
21
+ <!-- format: [id] description (progress%) -->
22
+ - [123] My Task (50%)
23
+ - [124] Subtask A (100%)
24
+ - [125] Subtask B (0%)
25
+ ```
26
+
27
+ **JSON output** includes: `id`, `description`, `progress`, `parent_id`, `tags`, `linked`, `origin_id`, `has_children`, `children_count`, `created_at`, `updated_at`, `children[]`, and optionally `recent_comments[]`.
28
+
29
+ ## creative_create_service
30
+
31
+ Create a new Creative.
32
+
33
+ | Param | Type | Required | Default | Description |
34
+ |-------|------|----------|---------|-------------|
35
+ | `description` | String | **Yes** | — | Content/title, written as Markdown (GFM) |
36
+ | `parent_id` | Integer | No | — | Parent Creative ID (omit for root) |
37
+ | `progress` | Float | No | 0 | Initial progress (0.0–1.0) |
38
+ | `after_id` | Integer | No | — | Sibling ID to insert after |
39
+ | `before_id` | Integer | No | — | Sibling ID to insert before |
40
+
41
+ **Returns:** `{ success, id, description, parent_id, progress }` or `{ error, details }`
42
+
43
+ ## creative_update_service
44
+
45
+ Update an existing Creative.
46
+
47
+ | Param | Type | Required | Default | Description |
48
+ |-------|------|----------|---------|-------------|
49
+ | `id` | Integer | **Yes** | — | Creative ID to update |
50
+ | `description` | String | No | — | New content/title, written as Markdown (GFM); replaces the whole body |
51
+ | `progress` | Float | No | — | Only `1.0` allowed; leaf Creatives only |
52
+ | `parent_id` | Integer | No | — | New parent ID (0 = make root) |
53
+
54
+ **Constraints:**
55
+ - Progress: only `1.0` accepted (mark complete). No partial progress.
56
+ - Only leaf Creatives (no children) can have progress set directly.
57
+ - Parent progress auto-calculates from children.
58
+ - Circular parent references are rejected.
59
+
60
+ ## creative_batch_service
61
+
62
+ Execute multiple operations atomically. **Requires approval.**
63
+
64
+ | Param | Type | Required | Description |
65
+ |-------|------|----------|-------------|
66
+ | `operations` | Array | **Yes** | Array of operation objects |
67
+
68
+ **Operation formats:**
69
+
70
+ | Action | Fields |
71
+ |--------|--------|
72
+ | `create` | `action`, `description`, `parent_id`, `progress`, `after_id`, `before_id` |
73
+ | `update` | `action`, `id`, `description`, `progress`, `parent_id` |
74
+ | `delete` | `action`, `id` |
75
+
76
+ **Behavior:** All-or-nothing transaction. If any operation fails, everything rolls back.
77
+
78
+ **Returns:** `{ success, results[] }` or `{ success: false, error, results[] }`
79
+
80
+ ## creative_import_service
81
+
82
+ Import a markdown document as a Creative tree. Uses the built-in MarkdownImporter which supports headings, bullet lists, tables, fenced code blocks, and inline images. **Requires approval.**
83
+
84
+ | Param | Type | Required | Description |
85
+ |-------|------|----------|-------------|
86
+ | `markdown` | String | **Yes** | Markdown text to import |
87
+ | `parent_id` | Integer | **Yes** | Parent Creative ID to import under |
88
+
89
+ **Supported markdown elements:**
90
+ - Headings (`#` through `######`) → nested Creatives by level
91
+ - Bullet lists (`-`, `*`, `+`) → nested children by indent
92
+ - Tables → single Creative with HTML table
93
+ - Fenced code blocks (`` ``` ``) → single Creative with `<pre><code>`
94
+ - Inline images and links → preserved in description HTML
95
+
96
+ **Returns:** `{ success, parent_id, created_count, tree[] }`
97
+
98
+ ## Topic tools
99
+
100
+ A **topic** is a conversation thread on a Creative, and it is also the unit of
101
+ agent concurrency: tasks dispatched in the same topic are serialized (one holds
102
+ the topic's slot, the rest queue), while tasks in different topics run in
103
+ parallel. Splitting work across topics is what makes it run concurrently.
104
+
105
+ ### topic_list
106
+
107
+ List a Creative's topics, or describe specific topics by id. The planning call —
108
+ use it before `topic_messages` to see how much conversation each topic holds.
109
+
110
+ | Param | Type | Required | Default | Description |
111
+ |-------|------|----------|---------|-------------|
112
+ | `creative_id` | Integer | One of | — | List every topic on this Creative |
113
+ | `topic_ids` | String | One of | — | Describe these topics, e.g. `"12,45,78"` (max 20 per call) |
114
+ | `include_archived` | Boolean | No | false | Include archived topics (listing by `creative_id`) |
115
+ | `include_stats` | Boolean | No | true | Include `message_count` / `message_chars` / `last_message_at` |
116
+ | `include_system` | Boolean | No | false | Count authorless notices. Approval prompts are never counted |
117
+
118
+ **Returns:** `{ topics[], errors[] }`. Each topic: `id`, `name`, `creative_id`,
119
+ `archived`, `main`, `system`, `source_topic_id`, `primary_agent`,
120
+ `agent_locked`, `message_count`, `message_chars`, `last_message_at`.
121
+
122
+ `message_chars` combines stored message HTML length with a conservative estimate
123
+ for the image attachment markers emitted by `topic_messages`. It is good for
124
+ relative sizing rather than exact budgeting. Requires **read** on each topic's
125
+ Creative; unknown or unreadable ids come back in `errors`.
126
+
127
+ ### topic_messages
128
+
129
+ Read messages from one or more topics, newest first, with paging.
130
+
131
+ | Param | Type | Required | Default | Description |
132
+ |-------|------|----------|---------|-------------|
133
+ | `topic_ids` | String | **Yes** | — | `"12,45,78"` (max 20 per call); a single id also works |
134
+ | `offset` | Integer | No | 0 | Messages back from the newest, **per topic** |
135
+ | `cursor` | String | No | — | Opaque per-topic snapshot/keyset cursor returned as `next_cursor` |
136
+ | `limit` | Integer | No | 50 | Messages **per topic** (max 200) |
137
+ | `order` | String | No | `"asc"` | Rendering order in the window: `asc` (transcript) or `desc` |
138
+ | `max_message_id` | Integer | No | — | Snapshot anchor: only messages with `id <=` this |
139
+ | `content_offset` | Integer | No | 0 | Character offset within the first message selected by `offset`; use the returned `next_content_offset` |
140
+ | `include_system` | Boolean | No | false | Include authorless notices. Approval prompts are never returned |
141
+ | `max_chars` | Integer | No | 40000 | Cap for the **whole response** (min 160, max 200000; smaller positive values are raised to 160) |
142
+ | `format` | String | No | `"markdown"` | `markdown` or `json` |
143
+
144
+ **Windowing.** Selection is always from the newest end: `offset: 0` is the latest
145
+ message. `order` only changes how the selected window is rendered, not which
146
+ messages it contains. With several topics, `offset`/`limit` apply to **each topic
147
+ independently** and results are grouped per topic — never merged into one
148
+ timeline, so an offset stays reproducible.
149
+
150
+ **Paging a long topic.** Take `newest_message_id` and `next_cursor` from the
151
+ first page and pass them as `max_message_id` and `cursor` on every later page.
152
+ The snapshot excludes newly-created messages and older messages moved into the
153
+ topic after page one. The keyset cursor also prevents messages that leave from
154
+ shifting unread rows past the offset. It binds a clipped continuation to the
155
+ row's content version, so an edit restarts that changed message at character
156
+ zero instead of skipping text.
157
+
158
+ ```
159
+ topic_messages(topic_ids: "12,45,78", limit: 100) # summarize three topics
160
+ topic_messages(topic_ids: 12, offset: 100, cursor: "1770000000000000:9820:1770000001000000:1770000002000000", max_message_id: 9931) # next page
161
+ topic_messages(topic_ids: 12, offset: 100, cursor: "1770000000000000:9820:1770000001000000:1770000002000000", content_offset: 28400, max_message_id: 9931) # clipped tail
162
+ ```
163
+
164
+ **Returns (json):** `{ topics[], truncated, max_chars }`. Each topic entry:
165
+ `topic_id`, `topic_name`, `creative_id`, `total_count`, `total_chars`, `offset`,
166
+ `limit`, `returned_count`, `returned_chars`, `has_more`, `next_offset`,
167
+ `next_cursor`, `next_content_offset`, `newest_message_id`, `messages[]`, and `budget_limited`
168
+ when `max_chars` (rather than `limit`) ended the window. Each message: `id`,
169
+ `author`, `author_id`, `agent`, `created_at`, `content` (plain text plus one
170
+ URL-bearing metadata marker per image attachment), plus content range fields
171
+ when the row is continued.
172
+
173
+ Attachment markers include filename, content type, byte size, and a readable
174
+ public-asset URL. Because they are part of `content`, image-only comments remain
175
+ visible and long attachment lists page through `content_offset` without evading
176
+ `max_chars`.
177
+
178
+ A topic the budget could not reach at all comes back with `skipped_reason` and
179
+ `returned_count: 0` rather than looking like an empty conversation.
180
+
181
+ If the fixed topic metadata alone cannot fit — for example, because a topic
182
+ name is unusually long — the tool returns a bounded error instead of emitting
183
+ a response wider than `max_chars` or silently omitting a topic.
184
+
185
+ A single message wider than the whole `max_chars` cap is clipped rather than
186
+ dropped — dropping it would return an empty page at an offset that has rows and
187
+ the caller would page against it forever. A clipped row keeps `next_offset` on
188
+ the same message and returns `next_content_offset`; pass both values with the
189
+ same `next_cursor` and `max_message_id` until `next_content_offset` disappears.
190
+ Only then is the message row consumed. The clip notice is separate from
191
+ `content`, so JSON callers can concatenate fragments without stripping tool
192
+ text.
193
+
194
+ Markdown `More:` calls repeat the resolved `limit` and `max_chars` alongside
195
+ the cursor, snapshot, content offset, order, and system-message scope. Following
196
+ the generated call therefore keeps the same page size and context budget.
197
+
198
+ Asking for more than 20 topics in one call is an error, not a silent trim — the
199
+ ids past the cap were never read, so there would be no per-topic entry to say
200
+ they were missing. Split them across calls. (Unknown or unreadable ids are
201
+ different: those are reported per topic and the call continues.) `topic_list`
202
+ applies the same cap to `topic_ids`.
203
+
204
+ Requires **read** on each topic's Creative. Private messages you are not party
205
+ to are always excluded.
206
+
207
+ ### topic_create
208
+
209
+ Create a topic on a Creative. The fan-out primitive.
210
+
211
+ | Param | Type | Required | Default | Description |
212
+ |-------|------|----------|---------|-------------|
213
+ | `creative_id` | Integer | **Yes** | — | Creative to create the topic on |
214
+ | `name` | String | No | `"Topic N"` | Must be unique on the Creative |
215
+ | `primary_agent` | String | No | — | Agent to pin — id, email, or exact name; private agents already shared here resolve too |
216
+ | `comment_ids` | String | No | — | Existing messages to **move** into the new topic |
217
+
218
+ Pinning a `primary_agent` is **exclusive**: the pinned agent alone answers
219
+ ambient messages in the topic and every other agent is silent. The agent must
220
+ already hold **feedback** or better on the Creative, otherwise the pin is
221
+ refused — a pinned agent that cannot answer would silence the topic entirely.
222
+
223
+ Requires **write** on the Creative. Use `topic_branch` to copy messages instead
224
+ of moving them.
225
+
226
+ ### topic_message_create
227
+
228
+ Post one public message to an existing topic and run the topic's normal agent
229
+ routing. This is the step that turns a newly created, pinned topic into active
230
+ work.
231
+
232
+ | Param | Type | Required | Description |
233
+ |-------|------|----------|-------------|
234
+ | `topic_id` | Integer | **Yes** | Topic to post to |
235
+ | `content` | String | **Yes** | Message body or initial instruction; Markdown is supported |
236
+
237
+ The caller remains the visible author. Human-authored messages follow ordinary
238
+ comment dispatch. Agent-authored messages dispatch as A2A work, so a coordinator
239
+ can create several topics, pin a primary agent on each, then start them with
240
+ independent instructions. Different topics can run concurrently; repeated
241
+ messages in one topic follow that topic's queue.
242
+
243
+ An agent cannot call this tool on the topic of its current turn. Continue that
244
+ work in the current turn; use this tool to start work in a different topic.
245
+
246
+ Requires **feedback** or better on the topic's Creative. Archived Creatives,
247
+ archived topics, and an inbox's reserved System topic reject new messages.
248
+
249
+ ### topic_update
250
+
251
+ Rename, archive/unarchive, or re-pin a topic. Pass only what changes.
252
+
253
+ | Param | Type | Required | Description |
254
+ |-------|------|----------|-------------|
255
+ | `topic_id` | Integer | **Yes** | Topic to update |
256
+ | `name` | String | No | New name (requires **admin**) |
257
+ | `archived` | Boolean | No | `true` archives, `false` unarchives (requires **write**) |
258
+ | `primary_agent` | String | No | Agent id/email/name, or `"none"` to clear (requires **write**; private agents already shared here resolve too) |
259
+
260
+ Archiving hides the topic from the active list but keeps every message, and
261
+ `topic_messages` can still read it by id. Archive a topic when its thread has
262
+ reached a conclusion rather than reusing it for the next subject.
263
+
264
+ Main and an inbox Creative's System topic are reserved. Their names and archive
265
+ state cannot change because message routing looks them up by name; their primary
266
+ agent pin can still change.
267
+
268
+ A Claude Channel session topic's pin is part of its session identity and cannot
269
+ be changed here.
270
+
271
+ **Returns:** the topic payload plus `changed[]` naming the fields that moved.
272
+
273
+ ### topic_move
274
+
275
+ Move one complete topic to another Creative.
276
+
277
+ | Param | Type | Required | Description |
278
+ |-------|------|----------|-------------|
279
+ | `topic_id` | Integer | **Yes** | Topic to move |
280
+ | `creative_id` | Integer | **Yes** | Destination Creative; links resolve to their origin |
281
+
282
+ The topic keeps its id, messages, archive state, and read cursors. Its primary
283
+ agent stays pinned only when it can still respond on the destination; otherwise
284
+ the result reports that the pin was released. Creative permissions do not move,
285
+ so verify that participants can access the destination. Active agent work must
286
+ finish or be cancelled before the topic can move, and dropped-message
287
+ restoration must settle. Recurring cron jobs targeting the topic must be
288
+ cancelled and recreated after the move. Topics referenced by a Drop Trigger loop
289
+ cannot move.
290
+
291
+ Requires **admin** on the source and **write** on the destination. Topic names
292
+ must be unique on the destination. Main, an inbox's System topic, and live agent
293
+ session topics cannot move.
294
+
295
+ **Returns:** the moved topic payload, `moved_from_creative_id`, and an optional
296
+ `released_primary_agent` explanation.
297
+
298
+ ### topic_branch
299
+
300
+ Create a new topic containing **copies** of selected messages. The originals stay
301
+ in place — the context-length escape hatch.
302
+
303
+ | Param | Type | Required | Description |
304
+ |-------|------|----------|-------------|
305
+ | `source_topic_id` | Integer | **Yes** | Topic to branch from |
306
+ | `comment_ids` | String | **Yes** | Messages to copy, e.g. `"991,994,1002"` (max 100) |
307
+ | `name` | String | No | Defaults to `"branch:<source name>"` |
308
+
309
+ Get the ids from `topic_messages`. Asking for more than the cap is an error, not
310
+ a silent trim. Requires **feedback** or better on the Creative.
311
+
312
+ Approval prompts cannot be branched. The copy carries the content but not the
313
+ approval action, so it would stop being excluded from agent history and read as
314
+ an ordinary message. Passing one is an error — `topic_messages` never returns
315
+ their ids in the first place. Image attachments, including image-only messages,
316
+ remain attached to the copies.
317
+
318
+ ## meta_tool
319
+
320
+ Introspect and dynamically run any registered MCP tool. Enables tool discovery without CLI updates.
321
+
322
+ | Param | Type | Required | Default | Description |
323
+ |-------|------|----------|---------|-------------|
324
+ | `action` | String | **Yes** | — | `list`, `list_summary`, `search`, `get`, or `run` |
325
+ | `tool_name` | String | No | — | Target tool name (required for `get` and `run`) |
326
+ | `query` | String | No | — | Search term (for `search` action) |
327
+ | `arguments` | Object | No | `{}` | Arguments to pass to the tool (for `run` action) |
328
+
329
+ **Actions:**
330
+
331
+ | Action | Description |
332
+ |--------|-------------|
333
+ | `list` | Full list of all tools with names, descriptions, and parameters |
334
+ | `list_summary` | Compact list with names and one-line descriptions only |
335
+ | `search` | Filter tools by name or description matching `query` |
336
+ | `get` | Full schema for a single tool (params, types, usage) |
337
+ | `run` | Execute a tool by name, passing `arguments` through |
338
+
339
+ **CLI mapping:**
340
+
341
+ | CLI Command | meta_tool Action |
342
+ |-------------|------------------|
343
+ | `collavre tool list` | `list_summary` |
344
+ | `collavre tool list --full` | `list` |
345
+ | `collavre tool search <q>` | `search` |
346
+ | `collavre tool info <name>` | `get` |
347
+ | `collavre tool run <name>` | `run` |