@wirecat/cli-core 0.563.0 → 0.565.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 (143) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/dist/calendar/busy.d.ts +10 -10
  3. package/dist/calendar/busy.js +9 -9
  4. package/dist/calendar/cli/answers.d.ts +7 -8
  5. package/dist/calendar/cli/answers.js +4 -5
  6. package/dist/calendar/cli/bodies.d.ts +33 -0
  7. package/dist/calendar/cli/bodies.js +52 -0
  8. package/dist/calendar/cli/files.d.ts +8 -0
  9. package/dist/calendar/cli/files.js +41 -0
  10. package/dist/calendar/cli/index.d.ts +58 -51
  11. package/dist/calendar/cli/index.js +311 -284
  12. package/dist/calendar/cli/remind.d.ts +2 -11
  13. package/dist/calendar/cli/remind.js +81 -81
  14. package/dist/calendar/cli/search-all.d.ts +3 -8
  15. package/dist/calendar/cli/search-all.js +47 -42
  16. package/dist/calendar/mcp/index.d.ts +1 -1
  17. package/dist/calendar/prepare.d.ts +1 -1
  18. package/dist/calendar/testing/answers.d.ts +27 -5
  19. package/dist/calendar/testing/answers.js +88 -17
  20. package/dist/calendar/testing/writer.d.ts +1 -0
  21. package/dist/calendar/testing/writer.js +6 -0
  22. package/dist/calendar/writer.d.ts +6 -1
  23. package/dist/calendar/writes.d.ts +3 -1
  24. package/dist/calendar/writes.js +42 -20
  25. package/dist/cli/config-command.js +1 -1
  26. package/dist/cli/config-issues.d.ts +3 -1
  27. package/dist/cli/config-issues.js +2 -2
  28. package/dist/cli/contract-evidence.d.ts +1 -1
  29. package/dist/cli/early-refusal.d.ts +2 -1
  30. package/dist/cli/early-refusal.js +4 -2
  31. package/dist/cli/entry.d.ts +6 -2
  32. package/dist/cli/entry.js +4 -1
  33. package/dist/cli/envelope.d.ts +2 -2
  34. package/dist/cli/index.d.ts +1 -0
  35. package/dist/cli/index.js +1 -0
  36. package/dist/cli/messenger/archive-commands.js +17 -0
  37. package/dist/cli/messenger/catch-up-answers.d.ts +5 -0
  38. package/dist/cli/messenger/catch-up-answers.js +3 -0
  39. package/dist/cli/messenger/search-answers.d.ts +1 -0
  40. package/dist/cli/messenger/search-answers.js +1 -1
  41. package/dist/cli/messenger/stats-answers.d.ts +3 -3
  42. package/dist/cli/messenger/stats-answers.js +21 -9
  43. package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
  44. package/dist/cli/messenger/tasks-command.js +35 -14
  45. package/dist/cli/permission-keys.d.ts +3 -1
  46. package/dist/cli/permission-keys.js +2 -1
  47. package/dist/cli/preview.d.ts +12 -0
  48. package/dist/cli/preview.js +8 -1
  49. package/dist/cli/settings.d.ts +2 -0
  50. package/dist/cli/settings.js +8 -1
  51. package/dist/conversations/mail-text.d.ts +6 -0
  52. package/dist/conversations/mail-text.js +73 -0
  53. package/dist/domain/calendar.d.ts +2 -0
  54. package/dist/domain/calendar.js +6 -0
  55. package/dist/entities/chat-stats.d.ts +16 -2
  56. package/dist/entities/chat-stats.js +18 -3
  57. package/dist/entities/index.d.ts +50 -802
  58. package/dist/entities/index.js +23 -16
  59. package/dist/entities/mail-counts.d.ts +15 -0
  60. package/dist/entities/mail-counts.js +16 -0
  61. package/dist/entities/meeting.d.ts +1 -1
  62. package/dist/entities/meeting.js +1 -1
  63. package/dist/entities/store-records.d.ts +8 -0
  64. package/dist/entities/store-records.js +8 -0
  65. package/dist/errors/reasons.js +19 -1
  66. package/dist/mail/cli/index.d.ts +5 -0
  67. package/dist/mail/cli/index.js +27 -3
  68. package/dist/mail/cli/review.js +11 -4
  69. package/dist/mail/index.d.ts +2 -0
  70. package/dist/mail/index.js +2 -0
  71. package/dist/mail/stats.d.ts +50 -0
  72. package/dist/mail/stats.js +60 -0
  73. package/dist/mail/whole.d.ts +4 -4
  74. package/dist/mail/whole.js +4 -3
  75. package/dist/mcp/meeting-preparation.d.ts +1 -1
  76. package/dist/mcp/meeting-project-candidates.d.ts +1 -1
  77. package/dist/mcp/meeting-series-inventory.d.ts +1 -1
  78. package/dist/meetings/index.d.ts +2 -2
  79. package/dist/meetings/index.js +2 -2
  80. package/dist/meetings/mcp/index.d.ts +15 -15
  81. package/dist/meetings/mcp/passage.d.ts +1 -1
  82. package/dist/meetings/mcp/project-evidence.d.ts +1 -1
  83. package/dist/meetings/mcp/search.d.ts +1 -1
  84. package/dist/meetings/read-answers.d.ts +22 -1
  85. package/dist/meetings/read-answers.js +38 -0
  86. package/dist/meetings/stats.d.ts +44 -0
  87. package/dist/meetings/stats.js +77 -7
  88. package/dist/search/lucene/registry.js +2 -1
  89. package/dist/search/question-plan.d.ts +16 -0
  90. package/dist/search/question-plan.js +34 -0
  91. package/dist/services/events-search.d.ts +5 -1
  92. package/dist/services/events-search.js +10 -4
  93. package/dist/services/index.d.ts +1 -1
  94. package/dist/services/index.js +1 -1
  95. package/dist/services/meeting-stats.d.ts +12 -1
  96. package/dist/services/meeting-stats.js +12 -0
  97. package/dist/services/messages-discovery.d.ts +1 -5
  98. package/dist/services/messages-discovery.js +5 -18
  99. package/dist/services/messages-meaning.js +25 -3
  100. package/dist/services/messages.js +4 -3
  101. package/dist/services/metadata.d.ts +1 -1
  102. package/dist/services/notes-search.d.ts +5 -1
  103. package/dist/services/notes-search.js +16 -5
  104. package/dist/services/proposals/ids.d.ts +2 -2
  105. package/dist/services/proposals/ids.js +5 -3
  106. package/dist/services/proposals/kinds/findings.d.ts +1 -1
  107. package/dist/services/proposals/kinds/findings.js +1 -1
  108. package/dist/services/proposals/kinds/meeting-findings.d.ts +7 -0
  109. package/dist/services/proposals/kinds/meeting-findings.js +73 -0
  110. package/dist/services/proposals/kinds/task-close.d.ts +7 -0
  111. package/dist/services/proposals/kinds/task-close.js +76 -0
  112. package/dist/services/proposals/registry.js +4 -0
  113. package/dist/services/search-all.d.ts +5 -0
  114. package/dist/services/search-all.js +47 -14
  115. package/dist/services/task-stats.d.ts +41 -0
  116. package/dist/services/task-stats.js +126 -0
  117. package/dist/services/tasks.d.ts +17 -4
  118. package/dist/services/tasks.js +31 -14
  119. package/dist/store/chats.d.ts +3 -1
  120. package/dist/store/chats.js +6 -0
  121. package/dist/store/decisions.d.ts +4 -2
  122. package/dist/store/decisions.js +5 -3
  123. package/dist/store/exports.d.ts +1 -1
  124. package/dist/store/exports.js +1 -1
  125. package/dist/store/index.d.ts +2 -1
  126. package/dist/store/index.js +1 -1
  127. package/dist/store/sqlite/completeness.d.ts +17 -0
  128. package/dist/store/sqlite/completeness.js +49 -13
  129. package/dist/store/sqlite/lucene-fields.js +2 -0
  130. package/dist/store/sqlite/lucene-groups.d.ts +15 -0
  131. package/dist/store/sqlite/lucene-groups.js +21 -0
  132. package/dist/store/sqlite/lucene.d.ts +2 -9
  133. package/dist/store/sqlite/lucene.js +1 -12
  134. package/dist/store/sqlite/meeting-stats.d.ts +2 -0
  135. package/dist/store/sqlite/meeting-stats.js +27 -1
  136. package/dist/store/sqlite/retention.js +2 -7
  137. package/dist/store/sqlite/task-board.js +2 -0
  138. package/dist/store/sqlite/task-stats.d.ts +32 -0
  139. package/dist/store/sqlite/task-stats.js +45 -0
  140. package/dist/store/sqlite/tasks.d.ts +2 -1
  141. package/dist/store/sqlite/tasks.js +2 -0
  142. package/package.json +3 -3
  143. package/parity.json +13 -1
@@ -86,3 +86,76 @@ export const mailCore = (body, earlier) => {
86
86
  const kept = trimEdges(lines.filter((_, i) => !drop.has(i)));
87
87
  return withoutSignOff(withoutGreeting(kept)).join("\n").trim();
88
88
  };
89
+ const QUOTED = /^\s*>/;
90
+ const ATTRIBUTION_END = /(wrote|написал(\(а\)|а|и)?|escribió|a écrit|schrieb\s.+|<[^<>\s]+@[^<>\s]+>)\s*:\s*$/iu;
91
+ /** The first line of an attribution a client wrapped in two: "On Mon, 3 Nov 2026 at 10:00, Alice Example <". */
92
+ const ATTRIBUTION_START = /^(on|le|am|el|в)\s/iu;
93
+ const DATED = /^(on|le|am|el|в|\d)/iu;
94
+ const ORIGINAL = /^-{2,}\s*(original message|ursprüngliche nachricht|message d'origine|mensaje original|исходное сообщение)\s*-{2,}$/iu;
95
+ const FROM_LINE = /^(from|von|de|от)\s?:\s*\S/iu;
96
+ const DATE_LINE = /^(sent|date|gesendet|datum|envoyé|enviado|fecha|отправлено|дата)\s?:/iu;
97
+ const FORWARD = /^(-{2,}\s*(forwarded message|weitergeleitete nachricht|message transféré|mensaje reenviado|пересылаемое сообщение)\s*-{2,}|begin forwarded message:)$/iu;
98
+ const RULE = /^_{5,}$/;
99
+ const MOBILE = /^(sent from my |von meinem .+ gesendet$|envoyé de mon |отправлено с |enviado desde mi )/iu;
100
+ /** Where an attribution ending at `i` begins, or -1 when the line is not one. */
101
+ const attributionAt = (lines, i) => {
102
+ const line = (lines[i] ?? "").trim();
103
+ if (!ATTRIBUTION_END.test(line))
104
+ return -1;
105
+ const prior = (lines[i - 1] ?? "").trim();
106
+ return prior && ATTRIBUTION_START.test(prior) && !ATTRIBUTION_START.test(line) ? i - 1 : i;
107
+ };
108
+ /** An Outlook header — From, then Sent or Date within the next lines — or its "Original Message" divider. */
109
+ const outlookAt = (lines, i) => {
110
+ const line = (lines[i] ?? "").trim();
111
+ if (ORIGINAL.test(line))
112
+ return true;
113
+ return FROM_LINE.test(line) && lines.slice(i + 1, i + 4).some((next) => DATE_LINE.test(next.trim()));
114
+ };
115
+ const nextText = (lines, from) => lines.slice(from).find((line) => line.trim()) ?? "";
116
+ /** The lines an email adds, in reading order: quotes dropped, and everything after a reply header cut. */
117
+ const ownLines = (lines) => {
118
+ const kept = [];
119
+ for (let i = 0; i < lines.length; i++) {
120
+ const line = lines[i] ?? "";
121
+ if (QUOTED.test(line))
122
+ continue;
123
+ if (outlookAt(lines, i)) {
124
+ const last = kept.findLastIndex((one) => one.trim());
125
+ return last !== -1 && RULE.test((kept[last] ?? "").trim()) ? kept.slice(0, last) : kept;
126
+ }
127
+ const start = attributionAt(lines, i);
128
+ if (start === -1) {
129
+ kept.push(line);
130
+ continue;
131
+ }
132
+ if (start < i)
133
+ kept.pop();
134
+ if (QUOTED.test(nextText(lines, i + 1)))
135
+ continue;
136
+ // Without quote marks only a dated header is one: "Here is what Bob wrote:" is not.
137
+ const header = lines
138
+ .slice(start, i + 1)
139
+ .join(" ")
140
+ .trim();
141
+ if (/\d/.test(header) && (header.includes("@") || DATED.test(header)) && header.length <= 300)
142
+ return kept;
143
+ if (start < i)
144
+ kept.push(lines[start] ?? "");
145
+ kept.push(line);
146
+ }
147
+ return kept;
148
+ };
149
+ /**
150
+ * What an email says itself, for a model that should not read earlier mail or the sender's signature: no quoted
151
+ * lines, nothing after a reply or Outlook header, no signature or mobile footer. A forwarded message is kept whole,
152
+ * since it is what was sent. When nothing would be left — an email that is only a quote — the body stays as it is.
153
+ */
154
+ export const mailOwnText = (body) => {
155
+ const lines = body.replace(/\r\n?/g, "\n").split("\n");
156
+ const forward = lines.findIndex((line) => FORWARD.test(line.trim()));
157
+ const head = forward === -1 ? lines : lines.slice(0, forward);
158
+ const own = withoutSignOff(trimEdges(ownLines(head).filter((line) => !MOBILE.test(line.trim()))));
159
+ const text = [...own, ...(forward === -1 ? [] : ["", ...lines.slice(forward)])].join("\n").trim();
160
+ return text || body.trim();
161
+ };
@@ -1 +1,3 @@
1
1
  export declare const calendarKey: (zone: string, by: "day" | "hour") => (time: number) => string;
2
+ /** The Monday that starts the week of a `YYYY-MM-DD` day. */
3
+ export declare const weekKey: (day: string) => string;
@@ -11,3 +11,9 @@ export const calendarKey = (zone, by) => {
11
11
  return `${part.year}-${part.month}-${part.day}${by === "hour" ? `T${part.hour}` : ""}`;
12
12
  };
13
13
  };
14
+ /** The Monday that starts the week of a `YYYY-MM-DD` day. */
15
+ export const weekKey = (day) => {
16
+ const date = new Date(`${day}T00:00:00Z`);
17
+ date.setUTCDate(date.getUTCDate() - ((date.getUTCDay() + 6) % 7));
18
+ return date.toISOString().slice(0, 10);
19
+ };
@@ -62,14 +62,28 @@ export declare const chatStats: v.StrictObjectSchema<{
62
62
  readonly left: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
63
63
  }, undefined>, undefined>, undefined>;
64
64
  }, undefined>;
65
- /** Open and closed tasks, one row per chat. */
65
+ /**
66
+ * Open and closed tasks, one row per chat, meeting or project. `open` is open now; `created` and `closed` count the
67
+ * tasks opened and closed in the query's period, every task without one.
68
+ */
66
69
  export declare const taskStats: v.StrictObjectSchema<{
67
70
  /** Open tasks across every row. */
68
71
  readonly open: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
72
+ readonly created: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
73
+ readonly closed: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
74
+ readonly median_close_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
75
+ readonly mean_open_age_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
69
76
  readonly rows: v.ArraySchema<v.StrictObjectSchema<{
70
- readonly chat: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
77
+ /** Rows of `--by chat` only. */
78
+ readonly chat: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
79
+ /** The chat reference, `meeting:<account>/<meeting>` or `project:<id>`. */
80
+ readonly key: v.StringSchema<undefined>;
81
+ readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
71
82
  readonly open: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
83
+ readonly created: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
84
+ readonly closed: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
72
85
  readonly oldest_open_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
73
86
  readonly median_close_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
87
+ readonly mean_open_age_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
74
88
  }, undefined>, undefined>;
75
89
  }, undefined>;
@@ -54,14 +54,29 @@ export const chatStats = v.strictObject({
54
54
  })),
55
55
  series: v.optional(v.array(v.strictObject({ key: text, messages: count, senders: count, joined: optionalCount, left: optionalCount }))),
56
56
  });
57
- /** Open and closed tasks, one row per chat. */
57
+ const ms = v.nullable(v.pipe(v.number(), v.minValue(0)));
58
+ /**
59
+ * Open and closed tasks, one row per chat, meeting or project. `open` is open now; `created` and `closed` count the
60
+ * tasks opened and closed in the query's period, every task without one.
61
+ */
58
62
  export const taskStats = v.strictObject({
59
63
  /** Open tasks across every row. */
60
64
  open: count,
65
+ created: count,
66
+ closed: count,
67
+ median_close_ms: ms,
68
+ mean_open_age_ms: ms,
61
69
  rows: v.array(v.strictObject({
62
- chat: reference,
70
+ /** Rows of `--by chat` only. */
71
+ chat: v.optional(reference),
72
+ /** The chat reference, `meeting:<account>/<meeting>` or `project:<id>`. */
73
+ key: text,
74
+ name: v.nullable(text),
63
75
  open: count,
76
+ created: count,
77
+ closed: count,
64
78
  oldest_open_at: v.nullable(time),
65
- median_close_ms: v.nullable(v.pipe(v.number(), v.minValue(0))),
79
+ median_close_ms: ms,
80
+ mean_open_age_ms: ms,
66
81
  })),
67
82
  });