@wirecat/cli-core 0.399.0 → 0.401.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 (259) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/README.md +1 -1
  3. package/dist/analysis/consents.d.ts +11 -6
  4. package/dist/analysis/consents.js +5 -2
  5. package/dist/cli/bot/mcp.js +2 -1
  6. package/dist/cli/bot/store.js +1 -1
  7. package/dist/cli/config-command.js +20 -1
  8. package/dist/cli/context.d.ts +2 -0
  9. package/dist/cli/context.js +1 -1
  10. package/dist/cli/effects.d.ts +4 -1
  11. package/dist/cli/effects.js +10 -2
  12. package/dist/cli/index.d.ts +3 -2
  13. package/dist/cli/index.js +3 -2
  14. package/dist/cli/json-fields.js +12 -1
  15. package/dist/cli/meeting-evidence-answer.d.ts +46 -0
  16. package/dist/cli/meeting-evidence-answer.js +22 -0
  17. package/dist/cli/meeting-preparation-answer.js +1 -13
  18. package/dist/cli/messenger/account-command.js +15 -6
  19. package/dist/cli/messenger/account-profile-query.d.ts +2 -0
  20. package/dist/cli/messenger/account-profile-query.js +13 -0
  21. package/dist/cli/messenger/account-sessions-command.js +1 -2
  22. package/dist/cli/messenger/admin-commands.js +12 -12
  23. package/dist/cli/messenger/admin-contacts-command.js +6 -3
  24. package/dist/cli/messenger/admin-folders-command.js +5 -5
  25. package/dist/cli/messenger/admin-moderation-command.js +4 -4
  26. package/dist/cli/messenger/admin-statistics-command.js +6 -14
  27. package/dist/cli/messenger/analysis-consents-query.d.ts +5 -0
  28. package/dist/cli/messenger/analysis-consents-query.js +20 -0
  29. package/dist/cli/messenger/archive-commands.js +3 -3
  30. package/dist/cli/messenger/attachments-command.js +3 -0
  31. package/dist/cli/messenger/backfill-command.js +5 -4
  32. package/dist/cli/messenger/chat-queries.d.ts +1 -0
  33. package/dist/cli/messenger/chat-queries.js +12 -2
  34. package/dist/cli/messenger/chats-command.js +2 -2
  35. package/dist/cli/messenger/chats-documents-command.js +7 -5
  36. package/dist/cli/messenger/chats-members-command.js +7 -3
  37. package/dist/cli/messenger/chats-read-command.js +1 -1
  38. package/dist/cli/messenger/chats-tracking-command.js +14 -6
  39. package/dist/cli/messenger/contacts-command.js +9 -5
  40. package/dist/cli/messenger/conversations-command.js +20 -16
  41. package/dist/cli/messenger/doctor-command.js +4 -1
  42. package/dist/cli/messenger/document-links-query.d.ts +2 -0
  43. package/dist/cli/messenger/document-links-query.js +9 -0
  44. package/dist/cli/messenger/download-command.js +1 -0
  45. package/dist/cli/messenger/flood-command.d.ts +2 -2
  46. package/dist/cli/messenger/flood-command.js +3 -3
  47. package/dist/cli/messenger/gaps-command.js +2 -2
  48. package/dist/cli/messenger/guard-commands.js +35 -13
  49. package/dist/cli/messenger/images-command.js +1 -0
  50. package/dist/cli/messenger/media-archive-command.js +2 -0
  51. package/dist/cli/messenger/media-archive-move-command.js +1 -0
  52. package/dist/cli/messenger/media-archive-timer-command.js +1 -1
  53. package/dist/cli/messenger/mentions-command.js +15 -2
  54. package/dist/cli/messenger/message-writes.d.ts +192 -2
  55. package/dist/cli/messenger/message-writes.js +6 -2
  56. package/dist/cli/messenger/messages-command.js +2 -0
  57. package/dist/cli/messenger/messages-delete-command.js +1 -0
  58. package/dist/cli/messenger/messages-edit-command.js +1 -0
  59. package/dist/cli/messenger/messages-evidence-command.js +3 -1
  60. package/dist/cli/messenger/messages-forward-command.js +1 -0
  61. package/dist/cli/messenger/messages-pin-command.js +3 -0
  62. package/dist/cli/messenger/messages-send-command.js +10 -6
  63. package/dist/cli/messenger/metadata-command.js +6 -1
  64. package/dist/cli/messenger/models-command.js +10 -5
  65. package/dist/cli/messenger/polls-command.js +4 -0
  66. package/dist/cli/messenger/private-people-command.js +3 -3
  67. package/dist/cli/messenger/rankings-command.js +6 -11
  68. package/dist/cli/messenger/reactions-command.js +2 -0
  69. package/dist/cli/messenger/recipients-query.d.ts +5 -0
  70. package/dist/cli/messenger/recipients-query.js +18 -0
  71. package/dist/cli/messenger/records-command.js +13 -8
  72. package/dist/cli/messenger/review.js +1 -1
  73. package/dist/cli/messenger/schedule-command.js +2 -2
  74. package/dist/cli/messenger/search-answers.js +2 -0
  75. package/dist/cli/messenger/search-command.js +3 -1
  76. package/dist/cli/messenger/searches-command.js +5 -1
  77. package/dist/cli/messenger/sends-query.d.ts +5 -0
  78. package/dist/cli/messenger/sends-query.js +33 -0
  79. package/dist/cli/messenger/serve-command.js +1 -0
  80. package/dist/cli/messenger/server-command.js +0 -3
  81. package/dist/cli/messenger/statistics-query.d.ts +14 -0
  82. package/dist/cli/messenger/statistics-query.js +143 -0
  83. package/dist/cli/messenger/stats-command.js +5 -5
  84. package/dist/cli/messenger/store-maintenance-command.js +10 -10
  85. package/dist/cli/messenger/stored.js +4 -1
  86. package/dist/cli/messenger/tags-command.js +7 -1
  87. package/dist/cli/messenger/tasks-command.js +57 -14
  88. package/dist/cli/messenger/transcribe-command.js +1 -0
  89. package/dist/cli/messenger/watch-answers.d.ts +6 -0
  90. package/dist/cli/messenger/watch-answers.js +69 -0
  91. package/dist/cli/messenger/watch-command.d.ts +1 -1
  92. package/dist/cli/messenger/watch-command.js +56 -7
  93. package/dist/cli/program.js +5 -1
  94. package/dist/cli/runs/command.js +25 -38
  95. package/dist/cli/runs/query.d.ts +5 -0
  96. package/dist/cli/runs/query.js +32 -0
  97. package/dist/cli/runs/search-command.d.ts +4 -0
  98. package/dist/cli/runs/search-command.js +27 -0
  99. package/dist/cli/runs/search-query.d.ts +4 -0
  100. package/dist/cli/runs/search-query.js +50 -0
  101. package/dist/cli/runs/search.d.ts +2 -1
  102. package/dist/cli/runs/search.js +6 -6
  103. package/dist/documents/index.d.ts +1 -0
  104. package/dist/documents/index.js +1 -0
  105. package/dist/domain/attachments.js +9 -1
  106. package/dist/domain/rankings-options.js +3 -3
  107. package/dist/entities/account-change.d.ts +89 -0
  108. package/dist/entities/account-change.js +20 -0
  109. package/dist/entities/account-profile.d.ts +7 -0
  110. package/dist/entities/account-profile.js +8 -0
  111. package/dist/entities/analysis-consent.d.ts +9 -0
  112. package/dist/entities/analysis-consent.js +4 -0
  113. package/dist/entities/attachment-results.d.ts +96 -0
  114. package/dist/entities/attachment-results.js +31 -0
  115. package/dist/entities/batch-result.d.ts +27 -0
  116. package/dist/entities/batch-result.js +18 -0
  117. package/dist/entities/chat-admin.d.ts +234 -0
  118. package/dist/entities/chat-admin.js +84 -0
  119. package/dist/entities/chat-change.d.ts +25 -0
  120. package/dist/entities/chat-change.js +11 -0
  121. package/dist/entities/chat-metadata.d.ts +34 -0
  122. package/dist/entities/chat-metadata.js +15 -0
  123. package/dist/entities/chat-moderation.d.ts +44 -0
  124. package/dist/entities/chat-moderation.js +37 -0
  125. package/dist/entities/chat-tracking.d.ts +26 -0
  126. package/dist/entities/chat-tracking.js +23 -0
  127. package/dist/entities/contact-activity.d.ts +52 -0
  128. package/dist/entities/contact-activity.js +42 -0
  129. package/dist/entities/contact-context.d.ts +1568 -0
  130. package/dist/entities/contact-context.js +191 -0
  131. package/dist/entities/contact-write.d.ts +22 -0
  132. package/dist/entities/contact-write.js +6 -0
  133. package/dist/entities/conversation-preparation.d.ts +63 -0
  134. package/dist/entities/conversation-preparation.js +23 -0
  135. package/dist/entities/conversation-results.d.ts +567 -0
  136. package/dist/entities/conversation-results.js +94 -0
  137. package/dist/entities/document-link.d.ts +13 -0
  138. package/dist/entities/document-link.js +11 -0
  139. package/dist/entities/extraction-report.d.ts +95 -0
  140. package/dist/entities/extraction-report.js +34 -0
  141. package/dist/entities/hit.d.ts +4 -0
  142. package/dist/entities/hit.js +4 -0
  143. package/dist/entities/image-embedding.d.ts +9 -0
  144. package/dist/entities/image-embedding.js +10 -0
  145. package/dist/entities/index.d.ts +8284 -1921
  146. package/dist/entities/index.js +178 -3
  147. package/dist/entities/listener.d.ts +2150 -0
  148. package/dist/entities/listener.js +46 -0
  149. package/dist/entities/media-archive.d.ts +43 -0
  150. package/dist/entities/media-archive.js +32 -0
  151. package/dist/entities/meeting-evidence.d.ts +86 -0
  152. package/dist/entities/meeting-evidence.js +25 -0
  153. package/dist/entities/meeting-preparation-parts.d.ts +14 -0
  154. package/dist/entities/meeting-preparation-parts.js +15 -13
  155. package/dist/entities/meeting-task-proposal.d.ts +14 -0
  156. package/dist/entities/meeting-task-proposal.js +19 -0
  157. package/dist/entities/meeting.d.ts +1 -1
  158. package/dist/entities/meeting.js +1 -1
  159. package/dist/entities/mention.d.ts +63 -0
  160. package/dist/entities/mention.js +44 -0
  161. package/dist/entities/message-change.d.ts +19 -0
  162. package/dist/entities/message-change.js +6 -0
  163. package/dist/entities/message-context.d.ts +617 -0
  164. package/dist/entities/message-context.js +20 -0
  165. package/dist/entities/message-read.d.ts +73 -0
  166. package/dist/entities/message-read.js +58 -0
  167. package/dist/entities/message-transfer.d.ts +379 -0
  168. package/dist/entities/message-transfer.js +83 -0
  169. package/dist/entities/message-write.d.ts +378 -0
  170. package/dist/entities/message-write.js +10 -0
  171. package/dist/entities/model-key.d.ts +14 -0
  172. package/dist/entities/model-key.js +10 -0
  173. package/dist/entities/poll.d.ts +40 -0
  174. package/dist/entities/poll.js +16 -0
  175. package/dist/entities/private-contact.d.ts +10 -0
  176. package/dist/entities/private-contact.js +4 -0
  177. package/dist/entities/reaction-change.d.ts +7 -0
  178. package/dist/entities/reaction-change.js +8 -0
  179. package/dist/entities/recipient.d.ts +29 -0
  180. package/dist/entities/recipient.js +11 -0
  181. package/dist/entities/recorded-run.d.ts +103 -0
  182. package/dist/entities/recorded-run.js +44 -0
  183. package/dist/entities/saved-search.d.ts +4 -0
  184. package/dist/entities/saved-search.js +2 -0
  185. package/dist/entities/send-attempt.d.ts +31 -0
  186. package/dist/entities/send-attempt.js +29 -0
  187. package/dist/entities/store-maintenance.d.ts +319 -0
  188. package/dist/entities/store-maintenance.js +145 -0
  189. package/dist/entities/store-records.d.ts +442 -0
  190. package/dist/entities/store-records.js +99 -0
  191. package/dist/entities/tag-change.d.ts +74 -0
  192. package/dist/entities/tag-change.js +31 -0
  193. package/dist/entities/task-pair.d.ts +31 -0
  194. package/dist/entities/task-pair.js +23 -0
  195. package/dist/entities/task-results.d.ts +524 -0
  196. package/dist/entities/task-results.js +142 -0
  197. package/dist/errors/reasons.js +3 -0
  198. package/dist/mcp/agent.d.ts +3 -1
  199. package/dist/mcp/agent.js +17 -10
  200. package/dist/mcp/bot/server.d.ts +2 -0
  201. package/dist/mcp/bot/server.js +1 -0
  202. package/dist/mcp/server.js +3 -1
  203. package/dist/mcp/tools/attachments.js +1 -0
  204. package/dist/meetings/cli/index.js +4 -2
  205. package/dist/meetings/cli/passage.js +1 -0
  206. package/dist/meetings/index.d.ts +2 -1
  207. package/dist/meetings/index.js +1 -0
  208. package/dist/meetings/links.d.ts +16 -0
  209. package/dist/meetings/read-answers.d.ts +185 -0
  210. package/dist/meetings/read-answers.js +213 -0
  211. package/dist/ports/messenger.d.ts +10 -1
  212. package/dist/runs/run.d.ts +10 -2
  213. package/dist/runs/run.js +11 -3
  214. package/dist/sends/guard.d.ts +1 -1
  215. package/dist/sends/guard.js +9 -5
  216. package/dist/sends/journal.d.ts +9 -2
  217. package/dist/sends/journal.js +9 -2
  218. package/dist/sends/permissions.d.ts +5 -1
  219. package/dist/sends/permissions.js +42 -2
  220. package/dist/sends/recipients.d.ts +8 -0
  221. package/dist/sends/recipients.js +9 -0
  222. package/dist/sends/upload.d.ts +4 -4
  223. package/dist/sends/upload.js +24 -20
  224. package/dist/services/admin-statistics.js +3 -3
  225. package/dist/services/chat-documents.d.ts +1 -0
  226. package/dist/services/chat-documents.js +9 -3
  227. package/dist/services/chats.d.ts +1 -1
  228. package/dist/services/chats.js +5 -2
  229. package/dist/services/documents/mirrors.d.ts +98 -0
  230. package/dist/services/documents/mirrors.js +144 -0
  231. package/dist/services/meeting-links.d.ts +2 -17
  232. package/dist/services/messages.js +1 -0
  233. package/dist/services/search-all-meetings.js +21 -8
  234. package/dist/services/task-rules.d.ts +1 -1
  235. package/dist/services/tasks.d.ts +2 -2
  236. package/dist/services/tasks.js +1 -1
  237. package/dist/store/exports.d.ts +1 -1
  238. package/dist/store/exports.js +1 -1
  239. package/dist/store/messages.d.ts +3 -1
  240. package/dist/store/messages.js +2 -2
  241. package/dist/store/roster.d.ts +4 -1
  242. package/dist/store/roster.js +2 -2
  243. package/dist/store/sqlite/chats.d.ts +12 -0
  244. package/dist/store/sqlite/chats.js +1 -0
  245. package/dist/store/sqlite/document-links.d.ts +1 -1
  246. package/dist/store/sqlite/document-links.js +5 -5
  247. package/dist/store/sqlite/drizzle/bun.js +3 -3
  248. package/dist/store/sqlite/drizzle/bun.js.map +1 -1
  249. package/dist/store/sqlite/drizzle/core.js +2 -2
  250. package/dist/store/sqlite/drizzle/core.js.map +1 -1
  251. package/dist/store/sqlite/drizzle/node.js +3 -3
  252. package/dist/store/sqlite/drizzle/node.js.map +1 -1
  253. package/dist/store/sqlite/drizzle/{shared-O7CTKP45.js → shared-HKXF6HKX.js} +57 -57
  254. package/dist/store/sqlite/drizzle/{shared-O7CTKP45.js.map → shared-HKXF6HKX.js.map} +1 -1
  255. package/dist/store/sqlite/involvements.js +2 -1
  256. package/dist/store/sqlite/roster.d.ts +2 -1
  257. package/dist/store/sqlite/roster.js +3 -2
  258. package/package.json +2 -2
  259. package/parity.json +14 -69
@@ -0,0 +1,213 @@
1
+ import { isoTime, reference } from "@wirecat/cli-base/standards";
2
+ import * as v from "valibot";
3
+ import { formatMeetingReference } from "./reference.js";
4
+ const text = v.string();
5
+ const count = v.pipe(v.number(), v.integer(), v.minValue(0));
6
+ const id = v.pipe(v.number(), v.integer(), v.minValue(1));
7
+ const iso = (ms) => (ms === null ? null : new Date(ms).toISOString());
8
+ const meetingRef = (accountId, meetingId) => formatMeetingReference({ type: "meeting", accountId, meetingId });
9
+ /** One meeting in `review`: what the store holds about it, never transcript text. */
10
+ export const meetingReview = v.strictObject({
11
+ ref: reference,
12
+ id: v.pipe(v.string(), v.minLength(1)),
13
+ title: v.nullable(text),
14
+ started_at: v.nullable(isoTime),
15
+ duration_ms: v.nullable(count),
16
+ participants_count: v.nullable(count),
17
+ projects: v.array(text),
18
+ /** Null when the meeting has no current transcript. */
19
+ transcript: v.nullable(v.strictObject({ lines: count, words: count })),
20
+ /** The three who talked longest. */
21
+ speakers: v.array(v.strictObject({ name: v.nullable(text), talk_ms: count })),
22
+ /** The newest stored summary; null when there is none. */
23
+ summary: v.nullable(v.strictObject({
24
+ source: text,
25
+ title: v.nullable(text),
26
+ overview: v.nullable(text),
27
+ next_steps: v.array(text),
28
+ url: v.nullable(text),
29
+ })),
30
+ });
31
+ export const meetingReviewItem = (one) => ({
32
+ ref: meetingRef(one.accountId, one.meetingId),
33
+ id: String(one.meetingId),
34
+ title: one.title,
35
+ started_at: iso(one.startedAt),
36
+ duration_ms: one.durationMs,
37
+ participants_count: one.participantsCount,
38
+ projects: one.projects,
39
+ transcript: one.transcript,
40
+ speakers: one.speakers.map((speaker) => ({ name: speaker.name, talk_ms: speaker.talkMs })),
41
+ summary: one.summary && {
42
+ source: one.summary.source,
43
+ title: one.summary.title,
44
+ overview: one.summary.overview,
45
+ next_steps: one.summary.nextSteps,
46
+ url: one.summary.url,
47
+ },
48
+ });
49
+ /** A link shared in meeting chat, with where and how often; `mentions list` answers these. */
50
+ export const meetingLink = v.strictObject({
51
+ url: text,
52
+ domain: v.nullable(text),
53
+ /** The Google Docs, Sheets, Slides, Forms or Drive file it names. */
54
+ document_id: v.nullable(text),
55
+ count,
56
+ first_at: isoTime,
57
+ last_at: isoTime,
58
+ senders: v.array(text),
59
+ meetings: v.array(v.strictObject({ ref: reference, title: v.nullable(text) })),
60
+ });
61
+ export const meetingLinkItem = (link) => ({
62
+ url: link.url,
63
+ domain: link.domain,
64
+ document_id: link.documentId,
65
+ count: link.count,
66
+ first_at: new Date(link.firstAt).toISOString(),
67
+ last_at: new Date(link.lastAt).toISOString(),
68
+ senders: link.senders,
69
+ meetings: link.meetings.map((one) => ({ ref: meetingRef(one.accountId, one.meetingId), title: one.title })),
70
+ });
71
+ /** One speaker's talk over the selected meetings; `stats meetings top` answers these. */
72
+ export const meetingSpeaker = v.strictObject({
73
+ /** `person:<id>`, `identity:<id>`, `name:<lowercased name>` or `unknown`. */
74
+ key: text,
75
+ name: v.nullable(text),
76
+ person_id: v.nullable(id),
77
+ identity_id: v.nullable(id),
78
+ meetings: count,
79
+ lines: count,
80
+ words: count,
81
+ talk_ms: count,
82
+ /** This speaker's part of all talk time, 0–1. */
83
+ share: v.pipe(v.number(), v.minValue(0), v.maxValue(1)),
84
+ });
85
+ export const meetingSpeakerItem = (one) => ({
86
+ key: one.key,
87
+ name: one.name,
88
+ person_id: one.personId,
89
+ identity_id: one.identityId,
90
+ meetings: one.meetings,
91
+ lines: one.lines,
92
+ words: one.words,
93
+ talk_ms: one.talkMs,
94
+ share: one.share,
95
+ });
96
+ /** `stats meetings show`: how much was said over the selected meetings, by week, with the top speakers. */
97
+ export const meetingStats = v.strictObject({
98
+ time_zone: text,
99
+ meetings: count,
100
+ lines: count,
101
+ words: count,
102
+ talk_ms: count,
103
+ /** `week_start` is the Monday, as a date in `time_zone`. */
104
+ weeks: v.array(v.strictObject({ week_start: text, meetings: count, talk_ms: count })),
105
+ top_speakers: v.array(meetingSpeaker),
106
+ });
107
+ export const meetingStatsItem = (found, top = 10) => ({
108
+ time_zone: found.timeZone,
109
+ meetings: found.meetings,
110
+ lines: found.lines,
111
+ words: found.words,
112
+ talk_ms: found.talkMs,
113
+ weeks: found.weeks.map((week) => ({ week_start: week.weekStart, meetings: week.meetings, talk_ms: week.talkMs })),
114
+ top_speakers: found.speakers.slice(0, top).map(meetingSpeakerItem),
115
+ });
116
+ const truncated = (...why) => v.nullable(v.picklist(why));
117
+ /** `meetings people`: one page of participant observations whose name or email matches. */
118
+ export const meetingParticipants = v.strictObject({
119
+ schema_version: v.literal(1),
120
+ kind: v.literal("meeting_participants"),
121
+ account_id: id,
122
+ query: text,
123
+ items: v.array(v.strictObject({
124
+ participant_id: id,
125
+ meeting_id: id,
126
+ identity_id: id,
127
+ display_name: v.nullable(text),
128
+ email: v.nullable(text),
129
+ })),
130
+ /** Several identities on one page are observations, never speaker attribution or person links. */
131
+ ambiguity: v.strictObject({ scope: v.literal("page"), multiple_identities: v.boolean(), identity_ids: v.array(id) }),
132
+ coverage: v.strictObject({
133
+ scanned: count,
134
+ read_bytes: count,
135
+ archive_completeness: v.literal("unknown"),
136
+ truncated_by: truncated("limit", "scan_limit", "read_bytes"),
137
+ }),
138
+ page: v.strictObject({
139
+ mode: v.literal("cursor"),
140
+ limit: count,
141
+ has_more: v.boolean(),
142
+ next_cursor: v.optional(text),
143
+ }),
144
+ });
145
+ const revision = v.picklist(["current", "superseded"]);
146
+ /** `meetings passage`: a transcript line with the lines around it. */
147
+ export const meetingPassage = v.strictObject({
148
+ schema_version: v.literal(1),
149
+ kind: v.literal("meeting_context"),
150
+ source: reference,
151
+ target_ref: reference,
152
+ target_fingerprint: text,
153
+ fingerprint: text,
154
+ revision,
155
+ limits: v.strictObject({ before: count, after: count, bytes: count, max_read_bytes: count }),
156
+ content_bytes: count,
157
+ coverage: v.strictObject({
158
+ included: count,
159
+ before: count,
160
+ after: count,
161
+ has_before: v.boolean(),
162
+ has_after: v.boolean(),
163
+ truncated_by: truncated("bytes"),
164
+ before_ref: v.nullable(reference),
165
+ after_ref: v.nullable(reference),
166
+ continuation: v.literal("anchor-inclusive"),
167
+ archive_completeness: v.literal("unknown"),
168
+ input: v.literal("bounded-meeting-context"),
169
+ }),
170
+ items: v.array(v.strictObject({
171
+ ref: reference,
172
+ fingerprint: text,
173
+ transcript_id: id,
174
+ content_hash: v.nullable(text),
175
+ position: count,
176
+ start_ms: count,
177
+ end_ms: count,
178
+ speaker_participant_id: v.nullable(id),
179
+ speaker_name: v.nullable(text),
180
+ text,
181
+ revision,
182
+ })),
183
+ });
184
+ /** A stored event a meeting belongs to; `id` is what `meetings update --event-id` takes. */
185
+ export const event = v.strictObject({
186
+ id: v.pipe(v.string(), v.minLength(1)),
187
+ event_series_id: v.nullable(text),
188
+ title: v.nullable(text),
189
+ description: v.nullable(text),
190
+ location: v.nullable(text),
191
+ starts_at: v.nullable(isoTime),
192
+ ends_at: v.nullable(isoTime),
193
+ timezone: v.nullable(text),
194
+ /** `auto`: made from a meeting; `owner`: made by hand. */
195
+ origin: v.picklist(["auto", "owner"]),
196
+ deleted_at: v.nullable(isoTime),
197
+ created_at: isoTime,
198
+ updated_at: isoTime,
199
+ });
200
+ export const eventItem = (one) => ({
201
+ id: String(one.id),
202
+ event_series_id: one.eventSeriesId === null ? null : String(one.eventSeriesId),
203
+ title: one.title,
204
+ description: one.description,
205
+ location: one.location,
206
+ starts_at: iso(one.startsAt),
207
+ ends_at: iso(one.endsAt),
208
+ timezone: one.timezone,
209
+ origin: one.origin,
210
+ deleted_at: iso(one.deletedAt),
211
+ created_at: new Date(one.createdAt).toISOString(),
212
+ updated_at: new Date(one.updatedAt).toISOString(),
213
+ });
@@ -41,7 +41,10 @@ export interface SendOptions {
41
41
  formatting?: TextSpan[];
42
42
  /** ISO time: the messenger holds it and sends it then, under a new id. */
43
43
  at?: string;
44
- /** Sent in one message, `text` as the caption. More than one is an album. */
44
+ /**
45
+ * Sent in one message, `text` as the caption. More than one is an album: photos first, then files, each in the
46
+ * order given. An adapter whose messenger cannot send one refuses it with `validation_error` before anything goes.
47
+ */
45
48
  attachments?: Upload[];
46
49
  /** One sticker by id, alone: no text, no attachment. Only where `Messenger.stickers` is on. */
47
50
  sticker?: Id;
@@ -82,7 +85,13 @@ export interface NewPoll {
82
85
  closeAfter?: number;
83
86
  }
84
87
  export interface Sent {
88
+ /** The message sent; for an album, its first. */
85
89
  message: Message;
90
+ /**
91
+ * For an album, every message it made, in order, `message` among them. Unset for a single message, and where an
92
+ * adapter has not learned to answer with them yet.
93
+ */
94
+ messages?: Message[];
86
95
  /** The send's identity. Repeat it after an unknown outcome, never a new one. */
87
96
  sendId: string;
88
97
  }
@@ -87,7 +87,7 @@ export declare const runsDirFor: (app: AppIdentity, env?: NodeJS.ProcessEnv) =>
87
87
  * `run.json` is written **now**, with `status: "running"`, and again by `finish`. A directory
88
88
  * holding events and no metadata is a special case `runs list` would carry forever.
89
89
  *
90
- * Each write also appends the metadata to the day's `index.jsonl`, which `runs list` and `runs search`
90
+ * Each write also appends the metadata to the day's `index.jsonl`, which `runs list` and `search runs`
91
91
  * read instead of every `run.json`. It is only a cache: pruned with its day, and a day without one is read
92
92
  * the slow way.
93
93
  */
@@ -95,13 +95,21 @@ export declare const startRun: (options: StartRunOptions) => Run;
95
95
  export declare const runtime: () => string;
96
96
  /** `20260920T084431Z-chats-list-a81f2c` — sortable, and readable without opening it. */
97
97
  export declare const newRunId: (startedAt: Date, command: string) => string;
98
+ export interface RunListFilter {
99
+ runId?: string;
100
+ command?: string;
101
+ profile?: string;
102
+ status?: RunMetadata["status"];
103
+ errorCode?: string;
104
+ }
98
105
  /**
99
106
  * Newest first, which is the order anyone asking "what did I just do" wants. Days before `since` are
100
107
  * not opened, nor any day once `atLeast` runs are in hand.
101
108
  */
102
- export declare const listRuns: (runsDir: string, { since, atLeast }?: {
109
+ export declare const listRuns: (runsDir: string, { since, atLeast, filter, }?: {
103
110
  since?: number;
104
111
  atLeast?: number;
112
+ filter?: RunListFilter;
105
113
  }) => RunMetadata[];
106
114
  export declare const findRun: (runsDir: string, id: string) => {
107
115
  dir: string;
package/dist/runs/run.js CHANGED
@@ -19,7 +19,7 @@ export const runsDirFor = (app, env = process.env) => join(resolvePaths({ appNam
19
19
  * `run.json` is written **now**, with `status: "running"`, and again by `finish`. A directory
20
20
  * holding events and no metadata is a special case `runs list` would carry forever.
21
21
  *
22
- * Each write also appends the metadata to the day's `index.jsonl`, which `runs list` and `runs search`
22
+ * Each write also appends the metadata to the day's `index.jsonl`, which `runs list` and `search runs`
23
23
  * read instead of every `run.json`. It is only a cache: pruned with its day, and a day without one is read
24
24
  * the slow way.
25
25
  */
@@ -124,17 +124,25 @@ const writeRunFile = (dir, metadata) => {
124
124
  // The index only makes reading faster; a day without one is read run by run.
125
125
  }
126
126
  };
127
+ const matchesListFilter = (run, filter) => (filter.runId === undefined || run.runId === filter.runId) &&
128
+ (filter.command === undefined || run.command === filter.command) &&
129
+ (filter.profile === undefined || run.profile === filter.profile) &&
130
+ (filter.status === undefined || run.status === filter.status) &&
131
+ (filter.errorCode === undefined || run.errorCode === filter.errorCode);
127
132
  /**
128
133
  * Newest first, which is the order anyone asking "what did I just do" wants. Days before `since` are
129
134
  * not opened, nor any day once `atLeast` runs are in hand.
130
135
  */
131
- export const listRuns = (runsDir, { since, atLeast = Number.POSITIVE_INFINITY } = {}) => {
136
+ export const listRuns = (runsDir, { since, atLeast = Number.POSITIVE_INFINITY, filter = {}, } = {}) => {
132
137
  const first = since === undefined ? undefined : day(new Date(since));
133
138
  const runs = [];
134
139
  for (const date of days(runsDir).sort().reverse()) {
135
140
  if ((first !== undefined && date < first) || runs.length >= atLeast)
136
141
  break;
137
- runs.push(...runsOfDay(join(runsDir, date)));
142
+ for (const metadata of runsOfDay(join(runsDir, date))) {
143
+ if (matchesListFilter(metadata, filter))
144
+ runs.push(metadata);
145
+ }
138
146
  }
139
147
  return runs;
140
148
  };
@@ -12,7 +12,7 @@ export interface GuardRequest {
12
12
  chatId: Id | null;
13
13
  kind?: SendKind;
14
14
  action?: ChatAction | AccountAction;
15
- /** Messages a deletion names, or people a chat change adds. */
15
+ /** Messages a deletion names or an album sends, or people a chat change adds. */
16
16
  count?: number;
17
17
  sendId?: string;
18
18
  sendAs?: Id;
@@ -40,11 +40,11 @@ const countsTowardLimit = ({ kind = "message", action, notify }) => kind === "me
40
40
  action === "join" ||
41
41
  action === "contact-import";
42
42
  /**
43
- * Each deleted message, each person added to a group or let in by a request, and each imported number
44
- * counts as one.
43
+ * Each deleted message, each photo or file of an album (`NEED-1660`), each person added to a group or let in by a
44
+ * request, and each imported number counts as one.
45
45
  */
46
- const weightOf = ({ kind, action, count, people }) => kind === "delete"
47
- ? (count ?? 1)
46
+ const weightOf = ({ kind = "message", action, count, people }) => kind === "delete" || (kind === "message" && action === undefined)
47
+ ? Math.max(1, count ?? 1)
48
48
  : action === "create" || action === "members.add" || action === "requests.accept" || action === "contact-import"
49
49
  ? Math.max(1, people ?? count ?? 1)
50
50
  : 1;
@@ -180,7 +180,11 @@ export const sendGuard = ({ profile, recipients, command = recipients.command, r
180
180
  reservation: id,
181
181
  ...(kind ? { kind } : {}),
182
182
  ...(action ? { action } : {}),
183
- ...(asked.people === undefined ? {} : kind === "delete" ? { count: asked.people } : { people: asked.people }),
183
+ ...(asked.people === undefined
184
+ ? {}
185
+ : kind === "delete" || kind === "message" || kind === undefined
186
+ ? { count: asked.people }
187
+ : { people: asked.people }),
184
188
  ...(sendId === undefined ? {} : { sendId }),
185
189
  ...(operationId === undefined ? {} : { operationId }),
186
190
  ...(scheduledFor ? { scheduledFor } : {}),
@@ -23,7 +23,7 @@ export interface SendEntry {
23
23
  messageId?: Id;
24
24
  /** The command a write belongs to, where it named one: `polls.create` sets a poll apart from a message. */
25
25
  key?: string;
26
- /** How many messages a `delete` entry named — each one counts toward the hourly limit. */
26
+ /** How many messages a `delete` entry named, or an album sent — each one counts toward the hourly limit. */
27
27
  count?: number;
28
28
  forEveryone?: boolean;
29
29
  /**
@@ -59,6 +59,13 @@ export interface SendEntry {
59
59
  reservation?: string;
60
60
  errorCode?: string;
61
61
  }
62
+ export interface SendFilter {
63
+ outcome?: SendOutcome;
64
+ chatId?: Id;
65
+ operationId?: string;
66
+ errorCode?: string;
67
+ key?: string;
68
+ }
62
69
  /**
63
70
  * `<state dir>/sends/<profile>.jsonl` — beside `runs`, never in the cache directory, so that
64
71
  * clearing a cache cannot erase what was sent in the owner's name.
@@ -88,5 +95,5 @@ export declare class SendJournal {
88
95
  * Oldest first, each reservation folded into its outcome; one with no outcome yet is in flight,
89
96
  * or its process died. A line that does not parse is skipped: a torn last write must not block sending.
90
97
  */
91
- entries(): SendEntry[];
98
+ entries(filter?: SendFilter): SendEntry[];
92
99
  }
@@ -54,13 +54,20 @@ export class SendJournal {
54
54
  * Oldest first, each reservation folded into its outcome; one with no outcome yet is in flight,
55
55
  * or its process died. A line that does not parse is skipped: a torn last write must not block sending.
56
56
  */
57
- entries() {
57
+ entries(filter) {
58
58
  const lines = this.#lines();
59
59
  const settled = new Set(lines.filter((entry) => entry.outcome !== "reserved").map((entry) => entry.reservation));
60
- return lines
60
+ const entries = lines
61
61
  .filter((entry) => entry.outcome !== "reserved" || !settled.has(entry.reservation))
62
62
  .map(({ reservation, ...entry }) => (entry.outcome === "reserved" ? { ...entry, reservation } : entry))
63
63
  .map(withSendId);
64
+ return filter === undefined
65
+ ? entries
66
+ : entries.filter((entry) => (filter.outcome === undefined || entry.outcome === filter.outcome) &&
67
+ (filter.chatId === undefined || entry.chatId === filter.chatId) &&
68
+ (filter.operationId === undefined || entry.operationId === filter.operationId) &&
69
+ (filter.errorCode === undefined || entry.errorCode === filter.errorCode) &&
70
+ (filter.key === undefined || entry.key === filter.key));
64
71
  }
65
72
  #lines() {
66
73
  let text;
@@ -17,8 +17,12 @@ export type PermissionKey = string;
17
17
  export declare const skipFlagFor: (key: string) => "--allow-dangerous" | "--yes";
18
18
  /** Only what cannot be undone asks; the tool is meant to work without questions (owner, NEED-460). */
19
19
  export declare const DEFAULT_PERMISSIONS: Readonly<Record<PermissionKey, Level>>;
20
+ /** Lets an MCP server offer the commands that change what a later run may do (`grantsAuthority`). */
21
+ export declare const AUTHORITY_KEY: PermissionKey;
22
+ /** Whether these levels let an agent run a command that changes what a later run may do; `ask` does, as for any write. */
23
+ export declare const authorityAllowed: (levels: Readonly<Record<PermissionKey, Level>>) => boolean;
20
24
  /** The resources at the top of the command tree, which `readOnly` and `allow` turn read-only as a whole. */
21
- export declare const RESOURCES: readonly ["messages", "reactions", "polls", "topics", "chats", "contacts", "account", "bot", "conversations", "tags", "mentions", "search", "searches", "tasks", "replies", "attachments", "stats", "store", "metadata"];
25
+ export declare const RESOURCES: readonly ["messages", "reactions", "polls", "topics", "chats", "contacts", "account", "bot", "conversations", "tags", "mentions", "search", "searches", "tasks", "replies", "attachments", "stats", "store", "metadata", "mcp", "server", "models", "schedule", "doctor", "images"];
22
26
  /** The command path an old `allow` word stood for, as one key — what an MCP tool's `permission` is checked against. */
23
27
  export declare const keyOfWord: (word: Permission) => PermissionKey;
24
28
  /**
@@ -77,6 +77,35 @@ export const DEFAULT_PERMISSIONS = {
77
77
  "chats.clear": "ask",
78
78
  // NEED-568: a rule writes to people with nobody typing a command; it waits for the owner's own allow.
79
79
  "replies.send": "deny",
80
+ // NEED-1662: an agent that changes settings, schedules or recipients could lift its own limits; the owner opts in.
81
+ "mcp.authority": "deny",
82
+ // NEED-1663: writes no level stopped before, so MCP could not offer them; over MCP `ask` goes ahead.
83
+ "store.backup": "ask",
84
+ "store.restore": "ask",
85
+ "store.migrate": "ask",
86
+ "store.repair": "ask",
87
+ "store.reset": "ask",
88
+ "store.clear": "ask",
89
+ "store.decrypt": "ask",
90
+ "store.copies.delete": "ask",
91
+ "server.start": "ask",
92
+ "server.stop": "ask",
93
+ "server.restart": "ask",
94
+ "models.audio.download": "ask",
95
+ "models.text.download": "ask",
96
+ "images.models.download": "ask",
97
+ "schedule.run": "ask",
98
+ "schedule.exec": "ask",
99
+ "doctor.report.create": "ask",
100
+ };
101
+ /** Commands under a housekeeping word, or store maintenance, that still have a key of their own: their path. */
102
+ const KEYED_UNDER_HOUSEKEEPING = new Set(Object.keys(DEFAULT_PERMISSIONS).filter((key) => /^(store|server|models|images|schedule|doctor)\./.test(key)));
103
+ /** Lets an MCP server offer the commands that change what a later run may do (`grantsAuthority`). */
104
+ export const AUTHORITY_KEY = "mcp.authority";
105
+ /** Whether these levels let an agent run a command that changes what a later run may do; `ask` does, as for any write. */
106
+ export const authorityAllowed = (levels) => {
107
+ const { level } = levelFor(levels, AUTHORITY_KEY);
108
+ return level === "allow" || level === "ask";
80
109
  };
81
110
  /** The resources at the top of the command tree, which `readOnly` and `allow` turn read-only as a whole. */
82
111
  export const RESOURCES = [
@@ -99,6 +128,12 @@ export const RESOURCES = [
99
128
  "stats",
100
129
  "store",
101
130
  "metadata",
131
+ "mcp",
132
+ "server",
133
+ "models",
134
+ "schedule",
135
+ "doctor",
136
+ "images",
102
137
  ];
103
138
  const OLD_WORDS = {
104
139
  send: ["messages.send", "polls.create", "chats.start"],
@@ -365,7 +400,7 @@ const HOUSEKEEPING = new Set([
365
400
  ]);
366
401
  /** Under `bot`: its token, its names, its lists and its MCP server. */
367
402
  const BOT_HOUSEKEEPING = new Set(["auth", "list", "sends", "recipients", "mcp"]);
368
- const STORE_MAINTENANCE = new Set(["info", "check", "migrate", "backup", "restore", "repair", "copies"]);
403
+ const STORE_MAINTENANCE = new Set(["info", "check", "copies"]);
369
404
  /** Commands outside `messages` that print what people wrote, so `deny messages` reaches them too. */
370
405
  const SHOW_MESSAGES = new Set(["inbox", "review", "watch", "serve", "store", "conversations"]);
371
406
  /** Before every search moved under `search` (2026-10-09). */
@@ -395,6 +430,9 @@ export const readKeysForCommand = (path) => {
395
430
  return [key, "messages"];
396
431
  if (path[0] === "store" && path[1] === "gaps" && path[2] === "repair")
397
432
  return [key, "messages"];
433
+ // Checked as `messages` before they had keys of their own: `deny messages` keeps stopping them.
434
+ if (path[0] === "store" && ["reset", "clear", "decrypt"].includes(path[1] ?? ""))
435
+ return [key, "messages"];
398
436
  // A search shows what people wrote, so `deny messages` reaches every leaf that reads messages.
399
437
  if (path[0] === "search") {
400
438
  if (path[1] === "notes")
@@ -428,7 +466,9 @@ export const keyForCommand = (path) => {
428
466
  const inner = keyForCommand(path.slice(1));
429
467
  return `bot.${inner ?? path.slice(1).join(".")}`;
430
468
  }
431
- if (top === undefined || HOUSEKEEPING.has(top))
469
+ if (KEYED_UNDER_HOUSEKEEPING.has(path.join(".")))
470
+ return path.join(".");
471
+ if (top === undefined || HOUSEKEEPING.has(top) || (top === "search" && next === "runs"))
432
472
  return null;
433
473
  // Picture models moved from `models image` (0.270.0); a model is housekeeping wherever it is listed.
434
474
  if (top === "images" && next === "models")
@@ -7,6 +7,10 @@ export interface Recipient {
7
7
  partnerId?: Id;
8
8
  addedAt: string;
9
9
  }
10
+ export interface RecipientFilter {
11
+ id?: Id;
12
+ title?: string;
13
+ }
10
14
  /**
11
15
  * A state file, not a setting: the configuration schema has deliberately no place for a chat id,
12
16
  * and this list is data about a profile rather than a preference.
@@ -25,6 +29,10 @@ export declare class RecipientList {
25
29
  constructor(path: string, command: string, lockWaitMs?: number | undefined);
26
30
  /** `undefined` when the list is off. A file that cannot be read refuses rather than opening up. */
27
31
  read(): Recipient[] | undefined;
32
+ list(filter?: RecipientFilter): {
33
+ state: "off" | "empty" | "on";
34
+ items: Recipient[];
35
+ };
28
36
  /** Whether it was new. Adding one again fills in a partner an older entry was stored without. */
29
37
  add(recipient: Recipient): boolean;
30
38
  /** `add` waiting for the lock on timers: `recipients add` connects, so it runs inside `serve` when one holds the account. */
@@ -36,6 +36,15 @@ export class RecipientList {
36
36
  `fix the file or turn the list off with \`${this.command} recipients clear\``);
37
37
  }
38
38
  }
39
+ list(filter = {}) {
40
+ const chats = this.read();
41
+ // A query that matches nothing must not describe a nonempty allowlist as allowing nowhere.
42
+ return {
43
+ state: chats === undefined ? "off" : chats.length === 0 ? "empty" : "on",
44
+ items: (chats ?? []).filter((chat) => (filter.id === undefined || chat.id === filter.id) &&
45
+ (filter.title === undefined || chat.title?.toLocaleLowerCase() === filter.title.toLocaleLowerCase())),
46
+ };
47
+ }
39
48
  /** Whether it was new. Adding one again fills in a partner an older entry was stored without. */
40
49
  add(recipient) {
41
50
  return this.#locked(() => this.#added(recipient));
@@ -18,12 +18,12 @@ export declare const readUpload: (kind: UploadKind, path: string, { app, env, an
18
18
  photoTypes?: readonly string[];
19
19
  }) => Promise<Upload>;
20
20
  /**
21
- * What a send attaches, as `messages send` and its tool take it. A voice message goes alone, as the
22
- * messengers' own apps send one.
21
+ * What a send attaches, as `messages send` and its tool take it. More than one photo or file is an album: photos
22
+ * first, then files, each in the order given. A voice message goes alone, as the messengers' own apps send one.
23
23
  */
24
24
  export declare const readAttachments: ({ photo, file, voice, asFile, filename, text, }: {
25
- photo?: string;
26
- file?: string;
25
+ photo?: string | readonly string[];
26
+ file?: string | readonly string[];
27
27
  voice?: string;
28
28
  asFile?: boolean;
29
29
  filename?: string;
@@ -197,37 +197,41 @@ export const readUpload = async (kind, path, { app, env = process.env, anyFile =
197
197
  }
198
198
  return { kind, name: basename(path), source: { kind: "file", path: resolve(path), size } };
199
199
  };
200
- const checkFilename = (filename, file) => {
201
- if (file === undefined)
200
+ const checkFilename = (filename, files) => {
201
+ if (files.length === 0)
202
202
  throw new CliError("validation_error", "--filename names a --file; give one");
203
+ if (files.length > 1)
204
+ throw new CliError("validation_error", "--filename names one --file; an album keeps its names");
203
205
  if (filename.trim() === "" || /[/\\\0]/.test(filename) || filename.length > 255)
204
206
  throw new CliError("validation_error", "--filename is a name, not a path: no / or \\, at most 255 characters");
205
207
  };
208
+ const listOf = (value) => value === undefined ? [] : typeof value === "string" ? [value] : value;
206
209
  /**
207
- * What a send attaches, as `messages send` and its tool take it. A voice message goes alone, as the
208
- * messengers' own apps send one.
210
+ * What a send attaches, as `messages send` and its tool take it. More than one photo or file is an album: photos
211
+ * first, then files, each in the order given. A voice message goes alone, as the messengers' own apps send one.
209
212
  */
210
213
  export const readAttachments = async ({ photo, file, voice, asFile, filename, text, }, read) => {
211
- if (voice !== undefined && (photo !== undefined || file !== undefined || (text ?? "").trim() !== "")) {
214
+ const photos = listOf(photo);
215
+ const files = listOf(file);
216
+ if (voice !== undefined && (photos.length > 0 || files.length > 0 || (text ?? "").trim() !== "")) {
212
217
  throw new CliError("validation_error", "a voice message goes alone — no text, no file, no photo beside it");
213
218
  }
214
- if (asFile && file === undefined)
219
+ if (asFile && files.length === 0)
215
220
  throw new CliError("validation_error", "--as-file is about a --file; give one");
216
221
  if (filename !== undefined)
217
- checkFilename(filename, file);
218
- return [
219
- ...(photo === undefined ? [] : [await readUpload("photo", photo, read)]),
220
- ...(file === undefined
221
- ? []
222
- : [
223
- {
224
- ...(await readUpload("file", file, read)),
225
- ...(filename === undefined ? {} : { name: filename }),
226
- ...(asFile ? { asFile: true } : {}),
227
- },
228
- ]),
229
- ...(voice === undefined ? [] : [await readUpload("voice", voice, read)]),
230
- ];
222
+ checkFilename(filename, files);
223
+ const uploads = [];
224
+ for (const one of photos)
225
+ uploads.push(await readUpload("photo", one, read));
226
+ for (const one of files)
227
+ uploads.push({
228
+ ...(await readUpload("file", one, read)),
229
+ ...(filename === undefined ? {} : { name: filename }),
230
+ ...(asFile ? { asFile: true } : {}),
231
+ });
232
+ if (voice !== undefined)
233
+ uploads.push(await readUpload("voice", voice, read));
234
+ return uploads;
231
235
  };
232
236
  /** A sticker to send from a file: a WebP image of at most `maxBytes`, behind the same file guard as `--file`. */
233
237
  export const readStickerFile = async (path, maxBytes, read) => {
@@ -216,12 +216,12 @@ export const adminStatisticsService = (deps) => ({
216
216
  cutoff,
217
217
  olderThan: query.olderThan === undefined && pinned
218
218
  ? pinned.options.olderThan
219
- : duration(query.olderThan ?? "24h", "--older-than"),
219
+ : duration(query.olderThan ?? "24h", "older_than"),
220
220
  within: query.within === undefined && pinned ? pinned.options.within : duration(query.within ?? "7d", "--within"),
221
221
  joinSince: window.since ?? pinned?.options.joinSince ?? cutoff - 30 * 86_400_000,
222
222
  joinUntil: window.until ?? pinned?.options.joinUntil ?? cutoff,
223
- minViews: count(query.minViews ?? pinned?.options.minViews ?? 1, "--min-views"),
224
- maxReplies: count(query.maxReplies ?? pinned?.options.maxReplies ?? 0, "--max-replies"),
223
+ minViews: count(query.minViews ?? pinned?.options.minViews ?? 1, "min_views"),
224
+ maxReplies: count(query.maxReplies ?? pinned?.options.maxReplies ?? 0, "max_replies"),
225
225
  answerers: query.answerers === undefined && pinned
226
226
  ? pinned.options.answerers
227
227
  : await answerers(store, query.answerers ?? [], prepared.execution.accounts),
@@ -23,6 +23,7 @@ export interface ChatDocumentsService {
23
23
  list(chat: string, window: {
24
24
  limit?: number;
25
25
  offset: number;
26
+ ref?: string;
26
27
  }): Promise<ChatDocuments>;
27
28
  }
28
29
  export declare const chatDocumentsService: (deps: ServiceDeps) => ChatDocumentsService;