@lasso-ai/cli 1.1.0 → 1.1.2
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/ARCHITECTURE.md +55 -37
- package/CHANGELOG.md +14 -0
- package/README.md +42 -41
- package/dist/cli/agent.js +77 -3
- package/dist/cli/bridge.d.ts +18 -1
- package/dist/cli/bridge.js +65 -13
- package/dist/overlay.js +706 -159
- package/package.json +1 -1
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,
|
|
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,
|
|
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,
|
|
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,
|
|
4636
|
+
parseNodeTree(context, childNode.shadowRoot, container, root2);
|
|
4637
4637
|
} else if (!isTextareaElement(childNode) && !isSVGElement(childNode) && !isSelectElement(childNode)) {
|
|
4638
|
-
parseNodeTree(context, childNode, container,
|
|
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,
|
|
4682
|
-
return container.styles.isPositionedWithZIndex() || container.styles.opacity < 1 || container.styles.isTransformed() || isBodyElement(node) &&
|
|
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
|
|
6266
|
+
var root2 = new StackingContext(paintContainer);
|
|
6267
6267
|
var listItems = [];
|
|
6268
|
-
parseStackTree(paintContainer,
|
|
6268
|
+
parseStackTree(paintContainer, root2, root2, listItems);
|
|
6269
6269
|
processListItems(paintContainer.container, listItems);
|
|
6270
|
-
return
|
|
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,
|
|
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
|
-
|
|
7784
|
-
if (backgroundColor2 ===
|
|
7785
|
-
|
|
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(
|
|
7789
|
+
return [4, renderer.render(root2)];
|
|
7790
7790
|
case 4:
|
|
7791
7791
|
canvas = _u.sent();
|
|
7792
7792
|
_u.label = 5;
|
|
@@ -8115,7 +8115,7 @@
|
|
|
8115
8115
|
align-items: center;
|
|
8116
8116
|
gap: 6px;
|
|
8117
8117
|
height: 34px;
|
|
8118
|
-
padding: 0
|
|
8118
|
+
padding: 0 12px;
|
|
8119
8119
|
border: 0;
|
|
8120
8120
|
border-radius: var(--lo-radius-full);
|
|
8121
8121
|
background: var(--lo-primary);
|
|
@@ -8126,22 +8126,62 @@
|
|
|
8126
8126
|
cursor: pointer;
|
|
8127
8127
|
transition: transform 150ms ease, filter 150ms ease;
|
|
8128
8128
|
}
|
|
8129
|
-
.lasso-new-page-btn span:first-child { font-size: 19px; font-weight: 400; line-height: 1; }
|
|
8130
8129
|
.lasso-new-page-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
|
|
8131
8130
|
.lasso-new-page-btn:active { transform: scale(.97); }
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
.lasso-
|
|
8137
|
-
.lasso-
|
|
8138
|
-
.lasso-
|
|
8139
|
-
|
|
8140
|
-
.lasso-page-
|
|
8141
|
-
.lasso-page-
|
|
8142
|
-
.lasso-
|
|
8143
|
-
.lasso-
|
|
8144
|
-
.lasso-
|
|
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%; } }
|
|
8145
8185
|
|
|
8146
8186
|
.lasso-tb-sep {
|
|
8147
8187
|
width: 1px;
|
|
@@ -11017,14 +11057,26 @@
|
|
|
11017
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; }
|
|
11018
11058
|
|
|
11019
11059
|
.lasso-agent-tasks-badge { position: absolute; top: 5px; right: 5px; width: 6px; height: 6px; border-radius: 50%; background: var(--lo-primary); }
|
|
11020
|
-
.lasso-agent-prompt { position: fixed;
|
|
11021
|
-
.lasso-agent-prompt[hidden] { display: none; }
|
|
11022
|
-
.lasso-agent-prompt
|
|
11023
|
-
|
|
11024
|
-
.lasso-agent-prompt-
|
|
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; }
|
|
11025
11075
|
.lasso-agent-prompt-actions { display: flex; justify-content: flex-end; gap: 7px; }
|
|
11026
|
-
.lasso-agent-prompt-actions button { padding: 7px
|
|
11027
|
-
.lasso-agent-prompt-actions button
|
|
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; }
|
|
11028
11080
|
|
|
11029
11081
|
.lasso-todo-header {
|
|
11030
11082
|
display: flex;
|
|
@@ -12386,15 +12438,15 @@
|
|
|
12386
12438
|
return panel;
|
|
12387
12439
|
}
|
|
12388
12440
|
function renderTasks() {
|
|
12389
|
-
const
|
|
12390
|
-
if (!
|
|
12441
|
+
const panelEl2 = panel;
|
|
12442
|
+
if (!panelEl2 || !list || !badge) return;
|
|
12391
12443
|
const activeCount = state.agentTasks.filter((task) => task.status !== "complete" && task.status !== "error" && task.status !== "stopped").length;
|
|
12392
12444
|
badge.hidden = state.agentTasks.length === 0;
|
|
12393
12445
|
badge.textContent = String(activeCount || state.agentTasks.length);
|
|
12394
12446
|
const navBadge = getDOM().shadow.querySelector(".lasso-agent-tasks-badge");
|
|
12395
12447
|
if (navBadge) navBadge.hidden = activeCount === 0;
|
|
12396
12448
|
list.replaceChildren();
|
|
12397
|
-
const activeTab =
|
|
12449
|
+
const activeTab = panelEl2.querySelector(".lasso-task-tab.active")?.dataset.taskTab || "active";
|
|
12398
12450
|
const visibleTasks = state.agentTasks.filter((task) => activeTab === "complete" ? task.status === "complete" : task.status !== "complete");
|
|
12399
12451
|
if (!visibleTasks.length) {
|
|
12400
12452
|
list.innerHTML = `<div class="lasso-task-empty">Prompt an element to start a task.</div>`;
|
|
@@ -17782,7 +17834,7 @@
|
|
|
17782
17834
|
const textarea = el.querySelector(".lasso-notepad-textarea");
|
|
17783
17835
|
const preview = el.querySelector(".lasso-notepad-preview");
|
|
17784
17836
|
const countEl = el.querySelector(".lasso-notepad-count");
|
|
17785
|
-
const
|
|
17837
|
+
const statusEl2 = el.querySelector(".lasso-notepad-status");
|
|
17786
17838
|
textarea.value = initialContent;
|
|
17787
17839
|
collabEmit("note:get", {}, (response) => {
|
|
17788
17840
|
if (response.ok && typeof response.body === "string") {
|
|
@@ -17804,7 +17856,7 @@
|
|
|
17804
17856
|
voiceBtn.classList.remove("recording");
|
|
17805
17857
|
voiceBtn.classList.add("transcribing");
|
|
17806
17858
|
voiceBtn.title = "Transcribing\u2026";
|
|
17807
|
-
|
|
17859
|
+
statusEl2.textContent = "Transcribing\u2026";
|
|
17808
17860
|
try {
|
|
17809
17861
|
const result = await stopVoiceRecording();
|
|
17810
17862
|
if (result.text) {
|
|
@@ -17818,20 +17870,20 @@
|
|
|
17818
17870
|
textarea.setSelectionRange(cursor, cursor);
|
|
17819
17871
|
textarea.dispatchEvent(new Event("input"));
|
|
17820
17872
|
textarea.focus();
|
|
17821
|
-
|
|
17873
|
+
statusEl2.textContent = "Transcribed";
|
|
17822
17874
|
window.setTimeout(() => {
|
|
17823
|
-
|
|
17875
|
+
statusEl2.textContent = "Autosaved";
|
|
17824
17876
|
}, 2e3);
|
|
17825
17877
|
} else {
|
|
17826
|
-
|
|
17878
|
+
statusEl2.textContent = "No speech detected";
|
|
17827
17879
|
window.setTimeout(() => {
|
|
17828
|
-
|
|
17880
|
+
statusEl2.textContent = "Autosaved";
|
|
17829
17881
|
}, 1500);
|
|
17830
17882
|
}
|
|
17831
17883
|
} catch (err) {
|
|
17832
|
-
|
|
17884
|
+
statusEl2.textContent = err?.message || "Transcription failed";
|
|
17833
17885
|
window.setTimeout(() => {
|
|
17834
|
-
|
|
17886
|
+
statusEl2.textContent = "Autosaved";
|
|
17835
17887
|
}, 2500);
|
|
17836
17888
|
} finally {
|
|
17837
17889
|
voiceBtn.classList.remove("transcribing");
|
|
@@ -17842,11 +17894,11 @@
|
|
|
17842
17894
|
await startVoiceRecording();
|
|
17843
17895
|
voiceBtn.classList.add("recording");
|
|
17844
17896
|
voiceBtn.title = "Recording\u2026 click again to stop & transcribe";
|
|
17845
|
-
|
|
17897
|
+
statusEl2.textContent = "Listening\u2026";
|
|
17846
17898
|
} catch (err) {
|
|
17847
|
-
|
|
17899
|
+
statusEl2.textContent = err?.message || "Microphone access denied";
|
|
17848
17900
|
window.setTimeout(() => {
|
|
17849
|
-
|
|
17901
|
+
statusEl2.textContent = "Autosaved";
|
|
17850
17902
|
}, 3e3);
|
|
17851
17903
|
}
|
|
17852
17904
|
}
|
|
@@ -17870,11 +17922,11 @@
|
|
|
17870
17922
|
textarea.addEventListener("input", () => {
|
|
17871
17923
|
const text = textarea.value;
|
|
17872
17924
|
updateCounts(text.length, countEl);
|
|
17873
|
-
|
|
17925
|
+
statusEl2.textContent = "Saving\u2026";
|
|
17874
17926
|
if (saveTimer) window.clearTimeout(saveTimer);
|
|
17875
17927
|
saveTimer = window.setTimeout(() => {
|
|
17876
17928
|
saveNote(text);
|
|
17877
|
-
|
|
17929
|
+
statusEl2.textContent = "Autosaved";
|
|
17878
17930
|
}, 400);
|
|
17879
17931
|
});
|
|
17880
17932
|
copyBtn.addEventListener("click", async () => {
|
|
@@ -17894,12 +17946,12 @@
|
|
|
17894
17946
|
ta.remove();
|
|
17895
17947
|
}
|
|
17896
17948
|
}
|
|
17897
|
-
|
|
17949
|
+
statusEl2.textContent = "Copied!";
|
|
17898
17950
|
setTimeout(() => {
|
|
17899
|
-
|
|
17951
|
+
statusEl2.textContent = "Autosaved";
|
|
17900
17952
|
}, 1500);
|
|
17901
17953
|
} catch {
|
|
17902
|
-
|
|
17954
|
+
statusEl2.textContent = "Copy failed";
|
|
17903
17955
|
}
|
|
17904
17956
|
});
|
|
17905
17957
|
return el;
|
|
@@ -18671,29 +18723,56 @@
|
|
|
18671
18723
|
dom.shadow.appendChild(el);
|
|
18672
18724
|
promptEl = el;
|
|
18673
18725
|
const agentPrompt = document.createElement("div");
|
|
18674
|
-
agentPrompt.className = "lasso-agent-prompt";
|
|
18726
|
+
agentPrompt.className = "lasso-agent-prompt-backdrop";
|
|
18675
18727
|
agentPrompt.hidden = true;
|
|
18676
18728
|
agentPrompt.innerHTML = `
|
|
18677
|
-
<div class="lasso-agent-prompt
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
18682
|
-
|
|
18683
|
-
|
|
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>
|
|
18684
18750
|
</div>
|
|
18685
18751
|
`;
|
|
18686
18752
|
dom.shadow.appendChild(agentPrompt);
|
|
18687
18753
|
agentPromptPanel = agentPrompt;
|
|
18688
|
-
agentPrompt.
|
|
18689
|
-
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
|
|
18693
|
-
|
|
18694
|
-
|
|
18695
|
-
|
|
18696
|
-
|
|
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);
|
|
18697
18776
|
});
|
|
18698
18777
|
promptInput = el.querySelector(".lasso-prompt-input");
|
|
18699
18778
|
promptElement = el.querySelector(".lasso-prompt-element-name");
|
|
@@ -18771,9 +18850,9 @@
|
|
|
18771
18850
|
});
|
|
18772
18851
|
modelMenu.addEventListener("click", (event) => {
|
|
18773
18852
|
event.stopPropagation();
|
|
18774
|
-
const
|
|
18775
|
-
if (
|
|
18776
|
-
state.modelFilter =
|
|
18853
|
+
const filter2 = event.target.closest(".lasso-model-filter");
|
|
18854
|
+
if (filter2?.dataset.providerFilter) {
|
|
18855
|
+
state.modelFilter = filter2.dataset.providerFilter;
|
|
18777
18856
|
refreshModelMenu();
|
|
18778
18857
|
return;
|
|
18779
18858
|
}
|
|
@@ -18897,17 +18976,59 @@
|
|
|
18897
18976
|
function showAgentPrompt(taskId2, prompt) {
|
|
18898
18977
|
if (!agentPromptPanel) return;
|
|
18899
18978
|
agentPromptTaskId = taskId2;
|
|
18979
|
+
const isPermission = prompt.kind === "permission";
|
|
18900
18980
|
const message = agentPromptPanel.querySelector(".lasso-agent-prompt-message");
|
|
18981
|
+
const subtitle = agentPromptPanel.querySelector(".lasso-agent-prompt-subtitle");
|
|
18901
18982
|
const input = agentPromptPanel.querySelector(".lasso-agent-prompt-input");
|
|
18902
|
-
|
|
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
|
+
}
|
|
18903
18991
|
if (input) {
|
|
18904
18992
|
input.value = "";
|
|
18905
|
-
input.hidden =
|
|
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
|
+
);
|
|
18906
19013
|
}
|
|
18907
|
-
agentPromptPanel.querySelector('[data-agent-response="Allow"]').hidden = prompt.kind !== "permission";
|
|
18908
|
-
agentPromptPanel.querySelector('[data-agent-response="Deny"]').hidden = prompt.kind !== "permission";
|
|
18909
19014
|
agentPromptPanel.hidden = false;
|
|
18910
|
-
if (
|
|
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);
|
|
18911
19032
|
}
|
|
18912
19033
|
function refreshModelMenu() {
|
|
18913
19034
|
if (!modelMenu) return;
|
|
@@ -18915,12 +19036,12 @@
|
|
|
18915
19036
|
filters.className = "lasso-model-filters";
|
|
18916
19037
|
const providers = ["all", ...Array.from(new Set(state.MODELS.map((m) => m.provider)))];
|
|
18917
19038
|
for (const provider of providers) {
|
|
18918
|
-
const
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
filters.appendChild(
|
|
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);
|
|
18924
19045
|
}
|
|
18925
19046
|
const children = [filters];
|
|
18926
19047
|
const visibleProviders = state.modelFilter === "all" ? providers.slice(1) : [state.modelFilter];
|
|
@@ -20591,6 +20712,483 @@
|
|
|
20591
20712
|
}
|
|
20592
20713
|
}
|
|
20593
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
|
+
|
|
20594
21192
|
// src/overlay/toolbar/toolbar.ts
|
|
20595
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>`;
|
|
20596
21194
|
var COMMENT_CURSOR_URL = `url("data:image/svg+xml,${encodeURIComponent(COMMENT_CURSOR_SVG)}") 4 2, crosshair`;
|
|
@@ -20766,24 +21364,15 @@
|
|
|
20766
21364
|
miniToolbar.className = "lasso-toolbar-mini";
|
|
20767
21365
|
miniToolbar.innerHTML = `
|
|
20768
21366
|
<button class="lasso-new-page-btn" type="button" aria-label="Create a new page" title="New page">
|
|
20769
|
-
<
|
|
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>
|
|
20770
21372
|
<span>New Page</span>
|
|
20771
21373
|
</button>
|
|
20772
21374
|
`;
|
|
20773
|
-
|
|
20774
|
-
pagePanel.className = "lasso-new-page-panel";
|
|
20775
|
-
pagePanel.hidden = true;
|
|
20776
|
-
pagePanel.innerHTML = `
|
|
20777
|
-
<div class="lasso-new-page-header"><strong>New page</strong><button type="button" class="lasso-new-page-close" aria-label="Close">\xD7</button></div>
|
|
20778
|
-
<label>File name<input class="lasso-new-page-name" value="page.tsx" /></label>
|
|
20779
|
-
<label>Folder<div class="lasso-page-folder-list"><span>Loading folders\u2026</span></div></label>
|
|
20780
|
-
<label>Starter content<textarea class="lasso-new-page-content" rows="5">export default function Page() {
|
|
20781
|
-
return <main />;
|
|
20782
|
-
}</textarea></label>
|
|
20783
|
-
<div class="lasso-new-page-status" aria-live="polite"></div>
|
|
20784
|
-
<button type="button" class="lasso-new-page-create">Create page</button>
|
|
20785
|
-
`;
|
|
20786
|
-
dom.shadow.append(toolbar, miniToolbar, pagePanel, toolbarReopen, voiceBar);
|
|
21375
|
+
dom.shadow.append(toolbar, miniToolbar, toolbarReopen, voiceBar);
|
|
20787
21376
|
const tooltip = document.createElement("div");
|
|
20788
21377
|
tooltip.className = "lasso-toolbar-tooltip";
|
|
20789
21378
|
tooltip.hidden = true;
|
|
@@ -20833,65 +21422,10 @@
|
|
|
20833
21422
|
const voiceBtn = toolbar.querySelector(".voice-tool");
|
|
20834
21423
|
const dismissBtn = toolbar.querySelector(".lasso-toolbar-dismiss");
|
|
20835
21424
|
const newPageBtn = miniToolbar.querySelector(".lasso-new-page-btn");
|
|
20836
|
-
const folderList = pagePanel.querySelector(".lasso-page-folder-list");
|
|
20837
|
-
const pageStatus = pagePanel.querySelector(".lasso-new-page-status");
|
|
20838
|
-
let selectedFolder = ".";
|
|
20839
|
-
const requestFolders = () => {
|
|
20840
|
-
if (state.bridgeSocket?.readyState === WebSocket.OPEN) {
|
|
20841
|
-
folderList.innerHTML = "<span>Loading folders\u2026</span>";
|
|
20842
|
-
state.bridgeSocket.send(JSON.stringify({ type: "list_page_folders" }));
|
|
20843
|
-
} else {
|
|
20844
|
-
folderList.innerHTML = "<span>Bridge is not connected.</span>";
|
|
20845
|
-
}
|
|
20846
|
-
};
|
|
20847
|
-
window.addEventListener("lasso-page-folders", (event) => {
|
|
20848
|
-
const folders = event.detail || [];
|
|
20849
|
-
folderList.replaceChildren();
|
|
20850
|
-
for (const folder of folders) {
|
|
20851
|
-
const button = document.createElement("button");
|
|
20852
|
-
button.type = "button";
|
|
20853
|
-
button.textContent = folder === "." ? "Project root" : folder;
|
|
20854
|
-
button.className = folder === selectedFolder ? "selected" : "";
|
|
20855
|
-
button.addEventListener("click", () => {
|
|
20856
|
-
selectedFolder = folder;
|
|
20857
|
-
folderList.querySelectorAll("button").forEach((item) => item.classList.toggle("selected", item === button));
|
|
20858
|
-
});
|
|
20859
|
-
folderList.appendChild(button);
|
|
20860
|
-
}
|
|
20861
|
-
folderList.querySelector("button")?.click();
|
|
20862
|
-
});
|
|
20863
|
-
window.addEventListener("lasso-page-created", (event) => {
|
|
20864
|
-
const result = event.detail;
|
|
20865
|
-
pageStatus.textContent = result.error || `Created ${result.path}`;
|
|
20866
|
-
pageStatus.classList.toggle("error", Boolean(result.error));
|
|
20867
|
-
if (!result.error) pagePanel.hidden = true;
|
|
20868
|
-
});
|
|
20869
21425
|
newPageBtn.addEventListener("click", (event) => {
|
|
20870
21426
|
event.preventDefault();
|
|
20871
21427
|
event.stopPropagation();
|
|
20872
|
-
|
|
20873
|
-
pageStatus.textContent = "";
|
|
20874
|
-
pageStatus.classList.remove("error");
|
|
20875
|
-
requestFolders();
|
|
20876
|
-
});
|
|
20877
|
-
pagePanel.querySelector(".lasso-new-page-close").addEventListener("click", () => {
|
|
20878
|
-
pagePanel.hidden = true;
|
|
20879
|
-
});
|
|
20880
|
-
pagePanel.querySelector(".lasso-new-page-create").addEventListener("click", () => {
|
|
20881
|
-
const fileName = pagePanel.querySelector(".lasso-new-page-name").value.trim();
|
|
20882
|
-
const content = pagePanel.querySelector(".lasso-new-page-content").value;
|
|
20883
|
-
if (!fileName) {
|
|
20884
|
-
pageStatus.textContent = "Enter a file name.";
|
|
20885
|
-
pageStatus.classList.add("error");
|
|
20886
|
-
return;
|
|
20887
|
-
}
|
|
20888
|
-
if (state.bridgeSocket?.readyState !== WebSocket.OPEN) {
|
|
20889
|
-
pageStatus.textContent = "Bridge is not connected.";
|
|
20890
|
-
pageStatus.classList.add("error");
|
|
20891
|
-
return;
|
|
20892
|
-
}
|
|
20893
|
-
pageStatus.textContent = "Creating\u2026";
|
|
20894
|
-
state.bridgeSocket.send(JSON.stringify({ type: "create_page", folder: selectedFolder, fileName, content }));
|
|
21428
|
+
togglePagePanel();
|
|
20895
21429
|
});
|
|
20896
21430
|
selectBtn.addEventListener("click", (e) => {
|
|
20897
21431
|
e.preventDefault();
|
|
@@ -21034,13 +21568,21 @@
|
|
|
21034
21568
|
return;
|
|
21035
21569
|
}
|
|
21036
21570
|
if (message.type === "page_folders") {
|
|
21037
|
-
window.dispatchEvent(
|
|
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
|
+
);
|
|
21038
21576
|
return;
|
|
21039
21577
|
}
|
|
21040
21578
|
if (message.type === "page_created") {
|
|
21041
21579
|
window.dispatchEvent(new CustomEvent("lasso-page-created", { detail: { path: message.path || "", error: message.error } }));
|
|
21042
21580
|
return;
|
|
21043
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
|
+
}
|
|
21044
21586
|
if (message.type === "agent_status" && message.status && message.message) {
|
|
21045
21587
|
const taskId2 = message.taskId;
|
|
21046
21588
|
const task = taskId2 ? getAgentTask(taskId2) : void 0;
|
|
@@ -21143,6 +21685,7 @@
|
|
|
21143
21685
|
buildNotepadPanel();
|
|
21144
21686
|
buildClipboardPanel();
|
|
21145
21687
|
buildTaskPanel();
|
|
21688
|
+
buildPagePanel();
|
|
21146
21689
|
buildPrompt();
|
|
21147
21690
|
buildDrag();
|
|
21148
21691
|
initErrorListeners();
|
|
@@ -21217,6 +21760,10 @@
|
|
|
21217
21760
|
closePinThread();
|
|
21218
21761
|
return;
|
|
21219
21762
|
}
|
|
21763
|
+
if (isPagePanelOpen()) {
|
|
21764
|
+
closePagePanel();
|
|
21765
|
+
return;
|
|
21766
|
+
}
|
|
21220
21767
|
if (isPromptOpen()) {
|
|
21221
21768
|
cancelPrompt(true);
|
|
21222
21769
|
return;
|