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