@phenx-inc/ctlsurf 0.12.0 → 0.12.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 (30) hide show
  1. package/out/headless/index.mjs +5 -1
  2. package/out/headless/index.mjs.map +2 -2
  3. package/out/main/index.js +5 -1
  4. package/out/renderer/assets/{cssMode-R8fTFLae.js → cssMode-D7r66wvO.js} +3 -3
  5. package/out/renderer/assets/{freemarker2-CyjWzWoP.js → freemarker2-jSWJIjPG.js} +1 -1
  6. package/out/renderer/assets/{handlebars-CrhCGIRM.js → handlebars-BnFyz5RH.js} +1 -1
  7. package/out/renderer/assets/{html-Cc3dPNZr.js → html-Bl5UFavp.js} +1 -1
  8. package/out/renderer/assets/{htmlMode-BWtG6ywk.js → htmlMode-D4VByBT6.js} +3 -3
  9. package/out/renderer/assets/{index-BL9njXIL.css → index-Cc_TqOCL.css} +117 -0
  10. package/out/renderer/assets/{index-kkG56aKv.js → index-DxhW1emk.js} +173 -73
  11. package/out/renderer/assets/{javascript-C8T_SdLC.js → javascript-CMN1OmwG.js} +2 -2
  12. package/out/renderer/assets/{jsonMode-D1zR4VVU.js → jsonMode-CJ5AYSPV.js} +3 -3
  13. package/out/renderer/assets/{liquid-COSMe9Uf.js → liquid-BGMIDTEm.js} +1 -1
  14. package/out/renderer/assets/{lspLanguageFeatures-CXGfrtzl.js → lspLanguageFeatures-DGifVYB5.js} +1 -1
  15. package/out/renderer/assets/{mdx-RfS44T-L.js → mdx-B2Z7R10Q.js} +1 -1
  16. package/out/renderer/assets/{python-DFSWKHUu.js → python-LMDMSSdn.js} +1 -1
  17. package/out/renderer/assets/{razor-DtH2_uvo.js → razor-BZSrziPu.js} +1 -1
  18. package/out/renderer/assets/{tsMode-BYIQ-S9Z.js → tsMode-DF9m6_3n.js} +1 -1
  19. package/out/renderer/assets/{typescript-HhQUr1Rb.js → typescript-rZeCMf0a.js} +1 -1
  20. package/out/renderer/assets/{xml-KuhgdKfD.js → xml-fNSZ-7so.js} +1 -1
  21. package/out/renderer/assets/{yaml-W_kzCFH7.js → yaml-1wxIuvzh.js} +1 -1
  22. package/out/renderer/index.html +2 -2
  23. package/package.json +1 -1
  24. package/src/main/index.ts +4 -1
  25. package/src/main/orchestrator.ts +7 -0
  26. package/src/renderer/App.tsx +5 -1
  27. package/src/renderer/components/SpeakControls.tsx +8 -2
  28. package/src/renderer/components/TerminalPanel.tsx +134 -23
  29. package/src/renderer/components/TicketPanel.tsx +67 -26
  30. package/src/renderer/styles.css +117 -0
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-R8fTFLae.js","./lspLanguageFeatures-CXGfrtzl.js","./htmlMode-BWtG6ywk.js","./jsonMode-D1zR4VVU.js","./javascript-C8T_SdLC.js","./typescript-HhQUr1Rb.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-D7r66wvO.js","./lspLanguageFeatures-DGifVYB5.js","./htmlMode-D4VByBT6.js","./jsonMode-CJ5AYSPV.js","./javascript-CMN1OmwG.js","./typescript-rZeCMf0a.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
  }
@@ -18851,14 +18851,34 @@ function handleTerminalLink(_event, uri) {
18851
18851
  const _terminals = /* @__PURE__ */ new Map();
18852
18852
  function isAtBottom(terminal) {
18853
18853
  const buf = terminal.buffer.active;
18854
- return buf.viewportY >= buf.baseY;
18854
+ return buf.baseY - buf.viewportY <= 2;
18855
18855
  }
18856
- function scrollIfPinned(tabId, terminal) {
18857
- const state = _terminals.get(tabId);
18858
- if (state?.pinnedToBottom) {
18859
- terminal.scrollToBottom();
18856
+ function notifyPin(state) {
18857
+ state.pinListeners.forEach((fn) => fn(state.pinnedToBottom));
18858
+ }
18859
+ function setPinned(state, pinned) {
18860
+ if (pinned) state.anchorLine = null;
18861
+ if (state.pinnedToBottom === pinned) return;
18862
+ state.pinnedToBottom = pinned;
18863
+ notifyPin(state);
18864
+ }
18865
+ function reassert(state) {
18866
+ const { terminal } = state;
18867
+ state.holding = true;
18868
+ try {
18869
+ if (state.pinnedToBottom) {
18870
+ terminal.scrollToBottom();
18871
+ } else if (state.anchorLine != null && terminal.buffer.active.viewportY !== state.anchorLine) {
18872
+ terminal.scrollToLine(state.anchorLine);
18873
+ }
18874
+ } finally {
18875
+ state.holding = false;
18860
18876
  }
18861
18877
  }
18878
+ function markGesture(tabId) {
18879
+ const s = _terminals.get(tabId);
18880
+ if (s) s.userScrollPending = true;
18881
+ }
18862
18882
  function getOrCreateTerminal(tabId, onExit) {
18863
18883
  const existing = _terminals.get(tabId);
18864
18884
  if (existing) {
@@ -18902,6 +18922,9 @@ function getOrCreateTerminal(tabId, onExit) {
18902
18922
  terminal.loadAddon(new addonWebLinksExports.WebLinksAddon(handleTerminalLink));
18903
18923
  terminal.attachCustomKeyEventHandler((e) => {
18904
18924
  if (e.type !== "keydown") return true;
18925
+ if (e.key === "PageUp" || e.key === "PageDown" || e.key === "Home" || e.key === "End") {
18926
+ markGesture(tabId);
18927
+ }
18905
18928
  const isCombo = (e.metaKey || e.ctrlKey) && e.shiftKey && e.code === "KeyE";
18906
18929
  if (!isCombo) return true;
18907
18930
  e.preventDefault();
@@ -18914,20 +18937,34 @@ function getOrCreateTerminal(tabId, onExit) {
18914
18937
  unsubData: null,
18915
18938
  unsubExit: null,
18916
18939
  spawnedAgentId: null,
18917
- pinnedToBottom: true
18940
+ pinnedToBottom: true,
18941
+ anchorLine: null,
18942
+ userScrollPending: false,
18943
+ holding: false,
18944
+ pinListeners: /* @__PURE__ */ new Set()
18918
18945
  };
18919
18946
  terminal.onScroll(() => {
18920
- state.pinnedToBottom = isAtBottom(terminal);
18947
+ if (state.holding) return;
18948
+ if (!state.userScrollPending) {
18949
+ reassert(state);
18950
+ return;
18951
+ }
18952
+ state.userScrollPending = false;
18953
+ if (isAtBottom(terminal)) {
18954
+ setPinned(state, true);
18955
+ } else {
18956
+ state.anchorLine = terminal.buffer.active.viewportY;
18957
+ setPinned(state, false);
18958
+ }
18921
18959
  });
18922
18960
  terminal.onData((data) => {
18923
- state.pinnedToBottom = true;
18961
+ setPinned(state, true);
18924
18962
  terminal.scrollToBottom();
18925
18963
  window.worker.writePty(tabId, data);
18926
18964
  });
18927
18965
  state.unsubData = window.worker.onPtyData((eventTabId, data) => {
18928
18966
  if (eventTabId === tabId) {
18929
- terminal.write(data);
18930
- scrollIfPinned(tabId, terminal);
18967
+ terminal.write(data, () => reassert(state));
18931
18968
  }
18932
18969
  });
18933
18970
  state.unsubExit = window.worker.onPtyExit((eventTabId, code) => {
@@ -18955,6 +18992,14 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
18955
18992
  const containerRef = reactExports.useRef(null);
18956
18993
  const [menu, setMenu] = reactExports.useState(null);
18957
18994
  const [toast, setToast] = reactExports.useState(null);
18995
+ const [followBottom, setFollowBottom] = reactExports.useState(true);
18996
+ const jumpToLatest = () => {
18997
+ const s = _terminals.get(tabId);
18998
+ if (!s) return;
18999
+ setPinned(s, true);
19000
+ s.terminal.scrollToBottom();
19001
+ s.terminal.focus();
19002
+ };
18958
19003
  const handleContextMenu = (e) => {
18959
19004
  const sel = _terminals.get(tabId)?.terminal.getSelection() ?? "";
18960
19005
  if (!convertToEmailTable(sel)) return;
@@ -19006,7 +19051,10 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
19006
19051
  terminal.open(containerRef.current);
19007
19052
  }
19008
19053
  fitAddon.fit();
19009
- scrollIfPinned(tabId, terminal);
19054
+ const attached = _terminals.get(tabId);
19055
+ if (attached) reassert(attached);
19056
+ const onWheel = () => markGesture(tabId);
19057
+ terminal.element?.addEventListener("wheel", onWheel, { passive: true });
19010
19058
  let resizeTimeout;
19011
19059
  const handleResize = () => {
19012
19060
  clearTimeout(resizeTimeout);
@@ -19018,7 +19066,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
19018
19066
  state.fitAddon.fit();
19019
19067
  const { cols, rows } = state.terminal;
19020
19068
  if (cols < 10 || rows < 5) return;
19021
- scrollIfPinned(tabId, state.terminal);
19069
+ reassert(state);
19022
19070
  window.worker.resizePty(tabId, cols, rows);
19023
19071
  }, 150);
19024
19072
  };
@@ -19029,6 +19077,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
19029
19077
  clearTimeout(resizeTimeout);
19030
19078
  window.removeEventListener("resize", handleResize);
19031
19079
  observer.disconnect();
19080
+ terminal.element?.removeEventListener("wheel", onWheel);
19032
19081
  };
19033
19082
  }, [tabId, onExit]);
19034
19083
  reactExports.useEffect(() => {
@@ -19042,7 +19091,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
19042
19091
  const s = _terminals.get(tabId);
19043
19092
  if (s) {
19044
19093
  s.fitAddon.fit();
19045
- s.pinnedToBottom = true;
19094
+ setPinned(s, true);
19046
19095
  s.terminal.scrollToBottom();
19047
19096
  const { cols, rows } = s.terminal;
19048
19097
  window.worker.resizePty(tabId, cols, rows);
@@ -19059,7 +19108,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
19059
19108
  if (state) {
19060
19109
  state.fitAddon.fit();
19061
19110
  state.terminal.focus();
19062
- scrollIfPinned(tabId, state.terminal);
19111
+ reassert(state);
19063
19112
  const { cols, rows } = state.terminal;
19064
19113
  window.worker.resizePty(tabId, cols, rows);
19065
19114
  }
@@ -19067,8 +19116,33 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
19067
19116
  });
19068
19117
  }
19069
19118
  }, [isActive, tabId]);
19119
+ reactExports.useEffect(() => {
19120
+ const s = _terminals.get(tabId);
19121
+ if (!s) return;
19122
+ setFollowBottom(s.pinnedToBottom);
19123
+ const fn = (p) => setFollowBottom(p);
19124
+ s.pinListeners.add(fn);
19125
+ return () => {
19126
+ s.pinListeners.delete(fn);
19127
+ };
19128
+ }, [tabId]);
19070
19129
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
19071
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "terminal-container", ref: containerRef, onContextMenu: handleContextMenu }),
19130
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "terminal-wrap", children: [
19131
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "terminal-container", ref: containerRef, onContextMenu: handleContextMenu }),
19132
+ !followBottom && /* @__PURE__ */ jsxRuntimeExports.jsx(
19133
+ "button",
19134
+ {
19135
+ type: "button",
19136
+ className: "term-jump-latest",
19137
+ onMouseDown: (e) => {
19138
+ e.preventDefault();
19139
+ jumpToLatest();
19140
+ },
19141
+ title: "Jump to latest output",
19142
+ children: "↓ Latest"
19143
+ }
19144
+ )
19145
+ ] }),
19072
19146
  menu && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "term-context-menu", style: { position: "fixed", left: menu.x, top: menu.y }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onMouseDown: (e) => {
19073
19147
  e.preventDefault();
19074
19148
  runConvert();
@@ -20022,7 +20096,7 @@ function FloatingMic({ onTranscript, onHide }) {
20022
20096
  ] });
20023
20097
  }
20024
20098
  const SAMPLE = "This is how spoken agent replies will sound.";
20025
- function SpeakControls() {
20099
+ function SpeakControls({ remote = false }) {
20026
20100
  const [enabled, setEnabled] = reactExports.useState(false);
20027
20101
  const [engine, setEngineState] = reactExports.useState(getEngine);
20028
20102
  const [voices, setVoices] = reactExports.useState([]);
@@ -20114,7 +20188,7 @@ function SpeakControls() {
20114
20188
  speech.stop();
20115
20189
  speech.enqueue(SAMPLE);
20116
20190
  }, []);
20117
- const title = enabled ? "Spoken replies on — click to mute" : "Speak agent replies (off)";
20191
+ const title = remote ? "Spoken replies aren't available for remote SSH sessions — the agent's transcript lives on the remote machine" : enabled ? "Spoken replies on — click to mute" : "Speak agent replies (off)";
20118
20192
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "speak-controls", ref: wrapRef, children: [
20119
20193
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
20120
20194
  "button",
@@ -20123,6 +20197,7 @@ function SpeakControls() {
20123
20197
  className: `titlebar-btn titlebar-icon-btn speak-btn ${enabled ? "active" : ""}`,
20124
20198
  onClick: toggle,
20125
20199
  title,
20200
+ disabled: remote,
20126
20201
  "aria-label": "Toggle spoken agent replies",
20127
20202
  "aria-pressed": enabled,
20128
20203
  children: [
@@ -207841,7 +207916,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
207841
207916
  modeConfigurationDefault$2
207842
207917
  );
207843
207918
  function getMode$3() {
207844
- return __vitePreload(() => import("./cssMode-R8fTFLae.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
207919
+ return __vitePreload(() => import("./cssMode-D7r66wvO.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
207845
207920
  }
207846
207921
  languages.onLanguage("less", () => {
207847
207922
  getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
@@ -207946,7 +208021,7 @@ const razorLanguageService = registerHTMLLanguageService(
207946
208021
  );
207947
208022
  const razorDefaults = razorLanguageService.defaults;
207948
208023
  function getMode$2() {
207949
- return __vitePreload(() => import("./htmlMode-BWtG6ywk.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
208024
+ return __vitePreload(() => import("./htmlMode-D4VByBT6.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
207950
208025
  }
207951
208026
  function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
207952
208027
  const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
@@ -208030,7 +208105,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
208030
208105
  );
208031
208106
  const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
208032
208107
  function getMode$1() {
208033
- return __vitePreload(() => import("./jsonMode-D1zR4VVU.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208108
+ return __vitePreload(() => import("./jsonMode-CJ5AYSPV.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208034
208109
  }
208035
208110
  languages.register({
208036
208111
  id: "json",
@@ -208276,7 +208351,7 @@ const getJavaScriptWorker = () => {
208276
208351
  return getMode().then((mode) => mode.getJavaScriptWorker());
208277
208352
  };
208278
208353
  function getMode() {
208279
- return __vitePreload(() => import("./tsMode-BYIQ-S9Z.js"), true ? [] : void 0, import.meta.url);
208354
+ return __vitePreload(() => import("./tsMode-DF9m6_3n.js"), true ? [] : void 0, import.meta.url);
208280
208355
  }
208281
208356
  languages.onLanguage("typescript", () => {
208282
208357
  return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
@@ -208471,49 +208546,49 @@ registerLanguage({
208471
208546
  extensions: [".ftl", ".ftlh", ".ftlx"],
208472
208547
  aliases: ["FreeMarker2", "Apache FreeMarker2"],
208473
208548
  loader: () => {
208474
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208549
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208475
208550
  }
208476
208551
  });
208477
208552
  registerLanguage({
208478
208553
  id: "freemarker2.tag-angle.interpolation-dollar",
208479
208554
  aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
208480
208555
  loader: () => {
208481
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208556
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208482
208557
  }
208483
208558
  });
208484
208559
  registerLanguage({
208485
208560
  id: "freemarker2.tag-bracket.interpolation-dollar",
208486
208561
  aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
208487
208562
  loader: () => {
208488
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208563
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208489
208564
  }
208490
208565
  });
208491
208566
  registerLanguage({
208492
208567
  id: "freemarker2.tag-angle.interpolation-bracket",
208493
208568
  aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
208494
208569
  loader: () => {
208495
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208570
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208496
208571
  }
208497
208572
  });
208498
208573
  registerLanguage({
208499
208574
  id: "freemarker2.tag-bracket.interpolation-bracket",
208500
208575
  aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
208501
208576
  loader: () => {
208502
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208577
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208503
208578
  }
208504
208579
  });
208505
208580
  registerLanguage({
208506
208581
  id: "freemarker2.tag-auto.interpolation-dollar",
208507
208582
  aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
208508
208583
  loader: () => {
208509
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208584
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208510
208585
  }
208511
208586
  });
208512
208587
  registerLanguage({
208513
208588
  id: "freemarker2.tag-auto.interpolation-bracket",
208514
208589
  aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
208515
208590
  loader: () => {
208516
- return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208591
+ return __vitePreload(() => import("./freemarker2-jSWJIjPG.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208517
208592
  }
208518
208593
  });
208519
208594
  registerLanguage({
@@ -208534,7 +208609,7 @@ registerLanguage({
208534
208609
  extensions: [".handlebars", ".hbs"],
208535
208610
  aliases: ["Handlebars", "handlebars", "hbs"],
208536
208611
  mimetypes: ["text/x-handlebars-template"],
208537
- loader: () => __vitePreload(() => import("./handlebars-CrhCGIRM.js"), true ? [] : void 0, import.meta.url)
208612
+ loader: () => __vitePreload(() => import("./handlebars-BnFyz5RH.js"), true ? [] : void 0, import.meta.url)
208538
208613
  });
208539
208614
  registerLanguage({
208540
208615
  id: "hcl",
@@ -208547,7 +208622,7 @@ registerLanguage({
208547
208622
  extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
208548
208623
  aliases: ["HTML", "htm", "html", "xhtml"],
208549
208624
  mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
208550
- loader: () => __vitePreload(() => import("./html-Cc3dPNZr.js"), true ? [] : void 0, import.meta.url)
208625
+ loader: () => __vitePreload(() => import("./html-Bl5UFavp.js"), true ? [] : void 0, import.meta.url)
208551
208626
  });
208552
208627
  registerLanguage({
208553
208628
  id: "ini",
@@ -208570,7 +208645,7 @@ registerLanguage({
208570
208645
  filenames: ["jakefile"],
208571
208646
  aliases: ["JavaScript", "javascript", "js"],
208572
208647
  mimetypes: ["text/javascript"],
208573
- loader: () => __vitePreload(() => import("./javascript-C8T_SdLC.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208648
+ loader: () => __vitePreload(() => import("./javascript-CMN1OmwG.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208574
208649
  });
208575
208650
  registerLanguage({
208576
208651
  id: "julia",
@@ -208609,7 +208684,7 @@ registerLanguage({
208609
208684
  extensions: [".liquid", ".html.liquid"],
208610
208685
  aliases: ["Liquid", "liquid"],
208611
208686
  mimetypes: ["application/liquid"],
208612
- loader: () => __vitePreload(() => import("./liquid-COSMe9Uf.js"), true ? [] : void 0, import.meta.url)
208687
+ loader: () => __vitePreload(() => import("./liquid-BGMIDTEm.js"), true ? [] : void 0, import.meta.url)
208613
208688
  });
208614
208689
  registerLanguage({
208615
208690
  id: "m3",
@@ -208627,7 +208702,7 @@ registerLanguage({
208627
208702
  id: "mdx",
208628
208703
  extensions: [".mdx"],
208629
208704
  aliases: ["MDX", "mdx"],
208630
- loader: () => __vitePreload(() => import("./mdx-RfS44T-L.js"), true ? [] : void 0, import.meta.url)
208705
+ loader: () => __vitePreload(() => import("./mdx-B2Z7R10Q.js"), true ? [] : void 0, import.meta.url)
208631
208706
  });
208632
208707
  registerLanguage({
208633
208708
  id: "mips",
@@ -208726,7 +208801,7 @@ registerLanguage({
208726
208801
  extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
208727
208802
  aliases: ["Python", "py"],
208728
208803
  firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
208729
- loader: () => __vitePreload(() => import("./python-DFSWKHUu.js"), true ? [] : void 0, import.meta.url)
208804
+ loader: () => __vitePreload(() => import("./python-LMDMSSdn.js"), true ? [] : void 0, import.meta.url)
208730
208805
  });
208731
208806
  registerLanguage({
208732
208807
  id: "qsharp",
@@ -208745,7 +208820,7 @@ registerLanguage({
208745
208820
  extensions: [".cshtml"],
208746
208821
  aliases: ["Razor", "razor"],
208747
208822
  mimetypes: ["text/x-cshtml"],
208748
- loader: () => __vitePreload(() => import("./razor-DtH2_uvo.js"), true ? [] : void 0, import.meta.url)
208823
+ loader: () => __vitePreload(() => import("./razor-BZSrziPu.js"), true ? [] : void 0, import.meta.url)
208749
208824
  });
208750
208825
  registerLanguage({
208751
208826
  id: "redis",
@@ -208878,7 +208953,7 @@ registerLanguage({
208878
208953
  aliases: ["TypeScript", "ts", "typescript"],
208879
208954
  mimetypes: ["text/typescript"],
208880
208955
  loader: () => {
208881
- return __vitePreload(() => import("./typescript-HhQUr1Rb.js"), true ? [] : void 0, import.meta.url);
208956
+ return __vitePreload(() => import("./typescript-rZeCMf0a.js"), true ? [] : void 0, import.meta.url);
208882
208957
  }
208883
208958
  });
208884
208959
  registerLanguage({
@@ -208923,14 +208998,14 @@ registerLanguage({
208923
208998
  firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
208924
208999
  aliases: ["XML", "xml"],
208925
209000
  mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
208926
- loader: () => __vitePreload(() => import("./xml-KuhgdKfD.js"), true ? [] : void 0, import.meta.url)
209001
+ loader: () => __vitePreload(() => import("./xml-fNSZ-7so.js"), true ? [] : void 0, import.meta.url)
208927
209002
  });
208928
209003
  registerLanguage({
208929
209004
  id: "yaml",
208930
209005
  extensions: [".yaml", ".yml"],
208931
209006
  aliases: ["YAML", "yaml", "YML", "yml"],
208932
209007
  mimetypes: ["application/x-yaml", "text/x-yaml"],
208933
- loader: () => __vitePreload(() => import("./yaml-W_kzCFH7.js"), true ? [] : void 0, import.meta.url)
209008
+ loader: () => __vitePreload(() => import("./yaml-1wxIuvzh.js"), true ? [] : void 0, import.meta.url)
208934
209009
  });
208935
209010
  var __defProp = Object.defineProperty;
208936
209011
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -213462,12 +213537,36 @@ function Segmented({ options, value, onChange }) {
213462
213537
  );
213463
213538
  }) });
213464
213539
  }
213540
+ function TicketCard({ ticket, onClick }) {
213541
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ticket-card", onClick, children: [
213542
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-bar", style: { background: colorOf(STATUS_OPTIONS, ticket.status) } }),
213543
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card-main", children: [
213544
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-title", children: ticket.title || "Untitled" }),
213545
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card-meta", children: [
213546
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ticket-card-status", style: { color: colorOf(STATUS_OPTIONS, ticket.status) }, children: [
213547
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-seg-dot", style: { background: colorOf(STATUS_OPTIONS, ticket.status) } }),
213548
+ ticket.status
213549
+ ] }),
213550
+ ticket.created && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-date", children: formatDate(ticket.created) })
213551
+ ] })
213552
+ ] }),
213553
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
213554
+ "span",
213555
+ {
213556
+ className: "ticket-card-pri",
213557
+ style: { color: colorOf(PRIORITY_OPTIONS, ticket.priority), borderColor: `${colorOf(PRIORITY_OPTIONS, ticket.priority)}66` },
213558
+ children: ticket.priority
213559
+ }
213560
+ )
213561
+ ] });
213562
+ }
213465
213563
  function TicketPane() {
213466
213564
  const [project, setProject] = reactExports.useState(null);
213467
213565
  const [view, setView] = reactExports.useState("list");
213468
213566
  const [tickets, setTickets] = reactExports.useState([]);
213469
213567
  const [listLoading, setListLoading] = reactExports.useState(false);
213470
213568
  const [listError, setListError] = reactExports.useState(null);
213569
+ const [showDone, setShowDone] = reactExports.useState(false);
213471
213570
  const [editingId, setEditingId] = reactExports.useState(null);
213472
213571
  const [title, setTitle] = reactExports.useState("");
213473
213572
  const [description, setDescription] = reactExports.useState("");
@@ -213557,17 +213656,22 @@ function TicketPane() {
213557
213656
  window.addEventListener("keydown", onKey);
213558
213657
  return () => window.removeEventListener("keydown", onKey);
213559
213658
  }, [view, handleSave]);
213659
+ const activeTickets = tickets.filter((t) => t.status !== "Done");
213660
+ const doneTickets = tickets.filter((t) => t.status === "Done");
213560
213661
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-pane", role: "region", "aria-label": "Tickets", children: [
213561
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-drawer-header", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-heading", children: [
213562
- view === "form" ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-drawer-back", onClick: () => setView("list"), title: "Back (Esc)", children: "‹" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-badge", children: /* @__PURE__ */ jsxRuntimeExports.jsx(TagIcon, { size: 16 }) }),
213563
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-headtext", children: [
213564
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-title", children: view === "form" ? editingId ? "Edit ticket" : "New ticket" : "Tickets" }),
213565
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-subtitle", children: project ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
213566
- "in ",
213567
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: project })
213568
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-warn", children: "no ctlsurf project for this tab" }) })
213569
- ] })
213570
- ] }) }),
213662
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-header", children: [
213663
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-heading", children: [
213664
+ view === "form" ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-drawer-back", onClick: () => setView("list"), title: "Back (Esc)", children: "‹" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-badge", children: /* @__PURE__ */ jsxRuntimeExports.jsx(TagIcon, { size: 16 }) }),
213665
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-headtext", children: [
213666
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-title", children: view === "form" ? editingId ? "Edit ticket" : "New ticket" : "Tickets" }),
213667
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-subtitle", children: project ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
213668
+ "in ",
213669
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: project })
213670
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-warn", children: "no ctlsurf project for this tab" }) })
213671
+ ] })
213672
+ ] }),
213673
+ view === "list" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-drawer-new", onClick: openNewForm, title: "New ticket", children: "+ New" })
213674
+ ] }),
213571
213675
  view === "list" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
213572
213676
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-list-body", children: [
213573
213677
  listLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-list-msg", children: "Loading tickets…" }),
@@ -213580,32 +213684,27 @@ function TicketPane() {
213580
213684
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-title", children: "No tickets yet" }),
213581
213685
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-hint", children: "Log the first one for this project." })
213582
213686
  ] }),
213583
- !listLoading && tickets.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ticket-card", onClick: () => openEditForm(t), children: [
213584
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-bar", style: { background: colorOf(STATUS_OPTIONS, t.status) } }),
213585
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card-main", children: [
213586
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-title", children: t.title || "Untitled" }),
213587
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card-meta", children: [
213588
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ticket-card-status", style: { color: colorOf(STATUS_OPTIONS, t.status) }, children: [
213589
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-seg-dot", style: { background: colorOf(STATUS_OPTIONS, t.status) } }),
213590
- t.status
213591
- ] }),
213592
- t.created && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-date", children: formatDate(t.created) })
213593
- ] })
213594
- ] }),
213595
- /* @__PURE__ */ jsxRuntimeExports.jsx(
213596
- "span",
213687
+ !listLoading && activeTickets.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsx(TicketCard, { ticket: t, onClick: () => openEditForm(t) }, t.id)),
213688
+ !listLoading && activeTickets.length === 0 && doneTickets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-list-msg", children: "Nothing open — all caught up." }),
213689
+ !listLoading && doneTickets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
213690
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
213691
+ "button",
213597
213692
  {
213598
- className: "ticket-card-pri",
213599
- style: { color: colorOf(PRIORITY_OPTIONS, t.priority), borderColor: `${colorOf(PRIORITY_OPTIONS, t.priority)}66` },
213600
- children: t.priority
213693
+ type: "button",
213694
+ className: "ticket-done-toggle",
213695
+ onClick: () => setShowDone((v2) => !v2),
213696
+ "aria-expanded": showDone,
213697
+ children: [
213698
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `ticket-done-caret ${showDone ? "open" : ""}`, "aria-hidden": "true", children: "▸" }),
213699
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-done-label", children: "Done" }),
213700
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-done-count", children: doneTickets.length })
213701
+ ]
213601
213702
  }
213602
- )
213603
- ] }, t.id))
213703
+ ),
213704
+ showDone && doneTickets.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsx(TicketCard, { ticket: t, onClick: () => openEditForm(t) }, t.id))
213705
+ ] })
213604
213706
  ] }),
213605
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-footer", children: [
213606
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-hint", children: tickets.length > 0 && `${tickets.length} ticket${tickets.length === 1 ? "" : "s"}` }),
213607
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-btn-primary", onClick: openNewForm, children: "+ New ticket" })
213608
- ] })
213707
+ tickets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-drawer-footer", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-hint", children: doneTickets.length > 0 ? `${activeTickets.length} open · ${doneTickets.length} done` : `${tickets.length} ticket${tickets.length === 1 ? "" : "s"}` }) })
213609
213708
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
213610
213709
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-body", children: [
213611
213710
  /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ticket-field", children: [
@@ -213950,6 +214049,7 @@ function App() {
213950
214049
  window.addEventListener("ctlsurf-open-url", onOpen);
213951
214050
  return () => window.removeEventListener("ctlsurf-open-url", onOpen);
213952
214051
  }, [layout2, togglePane]);
214052
+ const activeAgentIsRemote = !!tabs.find((t) => t.id === activeTabId)?.agent?.id?.startsWith("remote-");
213953
214053
  const panes = [
213954
214054
  { id: "editor", label: "Editor", content: /* @__PURE__ */ jsxRuntimeExports.jsx(EditorPanel, { cwd: cwd2 }) },
213955
214055
  {
@@ -214095,7 +214195,7 @@ function App() {
214095
214195
  )
214096
214196
  }
214097
214197
  ),
214098
- /* @__PURE__ */ jsxRuntimeExports.jsx(SpeakControls, {}),
214198
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SpeakControls, { remote: activeAgentIsRemote }),
214099
214199
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "titlebar-separator" }),
214100
214200
  agents.map((a) => {
214101
214201
  const activeTab = tabs.find((t) => t.id === activeTabId);
@@ -1,5 +1,5 @@
1
- import { conf as conf$1, language as language$1 } from "./typescript-HhQUr1Rb.js";
2
- import "./index-kkG56aKv.js";
1
+ import { conf as conf$1, language as language$1 } from "./typescript-rZeCMf0a.js";
2
+ import "./index-DxhW1emk.js";
3
3
  const conf = conf$1;
4
4
  const language = {
5
5
  // Set defaultToken to invalid to see what you do not tokenize yet
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages, e as editor } from "./index-kkG56aKv.js";
2
- import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-CXGfrtzl.js";
3
- import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-CXGfrtzl.js";
1
+ import { c as createWebWorker, l as languages, e as editor } from "./index-DxhW1emk.js";
2
+ import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-DGifVYB5.js";
3
+ import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-DGifVYB5.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-kkG56aKv.js";
1
+ import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-DxhW1emk.js";
2
2
  var DocumentUri;
3
3
  (function(DocumentUri2) {
4
4
  function is(value) {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  blockComment: ["{/*", "*/}"]
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  lineComment: "#",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-kkG56aKv.js";
1
+ import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-DxhW1emk.js";
2
2
  class WorkerManager {
3
3
  constructor(_modeId, _defaults) {
4
4
  this._modeId = _modeId;
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const conf = {
3
3
  wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
4
4
  comments: {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  blockComment: ["<!--", "-->"]
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-kkG56aKv.js";
1
+ import { l as languages } from "./index-DxhW1emk.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  lineComment: "#"
@@ -49,8 +49,8 @@
49
49
  color: #565f89;
50
50
  }
51
51
  </style>
52
- <script type="module" crossorigin src="./assets/index-kkG56aKv.js"></script>
53
- <link rel="stylesheet" crossorigin href="./assets/index-BL9njXIL.css">
52
+ <script type="module" crossorigin src="./assets/index-DxhW1emk.js"></script>
53
+ <link rel="stylesheet" crossorigin href="./assets/index-Cc_TqOCL.css">
54
54
  </head>
55
55
  <body>
56
56
  <div id="boot-splash">