@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.
Files changed (127) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/dist/botcheck/reasons.d.ts +1 -1
  3. package/dist/cli/analysis-choice.js +1 -1
  4. package/dist/cli/answer-entity.d.ts +8 -0
  5. package/dist/cli/answer-entity.js +31 -0
  6. package/dist/cli/command-contract.js +5 -6
  7. package/dist/cli/commands-command.js +4 -1
  8. package/dist/cli/effects.js +1 -1
  9. package/dist/cli/embedding-choice.d.ts +1 -1
  10. package/dist/cli/embedding-choice.js +2 -2
  11. package/dist/cli/help/command-help.js +2 -2
  12. package/dist/cli/index.d.ts +6 -2
  13. package/dist/cli/index.js +6 -2
  14. package/dist/cli/json-fields.js +2 -2
  15. package/dist/cli/meeting-batch.d.ts +1 -1
  16. package/dist/cli/meeting-batch.js +20 -2
  17. package/dist/cli/meeting-project-candidates-command.js +0 -1
  18. package/dist/cli/meeting-results.d.ts +3 -0
  19. package/dist/cli/meeting-results.js +31 -0
  20. package/dist/cli/meeting-series-inventory-command.js +0 -1
  21. package/dist/cli/messenger/admin-commands.js +14 -14
  22. package/dist/cli/messenger/archive-commands.js +2 -2
  23. package/dist/cli/messenger/attachments-command.js +7 -8
  24. package/dist/cli/messenger/backfill-command.js +1 -1
  25. package/dist/cli/messenger/chat-answers.js +3 -3
  26. package/dist/cli/messenger/chat-lists.js +3 -3
  27. package/dist/cli/messenger/chats-command.js +8 -8
  28. package/dist/cli/messenger/chats-members-command.js +1 -1
  29. package/dist/cli/messenger/contacts-command.js +10 -7
  30. package/dist/cli/messenger/context.d.ts +11 -4
  31. package/dist/cli/messenger/context.js +6 -0
  32. package/dist/cli/messenger/conversation-examples.js +7 -6
  33. package/dist/cli/messenger/conversations-command.d.ts +0 -4
  34. package/dist/cli/messenger/conversations-command.js +130 -135
  35. package/dist/cli/messenger/counters-command.js +4 -2
  36. package/dist/cli/messenger/doctor-command.js +8 -4
  37. package/dist/cli/messenger/gaps-command.js +2 -2
  38. package/dist/cli/messenger/hearing-command.d.ts +1 -1
  39. package/dist/cli/messenger/hearing-command.js +1 -1
  40. package/dist/cli/messenger/images-command.js +1 -1
  41. package/dist/cli/messenger/inbox.js +1 -3
  42. package/dist/cli/messenger/lacks.d.ts +1 -0
  43. package/dist/cli/messenger/lacks.js +1 -1
  44. package/dist/cli/messenger/mcp-command.js +4 -4
  45. package/dist/cli/messenger/messages-comments-command.js +10 -5
  46. package/dist/cli/messenger/metadata-command.js +5 -5
  47. package/dist/cli/messenger/models-command.js +101 -90
  48. package/dist/cli/messenger/private-people-command.js +5 -6
  49. package/dist/cli/messenger/replies-edit-command.js +0 -1
  50. package/dist/cli/messenger/review.js +1 -3
  51. package/dist/cli/messenger/serve-relay.d.ts +1 -0
  52. package/dist/cli/messenger/stats-command.js +1 -1
  53. package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
  54. package/dist/cli/messenger/store-maintenance-command.js +4 -4
  55. package/dist/cli/messenger/stored.js +5 -0
  56. package/dist/cli/messenger/tags-command.js +4 -10
  57. package/dist/cli/messenger/tasks-command.js +3 -3
  58. package/dist/cli/messenger/transcribe-command.js +1 -1
  59. package/dist/cli/moved.d.ts +2 -0
  60. package/dist/cli/moved.js +39 -1
  61. package/dist/cli/permission-keys.js +2 -0
  62. package/dist/cli/result-fields.js +19 -1
  63. package/dist/cli/settings.js +1 -1
  64. package/dist/cli/steps.js +4 -4
  65. package/dist/cli/store-settings.js +1 -1
  66. package/dist/cli/upgrade-command.js +0 -1
  67. package/dist/domain/models.d.ts +3 -3
  68. package/dist/domain/task-categories.js +1 -1
  69. package/dist/embeddings/remote.js +1 -1
  70. package/dist/entities/contact.d.ts +6 -0
  71. package/dist/entities/contact.js +3 -0
  72. package/dist/entities/index.d.ts +139 -0
  73. package/dist/entities/index.js +4 -1
  74. package/dist/entities/member.d.ts +2 -2
  75. package/dist/entities/member.js +2 -2
  76. package/dist/entities/store-records.d.ts +11 -0
  77. package/dist/entities/store-records.js +1 -0
  78. package/dist/mcp/agent.d.ts +1 -0
  79. package/dist/mcp/agent.js +1 -1
  80. package/dist/mcp/tools/attachments.js +1 -1
  81. package/dist/meetings/cli/index.js +10 -3
  82. package/dist/meetings/index.d.ts +1 -0
  83. package/dist/meetings/index.js +1 -0
  84. package/dist/meetings/result-items.d.ts +127 -0
  85. package/dist/meetings/result-items.js +125 -0
  86. package/dist/ports/app.d.ts +1 -1
  87. package/dist/ports/messenger.d.ts +6 -1
  88. package/dist/search/task-similarity.js +1 -1
  89. package/dist/sends/guard.js +2 -2
  90. package/dist/sends/permission-aliases.d.ts +5 -0
  91. package/dist/sends/permission-aliases.js +49 -0
  92. package/dist/sends/permissions.js +33 -25
  93. package/dist/services/admin.js +7 -7
  94. package/dist/services/chats.js +1 -1
  95. package/dist/services/conversations.d.ts +1 -1
  96. package/dist/services/conversations.js +1 -1
  97. package/dist/services/counters.js +1 -1
  98. package/dist/services/embeddings-maintenance.js +2 -2
  99. package/dist/services/embeddings-search.js +1 -1
  100. package/dist/services/embeddings.d.ts +4 -4
  101. package/dist/services/messages-search.d.ts +1 -1
  102. package/dist/services/messages-search.js +2 -2
  103. package/dist/services/metadata.js +2 -2
  104. package/dist/services/notes-search.js +3 -3
  105. package/dist/services/search-catchup.js +1 -1
  106. package/dist/speech/install.d.ts +4 -2
  107. package/dist/speech/install.js +16 -4
  108. package/dist/speech/local.js +1 -1
  109. package/dist/speech/transcribe.js +1 -1
  110. package/dist/store/search-index.d.ts +1 -1
  111. package/dist/store/sqlite/attachment-texts.d.ts +1 -1
  112. package/dist/store/sqlite/attachment-texts.js +1 -1
  113. package/dist/store/sqlite/batches.js +1 -1
  114. package/dist/store/sqlite/involvements.d.ts +1 -1
  115. package/dist/store/sqlite/note-index.d.ts +2 -2
  116. package/dist/store/sqlite/note-index.js +2 -2
  117. package/dist/store/sqlite/search-index.d.ts +1 -1
  118. package/dist/store/sqlite/search-index.js +1 -1
  119. package/dist/store/sqlite/stems-fill.d.ts +3 -3
  120. package/dist/store/sqlite/stems-fill.js +3 -3
  121. package/dist/store/sqlite/stems.d.ts +1 -1
  122. package/dist/store/sqlite/task-pairs.d.ts +1 -1
  123. package/dist/store/sqlite/task-pairs.js +1 -1
  124. package/package.json +1 -1
  125. package/parity.json +130 -139
  126. package/skills/follow-ups/SKILL.md +5 -5
  127. package/skills/link-conversations/SKILL.md +8 -8
@@ -17,11 +17,11 @@ const PER_SESSION = 8;
17
17
  const PER_REQUEST = 256;
18
18
  /** e5's tokenizer reads ~3.7 characters a token in Russian; 3 keeps the bound above the real count. */
19
19
  const CHARS_PER_TOKEN_AT_LEAST = 3;
20
- const notDownloaded = (deps, id) => new CliError("not_found", `${id} is not downloaded — \`${typedCommand(deps.messenger.app.command, `models text download ${id}`)}\``, {
20
+ const notDownloaded = (deps, id) => new CliError("not_found", `${id} is not downloaded — \`${typedCommand(deps.messenger.app.command, `models download ${id}`)}\``, {
21
21
  reason: "model.not-downloaded",
22
22
  model: id,
23
23
  });
24
- export const notBuiltError = (deps, chatId) => new CliError("not_found", `chat ${chatId} has no conversations yet — \`${typedCommand(deps.messenger.app.command, `conversations build --chat ${chatId}`)}\``);
24
+ export const notBuiltError = (deps, chatId) => new CliError("not_found", `chat ${chatId} has no conversations yet — \`${typedCommand(deps.messenger.app.command, `conversations links rebuild --chat ${chatId}`)}\``);
25
25
  export const embeddingTarget = (deps, choice = DEFAULT_TEXT_MODEL) => {
26
26
  if (typeof choice !== "string") {
27
27
  const { remote, apiKey, concurrency = 4 } = choice;
@@ -245,7 +245,7 @@ export const embeddingsSearch = (deps) => {
245
245
  const { vectors } = await store.vectors.conversationVectors(account, source.id, target.key);
246
246
  if (vectors.length === 0) {
247
247
  const [own] = await readinessOf(deps, chatId, target.key);
248
- const step = own && isStale(own) ? "build" : "embed";
248
+ const step = own && isStale(own) ? "links rebuild" : "embed";
249
249
  throw new CliError("not_found", `conversation ${source.id} has no vector of ${target.id} that matches its messages now — ` +
250
250
  `\`${command} conversations ${step} --chat ${chatId}\``);
251
251
  }
@@ -32,7 +32,7 @@ export interface Embedded {
32
32
  chat: Id;
33
33
  model: string;
34
34
  embedded: number;
35
- /** Chunks whose messages changed since the build: `conversations build` cuts them again. */
35
+ /** Chunks whose messages changed since the build: `conversations links rebuild` cuts them again. */
36
36
  skipped: number;
37
37
  }
38
38
  export interface EmbeddingsService {
@@ -77,7 +77,7 @@ export interface EmbeddingsService {
77
77
  }): Promise<RelatedConversations>;
78
78
  /**
79
79
  * How fresh one chat's conversations and vectors are, or every built chat's — and then how many group chats
80
- * were never built, which `conversations build` would also do.
80
+ * were never built, which `conversations links rebuild` would also do.
81
81
  */
82
82
  readiness(options: {
83
83
  chat?: string;
@@ -152,9 +152,9 @@ export interface SearchReadiness {
152
152
  wordsOnly: Id[];
153
153
  /** Searched by meaning, but some chunks have no vector yet: `conversations embed`. */
154
154
  partial: Id[];
155
- /** Messages or rules changed since the build: `conversations build`. */
155
+ /** Messages or rules changed since the build: `conversations links rebuild`. */
156
156
  stale: Id[];
157
- /** Never built, so their matches cannot be shown: `conversations build`. */
157
+ /** Never built, so their matches cannot be shown: `conversations links rebuild`. */
158
158
  notBuilt: Id[];
159
159
  }
160
160
  export type ReadinessState = "ready" | "stale" | "partial" | "words-only" | "not-built";
@@ -93,7 +93,7 @@ export declare const prepareLucene: (store: MessageStore, account: AccountKey, r
93
93
  /**
94
94
  * The stemmer a search with stemmed words runs with. While the stems are built, or chosen by a newer
95
95
  * tool, none: a half-built stem index would silently drop matches, while the word index answers each
96
- * word's own form. Stems waiting for the owner's `store reindex` still refuse.
96
+ * word's own form. Stems waiting for the owner's `store rebuild` still refuse.
97
97
  */
98
98
  export declare const searchStemming: (store: MessageStore, command?: string) => Promise<{
99
99
  stemmer?: Stemmer;
@@ -148,7 +148,7 @@ export const prepareLucene = async (store, account, request, messenger) => {
148
148
  /**
149
149
  * The stemmer a search with stemmed words runs with. While the stems are built, or chosen by a newer
150
150
  * tool, none: a half-built stem index would silently drop matches, while the word index answers each
151
- * word's own form. Stems waiting for the owner's `store reindex` still refuse.
151
+ * word's own form. Stems waiting for the owner's `store rebuild` still refuse.
152
152
  */
153
153
  export const searchStemming = async (store, command) => {
154
154
  const stems = await store.searchIndex.stemsState();
@@ -203,7 +203,7 @@ const stemsNotReady = (state, command) => {
203
203
  wanted: state.wanted,
204
204
  };
205
205
  if (state.cause === "stemmer_changed")
206
- throw new CliError("validation_error", `the stems were built by ${state.built}, and the store now asks for ${state.wanted} — run \`${cli}store reindex\` (or \`${cli}store migrate\`), or ${exact}`, details);
206
+ throw new CliError("validation_error", `the stems were built by ${state.built}, and the store now asks for ${state.wanted} — run \`${cli}store rebuild\` (or \`${cli}store migrate\`), or ${exact}`, details);
207
207
  if (state.cause === "stemmer_unknown")
208
208
  throw new CliError("validation_error", `the store asks for stemmers this tool does not know — upgrade this tool, or ${exact}`, details);
209
209
  const percent = Math.floor((Math.min(state.filledThrough, state.watermark) / Math.max(state.watermark, 1)) * 100);
@@ -11,11 +11,11 @@ export const metadataService = (deps) => {
11
11
  };
12
12
  const refresh = async (reference) => {
13
13
  if (deps.offline)
14
- throw new CliError("validation_error", "metadata refresh needs a connection; omit --offline");
14
+ throw new CliError("validation_error", "metadata sync needs a connection; omit --offline");
15
15
  const { store, account, chatId } = await held(reference);
16
16
  const found = (await store.chats.chats(account, {})).items.find((chat) => chat.id === chatId);
17
17
  if (!found || (found.kind !== "group" && found.kind !== "channel"))
18
- throw new CliError("validation_error", "metadata refresh applies to groups and channels");
18
+ throw new CliError("validation_error", "metadata sync applies to groups and channels");
19
19
  const read = async (adapter) => capability(adapter, "group", "read group or channel metadata")(chatId);
20
20
  const card = deps.withConnection ? await deps.withConnection(read) : await read(await deps.connection());
21
21
  return store.chats.saveChatMetadata(account, {
@@ -50,10 +50,10 @@ export const searchNotesQuery = async (store, request) => {
50
50
  };
51
51
  /** Chunks one batch embeds: one short transaction writes each, as for conversations. */
52
52
  const NOTE_BATCH = 8;
53
- /** `command` is given only by a tool that has `models text download`; any other gets the tools that do. */
53
+ /** `command` is given only by a tool that has `models download`; any other gets the tools that do. */
54
54
  const downloadHint = (model, command) => command === undefined
55
- ? `install it with a WireCat CLI that has \`models text download\` (tg, max or wa); they share the model folder`
56
- : `\`${command} models text download ${model}\``;
55
+ ? `install it with a WireCat CLI that has \`models download\` (tg, max or wa); they share the model folder`
56
+ : `\`${command} models download ${model}\``;
57
57
  const localModel = (choice, env, command) => {
58
58
  const model = textModel(choice ?? DEFAULT_TEXT_MODEL);
59
59
  const directory = textModelsDirectory(env);
@@ -12,7 +12,7 @@ export const validateCatchUpBounds = (options) => {
12
12
  };
13
13
  export const validateCatchUp = (deps, options) => {
14
14
  validateCatchUpBounds(options);
15
- for (const key of ["conversations.links", "conversations.embed"])
15
+ for (const key of ["conversations.links", "conversations.embeddings"])
16
16
  deps.guard.check({ chatId: null, key }, { reserve: false });
17
17
  };
18
18
  export const catchUpSearch = async (deps, chat, options, signal, clock = Date.now) => {
@@ -14,13 +14,15 @@ export declare const installedBytes: (model: SpeechModel) => number;
14
14
  export type Fetch = (url: string, init?: {
15
15
  signal?: AbortSignal;
16
16
  }) => Promise<Response>;
17
- export declare const install: (model: SpeechModel, directory: string, { fetch: get, progress }?: {
17
+ export declare const install: (model: SpeechModel, directory: string, { fetch: get, progress, verifyExisting, }?: {
18
18
  fetch?: Fetch;
19
19
  progress?: (line: string) => void;
20
+ verifyExisting?: boolean;
20
21
  }) => Promise<void>;
21
22
  /** Each file not already in place, downloaded and checked against its sha256 before it takes its name. */
22
- export declare const installFiles: (files: [ModelFile, string][], { fetch: get, progress }?: {
23
+ export declare const installFiles: (files: [ModelFile, string][], { fetch: get, progress, verifyExisting, }?: {
23
24
  fetch?: Fetch;
24
25
  progress?: (line: string) => void;
26
+ verifyExisting?: boolean;
25
27
  }) => Promise<void>;
26
28
  export declare const megabytes: (bytes: number) => string;
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { createWriteStream, mkdirSync, statSync } from "node:fs";
2
+ import { createReadStream, createWriteStream, mkdirSync, statSync } from "node:fs";
3
3
  import { rename, rm } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
5
5
  import { Readable, Transform } from "node:stream";
@@ -45,12 +45,24 @@ const sizeOf = (path) => {
45
45
  }
46
46
  };
47
47
  export const installedBytes = (model) => model.files.reduce((sum, file) => sum + file.bytes, 0);
48
- export const install = async (model, directory, { fetch: get = fetch, progress } = {}) => {
48
+ export const install = async (model, directory, { fetch: get = fetch, progress, verifyExisting, } = {}) => {
49
49
  mkdirSync(join(directory, model.id), { recursive: true, mode: 0o700 });
50
- await installFiles(placed(model, directory), { fetch: get, ...(progress ? { progress } : {}) });
50
+ await installFiles(placed(model, directory), { fetch: get, progress, verifyExisting });
51
51
  };
52
52
  /** Each file not already in place, downloaded and checked against its sha256 before it takes its name. */
53
- export const installFiles = async (files, { fetch: get = fetch, progress } = {}) => {
53
+ export const installFiles = async (files, { fetch: get = fetch, progress, verifyExisting, } = {}) => {
54
+ if (verifyExisting)
55
+ for (const [file, path] of files) {
56
+ if (sizeOf(path) !== undefined) {
57
+ const hash = createHash("sha256");
58
+ for await (const chunk of createReadStream(path))
59
+ hash.update(chunk);
60
+ if (hash.digest("hex") !== file.sha256) {
61
+ progress?.(`${path}: not the file this version expects, downloading it again`);
62
+ await rm(path, { force: true });
63
+ }
64
+ }
65
+ }
54
66
  for (const [file, path] of files) {
55
67
  if (sizeOf(path) === file.bytes)
56
68
  continue;
@@ -41,7 +41,7 @@ export const openLocalSpeechRecognizer = async (id, input = {}) => {
41
41
  throw new CliError("validation_error", "local speech requires an absolute model directory and bounded output bytes");
42
42
  cancelled(options.signal);
43
43
  if (!isInstalled(model, directory))
44
- throw new CliError("not_found", `speech model ${description.model} is not installed; download it explicitly with a WireCat messenger's models audio download command`, { reason: "model.not-downloaded", model: description.model });
44
+ throw new CliError("not_found", `speech model ${description.model} is not installed; download it explicitly with a WireCat messenger's models download command`, { reason: "model.not-downloaded", model: description.model });
45
45
  const { openRecognizer, toModelRate } = await import("./recognize.js");
46
46
  cancelled(options.signal);
47
47
  const engine = (options.open ?? openRecognizer)(model, modelPath(directory, model), vadPath(directory));
@@ -21,7 +21,7 @@ export const choose = (messenger, settings, flags, env = process.env) => {
21
21
  };
22
22
  /** Never a download: a model is hundreds of MB, and whether to fetch one is the owner's call. */
23
23
  export const notDownloaded = (messenger, model) => new CliError("not_found", `the speech model ${model.id} is not on this machine — the owner downloads it once with ` +
24
- `\`${typedCommand(messenger.app.command, `models audio download ${model.id}`)}\` (${megabytes(installedBytes(model))})`, { reason: "model.not-downloaded", model: model.id });
24
+ `\`${typedCommand(messenger.app.command, `models download ${model.id}`)}\` (${megabytes(installedBytes(model))})`, { reason: "model.not-downloaded", model: model.id });
25
25
  /**
26
26
  * Over an open connection: the messenger's own transcript, or the recording's bytes for a local model.
27
27
  * The model runs after the connection closes — a minute of speech should not hold a socket open.
@@ -36,7 +36,7 @@ export interface SearchIndexStore {
36
36
  * apply, `null` when a newer tool saved one this build does not know.
37
37
  */
38
38
  stemmers(): Promise<Stemmers | null | undefined>;
39
- /** Saves them; stems built by other choices wait for `store reindex` or `store migrate`. */
39
+ /** Saves them; stems built by other choices wait for `store rebuild` or `store migrate`. */
40
40
  saveStemmers(stemmers: Stemmers): Promise<void>;
41
41
  }
42
42
  export declare const searchIndexStoreOver: (context: StoreContext) => SearchIndexStore;
@@ -49,7 +49,7 @@ export declare const accountOf: ({ database }: StoreContext, attachmentPk: numbe
49
49
  /** Failed extraction cannot erase good text; agent text wins over every automated write. */
50
50
  export declare const keepText: ({ database, now }: StoreContext, attachmentPk: number, entry: AttachmentTextEntry) => boolean;
51
51
  /**
52
- * For `store reindex`: the normalized copies follow the current normalizer, then the word index is
52
+ * For `store rebuild`: the normalized copies follow the current normalizer, then the word index is
53
53
  * emptied and filled from them in one transaction — the table is small next to the messages.
54
54
  */
55
55
  export declare const resetAttachmentWords: (database: CacheDatabase) => number;
@@ -64,7 +64,7 @@ export const keepText = ({ database, now }, attachmentPk, entry) => {
64
64
  return Number(changes) > 0;
65
65
  };
66
66
  /**
67
- * For `store reindex`: the normalized copies follow the current normalizer, then the word index is
67
+ * For `store rebuild`: the normalized copies follow the current normalizer, then the word index is
68
68
  * emptied and filled from them in one transaction — the table is small next to the messages.
69
69
  */
70
70
  export const resetAttachmentWords = (database) => {
@@ -93,7 +93,7 @@ const windowOf = (context, id) => {
93
93
  const { orm } = context;
94
94
  const [, chat, first, last] = BATCH_ID.exec(id) ?? [];
95
95
  if (!chat)
96
- throw refused(`${id} is not a batch id from \`conversations batches next\``);
96
+ throw refused(`${id} is not a batch id from \`conversations batches show\``);
97
97
  const chatKey = Number(chat);
98
98
  const ends = orm.all(sql `SELECT id AS pk, sent_at FROM messages WHERE chat_id = ${chatKey} AND deleted_at IS NULL AND id IN (${Number(first)}, ${Number(last)})
99
99
  ORDER BY sent_at, id`);
@@ -17,7 +17,7 @@ export interface Involvement {
17
17
  message: string | null;
18
18
  }
19
19
  export interface InvolvementStore {
20
- /** Every row from scratch, or one person's; `store reindex` runs it, and it empties the queue. */
20
+ /** Every row from scratch, or one person's; `store rebuild` runs it, and it empties the queue. */
21
21
  rebuild(personId?: number): number;
22
22
  /** Recomputes what is still queued; every write already does this before it commits. */
23
23
  drain(): {
@@ -84,7 +84,7 @@ export declare const corpusIndexState: (database: CacheDatabase, corpus: Corpus)
84
84
  export declare const noteIndexState: (database: CacheDatabase) => NoteIndexState;
85
85
  /**
86
86
  * Indexes one corpus's rows written since the last drain, in short write transactions. These corpora are
87
- * small, so a change of stemmer choices simply queues every row again instead of waiting for `store reindex`.
87
+ * small, so a change of stemmer choices simply queues every row again instead of waiting for `store rebuild`.
88
88
  */
89
89
  export declare const drainCorpus: (database: CacheDatabase, corpus: Corpus, stemmerFor: (stemmers: Stemmers) => Stemmer, { batch, until }?: {
90
90
  batch?: number;
@@ -95,5 +95,5 @@ export declare const drainNoteIndex: (database: CacheDatabase, stemmerFor: (stem
95
95
  batch?: number;
96
96
  until?: () => boolean;
97
97
  }) => number;
98
- /** Queues every document, note and memory again — for `store reindex`. */
98
+ /** Queues every document, note and memory again — for `store rebuild`. */
99
99
  export declare const resetNoteIndex: (database: CacheDatabase) => boolean;
@@ -143,7 +143,7 @@ const writer = (database, corpus, stemmer) => {
143
143
  };
144
144
  /**
145
145
  * Indexes one corpus's rows written since the last drain, in short write transactions. These corpora are
146
- * small, so a change of stemmer choices simply queues every row again instead of waiting for `store reindex`.
146
+ * small, so a change of stemmer choices simply queues every row again instead of waiting for `store rebuild`.
147
147
  */
148
148
  export const drainCorpus = (database, corpus, stemmerFor, { batch = 200, until = () => false } = {}) => {
149
149
  // Pieces written before they carried their account get it, once: purge and vector search filter by it.
@@ -193,7 +193,7 @@ export const drainCorpus = (database, corpus, stemmerFor, { batch = 200, until =
193
193
  /** Documents, then notes: what a notes search reads. */
194
194
  export const drainNoteIndex = (database, stemmerFor, options = {}) => drainCorpus(database, CORPORA.document, stemmerFor, options) +
195
195
  drainCorpus(database, CORPORA.note, stemmerFor, options);
196
- /** Queues every document, note and memory again — for `store reindex`. */
196
+ /** Queues every document, note and memory again — for `store rebuild`. */
197
197
  export const resetNoteIndex = (database) => {
198
198
  write(database, () => {
199
199
  for (const corpus of Object.values(CORPORA))
@@ -34,6 +34,6 @@ export declare const fillSearchIndex: (database: CacheDatabase, { batch, until,
34
34
  }) => SearchIndexFill;
35
35
  /**
36
36
  * Empties the word index and its vocabulary and starts the fill again from the newest message — for
37
- * `store reindex`. Messages written meanwhile are indexed by the triggers, as after the migration.
37
+ * `store rebuild`. Messages written meanwhile are indexed by the triggers, as after the migration.
38
38
  */
39
39
  export declare const resetSearchIndex: (database: CacheDatabase) => void;
@@ -138,7 +138,7 @@ const buildTerms = (database, { batch, until, onBatch }) => {
138
138
  };
139
139
  /**
140
140
  * Empties the word index and its vocabulary and starts the fill again from the newest message — for
141
- * `store reindex`. Messages written meanwhile are indexed by the triggers, as after the migration.
141
+ * `store rebuild`. Messages written meanwhile are indexed by the triggers, as after the migration.
142
142
  */
143
143
  export const resetSearchIndex = (database) => {
144
144
  if (!searchIndexState(database))
@@ -3,7 +3,7 @@ import { type StemsFill } from "./stems.js";
3
3
  /**
4
4
  * Brings the stems towards "ready" in short write transactions: the messages up to the watermark, then
5
5
  * the queue. One stemmer per run, so its cache serves every batch. Never rebuilds: a row built by other
6
- * choices is left for `store migrate` or `store reindex`.
6
+ * choices is left for `store migrate` or `store rebuild`.
7
7
  */
8
8
  export declare const fillStems: (database: CacheDatabase, { batch, until, onBatch, now, }?: {
9
9
  batch?: number;
@@ -13,7 +13,7 @@ export declare const fillStems: (database: CacheDatabase, { batch, until, onBatc
13
13
  }) => StemsFill;
14
14
  /**
15
15
  * Empties the stems and starts them again from the newest message, claimed by the store's setting —
16
- * for `store reindex`, and for `store migrate` when the stems were built by other choices. A row built
16
+ * for `store rebuild`, and for `store migrate` when the stems were built by other choices. A row built
17
17
  * by a newer Snowball than this binary has is refused: rebuilding it would downgrade every newer tool.
18
18
  */
19
19
  export declare const resetStems: (database: CacheDatabase, { force, now }?: {
@@ -22,7 +22,7 @@ export declare const resetStems: (database: CacheDatabase, { force, now }?: {
22
22
  }) => boolean;
23
23
  /**
24
24
  * Stems an older tool built with its own default, while nobody chose stemmers, start again with this
25
- * build's default: nobody chose the old one, so it waits for no `store reindex`. Like a first fill
25
+ * build's default: nobody chose the old one, so it waits for no `store rebuild`. Like a first fill
26
26
  * from then on. A saved default is replaced only by newer defaults, so two versions never rebuild each
27
27
  * other's. A row a newer Snowball built is left for an upgrade.
28
28
  */
@@ -5,7 +5,7 @@ import { writeBatch } from "./transaction.js";
5
5
  /**
6
6
  * Brings the stems towards "ready" in short write transactions: the messages up to the watermark, then
7
7
  * the queue. One stemmer per run, so its cache serves every batch. Never rebuilds: a row built by other
8
- * choices is left for `store migrate` or `store reindex`.
8
+ * choices is left for `store migrate` or `store rebuild`.
9
9
  */
10
10
  export const fillStems = (database, { batch = 5_000, until = () => false, onBatch, now = Date.now, } = {}) => {
11
11
  const filled = { stemmed: 0, drained: 0 };
@@ -62,7 +62,7 @@ const newer = (a, b) => {
62
62
  };
63
63
  /**
64
64
  * Empties the stems and starts them again from the newest message, claimed by the store's setting —
65
- * for `store reindex`, and for `store migrate` when the stems were built by other choices. A row built
65
+ * for `store rebuild`, and for `store migrate` when the stems were built by other choices. A row built
66
66
  * by a newer Snowball than this binary has is refused: rebuilding it would downgrade every newer tool.
67
67
  */
68
68
  export const resetStems = (database, { force = false, now = Date.now } = {}) => {
@@ -93,7 +93,7 @@ export const resetStems = (database, { force = false, now = Date.now } = {}) =>
93
93
  };
94
94
  /**
95
95
  * Stems an older tool built with its own default, while nobody chose stemmers, start again with this
96
- * build's default: nobody chose the old one, so it waits for no `store reindex`. Like a first fill
96
+ * build's default: nobody chose the old one, so it waits for no `store rebuild`. Like a first fill
97
97
  * from then on. A saved default is replaced only by newer defaults, so two versions never rebuild each
98
98
  * other's. A row a newer Snowball built is left for an upgrade.
99
99
  */
@@ -15,7 +15,7 @@ export interface StemsState {
15
15
  /** Every live message is stemmed by `wanted`: stemmed search may run. */
16
16
  ready: boolean;
17
17
  /**
18
- * Why it is not ready: still filling, built by other choices and waiting for `store reindex`, or the
18
+ * Why it is not ready: still filling, built by other choices and waiting for `store rebuild`, or the
19
19
  * store asks for choices only a newer tool knows.
20
20
  */
21
21
  cause?: "building" | "stemmer_changed" | "stemmer_unknown";
@@ -4,7 +4,7 @@ import type { StoreContext } from "./open.js";
4
4
  import type { SimilarTask, TaskSimilarity } from "./task-candidates.js";
5
5
  /**
6
6
  * What became of a pair: `review` waits for the agent that reviews after a sync, `unsure` for the owner; the rest
7
- * are labelled pairs (tasks plan, "Learn from answers") — `merged`, `attached` say one job, `rejected`, `unmerged`,
7
+ * are labelled pairs (tasks update, "Learn from answers") — `merged`, `attached` say one job, `rejected`, `unmerged`,
8
8
  * `new` say two.
9
9
  */
10
10
  export declare const TASK_PAIR_DECISIONS: readonly ["review", "unsure", "merged", "rejected", "unmerged", "attached", "new"];
@@ -11,7 +11,7 @@ import { read, write } from "./transaction.js";
11
11
  import { recordTaskEvent } from "./work-tasks.js";
12
12
  /**
13
13
  * What became of a pair: `review` waits for the agent that reviews after a sync, `unsure` for the owner; the rest
14
- * are labelled pairs (tasks plan, "Learn from answers") — `merged`, `attached` say one job, `rejected`, `unmerged`,
14
+ * are labelled pairs (tasks update, "Learn from answers") — `merged`, `attached` say one job, `rejected`, `unmerged`,
15
15
  * `new` say two.
16
16
  */
17
17
  export const TASK_PAIR_DECISIONS = ["review", "unsure", "merged", "rejected", "unmerged", "attached", "new"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.405.0",
3
+ "version": "0.407.0",
4
4
  "description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",