@phenx-inc/ctlsurf 0.2.0 → 0.3.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 +320 -44
- package/out/headless/index.mjs.map +4 -4
- package/out/main/index.js +275 -15
- package/out/preload/index.js +3 -0
- package/out/renderer/assets/{cssMode-D3kH1Kju.js → cssMode-BW-SuYuP.js} +3 -3
- package/out/renderer/assets/{freemarker2-BCHZUSLb.js → freemarker2-2YWYzawi.js} +1 -1
- package/out/renderer/assets/{handlebars-DKx-Fw-H.js → handlebars-EwtUQRsf.js} +1 -1
- package/out/renderer/assets/{html-BSCM04uL.js → html-BNZkIDb9.js} +1 -1
- package/out/renderer/assets/{htmlMode-BucU1MUc.js → htmlMode-C2dZKrOy.js} +3 -3
- package/out/renderer/assets/{index-BsdOeO0U.js → index-Bm_rbVP-.js} +114 -34
- package/out/renderer/assets/{index-BzF7I1my.css → index-CrTu3Z4M.css} +21 -0
- package/out/renderer/assets/{javascript-bPY5C4uq.js → javascript-busdVZMv.js} +2 -2
- package/out/renderer/assets/{jsonMode-BmJotb6E.js → jsonMode-BaVI6jAw.js} +3 -3
- package/out/renderer/assets/{liquid-Cja_Pzh3.js → liquid-DG08un1Q.js} +1 -1
- package/out/renderer/assets/{lspLanguageFeatures-hoVZfVKv.js → lspLanguageFeatures-peGVtLxi.js} +1 -1
- package/out/renderer/assets/{mdx-C0s81MOq.js → mdx-DogBhUxZ.js} +1 -1
- package/out/renderer/assets/{python-CulkBOJr.js → python-Bf-INYXh.js} +1 -1
- package/out/renderer/assets/{razor-czmzhwVZ.js → razor-DLrZ2hsF.js} +1 -1
- package/out/renderer/assets/{tsMode-B90EqYGx.js → tsMode-B4oEmliC.js} +1 -1
- package/out/renderer/assets/{typescript-Ckc6emP2.js → typescript-CjkgfhVK.js} +1 -1
- package/out/renderer/assets/{xml-CKh-JyGN.js → xml-0FAXmuVg.js} +1 -1
- package/out/renderer/assets/{yaml-B49zLim4.js → yaml-DWxnPuy8.js} +1 -1
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/src/main/ctlsurfApi.ts +26 -0
- package/src/main/headless.ts +33 -28
- package/src/main/index.ts +8 -0
- package/src/main/orchestrator.ts +63 -2
- package/src/main/timeTracker.ts +223 -0
- package/src/main/tui.ts +25 -5
- package/src/preload/index.ts +7 -1
- package/src/renderer/App.tsx +36 -0
- package/src/renderer/components/SettingsDialog.tsx +38 -1
- package/src/renderer/components/TerminalPanel.tsx +25 -13
- package/src/renderer/styles.css +21 -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-BW-SuYuP.js","./lspLanguageFeatures-peGVtLxi.js","./htmlMode-C2dZKrOy.js","./jsonMode-BaVI6jAw.js","./javascript-busdVZMv.js","./typescript-CjkgfhVK.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
|
}
|
|
@@ -18827,13 +18827,15 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
18827
18827
|
const handleResize = () => {
|
|
18828
18828
|
clearTimeout(resizeTimeout);
|
|
18829
18829
|
resizeTimeout = setTimeout(() => {
|
|
18830
|
+
const el = containerRef.current;
|
|
18831
|
+
if (!el || el.offsetWidth === 0 || el.offsetHeight === 0) return;
|
|
18830
18832
|
const state = _terminals.get(tabId);
|
|
18831
|
-
if (state)
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18833
|
+
if (!state) return;
|
|
18834
|
+
state.fitAddon.fit();
|
|
18835
|
+
const { cols, rows } = state.terminal;
|
|
18836
|
+
if (cols < 10 || rows < 5) return;
|
|
18837
|
+
scrollIfPinned(tabId, state.terminal);
|
|
18838
|
+
window.worker.resizePty(tabId, cols, rows);
|
|
18837
18839
|
}, 150);
|
|
18838
18840
|
};
|
|
18839
18841
|
window.addEventListener("resize", handleResize);
|
|
@@ -18866,12 +18868,19 @@ function TerminalPanel({ tabId, agent, onSpawn, onExit, isActive }) {
|
|
|
18866
18868
|
}, [tabId, agent, onSpawn]);
|
|
18867
18869
|
reactExports.useEffect(() => {
|
|
18868
18870
|
if (isActive) {
|
|
18869
|
-
const state = _terminals.get(tabId);
|
|
18870
|
-
if (state) {
|
|
18871
|
-
state.fitAddon.fit();
|
|
18872
|
-
state.terminal.focus();
|
|
18873
|
-
}
|
|
18874
18871
|
window.worker.setActiveTab(tabId);
|
|
18872
|
+
requestAnimationFrame(() => {
|
|
18873
|
+
setTimeout(() => {
|
|
18874
|
+
const state = _terminals.get(tabId);
|
|
18875
|
+
if (state) {
|
|
18876
|
+
state.fitAddon.fit();
|
|
18877
|
+
state.terminal.focus();
|
|
18878
|
+
scrollIfPinned(tabId, state.terminal);
|
|
18879
|
+
const { cols, rows } = state.terminal;
|
|
18880
|
+
window.worker.resizePty(tabId, cols, rows);
|
|
18881
|
+
}
|
|
18882
|
+
}, 50);
|
|
18883
|
+
});
|
|
18875
18884
|
}
|
|
18876
18885
|
}, [isActive, tabId]);
|
|
18877
18886
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "terminal-container", ref: containerRef });
|
|
@@ -206549,7 +206558,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
|
|
|
206549
206558
|
modeConfigurationDefault$2
|
|
206550
206559
|
);
|
|
206551
206560
|
function getMode$3() {
|
|
206552
|
-
return __vitePreload(() => import("./cssMode-
|
|
206561
|
+
return __vitePreload(() => import("./cssMode-BW-SuYuP.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
|
|
206553
206562
|
}
|
|
206554
206563
|
languages.onLanguage("less", () => {
|
|
206555
206564
|
getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
|
|
@@ -206654,7 +206663,7 @@ const razorLanguageService = registerHTMLLanguageService(
|
|
|
206654
206663
|
);
|
|
206655
206664
|
const razorDefaults = razorLanguageService.defaults;
|
|
206656
206665
|
function getMode$2() {
|
|
206657
|
-
return __vitePreload(() => import("./htmlMode-
|
|
206666
|
+
return __vitePreload(() => import("./htmlMode-C2dZKrOy.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
|
|
206658
206667
|
}
|
|
206659
206668
|
function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
|
|
206660
206669
|
const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
|
|
@@ -206738,7 +206747,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
|
|
|
206738
206747
|
);
|
|
206739
206748
|
const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
|
|
206740
206749
|
function getMode$1() {
|
|
206741
|
-
return __vitePreload(() => import("./jsonMode-
|
|
206750
|
+
return __vitePreload(() => import("./jsonMode-BaVI6jAw.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
|
|
206742
206751
|
}
|
|
206743
206752
|
languages.register({
|
|
206744
206753
|
id: "json",
|
|
@@ -206984,7 +206993,7 @@ const getJavaScriptWorker = () => {
|
|
|
206984
206993
|
return getMode().then((mode) => mode.getJavaScriptWorker());
|
|
206985
206994
|
};
|
|
206986
206995
|
function getMode() {
|
|
206987
|
-
return __vitePreload(() => import("./tsMode-
|
|
206996
|
+
return __vitePreload(() => import("./tsMode-B4oEmliC.js"), true ? [] : void 0, import.meta.url);
|
|
206988
206997
|
}
|
|
206989
206998
|
languages.onLanguage("typescript", () => {
|
|
206990
206999
|
return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
|
|
@@ -207179,49 +207188,49 @@ registerLanguage({
|
|
|
207179
207188
|
extensions: [".ftl", ".ftlh", ".ftlx"],
|
|
207180
207189
|
aliases: ["FreeMarker2", "Apache FreeMarker2"],
|
|
207181
207190
|
loader: () => {
|
|
207182
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207191
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
|
|
207183
207192
|
}
|
|
207184
207193
|
});
|
|
207185
207194
|
registerLanguage({
|
|
207186
207195
|
id: "freemarker2.tag-angle.interpolation-dollar",
|
|
207187
207196
|
aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
|
|
207188
207197
|
loader: () => {
|
|
207189
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207198
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
|
|
207190
207199
|
}
|
|
207191
207200
|
});
|
|
207192
207201
|
registerLanguage({
|
|
207193
207202
|
id: "freemarker2.tag-bracket.interpolation-dollar",
|
|
207194
207203
|
aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
|
|
207195
207204
|
loader: () => {
|
|
207196
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207205
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
|
|
207197
207206
|
}
|
|
207198
207207
|
});
|
|
207199
207208
|
registerLanguage({
|
|
207200
207209
|
id: "freemarker2.tag-angle.interpolation-bracket",
|
|
207201
207210
|
aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
|
|
207202
207211
|
loader: () => {
|
|
207203
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207212
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
|
|
207204
207213
|
}
|
|
207205
207214
|
});
|
|
207206
207215
|
registerLanguage({
|
|
207207
207216
|
id: "freemarker2.tag-bracket.interpolation-bracket",
|
|
207208
207217
|
aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
|
|
207209
207218
|
loader: () => {
|
|
207210
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207219
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
|
|
207211
207220
|
}
|
|
207212
207221
|
});
|
|
207213
207222
|
registerLanguage({
|
|
207214
207223
|
id: "freemarker2.tag-auto.interpolation-dollar",
|
|
207215
207224
|
aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
|
|
207216
207225
|
loader: () => {
|
|
207217
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207226
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
|
|
207218
207227
|
}
|
|
207219
207228
|
});
|
|
207220
207229
|
registerLanguage({
|
|
207221
207230
|
id: "freemarker2.tag-auto.interpolation-bracket",
|
|
207222
207231
|
aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
|
|
207223
207232
|
loader: () => {
|
|
207224
|
-
return __vitePreload(() => import("./freemarker2-
|
|
207233
|
+
return __vitePreload(() => import("./freemarker2-2YWYzawi.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
|
|
207225
207234
|
}
|
|
207226
207235
|
});
|
|
207227
207236
|
registerLanguage({
|
|
@@ -207242,7 +207251,7 @@ registerLanguage({
|
|
|
207242
207251
|
extensions: [".handlebars", ".hbs"],
|
|
207243
207252
|
aliases: ["Handlebars", "handlebars", "hbs"],
|
|
207244
207253
|
mimetypes: ["text/x-handlebars-template"],
|
|
207245
|
-
loader: () => __vitePreload(() => import("./handlebars-
|
|
207254
|
+
loader: () => __vitePreload(() => import("./handlebars-EwtUQRsf.js"), true ? [] : void 0, import.meta.url)
|
|
207246
207255
|
});
|
|
207247
207256
|
registerLanguage({
|
|
207248
207257
|
id: "hcl",
|
|
@@ -207255,7 +207264,7 @@ registerLanguage({
|
|
|
207255
207264
|
extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
|
|
207256
207265
|
aliases: ["HTML", "htm", "html", "xhtml"],
|
|
207257
207266
|
mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
|
|
207258
|
-
loader: () => __vitePreload(() => import("./html-
|
|
207267
|
+
loader: () => __vitePreload(() => import("./html-BNZkIDb9.js"), true ? [] : void 0, import.meta.url)
|
|
207259
207268
|
});
|
|
207260
207269
|
registerLanguage({
|
|
207261
207270
|
id: "ini",
|
|
@@ -207278,7 +207287,7 @@ registerLanguage({
|
|
|
207278
207287
|
filenames: ["jakefile"],
|
|
207279
207288
|
aliases: ["JavaScript", "javascript", "js"],
|
|
207280
207289
|
mimetypes: ["text/javascript"],
|
|
207281
|
-
loader: () => __vitePreload(() => import("./javascript-
|
|
207290
|
+
loader: () => __vitePreload(() => import("./javascript-busdVZMv.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
|
|
207282
207291
|
});
|
|
207283
207292
|
registerLanguage({
|
|
207284
207293
|
id: "julia",
|
|
@@ -207317,7 +207326,7 @@ registerLanguage({
|
|
|
207317
207326
|
extensions: [".liquid", ".html.liquid"],
|
|
207318
207327
|
aliases: ["Liquid", "liquid"],
|
|
207319
207328
|
mimetypes: ["application/liquid"],
|
|
207320
|
-
loader: () => __vitePreload(() => import("./liquid-
|
|
207329
|
+
loader: () => __vitePreload(() => import("./liquid-DG08un1Q.js"), true ? [] : void 0, import.meta.url)
|
|
207321
207330
|
});
|
|
207322
207331
|
registerLanguage({
|
|
207323
207332
|
id: "m3",
|
|
@@ -207335,7 +207344,7 @@ registerLanguage({
|
|
|
207335
207344
|
id: "mdx",
|
|
207336
207345
|
extensions: [".mdx"],
|
|
207337
207346
|
aliases: ["MDX", "mdx"],
|
|
207338
|
-
loader: () => __vitePreload(() => import("./mdx-
|
|
207347
|
+
loader: () => __vitePreload(() => import("./mdx-DogBhUxZ.js"), true ? [] : void 0, import.meta.url)
|
|
207339
207348
|
});
|
|
207340
207349
|
registerLanguage({
|
|
207341
207350
|
id: "mips",
|
|
@@ -207434,7 +207443,7 @@ registerLanguage({
|
|
|
207434
207443
|
extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
|
|
207435
207444
|
aliases: ["Python", "py"],
|
|
207436
207445
|
firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
|
|
207437
|
-
loader: () => __vitePreload(() => import("./python-
|
|
207446
|
+
loader: () => __vitePreload(() => import("./python-Bf-INYXh.js"), true ? [] : void 0, import.meta.url)
|
|
207438
207447
|
});
|
|
207439
207448
|
registerLanguage({
|
|
207440
207449
|
id: "qsharp",
|
|
@@ -207453,7 +207462,7 @@ registerLanguage({
|
|
|
207453
207462
|
extensions: [".cshtml"],
|
|
207454
207463
|
aliases: ["Razor", "razor"],
|
|
207455
207464
|
mimetypes: ["text/x-cshtml"],
|
|
207456
|
-
loader: () => __vitePreload(() => import("./razor-
|
|
207465
|
+
loader: () => __vitePreload(() => import("./razor-DLrZ2hsF.js"), true ? [] : void 0, import.meta.url)
|
|
207457
207466
|
});
|
|
207458
207467
|
registerLanguage({
|
|
207459
207468
|
id: "redis",
|
|
@@ -207586,7 +207595,7 @@ registerLanguage({
|
|
|
207586
207595
|
aliases: ["TypeScript", "ts", "typescript"],
|
|
207587
207596
|
mimetypes: ["text/typescript"],
|
|
207588
207597
|
loader: () => {
|
|
207589
|
-
return __vitePreload(() => import("./typescript-
|
|
207598
|
+
return __vitePreload(() => import("./typescript-CjkgfhVK.js"), true ? [] : void 0, import.meta.url);
|
|
207590
207599
|
}
|
|
207591
207600
|
});
|
|
207592
207601
|
registerLanguage({
|
|
@@ -207631,14 +207640,14 @@ registerLanguage({
|
|
|
207631
207640
|
firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
|
|
207632
207641
|
aliases: ["XML", "xml"],
|
|
207633
207642
|
mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
|
|
207634
|
-
loader: () => __vitePreload(() => import("./xml-
|
|
207643
|
+
loader: () => __vitePreload(() => import("./xml-0FAXmuVg.js"), true ? [] : void 0, import.meta.url)
|
|
207635
207644
|
});
|
|
207636
207645
|
registerLanguage({
|
|
207637
207646
|
id: "yaml",
|
|
207638
207647
|
extensions: [".yaml", ".yml"],
|
|
207639
207648
|
aliases: ["YAML", "yaml", "YML", "yml"],
|
|
207640
207649
|
mimetypes: ["application/x-yaml", "text/x-yaml"],
|
|
207641
|
-
loader: () => __vitePreload(() => import("./yaml-
|
|
207650
|
+
loader: () => __vitePreload(() => import("./yaml-DWxnPuy8.js"), true ? [] : void 0, import.meta.url)
|
|
207642
207651
|
});
|
|
207643
207652
|
var __defProp = Object.defineProperty;
|
|
207644
207653
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -211507,6 +211516,8 @@ function SettingsDialog({ open, onClose }) {
|
|
|
211507
211516
|
const [apiKey, setApiKey] = reactExports.useState("");
|
|
211508
211517
|
const [baseUrl, setBaseUrl] = reactExports.useState("");
|
|
211509
211518
|
const [dataspacePageId, setDataspacePageId] = reactExports.useState("");
|
|
211519
|
+
const [trackTime, setTrackTime] = reactExports.useState(false);
|
|
211520
|
+
const [idleTimeoutMin, setIdleTimeoutMin] = reactExports.useState(15);
|
|
211510
211521
|
const [saved, setSaved] = reactExports.useState(false);
|
|
211511
211522
|
const loadProfiles = async () => {
|
|
211512
211523
|
const data = await window.worker.listProfiles();
|
|
@@ -211526,6 +211537,8 @@ function SettingsDialog({ open, onClose }) {
|
|
|
211526
211537
|
setApiKey("");
|
|
211527
211538
|
setBaseUrl(profile.baseUrl);
|
|
211528
211539
|
setDataspacePageId(profile.dataspacePageId || "");
|
|
211540
|
+
setTrackTime(!!profile.trackTime);
|
|
211541
|
+
setIdleTimeoutMin(profile.idleTimeoutMin ?? 15);
|
|
211529
211542
|
setSaved(false);
|
|
211530
211543
|
};
|
|
211531
211544
|
const startNewProfile = () => {
|
|
@@ -211535,6 +211548,8 @@ function SettingsDialog({ open, onClose }) {
|
|
|
211535
211548
|
setApiKey("");
|
|
211536
211549
|
setBaseUrl("http://localhost:8000");
|
|
211537
211550
|
setDataspacePageId("");
|
|
211551
|
+
setTrackTime(true);
|
|
211552
|
+
setIdleTimeoutMin(15);
|
|
211538
211553
|
setSaved(false);
|
|
211539
211554
|
};
|
|
211540
211555
|
const handleSave = async () => {
|
|
@@ -211542,7 +211557,9 @@ function SettingsDialog({ open, onClose }) {
|
|
|
211542
211557
|
const data = {
|
|
211543
211558
|
name: name.trim(),
|
|
211544
211559
|
baseUrl: baseUrl.trim() || "https://app.ctlsurf.com",
|
|
211545
|
-
dataspacePageId: dataspacePageId.trim()
|
|
211560
|
+
dataspacePageId: dataspacePageId.trim(),
|
|
211561
|
+
trackTime,
|
|
211562
|
+
idleTimeoutMin: Math.max(1, Math.floor(idleTimeoutMin)) || 15
|
|
211546
211563
|
};
|
|
211547
211564
|
if (apiKey.trim()) {
|
|
211548
211565
|
data.apiKey = apiKey.trim();
|
|
@@ -211622,6 +211639,31 @@ function SettingsDialog({ open, onClose }) {
|
|
|
211622
211639
|
}
|
|
211623
211640
|
)
|
|
211624
211641
|
] }),
|
|
211642
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "settings-checkbox", children: [
|
|
211643
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
211644
|
+
"input",
|
|
211645
|
+
{
|
|
211646
|
+
type: "checkbox",
|
|
211647
|
+
checked: trackTime,
|
|
211648
|
+
onChange: (e) => setTrackTime(e.target.checked)
|
|
211649
|
+
}
|
|
211650
|
+
),
|
|
211651
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Track time per project" }),
|
|
211652
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "settings-hint", children: `Logs each session to a "Time Tracking" datastore on the project's Agent Datastore page.` })
|
|
211653
|
+
] }),
|
|
211654
|
+
trackTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
|
|
211655
|
+
"Idle timeout (min)",
|
|
211656
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
211657
|
+
"input",
|
|
211658
|
+
{
|
|
211659
|
+
type: "number",
|
|
211660
|
+
min: 1,
|
|
211661
|
+
value: idleTimeoutMin,
|
|
211662
|
+
onChange: (e) => setIdleTimeoutMin(parseInt(e.target.value, 10) || 15)
|
|
211663
|
+
}
|
|
211664
|
+
),
|
|
211665
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "settings-hint", children: "Gaps longer than this without terminal activity are counted as idle, not work." })
|
|
211666
|
+
] }),
|
|
211625
211667
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "settings-actions", children: [
|
|
211626
211668
|
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "btn-secondary", onClick: () => setEditingId(null), children: "Back" }),
|
|
211627
211669
|
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "btn-primary", onClick: handleSave, children: saved ? "Saved!" : "Save" })
|
|
@@ -211687,6 +211729,7 @@ function App() {
|
|
|
211687
211729
|
return [{ id, label: "Terminal 1", agent: null, agentStatus: "idle" }];
|
|
211688
211730
|
});
|
|
211689
211731
|
const [activeTabId, setActiveTabId] = reactExports.useState(tabs[0].id);
|
|
211732
|
+
const [trackingActive, setTrackingActive] = reactExports.useState(false);
|
|
211690
211733
|
const [pickerTargetTabId, setPickerTargetTabId] = reactExports.useState(tabs[0].id);
|
|
211691
211734
|
const [showAgentPicker, setShowAgentPicker] = reactExports.useState(true);
|
|
211692
211735
|
const visiblePaneIds = findPaneIds(layout2);
|
|
@@ -211712,6 +211755,30 @@ function App() {
|
|
|
211712
211755
|
});
|
|
211713
211756
|
return unsub;
|
|
211714
211757
|
}, []);
|
|
211758
|
+
reactExports.useEffect(() => {
|
|
211759
|
+
let cancelled = false;
|
|
211760
|
+
const refresh = async () => {
|
|
211761
|
+
try {
|
|
211762
|
+
const r = await window.worker.getTracking();
|
|
211763
|
+
if (!cancelled) setTrackingActive(!!r?.active);
|
|
211764
|
+
} catch {
|
|
211765
|
+
}
|
|
211766
|
+
};
|
|
211767
|
+
refresh();
|
|
211768
|
+
const id = setInterval(refresh, 4e3);
|
|
211769
|
+
return () => {
|
|
211770
|
+
cancelled = true;
|
|
211771
|
+
clearInterval(id);
|
|
211772
|
+
};
|
|
211773
|
+
}, [activeTabId]);
|
|
211774
|
+
const handleToggleTracking = reactExports.useCallback(async () => {
|
|
211775
|
+
try {
|
|
211776
|
+
const r = await window.worker.setTracking(!trackingActive);
|
|
211777
|
+
setTrackingActive(!!r?.active);
|
|
211778
|
+
} catch (err) {
|
|
211779
|
+
console.error("[tracking] toggle failed", err);
|
|
211780
|
+
}
|
|
211781
|
+
}, [trackingActive]);
|
|
211715
211782
|
const cwdRef = reactExports.useRef(null);
|
|
211716
211783
|
const handleSpawn = reactExports.useCallback(async (tabId, agent) => {
|
|
211717
211784
|
setTabs((prev) => prev.map((t) => t.id === tabId ? { ...t, agentStatus: "active" } : t));
|
|
@@ -211912,6 +211979,19 @@ function App() {
|
|
|
211912
211979
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "titlebar-title", children: "ctlsurf-worker" }),
|
|
211913
211980
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "titlebar-controls", children: [
|
|
211914
211981
|
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "titlebar-btn", onClick: () => setShowSettings(true), title: "Settings", children: "Settings" }),
|
|
211982
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
211983
|
+
"button",
|
|
211984
|
+
{
|
|
211985
|
+
className: `titlebar-btn titlebar-icon-btn ${trackingActive ? "active" : ""}`,
|
|
211986
|
+
onClick: handleToggleTracking,
|
|
211987
|
+
title: trackingActive ? "Time tracking on — click to stop" : "Time tracking off — click to start",
|
|
211988
|
+
"aria-label": "Time tracking",
|
|
211989
|
+
children: [
|
|
211990
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tracking-icon", children: "⏱" }),
|
|
211991
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `tracking-dot ${trackingActive ? "on" : "off"}` })
|
|
211992
|
+
]
|
|
211993
|
+
}
|
|
211994
|
+
),
|
|
211915
211995
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "titlebar-separator" }),
|
|
211916
211996
|
agents.map((a) => {
|
|
211917
211997
|
const activeTab = tabs.find((t) => t.id === activeTabId);
|
|
@@ -7904,6 +7904,27 @@ html, body, #root {
|
|
|
7904
7904
|
.status-dot.idle { background: #565f89; }
|
|
7905
7905
|
.status-dot.pending { background: #e0af68; }
|
|
7906
7906
|
|
|
7907
|
+
.tracking-dot {
|
|
7908
|
+
width: 6px;
|
|
7909
|
+
height: 6px;
|
|
7910
|
+
border-radius: 50%;
|
|
7911
|
+
display: inline-block;
|
|
7912
|
+
vertical-align: middle;
|
|
7913
|
+
}
|
|
7914
|
+
.tracking-dot.on { background: #9ece6a; box-shadow: 0 0 4px #9ece6a; }
|
|
7915
|
+
.tracking-dot.off { background: #565f89; }
|
|
7916
|
+
|
|
7917
|
+
.titlebar-icon-btn {
|
|
7918
|
+
display: inline-flex;
|
|
7919
|
+
align-items: center;
|
|
7920
|
+
gap: 5px;
|
|
7921
|
+
padding: 0 8px;
|
|
7922
|
+
}
|
|
7923
|
+
.tracking-icon {
|
|
7924
|
+
font-size: 14px;
|
|
7925
|
+
line-height: 1;
|
|
7926
|
+
}
|
|
7927
|
+
|
|
7907
7928
|
/* Editor panel */
|
|
7908
7929
|
.editor-panel {
|
|
7909
7930
|
display: flex;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { conf as conf$1, language as language$1 } from "./typescript-
|
|
2
|
-
import "./index-
|
|
1
|
+
import { conf as conf$1, language as language$1 } from "./typescript-CjkgfhVK.js";
|
|
2
|
+
import "./index-Bm_rbVP-.js";
|
|
3
3
|
const conf = conf$1;
|
|
4
4
|
const language = {
|
|
5
5
|
// Set defaultToken to invalid to see what you do not tokenize yet
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createWebWorker, l as languages, e as editor } from "./index-
|
|
2
|
-
import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-
|
|
3
|
-
import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-
|
|
1
|
+
import { c as createWebWorker, l as languages, e as editor } from "./index-Bm_rbVP-.js";
|
|
2
|
+
import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-peGVtLxi.js";
|
|
3
|
+
import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-peGVtLxi.js";
|
|
4
4
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
|
|
5
5
|
class WorkerManager {
|
|
6
6
|
constructor(defaults) {
|
package/out/renderer/assets/{lspLanguageFeatures-hoVZfVKv.js → lspLanguageFeatures-peGVtLxi.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-
|
|
1
|
+
import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-Bm_rbVP-.js";
|
|
2
2
|
var DocumentUri;
|
|
3
3
|
(function(DocumentUri2) {
|
|
4
4
|
function is(value) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-
|
|
1
|
+
import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-Bm_rbVP-.js";
|
|
2
2
|
class WorkerManager {
|
|
3
3
|
constructor(_modeId, _defaults) {
|
|
4
4
|
this._modeId = _modeId;
|
package/out/renderer/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>ctlsurf-worker</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-Bm_rbVP-.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CrTu3Z4M.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phenx-inc/ctlsurf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Agent-agnostic terminal and desktop app for ctlsurf — run Claude Code, Codex, or any coding agent with live session logging and remote control",
|
|
5
5
|
"main": "out/main/index.js",
|
|
6
6
|
"bin": {
|
package/src/main/ctlsurfApi.ts
CHANGED
|
@@ -105,6 +105,32 @@ export class CtlsurfApi {
|
|
|
105
105
|
return folder?.pages || []
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
async getFolder(folderId: string): Promise<any> {
|
|
109
|
+
return this.request('GET', `/folders/${folderId}`)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ─── Datastore ───────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
async getPageBlockSummaries(pageId: string): Promise<any[]> {
|
|
115
|
+
return this.request('GET', `/blocks/page/${pageId}/summary`)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async addRow(blockId: string, data: Record<string, unknown>): Promise<any> {
|
|
119
|
+
return this.request('POST', `/datastore/${blockId}/rows`, { data })
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async updateRow(blockId: string, rowId: string, data: Record<string, unknown>): Promise<any> {
|
|
123
|
+
return this.request('PUT', `/datastore/${blockId}/rows/${rowId}`, { data })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async getDatastoreSchema(blockId: string): Promise<{ block_id: string; columns: Array<{ id: string; name: string; type: string }> }> {
|
|
127
|
+
return this.request('GET', `/datastore/${blockId}/schema`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async updateDatastoreSchema(blockId: string, columns: Array<{ id: string; name: string; type: string }>): Promise<any> {
|
|
131
|
+
return this.request('PUT', `/datastore/${blockId}/schema`, { columns })
|
|
132
|
+
}
|
|
133
|
+
|
|
108
134
|
async findFolderByGitRemote(gitRemote: string): Promise<any> {
|
|
109
135
|
// Search folders by listing all and matching git_remote
|
|
110
136
|
const folders = await this.request('GET', '/folders')
|
package/src/main/headless.ts
CHANGED
|
@@ -70,33 +70,7 @@ async function main() {
|
|
|
70
70
|
const tui = new Tui()
|
|
71
71
|
const agents = getBuiltinAgents()
|
|
72
72
|
|
|
73
|
-
// ───
|
|
74
|
-
let agent: AgentConfig
|
|
75
|
-
|
|
76
|
-
if (args.agent) {
|
|
77
|
-
const found = agents.find(a => a.id === args.agent)
|
|
78
|
-
agent = found || {
|
|
79
|
-
id: args.agent,
|
|
80
|
-
name: args.agent,
|
|
81
|
-
command: args.agent,
|
|
82
|
-
args: [],
|
|
83
|
-
description: `Custom agent: ${args.agent}`,
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
// Show interactive picker
|
|
87
|
-
const selectedIdx = await tui.showAgentPicker(agents)
|
|
88
|
-
agent = agents[selectedIdx]
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ─── Start TUI + agent ─────────────────────────
|
|
92
|
-
|
|
93
|
-
tui.update({
|
|
94
|
-
agentName: agent.name,
|
|
95
|
-
cwd: args.cwd,
|
|
96
|
-
mode: 'terminal',
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
tui.init()
|
|
73
|
+
// ─── Orchestrator (loaded early so picker can read profile defaults) ──
|
|
100
74
|
|
|
101
75
|
const orchestrator = new Orchestrator(settingsDir, {
|
|
102
76
|
onPtyData: (_tabId, data) => {
|
|
@@ -125,10 +99,41 @@ async function main() {
|
|
|
125
99
|
if (args.apiKey) orchestrator.overrideApiKey(args.apiKey)
|
|
126
100
|
if (args.baseUrl) orchestrator.overrideBaseUrl(args.baseUrl)
|
|
127
101
|
|
|
102
|
+
// ─── Agent selection ────────────────────────────
|
|
103
|
+
|
|
104
|
+
let agent: AgentConfig
|
|
105
|
+
let trackTimeOverride: boolean | undefined
|
|
106
|
+
|
|
107
|
+
if (args.agent) {
|
|
108
|
+
const found = agents.find(a => a.id === args.agent)
|
|
109
|
+
agent = found || {
|
|
110
|
+
id: args.agent,
|
|
111
|
+
name: args.agent,
|
|
112
|
+
command: args.agent,
|
|
113
|
+
args: [],
|
|
114
|
+
description: `Custom agent: ${args.agent}`,
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
const initialTrackTime = orchestrator.getActiveProfile().trackTime !== false
|
|
118
|
+
const picked = await tui.showAgentPicker(agents, { initialTrackTime })
|
|
119
|
+
agent = agents[picked.agentIdx]
|
|
120
|
+
trackTimeOverride = picked.trackTime
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ─── Start TUI + agent ─────────────────────────
|
|
124
|
+
|
|
125
|
+
tui.update({
|
|
126
|
+
agentName: agent.name,
|
|
127
|
+
cwd: args.cwd,
|
|
128
|
+
mode: 'terminal',
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
tui.init()
|
|
132
|
+
|
|
128
133
|
// Spawn agent with PTY sized to fit the TUI content area
|
|
129
134
|
const HEADLESS_TAB = 'headless'
|
|
130
135
|
const ptySize = tui.getPtySize()
|
|
131
|
-
await orchestrator.spawnAgent(HEADLESS_TAB, agent, args.cwd)
|
|
136
|
+
await orchestrator.spawnAgent(HEADLESS_TAB, agent, args.cwd, { trackTime: trackTimeOverride })
|
|
132
137
|
orchestrator.resizePty(HEADLESS_TAB, ptySize.cols, ptySize.rows)
|
|
133
138
|
|
|
134
139
|
// For coding agents, send an initial prompt to kick-start them
|
package/src/main/index.ts
CHANGED
|
@@ -309,6 +309,14 @@ ipcMain.handle('profiles:save', (_event, id: string, data: any) => {
|
|
|
309
309
|
ipcMain.handle('profiles:switch', (_event, id: string) => orchestrator.switchProfile(id))
|
|
310
310
|
ipcMain.handle('profiles:delete', (_event, id: string) => orchestrator.deleteProfile(id))
|
|
311
311
|
|
|
312
|
+
// ─── Tracking IPC ─────────────────────────────────
|
|
313
|
+
|
|
314
|
+
ipcMain.handle('tracking:get', () => ({ active: orchestrator.isActiveTabTracking() }))
|
|
315
|
+
ipcMain.handle('tracking:set', async (_event, enabled: boolean) => {
|
|
316
|
+
await orchestrator.setActiveTabTracking(enabled)
|
|
317
|
+
return { active: orchestrator.isActiveTabTracking() }
|
|
318
|
+
})
|
|
319
|
+
|
|
312
320
|
// ─── Legacy Settings IPC ──────────────────────────
|
|
313
321
|
|
|
314
322
|
ipcMain.handle('settings:get', (_event, key: string) => {
|