@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/ARCHITECTURE.md +27 -3
- package/CHANGELOG.md +30 -1
- package/README.md +43 -2
- package/dist/cli/agent.d.ts +11 -2
- package/dist/cli/agent.js +135 -11
- package/dist/cli/bridge.d.ts +40 -1
- package/dist/cli/bridge.js +102 -1
- package/dist/overlay.js +882 -98
- 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;
|
|
@@ -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
|
|
12300
|
-
if (!
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
17873
|
+
statusEl2.textContent = "Transcribed";
|
|
17775
17874
|
window.setTimeout(() => {
|
|
17776
|
-
|
|
17875
|
+
statusEl2.textContent = "Autosaved";
|
|
17777
17876
|
}, 2e3);
|
|
17778
17877
|
} else {
|
|
17779
|
-
|
|
17878
|
+
statusEl2.textContent = "No speech detected";
|
|
17780
17879
|
window.setTimeout(() => {
|
|
17781
|
-
|
|
17880
|
+
statusEl2.textContent = "Autosaved";
|
|
17782
17881
|
}, 1500);
|
|
17783
17882
|
}
|
|
17784
17883
|
} catch (err) {
|
|
17785
|
-
|
|
17884
|
+
statusEl2.textContent = err?.message || "Transcription failed";
|
|
17786
17885
|
window.setTimeout(() => {
|
|
17787
|
-
|
|
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
|
-
|
|
17897
|
+
statusEl2.textContent = "Listening\u2026";
|
|
17799
17898
|
} catch (err) {
|
|
17800
|
-
|
|
17899
|
+
statusEl2.textContent = err?.message || "Microphone access denied";
|
|
17801
17900
|
window.setTimeout(() => {
|
|
17802
|
-
|
|
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
|
-
|
|
17925
|
+
statusEl2.textContent = "Saving\u2026";
|
|
17827
17926
|
if (saveTimer) window.clearTimeout(saveTimer);
|
|
17828
17927
|
saveTimer = window.setTimeout(() => {
|
|
17829
17928
|
saveNote(text);
|
|
17830
|
-
|
|
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
|
-
|
|
17949
|
+
statusEl2.textContent = "Copied!";
|
|
17851
17950
|
setTimeout(() => {
|
|
17852
|
-
|
|
17951
|
+
statusEl2.textContent = "Autosaved";
|
|
17853
17952
|
}, 1500);
|
|
17854
17953
|
} catch {
|
|
17855
|
-
|
|
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
|
|
18690
|
-
if (
|
|
18691
|
-
state.modelFilter =
|
|
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
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
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);
|
|
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,
|
|
19259
|
+
function setAgentStatus(status, message, detail, taskId2 = state.promptTaskId, appendMessage = true) {
|
|
19039
19260
|
if (!agentStatusElement || !agentStatusMessage || !sendButton) return;
|
|
19040
|
-
const logMessage =
|
|
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
|
-
|
|
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
|
-
|
|
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;
|