@wirecat/cli-template 0.8.0 → 0.10.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 (125) hide show
  1. package/.github/workflows/ci.yml +3 -3
  2. package/.github/workflows/release.yml +63 -0
  3. package/.gitleaks.toml +18 -0
  4. package/AGENTS.md +9 -15
  5. package/CHANGELOG.md +87 -1
  6. package/README.md +4 -3
  7. package/bin/release +5 -3
  8. package/contracts/plan.json +2 -2
  9. package/dist/bin/clidev.js +34 -12
  10. package/dist/bundle/all-profiles-XHC7BG3P.js +24 -0
  11. package/dist/bundle/anthropic-N6B3ZZHQ.js +70 -0
  12. package/dist/bundle/bun-HUJLS7KP.js +169 -0
  13. package/dist/bundle/bun-sqlite-OWFO2TVR.js +69 -0
  14. package/dist/bundle/chunk-222FANS2.js +161 -0
  15. package/dist/bundle/chunk-2CFBHYFA.js +884 -0
  16. package/dist/bundle/chunk-2KQZ24GI.js +82 -0
  17. package/dist/bundle/chunk-2TBVT4SZ.js +31 -0
  18. package/dist/bundle/chunk-437W3Z2M.js +76 -0
  19. package/dist/bundle/chunk-4QRLPOJ7.js +18 -0
  20. package/dist/bundle/chunk-54AJONOM.js +54 -0
  21. package/dist/bundle/chunk-5D4AEUVA.js +24783 -0
  22. package/dist/bundle/chunk-6CBWO7OF.js +73 -0
  23. package/dist/bundle/chunk-75LVQQEK.js +35782 -0
  24. package/dist/bundle/chunk-7RB76E2L.js +264 -0
  25. package/dist/bundle/chunk-7RXBN7HP.js +63 -0
  26. package/dist/bundle/chunk-ABP7FDMJ.js +122 -0
  27. package/dist/bundle/chunk-ADLS6FVG.js +24600 -0
  28. package/dist/bundle/chunk-AP7QKYBG.js +3531 -0
  29. package/dist/bundle/chunk-ASMH7JWZ.js +288 -0
  30. package/dist/bundle/chunk-B4EED2RF.js +100 -0
  31. package/dist/bundle/chunk-B4LM2B6F.js +1900 -0
  32. package/dist/bundle/chunk-BDSDQCV4.js +281 -0
  33. package/dist/bundle/chunk-DFDN6AUB.js +21 -0
  34. package/dist/bundle/chunk-DMCN22H6.js +35 -0
  35. package/dist/bundle/chunk-E42W72PQ.js +151 -0
  36. package/dist/bundle/chunk-EFHLQXG6.js +5104 -0
  37. package/dist/bundle/chunk-FIHDGZIB.js +34352 -0
  38. package/dist/bundle/chunk-FWVKHD2L.js +48 -0
  39. package/dist/bundle/chunk-FXS3X76A.js +193 -0
  40. package/dist/bundle/chunk-HTQTIKWP.js +928 -0
  41. package/dist/bundle/chunk-IJ3IA7EK.js +24 -0
  42. package/dist/bundle/chunk-JEBSORH7.js +3379 -0
  43. package/dist/bundle/chunk-JTTW5ZKF.js +45 -0
  44. package/dist/bundle/chunk-LSEF4QC3.js +3075 -0
  45. package/dist/bundle/chunk-LY7GS2YI.js +58 -0
  46. package/dist/bundle/chunk-MFS52LTZ.js +570 -0
  47. package/dist/bundle/chunk-MNSD5BX2.js +78 -0
  48. package/dist/bundle/chunk-MTGLJCAZ.js +24 -0
  49. package/dist/bundle/chunk-MZVV2JZT.js +744 -0
  50. package/dist/bundle/chunk-NE3NSB5O.js +8341 -0
  51. package/dist/bundle/chunk-NTLPDH76.js +440 -0
  52. package/dist/bundle/chunk-O3PBQVAB.js +447 -0
  53. package/dist/bundle/chunk-O5EHUB2V.js +2 -0
  54. package/dist/bundle/chunk-O5LMDQTO.js +82 -0
  55. package/dist/bundle/chunk-OPJ24VGH.js +1028 -0
  56. package/dist/bundle/chunk-OPPMGPFW.js +164 -0
  57. package/dist/bundle/chunk-QGNNMPUB.js +158 -0
  58. package/dist/bundle/chunk-QVJLOUQB.js +2 -0
  59. package/dist/bundle/chunk-S57AMKLX.js +6848 -0
  60. package/dist/bundle/chunk-TARN7CHN.js +215 -0
  61. package/dist/bundle/chunk-TJLGI3N6.js +1095 -0
  62. package/dist/bundle/chunk-VMTM46FH.js +7532 -0
  63. package/dist/bundle/chunk-W2IDKBNB.js +2315 -0
  64. package/dist/bundle/chunk-XFXBXQBS.js +630 -0
  65. package/dist/bundle/chunk-Y5E2WNWB.js +35 -0
  66. package/dist/bundle/chunk-ZVVMGPBJ.js +50 -0
  67. package/dist/bundle/clidev.js +22 -0
  68. package/dist/bundle/command-contract-PEM3S634.js +29 -0
  69. package/dist/bundle/dist-ESHIQU4M.js +7577 -0
  70. package/dist/bundle/echarts-2QGL2JP5.js +42501 -0
  71. package/dist/bundle/embed-HHAAGHA6.js +35 -0
  72. package/dist/bundle/embedder-W2OGVVYH.js +108 -0
  73. package/dist/bundle/first-run-WCJUDUBU.js +23 -0
  74. package/dist/bundle/first-screen-U4DFUKUC.js +27 -0
  75. package/dist/bundle/instructions-OTZHT6NV.js +9 -0
  76. package/dist/bundle/mcp-OQBZXELQ.js +165 -0
  77. package/dist/bundle/mcp-VVF6J7SQ.js +151 -0
  78. package/dist/bundle/mcp-Y7VCIZ2J.js +78 -0
  79. package/dist/bundle/node-P4E63KXA.js +2340 -0
  80. package/dist/bundle/node-SYD4GX5O.js +176 -0
  81. package/dist/bundle/node-TLZSIHIJ.js +21 -0
  82. package/dist/bundle/node-sqlite-X2DGRFOZ.js +45 -0
  83. package/dist/bundle/oauth-42M34GQ5.js +17 -0
  84. package/dist/bundle/open-SWXRCDLN.js +19 -0
  85. package/dist/bundle/process-KAFGXZ7Q.js +91 -0
  86. package/dist/bundle/program-EHR4G7VN.js +16967 -0
  87. package/dist/bundle/prompt-ZQTMHRGX.js +12 -0
  88. package/dist/bundle/recognize-TTED4SE3.js +190 -0
  89. package/dist/bundle/remote-C37XJ4BP.js +26 -0
  90. package/dist/bundle/rerank-APFZAMQL.js +49 -0
  91. package/dist/bundle/serve-DDPIHDVZ.js +19 -0
  92. package/dist/bundle/server-L5GNG7KC.js +793 -0
  93. package/dist/bundle/server-LKVYA2AE.js +39 -0
  94. package/dist/bundle/state-WWPPHERF.js +33 -0
  95. package/dist/bundle/store-H6UIA4PK.js +120 -0
  96. package/dist/bundle/store-maintenance-command-EYBT64A2.js +40 -0
  97. package/dist/commands/mcp.d.ts.map +1 -1
  98. package/dist/commands/mcp.js +45 -30
  99. package/dist/commands/mcp.js.map +1 -1
  100. package/dist/version.d.ts +1 -1
  101. package/dist/version.d.ts.map +1 -1
  102. package/dist/version.js +1 -1
  103. package/dist/version.js.map +1 -1
  104. package/docs/commands.md +38 -22
  105. package/docs/dev/TESTING.md +14 -3
  106. package/docs/dev/reference-clis.md +17 -9
  107. package/docs/dev/skills/release/SKILL.md +9 -6
  108. package/docs/dev/skills/release/fresh-audit.md +4 -0
  109. package/docs/dev/test-matrix.md +10 -11
  110. package/docs/security.md +4 -0
  111. package/docs/usage.md +7 -6
  112. package/kit/dist/new.js +17 -2
  113. package/package.json +7 -5
  114. package/scripts/audit.sh +5 -3
  115. package/scripts/smoke-bundle.ts +63 -0
  116. package/scripts/test-matrix-untested.ts +4 -10
  117. package/scripts/version-level.test.ts +17 -1
  118. package/scripts/version-level.ts +35 -7
  119. package/skills/clidev-cli/SKILL.md +8 -0
  120. package/src/commands/mcp.ts +54 -33
  121. package/src/mcp-http.test.ts +20 -13
  122. package/src/mcp.test.ts +3 -3
  123. package/src/program.test.ts +8 -2
  124. package/src/roots.test.ts +2 -7
  125. package/src/version.ts +1 -1
@@ -0,0 +1,3075 @@
1
+ import { createRequire as __bundleRequire } from "node:module";
2
+ const require = __bundleRequire(import.meta.url);
3
+ import {
4
+ CliError,
5
+ RegistryError,
6
+ SNAKE_CASE,
7
+ STEPS,
8
+ array,
9
+ boolean,
10
+ defineReasons,
11
+ defineSteps,
12
+ duplicates,
13
+ integer,
14
+ isCliError,
15
+ isoTime,
16
+ lazy,
17
+ literal,
18
+ maxValue,
19
+ minLength,
20
+ minValue,
21
+ nullable,
22
+ number,
23
+ object,
24
+ optional,
25
+ pageSchema,
26
+ picklist,
27
+ pipe,
28
+ reference,
29
+ safeParse,
30
+ singleLine,
31
+ stepOf,
32
+ strictObject,
33
+ string,
34
+ union,
35
+ variant,
36
+ visibleControls
37
+ } from "./chunk-EFHLQXG6.js";
38
+ import {
39
+ __name
40
+ } from "./chunk-ZVVMGPBJ.js";
41
+
42
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/types.js
43
+ var QUERY_LIMITS = {
44
+ bytes: 8192,
45
+ depth: 32,
46
+ nodes: 256
47
+ };
48
+ var spanSchema = object({ start: number(), end: number() });
49
+ var predicateSchema = object({
50
+ kind: literal("predicate"),
51
+ field: string(),
52
+ operator: picklist(["term", "phrase", "wildcard", "regex", "range"]),
53
+ value: string(),
54
+ upper: optional(string()),
55
+ lower_inclusive: optional(boolean()),
56
+ upper_inclusive: optional(boolean()),
57
+ span: spanSchema,
58
+ implicit: optional(literal(true)),
59
+ slop: optional(pipe(number(), integer(), minValue(0)))
60
+ });
61
+ var queryNodeSchema = variant("kind", [
62
+ predicateSchema,
63
+ object({
64
+ kind: literal("boolean"),
65
+ clauses: array(object({ occur: picklist(["must", "should", "must_not"]), node: lazy(() => queryNodeSchema) })),
66
+ span: spanSchema
67
+ })
68
+ ]);
69
+ var queryAstSchema = object({
70
+ version: literal(1),
71
+ language: literal("lucene-v1"),
72
+ root: queryNodeSchema
73
+ });
74
+ function queryError(reason, span, alternative, context3 = {}, details = {}) {
75
+ throw new CliError("validation_error", `${context3.command ?? "query"}: ${reason} at position ${span.start + 1}${alternative ? ` \u2014 ${alternative}` : ""}`, {
76
+ reason,
77
+ span,
78
+ ...alternative ? { alternative } : {},
79
+ ...context3.guide ? { guide: context3.guide } : {},
80
+ ...details
81
+ });
82
+ }
83
+ __name(queryError, "queryError");
84
+ var walkQuery = /* @__PURE__ */ __name((node) => node.kind === "predicate" ? [node] : node.clauses.flatMap(({ node: node2 }) => walkQuery(node2)), "walkQuery");
85
+
86
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/dates.js
87
+ var timezoneOf = /* @__PURE__ */ __name((given) => {
88
+ const zone = given ?? Intl.DateTimeFormat().resolvedOptions().timeZone ?? "UTC";
89
+ try {
90
+ new Intl.DateTimeFormat("en", { timeZone: zone }).format(0);
91
+ } catch {
92
+ queryError("query.invalid-timezone", { start: 0, end: 0 }, "use an IANA timezone such as Europe/Madrid");
93
+ }
94
+ return zone;
95
+ }, "timezoneOf");
96
+ var calendar = /* @__PURE__ */ __name((value, span) => {
97
+ if (!/^\d{4}-\d{2}-\d{2}$/u.test(value))
98
+ queryError("query.invalid-date", span, "use an ISO date or a quoted timestamp with offset");
99
+ const year = Number(value.slice(0, 4)), month = Number(value.slice(5, 7)), day = Number(value.slice(8, 10));
100
+ const date = /* @__PURE__ */ new Date(0);
101
+ date.setUTCFullYear(year, month - 1, day);
102
+ date.setUTCHours(0, 0, 0, 0);
103
+ if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day)
104
+ queryError("query.invalid-date", span);
105
+ return date;
106
+ }, "calendar");
107
+ var dayBoundary = /* @__PURE__ */ __name((value, zone, next, span) => {
108
+ const date = calendar(value, span);
109
+ if (next)
110
+ date.setUTCDate(date.getUTCDate() + 1);
111
+ const wanted = date.getUTCFullYear() * 1e4 + (date.getUTCMonth() + 1) * 100 + date.getUTCDate();
112
+ const formatter = new Intl.DateTimeFormat("en-CA", {
113
+ timeZone: zone,
114
+ year: "numeric",
115
+ month: "2-digit",
116
+ day: "2-digit",
117
+ era: "short"
118
+ });
119
+ const dayAt = /* @__PURE__ */ __name((time) => {
120
+ const parts = formatter.formatToParts(time);
121
+ const value2 = /* @__PURE__ */ __name((name) => Number(parts.find((p) => p.type === name)?.value), "value");
122
+ const year = parts.find((p) => p.type === "era")?.value === "BC" ? 1 - value2("year") : value2("year");
123
+ return year * 1e4 + value2("month") * 100 + value2("day");
124
+ }, "dayAt");
125
+ let lo = date.getTime() - 2 * 864e5, hi = date.getTime() + 2 * 864e5;
126
+ while (lo < hi) {
127
+ const mid = Math.floor((lo + hi) / 2);
128
+ if (dayAt(mid) < wanted)
129
+ lo = mid + 1;
130
+ else
131
+ hi = mid;
132
+ }
133
+ if (dayAt(lo) !== wanted)
134
+ queryError("query.invalid-date", span, "this calendar day does not exist in the selected timezone");
135
+ return lo;
136
+ }, "dayBoundary");
137
+ var WALL = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/u;
138
+ var wallTime = /* @__PURE__ */ __name((value, zone, span) => {
139
+ const [, year, month, day, hour, minute, second = "0", fraction = "0"] = WALL.exec(value) ?? [];
140
+ if (year === void 0)
141
+ queryError("query.invalid-date", span, "use YYYY-MM-DDTHH:mm, with optional seconds");
142
+ const wanted = Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hour), Number(minute), Number(second), Number(fraction.padEnd(3, "0")));
143
+ const check = new Date(wanted);
144
+ if (check.getUTCDate() !== Number(day) || check.getUTCHours() !== Number(hour) || check.getUTCMinutes() !== Number(minute) || check.getUTCSeconds() !== Number(second))
145
+ queryError("query.invalid-date", span);
146
+ const formatter = new Intl.DateTimeFormat("en-CA", {
147
+ timeZone: zone,
148
+ year: "numeric",
149
+ month: "2-digit",
150
+ day: "2-digit",
151
+ hour: "2-digit",
152
+ minute: "2-digit",
153
+ second: "2-digit",
154
+ hourCycle: "h23"
155
+ });
156
+ const shown = /* @__PURE__ */ __name((instant) => {
157
+ const parts = Object.fromEntries(formatter.formatToParts(instant).map((part) => [part.type, Number(part.value)]));
158
+ return Date.UTC(parts.year ?? 0, (parts.month ?? 1) - 1, parts.day, parts.hour, parts.minute, parts.second) + (instant % 1e3 + 1e3) % 1e3;
159
+ }, "shown");
160
+ const found = /* @__PURE__ */ new Set();
161
+ for (const probe of [wanted - 864e5, wanted, wanted + 864e5]) {
162
+ const candidate = wanted - (shown(probe) - probe);
163
+ if (shown(candidate) === wanted)
164
+ found.add(candidate);
165
+ }
166
+ if (found.size !== 1)
167
+ queryError("query.invalid-date", span, "this local time is skipped or repeated by daylight saving; add an offset");
168
+ return [...found][0];
169
+ }, "wallTime");
170
+ var ZONED = /(?:Z|[+-]\d{2}:?\d{2})$/iu;
171
+ var zonedMoment = /* @__PURE__ */ __name((value, zone, span, { end = false } = {}) => {
172
+ if (/^\d{4}-\d{2}-\d{2}$/u.test(value))
173
+ return dayBoundary(value, zone, end, span) - (end ? 1 : 0);
174
+ if (!ZONED.test(value))
175
+ return wallTime(value, zone, span);
176
+ const time = Date.parse(value);
177
+ if (!/^\d{4}-\d{2}-\d{2}T/u.test(value) || !Number.isFinite(time))
178
+ queryError("query.invalid-date", span);
179
+ calendar(value.slice(0, 10), span);
180
+ return time;
181
+ }, "zonedMoment");
182
+ var AGO = /^(\d+)(m|h|d)$/u;
183
+ var AGO_MS = { m: 6e4, h: 36e5, d: 864e5 };
184
+ var dayOf = /* @__PURE__ */ __name((word, zone, now, span) => {
185
+ const today = new Intl.DateTimeFormat("en-CA", {
186
+ timeZone: zone,
187
+ year: "numeric",
188
+ month: "2-digit",
189
+ day: "2-digit"
190
+ }).format(now);
191
+ if (word === "today")
192
+ return today;
193
+ const date = calendar(today, span);
194
+ date.setUTCDate(date.getUTCDate() - 1);
195
+ return date.toISOString().slice(0, 10);
196
+ }, "dayOf");
197
+ var dateEndpoint = /* @__PURE__ */ __name((value, zone, side, inclusive, span, now = Date.now()) => {
198
+ if (value === "*")
199
+ return { inclusive };
200
+ const word = value.toLowerCase();
201
+ if (word === "today" || word === "yesterday")
202
+ return dateEndpoint(dayOf(word, zone, now, span), zone, side, inclusive, span);
203
+ const [, amount, unit] = AGO.exec(word) ?? [];
204
+ if (amount && unit)
205
+ return { time: now - Number(amount) * (AGO_MS[unit] ?? 0), inclusive };
206
+ if (/^\d{4}-\d{2}-\d{2}$/u.test(value))
207
+ return {
208
+ time: dayBoundary(value, zone, side === "lower" ? !inclusive : inclusive, span),
209
+ inclusive: side === "lower"
210
+ };
211
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/u.test(value))
212
+ queryError("query.invalid-date", span, "use an ISO date, today, yesterday, 30m/2h/7d ago, or a quoted timestamp with offset");
213
+ calendar(value.slice(0, 10), span);
214
+ const time = Date.parse(value);
215
+ if (!Number.isFinite(time) || Number(value.slice(11, 13)) > 23 || Number(value.slice(14, 16)) > 59 || Number(value.slice(17, 19)) > 59)
216
+ queryError("query.invalid-date", span);
217
+ return { time, inclusive };
218
+ }, "dateEndpoint");
219
+ var dateRange = /* @__PURE__ */ __name((lower, upper, lowerInclusive, upperInclusive, zone, span, now = Date.now()) => {
220
+ const since = lower === upper && AGO.test(lower.toLowerCase());
221
+ const lo = dateEndpoint(lower, zone, "lower", lowerInclusive, span, now);
222
+ const hi = dateEndpoint(since ? "*" : upper, zone, "upper", upperInclusive, span, now);
223
+ return {
224
+ ...lo.time === void 0 ? {} : { lower: lo.time },
225
+ ...hi.time === void 0 ? {} : { upper: hi.time },
226
+ lower_inclusive: lo.inclusive,
227
+ upper_inclusive: hi.inclusive
228
+ };
229
+ }, "dateRange");
230
+
231
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/fields.js
232
+ var FIELD_TYPES = ["kw", "txt", "enum", "num", "time", "bool", "ref"];
233
+ var OPERATORS_BY_TYPE = {
234
+ kw: ["term", "phrase", "wildcard"],
235
+ txt: ["term", "phrase", "wildcard"],
236
+ enum: ["term"],
237
+ num: ["term", "range"],
238
+ time: ["term", "range"],
239
+ bool: ["term"],
240
+ ref: ["term", "phrase"]
241
+ };
242
+ var QUERY_BACKENDS = ["sql", "native"];
243
+ var unwrap = /* @__PURE__ */ __name((schema) => schema.wrapped ? unwrap(schema.wrapped) : schema, "unwrap");
244
+ var REFERENCE_SOURCE = reference.pipe[1].requirement.source;
245
+ var typeOf = /* @__PURE__ */ __name((schema) => {
246
+ const plain = unwrap(schema);
247
+ const actions = plain.pipe ?? [];
248
+ switch (plain.type) {
249
+ case "picklist":
250
+ return { type: "enum", values: (plain.options ?? []).map(String) };
251
+ case "number":
252
+ return { type: "num" };
253
+ case "boolean":
254
+ return { type: "bool" };
255
+ case "string":
256
+ if (actions.some((action) => action.type === "iso_timestamp"))
257
+ return { type: "time" };
258
+ if (actions.some((action) => action.requirement instanceof RegExp && action.requirement.source === REFERENCE_SOURCE))
259
+ return { type: "ref" };
260
+ return { type: "kw" };
261
+ case "array":
262
+ return plain.item ? typeOf(plain.item) : void 0;
263
+ default:
264
+ return void 0;
265
+ }
266
+ }, "typeOf");
267
+ var exampleOf = /* @__PURE__ */ __name((name, type, values) => ({
268
+ kw: `${name}:abc`,
269
+ txt: `${name}:word*`,
270
+ enum: `${name}:${values?.[0] ?? "x"}`,
271
+ num: `${name}>0`,
272
+ time: `${name}>=7d`,
273
+ bool: `${name}:true`,
274
+ ref: `${name}:"note:42"`
275
+ })[type], "exampleOf");
276
+ var queryFieldsOf = /* @__PURE__ */ __name((schema, annotations = {}) => {
277
+ const entries = unwrap(schema).entries ?? {};
278
+ const excluded = new Set(annotations.exclude ?? []);
279
+ const words2 = new Set(annotations.text ?? []);
280
+ const native = new Set(annotations.native ?? []);
281
+ const finish = /* @__PURE__ */ __name((field) => ({
282
+ ...field,
283
+ operators: OPERATORS_BY_TYPE[field.type],
284
+ example: annotations.examples?.[field.name] ?? field.example ?? exampleOf(field.name, field.type, field.values),
285
+ ...native.has(field.name) ? { native: true } : {},
286
+ ...annotations.validate?.[field.name] ? { validate: annotations.validate[field.name] } : {}
287
+ }), "finish");
288
+ const own = Object.entries(entries).flatMap(([name, entry]) => {
289
+ if (excluded.has(name))
290
+ return [];
291
+ const found = typeOf(entry);
292
+ if (!found)
293
+ return [];
294
+ return [finish({ name, ...found, ...words2.has(name) && found.type === "kw" ? { type: "txt" } : {} })];
295
+ });
296
+ const relations = Object.entries(annotations.relations ?? {}).map(([name, relation]) => finish({ name, ...relation }));
297
+ const states = annotations.states ? [
298
+ finish({
299
+ name: "is",
300
+ type: "enum",
301
+ values: Object.keys(annotations.states),
302
+ relation: Object.entries(annotations.states).map(([state, meaning]) => `${state}: ${meaning}`).join("; ")
303
+ })
304
+ ] : [];
305
+ return [...own, ...relations, ...states];
306
+ }, "queryFieldsOf");
307
+
308
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/validate.js
309
+ var inContext = /* @__PURE__ */ __name((context3, run2) => {
310
+ try {
311
+ run2();
312
+ } catch (failure) {
313
+ if (!isCliError(failure) || typeof failure.details.reason !== "string" || failure.details.span === void 0)
314
+ throw failure;
315
+ const { reason, span, alternative } = failure.details;
316
+ queryError(reason, span, alternative, context3);
317
+ }
318
+ }, "inContext");
319
+ var bounds = /* @__PURE__ */ __name((node) => node.operator === "range" ? [node.value, node.upper ?? "*"].filter((bound) => bound !== "*") : [node.value], "bounds");
320
+ var checkValue = /* @__PURE__ */ __name((field, node, options) => {
321
+ const fail = /* @__PURE__ */ __name((reason, alternative) => queryError(reason, node.span, alternative, options), "fail");
322
+ if (node.value === "" && field.type !== "txt")
323
+ fail("query.missing-value");
324
+ if (node.operator === "wildcard")
325
+ return;
326
+ switch (field.type) {
327
+ case "enum":
328
+ if (!field.values?.includes(node.value.toLowerCase()))
329
+ fail("query.unknown-value", `${field.name} takes ${field.values?.join(", ")}`);
330
+ return;
331
+ case "bool":
332
+ if (!["true", "false"].includes(node.value.toLowerCase()))
333
+ fail("query.unknown-value", `${field.name} takes true, false`);
334
+ return;
335
+ case "num":
336
+ for (const bound of bounds(node))
337
+ if (!Number.isFinite(Number(bound)) || bound.trim() === "")
338
+ fail("query.invalid-number", `${field.name} takes a number`);
339
+ return;
340
+ case "time":
341
+ inContext(options, () => {
342
+ for (const bound of bounds(node))
343
+ dateEndpoint(bound, options.zone ?? "UTC", "lower", true, node.span);
344
+ });
345
+ return;
346
+ default:
347
+ return;
348
+ }
349
+ }, "checkValue");
350
+ var validateQuery = /* @__PURE__ */ __name((ast, registry, options = {}) => {
351
+ const byName = new Map(registry.fields.map((field) => [field.name, field]));
352
+ const visit = /* @__PURE__ */ __name((node, required) => {
353
+ if (node.kind === "boolean") {
354
+ for (const clause of node.clauses)
355
+ visit(clause.node, required && clause.occur === "must");
356
+ return;
357
+ }
358
+ const field = byName.get(node.field);
359
+ if (!field)
360
+ queryError("query.unknown-field", node.span, `no field "${node.field}"`, options, {
361
+ fields: registry.fields.map((one) => one.name)
362
+ });
363
+ if (registry.backend === "native" && !field.native)
364
+ queryError("query.unsupported-field", node.span, `the source cannot filter by ${field.name}`, options, {
365
+ supported: registry.fields.filter((one) => one.native).map((one) => one.name)
366
+ });
367
+ const presence = node.operator === "wildcard" && node.value === "*";
368
+ if (!presence && !field.operators.includes(node.operator))
369
+ queryError("query.unsupported-operator", node.span, `${field.name} takes ${field.operators.join(", ")}`, options);
370
+ if (field.placement === "and" && !required)
371
+ queryError("query.unsupported-placement", node.span, `${field.name} only as a required term, not under OR or NOT`, options);
372
+ if (presence)
373
+ return;
374
+ checkValue(field, node, options);
375
+ if (field.validate)
376
+ inContext(options, () => field.validate?.(node));
377
+ }, "visit");
378
+ visit(ast.root, true);
379
+ return ast;
380
+ }, "validateQuery");
381
+ var fieldsNamed = /* @__PURE__ */ __name((ast) => new Set(walkQuery(ast.root).map((node) => node.field)), "fieldsNamed");
382
+
383
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/parser.js
384
+ var whitespace = /* @__PURE__ */ __name((c) => /[ \t\n\r\u3000]/u.test(c), "whitespace");
385
+ var reserved = /* @__PURE__ */ new Set([
386
+ "+",
387
+ "-",
388
+ "!",
389
+ "(",
390
+ ")",
391
+ ":",
392
+ "=",
393
+ "^",
394
+ "@",
395
+ "<",
396
+ ">",
397
+ "[",
398
+ "]",
399
+ '"',
400
+ "{",
401
+ "}",
402
+ "~",
403
+ "\\",
404
+ "/"
405
+ ]);
406
+ var decodeEscapes = /* @__PURE__ */ __name((raw, span, fail) => {
407
+ let out = "";
408
+ for (let at = 0; at < raw.length; at++) {
409
+ if (raw[at] !== "\\") {
410
+ out += raw[at];
411
+ continue;
412
+ }
413
+ if (++at >= raw.length)
414
+ fail("query.invalid-escape", span);
415
+ if (raw[at] === "u") {
416
+ const hex = raw.slice(at + 1, at + 5);
417
+ if (!/^[0-9a-fA-F]{4}$/.test(hex))
418
+ fail("query.invalid-escape", span);
419
+ out += String.fromCharCode(Number.parseInt(hex, 16));
420
+ at += 4;
421
+ } else
422
+ out += raw[at];
423
+ }
424
+ return out;
425
+ }, "decodeEscapes");
426
+ var tokensOf = /* @__PURE__ */ __name((text6, fail = queryError) => {
427
+ const tokens = [];
428
+ let at = 0;
429
+ let range = false;
430
+ while (at < text6.length) {
431
+ const start = at;
432
+ const c = text6[at] ?? "";
433
+ if (whitespace(c)) {
434
+ at++;
435
+ continue;
436
+ }
437
+ let kind = c;
438
+ if (c === '"' || !range && c === "/") {
439
+ at++;
440
+ while (at < text6.length && text6[at] !== c) {
441
+ if (text6[at] === "\\" && (c === '"' || text6[at + 1] === "/"))
442
+ at++;
443
+ at++;
444
+ }
445
+ if (at >= text6.length)
446
+ fail("query.unclosed-literal", { start, end: at }, c === "/" ? regexHint(text6, start) : void 0);
447
+ at++;
448
+ if (c === "/" && /^[dgimsuvy]+(?:$|[ \t\n\r)])/.test(text6.slice(at)))
449
+ fail("query.unsupported-regex-flags", { start: at, end: at + 1 }, "Lucene regex does not take JavaScript flags");
450
+ kind = c === '"' ? "quoted" : "regex";
451
+ } else if (range && c !== "]" && c !== "}") {
452
+ while (at < text6.length && !whitespace(text6[at] ?? "") && !["]", "}"].includes(text6[at] ?? ""))
453
+ at++;
454
+ kind = "rangeValue";
455
+ } else if (reserved.has(c)) {
456
+ if (c === "\\") {
457
+ at += 2;
458
+ while (at < text6.length && !whitespace(text6[at] ?? "") && (!reserved.has(text6[at] ?? "") || ["+", "-"].includes(text6[at] ?? "")))
459
+ at++;
460
+ kind = "term";
461
+ } else {
462
+ at++;
463
+ if ((c === "<" || c === ">") && text6[at] === "=") {
464
+ at++;
465
+ kind += "=";
466
+ }
467
+ if (c === "[" || c === "{")
468
+ range = true;
469
+ if (c === "]" || c === "}")
470
+ range = false;
471
+ }
472
+ } else {
473
+ at++;
474
+ while (at < text6.length) {
475
+ const next = text6[at] ?? "";
476
+ if (next === "\\") {
477
+ if (at + 1 >= text6.length)
478
+ fail("query.invalid-escape", { start: at, end: at + 1 });
479
+ at += 2;
480
+ continue;
481
+ }
482
+ if (next === "@" && new RegExp("^@(?:\\p{L}|[\\p{L}\\p{N}][^\\s@]*\\.[\\p{L}\\p{N}])", "u").test(text6.slice(at))) {
483
+ at++;
484
+ continue;
485
+ }
486
+ if (whitespace(next) || reserved.has(next) && next !== "+" && next !== "-")
487
+ break;
488
+ at++;
489
+ }
490
+ const raw = text6.slice(start, at);
491
+ kind = { AND: "AND", OR: "OR", NOT: "NOT", "&&": "AND", "||": "OR" }[raw] ?? (/^\d+(?:\.\d+)?$/u.test(raw) ? "number" : "term");
492
+ }
493
+ tokens.push({ kind, raw: text6.slice(start, at), span: { start, end: at } });
494
+ }
495
+ tokens.push({ kind: "EOF", raw: "", span: { start: at, end: at } });
496
+ return tokens;
497
+ }, "tokensOf");
498
+ var quoteHint = /* @__PURE__ */ __name((text6, at) => {
499
+ for (const match of text6.matchAll(/(?<=^|[\s(])([\p{L}\p{N}_.-]+):([^\s"()]+)/gu)) {
500
+ const [whole, field, value = ""] = match;
501
+ if (at < match.index || at > match.index + whole.length)
502
+ continue;
503
+ return /[:=/?*~^@<>![\]{}\\]/u.test(value) ? `put the value in quotes: ${field}:"${value}"` : void 0;
504
+ }
505
+ return void 0;
506
+ }, "quoteHint");
507
+ var regexHint = /* @__PURE__ */ __name((text6, at) => {
508
+ const word = `${/[^\s()"]*$/u.exec(text6.slice(0, at))?.[0] ?? ""}${/^[^\s()"]*/u.exec(text6.slice(at))?.[0] ?? ""}`;
509
+ return quoteHint(text6, at) ?? `/ starts a regular expression; put the value in quotes: "${word}"`;
510
+ }, "regexHint");
511
+ var parseLucene = /* @__PURE__ */ __name((text6, { defaultField = "text", proximity = false, ...context3 } = {}) => {
512
+ const fail = /* @__PURE__ */ __name((reason, span, alternative) => queryError(reason, span, alternative ?? quoteHint(text6, span.start), context3), "fail");
513
+ if (text6.length > QUERY_LIMITS.bytes || new TextEncoder().encode(text6).length > QUERY_LIMITS.bytes)
514
+ fail("query.too-large", { start: 0, end: text6.length });
515
+ const tokens = tokensOf(text6, fail);
516
+ let at = 0;
517
+ let count6 = 0;
518
+ let depth = 0;
519
+ const peek = /* @__PURE__ */ __name(() => tokens[at], "peek");
520
+ const take = /* @__PURE__ */ __name(() => tokens[at++], "take");
521
+ const expect = /* @__PURE__ */ __name((kind) => {
522
+ if (peek().kind !== kind)
523
+ fail("query.invalid-syntax", peek().span);
524
+ return take();
525
+ }, "expect");
526
+ const built = /* @__PURE__ */ __name((node) => {
527
+ if (++count6 > QUERY_LIMITS.nodes)
528
+ fail("query.too-large", node.span);
529
+ return node;
530
+ }, "built");
531
+ const combine = /* @__PURE__ */ __name((clauses, occur) => {
532
+ const first = clauses[0];
533
+ const last = clauses.at(-1);
534
+ if (!first || !last)
535
+ fail("query.invalid-syntax", peek().span);
536
+ if (clauses.length === 1)
537
+ return first;
538
+ return {
539
+ node: built({
540
+ kind: "boolean",
541
+ clauses: clauses.map(({ node, modifier }) => ({ node, occur: modifier ?? occur })),
542
+ span: { start: first.node.span.start, end: last.node.span.end }
543
+ })
544
+ };
545
+ }, "combine");
546
+ const query = /* @__PURE__ */ __name((field, implicit = false) => {
547
+ if (++depth > QUERY_LIMITS.depth)
548
+ fail("query.too-large", peek().span);
549
+ const clauses = [];
550
+ do {
551
+ clauses.push(disjunction(field, implicit));
552
+ } while (!["EOF", ")"].includes(peek().kind));
553
+ const result = combine(clauses, "must");
554
+ depth--;
555
+ if (result.modifier === "must_not")
556
+ return built({ kind: "boolean", clauses: [{ node: result.node, occur: "must_not" }], span: result.node.span });
557
+ return result.node;
558
+ }, "query");
559
+ const disjunction = /* @__PURE__ */ __name((field, implicit) => {
560
+ const clauses = [conjunction(field, implicit)];
561
+ while (peek().kind === "OR") {
562
+ take();
563
+ clauses.push(conjunction(field, implicit));
564
+ }
565
+ return combine(clauses, "should");
566
+ }, "disjunction");
567
+ const conjunction = /* @__PURE__ */ __name((field, implicit) => {
568
+ const clauses = [clause(field, implicit)];
569
+ while (peek().kind === "AND") {
570
+ take();
571
+ clauses.push(clause(field, implicit));
572
+ }
573
+ return combine(clauses, "must");
574
+ }, "conjunction");
575
+ const clause = /* @__PURE__ */ __name((inherited, inheritedImplicit) => {
576
+ let modifier;
577
+ if (["+", "-", "NOT", "!"].includes(peek().kind))
578
+ modifier = take().kind === "+" ? "must" : "must_not";
579
+ let field = inherited;
580
+ let start;
581
+ let implicit = inheritedImplicit;
582
+ if (peek().kind === "term" && [":", "=", "<", ">", "<=", ">="].includes(tokens[at + 1]?.kind ?? "")) {
583
+ const token = take();
584
+ field = decodeEscapes(token.raw, token.span, fail);
585
+ start = token.span.start;
586
+ implicit = false;
587
+ let operator = take();
588
+ if (operator.kind === ":" && ["<", ">", "<=", ">="].includes(peek().kind))
589
+ operator = take();
590
+ if (["<", ">", "<=", ">="].includes(operator.kind)) {
591
+ const value = take();
592
+ if (!["term", "number", "quoted"].includes(value.kind))
593
+ fail("query.invalid-syntax", value.span);
594
+ const decoded = decodeEscapes(value.kind === "quoted" ? value.raw.slice(1, -1) : value.raw, value.span, fail);
595
+ const lower = operator.kind.startsWith(">");
596
+ const node2 = built({
597
+ kind: "predicate",
598
+ field,
599
+ operator: "range",
600
+ value: lower ? decoded : "*",
601
+ upper: lower ? "*" : decoded,
602
+ lower_inclusive: !lower || operator.kind.endsWith("="),
603
+ upper_inclusive: lower || operator.kind.endsWith("="),
604
+ span: { start: token.span.start, end: value.span.end }
605
+ });
606
+ return { node: node2, ...modifier ? { modifier } : {} };
607
+ }
608
+ }
609
+ let node;
610
+ if (peek().kind === "(") {
611
+ const start2 = take().span.start;
612
+ node = query(field, implicit);
613
+ const end = expect(")").span.end;
614
+ node = { ...node, span: { start: start2, end } };
615
+ } else if (["[", "{"].includes(peek().kind)) {
616
+ const opening = take();
617
+ const lower = take();
618
+ if (!["rangeValue", "quoted"].includes(lower.kind))
619
+ fail("query.invalid-syntax", lower.span);
620
+ const separator = take();
621
+ if (separator.raw !== "TO")
622
+ fail("query.invalid-syntax", separator.span);
623
+ const upper = take();
624
+ if (!["rangeValue", "quoted"].includes(upper.kind))
625
+ fail("query.invalid-syntax", upper.span);
626
+ const closing = take();
627
+ if (!["]", "}"].includes(closing.kind))
628
+ fail("query.invalid-syntax", closing.span);
629
+ const decode = /* @__PURE__ */ __name((t) => decodeEscapes(t.kind === "quoted" ? t.raw.slice(1, -1) : t.raw, t.span, fail), "decode");
630
+ node = built({
631
+ kind: "predicate",
632
+ field,
633
+ operator: "range",
634
+ value: decode(lower),
635
+ upper: decode(upper),
636
+ lower_inclusive: opening.kind === "[",
637
+ upper_inclusive: closing.kind === "]",
638
+ span: { start: start ?? opening.span.start, end: closing.span.end }
639
+ });
640
+ } else {
641
+ const token = take();
642
+ if (!["term", "number", "quoted", "regex"].includes(token.kind))
643
+ fail("query.invalid-syntax", token.span);
644
+ const raw = ["term", "number"].includes(token.kind) ? token.raw : token.raw.slice(1, -1);
645
+ if (field === "fn")
646
+ fail("query.unsupported-operator", token.span, "interval functions are not supported");
647
+ const wildcard = ["term", "number"].includes(token.kind) && /(?<!\\)[*?]/u.test(raw);
648
+ node = built({
649
+ kind: "predicate",
650
+ field,
651
+ operator: token.kind === "regex" ? "regex" : token.kind === "quoted" ? "phrase" : wildcard ? "wildcard" : "term",
652
+ value: token.kind === "regex" || wildcard ? raw : decodeEscapes(raw, token.span, fail),
653
+ span: { start: start ?? token.span.start, end: token.span.end },
654
+ ...implicit ? { implicit: true } : {}
655
+ });
656
+ }
657
+ if (proximity && peek().kind === "~" && node.kind === "predicate" && node.operator === "phrase") {
658
+ take();
659
+ const distance = take();
660
+ if (distance.kind !== "number" || !/^\d+$/u.test(distance.raw))
661
+ fail("query.invalid-syntax", distance.span, 'write the distance as a whole number: "a b"~3');
662
+ node = { ...node, slop: Number(distance.raw), span: { start: node.span.start, end: distance.span.end } };
663
+ }
664
+ if (peek().kind === "~")
665
+ fail("query.unsupported-operator", peek().span, node.kind === "predicate" && node.operator === "phrase" ? "proximity (~) is not supported \u2014 drop the ~ for the exact phrase, or join the words with AND" : "fuzzy matching (~) is not supported \u2014 use a prefix such as word* to catch word forms");
666
+ if (["^", "@"].includes(peek().kind))
667
+ fail("query.unsupported-operator", peek().span, "boost and minimum-should-match are not supported");
668
+ return { node, ...modifier ? { modifier } : {} };
669
+ }, "clause");
670
+ const root = query(defaultField, true);
671
+ expect("EOF");
672
+ if (defaultField === "none") {
673
+ const bare = walkQuery(root).find((node) => node.implicit);
674
+ if (bare)
675
+ queryError("query.bare-word", bare.span, `"${bare.value}" has no field; write field:value`, context3, {
676
+ word: bare.value
677
+ });
678
+ }
679
+ return { version: 1, language: "lucene-v1", root };
680
+ }, "parseLucene");
681
+ var implicitTextTerms = /* @__PURE__ */ __name((text6) => {
682
+ const tokens = tokensOf(text6);
683
+ if (tokens.some(({ kind }) => ["AND", "OR", "NOT", "+", "-", "!", "(", ")"].includes(kind)))
684
+ return /* @__PURE__ */ new Set();
685
+ return new Set(tokens.flatMap((token, index) => token.kind === "term" && ![":", "=", "<", ">", "<=", ">="].includes(tokens[index - 1]?.kind ?? "") && ![":", "=", "<", ">", "<=", ">="].includes(tokens[index + 1]?.kind ?? "") ? [token.span.start] : []));
686
+ }, "implicitTextTerms");
687
+
688
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/registry.js
689
+ var describeQuery = /* @__PURE__ */ __name((registry) => ({
690
+ entity: registry.entity,
691
+ backend: registry.backend,
692
+ fields: registry.fields.map(({ validate: _, ...field }) => field),
693
+ ...registry.defaults && registry.defaults.length > 0 ? { defaults: [...registry.defaults] } : {}
694
+ }), "describeQuery");
695
+ var exampleProblems = /* @__PURE__ */ __name((registry) => {
696
+ const syntaxOnly = { ...registry, backend: "sql" };
697
+ const problem = /* @__PURE__ */ __name((text6, field) => {
698
+ try {
699
+ const named = walkQuery(validateQuery(parseLucene(text6, { defaultField: "none" }), syntaxOnly).root);
700
+ return named.every((node) => node.field === field) ? void 0 : `"${text6}" does not name ${field}`;
701
+ } catch (failure) {
702
+ if (!isCliError(failure))
703
+ throw failure;
704
+ return `"${text6}": ${failure.message}`;
705
+ }
706
+ }, "problem");
707
+ const defaults = (registry.defaults ?? []).map((term) => {
708
+ const field = term.replace(/^-/, "").split(/[:<>=]/)[0] ?? "";
709
+ return { field, problem: problem(term.replace(/^-/, ""), field) };
710
+ });
711
+ return [
712
+ ...registry.fields.map((field) => ({ field: field.name, problem: problem(field.example, field.name) })),
713
+ ...defaults
714
+ ].filter((entry) => entry.problem !== void 0);
715
+ }, "exampleProblems");
716
+ var defineQuery = /* @__PURE__ */ __name((registry) => {
717
+ const names = registry.fields.map((field) => field.name);
718
+ const problems = [
719
+ ...duplicates(names).map((name) => `"${name}" is listed twice`),
720
+ ...names.filter((name) => !SNAKE_CASE.test(name)).map((name) => `"${name}" is not snake_case`),
721
+ ...exampleProblems(registry).map(({ field, problem }) => `${field}: ${problem}`)
722
+ ];
723
+ if (problems.length > 0)
724
+ throw new RegistryError(`${registry.entity} query`, problems);
725
+ return registry;
726
+ }, "defineQuery");
727
+ var SPAN = ["span", "alternative", "guide"];
728
+ var QUERY_REASONS = defineReasons([
729
+ ["query.bare-word", "a word in the query has no field", ["word"]],
730
+ ["query.invalid-ast", "the query tree is not valid", []],
731
+ ["query.invalid-date", "a date in the query cannot be read", []],
732
+ ["query.invalid-escape", "an escape in the query is not valid", []],
733
+ ["query.invalid-number", "a number in the query cannot be read", []],
734
+ ["query.invalid-regex", "a regular expression in the query is not valid", []],
735
+ ["query.invalid-syntax", "the query cannot be parsed", []],
736
+ ["query.invalid-timezone", "the time zone is not known", []],
737
+ ["query.missing-value", "a field in the query has no value", []],
738
+ ["query.too-large", "the query is over one of its limits", []],
739
+ ["query.unclosed-literal", "a quote or bracket in the query is not closed", []],
740
+ ["query.unknown-field", "a field in the query is not known", ["fields"]],
741
+ ["query.unknown-value", "a value in the query is not known", []],
742
+ ["query.unsupported-field", "this list cannot filter by that field", ["supported"]],
743
+ ["query.unsupported-operator", "this field does not take that operator", []],
744
+ ["query.unsupported-placement", "this field works only as a required term", []],
745
+ ["query.unsupported-regex", "that regular expression is not supported", []],
746
+ ["query.unsupported-regex-flags", "regular expression flags are not supported", []],
747
+ ["query.unsupported-version", "the query version is not supported", []]
748
+ ].map(([reason, message, details]) => ({
749
+ reason,
750
+ code: "validation_error",
751
+ message,
752
+ details: [...SPAN, ...details]
753
+ })));
754
+
755
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/evaluate.js
756
+ var wordsOf = /* @__PURE__ */ __name((text6) => text6.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [], "wordsOf");
757
+ var pattern = /* @__PURE__ */ __name((value) => new RegExp(`^${[...value].map((char) => char === "*" ? ".*" : char === "?" ? "." : char.replace(/[.+^${}()|[\]\\]/, "\\$&")).join("")}$`, "iu"), "pattern");
758
+ var present = /* @__PURE__ */ __name((value) => value !== void 0 && value !== null && value !== "", "present");
759
+ var matchOne = /* @__PURE__ */ __name((field, node, value, options) => {
760
+ if (!present(value))
761
+ return false;
762
+ if (node.operator === "wildcard" && node.value === "*")
763
+ return true;
764
+ const text6 = String(value);
765
+ switch (field.type) {
766
+ case "txt": {
767
+ const words2 = wordsOf(text6);
768
+ if (node.operator === "wildcard")
769
+ return words2.some((word) => pattern(node.value).test(word));
770
+ const wanted = wordsOf(node.value);
771
+ return words2.some((_, at) => wanted.every((word, offset) => words2[at + offset] === word));
772
+ }
773
+ case "num": {
774
+ const number2 = Number(value);
775
+ if (node.operator !== "range")
776
+ return number2 === Number(node.value);
777
+ const { value: lower, upper = "*", lower_inclusive: lowerInclusive, upper_inclusive: upperInclusive } = node;
778
+ return (lower === "*" || (lowerInclusive ? number2 >= Number(lower) : number2 > Number(lower))) && (upper === "*" || (upperInclusive ? number2 <= Number(upper) : number2 < Number(upper)));
779
+ }
780
+ case "time": {
781
+ const time = Date.parse(text6);
782
+ const [lower, upper, lowerInclusive, upperInclusive] = node.operator === "range" ? [node.value, node.upper ?? "*", node.lower_inclusive ?? true, node.upper_inclusive ?? true] : [node.value, node.value, true, true];
783
+ const range = dateRange(lower, upper, lowerInclusive, upperInclusive, options.zone ?? "UTC", node.span, options.now);
784
+ return (range.lower === void 0 || (range.lower_inclusive ? time >= range.lower : time > range.lower)) && (range.upper === void 0 || (range.upper_inclusive ? time <= range.upper : time < range.upper));
785
+ }
786
+ default:
787
+ return node.operator === "wildcard" ? pattern(node.value).test(text6) : text6.toLowerCase() === node.value.toLowerCase();
788
+ }
789
+ }, "matchOne");
790
+ var matches = /* @__PURE__ */ __name((node, item, byName, options) => {
791
+ if (node.kind === "boolean") {
792
+ const by = /* @__PURE__ */ __name((occur) => node.clauses.filter((clause) => clause.occur === occur), "by");
793
+ const [must, should, mustNot] = [by("must"), by("should"), by("must_not")];
794
+ const holds = /* @__PURE__ */ __name((clause) => matches(clause.node, item, byName, options), "holds");
795
+ return must.every(holds) && !mustNot.some(holds) && (should.length === 0 || must.length > 0 || should.some(holds));
796
+ }
797
+ const field = byName.get(node.field);
798
+ if (!field)
799
+ throw new Error(`evaluate: no field "${node.field}"; validate the query first`);
800
+ if (field.relation !== void 0) {
801
+ if (!options.relation)
802
+ throw new Error(`evaluate: "${node.field}" is a relation; pass options.relation`);
803
+ return options.relation(node, item);
804
+ }
805
+ const value = item[node.field];
806
+ return Array.isArray(value) ? value.some((one) => matchOne(field, node, one, options)) : matchOne(field, node, value, options);
807
+ }, "matches");
808
+ var evaluate = /* @__PURE__ */ __name((ast, fields2, item, options = {}) => matches(ast.root, item, new Map(fields2.map((field) => [field.name, field])), options), "evaluate");
809
+
810
+ // node_modules/.pnpm/@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/query/help.js
811
+ var QUERY_SYNTAX = 'field:value \xB7 "a phrase" \xB7 word* \xB7 AND OR NOT \xB7 ( ) \xB7 [a TO b] \xB7 > >= < <=';
812
+ var kindOf = /* @__PURE__ */ __name((field) => field.values ? `${field.type}: ${field.values.join("|")}` : `${field.type}: ${field.operators.join(", ")}`, "kindOf");
813
+ var fieldsHelp = /* @__PURE__ */ __name((registry, guide) => {
814
+ const shown = registry.backend === "native" ? registry.fields.filter((field) => field.native) : registry.fields;
815
+ const rows = shown.map((field) => [field.name, kindOf(field), field.example]);
816
+ const widths = [0, 1].map((at) => Math.max(...rows.map((row) => (row[at] ?? "").length)));
817
+ return [
818
+ "Fields:",
819
+ ...rows.map(([name = "", kind = "", example = ""]) => ` ${name.padEnd(widths[0] ?? 0)} ${kind.padEnd(widths[1] ?? 0)} ${example}`.trimEnd()),
820
+ ...registry.defaults && registry.defaults.length > 0 ? [`Defaults: ${registry.defaults.join(" ")} \u2014 name the field to change it`] : [],
821
+ `Syntax: ${QUERY_SYNTAX}`,
822
+ ...guide ? [`Guide: ${guide}`] : []
823
+ ].join("\n");
824
+ }, "fieldsHelp");
825
+
826
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/reference.js
827
+ var invalid = /* @__PURE__ */ __name(() => new CliError("validation_error", "expected meeting:<accountId>/<meetingId>[/<transcriptId>[/<cuePosition>]] with safe integer IDs"), "invalid");
828
+ var integer2 = /* @__PURE__ */ __name((value, minimum = 1) => {
829
+ if (!Number.isSafeInteger(value) || value < minimum)
830
+ throw invalid();
831
+ return value;
832
+ }, "integer");
833
+ var formatMeetingReference = /* @__PURE__ */ __name((reference2) => {
834
+ const parts = [integer2(reference2.accountId), integer2(reference2.meetingId)];
835
+ if (reference2.transcriptId !== void 0)
836
+ parts.push(integer2(reference2.transcriptId));
837
+ if (reference2.cuePosition !== void 0) {
838
+ if (reference2.transcriptId === void 0)
839
+ throw invalid();
840
+ parts.push(integer2(reference2.cuePosition, 0));
841
+ }
842
+ return `meeting:${parts.join("/")}`;
843
+ }, "formatMeetingReference");
844
+ var parseMeetingReference = /* @__PURE__ */ __name((text6) => {
845
+ const value = text6.trim();
846
+ if (!value.startsWith("meeting:"))
847
+ throw invalid();
848
+ const parts = value.slice(8).split("/");
849
+ if (parts.length < 2 || parts.length > 4 || parts.some((part) => !/^\d+$/.test(part)))
850
+ throw invalid();
851
+ const ids2 = parts.map(Number);
852
+ const reference2 = {
853
+ type: "meeting",
854
+ accountId: integer2(ids2[0]),
855
+ meetingId: integer2(ids2[1]),
856
+ ...ids2.length > 2 ? { transcriptId: integer2(ids2[2]) } : {},
857
+ ...ids2.length > 3 ? { cuePosition: integer2(ids2[3], 0) } : {}
858
+ };
859
+ return reference2;
860
+ }, "parseMeetingReference");
861
+ var canonicalMeetingReference = /* @__PURE__ */ __name((text6) => formatMeetingReference(parseMeetingReference(text6)), "canonicalMeetingReference");
862
+
863
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/item.js
864
+ var text = string();
865
+ var count = pipe(number(), integer(), minValue(0));
866
+ var MEETING_ISSUES = ["time_without_zone"];
867
+ var meetingIssuesOf = /* @__PURE__ */ __name((metadata) => {
868
+ const listed2 = metadata?.issues;
869
+ return Array.isArray(listed2) ? MEETING_ISSUES.filter((issue) => listed2.includes(issue)) : [];
870
+ }, "meetingIssuesOf");
871
+ var meeting = strictObject({
872
+ ref: reference,
873
+ id: pipe(string(), minLength(1)),
874
+ provider: text,
875
+ account: text,
876
+ title: nullable(text),
877
+ description: optional(nullable(text)),
878
+ location: optional(nullable(text)),
879
+ /** The link that joins it. */
880
+ url: nullable(text),
881
+ started_at: nullable(isoTime),
882
+ ended_at: nullable(isoTime),
883
+ duration_ms: nullable(count),
884
+ timezone: optional(nullable(text)),
885
+ participants_count: nullable(count),
886
+ /** Present only when something about this meeting is doubtful. */
887
+ issues: optional(array(picklist(MEETING_ISSUES))),
888
+ created_at: isoTime,
889
+ updated_at: isoTime
890
+ });
891
+ var iso = /* @__PURE__ */ __name((ms) => ms === null ? null : new Date(ms).toISOString(), "iso");
892
+ var meetingItem = /* @__PURE__ */ __name((row, owner) => {
893
+ const issues = meetingIssuesOf(row.metadata);
894
+ return {
895
+ ref: formatMeetingReference({ type: "meeting", accountId: row.accountId, meetingId: row.id }),
896
+ id: String(row.id),
897
+ provider: owner.provider,
898
+ account: owner.account,
899
+ title: row.title,
900
+ description: row.description,
901
+ location: row.location,
902
+ url: row.joinUrl,
903
+ started_at: iso(row.startedAt),
904
+ ended_at: iso(row.endedAt),
905
+ duration_ms: row.durationMs,
906
+ timezone: row.timezone,
907
+ participants_count: row.participantsCount,
908
+ ...issues.length ? { issues } : {},
909
+ created_at: new Date(row.createdAt).toISOString(),
910
+ updated_at: new Date(row.updatedAt).toISOString()
911
+ };
912
+ }, "meetingItem");
913
+ var MEETING_QUERY = {
914
+ entity: "meeting",
915
+ backend: "sql",
916
+ fields: queryFieldsOf(meeting, {
917
+ exclude: ["ref", "provider", "account", "description", "location", "url", "timezone", "issues"],
918
+ examples: {
919
+ id: "id:12",
920
+ title: "title:*standup*",
921
+ started_at: "started_at:[2026-10-01 TO 2026-10-31]",
922
+ duration_ms: "duration_ms>=3600000",
923
+ participants_count: "participants_count>5"
924
+ }
925
+ })
926
+ };
927
+
928
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/join-key.js
929
+ var joinKeyOf = /* @__PURE__ */ __name((url) => {
930
+ const parsed = urlOf(url);
931
+ if (!parsed)
932
+ return null;
933
+ const host = parsed.hostname.toLowerCase().replace(/^www\./u, "");
934
+ const path = parsed.pathname.replace(/\/+$/u, "");
935
+ if (host === "zoom.us" || host.endsWith(".zoom.us") || host === "zoomgov.com" || host.endsWith(".zoomgov.com")) {
936
+ const number2 = /^\/(?:j|w|s|wc\/join|wc)\/(\d{9,12})(?:\/|$)/u.exec(path)?.[1];
937
+ if (number2)
938
+ return `zoom:${number2}`;
939
+ }
940
+ if (host === "meet.google.com") {
941
+ const code = /^\/([a-z]{3}-[a-z]{4}-[a-z]{3})$/iu.exec(path)?.[1];
942
+ if (code)
943
+ return `meet:${code.toLowerCase()}`;
944
+ }
945
+ return `${host}${path}`;
946
+ }, "joinKeyOf");
947
+ var joinUrlWithoutQuery = /* @__PURE__ */ __name((url) => {
948
+ const parsed = urlOf(url);
949
+ return parsed ? `${parsed.origin}${parsed.pathname}` : null;
950
+ }, "joinUrlWithoutQuery");
951
+ var urlOf = /* @__PURE__ */ __name((url) => {
952
+ if (!url?.trim())
953
+ return null;
954
+ try {
955
+ const parsed = new URL(url.trim());
956
+ return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed : null;
957
+ } catch {
958
+ return null;
959
+ }
960
+ }, "urlOf");
961
+
962
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/calendar-text.js
963
+ var ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', "#39": "'", apos: "'", nbsp: " " };
964
+ var SECRET_LINE = /(?<![\p{L}\p{N}])(pass ?codes?|passwords?|pwd|pins?|access ?codes?|meeting ?codes?|kennwort|пароль|пин-?код|код доступа)(?![\p{L}\p{N}])|pwd=/iu;
965
+ var htmlToText = /* @__PURE__ */ __name((html) => html.replace(/<\s*br\s*\/?>/giu, "\n").replace(/<\/\s*(p|div|li|tr|h[1-6])\s*>/giu, "\n").replace(/<a\s[^>]*href\s*=\s*"([^"]*)"[^>]*>/giu, " $1 ").replace(/<[^>]+>/gu, "").replace(/&(amp|lt|gt|quot|#39|apos|nbsp);/gu, (_, name) => ENTITIES[name] ?? ""), "htmlToText");
966
+ var withoutLinkQueries = /* @__PURE__ */ __name((text6) => text6.replace(/https?:\/\/[^\s<>"')\]]+/giu, (url) => joinUrlWithoutQuery(url) ?? ""), "withoutLinkQueries");
967
+ var calendarText = /* @__PURE__ */ __name((text6, { dropSecretLines = true } = {}) => {
968
+ if (!text6)
969
+ return null;
970
+ const kept = htmlToText(text6).split(/\r?\n/u).map((line2) => withoutLinkQueries(line2).replace(/[ \t]+/gu, " ").trim()).filter((line2) => !dropSecretLines || !SECRET_LINE.test(line2));
971
+ const joined = kept.join("\n").replace(/\n{3,}/gu, "\n\n").trim();
972
+ return joined || null;
973
+ }, "calendarText");
974
+ var ENTRY_METADATA_KEYS = [
975
+ "colorId",
976
+ "guestsCanInviteOthers",
977
+ "guestsCanModify",
978
+ "guestsCanSeeOtherGuests",
979
+ "hangoutLink",
980
+ "locked",
981
+ "privateCopy"
982
+ ];
983
+ var entryMetadata = /* @__PURE__ */ __name((metadata) => {
984
+ const kept = {};
985
+ for (const key of ENTRY_METADATA_KEYS) {
986
+ const value = metadata?.[key];
987
+ if (typeof value === "string")
988
+ kept[key] = withoutLinkQueries(value);
989
+ else if (typeof value === "number" || typeof value === "boolean")
990
+ kept[key] = value;
991
+ }
992
+ return kept;
993
+ }, "entryMetadata");
994
+
995
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/cue-fingerprint.js
996
+ import { createHash } from "node:crypto";
997
+ var meetingCueFingerprint = /* @__PURE__ */ __name((cue2) => createHash("sha256").update(JSON.stringify({
998
+ reference: cue2.reference,
999
+ transcriptId: cue2.transcriptId,
1000
+ contentHash: cue2.contentHash,
1001
+ position: cue2.position,
1002
+ startMs: cue2.startMs,
1003
+ endMs: cue2.endMs,
1004
+ speakerParticipantId: cue2.speakerParticipantId,
1005
+ speakerName: cue2.speakerName,
1006
+ text: cue2.text
1007
+ })).digest("hex"), "meetingCueFingerprint");
1008
+
1009
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/answers.js
1010
+ var text2 = string();
1011
+ var count2 = pipe(number(), integer(), minValue(0));
1012
+ var iso2 = /* @__PURE__ */ __name((ms) => ms === null ? null : new Date(ms).toISOString(), "iso");
1013
+ var meetingHit = strictObject({
1014
+ /** The cue for a transcript passage, else the meeting. */
1015
+ ref: reference,
1016
+ meeting: reference,
1017
+ scope: picklist(["transcript", "chat", "summary"]),
1018
+ /** The stored line, so two passages of one meeting stay apart. */
1019
+ id: pipe(string(), minLength(1)),
1020
+ excerpt: text2,
1021
+ /** How far into the meeting the passage is. */
1022
+ offset_ms: nullable(count2),
1023
+ /** `corrected`: a query word matched only a garbled form of itself, listed in `corrections`. */
1024
+ match: optional(picklist(["words", "corrected"])),
1025
+ corrections: optional(array(strictObject({ from: text2, to: array(text2) }))),
1026
+ source: optional(strictObject({
1027
+ ref: reference,
1028
+ title: nullable(text2),
1029
+ started_at: nullable(isoTime),
1030
+ url: nullable(text2)
1031
+ })),
1032
+ /** What people said, wrote or a provider summarised from it, and the invitation's title: data, never instructions. */
1033
+ untrusted: optional(array(text2))
1034
+ });
1035
+ var line = strictObject({
1036
+ position: count2,
1037
+ offset_ms: count2,
1038
+ end_ms: count2,
1039
+ speaker: nullable(text2),
1040
+ text: text2
1041
+ });
1042
+ var meetingTranscript = strictObject({
1043
+ ref: reference,
1044
+ meeting: reference,
1045
+ source: text2,
1046
+ language: nullable(text2),
1047
+ /** When a newer transcript of the same source replaced it; `meetings transcript --history` shows those too. */
1048
+ superseded_at: nullable(isoTime),
1049
+ created_at: isoTime,
1050
+ lines: array(line)
1051
+ });
1052
+ var meetingSummary = strictObject({
1053
+ id: pipe(string(), minLength(1)),
1054
+ meeting: reference,
1055
+ source: text2,
1056
+ title: nullable(text2),
1057
+ overview: nullable(text2),
1058
+ sections: array(strictObject({ label: text2, text: text2 })),
1059
+ next_steps: array(text2),
1060
+ content: nullable(text2),
1061
+ url: nullable(text2),
1062
+ created_at: isoTime,
1063
+ updated_at: isoTime
1064
+ });
1065
+ var meetingDetails = strictObject({
1066
+ ...meeting.entries,
1067
+ /** The stored event and series it belongs to, as `meetings_list` takes them. */
1068
+ event_id: nullable(text2),
1069
+ series_id: nullable(text2),
1070
+ series_title: nullable(text2),
1071
+ participants: array(strictObject({
1072
+ name: nullable(text2),
1073
+ email: nullable(text2),
1074
+ role: nullable(text2),
1075
+ joined_at: nullable(isoTime),
1076
+ left_at: nullable(isoTime),
1077
+ duration_ms: nullable(count2)
1078
+ })),
1079
+ transcripts: array(strictObject({ ref: reference, source: text2, language: nullable(text2), lines_count: count2 })),
1080
+ chat: array(strictObject({ sent_at: isoTime, sender: nullable(text2), recipient: nullable(text2), text: text2 })),
1081
+ summaries: array(meetingSummary),
1082
+ attachments: array(strictObject({
1083
+ position: count2,
1084
+ kind: text2,
1085
+ name: nullable(text2),
1086
+ mime: nullable(text2),
1087
+ size: nullable(count2),
1088
+ url: nullable(text2)
1089
+ }))
1090
+ });
1091
+ var meetingRef = /* @__PURE__ */ __name((accountId, meetingId) => formatMeetingReference({ type: "meeting", accountId, meetingId }), "meetingRef");
1092
+ var meetingTranscriptItem = /* @__PURE__ */ __name((accountId, transcript, rows) => ({
1093
+ ref: formatMeetingReference({
1094
+ type: "meeting",
1095
+ accountId,
1096
+ meetingId: transcript.meetingId,
1097
+ transcriptId: transcript.id
1098
+ }),
1099
+ meeting: meetingRef(accountId, transcript.meetingId),
1100
+ source: transcript.source,
1101
+ language: transcript.language,
1102
+ superseded_at: iso2(transcript.supersededAt),
1103
+ created_at: new Date(transcript.externalCreatedAt ?? transcript.createdAt).toISOString(),
1104
+ lines: rows.map((row) => ({
1105
+ position: row.position,
1106
+ offset_ms: row.startMs,
1107
+ end_ms: row.endMs,
1108
+ speaker: row.speakerName,
1109
+ text: row.text
1110
+ }))
1111
+ }), "meetingTranscriptItem");
1112
+ var meetingSummaryItem = /* @__PURE__ */ __name((accountId, summary) => ({
1113
+ id: String(summary.id),
1114
+ meeting: meetingRef(accountId, summary.meetingId),
1115
+ source: summary.source,
1116
+ title: summary.title,
1117
+ overview: summary.overview,
1118
+ sections: summary.sections.map(({ label, text: text6 }) => ({ label, text: text6 })),
1119
+ next_steps: summary.nextSteps,
1120
+ content: summary.content,
1121
+ url: summary.docUrl,
1122
+ created_at: new Date(summary.externalCreatedAt ?? summary.createdAt).toISOString(),
1123
+ updated_at: new Date(summary.externalUpdatedAt ?? summary.updatedAt).toISOString()
1124
+ }), "meetingSummaryItem");
1125
+ var meetingDetailsItem = /* @__PURE__ */ __name((details, owner) => {
1126
+ const { accountId } = details.meeting;
1127
+ return {
1128
+ ...meetingItem(details.meeting, owner),
1129
+ event_id: details.meeting.eventId === null ? null : String(details.meeting.eventId),
1130
+ series_id: details.meeting.meetingSeriesId === null ? null : String(details.meeting.meetingSeriesId),
1131
+ series_title: details.series?.title ?? null,
1132
+ participants: details.participants.map((one) => ({
1133
+ name: one.displayName,
1134
+ email: one.email,
1135
+ role: one.role,
1136
+ joined_at: iso2(one.joinedAt),
1137
+ left_at: iso2(one.leftAt),
1138
+ duration_ms: one.durationMs
1139
+ })),
1140
+ transcripts: details.transcripts.filter(({ transcript }) => transcript.supersededAt === null && transcript.deletedAt === null).map(({ transcript, rows }) => ({
1141
+ ref: formatMeetingReference({
1142
+ type: "meeting",
1143
+ accountId,
1144
+ meetingId: transcript.meetingId,
1145
+ transcriptId: transcript.id
1146
+ }),
1147
+ source: transcript.source,
1148
+ language: transcript.language,
1149
+ lines_count: rows.length
1150
+ })),
1151
+ chat: details.chat.map((one) => ({
1152
+ sent_at: new Date(one.sentAt).toISOString(),
1153
+ sender: one.senderName,
1154
+ recipient: one.recipient,
1155
+ text: one.text
1156
+ })),
1157
+ summaries: details.summaries.map((one) => meetingSummaryItem(accountId, one)),
1158
+ attachments: details.attachments.map((one) => ({
1159
+ position: one.position,
1160
+ kind: one.kind,
1161
+ name: one.name ?? one.title,
1162
+ mime: one.mime,
1163
+ size: one.size,
1164
+ url: one.url
1165
+ }))
1166
+ };
1167
+ }, "meetingDetailsItem");
1168
+ var wholeList = /* @__PURE__ */ __name((items) => ({
1169
+ items,
1170
+ page: { mode: "page", limit: Math.max(1, items.length), has_more: false }
1171
+ }), "wholeList");
1172
+ var PAGE_NEXT = STEPS.find((step) => step.id === "page.next");
1173
+ var MEETING_STEPS = defineSteps([
1174
+ {
1175
+ id: "meetings.search-again",
1176
+ command: "*",
1177
+ args: [],
1178
+ why: "passages that changed since they were indexed were left out; the next search indexes them first"
1179
+ }
1180
+ ]);
1181
+ var SEARCH_AGAIN = MEETING_STEPS[0];
1182
+ var meetingHitItem = /* @__PURE__ */ __name((hit) => ({
1183
+ ref: hit.ref,
1184
+ meeting: meetingRef(parseMeetingReference(hit.ref).accountId, hit.meetingId),
1185
+ scope: hit.scope,
1186
+ id: String(hit.id),
1187
+ excerpt: hit.text,
1188
+ offset_ms: hit.startMs,
1189
+ untrusted: hit.source === void 0 ? ["excerpt"] : ["excerpt", "source.title"],
1190
+ ...hit.match === void 0 ? {} : { match: hit.match },
1191
+ ...hit.corrections === void 0 ? {} : { corrections: hit.corrections },
1192
+ ...hit.source === void 0 ? {} : {
1193
+ source: {
1194
+ ref: hit.ref,
1195
+ title: hit.source.title,
1196
+ started_at: iso2(hit.source.startedAt),
1197
+ url: hit.source.url
1198
+ }
1199
+ }
1200
+ }), "meetingHitItem");
1201
+ var meetingHitsList = /* @__PURE__ */ __name((found, limit, command = "search meetings", args = {}, meta = {}) => {
1202
+ const items = found.items.map(meetingHitItem);
1203
+ const cursor = found.hasMore && found.nextCursor !== null ? found.nextCursor : void 0;
1204
+ const pending = found.coverage.indexing === "pending";
1205
+ const next = [
1206
+ ...cursor === void 0 ? [] : [stepOf(PAGE_NEXT, { command, args: { ...args, cursor, limit }, values: { shown: items.length } })],
1207
+ ...pending ? [
1208
+ stepOf(SEARCH_AGAIN, {
1209
+ command,
1210
+ args: Object.fromEntries(Object.entries(args).filter(([key]) => key !== "cursor"))
1211
+ })
1212
+ ] : []
1213
+ ];
1214
+ return {
1215
+ items,
1216
+ page: {
1217
+ mode: "cursor",
1218
+ limit,
1219
+ has_more: cursor !== void 0,
1220
+ ...cursor === void 0 ? {} : { next_cursor: cursor }
1221
+ },
1222
+ ...next.length > 0 ? { next } : {},
1223
+ ...pending ? {
1224
+ missing: [
1225
+ {
1226
+ field: "excerpt",
1227
+ why: "passages that changed since they were indexed were left out",
1228
+ step: "meetings.search-again"
1229
+ }
1230
+ ]
1231
+ } : {},
1232
+ ...Object.keys(meta).length === 0 ? {} : { meta }
1233
+ };
1234
+ }, "meetingHitsList");
1235
+
1236
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/participant-search.js
1237
+ var normalizeMeetingParticipantQuery = /* @__PURE__ */ __name((text6) => text6.normalize("NFKC").toLowerCase(), "normalizeMeetingParticipantQuery");
1238
+ var validateMeetingParticipantQuery = /* @__PURE__ */ __name((query) => {
1239
+ if (typeof query !== "string" || !query.trim() || query.length > 500 || query.includes("\0"))
1240
+ throw new CliError("validation_error", "participant query must contain 1\u2013500 characters without NUL");
1241
+ return normalizeMeetingParticipantQuery(query.trim());
1242
+ }, "validateMeetingParticipantQuery");
1243
+ var validateMeetingParticipantSearch = /* @__PURE__ */ __name((query, input) => {
1244
+ input.signal?.throwIfAborted();
1245
+ const normalized = validateMeetingParticipantQuery(query);
1246
+ const bounded = /* @__PURE__ */ __name((value, maximum, name) => {
1247
+ if (!Number.isSafeInteger(value) || value < 1 || value > maximum)
1248
+ throw new CliError("validation_error", `${name} must be an integer from 1 through ${maximum}`);
1249
+ return value;
1250
+ }, "bounded");
1251
+ return {
1252
+ query: normalized,
1253
+ accountId: bounded(input.accountId, Number.MAX_SAFE_INTEGER, "accountId"),
1254
+ limit: bounded(input.limit ?? 50, 1e3, "limit"),
1255
+ scanLimit: bounded(input.scanLimit ?? 1e3, 1e4, "scanLimit"),
1256
+ maxReadBytes: bounded(input.maxReadBytes ?? 1024 ** 2, 64 * 1024 ** 2, "maxReadBytes")
1257
+ };
1258
+ }, "validateMeetingParticipantSearch");
1259
+
1260
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/reads.js
1261
+ var MeetingError = class extends CliError {
1262
+ static {
1263
+ __name(this, "MeetingError");
1264
+ }
1265
+ constructor(code, message) {
1266
+ super(code, message);
1267
+ }
1268
+ };
1269
+ var positiveInteger = /* @__PURE__ */ __name((value) => {
1270
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0)
1271
+ throw new MeetingError("validation_error", "expected a positive integer");
1272
+ return value;
1273
+ }, "positiveInteger");
1274
+ var validateFilter = /* @__PURE__ */ __name((filter) => {
1275
+ for (const value of [filter.accountId, filter.eventId, filter.meetingSeriesId])
1276
+ if (value !== void 0)
1277
+ positiveInteger(value);
1278
+ for (const value of [filter.since, filter.until])
1279
+ if (value !== void 0 && !Number.isFinite(value))
1280
+ throw new MeetingError("validation_error", "expected epoch milliseconds");
1281
+ if (filter.since !== void 0 && filter.until !== void 0 && filter.since > filter.until)
1282
+ throw new MeetingError("validation_error", "since must not exceed until");
1283
+ for (const value of [filter.limit, filter.offset])
1284
+ if (value !== void 0 && (!Number.isSafeInteger(value) || value < 0))
1285
+ throw new MeetingError("validation_error", "expected a nonnegative integer");
1286
+ }, "validateFilter");
1287
+ var meetingShow = /* @__PURE__ */ __name(async (store, id3, accountId) => {
1288
+ const details = await store.meeting(positiveInteger(id3));
1289
+ if (!details || accountId !== void 0 && details.meeting.accountId !== accountId)
1290
+ throw new MeetingError("not_found", "meeting not found");
1291
+ return details;
1292
+ }, "meetingShow");
1293
+ var listed = /* @__PURE__ */ __name((items) => ({ items, page: 1, limit: items.length, hasMore: false }), "listed");
1294
+ var meetingPeople = /* @__PURE__ */ __name(async (store, query, accountId, options = {}) => {
1295
+ if (accountId === void 0)
1296
+ validateMeetingParticipantQuery(query);
1297
+ else
1298
+ validateMeetingParticipantSearch(query, { ...options, accountId });
1299
+ if (store.participantCandidates && accountId === void 0)
1300
+ throw new MeetingError("configuration_error", "select an account for bounded participant lookup");
1301
+ if (accountId !== void 0 && store.participantCandidates) {
1302
+ const { limit, has_more, next_cursor, ...packet } = await store.participantCandidates(query, {
1303
+ ...options,
1304
+ accountId
1305
+ });
1306
+ return {
1307
+ ...packet,
1308
+ page: { mode: "cursor", limit, has_more, ...next_cursor ? { next_cursor } : {} },
1309
+ ...next_cursor ? {
1310
+ next: [
1311
+ stepOf(PAGE_NEXT2, {
1312
+ command: "meetings people",
1313
+ args: {
1314
+ query,
1315
+ limit,
1316
+ ...options.scanLimit === void 0 ? {} : { scan_limit: options.scanLimit },
1317
+ ...options.maxReadBytes === void 0 ? {} : { max_read_bytes: options.maxReadBytes },
1318
+ cursor: next_cursor
1319
+ },
1320
+ values: { shown: packet.items.length }
1321
+ })
1322
+ ]
1323
+ } : {}
1324
+ };
1325
+ }
1326
+ if (Object.values(options).some((value) => value !== void 0))
1327
+ throw new MeetingError("configuration_error", "bounded participant lookup needs a selected account and capable store");
1328
+ return listed(await store.participants(query, accountId));
1329
+ }, "meetingPeople");
1330
+ var PAGE_NEXT2 = STEPS.find((step) => step.id === "page.next");
1331
+ var meetingsList = /* @__PURE__ */ __name(async (store, filter = {}, page = 1) => {
1332
+ validateFilter(filter);
1333
+ positiveInteger(page);
1334
+ const limit = positiveInteger(filter.limit ?? 100);
1335
+ const offset = (page - 1) * limit;
1336
+ if (!Number.isSafeInteger(offset + limit + 1))
1337
+ throw new MeetingError("validation_error", "pagination exceeds safe integer range");
1338
+ const rows = await store.meetings({ ...filter, limit: limit + 1, offset });
1339
+ const shown = rows.slice(0, limit);
1340
+ const owners = /* @__PURE__ */ new Map();
1341
+ for (const { accountId } of shown) {
1342
+ if (owners.has(accountId))
1343
+ continue;
1344
+ const owner = await store.account(accountId);
1345
+ if (!owner)
1346
+ throw new MeetingError("not_found", `meeting account ${accountId} is not in the store`);
1347
+ owners.set(accountId, owner);
1348
+ }
1349
+ const has_more = rows.length > limit;
1350
+ return {
1351
+ items: shown.map((row) => meetingItem(row, owners.get(row.accountId))),
1352
+ page: { mode: "page", limit, has_more, ...has_more ? { next_page: page + 1 } : {} },
1353
+ ...has_more ? {
1354
+ next: [
1355
+ stepOf(PAGE_NEXT2, { command: "meetings list", args: { page: page + 1, limit }, values: { shown: limit } })
1356
+ ]
1357
+ } : {}
1358
+ };
1359
+ }, "meetingsList");
1360
+ var meetingsQuery = /* @__PURE__ */ __name((text6) => {
1361
+ if (text6 === void 0 || text6.trim() === "")
1362
+ return void 0;
1363
+ const context3 = { command: "meetings list", guide: MEETING_QUERY_GUIDE };
1364
+ const query = parseLucene(text6, { defaultField: "none", ...context3 });
1365
+ validateQuery(query, MEETING_QUERY, context3);
1366
+ return query;
1367
+ }, "meetingsQuery");
1368
+ var MEETING_QUERY_GUIDE = "https://github.com/WireCatLabs/cli-core/blob/main/docs/search/query-language.md";
1369
+ var ownerOf = /* @__PURE__ */ __name(async (store, accountId) => {
1370
+ const owner = await store.account(accountId);
1371
+ if (!owner)
1372
+ throw new MeetingError("not_found", `meeting account ${accountId} is not in the store`);
1373
+ return owner;
1374
+ }, "ownerOf");
1375
+ var meetingDetailsAnswer = /* @__PURE__ */ __name(async (store, id3, accountId) => {
1376
+ const details = await meetingShow(store, id3, accountId);
1377
+ return { item: meetingDetailsItem(details, await ownerOf(store, details.meeting.accountId)) };
1378
+ }, "meetingDetailsAnswer");
1379
+ var meetingTranscriptAnswer = /* @__PURE__ */ __name(async (store, id3, accountId, options = {}) => {
1380
+ const details = await meetingShow(store, id3, accountId);
1381
+ return wholeList(details.transcripts.filter((t) => (options.history || t.transcript.supersededAt === null) && t.transcript.deletedAt === null).map((t) => meetingTranscriptItem(details.meeting.accountId, t.transcript, t.rows)));
1382
+ }, "meetingTranscriptAnswer");
1383
+ var meetingSummaryAnswer = /* @__PURE__ */ __name(async (store, id3, accountId) => {
1384
+ const details = await meetingShow(store, id3, accountId);
1385
+ return wholeList(details.summaries.map((one) => meetingSummaryItem(details.meeting.accountId, one)));
1386
+ }, "meetingSummaryAnswer");
1387
+
1388
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/export.js
1389
+ var timestamp = /* @__PURE__ */ __name((milliseconds) => {
1390
+ if (!Number.isSafeInteger(milliseconds) || milliseconds < 0)
1391
+ throw new MeetingError("validation_error", "transcript times must be nonnegative integer milliseconds");
1392
+ const hours = Math.floor(milliseconds / 36e5);
1393
+ const minutes = Math.floor(milliseconds % 36e5 / 6e4);
1394
+ const seconds = Math.floor(milliseconds % 6e4 / 1e3);
1395
+ return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(milliseconds % 1e3).padStart(3, "0")}`;
1396
+ }, "timestamp");
1397
+ var vttText = /* @__PURE__ */ __name((text6) => {
1398
+ if (visibleControls(text6) !== text6 || /\n\s*\n/.test(text6))
1399
+ throw new MeetingError("validation_error", "cue paragraphs or control characters require Markdown export");
1400
+ return text6.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
1401
+ }, "vttText");
1402
+ var serializeVtt = /* @__PURE__ */ __name((lines) => `WEBVTT
1403
+
1404
+ ${lines.map((line2, index) => {
1405
+ if (index > 0 && line2.startMs < (lines[index - 1]?.startMs ?? 0))
1406
+ throw new MeetingError("validation_error", "WebVTT cues must have nondecreasing start times");
1407
+ if (line2.endMs <= line2.startMs)
1408
+ throw new MeetingError("validation_error", "a transcript cue ends before it starts");
1409
+ const speaker = line2.speaker === null ? "" : `${vttText(line2.speaker)}: `;
1410
+ if (line2.speaker?.includes("\n"))
1411
+ throw new MeetingError("validation_error", "a speaker must fit on one line");
1412
+ return `${index + 1}
1413
+ ${timestamp(line2.startMs)} --> ${timestamp(line2.endMs)}
1414
+ ${speaker}${vttText(line2.text)}
1415
+
1416
+ `;
1417
+ }).join("")}`, "serializeVtt");
1418
+ var markdown = /* @__PURE__ */ __name((text6) => visibleControls(text6).replace(/[\\`*_{}[\]()<>#+.!|~]/g, "\\$&"), "markdown");
1419
+ var heading = /* @__PURE__ */ __name((text6) => markdown(singleLine(text6)), "heading");
1420
+ var quote = /* @__PURE__ */ __name((text6) => markdown(text6).split(/\r\n|\r|\n/).map((line2) => `> ${line2}`).join("\n"), "quote");
1421
+ var transcriptsOf = /* @__PURE__ */ __name((details, transcriptId) => {
1422
+ if (transcriptId !== void 0) {
1423
+ positiveInteger(transcriptId);
1424
+ const transcript = details.transcripts.find((part) => part.transcript.id === transcriptId && part.transcript.deletedAt === null);
1425
+ if (!transcript)
1426
+ throw new MeetingError("not_found", "transcript not found in the selected meeting");
1427
+ return [transcript];
1428
+ }
1429
+ return details.transcripts.filter((part) => part.transcript.supersededAt === null && part.transcript.deletedAt === null);
1430
+ }, "transcriptsOf");
1431
+ var exportMeeting = /* @__PURE__ */ __name(async (store, id3, options) => {
1432
+ if (options.format !== "markdown" && options.format !== "vtt")
1433
+ throw new MeetingError("validation_error", "export format must be markdown or vtt");
1434
+ const details = await meetingShow(store, id3, options.accountId);
1435
+ const transcripts = transcriptsOf(details, options.transcriptId);
1436
+ let content;
1437
+ if (options.format === "vtt") {
1438
+ const [selected] = transcripts;
1439
+ if (!selected)
1440
+ throw new MeetingError("not_found", "meeting has no transcript to export");
1441
+ if (transcripts.length > 1)
1442
+ throw new MeetingError("validation_error", "choose a transcript id when exporting multiple transcripts as VTT");
1443
+ content = serializeVtt([...selected.rows].sort((a, b) => a.position - b.position).map((row) => ({
1444
+ startMs: row.startMs,
1445
+ endMs: row.endMs,
1446
+ speaker: row.speakerName,
1447
+ text: row.text
1448
+ })));
1449
+ } else {
1450
+ const parts = [`# ${heading(details.meeting.title ?? "Untitled meeting")}`, `Meeting ID: ${details.meeting.id}`];
1451
+ if (details.meeting.description !== null)
1452
+ parts.push("## Description", quote(details.meeting.description));
1453
+ for (const summary of details.summaries) {
1454
+ parts.push(`## ${heading(summary.title ?? "Summary")}`);
1455
+ if (summary.content !== null)
1456
+ parts.push(quote(summary.content));
1457
+ else {
1458
+ if (summary.overview !== null)
1459
+ parts.push(quote(summary.overview));
1460
+ for (const section of summary.sections)
1461
+ parts.push(`### ${heading(section.label)}`, quote(section.text));
1462
+ if (summary.nextSteps.length > 0)
1463
+ parts.push("### Next steps", summary.nextSteps.map((step) => `- ${markdown(step)}`).join("\n"));
1464
+ }
1465
+ }
1466
+ for (const part of transcripts) {
1467
+ parts.push(`## Transcript ${part.transcript.id}`, `Source: ${heading(part.transcript.source)}`);
1468
+ if (part.transcript.supersededAt !== null)
1469
+ parts.push("Version: superseded");
1470
+ for (const row of [...part.rows].sort((a, b) => a.position - b.position))
1471
+ parts.push(`[${timestamp(row.startMs)} \u2013 ${timestamp(row.endMs)}]${row.speakerName === null ? "" : ` ${heading(row.speakerName)}`}`, quote(row.text));
1472
+ }
1473
+ content = `${parts.join("\n\n")}
1474
+ `;
1475
+ }
1476
+ return {
1477
+ meetingId: details.meeting.id,
1478
+ format: options.format,
1479
+ filename: `meeting-${details.meeting.id}${options.transcriptId === void 0 ? "" : `-transcript-${options.transcriptId}`}.${options.format === "markdown" ? "md" : "vtt"}`,
1480
+ content
1481
+ };
1482
+ }, "exportMeeting");
1483
+
1484
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/findings-rules.js
1485
+ import { createHash as createHash2 } from "node:crypto";
1486
+
1487
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/timestamp.js
1488
+ var meetingTimestamp = /* @__PURE__ */ __name((value, name) => {
1489
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.+(?:Z|[+-]\d{2}:\d{2})$/i.test(value) || !Number.isFinite(Date.parse(value)))
1490
+ throw new CliError("validation_error", `${name} must be an ISO timestamp with a timezone`);
1491
+ const date = value.slice(0, 10);
1492
+ const instant = Date.parse(`${date}T00:00:00Z`);
1493
+ if (!Number.isFinite(instant) || new Date(instant).toISOString().slice(0, 10) !== date)
1494
+ throw new CliError("validation_error", `${name} contains an invalid calendar date`);
1495
+ return new Date(value).toISOString();
1496
+ }, "meetingTimestamp");
1497
+
1498
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/meeting-management.js
1499
+ var nonempty = /* @__PURE__ */ __name((value, name) => {
1500
+ if (typeof value !== "string" || !value.trim())
1501
+ throw new CliError("validation_error", `${name} must be nonempty`);
1502
+ return value;
1503
+ }, "nonempty");
1504
+ var validateMeetingChange = /* @__PURE__ */ __name((change, create) => {
1505
+ if (!change || typeof change !== "object" || Array.isArray(change) || Object.keys(change).some((key) => !["title", "kind", "startTime", "durationMinutes", "timezone", "agenda"].includes(key)))
1506
+ throw new CliError("validation_error", "unsupported meeting change field");
1507
+ const result = {};
1508
+ if (change.title !== void 0)
1509
+ result.title = nonempty(change.title, "meeting title");
1510
+ if (create && result.title === void 0)
1511
+ throw new CliError("validation_error", "meeting title is required");
1512
+ if (change.kind !== void 0) {
1513
+ if (change.kind !== "instant" && change.kind !== "scheduled")
1514
+ throw new CliError("validation_error", "only instant or scheduled meeting kinds are supported");
1515
+ result.kind = change.kind;
1516
+ }
1517
+ if (change.startTime !== void 0) {
1518
+ result.startTime = meetingTimestamp(change.startTime, "meeting start");
1519
+ }
1520
+ if (change.durationMinutes !== void 0) {
1521
+ if (!Number.isSafeInteger(change.durationMinutes) || change.durationMinutes <= 0 || change.durationMinutes > 1440)
1522
+ throw new CliError("validation_error", "meeting duration must be an integer from 1 to 1440 minutes");
1523
+ result.durationMinutes = change.durationMinutes;
1524
+ }
1525
+ if (change.timezone !== void 0) {
1526
+ if (typeof change.timezone !== "string" || !change.timezone.trim())
1527
+ throw new CliError("validation_error", "meeting timezone must be a valid IANA timezone");
1528
+ try {
1529
+ new Intl.DateTimeFormat("en", { timeZone: change.timezone }).format();
1530
+ } catch {
1531
+ throw new CliError("validation_error", "meeting timezone must be a valid IANA timezone");
1532
+ }
1533
+ result.timezone = change.timezone;
1534
+ }
1535
+ if (change.agenda !== void 0) {
1536
+ if (typeof change.agenda !== "string")
1537
+ throw new CliError("validation_error", "meeting agenda must be text");
1538
+ result.agenda = change.agenda;
1539
+ }
1540
+ if (create) {
1541
+ result.kind ??= "scheduled";
1542
+ if (result.kind === "scheduled" && result.startTime === void 0)
1543
+ throw new CliError("validation_error", "scheduled meeting start is required");
1544
+ } else if (!Object.keys(result).length)
1545
+ throw new CliError("validation_error", "at least one meeting change is required");
1546
+ return Object.freeze(result);
1547
+ }, "validateMeetingChange");
1548
+
1549
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/meeting-context.js
1550
+ var MEETING_FACT_TYPES = ["fact", "statement", "question", "decision", "promise"];
1551
+
1552
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/findings-rules.js
1553
+ var TASK_TYPES = ["bug", "feature", "chore"];
1554
+ var invalid2 = /* @__PURE__ */ __name((message) => {
1555
+ throw new CliError("validation_error", message);
1556
+ }, "invalid");
1557
+ var text3 = /* @__PURE__ */ __name((value, limit) => {
1558
+ if (typeof value !== "string" || !value.trim() || value.includes("\0") || value.length > limit)
1559
+ return invalid2(`finding text must contain 1\u2013${limit} characters without NUL`);
1560
+ return value.trim();
1561
+ }, "text");
1562
+ var findingHash = /* @__PURE__ */ __name((value) => createHash2("sha256").update(JSON.stringify(value)).digest("hex"), "findingHash");
1563
+ var fields = /* @__PURE__ */ __name((value, allowed, noun) => {
1564
+ if (Object.keys(value).some((key) => !allowed.includes(key)))
1565
+ invalid2(`unknown ${noun} field`);
1566
+ }, "fields");
1567
+ var validateFindings = /* @__PURE__ */ __name((input, rules) => {
1568
+ if (!input || typeof input !== "object" || Buffer.byteLength(JSON.stringify(input), "utf8") > 65536)
1569
+ return invalid2(`${rules.plural} take at most 65536 UTF-8 bytes`);
1570
+ fields(input, ["schemaVersion", "key", "extractor", "findings"], rules.singular);
1571
+ if (input.schemaVersion !== 1 || !Array.isArray(input.findings) || input.findings.length < 1 || input.findings.length > 16)
1572
+ return invalid2(`schemaVersion 1 takes 1\u201316 ${rules.plural}`);
1573
+ const key = text3(input.key, 64);
1574
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/.test(key))
1575
+ return invalid2("a findings key uses letters, digits, dot, colon, underscore or hyphen");
1576
+ const ids2 = /* @__PURE__ */ new Set();
1577
+ const findings = input.findings.map((finding) => {
1578
+ if (!finding || typeof finding !== "object")
1579
+ return invalid2("a finding is an object");
1580
+ const id3 = text3(finding.id, 64);
1581
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/.test(id3) || ids2.has(id3))
1582
+ return invalid2("finding IDs must be unique simple keys");
1583
+ ids2.add(id3);
1584
+ const project = text3(finding.project, 64);
1585
+ if (!/^project:[1-9]\d*$/.test(project))
1586
+ return invalid2("a finding names a project reference");
1587
+ if (!Array.isArray(finding.evidence) || finding.evidence.length < 1 || finding.evidence.length > 8)
1588
+ return invalid2(`a finding requires 1\u20138 cited ${rules.cited}s`);
1589
+ const evidence = finding.evidence.map((item) => {
1590
+ if (!item || typeof item !== "object")
1591
+ return invalid2("finding evidence is a reference and fingerprint");
1592
+ fields(item, ["reference", "fingerprint"], rules.singular);
1593
+ if (typeof item.reference !== "string" || typeof item.fingerprint !== "string")
1594
+ return invalid2("evidence requires a reference and fingerprint");
1595
+ const reference2 = rules.reference(item.reference);
1596
+ if (!/^[a-f0-9]{64}$/.test(item.fingerprint))
1597
+ return invalid2(`finding evidence requires exact ${rules.cited} references and fingerprints`);
1598
+ return { reference: reference2, fingerprint: item.fingerprint };
1599
+ }).sort((a, b) => a.reference.localeCompare(b.reference));
1600
+ if (new Set(evidence.map((item) => item.reference)).size !== evidence.length)
1601
+ return invalid2(`duplicate evidence ${rules.cited}`);
1602
+ const base = { id: id3, project, evidence };
1603
+ if (finding.kind === "fact") {
1604
+ fields(finding, ["id", "project", "evidence", "kind", "type", "statement"], rules.singular);
1605
+ if (!MEETING_FACT_TYPES.includes(finding.type))
1606
+ return invalid2("unknown fact finding type");
1607
+ return { ...base, kind: "fact", type: finding.type, statement: text3(finding.statement, 2e3) };
1608
+ }
1609
+ if (finding.kind !== "task")
1610
+ return invalid2("a finding is a fact or task");
1611
+ fields(finding, [
1612
+ "id",
1613
+ "project",
1614
+ "evidence",
1615
+ "kind",
1616
+ "type",
1617
+ "title",
1618
+ "reason",
1619
+ "commitment",
1620
+ "dueAt",
1621
+ "dueEvidence",
1622
+ "assignee",
1623
+ "assigneeEvidence"
1624
+ ], rules.singular);
1625
+ if (!TASK_TYPES.includes(finding.type))
1626
+ return invalid2("a task finding type is bug, chore or feature");
1627
+ if (!["explicit", "inferred"].includes(finding.commitment))
1628
+ return invalid2("task commitment must be explicit or inferred");
1629
+ const support = /* @__PURE__ */ __name((value) => {
1630
+ if (!Array.isArray(value) || value.length < 1 || value.length > 8 || value.some((ref) => typeof ref !== "string" || !evidence.some((item) => item.reference === ref)))
1631
+ return invalid2("date and assignee support must cite the finding's evidence");
1632
+ return [...new Set(value)].sort();
1633
+ }, "support");
1634
+ if (finding.dueAt === void 0 !== (finding.dueEvidence === void 0) || finding.assignee === void 0 !== (finding.assigneeEvidence === void 0))
1635
+ return invalid2("optional dates and assignees require their supporting evidence");
1636
+ if (finding.assignee !== void 0 && (typeof finding.assignee !== "string" || !/^person:[1-9]\d*$/.test(finding.assignee)))
1637
+ return invalid2("an assignee must be a person reference");
1638
+ return {
1639
+ ...base,
1640
+ kind: "task",
1641
+ type: finding.type,
1642
+ title: text3(finding.title, 300),
1643
+ reason: text3(finding.reason, 2e3),
1644
+ commitment: finding.commitment,
1645
+ ...finding.dueAt === void 0 ? {} : { dueAt: meetingTimestamp(finding.dueAt, "finding due date"), dueEvidence: support(finding.dueEvidence) },
1646
+ ...finding.assignee === void 0 ? {} : { assignee: finding.assignee, assigneeEvidence: support(finding.assigneeEvidence) }
1647
+ };
1648
+ });
1649
+ return { schemaVersion: 1, key, extractor: text3(input.extractor, 200), findings };
1650
+ }, "validateFindings");
1651
+ var findingFingerprint = /* @__PURE__ */ __name(({ id: _id, ...finding }) => findingHash(finding), "findingFingerprint");
1652
+
1653
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/findings.js
1654
+ var MEETING_FINDINGS_KIND = "meeting_findings";
1655
+ var cue = /* @__PURE__ */ __name((raw) => {
1656
+ const reference2 = canonicalMeetingReference(raw);
1657
+ if (parseMeetingReference(reference2).cuePosition === void 0)
1658
+ throw new CliError("validation_error", "finding evidence requires exact cue references and fingerprints");
1659
+ return reference2;
1660
+ }, "cue");
1661
+ var validateMeetingFindings = /* @__PURE__ */ __name((input) => validateFindings(input, { plural: "meeting findings", singular: "meeting finding", cited: "cue", reference: cue }), "validateMeetingFindings");
1662
+ var meetingFindingFingerprint = findingFingerprint;
1663
+
1664
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/result-items.js
1665
+ var text4 = string();
1666
+ var identifier = pipe(text4, minLength(1));
1667
+ var nullableText = nullable(text4);
1668
+ var count3 = pipe(number(), integer(), minValue(0));
1669
+ var flag = boolean();
1670
+ var scope = strictObject({ provider: text4, account: text4 });
1671
+ var run = strictObject({
1672
+ meetings: count3,
1673
+ participants: count3,
1674
+ transcript_rows: count3,
1675
+ summaries: count3,
1676
+ warnings: array(strictObject({ external_id: text4, message: text4 })),
1677
+ timezone: optional(text4)
1678
+ });
1679
+ var exported = union([
1680
+ strictObject({ meeting_id: identifier, format: picklist(["markdown", "vtt"]), filename: text4, content: text4 }),
1681
+ strictObject({ meeting_id: identifier, format: picklist(["markdown", "vtt"]), output: text4 })
1682
+ ]);
1683
+ var eventChange = strictObject({
1684
+ action: literal("event.link"),
1685
+ event_id: nullable(identifier),
1686
+ expected_event_id: optional(nullable(identifier))
1687
+ });
1688
+ var personChange = strictObject({
1689
+ action: literal("person.link"),
1690
+ participant_id: identifier,
1691
+ person_uid: text4,
1692
+ expected_person_uid: optional(nullableText),
1693
+ target_account_ids: optional(array(identifier))
1694
+ });
1695
+ var eventResult = strictObject({
1696
+ meeting_id: identifier,
1697
+ event_id: nullable(identifier),
1698
+ previous_event_id: nullable(identifier),
1699
+ changed: flag
1700
+ });
1701
+ var personResult = strictObject({
1702
+ meeting_id: identifier,
1703
+ participant_id: identifier,
1704
+ person_uid: text4,
1705
+ previous_person_uid: nullableText,
1706
+ changed: flag
1707
+ });
1708
+ var meetingChange = strictObject({
1709
+ scope,
1710
+ account_id: identifier,
1711
+ meeting_id: identifier,
1712
+ change: union([eventChange, personChange]),
1713
+ applied: flag,
1714
+ result: optional(union([eventResult, personResult]))
1715
+ });
1716
+ var recognition = strictObject({
1717
+ engine: text4,
1718
+ model: text4,
1719
+ version: optional(text4),
1720
+ timing: optional(picklist(["fixed-windows", "recognition-segments"]))
1721
+ });
1722
+ var transcription = union([
1723
+ strictObject({
1724
+ applied: literal(false),
1725
+ account_id: identifier,
1726
+ external_id: text4,
1727
+ segments: count3,
1728
+ media: strictObject({
1729
+ id: text4,
1730
+ content_hash: text4,
1731
+ size: count3,
1732
+ duration_ms: count3,
1733
+ format: text4,
1734
+ sample_rate: count3,
1735
+ channels: count3,
1736
+ recognition
1737
+ })
1738
+ }),
1739
+ strictObject({
1740
+ applied: literal(true),
1741
+ account_id: identifier,
1742
+ external_id: text4,
1743
+ meeting_id: identifier,
1744
+ created: flag,
1745
+ inserted_transcripts: count3,
1746
+ replayed_transcripts: count3,
1747
+ superseded_transcripts: count3,
1748
+ segments: count3,
1749
+ media_sha256: text4,
1750
+ engine: text4,
1751
+ model: text4,
1752
+ model_version: nullableText,
1753
+ timing: picklist(["fixed-windows", "recognition-segments"])
1754
+ })
1755
+ ]);
1756
+ var embeddingModel = strictObject({ key: text4, dims: count3, kind: picklist(["local", "remote"]), model: text4 });
1757
+ var embedding = union([
1758
+ strictObject({
1759
+ account_id: identifier,
1760
+ model: embeddingModel,
1761
+ status: strictObject({ chunks: count3, embedded: count3 }),
1762
+ applied: literal(false),
1763
+ scope: literal("existing-current-chunks"),
1764
+ rebuild_required: literal("explicit")
1765
+ }),
1766
+ strictObject({
1767
+ account_id: identifier,
1768
+ model: embeddingModel,
1769
+ saved: count3,
1770
+ skipped: count3,
1771
+ has_more: flag,
1772
+ next_hash: optional(text4),
1773
+ applied: literal(true),
1774
+ rebuild: strictObject({
1775
+ transcripts: count3,
1776
+ chunks: count3,
1777
+ has_more: flag,
1778
+ next_transcript_id: optional(identifier)
1779
+ })
1780
+ })
1781
+ ]);
1782
+ var MEETING_RESULT_ENTITIES = {
1783
+ meeting_ingestion: run,
1784
+ meeting_export: exported,
1785
+ meeting_association: meetingChange,
1786
+ meeting_transcription: transcription,
1787
+ meeting_embedding: embedding
1788
+ };
1789
+
1790
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/event-query.js
1791
+ var EVENT_QUERY = defineQuery({
1792
+ entity: "event",
1793
+ backend: "sql",
1794
+ fields: [
1795
+ { name: "id", type: "num", operators: ["term", "range"], example: "id:1" },
1796
+ { name: "origin", type: "enum", operators: ["term"], values: ["auto", "owner"], example: "origin:owner" },
1797
+ ...["starts_at", "ends_at", "created_at", "updated_at"].map((name) => ({
1798
+ name,
1799
+ type: "time",
1800
+ operators: ["term", "range"],
1801
+ example: `${name}>=2026-01-01`
1802
+ }))
1803
+ ]
1804
+ });
1805
+
1806
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/events.js
1807
+ var linkEvent = /* @__PURE__ */ __name(async (store, details, now = Date.now()) => {
1808
+ const current = await store.meeting(details.meeting.id);
1809
+ if (!current)
1810
+ return null;
1811
+ const { meeting: meeting2, series } = current;
1812
+ if (meeting2.eventId !== null)
1813
+ return (await store.events()).find((e) => e.id === meeting2.eventId) ?? null;
1814
+ const candidates = meeting2.startedAt === null ? [] : await store.eventCandidates({
1815
+ meetingSeriesId: meeting2.meetingSeriesId,
1816
+ joinUrl: meeting2.joinUrl,
1817
+ startsAt: meeting2.startedAt,
1818
+ endsAt: meeting2.endedAt ?? meeting2.startedAt
1819
+ });
1820
+ if (candidates.length > 1) {
1821
+ await store.reviewMeetingLink?.(meeting2.id, candidates.map(({ id: id3 }) => id3), now);
1822
+ return null;
1823
+ }
1824
+ let event2 = candidates[0];
1825
+ if (!event2) {
1826
+ let eventSeriesId = series?.eventSeriesId ?? null;
1827
+ if (series?.kind === "recurring" && eventSeriesId === null) {
1828
+ const created = await store.createEventSeries({ title: series.title, recurrence: null, origin: "auto" }, now);
1829
+ eventSeriesId = created.id;
1830
+ await store.setEventSeries(series.id, eventSeriesId, now);
1831
+ }
1832
+ event2 = await store.createEvent({
1833
+ eventSeriesId,
1834
+ title: meeting2.title,
1835
+ description: meeting2.description,
1836
+ location: meeting2.location,
1837
+ startsAt: meeting2.startedAt,
1838
+ endsAt: meeting2.endedAt,
1839
+ timezone: meeting2.timezone,
1840
+ origin: "auto",
1841
+ deletedAt: null
1842
+ }, now);
1843
+ }
1844
+ await store.linkMeeting(meeting2.id, event2.id, now);
1845
+ const linked = await store.meeting(meeting2.id);
1846
+ return (await store.events()).find((e) => e.id === linked?.meeting.eventId) ?? null;
1847
+ }, "linkEvent");
1848
+
1849
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/hit-query.js
1850
+ var context = {
1851
+ command: "search meetings",
1852
+ guide: "https://github.com/WireCatLabs/cli-core/blob/main/docs/search/query-language.md#\u0432\u0441\u0442\u0440\u0435\u0447\u0438"
1853
+ };
1854
+ var words = ["term", "phrase"];
1855
+ var MOST_LINES_APART = 20;
1856
+ var near = /* @__PURE__ */ __name((node) => {
1857
+ if (node.slop !== void 0 && node.slop > MOST_LINES_APART)
1858
+ queryError("query.invalid-number", node.span, `words at most ${MOST_LINES_APART} lines apart: "a b"~${MOST_LINES_APART}`, context);
1859
+ }, "near");
1860
+ var MEETING_HIT_QUERY = defineQuery({
1861
+ entity: "meeting_hit",
1862
+ backend: "sql",
1863
+ fields: [
1864
+ {
1865
+ name: "text",
1866
+ type: "txt",
1867
+ operators: words,
1868
+ example: "text:budget",
1869
+ relation: "a passage with the word in any form, or a spelling speech recognition garbled",
1870
+ validate: near
1871
+ },
1872
+ {
1873
+ name: "exact",
1874
+ type: "txt",
1875
+ operators: words,
1876
+ example: "exact:budget",
1877
+ relation: "a passage with the word as typed: no other forms, no garbled spellings",
1878
+ validate: near
1879
+ },
1880
+ {
1881
+ name: "from",
1882
+ type: "kw",
1883
+ operators: words,
1884
+ example: 'from:"Alice Synthetic"',
1885
+ relation: "a line said or a chat message written by this person; attendance is --identity-id"
1886
+ }
1887
+ ]
1888
+ });
1889
+ var MEETING_FIELDS = defineQuery({
1890
+ entity: "meeting_hit",
1891
+ backend: "sql",
1892
+ fields: [
1893
+ ...MEETING_HIT_QUERY.fields,
1894
+ {
1895
+ name: "date",
1896
+ type: "time",
1897
+ operators: ["term", "range"],
1898
+ example: "date>=30d",
1899
+ relation: "meetings that started then; the same as --since-time and --until-time"
1900
+ },
1901
+ ...["project", "tag", "topic"].map((name) => ({
1902
+ name,
1903
+ type: "kw",
1904
+ operators: words,
1905
+ example: `${name}:"Example name"`,
1906
+ relation: `meetings in this ${name}, by name or alias; the same as --${name}`
1907
+ }))
1908
+ ]
1909
+ });
1910
+ var parseMeetingQuery = /* @__PURE__ */ __name((query) => validateQuery(parseLucene(query, { defaultField: "text", proximity: true, ...context }), MEETING_HIT_QUERY, context), "parseMeetingQuery");
1911
+
1912
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/ingest.js
1913
+ var contentHash = /* @__PURE__ */ __name(async (text6) => {
1914
+ const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text6));
1915
+ return Array.from(new Uint8Array(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("");
1916
+ }, "contentHash");
1917
+ var speakerPosition = /* @__PURE__ */ __name((name, participants) => {
1918
+ if (name === null)
1919
+ return null;
1920
+ const matches3 = participants.flatMap((p, i) => p.displayName === name ? [i] : []);
1921
+ return matches3.length === 1 ? matches3[0] ?? null : null;
1922
+ }, "speakerPosition");
1923
+ var transcriptInput = /* @__PURE__ */ __name(async (lines, participants, source, hashText = JSON.stringify(lines), format = null) => ({
1924
+ source,
1925
+ format,
1926
+ language: null,
1927
+ contentHash: await contentHash(hashText),
1928
+ externalCreatedAt: null,
1929
+ metadata: null,
1930
+ deletedAt: null,
1931
+ rows: lines.map((line2, position) => ({
1932
+ position,
1933
+ startMs: line2.startMs,
1934
+ endMs: line2.endMs,
1935
+ speakerParticipantPosition: speakerPosition(line2.speaker, participants),
1936
+ speakerName: line2.speaker,
1937
+ text: line2.text,
1938
+ normalizedText: null,
1939
+ metadata: null
1940
+ }))
1941
+ }), "transcriptInput");
1942
+ var timestamp2 = /* @__PURE__ */ __name((value) => {
1943
+ const time = Date.parse(value);
1944
+ if (!Number.isFinite(time))
1945
+ throw new Error("Invalid meeting timestamp");
1946
+ return time;
1947
+ }, "timestamp");
1948
+
1949
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/transcript-text.js
1950
+ var TranscriptTextError = class extends Error {
1951
+ static {
1952
+ __name(this, "TranscriptTextError");
1953
+ }
1954
+ name = "TranscriptTextError";
1955
+ };
1956
+ var HEADER = {
1957
+ "\u0412\u0441\u0442\u0440\u0435\u0447\u0430: ": "title",
1958
+ "\u0414\u0430\u0442\u0430: ": "date",
1959
+ "Zoom ID: ": "meetingId",
1960
+ "\u0413\u043E\u0432\u043E\u0440\u044F\u0442: ": "speakers"
1961
+ };
1962
+ var LINE = /^\[(\d{2,}):([0-5]\d):([0-5]\d)\]\s*(?:([^:\n]{1,60}):\s*)?([\s\S]*)$/;
1963
+ var RULE = /^[—–-]{10,}[^\n]*(?:\n|$)/;
1964
+ var EMPTY = /* @__PURE__ */ new Set(["", "\u2014", "-"]);
1965
+ var parseTranscriptText = /* @__PURE__ */ __name((input) => {
1966
+ const text6 = input.replace(/^/, "").replace(/\r\n?/g, "\n");
1967
+ const header = { title: null, date: null, meetingId: null, speakers: [] };
1968
+ let sawHeader = false;
1969
+ for (const line2 of text6.split("\n")) {
1970
+ if (!line2.trim())
1971
+ break;
1972
+ for (const [prefix, key] of Object.entries(HEADER)) {
1973
+ if (!line2.startsWith(prefix))
1974
+ continue;
1975
+ sawHeader = true;
1976
+ const value = line2.slice(prefix.length).trim();
1977
+ if (key === "speakers")
1978
+ header.speakers = value.split(",").map((name) => name.trim()).filter((name) => !EMPTY.has(name));
1979
+ else
1980
+ header[key] = EMPTY.has(value) ? null : value;
1981
+ }
1982
+ }
1983
+ if (!sawHeader)
1984
+ throw new TranscriptTextError('a text transcript starts with a header such as "\u0412\u0441\u0442\u0440\u0435\u0447\u0430: \u2026"');
1985
+ const found = [];
1986
+ for (const block of text6.split(/\n\s*\n/)) {
1987
+ const match = LINE.exec(block.trim().replace(RULE, ""));
1988
+ if (!match)
1989
+ continue;
1990
+ const [, hours = "0", minutes = "0", seconds = "0", speaker, said = ""] = match;
1991
+ found.push({
1992
+ startMs: ((Number(hours) * 60 + Number(minutes)) * 60 + Number(seconds)) * 1e3,
1993
+ speaker: speaker?.trim() || null,
1994
+ text: said.trim()
1995
+ });
1996
+ }
1997
+ const lines = found.map((line2, at) => ({
1998
+ ...line2,
1999
+ endMs: Math.max(line2.startMs, found[at + 1]?.startMs ?? line2.startMs)
2000
+ }));
2001
+ return { header, lines };
2002
+ }, "parseTranscriptText");
2003
+
2004
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/vtt.js
2005
+ var VttError = class extends Error {
2006
+ static {
2007
+ __name(this, "VttError");
2008
+ }
2009
+ name = "VttError";
2010
+ };
2011
+ var TIMESTAMP = /^(?:(\d+):)?([0-5]\d):([0-5]\d)\.(\d{3})$/;
2012
+ var SKIPPED = /^(NOTE|STYLE|REGION)(\s|$)/;
2013
+ var millis = /* @__PURE__ */ __name((stamp, lineNo) => {
2014
+ const match = TIMESTAMP.exec(stamp);
2015
+ if (!match)
2016
+ throw new VttError(`line ${lineNo}: "${stamp}" is not a WebVTT timestamp`);
2017
+ const [, hours = "0", minutes = "0", seconds = "0", ms = "0"] = match;
2018
+ return ((Number(hours) * 60 + Number(minutes)) * 60 + Number(seconds)) * 1e3 + Number(ms);
2019
+ }, "millis");
2020
+ var splitSpeaker = /* @__PURE__ */ __name((text6) => {
2021
+ const firstLine = text6.split("\n", 1)[0] ?? "";
2022
+ const at = firstLine.indexOf(": ");
2023
+ if (at <= 0)
2024
+ return { speaker: null, text: text6 };
2025
+ return { speaker: firstLine.slice(0, at).trim(), text: text6.slice(at + 2) };
2026
+ }, "splitSpeaker");
2027
+ var parseVtt = /* @__PURE__ */ __name((input) => {
2028
+ const lines = input.replace(/^/, "").split(/\r\n|\r|\n/);
2029
+ if (!/^WEBVTT([ \t].*)?$/.test(lines[0] ?? ""))
2030
+ throw new VttError('line 1: a WebVTT file starts with "WEBVTT"');
2031
+ const cues = [];
2032
+ let i = lines.findIndex((line2) => line2.trim() === "");
2033
+ if (i < 0)
2034
+ return [];
2035
+ while (i < lines.length) {
2036
+ while (i < lines.length && lines[i]?.trim() === "")
2037
+ i++;
2038
+ const start = i;
2039
+ while (i < lines.length && lines[i]?.trim() !== "")
2040
+ i++;
2041
+ const block = lines.slice(start, i);
2042
+ if (block.length === 0 || SKIPPED.test(block[0] ?? ""))
2043
+ continue;
2044
+ const timingAt = block.findIndex((line2) => line2.includes("-->"));
2045
+ if (timingAt < 0 || timingAt > 1)
2046
+ throw new VttError(`line ${start + 1}: a cue has no timing line`);
2047
+ const lineNo = start + timingAt + 1;
2048
+ const [from = "", rest = ""] = (block[timingAt] ?? "").split("-->");
2049
+ const to = rest.trim().split(/\s+/)[0] ?? "";
2050
+ const text6 = block.slice(timingAt + 1).join("\n").trim();
2051
+ cues.push({ startMs: millis(from.trim(), lineNo), endMs: millis(to, lineNo), ...splitSpeaker(text6) });
2052
+ }
2053
+ return cues;
2054
+ }, "parseVtt");
2055
+
2056
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/import.js
2057
+ var importFiles = /* @__PURE__ */ __name(async (files, store, now = Date.now()) => {
2058
+ const report = { meetings: 0, participants: 0, transcriptRows: 0, summaries: 0, warnings: [] };
2059
+ for (const file of files) {
2060
+ try {
2061
+ const format = file.format ?? "vtt";
2062
+ const lines = format === "text" ? parseTranscriptText(file.content).lines : parseVtt(file.content);
2063
+ const participants = file.participants ?? [];
2064
+ const details = await store.saveMeeting({
2065
+ meeting: file.meeting,
2066
+ participants: file.participants,
2067
+ transcripts: [await transcriptInput(lines, participants, file.source ?? "file", file.content, format)],
2068
+ now,
2069
+ fromFile: true
2070
+ });
2071
+ await linkEvent(store, details, now);
2072
+ report.meetings++;
2073
+ report.participants += participants.length;
2074
+ report.transcriptRows += lines.length;
2075
+ } catch (error) {
2076
+ report.warnings.push({
2077
+ externalId: file.meeting.externalId,
2078
+ message: error instanceof Error ? error.message : "Meeting import failed"
2079
+ });
2080
+ }
2081
+ }
2082
+ const zones = new Set(files.map((file) => file.meeting.timezone).filter((zone2) => zone2 !== null && zone2 !== void 0));
2083
+ const [zone] = zones;
2084
+ if (zones.size === 1 && zone)
2085
+ report.timezone = zone;
2086
+ return report;
2087
+ }, "importFiles");
2088
+
2089
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/links.js
2090
+ var CHAT_MESSAGES_READ = 1e5;
2091
+
2092
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/passage.js
2093
+ var meetingHitContextLimits = /* @__PURE__ */ __name((options = {}) => {
2094
+ const { before = 3, after = 3, bytes = 65536, max_read_bytes = 4194304, expected_fingerprint } = options;
2095
+ if (![before, after].every((value) => Number.isSafeInteger(value) && value >= 0) || before + after > 999 || !Number.isSafeInteger(bytes) || bytes < 2 || bytes > 4194304 || !Number.isSafeInteger(max_read_bytes) || max_read_bytes < 1 || max_read_bytes > 67108864 || expected_fingerprint !== void 0 && (typeof expected_fingerprint !== "string" || !/^[a-f0-9]{64}$/.test(expected_fingerprint)))
2096
+ throw new CliError("validation_error", "context takes 0\u2013999 surrounding cues, 2\u20134194304 output bytes and a bounded read budget");
2097
+ return { before, after, bytes, max_read_bytes };
2098
+ }, "meetingHitContextLimits");
2099
+ var validateMeetingPassage = /* @__PURE__ */ __name((reference2, options) => {
2100
+ meetingHitContextLimits(options);
2101
+ if (typeof reference2 !== "string" || !reference2.trim() || reference2.length > 200 || options.format !== void 0 && !["json", "text", "markdown"].includes(options.format))
2102
+ throw new CliError("validation_error", "choose a cue reference and json, text or markdown output");
2103
+ }, "validateMeetingPassage");
2104
+
2105
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/preparation-context.js
2106
+ var validateMeetingPreparationContext = /* @__PURE__ */ __name((original) => {
2107
+ if (!original || typeof original !== "object" || Array.isArray(original))
2108
+ throw new CliError("validation_error", "meeting preparation context is required");
2109
+ const input = { ...original };
2110
+ for (const key of Object.keys(input))
2111
+ if (!["accountId", "meetingId", "seriesId", "updatedAt", "limit", "maxReadBytes", "signal"].includes(key))
2112
+ throw new CliError("validation_error", `unknown preparation context field: ${key}`);
2113
+ if (input.signal !== void 0 && !(input.signal instanceof AbortSignal))
2114
+ throw new CliError("validation_error", "signal must be an AbortSignal");
2115
+ input.signal?.throwIfAborted();
2116
+ for (const key of ["accountId", "meetingId", "seriesId"])
2117
+ if (!Number.isSafeInteger(input[key]) || input[key] <= 0)
2118
+ throw new CliError("validation_error", `${key} must be a positive safe integer`);
2119
+ if (!Number.isSafeInteger(input.updatedAt) || Math.abs(input.updatedAt) > 864e13)
2120
+ throw new CliError("validation_error", "updatedAt must be an absolute timestamp");
2121
+ const limit = input.limit === void 0 ? 20 : input.limit;
2122
+ const maxReadBytes = input.maxReadBytes === void 0 ? 262144 : input.maxReadBytes;
2123
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
2124
+ throw new CliError("validation_error", "limit must be an integer from 1 to 100");
2125
+ if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4194304)
2126
+ throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
2127
+ return { ...input, limit, maxReadBytes };
2128
+ }, "validateMeetingPreparationContext");
2129
+
2130
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/project-evidence-answer.js
2131
+ var count4 = pipe(number(), integer(), minValue(0));
2132
+ var id = pipe(string(), minLength(1));
2133
+ var meetingProjectEvidence = strictObject({
2134
+ schema_version: literal(1),
2135
+ kind: literal("meeting_project_evidence"),
2136
+ account_id: id,
2137
+ query: string(),
2138
+ project: strictObject({ id, name: string(), key: nullable(string()) }),
2139
+ term: strictObject({
2140
+ name: string(),
2141
+ kind: picklist(["canonical", "key", "alias"]),
2142
+ alias_id: optional(id)
2143
+ }),
2144
+ hits: array(meetingHit),
2145
+ association: literal("unconfirmed-word-evidence"),
2146
+ vocabulary_fingerprint: id,
2147
+ selection: strictObject({
2148
+ meeting_id: optional(id),
2149
+ identity_id: optional(id),
2150
+ person_id: optional(id),
2151
+ tag_id: optional(id),
2152
+ event_id: optional(id),
2153
+ series_id: optional(id),
2154
+ since: optional(isoTime),
2155
+ until: optional(isoTime)
2156
+ }),
2157
+ limits: strictObject({ limit: count4, max_read_bytes: count4, max_vocabulary_read_bytes: count4, max_terms: count4 }),
2158
+ page: pageSchema,
2159
+ coverage: strictObject({
2160
+ archive_completeness: literal("unknown"),
2161
+ current_revisions: literal(true),
2162
+ indexing: picklist(["ready", "pending"]),
2163
+ index_completeness: literal("unknown"),
2164
+ term_index: count4,
2165
+ terms_total: count4,
2166
+ remaining_terms: count4,
2167
+ duplicates: literal("may-repeat-between-terms")
2168
+ })
2169
+ });
2170
+ var PAGE_NEXT3 = STEPS.find((step) => step.id === "page.next");
2171
+ var meetingProjectEvidenceAnswer = /* @__PURE__ */ __name((page, prepared, command = "meetings projects evidence") => {
2172
+ const { options } = prepared;
2173
+ const selection = {};
2174
+ for (const [field, value] of [
2175
+ ["meeting_id", options.meetingId],
2176
+ ["identity_id", options.participantIdentityId],
2177
+ ["person_id", options.personId],
2178
+ ["tag_id", options.tagId],
2179
+ ["event_id", options.eventId],
2180
+ ["series_id", options.meetingSeriesId]
2181
+ ])
2182
+ if (value !== void 0)
2183
+ selection[field] = String(value);
2184
+ if (options.since !== void 0)
2185
+ selection.since = new Date(options.since).toISOString();
2186
+ if (options.until !== void 0)
2187
+ selection.until = new Date(options.until).toISOString();
2188
+ const cursor = page.nextCursor ?? void 0;
2189
+ if (page.hasMore !== (cursor !== void 0))
2190
+ throw new CliError("invalid_response", "project evidence continuation is inconsistent");
2191
+ const item = {
2192
+ schema_version: 1,
2193
+ kind: "meeting_project_evidence",
2194
+ account_id: String(page.accountId),
2195
+ query: page.query,
2196
+ project: page.project,
2197
+ term: {
2198
+ name: page.term.name,
2199
+ kind: page.term.kind,
2200
+ ...page.term.aliasId === void 0 ? {} : { alias_id: page.term.aliasId }
2201
+ },
2202
+ hits: page.hits.map(meetingHitItem),
2203
+ association: page.association,
2204
+ vocabulary_fingerprint: page.vocabularyFingerprint,
2205
+ selection,
2206
+ limits: {
2207
+ limit: page.limits.limit,
2208
+ max_read_bytes: page.limits.maxReadBytes,
2209
+ max_vocabulary_read_bytes: page.limits.maxVocabularyReadBytes,
2210
+ max_terms: page.limits.maxTerms
2211
+ },
2212
+ page: {
2213
+ mode: "cursor",
2214
+ limit: page.limits.limit,
2215
+ has_more: page.hasMore,
2216
+ ...cursor === void 0 ? {} : { next_cursor: cursor }
2217
+ },
2218
+ coverage: {
2219
+ archive_completeness: page.coverage.archiveCompleteness,
2220
+ current_revisions: page.coverage.currentRevisions,
2221
+ indexing: page.coverage.indexing,
2222
+ index_completeness: page.coverage.indexCompleteness,
2223
+ term_index: page.coverage.termIndex,
2224
+ terms_total: page.coverage.termsTotal,
2225
+ remaining_terms: page.coverage.remainingTerms,
2226
+ duplicates: page.coverage.duplicates
2227
+ }
2228
+ };
2229
+ if (!safeParse(meetingProjectEvidence, item).success)
2230
+ throw new CliError("invalid_response", "project evidence does not match its answer contract");
2231
+ return {
2232
+ item,
2233
+ ...cursor === void 0 ? {} : {
2234
+ next: [
2235
+ stepOf(PAGE_NEXT3, {
2236
+ command,
2237
+ args: {
2238
+ project: prepared.project,
2239
+ query: prepared.query,
2240
+ cursor,
2241
+ limit: page.limits.limit,
2242
+ max_read_bytes: page.limits.maxReadBytes
2243
+ },
2244
+ values: { shown: page.hits.length }
2245
+ })
2246
+ ]
2247
+ }
2248
+ };
2249
+ }, "meetingProjectEvidenceAnswer");
2250
+
2251
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/search-validation.js
2252
+ var validateMeetingHitSearch = /* @__PURE__ */ __name((query, options = {}) => {
2253
+ const integer3 = /* @__PURE__ */ __name((value, low, high) => Number.isSafeInteger(value) && value >= low && value <= high, "integer");
2254
+ if (typeof query !== "string" || !query.trim() || query.includes("\0") || new TextEncoder().encode(query).byteLength > 65536 || !integer3(options.limit ?? 100, 1, 1e3) || !integer3(options.maxReadBytes ?? 4194304, 1, 67108864) || [
2255
+ options.meetingId,
2256
+ options.participantIdentityId,
2257
+ options.personId,
2258
+ options.projectId,
2259
+ options.tagId,
2260
+ options.eventId,
2261
+ options.meetingSeriesId
2262
+ ].some((value) => value !== void 0 && !integer3(value, 1, Number.MAX_SAFE_INTEGER)) || [options.since, options.until].some((value) => value !== void 0 && !integer3(value, -864e13, 864e13)) || options.since !== void 0 && options.until !== void 0 && options.since > options.until || options.after !== void 0 && (typeof options.after !== "string" || !/^[A-Za-z0-9_-]{1,1000}$/.test(options.after)))
2263
+ throw new CliError("validation_error", "invalid bounded meeting search query, cursor or limits");
2264
+ for (const name of [options.project, options.tag, options.topic])
2265
+ if (name !== void 0 && (typeof name !== "string" || !name.trim() || name.length > 200 || /[\p{Cc}\p{Cf}]/u.test(name)))
2266
+ throw new CliError("validation_error", "a meeting vocabulary name takes 1\u2013200 characters without control characters");
2267
+ if (options.project !== void 0 && options.projectId !== void 0 || [options.tag, options.topic, options.tagId].filter((value) => value !== void 0).length > 1)
2268
+ throw new CliError("validation_error", "choose one project selector and one tag or topic selector");
2269
+ }, "validateMeetingHitSearch");
2270
+
2271
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/project-evidence-query.js
2272
+ var ids = {
2273
+ meeting_id: "meetingId",
2274
+ identity_id: "participantIdentityId",
2275
+ person_id: "personId",
2276
+ tag_id: "tagId",
2277
+ event_id: "eventId",
2278
+ series_id: "meetingSeriesId"
2279
+ };
2280
+ var context2 = {
2281
+ command: "meetings projects evidence",
2282
+ guide: "https://github.com/WireCatLabs/cli-core/blob/main/docs/search/query-language.md"
2283
+ };
2284
+ var MEETING_PROJECT_EVIDENCE_QUERY = defineQuery({
2285
+ entity: "meeting_project_evidence",
2286
+ backend: "sql",
2287
+ fields: [
2288
+ ...Object.keys(ids).map((name) => ({
2289
+ name,
2290
+ type: "num",
2291
+ operators: ["term"],
2292
+ example: `${name}:12`,
2293
+ placement: "and",
2294
+ relation: "meetings selected by this stored ID; identity selects participants, not speakers"
2295
+ })),
2296
+ {
2297
+ name: "started_at",
2298
+ type: "time",
2299
+ operators: ["term", "phrase", "range"],
2300
+ example: "started_at:[2026-10-01 TO 2026-10-31]",
2301
+ placement: "and",
2302
+ relation: "the meeting start time in UTC"
2303
+ }
2304
+ ]
2305
+ });
2306
+ var requestKeys = /* @__PURE__ */ new Set(["query", "limit", "cursor", "maxReadBytes", "signal"]);
2307
+ var prepareMeetingProjectEvidence = /* @__PURE__ */ __name((project, request = {}, now = Date.now()) => {
2308
+ if (!request || typeof request !== "object" || Array.isArray(request) || Object.keys(request).some((key) => !requestKeys.has(key)) || typeof project !== "string" || !project.trim() || project.length > 200 || /[\p{Cc}\p{Cf}]/u.test(project) || request.query !== void 0 && typeof request.query !== "string")
2309
+ throw new CliError("validation_error", "expected an existing project and bounded evidence arguments");
2310
+ if (request.query !== void 0 && new TextEncoder().encode(request.query).byteLength > 8192 || [request.limit, request.maxReadBytes].some((value) => value !== void 0 && typeof value !== "number"))
2311
+ throw new CliError("validation_error", "invalid project evidence query or budget");
2312
+ request.signal?.throwIfAborted();
2313
+ const options = {
2314
+ limit: request.limit ?? 100,
2315
+ maxReadBytes: request.maxReadBytes ?? 4194304,
2316
+ ...request.cursor === void 0 ? {} : { cursor: request.cursor },
2317
+ ...request.signal === void 0 ? {} : { signal: request.signal }
2318
+ };
2319
+ const terms = /* @__PURE__ */ new Map();
2320
+ if (request.query?.trim()) {
2321
+ const ast = parseLucene(request.query, { defaultField: "none", ...context2 });
2322
+ validateQuery(ast, MEETING_PROJECT_EVIDENCE_QUERY, context2);
2323
+ const add = /* @__PURE__ */ __name((node) => {
2324
+ if (terms.has(node.field))
2325
+ queryError("query.unsupported-placement", node.span, "each field only once", context2);
2326
+ terms.set(node.field, node);
2327
+ }, "add");
2328
+ if (ast.root.kind === "predicate")
2329
+ add(ast.root);
2330
+ else
2331
+ for (const clause of ast.root.clauses) {
2332
+ if (clause.occur !== "must" || clause.node.kind !== "predicate")
2333
+ queryError("query.unsupported-placement", clause.node.span, "field:value terms joined by AND", context2);
2334
+ add(clause.node);
2335
+ }
2336
+ }
2337
+ const frozen = [];
2338
+ for (const [field, key] of Object.entries(ids)) {
2339
+ const term2 = terms.get(field);
2340
+ if (!term2)
2341
+ continue;
2342
+ if (term2.operator !== "term" || !/^[1-9]\d*$/.test(term2.value) || !Number.isSafeInteger(Number(term2.value)))
2343
+ queryError("query.unsupported-operator", term2.span, "one positive safe integer ID", context2);
2344
+ options[key] = Number(term2.value);
2345
+ frozen.push(`${field}:${term2.value}`);
2346
+ }
2347
+ const term = terms.get("started_at");
2348
+ if (term) {
2349
+ const range = dateRange(term.value, term.operator === "range" ? term.upper ?? "*" : term.value, term.lower_inclusive !== false, term.upper_inclusive !== false, "UTC", term.span, now);
2350
+ if (range.lower !== void 0)
2351
+ options.since = range.lower + (range.lower_inclusive ? 0 : 1);
2352
+ if (range.upper !== void 0)
2353
+ options.until = range.upper - (range.upper_inclusive ? 0 : 1);
2354
+ frozen.push(`started_at:[${options.since === void 0 ? "*" : `"${new Date(options.since).toISOString()}"`} TO ${options.until === void 0 ? "*" : `"${new Date(options.until).toISOString()}"`}]`);
2355
+ }
2356
+ validateMeetingHitSearch(project, options);
2357
+ if (options.cursor !== void 0 && (typeof options.cursor !== "string" || !/^[A-Za-z0-9_-]{1,4096}$/.test(options.cursor)))
2358
+ throw new CliError("validation_error", "invalid project evidence cursor");
2359
+ return { project: project.trim(), options, query: frozen.join(" AND ") };
2360
+ }, "prepareMeetingProjectEvidence");
2361
+
2362
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/project-evidence.js
2363
+ var readMeetingProjectEvidence = /* @__PURE__ */ __name(async (read, project, request = {}, now = Date.now()) => {
2364
+ const prepared = prepareMeetingProjectEvidence(project, request, now);
2365
+ const page = await read(prepared.project, prepared.options);
2366
+ prepared.options.signal?.throwIfAborted();
2367
+ return meetingProjectEvidenceAnswer(page, prepared);
2368
+ }, "readMeetingProjectEvidence");
2369
+
2370
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/pull.js
2371
+ var participantInput = /* @__PURE__ */ __name((p, provider, occurrenceId2, position, accountId) => {
2372
+ const { identityExternalId, ...fields2 } = p;
2373
+ const externalId = identityExternalId ?? (p.email ? `email:${p.email.toLowerCase()}` : p.externalId) ?? `name:${p.displayName ?? "unknown"}@${accountId}/${occurrenceId2}:${position}`;
2374
+ return {
2375
+ ...fields2,
2376
+ identity: {
2377
+ provider,
2378
+ externalId,
2379
+ name: p.displayName,
2380
+ metadata: p.metadata,
2381
+ associatePerson: Boolean(identityExternalId?.trim() || p.email?.trim() || p.externalId?.trim())
2382
+ }
2383
+ };
2384
+ }, "participantInput");
2385
+ var pull = /* @__PURE__ */ __name(async (source, store, options) => {
2386
+ const now = options.now ?? Date.now();
2387
+ const lookbackMs = options.lookbackMs ?? 0;
2388
+ if (!Number.isSafeInteger(lookbackMs) || lookbackMs < 0 || lookbackMs > 31 * 864e5)
2389
+ throw new Error("lookbackMs must be an integer from 0 through 31 days");
2390
+ const since = options.since ?? await store.cursor(options.accountId) ?? new Date(now - 30 * 864e5).toISOString();
2391
+ timestamp2(since);
2392
+ const report = { meetings: 0, participants: 0, transcriptRows: 0, summaries: 0, warnings: [] };
2393
+ let failed = false;
2394
+ const from = timestamp2(since) - lookbackMs;
2395
+ const meetings = await source.meetings(lookbackMs === 0 ? since : new Date(from).toISOString());
2396
+ for (const m of meetings) {
2397
+ const id3 = m.occurrence.id;
2398
+ const read = /* @__PURE__ */ __name(async (part, call) => {
2399
+ try {
2400
+ return await call();
2401
+ } catch (error) {
2402
+ failed = true;
2403
+ const message = error instanceof Error ? error.message : "could not be read";
2404
+ report.warnings.push({ externalId: id3, message: `${part}: ${message}` });
2405
+ return void 0;
2406
+ }
2407
+ }, "read");
2408
+ try {
2409
+ const sourceParticipants = await read("participants", () => source.participants(id3));
2410
+ const participants = (sourceParticipants ?? []).map((p, i) => participantInput(p, source.provider, id3, i, options.accountId));
2411
+ const names = /* @__PURE__ */ new Map();
2412
+ for (const p of participants)
2413
+ if (p.displayName !== null) {
2414
+ const identities = names.get(p.displayName) ?? /* @__PURE__ */ new Set();
2415
+ identities.add(p.identity.externalId);
2416
+ names.set(p.displayName, identities);
2417
+ }
2418
+ if ([...names.values()].some((ids2) => ids2.size > 1))
2419
+ report.warnings.push({ externalId: id3, message: "Participant names are ambiguous" });
2420
+ const lines = await read("transcript", () => source.transcript(id3));
2421
+ const chat = await read("chat", () => source.chat(id3));
2422
+ const summary = await read("summary", () => source.summary(id3));
2423
+ const attachments = await read("files", () => source.files(id3));
2424
+ const startedAt = timestamp2(m.occurrence.startedAt);
2425
+ const endedAt = m.occurrence.endedAt === null ? null : timestamp2(m.occurrence.endedAt);
2426
+ if (endedAt !== null && endedAt < startedAt)
2427
+ throw new Error("Meeting ends before it starts");
2428
+ const meeting2 = {
2429
+ accountId: options.accountId,
2430
+ externalId: id3,
2431
+ title: m.occurrence.title,
2432
+ description: m.description ?? null,
2433
+ location: m.location ?? null,
2434
+ joinUrl: m.joinUrl ?? m.series?.joinUrl ?? null,
2435
+ startedAt,
2436
+ endedAt,
2437
+ durationMs: endedAt === null ? null : endedAt - startedAt,
2438
+ timezone: m.timezone ?? null,
2439
+ hostIdentityId: null,
2440
+ ...sourceParticipants === void 0 ? {} : { participantsCount: sourceParticipants?.length ?? null },
2441
+ metadata: m.metadata ?? null,
2442
+ deletedAt: null
2443
+ };
2444
+ if (m.series)
2445
+ meeting2.series = {
2446
+ externalId: m.series.id,
2447
+ title: m.series.title,
2448
+ description: null,
2449
+ kind: m.series.kind ?? null,
2450
+ recurrence: m.series.recurrence ?? null,
2451
+ hostIdentityId: null,
2452
+ joinUrl: m.series.joinUrl ?? null,
2453
+ metadata: null,
2454
+ deletedAt: null
2455
+ };
2456
+ const linked = sourceParticipants !== void 0;
2457
+ const format = source.transcriptFormat ?? null;
2458
+ const transcripts = lines && linked ? [await transcriptInput(lines, participants, source.name, void 0, format)] : void 0;
2459
+ const details = await store.saveMeeting({
2460
+ meeting: meeting2,
2461
+ participants: sourceParticipants ? participants : void 0,
2462
+ transcripts,
2463
+ chat: chat?.map((line2) => ({
2464
+ externalId: null,
2465
+ sentAt: timestamp2(line2.sentAt),
2466
+ senderParticipantPosition: speakerPosition(line2.sender, participants),
2467
+ senderName: line2.sender,
2468
+ recipient: null,
2469
+ text: line2.text,
2470
+ normalizedText: null,
2471
+ metadata: null
2472
+ })),
2473
+ summaries: summary ? [
2474
+ {
2475
+ ...summary,
2476
+ source: summary.source ?? source.name,
2477
+ content: summary.content ?? null,
2478
+ docUrl: summary.docUrl ?? null,
2479
+ externalCreatedAt: summary.externalCreatedAt ?? null,
2480
+ externalUpdatedAt: summary.externalUpdatedAt ?? null,
2481
+ metadata: summary.metadata ?? null
2482
+ }
2483
+ ] : void 0,
2484
+ attachments: attachments ?? void 0,
2485
+ now
2486
+ });
2487
+ if (lines && !linked && !details.transcripts.some((t) => t.transcript.source === source.name && t.transcript.supersededAt === null))
2488
+ await store.saveMeeting({
2489
+ meeting: meeting2,
2490
+ transcripts: [await transcriptInput(lines, [], source.name, `${JSON.stringify(lines)}
2491
+ unlinked`, format)],
2492
+ now
2493
+ });
2494
+ await linkEvent(store, details, now);
2495
+ report.meetings++;
2496
+ report.participants += participants.length;
2497
+ report.transcriptRows += lines?.length ?? 0;
2498
+ report.summaries += summary ? 1 : 0;
2499
+ } catch (error) {
2500
+ failed = true;
2501
+ report.warnings.push({ externalId: id3, message: error instanceof Error ? error.message : "Meeting pull failed" });
2502
+ }
2503
+ }
2504
+ if (!failed)
2505
+ await store.setCursor(options.accountId, new Date(now).toISOString(), now);
2506
+ return report;
2507
+ }, "pull");
2508
+
2509
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/read-answers.js
2510
+ var text5 = string();
2511
+ var count5 = pipe(number(), integer(), minValue(0));
2512
+ var id2 = pipe(number(), integer(), minValue(1));
2513
+ var iso3 = /* @__PURE__ */ __name((ms) => ms === null ? null : new Date(ms).toISOString(), "iso");
2514
+ var meetingReview = strictObject({
2515
+ ref: reference,
2516
+ id: pipe(string(), minLength(1)),
2517
+ title: nullable(text5),
2518
+ started_at: nullable(isoTime),
2519
+ duration_ms: nullable(count5),
2520
+ participants_count: nullable(count5),
2521
+ projects: array(text5),
2522
+ /** Null when the meeting has no current transcript. */
2523
+ transcript: nullable(strictObject({ lines: count5, words: count5 })),
2524
+ /** The three who talked longest. */
2525
+ speakers: array(strictObject({ name: nullable(text5), talk_ms: count5 })),
2526
+ /** The newest stored summary; null when there is none. */
2527
+ summary: nullable(strictObject({
2528
+ source: text5,
2529
+ title: nullable(text5),
2530
+ overview: nullable(text5),
2531
+ next_steps: array(text5),
2532
+ url: nullable(text5)
2533
+ }))
2534
+ });
2535
+ var meetingLink = strictObject({
2536
+ url: text5,
2537
+ domain: nullable(text5),
2538
+ /** The Google Docs, Sheets, Slides, Forms or Drive file it names. */
2539
+ document_id: nullable(text5),
2540
+ count: count5,
2541
+ first_at: isoTime,
2542
+ last_at: isoTime,
2543
+ senders: array(text5),
2544
+ meetings: array(strictObject({ ref: reference, title: nullable(text5) }))
2545
+ });
2546
+ var meetingSpeaker = strictObject({
2547
+ /** `person:<id>`, `identity:<id>`, `name:<lowercased name>` or `unknown`. */
2548
+ key: text5,
2549
+ name: nullable(text5),
2550
+ person_id: nullable(id2),
2551
+ identity_id: nullable(id2),
2552
+ meetings: count5,
2553
+ lines: count5,
2554
+ words: count5,
2555
+ talk_ms: count5,
2556
+ /** This speaker's part of all talk time, 0–1. */
2557
+ share: pipe(number(), minValue(0), maxValue(1))
2558
+ });
2559
+ var meetingStats = strictObject({
2560
+ time_zone: text5,
2561
+ meetings: count5,
2562
+ lines: count5,
2563
+ words: count5,
2564
+ talk_ms: count5,
2565
+ /** `week_start` is the Monday, as a date in `time_zone`. */
2566
+ weeks: array(strictObject({ week_start: text5, meetings: count5, talk_ms: count5 })),
2567
+ top_speakers: array(meetingSpeaker)
2568
+ });
2569
+ var truncated = /* @__PURE__ */ __name((...why) => nullable(picklist(why)), "truncated");
2570
+ var meetingParticipants = strictObject({
2571
+ schema_version: literal(1),
2572
+ kind: literal("meeting_participants"),
2573
+ account_id: id2,
2574
+ query: text5,
2575
+ items: array(strictObject({
2576
+ participant_id: id2,
2577
+ meeting_id: id2,
2578
+ identity_id: id2,
2579
+ display_name: nullable(text5),
2580
+ email: nullable(text5)
2581
+ })),
2582
+ /** Several identities on one page are observations, never speaker attribution or person links. */
2583
+ ambiguity: strictObject({ scope: literal("page"), multiple_identities: boolean(), identity_ids: array(id2) }),
2584
+ coverage: strictObject({
2585
+ scanned: count5,
2586
+ read_bytes: count5,
2587
+ archive_completeness: literal("unknown"),
2588
+ truncated_by: truncated("limit", "scan_limit", "read_bytes")
2589
+ }),
2590
+ page: strictObject({
2591
+ mode: literal("cursor"),
2592
+ limit: count5,
2593
+ has_more: boolean(),
2594
+ next_cursor: optional(text5)
2595
+ })
2596
+ });
2597
+ var revision = picklist(["current", "superseded"]);
2598
+ var meetingPassage = strictObject({
2599
+ schema_version: literal(1),
2600
+ kind: literal("meeting_context"),
2601
+ source: reference,
2602
+ target_ref: reference,
2603
+ target_fingerprint: text5,
2604
+ fingerprint: text5,
2605
+ revision,
2606
+ limits: strictObject({ before: count5, after: count5, bytes: count5, max_read_bytes: count5 }),
2607
+ content_bytes: count5,
2608
+ coverage: strictObject({
2609
+ included: count5,
2610
+ before: count5,
2611
+ after: count5,
2612
+ has_before: boolean(),
2613
+ has_after: boolean(),
2614
+ truncated_by: truncated("bytes"),
2615
+ before_ref: nullable(reference),
2616
+ after_ref: nullable(reference),
2617
+ continuation: literal("anchor-inclusive"),
2618
+ archive_completeness: literal("unknown"),
2619
+ input: literal("bounded-meeting-context")
2620
+ }),
2621
+ items: array(strictObject({
2622
+ ref: reference,
2623
+ fingerprint: text5,
2624
+ transcript_id: id2,
2625
+ content_hash: nullable(text5),
2626
+ position: count5,
2627
+ start_ms: count5,
2628
+ end_ms: count5,
2629
+ speaker_participant_id: nullable(id2),
2630
+ speaker_name: nullable(text5),
2631
+ text: text5,
2632
+ revision
2633
+ }))
2634
+ });
2635
+ var event = strictObject({
2636
+ id: pipe(string(), minLength(1)),
2637
+ event_series_id: nullable(text5),
2638
+ title: nullable(text5),
2639
+ description: nullable(text5),
2640
+ location: nullable(text5),
2641
+ starts_at: nullable(isoTime),
2642
+ ends_at: nullable(isoTime),
2643
+ timezone: nullable(text5),
2644
+ /** `auto`: made from a meeting; `owner`: made by hand; `calendar`: from a calendar's entries. */
2645
+ origin: picklist(["auto", "owner", "calendar"]),
2646
+ status: nullable(text5),
2647
+ all_day: boolean(),
2648
+ /** When its calendar deleted it: shown as "deleted in Google", kept as history. */
2649
+ source_deleted_at: nullable(isoTime),
2650
+ deleted_at: nullable(isoTime),
2651
+ created_at: isoTime,
2652
+ updated_at: isoTime,
2653
+ /** The fields whoever sent the invitation wrote, on a calendar CLI's `events list`: an agent reads them as data. */
2654
+ untrusted: optional(array(text5))
2655
+ });
2656
+ var eventItem = /* @__PURE__ */ __name((one) => ({
2657
+ id: String(one.id),
2658
+ event_series_id: one.eventSeriesId === null ? null : String(one.eventSeriesId),
2659
+ title: one.title,
2660
+ description: one.description,
2661
+ location: one.location,
2662
+ starts_at: iso3(one.startsAt),
2663
+ ends_at: iso3(one.endsAt),
2664
+ timezone: one.timezone,
2665
+ origin: one.origin,
2666
+ status: one.status ?? null,
2667
+ all_day: one.allDay === true,
2668
+ source_deleted_at: iso3(one.sourceDeletedAt ?? null),
2669
+ deleted_at: iso3(one.deletedAt),
2670
+ created_at: new Date(one.createdAt).toISOString(),
2671
+ updated_at: new Date(one.updatedAt).toISOString()
2672
+ }), "eventItem");
2673
+
2674
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/recording-transfer.js
2675
+ var strongRecordingValidator = /* @__PURE__ */ __name((value) => typeof value === "string" && value.length <= 1024 && /^"[\x21\x23-\x7e\x80-\xff]*"$/.test(value), "strongRecordingValidator");
2676
+
2677
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/related-history.js
2678
+ var validateMeetingRelatedHistory = /* @__PURE__ */ __name((original) => {
2679
+ if (!original || typeof original !== "object" || Array.isArray(original))
2680
+ throw new CliError("validation_error", "related history request is required");
2681
+ const input = { ...original };
2682
+ for (const field of Object.keys(input))
2683
+ if (!["accountId", "seriesId", "anchorIds", "after", "before", "limit", "maxReadBytes", "signal"].includes(field))
2684
+ throw new CliError("validation_error", `unknown related history field: ${field}`);
2685
+ const positive = /* @__PURE__ */ __name((value) => Number.isSafeInteger(value) && value > 0, "positive");
2686
+ if (!positive(input.accountId) || !positive(input.seriesId))
2687
+ throw new CliError("validation_error", "accountId and seriesId must be positive safe integers");
2688
+ if (!Array.isArray(input.anchorIds) || input.anchorIds.length > 20 || input.anchorIds.some((id3) => !positive(id3)))
2689
+ throw new CliError("validation_error", "anchorIds must contain at most 20 positive safe integers");
2690
+ for (const key of ["after", "before"])
2691
+ if (!Number.isSafeInteger(input[key]) || Math.abs(input[key]) > 864e13)
2692
+ throw new CliError("validation_error", `${key} must be an absolute timestamp`);
2693
+ if (input.after >= input.before)
2694
+ throw new CliError("validation_error", "after must precede before");
2695
+ const limit = input.limit === void 0 ? 5 : input.limit;
2696
+ const maxReadBytes = input.maxReadBytes === void 0 ? 262144 : input.maxReadBytes;
2697
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 20)
2698
+ throw new CliError("validation_error", "limit must be an integer from 1 to 20");
2699
+ if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4194304)
2700
+ throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
2701
+ if (input.signal !== void 0 && !(input.signal instanceof AbortSignal))
2702
+ throw new CliError("validation_error", "signal must be an AbortSignal");
2703
+ input.signal?.throwIfAborted();
2704
+ return { ...input, anchorIds: [...new Set(input.anchorIds)], limit, maxReadBytes };
2705
+ }, "validateMeetingRelatedHistory");
2706
+
2707
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/review.js
2708
+ var REVIEW_LIMIT = { default: 50, most: 200 };
2709
+
2710
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/save-hints.js
2711
+ var SAVE_HELP = `Worth keeping \u2014 a decision, a promise, a preference? Record it with \`memo facts add\` or
2712
+ \`memo memories add\`, citing the msg: locator or meeting: reference as --evidence.`;
2713
+
2714
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/series-history.js
2715
+ var validateMeetingSeriesHistory = /* @__PURE__ */ __name((input) => {
2716
+ input.signal?.throwIfAborted();
2717
+ if (!Number.isSafeInteger(input.accountId) || input.accountId <= 0)
2718
+ throw new CliError("validation_error", "accountId must be a positive safe integer");
2719
+ if (typeof input.externalId !== "string" || !input.externalId.trim() || new TextEncoder().encode(input.externalId).length > 4096 || /[\0\r\n]/.test(input.externalId))
2720
+ throw new CliError("validation_error", "externalId must be a bounded nonempty series identifier");
2721
+ for (const name of ["after", "before"])
2722
+ if (!Number.isSafeInteger(input[name]) || Math.abs(input[name]) > 864e13)
2723
+ throw new CliError("validation_error", `${name} must be an absolute timestamp in milliseconds`);
2724
+ if (input.after >= input.before)
2725
+ throw new CliError("validation_error", "after must be earlier than before");
2726
+ const limit = input.limit === void 0 ? 20 : input.limit;
2727
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
2728
+ throw new CliError("validation_error", "limit must be an integer from 1 to 100");
2729
+ const maxReadBytes = input.maxReadBytes === void 0 ? 256 * 1024 : input.maxReadBytes;
2730
+ if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4 * 1024 * 1024)
2731
+ throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
2732
+ return { ...input, limit, maxReadBytes };
2733
+ }, "validateMeetingSeriesHistory");
2734
+
2735
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/upcoming-validation.js
2736
+ var occurrenceId = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim().length > 0 && value.length <= 1e3 && !/[\0\r\n]/.test(value), "occurrenceId");
2737
+
2738
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/series-inventory-validation.js
2739
+ function invalid3(field, response = false) {
2740
+ throw new CliError(response ? "invalid_response" : "validation_error", `invalid meeting inventory ${field}`);
2741
+ }
2742
+ __name(invalid3, "invalid");
2743
+ var object2 = /* @__PURE__ */ __name((value, fields2, field, response = false) => {
2744
+ if (!value || typeof value !== "object" || Array.isArray(value))
2745
+ invalid3(field, response);
2746
+ for (const key of Object.keys(value))
2747
+ if (!fields2.includes(key))
2748
+ invalid3(`${field}.${key}`, response);
2749
+ }, "object");
2750
+ var cursorDetails = /* @__PURE__ */ __name((value) => {
2751
+ if (typeof value !== "string" || value.length > 4096 || !/^[A-Za-z0-9_-]+$/.test(value))
2752
+ invalid3("cursor");
2753
+ try {
2754
+ const decoded = JSON.parse(new TextDecoder("utf8", { fatal: true }).decode(Buffer.from(value, "base64url")));
2755
+ object2(decoded, ["version", "selection", "cursor"], "cursor");
2756
+ if (decoded.version !== 1 || typeof decoded.selection !== "string" || !/^[a-f0-9]{64}$/.test(decoded.selection) || !occurrenceId(decoded.cursor))
2757
+ invalid3("cursor");
2758
+ return decoded;
2759
+ } catch {
2760
+ return invalid3("cursor");
2761
+ }
2762
+ }, "cursorDetails");
2763
+ var validateMeetingSeriesInventoryCursor = /* @__PURE__ */ __name((value) => {
2764
+ cursorDetails(value);
2765
+ }, "validateMeetingSeriesInventoryCursor");
2766
+
2767
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/meetings/stats.js
2768
+ var zoneOf = /* @__PURE__ */ __name((timeZone) => {
2769
+ const zone = timeZone ?? "UTC";
2770
+ try {
2771
+ new Intl.DateTimeFormat("en", { timeZone: zone });
2772
+ } catch {
2773
+ throw new CliError("validation_error", "expected an IANA time zone such as Europe/Madrid");
2774
+ }
2775
+ return zone;
2776
+ }, "zoneOf");
2777
+ var DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
2778
+ var weekStart = /* @__PURE__ */ __name((at, format) => {
2779
+ const parts = Object.fromEntries(format.formatToParts(new Date(at)).map((part) => [part.type, part.value]));
2780
+ const day = Date.UTC(Number(parts.year), Number(parts.month) - 1, Number(parts.day));
2781
+ return new Date(day - DAYS.indexOf(parts.weekday ?? "Mon") * 864e5).toISOString().slice(0, 10);
2782
+ }, "weekStart");
2783
+ var UNKNOWN_SPEAKER = "unknown";
2784
+ var speakerOf = /* @__PURE__ */ __name((row) => row.personId !== null ? { key: `person:${row.personId}`, name: row.personName ?? row.identityName ?? row.speakerName } : row.identityId !== null ? { key: `identity:${row.identityId}`, name: row.identityName ?? row.speakerName } : row.speakerName?.trim() ? { key: `name:${row.speakerName.trim().toLowerCase()}`, name: row.speakerName.trim() } : { key: UNKNOWN_SPEAKER, name: null }, "speakerOf");
2785
+ var aggregateMeetingStats = /* @__PURE__ */ __name((rows, timeZone) => {
2786
+ const zone = zoneOf(timeZone);
2787
+ const format = new Intl.DateTimeFormat("en-US", {
2788
+ timeZone: zone,
2789
+ year: "numeric",
2790
+ month: "2-digit",
2791
+ day: "2-digit",
2792
+ weekday: "short"
2793
+ });
2794
+ const speakers = /* @__PURE__ */ new Map();
2795
+ const weeks = /* @__PURE__ */ new Map();
2796
+ const meetings = /* @__PURE__ */ new Set();
2797
+ let lines = 0;
2798
+ let words2 = 0;
2799
+ let talkMs = 0;
2800
+ for (const row of rows) {
2801
+ const talk = Math.max(0, row.endMs - row.startMs);
2802
+ meetings.add(row.meetingId);
2803
+ lines += 1;
2804
+ words2 += row.words;
2805
+ talkMs += talk;
2806
+ const who = speakerOf(row);
2807
+ const held = speakers.get(who.key) ?? {
2808
+ key: who.key,
2809
+ name: who.name ?? null,
2810
+ personId: row.personId,
2811
+ identityId: row.personId === null ? row.identityId : null,
2812
+ meetings: 0,
2813
+ lines: 0,
2814
+ words: 0,
2815
+ talkMs: 0,
2816
+ share: 0,
2817
+ seen: /* @__PURE__ */ new Set()
2818
+ };
2819
+ held.seen.add(row.meetingId);
2820
+ held.lines += 1;
2821
+ held.words += row.words;
2822
+ held.talkMs += talk;
2823
+ speakers.set(who.key, held);
2824
+ if (row.startedAt !== null) {
2825
+ const week = weeks.get(weekStart(row.startedAt, format)) ?? { meetings: /* @__PURE__ */ new Set(), talkMs: 0 };
2826
+ week.meetings.add(row.meetingId);
2827
+ week.talkMs += talk;
2828
+ weeks.set(weekStart(row.startedAt, format), week);
2829
+ }
2830
+ }
2831
+ return {
2832
+ timeZone: zone,
2833
+ meetings: meetings.size,
2834
+ lines,
2835
+ words: words2,
2836
+ talkMs,
2837
+ speakers: [...speakers.values()].map(({ seen, ...speaker }) => ({
2838
+ ...speaker,
2839
+ meetings: seen.size,
2840
+ share: talkMs === 0 ? 0 : Math.round(speaker.talkMs / talkMs * 1e3) / 1e3
2841
+ })).sort((a, b) => b.talkMs - a.talkMs || a.key.localeCompare(b.key)),
2842
+ weeks: [...weeks.entries()].map(([start, week]) => ({ weekStart: start, meetings: week.meetings.size, talkMs: week.talkMs })).sort((a, b) => a.weekStart.localeCompare(b.weekStart))
2843
+ };
2844
+ }, "aggregateMeetingStats");
2845
+
2846
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/tasks/model.js
2847
+ var TASK_KINDS = ["question", "request", "mention", "promise"];
2848
+ var TASK_STATES = ["open", "done", "dismissed"];
2849
+ var TASK_ORIGINS = ["rule", "agent", "owner"];
2850
+ var TASK_VERDICTS = ["useful", "not_useful"];
2851
+ function closeTask(task, state, by, at, reason) {
2852
+ if (task.state !== "open")
2853
+ throw new CliError("validation_error", `task ${task.id} is already ${task.state}`, { reason: "task.closed" });
2854
+ const { claimedBy: _by, claimedUntil: _until, ...unclaimed } = task;
2855
+ return { ...unclaimed, state, closedAt: at, closedBy: by, ...reason === void 0 ? {} : { reason } };
2856
+ }
2857
+ __name(closeTask, "closeTask");
2858
+
2859
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/tasks/store.js
2860
+ function matches2(task, filter) {
2861
+ return (filter.account === void 0 || task.account === filter.account) && (filter.state === void 0 || task.state === filter.state) && (filter.group === void 0 || task.group === filter.group) && (filter.kind === void 0 || task.kind === filter.kind) && (filter.createdBefore === void 0 || task.createdAt < filter.createdBefore);
2862
+ }
2863
+ __name(matches2, "matches");
2864
+
2865
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/tasks/service.js
2866
+ function createTaskService({ store, now = /* @__PURE__ */ __name(() => /* @__PURE__ */ new Date(), "now"), newId = /* @__PURE__ */ __name(() => crypto.randomUUID(), "newId") }) {
2867
+ async function find(id3) {
2868
+ const task = await store.get(id3);
2869
+ if (!task)
2870
+ throw new CliError("not_found", `no task ${id3}`);
2871
+ return task;
2872
+ }
2873
+ __name(find, "find");
2874
+ return {
2875
+ /**
2876
+ * A rule never makes a second task from a source it has seen, whatever that task's state, so a
2877
+ * dismissed one stays dismissed — nor from a message attached or merged into a task. A person or an agent may
2878
+ * add a task of another kind to it. A task a rule opens goes through the host's duplicate check.
2879
+ */
2880
+ async add(input) {
2881
+ const rule = input.origin === "rule";
2882
+ const existing = await store.findBySource(input.account, input.source, rule ? { linked: true } : void 0);
2883
+ const same = rule ? existing[0] : existing.find((task2) => task2.kind === input.kind);
2884
+ if (same)
2885
+ return { task: same, created: false };
2886
+ const task = { ...input, id: newId(), state: "open", createdAt: now() };
2887
+ await store.insert(task);
2888
+ if (!rule || !store.reviewDuplicates)
2889
+ return { task, created: true };
2890
+ return { task, created: true, review: await store.reviewDuplicates(task.id) };
2891
+ },
2892
+ async close(id3, { as, by, reason }) {
2893
+ const task = closeTask(await find(id3), as, by, now(), reason);
2894
+ await store.update(task);
2895
+ return task;
2896
+ },
2897
+ list: /* @__PURE__ */ __name((filter = {}) => store.list(filter), "list"),
2898
+ async stats(filter = {}) {
2899
+ const byGroup = /* @__PURE__ */ new Map();
2900
+ for (const task of await store.list(filter))
2901
+ byGroup.set(task.group, [...byGroup.get(task.group) ?? [], task]);
2902
+ return [...byGroup].map(([group, tasks]) => {
2903
+ const open = tasks.filter((task) => task.state === "open");
2904
+ const closeMs = tasks.flatMap((task) => task.closedAt ? [task.closedAt.getTime() - task.createdAt.getTime()] : []);
2905
+ const oldestOpenAt = open.map((task) => task.createdAt).sort((a, b) => a.getTime() - b.getTime())[0];
2906
+ return {
2907
+ group,
2908
+ open: open.length,
2909
+ ...oldestOpenAt ? { oldestOpenAt } : {},
2910
+ ...closeMs.length > 0 ? { medianCloseMs: median(closeMs) } : {}
2911
+ };
2912
+ });
2913
+ }
2914
+ };
2915
+ }
2916
+ __name(createTaskService, "createTaskService");
2917
+ function median(values) {
2918
+ const sorted = [...values].sort((a, b) => a - b);
2919
+ const middle = Math.floor(sorted.length / 2);
2920
+ const upper = sorted[middle] ?? 0;
2921
+ return sorted.length % 2 === 1 ? upper : ((sorted[middle - 1] ?? 0) + upper) / 2;
2922
+ }
2923
+ __name(median, "median");
2924
+
2925
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/domain/knowledge.js
2926
+ var FACT_TYPES = ["fact", "statement", "question", "decision", "promise"];
2927
+ var FACT_STATUSES = ["proposed", "accepted", "superseded", "reversed"];
2928
+ var MEMORY_KINDS = ["summary", "digest", "preference"];
2929
+ var MEMORY_STATUSES = ["proposed", "confirmed", "stale", "superseded"];
2930
+ var MEMORY_SCOPES = ["personal", "work"];
2931
+ var WORK_TASK_TYPES = ["bug", "feature", "chore"];
2932
+ var TASK_TYPES2 = [...WORK_TASK_TYPES, ...TASK_KINDS];
2933
+
2934
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/store/sqlite/link-kinds.js
2935
+ var LINK_KINDS = [
2936
+ "links-to",
2937
+ "blocked-by",
2938
+ "follow-up-of",
2939
+ "about",
2940
+ "member-of",
2941
+ "labelled",
2942
+ "answered-by",
2943
+ "evidence",
2944
+ "created-from",
2945
+ "duplicate-of",
2946
+ "related-to",
2947
+ "assigned-to",
2948
+ "attached"
2949
+ ];
2950
+ var LINK_ORIGINS = ["file", "owner", "suggested", "message"];
2951
+ var LINK_SOURCES = [...LINK_ORIGINS, "calendar"];
2952
+ var RELATION_KINDS = ["member-of", "related-to"];
2953
+ var linkKind = /* @__PURE__ */ __name((kind) => `'${kind}'`, "linkKind");
2954
+
2955
+ // node_modules/.pnpm/@wirecat+cli-core@0.469.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_9d12b0091b773232c527328da5835651/node_modules/@wirecat/cli-core/dist/domain/tags.js
2956
+ var TAG_TYPES = ["chat", "contact", "message", "task"];
2957
+ var TAG = /^[a-z0-9-]{1,32}$/;
2958
+ var tagOf = /* @__PURE__ */ __name((value) => {
2959
+ const tag = value.trim().toLowerCase();
2960
+ return TAG.test(tag) ? tag : void 0;
2961
+ }, "tagOf");
2962
+ var normalizeTag = /* @__PURE__ */ __name((value) => {
2963
+ const tag = tagOf(value);
2964
+ if (tag === void 0)
2965
+ throw new CliError("validation_error", `"${singleLine(value)}" is not a tag \u2014 use 1\u201332 letters a\u2013z, digits and hyphens`, { reason: "tag.invalid" });
2966
+ return tag;
2967
+ }, "normalizeTag");
2968
+
2969
+ export {
2970
+ QUERY_LIMITS,
2971
+ queryAstSchema,
2972
+ queryError,
2973
+ walkQuery,
2974
+ timezoneOf,
2975
+ zonedMoment,
2976
+ dateEndpoint,
2977
+ dateRange,
2978
+ evaluate,
2979
+ FIELD_TYPES,
2980
+ OPERATORS_BY_TYPE,
2981
+ QUERY_BACKENDS,
2982
+ queryFieldsOf,
2983
+ fieldsHelp,
2984
+ parseLucene,
2985
+ implicitTextTerms,
2986
+ validateQuery,
2987
+ fieldsNamed,
2988
+ describeQuery,
2989
+ defineQuery,
2990
+ QUERY_REASONS,
2991
+ formatMeetingReference,
2992
+ parseMeetingReference,
2993
+ canonicalMeetingReference,
2994
+ meeting,
2995
+ MEETING_QUERY,
2996
+ meetingHit,
2997
+ meetingTranscript,
2998
+ meetingSummary,
2999
+ meetingDetails,
3000
+ meetingHitsList,
3001
+ joinKeyOf,
3002
+ joinUrlWithoutQuery,
3003
+ calendarText,
3004
+ entryMetadata,
3005
+ meetingCueFingerprint,
3006
+ EVENT_QUERY,
3007
+ normalizeMeetingParticipantQuery,
3008
+ validateMeetingParticipantSearch,
3009
+ MeetingError,
3010
+ listed,
3011
+ meetingPeople,
3012
+ meetingsList,
3013
+ meetingsQuery,
3014
+ MEETING_QUERY_GUIDE,
3015
+ meetingDetailsAnswer,
3016
+ meetingTranscriptAnswer,
3017
+ meetingSummaryAnswer,
3018
+ exportMeeting,
3019
+ validateMeetingChange,
3020
+ findingHash,
3021
+ validateFindings,
3022
+ findingFingerprint,
3023
+ MEETING_FINDINGS_KIND,
3024
+ validateMeetingFindings,
3025
+ meetingFindingFingerprint,
3026
+ parseMeetingQuery,
3027
+ importFiles,
3028
+ CHAT_MESSAGES_READ,
3029
+ validateMeetingPassage,
3030
+ validateMeetingPreparationContext,
3031
+ meetingProjectEvidence,
3032
+ meetingProjectEvidenceAnswer,
3033
+ validateMeetingHitSearch,
3034
+ MEETING_PROJECT_EVIDENCE_QUERY,
3035
+ prepareMeetingProjectEvidence,
3036
+ readMeetingProjectEvidence,
3037
+ pull,
3038
+ meetingReview,
3039
+ meetingLink,
3040
+ meetingSpeaker,
3041
+ meetingStats,
3042
+ meetingParticipants,
3043
+ meetingPassage,
3044
+ event,
3045
+ eventItem,
3046
+ strongRecordingValidator,
3047
+ validateMeetingRelatedHistory,
3048
+ MEETING_RESULT_ENTITIES,
3049
+ REVIEW_LIMIT,
3050
+ SAVE_HELP,
3051
+ validateMeetingSeriesHistory,
3052
+ validateMeetingSeriesInventoryCursor,
3053
+ aggregateMeetingStats,
3054
+ TASK_KINDS,
3055
+ TASK_STATES,
3056
+ TASK_ORIGINS,
3057
+ TASK_VERDICTS,
3058
+ createTaskService,
3059
+ matches2 as matches,
3060
+ FACT_TYPES,
3061
+ FACT_STATUSES,
3062
+ MEMORY_KINDS,
3063
+ MEMORY_STATUSES,
3064
+ MEMORY_SCOPES,
3065
+ WORK_TASK_TYPES,
3066
+ TASK_TYPES2 as TASK_TYPES,
3067
+ LINK_KINDS,
3068
+ LINK_ORIGINS,
3069
+ LINK_SOURCES,
3070
+ RELATION_KINDS,
3071
+ linkKind,
3072
+ TAG_TYPES,
3073
+ tagOf,
3074
+ normalizeTag
3075
+ };