@phenx-inc/ctlsurf 0.11.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.
- package/out/headless/index.mjs +115 -5
- package/out/headless/index.mjs.map +3 -3
- package/out/main/index.js +316 -8
- package/out/preload/index.js +9 -0
- package/out/renderer/assets/{cssMode-Bmzy9hKX.js → cssMode-D7r66wvO.js} +3 -3
- package/out/renderer/assets/{freemarker2-CDAsExTa.js → freemarker2-jSWJIjPG.js} +1 -1
- package/out/renderer/assets/{handlebars-CvpBYG1L.js → handlebars-BnFyz5RH.js} +1 -1
- package/out/renderer/assets/{html-CNhEQqr8.js → html-Bl5UFavp.js} +1 -1
- package/out/renderer/assets/{htmlMode-DD7YPgga.js → htmlMode-D4VByBT6.js} +3 -3
- package/out/renderer/assets/{index-CGHeDwZa.css → index-Cc_TqOCL.css} +318 -0
- package/out/renderer/assets/{index-BDlCPzCG.js → index-DxhW1emk.js} +558 -85
- package/out/renderer/assets/{javascript-CsGLsswK.js → javascript-CMN1OmwG.js} +2 -2
- package/out/renderer/assets/{jsonMode-CTuGgRvC.js → jsonMode-CJ5AYSPV.js} +3 -3
- package/out/renderer/assets/{liquid-BrrN4uul.js → liquid-BGMIDTEm.js} +1 -1
- package/out/renderer/assets/{lspLanguageFeatures-Bhdn2Eqy.js → lspLanguageFeatures-DGifVYB5.js} +1 -1
- package/out/renderer/assets/{mdx-DJo-gax4.js → mdx-B2Z7R10Q.js} +1 -1
- package/out/renderer/assets/{python-DYHeg5b2.js → python-LMDMSSdn.js} +1 -1
- package/out/renderer/assets/{razor-Cqcks14K.js → razor-BZSrziPu.js} +1 -1
- package/out/renderer/assets/{tsMode-YTLgCayh.js → tsMode-DF9m6_3n.js} +1 -1
- package/out/renderer/assets/{typescript-oxBn_Vcw.js → typescript-rZeCMf0a.js} +1 -1
- package/out/renderer/assets/{xml-BEqGMCTc.js → xml-fNSZ-7so.js} +1 -1
- package/out/renderer/assets/{yaml-BGSrk5HC.js → yaml-1wxIuvzh.js} +1 -1
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/src/main/agents.ts +9 -1
- package/src/main/ctlsurfApi.ts +7 -0
- package/src/main/index.ts +62 -4
- package/src/main/orchestrator.ts +112 -4
- package/src/main/ssh.ts +348 -0
- package/src/preload/index.ts +26 -0
- package/src/renderer/App.tsx +25 -1
- package/src/renderer/components/AgentPicker.tsx +18 -0
- package/src/renderer/components/ProjectPicker.tsx +121 -0
- package/src/renderer/components/RemoteConnect.tsx +315 -0
- package/src/renderer/components/SpeakControls.tsx +8 -2
- package/src/renderer/components/TerminalPanel.tsx +134 -23
- package/src/renderer/components/TicketPanel.tsx +67 -26
- package/src/renderer/styles.css +318 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-
|
|
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.
|
|
18854
|
+
return buf.baseY - buf.viewportY <= 2;
|
|
18855
18855
|
}
|
|
18856
|
-
function
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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;
|
|
@@ -212419,10 +212494,276 @@ function EditorPanel({ cwd: cwd2 }) {
|
|
|
212419
212494
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "editor-placeholder", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Select a file to edit" }) }) })
|
|
212420
212495
|
] });
|
|
212421
212496
|
}
|
|
212497
|
+
const TMUX_PREFIX = "ctlsurf_";
|
|
212498
|
+
function nextSessionName(sessions) {
|
|
212499
|
+
const used = new Set(
|
|
212500
|
+
sessions.filter((s) => s.startsWith(TMUX_PREFIX)).map((s) => parseInt(s.slice(TMUX_PREFIX.length), 10)).filter((n22) => Number.isInteger(n22) && n22 > 0)
|
|
212501
|
+
);
|
|
212502
|
+
let n2 = 1;
|
|
212503
|
+
while (used.has(n2)) n2++;
|
|
212504
|
+
return `${TMUX_PREFIX}${n2}`;
|
|
212505
|
+
}
|
|
212506
|
+
function RemoteConnect({ onConnect, onBack }) {
|
|
212507
|
+
const [step, setStep] = reactExports.useState("hosts");
|
|
212508
|
+
const [configHosts, setConfigHosts] = reactExports.useState([]);
|
|
212509
|
+
const [recents, setRecents] = reactExports.useState([]);
|
|
212510
|
+
const [manual, setManual] = reactExports.useState("");
|
|
212511
|
+
const [agentCmd, setAgentCmd] = reactExports.useState("claude");
|
|
212512
|
+
const [target, setTarget] = reactExports.useState("");
|
|
212513
|
+
const [probe, setProbe] = reactExports.useState(null);
|
|
212514
|
+
const [errorMsg, setErrorMsg] = reactExports.useState("");
|
|
212515
|
+
const [password, setPassword] = reactExports.useState("");
|
|
212516
|
+
reactExports.useEffect(() => {
|
|
212517
|
+
let cancelled = false;
|
|
212518
|
+
window.worker.sshListHosts().then((r) => {
|
|
212519
|
+
if (cancelled) return;
|
|
212520
|
+
setConfigHosts(r.configHosts || []);
|
|
212521
|
+
setRecents(r.recents || []);
|
|
212522
|
+
}).catch(() => {
|
|
212523
|
+
});
|
|
212524
|
+
return () => {
|
|
212525
|
+
cancelled = true;
|
|
212526
|
+
};
|
|
212527
|
+
}, []);
|
|
212528
|
+
const startProbe = async (t) => {
|
|
212529
|
+
const dest = t.trim();
|
|
212530
|
+
if (!dest) return;
|
|
212531
|
+
setTarget(dest);
|
|
212532
|
+
setStep("probing");
|
|
212533
|
+
try {
|
|
212534
|
+
const result = await window.worker.sshProbe(dest);
|
|
212535
|
+
setProbe(result);
|
|
212536
|
+
if (result.reachable || result.authRequired) {
|
|
212537
|
+
setStep("action");
|
|
212538
|
+
} else {
|
|
212539
|
+
setErrorMsg(result.error || "Could not connect");
|
|
212540
|
+
setStep("error");
|
|
212541
|
+
}
|
|
212542
|
+
} catch (err) {
|
|
212543
|
+
setErrorMsg(err?.message || "Probe failed");
|
|
212544
|
+
setStep("error");
|
|
212545
|
+
}
|
|
212546
|
+
};
|
|
212547
|
+
const connect = async (action) => {
|
|
212548
|
+
try {
|
|
212549
|
+
const agent = await window.worker.sshBuildAgent(target, action, agentCmd);
|
|
212550
|
+
if (password) {
|
|
212551
|
+
await window.worker.sshSetPassword(target, password).catch(() => {
|
|
212552
|
+
});
|
|
212553
|
+
}
|
|
212554
|
+
setPassword("");
|
|
212555
|
+
window.worker.sshAddRecent(target).catch(() => {
|
|
212556
|
+
});
|
|
212557
|
+
onConnect(agent);
|
|
212558
|
+
} catch (err) {
|
|
212559
|
+
setErrorMsg(err?.message || "Failed to build connection");
|
|
212560
|
+
setStep("error");
|
|
212561
|
+
}
|
|
212562
|
+
};
|
|
212563
|
+
const passwordField = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-pw", children: [
|
|
212564
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212565
|
+
"input",
|
|
212566
|
+
{
|
|
212567
|
+
className: "remote-input",
|
|
212568
|
+
type: "password",
|
|
212569
|
+
placeholder: "Password (optional — blank prompts in terminal)",
|
|
212570
|
+
value: password,
|
|
212571
|
+
onChange: (e) => setPassword(e.target.value),
|
|
212572
|
+
autoCapitalize: "off",
|
|
212573
|
+
autoCorrect: "off",
|
|
212574
|
+
spellCheck: false
|
|
212575
|
+
}
|
|
212576
|
+
),
|
|
212577
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-pw-hint", children: "Used once for this connection — never stored." })
|
|
212578
|
+
] });
|
|
212579
|
+
const agentLabel = agentCmd === "claude" ? "Claude Code" : "shell";
|
|
212580
|
+
const agentToggle = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-toggle", children: [
|
|
212581
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "remote-toggle-label", children: "Run:" }),
|
|
212582
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212583
|
+
"button",
|
|
212584
|
+
{
|
|
212585
|
+
className: `remote-toggle-btn${agentCmd === "claude" ? " is-active" : ""}`,
|
|
212586
|
+
onClick: () => setAgentCmd("claude"),
|
|
212587
|
+
children: "Claude Code"
|
|
212588
|
+
}
|
|
212589
|
+
),
|
|
212590
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212591
|
+
"button",
|
|
212592
|
+
{
|
|
212593
|
+
className: `remote-toggle-btn${agentCmd === "" ? " is-active" : ""}`,
|
|
212594
|
+
onClick: () => setAgentCmd(""),
|
|
212595
|
+
children: "Shell"
|
|
212596
|
+
}
|
|
212597
|
+
)
|
|
212598
|
+
] });
|
|
212599
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-modal", children: [
|
|
212600
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-brand", children: "ctlsurf" }),
|
|
212601
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-title", children: "CONNECT TO REMOTE" }),
|
|
212602
|
+
step === "hosts" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212603
|
+
agentToggle,
|
|
212604
|
+
recents.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212605
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "RECENT" }),
|
|
212606
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list", children: recents.map((r) => /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "agent-picker-item", onClick: () => startProbe(r), children: [
|
|
212607
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: r }),
|
|
212608
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "reconnect" })
|
|
212609
|
+
] }, r)) })
|
|
212610
|
+
] }),
|
|
212611
|
+
configHosts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212612
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "~/.ssh/config" }),
|
|
212613
|
+
/* @__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: [
|
|
212614
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: h2.alias }),
|
|
212615
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-desc", children: [
|
|
212616
|
+
h2.user ? `${h2.user}@` : "",
|
|
212617
|
+
h2.hostName || ""
|
|
212618
|
+
] })
|
|
212619
|
+
] }, h2.alias)) })
|
|
212620
|
+
] }),
|
|
212621
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "OR TYPE A HOST" }),
|
|
212622
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212623
|
+
"form",
|
|
212624
|
+
{
|
|
212625
|
+
className: "remote-manual",
|
|
212626
|
+
onSubmit: (e) => {
|
|
212627
|
+
e.preventDefault();
|
|
212628
|
+
startProbe(manual);
|
|
212629
|
+
},
|
|
212630
|
+
children: [
|
|
212631
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212632
|
+
"input",
|
|
212633
|
+
{
|
|
212634
|
+
className: "remote-input",
|
|
212635
|
+
type: "text",
|
|
212636
|
+
placeholder: "user@host",
|
|
212637
|
+
value: manual,
|
|
212638
|
+
onChange: (e) => setManual(e.target.value),
|
|
212639
|
+
autoCapitalize: "off",
|
|
212640
|
+
autoCorrect: "off",
|
|
212641
|
+
spellCheck: false
|
|
212642
|
+
}
|
|
212643
|
+
),
|
|
212644
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-btn", type: "submit", disabled: !manual.trim(), children: "Connect" })
|
|
212645
|
+
]
|
|
212646
|
+
}
|
|
212647
|
+
),
|
|
212648
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", onClick: onBack, children: "← back to agents" })
|
|
212649
|
+
] }),
|
|
212650
|
+
step === "probing" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-status", children: [
|
|
212651
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-spinner" }),
|
|
212652
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
212653
|
+
"Connecting to ",
|
|
212654
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("b", { children: target }),
|
|
212655
|
+
"…"
|
|
212656
|
+
] }),
|
|
212657
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-status-sub", children: "Checking for tmux sessions" })
|
|
212658
|
+
] }),
|
|
212659
|
+
step === "action" && probe && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212660
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-target-line", children: [
|
|
212661
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("b", { children: target }),
|
|
212662
|
+
" · run ",
|
|
212663
|
+
agentLabel
|
|
212664
|
+
] }),
|
|
212665
|
+
probe.authRequired && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212666
|
+
/* @__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." }),
|
|
212667
|
+
passwordField
|
|
212668
|
+
] }),
|
|
212669
|
+
probe.reachable && probe.sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212670
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "REATTACH" }),
|
|
212671
|
+
/* @__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(
|
|
212672
|
+
"button",
|
|
212673
|
+
{
|
|
212674
|
+
className: "agent-picker-item",
|
|
212675
|
+
onClick: () => connect({ kind: "attach", session: s }),
|
|
212676
|
+
children: [
|
|
212677
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: s }),
|
|
212678
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "attach running tmux session" })
|
|
212679
|
+
]
|
|
212680
|
+
},
|
|
212681
|
+
s
|
|
212682
|
+
)) })
|
|
212683
|
+
] }),
|
|
212684
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "START" }),
|
|
212685
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-list", children: [
|
|
212686
|
+
(probe.reachable && probe.tmuxInstalled || probe.authRequired) && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212687
|
+
"button",
|
|
212688
|
+
{
|
|
212689
|
+
className: "agent-picker-item",
|
|
212690
|
+
onClick: () => {
|
|
212691
|
+
const session = probe.reachable ? nextSessionName(probe.sessions) : `${TMUX_PREFIX}1`;
|
|
212692
|
+
connect(probe.reachable ? { kind: "new-tmux", session } : { kind: "auto", session });
|
|
212693
|
+
},
|
|
212694
|
+
children: [
|
|
212695
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-name", children: [
|
|
212696
|
+
"New tmux session (",
|
|
212697
|
+
probe.reachable ? nextSessionName(probe.sessions) : `${TMUX_PREFIX}1`,
|
|
212698
|
+
")"
|
|
212699
|
+
] }),
|
|
212700
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "persists across disconnects (recommended)" })
|
|
212701
|
+
]
|
|
212702
|
+
}
|
|
212703
|
+
),
|
|
212704
|
+
probe.reachable && !probe.tmuxInstalled && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: "tmux isn't installed on this host — running without it." }),
|
|
212705
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212706
|
+
"button",
|
|
212707
|
+
{
|
|
212708
|
+
className: "agent-picker-item",
|
|
212709
|
+
onClick: () => connect({ kind: "no-tmux" }),
|
|
212710
|
+
children: [
|
|
212711
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "Run without tmux" }),
|
|
212712
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-desc", children: [
|
|
212713
|
+
agentLabel,
|
|
212714
|
+
" directly — won't survive a dropped connection"
|
|
212715
|
+
] })
|
|
212716
|
+
]
|
|
212717
|
+
}
|
|
212718
|
+
)
|
|
212719
|
+
] }),
|
|
212720
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", onClick: () => setStep("hosts"), children: "← choose another host" })
|
|
212721
|
+
] }),
|
|
212722
|
+
step === "error" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212723
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-error", children: [
|
|
212724
|
+
"Couldn't connect to ",
|
|
212725
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("b", { children: target })
|
|
212726
|
+
] }),
|
|
212727
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-status-sub", children: errorMsg }),
|
|
212728
|
+
passwordField,
|
|
212729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-section-label", children: "TRY ANYWAY (INTERACTIVE)" }),
|
|
212730
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-list", children: [
|
|
212731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212732
|
+
"button",
|
|
212733
|
+
{
|
|
212734
|
+
className: "agent-picker-item",
|
|
212735
|
+
onClick: () => connect({ kind: "auto", session: `${TMUX_PREFIX}1` }),
|
|
212736
|
+
children: [
|
|
212737
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "Connect with tmux" }),
|
|
212738
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "ssh will prompt if a password / key passphrase is needed" })
|
|
212739
|
+
]
|
|
212740
|
+
}
|
|
212741
|
+
),
|
|
212742
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212743
|
+
"button",
|
|
212744
|
+
{
|
|
212745
|
+
className: "agent-picker-item",
|
|
212746
|
+
onClick: () => connect({ kind: "no-tmux" }),
|
|
212747
|
+
children: [
|
|
212748
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "Connect without tmux" }),
|
|
212749
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "agent-picker-desc", children: [
|
|
212750
|
+
"run ",
|
|
212751
|
+
agentLabel,
|
|
212752
|
+
" directly"
|
|
212753
|
+
] })
|
|
212754
|
+
]
|
|
212755
|
+
}
|
|
212756
|
+
)
|
|
212757
|
+
] }),
|
|
212758
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", onClick: () => setStep("hosts"), children: "← choose another host" })
|
|
212759
|
+
] })
|
|
212760
|
+
] }) });
|
|
212761
|
+
}
|
|
212422
212762
|
function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
|
|
212423
212763
|
const displayPath = cwd2.replace(/^\/Users\/[^/]+/, "~");
|
|
212424
212764
|
const [logChat, setLogChat] = reactExports.useState(false);
|
|
212425
212765
|
const [loaded, setLoaded] = reactExports.useState(false);
|
|
212766
|
+
const [remoteMode, setRemoteMode] = reactExports.useState(false);
|
|
212426
212767
|
reactExports.useEffect(() => {
|
|
212427
212768
|
let cancelled = false;
|
|
212428
212769
|
window.worker.getLogChat().then((r) => {
|
|
@@ -212451,6 +212792,17 @@ function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
|
|
|
212451
212792
|
}
|
|
212452
212793
|
onSelect(agent);
|
|
212453
212794
|
};
|
|
212795
|
+
if (remoteMode) {
|
|
212796
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212797
|
+
RemoteConnect,
|
|
212798
|
+
{
|
|
212799
|
+
onConnect: (agent) => {
|
|
212800
|
+
handleSelect(agent);
|
|
212801
|
+
},
|
|
212802
|
+
onBack: () => setRemoteMode(false)
|
|
212803
|
+
}
|
|
212804
|
+
);
|
|
212805
|
+
}
|
|
212454
212806
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-modal", children: [
|
|
212455
212807
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-brand", children: "ctlsurf" }),
|
|
212456
212808
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-cwd", onClick: onChangeCwd, title: "Click to change directory", children: [
|
|
@@ -212459,18 +212811,31 @@ function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
|
|
|
212459
212811
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-cwd-change", children: "change" })
|
|
212460
212812
|
] }),
|
|
212461
212813
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-title", children: "SELECT AGENT" }),
|
|
212462
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
212463
|
-
|
|
212464
|
-
|
|
212465
|
-
|
|
212466
|
-
|
|
212467
|
-
|
|
212468
|
-
|
|
212469
|
-
|
|
212470
|
-
|
|
212471
|
-
|
|
212472
|
-
|
|
212473
|
-
|
|
212814
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-list", children: [
|
|
212815
|
+
agents.map((a) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212816
|
+
"button",
|
|
212817
|
+
{
|
|
212818
|
+
className: "agent-picker-item",
|
|
212819
|
+
onClick: () => handleSelect(a),
|
|
212820
|
+
children: [
|
|
212821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: a.name }),
|
|
212822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: a.description })
|
|
212823
|
+
]
|
|
212824
|
+
},
|
|
212825
|
+
a.id
|
|
212826
|
+
)),
|
|
212827
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212828
|
+
"button",
|
|
212829
|
+
{
|
|
212830
|
+
className: "agent-picker-item",
|
|
212831
|
+
onClick: () => setRemoteMode(true),
|
|
212832
|
+
children: [
|
|
212833
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: "🌐 Remote (SSH)" }),
|
|
212834
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: "Run an agent on a remote machine" })
|
|
212835
|
+
]
|
|
212836
|
+
}
|
|
212837
|
+
)
|
|
212838
|
+
] }),
|
|
212474
212839
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "agent-picker-option", onClick: (e) => e.stopPropagation(), children: [
|
|
212475
212840
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212476
212841
|
"input",
|
|
@@ -212485,6 +212850,84 @@ function AgentPicker({ agents, cwd: cwd2, onSelect, onChangeCwd }) {
|
|
|
212485
212850
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-hint", children: "Select an agent to start" })
|
|
212486
212851
|
] }) });
|
|
212487
212852
|
}
|
|
212853
|
+
function ProjectPicker({ onDone }) {
|
|
212854
|
+
const [state, setState2] = reactExports.useState("loading");
|
|
212855
|
+
const [projects, setProjects] = reactExports.useState([]);
|
|
212856
|
+
const [errorMsg, setErrorMsg] = reactExports.useState("");
|
|
212857
|
+
const [binding, setBinding] = reactExports.useState(false);
|
|
212858
|
+
const [filter, setFilter] = reactExports.useState("");
|
|
212859
|
+
reactExports.useEffect(() => {
|
|
212860
|
+
let cancelled = false;
|
|
212861
|
+
window.worker.listProjects().then((r) => {
|
|
212862
|
+
if (cancelled) return;
|
|
212863
|
+
if (r.ok) {
|
|
212864
|
+
setProjects(r.projects || []);
|
|
212865
|
+
setState2("ready");
|
|
212866
|
+
} else {
|
|
212867
|
+
setErrorMsg(r.error || "Could not load projects");
|
|
212868
|
+
setState2("error");
|
|
212869
|
+
}
|
|
212870
|
+
}).catch((err) => {
|
|
212871
|
+
if (cancelled) return;
|
|
212872
|
+
setErrorMsg(err?.message || "Could not load projects");
|
|
212873
|
+
setState2("error");
|
|
212874
|
+
});
|
|
212875
|
+
return () => {
|
|
212876
|
+
cancelled = true;
|
|
212877
|
+
};
|
|
212878
|
+
}, []);
|
|
212879
|
+
const pick = async (p) => {
|
|
212880
|
+
setBinding(true);
|
|
212881
|
+
try {
|
|
212882
|
+
await window.worker.bindProject(p.root_path);
|
|
212883
|
+
} catch {
|
|
212884
|
+
}
|
|
212885
|
+
onDone();
|
|
212886
|
+
};
|
|
212887
|
+
const shown = filter.trim() ? projects.filter((p) => p.name.toLowerCase().includes(filter.toLowerCase()) || p.root_path.toLowerCase().includes(filter.toLowerCase())) : projects;
|
|
212888
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "agent-picker-modal", children: [
|
|
212889
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-brand", children: "ctlsurf" }),
|
|
212890
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-title", children: "SELECT CTLSURF PROJECT" }),
|
|
212891
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-target-line", children: "Bind this remote session to a project" }),
|
|
212892
|
+
state === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "remote-status", children: [
|
|
212893
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-spinner" }),
|
|
212894
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading projects…" })
|
|
212895
|
+
] }),
|
|
212896
|
+
state === "error" && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: errorMsg }) }),
|
|
212897
|
+
state === "ready" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
212898
|
+
projects.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "remote-note", children: "No ctlsurf projects found. You can skip and bind one later." }),
|
|
212899
|
+
projects.length > 6 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
212900
|
+
"input",
|
|
212901
|
+
{
|
|
212902
|
+
className: "remote-input",
|
|
212903
|
+
style: { width: "100%", boxSizing: "border-box", margin: "4px 0 8px" },
|
|
212904
|
+
type: "text",
|
|
212905
|
+
placeholder: "Filter projects…",
|
|
212906
|
+
value: filter,
|
|
212907
|
+
onChange: (e) => setFilter(e.target.value),
|
|
212908
|
+
autoCapitalize: "off",
|
|
212909
|
+
autoCorrect: "off",
|
|
212910
|
+
spellCheck: false
|
|
212911
|
+
}
|
|
212912
|
+
),
|
|
212913
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "agent-picker-list remote-host-scroll", children: shown.map((p) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
212914
|
+
"button",
|
|
212915
|
+
{
|
|
212916
|
+
className: "agent-picker-item project-item",
|
|
212917
|
+
disabled: binding,
|
|
212918
|
+
onClick: () => pick(p),
|
|
212919
|
+
title: p.root_path,
|
|
212920
|
+
children: [
|
|
212921
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-name", children: p.name }),
|
|
212922
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "agent-picker-desc", children: p.root_path })
|
|
212923
|
+
]
|
|
212924
|
+
},
|
|
212925
|
+
p.id
|
|
212926
|
+
)) })
|
|
212927
|
+
] }),
|
|
212928
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "remote-link", disabled: binding, onClick: onDone, children: "Skip — no project" })
|
|
212929
|
+
] }) });
|
|
212930
|
+
}
|
|
212488
212931
|
function removePane(node, paneId) {
|
|
212489
212932
|
if (node.type === "leaf") {
|
|
212490
212933
|
return node.paneId === paneId ? null : node;
|
|
@@ -213094,12 +213537,36 @@ function Segmented({ options, value, onChange }) {
|
|
|
213094
213537
|
);
|
|
213095
213538
|
}) });
|
|
213096
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
|
+
}
|
|
213097
213563
|
function TicketPane() {
|
|
213098
213564
|
const [project, setProject] = reactExports.useState(null);
|
|
213099
213565
|
const [view, setView] = reactExports.useState("list");
|
|
213100
213566
|
const [tickets, setTickets] = reactExports.useState([]);
|
|
213101
213567
|
const [listLoading, setListLoading] = reactExports.useState(false);
|
|
213102
213568
|
const [listError, setListError] = reactExports.useState(null);
|
|
213569
|
+
const [showDone, setShowDone] = reactExports.useState(false);
|
|
213103
213570
|
const [editingId, setEditingId] = reactExports.useState(null);
|
|
213104
213571
|
const [title, setTitle] = reactExports.useState("");
|
|
213105
213572
|
const [description, setDescription] = reactExports.useState("");
|
|
@@ -213189,17 +213656,22 @@ function TicketPane() {
|
|
|
213189
213656
|
window.addEventListener("keydown", onKey);
|
|
213190
213657
|
return () => window.removeEventListener("keydown", onKey);
|
|
213191
213658
|
}, [view, handleSave]);
|
|
213659
|
+
const activeTickets = tickets.filter((t) => t.status !== "Done");
|
|
213660
|
+
const doneTickets = tickets.filter((t) => t.status === "Done");
|
|
213192
213661
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-pane", role: "region", "aria-label": "Tickets", children: [
|
|
213193
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
213194
|
-
|
|
213195
|
-
|
|
213196
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
213197
|
-
|
|
213198
|
-
"
|
|
213199
|
-
|
|
213200
|
-
|
|
213201
|
-
|
|
213202
|
-
|
|
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
|
+
] }),
|
|
213203
213675
|
view === "list" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
213204
213676
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-list-body", children: [
|
|
213205
213677
|
listLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-list-msg", children: "Loading tickets…" }),
|
|
@@ -213212,32 +213684,27 @@ function TicketPane() {
|
|
|
213212
213684
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-title", children: "No tickets yet" }),
|
|
213213
213685
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-hint", children: "Log the first one for this project." })
|
|
213214
213686
|
] }),
|
|
213215
|
-
!listLoading &&
|
|
213216
|
-
|
|
213217
|
-
|
|
213218
|
-
|
|
213219
|
-
|
|
213220
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ticket-card-status", style: { color: colorOf(STATUS_OPTIONS, t.status) }, children: [
|
|
213221
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-seg-dot", style: { background: colorOf(STATUS_OPTIONS, t.status) } }),
|
|
213222
|
-
t.status
|
|
213223
|
-
] }),
|
|
213224
|
-
t.created && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-date", children: formatDate(t.created) })
|
|
213225
|
-
] })
|
|
213226
|
-
] }),
|
|
213227
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
213228
|
-
"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",
|
|
213229
213692
|
{
|
|
213230
|
-
|
|
213231
|
-
|
|
213232
|
-
|
|
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
|
+
]
|
|
213233
213702
|
}
|
|
213234
|
-
)
|
|
213235
|
-
|
|
213703
|
+
),
|
|
213704
|
+
showDone && doneTickets.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsx(TicketCard, { ticket: t, onClick: () => openEditForm(t) }, t.id))
|
|
213705
|
+
] })
|
|
213236
213706
|
] }),
|
|
213237
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
213238
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-hint", children: tickets.length > 0 && `${tickets.length} ticket${tickets.length === 1 ? "" : "s"}` }),
|
|
213239
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-btn-primary", onClick: openNewForm, children: "+ New ticket" })
|
|
213240
|
-
] })
|
|
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"}` }) })
|
|
213241
213708
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
213242
213709
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-body", children: [
|
|
213243
213710
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ticket-field", children: [
|
|
@@ -213346,6 +213813,7 @@ function App() {
|
|
|
213346
213813
|
}, []);
|
|
213347
213814
|
const [pickerTargetTabId, setPickerTargetTabId] = reactExports.useState(tabs[0].id);
|
|
213348
213815
|
const [showAgentPicker, setShowAgentPicker] = reactExports.useState(true);
|
|
213816
|
+
const [showProjectPicker, setShowProjectPicker] = reactExports.useState(false);
|
|
213349
213817
|
const visiblePaneIds = findPaneIds(layout2);
|
|
213350
213818
|
reactExports.useEffect(() => {
|
|
213351
213819
|
async function init2() {
|
|
@@ -213478,6 +213946,9 @@ function App() {
|
|
|
213478
213946
|
}
|
|
213479
213947
|
setShowAgentPicker(false);
|
|
213480
213948
|
setPickerTargetTabId(null);
|
|
213949
|
+
if (agent.id.startsWith("remote-")) {
|
|
213950
|
+
setShowProjectPicker(true);
|
|
213951
|
+
}
|
|
213481
213952
|
}, [pickerTargetTabId, tabs]);
|
|
213482
213953
|
const closeTab = reactExports.useCallback(async (tabId) => {
|
|
213483
213954
|
await window.worker.killPty(tabId);
|
|
@@ -213578,6 +214049,7 @@ function App() {
|
|
|
213578
214049
|
window.addEventListener("ctlsurf-open-url", onOpen);
|
|
213579
214050
|
return () => window.removeEventListener("ctlsurf-open-url", onOpen);
|
|
213580
214051
|
}, [layout2, togglePane]);
|
|
214052
|
+
const activeAgentIsRemote = !!tabs.find((t) => t.id === activeTabId)?.agent?.id?.startsWith("remote-");
|
|
213581
214053
|
const panes = [
|
|
213582
214054
|
{ id: "editor", label: "Editor", content: /* @__PURE__ */ jsxRuntimeExports.jsx(EditorPanel, { cwd: cwd2 }) },
|
|
213583
214055
|
{
|
|
@@ -213723,7 +214195,7 @@ function App() {
|
|
|
213723
214195
|
)
|
|
213724
214196
|
}
|
|
213725
214197
|
),
|
|
213726
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SpeakControls, {}),
|
|
214198
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SpeakControls, { remote: activeAgentIsRemote }),
|
|
213727
214199
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "titlebar-separator" }),
|
|
213728
214200
|
agents.map((a) => {
|
|
213729
214201
|
const activeTab = tabs.find((t) => t.id === activeTabId);
|
|
@@ -213777,6 +214249,7 @@ function App() {
|
|
|
213777
214249
|
}
|
|
213778
214250
|
}
|
|
213779
214251
|
),
|
|
214252
|
+
showProjectPicker && /* @__PURE__ */ jsxRuntimeExports.jsx(ProjectPicker, { onDone: () => setShowProjectPicker(false) }),
|
|
213780
214253
|
showFloatingMic && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
213781
214254
|
FloatingMic,
|
|
213782
214255
|
{
|