@wirecat/cli-core 0.398.0 → 0.400.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +106 -0
- package/dist/analysis/consents.d.ts +11 -6
- package/dist/analysis/consents.js +5 -2
- package/dist/cli/analysis-choice.d.ts +1 -0
- package/dist/cli/analysis-choice.js +3 -0
- package/dist/cli/bot/admins.js +14 -4
- package/dist/cli/bot/command.js +38 -16
- package/dist/cli/bot/examples.d.ts +3 -0
- package/dist/cli/bot/examples.js +2 -0
- package/dist/cli/bot/mcp.js +6 -2
- package/dist/cli/bot/messages.js +17 -6
- package/dist/cli/bot/moderation.js +16 -4
- package/dist/cli/bot/people.js +16 -4
- package/dist/cli/bot/setup.js +27 -8
- package/dist/cli/bot/watch.js +7 -1
- package/dist/cli/config-command.js +20 -1
- package/dist/cli/context.d.ts +2 -0
- package/dist/cli/context.js +1 -1
- package/dist/cli/effects.d.ts +4 -1
- package/dist/cli/effects.js +10 -2
- package/dist/cli/embedding-choice.d.ts +2 -1
- package/dist/cli/embedding-choice.js +4 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/json-fields.js +12 -1
- package/dist/cli/messenger/account-command.js +15 -6
- package/dist/cli/messenger/account-profile-query.d.ts +2 -0
- package/dist/cli/messenger/account-profile-query.js +13 -0
- package/dist/cli/messenger/account-sessions-command.js +1 -0
- package/dist/cli/messenger/admin-commands.js +30 -21
- package/dist/cli/messenger/admin-contacts-command.js +6 -3
- package/dist/cli/messenger/admin-folders-command.js +5 -5
- package/dist/cli/messenger/admin-moderation-command.js +4 -4
- package/dist/cli/messenger/admin-statistics-command.js +6 -14
- package/dist/cli/messenger/analysis-consents-query.d.ts +5 -0
- package/dist/cli/messenger/analysis-consents-query.js +20 -0
- package/dist/cli/messenger/archive-commands.js +3 -3
- package/dist/cli/messenger/attachments-command.js +3 -0
- package/dist/cli/messenger/backfill-command.js +5 -4
- package/dist/cli/messenger/catch-up-answers.d.ts +2 -1
- package/dist/cli/messenger/catch-up-answers.js +6 -2
- package/dist/cli/messenger/chat-queries.d.ts +1 -0
- package/dist/cli/messenger/chat-queries.js +12 -2
- package/dist/cli/messenger/chats-command.js +2 -2
- package/dist/cli/messenger/chats-documents-command.js +7 -5
- package/dist/cli/messenger/chats-members-command.js +7 -3
- package/dist/cli/messenger/chats-read-command.js +1 -1
- package/dist/cli/messenger/chats-stats-command.js +1 -1
- package/dist/cli/messenger/chats-tracking-command.js +14 -6
- package/dist/cli/messenger/contacts-command.js +11 -7
- package/dist/cli/messenger/context.d.ts +2 -0
- package/dist/cli/messenger/conversations-command.js +47 -29
- package/dist/cli/messenger/doctor-command.js +5 -1
- package/dist/cli/messenger/document-links-query.d.ts +2 -0
- package/dist/cli/messenger/document-links-query.js +9 -0
- package/dist/cli/messenger/download-command.js +1 -0
- package/dist/cli/messenger/flood-command.d.ts +2 -2
- package/dist/cli/messenger/flood-command.js +3 -3
- package/dist/cli/messenger/gaps-command.js +2 -2
- package/dist/cli/messenger/guard-commands.js +35 -13
- package/dist/cli/messenger/hearing-command.d.ts +1 -1
- package/dist/cli/messenger/hearing-command.js +1 -1
- package/dist/cli/messenger/images-command.js +1 -0
- package/dist/cli/messenger/inbox.js +6 -4
- package/dist/cli/messenger/media-archive-command.js +2 -0
- package/dist/cli/messenger/media-archive-move-command.js +1 -0
- package/dist/cli/messenger/media-archive-timer-command.js +1 -1
- package/dist/cli/messenger/mentions-command.js +15 -2
- package/dist/cli/messenger/messages-command.js +2 -0
- package/dist/cli/messenger/messages-delete-command.js +1 -0
- package/dist/cli/messenger/messages-edit-command.js +1 -0
- package/dist/cli/messenger/messages-evidence-command.js +3 -1
- package/dist/cli/messenger/messages-forward-command.js +1 -0
- package/dist/cli/messenger/messages-pin-command.js +3 -0
- package/dist/cli/messenger/messages-send-command.js +1 -0
- package/dist/cli/messenger/messages-stats-command.js +1 -1
- package/dist/cli/messenger/metadata-command.js +7 -2
- package/dist/cli/messenger/models-command.js +10 -2
- package/dist/cli/messenger/polls-command.js +4 -0
- package/dist/cli/messenger/private-people-command.js +8 -6
- package/dist/cli/messenger/rankings-command.js +6 -11
- package/dist/cli/messenger/reactions-command.js +2 -0
- package/dist/cli/messenger/recipients-query.d.ts +5 -0
- package/dist/cli/messenger/recipients-query.js +18 -0
- package/dist/cli/messenger/records-command.js +13 -6
- package/dist/cli/messenger/replies-edit-command.d.ts +1 -1
- package/dist/cli/messenger/replies-edit-command.js +13 -5
- package/dist/cli/messenger/retention-command.js +1 -1
- package/dist/cli/messenger/review.js +6 -4
- package/dist/cli/messenger/search-command.js +3 -1
- package/dist/cli/messenger/searches-command.js +6 -2
- package/dist/cli/messenger/sends-query.d.ts +5 -0
- package/dist/cli/messenger/sends-query.js +33 -0
- package/dist/cli/messenger/serve-command.js +1 -0
- package/dist/cli/messenger/serve-relay.d.ts +1 -0
- package/dist/cli/messenger/statistics-query.d.ts +14 -0
- package/dist/cli/messenger/statistics-query.js +143 -0
- package/dist/cli/messenger/stats-command.js +6 -6
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/messenger/store-maintenance-command.js +10 -10
- package/dist/cli/messenger/tags-command.js +18 -6
- package/dist/cli/messenger/tasks-command.js +47 -8
- package/dist/cli/messenger/transcribe-command.js +2 -1
- package/dist/cli/messenger/watch-answers.d.ts +6 -0
- package/dist/cli/messenger/watch-answers.js +69 -0
- package/dist/cli/messenger/watch-command.d.ts +1 -1
- package/dist/cli/messenger/watch-command.js +56 -7
- package/dist/cli/program.js +5 -1
- package/dist/cli/runs/command.js +25 -38
- package/dist/cli/runs/query.d.ts +5 -0
- package/dist/cli/runs/query.js +32 -0
- package/dist/cli/runs/search-command.d.ts +4 -0
- package/dist/cli/runs/search-command.js +27 -0
- package/dist/cli/runs/search-query.d.ts +4 -0
- package/dist/cli/runs/search-query.js +50 -0
- package/dist/cli/runs/search.d.ts +2 -1
- package/dist/cli/runs/search.js +6 -6
- package/dist/domain/attachments.js +9 -1
- package/dist/domain/rankings-options.js +3 -3
- package/dist/entities/account-change.d.ts +89 -0
- package/dist/entities/account-change.js +20 -0
- package/dist/entities/account-profile.d.ts +7 -0
- package/dist/entities/account-profile.js +8 -0
- package/dist/entities/analysis-consent.d.ts +9 -0
- package/dist/entities/analysis-consent.js +4 -0
- package/dist/entities/attachment-results.d.ts +96 -0
- package/dist/entities/attachment-results.js +31 -0
- package/dist/entities/batch-result.d.ts +27 -0
- package/dist/entities/batch-result.js +18 -0
- package/dist/entities/chat-admin.d.ts +234 -0
- package/dist/entities/chat-admin.js +84 -0
- package/dist/entities/chat-change.d.ts +25 -0
- package/dist/entities/chat-change.js +11 -0
- package/dist/entities/chat-metadata.d.ts +34 -0
- package/dist/entities/chat-metadata.js +15 -0
- package/dist/entities/chat-moderation.d.ts +44 -0
- package/dist/entities/chat-moderation.js +37 -0
- package/dist/entities/chat-tracking.d.ts +26 -0
- package/dist/entities/chat-tracking.js +23 -0
- package/dist/entities/contact-activity.d.ts +52 -0
- package/dist/entities/contact-activity.js +42 -0
- package/dist/entities/contact-context.d.ts +1568 -0
- package/dist/entities/contact-context.js +191 -0
- package/dist/entities/contact-write.d.ts +22 -0
- package/dist/entities/contact-write.js +6 -0
- package/dist/entities/conversation-preparation.d.ts +63 -0
- package/dist/entities/conversation-preparation.js +23 -0
- package/dist/entities/conversation-results.d.ts +567 -0
- package/dist/entities/conversation-results.js +94 -0
- package/dist/entities/document-link.d.ts +13 -0
- package/dist/entities/document-link.js +11 -0
- package/dist/entities/extraction-report.d.ts +95 -0
- package/dist/entities/extraction-report.js +34 -0
- package/dist/entities/image-embedding.d.ts +9 -0
- package/dist/entities/image-embedding.js +10 -0
- package/dist/entities/index.d.ts +8006 -1928
- package/dist/entities/index.js +174 -3
- package/dist/entities/listener.d.ts +2150 -0
- package/dist/entities/listener.js +46 -0
- package/dist/entities/media-archive.d.ts +43 -0
- package/dist/entities/media-archive.js +32 -0
- package/dist/entities/meeting-task-proposal.d.ts +14 -0
- package/dist/entities/meeting-task-proposal.js +19 -0
- package/dist/entities/meeting.d.ts +1 -1
- package/dist/entities/meeting.js +1 -1
- package/dist/entities/mention.d.ts +63 -0
- package/dist/entities/mention.js +44 -0
- package/dist/entities/message-change.d.ts +19 -0
- package/dist/entities/message-change.js +6 -0
- package/dist/entities/message-context.d.ts +617 -0
- package/dist/entities/message-context.js +20 -0
- package/dist/entities/message-read.d.ts +73 -0
- package/dist/entities/message-read.js +58 -0
- package/dist/entities/message-transfer.d.ts +379 -0
- package/dist/entities/message-transfer.js +83 -0
- package/dist/entities/message-write.d.ts +191 -0
- package/dist/entities/message-write.js +8 -0
- package/dist/entities/model-key.d.ts +14 -0
- package/dist/entities/model-key.js +10 -0
- package/dist/entities/poll.d.ts +40 -0
- package/dist/entities/poll.js +16 -0
- package/dist/entities/private-contact.d.ts +10 -0
- package/dist/entities/private-contact.js +4 -0
- package/dist/entities/reaction-change.d.ts +7 -0
- package/dist/entities/reaction-change.js +8 -0
- package/dist/entities/recipient.d.ts +29 -0
- package/dist/entities/recipient.js +11 -0
- package/dist/entities/recorded-run.d.ts +103 -0
- package/dist/entities/recorded-run.js +44 -0
- package/dist/entities/saved-search.d.ts +4 -0
- package/dist/entities/saved-search.js +2 -0
- package/dist/entities/send-attempt.d.ts +31 -0
- package/dist/entities/send-attempt.js +29 -0
- package/dist/entities/store-maintenance.d.ts +319 -0
- package/dist/entities/store-maintenance.js +145 -0
- package/dist/entities/store-records.d.ts +442 -0
- package/dist/entities/store-records.js +99 -0
- package/dist/entities/tag-change.d.ts +74 -0
- package/dist/entities/tag-change.js +31 -0
- package/dist/entities/task-pair.d.ts +31 -0
- package/dist/entities/task-pair.js +23 -0
- package/dist/entities/task-results.d.ts +524 -0
- package/dist/entities/task-results.js +142 -0
- package/dist/errors/reasons.js +1 -0
- package/dist/mcp/agent.d.ts +3 -1
- package/dist/mcp/agent.js +9 -6
- package/dist/mcp/bot/server.d.ts +2 -0
- package/dist/mcp/bot/server.js +1 -0
- package/dist/mcp/prompts.js +8 -2
- package/dist/mcp/server.js +3 -1
- package/dist/mcp/tools/attachments.js +1 -0
- package/dist/meetings/cli/index.js +1 -1
- package/dist/meetings/cli/passage.js +1 -0
- package/dist/meetings/index.d.ts +2 -1
- package/dist/meetings/index.js +1 -0
- package/dist/meetings/links.d.ts +16 -0
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/meetings/read-answers.d.ts +167 -0
- package/dist/meetings/read-answers.js +183 -0
- package/dist/runs/run.d.ts +10 -2
- package/dist/runs/run.js +11 -3
- package/dist/sends/journal.d.ts +8 -1
- package/dist/sends/journal.js +9 -2
- package/dist/sends/permissions.d.ts +5 -1
- package/dist/sends/permissions.js +11 -1
- package/dist/sends/recipients.d.ts +8 -0
- package/dist/sends/recipients.js +9 -0
- package/dist/services/admin-statistics.js +3 -3
- package/dist/services/chat-documents.d.ts +1 -0
- package/dist/services/chat-documents.js +9 -3
- package/dist/services/chats.d.ts +1 -1
- package/dist/services/chats.js +5 -2
- package/dist/services/meeting-links.d.ts +2 -17
- package/dist/store/exports.d.ts +1 -1
- package/dist/store/exports.js +1 -1
- package/dist/store/messages.d.ts +3 -1
- package/dist/store/messages.js +2 -2
- package/dist/store/roster.d.ts +4 -1
- package/dist/store/roster.js +2 -2
- package/dist/store/sqlite/chats.d.ts +12 -0
- package/dist/store/sqlite/chats.js +1 -0
- package/dist/store/sqlite/document-links.d.ts +1 -1
- package/dist/store/sqlite/document-links.js +5 -5
- package/dist/store/sqlite/involvements.js +2 -1
- package/dist/store/sqlite/roster.d.ts +2 -1
- package/dist/store/sqlite/roster.js +3 -2
- package/package.json +3 -3
- package/parity.json +76 -108
|
@@ -11,6 +11,7 @@ export const editCommand = (messenger) => {
|
|
|
11
11
|
const edit = annotate(new Command("edit"), {
|
|
12
12
|
examples: [`${messenger.app.command} personal messages edit "Book club" 101 "The meeting starts at 11."`],
|
|
13
13
|
effects: REMOTE_WRITE,
|
|
14
|
+
output: { entity: "message_write" },
|
|
14
15
|
})
|
|
15
16
|
.description("change the text of your own message; the other side may have read it already")
|
|
16
17
|
.argument("<chat>", messenger.chatArgument)
|
|
@@ -7,10 +7,12 @@ import { positiveCount } from "../paging.js";
|
|
|
7
7
|
import { messengerContext } from "./context.js";
|
|
8
8
|
import { evidenceAnswer } from "./message-answers.js";
|
|
9
9
|
export const evidenceCommand = (messenger) => annotate(new Command("evidence"), {
|
|
10
|
+
output: { entity: "evidence_packet" },
|
|
10
11
|
examples: [`${messenger.app.command} personal messages evidence "Book club" --limit 10`],
|
|
11
12
|
effects: LOCAL_READ,
|
|
12
13
|
})
|
|
13
|
-
.
|
|
14
|
+
.summary("a recent-chat evidence packet from stored messages")
|
|
15
|
+
.description("general chat context, newest first, with references, coverage and fingerprints for verification")
|
|
14
16
|
.argument("<chat>", messenger.chatArgument)
|
|
15
17
|
.option("--limit <n>", "how many, 1–100", positiveCount("--limit"))
|
|
16
18
|
.option("--cursor <cursor>", "go on from where page.next says the last packet stopped")
|
|
@@ -9,6 +9,7 @@ export const forwardCommand = (messenger) => {
|
|
|
9
9
|
const forward = annotate(new Command("forward"), {
|
|
10
10
|
examples: [`${messenger.app.command} personal messages forward "Book club" 101 --to "Project room"`],
|
|
11
11
|
effects: REMOTE_WRITE,
|
|
12
|
+
output: { entity: "message_write" },
|
|
12
13
|
})
|
|
13
14
|
.description("forward one message to another chat")
|
|
14
15
|
.argument("<chat>", `the chat the message is in: ${messenger.chatArgument}`)
|
|
@@ -10,6 +10,7 @@ export const pinCommand = (messenger) => {
|
|
|
10
10
|
const durations = messenger.pinDurations?.length ? messenger.pinDurations : undefined;
|
|
11
11
|
const command = annotate(new Command("pin"), {
|
|
12
12
|
effects: REMOTE_WRITE,
|
|
13
|
+
output: { entity: "message_pin" },
|
|
13
14
|
examples: [
|
|
14
15
|
`${tool} messages pin <chat> <message>`,
|
|
15
16
|
...(quiet ? [`${tool} messages pin <chat> <message> --notify`] : []),
|
|
@@ -38,6 +39,7 @@ export const pinCommand = (messenger) => {
|
|
|
38
39
|
};
|
|
39
40
|
export const unpinCommand = (messenger) => annotate(new Command("unpin"), {
|
|
40
41
|
effects: REMOTE_WRITE,
|
|
42
|
+
output: { entity: "message_pin" },
|
|
41
43
|
examples: [`${messenger.app.command} messages unpin <chat> <message>`],
|
|
42
44
|
})
|
|
43
45
|
.description("unpin a message in a chat")
|
|
@@ -53,6 +55,7 @@ export const starCommands = (messenger) => [true, false].map((starred) => {
|
|
|
53
55
|
const name = starred ? "star" : "unstar";
|
|
54
56
|
return annotate(new Command(name), {
|
|
55
57
|
effects: REMOTE_WRITE,
|
|
58
|
+
output: { entity: "message_star" },
|
|
56
59
|
examples: [`${messenger.app.command} messages ${name} <chat> <message>`],
|
|
57
60
|
})
|
|
58
61
|
.description(starred ? "star a message, so it is easy to find again; only you see the star" : "take the star off a message")
|
|
@@ -19,6 +19,7 @@ export const sendCommand = (messenger) => {
|
|
|
19
19
|
const send = annotate(new Command("send"), {
|
|
20
20
|
examples: [`${messenger.app.command} personal messages send "Book club" "The meeting starts at 10."`],
|
|
21
21
|
effects: REMOTE_WRITE,
|
|
22
|
+
output: { entity: "message_write" },
|
|
22
23
|
})
|
|
23
24
|
.description("send a text message; without [text], the text is read from stdin")
|
|
24
25
|
.argument("<chat>", messenger.chatArgument)
|
|
@@ -12,7 +12,7 @@ export const messagesStatsCommand = (messenger) => syncOptions(annotate(new Comm
|
|
|
12
12
|
.summary("count stored messages by chat, sender, day or hour")
|
|
13
13
|
.description(`how many stored messages match, by chat, sender, day or hour — the local store only${syncsFirst(messenger) ? "; optionally fetches new messages with --sync-first" : ""}`)
|
|
14
14
|
.argument("[query...]", "a strict Lucene query, as for search messages; none counts every stored message; with --saved, more words AND-ed to it")
|
|
15
|
-
.option("--by <
|
|
15
|
+
.option("--by <group>", "count by chat, sender, day or hour (default: chat)", groupingOf)
|
|
16
16
|
.option("--chat <chat>", `only this chat — the same as chat: in the query; ${messenger.chatArgument}`)
|
|
17
17
|
.option("--source <accounts>", "every account of this messenger held in the store; personal, bots or all — the same as in: in the query")
|
|
18
18
|
.option("--limit <n>", "how many rows", positiveCount("--limit"))
|
|
@@ -8,7 +8,11 @@ import { messengerContext, refuseLocalWrite } from "./context.js";
|
|
|
8
8
|
export const metadataCommand = (messenger) => {
|
|
9
9
|
const tool = messenger.app.command;
|
|
10
10
|
const command = new Command("metadata").description("cached group/channel descriptions for local automatic tags");
|
|
11
|
-
annotate(command.command("get"), {
|
|
11
|
+
annotate(command.command("get"), {
|
|
12
|
+
output: { entity: "chat_metadata" },
|
|
13
|
+
effects: LOCAL_READ,
|
|
14
|
+
examples: [`${tool} metadata get --chat 7`],
|
|
15
|
+
})
|
|
12
16
|
.description("a stored chat's cached description, as automatic tags read it")
|
|
13
17
|
.requiredOption("--chat <chat>", "a stored chat")
|
|
14
18
|
.action(async function () {
|
|
@@ -17,13 +21,14 @@ export const metadataCommand = (messenger) => {
|
|
|
17
21
|
renderAnswer(this, context, itemOf(snakeKeys(await context.withServices((services) => services.metadata.get(chat)))));
|
|
18
22
|
});
|
|
19
23
|
annotate(command.command("refresh"), {
|
|
24
|
+
output: { entity: "chat_metadata_refresh" },
|
|
20
25
|
effects: FETCH,
|
|
21
26
|
examples: [`${tool} metadata refresh --chat 7 --chat 8`, `${tool} metadata refresh --only-missing --limit 20`],
|
|
22
27
|
})
|
|
23
28
|
.description("fetch group and channel descriptions again and cache them")
|
|
24
29
|
.option("--chat <chat>", "stored group/channel; repeat for several", (value, previous) => [...previous, value], [])
|
|
25
30
|
.option("--only-missing", "only chats with no metadata yet; without --chat, every stored group/channel")
|
|
26
|
-
.option("--limit <
|
|
31
|
+
.option("--limit <n>", "process at most 1–500 chats", positiveCount("--limit"), 50)
|
|
27
32
|
.action(async function () {
|
|
28
33
|
const context = messengerContext(this, messenger);
|
|
29
34
|
refuseLocalWrite(context, messenger.app.command, "metadata.refresh");
|
|
@@ -145,7 +145,11 @@ export const modelsCommand = (messenger) => {
|
|
|
145
145
|
}, { unbounded: true });
|
|
146
146
|
});
|
|
147
147
|
const key = text.command("key").description("API keys for embedding and analysis providers");
|
|
148
|
-
grantsAuthority(annotate(key.command("set"), {
|
|
148
|
+
grantsAuthority(annotate(key.command("set"), {
|
|
149
|
+
effects: LOCAL_WRITE,
|
|
150
|
+
output: { entity: "model_key", view: "stored" },
|
|
151
|
+
examples: [`${tool} models text key set openai`],
|
|
152
|
+
}))
|
|
149
153
|
.argument("<provider>", "openai, anthropic, or the host of a --base-url server that wants a key")
|
|
150
154
|
.description("store a key, typed at a hidden prompt or piped on stdin — never as an argument")
|
|
151
155
|
.action(async function (provider) {
|
|
@@ -159,7 +163,11 @@ export const modelsCommand = (messenger) => {
|
|
|
159
163
|
renderAnswer(this, context, itemOf({ provider, stored: source }));
|
|
160
164
|
});
|
|
161
165
|
});
|
|
162
|
-
grantsAuthority(annotate(key.command("remove"), {
|
|
166
|
+
grantsAuthority(annotate(key.command("remove"), {
|
|
167
|
+
effects: LOCAL_WRITE,
|
|
168
|
+
output: { entity: "model_key", view: "removed" },
|
|
169
|
+
examples: [`${tool} models text key remove openai`],
|
|
170
|
+
}))
|
|
163
171
|
.argument("<provider>", "openai, anthropic, or a server's host")
|
|
164
172
|
.description("forget a stored key")
|
|
165
173
|
.action(async function (provider) {
|
|
@@ -23,6 +23,7 @@ export const pollsCommand = (messenger) => {
|
|
|
23
23
|
? "read a poll, vote in it, create one"
|
|
24
24
|
: "read a poll, vote in it, close your own, create one");
|
|
25
25
|
annotate(polls.command("show"), {
|
|
26
|
+
output: { entity: "poll" },
|
|
26
27
|
effects: REMOTE_READ,
|
|
27
28
|
examples: [`${messenger.app.command} personal polls show "Book club" 101`],
|
|
28
29
|
})
|
|
@@ -67,6 +68,7 @@ export const pollsCommand = (messenger) => {
|
|
|
67
68
|
}), lines(({ voted_at, person_id, name, answers }) => [voted_at, name ?? person_id, answers.join(",")].join(" ")));
|
|
68
69
|
}));
|
|
69
70
|
annotate(polls.command("vote"), {
|
|
71
|
+
output: { entity: "poll_change" },
|
|
70
72
|
effects: REMOTE_WRITE,
|
|
71
73
|
examples: [`${messenger.app.command} personal polls vote "Book club" 101 0`],
|
|
72
74
|
})
|
|
@@ -95,6 +97,7 @@ export const pollsCommand = (messenger) => {
|
|
|
95
97
|
});
|
|
96
98
|
if (messenger.pollClose !== false)
|
|
97
99
|
annotate(polls.command("close"), {
|
|
100
|
+
output: { entity: "poll_change" },
|
|
98
101
|
effects: REMOTE_WRITE,
|
|
99
102
|
examples: [`${messenger.app.command} personal polls close "Book club" 101`],
|
|
100
103
|
})
|
|
@@ -107,6 +110,7 @@ export const pollsCommand = (messenger) => {
|
|
|
107
110
|
renderAnswer(this, context, itemOf(snakeKeys(closed)));
|
|
108
111
|
});
|
|
109
112
|
const create = annotate(polls.command("create"), {
|
|
113
|
+
output: { entity: "message_write" },
|
|
110
114
|
effects: REMOTE_WRITE,
|
|
111
115
|
examples: [`${messenger.app.command} personal polls create "Book club" "Which day?" Monday Tuesday`],
|
|
112
116
|
})
|
|
@@ -14,7 +14,7 @@ const NOTES_QUERY = unfilteredQuery("contact_note", contactNote);
|
|
|
14
14
|
const everyNote = (command, items) => listOf(command, { items, limit: Math.max(1, items.length), has_more: false });
|
|
15
15
|
export const privatePeopleCommands = (messenger) => {
|
|
16
16
|
const alias = new Command("alias").description("a private local display name in the selected account");
|
|
17
|
-
annotate(alias.command("set"), { effects: LOCAL_WRITE })
|
|
17
|
+
annotate(alias.command("set"), { effects: LOCAL_WRITE, output: { entity: "contact_alias" } })
|
|
18
18
|
.description("your own name for a person in this account; kept on this machine, never sent")
|
|
19
19
|
.argument("<person>", "the person's id, reference or known name")
|
|
20
20
|
.argument("<alias>", "the private name to use for this person")
|
|
@@ -23,7 +23,7 @@ export const privatePeopleCommands = (messenger) => {
|
|
|
23
23
|
refuseLocalWrite(context, messenger.app.command, "contacts.alias.set");
|
|
24
24
|
renderAnswer(this, context, itemOf(snakeKeys(await context.withServices((services) => services.privatePeople.alias(person, value)))));
|
|
25
25
|
});
|
|
26
|
-
annotate(alias.command("rm"), { effects: LOCAL_WRITE })
|
|
26
|
+
annotate(alias.command("rm"), { effects: LOCAL_WRITE, output: { entity: "contact_alias" } })
|
|
27
27
|
.description("drop your local name for a person; their own name shows again")
|
|
28
28
|
.argument("<person>", "the person's id, reference or known name")
|
|
29
29
|
.action(async function (person) {
|
|
@@ -54,10 +54,11 @@ export const privatePeopleCommands = (messenger) => {
|
|
|
54
54
|
output: { entity: "contact_note" },
|
|
55
55
|
}), { name: "text", description: "the note's text" })
|
|
56
56
|
.description(name === "add"
|
|
57
|
-
? "add a private note on a person from stdin or --file; never sent"
|
|
57
|
+
? "add a private note on a person from stdin or --text-file; never sent"
|
|
58
58
|
: "replace a note's text; --revision must match the one you read")
|
|
59
59
|
.argument("<person>", "the person's id, reference or known name")
|
|
60
|
-
.addOption(ownerOnlyOption("--file <path>", "read note text from a file; omitted or - reads stdin"))
|
|
60
|
+
.addOption(ownerOnlyOption("--text-file <path>", "read note text from a file; omitted or - reads stdin").conflicts("file"))
|
|
61
|
+
.addOption(ownerOnlyOption("--file <path>", "compatibility alias for --text-file").hideHelp().conflicts("textFile"));
|
|
61
62
|
if (name === "edit")
|
|
62
63
|
command
|
|
63
64
|
.argument("<id>", "the note id from contacts notes list")
|
|
@@ -65,7 +66,8 @@ export const privatePeopleCommands = (messenger) => {
|
|
|
65
66
|
command.action(async function (person, id) {
|
|
66
67
|
const context = messengerContext(this, messenger);
|
|
67
68
|
refuseLocalWrite(context, messenger.app.command, `contacts.notes.${name}`);
|
|
68
|
-
const { file, revision } = this.opts();
|
|
69
|
+
const { textFile, file: legacyFile, revision, } = this.opts();
|
|
70
|
+
const file = textFile ?? legacyFile;
|
|
69
71
|
const text = file === undefined || file === "-" ? await readAll(context.stdin) : await readFile(file, "utf8");
|
|
70
72
|
const version = Number(revision);
|
|
71
73
|
if (name === "edit" && (!Number.isSafeInteger(version) || version < 1))
|
|
@@ -76,7 +78,7 @@ export const privatePeopleCommands = (messenger) => {
|
|
|
76
78
|
renderAnswer(this, context, itemOf(saved));
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
|
-
annotate(notes.command("remove"), { effects: LOCAL_WRITE })
|
|
81
|
+
annotate(notes.command("remove"), { effects: LOCAL_WRITE, output: { entity: "contact_note_removal" } })
|
|
80
82
|
.description("delete one private note on a person")
|
|
81
83
|
.argument("<person>", "the person's id, reference or known name")
|
|
82
84
|
.argument("<id>", "the note id from contacts notes list")
|
|
@@ -12,6 +12,7 @@ import { renderAnswer } from "../envelope.js";
|
|
|
12
12
|
import { positiveCount } from "../paging.js";
|
|
13
13
|
import { messengerContext } from "./context.js";
|
|
14
14
|
import { syncOptions, syncRequest } from "./search-sync-options.js";
|
|
15
|
+
import { statisticsQuery, withStatisticsQuery } from "./statistics-query.js";
|
|
15
16
|
import { evidenceAnswer, rankingAnswer, refuseJsonl } from "./stats-answers.js";
|
|
16
17
|
const selectionOf = (value) => {
|
|
17
18
|
if (Buffer.byteLength(value) > RANKING_SELECTION_BYTES)
|
|
@@ -35,28 +36,22 @@ export const rankingsTopCommand = (messenger, target) => {
|
|
|
35
36
|
"engaging",
|
|
36
37
|
]))
|
|
37
38
|
.option("--weights <json>", "the complete component weights; replaces preset weights")
|
|
38
|
-
.addOption(new Option("--message-kind <kind>", "select proven all, posts or comments before ranking").choices([
|
|
39
|
-
"all",
|
|
40
|
-
"posts",
|
|
41
|
-
"comments",
|
|
42
|
-
]))
|
|
43
|
-
.option("--chat <chat>", `only this chat; ${messenger.chatArgument}`)
|
|
44
39
|
.option("--source <accounts>", "every held account of this messenger; personal, bots or all")
|
|
45
40
|
.option("--timezone <zone>", "the IANA timezone for dates and active days")
|
|
46
|
-
.option("--exact", "bare words match exact forms rather than stems")
|
|
47
41
|
.option("--limit <n>", "ranked rows, 1–100", positiveCount("--limit"))
|
|
48
42
|
.option("--saved <name|id>", "run a saved query or ranking run; typed options replace stored options");
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
const report = target === "contacts" ? "contacts-top" : "messages-top";
|
|
44
|
+
withStatisticsQuery(command, report);
|
|
51
45
|
command.action(async function (words) {
|
|
46
|
+
const filters = statisticsQuery(words, report);
|
|
52
47
|
const context = messengerContext(this, messenger);
|
|
53
48
|
refuseJsonl(context.format);
|
|
54
49
|
const options = this.opts();
|
|
55
50
|
const { saved, ...typed } = options;
|
|
56
|
-
let params = { ...typed, ...
|
|
51
|
+
let params = { ...typed, ...filters };
|
|
57
52
|
const found = await context.withServices(async (services) => {
|
|
58
53
|
if (saved !== undefined)
|
|
59
|
-
params = (await services.searches.resolve(saved, { ...params, text:
|
|
54
|
+
params = (await services.searches.resolve(saved, { ...params, text: filters.text ?? "" })).params;
|
|
60
55
|
if (params.target !== undefined && params.target !== target)
|
|
61
56
|
throw new CliError("validation_error", "saved ranking belongs to a different target");
|
|
62
57
|
if (params.newest || params.context)
|
|
@@ -8,6 +8,7 @@ export const reactionsCommand = (messenger) => {
|
|
|
8
8
|
const reactions = new Command("reactions").description("react to messages");
|
|
9
9
|
annotate(reactions.command("add"), {
|
|
10
10
|
effects: REMOTE_WRITE,
|
|
11
|
+
output: { entity: "reaction_change" },
|
|
11
12
|
examples: [`${messenger.app.command} personal reactions add "Book club" 101 👍`],
|
|
12
13
|
})
|
|
13
14
|
.description("put your reaction on a message; it replaces the one you had")
|
|
@@ -21,6 +22,7 @@ export const reactionsCommand = (messenger) => {
|
|
|
21
22
|
});
|
|
22
23
|
annotate(reactions.command("remove"), {
|
|
23
24
|
effects: REMOTE_WRITE,
|
|
25
|
+
output: { entity: "reaction_change" },
|
|
24
26
|
examples: [`${messenger.app.command} personal reactions remove "Book club" 101`],
|
|
25
27
|
})
|
|
26
28
|
.description("take your reaction off a message")
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type QueryRegistry } from "@wirecat/cli-base/query";
|
|
2
|
+
import type { RecipientFilter } from "../../sends/recipients.js";
|
|
3
|
+
import { type QueryWords } from "../list-query.js";
|
|
4
|
+
export declare const RECIPIENTS_QUERY: QueryRegistry;
|
|
5
|
+
export declare const recipientFilter: (words: QueryWords) => RecipientFilter;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { queryFieldsOf } from "@wirecat/cli-base/query";
|
|
2
|
+
import { recipient } from "../../entities/index.js";
|
|
3
|
+
import { queryTerms } from "../list-query.js";
|
|
4
|
+
export const RECIPIENTS_QUERY = {
|
|
5
|
+
entity: "recipient",
|
|
6
|
+
backend: "native",
|
|
7
|
+
fields: queryFieldsOf(recipient, {
|
|
8
|
+
native: ["id", "title"],
|
|
9
|
+
examples: { id: "id:7", title: 'title:"Book club"' },
|
|
10
|
+
}).map((field) => field.native
|
|
11
|
+
? { ...field, operators: field.operators.filter((operator) => operator === "term" || operator === "phrase") }
|
|
12
|
+
: field),
|
|
13
|
+
};
|
|
14
|
+
export const recipientFilter = (words) => {
|
|
15
|
+
const terms = queryTerms(words, RECIPIENTS_QUERY, "recipients list");
|
|
16
|
+
const id = terms.get("id"), title = terms.get("title");
|
|
17
|
+
return { ...(id === undefined ? {} : { id }), ...(title === undefined ? {} : { title }) };
|
|
18
|
+
};
|
|
@@ -83,6 +83,7 @@ export const callsCommand = (messenger) => {
|
|
|
83
83
|
/** `chats delete` and `chats clear` — for this account only; at the default level they ask first. */
|
|
84
84
|
export const chatDeletionCommands = (messenger) => [
|
|
85
85
|
annotate(new Command("delete"), {
|
|
86
|
+
output: { entity: "chat_removal" },
|
|
86
87
|
effects: REMOTE_WRITE,
|
|
87
88
|
mcp: false,
|
|
88
89
|
examples: [`${messenger.app.command} personal chats delete "Book club"`],
|
|
@@ -95,6 +96,7 @@ export const chatDeletionCommands = (messenger) => [
|
|
|
95
96
|
renderAnswer(this, context, itemOf(snakeKeys(await context.withServices((services) => services.admin.deleteChat(chat)))));
|
|
96
97
|
}),
|
|
97
98
|
annotate(new Command("clear"), {
|
|
99
|
+
output: { entity: "chat_removal" },
|
|
98
100
|
effects: REMOTE_WRITE,
|
|
99
101
|
mcp: false,
|
|
100
102
|
examples: [`${messenger.app.command} personal chats clear "Book club"`],
|
|
@@ -110,6 +112,7 @@ export const chatDeletionCommands = (messenger) => [
|
|
|
110
112
|
/** `chats mute` and `unmute` — the owner's own notifications for one chat; nobody in it is told. */
|
|
111
113
|
export const muteCommands = (messenger) => [
|
|
112
114
|
annotate(new Command("mute"), {
|
|
115
|
+
output: { entity: "chat_muting" },
|
|
113
116
|
effects: REMOTE_WRITE,
|
|
114
117
|
examples: [
|
|
115
118
|
`${messenger.app.command} chats mute "Book club"`,
|
|
@@ -126,6 +129,7 @@ export const muteCommands = (messenger) => [
|
|
|
126
129
|
renderAnswer(this, context, itemOf(snakeKeys(await context.withServices((services) => services.account.mute(chat, when)))));
|
|
127
130
|
}),
|
|
128
131
|
annotate(new Command("unmute"), {
|
|
132
|
+
output: { entity: "chat_muting" },
|
|
129
133
|
effects: REMOTE_WRITE,
|
|
130
134
|
examples: [`${messenger.app.command} chats unmute "Book club"`],
|
|
131
135
|
})
|
|
@@ -136,7 +140,8 @@ export const muteCommands = (messenger) => [
|
|
|
136
140
|
renderAnswer(this, context, itemOf(snakeKeys(await context.withServices((services) => services.account.mute(chat, null)))));
|
|
137
141
|
}),
|
|
138
142
|
];
|
|
139
|
-
const onChatCommand = (messenger, name, description, change) => annotate(new Command(name), {
|
|
143
|
+
const onChatCommand = (messenger, name, description, entity, change) => annotate(new Command(name), {
|
|
144
|
+
output: { entity },
|
|
140
145
|
effects: REMOTE_WRITE,
|
|
141
146
|
examples: [`${messenger.app.command} chats ${name} 123456789`],
|
|
142
147
|
})
|
|
@@ -148,16 +153,16 @@ const onChatCommand = (messenger, name, description, change) => annotate(new Com
|
|
|
148
153
|
});
|
|
149
154
|
/** `chats archive` and `unarchive` — the messenger's archive of chats, not the local store. */
|
|
150
155
|
export const archiveCommands = (messenger) => [
|
|
151
|
-
onChatCommand(messenger, "archive", "move a chat into the archive; nobody in it is told", (services, chat) => services.account.archive(chat, true)),
|
|
152
|
-
onChatCommand(messenger, "unarchive", "bring an archived chat back to the chat list", (services, chat) => services.account.archive(chat, false)),
|
|
156
|
+
onChatCommand(messenger, "archive", "move a chat into the archive; nobody in it is told", "chat_archive", (services, chat) => services.account.archive(chat, true)),
|
|
157
|
+
onChatCommand(messenger, "unarchive", "bring an archived chat back to the chat list", "chat_archive", (services, chat) => services.account.archive(chat, false)),
|
|
153
158
|
];
|
|
154
159
|
/** `chats pin` and `unpin` — where the chat sits in the owner's list; `messages pin` pins a message for everyone. */
|
|
155
160
|
export const chatPinCommands = (messenger) => [
|
|
156
|
-
onChatCommand(messenger, "pin", "keep a chat at the top of your chat list; nobody in it is told", (services, chat) => services.account.pinChat(chat, true)),
|
|
157
|
-
onChatCommand(messenger, "unpin", "let a pinned chat move down the chat list again", (services, chat) => services.account.pinChat(chat, false)),
|
|
161
|
+
onChatCommand(messenger, "pin", "keep a chat at the top of your chat list; nobody in it is told", "chat_pin", (services, chat) => services.account.pinChat(chat, true)),
|
|
162
|
+
onChatCommand(messenger, "unpin", "let a pinned chat move down the chat list again", "chat_pin", (services, chat) => services.account.pinChat(chat, false)),
|
|
158
163
|
];
|
|
159
164
|
/** `chats mark-unread` — undone by `chats mark-read`, which the other side does see. */
|
|
160
|
-
export const markUnreadCommand = (messenger) => onChatCommand(messenger, "mark-unread", "mark a chat unread on your own devices; nobody in it is told", (services, chat) => services.account.markUnread(chat));
|
|
165
|
+
export const markUnreadCommand = (messenger) => onChatCommand(messenger, "mark-unread", "mark a chat unread on your own devices; nobody in it is told", "chat_unread", (services, chat) => services.account.markUnread(chat));
|
|
161
166
|
const AUDIENCES = ["everyone", "contacts", "nobody"];
|
|
162
167
|
const audienceOf = (flag, value) => {
|
|
163
168
|
if (!AUDIENCES.includes(value))
|
|
@@ -202,6 +207,7 @@ export const privacyCommand = (messenger) => {
|
|
|
202
207
|
const keys = messenger.privacySettings ?? PRIVACY_SETTINGS;
|
|
203
208
|
const privacy = new Command("privacy").description("who may find, call or add the account");
|
|
204
209
|
annotate(privacy.command("show"), {
|
|
210
|
+
output: { entity: "account_privacy" },
|
|
205
211
|
effects: REMOTE_READ,
|
|
206
212
|
examples: [`${tool} account privacy show`, `${tool} account privacy show --json`],
|
|
207
213
|
})
|
|
@@ -214,6 +220,7 @@ export const privacyCommand = (messenger) => {
|
|
|
214
220
|
const audience = keys.find((key) => !SWITCHES.has(key));
|
|
215
221
|
const toggle = keys.find((key) => SWITCHES.has(key));
|
|
216
222
|
const set = annotate(new Command("set"), {
|
|
223
|
+
output: { entity: "account_privacy_change" },
|
|
217
224
|
effects: REMOTE_WRITE,
|
|
218
225
|
examples: [audience, toggle].flatMap((key) => (key === undefined ? [] : [exampleOf(tool, key)])),
|
|
219
226
|
}).description("change who may find, call or add the account; the settings not named stay");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { type Messenger } from "./context.js";
|
|
3
|
-
export declare const REPLY_EDIT_OPTIONS: readonly [readonly ["--do <actions>", "actions: reply, task, or both, comma-separated"], readonly ["--kinds <kinds>", "chat kinds: dialog, group; comma-separated, empty for any"], readonly ["--allow-chats <ids>", "only these chat ids, comma-separated; empty for any"], readonly ["--deny-chats <ids>", "leave these chat ids out, comma-separated; empty clears"], readonly ["--words <words>", "match any of these whole words, comma-separated; empty clears"], readonly ["--question", "match only questions"], readonly ["--no-question", "do not require a question"], readonly ["--mentions-me", "require a mention of you or a reply to you"], readonly ["--no-mentions-me", "do not require a mention of you or a reply to you"], readonly ["--allow-people <ids>", "only these sender ids, comma-separated; empty for any"], readonly ["--deny-people <ids>", "leave these sender ids out, comma-separated; empty clears"], readonly ["--contacts-only", "match only contacts"], readonly ["--no-contacts-only", "do not require a contact"], readonly ["--template <text>", "the reply template"], readonly ["--
|
|
3
|
+
export declare const REPLY_EDIT_OPTIONS: readonly [readonly ["--do <actions>", "actions: reply, task, or both, comma-separated"], readonly ["--kinds <kinds>", "chat kinds: dialog, group; comma-separated, empty for any"], readonly ["--allow-chats <ids>", "only these chat ids, comma-separated; empty for any"], readonly ["--deny-chats <ids>", "leave these chat ids out, comma-separated; empty clears"], readonly ["--words <words>", "match any of these whole words, comma-separated; empty clears"], readonly ["--question", "match only questions"], readonly ["--no-question", "do not require a question"], readonly ["--mentions-me", "require a mention of you or a reply to you"], readonly ["--no-mentions-me", "do not require a mention of you or a reply to you"], readonly ["--allow-people <ids>", "only these sender ids, comma-separated; empty for any"], readonly ["--deny-people <ids>", "leave these sender ids out, comma-separated; empty clears"], readonly ["--contacts-only", "match only contacts"], readonly ["--no-contacts-only", "do not require a contact"], readonly ["--template <text>", "the reply template"], readonly ["--template-mode <mode>", "legacy template mode: fill-only or may-reword; use ai blocks instead"], readonly ["--as-reply", "send as a reply to the matched message"], readonly ["--no-as-reply", "send without linking to the matched message"], readonly ["--per-chat <limit>", "at most this many per chat, such as 1/12h"], readonly ["--per-person <limit>", "at most this many per person, such as 1/1d"], readonly ["--outside <hours>", "answer outside this 24-hour window, such as 09:00-19:00"], readonly ["--days <days>", "days of the working window, such as mon-fri or sat,sun"], readonly ["--timezone <zone>", "the IANA timezone for the working window"], readonly ["--no-hours", "clear the working window"]];
|
|
4
4
|
export declare const REPLY_AUDIENCE_OPTIONS: readonly [readonly ["--reply <mode>", "answer all or only listed senders and chats: all, listed"], readonly ["--allow-people <ids>", "replace allowed sender ids, comma-separated; empty clears"], readonly ["--allow-chats <ids>", "replace allowed chat ids, comma-separated; empty clears"], readonly ["--deny-people <ids>", "replace denied sender ids, comma-separated; empty clears; deny wins"], readonly ["--deny-chats <ids>", "replace denied chat ids, comma-separated; empty clears; deny wins"]];
|
|
5
5
|
export declare const addReplyEditors: (replies: Command, messenger: Messenger) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { annotate } from "@wirecat/cli-base/commands";
|
|
2
|
-
import { Command } from "commander";
|
|
2
|
+
import { Command, Option } from "commander";
|
|
3
3
|
import { addRule, editAudience, editRule, switchRule } from "../../replies/edit.js";
|
|
4
4
|
import { audienceWarnings, repliesPathFor } from "../../replies/rules.js";
|
|
5
5
|
import { grantsAuthority, LOCAL_WRITE } from "../effects.js";
|
|
@@ -20,7 +20,7 @@ export const REPLY_EDIT_OPTIONS = [
|
|
|
20
20
|
["--contacts-only", "match only contacts"],
|
|
21
21
|
["--no-contacts-only", "do not require a contact"],
|
|
22
22
|
["--template <text>", "the reply template"],
|
|
23
|
-
["--
|
|
23
|
+
["--template-mode <mode>", "legacy template mode: fill-only or may-reword; use ai blocks instead"],
|
|
24
24
|
["--as-reply", "send as a reply to the matched message"],
|
|
25
25
|
["--no-as-reply", "send without linking to the matched message"],
|
|
26
26
|
["--per-chat <limit>", "at most this many per chat, such as 1/12h"],
|
|
@@ -59,8 +59,13 @@ export const addReplyEditors = (replies, messenger) => {
|
|
|
59
59
|
const edit = grantsAuthority(annotate(new Command("edit"), { effects: LOCAL_WRITE }))
|
|
60
60
|
.description("change only the named fields of a reply rule; lists replace the whole list")
|
|
61
61
|
.argument("<id>", "the rule's id");
|
|
62
|
-
for (const [flag, help] of REPLY_EDIT_OPTIONS)
|
|
63
|
-
|
|
62
|
+
for (const [flag, help] of REPLY_EDIT_OPTIONS) {
|
|
63
|
+
const option = new Option(flag, help);
|
|
64
|
+
if (flag === "--template-mode <mode>")
|
|
65
|
+
option.conflicts("model");
|
|
66
|
+
edit.addOption(option);
|
|
67
|
+
}
|
|
68
|
+
edit.addOption(new Option("--model <mode>", "compatibility alias for --template-mode").hideHelp().conflicts("templateMode"));
|
|
64
69
|
// Commander gives negated-only flags a true default; omission must preserve the saved field.
|
|
65
70
|
edit.action(function (id) {
|
|
66
71
|
const options = this.opts();
|
|
@@ -68,7 +73,10 @@ export const addReplyEditors = (replies, messenger) => {
|
|
|
68
73
|
delete options.hours;
|
|
69
74
|
const context = messengerContext(this, messenger);
|
|
70
75
|
const { settings, env } = context;
|
|
71
|
-
renderItem(this, context, editRule(repliesPathFor(messenger.app, settings.profile, env), messenger.provider, id,
|
|
76
|
+
renderItem(this, context, editRule(repliesPathFor(messenger.app, settings.profile, env), messenger.provider, id, {
|
|
77
|
+
...options,
|
|
78
|
+
model: options.templateMode ?? options.model,
|
|
79
|
+
}));
|
|
72
80
|
});
|
|
73
81
|
replies.addCommand(edit);
|
|
74
82
|
const audience = grantsAuthority(annotate(new Command("audience"), { effects: LOCAL_WRITE })).description("show the reply audience, who the rules may answer, or replace its named fields; a new file answers everyone a rule matches");
|
|
@@ -13,7 +13,7 @@ export const retentionCommand = (messenger) => annotate(new Command("retention")
|
|
|
13
13
|
.option("--until-time <time>", "joining period ends at this time; now by default")
|
|
14
14
|
.option("--checkpoints <durations>", "up to 10 increasing joining ages, comma separated; 1d,7d,30d by default")
|
|
15
15
|
.option("--within <duration>", "activity and early departure window after joining; 7d by default")
|
|
16
|
-
.addOption(new Option("--by <
|
|
16
|
+
.addOption(new Option("--by <group>", "group joining dates by calendar day or Monday week").choices(["day", "week"]))
|
|
17
17
|
.option("--timezone <zone>", "IANA timezone for joining cohorts")
|
|
18
18
|
.option("--limit <n>", "cohorts and member evidence, 1–100", positiveCount("--limit"))
|
|
19
19
|
.action(async function (chat) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { annotate } from "@wirecat/cli-base/commands";
|
|
3
|
-
import { Command } from "commander";
|
|
3
|
+
import { Command, Option } from "commander";
|
|
4
4
|
import { parseDuration } from "../../domain/duration.js";
|
|
5
5
|
import { renderMessages } from "../../render/messages.js";
|
|
6
6
|
import { CHAT_KINDS } from "../../services/chats.js";
|
|
@@ -34,7 +34,7 @@ export const reviewCommand = (messenger) => annotate(new Command("review"), {
|
|
|
34
34
|
.description("every message, yours too, in chats that changed since a point — for reviewing who owes what")
|
|
35
35
|
.addHelpText("after", queryHelp(REVIEW_QUERY))
|
|
36
36
|
.argument("[query...]", `where the last review ended and which chat: date>2h, chat:"Book club"; ${REVIEW_DAYS} days ago if no date`)
|
|
37
|
-
.
|
|
37
|
+
.addOption(new Option("--kind <kinds>", `compatibility spelling for kind:; ${CHAT_KINDS.join(", ")}`).hideHelp())
|
|
38
38
|
.option("--unanswered [duration]", `only questions to you or a group's admins that nobody answered, asked at least this long ago — 4h, 1d; ${UNANSWERED_HOURS}h if not given`)
|
|
39
39
|
.option("--all", "muted and archived chats too — left out unless they mention you or reply to you")
|
|
40
40
|
.option(...TRANSCRIBE_OPTION)
|
|
@@ -47,7 +47,9 @@ export const reviewCommand = (messenger) => annotate(new Command("review"), {
|
|
|
47
47
|
const hearWith = modelWith(options.transcribe, options.model);
|
|
48
48
|
const context = messengerContext(this, messenger);
|
|
49
49
|
const { settings, renderer, format, env } = context;
|
|
50
|
-
const { since: from, chat, meta } = catchUpQuery(query, REVIEW_QUERY, "review");
|
|
50
|
+
const { since: from, chat, meta, kinds: queriedKinds } = catchUpQuery(query, REVIEW_QUERY, "review");
|
|
51
|
+
if (options.kind !== undefined && queriedKinds !== undefined)
|
|
52
|
+
throw new CliError("validation_error", "give kind: or its legacy --kind spelling, not both");
|
|
51
53
|
if (options.new && (from !== undefined || options.unanswered !== undefined)) {
|
|
52
54
|
// An open question stays open: moving past it would drop it from the next review.
|
|
53
55
|
throw new CliError("validation_error", "--new keeps its own point — not with a date or --unanswered");
|
|
@@ -62,7 +64,7 @@ export const reviewCommand = (messenger) => annotate(new Command("review"), {
|
|
|
62
64
|
: undefined;
|
|
63
65
|
const since = from ?? saved?.first ?? reviewStart();
|
|
64
66
|
const hours = options.unanswered === undefined ? undefined : unansweredHours(options.unanswered);
|
|
65
|
-
const kinds = options.kind === undefined ? undefined : kindsOf(options.kind);
|
|
67
|
+
const kinds = queriedKinds ?? (options.kind === undefined ? undefined : kindsOf(options.kind));
|
|
66
68
|
let hearing;
|
|
67
69
|
const transcribe = options.transcribe === true;
|
|
68
70
|
const { found, reader } = await context.withServices(async (services, connect) => {
|
|
@@ -6,6 +6,7 @@ import { searchNotesOf } from "../../services/notes-search.js";
|
|
|
6
6
|
import { LOCAL_READ, REMOTE_READ } from "../effects.js";
|
|
7
7
|
import { renderAnswer } from "../envelope.js";
|
|
8
8
|
import { positiveCount } from "../paging.js";
|
|
9
|
+
import { runsSearchCommand } from "../runs/search-command.js";
|
|
9
10
|
import { commandAt } from "../steps.js";
|
|
10
11
|
import { messengerContext } from "./context.js";
|
|
11
12
|
import { conversationsSearchCommand } from "./conversations-command.js";
|
|
@@ -159,7 +160,8 @@ export const searchCommand = (messenger, { topics = false } = {}) => {
|
|
|
159
160
|
.addCommand(allCommand(messenger))
|
|
160
161
|
.addCommand(messagesSearchCommand(messenger))
|
|
161
162
|
.addCommand(notesCommand(messenger))
|
|
162
|
-
.addCommand(conversationsSearchCommand(messenger))
|
|
163
|
+
.addCommand(conversationsSearchCommand(messenger))
|
|
164
|
+
.addCommand(runsSearchCommand(messenger.app));
|
|
163
165
|
if (topics)
|
|
164
166
|
search.addCommand(topicsSearchCommand(messenger));
|
|
165
167
|
for (const [path, args] of Object.entries({
|
|
@@ -45,7 +45,7 @@ export const searchesCommand = (messenger) => {
|
|
|
45
45
|
.option("--exact", "bare words and quotes match their exact form only, as exact:word does; text: still matches every form")
|
|
46
46
|
.option("--context <n>", "messages before and after each hit", wholeCount)
|
|
47
47
|
.option("--timezone <zone>", "the IANA timezone for calendar date boundaries")
|
|
48
|
-
.option("--by <
|
|
48
|
+
.option("--by <group>", "count by chat, sender, day or hour for stats messages show --saved", groupingOf)
|
|
49
49
|
.option("--selection <json>", "save the resolved parent ranking query and options from a drilldown")
|
|
50
50
|
.option("--replace", "overwrite a saved search of the same name")
|
|
51
51
|
.action(async function (name, words) {
|
|
@@ -124,7 +124,11 @@ export const searchesCommand = (messenger) => {
|
|
|
124
124
|
const deleted = await context.withServices((services) => services.searches.delete(reference));
|
|
125
125
|
renderAnswer(this, context, itemOf(savedSearchItem(deleted)), () => `deleted ${deleted.name ?? `run ${deleted.id}`}\n`);
|
|
126
126
|
});
|
|
127
|
-
annotate(searches.command("clear"), {
|
|
127
|
+
annotate(searches.command("clear"), {
|
|
128
|
+
output: { entity: "search_history_clear" },
|
|
129
|
+
effects: LOCAL_WRITE,
|
|
130
|
+
examples: [`${tool} searches clear`],
|
|
131
|
+
})
|
|
128
132
|
.description("empty the history; saved searches stay")
|
|
129
133
|
.action(async function () {
|
|
130
134
|
const context = messengerContext(this, messenger);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type QueryRegistry } from "@wirecat/cli-base/query";
|
|
2
|
+
import type { SendFilter } from "../../sends/journal.js";
|
|
3
|
+
import { type QueryWords } from "../list-query.js";
|
|
4
|
+
export declare const SENDS_QUERY: QueryRegistry;
|
|
5
|
+
export declare const sendFilter: (words: QueryWords) => SendFilter | undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { queryFieldsOf } from "@wirecat/cli-base/query";
|
|
2
|
+
import { sendAttempt } from "../../entities/index.js";
|
|
3
|
+
import { queryTerms } from "../list-query.js";
|
|
4
|
+
export const SENDS_QUERY = {
|
|
5
|
+
entity: "send_attempt",
|
|
6
|
+
backend: "native",
|
|
7
|
+
fields: queryFieldsOf(sendAttempt, {
|
|
8
|
+
native: ["outcome", "chat_id", "operation_id", "error_code", "key"],
|
|
9
|
+
examples: {
|
|
10
|
+
outcome: "outcome:failed",
|
|
11
|
+
chat_id: "chat_id:7",
|
|
12
|
+
operation_id: "operation_id:op-1",
|
|
13
|
+
error_code: "error_code:timeout",
|
|
14
|
+
key: "key:messages.send",
|
|
15
|
+
},
|
|
16
|
+
}).map((field) => field.native
|
|
17
|
+
? { ...field, operators: field.operators.filter((operator) => operator === "term" || operator === "phrase") }
|
|
18
|
+
: field),
|
|
19
|
+
};
|
|
20
|
+
export const sendFilter = (words) => {
|
|
21
|
+
const terms = queryTerms(words, SENDS_QUERY, "sends list");
|
|
22
|
+
if (terms.size === 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
const outcome = sendAttempt.entries.outcome.options.find((value) => value === terms.get("outcome"));
|
|
25
|
+
const chatId = terms.get("chat_id"), operationId = terms.get("operation_id"), errorCode = terms.get("error_code"), key = terms.get("key");
|
|
26
|
+
return {
|
|
27
|
+
...(outcome === undefined ? {} : { outcome }),
|
|
28
|
+
...(chatId === undefined ? {} : { chatId }),
|
|
29
|
+
...(operationId === undefined ? {} : { operationId }),
|
|
30
|
+
...(errorCode === undefined ? {} : { errorCode }),
|
|
31
|
+
...(key === undefined ? {} : { key }),
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -31,6 +31,7 @@ export { lockPath, readLock, servingProfiles } from "../../background/lock.js";
|
|
|
31
31
|
*/
|
|
32
32
|
export const serveCommand = (messenger) => {
|
|
33
33
|
const command = annotate(new Command("serve"), {
|
|
34
|
+
output: { entity: "serve_summary" },
|
|
34
35
|
effects: REMOTE_WRITE,
|
|
35
36
|
lifetime: "persistent",
|
|
36
37
|
examples: [`${messenger.app.command} personal serve`],
|
|
@@ -78,6 +78,7 @@ export declare const serveRelay: (command: Command, messenger: Messenger) => {
|
|
|
78
78
|
inviteLinkRevoke?: boolean;
|
|
79
79
|
inviteLinkUpdate?: boolean;
|
|
80
80
|
joinRequestsAll?: boolean;
|
|
81
|
+
joinRequestsByLink?: boolean;
|
|
81
82
|
channelComments?: boolean;
|
|
82
83
|
addsWithHistory?: boolean;
|
|
83
84
|
adminRights?: readonly import("../../domain/models.js").AdminRight[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type QueryWords } from "../list-query.js";
|
|
3
|
+
export type StatisticsQuery = "contacts-top" | "messages-top" | "discussion" | "unanswered" | "responses";
|
|
4
|
+
export declare const withStatisticsQuery: (command: Command, report: StatisticsQuery) => Command;
|
|
5
|
+
/** Report predicates become the existing source/aggregate parameters; the message query keeps its syntax. */
|
|
6
|
+
export interface StatisticsFilters {
|
|
7
|
+
text?: string;
|
|
8
|
+
messageKind?: string;
|
|
9
|
+
minMessages?: number;
|
|
10
|
+
minViews?: number;
|
|
11
|
+
maxReplies?: number;
|
|
12
|
+
olderThan?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const statisticsQuery: (words: QueryWords, report: StatisticsQuery) => StatisticsFilters;
|