@dualityinstitute/blink 0.0.2 → 0.0.4

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.
@@ -14,7 +14,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
14
14
 
15
15
  // node_modules/picomatch/lib/constants.js
16
16
  var require_constants = __commonJS((exports, module) => {
17
- var path6 = __require("path");
17
+ var path7 = __require("path");
18
18
  var WIN_SLASH = "\\\\/";
19
19
  var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
20
20
  var DEFAULT_MAX_EXTGLOB_RECURSION = 0;
@@ -140,7 +140,7 @@ var require_constants = __commonJS((exports, module) => {
140
140
  CHAR_UNDERSCORE: 95,
141
141
  CHAR_VERTICAL_LINE: 124,
142
142
  CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
143
- SEP: path6.sep,
143
+ SEP: path7.sep,
144
144
  extglobChars(chars) {
145
145
  return {
146
146
  "!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` },
@@ -158,7 +158,7 @@ var require_constants = __commonJS((exports, module) => {
158
158
 
159
159
  // node_modules/picomatch/lib/utils.js
160
160
  var require_utils = __commonJS((exports) => {
161
- var path6 = __require("path");
161
+ var path7 = __require("path");
162
162
  var win32 = process.platform === "win32";
163
163
  var {
164
164
  REGEX_BACKSLASH,
@@ -187,7 +187,7 @@ var require_utils = __commonJS((exports) => {
187
187
  if (options && typeof options.windows === "boolean") {
188
188
  return options.windows;
189
189
  }
190
- return win32 === true || path6.sep === "\\";
190
+ return win32 === true || path7.sep === "\\";
191
191
  };
192
192
  exports.escapeLast = (input2, char, lastIdx) => {
193
193
  const idx = input2.lastIndexOf(char, lastIdx);
@@ -1540,7 +1540,7 @@ var require_parse = __commonJS((exports, module) => {
1540
1540
 
1541
1541
  // node_modules/picomatch/lib/picomatch.js
1542
1542
  var require_picomatch = __commonJS((exports, module) => {
1543
- var path6 = __require("path");
1543
+ var path7 = __require("path");
1544
1544
  var scan = require_scan();
1545
1545
  var parse5 = require_parse();
1546
1546
  var utils = require_utils();
@@ -1626,7 +1626,7 @@ var require_picomatch = __commonJS((exports, module) => {
1626
1626
  };
1627
1627
  picomatch.matchBase = (input2, glob, options, posix = utils.isWindows(options)) => {
1628
1628
  const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
1629
- return regex.test(path6.basename(input2));
1629
+ return regex.test(path7.basename(input2));
1630
1630
  };
1631
1631
  picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
1632
1632
  picomatch.parse = (pattern, options) => {
@@ -1681,15 +1681,15 @@ var require_picomatch = __commonJS((exports, module) => {
1681
1681
 
1682
1682
  // node_modules/readdirp/index.js
1683
1683
  var require_readdirp = __commonJS((exports, module) => {
1684
- var fs5 = __require("fs");
1684
+ var fs6 = __require("fs");
1685
1685
  var { Readable } = __require("stream");
1686
1686
  var sysPath = __require("path");
1687
1687
  var { promisify } = __require("util");
1688
1688
  var picomatch = require_picomatch();
1689
- var readdir = promisify(fs5.readdir);
1690
- var stat = promisify(fs5.stat);
1691
- var lstat = promisify(fs5.lstat);
1692
- var realpath = promisify(fs5.realpath);
1689
+ var readdir = promisify(fs6.readdir);
1690
+ var stat = promisify(fs6.stat);
1691
+ var lstat = promisify(fs6.lstat);
1692
+ var realpath = promisify(fs6.realpath);
1693
1693
  var BANG = "!";
1694
1694
  var RECURSIVE_ERROR_CODE = "READDIRP_RECURSIVE_ERROR";
1695
1695
  var NORMAL_FLOW_ERRORS = new Set(["ENOENT", "EPERM", "EACCES", "ELOOP", RECURSIVE_ERROR_CODE]);
@@ -1735,8 +1735,8 @@ var require_readdirp = __commonJS((exports, module) => {
1735
1735
  static get defaultOptions() {
1736
1736
  return {
1737
1737
  root: ".",
1738
- fileFilter: (path6) => true,
1739
- directoryFilter: (path6) => true,
1738
+ fileFilter: (path7) => true,
1739
+ directoryFilter: (path7) => true,
1740
1740
  type: FILE_TYPE,
1741
1741
  lstat: false,
1742
1742
  depth: 2147483648,
@@ -1755,7 +1755,7 @@ var require_readdirp = __commonJS((exports, module) => {
1755
1755
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
1756
1756
  const statMethod = opts.lstat ? lstat : stat;
1757
1757
  if (wantBigintFsStats) {
1758
- this._stat = (path6) => statMethod(path6, { bigint: true });
1758
+ this._stat = (path7) => statMethod(path7, { bigint: true });
1759
1759
  } else {
1760
1760
  this._stat = statMethod;
1761
1761
  }
@@ -1764,7 +1764,7 @@ var require_readdirp = __commonJS((exports, module) => {
1764
1764
  this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
1765
1765
  this._wantsEverything = type === EVERYTHING_TYPE;
1766
1766
  this._root = sysPath.resolve(root);
1767
- this._isDirent = "Dirent" in fs5 && !opts.alwaysStat;
1767
+ this._isDirent = "Dirent" in fs6 && !opts.alwaysStat;
1768
1768
  this._statsProp = this._isDirent ? "dirent" : "stats";
1769
1769
  this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
1770
1770
  this.parents = [this._exploreDir(root, 1)];
@@ -1777,9 +1777,9 @@ var require_readdirp = __commonJS((exports, module) => {
1777
1777
  this.reading = true;
1778
1778
  try {
1779
1779
  while (!this.destroyed && batch > 0) {
1780
- const { path: path6, depth, files = [] } = this.parent || {};
1780
+ const { path: path7, depth, files = [] } = this.parent || {};
1781
1781
  if (files.length > 0) {
1782
- const slice = files.splice(0, batch).map((dirent) => this._formatEntry(dirent, path6));
1782
+ const slice = files.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
1783
1783
  for (const entry of await Promise.all(slice)) {
1784
1784
  if (this.destroyed)
1785
1785
  return;
@@ -1816,20 +1816,20 @@ var require_readdirp = __commonJS((exports, module) => {
1816
1816
  this.reading = false;
1817
1817
  }
1818
1818
  }
1819
- async _exploreDir(path6, depth) {
1819
+ async _exploreDir(path7, depth) {
1820
1820
  let files;
1821
1821
  try {
1822
- files = await readdir(path6, this._rdOptions);
1822
+ files = await readdir(path7, this._rdOptions);
1823
1823
  } catch (error61) {
1824
1824
  this._onError(error61);
1825
1825
  }
1826
- return { files, depth, path: path6 };
1826
+ return { files, depth, path: path7 };
1827
1827
  }
1828
- async _formatEntry(dirent, path6) {
1828
+ async _formatEntry(dirent, path7) {
1829
1829
  let entry;
1830
1830
  try {
1831
1831
  const basename2 = this._isDirent ? dirent.name : dirent;
1832
- const fullPath = sysPath.resolve(sysPath.join(path6, basename2));
1832
+ const fullPath = sysPath.resolve(sysPath.join(path7, basename2));
1833
1833
  entry = { path: sysPath.relative(this._root, fullPath), fullPath, basename: basename2 };
1834
1834
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
1835
1835
  } catch (err) {
@@ -1918,24 +1918,24 @@ var require_normalize_path = __commonJS((exports, module) => {
1918
1918
  * Copyright (c) 2014-2018, Jon Schlinkert.
1919
1919
  * Released under the MIT License.
1920
1920
  */
1921
- module.exports = function(path6, stripTrailing) {
1922
- if (typeof path6 !== "string") {
1921
+ module.exports = function(path7, stripTrailing) {
1922
+ if (typeof path7 !== "string") {
1923
1923
  throw new TypeError("expected path to be a string");
1924
1924
  }
1925
- if (path6 === "\\" || path6 === "/")
1925
+ if (path7 === "\\" || path7 === "/")
1926
1926
  return "/";
1927
- var len = path6.length;
1927
+ var len = path7.length;
1928
1928
  if (len <= 1)
1929
- return path6;
1929
+ return path7;
1930
1930
  var prefix = "";
1931
- if (len > 4 && path6[3] === "\\") {
1932
- var ch = path6[2];
1933
- if ((ch === "?" || ch === ".") && path6.slice(0, 2) === "\\\\") {
1934
- path6 = path6.slice(2);
1931
+ if (len > 4 && path7[3] === "\\") {
1932
+ var ch = path7[2];
1933
+ if ((ch === "?" || ch === ".") && path7.slice(0, 2) === "\\\\") {
1934
+ path7 = path7.slice(2);
1935
1935
  prefix = "//";
1936
1936
  }
1937
1937
  }
1938
- var segs = path6.split(/[/\\]+/);
1938
+ var segs = path7.split(/[/\\]+/);
1939
1939
  if (stripTrailing !== false && segs[segs.length - 1] === "") {
1940
1940
  segs.pop();
1941
1941
  }
@@ -1970,17 +1970,17 @@ var require_anymatch = __commonJS((exports, module) => {
1970
1970
  if (!isList && typeof _path !== "string") {
1971
1971
  throw new TypeError("anymatch: second argument must be a string: got " + Object.prototype.toString.call(_path));
1972
1972
  }
1973
- const path6 = normalizePath(_path, false);
1973
+ const path7 = normalizePath(_path, false);
1974
1974
  for (let index = 0;index < negPatterns.length; index++) {
1975
1975
  const nglob = negPatterns[index];
1976
- if (nglob(path6)) {
1976
+ if (nglob(path7)) {
1977
1977
  return returnIndex ? -1 : false;
1978
1978
  }
1979
1979
  }
1980
- const applied = isList && [path6].concat(args.slice(1));
1980
+ const applied = isList && [path7].concat(args.slice(1));
1981
1981
  for (let index = 0;index < patterns.length; index++) {
1982
1982
  const pattern = patterns[index];
1983
- if (isList ? pattern(...applied) : pattern(path6)) {
1983
+ if (isList ? pattern(...applied) : pattern(path7)) {
1984
1984
  return returnIndex ? index : true;
1985
1985
  }
1986
1986
  }
@@ -2574,7 +2574,7 @@ var require_fill_range = __commonJS((exports, module) => {
2574
2574
  }
2575
2575
  return options.stringify === true;
2576
2576
  };
2577
- var pad3 = (input2, maxLength, toNumber) => {
2577
+ var pad4 = (input2, maxLength, toNumber) => {
2578
2578
  if (maxLength > 0) {
2579
2579
  let dash = input2[0] === "-" ? "-" : "";
2580
2580
  if (dash)
@@ -2683,7 +2683,7 @@ var require_fill_range = __commonJS((exports, module) => {
2683
2683
  if (options.toRegex === true && step > 1) {
2684
2684
  push(a);
2685
2685
  } else {
2686
- range.push(pad3(format(a, index), maxLen, toNumber));
2686
+ range.push(pad4(format(a, index), maxLen, toNumber));
2687
2687
  }
2688
2688
  a = descending ? a - step : a + step;
2689
2689
  index++;
@@ -3499,10 +3499,10 @@ var require_binary_extensions = __commonJS((exports, module) => {
3499
3499
 
3500
3500
  // node_modules/is-binary-path/index.js
3501
3501
  var require_is_binary_path = __commonJS((exports, module) => {
3502
- var path6 = __require("path");
3502
+ var path7 = __require("path");
3503
3503
  var binaryExtensions = require_binary_extensions();
3504
3504
  var extensions = new Set(binaryExtensions);
3505
- module.exports = (filePath) => extensions.has(path6.extname(filePath).slice(1).toLowerCase());
3505
+ module.exports = (filePath) => extensions.has(path7.extname(filePath).slice(1).toLowerCase());
3506
3506
  });
3507
3507
 
3508
3508
  // node_modules/chokidar/lib/constants.js
@@ -3567,7 +3567,7 @@ var require_constants3 = __commonJS((exports) => {
3567
3567
 
3568
3568
  // node_modules/chokidar/lib/nodefs-handler.js
3569
3569
  var require_nodefs_handler = __commonJS((exports, module) => {
3570
- var fs5 = __require("fs");
3570
+ var fs6 = __require("fs");
3571
3571
  var sysPath = __require("path");
3572
3572
  var { promisify } = __require("util");
3573
3573
  var isBinaryPath = require_is_binary_path();
@@ -3590,11 +3590,11 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3590
3590
  STAR
3591
3591
  } = require_constants3();
3592
3592
  var THROTTLE_MODE_WATCH = "watch";
3593
- var open2 = promisify(fs5.open);
3594
- var stat = promisify(fs5.stat);
3595
- var lstat = promisify(fs5.lstat);
3596
- var close = promisify(fs5.close);
3597
- var fsrealpath = promisify(fs5.realpath);
3593
+ var open2 = promisify(fs6.open);
3594
+ var stat = promisify(fs6.stat);
3595
+ var lstat = promisify(fs6.lstat);
3596
+ var close = promisify(fs6.close);
3597
+ var fsrealpath = promisify(fs6.realpath);
3598
3598
  var statMethods = { lstat, stat };
3599
3599
  var foreach = (val, fn) => {
3600
3600
  if (val instanceof Set) {
@@ -3628,16 +3628,16 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3628
3628
  };
3629
3629
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
3630
3630
  var FsWatchInstances = new Map;
3631
- function createFsWatchInstance(path6, options, listener, errHandler, emitRaw) {
3631
+ function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
3632
3632
  const handleEvent = (rawEvent, evPath) => {
3633
- listener(path6);
3634
- emitRaw(rawEvent, evPath, { watchedPath: path6 });
3635
- if (evPath && path6 !== evPath) {
3636
- fsWatchBroadcast(sysPath.resolve(path6, evPath), KEY_LISTENERS, sysPath.join(path6, evPath));
3633
+ listener(path7);
3634
+ emitRaw(rawEvent, evPath, { watchedPath: path7 });
3635
+ if (evPath && path7 !== evPath) {
3636
+ fsWatchBroadcast(sysPath.resolve(path7, evPath), KEY_LISTENERS, sysPath.join(path7, evPath));
3637
3637
  }
3638
3638
  };
3639
3639
  try {
3640
- return fs5.watch(path6, options, handleEvent);
3640
+ return fs6.watch(path7, options, handleEvent);
3641
3641
  } catch (error61) {
3642
3642
  errHandler(error61);
3643
3643
  }
@@ -3650,12 +3650,12 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3650
3650
  listener(val1, val2, val3);
3651
3651
  });
3652
3652
  };
3653
- var setFsWatchListener = (path6, fullPath, options, handlers) => {
3653
+ var setFsWatchListener = (path7, fullPath, options, handlers) => {
3654
3654
  const { listener, errHandler, rawEmitter } = handlers;
3655
3655
  let cont = FsWatchInstances.get(fullPath);
3656
3656
  let watcher;
3657
3657
  if (!options.persistent) {
3658
- watcher = createFsWatchInstance(path6, options, listener, errHandler, rawEmitter);
3658
+ watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
3659
3659
  return watcher.close.bind(watcher);
3660
3660
  }
3661
3661
  if (cont) {
@@ -3663,7 +3663,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3663
3663
  addAndConvert(cont, KEY_ERR, errHandler);
3664
3664
  addAndConvert(cont, KEY_RAW, rawEmitter);
3665
3665
  } else {
3666
- watcher = createFsWatchInstance(path6, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
3666
+ watcher = createFsWatchInstance(path7, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
3667
3667
  if (!watcher)
3668
3668
  return;
3669
3669
  watcher.on(EV_ERROR, async (error61) => {
@@ -3671,7 +3671,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3671
3671
  cont.watcherUnusable = true;
3672
3672
  if (isWindows && error61.code === "EPERM") {
3673
3673
  try {
3674
- const fd = await open2(path6, "r");
3674
+ const fd = await open2(path7, "r");
3675
3675
  await close(fd);
3676
3676
  broadcastErr(error61);
3677
3677
  } catch (err) {}
@@ -3701,7 +3701,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3701
3701
  };
3702
3702
  };
3703
3703
  var FsWatchFileInstances = new Map;
3704
- var setFsWatchFileListener = (path6, fullPath, options, handlers) => {
3704
+ var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
3705
3705
  const { listener, rawEmitter } = handlers;
3706
3706
  let cont = FsWatchFileInstances.get(fullPath);
3707
3707
  let listeners = new Set;
@@ -3710,7 +3710,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3710
3710
  if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
3711
3711
  listeners = cont.listeners;
3712
3712
  rawEmitters = cont.rawEmitters;
3713
- fs5.unwatchFile(fullPath);
3713
+ fs6.unwatchFile(fullPath);
3714
3714
  cont = undefined;
3715
3715
  }
3716
3716
  if (cont) {
@@ -3721,13 +3721,13 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3721
3721
  listeners: listener,
3722
3722
  rawEmitters: rawEmitter,
3723
3723
  options,
3724
- watcher: fs5.watchFile(fullPath, options, (curr, prev) => {
3724
+ watcher: fs6.watchFile(fullPath, options, (curr, prev) => {
3725
3725
  foreach(cont.rawEmitters, (rawEmitter2) => {
3726
3726
  rawEmitter2(EV_CHANGE, fullPath, { curr, prev });
3727
3727
  });
3728
3728
  const currmtime = curr.mtimeMs;
3729
3729
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
3730
- foreach(cont.listeners, (listener2) => listener2(path6, curr));
3730
+ foreach(cont.listeners, (listener2) => listener2(path7, curr));
3731
3731
  }
3732
3732
  })
3733
3733
  };
@@ -3738,7 +3738,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3738
3738
  delFromSet(cont, KEY_RAW, rawEmitter);
3739
3739
  if (isEmptySet(cont.listeners)) {
3740
3740
  FsWatchFileInstances.delete(fullPath);
3741
- fs5.unwatchFile(fullPath);
3741
+ fs6.unwatchFile(fullPath);
3742
3742
  cont.options = cont.watcher = undefined;
3743
3743
  Object.freeze(cont);
3744
3744
  }
@@ -3750,25 +3750,25 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3750
3750
  this.fsw = fsW;
3751
3751
  this._boundHandleError = (error61) => fsW._handleError(error61);
3752
3752
  }
3753
- _watchWithNodeFs(path6, listener) {
3753
+ _watchWithNodeFs(path7, listener) {
3754
3754
  const opts = this.fsw.options;
3755
- const directory = sysPath.dirname(path6);
3756
- const basename2 = sysPath.basename(path6);
3755
+ const directory = sysPath.dirname(path7);
3756
+ const basename2 = sysPath.basename(path7);
3757
3757
  const parent = this.fsw._getWatchedDir(directory);
3758
3758
  parent.add(basename2);
3759
- const absolutePath = sysPath.resolve(path6);
3759
+ const absolutePath = sysPath.resolve(path7);
3760
3760
  const options = { persistent: opts.persistent };
3761
3761
  if (!listener)
3762
3762
  listener = EMPTY_FN;
3763
3763
  let closer;
3764
3764
  if (opts.usePolling) {
3765
3765
  options.interval = opts.enableBinaryInterval && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
3766
- closer = setFsWatchFileListener(path6, absolutePath, options, {
3766
+ closer = setFsWatchFileListener(path7, absolutePath, options, {
3767
3767
  listener,
3768
3768
  rawEmitter: this.fsw._emitRaw
3769
3769
  });
3770
3770
  } else {
3771
- closer = setFsWatchListener(path6, absolutePath, options, {
3771
+ closer = setFsWatchListener(path7, absolutePath, options, {
3772
3772
  listener,
3773
3773
  errHandler: this._boundHandleError,
3774
3774
  rawEmitter: this.fsw._emitRaw
@@ -3786,7 +3786,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3786
3786
  let prevStats = stats;
3787
3787
  if (parent.has(basename2))
3788
3788
  return;
3789
- const listener = async (path6, newStats) => {
3789
+ const listener = async (path7, newStats) => {
3790
3790
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
3791
3791
  return;
3792
3792
  if (!newStats || newStats.mtimeMs === 0) {
@@ -3800,9 +3800,9 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3800
3800
  this.fsw._emit(EV_CHANGE, file2, newStats2);
3801
3801
  }
3802
3802
  if (isLinux && prevStats.ino !== newStats2.ino) {
3803
- this.fsw._closeFile(path6);
3803
+ this.fsw._closeFile(path7);
3804
3804
  prevStats = newStats2;
3805
- this.fsw._addPathCloser(path6, this._watchWithNodeFs(file2, listener));
3805
+ this.fsw._addPathCloser(path7, this._watchWithNodeFs(file2, listener));
3806
3806
  } else {
3807
3807
  prevStats = newStats2;
3808
3808
  }
@@ -3826,7 +3826,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3826
3826
  }
3827
3827
  return closer;
3828
3828
  }
3829
- async _handleSymlink(entry, directory, path6, item) {
3829
+ async _handleSymlink(entry, directory, path7, item) {
3830
3830
  if (this.fsw.closed) {
3831
3831
  return;
3832
3832
  }
@@ -3836,7 +3836,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3836
3836
  this.fsw._incrReadyCount();
3837
3837
  let linkPath;
3838
3838
  try {
3839
- linkPath = await fsrealpath(path6);
3839
+ linkPath = await fsrealpath(path7);
3840
3840
  } catch (e) {
3841
3841
  this.fsw._emitReady();
3842
3842
  return true;
@@ -3846,12 +3846,12 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3846
3846
  if (dir.has(item)) {
3847
3847
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
3848
3848
  this.fsw._symlinkPaths.set(full, linkPath);
3849
- this.fsw._emit(EV_CHANGE, path6, entry.stats);
3849
+ this.fsw._emit(EV_CHANGE, path7, entry.stats);
3850
3850
  }
3851
3851
  } else {
3852
3852
  dir.add(item);
3853
3853
  this.fsw._symlinkPaths.set(full, linkPath);
3854
- this.fsw._emit(EV_ADD, path6, entry.stats);
3854
+ this.fsw._emit(EV_ADD, path7, entry.stats);
3855
3855
  }
3856
3856
  this.fsw._emitReady();
3857
3857
  return true;
@@ -3880,9 +3880,9 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3880
3880
  return;
3881
3881
  }
3882
3882
  const item = entry.path;
3883
- let path6 = sysPath.join(directory, item);
3883
+ let path7 = sysPath.join(directory, item);
3884
3884
  current.add(item);
3885
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path6, item)) {
3885
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
3886
3886
  return;
3887
3887
  }
3888
3888
  if (this.fsw.closed) {
@@ -3891,8 +3891,8 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3891
3891
  }
3892
3892
  if (item === target || !target && !previous.has(item)) {
3893
3893
  this.fsw._incrReadyCount();
3894
- path6 = sysPath.join(dir, sysPath.relative(dir, path6));
3895
- this._addToNodeFs(path6, initialAdd, wh, depth + 1);
3894
+ path7 = sysPath.join(dir, sysPath.relative(dir, path7));
3895
+ this._addToNodeFs(path7, initialAdd, wh, depth + 1);
3896
3896
  }
3897
3897
  }).on(EV_ERROR, this._boundHandleError);
3898
3898
  return new Promise((resolve) => stream.once(STR_END, () => {
@@ -3940,13 +3940,13 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3940
3940
  }
3941
3941
  return closer;
3942
3942
  }
3943
- async _addToNodeFs(path6, initialAdd, priorWh, depth, target) {
3943
+ async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
3944
3944
  const ready = this.fsw._emitReady;
3945
- if (this.fsw._isIgnored(path6) || this.fsw.closed) {
3945
+ if (this.fsw._isIgnored(path7) || this.fsw.closed) {
3946
3946
  ready();
3947
3947
  return false;
3948
3948
  }
3949
- const wh = this.fsw._getWatchHelpers(path6, depth);
3949
+ const wh = this.fsw._getWatchHelpers(path7, depth);
3950
3950
  if (!wh.hasGlob && priorWh) {
3951
3951
  wh.hasGlob = priorWh.hasGlob;
3952
3952
  wh.globFilter = priorWh.globFilter;
@@ -3961,11 +3961,11 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3961
3961
  ready();
3962
3962
  return false;
3963
3963
  }
3964
- const follow = this.fsw.options.followSymlinks && !path6.includes(STAR) && !path6.includes(BRACE_START);
3964
+ const follow = this.fsw.options.followSymlinks && !path7.includes(STAR) && !path7.includes(BRACE_START);
3965
3965
  let closer;
3966
3966
  if (stats.isDirectory()) {
3967
- const absPath = sysPath.resolve(path6);
3968
- const targetPath = follow ? await fsrealpath(path6) : path6;
3967
+ const absPath = sysPath.resolve(path7);
3968
+ const targetPath = follow ? await fsrealpath(path7) : path7;
3969
3969
  if (this.fsw.closed)
3970
3970
  return;
3971
3971
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -3975,28 +3975,28 @@ var require_nodefs_handler = __commonJS((exports, module) => {
3975
3975
  this.fsw._symlinkPaths.set(absPath, targetPath);
3976
3976
  }
3977
3977
  } else if (stats.isSymbolicLink()) {
3978
- const targetPath = follow ? await fsrealpath(path6) : path6;
3978
+ const targetPath = follow ? await fsrealpath(path7) : path7;
3979
3979
  if (this.fsw.closed)
3980
3980
  return;
3981
3981
  const parent = sysPath.dirname(wh.watchPath);
3982
3982
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
3983
3983
  this.fsw._emit(EV_ADD, wh.watchPath, stats);
3984
- closer = await this._handleDir(parent, stats, initialAdd, depth, path6, wh, targetPath);
3984
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
3985
3985
  if (this.fsw.closed)
3986
3986
  return;
3987
3987
  if (targetPath !== undefined) {
3988
- this.fsw._symlinkPaths.set(sysPath.resolve(path6), targetPath);
3988
+ this.fsw._symlinkPaths.set(sysPath.resolve(path7), targetPath);
3989
3989
  }
3990
3990
  } else {
3991
3991
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
3992
3992
  }
3993
3993
  ready();
3994
- this.fsw._addPathCloser(path6, closer);
3994
+ this.fsw._addPathCloser(path7, closer);
3995
3995
  return false;
3996
3996
  } catch (error61) {
3997
3997
  if (this.fsw._handleError(error61)) {
3998
3998
  ready();
3999
- return path6;
3999
+ return path7;
4000
4000
  }
4001
4001
  }
4002
4002
  }
@@ -4016,9 +4016,9 @@ var require_fsevents2 = __commonJS((exports) => {
4016
4016
  }
4017
4017
  var Native = require_fsevents();
4018
4018
  var events = Native.constants;
4019
- function watch(path6, since, handler) {
4020
- if (typeof path6 !== "string") {
4021
- throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof path6}`);
4019
+ function watch(path7, since, handler) {
4020
+ if (typeof path7 !== "string") {
4021
+ throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof path7}`);
4022
4022
  }
4023
4023
  if (typeof since === "function" && typeof handler === "undefined") {
4024
4024
  handler = since;
@@ -4030,18 +4030,18 @@ var require_fsevents2 = __commonJS((exports) => {
4030
4030
  if (typeof handler !== "function") {
4031
4031
  throw new TypeError(`fsevents argument 3 must be a function and not a ${typeof handler}`);
4032
4032
  }
4033
- let instance = Native.start(Native.global, path6, since, handler);
4033
+ let instance = Native.start(Native.global, path7, since, handler);
4034
4034
  if (!instance)
4035
- throw new Error(`could not watch: ${path6}`);
4035
+ throw new Error(`could not watch: ${path7}`);
4036
4036
  return () => {
4037
4037
  const result = instance ? Promise.resolve(instance).then(Native.stop) : Promise.resolve(undefined);
4038
4038
  instance = undefined;
4039
4039
  return result;
4040
4040
  };
4041
4041
  }
4042
- function getInfo(path6, flags) {
4042
+ function getInfo(path7, flags) {
4043
4043
  return {
4044
- path: path6,
4044
+ path: path7,
4045
4045
  flags,
4046
4046
  event: getEventType(flags),
4047
4047
  type: getFileType(flags),
@@ -4095,7 +4095,7 @@ var require_fsevents2 = __commonJS((exports) => {
4095
4095
 
4096
4096
  // node_modules/chokidar/lib/fsevents-handler.js
4097
4097
  var require_fsevents_handler = __commonJS((exports, module) => {
4098
- var fs5 = __require("fs");
4098
+ var fs6 = __require("fs");
4099
4099
  var sysPath = __require("path");
4100
4100
  var { promisify } = __require("util");
4101
4101
  var fsevents;
@@ -4140,9 +4140,9 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4140
4140
  IDENTITY_FN
4141
4141
  } = require_constants3();
4142
4142
  var Depth = (value) => isNaN(value) ? {} : { depth: value };
4143
- var stat = promisify(fs5.stat);
4144
- var lstat = promisify(fs5.lstat);
4145
- var realpath = promisify(fs5.realpath);
4143
+ var stat = promisify(fs6.stat);
4144
+ var lstat = promisify(fs6.lstat);
4145
+ var realpath = promisify(fs6.realpath);
4146
4146
  var statMethods = { stat, lstat };
4147
4147
  var FSEventsWatchers = new Map;
4148
4148
  var consolidateThreshhold = 10;
@@ -4156,18 +4156,18 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4156
4156
  131840,
4157
4157
  262912
4158
4158
  ]);
4159
- var createFSEventsInstance = (path6, callback) => {
4160
- const stop2 = fsevents.watch(path6, callback);
4159
+ var createFSEventsInstance = (path7, callback) => {
4160
+ const stop2 = fsevents.watch(path7, callback);
4161
4161
  return { stop: stop2 };
4162
4162
  };
4163
- function setFSEventsListener(path6, realPath, listener, rawEmitter) {
4163
+ function setFSEventsListener(path7, realPath, listener, rawEmitter) {
4164
4164
  let watchPath = sysPath.extname(realPath) ? sysPath.dirname(realPath) : realPath;
4165
4165
  const parentPath = sysPath.dirname(watchPath);
4166
4166
  let cont = FSEventsWatchers.get(watchPath);
4167
4167
  if (couldConsolidate(parentPath)) {
4168
4168
  watchPath = parentPath;
4169
4169
  }
4170
- const resolvedPath = sysPath.resolve(path6);
4170
+ const resolvedPath = sysPath.resolve(path7);
4171
4171
  const hasSymlink = resolvedPath !== realPath;
4172
4172
  const filteredListener = (fullPath, flags, info) => {
4173
4173
  if (hasSymlink)
@@ -4217,10 +4217,10 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4217
4217
  }
4218
4218
  };
4219
4219
  }
4220
- var couldConsolidate = (path6) => {
4220
+ var couldConsolidate = (path7) => {
4221
4221
  let count = 0;
4222
4222
  for (const watchPath of FSEventsWatchers.keys()) {
4223
- if (watchPath.indexOf(path6) === 0) {
4223
+ if (watchPath.indexOf(path7) === 0) {
4224
4224
  count++;
4225
4225
  if (count >= consolidateThreshhold) {
4226
4226
  return true;
@@ -4230,9 +4230,9 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4230
4230
  return false;
4231
4231
  };
4232
4232
  var canUse = () => fsevents && FSEventsWatchers.size < 128;
4233
- var calcDepth = (path6, root) => {
4233
+ var calcDepth = (path7, root) => {
4234
4234
  let i = 0;
4235
- while (!path6.indexOf(root) && (path6 = sysPath.dirname(path6)) !== root)
4235
+ while (!path7.indexOf(root) && (path7 = sysPath.dirname(path7)) !== root)
4236
4236
  i++;
4237
4237
  return i;
4238
4238
  };
@@ -4242,42 +4242,42 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4242
4242
  constructor(fsw) {
4243
4243
  this.fsw = fsw;
4244
4244
  }
4245
- checkIgnored(path6, stats) {
4245
+ checkIgnored(path7, stats) {
4246
4246
  const ipaths = this.fsw._ignoredPaths;
4247
- if (this.fsw._isIgnored(path6, stats)) {
4248
- ipaths.add(path6);
4247
+ if (this.fsw._isIgnored(path7, stats)) {
4248
+ ipaths.add(path7);
4249
4249
  if (stats && stats.isDirectory()) {
4250
- ipaths.add(path6 + ROOT_GLOBSTAR);
4250
+ ipaths.add(path7 + ROOT_GLOBSTAR);
4251
4251
  }
4252
4252
  return true;
4253
4253
  }
4254
- ipaths.delete(path6);
4255
- ipaths.delete(path6 + ROOT_GLOBSTAR);
4254
+ ipaths.delete(path7);
4255
+ ipaths.delete(path7 + ROOT_GLOBSTAR);
4256
4256
  }
4257
- addOrChange(path6, fullPath, realPath, parent, watchedDir, item, info, opts) {
4257
+ addOrChange(path7, fullPath, realPath, parent, watchedDir, item, info, opts) {
4258
4258
  const event = watchedDir.has(item) ? EV_CHANGE : EV_ADD;
4259
- this.handleEvent(event, path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4259
+ this.handleEvent(event, path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4260
4260
  }
4261
- async checkExists(path6, fullPath, realPath, parent, watchedDir, item, info, opts) {
4261
+ async checkExists(path7, fullPath, realPath, parent, watchedDir, item, info, opts) {
4262
4262
  try {
4263
- const stats = await stat(path6);
4263
+ const stats = await stat(path7);
4264
4264
  if (this.fsw.closed)
4265
4265
  return;
4266
4266
  if (sameTypes(info, stats)) {
4267
- this.addOrChange(path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4267
+ this.addOrChange(path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4268
4268
  } else {
4269
- this.handleEvent(EV_UNLINK, path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4269
+ this.handleEvent(EV_UNLINK, path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4270
4270
  }
4271
4271
  } catch (error61) {
4272
4272
  if (error61.code === "EACCES") {
4273
- this.addOrChange(path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4273
+ this.addOrChange(path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4274
4274
  } else {
4275
- this.handleEvent(EV_UNLINK, path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4275
+ this.handleEvent(EV_UNLINK, path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4276
4276
  }
4277
4277
  }
4278
4278
  }
4279
- handleEvent(event, path6, fullPath, realPath, parent, watchedDir, item, info, opts) {
4280
- if (this.fsw.closed || this.checkIgnored(path6))
4279
+ handleEvent(event, path7, fullPath, realPath, parent, watchedDir, item, info, opts) {
4280
+ if (this.fsw.closed || this.checkIgnored(path7))
4281
4281
  return;
4282
4282
  if (event === EV_UNLINK) {
4283
4283
  const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY;
@@ -4287,17 +4287,17 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4287
4287
  } else {
4288
4288
  if (event === EV_ADD) {
4289
4289
  if (info.type === FSEVENT_TYPE_DIRECTORY)
4290
- this.fsw._getWatchedDir(path6);
4290
+ this.fsw._getWatchedDir(path7);
4291
4291
  if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) {
4292
4292
  const curDepth = opts.depth === undefined ? undefined : calcDepth(fullPath, realPath) + 1;
4293
- return this._addToFsEvents(path6, false, true, curDepth);
4293
+ return this._addToFsEvents(path7, false, true, curDepth);
4294
4294
  }
4295
4295
  this.fsw._getWatchedDir(parent).add(item);
4296
4296
  }
4297
4297
  const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event;
4298
- this.fsw._emit(eventName, path6);
4298
+ this.fsw._emit(eventName, path7);
4299
4299
  if (eventName === EV_ADD_DIR)
4300
- this._addToFsEvents(path6, false, true);
4300
+ this._addToFsEvents(path7, false, true);
4301
4301
  }
4302
4302
  }
4303
4303
  _watchWithFsEvents(watchPath, realPath, transform2, globFilter) {
@@ -4309,38 +4309,38 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4309
4309
  return;
4310
4310
  if (opts.depth !== undefined && calcDepth(fullPath, realPath) > opts.depth)
4311
4311
  return;
4312
- const path6 = transform2(sysPath.join(watchPath, sysPath.relative(watchPath, fullPath)));
4313
- if (globFilter && !globFilter(path6))
4312
+ const path7 = transform2(sysPath.join(watchPath, sysPath.relative(watchPath, fullPath)));
4313
+ if (globFilter && !globFilter(path7))
4314
4314
  return;
4315
- const parent = sysPath.dirname(path6);
4316
- const item = sysPath.basename(path6);
4317
- const watchedDir = this.fsw._getWatchedDir(info.type === FSEVENT_TYPE_DIRECTORY ? path6 : parent);
4315
+ const parent = sysPath.dirname(path7);
4316
+ const item = sysPath.basename(path7);
4317
+ const watchedDir = this.fsw._getWatchedDir(info.type === FSEVENT_TYPE_DIRECTORY ? path7 : parent);
4318
4318
  if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) {
4319
4319
  if (typeof opts.ignored === FUNCTION_TYPE) {
4320
4320
  let stats;
4321
4321
  try {
4322
- stats = await stat(path6);
4322
+ stats = await stat(path7);
4323
4323
  } catch (error61) {}
4324
4324
  if (this.fsw.closed)
4325
4325
  return;
4326
- if (this.checkIgnored(path6, stats))
4326
+ if (this.checkIgnored(path7, stats))
4327
4327
  return;
4328
4328
  if (sameTypes(info, stats)) {
4329
- this.addOrChange(path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4329
+ this.addOrChange(path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4330
4330
  } else {
4331
- this.handleEvent(EV_UNLINK, path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4331
+ this.handleEvent(EV_UNLINK, path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4332
4332
  }
4333
4333
  } else {
4334
- this.checkExists(path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4334
+ this.checkExists(path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4335
4335
  }
4336
4336
  } else {
4337
4337
  switch (info.event) {
4338
4338
  case FSEVENT_CREATED:
4339
4339
  case FSEVENT_MODIFIED:
4340
- return this.addOrChange(path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4340
+ return this.addOrChange(path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4341
4341
  case FSEVENT_DELETED:
4342
4342
  case FSEVENT_MOVED:
4343
- return this.checkExists(path6, fullPath, realPath, parent, watchedDir, item, info, opts);
4343
+ return this.checkExists(path7, fullPath, realPath, parent, watchedDir, item, info, opts);
4344
4344
  }
4345
4345
  }
4346
4346
  };
@@ -4361,12 +4361,12 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4361
4361
  return this.fsw._emitReady();
4362
4362
  }
4363
4363
  this.fsw._incrReadyCount();
4364
- this._addToFsEvents(linkTarget || linkPath, (path6) => {
4364
+ this._addToFsEvents(linkTarget || linkPath, (path7) => {
4365
4365
  let aliasedPath = linkPath;
4366
4366
  if (linkTarget && linkTarget !== DOT_SLASH) {
4367
- aliasedPath = path6.replace(linkTarget, linkPath);
4368
- } else if (path6 !== DOT_SLASH) {
4369
- aliasedPath = sysPath.join(linkPath, path6);
4367
+ aliasedPath = path7.replace(linkTarget, linkPath);
4368
+ } else if (path7 !== DOT_SLASH) {
4369
+ aliasedPath = sysPath.join(linkPath, path7);
4370
4370
  }
4371
4371
  return transform2(aliasedPath);
4372
4372
  }, false, curDepth);
@@ -4390,19 +4390,19 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4390
4390
  this.fsw._emit(isDir ? EV_ADD_DIR : EV_ADD, pp, stats);
4391
4391
  }
4392
4392
  }
4393
- initWatch(realPath, path6, wh, processPath) {
4393
+ initWatch(realPath, path7, wh, processPath) {
4394
4394
  if (this.fsw.closed)
4395
4395
  return;
4396
4396
  const closer = this._watchWithFsEvents(wh.watchPath, sysPath.resolve(realPath || wh.watchPath), processPath, wh.globFilter);
4397
- this.fsw._addPathCloser(path6, closer);
4397
+ this.fsw._addPathCloser(path7, closer);
4398
4398
  }
4399
- async _addToFsEvents(path6, transform2, forceAdd, priorDepth) {
4399
+ async _addToFsEvents(path7, transform2, forceAdd, priorDepth) {
4400
4400
  if (this.fsw.closed) {
4401
4401
  return;
4402
4402
  }
4403
4403
  const opts = this.fsw.options;
4404
4404
  const processPath = typeof transform2 === FUNCTION_TYPE ? transform2 : IDENTITY_FN;
4405
- const wh = this.fsw._getWatchHelpers(path6);
4405
+ const wh = this.fsw._getWatchHelpers(path7);
4406
4406
  try {
4407
4407
  const stats = await statMethods[wh.statMethod](wh.watchPath);
4408
4408
  if (this.fsw.closed)
@@ -4412,7 +4412,7 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4412
4412
  }
4413
4413
  if (stats.isDirectory()) {
4414
4414
  if (!wh.globFilter)
4415
- this.emitAdd(processPath(path6), stats, processPath, opts, forceAdd);
4415
+ this.emitAdd(processPath(path7), stats, processPath, opts, forceAdd);
4416
4416
  if (priorDepth && priorDepth > opts.depth)
4417
4417
  return;
4418
4418
  this.fsw._readdirp(wh.watchPath, {
@@ -4448,13 +4448,13 @@ var require_fsevents_handler = __commonJS((exports, module) => {
4448
4448
  }
4449
4449
  if (opts.persistent && forceAdd !== true) {
4450
4450
  if (typeof transform2 === FUNCTION_TYPE) {
4451
- this.initWatch(undefined, path6, wh, processPath);
4451
+ this.initWatch(undefined, path7, wh, processPath);
4452
4452
  } else {
4453
4453
  let realPath;
4454
4454
  try {
4455
4455
  realPath = await realpath(wh.watchPath);
4456
4456
  } catch (e) {}
4457
- this.initWatch(realPath, path6, wh, processPath);
4457
+ this.initWatch(realPath, path7, wh, processPath);
4458
4458
  }
4459
4459
  }
4460
4460
  }
@@ -23067,9 +23067,10 @@ var DEFAULTS = {
23067
23067
  accessToken: "",
23068
23068
  hideFromCapture: true,
23069
23069
  showTranscript: true,
23070
- saveTranscript: false
23070
+ monitorPrompt: "",
23071
+ meetingPrompt: ""
23071
23072
  };
23072
- var OBSOLETE_KEYS = ["sessionMode", "hotkeyPreset"];
23073
+ var OBSOLETE_KEYS = ["sessionMode", "hotkeyPreset", "saveTranscript"];
23073
23074
  var RawConfigSchema = exports_external.record(exports_external.string(), exports_external.unknown());
23074
23075
  var HttpUrlSchema = exports_external.url().refine((value) => {
23075
23076
  const protocol = new URL(value).protocol;
@@ -23153,8 +23154,13 @@ function loadConfig() {
23153
23154
  if (user["showTranscript"] !== undefined) {
23154
23155
  merged.showTranscript = user["showTranscript"] === true;
23155
23156
  }
23156
- if (user["saveTranscript"] !== undefined) {
23157
- merged.saveTranscript = user["saveTranscript"] === true;
23157
+ for (const key of ["monitorPrompt", "meetingPrompt"]) {
23158
+ if (user[key] === undefined)
23159
+ continue;
23160
+ const prompt = exports_external.string().safeParse(user[key]);
23161
+ if (!prompt.success)
23162
+ throw new ConfigFileError(`${key} must be a string`);
23163
+ merged[key] = prompt.data.trim();
23158
23164
  }
23159
23165
  const missing = Object.keys(merged).filter((key) => !(key in persisted));
23160
23166
  if (missing.length > 0 || hadObsolete) {
@@ -23176,9 +23182,9 @@ function getDefaults() {
23176
23182
  // src/electron/app-runtime.ts
23177
23183
  import { app as app3, globalShortcut, shell } from "electron";
23178
23184
  import { randomUUID as randomUUID2 } from "node:crypto";
23179
- import fs8 from "node:fs";
23185
+ import fs9 from "node:fs";
23180
23186
  import os3 from "node:os";
23181
- import path12 from "node:path";
23187
+ import path14 from "node:path";
23182
23188
  import { performance } from "node:perf_hooks";
23183
23189
 
23184
23190
  // src/backends/blink-cloud-client.ts
@@ -24780,14 +24786,17 @@ var ky = createInstance();
24780
24786
  var distribution_default = ky;
24781
24787
 
24782
24788
  // src/core/cloud-protocol.ts
24789
+ var OptionalPrompt = exports_external.preprocess((value) => value === null || value === "" ? undefined : value, exports_external.string().trim().min(1).max(4000).optional());
24783
24790
  var MonitorRequestSchema = exports_external.object({
24784
24791
  kind: exports_external.literal("monitor"),
24785
- image: exports_external.instanceof(File)
24792
+ image: exports_external.instanceof(File),
24793
+ prompt: OptionalPrompt
24786
24794
  });
24787
24795
  var MeetingRequestSchema = exports_external.object({
24788
24796
  kind: exports_external.literal("meeting"),
24789
24797
  text: exports_external.preprocess((value) => value === null ? undefined : value, exports_external.string().trim().min(1).optional()),
24790
- images: exports_external.array(exports_external.instanceof(File)).readonly()
24798
+ images: exports_external.array(exports_external.instanceof(File)).readonly(),
24799
+ prompt: OptionalPrompt
24791
24800
  });
24792
24801
  var CloudAnswerRequestSchema = exports_external.discriminatedUnion("kind", [MonitorRequestSchema, MeetingRequestSchema]).superRefine((request, context) => {
24793
24802
  if (request.kind === "meeting" && request.text === undefined && request.images.length === 0) {
@@ -24876,8 +24885,10 @@ class BlinkCloudResponseError extends Error {
24876
24885
 
24877
24886
  class BlinkCloudClient {
24878
24887
  http;
24888
+ prompts;
24879
24889
  activeRequest = null;
24880
24890
  constructor(options) {
24891
+ this.prompts = options.prompts;
24881
24892
  this.http = distribution_default.create({
24882
24893
  baseUrl: `${options.apiUrl.replace(/\/+$/, "")}/`,
24883
24894
  headers: { Authorization: `Bearer ${options.accessToken}` },
@@ -24890,6 +24901,8 @@ class BlinkCloudClient {
24890
24901
  const form = new FormData;
24891
24902
  form.set("kind", "monitor");
24892
24903
  form.set("image", await imageFile(screenshotPath));
24904
+ if (this.prompts?.monitor)
24905
+ form.set("prompt", this.prompts.monitor);
24893
24906
  await this.ask(form, callbacks);
24894
24907
  }
24895
24908
  async answerMeeting(context, callbacks) {
@@ -24900,6 +24913,8 @@ class BlinkCloudClient {
24900
24913
  for (const screenshotPath of context.screenshotPaths) {
24901
24914
  form.append("image", await imageFile(screenshotPath));
24902
24915
  }
24916
+ if (this.prompts?.meeting)
24917
+ form.set("prompt", this.prompts.meeting);
24903
24918
  await this.ask(form, callbacks);
24904
24919
  }
24905
24920
  async resetMeeting() {
@@ -25092,6 +25107,44 @@ function appendAnswer(record2) {
25092
25107
  `;
25093
25108
  fs3.appendFileSync(logPath, line, "utf-8");
25094
25109
  }
25110
+ function normalizeStoredAnswer(value) {
25111
+ const parsed = StoredAnswerSchema.safeParse(value);
25112
+ if (!parsed.success)
25113
+ return null;
25114
+ const stored = parsed.data;
25115
+ const source = stored.source === "meeting" || stored.source === "transcript" ? "meeting" : "monitor";
25116
+ const screenshotPaths = stored.screenshotPaths ?? (stored.screenshotPath === undefined || stored.screenshotPath.length === 0 ? [] : [stored.screenshotPath]);
25117
+ return {
25118
+ timestamp: stored.timestamp,
25119
+ source,
25120
+ screenshotPaths,
25121
+ answer: stored.answer,
25122
+ durationMs: stored.durationMs
25123
+ };
25124
+ }
25125
+ function readRecent(n) {
25126
+ if (n <= 0)
25127
+ return [];
25128
+ const blinkHome = getBlinkHome2();
25129
+ const logPath = path3.join(blinkHome, "answers.jsonl");
25130
+ if (!fs3.existsSync(logPath)) {
25131
+ return [];
25132
+ }
25133
+ const content = fs3.readFileSync(logPath, "utf-8");
25134
+ const lines = content.split(`
25135
+ `).filter((line) => line.trim().length > 0);
25136
+ const records = [];
25137
+ for (const line of lines) {
25138
+ try {
25139
+ const record2 = normalizeStoredAnswer(JSON.parse(line));
25140
+ if (record2 !== null)
25141
+ records.push(record2);
25142
+ } catch {
25143
+ continue;
25144
+ }
25145
+ }
25146
+ return records.slice(-n);
25147
+ }
25095
25148
 
25096
25149
  // src/core/audio-manager.ts
25097
25150
  import { spawn } from "node:child_process";
@@ -25437,29 +25490,18 @@ async function capture(targetDir, mode) {
25437
25490
 
25438
25491
  // src/core/meeting-context.ts
25439
25492
  class MeetingContextBuffer {
25440
- transcript;
25441
25493
  screenshotPaths = [];
25442
- updateTranscript(transcript) {
25443
- const normalized = transcript.trim();
25444
- this.transcript = normalized.length === 0 ? undefined : normalized;
25445
- }
25446
25494
  stageScreenshot(screenshotPath) {
25447
25495
  if (this.screenshotPaths.includes(screenshotPath))
25448
25496
  return false;
25449
25497
  this.screenshotPaths.push(screenshotPath);
25450
25498
  return true;
25451
25499
  }
25452
- snapshot() {
25453
- return {
25454
- ...this.transcript === undefined ? {} : { transcript: this.transcript },
25455
- screenshotPaths: [...this.screenshotPaths]
25456
- };
25500
+ staged() {
25501
+ return [...this.screenshotPaths];
25457
25502
  }
25458
25503
  summary() {
25459
- return {
25460
- transcriptAvailable: this.transcript !== undefined,
25461
- screenshotCount: this.screenshotPaths.length
25462
- };
25504
+ return { screenshotCount: this.screenshotPaths.length };
25463
25505
  }
25464
25506
  removeScreenshots(submittedPaths) {
25465
25507
  const submitted = new Set(submittedPaths);
@@ -25472,7 +25514,6 @@ class MeetingContextBuffer {
25472
25514
  }
25473
25515
  clear() {
25474
25516
  const screenshotPaths = [...this.screenshotPaths];
25475
- this.transcript = undefined;
25476
25517
  this.screenshotPaths.length = 0;
25477
25518
  return screenshotPaths;
25478
25519
  }
@@ -25728,95 +25769,211 @@ async function resolveScreenshotDir(configOverride, home = homedir3()) {
25728
25769
  return defaultDir;
25729
25770
  }
25730
25771
 
25731
- // src/core/transcript-buffer.ts
25732
- var speakerLabel = {
25733
- them: "Them",
25734
- you: "You"
25735
- };
25772
+ // src/core/transcript-archive.ts
25773
+ import * as fs4 from "node:fs";
25774
+ import * as path5 from "node:path";
25775
+ var SESSION_FILE = /^(\d{4}-\d{2}-\d{2})-(\d{2})(\d{2})(\d{2})(?:-\d+)?\.md$/;
25776
+ var LEGACY_TITLE = `# Blink transcript
25736
25777
 
25737
- class TranscriptBuffer {
25738
- windowMs;
25739
- finalized = [];
25740
- volatile = new Map;
25741
- latestEndMs = 0;
25742
- constructor(windowMs = 120000) {
25743
- this.windowMs = windowMs;
25744
- if (!Number.isFinite(windowMs) || windowMs <= 0) {
25745
- throw new RangeError("transcript window must be a positive number");
25778
+ `;
25779
+ function withoutLegacyTitle(markdown) {
25780
+ return markdown.startsWith(LEGACY_TITLE) ? markdown.slice(LEGACY_TITLE.length) : markdown;
25781
+ }
25782
+ function parseFileName(file2) {
25783
+ const match = SESSION_FILE.exec(file2);
25784
+ if (match === null)
25785
+ return;
25786
+ const [, day, hours, minutes, seconds] = match;
25787
+ return { day, startedAt: `${hours}:${minutes}:${seconds}` };
25788
+ }
25789
+ function countLines(markdown) {
25790
+ let count = 0;
25791
+ for (const line of markdown.split(`
25792
+ `)) {
25793
+ if (line.startsWith("**"))
25794
+ count += 1;
25795
+ }
25796
+ return count;
25797
+ }
25798
+ function countMatches(markdown, query) {
25799
+ if (query === "")
25800
+ return 0;
25801
+ const haystack = markdown.toLowerCase();
25802
+ let count = 0;
25803
+ let index = haystack.indexOf(query);
25804
+ while (index !== -1) {
25805
+ count += 1;
25806
+ index = haystack.indexOf(query, index + query.length);
25807
+ }
25808
+ return count;
25809
+ }
25810
+ function listTranscriptSessions(directory, query = "") {
25811
+ let entries;
25812
+ try {
25813
+ entries = fs4.readdirSync(directory);
25814
+ } catch {
25815
+ return [];
25816
+ }
25817
+ const needle = query.trim().toLowerCase();
25818
+ const sessions = [];
25819
+ for (const file2 of entries) {
25820
+ const parsed = parseFileName(file2);
25821
+ if (parsed === undefined)
25822
+ continue;
25823
+ let markdown;
25824
+ let byteSize;
25825
+ try {
25826
+ const full = path5.join(directory, file2);
25827
+ byteSize = fs4.statSync(full).size;
25828
+ markdown = withoutLegacyTitle(fs4.readFileSync(full, "utf8"));
25829
+ } catch {
25830
+ continue;
25746
25831
  }
25832
+ const matchCount = countMatches(markdown, needle);
25833
+ if (needle !== "" && matchCount === 0)
25834
+ continue;
25835
+ sessions.push({
25836
+ file: file2,
25837
+ day: parsed.day,
25838
+ startedAt: parsed.startedAt,
25839
+ lineCount: countLines(markdown),
25840
+ byteSize,
25841
+ matchCount
25842
+ });
25843
+ }
25844
+ return sessions.sort((left, right) => right.file.localeCompare(left.file));
25845
+ }
25846
+ function readTranscriptSession(directory, file2) {
25847
+ const parsed = parseFileName(file2);
25848
+ if (parsed === undefined)
25849
+ return;
25850
+ try {
25851
+ const full = path5.join(directory, file2);
25852
+ const markdown = withoutLegacyTitle(fs4.readFileSync(full, "utf8"));
25853
+ return {
25854
+ file: file2,
25855
+ day: parsed.day,
25856
+ startedAt: parsed.startedAt,
25857
+ lineCount: countLines(markdown),
25858
+ byteSize: fs4.statSync(full).size,
25859
+ matchCount: 0,
25860
+ markdown
25861
+ };
25862
+ } catch {
25863
+ return;
25747
25864
  }
25865
+ }
25866
+
25867
+ // src/core/transcript-history.ts
25868
+ function lineId(speaker, startMs) {
25869
+ return `${speaker}:${startMs}`;
25870
+ }
25871
+
25872
+ class TranscriptHistory {
25873
+ finalized = new Map;
25874
+ volatile = new Map;
25875
+ pending = new Map;
25748
25876
  get size() {
25749
- return this.finalized.length + this.volatile.size;
25877
+ return this.finalized.size;
25878
+ }
25879
+ volatileLines() {
25880
+ return [...this.volatile.values()].sort((left, right) => left.startMs - right.startMs);
25750
25881
  }
25751
25882
  push(segment) {
25752
- const normalized = this.normalize(segment);
25753
- if (normalized === undefined)
25883
+ const text = segment.text.trim();
25884
+ if (text.length === 0)
25885
+ return;
25886
+ if (!Number.isFinite(segment.startMs) || segment.startMs < 0)
25887
+ return;
25888
+ const id = lineId(segment.speaker, segment.startMs);
25889
+ const line = {
25890
+ id,
25891
+ speaker: segment.speaker,
25892
+ text,
25893
+ startMs: segment.startMs
25894
+ };
25895
+ if (!segment.isFinal) {
25896
+ this.volatile.set(segment.speaker, line);
25754
25897
  return;
25755
- this.latestEndMs = Math.max(this.latestEndMs, normalized.endMs);
25756
- if (normalized.isFinal) {
25757
- this.volatile.delete(normalized.speaker);
25758
- const existingIndex = this.finalized.findIndex((candidate) => candidate.speaker === normalized.speaker && candidate.startMs === normalized.startMs);
25759
- if (existingIndex === -1)
25760
- this.finalized.push(normalized);
25761
- else
25762
- this.finalized[existingIndex] = normalized;
25763
- } else {
25764
- this.volatile.set(normalized.speaker, normalized);
25765
25898
  }
25766
- this.trim(this.latestEndMs);
25767
- }
25768
- formatRecent(referenceMs = this.latestEndMs) {
25769
- return this.recentSegments(referenceMs).map((segment) => `${speakerLabel[segment.speaker]}: ${segment.text}`).join(`
25770
- `);
25771
- }
25772
- recentLines(limit, referenceMs = this.latestEndMs) {
25773
- const segments = this.recentSegments(referenceMs);
25774
- return segments.slice(Math.max(0, segments.length - limit)).map((segment) => ({ speaker: segment.speaker, text: segment.text }));
25899
+ this.volatile.delete(segment.speaker);
25900
+ if (this.finalized.get(id)?.text === text)
25901
+ return;
25902
+ this.finalized.set(id, line);
25903
+ this.pending.set(id, line);
25775
25904
  }
25776
- recentSegments(referenceMs) {
25777
- this.prune(referenceMs);
25778
- const cutoff = Math.max(0, referenceMs - this.windowMs);
25779
- return this.segments().filter((segment) => segment.endMs >= cutoff && segment.startMs <= referenceMs).sort((left, right) => left.startMs - right.startMs || left.endMs - right.endMs);
25905
+ drain() {
25906
+ const changed = [...this.pending.values()].sort((left, right) => left.startMs - right.startMs);
25907
+ this.pending.clear();
25908
+ return { changed, volatile: [...this.volatile.values()] };
25780
25909
  }
25781
- prune(referenceMs) {
25782
- if (!Number.isFinite(referenceMs) || referenceMs < 0)
25783
- return;
25784
- this.latestEndMs = Math.max(this.latestEndMs, referenceMs);
25785
- this.trim(referenceMs);
25910
+ lines() {
25911
+ return [...this.finalized.values()].sort((left, right) => left.startMs - right.startMs);
25786
25912
  }
25787
25913
  clear() {
25788
- this.finalized.length = 0;
25914
+ this.finalized.clear();
25789
25915
  this.volatile.clear();
25790
- this.latestEndMs = 0;
25916
+ this.pending.clear();
25791
25917
  }
25792
- segments() {
25793
- return [...this.finalized, ...this.volatile.values()];
25918
+ }
25919
+
25920
+ // src/core/meeting-transcript.ts
25921
+ var speakerLabel = {
25922
+ them: "Them",
25923
+ you: "You"
25924
+ };
25925
+ var EMPTY_CHUNK = "No new speech since the last ask.";
25926
+ function pad2(value) {
25927
+ return String(value).padStart(2, "0");
25928
+ }
25929
+ function offset(startMs) {
25930
+ const total = Math.max(0, Math.floor(startMs / 1000));
25931
+ const hours = Math.floor(total / 3600);
25932
+ const minutes = Math.floor(total % 3600 / 60);
25933
+ const seconds = total % 60;
25934
+ return hours > 0 ? `${hours}:${pad2(minutes)}:${pad2(seconds)}` : `${pad2(minutes)}:${pad2(seconds)}`;
25935
+ }
25936
+
25937
+ class MeetingTranscriptCursor {
25938
+ submitted = new Set;
25939
+ get submittedCount() {
25940
+ return this.submitted.size;
25941
+ }
25942
+ chunk(lines, volatile = []) {
25943
+ const pending = lines.filter((line) => !this.submitted.has(line.id));
25944
+ if (pending.length === 0 && volatile.length === 0) {
25945
+ return { text: EMPTY_CHUNK, lineIds: [], hasNewSpeech: false };
25946
+ }
25947
+ const continues = this.submitted.size > 0;
25948
+ const spoken = [
25949
+ ...pending.map((line) => `${speakerLabel[line.speaker]} (${offset(line.startMs)}): ${line.text}`),
25950
+ ...volatile.map((line) => `${speakerLabel[line.speaker]} (${offset(line.startMs)}, in progress): ${line.text}`)
25951
+ ];
25952
+ const first = pending[0] ?? volatile[0];
25953
+ const last = volatile[volatile.length - 1] ?? pending[pending.length - 1];
25954
+ const span = first === undefined || last === undefined ? "" : ` ${offset(first.startMs)}-${offset(last.startMs)}`;
25955
+ const heading = continues ? `Transcript${span} (new since the last ask)` : `Transcript${span}`;
25956
+ return {
25957
+ text: `${heading}
25958
+
25959
+ ${spoken.join(`
25960
+ `)}`,
25961
+ lineIds: pending.map((line) => line.id),
25962
+ hasNewSpeech: true
25963
+ };
25794
25964
  }
25795
- trim(referenceMs) {
25796
- const cutoff = Math.max(0, referenceMs - this.windowMs);
25797
- for (let index = this.finalized.length - 1;index >= 0; index -= 1) {
25798
- if (this.finalized[index].endMs < cutoff)
25799
- this.finalized.splice(index, 1);
25800
- }
25801
- for (const [speaker, segment] of this.volatile) {
25802
- if (segment.endMs < cutoff)
25803
- this.volatile.delete(speaker);
25804
- }
25965
+ markSubmitted(lineIds) {
25966
+ for (const id of lineIds)
25967
+ this.submitted.add(id);
25805
25968
  }
25806
- normalize(segment) {
25807
- const text = segment.text.trim();
25808
- if (text.length === 0)
25809
- return;
25810
- if (!Number.isFinite(segment.startMs) || !Number.isFinite(segment.endMs) || segment.startMs < 0 || segment.endMs < segment.startMs) {
25811
- return;
25812
- }
25813
- return { ...segment, text };
25969
+ reset() {
25970
+ this.submitted.clear();
25814
25971
  }
25815
25972
  }
25816
25973
 
25817
25974
  // src/core/transcript-log.ts
25818
- import * as fs4 from "node:fs";
25819
- import * as path5 from "node:path";
25975
+ import * as fs5 from "node:fs";
25976
+ import * as path6 from "node:path";
25820
25977
  var speakerLabel2 = {
25821
25978
  them: "Them",
25822
25979
  you: "You"
@@ -25845,49 +26002,47 @@ class TranscriptLog {
25845
26002
  return;
25846
26003
  this.written.add(key);
25847
26004
  this.ensureHeader();
25848
- const line = `**${speakerLabel2[entry.speaker]}** (${offset(entry.startMs)}) ${text}
26005
+ const line = `**${speakerLabel2[entry.speaker]}** (${offset2(entry.startMs)}) ${text}
25849
26006
 
25850
26007
  `;
25851
- fs4.appendFileSync(this.filePath, line, "utf8");
26008
+ fs5.appendFileSync(this.filePath, line, "utf8");
25852
26009
  }
25853
26010
  ensureHeader() {
25854
26011
  if (this.headerWritten)
25855
26012
  return;
25856
26013
  this.headerWritten = true;
25857
- fs4.mkdirSync(path5.dirname(this.filePath), { recursive: true });
25858
- const header = `# Blink transcript
25859
-
25860
- Started ${readableStamp(this.startedAt)}
26014
+ fs5.mkdirSync(path6.dirname(this.filePath), { recursive: true });
26015
+ const header = `Started ${readableStamp(this.startedAt)}
25861
26016
 
25862
26017
  `;
25863
- fs4.appendFileSync(this.filePath, header, "utf8");
26018
+ fs5.appendFileSync(this.filePath, header, "utf8");
25864
26019
  }
25865
26020
  }
25866
- function pad2(value, width = 2) {
26021
+ function pad3(value, width = 2) {
25867
26022
  return String(value).padStart(width, "0");
25868
26023
  }
25869
- function offset(startMs) {
26024
+ function offset2(startMs) {
25870
26025
  const totalSeconds = Math.max(0, Math.floor(startMs / 1000));
25871
- return `${pad2(Math.floor(totalSeconds / 60))}:${pad2(totalSeconds % 60)}`;
26026
+ return `${pad3(Math.floor(totalSeconds / 60))}:${pad3(totalSeconds % 60)}`;
25872
26027
  }
25873
26028
  function fileStamp(date5) {
25874
26029
  return [
25875
- `${date5.getFullYear()}-${pad2(date5.getMonth() + 1)}-${pad2(date5.getDate())}`,
25876
- `${pad2(date5.getHours())}${pad2(date5.getMinutes())}${pad2(date5.getSeconds())}`
26030
+ `${date5.getFullYear()}-${pad3(date5.getMonth() + 1)}-${pad3(date5.getDate())}`,
26031
+ `${pad3(date5.getHours())}${pad3(date5.getMinutes())}${pad3(date5.getSeconds())}`
25877
26032
  ].join("-");
25878
26033
  }
25879
26034
  function readableStamp(date5) {
25880
- const day = `${date5.getFullYear()}-${pad2(date5.getMonth() + 1)}-${pad2(date5.getDate())}`;
25881
- const time3 = `${pad2(date5.getHours())}:${pad2(date5.getMinutes())}:${pad2(date5.getSeconds())}`;
26035
+ const day = `${date5.getFullYear()}-${pad3(date5.getMonth() + 1)}-${pad3(date5.getDate())}`;
26036
+ const time3 = `${pad3(date5.getHours())}:${pad3(date5.getMinutes())}:${pad3(date5.getSeconds())}`;
25882
26037
  return `${day} ${time3}`;
25883
26038
  }
25884
26039
  function availablePath(directory, stamp) {
25885
- const candidate = path5.join(directory, `${stamp}.md`);
25886
- if (!fs4.existsSync(candidate))
26040
+ const candidate = path6.join(directory, `${stamp}.md`);
26041
+ if (!fs5.existsSync(candidate))
25887
26042
  return candidate;
25888
26043
  for (let suffix = 2;; suffix += 1) {
25889
- const next = path5.join(directory, `${stamp}-${suffix}.md`);
25890
- if (!fs4.existsSync(next))
26044
+ const next = path6.join(directory, `${stamp}-${suffix}.md`);
26045
+ if (!fs5.existsSync(next))
25891
26046
  return next;
25892
26047
  }
25893
26048
  }
@@ -25900,12 +26055,12 @@ var CAPTURE_ACCELERATORS = {
25900
26055
 
25901
26056
  // src/core/watcher.ts
25902
26057
  import { EventEmitter as EventEmitter3 } from "node:events";
25903
- import * as fs6 from "node:fs";
25904
- import * as path6 from "node:path";
26058
+ import * as fs7 from "node:fs";
26059
+ import * as path7 from "node:path";
25905
26060
 
25906
26061
  // node_modules/chokidar/index.js
25907
26062
  var { EventEmitter: EventEmitter2 } = __require("events");
25908
- var fs5 = __require("fs");
26063
+ var fs6 = __require("fs");
25909
26064
  var sysPath = __require("path");
25910
26065
  var { promisify } = __require("util");
25911
26066
  var readdirp = require_readdirp();
@@ -25950,8 +26105,8 @@ var {
25950
26105
  isMacos,
25951
26106
  isIBMi
25952
26107
  } = require_constants3();
25953
- var stat = promisify(fs5.stat);
25954
- var readdir = promisify(fs5.readdir);
26108
+ var stat = promisify(fs6.stat);
26109
+ var readdir = promisify(fs6.readdir);
25955
26110
  var arrify = (value = []) => Array.isArray(value) ? value : [value];
25956
26111
  var flatten = (list, result = []) => {
25957
26112
  list.forEach((item) => {
@@ -25984,20 +26139,20 @@ var toUnix = (string4) => {
25984
26139
  }
25985
26140
  return str;
25986
26141
  };
25987
- var normalizePathToUnix = (path6) => toUnix(sysPath.normalize(toUnix(path6)));
25988
- var normalizeIgnored = (cwd = EMPTY_STR) => (path6) => {
25989
- if (typeof path6 !== STRING_TYPE)
25990
- return path6;
25991
- return normalizePathToUnix(sysPath.isAbsolute(path6) ? path6 : sysPath.join(cwd, path6));
26142
+ var normalizePathToUnix = (path7) => toUnix(sysPath.normalize(toUnix(path7)));
26143
+ var normalizeIgnored = (cwd = EMPTY_STR) => (path7) => {
26144
+ if (typeof path7 !== STRING_TYPE)
26145
+ return path7;
26146
+ return normalizePathToUnix(sysPath.isAbsolute(path7) ? path7 : sysPath.join(cwd, path7));
25992
26147
  };
25993
- var getAbsolutePath = (path6, cwd) => {
25994
- if (sysPath.isAbsolute(path6)) {
25995
- return path6;
26148
+ var getAbsolutePath = (path7, cwd) => {
26149
+ if (sysPath.isAbsolute(path7)) {
26150
+ return path7;
25996
26151
  }
25997
- if (path6.startsWith(BANG)) {
25998
- return BANG + sysPath.join(cwd, path6.slice(1));
26152
+ if (path7.startsWith(BANG)) {
26153
+ return BANG + sysPath.join(cwd, path7.slice(1));
25999
26154
  }
26000
- return sysPath.join(cwd, path6);
26155
+ return sysPath.join(cwd, path7);
26001
26156
  };
26002
26157
  var undef = (opts, key) => opts[key] === undefined;
26003
26158
 
@@ -26054,17 +26209,17 @@ var STAT_METHOD_F = "stat";
26054
26209
  var STAT_METHOD_L = "lstat";
26055
26210
 
26056
26211
  class WatchHelper {
26057
- constructor(path6, watchPath, follow, fsw) {
26212
+ constructor(path7, watchPath, follow, fsw) {
26058
26213
  this.fsw = fsw;
26059
- this.path = path6 = path6.replace(REPLACER_RE, EMPTY_STR);
26214
+ this.path = path7 = path7.replace(REPLACER_RE, EMPTY_STR);
26060
26215
  this.watchPath = watchPath;
26061
26216
  this.fullWatchPath = sysPath.resolve(watchPath);
26062
- this.hasGlob = watchPath !== path6;
26063
- if (path6 === EMPTY_STR)
26217
+ this.hasGlob = watchPath !== path7;
26218
+ if (path7 === EMPTY_STR)
26064
26219
  this.hasGlob = false;
26065
26220
  this.globSymlink = this.hasGlob && follow ? undefined : false;
26066
- this.globFilter = this.hasGlob ? anymatch(path6, undefined, ANYMATCH_OPTS) : false;
26067
- this.dirParts = this.getDirParts(path6);
26221
+ this.globFilter = this.hasGlob ? anymatch(path7, undefined, ANYMATCH_OPTS) : false;
26222
+ this.dirParts = this.getDirParts(path7);
26068
26223
  this.dirParts.forEach((parts) => {
26069
26224
  if (parts.length > 1)
26070
26225
  parts.pop();
@@ -26092,13 +26247,13 @@ class WatchHelper {
26092
26247
  const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ? this.globFilter(resolvedPath) : true;
26093
26248
  return matchesGlob && this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
26094
26249
  }
26095
- getDirParts(path6) {
26250
+ getDirParts(path7) {
26096
26251
  if (!this.hasGlob)
26097
26252
  return [];
26098
26253
  const parts = [];
26099
- const expandedPath = path6.includes(BRACE_START) ? braces.expand(path6) : [path6];
26100
- expandedPath.forEach((path7) => {
26101
- parts.push(sysPath.relative(this.watchPath, path7).split(SLASH_OR_BACK_SLASH_RE));
26254
+ const expandedPath = path7.includes(BRACE_START) ? braces.expand(path7) : [path7];
26255
+ expandedPath.forEach((path8) => {
26256
+ parts.push(sysPath.relative(this.watchPath, path8).split(SLASH_OR_BACK_SLASH_RE));
26102
26257
  });
26103
26258
  return parts;
26104
26259
  }
@@ -26214,21 +26369,21 @@ class FSWatcher extends EventEmitter2 {
26214
26369
  this.closed = false;
26215
26370
  let paths = unifyPaths(paths_);
26216
26371
  if (cwd) {
26217
- paths = paths.map((path6) => {
26218
- const absPath = getAbsolutePath(path6, cwd);
26219
- if (disableGlobbing || !isGlob(path6)) {
26372
+ paths = paths.map((path7) => {
26373
+ const absPath = getAbsolutePath(path7, cwd);
26374
+ if (disableGlobbing || !isGlob(path7)) {
26220
26375
  return absPath;
26221
26376
  }
26222
26377
  return normalizePath(absPath);
26223
26378
  });
26224
26379
  }
26225
- paths = paths.filter((path6) => {
26226
- if (path6.startsWith(BANG)) {
26227
- this._ignoredPaths.add(path6.slice(1));
26380
+ paths = paths.filter((path7) => {
26381
+ if (path7.startsWith(BANG)) {
26382
+ this._ignoredPaths.add(path7.slice(1));
26228
26383
  return false;
26229
26384
  }
26230
- this._ignoredPaths.delete(path6);
26231
- this._ignoredPaths.delete(path6 + SLASH_GLOBSTAR);
26385
+ this._ignoredPaths.delete(path7);
26386
+ this._ignoredPaths.delete(path7 + SLASH_GLOBSTAR);
26232
26387
  this._userIgnored = undefined;
26233
26388
  return true;
26234
26389
  });
@@ -26237,13 +26392,13 @@ class FSWatcher extends EventEmitter2 {
26237
26392
  this._readyCount = paths.length;
26238
26393
  if (this.options.persistent)
26239
26394
  this._readyCount += paths.length;
26240
- paths.forEach((path6) => this._fsEventsHandler._addToFsEvents(path6));
26395
+ paths.forEach((path7) => this._fsEventsHandler._addToFsEvents(path7));
26241
26396
  } else {
26242
26397
  if (!this._readyCount)
26243
26398
  this._readyCount = 0;
26244
26399
  this._readyCount += paths.length;
26245
- Promise.all(paths.map(async (path6) => {
26246
- const res = await this._nodeFsHandler._addToNodeFs(path6, !_internal, 0, 0, _origAdd);
26400
+ Promise.all(paths.map(async (path7) => {
26401
+ const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, 0, 0, _origAdd);
26247
26402
  if (res)
26248
26403
  this._emitReady();
26249
26404
  return res;
@@ -26262,16 +26417,16 @@ class FSWatcher extends EventEmitter2 {
26262
26417
  return this;
26263
26418
  const paths = unifyPaths(paths_);
26264
26419
  const { cwd } = this.options;
26265
- paths.forEach((path6) => {
26266
- if (!sysPath.isAbsolute(path6) && !this._closers.has(path6)) {
26420
+ paths.forEach((path7) => {
26421
+ if (!sysPath.isAbsolute(path7) && !this._closers.has(path7)) {
26267
26422
  if (cwd)
26268
- path6 = sysPath.join(cwd, path6);
26269
- path6 = sysPath.resolve(path6);
26423
+ path7 = sysPath.join(cwd, path7);
26424
+ path7 = sysPath.resolve(path7);
26270
26425
  }
26271
- this._closePath(path6);
26272
- this._ignoredPaths.add(path6);
26273
- if (this._watched.has(path6)) {
26274
- this._ignoredPaths.add(path6 + SLASH_GLOBSTAR);
26426
+ this._closePath(path7);
26427
+ this._ignoredPaths.add(path7);
26428
+ if (this._watched.has(path7)) {
26429
+ this._ignoredPaths.add(path7 + SLASH_GLOBSTAR);
26275
26430
  }
26276
26431
  this._userIgnored = undefined;
26277
26432
  });
@@ -26314,15 +26469,15 @@ class FSWatcher extends EventEmitter2 {
26314
26469
  if (event !== EV_ERROR)
26315
26470
  this.emit(EV_ALL, ...args);
26316
26471
  }
26317
- async _emit(event, path6, val1, val2, val3) {
26472
+ async _emit(event, path7, val1, val2, val3) {
26318
26473
  if (this.closed)
26319
26474
  return;
26320
26475
  const opts = this.options;
26321
26476
  if (isWindows)
26322
- path6 = sysPath.normalize(path6);
26477
+ path7 = sysPath.normalize(path7);
26323
26478
  if (opts.cwd)
26324
- path6 = sysPath.relative(opts.cwd, path6);
26325
- const args = [event, path6];
26479
+ path7 = sysPath.relative(opts.cwd, path7);
26480
+ const args = [event, path7];
26326
26481
  if (val3 !== undefined)
26327
26482
  args.push(val1, val2, val3);
26328
26483
  else if (val2 !== undefined)
@@ -26331,25 +26486,25 @@ class FSWatcher extends EventEmitter2 {
26331
26486
  args.push(val1);
26332
26487
  const awf = opts.awaitWriteFinish;
26333
26488
  let pw;
26334
- if (awf && (pw = this._pendingWrites.get(path6))) {
26489
+ if (awf && (pw = this._pendingWrites.get(path7))) {
26335
26490
  pw.lastChange = new Date;
26336
26491
  return this;
26337
26492
  }
26338
26493
  if (opts.atomic) {
26339
26494
  if (event === EV_UNLINK) {
26340
- this._pendingUnlinks.set(path6, args);
26495
+ this._pendingUnlinks.set(path7, args);
26341
26496
  setTimeout(() => {
26342
- this._pendingUnlinks.forEach((entry, path7) => {
26497
+ this._pendingUnlinks.forEach((entry, path8) => {
26343
26498
  this.emit(...entry);
26344
26499
  this.emit(EV_ALL, ...entry);
26345
- this._pendingUnlinks.delete(path7);
26500
+ this._pendingUnlinks.delete(path8);
26346
26501
  });
26347
26502
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
26348
26503
  return this;
26349
26504
  }
26350
- if (event === EV_ADD && this._pendingUnlinks.has(path6)) {
26505
+ if (event === EV_ADD && this._pendingUnlinks.has(path7)) {
26351
26506
  event = args[0] = EV_CHANGE;
26352
- this._pendingUnlinks.delete(path6);
26507
+ this._pendingUnlinks.delete(path7);
26353
26508
  }
26354
26509
  }
26355
26510
  if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) {
@@ -26367,16 +26522,16 @@ class FSWatcher extends EventEmitter2 {
26367
26522
  this.emitWithAll(event, args);
26368
26523
  }
26369
26524
  };
26370
- this._awaitWriteFinish(path6, awf.stabilityThreshold, event, awfEmit);
26525
+ this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
26371
26526
  return this;
26372
26527
  }
26373
26528
  if (event === EV_CHANGE) {
26374
- const isThrottled = !this._throttle(EV_CHANGE, path6, 50);
26529
+ const isThrottled = !this._throttle(EV_CHANGE, path7, 50);
26375
26530
  if (isThrottled)
26376
26531
  return this;
26377
26532
  }
26378
26533
  if (opts.alwaysStat && val1 === undefined && (event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE)) {
26379
- const fullPath = opts.cwd ? sysPath.join(opts.cwd, path6) : path6;
26534
+ const fullPath = opts.cwd ? sysPath.join(opts.cwd, path7) : path7;
26380
26535
  let stats;
26381
26536
  try {
26382
26537
  stats = await stat(fullPath);
@@ -26395,21 +26550,21 @@ class FSWatcher extends EventEmitter2 {
26395
26550
  }
26396
26551
  return error61 || this.closed;
26397
26552
  }
26398
- _throttle(actionType, path6, timeout2) {
26553
+ _throttle(actionType, path7, timeout2) {
26399
26554
  if (!this._throttled.has(actionType)) {
26400
26555
  this._throttled.set(actionType, new Map);
26401
26556
  }
26402
26557
  const action = this._throttled.get(actionType);
26403
- const actionPath = action.get(path6);
26558
+ const actionPath = action.get(path7);
26404
26559
  if (actionPath) {
26405
26560
  actionPath.count++;
26406
26561
  return false;
26407
26562
  }
26408
26563
  let timeoutObject;
26409
26564
  const clear = () => {
26410
- const item = action.get(path6);
26565
+ const item = action.get(path7);
26411
26566
  const count = item ? item.count : 0;
26412
- action.delete(path6);
26567
+ action.delete(path7);
26413
26568
  clearTimeout(timeoutObject);
26414
26569
  if (item)
26415
26570
  clearTimeout(item.timeoutObject);
@@ -26417,45 +26572,45 @@ class FSWatcher extends EventEmitter2 {
26417
26572
  };
26418
26573
  timeoutObject = setTimeout(clear, timeout2);
26419
26574
  const thr = { timeoutObject, clear, count: 0 };
26420
- action.set(path6, thr);
26575
+ action.set(path7, thr);
26421
26576
  return thr;
26422
26577
  }
26423
26578
  _incrReadyCount() {
26424
26579
  return this._readyCount++;
26425
26580
  }
26426
- _awaitWriteFinish(path6, threshold, event, awfEmit) {
26581
+ _awaitWriteFinish(path7, threshold, event, awfEmit) {
26427
26582
  let timeoutHandler;
26428
- let fullPath = path6;
26429
- if (this.options.cwd && !sysPath.isAbsolute(path6)) {
26430
- fullPath = sysPath.join(this.options.cwd, path6);
26583
+ let fullPath = path7;
26584
+ if (this.options.cwd && !sysPath.isAbsolute(path7)) {
26585
+ fullPath = sysPath.join(this.options.cwd, path7);
26431
26586
  }
26432
26587
  const now = new Date;
26433
26588
  const awaitWriteFinish = (prevStat) => {
26434
- fs5.stat(fullPath, (err, curStat) => {
26435
- if (err || !this._pendingWrites.has(path6)) {
26589
+ fs6.stat(fullPath, (err, curStat) => {
26590
+ if (err || !this._pendingWrites.has(path7)) {
26436
26591
  if (err && err.code !== "ENOENT")
26437
26592
  awfEmit(err);
26438
26593
  return;
26439
26594
  }
26440
26595
  const now2 = Number(new Date);
26441
26596
  if (prevStat && curStat.size !== prevStat.size) {
26442
- this._pendingWrites.get(path6).lastChange = now2;
26597
+ this._pendingWrites.get(path7).lastChange = now2;
26443
26598
  }
26444
- const pw = this._pendingWrites.get(path6);
26599
+ const pw = this._pendingWrites.get(path7);
26445
26600
  const df = now2 - pw.lastChange;
26446
26601
  if (df >= threshold) {
26447
- this._pendingWrites.delete(path6);
26602
+ this._pendingWrites.delete(path7);
26448
26603
  awfEmit(undefined, curStat);
26449
26604
  } else {
26450
26605
  timeoutHandler = setTimeout(awaitWriteFinish, this.options.awaitWriteFinish.pollInterval, curStat);
26451
26606
  }
26452
26607
  });
26453
26608
  };
26454
- if (!this._pendingWrites.has(path6)) {
26455
- this._pendingWrites.set(path6, {
26609
+ if (!this._pendingWrites.has(path7)) {
26610
+ this._pendingWrites.set(path7, {
26456
26611
  lastChange: now,
26457
26612
  cancelWait: () => {
26458
- this._pendingWrites.delete(path6);
26613
+ this._pendingWrites.delete(path7);
26459
26614
  clearTimeout(timeoutHandler);
26460
26615
  return event;
26461
26616
  }
@@ -26466,26 +26621,26 @@ class FSWatcher extends EventEmitter2 {
26466
26621
  _getGlobIgnored() {
26467
26622
  return [...this._ignoredPaths.values()];
26468
26623
  }
26469
- _isIgnored(path6, stats) {
26470
- if (this.options.atomic && DOT_RE.test(path6))
26624
+ _isIgnored(path7, stats) {
26625
+ if (this.options.atomic && DOT_RE.test(path7))
26471
26626
  return true;
26472
26627
  if (!this._userIgnored) {
26473
26628
  const { cwd } = this.options;
26474
26629
  const ign = this.options.ignored;
26475
26630
  const ignored = ign && ign.map(normalizeIgnored(cwd));
26476
- const paths = arrify(ignored).filter((path7) => typeof path7 === STRING_TYPE && !isGlob(path7)).map((path7) => path7 + SLASH_GLOBSTAR);
26631
+ const paths = arrify(ignored).filter((path8) => typeof path8 === STRING_TYPE && !isGlob(path8)).map((path8) => path8 + SLASH_GLOBSTAR);
26477
26632
  const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths);
26478
26633
  this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS);
26479
26634
  }
26480
- return this._userIgnored([path6, stats]);
26635
+ return this._userIgnored([path7, stats]);
26481
26636
  }
26482
- _isntIgnored(path6, stat2) {
26483
- return !this._isIgnored(path6, stat2);
26637
+ _isntIgnored(path7, stat2) {
26638
+ return !this._isIgnored(path7, stat2);
26484
26639
  }
26485
- _getWatchHelpers(path6, depth) {
26486
- const watchPath = depth || this.options.disableGlobbing || !isGlob(path6) ? path6 : globParent(path6);
26640
+ _getWatchHelpers(path7, depth) {
26641
+ const watchPath = depth || this.options.disableGlobbing || !isGlob(path7) ? path7 : globParent(path7);
26487
26642
  const follow = this.options.followSymlinks;
26488
- return new WatchHelper(path6, watchPath, follow, this);
26643
+ return new WatchHelper(path7, watchPath, follow, this);
26489
26644
  }
26490
26645
  _getWatchedDir(directory) {
26491
26646
  if (!this._boundRemove)
@@ -26504,59 +26659,59 @@ class FSWatcher extends EventEmitter2 {
26504
26659
  return Boolean(4 & it);
26505
26660
  }
26506
26661
  _remove(directory, item, isDirectory) {
26507
- const path6 = sysPath.join(directory, item);
26508
- const fullPath = sysPath.resolve(path6);
26509
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path6) || this._watched.has(fullPath);
26510
- if (!this._throttle("remove", path6, 100))
26662
+ const path7 = sysPath.join(directory, item);
26663
+ const fullPath = sysPath.resolve(path7);
26664
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
26665
+ if (!this._throttle("remove", path7, 100))
26511
26666
  return;
26512
26667
  if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
26513
26668
  this.add(directory, item, true);
26514
26669
  }
26515
- const wp = this._getWatchedDir(path6);
26670
+ const wp = this._getWatchedDir(path7);
26516
26671
  const nestedDirectoryChildren = wp.getChildren();
26517
- nestedDirectoryChildren.forEach((nested) => this._remove(path6, nested));
26672
+ nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
26518
26673
  const parent = this._getWatchedDir(directory);
26519
26674
  const wasTracked = parent.has(item);
26520
26675
  parent.remove(item);
26521
26676
  if (this._symlinkPaths.has(fullPath)) {
26522
26677
  this._symlinkPaths.delete(fullPath);
26523
26678
  }
26524
- let relPath = path6;
26679
+ let relPath = path7;
26525
26680
  if (this.options.cwd)
26526
- relPath = sysPath.relative(this.options.cwd, path6);
26681
+ relPath = sysPath.relative(this.options.cwd, path7);
26527
26682
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
26528
26683
  const event = this._pendingWrites.get(relPath).cancelWait();
26529
26684
  if (event === EV_ADD)
26530
26685
  return;
26531
26686
  }
26532
- this._watched.delete(path6);
26687
+ this._watched.delete(path7);
26533
26688
  this._watched.delete(fullPath);
26534
26689
  const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK;
26535
- if (wasTracked && !this._isIgnored(path6))
26536
- this._emit(eventName, path6);
26690
+ if (wasTracked && !this._isIgnored(path7))
26691
+ this._emit(eventName, path7);
26537
26692
  if (!this.options.useFsEvents) {
26538
- this._closePath(path6);
26693
+ this._closePath(path7);
26539
26694
  }
26540
26695
  }
26541
- _closePath(path6) {
26542
- this._closeFile(path6);
26543
- const dir = sysPath.dirname(path6);
26544
- this._getWatchedDir(dir).remove(sysPath.basename(path6));
26696
+ _closePath(path7) {
26697
+ this._closeFile(path7);
26698
+ const dir = sysPath.dirname(path7);
26699
+ this._getWatchedDir(dir).remove(sysPath.basename(path7));
26545
26700
  }
26546
- _closeFile(path6) {
26547
- const closers = this._closers.get(path6);
26701
+ _closeFile(path7) {
26702
+ const closers = this._closers.get(path7);
26548
26703
  if (!closers)
26549
26704
  return;
26550
26705
  closers.forEach((closer) => closer());
26551
- this._closers.delete(path6);
26706
+ this._closers.delete(path7);
26552
26707
  }
26553
- _addPathCloser(path6, closer) {
26708
+ _addPathCloser(path7, closer) {
26554
26709
  if (!closer)
26555
26710
  return;
26556
- let list = this._closers.get(path6);
26711
+ let list = this._closers.get(path7);
26557
26712
  if (!list) {
26558
26713
  list = [];
26559
- this._closers.set(path6, list);
26714
+ this._closers.set(path7, list);
26560
26715
  }
26561
26716
  list.push(closer);
26562
26717
  }
@@ -26633,14 +26788,14 @@ class ScreenshotWatcher extends EventEmitter3 {
26633
26788
  return () => this.off("screenshot", listener);
26634
26789
  }
26635
26790
  async handleAdd(filePath) {
26636
- const base = path6.basename(filePath);
26791
+ const base = path7.basename(filePath);
26637
26792
  if (base.startsWith("."))
26638
26793
  return;
26639
26794
  if (!base.toLowerCase().endsWith(".png"))
26640
26795
  return;
26641
26796
  let stat2;
26642
26797
  try {
26643
- stat2 = await fs6.promises.stat(filePath);
26798
+ stat2 = await fs7.promises.stat(filePath);
26644
26799
  } catch {
26645
26800
  return;
26646
26801
  }
@@ -26669,12 +26824,31 @@ class ScreenshotWatcher extends EventEmitter3 {
26669
26824
  }
26670
26825
 
26671
26826
  // src/electron/app-state.ts
26827
+ var ERROR_VISIBLE_MS = 9000;
26828
+
26672
26829
  class AppStateStore {
26830
+ errorVisibleMs;
26673
26831
  state;
26674
26832
  listeners = new Set;
26675
- constructor(initial) {
26833
+ errorTimer = null;
26834
+ constructor(initial, errorVisibleMs = ERROR_VISIBLE_MS) {
26835
+ this.errorVisibleMs = errorVisibleMs;
26676
26836
  this.state = { ...initial };
26677
26837
  }
26838
+ scheduleErrorClear() {
26839
+ if (this.errorTimer !== null)
26840
+ clearTimeout(this.errorTimer);
26841
+ this.errorTimer = null;
26842
+ if (this.state.lastError === undefined || this.errorVisibleMs <= 0)
26843
+ return;
26844
+ const timer = setTimeout(() => {
26845
+ this.errorTimer = null;
26846
+ if (this.state.lastError !== undefined)
26847
+ this.update({ lastError: null });
26848
+ }, this.errorVisibleMs);
26849
+ timer.unref?.();
26850
+ this.errorTimer = timer;
26851
+ }
26678
26852
  get() {
26679
26853
  return { ...this.state };
26680
26854
  }
@@ -26685,10 +26859,8 @@ class AppStateStore {
26685
26859
  meeting: this.state.meeting,
26686
26860
  meetingStarting: this.state.meetingStarting,
26687
26861
  meetingAsking: this.state.meetingAsking,
26688
- meetingTranscriptAvailable: this.state.meetingTranscriptAvailable,
26689
26862
  meetingScreenshotCount: this.state.meetingScreenshotCount,
26690
26863
  showTranscript: this.state.showTranscript,
26691
- saveTranscript: this.state.saveTranscript,
26692
26864
  processing: this.state.processing,
26693
26865
  queued: this.state.queued,
26694
26866
  inFlight: this.state.inFlight,
@@ -26706,9 +26878,6 @@ class AppStateStore {
26706
26878
  if (patch.meetingAsking !== undefined) {
26707
26879
  next.meetingAsking = patch.meetingAsking;
26708
26880
  }
26709
- if (patch.meetingTranscriptAvailable !== undefined) {
26710
- next.meetingTranscriptAvailable = patch.meetingTranscriptAvailable;
26711
- }
26712
26881
  if (patch.meetingScreenshotCount !== undefined) {
26713
26882
  next.meetingScreenshotCount = patch.meetingScreenshotCount;
26714
26883
  }
@@ -26720,8 +26889,11 @@ class AppStateStore {
26720
26889
  if (patch.showTranscript !== undefined) {
26721
26890
  next.showTranscript = patch.showTranscript;
26722
26891
  }
26723
- if (patch.saveTranscript !== undefined) {
26724
- next.saveTranscript = patch.saveTranscript;
26892
+ if (patch.meetingStartedAt !== undefined) {
26893
+ if (patch.meetingStartedAt === null)
26894
+ delete next.meetingStartedAt;
26895
+ else
26896
+ next.meetingStartedAt = patch.meetingStartedAt;
26725
26897
  }
26726
26898
  if (patch.processing !== undefined)
26727
26899
  next.processing = patch.processing;
@@ -26744,7 +26916,10 @@ class AppStateStore {
26744
26916
  else
26745
26917
  next.usage = patch.usage;
26746
26918
  }
26919
+ const errorChanged = this.state.lastError !== next.lastError;
26747
26920
  this.state = next;
26921
+ if (errorChanged)
26922
+ this.scheduleErrorClear();
26748
26923
  const snapshot = this.get();
26749
26924
  for (const l of this.listeners)
26750
26925
  l(snapshot);
@@ -26758,12 +26933,12 @@ class AppStateStore {
26758
26933
  }
26759
26934
 
26760
26935
  // src/electron/meeting-listener.ts
26761
- import path7 from "node:path";
26936
+ import path8 from "node:path";
26762
26937
  function resolveAppBundlePath(appPath) {
26763
- return path7.join(appPath, "vendor", "Blink.app");
26938
+ return path8.join(appPath, "vendor", "Blink.app");
26764
26939
  }
26765
26940
  function resolveAudioHelperPath(appPath) {
26766
- return path7.join(resolveAppBundlePath(appPath), "Contents", "Helpers", "BlinkAudio");
26941
+ return path8.join(resolveAppBundlePath(appPath), "Contents", "Helpers", "BlinkAudio");
26767
26942
  }
26768
26943
 
26769
26944
  // src/electron/popup.ts
@@ -26773,7 +26948,7 @@ import {
26773
26948
  ipcMain,
26774
26949
  app
26775
26950
  } from "electron";
26776
- import path8 from "node:path";
26951
+ import path9 from "node:path";
26777
26952
  import { pathToFileURL } from "node:url";
26778
26953
 
26779
26954
  // src/electron/ipc.ts
@@ -26802,17 +26977,28 @@ var CHANNEL_PRESENTER_DISMISS = "blink:presenter-dismiss";
26802
26977
  var CHANNEL_PRESENTER_SET_PRIVACY = "blink:presenter-set-privacy";
26803
26978
  var CHANNEL_PRESENTER_PRIVACY_CHANGED = "blink:presenter-privacy-changed";
26804
26979
  var CHANNEL_PRESENTER_SCROLL = "blink:presenter-scroll";
26980
+ var CHANNEL_SETTINGS_LOAD_PROMPTS = "blink:settings-load-prompts";
26981
+ var CHANNEL_SETTINGS_SAVE_PROMPTS = "blink:settings-save-prompts";
26982
+ var CHANNEL_SETTINGS_LOAD_ANSWERS = "blink:settings-load-answers";
26983
+ var CHANNEL_SETTINGS_DISMISS = "blink:settings-dismiss";
26984
+ var CHANNEL_SETTINGS_LOAD_TRANSCRIPTS = "blink:settings-load-transcripts";
26985
+ var CHANNEL_SETTINGS_READ_TRANSCRIPT = "blink:settings-read-transcript";
26986
+ var CHANNEL_SETTINGS_SHOW_TAB = "blink:settings-show-tab";
26805
26987
 
26806
26988
  // src/electron/popup.ts
26807
- var POPUP_WIDTH = 420;
26808
- var POPUP_HEIGHT = 320;
26809
- var POPUP_EDGE_MARGIN = 12;
26989
+ var POPUP_WIDTH = 520;
26990
+ var POPUP_HEIGHT = 520;
26991
+ var POPUP_EDGE_MARGIN = 0;
26810
26992
  var POPUP_MOVE_STEP = 36;
26993
+ var TRANSCRIPT_COLUMN_WIDTH = 400;
26994
+ var POPUP_MIN_WIDTH = 360;
26995
+ var SPLIT_MIN_WIDTH = 480;
26996
+ var TRANSCRIPT_COLUMN_EXTRA_HEIGHT = 140;
26811
26997
  function resolvePreloadPath() {
26812
- return path8.join(app.getAppPath(), "dist", "electron", "preload.cjs");
26998
+ return path9.join(app.getAppPath(), "dist", "electron", "preload.cjs");
26813
26999
  }
26814
27000
  function resolveRendererIndexUrl() {
26815
- const p = path8.join(app.getAppPath(), "dist", "electron", "renderer", "popup.html");
27001
+ const p = path9.join(app.getAppPath(), "dist", "electron", "renderer", "popup.html");
26816
27002
  return pathToFileURL(p).toString();
26817
27003
  }
26818
27004
 
@@ -26823,6 +27009,7 @@ class PopupController {
26823
27009
  ipcInstalled = false;
26824
27010
  rendererReady = false;
26825
27011
  shuttingDown = false;
27012
+ transcriptColumn = false;
26826
27013
  dismissListener = () => {
26827
27014
  this.hide();
26828
27015
  };
@@ -26874,12 +27061,14 @@ class PopupController {
26874
27061
  return this.window;
26875
27062
  }
26876
27063
  const workArea = screen.getPrimaryDisplay().workArea;
26877
- const x = workArea.x + workArea.width - POPUP_WIDTH - POPUP_EDGE_MARGIN;
27064
+ const width = POPUP_WIDTH + (this.transcriptColumn ? TRANSCRIPT_COLUMN_WIDTH : 0);
27065
+ const height = Math.min(workArea.height, POPUP_HEIGHT + (this.transcriptColumn ? TRANSCRIPT_COLUMN_EXTRA_HEIGHT : 0));
27066
+ const x = workArea.x + workArea.width - width - POPUP_EDGE_MARGIN;
26878
27067
  const y = workArea.y + POPUP_EDGE_MARGIN;
26879
27068
  const win = new BrowserWindow({
26880
- width: POPUP_WIDTH,
26881
- height: POPUP_HEIGHT,
26882
- minWidth: 360,
27069
+ width,
27070
+ height,
27071
+ minWidth: this.transcriptColumn ? SPLIT_MIN_WIDTH : POPUP_MIN_WIDTH,
26883
27072
  x,
26884
27073
  y,
26885
27074
  frame: false,
@@ -26922,6 +27111,7 @@ class PopupController {
26922
27111
  }
26923
27112
  }
26924
27113
  this.pendingMessages.length = 0;
27114
+ this.options.onRendererReady();
26925
27115
  });
26926
27116
  win.loadURL(resolveRendererIndexUrl());
26927
27117
  this.window = win;
@@ -26954,11 +27144,35 @@ class PopupController {
26954
27144
  }
26955
27145
  this.window.webContents.send(CHANNEL_POPUP_USAGE_CHANGED, payload);
26956
27146
  }
27147
+ setTranscriptColumn(visible) {
27148
+ if (this.transcriptColumn === visible)
27149
+ return;
27150
+ this.transcriptColumn = visible;
27151
+ const win = this.window;
27152
+ if (win === null || win.isDestroyed())
27153
+ return;
27154
+ const bounds = win.getBounds();
27155
+ const delta = visible ? TRANSCRIPT_COLUMN_WIDTH : -TRANSCRIPT_COLUMN_WIDTH;
27156
+ const heightDelta = visible ? TRANSCRIPT_COLUMN_EXTRA_HEIGHT : -TRANSCRIPT_COLUMN_EXTRA_HEIGHT;
27157
+ const workArea = screen.getDisplayMatching(bounds).workArea;
27158
+ const minimum = visible ? SPLIT_MIN_WIDTH : POPUP_MIN_WIDTH;
27159
+ win.setMinimumSize(minimum, 240);
27160
+ const height = Math.max(240, Math.min(workArea.height, bounds.height + heightDelta));
27161
+ const y = Math.max(workArea.y, Math.min(bounds.y, workArea.y + workArea.height - height));
27162
+ win.setBounds({
27163
+ width: Math.max(minimum, bounds.width + delta),
27164
+ height,
27165
+ x: Math.max(workArea.x, bounds.x - delta),
27166
+ y
27167
+ });
27168
+ }
27169
+ get rendererLoaded() {
27170
+ return this.window !== null && !this.window.isDestroyed() && this.rendererReady;
27171
+ }
26957
27172
  sendTranscript(payload) {
26958
- if (this.window === null || this.window.isDestroyed() || !this.rendererReady) {
27173
+ if (!this.rendererLoaded)
26959
27174
  return;
26960
- }
26961
- this.window.webContents.send(CHANNEL_TRANSCRIPT_UPDATE, payload);
27175
+ this.window?.webContents.send(CHANNEL_TRANSCRIPT_UPDATE, payload);
26962
27176
  }
26963
27177
  show() {
26964
27178
  const win = this.ensureWindow();
@@ -27050,12 +27264,12 @@ import {
27050
27264
  ipcMain as ipcMain2,
27051
27265
  screen as screen2
27052
27266
  } from "electron";
27053
- import * as path10 from "node:path";
27267
+ import * as path11 from "node:path";
27054
27268
  import { pathToFileURL as pathToFileURL2 } from "node:url";
27055
27269
 
27056
27270
  // src/core/presenter-notes.ts
27057
- import * as fs7 from "node:fs";
27058
- import * as path9 from "node:path";
27271
+ import * as fs8 from "node:fs";
27272
+ import * as path10 from "node:path";
27059
27273
  var MAX_PRESENTER_NOTES_BYTES = 512 * 1024;
27060
27274
  function assertWithinSizeLimit(size) {
27061
27275
  if (size > MAX_PRESENTER_NOTES_BYTES) {
@@ -27064,7 +27278,7 @@ function assertWithinSizeLimit(size) {
27064
27278
  }
27065
27279
  function loadPresenterNotes(filePath) {
27066
27280
  try {
27067
- const contents = fs7.readFileSync(filePath);
27281
+ const contents = fs8.readFileSync(filePath);
27068
27282
  assertWithinSizeLimit(contents.byteLength);
27069
27283
  return contents.toString("utf8");
27070
27284
  } catch (error61) {
@@ -27077,16 +27291,16 @@ function loadPresenterNotes(filePath) {
27077
27291
  function savePresenterNotes(filePath, markdown) {
27078
27292
  const size = Buffer.byteLength(markdown, "utf8");
27079
27293
  assertWithinSizeLimit(size);
27080
- fs7.mkdirSync(path9.dirname(filePath), { recursive: true });
27294
+ fs8.mkdirSync(path10.dirname(filePath), { recursive: true });
27081
27295
  const temporaryPath = `${filePath}.${process.pid}.tmp`;
27082
27296
  try {
27083
- fs7.writeFileSync(temporaryPath, markdown, {
27297
+ fs8.writeFileSync(temporaryPath, markdown, {
27084
27298
  encoding: "utf8",
27085
27299
  mode: 384
27086
27300
  });
27087
- fs7.renameSync(temporaryPath, filePath);
27301
+ fs8.renameSync(temporaryPath, filePath);
27088
27302
  } catch (error61) {
27089
- fs7.rmSync(temporaryPath, { force: true });
27303
+ fs8.rmSync(temporaryPath, { force: true });
27090
27304
  throw error61;
27091
27305
  }
27092
27306
  }
@@ -27096,10 +27310,10 @@ var WINDOW_WIDTH = 760;
27096
27310
  var WINDOW_HEIGHT = 560;
27097
27311
  var WINDOW_MARGIN = 24;
27098
27312
  function preloadPath() {
27099
- return path10.join(app2.getAppPath(), "dist", "electron", "preload.cjs");
27313
+ return path11.join(app2.getAppPath(), "dist", "electron", "preload.cjs");
27100
27314
  }
27101
27315
  function rendererUrl() {
27102
- return pathToFileURL2(path10.join(app2.getAppPath(), "dist", "electron", "renderer", "presenter.html")).toString();
27316
+ return pathToFileURL2(path11.join(app2.getAppPath(), "dist", "electron", "renderer", "presenter.html")).toString();
27103
27317
  }
27104
27318
 
27105
27319
  class PresenterNotesController {
@@ -27238,9 +27452,94 @@ class PresenterNotesController {
27238
27452
  }
27239
27453
  }
27240
27454
 
27455
+ // src/electron/settings.ts
27456
+ import * as path12 from "node:path";
27457
+ import { fileURLToPath } from "node:url";
27458
+ import { BrowserWindow as BrowserWindow3, ipcMain as ipcMain3, screen as screen3 } from "electron";
27459
+ var WINDOW_WIDTH2 = 760;
27460
+ var WINDOW_HEIGHT2 = 620;
27461
+ function rendererFile(name) {
27462
+ return path12.join(path12.dirname(fileURLToPath(import.meta.url)), "renderer", name);
27463
+ }
27464
+ function preloadPath2() {
27465
+ return path12.join(path12.dirname(fileURLToPath(import.meta.url)), "preload.cjs");
27466
+ }
27467
+
27468
+ class SettingsWindow {
27469
+ callbacks;
27470
+ window = null;
27471
+ handlersBound = false;
27472
+ constructor(callbacks) {
27473
+ this.callbacks = callbacks;
27474
+ }
27475
+ show(tab) {
27476
+ this.bindHandlers();
27477
+ const win = this.ensureWindow();
27478
+ const send = () => win.webContents.send(CHANNEL_SETTINGS_SHOW_TAB, tab);
27479
+ if (win.webContents.isLoading())
27480
+ win.webContents.once("did-finish-load", send);
27481
+ else
27482
+ send();
27483
+ win.show();
27484
+ win.focus();
27485
+ }
27486
+ close() {
27487
+ this.window?.destroy();
27488
+ this.window = null;
27489
+ }
27490
+ bindHandlers() {
27491
+ if (this.handlersBound)
27492
+ return;
27493
+ this.handlersBound = true;
27494
+ ipcMain3.handle(CHANNEL_SETTINGS_LOAD_PROMPTS, () => this.callbacks.loadPrompts());
27495
+ ipcMain3.handle(CHANNEL_SETTINGS_SAVE_PROMPTS, (_event, prompts) => {
27496
+ const value = prompts;
27497
+ this.callbacks.savePrompts({
27498
+ monitorPrompt: typeof value.monitorPrompt === "string" ? value.monitorPrompt : "",
27499
+ meetingPrompt: typeof value.meetingPrompt === "string" ? value.meetingPrompt : ""
27500
+ });
27501
+ });
27502
+ ipcMain3.handle(CHANNEL_SETTINGS_LOAD_ANSWERS, () => this.callbacks.loadAnswers());
27503
+ ipcMain3.handle(CHANNEL_SETTINGS_LOAD_TRANSCRIPTS, (_event, query) => this.callbacks.loadTranscripts(typeof query === "string" ? query : ""));
27504
+ ipcMain3.handle(CHANNEL_SETTINGS_READ_TRANSCRIPT, (_event, file2) => typeof file2 === "string" ? this.callbacks.readTranscript(file2) : "");
27505
+ ipcMain3.on(CHANNEL_SETTINGS_DISMISS, () => this.close());
27506
+ }
27507
+ ensureWindow() {
27508
+ if (this.window?.isDestroyed() === false)
27509
+ return this.window;
27510
+ const workArea = screen3.getPrimaryDisplay().workArea;
27511
+ const width = Math.min(WINDOW_WIDTH2, workArea.width - 80);
27512
+ const height = Math.min(WINDOW_HEIGHT2, workArea.height - 80);
27513
+ const win = new BrowserWindow3({
27514
+ width,
27515
+ height,
27516
+ minWidth: 560,
27517
+ minHeight: 420,
27518
+ x: Math.round(workArea.x + (workArea.width - width) / 2),
27519
+ y: Math.round(workArea.y + (workArea.height - height) / 2),
27520
+ title: "Blink",
27521
+ titleBarStyle: "hiddenInset",
27522
+ backgroundColor: "#ffffff",
27523
+ show: false,
27524
+ webPreferences: {
27525
+ preload: preloadPath2(),
27526
+ contextIsolation: true,
27527
+ nodeIntegration: false,
27528
+ sandbox: true
27529
+ }
27530
+ });
27531
+ win.on("closed", () => {
27532
+ this.window = null;
27533
+ });
27534
+ win.loadFile(rendererFile("settings.html"));
27535
+ this.window = win;
27536
+ return win;
27537
+ }
27538
+ }
27539
+
27241
27540
  // src/electron/tray.ts
27242
27541
  import { Tray, Menu, nativeImage } from "electron";
27243
- import * as path11 from "node:path";
27542
+ import * as path13 from "node:path";
27244
27543
  var PROCESSING_FRAME_MS = 500;
27245
27544
  function iconFile(variant) {
27246
27545
  switch (variant) {
@@ -27302,13 +27601,19 @@ class IconCache {
27302
27601
  const cached2 = this.cache.get(variant);
27303
27602
  if (cached2 !== undefined)
27304
27603
  return cached2;
27305
- const filepath = path11.join(this.assetsDir, iconFile(variant));
27604
+ const filepath = path13.join(this.assetsDir, iconFile(variant));
27306
27605
  const img = nativeImage.createFromPath(filepath);
27307
27606
  img.setTemplateImage(true);
27308
27607
  this.cache.set(variant, img);
27309
27608
  return img;
27310
27609
  }
27311
27610
  }
27611
+ function meetingElapsed(state) {
27612
+ if (state.meetingStartedAt === undefined)
27613
+ return "";
27614
+ const minutes = Math.floor((Date.now() - state.meetingStartedAt) / 60000);
27615
+ return minutes < 1 ? "" : ` (${minutes} min)`;
27616
+ }
27312
27617
  function buildTray(opts) {
27313
27618
  const icons = new IconCache(opts.assetsDir);
27314
27619
  const tray = new Tray(icons.get("idle"));
@@ -27350,7 +27655,7 @@ function buildTray(opts) {
27350
27655
  }
27351
27656
  },
27352
27657
  {
27353
- label: `Meeting: ${state.meetingStarting ? "STARTING…" : state.meeting ? "ON" : "OFF"}`,
27658
+ label: state.meetingStarting ? "Meeting: STARTING…" : state.meeting ? `Leave Meeting${meetingElapsed(state)}` : "Meeting: OFF",
27354
27659
  type: "checkbox",
27355
27660
  checked: state.meeting || state.meetingStarting,
27356
27661
  enabled: !state.meetingStarting,
@@ -27358,13 +27663,6 @@ function buildTray(opts) {
27358
27663
  runAction(opts.callbacks.onToggleMeeting);
27359
27664
  }
27360
27665
  },
27361
- {
27362
- label: state.meetingAsking ? "Asking Meeting…" : "Ask Meeting",
27363
- enabled: state.meeting && !state.meetingAsking && (state.meetingTranscriptAvailable || state.meetingScreenshotCount > 0),
27364
- click: () => {
27365
- runAction(opts.callbacks.onAskMeeting);
27366
- }
27367
- },
27368
27666
  {
27369
27667
  label: `Privacy mode: ${state.hideFromCapture ? "ON" : "OFF"}`,
27370
27668
  type: "checkbox",
@@ -27373,14 +27671,6 @@ function buildTray(opts) {
27373
27671
  runAction(opts.callbacks.onToggleHideFromCapture);
27374
27672
  }
27375
27673
  },
27376
- {
27377
- label: `Save transcript: ${state.saveTranscript ? "ON" : "OFF"}`,
27378
- type: "checkbox",
27379
- checked: state.saveTranscript,
27380
- click: () => {
27381
- runAction(opts.callbacks.onToggleSaveTranscript);
27382
- }
27383
- },
27384
27674
  { type: "separator" },
27385
27675
  {
27386
27676
  label: "Open Answer Popup",
@@ -27394,23 +27684,30 @@ function buildTray(opts) {
27394
27684
  runAction(opts.callbacks.onShowPresenter);
27395
27685
  }
27396
27686
  },
27687
+ { type: "separator" },
27397
27688
  {
27398
- label: "Reveal Blink.app in Finder",
27689
+ label: "Custom Prompts…",
27399
27690
  click: () => {
27400
- runAction(opts.callbacks.onRevealBundle);
27691
+ runAction(opts.callbacks.onOpenConfig);
27401
27692
  }
27402
27693
  },
27403
- { type: "separator" },
27404
27694
  {
27405
- label: "Open Config",
27695
+ label: "Answer Log…",
27406
27696
  click: () => {
27407
- runAction(opts.callbacks.onOpenConfig);
27697
+ runAction(opts.callbacks.onOpenAnswerLog);
27408
27698
  }
27409
27699
  },
27410
27700
  {
27411
- label: "Open Answer Log",
27701
+ label: "Meeting Transcripts…",
27412
27702
  click: () => {
27413
- runAction(opts.callbacks.onOpenAnswerLog);
27703
+ runAction(opts.callbacks.onOpenTranscripts);
27704
+ }
27705
+ },
27706
+ { type: "separator" },
27707
+ {
27708
+ label: "Reveal Blink.app in Finder",
27709
+ click: () => {
27710
+ runAction(opts.callbacks.onRevealBundle);
27414
27711
  }
27415
27712
  },
27416
27713
  {
@@ -27459,6 +27756,8 @@ function buildTray(opts) {
27459
27756
  }
27460
27757
 
27461
27758
  // src/electron/app-runtime.ts
27759
+ var DEFAULT_MONITOR_PROMPT = "Answer the question shown in this screenshot. Be concise and direct. If there are multiple questions, answer each one. If the question is coding-related, include Big O time and space complexity.";
27760
+ var DEFAULT_MEETING_PROMPT = "The transcript and screenshots are meeting context and may not contain an explicit question. Identify the latest question, decision, or task the user needs help with, then answer directly and concisely using all supplied context.";
27462
27761
  var PRESENTER_SCROLL_SHORTCUTS = [
27463
27762
  ["Command+Control+Up", "up"],
27464
27763
  ["Command+Control+Down", "down"]
@@ -27472,24 +27771,21 @@ var POPUP_MOVE_SHORTCUTS = [
27472
27771
  var TRANSCRIPT_ASK_SHORTCUT = "Command+Control+Return";
27473
27772
  var TRANSCRIPT_PRUNE_INTERVAL_MS = 1000;
27474
27773
  var TRANSCRIPT_FLUSH_INTERVAL_MS = 150;
27475
- var TRANSCRIPT_STRIP_LINES = 3;
27774
+ var MEETING_SESSION_IDLE_MS = 110 * 60000;
27476
27775
  function blinkHome() {
27477
- return process.env["BLINK_HOME"] ?? path12.join(os3.homedir(), ".blink");
27776
+ return process.env["BLINK_HOME"] ?? path14.join(os3.homedir(), ".blink");
27478
27777
  }
27479
27778
  function configPath() {
27480
- return path12.join(blinkHome(), "config.json");
27481
- }
27482
- function answerLogPath() {
27483
- return path12.join(blinkHome(), "answers.jsonl");
27779
+ return path14.join(blinkHome(), "config.json");
27484
27780
  }
27485
27781
  function presenterNotesPath() {
27486
- return path12.join(blinkHome(), "presenter.md");
27782
+ return path14.join(blinkHome(), "presenter.md");
27487
27783
  }
27488
27784
  function transcriptsDirectory() {
27489
- return path12.join(blinkHome(), "transcripts");
27785
+ return path14.join(blinkHome(), "transcripts");
27490
27786
  }
27491
27787
  function meetingCapturesRoot() {
27492
- return path12.join(blinkHome(), "meeting-captures");
27788
+ return path14.join(blinkHome(), "meeting-captures");
27493
27789
  }
27494
27790
  function meetingAnswerTitle(context) {
27495
27791
  const screenshots = context.screenshotPaths.length;
@@ -27521,11 +27817,40 @@ class AppRuntime {
27521
27817
  tray = null;
27522
27818
  popup = null;
27523
27819
  presenter = null;
27820
+ lastNotifiedError = undefined;
27821
+ settings = new SettingsWindow({
27822
+ loadPrompts: () => ({
27823
+ monitorPrompt: this.config.monitorPrompt,
27824
+ meetingPrompt: this.config.meetingPrompt,
27825
+ monitorDefault: DEFAULT_MONITOR_PROMPT,
27826
+ meetingDefault: DEFAULT_MEETING_PROMPT
27827
+ }),
27828
+ savePrompts: (prompts) => {
27829
+ this.config = {
27830
+ ...this.config,
27831
+ monitorPrompt: prompts.monitorPrompt,
27832
+ meetingPrompt: prompts.meetingPrompt
27833
+ };
27834
+ saveConfig(this.config);
27835
+ this.client = null;
27836
+ },
27837
+ loadAnswers: () => readRecent(500).map((record2) => ({
27838
+ timestamp: record2.timestamp,
27839
+ source: record2.source,
27840
+ answer: record2.answer,
27841
+ durationMs: record2.durationMs
27842
+ })).reverse(),
27843
+ loadTranscripts: (query) => listTranscriptSessions(transcriptsDirectory(), query),
27844
+ readTranscript: (file2) => readTranscriptSession(transcriptsDirectory(), file2)?.markdown ?? ""
27845
+ });
27524
27846
  client = null;
27525
27847
  orchestrator = null;
27526
27848
  orchestratorSetup = null;
27527
27849
  audioManager = null;
27528
- transcriptBuffer = new TranscriptBuffer;
27850
+ transcriptHistory = new TranscriptHistory;
27851
+ transcriptCursor = new MeetingTranscriptCursor;
27852
+ meetingStartedAt = null;
27853
+ lastMeetingAskAt = null;
27529
27854
  meetingContext = new MeetingContextBuffer;
27530
27855
  transcriptLog = null;
27531
27856
  transcriptTimelineOriginMs = null;
@@ -27533,6 +27858,7 @@ class AppRuntime {
27533
27858
  transcriptFlushTimer = null;
27534
27859
  transcriptSentAtMs = 0;
27535
27860
  transcriptSentPayload = "";
27861
+ transcriptResetPending = false;
27536
27862
  screenshotDirectory = null;
27537
27863
  meetingCaptureDirectory = null;
27538
27864
  monitoringToggle = null;
@@ -27554,10 +27880,8 @@ class AppRuntime {
27554
27880
  meeting: false,
27555
27881
  meetingStarting: false,
27556
27882
  meetingAsking: false,
27557
- meetingTranscriptAvailable: false,
27558
27883
  meetingScreenshotCount: 0,
27559
27884
  showTranscript: config2.showTranscript,
27560
- saveTranscript: config2.saveTranscript,
27561
27885
  processing: false,
27562
27886
  queued: 0,
27563
27887
  inFlight: 0,
@@ -27589,6 +27913,7 @@ class AppRuntime {
27589
27913
  this.askMeeting();
27590
27914
  },
27591
27915
  onShowTranscriptChange: (show) => this.setShowTranscript(show),
27916
+ onRendererReady: () => this.resendFullTranscript(),
27592
27917
  getHeaderState: () => {
27593
27918
  const {
27594
27919
  monitoring,
@@ -27596,10 +27921,10 @@ class AppRuntime {
27596
27921
  meeting,
27597
27922
  meetingStarting,
27598
27923
  meetingAsking,
27599
- meetingTranscriptAvailable,
27600
27924
  meetingScreenshotCount,
27601
27925
  showTranscript,
27602
- usage
27926
+ usage,
27927
+ lastError
27603
27928
  } = this.store.get();
27604
27929
  return {
27605
27930
  hideFromCapture: this.config.hideFromCapture,
@@ -27608,10 +27933,11 @@ class AppRuntime {
27608
27933
  meeting,
27609
27934
  meetingStarting,
27610
27935
  asking: meetingAsking,
27611
- transcriptAvailable: meetingTranscriptAvailable,
27612
27936
  screenshotCount: meetingScreenshotCount,
27613
27937
  showTranscript,
27614
- usage: popupUsage(usage)
27938
+ ...this.meetingStartedAt === null ? {} : { startedAt: this.meetingStartedAt },
27939
+ usage: popupUsage(usage),
27940
+ ...lastError === undefined ? {} : { lastError }
27615
27941
  };
27616
27942
  }
27617
27943
  });
@@ -27622,18 +27948,23 @@ class AppRuntime {
27622
27948
  meeting,
27623
27949
  meetingStarting,
27624
27950
  meetingAsking,
27625
- meetingTranscriptAvailable,
27626
27951
  meetingScreenshotCount,
27627
- showTranscript
27952
+ showTranscript,
27953
+ lastError
27628
27954
  }) => {
27955
+ if (lastError !== this.lastNotifiedError) {
27956
+ this.lastNotifiedError = lastError;
27957
+ this.popup?.refreshHeader();
27958
+ }
27629
27959
  this.popup?.sendMonitoringChange({ monitoring, monitoringStarting });
27960
+ this.popup?.setTranscriptColumn(meeting && showTranscript);
27630
27961
  this.popup?.sendMeetingChange({
27631
27962
  meeting,
27632
27963
  meetingStarting,
27633
27964
  asking: meetingAsking,
27634
27965
  showTranscript,
27635
- transcriptAvailable: meetingTranscriptAvailable,
27636
- screenshotCount: meetingScreenshotCount
27966
+ screenshotCount: meetingScreenshotCount,
27967
+ ...this.meetingStartedAt === null ? {} : { startedAt: this.meetingStartedAt }
27637
27968
  });
27638
27969
  });
27639
27970
  this.presenter = new PresenterNotesController({
@@ -27650,18 +27981,17 @@ class AppRuntime {
27650
27981
  this.presenter.registerIpcHandlers();
27651
27982
  this.tray = buildTray({
27652
27983
  store: this.store,
27653
- assetsDir: path12.join(app3.getAppPath(), "assets", "tray"),
27984
+ assetsDir: path14.join(app3.getAppPath(), "assets", "tray"),
27654
27985
  callbacks: {
27655
27986
  onToggleMonitoring: () => this.toggleMonitoring(),
27656
27987
  onToggleMeeting: () => this.toggleMeeting(),
27657
- onAskMeeting: () => this.askMeeting(),
27658
27988
  onShowPopup: () => this.popup?.show(),
27659
27989
  onShowPresenter: () => this.showPresenter(),
27660
27990
  onToggleHideFromCapture: () => this.toggleHideFromCapture(),
27661
- onToggleSaveTranscript: () => this.setSaveTranscript(!this.config.saveTranscript),
27662
27991
  onRevealBundle: () => this.revealBundle(),
27663
27992
  onOpenConfig: () => this.openConfig(),
27664
27993
  onOpenAnswerLog: () => this.openAnswerLog(),
27994
+ onOpenTranscripts: () => this.settings.show("transcripts"),
27665
27995
  onManageSubscription: () => this.openBillingPortal(),
27666
27996
  onQuit: () => app3.quit()
27667
27997
  }
@@ -27678,6 +28008,7 @@ class AppRuntime {
27678
28008
  toggleMonitoring() {
27679
28009
  if (this.monitoringToggle !== null)
27680
28010
  return this.monitoringToggle;
28011
+ this.store.update({ lastError: null });
27681
28012
  this.monitoringToggle = this.performMonitoringToggle().finally(() => {
27682
28013
  this.monitoringToggle = null;
27683
28014
  });
@@ -27686,6 +28017,7 @@ class AppRuntime {
27686
28017
  toggleMeeting() {
27687
28018
  if (this.meetingToggle !== null)
27688
28019
  return this.meetingToggle;
28020
+ this.store.update({ lastError: null });
27689
28021
  this.meetingToggle = this.performMeetingToggle().finally(() => {
27690
28022
  this.meetingToggle = null;
27691
28023
  });
@@ -27744,7 +28076,6 @@ class AppRuntime {
27744
28076
  meeting: false,
27745
28077
  meetingStarting: false,
27746
28078
  meetingAsking: false,
27747
- meetingTranscriptAvailable: false,
27748
28079
  meetingScreenshotCount: 0,
27749
28080
  processing: false,
27750
28081
  queued: 0,
@@ -27793,7 +28124,7 @@ class AppRuntime {
27793
28124
  }
27794
28125
  async startMeeting() {
27795
28126
  const binary = resolveAudioHelperPath(app3.getAppPath());
27796
- if (!fs8.existsSync(binary)) {
28127
+ if (!fs9.existsSync(binary)) {
27797
28128
  this.store.update({
27798
28129
  meeting: false,
27799
28130
  meetingStarting: false,
@@ -27802,7 +28133,9 @@ class AppRuntime {
27802
28133
  return;
27803
28134
  }
27804
28135
  this.clearTranscriptState();
28136
+ this.meetingStartedAt = Date.now();
27805
28137
  this.store.update({
28138
+ meetingStartedAt: this.meetingStartedAt,
27806
28139
  meeting: false,
27807
28140
  meetingStarting: true,
27808
28141
  lastError: null
@@ -27837,8 +28170,8 @@ class AppRuntime {
27837
28170
  if (this.audioManager !== manager || this.shuttingDown)
27838
28171
  return;
27839
28172
  this.alignTranscriptTimeline(event.endMs);
27840
- this.transcriptBuffer.push(event);
27841
- this.updateMeetingTranscript(event.endMs);
28173
+ this.transcriptHistory.push(event);
28174
+ this.syncMeetingContextState();
27842
28175
  this.appendToTranscriptLog(event);
27843
28176
  this.scheduleTranscriptFlush();
27844
28177
  });
@@ -27903,6 +28236,8 @@ class AppRuntime {
27903
28236
  if (this.audioManager !== manager)
27904
28237
  return;
27905
28238
  this.audioManager = null;
28239
+ this.meetingStartedAt = null;
28240
+ this.store.update({ meetingStartedAt: null });
27906
28241
  this.meetingAbortController?.abort();
27907
28242
  if (this.meetingAsk !== null)
27908
28243
  await this.meetingAsk;
@@ -27925,6 +28260,8 @@ class AppRuntime {
27925
28260
  async stopMeeting() {
27926
28261
  const manager = this.audioManager;
27927
28262
  this.audioManager = null;
28263
+ this.meetingStartedAt = null;
28264
+ this.store.update({ meetingStartedAt: null });
27928
28265
  this.meetingAbortController?.abort();
27929
28266
  if (this.meetingAsk !== null)
27930
28267
  await this.meetingAsk;
@@ -27960,42 +28297,30 @@ class AppRuntime {
27960
28297
  return;
27961
28298
  this.transcriptTimelineOriginMs = performance.now() - Math.max(0, streamPositionMs);
27962
28299
  this.transcriptPruneTimer = setInterval(() => {
27963
- const referenceMs = this.currentTranscriptReferenceMs();
27964
- if (referenceMs === null)
27965
- return;
27966
- this.transcriptBuffer.prune(referenceMs);
27967
- this.updateMeetingTranscript(referenceMs);
27968
28300
  this.flushTranscriptLines();
27969
28301
  }, TRANSCRIPT_PRUNE_INTERVAL_MS);
27970
28302
  this.transcriptPruneTimer.unref();
27971
28303
  }
27972
- currentTranscriptReferenceMs() {
27973
- if (this.transcriptTimelineOriginMs === null)
27974
- return null;
27975
- return Math.max(0, performance.now() - this.transcriptTimelineOriginMs);
27976
- }
27977
- updateMeetingTranscript(referenceMs) {
27978
- const { meeting, meetingStarting } = this.store.get();
27979
- if (!meeting && !meetingStarting)
27980
- return;
27981
- this.meetingContext.updateTranscript(this.transcriptBuffer.formatRecent(referenceMs));
27982
- this.syncMeetingContextState();
28304
+ meetingSessionExpired() {
28305
+ const lastAskAt = this.lastMeetingAskAt;
28306
+ if (lastAskAt === null)
28307
+ return false;
28308
+ return Date.now() - lastAskAt >= MEETING_SESSION_IDLE_MS;
27983
28309
  }
27984
28310
  syncMeetingContextState() {
27985
- const { transcriptAvailable, screenshotCount } = this.meetingContext.summary();
27986
- this.store.update({
27987
- meetingTranscriptAvailable: transcriptAvailable,
27988
- meetingScreenshotCount: screenshotCount
27989
- });
28311
+ const { screenshotCount } = this.meetingContext.summary();
28312
+ if (this.store.get().meetingScreenshotCount === screenshotCount)
28313
+ return;
28314
+ this.store.update({ meetingScreenshotCount: screenshotCount });
27990
28315
  }
27991
28316
  async prepareMeetingContext() {
27992
28317
  await this.clearMeetingContext();
27993
28318
  const root = meetingCapturesRoot();
27994
- await fs8.promises.rm(root, { recursive: true, force: true });
27995
- await fs8.promises.mkdir(root, { recursive: true, mode: 448 });
27996
- await fs8.promises.chmod(root, 448);
27997
- const directory = path12.join(root, randomUUID2());
27998
- await fs8.promises.mkdir(directory, { mode: 448 });
28319
+ await fs9.promises.rm(root, { recursive: true, force: true });
28320
+ await fs9.promises.mkdir(root, { recursive: true, mode: 448 });
28321
+ await fs9.promises.chmod(root, 448);
28322
+ const directory = path14.join(root, randomUUID2());
28323
+ await fs9.promises.mkdir(directory, { mode: 448 });
27999
28324
  this.meetingCaptureDirectory = directory;
28000
28325
  }
28001
28326
  async clearMeetingContext() {
@@ -28006,7 +28331,7 @@ class AppRuntime {
28006
28331
  if (directory === null)
28007
28332
  return;
28008
28333
  try {
28009
- await fs8.promises.rm(directory, { recursive: true, force: true });
28334
+ await fs9.promises.rm(directory, { recursive: true, force: true });
28010
28335
  } catch (error61) {
28011
28336
  if (!this.shuttingDown) {
28012
28337
  this.store.update({
@@ -28018,7 +28343,7 @@ class AppRuntime {
28018
28343
  async removeSubmittedScreenshots(screenshotPaths) {
28019
28344
  this.meetingContext.removeScreenshots(screenshotPaths);
28020
28345
  this.syncMeetingContextState();
28021
- const results = await Promise.allSettled(screenshotPaths.map((screenshotPath) => fs8.promises.rm(screenshotPath, { force: true })));
28346
+ const results = await Promise.allSettled(screenshotPaths.map((screenshotPath) => fs9.promises.rm(screenshotPath, { force: true })));
28022
28347
  const failed = results.find((result) => result.status === "rejected");
28023
28348
  if (failed !== undefined && !this.shuttingDown) {
28024
28349
  this.store.update({
@@ -28043,8 +28368,6 @@ class AppRuntime {
28043
28368
  };
28044
28369
  }
28045
28370
  appendToTranscriptLog(event) {
28046
- if (!this.store.get().saveTranscript)
28047
- return;
28048
28371
  try {
28049
28372
  this.transcriptLog ??= new TranscriptLog(transcriptsDirectory());
28050
28373
  this.transcriptLog.append(event);
@@ -28055,15 +28378,6 @@ class AppRuntime {
28055
28378
  });
28056
28379
  }
28057
28380
  }
28058
- setSaveTranscript(save) {
28059
- if (this.config.saveTranscript === save)
28060
- return;
28061
- this.config.saveTranscript = save;
28062
- saveConfig(this.config);
28063
- if (!save)
28064
- this.transcriptLog = null;
28065
- this.store.update({ saveTranscript: save });
28066
- }
28067
28381
  clearTranscriptState() {
28068
28382
  this.transcriptLog = null;
28069
28383
  if (this.transcriptPruneTimer !== null) {
@@ -28075,7 +28389,10 @@ class AppRuntime {
28075
28389
  this.transcriptFlushTimer = null;
28076
28390
  }
28077
28391
  this.transcriptTimelineOriginMs = null;
28078
- this.transcriptBuffer.clear();
28392
+ this.transcriptHistory.clear();
28393
+ this.transcriptCursor.reset();
28394
+ this.lastMeetingAskAt = null;
28395
+ this.transcriptResetPending = true;
28079
28396
  this.flushTranscriptLines();
28080
28397
  }
28081
28398
  scheduleTranscriptFlush() {
@@ -28090,14 +28407,35 @@ class AppRuntime {
28090
28407
  this.transcriptFlushTimer.unref();
28091
28408
  }
28092
28409
  flushTranscriptLines() {
28093
- const referenceMs = this.currentTranscriptReferenceMs();
28094
- const lines = referenceMs === null ? [] : this.transcriptBuffer.recentLines(TRANSCRIPT_STRIP_LINES, referenceMs);
28095
- const serialized = JSON.stringify(lines);
28096
- if (serialized === this.transcriptSentPayload)
28410
+ if (this.popup === null || !this.popup.rendererLoaded)
28411
+ return;
28412
+ const { changed, volatile } = this.transcriptHistory.drain();
28413
+ const serializedVolatile = JSON.stringify(volatile);
28414
+ const reset = this.transcriptResetPending;
28415
+ if (!reset && changed.length === 0 && serializedVolatile === this.transcriptSentPayload) {
28097
28416
  return;
28098
- this.transcriptSentPayload = serialized;
28417
+ }
28418
+ this.transcriptResetPending = false;
28419
+ this.transcriptSentPayload = serializedVolatile;
28099
28420
  this.transcriptSentAtMs = performance.now();
28100
- this.popup?.sendTranscript({ lines });
28421
+ this.popup.sendTranscript({
28422
+ changed: [...changed],
28423
+ volatile: [...volatile],
28424
+ reset
28425
+ });
28426
+ }
28427
+ resendFullTranscript() {
28428
+ if (this.popup === null || !this.popup.rendererLoaded)
28429
+ return;
28430
+ const { volatile } = this.transcriptHistory.drain();
28431
+ this.transcriptResetPending = false;
28432
+ this.transcriptSentPayload = JSON.stringify(volatile);
28433
+ this.transcriptSentAtMs = performance.now();
28434
+ this.popup.sendTranscript({
28435
+ changed: [...this.transcriptHistory.lines()],
28436
+ volatile: [...volatile],
28437
+ reset: true
28438
+ });
28101
28439
  }
28102
28440
  setShowTranscript(show) {
28103
28441
  if (this.config.showTranscript === show)
@@ -28131,14 +28469,8 @@ class AppRuntime {
28131
28469
  this.showMeetingError("Start Meeting before asking");
28132
28470
  return;
28133
28471
  }
28134
- const referenceMs = this.currentTranscriptReferenceMs();
28135
- if (referenceMs !== null)
28136
- this.updateMeetingTranscript(referenceMs);
28137
- const context = this.meetingContext.snapshot();
28138
- if (context.transcript === undefined && context.screenshotPaths.length === 0) {
28139
- this.showMeetingError("Meeting has no transcript or screenshots yet");
28140
- return;
28141
- }
28472
+ const screenshotPaths = this.meetingContext.staged();
28473
+ let chunk = this.transcriptCursor.chunk(this.transcriptHistory.lines(), this.transcriptHistory.volatileLines());
28142
28474
  const abortController = new AbortController;
28143
28475
  this.meetingAbortController = abortController;
28144
28476
  this.store.update({ meetingAsking: true, lastError: null });
@@ -28149,6 +28481,15 @@ class AppRuntime {
28149
28481
  return;
28150
28482
  }
28151
28483
  const client = await this.ensureClient();
28484
+ if (this.meetingSessionExpired()) {
28485
+ await client.resetMeeting();
28486
+ this.transcriptCursor.reset();
28487
+ chunk = this.transcriptCursor.chunk(this.transcriptHistory.lines(), this.transcriptHistory.volatileLines());
28488
+ }
28489
+ const context = {
28490
+ transcript: chunk.text,
28491
+ screenshotPaths: [...screenshotPaths]
28492
+ };
28152
28493
  const detectedAt = new Date().toISOString();
28153
28494
  this.popup?.sendStart({
28154
28495
  source: "meeting",
@@ -28198,6 +28539,8 @@ class AppRuntime {
28198
28539
  answer: outcome.text,
28199
28540
  durationMs: outcome.durationMs
28200
28541
  });
28542
+ this.transcriptCursor.markSubmitted(chunk.lineIds);
28543
+ this.lastMeetingAskAt = Date.now();
28201
28544
  await this.removeSubmittedScreenshots(context.screenshotPaths);
28202
28545
  this.popup?.sendDone({
28203
28546
  type: "complete",
@@ -28351,7 +28694,7 @@ class AppRuntime {
28351
28694
  this.meetingContext.stageScreenshot(result.path);
28352
28695
  this.syncMeetingContextState();
28353
28696
  } else {
28354
- await fs8.promises.rm(result.path, { force: true });
28697
+ await fs9.promises.rm(result.path, { force: true });
28355
28698
  }
28356
28699
  }
28357
28700
  } catch (error61) {
@@ -28407,7 +28750,7 @@ class AppRuntime {
28407
28750
  onStart: (event) => {
28408
28751
  this.popup?.sendStart({
28409
28752
  source: "monitor",
28410
- title: path12.basename(event.path),
28753
+ title: path14.basename(event.path),
28411
28754
  detectedAt: event.detectedAt.toISOString()
28412
28755
  });
28413
28756
  },
@@ -28453,26 +28796,19 @@ class AppRuntime {
28453
28796
  }
28454
28797
  this.client = new BlinkCloudClient({
28455
28798
  apiUrl: this.config.apiUrl,
28456
- accessToken: this.config.accessToken
28799
+ accessToken: this.config.accessToken,
28800
+ prompts: {
28801
+ ...this.config.monitorPrompt === "" ? {} : { monitor: this.config.monitorPrompt },
28802
+ ...this.config.meetingPrompt === "" ? {} : { meeting: this.config.meetingPrompt }
28803
+ }
28457
28804
  });
28458
28805
  return Promise.resolve(this.client);
28459
28806
  }
28460
- async openConfig() {
28461
- const target = configPath();
28462
- if (!fs8.existsSync(target))
28463
- saveConfig(this.config);
28464
- const error61 = await shell.openPath(target);
28465
- if (error61 !== "")
28466
- this.store.update({ lastError: `open config: ${error61}` });
28467
- }
28468
- async openAnswerLog() {
28469
- const target = answerLogPath();
28470
- fs8.mkdirSync(path12.dirname(target), { recursive: true });
28471
- if (!fs8.existsSync(target))
28472
- fs8.writeFileSync(target, "");
28473
- const error61 = await shell.openPath(target);
28474
- if (error61 !== "")
28475
- this.store.update({ lastError: `open log: ${error61}` });
28807
+ openConfig() {
28808
+ this.settings.show("prompts");
28809
+ }
28810
+ openAnswerLog() {
28811
+ this.settings.show("answers");
28476
28812
  }
28477
28813
  async openBillingPortal() {
28478
28814
  const client = await this.ensureClient();
@@ -28485,7 +28821,7 @@ class AppRuntime {
28485
28821
  }
28486
28822
  revealBundle() {
28487
28823
  const bundle = resolveAppBundlePath(app3.getAppPath());
28488
- if (!fs8.existsSync(bundle)) {
28824
+ if (!fs9.existsSync(bundle)) {
28489
28825
  this.store.update({ lastError: `Blink.app is missing at ${bundle}` });
28490
28826
  return;
28491
28827
  }