@wirecat/cli-core 0.424.0 → 0.425.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 (61) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/cli/author.d.ts +5 -6
  3. package/dist/cli/author.js +9 -16
  4. package/dist/cli/config-issues.d.ts +20 -2
  5. package/dist/cli/config-issues.js +111 -17
  6. package/dist/cli/context.d.ts +2 -0
  7. package/dist/cli/context.js +17 -6
  8. package/dist/cli/dry-run-guard.d.ts +2 -0
  9. package/dist/cli/dry-run-guard.js +68 -0
  10. package/dist/cli/entry.js +14 -9
  11. package/dist/cli/index.d.ts +3 -3
  12. package/dist/cli/index.js +3 -2
  13. package/dist/cli/list-query.d.ts +2 -0
  14. package/dist/cli/list-query.js +5 -2
  15. package/dist/cli/messenger/store-maintenance-command.js +15 -5
  16. package/dist/cli/preview.d.ts +44 -5
  17. package/dist/cli/preview.js +26 -8
  18. package/dist/cli/program.js +30 -18
  19. package/dist/cli/runs/search.js +2 -0
  20. package/dist/cli/settings.js +13 -12
  21. package/dist/cli/shared-command-exports.js +3 -1
  22. package/dist/entities/index.d.ts +148 -0
  23. package/dist/entities/recorded-run.d.ts +84 -0
  24. package/dist/entities/recorded-run.js +15 -0
  25. package/dist/entities/store-maintenance.d.ts +64 -0
  26. package/dist/entities/store-maintenance.js +24 -1
  27. package/dist/mcp/agent.js +3 -4
  28. package/dist/mcp/bot/server.js +1 -1
  29. package/dist/mcp/meeting-preparation.js +2 -2
  30. package/dist/mcp/meeting-project-candidates.js +2 -2
  31. package/dist/mcp/meeting-series-inventory.js +2 -2
  32. package/dist/mcp/server.js +1 -1
  33. package/dist/mcp/surface.d.ts +3 -1
  34. package/dist/mcp/surface.js +20 -9
  35. package/dist/mcp/text.d.ts +1 -1
  36. package/dist/mcp/text.js +1 -1
  37. package/dist/mcp/tool.d.ts +1 -1
  38. package/dist/mcp/tool.js +3 -1
  39. package/dist/meetings/mcp/agent-text.d.ts +2 -0
  40. package/dist/meetings/mcp/agent-text.js +2 -0
  41. package/dist/meetings/mcp/index.d.ts +1 -1
  42. package/dist/meetings/mcp/index.js +3 -3
  43. package/dist/meetings/mcp/passage.js +2 -2
  44. package/dist/meetings/mcp/project-evidence.js +2 -2
  45. package/dist/meetings/mcp/search.js +2 -2
  46. package/dist/runs/error-detail.d.ts +42 -0
  47. package/dist/runs/error-detail.js +131 -0
  48. package/dist/runs/events.d.ts +4 -0
  49. package/dist/runs/events.js +2 -0
  50. package/dist/runs/log-attributes.js +2 -0
  51. package/dist/runs/recording.d.ts +5 -2
  52. package/dist/runs/recording.js +20 -19
  53. package/dist/runs/run-context.d.ts +37 -0
  54. package/dist/runs/run-context.js +148 -0
  55. package/dist/runs/run.d.ts +19 -3
  56. package/dist/runs/run.js +1 -0
  57. package/dist/store/exports.d.ts +2 -0
  58. package/dist/store/exports.js +2 -0
  59. package/dist/store/sqlite/store-contents.d.ts +47 -0
  60. package/dist/store/sqlite/store-contents.js +104 -0
  61. package/package.json +1 -1
@@ -0,0 +1,104 @@
1
+ /** The tables `store info` counts; a file from before a table's migration simply lacks it. */
2
+ export const COUNTED_TABLES = [
3
+ "accounts",
4
+ "chats",
5
+ "messages",
6
+ "emails",
7
+ "documents",
8
+ "meetings",
9
+ "events",
10
+ "attachments",
11
+ "identities",
12
+ ];
13
+ /** Tables whose rows belong to one account, so they can be counted per account and per provider. */
14
+ const PER_ACCOUNT = ["chats", "messages", "emails", "documents", "meetings"];
15
+ export const hasTable = (database, table) => database.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) !== undefined;
16
+ export const rowCounts = (database) => Object.fromEntries(COUNTED_TABLES.filter((table) => hasTable(database, table)).map((table) => [
17
+ table,
18
+ Number(database.prepare(`SELECT count(*) AS n FROM ${table}`).get()?.n ?? 0),
19
+ ]));
20
+ const zero = () => ({ chats: 0, messages: 0, emails: 0, documents: 0, meetings: 0 });
21
+ /**
22
+ * What the store holds, grouped, over every account in it. Plain `count(*) … GROUP BY` on indexed
23
+ * columns only: `dbstat` would give sizes per table but reads every page of the file.
24
+ */
25
+ export const storeContents = (database) => {
26
+ if (!hasTable(database, "accounts"))
27
+ return undefined;
28
+ const accounts = database.prepare("SELECT id, provider, name FROM accounts ORDER BY provider, id").all();
29
+ const perAccount = new Map(accounts.map((row) => [Number(row.id), zero()]));
30
+ for (const table of PER_ACCOUNT.filter((one) => hasTable(database, one))) {
31
+ for (const row of database.prepare(`SELECT account_id, count(*) AS n FROM ${table} GROUP BY account_id`).all()) {
32
+ const counts = perAccount.get(Number(row.account_id));
33
+ if (counts)
34
+ counts[table] = Number(row.n);
35
+ }
36
+ }
37
+ const providerOf = new Map(accounts.map((row) => [Number(row.id), String(row.provider)]));
38
+ const byProvider = new Map();
39
+ for (const [account, counts] of perAccount) {
40
+ const provider = providerOf.get(account);
41
+ const into = byProvider.get(provider) ?? { accounts: 0, ...zero() };
42
+ into.accounts++;
43
+ for (const table of PER_ACCOUNT)
44
+ into[table] += counts[table];
45
+ byProvider.set(provider, into);
46
+ }
47
+ const byYear = new Map();
48
+ if (hasTable(database, "messages")) {
49
+ // UTC years: the store keeps `sent_at` as epoch milliseconds and the machine's zone is not the owner's.
50
+ const rows = database
51
+ .prepare(`SELECT account_id, CAST(strftime('%Y', sent_at / 1000, 'unixepoch') AS INTEGER) AS year, count(*) AS n
52
+ FROM messages GROUP BY account_id, year`)
53
+ .all();
54
+ for (const row of rows) {
55
+ const provider = providerOf.get(Number(row.account_id)) ?? "unknown";
56
+ const key = `${provider}\u0000${row.year}`;
57
+ const into = byYear.get(key) ?? { provider, year: Number(row.year), messages: 0 };
58
+ into.messages += Number(row.n);
59
+ byYear.set(key, into);
60
+ }
61
+ }
62
+ const byChatKind = hasTable(database, "chats")
63
+ ? database
64
+ .prepare(`SELECT a.provider, c.kind, count(*) AS chats, coalesce(sum(m.n), 0) AS messages
65
+ FROM chats c
66
+ JOIN accounts a ON a.id = c.account_id
67
+ LEFT JOIN (SELECT chat_id, count(*) AS n FROM messages GROUP BY chat_id) m ON m.chat_id = c.id
68
+ GROUP BY a.provider, c.kind
69
+ ORDER BY a.provider, c.kind`)
70
+ .all()
71
+ .map((row) => ({
72
+ provider: String(row.provider),
73
+ kind: String(row.kind),
74
+ chats: Number(row.chats),
75
+ messages: Number(row.messages),
76
+ }))
77
+ : [];
78
+ const byAttachmentKind = hasTable(database, "attachments")
79
+ ? database
80
+ .prepare(`SELECT attachable_type, kind, count(*) AS n, coalesce(sum(size), 0) AS bytes
81
+ FROM attachments GROUP BY attachable_type, kind ORDER BY attachable_type, kind`)
82
+ .all()
83
+ .map((row) => ({
84
+ type: String(row.attachable_type),
85
+ kind: String(row.kind),
86
+ count: Number(row.n),
87
+ bytes: Number(row.bytes),
88
+ }))
89
+ : [];
90
+ return {
91
+ byProvider: [...byProvider]
92
+ .sort(([a], [b]) => a.localeCompare(b))
93
+ .map(([provider, counts]) => ({ provider, ...counts })),
94
+ byChatKind,
95
+ byAccount: accounts.map((row) => ({
96
+ provider: String(row.provider),
97
+ accountId: Number(row.id),
98
+ name: row.name === null ? null : String(row.name),
99
+ ...perAccount.get(Number(row.id)),
100
+ })),
101
+ byYear: [...byYear.values()].sort((a, b) => a.provider.localeCompare(b.provider) || a.year - b.year),
102
+ byAttachmentKind,
103
+ };
104
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.424.0",
3
+ "version": "0.425.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",