picocode 0.9.202 → 0.9.204

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.
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+
3
+ // helper/linux-dictate.js
4
+ import { spawn as nodeSpawn } from "node:child_process";
5
+ import * as fs from "node:fs/promises";
6
+ import { constants } from "node:fs";
7
+ import { homedir, tmpdir } from "node:os";
8
+ import { delimiter, join, resolve } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { createInterface } from "node:readline";
11
+ function wavHeader(bytes) {
12
+ const header = Buffer.alloc(44);
13
+ header.write("RIFF");
14
+ header.writeUInt32LE(bytes + 36, 4);
15
+ header.write("WAVEfmt ", 8);
16
+ header.writeUInt32LE(16, 16);
17
+ header.writeUInt16LE(1, 20);
18
+ header.writeUInt16LE(1, 22);
19
+ header.writeUInt32LE(16e3, 24);
20
+ header.writeUInt32LE(32e3, 28);
21
+ header.writeUInt16LE(2, 32);
22
+ header.writeUInt16LE(16, 34);
23
+ header.write("data", 36);
24
+ header.writeUInt32LE(bytes, 40);
25
+ return header;
26
+ }
27
+ async function findExecutable(name, env = process.env) {
28
+ const paths = name.includes("/") ? [name] : (env.PATH || "").split(delimiter).map((dir) => join(dir, name));
29
+ for (const path of paths) {
30
+ try {
31
+ await fs.access(path, constants.X_OK);
32
+ return path;
33
+ } catch {
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+ function createLinuxDictation({
39
+ emit = () => {
40
+ },
41
+ spawn = nodeSpawn,
42
+ env = process.env,
43
+ executable = (name) => findExecutable(name, env),
44
+ files = fs,
45
+ tempRoot = tmpdir(),
46
+ maxRecordingMs = 12e4,
47
+ killTimeoutMs = 1e3
48
+ } = {}) {
49
+ const model = env.PICO_WHISPER_MODEL || join(env.XDG_CACHE_HOME || join(homedir(), ".cache"), "pico/whisper/ggml-base.en.bin");
50
+ let active = null;
51
+ let disposed = false;
52
+ const jobs = /* @__PURE__ */ new Set();
53
+ const send = (message) => {
54
+ if (!disposed) emit(message);
55
+ };
56
+ function launch(binary, args) {
57
+ const child = spawn(binary, args, { stdio: ["ignore", "pipe", "pipe"] });
58
+ const job = { child, error: null, stderr: "", done: false };
59
+ jobs.add(job);
60
+ child.stderr?.on("data", (chunk) => {
61
+ job.stderr = (job.stderr + chunk.toString()).slice(-4096);
62
+ });
63
+ job.closed = new Promise((resolve2) => {
64
+ child.once("error", (error) => {
65
+ job.error = error;
66
+ finish(null);
67
+ });
68
+ child.once("close", (code) => finish(code));
69
+ function finish(code) {
70
+ if (job.done) return;
71
+ job.done = true;
72
+ jobs.delete(job);
73
+ resolve2(code);
74
+ }
75
+ });
76
+ job.started = new Promise((resolve2, reject) => {
77
+ child.once("spawn", resolve2);
78
+ child.once("error", reject);
79
+ });
80
+ job.started.catch(() => {
81
+ });
82
+ return job;
83
+ }
84
+ async function terminate(job) {
85
+ if (!job || job.done) return;
86
+ job.child.kill("SIGTERM");
87
+ const timer = setTimeout(() => {
88
+ if (!job.done) job.child.kill("SIGKILL");
89
+ }, killTimeoutMs);
90
+ try {
91
+ await job.closed;
92
+ } finally {
93
+ clearTimeout(timer);
94
+ }
95
+ }
96
+ async function cleanup(session) {
97
+ if (!session) return;
98
+ session.cancelled = true;
99
+ clearTimeout(session.timer);
100
+ await Promise.all([terminate(session.recorder), terminate(session.transcriber)]);
101
+ if (session.dir) await files.rm(session.dir, { recursive: true, force: true });
102
+ if (active === session) active = null;
103
+ }
104
+ async function start() {
105
+ if (active) throw new Error("Dictation is already active.");
106
+ const session = { chunks: [], bytes: 0, cancelled: false, stopping: false };
107
+ active = session;
108
+ try {
109
+ const whisper = env.PICO_WHISPER_BIN ? await executable(env.PICO_WHISPER_BIN) : await executable(join(env.XDG_CACHE_HOME || join(homedir(), ".cache"), "pico/whisper/whisper-cli")) || await executable("whisper-cli");
110
+ if (!whisper) throw new Error("Install whisper.cpp and put whisper-cli on PATH, or set PICO_WHISPER_BIN.");
111
+ try {
112
+ await files.access(model, constants.R_OK);
113
+ } catch {
114
+ throw new Error(`Whisper model not found or unreadable: ${model}. Install a whisper.cpp GGML model and set PICO_WHISPER_MODEL (no models are downloaded automatically).`);
115
+ }
116
+ const pw = await executable("pw-record");
117
+ const recorder = pw || await executable("parec");
118
+ if (!recorder) throw new Error("Install PipeWire (pw-record) or PulseAudio utilities (parec) for microphone recording.");
119
+ if (session.cancelled) return;
120
+ session.whisper = whisper;
121
+ session.dir = await files.mkdtemp(join(tempRoot, "pico-dictation-"));
122
+ if (session.cancelled) {
123
+ await cleanup(session);
124
+ return;
125
+ }
126
+ const args = pw ? ["--raw", "--format", "s16", "--rate", "16000", "--channels", "1"] : ["--raw", "--format=s16le", "--rate=16000", "--channels=1"];
127
+ if (env.PICO_DICTATION_SOURCE) args.push(pw ? "--target" : "--device", env.PICO_DICTATION_SOURCE);
128
+ if (pw) args.push("-");
129
+ const job = session.recorder = launch(recorder, args);
130
+ let lastLevel = 0;
131
+ job.child.stdout.on("data", (chunk) => {
132
+ if (session.cancelled || session.stopping) return;
133
+ const remaining = Math.floor(maxRecordingMs * 32) - session.bytes;
134
+ const data = Buffer.from(chunk.subarray(0, Math.max(0, remaining)));
135
+ session.chunks.push(data);
136
+ session.bytes += data.length;
137
+ if (Date.now() - lastLevel >= 50) {
138
+ let sum = 0;
139
+ for (let i = 0; i + 1 < data.length; i += 2) sum += (data.readInt16LE(i) / 32768) ** 2;
140
+ send({ status: "level", level: data.length >= 2 ? Math.sqrt(sum / Math.floor(data.length / 2)) : 0 });
141
+ lastLevel = Date.now();
142
+ }
143
+ if (session.bytes >= Math.floor(maxRecordingMs * 32)) void limit();
144
+ });
145
+ const limit = async () => {
146
+ if (session.cancelled || session.stopping) return;
147
+ session.stopping = true;
148
+ send({ status: "error", message: "Dictation reached the 120-second recording limit. Please record a shorter passage." });
149
+ await cleanup(session);
150
+ };
151
+ await job.started;
152
+ job.closed.then(async (code) => {
153
+ if (session.cancelled || session.stopping) return;
154
+ send({ status: "error", message: `Microphone recording stopped unexpectedly (${code ?? job.error?.message ?? "unknown error"}). Check your audio source and permissions.${job.stderr ? ` ${job.stderr.trim()}` : ""}` });
155
+ await cleanup(session);
156
+ });
157
+ session.timer = setTimeout(() => {
158
+ void limit();
159
+ }, maxRecordingMs);
160
+ } catch (error) {
161
+ await cleanup(session);
162
+ throw error;
163
+ }
164
+ }
165
+ async function stop() {
166
+ const session = active;
167
+ if (!session || !session.recorder || session.stopping) throw new Error("No active dictation recording.");
168
+ session.stopping = true;
169
+ clearTimeout(session.timer);
170
+ try {
171
+ await terminate(session.recorder);
172
+ if (session.cancelled) throw new Error("Dictation cancelled.");
173
+ const pcm = Buffer.concat(session.chunks);
174
+ const audio = join(session.dir, "audio.wav");
175
+ const prefix = join(session.dir, "transcript");
176
+ const even = pcm.subarray(0, pcm.length - pcm.length % 2);
177
+ await files.writeFile(audio, Buffer.concat([wavHeader(even.length), even]), { mode: 384 });
178
+ if (session.cancelled) throw new Error("Dictation cancelled.");
179
+ const job = session.transcriber = launch(session.whisper, ["-m", model, "-f", audio, "-otxt", "-of", prefix, "-l", env.PICO_WHISPER_LANGUAGE || "en", "-nt"]);
180
+ const code = await job.closed;
181
+ if (session.cancelled) throw new Error("Dictation cancelled.");
182
+ if (job.error || code !== 0) throw new Error(`Whisper transcription failed: ${job.error?.message || job.stderr.trim() || `exit ${code}`}`);
183
+ return (await files.readFile(`${prefix}.txt`, "utf8")).trim();
184
+ } finally {
185
+ await cleanup(session);
186
+ }
187
+ }
188
+ async function handle(command) {
189
+ if (disposed) return;
190
+ const id = command?.id;
191
+ try {
192
+ if (id == null) throw new Error("Command requires an id.");
193
+ if (command.op === "start") {
194
+ await start();
195
+ send({ id });
196
+ } else if (command.op === "stop") send({ id, text: await stop() });
197
+ else if (command.op === "cancel") {
198
+ await cleanup(active);
199
+ send({ id });
200
+ } else throw new Error("Unknown dictation command.");
201
+ } catch (error) {
202
+ send({ id, error: error.message });
203
+ }
204
+ }
205
+ async function dispose() {
206
+ disposed = true;
207
+ await cleanup(active);
208
+ await Promise.all([...jobs].map(terminate));
209
+ }
210
+ return { handle, dispose };
211
+ }
212
+ function runLinuxDictation({ input = process.stdin, output = process.stdout, signals = process, ...options } = {}) {
213
+ const emit = (message) => output.write(`${JSON.stringify(message)}
214
+ `);
215
+ const helper = createLinuxDictation({ ...options, emit });
216
+ const lines = createInterface({ input });
217
+ let closing = false;
218
+ const close = async () => {
219
+ if (closing) return;
220
+ closing = true;
221
+ lines.close();
222
+ signals.removeListener("SIGTERM", close);
223
+ signals.removeListener("SIGINT", close);
224
+ await helper.dispose();
225
+ };
226
+ lines.on("line", (line) => {
227
+ if (line.length > 65536) return emit({ status: "error", message: "Dictation command is too large." });
228
+ try {
229
+ void helper.handle(JSON.parse(line));
230
+ } catch {
231
+ emit({ status: "error", message: "Invalid dictation command JSON." });
232
+ }
233
+ });
234
+ lines.on("close", close);
235
+ input.on("error", close);
236
+ output.on("error", close);
237
+ signals.on("SIGTERM", close);
238
+ signals.on("SIGINT", close);
239
+ emit({ status: "ready" });
240
+ return { ...helper, dispose: close };
241
+ }
242
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) runLinuxDictation();
243
+ export {
244
+ createLinuxDictation,
245
+ findExecutable,
246
+ runLinuxDictation,
247
+ wavHeader
248
+ };
249
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vaGVscGVyL2xpbnV4LWRpY3RhdGUuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIiMhL3Vzci9iaW4vZW52IG5vZGVcbmltcG9ydCB7IHNwYXduIGFzIG5vZGVTcGF3biB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2VzcydcbmltcG9ydCAqIGFzIGZzIGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnXG5pbXBvcnQgeyBjb25zdGFudHMgfSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgaG9tZWRpciwgdG1wZGlyIH0gZnJvbSAnbm9kZTpvcydcbmltcG9ydCB7IGRlbGltaXRlciwgam9pbiwgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCdcbmltcG9ydCB7IGNyZWF0ZUludGVyZmFjZSB9IGZyb20gJ25vZGU6cmVhZGxpbmUnXG5cbmV4cG9ydCBmdW5jdGlvbiB3YXZIZWFkZXIoYnl0ZXMpIHtcbiAgY29uc3QgaGVhZGVyID0gQnVmZmVyLmFsbG9jKDQ0KVxuICBoZWFkZXIud3JpdGUoJ1JJRkYnKTsgaGVhZGVyLndyaXRlVUludDMyTEUoYnl0ZXMgKyAzNiwgNCk7IGhlYWRlci53cml0ZSgnV0FWRWZtdCAnLCA4KVxuICBoZWFkZXIud3JpdGVVSW50MzJMRSgxNiwgMTYpOyBoZWFkZXIud3JpdGVVSW50MTZMRSgxLCAyMCk7IGhlYWRlci53cml0ZVVJbnQxNkxFKDEsIDIyKVxuICBoZWFkZXIud3JpdGVVSW50MzJMRSgxNjAwMCwgMjQpOyBoZWFkZXIud3JpdGVVSW50MzJMRSgzMjAwMCwgMjgpXG4gIGhlYWRlci53cml0ZVVJbnQxNkxFKDIsIDMyKTsgaGVhZGVyLndyaXRlVUludDE2TEUoMTYsIDM0KVxuICBoZWFkZXIud3JpdGUoJ2RhdGEnLCAzNik7IGhlYWRlci53cml0ZVVJbnQzMkxFKGJ5dGVzLCA0MClcbiAgcmV0dXJuIGhlYWRlclxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZEV4ZWN1dGFibGUobmFtZSwgZW52ID0gcHJvY2Vzcy5lbnYpIHtcbiAgY29uc3QgcGF0aHMgPSBuYW1lLmluY2x1ZGVzKCcvJykgPyBbbmFtZV0gOiAoZW52LlBBVEggfHwgJycpLnNwbGl0KGRlbGltaXRlcikubWFwKGRpciA9PiBqb2luKGRpciwgbmFtZSkpXG4gIGZvciAoY29uc3QgcGF0aCBvZiBwYXRocykge1xuICAgIHRyeSB7IGF3YWl0IGZzLmFjY2VzcyhwYXRoLCBjb25zdGFudHMuWF9PSyk7IHJldHVybiBwYXRoIH0gY2F0Y2gge31cbiAgfVxuICByZXR1cm4gbnVsbFxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTGludXhEaWN0YXRpb24oeyBlbWl0ID0gKCkgPT4ge30sIHNwYXduID0gbm9kZVNwYXduLCBlbnYgPSBwcm9jZXNzLmVudixcbiAgZXhlY3V0YWJsZSA9IG5hbWUgPT4gZmluZEV4ZWN1dGFibGUobmFtZSwgZW52KSwgZmlsZXMgPSBmcywgdGVtcFJvb3QgPSB0bXBkaXIoKSxcbiAgbWF4UmVjb3JkaW5nTXMgPSAxMjAwMDAsIGtpbGxUaW1lb3V0TXMgPSAxMDAwIH0gPSB7fSkge1xuICBjb25zdCBtb2RlbCA9IGVudi5QSUNPX1dISVNQRVJfTU9ERUwgfHwgam9pbihlbnYuWERHX0NBQ0hFX0hPTUUgfHwgam9pbihob21lZGlyKCksICcuY2FjaGUnKSwgJ3BpY28vd2hpc3Blci9nZ21sLWJhc2UuZW4uYmluJylcbiAgbGV0IGFjdGl2ZSA9IG51bGxcbiAgbGV0IGRpc3Bvc2VkID0gZmFsc2VcbiAgY29uc3Qgam9icyA9IG5ldyBTZXQoKVxuICBjb25zdCBzZW5kID0gbWVzc2FnZSA9PiB7IGlmICghZGlzcG9zZWQpIGVtaXQobWVzc2FnZSkgfVxuXG4gIGZ1bmN0aW9uIGxhdW5jaChiaW5hcnksIGFyZ3MpIHtcbiAgICBjb25zdCBjaGlsZCA9IHNwYXduKGJpbmFyeSwgYXJncywgeyBzdGRpbzogWydpZ25vcmUnLCAncGlwZScsICdwaXBlJ10gfSlcbiAgICBjb25zdCBqb2IgPSB7IGNoaWxkLCBlcnJvcjogbnVsbCwgc3RkZXJyOiAnJywgZG9uZTogZmFsc2UgfVxuICAgIGpvYnMuYWRkKGpvYilcbiAgICBjaGlsZC5zdGRlcnI/Lm9uKCdkYXRhJywgY2h1bmsgPT4geyBqb2Iuc3RkZXJyID0gKGpvYi5zdGRlcnIgKyBjaHVuay50b1N0cmluZygpKS5zbGljZSgtNDA5NikgfSlcbiAgICBqb2IuY2xvc2VkID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBjaGlsZC5vbmNlKCdlcnJvcicsIGVycm9yID0+IHsgam9iLmVycm9yID0gZXJyb3I7IGZpbmlzaChudWxsKSB9KVxuICAgICAgY2hpbGQub25jZSgnY2xvc2UnLCBjb2RlID0+IGZpbmlzaChjb2RlKSlcbiAgICAgIGZ1bmN0aW9uIGZpbmlzaChjb2RlKSB7XG4gICAgICAgIGlmIChqb2IuZG9uZSkgcmV0dXJuXG4gICAgICAgIGpvYi5kb25lID0gdHJ1ZTsgam9icy5kZWxldGUoam9iKTsgcmVzb2x2ZShjb2RlKVxuICAgICAgfVxuICAgIH0pXG4gICAgam9iLnN0YXJ0ZWQgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjaGlsZC5vbmNlKCdzcGF3bicsIHJlc29sdmUpOyBjaGlsZC5vbmNlKCdlcnJvcicsIHJlamVjdClcbiAgICB9KVxuICAgIC8vIFRyYW5zY3JpcHRpb24gbWF5IGJlIGNhbmNlbGxlZCBiZWZvcmUgYW55b25lIGF3YWl0cyBzdGFydHVwLlxuICAgIGpvYi5zdGFydGVkLmNhdGNoKCgpID0+IHt9KVxuICAgIHJldHVybiBqb2JcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHRlcm1pbmF0ZShqb2IpIHtcbiAgICBpZiAoIWpvYiB8fCBqb2IuZG9uZSkgcmV0dXJuXG4gICAgam9iLmNoaWxkLmtpbGwoJ1NJR1RFUk0nKVxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7IGlmICgham9iLmRvbmUpIGpvYi5jaGlsZC5raWxsKCdTSUdLSUxMJykgfSwga2lsbFRpbWVvdXRNcylcbiAgICB0cnkgeyBhd2FpdCBqb2IuY2xvc2VkIH0gZmluYWxseSB7IGNsZWFyVGltZW91dCh0aW1lcikgfVxuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gY2xlYW51cChzZXNzaW9uKSB7XG4gICAgaWYgKCFzZXNzaW9uKSByZXR1cm5cbiAgICBzZXNzaW9uLmNhbmNlbGxlZCA9IHRydWVcbiAgICBjbGVhclRpbWVvdXQoc2Vzc2lvbi50aW1lcilcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbdGVybWluYXRlKHNlc3Npb24ucmVjb3JkZXIpLCB0ZXJtaW5hdGUoc2Vzc2lvbi50cmFuc2NyaWJlcildKVxuICAgIGlmIChzZXNzaW9uLmRpcikgYXdhaXQgZmlsZXMucm0oc2Vzc2lvbi5kaXIsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KVxuICAgIGlmIChhY3RpdmUgPT09IHNlc3Npb24pIGFjdGl2ZSA9IG51bGxcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChhY3RpdmUpIHRocm93IG5ldyBFcnJvcignRGljdGF0aW9uIGlzIGFscmVhZHkgYWN0aXZlLicpXG4gICAgY29uc3Qgc2Vzc2lvbiA9IHsgY2h1bmtzOiBbXSwgYnl0ZXM6IDAsIGNhbmNlbGxlZDogZmFsc2UsIHN0b3BwaW5nOiBmYWxzZSB9XG4gICAgYWN0aXZlID0gc2Vzc2lvblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB3aGlzcGVyID0gZW52LlBJQ09fV0hJU1BFUl9CSU5cbiAgICAgICAgPyBhd2FpdCBleGVjdXRhYmxlKGVudi5QSUNPX1dISVNQRVJfQklOKVxuICAgICAgICA6IGF3YWl0IGV4ZWN1dGFibGUoam9pbihlbnYuWERHX0NBQ0hFX0hPTUUgfHwgam9pbihob21lZGlyKCksICcuY2FjaGUnKSwgJ3BpY28vd2hpc3Blci93aGlzcGVyLWNsaScpKSB8fCBhd2FpdCBleGVjdXRhYmxlKCd3aGlzcGVyLWNsaScpXG4gICAgICBpZiAoIXdoaXNwZXIpIHRocm93IG5ldyBFcnJvcignSW5zdGFsbCB3aGlzcGVyLmNwcCBhbmQgcHV0IHdoaXNwZXItY2xpIG9uIFBBVEgsIG9yIHNldCBQSUNPX1dISVNQRVJfQklOLicpXG4gICAgICB0cnkgeyBhd2FpdCBmaWxlcy5hY2Nlc3MobW9kZWwsIGNvbnN0YW50cy5SX09LKSB9IGNhdGNoIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBXaGlzcGVyIG1vZGVsIG5vdCBmb3VuZCBvciB1bnJlYWRhYmxlOiAke21vZGVsfS4gSW5zdGFsbCBhIHdoaXNwZXIuY3BwIEdHTUwgbW9kZWwgYW5kIHNldCBQSUNPX1dISVNQRVJfTU9ERUwgKG5vIG1vZGVscyBhcmUgZG93bmxvYWRlZCBhdXRvbWF0aWNhbGx5KS5gKVxuICAgICAgfVxuICAgICAgY29uc3QgcHcgPSBhd2FpdCBleGVjdXRhYmxlKCdwdy1yZWNvcmQnKVxuICAgICAgY29uc3QgcmVjb3JkZXIgPSBwdyB8fCBhd2FpdCBleGVjdXRhYmxlKCdwYXJlYycpXG4gICAgICBpZiAoIXJlY29yZGVyKSB0aHJvdyBuZXcgRXJyb3IoJ0luc3RhbGwgUGlwZVdpcmUgKHB3LXJlY29yZCkgb3IgUHVsc2VBdWRpbyB1dGlsaXRpZXMgKHBhcmVjKSBmb3IgbWljcm9waG9uZSByZWNvcmRpbmcuJylcbiAgICAgIGlmIChzZXNzaW9uLmNhbmNlbGxlZCkgcmV0dXJuXG4gICAgICBzZXNzaW9uLndoaXNwZXIgPSB3aGlzcGVyXG4gICAgICBzZXNzaW9uLmRpciA9IGF3YWl0IGZpbGVzLm1rZHRlbXAoam9pbih0ZW1wUm9vdCwgJ3BpY28tZGljdGF0aW9uLScpKVxuICAgICAgaWYgKHNlc3Npb24uY2FuY2VsbGVkKSB7IGF3YWl0IGNsZWFudXAoc2Vzc2lvbik7IHJldHVybiB9XG4gICAgICBjb25zdCBhcmdzID0gcHcgPyBbJy0tcmF3JywgJy0tZm9ybWF0JywgJ3MxNicsICctLXJhdGUnLCAnMTYwMDAnLCAnLS1jaGFubmVscycsICcxJ10gOiBbJy0tcmF3JywgJy0tZm9ybWF0PXMxNmxlJywgJy0tcmF0ZT0xNjAwMCcsICctLWNoYW5uZWxzPTEnXVxuICAgICAgaWYgKGVudi5QSUNPX0RJQ1RBVElPTl9TT1VSQ0UpIGFyZ3MucHVzaChwdyA/ICctLXRhcmdldCcgOiAnLS1kZXZpY2UnLCBlbnYuUElDT19ESUNUQVRJT05fU09VUkNFKVxuICAgICAgaWYgKHB3KSBhcmdzLnB1c2goJy0nKVxuICAgICAgY29uc3Qgam9iID0gc2Vzc2lvbi5yZWNvcmRlciA9IGxhdW5jaChyZWNvcmRlciwgYXJncylcbiAgICAgIGxldCBsYXN0TGV2ZWwgPSAwXG4gICAgICBqb2IuY2hpbGQuc3Rkb3V0Lm9uKCdkYXRhJywgY2h1bmsgPT4ge1xuICAgICAgICBpZiAoc2Vzc2lvbi5jYW5jZWxsZWQgfHwgc2Vzc2lvbi5zdG9wcGluZykgcmV0dXJuXG4gICAgICAgIGNvbnN0IHJlbWFpbmluZyA9IE1hdGguZmxvb3IobWF4UmVjb3JkaW5nTXMgKiAzMikgLSBzZXNzaW9uLmJ5dGVzXG4gICAgICAgIGNvbnN0IGRhdGEgPSBCdWZmZXIuZnJvbShjaHVuay5zdWJhcnJheSgwLCBNYXRoLm1heCgwLCByZW1haW5pbmcpKSlcbiAgICAgICAgc2Vzc2lvbi5jaHVua3MucHVzaChkYXRhKTsgc2Vzc2lvbi5ieXRlcyArPSBkYXRhLmxlbmd0aFxuICAgICAgICBpZiAoRGF0ZS5ub3coKSAtIGxhc3RMZXZlbCA+PSA1MCkge1xuICAgICAgICAgIGxldCBzdW0gPSAwXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgKyAxIDwgZGF0YS5sZW5ndGg7IGkgKz0gMikgc3VtICs9IChkYXRhLnJlYWRJbnQxNkxFKGkpIC8gMzI3NjgpICoqIDJcbiAgICAgICAgICBzZW5kKHsgc3RhdHVzOiAnbGV2ZWwnLCBsZXZlbDogZGF0YS5sZW5ndGggPj0gMiA/IE1hdGguc3FydChzdW0gLyBNYXRoLmZsb29yKGRhdGEubGVuZ3RoIC8gMikpIDogMCB9KVxuICAgICAgICAgIGxhc3RMZXZlbCA9IERhdGUubm93KClcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2Vzc2lvbi5ieXRlcyA+PSBNYXRoLmZsb29yKG1heFJlY29yZGluZ01zICogMzIpKSB2b2lkIGxpbWl0KClcbiAgICAgIH0pXG4gICAgICBjb25zdCBsaW1pdCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgaWYgKHNlc3Npb24uY2FuY2VsbGVkIHx8IHNlc3Npb24uc3RvcHBpbmcpIHJldHVyblxuICAgICAgICBzZXNzaW9uLnN0b3BwaW5nID0gdHJ1ZVxuICAgICAgICBzZW5kKHsgc3RhdHVzOiAnZXJyb3InLCBtZXNzYWdlOiAnRGljdGF0aW9uIHJlYWNoZWQgdGhlIDEyMC1zZWNvbmQgcmVjb3JkaW5nIGxpbWl0LiBQbGVhc2UgcmVjb3JkIGEgc2hvcnRlciBwYXNzYWdlLicgfSlcbiAgICAgICAgYXdhaXQgY2xlYW51cChzZXNzaW9uKVxuICAgICAgfVxuICAgICAgYXdhaXQgam9iLnN0YXJ0ZWRcbiAgICAgIGpvYi5jbG9zZWQudGhlbihhc3luYyBjb2RlID0+IHtcbiAgICAgICAgaWYgKHNlc3Npb24uY2FuY2VsbGVkIHx8IHNlc3Npb24uc3RvcHBpbmcpIHJldHVyblxuICAgICAgICBzZW5kKHsgc3RhdHVzOiAnZXJyb3InLCBtZXNzYWdlOiBgTWljcm9waG9uZSByZWNvcmRpbmcgc3RvcHBlZCB1bmV4cGVjdGVkbHkgKCR7Y29kZSA/PyBqb2IuZXJyb3I/Lm1lc3NhZ2UgPz8gJ3Vua25vd24gZXJyb3InfSkuIENoZWNrIHlvdXIgYXVkaW8gc291cmNlIGFuZCBwZXJtaXNzaW9ucy4ke2pvYi5zdGRlcnIgPyBgICR7am9iLnN0ZGVyci50cmltKCl9YCA6ICcnfWAgfSlcbiAgICAgICAgYXdhaXQgY2xlYW51cChzZXNzaW9uKVxuICAgICAgfSlcbiAgICAgIHNlc3Npb24udGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHsgdm9pZCBsaW1pdCgpIH0sIG1heFJlY29yZGluZ01zKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7IGF3YWl0IGNsZWFudXAoc2Vzc2lvbik7IHRocm93IGVycm9yIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHN0b3AoKSB7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVxuICAgIGlmICghc2Vzc2lvbiB8fCAhc2Vzc2lvbi5yZWNvcmRlciB8fCBzZXNzaW9uLnN0b3BwaW5nKSB0aHJvdyBuZXcgRXJyb3IoJ05vIGFjdGl2ZSBkaWN0YXRpb24gcmVjb3JkaW5nLicpXG4gICAgc2Vzc2lvbi5zdG9wcGluZyA9IHRydWVcbiAgICBjbGVhclRpbWVvdXQoc2Vzc2lvbi50aW1lcilcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGVybWluYXRlKHNlc3Npb24ucmVjb3JkZXIpXG4gICAgICBpZiAoc2Vzc2lvbi5jYW5jZWxsZWQpIHRocm93IG5ldyBFcnJvcignRGljdGF0aW9uIGNhbmNlbGxlZC4nKVxuICAgICAgY29uc3QgcGNtID0gQnVmZmVyLmNvbmNhdChzZXNzaW9uLmNodW5rcylcbiAgICAgIGNvbnN0IGF1ZGlvID0gam9pbihzZXNzaW9uLmRpciwgJ2F1ZGlvLndhdicpXG4gICAgICBjb25zdCBwcmVmaXggPSBqb2luKHNlc3Npb24uZGlyLCAndHJhbnNjcmlwdCcpXG4gICAgICBjb25zdCBldmVuID0gcGNtLnN1YmFycmF5KDAsIHBjbS5sZW5ndGggLSBwY20ubGVuZ3RoICUgMilcbiAgICAgIGF3YWl0IGZpbGVzLndyaXRlRmlsZShhdWRpbywgQnVmZmVyLmNvbmNhdChbd2F2SGVhZGVyKGV2ZW4ubGVuZ3RoKSwgZXZlbl0pLCB7IG1vZGU6IDBvNjAwIH0pXG4gICAgICBpZiAoc2Vzc2lvbi5jYW5jZWxsZWQpIHRocm93IG5ldyBFcnJvcignRGljdGF0aW9uIGNhbmNlbGxlZC4nKVxuICAgICAgY29uc3Qgam9iID0gc2Vzc2lvbi50cmFuc2NyaWJlciA9IGxhdW5jaChzZXNzaW9uLndoaXNwZXIsIFsnLW0nLCBtb2RlbCwgJy1mJywgYXVkaW8sICctb3R4dCcsICctb2YnLCBwcmVmaXgsICctbCcsIGVudi5QSUNPX1dISVNQRVJfTEFOR1VBR0UgfHwgJ2VuJywgJy1udCddKVxuICAgICAgY29uc3QgY29kZSA9IGF3YWl0IGpvYi5jbG9zZWRcbiAgICAgIGlmIChzZXNzaW9uLmNhbmNlbGxlZCkgdGhyb3cgbmV3IEVycm9yKCdEaWN0YXRpb24gY2FuY2VsbGVkLicpXG4gICAgICBpZiAoam9iLmVycm9yIHx8IGNvZGUgIT09IDApIHRocm93IG5ldyBFcnJvcihgV2hpc3BlciB0cmFuc2NyaXB0aW9uIGZhaWxlZDogJHtqb2IuZXJyb3I/Lm1lc3NhZ2UgfHwgam9iLnN0ZGVyci50cmltKCkgfHwgYGV4aXQgJHtjb2RlfWB9YClcbiAgICAgIHJldHVybiAoYXdhaXQgZmlsZXMucmVhZEZpbGUoYCR7cHJlZml4fS50eHRgLCAndXRmOCcpKS50cmltKClcbiAgICB9IGZpbmFsbHkgeyBhd2FpdCBjbGVhbnVwKHNlc3Npb24pIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGhhbmRsZShjb21tYW5kKSB7XG4gICAgaWYgKGRpc3Bvc2VkKSByZXR1cm5cbiAgICBjb25zdCBpZCA9IGNvbW1hbmQ/LmlkXG4gICAgdHJ5IHtcbiAgICAgIGlmIChpZCA9PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoJ0NvbW1hbmQgcmVxdWlyZXMgYW4gaWQuJylcbiAgICAgIGlmIChjb21tYW5kLm9wID09PSAnc3RhcnQnKSB7IGF3YWl0IHN0YXJ0KCk7IHNlbmQoeyBpZCB9KSB9XG4gICAgICBlbHNlIGlmIChjb21tYW5kLm9wID09PSAnc3RvcCcpIHNlbmQoeyBpZCwgdGV4dDogYXdhaXQgc3RvcCgpIH0pXG4gICAgICBlbHNlIGlmIChjb21tYW5kLm9wID09PSAnY2FuY2VsJykgeyBhd2FpdCBjbGVhbnVwKGFjdGl2ZSk7IHNlbmQoeyBpZCB9KSB9XG4gICAgICBlbHNlIHRocm93IG5ldyBFcnJvcignVW5rbm93biBkaWN0YXRpb24gY29tbWFuZC4nKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7IHNlbmQoeyBpZCwgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfSkgfVxuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICBkaXNwb3NlZCA9IHRydWVcbiAgICBhd2FpdCBjbGVhbnVwKGFjdGl2ZSlcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbLi4uam9ic10ubWFwKHRlcm1pbmF0ZSkpXG4gIH1cbiAgcmV0dXJuIHsgaGFuZGxlLCBkaXNwb3NlIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1bkxpbnV4RGljdGF0aW9uKHsgaW5wdXQgPSBwcm9jZXNzLnN0ZGluLCBvdXRwdXQgPSBwcm9jZXNzLnN0ZG91dCwgc2lnbmFscyA9IHByb2Nlc3MsIC4uLm9wdGlvbnMgfSA9IHt9KSB7XG4gIGNvbnN0IGVtaXQgPSBtZXNzYWdlID0+IG91dHB1dC53cml0ZShgJHtKU09OLnN0cmluZ2lmeShtZXNzYWdlKX1cXG5gKVxuICBjb25zdCBoZWxwZXIgPSBjcmVhdGVMaW51eERpY3RhdGlvbih7IC4uLm9wdGlvbnMsIGVtaXQgfSlcbiAgY29uc3QgbGluZXMgPSBjcmVhdGVJbnRlcmZhY2UoeyBpbnB1dCB9KVxuICBsZXQgY2xvc2luZyA9IGZhbHNlXG4gIGNvbnN0IGNsb3NlID0gYXN5bmMgKCkgPT4ge1xuICAgIGlmIChjbG9zaW5nKSByZXR1cm5cbiAgICBjbG9zaW5nID0gdHJ1ZVxuICAgIGxpbmVzLmNsb3NlKClcbiAgICBzaWduYWxzLnJlbW92ZUxpc3RlbmVyKCdTSUdURVJNJywgY2xvc2UpOyBzaWduYWxzLnJlbW92ZUxpc3RlbmVyKCdTSUdJTlQnLCBjbG9zZSlcbiAgICBhd2FpdCBoZWxwZXIuZGlzcG9zZSgpXG4gIH1cbiAgbGluZXMub24oJ2xpbmUnLCBsaW5lID0+IHtcbiAgICBpZiAobGluZS5sZW5ndGggPiA2NTUzNikgcmV0dXJuIGVtaXQoeyBzdGF0dXM6ICdlcnJvcicsIG1lc3NhZ2U6ICdEaWN0YXRpb24gY29tbWFuZCBpcyB0b28gbGFyZ2UuJyB9KVxuICAgIHRyeSB7IHZvaWQgaGVscGVyLmhhbmRsZShKU09OLnBhcnNlKGxpbmUpKSB9IGNhdGNoIHsgZW1pdCh7IHN0YXR1czogJ2Vycm9yJywgbWVzc2FnZTogJ0ludmFsaWQgZGljdGF0aW9uIGNvbW1hbmQgSlNPTi4nIH0pIH1cbiAgfSlcbiAgbGluZXMub24oJ2Nsb3NlJywgY2xvc2UpXG4gIGlucHV0Lm9uKCdlcnJvcicsIGNsb3NlKVxuICBvdXRwdXQub24oJ2Vycm9yJywgY2xvc2UpXG4gIHNpZ25hbHMub24oJ1NJR1RFUk0nLCBjbG9zZSk7IHNpZ25hbHMub24oJ1NJR0lOVCcsIGNsb3NlKVxuICBlbWl0KHsgc3RhdHVzOiAncmVhZHknIH0pXG4gIHJldHVybiB7IC4uLmhlbHBlciwgZGlzcG9zZTogY2xvc2UgfVxufVxuXG5pZiAocHJvY2Vzcy5hcmd2WzFdICYmIHJlc29sdmUocHJvY2Vzcy5hcmd2WzFdKSA9PT0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKSBydW5MaW51eERpY3RhdGlvbigpXG4iXSwKICAibWFwcGluZ3MiOiAiOzs7QUFDQSxTQUFTLFNBQVMsaUJBQWlCO0FBQ25DLFlBQVksUUFBUTtBQUNwQixTQUFTLGlCQUFpQjtBQUMxQixTQUFTLFNBQVMsY0FBYztBQUNoQyxTQUFTLFdBQVcsTUFBTSxlQUFlO0FBQ3pDLFNBQVMscUJBQXFCO0FBQzlCLFNBQVMsdUJBQXVCO0FBRXpCLFNBQVMsVUFBVSxPQUFPO0FBQy9CLFFBQU0sU0FBUyxPQUFPLE1BQU0sRUFBRTtBQUM5QixTQUFPLE1BQU0sTUFBTTtBQUFHLFNBQU8sY0FBYyxRQUFRLElBQUksQ0FBQztBQUFHLFNBQU8sTUFBTSxZQUFZLENBQUM7QUFDckYsU0FBTyxjQUFjLElBQUksRUFBRTtBQUFHLFNBQU8sY0FBYyxHQUFHLEVBQUU7QUFBRyxTQUFPLGNBQWMsR0FBRyxFQUFFO0FBQ3JGLFNBQU8sY0FBYyxNQUFPLEVBQUU7QUFBRyxTQUFPLGNBQWMsTUFBTyxFQUFFO0FBQy9ELFNBQU8sY0FBYyxHQUFHLEVBQUU7QUFBRyxTQUFP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
package/dist/pico-dictate CHANGED
Binary file