@phenx-inc/ctlsurf 0.12.0 → 0.13.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 +29 -19
- package/out/headless/index.mjs.map +2 -2
- package/out/main/index.js +35 -19
- package/out/renderer/assets/{cssMode-R8fTFLae.js → cssMode-KhYyY-BM.js} +3 -3
- package/out/renderer/assets/{freemarker2-CyjWzWoP.js → freemarker2-BFsSgcWk.js} +1 -1
- package/out/renderer/assets/{handlebars-CrhCGIRM.js → handlebars-Be6_aBsm.js} +1 -1
- package/out/renderer/assets/{html-Cc3dPNZr.js → html-G8mvsyfc.js} +1 -1
- package/out/renderer/assets/{htmlMode-BWtG6ywk.js → htmlMode-Cfd5VCjw.js} +3 -3
- package/out/renderer/assets/{index-BL9njXIL.css → index-Bi_MjBqs.css} +233 -8
- package/out/renderer/assets/{index-kkG56aKv.js → index-MqgBcJzy.js} +392 -120
- package/out/renderer/assets/{javascript-C8T_SdLC.js → javascript-XyDWi6dC.js} +2 -2
- package/out/renderer/assets/{jsonMode-D1zR4VVU.js → jsonMode-DZT5gBVW.js} +3 -3
- package/out/renderer/assets/{liquid-COSMe9Uf.js → liquid-BuajCNJ9.js} +1 -1
- package/out/renderer/assets/{lspLanguageFeatures-CXGfrtzl.js → lspLanguageFeatures-BYkg2Yc-.js} +1 -1
- package/out/renderer/assets/{mdx-RfS44T-L.js → mdx-D0Qx2GMS.js} +1 -1
- package/out/renderer/assets/{python-DFSWKHUu.js → python-ChncNy6S.js} +1 -1
- package/out/renderer/assets/{razor-DtH2_uvo.js → razor-C6MUtfaS.js} +1 -1
- package/out/renderer/assets/{tsMode-BYIQ-S9Z.js → tsMode-C2aMdzdU.js} +1 -1
- package/out/renderer/assets/{typescript-HhQUr1Rb.js → typescript-CB71AtAT.js} +1 -1
- package/out/renderer/assets/{xml-KuhgdKfD.js → xml-tHS1Ec9w.js} +1 -1
- package/out/renderer/assets/{yaml-W_kzCFH7.js → yaml-CZcp5ueF.js} +1 -1
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/src/main/index.ts +13 -1
- package/src/main/orchestrator.ts +8 -1
- package/src/main/ticketStore.ts +26 -20
- package/src/renderer/App.tsx +19 -3
- package/src/renderer/components/CtlsurfPanel.tsx +169 -35
- package/src/renderer/components/SpeakControls.tsx +8 -2
- package/src/renderer/components/TerminalPanel.tsx +141 -44
- package/src/renderer/components/TicketPanel.tsx +126 -29
- package/src/renderer/styles.css +233 -8
|
@@ -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-KhYyY-BM.js","./lspLanguageFeatures-BYkg2Yc-.js","./htmlMode-Cfd5VCjw.js","./jsonMode-DZT5gBVW.js","./javascript-XyDWi6dC.js","./typescript-CB71AtAT.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
|
}
|
|
@@ -18829,36 +18829,41 @@ function copySelectionAsEmailTable(terminal) {
|
|
|
18829
18829
|
})
|
|
18830
18830
|
);
|
|
18831
18831
|
}
|
|
18832
|
-
function openExternal(uri) {
|
|
18833
|
-
const win = window.open();
|
|
18834
|
-
if (win) {
|
|
18835
|
-
try {
|
|
18836
|
-
win.opener = null;
|
|
18837
|
-
} catch {
|
|
18838
|
-
}
|
|
18839
|
-
win.location.href = uri;
|
|
18840
|
-
}
|
|
18841
|
-
}
|
|
18842
18832
|
function handleTerminalLink(_event, uri) {
|
|
18843
|
-
|
|
18844
|
-
|
|
18845
|
-
window.dispatchEvent(new CustomEvent("ctlsurf-open-url", { detail: { url: embedUrl } }));
|
|
18846
|
-
} else {
|
|
18847
|
-
openExternal(uri);
|
|
18848
|
-
}
|
|
18849
|
-
}).catch(() => openExternal(uri));
|
|
18833
|
+
const openInPanel = (url) => window.dispatchEvent(new CustomEvent("ctlsurf-open-url", { detail: { url } }));
|
|
18834
|
+
window.worker.getEmbedUrl(uri).then((embedUrl) => openInPanel(embedUrl || uri)).catch(() => openInPanel(uri));
|
|
18850
18835
|
}
|
|
18851
18836
|
const _terminals = /* @__PURE__ */ new Map();
|
|
18852
18837
|
function isAtBottom(terminal) {
|
|
18853
18838
|
const buf = terminal.buffer.active;
|
|
18854
|
-
return buf.
|
|
18839
|
+
return buf.baseY - buf.viewportY <= 2;
|
|
18855
18840
|
}
|
|
18856
|
-
function
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18841
|
+
function notifyPin(state) {
|
|
18842
|
+
state.pinListeners.forEach((fn) => fn(state.pinnedToBottom));
|
|
18843
|
+
}
|
|
18844
|
+
function setPinned(state, pinned) {
|
|
18845
|
+
if (pinned) state.anchorLine = null;
|
|
18846
|
+
if (state.pinnedToBottom === pinned) return;
|
|
18847
|
+
state.pinnedToBottom = pinned;
|
|
18848
|
+
notifyPin(state);
|
|
18849
|
+
}
|
|
18850
|
+
function reassert(state) {
|
|
18851
|
+
const { terminal } = state;
|
|
18852
|
+
state.holding = true;
|
|
18853
|
+
try {
|
|
18854
|
+
if (state.pinnedToBottom) {
|
|
18855
|
+
terminal.scrollToBottom();
|
|
18856
|
+
} else if (state.anchorLine != null && terminal.buffer.active.viewportY !== state.anchorLine) {
|
|
18857
|
+
terminal.scrollToLine(state.anchorLine);
|
|
18858
|
+
}
|
|
18859
|
+
} finally {
|
|
18860
|
+
state.holding = false;
|
|
18860
18861
|
}
|
|
18861
18862
|
}
|
|
18863
|
+
function markGesture(tabId) {
|
|
18864
|
+
const s = _terminals.get(tabId);
|
|
18865
|
+
if (s) s.userScrollPending = true;
|
|
18866
|
+
}
|
|
18862
18867
|
function getOrCreateTerminal(tabId, onExit) {
|
|
18863
18868
|
const existing = _terminals.get(tabId);
|
|
18864
18869
|
if (existing) {
|
|
@@ -18902,6 +18907,9 @@ function getOrCreateTerminal(tabId, onExit) {
|
|
|
18902
18907
|
terminal.loadAddon(new addonWebLinksExports.WebLinksAddon(handleTerminalLink));
|
|
18903
18908
|
terminal.attachCustomKeyEventHandler((e) => {
|
|
18904
18909
|
if (e.type !== "keydown") return true;
|
|
18910
|
+
if (e.key === "PageUp" || e.key === "PageDown" || e.key === "Home" || e.key === "End") {
|
|
18911
|
+
markGesture(tabId);
|
|
18912
|
+
}
|
|
18905
18913
|
const isCombo = (e.metaKey || e.ctrlKey) && e.shiftKey && e.code === "KeyE";
|
|
18906
18914
|
if (!isCombo) return true;
|
|
18907
18915
|
e.preventDefault();
|
|
@@ -18914,20 +18922,34 @@ function getOrCreateTerminal(tabId, onExit) {
|
|
|
18914
18922
|
unsubData: null,
|
|
18915
18923
|
unsubExit: null,
|
|
18916
18924
|
spawnedAgentId: null,
|
|
18917
|
-
pinnedToBottom: true
|
|
18925
|
+
pinnedToBottom: true,
|
|
18926
|
+
anchorLine: null,
|
|
18927
|
+
userScrollPending: false,
|
|
18928
|
+
holding: false,
|
|
18929
|
+
pinListeners: /* @__PURE__ */ new Set()
|
|
18918
18930
|
};
|
|
18919
18931
|
terminal.onScroll(() => {
|
|
18920
|
-
state.
|
|
18932
|
+
if (state.holding) return;
|
|
18933
|
+
if (!state.userScrollPending) {
|
|
18934
|
+
reassert(state);
|
|
18935
|
+
return;
|
|
18936
|
+
}
|
|
18937
|
+
state.userScrollPending = false;
|
|
18938
|
+
if (isAtBottom(terminal)) {
|
|
18939
|
+
setPinned(state, true);
|
|
18940
|
+
} else {
|
|
18941
|
+
state.anchorLine = terminal.buffer.active.viewportY;
|
|
18942
|
+
setPinned(state, false);
|
|
18943
|
+
}
|
|
18921
18944
|
});
|
|
18922
18945
|
terminal.onData((data) => {
|
|
18923
|
-
state
|
|
18946
|
+
setPinned(state, true);
|
|
18924
18947
|
terminal.scrollToBottom();
|
|
18925
18948
|
window.worker.writePty(tabId, data);
|
|
18926
18949
|
});
|
|
18927
18950
|
state.unsubData = window.worker.onPtyData((eventTabId, data) => {
|
|
18928
18951
|
if (eventTabId === tabId) {
|
|
18929
|
-
terminal.write(data);
|
|
18930
|
-
scrollIfPinned(tabId, terminal);
|
|
18952
|
+
terminal.write(data, () => reassert(state));
|
|
18931
18953
|
}
|
|
18932
18954
|
});
|
|
18933
18955
|
state.unsubExit = window.worker.onPtyExit((eventTabId, code) => {
|
|
@@ -18955,6 +18977,14 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
18955
18977
|
const containerRef = reactExports.useRef(null);
|
|
18956
18978
|
const [menu, setMenu] = reactExports.useState(null);
|
|
18957
18979
|
const [toast, setToast] = reactExports.useState(null);
|
|
18980
|
+
const [followBottom, setFollowBottom] = reactExports.useState(true);
|
|
18981
|
+
const jumpToLatest = () => {
|
|
18982
|
+
const s = _terminals.get(tabId);
|
|
18983
|
+
if (!s) return;
|
|
18984
|
+
setPinned(s, true);
|
|
18985
|
+
s.terminal.scrollToBottom();
|
|
18986
|
+
s.terminal.focus();
|
|
18987
|
+
};
|
|
18958
18988
|
const handleContextMenu = (e) => {
|
|
18959
18989
|
const sel = _terminals.get(tabId)?.terminal.getSelection() ?? "";
|
|
18960
18990
|
if (!convertToEmailTable(sel)) return;
|
|
@@ -19006,7 +19036,10 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
19006
19036
|
terminal.open(containerRef.current);
|
|
19007
19037
|
}
|
|
19008
19038
|
fitAddon.fit();
|
|
19009
|
-
|
|
19039
|
+
const attached = _terminals.get(tabId);
|
|
19040
|
+
if (attached) reassert(attached);
|
|
19041
|
+
const onWheel = () => markGesture(tabId);
|
|
19042
|
+
terminal.element?.addEventListener("wheel", onWheel, { passive: true });
|
|
19010
19043
|
let resizeTimeout;
|
|
19011
19044
|
const handleResize = () => {
|
|
19012
19045
|
clearTimeout(resizeTimeout);
|
|
@@ -19018,7 +19051,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
19018
19051
|
state.fitAddon.fit();
|
|
19019
19052
|
const { cols, rows } = state.terminal;
|
|
19020
19053
|
if (cols < 10 || rows < 5) return;
|
|
19021
|
-
|
|
19054
|
+
reassert(state);
|
|
19022
19055
|
window.worker.resizePty(tabId, cols, rows);
|
|
19023
19056
|
}, 150);
|
|
19024
19057
|
};
|
|
@@ -19029,6 +19062,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
19029
19062
|
clearTimeout(resizeTimeout);
|
|
19030
19063
|
window.removeEventListener("resize", handleResize);
|
|
19031
19064
|
observer.disconnect();
|
|
19065
|
+
terminal.element?.removeEventListener("wheel", onWheel);
|
|
19032
19066
|
};
|
|
19033
19067
|
}, [tabId, onExit]);
|
|
19034
19068
|
reactExports.useEffect(() => {
|
|
@@ -19042,7 +19076,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
19042
19076
|
const s = _terminals.get(tabId);
|
|
19043
19077
|
if (s) {
|
|
19044
19078
|
s.fitAddon.fit();
|
|
19045
|
-
s
|
|
19079
|
+
setPinned(s, true);
|
|
19046
19080
|
s.terminal.scrollToBottom();
|
|
19047
19081
|
const { cols, rows } = s.terminal;
|
|
19048
19082
|
window.worker.resizePty(tabId, cols, rows);
|
|
@@ -19059,7 +19093,7 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
19059
19093
|
if (state) {
|
|
19060
19094
|
state.fitAddon.fit();
|
|
19061
19095
|
state.terminal.focus();
|
|
19062
|
-
|
|
19096
|
+
reassert(state);
|
|
19063
19097
|
const { cols, rows } = state.terminal;
|
|
19064
19098
|
window.worker.resizePty(tabId, cols, rows);
|
|
19065
19099
|
}
|
|
@@ -19067,8 +19101,33 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
19067
19101
|
});
|
|
19068
19102
|
}
|
|
19069
19103
|
}, [isActive, tabId]);
|
|
19104
|
+
reactExports.useEffect(() => {
|
|
19105
|
+
const s = _terminals.get(tabId);
|
|
19106
|
+
if (!s) return;
|
|
19107
|
+
setFollowBottom(s.pinnedToBottom);
|
|
19108
|
+
const fn = (p) => setFollowBottom(p);
|
|
19109
|
+
s.pinListeners.add(fn);
|
|
19110
|
+
return () => {
|
|
19111
|
+
s.pinListeners.delete(fn);
|
|
19112
|
+
};
|
|
19113
|
+
}, [tabId]);
|
|
19070
19114
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
19071
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
19115
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "terminal-wrap", children: [
|
|
19116
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "terminal-container", ref: containerRef, onContextMenu: handleContextMenu }),
|
|
19117
|
+
!followBottom && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19118
|
+
"button",
|
|
19119
|
+
{
|
|
19120
|
+
type: "button",
|
|
19121
|
+
className: "term-jump-latest",
|
|
19122
|
+
onMouseDown: (e) => {
|
|
19123
|
+
e.preventDefault();
|
|
19124
|
+
jumpToLatest();
|
|
19125
|
+
},
|
|
19126
|
+
title: "Jump to latest output",
|
|
19127
|
+
children: "↓ Latest"
|
|
19128
|
+
}
|
|
19129
|
+
)
|
|
19130
|
+
] }),
|
|
19072
19131
|
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
19132
|
e.preventDefault();
|
|
19074
19133
|
runConvert();
|
|
@@ -20022,7 +20081,7 @@ function FloatingMic({ onTranscript, onHide }) {
|
|
|
20022
20081
|
] });
|
|
20023
20082
|
}
|
|
20024
20083
|
const SAMPLE = "This is how spoken agent replies will sound.";
|
|
20025
|
-
function SpeakControls() {
|
|
20084
|
+
function SpeakControls({ remote = false }) {
|
|
20026
20085
|
const [enabled, setEnabled] = reactExports.useState(false);
|
|
20027
20086
|
const [engine, setEngineState] = reactExports.useState(getEngine);
|
|
20028
20087
|
const [voices, setVoices] = reactExports.useState([]);
|
|
@@ -20114,7 +20173,7 @@ function SpeakControls() {
|
|
|
20114
20173
|
speech.stop();
|
|
20115
20174
|
speech.enqueue(SAMPLE);
|
|
20116
20175
|
}, []);
|
|
20117
|
-
const title = enabled ? "Spoken replies on — click to mute" : "Speak agent replies (off)";
|
|
20176
|
+
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
20177
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "speak-controls", ref: wrapRef, children: [
|
|
20119
20178
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20120
20179
|
"button",
|
|
@@ -20123,6 +20182,7 @@ function SpeakControls() {
|
|
|
20123
20182
|
className: `titlebar-btn titlebar-icon-btn speak-btn ${enabled ? "active" : ""}`,
|
|
20124
20183
|
onClick: toggle,
|
|
20125
20184
|
title,
|
|
20185
|
+
disabled: remote,
|
|
20126
20186
|
"aria-label": "Toggle spoken agent replies",
|
|
20127
20187
|
"aria-pressed": enabled,
|
|
20128
20188
|
children: [
|
|
@@ -20247,49 +20307,170 @@ function SpeakControls() {
|
|
|
20247
20307
|
error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "speak-error", children: error })
|
|
20248
20308
|
] });
|
|
20249
20309
|
}
|
|
20310
|
+
function displayUrl(raw) {
|
|
20311
|
+
try {
|
|
20312
|
+
const u = new URL(raw);
|
|
20313
|
+
u.searchParams.delete("_code");
|
|
20314
|
+
u.searchParams.delete("embed");
|
|
20315
|
+
return u.toString();
|
|
20316
|
+
} catch {
|
|
20317
|
+
return raw;
|
|
20318
|
+
}
|
|
20319
|
+
}
|
|
20250
20320
|
function CtlsurfPanel({ navigate }) {
|
|
20251
20321
|
const webviewRef = reactExports.useRef(null);
|
|
20252
|
-
const [
|
|
20322
|
+
const [src, setSrc] = reactExports.useState(null);
|
|
20323
|
+
const [address, setAddress] = reactExports.useState("");
|
|
20324
|
+
const [loading, setLoading] = reactExports.useState(false);
|
|
20325
|
+
const [nav, setNav] = reactExports.useState({ back: false, forward: false });
|
|
20253
20326
|
const [key, setKey] = reactExports.useState(0);
|
|
20254
|
-
const
|
|
20327
|
+
const hasSrcRef = reactExports.useRef(false);
|
|
20328
|
+
const readyRef = reactExports.useRef(false);
|
|
20329
|
+
const pendingRef = reactExports.useRef(null);
|
|
20330
|
+
const resolve2 = reactExports.useCallback(async (raw) => {
|
|
20331
|
+
try {
|
|
20332
|
+
return await window.worker.getEmbedUrl(raw) || raw;
|
|
20333
|
+
} catch {
|
|
20334
|
+
return raw;
|
|
20335
|
+
}
|
|
20336
|
+
}, []);
|
|
20337
|
+
const load = reactExports.useCallback((url) => {
|
|
20338
|
+
if (!url) return;
|
|
20339
|
+
setAddress(displayUrl(url));
|
|
20340
|
+
if (!hasSrcRef.current) {
|
|
20341
|
+
hasSrcRef.current = true;
|
|
20342
|
+
setSrc(url);
|
|
20343
|
+
return;
|
|
20344
|
+
}
|
|
20345
|
+
const wv = webviewRef.current;
|
|
20346
|
+
if (wv && readyRef.current) wv.loadURL(url);
|
|
20347
|
+
else pendingRef.current = url;
|
|
20348
|
+
}, []);
|
|
20349
|
+
const loadProject = reactExports.useCallback(async () => {
|
|
20255
20350
|
try {
|
|
20256
20351
|
const info = await window.worker.getWebviewInfo();
|
|
20257
|
-
|
|
20352
|
+
load(info.pageUrl || info.frontendUrl);
|
|
20258
20353
|
} catch (err) {
|
|
20259
20354
|
console.error("[ctlsurf] Failed to get webview info:", err);
|
|
20260
|
-
|
|
20355
|
+
load("https://app.ctlsurf.com");
|
|
20261
20356
|
}
|
|
20262
|
-
};
|
|
20357
|
+
}, [load]);
|
|
20263
20358
|
reactExports.useEffect(() => {
|
|
20264
|
-
if (!navigate?.url)
|
|
20359
|
+
if (!navigate?.url) loadProject();
|
|
20265
20360
|
}, []);
|
|
20266
20361
|
reactExports.useEffect(() => {
|
|
20267
|
-
if (navigate?.url)
|
|
20268
|
-
setUrl(navigate.url);
|
|
20269
|
-
setKey((k2) => k2 + 1);
|
|
20270
|
-
}
|
|
20362
|
+
if (navigate?.url) resolve2(navigate.url).then(load);
|
|
20271
20363
|
}, [navigate?.n]);
|
|
20272
20364
|
reactExports.useEffect(() => {
|
|
20273
20365
|
const unsub = window.worker.onCwdChanged(() => {
|
|
20274
|
-
|
|
20366
|
+
hasSrcRef.current = false;
|
|
20367
|
+
readyRef.current = false;
|
|
20368
|
+
pendingRef.current = null;
|
|
20369
|
+
setSrc(null);
|
|
20275
20370
|
setKey((k2) => k2 + 1);
|
|
20276
|
-
|
|
20371
|
+
loadProject();
|
|
20277
20372
|
});
|
|
20278
20373
|
return unsub;
|
|
20279
|
-
}, []);
|
|
20280
|
-
|
|
20281
|
-
|
|
20282
|
-
|
|
20283
|
-
|
|
20284
|
-
|
|
20285
|
-
|
|
20286
|
-
|
|
20287
|
-
|
|
20288
|
-
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20374
|
+
}, [loadProject]);
|
|
20375
|
+
reactExports.useEffect(() => {
|
|
20376
|
+
const wv = webviewRef.current;
|
|
20377
|
+
if (!wv) return;
|
|
20378
|
+
const syncNav = () => setNav({ back: wv.canGoBack?.() ?? false, forward: wv.canGoForward?.() ?? false });
|
|
20379
|
+
const onReady = () => {
|
|
20380
|
+
readyRef.current = true;
|
|
20381
|
+
if (pendingRef.current) {
|
|
20382
|
+
wv.loadURL(pendingRef.current);
|
|
20383
|
+
pendingRef.current = null;
|
|
20384
|
+
}
|
|
20385
|
+
syncNav();
|
|
20386
|
+
};
|
|
20387
|
+
const onNavigate = (e) => {
|
|
20388
|
+
const url = e.url;
|
|
20389
|
+
if (url) setAddress(displayUrl(url));
|
|
20390
|
+
syncNav();
|
|
20391
|
+
};
|
|
20392
|
+
const onStart = () => setLoading(true);
|
|
20393
|
+
const onStop = () => {
|
|
20394
|
+
setLoading(false);
|
|
20395
|
+
syncNav();
|
|
20396
|
+
};
|
|
20397
|
+
wv.addEventListener("dom-ready", onReady);
|
|
20398
|
+
wv.addEventListener("did-navigate", onNavigate);
|
|
20399
|
+
wv.addEventListener("did-navigate-in-page", onNavigate);
|
|
20400
|
+
wv.addEventListener("did-start-loading", onStart);
|
|
20401
|
+
wv.addEventListener("did-stop-loading", onStop);
|
|
20402
|
+
return () => {
|
|
20403
|
+
wv.removeEventListener("dom-ready", onReady);
|
|
20404
|
+
wv.removeEventListener("did-navigate", onNavigate);
|
|
20405
|
+
wv.removeEventListener("did-navigate-in-page", onNavigate);
|
|
20406
|
+
wv.removeEventListener("did-start-loading", onStart);
|
|
20407
|
+
wv.removeEventListener("did-stop-loading", onStop);
|
|
20408
|
+
};
|
|
20409
|
+
}, [src, key]);
|
|
20410
|
+
const onSubmit = (e) => {
|
|
20411
|
+
e.preventDefault();
|
|
20412
|
+
let target = address.trim();
|
|
20413
|
+
if (!target) return;
|
|
20414
|
+
if (!/^[a-z][a-z0-9+.-]*:\/\//i.test(target)) target = "https://" + target;
|
|
20415
|
+
resolve2(target).then(load);
|
|
20416
|
+
};
|
|
20417
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ctlsurf-panel", children: [
|
|
20418
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ctlsurf-addressbar", children: [
|
|
20419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20420
|
+
"button",
|
|
20421
|
+
{
|
|
20422
|
+
type: "button",
|
|
20423
|
+
className: "ctlsurf-nav-btn",
|
|
20424
|
+
title: "Back",
|
|
20425
|
+
disabled: !nav.back,
|
|
20426
|
+
onClick: () => webviewRef.current?.goBack?.(),
|
|
20427
|
+
children: "‹"
|
|
20428
|
+
}
|
|
20429
|
+
),
|
|
20430
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20431
|
+
"button",
|
|
20432
|
+
{
|
|
20433
|
+
type: "button",
|
|
20434
|
+
className: "ctlsurf-nav-btn",
|
|
20435
|
+
title: "Forward",
|
|
20436
|
+
disabled: !nav.forward,
|
|
20437
|
+
onClick: () => webviewRef.current?.goForward?.(),
|
|
20438
|
+
children: "›"
|
|
20439
|
+
}
|
|
20440
|
+
),
|
|
20441
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20442
|
+
"button",
|
|
20443
|
+
{
|
|
20444
|
+
type: "button",
|
|
20445
|
+
className: "ctlsurf-nav-btn",
|
|
20446
|
+
title: loading ? "Stop" : "Reload",
|
|
20447
|
+
onClick: () => loading ? webviewRef.current?.stop?.() : webviewRef.current?.reload?.(),
|
|
20448
|
+
children: loading ? "×" : "⟳"
|
|
20449
|
+
}
|
|
20450
|
+
),
|
|
20451
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("form", { className: "ctlsurf-address-form", onSubmit, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20452
|
+
"input",
|
|
20453
|
+
{
|
|
20454
|
+
className: "ctlsurf-address-input",
|
|
20455
|
+
value: address,
|
|
20456
|
+
spellCheck: false,
|
|
20457
|
+
placeholder: "Enter a URL",
|
|
20458
|
+
onChange: (e) => setAddress(e.target.value),
|
|
20459
|
+
onFocus: (e) => e.currentTarget.select()
|
|
20460
|
+
}
|
|
20461
|
+
) })
|
|
20462
|
+
] }),
|
|
20463
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ctlsurf-webview-host", children: src ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20464
|
+
"webview",
|
|
20465
|
+
{
|
|
20466
|
+
ref: webviewRef,
|
|
20467
|
+
src,
|
|
20468
|
+
style: { width: "100%", height: "100%" },
|
|
20469
|
+
allowpopups: "true"
|
|
20470
|
+
},
|
|
20471
|
+
key
|
|
20472
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ctlsurf-webview-loading", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#565f89", fontSize: "13px" }, children: "Loading ctlsurf..." }) }) })
|
|
20473
|
+
] });
|
|
20293
20474
|
}
|
|
20294
20475
|
function _arrayLikeToArray(r, a) {
|
|
20295
20476
|
(null == a || a > r.length) && (a = r.length);
|
|
@@ -207841,7 +208022,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
|
|
|
207841
208022
|
modeConfigurationDefault$2
|
|
207842
208023
|
);
|
|
207843
208024
|
function getMode$3() {
|
|
207844
|
-
return __vitePreload(() => import("./cssMode-
|
|
208025
|
+
return __vitePreload(() => import("./cssMode-KhYyY-BM.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
|
|
207845
208026
|
}
|
|
207846
208027
|
languages.onLanguage("less", () => {
|
|
207847
208028
|
getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
|
|
@@ -207946,7 +208127,7 @@ const razorLanguageService = registerHTMLLanguageService(
|
|
|
207946
208127
|
);
|
|
207947
208128
|
const razorDefaults = razorLanguageService.defaults;
|
|
207948
208129
|
function getMode$2() {
|
|
207949
|
-
return __vitePreload(() => import("./htmlMode-
|
|
208130
|
+
return __vitePreload(() => import("./htmlMode-Cfd5VCjw.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
|
|
207950
208131
|
}
|
|
207951
208132
|
function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
|
|
207952
208133
|
const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
|
|
@@ -208030,7 +208211,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
|
|
|
208030
208211
|
);
|
|
208031
208212
|
const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
|
|
208032
208213
|
function getMode$1() {
|
|
208033
|
-
return __vitePreload(() => import("./jsonMode-
|
|
208214
|
+
return __vitePreload(() => import("./jsonMode-DZT5gBVW.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
|
|
208034
208215
|
}
|
|
208035
208216
|
languages.register({
|
|
208036
208217
|
id: "json",
|
|
@@ -208276,7 +208457,7 @@ const getJavaScriptWorker = () => {
|
|
|
208276
208457
|
return getMode().then((mode) => mode.getJavaScriptWorker());
|
|
208277
208458
|
};
|
|
208278
208459
|
function getMode() {
|
|
208279
|
-
return __vitePreload(() => import("./tsMode-
|
|
208460
|
+
return __vitePreload(() => import("./tsMode-C2aMdzdU.js"), true ? [] : void 0, import.meta.url);
|
|
208280
208461
|
}
|
|
208281
208462
|
languages.onLanguage("typescript", () => {
|
|
208282
208463
|
return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
|
|
@@ -208471,49 +208652,49 @@ registerLanguage({
|
|
|
208471
208652
|
extensions: [".ftl", ".ftlh", ".ftlx"],
|
|
208472
208653
|
aliases: ["FreeMarker2", "Apache FreeMarker2"],
|
|
208473
208654
|
loader: () => {
|
|
208474
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208655
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
|
|
208475
208656
|
}
|
|
208476
208657
|
});
|
|
208477
208658
|
registerLanguage({
|
|
208478
208659
|
id: "freemarker2.tag-angle.interpolation-dollar",
|
|
208479
208660
|
aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
|
|
208480
208661
|
loader: () => {
|
|
208481
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208662
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
|
|
208482
208663
|
}
|
|
208483
208664
|
});
|
|
208484
208665
|
registerLanguage({
|
|
208485
208666
|
id: "freemarker2.tag-bracket.interpolation-dollar",
|
|
208486
208667
|
aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
|
|
208487
208668
|
loader: () => {
|
|
208488
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208669
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
|
|
208489
208670
|
}
|
|
208490
208671
|
});
|
|
208491
208672
|
registerLanguage({
|
|
208492
208673
|
id: "freemarker2.tag-angle.interpolation-bracket",
|
|
208493
208674
|
aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
|
|
208494
208675
|
loader: () => {
|
|
208495
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208676
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
|
|
208496
208677
|
}
|
|
208497
208678
|
});
|
|
208498
208679
|
registerLanguage({
|
|
208499
208680
|
id: "freemarker2.tag-bracket.interpolation-bracket",
|
|
208500
208681
|
aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
|
|
208501
208682
|
loader: () => {
|
|
208502
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208683
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
|
|
208503
208684
|
}
|
|
208504
208685
|
});
|
|
208505
208686
|
registerLanguage({
|
|
208506
208687
|
id: "freemarker2.tag-auto.interpolation-dollar",
|
|
208507
208688
|
aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
|
|
208508
208689
|
loader: () => {
|
|
208509
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208690
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
|
|
208510
208691
|
}
|
|
208511
208692
|
});
|
|
208512
208693
|
registerLanguage({
|
|
208513
208694
|
id: "freemarker2.tag-auto.interpolation-bracket",
|
|
208514
208695
|
aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
|
|
208515
208696
|
loader: () => {
|
|
208516
|
-
return __vitePreload(() => import("./freemarker2-
|
|
208697
|
+
return __vitePreload(() => import("./freemarker2-BFsSgcWk.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
|
|
208517
208698
|
}
|
|
208518
208699
|
});
|
|
208519
208700
|
registerLanguage({
|
|
@@ -208534,7 +208715,7 @@ registerLanguage({
|
|
|
208534
208715
|
extensions: [".handlebars", ".hbs"],
|
|
208535
208716
|
aliases: ["Handlebars", "handlebars", "hbs"],
|
|
208536
208717
|
mimetypes: ["text/x-handlebars-template"],
|
|
208537
|
-
loader: () => __vitePreload(() => import("./handlebars-
|
|
208718
|
+
loader: () => __vitePreload(() => import("./handlebars-Be6_aBsm.js"), true ? [] : void 0, import.meta.url)
|
|
208538
208719
|
});
|
|
208539
208720
|
registerLanguage({
|
|
208540
208721
|
id: "hcl",
|
|
@@ -208547,7 +208728,7 @@ registerLanguage({
|
|
|
208547
208728
|
extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
|
|
208548
208729
|
aliases: ["HTML", "htm", "html", "xhtml"],
|
|
208549
208730
|
mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
|
|
208550
|
-
loader: () => __vitePreload(() => import("./html-
|
|
208731
|
+
loader: () => __vitePreload(() => import("./html-G8mvsyfc.js"), true ? [] : void 0, import.meta.url)
|
|
208551
208732
|
});
|
|
208552
208733
|
registerLanguage({
|
|
208553
208734
|
id: "ini",
|
|
@@ -208570,7 +208751,7 @@ registerLanguage({
|
|
|
208570
208751
|
filenames: ["jakefile"],
|
|
208571
208752
|
aliases: ["JavaScript", "javascript", "js"],
|
|
208572
208753
|
mimetypes: ["text/javascript"],
|
|
208573
|
-
loader: () => __vitePreload(() => import("./javascript-
|
|
208754
|
+
loader: () => __vitePreload(() => import("./javascript-XyDWi6dC.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
|
|
208574
208755
|
});
|
|
208575
208756
|
registerLanguage({
|
|
208576
208757
|
id: "julia",
|
|
@@ -208609,7 +208790,7 @@ registerLanguage({
|
|
|
208609
208790
|
extensions: [".liquid", ".html.liquid"],
|
|
208610
208791
|
aliases: ["Liquid", "liquid"],
|
|
208611
208792
|
mimetypes: ["application/liquid"],
|
|
208612
|
-
loader: () => __vitePreload(() => import("./liquid-
|
|
208793
|
+
loader: () => __vitePreload(() => import("./liquid-BuajCNJ9.js"), true ? [] : void 0, import.meta.url)
|
|
208613
208794
|
});
|
|
208614
208795
|
registerLanguage({
|
|
208615
208796
|
id: "m3",
|
|
@@ -208627,7 +208808,7 @@ registerLanguage({
|
|
|
208627
208808
|
id: "mdx",
|
|
208628
208809
|
extensions: [".mdx"],
|
|
208629
208810
|
aliases: ["MDX", "mdx"],
|
|
208630
|
-
loader: () => __vitePreload(() => import("./mdx-
|
|
208811
|
+
loader: () => __vitePreload(() => import("./mdx-D0Qx2GMS.js"), true ? [] : void 0, import.meta.url)
|
|
208631
208812
|
});
|
|
208632
208813
|
registerLanguage({
|
|
208633
208814
|
id: "mips",
|
|
@@ -208726,7 +208907,7 @@ registerLanguage({
|
|
|
208726
208907
|
extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
|
|
208727
208908
|
aliases: ["Python", "py"],
|
|
208728
208909
|
firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
|
|
208729
|
-
loader: () => __vitePreload(() => import("./python-
|
|
208910
|
+
loader: () => __vitePreload(() => import("./python-ChncNy6S.js"), true ? [] : void 0, import.meta.url)
|
|
208730
208911
|
});
|
|
208731
208912
|
registerLanguage({
|
|
208732
208913
|
id: "qsharp",
|
|
@@ -208745,7 +208926,7 @@ registerLanguage({
|
|
|
208745
208926
|
extensions: [".cshtml"],
|
|
208746
208927
|
aliases: ["Razor", "razor"],
|
|
208747
208928
|
mimetypes: ["text/x-cshtml"],
|
|
208748
|
-
loader: () => __vitePreload(() => import("./razor-
|
|
208929
|
+
loader: () => __vitePreload(() => import("./razor-C6MUtfaS.js"), true ? [] : void 0, import.meta.url)
|
|
208749
208930
|
});
|
|
208750
208931
|
registerLanguage({
|
|
208751
208932
|
id: "redis",
|
|
@@ -208878,7 +209059,7 @@ registerLanguage({
|
|
|
208878
209059
|
aliases: ["TypeScript", "ts", "typescript"],
|
|
208879
209060
|
mimetypes: ["text/typescript"],
|
|
208880
209061
|
loader: () => {
|
|
208881
|
-
return __vitePreload(() => import("./typescript-
|
|
209062
|
+
return __vitePreload(() => import("./typescript-CB71AtAT.js"), true ? [] : void 0, import.meta.url);
|
|
208882
209063
|
}
|
|
208883
209064
|
});
|
|
208884
209065
|
registerLanguage({
|
|
@@ -208923,14 +209104,14 @@ registerLanguage({
|
|
|
208923
209104
|
firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
|
|
208924
209105
|
aliases: ["XML", "xml"],
|
|
208925
209106
|
mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
|
|
208926
|
-
loader: () => __vitePreload(() => import("./xml-
|
|
209107
|
+
loader: () => __vitePreload(() => import("./xml-tHS1Ec9w.js"), true ? [] : void 0, import.meta.url)
|
|
208927
209108
|
});
|
|
208928
209109
|
registerLanguage({
|
|
208929
209110
|
id: "yaml",
|
|
208930
209111
|
extensions: [".yaml", ".yml"],
|
|
208931
209112
|
aliases: ["YAML", "yaml", "YML", "yml"],
|
|
208932
209113
|
mimetypes: ["application/x-yaml", "text/x-yaml"],
|
|
208933
|
-
loader: () => __vitePreload(() => import("./yaml-
|
|
209114
|
+
loader: () => __vitePreload(() => import("./yaml-CZcp5ueF.js"), true ? [] : void 0, import.meta.url)
|
|
208934
209115
|
});
|
|
208935
209116
|
var __defProp = Object.defineProperty;
|
|
208936
209117
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -213443,6 +213624,47 @@ function TagIcon({ size: size2 = 16 }) {
|
|
|
213443
213624
|
}
|
|
213444
213625
|
);
|
|
213445
213626
|
}
|
|
213627
|
+
function SendIcon({ size: size2 = 15 }) {
|
|
213628
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
213629
|
+
"svg",
|
|
213630
|
+
{
|
|
213631
|
+
viewBox: "0 0 24 24",
|
|
213632
|
+
width: size2,
|
|
213633
|
+
height: size2,
|
|
213634
|
+
fill: "none",
|
|
213635
|
+
stroke: "currentColor",
|
|
213636
|
+
strokeWidth: "2",
|
|
213637
|
+
strokeLinecap: "round",
|
|
213638
|
+
strokeLinejoin: "round",
|
|
213639
|
+
"aria-hidden": "true",
|
|
213640
|
+
children: [
|
|
213641
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
|
|
213642
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
|
|
213643
|
+
]
|
|
213644
|
+
}
|
|
213645
|
+
);
|
|
213646
|
+
}
|
|
213647
|
+
function ticketPrompt(t, refs) {
|
|
213648
|
+
const lines = [
|
|
213649
|
+
"Please work on this ticket:",
|
|
213650
|
+
`Title: ${t.title || "Untitled"}`,
|
|
213651
|
+
`Priority: ${t.priority}`
|
|
213652
|
+
];
|
|
213653
|
+
const desc = t.description?.trim();
|
|
213654
|
+
if (desc) lines.push("", desc);
|
|
213655
|
+
lines.push(
|
|
213656
|
+
"",
|
|
213657
|
+
"ctlsurf references (use the ctlsurf MCP tools to read details or update status):",
|
|
213658
|
+
`- Ticket row ID: ${t.id}`
|
|
213659
|
+
);
|
|
213660
|
+
if (refs) {
|
|
213661
|
+
lines.push(
|
|
213662
|
+
`- Tickets datastore block ID: ${refs.blockId}`,
|
|
213663
|
+
`- Agent Datastore page ID: ${refs.pageId}`
|
|
213664
|
+
);
|
|
213665
|
+
}
|
|
213666
|
+
return lines.join("\n");
|
|
213667
|
+
}
|
|
213446
213668
|
function Segmented({ options, value, onChange }) {
|
|
213447
213669
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-segmented", children: options.map((o) => {
|
|
213448
213670
|
const active = o.value === value;
|
|
@@ -213462,12 +213684,50 @@ function Segmented({ options, value, onChange }) {
|
|
|
213462
213684
|
);
|
|
213463
213685
|
}) });
|
|
213464
213686
|
}
|
|
213465
|
-
function
|
|
213687
|
+
function TicketCard({ ticket, onClick, onSend }) {
|
|
213688
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card", children: [
|
|
213689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ticket-card-open", onClick, title: "Edit ticket", children: [
|
|
213690
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-bar", style: { background: colorOf(STATUS_OPTIONS, ticket.status) } }),
|
|
213691
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card-main", children: [
|
|
213692
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-title", children: ticket.title || "Untitled" }),
|
|
213693
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-card-meta", children: [
|
|
213694
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ticket-card-status", style: { color: colorOf(STATUS_OPTIONS, ticket.status) }, children: [
|
|
213695
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-seg-dot", style: { background: colorOf(STATUS_OPTIONS, ticket.status) } }),
|
|
213696
|
+
ticket.status
|
|
213697
|
+
] }),
|
|
213698
|
+
ticket.created && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-date", children: formatDate(ticket.created) })
|
|
213699
|
+
] })
|
|
213700
|
+
] }),
|
|
213701
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
213702
|
+
"span",
|
|
213703
|
+
{
|
|
213704
|
+
className: "ticket-card-pri",
|
|
213705
|
+
style: { color: colorOf(PRIORITY_OPTIONS, ticket.priority), borderColor: `${colorOf(PRIORITY_OPTIONS, ticket.priority)}66` },
|
|
213706
|
+
children: ticket.priority
|
|
213707
|
+
}
|
|
213708
|
+
)
|
|
213709
|
+
] }),
|
|
213710
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
213711
|
+
"button",
|
|
213712
|
+
{
|
|
213713
|
+
type: "button",
|
|
213714
|
+
className: "ticket-card-send",
|
|
213715
|
+
onClick: onSend,
|
|
213716
|
+
title: "Send to coding terminal",
|
|
213717
|
+
"aria-label": "Send ticket to coding terminal",
|
|
213718
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(SendIcon, {})
|
|
213719
|
+
}
|
|
213720
|
+
)
|
|
213721
|
+
] });
|
|
213722
|
+
}
|
|
213723
|
+
function TicketPane({ onSendToTerminal }) {
|
|
213466
213724
|
const [project, setProject] = reactExports.useState(null);
|
|
213467
213725
|
const [view, setView] = reactExports.useState("list");
|
|
213468
213726
|
const [tickets, setTickets] = reactExports.useState([]);
|
|
213727
|
+
const [refs, setRefs] = reactExports.useState(null);
|
|
213469
213728
|
const [listLoading, setListLoading] = reactExports.useState(false);
|
|
213470
213729
|
const [listError, setListError] = reactExports.useState(null);
|
|
213730
|
+
const [showDone, setShowDone] = reactExports.useState(false);
|
|
213471
213731
|
const [editingId, setEditingId] = reactExports.useState(null);
|
|
213472
213732
|
const [title, setTitle] = reactExports.useState("");
|
|
213473
213733
|
const [description, setDescription] = reactExports.useState("");
|
|
@@ -213479,13 +213739,17 @@ function TicketPane() {
|
|
|
213479
213739
|
setListError(null);
|
|
213480
213740
|
try {
|
|
213481
213741
|
const r = await window.worker.listTickets();
|
|
213482
|
-
if (r?.ok)
|
|
213483
|
-
|
|
213742
|
+
if (r?.ok) {
|
|
213743
|
+
setTickets(r.tickets || []);
|
|
213744
|
+
setRefs(r.blockId && r.pageId ? { blockId: r.blockId, pageId: r.pageId } : null);
|
|
213745
|
+
} else {
|
|
213484
213746
|
setTickets([]);
|
|
213747
|
+
setRefs(null);
|
|
213485
213748
|
setListError(r?.error || "Failed to load tickets");
|
|
213486
213749
|
}
|
|
213487
213750
|
} catch (err) {
|
|
213488
213751
|
setTickets([]);
|
|
213752
|
+
setRefs(null);
|
|
213489
213753
|
setListError(err?.message || "Failed to load tickets");
|
|
213490
213754
|
} finally {
|
|
213491
213755
|
setListLoading(false);
|
|
@@ -213557,17 +213821,22 @@ function TicketPane() {
|
|
|
213557
213821
|
window.addEventListener("keydown", onKey);
|
|
213558
213822
|
return () => window.removeEventListener("keydown", onKey);
|
|
213559
213823
|
}, [view, handleSave]);
|
|
213824
|
+
const activeTickets = tickets.filter((t) => t.status !== "Done");
|
|
213825
|
+
const doneTickets = tickets.filter((t) => t.status === "Done");
|
|
213560
213826
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-pane", role: "region", "aria-label": "Tickets", children: [
|
|
213561
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
213562
|
-
|
|
213563
|
-
|
|
213564
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
213565
|
-
|
|
213566
|
-
"
|
|
213567
|
-
|
|
213568
|
-
|
|
213569
|
-
|
|
213570
|
-
|
|
213827
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-header", children: [
|
|
213828
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-heading", children: [
|
|
213829
|
+
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 }) }),
|
|
213830
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-headtext", children: [
|
|
213831
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-title", children: view === "form" ? editingId ? "Edit ticket" : "New ticket" : "Tickets" }),
|
|
213832
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-subtitle", children: project ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
213833
|
+
"in ",
|
|
213834
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: project })
|
|
213835
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-warn", children: "no ctlsurf project for this tab" }) })
|
|
213836
|
+
] })
|
|
213837
|
+
] }),
|
|
213838
|
+
view === "list" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-drawer-new", onClick: openNewForm, title: "New ticket", children: "+ New" })
|
|
213839
|
+
] }),
|
|
213571
213840
|
view === "list" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
213572
213841
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-list-body", children: [
|
|
213573
213842
|
listLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-list-msg", children: "Loading tickets…" }),
|
|
@@ -213580,32 +213849,27 @@ function TicketPane() {
|
|
|
213580
213849
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-title", children: "No tickets yet" }),
|
|
213581
213850
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-empty-hint", children: "Log the first one for this project." })
|
|
213582
213851
|
] }),
|
|
213583
|
-
!listLoading &&
|
|
213584
|
-
|
|
213585
|
-
|
|
213586
|
-
|
|
213587
|
-
|
|
213588
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ticket-card-status", style: { color: colorOf(STATUS_OPTIONS, t.status) }, children: [
|
|
213589
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-seg-dot", style: { background: colorOf(STATUS_OPTIONS, t.status) } }),
|
|
213590
|
-
t.status
|
|
213591
|
-
] }),
|
|
213592
|
-
t.created && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-card-date", children: formatDate(t.created) })
|
|
213593
|
-
] })
|
|
213594
|
-
] }),
|
|
213595
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
213596
|
-
"span",
|
|
213852
|
+
!listLoading && activeTickets.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsx(TicketCard, { ticket: t, onClick: () => openEditForm(t), onSend: () => onSendToTerminal(ticketPrompt(t, refs)) }, t.id)),
|
|
213853
|
+
!listLoading && activeTickets.length === 0 && doneTickets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-list-msg", children: "Nothing open — all caught up." }),
|
|
213854
|
+
!listLoading && doneTickets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
213855
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
213856
|
+
"button",
|
|
213597
213857
|
{
|
|
213598
|
-
|
|
213599
|
-
|
|
213600
|
-
|
|
213858
|
+
type: "button",
|
|
213859
|
+
className: "ticket-done-toggle",
|
|
213860
|
+
onClick: () => setShowDone((v2) => !v2),
|
|
213861
|
+
"aria-expanded": showDone,
|
|
213862
|
+
children: [
|
|
213863
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `ticket-done-caret ${showDone ? "open" : ""}`, "aria-hidden": "true", children: "▸" }),
|
|
213864
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-done-label", children: "Done" }),
|
|
213865
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-done-count", children: doneTickets.length })
|
|
213866
|
+
]
|
|
213601
213867
|
}
|
|
213602
|
-
)
|
|
213603
|
-
|
|
213868
|
+
),
|
|
213869
|
+
showDone && doneTickets.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsx(TicketCard, { ticket: t, onClick: () => openEditForm(t), onSend: () => onSendToTerminal(ticketPrompt(t, refs)) }, t.id))
|
|
213870
|
+
] })
|
|
213604
213871
|
] }),
|
|
213605
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
213606
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-hint", children: tickets.length > 0 && `${tickets.length} ticket${tickets.length === 1 ? "" : "s"}` }),
|
|
213607
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ticket-btn-primary", onClick: openNewForm, children: "+ New ticket" })
|
|
213608
|
-
] })
|
|
213872
|
+
tickets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ticket-drawer-footer", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ticket-drawer-hint", children: doneTickets.length > 0 ? `${activeTickets.length} open · ${doneTickets.length} done` : `${tickets.length} ticket${tickets.length === 1 ? "" : "s"}` }) })
|
|
213609
213873
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
213610
213874
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ticket-drawer-body", children: [
|
|
213611
213875
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ticket-field", children: [
|
|
@@ -213798,6 +214062,13 @@ function App() {
|
|
|
213798
214062
|
focusTerminal(activeTabId);
|
|
213799
214063
|
setTimeout(() => window.worker.writePty(activeTabId, "\r"), 80);
|
|
213800
214064
|
}, [activeTabId]);
|
|
214065
|
+
const handleSendToTerminal = reactExports.useCallback((text2) => {
|
|
214066
|
+
const trimmed = text2.trim();
|
|
214067
|
+
if (!trimmed) return;
|
|
214068
|
+
window.worker.writePty(activeTabId, trimmed);
|
|
214069
|
+
focusTerminal(activeTabId);
|
|
214070
|
+
setTimeout(() => window.worker.writePty(activeTabId, "\r"), 120);
|
|
214071
|
+
}, [activeTabId]);
|
|
213801
214072
|
const cwdRef = reactExports.useRef(null);
|
|
213802
214073
|
const handleSpawn = reactExports.useCallback(async (tabId, agent) => {
|
|
213803
214074
|
setTabs((prev) => prev.map((t) => t.id === tabId ? { ...t, agentStatus: "active" } : t));
|
|
@@ -213950,6 +214221,7 @@ function App() {
|
|
|
213950
214221
|
window.addEventListener("ctlsurf-open-url", onOpen);
|
|
213951
214222
|
return () => window.removeEventListener("ctlsurf-open-url", onOpen);
|
|
213952
214223
|
}, [layout2, togglePane]);
|
|
214224
|
+
const activeAgentIsRemote = !!tabs.find((t) => t.id === activeTabId)?.agent?.id?.startsWith("remote-");
|
|
213953
214225
|
const panes = [
|
|
213954
214226
|
{ id: "editor", label: "Editor", content: /* @__PURE__ */ jsxRuntimeExports.jsx(EditorPanel, { cwd: cwd2 }) },
|
|
213955
214227
|
{
|
|
@@ -214009,7 +214281,7 @@ function App() {
|
|
|
214009
214281
|
] })
|
|
214010
214282
|
},
|
|
214011
214283
|
{ id: "ctlsurf", label: "ctlsurf", content: /* @__PURE__ */ jsxRuntimeExports.jsx(CtlsurfPanel, { navigate: ctlsurfNav }) },
|
|
214012
|
-
{ id: "tickets", label: "Tickets", content: /* @__PURE__ */ jsxRuntimeExports.jsx(TicketPane, {}) }
|
|
214284
|
+
{ id: "tickets", label: "Tickets", content: /* @__PURE__ */ jsxRuntimeExports.jsx(TicketPane, { onSendToTerminal: handleSendToTerminal }) }
|
|
214013
214285
|
];
|
|
214014
214286
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "app", children: [
|
|
214015
214287
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "titlebar", children: [
|
|
@@ -214095,7 +214367,7 @@ function App() {
|
|
|
214095
214367
|
)
|
|
214096
214368
|
}
|
|
214097
214369
|
),
|
|
214098
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SpeakControls, {}),
|
|
214370
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SpeakControls, { remote: activeAgentIsRemote }),
|
|
214099
214371
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "titlebar-separator" }),
|
|
214100
214372
|
agents.map((a) => {
|
|
214101
214373
|
const activeTab = tabs.find((t) => t.id === activeTabId);
|