@lasso-ai/cli 1.0.29 → 1.1.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/dist/overlay.js CHANGED
@@ -4609,7 +4609,7 @@
4609
4609
  }(ElementContainer)
4610
4610
  );
4611
4611
  var LIST_OWNERS = ["OL", "UL", "MENU"];
4612
- var parseNodeTree = function(context, node, parent, root) {
4612
+ var parseNodeTree = function(context, node, parent, root2) {
4613
4613
  for (var childNode = node.firstChild, nextNode = void 0; childNode; childNode = nextNode) {
4614
4614
  nextNode = childNode.nextSibling;
4615
4615
  if (isTextNode(childNode) && childNode.data.trim().length > 0) {
@@ -4617,12 +4617,12 @@
4617
4617
  } else if (isElementNode(childNode)) {
4618
4618
  if (isSlotElement(childNode) && childNode.assignedNodes) {
4619
4619
  childNode.assignedNodes().forEach(function(childNode2) {
4620
- return parseNodeTree(context, childNode2, parent, root);
4620
+ return parseNodeTree(context, childNode2, parent, root2);
4621
4621
  });
4622
4622
  } else {
4623
4623
  var container = createContainer(context, childNode);
4624
4624
  if (container.styles.isVisible()) {
4625
- if (createsRealStackingContext(childNode, container, root)) {
4625
+ if (createsRealStackingContext(childNode, container, root2)) {
4626
4626
  container.flags |= 4;
4627
4627
  } else if (createsStackingContext(container.styles)) {
4628
4628
  container.flags |= 2;
@@ -4633,9 +4633,9 @@
4633
4633
  parent.elements.push(container);
4634
4634
  childNode.slot;
4635
4635
  if (childNode.shadowRoot) {
4636
- parseNodeTree(context, childNode.shadowRoot, container, root);
4636
+ parseNodeTree(context, childNode.shadowRoot, container, root2);
4637
4637
  } else if (!isTextareaElement(childNode) && !isSVGElement(childNode) && !isSelectElement(childNode)) {
4638
- parseNodeTree(context, childNode, container, root);
4638
+ parseNodeTree(context, childNode, container, root2);
4639
4639
  }
4640
4640
  }
4641
4641
  }
@@ -4678,8 +4678,8 @@
4678
4678
  parseNodeTree(context, element, container, container);
4679
4679
  return container;
4680
4680
  };
4681
- var createsRealStackingContext = function(node, container, root) {
4682
- return container.styles.isPositionedWithZIndex() || container.styles.opacity < 1 || container.styles.isTransformed() || isBodyElement(node) && root.styles.isTransparent();
4681
+ var createsRealStackingContext = function(node, container, root2) {
4682
+ return container.styles.isPositionedWithZIndex() || container.styles.opacity < 1 || container.styles.isTransformed() || isBodyElement(node) && root2.styles.isTransparent();
4683
4683
  };
4684
4684
  var createsStackingContext = function(styles) {
4685
4685
  return styles.isPositioned() || styles.isFloating();
@@ -6263,11 +6263,11 @@
6263
6263
  };
6264
6264
  var parseStackingContexts = function(container) {
6265
6265
  var paintContainer = new ElementPaint(container, null);
6266
- var root = new StackingContext(paintContainer);
6266
+ var root2 = new StackingContext(paintContainer);
6267
6267
  var listItems = [];
6268
- parseStackTree(paintContainer, root, root, listItems);
6268
+ parseStackTree(paintContainer, root2, root2, listItems);
6269
6269
  processListItems(paintContainer.container, listItems);
6270
- return root;
6270
+ return root2;
6271
6271
  };
6272
6272
  var parsePathForBorder = function(curves, borderSide) {
6273
6273
  switch (borderSide) {
@@ -7711,7 +7711,7 @@
7711
7711
  }
7712
7712
  var renderElement = function(element, opts) {
7713
7713
  return __awaiter(void 0, void 0, void 0, function() {
7714
- var ownerDocument, defaultView, resourceOptions, contextOptions, windowOptions, windowBounds, context, foreignObjectRendering, cloneOptions, documentCloner, clonedElement, container, _a, width, height, left, top, backgroundColor2, renderOptions, canvas, renderer, root, renderer;
7714
+ var ownerDocument, defaultView, resourceOptions, contextOptions, windowOptions, windowBounds, context, foreignObjectRendering, cloneOptions, documentCloner, clonedElement, container, _a, width, height, left, top, backgroundColor2, renderOptions, canvas, renderer, root2, renderer;
7715
7715
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
7716
7716
  return __generator(this, function(_u) {
7717
7717
  switch (_u.label) {
@@ -7780,13 +7780,13 @@
7780
7780
  case 3:
7781
7781
  context.logger.debug("Document cloned, element located at " + left + "," + top + " with size " + width + "x" + height + " using computed rendering");
7782
7782
  context.logger.debug("Starting DOM parsing");
7783
- root = parseTree(context, clonedElement);
7784
- if (backgroundColor2 === root.styles.backgroundColor) {
7785
- root.styles.backgroundColor = COLORS.TRANSPARENT;
7783
+ root2 = parseTree(context, clonedElement);
7784
+ if (backgroundColor2 === root2.styles.backgroundColor) {
7785
+ root2.styles.backgroundColor = COLORS.TRANSPARENT;
7786
7786
  }
7787
7787
  context.logger.debug("Starting renderer for element at " + renderOptions.x + "," + renderOptions.y + " with size " + renderOptions.width + "x" + renderOptions.height);
7788
7788
  renderer = new CanvasRenderer(context, renderOptions);
7789
- return [4, renderer.render(root)];
7789
+ return [4, renderer.render(root2)];
7790
7790
  case 4:
7791
7791
  canvas = _u.sent();
7792
7792
  _u.label = 5;
@@ -8092,6 +8092,97 @@
8092
8092
  display: none !important;
8093
8093
  }
8094
8094
 
8095
+ .lasso-toolbar-mini {
8096
+ position: fixed;
8097
+ left: calc(50% + 280px);
8098
+ bottom: 24px;
8099
+ display: inline-flex;
8100
+ align-items: center;
8101
+ min-height: 48px;
8102
+ padding: 6px;
8103
+ border: 1px solid var(--lo-border);
8104
+ border-radius: var(--lo-radius-full);
8105
+ background: rgba(22, 23, 27, 0.94);
8106
+ box-shadow: var(--lo-shadow-lg);
8107
+ backdrop-filter: blur(20px);
8108
+ -webkit-backdrop-filter: blur(20px);
8109
+ pointer-events: auto;
8110
+ z-index: 10;
8111
+ }
8112
+ .lasso-toolbar-mini.dismissed { display: none; }
8113
+ .lasso-new-page-btn {
8114
+ display: inline-flex;
8115
+ align-items: center;
8116
+ gap: 6px;
8117
+ height: 34px;
8118
+ padding: 0 12px;
8119
+ border: 0;
8120
+ border-radius: var(--lo-radius-full);
8121
+ background: var(--lo-primary);
8122
+ color: #111214;
8123
+ font: inherit;
8124
+ font-size: 12px;
8125
+ font-weight: 650;
8126
+ cursor: pointer;
8127
+ transition: transform 150ms ease, filter 150ms ease;
8128
+ }
8129
+ .lasso-new-page-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
8130
+ .lasso-new-page-btn:active { transform: scale(.97); }
8131
+
8132
+ /* ==========================================================
8133
+ NEW PAGE \u2014 nested project explorer
8134
+ ========================================================== */
8135
+ .lasso-page-backdrop { position: fixed; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; padding: 16px; background: rgba(8, 9, 11, 0.5); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); pointer-events: auto; }
8136
+ .lasso-page-backdrop[hidden] { display: none; }
8137
+ .lasso-page-panel { display: flex; flex-direction: column; width: min(400px, 100%); max-height: calc(100vh - 32px); padding: 16px; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-xl); background: var(--lo-surface); color: var(--lo-text); box-shadow: var(--lo-shadow-lg); pointer-events: auto; animation: lasso-page-in 170ms cubic-bezier(0.16, 1, 0.3, 1); }
8138
+ @keyframes lasso-page-in { from { opacity: 0; transform: translateY(10px) scale(0.98); } to { opacity: 1; transform: none; } }
8139
+ .lasso-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
8140
+ .lasso-page-title-row { display: flex; align-items: center; gap: 7px; color: var(--lo-text); }
8141
+ .lasso-page-title { font-size: 13px; font-weight: 650; letter-spacing: -0.01em; }
8142
+ .lasso-page-close { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border: 0; border-radius: 6px; background: transparent; color: var(--lo-text-3); cursor: pointer; transition: background 120ms, color 120ms; }
8143
+ .lasso-page-close:hover { background: var(--lo-surface-hover); color: var(--lo-text); }
8144
+ .lasso-page-field { display: block; margin-bottom: 13px; }
8145
+ .lasso-page-label-text { display: block; margin-bottom: 6px; color: var(--lo-text-3); font-size: 10.5px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
8146
+ .lasso-page-name { width: 100%; box-sizing: border-box; padding: 9px 11px; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-md); background: var(--lo-surface-2); color: var(--lo-text); font: inherit; font-size: 12.5px; }
8147
+ .lasso-page-name::placeholder, .lasso-page-filter::placeholder, .lasso-page-inline-input::placeholder { color: var(--lo-text-3); }
8148
+ .lasso-page-name:focus, .lasso-page-filter:focus, .lasso-page-inline-input:focus { outline: none; border-color: var(--lo-primary); box-shadow: 0 0 0 3px var(--lo-primary-soft); }
8149
+ .lasso-page-name.invalid { border-color: var(--lo-error); }
8150
+ .lasso-page-field-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
8151
+ .lasso-page-field-head .lasso-page-label-text { margin-bottom: 0; }
8152
+ .lasso-page-field-tools { display: flex; align-items: center; gap: 5px; }
8153
+ .lasso-page-filter { width: 96px; box-sizing: border-box; padding: 4px 8px; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-full); background: var(--lo-surface-2); color: var(--lo-text); font: inherit; font-size: 11px; }
8154
+ .lasso-page-new-folder { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border: 1px solid var(--lo-border); border-radius: 6px; background: var(--lo-surface-2); color: var(--lo-text-2); cursor: pointer; transition: background 120ms, color 120ms; }
8155
+ .lasso-page-new-folder:hover { background: var(--lo-surface-hover); color: var(--lo-text); }
8156
+ .lasso-page-tree { max-height: 240px; overflow: auto; padding: 5px; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-md); background: var(--lo-surface-2); }
8157
+ .lasso-page-row { display: flex; align-items: center; gap: 4px; min-height: 24px; padding-left: calc(4px + var(--lasso-page-depth, 0) * 13px); padding-right: 4px; border-radius: 5px; color: var(--lo-text-2); font: inherit; font-size: 12px; cursor: pointer; user-select: none; }
8158
+ .lasso-page-row:hover { background: var(--lo-surface-hover); color: var(--lo-text); }
8159
+ .lasso-page-row.selected { background: var(--lo-primary-soft); color: var(--lo-text); box-shadow: inset 2px 0 0 var(--lo-primary); }
8160
+ .lasso-page-row.muted { color: var(--lo-text-3); font-size: 11px; font-style: italic; cursor: default; }
8161
+ .lasso-page-row.muted:hover { background: transparent; color: var(--lo-text-3); }
8162
+ .lasso-page-row.creating { cursor: default; }
8163
+ .lasso-page-row.creating:hover { background: transparent; }
8164
+ .lasso-page-twisty { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; flex: 0 0 auto; color: var(--lo-text-3); transition: transform 120ms ease; }
8165
+ .lasso-page-twisty.open { transform: rotate(90deg); }
8166
+ .lasso-page-twisty svg { width: 11px; height: 11px; }
8167
+ .lasso-page-icon { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; flex: 0 0 auto; }
8168
+ .lasso-page-icon svg { width: 14px; height: 14px; }
8169
+ .lasso-page-icon.folder { color: var(--lo-primary); }
8170
+ .lasso-page-icon.file { color: var(--lo-text-3); }
8171
+ .lasso-page-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8172
+ .lasso-page-inline-input { min-width: 0; flex: 1; padding: 3px 6px; border: 1px solid var(--lo-primary); border-radius: 5px; background: var(--lo-surface); color: var(--lo-text); font: inherit; font-size: 12px; }
8173
+ .lasso-page-inline-confirm, .lasso-page-inline-cancel { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex: 0 0 auto; padding: 0; border: 0; border-radius: 5px; cursor: pointer; }
8174
+ .lasso-page-inline-confirm { background: var(--lo-primary-soft); color: var(--lo-primary); }
8175
+ .lasso-page-inline-cancel { background: transparent; color: var(--lo-text-3); }
8176
+ .lasso-page-inline-confirm:hover, .lasso-page-inline-cancel:hover { filter: brightness(1.2); }
8177
+ .lasso-page-inline-confirm svg, .lasso-page-inline-cancel svg { width: 12px; height: 12px; }
8178
+ .lasso-page-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
8179
+ .lasso-page-status { min-width: 0; flex: 1; color: var(--lo-text-3); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8180
+ .lasso-page-status.error { color: var(--lo-error); }
8181
+ .lasso-page-create { flex: 0 0 auto; padding: 8px 15px; border: 0; border-radius: var(--lo-radius-full); background: var(--lo-primary); color: #111214; font: inherit; font-size: 12px; font-weight: 650; cursor: pointer; transition: filter 120ms, opacity 120ms; }
8182
+ .lasso-page-create:disabled { opacity: 0.45; cursor: not-allowed; }
8183
+ .lasso-page-create:not(:disabled):hover { filter: brightness(1.08); }
8184
+ @media (max-width: 600px) { .lasso-page-panel { width: 100%; } }
8185
+
8095
8186
  .lasso-tb-sep {
8096
8187
  width: 1px;
8097
8188
  height: 20px;
@@ -8138,6 +8229,24 @@
8138
8229
  transform: scale(0.96);
8139
8230
  }
8140
8231
 
8232
+ .lasso-toolbar-tooltip {
8233
+ position: fixed;
8234
+ z-index: 100;
8235
+ transform: translateX(-50%);
8236
+ max-width: 220px;
8237
+ padding: 6px 9px;
8238
+ border: 1px solid var(--lo-border);
8239
+ border-radius: 7px;
8240
+ background: var(--lo-surface-2);
8241
+ color: var(--lo-text);
8242
+ box-shadow: 0 8px 24px rgba(0,0,0,.28);
8243
+ font-size: 11px;
8244
+ line-height: 1.2;
8245
+ white-space: nowrap;
8246
+ pointer-events: none;
8247
+ }
8248
+ .lasso-toolbar-tooltip[hidden] { display: none; }
8249
+
8141
8250
  /* Animated label transition */
8142
8251
  .lasso-tool-label {
8143
8252
  max-width: 0;
@@ -8306,6 +8415,11 @@
8306
8415
  color: #ffffff;
8307
8416
  }
8308
8417
 
8418
+ @media (max-width: 760px) {
8419
+ .lasso-toolbar-mini { left: 50%; bottom: 82px; transform: translateX(-50%); }
8420
+ .lasso-new-page-panel { left: 50%; transform: translateX(-50%); }
8421
+ }
8422
+
8309
8423
  /* Presence Avatars in toolbar with color outlines */
8310
8424
  .lasso-presence {
8311
8425
  display: flex;
@@ -10943,6 +11057,26 @@
10943
11057
  .lasso-task-apply { padding: 7px 11px; border: 0; border-radius: var(--lo-radius-full); background: var(--lo-primary); color: #111214; font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; }
10944
11058
 
10945
11059
  .lasso-agent-tasks-badge { position: absolute; top: 5px; right: 5px; width: 6px; height: 6px; border-radius: 50%; background: var(--lo-primary); }
11060
+ .lasso-agent-prompt-backdrop { position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 16px; background: rgba(8, 9, 11, 0.55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); pointer-events: auto; }
11061
+ .lasso-agent-prompt-backdrop[hidden] { display: none; }
11062
+ .lasso-agent-prompt { display: flex; flex-direction: column; width: min(420px, 100%); max-height: calc(100vh - 32px); overflow: auto; padding: 16px; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-lg); background: var(--lo-surface); color: var(--lo-text); box-shadow: var(--lo-shadow-lg); pointer-events: auto; animation: lasso-agent-prompt-in 160ms cubic-bezier(0.16, 1, 0.3, 1); }
11063
+ @keyframes lasso-agent-prompt-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
11064
+ .lasso-agent-prompt-head { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; }
11065
+ .lasso-agent-prompt-mark { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex: 0 0 auto; border-radius: 8px; background: var(--lo-primary-soft); color: var(--lo-primary); }
11066
+ .lasso-agent-prompt-mark svg { width: 15px; height: 15px; }
11067
+ .lasso-agent-prompt-headings { min-width: 0; flex: 1; }
11068
+ .lasso-agent-prompt-title { font-size: 13px; font-weight: 650; letter-spacing: -0.01em; }
11069
+ .lasso-agent-prompt-subtitle { margin-top: 2px; color: var(--lo-text-3); font-size: 11px; }
11070
+ .lasso-agent-prompt-close { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex: 0 0 auto; border: 0; border-radius: 6px; background: transparent; color: var(--lo-text-3); cursor: pointer; transition: background 120ms, color 120ms; }
11071
+ .lasso-agent-prompt-close:hover { background: var(--lo-surface-hover); color: var(--lo-text); }
11072
+ .lasso-agent-prompt-message { max-height: 220px; margin-bottom: 14px; padding: 10px 11px; overflow: auto; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-md); background: var(--lo-surface-2); color: var(--lo-text-2); font: inherit; font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; user-select: text; }
11073
+ .lasso-agent-prompt-input { width: 100%; box-sizing: border-box; margin-bottom: 12px; padding: 9px 11px; border: 1px solid var(--lo-border); border-radius: var(--lo-radius-md); background: var(--lo-surface-2); color: var(--lo-text); font: inherit; font-size: 12px; }
11074
+ .lasso-agent-prompt-input[hidden] { display: none; }
11075
+ .lasso-agent-prompt-actions { display: flex; justify-content: flex-end; gap: 7px; }
11076
+ .lasso-agent-prompt-actions button { padding: 7px 13px; border: 0; border-radius: var(--lo-radius-full); background: var(--lo-surface-2); color: var(--lo-text); font: inherit; font-size: 11.5px; font-weight: 500; cursor: pointer; transition: filter 120ms, transform 120ms; }
11077
+ .lasso-agent-prompt-actions button:hover { filter: brightness(1.12); }
11078
+ .lasso-agent-prompt-actions button:active { transform: scale(0.97); }
11079
+ .lasso-agent-prompt-actions button.primary { background: var(--lo-primary); color: #111214; font-weight: 600; }
10946
11080
 
10947
11081
  .lasso-todo-header {
10948
11082
  display: flex;
@@ -12129,7 +12263,6 @@
12129
12263
  // src/overlay/tasks/tasks.ts
12130
12264
  var panel = null;
12131
12265
  var list = null;
12132
- var detail = null;
12133
12266
  var badge = null;
12134
12267
  var selectionListeners = /* @__PURE__ */ new Set();
12135
12268
  var reviewListeners = /* @__PURE__ */ new Set();
@@ -12160,6 +12293,17 @@
12160
12293
  (task) => task.status !== "complete" && task.status !== "error" && task.status !== "stopped" && normalizedInstruction(task.instruction) === normalized && task.element === (element || void 0)
12161
12294
  );
12162
12295
  }
12296
+ function getComponentConversation(selectionId) {
12297
+ const task = state.agentTasks.find((candidate) => candidate.selectionId === selectionId);
12298
+ if (!task) return { messages: [], changesHistory: [] };
12299
+ return {
12300
+ messages: task.messages.map((message) => ({ ...message })),
12301
+ changesHistory: task.changesHistory.map((entry) => ({
12302
+ ...entry,
12303
+ changes: entry.changes.map((change) => ({ ...change }))
12304
+ }))
12305
+ };
12306
+ }
12163
12307
  function onAgentTaskSelected(listener) {
12164
12308
  selectionListeners.add(listener);
12165
12309
  return () => selectionListeners.delete(listener);
@@ -12274,12 +12418,10 @@
12274
12418
  </div>
12275
12419
  <div class="lasso-task-body">
12276
12420
  <div class="lasso-task-list"></div>
12277
- <div class="lasso-task-detail" hidden></div>
12278
12421
  </div>
12279
12422
  `;
12280
12423
  dom.shadow.appendChild(panel);
12281
12424
  list = panel.querySelector(".lasso-task-list");
12282
- detail = panel.querySelector(".lasso-task-detail");
12283
12425
  badge = panel.querySelector(".lasso-task-badge");
12284
12426
  panel.querySelector(".lasso-task-close").addEventListener("click", () => toggleTaskPanel(false));
12285
12427
  panel.querySelectorAll(".lasso-task-tab").forEach((tab) => {
@@ -12296,15 +12438,15 @@
12296
12438
  return panel;
12297
12439
  }
12298
12440
  function renderTasks() {
12299
- const panelEl = panel;
12300
- if (!panelEl || !list || !detail || !badge) return;
12441
+ const panelEl2 = panel;
12442
+ if (!panelEl2 || !list || !badge) return;
12301
12443
  const activeCount = state.agentTasks.filter((task) => task.status !== "complete" && task.status !== "error" && task.status !== "stopped").length;
12302
12444
  badge.hidden = state.agentTasks.length === 0;
12303
12445
  badge.textContent = String(activeCount || state.agentTasks.length);
12304
12446
  const navBadge = getDOM().shadow.querySelector(".lasso-agent-tasks-badge");
12305
12447
  if (navBadge) navBadge.hidden = activeCount === 0;
12306
12448
  list.replaceChildren();
12307
- const activeTab = panelEl.querySelector(".lasso-task-tab.active")?.dataset.taskTab || "active";
12449
+ const activeTab = panelEl2.querySelector(".lasso-task-tab.active")?.dataset.taskTab || "active";
12308
12450
  const visibleTasks = state.agentTasks.filter((task) => activeTab === "complete" ? task.status === "complete" : task.status !== "complete");
12309
12451
  if (!visibleTasks.length) {
12310
12452
  list.innerHTML = `<div class="lasso-task-empty">Prompt an element to start a task.</div>`;
@@ -12326,49 +12468,6 @@
12326
12468
  list.appendChild(button);
12327
12469
  }
12328
12470
  }
12329
- const selected = getAgentTask(state.activeTaskId);
12330
- if (!selected) {
12331
- detail.hidden = true;
12332
- return;
12333
- }
12334
- detail.hidden = false;
12335
- detail.replaceChildren();
12336
- const heading = document.createElement("div");
12337
- heading.className = "lasso-task-detail-heading";
12338
- heading.innerHTML = `<span class="lasso-task-detail-status ${selected.status}">${statusLabel[selected.status]}</span><button type="button" class="lasso-task-back">All tasks</button>`;
12339
- heading.querySelector("button").addEventListener("click", () => selectAgentTask(null));
12340
- const prompt = document.createElement("p");
12341
- prompt.className = "lasso-task-prompt";
12342
- prompt.textContent = selected.instruction;
12343
- const activity = document.createElement("p");
12344
- activity.className = "lasso-task-message";
12345
- activity.textContent = selected.response || selected.message;
12346
- detail.append(heading, prompt, activity);
12347
- if (selected.activity.length) {
12348
- const activityList = document.createElement("div");
12349
- activityList.className = "lasso-task-activity";
12350
- for (const entry of selected.activity.slice(-8)) {
12351
- const line = document.createElement("div");
12352
- line.textContent = entry;
12353
- activityList.appendChild(line);
12354
- }
12355
- detail.appendChild(activityList);
12356
- }
12357
- const pendingChanges = selected.pendingChanges.length ? selected.pendingChanges : selected.changes || [];
12358
- if (pendingChanges.length) {
12359
- const changes = document.createElement("div");
12360
- changes.className = "lasso-task-changes";
12361
- changes.textContent = `${pendingChanges.length} proposed file change${pendingChanges.length === 1 ? "" : "s"}`;
12362
- detail.appendChild(changes);
12363
- if (selected.status === "review") {
12364
- const review = document.createElement("button");
12365
- review.type = "button";
12366
- review.className = "lasso-task-apply";
12367
- review.textContent = "Review changes";
12368
- review.addEventListener("click", () => requestAgentTaskReview(selected.id));
12369
- detail.appendChild(review);
12370
- }
12371
- }
12372
12471
  }
12373
12472
 
12374
12473
  // src/overlay/notifications.ts
@@ -17735,7 +17834,7 @@
17735
17834
  const textarea = el.querySelector(".lasso-notepad-textarea");
17736
17835
  const preview = el.querySelector(".lasso-notepad-preview");
17737
17836
  const countEl = el.querySelector(".lasso-notepad-count");
17738
- const statusEl = el.querySelector(".lasso-notepad-status");
17837
+ const statusEl2 = el.querySelector(".lasso-notepad-status");
17739
17838
  textarea.value = initialContent;
17740
17839
  collabEmit("note:get", {}, (response) => {
17741
17840
  if (response.ok && typeof response.body === "string") {
@@ -17757,7 +17856,7 @@
17757
17856
  voiceBtn.classList.remove("recording");
17758
17857
  voiceBtn.classList.add("transcribing");
17759
17858
  voiceBtn.title = "Transcribing\u2026";
17760
- statusEl.textContent = "Transcribing\u2026";
17859
+ statusEl2.textContent = "Transcribing\u2026";
17761
17860
  try {
17762
17861
  const result = await stopVoiceRecording();
17763
17862
  if (result.text) {
@@ -17771,20 +17870,20 @@
17771
17870
  textarea.setSelectionRange(cursor, cursor);
17772
17871
  textarea.dispatchEvent(new Event("input"));
17773
17872
  textarea.focus();
17774
- statusEl.textContent = "Transcribed";
17873
+ statusEl2.textContent = "Transcribed";
17775
17874
  window.setTimeout(() => {
17776
- statusEl.textContent = "Autosaved";
17875
+ statusEl2.textContent = "Autosaved";
17777
17876
  }, 2e3);
17778
17877
  } else {
17779
- statusEl.textContent = "No speech detected";
17878
+ statusEl2.textContent = "No speech detected";
17780
17879
  window.setTimeout(() => {
17781
- statusEl.textContent = "Autosaved";
17880
+ statusEl2.textContent = "Autosaved";
17782
17881
  }, 1500);
17783
17882
  }
17784
17883
  } catch (err) {
17785
- statusEl.textContent = err?.message || "Transcription failed";
17884
+ statusEl2.textContent = err?.message || "Transcription failed";
17786
17885
  window.setTimeout(() => {
17787
- statusEl.textContent = "Autosaved";
17886
+ statusEl2.textContent = "Autosaved";
17788
17887
  }, 2500);
17789
17888
  } finally {
17790
17889
  voiceBtn.classList.remove("transcribing");
@@ -17795,11 +17894,11 @@
17795
17894
  await startVoiceRecording();
17796
17895
  voiceBtn.classList.add("recording");
17797
17896
  voiceBtn.title = "Recording\u2026 click again to stop & transcribe";
17798
- statusEl.textContent = "Listening\u2026";
17897
+ statusEl2.textContent = "Listening\u2026";
17799
17898
  } catch (err) {
17800
- statusEl.textContent = err?.message || "Microphone access denied";
17899
+ statusEl2.textContent = err?.message || "Microphone access denied";
17801
17900
  window.setTimeout(() => {
17802
- statusEl.textContent = "Autosaved";
17901
+ statusEl2.textContent = "Autosaved";
17803
17902
  }, 3e3);
17804
17903
  }
17805
17904
  }
@@ -17823,11 +17922,11 @@
17823
17922
  textarea.addEventListener("input", () => {
17824
17923
  const text = textarea.value;
17825
17924
  updateCounts(text.length, countEl);
17826
- statusEl.textContent = "Saving\u2026";
17925
+ statusEl2.textContent = "Saving\u2026";
17827
17926
  if (saveTimer) window.clearTimeout(saveTimer);
17828
17927
  saveTimer = window.setTimeout(() => {
17829
17928
  saveNote(text);
17830
- statusEl.textContent = "Autosaved";
17929
+ statusEl2.textContent = "Autosaved";
17831
17930
  }, 400);
17832
17931
  });
17833
17932
  copyBtn.addEventListener("click", async () => {
@@ -17847,12 +17946,12 @@
17847
17946
  ta.remove();
17848
17947
  }
17849
17948
  }
17850
- statusEl.textContent = "Copied!";
17949
+ statusEl2.textContent = "Copied!";
17851
17950
  setTimeout(() => {
17852
- statusEl.textContent = "Autosaved";
17951
+ statusEl2.textContent = "Autosaved";
17853
17952
  }, 1500);
17854
17953
  } catch {
17855
- statusEl.textContent = "Copy failed";
17954
+ statusEl2.textContent = "Copy failed";
17856
17955
  }
17857
17956
  });
17858
17957
  return el;
@@ -18494,6 +18593,8 @@
18494
18593
  var agentLogLines = [];
18495
18594
  var agentLogExpanded = false;
18496
18595
  var reviewPanel = null;
18596
+ var agentPromptPanel = null;
18597
+ var agentPromptTaskId = null;
18497
18598
  var modelBtn = null;
18498
18599
  var modelName = null;
18499
18600
  var modelMenu = null;
@@ -18519,6 +18620,17 @@
18519
18620
  const icon = providerIcons[provider];
18520
18621
  return `<span class="${active ? "lasso-model-active-icon" : "lasso-model-item-icon"} provider-${provider}" aria-hidden="true"><svg viewBox="0 0 ${icon.width} ${icon.height}" xmlns="http://www.w3.org/2000/svg" focusable="false">${icon.body}</svg></span>`;
18521
18622
  }
18623
+ function componentConversationId(element) {
18624
+ const source = element.getAttribute("data-source") || element.getAttribute("data-lasso-source") || getSourceHint(element);
18625
+ return `component:${source || elementKey(element)}`;
18626
+ }
18627
+ function loadComponentConversation(element) {
18628
+ const selectionId = componentConversationId(element);
18629
+ const conversation = getComponentConversation(selectionId);
18630
+ state.selectionId = selectionId;
18631
+ state.chatHistory = conversation.messages;
18632
+ state.changesHistory = conversation.changesHistory;
18633
+ }
18522
18634
  function buildPrompt() {
18523
18635
  const dom = getDOM();
18524
18636
  const el = document.createElement("div");
@@ -18610,6 +18722,58 @@
18610
18722
  `;
18611
18723
  dom.shadow.appendChild(el);
18612
18724
  promptEl = el;
18725
+ const agentPrompt = document.createElement("div");
18726
+ agentPrompt.className = "lasso-agent-prompt-backdrop";
18727
+ agentPrompt.hidden = true;
18728
+ agentPrompt.innerHTML = `
18729
+ <div class="lasso-agent-prompt" role="dialog" aria-modal="true" aria-labelledby="lasso-agent-prompt-title">
18730
+ <div class="lasso-agent-prompt-head">
18731
+ <span class="lasso-agent-prompt-mark" aria-hidden="true">
18732
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
18733
+ <path d="M12 3l7.5 3.2v5.1c0 4.4-3 8.4-7.5 9.7-4.5-1.3-7.5-5.3-7.5-9.7V6.2z"/>
18734
+ <path d="M9.4 12.1l1.9 1.9 3.4-3.7"/>
18735
+ </svg>
18736
+ </span>
18737
+ <div class="lasso-agent-prompt-headings">
18738
+ <div class="lasso-agent-prompt-title" id="lasso-agent-prompt-title">Agent needs your input</div>
18739
+ <div class="lasso-agent-prompt-subtitle"></div>
18740
+ </div>
18741
+ <button class="lasso-agent-prompt-close" type="button" aria-label="Deny and continue">
18742
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
18743
+ <path d="M18 6L6 18M6 6l12 12"/>
18744
+ </svg>
18745
+ </button>
18746
+ </div>
18747
+ <div class="lasso-agent-prompt-message" tabindex="0"></div>
18748
+ <input class="lasso-agent-prompt-input" type="text" placeholder="Type a response\u2026" hidden />
18749
+ <div class="lasso-agent-prompt-actions"></div>
18750
+ </div>
18751
+ `;
18752
+ dom.shadow.appendChild(agentPrompt);
18753
+ agentPromptPanel = agentPrompt;
18754
+ agentPrompt.addEventListener("pointerdown", (event) => {
18755
+ if (event.target === agentPrompt) respondToAgentPrompt("Deny");
18756
+ });
18757
+ agentPrompt.addEventListener("keydown", (event) => {
18758
+ const key = event.key;
18759
+ if (key === "Escape") {
18760
+ event.preventDefault();
18761
+ event.stopPropagation();
18762
+ respondToAgentPrompt("Deny");
18763
+ }
18764
+ });
18765
+ agentPrompt.querySelector(".lasso-agent-prompt-close").addEventListener("click", (event) => {
18766
+ event.preventDefault();
18767
+ event.stopPropagation();
18768
+ respondToAgentPrompt("Deny");
18769
+ });
18770
+ agentPrompt.querySelector(".lasso-agent-prompt-input").addEventListener("keydown", (event) => {
18771
+ if (event.key !== "Enter") return;
18772
+ event.preventDefault();
18773
+ event.stopPropagation();
18774
+ const value2 = agentPrompt.querySelector(".lasso-agent-prompt-input")?.value.trim();
18775
+ if (value2) respondToAgentPrompt(value2);
18776
+ });
18613
18777
  promptInput = el.querySelector(".lasso-prompt-input");
18614
18778
  promptElement = el.querySelector(".lasso-prompt-element-name");
18615
18779
  sendButton = el.querySelector(".lasso-prompt-send");
@@ -18686,9 +18850,9 @@
18686
18850
  });
18687
18851
  modelMenu.addEventListener("click", (event) => {
18688
18852
  event.stopPropagation();
18689
- const filter = event.target.closest(".lasso-model-filter");
18690
- if (filter?.dataset.providerFilter) {
18691
- state.modelFilter = filter.dataset.providerFilter;
18853
+ const filter2 = event.target.closest(".lasso-model-filter");
18854
+ if (filter2?.dataset.providerFilter) {
18855
+ state.modelFilter = filter2.dataset.providerFilter;
18692
18856
  refreshModelMenu();
18693
18857
  return;
18694
18858
  }
@@ -18809,18 +18973,75 @@
18809
18973
  });
18810
18974
  return { prompt: el, review: rev };
18811
18975
  }
18976
+ function showAgentPrompt(taskId2, prompt) {
18977
+ if (!agentPromptPanel) return;
18978
+ agentPromptTaskId = taskId2;
18979
+ const isPermission = prompt.kind === "permission";
18980
+ const message = agentPromptPanel.querySelector(".lasso-agent-prompt-message");
18981
+ const subtitle = agentPromptPanel.querySelector(".lasso-agent-prompt-subtitle");
18982
+ const input = agentPromptPanel.querySelector(".lasso-agent-prompt-input");
18983
+ const actions = agentPromptPanel.querySelector(".lasso-agent-prompt-actions");
18984
+ agentPromptPanel.dataset.kind = prompt.kind;
18985
+ if (message) {
18986
+ message.textContent = prompt.message.trim() || "The agent is waiting for a response before it can continue.";
18987
+ }
18988
+ if (subtitle) {
18989
+ subtitle.textContent = isPermission ? "Lasso is paused until you choose an option." : "Type your answer and press Enter.";
18990
+ }
18991
+ if (input) {
18992
+ input.value = "";
18993
+ input.hidden = isPermission;
18994
+ }
18995
+ if (actions) {
18996
+ const options = isPermission ? prompt.options?.length ? prompt.options : ["Allow", "Deny"] : ["Send"];
18997
+ actions.replaceChildren(
18998
+ ...options.map((option) => {
18999
+ const button = document.createElement("button");
19000
+ button.type = "button";
19001
+ button.dataset.agentResponse = option;
19002
+ button.textContent = option;
19003
+ button.className = isDenyOption(option) ? "" : "primary";
19004
+ button.addEventListener("click", (event) => {
19005
+ event.preventDefault();
19006
+ event.stopPropagation();
19007
+ const typed = isPermission ? option : input?.value.trim() || "";
19008
+ if (typed) respondToAgentPrompt(typed);
19009
+ });
19010
+ return button;
19011
+ })
19012
+ );
19013
+ }
19014
+ agentPromptPanel.hidden = false;
19015
+ if (!isPermission) input?.focus();
19016
+ else agentPromptPanel.querySelector(".lasso-agent-prompt-message")?.focus();
19017
+ }
19018
+ function isDenyOption(option) {
19019
+ return /^(deny|decline|no|cancel|reject|stop|abort)$/i.test(option.trim());
19020
+ }
19021
+ function respondToAgentPrompt(response) {
19022
+ const taskId2 = agentPromptTaskId;
19023
+ if (!taskId2 || !agentPromptPanel) return;
19024
+ agentPromptTaskId = null;
19025
+ agentPromptPanel.hidden = true;
19026
+ if (state.bridgeSocket?.readyState !== WebSocket.OPEN) {
19027
+ appendChat("error", "The Lasso agent bridge disconnected before the response was sent.", taskId2);
19028
+ return;
19029
+ }
19030
+ state.bridgeSocket.send(JSON.stringify({ type: "agent_prompt_response", taskId: taskId2, response }));
19031
+ appendChat("assistant", `Responded to the agent: ${response}`, taskId2);
19032
+ }
18812
19033
  function refreshModelMenu() {
18813
19034
  if (!modelMenu) return;
18814
19035
  const filters = document.createElement("div");
18815
19036
  filters.className = "lasso-model-filters";
18816
19037
  const providers = ["all", ...Array.from(new Set(state.MODELS.map((m) => m.provider)))];
18817
19038
  for (const provider of providers) {
18818
- const filter = document.createElement("button");
18819
- filter.type = "button";
18820
- filter.className = `lasso-model-filter${state.modelFilter === provider ? " active" : ""}`;
18821
- filter.dataset.providerFilter = provider;
18822
- filter.textContent = provider === "all" ? "All" : providerLabels[provider];
18823
- filters.appendChild(filter);
19039
+ const filter2 = document.createElement("button");
19040
+ filter2.type = "button";
19041
+ filter2.className = `lasso-model-filter${state.modelFilter === provider ? " active" : ""}`;
19042
+ filter2.dataset.providerFilter = provider;
19043
+ filter2.textContent = provider === "all" ? "All" : providerLabels[provider];
19044
+ filters.appendChild(filter2);
18824
19045
  }
18825
19046
  const children = [filters];
18826
19047
  const visibleProviders = state.modelFilter === "all" ? providers.slice(1) : [state.modelFilter];
@@ -19035,9 +19256,9 @@
19035
19256
  container.append(document.createTextNode(text.slice(lastIndex)));
19036
19257
  }
19037
19258
  }
19038
- function setAgentStatus(status, message, detail2, taskId2 = state.promptTaskId, appendMessage = true) {
19259
+ function setAgentStatus(status, message, detail, taskId2 = state.promptTaskId, appendMessage = true) {
19039
19260
  if (!agentStatusElement || !agentStatusMessage || !sendButton) return;
19040
- const logMessage = detail2?.trim() || message.trim();
19261
+ const logMessage = detail?.trim() || message.trim();
19041
19262
  const lastLog = agentLogLines[agentLogLines.length - 1];
19042
19263
  if (agentStatusElement.dataset.status === status && agentStatusMessage.textContent === message && (!logMessage || lastLog === logMessage)) return;
19043
19264
  appendAgentLog(logMessage);
@@ -19092,13 +19313,17 @@
19092
19313
  function hideReview() {
19093
19314
  if (reviewPanel) reviewPanel.hidden = true;
19094
19315
  }
19095
- function resetPromptSession() {
19316
+ function resetPromptSession(element = state.selected) {
19096
19317
  state.promptTaskId = null;
19097
- state.chatHistory = [];
19098
- state.changesHistory = [];
19099
19318
  state.pendingChanges = [];
19100
19319
  state.lastInstruction = "";
19101
- state.selectionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
19320
+ if (element) {
19321
+ loadComponentConversation(element);
19322
+ } else {
19323
+ state.chatHistory = [];
19324
+ state.changesHistory = [];
19325
+ state.selectionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
19326
+ }
19102
19327
  state.screenshotPromise = Promise.resolve({});
19103
19328
  hideReview();
19104
19329
  clearAgentLog();
@@ -19271,7 +19496,7 @@
19271
19496
  const changesHistory = state.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
19272
19497
  const task = createAgentTask(instruction, messages, changesHistory, selectedElement, selectionId);
19273
19498
  updateAgentTask(task.id, { status: "thinking", message: "Thinking\u2026", activity: [...task.activity, "Thinking\u2026"] });
19274
- resetPromptSession();
19499
+ resetPromptSession(selectedElement);
19275
19500
  state.promptTaskId = task.id;
19276
19501
  state.lastInstruction = instruction;
19277
19502
  const rect = selectedElement.getBoundingClientRect();
@@ -19341,7 +19566,7 @@
19341
19566
  }
19342
19567
  function openPromptForSelected(selected) {
19343
19568
  if (!promptEl || !promptElement) return;
19344
- resetPromptSession();
19569
+ resetPromptSession(selected);
19345
19570
  promptElement.textContent = getElementLabel(selected);
19346
19571
  positionPrompt(selected);
19347
19572
  promptEl.classList.add("visible");
@@ -20487,6 +20712,483 @@
20487
20712
  }
20488
20713
  }
20489
20714
 
20715
+ // src/overlay/pages/pages.ts
20716
+ var ROOT_PATH = ".";
20717
+ var DEFAULT_FILE_NAME = "page.tsx";
20718
+ var ICON_FOLDER = `<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M1.75 4.2c0-.6.5-1.1 1.1-1.1h3.1c.35 0 .68.16.9.45l.7.95h4.4c.6 0 1.1.5 1.1 1.1v6.3c0 .6-.5 1.1-1.1 1.1H2.85c-.6 0-1.1-.5-1.1-1.1z" fill="currentColor" fill-opacity=".16" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/></svg>`;
20719
+ var ICON_FOLDER_OPEN = `<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M1.75 12.4V4.2c0-.6.5-1.1 1.1-1.1h3.1c.35 0 .68.16.9.45l.7.95h3.9c.5 0 .92.34 1.05.8l.9 3.3H4.4l-1.5 3.1H2.85c-.6 0-1.1-.5-1.1-1.1z" fill="currentColor" fill-opacity=".16" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/><path d="M4.2 12.4l1.6-3.3h8.6l-1.7 3.3z" fill="currentColor" fill-opacity=".16" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/></svg>`;
20720
+ var ICON_FILE = `<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 2.2h4.6L12 5.6v8.2H4z" fill="currentColor" fill-opacity=".1" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/><path d="M8.4 2.4V5.7H11.7" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/></svg>`;
20721
+ var ICON_CHEVRON = `<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
20722
+ var panelEl = null;
20723
+ var treeEl = null;
20724
+ var nameInput = null;
20725
+ var filterInput = null;
20726
+ var statusEl = null;
20727
+ var newFolderBtn = null;
20728
+ var createBtn = null;
20729
+ var root = { name: "Project", path: ROOT_PATH, type: "directory", expanded: true, loaded: false, children: [] };
20730
+ var selectedFolder = ROOT_PATH;
20731
+ var filter = "";
20732
+ var inlineCreate = null;
20733
+ var loadingPaths = /* @__PURE__ */ new Set();
20734
+ function findNode(path, nodes = [root]) {
20735
+ for (const node of nodes) {
20736
+ if (node.path === path) return node;
20737
+ if (node.type === "directory") {
20738
+ const found = findNode(path, node.children);
20739
+ if (found) return found;
20740
+ }
20741
+ }
20742
+ return null;
20743
+ }
20744
+ function toNode(entry) {
20745
+ return { ...entry, expanded: false, loaded: false, children: [] };
20746
+ }
20747
+ function requestChildren(path, force = false) {
20748
+ const node = findNode(path);
20749
+ if (!node || node.type !== "directory") return;
20750
+ if (node.loaded && !force) return;
20751
+ if (state.bridgeSocket?.readyState !== WebSocket.OPEN) {
20752
+ setStatus2("The Lasso agent bridge is not connected.", true);
20753
+ return;
20754
+ }
20755
+ loadingPaths.add(path);
20756
+ render2();
20757
+ state.bridgeSocket.send(JSON.stringify({ type: "list_page_folders", path }));
20758
+ }
20759
+ function revealSelected() {
20760
+ const found = findNode(selectedFolder);
20761
+ if (!found || found === root) return;
20762
+ const chain = [];
20763
+ const collect = (nodes, trail) => {
20764
+ for (const node of nodes) {
20765
+ if (node === found) {
20766
+ chain.push(...trail);
20767
+ return true;
20768
+ }
20769
+ if (node.type === "directory" && collect(node.children, [...trail, node])) return true;
20770
+ }
20771
+ return false;
20772
+ };
20773
+ if (!collect(root.children, [])) return;
20774
+ for (const node of chain) {
20775
+ if (!node.expanded) {
20776
+ node.expanded = true;
20777
+ if (!node.loaded) requestChildren(node.path);
20778
+ }
20779
+ }
20780
+ }
20781
+ function setStatus2(message, isError = false) {
20782
+ if (!statusEl) return;
20783
+ statusEl.textContent = message;
20784
+ statusEl.classList.toggle("error", isError);
20785
+ }
20786
+ function matchesFilter(node, term) {
20787
+ if (node.name.toLowerCase().includes(term)) return true;
20788
+ return node.children.some((child) => child.type === "directory" && child.expanded && matchesFilter(child, term));
20789
+ }
20790
+ function render2() {
20791
+ if (!treeEl) return;
20792
+ const rows = [];
20793
+ const term = filter.trim().toLowerCase();
20794
+ const walk = (nodes, depth) => {
20795
+ for (const node of nodes) {
20796
+ if (term && !matchesFilter(node, term)) continue;
20797
+ rows.push(renderRow(node, depth));
20798
+ if (node.type === "directory" && node.expanded) {
20799
+ if (inlineCreate?.parent === node.path) rows.push(renderInlineCreate(depth + 1));
20800
+ if (loadingPaths.has(node.path)) {
20801
+ rows.push(placeholderRow(depth + 1, "Loading\u2026"));
20802
+ continue;
20803
+ }
20804
+ if (!node.children.length) {
20805
+ if (node.loaded) rows.push(placeholderRow(depth + 1, "Empty"));
20806
+ continue;
20807
+ }
20808
+ walk(node.children, depth + 1);
20809
+ }
20810
+ }
20811
+ };
20812
+ walk([root], 0);
20813
+ if (!rows.length) {
20814
+ rows.push(placeholderRow(0, term ? "No matching folders" : loadingPaths.size ? "Loading folders\u2026" : "No folders to show"));
20815
+ }
20816
+ treeEl.replaceChildren(...rows);
20817
+ syncCreateButton();
20818
+ }
20819
+ function placeholderRow(depth, label) {
20820
+ const row = document.createElement("div");
20821
+ row.className = "lasso-page-row muted";
20822
+ row.style.setProperty("--lasso-page-depth", String(depth));
20823
+ row.textContent = label;
20824
+ return row;
20825
+ }
20826
+ function renderRow(node, depth) {
20827
+ const isDirectory = node.type === "directory";
20828
+ const row = document.createElement("div");
20829
+ row.className = "lasso-page-row";
20830
+ row.dataset.path = node.path;
20831
+ row.dataset.type = node.type;
20832
+ row.style.setProperty("--lasso-page-depth", String(depth));
20833
+ row.setAttribute("role", "treeitem");
20834
+ if (isDirectory) {
20835
+ row.setAttribute("aria-expanded", String(node.expanded));
20836
+ }
20837
+ row.classList.toggle("selected", isDirectory && node.path === selectedFolder);
20838
+ const twisty = document.createElement("span");
20839
+ twisty.className = "lasso-page-twisty";
20840
+ if (isDirectory) {
20841
+ twisty.innerHTML = ICON_CHEVRON;
20842
+ twisty.classList.toggle("open", node.expanded);
20843
+ twisty.title = node.expanded ? "Collapse" : "Expand";
20844
+ twisty.addEventListener("click", (event) => {
20845
+ event.preventDefault();
20846
+ event.stopPropagation();
20847
+ toggleDirectory(node);
20848
+ });
20849
+ }
20850
+ const icon = document.createElement("span");
20851
+ icon.className = `lasso-page-icon ${isDirectory ? "folder" : "file"}`;
20852
+ icon.innerHTML = isDirectory && node.expanded ? ICON_FOLDER_OPEN : isDirectory ? ICON_FOLDER : ICON_FILE;
20853
+ const label = document.createElement("span");
20854
+ label.className = "lasso-page-label";
20855
+ label.textContent = node.name;
20856
+ row.append(twisty, icon, label);
20857
+ row.addEventListener("click", (event) => {
20858
+ event.preventDefault();
20859
+ event.stopPropagation();
20860
+ if (isDirectory) {
20861
+ selectFolder(node.path);
20862
+ if (!node.expanded) toggleDirectory(node);
20863
+ } else {
20864
+ selectFolder(node.path.includes("/") ? node.path.slice(0, node.path.lastIndexOf("/")) : ROOT_PATH);
20865
+ if (nameInput && !nameInput.value.trim()) nameInput.value = node.name;
20866
+ }
20867
+ });
20868
+ return row;
20869
+ }
20870
+ function renderInlineCreate(depth) {
20871
+ const row = document.createElement("div");
20872
+ row.className = "lasso-page-row creating";
20873
+ row.style.setProperty("--lasso-page-depth", String(depth));
20874
+ const icon = document.createElement("span");
20875
+ icon.className = "lasso-page-icon folder";
20876
+ icon.innerHTML = ICON_FOLDER;
20877
+ const input = document.createElement("input");
20878
+ input.className = "lasso-page-inline-input";
20879
+ input.type = "text";
20880
+ input.placeholder = "New folder name";
20881
+ input.setAttribute("aria-label", "New folder name");
20882
+ const confirm = document.createElement("button");
20883
+ confirm.type = "button";
20884
+ confirm.className = "lasso-page-inline-confirm";
20885
+ confirm.title = "Create folder";
20886
+ confirm.setAttribute("aria-label", "Create folder");
20887
+ confirm.innerHTML = `<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8.4l3 3 6-6.4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
20888
+ const cancel = document.createElement("button");
20889
+ cancel.type = "button";
20890
+ cancel.className = "lasso-page-inline-cancel";
20891
+ cancel.title = "Cancel";
20892
+ cancel.setAttribute("aria-label", "Cancel folder creation");
20893
+ cancel.innerHTML = `<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4.5 4.5l7 7M11.5 4.5l-7 7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>`;
20894
+ const submit = () => {
20895
+ const name = input.value.trim();
20896
+ if (!name) {
20897
+ cancelCreate();
20898
+ return;
20899
+ }
20900
+ if (state.bridgeSocket?.readyState !== WebSocket.OPEN) {
20901
+ setStatus2("The Lasso agent bridge is not connected.", true);
20902
+ return;
20903
+ }
20904
+ const parent = inlineCreate?.parent || selectedFolder;
20905
+ setStatus2(`Creating ${name}\u2026`);
20906
+ state.bridgeSocket.send(JSON.stringify({ type: "create_page_folder", parent, name }));
20907
+ inlineCreate = null;
20908
+ render2();
20909
+ };
20910
+ input.addEventListener("keydown", (event) => {
20911
+ event.stopPropagation();
20912
+ if (event.key === "Enter") {
20913
+ event.preventDefault();
20914
+ submit();
20915
+ } else if (event.key === "Escape") {
20916
+ event.preventDefault();
20917
+ cancelCreate();
20918
+ }
20919
+ });
20920
+ input.addEventListener("click", (event) => event.stopPropagation());
20921
+ confirm.addEventListener("click", (event) => {
20922
+ event.preventDefault();
20923
+ event.stopPropagation();
20924
+ submit();
20925
+ });
20926
+ cancel.addEventListener("click", (event) => {
20927
+ event.preventDefault();
20928
+ event.stopPropagation();
20929
+ cancelCreate();
20930
+ });
20931
+ row.append(icon, input, confirm, cancel);
20932
+ requestAnimationFrame(() => input.focus());
20933
+ return row;
20934
+ }
20935
+ function cancelCreate() {
20936
+ inlineCreate = null;
20937
+ render2();
20938
+ }
20939
+ function startInlineCreate() {
20940
+ inlineCreate = { parent: selectedFolder };
20941
+ setStatus2("");
20942
+ render2();
20943
+ }
20944
+ function toggleDirectory(node) {
20945
+ node.expanded = !node.expanded;
20946
+ if (node.expanded && !node.loaded) requestChildren(node.path);
20947
+ render2();
20948
+ }
20949
+ function selectFolder(path) {
20950
+ selectedFolder = path;
20951
+ if (nameInput) {
20952
+ nameInput.placeholder = path === ROOT_PATH ? DEFAULT_FILE_NAME : `${path}/page.tsx`;
20953
+ }
20954
+ render2();
20955
+ }
20956
+ function syncCreateButton() {
20957
+ if (!createBtn) return;
20958
+ const name = nameInput?.value.trim() || "";
20959
+ createBtn.disabled = !name;
20960
+ if (nameInput) nameInput.classList.toggle("invalid", Boolean(name) && /(^|\/)(\.|\.\.)$/.test(name));
20961
+ }
20962
+ function selectedTargetLabel() {
20963
+ return selectedFolder === ROOT_PATH ? "project root" : selectedFolder;
20964
+ }
20965
+ function buildPagePanel() {
20966
+ const dom = getDOM();
20967
+ const el = document.createElement("div");
20968
+ el.className = "lasso-page-backdrop";
20969
+ el.hidden = true;
20970
+ el.innerHTML = `
20971
+ <div class="lasso-page-panel" role="dialog" aria-modal="true" aria-labelledby="lasso-page-title">
20972
+ <div class="lasso-page-header">
20973
+ <div class="lasso-page-title-row">
20974
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
20975
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
20976
+ <path d="M14 2v6h6"/>
20977
+ </svg>
20978
+ <span class="lasso-page-title" id="lasso-page-title">New page</span>
20979
+ </div>
20980
+ <button class="lasso-page-close" type="button" aria-label="Close">
20981
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
20982
+ <path d="M18 6L6 18M6 6l12 12"/>
20983
+ </svg>
20984
+ </button>
20985
+ </div>
20986
+
20987
+ <label class="lasso-page-field">
20988
+ <span class="lasso-page-label-text">Name</span>
20989
+ <input class="lasso-page-name" type="text" spellcheck="false" autocomplete="off" placeholder="${DEFAULT_FILE_NAME}" />
20990
+ </label>
20991
+
20992
+ <div class="lasso-page-field">
20993
+ <div class="lasso-page-field-head">
20994
+ <span class="lasso-page-label-text">Folder</span>
20995
+ <div class="lasso-page-field-tools">
20996
+ <input class="lasso-page-filter" type="text" spellcheck="false" autocomplete="off" placeholder="Filter" aria-label="Filter folders" />
20997
+ <button class="lasso-page-new-folder" type="button" title="New folder">
20998
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
20999
+ <path d="M12 5v14M5 12h14"/>
21000
+ </svg>
21001
+ </button>
21002
+ </div>
21003
+ </div>
21004
+ <div class="lasso-page-tree" role="tree" aria-label="Project folders"></div>
21005
+ </div>
21006
+
21007
+ <div class="lasso-page-footer">
21008
+ <div class="lasso-page-status" aria-live="polite"></div>
21009
+ <button class="lasso-page-create" type="button">Create page</button>
21010
+ </div>
21011
+ </div>
21012
+ `;
21013
+ dom.shadow.appendChild(el);
21014
+ panelEl = el;
21015
+ treeEl = el.querySelector(".lasso-page-tree");
21016
+ nameInput = el.querySelector(".lasso-page-name");
21017
+ filterInput = el.querySelector(".lasso-page-filter");
21018
+ statusEl = el.querySelector(".lasso-page-status");
21019
+ newFolderBtn = el.querySelector(".lasso-page-new-folder");
21020
+ createBtn = el.querySelector(".lasso-page-create");
21021
+ el.addEventListener("pointerdown", (event) => {
21022
+ if (event.target === el) closePagePanel();
21023
+ });
21024
+ el.addEventListener("keydown", (event) => {
21025
+ if (event.key !== "Escape") return;
21026
+ if (inlineCreate) {
21027
+ cancelCreate();
21028
+ return;
21029
+ }
21030
+ event.preventDefault();
21031
+ event.stopPropagation();
21032
+ closePagePanel();
21033
+ });
21034
+ el.querySelector(".lasso-page-close").addEventListener("click", (event) => {
21035
+ event.preventDefault();
21036
+ event.stopPropagation();
21037
+ closePagePanel();
21038
+ });
21039
+ newFolderBtn.addEventListener("click", (event) => {
21040
+ event.preventDefault();
21041
+ event.stopPropagation();
21042
+ startInlineCreate();
21043
+ });
21044
+ nameInput.addEventListener("input", syncCreateButton);
21045
+ nameInput.addEventListener("keydown", (event) => {
21046
+ if (event.key === "Enter") {
21047
+ event.preventDefault();
21048
+ createPage();
21049
+ }
21050
+ });
21051
+ filterInput.addEventListener("input", () => {
21052
+ filter = filterInput?.value || "";
21053
+ render2();
21054
+ });
21055
+ filterInput.addEventListener("keydown", (event) => {
21056
+ if (event.key === "Escape") {
21057
+ event.preventDefault();
21058
+ if (filterInput?.value) {
21059
+ filterInput.value = "";
21060
+ filter = "";
21061
+ } else {
21062
+ closePagePanel();
21063
+ }
21064
+ render2();
21065
+ }
21066
+ });
21067
+ createBtn.addEventListener("click", (event) => {
21068
+ event.preventDefault();
21069
+ event.stopPropagation();
21070
+ createPage();
21071
+ });
21072
+ window.addEventListener("lasso-page-folders", (event) => {
21073
+ const detail = event.detail;
21074
+ if (!detail) return;
21075
+ loadingPaths.delete(detail.path);
21076
+ const node = findNode(detail.path);
21077
+ if (detail.error) {
21078
+ setStatus2(detail.error, true);
21079
+ } else if (node) {
21080
+ if (detail.project) root.name = detail.project;
21081
+ node.children = detail.entries.map(toNode);
21082
+ node.loaded = true;
21083
+ }
21084
+ render2();
21085
+ });
21086
+ window.addEventListener("lasso-page-folder-created", (event) => {
21087
+ const detail = event.detail;
21088
+ if (!detail) return;
21089
+ if (detail.error) {
21090
+ setStatus2(detail.error, true);
21091
+ return;
21092
+ }
21093
+ setStatus2(`Created folder ${detail.path}`);
21094
+ requestChildren(detail.path.replace(/\/[^/]+$/, "") || ROOT_PATH, true);
21095
+ selectFolder(detail.path);
21096
+ });
21097
+ window.addEventListener("lasso-page-created", (event) => {
21098
+ const detail = event.detail;
21099
+ if (!detail) return;
21100
+ if (detail.error) {
21101
+ setStatus2(detail.error, true);
21102
+ return;
21103
+ }
21104
+ const parent = detail.path.includes("/") ? detail.path.slice(0, detail.path.lastIndexOf("/")) : ROOT_PATH;
21105
+ requestChildren(parent, true);
21106
+ setStatus2(`Created ${detail.path}`);
21107
+ if (nameInput) {
21108
+ nameInput.value = "";
21109
+ nameInput.focus();
21110
+ }
21111
+ syncCreateButton();
21112
+ });
21113
+ return el;
21114
+ }
21115
+ function createPage() {
21116
+ if (!nameInput || !createBtn) return;
21117
+ const fileName = nameInput.value.trim();
21118
+ if (!fileName) {
21119
+ setStatus2("Enter a name for the new page.", true);
21120
+ nameInput.focus();
21121
+ return;
21122
+ }
21123
+ if (state.bridgeSocket?.readyState !== WebSocket.OPEN) {
21124
+ setStatus2("The Lasso agent bridge is not connected.", true);
21125
+ return;
21126
+ }
21127
+ createBtn.disabled = true;
21128
+ setStatus2(`Creating ${fileName} in ${selectedTargetLabel()}\u2026`);
21129
+ state.bridgeSocket.send(
21130
+ JSON.stringify({
21131
+ type: "create_page",
21132
+ folder: selectedFolder,
21133
+ fileName,
21134
+ content: starterContent(fileName)
21135
+ })
21136
+ );
21137
+ }
21138
+ function starterContent(fileName) {
21139
+ const extension = (fileName.split(".").pop() || "").toLowerCase();
21140
+ const base = (fileName.split("/").pop() || "page").replace(/\.[^.]+$/, "");
21141
+ const component = base.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join("") || "Page";
21142
+ const className = base.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "page";
21143
+ if (extension === "tsx" || extension === "jsx") {
21144
+ return `export default function ${component}() {
21145
+ return (
21146
+ <main className="${className}">
21147
+ <h1>${component}</h1>
21148
+ </main>
21149
+ );
21150
+ }
21151
+ `;
21152
+ }
21153
+ if (extension === "ts" || extension === "js") {
21154
+ return `export function ${component.toLowerCase()}() {
21155
+ return null;
21156
+ }
21157
+ `;
21158
+ }
21159
+ if (extension === "css") return `/* ${base} styles */
21160
+ `;
21161
+ if (extension === "json") return "{}\n";
21162
+ if (extension === "md") return `# ${base}
21163
+ `;
21164
+ return "";
21165
+ }
21166
+ function openPagePanel() {
21167
+ if (!panelEl) return;
21168
+ panelEl.hidden = false;
21169
+ setStatus2("");
21170
+ if (nameInput) nameInput.value = "";
21171
+ syncCreateButton();
21172
+ render2();
21173
+ requestChildren(ROOT_PATH, true);
21174
+ revealSelected();
21175
+ render2();
21176
+ requestAnimationFrame(() => nameInput?.focus());
21177
+ }
21178
+ function closePagePanel() {
21179
+ if (!panelEl) return;
21180
+ panelEl.hidden = true;
21181
+ inlineCreate = null;
21182
+ }
21183
+ function togglePagePanel() {
21184
+ if (!panelEl) return;
21185
+ if (panelEl.hidden) openPagePanel();
21186
+ else closePagePanel();
21187
+ }
21188
+ function isPagePanelOpen() {
21189
+ return panelEl ? !panelEl.hidden : false;
21190
+ }
21191
+
20490
21192
  // src/overlay/toolbar/toolbar.ts
20491
21193
  var COMMENT_CURSOR_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="32" viewBox="0 0 28 32"><defs><filter id="s" x="-30%" y="-30%" width="160%" height="160%"><feDropShadow dx="0" dy="1" stdDeviation="1.5" flood-color="rgba(0,0,0,0.5)"/></filter></defs><g filter="url(#s)"><path d="M4 2h16a3 3 0 0 1 3 3v13a3 3 0 0 1-3 3H10l-6 6V5a3 3 0 0 1 3-3z" fill="#7C3AED"/><path d="M4 2h16a3 3 0 0 1 3 3v13a3 3 0 0 1-3 3H10l-6 6V5a3 3 0 0 1 3-3z" fill="none" stroke="rgba(255,255,255,0.25)" stroke-width="0.8"/><line x1="12" y1="7" x2="12" y2="15" stroke="white" stroke-width="1.8" stroke-linecap="round"/><line x1="8" y1="11" x2="16" y2="11" stroke="white" stroke-width="1.8" stroke-linecap="round"/></g></svg>`;
20492
21194
  var COMMENT_CURSOR_URL = `url("data:image/svg+xml,${encodeURIComponent(COMMENT_CURSOR_SVG)}") 4 2, crosshair`;
@@ -20658,7 +21360,56 @@
20658
21360
  </svg>
20659
21361
  </button>
20660
21362
  `;
20661
- dom.shadow.append(toolbar, toolbarReopen, voiceBar);
21363
+ const miniToolbar = document.createElement("div");
21364
+ miniToolbar.className = "lasso-toolbar-mini";
21365
+ miniToolbar.innerHTML = `
21366
+ <button class="lasso-new-page-btn" type="button" aria-label="Create a new page" title="New page">
21367
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
21368
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
21369
+ <path d="M14 2v6h6"/>
21370
+ <path d="M12 12v6M9 15h6"/>
21371
+ </svg>
21372
+ <span>New Page</span>
21373
+ </button>
21374
+ `;
21375
+ dom.shadow.append(toolbar, miniToolbar, toolbarReopen, voiceBar);
21376
+ const tooltip = document.createElement("div");
21377
+ tooltip.className = "lasso-toolbar-tooltip";
21378
+ tooltip.hidden = true;
21379
+ tooltip.setAttribute("role", "tooltip");
21380
+ dom.shadow.appendChild(tooltip);
21381
+ let tooltipTarget = null;
21382
+ const showTooltip = (target) => {
21383
+ const label = target.dataset.tooltip || target.getAttribute("title") || target.getAttribute("aria-label");
21384
+ if (!label) return;
21385
+ target.removeAttribute("title");
21386
+ tooltipTarget = target;
21387
+ tooltip.textContent = label;
21388
+ tooltip.hidden = false;
21389
+ const rect = target.getBoundingClientRect();
21390
+ tooltip.style.left = `${rect.left + rect.width / 2}px`;
21391
+ tooltip.style.top = `${rect.bottom + 8}px`;
21392
+ };
21393
+ const hideTooltip = (target) => {
21394
+ if (!target || tooltipTarget === target) {
21395
+ tooltip.hidden = true;
21396
+ tooltipTarget = null;
21397
+ }
21398
+ };
21399
+ toolbar.querySelectorAll("[title]").forEach((target) => {
21400
+ target.dataset.tooltip = target.getAttribute("title") || "";
21401
+ target.addEventListener("pointerenter", () => showTooltip(target));
21402
+ target.addEventListener("pointerleave", () => hideTooltip(target));
21403
+ target.addEventListener("focusin", () => showTooltip(target));
21404
+ target.addEventListener("focusout", () => hideTooltip(target));
21405
+ });
21406
+ miniToolbar.querySelectorAll("[title]").forEach((target) => {
21407
+ target.dataset.tooltip = target.getAttribute("title") || "";
21408
+ target.addEventListener("pointerenter", () => showTooltip(target));
21409
+ target.addEventListener("pointerleave", () => hideTooltip(target));
21410
+ target.addEventListener("focusin", () => showTooltip(target));
21411
+ target.addEventListener("focusout", () => hideTooltip(target));
21412
+ });
20662
21413
  const selectBtn = toolbar.querySelector(".select-tool");
20663
21414
  const dragBtn = toolbar.querySelector(".drag-tool");
20664
21415
  const previewBtn = toolbar.querySelector(".preview-tool");
@@ -20670,6 +21421,12 @@
20670
21421
  const clipboardBtn = toolbar.querySelector(".clipboard-tool");
20671
21422
  const voiceBtn = toolbar.querySelector(".voice-tool");
20672
21423
  const dismissBtn = toolbar.querySelector(".lasso-toolbar-dismiss");
21424
+ const newPageBtn = miniToolbar.querySelector(".lasso-new-page-btn");
21425
+ newPageBtn.addEventListener("click", (event) => {
21426
+ event.preventDefault();
21427
+ event.stopPropagation();
21428
+ togglePagePanel();
21429
+ });
20673
21430
  selectBtn.addEventListener("click", (e) => {
20674
21431
  e.preventDefault();
20675
21432
  e.stopPropagation();
@@ -20728,10 +21485,12 @@
20728
21485
  });
20729
21486
  dismissBtn.addEventListener("click", () => {
20730
21487
  toolbar.classList.add("dismissed");
21488
+ miniToolbar.classList.add("dismissed");
20731
21489
  toolbarReopen.classList.add("visible");
20732
21490
  });
20733
21491
  toolbarReopen.addEventListener("click", () => {
20734
21492
  toolbar.classList.remove("dismissed");
21493
+ miniToolbar.classList.remove("dismissed");
20735
21494
  toolbarReopen.classList.remove("visible");
20736
21495
  });
20737
21496
  voiceBar.querySelector(".mute-toggle").addEventListener("click", () => {
@@ -20804,6 +21563,26 @@
20804
21563
  if (message.type === "git_progress" && message.message) {
20805
21564
  setGitMessage(message.message);
20806
21565
  }
21566
+ if (message.type === "agent_prompt" && message.taskId && message.prompt) {
21567
+ showAgentPrompt(message.taskId, message.prompt);
21568
+ return;
21569
+ }
21570
+ if (message.type === "page_folders") {
21571
+ window.dispatchEvent(
21572
+ new CustomEvent("lasso-page-folders", {
21573
+ detail: { path: message.path || ".", entries: message.entries || [], project: message.project, error: message.error }
21574
+ })
21575
+ );
21576
+ return;
21577
+ }
21578
+ if (message.type === "page_created") {
21579
+ window.dispatchEvent(new CustomEvent("lasso-page-created", { detail: { path: message.path || "", error: message.error } }));
21580
+ return;
21581
+ }
21582
+ if (message.type === "page_folder_created") {
21583
+ window.dispatchEvent(new CustomEvent("lasso-page-folder-created", { detail: { path: message.path || "", error: message.error } }));
21584
+ return;
21585
+ }
20807
21586
  if (message.type === "agent_status" && message.status && message.message) {
20808
21587
  const taskId2 = message.taskId;
20809
21588
  const task = taskId2 ? getAgentTask(taskId2) : void 0;
@@ -20906,6 +21685,7 @@
20906
21685
  buildNotepadPanel();
20907
21686
  buildClipboardPanel();
20908
21687
  buildTaskPanel();
21688
+ buildPagePanel();
20909
21689
  buildPrompt();
20910
21690
  buildDrag();
20911
21691
  initErrorListeners();
@@ -20980,6 +21760,10 @@
20980
21760
  closePinThread();
20981
21761
  return;
20982
21762
  }
21763
+ if (isPagePanelOpen()) {
21764
+ closePagePanel();
21765
+ return;
21766
+ }
20983
21767
  if (isPromptOpen()) {
20984
21768
  cancelPrompt(true);
20985
21769
  return;