@phenx-inc/ctlsurf 0.12.1 → 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.
Files changed (31) hide show
  1. package/out/headless/index.mjs +25 -19
  2. package/out/headless/index.mjs.map +2 -2
  3. package/out/main/index.js +30 -18
  4. package/out/renderer/assets/{cssMode-D7r66wvO.js → cssMode-KhYyY-BM.js} +3 -3
  5. package/out/renderer/assets/{freemarker2-jSWJIjPG.js → freemarker2-BFsSgcWk.js} +1 -1
  6. package/out/renderer/assets/{handlebars-BnFyz5RH.js → handlebars-Be6_aBsm.js} +1 -1
  7. package/out/renderer/assets/{html-Bl5UFavp.js → html-G8mvsyfc.js} +1 -1
  8. package/out/renderer/assets/{htmlMode-D4VByBT6.js → htmlMode-Cfd5VCjw.js} +3 -3
  9. package/out/renderer/assets/{index-Cc_TqOCL.css → index-Bi_MjBqs.css} +116 -8
  10. package/out/renderer/assets/{index-DxhW1emk.js → index-MqgBcJzy.js} +259 -87
  11. package/out/renderer/assets/{javascript-CMN1OmwG.js → javascript-XyDWi6dC.js} +2 -2
  12. package/out/renderer/assets/{jsonMode-CJ5AYSPV.js → jsonMode-DZT5gBVW.js} +3 -3
  13. package/out/renderer/assets/{liquid-BGMIDTEm.js → liquid-BuajCNJ9.js} +1 -1
  14. package/out/renderer/assets/{lspLanguageFeatures-DGifVYB5.js → lspLanguageFeatures-BYkg2Yc-.js} +1 -1
  15. package/out/renderer/assets/{mdx-B2Z7R10Q.js → mdx-D0Qx2GMS.js} +1 -1
  16. package/out/renderer/assets/{python-LMDMSSdn.js → python-ChncNy6S.js} +1 -1
  17. package/out/renderer/assets/{razor-BZSrziPu.js → razor-C6MUtfaS.js} +1 -1
  18. package/out/renderer/assets/{tsMode-DF9m6_3n.js → tsMode-C2aMdzdU.js} +1 -1
  19. package/out/renderer/assets/{typescript-rZeCMf0a.js → typescript-CB71AtAT.js} +1 -1
  20. package/out/renderer/assets/{xml-fNSZ-7so.js → xml-tHS1Ec9w.js} +1 -1
  21. package/out/renderer/assets/{yaml-1wxIuvzh.js → yaml-CZcp5ueF.js} +1 -1
  22. package/out/renderer/index.html +2 -2
  23. package/package.json +1 -1
  24. package/src/main/index.ts +9 -0
  25. package/src/main/orchestrator.ts +1 -1
  26. package/src/main/ticketStore.ts +26 -20
  27. package/src/renderer/App.tsx +14 -2
  28. package/src/renderer/components/CtlsurfPanel.tsx +169 -35
  29. package/src/renderer/components/TerminalPanel.tsx +7 -21
  30. package/src/renderer/components/TicketPanel.tsx +80 -24
  31. package/src/renderer/styles.css +116 -8
package/out/main/index.js CHANGED
@@ -11276,7 +11276,10 @@ function findPageByTitle(pages, title) {
11276
11276
  }
11277
11277
  class TicketStore {
11278
11278
  api;
11279
- blockCache = /* @__PURE__ */ new Map();
11279
+ // Per-cwd cache of the resolved Tickets datastore: the block (the datastore
11280
+ // element) and the Agent Datastore page it lives on. Both ids are handed to
11281
+ // the coding agent so it can read/update tickets via the ctlsurf MCP tools.
11282
+ dsCache = /* @__PURE__ */ new Map();
11280
11283
  constructor(api) {
11281
11284
  this.api = api;
11282
11285
  }
@@ -11285,11 +11288,11 @@ class TicketStore {
11285
11288
  const title = input.title?.trim();
11286
11289
  if (!title) return { ok: false, error: "Title is required" };
11287
11290
  try {
11288
- const blockId = await this.ensureDatastore(cwd, true);
11289
- if (!blockId) {
11291
+ const ds = await this.ensureDatastore(cwd, true);
11292
+ if (!ds) {
11290
11293
  return { ok: false, error: "No ctlsurf project found for this folder" };
11291
11294
  }
11292
- await this.api.addRow(blockId, {
11295
+ await this.api.addRow(ds.blockId, {
11293
11296
  Title: title,
11294
11297
  Description: input.description?.trim() || "",
11295
11298
  Status: input.status || "Open",
@@ -11308,9 +11311,9 @@ class TicketStore {
11308
11311
  const title = input.title?.trim();
11309
11312
  if (!title) return { ok: false, error: "Title is required" };
11310
11313
  try {
11311
- const blockId = await this.ensureDatastore(cwd, false);
11312
- if (!blockId) return { ok: false, error: "No Tickets datastore for this project" };
11313
- await this.api.updateRow(blockId, rowId, {
11314
+ const ds = await this.ensureDatastore(cwd, false);
11315
+ if (!ds) return { ok: false, error: "No Tickets datastore for this project" };
11316
+ await this.api.updateRow(ds.blockId, rowId, {
11314
11317
  Title: title,
11315
11318
  Description: input.description?.trim() || "",
11316
11319
  Status: input.status || "Open",
@@ -11327,9 +11330,9 @@ class TicketStore {
11327
11330
  * datastore — an unconfigured project simply has no tickets yet. */
11328
11331
  async listTickets(cwd) {
11329
11332
  try {
11330
- const blockId = await this.ensureDatastore(cwd, false);
11331
- if (!blockId) return { ok: true, tickets: [] };
11332
- const res = await this.api.queryRows(blockId, { orderBy: "Created", order: "desc", limit: 200 });
11333
+ const ds = await this.ensureDatastore(cwd, false);
11334
+ if (!ds) return { ok: true, tickets: [] };
11335
+ const res = await this.api.queryRows(ds.blockId, { orderBy: "Created", order: "desc", limit: 200 });
11333
11336
  const tickets = (res?.rows || []).map((r) => ({
11334
11337
  id: r.id,
11335
11338
  title: String(r.data?.Title ?? ""),
@@ -11338,14 +11341,14 @@ class TicketStore {
11338
11341
  priority: String(r.data?.Priority ?? "Med"),
11339
11342
  created: r.data?.Created ?? r.created_at ?? null
11340
11343
  }));
11341
- return { ok: true, tickets };
11344
+ return { ok: true, tickets, blockId: ds.blockId, pageId: ds.pageId };
11342
11345
  } catch (err) {
11343
11346
  log$1(`listTickets failed for ${cwd}: ${err?.message || err}`);
11344
11347
  return { ok: false, tickets: [], error: err?.message || String(err) };
11345
11348
  }
11346
11349
  }
11347
11350
  async ensureDatastore(cwd, create) {
11348
- const cached = this.blockCache.get(cwd);
11351
+ const cached = this.dsCache.get(cwd);
11349
11352
  if (cached) return cached;
11350
11353
  let folder = null;
11351
11354
  try {
@@ -11357,11 +11360,13 @@ class TicketStore {
11357
11360
  const folderDetail = await this.api.getFolder(folder.id);
11358
11361
  const agentPage = findPageByTitle(folderDetail?.pages || [], AGENT_DATASTORE_PAGE_TITLE);
11359
11362
  if (!agentPage?.id) return null;
11360
- const blockId = await this.findOrAdoptBlock(agentPage.id);
11363
+ const pageId = agentPage.id;
11364
+ const blockId = await this.findOrAdoptBlock(pageId);
11361
11365
  if (blockId) {
11362
11366
  await this.ensureColumns(blockId);
11363
- this.blockCache.set(cwd, blockId);
11364
- return blockId;
11367
+ const ds = { blockId, pageId };
11368
+ this.dsCache.set(cwd, ds);
11369
+ return ds;
11365
11370
  }
11366
11371
  if (!create) return null;
11367
11372
  const columns = COLUMNS.map((c, i) => ({
@@ -11370,15 +11375,16 @@ class TicketStore {
11370
11375
  type: c.type,
11371
11376
  ...c.options ? { options: c.options } : {}
11372
11377
  }));
11373
- const created = await this.api.createBlock(agentPage.id, {
11378
+ const created = await this.api.createBlock(pageId, {
11374
11379
  type: "datastore",
11375
11380
  title: DATASTORE_TITLE,
11376
11381
  props: { columns, system_key: SYSTEM_KEY }
11377
11382
  });
11378
11383
  if (created?.id) {
11379
11384
  log$1(`Created "${DATASTORE_TITLE}" datastore on Agent Datastore page for ${cwd}`);
11380
- this.blockCache.set(cwd, created.id);
11381
- return created.id;
11385
+ const ds = { blockId: created.id, pageId };
11386
+ this.dsCache.set(cwd, ds);
11387
+ return ds;
11382
11388
  }
11383
11389
  return null;
11384
11390
  }
@@ -12297,6 +12303,12 @@ function createWindow() {
12297
12303
  mainWindow.webContents.session.setPermissionRequestHandler((_wc, _permission, callback) => {
12298
12304
  callback(true);
12299
12305
  });
12306
+ mainWindow.webContents.on("did-attach-webview", (_e, contents) => {
12307
+ contents.setWindowOpenHandler(({ url }) => {
12308
+ setImmediate(() => contents.loadURL(url));
12309
+ return { action: "deny" };
12310
+ });
12311
+ });
12300
12312
  if (process.env.ELECTRON_RENDERER_URL) {
12301
12313
  mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL);
12302
12314
  } else {
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages } from "./index-DxhW1emk.js";
2
- import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-DGifVYB5.js";
3
- import { h, i, j, t, k } from "./lspLanguageFeatures-DGifVYB5.js";
1
+ import { c as createWebWorker, l as languages } from "./index-MqgBcJzy.js";
2
+ import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-BYkg2Yc-.js";
3
+ import { h, i, j, t, k } from "./lspLanguageFeatures-BYkg2Yc-.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-DxhW1emk.js";
1
+ import { l as languages } from "./index-MqgBcJzy.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "assign",
4
4
  "flush",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-DxhW1emk.js";
1
+ import { l as languages } from "./index-MqgBcJzy.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-DxhW1emk.js";
1
+ import { l as languages } from "./index-MqgBcJzy.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages } from "./index-DxhW1emk.js";
2
- import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-DGifVYB5.js";
3
- import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-DGifVYB5.js";
1
+ import { c as createWebWorker, l as languages } from "./index-MqgBcJzy.js";
2
+ import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-BYkg2Yc-.js";
3
+ import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-BYkg2Yc-.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -7915,13 +7915,88 @@ html, body, #root {
7915
7915
  width: 100%;
7916
7916
  height: 100%;
7917
7917
  overflow: hidden;
7918
+ display: flex;
7919
+ flex-direction: column;
7920
+ }
7921
+
7922
+ .ctlsurf-addressbar {
7923
+ flex: 0 0 auto;
7924
+ display: flex;
7925
+ align-items: center;
7926
+ gap: 4px;
7927
+ padding: 5px 6px;
7928
+ background: #1a1b26;
7929
+ border-bottom: 1px solid #2a2b3d;
7930
+ }
7931
+
7932
+ .ctlsurf-nav-btn {
7933
+ flex: 0 0 auto;
7934
+ width: 24px;
7935
+ height: 24px;
7936
+ display: flex;
7937
+ align-items: center;
7938
+ justify-content: center;
7939
+ padding: 0;
7940
+ background: transparent;
7941
+ border: none;
7942
+ border-radius: 4px;
7943
+ color: #a9b1d6;
7944
+ font-size: 16px;
7945
+ line-height: 1;
7946
+ cursor: pointer;
7947
+ }
7948
+
7949
+ .ctlsurf-nav-btn:hover:not(:disabled) {
7950
+ background: #2a2b3d;
7951
+ }
7952
+
7953
+ .ctlsurf-nav-btn:disabled {
7954
+ color: #565f89;
7955
+ opacity: 0.5;
7956
+ cursor: default;
7957
+ }
7958
+
7959
+ .ctlsurf-address-form {
7960
+ flex: 1 1 auto;
7961
+ display: flex;
7962
+ min-width: 0;
7963
+ }
7964
+
7965
+ .ctlsurf-address-input {
7966
+ width: 100%;
7967
+ height: 26px;
7968
+ padding: 0 11px;
7969
+ background: #16161e;
7970
+ border: 1px solid #2a2b3d;
7971
+ border-radius: 13px;
7972
+ color: #c0caf5;
7973
+ font-size: 12px;
7974
+ outline: none;
7918
7975
  }
7919
7976
 
7920
- .ctlsurf-panel webview {
7977
+ .ctlsurf-address-input:focus {
7978
+ border-color: #7aa2f7;
7979
+ }
7980
+
7981
+ .ctlsurf-webview-host {
7982
+ flex: 1 1 auto;
7983
+ position: relative;
7984
+ min-height: 0;
7985
+ }
7986
+
7987
+ .ctlsurf-webview-host webview {
7921
7988
  width: 100%;
7922
7989
  height: 100%;
7923
7990
  }
7924
7991
 
7992
+ .ctlsurf-webview-loading {
7993
+ width: 100%;
7994
+ height: 100%;
7995
+ display: flex;
7996
+ align-items: center;
7997
+ justify-content: center;
7998
+ }
7999
+
7925
8000
  /* Status bar */
7926
8001
  .statusbar {
7927
8002
  height: 24px;
@@ -9438,24 +9513,57 @@ html, body, #root {
9438
9513
  .ticket-card {
9439
9514
  display: flex;
9440
9515
  align-items: stretch;
9441
- gap: 10px;
9442
9516
  background: #15161f;
9443
9517
  border: 1px solid #262a3f;
9444
9518
  border-radius: 10px;
9445
- padding: 10px 11px 10px 0;
9446
- cursor: pointer;
9447
- text-align: left;
9448
- font-family: inherit;
9449
9519
  overflow: hidden;
9450
- transition: border-color 0.13s ease, background 0.13s ease, transform 0.06s ease;
9520
+ transition: border-color 0.13s ease, background 0.13s ease;
9451
9521
  }
9452
9522
  .ticket-card:hover {
9453
9523
  border-color: #3d425f;
9454
9524
  background: #181a26;
9455
9525
  }
9456
- .ticket-card:active {
9526
+ /* Clickable body of the card — opens the editor. */
9527
+ .ticket-card-open {
9528
+ flex: 1;
9529
+ min-width: 0;
9530
+ display: flex;
9531
+ align-items: stretch;
9532
+ gap: 10px;
9533
+ padding: 10px 11px 10px 0;
9534
+ background: transparent;
9535
+ border: none;
9536
+ color: inherit;
9537
+ cursor: pointer;
9538
+ text-align: left;
9539
+ font-family: inherit;
9540
+ transition: transform 0.06s ease;
9541
+ }
9542
+ .ticket-card-open:active {
9457
9543
  transform: scale(0.99);
9458
9544
  }
9545
+ /* Trailing button that dispatches the ticket to the coding terminal. */
9546
+ .ticket-card-send {
9547
+ flex-shrink: 0;
9548
+ width: 36px;
9549
+ align-self: stretch;
9550
+ display: flex;
9551
+ align-items: center;
9552
+ justify-content: center;
9553
+ background: transparent;
9554
+ border: none;
9555
+ border-left: 1px solid #262a3f;
9556
+ color: #565f89;
9557
+ cursor: pointer;
9558
+ transition: background 0.13s ease, color 0.13s ease, transform 0.06s ease;
9559
+ }
9560
+ .ticket-card-send:hover {
9561
+ background: #1b2030;
9562
+ color: #7aa2f7;
9563
+ }
9564
+ .ticket-card-send:active {
9565
+ transform: scale(0.9);
9566
+ }
9459
9567
  .ticket-card-bar {
9460
9568
  width: 3px;
9461
9569
  border-radius: 3px;