@wirecat/zoom-cli 0.56.0 → 0.58.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.
- package/README.md +1 -1
- package/dist/bin/zm.js +35 -5
- package/dist/bundle/all-profiles-RS5IWIGR.js +25 -0
- package/dist/bundle/answer-policy-R7VZMCGE.js +96 -0
- package/dist/bundle/anthropic-5QHQR4WF.js +70 -0
- package/dist/bundle/app-server-7LANSZGE.js +232 -0
- package/dist/bundle/bun-O6RL6LRQ.js +169 -0
- package/dist/bundle/bun-sqlite-PEJM6CS4.js +69 -0
- package/dist/bundle/chunk-24DLFGES.js +97 -0
- package/dist/bundle/chunk-27P22POE.js +1109 -0
- package/dist/bundle/chunk-3SCTDFNO.js +3398 -0
- package/dist/bundle/chunk-3SERIWJD.js +36139 -0
- package/dist/bundle/chunk-4AURKUDZ.js +60 -0
- package/dist/bundle/chunk-4NGLRHWO.js +24 -0
- package/dist/bundle/chunk-5D4AEUVA.js +24783 -0
- package/dist/bundle/chunk-5DVW77VC.js +789 -0
- package/dist/bundle/chunk-6CYLVFXM.js +9 -0
- package/dist/bundle/chunk-6FL25KC5.js +264 -0
- package/dist/bundle/chunk-7D2CD3E3.js +193 -0
- package/dist/bundle/chunk-7GVNQOV6.js +17 -0
- package/dist/bundle/chunk-7H3ZRDLW.js +630 -0
- package/dist/bundle/chunk-7Z4ANTAK.js +1095 -0
- package/dist/bundle/chunk-A6323R5P.js +22 -0
- package/dist/bundle/chunk-ADLS6FVG.js +24600 -0
- package/dist/bundle/chunk-AIXLOMH4.js +63 -0
- package/dist/bundle/chunk-AQDWGJZT.js +188 -0
- package/dist/bundle/chunk-B32SF7J3.js +18 -0
- package/dist/bundle/chunk-BAQLQIMI.js +1938 -0
- package/dist/bundle/chunk-BGILD4CI.js +1109 -0
- package/dist/bundle/chunk-BXZ6WSVF.js +100 -0
- package/dist/bundle/chunk-CTGI4ES2.js +138 -0
- package/dist/bundle/chunk-CVIKKIGE.js +76 -0
- package/dist/bundle/chunk-DDYR6DYL.js +78 -0
- package/dist/bundle/chunk-DFDN6AUB.js +21 -0
- package/dist/bundle/chunk-DP5DX45H.js +151 -0
- package/dist/bundle/chunk-DXKVEOSS.js +53 -0
- package/dist/bundle/chunk-DXZTLB24.js +120 -0
- package/dist/bundle/chunk-G27MRA24.js +82 -0
- package/dist/bundle/chunk-HTQTIKWP.js +928 -0
- package/dist/bundle/chunk-IYAGQXED.js +433 -0
- package/dist/bundle/chunk-K76WFW4I.js +124 -0
- package/dist/bundle/chunk-KVHRHBLY.js +884 -0
- package/dist/bundle/chunk-L2UIJDWB.js +31 -0
- package/dist/bundle/chunk-L3VS3H34.js +482 -0
- package/dist/bundle/chunk-MBT7GP7K.js +1970 -0
- package/dist/bundle/chunk-MFS52LTZ.js +570 -0
- package/dist/bundle/chunk-MMT46EN4.js +29 -0
- package/dist/bundle/chunk-MNUTWGSA.js +6094 -0
- package/dist/bundle/chunk-N7GAQ27N.js +82 -0
- package/dist/bundle/chunk-NDXAZB5Z.js +409 -0
- package/dist/bundle/chunk-NOKFJJPA.js +1028 -0
- package/dist/bundle/chunk-NW7IMGRR.js +6848 -0
- package/dist/bundle/chunk-O5EHUB2V.js +2 -0
- package/dist/bundle/chunk-OBZWUNO4.js +160 -0
- package/dist/bundle/chunk-PACC5N6T.js +240 -0
- package/dist/bundle/chunk-PF25S7L4.js +422 -0
- package/dist/bundle/chunk-PKTFZAXG.js +48 -0
- package/dist/bundle/chunk-PNBEREOU.js +35626 -0
- package/dist/bundle/chunk-POOGFSRA.js +385 -0
- package/dist/bundle/chunk-PP3JGQQE.js +3517 -0
- package/dist/bundle/chunk-Q2Z3VCM4.js +2 -0
- package/dist/bundle/chunk-QCFHL4ES.js +45 -0
- package/dist/bundle/chunk-QFGBMS67.js +492 -0
- package/dist/bundle/chunk-RUP467ZX.js +948 -0
- package/dist/bundle/chunk-RXDIG23Z.js +166 -0
- package/dist/bundle/chunk-SIA7HJE2.js +8192 -0
- package/dist/bundle/chunk-SL3SXQZ5.js +100 -0
- package/dist/bundle/chunk-SV5L36WK.js +19 -0
- package/dist/bundle/chunk-T6AAM7UT.js +846 -0
- package/dist/bundle/chunk-U6QW67SU.js +18673 -0
- package/dist/bundle/chunk-UKR7KH3H.js +288 -0
- package/dist/bundle/chunk-UOFOMU3T.js +836 -0
- package/dist/bundle/chunk-URO44C5T.js +3570 -0
- package/dist/bundle/chunk-UXM7I35J.js +281 -0
- package/dist/bundle/chunk-UYJUTZTT.js +73 -0
- package/dist/bundle/chunk-VOAVOK4I.js +1146 -0
- package/dist/bundle/chunk-VSUY7PDW.js +192 -0
- package/dist/bundle/chunk-VYUSEJE4.js +98 -0
- package/dist/bundle/chunk-XFCSPOLZ.js +25 -0
- package/dist/bundle/chunk-XT7XVPEM.js +538 -0
- package/dist/bundle/chunk-Y5E2WNWB.js +35 -0
- package/dist/bundle/chunk-YIFIY7ZE.js +58 -0
- package/dist/bundle/chunk-YIMI6O7R.js +5292 -0
- package/dist/bundle/chunk-YJRMMZI5.js +275 -0
- package/dist/bundle/chunk-YSHSCBPM.js +2315 -0
- package/dist/bundle/chunk-ZC5UXEIH.js +215 -0
- package/dist/bundle/chunk-ZHXIXDH5.js +161 -0
- package/dist/bundle/chunk-ZTOAAYFV.js +122 -0
- package/dist/bundle/chunk-ZVVMGPBJ.js +50 -0
- package/dist/bundle/cli-IQTASP44.js +831 -0
- package/dist/bundle/command-contract-WHZPF7NA.js +38 -0
- package/dist/bundle/config-IP5SGHKN.js +79 -0
- package/dist/bundle/dist-WT73DF46.js +136 -0
- package/dist/bundle/dist-XUFQCJXW.js +7577 -0
- package/dist/bundle/echarts-LD3AI55P.js +42501 -0
- package/dist/bundle/embed-XEMH4LNX.js +35 -0
- package/dist/bundle/embedder-ZCYKSKAE.js +108 -0
- package/dist/bundle/first-run-LGYDLIUM.js +23 -0
- package/dist/bundle/first-screen-LYQKPNF4.js +36 -0
- package/dist/bundle/folders-5ZBUQHAM.js +13 -0
- package/dist/bundle/instructions-RZMSW3OC.js +11 -0
- package/dist/bundle/main-NKY3JGXY.js +130 -0
- package/dist/bundle/mcp-7OXUHLTO.js +189 -0
- package/dist/bundle/mcp-OQBZXELQ.js +165 -0
- package/dist/bundle/mcp-VISEXTVC.js +92 -0
- package/dist/bundle/meetings-XPBHVZAU.js +215 -0
- package/dist/bundle/node-P4E63KXA.js +2340 -0
- package/dist/bundle/node-TLZSIHIJ.js +21 -0
- package/dist/bundle/node-ZRLYQL7J.js +176 -0
- package/dist/bundle/node-sqlite-BBEDYBWO.js +45 -0
- package/dist/bundle/oauth-UHVRGKZU.js +17 -0
- package/dist/bundle/open-J4FCAUAJ.js +19 -0
- package/dist/bundle/output-file-SXV2ANW7.js +63 -0
- package/dist/bundle/process-LL77573L.js +91 -0
- package/dist/bundle/program-EPMIJCGA.js +5845 -0
- package/dist/bundle/prompt-LUUMQTMY.js +12 -0
- package/dist/bundle/recognize-EMHQX4XF.js +190 -0
- package/dist/bundle/remote-ZXS6D7VB.js +26 -0
- package/dist/bundle/rerank-WP7RKZNB.js +49 -0
- package/dist/bundle/run-log-GS2L66G6.js +111 -0
- package/dist/bundle/serve-L6KLLXK2.js +19 -0
- package/dist/bundle/server-NOFYENP5.js +53 -0
- package/dist/bundle/server-P5TXAPBY.js +66 -0
- package/dist/bundle/services-SPOEWVK3.js +330 -0
- package/dist/bundle/speech-6OBAKMND.js +44 -0
- package/dist/bundle/state-HN5EJKXQ.js +33 -0
- package/dist/bundle/store-LEU3M6IN.js +124 -0
- package/dist/bundle/store-ZP2URKET.js +141 -0
- package/dist/bundle/store-connection-I53XZ2TS.js +76 -0
- package/dist/bundle/store-maintenance-command-PSCHEHHY.js +54 -0
- package/dist/bundle/streaming-AK6Q2ZGQ.js +15 -0
- package/dist/bundle/tokens-CCM3D4ZT.js +17 -0
- package/dist/bundle/zm.js +8 -0
- package/dist/contract-overrides.d.ts.map +1 -1
- package/dist/contract-overrides.js +29 -17
- package/dist/contract-overrides.js.map +1 -1
- package/dist/mcp-command.d.ts +3 -2
- package/dist/mcp-command.d.ts.map +1 -1
- package/dist/mcp-command.js +62 -10
- package/dist/mcp-command.js.map +1 -1
- package/dist/program-bindings.d.ts.map +1 -1
- package/dist/program-bindings.js +1 -0
- package/dist/program-bindings.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -5
- package/skills/zoom-cli/SKILL.md +2 -0
|
@@ -0,0 +1,3517 @@
|
|
|
1
|
+
import { createRequire as __bundleRequire } from "node:module";
|
|
2
|
+
const require = __bundleRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
dateRange,
|
|
5
|
+
defineQuery,
|
|
6
|
+
parseLucene,
|
|
7
|
+
queryError,
|
|
8
|
+
queryFieldsOf,
|
|
9
|
+
timezoneOf,
|
|
10
|
+
validateQuery
|
|
11
|
+
} from "./chunk-UOFOMU3T.js";
|
|
12
|
+
import {
|
|
13
|
+
CliError,
|
|
14
|
+
STEPS,
|
|
15
|
+
array,
|
|
16
|
+
boolean,
|
|
17
|
+
defineSteps,
|
|
18
|
+
integer,
|
|
19
|
+
isoTime,
|
|
20
|
+
literal,
|
|
21
|
+
maxValue,
|
|
22
|
+
minLength,
|
|
23
|
+
minValue,
|
|
24
|
+
nullable,
|
|
25
|
+
number,
|
|
26
|
+
optional,
|
|
27
|
+
pageSchema,
|
|
28
|
+
picklist,
|
|
29
|
+
pipe,
|
|
30
|
+
reference,
|
|
31
|
+
safeParse,
|
|
32
|
+
singleLine,
|
|
33
|
+
stepOf,
|
|
34
|
+
strictObject,
|
|
35
|
+
string,
|
|
36
|
+
union,
|
|
37
|
+
visibleControls
|
|
38
|
+
} from "./chunk-YIMI6O7R.js";
|
|
39
|
+
import {
|
|
40
|
+
__name
|
|
41
|
+
} from "./chunk-ZVVMGPBJ.js";
|
|
42
|
+
|
|
43
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/reference.js
|
|
44
|
+
var invalid = /* @__PURE__ */ __name(() => new CliError("validation_error", "expected meeting:<accountId>/<meetingId>[/<transcriptId>[/<cuePosition>]] with safe integer IDs"), "invalid");
|
|
45
|
+
var integer2 = /* @__PURE__ */ __name((value, minimum = 1) => {
|
|
46
|
+
if (!Number.isSafeInteger(value) || value < minimum)
|
|
47
|
+
throw invalid();
|
|
48
|
+
return value;
|
|
49
|
+
}, "integer");
|
|
50
|
+
var formatMeetingReference = /* @__PURE__ */ __name((reference2) => {
|
|
51
|
+
const parts = [integer2(reference2.accountId), integer2(reference2.meetingId)];
|
|
52
|
+
if (reference2.transcriptId !== void 0)
|
|
53
|
+
parts.push(integer2(reference2.transcriptId));
|
|
54
|
+
if (reference2.cuePosition !== void 0) {
|
|
55
|
+
if (reference2.transcriptId === void 0)
|
|
56
|
+
throw invalid();
|
|
57
|
+
parts.push(integer2(reference2.cuePosition, 0));
|
|
58
|
+
}
|
|
59
|
+
return `meeting:${parts.join("/")}`;
|
|
60
|
+
}, "formatMeetingReference");
|
|
61
|
+
var parseMeetingReference = /* @__PURE__ */ __name((text9) => {
|
|
62
|
+
const value = text9.trim();
|
|
63
|
+
if (!value.startsWith("meeting:"))
|
|
64
|
+
throw invalid();
|
|
65
|
+
const parts = value.slice(8).split("/");
|
|
66
|
+
if (parts.length < 2 || parts.length > 4 || parts.some((part) => !/^\d+$/.test(part)))
|
|
67
|
+
throw invalid();
|
|
68
|
+
const ids2 = parts.map(Number);
|
|
69
|
+
const reference2 = {
|
|
70
|
+
type: "meeting",
|
|
71
|
+
accountId: integer2(ids2[0]),
|
|
72
|
+
meetingId: integer2(ids2[1]),
|
|
73
|
+
...ids2.length > 2 ? { transcriptId: integer2(ids2[2]) } : {},
|
|
74
|
+
...ids2.length > 3 ? { cuePosition: integer2(ids2[3], 0) } : {}
|
|
75
|
+
};
|
|
76
|
+
return reference2;
|
|
77
|
+
}, "parseMeetingReference");
|
|
78
|
+
var canonicalMeetingReference = /* @__PURE__ */ __name((text9) => formatMeetingReference(parseMeetingReference(text9)), "canonicalMeetingReference");
|
|
79
|
+
|
|
80
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/item.js
|
|
81
|
+
var text = string();
|
|
82
|
+
var count = pipe(number(), integer(), minValue(0));
|
|
83
|
+
var MEETING_ISSUES = ["time_without_zone"];
|
|
84
|
+
var meetingIssuesOf = /* @__PURE__ */ __name((metadata) => {
|
|
85
|
+
const listed2 = metadata?.issues;
|
|
86
|
+
return Array.isArray(listed2) ? MEETING_ISSUES.filter((issue) => listed2.includes(issue)) : [];
|
|
87
|
+
}, "meetingIssuesOf");
|
|
88
|
+
var meeting = strictObject({
|
|
89
|
+
ref: reference,
|
|
90
|
+
id: pipe(string(), minLength(1)),
|
|
91
|
+
provider: text,
|
|
92
|
+
account: text,
|
|
93
|
+
title: nullable(text),
|
|
94
|
+
description: optional(nullable(text)),
|
|
95
|
+
location: optional(nullable(text)),
|
|
96
|
+
/** The link that joins it. */
|
|
97
|
+
url: nullable(text),
|
|
98
|
+
started_at: nullable(isoTime),
|
|
99
|
+
ended_at: nullable(isoTime),
|
|
100
|
+
duration_ms: nullable(count),
|
|
101
|
+
timezone: optional(nullable(text)),
|
|
102
|
+
participants_count: nullable(count),
|
|
103
|
+
/** Present only when something about this meeting is doubtful. */
|
|
104
|
+
issues: optional(array(picklist(MEETING_ISSUES))),
|
|
105
|
+
created_at: isoTime,
|
|
106
|
+
updated_at: isoTime
|
|
107
|
+
});
|
|
108
|
+
var iso = /* @__PURE__ */ __name((ms) => ms === null ? null : new Date(ms).toISOString(), "iso");
|
|
109
|
+
var meetingItem = /* @__PURE__ */ __name((row, owner) => {
|
|
110
|
+
const issues = meetingIssuesOf(row.metadata);
|
|
111
|
+
return {
|
|
112
|
+
ref: formatMeetingReference({ type: "meeting", accountId: row.accountId, meetingId: row.id }),
|
|
113
|
+
id: String(row.id),
|
|
114
|
+
provider: owner.provider,
|
|
115
|
+
account: owner.account,
|
|
116
|
+
title: row.title,
|
|
117
|
+
description: row.description,
|
|
118
|
+
location: row.location,
|
|
119
|
+
url: row.joinUrl,
|
|
120
|
+
started_at: iso(row.startedAt),
|
|
121
|
+
ended_at: iso(row.endedAt),
|
|
122
|
+
duration_ms: row.durationMs,
|
|
123
|
+
timezone: row.timezone,
|
|
124
|
+
participants_count: row.participantsCount,
|
|
125
|
+
...issues.length ? { issues } : {},
|
|
126
|
+
created_at: new Date(row.createdAt).toISOString(),
|
|
127
|
+
updated_at: new Date(row.updatedAt).toISOString()
|
|
128
|
+
};
|
|
129
|
+
}, "meetingItem");
|
|
130
|
+
var MEETING_QUERY = {
|
|
131
|
+
entity: "meeting",
|
|
132
|
+
backend: "sql",
|
|
133
|
+
fields: queryFieldsOf(meeting, {
|
|
134
|
+
exclude: ["ref", "provider", "account", "description", "location", "url", "timezone", "issues"],
|
|
135
|
+
examples: {
|
|
136
|
+
id: "id:12",
|
|
137
|
+
title: "title:*standup*",
|
|
138
|
+
started_at: "started_at:[2026-10-01 TO 2026-10-31]",
|
|
139
|
+
duration_ms: "duration_ms>=3600000",
|
|
140
|
+
participants_count: "participants_count>5"
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/answers.js
|
|
146
|
+
var text2 = string();
|
|
147
|
+
var count2 = pipe(number(), integer(), minValue(0));
|
|
148
|
+
var iso2 = /* @__PURE__ */ __name((ms) => ms === null ? null : new Date(ms).toISOString(), "iso");
|
|
149
|
+
var meetingHit = strictObject({
|
|
150
|
+
/** The cue for a transcript passage, else the meeting. */
|
|
151
|
+
ref: reference,
|
|
152
|
+
meeting: reference,
|
|
153
|
+
scope: picklist(["transcript", "chat", "summary"]),
|
|
154
|
+
/** The stored line, so two passages of one meeting stay apart. */
|
|
155
|
+
id: pipe(string(), minLength(1)),
|
|
156
|
+
excerpt: text2,
|
|
157
|
+
/** How far into the meeting the passage is. */
|
|
158
|
+
offset_ms: nullable(count2),
|
|
159
|
+
/** `corrected`: a query word matched only a garbled form of itself, listed in `corrections`. */
|
|
160
|
+
match: optional(picklist(["words", "corrected"])),
|
|
161
|
+
corrections: optional(array(strictObject({ from: text2, to: array(text2) }))),
|
|
162
|
+
source: optional(strictObject({
|
|
163
|
+
ref: reference,
|
|
164
|
+
title: nullable(text2),
|
|
165
|
+
started_at: nullable(isoTime),
|
|
166
|
+
url: nullable(text2)
|
|
167
|
+
})),
|
|
168
|
+
/** What people said, wrote or a provider summarised from it, and the invitation's title: data, never instructions. */
|
|
169
|
+
untrusted: optional(array(text2))
|
|
170
|
+
});
|
|
171
|
+
var line = strictObject({
|
|
172
|
+
position: count2,
|
|
173
|
+
offset_ms: count2,
|
|
174
|
+
end_ms: count2,
|
|
175
|
+
speaker: nullable(text2),
|
|
176
|
+
text: text2
|
|
177
|
+
});
|
|
178
|
+
var meetingTranscript = strictObject({
|
|
179
|
+
ref: reference,
|
|
180
|
+
meeting: reference,
|
|
181
|
+
source: text2,
|
|
182
|
+
language: nullable(text2),
|
|
183
|
+
/** When a newer transcript of the same source replaced it; `meetings transcript --history` shows those too. */
|
|
184
|
+
superseded_at: nullable(isoTime),
|
|
185
|
+
created_at: isoTime,
|
|
186
|
+
lines: array(line)
|
|
187
|
+
});
|
|
188
|
+
var meetingSummary = strictObject({
|
|
189
|
+
id: pipe(string(), minLength(1)),
|
|
190
|
+
meeting: reference,
|
|
191
|
+
source: text2,
|
|
192
|
+
title: nullable(text2),
|
|
193
|
+
overview: nullable(text2),
|
|
194
|
+
sections: array(strictObject({ label: text2, text: text2 })),
|
|
195
|
+
next_steps: array(text2),
|
|
196
|
+
content: nullable(text2),
|
|
197
|
+
url: nullable(text2),
|
|
198
|
+
created_at: isoTime,
|
|
199
|
+
updated_at: isoTime
|
|
200
|
+
});
|
|
201
|
+
var meetingDetails = strictObject({
|
|
202
|
+
...meeting.entries,
|
|
203
|
+
/** The stored event and series it belongs to, as `meetings_list` takes them. */
|
|
204
|
+
event_id: nullable(text2),
|
|
205
|
+
series_id: nullable(text2),
|
|
206
|
+
series_title: nullable(text2),
|
|
207
|
+
participants: array(strictObject({
|
|
208
|
+
name: nullable(text2),
|
|
209
|
+
email: nullable(text2),
|
|
210
|
+
role: nullable(text2),
|
|
211
|
+
joined_at: nullable(isoTime),
|
|
212
|
+
left_at: nullable(isoTime),
|
|
213
|
+
duration_ms: nullable(count2)
|
|
214
|
+
})),
|
|
215
|
+
transcripts: array(strictObject({ ref: reference, source: text2, language: nullable(text2), lines_count: count2 })),
|
|
216
|
+
chat: array(strictObject({ sent_at: isoTime, sender: nullable(text2), recipient: nullable(text2), text: text2 })),
|
|
217
|
+
summaries: array(meetingSummary),
|
|
218
|
+
attachments: array(strictObject({
|
|
219
|
+
position: count2,
|
|
220
|
+
kind: text2,
|
|
221
|
+
name: nullable(text2),
|
|
222
|
+
mime: nullable(text2),
|
|
223
|
+
size: nullable(count2),
|
|
224
|
+
url: nullable(text2)
|
|
225
|
+
}))
|
|
226
|
+
});
|
|
227
|
+
var meetingRef = /* @__PURE__ */ __name((accountId, meetingId) => formatMeetingReference({ type: "meeting", accountId, meetingId }), "meetingRef");
|
|
228
|
+
var meetingTranscriptItem = /* @__PURE__ */ __name((accountId, transcript, rows) => ({
|
|
229
|
+
ref: formatMeetingReference({
|
|
230
|
+
type: "meeting",
|
|
231
|
+
accountId,
|
|
232
|
+
meetingId: transcript.meetingId,
|
|
233
|
+
transcriptId: transcript.id
|
|
234
|
+
}),
|
|
235
|
+
meeting: meetingRef(accountId, transcript.meetingId),
|
|
236
|
+
source: transcript.source,
|
|
237
|
+
language: transcript.language,
|
|
238
|
+
superseded_at: iso2(transcript.supersededAt),
|
|
239
|
+
created_at: new Date(transcript.externalCreatedAt ?? transcript.createdAt).toISOString(),
|
|
240
|
+
lines: rows.map((row) => ({
|
|
241
|
+
position: row.position,
|
|
242
|
+
offset_ms: row.startMs,
|
|
243
|
+
end_ms: row.endMs,
|
|
244
|
+
speaker: row.speakerName,
|
|
245
|
+
text: row.text
|
|
246
|
+
}))
|
|
247
|
+
}), "meetingTranscriptItem");
|
|
248
|
+
var meetingSummaryItem = /* @__PURE__ */ __name((accountId, summary) => ({
|
|
249
|
+
id: String(summary.id),
|
|
250
|
+
meeting: meetingRef(accountId, summary.meetingId),
|
|
251
|
+
source: summary.source,
|
|
252
|
+
title: summary.title,
|
|
253
|
+
overview: summary.overview,
|
|
254
|
+
sections: summary.sections.map(({ label: label2, text: text9 }) => ({ label: label2, text: text9 })),
|
|
255
|
+
next_steps: summary.nextSteps,
|
|
256
|
+
content: summary.content,
|
|
257
|
+
url: summary.docUrl,
|
|
258
|
+
created_at: new Date(summary.externalCreatedAt ?? summary.createdAt).toISOString(),
|
|
259
|
+
updated_at: new Date(summary.externalUpdatedAt ?? summary.updatedAt).toISOString()
|
|
260
|
+
}), "meetingSummaryItem");
|
|
261
|
+
var meetingDetailsItem = /* @__PURE__ */ __name((details, owner) => {
|
|
262
|
+
const { accountId } = details.meeting;
|
|
263
|
+
return {
|
|
264
|
+
...meetingItem(details.meeting, owner),
|
|
265
|
+
event_id: details.meeting.eventId === null ? null : String(details.meeting.eventId),
|
|
266
|
+
series_id: details.meeting.meetingSeriesId === null ? null : String(details.meeting.meetingSeriesId),
|
|
267
|
+
series_title: details.series?.title ?? null,
|
|
268
|
+
participants: details.participants.map((one) => ({
|
|
269
|
+
name: one.displayName,
|
|
270
|
+
email: one.email,
|
|
271
|
+
role: one.role,
|
|
272
|
+
joined_at: iso2(one.joinedAt),
|
|
273
|
+
left_at: iso2(one.leftAt),
|
|
274
|
+
duration_ms: one.durationMs
|
|
275
|
+
})),
|
|
276
|
+
transcripts: details.transcripts.filter(({ transcript }) => transcript.supersededAt === null && transcript.deletedAt === null).map(({ transcript, rows }) => ({
|
|
277
|
+
ref: formatMeetingReference({
|
|
278
|
+
type: "meeting",
|
|
279
|
+
accountId,
|
|
280
|
+
meetingId: transcript.meetingId,
|
|
281
|
+
transcriptId: transcript.id
|
|
282
|
+
}),
|
|
283
|
+
source: transcript.source,
|
|
284
|
+
language: transcript.language,
|
|
285
|
+
lines_count: rows.length
|
|
286
|
+
})),
|
|
287
|
+
chat: details.chat.map((one) => ({
|
|
288
|
+
sent_at: new Date(one.sentAt).toISOString(),
|
|
289
|
+
sender: one.senderName,
|
|
290
|
+
recipient: one.recipient,
|
|
291
|
+
text: one.text
|
|
292
|
+
})),
|
|
293
|
+
summaries: details.summaries.map((one) => meetingSummaryItem(accountId, one)),
|
|
294
|
+
attachments: details.attachments.map((one) => ({
|
|
295
|
+
position: one.position,
|
|
296
|
+
kind: one.kind,
|
|
297
|
+
name: one.name ?? one.title,
|
|
298
|
+
mime: one.mime,
|
|
299
|
+
size: one.size,
|
|
300
|
+
url: one.url
|
|
301
|
+
}))
|
|
302
|
+
};
|
|
303
|
+
}, "meetingDetailsItem");
|
|
304
|
+
var wholeList = /* @__PURE__ */ __name((items) => ({
|
|
305
|
+
items,
|
|
306
|
+
page: { mode: "page", limit: Math.max(1, items.length), has_more: false }
|
|
307
|
+
}), "wholeList");
|
|
308
|
+
var PAGE_NEXT = STEPS.find((step) => step.id === "page.next");
|
|
309
|
+
var MEETING_STEPS = defineSteps([
|
|
310
|
+
{
|
|
311
|
+
id: "meetings.search-again",
|
|
312
|
+
command: "*",
|
|
313
|
+
args: [],
|
|
314
|
+
why: "passages that changed since they were indexed were left out; the next search indexes them first"
|
|
315
|
+
}
|
|
316
|
+
]);
|
|
317
|
+
var SEARCH_AGAIN = MEETING_STEPS[0];
|
|
318
|
+
var meetingHitItem = /* @__PURE__ */ __name((hit) => ({
|
|
319
|
+
ref: hit.ref,
|
|
320
|
+
meeting: meetingRef(parseMeetingReference(hit.ref).accountId, hit.meetingId),
|
|
321
|
+
scope: hit.scope,
|
|
322
|
+
id: String(hit.id),
|
|
323
|
+
excerpt: hit.text,
|
|
324
|
+
offset_ms: hit.startMs,
|
|
325
|
+
untrusted: hit.source === void 0 ? ["excerpt"] : ["excerpt", "source.title"],
|
|
326
|
+
...hit.match === void 0 ? {} : { match: hit.match },
|
|
327
|
+
...hit.corrections === void 0 ? {} : { corrections: hit.corrections },
|
|
328
|
+
...hit.source === void 0 ? {} : {
|
|
329
|
+
source: {
|
|
330
|
+
ref: hit.ref,
|
|
331
|
+
title: hit.source.title,
|
|
332
|
+
started_at: iso2(hit.source.startedAt),
|
|
333
|
+
url: hit.source.url
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}), "meetingHitItem");
|
|
337
|
+
var meetingHitsList = /* @__PURE__ */ __name((found, limit, command = "search meetings", args = {}, meta = {}) => {
|
|
338
|
+
const items = found.items.map(meetingHitItem);
|
|
339
|
+
const cursor = found.hasMore && found.nextCursor !== null ? found.nextCursor : void 0;
|
|
340
|
+
const pending2 = found.coverage.indexing === "pending";
|
|
341
|
+
const next = [
|
|
342
|
+
...cursor === void 0 ? [] : [stepOf(PAGE_NEXT, { command, args: { ...args, cursor, limit }, values: { shown: items.length } })],
|
|
343
|
+
...pending2 ? [
|
|
344
|
+
stepOf(SEARCH_AGAIN, {
|
|
345
|
+
command,
|
|
346
|
+
args: Object.fromEntries(Object.entries(args).filter(([key]) => key !== "cursor"))
|
|
347
|
+
})
|
|
348
|
+
] : []
|
|
349
|
+
];
|
|
350
|
+
return {
|
|
351
|
+
items,
|
|
352
|
+
page: {
|
|
353
|
+
mode: "cursor",
|
|
354
|
+
limit,
|
|
355
|
+
has_more: cursor !== void 0,
|
|
356
|
+
...cursor === void 0 ? {} : { next_cursor: cursor }
|
|
357
|
+
},
|
|
358
|
+
...next.length > 0 ? { next } : {},
|
|
359
|
+
...pending2 ? {
|
|
360
|
+
missing: [
|
|
361
|
+
{
|
|
362
|
+
field: "excerpt",
|
|
363
|
+
why: "passages that changed since they were indexed were left out",
|
|
364
|
+
step: "meetings.search-again"
|
|
365
|
+
}
|
|
366
|
+
]
|
|
367
|
+
} : {},
|
|
368
|
+
...Object.keys(meta).length === 0 ? {} : { meta }
|
|
369
|
+
};
|
|
370
|
+
}, "meetingHitsList");
|
|
371
|
+
|
|
372
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/join-key.js
|
|
373
|
+
var joinKeyOf = /* @__PURE__ */ __name((url) => {
|
|
374
|
+
const parsed = urlOf(url);
|
|
375
|
+
if (!parsed)
|
|
376
|
+
return null;
|
|
377
|
+
const host = parsed.hostname.toLowerCase().replace(/^www\./u, "");
|
|
378
|
+
const path = parsed.pathname.replace(/\/+$/u, "");
|
|
379
|
+
if (host === "zoom.us" || host.endsWith(".zoom.us") || host === "zoomgov.com" || host.endsWith(".zoomgov.com")) {
|
|
380
|
+
const number2 = /^\/(?:j|w|s|wc\/join|wc)\/(\d{9,12})(?:\/|$)/u.exec(path)?.[1];
|
|
381
|
+
if (number2)
|
|
382
|
+
return `zoom:${number2}`;
|
|
383
|
+
}
|
|
384
|
+
if (host === "meet.google.com") {
|
|
385
|
+
const code = /^\/([a-z]{3}-[a-z]{4}-[a-z]{3})$/iu.exec(path)?.[1];
|
|
386
|
+
if (code)
|
|
387
|
+
return `meet:${code.toLowerCase()}`;
|
|
388
|
+
}
|
|
389
|
+
return `${host}${path}`;
|
|
390
|
+
}, "joinKeyOf");
|
|
391
|
+
var joinUrlWithoutQuery = /* @__PURE__ */ __name((url) => {
|
|
392
|
+
const parsed = urlOf(url);
|
|
393
|
+
return parsed ? `${parsed.origin}${parsed.pathname}` : null;
|
|
394
|
+
}, "joinUrlWithoutQuery");
|
|
395
|
+
var urlOf = /* @__PURE__ */ __name((url) => {
|
|
396
|
+
if (!url?.trim())
|
|
397
|
+
return null;
|
|
398
|
+
try {
|
|
399
|
+
const parsed = new URL(url.trim());
|
|
400
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed : null;
|
|
401
|
+
} catch {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
}, "urlOf");
|
|
405
|
+
|
|
406
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/calendar-text.js
|
|
407
|
+
var ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', "#39": "'", apos: "'", nbsp: " " };
|
|
408
|
+
var SECRET_LINE = /(?<![\p{L}\p{N}])(pass ?codes?|passwords?|pwd|pins?|access ?codes?|meeting ?codes?|kennwort|пароль|пин-?код|код доступа)(?![\p{L}\p{N}])|pwd=/iu;
|
|
409
|
+
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");
|
|
410
|
+
var withoutLinkQueries = /* @__PURE__ */ __name((text9) => text9.replace(/https?:\/\/[^\s<>"')\]]+/giu, (url) => joinUrlWithoutQuery(url) ?? ""), "withoutLinkQueries");
|
|
411
|
+
var calendarText = /* @__PURE__ */ __name((text9, { dropSecretLines = true } = {}) => {
|
|
412
|
+
if (!text9)
|
|
413
|
+
return null;
|
|
414
|
+
const kept = htmlToText(text9).split(/\r?\n/u).map((line2) => withoutLinkQueries(line2).replace(/[ \t]+/gu, " ").trim()).filter((line2) => !dropSecretLines || !SECRET_LINE.test(line2));
|
|
415
|
+
const joined = kept.join("\n").replace(/\n{3,}/gu, "\n\n").trim();
|
|
416
|
+
return joined || null;
|
|
417
|
+
}, "calendarText");
|
|
418
|
+
var ENTRY_METADATA_KEYS = [
|
|
419
|
+
"colorId",
|
|
420
|
+
"guestsCanInviteOthers",
|
|
421
|
+
"guestsCanModify",
|
|
422
|
+
"guestsCanSeeOtherGuests",
|
|
423
|
+
"hangoutLink",
|
|
424
|
+
"locked",
|
|
425
|
+
"privateCopy"
|
|
426
|
+
];
|
|
427
|
+
var entryMetadata = /* @__PURE__ */ __name((metadata) => {
|
|
428
|
+
const kept = {};
|
|
429
|
+
for (const key of ENTRY_METADATA_KEYS) {
|
|
430
|
+
const value = metadata?.[key];
|
|
431
|
+
if (typeof value === "string")
|
|
432
|
+
kept[key] = withoutLinkQueries(value);
|
|
433
|
+
else if (typeof value === "number" || typeof value === "boolean")
|
|
434
|
+
kept[key] = value;
|
|
435
|
+
}
|
|
436
|
+
return kept;
|
|
437
|
+
}, "entryMetadata");
|
|
438
|
+
|
|
439
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/cue-fingerprint.js
|
|
440
|
+
import { createHash } from "node:crypto";
|
|
441
|
+
var meetingCueFingerprint = /* @__PURE__ */ __name((cue2) => createHash("sha256").update(JSON.stringify({
|
|
442
|
+
reference: cue2.reference,
|
|
443
|
+
transcriptId: cue2.transcriptId,
|
|
444
|
+
contentHash: cue2.contentHash,
|
|
445
|
+
position: cue2.position,
|
|
446
|
+
startMs: cue2.startMs,
|
|
447
|
+
endMs: cue2.endMs,
|
|
448
|
+
speakerParticipantId: cue2.speakerParticipantId,
|
|
449
|
+
speakerName: cue2.speakerName,
|
|
450
|
+
text: cue2.text
|
|
451
|
+
})).digest("hex"), "meetingCueFingerprint");
|
|
452
|
+
|
|
453
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/event-query.js
|
|
454
|
+
var EVENT_QUERY = defineQuery({
|
|
455
|
+
entity: "event",
|
|
456
|
+
backend: "sql",
|
|
457
|
+
fields: [
|
|
458
|
+
{ name: "id", type: "num", operators: ["term", "range"], example: "id:1" },
|
|
459
|
+
{ name: "origin", type: "enum", operators: ["term"], values: ["auto", "owner"], example: "origin:owner" },
|
|
460
|
+
...["starts_at", "ends_at", "created_at", "updated_at"].map((name) => ({
|
|
461
|
+
name,
|
|
462
|
+
type: "time",
|
|
463
|
+
operators: ["term", "range"],
|
|
464
|
+
example: `${name}>=2026-01-01`
|
|
465
|
+
}))
|
|
466
|
+
]
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/events.js
|
|
470
|
+
var linkEvent = /* @__PURE__ */ __name(async (store, details, now = Date.now()) => {
|
|
471
|
+
const current = await store.meeting(details.meeting.id);
|
|
472
|
+
if (!current)
|
|
473
|
+
return null;
|
|
474
|
+
const { meeting: meeting2, series } = current;
|
|
475
|
+
if (meeting2.eventId !== null)
|
|
476
|
+
return (await store.events()).find((e) => e.id === meeting2.eventId) ?? null;
|
|
477
|
+
const candidates = meeting2.startedAt === null ? [] : await store.eventCandidates({
|
|
478
|
+
meetingSeriesId: meeting2.meetingSeriesId,
|
|
479
|
+
joinUrl: meeting2.joinUrl,
|
|
480
|
+
startsAt: meeting2.startedAt,
|
|
481
|
+
endsAt: meeting2.endedAt ?? meeting2.startedAt
|
|
482
|
+
});
|
|
483
|
+
if (candidates.length > 1) {
|
|
484
|
+
await store.reviewMeetingLink?.(meeting2.id, candidates.map(({ id: id4 }) => id4), now);
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
let event2 = candidates[0];
|
|
488
|
+
if (!event2) {
|
|
489
|
+
let eventSeriesId = series?.eventSeriesId ?? null;
|
|
490
|
+
if (series?.kind === "recurring" && eventSeriesId === null) {
|
|
491
|
+
const created = await store.createEventSeries({ title: series.title, recurrence: null, origin: "auto" }, now);
|
|
492
|
+
eventSeriesId = created.id;
|
|
493
|
+
await store.setEventSeries(series.id, eventSeriesId, now);
|
|
494
|
+
}
|
|
495
|
+
event2 = await store.createEvent({
|
|
496
|
+
eventSeriesId,
|
|
497
|
+
title: meeting2.title,
|
|
498
|
+
description: meeting2.description,
|
|
499
|
+
location: meeting2.location,
|
|
500
|
+
startsAt: meeting2.startedAt,
|
|
501
|
+
endsAt: meeting2.endedAt,
|
|
502
|
+
timezone: meeting2.timezone,
|
|
503
|
+
origin: "auto",
|
|
504
|
+
deletedAt: null
|
|
505
|
+
}, now);
|
|
506
|
+
}
|
|
507
|
+
await store.linkMeeting(meeting2.id, event2.id, now);
|
|
508
|
+
const linked = await store.meeting(meeting2.id);
|
|
509
|
+
return (await store.events()).find((e) => e.id === linked?.meeting.eventId) ?? null;
|
|
510
|
+
}, "linkEvent");
|
|
511
|
+
|
|
512
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/participant-search.js
|
|
513
|
+
var normalizeMeetingParticipantQuery = /* @__PURE__ */ __name((text9) => text9.normalize("NFKC").toLowerCase(), "normalizeMeetingParticipantQuery");
|
|
514
|
+
var validateMeetingParticipantQuery = /* @__PURE__ */ __name((query) => {
|
|
515
|
+
if (typeof query !== "string" || !query.trim() || query.length > 500 || query.includes("\0"))
|
|
516
|
+
throw new CliError("validation_error", "participant query must contain 1\u2013500 characters without NUL");
|
|
517
|
+
return normalizeMeetingParticipantQuery(query.trim());
|
|
518
|
+
}, "validateMeetingParticipantQuery");
|
|
519
|
+
var validateMeetingParticipantSearch = /* @__PURE__ */ __name((query, input) => {
|
|
520
|
+
input.signal?.throwIfAborted();
|
|
521
|
+
const normalized = validateMeetingParticipantQuery(query);
|
|
522
|
+
const bounded2 = /* @__PURE__ */ __name((value, maximum, name) => {
|
|
523
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum)
|
|
524
|
+
throw new CliError("validation_error", `${name} must be an integer from 1 through ${maximum}`);
|
|
525
|
+
return value;
|
|
526
|
+
}, "bounded");
|
|
527
|
+
return {
|
|
528
|
+
query: normalized,
|
|
529
|
+
accountId: bounded2(input.accountId, Number.MAX_SAFE_INTEGER, "accountId"),
|
|
530
|
+
limit: bounded2(input.limit ?? 50, 1e3, "limit"),
|
|
531
|
+
scanLimit: bounded2(input.scanLimit ?? 1e3, 1e4, "scanLimit"),
|
|
532
|
+
maxReadBytes: bounded2(input.maxReadBytes ?? 1024 ** 2, 64 * 1024 ** 2, "maxReadBytes")
|
|
533
|
+
};
|
|
534
|
+
}, "validateMeetingParticipantSearch");
|
|
535
|
+
|
|
536
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/reads.js
|
|
537
|
+
var MeetingError = class extends CliError {
|
|
538
|
+
static {
|
|
539
|
+
__name(this, "MeetingError");
|
|
540
|
+
}
|
|
541
|
+
constructor(code, message) {
|
|
542
|
+
super(code, message);
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
var positiveInteger = /* @__PURE__ */ __name((value) => {
|
|
546
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0)
|
|
547
|
+
throw new MeetingError("validation_error", "expected a positive integer");
|
|
548
|
+
return value;
|
|
549
|
+
}, "positiveInteger");
|
|
550
|
+
var validateFilter = /* @__PURE__ */ __name((filter) => {
|
|
551
|
+
for (const value of [filter.accountId, filter.eventId, filter.meetingSeriesId])
|
|
552
|
+
if (value !== void 0)
|
|
553
|
+
positiveInteger(value);
|
|
554
|
+
for (const value of [filter.since, filter.until])
|
|
555
|
+
if (value !== void 0 && !Number.isFinite(value))
|
|
556
|
+
throw new MeetingError("validation_error", "expected epoch milliseconds");
|
|
557
|
+
if (filter.since !== void 0 && filter.until !== void 0 && filter.since > filter.until)
|
|
558
|
+
throw new MeetingError("validation_error", "since must not exceed until");
|
|
559
|
+
for (const value of [filter.limit, filter.offset])
|
|
560
|
+
if (value !== void 0 && (!Number.isSafeInteger(value) || value < 0))
|
|
561
|
+
throw new MeetingError("validation_error", "expected a nonnegative integer");
|
|
562
|
+
}, "validateFilter");
|
|
563
|
+
var meetingShow = /* @__PURE__ */ __name(async (store, id4, accountId) => {
|
|
564
|
+
const details = await store.meeting(positiveInteger(id4));
|
|
565
|
+
if (!details || accountId !== void 0 && details.meeting.accountId !== accountId)
|
|
566
|
+
throw new MeetingError("not_found", "meeting not found");
|
|
567
|
+
return details;
|
|
568
|
+
}, "meetingShow");
|
|
569
|
+
var listed = /* @__PURE__ */ __name((items) => ({ items, page: 1, limit: items.length, hasMore: false }), "listed");
|
|
570
|
+
var meetingPeople = /* @__PURE__ */ __name(async (store, query, accountId, options = {}) => {
|
|
571
|
+
if (accountId === void 0)
|
|
572
|
+
validateMeetingParticipantQuery(query);
|
|
573
|
+
else
|
|
574
|
+
validateMeetingParticipantSearch(query, { ...options, accountId });
|
|
575
|
+
if (store.participantCandidates && accountId === void 0)
|
|
576
|
+
throw new MeetingError("configuration_error", "select an account for bounded participant lookup");
|
|
577
|
+
if (accountId !== void 0 && store.participantCandidates) {
|
|
578
|
+
const { limit, has_more, next_cursor, ...packet } = await store.participantCandidates(query, {
|
|
579
|
+
...options,
|
|
580
|
+
accountId
|
|
581
|
+
});
|
|
582
|
+
return {
|
|
583
|
+
...packet,
|
|
584
|
+
page: { mode: "cursor", limit, has_more, ...next_cursor ? { next_cursor } : {} },
|
|
585
|
+
...next_cursor ? {
|
|
586
|
+
next: [
|
|
587
|
+
stepOf(PAGE_NEXT2, {
|
|
588
|
+
command: "meetings people",
|
|
589
|
+
args: {
|
|
590
|
+
query,
|
|
591
|
+
limit,
|
|
592
|
+
...options.scanLimit === void 0 ? {} : { scan_limit: options.scanLimit },
|
|
593
|
+
...options.maxReadBytes === void 0 ? {} : { max_read_bytes: options.maxReadBytes },
|
|
594
|
+
cursor: next_cursor
|
|
595
|
+
},
|
|
596
|
+
values: { shown: packet.items.length }
|
|
597
|
+
})
|
|
598
|
+
]
|
|
599
|
+
} : {}
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
if (Object.values(options).some((value) => value !== void 0))
|
|
603
|
+
throw new MeetingError("configuration_error", "bounded participant lookup needs a selected account and capable store");
|
|
604
|
+
return listed(await store.participants(query, accountId));
|
|
605
|
+
}, "meetingPeople");
|
|
606
|
+
var PAGE_NEXT2 = STEPS.find((step) => step.id === "page.next");
|
|
607
|
+
var meetingsList = /* @__PURE__ */ __name(async (store, filter = {}, page = 1) => {
|
|
608
|
+
validateFilter(filter);
|
|
609
|
+
positiveInteger(page);
|
|
610
|
+
const limit = positiveInteger(filter.limit ?? 100);
|
|
611
|
+
const offset = (page - 1) * limit;
|
|
612
|
+
if (!Number.isSafeInteger(offset + limit + 1))
|
|
613
|
+
throw new MeetingError("validation_error", "pagination exceeds safe integer range");
|
|
614
|
+
const rows = await store.meetings({ ...filter, limit: limit + 1, offset });
|
|
615
|
+
const shown = rows.slice(0, limit);
|
|
616
|
+
const owners = /* @__PURE__ */ new Map();
|
|
617
|
+
for (const { accountId } of shown) {
|
|
618
|
+
if (owners.has(accountId))
|
|
619
|
+
continue;
|
|
620
|
+
const owner = await store.account(accountId);
|
|
621
|
+
if (!owner)
|
|
622
|
+
throw new MeetingError("not_found", `meeting account ${accountId} is not in the store`);
|
|
623
|
+
owners.set(accountId, owner);
|
|
624
|
+
}
|
|
625
|
+
const has_more = rows.length > limit;
|
|
626
|
+
return {
|
|
627
|
+
items: shown.map((row) => meetingItem(row, owners.get(row.accountId))),
|
|
628
|
+
page: { mode: "page", limit, has_more, ...has_more ? { next_page: page + 1 } : {} },
|
|
629
|
+
...has_more ? {
|
|
630
|
+
next: [
|
|
631
|
+
stepOf(PAGE_NEXT2, { command: "meetings list", args: { page: page + 1, limit }, values: { shown: limit } })
|
|
632
|
+
]
|
|
633
|
+
} : {}
|
|
634
|
+
};
|
|
635
|
+
}, "meetingsList");
|
|
636
|
+
var meetingsQuery = /* @__PURE__ */ __name((text9) => {
|
|
637
|
+
if (text9 === void 0 || text9.trim() === "")
|
|
638
|
+
return void 0;
|
|
639
|
+
const context3 = { command: "meetings list", guide: MEETING_QUERY_GUIDE };
|
|
640
|
+
const query = parseLucene(text9, { defaultField: "none", ...context3 });
|
|
641
|
+
validateQuery(query, MEETING_QUERY, context3);
|
|
642
|
+
return query;
|
|
643
|
+
}, "meetingsQuery");
|
|
644
|
+
var MEETING_QUERY_GUIDE = "https://github.com/WireCatLabs/cli-core/blob/main/docs/search/query-language.md";
|
|
645
|
+
var ownerOf = /* @__PURE__ */ __name(async (store, accountId) => {
|
|
646
|
+
const owner = await store.account(accountId);
|
|
647
|
+
if (!owner)
|
|
648
|
+
throw new MeetingError("not_found", `meeting account ${accountId} is not in the store`);
|
|
649
|
+
return owner;
|
|
650
|
+
}, "ownerOf");
|
|
651
|
+
var meetingDetailsAnswer = /* @__PURE__ */ __name(async (store, id4, accountId) => {
|
|
652
|
+
const details = await meetingShow(store, id4, accountId);
|
|
653
|
+
return { item: meetingDetailsItem(details, await ownerOf(store, details.meeting.accountId)) };
|
|
654
|
+
}, "meetingDetailsAnswer");
|
|
655
|
+
var meetingTranscriptAnswer = /* @__PURE__ */ __name(async (store, id4, accountId, options = {}) => {
|
|
656
|
+
const details = await meetingShow(store, id4, accountId);
|
|
657
|
+
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)));
|
|
658
|
+
}, "meetingTranscriptAnswer");
|
|
659
|
+
var meetingSummaryAnswer = /* @__PURE__ */ __name(async (store, id4, accountId) => {
|
|
660
|
+
const details = await meetingShow(store, id4, accountId);
|
|
661
|
+
return wholeList(details.summaries.map((one) => meetingSummaryItem(details.meeting.accountId, one)));
|
|
662
|
+
}, "meetingSummaryAnswer");
|
|
663
|
+
|
|
664
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/export.js
|
|
665
|
+
var timestamp = /* @__PURE__ */ __name((milliseconds) => {
|
|
666
|
+
if (!Number.isSafeInteger(milliseconds) || milliseconds < 0)
|
|
667
|
+
throw new MeetingError("validation_error", "transcript times must be nonnegative integer milliseconds");
|
|
668
|
+
const hours = Math.floor(milliseconds / 36e5);
|
|
669
|
+
const minutes = Math.floor(milliseconds % 36e5 / 6e4);
|
|
670
|
+
const seconds = Math.floor(milliseconds % 6e4 / 1e3);
|
|
671
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(milliseconds % 1e3).padStart(3, "0")}`;
|
|
672
|
+
}, "timestamp");
|
|
673
|
+
var vttText = /* @__PURE__ */ __name((text9) => {
|
|
674
|
+
if (visibleControls(text9) !== text9 || /\n\s*\n/.test(text9))
|
|
675
|
+
throw new MeetingError("validation_error", "cue paragraphs or control characters require Markdown export");
|
|
676
|
+
return text9.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
677
|
+
}, "vttText");
|
|
678
|
+
var serializeVtt = /* @__PURE__ */ __name((lines) => `WEBVTT
|
|
679
|
+
|
|
680
|
+
${lines.map((line2, index) => {
|
|
681
|
+
if (index > 0 && line2.startMs < (lines[index - 1]?.startMs ?? 0))
|
|
682
|
+
throw new MeetingError("validation_error", "WebVTT cues must have nondecreasing start times");
|
|
683
|
+
if (line2.endMs <= line2.startMs)
|
|
684
|
+
throw new MeetingError("validation_error", "a transcript cue ends before it starts");
|
|
685
|
+
const speaker = line2.speaker === null ? "" : `${vttText(line2.speaker)}: `;
|
|
686
|
+
if (line2.speaker?.includes("\n"))
|
|
687
|
+
throw new MeetingError("validation_error", "a speaker must fit on one line");
|
|
688
|
+
return `${index + 1}
|
|
689
|
+
${timestamp(line2.startMs)} --> ${timestamp(line2.endMs)}
|
|
690
|
+
${speaker}${vttText(line2.text)}
|
|
691
|
+
|
|
692
|
+
`;
|
|
693
|
+
}).join("")}`, "serializeVtt");
|
|
694
|
+
var markdown = /* @__PURE__ */ __name((text9) => visibleControls(text9).replace(/[\\`*_{}[\]()<>#+.!|~]/g, "\\$&"), "markdown");
|
|
695
|
+
var heading = /* @__PURE__ */ __name((text9) => markdown(singleLine(text9)), "heading");
|
|
696
|
+
var quote = /* @__PURE__ */ __name((text9) => markdown(text9).split(/\r\n|\r|\n/).map((line2) => `> ${line2}`).join("\n"), "quote");
|
|
697
|
+
var transcriptsOf = /* @__PURE__ */ __name((details, transcriptId) => {
|
|
698
|
+
if (transcriptId !== void 0) {
|
|
699
|
+
positiveInteger(transcriptId);
|
|
700
|
+
const transcript = details.transcripts.find((part) => part.transcript.id === transcriptId && part.transcript.deletedAt === null);
|
|
701
|
+
if (!transcript)
|
|
702
|
+
throw new MeetingError("not_found", "transcript not found in the selected meeting");
|
|
703
|
+
return [transcript];
|
|
704
|
+
}
|
|
705
|
+
return details.transcripts.filter((part) => part.transcript.supersededAt === null && part.transcript.deletedAt === null);
|
|
706
|
+
}, "transcriptsOf");
|
|
707
|
+
var exportMeeting = /* @__PURE__ */ __name(async (store, id4, options) => {
|
|
708
|
+
if (options.format !== "markdown" && options.format !== "vtt")
|
|
709
|
+
throw new MeetingError("validation_error", "export format must be markdown or vtt");
|
|
710
|
+
const details = await meetingShow(store, id4, options.accountId);
|
|
711
|
+
const transcripts = transcriptsOf(details, options.transcriptId);
|
|
712
|
+
let content;
|
|
713
|
+
if (options.format === "vtt") {
|
|
714
|
+
const [selected] = transcripts;
|
|
715
|
+
if (!selected)
|
|
716
|
+
throw new MeetingError("not_found", "meeting has no transcript to export");
|
|
717
|
+
if (transcripts.length > 1)
|
|
718
|
+
throw new MeetingError("validation_error", "choose a transcript id when exporting multiple transcripts as VTT");
|
|
719
|
+
content = serializeVtt([...selected.rows].sort((a, b) => a.position - b.position).map((row) => ({
|
|
720
|
+
startMs: row.startMs,
|
|
721
|
+
endMs: row.endMs,
|
|
722
|
+
speaker: row.speakerName,
|
|
723
|
+
text: row.text
|
|
724
|
+
})));
|
|
725
|
+
} else {
|
|
726
|
+
const parts = [`# ${heading(details.meeting.title ?? "Untitled meeting")}`, `Meeting ID: ${details.meeting.id}`];
|
|
727
|
+
if (details.meeting.description !== null)
|
|
728
|
+
parts.push("## Description", quote(details.meeting.description));
|
|
729
|
+
for (const summary of details.summaries) {
|
|
730
|
+
parts.push(`## ${heading(summary.title ?? "Summary")}`);
|
|
731
|
+
if (summary.content !== null)
|
|
732
|
+
parts.push(quote(summary.content));
|
|
733
|
+
else {
|
|
734
|
+
if (summary.overview !== null)
|
|
735
|
+
parts.push(quote(summary.overview));
|
|
736
|
+
for (const section of summary.sections)
|
|
737
|
+
parts.push(`### ${heading(section.label)}`, quote(section.text));
|
|
738
|
+
if (summary.nextSteps.length > 0)
|
|
739
|
+
parts.push("### Next steps", summary.nextSteps.map((step) => `- ${markdown(step)}`).join("\n"));
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
for (const part of transcripts) {
|
|
743
|
+
parts.push(`## Transcript ${part.transcript.id}`, `Source: ${heading(part.transcript.source)}`);
|
|
744
|
+
if (part.transcript.supersededAt !== null)
|
|
745
|
+
parts.push("Version: superseded");
|
|
746
|
+
for (const row of [...part.rows].sort((a, b) => a.position - b.position))
|
|
747
|
+
parts.push(`[${timestamp(row.startMs)} \u2013 ${timestamp(row.endMs)}]${row.speakerName === null ? "" : ` ${heading(row.speakerName)}`}`, quote(row.text));
|
|
748
|
+
}
|
|
749
|
+
content = `${parts.join("\n\n")}
|
|
750
|
+
`;
|
|
751
|
+
}
|
|
752
|
+
return {
|
|
753
|
+
meetingId: details.meeting.id,
|
|
754
|
+
format: options.format,
|
|
755
|
+
filename: `meeting-${details.meeting.id}${options.transcriptId === void 0 ? "" : `-transcript-${options.transcriptId}`}.${options.format === "markdown" ? "md" : "vtt"}`,
|
|
756
|
+
content
|
|
757
|
+
};
|
|
758
|
+
}, "exportMeeting");
|
|
759
|
+
|
|
760
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/findings-rules.js
|
|
761
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
762
|
+
|
|
763
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/provider.js
|
|
764
|
+
var snapshotMeetingScope = /* @__PURE__ */ __name((scope3) => {
|
|
765
|
+
const provider = scope3?.provider;
|
|
766
|
+
const account = scope3?.account;
|
|
767
|
+
if (typeof provider !== "string" || !provider.trim() || provider.length > 200 || /[\0\r\n]/.test(provider) || typeof account !== "string" || !account.trim() || account.length > 1e3 || /[\0\r\n]/.test(account))
|
|
768
|
+
throw new CliError("validation_error", "meeting provider and account must be bounded nonempty identifiers");
|
|
769
|
+
return Object.freeze({ provider, account });
|
|
770
|
+
}, "snapshotMeetingScope");
|
|
771
|
+
|
|
772
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/timestamp.js
|
|
773
|
+
var meetingTimestamp = /* @__PURE__ */ __name((value, name) => {
|
|
774
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.+(?:Z|[+-]\d{2}:\d{2})$/i.test(value) || !Number.isFinite(Date.parse(value)))
|
|
775
|
+
throw new CliError("validation_error", `${name} must be an ISO timestamp with a timezone`);
|
|
776
|
+
const date2 = value.slice(0, 10);
|
|
777
|
+
const instant = Date.parse(`${date2}T00:00:00Z`);
|
|
778
|
+
if (!Number.isFinite(instant) || new Date(instant).toISOString().slice(0, 10) !== date2)
|
|
779
|
+
throw new CliError("validation_error", `${name} contains an invalid calendar date`);
|
|
780
|
+
return new Date(value).toISOString();
|
|
781
|
+
}, "meetingTimestamp");
|
|
782
|
+
|
|
783
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/meeting-management.js
|
|
784
|
+
var nonempty = /* @__PURE__ */ __name((value, name) => {
|
|
785
|
+
if (typeof value !== "string" || !value.trim())
|
|
786
|
+
throw new CliError("validation_error", `${name} must be nonempty`);
|
|
787
|
+
return value;
|
|
788
|
+
}, "nonempty");
|
|
789
|
+
var validateMeetingChange = /* @__PURE__ */ __name((change, create) => {
|
|
790
|
+
if (!change || typeof change !== "object" || Array.isArray(change) || Object.keys(change).some((key) => !["title", "kind", "startTime", "durationMinutes", "timezone", "agenda"].includes(key)))
|
|
791
|
+
throw new CliError("validation_error", "unsupported meeting change field");
|
|
792
|
+
const result = {};
|
|
793
|
+
if (change.title !== void 0)
|
|
794
|
+
result.title = nonempty(change.title, "meeting title");
|
|
795
|
+
if (create && result.title === void 0)
|
|
796
|
+
throw new CliError("validation_error", "meeting title is required");
|
|
797
|
+
if (change.kind !== void 0) {
|
|
798
|
+
if (change.kind !== "instant" && change.kind !== "scheduled")
|
|
799
|
+
throw new CliError("validation_error", "only instant or scheduled meeting kinds are supported");
|
|
800
|
+
result.kind = change.kind;
|
|
801
|
+
}
|
|
802
|
+
if (change.startTime !== void 0) {
|
|
803
|
+
result.startTime = meetingTimestamp(change.startTime, "meeting start");
|
|
804
|
+
}
|
|
805
|
+
if (change.durationMinutes !== void 0) {
|
|
806
|
+
if (!Number.isSafeInteger(change.durationMinutes) || change.durationMinutes <= 0 || change.durationMinutes > 1440)
|
|
807
|
+
throw new CliError("validation_error", "meeting duration must be an integer from 1 to 1440 minutes");
|
|
808
|
+
result.durationMinutes = change.durationMinutes;
|
|
809
|
+
}
|
|
810
|
+
if (change.timezone !== void 0) {
|
|
811
|
+
if (typeof change.timezone !== "string" || !change.timezone.trim())
|
|
812
|
+
throw new CliError("validation_error", "meeting timezone must be a valid IANA timezone");
|
|
813
|
+
try {
|
|
814
|
+
new Intl.DateTimeFormat("en", { timeZone: change.timezone }).format();
|
|
815
|
+
} catch {
|
|
816
|
+
throw new CliError("validation_error", "meeting timezone must be a valid IANA timezone");
|
|
817
|
+
}
|
|
818
|
+
result.timezone = change.timezone;
|
|
819
|
+
}
|
|
820
|
+
if (change.agenda !== void 0) {
|
|
821
|
+
if (typeof change.agenda !== "string")
|
|
822
|
+
throw new CliError("validation_error", "meeting agenda must be text");
|
|
823
|
+
result.agenda = change.agenda;
|
|
824
|
+
}
|
|
825
|
+
if (create) {
|
|
826
|
+
result.kind ??= "scheduled";
|
|
827
|
+
if (result.kind === "scheduled" && result.startTime === void 0)
|
|
828
|
+
throw new CliError("validation_error", "scheduled meeting start is required");
|
|
829
|
+
} else if (!Object.keys(result).length)
|
|
830
|
+
throw new CliError("validation_error", "at least one meeting change is required");
|
|
831
|
+
return Object.freeze(result);
|
|
832
|
+
}, "validateMeetingChange");
|
|
833
|
+
var checkCancelled = /* @__PURE__ */ __name((signal) => {
|
|
834
|
+
if (!signal?.aborted)
|
|
835
|
+
return;
|
|
836
|
+
if (signal.reason instanceof CliError)
|
|
837
|
+
throw signal.reason;
|
|
838
|
+
const timeout = signal.reason instanceof Error && signal.reason.name === "TimeoutError";
|
|
839
|
+
throw new CliError(timeout ? "timeout" : "cancelled", timeout ? "meeting operation timed out" : "meeting operation cancelled");
|
|
840
|
+
}, "checkCancelled");
|
|
841
|
+
var dispatchMeetingMutation = /* @__PURE__ */ __name(async (options, dispatch) => {
|
|
842
|
+
const { apply, dryRun, signal } = options;
|
|
843
|
+
checkCancelled(signal);
|
|
844
|
+
if (apply !== true || dryRun)
|
|
845
|
+
return { applied: false };
|
|
846
|
+
return { applied: true, value: await dispatch(signal) };
|
|
847
|
+
}, "dispatchMeetingMutation");
|
|
848
|
+
var createMeetingManagement = /* @__PURE__ */ __name((scope3, ports) => {
|
|
849
|
+
const fixed = snapshotMeetingScope(scope3);
|
|
850
|
+
const capabilities = {};
|
|
851
|
+
for (const name of ["list", "get", "invitation", "create", "update", "cancel"]) {
|
|
852
|
+
const port = ports[name];
|
|
853
|
+
if (typeof port === "function")
|
|
854
|
+
Object.defineProperty(capabilities, name, { value: port.bind(ports), enumerable: true });
|
|
855
|
+
}
|
|
856
|
+
Object.freeze(capabilities);
|
|
857
|
+
const context3 = /* @__PURE__ */ __name((options) => {
|
|
858
|
+
const signal = options.signal;
|
|
859
|
+
checkCancelled(signal);
|
|
860
|
+
return Object.freeze({ scope: fixed, ...signal ? { signal } : {} });
|
|
861
|
+
}, "context");
|
|
862
|
+
const capability = /* @__PURE__ */ __name((name) => {
|
|
863
|
+
const port = capabilities[name];
|
|
864
|
+
if (!port)
|
|
865
|
+
throw new CliError("provider_unavailable", `meeting provider does not support ${name}`);
|
|
866
|
+
return port;
|
|
867
|
+
}, "capability");
|
|
868
|
+
return {
|
|
869
|
+
scope: fixed,
|
|
870
|
+
capabilities: Object.freeze(Object.keys(capabilities).filter((name) => typeof capabilities[name] === "function")),
|
|
871
|
+
list(options = {}) {
|
|
872
|
+
return capability("list")(context3(options));
|
|
873
|
+
},
|
|
874
|
+
get(id4, options = {}) {
|
|
875
|
+
return capability("get")(nonempty(id4, "meeting id"), context3(options));
|
|
876
|
+
},
|
|
877
|
+
invitation(id4, options = {}) {
|
|
878
|
+
return capability("invitation")(nonempty(id4, "meeting id"), context3(options));
|
|
879
|
+
},
|
|
880
|
+
async create(change, options = {}) {
|
|
881
|
+
const port = capability("create");
|
|
882
|
+
const validated = validateMeetingChange(change, true);
|
|
883
|
+
const ctx = context3(options);
|
|
884
|
+
const outcome = await dispatchMeetingMutation(options, () => port(validated, ctx));
|
|
885
|
+
return {
|
|
886
|
+
action: "create",
|
|
887
|
+
scope: fixed,
|
|
888
|
+
change: validated,
|
|
889
|
+
applied: outcome.applied,
|
|
890
|
+
...outcome.value ? { meeting: outcome.value } : {}
|
|
891
|
+
};
|
|
892
|
+
},
|
|
893
|
+
async update(id4, change, options = {}) {
|
|
894
|
+
const port = capability("update");
|
|
895
|
+
const validatedId = nonempty(id4, "meeting id");
|
|
896
|
+
const validated = validateMeetingChange(change, false);
|
|
897
|
+
const ctx = context3(options);
|
|
898
|
+
const outcome = await dispatchMeetingMutation(options, () => port(validatedId, validated, ctx));
|
|
899
|
+
return { action: "update", scope: fixed, id: validatedId, change: validated, applied: outcome.applied };
|
|
900
|
+
},
|
|
901
|
+
async cancel(id4, options = {}) {
|
|
902
|
+
const port = capability("cancel");
|
|
903
|
+
const validatedId = nonempty(id4, "meeting id");
|
|
904
|
+
const occurrenceId2 = options.occurrenceId === void 0 ? void 0 : nonempty(options.occurrenceId, "occurrence id");
|
|
905
|
+
const ctx = { ...context3(options), ...occurrenceId2 === void 0 ? {} : { occurrenceId: occurrenceId2 } };
|
|
906
|
+
const outcome = await dispatchMeetingMutation(options, () => port(validatedId, ctx));
|
|
907
|
+
return {
|
|
908
|
+
action: "cancel",
|
|
909
|
+
scope: fixed,
|
|
910
|
+
id: validatedId,
|
|
911
|
+
applied: outcome.applied,
|
|
912
|
+
...occurrenceId2 === void 0 ? {} : { occurrenceId: occurrenceId2 }
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
}, "createMeetingManagement");
|
|
917
|
+
|
|
918
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/meeting-context.js
|
|
919
|
+
var MEETING_FACT_TYPES = ["fact", "statement", "question", "decision", "promise"];
|
|
920
|
+
var id = /* @__PURE__ */ __name((value) => {
|
|
921
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
|
|
922
|
+
throw new CliError("validation_error", "meeting context identifiers must be positive integers");
|
|
923
|
+
return value;
|
|
924
|
+
}, "id");
|
|
925
|
+
var text3 = /* @__PURE__ */ __name((value, max) => {
|
|
926
|
+
if (typeof value !== "string" || !value.trim() || value.length > max || value.includes("\0"))
|
|
927
|
+
throw new CliError("validation_error", `meeting context text must contain 1\u2013${max} characters without NUL`);
|
|
928
|
+
return value.trim();
|
|
929
|
+
}, "text");
|
|
930
|
+
var uid = /* @__PURE__ */ __name((value) => {
|
|
931
|
+
const result = text3(value, 100);
|
|
932
|
+
if (!/^[1-9]\d*$/.test(result) || !Number.isSafeInteger(Number(result)))
|
|
933
|
+
throw new CliError("validation_error", "person UID must be a positive integer");
|
|
934
|
+
return result;
|
|
935
|
+
}, "uid");
|
|
936
|
+
var strings = /* @__PURE__ */ __name((value, count6, length) => {
|
|
937
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > count6)
|
|
938
|
+
throw new CliError("validation_error", `meeting context list must contain 1\u2013${count6} entries`);
|
|
939
|
+
return Object.freeze([...new Set(value.map((entry) => text3(entry, length)))]);
|
|
940
|
+
}, "strings");
|
|
941
|
+
var fields = {
|
|
942
|
+
"note.add": ["text", "title"],
|
|
943
|
+
"tags.add": ["tags"],
|
|
944
|
+
"tags.remove": ["tags"],
|
|
945
|
+
"memory.add": ["body", "kind", "scope", "evidence", "subject"],
|
|
946
|
+
"fact.add": ["statement", "type", "scope", "evidence", "subject"],
|
|
947
|
+
"event.link": ["eventId", "expectedEventId"],
|
|
948
|
+
"person.link": ["participantId", "personUid", "targetAccountIds", "expectedPersonUid"]
|
|
949
|
+
};
|
|
950
|
+
var validateMeetingContextChange = /* @__PURE__ */ __name((change) => {
|
|
951
|
+
if (!change || typeof change !== "object" || Array.isArray(change) || !Object.hasOwn(fields, change.action) || Object.keys(change).some((key) => key !== "action" && !fields[change.action].includes(key)))
|
|
952
|
+
throw new CliError("validation_error", "unsupported meeting context change");
|
|
953
|
+
switch (change.action) {
|
|
954
|
+
case "note.add":
|
|
955
|
+
return Object.freeze({
|
|
956
|
+
action: change.action,
|
|
957
|
+
text: text3(change.text, 1e5),
|
|
958
|
+
...change.title === void 0 ? {} : { title: text3(change.title, 500) }
|
|
959
|
+
});
|
|
960
|
+
case "tags.add":
|
|
961
|
+
case "tags.remove":
|
|
962
|
+
return Object.freeze({ action: change.action, tags: strings(change.tags, 100, 200) });
|
|
963
|
+
case "memory.add": {
|
|
964
|
+
if (!["summary", "digest", "preference"].includes(change.kind) || !["personal", "work"].includes(change.scope))
|
|
965
|
+
throw new CliError("validation_error", "memory kind and explicit personal/work scope are required");
|
|
966
|
+
return Object.freeze({
|
|
967
|
+
action: change.action,
|
|
968
|
+
body: text3(change.body, 2e4),
|
|
969
|
+
kind: change.kind,
|
|
970
|
+
scope: change.scope,
|
|
971
|
+
evidence: strings(change.evidence, 100, 4e3),
|
|
972
|
+
...change.subject === void 0 ? {} : { subject: text3(change.subject, 4e3) }
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
case "fact.add": {
|
|
976
|
+
if (!MEETING_FACT_TYPES.includes(change.type) || !["personal", "work"].includes(change.scope))
|
|
977
|
+
throw new CliError("validation_error", `fact type (${MEETING_FACT_TYPES.join(", ")}) and explicit personal/work scope are required`);
|
|
978
|
+
return Object.freeze({
|
|
979
|
+
action: change.action,
|
|
980
|
+
statement: text3(change.statement, 2e4),
|
|
981
|
+
type: change.type,
|
|
982
|
+
scope: change.scope,
|
|
983
|
+
evidence: strings(change.evidence, 100, 4e3),
|
|
984
|
+
...change.subject === void 0 ? {} : { subject: text3(change.subject, 4e3) }
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
case "event.link":
|
|
988
|
+
return Object.freeze({
|
|
989
|
+
action: change.action,
|
|
990
|
+
eventId: change.eventId === null ? null : id(change.eventId),
|
|
991
|
+
...change.expectedEventId === void 0 ? {} : { expectedEventId: change.expectedEventId === null ? null : id(change.expectedEventId) }
|
|
992
|
+
});
|
|
993
|
+
case "person.link": {
|
|
994
|
+
const targets = change.targetAccountIds;
|
|
995
|
+
if (targets !== void 0 && (!Array.isArray(targets) || targets.length < 1 || targets.length > 1e3))
|
|
996
|
+
throw new CliError("validation_error", "target accounts must contain 1\u20131000 identifiers");
|
|
997
|
+
return Object.freeze({
|
|
998
|
+
action: change.action,
|
|
999
|
+
participantId: id(change.participantId),
|
|
1000
|
+
personUid: uid(change.personUid),
|
|
1001
|
+
...targets === void 0 ? {} : { targetAccountIds: Object.freeze([...new Set(targets.map(id))]) },
|
|
1002
|
+
...change.expectedPersonUid === void 0 ? {} : { expectedPersonUid: change.expectedPersonUid === null ? null : uid(change.expectedPersonUid) }
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}, "validateMeetingContextChange");
|
|
1007
|
+
var createMeetingContext = /* @__PURE__ */ __name((scope3, accountId, ports) => {
|
|
1008
|
+
const fixed = snapshotMeetingScope(scope3);
|
|
1009
|
+
const account = id(accountId);
|
|
1010
|
+
const actions = Object.freeze([...new Set(ports.actions)]);
|
|
1011
|
+
if (actions.some((action) => !Object.hasOwn(fields, action)))
|
|
1012
|
+
throw new CliError("validation_error", "unsupported meeting context capability");
|
|
1013
|
+
const apply = ports.apply.bind(ports);
|
|
1014
|
+
return {
|
|
1015
|
+
scope: fixed,
|
|
1016
|
+
accountId: account,
|
|
1017
|
+
actions,
|
|
1018
|
+
async change(meetingId, input, options = {}) {
|
|
1019
|
+
const target = id(meetingId);
|
|
1020
|
+
const change = validateMeetingContextChange(input);
|
|
1021
|
+
if (!actions.includes(change.action))
|
|
1022
|
+
throw new CliError("provider_unavailable", `meeting context does not support ${change.action}`);
|
|
1023
|
+
const context3 = Object.freeze({
|
|
1024
|
+
scope: fixed,
|
|
1025
|
+
accountId: account,
|
|
1026
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1027
|
+
});
|
|
1028
|
+
const outcome = await dispatchMeetingMutation(options, () => apply(target, change, context3));
|
|
1029
|
+
return {
|
|
1030
|
+
scope: fixed,
|
|
1031
|
+
accountId: account,
|
|
1032
|
+
meetingId: target,
|
|
1033
|
+
change,
|
|
1034
|
+
applied: outcome.applied,
|
|
1035
|
+
...outcome.applied ? { result: outcome.value } : {}
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
}, "createMeetingContext");
|
|
1040
|
+
|
|
1041
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/findings-rules.js
|
|
1042
|
+
var TASK_TYPES = ["bug", "feature", "chore"];
|
|
1043
|
+
var invalid2 = /* @__PURE__ */ __name((message) => {
|
|
1044
|
+
throw new CliError("validation_error", message);
|
|
1045
|
+
}, "invalid");
|
|
1046
|
+
var text4 = /* @__PURE__ */ __name((value, limit) => {
|
|
1047
|
+
if (typeof value !== "string" || !value.trim() || value.includes("\0") || value.length > limit)
|
|
1048
|
+
return invalid2(`finding text must contain 1\u2013${limit} characters without NUL`);
|
|
1049
|
+
return value.trim();
|
|
1050
|
+
}, "text");
|
|
1051
|
+
var findingHash = /* @__PURE__ */ __name((value) => createHash2("sha256").update(JSON.stringify(value)).digest("hex"), "findingHash");
|
|
1052
|
+
var fields2 = /* @__PURE__ */ __name((value, allowed, noun) => {
|
|
1053
|
+
if (Object.keys(value).some((key) => !allowed.includes(key)))
|
|
1054
|
+
invalid2(`unknown ${noun} field`);
|
|
1055
|
+
}, "fields");
|
|
1056
|
+
var validateFindings = /* @__PURE__ */ __name((input, rules) => {
|
|
1057
|
+
if (!input || typeof input !== "object" || Buffer.byteLength(JSON.stringify(input), "utf8") > 65536)
|
|
1058
|
+
return invalid2(`${rules.plural} take at most 65536 UTF-8 bytes`);
|
|
1059
|
+
fields2(input, ["schemaVersion", "key", "extractor", "findings"], rules.singular);
|
|
1060
|
+
if (input.schemaVersion !== 1 || !Array.isArray(input.findings) || input.findings.length < 1 || input.findings.length > 16)
|
|
1061
|
+
return invalid2(`schemaVersion 1 takes 1\u201316 ${rules.plural}`);
|
|
1062
|
+
const key = text4(input.key, 64);
|
|
1063
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/.test(key))
|
|
1064
|
+
return invalid2("a findings key uses letters, digits, dot, colon, underscore or hyphen");
|
|
1065
|
+
const ids2 = /* @__PURE__ */ new Set();
|
|
1066
|
+
const findings = input.findings.map((finding) => {
|
|
1067
|
+
if (!finding || typeof finding !== "object")
|
|
1068
|
+
return invalid2("a finding is an object");
|
|
1069
|
+
const id4 = text4(finding.id, 64);
|
|
1070
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/.test(id4) || ids2.has(id4))
|
|
1071
|
+
return invalid2("finding IDs must be unique simple keys");
|
|
1072
|
+
ids2.add(id4);
|
|
1073
|
+
const project = text4(finding.project, 64);
|
|
1074
|
+
if (!/^project:[1-9]\d*$/.test(project))
|
|
1075
|
+
return invalid2("a finding names a project reference");
|
|
1076
|
+
if (!Array.isArray(finding.evidence) || finding.evidence.length < 1 || finding.evidence.length > 8)
|
|
1077
|
+
return invalid2(`a finding requires 1\u20138 cited ${rules.cited}s`);
|
|
1078
|
+
const evidence = finding.evidence.map((item) => {
|
|
1079
|
+
if (!item || typeof item !== "object")
|
|
1080
|
+
return invalid2("finding evidence is a reference and fingerprint");
|
|
1081
|
+
fields2(item, ["reference", "fingerprint"], rules.singular);
|
|
1082
|
+
if (typeof item.reference !== "string" || typeof item.fingerprint !== "string")
|
|
1083
|
+
return invalid2("evidence requires a reference and fingerprint");
|
|
1084
|
+
const reference2 = rules.reference(item.reference);
|
|
1085
|
+
if (!/^[a-f0-9]{64}$/.test(item.fingerprint))
|
|
1086
|
+
return invalid2(`finding evidence requires exact ${rules.cited} references and fingerprints`);
|
|
1087
|
+
return { reference: reference2, fingerprint: item.fingerprint };
|
|
1088
|
+
}).sort((a, b) => a.reference.localeCompare(b.reference));
|
|
1089
|
+
if (new Set(evidence.map((item) => item.reference)).size !== evidence.length)
|
|
1090
|
+
return invalid2(`duplicate evidence ${rules.cited}`);
|
|
1091
|
+
const base = { id: id4, project, evidence };
|
|
1092
|
+
if (finding.kind === "fact") {
|
|
1093
|
+
fields2(finding, ["id", "project", "evidence", "kind", "type", "statement"], rules.singular);
|
|
1094
|
+
if (!MEETING_FACT_TYPES.includes(finding.type))
|
|
1095
|
+
return invalid2("unknown fact finding type");
|
|
1096
|
+
return { ...base, kind: "fact", type: finding.type, statement: text4(finding.statement, 2e3) };
|
|
1097
|
+
}
|
|
1098
|
+
if (finding.kind !== "task")
|
|
1099
|
+
return invalid2("a finding is a fact or task");
|
|
1100
|
+
fields2(finding, [
|
|
1101
|
+
"id",
|
|
1102
|
+
"project",
|
|
1103
|
+
"evidence",
|
|
1104
|
+
"kind",
|
|
1105
|
+
"type",
|
|
1106
|
+
"title",
|
|
1107
|
+
"reason",
|
|
1108
|
+
"commitment",
|
|
1109
|
+
"dueAt",
|
|
1110
|
+
"dueEvidence",
|
|
1111
|
+
"assignee",
|
|
1112
|
+
"assigneeEvidence"
|
|
1113
|
+
], rules.singular);
|
|
1114
|
+
if (!TASK_TYPES.includes(finding.type))
|
|
1115
|
+
return invalid2("a task finding type is bug, chore or feature");
|
|
1116
|
+
if (!["explicit", "inferred"].includes(finding.commitment))
|
|
1117
|
+
return invalid2("task commitment must be explicit or inferred");
|
|
1118
|
+
const support = /* @__PURE__ */ __name((value) => {
|
|
1119
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > 8 || value.some((ref) => typeof ref !== "string" || !evidence.some((item) => item.reference === ref)))
|
|
1120
|
+
return invalid2("date and assignee support must cite the finding's evidence");
|
|
1121
|
+
return [...new Set(value)].sort();
|
|
1122
|
+
}, "support");
|
|
1123
|
+
if (finding.dueAt === void 0 !== (finding.dueEvidence === void 0) || finding.assignee === void 0 !== (finding.assigneeEvidence === void 0))
|
|
1124
|
+
return invalid2("optional dates and assignees require their supporting evidence");
|
|
1125
|
+
if (finding.assignee !== void 0 && (typeof finding.assignee !== "string" || !/^person:[1-9]\d*$/.test(finding.assignee)))
|
|
1126
|
+
return invalid2("an assignee must be a person reference");
|
|
1127
|
+
return {
|
|
1128
|
+
...base,
|
|
1129
|
+
kind: "task",
|
|
1130
|
+
type: finding.type,
|
|
1131
|
+
title: text4(finding.title, 300),
|
|
1132
|
+
reason: text4(finding.reason, 2e3),
|
|
1133
|
+
commitment: finding.commitment,
|
|
1134
|
+
...finding.dueAt === void 0 ? {} : { dueAt: meetingTimestamp(finding.dueAt, "finding due date"), dueEvidence: support(finding.dueEvidence) },
|
|
1135
|
+
...finding.assignee === void 0 ? {} : { assignee: finding.assignee, assigneeEvidence: support(finding.assigneeEvidence) }
|
|
1136
|
+
};
|
|
1137
|
+
});
|
|
1138
|
+
return { schemaVersion: 1, key, extractor: text4(input.extractor, 200), findings };
|
|
1139
|
+
}, "validateFindings");
|
|
1140
|
+
var findingFingerprint = /* @__PURE__ */ __name(({ id: _id, ...finding }) => findingHash(finding), "findingFingerprint");
|
|
1141
|
+
|
|
1142
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/findings.js
|
|
1143
|
+
var MEETING_FINDINGS_KIND = "meeting_findings";
|
|
1144
|
+
var cue = /* @__PURE__ */ __name((raw) => {
|
|
1145
|
+
const reference2 = canonicalMeetingReference(raw);
|
|
1146
|
+
if (parseMeetingReference(reference2).cuePosition === void 0)
|
|
1147
|
+
throw new CliError("validation_error", "finding evidence requires exact cue references and fingerprints");
|
|
1148
|
+
return reference2;
|
|
1149
|
+
}, "cue");
|
|
1150
|
+
var validateMeetingFindings = /* @__PURE__ */ __name((input) => validateFindings(input, { plural: "meeting findings", singular: "meeting finding", cited: "cue", reference: cue }), "validateMeetingFindings");
|
|
1151
|
+
var meetingFindingFingerprint = findingFingerprint;
|
|
1152
|
+
|
|
1153
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/hit-query.js
|
|
1154
|
+
var context = {
|
|
1155
|
+
command: "search meetings",
|
|
1156
|
+
guide: "https://github.com/WireCatLabs/cli-core/blob/main/docs/search/query-language.md#\u0432\u0441\u0442\u0440\u0435\u0447\u0438"
|
|
1157
|
+
};
|
|
1158
|
+
var words = ["term", "phrase"];
|
|
1159
|
+
var MOST_LINES_APART = 20;
|
|
1160
|
+
var near = /* @__PURE__ */ __name((node) => {
|
|
1161
|
+
if (node.slop !== void 0 && node.slop > MOST_LINES_APART)
|
|
1162
|
+
queryError("query.invalid-number", node.span, `words at most ${MOST_LINES_APART} lines apart: "a b"~${MOST_LINES_APART}`, context);
|
|
1163
|
+
}, "near");
|
|
1164
|
+
var MEETING_HIT_QUERY = defineQuery({
|
|
1165
|
+
entity: "meeting_hit",
|
|
1166
|
+
backend: "sql",
|
|
1167
|
+
fields: [
|
|
1168
|
+
{
|
|
1169
|
+
name: "text",
|
|
1170
|
+
type: "txt",
|
|
1171
|
+
operators: words,
|
|
1172
|
+
example: "text:budget",
|
|
1173
|
+
relation: "a passage with the word in any form, or a spelling speech recognition garbled",
|
|
1174
|
+
validate: near
|
|
1175
|
+
},
|
|
1176
|
+
{
|
|
1177
|
+
name: "exact",
|
|
1178
|
+
type: "txt",
|
|
1179
|
+
operators: words,
|
|
1180
|
+
example: "exact:budget",
|
|
1181
|
+
relation: "a passage with the word as typed: no other forms, no garbled spellings",
|
|
1182
|
+
validate: near
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
name: "from",
|
|
1186
|
+
type: "kw",
|
|
1187
|
+
operators: words,
|
|
1188
|
+
example: 'from:"Alice Synthetic"',
|
|
1189
|
+
relation: "a line said or a chat message written by this person; attendance is --identity-id"
|
|
1190
|
+
}
|
|
1191
|
+
]
|
|
1192
|
+
});
|
|
1193
|
+
var MEETING_FIELDS = defineQuery({
|
|
1194
|
+
entity: "meeting_hit",
|
|
1195
|
+
backend: "sql",
|
|
1196
|
+
fields: [
|
|
1197
|
+
...MEETING_HIT_QUERY.fields,
|
|
1198
|
+
{
|
|
1199
|
+
name: "date",
|
|
1200
|
+
type: "time",
|
|
1201
|
+
operators: ["term", "range"],
|
|
1202
|
+
example: "date>=30d",
|
|
1203
|
+
relation: "meetings that started then; the same as --since-time and --until-time"
|
|
1204
|
+
},
|
|
1205
|
+
...["project", "tag", "topic"].map((name) => ({
|
|
1206
|
+
name,
|
|
1207
|
+
type: "kw",
|
|
1208
|
+
operators: words,
|
|
1209
|
+
example: `${name}:"Example name"`,
|
|
1210
|
+
relation: `meetings in this ${name}, by name or alias; the same as --${name}`
|
|
1211
|
+
}))
|
|
1212
|
+
]
|
|
1213
|
+
});
|
|
1214
|
+
var LIFTED = /* @__PURE__ */ new Set(["date", "project", "tag", "topic"]);
|
|
1215
|
+
var liftMeetingFields = /* @__PURE__ */ __name((query, request, now) => {
|
|
1216
|
+
let ast;
|
|
1217
|
+
try {
|
|
1218
|
+
ast = validateQuery(parseLucene(query, { defaultField: "text", proximity: true, ...context }), MEETING_FIELDS, context);
|
|
1219
|
+
} catch (error) {
|
|
1220
|
+
if (error instanceof CliError)
|
|
1221
|
+
return { query, request };
|
|
1222
|
+
throw error;
|
|
1223
|
+
}
|
|
1224
|
+
const top = ast.root.kind === "boolean" ? ast.root.clauses : [{ occur: "must", node: ast.root }];
|
|
1225
|
+
const lifted = top.filter((clause) => clause.node.kind === "predicate" && LIFTED.has(clause.node.field));
|
|
1226
|
+
const misplaced = /* @__PURE__ */ __name((node, nested) => node.kind === "predicate" ? nested && LIFTED.has(node.field) ? node : void 0 : node.clauses.map((clause) => misplaced(clause.node, true)).find(Boolean), "misplaced");
|
|
1227
|
+
const wrong = lifted.find((clause) => clause.occur !== "must")?.node ?? top.map((clause) => clause.node.kind === "boolean" ? misplaced(clause.node, true) : void 0).find(Boolean);
|
|
1228
|
+
if (wrong)
|
|
1229
|
+
queryError("query.unsupported-field", wrong.span, `${wrong.field}: chooses meetings; join it to the words with AND, outside OR, NOT and groups`, context);
|
|
1230
|
+
if (!lifted.length)
|
|
1231
|
+
return { query, request };
|
|
1232
|
+
const next = { ...request };
|
|
1233
|
+
const once = /* @__PURE__ */ __name((name, flag2) => {
|
|
1234
|
+
if (next[name] !== void 0)
|
|
1235
|
+
throw new CliError("validation_error", `give ${flag2.replace(/^--/, "")} once: as ${flag2} or in the query`);
|
|
1236
|
+
}, "once");
|
|
1237
|
+
for (const { node } of lifted) {
|
|
1238
|
+
if (node.field === "date") {
|
|
1239
|
+
once("since", "--since-time");
|
|
1240
|
+
once("until", "--until-time");
|
|
1241
|
+
const range = dateRange(node.value, node.operator === "range" ? node.upper ?? "*" : node.value, node.lower_inclusive !== false, node.upper_inclusive !== false, timezoneOf(), node.span, now);
|
|
1242
|
+
if (range.lower !== void 0)
|
|
1243
|
+
next.since = range.lower + (range.lower_inclusive ? 0 : 1);
|
|
1244
|
+
if (range.upper !== void 0)
|
|
1245
|
+
next.until = range.upper - (range.upper_inclusive ? 0 : 1);
|
|
1246
|
+
} else {
|
|
1247
|
+
const field = node.field;
|
|
1248
|
+
once(field, `--${field}`);
|
|
1249
|
+
next[field] = node.value;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
let rest = query;
|
|
1253
|
+
for (const { node } of [...lifted].sort((a, b) => b.node.span.start - a.node.span.start))
|
|
1254
|
+
rest = `${rest.slice(0, node.span.start)}${rest.slice(node.span.end)}`;
|
|
1255
|
+
rest = rest.replace(/^(?:\s*AND\b)+|(?:\bAND\s*)+$/g, "").replace(/\bAND(\s+AND\b)+/g, "AND").trim();
|
|
1256
|
+
if (!rest)
|
|
1257
|
+
throw new CliError("validation_error", "give words to find besides date:, project:, tag: and topic:");
|
|
1258
|
+
return { query: rest, request: next };
|
|
1259
|
+
}, "liftMeetingFields");
|
|
1260
|
+
var parseMeetingQuery = /* @__PURE__ */ __name((query) => validateQuery(parseLucene(query, { defaultField: "text", proximity: true, ...context }), MEETING_HIT_QUERY, context), "parseMeetingQuery");
|
|
1261
|
+
var meetingWordsQuery = /* @__PURE__ */ __name((text9) => {
|
|
1262
|
+
const found = text9.match(/[\p{L}\p{N}\p{M}]+/gu) ?? [];
|
|
1263
|
+
const span = { start: 0, end: text9.length };
|
|
1264
|
+
const clauses = found.map((value) => ({
|
|
1265
|
+
occur: "must",
|
|
1266
|
+
node: { kind: "predicate", field: "text", operator: "term", value, span }
|
|
1267
|
+
}));
|
|
1268
|
+
const root = clauses.length === 1 && clauses[0] ? clauses[0].node : { kind: "boolean", clauses, span };
|
|
1269
|
+
return { version: 1, language: "lucene-v1", root };
|
|
1270
|
+
}, "meetingWordsQuery");
|
|
1271
|
+
|
|
1272
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/ingest.js
|
|
1273
|
+
var contentHash = /* @__PURE__ */ __name(async (text9) => {
|
|
1274
|
+
const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text9));
|
|
1275
|
+
return Array.from(new Uint8Array(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1276
|
+
}, "contentHash");
|
|
1277
|
+
var speakerPosition = /* @__PURE__ */ __name((name, participants) => {
|
|
1278
|
+
if (name === null)
|
|
1279
|
+
return null;
|
|
1280
|
+
const matches = participants.flatMap((p, i) => p.displayName === name ? [i] : []);
|
|
1281
|
+
return matches.length === 1 ? matches[0] ?? null : null;
|
|
1282
|
+
}, "speakerPosition");
|
|
1283
|
+
var transcriptInput = /* @__PURE__ */ __name(async (lines, participants, source, hashText = JSON.stringify(lines), format = null) => ({
|
|
1284
|
+
source,
|
|
1285
|
+
format,
|
|
1286
|
+
language: null,
|
|
1287
|
+
contentHash: await contentHash(hashText),
|
|
1288
|
+
externalCreatedAt: null,
|
|
1289
|
+
metadata: null,
|
|
1290
|
+
deletedAt: null,
|
|
1291
|
+
rows: lines.map((line2, position) => ({
|
|
1292
|
+
position,
|
|
1293
|
+
startMs: line2.startMs,
|
|
1294
|
+
endMs: line2.endMs,
|
|
1295
|
+
speakerParticipantPosition: speakerPosition(line2.speaker, participants),
|
|
1296
|
+
speakerName: line2.speaker,
|
|
1297
|
+
text: line2.text,
|
|
1298
|
+
normalizedText: null,
|
|
1299
|
+
metadata: null
|
|
1300
|
+
}))
|
|
1301
|
+
}), "transcriptInput");
|
|
1302
|
+
var timestamp2 = /* @__PURE__ */ __name((value) => {
|
|
1303
|
+
const time = Date.parse(value);
|
|
1304
|
+
if (!Number.isFinite(time))
|
|
1305
|
+
throw new Error("Invalid meeting timestamp");
|
|
1306
|
+
return time;
|
|
1307
|
+
}, "timestamp");
|
|
1308
|
+
|
|
1309
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/transcript-text.js
|
|
1310
|
+
var TranscriptTextError = class extends Error {
|
|
1311
|
+
static {
|
|
1312
|
+
__name(this, "TranscriptTextError");
|
|
1313
|
+
}
|
|
1314
|
+
name = "TranscriptTextError";
|
|
1315
|
+
};
|
|
1316
|
+
var HEADER = {
|
|
1317
|
+
"\u0412\u0441\u0442\u0440\u0435\u0447\u0430: ": "title",
|
|
1318
|
+
"\u0414\u0430\u0442\u0430: ": "date",
|
|
1319
|
+
"Zoom ID: ": "meetingId",
|
|
1320
|
+
"\u0413\u043E\u0432\u043E\u0440\u044F\u0442: ": "speakers"
|
|
1321
|
+
};
|
|
1322
|
+
var LINE = /^\[(\d{2,}):([0-5]\d):([0-5]\d)\]\s*(?:([^:\n]{1,60}):\s*)?([\s\S]*)$/;
|
|
1323
|
+
var RULE = /^[—–-]{10,}[^\n]*(?:\n|$)/;
|
|
1324
|
+
var EMPTY = /* @__PURE__ */ new Set(["", "\u2014", "-"]);
|
|
1325
|
+
var parseTranscriptText = /* @__PURE__ */ __name((input) => {
|
|
1326
|
+
const text9 = input.replace(/^/, "").replace(/\r\n?/g, "\n");
|
|
1327
|
+
const header = { title: null, date: null, meetingId: null, speakers: [] };
|
|
1328
|
+
let sawHeader = false;
|
|
1329
|
+
for (const line2 of text9.split("\n")) {
|
|
1330
|
+
if (!line2.trim())
|
|
1331
|
+
break;
|
|
1332
|
+
for (const [prefix, key] of Object.entries(HEADER)) {
|
|
1333
|
+
if (!line2.startsWith(prefix))
|
|
1334
|
+
continue;
|
|
1335
|
+
sawHeader = true;
|
|
1336
|
+
const value = line2.slice(prefix.length).trim();
|
|
1337
|
+
if (key === "speakers")
|
|
1338
|
+
header.speakers = value.split(",").map((name) => name.trim()).filter((name) => !EMPTY.has(name));
|
|
1339
|
+
else
|
|
1340
|
+
header[key] = EMPTY.has(value) ? null : value;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
if (!sawHeader)
|
|
1344
|
+
throw new TranscriptTextError('a text transcript starts with a header such as "\u0412\u0441\u0442\u0440\u0435\u0447\u0430: \u2026"');
|
|
1345
|
+
const found = [];
|
|
1346
|
+
for (const block of text9.split(/\n\s*\n/)) {
|
|
1347
|
+
const match = LINE.exec(block.trim().replace(RULE, ""));
|
|
1348
|
+
if (!match)
|
|
1349
|
+
continue;
|
|
1350
|
+
const [, hours = "0", minutes = "0", seconds = "0", speaker, said = ""] = match;
|
|
1351
|
+
found.push({
|
|
1352
|
+
startMs: ((Number(hours) * 60 + Number(minutes)) * 60 + Number(seconds)) * 1e3,
|
|
1353
|
+
speaker: speaker?.trim() || null,
|
|
1354
|
+
text: said.trim()
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
const lines = found.map((line2, at) => ({
|
|
1358
|
+
...line2,
|
|
1359
|
+
endMs: Math.max(line2.startMs, found[at + 1]?.startMs ?? line2.startMs)
|
|
1360
|
+
}));
|
|
1361
|
+
return { header, lines };
|
|
1362
|
+
}, "parseTranscriptText");
|
|
1363
|
+
|
|
1364
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/vtt.js
|
|
1365
|
+
var VttError = class extends Error {
|
|
1366
|
+
static {
|
|
1367
|
+
__name(this, "VttError");
|
|
1368
|
+
}
|
|
1369
|
+
name = "VttError";
|
|
1370
|
+
};
|
|
1371
|
+
var TIMESTAMP = /^(?:(\d+):)?([0-5]\d):([0-5]\d)\.(\d{3})$/;
|
|
1372
|
+
var SKIPPED = /^(NOTE|STYLE|REGION)(\s|$)/;
|
|
1373
|
+
var millis = /* @__PURE__ */ __name((stamp, lineNo) => {
|
|
1374
|
+
const match = TIMESTAMP.exec(stamp);
|
|
1375
|
+
if (!match)
|
|
1376
|
+
throw new VttError(`line ${lineNo}: "${stamp}" is not a WebVTT timestamp`);
|
|
1377
|
+
const [, hours = "0", minutes = "0", seconds = "0", ms = "0"] = match;
|
|
1378
|
+
return ((Number(hours) * 60 + Number(minutes)) * 60 + Number(seconds)) * 1e3 + Number(ms);
|
|
1379
|
+
}, "millis");
|
|
1380
|
+
var splitSpeaker = /* @__PURE__ */ __name((text9) => {
|
|
1381
|
+
const firstLine = text9.split("\n", 1)[0] ?? "";
|
|
1382
|
+
const at = firstLine.indexOf(": ");
|
|
1383
|
+
if (at <= 0)
|
|
1384
|
+
return { speaker: null, text: text9 };
|
|
1385
|
+
return { speaker: firstLine.slice(0, at).trim(), text: text9.slice(at + 2) };
|
|
1386
|
+
}, "splitSpeaker");
|
|
1387
|
+
var parseVtt = /* @__PURE__ */ __name((input) => {
|
|
1388
|
+
const lines = input.replace(/^/, "").split(/\r\n|\r|\n/);
|
|
1389
|
+
if (!/^WEBVTT([ \t].*)?$/.test(lines[0] ?? ""))
|
|
1390
|
+
throw new VttError('line 1: a WebVTT file starts with "WEBVTT"');
|
|
1391
|
+
const cues = [];
|
|
1392
|
+
let i = lines.findIndex((line2) => line2.trim() === "");
|
|
1393
|
+
if (i < 0)
|
|
1394
|
+
return [];
|
|
1395
|
+
while (i < lines.length) {
|
|
1396
|
+
while (i < lines.length && lines[i]?.trim() === "")
|
|
1397
|
+
i++;
|
|
1398
|
+
const start = i;
|
|
1399
|
+
while (i < lines.length && lines[i]?.trim() !== "")
|
|
1400
|
+
i++;
|
|
1401
|
+
const block = lines.slice(start, i);
|
|
1402
|
+
if (block.length === 0 || SKIPPED.test(block[0] ?? ""))
|
|
1403
|
+
continue;
|
|
1404
|
+
const timingAt = block.findIndex((line2) => line2.includes("-->"));
|
|
1405
|
+
if (timingAt < 0 || timingAt > 1)
|
|
1406
|
+
throw new VttError(`line ${start + 1}: a cue has no timing line`);
|
|
1407
|
+
const lineNo = start + timingAt + 1;
|
|
1408
|
+
const [from = "", rest = ""] = (block[timingAt] ?? "").split("-->");
|
|
1409
|
+
const to = rest.trim().split(/\s+/)[0] ?? "";
|
|
1410
|
+
const text9 = block.slice(timingAt + 1).join("\n").trim();
|
|
1411
|
+
cues.push({ startMs: millis(from.trim(), lineNo), endMs: millis(to, lineNo), ...splitSpeaker(text9) });
|
|
1412
|
+
}
|
|
1413
|
+
return cues;
|
|
1414
|
+
}, "parseVtt");
|
|
1415
|
+
|
|
1416
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/import.js
|
|
1417
|
+
var importFiles = /* @__PURE__ */ __name(async (files, store, now = Date.now()) => {
|
|
1418
|
+
const report = { meetings: 0, participants: 0, transcriptRows: 0, summaries: 0, warnings: [] };
|
|
1419
|
+
for (const file of files) {
|
|
1420
|
+
try {
|
|
1421
|
+
const format = file.format ?? "vtt";
|
|
1422
|
+
const lines = format === "text" ? parseTranscriptText(file.content).lines : parseVtt(file.content);
|
|
1423
|
+
const participants = file.participants ?? [];
|
|
1424
|
+
const details = await store.saveMeeting({
|
|
1425
|
+
meeting: file.meeting,
|
|
1426
|
+
participants: file.participants,
|
|
1427
|
+
transcripts: [await transcriptInput(lines, participants, file.source ?? "file", file.content, format)],
|
|
1428
|
+
now,
|
|
1429
|
+
fromFile: true
|
|
1430
|
+
});
|
|
1431
|
+
await linkEvent(store, details, now);
|
|
1432
|
+
report.meetings++;
|
|
1433
|
+
report.participants += participants.length;
|
|
1434
|
+
report.transcriptRows += lines.length;
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
report.warnings.push({
|
|
1437
|
+
externalId: file.meeting.externalId,
|
|
1438
|
+
message: error instanceof Error ? error.message : "Meeting import failed"
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
const zones = new Set(files.map((file) => file.meeting.timezone).filter((zone2) => zone2 !== null && zone2 !== void 0));
|
|
1443
|
+
const [zone] = zones;
|
|
1444
|
+
if (zones.size === 1 && zone)
|
|
1445
|
+
report.timezone = zone;
|
|
1446
|
+
return report;
|
|
1447
|
+
}, "importFiles");
|
|
1448
|
+
|
|
1449
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/links.js
|
|
1450
|
+
var CHAT_MESSAGES_READ = 1e5;
|
|
1451
|
+
|
|
1452
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/passage.js
|
|
1453
|
+
var meetingHitContextLimits = /* @__PURE__ */ __name((options = {}) => {
|
|
1454
|
+
const { before = 3, after = 3, bytes = 65536, max_read_bytes = 4194304, expected_fingerprint } = options;
|
|
1455
|
+
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)))
|
|
1456
|
+
throw new CliError("validation_error", "context takes 0\u2013999 surrounding cues, 2\u20134194304 output bytes and a bounded read budget");
|
|
1457
|
+
return { before, after, bytes, max_read_bytes };
|
|
1458
|
+
}, "meetingHitContextLimits");
|
|
1459
|
+
var validateMeetingPassage = /* @__PURE__ */ __name((reference2, options) => {
|
|
1460
|
+
meetingHitContextLimits(options);
|
|
1461
|
+
if (typeof reference2 !== "string" || !reference2.trim() || reference2.length > 200 || options.format !== void 0 && !["json", "text", "markdown"].includes(options.format))
|
|
1462
|
+
throw new CliError("validation_error", "choose a cue reference and json, text or markdown output");
|
|
1463
|
+
}, "validateMeetingPassage");
|
|
1464
|
+
|
|
1465
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/preparation-context.js
|
|
1466
|
+
var validateMeetingPreparationContext = /* @__PURE__ */ __name((original) => {
|
|
1467
|
+
if (!original || typeof original !== "object" || Array.isArray(original))
|
|
1468
|
+
throw new CliError("validation_error", "meeting preparation context is required");
|
|
1469
|
+
const input = { ...original };
|
|
1470
|
+
for (const key of Object.keys(input))
|
|
1471
|
+
if (!["accountId", "meetingId", "seriesId", "updatedAt", "limit", "maxReadBytes", "signal"].includes(key))
|
|
1472
|
+
throw new CliError("validation_error", `unknown preparation context field: ${key}`);
|
|
1473
|
+
if (input.signal !== void 0 && !(input.signal instanceof AbortSignal))
|
|
1474
|
+
throw new CliError("validation_error", "signal must be an AbortSignal");
|
|
1475
|
+
input.signal?.throwIfAborted();
|
|
1476
|
+
for (const key of ["accountId", "meetingId", "seriesId"])
|
|
1477
|
+
if (!Number.isSafeInteger(input[key]) || input[key] <= 0)
|
|
1478
|
+
throw new CliError("validation_error", `${key} must be a positive safe integer`);
|
|
1479
|
+
if (!Number.isSafeInteger(input.updatedAt) || Math.abs(input.updatedAt) > 864e13)
|
|
1480
|
+
throw new CliError("validation_error", "updatedAt must be an absolute timestamp");
|
|
1481
|
+
const limit = input.limit === void 0 ? 20 : input.limit;
|
|
1482
|
+
const maxReadBytes = input.maxReadBytes === void 0 ? 262144 : input.maxReadBytes;
|
|
1483
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
1484
|
+
throw new CliError("validation_error", "limit must be an integer from 1 to 100");
|
|
1485
|
+
if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4194304)
|
|
1486
|
+
throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
|
|
1487
|
+
return { ...input, limit, maxReadBytes };
|
|
1488
|
+
}, "validateMeetingPreparationContext");
|
|
1489
|
+
|
|
1490
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/project-evidence-answer.js
|
|
1491
|
+
var count3 = pipe(number(), integer(), minValue(0));
|
|
1492
|
+
var id2 = pipe(string(), minLength(1));
|
|
1493
|
+
var meetingProjectEvidence = strictObject({
|
|
1494
|
+
schema_version: literal(1),
|
|
1495
|
+
kind: literal("meeting_project_evidence"),
|
|
1496
|
+
account_id: id2,
|
|
1497
|
+
query: string(),
|
|
1498
|
+
project: strictObject({ id: id2, name: string(), key: nullable(string()) }),
|
|
1499
|
+
term: strictObject({
|
|
1500
|
+
name: string(),
|
|
1501
|
+
kind: picklist(["canonical", "key", "alias"]),
|
|
1502
|
+
alias_id: optional(id2)
|
|
1503
|
+
}),
|
|
1504
|
+
hits: array(meetingHit),
|
|
1505
|
+
association: literal("unconfirmed-word-evidence"),
|
|
1506
|
+
vocabulary_fingerprint: id2,
|
|
1507
|
+
selection: strictObject({
|
|
1508
|
+
meeting_id: optional(id2),
|
|
1509
|
+
identity_id: optional(id2),
|
|
1510
|
+
person_id: optional(id2),
|
|
1511
|
+
tag_id: optional(id2),
|
|
1512
|
+
event_id: optional(id2),
|
|
1513
|
+
series_id: optional(id2),
|
|
1514
|
+
since: optional(isoTime),
|
|
1515
|
+
until: optional(isoTime)
|
|
1516
|
+
}),
|
|
1517
|
+
limits: strictObject({ limit: count3, max_read_bytes: count3, max_vocabulary_read_bytes: count3, max_terms: count3 }),
|
|
1518
|
+
page: pageSchema,
|
|
1519
|
+
coverage: strictObject({
|
|
1520
|
+
archive_completeness: literal("unknown"),
|
|
1521
|
+
current_revisions: literal(true),
|
|
1522
|
+
indexing: picklist(["ready", "pending"]),
|
|
1523
|
+
index_completeness: literal("unknown"),
|
|
1524
|
+
term_index: count3,
|
|
1525
|
+
terms_total: count3,
|
|
1526
|
+
remaining_terms: count3,
|
|
1527
|
+
duplicates: literal("may-repeat-between-terms")
|
|
1528
|
+
})
|
|
1529
|
+
});
|
|
1530
|
+
var PAGE_NEXT3 = STEPS.find((step) => step.id === "page.next");
|
|
1531
|
+
var meetingProjectEvidenceAnswer = /* @__PURE__ */ __name((page, prepared, command = "meetings projects evidence") => {
|
|
1532
|
+
const { options } = prepared;
|
|
1533
|
+
const selection = {};
|
|
1534
|
+
for (const [field, value] of [
|
|
1535
|
+
["meeting_id", options.meetingId],
|
|
1536
|
+
["identity_id", options.participantIdentityId],
|
|
1537
|
+
["person_id", options.personId],
|
|
1538
|
+
["tag_id", options.tagId],
|
|
1539
|
+
["event_id", options.eventId],
|
|
1540
|
+
["series_id", options.meetingSeriesId]
|
|
1541
|
+
])
|
|
1542
|
+
if (value !== void 0)
|
|
1543
|
+
selection[field] = String(value);
|
|
1544
|
+
if (options.since !== void 0)
|
|
1545
|
+
selection.since = new Date(options.since).toISOString();
|
|
1546
|
+
if (options.until !== void 0)
|
|
1547
|
+
selection.until = new Date(options.until).toISOString();
|
|
1548
|
+
const cursor = page.nextCursor ?? void 0;
|
|
1549
|
+
if (page.hasMore !== (cursor !== void 0))
|
|
1550
|
+
throw new CliError("invalid_response", "project evidence continuation is inconsistent");
|
|
1551
|
+
const item = {
|
|
1552
|
+
schema_version: 1,
|
|
1553
|
+
kind: "meeting_project_evidence",
|
|
1554
|
+
account_id: String(page.accountId),
|
|
1555
|
+
query: page.query,
|
|
1556
|
+
project: page.project,
|
|
1557
|
+
term: {
|
|
1558
|
+
name: page.term.name,
|
|
1559
|
+
kind: page.term.kind,
|
|
1560
|
+
...page.term.aliasId === void 0 ? {} : { alias_id: page.term.aliasId }
|
|
1561
|
+
},
|
|
1562
|
+
hits: page.hits.map(meetingHitItem),
|
|
1563
|
+
association: page.association,
|
|
1564
|
+
vocabulary_fingerprint: page.vocabularyFingerprint,
|
|
1565
|
+
selection,
|
|
1566
|
+
limits: {
|
|
1567
|
+
limit: page.limits.limit,
|
|
1568
|
+
max_read_bytes: page.limits.maxReadBytes,
|
|
1569
|
+
max_vocabulary_read_bytes: page.limits.maxVocabularyReadBytes,
|
|
1570
|
+
max_terms: page.limits.maxTerms
|
|
1571
|
+
},
|
|
1572
|
+
page: {
|
|
1573
|
+
mode: "cursor",
|
|
1574
|
+
limit: page.limits.limit,
|
|
1575
|
+
has_more: page.hasMore,
|
|
1576
|
+
...cursor === void 0 ? {} : { next_cursor: cursor }
|
|
1577
|
+
},
|
|
1578
|
+
coverage: {
|
|
1579
|
+
archive_completeness: page.coverage.archiveCompleteness,
|
|
1580
|
+
current_revisions: page.coverage.currentRevisions,
|
|
1581
|
+
indexing: page.coverage.indexing,
|
|
1582
|
+
index_completeness: page.coverage.indexCompleteness,
|
|
1583
|
+
term_index: page.coverage.termIndex,
|
|
1584
|
+
terms_total: page.coverage.termsTotal,
|
|
1585
|
+
remaining_terms: page.coverage.remainingTerms,
|
|
1586
|
+
duplicates: page.coverage.duplicates
|
|
1587
|
+
}
|
|
1588
|
+
};
|
|
1589
|
+
if (!safeParse(meetingProjectEvidence, item).success)
|
|
1590
|
+
throw new CliError("invalid_response", "project evidence does not match its answer contract");
|
|
1591
|
+
return {
|
|
1592
|
+
item,
|
|
1593
|
+
...cursor === void 0 ? {} : {
|
|
1594
|
+
next: [
|
|
1595
|
+
stepOf(PAGE_NEXT3, {
|
|
1596
|
+
command,
|
|
1597
|
+
args: {
|
|
1598
|
+
project: prepared.project,
|
|
1599
|
+
query: prepared.query,
|
|
1600
|
+
cursor,
|
|
1601
|
+
limit: page.limits.limit,
|
|
1602
|
+
max_read_bytes: page.limits.maxReadBytes
|
|
1603
|
+
},
|
|
1604
|
+
values: { shown: page.hits.length }
|
|
1605
|
+
})
|
|
1606
|
+
]
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
}, "meetingProjectEvidenceAnswer");
|
|
1610
|
+
|
|
1611
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/search-validation.js
|
|
1612
|
+
var validateMeetingHitSearch = /* @__PURE__ */ __name((query, options = {}) => {
|
|
1613
|
+
const integer5 = /* @__PURE__ */ __name((value, low, high) => Number.isSafeInteger(value) && value >= low && value <= high, "integer");
|
|
1614
|
+
if (typeof query !== "string" || !query.trim() || query.includes("\0") || new TextEncoder().encode(query).byteLength > 65536 || !integer5(options.limit ?? 100, 1, 1e3) || !integer5(options.maxReadBytes ?? 4194304, 1, 67108864) || [
|
|
1615
|
+
options.meetingId,
|
|
1616
|
+
options.participantIdentityId,
|
|
1617
|
+
options.personId,
|
|
1618
|
+
options.projectId,
|
|
1619
|
+
options.tagId,
|
|
1620
|
+
options.eventId,
|
|
1621
|
+
options.meetingSeriesId
|
|
1622
|
+
].some((value) => value !== void 0 && !integer5(value, 1, Number.MAX_SAFE_INTEGER)) || [options.since, options.until].some((value) => value !== void 0 && !integer5(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)))
|
|
1623
|
+
throw new CliError("validation_error", "invalid bounded meeting search query, cursor or limits");
|
|
1624
|
+
for (const name of [options.project, options.tag, options.topic])
|
|
1625
|
+
if (name !== void 0 && (typeof name !== "string" || !name.trim() || name.length > 200 || /[\p{Cc}\p{Cf}]/u.test(name)))
|
|
1626
|
+
throw new CliError("validation_error", "a meeting vocabulary name takes 1\u2013200 characters without control characters");
|
|
1627
|
+
if (options.project !== void 0 && options.projectId !== void 0 || [options.tag, options.topic, options.tagId].filter((value) => value !== void 0).length > 1)
|
|
1628
|
+
throw new CliError("validation_error", "choose one project selector and one tag or topic selector");
|
|
1629
|
+
}, "validateMeetingHitSearch");
|
|
1630
|
+
|
|
1631
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/project-evidence-query.js
|
|
1632
|
+
var ids = {
|
|
1633
|
+
meeting_id: "meetingId",
|
|
1634
|
+
identity_id: "participantIdentityId",
|
|
1635
|
+
person_id: "personId",
|
|
1636
|
+
tag_id: "tagId",
|
|
1637
|
+
event_id: "eventId",
|
|
1638
|
+
series_id: "meetingSeriesId"
|
|
1639
|
+
};
|
|
1640
|
+
var context2 = {
|
|
1641
|
+
command: "meetings projects evidence",
|
|
1642
|
+
guide: "https://github.com/WireCatLabs/cli-core/blob/main/docs/search/query-language.md"
|
|
1643
|
+
};
|
|
1644
|
+
var MEETING_PROJECT_EVIDENCE_QUERY = defineQuery({
|
|
1645
|
+
entity: "meeting_project_evidence",
|
|
1646
|
+
backend: "sql",
|
|
1647
|
+
fields: [
|
|
1648
|
+
...Object.keys(ids).map((name) => ({
|
|
1649
|
+
name,
|
|
1650
|
+
type: "num",
|
|
1651
|
+
operators: ["term"],
|
|
1652
|
+
example: `${name}:12`,
|
|
1653
|
+
placement: "and",
|
|
1654
|
+
relation: "meetings selected by this stored ID; identity selects participants, not speakers"
|
|
1655
|
+
})),
|
|
1656
|
+
{
|
|
1657
|
+
name: "started_at",
|
|
1658
|
+
type: "time",
|
|
1659
|
+
operators: ["term", "phrase", "range"],
|
|
1660
|
+
example: "started_at:[2026-10-01 TO 2026-10-31]",
|
|
1661
|
+
placement: "and",
|
|
1662
|
+
relation: "the meeting start time in UTC"
|
|
1663
|
+
}
|
|
1664
|
+
]
|
|
1665
|
+
});
|
|
1666
|
+
var requestKeys = /* @__PURE__ */ new Set(["query", "limit", "cursor", "maxReadBytes", "signal"]);
|
|
1667
|
+
var prepareMeetingProjectEvidence = /* @__PURE__ */ __name((project, request = {}, now = Date.now()) => {
|
|
1668
|
+
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")
|
|
1669
|
+
throw new CliError("validation_error", "expected an existing project and bounded evidence arguments");
|
|
1670
|
+
if (request.query !== void 0 && new TextEncoder().encode(request.query).byteLength > 8192 || [request.limit, request.maxReadBytes].some((value) => value !== void 0 && typeof value !== "number"))
|
|
1671
|
+
throw new CliError("validation_error", "invalid project evidence query or budget");
|
|
1672
|
+
request.signal?.throwIfAborted();
|
|
1673
|
+
const options = {
|
|
1674
|
+
limit: request.limit ?? 100,
|
|
1675
|
+
maxReadBytes: request.maxReadBytes ?? 4194304,
|
|
1676
|
+
...request.cursor === void 0 ? {} : { cursor: request.cursor },
|
|
1677
|
+
...request.signal === void 0 ? {} : { signal: request.signal }
|
|
1678
|
+
};
|
|
1679
|
+
const terms = /* @__PURE__ */ new Map();
|
|
1680
|
+
if (request.query?.trim()) {
|
|
1681
|
+
const ast = parseLucene(request.query, { defaultField: "none", ...context2 });
|
|
1682
|
+
validateQuery(ast, MEETING_PROJECT_EVIDENCE_QUERY, context2);
|
|
1683
|
+
const add = /* @__PURE__ */ __name((node) => {
|
|
1684
|
+
if (terms.has(node.field))
|
|
1685
|
+
queryError("query.unsupported-placement", node.span, "each field only once", context2);
|
|
1686
|
+
terms.set(node.field, node);
|
|
1687
|
+
}, "add");
|
|
1688
|
+
if (ast.root.kind === "predicate")
|
|
1689
|
+
add(ast.root);
|
|
1690
|
+
else
|
|
1691
|
+
for (const clause of ast.root.clauses) {
|
|
1692
|
+
if (clause.occur !== "must" || clause.node.kind !== "predicate")
|
|
1693
|
+
queryError("query.unsupported-placement", clause.node.span, "field:value terms joined by AND", context2);
|
|
1694
|
+
add(clause.node);
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
const frozen = [];
|
|
1698
|
+
for (const [field, key] of Object.entries(ids)) {
|
|
1699
|
+
const term2 = terms.get(field);
|
|
1700
|
+
if (!term2)
|
|
1701
|
+
continue;
|
|
1702
|
+
if (term2.operator !== "term" || !/^[1-9]\d*$/.test(term2.value) || !Number.isSafeInteger(Number(term2.value)))
|
|
1703
|
+
queryError("query.unsupported-operator", term2.span, "one positive safe integer ID", context2);
|
|
1704
|
+
options[key] = Number(term2.value);
|
|
1705
|
+
frozen.push(`${field}:${term2.value}`);
|
|
1706
|
+
}
|
|
1707
|
+
const term = terms.get("started_at");
|
|
1708
|
+
if (term) {
|
|
1709
|
+
const range = dateRange(term.value, term.operator === "range" ? term.upper ?? "*" : term.value, term.lower_inclusive !== false, term.upper_inclusive !== false, "UTC", term.span, now);
|
|
1710
|
+
if (range.lower !== void 0)
|
|
1711
|
+
options.since = range.lower + (range.lower_inclusive ? 0 : 1);
|
|
1712
|
+
if (range.upper !== void 0)
|
|
1713
|
+
options.until = range.upper - (range.upper_inclusive ? 0 : 1);
|
|
1714
|
+
frozen.push(`started_at:[${options.since === void 0 ? "*" : `"${new Date(options.since).toISOString()}"`} TO ${options.until === void 0 ? "*" : `"${new Date(options.until).toISOString()}"`}]`);
|
|
1715
|
+
}
|
|
1716
|
+
validateMeetingHitSearch(project, options);
|
|
1717
|
+
if (options.cursor !== void 0 && (typeof options.cursor !== "string" || !/^[A-Za-z0-9_-]{1,4096}$/.test(options.cursor)))
|
|
1718
|
+
throw new CliError("validation_error", "invalid project evidence cursor");
|
|
1719
|
+
return { project: project.trim(), options, query: frozen.join(" AND ") };
|
|
1720
|
+
}, "prepareMeetingProjectEvidence");
|
|
1721
|
+
|
|
1722
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/project-evidence.js
|
|
1723
|
+
var readMeetingProjectEvidence = /* @__PURE__ */ __name(async (read, project, request = {}, now = Date.now()) => {
|
|
1724
|
+
const prepared = prepareMeetingProjectEvidence(project, request, now);
|
|
1725
|
+
const page = await read(prepared.project, prepared.options);
|
|
1726
|
+
prepared.options.signal?.throwIfAborted();
|
|
1727
|
+
return meetingProjectEvidenceAnswer(page, prepared);
|
|
1728
|
+
}, "readMeetingProjectEvidence");
|
|
1729
|
+
|
|
1730
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/pull.js
|
|
1731
|
+
var participantInput = /* @__PURE__ */ __name((p, provider, occurrenceId2, position, accountId) => {
|
|
1732
|
+
const { identityExternalId, ...fields3 } = p;
|
|
1733
|
+
const externalId = identityExternalId ?? (p.email ? `email:${p.email.toLowerCase()}` : p.externalId) ?? `name:${p.displayName ?? "unknown"}@${accountId}/${occurrenceId2}:${position}`;
|
|
1734
|
+
return {
|
|
1735
|
+
...fields3,
|
|
1736
|
+
identity: {
|
|
1737
|
+
provider,
|
|
1738
|
+
externalId,
|
|
1739
|
+
name: p.displayName,
|
|
1740
|
+
metadata: p.metadata,
|
|
1741
|
+
associatePerson: Boolean(identityExternalId?.trim() || p.email?.trim() || p.externalId?.trim())
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1744
|
+
}, "participantInput");
|
|
1745
|
+
var pull = /* @__PURE__ */ __name(async (source, store, options) => {
|
|
1746
|
+
const now = options.now ?? Date.now();
|
|
1747
|
+
const lookbackMs = options.lookbackMs ?? 0;
|
|
1748
|
+
if (!Number.isSafeInteger(lookbackMs) || lookbackMs < 0 || lookbackMs > 31 * 864e5)
|
|
1749
|
+
throw new Error("lookbackMs must be an integer from 0 through 31 days");
|
|
1750
|
+
const since = options.since ?? await store.cursor(options.accountId) ?? new Date(now - 30 * 864e5).toISOString();
|
|
1751
|
+
timestamp2(since);
|
|
1752
|
+
const report = { meetings: 0, participants: 0, transcriptRows: 0, summaries: 0, warnings: [] };
|
|
1753
|
+
let failed = false;
|
|
1754
|
+
const from = timestamp2(since) - lookbackMs;
|
|
1755
|
+
const meetings = await source.meetings(lookbackMs === 0 ? since : new Date(from).toISOString());
|
|
1756
|
+
for (const m of meetings) {
|
|
1757
|
+
const id4 = m.occurrence.id;
|
|
1758
|
+
const read = /* @__PURE__ */ __name(async (part, call) => {
|
|
1759
|
+
try {
|
|
1760
|
+
return await call();
|
|
1761
|
+
} catch (error) {
|
|
1762
|
+
failed = true;
|
|
1763
|
+
const message = error instanceof Error ? error.message : "could not be read";
|
|
1764
|
+
report.warnings.push({ externalId: id4, message: `${part}: ${message}` });
|
|
1765
|
+
return void 0;
|
|
1766
|
+
}
|
|
1767
|
+
}, "read");
|
|
1768
|
+
try {
|
|
1769
|
+
const sourceParticipants = await read("participants", () => source.participants(id4));
|
|
1770
|
+
const participants = (sourceParticipants ?? []).map((p, i) => participantInput(p, source.provider, id4, i, options.accountId));
|
|
1771
|
+
const names = /* @__PURE__ */ new Map();
|
|
1772
|
+
for (const p of participants)
|
|
1773
|
+
if (p.displayName !== null) {
|
|
1774
|
+
const identities = names.get(p.displayName) ?? /* @__PURE__ */ new Set();
|
|
1775
|
+
identities.add(p.identity.externalId);
|
|
1776
|
+
names.set(p.displayName, identities);
|
|
1777
|
+
}
|
|
1778
|
+
if ([...names.values()].some((ids2) => ids2.size > 1))
|
|
1779
|
+
report.warnings.push({ externalId: id4, message: "Participant names are ambiguous" });
|
|
1780
|
+
const lines = await read("transcript", () => source.transcript(id4));
|
|
1781
|
+
const chat = await read("chat", () => source.chat(id4));
|
|
1782
|
+
const summary = await read("summary", () => source.summary(id4));
|
|
1783
|
+
const attachments = await read("files", () => source.files(id4));
|
|
1784
|
+
const startedAt = timestamp2(m.occurrence.startedAt);
|
|
1785
|
+
const endedAt = m.occurrence.endedAt === null ? null : timestamp2(m.occurrence.endedAt);
|
|
1786
|
+
if (endedAt !== null && endedAt < startedAt)
|
|
1787
|
+
throw new Error("Meeting ends before it starts");
|
|
1788
|
+
const meeting2 = {
|
|
1789
|
+
accountId: options.accountId,
|
|
1790
|
+
externalId: id4,
|
|
1791
|
+
title: m.occurrence.title,
|
|
1792
|
+
description: m.description ?? null,
|
|
1793
|
+
location: m.location ?? null,
|
|
1794
|
+
joinUrl: m.joinUrl ?? m.series?.joinUrl ?? null,
|
|
1795
|
+
startedAt,
|
|
1796
|
+
endedAt,
|
|
1797
|
+
durationMs: endedAt === null ? null : endedAt - startedAt,
|
|
1798
|
+
timezone: m.timezone ?? null,
|
|
1799
|
+
hostIdentityId: null,
|
|
1800
|
+
...sourceParticipants === void 0 ? {} : { participantsCount: sourceParticipants?.length ?? null },
|
|
1801
|
+
metadata: m.metadata ?? null,
|
|
1802
|
+
deletedAt: null
|
|
1803
|
+
};
|
|
1804
|
+
if (m.series)
|
|
1805
|
+
meeting2.series = {
|
|
1806
|
+
externalId: m.series.id,
|
|
1807
|
+
title: m.series.title,
|
|
1808
|
+
description: null,
|
|
1809
|
+
kind: m.series.kind ?? null,
|
|
1810
|
+
recurrence: m.series.recurrence ?? null,
|
|
1811
|
+
hostIdentityId: null,
|
|
1812
|
+
joinUrl: m.series.joinUrl ?? null,
|
|
1813
|
+
metadata: null,
|
|
1814
|
+
deletedAt: null
|
|
1815
|
+
};
|
|
1816
|
+
const linked = sourceParticipants !== void 0;
|
|
1817
|
+
const format = source.transcriptFormat ?? null;
|
|
1818
|
+
const transcripts = lines && linked ? [await transcriptInput(lines, participants, source.name, void 0, format)] : void 0;
|
|
1819
|
+
const details = await store.saveMeeting({
|
|
1820
|
+
meeting: meeting2,
|
|
1821
|
+
participants: sourceParticipants ? participants : void 0,
|
|
1822
|
+
transcripts,
|
|
1823
|
+
chat: chat?.map((line2) => ({
|
|
1824
|
+
externalId: null,
|
|
1825
|
+
sentAt: timestamp2(line2.sentAt),
|
|
1826
|
+
senderParticipantPosition: speakerPosition(line2.sender, participants),
|
|
1827
|
+
senderName: line2.sender,
|
|
1828
|
+
recipient: null,
|
|
1829
|
+
text: line2.text,
|
|
1830
|
+
normalizedText: null,
|
|
1831
|
+
metadata: null
|
|
1832
|
+
})),
|
|
1833
|
+
summaries: summary ? [
|
|
1834
|
+
{
|
|
1835
|
+
...summary,
|
|
1836
|
+
source: summary.source ?? source.name,
|
|
1837
|
+
content: summary.content ?? null,
|
|
1838
|
+
docUrl: summary.docUrl ?? null,
|
|
1839
|
+
externalCreatedAt: summary.externalCreatedAt ?? null,
|
|
1840
|
+
externalUpdatedAt: summary.externalUpdatedAt ?? null,
|
|
1841
|
+
metadata: summary.metadata ?? null
|
|
1842
|
+
}
|
|
1843
|
+
] : void 0,
|
|
1844
|
+
attachments: attachments ?? void 0,
|
|
1845
|
+
now
|
|
1846
|
+
});
|
|
1847
|
+
if (lines && !linked && !details.transcripts.some((t) => t.transcript.source === source.name && t.transcript.supersededAt === null))
|
|
1848
|
+
await store.saveMeeting({
|
|
1849
|
+
meeting: meeting2,
|
|
1850
|
+
transcripts: [await transcriptInput(lines, [], source.name, `${JSON.stringify(lines)}
|
|
1851
|
+
unlinked`, format)],
|
|
1852
|
+
now
|
|
1853
|
+
});
|
|
1854
|
+
await linkEvent(store, details, now);
|
|
1855
|
+
report.meetings++;
|
|
1856
|
+
report.participants += participants.length;
|
|
1857
|
+
report.transcriptRows += lines?.length ?? 0;
|
|
1858
|
+
report.summaries += summary ? 1 : 0;
|
|
1859
|
+
} catch (error) {
|
|
1860
|
+
failed = true;
|
|
1861
|
+
report.warnings.push({ externalId: id4, message: error instanceof Error ? error.message : "Meeting pull failed" });
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
if (!failed)
|
|
1865
|
+
await store.setCursor(options.accountId, new Date(now).toISOString(), now);
|
|
1866
|
+
return report;
|
|
1867
|
+
}, "pull");
|
|
1868
|
+
|
|
1869
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/read-answers.js
|
|
1870
|
+
var text5 = string();
|
|
1871
|
+
var count4 = pipe(number(), integer(), minValue(0));
|
|
1872
|
+
var id3 = pipe(number(), integer(), minValue(1));
|
|
1873
|
+
var iso3 = /* @__PURE__ */ __name((ms) => ms === null ? null : new Date(ms).toISOString(), "iso");
|
|
1874
|
+
var meetingRef2 = /* @__PURE__ */ __name((accountId, meetingId) => formatMeetingReference({ type: "meeting", accountId, meetingId }), "meetingRef");
|
|
1875
|
+
var meetingReview = strictObject({
|
|
1876
|
+
ref: reference,
|
|
1877
|
+
id: pipe(string(), minLength(1)),
|
|
1878
|
+
title: nullable(text5),
|
|
1879
|
+
started_at: nullable(isoTime),
|
|
1880
|
+
duration_ms: nullable(count4),
|
|
1881
|
+
participants_count: nullable(count4),
|
|
1882
|
+
projects: array(text5),
|
|
1883
|
+
/** Null when the meeting has no current transcript. */
|
|
1884
|
+
transcript: nullable(strictObject({ lines: count4, words: count4 })),
|
|
1885
|
+
/** The three who talked longest. */
|
|
1886
|
+
speakers: array(strictObject({ name: nullable(text5), talk_ms: count4 })),
|
|
1887
|
+
/** The newest stored summary; null when there is none. */
|
|
1888
|
+
summary: nullable(strictObject({
|
|
1889
|
+
source: text5,
|
|
1890
|
+
title: nullable(text5),
|
|
1891
|
+
overview: nullable(text5),
|
|
1892
|
+
next_steps: array(text5),
|
|
1893
|
+
url: nullable(text5)
|
|
1894
|
+
}))
|
|
1895
|
+
});
|
|
1896
|
+
var meetingReviewItem = /* @__PURE__ */ __name((one) => ({
|
|
1897
|
+
ref: meetingRef2(one.accountId, one.meetingId),
|
|
1898
|
+
id: String(one.meetingId),
|
|
1899
|
+
title: one.title,
|
|
1900
|
+
started_at: iso3(one.startedAt),
|
|
1901
|
+
duration_ms: one.durationMs,
|
|
1902
|
+
participants_count: one.participantsCount,
|
|
1903
|
+
projects: one.projects,
|
|
1904
|
+
transcript: one.transcript,
|
|
1905
|
+
speakers: one.speakers.map((speaker) => ({ name: speaker.name, talk_ms: speaker.talkMs })),
|
|
1906
|
+
summary: one.summary && {
|
|
1907
|
+
source: one.summary.source,
|
|
1908
|
+
title: one.summary.title,
|
|
1909
|
+
overview: one.summary.overview,
|
|
1910
|
+
next_steps: one.summary.nextSteps,
|
|
1911
|
+
url: one.summary.url
|
|
1912
|
+
}
|
|
1913
|
+
}), "meetingReviewItem");
|
|
1914
|
+
var meetingLink = strictObject({
|
|
1915
|
+
url: text5,
|
|
1916
|
+
domain: nullable(text5),
|
|
1917
|
+
/** The Google Docs, Sheets, Slides, Forms or Drive file it names. */
|
|
1918
|
+
document_id: nullable(text5),
|
|
1919
|
+
count: count4,
|
|
1920
|
+
first_at: isoTime,
|
|
1921
|
+
last_at: isoTime,
|
|
1922
|
+
senders: array(text5),
|
|
1923
|
+
meetings: array(strictObject({ ref: reference, title: nullable(text5) }))
|
|
1924
|
+
});
|
|
1925
|
+
var meetingLinkItem = /* @__PURE__ */ __name((link) => ({
|
|
1926
|
+
url: link.url,
|
|
1927
|
+
domain: link.domain,
|
|
1928
|
+
document_id: link.documentId,
|
|
1929
|
+
count: link.count,
|
|
1930
|
+
first_at: new Date(link.firstAt).toISOString(),
|
|
1931
|
+
last_at: new Date(link.lastAt).toISOString(),
|
|
1932
|
+
senders: link.senders,
|
|
1933
|
+
meetings: link.meetings.map((one) => ({ ref: meetingRef2(one.accountId, one.meetingId), title: one.title }))
|
|
1934
|
+
}), "meetingLinkItem");
|
|
1935
|
+
var meetingSpeaker = strictObject({
|
|
1936
|
+
/** `person:<id>`, `identity:<id>`, `name:<lowercased name>` or `unknown`. */
|
|
1937
|
+
key: text5,
|
|
1938
|
+
name: nullable(text5),
|
|
1939
|
+
person_id: nullable(id3),
|
|
1940
|
+
identity_id: nullable(id3),
|
|
1941
|
+
meetings: count4,
|
|
1942
|
+
lines: count4,
|
|
1943
|
+
words: count4,
|
|
1944
|
+
talk_ms: count4,
|
|
1945
|
+
/** This speaker's part of all talk time, 0–1. */
|
|
1946
|
+
share: pipe(number(), minValue(0), maxValue(1))
|
|
1947
|
+
});
|
|
1948
|
+
var meetingSpeakerItem = /* @__PURE__ */ __name((one) => ({
|
|
1949
|
+
key: one.key,
|
|
1950
|
+
name: one.name,
|
|
1951
|
+
person_id: one.personId,
|
|
1952
|
+
identity_id: one.identityId,
|
|
1953
|
+
meetings: one.meetings,
|
|
1954
|
+
lines: one.lines,
|
|
1955
|
+
words: one.words,
|
|
1956
|
+
talk_ms: one.talkMs,
|
|
1957
|
+
share: one.share
|
|
1958
|
+
}), "meetingSpeakerItem");
|
|
1959
|
+
var meetingStats = strictObject({
|
|
1960
|
+
time_zone: text5,
|
|
1961
|
+
meetings: count4,
|
|
1962
|
+
lines: count4,
|
|
1963
|
+
words: count4,
|
|
1964
|
+
talk_ms: count4,
|
|
1965
|
+
/** `week_start` is the Monday, as a date in `time_zone`. */
|
|
1966
|
+
weeks: array(strictObject({ week_start: text5, meetings: count4, talk_ms: count4 })),
|
|
1967
|
+
top_speakers: array(meetingSpeaker)
|
|
1968
|
+
});
|
|
1969
|
+
var meetingStatsItem = /* @__PURE__ */ __name((found, top = 10) => ({
|
|
1970
|
+
time_zone: found.timeZone,
|
|
1971
|
+
meetings: found.meetings,
|
|
1972
|
+
lines: found.lines,
|
|
1973
|
+
words: found.words,
|
|
1974
|
+
talk_ms: found.talkMs,
|
|
1975
|
+
weeks: found.weeks.map((week) => ({ week_start: week.weekStart, meetings: week.meetings, talk_ms: week.talkMs })),
|
|
1976
|
+
top_speakers: found.speakers.slice(0, top).map(meetingSpeakerItem)
|
|
1977
|
+
}), "meetingStatsItem");
|
|
1978
|
+
var truncated = /* @__PURE__ */ __name((...why) => nullable(picklist(why)), "truncated");
|
|
1979
|
+
var meetingParticipants = strictObject({
|
|
1980
|
+
schema_version: literal(1),
|
|
1981
|
+
kind: literal("meeting_participants"),
|
|
1982
|
+
account_id: id3,
|
|
1983
|
+
query: text5,
|
|
1984
|
+
items: array(strictObject({
|
|
1985
|
+
participant_id: id3,
|
|
1986
|
+
meeting_id: id3,
|
|
1987
|
+
identity_id: id3,
|
|
1988
|
+
display_name: nullable(text5),
|
|
1989
|
+
email: nullable(text5)
|
|
1990
|
+
})),
|
|
1991
|
+
/** Several identities on one page are observations, never speaker attribution or person links. */
|
|
1992
|
+
ambiguity: strictObject({ scope: literal("page"), multiple_identities: boolean(), identity_ids: array(id3) }),
|
|
1993
|
+
coverage: strictObject({
|
|
1994
|
+
scanned: count4,
|
|
1995
|
+
read_bytes: count4,
|
|
1996
|
+
archive_completeness: literal("unknown"),
|
|
1997
|
+
truncated_by: truncated("limit", "scan_limit", "read_bytes")
|
|
1998
|
+
}),
|
|
1999
|
+
page: strictObject({
|
|
2000
|
+
mode: literal("cursor"),
|
|
2001
|
+
limit: count4,
|
|
2002
|
+
has_more: boolean(),
|
|
2003
|
+
next_cursor: optional(text5)
|
|
2004
|
+
})
|
|
2005
|
+
});
|
|
2006
|
+
var revision = picklist(["current", "superseded"]);
|
|
2007
|
+
var meetingPassage = strictObject({
|
|
2008
|
+
schema_version: literal(1),
|
|
2009
|
+
kind: literal("meeting_context"),
|
|
2010
|
+
source: reference,
|
|
2011
|
+
target_ref: reference,
|
|
2012
|
+
target_fingerprint: text5,
|
|
2013
|
+
fingerprint: text5,
|
|
2014
|
+
revision,
|
|
2015
|
+
limits: strictObject({ before: count4, after: count4, bytes: count4, max_read_bytes: count4 }),
|
|
2016
|
+
content_bytes: count4,
|
|
2017
|
+
coverage: strictObject({
|
|
2018
|
+
included: count4,
|
|
2019
|
+
before: count4,
|
|
2020
|
+
after: count4,
|
|
2021
|
+
has_before: boolean(),
|
|
2022
|
+
has_after: boolean(),
|
|
2023
|
+
truncated_by: truncated("bytes"),
|
|
2024
|
+
before_ref: nullable(reference),
|
|
2025
|
+
after_ref: nullable(reference),
|
|
2026
|
+
continuation: literal("anchor-inclusive"),
|
|
2027
|
+
archive_completeness: literal("unknown"),
|
|
2028
|
+
input: literal("bounded-meeting-context")
|
|
2029
|
+
}),
|
|
2030
|
+
items: array(strictObject({
|
|
2031
|
+
ref: reference,
|
|
2032
|
+
fingerprint: text5,
|
|
2033
|
+
transcript_id: id3,
|
|
2034
|
+
content_hash: nullable(text5),
|
|
2035
|
+
position: count4,
|
|
2036
|
+
start_ms: count4,
|
|
2037
|
+
end_ms: count4,
|
|
2038
|
+
speaker_participant_id: nullable(id3),
|
|
2039
|
+
speaker_name: nullable(text5),
|
|
2040
|
+
text: text5,
|
|
2041
|
+
revision
|
|
2042
|
+
}))
|
|
2043
|
+
});
|
|
2044
|
+
var event = strictObject({
|
|
2045
|
+
id: pipe(string(), minLength(1)),
|
|
2046
|
+
event_series_id: nullable(text5),
|
|
2047
|
+
title: nullable(text5),
|
|
2048
|
+
description: nullable(text5),
|
|
2049
|
+
location: nullable(text5),
|
|
2050
|
+
starts_at: nullable(isoTime),
|
|
2051
|
+
ends_at: nullable(isoTime),
|
|
2052
|
+
timezone: nullable(text5),
|
|
2053
|
+
/** `auto`: made from a meeting; `owner`: made by hand; `calendar`: from a calendar's entries. */
|
|
2054
|
+
origin: picklist(["auto", "owner", "calendar"]),
|
|
2055
|
+
status: nullable(text5),
|
|
2056
|
+
all_day: boolean(),
|
|
2057
|
+
/** When its calendar deleted it: shown as "deleted in Google", kept as history. */
|
|
2058
|
+
source_deleted_at: nullable(isoTime),
|
|
2059
|
+
deleted_at: nullable(isoTime),
|
|
2060
|
+
created_at: isoTime,
|
|
2061
|
+
updated_at: isoTime,
|
|
2062
|
+
/** The fields whoever sent the invitation wrote, on a calendar CLI's `events list`: an agent reads them as data. */
|
|
2063
|
+
untrusted: optional(array(text5))
|
|
2064
|
+
});
|
|
2065
|
+
var eventItem = /* @__PURE__ */ __name((one) => ({
|
|
2066
|
+
id: String(one.id),
|
|
2067
|
+
event_series_id: one.eventSeriesId === null ? null : String(one.eventSeriesId),
|
|
2068
|
+
title: one.title,
|
|
2069
|
+
description: one.description,
|
|
2070
|
+
location: one.location,
|
|
2071
|
+
starts_at: iso3(one.startsAt),
|
|
2072
|
+
ends_at: iso3(one.endsAt),
|
|
2073
|
+
timezone: one.timezone,
|
|
2074
|
+
origin: one.origin,
|
|
2075
|
+
status: one.status ?? null,
|
|
2076
|
+
all_day: one.allDay === true,
|
|
2077
|
+
source_deleted_at: iso3(one.sourceDeletedAt ?? null),
|
|
2078
|
+
deleted_at: iso3(one.deletedAt),
|
|
2079
|
+
created_at: new Date(one.createdAt).toISOString(),
|
|
2080
|
+
updated_at: new Date(one.updatedAt).toISOString()
|
|
2081
|
+
}), "eventItem");
|
|
2082
|
+
|
|
2083
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/recording-schedule.js
|
|
2084
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
2085
|
+
|
|
2086
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/recording-sync.js
|
|
2087
|
+
var RecordingSyncError = class extends CliError {
|
|
2088
|
+
static {
|
|
2089
|
+
__name(this, "RecordingSyncError");
|
|
2090
|
+
}
|
|
2091
|
+
constructor(code, message) {
|
|
2092
|
+
super(code, message);
|
|
2093
|
+
this.name = "RecordingSyncError";
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
var fail = /* @__PURE__ */ __name((message, code = "validation_error") => {
|
|
2097
|
+
throw new RecordingSyncError(code, message);
|
|
2098
|
+
}, "fail");
|
|
2099
|
+
var text6 = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim().length > 0 && value.length <= 4096, "text");
|
|
2100
|
+
var integer3 = /* @__PURE__ */ __name((value, low, high) => Number.isSafeInteger(value) && Number(value) >= low && Number(value) <= high, "integer");
|
|
2101
|
+
var date = /* @__PURE__ */ __name((value) => {
|
|
2102
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value))
|
|
2103
|
+
return fail("archive dates must be valid YYYY-MM-DD dates");
|
|
2104
|
+
const result = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
|
|
2105
|
+
if (!Number.isFinite(result.getTime()) || result.toISOString().slice(0, 10) !== value)
|
|
2106
|
+
return fail("archive dates must be valid YYYY-MM-DD dates");
|
|
2107
|
+
return result;
|
|
2108
|
+
}, "date");
|
|
2109
|
+
var label = /* @__PURE__ */ __name((value) => value.toISOString().slice(0, 10), "label");
|
|
2110
|
+
var windowKey = /* @__PURE__ */ __name((window2) => `${window2.from}/${window2.to}`, "windowKey");
|
|
2111
|
+
var cancelled = /* @__PURE__ */ __name((signal) => {
|
|
2112
|
+
if (signal?.aborted)
|
|
2113
|
+
fail("archive synchronization cancelled", "cancelled");
|
|
2114
|
+
}, "cancelled");
|
|
2115
|
+
function recordingWindows(fromValue, toValue) {
|
|
2116
|
+
const from = date(fromValue);
|
|
2117
|
+
const to = date(toValue);
|
|
2118
|
+
const anniversary = new Date(from);
|
|
2119
|
+
const lastDay = new Date(from);
|
|
2120
|
+
lastDay.setUTCFullYear(from.getUTCFullYear() + 10, from.getUTCMonth() + 1, 0);
|
|
2121
|
+
anniversary.setUTCFullYear(from.getUTCFullYear() + 10, from.getUTCMonth(), Math.min(from.getUTCDate(), lastDay.getUTCDate()));
|
|
2122
|
+
if (to < from || to > anniversary)
|
|
2123
|
+
return fail("archive date range must be ordered and at most ten calendar years");
|
|
2124
|
+
const windows = [];
|
|
2125
|
+
let cursor = from;
|
|
2126
|
+
while (cursor <= to) {
|
|
2127
|
+
const end = new Date(cursor);
|
|
2128
|
+
end.setUTCMonth(end.getUTCMonth() + 1, 0);
|
|
2129
|
+
const upper = new Date(Math.min(end.getTime(), to.getTime()));
|
|
2130
|
+
windows.push({ from: label(cursor), to: label(upper) });
|
|
2131
|
+
cursor = new Date(upper);
|
|
2132
|
+
cursor.setUTCDate(cursor.getUTCDate() + 1);
|
|
2133
|
+
}
|
|
2134
|
+
return windows;
|
|
2135
|
+
}
|
|
2136
|
+
__name(recordingWindows, "recordingWindows");
|
|
2137
|
+
var object = /* @__PURE__ */ __name((value) => {
|
|
2138
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
2139
|
+
return fail("invalid archive checkpoint or provider metadata", "invalid_response");
|
|
2140
|
+
return value;
|
|
2141
|
+
}, "object");
|
|
2142
|
+
var scope = /* @__PURE__ */ __name((value) => {
|
|
2143
|
+
const row = object(value);
|
|
2144
|
+
if (!text6(row.provider) || !text6(row.account))
|
|
2145
|
+
return fail("archive provider and account are required");
|
|
2146
|
+
try {
|
|
2147
|
+
return snapshotMeetingScope({ provider: row.provider, account: row.account });
|
|
2148
|
+
} catch {
|
|
2149
|
+
return fail("archive provider and account must be bounded nonempty identifiers");
|
|
2150
|
+
}
|
|
2151
|
+
}, "scope");
|
|
2152
|
+
var window = /* @__PURE__ */ __name((value) => {
|
|
2153
|
+
const row = object(value);
|
|
2154
|
+
const from = label(date(row.from));
|
|
2155
|
+
const to = label(date(row.to));
|
|
2156
|
+
if (to < from || recordingWindows(from, to).length !== 1)
|
|
2157
|
+
return fail("invalid archive checkpoint window", "invalid_response");
|
|
2158
|
+
return { from, to };
|
|
2159
|
+
}, "window");
|
|
2160
|
+
var nullableText = /* @__PURE__ */ __name((value) => value === null || text6(value), "nullableText");
|
|
2161
|
+
var asset = /* @__PURE__ */ __name((value) => {
|
|
2162
|
+
const row = object(value);
|
|
2163
|
+
if (!nullableText(row.id) || !text6(row.type) || !nullableText(row.format) || !text6(row.status) || typeof row.available !== "boolean" || !(row.size === null || integer3(row.size, 0, Number.MAX_SAFE_INTEGER)) || !nullableText(row.startedAt) || !nullableText(row.endedAt))
|
|
2164
|
+
return fail("invalid recording asset metadata", "invalid_response");
|
|
2165
|
+
for (const value2 of [row.startedAt, row.endedAt])
|
|
2166
|
+
if (value2 !== null && !Number.isFinite(Date.parse(value2)))
|
|
2167
|
+
return fail("invalid recording asset timestamp", "invalid_response");
|
|
2168
|
+
if (row.available && row.id === null)
|
|
2169
|
+
return fail("available recording assets require an id", "invalid_response");
|
|
2170
|
+
return {
|
|
2171
|
+
id: row.id,
|
|
2172
|
+
type: row.type,
|
|
2173
|
+
format: row.format,
|
|
2174
|
+
size: row.size,
|
|
2175
|
+
status: row.status,
|
|
2176
|
+
available: row.available,
|
|
2177
|
+
startedAt: row.startedAt,
|
|
2178
|
+
endedAt: row.endedAt
|
|
2179
|
+
};
|
|
2180
|
+
}, "asset");
|
|
2181
|
+
var recordingAssetFingerprint = /* @__PURE__ */ __name((value) => JSON.stringify(asset(value)), "recordingAssetFingerprint");
|
|
2182
|
+
var metadataSize = /* @__PURE__ */ __name((value) => new TextEncoder().encode(JSON.stringify(value)).byteLength, "metadataSize");
|
|
2183
|
+
var assets = /* @__PURE__ */ __name((value) => {
|
|
2184
|
+
if (!Array.isArray(value) || value.length > 1e3)
|
|
2185
|
+
return fail("recording asset metadata exceeds its limit", "invalid_response");
|
|
2186
|
+
const result = value.map(asset);
|
|
2187
|
+
if (metadataSize(result) > 1024 ** 2)
|
|
2188
|
+
return fail("recording asset metadata exceeds its byte limit", "invalid_response");
|
|
2189
|
+
const ids2 = result.flatMap((item) => item.id === null ? [] : [item.id]);
|
|
2190
|
+
if (new Set(ids2).size !== ids2.length)
|
|
2191
|
+
return fail("provider repeated a recording asset id", "invalid_response");
|
|
2192
|
+
return result;
|
|
2193
|
+
}, "assets");
|
|
2194
|
+
function parseRecordingSyncCheckpoint(value, maxEntries = 1e4) {
|
|
2195
|
+
if (!integer3(maxEntries, 1, 1e4))
|
|
2196
|
+
return fail("archive entry limit must be between 1 and 10000");
|
|
2197
|
+
const row = object(value);
|
|
2198
|
+
if (row.version !== 1 || !text6(row.configKey) || !integer3(row.revision, 1, Number.MAX_SAFE_INTEGER) || !integer3(row.updatedAt, 0, Number.MAX_SAFE_INTEGER) || !Array.isArray(row.windows) || row.windows.length > 1e3 || !Array.isArray(row.pendingWindows) || row.pendingWindows.length > 1e3 || !Array.isArray(row.entries) || row.entries.length > maxEntries)
|
|
2199
|
+
return fail("unsupported or oversized archive checkpoint", "invalid_response");
|
|
2200
|
+
const windows = row.windows.map(window);
|
|
2201
|
+
const pendingWindows = row.pendingWindows.map(window);
|
|
2202
|
+
let metadataBytes = 0;
|
|
2203
|
+
const entries = row.entries.map((value2) => {
|
|
2204
|
+
const entry = object(value2);
|
|
2205
|
+
if (!text6(entry.externalId) || !Array.isArray(entry.acknowledged) || entry.acknowledged.length > 1e3 || entry.acknowledged.some((value3) => typeof value3 !== "string" || value3.length > 65536))
|
|
2206
|
+
return fail("invalid archive checkpoint entry", "invalid_response");
|
|
2207
|
+
const metadata = assets(entry.assets);
|
|
2208
|
+
const acknowledged = entry.acknowledged;
|
|
2209
|
+
metadataBytes += metadataSize(metadata) + metadataSize(acknowledged);
|
|
2210
|
+
if (metadataBytes > 8 * 1024 ** 2)
|
|
2211
|
+
return fail("archive checkpoint exceeds its byte limit", "invalid_response");
|
|
2212
|
+
if (new Set(acknowledged).size !== acknowledged.length || acknowledged.some((key) => !metadata.some((item) => item.available && recordingAssetFingerprint(item) === key)))
|
|
2213
|
+
return fail("invalid archive checkpoint acknowledgement", "invalid_response");
|
|
2214
|
+
return {
|
|
2215
|
+
externalId: entry.externalId,
|
|
2216
|
+
window: window(entry.window),
|
|
2217
|
+
assets: metadata,
|
|
2218
|
+
acknowledged: [...acknowledged]
|
|
2219
|
+
};
|
|
2220
|
+
});
|
|
2221
|
+
if (new Set(windows.map(windowKey)).size !== windows.length || new Set(pendingWindows.map(windowKey)).size !== pendingWindows.length || new Set(entries.map((entry) => entry.externalId)).size !== entries.length)
|
|
2222
|
+
return fail("duplicate archive checkpoint metadata", "invalid_response");
|
|
2223
|
+
return {
|
|
2224
|
+
version: 1,
|
|
2225
|
+
scope: scope(row.scope),
|
|
2226
|
+
configKey: row.configKey,
|
|
2227
|
+
revision: row.revision,
|
|
2228
|
+
updatedAt: row.updatedAt,
|
|
2229
|
+
windows,
|
|
2230
|
+
pendingWindows,
|
|
2231
|
+
entries
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
__name(parseRecordingSyncCheckpoint, "parseRecordingSyncCheckpoint");
|
|
2235
|
+
var covered = /* @__PURE__ */ __name((windows, selected) => windows.some((item) => item.from <= selected.from && item.to >= selected.to), "covered");
|
|
2236
|
+
var compactWindows = /* @__PURE__ */ __name((windows, from) => {
|
|
2237
|
+
const result = [];
|
|
2238
|
+
for (const item of windows.filter((item2) => item2.to >= from).sort((a, b) => a.from.localeCompare(b.from))) {
|
|
2239
|
+
const last = result.at(-1);
|
|
2240
|
+
if (last && last.from.slice(0, 7) === item.from.slice(0, 7)) {
|
|
2241
|
+
const nextDay = date(last.to);
|
|
2242
|
+
nextDay.setUTCDate(nextDay.getUTCDate() + 1);
|
|
2243
|
+
if (item.from <= label(nextDay)) {
|
|
2244
|
+
last.to = last.to > item.to ? last.to : item.to;
|
|
2245
|
+
continue;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
result.push({ ...item });
|
|
2249
|
+
}
|
|
2250
|
+
return result;
|
|
2251
|
+
}, "compactWindows");
|
|
2252
|
+
var pending = /* @__PURE__ */ __name((entry) => entry.assets.length === 0 || entry.assets.some((item) => !item.available || !entry.acknowledged.includes(recordingAssetFingerprint(item))), "pending");
|
|
2253
|
+
var acknowledgedAssets = /* @__PURE__ */ __name((occurrence, result) => {
|
|
2254
|
+
if (result.externalId !== occurrence.externalId || !text6(result.manifestPath) || !Array.isArray(result.downloaded) || !Array.isArray(result.skipped) || !Array.isArray(result.unavailable) || result.downloaded.length + result.skipped.length > 1e3)
|
|
2255
|
+
return fail("archive returned an invalid occurrence acknowledgement", "invalid_response");
|
|
2256
|
+
const completed = [...result.downloaded, ...result.skipped];
|
|
2257
|
+
return occurrence.assets.filter((item) => item.available && completed.some((file) => file.id === item.id && file.remoteSize === item.size && file.type === item.type && file.format === item.format && file.startedAt === item.startedAt && file.endedAt === item.endedAt && text6(file.path) && integer3(file.size, 0, Number.MAX_SAFE_INTEGER) && (item.size === null || file.size === item.size) && /^[a-f0-9]{64}$/.test(file.sha256))).map(recordingAssetFingerprint);
|
|
2258
|
+
}, "acknowledgedAssets");
|
|
2259
|
+
async function* syncRecordingArchive(catalog, input) {
|
|
2260
|
+
const options = {
|
|
2261
|
+
...input,
|
|
2262
|
+
scope: { ...input.scope },
|
|
2263
|
+
checkpoint: input.checkpoint ? { ...input.checkpoint } : void 0
|
|
2264
|
+
};
|
|
2265
|
+
const windows = recordingWindows(options.from, options.to);
|
|
2266
|
+
const selectedScope = scope(options.scope);
|
|
2267
|
+
const maxPages = options.maxPages ?? 1e3;
|
|
2268
|
+
const maxEntries = options.maxEntries ?? 1e4;
|
|
2269
|
+
if (catalog.provider !== selectedScope.provider || !integer3(maxPages, 1, 1e4) || !integer3(maxEntries, 1, 1e4) || typeof options.archive !== "function" || typeof options.now !== "function")
|
|
2270
|
+
return fail("invalid archive synchronization configuration");
|
|
2271
|
+
if (options.recheckFrom !== void 0)
|
|
2272
|
+
date(options.recheckFrom);
|
|
2273
|
+
const checkpoint = options.checkpoint;
|
|
2274
|
+
if (checkpoint && (!text6(checkpoint.jobId) || !text6(checkpoint.configKey)))
|
|
2275
|
+
return fail("archive checkpoint job and configuration key are required");
|
|
2276
|
+
const clock2 = /* @__PURE__ */ __name(() => {
|
|
2277
|
+
const now = options.now();
|
|
2278
|
+
if (!integer3(now, 0, Number.MAX_SAFE_INTEGER))
|
|
2279
|
+
return fail("archive clock must return an epoch millisecond timestamp");
|
|
2280
|
+
return now;
|
|
2281
|
+
}, "clock");
|
|
2282
|
+
clock2();
|
|
2283
|
+
cancelled(options.signal);
|
|
2284
|
+
const lease = checkpoint ? await checkpoint.store.acquire(checkpoint.jobId) : void 0;
|
|
2285
|
+
try {
|
|
2286
|
+
cancelled(options.signal);
|
|
2287
|
+
const previous = checkpoint && lease ? await checkpoint.store.read(checkpoint.jobId, lease.token) : null;
|
|
2288
|
+
let state = previous ? parseRecordingSyncCheckpoint(previous, maxEntries) : {
|
|
2289
|
+
version: 1,
|
|
2290
|
+
scope: selectedScope,
|
|
2291
|
+
configKey: checkpoint?.configKey ?? "ephemeral",
|
|
2292
|
+
revision: 0,
|
|
2293
|
+
updatedAt: clock2(),
|
|
2294
|
+
windows: [],
|
|
2295
|
+
pendingWindows: [],
|
|
2296
|
+
entries: []
|
|
2297
|
+
};
|
|
2298
|
+
if (state.scope.provider !== selectedScope.provider || state.scope.account !== selectedScope.account || state.configKey !== (checkpoint?.configKey ?? "ephemeral"))
|
|
2299
|
+
return fail("archive checkpoint belongs to another account or configuration", "configuration_error");
|
|
2300
|
+
const save = /* @__PURE__ */ __name(async (next) => {
|
|
2301
|
+
const updated = { ...next, revision: state.revision + 1, updatedAt: clock2() };
|
|
2302
|
+
if (!integer3(updated.revision, 1, Number.MAX_SAFE_INTEGER) || updated.windows.length > 1e3 || updated.pendingWindows.length > 1e3 || updated.entries.length > maxEntries || metadataSize(updated) > 8 * 1024 ** 2)
|
|
2303
|
+
return fail("archive checkpoint exceeds its metadata limit", "invalid_response");
|
|
2304
|
+
if (checkpoint && lease)
|
|
2305
|
+
await checkpoint.store.save(checkpoint.jobId, lease.token, state.revision === 0 ? null : state.revision, updated);
|
|
2306
|
+
state = updated;
|
|
2307
|
+
}, "save");
|
|
2308
|
+
const backlog = state.entries.filter(pending).map((entry) => entry.window);
|
|
2309
|
+
const planned = [
|
|
2310
|
+
...new Map([...state.pendingWindows, ...backlog, ...windows].map((item) => [windowKey(item), item])).values()
|
|
2311
|
+
].sort((a, b) => a.from.localeCompare(b.from));
|
|
2312
|
+
const observed = /* @__PURE__ */ new Map();
|
|
2313
|
+
let pages = 0;
|
|
2314
|
+
let observedBytes = 0;
|
|
2315
|
+
for (const selectedWindow of planned) {
|
|
2316
|
+
cancelled(options.signal);
|
|
2317
|
+
if (covered(state.windows, selectedWindow) && !state.pendingWindows.some((item) => windowKey(item) === windowKey(selectedWindow)) && !state.entries.some((entry) => windowKey(entry.window) === windowKey(selectedWindow) && pending(entry)) && !(options.recheckFrom !== void 0 && selectedWindow.to >= options.recheckFrom))
|
|
2318
|
+
continue;
|
|
2319
|
+
if (!state.pendingWindows.some((item) => windowKey(item) === windowKey(selectedWindow)))
|
|
2320
|
+
await save({ ...state, pendingWindows: [...state.pendingWindows, selectedWindow] });
|
|
2321
|
+
const cursors = /* @__PURE__ */ new Set();
|
|
2322
|
+
let cursor;
|
|
2323
|
+
do {
|
|
2324
|
+
cancelled(options.signal);
|
|
2325
|
+
if (++pages > maxPages)
|
|
2326
|
+
return fail("archive catalog page limit exceeded", "invalid_response");
|
|
2327
|
+
const page = await catalog.list({
|
|
2328
|
+
...selectedWindow,
|
|
2329
|
+
account: selectedScope.account,
|
|
2330
|
+
...cursor === void 0 ? {} : { cursor },
|
|
2331
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2332
|
+
});
|
|
2333
|
+
cancelled(options.signal);
|
|
2334
|
+
if (!Array.isArray(page.items) || page.items.length > 1e3 || !(page.nextCursor === null || text6(page.nextCursor)))
|
|
2335
|
+
return fail("provider returned an invalid recording page", "invalid_response");
|
|
2336
|
+
for (const raw of page.items) {
|
|
2337
|
+
cancelled(options.signal);
|
|
2338
|
+
if (!text6(raw.id) || !text6(raw.externalId) || !nullableText(raw.title) || !nullableText(raw.startedAt))
|
|
2339
|
+
return fail("provider returned an invalid recording occurrence", "invalid_response");
|
|
2340
|
+
const occurrence = {
|
|
2341
|
+
id: raw.id,
|
|
2342
|
+
externalId: raw.externalId,
|
|
2343
|
+
title: raw.title,
|
|
2344
|
+
startedAt: raw.startedAt,
|
|
2345
|
+
assets: assets(raw.assets)
|
|
2346
|
+
};
|
|
2347
|
+
const signature = JSON.stringify(occurrence);
|
|
2348
|
+
const earlier = observed.get(occurrence.externalId);
|
|
2349
|
+
if (earlier !== void 0) {
|
|
2350
|
+
if (earlier !== signature)
|
|
2351
|
+
return fail("provider returned conflicting recording occurrences", "invalid_response");
|
|
2352
|
+
continue;
|
|
2353
|
+
}
|
|
2354
|
+
observedBytes += new TextEncoder().encode(signature).byteLength;
|
|
2355
|
+
if (observedBytes > 8 * 1024 ** 2)
|
|
2356
|
+
return fail("archive occurrence metadata exceeds its byte limit", "invalid_response");
|
|
2357
|
+
if (observed.size >= maxEntries)
|
|
2358
|
+
return fail("archive occurrence limit exceeded", "invalid_response");
|
|
2359
|
+
observed.set(occurrence.externalId, signature);
|
|
2360
|
+
const old = state.entries.find((entry) => entry.externalId === occurrence.externalId);
|
|
2361
|
+
const current = {
|
|
2362
|
+
externalId: occurrence.externalId,
|
|
2363
|
+
window: selectedWindow,
|
|
2364
|
+
assets: occurrence.assets,
|
|
2365
|
+
acknowledged: old?.acknowledged.filter((key) => occurrence.assets.some((item) => recordingAssetFingerprint(item) === key)) ?? []
|
|
2366
|
+
};
|
|
2367
|
+
if (old && !pending(current))
|
|
2368
|
+
continue;
|
|
2369
|
+
if (!old && state.entries.length >= maxEntries)
|
|
2370
|
+
return fail("archive checkpoint entry limit exceeded", "invalid_response");
|
|
2371
|
+
const archive = await options.archive(structuredClone(occurrence), options.signal);
|
|
2372
|
+
current.acknowledged = [.../* @__PURE__ */ new Set([...current.acknowledged, ...acknowledgedAssets(occurrence, archive)])];
|
|
2373
|
+
await save({
|
|
2374
|
+
...state,
|
|
2375
|
+
entries: [...state.entries.filter((entry) => entry.externalId !== current.externalId), current]
|
|
2376
|
+
});
|
|
2377
|
+
yield {
|
|
2378
|
+
window: selectedWindow,
|
|
2379
|
+
occurrence: { id: occurrence.id, externalId: occurrence.externalId, title: occurrence.title },
|
|
2380
|
+
archive,
|
|
2381
|
+
availability: "unknown",
|
|
2382
|
+
checkpointRevision: checkpoint ? state.revision : null
|
|
2383
|
+
};
|
|
2384
|
+
}
|
|
2385
|
+
if (page.nextCursor !== null && cursors.has(page.nextCursor))
|
|
2386
|
+
return fail("provider repeated a recording pagination cursor", "invalid_response");
|
|
2387
|
+
if (page.nextCursor !== null)
|
|
2388
|
+
cursors.add(page.nextCursor);
|
|
2389
|
+
cursor = page.nextCursor ?? void 0;
|
|
2390
|
+
} while (cursor !== void 0);
|
|
2391
|
+
cancelled(options.signal);
|
|
2392
|
+
const pendingWindows = state.pendingWindows.filter((item) => windowKey(item) !== windowKey(selectedWindow));
|
|
2393
|
+
const retainFrom = options.recheckFrom ?? `${options.to.slice(0, 7)}-01`;
|
|
2394
|
+
await save({
|
|
2395
|
+
...state,
|
|
2396
|
+
windows: compactWindows([...state.windows, selectedWindow], options.from),
|
|
2397
|
+
pendingWindows,
|
|
2398
|
+
entries: state.entries.filter((entry) => pending(entry) || entry.window.to >= retainFrom || pendingWindows.some((item) => item.from <= entry.window.to && item.to >= entry.window.from))
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
2401
|
+
} finally {
|
|
2402
|
+
await lease?.release();
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
__name(syncRecordingArchive, "syncRecordingArchive");
|
|
2406
|
+
|
|
2407
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/recording-schedule.js
|
|
2408
|
+
var fail2 = /* @__PURE__ */ __name((message) => {
|
|
2409
|
+
throw new CliError("validation_error", message);
|
|
2410
|
+
}, "fail");
|
|
2411
|
+
var text7 = /* @__PURE__ */ __name((value, maximum) => typeof value === "string" && !!value.trim() && value.length <= maximum && !/[\0\r\n]/.test(value), "text");
|
|
2412
|
+
var clock = /* @__PURE__ */ __name((now) => {
|
|
2413
|
+
if (!Number.isSafeInteger(now) || now < 0 || now > 253402300799999)
|
|
2414
|
+
fail2("invalid archive schedule clock");
|
|
2415
|
+
return new Date(now);
|
|
2416
|
+
}, "clock");
|
|
2417
|
+
var day = /* @__PURE__ */ __name((instant) => instant.toISOString().slice(0, 10), "day");
|
|
2418
|
+
var localDay = /* @__PURE__ */ __name((instant, timeZone) => new Intl.DateTimeFormat("en-CA", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }).format(instant), "localDay");
|
|
2419
|
+
var identity = /* @__PURE__ */ __name((schedule) => createHash3("sha256").update(JSON.stringify(schedule)).digest("hex"), "identity");
|
|
2420
|
+
var planRecordingArchiveSchedule = /* @__PURE__ */ __name((input, options) => {
|
|
2421
|
+
const now = clock(options.now);
|
|
2422
|
+
const scope3 = snapshotMeetingScope(input.scope);
|
|
2423
|
+
if (!text7(input.name, 200) || !text7(input.destination, 4096))
|
|
2424
|
+
fail2("archive schedule name and destination are required");
|
|
2425
|
+
if (typeof input.dailyAt !== "string" || !/^(?:[01]\d|2[0-3]):[0-5]\d$/.test(input.dailyAt))
|
|
2426
|
+
fail2("archive schedule time must be HH:mm");
|
|
2427
|
+
if (!text7(input.timeZone, 200))
|
|
2428
|
+
fail2("archive schedule requires a time zone");
|
|
2429
|
+
try {
|
|
2430
|
+
new Intl.DateTimeFormat("en", { timeZone: input.timeZone });
|
|
2431
|
+
} catch {
|
|
2432
|
+
fail2("archive schedule requires a valid IANA time zone");
|
|
2433
|
+
}
|
|
2434
|
+
recordingWindows(input.from, input.from);
|
|
2435
|
+
if (input.from <= localDay(now, input.timeZone))
|
|
2436
|
+
recordingWindows(input.from, localDay(now, input.timeZone));
|
|
2437
|
+
const lookbackDays = input.lookbackDays ?? 7;
|
|
2438
|
+
const maxBytes = input.maxBytes ?? 20 * 1024 ** 3;
|
|
2439
|
+
if (!Number.isSafeInteger(lookbackDays) || lookbackDays < 0 || lookbackDays > 31)
|
|
2440
|
+
fail2("archive schedule lookback must be between zero and 31 days");
|
|
2441
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)
|
|
2442
|
+
fail2("archive schedule byte limit must be positive");
|
|
2443
|
+
const definition = {
|
|
2444
|
+
name: input.name,
|
|
2445
|
+
scope: scope3,
|
|
2446
|
+
destination: input.destination,
|
|
2447
|
+
from: input.from,
|
|
2448
|
+
dailyAt: input.dailyAt,
|
|
2449
|
+
timeZone: input.timeZone,
|
|
2450
|
+
lookbackDays,
|
|
2451
|
+
maxBytes
|
|
2452
|
+
};
|
|
2453
|
+
return Object.freeze({ version: 1, id: identity(definition), ...definition, createdAt: options.now });
|
|
2454
|
+
}, "planRecordingArchiveSchedule");
|
|
2455
|
+
var parseRecordingArchiveSchedule = /* @__PURE__ */ __name((value) => {
|
|
2456
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
2457
|
+
fail2("invalid archive schedule");
|
|
2458
|
+
const row = value;
|
|
2459
|
+
if (Object.keys(row).some((key) => ![
|
|
2460
|
+
"version",
|
|
2461
|
+
"id",
|
|
2462
|
+
"name",
|
|
2463
|
+
"scope",
|
|
2464
|
+
"destination",
|
|
2465
|
+
"from",
|
|
2466
|
+
"dailyAt",
|
|
2467
|
+
"timeZone",
|
|
2468
|
+
"lookbackDays",
|
|
2469
|
+
"maxBytes",
|
|
2470
|
+
"createdAt"
|
|
2471
|
+
].includes(key)) || row.version !== 1)
|
|
2472
|
+
fail2("unsupported archive schedule");
|
|
2473
|
+
const schedule = planRecordingArchiveSchedule(row, { now: row.createdAt });
|
|
2474
|
+
if (schedule.id !== row.id)
|
|
2475
|
+
fail2("archive schedule does not match its identity");
|
|
2476
|
+
return schedule;
|
|
2477
|
+
}, "parseRecordingArchiveSchedule");
|
|
2478
|
+
var recordingArchiveScheduleWindow = /* @__PURE__ */ __name((value, options) => {
|
|
2479
|
+
const schedule = parseRecordingArchiveSchedule(value);
|
|
2480
|
+
const now = clock(options.now);
|
|
2481
|
+
const through = localDay(now, schedule.timeZone);
|
|
2482
|
+
if (schedule.from > through)
|
|
2483
|
+
return null;
|
|
2484
|
+
const floor = /* @__PURE__ */ new Date(`${through}T00:00:00Z`);
|
|
2485
|
+
const month = floor.getUTCMonth();
|
|
2486
|
+
const date2 = floor.getUTCDate();
|
|
2487
|
+
floor.setUTCDate(1);
|
|
2488
|
+
floor.setUTCFullYear(floor.getUTCFullYear() - 10);
|
|
2489
|
+
const last = new Date(floor);
|
|
2490
|
+
last.setUTCMonth(month + 1, 0);
|
|
2491
|
+
floor.setUTCDate(Math.min(date2, last.getUTCDate()));
|
|
2492
|
+
const from = schedule.from > day(floor) ? schedule.from : day(floor);
|
|
2493
|
+
const overlap = /* @__PURE__ */ new Date(`${through}T00:00:00Z`);
|
|
2494
|
+
overlap.setUTCDate(overlap.getUTCDate() - schedule.lookbackDays);
|
|
2495
|
+
const recheckFrom = from > day(overlap) ? from : day(overlap);
|
|
2496
|
+
return { from, to: through, recheckFrom };
|
|
2497
|
+
}, "recordingArchiveScheduleWindow");
|
|
2498
|
+
var installRecordingArchiveSchedule = /* @__PURE__ */ __name(async (scheduler, value, options = {}) => {
|
|
2499
|
+
const schedule = parseRecordingArchiveSchedule(value);
|
|
2500
|
+
const backend = scheduler.backend;
|
|
2501
|
+
const signal = options.signal;
|
|
2502
|
+
if (signal?.aborted) {
|
|
2503
|
+
if (signal.reason instanceof CliError)
|
|
2504
|
+
throw signal.reason;
|
|
2505
|
+
const timeout = signal.reason instanceof Error && signal.reason.name === "TimeoutError";
|
|
2506
|
+
throw new CliError(timeout ? "timeout" : "cancelled", timeout ? "archive schedule installation timed out" : "archive schedule installation cancelled");
|
|
2507
|
+
}
|
|
2508
|
+
if (options.apply !== true || options.dryRun === true)
|
|
2509
|
+
return { applied: false, backend, schedule };
|
|
2510
|
+
await scheduler.install(schedule, { signal });
|
|
2511
|
+
return { applied: true, backend, schedule };
|
|
2512
|
+
}, "installRecordingArchiveSchedule");
|
|
2513
|
+
|
|
2514
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/recording-transfer.js
|
|
2515
|
+
var RecordingTransferError = class extends CliError {
|
|
2516
|
+
static {
|
|
2517
|
+
__name(this, "RecordingTransferError");
|
|
2518
|
+
}
|
|
2519
|
+
constructor(message, code = "invalid_response") {
|
|
2520
|
+
super(code, message);
|
|
2521
|
+
this.name = "RecordingTransferError";
|
|
2522
|
+
}
|
|
2523
|
+
};
|
|
2524
|
+
var strongRecordingValidator = /* @__PURE__ */ __name((value) => typeof value === "string" && value.length <= 1024 && /^"[\x21\x23-\x7e\x80-\xff]*"$/.test(value), "strongRecordingValidator");
|
|
2525
|
+
var fail3 = /* @__PURE__ */ __name((message, code = "invalid_response") => {
|
|
2526
|
+
throw new RecordingTransferError(message, code);
|
|
2527
|
+
}, "fail");
|
|
2528
|
+
var integer4 = /* @__PURE__ */ __name((value) => {
|
|
2529
|
+
if (value === null)
|
|
2530
|
+
return null;
|
|
2531
|
+
if (typeof value !== "string" || !/^\d+$/.test(value) || !Number.isSafeInteger(Number(value)))
|
|
2532
|
+
return fail3("invalid recording content length");
|
|
2533
|
+
return Number(value);
|
|
2534
|
+
}, "integer");
|
|
2535
|
+
var cancelled2 = /* @__PURE__ */ __name((signal) => {
|
|
2536
|
+
if (!signal?.aborted)
|
|
2537
|
+
return;
|
|
2538
|
+
if (signal.reason instanceof CliError)
|
|
2539
|
+
throw signal.reason;
|
|
2540
|
+
throw new RecordingTransferError("recording transfer cancelled", "cancelled");
|
|
2541
|
+
}, "cancelled");
|
|
2542
|
+
var sameLocator = /* @__PURE__ */ __name((a, b) => a.provider === b.provider && a.account === b.account && a.occurrenceId === b.occurrenceId && a.assetId === b.assetId, "sameLocator");
|
|
2543
|
+
var receipt = /* @__PURE__ */ __name((value, expectedSize, expectedHash) => {
|
|
2544
|
+
if (typeof value !== "object" || value === null)
|
|
2545
|
+
return fail3("invalid recording storage receipt");
|
|
2546
|
+
const { size, sha256 } = value;
|
|
2547
|
+
if (size !== expectedSize || typeof sha256 !== "string" || !/^[a-f0-9]{64}$/.test(sha256) || expectedHash !== void 0 && sha256 !== expectedHash)
|
|
2548
|
+
return fail3("invalid recording storage receipt");
|
|
2549
|
+
return { size, sha256 };
|
|
2550
|
+
}, "receipt");
|
|
2551
|
+
var transferRecording = /* @__PURE__ */ __name(async (source, storage, options) => {
|
|
2552
|
+
const { maxBytes, signal, expectedSize } = options;
|
|
2553
|
+
const inputLocator = options.locator;
|
|
2554
|
+
const fixedScope = snapshotMeetingScope(inputLocator);
|
|
2555
|
+
const locator = Object.freeze({
|
|
2556
|
+
provider: fixedScope.provider,
|
|
2557
|
+
account: fixedScope.account,
|
|
2558
|
+
occurrenceId: inputLocator.occurrenceId,
|
|
2559
|
+
assetId: inputLocator.assetId
|
|
2560
|
+
});
|
|
2561
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0 || [locator.occurrenceId, locator.assetId].some((value) => typeof value !== "string" || !value.trim() || value.length > 512 || /[\0\r\n]/.test(value)) || expectedSize != null && (!Number.isSafeInteger(expectedSize) || expectedSize < 0 || expectedSize > maxBytes))
|
|
2562
|
+
fail3("invalid recording transfer options", "validation_error");
|
|
2563
|
+
cancelled2(signal);
|
|
2564
|
+
const loaded = await storage.load(locator);
|
|
2565
|
+
const loadedLocator = loaded?.locator;
|
|
2566
|
+
let partial = loaded && loadedLocator ? Object.freeze({
|
|
2567
|
+
locator: Object.freeze({
|
|
2568
|
+
provider: loadedLocator.provider,
|
|
2569
|
+
account: loadedLocator.account,
|
|
2570
|
+
occurrenceId: loadedLocator.occurrenceId,
|
|
2571
|
+
assetId: loadedLocator.assetId
|
|
2572
|
+
}),
|
|
2573
|
+
offset: loaded.offset,
|
|
2574
|
+
sha256: loaded.sha256,
|
|
2575
|
+
validator: loaded.validator,
|
|
2576
|
+
total: loaded.total
|
|
2577
|
+
}) : null;
|
|
2578
|
+
if (partial && (!sameLocator(partial.locator, locator) || !strongRecordingValidator(partial.validator) || !Number.isSafeInteger(partial.offset) || partial.offset <= 0 || partial.offset > maxBytes || !/^[a-f0-9]{64}$/.test(partial.sha256) || partial.total !== null && (!Number.isSafeInteger(partial.total) || partial.total < partial.offset || partial.total > maxBytes) || expectedSize != null && partial.total !== expectedSize))
|
|
2579
|
+
partial = null;
|
|
2580
|
+
cancelled2(signal);
|
|
2581
|
+
const openResponse = /* @__PURE__ */ __name(async (request) => {
|
|
2582
|
+
const opened = await source.open(request);
|
|
2583
|
+
const close = opened.close.bind(opened);
|
|
2584
|
+
try {
|
|
2585
|
+
return Object.freeze({
|
|
2586
|
+
status: opened.status,
|
|
2587
|
+
etag: opened.etag,
|
|
2588
|
+
contentRange: opened.contentRange,
|
|
2589
|
+
contentLength: opened.contentLength,
|
|
2590
|
+
body: opened.body,
|
|
2591
|
+
close
|
|
2592
|
+
});
|
|
2593
|
+
} catch (error) {
|
|
2594
|
+
await close();
|
|
2595
|
+
throw error;
|
|
2596
|
+
}
|
|
2597
|
+
}, "openResponse");
|
|
2598
|
+
let response = await openResponse({
|
|
2599
|
+
locator,
|
|
2600
|
+
...partial ? { offset: partial.offset, validator: partial.validator } : {},
|
|
2601
|
+
...signal ? { signal } : {}
|
|
2602
|
+
});
|
|
2603
|
+
try {
|
|
2604
|
+
cancelled2(signal);
|
|
2605
|
+
if (partial && response.status === 416) {
|
|
2606
|
+
const match = /^bytes \*\/(\d+)$/.exec(response.contentRange ?? "");
|
|
2607
|
+
if (match && Number(match[1]) === partial.offset && partial.total === partial.offset && response.etag === partial.validator) {
|
|
2608
|
+
const writer2 = await storage.open(locator, {
|
|
2609
|
+
resume: partial,
|
|
2610
|
+
validator: partial.validator,
|
|
2611
|
+
total: partial.total
|
|
2612
|
+
});
|
|
2613
|
+
try {
|
|
2614
|
+
cancelled2(signal);
|
|
2615
|
+
return { ...receipt(await writer2.finish(), partial.offset, partial.sha256), resumedBytes: partial.offset };
|
|
2616
|
+
} finally {
|
|
2617
|
+
await writer2.close();
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
await response.close();
|
|
2621
|
+
partial = null;
|
|
2622
|
+
response = await openResponse({ locator, ...signal ? { signal } : {} });
|
|
2623
|
+
}
|
|
2624
|
+
if (partial && response.status === 206 && response.etag !== partial.validator) {
|
|
2625
|
+
await response.close();
|
|
2626
|
+
partial = null;
|
|
2627
|
+
response = await openResponse({ locator, ...signal ? { signal } : {} });
|
|
2628
|
+
cancelled2(signal);
|
|
2629
|
+
}
|
|
2630
|
+
let total = null;
|
|
2631
|
+
const length = integer4(response.contentLength);
|
|
2632
|
+
if (response.status === 206 && partial) {
|
|
2633
|
+
const match = /^bytes (\d+)-(\d+)\/(\d+)$/.exec(response.contentRange ?? "");
|
|
2634
|
+
if (!match)
|
|
2635
|
+
return fail3("invalid recording content range");
|
|
2636
|
+
const start = Number(match[1]);
|
|
2637
|
+
const end = Number(match[2]);
|
|
2638
|
+
const size2 = Number(match[3]);
|
|
2639
|
+
if (!Number.isSafeInteger(size2) || start !== partial.offset || end < start || end !== size2 - 1 || partial.total !== null && size2 !== partial.total || length !== null && length !== end - start + 1)
|
|
2640
|
+
fail3("recording range does not match its verified prefix");
|
|
2641
|
+
total = size2;
|
|
2642
|
+
} else if (response.status === 200) {
|
|
2643
|
+
partial = null;
|
|
2644
|
+
if (response.contentRange !== null)
|
|
2645
|
+
fail3("unexpected recording content range");
|
|
2646
|
+
total = length ?? expectedSize ?? null;
|
|
2647
|
+
} else
|
|
2648
|
+
fail3("recording transfer requires a complete response or validated range");
|
|
2649
|
+
if (total !== null && (total > maxBytes || expectedSize != null && total !== expectedSize))
|
|
2650
|
+
fail3("recording size does not match transfer limits");
|
|
2651
|
+
const writer = await storage.open(locator, {
|
|
2652
|
+
...partial ? { resume: partial } : {},
|
|
2653
|
+
validator: strongRecordingValidator(response.etag) ? response.etag : null,
|
|
2654
|
+
total
|
|
2655
|
+
});
|
|
2656
|
+
const resumedBytes = partial?.offset ?? 0;
|
|
2657
|
+
let size = resumedBytes;
|
|
2658
|
+
try {
|
|
2659
|
+
for await (const bytes of response.body) {
|
|
2660
|
+
cancelled2(signal);
|
|
2661
|
+
if (!(bytes instanceof Uint8Array) || bytes.byteLength > maxBytes - size || total !== null && bytes.byteLength > total - size)
|
|
2662
|
+
fail3("recording exceeds transfer size");
|
|
2663
|
+
await writer.write(bytes);
|
|
2664
|
+
size += bytes.byteLength;
|
|
2665
|
+
await writer.checkpoint();
|
|
2666
|
+
}
|
|
2667
|
+
cancelled2(signal);
|
|
2668
|
+
if (total !== null && size !== total || expectedSize != null && size !== expectedSize)
|
|
2669
|
+
fail3("recording body was truncated");
|
|
2670
|
+
return { ...receipt(await writer.finish(), size), resumedBytes };
|
|
2671
|
+
} finally {
|
|
2672
|
+
await writer.close();
|
|
2673
|
+
}
|
|
2674
|
+
} finally {
|
|
2675
|
+
await response.close();
|
|
2676
|
+
}
|
|
2677
|
+
}, "transferRecording");
|
|
2678
|
+
|
|
2679
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/related-history.js
|
|
2680
|
+
var validateMeetingRelatedHistory = /* @__PURE__ */ __name((original) => {
|
|
2681
|
+
if (!original || typeof original !== "object" || Array.isArray(original))
|
|
2682
|
+
throw new CliError("validation_error", "related history request is required");
|
|
2683
|
+
const input = { ...original };
|
|
2684
|
+
for (const field of Object.keys(input))
|
|
2685
|
+
if (!["accountId", "seriesId", "anchorIds", "after", "before", "limit", "maxReadBytes", "signal"].includes(field))
|
|
2686
|
+
throw new CliError("validation_error", `unknown related history field: ${field}`);
|
|
2687
|
+
const positive = /* @__PURE__ */ __name((value) => Number.isSafeInteger(value) && value > 0, "positive");
|
|
2688
|
+
if (!positive(input.accountId) || !positive(input.seriesId))
|
|
2689
|
+
throw new CliError("validation_error", "accountId and seriesId must be positive safe integers");
|
|
2690
|
+
if (!Array.isArray(input.anchorIds) || input.anchorIds.length > 20 || input.anchorIds.some((id4) => !positive(id4)))
|
|
2691
|
+
throw new CliError("validation_error", "anchorIds must contain at most 20 positive safe integers");
|
|
2692
|
+
for (const key of ["after", "before"])
|
|
2693
|
+
if (!Number.isSafeInteger(input[key]) || Math.abs(input[key]) > 864e13)
|
|
2694
|
+
throw new CliError("validation_error", `${key} must be an absolute timestamp`);
|
|
2695
|
+
if (input.after >= input.before)
|
|
2696
|
+
throw new CliError("validation_error", "after must precede before");
|
|
2697
|
+
const limit = input.limit === void 0 ? 5 : input.limit;
|
|
2698
|
+
const maxReadBytes = input.maxReadBytes === void 0 ? 262144 : input.maxReadBytes;
|
|
2699
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 20)
|
|
2700
|
+
throw new CliError("validation_error", "limit must be an integer from 1 to 20");
|
|
2701
|
+
if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4194304)
|
|
2702
|
+
throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
|
|
2703
|
+
if (input.signal !== void 0 && !(input.signal instanceof AbortSignal))
|
|
2704
|
+
throw new CliError("validation_error", "signal must be an AbortSignal");
|
|
2705
|
+
input.signal?.throwIfAborted();
|
|
2706
|
+
return { ...input, anchorIds: [...new Set(input.anchorIds)], limit, maxReadBytes };
|
|
2707
|
+
}, "validateMeetingRelatedHistory");
|
|
2708
|
+
|
|
2709
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/result-items.js
|
|
2710
|
+
var text8 = string();
|
|
2711
|
+
var identifier = pipe(text8, minLength(1));
|
|
2712
|
+
var nullableText2 = nullable(text8);
|
|
2713
|
+
var count5 = pipe(number(), integer(), minValue(0));
|
|
2714
|
+
var flag = boolean();
|
|
2715
|
+
var scope2 = strictObject({ provider: text8, account: text8 });
|
|
2716
|
+
var run = strictObject({
|
|
2717
|
+
meetings: count5,
|
|
2718
|
+
participants: count5,
|
|
2719
|
+
transcript_rows: count5,
|
|
2720
|
+
summaries: count5,
|
|
2721
|
+
warnings: array(strictObject({ external_id: text8, message: text8 })),
|
|
2722
|
+
timezone: optional(text8)
|
|
2723
|
+
});
|
|
2724
|
+
var exported = union([
|
|
2725
|
+
strictObject({ meeting_id: identifier, format: picklist(["markdown", "vtt"]), filename: text8, content: text8 }),
|
|
2726
|
+
strictObject({ meeting_id: identifier, format: picklist(["markdown", "vtt"]), output: text8 })
|
|
2727
|
+
]);
|
|
2728
|
+
var eventChange = strictObject({
|
|
2729
|
+
action: literal("event.link"),
|
|
2730
|
+
event_id: nullable(identifier),
|
|
2731
|
+
expected_event_id: optional(nullable(identifier))
|
|
2732
|
+
});
|
|
2733
|
+
var personChange = strictObject({
|
|
2734
|
+
action: literal("person.link"),
|
|
2735
|
+
participant_id: identifier,
|
|
2736
|
+
person_uid: text8,
|
|
2737
|
+
expected_person_uid: optional(nullableText2),
|
|
2738
|
+
target_account_ids: optional(array(identifier))
|
|
2739
|
+
});
|
|
2740
|
+
var eventResult = strictObject({
|
|
2741
|
+
meeting_id: identifier,
|
|
2742
|
+
event_id: nullable(identifier),
|
|
2743
|
+
previous_event_id: nullable(identifier),
|
|
2744
|
+
changed: flag
|
|
2745
|
+
});
|
|
2746
|
+
var personResult = strictObject({
|
|
2747
|
+
meeting_id: identifier,
|
|
2748
|
+
participant_id: identifier,
|
|
2749
|
+
person_uid: text8,
|
|
2750
|
+
previous_person_uid: nullableText2,
|
|
2751
|
+
changed: flag
|
|
2752
|
+
});
|
|
2753
|
+
var meetingChange = strictObject({
|
|
2754
|
+
scope: scope2,
|
|
2755
|
+
account_id: identifier,
|
|
2756
|
+
meeting_id: identifier,
|
|
2757
|
+
change: union([eventChange, personChange]),
|
|
2758
|
+
applied: flag,
|
|
2759
|
+
result: optional(union([eventResult, personResult]))
|
|
2760
|
+
});
|
|
2761
|
+
var recognition = strictObject({
|
|
2762
|
+
engine: text8,
|
|
2763
|
+
model: text8,
|
|
2764
|
+
version: optional(text8),
|
|
2765
|
+
timing: optional(picklist(["fixed-windows", "recognition-segments"]))
|
|
2766
|
+
});
|
|
2767
|
+
var transcription = union([
|
|
2768
|
+
strictObject({
|
|
2769
|
+
applied: literal(false),
|
|
2770
|
+
account_id: identifier,
|
|
2771
|
+
external_id: text8,
|
|
2772
|
+
segments: count5,
|
|
2773
|
+
media: strictObject({
|
|
2774
|
+
id: text8,
|
|
2775
|
+
content_hash: text8,
|
|
2776
|
+
size: count5,
|
|
2777
|
+
duration_ms: count5,
|
|
2778
|
+
format: text8,
|
|
2779
|
+
sample_rate: count5,
|
|
2780
|
+
channels: count5,
|
|
2781
|
+
recognition
|
|
2782
|
+
})
|
|
2783
|
+
}),
|
|
2784
|
+
strictObject({
|
|
2785
|
+
applied: literal(true),
|
|
2786
|
+
account_id: identifier,
|
|
2787
|
+
external_id: text8,
|
|
2788
|
+
meeting_id: identifier,
|
|
2789
|
+
created: flag,
|
|
2790
|
+
inserted_transcripts: count5,
|
|
2791
|
+
replayed_transcripts: count5,
|
|
2792
|
+
superseded_transcripts: count5,
|
|
2793
|
+
segments: count5,
|
|
2794
|
+
media_sha256: text8,
|
|
2795
|
+
engine: text8,
|
|
2796
|
+
model: text8,
|
|
2797
|
+
model_version: nullableText2,
|
|
2798
|
+
timing: picklist(["fixed-windows", "recognition-segments"])
|
|
2799
|
+
})
|
|
2800
|
+
]);
|
|
2801
|
+
var embeddingModel = strictObject({ key: text8, dims: count5, kind: picklist(["local", "remote"]), model: text8 });
|
|
2802
|
+
var embedding = union([
|
|
2803
|
+
strictObject({
|
|
2804
|
+
account_id: identifier,
|
|
2805
|
+
model: embeddingModel,
|
|
2806
|
+
status: strictObject({ chunks: count5, embedded: count5 }),
|
|
2807
|
+
applied: literal(false),
|
|
2808
|
+
scope: literal("existing-current-chunks"),
|
|
2809
|
+
rebuild_required: literal("explicit")
|
|
2810
|
+
}),
|
|
2811
|
+
strictObject({
|
|
2812
|
+
account_id: identifier,
|
|
2813
|
+
model: embeddingModel,
|
|
2814
|
+
saved: count5,
|
|
2815
|
+
skipped: count5,
|
|
2816
|
+
has_more: flag,
|
|
2817
|
+
next_hash: optional(text8),
|
|
2818
|
+
applied: literal(true),
|
|
2819
|
+
rebuild: strictObject({
|
|
2820
|
+
transcripts: count5,
|
|
2821
|
+
chunks: count5,
|
|
2822
|
+
has_more: flag,
|
|
2823
|
+
next_transcript_id: optional(identifier)
|
|
2824
|
+
})
|
|
2825
|
+
})
|
|
2826
|
+
]);
|
|
2827
|
+
var MEETING_RESULT_ENTITIES = {
|
|
2828
|
+
meeting_ingestion: run,
|
|
2829
|
+
meeting_export: exported,
|
|
2830
|
+
meeting_association: meetingChange,
|
|
2831
|
+
meeting_transcription: transcription,
|
|
2832
|
+
meeting_embedding: embedding
|
|
2833
|
+
};
|
|
2834
|
+
|
|
2835
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/review.js
|
|
2836
|
+
var REVIEW_LIMIT = { default: 50, most: 200 };
|
|
2837
|
+
|
|
2838
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/save-hints.js
|
|
2839
|
+
var SAVE_INSTRUCTION = "If this shows something worth keeping \u2014 a decision, a promise, a preference \u2014 and memo's server is connected, propose it with facts_add or memories_add, citing the msg: locator or meeting: reference. Otherwise skip this.";
|
|
2840
|
+
var SAVE_HELP = `Worth keeping \u2014 a decision, a promise, a preference? Record it with \`memo facts add\` or
|
|
2841
|
+
\`memo memories add\`, citing the msg: locator or meeting: reference as --evidence.`;
|
|
2842
|
+
|
|
2843
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/series-history.js
|
|
2844
|
+
var validateMeetingSeriesHistory = /* @__PURE__ */ __name((input) => {
|
|
2845
|
+
input.signal?.throwIfAborted();
|
|
2846
|
+
if (!Number.isSafeInteger(input.accountId) || input.accountId <= 0)
|
|
2847
|
+
throw new CliError("validation_error", "accountId must be a positive safe integer");
|
|
2848
|
+
if (typeof input.externalId !== "string" || !input.externalId.trim() || new TextEncoder().encode(input.externalId).length > 4096 || /[\0\r\n]/.test(input.externalId))
|
|
2849
|
+
throw new CliError("validation_error", "externalId must be a bounded nonempty series identifier");
|
|
2850
|
+
for (const name of ["after", "before"])
|
|
2851
|
+
if (!Number.isSafeInteger(input[name]) || Math.abs(input[name]) > 864e13)
|
|
2852
|
+
throw new CliError("validation_error", `${name} must be an absolute timestamp in milliseconds`);
|
|
2853
|
+
if (input.after >= input.before)
|
|
2854
|
+
throw new CliError("validation_error", "after must be earlier than before");
|
|
2855
|
+
const limit = input.limit === void 0 ? 20 : input.limit;
|
|
2856
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
2857
|
+
throw new CliError("validation_error", "limit must be an integer from 1 to 100");
|
|
2858
|
+
const maxReadBytes = input.maxReadBytes === void 0 ? 256 * 1024 : input.maxReadBytes;
|
|
2859
|
+
if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4 * 1024 * 1024)
|
|
2860
|
+
throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
|
|
2861
|
+
return { ...input, limit, maxReadBytes };
|
|
2862
|
+
}, "validateMeetingSeriesHistory");
|
|
2863
|
+
|
|
2864
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/series-inventory-validation.js
|
|
2865
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
2866
|
+
|
|
2867
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/upcoming-validation.js
|
|
2868
|
+
var invalid3 = /* @__PURE__ */ __name((field) => {
|
|
2869
|
+
throw new CliError("invalid_response", `meeting occurrence ${field} is invalid`);
|
|
2870
|
+
}, "invalid");
|
|
2871
|
+
var occurrenceTime = /* @__PURE__ */ __name((value) => typeof value === "number" && Number.isSafeInteger(value) && Math.abs(value) <= 864e13, "occurrenceTime");
|
|
2872
|
+
var occurrenceId = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim().length > 0 && value.length <= 1e3 && !/[\0\r\n]/.test(value), "occurrenceId");
|
|
2873
|
+
var readOccurrenceSchedule = /* @__PURE__ */ __name((input, meetingId, limit, maxReadBytes) => {
|
|
2874
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
2875
|
+
invalid3("schedule");
|
|
2876
|
+
for (const key of Object.keys(input))
|
|
2877
|
+
if (!["meetingId", "kind", "timezone", "occurrences", "complete", "missing"].includes(key))
|
|
2878
|
+
invalid3(key);
|
|
2879
|
+
if (input.meetingId !== meetingId)
|
|
2880
|
+
invalid3("meetingId");
|
|
2881
|
+
if (!["single", "recurring", "unscheduled", "unknown"].includes(input.kind))
|
|
2882
|
+
invalid3("kind");
|
|
2883
|
+
if (input.timezone !== null) {
|
|
2884
|
+
if (typeof input.timezone !== "string" || input.timezone.length > 100)
|
|
2885
|
+
invalid3("timezone");
|
|
2886
|
+
try {
|
|
2887
|
+
new Intl.DateTimeFormat("en", { timeZone: input.timezone }).format(0);
|
|
2888
|
+
} catch {
|
|
2889
|
+
invalid3("timezone");
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
if (typeof input.complete !== "boolean")
|
|
2893
|
+
invalid3("complete");
|
|
2894
|
+
if (!Array.isArray(input.missing) || input.missing.length > 2 || new Set(input.missing).size !== input.missing.length || input.missing.some((value) => !["schedule-details", "occurrence-details"].includes(value)) || input.complete && input.missing.length > 0)
|
|
2895
|
+
invalid3("missing");
|
|
2896
|
+
if (!Array.isArray(input.occurrences) || input.occurrences.length > limit)
|
|
2897
|
+
invalid3("occurrences");
|
|
2898
|
+
if (input.kind === "single" && input.occurrences.length > 1)
|
|
2899
|
+
invalid3("single occurrence count");
|
|
2900
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2901
|
+
const occurrences = input.occurrences.map((entry) => {
|
|
2902
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
2903
|
+
invalid3("entry");
|
|
2904
|
+
for (const key2 of Object.keys(entry))
|
|
2905
|
+
if (!["id", "startAt", "endAt", "status", "verified"].includes(key2))
|
|
2906
|
+
invalid3(key2);
|
|
2907
|
+
if (entry.id !== null && !occurrenceId(entry.id))
|
|
2908
|
+
invalid3("id");
|
|
2909
|
+
if (entry.startAt !== null && !occurrenceTime(entry.startAt))
|
|
2910
|
+
invalid3("startAt");
|
|
2911
|
+
if (entry.endAt !== null && (!occurrenceTime(entry.endAt) || entry.startAt === null || entry.endAt <= entry.startAt))
|
|
2912
|
+
invalid3("endAt");
|
|
2913
|
+
if (!["scheduled", "cancelled"].includes(entry.status) || typeof entry.verified !== "boolean")
|
|
2914
|
+
invalid3("status");
|
|
2915
|
+
if (entry.verified && (entry.startAt === null || !["single", "recurring"].includes(input.kind) || input.kind === "recurring" && entry.id === null))
|
|
2916
|
+
invalid3("verification");
|
|
2917
|
+
const key = entry.id ?? "single";
|
|
2918
|
+
if (seen.has(key))
|
|
2919
|
+
invalid3("duplicate id");
|
|
2920
|
+
seen.add(key);
|
|
2921
|
+
return { id: entry.id, startAt: entry.startAt, endAt: entry.endAt, status: entry.status, verified: entry.verified };
|
|
2922
|
+
});
|
|
2923
|
+
const result = {
|
|
2924
|
+
meetingId,
|
|
2925
|
+
kind: input.kind,
|
|
2926
|
+
timezone: input.timezone,
|
|
2927
|
+
occurrences,
|
|
2928
|
+
complete: input.complete,
|
|
2929
|
+
missing: [...input.missing]
|
|
2930
|
+
};
|
|
2931
|
+
if (new TextEncoder().encode(JSON.stringify(result)).byteLength > maxReadBytes)
|
|
2932
|
+
invalid3("maxReadBytes budget");
|
|
2933
|
+
return result;
|
|
2934
|
+
}, "readOccurrenceSchedule");
|
|
2935
|
+
|
|
2936
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/series-inventory-validation.js
|
|
2937
|
+
var inventoryHash = /* @__PURE__ */ __name((value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex"), "inventoryHash");
|
|
2938
|
+
var inventorySize = /* @__PURE__ */ __name((value) => Buffer.byteLength(JSON.stringify(value), "utf8"), "inventorySize");
|
|
2939
|
+
function invalid4(field, response = false) {
|
|
2940
|
+
throw new CliError(response ? "invalid_response" : "validation_error", `invalid meeting inventory ${field}`);
|
|
2941
|
+
}
|
|
2942
|
+
__name(invalid4, "invalid");
|
|
2943
|
+
var object2 = /* @__PURE__ */ __name((value, fields3, field, response = false) => {
|
|
2944
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
2945
|
+
invalid4(field, response);
|
|
2946
|
+
for (const key of Object.keys(value))
|
|
2947
|
+
if (!fields3.includes(key))
|
|
2948
|
+
invalid4(`${field}.${key}`, response);
|
|
2949
|
+
}, "object");
|
|
2950
|
+
var cursorDetails = /* @__PURE__ */ __name((value) => {
|
|
2951
|
+
if (typeof value !== "string" || value.length > 4096 || !/^[A-Za-z0-9_-]+$/.test(value))
|
|
2952
|
+
invalid4("cursor");
|
|
2953
|
+
try {
|
|
2954
|
+
const decoded = JSON.parse(new TextDecoder("utf8", { fatal: true }).decode(Buffer.from(value, "base64url")));
|
|
2955
|
+
object2(decoded, ["version", "selection", "cursor"], "cursor");
|
|
2956
|
+
if (decoded.version !== 1 || typeof decoded.selection !== "string" || !/^[a-f0-9]{64}$/.test(decoded.selection) || !occurrenceId(decoded.cursor))
|
|
2957
|
+
invalid4("cursor");
|
|
2958
|
+
return decoded;
|
|
2959
|
+
} catch {
|
|
2960
|
+
return invalid4("cursor");
|
|
2961
|
+
}
|
|
2962
|
+
}, "cursorDetails");
|
|
2963
|
+
var validateMeetingSeriesInventoryCursor = /* @__PURE__ */ __name((value) => {
|
|
2964
|
+
cursorDetails(value);
|
|
2965
|
+
}, "validateMeetingSeriesInventoryCursor");
|
|
2966
|
+
var inventoryRequest = /* @__PURE__ */ __name((scope3, input) => {
|
|
2967
|
+
object2(input, ["after", "until", "limit", "maxReadBytes", "bytes", "cursor", "signal"], "request");
|
|
2968
|
+
const { after, until, signal } = input;
|
|
2969
|
+
if (!occurrenceTime(after) || !occurrenceTime(until) || after >= until || until - after > 366 * 864e5)
|
|
2970
|
+
invalid4("after/until");
|
|
2971
|
+
const limits = { limit: input.limit ?? 100, maxReadBytes: input.maxReadBytes ?? 65536, bytes: input.bytes ?? 65536 };
|
|
2972
|
+
for (const [key, value] of Object.entries(limits))
|
|
2973
|
+
if (!Number.isSafeInteger(value) || value < (key === "bytes" ? 2048 : 1) || value > (key === "limit" ? 100 : 1048576))
|
|
2974
|
+
invalid4(key);
|
|
2975
|
+
if (signal !== void 0 && !(signal instanceof AbortSignal))
|
|
2976
|
+
invalid4("signal");
|
|
2977
|
+
const selection = inventoryHash({ scope: scope3, after, until });
|
|
2978
|
+
let cursor;
|
|
2979
|
+
if (input.cursor !== void 0) {
|
|
2980
|
+
const decoded = cursorDetails(input.cursor);
|
|
2981
|
+
if (decoded.selection !== selection)
|
|
2982
|
+
invalid4("cursor");
|
|
2983
|
+
cursor = decoded.cursor;
|
|
2984
|
+
}
|
|
2985
|
+
return { after, until, limits, signal, selection, cursor };
|
|
2986
|
+
}, "inventoryRequest");
|
|
2987
|
+
var inventoryCursor = /* @__PURE__ */ __name((selection, cursor) => {
|
|
2988
|
+
const encoded = Buffer.from(JSON.stringify({ version: 1, selection, cursor }), "utf8").toString("base64url");
|
|
2989
|
+
if (encoded.length > 4096)
|
|
2990
|
+
invalid4("nextCursor budget", true);
|
|
2991
|
+
return encoded;
|
|
2992
|
+
}, "inventoryCursor");
|
|
2993
|
+
var inventoryPage = /* @__PURE__ */ __name((scope3, request, page) => {
|
|
2994
|
+
object2(page, ["scope", "after", "until", "items", "nextCursor", "coverage"], "page", true);
|
|
2995
|
+
object2(page.scope, ["provider", "account"], "scope", true);
|
|
2996
|
+
if (page.scope.provider !== scope3.provider || page.scope.account !== scope3.account || page.after !== request.after || page.until !== request.until)
|
|
2997
|
+
invalid4("selection", true);
|
|
2998
|
+
object2(page.coverage, ["selection", "partial"], "coverage", true);
|
|
2999
|
+
if (!["provider-window", "provider-inventory"].includes(page.coverage.selection) || typeof page.coverage.partial !== "boolean")
|
|
3000
|
+
invalid4("coverage", true);
|
|
3001
|
+
if (page.nextCursor !== null && (!occurrenceId(page.nextCursor) || page.nextCursor === request.cursor))
|
|
3002
|
+
invalid4("nextCursor", true);
|
|
3003
|
+
if (!Array.isArray(page.items) || page.items.length > request.limits.limit)
|
|
3004
|
+
invalid4("items", true);
|
|
3005
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3006
|
+
const items = page.items.map((item) => {
|
|
3007
|
+
object2(item, ["meetingId", "title", "kind", "scheduledStartAt"], "item", true);
|
|
3008
|
+
if (!occurrenceId(item.meetingId) || seen.has(item.meetingId))
|
|
3009
|
+
invalid4("meetingId", true);
|
|
3010
|
+
seen.add(item.meetingId);
|
|
3011
|
+
if (item.title !== null && (typeof item.title !== "string" || item.title.length > 8192))
|
|
3012
|
+
invalid4("title", true);
|
|
3013
|
+
if (!["single", "recurring", "unscheduled", "unknown"].includes(item.kind))
|
|
3014
|
+
invalid4("kind", true);
|
|
3015
|
+
if (item.scheduledStartAt !== null && !occurrenceTime(item.scheduledStartAt))
|
|
3016
|
+
invalid4("scheduledStartAt", true);
|
|
3017
|
+
return { meetingId: item.meetingId, title: item.title, kind: item.kind, scheduledStartAt: item.scheduledStartAt };
|
|
3018
|
+
});
|
|
3019
|
+
if (inventorySize(page) > request.limits.maxReadBytes)
|
|
3020
|
+
invalid4("maxReadBytes budget", true);
|
|
3021
|
+
return { items, selection: page.coverage.selection, partial: page.coverage.partial, nextCursor: page.nextCursor };
|
|
3022
|
+
}, "inventoryPage");
|
|
3023
|
+
|
|
3024
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/series-inventory.js
|
|
3025
|
+
var cancelled3 = /* @__PURE__ */ __name((signal) => {
|
|
3026
|
+
if (signal?.aborted)
|
|
3027
|
+
throw new CliError("cancelled", "meeting inventory reading was cancelled");
|
|
3028
|
+
}, "cancelled");
|
|
3029
|
+
var createMeetingSeriesInventoryReader = /* @__PURE__ */ __name((scope3, port) => {
|
|
3030
|
+
const fixed = snapshotMeetingScope(scope3);
|
|
3031
|
+
if (typeof port?.read !== "function")
|
|
3032
|
+
throw new CliError("configuration_error", "bounded meeting inventory reader is required");
|
|
3033
|
+
const read = port.read.bind(port);
|
|
3034
|
+
return {
|
|
3035
|
+
scope: fixed,
|
|
3036
|
+
async page(input) {
|
|
3037
|
+
const request = inventoryRequest(fixed, input);
|
|
3038
|
+
const { after, until, limits, signal, cursor } = request;
|
|
3039
|
+
cancelled3(signal);
|
|
3040
|
+
const raw = await read(Object.freeze({
|
|
3041
|
+
scope: fixed,
|
|
3042
|
+
after,
|
|
3043
|
+
until,
|
|
3044
|
+
limit: limits.limit,
|
|
3045
|
+
maxReadBytes: limits.maxReadBytes,
|
|
3046
|
+
...cursor === void 0 ? {} : { cursor },
|
|
3047
|
+
...signal ? { signal } : {}
|
|
3048
|
+
}));
|
|
3049
|
+
cancelled3(signal);
|
|
3050
|
+
const page = inventoryPage(fixed, request, raw);
|
|
3051
|
+
const packet = {
|
|
3052
|
+
schemaVersion: 1,
|
|
3053
|
+
kind: "meeting_series_inventory",
|
|
3054
|
+
scope: fixed,
|
|
3055
|
+
after,
|
|
3056
|
+
until,
|
|
3057
|
+
items: page.items,
|
|
3058
|
+
nextCursor: page.nextCursor === null ? null : inventoryCursor(request.selection, page.nextCursor),
|
|
3059
|
+
limits,
|
|
3060
|
+
coverage: {
|
|
3061
|
+
selection: page.selection,
|
|
3062
|
+
sourcePartial: page.partial,
|
|
3063
|
+
hasMore: page.nextCursor !== null,
|
|
3064
|
+
undated: page.items.filter((item) => item.scheduledStartAt === null).length,
|
|
3065
|
+
dateHintsOutsideWindow: page.items.filter((item) => item.scheduledStartAt !== null && (item.scheduledStartAt < after || item.scheduledStartAt >= until)).length,
|
|
3066
|
+
calendarCompleteness: "unknown",
|
|
3067
|
+
occurrenceProof: "not-read",
|
|
3068
|
+
consistency: "live-provider-pages"
|
|
3069
|
+
}
|
|
3070
|
+
};
|
|
3071
|
+
const result = { ...packet, fingerprint: inventoryHash(packet) };
|
|
3072
|
+
if (inventorySize(result) > limits.bytes)
|
|
3073
|
+
throw new CliError("validation_error", "meeting inventory bytes cannot fit the provider page; increase bytes or lower limit");
|
|
3074
|
+
cancelled3(signal);
|
|
3075
|
+
return result;
|
|
3076
|
+
}
|
|
3077
|
+
};
|
|
3078
|
+
}, "createMeetingSeriesInventoryReader");
|
|
3079
|
+
|
|
3080
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/stats.js
|
|
3081
|
+
var zoneOf = /* @__PURE__ */ __name((timeZone) => {
|
|
3082
|
+
const zone = timeZone ?? "UTC";
|
|
3083
|
+
try {
|
|
3084
|
+
new Intl.DateTimeFormat("en", { timeZone: zone });
|
|
3085
|
+
} catch {
|
|
3086
|
+
throw new CliError("validation_error", "expected an IANA time zone such as Europe/Madrid");
|
|
3087
|
+
}
|
|
3088
|
+
return zone;
|
|
3089
|
+
}, "zoneOf");
|
|
3090
|
+
var DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
3091
|
+
var weekStart = /* @__PURE__ */ __name((at, format) => {
|
|
3092
|
+
const parts = Object.fromEntries(format.formatToParts(new Date(at)).map((part) => [part.type, part.value]));
|
|
3093
|
+
const day2 = Date.UTC(Number(parts.year), Number(parts.month) - 1, Number(parts.day));
|
|
3094
|
+
return new Date(day2 - DAYS.indexOf(parts.weekday ?? "Mon") * 864e5).toISOString().slice(0, 10);
|
|
3095
|
+
}, "weekStart");
|
|
3096
|
+
var UNKNOWN_SPEAKER = "unknown";
|
|
3097
|
+
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");
|
|
3098
|
+
var aggregateMeetingStats = /* @__PURE__ */ __name((rows, timeZone) => {
|
|
3099
|
+
const zone = zoneOf(timeZone);
|
|
3100
|
+
const format = new Intl.DateTimeFormat("en-US", {
|
|
3101
|
+
timeZone: zone,
|
|
3102
|
+
year: "numeric",
|
|
3103
|
+
month: "2-digit",
|
|
3104
|
+
day: "2-digit",
|
|
3105
|
+
weekday: "short"
|
|
3106
|
+
});
|
|
3107
|
+
const speakers = /* @__PURE__ */ new Map();
|
|
3108
|
+
const weeks = /* @__PURE__ */ new Map();
|
|
3109
|
+
const meetings = /* @__PURE__ */ new Set();
|
|
3110
|
+
let lines = 0;
|
|
3111
|
+
let words2 = 0;
|
|
3112
|
+
let talkMs = 0;
|
|
3113
|
+
for (const row of rows) {
|
|
3114
|
+
const talk = Math.max(0, row.endMs - row.startMs);
|
|
3115
|
+
meetings.add(row.meetingId);
|
|
3116
|
+
lines += 1;
|
|
3117
|
+
words2 += row.words;
|
|
3118
|
+
talkMs += talk;
|
|
3119
|
+
const who = speakerOf(row);
|
|
3120
|
+
const held = speakers.get(who.key) ?? {
|
|
3121
|
+
key: who.key,
|
|
3122
|
+
name: who.name ?? null,
|
|
3123
|
+
personId: row.personId,
|
|
3124
|
+
identityId: row.personId === null ? row.identityId : null,
|
|
3125
|
+
meetings: 0,
|
|
3126
|
+
lines: 0,
|
|
3127
|
+
words: 0,
|
|
3128
|
+
talkMs: 0,
|
|
3129
|
+
share: 0,
|
|
3130
|
+
seen: /* @__PURE__ */ new Set()
|
|
3131
|
+
};
|
|
3132
|
+
held.seen.add(row.meetingId);
|
|
3133
|
+
held.lines += 1;
|
|
3134
|
+
held.words += row.words;
|
|
3135
|
+
held.talkMs += talk;
|
|
3136
|
+
speakers.set(who.key, held);
|
|
3137
|
+
if (row.startedAt !== null) {
|
|
3138
|
+
const week = weeks.get(weekStart(row.startedAt, format)) ?? { meetings: /* @__PURE__ */ new Set(), talkMs: 0 };
|
|
3139
|
+
week.meetings.add(row.meetingId);
|
|
3140
|
+
week.talkMs += talk;
|
|
3141
|
+
weeks.set(weekStart(row.startedAt, format), week);
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
return {
|
|
3145
|
+
timeZone: zone,
|
|
3146
|
+
meetings: meetings.size,
|
|
3147
|
+
lines,
|
|
3148
|
+
words: words2,
|
|
3149
|
+
talkMs,
|
|
3150
|
+
speakers: [...speakers.values()].map(({ seen, ...speaker }) => ({
|
|
3151
|
+
...speaker,
|
|
3152
|
+
meetings: seen.size,
|
|
3153
|
+
share: talkMs === 0 ? 0 : Math.round(speaker.talkMs / talkMs * 1e3) / 1e3
|
|
3154
|
+
})).sort((a, b) => b.talkMs - a.talkMs || a.key.localeCompare(b.key)),
|
|
3155
|
+
weeks: [...weeks.entries()].map(([start, week]) => ({ weekStart: start, meetings: week.meetings.size, talkMs: week.talkMs })).sort((a, b) => a.weekStart.localeCompare(b.weekStart))
|
|
3156
|
+
};
|
|
3157
|
+
}, "aggregateMeetingStats");
|
|
3158
|
+
|
|
3159
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/transcription.js
|
|
3160
|
+
var bounded = /* @__PURE__ */ __name((value, max, name) => {
|
|
3161
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > max)
|
|
3162
|
+
throw new CliError("validation_error", `${name} must be an integer from 1 to ${max}`);
|
|
3163
|
+
return value;
|
|
3164
|
+
}, "bounded");
|
|
3165
|
+
var identifier2 = /* @__PURE__ */ __name((value) => {
|
|
3166
|
+
if (typeof value !== "string" || !value.trim() || value.length > 1e3 || /[\0\r\n]/.test(value))
|
|
3167
|
+
throw new CliError("validation_error", "transcription identifiers must be bounded nonempty strings");
|
|
3168
|
+
return value;
|
|
3169
|
+
}, "identifier");
|
|
3170
|
+
var cancelled4 = /* @__PURE__ */ __name((signal) => {
|
|
3171
|
+
if (signal?.aborted) {
|
|
3172
|
+
if (signal.reason instanceof CliError)
|
|
3173
|
+
throw signal.reason;
|
|
3174
|
+
const timeout = signal.reason instanceof Error && signal.reason.name === "TimeoutError";
|
|
3175
|
+
throw new CliError(timeout ? "timeout" : "cancelled", "meeting transcription was interrupted");
|
|
3176
|
+
}
|
|
3177
|
+
}, "cancelled");
|
|
3178
|
+
var transcribeMeeting = /* @__PURE__ */ __name(async (source, store, target, options = {}) => {
|
|
3179
|
+
const accountId = bounded(target.accountId, Number.MAX_SAFE_INTEGER, "account ID");
|
|
3180
|
+
const externalId = identifier2(target.externalId);
|
|
3181
|
+
const now = target.now;
|
|
3182
|
+
const mutation = { apply: options.apply, dryRun: options.dryRun, signal: options.signal };
|
|
3183
|
+
if (!Number.isSafeInteger(now) || now < 0)
|
|
3184
|
+
throw new CliError("validation_error", "invalid transcription timestamp");
|
|
3185
|
+
const context3 = Object.freeze({
|
|
3186
|
+
maxBytes: bounded(options.maxBytes ?? 1024 ** 3, 4 * 1024 ** 3, "media byte limit"),
|
|
3187
|
+
maxDurationMs: bounded(options.maxDurationMs ?? 4 * 36e5, 24 * 36e5, "media duration limit"),
|
|
3188
|
+
...options.signal ? { signal: options.signal } : {}
|
|
3189
|
+
});
|
|
3190
|
+
const maxSegments = bounded(options.maxSegments ?? 1e4, 1e5, "segment limit");
|
|
3191
|
+
const maxTextBytes = bounded(options.maxTextBytes ?? 4 * 1024 ** 2, 64 * 1024 ** 2, "transcript byte limit");
|
|
3192
|
+
cancelled4(context3.signal);
|
|
3193
|
+
const raw = await source.describe(context3);
|
|
3194
|
+
cancelled4(context3.signal);
|
|
3195
|
+
const recognition2 = raw.recognition;
|
|
3196
|
+
const engine = recognition2.engine;
|
|
3197
|
+
const model = recognition2.model;
|
|
3198
|
+
const version = recognition2.version;
|
|
3199
|
+
const timing = recognition2.timing ?? "recognition-segments";
|
|
3200
|
+
if (timing !== "fixed-windows" && timing !== "recognition-segments")
|
|
3201
|
+
throw new CliError("invalid_response", "unsupported recognition timing");
|
|
3202
|
+
const media = Object.freeze({
|
|
3203
|
+
id: identifier2(raw.id),
|
|
3204
|
+
contentHash: raw.contentHash,
|
|
3205
|
+
size: bounded(raw.size, context3.maxBytes, "media size"),
|
|
3206
|
+
durationMs: bounded(raw.durationMs, context3.maxDurationMs, "media duration"),
|
|
3207
|
+
format: identifier2(raw.format),
|
|
3208
|
+
sampleRate: bounded(raw.sampleRate, 384e3, "sample rate"),
|
|
3209
|
+
channels: bounded(raw.channels, 32, "channel count"),
|
|
3210
|
+
recognition: Object.freeze({
|
|
3211
|
+
engine: identifier2(engine),
|
|
3212
|
+
model: identifier2(model),
|
|
3213
|
+
...version === void 0 ? {} : { version: identifier2(version) },
|
|
3214
|
+
timing
|
|
3215
|
+
})
|
|
3216
|
+
});
|
|
3217
|
+
if (!/^[a-f0-9]{64}$/.test(media.contentHash))
|
|
3218
|
+
throw new CliError("invalid_response", "media needs a SHA-256 content hash");
|
|
3219
|
+
const outcome = await dispatchMeetingMutation(mutation, async () => {
|
|
3220
|
+
const rows = [];
|
|
3221
|
+
let textBytes = 0;
|
|
3222
|
+
let end = 0;
|
|
3223
|
+
let provided = 0;
|
|
3224
|
+
for await (const segment of source.segments(media, context3)) {
|
|
3225
|
+
cancelled4(context3.signal);
|
|
3226
|
+
provided++;
|
|
3227
|
+
if (provided > maxSegments || !Number.isSafeInteger(segment.startMs) || !Number.isSafeInteger(segment.endMs) || segment.startMs < end || segment.endMs <= segment.startMs || segment.endMs > media.durationMs || typeof segment.text !== "string" || segment.text.includes("\0"))
|
|
3228
|
+
throw new CliError("invalid_response", "invalid or excessive recognition segments");
|
|
3229
|
+
end = segment.endMs;
|
|
3230
|
+
const text9 = segment.text.trim();
|
|
3231
|
+
if (text9.length > maxTextBytes - textBytes)
|
|
3232
|
+
throw new CliError("validation_error", "transcript exceeds its byte limit");
|
|
3233
|
+
textBytes += new TextEncoder().encode(text9).byteLength;
|
|
3234
|
+
if (textBytes > maxTextBytes)
|
|
3235
|
+
throw new CliError("validation_error", "transcript exceeds its byte limit");
|
|
3236
|
+
if (text9)
|
|
3237
|
+
rows.push({
|
|
3238
|
+
position: rows.length,
|
|
3239
|
+
startMs: segment.startMs,
|
|
3240
|
+
endMs: segment.endMs,
|
|
3241
|
+
speakerName: null,
|
|
3242
|
+
text: text9,
|
|
3243
|
+
normalizedText: null,
|
|
3244
|
+
metadata: null
|
|
3245
|
+
});
|
|
3246
|
+
}
|
|
3247
|
+
cancelled4(context3.signal);
|
|
3248
|
+
if (!rows.length)
|
|
3249
|
+
throw new CliError("not_found", "no speech was recognized");
|
|
3250
|
+
const provenance = {
|
|
3251
|
+
mediaSha256: media.contentHash,
|
|
3252
|
+
engine: media.recognition.engine,
|
|
3253
|
+
model: media.recognition.model,
|
|
3254
|
+
modelVersion: media.recognition.version ?? null,
|
|
3255
|
+
timing: media.recognition.timing
|
|
3256
|
+
};
|
|
3257
|
+
const hash = await contentHash(JSON.stringify({ provenance, rows }));
|
|
3258
|
+
cancelled4(context3.signal);
|
|
3259
|
+
const append = await store.appendTranscriptsWithReceipt({
|
|
3260
|
+
accountId,
|
|
3261
|
+
externalId,
|
|
3262
|
+
now,
|
|
3263
|
+
transcripts: [
|
|
3264
|
+
{
|
|
3265
|
+
source: `local/${encodeURIComponent(media.recognition.engine)}/${encodeURIComponent(media.recognition.model)}`,
|
|
3266
|
+
format: "local-transcription",
|
|
3267
|
+
language: null,
|
|
3268
|
+
contentHash: hash,
|
|
3269
|
+
externalCreatedAt: null,
|
|
3270
|
+
metadata: provenance,
|
|
3271
|
+
deletedAt: null,
|
|
3272
|
+
rows
|
|
3273
|
+
}
|
|
3274
|
+
]
|
|
3275
|
+
});
|
|
3276
|
+
let valid = false;
|
|
3277
|
+
try {
|
|
3278
|
+
const meeting2 = append?.meeting?.meeting;
|
|
3279
|
+
valid = meeting2?.accountId === accountId && meeting2.externalId === externalId && meeting2.deletedAt === null && Number.isSafeInteger(meeting2.id) && meeting2.id > 0 && append.created === false && [append.insertedTranscripts, append.replayedTranscripts, append.supersededTranscripts].every((count6) => Number.isSafeInteger(count6) && count6 >= 0) && append.insertedTranscripts + append.replayedTranscripts === 1;
|
|
3280
|
+
} catch {
|
|
3281
|
+
valid = false;
|
|
3282
|
+
}
|
|
3283
|
+
if (!valid)
|
|
3284
|
+
throw new CliError("outcome_unknown", "transcription append acknowledgement is invalid; verify stored state before retrying");
|
|
3285
|
+
return { append, segments: rows.length };
|
|
3286
|
+
});
|
|
3287
|
+
return {
|
|
3288
|
+
media,
|
|
3289
|
+
accountId,
|
|
3290
|
+
externalId,
|
|
3291
|
+
applied: outcome.applied,
|
|
3292
|
+
segments: outcome.value?.segments ?? 0,
|
|
3293
|
+
...outcome.value ? { append: outcome.value.append } : {}
|
|
3294
|
+
};
|
|
3295
|
+
}, "transcribeMeeting");
|
|
3296
|
+
|
|
3297
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/upcoming.js
|
|
3298
|
+
var cancelled5 = /* @__PURE__ */ __name((signal) => {
|
|
3299
|
+
if (!signal?.aborted)
|
|
3300
|
+
return;
|
|
3301
|
+
if (signal.reason instanceof CliError)
|
|
3302
|
+
throw signal.reason;
|
|
3303
|
+
const timeout = signal.reason instanceof Error && signal.reason.name === "TimeoutError";
|
|
3304
|
+
throw new CliError(timeout ? "timeout" : "cancelled", "meeting occurrence read was interrupted");
|
|
3305
|
+
}, "cancelled");
|
|
3306
|
+
var createUpcomingMeetingReader = /* @__PURE__ */ __name((scope3, port) => {
|
|
3307
|
+
const fixed = snapshotMeetingScope(scope3);
|
|
3308
|
+
if (typeof port?.read !== "function")
|
|
3309
|
+
throw new CliError("configuration_error", "meeting occurrence reader is required");
|
|
3310
|
+
const read = port.read.bind(port);
|
|
3311
|
+
return {
|
|
3312
|
+
scope: fixed,
|
|
3313
|
+
async next(meetingId, request) {
|
|
3314
|
+
if (!occurrenceId(meetingId))
|
|
3315
|
+
throw new CliError("validation_error", "meetingId must be a bounded identifier");
|
|
3316
|
+
if (!request || typeof request !== "object" || Array.isArray(request))
|
|
3317
|
+
throw new CliError("validation_error", "meeting occurrence request is required");
|
|
3318
|
+
for (const key of Object.keys(request))
|
|
3319
|
+
if (!["after", "until", "limit", "maxReadBytes", "signal"].includes(key))
|
|
3320
|
+
throw new CliError("validation_error", `unknown meeting occurrence field: ${key}`);
|
|
3321
|
+
const { after, until, signal } = request;
|
|
3322
|
+
if (signal !== void 0 && !(signal instanceof AbortSignal))
|
|
3323
|
+
throw new CliError("validation_error", "signal must be an AbortSignal");
|
|
3324
|
+
if (!occurrenceTime(after) || !occurrenceTime(until) || after >= until)
|
|
3325
|
+
throw new CliError("validation_error", "after and until must form an increasing absolute millisecond window");
|
|
3326
|
+
const limit = request.limit ?? 100;
|
|
3327
|
+
const maxReadBytes = request.maxReadBytes ?? 1048576;
|
|
3328
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e3)
|
|
3329
|
+
throw new CliError("validation_error", "limit must be an integer from 1 to 1000");
|
|
3330
|
+
if (!Number.isSafeInteger(maxReadBytes) || maxReadBytes < 1 || maxReadBytes > 4194304)
|
|
3331
|
+
throw new CliError("validation_error", "maxReadBytes must be an integer from 1 to 4194304");
|
|
3332
|
+
cancelled5(signal);
|
|
3333
|
+
const context3 = Object.freeze({ scope: fixed, after, until, limit, maxReadBytes, ...signal ? { signal } : {} });
|
|
3334
|
+
const raw = await read(meetingId, context3);
|
|
3335
|
+
cancelled5(signal);
|
|
3336
|
+
const schedule = readOccurrenceSchedule(raw, meetingId, limit, maxReadBytes);
|
|
3337
|
+
const active = schedule.occurrences.filter((entry) => entry.status !== "cancelled");
|
|
3338
|
+
const eligible = active.filter((entry) => entry.startAt !== null && entry.startAt >= after && entry.startAt < until);
|
|
3339
|
+
eligible.sort((a, b) => a.startAt - b.startAt || ((a.id ?? "") < (b.id ?? "") ? -1 : 1));
|
|
3340
|
+
const candidate = eligible[0] ?? null;
|
|
3341
|
+
const undated = active.filter((entry) => entry.startAt === null).length;
|
|
3342
|
+
const unverified = active.filter((entry) => !entry.verified).length;
|
|
3343
|
+
const simultaneous = candidate === null ? 0 : eligible.filter((entry) => entry.startAt === candidate.startAt).length;
|
|
3344
|
+
return {
|
|
3345
|
+
scope: fixed,
|
|
3346
|
+
meetingId,
|
|
3347
|
+
kind: schedule.kind,
|
|
3348
|
+
after,
|
|
3349
|
+
until,
|
|
3350
|
+
timezone: schedule.timezone,
|
|
3351
|
+
candidate,
|
|
3352
|
+
verifiedNext: Boolean(candidate?.verified && schedule.complete && unverified === 0 && simultaneous === 1),
|
|
3353
|
+
coverage: {
|
|
3354
|
+
scheduleComplete: schedule.complete,
|
|
3355
|
+
inspected: schedule.occurrences.length,
|
|
3356
|
+
undated,
|
|
3357
|
+
unverified,
|
|
3358
|
+
cancelled: schedule.occurrences.length - active.length,
|
|
3359
|
+
simultaneous,
|
|
3360
|
+
missing: schedule.missing
|
|
3361
|
+
}
|
|
3362
|
+
};
|
|
3363
|
+
}
|
|
3364
|
+
};
|
|
3365
|
+
}, "createUpcomingMeetingReader");
|
|
3366
|
+
|
|
3367
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.473.0_@wirecat+cli-base@0.65.0_commander@15.0.0_esbuild@0.28.2_type_39633e3162553a2c86dde989a9811fcb/node_modules/@wirecat/cli-core/dist/meetings/watch.js
|
|
3368
|
+
var sleep = /* @__PURE__ */ __name((milliseconds, signal) => new Promise((resolve) => {
|
|
3369
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
3370
|
+
clearTimeout(timer);
|
|
3371
|
+
signal.removeEventListener("abort", finish);
|
|
3372
|
+
resolve();
|
|
3373
|
+
}, "finish");
|
|
3374
|
+
const timer = setTimeout(finish, milliseconds);
|
|
3375
|
+
signal.addEventListener("abort", finish, { once: true });
|
|
3376
|
+
}), "sleep");
|
|
3377
|
+
var isCancellation = /* @__PURE__ */ __name((error, signal) => {
|
|
3378
|
+
if (!signal.aborted)
|
|
3379
|
+
return false;
|
|
3380
|
+
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string")
|
|
3381
|
+
return error.code === "cancelled" || error.code === "timeout" || error.code === "ABORT_ERR";
|
|
3382
|
+
return error === signal.reason || error instanceof DOMException && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
3383
|
+
}, "isCancellation");
|
|
3384
|
+
async function* watchMeetingIngestion(ingest, options) {
|
|
3385
|
+
if (!Number.isSafeInteger(options.intervalMs) || options.intervalMs < 1e3 || options.intervalMs > 864e5)
|
|
3386
|
+
throw new MeetingError("validation_error", "watch interval must be an integer from 1000 to 86400000 milliseconds");
|
|
3387
|
+
const wait = options.sleep ?? sleep;
|
|
3388
|
+
while (!options.signal.aborted) {
|
|
3389
|
+
let report;
|
|
3390
|
+
try {
|
|
3391
|
+
report = await ingest(options.signal);
|
|
3392
|
+
} catch (error) {
|
|
3393
|
+
if (isCancellation(error, options.signal))
|
|
3394
|
+
return;
|
|
3395
|
+
throw error;
|
|
3396
|
+
}
|
|
3397
|
+
yield report;
|
|
3398
|
+
if (options.signal.aborted)
|
|
3399
|
+
return;
|
|
3400
|
+
try {
|
|
3401
|
+
await wait(options.intervalMs, options.signal);
|
|
3402
|
+
} catch (error) {
|
|
3403
|
+
if (isCancellation(error, options.signal))
|
|
3404
|
+
return;
|
|
3405
|
+
throw error;
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
__name(watchMeetingIngestion, "watchMeetingIngestion");
|
|
3410
|
+
|
|
3411
|
+
export {
|
|
3412
|
+
formatMeetingReference,
|
|
3413
|
+
parseMeetingReference,
|
|
3414
|
+
canonicalMeetingReference,
|
|
3415
|
+
MEETING_ISSUES,
|
|
3416
|
+
meetingIssuesOf,
|
|
3417
|
+
meeting,
|
|
3418
|
+
meetingItem,
|
|
3419
|
+
MEETING_QUERY,
|
|
3420
|
+
meetingHit,
|
|
3421
|
+
meetingTranscript,
|
|
3422
|
+
meetingSummary,
|
|
3423
|
+
meetingDetails,
|
|
3424
|
+
MEETING_STEPS,
|
|
3425
|
+
meetingHitsList,
|
|
3426
|
+
joinKeyOf,
|
|
3427
|
+
joinUrlWithoutQuery,
|
|
3428
|
+
withoutLinkQueries,
|
|
3429
|
+
calendarText,
|
|
3430
|
+
ENTRY_METADATA_KEYS,
|
|
3431
|
+
entryMetadata,
|
|
3432
|
+
meetingCueFingerprint,
|
|
3433
|
+
EVENT_QUERY,
|
|
3434
|
+
linkEvent,
|
|
3435
|
+
normalizeMeetingParticipantQuery,
|
|
3436
|
+
validateMeetingParticipantSearch,
|
|
3437
|
+
MeetingError,
|
|
3438
|
+
listed,
|
|
3439
|
+
meetingPeople,
|
|
3440
|
+
meetingsList,
|
|
3441
|
+
meetingsQuery,
|
|
3442
|
+
MEETING_QUERY_GUIDE,
|
|
3443
|
+
meetingDetailsAnswer,
|
|
3444
|
+
meetingTranscriptAnswer,
|
|
3445
|
+
meetingSummaryAnswer,
|
|
3446
|
+
serializeVtt,
|
|
3447
|
+
exportMeeting,
|
|
3448
|
+
snapshotMeetingScope,
|
|
3449
|
+
validateMeetingChange,
|
|
3450
|
+
dispatchMeetingMutation,
|
|
3451
|
+
createMeetingManagement,
|
|
3452
|
+
MEETING_FACT_TYPES,
|
|
3453
|
+
validateMeetingContextChange,
|
|
3454
|
+
createMeetingContext,
|
|
3455
|
+
findingHash,
|
|
3456
|
+
validateFindings,
|
|
3457
|
+
findingFingerprint,
|
|
3458
|
+
MEETING_FINDINGS_KIND,
|
|
3459
|
+
validateMeetingFindings,
|
|
3460
|
+
meetingFindingFingerprint,
|
|
3461
|
+
MEETING_HIT_QUERY,
|
|
3462
|
+
liftMeetingFields,
|
|
3463
|
+
parseMeetingQuery,
|
|
3464
|
+
meetingWordsQuery,
|
|
3465
|
+
TranscriptTextError,
|
|
3466
|
+
parseTranscriptText,
|
|
3467
|
+
VttError,
|
|
3468
|
+
parseVtt,
|
|
3469
|
+
importFiles,
|
|
3470
|
+
CHAT_MESSAGES_READ,
|
|
3471
|
+
meetingHitContextLimits,
|
|
3472
|
+
validateMeetingPassage,
|
|
3473
|
+
validateMeetingPreparationContext,
|
|
3474
|
+
meetingProjectEvidence,
|
|
3475
|
+
meetingProjectEvidenceAnswer,
|
|
3476
|
+
validateMeetingHitSearch,
|
|
3477
|
+
MEETING_PROJECT_EVIDENCE_QUERY,
|
|
3478
|
+
prepareMeetingProjectEvidence,
|
|
3479
|
+
readMeetingProjectEvidence,
|
|
3480
|
+
pull,
|
|
3481
|
+
meetingReview,
|
|
3482
|
+
meetingReviewItem,
|
|
3483
|
+
meetingLink,
|
|
3484
|
+
meetingLinkItem,
|
|
3485
|
+
meetingSpeaker,
|
|
3486
|
+
meetingSpeakerItem,
|
|
3487
|
+
meetingStats,
|
|
3488
|
+
meetingStatsItem,
|
|
3489
|
+
meetingParticipants,
|
|
3490
|
+
meetingPassage,
|
|
3491
|
+
event,
|
|
3492
|
+
eventItem,
|
|
3493
|
+
RecordingSyncError,
|
|
3494
|
+
recordingWindows,
|
|
3495
|
+
recordingAssetFingerprint,
|
|
3496
|
+
parseRecordingSyncCheckpoint,
|
|
3497
|
+
syncRecordingArchive,
|
|
3498
|
+
planRecordingArchiveSchedule,
|
|
3499
|
+
parseRecordingArchiveSchedule,
|
|
3500
|
+
recordingArchiveScheduleWindow,
|
|
3501
|
+
installRecordingArchiveSchedule,
|
|
3502
|
+
RecordingTransferError,
|
|
3503
|
+
strongRecordingValidator,
|
|
3504
|
+
transferRecording,
|
|
3505
|
+
validateMeetingRelatedHistory,
|
|
3506
|
+
MEETING_RESULT_ENTITIES,
|
|
3507
|
+
REVIEW_LIMIT,
|
|
3508
|
+
SAVE_INSTRUCTION,
|
|
3509
|
+
SAVE_HELP,
|
|
3510
|
+
validateMeetingSeriesHistory,
|
|
3511
|
+
validateMeetingSeriesInventoryCursor,
|
|
3512
|
+
createMeetingSeriesInventoryReader,
|
|
3513
|
+
aggregateMeetingStats,
|
|
3514
|
+
transcribeMeeting,
|
|
3515
|
+
createUpcomingMeetingReader,
|
|
3516
|
+
watchMeetingIngestion
|
|
3517
|
+
};
|