@phenx-inc/ctlsurf 0.13.5 → 0.13.6

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 (26) hide show
  1. package/out/headless/index.mjs +1 -1
  2. package/out/headless/index.mjs.map +1 -1
  3. package/out/main/index.js +12 -4
  4. package/out/preload/index.js +2 -0
  5. package/out/renderer/assets/{cssMode-CAEObGNt.js → cssMode-CsSLnKZ-.js} +3 -3
  6. package/out/renderer/assets/{freemarker2-D63hnnDq.js → freemarker2-C1XYRbOq.js} +1 -1
  7. package/out/renderer/assets/{handlebars-UYo_IYpi.js → handlebars-BSdbbnMW.js} +1 -1
  8. package/out/renderer/assets/{html-2dvYDi3g.js → html-96igtyOz.js} +1 -1
  9. package/out/renderer/assets/{htmlMode-B6fxDDPF.js → htmlMode-BRnCcIzp.js} +3 -3
  10. package/out/renderer/assets/{index-CMb4AqkZ.js → index-Cc-jDHm3.js} +44 -28
  11. package/out/renderer/assets/{javascript-8RyFDDdk.js → javascript-7MdRNHk9.js} +2 -2
  12. package/out/renderer/assets/{jsonMode-CqspkWCb.js → jsonMode-oGam2go_.js} +3 -3
  13. package/out/renderer/assets/{liquid-DaEnAsYY.js → liquid-DoKC7ba2.js} +1 -1
  14. package/out/renderer/assets/{lspLanguageFeatures-Czkp5sZb.js → lspLanguageFeatures-C2h5qGCv.js} +1 -1
  15. package/out/renderer/assets/{mdx-Q-qSZsFg.js → mdx-0w8n1HGo.js} +1 -1
  16. package/out/renderer/assets/{python-Sw0S0BJV.js → python-BfY4HssB.js} +1 -1
  17. package/out/renderer/assets/{razor-C7zQmabz.js → razor-BoDk9Ula.js} +1 -1
  18. package/out/renderer/assets/{tsMode-BWdOxk6v.js → tsMode-CX0oVKRt.js} +1 -1
  19. package/out/renderer/assets/{typescript-BrdIiKZf.js → typescript-BqIU7abP.js} +1 -1
  20. package/out/renderer/assets/{xml-DbKLNPOq.js → xml-BlSDnxFw.js} +1 -1
  21. package/out/renderer/assets/{yaml-ehupJBsZ.js → yaml-bVMmGUtU.js} +1 -1
  22. package/out/renderer/index.html +1 -1
  23. package/package.json +1 -1
  24. package/src/main/index.ts +19 -6
  25. package/src/preload/index.ts +4 -2
  26. package/src/renderer/components/TerminalPanel.tsx +28 -5
package/out/main/index.js CHANGED
@@ -12312,12 +12312,20 @@ function createWindow() {
12312
12312
  });
12313
12313
  }
12314
12314
  electron.ipcMain.handle("clipboard:writeTable", (_event, html, text) => {
12315
- electron.clipboard.write({ html, text });
12316
- return { ok: true };
12315
+ try {
12316
+ electron.clipboard.write({ html, text });
12317
+ return { ok: electron.clipboard.readText() === text };
12318
+ } catch (err) {
12319
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
12320
+ }
12317
12321
  });
12318
12322
  electron.ipcMain.handle("clipboard:writeText", (_event, text) => {
12319
- electron.clipboard.writeText(text);
12320
- return { ok: true };
12323
+ try {
12324
+ electron.clipboard.writeText(text);
12325
+ return { ok: electron.clipboard.readText() === text };
12326
+ } catch (err) {
12327
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
12328
+ }
12321
12329
  });
12322
12330
  electron.ipcMain.handle("pty:spawn", async (_event, tabId, agent, cwd) => {
12323
12331
  await orchestrator.spawnAgent(tabId, agent, cwd);
@@ -41,6 +41,8 @@ const api = {
41
41
  },
42
42
  browseCwd: () => electron.ipcRenderer.invoke("app:browseCwd"),
43
43
  // Clipboard — write a rich-HTML table (+ plain-text fallback) for email paste.
44
+ // `ok` reflects a read-back verification in the main process, not just that the
45
+ // call was made; `error` is set when the write threw.
44
46
  copyEmailTable: (html, text) => electron.ipcRenderer.invoke("clipboard:writeTable", html, text),
45
47
  copyText: (text) => electron.ipcRenderer.invoke("clipboard:writeText", text),
46
48
  getVersion: () => electron.ipcRenderer.invoke("app:getVersion"),
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages } from "./index-CMb4AqkZ.js";
2
- import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-Czkp5sZb.js";
3
- import { h, i, j, t, k } from "./lspLanguageFeatures-Czkp5sZb.js";
1
+ import { c as createWebWorker, l as languages } from "./index-Cc-jDHm3.js";
2
+ import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-C2h5qGCv.js";
3
+ import { h, i, j, t, k } from "./lspLanguageFeatures-C2h5qGCv.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-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "assign",
4
4
  "flush",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages } from "./index-CMb4AqkZ.js";
2
- import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-Czkp5sZb.js";
3
- import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-Czkp5sZb.js";
1
+ import { c as createWebWorker, l as languages } from "./index-Cc-jDHm3.js";
2
+ import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-C2h5qGCv.js";
3
+ import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-C2h5qGCv.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-CAEObGNt.js","./lspLanguageFeatures-Czkp5sZb.js","./htmlMode-B6fxDDPF.js","./jsonMode-CqspkWCb.js","./javascript-8RyFDDdk.js","./typescript-BrdIiKZf.js"])))=>i.map(i=>d[i]);
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]);
2
2
  function getDefaultExportFromCjs(x) {
3
3
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
4
4
  }
@@ -19189,17 +19189,33 @@ function showTerminalToast(message) {
19189
19189
  }
19190
19190
  function copyTextValue(text2) {
19191
19191
  if (!text2) return;
19192
- void window.worker.copyText(text2);
19193
- showTerminalToast("Copied to clipboard");
19192
+ void window.worker.copyText(text2).then((res) => {
19193
+ if (res?.ok) showTerminalToast("Copied to clipboard");
19194
+ else {
19195
+ showTerminalToast("Copy failed — clipboard not updated");
19196
+ console.warn("[copy] clipboard write not verified", res);
19197
+ }
19198
+ }).catch((err) => {
19199
+ showTerminalToast("Copy failed");
19200
+ console.warn("[copy] clipboard write threw", err);
19201
+ });
19194
19202
  }
19195
19203
  function convertTextToTable(text2) {
19196
19204
  const result = convertToEmailTable(text2);
19197
- if (result) {
19198
- window.worker.copyEmailTable(result.html, result.text);
19199
- showTerminalToast(`Copied ${result.rows}×${result.cols} table to clipboard`);
19200
- } else {
19205
+ if (!result) {
19201
19206
  showTerminalToast("No table found in selection");
19207
+ return;
19202
19208
  }
19209
+ void window.worker.copyEmailTable(result.html, result.text).then((res) => {
19210
+ if (res?.ok) showTerminalToast(`Copied ${result.rows}×${result.cols} table to clipboard`);
19211
+ else {
19212
+ showTerminalToast("Copy failed — clipboard not updated");
19213
+ console.warn("[copy] table clipboard write not verified", res);
19214
+ }
19215
+ }).catch((err) => {
19216
+ showTerminalToast("Copy failed");
19217
+ console.warn("[copy] table clipboard write threw", err);
19218
+ });
19203
19219
  }
19204
19220
  function speakTextValue(text2) {
19205
19221
  if (!text2.trim()) return;
@@ -208151,7 +208167,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
208151
208167
  modeConfigurationDefault$2
208152
208168
  );
208153
208169
  function getMode$3() {
208154
- return __vitePreload(() => import("./cssMode-CAEObGNt.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
208170
+ return __vitePreload(() => import("./cssMode-CsSLnKZ-.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
208155
208171
  }
208156
208172
  languages.onLanguage("less", () => {
208157
208173
  getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
@@ -208256,7 +208272,7 @@ const razorLanguageService = registerHTMLLanguageService(
208256
208272
  );
208257
208273
  const razorDefaults = razorLanguageService.defaults;
208258
208274
  function getMode$2() {
208259
- return __vitePreload(() => import("./htmlMode-B6fxDDPF.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
208275
+ return __vitePreload(() => import("./htmlMode-BRnCcIzp.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
208260
208276
  }
208261
208277
  function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
208262
208278
  const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
@@ -208340,7 +208356,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
208340
208356
  );
208341
208357
  const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
208342
208358
  function getMode$1() {
208343
- return __vitePreload(() => import("./jsonMode-CqspkWCb.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208359
+ return __vitePreload(() => import("./jsonMode-oGam2go_.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208344
208360
  }
208345
208361
  languages.register({
208346
208362
  id: "json",
@@ -208586,7 +208602,7 @@ const getJavaScriptWorker = () => {
208586
208602
  return getMode().then((mode) => mode.getJavaScriptWorker());
208587
208603
  };
208588
208604
  function getMode() {
208589
- return __vitePreload(() => import("./tsMode-BWdOxk6v.js"), true ? [] : void 0, import.meta.url);
208605
+ return __vitePreload(() => import("./tsMode-CX0oVKRt.js"), true ? [] : void 0, import.meta.url);
208590
208606
  }
208591
208607
  languages.onLanguage("typescript", () => {
208592
208608
  return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
@@ -208781,49 +208797,49 @@ registerLanguage({
208781
208797
  extensions: [".ftl", ".ftlh", ".ftlx"],
208782
208798
  aliases: ["FreeMarker2", "Apache FreeMarker2"],
208783
208799
  loader: () => {
208784
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208800
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208785
208801
  }
208786
208802
  });
208787
208803
  registerLanguage({
208788
208804
  id: "freemarker2.tag-angle.interpolation-dollar",
208789
208805
  aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
208790
208806
  loader: () => {
208791
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208807
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208792
208808
  }
208793
208809
  });
208794
208810
  registerLanguage({
208795
208811
  id: "freemarker2.tag-bracket.interpolation-dollar",
208796
208812
  aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
208797
208813
  loader: () => {
208798
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208814
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208799
208815
  }
208800
208816
  });
208801
208817
  registerLanguage({
208802
208818
  id: "freemarker2.tag-angle.interpolation-bracket",
208803
208819
  aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
208804
208820
  loader: () => {
208805
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208821
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208806
208822
  }
208807
208823
  });
208808
208824
  registerLanguage({
208809
208825
  id: "freemarker2.tag-bracket.interpolation-bracket",
208810
208826
  aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
208811
208827
  loader: () => {
208812
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208828
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208813
208829
  }
208814
208830
  });
208815
208831
  registerLanguage({
208816
208832
  id: "freemarker2.tag-auto.interpolation-dollar",
208817
208833
  aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
208818
208834
  loader: () => {
208819
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208835
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208820
208836
  }
208821
208837
  });
208822
208838
  registerLanguage({
208823
208839
  id: "freemarker2.tag-auto.interpolation-bracket",
208824
208840
  aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
208825
208841
  loader: () => {
208826
- return __vitePreload(() => import("./freemarker2-D63hnnDq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208842
+ return __vitePreload(() => import("./freemarker2-C1XYRbOq.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208827
208843
  }
208828
208844
  });
208829
208845
  registerLanguage({
@@ -208844,7 +208860,7 @@ registerLanguage({
208844
208860
  extensions: [".handlebars", ".hbs"],
208845
208861
  aliases: ["Handlebars", "handlebars", "hbs"],
208846
208862
  mimetypes: ["text/x-handlebars-template"],
208847
- loader: () => __vitePreload(() => import("./handlebars-UYo_IYpi.js"), true ? [] : void 0, import.meta.url)
208863
+ loader: () => __vitePreload(() => import("./handlebars-BSdbbnMW.js"), true ? [] : void 0, import.meta.url)
208848
208864
  });
208849
208865
  registerLanguage({
208850
208866
  id: "hcl",
@@ -208857,7 +208873,7 @@ registerLanguage({
208857
208873
  extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
208858
208874
  aliases: ["HTML", "htm", "html", "xhtml"],
208859
208875
  mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
208860
- loader: () => __vitePreload(() => import("./html-2dvYDi3g.js"), true ? [] : void 0, import.meta.url)
208876
+ loader: () => __vitePreload(() => import("./html-96igtyOz.js"), true ? [] : void 0, import.meta.url)
208861
208877
  });
208862
208878
  registerLanguage({
208863
208879
  id: "ini",
@@ -208880,7 +208896,7 @@ registerLanguage({
208880
208896
  filenames: ["jakefile"],
208881
208897
  aliases: ["JavaScript", "javascript", "js"],
208882
208898
  mimetypes: ["text/javascript"],
208883
- loader: () => __vitePreload(() => import("./javascript-8RyFDDdk.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208899
+ loader: () => __vitePreload(() => import("./javascript-7MdRNHk9.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208884
208900
  });
208885
208901
  registerLanguage({
208886
208902
  id: "julia",
@@ -208919,7 +208935,7 @@ registerLanguage({
208919
208935
  extensions: [".liquid", ".html.liquid"],
208920
208936
  aliases: ["Liquid", "liquid"],
208921
208937
  mimetypes: ["application/liquid"],
208922
- loader: () => __vitePreload(() => import("./liquid-DaEnAsYY.js"), true ? [] : void 0, import.meta.url)
208938
+ loader: () => __vitePreload(() => import("./liquid-DoKC7ba2.js"), true ? [] : void 0, import.meta.url)
208923
208939
  });
208924
208940
  registerLanguage({
208925
208941
  id: "m3",
@@ -208937,7 +208953,7 @@ registerLanguage({
208937
208953
  id: "mdx",
208938
208954
  extensions: [".mdx"],
208939
208955
  aliases: ["MDX", "mdx"],
208940
- loader: () => __vitePreload(() => import("./mdx-Q-qSZsFg.js"), true ? [] : void 0, import.meta.url)
208956
+ loader: () => __vitePreload(() => import("./mdx-0w8n1HGo.js"), true ? [] : void 0, import.meta.url)
208941
208957
  });
208942
208958
  registerLanguage({
208943
208959
  id: "mips",
@@ -209036,7 +209052,7 @@ registerLanguage({
209036
209052
  extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
209037
209053
  aliases: ["Python", "py"],
209038
209054
  firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
209039
- loader: () => __vitePreload(() => import("./python-Sw0S0BJV.js"), true ? [] : void 0, import.meta.url)
209055
+ loader: () => __vitePreload(() => import("./python-BfY4HssB.js"), true ? [] : void 0, import.meta.url)
209040
209056
  });
209041
209057
  registerLanguage({
209042
209058
  id: "qsharp",
@@ -209055,7 +209071,7 @@ registerLanguage({
209055
209071
  extensions: [".cshtml"],
209056
209072
  aliases: ["Razor", "razor"],
209057
209073
  mimetypes: ["text/x-cshtml"],
209058
- loader: () => __vitePreload(() => import("./razor-C7zQmabz.js"), true ? [] : void 0, import.meta.url)
209074
+ loader: () => __vitePreload(() => import("./razor-BoDk9Ula.js"), true ? [] : void 0, import.meta.url)
209059
209075
  });
209060
209076
  registerLanguage({
209061
209077
  id: "redis",
@@ -209188,7 +209204,7 @@ registerLanguage({
209188
209204
  aliases: ["TypeScript", "ts", "typescript"],
209189
209205
  mimetypes: ["text/typescript"],
209190
209206
  loader: () => {
209191
- return __vitePreload(() => import("./typescript-BrdIiKZf.js"), true ? [] : void 0, import.meta.url);
209207
+ return __vitePreload(() => import("./typescript-BqIU7abP.js"), true ? [] : void 0, import.meta.url);
209192
209208
  }
209193
209209
  });
209194
209210
  registerLanguage({
@@ -209233,14 +209249,14 @@ registerLanguage({
209233
209249
  firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
209234
209250
  aliases: ["XML", "xml"],
209235
209251
  mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
209236
- loader: () => __vitePreload(() => import("./xml-DbKLNPOq.js"), true ? [] : void 0, import.meta.url)
209252
+ loader: () => __vitePreload(() => import("./xml-BlSDnxFw.js"), true ? [] : void 0, import.meta.url)
209237
209253
  });
209238
209254
  registerLanguage({
209239
209255
  id: "yaml",
209240
209256
  extensions: [".yaml", ".yml"],
209241
209257
  aliases: ["YAML", "yaml", "YML", "yml"],
209242
209258
  mimetypes: ["application/x-yaml", "text/x-yaml"],
209243
- loader: () => __vitePreload(() => import("./yaml-ehupJBsZ.js"), true ? [] : void 0, import.meta.url)
209259
+ loader: () => __vitePreload(() => import("./yaml-bVMmGUtU.js"), true ? [] : void 0, import.meta.url)
209244
209260
  });
209245
209261
  var __defProp = Object.defineProperty;
209246
209262
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -1,5 +1,5 @@
1
- import { conf as conf$1, language as language$1 } from "./typescript-BrdIiKZf.js";
2
- import "./index-CMb4AqkZ.js";
1
+ import { conf as conf$1, language as language$1 } from "./typescript-BqIU7abP.js";
2
+ import "./index-Cc-jDHm3.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-CMb4AqkZ.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-Czkp5sZb.js";
3
- import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-Czkp5sZb.js";
1
+ import { c as createWebWorker, l as languages, e as editor } from "./index-Cc-jDHm3.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-C2h5qGCv.js";
3
+ import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-C2h5qGCv.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-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.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-CMb4AqkZ.js";
1
+ import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-Cc-jDHm3.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-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  blockComment: ["{/*", "*/}"]
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  lineComment: "#",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.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-CMb4AqkZ.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-Cc-jDHm3.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-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.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-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  blockComment: ["<!--", "-->"]
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-CMb4AqkZ.js";
1
+ import { l as languages } from "./index-Cc-jDHm3.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  lineComment: "#"
@@ -49,7 +49,7 @@
49
49
  color: #565f89;
50
50
  }
51
51
  </style>
52
- <script type="module" crossorigin src="./assets/index-CMb4AqkZ.js"></script>
52
+ <script type="module" crossorigin src="./assets/index-Cc-jDHm3.js"></script>
53
53
  <link rel="stylesheet" crossorigin href="./assets/index-BEekQe3-.css">
54
54
  </head>
55
55
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phenx-inc/ctlsurf",
3
- "version": "0.13.5",
3
+ "version": "0.13.6",
4
4
  "description": "Agent-agnostic terminal and desktop app for ctlsurf — run Claude Code, Codex, or any coding agent with live session logging and remote control",
5
5
  "main": "out/main/index.js",
6
6
  "bin": {
package/src/main/index.ts CHANGED
@@ -283,16 +283,29 @@ function createWindow(): void {
283
283
  // ─── IPC Handlers ──────────────────────────────────
284
284
 
285
285
  // Write a rich-HTML table (plus plain-text fallback) to the clipboard so it
286
- // can be pasted as a formatted table into an email client.
286
+ // can be pasted as a formatted table into an email client. Verify the write
287
+ // landed by reading the plain-text side back — clipboard.write never throws on
288
+ // macOS even when the pasteboard write is dropped, so a read-back is the only
289
+ // reliable success signal.
287
290
  ipcMain.handle('clipboard:writeTable', (_event, html: string, text: string) => {
288
- clipboard.write({ html, text })
289
- return { ok: true }
291
+ try {
292
+ clipboard.write({ html, text })
293
+ return { ok: clipboard.readText() === text }
294
+ } catch (err) {
295
+ return { ok: false, error: err instanceof Error ? err.message : String(err) }
296
+ }
290
297
  })
291
298
 
292
- // Plain-text clipboard write, for the terminal right-click "Copy" item.
299
+ // Plain-text clipboard write, for the terminal right-click "Copy" item and the
300
+ // snapshot panel. Read the value back and report whether it actually stuck, so
301
+ // the renderer can show an honest toast instead of claiming success blindly.
293
302
  ipcMain.handle('clipboard:writeText', (_event, text: string) => {
294
- clipboard.writeText(text)
295
- return { ok: true }
303
+ try {
304
+ clipboard.writeText(text)
305
+ return { ok: clipboard.readText() === text }
306
+ } catch (err) {
307
+ return { ok: false, error: err instanceof Error ? err.message : String(err) }
308
+ }
296
309
  })
297
310
 
298
311
  ipcMain.handle('pty:spawn', async (_event, tabId: string, agent: AgentConfig, cwd: string) => {
@@ -81,9 +81,11 @@ const api = {
81
81
  ipcRenderer.invoke('app:browseCwd'),
82
82
 
83
83
  // Clipboard — write a rich-HTML table (+ plain-text fallback) for email paste.
84
- copyEmailTable: (html: string, text: string): Promise<{ ok: boolean }> =>
84
+ // `ok` reflects a read-back verification in the main process, not just that the
85
+ // call was made; `error` is set when the write threw.
86
+ copyEmailTable: (html: string, text: string): Promise<{ ok: boolean; error?: string }> =>
85
87
  ipcRenderer.invoke('clipboard:writeTable', html, text),
86
- copyText: (text: string): Promise<{ ok: boolean }> =>
88
+ copyText: (text: string): Promise<{ ok: boolean; error?: string }> =>
87
89
  ipcRenderer.invoke('clipboard:writeText', text),
88
90
  getVersion: (): Promise<string> =>
89
91
  ipcRenderer.invoke('app:getVersion'),
@@ -17,18 +17,41 @@ function showTerminalToast(message: string): void {
17
17
 
18
18
  function copyTextValue(text: string): void {
19
19
  if (!text) return
20
+ // Toast only after the main process confirms the write actually landed
21
+ // (read-back verified). A silent clipboard failure used to still show
22
+ // "Copied to clipboard", masking the problem.
20
23
  void window.worker.copyText(text)
21
- showTerminalToast('Copied to clipboard')
24
+ .then((res) => {
25
+ if (res?.ok) showTerminalToast('Copied to clipboard')
26
+ else {
27
+ showTerminalToast('Copy failed — clipboard not updated')
28
+ console.warn('[copy] clipboard write not verified', res)
29
+ }
30
+ })
31
+ .catch((err) => {
32
+ showTerminalToast('Copy failed')
33
+ console.warn('[copy] clipboard write threw', err)
34
+ })
22
35
  }
23
36
 
24
37
  function convertTextToTable(text: string): void {
25
38
  const result = convertToEmailTable(text)
26
- if (result) {
27
- window.worker.copyEmailTable(result.html, result.text)
28
- showTerminalToast(`Copied ${result.rows}×${result.cols} table to clipboard`)
29
- } else {
39
+ if (!result) {
30
40
  showTerminalToast('No table found in selection')
41
+ return
31
42
  }
43
+ void window.worker.copyEmailTable(result.html, result.text)
44
+ .then((res) => {
45
+ if (res?.ok) showTerminalToast(`Copied ${result.rows}×${result.cols} table to clipboard`)
46
+ else {
47
+ showTerminalToast('Copy failed — clipboard not updated')
48
+ console.warn('[copy] table clipboard write not verified', res)
49
+ }
50
+ })
51
+ .catch((err) => {
52
+ showTerminalToast('Copy failed')
53
+ console.warn('[copy] table clipboard write threw', err)
54
+ })
32
55
  }
33
56
 
34
57
  // unlock() is called from the triggering gesture so the neural voice isn't