@wirecat/zoom-cli 0.12.0 → 0.14.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 +5 -5
- package/dist/agent-skill.d.ts.map +1 -1
- package/dist/agent-skill.js +2 -2
- package/dist/agent-skill.js.map +1 -1
- package/dist/answer-output.d.ts +23 -0
- package/dist/answer-output.d.ts.map +1 -0
- package/dist/answer-output.js +52 -0
- package/dist/answer-output.js.map +1 -0
- package/dist/answer-policy.d.ts +11 -0
- package/dist/answer-policy.d.ts.map +1 -0
- package/dist/answer-policy.js +8 -0
- package/dist/answer-policy.js.map +1 -0
- package/dist/answers.d.ts +105 -42
- package/dist/answers.d.ts.map +1 -1
- package/dist/answers.js +23 -34
- package/dist/answers.js.map +1 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +20 -19
- package/dist/api.js.map +1 -1
- package/dist/archive-commands.d.ts +5 -4
- package/dist/archive-commands.d.ts.map +1 -1
- package/dist/archive-commands.js +32 -31
- package/dist/archive-commands.js.map +1 -1
- package/dist/archive-import.d.ts +2 -2
- package/dist/archive-import.d.ts.map +1 -1
- package/dist/archive-import.js +20 -30
- package/dist/archive-import.js.map +1 -1
- package/dist/archive-transcripts.d.ts.map +1 -1
- package/dist/archive-transcripts.js +22 -21
- package/dist/archive-transcripts.js.map +1 -1
- package/dist/bin/zm.js +1 -2
- package/dist/bin/zm.js.map +1 -1
- package/dist/command-effects.d.ts +5 -0
- package/dist/command-effects.d.ts.map +1 -0
- package/dist/command-effects.js +38 -0
- package/dist/command-effects.js.map +1 -0
- package/dist/commands.d.ts +2 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +21 -18
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +54 -37
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +0 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -7
- package/dist/errors.js.map +1 -1
- package/dist/execution.d.ts +1 -0
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +4 -4
- package/dist/execution.js.map +1 -1
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +9 -9
- package/dist/files.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/ingestion-search-commands.d.ts +3 -2
- package/dist/ingestion-search-commands.d.ts.map +1 -1
- package/dist/ingestion-search-commands.js +9 -8
- package/dist/ingestion-search-commands.js.map +1 -1
- package/dist/json-fields.d.ts +7 -0
- package/dist/json-fields.d.ts.map +1 -0
- package/dist/json-fields.js +23 -0
- package/dist/json-fields.js.map +1 -0
- package/dist/keys.d.ts +1 -1
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +7 -5
- package/dist/keys.js.map +1 -1
- package/dist/local-transcription-commands.d.ts +3 -2
- package/dist/local-transcription-commands.d.ts.map +1 -1
- package/dist/local-transcription-commands.js +7 -7
- package/dist/local-transcription-commands.js.map +1 -1
- package/dist/local-transcription.d.ts.map +1 -1
- package/dist/local-transcription.js +13 -12
- package/dist/local-transcription.js.map +1 -1
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +8 -7
- package/dist/login.js.map +1 -1
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +40 -48
- package/dist/mcp-server.js.map +1 -1
- package/dist/meeting-context-commands.d.ts +2 -1
- package/dist/meeting-context-commands.d.ts.map +1 -1
- package/dist/meeting-context-commands.js +11 -15
- package/dist/meeting-context-commands.js.map +1 -1
- package/dist/meeting-context.d.ts +6 -6
- package/dist/meeting-context.d.ts.map +1 -1
- package/dist/meeting-context.js +8 -21
- package/dist/meeting-context.js.map +1 -1
- package/dist/meeting-integration-commands.d.ts +3 -2
- package/dist/meeting-integration-commands.d.ts.map +1 -1
- package/dist/meeting-integration-commands.js +7 -7
- package/dist/meeting-integration-commands.js.map +1 -1
- package/dist/meeting-integration.d.ts.map +1 -1
- package/dist/meeting-integration.js +2 -2
- package/dist/meeting-integration.js.map +1 -1
- package/dist/meeting-mcp-command.d.ts +19 -0
- package/dist/meeting-mcp-command.d.ts.map +1 -0
- package/dist/meeting-mcp-command.js +41 -0
- package/dist/meeting-mcp-command.js.map +1 -0
- package/dist/meeting-preparation-mcp.d.ts +131 -0
- package/dist/meeting-preparation-mcp.d.ts.map +1 -0
- package/dist/meeting-preparation-mcp.js +20 -0
- package/dist/meeting-preparation-mcp.js.map +1 -0
- package/dist/meeting-preparation.d.ts +22 -0
- package/dist/meeting-preparation.d.ts.map +1 -0
- package/dist/meeting-preparation.js +29 -0
- package/dist/meeting-preparation.js.map +1 -0
- package/dist/meeting-project-evidence-commands.d.ts +1 -4
- package/dist/meeting-project-evidence-commands.d.ts.map +1 -1
- package/dist/meeting-project-evidence-commands.js +2 -6
- package/dist/meeting-project-evidence-commands.js.map +1 -1
- package/dist/meeting-project-evidence-mcp.d.ts +76 -83
- package/dist/meeting-project-evidence-mcp.d.ts.map +1 -1
- package/dist/meeting-project-evidence-mcp.js +7 -8
- package/dist/meeting-project-evidence-mcp.js.map +1 -1
- package/dist/meeting-read-command-bindings.d.ts +10 -0
- package/dist/meeting-read-command-bindings.d.ts.map +1 -0
- package/dist/meeting-read-command-bindings.js +13 -0
- package/dist/meeting-read-command-bindings.js.map +1 -0
- package/dist/meeting-search-commands.d.ts +3 -2
- package/dist/meeting-search-commands.d.ts.map +1 -1
- package/dist/meeting-search-commands.js +47 -38
- package/dist/meeting-search-commands.js.map +1 -1
- package/dist/meeting-semantic-commands.d.ts +3 -2
- package/dist/meeting-semantic-commands.d.ts.map +1 -1
- package/dist/meeting-semantic-commands.js +13 -12
- package/dist/meeting-semantic-commands.js.map +1 -1
- package/dist/meeting-semantic.d.ts.map +1 -1
- package/dist/meeting-semantic.js +3 -2
- package/dist/meeting-semantic.js.map +1 -1
- package/dist/occurrence-schedule.d.ts +3 -0
- package/dist/occurrence-schedule.d.ts.map +1 -0
- package/dist/occurrence-schedule.js +106 -0
- package/dist/occurrence-schedule.js.map +1 -0
- package/dist/output-file.js +3 -3
- package/dist/output-file.js.map +1 -1
- package/dist/program.d.ts +15 -28
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +163 -333
- package/dist/program.js.map +1 -1
- package/dist/recording-archive.d.ts +1 -1
- package/dist/recording-archive.d.ts.map +1 -1
- package/dist/recording-archive.js +99 -46
- package/dist/recording-archive.js.map +1 -1
- package/dist/recording-partial-store.d.ts.map +1 -1
- package/dist/recording-partial-store.js +11 -10
- package/dist/recording-partial-store.js.map +1 -1
- package/dist/recording-promotion-store.d.ts.map +1 -1
- package/dist/recording-promotion-store.js +4 -4
- package/dist/recording-promotion-store.js.map +1 -1
- package/dist/recording-schedule-commands.d.ts +3 -2
- package/dist/recording-schedule-commands.d.ts.map +1 -1
- package/dist/recording-schedule-commands.js +13 -12
- package/dist/recording-schedule-commands.js.map +1 -1
- package/dist/recording-schedule-store.d.ts.map +1 -1
- package/dist/recording-schedule-store.js +15 -14
- 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 +16 -15
- package/dist/recording-schedule-systemd.js.map +1 -1
- package/dist/recording-schedule.d.ts +1 -1
- package/dist/recording-schedule.d.ts.map +1 -1
- package/dist/recording-schedule.js +15 -14
- package/dist/recording-schedule.js.map +1 -1
- package/dist/recording-sync-store.d.ts.map +1 -1
- package/dist/recording-sync-store.js +9 -9
- package/dist/recording-sync-store.js.map +1 -1
- package/dist/recording-sync.d.ts +1 -1
- package/dist/recording-sync.d.ts.map +1 -1
- package/dist/recording-sync.js +10 -19
- package/dist/recording-sync.js.map +1 -1
- package/dist/recordings.d.ts.map +1 -1
- package/dist/recordings.js +19 -18
- package/dist/recordings.js.map +1 -1
- package/dist/remote-http.d.ts +1 -0
- package/dist/remote-http.d.ts.map +1 -1
- package/dist/remote-http.js +26 -14
- package/dist/remote-http.js.map +1 -1
- package/dist/remote-meeting-id.d.ts +2 -0
- package/dist/remote-meeting-id.d.ts.map +1 -0
- package/dist/remote-meeting-id.js +7 -0
- package/dist/remote-meeting-id.js.map +1 -0
- package/dist/remote-meetings.d.ts.map +1 -1
- package/dist/remote-meetings.js +10 -13
- package/dist/remote-meetings.js.map +1 -1
- package/dist/store-connection.d.ts +1 -7
- package/dist/store-connection.d.ts.map +1 -1
- package/dist/store-connection.js +95 -176
- package/dist/store-connection.js.map +1 -1
- package/dist/streaming.js +3 -3
- package/dist/streaming.js.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +10 -9
- package/dist/tokens.js.map +1 -1
- package/dist/unified-search.d.ts +1 -0
- package/dist/unified-search.d.ts.map +1 -1
- package/dist/unified-search.js +18 -3
- package/dist/unified-search.js.map +1 -1
- package/dist/upcoming-meetings.d.ts +10 -0
- package/dist/upcoming-meetings.d.ts.map +1 -0
- package/dist/upcoming-meetings.js +24 -0
- package/dist/upcoming-meetings.js.map +1 -0
- package/dist/watch-commands.d.ts +2 -1
- package/dist/watch-commands.d.ts.map +1 -1
- package/dist/watch-commands.js +9 -9
- package/dist/watch-commands.js.map +1 -1
- package/package.json +5 -4
- package/skills/zoom-cli/SKILL.md +32 -12
- package/dist/ordinary-file.d.ts +0 -3
- package/dist/ordinary-file.d.ts.map +0 -1
- package/dist/ordinary-file.js +0 -16
- package/dist/ordinary-file.js.map +0 -1
- package/dist/wav-audio.d.ts +0 -2
- package/dist/wav-audio.d.ts.map +0 -1
- package/dist/wav-audio.js +0 -2
- package/dist/wav-audio.js.map +0 -1
package/dist/program.js
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { createDeadline, createRenderer, errorObjectOf, errorRecordOf, exitCodeOfError,
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { CliError, createDeadline, createOutputBuffer, createRenderer, errorObjectOf, errorRecordOf, exitCodeOfError, isCliError, projectFields, realSleep, renderError, } from "@wirecat/cli-base";
|
|
4
|
+
import { metaOf } from "@wirecat/cli-base/commands";
|
|
5
|
+
import { checkJson, itemOf, snakeKeys } from "@wirecat/cli-core/cli";
|
|
6
|
+
import { importFiles, pull, } from "@wirecat/cli-core/meetings";
|
|
6
7
|
import { addMeetingCommands, addMeetingPassageCommand } from "@wirecat/cli-core/meetings/cli";
|
|
7
8
|
import { Command, CommanderError } from "commander";
|
|
8
9
|
import { addZoomSkillCommands } from "./agent-skill.js";
|
|
9
|
-
import {
|
|
10
|
+
import { bodyOf, renderBody, wholeList } from "./answer-output.js";
|
|
11
|
+
import { hostFailureContext } from "./answer-policy.js";
|
|
10
12
|
import { ZoomApiSource } from "./api.js";
|
|
11
13
|
import { addArchiveCommands, } from "./archive-commands.js";
|
|
12
14
|
import { applyArchiveImport, preflightArchiveImport } from "./archive-import.js";
|
|
13
15
|
import { readArchiveTranscripts, searchArchiveTranscripts } from "./archive-transcripts.js";
|
|
14
16
|
import { addStandardCommands, annotateMeetingCommands } from "./commands.js";
|
|
15
17
|
import { profileAccountKey, readConfig, setConfig } from "./config.js";
|
|
16
|
-
import { checkCancelled
|
|
18
|
+
import { checkCancelled } from "./errors.js";
|
|
17
19
|
import { bytes, duration, resetCliOptions, startExecution } from "./execution.js";
|
|
18
20
|
import { FilesSource, importFile, readDownloadedFiles, validateDownloadedFiles } from "./files.js";
|
|
19
21
|
import { addIngestionSearchCommands } from "./ingestion-search-commands.js";
|
|
20
|
-
import {
|
|
22
|
+
import { liftJsonFields } from "./json-fields.js";
|
|
21
23
|
import { addLocalTranscriptionCommands } from "./local-transcription-commands.js";
|
|
22
24
|
import { login } from "./login.js";
|
|
23
25
|
import { addMeetingContextCommands } from "./meeting-context-commands.js";
|
|
24
26
|
import { addMeetingIntegrationCommands } from "./meeting-integration-commands.js";
|
|
25
|
-
import {
|
|
27
|
+
import { addZoomMcpCommand } from "./meeting-mcp-command.js";
|
|
28
|
+
import { addMeetingReadBindings } from "./meeting-read-command-bindings.js";
|
|
26
29
|
import { addMeetingSearchCommands } from "./meeting-search-commands.js";
|
|
27
|
-
import { addMeetingEmbeddingCommand
|
|
30
|
+
import { addMeetingEmbeddingCommand } from "./meeting-semantic-commands.js";
|
|
28
31
|
import { createRecordingScheduleService } from "./recording-schedule.js";
|
|
29
32
|
import { addRecordingScheduleCommands } from "./recording-schedule-commands.js";
|
|
30
33
|
import { fileRecordingScheduleStore } from "./recording-schedule-store.js";
|
|
@@ -37,7 +40,7 @@ import { runUnifiedSearch } from "./unified-search.js";
|
|
|
37
40
|
import { VERSION } from "./version.js";
|
|
38
41
|
import { addWatchCommand } from "./watch-commands.js";
|
|
39
42
|
const unavailable = async () => {
|
|
40
|
-
throw new
|
|
43
|
+
throw new CliError("configuration_error", "the shared SQLite meeting store is not available yet");
|
|
41
44
|
};
|
|
42
45
|
const unavailableStore = {
|
|
43
46
|
saveMeeting: unavailable,
|
|
@@ -55,39 +58,11 @@ const unavailableStore = {
|
|
|
55
58
|
cursor: unavailable,
|
|
56
59
|
setCursor: unavailable,
|
|
57
60
|
};
|
|
58
|
-
const
|
|
59
|
-
if (!providerKeys)
|
|
60
|
-
value = snakeKeys(value);
|
|
61
|
-
if (seal)
|
|
62
|
-
value = meetingAnswer(value, seal());
|
|
63
|
-
if (fields) {
|
|
64
|
-
if (seal && value && typeof value === "object" && "item" in value)
|
|
65
|
-
value = { ...value, item: projectFields(value.item, fields) };
|
|
66
|
-
else
|
|
67
|
-
value = projectFields(value, fields);
|
|
68
|
-
}
|
|
69
|
-
const chunks = [];
|
|
70
|
-
const renderer = createRenderer({
|
|
71
|
-
format: format === "text" ? (deps.outputIsTTY ? "pretty" : "json") : format,
|
|
72
|
-
color: false,
|
|
73
|
-
streams: { data: (text) => chunks.push(`${text}\n`), diagnostic: deps.diagnostic },
|
|
74
|
-
});
|
|
75
|
-
if (!preserveEnvelope &&
|
|
76
|
-
!seal &&
|
|
77
|
-
format === "jsonl" &&
|
|
78
|
-
typeof value === "object" &&
|
|
79
|
-
value !== null &&
|
|
80
|
-
"items" in value &&
|
|
81
|
-
Array.isArray(value.items))
|
|
82
|
-
renderer.stream(value.items);
|
|
83
|
-
else
|
|
84
|
-
renderer.result(value);
|
|
85
|
-
return chunks.join("");
|
|
86
|
-
};
|
|
61
|
+
const answerExitCodes = new WeakMap();
|
|
87
62
|
export const createProgram = (deps) => {
|
|
88
63
|
let config;
|
|
89
64
|
const getConfig = () => (config ??= readConfig(deps.configPath));
|
|
90
|
-
let
|
|
65
|
+
let connecting;
|
|
91
66
|
let parsing = false;
|
|
92
67
|
let execution;
|
|
93
68
|
let fields;
|
|
@@ -97,7 +72,7 @@ export const createProgram = (deps) => {
|
|
|
97
72
|
const fetchWithSignal = (fetcher) => (input, init) => {
|
|
98
73
|
checkCancelled(signal());
|
|
99
74
|
if (program.opts().offline)
|
|
100
|
-
throw new
|
|
75
|
+
throw new CliError("configuration_error", "the command requires network access; remove --offline");
|
|
101
76
|
const operation = signal();
|
|
102
77
|
return fetcher(input, {
|
|
103
78
|
...init,
|
|
@@ -107,7 +82,7 @@ export const createProgram = (deps) => {
|
|
|
107
82
|
const tokens = () => (activeTokens ??= deps.tokens.withSignal(signal(), fetchWithSignal(deps.tokens.options.fetch)));
|
|
108
83
|
const buffer = (text) => {
|
|
109
84
|
if (!execution)
|
|
110
|
-
throw new
|
|
85
|
+
throw new CliError("configuration_error", "command execution is not initialized");
|
|
111
86
|
execution.output.data(text);
|
|
112
87
|
};
|
|
113
88
|
const guardedStore = (store) => new Proxy(store, {
|
|
@@ -127,116 +102,99 @@ export const createProgram = (deps) => {
|
|
|
127
102
|
let selectedAccountId = deps.accountId;
|
|
128
103
|
const requireAccount = () => {
|
|
129
104
|
if (!Number.isSafeInteger(selectedAccountId) || !selectedAccountId || selectedAccountId < 1)
|
|
130
|
-
throw new
|
|
105
|
+
throw new CliError("configuration_error", "the selected meeting account is unavailable");
|
|
131
106
|
return selectedAccountId;
|
|
132
107
|
};
|
|
108
|
+
const openStore = async (intent) => {
|
|
109
|
+
if (!deps.connectStore)
|
|
110
|
+
return unavailable();
|
|
111
|
+
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
|
+
try {
|
|
115
|
+
return await deps.connectStore({ profile, externalId: profileAccountKey(profile), intent });
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (isCliError(error))
|
|
119
|
+
throw error;
|
|
120
|
+
throw new CliError("configuration_error", "could not open the shared meeting store");
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const connected = (intent = "read") => (connecting ??= openStore(intent));
|
|
133
124
|
const program = new Command()
|
|
134
125
|
.name("zm")
|
|
135
126
|
.version(VERSION)
|
|
136
127
|
.description("Zoom meeting transcripts and summaries")
|
|
137
|
-
.option("--json", "one JSON value")
|
|
128
|
+
.option("--json", "one JSON value; --json=id,title keeps only those fields")
|
|
138
129
|
.option("--jsonl", "one JSON object per item")
|
|
139
130
|
.option("--no-input", "disable interactive login")
|
|
140
131
|
.option("--interactive", "permit browser approval in an interactive terminal")
|
|
141
132
|
.option("--quiet", "suppress non-error diagnostics")
|
|
142
|
-
.option("--fields <paths>", "project result fields, such as id,title")
|
|
143
133
|
.option("--timeout <duration>", "command deadline: reads 30s, login 5m, downloads/transcription 1h; watch/MCP have no default", duration)
|
|
144
134
|
.option("--max-output-bytes <bytes>", "bound rendered result bytes (default 4194304; zero is unlimited)", bytes)
|
|
145
135
|
.option("--offline", "refuse network requests")
|
|
146
136
|
.option("--debug", "on a failure, its whole record — cause and stack — in place of the short line")
|
|
147
137
|
.exitOverride()
|
|
148
138
|
.configureOutput({ writeOut: deps.data, writeErr: deps.diagnostic, outputError: () => { } });
|
|
139
|
+
const formatOf = () => program.opts().jsonl ? "jsonl" : program.opts().json || !deps.outputIsTTY ? "json" : "pretty";
|
|
140
|
+
const rendered = (body, format = formatOf()) => {
|
|
141
|
+
if (!execution)
|
|
142
|
+
throw new CliError("configuration_error", "command execution is not initialized");
|
|
143
|
+
const answer = renderBody(execution.action, body, {
|
|
144
|
+
format,
|
|
145
|
+
meta: execution.meta(),
|
|
146
|
+
fields,
|
|
147
|
+
quiet: Boolean(program.opts().quiet),
|
|
148
|
+
diagnostic: deps.diagnostic,
|
|
149
|
+
});
|
|
150
|
+
answerExitCodes.set(program, Math.max(answerExitCodes.get(program) ?? 0, answer.exitCode));
|
|
151
|
+
return answer.text;
|
|
152
|
+
};
|
|
149
153
|
const api = () => {
|
|
150
154
|
if (program.opts().offline)
|
|
151
|
-
throw new
|
|
155
|
+
throw new CliError("configuration_error", "the command requires network access; remove --offline");
|
|
152
156
|
if (!getConfig().clientId)
|
|
153
|
-
throw new
|
|
157
|
+
throw new CliError("configuration_error", "run zm config set zoom.client_id <Public Client ID> first");
|
|
154
158
|
};
|
|
155
159
|
program.hook("preAction", async (_root, action) => {
|
|
156
160
|
const opts = action.optsWithGlobals();
|
|
157
161
|
if (opts.json && opts.jsonl)
|
|
158
|
-
throw new
|
|
159
|
-
|
|
162
|
+
throw new CliError("validation_error", "choose --json or --jsonl");
|
|
163
|
+
checkJson(action, { json: opts.json === true, ...(fields ? { fields: fields.join(",") } : {}) }, false);
|
|
160
164
|
execution = startExecution(action, { signal: deps.signal, sleep: deps.sleep, now: deps.now });
|
|
161
165
|
checkCancelled(signal());
|
|
162
|
-
|
|
163
|
-
while (family.parent && family.parent !== program)
|
|
164
|
-
family = family.parent;
|
|
165
|
-
if ([
|
|
166
|
-
"commands",
|
|
167
|
-
"complete",
|
|
168
|
-
"doctor",
|
|
169
|
-
"config",
|
|
170
|
-
"session",
|
|
171
|
-
"recordings",
|
|
172
|
-
"remote-meetings",
|
|
173
|
-
"serve",
|
|
174
|
-
"skill",
|
|
175
|
-
"watch",
|
|
176
|
-
"search",
|
|
177
|
-
].includes(family.name()) ||
|
|
178
|
-
(family.name() === "meetings" &&
|
|
179
|
-
["passage", "evidence", "context", "task-proposal", "embeddings", "update", "link", "transcribe"].includes(action.name())))
|
|
166
|
+
if (!storeCommands.has(action))
|
|
180
167
|
return;
|
|
181
168
|
const config = getConfig();
|
|
182
|
-
const ingestion =
|
|
169
|
+
const ingestion = action.parent?.name() === "meetings" && ["sync", "import"].includes(action.name());
|
|
183
170
|
if (opts.offline && ingestion && action.name() !== "import" && config.source === "api" && !deps.source)
|
|
184
|
-
throw new
|
|
171
|
+
throw new CliError("configuration_error", "API sync requires network access; remove --offline");
|
|
185
172
|
if (!selectedStore) {
|
|
186
|
-
|
|
187
|
-
return unavailable();
|
|
188
|
-
if (!config.accountProfile)
|
|
189
|
-
throw new ZoomError("configuration_error", "select a local profile with zm config set account.profile <label>");
|
|
190
|
-
try {
|
|
191
|
-
connection = await deps.connectStore({
|
|
192
|
-
profile: config.accountProfile,
|
|
193
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
194
|
-
intent: ingestion ? "ingestion" : "read",
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
catch (error) {
|
|
198
|
-
if (error instanceof ZoomError || error instanceof MeetingError)
|
|
199
|
-
throw error;
|
|
200
|
-
throw new ZoomError("configuration_error", "could not open the shared meeting store");
|
|
201
|
-
}
|
|
173
|
+
const connection = await connected(ingestion ? "ingestion" : "read");
|
|
202
174
|
selectedStore = connection.store;
|
|
203
175
|
selectedAccountId = connection.accountId;
|
|
204
176
|
}
|
|
205
177
|
requireAccount();
|
|
206
178
|
});
|
|
207
|
-
const output = (
|
|
179
|
+
const output = (body) => buffer(rendered(body));
|
|
208
180
|
const outputItems = async (values) => {
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
let count = 0;
|
|
213
|
-
if (format === "json")
|
|
214
|
-
buffer('{"items":[');
|
|
181
|
+
const items = [];
|
|
182
|
+
// Fails on the row that crosses --max-output-bytes, so a long iterator stops reading there.
|
|
183
|
+
const measured = createOutputBuffer({ maxOutputBytes: program.opts().maxOutputBytes });
|
|
215
184
|
for await (const value of values) {
|
|
216
185
|
checkCancelled(signal());
|
|
217
186
|
const item = snakeKeys(value);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (count)
|
|
221
|
-
buffer(",");
|
|
222
|
-
buffer(render(projected, "json", deps).trimEnd());
|
|
223
|
-
}
|
|
224
|
-
else
|
|
225
|
-
buffer(render(projected, format, deps, undefined, true, false, execution?.meta));
|
|
226
|
-
count++;
|
|
187
|
+
measured.data(JSON.stringify(fields ? projectFields(item, fields) : item));
|
|
188
|
+
items.push(item);
|
|
227
189
|
}
|
|
228
|
-
|
|
229
|
-
if (format === "json")
|
|
230
|
-
buffer(`],"page":${JSON.stringify({ limit: Math.max(1, count), has_more: false })},"meta":${JSON.stringify(execution?.meta())}}\n`);
|
|
231
|
-
else if (format === "text")
|
|
232
|
-
buffer(render(count ? metadata : listed([]), "text", deps));
|
|
190
|
+
output(wholeList("list", items));
|
|
233
191
|
};
|
|
234
192
|
const cfg = program.command("config").description("local Zoom configuration");
|
|
235
193
|
cfg
|
|
236
194
|
.command("show")
|
|
237
195
|
.description("show local configuration")
|
|
238
196
|
.action(() => {
|
|
239
|
-
output(getConfig());
|
|
197
|
+
output(itemOf(getConfig()));
|
|
240
198
|
});
|
|
241
199
|
cfg
|
|
242
200
|
.command("set")
|
|
@@ -244,7 +202,7 @@ export const createProgram = (deps) => {
|
|
|
244
202
|
.argument("<key>", "setting name, such as account.profile")
|
|
245
203
|
.argument("<value>", "new value")
|
|
246
204
|
.action((key, value) => {
|
|
247
|
-
output(setConfig(deps.configPath, key, value));
|
|
205
|
+
output(itemOf(setConfig(deps.configPath, key, value)));
|
|
248
206
|
});
|
|
249
207
|
let activeSource;
|
|
250
208
|
const getSource = () => {
|
|
@@ -255,7 +213,7 @@ export const createProgram = (deps) => {
|
|
|
255
213
|
if (config.source === "api")
|
|
256
214
|
return new ZoomApiSource(tokens(), fetchWithSignal(deps.fetch));
|
|
257
215
|
if (!config.filesFolder)
|
|
258
|
-
throw new
|
|
216
|
+
throw new CliError("configuration_error", "set files.folder before pulling from files");
|
|
259
217
|
return new FilesSource(await (deps.readFiles ?? readDownloadedFiles)(config.filesFolder), config.filesTimezone);
|
|
260
218
|
})();
|
|
261
219
|
return activeSource;
|
|
@@ -302,10 +260,7 @@ export const createProgram = (deps) => {
|
|
|
302
260
|
return validateDownloadedFiles(await (deps.readFiles ?? readDownloadedFiles)(folder), config.filesTimezone).map((file) => importFile(file, requireAccount(), config.filesTimezone));
|
|
303
261
|
},
|
|
304
262
|
now: deps.now,
|
|
305
|
-
write: (value
|
|
306
|
-
const paged = typeof value === "object" && value !== null && "page" in value && typeof value.page === "object";
|
|
307
|
-
buffer(render(value, format, deps, fields, paged, true, execution?.meta));
|
|
308
|
-
},
|
|
263
|
+
write: (value) => output(bodyOf(value)),
|
|
309
264
|
writeFile: deps.writeFile
|
|
310
265
|
? async (path, content) => {
|
|
311
266
|
checkCancelled(signal());
|
|
@@ -314,10 +269,18 @@ export const createProgram = (deps) => {
|
|
|
314
269
|
}
|
|
315
270
|
: undefined,
|
|
316
271
|
};
|
|
272
|
+
const before = new Set(program.commands);
|
|
317
273
|
addMeetingCommands(program, meetingCommands);
|
|
274
|
+
const leaves = (command) => command.commands.length ? command.commands.flatMap(leaves) : [command];
|
|
275
|
+
// The meeting reads cli-core mounts read the store opened before their action; zoom's own commands open it lazily.
|
|
276
|
+
const storeCommands = new Set(program.commands.filter((group) => !before.has(group)).flatMap(leaves));
|
|
318
277
|
addStandardCommands(program, {
|
|
319
278
|
output,
|
|
320
|
-
discovery: (value) =>
|
|
279
|
+
discovery: (value) => createRenderer({
|
|
280
|
+
format: formatOf(),
|
|
281
|
+
color: false,
|
|
282
|
+
streams: { data: (text) => buffer(`${text}\n`), diagnostic: deps.diagnostic },
|
|
283
|
+
}).result(value),
|
|
321
284
|
fields: () => fields,
|
|
322
285
|
raw: buffer,
|
|
323
286
|
doctor: () => {
|
|
@@ -337,7 +300,7 @@ export const createProgram = (deps) => {
|
|
|
337
300
|
return { configured: false, state: "not_configured", dataProfile: config.accountProfile, verified: false };
|
|
338
301
|
if (check) {
|
|
339
302
|
if (program.opts().offline)
|
|
340
|
-
throw new
|
|
303
|
+
throw new CliError("configuration_error", "session verification requires network access; remove --offline");
|
|
341
304
|
api();
|
|
342
305
|
return {
|
|
343
306
|
configured: true,
|
|
@@ -361,7 +324,7 @@ export const createProgram = (deps) => {
|
|
|
361
324
|
});
|
|
362
325
|
const session = program.commands.find((command) => command.name() === "session");
|
|
363
326
|
if (!session)
|
|
364
|
-
throw new
|
|
327
|
+
throw new CliError("configuration_error", "session command group is unavailable");
|
|
365
328
|
session
|
|
366
329
|
.command("start")
|
|
367
330
|
.description("log in to Zoom through your browser")
|
|
@@ -369,18 +332,18 @@ export const createProgram = (deps) => {
|
|
|
369
332
|
.action(async (opts) => {
|
|
370
333
|
const config = getConfig();
|
|
371
334
|
if (!config.clientId)
|
|
372
|
-
throw new
|
|
335
|
+
throw new CliError("configuration_error", "run zm config set zoom.client_id <Public Client ID> first");
|
|
373
336
|
const globals = program.opts();
|
|
374
337
|
if (globals.offline)
|
|
375
|
-
throw new
|
|
338
|
+
throw new CliError("configuration_error", "login requires network access; remove --offline");
|
|
376
339
|
const headless = deps.interactive === false ||
|
|
377
340
|
Boolean(deps.env?.CI) ||
|
|
378
341
|
(deps.interactive !== undefined &&
|
|
379
342
|
(globals.json || globals.jsonl || deps.outputIsTTY === false) &&
|
|
380
343
|
!globals.interactive);
|
|
381
344
|
if (globals.input === false || headless)
|
|
382
|
-
throw new
|
|
383
|
-
output(await login({
|
|
345
|
+
throw new CliError("configuration_error", "login requires browser approval; remove --no-input");
|
|
346
|
+
output(itemOf(await login({
|
|
384
347
|
tokens: tokens(),
|
|
385
348
|
signal: signal(),
|
|
386
349
|
openBrowser: (url) => deps.openBrowser(url, opts.browser),
|
|
@@ -389,13 +352,13 @@ export const createProgram = (deps) => {
|
|
|
389
352
|
if (!program.opts().quiet)
|
|
390
353
|
deps.diagnostic(`Open this URL to approve Zoom login:\n${url}\n`);
|
|
391
354
|
},
|
|
392
|
-
}));
|
|
355
|
+
})));
|
|
393
356
|
});
|
|
394
357
|
let watchConfig;
|
|
395
358
|
let watchSince;
|
|
396
359
|
const watchSleep = deps.sleep;
|
|
397
|
-
const receipt = async (
|
|
398
|
-
const text =
|
|
360
|
+
const receipt = async (body) => {
|
|
361
|
+
const text = rendered(body);
|
|
399
362
|
const operation = signal();
|
|
400
363
|
const grace = operation.aborted ? createDeadline({ timeoutMs: 1000 }) : undefined;
|
|
401
364
|
try {
|
|
@@ -427,24 +390,24 @@ export const createProgram = (deps) => {
|
|
|
427
390
|
};
|
|
428
391
|
if (source === "files") {
|
|
429
392
|
if (flags.sinceTime !== undefined || flags.lookbackDays !== undefined)
|
|
430
|
-
throw new
|
|
393
|
+
throw new CliError("validation_error", "--since-time and --lookback-days apply only to API watching");
|
|
431
394
|
if (!plan.folder?.trim())
|
|
432
|
-
throw new
|
|
395
|
+
throw new CliError("configuration_error", "set files.folder or provide a folder for file watching");
|
|
433
396
|
}
|
|
434
397
|
else {
|
|
435
398
|
if (folder !== undefined)
|
|
436
|
-
throw new
|
|
399
|
+
throw new CliError("validation_error", "API watching does not accept a folder");
|
|
437
400
|
if (program.opts().offline)
|
|
438
|
-
throw new
|
|
401
|
+
throw new CliError("configuration_error", "API watching requires network access; remove --offline");
|
|
439
402
|
if (!deps.source) {
|
|
440
403
|
if (!config.clientId)
|
|
441
|
-
throw new
|
|
404
|
+
throw new CliError("configuration_error", "run zm config set zoom.client_id <Public Client ID> first");
|
|
442
405
|
if (tokens().options.clientId !== config.clientId)
|
|
443
|
-
throw new
|
|
406
|
+
throw new CliError("configuration_error", "the OAuth client changed before watch started; retry with matching configuration");
|
|
444
407
|
}
|
|
445
408
|
}
|
|
446
409
|
if (!deps.store && !config.accountProfile)
|
|
447
|
-
throw new
|
|
410
|
+
throw new CliError("configuration_error", "select a local profile with zm config set account.profile <label>");
|
|
448
411
|
watchConfig = config;
|
|
449
412
|
watchSince = plan.since;
|
|
450
413
|
return plan;
|
|
@@ -453,33 +416,17 @@ export const createProgram = (deps) => {
|
|
|
453
416
|
checkCancelled(operation);
|
|
454
417
|
const config = watchConfig;
|
|
455
418
|
if (!config)
|
|
456
|
-
throw new
|
|
419
|
+
throw new CliError("configuration_error", "watch configuration is unavailable");
|
|
457
420
|
let cycle;
|
|
458
421
|
let failure;
|
|
459
422
|
let result;
|
|
460
423
|
try {
|
|
461
|
-
if (!deps.store)
|
|
462
|
-
|
|
463
|
-
return unavailable();
|
|
464
|
-
if (!config.accountProfile)
|
|
465
|
-
throw new ZoomError("configuration_error", "select a local profile with zm config set account.profile <label>");
|
|
466
|
-
try {
|
|
467
|
-
cycle = await deps.connectStore({
|
|
468
|
-
profile: config.accountProfile,
|
|
469
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
470
|
-
intent: "ingestion",
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
catch (error) {
|
|
474
|
-
if (isCliError(error))
|
|
475
|
-
throw error;
|
|
476
|
-
throw new ZoomError("configuration_error", "could not open the shared meeting store");
|
|
477
|
-
}
|
|
478
|
-
}
|
|
424
|
+
if (!deps.store)
|
|
425
|
+
cycle = await openStore("ingestion");
|
|
479
426
|
checkCancelled(operation);
|
|
480
427
|
const accountId = cycle?.accountId ?? deps.accountId;
|
|
481
428
|
if (!Number.isSafeInteger(accountId) || !accountId || accountId < 1)
|
|
482
|
-
throw new
|
|
429
|
+
throw new CliError("configuration_error", "the selected meeting account is unavailable");
|
|
483
430
|
const store = guardedStore(cycle?.store ?? deps.store ?? unavailableStore);
|
|
484
431
|
if (plan.source === "files") {
|
|
485
432
|
const files = validateDownloadedFiles(await (deps.readFiles ?? readDownloadedFiles)(plan.folder ?? ""), config.filesTimezone);
|
|
@@ -551,7 +498,7 @@ export const createProgram = (deps) => {
|
|
|
551
498
|
await cycle.close();
|
|
552
499
|
}
|
|
553
500
|
catch {
|
|
554
|
-
failure ??= new
|
|
501
|
+
failure ??= new CliError("configuration_error", "could not close the shared meeting store");
|
|
555
502
|
}
|
|
556
503
|
}
|
|
557
504
|
}
|
|
@@ -605,7 +552,7 @@ export const createProgram = (deps) => {
|
|
|
605
552
|
if (dirname(deps.configPath) !== job.capture.configDir ||
|
|
606
553
|
selected.accountProfile !== job.capture.profile ||
|
|
607
554
|
selected.clientId !== job.capture.clientId)
|
|
608
|
-
throw new
|
|
555
|
+
throw new CliError("configuration_error", "archive schedule requires its saved profile and Zoom client id; select those settings before running");
|
|
609
556
|
return new ZoomRecordings(new TokenManager({
|
|
610
557
|
clientId: job.capture.clientId,
|
|
611
558
|
keyring: deps.tokens.options.keyring,
|
|
@@ -623,9 +570,9 @@ export const createProgram = (deps) => {
|
|
|
623
570
|
capture: () => {
|
|
624
571
|
const selected = getConfig();
|
|
625
572
|
if (!selected.accountProfile || !selected.clientId)
|
|
626
|
-
throw new
|
|
573
|
+
throw new CliError("configuration_error", "archive schedules require a configured local profile and Zoom client id");
|
|
627
574
|
if (!deps.recordingScheduleTarget)
|
|
628
|
-
throw new
|
|
575
|
+
throw new CliError("configuration_error", "archive scheduler requires an explicit runtime and CLI path");
|
|
629
576
|
return {
|
|
630
577
|
profile: selected.accountProfile,
|
|
631
578
|
clientId: selected.clientId,
|
|
@@ -642,219 +589,99 @@ export const createProgram = (deps) => {
|
|
|
642
589
|
});
|
|
643
590
|
addZoomSkillCommands(program, () => {
|
|
644
591
|
const renderer = createRenderer({
|
|
645
|
-
format:
|
|
592
|
+
format: formatOf(),
|
|
646
593
|
color: false,
|
|
647
594
|
quiet: Boolean(program.opts().quiet),
|
|
648
595
|
streams: { data: buffer, diagnostic: deps.diagnostic },
|
|
649
596
|
});
|
|
650
597
|
return {
|
|
651
|
-
renderer: {
|
|
598
|
+
renderer: {
|
|
599
|
+
...renderer,
|
|
600
|
+
result: (value) => output(bodyOf(value)),
|
|
601
|
+
stream: (items) => output(wholeList("skill", [...items])),
|
|
602
|
+
},
|
|
652
603
|
streams: { data: (text) => buffer(`${text}\n`), diagnostic: deps.diagnostic },
|
|
653
604
|
env: deps.env,
|
|
654
605
|
};
|
|
655
606
|
});
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
.
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
.option("--dims <n>", "vector size the remote service returns, in dimensions", bytes)
|
|
666
|
-
.action(async (options) => {
|
|
667
|
-
const opts = program.opts();
|
|
668
|
-
if (opts.json || opts.jsonl || opts.fields)
|
|
669
|
-
throw new ZoomError("validation_error", "MCP stdio controls its own output; omit --json, --jsonl and --fields");
|
|
670
|
-
if (!deps.serveMcp)
|
|
671
|
-
throw new ZoomError("configuration_error", "the MCP server adapter is not available");
|
|
672
|
-
if (options.semantic)
|
|
673
|
-
validateMeetingModel({ model: options.model ?? "", baseUrl: options.baseUrl, dims: options.dims });
|
|
674
|
-
else if (options.model !== undefined || options.baseUrl !== undefined || options.dims !== undefined)
|
|
675
|
-
throw new ZoomError("validation_error", "MCP model options require --semantic");
|
|
676
|
-
if (options.semantic && options.baseUrl !== undefined && opts.offline)
|
|
677
|
-
throw new ZoomError("configuration_error", "remote embeddings require network access; remove --offline");
|
|
678
|
-
await deps.serveMcp({
|
|
679
|
-
signal: signal(),
|
|
680
|
-
maxResultBytes: program.opts().maxOutputBytes,
|
|
681
|
-
...(options.unifiedSearch ? { includeUnifiedSearch: true } : {}),
|
|
682
|
-
...(options.meetingContext ? { includeMeetingContext: true } : {}),
|
|
683
|
-
...(options.semantic
|
|
684
|
-
? { semanticModel: { model: options.model ?? "", baseUrl: options.baseUrl, dims: options.dims } }
|
|
685
|
-
: {}),
|
|
686
|
-
});
|
|
687
|
-
});
|
|
607
|
+
const preparationOptions = {
|
|
608
|
+
credentials: () => {
|
|
609
|
+
api();
|
|
610
|
+
return tokens();
|
|
611
|
+
},
|
|
612
|
+
fetch: fetchWithSignal(deps.fetch),
|
|
613
|
+
remoteOptions,
|
|
614
|
+
};
|
|
615
|
+
addZoomMcpCommand(program, { fields: () => fields, signal, serve: deps.serveMcp, preparation: preparationOptions });
|
|
688
616
|
addIngestionSearchCommands(program, {
|
|
689
617
|
signal,
|
|
690
|
-
output
|
|
618
|
+
output,
|
|
691
619
|
outputItems,
|
|
692
620
|
receipt,
|
|
693
621
|
preflight: preflightArchiveImport,
|
|
694
622
|
apply: async function* (plan) {
|
|
695
623
|
if (plan.occurrences === 0)
|
|
696
624
|
return;
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
const config = getConfig();
|
|
701
|
-
if (!config.accountProfile || !deps.connectStore)
|
|
702
|
-
throw new ZoomError("configuration_error", "select a local profile with an available transcript append store");
|
|
703
|
-
connection = await deps.connectStore({
|
|
704
|
-
profile: config.accountProfile,
|
|
705
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
706
|
-
intent: "ingestion",
|
|
707
|
-
capability: "transcript-append",
|
|
708
|
-
});
|
|
709
|
-
accountId = connection.accountId;
|
|
710
|
-
if (!connection.appendTranscripts && !connection.appendTranscriptsWithReceipt)
|
|
711
|
-
throw new ZoomError("configuration_error", "the installed meeting store does not support transcript append");
|
|
712
|
-
store = {
|
|
713
|
-
appendTranscripts: connection.appendTranscripts,
|
|
714
|
-
appendTranscriptsWithReceipt: connection.appendTranscriptsWithReceipt,
|
|
715
|
-
};
|
|
716
|
-
}
|
|
717
|
-
for await (const item of applyArchiveImport(plan, store, {
|
|
718
|
-
accountId: accountId ?? 0,
|
|
625
|
+
const connection = await connected("ingestion");
|
|
626
|
+
for await (const item of applyArchiveImport(plan, connection, {
|
|
627
|
+
accountId: connection.accountId,
|
|
719
628
|
now: deps.now?.(),
|
|
720
629
|
signal: signal(),
|
|
721
630
|
}))
|
|
722
631
|
yield item;
|
|
723
632
|
},
|
|
724
|
-
search: async (request) =>
|
|
725
|
-
if (deps.unifiedSearch)
|
|
726
|
-
return runUnifiedSearch(deps.unifiedSearch, request);
|
|
727
|
-
const config = getConfig();
|
|
728
|
-
if (!config.accountProfile || !deps.connectStore)
|
|
729
|
-
throw new ZoomError("configuration_error", "select a stored local profile for unified search");
|
|
730
|
-
connection = await deps.connectStore({
|
|
731
|
-
profile: config.accountProfile,
|
|
732
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
733
|
-
intent: "read",
|
|
734
|
-
});
|
|
735
|
-
if (!connection.unifiedSearch)
|
|
736
|
-
throw new ZoomError("configuration_error", "unified search is unavailable in this store connector");
|
|
737
|
-
return runUnifiedSearch(connection.unifiedSearch, request);
|
|
738
|
-
},
|
|
633
|
+
search: async (request) => runUnifiedSearch((await connected()).unifiedSearch, request),
|
|
739
634
|
});
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
};
|
|
752
|
-
const integrationOutput = (value) => buffer(render(value, program.opts().jsonl ? "jsonl" : program.opts().json ? "json" : "text", deps, fields, true, false, execution?.meta));
|
|
753
|
-
addProjectEvidenceCommand(program, {
|
|
754
|
-
read: deps.meetingProjectEvidence,
|
|
755
|
-
connect: () => integrationConnection("meeting-project-evidence"),
|
|
756
|
-
signal,
|
|
757
|
-
now: deps.now,
|
|
758
|
-
output: integrationOutput,
|
|
635
|
+
addMeetingReadBindings(program, {
|
|
636
|
+
project: {
|
|
637
|
+
read: async (project, request) => (await connected()).meetingProjectEvidence(project, request),
|
|
638
|
+
signal,
|
|
639
|
+
now: deps.now,
|
|
640
|
+
output: (value) => output(bodyOf(value)),
|
|
641
|
+
},
|
|
642
|
+
preparation: {
|
|
643
|
+
...preparationOptions,
|
|
644
|
+
connect: () => openStore("read"),
|
|
645
|
+
},
|
|
759
646
|
});
|
|
760
647
|
addMeetingIntegrationCommands(program, {
|
|
761
648
|
signal,
|
|
762
|
-
output
|
|
649
|
+
output,
|
|
763
650
|
receipt,
|
|
764
|
-
integration: async () =>
|
|
765
|
-
if (deps.meetingIntegration)
|
|
766
|
-
return deps.meetingIntegration;
|
|
767
|
-
const connected = await integrationConnection("meeting-integration");
|
|
768
|
-
if (!connected.meetingIntegration)
|
|
769
|
-
throw new ZoomError("configuration_error", "meeting integration is unavailable in this store connector");
|
|
770
|
-
return connected.meetingIntegration;
|
|
771
|
-
},
|
|
651
|
+
integration: async () => (await connected()).meetingIntegration,
|
|
772
652
|
});
|
|
773
653
|
addLocalTranscriptionCommands(program, {
|
|
774
654
|
signal,
|
|
775
|
-
output
|
|
655
|
+
output,
|
|
776
656
|
receipt,
|
|
777
|
-
capabilities: async () =>
|
|
778
|
-
if (deps.meetingTranscription)
|
|
779
|
-
return deps.meetingTranscription;
|
|
780
|
-
const config = getConfig();
|
|
781
|
-
if (!config.accountProfile || !deps.connectStore)
|
|
782
|
-
throw new ZoomError("configuration_error", "select a stored local profile for transcription");
|
|
783
|
-
connection = await deps.connectStore({
|
|
784
|
-
profile: config.accountProfile,
|
|
785
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
786
|
-
intent: "read",
|
|
787
|
-
capability: "transcript-append",
|
|
788
|
-
});
|
|
789
|
-
if (!connection.meetingTranscription)
|
|
790
|
-
throw new ZoomError("configuration_error", "local transcription is unavailable in this store connector");
|
|
791
|
-
return connection.meetingTranscription;
|
|
792
|
-
},
|
|
657
|
+
capabilities: async () => (await connected()).meetingTranscription,
|
|
793
658
|
});
|
|
794
|
-
const meetingContext = async () =>
|
|
795
|
-
if (deps.meetingContext)
|
|
796
|
-
return deps.meetingContext;
|
|
797
|
-
const config = getConfig();
|
|
798
|
-
if (!config.accountProfile || !deps.connectStore)
|
|
799
|
-
throw new ZoomError("configuration_error", "select a stored local profile for meeting context");
|
|
800
|
-
connection = await deps.connectStore({
|
|
801
|
-
profile: config.accountProfile,
|
|
802
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
803
|
-
intent: "read",
|
|
804
|
-
});
|
|
805
|
-
if (!connection.meetingContext)
|
|
806
|
-
throw new ZoomError("configuration_error", "meeting context is unavailable in this store connector");
|
|
807
|
-
return connection.meetingContext;
|
|
808
|
-
};
|
|
659
|
+
const meetingContext = async () => (await connected()).meetingContext;
|
|
809
660
|
addMeetingContextCommands(program, {
|
|
810
661
|
signal,
|
|
811
|
-
output
|
|
662
|
+
output,
|
|
812
663
|
context: meetingContext,
|
|
813
664
|
});
|
|
814
665
|
addMeetingPassageCommand(program, {
|
|
815
666
|
signal,
|
|
816
667
|
read: async (reference, options) => {
|
|
817
668
|
if (fields && options.format !== "json")
|
|
818
|
-
throw new
|
|
819
|
-
|
|
820
|
-
if (!context.passage)
|
|
821
|
-
throw new ZoomError("configuration_error", "meeting passage is unavailable in this store connector");
|
|
822
|
-
return context.passage(reference, options);
|
|
669
|
+
throw new CliError("validation_error", "passage field selection requires --json or --format json");
|
|
670
|
+
return (await meetingContext()).passage(reference, options);
|
|
823
671
|
},
|
|
824
672
|
output: (result, format) => {
|
|
825
673
|
if (format === "json")
|
|
826
|
-
buffer(
|
|
674
|
+
buffer(rendered(bodyOf(result.packet), program.opts().jsonl ? "jsonl" : "json"));
|
|
827
675
|
else
|
|
828
676
|
buffer(result.content);
|
|
829
677
|
},
|
|
830
678
|
});
|
|
831
|
-
const meetingSemantic = async () =>
|
|
832
|
-
if (deps.meetingSemantic)
|
|
833
|
-
return deps.meetingSemantic;
|
|
834
|
-
const config = getConfig();
|
|
835
|
-
if (!config.accountProfile || !deps.connectStore)
|
|
836
|
-
throw new ZoomError("configuration_error", "select a stored local profile for meeting vectors");
|
|
837
|
-
connection = await deps.connectStore({
|
|
838
|
-
profile: config.accountProfile,
|
|
839
|
-
externalId: profileAccountKey(config.accountProfile),
|
|
840
|
-
intent: "read",
|
|
841
|
-
});
|
|
842
|
-
if (!connection.meetingSemantic)
|
|
843
|
-
throw new ZoomError("configuration_error", "meeting vector capabilities are unavailable in this store connector");
|
|
844
|
-
return connection.meetingSemantic;
|
|
845
|
-
};
|
|
679
|
+
const meetingSemantic = async () => (await connected()).meetingSemantic;
|
|
846
680
|
addMeetingSearchCommands(program, {
|
|
847
681
|
signal,
|
|
848
682
|
offline: () => Boolean(program.opts().offline),
|
|
849
|
-
output
|
|
850
|
-
words: async () =>
|
|
851
|
-
if (deps.meetingSearch)
|
|
852
|
-
return deps.meetingSearch;
|
|
853
|
-
const connected = await integrationConnection("meeting-search");
|
|
854
|
-
if (!connected.meetingSearch)
|
|
855
|
-
throw new ZoomError("configuration_error", "meeting search is unavailable in this store connector");
|
|
856
|
-
return connected.meetingSearch;
|
|
857
|
-
},
|
|
683
|
+
output,
|
|
684
|
+
words: async () => (await connected()).meetingSearch,
|
|
858
685
|
meaning: meetingSemantic,
|
|
859
686
|
archive: (deps.archiveTranscripts ?? { search: searchArchiveTranscripts }).search,
|
|
860
687
|
});
|
|
@@ -862,27 +689,29 @@ export const createProgram = (deps) => {
|
|
|
862
689
|
signal,
|
|
863
690
|
offline: () => Boolean(program.opts().offline),
|
|
864
691
|
receipt,
|
|
865
|
-
output
|
|
692
|
+
output,
|
|
866
693
|
capabilities: meetingSemantic,
|
|
867
694
|
});
|
|
868
695
|
annotateMeetingCommands(program);
|
|
869
696
|
const parseAsync = program.parseAsync.bind(program);
|
|
870
697
|
program.parseAsync = async (...args) => {
|
|
871
698
|
if (parsing)
|
|
872
|
-
throw new
|
|
699
|
+
throw new CliError("validation_error", "concurrent command parsing is unavailable");
|
|
873
700
|
resetCliOptions(program);
|
|
874
701
|
parsing = true;
|
|
702
|
+
answerExitCodes.set(program, 0);
|
|
875
703
|
config = undefined;
|
|
876
704
|
activeSource = undefined;
|
|
877
705
|
execution = undefined;
|
|
878
706
|
activeTokens = undefined;
|
|
879
707
|
watchConfig = undefined;
|
|
880
708
|
watchSince = undefined;
|
|
881
|
-
|
|
709
|
+
const lifted = liftJsonFields(program, args);
|
|
710
|
+
fields = lifted.fields;
|
|
882
711
|
let result = program;
|
|
883
712
|
let failed = false;
|
|
884
713
|
let failure;
|
|
885
|
-
const running = parseAsync(...args);
|
|
714
|
+
const running = parseAsync(...lifted.args);
|
|
886
715
|
void running.catch(() => { });
|
|
887
716
|
try {
|
|
888
717
|
const active = currentExecution();
|
|
@@ -894,18 +723,18 @@ export const createProgram = (deps) => {
|
|
|
894
723
|
failure = error;
|
|
895
724
|
}
|
|
896
725
|
finally {
|
|
897
|
-
if (
|
|
898
|
-
const closing =
|
|
899
|
-
|
|
726
|
+
if (connecting) {
|
|
727
|
+
const closing = connecting;
|
|
728
|
+
connecting = undefined;
|
|
900
729
|
selectedStore = deps.store;
|
|
901
730
|
selectedAccountId = deps.accountId;
|
|
902
731
|
try {
|
|
903
|
-
await closing.close();
|
|
732
|
+
await (await closing.catch(() => undefined))?.close();
|
|
904
733
|
}
|
|
905
734
|
catch {
|
|
906
735
|
if (!failed) {
|
|
907
736
|
failed = true;
|
|
908
|
-
failure = new
|
|
737
|
+
failure = new CliError("configuration_error", "could not close the shared meeting store");
|
|
909
738
|
}
|
|
910
739
|
}
|
|
911
740
|
}
|
|
@@ -935,7 +764,7 @@ export const run = async (args, deps) => {
|
|
|
935
764
|
const program = createProgram(deps);
|
|
936
765
|
try {
|
|
937
766
|
await program.parseAsync(args, { from: "user" });
|
|
938
|
-
return 0;
|
|
767
|
+
return answerExitCodes.get(program) ?? 0;
|
|
939
768
|
}
|
|
940
769
|
catch (error) {
|
|
941
770
|
if (typeof error === "object" &&
|
|
@@ -947,18 +776,19 @@ export const run = async (args, deps) => {
|
|
|
947
776
|
const failure = isCliError(error)
|
|
948
777
|
? error
|
|
949
778
|
: unknownOutcome
|
|
950
|
-
? new
|
|
779
|
+
? new CliError("outcome_unknown", "operation outcome is unknown; verify stored state before retrying")
|
|
951
780
|
: error instanceof CommanderError
|
|
952
|
-
? new
|
|
781
|
+
? new CliError("validation_error", "command failed; use --help for usage")
|
|
953
782
|
: error;
|
|
954
|
-
|
|
783
|
+
const selected = commandSelection(program, args);
|
|
784
|
+
return reportFailure(failure, args, deps, selected.path, hostFailureContext(program, metaOf(selected.action).effects));
|
|
955
785
|
}
|
|
956
786
|
};
|
|
957
|
-
export const reportFailure = (failure, args, deps, command = "zm") => {
|
|
787
|
+
export const reportFailure = (failure, args, deps, command = "zm", context = hostFailureContext()) => {
|
|
958
788
|
const end = args.indexOf("--");
|
|
959
789
|
const flags = args.slice(0, end < 0 ? undefined : end);
|
|
960
790
|
const machine = flags.some((word) => word === "--json" || word === "--jsonl");
|
|
961
|
-
const object = errorObjectOf(failure,
|
|
791
|
+
const object = errorObjectOf(failure, context);
|
|
962
792
|
const record = flags.includes("--debug")
|
|
963
793
|
? errorRecordOf(failure, object, { command, service: "zm", version: VERSION })
|
|
964
794
|
: undefined;
|
|
@@ -966,7 +796,7 @@ export const reportFailure = (failure, args, deps, command = "zm") => {
|
|
|
966
796
|
deps.diagnostic(`${renderError(object, { cli: "zm", interactive, ...(record ? { record } : {}) })}\n`);
|
|
967
797
|
return exitCodeOfError(object);
|
|
968
798
|
};
|
|
969
|
-
const
|
|
799
|
+
const commandSelection = (program, args) => {
|
|
970
800
|
const words = [];
|
|
971
801
|
let current = program;
|
|
972
802
|
for (const word of args) {
|
|
@@ -980,6 +810,6 @@ const commandPath = (program, args) => {
|
|
|
980
810
|
words.push(word);
|
|
981
811
|
current = next;
|
|
982
812
|
}
|
|
983
|
-
return words.length ? words.join(" ") : "zm";
|
|
813
|
+
return { path: words.length ? words.join(" ") : "zm", action: current };
|
|
984
814
|
};
|
|
985
815
|
//# sourceMappingURL=program.js.map
|