@wirecat/cli-core 0.377.0 → 0.379.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 (74) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/cli/envelope.d.ts +10 -0
  3. package/dist/cli/list-query.js +2 -2
  4. package/dist/cli/meeting-preparation-read.js +5 -5
  5. package/dist/cli/meeting-series-inventory-read.js +3 -4
  6. package/dist/cli/messenger/contacts-command.js +1 -1
  7. package/dist/cli/messenger/stats-command.js +3 -1
  8. package/dist/context/evidence-response.js +2 -2
  9. package/dist/context/evidence.d.ts +5 -2
  10. package/dist/context/evidence.js +21 -6
  11. package/dist/domain/moment.d.ts +8 -0
  12. package/dist/domain/moment.js +14 -0
  13. package/dist/domain/send-time.d.ts +2 -2
  14. package/dist/domain/send-time.js +4 -3
  15. package/dist/entities/account-session.d.ts +2 -2
  16. package/dist/entities/admin-report.d.ts +8 -8
  17. package/dist/entities/agenda.d.ts +12 -12
  18. package/dist/entities/chat-event.d.ts +1 -1
  19. package/dist/entities/chat-stats.d.ts +5 -5
  20. package/dist/entities/chat.d.ts +4 -4
  21. package/dist/entities/contact-note.d.ts +2 -2
  22. package/dist/entities/contact.d.ts +13 -13
  23. package/dist/entities/conversation.d.ts +3 -3
  24. package/dist/entities/counter-reading.d.ts +1 -1
  25. package/dist/entities/counters.d.ts +2 -2
  26. package/dist/entities/document.d.ts +2 -2
  27. package/dist/entities/evidence.d.ts +72 -72
  28. package/dist/entities/fact.d.ts +3 -3
  29. package/dist/entities/fields.d.ts +3 -1
  30. package/dist/entities/fields.js +2 -0
  31. package/dist/entities/hit.d.ts +1 -1
  32. package/dist/entities/index.d.ts +216 -215
  33. package/dist/entities/index.js +1 -0
  34. package/dist/entities/invite-link.d.ts +1 -1
  35. package/dist/entities/job.d.ts +2 -2
  36. package/dist/entities/join-request.d.ts +1 -1
  37. package/dist/entities/meeting-communications.d.ts +4 -4
  38. package/dist/entities/meeting-findings.d.ts +2 -2
  39. package/dist/entities/meeting-preparation-parts.d.ts +9 -9
  40. package/dist/entities/meeting-preparation.d.ts +23 -23
  41. package/dist/entities/meeting-series-inventory.d.ts +3 -3
  42. package/dist/entities/member.d.ts +3 -3
  43. package/dist/entities/memory.d.ts +3 -3
  44. package/dist/entities/message.d.ts +6 -6
  45. package/dist/entities/note.d.ts +3 -3
  46. package/dist/entities/official-stats.d.ts +2 -2
  47. package/dist/entities/poll-vote.d.ts +1 -1
  48. package/dist/entities/ranking.d.ts +2 -2
  49. package/dist/entities/relationship.d.ts +1 -1
  50. package/dist/entities/retention.d.ts +4 -4
  51. package/dist/entities/saved-search.d.ts +2 -2
  52. package/dist/entities/tagging.d.ts +1 -1
  53. package/dist/entities/task.d.ts +7 -7
  54. package/dist/entities/topic.d.ts +2 -2
  55. package/dist/mcp/tools/stats.js +3 -1
  56. package/dist/meetings/answers.d.ts +14 -14
  57. package/dist/meetings/cli/index.js +7 -4
  58. package/dist/meetings/cli/search.js +11 -13
  59. package/dist/meetings/item.d.ts +4 -4
  60. package/dist/meetings/project-evidence-answer.d.ts +3 -3
  61. package/dist/services/admin-statistics.js +2 -2
  62. package/dist/services/context-evidence.js +1 -0
  63. package/dist/services/index.d.ts +1 -1
  64. package/dist/services/meeting-communications-selection.d.ts +1 -0
  65. package/dist/services/messages-archive-search.js +1 -1
  66. package/dist/services/moment.d.ts +4 -2
  67. package/dist/services/moment.js +13 -4
  68. package/dist/services/project-gathering-request.d.ts +30 -8
  69. package/dist/services/project-gathering-request.js +61 -8
  70. package/dist/services/project-gathering.d.ts +5 -2
  71. package/dist/services/project-gathering.js +11 -5
  72. package/dist/store/sqlite/context-evidence.js +24 -12
  73. package/dist/store/sqlite/facts.js +2 -1
  74. package/package.json +3 -3
@@ -20,6 +20,7 @@ const corpora = {
20
20
  join: "JOIN chats c ON c.id=n.chat_id AND c.account_id=n.account_id",
21
21
  where: "c.searchable=1",
22
22
  chats: "chats",
23
+ sender: "n.sender_identity_id",
23
24
  // A read that names the chat sees it even when it is hidden from search (searchable=0).
24
25
  named: "c.external_id=?",
25
26
  },
@@ -36,6 +37,7 @@ const corpora = {
36
37
  join: "JOIN email_threads c ON c.id=n.email_thread_id AND c.account_id=n.account_id",
37
38
  where: "a.provider='email'",
38
39
  chats: "email_threads",
40
+ sender: "n.from_identity_id",
39
41
  named: "a.provider='email' AND c.external_id=?",
40
42
  },
41
43
  document: {
@@ -51,6 +53,7 @@ const corpora = {
51
53
  join: "",
52
54
  where: "n.body IS NOT NULL AND CASE WHEN json_valid(n.metadata) THEN coalesce(json_extract(n.metadata, '$.catalog.active'),1) ELSE 1 END=1",
53
55
  chats: null,
56
+ sender: null,
54
57
  named: null,
55
58
  },
56
59
  };
@@ -58,11 +61,12 @@ const corpora = {
58
61
  export const contextEvidenceOver = ({ database }) => ({
59
62
  async read(original) {
60
63
  const request = contextEvidenceRequest(original);
61
- const { source, words, chat, after, before, limit, maxReadBytes, cursor, signal } = request;
64
+ const { source, words, chat, senders, after, before, limit, maxReadBytes, cursor, signal } = request;
62
65
  if (source.kind === "meeting")
63
66
  return readMeetingContextEvidence(database, request);
64
67
  const corpus = corpora[source.kind];
65
- const scope = contextCursorScope({ source, query: request.query, chat, after, before });
68
+ const scope = contextCursorScope({ source, query: request.query, chat, senders, after, before });
69
+ const searched = chat === undefined && senders === undefined;
66
70
  signal?.throwIfAborted();
67
71
  return read(database, () => {
68
72
  const coverage = {
@@ -71,7 +75,7 @@ export const contextEvidenceOver = ({ database }) => ({
71
75
  hasMore: false,
72
76
  hasUndated: false,
73
77
  completeness: "unknown",
74
- matching: chat === undefined ? "literal-words" : "chat",
78
+ matching: chat !== undefined ? "chat" : senders !== undefined ? "sender" : "literal-words",
75
79
  consistency: "snapshot-per-page",
76
80
  };
77
81
  const empty = () => ({ source, items: [], next: null, readBytes: 0, coverage });
@@ -87,19 +91,27 @@ export const contextEvidenceOver = ({ database }) => ({
87
91
  .get(source.accountId, chat))
88
92
  return empty();
89
93
  coverage.available = true;
90
- const scopeParams = chat === undefined ? accountParams : [...accountParams, chat];
94
+ const scopeParams = chat !== undefined
95
+ ? [...accountParams, chat]
96
+ : senders !== undefined
97
+ ? [...accountParams, ...senders]
98
+ : accountParams;
99
+ const byChat = chat === undefined ? corpus.where : corpus.named;
100
+ const bySender = senders === undefined
101
+ ? ""
102
+ : ` AND ${corpus.sender} IN (SELECT id FROM identities WHERE provider=a.provider AND external_id IN (${senders.map(() => "?").join(",")}))`;
91
103
  const base = `FROM ${corpus.table} n JOIN accounts a ON a.id=n.account_id ${corpus.join}
92
104
  WHERE n.account_id=? AND a.provider=? AND a.external_id=? AND n.deleted_at IS NULL
93
- AND ${chat === undefined ? corpus.where : corpus.named}`;
94
- // A chat read uses no word index, so words still waiting for it hide nothing.
95
- if (chat !== undefined)
105
+ AND ${byChat}${bySender}`;
106
+ // A chat or sender read uses no word index, so words still waiting for it hide nothing.
107
+ if (!searched)
96
108
  coverage.index = "ready";
97
109
  else if (!database.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(corpus.index)) {
98
110
  coverage.index = "missing";
99
111
  return empty();
100
112
  }
101
113
  coverage.hasUndated = Boolean(database.prepare(`SELECT 1 ${base} AND ${corpus.at} IS NULL LIMIT 1`).get(...scopeParams));
102
- if (chat === undefined && source.kind === "message") {
114
+ if (searched && source.kind === "message") {
103
115
  const state = database
104
116
  .prepare("SELECT watermark,filled_through FROM search_index_state WHERE name='message_words'")
105
117
  .get();
@@ -112,7 +124,7 @@ export const contextEvidenceOver = ({ database }) => ({
112
124
  ? "pending"
113
125
  : "ready";
114
126
  }
115
- else if (chat === undefined) {
127
+ else if (searched) {
116
128
  coverage.index = database
117
129
  .prepare(`SELECT 1 ${base} AND ${corpus.at}>=? AND ${corpus.at}<?
118
130
  AND EXISTS(SELECT 1 FROM ${source.kind === "mail" ? "email" : "document"}_index_pending p
@@ -125,12 +137,12 @@ export const contextEvidenceOver = ({ database }) => ({
125
137
  ${corpus.title} AS title,${corpus.body} AS body,${corpus.url} AS url,${corpus.at} AS at,
126
138
  n.updated_at,${corpus.revision} AS revision,${corpus.timeKind} AS time_kind ${base}
127
139
  AND ${corpus.at}>=? AND ${corpus.at}<?
128
- ${chat !== undefined ? "" : `AND n.id IN (SELECT rowid FROM ${corpus.index} WHERE ${corpus.index} MATCH ?)`}
129
- ${chat !== undefined ? "" : source.kind === "message" ? `AND n.normalized_text IS NOT NULL AND n.normalizer_version=${NORMALIZER_VERSION}` : `AND NOT EXISTS(SELECT 1 FROM ${source.kind === "mail" ? "email" : "document"}_index_pending p WHERE p.id=n.id AND p.indexable_type='${source.kind === "mail" ? "email" : "document"}')`}
140
+ ${!searched ? "" : `AND n.id IN (SELECT rowid FROM ${corpus.index} WHERE ${corpus.index} MATCH ?)`}
141
+ ${!searched ? "" : source.kind === "message" ? `AND n.normalized_text IS NOT NULL AND n.normalizer_version=${NORMALIZER_VERSION}` : `AND NOT EXISTS(SELECT 1 FROM ${source.kind === "mail" ? "email" : "document"}_index_pending p WHERE p.id=n.id AND p.indexable_type='${source.kind === "mail" ? "email" : "document"}')`}
130
142
  ${cursor ? `AND (${corpus.at}<? OR (${corpus.at}=? AND n.id<?))` : ""}
131
143
  ORDER BY ${corpus.at} DESC,n.id DESC LIMIT ?`;
132
144
  const params = [...scopeParams, after, before];
133
- if (chat === undefined)
145
+ if (searched)
134
146
  params.push(words.map((w) => `normalized_text:"${normalize(w)}"`).join(" AND "));
135
147
  if (cursor)
136
148
  params.push(cursor.at, cursor.at, cursor.id);
@@ -1,5 +1,6 @@
1
1
  import { CliError } from "@wirecat/cli-base";
2
2
  import { FACT_TYPES, MEMORY_SCOPES } from "../../domain/knowledge.js";
3
+ import { calendarMoment } from "../../domain/moment.js";
3
4
  import { linkKind } from "./link-kinds.js";
4
5
  import { authorActor, authorOf, evidenceOf, linkEvidence } from "./memories.js";
5
6
  import { requiredThing } from "./notes.js";
@@ -64,7 +65,7 @@ export const factOperationsOver = (context) => {
64
65
  if (!statement || statement.length > 2000)
65
66
  throw new CliError("validation_error", "a fact's statement takes 1–2000 characters");
66
67
  const scope = input.scope === undefined ? null : oneOf(input.scope, MEMORY_SCOPES, "a fact's scope");
67
- const occurredAt = input.occurredAt === undefined ? null : Date.parse(input.occurredAt);
68
+ const occurredAt = input.occurredAt === undefined ? null : calendarMoment(input.occurredAt, "occurredAt");
68
69
  if (occurredAt !== null && !Number.isFinite(occurredAt))
69
70
  throw new CliError("validation_error", "occurredAt takes an ISO timestamp");
70
71
  if (input.supersedes !== undefined && type !== "decision")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.377.0",
3
+ "version": "0.379.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",
@@ -202,7 +202,7 @@
202
202
  "@types/node": "^22.20.4",
203
203
  "@types/pngjs": "6.0.5",
204
204
  "@vitest/coverage-v8": "^5.0.2",
205
- "@wirecat/cli-base": "0.47.3",
205
+ "@wirecat/cli-base": "0.48.0",
206
206
  "commander": "15.0.0",
207
207
  "cspell": "10.3.6",
208
208
  "drizzle-kit": "1.0.0-rc.4",
@@ -222,7 +222,7 @@
222
222
  },
223
223
  "peerDependencies": {
224
224
  "@napi-rs/canvas": ">=0.1.69 <2",
225
- "@wirecat/cli-base": ">=0.47.3 <0.48.0",
225
+ "@wirecat/cli-base": ">=0.48.0 <0.49.0",
226
226
  "commander": ">=15"
227
227
  },
228
228
  "bin": {