@wirecat/zoom-cli 0.56.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/zm.js +35 -5
  3. package/dist/bundle/all-profiles-EKHWTGOY.js +25 -0
  4. package/dist/bundle/answer-policy-KH2IFXPN.js +96 -0
  5. package/dist/bundle/anthropic-VL54IUGF.js +70 -0
  6. package/dist/bundle/bun-ADJVI4HY.js +169 -0
  7. package/dist/bundle/bun-sqlite-2SDA3YOT.js +69 -0
  8. package/dist/bundle/chunk-2IKY7VBH.js +9 -0
  9. package/dist/bundle/chunk-2WOGZDZG.js +431 -0
  10. package/dist/bundle/chunk-4R7HYNZS.js +73 -0
  11. package/dist/bundle/chunk-4VCA7QU3.js +538 -0
  12. package/dist/bundle/chunk-4YLS4YLS.js +29 -0
  13. package/dist/bundle/chunk-5D4AEUVA.js +24783 -0
  14. package/dist/bundle/chunk-5F7IOESV.js +281 -0
  15. package/dist/bundle/chunk-5QESMCQK.js +122 -0
  16. package/dist/bundle/chunk-6M6FJV5D.js +138 -0
  17. package/dist/bundle/chunk-6MX5T6AQ.js +17 -0
  18. package/dist/bundle/chunk-6P3YHT54.js +385 -0
  19. package/dist/bundle/chunk-7A6PZUDR.js +938 -0
  20. package/dist/bundle/chunk-7GUG6UZS.js +884 -0
  21. package/dist/bundle/chunk-7JZJMHQY.js +487 -0
  22. package/dist/bundle/chunk-A4ETXPMZ.js +98 -0
  23. package/dist/bundle/chunk-ADLS6FVG.js +24600 -0
  24. package/dist/bundle/chunk-AE4BOXH7.js +5292 -0
  25. package/dist/bundle/chunk-AN3GVZTU.js +76 -0
  26. package/dist/bundle/chunk-BAYNCCNM.js +215 -0
  27. package/dist/bundle/chunk-BW2WPOXP.js +166 -0
  28. package/dist/bundle/chunk-BW52AJ4R.js +3387 -0
  29. package/dist/bundle/chunk-CB5UTASG.js +18 -0
  30. package/dist/bundle/chunk-CLMXBW53.js +1028 -0
  31. package/dist/bundle/chunk-DCTXOMOR.js +35 -0
  32. package/dist/bundle/chunk-DFDN6AUB.js +21 -0
  33. package/dist/bundle/chunk-EOQFWJJD.js +1095 -0
  34. package/dist/bundle/chunk-G4R4ZIGD.js +3569 -0
  35. package/dist/bundle/chunk-G4VZDINN.js +161 -0
  36. package/dist/bundle/chunk-GARCOIB6.js +409 -0
  37. package/dist/bundle/chunk-GKMGS7G5.js +1938 -0
  38. package/dist/bundle/chunk-HCNMFFG3.js +82 -0
  39. package/dist/bundle/chunk-HG5KRV55.js +1970 -0
  40. package/dist/bundle/chunk-HKYLSIZ2.js +82 -0
  41. package/dist/bundle/chunk-HTQTIKWP.js +928 -0
  42. package/dist/bundle/chunk-I4VQDXFR.js +100 -0
  43. package/dist/bundle/chunk-ICSKEDPI.js +36139 -0
  44. package/dist/bundle/chunk-IP4OK7RQ.js +24 -0
  45. package/dist/bundle/chunk-IVQ6342B.js +2 -0
  46. package/dist/bundle/chunk-K72SEMYI.js +160 -0
  47. package/dist/bundle/chunk-LHRCJYFC.js +19 -0
  48. package/dist/bundle/chunk-LPTIQLDW.js +192 -0
  49. package/dist/bundle/chunk-LQ3T2ZIX.js +124 -0
  50. package/dist/bundle/chunk-LSVI3A5X.js +836 -0
  51. package/dist/bundle/chunk-LW2G4U6W.js +570 -0
  52. package/dist/bundle/chunk-LXB6ONWC.js +3517 -0
  53. package/dist/bundle/chunk-LY26NW3I.js +6848 -0
  54. package/dist/bundle/chunk-MAEFLDHG.js +6092 -0
  55. package/dist/bundle/chunk-MZH4GDR4.js +45 -0
  56. package/dist/bundle/chunk-NN5B24KP.js +1109 -0
  57. package/dist/bundle/chunk-NO7CJEYV.js +22 -0
  58. package/dist/bundle/chunk-NTDWAAGL.js +18435 -0
  59. package/dist/bundle/chunk-NW3X3G5X.js +264 -0
  60. package/dist/bundle/chunk-O66V2WHK.js +48 -0
  61. package/dist/bundle/chunk-OCGPZHXW.js +25 -0
  62. package/dist/bundle/chunk-OIHDCGV4.js +151 -0
  63. package/dist/bundle/chunk-OVSWVPXL.js +8190 -0
  64. package/dist/bundle/chunk-PIN5RZ3D.js +63 -0
  65. package/dist/bundle/chunk-QLIB3PEC.js +1146 -0
  66. package/dist/bundle/chunk-QTR6D5HT.js +58 -0
  67. package/dist/bundle/chunk-QUJPQMHJ.js +2315 -0
  68. package/dist/bundle/chunk-R3HPOCZD.js +188 -0
  69. package/dist/bundle/chunk-RMV4C2YL.js +482 -0
  70. package/dist/bundle/chunk-RRRBMQ2E.js +844 -0
  71. package/dist/bundle/chunk-S4S7E54J.js +60 -0
  72. package/dist/bundle/chunk-SB6WOSHG.js +1109 -0
  73. package/dist/bundle/chunk-SE75DPBY.js +31 -0
  74. package/dist/bundle/chunk-SQJ7EH2D.js +97 -0
  75. package/dist/bundle/chunk-TKCHUT2H.js +422 -0
  76. package/dist/bundle/chunk-TLQUKHEM.js +193 -0
  77. package/dist/bundle/chunk-TZ2MKETI.js +100 -0
  78. package/dist/bundle/chunk-UC44ZMQV.js +78 -0
  79. package/dist/bundle/chunk-UI5UTMSZ.js +275 -0
  80. package/dist/bundle/chunk-VPPYYWOH.js +630 -0
  81. package/dist/bundle/chunk-WJHK5D7Z.js +35612 -0
  82. package/dist/bundle/chunk-WQ24UC44.js +239 -0
  83. package/dist/bundle/chunk-X5DFDGWS.js +2 -0
  84. package/dist/bundle/chunk-Y5E2WNWB.js +35 -0
  85. package/dist/bundle/chunk-YB4DMKYX.js +119 -0
  86. package/dist/bundle/chunk-Z4TZ6TAF.js +288 -0
  87. package/dist/bundle/chunk-ZVVMGPBJ.js +50 -0
  88. package/dist/bundle/cli-72EQATJF.js +825 -0
  89. package/dist/bundle/command-contract-4MHSZUN3.js +38 -0
  90. package/dist/bundle/config-GFIJK6G2.js +79 -0
  91. package/dist/bundle/dist-IBNHCQXT.js +136 -0
  92. package/dist/bundle/dist-XUFQCJXW.js +7577 -0
  93. package/dist/bundle/echarts-RFTK737T.js +42501 -0
  94. package/dist/bundle/embed-7QYA2ZZE.js +35 -0
  95. package/dist/bundle/embedder-YNN6PCHG.js +108 -0
  96. package/dist/bundle/first-run-EVSRQKZJ.js +23 -0
  97. package/dist/bundle/first-screen-RG4GUKW7.js +36 -0
  98. package/dist/bundle/folders-JEPOMYM4.js +13 -0
  99. package/dist/bundle/instructions-FHNL7CMW.js +9 -0
  100. package/dist/bundle/main-NYGJXPH7.js +130 -0
  101. package/dist/bundle/mcp-IXFC2VVR.js +165 -0
  102. package/dist/bundle/mcp-VGSZDCKK.js +189 -0
  103. package/dist/bundle/mcp-XKP2PXLS.js +92 -0
  104. package/dist/bundle/meetings-IBPI4MM4.js +215 -0
  105. package/dist/bundle/node-P4E63KXA.js +2340 -0
  106. package/dist/bundle/node-TLZSIHIJ.js +21 -0
  107. package/dist/bundle/node-ZMCACJVS.js +176 -0
  108. package/dist/bundle/node-sqlite-ZNGOBA5Q.js +45 -0
  109. package/dist/bundle/oauth-Q6LKF7DB.js +17 -0
  110. package/dist/bundle/open-LJ332Y5O.js +19 -0
  111. package/dist/bundle/output-file-RYQZ3RTE.js +63 -0
  112. package/dist/bundle/process-ZPTLNVQS.js +91 -0
  113. package/dist/bundle/program-IBRQBQ6W.js +5845 -0
  114. package/dist/bundle/prompt-RT7GUUXH.js +12 -0
  115. package/dist/bundle/recognize-QXGE7YJH.js +190 -0
  116. package/dist/bundle/remote-FD4MZQV3.js +26 -0
  117. package/dist/bundle/rerank-V6AVV755.js +49 -0
  118. package/dist/bundle/run-log-RE2EI3UU.js +111 -0
  119. package/dist/bundle/serve-HIJTFAW7.js +19 -0
  120. package/dist/bundle/server-3QOXOYYL.js +53 -0
  121. package/dist/bundle/server-WLJCU7KK.js +812 -0
  122. package/dist/bundle/services-KC5KQFBS.js +330 -0
  123. package/dist/bundle/speech-5JOXLYDA.js +44 -0
  124. package/dist/bundle/state-PPGRB3T6.js +33 -0
  125. package/dist/bundle/store-LODVDPK3.js +141 -0
  126. package/dist/bundle/store-WB5BICTG.js +124 -0
  127. package/dist/bundle/store-connection-EG6Z5ITP.js +76 -0
  128. package/dist/bundle/store-maintenance-command-Q5WMFUZ2.js +54 -0
  129. package/dist/bundle/streaming-UGFFNOXL.js +15 -0
  130. package/dist/bundle/tokens-AF5CPY2F.js +17 -0
  131. package/dist/bundle/zm.js +8 -0
  132. package/dist/contract-overrides.d.ts.map +1 -1
  133. package/dist/contract-overrides.js +18 -16
  134. package/dist/contract-overrides.js.map +1 -1
  135. package/dist/mcp-command.d.ts +3 -2
  136. package/dist/mcp-command.d.ts.map +1 -1
  137. package/dist/mcp-command.js +62 -10
  138. package/dist/mcp-command.js.map +1 -1
  139. package/dist/program-bindings.d.ts.map +1 -1
  140. package/dist/program-bindings.js +1 -0
  141. package/dist/program-bindings.js.map +1 -1
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/package.json +7 -5
  145. package/skills/zoom-cli/SKILL.md +2 -0
@@ -0,0 +1,385 @@
1
+ import { createRequire as __bundleRequire } from "node:module";
2
+ const require = __bundleRequire(import.meta.url);
3
+ import {
4
+ parsePermissions
5
+ } from "./chunk-7A6PZUDR.js";
6
+ import {
7
+ checkConfigText,
8
+ issueMessage,
9
+ usableProfileName
10
+ } from "./chunk-MAEFLDHG.js";
11
+ import {
12
+ LEVELS
13
+ } from "./chunk-TKCHUT2H.js";
14
+ import {
15
+ CliError,
16
+ array,
17
+ boolean,
18
+ check,
19
+ integer,
20
+ literal,
21
+ maxLength,
22
+ minValue,
23
+ nullable,
24
+ number,
25
+ optional,
26
+ parse,
27
+ picklist,
28
+ pipe,
29
+ record,
30
+ regex,
31
+ safeParse,
32
+ saveConfigFile,
33
+ strictObject,
34
+ string,
35
+ union
36
+ } from "./chunk-AE4BOXH7.js";
37
+ import {
38
+ __name
39
+ } from "./chunk-ZVVMGPBJ.js";
40
+
41
+ // dist/config.js
42
+ import { existsSync, readFileSync, statSync } from "node:fs";
43
+
44
+ // dist/config-issues.js
45
+ var isNode = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isNode");
46
+ var SETTING_NAMES = {
47
+ client_id: "zoom.client_id",
48
+ source: "source",
49
+ files_folder: "files.folder",
50
+ files_timezone: "files.timezone",
51
+ context_sources: "context.sources",
52
+ record: "record",
53
+ keep_runs_for_days: "keep_runs_for_days",
54
+ keep_successful_runs_for_days: "keep_successful_runs_for_days",
55
+ runs_size_limit_mb: "runs_size_limit_mb",
56
+ record_input: "record_input"
57
+ };
58
+ var SHELL_SAFE = /^[A-Za-z0-9_.:@-]*$/;
59
+ var fileIssue = /* @__PURE__ */ __name((file, what) => ({ kind: "invalid_value", file, what, at: [] }), "fileIssue");
60
+ var pathOf = /* @__PURE__ */ __name((raw, { profile, key }) => {
61
+ if (key === void 0)
62
+ return [];
63
+ if (profile !== void 0) {
64
+ const entry = isNode(raw.profiles) ? raw.profiles[profile] : void 0;
65
+ const permission = key.startsWith("permissions.") && !(isNode(entry) && Object.hasOwn(entry, key));
66
+ return permission ? ["profiles", profile, "permissions", key.slice("permissions.".length)] : ["profiles", profile, key];
67
+ }
68
+ if (Object.hasOwn(raw, key))
69
+ return [key];
70
+ if (key.startsWith("profiles."))
71
+ return ["profiles", key.slice("profiles.".length)];
72
+ return [key.split(".")[0]];
73
+ }, "pathOf");
74
+ var inZmTerms = /* @__PURE__ */ __name((raw, issue) => {
75
+ const { fix: _, key: shared, ...rest } = issue;
76
+ const at = pathOf(raw, issue);
77
+ const [first] = at;
78
+ if (shared === void 0 || first === void 0)
79
+ return { ...rest, at };
80
+ const key = first === "profiles" ? shared : SETTING_NAMES[first] ?? first;
81
+ const named = key + shared.slice(first === "profiles" ? shared.length : first.length);
82
+ const fixable = [key, issue.profile ?? ""].every((word) => SHELL_SAFE.test(word));
83
+ return {
84
+ ...rest,
85
+ kind: issue.kind === "missing_setting" ? "invalid_value" : issue.kind,
86
+ key,
87
+ what: issue.what.replace(`setting ${shared}`, `setting ${named}`),
88
+ ...fixable ? { fix: `zm${issue.profile === void 0 ? "" : ` ${issue.profile}`} config unset ${key}` } : {},
89
+ at
90
+ };
91
+ }, "inZmTerms");
92
+ var configIssues = /* @__PURE__ */ __name((text, file, schema, permissionKeys) => {
93
+ const checked = checkConfigText(text, { file, tool: "zm", schema });
94
+ const broken = checked.issues.find((issue) => issue.kind === "invalid_json");
95
+ if (broken)
96
+ return { issues: [{ ...broken, at: [] }], raw: null };
97
+ const raw = JSON.parse(text);
98
+ if (!isNode(raw))
99
+ return { issues: [fileIssue(file, "the file has to be an object, in braces")], raw: null };
100
+ const found = /* @__PURE__ */ new Map();
101
+ const add = /* @__PURE__ */ __name((issue) => {
102
+ const id = issue.at.join("\0");
103
+ if (!found.has(id))
104
+ found.set(id, issue);
105
+ }, "add");
106
+ for (const issue of checked.issues)
107
+ add(inZmTerms(raw, issue));
108
+ if (permissionKeys) {
109
+ const rest = JSON.stringify(withoutIssues(raw, [...found.values()]));
110
+ for (const issue of checkConfigText(rest, { file, tool: "zm", schema, knownPermissions: permissionKeys }).issues)
111
+ if (issue.kind === "unknown_permission")
112
+ add(inZmTerms(raw, issue));
113
+ }
114
+ return { issues: [...found.values()], raw };
115
+ }, "configIssues");
116
+ var withoutIssues = /* @__PURE__ */ __name((raw, issues) => {
117
+ const copy = structuredClone(raw);
118
+ for (const { at } of issues)
119
+ removeAt(copy, at);
120
+ return copy;
121
+ }, "withoutIssues");
122
+ var removeAt = /* @__PURE__ */ __name((raw, at) => {
123
+ const parent = at.slice(0, -1).reduce((node, key) => isNode(node) ? node[key] : void 0, raw);
124
+ if (isNode(parent))
125
+ delete parent[at.at(-1)];
126
+ }, "removeAt");
127
+ var publicIssue = /* @__PURE__ */ __name(({ at: _, ...issue }) => issue, "publicIssue");
128
+
129
+ // dist/profile.js
130
+ var profilePattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
131
+ var profileAccountKey = /* @__PURE__ */ __name((profile) => `zm-profile:${profile}`, "profileAccountKey");
132
+ var given = /* @__PURE__ */ __name((value) => value?.trim() ? value.trim() : void 0, "given");
133
+ var usable = /* @__PURE__ */ __name((profile) => {
134
+ usableProfileName(profile);
135
+ if (!profilePattern.test(profile))
136
+ throw new CliError("validation_error", `"${profile}" cannot be a profile name \u2014 64 characters at most`);
137
+ return profile;
138
+ }, "usable");
139
+ var chooseProfile = /* @__PURE__ */ __name(({ word, env, profiles }) => {
140
+ const lock = given(env.ZM_PROFILE_LOCK);
141
+ const named = word !== void 0 ? word : given(env.ZM_PROFILE);
142
+ if (lock !== void 0)
143
+ usable(lock);
144
+ if (named !== void 0 && lock !== void 0 && named !== lock)
145
+ throw new CliError("permission_error", `this process is locked to profile ${lock} (ZM_PROFILE_LOCK) \u2014 profile ${named} is refused`);
146
+ const profile = named ?? lock;
147
+ if (profile === void 0) {
148
+ const here = profiles();
149
+ throw new CliError("validation_error", here.length === 0 ? "name a profile: there is none on this computer yet \u2014 create one with `zm personal session start` (any name in place of personal)" : `name a profile: \`zm <profile> \u2026\` \u2014 profiles here: ${here.join(", ")} (or set ZM_PROFILE)`, { profiles: [...here] });
150
+ }
151
+ return usable(profile);
152
+ }, "chooseProfile");
153
+
154
+ // dist/context-sources.js
155
+ var fields = {
156
+ id: pipe(string(), regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/)),
157
+ kind: picklist(["message", "mail", "document"]),
158
+ provider: pipe(string(), check((s) => !!s.trim() && Buffer.byteLength(s) <= 128)),
159
+ account: pipe(string(), check((s) => !!s.trim() && Buffer.byteLength(s) <= 1024))
160
+ };
161
+ var selected = pipe(array(strictObject(fields)), maxLength(8));
162
+ var contextSourcesSchema = pipe(array(strictObject({ ...fields, profile: pipe(string(), regex(profilePattern)) })), maxLength(64), check((entries) => {
163
+ const ids = /* @__PURE__ */ new Set(), identities = /* @__PURE__ */ new Set(), counts = /* @__PURE__ */ new Map();
164
+ for (const entry of entries) {
165
+ const id = JSON.stringify([entry.profile, entry.id]), key = JSON.stringify([entry.profile, entry.kind, entry.provider, entry.account]);
166
+ const count = (counts.get(entry.profile) ?? 0) + 1;
167
+ if (ids.has(id) || identities.has(key) || count > 8)
168
+ return false;
169
+ ids.add(id);
170
+ identities.add(key);
171
+ counts.set(entry.profile, count);
172
+ }
173
+ return true;
174
+ }));
175
+ var replaceContextSources = /* @__PURE__ */ __name((value, profile, existing = []) => {
176
+ if (!profile)
177
+ throw new CliError("configuration_error", "name a profile: `zm <profile> config set context.sources \u2026`");
178
+ let input;
179
+ try {
180
+ input = JSON.parse(value);
181
+ } catch {
182
+ throw new CliError("validation_error", "context.sources must be a JSON array");
183
+ }
184
+ const parsed = safeParse(selected, input);
185
+ if (!parsed.success)
186
+ throw new CliError("validation_error", "context.sources needs at most eight unique source IDs with kind/provider/account; unknown fields are refused");
187
+ const combined = [...existing.filter((s) => s.profile !== profile), ...parsed.output.map((s) => ({ ...s, profile }))];
188
+ const all = safeParse(contextSourcesSchema, combined);
189
+ if (!all.success)
190
+ throw new CliError("validation_error", "context.sources contains duplicate IDs/identities or exceeds its profile limits");
191
+ return all.output;
192
+ }, "replaceContextSources");
193
+
194
+ // dist/config.js
195
+ var ProfileEntry = strictObject({
196
+ permissions: optional(record(pipe(string(), regex(/^[a-z][a-z.-]*$/)), picklist(LEVELS)))
197
+ });
198
+ var ConfigFile = strictObject({
199
+ client_id: optional(nullable(pipe(string(), check((id) => id.trim() !== "" && !/\s/.test(id), "has to be a Zoom client ID, without spaces")))),
200
+ source: optional(picklist(["api", "files"])),
201
+ files_folder: optional(nullable(string())),
202
+ files_timezone: optional(nullable(pipe(string(), check((zone) => {
203
+ try {
204
+ new Intl.DateTimeFormat("en", { timeZone: zone });
205
+ return true;
206
+ } catch {
207
+ return false;
208
+ }
209
+ }, "has to be an IANA time zone, such as Europe/Madrid")))),
210
+ profiles: optional(record(pipe(string(), regex(profilePattern, "has to be a profile name of 64 characters at most")), ProfileEntry)),
211
+ context_sources: optional(contextSourcesSchema),
212
+ record: optional(boolean()),
213
+ keep_runs_for_days: optional(pipe(number(), integer(), minValue(1))),
214
+ keep_successful_runs_for_days: optional(pipe(number(), integer(), minValue(1))),
215
+ runs_size_limit_mb: optional(pipe(number(), integer(), minValue(1))),
216
+ record_input: optional(union([boolean(), literal("failed")]))
217
+ });
218
+ var DOCTOR = "zm doctor";
219
+ var configOf = /* @__PURE__ */ __name((file) => ({
220
+ clientId: file.client_id ?? null,
221
+ source: file.source ?? "api",
222
+ filesFolder: file.files_folder ?? null,
223
+ filesTimezone: file.files_timezone ?? null,
224
+ profiles: Object.keys(file.profiles ?? {}).sort(),
225
+ permissions: Object.fromEntries(Object.entries(file.profiles ?? {}).flatMap(([name, entry]) => entry.permissions ? [[name, entry.permissions]] : [])),
226
+ ...file.context_sources === void 0 ? {} : { contextSources: file.context_sources },
227
+ ...file.record === void 0 ? {} : { record: file.record },
228
+ ...file.keep_runs_for_days === void 0 ? {} : { keepRunsForDays: file.keep_runs_for_days },
229
+ ...file.keep_successful_runs_for_days === void 0 ? {} : { keepSuccessfulRunsForDays: file.keep_successful_runs_for_days },
230
+ ...file.runs_size_limit_mb === void 0 ? {} : { runsSizeLimitMb: file.runs_size_limit_mb },
231
+ ...file.record_input === void 0 ? {} : { recordInput: file.record_input }
232
+ }), "configOf");
233
+ var inspectConfig = /* @__PURE__ */ __name((path, permissionKeys) => {
234
+ let text;
235
+ try {
236
+ text = readFileSync(path, "utf8");
237
+ } catch {
238
+ if (!existsSync(path))
239
+ return { found: false, issues: [], raw: {}, config: configOf({}) };
240
+ const what = statSync(path, { throwIfNoEntry: false })?.isDirectory() ? "the path is a folder, not a file" : "the file could not be read";
241
+ return { found: true, issues: [fileIssue(path, what)], raw: null, config: configOf({}) };
242
+ }
243
+ const { issues, raw } = configIssues(text, path, ConfigFile, permissionKeys);
244
+ return {
245
+ found: true,
246
+ issues,
247
+ raw,
248
+ config: configOf(raw ? parse(ConfigFile, withoutIssues(raw, issues)) : {})
249
+ };
250
+ }, "inspectConfig");
251
+ var readConfig = /* @__PURE__ */ __name((path, permissionKeys) => {
252
+ const { issues, config } = inspectConfig(path, permissionKeys);
253
+ if (issues.length > 0)
254
+ throw new CliError("configuration_error", issueMessage(issues.map(publicIssue), DOCTOR));
255
+ return config;
256
+ }, "readConfig");
257
+ var changeFile = /* @__PURE__ */ __name((path, permissionKeys, change) => {
258
+ const inspection = inspectConfig(path, permissionKeys);
259
+ if (!inspection.raw)
260
+ throw new CliError("configuration_error", issueMessage(inspection.issues.map(publicIssue), DOCTOR));
261
+ const raw = structuredClone(inspection.raw);
262
+ change(raw, inspection);
263
+ saveConfigFile(path, raw);
264
+ return inspectConfig(path, permissionKeys).config;
265
+ }, "changeFile");
266
+ var profileEntry = /* @__PURE__ */ __name((raw, profile) => {
267
+ if (!isNode(raw.profiles))
268
+ raw.profiles = {};
269
+ const profiles = raw.profiles;
270
+ if (!isNode(profiles[profile]))
271
+ profiles[profile] = {};
272
+ return profiles[profile];
273
+ }, "profileEntry");
274
+ var FILE_KEYS = Object.fromEntries(Object.entries(SETTING_NAMES).map(([file, name]) => [name, file]));
275
+ var setConfig = /* @__PURE__ */ __name((path, key, value, profile, permissionKeys) => changeFile(path, permissionKeys, (raw, { config, issues }) => {
276
+ switch (key) {
277
+ case "permissions": {
278
+ const name = profile?.();
279
+ if (!name)
280
+ throw new CliError("validation_error", "name a profile: `zm <profile> config set permissions \u2026`");
281
+ profileEntry(raw, name).permissions = parsePermissions(value, permissionKeys ?? /* @__PURE__ */ new Set());
282
+ return;
283
+ }
284
+ case "context.sources": {
285
+ const broken = issues.find((issue) => issue.at[0] === "context_sources");
286
+ if (broken)
287
+ throw new CliError("configuration_error", issueMessage([publicIssue(broken)], DOCTOR));
288
+ raw.context_sources = replaceContextSources(value, profile?.() ?? null, config.contextSources);
289
+ return;
290
+ }
291
+ case "zoom.client_id":
292
+ if (!value.trim() || /\s/.test(value))
293
+ throw new CliError("validation_error", "client id must not contain whitespace");
294
+ raw.client_id = value;
295
+ return;
296
+ case "source":
297
+ if (value !== "api" && value !== "files")
298
+ throw new CliError("validation_error", "source must be api or files");
299
+ raw.source = value;
300
+ return;
301
+ case "files.folder":
302
+ if (!value.trim())
303
+ throw new CliError("validation_error", "folder must not be empty");
304
+ raw.files_folder = value;
305
+ return;
306
+ case "files.timezone":
307
+ try {
308
+ new Intl.DateTimeFormat("en", { timeZone: value });
309
+ } catch {
310
+ throw new CliError("validation_error", "expected an IANA time zone");
311
+ }
312
+ raw.files_timezone = value;
313
+ return;
314
+ case "record":
315
+ if (value !== "true" && value !== "false")
316
+ throw new CliError("validation_error", "record must be true or false");
317
+ raw.record = value === "true";
318
+ return;
319
+ case "keep_runs_for_days":
320
+ if (!/^[1-9]\d{0,4}$/.test(value))
321
+ throw new CliError("validation_error", "keep_runs_for_days must be a whole number of days, 1 or more");
322
+ raw.keep_runs_for_days = Number(value);
323
+ return;
324
+ case "record_input":
325
+ if (value !== "true" && value !== "false" && value !== "failed")
326
+ throw new CliError("validation_error", "record_input must be true, false or failed");
327
+ raw.record_input = value === "failed" ? value : value === "true";
328
+ return;
329
+ case "keep_successful_runs_for_days":
330
+ if (!/^[1-9]\d{0,4}$/.test(value))
331
+ throw new CliError("validation_error", "keep_successful_runs_for_days must be a whole number of days, 1 or more");
332
+ raw.keep_successful_runs_for_days = Number(value);
333
+ return;
334
+ case "runs_size_limit_mb":
335
+ if (!/^[1-9]\d{0,5}$/.test(value))
336
+ throw new CliError("validation_error", "runs_size_limit_mb must be a whole number of megabytes, 1 or more");
337
+ raw.runs_size_limit_mb = Number(value);
338
+ return;
339
+ default:
340
+ throw new CliError("validation_error", "unknown config key");
341
+ }
342
+ }), "setConfig");
343
+ var unsetConfig = /* @__PURE__ */ __name((path, key, profile, permissionKeys) => changeFile(path, permissionKeys, (raw, { issues }) => {
344
+ const reported = issues.find((issue) => issue.key === key && (issue.profile === void 0 || issue.profile === profile));
345
+ if (key === "context.sources" && !reported && profile !== void 0 && Array.isArray(raw.context_sources)) {
346
+ raw.context_sources = raw.context_sources.filter((source) => !isNode(source) || source.profile !== profile);
347
+ return;
348
+ }
349
+ const at = reported?.at ?? (FILE_KEYS[key] ? [FILE_KEYS[key]] : profileSettingAt(key, profile));
350
+ removeAt(raw, at);
351
+ const entry = isNode(raw.profiles) ? raw.profiles[at[1] ?? ""] : void 0;
352
+ if (at[2] === "permissions" && isNode(entry) && isNode(entry.permissions)) {
353
+ if (Object.keys(entry.permissions).length === 0)
354
+ delete entry.permissions;
355
+ }
356
+ }), "unsetConfig");
357
+ var profileSettingAt = /* @__PURE__ */ __name((key, profile) => {
358
+ if (key !== "permissions" && !key.startsWith("permissions."))
359
+ throw new CliError("validation_error", "unknown config key");
360
+ if (!profile)
361
+ throw new CliError("validation_error", `name a profile: \`zm <profile> config unset ${key}\``);
362
+ return key === "permissions" ? ["profiles", profile, "permissions"] : ["profiles", profile, "permissions", key.slice("permissions.".length)];
363
+ }, "profileSettingAt");
364
+ var addProfile = /* @__PURE__ */ __name((path, profile) => {
365
+ if (readConfig(path).profiles.includes(profile))
366
+ return;
367
+ changeFile(path, void 0, (raw) => {
368
+ profileEntry(raw, profile);
369
+ });
370
+ }, "addProfile");
371
+ var filesZone = /* @__PURE__ */ __name((config) => config.filesTimezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone, "filesZone");
372
+
373
+ export {
374
+ publicIssue,
375
+ profilePattern,
376
+ profileAccountKey,
377
+ chooseProfile,
378
+ contextSourcesSchema,
379
+ inspectConfig,
380
+ readConfig,
381
+ setConfig,
382
+ unsetConfig,
383
+ addProfile,
384
+ filesZone
385
+ };