@phenx-inc/ctlsurf 0.11.0 → 0.12.0

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 (35) hide show
  1. package/out/headless/index.mjs +111 -5
  2. package/out/headless/index.mjs.map +3 -3
  3. package/out/main/index.js +311 -7
  4. package/out/preload/index.js +9 -0
  5. package/out/renderer/assets/{cssMode-Bmzy9hKX.js → cssMode-R8fTFLae.js} +3 -3
  6. package/out/renderer/assets/{freemarker2-CDAsExTa.js → freemarker2-CyjWzWoP.js} +1 -1
  7. package/out/renderer/assets/{handlebars-CvpBYG1L.js → handlebars-CrhCGIRM.js} +1 -1
  8. package/out/renderer/assets/{html-CNhEQqr8.js → html-Cc3dPNZr.js} +1 -1
  9. package/out/renderer/assets/{htmlMode-DD7YPgga.js → htmlMode-BWtG6ywk.js} +3 -3
  10. package/out/renderer/assets/{index-CGHeDwZa.css → index-BL9njXIL.css} +201 -0
  11. package/out/renderer/assets/{index-BDlCPzCG.js → index-kkG56aKv.js} +407 -34
  12. package/out/renderer/assets/{javascript-CsGLsswK.js → javascript-C8T_SdLC.js} +2 -2
  13. package/out/renderer/assets/{jsonMode-CTuGgRvC.js → jsonMode-D1zR4VVU.js} +3 -3
  14. package/out/renderer/assets/{liquid-BrrN4uul.js → liquid-COSMe9Uf.js} +1 -1
  15. package/out/renderer/assets/{lspLanguageFeatures-Bhdn2Eqy.js → lspLanguageFeatures-CXGfrtzl.js} +1 -1
  16. package/out/renderer/assets/{mdx-DJo-gax4.js → mdx-RfS44T-L.js} +1 -1
  17. package/out/renderer/assets/{python-DYHeg5b2.js → python-DFSWKHUu.js} +1 -1
  18. package/out/renderer/assets/{razor-Cqcks14K.js → razor-DtH2_uvo.js} +1 -1
  19. package/out/renderer/assets/{tsMode-YTLgCayh.js → tsMode-BYIQ-S9Z.js} +1 -1
  20. package/out/renderer/assets/{typescript-oxBn_Vcw.js → typescript-HhQUr1Rb.js} +1 -1
  21. package/out/renderer/assets/{xml-BEqGMCTc.js → xml-KuhgdKfD.js} +1 -1
  22. package/out/renderer/assets/{yaml-BGSrk5HC.js → yaml-W_kzCFH7.js} +1 -1
  23. package/out/renderer/index.html +2 -2
  24. package/package.json +1 -1
  25. package/src/main/agents.ts +9 -1
  26. package/src/main/ctlsurfApi.ts +7 -0
  27. package/src/main/index.ts +58 -3
  28. package/src/main/orchestrator.ts +105 -4
  29. package/src/main/ssh.ts +348 -0
  30. package/src/preload/index.ts +26 -0
  31. package/src/renderer/App.tsx +20 -0
  32. package/src/renderer/components/AgentPicker.tsx +18 -0
  33. package/src/renderer/components/ProjectPicker.tsx +121 -0
  34. package/src/renderer/components/RemoteConnect.tsx +315 -0
  35. package/src/renderer/styles.css +201 -0
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-Bmzy9hKX.js","./lspLanguageFeatures-Bhdn2Eqy.js","./htmlMode-DD7YPgga.js","./jsonMode-CTuGgRvC.js","./javascript-CsGLsswK.js","./typescript-oxBn_Vcw.js"])))=>i.map(i=>d[i]);
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]);
2
2
  function getDefaultExportFromCjs(x) {
3
3
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
4
4
  }
@@ -207841,7 +207841,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
207841
207841
  modeConfigurationDefault$2
207842
207842
  );
207843
207843
  function getMode$3() {
207844
- return __vitePreload(() => import("./cssMode-Bmzy9hKX.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
207844
+ return __vitePreload(() => import("./cssMode-R8fTFLae.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
207845
207845
  }
207846
207846
  languages.onLanguage("less", () => {
207847
207847
  getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
@@ -207946,7 +207946,7 @@ const razorLanguageService = registerHTMLLanguageService(
207946
207946
  );
207947
207947
  const razorDefaults = razorLanguageService.defaults;
207948
207948
  function getMode$2() {
207949
- return __vitePreload(() => import("./htmlMode-DD7YPgga.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
207949
+ return __vitePreload(() => import("./htmlMode-BWtG6ywk.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
207950
207950
  }
207951
207951
  function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
207952
207952
  const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
@@ -208030,7 +208030,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
208030
208030
  );
208031
208031
  const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
208032
208032
  function getMode$1() {
208033
- return __vitePreload(() => import("./jsonMode-CTuGgRvC.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208033
+ return __vitePreload(() => import("./jsonMode-D1zR4VVU.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
208034
208034
  }
208035
208035
  languages.register({
208036
208036
  id: "json",
@@ -208276,7 +208276,7 @@ const getJavaScriptWorker = () => {
208276
208276
  return getMode().then((mode) => mode.getJavaScriptWorker());
208277
208277
  };
208278
208278
  function getMode() {
208279
- return __vitePreload(() => import("./tsMode-YTLgCayh.js"), true ? [] : void 0, import.meta.url);
208279
+ return __vitePreload(() => import("./tsMode-BYIQ-S9Z.js"), true ? [] : void 0, import.meta.url);
208280
208280
  }
208281
208281
  languages.onLanguage("typescript", () => {
208282
208282
  return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
@@ -208471,49 +208471,49 @@ registerLanguage({
208471
208471
  extensions: [".ftl", ".ftlh", ".ftlx"],
208472
208472
  aliases: ["FreeMarker2", "Apache FreeMarker2"],
208473
208473
  loader: () => {
208474
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208474
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208475
208475
  }
208476
208476
  });
208477
208477
  registerLanguage({
208478
208478
  id: "freemarker2.tag-angle.interpolation-dollar",
208479
208479
  aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
208480
208480
  loader: () => {
208481
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208481
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
208482
208482
  }
208483
208483
  });
208484
208484
  registerLanguage({
208485
208485
  id: "freemarker2.tag-bracket.interpolation-dollar",
208486
208486
  aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
208487
208487
  loader: () => {
208488
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208488
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
208489
208489
  }
208490
208490
  });
208491
208491
  registerLanguage({
208492
208492
  id: "freemarker2.tag-angle.interpolation-bracket",
208493
208493
  aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
208494
208494
  loader: () => {
208495
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208495
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
208496
208496
  }
208497
208497
  });
208498
208498
  registerLanguage({
208499
208499
  id: "freemarker2.tag-bracket.interpolation-bracket",
208500
208500
  aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
208501
208501
  loader: () => {
208502
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208502
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
208503
208503
  }
208504
208504
  });
208505
208505
  registerLanguage({
208506
208506
  id: "freemarker2.tag-auto.interpolation-dollar",
208507
208507
  aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
208508
208508
  loader: () => {
208509
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208509
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
208510
208510
  }
208511
208511
  });
208512
208512
  registerLanguage({
208513
208513
  id: "freemarker2.tag-auto.interpolation-bracket",
208514
208514
  aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
208515
208515
  loader: () => {
208516
- return __vitePreload(() => import("./freemarker2-CDAsExTa.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208516
+ return __vitePreload(() => import("./freemarker2-CyjWzWoP.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
208517
208517
  }
208518
208518
  });
208519
208519
  registerLanguage({
@@ -208534,7 +208534,7 @@ registerLanguage({
208534
208534
  extensions: [".handlebars", ".hbs"],
208535
208535
  aliases: ["Handlebars", "handlebars", "hbs"],
208536
208536
  mimetypes: ["text/x-handlebars-template"],
208537
- loader: () => __vitePreload(() => import("./handlebars-CvpBYG1L.js"), true ? [] : void 0, import.meta.url)
208537
+ loader: () => __vitePreload(() => import("./handlebars-CrhCGIRM.js"), true ? [] : void 0, import.meta.url)
208538
208538
  });
208539
208539
  registerLanguage({
208540
208540
  id: "hcl",
@@ -208547,7 +208547,7 @@ registerLanguage({
208547
208547
  extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
208548
208548
  aliases: ["HTML", "htm", "html", "xhtml"],
208549
208549
  mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
208550
- loader: () => __vitePreload(() => import("./html-CNhEQqr8.js"), true ? [] : void 0, import.meta.url)
208550
+ loader: () => __vitePreload(() => import("./html-Cc3dPNZr.js"), true ? [] : void 0, import.meta.url)
208551
208551
  });
208552
208552
  registerLanguage({
208553
208553
  id: "ini",
@@ -208570,7 +208570,7 @@ registerLanguage({
208570
208570
  filenames: ["jakefile"],
208571
208571
  aliases: ["JavaScript", "javascript", "js"],
208572
208572
  mimetypes: ["text/javascript"],
208573
- loader: () => __vitePreload(() => import("./javascript-CsGLsswK.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208573
+ loader: () => __vitePreload(() => import("./javascript-C8T_SdLC.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
208574
208574
  });
208575
208575
  registerLanguage({
208576
208576
  id: "julia",
@@ -208609,7 +208609,7 @@ registerLanguage({
208609
208609
  extensions: [".liquid", ".html.liquid"],
208610
208610
  aliases: ["Liquid", "liquid"],
208611
208611
  mimetypes: ["application/liquid"],
208612
- loader: () => __vitePreload(() => import("./liquid-BrrN4uul.js"), true ? [] : void 0, import.meta.url)
208612
+ loader: () => __vitePreload(() => import("./liquid-COSMe9Uf.js"), true ? [] : void 0, import.meta.url)
208613
208613
  });
208614
208614
  registerLanguage({
208615
208615
  id: "m3",
@@ -208627,7 +208627,7 @@ registerLanguage({
208627
208627
  id: "mdx",
208628
208628
  extensions: [".mdx"],
208629
208629
  aliases: ["MDX", "mdx"],
208630
- loader: () => __vitePreload(() => import("./mdx-DJo-gax4.js"), true ? [] : void 0, import.meta.url)
208630
+ loader: () => __vitePreload(() => import("./mdx-RfS44T-L.js"), true ? [] : void 0, import.meta.url)
208631
208631
  });
208632
208632
  registerLanguage({
208633
208633
  id: "mips",
@@ -208726,7 +208726,7 @@ registerLanguage({
208726
208726
  extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
208727
208727
  aliases: ["Python", "py"],
208728
208728
  firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
208729
- loader: () => __vitePreload(() => import("./python-DYHeg5b2.js"), true ? [] : void 0, import.meta.url)
208729
+ loader: () => __vitePreload(() => import("./python-DFSWKHUu.js"), true ? [] : void 0, import.meta.url)
208730
208730
  });
208731
208731
  registerLanguage({
208732
208732
  id: "qsharp",
@@ -208745,7 +208745,7 @@ registerLanguage({
208745
208745
  extensions: [".cshtml"],
208746
208746
  aliases: ["Razor", "razor"],
208747
208747
  mimetypes: ["text/x-cshtml"],
208748
- loader: () => __vitePreload(() => import("./razor-Cqcks14K.js"), true ? [] : void 0, import.meta.url)
208748
+ loader: () => __vitePreload(() => import("./razor-DtH2_uvo.js"), true ? [] : void 0, import.meta.url)
208749
208749
  });
208750
208750
  registerLanguage({
208751
208751
  id: "redis",
@@ -208878,7 +208878,7 @@ registerLanguage({
208878
208878
  aliases: ["TypeScript", "ts", "typescript"],
208879
208879
  mimetypes: ["text/typescript"],
208880
208880
  loader: () => {
208881
- return __vitePreload(() => import("./typescript-oxBn_Vcw.js"), true ? [] : void 0, import.meta.url);
208881
+ return __vitePreload(() => import("./typescript-HhQUr1Rb.js"), true ? [] : void 0, import.meta.url);
208882
208882
  }
208883
208883
  });
208884
208884
  registerLanguage({
@@ -208923,14 +208923,14 @@ registerLanguage({
208923
208923
  firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
208924
208924
  aliases: ["XML", "xml"],
208925
208925
  mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
208926
- loader: () => __vitePreload(() => import("./xml-BEqGMCTc.js"), true ? [] : void 0, import.meta.url)
208926
+ loader: () => __vitePreload(() => import("./xml-KuhgdKfD.js"), true ? [] : void 0, import.meta.url)
208927
208927
  });
208928
208928
  registerLanguage({
208929
208929
  id: "yaml",
208930
208930
  extensions: [".yaml", ".yml"],
208931
208931
  aliases: ["YAML", "yaml", "YML", "yml"],
208932
208932
  mimetypes: ["application/x-yaml", "text/x-yaml"],
208933
- loader: () => __vitePreload(() => import("./yaml-BGSrk5HC.js"), true ? [] : void 0, import.meta.url)
208933
+ loader: () => __vitePreload(() => import("./yaml-W_kzCFH7.js"), true ? [] : void 0, import.meta.url)
208934
208934
  });
208935
208935
  var __defProp = Object.defineProperty;
208936
208936
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -212419,10 +212419,276 @@ function EditorPanel({ cwd: cwd2 }) {
212419
212419
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "editor-placeholder", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Select a file to edit" }) }) })
212420
212420
  ] });
212421
212421
  }
212422
+ const TMUX_PREFIX = "ctlsurf_";
212423
+ function nextSessionName(sessions) {
212424
+ const used = new Set(
212425
+ sessions.filter((s) => s.startsWith(TMUX_PREFIX)).map((s) => parseInt(s.slice(TMUX_PREFIX.length), 10)).filter((n22) => Number.isInteger(n22) && n22 > 0)
212426
+ );
212427
+ let n2 = 1;
212428
+ while (used.has(n2)) n2++;
212429
+ return `${TMUX_PREFIX}${n2}`;
212430
+ }
212431
+ function RemoteConnect({ onConnect, onBack }) {
212432
+ const [step, setStep] = reactExports.useState("hosts");
212433
+ const [configHosts, setConfigHosts] = reactExports.useState([]);
212434
+ const [recents, setRecents] = reactExports.useState([]);
212435
+ const [manual, setManual] = reactExports.useState("");
212436
+ const [agentCmd, setAgentCmd] = reactExports.useState("claude");
212437
+ const [target, setTarget] = reactExports.useState("");
212438
+ const [probe, setProbe] = reactExports.useState(null);
212439
+ const [errorMsg, setErrorMsg] = reactExports.useState("");
212440
+ const [password, setPassword] = reactExports.useState("");
212441
+ reactExports.useEffect(() => {
212442
+ let cancelled = false;
212443
+ window.worker.sshListHosts().then((r) => {
212444
+ if (cancelled) return;
212445
+ setConfigHosts(r.configHosts || []);
212446
+ setRecents(r.recents || []);
212447
+ }).catch(() => {
212448
+ });
212449
+ return () => {
212450
+ cancelled = true;
212451
+ };
212452
+ }, []);
212453
+ const startProbe = async (t) => {
212454
+ const dest = t.trim();
212455
+ if (!dest) return;
212456
+ setTarget(dest);
212457
+ setStep("probing");
212458
+ try {
212459
+ const result = await window.worker.sshProbe(dest);
212460
+ setProbe(result);
212461
+ if (result.reachable || result.authRequired) {
212462
+ setStep("action");
212463
+ } else {
212464
+ setErrorMsg(result.error || "Could not connect");
212465
+ setStep("error");
212466
+ }
212467
+ } catch (err) {
212468
+ setErrorMsg(err?.message || "Probe failed");
212469
+ setStep("error");
212470
+ }
212471
+ };
212472
+ const connect = async (action) => {
212473
+ try {
212474
+ const agent = await window.worker.sshBuildAgent(target, action, agentCmd);
212475
+ if (password) {
212476
+ await window.worker.sshSetPassword(target, password).catch(() => {
212477
+ });
212478
+ }
212479
+ setPassword("");
212480
+ window.worker.sshAddRecent(target).catch(() => {
212481
+ });
212482
+ onConnect(agent);
212483
+ } catch (err) {
212484
+ setErrorMsg(err?.message || "Failed to build connection");
212485
+ setStep("error");
212486
+ }
212487
+ };
212488
+ const passwordField = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-pw", children: [
212489
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
212490
+ "input",
212491
+ {
212492
+ className: "remote-input",
212493
+ type: "password",
212494
+ placeholder: "Password (optional — blank prompts in terminal)",
212495
+ value: password,
212496
+ onChange: (e) => setPassword(e.target.value),
212497
+ autoCapitalize: "off",
212498
+ autoCorrect: "off",
212499
+ spellCheck: false
212500
+ }
212501
+ ),
212502
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-pw-hint", children: "Used once for this connection — never stored." })
212503
+ ] });
212504
+ const agentLabel = agentCmd === "claude" ? "Claude Code" : "shell";
212505
+ const agentToggle = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-toggle", children: [
212506
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "remote-toggle-label", children: "Run:" }),
212507
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
212508
+ "button",
212509
+ {
212510
+ className: `remote-toggle-btn${agentCmd === "claude" ? " is-active" : ""}`,
212511
+ onClick: () => setAgentCmd("claude"),
212512
+ children: "Claude Code"
212513
+ }
212514
+ ),
212515
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
212516
+ "button",
212517
+ {
212518
+ className: `remote-toggle-btn${agentCmd === "" ? " is-active" : ""}`,
212519
+ onClick: () => setAgentCmd(""),
212520
+ children: "Shell"
212521
+ }
212522
+ )
212523
+ ] });
212524
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-modal", children: [
212525
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-brand", children: "ctlsurf" }),
212526
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-title", children: "CONNECT TO REMOTE" }),
212527
+ step === "hosts" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212528
+ agentToggle,
212529
+ recents.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212530
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "RECENT" }),
212531
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list", children: recents.map((r) => /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "agent-picker-item", onClick: () => startProbe(r), children: [
212532
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: r }),
212533
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "reconnect" })
212534
+ ] }, r)) })
212535
+ ] }),
212536
+ configHosts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212537
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "~/.ssh/config" }),
212538
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list remote-host-scroll", children: configHosts.map((h2) => /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "agent-picker-item", onClick: () => startProbe(h2.alias), children: [
212539
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: h2.alias }),
212540
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-desc", children: [
212541
+ h2.user ? `${h2.user}@` : "",
212542
+ h2.hostName || ""
212543
+ ] })
212544
+ ] }, h2.alias)) })
212545
+ ] }),
212546
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "OR TYPE A HOST" }),
212547
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
212548
+ "form",
212549
+ {
212550
+ className: "remote-manual",
212551
+ onSubmit: (e) => {
212552
+ e.preventDefault();
212553
+ startProbe(manual);
212554
+ },
212555
+ children: [
212556
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
212557
+ "input",
212558
+ {
212559
+ className: "remote-input",
212560
+ type: "text",
212561
+ placeholder: "user@host",
212562
+ value: manual,
212563
+ onChange: (e) => setManual(e.target.value),
212564
+ autoCapitalize: "off",
212565
+ autoCorrect: "off",
212566
+ spellCheck: false
212567
+ }
212568
+ ),
212569
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-btn", type: "submit", disabled: !manual.trim(), children: "Connect" })
212570
+ ]
212571
+ }
212572
+ ),
212573
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", onClick: onBack, children: "← back to agents" })
212574
+ ] }),
212575
+ step === "probing" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-status", children: [
212576
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-spinner" }),
212577
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
212578
+ "Connecting to ",
212579
+ /* @__PURE__ */ jsxRuntimeExports.jsx("b", { children: target }),
212580
+ "…"
212581
+ ] }),
212582
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-status-sub", children: "Checking for tmux sessions" })
212583
+ ] }),
212584
+ step === "action" && probe && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212585
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-target-line", children: [
212586
+ /* @__PURE__ */ jsxRuntimeExports.jsx("b", { children: target }),
212587
+ " · run ",
212588
+ agentLabel
212589
+ ] }),
212590
+ probe.authRequired && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212591
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: "This host needs a password. Enter it below, or leave blank to type it at ssh's prompt in the terminal. Either way it is never stored." }),
212592
+ passwordField
212593
+ ] }),
212594
+ probe.reachable && probe.sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212595
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "REATTACH" }),
212596
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list", children: [...probe.sessions].sort((a, b) => a.startsWith(TMUX_PREFIX) === b.startsWith(TMUX_PREFIX) ? 0 : a.startsWith(TMUX_PREFIX) ? -1 : 1).map((s) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
212597
+ "button",
212598
+ {
212599
+ className: "agent-picker-item",
212600
+ onClick: () => connect({ kind: "attach", session: s }),
212601
+ children: [
212602
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: s }),
212603
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "attach running tmux session" })
212604
+ ]
212605
+ },
212606
+ s
212607
+ )) })
212608
+ ] }),
212609
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "START" }),
212610
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-list", children: [
212611
+ (probe.reachable && probe.tmuxInstalled || probe.authRequired) && /* @__PURE__ */ jsxRuntimeExports.jsxs(
212612
+ "button",
212613
+ {
212614
+ className: "agent-picker-item",
212615
+ onClick: () => {
212616
+ const session = probe.reachable ? nextSessionName(probe.sessions) : `${TMUX_PREFIX}1`;
212617
+ connect(probe.reachable ? { kind: "new-tmux", session } : { kind: "auto", session });
212618
+ },
212619
+ children: [
212620
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-name", children: [
212621
+ "New tmux session (",
212622
+ probe.reachable ? nextSessionName(probe.sessions) : `${TMUX_PREFIX}1`,
212623
+ ")"
212624
+ ] }),
212625
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "persists across disconnects (recommended)" })
212626
+ ]
212627
+ }
212628
+ ),
212629
+ probe.reachable && !probe.tmuxInstalled && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: "tmux isn't installed on this host — running without it." }),
212630
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
212631
+ "button",
212632
+ {
212633
+ className: "agent-picker-item",
212634
+ onClick: () => connect({ kind: "no-tmux" }),
212635
+ children: [
212636
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "Run without tmux" }),
212637
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-desc", children: [
212638
+ agentLabel,
212639
+ " directly — won't survive a dropped connection"
212640
+ ] })
212641
+ ]
212642
+ }
212643
+ )
212644
+ ] }),
212645
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", onClick: () => setStep("hosts"), children: "← choose another host" })
212646
+ ] }),
212647
+ step === "error" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212648
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-error", children: [
212649
+ "Couldn't connect to ",
212650
+ /* @__PURE__ */ jsxRuntimeExports.jsx("b", { children: target })
212651
+ ] }),
212652
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-status-sub", children: errorMsg }),
212653
+ passwordField,
212654
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "TRY ANYWAY (INTERACTIVE)" }),
212655
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-list", children: [
212656
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
212657
+ "button",
212658
+ {
212659
+ className: "agent-picker-item",
212660
+ onClick: () => connect({ kind: "auto", session: `${TMUX_PREFIX}1` }),
212661
+ children: [
212662
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "Connect with tmux" }),
212663
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "ssh will prompt if a password / key passphrase is needed" })
212664
+ ]
212665
+ }
212666
+ ),
212667
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
212668
+ "button",
212669
+ {
212670
+ className: "agent-picker-item",
212671
+ onClick: () => connect({ kind: "no-tmux" }),
212672
+ children: [
212673
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "Connect without tmux" }),
212674
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-desc", children: [
212675
+ "run ",
212676
+ agentLabel,
212677
+ " directly"
212678
+ ] })
212679
+ ]
212680
+ }
212681
+ )
212682
+ ] }),
212683
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", onClick: () => setStep("hosts"), children: "← choose another host" })
212684
+ ] })
212685
+ ] }) });
212686
+ }
212422
212687
  function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
212423
212688
  const displayPath = cwd2.replace(/^\/Users\/[^/]+/, "~");
212424
212689
  const [logChat, setLogChat] = reactExports.useState(false);
212425
212690
  const [loaded, setLoaded] = reactExports.useState(false);
212691
+ const [remoteMode, setRemoteMode] = reactExports.useState(false);
212426
212692
  reactExports.useEffect(() => {
212427
212693
  let cancelled = false;
212428
212694
  window.worker.getLogChat().then((r) => {
@@ -212451,6 +212717,17 @@ function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
212451
212717
  }
212452
212718
  onSelect(agent);
212453
212719
  };
212720
+ if (remoteMode) {
212721
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
212722
+ RemoteConnect,
212723
+ {
212724
+ onConnect: (agent) => {
212725
+ handleSelect(agent);
212726
+ },
212727
+ onBack: () => setRemoteMode(false)
212728
+ }
212729
+ );
212730
+ }
212454
212731
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-modal", children: [
212455
212732
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-brand", children: "ctlsurf" }),
212456
212733
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-cwd", onClick: onChangeCwd, title: "Click to change directory", children: [
@@ -212459,18 +212736,31 @@ function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
212459
212736
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-cwd-change", children: "change" })
212460
212737
  ] }),
212461
212738
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-title", children: "SELECT AGENT" }),
212462
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list", children: agents.map((a) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
212463
- "button",
212464
- {
212465
- className: "agent-picker-item",
212466
- onClick: () => handleSelect(a),
212467
- children: [
212468
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: a.name }),
212469
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: a.description })
212470
- ]
212471
- },
212472
- a.id
212473
- )) }),
212739
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-list", children: [
212740
+ agents.map((a) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
212741
+ "button",
212742
+ {
212743
+ className: "agent-picker-item",
212744
+ onClick: () => handleSelect(a),
212745
+ children: [
212746
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: a.name }),
212747
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: a.description })
212748
+ ]
212749
+ },
212750
+ a.id
212751
+ )),
212752
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
212753
+ "button",
212754
+ {
212755
+ className: "agent-picker-item",
212756
+ onClick: () => setRemoteMode(true),
212757
+ children: [
212758
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "🌐 Remote (SSH)" }),
212759
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "Run an agent on a remote machine" })
212760
+ ]
212761
+ }
212762
+ )
212763
+ ] }),
212474
212764
  /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "agent-picker-option", onClick: (e) => e.stopPropagation(), children: [
212475
212765
  /* @__PURE__ */ jsxRuntimeExports.jsx(
212476
212766
  "input",
@@ -212485,6 +212775,84 @@ function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
212485
212775
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-hint", children: "Select an agent to start" })
212486
212776
  ] }) });
212487
212777
  }
212778
+ function ProjectPicker({ onDone }) {
212779
+ const [state, setState2] = reactExports.useState("loading");
212780
+ const [projects, setProjects] = reactExports.useState([]);
212781
+ const [errorMsg, setErrorMsg] = reactExports.useState("");
212782
+ const [binding, setBinding] = reactExports.useState(false);
212783
+ const [filter, setFilter] = reactExports.useState("");
212784
+ reactExports.useEffect(() => {
212785
+ let cancelled = false;
212786
+ window.worker.listProjects().then((r) => {
212787
+ if (cancelled) return;
212788
+ if (r.ok) {
212789
+ setProjects(r.projects || []);
212790
+ setState2("ready");
212791
+ } else {
212792
+ setErrorMsg(r.error || "Could not load projects");
212793
+ setState2("error");
212794
+ }
212795
+ }).catch((err) => {
212796
+ if (cancelled) return;
212797
+ setErrorMsg(err?.message || "Could not load projects");
212798
+ setState2("error");
212799
+ });
212800
+ return () => {
212801
+ cancelled = true;
212802
+ };
212803
+ }, []);
212804
+ const pick = async (p) => {
212805
+ setBinding(true);
212806
+ try {
212807
+ await window.worker.bindProject(p.root_path);
212808
+ } catch {
212809
+ }
212810
+ onDone();
212811
+ };
212812
+ const shown = filter.trim() ? projects.filter((p) => p.name.toLowerCase().includes(filter.toLowerCase()) || p.root_path.toLowerCase().includes(filter.toLowerCase())) : projects;
212813
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-modal", children: [
212814
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-brand", children: "ctlsurf" }),
212815
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-title", children: "SELECT CTLSURF PROJECT" }),
212816
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-target-line", children: "Bind this remote session to a project" }),
212817
+ state === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-status", children: [
212818
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-spinner" }),
212819
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading projects…" })
212820
+ ] }),
212821
+ state === "error" && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: errorMsg }) }),
212822
+ state === "ready" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
212823
+ projects.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: "No ctlsurf projects found. You can skip and bind one later." }),
212824
+ projects.length > 6 && /* @__PURE__ */ jsxRuntimeExports.jsx(
212825
+ "input",
212826
+ {
212827
+ className: "remote-input",
212828
+ style: { width: "100%", boxSizing: "border-box", margin: "4px 0 8px" },
212829
+ type: "text",
212830
+ placeholder: "Filter projects…",
212831
+ value: filter,
212832
+ onChange: (e) => setFilter(e.target.value),
212833
+ autoCapitalize: "off",
212834
+ autoCorrect: "off",
212835
+ spellCheck: false
212836
+ }
212837
+ ),
212838
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list remote-host-scroll", children: shown.map((p) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
212839
+ "button",
212840
+ {
212841
+ className: "agent-picker-item project-item",
212842
+ disabled: binding,
212843
+ onClick: () => pick(p),
212844
+ title: p.root_path,
212845
+ children: [
212846
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: p.name }),
212847
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: p.root_path })
212848
+ ]
212849
+ },
212850
+ p.id
212851
+ )) })
212852
+ ] }),
212853
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", disabled: binding, onClick: onDone, children: "Skip — no project" })
212854
+ ] }) });
212855
+ }
212488
212856
  function removePane(node, paneId) {
212489
212857
  if (node.type === "leaf") {
212490
212858
  return node.paneId === paneId ? null : node;
@@ -213346,6 +213714,7 @@ function App() {
213346
213714
  }, []);
213347
213715
  const [pickerTargetTabId, setPickerTargetTabId] = reactExports.useState(tabs[0].id);
213348
213716
  const [showAgentPicker, setShowAgentPicker] = reactExports.useState(true);
213717
+ const [showProjectPicker, setShowProjectPicker] = reactExports.useState(false);
213349
213718
  const visiblePaneIds = findPaneIds(layout2);
213350
213719
  reactExports.useEffect(() => {
213351
213720
  async function init2() {
@@ -213478,6 +213847,9 @@ function App() {
213478
213847
  }
213479
213848
  setShowAgentPicker(false);
213480
213849
  setPickerTargetTabId(null);
213850
+ if (agent.id.startsWith("remote-")) {
213851
+ setShowProjectPicker(true);
213852
+ }
213481
213853
  }, [pickerTargetTabId, tabs]);
213482
213854
  const closeTab = reactExports.useCallback(async (tabId) => {
213483
213855
  await window.worker.killPty(tabId);
@@ -213777,6 +214149,7 @@ function App() {
213777
214149
  }
213778
214150
  }
213779
214151
  ),
214152
+ showProjectPicker && /* @__PURE__ */ jsxRuntimeExports.jsx(ProjectPicker, { onDone: () => setShowProjectPicker(false) }),
213780
214153
  showFloatingMic && /* @__PURE__ */ jsxRuntimeExports.jsx(
213781
214154
  FloatingMic,
213782
214155
  {
@@ -1,5 +1,5 @@
1
- import { conf as conf$1, language as language$1 } from "./typescript-oxBn_Vcw.js";
2
- import "./index-BDlCPzCG.js";
1
+ import { conf as conf$1, language as language$1 } from "./typescript-HhQUr1Rb.js";
2
+ import "./index-kkG56aKv.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-BDlCPzCG.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-Bhdn2Eqy.js";
3
- import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-Bhdn2Eqy.js";
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";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {