@phenx-inc/ctlsurf 0.13.6 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/out/headless/index.mjs +13663 -385
  2. package/out/headless/index.mjs.map +4 -4
  3. package/out/main/index.js +11665 -286
  4. package/out/main/node-CUnQxFha.js +868 -0
  5. package/out/preload/index.js +17 -0
  6. package/out/renderer/assets/{cssMode-CsSLnKZ-.js → cssMode-bQYoCKra.js} +3 -3
  7. package/out/renderer/assets/{freemarker2-C1XYRbOq.js → freemarker2-BS1ERQl_.js} +1 -1
  8. package/out/renderer/assets/{handlebars-BSdbbnMW.js → handlebars-B-ZEHRLr.js} +1 -1
  9. package/out/renderer/assets/{html-96igtyOz.js → html-lk9e1Lkl.js} +1 -1
  10. package/out/renderer/assets/{htmlMode-BRnCcIzp.js → htmlMode-Ds1eMYgM.js} +3 -3
  11. package/out/renderer/assets/{index-Cc-jDHm3.js → index-BJNR4hRK.js} +380 -23
  12. package/out/renderer/assets/{index-BEekQe3-.css → index-BpCORklm.css} +217 -0
  13. package/out/renderer/assets/{javascript-7MdRNHk9.js → javascript-D6OeziKX.js} +2 -2
  14. package/out/renderer/assets/{jsonMode-oGam2go_.js → jsonMode-t5SESE75.js} +3 -3
  15. package/out/renderer/assets/{liquid-DoKC7ba2.js → liquid-B5Wjh0p_.js} +1 -1
  16. package/out/renderer/assets/{lspLanguageFeatures-C2h5qGCv.js → lspLanguageFeatures-BEgiDCIW.js} +1 -1
  17. package/out/renderer/assets/{mdx-0w8n1HGo.js → mdx-ByNAXh8t.js} +1 -1
  18. package/out/renderer/assets/{python-BfY4HssB.js → python-CIFO0XQW.js} +1 -1
  19. package/out/renderer/assets/{razor-BoDk9Ula.js → razor-LXHhGcNO.js} +1 -1
  20. package/out/renderer/assets/{tsMode-CX0oVKRt.js → tsMode-WiO8CDaI.js} +1 -1
  21. package/out/renderer/assets/{typescript-BqIU7abP.js → typescript-ZBQlq256.js} +1 -1
  22. package/out/renderer/assets/{xml-BlSDnxFw.js → xml-DBaLJlQU.js} +1 -1
  23. package/out/renderer/assets/{yaml-bVMmGUtU.js → yaml-CId9skah.js} +1 -1
  24. package/out/renderer/index.html +2 -2
  25. package/package.json +2 -1
  26. package/src/main/index.ts +36 -2
  27. package/src/main/observer/anthropic.ts +48 -0
  28. package/src/main/observer/budget.ts +79 -0
  29. package/src/main/observer/ledger.ts +61 -0
  30. package/src/main/observer/observer.ts +566 -0
  31. package/src/main/observer/spans.ts +170 -0
  32. package/src/main/observer/store.ts +200 -0
  33. package/src/main/observer/tier0.ts +234 -0
  34. package/src/main/observer/tier1.ts +306 -0
  35. package/src/main/observer/tier2.ts +125 -0
  36. package/src/main/observer/types.ts +224 -0
  37. package/src/main/orchestrator.ts +74 -0
  38. package/src/main/transcripts.ts +18 -0
  39. package/src/preload/index.ts +36 -0
  40. package/src/renderer/App.tsx +22 -0
  41. package/src/renderer/components/ObserverPanel.tsx +289 -0
  42. package/src/renderer/components/SettingsDialog.tsx +104 -0
  43. package/src/renderer/components/TerminalPanel.tsx +29 -0
  44. package/src/renderer/styles.css +217 -0
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-CsSLnKZ-.js","./lspLanguageFeatures-C2h5qGCv.js","./htmlMode-BRnCcIzp.js","./jsonMode-oGam2go_.js","./javascript-7MdRNHk9.js","./typescript-BqIU7abP.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-bQYoCKra.js","./lspLanguageFeatures-BEgiDCIW.js","./htmlMode-Ds1eMYgM.js","./jsonMode-t5SESE75.js","./javascript-D6OeziKX.js","./typescript-ZBQlq256.js"])))=>i.map(i=>d[i]);
2
2
  function getDefaultExportFromCjs(x) {
3
3
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
4
4
  }
@@ -19286,6 +19286,12 @@ function getOrCreateTerminal(tabId, onExit) {
19286
19286
  // Off by default on macOS; without this a right-click would reselect the
19287
19287
  // word under the cursor and clobber a multi-line table selection.
19288
19288
  rightClickSelectsWord: false,
19289
+ // A mouse-tracking TUI (notably tmux with `set -g mouse on`) swallows plain
19290
+ // drags, so they yank into a remote tmux buffer instead of selecting here.
19291
+ // Option+drag is the only way back to a local selection on macOS, and xterm
19292
+ // gates it behind this flag. Elsewhere Shift+drag already does it. Costs us
19293
+ // Option+drag column-select on macOS, which nothing here relies on.
19294
+ macOptionClickForcesSelection: true,
19289
19295
  fontSize: 14,
19290
19296
  fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', monospace",
19291
19297
  theme: {
@@ -19317,6 +19323,21 @@ function getOrCreateTerminal(tabId, onExit) {
19317
19323
  const fitAddon = new addonFitExports.FitAddon();
19318
19324
  terminal.loadAddon(fitAddon);
19319
19325
  terminal.loadAddon(new addonWebLinksExports.WebLinksAddon(handleTerminalLink));
19326
+ terminal.parser.registerOscHandler(52, (data) => {
19327
+ const payload = data.slice(data.indexOf(";") + 1);
19328
+ if (!payload || payload === "?") return false;
19329
+ if (payload.length > 14e5) return false;
19330
+ let text2;
19331
+ try {
19332
+ const bin = atob(payload);
19333
+ text2 = new TextDecoder().decode(Uint8Array.from(bin, (c) => c.charCodeAt(0)));
19334
+ } catch (err) {
19335
+ console.warn("[copy] OSC 52 payload was not valid base64", err);
19336
+ return false;
19337
+ }
19338
+ copyTextValue(text2);
19339
+ return true;
19340
+ });
19320
19341
  terminal.attachCustomKeyEventHandler((e) => {
19321
19342
  if (e.type !== "keydown") return true;
19322
19343
  if (e.key === "PageUp" || e.key === "PageDown" || e.key === "Home" || e.key === "End") {
@@ -208167,7 +208188,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
208167
208188
  modeConfigurationDefault$2
208168
208189
  );
208169
208190
  function getMode$3() {
208170
- return __vitePreload(() => import("./cssMode-CsSLnKZ-.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
208191
+ return __vitePreload(() => import("./cssMode-bQYoCKra.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
208171
208192
  }
208172
208193
  languages.onLanguage("less", () => {
208173
208194
  getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
@@ -208272,7 +208293,7 @@ const razorLanguageService = registerHTMLLanguageService(
208272
208293
  );
208273
208294
  const razorDefaults = razorLanguageService.defaults;
208274
208295
  function getMode$2() {
208275
- return __vitePreload(() => import("./htmlMode-BRnCcIzp.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
208296
+ return __vitePreload(() => import("./htmlMode-Ds1eMYgM.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
208276
208297
  }
208277
208298
  function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
208278
208299
  const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
@@ -208356,7 +208377,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
208356
208377
  );
208357
208378
  const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
208358
208379
  function getMode$1() {
208359
- return __vitePreload(() => import("./jsonMode-oGam2go_.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208380
+ return __vitePreload(() => import("./jsonMode-t5SESE75.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208360
208381
  }
208361
208382
  languages.register({
208362
208383
  id: "json",
@@ -208602,7 +208623,7 @@ const getJavaScriptWorker = () => {
208602
208623
  return getMode().then((mode) => mode.getJavaScriptWorker());
208603
208624
  };
208604
208625
  function getMode() {
208605
- return __vitePreload(() => import("./tsMode-CX0oVKRt.js"), true ? [] : void 0, import.meta.url);
208626
+ return __vitePreload(() => import("./tsMode-WiO8CDaI.js"), true ? [] : void 0, import.meta.url);
208606
208627
  }
208607
208628
  languages.onLanguage("typescript", () => {
208608
208629
  return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
@@ -208797,49 +208818,49 @@ registerLanguage({
208797
208818
  extensions: [".ftl", ".ftlh", ".ftlx"],
208798
208819
  aliases: ["FreeMarker2", "Apache FreeMarker2"],
208799
208820
  loader: () => {
208800
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208821
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208801
208822
  }
208802
208823
  });
208803
208824
  registerLanguage({
208804
208825
  id: "freemarker2.tag-angle.interpolation-dollar",
208805
208826
  aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
208806
208827
  loader: () => {
208807
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208828
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208808
208829
  }
208809
208830
  });
208810
208831
  registerLanguage({
208811
208832
  id: "freemarker2.tag-bracket.interpolation-dollar",
208812
208833
  aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
208813
208834
  loader: () => {
208814
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208835
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208815
208836
  }
208816
208837
  });
208817
208838
  registerLanguage({
208818
208839
  id: "freemarker2.tag-angle.interpolation-bracket",
208819
208840
  aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
208820
208841
  loader: () => {
208821
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208842
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208822
208843
  }
208823
208844
  });
208824
208845
  registerLanguage({
208825
208846
  id: "freemarker2.tag-bracket.interpolation-bracket",
208826
208847
  aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
208827
208848
  loader: () => {
208828
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208849
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208829
208850
  }
208830
208851
  });
208831
208852
  registerLanguage({
208832
208853
  id: "freemarker2.tag-auto.interpolation-dollar",
208833
208854
  aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
208834
208855
  loader: () => {
208835
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208856
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208836
208857
  }
208837
208858
  });
208838
208859
  registerLanguage({
208839
208860
  id: "freemarker2.tag-auto.interpolation-bracket",
208840
208861
  aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
208841
208862
  loader: () => {
208842
- return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208863
+ return __vitePreload(() => import("./freemarker2-BS1ERQl_.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208843
208864
  }
208844
208865
  });
208845
208866
  registerLanguage({
@@ -208860,7 +208881,7 @@ registerLanguage({
208860
208881
  extensions: [".handlebars", ".hbs"],
208861
208882
  aliases: ["Handlebars", "handlebars", "hbs"],
208862
208883
  mimetypes: ["text/x-handlebars-template"],
208863
- loader: () => __vitePreload(() => import("./handlebars-BSdbbnMW.js"), true ? [] : void 0, import.meta.url)
208884
+ loader: () => __vitePreload(() => import("./handlebars-B-ZEHRLr.js"), true ? [] : void 0, import.meta.url)
208864
208885
  });
208865
208886
  registerLanguage({
208866
208887
  id: "hcl",
@@ -208873,7 +208894,7 @@ registerLanguage({
208873
208894
  extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
208874
208895
  aliases: ["HTML", "htm", "html", "xhtml"],
208875
208896
  mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
208876
- loader: () => __vitePreload(() => import("./html-96igtyOz.js"), true ? [] : void 0, import.meta.url)
208897
+ loader: () => __vitePreload(() => import("./html-lk9e1Lkl.js"), true ? [] : void 0, import.meta.url)
208877
208898
  });
208878
208899
  registerLanguage({
208879
208900
  id: "ini",
@@ -208896,7 +208917,7 @@ registerLanguage({
208896
208917
  filenames: ["jakefile"],
208897
208918
  aliases: ["JavaScript", "javascript", "js"],
208898
208919
  mimetypes: ["text/javascript"],
208899
- loader: () => __vitePreload(() => import("./javascript-7MdRNHk9.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208920
+ loader: () => __vitePreload(() => import("./javascript-D6OeziKX.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208900
208921
  });
208901
208922
  registerLanguage({
208902
208923
  id: "julia",
@@ -208935,7 +208956,7 @@ registerLanguage({
208935
208956
  extensions: [".liquid", ".html.liquid"],
208936
208957
  aliases: ["Liquid", "liquid"],
208937
208958
  mimetypes: ["application/liquid"],
208938
- loader: () => __vitePreload(() => import("./liquid-DoKC7ba2.js"), true ? [] : void 0, import.meta.url)
208959
+ loader: () => __vitePreload(() => import("./liquid-B5Wjh0p_.js"), true ? [] : void 0, import.meta.url)
208939
208960
  });
208940
208961
  registerLanguage({
208941
208962
  id: "m3",
@@ -208953,7 +208974,7 @@ registerLanguage({
208953
208974
  id: "mdx",
208954
208975
  extensions: [".mdx"],
208955
208976
  aliases: ["MDX", "mdx"],
208956
- loader: () => __vitePreload(() => import("./mdx-0w8n1HGo.js"), true ? [] : void 0, import.meta.url)
208977
+ loader: () => __vitePreload(() => import("./mdx-ByNAXh8t.js"), true ? [] : void 0, import.meta.url)
208957
208978
  });
208958
208979
  registerLanguage({
208959
208980
  id: "mips",
@@ -209052,7 +209073,7 @@ registerLanguage({
209052
209073
  extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
209053
209074
  aliases: ["Python", "py"],
209054
209075
  firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
209055
- loader: () => __vitePreload(() => import("./python-BfY4HssB.js"), true ? [] : void 0, import.meta.url)
209076
+ loader: () => __vitePreload(() => import("./python-CIFO0XQW.js"), true ? [] : void 0, import.meta.url)
209056
209077
  });
209057
209078
  registerLanguage({
209058
209079
  id: "qsharp",
@@ -209071,7 +209092,7 @@ registerLanguage({
209071
209092
  extensions: [".cshtml"],
209072
209093
  aliases: ["Razor", "razor"],
209073
209094
  mimetypes: ["text/x-cshtml"],
209074
- loader: () => __vitePreload(() => import("./razor-BoDk9Ula.js"), true ? [] : void 0, import.meta.url)
209095
+ loader: () => __vitePreload(() => import("./razor-LXHhGcNO.js"), true ? [] : void 0, import.meta.url)
209075
209096
  });
209076
209097
  registerLanguage({
209077
209098
  id: "redis",
@@ -209204,7 +209225,7 @@ registerLanguage({
209204
209225
  aliases: ["TypeScript", "ts", "typescript"],
209205
209226
  mimetypes: ["text/typescript"],
209206
209227
  loader: () => {
209207
- return __vitePreload(() => import("./typescript-BqIU7abP.js"), true ? [] : void 0, import.meta.url);
209228
+ return __vitePreload(() => import("./typescript-ZBQlq256.js"), true ? [] : void 0, import.meta.url);
209208
209229
  }
209209
209230
  });
209210
209231
  registerLanguage({
@@ -209249,14 +209270,14 @@ registerLanguage({
209249
209270
  firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
209250
209271
  aliases: ["XML", "xml"],
209251
209272
  mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
209252
- loader: () => __vitePreload(() => import("./xml-BlSDnxFw.js"), true ? [] : void 0, import.meta.url)
209273
+ loader: () => __vitePreload(() => import("./xml-DBaLJlQU.js"), true ? [] : void 0, import.meta.url)
209253
209274
  });
209254
209275
  registerLanguage({
209255
209276
  id: "yaml",
209256
209277
  extensions: [".yaml", ".yml"],
209257
209278
  aliases: ["YAML", "yaml", "YML", "yml"],
209258
209279
  mimetypes: ["application/x-yaml", "text/x-yaml"],
209259
- loader: () => __vitePreload(() => import("./yaml-bVMmGUtU.js"), true ? [] : void 0, import.meta.url)
209280
+ loader: () => __vitePreload(() => import("./yaml-CId9skah.js"), true ? [] : void 0, import.meta.url)
209260
209281
  });
209261
209282
  var __defProp = Object.defineProperty;
209262
209283
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -213549,20 +213570,54 @@ function SettingsDialog({ open, onClose }) {
213549
213570
  const [idleTimeoutMin, setIdleTimeoutMin] = reactExports.useState(15);
213550
213571
  const [saved, setSaved] = reactExports.useState(false);
213551
213572
  const [version, setVersion] = reactExports.useState("");
213573
+ const [obsEnabled, setObsEnabled] = reactExports.useState(false);
213574
+ const [obsApiKey, setObsApiKey] = reactExports.useState("");
213575
+ const [obsHasKey, setObsHasKey] = reactExports.useState(false);
213576
+ const [obsKeySource, setObsKeySource] = reactExports.useState(null);
213577
+ const [obsCapUsd, setObsCapUsd] = reactExports.useState(1);
213578
+ const [obsSaved, setObsSaved] = reactExports.useState(false);
213552
213579
  const loadProfiles = async () => {
213553
213580
  const data = await window.worker.listProfiles();
213554
213581
  setProfileList(data);
213555
213582
  setActiveProfileId(data.activeProfile);
213556
213583
  };
213584
+ const loadObserver = async () => {
213585
+ try {
213586
+ const o = await window.worker.getObserverSettings();
213587
+ setObsEnabled(o.enabled);
213588
+ setObsHasKey(o.hasApiKey);
213589
+ setObsKeySource(o.keySource);
213590
+ setObsCapUsd(o.dailyCapUsd);
213591
+ setObsApiKey("");
213592
+ } catch {
213593
+ }
213594
+ };
213557
213595
  reactExports.useEffect(() => {
213558
213596
  if (open) {
213559
213597
  loadProfiles();
213598
+ loadObserver();
213560
213599
  setEditingId(null);
213561
213600
  setSaved(false);
213601
+ setObsSaved(false);
213562
213602
  window.worker.getVersion().then(setVersion).catch(() => {
213563
213603
  });
213564
213604
  }
213565
213605
  }, [open]);
213606
+ const handleObserverSave = async () => {
213607
+ const data = {
213608
+ enabled: obsEnabled,
213609
+ dailyCapUsd: Math.max(0.05, obsCapUsd) || 1
213610
+ };
213611
+ if (obsApiKey.trim()) {
213612
+ data.anthropicApiKey = obsApiKey.trim();
213613
+ }
213614
+ const o = await window.worker.setObserverSettings(data);
213615
+ setObsHasKey(o.hasApiKey);
213616
+ setObsKeySource(o.keySource);
213617
+ setObsApiKey("");
213618
+ setObsSaved(true);
213619
+ setTimeout(() => setObsSaved(false), 900);
213620
+ };
213566
213621
  const startEditing = (profile) => {
213567
213622
  setEditingId(profile.id);
213568
213623
  setName(profile.name);
@@ -213732,6 +213787,51 @@ function SettingsDialog({ open, onClose }) {
213732
213787
  ] })
213733
213788
  ] })
213734
213789
  ),
213790
+ !editingId && // ─── Observer (global) ─────────────────
213791
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "settings-section", children: [
213792
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { children: "Observer" }),
213793
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "settings-hint", children: "Reviews agent sessions for assumptions, unverified claims, and dependency/license risk, tracks time per work item, and posts a session digest to the project's Agent Datastore page." }),
213794
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "settings-checkbox", children: [
213795
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
213796
+ "input",
213797
+ {
213798
+ type: "checkbox",
213799
+ checked: obsEnabled,
213800
+ onChange: (e) => setObsEnabled(e.target.checked)
213801
+ }
213802
+ ),
213803
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Enable Observer" }),
213804
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "settings-hint", children: "Applies to newly started agent tabs. Advisory only — never blocks or slows the agent." })
213805
+ ] }),
213806
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
213807
+ "Anthropic API Key",
213808
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
213809
+ "input",
213810
+ {
213811
+ type: "password",
213812
+ value: obsApiKey,
213813
+ onChange: (e) => setObsApiKey(e.target.value),
213814
+ placeholder: obsKeySource === "settings" ? "***configured*** (leave blank to keep)" : obsKeySource === "env" ? "using ANTHROPIC_API_KEY from environment" : "sk-ant-…"
213815
+ }
213816
+ ),
213817
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "settings-hint", children: "Your own Anthropic key — separate from the ctlsurf profile key. Without one, the Observer still records the session ledger, Tier-0 tags, and spans, but skips model review and digests." })
213818
+ ] }),
213819
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
213820
+ "Daily budget cap (USD)",
213821
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
213822
+ "input",
213823
+ {
213824
+ type: "number",
213825
+ min: 0.05,
213826
+ step: 0.25,
213827
+ value: obsCapUsd,
213828
+ onChange: (e) => setObsCapUsd(parseFloat(e.target.value) || 1)
213829
+ }
213830
+ ),
213831
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "settings-hint", children: "Model review pauses for the day once spend reaches the cap; Tier-0 tagging and spans continue." })
213832
+ ] }),
213833
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "settings-actions", children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "btn-primary", onClick: handleObserverSave, children: obsSaved ? "Saved!" : "Save Observer Settings" }) })
213834
+ ] }),
213735
213835
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "settings-section settings-about", children: [
213736
213836
  /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { children: "About" }),
213737
213837
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "about-name", children: [
@@ -214086,6 +214186,232 @@ function TicketPane({ onSendToTerminal }) {
214086
214186
  ] })
214087
214187
  ] });
214088
214188
  }
214189
+ const SENSITIVITY_LEVELS = [
214190
+ { value: "severe", label: "Severe", hint: "Only high/critical findings — near silence" },
214191
+ { value: "balanced", label: "Balanced", hint: "Warn and above — clear signals only" },
214192
+ { value: "all", label: "All signals", hint: "Everything, including low-confidence observations" }
214193
+ ];
214194
+ const SEVERITY_COLORS = {
214195
+ info: "#7aa2f7",
214196
+ warn: "#e0af68",
214197
+ high: "#ff9e64",
214198
+ critical: "#f7768e"
214199
+ };
214200
+ const DIGEST_COLOR = "#bb9af7";
214201
+ function EyeIcon({ size: size2 = 16 }) {
214202
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
214203
+ "svg",
214204
+ {
214205
+ viewBox: "0 0 24 24",
214206
+ width: size2,
214207
+ height: size2,
214208
+ fill: "none",
214209
+ stroke: "currentColor",
214210
+ strokeWidth: "2",
214211
+ strokeLinecap: "round",
214212
+ strokeLinejoin: "round",
214213
+ "aria-hidden": "true",
214214
+ children: [
214215
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
214216
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3" })
214217
+ ]
214218
+ }
214219
+ );
214220
+ }
214221
+ function formatTime(iso) {
214222
+ const d = new Date(iso);
214223
+ if (Number.isNaN(d.getTime())) return "";
214224
+ return d.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" });
214225
+ }
214226
+ function Chip({ color, label }) {
214227
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "obs-chip", style: { color, borderColor: `${color}55`, background: `${color}14` }, children: [
214228
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-chip-dot", style: { background: color } }),
214229
+ label
214230
+ ] });
214231
+ }
214232
+ function FindingCard({ item }) {
214233
+ const [expanded2, setExpanded] = reactExports.useState(false);
214234
+ const color = SEVERITY_COLORS[item.severity || "info"] || SEVERITY_COLORS.info;
214235
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
214236
+ "button",
214237
+ {
214238
+ type: "button",
214239
+ className: "obs-card",
214240
+ style: { borderLeftColor: color },
214241
+ onClick: () => setExpanded((v2) => !v2),
214242
+ "aria-expanded": expanded2,
214243
+ children: [
214244
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "obs-card-top", children: [
214245
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Chip, { color, label: item.severity || "info" }),
214246
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-card-cat", children: (item.category || "").replace(/_/g, " ") }),
214247
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-card-time", children: formatTime(item.ts) })
214248
+ ] }),
214249
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "obs-card-title", children: item.title }),
214250
+ expanded2 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "obs-card-body", children: [
214251
+ item.detail && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: item.detail }),
214252
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "obs-card-facts", children: [
214253
+ typeof item.confidence === "number" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "obs-fact", children: [
214254
+ Math.round(item.confidence * 100),
214255
+ "% confidence"
214256
+ ] }),
214257
+ typeof item.tier === "number" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "obs-fact", children: [
214258
+ "tier ",
214259
+ item.tier
214260
+ ] }),
214261
+ item.receipts && item.receipts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-fact", children: item.receipts.join(" · ") })
214262
+ ] })
214263
+ ] }),
214264
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `obs-card-caret ${expanded2 ? "open" : ""}`, "aria-hidden": "true", children: "▸" })
214265
+ ]
214266
+ }
214267
+ );
214268
+ }
214269
+ function DigestCard({ item }) {
214270
+ const [expanded2, setExpanded] = reactExports.useState(true);
214271
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
214272
+ "button",
214273
+ {
214274
+ type: "button",
214275
+ className: "obs-card",
214276
+ style: { borderLeftColor: DIGEST_COLOR },
214277
+ onClick: () => setExpanded((v2) => !v2),
214278
+ "aria-expanded": expanded2,
214279
+ children: [
214280
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "obs-card-top", children: [
214281
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Chip, { color: DIGEST_COLOR, label: "digest" }),
214282
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-card-time", children: formatTime(item.ts) })
214283
+ ] }),
214284
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "obs-card-title", children: item.title }),
214285
+ expanded2 && item.detail && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "obs-card-body", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: item.detail }) }),
214286
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `obs-card-caret ${expanded2 ? "open" : ""}`, "aria-hidden": "true", children: "▸" })
214287
+ ]
214288
+ }
214289
+ );
214290
+ }
214291
+ function ObserverPane() {
214292
+ const [snapshot, setSnapshot] = reactExports.useState(null);
214293
+ const [toggling, setToggling] = reactExports.useState(false);
214294
+ const [reviewing, setReviewing] = reactExports.useState(false);
214295
+ const refresh = reactExports.useCallback(async () => {
214296
+ try {
214297
+ const s = await window.worker.getObserverFeed();
214298
+ setSnapshot(s);
214299
+ setReviewing(s.reviewing);
214300
+ } catch {
214301
+ }
214302
+ }, []);
214303
+ reactExports.useEffect(() => {
214304
+ void refresh();
214305
+ const unsub = window.worker.onObserverUpdate((item) => {
214306
+ setSnapshot((prev) => prev ? { ...prev, items: [...prev.items.filter((i2) => i2.id !== item.id), item].slice(-200) } : prev);
214307
+ });
214308
+ const unsubActivity = window.worker.onObserverActivity(setReviewing);
214309
+ const unsubCwd = window.worker.onCwdChanged(() => void refresh());
214310
+ return () => {
214311
+ unsub();
214312
+ unsubActivity();
214313
+ unsubCwd();
214314
+ };
214315
+ }, [refresh]);
214316
+ const handleToggle = reactExports.useCallback(async (enabled2) => {
214317
+ if (toggling) return;
214318
+ setToggling(true);
214319
+ try {
214320
+ const s = await window.worker.toggleObserver(enabled2);
214321
+ setSnapshot(s);
214322
+ } finally {
214323
+ setToggling(false);
214324
+ }
214325
+ }, [toggling]);
214326
+ const handleSensitivity = reactExports.useCallback(async (level) => {
214327
+ const current = snapshot;
214328
+ if (!current || current.sensitivity === level) return;
214329
+ setSnapshot({ ...current, sensitivity: level });
214330
+ try {
214331
+ await window.worker.setObserverSettings({ enabled: current.enabled, sensitivity: level });
214332
+ } catch {
214333
+ void refresh();
214334
+ }
214335
+ }, [snapshot, refresh]);
214336
+ const enabled = snapshot?.enabled ?? false;
214337
+ const items = [...snapshot?.items || []].reverse();
214338
+ const findings = items.filter((i2) => i2.kind === "finding");
214339
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-pane observer-pane", role: "region", "aria-label": "Observer", children: [
214340
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-header", children: [
214341
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-heading", children: [
214342
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `ticket-drawer-badge obs-badge ${reviewing && enabled ? "reviewing" : ""}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(EyeIcon, { size: 16 }) }),
214343
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-headtext", children: [
214344
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-title", children: "Observer" }),
214345
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-subtitle", children: !snapshot ? "loading…" : !enabled ? "off" : !snapshot.hasApiKey ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-warn", children: "no Anthropic API key — Tier 0 only (add in Settings)" }) : snapshot.observing.length === 0 ? "on — waiting for an agent tab" : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
214346
+ "watching ",
214347
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: snapshot.observing.map((o) => o.agentName).join(", ") })
214348
+ ] }) })
214349
+ ] })
214350
+ ] }),
214351
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "observer-switch", title: enabled ? "Turn Observer off" : "Turn Observer on", children: [
214352
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
214353
+ "input",
214354
+ {
214355
+ type: "checkbox",
214356
+ checked: enabled,
214357
+ disabled: toggling || !snapshot,
214358
+ onChange: (e) => void handleToggle(e.target.checked)
214359
+ }
214360
+ ),
214361
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "observer-switch-track", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "observer-switch-thumb" }) })
214362
+ ] })
214363
+ ] }),
214364
+ enabled && snapshot && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "obs-toolbar", children: [
214365
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "obs-sensitivity", role: "radiogroup", "aria-label": "Detection threshold", children: SENSITIVITY_LEVELS.map((l2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
214366
+ "button",
214367
+ {
214368
+ type: "button",
214369
+ className: `obs-sens-btn ${snapshot.sensitivity === l2.value ? "active" : ""}`,
214370
+ title: l2.hint,
214371
+ "aria-pressed": snapshot.sensitivity === l2.value,
214372
+ onClick: () => void handleSensitivity(l2.value),
214373
+ children: l2.label
214374
+ },
214375
+ l2.value
214376
+ )) }),
214377
+ reviewing && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "obs-reviewing", "aria-live": "polite", children: [
214378
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-reviewing-dot" }),
214379
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-reviewing-dot" }),
214380
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-reviewing-dot" }),
214381
+ "reviewing"
214382
+ ] })
214383
+ ] }),
214384
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-list-body obs-feed", children: [
214385
+ !enabled && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-empty", children: [
214386
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(EyeIcon, { size: 26 }) }),
214387
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-title", children: "Observer is off" }),
214388
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-hint", children: "Flip the switch to review this session for assumptions, unverified claims, and dependency/license risk each time the agent hands control back to you." })
214389
+ ] }),
214390
+ enabled && items.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-empty", children: [
214391
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(EyeIcon, { size: 26 }) }),
214392
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-title", children: "Nothing yet" }),
214393
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-hint", children: "Reviews run when the agent finishes a turn. Results land here." })
214394
+ ] }),
214395
+ enabled && items.map((item) => {
214396
+ if (item.kind === "finding") return /* @__PURE__ */ jsxRuntimeExports.jsx(FindingCard, { item }, item.id);
214397
+ if (item.kind === "digest") return /* @__PURE__ */ jsxRuntimeExports.jsx(DigestCard, { item }, item.id);
214398
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `obs-line ${item.kind}`, children: [
214399
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-line-dot", "aria-hidden": "true" }),
214400
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-line-text", children: item.title }),
214401
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "obs-line-time", children: formatTime(item.ts) })
214402
+ ] }, item.id);
214403
+ })
214404
+ ] }),
214405
+ snapshot && enabled && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-drawer-footer", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ticket-drawer-hint", children: [
214406
+ findings.length,
214407
+ " finding",
214408
+ findings.length === 1 ? "" : "s",
214409
+ " · $",
214410
+ snapshot.spentTodayUsd.toFixed(2),
214411
+ " spent today"
214412
+ ] }) })
214413
+ ] });
214414
+ }
214089
214415
  const DEFAULT_LAYOUT = {
214090
214416
  type: "split",
214091
214417
  direction: "horizontal",
@@ -214438,7 +214764,8 @@ function App() {
214438
214764
  ] })
214439
214765
  },
214440
214766
  { id: "ctlsurf", label: "ctlsurf", content: /* @__PURE__ */ jsxRuntimeExports.jsx(CtlsurfPanel, { navigate: ctlsurfNav }) },
214441
- { id: "tickets", label: "Tickets", content: /* @__PURE__ */ jsxRuntimeExports.jsx(TicketPane, { onSendToTerminal: handleSendToTerminal }) }
214767
+ { id: "tickets", label: "Tickets", content: /* @__PURE__ */ jsxRuntimeExports.jsx(TicketPane, { onSendToTerminal: handleSendToTerminal }) },
214768
+ { id: "observer", label: "Observer", content: /* @__PURE__ */ jsxRuntimeExports.jsx(ObserverPane, {}) }
214442
214769
  ];
214443
214770
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "app", children: [
214444
214771
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "titlebar", children: [
@@ -214495,6 +214822,36 @@ function App() {
214495
214822
  ]
214496
214823
  }
214497
214824
  ),
214825
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
214826
+ "button",
214827
+ {
214828
+ className: `titlebar-btn titlebar-icon-btn ${visiblePaneIds.includes("observer") ? "active" : ""}`,
214829
+ onClick: () => togglePane("observer"),
214830
+ title: "Toggle Observer pane — live session review",
214831
+ "aria-label": "Observer",
214832
+ children: [
214833
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
214834
+ "svg",
214835
+ {
214836
+ viewBox: "0 0 24 24",
214837
+ width: "13",
214838
+ height: "13",
214839
+ fill: "none",
214840
+ stroke: "currentColor",
214841
+ strokeWidth: "2",
214842
+ strokeLinecap: "round",
214843
+ strokeLinejoin: "round",
214844
+ "aria-hidden": "true",
214845
+ children: [
214846
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
214847
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3" })
214848
+ ]
214849
+ }
214850
+ ),
214851
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Observer" })
214852
+ ]
214853
+ }
214854
+ ),
214498
214855
  /* @__PURE__ */ jsxRuntimeExports.jsx(
214499
214856
  "button",
214500
214857
  {