@wirecat/zoom-cli 0.22.1 → 0.23.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/dist/answer-policy.d.ts +9 -0
- package/dist/answer-policy.d.ts.map +1 -1
- package/dist/answer-policy.js +30 -0
- package/dist/answer-policy.js.map +1 -1
- package/dist/api.d.ts +0 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +44 -77
- package/dist/api.js.map +1 -1
- package/dist/archive-commands.d.ts +2 -1
- package/dist/archive-commands.d.ts.map +1 -1
- package/dist/archive-commands.js.map +1 -1
- package/dist/archive-transcripts.d.ts +1 -1
- package/dist/archive-transcripts.d.ts.map +1 -1
- package/dist/archive-transcripts.js +1 -1
- package/dist/archive-transcripts.js.map +1 -1
- package/dist/bin/main.js +5 -6
- package/dist/bin/main.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/meeting-preparation-mcp.d.ts +86 -0
- package/dist/meeting-preparation-mcp.d.ts.map +1 -1
- package/dist/meeting-project-evidence-mcp.d.ts +1 -1
- package/dist/meeting-project-evidence-mcp.d.ts.map +1 -1
- package/dist/meeting-source.d.ts +15 -0
- package/dist/meeting-source.d.ts.map +1 -0
- package/dist/meeting-source.js +56 -0
- package/dist/meeting-source.js.map +1 -0
- package/dist/program.d.ts +4 -31
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +53 -510
- package/dist/program.js.map +1 -1
- package/dist/recording-archive.d.ts +1 -28
- package/dist/recording-archive.d.ts.map +1 -1
- package/dist/recording-archive.js +15 -248
- package/dist/recording-archive.js.map +1 -1
- package/dist/recording-manifest.d.ts +49 -0
- package/dist/recording-manifest.d.ts.map +1 -0
- package/dist/recording-manifest.js +183 -0
- package/dist/recording-manifest.js.map +1 -0
- package/dist/recording-promotion-store.d.ts +1 -1
- package/dist/recording-promotion-store.d.ts.map +1 -1
- package/dist/recording-schedule-setup.d.ts +16 -0
- package/dist/recording-schedule-setup.d.ts.map +1 -0
- package/dist/recording-schedule-setup.js +60 -0
- package/dist/recording-schedule-setup.js.map +1 -0
- package/dist/recording-schedule-store.d.ts.map +1 -1
- package/dist/recording-schedule-store.js +10 -24
- package/dist/recording-schedule-store.js.map +1 -1
- package/dist/recording-schedule-systemd.d.ts.map +1 -1
- package/dist/recording-schedule-systemd.js +2 -20
- package/dist/recording-schedule-systemd.js.map +1 -1
- package/dist/recording-sync-store.d.ts.map +1 -1
- package/dist/recording-sync-store.js +9 -23
- package/dist/recording-sync-store.js.map +1 -1
- package/dist/recordings.d.ts +4 -2
- package/dist/recordings.d.ts.map +1 -1
- package/dist/recordings.js +2 -1
- package/dist/recordings.js.map +1 -1
- package/dist/remote-http.d.ts +12 -0
- package/dist/remote-http.d.ts.map +1 -1
- package/dist/remote-http.js +43 -0
- package/dist/remote-http.js.map +1 -1
- package/dist/setup-commands.d.ts +26 -0
- package/dist/setup-commands.d.ts.map +1 -0
- package/dist/setup-commands.js +124 -0
- package/dist/setup-commands.js.map +1 -0
- package/dist/store-commands.d.ts +26 -0
- package/dist/store-commands.d.ts.map +1 -0
- package/dist/store-commands.js +130 -0
- package/dist/store-commands.js.map +1 -0
- package/dist/store-connection.d.ts +31 -1
- package/dist/store-connection.d.ts.map +1 -1
- package/dist/store-connection.js +30 -2
- package/dist/store-connection.js.map +1 -1
- package/dist/watch-service.d.ts +20 -0
- package/dist/watch-service.d.ts.map +1 -0
- package/dist/watch-service.js +148 -0
- package/dist/watch-service.js.map +1 -0
- package/package.json +3 -3
- package/skills/zoom-cli/SKILL.md +11 -2
package/dist/program.js
CHANGED
|
@@ -1,63 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { CliError, createDeadline, createOutputBuffer, createRenderer, errorObjectOf, errorRecordOf, exitCodeOfError, isCliError, projectFields, realSleep, renderError, } from "@wirecat/cli-base";
|
|
1
|
+
import { CliError, createDeadline, createOutputBuffer, createRenderer, isCliError, projectFields, } from "@wirecat/cli-base";
|
|
4
2
|
import { metaOf } from "@wirecat/cli-base/commands";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { addMeetingCommands, addMeetingPassageCommand } from "@wirecat/cli-core/meetings/cli";
|
|
3
|
+
import { checkJson, snakeKeys } from "@wirecat/cli-core/cli";
|
|
4
|
+
import { addMeetingCommands } from "@wirecat/cli-core/meetings/cli";
|
|
8
5
|
import { Command, CommanderError } from "commander";
|
|
9
6
|
import { addZoomSkillCommands } from "./agent-skill.js";
|
|
10
7
|
import { bodyOf, renderBody, wholeList } from "./answer-output.js";
|
|
11
|
-
import { hostFailureContext } from "./answer-policy.js";
|
|
12
|
-
import { ZoomApiSource } from "./api.js";
|
|
8
|
+
import { commandSelection, hostFailureContext, reportFailure } from "./answer-policy.js";
|
|
13
9
|
import { addArchiveCommands, } from "./archive-commands.js";
|
|
14
|
-
import { applyArchiveImport, preflightArchiveImport } from "./archive-import.js";
|
|
15
10
|
import { readArchiveTranscripts, searchArchiveTranscripts } from "./archive-transcripts.js";
|
|
16
|
-
import {
|
|
17
|
-
import { profileAccountKey, readConfig
|
|
11
|
+
import { annotateMeetingCommands } from "./commands.js";
|
|
12
|
+
import { profileAccountKey, readConfig } from "./config.js";
|
|
18
13
|
import { checkCancelled } from "./errors.js";
|
|
19
14
|
import { bytes, duration, resetCliOptions, startExecution } from "./execution.js";
|
|
20
|
-
import {
|
|
21
|
-
import { addIngestionSearchCommands } from "./ingestion-search-commands.js";
|
|
15
|
+
import { importFile, readDownloadedFiles, validateDownloadedFiles } from "./files.js";
|
|
22
16
|
import { liftJsonFields } from "./json-fields.js";
|
|
23
|
-
import { addLocalTranscriptionCommands } from "./local-transcription-commands.js";
|
|
24
|
-
import { login } from "./login.js";
|
|
25
|
-
import { addMeetingContextCommands } from "./meeting-context-commands.js";
|
|
26
|
-
import { addMeetingIntegrationCommands } from "./meeting-integration-commands.js";
|
|
27
17
|
import { addZoomMcpCommand } from "./meeting-mcp-command.js";
|
|
28
|
-
import {
|
|
29
|
-
import { addMeetingSearchCommands } from "./meeting-search-commands.js";
|
|
30
|
-
import { addMeetingEmbeddingCommand } from "./meeting-semantic-commands.js";
|
|
31
|
-
import { createRecordingScheduleService } from "./recording-schedule.js";
|
|
18
|
+
import { configuredMeetingSource } from "./meeting-source.js";
|
|
32
19
|
import { addRecordingScheduleCommands } from "./recording-schedule-commands.js";
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import { getZoomProfile, inspectArchive, inspectArchiveLocks, recoverArchiveLocks, verifyArchive, ZoomRecordings, } from "./recordings.js";
|
|
20
|
+
import { zoomRecordingSchedule } from "./recording-schedule-setup.js";
|
|
21
|
+
import { inspectArchive, inspectArchiveLocks, recoverArchiveLocks, verifyArchive, ZoomRecordings, } from "./recordings.js";
|
|
36
22
|
import { ZoomRemoteMeetings } from "./remote-meetings.js";
|
|
23
|
+
import { addConfigCommands, addSessionCommands } from "./setup-commands.js";
|
|
24
|
+
import { addStoreCommands } from "./store-commands.js";
|
|
25
|
+
import { connectSelectedProfile, storeUnavailable, unavailableStore, } from "./store-connection.js";
|
|
37
26
|
import { emitReceipt } from "./streaming.js";
|
|
38
|
-
import { TokenManager } from "./tokens.js";
|
|
39
|
-
import { runUnifiedSearch } from "./unified-search.js";
|
|
40
27
|
import { VERSION } from "./version.js";
|
|
41
28
|
import { addWatchCommand } from "./watch-commands.js";
|
|
42
|
-
|
|
43
|
-
throw new CliError("configuration_error", "the shared SQLite meeting store is not available yet");
|
|
44
|
-
};
|
|
45
|
-
const unavailableStore = {
|
|
46
|
-
saveMeeting: unavailable,
|
|
47
|
-
account: unavailable,
|
|
48
|
-
meetings: unavailable,
|
|
49
|
-
meeting: unavailable,
|
|
50
|
-
participants: unavailable,
|
|
51
|
-
search: unavailable,
|
|
52
|
-
events: unavailable,
|
|
53
|
-
eventCandidates: unavailable,
|
|
54
|
-
createEvent: unavailable,
|
|
55
|
-
createEventSeries: unavailable,
|
|
56
|
-
setEventSeries: unavailable,
|
|
57
|
-
linkMeeting: unavailable,
|
|
58
|
-
cursor: unavailable,
|
|
59
|
-
setCursor: unavailable,
|
|
60
|
-
};
|
|
29
|
+
import { createWatchService } from "./watch-service.js";
|
|
61
30
|
const answerExitCodes = new WeakMap();
|
|
62
31
|
export const createProgram = (deps) => {
|
|
63
32
|
let config;
|
|
@@ -107,12 +76,10 @@ export const createProgram = (deps) => {
|
|
|
107
76
|
};
|
|
108
77
|
const openStore = async (intent) => {
|
|
109
78
|
if (!deps.connectStore)
|
|
110
|
-
return
|
|
79
|
+
return storeUnavailable();
|
|
111
80
|
const profile = getConfig().accountProfile;
|
|
112
|
-
if (!profile)
|
|
113
|
-
throw new CliError("configuration_error", "select a local profile with zm config set account.profile <label>");
|
|
114
81
|
try {
|
|
115
|
-
return await deps.connectStore
|
|
82
|
+
return await connectSelectedProfile(deps.connectStore, profile, intent);
|
|
116
83
|
}
|
|
117
84
|
catch (error) {
|
|
118
85
|
if (isCliError(error))
|
|
@@ -189,64 +156,14 @@ export const createProgram = (deps) => {
|
|
|
189
156
|
}
|
|
190
157
|
output(wholeList("list", items));
|
|
191
158
|
};
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
});
|
|
199
|
-
cfg
|
|
200
|
-
.command("set")
|
|
201
|
-
.description("set a configuration value")
|
|
202
|
-
.argument("<key>", "setting name, such as account.profile")
|
|
203
|
-
.argument("<value>", "new value")
|
|
204
|
-
.action((key, value) => {
|
|
205
|
-
output(itemOf(setConfig(deps.configPath, key, value)));
|
|
159
|
+
addConfigCommands(program, { configPath: deps.configPath, getConfig, output });
|
|
160
|
+
const configured = configuredMeetingSource({
|
|
161
|
+
deps,
|
|
162
|
+
getConfig,
|
|
163
|
+
tokens,
|
|
164
|
+
fetch: () => fetchWithSignal(deps.fetch),
|
|
206
165
|
});
|
|
207
|
-
|
|
208
|
-
const getSource = () => {
|
|
209
|
-
if (deps.source)
|
|
210
|
-
return Promise.resolve(deps.source);
|
|
211
|
-
activeSource ??= (async () => {
|
|
212
|
-
const config = getConfig();
|
|
213
|
-
if (config.source === "api")
|
|
214
|
-
return new ZoomApiSource(tokens(), fetchWithSignal(deps.fetch));
|
|
215
|
-
if (!config.filesFolder)
|
|
216
|
-
throw new CliError("configuration_error", "set files.folder before pulling from files");
|
|
217
|
-
return new FilesSource(await (deps.readFiles ?? readDownloadedFiles)(config.filesFolder), config.filesTimezone);
|
|
218
|
-
})();
|
|
219
|
-
return activeSource;
|
|
220
|
-
};
|
|
221
|
-
const source = {
|
|
222
|
-
get provider() {
|
|
223
|
-
return deps.source?.provider ?? "zoom";
|
|
224
|
-
},
|
|
225
|
-
get name() {
|
|
226
|
-
return deps.source?.name ?? (getConfig().source === "api" ? "api" : "file");
|
|
227
|
-
},
|
|
228
|
-
get transcriptFormat() {
|
|
229
|
-
return deps.source ? deps.source.transcriptFormat : "vtt";
|
|
230
|
-
},
|
|
231
|
-
async meetings(since) {
|
|
232
|
-
return (await getSource()).meetings(since);
|
|
233
|
-
},
|
|
234
|
-
async participants(id) {
|
|
235
|
-
return (await getSource()).participants(id);
|
|
236
|
-
},
|
|
237
|
-
async transcript(id) {
|
|
238
|
-
return (await getSource()).transcript(id);
|
|
239
|
-
},
|
|
240
|
-
async chat(id) {
|
|
241
|
-
return (await getSource()).chat(id);
|
|
242
|
-
},
|
|
243
|
-
async summary(id) {
|
|
244
|
-
return (await getSource()).summary(id);
|
|
245
|
-
},
|
|
246
|
-
async files(id) {
|
|
247
|
-
return (await getSource()).files(id);
|
|
248
|
-
},
|
|
249
|
-
};
|
|
166
|
+
const source = configured.source;
|
|
250
167
|
const meetingCommands = {
|
|
251
168
|
get store() {
|
|
252
169
|
return guardedStore(selectedStore ?? unavailableStore);
|
|
@@ -274,104 +191,28 @@ export const createProgram = (deps) => {
|
|
|
274
191
|
const leaves = (command) => command.commands.length ? command.commands.flatMap(leaves) : [command];
|
|
275
192
|
// The meeting reads cli-core mounts read the store opened before their action; zoom's own commands open it lazily.
|
|
276
193
|
const storeCommands = new Set(program.commands.filter((group) => !before.has(group)).flatMap(leaves));
|
|
277
|
-
|
|
194
|
+
addSessionCommands(program, {
|
|
195
|
+
deps,
|
|
196
|
+
getConfig,
|
|
278
197
|
output,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
color: false,
|
|
282
|
-
streams: { data: (text) => buffer(`${text}\n`), diagnostic: deps.diagnostic },
|
|
283
|
-
}).result(value),
|
|
198
|
+
buffer,
|
|
199
|
+
formatOf,
|
|
284
200
|
fields: () => fields,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
config = getConfig();
|
|
290
|
-
}
|
|
291
|
-
catch (error) {
|
|
292
|
-
if (!isCliError(error))
|
|
293
|
-
throw error;
|
|
294
|
-
return {
|
|
295
|
-
version: VERSION,
|
|
296
|
-
runtime: { node: process.versions.node },
|
|
297
|
-
config: { readable: false, path: deps.configPath, error: error.message },
|
|
298
|
-
dataProfile: null,
|
|
299
|
-
authentication: { configured: null, state: "not_checked" },
|
|
300
|
-
database: "not_checked",
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
return {
|
|
304
|
-
version: VERSION,
|
|
305
|
-
runtime: { node: process.versions.node },
|
|
306
|
-
config: { readable: true, path: deps.configPath, source: config.source },
|
|
307
|
-
dataProfile: config.accountProfile,
|
|
308
|
-
authentication: { configured: config.clientId !== null, state: "not_checked" },
|
|
309
|
-
database: "not_checked",
|
|
310
|
-
};
|
|
311
|
-
},
|
|
312
|
-
sessionStatus: async (check) => {
|
|
313
|
-
const config = getConfig();
|
|
314
|
-
if (!config.clientId)
|
|
315
|
-
return { configured: false, state: "not_configured", dataProfile: config.accountProfile, verified: false };
|
|
316
|
-
if (check) {
|
|
317
|
-
if (program.opts().offline)
|
|
318
|
-
throw new CliError("configuration_error", "session verification requires network access; remove --offline");
|
|
319
|
-
api();
|
|
320
|
-
return {
|
|
321
|
-
configured: true,
|
|
322
|
-
state: "verified",
|
|
323
|
-
dataProfile: config.accountProfile,
|
|
324
|
-
verified: true,
|
|
325
|
-
profile: await (deps.checkSession
|
|
326
|
-
? deps.checkSession({ signal: signal() })
|
|
327
|
-
: getZoomProfile(tokens(), fetchWithSignal(deps.fetch), { signal: signal() })),
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
const saved = deps.tokens.load();
|
|
331
|
-
return {
|
|
332
|
-
configured: true,
|
|
333
|
-
state: saved ? (saved.expiresAt > (deps.now?.() ?? Date.now()) ? "saved" : "expired") : "missing",
|
|
334
|
-
dataProfile: config.accountProfile,
|
|
335
|
-
verified: false,
|
|
336
|
-
...(saved ? { expiresAt: saved.expiresAt, scopes: saved.scopes } : {}),
|
|
337
|
-
};
|
|
338
|
-
},
|
|
339
|
-
});
|
|
340
|
-
const session = program.commands.find((command) => command.name() === "session");
|
|
341
|
-
if (!session)
|
|
342
|
-
throw new CliError("configuration_error", "session command group is unavailable");
|
|
343
|
-
session
|
|
344
|
-
.command("start")
|
|
345
|
-
.description("log in to Zoom through your browser")
|
|
346
|
-
.option("--browser <program>", "browser program")
|
|
347
|
-
.action(async (opts) => {
|
|
348
|
-
const config = getConfig();
|
|
349
|
-
if (!config.clientId)
|
|
350
|
-
throw new CliError("configuration_error", "run zm config set zoom.client_id <Public Client ID> first");
|
|
351
|
-
const globals = program.opts();
|
|
352
|
-
if (globals.offline)
|
|
353
|
-
throw new CliError("configuration_error", "login requires network access; remove --offline");
|
|
354
|
-
const headless = deps.interactive === false ||
|
|
355
|
-
Boolean(deps.env?.CI) ||
|
|
356
|
-
(deps.interactive !== undefined &&
|
|
357
|
-
(globals.json || globals.jsonl || deps.outputIsTTY === false) &&
|
|
358
|
-
!globals.interactive);
|
|
359
|
-
if (globals.input === false || headless)
|
|
360
|
-
throw new CliError("configuration_error", "login requires browser approval; remove --no-input");
|
|
361
|
-
output(itemOf(await login({
|
|
362
|
-
tokens: tokens(),
|
|
363
|
-
signal: signal(),
|
|
364
|
-
openBrowser: (url) => deps.openBrowser(url, opts.browser),
|
|
365
|
-
readPaste: deps.readPaste,
|
|
366
|
-
showUrl: (url) => {
|
|
367
|
-
if (!program.opts().quiet)
|
|
368
|
-
deps.diagnostic(`Open this URL to approve Zoom login:\n${url}\n`);
|
|
369
|
-
},
|
|
370
|
-
})));
|
|
201
|
+
api,
|
|
202
|
+
tokens,
|
|
203
|
+
fetch: () => fetchWithSignal(deps.fetch),
|
|
204
|
+
signal,
|
|
371
205
|
});
|
|
372
|
-
let watchConfig;
|
|
373
|
-
let watchSince;
|
|
374
206
|
const watchSleep = deps.sleep;
|
|
207
|
+
const watch = createWatchService({
|
|
208
|
+
deps,
|
|
209
|
+
getConfig,
|
|
210
|
+
tokens,
|
|
211
|
+
fetch: () => fetchWithSignal(deps.fetch),
|
|
212
|
+
offline: () => Boolean(program.opts().offline),
|
|
213
|
+
openStore,
|
|
214
|
+
guardedStore,
|
|
215
|
+
});
|
|
375
216
|
const receipt = async (body) => {
|
|
376
217
|
const text = rendered(body);
|
|
377
218
|
const operation = signal();
|
|
@@ -393,136 +234,8 @@ export const createProgram = (deps) => {
|
|
|
393
234
|
receipt,
|
|
394
235
|
outputIsTTY: deps.outputIsTTY,
|
|
395
236
|
sleep: watchSleep ? (ms, abort) => watchSleep(ms, abort, "retry") : undefined,
|
|
396
|
-
prepare:
|
|
397
|
-
|
|
398
|
-
const source = target ?? config.source;
|
|
399
|
-
const plan = {
|
|
400
|
-
source,
|
|
401
|
-
since: flags.sinceTime,
|
|
402
|
-
lookbackDays: flags.lookbackDays ?? 0,
|
|
403
|
-
intervalMs: flags.pause,
|
|
404
|
-
folder: folder ?? config.filesFolder ?? undefined,
|
|
405
|
-
};
|
|
406
|
-
if (source === "files") {
|
|
407
|
-
if (flags.sinceTime !== undefined || flags.lookbackDays !== undefined)
|
|
408
|
-
throw new CliError("validation_error", "--since-time and --lookback-days apply only to API watching");
|
|
409
|
-
if (!plan.folder?.trim())
|
|
410
|
-
throw new CliError("configuration_error", "set files.folder or provide a folder for file watching");
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
if (folder !== undefined)
|
|
414
|
-
throw new CliError("validation_error", "API watching does not accept a folder");
|
|
415
|
-
if (program.opts().offline)
|
|
416
|
-
throw new CliError("configuration_error", "API watching requires network access; remove --offline");
|
|
417
|
-
if (!deps.source) {
|
|
418
|
-
if (!config.clientId)
|
|
419
|
-
throw new CliError("configuration_error", "run zm config set zoom.client_id <Public Client ID> first");
|
|
420
|
-
if (tokens().options.clientId !== config.clientId)
|
|
421
|
-
throw new CliError("configuration_error", "the OAuth client changed before watch started; retry with matching configuration");
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
if (!deps.store && !config.accountProfile)
|
|
425
|
-
throw new CliError("configuration_error", "select a local profile with zm config set account.profile <label>");
|
|
426
|
-
watchConfig = config;
|
|
427
|
-
watchSince = plan.since;
|
|
428
|
-
return plan;
|
|
429
|
-
},
|
|
430
|
-
ingest: async (plan, operation) => {
|
|
431
|
-
checkCancelled(operation);
|
|
432
|
-
const config = watchConfig;
|
|
433
|
-
if (!config)
|
|
434
|
-
throw new CliError("configuration_error", "watch configuration is unavailable");
|
|
435
|
-
let cycle;
|
|
436
|
-
let failure;
|
|
437
|
-
let result;
|
|
438
|
-
try {
|
|
439
|
-
if (!deps.store)
|
|
440
|
-
cycle = await openStore("ingestion");
|
|
441
|
-
checkCancelled(operation);
|
|
442
|
-
const accountId = cycle?.accountId ?? deps.accountId;
|
|
443
|
-
if (!Number.isSafeInteger(accountId) || !accountId || accountId < 1)
|
|
444
|
-
throw new CliError("configuration_error", "the selected meeting account is unavailable");
|
|
445
|
-
const store = guardedStore(cycle?.store ?? deps.store ?? unavailableStore);
|
|
446
|
-
if (plan.source === "files") {
|
|
447
|
-
const files = validateDownloadedFiles(await (deps.readFiles ?? readDownloadedFiles)(plan.folder ?? ""), config.filesTimezone);
|
|
448
|
-
checkCancelled(operation);
|
|
449
|
-
result = await importFiles(files.map((file) => importFile(file, accountId, config.filesTimezone)), store, deps.now?.());
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
const original = deps.source ??
|
|
453
|
-
new ZoomApiSource(tokens(), fetchWithSignal(deps.fetch), {
|
|
454
|
-
now: deps.now,
|
|
455
|
-
sleep: (ms, abort) => (deps.sleep ?? realSleep)(ms, AbortSignal.any([operation, abort]), "retry"),
|
|
456
|
-
});
|
|
457
|
-
let sourceFailure;
|
|
458
|
-
const source = new Proxy(original, {
|
|
459
|
-
get(target, key, receiver) {
|
|
460
|
-
const method = Reflect.get(target, key, receiver);
|
|
461
|
-
return typeof method === "function"
|
|
462
|
-
? async (...args) => {
|
|
463
|
-
if (sourceFailure)
|
|
464
|
-
throw sourceFailure;
|
|
465
|
-
checkCancelled(operation);
|
|
466
|
-
try {
|
|
467
|
-
const value = await method.apply(target, args);
|
|
468
|
-
checkCancelled(operation);
|
|
469
|
-
return value;
|
|
470
|
-
}
|
|
471
|
-
catch (error) {
|
|
472
|
-
if (isCliError(error) && error.code === "outcome_unknown") {
|
|
473
|
-
sourceFailure = error;
|
|
474
|
-
throw error;
|
|
475
|
-
}
|
|
476
|
-
checkCancelled(operation);
|
|
477
|
-
throw error;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
: method;
|
|
481
|
-
},
|
|
482
|
-
});
|
|
483
|
-
let cursorAdvanced = false;
|
|
484
|
-
const trackingStore = new Proxy(store, {
|
|
485
|
-
get(target, key, receiver) {
|
|
486
|
-
if (key === "setCursor")
|
|
487
|
-
return async (...args) => {
|
|
488
|
-
await target.setCursor(...args);
|
|
489
|
-
cursorAdvanced = true;
|
|
490
|
-
};
|
|
491
|
-
return Reflect.get(target, key, receiver);
|
|
492
|
-
},
|
|
493
|
-
});
|
|
494
|
-
result = await pull(source, trackingStore, {
|
|
495
|
-
accountId,
|
|
496
|
-
since: watchSince,
|
|
497
|
-
lookbackMs: plan.lookbackDays * 86400000,
|
|
498
|
-
now: deps.now?.(),
|
|
499
|
-
});
|
|
500
|
-
if (sourceFailure)
|
|
501
|
-
throw sourceFailure;
|
|
502
|
-
checkCancelled(operation);
|
|
503
|
-
if (cursorAdvanced)
|
|
504
|
-
watchSince = undefined;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
catch (error) {
|
|
508
|
-
failure = error;
|
|
509
|
-
}
|
|
510
|
-
finally {
|
|
511
|
-
if (cycle) {
|
|
512
|
-
try {
|
|
513
|
-
await cycle.close();
|
|
514
|
-
}
|
|
515
|
-
catch {
|
|
516
|
-
failure ??= new CliError("configuration_error", "could not close the shared meeting store");
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
if (failure)
|
|
521
|
-
throw failure;
|
|
522
|
-
if (!result)
|
|
523
|
-
return unavailable();
|
|
524
|
-
return result;
|
|
525
|
-
},
|
|
237
|
+
prepare: watch.prepare,
|
|
238
|
+
ingest: watch.ingest,
|
|
526
239
|
});
|
|
527
240
|
const retrySleep = deps.sleep;
|
|
528
241
|
const remoteOptions = {
|
|
@@ -551,52 +264,8 @@ export const createProgram = (deps) => {
|
|
|
551
264
|
recover: recoverArchiveLocks,
|
|
552
265
|
},
|
|
553
266
|
});
|
|
554
|
-
let recordingSchedule = deps.recordingSchedule;
|
|
555
267
|
addRecordingScheduleCommands(program, {
|
|
556
|
-
|
|
557
|
-
if (!recordingSchedule) {
|
|
558
|
-
const env = deps.env ?? process.env;
|
|
559
|
-
const configDir = dirname(deps.configPath);
|
|
560
|
-
recordingSchedule = createRecordingScheduleService({
|
|
561
|
-
store: fileRecordingScheduleStore(join(configDir, "recording-schedules")),
|
|
562
|
-
backend: createSystemdRecordingArchiveScheduler({
|
|
563
|
-
unitDirectory: join(env.XDG_CONFIG_HOME ?? join(env.HOME ?? homedir(), ".config"), "systemd", "user"),
|
|
564
|
-
}),
|
|
565
|
-
recordings: (job) => {
|
|
566
|
-
const selected = readConfig(deps.configPath);
|
|
567
|
-
if (dirname(deps.configPath) !== job.capture.configDir ||
|
|
568
|
-
selected.accountProfile !== job.capture.profile ||
|
|
569
|
-
selected.clientId !== job.capture.clientId)
|
|
570
|
-
throw new CliError("configuration_error", "archive schedule requires its saved profile and Zoom client id; select those settings before running");
|
|
571
|
-
return new ZoomRecordings(new TokenManager({
|
|
572
|
-
clientId: job.capture.clientId,
|
|
573
|
-
keyring: deps.tokens.options.keyring,
|
|
574
|
-
service: `zoom-cli:${job.capture.configDir}`,
|
|
575
|
-
fetch: fetchWithSignal(deps.tokens.options.fetch),
|
|
576
|
-
now: deps.now,
|
|
577
|
-
signal: signal(),
|
|
578
|
-
log: deps.tokens.options.log,
|
|
579
|
-
}), fetchWithSignal(deps.fetch), remoteOptions);
|
|
580
|
-
},
|
|
581
|
-
now: deps.now,
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
return recordingSchedule;
|
|
585
|
-
},
|
|
586
|
-
capture: () => {
|
|
587
|
-
const selected = getConfig();
|
|
588
|
-
if (!selected.accountProfile || !selected.clientId)
|
|
589
|
-
throw new CliError("configuration_error", "archive schedules require a configured local profile and Zoom client id");
|
|
590
|
-
if (!deps.recordingScheduleTarget)
|
|
591
|
-
throw new CliError("configuration_error", "archive scheduler requires an explicit runtime and CLI path");
|
|
592
|
-
return {
|
|
593
|
-
profile: selected.accountProfile,
|
|
594
|
-
clientId: selected.clientId,
|
|
595
|
-
configDir: dirname(deps.configPath),
|
|
596
|
-
runtime: deps.recordingScheduleTarget.runtime,
|
|
597
|
-
cliPath: deps.recordingScheduleTarget.cliPath,
|
|
598
|
-
};
|
|
599
|
-
},
|
|
268
|
+
...zoomRecordingSchedule({ deps, getConfig, withSignal: fetchWithSignal, signal, remoteOptions }),
|
|
600
269
|
offline: () => Boolean(program.opts().offline),
|
|
601
270
|
signal,
|
|
602
271
|
output,
|
|
@@ -629,120 +298,23 @@ export const createProgram = (deps) => {
|
|
|
629
298
|
remoteOptions,
|
|
630
299
|
};
|
|
631
300
|
addZoomMcpCommand(program, { fields: () => fields, signal, serve: deps.serveMcp, preparation: preparationOptions });
|
|
632
|
-
|
|
301
|
+
addStoreCommands(program, {
|
|
302
|
+
deps,
|
|
303
|
+
connected,
|
|
304
|
+
openStore,
|
|
305
|
+
preparation: preparationOptions,
|
|
633
306
|
signal,
|
|
634
307
|
output,
|
|
635
308
|
outputItems,
|
|
636
309
|
receipt,
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
if (plan.occurrences === 0)
|
|
640
|
-
return;
|
|
641
|
-
const connection = await connected("ingestion");
|
|
642
|
-
for await (const item of applyArchiveImport(plan, connection, {
|
|
643
|
-
accountId: connection.accountId,
|
|
644
|
-
now: deps.now?.(),
|
|
645
|
-
signal: signal(),
|
|
646
|
-
}))
|
|
647
|
-
yield item;
|
|
648
|
-
},
|
|
649
|
-
search: async (request) => runUnifiedSearch((await connected()).unifiedSearch, request),
|
|
650
|
-
});
|
|
651
|
-
addMeetingReadBindings(program, {
|
|
652
|
-
project: {
|
|
653
|
-
read: async (project, request) => (await connected()).meetingProjectEvidence(project, request),
|
|
654
|
-
signal,
|
|
655
|
-
now: deps.now,
|
|
656
|
-
output: (value) => output(bodyOf(value)),
|
|
657
|
-
},
|
|
658
|
-
preparation: {
|
|
659
|
-
...preparationOptions,
|
|
660
|
-
connect: () => openStore("read"),
|
|
661
|
-
},
|
|
662
|
-
});
|
|
663
|
-
addMeetingIntegrationCommands(program, {
|
|
664
|
-
signal,
|
|
665
|
-
output,
|
|
666
|
-
receipt,
|
|
667
|
-
integration: async () => (await connected()).meetingIntegration,
|
|
668
|
-
});
|
|
669
|
-
addLocalTranscriptionCommands(program, {
|
|
670
|
-
signal,
|
|
671
|
-
output,
|
|
672
|
-
receipt,
|
|
673
|
-
capabilities: async () => (await connected()).meetingTranscription,
|
|
674
|
-
});
|
|
675
|
-
const meetingContext = async () => (await connected()).meetingContext;
|
|
676
|
-
addMeetingContextCommands(program, {
|
|
677
|
-
signal,
|
|
678
|
-
output,
|
|
679
|
-
context: meetingContext,
|
|
680
|
-
});
|
|
681
|
-
addMeetingPassageCommand(program, {
|
|
682
|
-
signal,
|
|
683
|
-
read: async (reference, options) => {
|
|
684
|
-
if (fields && options.format !== "json")
|
|
685
|
-
throw new CliError("validation_error", "passage field selection requires --json or --format json");
|
|
686
|
-
return (await meetingContext()).passage(reference, options);
|
|
687
|
-
},
|
|
688
|
-
output: (result, format) => {
|
|
689
|
-
if (format === "json")
|
|
690
|
-
buffer(rendered(bodyOf(result.packet), program.opts().jsonl ? "jsonl" : "json"));
|
|
691
|
-
else
|
|
692
|
-
buffer(result.content);
|
|
693
|
-
},
|
|
694
|
-
});
|
|
695
|
-
const meetingSemantic = async () => (await connected()).meetingSemantic;
|
|
696
|
-
addMeetingSearchCommands(program, {
|
|
697
|
-
signal,
|
|
698
|
-
offline: () => Boolean(program.opts().offline),
|
|
699
|
-
output,
|
|
700
|
-
words: async () => (await connected()).meetingSearch,
|
|
701
|
-
meaning: meetingSemantic,
|
|
702
|
-
archive: (deps.archiveTranscripts ?? { search: searchArchiveTranscripts }).search,
|
|
703
|
-
});
|
|
704
|
-
addMeetingEmbeddingCommand(program, {
|
|
705
|
-
signal,
|
|
706
|
-
offline: () => Boolean(program.opts().offline),
|
|
707
|
-
receipt,
|
|
708
|
-
output,
|
|
709
|
-
capabilities: meetingSemantic,
|
|
710
|
-
});
|
|
711
|
-
const batchReader = async () => {
|
|
712
|
-
const reader = (await connected()).meetingBatch;
|
|
713
|
-
if (!reader)
|
|
714
|
-
throw new CliError("configuration_error", "the selected store connector does not support meeting batches");
|
|
715
|
-
return reader;
|
|
716
|
-
};
|
|
717
|
-
addMeetingBatchCommand(program, {
|
|
718
|
-
signal,
|
|
310
|
+
buffer,
|
|
311
|
+
rendered,
|
|
719
312
|
fields: () => fields,
|
|
720
313
|
meta: () => {
|
|
721
314
|
if (!execution)
|
|
722
315
|
throw new CliError("configuration_error", "command execution is not initialized");
|
|
723
316
|
return execution.meta();
|
|
724
317
|
},
|
|
725
|
-
input: async (path, signal) => {
|
|
726
|
-
if (!deps.readBatchInput)
|
|
727
|
-
throw new CliError("configuration_error", "batch input reader is unavailable");
|
|
728
|
-
return deps.readBatchInput(path, signal);
|
|
729
|
-
},
|
|
730
|
-
reader: {
|
|
731
|
-
index: async (options) => (await batchReader()).index(options),
|
|
732
|
-
search: async (query, options) => (await batchReader()).search(query, options),
|
|
733
|
-
passage: async (reference, options) => (await batchReader()).passage(reference, options),
|
|
734
|
-
},
|
|
735
|
-
output: (body, report, format) => {
|
|
736
|
-
const text = format === "json"
|
|
737
|
-
? rendered(body, program.opts().jsonl ? "jsonl" : "json", false)
|
|
738
|
-
: formatMeetingBatch(report, format);
|
|
739
|
-
if (Buffer.byteLength(text, "utf8") > 4194304)
|
|
740
|
-
throw new CliError("invalid_response", "batch rendered output exceeds 4194304 bytes", {
|
|
741
|
-
reason: "output.too-large",
|
|
742
|
-
max_bytes: 4194304,
|
|
743
|
-
});
|
|
744
|
-
buffer(text);
|
|
745
|
-
},
|
|
746
318
|
});
|
|
747
319
|
annotateMeetingCommands(program);
|
|
748
320
|
const parseAsync = program.parseAsync.bind(program);
|
|
@@ -753,11 +325,10 @@ export const createProgram = (deps) => {
|
|
|
753
325
|
parsing = true;
|
|
754
326
|
answerExitCodes.set(program, 0);
|
|
755
327
|
config = undefined;
|
|
756
|
-
|
|
328
|
+
configured.reset();
|
|
757
329
|
execution = undefined;
|
|
758
330
|
activeTokens = undefined;
|
|
759
|
-
|
|
760
|
-
watchSince = undefined;
|
|
331
|
+
watch.reset();
|
|
761
332
|
const lifted = liftJsonFields(program, args);
|
|
762
333
|
fields = lifted.fields;
|
|
763
334
|
let result = program;
|
|
@@ -836,32 +407,4 @@ export const run = async (args, deps) => {
|
|
|
836
407
|
return reportFailure(failure, args, deps, selected.path, hostFailureContext(program, metaOf(selected.action).effects));
|
|
837
408
|
}
|
|
838
409
|
};
|
|
839
|
-
export const reportFailure = (failure, args, deps, command = "zm", context = hostFailureContext()) => {
|
|
840
|
-
const end = args.indexOf("--");
|
|
841
|
-
const flags = args.slice(0, end < 0 ? undefined : end);
|
|
842
|
-
const machine = flags.some((word) => word === "--json" || word === "--jsonl");
|
|
843
|
-
const object = errorObjectOf(failure, context);
|
|
844
|
-
const record = flags.includes("--debug")
|
|
845
|
-
? errorRecordOf(failure, object, { command, service: "zm", version: VERSION })
|
|
846
|
-
: undefined;
|
|
847
|
-
const interactive = deps.outputIsTTY === true && !machine;
|
|
848
|
-
deps.diagnostic(`${renderError(object, { cli: "zm", interactive, ...(record ? { record } : {}) })}\n`);
|
|
849
|
-
return exitCodeOfError(object);
|
|
850
|
-
};
|
|
851
|
-
const commandSelection = (program, args) => {
|
|
852
|
-
const words = [];
|
|
853
|
-
let current = program;
|
|
854
|
-
for (const word of args) {
|
|
855
|
-
if (word === "--")
|
|
856
|
-
break;
|
|
857
|
-
if (word.startsWith("-"))
|
|
858
|
-
continue;
|
|
859
|
-
const next = current.commands.find((command) => command.name() === word || command.aliases().includes(word));
|
|
860
|
-
if (!next)
|
|
861
|
-
break;
|
|
862
|
-
words.push(word);
|
|
863
|
-
current = next;
|
|
864
|
-
}
|
|
865
|
-
return { path: words.length ? words.join(" ") : "zm", action: current };
|
|
866
|
-
};
|
|
867
410
|
//# sourceMappingURL=program.js.map
|