@wirecat/cli-core 0.398.0 → 0.400.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 (248) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/dist/analysis/consents.d.ts +11 -6
  3. package/dist/analysis/consents.js +5 -2
  4. package/dist/cli/analysis-choice.d.ts +1 -0
  5. package/dist/cli/analysis-choice.js +3 -0
  6. package/dist/cli/bot/admins.js +14 -4
  7. package/dist/cli/bot/command.js +38 -16
  8. package/dist/cli/bot/examples.d.ts +3 -0
  9. package/dist/cli/bot/examples.js +2 -0
  10. package/dist/cli/bot/mcp.js +6 -2
  11. package/dist/cli/bot/messages.js +17 -6
  12. package/dist/cli/bot/moderation.js +16 -4
  13. package/dist/cli/bot/people.js +16 -4
  14. package/dist/cli/bot/setup.js +27 -8
  15. package/dist/cli/bot/watch.js +7 -1
  16. package/dist/cli/config-command.js +20 -1
  17. package/dist/cli/context.d.ts +2 -0
  18. package/dist/cli/context.js +1 -1
  19. package/dist/cli/effects.d.ts +4 -1
  20. package/dist/cli/effects.js +10 -2
  21. package/dist/cli/embedding-choice.d.ts +2 -1
  22. package/dist/cli/embedding-choice.js +4 -1
  23. package/dist/cli/index.d.ts +1 -1
  24. package/dist/cli/index.js +1 -1
  25. package/dist/cli/json-fields.js +12 -1
  26. package/dist/cli/messenger/account-command.js +15 -6
  27. package/dist/cli/messenger/account-profile-query.d.ts +2 -0
  28. package/dist/cli/messenger/account-profile-query.js +13 -0
  29. package/dist/cli/messenger/account-sessions-command.js +1 -0
  30. package/dist/cli/messenger/admin-commands.js +30 -21
  31. package/dist/cli/messenger/admin-contacts-command.js +6 -3
  32. package/dist/cli/messenger/admin-folders-command.js +5 -5
  33. package/dist/cli/messenger/admin-moderation-command.js +4 -4
  34. package/dist/cli/messenger/admin-statistics-command.js +6 -14
  35. package/dist/cli/messenger/analysis-consents-query.d.ts +5 -0
  36. package/dist/cli/messenger/analysis-consents-query.js +20 -0
  37. package/dist/cli/messenger/archive-commands.js +3 -3
  38. package/dist/cli/messenger/attachments-command.js +3 -0
  39. package/dist/cli/messenger/backfill-command.js +5 -4
  40. package/dist/cli/messenger/catch-up-answers.d.ts +2 -1
  41. package/dist/cli/messenger/catch-up-answers.js +6 -2
  42. package/dist/cli/messenger/chat-queries.d.ts +1 -0
  43. package/dist/cli/messenger/chat-queries.js +12 -2
  44. package/dist/cli/messenger/chats-command.js +2 -2
  45. package/dist/cli/messenger/chats-documents-command.js +7 -5
  46. package/dist/cli/messenger/chats-members-command.js +7 -3
  47. package/dist/cli/messenger/chats-read-command.js +1 -1
  48. package/dist/cli/messenger/chats-stats-command.js +1 -1
  49. package/dist/cli/messenger/chats-tracking-command.js +14 -6
  50. package/dist/cli/messenger/contacts-command.js +11 -7
  51. package/dist/cli/messenger/context.d.ts +2 -0
  52. package/dist/cli/messenger/conversations-command.js +47 -29
  53. package/dist/cli/messenger/doctor-command.js +5 -1
  54. package/dist/cli/messenger/document-links-query.d.ts +2 -0
  55. package/dist/cli/messenger/document-links-query.js +9 -0
  56. package/dist/cli/messenger/download-command.js +1 -0
  57. package/dist/cli/messenger/flood-command.d.ts +2 -2
  58. package/dist/cli/messenger/flood-command.js +3 -3
  59. package/dist/cli/messenger/gaps-command.js +2 -2
  60. package/dist/cli/messenger/guard-commands.js +35 -13
  61. package/dist/cli/messenger/hearing-command.d.ts +1 -1
  62. package/dist/cli/messenger/hearing-command.js +1 -1
  63. package/dist/cli/messenger/images-command.js +1 -0
  64. package/dist/cli/messenger/inbox.js +6 -4
  65. package/dist/cli/messenger/media-archive-command.js +2 -0
  66. package/dist/cli/messenger/media-archive-move-command.js +1 -0
  67. package/dist/cli/messenger/media-archive-timer-command.js +1 -1
  68. package/dist/cli/messenger/mentions-command.js +15 -2
  69. package/dist/cli/messenger/messages-command.js +2 -0
  70. package/dist/cli/messenger/messages-delete-command.js +1 -0
  71. package/dist/cli/messenger/messages-edit-command.js +1 -0
  72. package/dist/cli/messenger/messages-evidence-command.js +3 -1
  73. package/dist/cli/messenger/messages-forward-command.js +1 -0
  74. package/dist/cli/messenger/messages-pin-command.js +3 -0
  75. package/dist/cli/messenger/messages-send-command.js +1 -0
  76. package/dist/cli/messenger/messages-stats-command.js +1 -1
  77. package/dist/cli/messenger/metadata-command.js +7 -2
  78. package/dist/cli/messenger/models-command.js +10 -2
  79. package/dist/cli/messenger/polls-command.js +4 -0
  80. package/dist/cli/messenger/private-people-command.js +8 -6
  81. package/dist/cli/messenger/rankings-command.js +6 -11
  82. package/dist/cli/messenger/reactions-command.js +2 -0
  83. package/dist/cli/messenger/recipients-query.d.ts +5 -0
  84. package/dist/cli/messenger/recipients-query.js +18 -0
  85. package/dist/cli/messenger/records-command.js +13 -6
  86. package/dist/cli/messenger/replies-edit-command.d.ts +1 -1
  87. package/dist/cli/messenger/replies-edit-command.js +13 -5
  88. package/dist/cli/messenger/retention-command.js +1 -1
  89. package/dist/cli/messenger/review.js +6 -4
  90. package/dist/cli/messenger/search-command.js +3 -1
  91. package/dist/cli/messenger/searches-command.js +6 -2
  92. package/dist/cli/messenger/sends-query.d.ts +5 -0
  93. package/dist/cli/messenger/sends-query.js +33 -0
  94. package/dist/cli/messenger/serve-command.js +1 -0
  95. package/dist/cli/messenger/serve-relay.d.ts +1 -0
  96. package/dist/cli/messenger/statistics-query.d.ts +14 -0
  97. package/dist/cli/messenger/statistics-query.js +143 -0
  98. package/dist/cli/messenger/stats-command.js +6 -6
  99. package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
  100. package/dist/cli/messenger/store-maintenance-command.js +10 -10
  101. package/dist/cli/messenger/tags-command.js +18 -6
  102. package/dist/cli/messenger/tasks-command.js +47 -8
  103. package/dist/cli/messenger/transcribe-command.js +2 -1
  104. package/dist/cli/messenger/watch-answers.d.ts +6 -0
  105. package/dist/cli/messenger/watch-answers.js +69 -0
  106. package/dist/cli/messenger/watch-command.d.ts +1 -1
  107. package/dist/cli/messenger/watch-command.js +56 -7
  108. package/dist/cli/program.js +5 -1
  109. package/dist/cli/runs/command.js +25 -38
  110. package/dist/cli/runs/query.d.ts +5 -0
  111. package/dist/cli/runs/query.js +32 -0
  112. package/dist/cli/runs/search-command.d.ts +4 -0
  113. package/dist/cli/runs/search-command.js +27 -0
  114. package/dist/cli/runs/search-query.d.ts +4 -0
  115. package/dist/cli/runs/search-query.js +50 -0
  116. package/dist/cli/runs/search.d.ts +2 -1
  117. package/dist/cli/runs/search.js +6 -6
  118. package/dist/domain/attachments.js +9 -1
  119. package/dist/domain/rankings-options.js +3 -3
  120. package/dist/entities/account-change.d.ts +89 -0
  121. package/dist/entities/account-change.js +20 -0
  122. package/dist/entities/account-profile.d.ts +7 -0
  123. package/dist/entities/account-profile.js +8 -0
  124. package/dist/entities/analysis-consent.d.ts +9 -0
  125. package/dist/entities/analysis-consent.js +4 -0
  126. package/dist/entities/attachment-results.d.ts +96 -0
  127. package/dist/entities/attachment-results.js +31 -0
  128. package/dist/entities/batch-result.d.ts +27 -0
  129. package/dist/entities/batch-result.js +18 -0
  130. package/dist/entities/chat-admin.d.ts +234 -0
  131. package/dist/entities/chat-admin.js +84 -0
  132. package/dist/entities/chat-change.d.ts +25 -0
  133. package/dist/entities/chat-change.js +11 -0
  134. package/dist/entities/chat-metadata.d.ts +34 -0
  135. package/dist/entities/chat-metadata.js +15 -0
  136. package/dist/entities/chat-moderation.d.ts +44 -0
  137. package/dist/entities/chat-moderation.js +37 -0
  138. package/dist/entities/chat-tracking.d.ts +26 -0
  139. package/dist/entities/chat-tracking.js +23 -0
  140. package/dist/entities/contact-activity.d.ts +52 -0
  141. package/dist/entities/contact-activity.js +42 -0
  142. package/dist/entities/contact-context.d.ts +1568 -0
  143. package/dist/entities/contact-context.js +191 -0
  144. package/dist/entities/contact-write.d.ts +22 -0
  145. package/dist/entities/contact-write.js +6 -0
  146. package/dist/entities/conversation-preparation.d.ts +63 -0
  147. package/dist/entities/conversation-preparation.js +23 -0
  148. package/dist/entities/conversation-results.d.ts +567 -0
  149. package/dist/entities/conversation-results.js +94 -0
  150. package/dist/entities/document-link.d.ts +13 -0
  151. package/dist/entities/document-link.js +11 -0
  152. package/dist/entities/extraction-report.d.ts +95 -0
  153. package/dist/entities/extraction-report.js +34 -0
  154. package/dist/entities/image-embedding.d.ts +9 -0
  155. package/dist/entities/image-embedding.js +10 -0
  156. package/dist/entities/index.d.ts +8006 -1928
  157. package/dist/entities/index.js +174 -3
  158. package/dist/entities/listener.d.ts +2150 -0
  159. package/dist/entities/listener.js +46 -0
  160. package/dist/entities/media-archive.d.ts +43 -0
  161. package/dist/entities/media-archive.js +32 -0
  162. package/dist/entities/meeting-task-proposal.d.ts +14 -0
  163. package/dist/entities/meeting-task-proposal.js +19 -0
  164. package/dist/entities/meeting.d.ts +1 -1
  165. package/dist/entities/meeting.js +1 -1
  166. package/dist/entities/mention.d.ts +63 -0
  167. package/dist/entities/mention.js +44 -0
  168. package/dist/entities/message-change.d.ts +19 -0
  169. package/dist/entities/message-change.js +6 -0
  170. package/dist/entities/message-context.d.ts +617 -0
  171. package/dist/entities/message-context.js +20 -0
  172. package/dist/entities/message-read.d.ts +73 -0
  173. package/dist/entities/message-read.js +58 -0
  174. package/dist/entities/message-transfer.d.ts +379 -0
  175. package/dist/entities/message-transfer.js +83 -0
  176. package/dist/entities/message-write.d.ts +191 -0
  177. package/dist/entities/message-write.js +8 -0
  178. package/dist/entities/model-key.d.ts +14 -0
  179. package/dist/entities/model-key.js +10 -0
  180. package/dist/entities/poll.d.ts +40 -0
  181. package/dist/entities/poll.js +16 -0
  182. package/dist/entities/private-contact.d.ts +10 -0
  183. package/dist/entities/private-contact.js +4 -0
  184. package/dist/entities/reaction-change.d.ts +7 -0
  185. package/dist/entities/reaction-change.js +8 -0
  186. package/dist/entities/recipient.d.ts +29 -0
  187. package/dist/entities/recipient.js +11 -0
  188. package/dist/entities/recorded-run.d.ts +103 -0
  189. package/dist/entities/recorded-run.js +44 -0
  190. package/dist/entities/saved-search.d.ts +4 -0
  191. package/dist/entities/saved-search.js +2 -0
  192. package/dist/entities/send-attempt.d.ts +31 -0
  193. package/dist/entities/send-attempt.js +29 -0
  194. package/dist/entities/store-maintenance.d.ts +319 -0
  195. package/dist/entities/store-maintenance.js +145 -0
  196. package/dist/entities/store-records.d.ts +442 -0
  197. package/dist/entities/store-records.js +99 -0
  198. package/dist/entities/tag-change.d.ts +74 -0
  199. package/dist/entities/tag-change.js +31 -0
  200. package/dist/entities/task-pair.d.ts +31 -0
  201. package/dist/entities/task-pair.js +23 -0
  202. package/dist/entities/task-results.d.ts +524 -0
  203. package/dist/entities/task-results.js +142 -0
  204. package/dist/errors/reasons.js +1 -0
  205. package/dist/mcp/agent.d.ts +3 -1
  206. package/dist/mcp/agent.js +9 -6
  207. package/dist/mcp/bot/server.d.ts +2 -0
  208. package/dist/mcp/bot/server.js +1 -0
  209. package/dist/mcp/prompts.js +8 -2
  210. package/dist/mcp/server.js +3 -1
  211. package/dist/mcp/tools/attachments.js +1 -0
  212. package/dist/meetings/cli/index.js +1 -1
  213. package/dist/meetings/cli/passage.js +1 -0
  214. package/dist/meetings/index.d.ts +2 -1
  215. package/dist/meetings/index.js +1 -0
  216. package/dist/meetings/links.d.ts +16 -0
  217. package/dist/meetings/mcp/index.d.ts +15 -15
  218. package/dist/meetings/read-answers.d.ts +167 -0
  219. package/dist/meetings/read-answers.js +183 -0
  220. package/dist/runs/run.d.ts +10 -2
  221. package/dist/runs/run.js +11 -3
  222. package/dist/sends/journal.d.ts +8 -1
  223. package/dist/sends/journal.js +9 -2
  224. package/dist/sends/permissions.d.ts +5 -1
  225. package/dist/sends/permissions.js +11 -1
  226. package/dist/sends/recipients.d.ts +8 -0
  227. package/dist/sends/recipients.js +9 -0
  228. package/dist/services/admin-statistics.js +3 -3
  229. package/dist/services/chat-documents.d.ts +1 -0
  230. package/dist/services/chat-documents.js +9 -3
  231. package/dist/services/chats.d.ts +1 -1
  232. package/dist/services/chats.js +5 -2
  233. package/dist/services/meeting-links.d.ts +2 -17
  234. package/dist/store/exports.d.ts +1 -1
  235. package/dist/store/exports.js +1 -1
  236. package/dist/store/messages.d.ts +3 -1
  237. package/dist/store/messages.js +2 -2
  238. package/dist/store/roster.d.ts +4 -1
  239. package/dist/store/roster.js +2 -2
  240. package/dist/store/sqlite/chats.d.ts +12 -0
  241. package/dist/store/sqlite/chats.js +1 -0
  242. package/dist/store/sqlite/document-links.d.ts +1 -1
  243. package/dist/store/sqlite/document-links.js +5 -5
  244. package/dist/store/sqlite/involvements.js +2 -1
  245. package/dist/store/sqlite/roster.d.ts +2 -1
  246. package/dist/store/sqlite/roster.js +3 -2
  247. package/package.json +3 -3
  248. package/parity.json +76 -108
package/CHANGELOG.md CHANGED
@@ -5,6 +5,112 @@ Notable changes to `@wirecat/cli-core` (`@wirecat/cli-messaging` up to 0.261.0,
5
5
  minor version may break callers, and says how under "Changed — may break callers". `pnpm docs:check` checks the
6
6
  shape of this file.
7
7
 
8
+ ## Unreleased
9
+
10
+ ## 0.400.0 — 24.10.2026
11
+
12
+ ### Fixed
13
+
14
+ - **Downloads skip service events and keyboards.** A message whose only attachment is a group event (`control`) or an inline keyboard no longer makes a media archive or `attachments download` fail with `provider.invalid-response`; both count as non-files like polls and links.
15
+
16
+ - Account lists accept profile and current-profile query terms, and declare their answer fields for discovery and projection.
17
+
18
+ - **Account change and privacy schemas.** Profile updates, ended sessions and privacy reads and writes declare their existing answers for field discovery and projection. Privacy fields remain optional where a messenger does not expose a setting.
19
+
20
+ - **`contacts timeline` stays in its account for tasks.** A task assigned to the person now shows only when its project belongs to the asked account or to no account; before, tasks from another account of the same messenger showed too. Task rows now also name the account of their project.
21
+
22
+ ### Added
23
+
24
+ - **Meeting answer schemas.** `review`, `mentions list`, `stats meetings show` and `top`, `meetings people`, `meetings passage` and `meetings task-proposal` declare their answer entities (`meeting_review`, `meeting_link`, `meeting_stats`, `meeting_speaker`, `meeting_participants`, `meeting_passage`, `meeting_task_proposal`) for field discovery and projection. `meetings/` exports the item builders the meeting CLIs share: `meetingReviewItem`, `meetingLinkItem`, `meetingStatsItem`, `meetingSpeakerItem`.
25
+
26
+ - **Listener answers declare their fields.** Live messages and events, and the final serve summary, expose exact schemas for discovery and cross-CLI output contracts. Provider-only attachment references stay private.
27
+
28
+ - **Poll answer schemas.** Poll reads, vote and close receipts, and newly sent poll messages declare their answer entities for field discovery and projection.
29
+
30
+ - **Image embedding progress has declared fields.** Discovery and projection describe the bounded batch’s model, embedded, skipped and failed counts, and whether more pictures remain. The existing receipt and processing behavior stay unchanged.
31
+
32
+ - **Model key receipt schemas.** Storing or removing a model-provider key declares its provider and storage sources for field discovery and projection. No credential value appears in either schema or answer.
33
+
34
+ - Recipient lists accept ID and title queries without changing the allowlist state. Recipient commands declare their answer schemas for discovery and field projection.
35
+
36
+ - **Cached chat metadata declares its answers.** Cached reads describe absent or populated metadata; refresh receipts describe each successful chat or failure and whether more chats remain. Existing keys and cached-read behavior stay unchanged.
37
+
38
+ - **Contact answers have declared fields.** Address-book writes, private aliases and note removal, activity, bot checks, identity links, context and preparation expose their exact answer schemas. Context describes both the cross-account report and selected-chat message windows at every detail level. Field projection recognizes both shapes and refuses unknown fields before reading contact data. CLI, SDK and MCP receipts keep their existing shapes.
39
+
40
+ - **Mention answers have declared fields.** Mentions, details, linked domains, confirmed places, decisions and rebuild receipts expose their existing schemas for discovery, JSON field projection and MCP. Numeric local IDs and cross-account decision behavior stay unchanged.
41
+
42
+ - **Reaction answer schemas.** Add and remove declare the same reaction-change entity, including the operation id and a null reaction when removed. Field discovery and projection now describe these write receipts.
43
+
44
+ - **Tag changes declare their results.** Add and remove expose precise chat, contact, message and task target shapes. Automatic tagging describes each classification or failed chat, including preview status and remaining work; existing receipts and ownership claims stay unchanged.
45
+
46
+ - Send history includes a concrete example in help and command discovery.
47
+
48
+ - Chat document lists accept a source-message reference query, filtered in the store before link pagination, and declare their document-link answer fields.
49
+
50
+ - Doctor reports include a concrete creation example in help and command discovery.
51
+
52
+ - Send-attempt lists accept queries over their stored metadata before pagination. Continuation steps keep the query, and discovery declares the answer fields.
53
+
54
+ - **Clearing search history declares its receipt.** Discovery and JSON projection expose the existing cleared count; saved searches remain untouched.
55
+
56
+ - Recorded-run lists accept metadata queries before pagination, and recorded-run commands declare their answer schemas. Continuation steps keep the query.
57
+
58
+ - **Message read and write schemas.** Showing a message, sending, editing, forwarding, pinning, starring and deleting declare their existing answer entities for field discovery and projection. Write receipts retain their operation id.
59
+
60
+ - **Chat-state write schemas.** Muting, archiving, pinning, marking unread, deleting a chat and clearing its history declare their existing write receipts for field discovery and projection, including their operation ids.
61
+
62
+ - **Chat administration declares its answers.** Invite inspection, posting identities, read receipts, roster fetches, membership and group changes, invitations, join requests, administrators, folder writes and moderation expose their exact existing result fields, including operation identifiers and partial outcomes.
63
+
64
+ - **Message read schemas.** Evidence packets, voice transcripts and conversation links declare separate answer entities for field discovery and projection, preserving existing response keys.
65
+
66
+ - **Conversation results have declared schemas.** Builds, analysis, message batches, link changes, embedding progress, readiness, related conversations and search hits describe their existing answer fields for discovery and projection, including bounded preparation and empty batches.
67
+
68
+ - **Message context, downloads and sync have declared answers.** Context describes both message windows and bounded thread reports. Downloads retain file paths and partial extraction results; sync describes estimates, chat and all-chat progress, preparation and background jobs. General chat evidence packets and exact statistics evidence now explain their separate purposes in help and the guide.
69
+
70
+ - Analysis-consent lists accept chat and provider-identity queries, and consent commands declare their answer fields. Reading a filtered list leaves remembered permissions unchanged.
71
+
72
+ - **Attachment and media archive results have declared fields.** Extraction reports and streamed file rows, retained-file transfers, saved text, archive downloads, integrity checks, relocations and timer management describe their existing receipts. MCP resource/image transfers keep byte metadata in the same shape while carrying bytes separately.
73
+
74
+ - Tracked-chat lists accept a query over chat IDs and titles, filtered in the store. Tracking commands declare their answer schemas for field projection and discovery.
75
+
76
+ - **Task actions declare their answers.** Task cards, source previews, creation and close receipts, relationships, similarity and duplicate decisions, merges, categories and rule scans expose their exact existing fields for discovery and projection. Stored tasks and actions keep their behavior.
77
+
78
+ - **Store commands declare their answers.** Archive coverage, exports, selected-chat clearing, gap plans and repairs, background jobs, health checks, maintenance and backup/restore receipts describe their existing result fields. Missing-file and partial-result variants remain explicit; stored data and command behavior stay unchanged.
79
+
80
+ ### Changed — may break callers
81
+
82
+ - **Watch uses the shared JSONL contract.** Read each message or event from `{ type: "item", data }` and wait for the final `type: "end"` record. Message and event fields are snake_case, message values use the canonical read shape with references, and live counter observations remain available. Normal stops and timeouts finish complete; a source failure finishes incomplete and returns its failure code. Update readers of the old raw lines.
83
+
84
+ - **MCP offers the commands that change what a later run may do, behind `mcp.authority`.** `config set|unset`, `schedule command|agent|remove`, auto-reply rules and consents, recipients, chat rules, `server install`, `skill install`, model keys, media archive timers and `flood clear` are MCP tools again, offered only where the profile sets `permissions.mcp.authority` to `allow`; it is `deny` by default, so nothing changes until the owner turns it on. An agent cannot change that key through `config set`. What to change in a CLI: `grantsAuthority` no longer adds `mcp: false`, so `commands --json` no longer marks these commands, and a catalogue built with `toolsFromCommands` without `levels` lists them; update a pinned catalogue and a document that lists what MCP leaves out. A command of the CLI's own marked `grantsAuthority` (max `recipients add`) is gated the same way. A caller of `createBotServer` passes `authority: changesAuthorityAt(root)` to hide them; without it they are listed and refuse when called.
85
+
86
+ - **Diagnostic search is `search runs`.** Replace `runs search`; saved MCP requests use the new command path. Filters are query terms: `status:failed`, `error_code:timeout`, `operation:messages.download` and `profile:work`, alongside literal diagnostic words. Unsupported operators are refused; time bounds and paging remain options. The local search still needs no linked messenger profile, filters before pagination and returns diagnostic fields without message contents. No alias remains for the retired path.
87
+
88
+ - **Statistics select rows through their query.** Rankings use `message_kind:` with `posts`, `comments` or `all`, and author rankings `min_messages:5`; discussion uses `min_views:10` and `max_replies:0`; unanswered questions use `older_than:24h`. These predicates replace the corresponding filter flags and reach the existing SQL selection before aggregation or row limits. The same reports select chats with `chat:` and exact words with `exact:` instead of `--chat` and `--exact`; source and timezone remain options. Saved CLI/MCP requests must migrate. Stored selections and SDK parameters retain their meanings.
89
+
90
+ ## 0.399.0 — 23.10.2026
91
+
92
+ ### Changed — may break callers
93
+
94
+ - **Flags have one meaning.** Use `--analysis-provider` for analysis, `--embedding-provider` for vector computation, `--consent-provider` for revoking a recorded provider identity, `--claim` for tag ownership, `--answer-model` for removing stored answers and `--template-mode` for reply templates. `inbox` and `review` take `kind:group,channel` in their query. Group message lifetime is `--disappear-after`, a duration or `off`. Legacy CLI spellings remain hidden for one release and cannot be combined with their replacements. MCP callers use the canonical argument names and `query` for chat kinds; update saved MCP requests.
95
+
96
+ - cli-core requires cli-base 0.50.2 or newer within the 0.50 line for the approved option roles and messenger vocabulary.
97
+
98
+ - **Private contact notes use `--text-file`.** `--file` continues to work as a hidden compatibility alias; giving both is refused before any note is changed. New help and discovery reserve `--file` for message attachments.
99
+
100
+ ### Fixed
101
+
102
+ - **Count and grouping placeholders match the shared vocabulary.** Processing limits use `<n>` and statistics grouping uses `<group>` across supported fields and calendar units; accepted values and defaults stay the same.
103
+
104
+ ### Added
105
+
106
+ - **The shared `bot` commands have help examples and short summaries.** Each leaf under `bot` shows one to three
107
+ examples in the calling CLI's own words, and every summary fits 80 characters; `bot recipients add|remove` describe
108
+ their `<chat>`. A CLI that baselined these for `command-example-count`, `command-help-too-long` or
109
+ `missing-argument-help` sees "stale baseline entry" and removes the lines; tg, max and wa grow no baseline for them.
110
+ - **`Messenger.joinRequestsByLink`**: whether `chats requests accept|decline --all` can be narrowed with `--link`;
111
+ yes when unset. `joinRequestsAll` now turns on `--all` alone, so a messenger that answers every request at once
112
+ but does not say which invite link each came by (MAX) offers `--all` without `--link`.
113
+
8
114
  ## 0.398.0 — 23.10.2026
9
115
 
10
116
  ### Added
@@ -4,9 +4,14 @@ export interface AnalysisConsent {
4
4
  provider: string;
5
5
  at: string;
6
6
  }
7
- export declare const analysisConsents: (store: MessageStore, account: AccountKey) => {
8
- list: () => Promise<AnalysisConsent[]>;
9
- has: (chat: string, provider: string) => Promise<boolean>;
10
- remember: (chat: string, provider: string) => Promise<void>;
11
- revoke: (chat?: string, provider?: string) => Promise<void>;
12
- };
7
+ export interface AnalysisConsentFilter {
8
+ chat?: string;
9
+ provider?: string;
10
+ }
11
+ export interface AnalysisConsents {
12
+ list(filter?: AnalysisConsentFilter): Promise<AnalysisConsent[]>;
13
+ has(chat: string, provider: string): Promise<boolean>;
14
+ remember(chat: string, provider: string): Promise<void>;
15
+ revoke(chat?: string, provider?: string): Promise<void>;
16
+ }
17
+ export declare const analysisConsents: (store: MessageStore, account: AccountKey) => AnalysisConsents;
@@ -1,7 +1,7 @@
1
1
  import { CliError } from "@wirecat/cli-base";
2
2
  const KEY = "analysis-consents-v1";
3
3
  export const analysisConsents = (store, account) => {
4
- const list = async () => {
4
+ const list = async (filter) => {
5
5
  const state = await store.sync.syncState(account, KEY);
6
6
  if (!state)
7
7
  return [];
@@ -10,7 +10,10 @@ export const analysisConsents = (store, account) => {
10
10
  if (!Array.isArray(items) ||
11
11
  items.some((item) => !item || typeof item.chat !== "string" || typeof item.provider !== "string" || typeof item.at !== "string"))
12
12
  throw new Error("invalid");
13
- return items;
13
+ return filter === undefined
14
+ ? items
15
+ : items.filter((item) => (filter.chat === undefined || item.chat === filter.chat) &&
16
+ (filter.provider === undefined || item.provider === filter.provider));
14
17
  }
15
18
  catch {
16
19
  throw new CliError("configuration_error", "stored analysis consent is invalid; revoke it before running analysis");
@@ -3,6 +3,7 @@ import type { AnalysisProvider } from "../analysis/provider.js";
3
3
  import type { AppIdentity } from "../ports/app.js";
4
4
  import type { Settings } from "./settings.js";
5
5
  export interface AnalysisOptions {
6
+ analysisProvider?: string;
6
7
  provider?: string;
7
8
  model?: string;
8
9
  baseUrl?: string;
@@ -2,6 +2,9 @@ import { CliError } from "@wirecat/cli-base";
2
2
  import { endpoint } from "../analysis/settings.js";
3
3
  import { embeddingKeys, endpointKeyName } from "../embeddings/keys.js";
4
4
  export const analysisChoice = (options, app, settings, env, keyring) => {
5
+ if (options.analysisProvider !== undefined && options.provider !== undefined)
6
+ throw new CliError("validation_error", "give --analysis-provider or its legacy --provider spelling, not both");
7
+ options = { ...options, provider: options.analysisProvider ?? options.provider };
5
8
  const configured = { ...settings.models?.default, ...settings.models?.analysis };
6
9
  settings = {
7
10
  ...settings,
@@ -9,6 +9,7 @@ import { renderAnswer, snakeKeys } from "../envelope.js";
9
9
  import { rightsOf } from "../messenger/admin-commands.js";
10
10
  import { renderItem, wholeList } from "../messenger/chat-answers.js";
11
11
  import { botContext, online } from "./context.js";
12
+ import { botExamples } from "./examples.js";
12
13
  import { botCan } from "./messages.js";
13
14
  const CHAT = "a chat id, or the title of a chat this bot has seen";
14
15
  const PERSON = "the person's user id";
@@ -23,7 +24,7 @@ const personOf = (typed) => {
23
24
  export const botAdminsCommand = (bot) => {
24
25
  const offered = bot.adminRights ?? ADMIN_RIGHTS;
25
26
  const command = new Command("admins").description("the admins of a chat the bot is an admin in");
26
- annotate(command.command("list"), { effects: REMOTE_READ })
27
+ annotate(command.command("list"), { effects: REMOTE_READ, examples: botExamples(bot, "chats admins list Team") })
27
28
  .description("the chat's admins and what each may do")
28
29
  .argument("<chat>", CHAT)
29
30
  .action(async function (chat) {
@@ -35,7 +36,10 @@ export const botAdminsCommand = (bot) => {
35
36
  renderAnswer(this, context, wholeList("bot chats admins list", admins.map(snakeKeys)));
36
37
  });
37
38
  });
38
- annotate(command.command("add"), { effects: REMOTE_WRITE })
39
+ annotate(command.command("add"), {
40
+ effects: REMOTE_WRITE,
41
+ examples: botExamples(bot, "chats admins add Team 42 --title Helper"),
42
+ })
39
43
  .description("make a member an admin with these rights")
40
44
  .argument("<chat>", CHAT)
41
45
  .argument("<person>", PERSON)
@@ -61,7 +65,10 @@ export const botAdminsCommand = (bot) => {
61
65
  });
62
66
  });
63
67
  });
64
- annotate(command.command("remove"), { effects: REMOTE_WRITE })
68
+ annotate(command.command("remove"), {
69
+ effects: REMOTE_WRITE,
70
+ examples: botExamples(bot, "chats admins remove Team 42"),
71
+ })
65
72
  .description("take an admin's rights back; they stay a member")
66
73
  .argument("<chat>", CHAT)
67
74
  .argument("<person>", PERSON)
@@ -85,7 +92,10 @@ export const botAdminsCommand = (bot) => {
85
92
  */
86
93
  export const botMembersCommand = (bot) => {
87
94
  const command = new Command("members").description("the people in a chat the bot is an admin in");
88
- annotate(command.command("remove"), { effects: REMOTE_WRITE })
95
+ annotate(command.command("remove"), {
96
+ effects: REMOTE_WRITE,
97
+ examples: botExamples(bot, "chats members remove Team 42 --block"),
98
+ })
89
99
  .description("take a person out of a chat; their messages stay")
90
100
  .argument("<chat>", CHAT)
91
101
  .argument("<person>", PERSON)
@@ -9,6 +9,7 @@ import { itemOf, renderAnswer, snakeKeys } from "../envelope.js";
9
9
  import { renderItem, wholeList } from "../messenger/chat-answers.js";
10
10
  import { botAdminsCommand, botMembersCommand } from "./admins.js";
11
11
  import { botContext, online } from "./context.js";
12
+ import { botExamples } from "./examples.js";
12
13
  import { botMcpCommand } from "./mcp.js";
13
14
  import { botCan, botIdOf, botMessagesCommand } from "./messages.js";
14
15
  import { botModerateCommand, botRulesCommand } from "./moderation.js";
@@ -25,7 +26,9 @@ const secretSources = (bot, tokens) => bot.secrets?.length
25
26
  : {};
26
27
  const authCommand = (bot, tokenVariable) => {
27
28
  const auth = annotate(new Command("auth"), { mcp: false }).description("the bot token this profile uses");
28
- const set = grantsAuthority(annotate(auth.command("set"), { effects: LOCAL_WRITE })).description(`check a bot token with ${bot.name ?? "the messenger"}, then keep it — typed at a hidden prompt or piped on stdin`);
29
+ const set = grantsAuthority(annotate(auth.command("set"), { effects: LOCAL_WRITE, examples: botExamples(bot, "auth set") }))
30
+ .description(`check a bot token with ${bot.name ?? "the messenger"}, then keep it — typed at a hidden prompt or piped on stdin`)
31
+ .summary("check a bot token, then keep it; or keep a named secret beside it");
29
32
  const secrets = bot.secrets ?? [];
30
33
  if (secrets.length > 0)
31
34
  set.option("--secret <name>", `keep this secret instead of the token, the same way: ${secrets.map((one) => `${one.name} (${one.description})`).join("; ")}`);
@@ -68,7 +71,7 @@ const authCommand = (bot, tokenVariable) => {
68
71
  });
69
72
  });
70
73
  });
71
- annotate(auth.command("show"), { effects: LOCAL_READ })
74
+ annotate(auth.command("show"), { effects: LOCAL_READ, examples: botExamples(bot, "auth show") })
72
75
  .description("where this profile's bot token comes from, and which bot it is")
73
76
  .action(async function () {
74
77
  const context = online(botContext(this, bot), this);
@@ -85,7 +88,7 @@ const authCommand = (bot, tokenVariable) => {
85
88
  });
86
89
  });
87
90
  });
88
- grantsAuthority(annotate(auth.command("remove"), { effects: LOCAL_WRITE }))
91
+ grantsAuthority(annotate(auth.command("remove"), { effects: LOCAL_WRITE, examples: botExamples(bot, "auth remove") }))
89
92
  .description("forget this profile's bot token")
90
93
  .action(async function () {
91
94
  const context = botContext(this, bot);
@@ -97,7 +100,7 @@ const authCommand = (bot, tokenVariable) => {
97
100
  });
98
101
  return auth;
99
102
  };
100
- const meCommand = (bot) => annotate(new Command("me"), { effects: REMOTE_READ })
103
+ const meCommand = (bot) => annotate(new Command("me"), { effects: REMOTE_READ, examples: botExamples(bot, "me") })
101
104
  .description("the bot this profile's token belongs to: id, name and username")
102
105
  .action(async function () {
103
106
  const context = online(botContext(this, bot), this);
@@ -111,8 +114,9 @@ const meCommand = (bot) => annotate(new Command("me"), { effects: REMOTE_READ })
111
114
  }
112
115
  });
113
116
  });
114
- const listCommand = (bot, tokenVariable) => annotate(new Command("list"), { effects: LOCAL_READ })
117
+ const listCommand = (bot, tokenVariable) => annotate(new Command("list"), { effects: LOCAL_READ, examples: botExamples(bot, "list", "list --check") })
115
118
  .description(`every name on this machine that has a bot token; --check asks ${bot.name ?? "the messenger"} which bot each is`)
119
+ .summary("every bot profile on this machine; --check asks which bot each is")
116
120
  .option("--check", "ask the messenger who each bot is, with its token")
117
121
  .action(async function () {
118
122
  const context = botContext(this, bot);
@@ -154,14 +158,20 @@ const listCommand = (bot, tokenVariable) => annotate(new Command("list"), { effe
154
158
  });
155
159
  });
156
160
  const recipientsCommand = (bot) => {
157
- const command = new Command("recipients").description("the chats this bot may write to; with no list, every chat — `clear` removes the list");
158
- annotate(command.command("list"), { effects: LOCAL_READ })
161
+ const command = new Command("recipients")
162
+ .description("the chats this bot may write to; with no list, every chat — `clear` removes the list")
163
+ .summary("the chats this bot may write to; with no list, every chat");
164
+ annotate(command.command("list"), { effects: LOCAL_READ, examples: botExamples(bot, "recipients list") })
159
165
  .description("the chats on the list, or nothing when there is no list")
160
166
  .action(async function () {
161
167
  const context = botContext(this, bot);
162
168
  await context.run(async () => renderAnswer(this, context, wholeList("bot recipients list", (context.recipients().read() ?? []).map(snakeKeys))));
163
169
  });
164
- grantsAuthority(annotate(command.command("add <chat>"), { effects: LOCAL_WRITE }))
170
+ grantsAuthority(annotate(command.command("add"), {
171
+ effects: LOCAL_WRITE,
172
+ examples: botExamples(bot, "recipients add Team"),
173
+ }))
174
+ .argument("<chat>", "a chat id, `user:<id>`, or the title of a chat this bot has seen")
165
175
  .description("allow a chat: its id, `user:<id>`, or the title of a chat this bot has seen")
166
176
  .action(async function (chat) {
167
177
  const context = botContext(this, bot);
@@ -172,13 +182,17 @@ const recipientsCommand = (bot) => {
172
182
  renderAnswer(this, context, wholeList("bot recipients list", (context.recipients().read() ?? []).map(snakeKeys)));
173
183
  });
174
184
  });
175
- grantsAuthority(annotate(command.command("remove <chat>"), { effects: LOCAL_WRITE }))
185
+ grantsAuthority(annotate(command.command("remove"), {
186
+ effects: LOCAL_WRITE,
187
+ examples: botExamples(bot, "recipients remove Team"),
188
+ }))
189
+ .argument("<chat>", "the chat id, or the title as the list shows it")
176
190
  .description("take a chat off the list")
177
191
  .action(async function (chat) {
178
192
  const context = botContext(this, bot);
179
193
  await context.run(async () => renderItem(this, context, { removed: context.recipients().remove(chat) ?? null }));
180
194
  });
181
- grantsAuthority(annotate(command.command("clear"), { effects: LOCAL_WRITE }))
195
+ grantsAuthority(annotate(command.command("clear"), { effects: LOCAL_WRITE, examples: botExamples(bot, "recipients clear") }))
182
196
  .description("remove the list: the bot may write to any chat again")
183
197
  .action(async function () {
184
198
  const context = botContext(this, bot);
@@ -188,21 +202,24 @@ const recipientsCommand = (bot) => {
188
202
  };
189
203
  const sendsCommand = (bot) => new Command("sends")
190
204
  .description("what this bot sent, edited and deleted from this machine — ids and outcomes, never text")
191
- .addCommand(annotate(new Command("list"), { effects: LOCAL_READ })
205
+ .summary("what this bot sent, edited and deleted from here — never the text")
206
+ .addCommand(annotate(new Command("list"), { effects: LOCAL_READ, examples: botExamples(bot, "sends list") })
192
207
  .description("every send, edit and delete this bot made from this machine, with its outcome")
193
208
  .action(async function () {
194
209
  const context = botContext(this, bot);
195
210
  await context.run(async () => renderAnswer(this, context, wholeList("bot sends list", context.journal().entries().map(snakeKeys))));
196
211
  }));
197
212
  const chatsCommand = (bot) => {
198
- const command = new Command("chats").description(`the chats this bot is in — ${bot.name ?? "the messenger"} gives a bot no list of them, so \`list\` shows the ones it has seen`);
199
- annotate(command.command("list"), { effects: REMOTE_READ })
213
+ const command = new Command("chats")
214
+ .description(`the chats this bot is in — ${bot.name ?? "the messenger"} gives a bot no list of them, so \`list\` shows the ones it has seen`)
215
+ .summary("the chats this bot is in, and what it does there");
216
+ annotate(command.command("list"), { effects: REMOTE_READ, examples: botExamples(bot, "chats list") })
200
217
  .description(`chats this bot has seen on this machine — not a complete list from ${bot.name ?? "the messenger"}`)
201
218
  .action(async function () {
202
219
  const context = botContext(this, bot);
203
220
  await context.run(async () => renderAnswer(this, context, wholeList("bot chats list", context.registry.list().map(snakeKeys))));
204
221
  });
205
- annotate(command.command("show"), { effects: REMOTE_READ })
222
+ annotate(command.command("show"), { effects: REMOTE_READ, examples: botExamples(bot, "chats show Team") })
206
223
  .description(`one chat from ${bot.name ?? "the messenger"}, and remember it`)
207
224
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
208
225
  .action(async function (chat) {
@@ -216,7 +233,10 @@ const chatsCommand = (bot) => {
216
233
  renderItem(this, context, found);
217
234
  });
218
235
  });
219
- annotate(command.command("leave"), { effects: REMOTE_WRITE })
236
+ annotate(command.command("leave"), {
237
+ effects: REMOTE_WRITE,
238
+ examples: botExamples(bot, "chats leave Team"),
239
+ })
220
240
  .description("take the bot out of a chat; only an admin of the chat can bring it back")
221
241
  .argument("<chat>", "a chat id, or the title of a chat this bot has seen")
222
242
  .action(async function (chat) {
@@ -230,8 +250,9 @@ const chatsCommand = (bot) => {
230
250
  renderAnswer(this, context, itemOf({ operation_id: operationId, chat_id: ref, left: true }));
231
251
  });
232
252
  });
233
- annotate(command.command("action"), { effects: REMOTE_WRITE })
253
+ annotate(command.command("action"), { effects: REMOTE_WRITE, examples: botExamples(bot, "chats action Team typing") })
234
254
  .description("show what the bot is doing in a chat — typing, sending a photo — for a few seconds")
255
+ .summary("show what the bot is doing in a chat, for a few seconds")
235
256
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
236
257
  .addArgument(new Argument("<action>", "what the chat sees").choices(BOT_ACTIONS))
237
258
  .action(async function (chat, action) {
@@ -263,6 +284,7 @@ export const botCommand = (bot) => {
263
284
  const tokenVariable = envName(bot.app, "BOT_TOKEN");
264
285
  const command = new Command("bot")
265
286
  .description(`a ${bot.name ?? "messenger"} bot, through the official Bot API and a bot token — not your personal account`)
287
+ .summary("a bot account, through the official Bot API and a bot token")
266
288
  .addCommand(authCommand(bot, tokenVariable))
267
289
  .addCommand(listCommand(bot, tokenVariable))
268
290
  .addCommand(chatsCommand(bot))
@@ -0,0 +1,3 @@
1
+ import type { BotMessenger } from "./port.js";
2
+ /** Help examples for a shared bot command, in the calling CLI's own words, for a bot profile named `sales`. */
3
+ export declare const botExamples: (bot: BotMessenger, ...lines: string[]) => string[];
@@ -0,0 +1,2 @@
1
+ /** Help examples for a shared bot command, in the calling CLI's own words, for a bot profile named `sales`. */
2
+ export const botExamples = (bot, ...lines) => lines.map((line) => `${bot.app.command} sales bot ${line}`);
@@ -3,16 +3,18 @@ import { CliError } from "@wirecat/cli-base";
3
3
  import { annotate, describeProgram } from "@wirecat/cli-base/commands";
4
4
  import { Command } from "commander";
5
5
  import { environmentOf } from "../context.js";
6
- import { LOCAL_READ, REMOTE_WRITE } from "../effects.js";
6
+ import { changesAuthorityAt, LOCAL_READ, REMOTE_WRITE } from "../effects.js";
7
7
  import { itemOf, renderAnswer } from "../envelope.js";
8
8
  import { serverEntry } from "../messenger/mcp-command.js";
9
9
  import { nextStep, rootOf } from "../steps.js";
10
10
  import { botContext } from "./context.js";
11
+ import { botExamples } from "./examples.js";
11
12
  /** `bot mcp`, mounted only for a messenger that hands in its `run` on `BotMessenger.mcp`. */
12
13
  export const botMcpCommand = (bot) => {
13
14
  const { app } = bot;
14
15
  const command = annotate(new Command("mcp"), { effects: REMOTE_WRITE, lifetime: "persistent", mcp: false })
15
16
  .description(`serve this bot to an agent over MCP, on stdin and stdout — \`claude mcp add sales-bot -- ${app.command} sales bot mcp\``)
17
+ .summary("serve this bot to an agent over MCP, on stdin and stdout")
16
18
  .action(async function () {
17
19
  const context = botContext(this, bot);
18
20
  if (!context.tokens.read()) {
@@ -26,6 +28,7 @@ export const botMcpCommand = (bot) => {
26
28
  await serveBotOverStdio({
27
29
  bot,
28
30
  program: { run, commands: describeProgram(rootOf(this)) },
31
+ authority: changesAuthorityAt(rootOf(this)),
29
32
  settings: context.settings,
30
33
  levels: () => bot.resolveSettings(this.optsWithGlobals(), { env: context.env, kind: "bot" }).permissions,
31
34
  env: context.env,
@@ -33,8 +36,9 @@ export const botMcpCommand = (bot) => {
33
36
  ...(mcp.skill ? { skill: mcp.skill } : {}),
34
37
  }, context.streams.diagnostic);
35
38
  });
36
- command.addCommand(annotate(new Command("config"), { effects: LOCAL_READ })
39
+ command.addCommand(annotate(new Command("config"), { effects: LOCAL_READ, examples: botExamples(bot, "mcp config") })
37
40
  .description("print the mcpServers entry for Claude Desktop, Cursor and others, with full paths; writes nothing")
41
+ .summary("print the mcpServers entry for an MCP client; writes nothing")
38
42
  .action(function () {
39
43
  const context = botContext(this, bot);
40
44
  const { settings, env } = context;
@@ -14,6 +14,7 @@ import { messageItem } from "../messenger/message-items.js";
14
14
  import { readAll } from "../messenger/stdin.js";
15
15
  import { positiveCount } from "../paging.js";
16
16
  import { botContext } from "./context.js";
17
+ import { botExamples } from "./examples.js";
17
18
  /** The adapter's `method`, or a refusal naming what this messenger's bot cannot do. */
18
19
  export const botCan = (adapter, method, bot, what) => {
19
20
  const found = adapter[method];
@@ -59,7 +60,10 @@ const seen = (context, message) => {
59
60
  if (/^-?\d+$/.test(message.chatId))
60
61
  context.registry.observe([{ id: message.chatId }]);
61
62
  };
62
- const sendCommand = (bot) => annotate(new Command("send"), { effects: REMOTE_WRITE })
63
+ const sendCommand = (bot) => annotate(new Command("send"), {
64
+ effects: REMOTE_WRITE,
65
+ examples: botExamples(bot, 'messages send Team "Doors open at 9"', 'messages send Team "Here it is" --file report.pdf'),
66
+ })
63
67
  .description("send a message as the bot; without [text], the text is read from stdin")
64
68
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
65
69
  .argument("[text]", "the message")
@@ -120,9 +124,10 @@ const sendCommand = (bot) => annotate(new Command("send"), { effects: REMOTE_WRI
120
124
  renderAnswer(this, context, written(context, botId, { operationId }, message));
121
125
  });
122
126
  });
123
- const listCommand = (bot) => annotate(new Command("list"), { effects: REMOTE_READ })
127
+ const listCommand = (bot) => annotate(new Command("list"), { effects: REMOTE_READ, examples: botExamples(bot, "messages list Team --limit 20") })
124
128
  .description(`the latest messages in a chat; where ${bot.name ?? "the messenger"} gives a bot no history, and with --offline, ` +
125
129
  "the ones this bot has seen on this machine")
130
+ .summary("the latest messages in a chat")
126
131
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
127
132
  .option("--limit <n>", "how many, the newest", positiveCount("--limit"))
128
133
  .action(async function (chat) {
@@ -155,7 +160,7 @@ const listCommand = (bot) => annotate(new Command("list"), { effects: REMOTE_REA
155
160
  show(this, context, bot, botId, messages);
156
161
  });
157
162
  });
158
- const showCommand = (bot) => annotate(new Command("show"), { effects: REMOTE_READ })
163
+ const showCommand = (bot) => annotate(new Command("show"), { effects: REMOTE_READ, examples: botExamples(bot, "messages show Team 101") })
159
164
  .description("one message by its id in a chat")
160
165
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
161
166
  .argument("<message>", "message id")
@@ -187,7 +192,10 @@ const showCommand = (bot) => annotate(new Command("show"), { effects: REMOTE_REA
187
192
  show(this, context, bot, botId, [found], true);
188
193
  });
189
194
  });
190
- const editCommand = (bot) => annotate(new Command("edit"), { effects: REMOTE_WRITE })
195
+ const editCommand = (bot) => annotate(new Command("edit"), {
196
+ effects: REMOTE_WRITE,
197
+ examples: botExamples(bot, 'messages edit Team 101 "Doors open at 10"'),
198
+ })
191
199
  .description("replace the text of a message the bot sent")
192
200
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
193
201
  .argument("<message>", "message id")
@@ -217,7 +225,7 @@ const editCommand = (bot) => annotate(new Command("edit"), { effects: REMOTE_WRI
217
225
  renderAnswer(this, context, written(context, botId, { operationId }, message));
218
226
  });
219
227
  });
220
- const deleteCommand = (bot) => annotate(new Command("delete"), { effects: REMOTE_WRITE })
228
+ const deleteCommand = (bot) => annotate(new Command("delete"), { effects: REMOTE_WRITE, examples: botExamples(bot, "messages delete Team 101") })
221
229
  .description("delete messages in a chat the bot can delete in; it cannot be undone")
222
230
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
223
231
  .argument("<messages...>", "message ids")
@@ -235,7 +243,10 @@ const deleteCommand = (bot) => annotate(new Command("delete"), { effects: REMOTE
235
243
  });
236
244
  });
237
245
  const pinCommand = (bot, pin) => {
238
- const command = annotate(new Command(pin ? "pin" : "unpin"), { effects: REMOTE_WRITE })
246
+ const command = annotate(new Command(pin ? "pin" : "unpin"), {
247
+ effects: REMOTE_WRITE,
248
+ examples: botExamples(bot, `messages ${pin ? "pin" : "unpin"} Team 101`),
249
+ })
239
250
  .description(pin ? "pin a message in a chat; quietly unless --notify" : "unpin a message in a chat")
240
251
  .argument("<chat>", "a chat id, user:<id> for a person, or the title of a chat this bot has seen")
241
252
  .argument("<message>", "message id");
@@ -13,6 +13,7 @@ import { grantsAuthority, LOCAL_READ, LOCAL_WRITE, ownerOnlyOption, REMOTE_WRITE
13
13
  import { itemOf, renderAnswer, snakeKeys } from "../envelope.js";
14
14
  import { answerOf } from "../messenger/ask.js";
15
15
  import { botContext, online } from "./context.js";
16
+ import { botExamples } from "./examples.js";
16
17
  import { botCan, botIdOf } from "./messages.js";
17
18
  import { botFiles } from "./registry.js";
18
19
  const CHAT = "a group's id, or the title of a group this bot has seen";
@@ -34,15 +35,19 @@ const shown = (context, chatId, rules) => {
34
35
  /** `bot chats rules show|set|unset`: kept on this machine, the chat named the bot's way. */
35
36
  export const botRulesCommand = (bot) => {
36
37
  const command = new Command("rules").description("a chat's moderation rules for this bot, kept on this machine");
37
- annotate(command.command("show"), { effects: LOCAL_READ })
38
+ annotate(command.command("show"), { effects: LOCAL_READ, examples: botExamples(bot, "chats rules show Team") })
38
39
  .description("the chat's rules; the defaults, marked not saved, if it has none yet")
39
40
  .argument("<chat>", CHAT)
40
41
  .action(function (chat) {
41
42
  const context = botContext(this, bot);
42
43
  renderAnswer(this, context, shown(context, context.chatRef(chat), rulesOf(context, bot)));
43
44
  });
44
- grantsAuthority(annotate(command.command("set"), { effects: LOCAL_WRITE }))
45
+ grantsAuthority(annotate(command.command("set"), {
46
+ effects: LOCAL_WRITE,
47
+ examples: botExamples(bot, "chats rules set Team links delete"),
48
+ }))
45
49
  .description(`change one rule — ${RULE_KEYS.join(", ")}`)
50
+ .summary("change one moderation rule of a chat")
46
51
  .argument("<chat>", CHAT)
47
52
  .argument("<key>", "the rule")
48
53
  .argument("<value>", "its new value")
@@ -56,7 +61,10 @@ export const botRulesCommand = (bot) => {
56
61
  rules.set(chatId, titleOf(context, chatId), key, value);
57
62
  renderAnswer(this, context, shown(context, chatId, rules));
58
63
  });
59
- grantsAuthority(annotate(command.command("unset"), { effects: LOCAL_WRITE }))
64
+ grantsAuthority(annotate(command.command("unset"), {
65
+ effects: LOCAL_WRITE,
66
+ examples: botExamples(bot, "chats rules unset Team links"),
67
+ }))
60
68
  .description("put one rule back to its default")
61
69
  .argument("<chat>", CHAT)
62
70
  .argument("<key>", "the rule")
@@ -136,8 +144,12 @@ const yes = (answer) => /^\s*y(es)?\s*$/i.test(answer);
136
144
  * `bot chats moderate`: the personal `chats moderate`, done by the bot. Typing it is the consent for
137
145
  * what the rules name. A removal bans unless `--no-block`.
138
146
  */
139
- export const botModerateCommand = (bot) => annotate(new Command("moderate"), { effects: REMOTE_WRITE })
147
+ export const botModerateCommand = (bot) => annotate(new Command("moderate"), {
148
+ effects: REMOTE_WRITE,
149
+ examples: botExamples(bot, "chats moderate Team --dry-run"),
150
+ })
140
151
  .description("judge a group's new messages and joins by its rules, and act as they allow — as the bot")
152
+ .summary("act on a group's new messages and joins by its rules, as the bot")
141
153
  .argument("<chat>", CHAT)
142
154
  .option("--since-time <time>", "judge what came after this ISO 8601 time, or 2h / 1d ago; the saved point stays")
143
155
  .option("--dry-run", "judge and plan; do nothing")