@wirecat/cli-core 0.263.0 → 0.265.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.
- package/README.md +226 -486
- package/dist/background/schedules.d.ts +2 -0
- package/dist/background/schedules.d.ts.map +1 -1
- package/dist/background/schedules.js +26 -8
- package/dist/background/schedules.js.map +1 -1
- package/dist/cli/envelope.d.ts +2 -0
- package/dist/cli/envelope.d.ts.map +1 -1
- package/dist/cli/envelope.js +2 -2
- package/dist/cli/envelope.js.map +1 -1
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/list-query.d.ts +42 -0
- package/dist/cli/list-query.d.ts.map +1 -0
- package/dist/cli/list-query.js +121 -0
- package/dist/cli/list-query.js.map +1 -0
- package/dist/cli/messenger/admin-commands.d.ts.map +1 -1
- package/dist/cli/messenger/admin-commands.js +34 -46
- package/dist/cli/messenger/admin-commands.js.map +1 -1
- package/dist/cli/messenger/admin-contacts-command.d.ts.map +1 -1
- package/dist/cli/messenger/admin-contacts-command.js +7 -3
- package/dist/cli/messenger/admin-contacts-command.js.map +1 -1
- package/dist/cli/messenger/admin-folders-command.d.ts.map +1 -1
- package/dist/cli/messenger/admin-folders-command.js +21 -21
- package/dist/cli/messenger/admin-folders-command.js.map +1 -1
- package/dist/cli/messenger/admin-moderation-command.d.ts.map +1 -1
- package/dist/cli/messenger/admin-moderation-command.js +11 -13
- package/dist/cli/messenger/admin-moderation-command.js.map +1 -1
- package/dist/cli/messenger/backfill-command.d.ts.map +1 -1
- package/dist/cli/messenger/backfill-command.js +10 -6
- package/dist/cli/messenger/backfill-command.js.map +1 -1
- package/dist/cli/messenger/backfill-jobs.d.ts +1 -1
- package/dist/cli/messenger/backfill-jobs.d.ts.map +1 -1
- package/dist/cli/messenger/backfill-jobs.js +1 -1
- package/dist/cli/messenger/backfill-jobs.js.map +1 -1
- package/dist/cli/messenger/chat-answers.d.ts +155 -0
- package/dist/cli/messenger/chat-answers.d.ts.map +1 -0
- package/dist/cli/messenger/chat-answers.js +243 -0
- package/dist/cli/messenger/chat-answers.js.map +1 -0
- package/dist/cli/messenger/chat-lists.d.ts +161 -0
- package/dist/cli/messenger/chat-lists.d.ts.map +1 -0
- package/dist/cli/messenger/chat-lists.js +82 -0
- package/dist/cli/messenger/chat-lists.js.map +1 -0
- package/dist/cli/messenger/chat-queries.d.ts +14 -0
- package/dist/cli/messenger/chat-queries.d.ts.map +1 -0
- package/dist/cli/messenger/chat-queries.js +48 -0
- package/dist/cli/messenger/chat-queries.js.map +1 -0
- package/dist/cli/messenger/chats-bots-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-bots-command.js +7 -2
- package/dist/cli/messenger/chats-bots-command.js.map +1 -1
- package/dist/cli/messenger/chats-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-command.js +33 -71
- package/dist/cli/messenger/chats-command.js.map +1 -1
- package/dist/cli/messenger/chats-documents-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-documents-command.js +10 -5
- package/dist/cli/messenger/chats-documents-command.js.map +1 -1
- package/dist/cli/messenger/chats-members-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-members-command.js +38 -64
- package/dist/cli/messenger/chats-members-command.js.map +1 -1
- package/dist/cli/messenger/chats-read-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-read-command.js +4 -2
- package/dist/cli/messenger/chats-read-command.js.map +1 -1
- package/dist/cli/messenger/chats-stats-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-stats-command.js +24 -17
- package/dist/cli/messenger/chats-stats-command.js.map +1 -1
- package/dist/cli/messenger/chats-tracking-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-tracking-command.js +11 -17
- package/dist/cli/messenger/chats-tracking-command.js.map +1 -1
- package/dist/cli/messenger/contacts-command.d.ts.map +1 -1
- package/dist/cli/messenger/contacts-command.js +61 -43
- package/dist/cli/messenger/contacts-command.js.map +1 -1
- package/dist/cli/messenger/context.d.ts.map +1 -1
- package/dist/cli/messenger/context.js +5 -2
- package/dist/cli/messenger/context.js.map +1 -1
- package/dist/cli/messenger/conversations-command.d.ts.map +1 -1
- package/dist/cli/messenger/conversations-command.js +13 -20
- package/dist/cli/messenger/conversations-command.js.map +1 -1
- package/dist/cli/messenger/gaps-command.js +3 -3
- package/dist/cli/messenger/gaps-command.js.map +1 -1
- package/dist/cli/messenger/hearing-command.d.ts +1 -1
- package/dist/cli/messenger/hearing-command.d.ts.map +1 -1
- package/dist/cli/messenger/hearing-command.js +1 -1
- package/dist/cli/messenger/hearing-command.js.map +1 -1
- package/dist/cli/messenger/history-query.d.ts +18 -0
- package/dist/cli/messenger/history-query.d.ts.map +1 -0
- package/dist/cli/messenger/history-query.js +63 -0
- package/dist/cli/messenger/history-query.js.map +1 -0
- package/dist/cli/messenger/images-command.d.ts +8 -0
- package/dist/cli/messenger/images-command.d.ts.map +1 -0
- package/dist/cli/messenger/images-command.js +36 -0
- package/dist/cli/messenger/images-command.js.map +1 -0
- package/dist/cli/messenger/list-query.d.ts +13 -0
- package/dist/cli/messenger/list-query.d.ts.map +1 -0
- package/dist/cli/messenger/list-query.js +23 -0
- package/dist/cli/messenger/list-query.js.map +1 -0
- package/dist/cli/messenger/mentions-command.d.ts +5 -0
- package/dist/cli/messenger/mentions-command.d.ts.map +1 -0
- package/dist/cli/messenger/mentions-command.js +51 -0
- package/dist/cli/messenger/mentions-command.js.map +1 -0
- package/dist/cli/messenger/message-items.d.ts +31 -0
- package/dist/cli/messenger/message-items.d.ts.map +1 -0
- package/dist/cli/messenger/message-items.js +95 -0
- package/dist/cli/messenger/message-items.js.map +1 -0
- package/dist/cli/messenger/messages-command.d.ts.map +1 -1
- package/dist/cli/messenger/messages-command.js +52 -77
- package/dist/cli/messenger/messages-command.js.map +1 -1
- package/dist/cli/messenger/messages-comments-command.d.ts.map +1 -1
- package/dist/cli/messenger/messages-comments-command.js +39 -28
- package/dist/cli/messenger/messages-comments-command.js.map +1 -1
- package/dist/cli/messenger/messages-link-command.d.ts.map +1 -1
- package/dist/cli/messenger/messages-link-command.js +16 -14
- package/dist/cli/messenger/messages-link-command.js.map +1 -1
- package/dist/cli/messenger/messages-scheduled-command.d.ts.map +1 -1
- package/dist/cli/messenger/messages-scheduled-command.js +23 -26
- package/dist/cli/messenger/messages-scheduled-command.js.map +1 -1
- package/dist/cli/messenger/messages-search-command.d.ts.map +1 -1
- package/dist/cli/messenger/messages-search-command.js +6 -0
- package/dist/cli/messenger/messages-search-command.js.map +1 -1
- package/dist/cli/messenger/models-command.d.ts.map +1 -1
- package/dist/cli/messenger/models-command.js +57 -0
- package/dist/cli/messenger/models-command.js.map +1 -1
- package/dist/cli/messenger/people-queries.d.ts +6 -0
- package/dist/cli/messenger/people-queries.d.ts.map +1 -0
- package/dist/cli/messenger/people-queries.js +15 -0
- package/dist/cli/messenger/people-queries.js.map +1 -0
- package/dist/cli/messenger/polls-command.d.ts.map +1 -1
- package/dist/cli/messenger/polls-command.js +29 -23
- package/dist/cli/messenger/polls-command.js.map +1 -1
- package/dist/cli/messenger/reactions-command.d.ts.map +1 -1
- package/dist/cli/messenger/reactions-command.js +6 -2
- package/dist/cli/messenger/reactions-command.js.map +1 -1
- package/dist/cli/messenger/serve-command.d.ts.map +1 -1
- package/dist/cli/messenger/serve-command.js +21 -33
- package/dist/cli/messenger/serve-command.js.map +1 -1
- package/dist/cli/messenger/serve-members.d.ts +2 -1
- package/dist/cli/messenger/serve-members.d.ts.map +1 -1
- package/dist/cli/messenger/serve-members.js +11 -2
- package/dist/cli/messenger/serve-members.js.map +1 -1
- package/dist/cli/messenger/serve-notice.d.ts +21 -0
- package/dist/cli/messenger/serve-notice.d.ts.map +1 -0
- package/dist/cli/messenger/serve-notice.js +40 -0
- package/dist/cli/messenger/serve-notice.js.map +1 -0
- package/dist/cli/messenger/serve-stems.d.ts +2 -1
- package/dist/cli/messenger/serve-stems.d.ts.map +1 -1
- package/dist/cli/messenger/serve-stems.js +2 -1
- package/dist/cli/messenger/serve-stems.js.map +1 -1
- package/dist/cli/messenger/tags-command.d.ts.map +1 -1
- package/dist/cli/messenger/tags-command.js +11 -30
- package/dist/cli/messenger/tags-command.js.map +1 -1
- package/dist/cli/messenger/tasks-command.d.ts.map +1 -1
- package/dist/cli/messenger/tasks-command.js +13 -22
- package/dist/cli/messenger/tasks-command.js.map +1 -1
- package/dist/cli/messenger/topics-command.d.ts.map +1 -1
- package/dist/cli/messenger/topics-command.js +21 -9
- package/dist/cli/messenger/topics-command.js.map +1 -1
- package/dist/cli/runs/log-attributes.d.ts +5 -0
- package/dist/cli/runs/log-attributes.d.ts.map +1 -0
- package/dist/cli/runs/log-attributes.js +67 -0
- package/dist/cli/runs/log-attributes.js.map +1 -0
- package/dist/cli/runs/record-log.d.ts +8 -0
- package/dist/cli/runs/record-log.d.ts.map +1 -0
- package/dist/cli/runs/record-log.js +17 -0
- package/dist/cli/runs/record-log.js.map +1 -0
- package/dist/cli/runs/recording.d.ts +4 -1
- package/dist/cli/runs/recording.d.ts.map +1 -1
- package/dist/cli/runs/recording.js +11 -3
- package/dist/cli/runs/recording.js.map +1 -1
- package/dist/cli/runs/run.d.ts +4 -0
- package/dist/cli/runs/run.d.ts.map +1 -1
- package/dist/cli/runs/run.js +4 -0
- package/dist/cli/runs/run.js.map +1 -1
- package/dist/cli/runs/scope.d.ts +17 -0
- package/dist/cli/runs/scope.d.ts.map +1 -1
- package/dist/cli/runs/scope.js +25 -1
- package/dist/cli/runs/scope.js.map +1 -1
- package/dist/cli/settings.d.ts +4 -0
- package/dist/cli/settings.d.ts.map +1 -1
- package/dist/cli/settings.js +4 -0
- package/dist/cli/settings.js.map +1 -1
- package/dist/cli/steps.d.ts.map +1 -1
- package/dist/cli/steps.js +24 -0
- package/dist/cli/steps.js.map +1 -1
- package/dist/domain/google-documents.d.ts +4 -0
- package/dist/domain/google-documents.d.ts.map +1 -1
- package/dist/domain/google-documents.js +7 -6
- package/dist/domain/google-documents.js.map +1 -1
- package/dist/domain/mentions.d.ts +22 -0
- package/dist/domain/mentions.d.ts.map +1 -0
- package/dist/domain/mentions.js +139 -0
- package/dist/domain/mentions.js.map +1 -0
- package/dist/embeddings/embed.d.ts.map +1 -1
- package/dist/embeddings/embed.js +1 -4
- package/dist/embeddings/embed.js.map +1 -1
- package/dist/embeddings/models.d.ts +1 -1
- package/dist/entities/attachment.d.ts +6 -0
- package/dist/entities/attachment.d.ts.map +1 -1
- package/dist/entities/attachment.js +6 -0
- package/dist/entities/attachment.js.map +1 -1
- package/dist/entities/chat-event.d.ts +28 -0
- package/dist/entities/chat-event.d.ts.map +1 -0
- package/dist/entities/chat-event.js +19 -0
- package/dist/entities/chat-event.js.map +1 -0
- package/dist/entities/chat.d.ts +29 -0
- package/dist/entities/chat.d.ts.map +1 -1
- package/dist/entities/chat.js +15 -0
- package/dist/entities/chat.js.map +1 -1
- package/dist/entities/contact.d.ts +137 -0
- package/dist/entities/contact.d.ts.map +1 -1
- package/dist/entities/contact.js +6 -1
- package/dist/entities/contact.js.map +1 -1
- package/dist/entities/conversation.d.ts +16 -0
- package/dist/entities/conversation.d.ts.map +1 -0
- package/dist/entities/conversation.js +17 -0
- package/dist/entities/conversation.js.map +1 -0
- package/dist/entities/folder.d.ts +31 -0
- package/dist/entities/folder.d.ts.map +1 -0
- package/dist/entities/folder.js +25 -0
- package/dist/entities/folder.js.map +1 -0
- package/dist/entities/index.d.ts +385 -1
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/index.js +21 -1
- package/dist/entities/index.js.map +1 -1
- package/dist/entities/invite-link.d.ts +17 -0
- package/dist/entities/invite-link.d.ts.map +1 -0
- package/dist/entities/invite-link.js +18 -0
- package/dist/entities/invite-link.js.map +1 -0
- package/dist/entities/join-request.d.ts +12 -0
- package/dist/entities/join-request.d.ts.map +1 -0
- package/dist/entities/join-request.js +13 -0
- package/dist/entities/join-request.js.map +1 -0
- package/dist/entities/member.d.ts +24 -0
- package/dist/entities/member.d.ts.map +1 -0
- package/dist/entities/member.js +25 -0
- package/dist/entities/member.js.map +1 -0
- package/dist/entities/message-link.d.ts +10 -0
- package/dist/entities/message-link.d.ts.map +1 -0
- package/dist/entities/message-link.js +11 -0
- package/dist/entities/message-link.js.map +1 -0
- package/dist/entities/message.d.ts +19 -0
- package/dist/entities/message.d.ts.map +1 -1
- package/dist/entities/message.js +4 -0
- package/dist/entities/message.js.map +1 -1
- package/dist/entities/poll-vote.d.ts +11 -0
- package/dist/entities/poll-vote.d.ts.map +1 -0
- package/dist/entities/poll-vote.js +12 -0
- package/dist/entities/poll-vote.js.map +1 -0
- package/dist/entities/tagging.d.ts +14 -0
- package/dist/entities/tagging.d.ts.map +1 -0
- package/dist/entities/tagging.js +16 -0
- package/dist/entities/tagging.js.map +1 -0
- package/dist/entities/topic.d.ts +14 -0
- package/dist/entities/topic.d.ts.map +1 -0
- package/dist/entities/topic.js +15 -0
- package/dist/entities/topic.js.map +1 -0
- package/dist/images/picture/embedder.d.ts +15 -0
- package/dist/images/picture/embedder.d.ts.map +1 -0
- package/dist/images/picture/embedder.js +48 -0
- package/dist/images/picture/embedder.js.map +1 -0
- package/dist/images/picture/models.d.ts +27 -0
- package/dist/images/picture/models.d.ts.map +1 -0
- package/dist/images/picture/models.js +55 -0
- package/dist/images/picture/models.js.map +1 -0
- package/dist/images/picture/preprocess.d.ts +28 -0
- package/dist/images/picture/preprocess.d.ts.map +1 -0
- package/dist/images/picture/preprocess.js +48 -0
- package/dist/images/picture/preprocess.js.map +1 -0
- package/dist/mcp/agent-log.d.ts +7 -0
- package/dist/mcp/agent-log.d.ts.map +1 -1
- package/dist/mcp/agent-log.js +32 -0
- package/dist/mcp/agent-log.js.map +1 -1
- package/dist/mcp/instructions.d.ts.map +1 -1
- package/dist/mcp/instructions.js +3 -2
- package/dist/mcp/instructions.js.map +1 -1
- package/dist/mcp/prompts.js +3 -3
- package/dist/mcp/prompts.js.map +1 -1
- package/dist/mcp/tool.d.ts +1 -1
- package/dist/mcp/tool.d.ts.map +1 -1
- package/dist/mcp/tool.js +23 -11
- package/dist/mcp/tool.js.map +1 -1
- package/dist/mcp/tools/admin.d.ts.map +1 -1
- package/dist/mcp/tools/admin.js +41 -39
- package/dist/mcp/tools/admin.js.map +1 -1
- package/dist/mcp/tools/chats-read.d.ts.map +1 -1
- package/dist/mcp/tools/chats-read.js +4 -2
- package/dist/mcp/tools/chats-read.js.map +1 -1
- package/dist/mcp/tools/chats.d.ts.map +1 -1
- package/dist/mcp/tools/chats.js +77 -84
- package/dist/mcp/tools/chats.js.map +1 -1
- package/dist/mcp/tools/contacts-write.d.ts.map +1 -1
- package/dist/mcp/tools/contacts-write.js +4 -2
- package/dist/mcp/tools/contacts-write.js.map +1 -1
- package/dist/mcp/tools/contacts.d.ts.map +1 -1
- package/dist/mcp/tools/contacts.js +55 -30
- package/dist/mcp/tools/contacts.js.map +1 -1
- package/dist/mcp/tools/conversations.d.ts.map +1 -1
- package/dist/mcp/tools/conversations.js +12 -15
- package/dist/mcp/tools/conversations.js.map +1 -1
- package/dist/mcp/tools/folders.d.ts.map +1 -1
- package/dist/mcp/tools/folders.js +12 -11
- package/dist/mcp/tools/folders.js.map +1 -1
- package/dist/mcp/tools/messages.d.ts.map +1 -1
- package/dist/mcp/tools/messages.js +74 -59
- package/dist/mcp/tools/messages.js.map +1 -1
- package/dist/mcp/tools/moderation.d.ts.map +1 -1
- package/dist/mcp/tools/moderation.js +5 -3
- package/dist/mcp/tools/moderation.js.map +1 -1
- package/dist/mcp/tools/polls.d.ts.map +1 -1
- package/dist/mcp/tools/polls.js +31 -14
- package/dist/mcp/tools/polls.js.map +1 -1
- package/dist/mcp/tools/reactions.d.ts.map +1 -1
- package/dist/mcp/tools/reactions.js +4 -2
- package/dist/mcp/tools/reactions.js.map +1 -1
- package/dist/mcp/tools/search.d.ts +2 -0
- package/dist/mcp/tools/search.d.ts.map +1 -1
- package/dist/mcp/tools/tags.d.ts.map +1 -1
- package/dist/mcp/tools/tags.js +16 -11
- package/dist/mcp/tools/tags.js.map +1 -1
- package/dist/mcp/tools/tasks.d.ts.map +1 -1
- package/dist/mcp/tools/tasks.js +15 -20
- package/dist/mcp/tools/tasks.js.map +1 -1
- package/dist/mcp/tools/topics.d.ts.map +1 -1
- package/dist/mcp/tools/topics.js +30 -20
- package/dist/mcp/tools/topics.js.map +1 -1
- package/dist/meetings/cli/passage.d.ts.map +1 -1
- package/dist/meetings/cli/passage.js +6 -2
- package/dist/meetings/cli/passage.js.map +1 -1
- package/dist/sends/guard.js +3 -1
- package/dist/sends/guard.js.map +1 -1
- package/dist/sends/journal.d.ts.map +1 -1
- package/dist/sends/journal.js +11 -8
- package/dist/sends/journal.js.map +1 -1
- package/dist/sends/permissions.d.ts +1 -1
- package/dist/sends/permissions.d.ts.map +1 -1
- package/dist/sends/permissions.js +6 -1
- package/dist/sends/permissions.js.map +1 -1
- package/dist/services/admin.js +2 -2
- package/dist/services/admin.js.map +1 -1
- package/dist/services/backfill-jobs.d.ts +11 -1
- package/dist/services/backfill-jobs.d.ts.map +1 -1
- package/dist/services/backfill-jobs.js +36 -4
- package/dist/services/backfill-jobs.js.map +1 -1
- package/dist/services/chats.d.ts +6 -20
- package/dist/services/chats.d.ts.map +1 -1
- package/dist/services/chats.js +6 -43
- package/dist/services/chats.js.map +1 -1
- package/dist/services/conversations.d.ts +18 -4
- package/dist/services/conversations.d.ts.map +1 -1
- package/dist/services/conversations.js +29 -2
- package/dist/services/conversations.js.map +1 -1
- package/dist/services/deps.d.ts +5 -0
- package/dist/services/deps.d.ts.map +1 -1
- package/dist/services/deps.js.map +1 -1
- package/dist/services/document-pictures.d.ts +26 -0
- package/dist/services/document-pictures.d.ts.map +1 -0
- package/dist/services/document-pictures.js +37 -0
- package/dist/services/document-pictures.js.map +1 -0
- package/dist/services/index.d.ts +8 -3
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +8 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/meeting-hit-context.d.ts.map +1 -1
- package/dist/services/meeting-hit-context.js +5 -2
- package/dist/services/meeting-hit-context.js.map +1 -1
- package/dist/services/mentions.d.ts +30 -0
- package/dist/services/mentions.d.ts.map +1 -0
- package/dist/services/mentions.js +38 -0
- package/dist/services/mentions.js.map +1 -0
- package/dist/services/messages.d.ts +10 -0
- package/dist/services/messages.d.ts.map +1 -1
- package/dist/services/messages.js +1 -0
- package/dist/services/messages.js.map +1 -1
- package/dist/services/notes-search.d.ts +14 -1
- package/dist/services/notes-search.d.ts.map +1 -1
- package/dist/services/notes-search.js +46 -1
- package/dist/services/notes-search.js.map +1 -1
- package/dist/services/people.d.ts +1 -1
- package/dist/services/people.d.ts.map +1 -1
- package/dist/services/people.js +0 -18
- package/dist/services/people.js.map +1 -1
- package/dist/services/pictures.d.ts +56 -0
- package/dist/services/pictures.d.ts.map +1 -0
- package/dist/services/pictures.js +226 -0
- package/dist/services/pictures.js.map +1 -0
- package/dist/services/tags.d.ts +17 -6
- package/dist/services/tags.d.ts.map +1 -1
- package/dist/services/tags.js +42 -5
- package/dist/services/tags.js.map +1 -1
- package/dist/services/tasks.d.ts +28 -9
- package/dist/services/tasks.d.ts.map +1 -1
- package/dist/services/tasks.js +69 -11
- package/dist/services/tasks.js.map +1 -1
- package/dist/speech/hearing.d.ts +3 -0
- package/dist/speech/hearing.d.ts.map +1 -1
- package/dist/speech/hearing.js +16 -0
- package/dist/speech/hearing.js.map +1 -1
- package/dist/speech/install.d.ts +1 -1
- package/dist/speech/install.d.ts.map +1 -1
- package/dist/speech/install.js.map +1 -1
- package/dist/sqlite-runtime.d.ts +1 -1
- package/dist/sqlite-runtime.js +2 -2
- package/dist/sqlite-runtime.js.map +1 -1
- package/dist/store/account-store.d.ts +1 -1
- package/dist/store/account-store.d.ts.map +1 -1
- package/dist/store/account-store.js +5 -0
- package/dist/store/account-store.js.map +1 -1
- package/dist/store/drivers/bun-sqlite.js +1 -1
- package/dist/store/drivers/bun-sqlite.js.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/sqlite/conversations.d.ts +36 -4
- package/dist/store/sqlite/conversations.d.ts.map +1 -1
- package/dist/store/sqlite/conversations.js +20 -3
- package/dist/store/sqlite/conversations.js.map +1 -1
- package/dist/store/sqlite/document-pictures.d.ts +29 -0
- package/dist/store/sqlite/document-pictures.d.ts.map +1 -0
- package/dist/store/sqlite/document-pictures.js +81 -0
- package/dist/store/sqlite/document-pictures.js.map +1 -0
- package/dist/store/sqlite/emails.d.ts +10 -0
- package/dist/store/sqlite/emails.d.ts.map +1 -1
- package/dist/store/sqlite/emails.js +14 -0
- package/dist/store/sqlite/emails.js.map +1 -1
- package/dist/store/sqlite/entity-types.d.ts +1 -0
- package/dist/store/sqlite/entity-types.d.ts.map +1 -1
- package/dist/store/sqlite/entity-types.js +1 -0
- package/dist/store/sqlite/entity-types.js.map +1 -1
- package/dist/store/sqlite/image-chunks.d.ts +33 -2
- package/dist/store/sqlite/image-chunks.d.ts.map +1 -1
- package/dist/store/sqlite/image-chunks.js +45 -6
- package/dist/store/sqlite/image-chunks.js.map +1 -1
- package/dist/store/sqlite/manifest.d.ts.map +1 -1
- package/dist/store/sqlite/manifest.js +2 -0
- package/dist/store/sqlite/manifest.js.map +1 -1
- package/dist/store/sqlite/mentions.d.ts +61 -0
- package/dist/store/sqlite/mentions.d.ts.map +1 -0
- package/dist/store/sqlite/mentions.js +186 -0
- package/dist/store/sqlite/mentions.js.map +1 -0
- package/dist/store/sqlite/migrations.generated.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.generated.js +19 -0
- package/dist/store/sqlite/migrations.generated.js.map +1 -1
- package/dist/store/sqlite/note-index.d.ts.map +1 -1
- package/dist/store/sqlite/note-index.js +3 -0
- package/dist/store/sqlite/note-index.js.map +1 -1
- package/dist/store/sqlite/note-search.d.ts +2 -1
- package/dist/store/sqlite/note-search.d.ts.map +1 -1
- package/dist/store/sqlite/note-search.js +4 -1
- package/dist/store/sqlite/note-search.js.map +1 -1
- package/dist/store/sqlite/notes.js +1 -1
- package/dist/store/sqlite/notes.js.map +1 -1
- package/dist/store/sqlite/schema.d.ts +339 -0
- package/dist/store/sqlite/schema.d.ts.map +1 -1
- package/dist/store/sqlite/schema.js +35 -0
- package/dist/store/sqlite/schema.js.map +1 -1
- package/dist/store/sqlite/tags.d.ts +7 -0
- package/dist/store/sqlite/tags.d.ts.map +1 -1
- package/dist/store/sqlite/tags.js +16 -9
- package/dist/store/sqlite/tags.js.map +1 -1
- package/dist/store/sqlite/tasks.d.ts +11 -1
- package/dist/store/sqlite/tasks.d.ts.map +1 -1
- package/dist/store/sqlite/tasks.js +11 -0
- package/dist/store/sqlite/tasks.js.map +1 -1
- package/dist/store/store.d.ts +57 -3
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +57 -7
- package/dist/store/store.js.map +1 -1
- package/package.json +6 -5
- package/parity.json +65 -104
- package/skills/follow-ups/SKILL.md +1 -1
- package/dist/cli/messenger/after.d.ts +0 -20
- package/dist/cli/messenger/after.d.ts.map +0 -1
- package/dist/cli/messenger/after.js +0 -27
- package/dist/cli/messenger/after.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,391 +4,240 @@
|
|
|
4
4
|
|
|
5
5
|
# @wirecat/cli-core
|
|
6
6
|
|
|
7
|
-
The
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
**Status: on npm** — what each version changed is in [CHANGELOG.md](CHANGELOG.md). The domain model, message locators, message rendering, name
|
|
13
|
-
resolution, the SQLite seam that runs under Node and Bun, and the first part of the command
|
|
14
|
-
skeleton with the shared read commands, the send guard, run records and the message store — see
|
|
15
|
-
[the platform proposal](docs/dev/BACKLOG.md).
|
|
16
|
-
|
|
17
|
-
## Retained meeting references
|
|
18
|
-
|
|
19
|
-
`parseMeetingReference`, `formatMeetingReference` and `canonicalMeetingReference` name local meeting
|
|
20
|
-
records as `meeting:<accountId>/<meetingId>`, a retained transcript revision with `/<transcriptId>`,
|
|
21
|
-
and one cue with `/<cuePosition>`. IDs are positive safe integers; cue positions start at zero.
|
|
22
|
-
These references stay within one store and retain the exact revision after a correction.
|
|
23
|
-
They use a dedicated parser; the general `parseReference` and existing knowledge targets do not
|
|
24
|
-
accept them yet. A reader must verify the caller's authorized account before returning content.
|
|
25
|
-
|
|
26
|
-
## Canonical project and label vocabulary
|
|
27
|
-
|
|
28
|
-
`store.knowledge.vocabulary({ kind?, scope?, maxEntries?, maxReadBytes?, signal? })` lists live owner
|
|
29
|
-
projects and tags/topics with stable IDs, aliases, usage counts and a preview fingerprint.
|
|
30
|
-
`resolveVocabulary(name, options)` matches only explicit aliases, canonical names or project keys;
|
|
31
|
-
several matches remain ambiguous. Unicode normalization preserves accents and distinct letters.
|
|
32
|
-
Person/contact aliases are independent and retain their existing behavior.
|
|
33
|
-
|
|
34
|
-
`addVocabularyAlias({ kind, id }, name, { expectedFingerprint?, by?, signal? })` and
|
|
35
|
-
`removeVocabularyAlias(target, aliasId, options)` are owner writes with transactional collision and
|
|
36
|
-
stale-preview checks. Creating a project cannot shadow an existing project alias. Knowledge labels,
|
|
37
|
-
main-topic selection and label filters resolve an exact tag/topic alias to its canonical name.
|
|
38
|
-
|
|
39
|
-
`tagPreflight(name, { kind?, maxEntries?, maxReadBytes?, signal? })` returns `reuse`, `create` or
|
|
40
|
-
`review`, with lexical candidates and a vocabulary fingerprint. Its separate `creationFingerprint`
|
|
41
|
-
binds owner approval to the requested name, kind and current label/alias metadata. Similarity suggests
|
|
42
|
-
review; it never selects a synonym, changes a tag or loads a model.
|
|
43
|
-
|
|
44
|
-
Every native new-label path checks tags, topics and their aliases before insertion, including implicit
|
|
45
|
-
knowledge labels, note-file imports and automatic chat tagging. A lexical score of at least 0.65
|
|
46
|
-
refuses creation with `tag_review_required` and up to ten candidates. The whole enclosing write rolls
|
|
47
|
-
back. Existing exact names and explicit aliases still reuse their canonical label.
|
|
48
|
-
|
|
49
|
-
Reuse an existing label or add an owner-reviewed alias when the names mean the same thing. For a
|
|
50
|
-
purposefully distinct label, call `createTag(name, { kind?, expectedCreationFingerprint })` with the
|
|
51
|
-
current preflight receipt. This owner-only acceptance is checked under the write lock and refuses
|
|
52
|
-
stale or differently targeted receipts. There is no force bypass. The creation check bounds input to
|
|
53
|
-
5,000 labels, 100,000 aliases and 4 MiB of names, and fails before hydration if those limits are exceeded.
|
|
54
|
-
`auditVocabulary({ kind?, scope?, minSimilarity?, maxComparisons?, limit?, maxEntries?, maxReadBytes?, signal? })`
|
|
55
|
-
reports pairs of distinct canonical records with lexical similarity. It compares projects with projects,
|
|
56
|
-
and tags/topics with labels, including explicit aliases. Defaults are similarity 0.65, 10,000 name
|
|
57
|
-
comparisons and 20 pairs; maximums are 100,000 comparisons and 200 pairs. `complete: false` means a
|
|
58
|
-
budget stopped the scan, not that remaining names are unique. The fingerprint identifies the reviewed
|
|
59
|
-
catalog. Names in output are capped at 300 characters with an explicit truncation flag. This read does
|
|
60
|
-
not accept a synonym, mutate tags or load a model. Semantic detection and reviewed merges remain separate work.
|
|
61
|
-
|
|
62
|
-
## Meeting-project membership
|
|
63
|
-
|
|
64
|
-
`store.knowledge.linkMeetingProject(account, meetingId, projectId, options)` records one `member-of`
|
|
65
|
-
link in the shared relationship table. Meetings are checked against the explicit provider/account;
|
|
66
|
-
projects must be live owner projects. `by: "agent"` creates a proposed link; it cannot confirm one.
|
|
67
|
-
An owner accepts a proposal by passing its `expectedFingerprint`, preserving its recorded provenance.
|
|
68
|
-
Replaying an existing link returns `changed: false`; stale review fails before writing.
|
|
69
|
-
|
|
70
|
-
`meetingProjects(account, { meetingId?, projectId?, confirmed?, limit?, offset?, signal? })` lists
|
|
71
|
-
membership in that account, with canonical references and fingerprints. Reads take at most 500 rows
|
|
72
|
-
and 2000 provenance characters per row; deleted/foreign meetings and deleted/account projects are
|
|
73
|
-
excluded. Title/alias similarity never creates membership. These are shared store APIs; a command
|
|
74
|
-
surface and project-selected transcript retrieval are separate consumer work.
|
|
75
|
-
|
|
76
|
-
## Project task keys and dependencies
|
|
77
|
-
|
|
78
|
-
New owner projects receive a 3–4-character uppercase key, or take an explicit key of that shape.
|
|
79
|
-
Existing keys stay stable. Task creation allocates `<project key>-<number>` inside a write transaction;
|
|
80
|
-
a failed creation rolls back the counter. No project or task is renumbered.
|
|
81
|
-
|
|
82
|
-
`store.tasks.linkTask(from, to, kind, "owner")` and `unlinkTask` manage `blocked-by`, `follow-up-of`
|
|
83
|
-
and `related-to`. `RES-2 blocked-by RES-1` means RES-1 must finish first. Informational follow-up and
|
|
84
|
-
related links do not affect readiness; related pairs are symmetric. Cycles and self-links fail before
|
|
85
|
-
writing, replays return `changed: false`, and actual changes append linked/unlinked task events.
|
|
86
|
-
Agents propose changes for owner review. Targets must be live tasks in owner projects; inbox tasks
|
|
87
|
-
need their separate account-scoped service. Parent hierarchy remains a separate field.
|
|
88
|
-
|
|
89
|
-
`taskRelations(id)`, `taskReadiness(id)` and `readyTasks(project, { limit? })` read bounded coherent
|
|
90
|
-
snapshots. Only a done blocker is resolved: dismissed/deleted blockers continue to require review.
|
|
91
|
-
Ready reads are discovery, not a work claim or exclusive lock. SQLite write transactions serialize
|
|
92
|
-
counter/dependency mutations; expiring agent leases and command mounting are subsequent work.
|
|
93
|
-
|
|
94
|
-
## The rule this package keeps
|
|
95
|
-
|
|
96
|
-
**Nothing here knows a messenger.** An adapter translates its provider's objects into these types,
|
|
97
|
-
and a lint rule refuses any import of a messenger library or an adapter under `src/`. What only one
|
|
98
|
-
provider has travels in `providerMetadata`.
|
|
99
|
-
|
|
100
|
-
| | |
|
|
101
|
-
|---|---|
|
|
102
|
-
| `.` | `Chat`, `Message`, `Contact`, `Page`… · `formatLocator` / `parseLocator` · `renderMessages` · `pickChat` / `pickPerson` |
|
|
103
|
-
| `./charts` | neutral chart data, a replaceable renderer interface and on-demand dark SVG and PNG images |
|
|
104
|
-
| `./models` | `modelGateway`, provider-neutral requests, adapter-owned option checks, injected keys and purpose consent, and `modelTarget` for effective configuration; [provider settings](docs/search/ai-providers.md) |
|
|
105
|
-
| `./store` | `openCache` — `node:sqlite` under Node, `bun:sqlite` under Bun, WAL and a busy timeout on both · `openStore` — the shared message store, every method async: one file for every messenger (`wirecat.db` in `~/.local/share/WireCat/`, `%LOCALAPPDATA%\WireCat\Data\` on Windows; `MESSAGING_STORE` overrides where), forward-only migrations with `min_compatible`, every sender an identity with a person of their own, edits kept as revisions, a message by its id, deletions kept as tombstones, trigram search · `find` — by text, by sender, or both; `together` for the chats where every sender wrote, `perChat` to cap each chat · `savePeople` and `people` — usernames and bot flags, and a `PeopleLookup` for `pickPerson` |
|
|
106
|
-
| `./sends` | the send guard: a level per command path (`permissions`: deny, readonly, ask, allow — `readOnly` and `allow` read as levels), a recipient list, an hourly limit, and a journal of every attempt that never holds the text; `newSendId` for a send's identity across retries |
|
|
107
|
-
| `./cli` | the command skeleton: `run` (never throws, returns an exit code), the global flags, `settingsFor` (flag → environment → file → default, one strict file schema with each CLI's own fields), the profile as the first word, `--timeout` that closes what a command holds, paging, and run records: `--record` keeps a run's ids and timings (never content), a failure is kept unless `--no-record`, and `runsCommand` gives `runs list\|show\|path` · `configCommand(app, config)` shows and changes the settings with where each came from, and `config migrate --dry-run` previews translation of legacy access settings before `config migrate` saves it; `migratePermissionConfig` provides the same layer-preserving transformation to consumers · `completeCommand(messenger, config, options?)` gives shell completion, account-scoped chat and person ids from the store and never a connection; `options.sources` can supply local suggestions for a separate command group and `options.account` can read an existing local account binding · `storeSummary(env)` gives its local store diagnostics to consumers retaining their own doctor command · `doctorCommand(messenger)` reports the installation's state from disk (the store, the account, sends, runs, the messenger's own checks), and connects only with `--online`; `doctor report create` writes that, the failed run and the recent sends to a file with every id a label · `skillCommand(app, url)` prints the CLI's own SKILL.md for an agent (`skill show`) · `commandsCommand(app)` describes every command as JSON, with `contract` (`CONTRACT`, the major version of the output types) and which commands write · the shared read commands: a CLI describes its messenger once (`Messenger`: its app, a `connect` that returns a `MessengerAdapter`, how `me` maps to a chat) and gets `accountCommand`, `chatsCommand` (`list`, `show`), `contactsCommand` (`list`, `show`) `recipientsCommand`, `sendsCommand`, `watchCommand` (new messages as they arrive, `--jsonl`, until Ctrl-C or `--timeout`; `--events` adds edits, deletions and reactions, each kept in the store), `storeCommand` (the local store: `messages sync` (mounted under `messages`) puts a chat's history into it, resumable, FloodWait-aware, `--since` to stop at a time, `--background` for a detached job that `store jobs list|show|cancel` follow, `--estimate` to only price what is left from the store alone; `store status` what it holds; `store export` a chat's messages out of it, as JSON or `--format markdown`; `store clear --left` deletes the chats the account has left; `store info`, `store check`, `store migrate`, `store backup` and `store restore` look after the file itself — its size and schema, whether it is healthy and which chats are behind, bringing it up to this build, and a copy to go back to), `inboxCommand` (other people's unread messages in every chat, or with `--new` what arrived since the last check — each message once, the point moved only by a run that printed; copied from max-cli), `serveCommand` (keeps the store current until stopped — one per profile by a lock file, catch-up on, started by a person, `server start` or a unit), `serverCommand` (`server start|stop|restart|status|logs`: `serve` in the background, as max-cli's `server`; `install|uninstall` add a systemd user unit or a launchd agent per profile, and `install` starts nothing), and `messagesCommand` (`list`, `show`, `context`, `search` over the store by any three letters inside a word, or `--regex`, `send` through the send guard (`--reply-to`, `--silent`, `--no-preview`, `--md`, `--file` and `--photo` with the text as the caption, and `--at` to send later, with `scheduled` listing the queue), `edit` of the owner's own message, `forward` to another chat and `pin`/`unpin` through it too (the adapter's optional `edit`, `forward`, `pin` and `unpin`), and `delete` — at most 10, for the owner unless `--for-everyone`; it asks first by default, and `--allow-dangerous` is the yes · `reactionsCommand` (`add`, `remove`: the owner's reaction on a message, through the guard; the adapter's optional `react`) · `pollsCommand` (`show` a poll with its answer ids, `vote` by id or `--retract`, `close` the owner's own, `create` one — a vote guarded as a reaction, closing as an edit, a new poll as a message with a send id); a `msg:` locator names a message) — every read saved to the store, `--offline` answered from it, each call a run event · `mcpCommand(messenger)` serves the profile to an agent over MCP on stdin and stdout (copied from max-cli: one connection held for minutes, one call at a time, read tools named `<cli>_<command words>` answering what `--json` prints, `<cli>_status` without connecting; the write tools — `<cli>_messages_send`, `_edit`, `_forward`, `_pin`, `_unpin`, `_delete`, `<cli>_reactions_add`, `_remove`, `<cli>_chats_mark_read`, `<cli>_polls_vote`, `_close` and `_create` — are offered by the profile's `permissions` and run through the same guard as their commands; a write at level `ask` follows the host approval boundary and profile permissions without a form; retired confirmation flags only warn, and `messages_delete` never deletes for everyone), and `mcp config` prints the entry for a desktop client · `mcp --http` serves the same tools over HTTP on 127.0.0.1 behind the owner's tunnel with a one-owner login; a CLI with its own MCP server mounts `serveOverHttp(build, options)` with `httpServerOptions(mode)`, `httpTokenFile` and `revokeAll` (`OVER_HTTP` follows the same profile permission policy) |
|
|
108
|
-
| `./testing` | the adapter kit — **not stable yet**, so it may change in any release: `fakeAdapter(seed)`, a messenger in memory with every method group, for command tests; `contractCases({ connect })`, the port's promises as cases any test runner runs over an adapter; `contractSeed`, the chats and messages they read. How to write an adapter and run them: [the adapter guide](docs/dev/ADAPTERS.md) |
|
|
109
|
-
| `./tasks`, `./tasks/testing` | what waits on the owner: the task model, `TaskStore` and the service over it; the testing entry adds a memory store. Was `@wirecat/cli-tasks` |
|
|
110
|
-
| `./meetings` (`/cli`, `/mcp`, `/testing`) | events and meetings: the model, the WebVTT parser, the `MeetingSource` port a provider implements, `MeetingStore`, pull and import, the meeting commands and MCP reads; the testing entry adds a memory store, a fake source and the contract cases. Was `@wirecat/cli-meetings` — see [Meetings](docs/dev/MEETINGS.md) |
|
|
111
|
-
|
|
112
|
-
⚠ **Errors are recognised by shape, not by class** (`isCliFailure`). A package linked during
|
|
113
|
-
development brings its own copy of cli-base, and an error built by one copy is not an `instanceof`
|
|
114
|
-
the other's class.
|
|
115
|
-
|
|
116
|
-
Field selection uses cli-base's `fieldsOf` and `projectFields`; list envelopes and operation IDs
|
|
117
|
-
stay intact. Direct empty field lists keep only operation metadata, preserving the existing helper
|
|
118
|
-
contract. Direct invalid or unsafe paths are rejected before projection. cli-base 0.19.2 or newer
|
|
119
|
-
within the 0.19 series is required.
|
|
120
|
-
|
|
121
|
-
`searchAllIncludingMeetings` from `./services` adds one selected meeting account to the existing
|
|
122
|
-
message, mail and notes search. It leaves `searchAll` and its item references unchanged. The CLI
|
|
123
|
-
reaches it with `search all <query> --source zoom:<account>` (or `zoom`, `meetings`, `all`) and MCP with
|
|
124
|
-
`search_all`'s `source`; a bare word takes the one account that holds meetings and refuses when several do.
|
|
125
|
-
Choose another meeting account explicitly:
|
|
7
|
+
The engine behind the WireCat command-line tools for Telegram, MAX, mail, notes and meetings. Everything that
|
|
8
|
+
does not depend on one messenger lives here: the data model, a local SQLite store with full-text and semantic
|
|
9
|
+
search, a Lucene query language, the shared commands, an MCP server for AI agents, and the guard around every
|
|
10
|
+
write. A messenger plugs in as one adapter and gets all of it.
|
|
126
11
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
limit: 20,
|
|
131
|
-
meetingAccount: { provider: "zoom", account: "zm-profile:example" },
|
|
132
|
-
maxMeetings: 100,
|
|
133
|
-
})
|
|
134
|
-
```
|
|
12
|
+
[Architecture](docs/dev/ARCHITECTURE.md) · [Write an adapter](docs/dev/ADAPTERS.md) ·
|
|
13
|
+
[Query language](docs/search/query-language.md) · [CLI standard](docs/dev/STANDARD.md) ·
|
|
14
|
+
[API reference](docs/REFERENCE.md) · [Changelog](CHANGELOG.md) · [wirecat.dev](https://wirecat.dev)
|
|
135
15
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
Meetings support letter/digit words joined by AND, including adjacent words, as word prefixes.
|
|
142
|
-
Exact forms, phrases, OR/NOT, patterns and field/date filters skip only meetings with a reason.
|
|
143
|
-
The meeting account defaults to `account` and is looked up without registration. Search reads
|
|
144
|
-
current transcripts, chat and summaries and excludes deleted meetings.
|
|
145
|
-
|
|
146
|
-
`maxMeetings` limits visited candidate meetings (1–1000, default 100), while `limit` bounds returned
|
|
147
|
-
items (1–1000). The store can allocate many hit rows within one candidate meeting; this service
|
|
148
|
-
cannot promise a hard query memory bound. `hasMore: null` means the scan stopped before proving
|
|
149
|
-
whether another match exists. `meetings.complete` describes the selected source's scan, and
|
|
150
|
-
`meetings.nextCursor` resumes with `only: ["meetings"]`, the same query and the same account. It
|
|
151
|
-
retains unreturned hits even when another resource filled the result limit. This is a meeting source
|
|
152
|
-
continuation, not a global cursor or a snapshot; changing archive contents can require restarting.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
A **message locator** names one message across every provider and account:
|
|
156
|
-
`msg:telegram/<account>/<chat>/<message>`. A message id alone does not — Telegram numbers messages
|
|
157
|
-
per chat in channels and per account in private chats.
|
|
158
|
-
|
|
159
|
-
Forum addressing is an optional adapter capability: `messages send --topic` and `polls create --topic`
|
|
160
|
-
pass `threadId` through the shared service/guard. `validateThread` checks the topic and any reply
|
|
161
|
-
before sending, after the permission gate. Telegram group forums support it; MAX refuses it.
|
|
162
|
-
Journal records carry only the thread id. A retry keeps the same send id, chat and topic; scheduled
|
|
163
|
-
sends must be checked in the queue instead of repeated.
|
|
164
|
-
|
|
165
|
-
Consumers retaining their own personal MCP session can import `personalMcpTools`,
|
|
166
|
-
`registerPersonalMcpTools`, `personalMcpConfirmer` and the `PersonalMcpRegistration` types from
|
|
167
|
-
`./cli`. Filter unsupported provider capabilities before mounting. The host supplies its held
|
|
168
|
-
session, account-scoped store, defaults and permission scope (`around`); `withServices` and
|
|
169
|
-
`resolveChat` bind its service overrides and confirmation titles. Session callbacks receive a
|
|
170
|
-
`release` function for local inference. The host closes `warmEmbedders()` on shutdown. The same
|
|
171
|
-
strict catalogue is mounted by the built-in server; unknown arguments fail before execution.
|
|
172
|
-
|
|
173
|
-
## Media options
|
|
174
|
-
|
|
175
|
-
`messages send --spoiler` hides a photo or video until tapped, and `--caption-above` shows the text above the
|
|
176
|
-
attachment (send tool: `spoiler`, `caption_above`). A messenger offers them through `Messenger.mediaOptions`;
|
|
177
|
-
where it is unset the service refuses them before connecting, so an adapter that does not know an option never
|
|
178
|
-
receives one to drop. Both need an attachment. Per-message forward protection is left out: Telegram grants it
|
|
179
|
-
to bots only, and a personal account protects a whole chat instead.
|
|
180
|
-
|
|
181
|
-
## Sender identities
|
|
182
|
-
|
|
183
|
-
`chats send-as <chat>` lists who the account may post as in a chat: `{ id, title, kind, premiumRequired,
|
|
184
|
-
default }`, `kind` being `self`, `channel` or `group`. The personal identity is always in the list, and
|
|
185
|
-
`default` marks the chat's saved choice. Reading it changes nothing — the saved choice stays as it is.
|
|
186
|
-
`messages send`, `messages forward` and `polls create` take `--send-as <id>` (their tools `send_as`): the
|
|
187
|
-
service lists the identities of the chat the message lands in, in the same connection, and refuses an id
|
|
188
|
-
that is not there. An adapter without the optional `sendAsIdentities` refuses the option — it is never
|
|
189
|
-
dropped, and never falls back to the personal identity. Without `--send-as`, a chat whose saved sender is not
|
|
190
|
-
the account (the adapter's `savedSender`, say a group that posts as a linked channel) is refused before
|
|
191
|
-
sending: the messenger would post as that sender, and nothing typed said so. The refusal names both ids. The journal records the identity, and a retry of an
|
|
192
|
-
unknown send under the same send id must name the same identity.
|
|
193
|
-
|
|
194
|
-
## Message permalinks
|
|
195
|
-
|
|
196
|
-
The personal `messages link <chat> <message>` command also accepts a `msg:` locator.
|
|
197
|
-
Its read-only MCP tool and CLI call the same service and return `{ locator, url, access, reason }`.
|
|
198
|
-
Adapters can implement optional `permalink` to return HTTPS links; its result contains no message
|
|
199
|
-
content. Link audience is `public`, `restricted` or `unknown`; a URL grants no membership.
|
|
200
|
-
Without support, a validated target returns `url: null`, `access: unavailable`, and a reason.
|
|
201
|
-
Offline validates this account's stored message and returns reason `offline`, without connecting.
|
|
202
|
-
A locator for another messenger or account is refused. Singular `link` differs from graph `links`.
|
|
203
|
-
|
|
204
|
-
## Command discovery
|
|
205
|
-
|
|
206
|
-
The [CLI standard](docs/dev/STANDARD.md#external-references-and-our-adoption-profile) explains
|
|
207
|
-
which POSIX, GNU, CLIG and agent-facing conventions we adopt. The [architecture](docs/dev/ARCHITECTURE.md#cli-design-references)
|
|
208
|
-
shows where their contracts live; the [compliance audit](docs/dev/CLI-COMPLIANCE.md) records
|
|
209
|
-
remaining gaps and deliberate differences.
|
|
210
|
-
|
|
211
|
-
To discover arguments without reading the whole command tree, run
|
|
212
|
-
`<cli> commands messages evidence --json`. Replace the path with any command or group;
|
|
213
|
-
`<cli> commands messages --json` includes its descendants. The response retains global options
|
|
214
|
-
and exit codes, includes options inherited from ancestor groups, and resolves command aliases.
|
|
215
|
-
Give one command path per call; inspect other groups in separate calls.
|
|
216
|
-
`<cli> commands --json` still returns the full tree.
|
|
217
|
-
|
|
218
|
-
## Evidence packets for agents
|
|
219
|
-
|
|
220
|
-
`prepareEvidencePacket` from `@wirecat/cli-core/services` packages a message page that the
|
|
221
|
-
caller has already read and authorised. It works with any messenger's domain messages:
|
|
16
|
+
[](https://www.npmjs.com/package/@wirecat/cli-core)
|
|
17
|
+
[](https://github.com/WireCatLabs/cli-core/actions/workflows/ci.yml)
|
|
18
|
+
[](https://nodejs.org/)
|
|
19
|
+
[](https://bun.sh/)
|
|
20
|
+
[](LICENSE)
|
|
222
21
|
|
|
223
|
-
|
|
224
|
-
import { prepareEvidencePacket } from "@wirecat/cli-core/services"
|
|
22
|
+
## Key documents
|
|
225
23
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
24
|
+
| Document | What it answers |
|
|
25
|
+
|---|---|
|
|
26
|
+
| [Architecture](docs/dev/ARCHITECTURE.md) | The layers, the module map, the store internals and migrations, who consumes what |
|
|
27
|
+
| [Write an adapter](docs/dev/ADAPTERS.md) | How to add a messenger: the port, the `Messenger` description, the contract cases |
|
|
28
|
+
| [CLI standard](docs/dev/STANDARD.md) | The rules every WireCat CLI follows: command shape, output, exit codes, permissions, MCP |
|
|
29
|
+
| [Glossary](docs/dev/GLOSSARY.md) | One word, one meaning across the tools |
|
|
30
|
+
| [Query language](docs/search/query-language.md) · [spec](docs/search/query-language-spec.md) | The search syntax and its exact grammar |
|
|
31
|
+
| [Storage](docs/storage/README.md) | The schema, the search indexes and the decisions behind them |
|
|
32
|
+
| [Knowledge](docs/dev/KNOWLEDGE.md) · [Meetings](docs/dev/MEETINGS.md) | Labels, links and proposals across sources; the meetings module and its providers |
|
|
33
|
+
| [Testing](docs/dev/TESTING.md) · [Parity audit](docs/dev/PARITY-AUDIT.md) | The sandbox, the coverage floor, the checks across tg and max |
|
|
34
|
+
| [Tool boundaries](docs/dev/TOOL-BOUNDARIES.md) | Which tool owns which command |
|
|
35
|
+
| [API reference](docs/REFERENCE.md) | Every entry point and the detailed contract of each feature |
|
|
36
|
+
| [Changelog](CHANGELOG.md) | What each version changed, and what may break callers |
|
|
37
|
+
|
|
38
|
+
## What it is
|
|
39
|
+
|
|
40
|
+
A messaging CLI has two halves. One speaks a protocol: MTProto for Telegram, a WebSocket for MAX, IMAP for mail.
|
|
41
|
+
The other half is the same for every messenger: store what was read, search it, render it for a person and as JSON
|
|
42
|
+
for a program, guard every send, expose it all to an agent. This package is the second half.
|
|
43
|
+
|
|
44
|
+
[tg-cli](https://github.com/WireCatLabs/tg-cli) and [max-cli](https://github.com/WireCatLabs/max-cli) are built on it,
|
|
45
|
+
and so are the mail and notes tool [cli-memo](https://github.com/WireCatLabs/cli-memo),
|
|
46
|
+
[zoom-cli](https://github.com/WireCatLabs/zoom-cli) and [drive-cli](https://github.com/WireCatLabs/drive-cli). Until
|
|
47
|
+
they move to the new name, they import it as `@wirecat/cli-messaging`: that was this package's name up to 0.261.0.
|
|
48
|
+
|
|
49
|
+
It is built on [`@wirecat/cli-base`](https://github.com/WireCatLabs/cli-base), the layer every CLI needs: two output
|
|
50
|
+
streams, closed error codes, the keyring, injectable clocks, the query parser. cli-base is a peer dependency, so an
|
|
51
|
+
install holds one copy.
|
|
52
|
+
|
|
53
|
+
In numbers, on `main`: 608 source files and 344 test files, 23 entry points, 27 search fields, 13 search presets.
|
|
54
|
+
It runs on Node 22.16+ and 24+, and on Bun.
|
|
55
|
+
|
|
56
|
+
## Architecture
|
|
57
|
+
|
|
58
|
+
```mermaid
|
|
59
|
+
flowchart TB
|
|
60
|
+
tools["tg · max · memo · zm · drive"] --> interface
|
|
61
|
+
subgraph core ["@wirecat/cli-core"]
|
|
62
|
+
interface["Interface: CLI commands and MCP tools"] --> services["Services: one use case each"]
|
|
63
|
+
services --> ports["Ports: MessengerAdapter · MeetingSource · TaskStore"]
|
|
64
|
+
services --> store[("Store: one SQLite file, wirecat.db")]
|
|
65
|
+
ports --> domain["Domain types"]
|
|
66
|
+
store --> domain
|
|
67
|
+
end
|
|
68
|
+
adapters["Adapters, in each tool: Telegram, MAX, IMAP, Zoom…"] -. implement .-> ports
|
|
69
|
+
core --> base["@wirecat/cli-base: output, exit codes, keyring, clocks, query parser"]
|
|
232
70
|
```
|
|
233
71
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
72
|
+
Five layers, and each calls only the layers below it: domain, adapters behind a port, ports, services, interface.
|
|
73
|
+
|
|
74
|
+
- **The CLI and the MCP server are two adapters over the same services.** A command and its MCP tool answer with
|
|
75
|
+
the same data, because one service produces it.
|
|
76
|
+
- **A port with one required core and optional groups.** `MessengerCore` is what every messenger must do. Seventeen
|
|
77
|
+
groups — server reads, polls, forums, reactions and the rest — are optional and reached through `capability()`.
|
|
78
|
+
A messenger without a group refuses the command before connecting; it never crashes and never silently drops an
|
|
79
|
+
option.
|
|
80
|
+
- **Decorators, so no service can forget.** Every adapter is wrapped twice: `stored` saves what a read answered,
|
|
81
|
+
and `observed` times each call for the run record.
|
|
82
|
+
- **Override a use case, not a command.** A tool replaces one service through `Messenger.services`; every command
|
|
83
|
+
and tool that uses it follows.
|
|
84
|
+
- **Tasks and meetings know nothing of SQLite.** They define their own ports (`TaskStore`, `MeetingStore`), and the
|
|
85
|
+
store implements them.
|
|
86
|
+
|
|
87
|
+
**The build enforces these boundaries.** Biome import rules refuse, under `src/`:
|
|
88
|
+
|
|
89
|
+
- any messenger library or adapter — this package speaks no provider;
|
|
90
|
+
- `commander` or a command file in services, sends or MCP;
|
|
91
|
+
- the SQLite table modules anywhere outside the store's own interface;
|
|
92
|
+
- any import from the rest of the package inside tasks and meetings, and any file system or SQLite there.
|
|
93
|
+
|
|
94
|
+
Tests guard the rest. Migrations must be numbered without gaps and may not rebuild a table. The schema spec, the
|
|
95
|
+
code and its document must agree. A search plan that reads an index once per message fails the build.
|
|
96
|
+
|
|
97
|
+
## Features
|
|
98
|
+
|
|
99
|
+
### Search that finds it
|
|
100
|
+
|
|
101
|
+
- **One query language for every list and every source.** A TypeScript port of the Apache Lucene 9.12.3 parsers,
|
|
102
|
+
with no runtime parser dependency. Phrases, `AND` / `OR` / `NOT`, `+required`, grouping, field groups like
|
|
103
|
+
`from:(alice OR bob)`, ranges `date:[2026-01-01 TO 2026-02-01}`, comparisons `size>10MB`, wildcards and regular
|
|
104
|
+
expressions. 27 fields: sender, chat, date, file name, MIME type, transcript, subject, label and more. Fuzzy
|
|
105
|
+
and proximity operators are refused with an error that names the alternative.
|
|
106
|
+
[Syntax](docs/search/query-language.md) · [grammar](docs/search/query-language-spec.md)
|
|
107
|
+
- **Any three letters inside a word.** An FTS5 trigram index finds `port` inside `report`. A
|
|
108
|
+
second, word index ranks by BM25.
|
|
109
|
+
- **Word forms in three languages.** Snowball 3.1.1 stemmers for Russian, English and Spanish: `встреча` finds
|
|
110
|
+
`встречи`. Exact forms rank first; `exact:` turns stemming off.
|
|
111
|
+
- **Safe regular expressions.** A Thompson NFA without backtracking, with budgets for states and work, so no
|
|
112
|
+
pattern can hang the search.
|
|
113
|
+
- **Presets for what people actually look for.** `preset:password`, `api-key`, `card`, `phone`, `email`, `url` and
|
|
114
|
+
seven more find candidates, labelled as candidates.
|
|
115
|
+
- **Search by meaning, opt in.** Conversations are split into chunks and embedded locally by a WebAssembly ONNX
|
|
116
|
+
runtime, the same on Node and Bun — e5-small by default, or any OpenAI-compatible API with your own key, after
|
|
117
|
+
you see the cost. Results by meaning and by words are merged by reciprocal rank fusion.
|
|
118
|
+
- **The archive and the server together.** `--backend both` also asks the messenger's own search; its hits are saved
|
|
119
|
+
and filtered by the same query, so nothing is counted twice. `--thread` brings the reply thread around a hit.
|
|
120
|
+
- **Bounded by design.** Query size, depth, nodes, pattern length, expansions and run time all have limits.
|
|
121
|
+
|
|
122
|
+
Measured on synthetic data ([methodology and results](https://github.com/WireCatLabs/cli-testing/tree/main/performance/search)):
|
|
123
|
+
|
|
124
|
+
| Stored messages | Search p50 / p95 |
|
|
125
|
+
|---|---|
|
|
126
|
+
| 10,341 | 9.0 / 22.6 ms |
|
|
127
|
+
| 100,341 | 53.9 / 107.6 ms |
|
|
128
|
+
|
|
129
|
+
### One local store for every source
|
|
130
|
+
|
|
131
|
+
- **One file, every messenger and account:** `wirecat.db` in `~/.local/share/WireCat/` (`%LOCALAPPDATA%\WireCat\Data\`
|
|
132
|
+
on Windows). Messages from Telegram and MAX, mail, notes and meeting transcripts sit side by side, so one query
|
|
133
|
+
searches all of them.
|
|
134
|
+
- **`node:sqlite` under Node and `bun:sqlite` under Bun,** behind a small seam. WAL and a busy timeout on both.
|
|
135
|
+
- **History you can trust.** Edits are kept as revisions and deletions as tombstones. Every sender is an identity
|
|
136
|
+
with a person of their own, so one person across two messengers can be linked.
|
|
137
|
+
- **Migrations an older build survives.** Forward-only, additive and frozen once released. `min_compatible` lets an
|
|
138
|
+
older CLI keep using a file a newer one migrated, and refuses a file it cannot read.
|
|
139
|
+
- **Built for the long run.** History download is resumable and respects the messenger's rate limits; it can run in
|
|
140
|
+
the background as a job. `store check`, `backup` and `restore` look after the file itself.
|
|
141
|
+
|
|
142
|
+
[Storage](docs/storage/README.md) · [why SQLite FTS5 and no daemon](docs/storage/decisions.md)
|
|
143
|
+
|
|
144
|
+
### A full CLI and an MCP server from one adapter
|
|
145
|
+
|
|
146
|
+
Describe a messenger once — its name, how to connect, how `me` maps to a chat — and the tool gets about sixty
|
|
147
|
+
shared commands: chats, contacts, messages, search, reactions, polls, the inbox of unread messages, `watch` for live
|
|
148
|
+
updates, history download, the store, run records, configuration, shell completion, `doctor`, and `commands --json`,
|
|
149
|
+
the whole command tree as data for an agent.
|
|
150
|
+
|
|
151
|
+
The same commands become MCP tools for agents without a terminal. The server offers three tools — find a command,
|
|
152
|
+
run a read, run a write — so an agent's context does not fill with a hundred tool schemas. It runs over stdio, or
|
|
153
|
+
over HTTP on 127.0.0.1 behind the owner's tunnel, with a one-owner OAuth login.
|
|
154
|
+
|
|
155
|
+
`serve` keeps the store current, one process per profile by a lock file; `server install` adds a systemd user unit
|
|
156
|
+
or a launchd agent.
|
|
157
|
+
|
|
158
|
+
### Every write behind a guard
|
|
159
|
+
|
|
160
|
+
- **A permission level per command path:** deny, readonly, ask or allow. The most specific key wins, and a built-in
|
|
161
|
+
default can only tighten what the owner set. No level lets an agent delete for everyone.
|
|
162
|
+
- **A recipient list and an hourly limit** for sends, and a journal of every attempt that records the length of the
|
|
163
|
+
text, never the text.
|
|
164
|
+
- **A send id across retries.** A write whose outcome is unknown is never retried automatically; a retry under the
|
|
165
|
+
same send id cannot send twice.
|
|
166
|
+
- **Deletion asks first,** at most ten messages at a time.
|
|
167
|
+
- **MCP writes follow the same profile permissions.** An agent sees only the tools the profile allows.
|
|
168
|
+
|
|
169
|
+
### Knowledge, tasks and meetings
|
|
170
|
+
|
|
171
|
+
- **Labels, links and facts across sources,** always scoped to an explicit account. What an agent adds stays
|
|
172
|
+
*proposed* until the owner accepts it, with a fingerprint so a stale review cannot overwrite a newer change.
|
|
173
|
+
- **A shared vocabulary.** Before a new tag is created, similar existing tags and aliases are offered for review.
|
|
174
|
+
- **Tasks** with project keys (`RES-12`), dependencies and a readiness check.
|
|
175
|
+
- **Meetings:** a WebVTT parser, a `MeetingSource` port a provider implements, transcripts kept by revision, and
|
|
176
|
+
references to one cue of one transcript.
|
|
177
|
+
|
|
178
|
+
### Files, voice and charts
|
|
179
|
+
|
|
180
|
+
- **Readers for PDF, Word, ODF, HTML and more,** each library loaded on first use.
|
|
181
|
+
- **Local speech recognition** from a pinned model catalogue; importing it loads no engine and downloads nothing.
|
|
182
|
+
- **Charts from statistics** as JSON, SVG or PNG, with a replaceable renderer loaded only when an image is asked for.
|
|
183
|
+
|
|
184
|
+
## Engineering standards
|
|
185
|
+
|
|
186
|
+
The [CLI standard](docs/dev/STANDARD.md) binds every WireCat CLI. It measures itself against POSIX, GNU, [Command Line Interface Guidelines](https://clig.dev),
|
|
187
|
+
the MCP specification and JSON Schema 2020-12, and says where it deliberately differs. A rule changes in its own pull
|
|
188
|
+
request, before the code that needs it.
|
|
189
|
+
|
|
190
|
+
- **stdout carries data, stderr carries diagnostics,** in every mode. `--json` prints one object; `--jsonl` one per
|
|
191
|
+
line; `--json=id,text` only those fields.
|
|
192
|
+
- **Stable exit codes** a script can branch on: 2 validation, 3 config, 4 auth, 5 permission, 6 not found,
|
|
193
|
+
8 rate limited, 9 timeout, 14 outcome unknown, and the rest. An error is one JSON object with a stable `code` and
|
|
194
|
+
`reason` — callers never parse the message.
|
|
195
|
+
- **Built for agents.** `--no-input` never prompts. Input and output are bounded (16 MiB in, 4 MiB out) and fail
|
|
196
|
+
visibly instead of truncating. One-shot commands time out after 30 seconds and close what they hold. `--dry-run`
|
|
197
|
+
previews any write.
|
|
198
|
+
- **The tool never picks an account.** The profile is the first word of every account command; without one, the
|
|
199
|
+
command stops and lists the choices — even when there is only one.
|
|
200
|
+
- **Run records keep ids and timings, never content.** A failure is kept by default, so `runs show` can explain it
|
|
201
|
+
without anyone sending a log full of messages.
|
|
202
|
+
- **Tests that cannot touch real data.** A sandbox keeps every test away from the owner's store, and no test may
|
|
203
|
+
sleep. A coverage floor: 92% of lines, and at least half of every file.
|
|
204
|
+
- **Contract cases for every adapter.** `contractCases` turns the port's promises into cases any test runner can run,
|
|
205
|
+
over an in-memory fake or a real client.
|
|
206
|
+
- **Checked across tools and runtimes.** CI runs on Node 24 and on Bun; a parity workflow
|
|
207
|
+
builds tg-cli and max-cli against this repository; macOS and Windows run on a schedule; gitleaks scans the full
|
|
208
|
+
history.
|
|
209
|
+
- **One shared toolchain.** Biome, markdownlint, CSpell and Lefthook configs come from the
|
|
210
|
+
[WireCat standards](https://github.com/WireCatLabs/community/blob/main/standards/README.md), and CI fails when a
|
|
211
|
+
copy drifts.
|
|
212
|
+
|
|
213
|
+
## Build on it
|
|
214
|
+
|
|
215
|
+
A new messenger is three pieces: an adapter that implements `MessengerCore` (and any optional groups), a
|
|
216
|
+
`Messenger` that describes it, and the contract cases run against it. The
|
|
217
|
+
[adapter guide](docs/dev/ADAPTERS.md) walks through each one.
|
|
299
218
|
|
|
300
219
|
```ts
|
|
301
|
-
import {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
|
|
220
|
+
import { contractCases, digitIds } from "@wirecat/cli-core/testing"
|
|
221
|
+
import { describe, it } from "vitest"
|
|
222
|
+
|
|
223
|
+
describe("the adapter keeps the port's promises", () => {
|
|
224
|
+
for (const one of contractCases({ connect: (seed) => adapterOver(fakeClient(seed)), ids: digitIds }))
|
|
225
|
+
it(one.name, async (context) => {
|
|
226
|
+
const result = await one.run()
|
|
227
|
+
if (result) context.skip(result.skipped)
|
|
228
|
+
})
|
|
229
|
+
})
|
|
307
230
|
```
|
|
308
231
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
reach the revision-work cap. The cursor belongs to the same authorized source. Individual SQL reads
|
|
319
|
-
have snapshots; the service does not claim one snapshot across pages. Archive completeness remains unknown.
|
|
320
|
-
|
|
321
|
-
`personMeetingContext(store, "person:1", { accountIds: [1] })` reads linked meeting
|
|
322
|
-
participation for explicitly authorized accounts. A native account-presence check runs before the global
|
|
323
|
-
person lookup; a person seen only by other accounts returns `not_found` without exposing their name.
|
|
324
|
-
The allowed accounts are snapshotted before asynchronous reads. It returns current meeting context, without
|
|
325
|
-
claiming that the person spoke every returned cue. Defaults are 10 meetings, 5 cues per meeting,
|
|
326
|
-
64 KiB for the JSON `items` array, and a scan of at most 1000 mixed involvement rows. Coverage
|
|
327
|
-
reports the scan cap, queued changes and skipped unavailable meetings; it never claims complete history or matches people by
|
|
328
|
-
name or email. The helper does not rebuild the derived index.
|
|
329
|
-
|
|
330
|
-
A task proposal has a stable source-and-kind ID and `applied: false`; it creates no task or message.
|
|
331
|
-
The separate `createTaskFromMeeting(store, accountKey, { source, kind, origin, dueAt? })` helper
|
|
332
|
-
explicitly writes one local task after looking up the existing account and authorizing its source.
|
|
333
|
-
It accepts the task package's kinds and origins, keeps canonical references, and reuses an existing
|
|
334
|
-
task of the same kind; `rule` origin reuses any task from that source, including a closed task.
|
|
335
|
-
Deduplication follows the task package's sequential find-and-add contract; concurrent writers need
|
|
336
|
-
additional coordination. Proposal generation never calls this helper.
|
|
337
|
-
|
|
338
|
-
`readMeetingTask(store, accountKey, id)` resolves source text on demand, with a preview of at most
|
|
339
|
-
200 text characters. A deleted source returns `state: "unavailable"` and `source: null`; other source
|
|
340
|
-
errors propagate. The task itself retains its reference rather than transcript text.
|
|
341
|
-
|
|
342
|
-
Canonical meeting, revision and cue references can also be stored in memory and fact evidence
|
|
343
|
-
and in note links. Cue references use the actual cue position, and keep pointing to their retained
|
|
344
|
-
revision after a correction. Deleted parents refuse new links; existing evidence retains its source
|
|
345
|
-
reference so callers can report that it is unavailable.
|
|
346
|
-
|
|
347
|
-
`store.meetingVectors` shares the existing text chunks and model/content-hash embedding cache.
|
|
348
|
-
Explicit `rebuild({ accountId })` creates bindings for current live transcripts; `chunksToEmbed(model,
|
|
349
|
-
{ accountId, limit })` reads missing texts, and `saveCurrent(model, dims, rows, { accountId })`
|
|
350
|
-
rechecks their current account ownership atomically before caching model results. It acknowledges
|
|
351
|
-
saved and skipped hashes and never replaces an existing vector. No operation chooses a model,
|
|
352
|
-
downloads one or calls a provider.
|
|
353
|
-
Rebuild retires inactive transcript bindings and their orphaned model vectors atomically, while
|
|
354
|
-
preserving every hash still used by another corpus or live meeting binding.
|
|
355
|
-
|
|
356
|
-
Vector operations default to a 4 MiB aggregate text budget and 10,000 rows per transcript, with
|
|
357
|
-
explicit maxima of 64 MiB and 100,000 rows. Oversized rebuilds roll back the complete batch.
|
|
358
|
-
`nearest(model, query, { accountId, limit, maxChunks? })` defaults to scanning at most 1000 chunks
|
|
359
|
-
and ranks only those candidates. Its `ranking: "scanned-candidates"`, `scanned`, `complete`,
|
|
360
|
-
`hasMore` and `nextChunkId` fields distinguish a complete scan from continuation; continuation
|
|
361
|
-
pages do not promise a global ranking. Vector writes and scans additionally cap payloads at 16 MiB.
|
|
362
|
-
|
|
363
|
-
These helpers add no CLI or MCP command. Persisting meeting references through existing memory
|
|
364
|
-
or fact evidence links needs separate store integration.
|
|
365
|
-
|
|
366
|
-
## Charts from statistics
|
|
367
|
-
|
|
368
|
-
`statsCommand(messenger)` from `./cli` mounts `stats charts <chat>`. It returns `{ chart }`:
|
|
369
|
-
messages per day/week, active authors, or joins and leaves (`--chart-kind`). `--output activity.svg`
|
|
370
|
-
or `--output activity.png` also saves a dark image in a new private file and returns `chartFile`. The command reads the same
|
|
371
|
-
statistics service; the chart itself never fetches extra history, sends or marks read. Missing dates
|
|
372
|
-
are gaps, and partial data is labelled. `--jsonl` and image output to stdout are unavailable.
|
|
373
|
-
|
|
374
|
-
The read-only MCP `stats_charts` returns the same chart JSON from the store, without writing a file
|
|
375
|
-
or connecting. Optional `format: "png"` returns PNG image content and JSON text containing
|
|
376
|
-
`chart` and `image: { format, width, height }`; the default remains JSON. Membership is unavailable in that stored mode because it needs online events.
|
|
377
|
-
Both interfaces inherit the `messages` read permission.
|
|
378
|
-
|
|
379
|
-
`./charts` exports the library-neutral `ChartData`, `ChartRenderer`, `chatChart`, `CHART_SIZE`
|
|
380
|
-
and the lazy `chartRenderer()` loader, plus the separate `chartPng(svg)` encoder. ECharts types stay in the renderer module; JSON-only commands
|
|
381
|
-
do not load it. PNG lazily loads resvg-js 2.6.2 and uses bundled Noto Sans Regular (SIL OFL 1.1),
|
|
382
|
-
with system fonts disabled. SVG does not load resvg. Pass a renderer loader as the second argument to `statsCommand` to replace the image implementation
|
|
383
|
-
while keeping the neutral data and command contract. Images default to a dark theme. ECharts is pinned at 6.1.0; its published unpacked files
|
|
384
|
-
plus zrender and tslib total about 61.6 MiB before package-manager deduplication.
|
|
385
|
-
|
|
386
|
-
## Where it came from
|
|
387
|
-
|
|
388
|
-
The files were copied from max-cli at `3ca8874`, from the part its lint rule `CLI-30` already kept
|
|
389
|
-
free of MAX. What changed on the way is listed as `DEBT-1`…`DEBT-10` in the proposal.
|
|
390
|
-
|
|
391
|
-
## Checks
|
|
232
|
+
**Seven entry points are stable:** `.`, `./cli`, `./store`, `./sends`, `./speech`, `./services` and `./background`.
|
|
233
|
+
A change that breaks them waits for a breaking release — at most one a week — whose changelog says what to change.
|
|
234
|
+
Everything else may change in any release and is still listed under "Changed — may break callers". The full list of
|
|
235
|
+
entry points and what each holds is in the [API reference](docs/REFERENCE.md).
|
|
236
|
+
|
|
237
|
+
⚠ **Errors are recognised by shape, not by class** (`isCliFailure`). A package linked during development brings its
|
|
238
|
+
own copy of cli-base, and an error built by one copy is not an `instanceof` the other's class.
|
|
239
|
+
|
|
240
|
+
## Development
|
|
392
241
|
|
|
393
242
|
```sh
|
|
394
243
|
pnpm install
|
|
@@ -396,118 +245,9 @@ pnpm lint && pnpm typecheck && pnpm test
|
|
|
396
245
|
pnpm smoke:bun # the same exports, run under Bun
|
|
397
246
|
```
|
|
398
247
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
Raise `version` in `package.json` through a pull request, merge it, then on `main`:
|
|
402
|
-
|
|
403
|
-
```sh
|
|
404
|
-
bin/release --local # from this machine: NPM_TOKEN if exported, else the keyring (service npm, account leemour)
|
|
405
|
-
bin/release # from GitHub Actions, once npm trusts .github/workflows/release.yml
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
Both refuse a dirty tree, a branch other than `main` and an unpushed `main`. When npm already has the
|
|
409
|
-
version, or a higher one, they raise it to the next free version through a pull request — the next
|
|
410
|
-
minor for `x.y.0`, the next patch otherwise — merge it once its checks pass, and publish that. They run every check, and tag `v<version>` once npm
|
|
411
|
-
shows it. The token is never printed and never
|
|
412
|
-
written to a file.
|
|
413
|
-
|
|
414
|
-
The GitHub form publishes from the job in the `npm` environment, which is what
|
|
415
|
-
npm's trusted publisher names: `WireCatLabs` / `cli-core` / `release.yml` / environment `npm`.
|
|
416
|
-
|
|
417
|
-
### How often, and what may break
|
|
418
|
-
|
|
419
|
-
**Release when a consumer needs it.** Changes wait under `## Unreleased` until then; there is no
|
|
420
|
-
gap to keep between releases — tg-cli and max-cli pace their own.
|
|
421
|
-
|
|
422
|
-
**These exports are stable.** A change that breaks them waits for a **breaking release**, at most one
|
|
423
|
-
a week, whose changelog section says what to change in a consumer; tg-cli and max-cli move to it
|
|
424
|
-
the same day.
|
|
425
|
-
|
|
426
|
-
| Export | Stable |
|
|
427
|
-
|---|---|
|
|
428
|
-
| `.` | the domain types (`Chat`, `Message`, `Contact`, `Page`, …), the message locator |
|
|
429
|
-
| `./cli` | `Messenger`, `MessengerAdapter` and its method groups (`MessengerCore` required; `ServerReads` and the rest optional), `createProgram`, `run`, `messengerContext`, the command factories' names and arguments |
|
|
430
|
-
| `./store` | `openStore`, `MessageStore`, `storePath`, and the file format: `minCompatible` rises only in a breaking release |
|
|
431
|
-
| `./sends` | `sendGuard`, `SendJournal`, the journal's line format |
|
|
432
|
-
| `./speech` | The pinned speech-model catalogue, shared directories, verified installer and installed-only bounded PCM recognizer. Importing it does not load a recognizer or download a model |
|
|
433
|
-
| `./services` | `servicesFor`, `Override` and the service names |
|
|
434
|
-
| `./background` | `lockPath`, `readLock`, `holdLock`, `releaseLock`, `servingProfiles`, `alive`, `carries`, `holdersOf`, `ServerSystem`, `thisMachine`, `platformFor` and the systemd and launchd units |
|
|
435
|
-
|
|
436
|
-
`./testing` and `./parity` are not on this list. Everything else may change in any release, and still goes under "Changed — may break callers" when
|
|
437
|
-
it does. tg-cli and max-cli take new versions through Dependabot pull requests.
|
|
248
|
+
Releases go through `bin/release` from `main`: it refuses a dirty tree, runs every check, publishes to npm and tags
|
|
249
|
+
`v<version>`. The steps and the release rules are in [RELEASING.md](docs/dev/RELEASING.md).
|
|
438
250
|
|
|
439
251
|
## Licence
|
|
440
252
|
|
|
441
253
|
[Apache License 2.0](LICENSE).
|
|
442
|
-
|
|
443
|
-
Forum configuration uses the shared topics service: explicit enable/upgrade and named creation,
|
|
444
|
-
with staged guards, original/result chat ids and unknown-outcome handling. Adapters opt into the
|
|
445
|
-
forum capabilities; sending and creating a topic never implicitly convert a group. Enabling defaults
|
|
446
|
-
to confirmation; topic creation preserves a caller's send id. Local history remains under its
|
|
447
|
-
original peer id after migration.
|
|
448
|
-
|
|
449
|
-
Markdown conversion belongs to each messenger adapter through optional `formatMarkdown`.
|
|
450
|
-
Shared personal and bot send/edit use its neutral `FormattedText`/`TextSpan` result; they do not
|
|
451
|
-
choose a dialect. New adapters must implement the capability to support `--md`. The legacy
|
|
452
|
-
`parseMarkdown` export and `markup` port argument remain available for existing callers.
|
|
453
|
-
|
|
454
|
-
## MCP from browser clients
|
|
455
|
-
|
|
456
|
-
Writes over MCP show no form, over stdio or HTTP: the profile's permissions decide, and a level of
|
|
457
|
-
`ask` goes ahead, since nobody is at a terminal to answer it. An app's own permission prompt is
|
|
458
|
-
separate and cannot be verified by the server; its “always allow” setting may permit later calls
|
|
459
|
-
without another prompt.
|
|
460
|
-
|
|
461
|
-
Repeat `--permission key=level` to override profile permissions only for the server process.
|
|
462
|
-
For example, `--permission messages.send=allow` enables sending even in a read-only profile.
|
|
463
|
-
A broader key overrides saved descendant keys; built-in defaults still tighten broader grants.
|
|
464
|
-
Recipient restrictions and hourly limits remain in effect; no saved configuration is changed.
|
|
465
|
-
|
|
466
|
-
The browser connector uses the tunnel's HTTPS URL ending in `/mcp`, with the owner OAuth login.
|
|
467
|
-
Both legacy session-based and modern HTTP MCP clients are supported. Web clients can use tools
|
|
468
|
-
without prompts or resources; neither is required for reading and sending.
|
|
469
|
-
|
|
470
|
-
Message and author rankings are mounted by `statsCommand`: see the [ranking guide](docs/rankings.md)
|
|
471
|
-
for metrics, scores, saved selections, evidence paging and data-quality limits.
|
|
472
|
-
|
|
473
|
-
### Private contact metadata and automatic tags
|
|
474
|
-
|
|
475
|
-
Both messenger consumers can keep private contact aliases, scoped to one account, and multiple notes,
|
|
476
|
-
which belong to the owner: a contact's notes show in every account that sees the contact.
|
|
477
|
-
`contacts alias set <person> <alias>` and `contacts alias rm <person>` affect local display and
|
|
478
|
-
resolution only. `contacts rename` continues to change the messenger address book. Show/list
|
|
479
|
-
retain the messenger name; a local alias adds `alias` and `displayName`. Duplicate aliases require
|
|
480
|
-
an explicit id. Stored direct-chat resolution supports aliases; it never invents a chat id from
|
|
481
|
-
an identity id. `contacts show --with-notes` includes private notes explicitly; the notes read permission still applies. Local metadata survives profile refresh and stays on its original identity/account
|
|
482
|
-
when identities are linked or unlinked.
|
|
483
|
-
|
|
484
|
-
`contacts notes add <person> --file <path>` (or stdin) creates a stable note id. Use `list`,
|
|
485
|
-
`show`, `edit --revision <number>` and `remove` for that person's notes. Notes are independent of
|
|
486
|
-
public bios, imported documents and source messages. They are rows of the store's `notes` table (version
|
|
487
|
-
25), linked to the contact, so `search notes` and `search all` find them too. `contacts list --search-notes
|
|
488
|
-
<text>` is an explicit substring search over the notes of the selected account's contacts.
|
|
489
|
-
|
|
490
|
-
`metadata get --chat <chat>` reads the cached group/channel description and fetched time.
|
|
491
|
-
`metadata refresh --chat <chat>` reads it from the messenger, without changing the remote chat.
|
|
492
|
-
The refresh command accepts repeated chats and a bounded `--limit` (1–500).
|
|
493
|
-
`tags auto [--chat <chat>] [--limit 50]` classifies cached title, username and description with
|
|
494
|
-
versioned keyword rules. It works offline and uses only stored group/channel titles when there is
|
|
495
|
-
no full metadata snapshot. `--refresh-metadata` explicitly fetches descriptions; `--dry-run`
|
|
496
|
-
previews cached results without writes. These flags cannot be combined. Results identify matched
|
|
497
|
-
fields and a rule score, not a topic probability. No model or message text is used.
|
|
498
|
-
|
|
499
|
-
Automatic tag claims are distinct from manual labels. Rerunning removes obsolete automatic tags
|
|
500
|
-
and preserves manual tags. Adding a label already generated promotes it to manual ownership;
|
|
501
|
-
listing generated tags includes `sources`. Use `tags list|remove --source manual|auto` to select one ownership source. Removing a tag without a source removes its claims; a later explicit
|
|
502
|
-
automatic run can regenerate it. Upgrade consumers together before relying on manual promotion:
|
|
503
|
-
older builds cannot record manual ownership of an already generated label.
|
|
504
|
-
|
|
505
|
-
Administrator reports are mounted by the same `statsCommand`: `stats messages unanswered`,
|
|
506
|
-
`stats contacts responses`, `stats chats newcomers` and `stats messages discussion`. They read
|
|
507
|
-
held data only; [the guide](docs/rankings.md#find-questions-and-posts-that-need-attention) explains
|
|
508
|
-
explicit reply attribution, selected answerers, unknown joining dates and bounded evidence.
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
`--json` prints text as it was written; MCP answers show control and direction characters visibly in
|
|
512
|
-
strings and keys. `--json=id,text` keeps only those fields. MCP contact searches keep third-party registries off
|
|
513
|
-
unless the caller explicitly sets `registries: true`.
|