@wirecat/cli-core 0.405.0 → 0.407.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 +36 -1
- package/dist/botcheck/reasons.d.ts +1 -1
- package/dist/cli/analysis-choice.js +1 -1
- package/dist/cli/answer-entity.d.ts +8 -0
- package/dist/cli/answer-entity.js +31 -0
- package/dist/cli/command-contract.js +5 -6
- package/dist/cli/commands-command.js +4 -1
- package/dist/cli/effects.js +1 -1
- package/dist/cli/embedding-choice.d.ts +1 -1
- package/dist/cli/embedding-choice.js +2 -2
- package/dist/cli/help/command-help.js +2 -2
- package/dist/cli/index.d.ts +6 -2
- package/dist/cli/index.js +6 -2
- package/dist/cli/json-fields.js +2 -2
- package/dist/cli/meeting-batch.d.ts +1 -1
- package/dist/cli/meeting-batch.js +20 -2
- package/dist/cli/meeting-project-candidates-command.js +0 -1
- package/dist/cli/meeting-results.d.ts +3 -0
- package/dist/cli/meeting-results.js +31 -0
- package/dist/cli/meeting-series-inventory-command.js +0 -1
- package/dist/cli/messenger/admin-commands.js +14 -14
- package/dist/cli/messenger/archive-commands.js +2 -2
- package/dist/cli/messenger/attachments-command.js +7 -8
- package/dist/cli/messenger/backfill-command.js +1 -1
- package/dist/cli/messenger/chat-answers.js +3 -3
- package/dist/cli/messenger/chat-lists.js +3 -3
- package/dist/cli/messenger/chats-command.js +8 -8
- package/dist/cli/messenger/chats-members-command.js +1 -1
- package/dist/cli/messenger/contacts-command.js +10 -7
- package/dist/cli/messenger/context.d.ts +11 -4
- package/dist/cli/messenger/context.js +6 -0
- package/dist/cli/messenger/conversation-examples.js +7 -6
- package/dist/cli/messenger/conversations-command.d.ts +0 -4
- package/dist/cli/messenger/conversations-command.js +130 -135
- package/dist/cli/messenger/counters-command.js +4 -2
- package/dist/cli/messenger/doctor-command.js +8 -4
- package/dist/cli/messenger/gaps-command.js +2 -2
- 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 -1
- package/dist/cli/messenger/inbox.js +1 -3
- package/dist/cli/messenger/lacks.d.ts +1 -0
- package/dist/cli/messenger/lacks.js +1 -1
- package/dist/cli/messenger/mcp-command.js +4 -4
- package/dist/cli/messenger/messages-comments-command.js +10 -5
- package/dist/cli/messenger/metadata-command.js +5 -5
- package/dist/cli/messenger/models-command.js +101 -90
- package/dist/cli/messenger/private-people-command.js +5 -6
- package/dist/cli/messenger/replies-edit-command.js +0 -1
- package/dist/cli/messenger/review.js +1 -3
- package/dist/cli/messenger/serve-relay.d.ts +1 -0
- package/dist/cli/messenger/stats-command.js +1 -1
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/messenger/store-maintenance-command.js +4 -4
- package/dist/cli/messenger/stored.js +5 -0
- package/dist/cli/messenger/tags-command.js +4 -10
- package/dist/cli/messenger/tasks-command.js +3 -3
- package/dist/cli/messenger/transcribe-command.js +1 -1
- package/dist/cli/moved.d.ts +2 -0
- package/dist/cli/moved.js +39 -1
- package/dist/cli/permission-keys.js +2 -0
- package/dist/cli/result-fields.js +19 -1
- package/dist/cli/settings.js +1 -1
- package/dist/cli/steps.js +4 -4
- package/dist/cli/store-settings.js +1 -1
- package/dist/cli/upgrade-command.js +0 -1
- package/dist/domain/models.d.ts +3 -3
- package/dist/domain/task-categories.js +1 -1
- package/dist/embeddings/remote.js +1 -1
- package/dist/entities/contact.d.ts +6 -0
- package/dist/entities/contact.js +3 -0
- package/dist/entities/index.d.ts +139 -0
- package/dist/entities/index.js +4 -1
- package/dist/entities/member.d.ts +2 -2
- package/dist/entities/member.js +2 -2
- package/dist/entities/store-records.d.ts +11 -0
- package/dist/entities/store-records.js +1 -0
- package/dist/mcp/agent.d.ts +1 -0
- package/dist/mcp/agent.js +1 -1
- package/dist/mcp/tools/attachments.js +1 -1
- package/dist/meetings/cli/index.js +10 -3
- package/dist/meetings/index.d.ts +1 -0
- package/dist/meetings/index.js +1 -0
- package/dist/meetings/result-items.d.ts +127 -0
- package/dist/meetings/result-items.js +125 -0
- package/dist/ports/app.d.ts +1 -1
- package/dist/ports/messenger.d.ts +6 -1
- package/dist/search/task-similarity.js +1 -1
- package/dist/sends/guard.js +2 -2
- package/dist/sends/permission-aliases.d.ts +5 -0
- package/dist/sends/permission-aliases.js +49 -0
- package/dist/sends/permissions.js +33 -25
- package/dist/services/admin.js +7 -7
- package/dist/services/chats.js +1 -1
- package/dist/services/conversations.d.ts +1 -1
- package/dist/services/conversations.js +1 -1
- package/dist/services/counters.js +1 -1
- package/dist/services/embeddings-maintenance.js +2 -2
- package/dist/services/embeddings-search.js +1 -1
- package/dist/services/embeddings.d.ts +4 -4
- package/dist/services/messages-search.d.ts +1 -1
- package/dist/services/messages-search.js +2 -2
- package/dist/services/metadata.js +2 -2
- package/dist/services/notes-search.js +3 -3
- package/dist/services/search-catchup.js +1 -1
- package/dist/speech/install.d.ts +4 -2
- package/dist/speech/install.js +16 -4
- package/dist/speech/local.js +1 -1
- package/dist/speech/transcribe.js +1 -1
- package/dist/store/search-index.d.ts +1 -1
- package/dist/store/sqlite/attachment-texts.d.ts +1 -1
- package/dist/store/sqlite/attachment-texts.js +1 -1
- package/dist/store/sqlite/batches.js +1 -1
- package/dist/store/sqlite/involvements.d.ts +1 -1
- package/dist/store/sqlite/note-index.d.ts +2 -2
- package/dist/store/sqlite/note-index.js +2 -2
- package/dist/store/sqlite/search-index.d.ts +1 -1
- package/dist/store/sqlite/search-index.js +1 -1
- package/dist/store/sqlite/stems-fill.d.ts +3 -3
- package/dist/store/sqlite/stems-fill.js +3 -3
- package/dist/store/sqlite/stems.d.ts +1 -1
- package/dist/store/sqlite/task-pairs.d.ts +1 -1
- package/dist/store/sqlite/task-pairs.js +1 -1
- package/package.json +1 -1
- package/parity.json +130 -139
- package/skills/follow-ups/SKILL.md +5 -5
- package/skills/link-conversations/SKILL.md +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,42 @@ Notable changes to `@wirecat/cli-core` (`@wirecat/cli-messaging` up to 0.261.0,
|
|
|
5
5
|
minor version may break callers, and says how under "Changed — may break callers". `pnpm docs:check` checks the
|
|
6
6
|
shape of this file.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## 0.407.0 — 24.10.2026
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- The `contact` entity has optional `email` and `phones` (number and label), for a source that knows them, such as zm's Zoom contacts.
|
|
13
|
+
|
|
14
|
+
- Command discovery projections preserve the CLI document and command identities while selecting fields inside its command tree.
|
|
15
|
+
|
|
16
|
+
- Portable ingestion, export, association, transcription and embedding receipts have shared entities and `meetingResultItem` serializers. Public IDs are strings; stored numeric IDs remain internal.
|
|
17
|
+
|
|
18
|
+
- Meeting batch results declare their correlated success/error schemas. `answerEntity` can name a separate typed projection payload, preserving batch field selection inside each answer without weakening its outer result contract.
|
|
19
|
+
|
|
20
|
+
## 0.406.0 — 24.10.2026
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `StoredMessages.threadMessages` lets an adapter read a provider thread from the shared message store without
|
|
25
|
+
keeping another copy. `HistoryBatch.deletions` applies chat-scoped tombstones from synced snapshots without
|
|
26
|
+
replaying those deletions as live events. `Messenger.readsComments` allows comment reads independently of
|
|
27
|
+
comment sending; unset, it keeps the existing capability behavior.
|
|
28
|
+
- Speech model installation can verify existing files before reusing them (`verifyExisting`), so repair uses the shared checksum and download path.
|
|
29
|
+
- Provider adapters can declare a typed answer with `answerEntity`, shared by command schemas, help and JSON field validation without changing a shared entity.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Finite meeting inventory, project scanning and upgrade commands are available to the shared MCP catalogue. Profile permissions still apply; upgrade retains its authority grant.
|
|
34
|
+
|
|
35
|
+
### Changed — may break callers
|
|
36
|
+
|
|
37
|
+
- **Only canonical option spellings are accepted.** The hidden flag aliases introduced in 0.399.0 are removed: use the analysis/embedding/consent provider flags, `--claim`, `--answer-model`, `--template-mode`, `--text-file`, `--disappear-after` and the `kind:` query term. Retired flags are refused before command work.
|
|
38
|
+
|
|
39
|
+
- **Shared command paths use the vocabulary.** Contacts use `info`, `events` and `aliases remove`; chat invite links use `links remove`, member checks use `check`, and join requests use `confirm` or `reject`. Metadata uses `show` and `sync`; task edits use `update`; derived tags and search indexes use `rebuild`. Discovery uses `commands info`; MCP configuration uses `mcp add` and `mcp check`.
|
|
40
|
+
|
|
41
|
+
- **Explicit model and conversation commands.** Use `models list kind:audio` or `kind:text`, `models download <model>` and `models keys set/remove`. Conversation link construction is `conversations links rebuild`; vector reports and removal are `conversations embeddings status/clear`, while `conversations embed` still computes vectors. Duplicate candidates are `tasks duplicates list`. Report information is `doctor reports show`; `doctor reports create` writes the report. Bare groups only offer help. Retired spellings are refused with guidance to the canonical path; no compatibility command aliases are mounted. CLI and MCP use the same paths.
|
|
42
|
+
|
|
43
|
+
- **Rename moved permission paths.** A saved key or startup override using a renamed path now stops with `configuration_error` and its exact replacement (including bot keys), before opening the store or performing the action. Canonical commands keep the migrated denial; retired CLI spellings cannot run.
|
|
9
44
|
|
|
10
45
|
## 0.405.0 — 24.10.2026
|
|
11
46
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** What `chats members
|
|
1
|
+
/** What `chats members check` judges from a member list and the store. */
|
|
2
2
|
export type AuditReason = "bot" | "scam" | "fake" | "deleted" | "no_photo" | "no_username" | "odd_name" | "never_wrote" | "link_first" | "burst_join" | "mass_invited";
|
|
3
3
|
/** What only a look at one person adds: their profile, all their stored messages, the registries. */
|
|
4
4
|
export type PersonReason = "new_account" | "no_bio" | "same_text" | "photo_recent" | RegistryReason;
|
|
@@ -35,6 +35,6 @@ export const analysisChoice = (options, app, settings, env, keyring) => {
|
|
|
35
35
|
const keyName = customUrl === undefined ? provider : endpointKeyName(baseUrl);
|
|
36
36
|
const apiKey = embeddingKeys(app, env, keyring).read(keyName)?.key;
|
|
37
37
|
if (!apiKey && customUrl === undefined)
|
|
38
|
-
throw new CliError("authentication_error", `no ${provider} key — use models
|
|
38
|
+
throw new CliError("authentication_error", `no ${provider} key — use models keys set ${provider}`);
|
|
39
39
|
return { provider, model, baseUrl, ...(apiKey ? { apiKey } : {}) };
|
|
40
40
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type * as v from "valibot";
|
|
3
|
+
/** Provider-specific wire fields must not redefine an entity shared by every CLI. */
|
|
4
|
+
export declare const answerEntity: (command: Command, name: string, schema: v.GenericSchema, options?: {
|
|
5
|
+
project?: v.GenericSchema;
|
|
6
|
+
}) => Command;
|
|
7
|
+
export declare const answerEntitySchema: (command: Command | undefined) => v.GenericSchema | undefined;
|
|
8
|
+
export declare const answerProjectionSchema: (command: Command | undefined) => v.GenericSchema | undefined;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { annotate, metaOf } from "@wirecat/cli-base/commands";
|
|
2
|
+
import { ENTITIES } from "../entities/index.js";
|
|
3
|
+
const schemas = new WeakMap();
|
|
4
|
+
/** Provider-specific wire fields must not redefine an entity shared by every CLI. */
|
|
5
|
+
export const answerEntity = (command, name, schema, options = {}) => {
|
|
6
|
+
if (Object.hasOwn(ENTITIES, name))
|
|
7
|
+
throw new Error(`${name} is a shared entity; use its existing schema`);
|
|
8
|
+
if (!/^[a-z][a-z0-9_]*$/.test(name))
|
|
9
|
+
throw new Error("an answer entity needs a lowercase name");
|
|
10
|
+
if (!("entries" in schema) && schema.type !== "union")
|
|
11
|
+
throw new Error("an answer entity needs an object schema or a union of object schemas");
|
|
12
|
+
if (options.project && !("entries" in options.project) && options.project.type !== "union")
|
|
13
|
+
throw new Error("projection needs an object schema or a union of object schemas");
|
|
14
|
+
schemas.set(command, { name, schema, ...options });
|
|
15
|
+
return annotate(command, { output: { entity: name } });
|
|
16
|
+
};
|
|
17
|
+
export const answerEntitySchema = (command) => {
|
|
18
|
+
const output = command && metaOf(command).output;
|
|
19
|
+
if (!output)
|
|
20
|
+
return undefined;
|
|
21
|
+
const name = output.view ? `${output.entity}.${output.view}` : output.entity;
|
|
22
|
+
const shared = ENTITIES[name];
|
|
23
|
+
if (shared)
|
|
24
|
+
return shared;
|
|
25
|
+
const own = schemas.get(command);
|
|
26
|
+
return own?.name === name ? own.schema : undefined;
|
|
27
|
+
};
|
|
28
|
+
export const answerProjectionSchema = (command) => {
|
|
29
|
+
const own = command && schemas.get(command);
|
|
30
|
+
return own && metaOf(command).output?.entity === own.name ? own.project : undefined;
|
|
31
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { describeOptions, metaOf } from "@wirecat/cli-base/commands";
|
|
3
3
|
import { jsonSchemaOf } from "@wirecat/cli-base/standards";
|
|
4
|
-
import { ENTITIES } from "../entities/index.js";
|
|
5
4
|
import { keyForCommand } from "../sends/permissions.js";
|
|
5
|
+
import { answerEntitySchema, answerProjectionSchema } from "./answer-entity.js";
|
|
6
6
|
import { answerSchema } from "./envelope.js";
|
|
7
7
|
export const SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
|
|
8
8
|
/**
|
|
@@ -10,10 +10,7 @@ export const SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
|
|
|
10
10
|
* A command that declares none answers the same envelopes with items of any shape; `--jsonl` streams the items.
|
|
11
11
|
*/
|
|
12
12
|
export const outputOf = (command) => {
|
|
13
|
-
const
|
|
14
|
-
const entity = output
|
|
15
|
-
? ENTITIES[(output.view ? `${output.entity}.${output.view}` : output.entity)]
|
|
16
|
-
: undefined;
|
|
13
|
+
const entity = answerEntitySchema(command);
|
|
17
14
|
const { $schema: _, ...schema } = jsonSchemaOf(answerSchema(entity));
|
|
18
15
|
const { $schema: __, ...item } = (entity ? jsonSchemaOf(entity) : {});
|
|
19
16
|
const coverage = entity ? "declared-entity" : "envelope-with-open-items";
|
|
@@ -100,7 +97,9 @@ export const commandContract = (command) => {
|
|
|
100
97
|
outputSchemaCoverage: output.coverage,
|
|
101
98
|
jsonlSchema: { $schema: SCHEMA_DIALECT, ...output.item },
|
|
102
99
|
jsonlSchemaCoverage: output.coverage,
|
|
103
|
-
projection:
|
|
100
|
+
projection: answerProjectionSchema(command)
|
|
101
|
+
? "--json=<fields> selects inside each nested answer; correlation and envelopes are preserved"
|
|
102
|
+
: "--json=<fields> may omit item/object members; present members retain their types and envelopes are preserved",
|
|
104
103
|
validation: {
|
|
105
104
|
syntax: "declared",
|
|
106
105
|
semantic: "command-and-provider-validation",
|
|
@@ -50,7 +50,10 @@ export const commandsCommand = (app) => {
|
|
|
50
50
|
exit_codes: { ok: 0, [CRASH_CODE]: GENERIC_FAILURE, ...EXIT_CODES },
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
|
-
command.addCommand(annotate(new Command("
|
|
53
|
+
command.addCommand(annotate(new Command("info"), {
|
|
54
|
+
effects: NO_EFFECTS,
|
|
55
|
+
examples: [`${app.command} commands info messages list`],
|
|
56
|
+
})
|
|
54
57
|
.description("one command's argv and result schemas, effects, permissions and retry guidance")
|
|
55
58
|
.argument("<path...>", "one command path, for example: stats messages show")
|
|
56
59
|
.action(function (path) {
|
package/dist/cli/effects.js
CHANGED
|
@@ -124,7 +124,7 @@ export const ownerOnlyOption = (flags, description) => annotateOption(new Option
|
|
|
124
124
|
export const judgedEffects = (effects) => effects && { remote: effects.remote, local: "none" };
|
|
125
125
|
/**
|
|
126
126
|
* An unasked step is judged stricter than a retry: only a fetch's local write is incidental. A command that reads
|
|
127
|
-
* nothing remotely and writes here (`server restart`, `store
|
|
127
|
+
* nothing remotely and writes here (`server restart`, `store rebuild`) is the whole point of the step, so it waits
|
|
128
128
|
* to be asked (RISK-1211).
|
|
129
129
|
*/
|
|
130
130
|
const judgedStepEffects = (effects) => effects?.remote === "none" ? effects : judgedEffects(effects);
|
|
@@ -10,7 +10,7 @@ export interface ModelOptions {
|
|
|
10
10
|
dims?: number;
|
|
11
11
|
concurrency?: number;
|
|
12
12
|
}
|
|
13
|
-
/** A local model id, or a remote model with its key from `models
|
|
13
|
+
/** A local model id, or a remote model with its key from `models keys set`. */
|
|
14
14
|
export declare const embeddingChoice: ({ model, provider, embeddingProvider, baseUrl, dims, concurrency }: ModelOptions, app: AppIdentity, settings: AISettings, env: NodeJS.ProcessEnv, { needKey, keyring }?: {
|
|
15
15
|
needKey?: boolean;
|
|
16
16
|
keyring?: KeyringStore | undefined;
|
|
@@ -5,7 +5,7 @@ import { DEFAULT_TEXT_MODEL } from "../embeddings/models.js";
|
|
|
5
5
|
import { isLocal, remoteModel } from "../embeddings/remote.js";
|
|
6
6
|
import { readOnlyLockOf, readOnlyRefusal } from "../ports/app.js";
|
|
7
7
|
import { typedCommand } from "../runs/scope.js";
|
|
8
|
-
/** A local model id, or a remote model with its key from `models
|
|
8
|
+
/** A local model id, or a remote model with its key from `models keys set`. */
|
|
9
9
|
export const embeddingChoice = ({ model, provider, embeddingProvider, baseUrl, dims, concurrency }, app, settings, env, { needKey = true, keyring } = {}) => {
|
|
10
10
|
if (embeddingProvider !== undefined && provider !== undefined)
|
|
11
11
|
throw new CliError("validation_error", "give --embedding-provider or its legacy --provider spelling, not both");
|
|
@@ -34,7 +34,7 @@ export const embeddingChoice = ({ model, provider, embeddingProvider, baseUrl, d
|
|
|
34
34
|
const keyName = baseUrl === undefined ? "openai" : endpointKeyName(baseUrl);
|
|
35
35
|
const key = embeddingKeys(app, env, keyring).read(keyName)?.key;
|
|
36
36
|
if (!key && needKey && baseUrl === undefined) {
|
|
37
|
-
throw new CliError("authentication_error", `no OpenAI key — \`${typedCommand(app.command, "models
|
|
37
|
+
throw new CliError("authentication_error", `no OpenAI key — \`${typedCommand(app.command, "models keys set openai")}\`, or OPENAI_API_KEY`);
|
|
38
38
|
}
|
|
39
39
|
return { remote, ...(key ? { apiKey: key } : {}), ...(concurrency ? { concurrency } : {}) };
|
|
40
40
|
};
|
|
@@ -112,8 +112,8 @@ const returnsOf = (command) => {
|
|
|
112
112
|
const noun = (output.view ? `${output.entity} ${output.view}` : output.entity).replaceAll("_", " ");
|
|
113
113
|
const more = fields.length > 8 ? `, and ${fields.length - 8} more` : "";
|
|
114
114
|
const root = rootOf(command);
|
|
115
|
-
const schema = commandAt(root, "commands
|
|
116
|
-
? `; every field: ${root.name()} commands
|
|
115
|
+
const schema = commandAt(root, "commands info")
|
|
116
|
+
? `; every field: ${root.name()} commands info ${commandPathOf(command).join(" ")}`
|
|
117
117
|
: "";
|
|
118
118
|
return `${noun} — ${fields.slice(0, 8).join(", ")}${more}${schema}`;
|
|
119
119
|
};
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { AI_ENTRIES, AI_SETTING_KEYS, type AISettings, resolveAISettings } from "../analysis/settings.js";
|
|
2
2
|
export { parseDuration } from "../domain/duration.js";
|
|
3
|
+
export { syncProgress } from "../entities/store-records.js";
|
|
3
4
|
export { isCliFailure, isCommanderFailure } from "../errors/failures.js";
|
|
4
5
|
export { type AppErrors, failureContext } from "../errors/reasons.js";
|
|
5
6
|
export { botInstructions } from "../mcp/bot/instructions.js";
|
|
@@ -10,6 +11,7 @@ export { callMeetingProjectCandidatesTool, meetingProjectCandidatesTool } from "
|
|
|
10
11
|
export { callMeetingSeriesInventoryTool, meetingSeriesInventoryTool } from "../mcp/meeting-series-inventory.js";
|
|
11
12
|
export { registerLinkConversationsPrompt } from "../mcp/prompts.js";
|
|
12
13
|
export { agentBody, agentJson, agentResult, UNTRUSTED, UNTRUSTED_INSTRUCTION } from "../mcp/text.js";
|
|
14
|
+
export { MEETING_RESULT_ENTITIES } from "../meetings/index.js";
|
|
13
15
|
export { type AppIdentity, envName, readOnlyLockOf, readOnlyRefusal } from "../ports/app.js";
|
|
14
16
|
export type { AccountEditing, AccountHealth, AccountRecords, AccountSettings, AccountStanding, AccountTools, After, BotChats, ChannelComments, ChatDeletion, ChatFolders, ChatReading, ContactBook, Download, ForumControl, ForumState, GroupAdmin, GroupModeration, HistoryBatch, HistoryChatEvent, HistoryReaction, HistoryStar, HistoryVote, InviteLinks, JoinRequests, LiveUpdates, MessageButtons, MessageEditing, MessageMedia, MessagePermalinks, MessagePins, MessagePolls, MessageReactions, MessageSearch, MessageStars, MessengerAdapter, MessengerCore, NewPoll, OfficialStats, PassiveUpdates, PersonProfiles, ProfileChange, ProfilePhotos, PushedHistory, ReadState, RemoteFile, ScheduledMessages, SenderIdentities, SenderSearch, SendOptions, Sent, ServerQuery, ServerReads, ThreadAddressing, TopicEditing, TopicHistory, TopicReadState, Transcript, } from "../ports/messenger.js";
|
|
15
17
|
export type { Fetching, MediaOption, MessengerTraits } from "../ports/traits.js";
|
|
@@ -33,6 +35,7 @@ export { unanswered } from "../services/questions.js";
|
|
|
33
35
|
export { openRequestTask } from "../services/task-rules.js";
|
|
34
36
|
export { TASK_PAIR_QUERY, TASK_QUERY } from "../services/tasks.js";
|
|
35
37
|
export { type AgentPolicy, type AgentTask, type EvaluationResult, evaluateAgent, type Observation, } from "./agent-evaluation.js";
|
|
38
|
+
export { answerEntity } from "./answer-entity.js";
|
|
36
39
|
export { botAdminsCommand, botMembersCommand } from "./bot/admins.js";
|
|
37
40
|
export { type ApiCommandInput, type ApiCommands, generatedApiCommand } from "./bot/api.js";
|
|
38
41
|
export { apiFlagOf, apiJson, apiOptionKey, apiPlainJson, checkApiBody, checkApiParameter, parseApiJson, readApiBody, } from "./bot/api-input.js";
|
|
@@ -53,8 +56,8 @@ export { loadSnakeCaseConfig } from "./config-keys.js";
|
|
|
53
56
|
export { type AgentRun, type BaseContext, type BaseEnvironment, baseContext, environmentOf, outputFor, provide, secretInputOf, } from "./context.js";
|
|
54
57
|
export { type Closeable, withDeadline } from "./deadline.js";
|
|
55
58
|
export { DEFAULT_CONFIG, ensureDefaultConfig } from "./default-config.js";
|
|
56
|
-
export { changesAuthority, changesAuthorityAt, destroysNothing, FETCH, grantsAuthority, isLogin, isOtherServiceCall, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, REMOTE_READ, REMOTE_WRITE, reachesOtherService, refuseUnderReadOnly, } from "./effects.js";
|
|
57
|
-
export { type AnswerOutput, answerSchema, type Body, type ItemBody, itemAnswer, itemOf, jsonlRecords, judgedAnswer, type ListBody, type ListInput, listOf, metaNow, printItem, renderAnswer, sealed, snakeKeys, snakeKeysKeeping, } from "./envelope.js";
|
|
59
|
+
export { changesAuthority, changesAuthorityAt, changesAuthorityNow, destroysNothing, FETCH, grantsAuthority, isLogin, isOtherServiceCall, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, REMOTE_READ, REMOTE_WRITE, reachesOtherService, refuseUnderReadOnly, } from "./effects.js";
|
|
60
|
+
export { type AnswerOutput, answerSchema, type Body, type ItemBody, isBody, itemAnswer, itemOf, jsonlRecords, judgedAnswer, type ListBody, type ListInput, listOf, metaNow, printItem, renderAnswer, sealed, snakeKeys, snakeKeysKeeping, } from "./envelope.js";
|
|
58
61
|
export { withAbort } from "./execution.js";
|
|
59
62
|
export { askSetupQuestions, asksAtStart, type FirstRun, type FirstRunIo, LANGUAGES, setupAtStart, systemLanguage, } from "./first-run.js";
|
|
60
63
|
export { checkGuide, checkStep, type GuideOptions, type GuideReference, type GuideStep, guideCommand, loadScenarios, MEMO_SCENARIOS, type Scenario, shellProblems, } from "./guide.js";
|
|
@@ -73,6 +76,7 @@ export { addMeetingPreparationCommand } from "./meeting-preparation-command.js";
|
|
|
73
76
|
export { type MeetingPreparationReader, meetingPreparationInput, readMeetingPreparation, } from "./meeting-preparation-read.js";
|
|
74
77
|
export { addMeetingProjectCandidatesCommand } from "./meeting-project-candidates-command.js";
|
|
75
78
|
export { readMeetingProjectCandidates } from "./meeting-project-candidates-read.js";
|
|
79
|
+
export { meetingResultItem } from "./meeting-results.js";
|
|
76
80
|
export { addMeetingSeriesInventoryCommand } from "./meeting-series-inventory-command.js";
|
|
77
81
|
export { type MeetingSeriesInventoryReader, readMeetingSeriesInventory } from "./meeting-series-inventory-read.js";
|
|
78
82
|
export { accountCommand } from "./messenger/account-command.js";
|
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { AI_ENTRIES, AI_SETTING_KEYS, resolveAISettings } from "../analysis/settings.js";
|
|
2
2
|
export { parseDuration } from "../domain/duration.js";
|
|
3
|
+
export { syncProgress } from "../entities/store-records.js";
|
|
3
4
|
export { isCliFailure, isCommanderFailure } from "../errors/failures.js";
|
|
4
5
|
export { failureContext } from "../errors/reasons.js";
|
|
5
6
|
export { botInstructions } from "../mcp/bot/instructions.js";
|
|
@@ -8,6 +9,7 @@ export { callMeetingProjectCandidatesTool, meetingProjectCandidatesTool } from "
|
|
|
8
9
|
export { callMeetingSeriesInventoryTool, meetingSeriesInventoryTool } from "../mcp/meeting-series-inventory.js";
|
|
9
10
|
export { registerLinkConversationsPrompt } from "../mcp/prompts.js";
|
|
10
11
|
export { agentBody, agentJson, agentResult, UNTRUSTED, UNTRUSTED_INSTRUCTION } from "../mcp/text.js";
|
|
12
|
+
export { MEETING_RESULT_ENTITIES } from "../meetings/index.js";
|
|
11
13
|
export { envName, readOnlyLockOf, readOnlyRefusal } from "../ports/app.js";
|
|
12
14
|
export { senderFacts } from "../replies/dry-run.js";
|
|
13
15
|
export { replyRenderer } from "../replies/rendering.js";
|
|
@@ -28,6 +30,7 @@ export { unanswered } from "../services/questions.js";
|
|
|
28
30
|
export { openRequestTask } from "../services/task-rules.js";
|
|
29
31
|
export { TASK_PAIR_QUERY, TASK_QUERY } from "../services/tasks.js";
|
|
30
32
|
export { evaluateAgent, } from "./agent-evaluation.js";
|
|
33
|
+
export { answerEntity } from "./answer-entity.js";
|
|
31
34
|
export { botAdminsCommand, botMembersCommand } from "./bot/admins.js";
|
|
32
35
|
export { generatedApiCommand } from "./bot/api.js";
|
|
33
36
|
export { apiFlagOf, apiJson, apiOptionKey, apiPlainJson, checkApiBody, checkApiParameter, parseApiJson, readApiBody, } from "./bot/api-input.js";
|
|
@@ -48,8 +51,8 @@ export { loadSnakeCaseConfig } from "./config-keys.js";
|
|
|
48
51
|
export { baseContext, environmentOf, outputFor, provide, secretInputOf, } from "./context.js";
|
|
49
52
|
export { withDeadline } from "./deadline.js";
|
|
50
53
|
export { DEFAULT_CONFIG, ensureDefaultConfig } from "./default-config.js";
|
|
51
|
-
export { changesAuthority, changesAuthorityAt, destroysNothing, FETCH, grantsAuthority, isLogin, isOtherServiceCall, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, REMOTE_READ, REMOTE_WRITE, reachesOtherService, refuseUnderReadOnly, } from "./effects.js";
|
|
52
|
-
export { answerSchema, itemAnswer, itemOf, jsonlRecords, judgedAnswer, listOf, metaNow, printItem, renderAnswer, sealed, snakeKeys, snakeKeysKeeping, } from "./envelope.js";
|
|
54
|
+
export { changesAuthority, changesAuthorityAt, changesAuthorityNow, destroysNothing, FETCH, grantsAuthority, isLogin, isOtherServiceCall, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, REMOTE_READ, REMOTE_WRITE, reachesOtherService, refuseUnderReadOnly, } from "./effects.js";
|
|
55
|
+
export { answerSchema, isBody, itemAnswer, itemOf, jsonlRecords, judgedAnswer, listOf, metaNow, printItem, renderAnswer, sealed, snakeKeys, snakeKeysKeeping, } from "./envelope.js";
|
|
53
56
|
export { withAbort } from "./execution.js";
|
|
54
57
|
export { askSetupQuestions, asksAtStart, LANGUAGES, setupAtStart, systemLanguage, } from "./first-run.js";
|
|
55
58
|
export { checkGuide, checkStep, guideCommand, loadScenarios, MEMO_SCENARIOS, shellProblems, } from "./guide.js";
|
|
@@ -68,6 +71,7 @@ export { addMeetingPreparationCommand } from "./meeting-preparation-command.js";
|
|
|
68
71
|
export { meetingPreparationInput, readMeetingPreparation, } from "./meeting-preparation-read.js";
|
|
69
72
|
export { addMeetingProjectCandidatesCommand } from "./meeting-project-candidates-command.js";
|
|
70
73
|
export { readMeetingProjectCandidates } from "./meeting-project-candidates-read.js";
|
|
74
|
+
export { meetingResultItem } from "./meeting-results.js";
|
|
71
75
|
export { addMeetingSeriesInventoryCommand } from "./meeting-series-inventory-command.js";
|
|
72
76
|
export { readMeetingSeriesInventory } from "./meeting-series-inventory-read.js";
|
|
73
77
|
export { accountCommand } from "./messenger/account-command.js";
|
package/dist/cli/json-fields.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { metaOf } from "@wirecat/cli-base/commands";
|
|
3
3
|
import { ENTITIES } from "../entities/index.js";
|
|
4
|
+
import { answerEntitySchema, answerProjectionSchema } from "./answer-entity.js";
|
|
4
5
|
const declaredEntity = (command) => {
|
|
5
6
|
const output = command ? metaOf(command).output : undefined;
|
|
6
7
|
return output && (output.view ? `${output.entity}.${output.view}` : output.entity);
|
|
@@ -37,8 +38,7 @@ export const answerFields = (command, resolve) => {
|
|
|
37
38
|
const own = resolve?.(command);
|
|
38
39
|
if (own !== undefined)
|
|
39
40
|
return [...own];
|
|
40
|
-
const
|
|
41
|
-
const schema = name === undefined ? undefined : ENTITIES[name];
|
|
41
|
+
const schema = answerProjectionSchema(command) ?? answerEntitySchema(command);
|
|
42
42
|
return schemaFields(schema);
|
|
43
43
|
};
|
|
44
44
|
const PATHS = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*(,[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*)*$/;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type BatchReport } from "@wirecat/cli-base";
|
|
2
|
-
import type
|
|
2
|
+
import { type Meta } from "@wirecat/cli-base/standards";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { type MeetingBatchReader, type MeetingPassageOutputFormat } from "../meetings/index.js";
|
|
5
5
|
import { type Body } from "./envelope.js";
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { BATCH_LIMITS, CliError, prepareBatch, runBatch, } from "@wirecat/cli-base";
|
|
2
2
|
import { annotate } from "@wirecat/cli-base/commands";
|
|
3
|
+
import { errorObjectSchema } from "@wirecat/cli-base/standards";
|
|
3
4
|
import { Command, Option } from "commander";
|
|
5
|
+
import * as v from "valibot";
|
|
6
|
+
import { ENTITIES } from "../entities/index.js";
|
|
4
7
|
import { failureContext } from "../errors/reasons.js";
|
|
5
8
|
import { createMeetingPassageCommand, createMeetingSearchCommand, meetingHitSearchRequest, meetingPassageRequest, meetingSearchArguments, meetingSearchMeta, } from "../meetings/cli/index.js";
|
|
6
9
|
import { meetingHitsList, parseMeetingReference, } from "../meetings/index.js";
|
|
7
10
|
import { formatMeetingEvidenceText, formatMeetingPassage } from "../services/meeting-passage-format.js";
|
|
8
|
-
import {
|
|
11
|
+
import { answerEntity } from "./answer-entity.js";
|
|
12
|
+
import { destroysNothing } from "./effects.js";
|
|
13
|
+
import { answerSchema, itemOf, listOf } from "./envelope.js";
|
|
9
14
|
const INDEX_BYTES = 4194304;
|
|
10
15
|
const parse = (command, args) => {
|
|
11
16
|
command
|
|
@@ -162,10 +167,23 @@ export const addMeetingBatchCommand = (program, deps) => {
|
|
|
162
167
|
},
|
|
163
168
|
}), report, format);
|
|
164
169
|
});
|
|
165
|
-
|
|
170
|
+
destroysNothing(command);
|
|
171
|
+
annotate(command, {
|
|
166
172
|
origin: "handwritten",
|
|
167
173
|
partial: true,
|
|
168
174
|
effects: { remote: "none", local: "write" },
|
|
169
175
|
examples: [`${program.name()} batch requests.json --json`],
|
|
170
176
|
});
|
|
177
|
+
return answerEntity(command, "meeting_batch_result", batchResult, { project: batchPayload });
|
|
171
178
|
};
|
|
179
|
+
const batchPayload = v.union([ENTITIES.meeting_hit, ENTITIES.meeting_passage]);
|
|
180
|
+
const correlated = { id: v.string(), command: v.array(v.string()) };
|
|
181
|
+
const batchResult = v.union([
|
|
182
|
+
v.strictObject({ ...correlated, status: v.literal("ok"), answer: answerSchema(batchPayload), complete: v.boolean() }),
|
|
183
|
+
v.strictObject({
|
|
184
|
+
...correlated,
|
|
185
|
+
status: v.picklist(["error", "not_run"]),
|
|
186
|
+
error: errorObjectSchema.entries.error,
|
|
187
|
+
complete: v.literal(false),
|
|
188
|
+
}),
|
|
189
|
+
]);
|
|
@@ -31,7 +31,6 @@ export const addMeetingProjectCandidatesCommand = (program, deps) => {
|
|
|
31
31
|
cursor: options.cursor,
|
|
32
32
|
}, deps.signal()))), {
|
|
33
33
|
origin: "handwritten",
|
|
34
|
-
mcp: false,
|
|
35
34
|
effects: LOCAL_READ,
|
|
36
35
|
output: { entity: "meeting_project_candidates" },
|
|
37
36
|
examples: [`${program.name()} meetings projects scan meeting:1/2 --json`],
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { MEETING_RESULT_ENTITIES } from "../meetings/index.js";
|
|
2
|
+
/** Store IDs stay numeric below the CLI; public receipts use the shared string IDs and validated wire fields. */
|
|
3
|
+
export declare const meetingResultItem: (entity: keyof typeof MEETING_RESULT_ENTITIES, value: unknown) => unknown;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { MEETING_RESULT_ENTITIES } from "../meetings/index.js";
|
|
4
|
+
import { snakeKeys } from "./envelope.js";
|
|
5
|
+
const ids = new Set([
|
|
6
|
+
"meeting_id",
|
|
7
|
+
"account_id",
|
|
8
|
+
"participant_id",
|
|
9
|
+
"event_id",
|
|
10
|
+
"previous_event_id",
|
|
11
|
+
"expected_event_id",
|
|
12
|
+
"next_transcript_id",
|
|
13
|
+
]);
|
|
14
|
+
const publicValue = (value, key = "") => {
|
|
15
|
+
if (typeof value === "number" && ids.has(key))
|
|
16
|
+
return String(value);
|
|
17
|
+
if (Array.isArray(value))
|
|
18
|
+
return value.map((item) => publicValue(item, key === "target_account_ids" ? "account_id" : ""));
|
|
19
|
+
if (value && typeof value === "object")
|
|
20
|
+
return Object.fromEntries(Object.entries(value).map(([name, item]) => [name, publicValue(item, name)]));
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
/** Store IDs stay numeric below the CLI; public receipts use the shared string IDs and validated wire fields. */
|
|
24
|
+
export const meetingResultItem = (entity, value) => {
|
|
25
|
+
const parsed = v.safeParse(MEETING_RESULT_ENTITIES[entity], publicValue(snakeKeys(value)));
|
|
26
|
+
if (!parsed.success) {
|
|
27
|
+
const applied = value && typeof value === "object" && "applied" in value && value.applied === true;
|
|
28
|
+
throw new CliError(applied ? "outcome_unknown" : "invalid_response", `the command returned an invalid ${entity} answer`);
|
|
29
|
+
}
|
|
30
|
+
return parsed.output;
|
|
31
|
+
};
|
|
@@ -31,7 +31,6 @@ export const addMeetingSeriesInventoryCommand = (program, deps) => {
|
|
|
31
31
|
origin: "handwritten",
|
|
32
32
|
effects: REMOTE_READ,
|
|
33
33
|
offline: false,
|
|
34
|
-
mcp: false,
|
|
35
34
|
output: { entity: "meeting_series_inventory" },
|
|
36
35
|
examples: [`${program.name()} meetings scheduled --json`],
|
|
37
36
|
});
|
|
@@ -69,14 +69,8 @@ const updateCommand = (messenger) => {
|
|
|
69
69
|
update.option("--remove-photo", "take its photo away; not with --photo");
|
|
70
70
|
for (const key of keys) {
|
|
71
71
|
const option = new Option(`--${SETTING_FLAGS[key][0]}`, SETTING_FLAGS[key][1]);
|
|
72
|
-
if (key === "disappearingSeconds")
|
|
73
|
-
option.conflicts("disappearTime");
|
|
74
72
|
update.addOption(option);
|
|
75
73
|
}
|
|
76
|
-
if (keys.includes("disappearingSeconds"))
|
|
77
|
-
update.addOption(new Option("--disappear-time <duration|off>", "compatibility alias for --disappear-after")
|
|
78
|
-
.hideHelp()
|
|
79
|
-
.conflicts("disappearAfter"));
|
|
80
74
|
return update.action(async function (chat) {
|
|
81
75
|
const context = messengerContext(this, messenger);
|
|
82
76
|
const { title, description, photo, removePhoto, ...rest } = this.opts();
|
|
@@ -92,7 +86,7 @@ const updateCommand = (messenger) => {
|
|
|
92
86
|
});
|
|
93
87
|
};
|
|
94
88
|
const linkCommand = (messenger) => {
|
|
95
|
-
const link = new Command("
|
|
89
|
+
const link = new Command("links").description("a group's invite link");
|
|
96
90
|
annotate(link.command("show"), { output: { entity: "chat_invite" }, effects: REMOTE_READ })
|
|
97
91
|
.description("the invite link, if you may see it")
|
|
98
92
|
.argument("<chat>", messenger.chatArgument)
|
|
@@ -132,10 +126,13 @@ const linkCommand = (messenger) => {
|
|
|
132
126
|
].join(" ")));
|
|
133
127
|
}));
|
|
134
128
|
if (messenger.inviteLinkRevoke !== false)
|
|
135
|
-
link.addCommand(annotate(new Command("
|
|
129
|
+
link.addCommand(annotate(new Command("remove"), {
|
|
130
|
+
output: { entity: "chat_invite_change" },
|
|
131
|
+
effects: REMOTE_WRITE,
|
|
132
|
+
})
|
|
136
133
|
.description("stop one link; for the group's own link, the answer is the new one")
|
|
137
134
|
.argument("<chat>", messenger.chatArgument)
|
|
138
|
-
.argument("<link>", "the link, as `chats
|
|
135
|
+
.argument("<link>", "the link, as `chats links list` shows it")
|
|
139
136
|
.action(async function (chat, link) {
|
|
140
137
|
const context = messengerContext(this, messenger);
|
|
141
138
|
renderItem(this, context, await context.withServices((services) => services.admin.revokeLink(chat, link)));
|
|
@@ -144,7 +141,7 @@ const linkCommand = (messenger) => {
|
|
|
144
141
|
link.addCommand(annotate(new Command("update"), { output: { entity: "chat_invite_change" }, effects: REMOTE_WRITE })
|
|
145
142
|
.description("change one of your invite links, the group's own one too")
|
|
146
143
|
.argument("<chat>", messenger.chatArgument)
|
|
147
|
-
.argument("<link>", "the link, as `chats
|
|
144
|
+
.argument("<link>", "the link, as `chats links list` shows it")
|
|
148
145
|
.option("--approval", "who joins by it asks first, and an admin lets them in; it then has no use limit")
|
|
149
146
|
.option("--no-approval", "anyone with it joins at once")
|
|
150
147
|
.option("--expire-time <time>", "it stops working then: 2026-09-25T09:00 (local time), or 30m, 2h, 7d from now; `never` takes the expiry away")
|
|
@@ -219,11 +216,14 @@ const requestsCommand = (messenger) => {
|
|
|
219
216
|
}));
|
|
220
217
|
const everyone = messenger.joinRequestsAll !== false;
|
|
221
218
|
const byLink = everyone && messenger.joinRequestsByLink !== false;
|
|
222
|
-
for (const [
|
|
223
|
-
[
|
|
224
|
-
[
|
|
219
|
+
for (const [accept, help] of [
|
|
220
|
+
[true, "let them in; the group sees them join"],
|
|
221
|
+
[false, "turn the request away"],
|
|
225
222
|
]) {
|
|
226
|
-
const answer = annotate(new Command(
|
|
223
|
+
const answer = annotate(new Command(accept ? "confirm" : "reject"), {
|
|
224
|
+
output: { entity: "chat_request_change" },
|
|
225
|
+
effects: REMOTE_WRITE,
|
|
226
|
+
})
|
|
227
227
|
.description(help)
|
|
228
228
|
.argument("<chat>", messenger.chatArgument)
|
|
229
229
|
.argument(everyone ? "[person]" : "<person>", "who asked: an id from `chats requests list`");
|
|
@@ -38,7 +38,7 @@ export const storeCommand = (messenger) => {
|
|
|
38
38
|
"copies delete": "messages_copy_1",
|
|
39
39
|
decrypt: "./backup.enc --output ./restored.db",
|
|
40
40
|
export: '"Book club" --output ./messages.jsonl',
|
|
41
|
-
"gaps
|
|
41
|
+
"gaps show": '"Book club"',
|
|
42
42
|
"gaps repair": '"Book club" --limit 100',
|
|
43
43
|
info: "",
|
|
44
44
|
"jobs cancel": "job-101",
|
|
@@ -47,7 +47,7 @@ export const storeCommand = (messenger) => {
|
|
|
47
47
|
"jobs retry": "--failed",
|
|
48
48
|
"jobs show": "",
|
|
49
49
|
migrate: "",
|
|
50
|
-
|
|
50
|
+
rebuild: "",
|
|
51
51
|
repair: "--dry-run",
|
|
52
52
|
reset: "",
|
|
53
53
|
restore: "./backup.db",
|
|
@@ -27,7 +27,7 @@ const count = (value) => {
|
|
|
27
27
|
const line = ({ status, ref, attachment, name, chars }) => `${status} ${ref} #${attachment}${name ? ` ${name}` : ""}${chars === undefined ? "" : ` (${chars} characters)`}`;
|
|
28
28
|
const summary = (run) => [
|
|
29
29
|
`${run.extracted} extracted`,
|
|
30
|
-
run.needsAgent ? `${run.needsAgent} for an agent to read (attachments
|
|
30
|
+
run.needsAgent ? `${run.needsAgent} for an agent to read (attachments update)` : "",
|
|
31
31
|
run.failed ? `${run.failed} unreadable` : "",
|
|
32
32
|
run.unchanged ? `${run.unchanged} unchanged` : "",
|
|
33
33
|
run.notDownloaded ? `${run.notDownloaded} not downloaded (--download)` : "",
|
|
@@ -172,12 +172,11 @@ const showCommand = (messenger) => annotate(new Command("show"), {
|
|
|
172
172
|
stop.release();
|
|
173
173
|
}
|
|
174
174
|
});
|
|
175
|
-
const
|
|
176
|
-
const
|
|
177
|
-
readsStdin(annotate(text.command("set"), {
|
|
175
|
+
const textUpdateCommand = (messenger) => {
|
|
176
|
+
const update = readsStdin(annotate(new Command("update"), {
|
|
178
177
|
output: { entity: "attachment_text_change" },
|
|
179
178
|
effects: LOCAL_WRITE,
|
|
180
|
-
examples: [`${messenger.app.command} personal attachments
|
|
179
|
+
examples: [`${messenger.app.command} personal attachments update "Book club" 101 --text-file ./transcript.txt`],
|
|
181
180
|
}), {
|
|
182
181
|
name: "text",
|
|
183
182
|
description: "the text of the file",
|
|
@@ -190,7 +189,7 @@ const textCommand = (messenger) => {
|
|
|
190
189
|
.addOption(ownerOnlyOption("--text-file <path>", "read the text from this file; - or none reads stdin"))
|
|
191
190
|
.action(async function (chat, message) {
|
|
192
191
|
const context = messengerContext(this, messenger);
|
|
193
|
-
refuseLocalWrite(context, messenger.app.command, "attachments.
|
|
192
|
+
refuseLocalWrite(context, messenger.app.command, "attachments.update");
|
|
194
193
|
const { attachment, textFile } = this.opts();
|
|
195
194
|
const given = textFile === undefined || textFile === "-" ? await readAll(context.stdin) : readFileSync(textFile, "utf8");
|
|
196
195
|
const done = await context.withServices((services) => services.attachments.setText({
|
|
@@ -201,7 +200,7 @@ const textCommand = (messenger) => {
|
|
|
201
200
|
}));
|
|
202
201
|
renderAnswer(this, context, itemOf(snakeKeys(done)), () => `${done.ref} #${done.attachment} ${done.chars} characters kept\n`);
|
|
203
202
|
});
|
|
204
|
-
return
|
|
203
|
+
return update;
|
|
205
204
|
};
|
|
206
205
|
/** Files of stored messages: what is in them, for `content:` in a search. Nothing here is sent. */
|
|
207
206
|
export const attachmentsCommand = (messenger) => {
|
|
@@ -211,7 +210,7 @@ export const attachmentsCommand = (messenger) => {
|
|
|
211
210
|
.addCommand(extractCommand(messenger))
|
|
212
211
|
.addCommand(listCommand(messenger))
|
|
213
212
|
.addCommand(showCommand(messenger))
|
|
214
|
-
.addCommand(
|
|
213
|
+
.addCommand(textUpdateCommand(messenger));
|
|
215
214
|
addMediaArchiveCommands(attachments, messenger);
|
|
216
215
|
return attachments;
|
|
217
216
|
};
|
|
@@ -107,7 +107,7 @@ export const syncCommand = (messenger) => {
|
|
|
107
107
|
if (prepare) {
|
|
108
108
|
validateCatchUpBounds(preparation);
|
|
109
109
|
refuseLocalWrite(context, messenger.app.command, "conversations.links");
|
|
110
|
-
refuseLocalWrite(context, messenger.app.command, "conversations.
|
|
110
|
+
refuseLocalWrite(context, messenger.app.command, "conversations.embeddings");
|
|
111
111
|
}
|
|
112
112
|
if (background) {
|
|
113
113
|
const named = chat ?? ALL_CHATS;
|
|
@@ -182,19 +182,19 @@ export const chatShown = (account, card) => {
|
|
|
182
182
|
};
|
|
183
183
|
/** The lowest score `score>=n` asks for; the audit's own floor when the query names none. */
|
|
184
184
|
export const scoreFloor = (ast) => {
|
|
185
|
-
const term = nativeTerms(ast, "chats members
|
|
185
|
+
const term = nativeTerms(ast, "chats members check").get("score");
|
|
186
186
|
if (!term)
|
|
187
187
|
return AUDIT_MIN_SCORE;
|
|
188
188
|
const upper = term.operator === "range" ? (term.upper ?? "*") : term.value;
|
|
189
189
|
if (term.operator !== "range" || upper !== "*")
|
|
190
190
|
queryError("query.unsupported-operator", term.span, "score takes a lower bound: score>=3", {
|
|
191
|
-
command: "chats members
|
|
191
|
+
command: "chats members check",
|
|
192
192
|
guide: LIST_QUERY_GUIDE,
|
|
193
193
|
});
|
|
194
194
|
const floor = Number(term.value);
|
|
195
195
|
return Math.ceil(term.lower_inclusive === false ? floor + 1 : floor);
|
|
196
196
|
};
|
|
197
|
-
export const auditAnswer = (audit) => wholeList("chats members
|
|
197
|
+
export const auditAnswer = (audit) => wholeList("chats members check", audit.items.map(memberAnswer), {
|
|
198
198
|
...(audit.more ? { meta: { truncated: true } } : {}),
|
|
199
199
|
...(audit.completeness && audit.completeness.state !== "complete"
|
|
200
200
|
? {
|
|
@@ -45,16 +45,16 @@ export const membersHistory = async (services, chat, query) => {
|
|
|
45
45
|
});
|
|
46
46
|
};
|
|
47
47
|
export const membersAudit = async (services, chat, query, options) => {
|
|
48
|
-
const minScore = scoreFloor(listQuery(typedQuery(query), AUDIT_QUERY, "chats members
|
|
48
|
+
const minScore = scoreFloor(listQuery(typedQuery(query), AUDIT_QUERY, "chats members check"));
|
|
49
49
|
const audit = await services.chats.audit(chat, { ...options, minScore });
|
|
50
50
|
return { audit, body: auditAnswer(audit) };
|
|
51
51
|
};
|
|
52
52
|
/** The source takes a count but no offset, so page n reads n pages and shows the last. */
|
|
53
53
|
export const inviteLinks = async (services, chat, query, { limit, page }) => {
|
|
54
|
-
const terms = nativeTerms(listQuery(typedQuery(query), LINKS_QUERY, "chats
|
|
54
|
+
const terms = nativeTerms(listQuery(typedQuery(query), LINKS_QUERY, "chats links list"), "chats links list");
|
|
55
55
|
const revoked = terms.get("revoked")?.value.toLowerCase() === "true";
|
|
56
56
|
const found = await services.admin.links(chat, { limit: limit * page, revoked });
|
|
57
|
-
return listOf("chats
|
|
57
|
+
return listOf("chats links list", {
|
|
58
58
|
items: found.items.slice((page - 1) * limit).map(inviteLinkAnswer),
|
|
59
59
|
limit,
|
|
60
60
|
has_more: found.hasMore,
|