@wirecat/zoom-cli 0.2.2 → 0.3.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 +98 -3
- package/dist/archive-import.d.ts +27 -0
- package/dist/archive-import.d.ts.map +1 -0
- package/dist/archive-import.js +125 -0
- package/dist/archive-import.js.map +1 -0
- package/dist/archive-transcripts.d.ts.map +1 -1
- package/dist/archive-transcripts.js +3 -3
- package/dist/archive-transcripts.js.map +1 -1
- package/dist/bin/zm.js +6 -1
- package/dist/bin/zm.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/ingestion-search-commands.d.ts +15 -0
- package/dist/ingestion-search-commands.d.ts.map +1 -0
- package/dist/ingestion-search-commands.js +66 -0
- package/dist/ingestion-search-commands.js.map +1 -0
- package/dist/mcp-server.d.ts +6 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +209 -6
- package/dist/mcp-server.js.map +1 -1
- package/dist/meeting-context-commands.d.ts +8 -0
- package/dist/meeting-context-commands.d.ts.map +1 -0
- package/dist/meeting-context-commands.js +77 -0
- package/dist/meeting-context-commands.js.map +1 -0
- package/dist/meeting-context.d.ts +30 -0
- package/dist/meeting-context.d.ts.map +1 -0
- package/dist/meeting-context.js +119 -0
- package/dist/meeting-context.js.map +1 -0
- package/dist/meeting-semantic-commands.d.ts +38 -0
- package/dist/meeting-semantic-commands.d.ts.map +1 -0
- package/dist/meeting-semantic-commands.js +98 -0
- package/dist/meeting-semantic-commands.js.map +1 -0
- package/dist/meeting-semantic.d.ts +10 -0
- package/dist/meeting-semantic.d.ts.map +1 -0
- package/dist/meeting-semantic.js +70 -0
- package/dist/meeting-semantic.js.map +1 -0
- package/dist/ordinary-file.d.ts +4 -0
- package/dist/ordinary-file.d.ts.map +1 -0
- package/dist/ordinary-file.js +51 -0
- package/dist/ordinary-file.js.map +1 -0
- package/dist/program.d.ts +16 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +138 -9
- package/dist/program.js.map +1 -1
- package/dist/recording-archive.d.ts.map +1 -1
- package/dist/recording-archive.js +2 -6
- package/dist/recording-archive.js.map +1 -1
- package/dist/store-connection.d.ts +1 -1
- package/dist/store-connection.d.ts.map +1 -1
- package/dist/store-connection.js +39 -2
- package/dist/store-connection.js.map +1 -1
- package/dist/unified-search.d.ts +6 -0
- package/dist/unified-search.d.ts.map +1 -0
- package/dist/unified-search.js +58 -0
- package/dist/unified-search.js.map +1 -0
- package/package.json +15 -7
- package/skills/zoom-cli/SKILL.md +54 -4
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { annotate } from "@wirecat/cli-core/commands";
|
|
2
|
+
import { ZoomError } from "./errors.js";
|
|
3
|
+
import { bytes } from "./execution.js";
|
|
4
|
+
const bounded = (value, maximum) => value === undefined || (Number.isSafeInteger(value) && value > 0 && value <= maximum);
|
|
5
|
+
export const validateMeetingModel = (options) => {
|
|
6
|
+
if (typeof options.model !== "string" || !options.model.trim() || options.model.length > 1000)
|
|
7
|
+
throw new ZoomError("validation_error", "select an explicit embedding model");
|
|
8
|
+
if (options.baseUrl === undefined) {
|
|
9
|
+
if (options.dims !== undefined)
|
|
10
|
+
throw new ZoomError("validation_error", "dimensions require an explicit remote base URL");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let url;
|
|
14
|
+
try {
|
|
15
|
+
url = new URL(options.baseUrl);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new ZoomError("validation_error", "embedding base URL must be an HTTP or HTTPS URL");
|
|
19
|
+
}
|
|
20
|
+
if (!["http:", "https:"].includes(url.protocol) ||
|
|
21
|
+
url.username ||
|
|
22
|
+
url.password ||
|
|
23
|
+
url.search ||
|
|
24
|
+
url.hash ||
|
|
25
|
+
!/^[\w./:-]{1,200}$/.test(options.model) ||
|
|
26
|
+
options.dims === undefined ||
|
|
27
|
+
!bounded(options.dims, 8192))
|
|
28
|
+
throw new ZoomError("validation_error", "remote embeddings require an HTTP base URL without credentials and explicit dimensions");
|
|
29
|
+
};
|
|
30
|
+
export const validateMeetingSemantic = (query, options) => {
|
|
31
|
+
validateMeetingModel(options);
|
|
32
|
+
if (typeof query !== "string" ||
|
|
33
|
+
!query.trim() ||
|
|
34
|
+
Buffer.byteLength(query, "utf8") > 65536 ||
|
|
35
|
+
!bounded(options.limit, 1000) ||
|
|
36
|
+
!bounded(options.maxChunks, 10000) ||
|
|
37
|
+
!bounded(options.afterChunkId, Number.MAX_SAFE_INTEGER) ||
|
|
38
|
+
!bounded(options.maxRows, 100000) ||
|
|
39
|
+
!bounded(options.maxTextBytes, 64 * 1024 * 1024))
|
|
40
|
+
throw new ZoomError("validation_error", "meeting semantic search requires a nonempty bounded query and positive limits");
|
|
41
|
+
};
|
|
42
|
+
export const validateMeetingEmbeddings = (options) => {
|
|
43
|
+
validateMeetingModel(options);
|
|
44
|
+
if (!bounded(options.limit, 1000) ||
|
|
45
|
+
!bounded(options.afterTranscriptId, Number.MAX_SAFE_INTEGER) ||
|
|
46
|
+
!bounded(options.maxRows, 100000) ||
|
|
47
|
+
!bounded(options.maxTextBytes, 64 * 1024 * 1024) ||
|
|
48
|
+
(options.afterHash !== undefined && !/^[a-f0-9]{64}$/.test(options.afterHash)))
|
|
49
|
+
throw new ZoomError("validation_error", "meeting embedding generation requires valid bounded limits and cursors");
|
|
50
|
+
};
|
|
51
|
+
export const addMeetingSemanticCommands = (program, deps) => {
|
|
52
|
+
const meetings = program.commands.find((command) => command.name() === "meetings");
|
|
53
|
+
if (!meetings)
|
|
54
|
+
throw new ZoomError("configuration_error", "meeting command group is unavailable");
|
|
55
|
+
const model = (command) => command
|
|
56
|
+
.requiredOption("--model <id>", "explicit installed local model ID, or model served at --base-url")
|
|
57
|
+
.option("--base-url <url>", "explicit remote endpoint; OpenAI uses OPENAI_API_KEY")
|
|
58
|
+
.option("--dims <count>", "remote embedding vector dimensions", bytes);
|
|
59
|
+
const budget = (command) => command
|
|
60
|
+
.option("--limit <count>", "bounded batch/result count from 1 through 1000", bytes)
|
|
61
|
+
.option("--max-rows <count>", "transcript cue read limit from 1 through 100000", bytes)
|
|
62
|
+
.option("--max-text-bytes <count>", "aggregate transcript text read byte limit (default 4 MiB)", bytes);
|
|
63
|
+
annotate(budget(model(meetings
|
|
64
|
+
.command("semantic")
|
|
65
|
+
.description("search stored meeting vectors with an explicit query model; ranks only scanned candidates")
|
|
66
|
+
.argument("<query>")))
|
|
67
|
+
.option("--max-chunks <count>", "embedded candidate scan bound", bytes)
|
|
68
|
+
.option("--after-chunk-id <id>", "candidate scan continuation; not globally ranked result pagination", bytes)
|
|
69
|
+
.action(async (query, options) => {
|
|
70
|
+
validateMeetingSemantic(query, options);
|
|
71
|
+
if (options.baseUrl !== undefined && deps.offline())
|
|
72
|
+
throw new ZoomError("configuration_error", "remote embeddings require network access; remove --offline");
|
|
73
|
+
const api = await deps.capabilities();
|
|
74
|
+
deps.output(await api.search(query, { ...options, signal: deps.signal() }));
|
|
75
|
+
}), {
|
|
76
|
+
origin: "handwritten",
|
|
77
|
+
mutates: false,
|
|
78
|
+
examples: ['zm meetings semantic "example plan" --model e5-small --json'],
|
|
79
|
+
});
|
|
80
|
+
annotate(budget(model(meetings
|
|
81
|
+
.command("embeddings")
|
|
82
|
+
.description("preview meeting vector generation; --yes explicitly rebuilds and embeds one bounded batch")))
|
|
83
|
+
.option("--after-transcript-id <id>", "transcript chunk rebuild continuation", bytes)
|
|
84
|
+
.option("--after-hash <hash>", "missing embedding batch continuation")
|
|
85
|
+
.option("--yes", "apply chunk rebuild and embedding generation; preview otherwise")
|
|
86
|
+
.action(async (options) => {
|
|
87
|
+
validateMeetingEmbeddings(options);
|
|
88
|
+
if (options.baseUrl !== undefined && deps.offline())
|
|
89
|
+
throw new ZoomError("configuration_error", "remote embeddings require network access; remove --offline");
|
|
90
|
+
const api = await deps.capabilities();
|
|
91
|
+
const result = await api.generate({ ...options, signal: deps.signal() });
|
|
92
|
+
if (options.yes)
|
|
93
|
+
await deps.receipt(result);
|
|
94
|
+
else
|
|
95
|
+
deps.output(result);
|
|
96
|
+
}), { origin: "handwritten", mutates: true, local: true, examples: ["zm meetings embeddings --model e5-small --json"] });
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=meeting-semantic-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meeting-semantic-commands.js","sourceRoot":"","sources":["../src/meeting-semantic-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MeetingVectors } from "@wirecat/cli-messaging/store";
|
|
2
|
+
import { type MeetingSemanticCapabilities } from "./meeting-semantic-commands.js";
|
|
3
|
+
type ProducerSemanticApi = Pick<typeof import("@wirecat/cli-messaging/services"), "meetingEmbeddingModel" | "createMeetingRemoteModel" | "openMeetingEmbedder" | "readMeetingSemantic" | "proposeMeetingEmbedding" | "applyMeetingEmbedding">;
|
|
4
|
+
/** The connection selects the account; explicit command options select the model. */
|
|
5
|
+
export declare const createMeetingSemanticCapabilities: (vectors: MeetingVectors, accountId: number, options?: {
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
load?: () => Promise<ProducerSemanticApi>;
|
|
8
|
+
}) => MeetingSemanticCapabilities;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=meeting-semantic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meeting-semantic.d.ts","sourceRoot":"","sources":["../src/meeting-semantic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAElE,OAAO,EAGL,KAAK,2BAA2B,EAGjC,MAAM,gCAAgC,CAAA;AAEvC,KAAK,mBAAmB,GAAG,IAAI,CAC7B,cAAc,iCAAiC,CAAC,EAC9C,uBAAuB,GACvB,0BAA0B,GAC1B,qBAAqB,GACrB,qBAAqB,GACrB,yBAAyB,GACzB,uBAAuB,CAC1B,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,iCAAiC,YACnC,cAAc,aACZ,MAAM,YACR;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAA;CAAE,KAC9E,2BA+DF,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { checkCancelled, ZoomError } from "./errors.js";
|
|
2
|
+
import { validateMeetingEmbeddings, validateMeetingSemantic, } from "./meeting-semantic-commands.js";
|
|
3
|
+
const loadProducer = async () => import("@wirecat/cli-messaging/services");
|
|
4
|
+
/** The connection selects the account; explicit command options select the model. */
|
|
5
|
+
export const createMeetingSemanticCapabilities = (vectors, accountId, options = {}) => {
|
|
6
|
+
if (!Number.isSafeInteger(accountId) || accountId < 1)
|
|
7
|
+
throw new ZoomError("validation_error", "meeting vectors require a selected positive account ID");
|
|
8
|
+
const load = options.load ?? loadProducer;
|
|
9
|
+
const choice = (api, input) => input.baseUrl === undefined
|
|
10
|
+
? input.model
|
|
11
|
+
: { remote: api.createMeetingRemoteModel({ model: input.model, baseUrl: input.baseUrl, dims: input.dims }) };
|
|
12
|
+
return {
|
|
13
|
+
search: async (query, input) => {
|
|
14
|
+
validateMeetingSemantic(query, input);
|
|
15
|
+
checkCancelled(input.signal);
|
|
16
|
+
const api = await load();
|
|
17
|
+
checkCancelled(input.signal);
|
|
18
|
+
const selected = choice(api, input);
|
|
19
|
+
const embedder = await api.openMeetingEmbedder(selected, { env: options.env, signal: input.signal });
|
|
20
|
+
try {
|
|
21
|
+
return await api.readMeetingSemantic(vectors, accountId, query, embedder, {
|
|
22
|
+
limit: input.limit,
|
|
23
|
+
maxChunks: input.maxChunks,
|
|
24
|
+
afterChunkId: input.afterChunkId,
|
|
25
|
+
maxRows: input.maxRows,
|
|
26
|
+
maxTextBytes: input.maxTextBytes,
|
|
27
|
+
signal: input.signal,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await embedder.close();
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
generate: async (input) => {
|
|
35
|
+
validateMeetingEmbeddings(input);
|
|
36
|
+
checkCancelled(input.signal);
|
|
37
|
+
const api = await load();
|
|
38
|
+
checkCancelled(input.signal);
|
|
39
|
+
const selected = choice(api, input);
|
|
40
|
+
const descriptor = api.meetingEmbeddingModel(selected);
|
|
41
|
+
if (input.yes !== true)
|
|
42
|
+
return api.proposeMeetingEmbedding(vectors, accountId, descriptor, { signal: input.signal });
|
|
43
|
+
const embedder = await api.openMeetingEmbedder(selected, { env: options.env, signal: input.signal });
|
|
44
|
+
try {
|
|
45
|
+
checkCancelled(input.signal);
|
|
46
|
+
const rebuild = await vectors.rebuild({
|
|
47
|
+
accountId,
|
|
48
|
+
limit: input.limit,
|
|
49
|
+
afterTranscriptId: input.afterTranscriptId,
|
|
50
|
+
maxRows: input.maxRows,
|
|
51
|
+
maxTextBytes: input.maxTextBytes,
|
|
52
|
+
signal: input.signal,
|
|
53
|
+
});
|
|
54
|
+
checkCancelled(input.signal);
|
|
55
|
+
const result = await api.applyMeetingEmbedding(vectors, accountId, embedder, {
|
|
56
|
+
maxChunks: input.limit,
|
|
57
|
+
afterHash: input.afterHash,
|
|
58
|
+
maxRows: input.maxRows,
|
|
59
|
+
maxTextBytes: input.maxTextBytes,
|
|
60
|
+
signal: input.signal,
|
|
61
|
+
});
|
|
62
|
+
return { ...result, applied: true, model: descriptor, rebuild };
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await embedder.close();
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=meeting-semantic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meeting-semantic.js","sourceRoot":"","sources":["../src/meeting-semantic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ordinary-file.d.ts","sourceRoot":"","sources":["../src/ordinary-file.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAe,MAAM,kBAAkB,CAAA;AAM/D,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,SAAgB,MAAM,KAAG,OAAO,CAAC,UAAU,CA0CvE,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { lstat, open } from "node:fs/promises";
|
|
3
|
+
import { ZoomError } from "./errors.js";
|
|
4
|
+
// Node 22's Windows path stat uses a 64-bit volume serial; handle stat uses its low DWORD.
|
|
5
|
+
const deviceOf = (dev) => (process.platform === "win32" ? BigInt.asUintN(32, dev) : dev);
|
|
6
|
+
/** Check the opened object before reading: Windows has no O_NOFOLLOW support. */
|
|
7
|
+
export const openOrdinaryFile = async (path) => {
|
|
8
|
+
const before = await lstat(path, { bigint: true });
|
|
9
|
+
if (before.isSymbolicLink())
|
|
10
|
+
throw new ZoomError("validation_error", "archive path must be an ordinary file without a symlink");
|
|
11
|
+
if (!before.isFile())
|
|
12
|
+
throw new ZoomError("validation_error", "archive path must be an ordinary file");
|
|
13
|
+
const flags = process.platform === "win32"
|
|
14
|
+
? constants.O_RDONLY
|
|
15
|
+
: constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
16
|
+
const file = await open(path, flags);
|
|
17
|
+
try {
|
|
18
|
+
const opened = await file.stat({ bigint: true });
|
|
19
|
+
const after = await lstat(path, { bigint: true });
|
|
20
|
+
if (!opened.isFile() || !after.isFile() || before.ino !== opened.ino || before.ino !== after.ino)
|
|
21
|
+
throw new ZoomError("validation_error", "archive file changed while opening");
|
|
22
|
+
if (process.platform === "win32" && before.dev === 0n && after.dev === 0n) {
|
|
23
|
+
// Older Windows path stats omit the device; compare two handles before any content read.
|
|
24
|
+
const witness = await open(path, flags);
|
|
25
|
+
try {
|
|
26
|
+
const identified = await witness.stat({ bigint: true });
|
|
27
|
+
const final = await lstat(path, { bigint: true });
|
|
28
|
+
if (opened.dev === 0n ||
|
|
29
|
+
!identified.isFile() ||
|
|
30
|
+
!final.isFile() ||
|
|
31
|
+
deviceOf(identified.dev) !== deviceOf(opened.dev) ||
|
|
32
|
+
identified.ino !== opened.ino ||
|
|
33
|
+
final.ino !== before.ino ||
|
|
34
|
+
(final.dev !== 0n && deviceOf(final.dev) !== deviceOf(opened.dev)))
|
|
35
|
+
throw new ZoomError("validation_error", "archive file changed while opening");
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
await witness.close();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (deviceOf(before.dev) !== deviceOf(opened.dev) || deviceOf(before.dev) !== deviceOf(after.dev)) {
|
|
42
|
+
throw new ZoomError("validation_error", "archive file changed while opening");
|
|
43
|
+
}
|
|
44
|
+
return file;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
await file.close();
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=ordinary-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ordinary-file.js","sourceRoot":"","sources":["../src/ordinary-file.ts"],"names":[],"mappings":"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"}
|
package/dist/program.d.ts
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { type SleepLike } from "@wirecat/cli-core";
|
|
2
|
-
import { type MeetingSource, type MeetingStore } from "@wirecat/cli-meetings";
|
|
2
|
+
import { type MeetingSource, type MeetingStore, type MeetingTranscriptStore } from "@wirecat/cli-meetings";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { type ArchiveService, type ArchiveTranscriptService, type RecordingsService, type RemoteMeetingsService } from "./archive-commands.js";
|
|
5
5
|
import { readDownloadedFiles } from "./files.js";
|
|
6
|
+
import type { MeetingContextCapabilities } from "./meeting-context.js";
|
|
7
|
+
import { type MeetingModelOptions, type MeetingSemanticCapabilities } from "./meeting-semantic-commands.js";
|
|
6
8
|
import type { TokenManager } from "./tokens.js";
|
|
9
|
+
import { type UnifiedSearch } from "./unified-search.js";
|
|
7
10
|
export interface StoreConnection {
|
|
8
11
|
store: MeetingStore;
|
|
9
12
|
accountId: number;
|
|
10
13
|
close: () => Promise<void>;
|
|
14
|
+
appendTranscripts?: MeetingTranscriptStore["appendTranscripts"];
|
|
15
|
+
unifiedSearch?: UnifiedSearch;
|
|
16
|
+
meetingContext?: MeetingContextCapabilities;
|
|
17
|
+
meetingSemantic?: MeetingSemanticCapabilities;
|
|
11
18
|
}
|
|
12
19
|
export interface StoreConnectRequest {
|
|
13
20
|
profile: string;
|
|
14
21
|
externalId: string;
|
|
15
22
|
intent: "read" | "ingestion";
|
|
23
|
+
capability?: "transcript-append";
|
|
16
24
|
}
|
|
17
25
|
export interface ProgramDeps {
|
|
18
26
|
configPath: string;
|
|
@@ -21,6 +29,10 @@ export interface ProgramDeps {
|
|
|
21
29
|
store?: MeetingStore;
|
|
22
30
|
accountId?: number;
|
|
23
31
|
connectStore?: (request: StoreConnectRequest) => Promise<StoreConnection>;
|
|
32
|
+
transcriptStore?: MeetingTranscriptStore;
|
|
33
|
+
unifiedSearch?: UnifiedSearch;
|
|
34
|
+
meetingContext?: MeetingContextCapabilities;
|
|
35
|
+
meetingSemantic?: MeetingSemanticCapabilities;
|
|
24
36
|
source?: MeetingSource;
|
|
25
37
|
recordings?: RecordingsService;
|
|
26
38
|
remoteMeetings?: RemoteMeetingsService;
|
|
@@ -46,6 +58,9 @@ export interface ProgramDeps {
|
|
|
46
58
|
serveMcp?: (options: {
|
|
47
59
|
signal: AbortSignal;
|
|
48
60
|
maxResultBytes?: number;
|
|
61
|
+
includeUnifiedSearch?: boolean;
|
|
62
|
+
includeMeetingContext?: boolean;
|
|
63
|
+
semanticModel?: MeetingModelOptions;
|
|
49
64
|
}) => Promise<void>;
|
|
50
65
|
streamData?: (text: string, signal: AbortSignal) => Promise<void>;
|
|
51
66
|
}
|
package/dist/program.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAE5B,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAA;AAGnD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAE7B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAA;AAO9B,OAAO,EAA2B,mBAAmB,EAA2B,MAAM,YAAY,CAAA;AAGlG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAEtE,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAEjC,MAAM,gCAAgC,CAAA;AAYvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAI1E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,iBAAiB,CAAC,EAAE,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;IAC/D,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,0BAA0B,CAAA;IAC3C,eAAe,CAAC,EAAE,2BAA2B,CAAA;CAC9C;AACD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,WAAW,CAAA;IAC5B,UAAU,CAAC,EAAE,mBAAmB,CAAA;CACjC;AACD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE,OAAO,KAAK,CAAA;IACnB,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;IACzE,eAAe,CAAC,EAAE,sBAAsB,CAAA;IACxC,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,0BAA0B,CAAA;IAC3C,eAAe,CAAC,EAAE,2BAA2B,CAAA;IAC7C,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,cAAc,CAAC,EAAE,qBAAqB,CAAA;IACtC,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,kBAAkB,CAAC,EAAE,wBAAwB,CAAA;IAC7C,SAAS,CAAC,EAAE,OAAO,mBAAmB,CAAA;IACtC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChG,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACpD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACvE,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;QACnB,MAAM,EAAE,WAAW,CAAA;QACnB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,oBAAoB,CAAC,EAAE,OAAO,CAAA;QAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAA;QAC/B,aAAa,CAAC,EAAE,mBAAmB,CAAA;KACpC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClE;AA6CD,eAAO,MAAM,aAAa,SAAU,WAAW,KAAG,OA0rBjD,CAAA;AACD,eAAO,MAAM,GAAG,SAAgB,MAAM,EAAE,QAAQ,WAAW,KAAG,OAAO,CAAC,MAAM,CA6B3E,CAAA"}
|
package/dist/program.js
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { CliError, createDeadline, createRenderer, exitCodeFor, fieldsOf, GENERIC_FAILURE, projectFields, realSleep, } from "@wirecat/cli-core";
|
|
2
|
-
import { importFiles, listed, MeetingError, pull } from "@wirecat/cli-meetings";
|
|
2
|
+
import { importFiles, listed, MeetingError, pull, } from "@wirecat/cli-meetings";
|
|
3
3
|
import { addMeetingCommands } from "@wirecat/cli-meetings/cli";
|
|
4
4
|
import { Command, CommanderError } from "commander";
|
|
5
5
|
import { addZoomSkillCommands } from "./agent-skill.js";
|
|
6
6
|
import { ZoomApiSource } from "./api.js";
|
|
7
7
|
import { addArchiveCommands, } from "./archive-commands.js";
|
|
8
|
+
import { applyArchiveImport, preflightArchiveImport } from "./archive-import.js";
|
|
8
9
|
import { readArchiveTranscripts, searchArchiveTranscripts } from "./archive-transcripts.js";
|
|
9
10
|
import { addStandardCommands, annotateMeetingCommands } from "./commands.js";
|
|
10
11
|
import { profileAccountKey, readConfig, setConfig } from "./config.js";
|
|
11
12
|
import { checkCancelled, ZoomError } from "./errors.js";
|
|
12
13
|
import { bytes, duration, resetCliOptions, startExecution } from "./execution.js";
|
|
13
14
|
import { FilesSource, importFile, readDownloadedFiles, validateDownloadedFiles } from "./files.js";
|
|
15
|
+
import { addIngestionSearchCommands } from "./ingestion-search-commands.js";
|
|
14
16
|
import { login } from "./login.js";
|
|
17
|
+
import { addMeetingContextCommands } from "./meeting-context-commands.js";
|
|
18
|
+
import { addMeetingSemanticCommands, validateMeetingModel, } from "./meeting-semantic-commands.js";
|
|
15
19
|
import { getZoomProfile, inspectArchive, inspectArchiveLocks, recoverArchiveLocks, verifyArchive, ZoomRecordings, } from "./recordings.js";
|
|
16
20
|
import { ZoomRemoteMeetings } from "./remote-meetings.js";
|
|
17
21
|
import { emitReceipt } from "./streaming.js";
|
|
22
|
+
import { runUnifiedSearch } from "./unified-search.js";
|
|
18
23
|
import { VERSION } from "./version.js";
|
|
19
24
|
import { addWatchCommand } from "./watch-commands.js";
|
|
20
25
|
const unavailable = async () => {
|
|
@@ -35,7 +40,7 @@ const unavailableStore = {
|
|
|
35
40
|
cursor: unavailable,
|
|
36
41
|
setCursor: unavailable,
|
|
37
42
|
};
|
|
38
|
-
const render = (value, format, deps, fields) => {
|
|
43
|
+
const render = (value, format, deps, fields, preserveEnvelope = false) => {
|
|
39
44
|
if (fields)
|
|
40
45
|
value = projectFields(value, fields);
|
|
41
46
|
const chunks = [];
|
|
@@ -44,7 +49,8 @@ const render = (value, format, deps, fields) => {
|
|
|
44
49
|
color: false,
|
|
45
50
|
streams: { data: (text) => chunks.push(`${text}\n`), diagnostic: deps.diagnostic },
|
|
46
51
|
});
|
|
47
|
-
if (
|
|
52
|
+
if (!preserveEnvelope &&
|
|
53
|
+
format === "jsonl" &&
|
|
48
54
|
typeof value === "object" &&
|
|
49
55
|
value !== null &&
|
|
50
56
|
"items" in value &&
|
|
@@ -143,7 +149,10 @@ export const createProgram = (deps) => {
|
|
|
143
149
|
"serve",
|
|
144
150
|
"skill",
|
|
145
151
|
"watch",
|
|
146
|
-
|
|
152
|
+
"search",
|
|
153
|
+
].includes(family.name()) ||
|
|
154
|
+
(family.name() === "meetings" &&
|
|
155
|
+
["evidence", "context", "task-proposal", "semantic", "embeddings"].includes(action.name())))
|
|
147
156
|
return;
|
|
148
157
|
const config = getConfig();
|
|
149
158
|
if (opts.offline && action.name() === "pull" && config.source === "api" && !deps.source)
|
|
@@ -357,7 +366,7 @@ export const createProgram = (deps) => {
|
|
|
357
366
|
let watchSince;
|
|
358
367
|
const watchSleep = deps.sleep;
|
|
359
368
|
const receipt = async (value) => {
|
|
360
|
-
const text = render(value, program.opts().jsonl ? "jsonl" : "text", deps, fields);
|
|
369
|
+
const text = render(value, program.opts().jsonl ? "jsonl" : program.opts().json ? "json" : "text", deps, fields);
|
|
361
370
|
const operation = signal();
|
|
362
371
|
const grace = operation.aborted ? createDeadline({ timeoutMs: 1000 }) : undefined;
|
|
363
372
|
try {
|
|
@@ -564,13 +573,122 @@ export const createProgram = (deps) => {
|
|
|
564
573
|
.command("serve")
|
|
565
574
|
.description("serve read-only meeting tools over MCP stdio")
|
|
566
575
|
.requiredOption("--mcp", "use the MCP JSON-RPC protocol")
|
|
567
|
-
.
|
|
576
|
+
.option("--unified-search", "include selected-profile meetings-only unified search")
|
|
577
|
+
.option("--meeting-context", "include account-fixed evidence, person context and task proposals")
|
|
578
|
+
.option("--semantic", "include read-only meeting vector search with an explicit query model")
|
|
579
|
+
.option("--model <id>", "explicit installed query model, or remote model at --base-url")
|
|
580
|
+
.option("--base-url <url>", "explicit remote embedding endpoint for semantic queries")
|
|
581
|
+
.option("--dims <count>", "remote embedding dimensions", bytes)
|
|
582
|
+
.action(async (options) => {
|
|
568
583
|
const opts = program.opts();
|
|
569
584
|
if (opts.json || opts.jsonl || opts.fields)
|
|
570
585
|
throw new ZoomError("validation_error", "MCP stdio controls its own output; omit --json, --jsonl and --fields");
|
|
571
586
|
if (!deps.serveMcp)
|
|
572
587
|
throw new ZoomError("configuration_error", "the MCP server adapter is not available");
|
|
573
|
-
|
|
588
|
+
if (options.semantic)
|
|
589
|
+
validateMeetingModel({ model: options.model ?? "", baseUrl: options.baseUrl, dims: options.dims });
|
|
590
|
+
else if (options.model !== undefined || options.baseUrl !== undefined || options.dims !== undefined)
|
|
591
|
+
throw new ZoomError("validation_error", "MCP model options require --semantic");
|
|
592
|
+
if (options.semantic && options.baseUrl !== undefined && opts.offline)
|
|
593
|
+
throw new ZoomError("configuration_error", "remote embeddings require network access; remove --offline");
|
|
594
|
+
await deps.serveMcp({
|
|
595
|
+
signal: signal(),
|
|
596
|
+
maxResultBytes: program.opts().maxOutputBytes,
|
|
597
|
+
...(options.unifiedSearch ? { includeUnifiedSearch: true } : {}),
|
|
598
|
+
...(options.meetingContext ? { includeMeetingContext: true } : {}),
|
|
599
|
+
...(options.semantic
|
|
600
|
+
? { semanticModel: { model: options.model ?? "", baseUrl: options.baseUrl, dims: options.dims } }
|
|
601
|
+
: {}),
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
addIngestionSearchCommands(program, {
|
|
605
|
+
signal,
|
|
606
|
+
output: (value) => buffer(render(value, program.opts().jsonl ? "jsonl" : program.opts().json ? "json" : "text", deps, fields, true)),
|
|
607
|
+
outputItems,
|
|
608
|
+
receipt,
|
|
609
|
+
preflight: preflightArchiveImport,
|
|
610
|
+
apply: async function* (plan) {
|
|
611
|
+
if (plan.occurrences === 0)
|
|
612
|
+
return;
|
|
613
|
+
let store = deps.transcriptStore;
|
|
614
|
+
let accountId = selectedAccountId;
|
|
615
|
+
if (!store) {
|
|
616
|
+
const config = getConfig();
|
|
617
|
+
if (!config.accountProfile || !deps.connectStore)
|
|
618
|
+
throw new ZoomError("configuration_error", "select a local profile with an available transcript append store");
|
|
619
|
+
connection = await deps.connectStore({
|
|
620
|
+
profile: config.accountProfile,
|
|
621
|
+
externalId: profileAccountKey(config.accountProfile),
|
|
622
|
+
intent: "ingestion",
|
|
623
|
+
capability: "transcript-append",
|
|
624
|
+
});
|
|
625
|
+
accountId = connection.accountId;
|
|
626
|
+
if (!connection.appendTranscripts)
|
|
627
|
+
throw new ZoomError("configuration_error", "the installed meeting store does not support transcript append");
|
|
628
|
+
store = { appendTranscripts: connection.appendTranscripts };
|
|
629
|
+
}
|
|
630
|
+
for await (const item of applyArchiveImport(plan, store, {
|
|
631
|
+
accountId: accountId ?? 0,
|
|
632
|
+
now: deps.now?.(),
|
|
633
|
+
signal: signal(),
|
|
634
|
+
}))
|
|
635
|
+
yield item;
|
|
636
|
+
},
|
|
637
|
+
search: async (request) => {
|
|
638
|
+
if (deps.unifiedSearch)
|
|
639
|
+
return runUnifiedSearch(deps.unifiedSearch, request);
|
|
640
|
+
const config = getConfig();
|
|
641
|
+
if (!config.accountProfile || !deps.connectStore)
|
|
642
|
+
throw new ZoomError("configuration_error", "select a stored local profile for unified search");
|
|
643
|
+
connection = await deps.connectStore({
|
|
644
|
+
profile: config.accountProfile,
|
|
645
|
+
externalId: profileAccountKey(config.accountProfile),
|
|
646
|
+
intent: "read",
|
|
647
|
+
});
|
|
648
|
+
if (!connection.unifiedSearch)
|
|
649
|
+
throw new ZoomError("configuration_error", "unified search is unavailable in this store connector");
|
|
650
|
+
return runUnifiedSearch(connection.unifiedSearch, request);
|
|
651
|
+
},
|
|
652
|
+
});
|
|
653
|
+
addMeetingContextCommands(program, {
|
|
654
|
+
signal,
|
|
655
|
+
output: (value) => buffer(render(value, program.opts().jsonl ? "jsonl" : program.opts().json ? "json" : "text", deps, fields, true)),
|
|
656
|
+
context: async () => {
|
|
657
|
+
if (deps.meetingContext)
|
|
658
|
+
return deps.meetingContext;
|
|
659
|
+
const config = getConfig();
|
|
660
|
+
if (!config.accountProfile || !deps.connectStore)
|
|
661
|
+
throw new ZoomError("configuration_error", "select a stored local profile for meeting context");
|
|
662
|
+
connection = await deps.connectStore({
|
|
663
|
+
profile: config.accountProfile,
|
|
664
|
+
externalId: profileAccountKey(config.accountProfile),
|
|
665
|
+
intent: "read",
|
|
666
|
+
});
|
|
667
|
+
if (!connection.meetingContext)
|
|
668
|
+
throw new ZoomError("configuration_error", "meeting context is unavailable in this store connector");
|
|
669
|
+
return connection.meetingContext;
|
|
670
|
+
},
|
|
671
|
+
});
|
|
672
|
+
addMeetingSemanticCommands(program, {
|
|
673
|
+
signal,
|
|
674
|
+
offline: () => Boolean(program.opts().offline),
|
|
675
|
+
receipt,
|
|
676
|
+
output: (value) => buffer(render(value, program.opts().jsonl ? "jsonl" : program.opts().json ? "json" : "text", deps, fields, true)),
|
|
677
|
+
capabilities: async () => {
|
|
678
|
+
if (deps.meetingSemantic)
|
|
679
|
+
return deps.meetingSemantic;
|
|
680
|
+
const config = getConfig();
|
|
681
|
+
if (!config.accountProfile || !deps.connectStore)
|
|
682
|
+
throw new ZoomError("configuration_error", "select a stored local profile for meeting vectors");
|
|
683
|
+
connection = await deps.connectStore({
|
|
684
|
+
profile: config.accountProfile,
|
|
685
|
+
externalId: profileAccountKey(config.accountProfile),
|
|
686
|
+
intent: "read",
|
|
687
|
+
});
|
|
688
|
+
if (!connection.meetingSemantic)
|
|
689
|
+
throw new ZoomError("configuration_error", "meeting vector capabilities are unavailable in this store connector");
|
|
690
|
+
return connection.meetingSemantic;
|
|
691
|
+
},
|
|
574
692
|
});
|
|
575
693
|
annotateMeetingCommands(program);
|
|
576
694
|
const parseAsync = program.parseAsync.bind(program);
|
|
@@ -650,8 +768,19 @@ export const run = async (args, deps) => {
|
|
|
650
768
|
["commander.helpDisplayed", "commander.help", "commander.version"].includes(String(error.code)))
|
|
651
769
|
return 0;
|
|
652
770
|
const typed = error instanceof CliError || error instanceof MeetingError;
|
|
653
|
-
const
|
|
654
|
-
const
|
|
771
|
+
const unknownOutcome = error instanceof Error && "code" in error && error.code === "outcome_unknown";
|
|
772
|
+
const code = typed
|
|
773
|
+
? error.code
|
|
774
|
+
: unknownOutcome
|
|
775
|
+
? "outcome_unknown"
|
|
776
|
+
: error instanceof CommanderError
|
|
777
|
+
? "validation_error"
|
|
778
|
+
: "generic_failure";
|
|
779
|
+
const message = typed
|
|
780
|
+
? error.message
|
|
781
|
+
: unknownOutcome
|
|
782
|
+
? "operation outcome is unknown; verify stored state before retrying"
|
|
783
|
+
: "command failed; use --help for usage";
|
|
655
784
|
deps.diagnostic(`${JSON.stringify({ error: { code, message } })}\n`);
|
|
656
785
|
return code === "generic_failure" ? GENERIC_FAILURE : exitCodeFor(code);
|
|
657
786
|
}
|